changeset 11194:e429b4b36c3c

6873566 Core File Gathering/Firmware Diag Buffer support 6892600 Add support for IOC Fault Watchdog in Solaris SAS2 storage driver (mpt_sas) 6892609 Add support for REG_ACCESS IOCTL in Solaris SAS2 storage driver (mpt_sas) 6892984 Add support for "System Shutdown Initiated" RAID action 6892985 Add support for extended FW Diag Buffer in Solaris SAS2 storage driver (mpt_sas) 6892995 Add time stamp to IOC Init message for Solaris SAS2 storage driver (mpt_sas) 6870234 Erie: Upgrading Firmware of Erie HBA with Solaris sas2flash turns HBA inactive 6901371 IOCTL path locks if issued after forcing fault
author Ada <Ada.Feng@Sun.COM>
date Wed, 25 Nov 2009 13:05:40 +0800
parents b54c6739cd88
children ee2c1bd94ea5
files usr/src/cmd/mdb/common/modules/mpt_sas/mpt_sas.c usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_impl.c usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_init.c usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_raid.c usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/mpi2.h usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/mpi2_raid.h usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_ioctl.h usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_var.h
diffstat 13 files changed, 2868 insertions(+), 150 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/mdb/common/modules/mpt_sas/mpt_sas.c	Wed Nov 25 12:30:41 2009 +0800
+++ b/usr/src/cmd/mdb/common/modules/mpt_sas/mpt_sas.c	Wed Nov 25 13:05:40 2009 +0800
@@ -36,6 +36,8 @@
 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_sas.h>
+#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_raid.h>
+#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
 #pragma pack()
 
 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
--- a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c	Wed Nov 25 12:30:41 2009 +0800
+++ b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c	Wed Nov 25 13:05:40 2009 +0800
@@ -80,6 +80,8 @@
 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_sas.h>
+#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
+#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_raid.h>
 #pragma pack()
 
 /*
@@ -224,6 +226,31 @@
     uint32_t dataout_size, short timeout, int mode);
 static int mptsas_free_devhdl(mptsas_t *mpt, uint16_t devhdl);
 
+static uint8_t mptsas_get_fw_diag_buffer_number(mptsas_t *mpt,
+    uint32_t unique_id);
+static void mptsas_start_diag(mptsas_t *mpt, mptsas_cmd_t *cmd);
+static int mptsas_post_fw_diag_buffer(mptsas_t *mpt,
+    mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code);
+static int mptsas_release_fw_diag_buffer(mptsas_t *mpt,
+    mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
+    uint32_t diag_type);
+static int mptsas_diag_register(mptsas_t *mpt,
+    mptsas_fw_diag_register_t *diag_register, uint32_t *return_code);
+static int mptsas_diag_unregister(mptsas_t *mpt,
+    mptsas_fw_diag_unregister_t *diag_unregister, uint32_t *return_code);
+static int mptsas_diag_query(mptsas_t *mpt, mptsas_fw_diag_query_t *diag_query,
+    uint32_t *return_code);
+static int mptsas_diag_read_buffer(mptsas_t *mpt,
+    mptsas_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
+    uint32_t *return_code, int ioctl_mode);
+static int mptsas_diag_release(mptsas_t *mpt,
+    mptsas_fw_diag_release_t *diag_release, uint32_t *return_code);
+static int mptsas_do_diag_action(mptsas_t *mpt, uint32_t action,
+    uint8_t *diag_action, uint32_t length, uint32_t *return_code,
+    int ioctl_mode);
+static int mptsas_diag_action(mptsas_t *mpt, mptsas_diag_action_t *data,
+    int mode);
+
 static int mptsas_pkt_alloc_extern(mptsas_t *mpt, mptsas_cmd_t *cmd,
     int cmdlen, int tgtlen, int statuslen, int kf);
 static void mptsas_pkt_destroy_extern(mptsas_t *mpt, mptsas_cmd_t *cmd);
@@ -344,6 +371,8 @@
 static int mptsas_event_report(mptsas_t *mpt, mptsas_event_report_t *data,
     int mode, int *rval);
 static void mptsas_record_event(void *args);
+static int mptsas_reg_access(mptsas_t *mpt, mptsas_reg_access_t *data,
+    int mode);
 
 static void mptsas_hash_init(mptsas_hash_table_t *hashtab);
 static void mptsas_hash_uninit(mptsas_hash_table_t *hashtab, size_t datalen);
@@ -489,7 +518,7 @@
 };
 
 
-#define	MPTSAS_MOD_STRING "MPTSAS HBA Driver 00.00.00.20"
+#define	MPTSAS_MOD_STRING "MPTSAS HBA Driver 00.00.00.21"
 
 static struct modldrv modldrv = {
 	&mod_driverops,	/* Type of module. This one is a driver */
@@ -1089,6 +1118,7 @@
 	cv_init(&mpt->m_passthru_cv, NULL, CV_DRIVER, NULL);
 	cv_init(&mpt->m_fw_cv, NULL, CV_DRIVER, NULL);
 	cv_init(&mpt->m_config_cv, NULL, CV_DRIVER, NULL);
+	cv_init(&mpt->m_fw_diag_cv, NULL, CV_DRIVER, NULL);
 	mutex_init_done++;
 
 	/*
@@ -1460,6 +1490,7 @@
 			cv_destroy(&mpt->m_passthru_cv);
 			cv_destroy(&mpt->m_fw_cv);
 			cv_destroy(&mpt->m_config_cv);
+			cv_destroy(&mpt->m_fw_diag_cv);
 		}
 		mptsas_free_handshake_msg(mpt);
 		mptsas_hba_fini(mpt);
@@ -1504,6 +1535,11 @@
 
 	mutex_enter(&mpt->m_mutex);
 
+	/*
+	 * Send RAID action system shutdown to sync IR
+	 */
+	mptsas_raid_action_system_shutdown(mpt);
+
 	if (mpt->m_suspended++) {
 		mutex_exit(&mpt->m_mutex);
 		return (DDI_SUCCESS);
@@ -1719,6 +1755,11 @@
 	}
 
 	mutex_enter(&mpt->m_mutex);
+
+	/*
+	 * Send RAID action system shutdown to sync IR
+	 */
+	mptsas_raid_action_system_shutdown(mpt);
 	MPTSAS_DISABLE_INTR(mpt);
 	mutex_exit(&mpt->m_mutex);
 	mptsas_rem_intrs(mpt);
@@ -1877,6 +1918,7 @@
 	cv_destroy(&mpt->m_passthru_cv);
 	cv_destroy(&mpt->m_fw_cv);
 	cv_destroy(&mpt->m_config_cv);
+	cv_destroy(&mpt->m_fw_diag_cv);
 
 	pci_config_teardown(&mpt->m_config_handle);
 	if (mpt->m_tran) {
@@ -2167,13 +2209,13 @@
 }
 
 int
-mptsas_passthru_dma_alloc(mptsas_t *mpt, mptsas_dma_alloc_state_t *dma_statep)
+mptsas_dma_alloc(mptsas_t *mpt, mptsas_dma_alloc_state_t *dma_statep)
 {
 	ddi_dma_attr_t	attrs;
 	uint_t		ncookie;
 	size_t		alloc_len;
 
-	attrs = mpt->m_msg_dma_attr;
+	attrs = mpt->m_io_dma_attr;
 	attrs.dma_attr_sgllen = 1;
 
 	ASSERT(dma_statep != NULL);
@@ -2210,7 +2252,7 @@
 }
 
 void
-mptsas_passthru_dma_free(mptsas_dma_alloc_state_t *dma_statep)
+mptsas_dma_free(mptsas_dma_alloc_state_t *dma_statep)
 {
 	ASSERT(dma_statep != NULL);
 	if (dma_statep->handle != NULL) {
@@ -4515,8 +4557,8 @@
 	mpt->m_polled_intr = 1;
 
 	/*
-	 * Get the current interrupt mask.  When re-enabling ints, set mask to
-	 * saved value.
+	 * Get the current interrupt mask and disable interrupts.  When
+	 * re-enabling ints, set mask to saved value.
 	 */
 	int_mask = ddi_get32(mpt->m_datap, &mpt->m_reg->HostInterruptMask);
 	MPTSAS_DISABLE_INTR(mpt);
@@ -4538,6 +4580,7 @@
 			drv_usecwait(1000);
 			continue;
 		}
+
 		/*
 		 * The reply is valid, process it according to its
 		 * type.
@@ -4548,10 +4591,13 @@
 			mpt->m_post_index = 0;
 		}
 
+		/*
+		 * Update the global reply index
+		 */
 		ddi_put32(mpt->m_datap,
 		    &mpt->m_reg->ReplyPostHostIndex, mpt->m_post_index);
-
 		mpt->m_polled_intr = 0;
+
 		/*
 		 * Re-enable interrupts and quit.
 		 */
@@ -4645,11 +4691,12 @@
 {
 	pMpi2AddressReplyDescriptor_t	address_reply;
 	pMPI2DefaultReply_t		reply;
+	mptsas_fw_diagnostic_buffer_t	*pBuffer;
 	uint32_t			reply_addr;
-	uint16_t			SMID;
+	uint16_t			SMID, iocstatus, action;
 	mptsas_slots_t			*slots = mpt->m_active;
 	mptsas_cmd_t			*cmd = NULL;
-	uint8_t				function;
+	uint8_t				function, buffer_type;
 	m_replyh_arg_t			*args;
 	int				reply_frame_no;
 
@@ -4685,7 +4732,24 @@
 	 * don't get slot information and command for events since these values
 	 * don't exist
 	 */
-	if (function != MPI2_FUNCTION_EVENT_NOTIFICATION) {
+	if ((function != MPI2_FUNCTION_EVENT_NOTIFICATION) &&
+	    (function != MPI2_FUNCTION_DIAG_BUFFER_POST)) {
+		/*
+		 * If this is a raid action reply for system shutdown just exit
+		 * because the reply doesn't matter.  Signal that we got the
+		 * reply even though it's not really necessary since we're
+		 * shutting down.
+		 */
+		if (function == MPI2_FUNCTION_RAID_ACTION) {
+			action = ddi_get16(mpt->m_acc_reply_frame_hdl,
+			    &reply->FunctionDependent1);
+			if (action ==
+			    MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED) {
+				cv_broadcast(&mpt->m_fw_diag_cv);
+				return;
+			}
+		}
+
 		/*
 		 * This could be a TM reply, which use the last allocated SMID,
 		 * so allow for that.
@@ -4709,11 +4773,13 @@
 			return;
 		}
 		if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
-		    (cmd->cmd_flags & CFLAG_CONFIG)) {
+		    (cmd->cmd_flags & CFLAG_CONFIG) ||
+		    (cmd->cmd_flags & CFLAG_FW_DIAG)) {
 			cmd->cmd_rfm = reply_addr;
 			cmd->cmd_flags |= CFLAG_FINISHED;
 			cv_broadcast(&mpt->m_passthru_cv);
 			cv_broadcast(&mpt->m_config_cv);
+			cv_broadcast(&mpt->m_fw_diag_cv);
 			return;
 		} else if (!(cmd->cmd_flags & CFLAG_FW_CMD)) {
 			mptsas_remove_cmd(mpt, cmd);
@@ -4781,6 +4847,43 @@
 			    &mpt->m_reg->ReplyFreeHostIndex, mpt->m_free_index);
 		}
 		return;
+	case MPI2_FUNCTION_DIAG_BUFFER_POST:
+		/*
+		 * If SMID is 0, 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.
+		 */
+		if (SMID == 0) {
+			iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
+			    &reply->IOCStatus);
+			buffer_type = ddi_get8(mpt->m_acc_reply_frame_hdl,
+			    &(((pMpi2DiagBufferPostReply_t)reply)->BufferType));
+			if (iocstatus == MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED) {
+				pBuffer =
+				    &mpt->m_fw_diag_buffer_list[buffer_type];
+				pBuffer->valid_data = TRUE;
+				pBuffer->owned_by_firmware = FALSE;
+				pBuffer->immediate = FALSE;
+			}
+		} else {
+			/*
+			 * Normal handling of diag post reply with SMID.
+			 */
+			cmd = slots->m_slot[SMID];
+
+			/*
+			 * print warning and return if the slot is empty
+			 */
+			if (cmd == NULL) {
+				mptsas_log(mpt, CE_WARN, "?NULL command for "
+				    "address reply in slot %d", SMID);
+				return;
+			}
+			cmd->cmd_rfm = reply_addr;
+			cmd->cmd_flags |= CFLAG_FINISHED;
+			cv_broadcast(&mpt->m_fw_diag_cv);
+		}
+		return;
 	default:
 		mptsas_log(mpt, CE_WARN, "Unknown function 0x%x ", function);
 		break;
@@ -5163,10 +5266,9 @@
 	mutex_enter(&mpt->m_mutex);
 
 	/*
-	 * If interrupts are shared by two channels then
-	 * check whether this interrupt is genuinely for this
-	 * channel by making sure first the chip is in high
-	 * power state.
+	 * If interrupts are shared by two channels then check whether this
+	 * interrupt is genuinely for this channel by making sure first the
+	 * chip is in high power state.
 	 */
 	if ((mpt->m_options & MPTSAS_OPT_PM) &&
 	    (mpt->m_power_level != PM_LEVEL_D0)) {
@@ -5211,13 +5313,16 @@
 
 			/*
 			 * The reply is valid, process it according to its
-			 * type.  Also, set a flag for updated the reply index
+			 * type.  Also, set a flag for updating the reply index
 			 * after they've all been processed.
 			 */
 			did_reply = TRUE;
 
 			mptsas_process_intr(mpt, reply_desc_union);
 
+			/*
+			 * Increment post index and roll over if needed.
+			 */
 			if (++mpt->m_post_index == mpt->m_post_queue_depth) {
 				mpt->m_post_index = 0;
 			}
@@ -5238,16 +5343,13 @@
 	NDBG1(("mptsas_intr complete"));
 
 	/*
-	 * If no helper threads are created, process the doneq in ISR.
-	 * If helpers are created, use the doneq length as a metric to
-	 * measure the load on the interrupt CPU. If it is long enough,
-	 * which indicates the load is heavy, then we deliver the IO
-	 * completions to the helpers.
-	 * this measurement has some limitations although, it is simple
-	 * and straightforward and works well for most of the cases at
-	 * present.
-	 */
-
+	 * If no helper threads are created, process the doneq in ISR. If
+	 * helpers are created, use the doneq length as a metric to measure the
+	 * load on the interrupt CPU. If it is long enough, which indicates the
+	 * load is heavy, then we deliver the IO completions to the helpers.
+	 * This measurement has some limitations, although it is simple and
+	 * straightforward and works well for most of the cases at present.
+	 */
 	if (!mpt->m_doneq_thread_n ||
 	    (mpt->m_doneq_len <= mpt->m_doneq_length_threshold)) {
 		mptsas_doneq_empty(mpt);
@@ -7400,6 +7502,19 @@
 			cmd = next_cmd;
 			continue;
 		}
+		if (cmd->cmd_flags & CFLAG_FW_DIAG) {
+			if (mptsas_save_cmd(mpt, cmd) == TRUE) {
+				/*
+				 * Send the FW Diag request and delete if from
+				 * the waitq.
+				 */
+				cmd->cmd_flags |= CFLAG_PREPARED;
+				mptsas_waitq_delete(mpt, cmd);
+				mptsas_start_diag(mpt, cmd);
+			}
+			cmd = next_cmd;
+			continue;
+		}
 
 		ptgt = cmd->cmd_tgt_addr;
 		if (ptgt && (ptgt->m_t_throttle == DRAIN_THROTTLE) &&
@@ -8294,8 +8409,27 @@
 		if ((cmd = slots->m_slot[slot]) == NULL)
 			continue;
 
-		if (cmd->cmd_flags & CFLAG_CMDIOC)
+		if (cmd->cmd_flags & CFLAG_CMDIOC) {
+			/*
+			 * Need to make sure to tell everyone that might be
+			 * waiting on this command that it's going to fail.  If
+			 * we get here, this command will never timeout because
+			 * the active command table is going to be re-allocated,
+			 * so there will be nothing to check against a time out.
+			 * Instead, mark the command as failed due to reset.
+			 */
+			mptsas_set_pkt_reason(mpt, cmd, CMD_RESET,
+			    STAT_BUS_RESET);
+			if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
+			    (cmd->cmd_flags & CFLAG_CONFIG) ||
+			    (cmd->cmd_flags & CFLAG_FW_DIAG)) {
+				cmd->cmd_flags |= CFLAG_FINISHED;
+				cv_broadcast(&mpt->m_passthru_cv);
+				cv_broadcast(&mpt->m_config_cv);
+				cv_broadcast(&mpt->m_fw_diag_cv);
+			}
 			continue;
+		}
 
 		mptsas_log(mpt, CE_NOTE, "mptsas_flush_hba discovered non-NULL "
 		    "cmd in slot %d", slot);
@@ -8312,10 +8446,12 @@
 	while ((cmd = mptsas_waitq_rm(mpt)) != NULL) {
 		mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
 		if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
-		    (cmd->cmd_flags & CFLAG_CONFIG)) {
+		    (cmd->cmd_flags & CFLAG_CONFIG) ||
+		    (cmd->cmd_flags & CFLAG_FW_DIAG)) {
 			cmd->cmd_flags |= CFLAG_FINISHED;
 			cv_broadcast(&mpt->m_passthru_cv);
 			cv_broadcast(&mpt->m_config_cv);
+			cv_broadcast(&mpt->m_fw_diag_cv);
 		} else {
 			mptsas_doneq_add(mpt, cmd);
 		}
@@ -8854,6 +8990,7 @@
 #endif
 
 	mptsas_t	*mpt;
+	uint32_t	doorbell;
 
 	NDBG30(("mptsas_watch"));
 
@@ -8874,6 +9011,20 @@
 		}
 
 		/*
+		 * Check if controller is in a FAULT state. If so, reset it.
+		 */
+		doorbell = ddi_get32(mpt->m_datap, &mpt->m_reg->Doorbell);
+		if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
+			doorbell &= MPI2_DOORBELL_DATA_MASK;
+			mptsas_log(mpt, CE_WARN, "MPT Firmware Fault, "
+			    "code: %04x", doorbell);
+			if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
+				mptsas_log(mpt, CE_WARN, "Reset failed"
+				    "after fault was detected");
+			}
+		}
+
+		/*
 		 * For now, always call mptsas_watchsubr.
 		 */
 		mptsas_watchsubr(mpt);
@@ -8928,7 +9079,8 @@
 				}
 			}
 			if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
-			    (cmd->cmd_flags & CFLAG_CONFIG)) {
+			    (cmd->cmd_flags & CFLAG_CONFIG) ||
+			    (cmd->cmd_flags & CFLAG_FW_DIAG)) {
 				cmd->cmd_active_timeout -=
 				    mptsas_scsi_watchdog_tick;
 				if (cmd->cmd_active_timeout <= 0) {
@@ -8939,6 +9091,7 @@
 					    CFLAG_TIMEOUT);
 					cv_broadcast(&mpt->m_passthru_cv);
 					cv_broadcast(&mpt->m_config_cv);
+					cv_broadcast(&mpt->m_fw_diag_cv);
 				}
 			}
 		}
@@ -9379,8 +9532,7 @@
 
 	if (data_size != 0) {
 		data_dma_state.size = data_size;
-		if (mptsas_passthru_dma_alloc(mpt, &data_dma_state) !=
-		    DDI_SUCCESS) {
+		if (mptsas_dma_alloc(mpt, &data_dma_state) != DDI_SUCCESS) {
 			status = ENOMEM;
 			mptsas_log(mpt, CE_WARN, "failed to alloc DMA "
 			    "resource");
@@ -9405,8 +9557,7 @@
 
 	if (dataout_size != 0) {
 		dataout_dma_state.size = dataout_size;
-		if (mptsas_passthru_dma_alloc(mpt, &dataout_dma_state) !=
-		    DDI_SUCCESS) {
+		if (mptsas_dma_alloc(mpt, &dataout_dma_state) != DDI_SUCCESS) {
 			status = ENOMEM;
 			mptsas_log(mpt, CE_WARN, "failed to alloc DMA "
 			    "resource");
@@ -9607,7 +9758,7 @@
 			    DDI_SERVICE_UNAFFECTED);
 			status = EFAULT;
 		}
-		mptsas_passthru_dma_free(&data_dma_state);
+		mptsas_dma_free(&data_dma_state);
 	}
 	if (pt_flags & MPTSAS_DATAOUT_ALLOCATED) {
 		if (mptsas_check_dma_handle(dataout_dma_state.handle) !=
@@ -9616,7 +9767,7 @@
 			    DDI_SERVICE_UNAFFECTED);
 			status = EFAULT;
 		}
-		mptsas_passthru_dma_free(&dataout_dma_state);
+		mptsas_dma_free(&dataout_dma_state);
 	}
 	if (pt_flags & MPTSAS_CMD_TIMEOUT) {
 		if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
@@ -9667,6 +9818,928 @@
 	}
 }
 
+static uint8_t
+mptsas_get_fw_diag_buffer_number(mptsas_t *mpt, uint32_t unique_id)
+{
+	uint8_t	index;
+
+	for (index = 0; index < MPI2_DIAG_BUF_TYPE_COUNT; index++) {
+		if (mpt->m_fw_diag_buffer_list[index].unique_id == unique_id) {
+			return (index);
+		}
+	}
+
+	return (MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND);
+}
+
+static void
+mptsas_start_diag(mptsas_t *mpt, mptsas_cmd_t *cmd)
+{
+	pMpi2DiagBufferPostRequest_t	pDiag_post_msg;
+	pMpi2DiagReleaseRequest_t	pDiag_release_msg;
+	struct scsi_pkt			*pkt = cmd->cmd_pkt;
+	mptsas_diag_request_t		*diag = pkt->pkt_ha_private;
+	uint32_t			request_desc_low, i;
+
+	ASSERT(mutex_owned(&mpt->m_mutex));
+
+	/*
+	 * Form the diag message depending on the post or release function.
+	 */
+	if (diag->function == MPI2_FUNCTION_DIAG_BUFFER_POST) {
+		pDiag_post_msg = (pMpi2DiagBufferPostRequest_t)
+		    (mpt->m_req_frame + (mpt->m_req_frame_size *
+		    cmd->cmd_slot));
+		bzero(pDiag_post_msg, mpt->m_req_frame_size);
+		ddi_put8(mpt->m_acc_req_frame_hdl, &pDiag_post_msg->Function,
+		    diag->function);
+		ddi_put8(mpt->m_acc_req_frame_hdl, &pDiag_post_msg->BufferType,
+		    diag->pBuffer->buffer_type);
+		ddi_put8(mpt->m_acc_req_frame_hdl,
+		    &pDiag_post_msg->ExtendedType,
+		    diag->pBuffer->extended_type);
+		ddi_put32(mpt->m_acc_req_frame_hdl,
+		    &pDiag_post_msg->BufferLength,
+		    diag->pBuffer->buffer_data.size);
+		for (i = 0; i < (sizeof (pDiag_post_msg->ProductSpecific) / 4);
+		    i++) {
+			ddi_put32(mpt->m_acc_req_frame_hdl,
+			    &pDiag_post_msg->ProductSpecific[i],
+			    diag->pBuffer->product_specific[i]);
+		}
+		ddi_put32(mpt->m_acc_req_frame_hdl,
+		    &pDiag_post_msg->BufferAddress.Low,
+		    (uint32_t)(diag->pBuffer->buffer_data.cookie.dmac_laddress
+		    & 0xffffffffull));
+		ddi_put32(mpt->m_acc_req_frame_hdl,
+		    &pDiag_post_msg->BufferAddress.High,
+		    (uint32_t)(diag->pBuffer->buffer_data.cookie.dmac_laddress
+		    >> 32));
+	} else {
+		pDiag_release_msg = (pMpi2DiagReleaseRequest_t)
+		    (mpt->m_req_frame + (mpt->m_req_frame_size *
+		    cmd->cmd_slot));
+		bzero(pDiag_release_msg, mpt->m_req_frame_size);
+		ddi_put8(mpt->m_acc_req_frame_hdl,
+		    &pDiag_release_msg->Function, diag->function);
+		ddi_put8(mpt->m_acc_req_frame_hdl,
+		    &pDiag_release_msg->BufferType,
+		    diag->pBuffer->buffer_type);
+	}
+
+	/*
+	 * Send the message
+	 */
+	(void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
+	    DDI_DMA_SYNC_FORDEV);
+	request_desc_low = (cmd->cmd_slot << 16) +
+	    MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+	cmd->cmd_rfm = NULL;
+	MPTSAS_START_CMD(mpt, request_desc_low, 0);
+	if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
+	    DDI_SUCCESS) ||
+	    (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
+	    DDI_SUCCESS)) {
+		ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
+	}
+}
+
+static int
+mptsas_post_fw_diag_buffer(mptsas_t *mpt,
+    mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code)
+{
+	mptsas_diag_request_t		diag;
+	int				status, slot_num, post_flags = 0;
+	mptsas_cmd_t			*cmd = NULL;
+	struct scsi_pkt			*pkt;
+	pMpi2DiagBufferPostReply_t	reply;
+	uint16_t			iocstatus;
+	uint32_t			iocloginfo, transfer_length;
+
+	/*
+	 * If buffer is not enabled, just leave.
+	 */
+	*return_code = MPTSAS_FW_DIAG_ERROR_POST_FAILED;
+	if (!pBuffer->enabled) {
+		status = DDI_FAILURE;
+		goto out;
+	}
+
+	/*
+	 * Clear some flags initially.
+	 */
+	pBuffer->force_release = FALSE;
+	pBuffer->valid_data = FALSE;
+	pBuffer->owned_by_firmware = FALSE;
+
+	/*
+	 * Get a cmd buffer from the cmd buffer pool
+	 */
+	if ((slot_num = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
+		status = DDI_FAILURE;
+		mptsas_log(mpt, CE_NOTE, "command pool is full: Post FW Diag");
+		goto out;
+	}
+	post_flags |= MPTSAS_REQUEST_POOL_CMD;
+
+	bzero((caddr_t)cmd, sizeof (*cmd));
+	bzero((caddr_t)pkt, scsi_pkt_size());
+
+	cmd->ioc_cmd_slot = (uint32_t)(slot_num);
+
+	diag.pBuffer = pBuffer;
+	diag.function = MPI2_FUNCTION_DIAG_BUFFER_POST;
+
+	/*
+	 * Form a blank cmd/pkt to store the acknowledgement message
+	 */
+	pkt->pkt_ha_private	= (opaque_t)&diag;
+	pkt->pkt_flags		= FLAG_HEAD;
+	pkt->pkt_time		= 60;
+	cmd->cmd_pkt		= pkt;
+	cmd->cmd_flags		= CFLAG_CMDIOC | CFLAG_FW_DIAG;
+
+	/*
+	 * Save the command in a slot
+	 */
+	if (mptsas_save_cmd(mpt, cmd) == TRUE) {
+		/*
+		 * Once passthru command get slot, set cmd_flags
+		 * CFLAG_PREPARED.
+		 */
+		cmd->cmd_flags |= CFLAG_PREPARED;
+		mptsas_start_diag(mpt, cmd);
+	} else {
+		mptsas_waitq_add(mpt, cmd);
+	}
+
+	while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
+		cv_wait(&mpt->m_fw_diag_cv, &mpt->m_mutex);
+	}
+
+	if (cmd->cmd_flags & CFLAG_TIMEOUT) {
+		status = DDI_FAILURE;
+		mptsas_log(mpt, CE_WARN, "Post FW Diag command timeout");
+		goto out;
+	}
+
+	/*
+	 * cmd_rfm points to the reply message if a reply was given.  Check the
+	 * IOCStatus to make sure everything went OK with the FW diag request
+	 * and set buffer flags.
+	 */
+	if (cmd->cmd_rfm) {
+		post_flags |= MPTSAS_ADDRESS_REPLY;
+		(void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
+		    DDI_DMA_SYNC_FORCPU);
+		reply = (pMpi2DiagBufferPostReply_t)(mpt->m_reply_frame +
+		    (cmd->cmd_rfm - mpt->m_reply_frame_dma_addr));
+
+		/*
+		 * Get the reply message data
+		 */
+		iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
+		    &reply->IOCStatus);
+		iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
+		    &reply->IOCLogInfo);
+		transfer_length = ddi_get32(mpt->m_acc_reply_frame_hdl,
+		    &reply->TransferLength);
+
+		/*
+		 * If post failed quit.
+		 */
+		if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
+			status = DDI_FAILURE;
+			NDBG13(("post FW Diag Buffer failed: IOCStatus=0x%x, "
+			    "IOCLogInfo=0x%x, TransferLength=0x%x", iocstatus,
+			    iocloginfo, transfer_length));
+			goto out;
+		}
+
+		/*
+		 * Post was successful.
+		 */
+		pBuffer->valid_data = TRUE;
+		pBuffer->owned_by_firmware = TRUE;
+		*return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
+		status = DDI_SUCCESS;
+	}
+
+out:
+	/*
+	 * Put the reply frame back on the free queue, increment the free
+	 * index, and write the new index to the free index register.  But only
+	 * if this reply is an ADDRESS reply.
+	 */
+	if (post_flags & MPTSAS_ADDRESS_REPLY) {
+		ddi_put32(mpt->m_acc_free_queue_hdl,
+		    &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
+		    cmd->cmd_rfm);
+		(void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
+		    DDI_DMA_SYNC_FORDEV);
+		if (++mpt->m_free_index == mpt->m_free_queue_depth) {
+			mpt->m_free_index = 0;
+		}
+		ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
+		    mpt->m_free_index);
+	}
+	if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
+		mptsas_remove_cmd(mpt, cmd);
+		post_flags &= (~MPTSAS_REQUEST_POOL_CMD);
+	}
+	if (post_flags & MPTSAS_REQUEST_POOL_CMD) {
+		mptsas_return_to_pool(mpt, cmd);
+	}
+
+	return (status);
+}
+
+static int
+mptsas_release_fw_diag_buffer(mptsas_t *mpt,
+    mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
+    uint32_t diag_type)
+{
+	mptsas_diag_request_t	diag;
+	int			status, slot_num, rel_flags = 0;
+	mptsas_cmd_t		*cmd = NULL;
+	struct scsi_pkt		*pkt;
+	pMpi2DiagReleaseReply_t	reply;
+	uint16_t		iocstatus;
+	uint32_t		iocloginfo;
+
+	/*
+	 * If buffer is not enabled, just leave.
+	 */
+	*return_code = MPTSAS_FW_DIAG_ERROR_RELEASE_FAILED;
+	if (!pBuffer->enabled) {
+		mptsas_log(mpt, CE_NOTE, "This buffer type is not supported "
+		    "by the IOC");
+		status = DDI_FAILURE;
+		goto out;
+	}
+
+	/*
+	 * Clear some flags initially.
+	 */
+	pBuffer->force_release = FALSE;
+	pBuffer->valid_data = FALSE;
+	pBuffer->owned_by_firmware = FALSE;
+
+	/*
+	 * Get a cmd buffer from the cmd buffer pool
+	 */
+	if ((slot_num = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
+		status = DDI_FAILURE;
+		mptsas_log(mpt, CE_NOTE, "command pool is full: Release FW "
+		    "Diag");
+		goto out;
+	}
+	rel_flags |= MPTSAS_REQUEST_POOL_CMD;
+
+	bzero((caddr_t)cmd, sizeof (*cmd));
+	bzero((caddr_t)pkt, scsi_pkt_size());
+
+	cmd->ioc_cmd_slot = (uint32_t)(slot_num);
+
+	diag.pBuffer = pBuffer;
+	diag.function = MPI2_FUNCTION_DIAG_RELEASE;
+
+	/*
+	 * Form a blank cmd/pkt to store the acknowledgement message
+	 */
+	pkt->pkt_ha_private	= (opaque_t)&diag;
+	pkt->pkt_flags		= FLAG_HEAD;
+	pkt->pkt_time		= 60;
+	cmd->cmd_pkt		= pkt;
+	cmd->cmd_flags		= CFLAG_CMDIOC | CFLAG_FW_DIAG;
+
+	/*
+	 * Save the command in a slot
+	 */
+	if (mptsas_save_cmd(mpt, cmd) == TRUE) {
+		/*
+		 * Once passthru command get slot, set cmd_flags
+		 * CFLAG_PREPARED.
+		 */
+		cmd->cmd_flags |= CFLAG_PREPARED;
+		mptsas_start_diag(mpt, cmd);
+	} else {
+		mptsas_waitq_add(mpt, cmd);
+	}
+
+	while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
+		cv_wait(&mpt->m_fw_diag_cv, &mpt->m_mutex);
+	}
+
+	if (cmd->cmd_flags & CFLAG_TIMEOUT) {
+		status = DDI_FAILURE;
+		mptsas_log(mpt, CE_WARN, "Release FW Diag command timeout");
+		goto out;
+	}
+
+	/*
+	 * cmd_rfm points to the reply message if a reply was given.  Check the
+	 * IOCStatus to make sure everything went OK with the FW diag request
+	 * and set buffer flags.
+	 */
+	if (cmd->cmd_rfm) {
+		rel_flags |= MPTSAS_ADDRESS_REPLY;
+		(void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
+		    DDI_DMA_SYNC_FORCPU);
+		reply = (pMpi2DiagReleaseReply_t)(mpt->m_reply_frame +
+		    (cmd->cmd_rfm - mpt->m_reply_frame_dma_addr));
+
+		/*
+		 * Get the reply message data
+		 */
+		iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
+		    &reply->IOCStatus);
+		iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
+		    &reply->IOCLogInfo);
+
+		/*
+		 * If release failed quit.
+		 */
+		if ((iocstatus != MPI2_IOCSTATUS_SUCCESS) ||
+		    pBuffer->owned_by_firmware) {
+			status = DDI_FAILURE;
+			NDBG13(("release FW Diag Buffer failed: "
+			    "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
+			    iocloginfo));
+			goto out;
+		}
+
+		/*
+		 * Release was successful.
+		 */
+		*return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
+		status = DDI_SUCCESS;
+
+		/*
+		 * If this was for an UNREGISTER diag type command, clear the
+		 * unique ID.
+		 */
+		if (diag_type == MPTSAS_FW_DIAG_TYPE_UNREGISTER) {
+			pBuffer->unique_id = MPTSAS_FW_DIAG_INVALID_UID;
+		}
+	}
+
+out:
+	/*
+	 * Put the reply frame back on the free queue, increment the free
+	 * index, and write the new index to the free index register.  But only
+	 * if this reply is an ADDRESS reply.
+	 */
+	if (rel_flags & MPTSAS_ADDRESS_REPLY) {
+		ddi_put32(mpt->m_acc_free_queue_hdl,
+		    &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
+		    cmd->cmd_rfm);
+		(void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
+		    DDI_DMA_SYNC_FORDEV);
+		if (++mpt->m_free_index == mpt->m_free_queue_depth) {
+			mpt->m_free_index = 0;
+		}
+		ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
+		    mpt->m_free_index);
+	}
+	if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
+		mptsas_remove_cmd(mpt, cmd);
+		rel_flags &= (~MPTSAS_REQUEST_POOL_CMD);
+	}
+	if (rel_flags & MPTSAS_REQUEST_POOL_CMD) {
+		mptsas_return_to_pool(mpt, cmd);
+	}
+
+	return (status);
+}
+
+static int
+mptsas_diag_register(mptsas_t *mpt, mptsas_fw_diag_register_t *diag_register,
+    uint32_t *return_code)
+{
+	mptsas_fw_diagnostic_buffer_t	*pBuffer;
+	uint8_t				extended_type, buffer_type, i;
+	uint32_t			buffer_size;
+	uint32_t			unique_id;
+	int				status;
+
+	ASSERT(mutex_owned(&mpt->m_mutex));
+
+	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 = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
+		return (DDI_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 = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
+	pBuffer = &mpt->m_fw_diag_buffer_list[buffer_type];
+	if (i != MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
+		*return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
+		return (DDI_FAILURE);
+	}
+
+	/*
+	 * The buffer's unique ID should not be registered yet, and the given
+	 * unique ID cannot be 0.
+	 */
+	if ((pBuffer->unique_id != MPTSAS_FW_DIAG_INVALID_UID) ||
+	    (unique_id == MPTSAS_FW_DIAG_INVALID_UID)) {
+		*return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
+		return (DDI_FAILURE);
+	}
+
+	/*
+	 * If this buffer is already posted as immediate, just change owner.
+	 */
+	if (pBuffer->immediate && pBuffer->owned_by_firmware &&
+	    (pBuffer->unique_id == MPTSAS_FW_DIAG_INVALID_UID)) {
+		pBuffer->immediate = FALSE;
+		pBuffer->unique_id = unique_id;
+		return (DDI_SUCCESS);
+	}
+
+	/*
+	 * Post a new buffer after checking if it's enabled.  The DMA buffer
+	 * that is allocated will be contiguous (sgl_len = 1).
+	 */
+	if (!pBuffer->enabled) {
+		*return_code = MPTSAS_FW_DIAG_ERROR_NO_BUFFER;
+		return (DDI_FAILURE);
+	}
+	bzero(&pBuffer->buffer_data, sizeof (mptsas_dma_alloc_state_t));
+	pBuffer->buffer_data.size = buffer_size;
+	if (mptsas_dma_alloc(mpt, &pBuffer->buffer_data) != DDI_SUCCESS) {
+		mptsas_log(mpt, CE_WARN, "failed to alloc DMA resource for "
+		    "diag buffer: size = %d bytes", buffer_size);
+		*return_code = MPTSAS_FW_DIAG_ERROR_NO_BUFFER;
+		return (DDI_FAILURE);
+	}
+
+	/*
+	 * 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 = mptsas_post_fw_diag_buffer(mpt, pBuffer, return_code);
+
+	if (mptsas_check_dma_handle(pBuffer->buffer_data.handle) !=
+	    DDI_SUCCESS) {
+		mptsas_log(mpt, CE_WARN, "Check of DMA handle failed in "
+		    "mptsas_diag_register.");
+		ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
+			status = DDI_FAILURE;
+	}
+
+	/*
+	 * In case there was a failure, free the DMA buffer.
+	 */
+	if (status == DDI_FAILURE) {
+		mptsas_dma_free(&pBuffer->buffer_data);
+	}
+
+	return (status);
+}
+
+static int
+mptsas_diag_unregister(mptsas_t *mpt,
+    mptsas_fw_diag_unregister_t *diag_unregister, uint32_t *return_code)
+{
+	mptsas_fw_diagnostic_buffer_t	*pBuffer;
+	uint8_t				i;
+	uint32_t			unique_id;
+	int				status;
+
+	ASSERT(mutex_owned(&mpt->m_mutex));
+
+	unique_id = diag_unregister->UniqueId;
+
+	/*
+	 * Get the current buffer and look up the unique ID.  The unique ID
+	 * should be there.
+	 */
+	i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
+	if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
+		*return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
+		return (DDI_FAILURE);
+	}
+
+	pBuffer = &mpt->m_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 = DDI_SUCCESS;
+	} else {
+		status = mptsas_release_fw_diag_buffer(mpt, pBuffer,
+		    return_code, MPTSAS_FW_DIAG_TYPE_UNREGISTER);
+	}
+
+	/*
+	 * At this point, return the current status no matter what happens with
+	 * the DMA buffer.
+	 */
+	pBuffer->unique_id = MPTSAS_FW_DIAG_INVALID_UID;
+	if (status == DDI_SUCCESS) {
+		if (mptsas_check_dma_handle(pBuffer->buffer_data.handle) !=
+		    DDI_SUCCESS) {
+			mptsas_log(mpt, CE_WARN, "Check of DMA handle failed "
+			    "in mptsas_diag_unregister.");
+			ddi_fm_service_impact(mpt->m_dip,
+			    DDI_SERVICE_UNAFFECTED);
+		}
+		mptsas_dma_free(&pBuffer->buffer_data);
+	}
+
+	return (status);
+}
+
+static int
+mptsas_diag_query(mptsas_t *mpt, mptsas_fw_diag_query_t *diag_query,
+    uint32_t *return_code)
+{
+	mptsas_fw_diagnostic_buffer_t	*pBuffer;
+	uint8_t				i;
+	uint32_t			unique_id;
+
+	ASSERT(mutex_owned(&mpt->m_mutex));
+
+	unique_id = diag_query->UniqueId;
+
+	/*
+	 * If ID is valid, query on ID.
+	 * If ID is invalid, query on buffer type.
+	 */
+	if (unique_id == MPTSAS_FW_DIAG_INVALID_UID) {
+		i = diag_query->BufferType;
+		if (i >= MPI2_DIAG_BUF_TYPE_COUNT) {
+			*return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
+			return (DDI_FAILURE);
+		}
+	} else {
+		i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
+		if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
+			*return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
+			return (DDI_FAILURE);
+		}
+	}
+
+	/*
+	 * Fill query structure with the diag buffer info.
+	 */
+	pBuffer = &mpt->m_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->buffer_data.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 &= ~MPTSAS_FW_DIAG_FLAG_APP_OWNED;
+	} else {
+		diag_query->ApplicationFlags |= MPTSAS_FW_DIAG_FLAG_APP_OWNED;
+	}
+	if (pBuffer->valid_data || pBuffer->owned_by_firmware) {
+		diag_query->ApplicationFlags |=
+		    MPTSAS_FW_DIAG_FLAG_BUFFER_VALID;
+	} else {
+		diag_query->ApplicationFlags &=
+		    ~MPTSAS_FW_DIAG_FLAG_BUFFER_VALID;
+	}
+	if (pBuffer->owned_by_firmware) {
+		diag_query->ApplicationFlags |=
+		    MPTSAS_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
+	} else {
+		diag_query->ApplicationFlags &=
+		    ~MPTSAS_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
+	}
+
+	return (DDI_SUCCESS);
+}
+
+static int
+mptsas_diag_read_buffer(mptsas_t *mpt,
+    mptsas_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
+    uint32_t *return_code, int ioctl_mode)
+{
+	mptsas_fw_diagnostic_buffer_t	*pBuffer;
+	uint8_t				i, *pData;
+	uint32_t			unique_id, byte;
+	int				status;
+
+	ASSERT(mutex_owned(&mpt->m_mutex));
+
+	unique_id = diag_read_buffer->UniqueId;
+
+	/*
+	 * Get the current buffer and look up the unique ID.  The unique ID
+	 * should be there.
+	 */
+	i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
+	if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
+		*return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
+		return (DDI_FAILURE);
+	}
+
+	pBuffer = &mpt->m_fw_diag_buffer_list[i];
+
+	/*
+	 * Make sure requested read is within limits
+	 */
+	if (diag_read_buffer->StartingOffset + diag_read_buffer->BytesToRead >
+	    pBuffer->buffer_data.size) {
+		*return_code = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
+		return (DDI_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 *)(pBuffer->buffer_data.memp +
+	    diag_read_buffer->StartingOffset);
+	(void) ddi_dma_sync(pBuffer->buffer_data.handle, 0, 0,
+	    DDI_DMA_SYNC_FORCPU);
+	for (byte = 0; byte < diag_read_buffer->BytesToRead; byte++) {
+		if (ddi_copyout(pData + byte, ioctl_buf + byte, 1, ioctl_mode)
+		    != 0) {
+			return (DDI_FAILURE);
+		}
+	}
+	diag_read_buffer->Status = 0;
+
+	/*
+	 * Set or clear the Force Release flag.
+	 */
+	if (pBuffer->force_release) {
+		diag_read_buffer->Flags |= MPTSAS_FW_DIAG_FLAG_FORCE_RELEASE;
+	} else {
+		diag_read_buffer->Flags &= ~MPTSAS_FW_DIAG_FLAG_FORCE_RELEASE;
+	}
+
+	/*
+	 * If buffer is to be reregistered, make sure it's not already owned by
+	 * firmware first.
+	 */
+	status = DDI_SUCCESS;
+	if (!pBuffer->owned_by_firmware) {
+		if (diag_read_buffer->Flags & MPTSAS_FW_DIAG_FLAG_REREGISTER) {
+			status = mptsas_post_fw_diag_buffer(mpt, pBuffer,
+			    return_code);
+		}
+	}
+
+	return (status);
+}
+
+static int
+mptsas_diag_release(mptsas_t *mpt, mptsas_fw_diag_release_t *diag_release,
+    uint32_t *return_code)
+{
+	mptsas_fw_diagnostic_buffer_t	*pBuffer;
+	uint8_t				i;
+	uint32_t			unique_id;
+	int				status;
+
+	ASSERT(mutex_owned(&mpt->m_mutex));
+
+	unique_id = diag_release->UniqueId;
+
+	/*
+	 * Get the current buffer and look up the unique ID.  The unique ID
+	 * should be there.
+	 */
+	i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
+	if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
+		*return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
+		return (DDI_FAILURE);
+	}
+
+	pBuffer = &mpt->m_fw_diag_buffer_list[i];
+
+	/*
+	 * If buffer is not owned by firmware, it's already been released.
+	 */
+	if (!pBuffer->owned_by_firmware) {
+		*return_code = MPTSAS_FW_DIAG_ERROR_ALREADY_RELEASED;
+		return (DDI_FAILURE);
+	}
+
+	/*
+	 * Release the buffer.
+	 */
+	status = mptsas_release_fw_diag_buffer(mpt, pBuffer, return_code,
+	    MPTSAS_FW_DIAG_TYPE_RELEASE);
+	return (status);
+}
+
+static int
+mptsas_do_diag_action(mptsas_t *mpt, uint32_t action, uint8_t *diag_action,
+    uint32_t length, uint32_t *return_code, int ioctl_mode)
+{
+	mptsas_fw_diag_register_t	diag_register;
+	mptsas_fw_diag_unregister_t	diag_unregister;
+	mptsas_fw_diag_query_t		diag_query;
+	mptsas_diag_read_buffer_t	diag_read_buffer;
+	mptsas_fw_diag_release_t	diag_release;
+	int				status = DDI_SUCCESS;
+	uint32_t			original_return_code, read_buf_len;
+
+	ASSERT(mutex_owned(&mpt->m_mutex));
+
+	original_return_code = *return_code;
+	*return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
+
+	switch (action) {
+		case MPTSAS_FW_DIAG_TYPE_REGISTER:
+			if (!length) {
+				*return_code =
+				    MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
+				status = DDI_FAILURE;
+				break;
+			}
+			if (ddi_copyin(diag_action, &diag_register,
+			    sizeof (diag_register), ioctl_mode) != 0) {
+				return (DDI_FAILURE);
+			}
+			status = mptsas_diag_register(mpt, &diag_register,
+			    return_code);
+			break;
+
+		case MPTSAS_FW_DIAG_TYPE_UNREGISTER:
+			if (length < sizeof (diag_unregister)) {
+				*return_code =
+				    MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
+				status = DDI_FAILURE;
+				break;
+			}
+			if (ddi_copyin(diag_action, &diag_unregister,
+			    sizeof (diag_unregister), ioctl_mode) != 0) {
+				return (DDI_FAILURE);
+			}
+			status = mptsas_diag_unregister(mpt, &diag_unregister,
+			    return_code);
+			break;
+
+		case MPTSAS_FW_DIAG_TYPE_QUERY:
+			if (length < sizeof (diag_query)) {
+				*return_code =
+				    MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
+				status = DDI_FAILURE;
+				break;
+			}
+			if (ddi_copyin(diag_action, &diag_query,
+			    sizeof (diag_query), ioctl_mode) != 0) {
+				return (DDI_FAILURE);
+			}
+			status = mptsas_diag_query(mpt, &diag_query,
+			    return_code);
+			if (status == DDI_SUCCESS) {
+				if (ddi_copyout(&diag_query, diag_action,
+				    sizeof (diag_query), ioctl_mode) != 0) {
+					return (DDI_FAILURE);
+				}
+			}
+			break;
+
+		case MPTSAS_FW_DIAG_TYPE_READ_BUFFER:
+			if (ddi_copyin(diag_action, &diag_read_buffer,
+			    sizeof (diag_read_buffer) - 4, ioctl_mode) != 0) {
+				return (DDI_FAILURE);
+			}
+			read_buf_len = sizeof (diag_read_buffer) -
+			    sizeof (diag_read_buffer.DataBuffer) +
+			    diag_read_buffer.BytesToRead;
+			if (length < read_buf_len) {
+				*return_code =
+				    MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
+				status = DDI_FAILURE;
+				break;
+			}
+			status = mptsas_diag_read_buffer(mpt,
+			    &diag_read_buffer, diag_action +
+			    sizeof (diag_read_buffer) - 4, return_code,
+			    ioctl_mode);
+			if (status == DDI_SUCCESS) {
+				if (ddi_copyout(&diag_read_buffer, diag_action,
+				    sizeof (diag_read_buffer) - 4, ioctl_mode)
+				    != 0) {
+					return (DDI_FAILURE);
+				}
+			}
+			break;
+
+		case MPTSAS_FW_DIAG_TYPE_RELEASE:
+			if (length < sizeof (diag_release)) {
+				*return_code =
+				    MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
+				status = DDI_FAILURE;
+				break;
+			}
+			if (ddi_copyin(diag_action, &diag_release,
+			    sizeof (diag_release), ioctl_mode) != 0) {
+				return (DDI_FAILURE);
+			}
+			status = mptsas_diag_release(mpt, &diag_release,
+			    return_code);
+			break;
+
+		default:
+			*return_code = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
+			status = DDI_FAILURE;
+			break;
+	}
+
+	if ((status == DDI_FAILURE) &&
+	    (original_return_code == MPTSAS_FW_DIAG_NEW) &&
+	    (*return_code != MPTSAS_FW_DIAG_ERROR_SUCCESS)) {
+		status = DDI_SUCCESS;
+	}
+
+	return (status);
+}
+
+static int
+mptsas_diag_action(mptsas_t *mpt, mptsas_diag_action_t *user_data, int mode)
+{
+	int			status;
+	mptsas_diag_action_t	driver_data;
+
+	ASSERT(mutex_owned(&mpt->m_mutex));
+
+	/*
+	 * Copy the user data to a driver data buffer.
+	 */
+	if (ddi_copyin(user_data, &driver_data, sizeof (mptsas_diag_action_t),
+	    mode) == 0) {
+		/*
+		 * Send diag action request if Action is valid
+		 */
+		if (driver_data.Action == MPTSAS_FW_DIAG_TYPE_REGISTER ||
+		    driver_data.Action == MPTSAS_FW_DIAG_TYPE_UNREGISTER ||
+		    driver_data.Action == MPTSAS_FW_DIAG_TYPE_QUERY ||
+		    driver_data.Action == MPTSAS_FW_DIAG_TYPE_READ_BUFFER ||
+		    driver_data.Action == MPTSAS_FW_DIAG_TYPE_RELEASE) {
+			status = mptsas_do_diag_action(mpt, driver_data.Action,
+			    (void *)(uintptr_t)driver_data.PtrDiagAction,
+			    driver_data.Length, &driver_data.ReturnCode,
+			    mode);
+			if (status == DDI_SUCCESS) {
+				if (ddi_copyout(&driver_data.ReturnCode,
+				    &user_data->ReturnCode,
+				    sizeof (user_data->ReturnCode), mode)
+				    != 0) {
+					status = EFAULT;
+				} else {
+					status = 0;
+				}
+			} else {
+				status = EIO;
+			}
+		} else {
+			status = EINVAL;
+		}
+	} else {
+		status = EFAULT;
+	}
+
+	return (status);
+}
+
 /*
  * This routine handles the "event query" ioctl.
  */
@@ -9879,6 +10952,57 @@
 }
 
 static int
+mptsas_reg_access(mptsas_t *mpt, mptsas_reg_access_t *data, int mode)
+{
+	int			status = 0;
+	mptsas_reg_access_t	driverdata;
+
+	mutex_enter(&mpt->m_mutex);
+	if (ddi_copyin(data, &driverdata, sizeof (driverdata), mode) == 0) {
+		switch (driverdata.Command) {
+			/*
+			 * IO access is not supported.
+			 */
+			case REG_IO_READ:
+			case REG_IO_WRITE:
+				mptsas_log(mpt, CE_WARN, "IO access is not "
+				    "supported.  Use memory access.");
+				status = EINVAL;
+				break;
+
+			case REG_MEM_READ:
+				driverdata.RegData = ddi_get32(mpt->m_datap,
+				    (uint32_t *)(void *)mpt->m_reg +
+				    driverdata.RegOffset);
+				if (ddi_copyout(&driverdata.RegData,
+				    &data->RegData,
+				    sizeof (driverdata.RegData), mode) != 0) {
+					mptsas_log(mpt, CE_WARN, "Register "
+					    "Read Failed");
+					status = EFAULT;
+				}
+				break;
+
+			case REG_MEM_WRITE:
+				ddi_put32(mpt->m_datap,
+				    (uint32_t *)(void *)mpt->m_reg +
+				    driverdata.RegOffset,
+				    driverdata.RegData);
+				break;
+
+			default:
+				status = EINVAL;
+				break;
+		}
+	} else {
+		status = EFAULT;
+	}
+
+	mutex_exit(&mpt->m_mutex);
+	return (status);
+}
+
+static int
 mptsas_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp,
     int *rval)
 {
@@ -10020,6 +11144,23 @@
 			}
 			mutex_exit(&mpt->m_mutex);
 			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.
+			 */
+			mutex_enter(&mpt->m_mutex);
+			if (mpt->m_diag_action_in_progress) {
+				mutex_exit(&mpt->m_mutex);
+				return (EBUSY);
+			}
+			mpt->m_diag_action_in_progress = 1;
+			status = mptsas_diag_action(mpt,
+			    (mptsas_diag_action_t *)data, mode);
+			mpt->m_diag_action_in_progress = 0;
+			mutex_exit(&mpt->m_mutex);
+			break;
 		case MPTIOCTL_EVENT_QUERY:
 			/*
 			 * The user has done an event query. Call our routine
@@ -10044,6 +11185,14 @@
 			status = mptsas_event_report(mpt,
 			    (mptsas_event_report_t *)data, mode, rval);
 			break;
+		case MPTIOCTL_REG_ACCESS:
+			/*
+			 * The user has requested register access.  Call our
+			 * routine which does this.
+			 */
+			status = mptsas_reg_access(mpt,
+			    (mptsas_reg_access_t *)data, mode);
+			break;
 		default:
 			status = scsi_hba_ioctl(dev, cmd, data, mode, credp,
 			    rval);
@@ -10157,23 +11306,6 @@
 	uint32_t		i;
 	mptsas_slots_t		*new_active;
 
-	if (first_time == FALSE) {
-		/*
-		 * De-allocate buffers before re-allocating them using the
-		 * latest IOC facts.
-		 */
-		mptsas_hba_fini(mpt);
-
-		/*
-		 * Setup configuration space
-		 */
-		if (mptsas_config_space_init(mpt) == FALSE) {
-			mptsas_log(mpt, CE_WARN, "mptsas_config_space_init "
-			    "failed!");
-			goto fail;
-		}
-	}
-
 	/*
 	 * Check to see if the firmware image is valid
 	 */
@@ -10190,14 +11322,31 @@
 		mptsas_log(mpt, CE_WARN, "hard reset failed!");
 		goto fail;
 	}
+
+	if (first_time == FALSE) {
+		/*
+		 * De-allocate buffers before re-allocating them using the
+		 * latest IOC facts.
+		 */
+		mptsas_hba_fini(mpt);
+
+		/*
+		 * Setup configuration space
+		 */
+		if (mptsas_config_space_init(mpt) == FALSE) {
+			mptsas_log(mpt, CE_WARN, "mptsas_config_space_init "
+			    "failed!");
+			goto fail;
+		}
+	}
+
 	/*
 	 * IOC facts can change after a diag reset so all buffers that are
 	 * based on these numbers must be de-allocated and re-allocated.  Get
 	 * new IOC facts each time chip is initialized.
 	 */
 	if (mptsas_ioc_get_facts(mpt) == DDI_FAILURE) {
-		mptsas_log(mpt, CE_WARN, "mptsas_ioc_get_facts "
-		    "failed");
+		mptsas_log(mpt, CE_WARN, "mptsas_ioc_get_facts failed");
 		goto fail;
 	}
 	/*
@@ -10230,35 +11379,23 @@
 	}
 
 	/*
-	 * Allocate request message frames
+	 * Allocate request message frames, reply free queue, reply descriptor
+	 * post queue, and reply message frames using latest IOC facts.
 	 */
 	if (mptsas_alloc_request_frames(mpt) == DDI_FAILURE) {
-		mptsas_log(mpt, CE_WARN, "mptsas_alloc_request_frames "
-		    "failed");
+		mptsas_log(mpt, CE_WARN, "mptsas_alloc_request_frames failed");
 		goto fail;
 	}
-	/*
-	 * Allocate reply free queue
-	 */
 	if (mptsas_alloc_free_queue(mpt) == DDI_FAILURE) {
-		mptsas_log(mpt, CE_WARN, "mptsas_alloc_free_queue "
-		    "failed!");
+		mptsas_log(mpt, CE_WARN, "mptsas_alloc_free_queue failed!");
 		goto fail;
 	}
-	/*
-	 * Allocate reply descriptor post queue
-	 */
 	if (mptsas_alloc_post_queue(mpt) == DDI_FAILURE) {
-		mptsas_log(mpt, CE_WARN, "mptsas_alloc_post_queue "
-		    "failed!");
+		mptsas_log(mpt, CE_WARN, "mptsas_alloc_post_queue failed!");
 		goto fail;
 	}
-	/*
-	 * Allocate reply message frames
-	 */
 	if (mptsas_alloc_reply_frames(mpt) == DDI_FAILURE) {
-		mptsas_log(mpt, CE_WARN, "mptsas_alloc_reply_frames "
-		    "failed!");
+		mptsas_log(mpt, CE_WARN, "mptsas_alloc_reply_frames failed!");
 		goto fail;
 	}
 
@@ -10274,8 +11411,8 @@
 	    mpt->m_max_replies, KM_SLEEP);
 
 	/*
-	 * Initialize reply post index and request index.  Reply free index is
-	 * initialized after the next loop.
+	 * Initialize reply post index.  Reply free index is initialized after
+	 * the next loop.
 	 */
 	mpt->m_post_index = 0;
 
@@ -10870,6 +12007,7 @@
 	kmem_free(inq83, inq83_len);
 	return (sata_guid);
 }
+
 static int
 mptsas_inquiry(mptsas_t *mpt, mptsas_target_t *ptgt, int lun, uchar_t page,
     unsigned char *buf, int len, int *reallen, uchar_t evpd)
@@ -11182,7 +12320,7 @@
 	} else {
 		rval = DDI_FAILURE;
 	}
-out:
+
 	kmem_free(sd_inq, SUN_INQSIZE);
 	return (rval);
 }
@@ -11473,7 +12611,6 @@
 		rval = DDI_FAILURE;
 	}
 
-out:
 	kmem_free(sd_inq, SUN_INQSIZE);
 	return (rval);
 }
--- a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_impl.c	Wed Nov 25 12:30:41 2009 +0800
+++ b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_impl.c	Wed Nov 25 13:05:40 2009 +0800
@@ -74,6 +74,7 @@
 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_sas.h>
+#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
 #pragma pack()
 
 /*
@@ -871,11 +872,11 @@
 	saved_HCB_size = ddi_get32(mpt->m_datap, &mpt->m_reg->HCBSize);
 
 	/*
-	 * Set Reset Adapter bit and wait 30 mSeconds.
+	 * Set Reset Adapter bit and wait 50 mSeconds.
 	 */
 	diag_reg |= MPI2_DIAG_RESET_ADAPTER;
 	ddi_put32(mpt->m_datap, &mpt->m_reg->HostDiagnostic, diag_reg);
-	drv_usecwait(30000);
+	drv_usecwait(50000);
 
 	/*
 	 * Poll, waiting for Reset Adapter bit to clear.  300 Seconds max
@@ -931,9 +932,9 @@
 	    MPI2_WRSEQ_FLUSH_KEY_VALUE);
 
 	/*
-	 * Wait 20 seconds max for FW to come to ready state.
+	 * Wait 60 seconds max for FW to come to ready state.
 	 */
-	for (polls = 0; polls < 20000; polls++) {
+	for (polls = 0; polls < 60000; polls++) {
 		ioc_state = ddi_get32(mpt->m_datap, &mpt->m_reg->Doorbell);
 		if (ioc_state == 0xFFFFFFFF) {
 			mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
@@ -946,7 +947,7 @@
 		}
 		drv_usecwait(1000);
 	}
-	if (polls == 20000) {
+	if (polls == 60000) {
 		mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
 		ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
 		return (DDI_FAILURE);
@@ -996,12 +997,12 @@
 		}
 
 		/*
-		 * Wait for chip to become ready
+		 * Wait no more than 60 seconds for chip to become ready.
 		 */
 		while ((ddi_get32(mpt->m_datap, &mpt->m_reg->Doorbell) &
 		    MPI2_IOC_STATE_READY) == 0x0) {
 			drv_usecwait(1000);
-			if (polls++ > 20000) {
+			if (polls++ > 60000) {
 				goto hard_reset;
 			}
 		}
--- a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_init.c	Wed Nov 25 12:30:41 2009 +0800
+++ b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_init.c	Wed Nov 25 13:05:40 2009 +0800
@@ -72,6 +72,7 @@
 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
+#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
 #pragma pack()
 /*
  * private header files.
@@ -174,6 +175,7 @@
 	uint16_t		queueSize, queueDiff;
 	int			simple_sge_main;
 	int			simple_sge_next;
+	uint32_t		capabilities;
 
 	bzero(memp, sizeof (*factsreply));
 	factsreply = (void *)memp;
@@ -263,7 +265,7 @@
 	mpt->m_post_queue_depth = queueSize;
 
 	/*
-	 * Set up other stuff.
+	 * Set up max chain depth.
 	 */
 	mpt->m_max_chain_depth = ddi_get8(accessp,
 	    &factsreply->MaxChainDepth);
@@ -273,7 +275,6 @@
 	/*
 	 * Calculate max frames per request based on DMA S/G length.
 	 */
-
 	simple_sge_main = MPTSAS_MAX_FRAME_SGES64(mpt) - 1;
 	simple_sge_next = mpt->m_req_frame_size /
 	    sizeof (MPI2_SGE_SIMPLE64) - 1;
@@ -285,6 +286,39 @@
 		mpt->m_max_request_frames++;
 	}
 
+	/*
+	 * Check if controller supports FW diag buffers and set flag to enable
+	 * each type.
+	 */
+	capabilities = ddi_get32(accessp, &factsreply->IOCCapabilities);
+	if (capabilities & MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) {
+		mpt->m_fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_TRACE].enabled =
+		    TRUE;
+	}
+	if (capabilities & MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) {
+		mpt->m_fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_SNAPSHOT].
+		    enabled = TRUE;
+	}
+	if (capabilities & MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) {
+		mpt->m_fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_EXTENDED].
+		    enabled = TRUE;
+	}
+
+	/*
+	 * Check if controller supports replaying events when issuing Message
+	 * Unit Reset and set flag to enable MUR.
+	 */
+	if (capabilities & MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY) {
+		mpt->m_event_replay = TRUE;
+	}
+
+	/*
+	 * Check if controller supports IR.
+	 */
+	if (capabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) {
+		mpt->m_ir_capable = TRUE;
+	}
+
 	return (DDI_SUCCESS);
 }
 
@@ -560,6 +594,8 @@
 
 	pMpi2IOCInitRequest_t	init;
 	int			numbytes;
+	timespec_t		time;
+	uint64_t		mSec;
 
 	bzero(memp, sizeof (*init));
 	init = (void *)memp;
@@ -594,6 +630,18 @@
 	ddi_put32(accessp, &init->ReplyFreeQueueAddress.Low,
 	    (uint32_t)mpt->m_free_queue_dma_addr);
 
+	/*
+	 * Fill in the timestamp with the number of milliseconds since midnight
+	 * of January 1, 1970 UT (Greenwich Mean Time).  Time is returned in
+	 * seconds and nanoseconds.  Translate both to milliseconds and add
+	 * them together to get total milliseconds.
+	 */
+	gethrestime(&time);
+	mSec = time.tv_sec * MILLISEC;
+	mSec += (time.tv_nsec / MICROSEC);
+	ddi_put32(accessp, &init->TimeStamp.High, (uint32_t)(mSec >> 32));
+	ddi_put32(accessp, &init->TimeStamp.Low, (uint32_t)mSec);
+
 	numbytes = sizeof (*init);
 
 	/*
--- a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_raid.c	Wed Nov 25 12:30:41 2009 +0800
+++ b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_raid.c	Wed Nov 25 13:05:40 2009 +0800
@@ -77,6 +77,8 @@
 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
+#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_raid.h>
+#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
 
 #pragma pack()
 
@@ -557,6 +559,114 @@
 	return (rval);
 }
 
+/*
+ * The only RAID Action needed throughout the driver is for System Shutdown.
+ * Since this is the only RAID Action and because this Action does not require
+ * waiting for a reply, make this a non-generic function.  If it turns out that
+ * other RAID Actions are required later, a generic function should be used.
+ */
+void
+mptsas_raid_action_system_shutdown(mptsas_t *mpt)
+{
+	pMpi2RaidActionRequest_t	action;
+	uint8_t				ir_active = FALSE;
+	mptsas_slots_t			*slots = mpt->m_active;
+	int				config, vol, action_flags = 0;
+	mptsas_cmd_t			*cmd;
+	struct scsi_pkt			*pkt;
+	uint32_t			request_desc_low;
+
+	ASSERT(mutex_owned(&mpt->m_mutex));
+
+	/*
+	 * Before doing the system shutdown RAID Action, make sure that the IOC
+	 * supports IR and make sure there is a valid volume for the request.
+	 */
+	if (mpt->m_ir_capable) {
+		for (config = 0; config < slots->m_num_raid_configs;
+		    config++) {
+			for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
+				if (slots->m_raidconfig[config].m_raidvol[vol].
+				    m_israid) {
+					ir_active = TRUE;
+					break;
+				}
+			}
+		}
+	}
+	if (!ir_active) {
+		return;
+	}
+
+	/*
+	 * Get a command from the pool.
+	 */
+	if (mptsas_request_from_pool(mpt, &cmd, &pkt) == -1) {
+		mptsas_log(mpt, CE_NOTE, "command pool is full for RAID "
+		    "action request");
+		return;
+	}
+	action_flags |= MPTSAS_REQUEST_POOL_CMD;
+
+	bzero((caddr_t)cmd, sizeof (*cmd));
+	bzero((caddr_t)pkt, scsi_pkt_size());
+
+	pkt->pkt_cdbp		= (opaque_t)&cmd->cmd_cdb[0];
+	pkt->pkt_scbp		= (opaque_t)&cmd->cmd_scb;
+	pkt->pkt_ha_private	= (opaque_t)cmd;
+	pkt->pkt_flags		= (FLAG_NOINTR | FLAG_HEAD);
+	pkt->pkt_time		= 5;
+	cmd->cmd_pkt		= pkt;
+	cmd->cmd_flags		= CFLAG_CMDIOC;
+
+	/*
+	 * Send RAID Action.  We don't care what the reply is so just exit
+	 * after sending the request.  This is just sent to the controller to
+	 * keep the volume from having to resync the next time it starts.  If
+	 * the request doesn't work for whatever reason, we're not going to
+	 * bother wondering why.
+	 */
+	if (mptsas_save_cmd(mpt, cmd) == TRUE) {
+		cmd->cmd_flags |= CFLAG_PREPARED;
+		/*
+		 * Form message for raid action
+		 */
+		action = (pMpi2RaidActionRequest_t)(mpt->m_req_frame +
+		    (mpt->m_req_frame_size * cmd->cmd_slot));
+		bzero(action, mpt->m_req_frame_size);
+		action->Function = MPI2_FUNCTION_RAID_ACTION;
+		action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
+
+		/*
+		 * Send request
+		 */
+		(void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
+		    DDI_DMA_SYNC_FORDEV);
+		request_desc_low = (cmd->cmd_slot << 16) +
+		    MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+		MPTSAS_START_CMD(mpt, request_desc_low, 0);
+
+		/*
+		 * Even though reply does not matter, wait no more than 5
+		 * seconds here to get the reply just because we don't want to
+		 * leave it hanging if it's coming.  Use the FW diag cv.
+		 */
+		(void) cv_reltimedwait(&mpt->m_fw_diag_cv, &mpt->m_mutex,
+		    drv_usectohz(5 * MICROSEC), TR_CLOCK_TICK);
+	}
+
+	/*
+	 * Be sure to deallocate cmd before leaving.
+	 */
+	if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
+		mptsas_remove_cmd(mpt, cmd);
+		action_flags &= (~MPTSAS_REQUEST_POOL_CMD);
+	}
+	if (action_flags & MPTSAS_REQUEST_POOL_CMD)
+		mptsas_return_to_pool(mpt, cmd);
+
+}
+
 int
 mptsas_delete_volume(mptsas_t *mpt, uint16_t volid)
 {
--- a/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/mpi2.h	Wed Nov 25 12:30:41 2009 +0800
+++ b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/mpi2.h	Wed Nov 25 13:05:40 2009 +0800
@@ -53,7 +53,7 @@
  *                  scatter/gather formats.
  *  Creation Date:  June 21, 2006
  *
- *  mpi2.h Version:  02.00.11
+ *  mpi2.h Version:  02.00.13
  *
  *  Version History
  *  ---------------
@@ -90,6 +90,14 @@
  *  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.
  *  --------------------------------------------------------------------------
  */
 
@@ -115,7 +123,7 @@
 #define MPI2_VERSION_02_00                  (0x0200)
 
 /* versioning for this MPI header set */
-#define MPI2_HEADER_VERSION_UNIT            (0x0B)
+#define MPI2_HEADER_VERSION_UNIT            (0x0D)
 #define MPI2_HEADER_VERSION_DEV             (0x00)
 #define MPI2_HEADER_VERSION_UNIT_MASK       (0xFF00)
 #define MPI2_HEADER_VERSION_UNIT_SHIFT      (8)
@@ -302,7 +310,7 @@
 typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR
 {
     U8              RequestFlags;               /* 0x00 */
-    U8              VF_ID;                      /* 0x01 */
+    U8              MSIxIndex;                  /* 0x01 */
     U16             SMID;                       /* 0x02 */
     U16             LMID;                       /* 0x04 */
     U16             DescriptorTypeDependent;    /* 0x06 */
@@ -316,6 +324,7 @@
 #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)
 
@@ -324,7 +333,7 @@
 typedef struct _MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR
 {
     U8              RequestFlags;               /* 0x00 */
-    U8              VF_ID;                      /* 0x01 */
+    U8              MSIxIndex;                  /* 0x01 */
     U16             SMID;                       /* 0x02 */
     U16             LMID;                       /* 0x04 */
     U16             Reserved1;                  /* 0x06 */
@@ -338,7 +347,7 @@
 typedef struct _MPI2_SCSI_IO_REQUEST_DESCRIPTOR
 {
     U8              RequestFlags;               /* 0x00 */
-    U8              VF_ID;                      /* 0x01 */
+    U8              MSIxIndex;                  /* 0x01 */
     U16             SMID;                       /* 0x02 */
     U16             LMID;                       /* 0x04 */
     U16             DevHandle;                  /* 0x06 */
@@ -351,7 +360,7 @@
 typedef struct _MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR
 {
     U8              RequestFlags;               /* 0x00 */
-    U8              VF_ID;                      /* 0x01 */
+    U8              MSIxIndex;                  /* 0x01 */
     U16             SMID;                       /* 0x02 */
     U16             LMID;                       /* 0x04 */
     U16             IoIndex;                    /* 0x06 */
@@ -360,14 +369,30 @@
   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;
-    U64                                     Words;
+    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;
 
@@ -378,19 +403,20 @@
 typedef struct _MPI2_DEFAULT_REPLY_DESCRIPTOR
 {
     U8              ReplyFlags;                 /* 0x00 */
-    U8              VF_ID;                      /* 0x01 */
+    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_UNUSED                  (0x0F)
+#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)
@@ -400,7 +426,7 @@
 typedef struct _MPI2_ADDRESS_REPLY_DESCRIPTOR
 {
     U8              ReplyFlags;                 /* 0x00 */
-    U8              VF_ID;                      /* 0x01 */
+    U8              MSIxIndex;                  /* 0x01 */
     U16             SMID;                       /* 0x02 */
     U32             ReplyFrameAddress;          /* 0x04 */
 } MPI2_ADDRESS_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_ADDRESS_REPLY_DESCRIPTOR,
@@ -413,10 +439,10 @@
 typedef struct _MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR
 {
     U8              ReplyFlags;                 /* 0x00 */
-    U8              VF_ID;                      /* 0x01 */
+    U8              MSIxIndex;                  /* 0x01 */
     U16             SMID;                       /* 0x02 */
     U16             TaskTag;                    /* 0x04 */
-    U16             DevHandle;                  /* 0x06 */
+    U16             Reserved1;                  /* 0x06 */
 } MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
   MPI2_POINTER PTR_MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
   Mpi2SCSIIOSuccessReplyDescriptor_t,
@@ -427,7 +453,7 @@
 typedef struct _MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR
 {
     U8              ReplyFlags;                 /* 0x00 */
-    U8              VF_ID;                      /* 0x01 */
+    U8              MSIxIndex;                  /* 0x01 */
     U16             SMID;                       /* 0x02 */
     U8              SequenceNumber;             /* 0x04 */
     U8              Reserved1;                  /* 0x05 */
@@ -442,7 +468,7 @@
 typedef struct _MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR
 {
     U8              ReplyFlags;                 /* 0x00 */
-    U8              VF_ID;                      /* 0x01 */
+    U8              MSIxIndex;                  /* 0x01 */
     U8              VP_ID;                      /* 0x02 */
     U8              Flags;                      /* 0x03 */
     U16             InitiatorDevHandle;         /* 0x04 */
@@ -456,15 +482,29 @@
 #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;
-    U64                                         Words;
+    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;
 
@@ -503,6 +543,7 @@
 #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 */
 
 
 
@@ -600,12 +641,17 @@
 
 #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)
+#define MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE      (0x8000)
 
 /****************************************************************************
 *  IOCLogInfo Types
--- a/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h	Wed Nov 25 12:30:41 2009 +0800
+++ b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h	Wed Nov 25 13:05:40 2009 +0800
@@ -51,7 +51,7 @@
  *          Title:  MPI Configuration messages and pages
  *  Creation Date:  November 10, 2006
  *
- *    mpi2_cnfg.h Version:  02.00.10
+ *    mpi2_cnfg.h Version:  02.00.12
  *
  *  Version History
  *  ---------------
@@ -140,6 +140,18 @@
  *                      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.
  *  --------------------------------------------------------------------------
  */
 
@@ -222,6 +234,7 @@
 #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)
 
 
 /*****************************************************************************
@@ -308,6 +321,14 @@
 #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
 ****************************************************************************/
@@ -389,6 +410,15 @@
 #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 */
 
@@ -768,6 +798,117 @@
 #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
 ****************************************************************************/
@@ -1451,6 +1592,12 @@
 
 /* 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)
@@ -1663,11 +1810,11 @@
 /* values for SAS IO Unit Page 1 PortFlags */
 #define MPI2_SASIOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG                 (0x01)
 
-/* values for SAS IO Unit Page 2 PhyFlags */
+/* 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 0 MaxMinLinkRate */
+/* 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)
@@ -1726,6 +1873,75 @@
 #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
 ****************************************************************************/
@@ -1754,10 +1970,14 @@
     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       (0x05)
+#define MPI2_SASEXPANDER0_PAGEVERSION       (0x06)
 
 /* values for SAS Expander Page 0 DiscoveryStatus field */
 #define MPI2_SAS_EXPANDER0_DS_MAX_ENCLOSURES_EXCEED         (0x80000000)
@@ -1782,6 +2002,7 @@
 #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)
@@ -1903,6 +2124,8 @@
 /* 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)
@@ -1989,6 +2212,135 @@
 #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 Port Config Pages
 ****************************************************************************/
@@ -2192,5 +2544,123 @@
 #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
 
--- a/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h	Wed Nov 25 12:30:41 2009 +0800
+++ b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h	Wed Nov 25 13:05:40 2009 +0800
@@ -51,7 +51,7 @@
  *          Title:  MPI SCSI initiator mode messages and structures
  *  Creation Date:  June 23, 2006
  *
- *    mpi2_init.h Version:  02.00.06
+ *    mpi2_init.h Version:  02.00.07
  *
  *  Version History
  *  ---------------
@@ -68,6 +68,10 @@
  *                      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.
  *  --------------------------------------------------------------------------
  */
 
@@ -334,7 +338,10 @@
 #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_UNIT_ATTENTION   (0x0A)
+#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 */
 
@@ -420,6 +427,8 @@
 #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)
@@ -455,6 +464,8 @@
 #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)
--- a/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h	Wed Nov 25 12:30:41 2009 +0800
+++ b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h	Wed Nov 25 13:05:40 2009 +0800
@@ -25,7 +25,7 @@
  *
  * Redistribution and use in source and binary forms of all code within
  * this file that is exclusively owned by LSI, with or without
- * modification, is permitted provided that, in addition to the CDDL 1.0 
+ * modification, is permitted provided that, in addition to the CDDL 1.0
  * License requirements, the following conditions are met:
  *
  *    Neither the name of the author nor the names of its contributors may be
@@ -51,7 +51,7 @@
  *          Title:  MPI IOC, Port, Event, FW Download, and FW Upload messages
  *  Creation Date:  October 11, 2006
  *
- *  mpi2_ioc.h Version:  02.00.10
+ *  mpi2_ioc.h Version:  02.00.12
  *
  *  Version History
  *  ---------------
@@ -124,6 +124,14 @@
  *                      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.
  *  --------------------------------------------------------------------------
  */
 
@@ -306,12 +314,15 @@
 /* ProductID field uses MPI2_FW_HEADER_PID_ */
 
 /* IOCCapabilities */
+#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)
@@ -485,6 +496,8 @@
 #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)
 
 
 /* Log Entry Added Event data */
@@ -506,6 +519,17 @@
   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
@@ -547,17 +571,19 @@
   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_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 */
@@ -867,6 +893,36 @@
 #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 */
+
+
 /****************************************************************************
 *  EventAck message
 ****************************************************************************/
@@ -1121,6 +1177,7 @@
 #define MPI2_FW_HEADER_PID_FAMILY_MASK          (0x00FF)
 /* SAS */
 #define MPI2_FW_HEADER_PID_FAMILY_2108_SAS      (0x0010)
+#define MPI2_FW_HEADER_PID_FAMILY_2208_SAS      (0x0011)
 
 /* use MPI2_IOCFACTS_PROTOCOL_ defines for ProtocolFlags field */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/mpi2_raid.h	Wed Nov 25 13:05:40 2009 +0800
@@ -0,0 +1,346 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2000 to 2009, LSI Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms of all code within
+ * this file that is exclusively owned by LSI, with or without
+ * modification, is permitted provided that, in addition to the CDDL 1.0
+ * License requirements, the following conditions are met:
+ *
+ *    Neither the name of the author nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
+ */
+
+/*
+ *           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
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h	Wed Nov 25 13:05:40 2009 +0800
@@ -0,0 +1,435 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2000 to 2009, LSI Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms of all code within
+ * this file that is exclusively owned by LSI, with or without
+ * modification, is permitted provided that, in addition to the CDDL 1.0
+ * License requirements, the following conditions are met:
+ *
+ *    Neither the name of the author nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
+ */
+
+/*
+ *           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
+
--- a/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_ioctl.h	Wed Nov 25 12:30:41 2009 +0800
+++ b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_ioctl.h	Wed Nov 25 13:05:40 2009 +0800
@@ -70,6 +70,7 @@
 #define	MPTIOCTL_EVENT_REPORT		(MPTIOCTL | 7)
 #define	MPTIOCTL_GET_PCI_INFO		(MPTIOCTL | 8)
 #define	MPTIOCTL_DIAG_ACTION		(MPTIOCTL | 9)
+#define	MPTIOCTL_REG_ACCESS		(MPTIOCTL | 10)
 
 /*
  *  The following are our ioctl() return status values.  If everything went
@@ -196,7 +197,6 @@
 	uint32_t	ReturnCode;
 } mptsas_diag_action_t;
 
-#define	MPTSAS_FW_DIAGNOSTIC_BUFFER_COUNT	(3)
 #define	MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND	(0xFF)
 
 #define	MPTSAS_FW_DIAG_NEW			(0x806E6577)
@@ -221,7 +221,7 @@
 
 typedef struct mptsas_fw_diag_register
 {
-	uint8_t		Reserved1;
+	uint8_t		ExtendedType;
 	uint8_t		BufferType;
 	uint16_t	ApplicationFlags;
 	uint32_t	DiagnosticFlags;
@@ -241,7 +241,7 @@
 
 typedef struct mptsas_fw_diag_query
 {
-	uint8_t		Reserved1;
+	uint8_t		ExtendedType;
 	uint8_t		BufferType;
 	uint16_t	ApplicationFlags;
 	uint32_t	DiagnosticFlags;
@@ -254,7 +254,7 @@
 typedef struct mptsas_fw_diag_release
 {
 	uint32_t	UniqueId;
-} mptsas_fw_diag_release;
+} mptsas_fw_diag_release_t;
 
 #define	MPTSAS_FW_DIAG_FLAG_REREGISTER		(0x0001)
 #define	MPTSAS_FW_DIAG_FLAG_FORCE_RELEASE	(0x0002)
@@ -270,6 +270,21 @@
 	uint32_t	DataBuffer[1];
 } mptsas_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 mptsas_reg_access
+{
+	uint32_t	Command;
+	uint32_t	RegOffset;
+	uint32_t	RegData;
+} mptsas_reg_access_t;
+
 #ifdef  __cplusplus
 }
 #endif
--- a/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_var.h	Wed Nov 25 12:30:41 2009 +0800
+++ b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_var.h	Wed Nov 25 13:05:40 2009 +0800
@@ -305,6 +305,7 @@
 #define	CFLAG_TXQ		0x10000000 /* cmd queued in the tx_waitq */
 #define	CFLAG_FW_CMD		0x20000000 /* cmd is a fw up/down command */
 #define	CFLAG_CONFIG		0x40000000 /* cmd is for config header/page */
+#define	CFLAG_FW_DIAG		0x80000000 /* cmd is for FW diag buffers */
 
 #define	MPTSAS_SCSI_REPORTLUNS_ADDRESS_SIZE			8
 #define	MPTSAS_SCSI_REPORTLUNS_ADDRESS_MASK			0xC0
@@ -326,6 +327,15 @@
 #define	MPTSAS_HASH_FIRST	0xffff
 #define	MPTSAS_HASH_NEXT	0x0000
 
+typedef struct mptsas_dma_alloc_state
+{
+	ddi_dma_handle_t	handle;
+	caddr_t			memp;
+	size_t			size;
+	ddi_acc_handle_t	accessp;
+	ddi_dma_cookie_t	cookie;
+} mptsas_dma_alloc_state_t;
+
 /*
  * passthrough request structure
  */
@@ -353,6 +363,27 @@
 	uint16_t	ext_page_length;
 } mptsas_config_request_t;
 
+typedef struct mptsas_fw_diagnostic_buffer {
+	mptsas_dma_alloc_state_t	buffer_data;
+	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;
+} mptsas_fw_diagnostic_buffer_t;
+
+/*
+ * FW diag request structure
+ */
+typedef struct mptsas_diag_request {
+	mptsas_fw_diagnostic_buffer_t	*pBuffer;
+	uint8_t				function;
+} mptsas_diag_request_t;
+
 typedef struct mptsas_hash_node {
 	void *data;
 	struct mptsas_hash_node *next;
@@ -591,6 +622,7 @@
 	kcondvar_t		m_passthru_cv;
 	kcondvar_t		m_fw_cv;
 	kcondvar_t		m_config_cv;
+	kcondvar_t		m_fw_diag_cv;
 	dev_info_t		*m_dip;
 
 	/*
@@ -785,6 +817,7 @@
 	uint8_t			m_done_traverse_dev;
 	uint8_t			m_done_traverse_smp;
 	int			m_passthru_in_progress;
+	int			m_diag_action_in_progress;
 	uint16_t		m_dev_handle;
 	uint16_t		m_smp_devhdl;
 
@@ -797,6 +830,22 @@
 	mptsas_event_entry_t	m_events[MPTSAS_EVENT_QUEUE_SIZE];
 
 	/*
+	 * FW diag Buffer List
+	 */
+	mptsas_fw_diagnostic_buffer_t
+		m_fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_COUNT];
+
+	/*
+	 * Event Replay flag (MUR support)
+	 */
+	uint8_t			m_event_replay;
+
+	/*
+	 * IR Capable flag
+	 */
+	uint8_t			m_ir_capable;
+
+	/*
 	 * per instance cmd data structures for task management cmds
 	 */
 	m_event_struct_t	m_event_task_mgmt;	/* must be last */
@@ -830,15 +879,6 @@
 _NOTE(DATA_READABLE_WITHOUT_LOCK(mptsas::m_ntargets))
 _NOTE(DATA_READABLE_WITHOUT_LOCK(mptsas::m_instance))
 
-typedef struct mptsas_dma_alloc_state
-{
-	ddi_dma_handle_t	handle;
-	caddr_t			memp;
-	size_t			size;
-	ddi_acc_handle_t	accessp;
-	ddi_dma_cookie_t	cookie;
-} mptsas_dma_alloc_state_t;
-
 /*
  * These should eventually migrate into the mpt header files
  * that may become the /kernel/misc/mpt module...
@@ -1165,9 +1205,8 @@
 	uint8_t type, int mode);
 int mptsas_download_firmware();
 int mptsas_can_download_firmware();
-int mptsas_passthru_dma_alloc(mptsas_t *mpt,
-    mptsas_dma_alloc_state_t *dma_statep);
-void mptsas_passthru_dma_free(mptsas_dma_alloc_state_t *dma_statep);
+int mptsas_dma_alloc(mptsas_t *mpt, mptsas_dma_alloc_state_t *dma_statep);
+void mptsas_dma_free(mptsas_dma_alloc_state_t *dma_statep);
 uint8_t mptsas_physport_to_phymask(mptsas_t *mpt, uint8_t physport);
 uint8_t mptsas_phymask_to_physport(mptsas_t *mpt, uint8_t phymask);
 void mptsas_fma_check(mptsas_t *mpt, mptsas_cmd_t *cmd);
@@ -1246,6 +1285,7 @@
 int mptsas_get_physdisk_settings(mptsas_t *mpt, mptsas_raidvol_t *raidvol,
     uint8_t physdisknum);
 int mptsas_delete_volume(mptsas_t *mpt, uint16_t volid);
+void mptsas_raid_action_system_shutdown(mptsas_t *mpt);
 
 #define	MPTSAS_IOCSTATUS(status) (status & MPI2_IOCSTATUS_MASK)
 /*