--- old/usr/src/uts/common/io/scsi/adapters/mpt_sas3/mptsas3_init.c	2014-06-12 17:42:17.118522197 +0100
+++ new/usr/src/uts/common/io/scsi/adapters/mpt_sas3/mptsas3_init.c	2014-06-12 17:42:17.124301808 +0100
@@ -22,6 +22,7 @@
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright (c) 2014, Tegile Systems Inc. All rights reserved.
  */
 
 /*
@@ -67,17 +68,17 @@
 #include <sys/scsi/scsi.h>
 
 #pragma pack(1)
-#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h>
-#include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
-#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>
+#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_type.h>
+#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2.h>
+#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_cnfg.h>
+#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_init.h>
+#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_ioc.h>
+#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_tool.h>
 #pragma pack()
 /*
  * private header files.
  */
-#include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
+#include <sys/scsi/adapters/mpt_sas3/mptsas3_var.h>
 
 static int mptsas_ioc_do_get_facts(mptsas_t *mpt, caddr_t memp, int var,
 	ddi_acc_handle_t accessp);
@@ -101,12 +102,47 @@
 	ddi_acc_handle_t accessp);
 
 static const char *
-mptsas_product_type_string(mptsas_t *mpt)
+mptsas_devid_type_string(mptsas_t *mpt)
 {
-	switch (mpt->m_productid & MPI2_FW_HEADER_PID_PROD_MASK) {
-
-	case MPI2_FW_HEADER_PID_PROD_A:
-		return ("A");
+	switch (mpt->m_devid) {
+	case MPI2_MFGPAGE_DEVID_SAS2008:
+		return ("SAS2008");
+	case MPI2_MFGPAGE_DEVID_SAS2004:
+		return ("SAS2004");
+	case MPI2_MFGPAGE_DEVID_SAS2108_1:
+	case MPI2_MFGPAGE_DEVID_SAS2108_2:
+	case MPI2_MFGPAGE_DEVID_SAS2108_3:
+		return ("SAS2108");
+	case MPI2_MFGPAGE_DEVID_SAS2116_1:
+	case MPI2_MFGPAGE_DEVID_SAS2116_2:
+		return ("SAS2116");
+	case MPI2_MFGPAGE_DEVID_SAS2208_1:
+	case MPI2_MFGPAGE_DEVID_SAS2208_2:
+	case MPI2_MFGPAGE_DEVID_SAS2208_3:
+	case MPI2_MFGPAGE_DEVID_SAS2208_4:
+	case MPI2_MFGPAGE_DEVID_SAS2208_5:
+	case MPI2_MFGPAGE_DEVID_SAS2208_6:
+#if 0
+	/* These are the same as the next 2?? */
+	case MPI2_MFGPAGE_DEVID_SAS2208_7:
+	case MPI2_MFGPAGE_DEVID_SAS2208_8:
+#endif
+		return ("SAS2208");
+	case MPI2_MFGPAGE_DEVID_SAS2308_1:
+	case MPI2_MFGPAGE_DEVID_SAS2308_2:
+	case MPI2_MFGPAGE_DEVID_SAS2308_3:
+		return ("SAS2308");
+	case MPI25_MFGPAGE_DEVID_SAS3004:
+		return ("SAS3004");
+	case MPI25_MFGPAGE_DEVID_SAS3008:
+		return ("SAS3008");
+	case MPI25_MFGPAGE_DEVID_SAS3108_1:
+	case MPI25_MFGPAGE_DEVID_SAS3108_2:
+	case MPI25_MFGPAGE_DEVID_SAS3108_3:
+	case MPI25_MFGPAGE_DEVID_SAS3108_4:
+	case MPI25_MFGPAGE_DEVID_SAS3108_5:
+	case MPI25_MFGPAGE_DEVID_SAS3108_6:
+		return ("SAS3108");
 	default:
 		return ("?");
 	}
@@ -176,6 +212,7 @@
 	int			simple_sge_main;
 	int			simple_sge_next;
 	uint32_t		capabilities;
+	uint16_t		msgversion;
 
 	bzero(memp, sizeof (*factsreply));
 	factsreply = (void *)memp;
@@ -207,8 +244,8 @@
 	    ddi_get8(accessp, &factsreply->FWVersion.Struct.Minor),
 	    ddi_get8(accessp, &factsreply->FWVersion.Struct.Unit),
 	    ddi_get8(accessp, &factsreply->FWVersion.Struct.Dev));
-	mptsas_log(mpt, CE_NOTE, "?mpt%d Firmware version v%s (%s)\n",
-	    mpt->m_instance, buf, mptsas_product_type_string(mpt));
+	mptsas_log(mpt, CE_NOTE, "?MPT Firmware version v%s (%s)\n",
+	    buf, mptsas_devid_type_string(mpt));
 	(void) ddi_prop_update_string(DDI_DEV_T_NONE, mpt->m_dip,
 	    "firmware-version", buf);
 
@@ -245,6 +282,9 @@
 	 * calculated queue size is larger than allowed, subtract a
 	 * multiple of 16 from m_max_requests, m_max_replies, and
 	 * m_reply_free_depth.
+	 *
+	 * There is no indication in the spec that you can reduce the
+	 * queue size if you have many.
 	 */
 	queueSize = mpt->m_max_requests + numReplyFrames + 1;
 	if (queueSize % 16) {
@@ -271,13 +311,31 @@
 	    &factsreply->MaxChainDepth);
 	mpt->m_ioc_capabilities = ddi_get32(accessp,
 	    &factsreply->IOCCapabilities);
+	if (mpt->m_ioc_capabilities & MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) {
+		mpt->m_max_msix_vectors = ddi_get8(accessp,
+		    &factsreply->MaxMSIxVectors);
+	}
+
+	/*
+	 * Set flag to check for SAS3 support.
+	 */
+	msgversion = ddi_get16(accessp, &factsreply->MsgVersion);
+	if (msgversion == MPI2_VERSION_02_05) {
+		mptsas_log(mpt, CE_NOTE, "?mpt_sas3%d SAS 3 Supported\n",
+		    mpt->m_instance);
+		mpt->m_MPI25 = TRUE;
+	} else {
+		mptsas_log(mpt, CE_NOTE, "?mpt_sas3%d MPI Version 0x%x\n",
+		    mpt->m_instance, msgversion);
+	}
 
 	/*
 	 * 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;
+	    (mpt->m_MPI25 ? sizeof (MPI2_IEEE_SGE_SIMPLE64) :
+	    sizeof (MPI2_SGE_SIMPLE64)) - 1;
 
 	mpt->m_max_request_frames = (MPTSAS_MAX_DMA_SEGS -
 	    simple_sge_main) / simple_sge_next + 1;
@@ -290,7 +348,7 @@
 	 * Check if controller supports FW diag buffers and set flag to enable
 	 * each type.
 	 */
-	capabilities = ddi_get32(accessp, &factsreply->IOCCapabilities);
+	capabilities = mpt->m_ioc_capabilities;
 	if (capabilities & MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) {
 		mpt->m_fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_TRACE].enabled =
 		    TRUE;
@@ -603,6 +661,9 @@
 	ddi_put8(accessp, &init->WhoInit, MPI2_WHOINIT_HOST_DRIVER);
 	ddi_put16(accessp, &init->MsgVersion, MPI2_VERSION);
 	ddi_put16(accessp, &init->HeaderVersion, MPI2_HEADER_VERSION);
+	if (mpt->m_intr_type == DDI_INTR_TYPE_MSIX) {
+		ddi_put8(accessp, &init->HostMSIxVectors, mpt->m_intr_cnt);
+	}
 	ddi_put16(accessp, &init->SystemRequestFrameSize,
 	    mpt->m_req_frame_size / 4);
 	ddi_put16(accessp, &init->ReplyDescriptorPostQueueDepth,
@@ -614,7 +675,8 @@
 	 * These addresses are set using the DMA cookie addresses from when the
 	 * memory was allocated.  Sense buffer hi address should be 0.
 	 */
-	ddi_put32(accessp, &init->SenseBufferAddressHigh, 0);
+	ddi_put32(accessp, &init->SenseBufferAddressHigh,
+	    (uint32_t)(mpt->m_req_sense_dma_addr >> 32));
 	ddi_put32(accessp, &init->SystemReplyAddressHigh,
 	    (uint32_t)(mpt->m_reply_frame_dma_addr >> 32));
 	ddi_put32(accessp, &init->SystemRequestFrameBaseAddress.High,
