From 33219b9f4dc73699d02462f60bb278f79deb72c9 Mon Sep 17 00:00:00 2001
From: Sascha Wildner <saw@online.de>
Date: Sun, 12 Feb 2012 16:28:16 +0100
Subject: [PATCH] mfi(4): Update to LSI's version 4.23 of the driver.

Brings in support for a couple of new cards, namely the Intel RAID
controllers RS25DB080 and RS25NB008. Probably also for other cards
of the "ThunderBolt" type.

A few other things have been fixed too. Most x86_64/i386 specific
parts have been merged, MSI is now setup in mfi_pci.c properly.

Many thanks to LSI for having a place for the BSDs in their heart
and to Xin Li for bringing this work to my attention. It was taken
from FreeBSD's projects/ repository.

The ThunderBolt support has not been tested yet since I don't own
a compatible card.
---
 share/man/man4/mfi.4         |    6 +-
 sys/conf/files               |    1 +
 sys/dev/raid/mfi/Makefile    |    2 +-
 sys/dev/raid/mfi/mfi.c       | 1048 +++++++++++++++++++++-----------
 sys/dev/raid/mfi/mfi_cam.c   |   35 +-
 sys/dev/raid/mfi/mfi_debug.c |   20 +-
 sys/dev/raid/mfi/mfi_disk.c  |   43 +-
 sys/dev/raid/mfi/mfi_ioctl.h |   41 +-
 sys/dev/raid/mfi/mfi_pci.c   |   84 ++--
 sys/dev/raid/mfi/mfi_syspd.c |   13 +-
 sys/dev/raid/mfi/mfi_tbolt.c | 1383 ++++++++++++++++++++++++++++++++++++++++++
 sys/dev/raid/mfi/mfireg.h    |  634 ++++++++++++++++++--
 sys/dev/raid/mfi/mfivar.h    |  219 ++++++--
 13 files changed, 2933 insertions(+), 596 deletions(-)
 create mode 100644 sys/dev/raid/mfi/mfi_tbolt.c

diff --git a/share/man/man4/mfi.4 b/share/man/man4/mfi.4
index ffad85e..1d70479 100644
--- a/share/man/man4/mfi.4
+++ b/share/man/man4/mfi.4
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD: src/share/man/man4/mfi.4,v 1.13 2010/05/12 17:12:38 brueffer Exp $
 .\"
-.Dd August 11, 2011
+.Dd February 12, 2012
 .Dt MFI 4
 .Os
 .Sh NAME
@@ -134,6 +134,10 @@ IBM ServeRAID M5015 SAS/SATA
 IBM ServeRAID-MR10i
 .It
 Intel RAID Controller SROMBSAS18E
+.It
+Intel RAID Controller RS25DB080
+.It
+Intel RAID Controller RS25NB008
 .El
 .Sh FILES
 .Bl -tag -width ".Pa /dev/mfisyspd?" -compact
diff --git a/sys/conf/files b/sys/conf/files
index cf01bf8..f492730 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -578,6 +578,7 @@ dev/raid/mfi/mfi_debug.c	optional mfi
 dev/raid/mfi/mfi_pci.c		optional mfi pci
 dev/raid/mfi/mfi_disk.c		optional mfi
 dev/raid/mfi/mfi_syspd.c	optional mfi
+dev/raid/mfi/mfi_tbolt.c	optional mfi
 dev/raid/mfi/mfi_linux.c	optional mfi compat_linux
 dev/raid/mfi/mfi_cam.c		optional mfip scbus
 dev/netif/mii_layer/mii.c		optional miibus
diff --git a/sys/dev/raid/mfi/Makefile b/sys/dev/raid/mfi/Makefile
index 809eac3..62557da 100644
--- a/sys/dev/raid/mfi/Makefile
+++ b/sys/dev/raid/mfi/Makefile
@@ -8,7 +8,7 @@ SUBDIR+= mfi_linux
 .endif
 
 KMOD=	mfi
-SRCS=	mfi.c mfi_pci.c mfi_disk.c mfi_debug.c mfi_syspd.c
+SRCS=	mfi.c mfi_pci.c mfi_disk.c mfi_debug.c mfi_syspd.c mfi_tbolt.c
 SRCS+=	opt_mfi.h opt_cam.h
 SRCS+=	device_if.h bus_if.h pci_if.h
 
diff --git a/sys/dev/raid/mfi/mfi.c b/sys/dev/raid/mfi/mfi.c
index 0bd850a..c9ecd7f 100644
--- a/sys/dev/raid/mfi/mfi.c
+++ b/sys/dev/raid/mfi/mfi.c
@@ -48,36 +48,6 @@
  * 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.
- */
-/*-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *            Copyright 1994-2009 The FreeBSD Project.
- *            All rights reserved.
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- *    THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT``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 FREEBSD PROJECT 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.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies,either expressed or implied, of the FreeBSD Project.
  *
  * $FreeBSD: src/sys/dev/mfi/mfi.c,v 1.62 2011/11/09 21:53:49 delphij Exp $
  */
@@ -100,6 +70,7 @@
 #include <sys/signalvar.h>
 #include <sys/device.h>
 #include <sys/mplock2.h>
+#include <sys/taskqueue.h>
 
 #include <bus/cam/scsi/scsi_all.h>
 
@@ -111,7 +82,6 @@
 
 static int	mfi_alloc_commands(struct mfi_softc *);
 static int	mfi_comms_init(struct mfi_softc *);
-static int	mfi_wait_command(struct mfi_softc *, struct mfi_command *);
 static int	mfi_get_controller_info(struct mfi_softc *);
 static int	mfi_get_log_state(struct mfi_softc *,
 		    struct mfi_evt_log_state **);
@@ -123,9 +93,9 @@ static void	mfi_startup(void *arg);
 static void	mfi_intr(void *arg);
 static void	mfi_ldprobe(struct mfi_softc *sc);
 static void	mfi_syspdprobe(struct mfi_softc *sc);
+static void	mfi_handle_evt(void *context, int pending);
 static int	mfi_aen_register(struct mfi_softc *sc, int seq, int locale);
 static void	mfi_aen_complete(struct mfi_command *);
-static int	mfi_aen_setup(struct mfi_softc *, uint32_t);
 static int	mfi_add_ld(struct mfi_softc *sc, int);
 static void	mfi_add_ld_complete(struct mfi_command *);
 static int	mfi_add_sys_pd(struct mfi_softc *sc, int);
@@ -134,9 +104,7 @@ static struct mfi_command * mfi_bio_command(struct mfi_softc *);
 static void	mfi_bio_complete(struct mfi_command *);
 static struct mfi_command * mfi_build_ldio(struct mfi_softc *,struct bio*);
 static struct mfi_command * mfi_build_syspdio(struct mfi_softc *,struct bio*);
-static int	mfi_mapcmd(struct mfi_softc *, struct mfi_command *);
 static int	mfi_send_frame(struct mfi_softc *, struct mfi_command *);
-static void	mfi_complete(struct mfi_softc *, struct mfi_command *);
 static int	mfi_abort(struct mfi_softc *, struct mfi_command *);
 static int	mfi_linux_ioctl_int(struct cdev *, u_long, caddr_t, int);
 static void	mfi_timeout(void *);
@@ -148,11 +116,18 @@ static int32_t 	mfi_read_fw_status_xscale(struct mfi_softc *sc);
 static int32_t 	mfi_read_fw_status_ppc(struct mfi_softc *sc);
 static int 	mfi_check_clear_intr_xscale(struct mfi_softc *sc);
 static int 	mfi_check_clear_intr_ppc(struct mfi_softc *sc);
-static void 	mfi_issue_cmd_xscale(struct mfi_softc *sc,uint32_t bus_add,uint32_t frame_cnt);
-static void 	mfi_issue_cmd_ppc(struct mfi_softc *sc,uint32_t bus_add,uint32_t frame_cnt);
 static void	mfi_filter_detach(struct knote *);
 static int	mfi_filter_read(struct knote *, long);
 static int	mfi_filter_write(struct knote *, long);
+static void 	mfi_issue_cmd_xscale(struct mfi_softc *sc, bus_addr_t bus_add,
+		    uint32_t frame_cnt);
+static void 	mfi_issue_cmd_ppc(struct mfi_softc *sc, bus_addr_t bus_add,
+		    uint32_t frame_cnt);
+static int mfi_config_lock(struct mfi_softc *sc, uint32_t opcode);
+static void mfi_config_unlock(struct mfi_softc *sc, int locked);
+static int mfi_check_command_pre(struct mfi_softc *sc, struct mfi_command *cm);
+static void mfi_check_command_post(struct mfi_softc *sc, struct mfi_command *cm);
+static int mfi_check_for_sscd(struct mfi_softc *sc, struct mfi_command *cm);
 
 SYSCTL_NODE(_hw, OID_AUTO, mfi, CTLFLAG_RD, 0, "MFI driver parameters");
 static int	mfi_event_locale = MFI_EVT_LOCALE_ALL;
@@ -170,9 +145,6 @@ TUNABLE_INT("hw.mfi.max_cmds", &mfi_max_cmds);
 SYSCTL_INT(_hw_mfi, OID_AUTO, max_cmds, CTLFLAG_RD, &mfi_max_cmds,
 	   0, "Max commands");
 
-static int	mfi_msi_enable = 1;
-TUNABLE_INT("hw.mfi.msi.enable", &mfi_msi_enable);
-
 /* Management interface */
 static d_open_t		mfi_open;
 static d_close_t	mfi_close;
@@ -195,6 +167,7 @@ static struct filterops mfi_write_filterops =
 MALLOC_DEFINE(M_MFIBUF, "mfibuf", "Buffers for the MFI driver");
 
 #define MFI_INQ_LENGTH SHORT_INQUIRY_LENGTH
+struct mfi_skinny_dma_info mfi_skinny;
 
 static void
 mfi_enable_intr_xscale(struct mfi_softc *sc)
@@ -262,13 +235,13 @@ mfi_check_clear_intr_ppc(struct mfi_softc *sc)
 }
 
 static void
-mfi_issue_cmd_xscale(struct mfi_softc *sc,uint32_t bus_add,uint32_t frame_cnt)
+mfi_issue_cmd_xscale(struct mfi_softc *sc, bus_addr_t bus_add, uint32_t frame_cnt)
 {
 	MFI_WRITE4(sc, MFI_IQP,(bus_add >>3) | frame_cnt);
 }
 
 static void
-mfi_issue_cmd_ppc(struct mfi_softc *sc,uint32_t bus_add,uint32_t frame_cnt)
+mfi_issue_cmd_ppc(struct mfi_softc *sc, bus_addr_t bus_add, uint32_t frame_cnt)
 {
 	if (sc->mfi_flags & MFI_FLAGS_SKINNY) {
 		MFI_WRITE4(sc, MFI_IQPL, (bus_add | frame_cnt << 1) | 1);
@@ -278,18 +251,16 @@ mfi_issue_cmd_ppc(struct mfi_softc *sc,uint32_t bus_add,uint32_t frame_cnt)
 	}
 }
 
-static int
+int
 mfi_transition_firmware(struct mfi_softc *sc)
 {
 	uint32_t fw_state, cur_state;
 	int max_wait, i;
 	uint32_t cur_abs_reg_val = 0;
 	uint32_t prev_abs_reg_val = 0;
-	bus_space_handle_t idb;
 
 	cur_abs_reg_val = sc->mfi_read_fw_status(sc);
 	fw_state = cur_abs_reg_val & MFI_FWSTATE_MASK;
-	idb = sc->mfi_flags & MFI_FLAGS_SKINNY ? MFI_SKINNY_IDB : MFI_IDB;
 	while (fw_state != MFI_FWSTATE_READY) {
 		if (bootverbose)
 			device_printf(sc->mfi_dev, "Waiting for firmware to "
@@ -300,28 +271,41 @@ mfi_transition_firmware(struct mfi_softc *sc)
 			device_printf(sc->mfi_dev, "Firmware fault\n");
 			return (ENXIO);
 		case MFI_FWSTATE_WAIT_HANDSHAKE:
-			MFI_WRITE4(sc, idb, MFI_FWINIT_CLEAR_HANDSHAKE);
-			max_wait = 2;
+			if (sc->mfi_flags & MFI_FLAGS_SKINNY || sc->mfi_flags & MFI_FLAGS_TBOLT)
+			    MFI_WRITE4(sc, MFI_SKINNY_IDB, MFI_FWINIT_CLEAR_HANDSHAKE);
+			else
+			    MFI_WRITE4(sc, MFI_IDB, MFI_FWINIT_CLEAR_HANDSHAKE);
+			max_wait = MFI_RESET_WAIT_TIME;
 			break;
 		case MFI_FWSTATE_OPERATIONAL:
-			MFI_WRITE4(sc, idb, MFI_FWINIT_READY);
-			max_wait = 10;
+			if (sc->mfi_flags & MFI_FLAGS_SKINNY || sc->mfi_flags & MFI_FLAGS_TBOLT)
+			    //MFI_WRITE4(sc, MFI_SKINNY_IDB, MFI_FWINIT_READY);
+			    MFI_WRITE4(sc, MFI_SKINNY_IDB, 7);
+			else
+			    MFI_WRITE4(sc, MFI_IDB, MFI_FWINIT_READY);
+			max_wait = MFI_RESET_WAIT_TIME;
 			break;
 		case MFI_FWSTATE_UNDEFINED:
 		case MFI_FWSTATE_BB_INIT:
-			max_wait = 2;
+			max_wait = MFI_RESET_WAIT_TIME;
+			break;
+		case MFI_FWSTATE_FW_INIT_2:
+			max_wait = MFI_RESET_WAIT_TIME;
 			break;
 		case MFI_FWSTATE_FW_INIT:
 		case MFI_FWSTATE_FLUSH_CACHE:
-			max_wait = 20;
+			max_wait = MFI_RESET_WAIT_TIME;
 			break;
 		case MFI_FWSTATE_DEVICE_SCAN:
-			max_wait = 180; /* wait for 180 seconds */
+			max_wait = MFI_RESET_WAIT_TIME; /* wait for 180 seconds */
 			prev_abs_reg_val = cur_abs_reg_val;
 			break;
 		case MFI_FWSTATE_BOOT_MESSAGE_PENDING:
-			MFI_WRITE4(sc, idb, MFI_FWINIT_HOTPLUG);
-			max_wait = 10;
+			if (sc->mfi_flags & MFI_FLAGS_SKINNY || sc->mfi_flags & MFI_FLAGS_TBOLT)
+			    MFI_WRITE4(sc, MFI_SKINNY_IDB, MFI_FWINIT_HOTPLUG);
+			else
+			    MFI_WRITE4(sc, MFI_IDB, MFI_FWINIT_HOTPLUG);
+			max_wait = MFI_RESET_WAIT_TIME;
 			break;
 		default:
 			device_printf(sc->mfi_dev,"Unknown firmware state %#x\n",
@@ -350,25 +334,14 @@ mfi_transition_firmware(struct mfi_softc *sc)
 	return (0);
 }
 
-#if defined(__x86_64__)
-static void
-mfi_addr64_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
-{
-	uint64_t *addr;
-
-	addr = arg;
-	*addr = segs[0].ds_addr;
-}
-#else
 static void
-mfi_addr32_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+mfi_addr_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
 {
-	uint32_t *addr;
+	bus_addr_t *addr;
 
 	addr = arg;
 	*addr = segs[0].ds_addr;
 }
-#endif
 
 int
 mfi_attach(struct mfi_softc *sc)
@@ -376,14 +349,20 @@ mfi_attach(struct mfi_softc *sc)
 	uint32_t status;
 	int error, commsz, framessz, sensesz;
 	int frames, unit, max_fw_sge;
-	u_int irq_flags;
+	uint32_t tb_mem_size = 0;
 
-	device_printf(sc->mfi_dev, "Megaraid SAS driver Ver 3.981\n");
+	if(sc == NULL)
+		return EINVAL;
+
+	device_printf(sc->mfi_dev, "Megaraid SAS driver Ver %s\n",
+	    MEGASAS_VERSION);
 
 	lockinit(&sc->mfi_io_lock, "MFI I/O lock", 0, LK_CANRECURSE);
 	lockinit(&sc->mfi_config_lock, "MFI config", 0, LK_CANRECURSE);
 	TAILQ_INIT(&sc->mfi_ld_tqh);
 	TAILQ_INIT(&sc->mfi_syspd_tqh);
+	TAILQ_INIT(&sc->mfi_evt_queue);
+	TASK_INIT(&sc->mfi_evt_task, 0, mfi_handle_evt, sc);
 	TAILQ_INIT(&sc->mfi_aen_pids);
 	TAILQ_INIT(&sc->mfi_cam_ccbq);
 
@@ -392,11 +371,27 @@ mfi_attach(struct mfi_softc *sc)
 	mfi_initq_busy(sc);
 	mfi_initq_bio(sc);
 
+	//atomic_set(&sc->fw_reset_no_pci_access, 0);
+	sc->adpreset = 0;
+	sc->last_seq_num = 0;
+	sc->disableOnlineCtrlReset = 1;
+	sc->issuepend_done = 1;
+	sc->hw_crit_error = 0;
+
 	if (sc->mfi_flags & MFI_FLAGS_1064R) {
 		sc->mfi_enable_intr = mfi_enable_intr_xscale;
 		sc->mfi_read_fw_status = mfi_read_fw_status_xscale;
 		sc->mfi_check_clear_intr = mfi_check_clear_intr_xscale;
 		sc->mfi_issue_cmd = mfi_issue_cmd_xscale;
+	} else if(sc->mfi_flags & MFI_FLAGS_TBOLT) {
+		sc->mfi_enable_intr = mfi_tbolt_enable_intr_ppc;
+		sc->mfi_disable_intr = mfi_tbolt_disable_intr_ppc;
+		sc->mfi_read_fw_status = mfi_tbolt_read_fw_status_ppc;
+		sc->mfi_check_clear_intr = mfi_tbolt_check_clear_intr_ppc;
+		sc->mfi_issue_cmd = mfi_tbolt_issue_cmd_ppc;
+		sc->mfi_adp_reset = mfi_tbolt_adp_reset;
+		sc->mfi_tbolt = 1;
+		TAILQ_INIT(&sc->mfi_cmd_tbolt_tqh);
 	} else {
 		sc->mfi_enable_intr =  mfi_enable_intr_ppc;
 		sc->mfi_read_fw_status = mfi_read_fw_status_ppc;
@@ -412,6 +407,30 @@ mfi_attach(struct mfi_softc *sc)
 		return (ENXIO);
 	}
 
+	//Start: LSIP200113393
+	if (bus_dma_tag_create( sc->mfi_parent_dmat,	/* parent */
+				1, 0,			/* algnmnt, boundary */
+				BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+				BUS_SPACE_MAXADDR,	/* highaddr */
+				NULL, NULL,		/* filter, filterarg */
+				MEGASAS_MAX_NAME*sizeof(bus_addr_t),			/* maxsize */
+				1,			/* msegments */
+				MEGASAS_MAX_NAME*sizeof(bus_addr_t),			/* maxsegsize */
+				0,			/* flags */
+				&sc->verbuf_h_dmat)) {
+		device_printf(sc->mfi_dev, "Cannot allocate verbuf_h_dmat DMA tag\n");
+		return (ENOMEM);
+	}
+	if (bus_dmamem_alloc(sc->verbuf_h_dmat, (void **)&sc->verbuf,
+	    BUS_DMA_NOWAIT, &sc->verbuf_h_dmamap)) {
+		device_printf(sc->mfi_dev, "Cannot allocate verbuf_h_dmamap memory\n");
+		return (ENOMEM);
+	}
+	bzero(sc->verbuf, MEGASAS_MAX_NAME*sizeof(bus_addr_t));
+	bus_dmamap_load(sc->verbuf_h_dmat, sc->verbuf_h_dmamap,
+	    sc->verbuf, MEGASAS_MAX_NAME*sizeof(bus_addr_t), mfi_addr_cb, &sc->verbuf_h_busaddr, 0);
+	//End: LSIP200113393
+
 	/*
 	 * Get information needed for sizing the contiguous memory for the
 	 * frame pool.  Size down the sgl parameter since we know that
@@ -424,6 +443,91 @@ mfi_attach(struct mfi_softc *sc)
 	max_fw_sge = (status & MFI_FWSTATE_MAXSGL_MASK) >> 16;
 	sc->mfi_max_sge = min(max_fw_sge, ((MFI_MAXPHYS / PAGE_SIZE) + 1));
 
+	/* ThunderBolt Support get the contiguous memory */
+
+	if(sc->mfi_flags & MFI_FLAGS_TBOLT) {
+		mfi_tbolt_init_globals(sc);
+		device_printf(sc->mfi_dev,"MaxCmd = %x MaxSgl = %x state = %x \n",
+		    sc->mfi_max_fw_cmds, sc->mfi_max_sge, status);
+		tb_mem_size = mfi_tbolt_get_memory_requirement(sc);
+
+		if (bus_dma_tag_create( sc->mfi_parent_dmat,	/* parent */
+				1, 0,			/* algnmnt, boundary */
+				BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+				BUS_SPACE_MAXADDR,	/* highaddr */
+				NULL, NULL,		/* filter, filterarg */
+				tb_mem_size,			/* maxsize */
+				1,			/* msegments */
+				tb_mem_size,			/* maxsegsize */
+				0,			/* flags */
+				&sc->mfi_tb_dmat)) {
+			device_printf(sc->mfi_dev, "Cannot allocate comms DMA tag\n");
+			return (ENOMEM);
+		}
+		if (bus_dmamem_alloc(sc->mfi_tb_dmat, (void **)&sc->request_message_pool,
+		BUS_DMA_NOWAIT, &sc->mfi_tb_dmamap)) {
+			device_printf(sc->mfi_dev, "Cannot allocate comms memory\n");
+			return (ENOMEM);
+		}
+		bzero(sc->request_message_pool, tb_mem_size);
+		bus_dmamap_load(sc->mfi_tb_dmat, sc->mfi_tb_dmamap,
+		sc->request_message_pool, tb_mem_size, mfi_addr_cb, &sc->mfi_tb_busaddr, 0);
+
+		/* For ThunderBolt memory init */
+		if (bus_dma_tag_create( sc->mfi_parent_dmat,	/* parent */
+				0x100, 0,			/* algnmnt, boundary */
+				BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+				BUS_SPACE_MAXADDR,	/* highaddr */
+				NULL, NULL,			/* filter, filterarg */
+				MFI_FRAME_SIZE,		/* maxsize */
+				1,					/* msegments */
+				MFI_FRAME_SIZE,		/* maxsegsize */
+				0,					/* flags */
+				&sc->mfi_tb_init_dmat)) {
+		device_printf(sc->mfi_dev, "Cannot allocate init DMA tag\n");
+		return (ENOMEM);
+		}
+		if (bus_dmamem_alloc(sc->mfi_tb_init_dmat, (void **)&sc->mfi_tb_init,
+		    BUS_DMA_NOWAIT, &sc->mfi_tb_init_dmamap)) {
+			device_printf(sc->mfi_dev, "Cannot allocate init memory\n");
+			return (ENOMEM);
+		}
+		bzero(sc->mfi_tb_init, MFI_FRAME_SIZE);
+		bus_dmamap_load(sc->mfi_tb_init_dmat, sc->mfi_tb_init_dmamap,
+		sc->mfi_tb_init, MFI_FRAME_SIZE, mfi_addr_cb, &sc->mfi_tb_init_busaddr, 0);
+		if(mfi_tbolt_init_desc_pool(sc, sc->request_message_pool, tb_mem_size)) {
+			device_printf(sc->mfi_dev,"Thunderbolt pool preparation error\n");
+			return 0;
+		}
+
+		/*
+		  Allocate DMA memory mapping for MPI2 IOC Init descriptor,
+		  we are taking it diffrent from what we have allocated for Request
+		  and reply descriptors to avoid confusion later
+		*/
+		tb_mem_size = sizeof(struct MPI2_IOC_INIT_REQUEST);
+		if (bus_dma_tag_create( sc->mfi_parent_dmat,	/* parent */
+				1, 0,			/* algnmnt, boundary */
+				BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+				BUS_SPACE_MAXADDR,	/* highaddr */
+				NULL, NULL,		/* filter, filterarg */
+				tb_mem_size,			/* maxsize */
+				1,			/* msegments */
+				tb_mem_size,			/* maxsegsize */
+				0,			/* flags */
+				&sc->mfi_tb_ioc_init_dmat)) {
+			device_printf(sc->mfi_dev, "Cannot allocate comms DMA tag\n");
+			return (ENOMEM);
+		}
+		if (bus_dmamem_alloc(sc->mfi_tb_ioc_init_dmat, (void **)&sc->mfi_tb_ioc_init_desc,
+		    BUS_DMA_NOWAIT, &sc->mfi_tb_ioc_init_dmamap)) {
+			device_printf(sc->mfi_dev, "Cannot allocate comms memory\n");
+			return (ENOMEM);
+		}
+		bzero(sc->mfi_tb_ioc_init_desc, tb_mem_size);
+		bus_dmamap_load(sc->mfi_tb_ioc_init_dmat, sc->mfi_tb_ioc_init_dmamap,
+		sc->mfi_tb_ioc_init_desc, tb_mem_size, mfi_addr_cb, &sc->mfi_tb_ioc_init_busaddr, 0);
+	}
 	/*
 	 * Create the dma tag for data buffers.  Used both for block I/O
 	 * and for various internal data queries.
@@ -469,14 +573,8 @@ mfi_attach(struct mfi_softc *sc)
 		return (ENOMEM);
 	}
 	bzero(sc->mfi_comms, commsz);
-#if defined(__x86_64__)
-	bus_dmamap_load(sc->mfi_comms_dmat, sc->mfi_comms_dmamap,
-	    sc->mfi_comms, commsz, mfi_addr64_cb, &sc->mfi_comms_busaddr, 0);
-#else
 	bus_dmamap_load(sc->mfi_comms_dmat, sc->mfi_comms_dmamap,
-	    sc->mfi_comms, commsz, mfi_addr32_cb, &sc->mfi_comms_busaddr, 0);
-#endif
-
+	    sc->mfi_comms, commsz, mfi_addr_cb, &sc->mfi_comms_busaddr, 0);
 	/*
 	 * Allocate DMA memory for the command frames.  Keep them in the
 	 * lower 4GB for efficiency.  Calculate the size of the commands at
@@ -517,14 +615,8 @@ mfi_attach(struct mfi_softc *sc)
 		return (ENOMEM);
 	}
 	bzero(sc->mfi_frames, framessz);
-#if defined(__x86_64__)
-	bus_dmamap_load(sc->mfi_frames_dmat, sc->mfi_frames_dmamap,
-	    sc->mfi_frames, framessz, mfi_addr64_cb, &sc->mfi_frames_busaddr,0);
-#else
 	bus_dmamap_load(sc->mfi_frames_dmat, sc->mfi_frames_dmamap,
-	    sc->mfi_frames, framessz, mfi_addr32_cb, &sc->mfi_frames_busaddr,0);
-#endif
-
+	    sc->mfi_frames, framessz, mfi_addr_cb, &sc->mfi_frames_busaddr,0);
 	/*
 	 * Allocate DMA memory for the frame sense data.  Keep them in the
 	 * lower 4GB for efficiency
@@ -548,47 +640,49 @@ mfi_attach(struct mfi_softc *sc)
 		device_printf(sc->mfi_dev, "Cannot allocate sense memory\n");
 		return (ENOMEM);
 	}
-#if defined(__x86_64__)
-	bus_dmamap_load(sc->mfi_sense_dmat, sc->mfi_sense_dmamap,
-	    sc->mfi_sense, sensesz, mfi_addr64_cb, &sc->mfi_sense_busaddr, 0);
-#else
 	bus_dmamap_load(sc->mfi_sense_dmat, sc->mfi_sense_dmamap,
-	    sc->mfi_sense, sensesz, mfi_addr32_cb, &sc->mfi_sense_busaddr, 0);
-#endif
-
+	    sc->mfi_sense, sensesz, mfi_addr_cb, &sc->mfi_sense_busaddr, 0);
 	if ((error = mfi_alloc_commands(sc)) != 0)
 		return (error);
 
-	if ((error = mfi_comms_init(sc)) != 0)
-		return (error);
+	/*
+	 * Before moving the FW to operational state, check whether
+	 * hostmemory is required by the FW or not
+	 */
 
-	if ((error = mfi_get_controller_info(sc)) != 0)
-		return (error);
+	/* ThunderBolt MFI_IOC2 INIT */
+	if(sc->mfi_flags & MFI_FLAGS_TBOLT)
+	{
+		sc->mfi_disable_intr(sc);
+		if((error = mfi_tbolt_init_MFI_queue(sc)) != 0)
+		{
+			device_printf(sc->mfi_dev,"TB Init has failed with error %d\n",error);
+			return error;
+		}
 
-	lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
-	if ((error = mfi_aen_setup(sc, 0), 0) != 0) {
-		lockmgr(&sc->mfi_io_lock, LK_RELEASE);
-		return (error);
-	}
-	lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+		if((error = mfi_tbolt_alloc_cmd(sc)) != 0)
+			return error;
+		if (bus_setup_intr(sc->mfi_dev, sc->mfi_irq, INTR_MPSAFE,
+			mfi_intr_tbolt, sc, &sc->mfi_intr, NULL)) {
+			device_printf(sc->mfi_dev, "Cannot set up interrupt\n");
+			return (EINVAL);
+		}
+		sc->mfi_enable_intr(sc);
+		sc->map_id = 0;
+	} else {
+		if ((error = mfi_comms_init(sc)) != 0)
+			return (error);
 
-	/*
-	 * Set up the interrupt handler.  XXX This should happen in
-	 * mfi_pci.c
-	 */
-	sc->mfi_irq_rid = 0;
-	sc->mfi_irq_type = pci_alloc_1intr(sc->mfi_dev, mfi_msi_enable,
-	    &sc->mfi_irq_rid, &irq_flags);
-	if ((sc->mfi_irq = bus_alloc_resource_any(sc->mfi_dev, SYS_RES_IRQ,
-	    &sc->mfi_irq_rid, irq_flags)) == NULL) {
-		device_printf(sc->mfi_dev, "Cannot allocate interrupt\n");
-		return (EINVAL);
-	}
-	if (bus_setup_intr(sc->mfi_dev, sc->mfi_irq, INTR_MPSAFE,
-	    mfi_intr, sc, &sc->mfi_intr, NULL)) {
-		device_printf(sc->mfi_dev, "Cannot set up interrupt\n");
-		return (EINVAL);
+		if (bus_setup_intr(sc->mfi_dev, sc->mfi_irq, INTR_MPSAFE,
+			mfi_intr, sc, &sc->mfi_intr, NULL)) {
+			device_printf(sc->mfi_dev, "Cannot set up interrupt\n");
+			return (EINVAL);
+		}
+		sc->mfi_enable_intr(sc);
 	}
+	if ((error = mfi_get_controller_info(sc)) != 0)
+		return (error);
+	sc->disableOnlineCtrlReset = 0;
 
 	/* Register a config hook to probe the bus for arrays */
 	sc->mfi_ich.ich_func = mfi_startup;
@@ -598,6 +692,10 @@ mfi_attach(struct mfi_softc *sc)
 		    "hook\n");
 		return (EINVAL);
 	}
+	if ((error = mfi_aen_setup(sc, 0), 0) != 0) {
+		lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+		return (error);
+	}
 
 	/*
 	 * Register a shutdown handler.
@@ -677,8 +775,11 @@ mfi_alloc_commands(struct mfi_softc *sc)
 		cm->cm_sc = sc;
 		cm->cm_index = i;
 		if (bus_dmamap_create(sc->mfi_buffer_dmat, 0,
-		    &cm->cm_dmamap) == 0)
+		    &cm->cm_dmamap) == 0) {
+			lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
 			mfi_release_command(cm);
+			lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+		}
 		else
 			break;
 		sc->mfi_total_cmds++;
@@ -693,6 +794,8 @@ mfi_release_command(struct mfi_command *cm)
 	struct mfi_frame_header *hdr;
 	uint32_t *hdr_data;
 
+	KKASSERT(lockstatus(&cm->cm_sc->mfi_io_lock, curthread) != 0);
+
 	/*
 	 * Zero out the important fields of the frame, but make sure the
 	 * context field is preserved.  For efficiency, handle the fields
@@ -717,6 +820,7 @@ mfi_release_command(struct mfi_command *cm)
 	cm->cm_data = NULL;
 	cm->cm_sg = 0;
 	cm->cm_total_frame_size = 0;
+	cm->retry_for_fw_reset = 0;
 
 	mfi_enqueue_free(cm);
 }
@@ -853,9 +957,10 @@ mfi_get_controller_info(struct mfi_softc *sc)
 	    BUS_DMASYNC_POSTREAD);
 	bus_dmamap_unload(sc->mfi_buffer_dmat, cm->cm_dmamap);
 
-	max_sectors_1 = (1 << ci->stripe_sz_ops.min) * ci->max_strips_per_io;
+	max_sectors_1 = (1 << ci->stripe_sz_ops.max) * ci->max_strips_per_io;
 	max_sectors_2 = ci->max_request_size;
 	sc->mfi_max_io = min(max_sectors_1, max_sectors_2);
+	sc->disableOnlineCtrlReset = ci->properties.OnOffProperties.disableOnlineCtrlReset;
 
 out:
 	if (ci)
@@ -872,6 +977,7 @@ mfi_get_log_state(struct mfi_softc *sc, struct mfi_evt_log_state **log_state)
 	struct mfi_command *cm = NULL;
 	int error;
 
+	lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
 	error = mfi_dcmd_command(sc, &cm, MFI_DCMD_CTRL_EVENT_GETINFO,
 	    (void **)log_state, sizeof(**log_state));
 	if (error)
@@ -890,11 +996,12 @@ mfi_get_log_state(struct mfi_softc *sc, struct mfi_evt_log_state **log_state)
 out:
 	if (cm)
 		mfi_release_command(cm);
+	lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 
 	return (error);
 }
 
-static int
+int
 mfi_aen_setup(struct mfi_softc *sc, uint32_t seq_start)
 {
 	struct mfi_evt_log_state *log_state = NULL;
@@ -930,7 +1037,7 @@ mfi_aen_setup(struct mfi_softc *sc, uint32_t seq_start)
 	return 0;
 }
 
-static int
+int
 mfi_wait_command(struct mfi_softc *sc, struct mfi_command *cm)
 {
 
@@ -979,8 +1086,7 @@ mfi_free(struct mfi_softc *sc)
 	if (sc->mfi_irq != NULL)
 		bus_release_resource(sc->mfi_dev, SYS_RES_IRQ, sc->mfi_irq_rid,
 		    sc->mfi_irq);
-	if (sc->mfi_irq_type == PCI_INTR_TYPE_MSI)
-		pci_release_msi(sc->mfi_dev);
+
 	if (sc->mfi_sense_busaddr != 0)
 		bus_dmamap_unload(sc->mfi_sense_dmat, sc->mfi_sense_dmamap);
 	if (sc->mfi_sense != NULL)
@@ -1005,6 +1111,69 @@ mfi_free(struct mfi_softc *sc)
 	if (sc->mfi_comms_dmat != NULL)
 		bus_dma_tag_destroy(sc->mfi_comms_dmat);
 
+	/* ThunderBolt contiguous memory free here */
+
+	if(sc->mfi_flags & MFI_FLAGS_TBOLT)
+	{
+		if (sc->mfi_tb_busaddr != 0)
+			bus_dmamap_unload(sc->mfi_tb_dmat, sc->mfi_tb_dmamap);
+		if (sc->request_message_pool != NULL)
+			bus_dmamem_free(sc->mfi_tb_dmat, sc->request_message_pool,
+			    sc->mfi_tb_dmamap);
+		if (sc->mfi_tb_dmat != NULL)
+			bus_dma_tag_destroy(sc->mfi_tb_dmat);
+
+		/* Version buffer memory free */
+		// Start LSIP200113393
+		if (sc->verbuf_h_busaddr != 0)
+			bus_dmamap_unload(sc->verbuf_h_dmat, sc->verbuf_h_dmamap);
+		if (sc->verbuf != NULL)
+			bus_dmamem_free(sc->verbuf_h_dmat, sc->verbuf,
+			    sc->verbuf_h_dmamap);
+		if (sc->verbuf_h_dmat != NULL)
+			bus_dma_tag_destroy(sc->verbuf_h_dmat);
+
+		// End LSIP200113393
+		/* ThunderBolt INIT pcaket memory Free */
+		if (sc->mfi_tb_init_busaddr != 0)
+			bus_dmamap_unload(sc->mfi_tb_init_dmat, sc->mfi_tb_init_dmamap);
+		if (sc->mfi_tb_init != NULL)
+			bus_dmamem_free(sc->mfi_tb_init_dmat, sc->mfi_tb_init,
+			    sc->mfi_tb_init_dmamap);
+		if (sc->mfi_tb_init_dmat != NULL)
+			bus_dma_tag_destroy(sc->mfi_tb_init_dmat);
+
+		/* ThunderBolt IOC Init Desc memory free here */
+
+		if (sc->mfi_tb_ioc_init_busaddr != 0)
+			bus_dmamap_unload(sc->mfi_tb_ioc_init_dmat, sc->mfi_tb_ioc_init_dmamap);
+		if (sc->mfi_tb_ioc_init_desc != NULL)
+			bus_dmamem_free(sc->mfi_tb_ioc_init_dmat, sc->mfi_tb_ioc_init_desc, sc->mfi_tb_ioc_init_dmamap);
+		if (sc->mfi_tb_ioc_init_dmat != NULL)
+			bus_dma_tag_destroy(sc->mfi_tb_ioc_init_dmat);
+
+		for(int i=0; i < sc->mfi_max_fw_cmds; i++)
+		{
+			if (sc->mfi_cmd_pool_tbolt != NULL)
+			{
+				if (sc->mfi_cmd_pool_tbolt[i] != NULL)
+				{
+					kfree(sc->mfi_cmd_pool_tbolt[i], M_MFIBUF);
+					sc->mfi_cmd_pool_tbolt[i] = NULL;
+				}
+			}
+		}
+		if (sc->mfi_cmd_pool_tbolt != NULL)
+		{
+			kfree(sc->mfi_cmd_pool_tbolt, M_MFIBUF);
+			sc->mfi_cmd_pool_tbolt = NULL;
+		}
+		if (sc->request_desc_pool != NULL)
+		{
+			kfree(sc->request_desc_pool, M_MFIBUF);
+			sc->request_desc_pool = NULL;
+		}
+	}
 	if (sc->mfi_buffer_dmat != NULL)
 		bus_dma_tag_destroy(sc->mfi_buffer_dmat);
 	if (sc->mfi_parent_dmat != NULL)
@@ -1033,7 +1202,7 @@ mfi_startup(void *arg)
 
 	config_intrhook_disestablish(&sc->mfi_ich);
 
-	sc->mfi_enable_intr(sc);
+	//sc->mfi_enable_intr(sc);
 	lockmgr(&sc->mfi_config_lock, LK_EXCLUSIVE);
 	lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
 	mfi_ldprobe(sc);
@@ -1055,12 +1224,7 @@ mfi_intr(void *arg)
 	if (sc->mfi_check_clear_intr(sc))
 		return;
 
-	/*
-	 * Do a dummy read to flush the interrupt ACK that we just performed,
-	 * ensuring that everything is really, truly consistent.
-	 */
-	(void)sc->mfi_read_fw_status(sc);
-
+restart:
 	pi = sc->mfi_comms->hw_pi;
 	ci = sc->mfi_comms->hw_ci;
 	lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
@@ -1085,6 +1249,14 @@ mfi_intr(void *arg)
 	mfi_startio(sc);
 	lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 
+	/*
+	 * Dummy read to flush the bus; this ensures that the indexes are up
+	 * to date.  Restart processing if more commands have come it.
+	 */
+	(void)sc->mfi_read_fw_status(sc);
+	if (pi != sc->mfi_comms->hw_pi)
+		goto restart;
+
 	return;
 }
 
@@ -1105,6 +1277,9 @@ mfi_shutdown(struct mfi_softc *sc)
 	if (sc->mfi_aen_cm != NULL)
 		mfi_abort(sc, sc->mfi_aen_cm);
 
+	if (sc->map_update_cmd != NULL)
+		mfi_abort(sc, sc->map_update_cmd);
+
 	dcmd = &cm->cm_frame->dcmd;
 	dcmd->header.flags = MFI_FRAME_DIR_NONE;
 	cm->cm_flags = MFI_CMD_POLLED;
@@ -1115,6 +1290,7 @@ mfi_shutdown(struct mfi_softc *sc)
 	}
 
 	mfi_release_command(cm);
+	sc->shutdown_issued = 1;
 	lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 	return (error);
 }
@@ -1153,15 +1329,13 @@ mfi_syspdprobe(struct mfi_softc *sc)
 		    hdr->cmd_status);
 		goto out;
 	}
+	/* Get each PD and add it to the system */
 	for (i = 0; i < pdlist->count; i++) {
 		if (pdlist->addr[i].device_id == pdlist->addr[i].encl_device_id)
 			goto skip_sys_pd_add;
-		/* Get each PD and add it to the system */
-		if (!TAILQ_EMPTY(&sc->mfi_syspd_tqh)) {
-			TAILQ_FOREACH(syspd, &sc->mfi_syspd_tqh,pd_link) {
-				if (syspd->pd_id == pdlist->addr[i].device_id)
-					goto skip_sys_pd_add;
-			}
+		TAILQ_FOREACH(syspd, &sc->mfi_syspd_tqh, pd_link) {
+			if (syspd->pd_id == pdlist->addr[i].device_id)
+				goto skip_sys_pd_add;
 		}
 		mfi_add_sys_pd(sc,pdlist->addr[i].device_id);
 skip_sys_pd_add:
@@ -1280,12 +1454,114 @@ format_class(int8_t class)
 }
 
 static void
-mfi_decode_evt(struct mfi_softc *sc, struct mfi_evt_detail *detail)
+mfi_decode_evt(struct mfi_softc *sc, struct mfi_evt_detail *detail,
+    uint8_t probe_sys_pd)
 {
+	struct mfi_system_pd *syspd = NULL;
 
 	device_printf(sc->mfi_dev, "%d (%s/0x%04x/%s) - %s\n", detail->seq,
 	    format_timestamp(detail->time), detail->evt_class.members.locale,
 	    format_class(detail->evt_class.members.evt_class), detail->description);
+	switch (detail->arg_type) {
+	case MR_EVT_ARGS_NONE:
+#define MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED 0x0152
+		if (detail->code == MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED) {
+		    device_printf(sc->mfi_dev,"HostBus scan raised\n");
+		    if (probe_sys_pd) {
+			/* Probe for new SYSPD's and Delete invalid SYSPD's */
+			lockmgr(&sc->mfi_config_lock, LK_EXCLUSIVE);
+			lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
+			mfi_syspdprobe(sc);
+			lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+			lockmgr(&sc->mfi_config_lock, LK_RELEASE);
+		    }
+		}
+		break;
+	case MR_EVT_ARGS_LD_STATE:
+		/* During load time driver reads all the events starting from the one that
+		 * has been logged after shutdown. Avoid these old events.
+		 */
+		if (detail->args.ld_state.new_state == MFI_LD_STATE_OFFLINE ) {
+			/* Remove the LD */
+			struct mfi_disk *ld;
+			TAILQ_FOREACH(ld, &sc->mfi_ld_tqh, ld_link) {
+				if (ld->ld_id == detail->args.ld_state.ld.target_id)
+					break;
+			}
+			/*
+			Fix: for kernel panics when SSCD is removed
+			KASSERT(ld != NULL, ("volume dissappeared"));
+			*/
+			if(ld != NULL) {
+				get_mplock();
+				device_delete_child(sc->mfi_dev, ld->ld_dev);
+				rel_mplock();
+			}
+		}
+		break;
+	case MR_EVT_ARGS_PD:
+#define MR_EVT_PD_REMOVED  0x0070
+#define MR_EVT_PD_INSERTED 0x005b
+		if (detail->code == MR_EVT_PD_REMOVED) {
+		    if (probe_sys_pd) {
+			/* If the removed device is a SYSPD then delete it */
+			TAILQ_FOREACH(syspd,&sc->mfi_syspd_tqh,pd_link) {
+				if (syspd->pd_id == detail->args.pd.device_id) {
+					get_mplock();
+					device_delete_child(sc->mfi_dev,syspd->pd_dev);
+					rel_mplock();
+					break;
+				}
+			}
+		    }
+		}
+		if (detail->code == MR_EVT_PD_INSERTED) {
+		    if (probe_sys_pd) {
+			/* Probe for new SYSPD's */
+			lockmgr(&sc->mfi_config_lock, LK_EXCLUSIVE);
+			lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
+			mfi_syspdprobe(sc);
+			lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+			lockmgr(&sc->mfi_config_lock, LK_RELEASE);
+		    }
+		}
+		break;
+	}
+}
+
+static void
+mfi_queue_evt(struct mfi_softc *sc, struct mfi_evt_detail *detail,
+    uint8_t probe_sys_pd)
+{
+	struct mfi_evt_queue_elm *elm;
+
+	KKASSERT(lockstatus(&sc->mfi_io_lock, curthread) != 0);
+	elm = kmalloc(sizeof(*elm), M_MFIBUF, M_NOWAIT|M_ZERO);
+	if (elm == NULL)
+		return;
+	elm->probe_sys_pd = probe_sys_pd;
+	memcpy(&elm->detail, detail, sizeof(*detail));
+	TAILQ_INSERT_TAIL(&sc->mfi_evt_queue, elm, link);
+	taskqueue_enqueue(taskqueue_swi, &sc->mfi_evt_task);
+}
+
+static void
+mfi_handle_evt(void *context, int pending)
+{
+	TAILQ_HEAD(,mfi_evt_queue_elm) queue;
+	struct mfi_softc *sc;
+	struct mfi_evt_queue_elm *elm;
+
+	sc = context;
+	TAILQ_INIT(&queue);
+	lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
+	TAILQ_CONCAT(&queue, &sc->mfi_evt_queue, link);
+	lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+	while ((elm = TAILQ_FIRST(&queue)) != NULL) {
+		TAILQ_REMOVE(&queue, elm, link);
+		mfi_decode_evt(sc, &elm->detail, elm->probe_sys_pd);
+		kfree(elm, M_MFIBUF);
+	}
 }
 
 static int
@@ -1311,12 +1587,16 @@ mfi_aen_register(struct mfi_softc *sc, int seq, int locale)
 			    < current_aen.members.evt_class)
 				current_aen.members.evt_class =
 				    prior_aen.members.evt_class;
+			lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
 			mfi_abort(sc, sc->mfi_aen_cm);
+			lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 		}
 	}
 
+	lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
 	error = mfi_dcmd_command(sc, &cm, MFI_DCMD_CTRL_EVENT_WAIT,
 	    (void **)&ed, sizeof(*ed));
+	lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 	if (error) {
 		goto out;
 	}
@@ -1327,10 +1607,13 @@ mfi_aen_register(struct mfi_softc *sc, int seq, int locale)
 	cm->cm_flags = MFI_CMD_DATAIN;
 	cm->cm_complete = mfi_aen_complete;
 
+	sc->last_seq_num = seq;
 	sc->mfi_aen_cm = cm;
 
+	lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
 	mfi_enqueue_ready(cm);
 	mfi_startio(sc);
+	lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 
 out:
 	return (error);
@@ -1346,6 +1629,8 @@ mfi_aen_complete(struct mfi_command *cm)
 	int seq = 0, aborted = 0;
 
 	sc = cm->cm_sc;
+	KKASSERT(lockstatus(&sc->mfi_io_lock, curthread) != 0);
+
 	hdr = &cm->cm_frame->header;
 
 	if (sc->mfi_aen_cm == NULL)
@@ -1362,11 +1647,7 @@ mfi_aen_complete(struct mfi_command *cm)
 			KNOTE(&sc->mfi_kq.ki_note, 0);
 		}
 		detail = cm->cm_data;
-		/*
-		 * XXX If this function is too expensive or is recursive, then
-		 * events should be put onto a queue and processed later.
-		 */
-		mfi_decode_evt(sc, detail);
+		mfi_queue_evt(sc, detail, 1);
 		seq = detail->seq + 1;
 		TAILQ_FOREACH_MUTABLE(mfi_aen_entry, &sc->mfi_aen_pids, aen_link, tmp) {
 			TAILQ_REMOVE(&sc->mfi_aen_pids, mfi_aen_entry,
@@ -1385,7 +1666,9 @@ mfi_aen_complete(struct mfi_command *cm)
 
 	/* set it up again so the driver can catch more events */
 	if (!aborted) {
+		lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 		mfi_aen_setup(sc, seq);
+		lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
 	}
 }
 
@@ -1399,7 +1682,6 @@ mfi_parse_entries(struct mfi_softc *sc, int start_seq, int stop_seq)
 	struct mfi_evt_list *el;
 	union mfi_evt class_locale;
 	int error, i, seq, size;
-	uint32_t context = 0;
 
 	class_locale.members.reserved = 0;
 	class_locale.members.locale = mfi_event_locale;
@@ -1412,22 +1694,20 @@ mfi_parse_entries(struct mfi_softc *sc, int start_seq, int stop_seq)
 		return (ENOMEM);
 
 	for (seq = start_seq;;) {
+		lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
 		if ((cm = mfi_dequeue_free(sc)) == NULL) {
 			kfree(el, M_MFIBUF);
+			lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 			return (EBUSY);
 		}
 
-		/* Zero out the MFI frame */
-		context = cm->cm_frame->header.context;
-		bzero(cm->cm_frame, sizeof(union mfi_frame));
-		cm->cm_frame->header.context = context;
+		lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 
 		dcmd = &cm->cm_frame->dcmd;
 		bzero(dcmd->mbox, MFI_MBOX_SIZE);
 		dcmd->header.cmd = MFI_CMD_DCMD;
 		dcmd->header.timeout = 0;
 		dcmd->header.data_len = size;
-		dcmd->header.scsi_status = 0;
 		dcmd->opcode = MFI_DCMD_CTRL_EVENT_GET;
 		((uint32_t *)&dcmd->mbox)[0] = seq;
 		((uint32_t *)&dcmd->mbox)[1] = class_locale.word;
@@ -1437,29 +1717,38 @@ mfi_parse_entries(struct mfi_softc *sc, int start_seq, int stop_seq)
 		cm->cm_data = el;
 		cm->cm_len = size;
 
+		lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
 		if ((error = mfi_mapcmd(sc, cm)) != 0) {
 			device_printf(sc->mfi_dev,
 			    "Failed to get controller entries\n");
 			mfi_release_command(cm);
+			lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 			break;
 		}
 
+		lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 		bus_dmamap_sync(sc->mfi_buffer_dmat, cm->cm_dmamap,
 		    BUS_DMASYNC_POSTREAD);
 		bus_dmamap_unload(sc->mfi_buffer_dmat, cm->cm_dmamap);
 
 		if (dcmd->header.cmd_status == MFI_STAT_NOT_FOUND) {
+			lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
 			mfi_release_command(cm);
+			lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 			break;
 		}
 		if (dcmd->header.cmd_status != MFI_STAT_OK) {
 			device_printf(sc->mfi_dev,
 			    "Error %d fetching controller entries\n",
 			    dcmd->header.cmd_status);
+			lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
 			mfi_release_command(cm);
+			lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 			break;
 		}
+		lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
 		mfi_release_command(cm);
+		lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 
 		for (i = 0; i < el->count; i++) {
 			/*
@@ -1475,7 +1764,9 @@ mfi_parse_entries(struct mfi_softc *sc, int start_seq, int stop_seq)
 				else if (el->event[i].seq < start_seq)
 					break;
 			}
-			mfi_decode_evt(sc, &el->event[i]);
+			lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
+			mfi_queue_evt(sc, &el->event[i], 0);
+			lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 		}
 		seq = el->event[el->count - 1].seq + 1;
 	}
@@ -1711,13 +2002,8 @@ mfi_build_syspdio(struct mfi_softc *sc, struct bio *bio)
 	pass->header.sense_len = MFI_SENSE_LEN;
 	pass->header.data_len = bp->b_bcount;
 	pass->header.cdb_len = 10;
-#if defined(__x86_64__)
-	pass->sense_addr_lo = (cm->cm_sense_busaddr & 0xFFFFFFFF);
-	pass->sense_addr_hi = (cm->cm_sense_busaddr & 0xFFFFFFFF00000000) >> 32;
-#else
-	pass->sense_addr_lo = cm->cm_sense_busaddr;
-	pass->sense_addr_hi = 0;
-#endif
+	pass->sense_addr_lo = (uint32_t)cm->cm_sense_busaddr;
+	pass->sense_addr_hi = (uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32);
 	cm->cm_complete = mfi_bio_complete;
 	cm->cm_private = bio;
 	cm->cm_data = bp->b_data;
@@ -1769,13 +2055,8 @@ mfi_build_ldio(struct mfi_softc *sc,struct bio *bio)
 	io->header.scsi_status = 0;
 	io->header.sense_len = MFI_SENSE_LEN;
 	io->header.data_len = blkcount;
-#if defined(__x86_64__)
-	io->sense_addr_lo = (cm->cm_sense_busaddr & 0xFFFFFFFF);
-	io->sense_addr_hi = (cm->cm_sense_busaddr & 0xFFFFFFFF00000000) >> 32;
-#else
-	io->sense_addr_lo = cm->cm_sense_busaddr;
-	io->sense_addr_hi = 0;
-#endif
+	io->sense_addr_lo = (uint32_t)cm->cm_sense_busaddr;
+	io->sense_addr_hi = (uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32);
 	io->lba_hi = ((bio->bio_offset / MFI_SECTOR_LEN) & 0xffffffff00000000) >> 32;
 	io->lba_lo = (bio->bio_offset / MFI_SECTOR_LEN) & 0xffffffff;
 	cm->cm_complete = mfi_bio_complete;
@@ -1850,14 +2131,14 @@ mfi_startio(struct mfi_softc *sc)
 	}
 }
 
-static int
+int
 mfi_mapcmd(struct mfi_softc *sc, struct mfi_command *cm)
 {
 	int error, polled;
 
 	KKASSERT(lockstatus(&sc->mfi_io_lock, curthread) != 0);
 
-	if (cm->cm_data != NULL) {
+	if ((cm->cm_data != NULL) && (cm->cm_frame->header.cmd != MFI_CMD_STP)) {
 		polled = (cm->cm_flags & MFI_CMD_POLLED) ? BUS_DMA_NOWAIT : 0;
 		error = bus_dmamap_load(sc->mfi_buffer_dmat, cm->cm_dmamap,
 		    cm->cm_data, cm->cm_len, mfi_data_cb, cm, polled);
@@ -1866,7 +2147,10 @@ mfi_mapcmd(struct mfi_softc *sc, struct mfi_command *cm)
 			return (0);
 		}
 	} else {
-		error = mfi_send_frame(sc, cm);
+		if (sc->MFA_enabled)
+			error = mfi_tbolt_send_frame(sc, cm);
+		else
+			error = mfi_send_frame(sc, cm);
 	}
 
 	return (error);
@@ -1880,8 +2164,7 @@ mfi_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
 	union mfi_sgl *sgl;
 	struct mfi_softc *sc;
 	int i, j, first, dir;
-	int sgl_mapped = 0;
-	int sge_size = 0;
+	int sge_size;
 
 	cm = (struct mfi_command *)arg;
 	sc = cm->cm_sc;
@@ -1911,10 +2194,9 @@ mfi_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
 			sgl->sg_skinny[i].flag = 0;
 		}
 		hdr->flags |= MFI_FRAME_IEEE_SGL | MFI_FRAME_SGL64;
-		sgl_mapped = 1;
 		sge_size = sizeof(struct mfi_sg_skinny);
-	}
-	if (!sgl_mapped) {
+		hdr->sg_count = nsegs;
+	} else {
 		j = 0;
 		if (cm->cm_frame->header.cmd == MFI_CMD_STP) {
 			first = cm->cm_stp_len;
@@ -1933,7 +2215,6 @@ mfi_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
 				sgl->sg32[j++].len = segs[i].ds_len - first;
 				first = 0;
 			}
-			sge_size = sizeof(struct mfi_sg32);
 		} else {
 			for (i = 0; i < nsegs; i++) {
 				sgl->sg64[j].addr = segs[i].ds_addr + first;
@@ -1941,11 +2222,10 @@ mfi_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
 				first = 0;
 			}
 			hdr->flags |= MFI_FRAME_SGL64;
-			sge_size = sizeof(struct mfi_sg64);
 		}
 		hdr->sg_count = j;
-	} else
-		hdr->sg_count = nsegs;
+		sge_size = sc->mfi_sge_size;
+	}
 
 	dir = 0;
 	if (cm->cm_flags & MFI_CMD_DATAIN) {
@@ -1956,8 +2236,6 @@ mfi_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
 		dir |= BUS_DMASYNC_PREWRITE;
 		hdr->flags |= MFI_FRAME_DIR_WRITE;
 	}
-	if (cm->cm_frame->header.cmd == MFI_CMD_STP)
-		dir |= BUS_DMASYNC_PREWRITE;
 	bus_dmamap_sync(sc->mfi_buffer_dmat, cm->cm_dmamap, dir);
 	cm->cm_flags |= MFI_CMD_MAPPED;
 
@@ -1967,10 +2245,13 @@ mfi_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
 	 * least 1 frame, so don't compensate for the modulo of the
 	 * following division.
 	 */
-	cm->cm_total_frame_size += (sge_size * nsegs);
+	cm->cm_total_frame_size += (sc->mfi_sge_size * nsegs);
 	cm->cm_extra_frames = (cm->cm_total_frame_size - 1) / MFI_FRAME_SIZE;
 
-	mfi_send_frame(sc, cm);
+	if (sc->MFA_enabled)
+		mfi_tbolt_send_frame(sc, cm);
+	else
+		mfi_send_frame(sc, cm);
 }
 
 static int
@@ -2026,7 +2307,7 @@ mfi_send_frame(struct mfi_softc *sc, struct mfi_command *cm)
 	return (0);
 }
 
-static void
+void
 mfi_complete(struct mfi_softc *sc, struct mfi_command *cm)
 {
 	int dir;
@@ -2076,17 +2357,14 @@ mfi_abort(struct mfi_softc *sc, struct mfi_command *cm_abort)
 	abort->header.flags = 0;
 	abort->header.scsi_status = 0;
 	abort->abort_context = cm_abort->cm_frame->header.context;
-#if defined(__x86_64__)
-	abort->abort_mfi_addr_lo = cm_abort->cm_frame_busaddr & 0xFFFFFFFF;
-	abort->abort_mfi_addr_hi = (cm_abort->cm_frame_busaddr & 0xFFFFFFFF00000000 ) >> 32  ;
-#else
-	abort->abort_mfi_addr_lo = cm_abort->cm_frame_busaddr;
-	abort->abort_mfi_addr_hi = 0;
-#endif
+	abort->abort_mfi_addr_lo = (uint32_t)cm_abort->cm_frame_busaddr;
+	abort->abort_mfi_addr_hi =
+	    (uint32_t)((uint64_t)cm_abort->cm_frame_busaddr >> 32);
 	cm->cm_data = NULL;
 	cm->cm_flags = MFI_CMD_POLLED;
 
-	sc->mfi_aen_cm->cm_aen_abort = 1;
+	if(sc->mfi_aen_cm)
+		sc->mfi_aen_cm->cm_aen_abort = 1;
 	mfi_mapcmd(sc, cm);
 	mfi_release_command(cm);
 
@@ -2122,13 +2400,8 @@ mfi_dump_blocks(struct mfi_softc *sc, int id, uint64_t lba, void *virt, int len)
 	io->header.scsi_status = 0;
 	io->header.sense_len = MFI_SENSE_LEN;
 	io->header.data_len = (len + MFI_SECTOR_LEN - 1) / MFI_SECTOR_LEN;
-#if defined(__x86_64__)
-	io->sense_addr_lo = (cm->cm_sense_busaddr & 0xFFFFFFFF);
-	io->sense_addr_hi = (cm->cm_sense_busaddr & 0xFFFFFFFF00000000 ) >> 32;
-#else
-	io->sense_addr_lo = cm->cm_sense_busaddr;
-	io->sense_addr_hi = 0;
-#endif
+	io->sense_addr_lo = (uint32_t)cm->cm_sense_busaddr;
+	io->sense_addr_hi = (uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32);
 	io->lba_hi = (lba & 0xffffffff00000000) >> 32;
 	io->lba_lo = lba & 0xffffffff;
 	cm->cm_data = virt;
@@ -2176,13 +2449,8 @@ mfi_dump_syspd_blocks(struct mfi_softc *sc, int id, uint64_t lba, void *virt,
 	pass->header.sense_len = MFI_SENSE_LEN;
 	pass->header.data_len = len;
 	pass->header.cdb_len = 10;
-#if defined(__x86_64__)
-	pass->sense_addr_lo = (cm->cm_sense_busaddr & 0xFFFFFFFF);
-	pass->sense_addr_hi = (cm->cm_sense_busaddr & 0xFFFFFFFF00000000 ) >> 32;
-#else
-	pass->sense_addr_lo = cm->cm_sense_busaddr;
-	pass->sense_addr_hi = 0;
-#endif
+	pass->sense_addr_lo = (uint32_t)cm->cm_sense_busaddr;
+	pass->sense_addr_hi = (uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32);
 	cm->cm_data = virt;
 	cm->cm_len = len;
 	cm->cm_sg = &pass->sgl;
@@ -2306,11 +2574,9 @@ mfi_check_command_pre(struct mfi_softc *sc, struct mfi_command *cm)
 		mbox = (uint16_t *)cm->cm_frame->dcmd.mbox;
 		syspd_id = mbox[0];
 		if (mbox[2] == MFI_PD_STATE_UNCONFIGURED_GOOD) {
-			if (!TAILQ_EMPTY(&sc->mfi_syspd_tqh)) {
-				TAILQ_FOREACH(syspd, &sc->mfi_syspd_tqh, pd_link) {
-					if (syspd->pd_id == syspd_id)
-						break;
-				}
+			TAILQ_FOREACH(syspd, &sc->mfi_syspd_tqh, pd_link) {
+				if (syspd->pd_id == syspd_id)
+					break;
 			}
 		} else {
 			break;
@@ -2373,11 +2639,9 @@ mfi_check_command_post(struct mfi_softc *sc, struct mfi_command *cm)
 		mbox = (uint16_t *)cm->cm_frame->dcmd.mbox;
 		syspd_id = mbox[0];
 		if (mbox[2] == MFI_PD_STATE_UNCONFIGURED_GOOD) {
-			if (!TAILQ_EMPTY(&sc->mfi_syspd_tqh)) {
-				TAILQ_FOREACH(syspd,&sc->mfi_syspd_tqh,pd_link) {
-					if (syspd->pd_id == syspd_id)
-						break;
-				}
+			TAILQ_FOREACH(syspd,&sc->mfi_syspd_tqh,pd_link) {
+				if (syspd->pd_id == syspd_id)
+					break;
 			}
 		} else {
 			break;
@@ -2390,6 +2654,133 @@ mfi_check_command_post(struct mfi_softc *sc, struct mfi_command *cm)
 }
 
 static int
+mfi_check_for_sscd(struct mfi_softc *sc, struct mfi_command *cm)
+{
+	struct mfi_config_data *conf_data = cm->cm_data;
+	struct mfi_command *ld_cm = NULL;
+	struct mfi_ld_info *ld_info = NULL;
+	int error = 0;
+
+	if ((cm->cm_frame->dcmd.opcode == MFI_DCMD_CFG_ADD) &&
+	    (conf_data->ld[0].params.isSSCD == 1)) {
+		error = 1;
+	} else if (cm->cm_frame->dcmd.opcode == MFI_DCMD_LD_DELETE) {
+		error = mfi_dcmd_command(sc, &ld_cm, MFI_DCMD_LD_GET_INFO,
+		    (void **)&ld_info, sizeof(*ld_info));
+		if (error) {
+			device_printf(sc->mfi_dev,"Failed to allocate "
+			    "MFI_DCMD_LD_GET_INFO %d", error);
+			if (ld_info)
+				kfree(ld_info, M_MFIBUF);
+			return 0;
+		}
+		ld_cm->cm_flags = MFI_CMD_DATAIN;
+		ld_cm->cm_frame->dcmd.mbox[0]= cm->cm_frame->dcmd.mbox[0];
+		ld_cm->cm_frame->header.target_id = cm->cm_frame->dcmd.mbox[0];
+		if (mfi_wait_command(sc, ld_cm) != 0) {
+			device_printf(sc->mfi_dev, "failed to get log drv\n");
+			mfi_release_command(ld_cm);
+			kfree(ld_info, M_MFIBUF);
+			return 0;
+		}
+
+		if (ld_cm->cm_frame->header.cmd_status != MFI_STAT_OK) {
+			kfree(ld_info, M_MFIBUF);
+			mfi_release_command(ld_cm);
+			return 0;
+		} else {
+			ld_info = (struct mfi_ld_info *)ld_cm->cm_private;
+		}
+
+		if (ld_info->ld_config.params.isSSCD == 1)
+			error = 1;
+
+		mfi_release_command(ld_cm);
+		kfree(ld_info, M_MFIBUF);
+	}
+	return error;
+}
+
+static int
+mfi_stp_cmd(struct mfi_softc *sc, struct mfi_command *cm,caddr_t arg)
+{
+	uint8_t i;
+	struct mfi_ioc_packet *ioc;
+	ioc = (struct mfi_ioc_packet *)arg;
+	int sge_size, error;
+	struct megasas_sge *kern_sge;
+
+	memset(sc->kbuff_arr, 0, sizeof(sc->kbuff_arr));
+	kern_sge =(struct megasas_sge *) ((uintptr_t)cm->cm_frame + ioc->mfi_sgl_off);
+	cm->cm_frame->header.sg_count = ioc->mfi_sge_count;
+
+	if (sizeof(bus_addr_t) == 8) {
+		cm->cm_frame->header.flags |= MFI_FRAME_SGL64;
+		cm->cm_extra_frames = 2;
+		sge_size = sizeof(struct mfi_sg64);
+	} else {
+		cm->cm_extra_frames =  (cm->cm_total_frame_size - 1) / MFI_FRAME_SIZE;
+		sge_size = sizeof(struct mfi_sg32);
+	}
+
+	cm->cm_total_frame_size += (sge_size * ioc->mfi_sge_count);
+	for (i = 0; i < ioc->mfi_sge_count; i++)
+	{
+			if (bus_dma_tag_create( sc->mfi_parent_dmat,	/* parent */
+			1, 0,			/* algnmnt, boundary */
+			BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+			BUS_SPACE_MAXADDR,	/* highaddr */
+			NULL, NULL,		/* filter, filterarg */
+			ioc->mfi_sgl[i].iov_len,		/* maxsize */
+			2,			/* nsegments */
+			ioc->mfi_sgl[i].iov_len,		/* maxsegsize */
+			BUS_DMA_ALLOCNOW,			/* flags */
+			&sc->mfi_kbuff_arr_dmat[i])) {
+			device_printf(sc->mfi_dev, "Cannot allocate mfi_kbuff_arr_dmat tag\n");
+			return (ENOMEM);
+		}
+
+		if (bus_dmamem_alloc(sc->mfi_kbuff_arr_dmat[i], (void **)&sc->kbuff_arr[i],
+			 BUS_DMA_NOWAIT, &sc->mfi_kbuff_arr_dmamap[i])) {
+			device_printf(sc->mfi_dev, "Cannot allocate mfi_kbuff_arr_dmamap memory\n");
+			return (ENOMEM);
+		}
+
+		bus_dmamap_load(sc->mfi_kbuff_arr_dmat[i], sc->mfi_kbuff_arr_dmamap[i],
+		sc->kbuff_arr[i], ioc->mfi_sgl[i].iov_len, mfi_addr_cb, &sc->mfi_kbuff_arr_busaddr[i], 0);
+
+		if (!sc->kbuff_arr[i]) {
+			device_printf(sc->mfi_dev,"Could not allocate memory for kbuff_arr"
+				" info\n");
+			return -1;
+		}
+		kern_sge[i].phys_addr = sc->mfi_kbuff_arr_busaddr[i];
+		kern_sge[i].length = ioc->mfi_sgl[i].iov_len;
+
+		if (sizeof(bus_addr_t) == 8) {
+			cm->cm_frame->stp.sgl.sg64[i].addr = kern_sge[i].phys_addr;
+			cm->cm_frame->stp.sgl.sg64[i].len = ioc->mfi_sgl[i].iov_len;
+		} else {
+			cm->cm_frame->stp.sgl.sg32[i].len = kern_sge[i].phys_addr;
+			cm->cm_frame->stp.sgl.sg32[i].len = ioc->mfi_sgl[i].iov_len;
+		}
+
+		error = copyin(ioc->mfi_sgl[i].iov_base,
+		    sc->kbuff_arr[i],
+		    ioc->mfi_sgl[i].iov_len);
+		if (error != 0)
+		{
+			device_printf(sc->mfi_dev,
+				"Copy in failed\n");
+			return error;
+		}
+	}
+
+	cm->cm_flags |=MFI_CMD_MAPPED;
+	return 0;
+}
+
+static int
 mfi_user_command(struct mfi_softc *sc, struct mfi_ioc_passthru *ioc)
 {
 	struct mfi_command *cm;
@@ -2454,59 +2845,7 @@ out:
 	return (error);
 }
 
-#ifdef __x86_64__
 #define	PTRIN(p)		((void *)(uintptr_t)(p))
-#else
-#define	PTRIN(p)		(p)
-#endif
-
-static int
-mfi_check_for_sscd(struct mfi_softc *sc, struct mfi_command *cm)
-{
-	struct mfi_config_data *conf_data = cm->cm_data;
-	struct mfi_command *ld_cm = NULL;
-	struct mfi_ld_info *ld_info = NULL;
-	int error = 0;
-
-	if ((cm->cm_frame->dcmd.opcode == MFI_DCMD_CFG_ADD) &&
-	    (conf_data->ld[0].params.isSSCD == 1)) {
-		error = 1;
-	} else if (cm->cm_frame->dcmd.opcode == MFI_DCMD_LD_DELETE) {
-		error = mfi_dcmd_command(sc, &ld_cm, MFI_DCMD_LD_GET_INFO,
-		    (void **)&ld_info, sizeof(*ld_info));
-		if (error) {
-			device_printf(sc->mfi_dev,"Failed to allocate "
-			    "MFI_DCMD_LD_GET_INFO %d", error);
-			if (ld_info)
-				kfree(ld_info, M_MFIBUF);
-			return 0;
-		}
-		ld_cm->cm_flags = MFI_CMD_DATAIN;
-		ld_cm->cm_frame->dcmd.mbox[0]= cm->cm_frame->dcmd.mbox[0];
-		ld_cm->cm_frame->header.target_id = cm->cm_frame->dcmd.mbox[0];
-		if (mfi_wait_command(sc, ld_cm) != 0) {
-			device_printf(sc->mfi_dev, "failed to get log drv\n");
-			mfi_release_command(ld_cm);
-			kfree(ld_info, M_MFIBUF);
-			return 0;
-		}
-
-		if (ld_cm->cm_frame->header.cmd_status != MFI_STAT_OK) {
-			kfree(ld_info, M_MFIBUF);
-			mfi_release_command(ld_cm);
-			return 0;
-		} else {
-			ld_info = (struct mfi_ld_info *)ld_cm->cm_private;
-		}
-
-		if (ld_info->ld_config.params.isSSCD == 1)
-			error = 1;
-
-		mfi_release_command(ld_cm);
-		kfree(ld_info, M_MFIBUF);
-	}
-	return error;
-}
 
 static int
 mfi_ioctl(struct dev_ioctl_args *ap)
@@ -2518,26 +2857,29 @@ mfi_ioctl(struct dev_ioctl_args *ap)
 	struct mfi_softc *sc;
 	union mfi_statrequest *ms;
 	struct mfi_ioc_packet *ioc;
-#ifdef __x86_64__
-	struct mfi_ioc_packet32 *ioc32;
-#endif
 	struct mfi_ioc_aen *aen;
 	struct mfi_command *cm = NULL;
 	uint32_t context;
 	union mfi_sense_ptr sense_ptr;
 	uint8_t *data = NULL, *temp, *addr, skip_pre_post = 0;
 	size_t len;
-	int i;
+	int i, res;
 	struct mfi_ioc_passthru *iop = (struct mfi_ioc_passthru *)arg;
-#ifdef __x86_64__
-	struct mfi_ioc_passthru32 *iop32 = (struct mfi_ioc_passthru32 *)arg;
-	struct mfi_ioc_passthru iop_swab;
-#endif
 	int error, locked;
+	union mfi_sgl *sgl;
 
 	sc = dev->si_drv1;
 	error = 0;
 
+	if (sc->adpreset)
+		return EBUSY;
+
+	if (sc->hw_crit_error)
+		return EBUSY;
+
+	if (sc->issuepend_done == 0)
+		return EBUSY;
+
 	switch (cmd) {
 	case MFIIO_STATS:
 		ms = (union mfi_statrequest *)arg;
@@ -2579,9 +2921,6 @@ mfi_ioctl(struct dev_ioctl_args *ap)
 		break;
 	}
 	case MFI_CMD:
-#ifdef __x86_64__
-	case MFI_CMD32:
-#endif
 		{
 		devclass_t devclass;
 		ioc = (struct mfi_ioc_packet *)arg;
@@ -2605,9 +2944,10 @@ mfi_ioctl(struct dev_ioctl_args *ap)
 		 * will clobber some data
 		 */
 		context = cm->cm_frame->header.context;
+		cm->cm_frame->header.context = cm->cm_index;
 
 		bcopy(ioc->mfi_frame.raw, cm->cm_frame,
-		    2 * MFI_DCMD_FRAME_SIZE);  /* this isn't quite right */
+		    2 * MEGAMFI_FRAME_SIZE);
 		cm->cm_total_frame_size = (sizeof(union mfi_sgl)
 		    * ioc->mfi_sge_count) + ioc->mfi_sgl_off;
 		cm->cm_frame->header.scsi_status = 0;
@@ -2616,6 +2956,7 @@ mfi_ioctl(struct dev_ioctl_args *ap)
 			cm->cm_sg =
 			    (union mfi_sgl *)&cm->cm_frame->bytes[ioc->mfi_sgl_off];
 		}
+		sgl = cm->cm_sg;
 		cm->cm_flags = 0;
 		if (cm->cm_frame->header.flags & MFI_FRAME_DATAIN)
 			cm->cm_flags |= MFI_CMD_DATAIN;
@@ -2626,18 +2967,7 @@ mfi_ioctl(struct dev_ioctl_args *ap)
 			cm->cm_flags |= MFI_CMD_DATAIN | MFI_CMD_DATAOUT;
 		cm->cm_len = cm->cm_frame->header.data_len;
 		if (cm->cm_frame->header.cmd == MFI_CMD_STP) {
-#ifdef __x86_64__
-			if (cmd == MFI_CMD) {
-#endif
-				/* Native */
-				cm->cm_stp_len = ioc->mfi_sgl[0].iov_len;
-#ifdef __x86_64__
-			} else {
-				/* 32bit on 64bit */
-				ioc32 = (struct mfi_ioc_packet32 *)ioc;
-				cm->cm_stp_len = ioc32->mfi_sgl[0].iov_len;
-			}
-#endif
+			cm->cm_stp_len = ioc->mfi_sgl[0].iov_len;
 			cm->cm_len += cm->cm_stp_len;
 		}
 		if (cm->cm_len &&
@@ -2651,31 +2981,25 @@ mfi_ioctl(struct dev_ioctl_args *ap)
 		/* restore header context */
 		cm->cm_frame->header.context = context;
 
-		temp = data;
-		if ((cm->cm_flags & MFI_CMD_DATAOUT) ||
-		    (cm->cm_frame->header.cmd == MFI_CMD_STP)) {
-			for (i = 0; i < ioc->mfi_sge_count; i++) {
-#ifdef __x86_64__
-				if (cmd == MFI_CMD) {
-#endif
-					/* Native */
+		if (cm->cm_frame->header.cmd == MFI_CMD_STP) {
+			res = mfi_stp_cmd(sc,cm,arg);
+			if(res != 0)
+				goto out;
+		} else {
+			temp = data;
+			if ((cm->cm_flags & MFI_CMD_DATAOUT) ||
+			    (cm->cm_frame->header.cmd == MFI_CMD_STP)) {
+				for (i = 0; i < ioc->mfi_sge_count; i++) {
 					addr = ioc->mfi_sgl[i].iov_base;
 					len = ioc->mfi_sgl[i].iov_len;
-#ifdef __x86_64__
-				} else {
-					/* 32bit on 64bit */
-					ioc32 = (struct mfi_ioc_packet32 *)ioc;
-					addr = PTRIN(ioc32->mfi_sgl[i].iov_base);
-					len = ioc32->mfi_sgl[i].iov_len;
-				}
-#endif
-				error = copyin(addr, temp, len);
-				if (error != 0) {
-					device_printf(sc->mfi_dev,
-					    "Copy in failed\n");
-					goto out;
+					error = copyin(addr, temp, len);
+					if (error != 0) {
+						device_printf(sc->mfi_dev,
+						    "Copy in failed\n");
+						goto out;
+					}
+					temp = &temp[len];
 				}
-				temp = &temp[len];
 			}
 		}
 
@@ -2683,15 +3007,10 @@ mfi_ioctl(struct dev_ioctl_args *ap)
 			locked = mfi_config_lock(sc, cm->cm_frame->dcmd.opcode);
 
 		if (cm->cm_frame->header.cmd == MFI_CMD_PD_SCSI_IO) {
-#if defined(__x86_64__)
 			cm->cm_frame->pass.sense_addr_lo =
-			    (cm->cm_sense_busaddr & 0xFFFFFFFF);
+			    (uint32_t)cm->cm_sense_busaddr;
 			cm->cm_frame->pass.sense_addr_hi =
-			    (cm->cm_sense_busaddr& 0xFFFFFFFF00000000) >> 32;
-#else
-			cm->cm_frame->pass.sense_addr_lo = cm->cm_sense_busaddr;
-			cm->cm_frame->pass.sense_addr_hi = 0;
-#endif
+			    (uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32);
 		}
 
 		lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
@@ -2715,31 +3034,21 @@ mfi_ioctl(struct dev_ioctl_args *ap)
 			mfi_check_command_post(sc, cm);
 		lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 
-		temp = data;
-		if ((cm->cm_flags & MFI_CMD_DATAIN) ||
-		    (cm->cm_frame->header.cmd == MFI_CMD_STP)) {
-			for (i = 0; i < ioc->mfi_sge_count; i++) {
-#ifdef __x86_64__
-				if (cmd == MFI_CMD) {
-#endif
-					/* Native */
+		if (cm->cm_frame->header.cmd != MFI_CMD_STP) {
+			temp = data;
+			if ((cm->cm_flags & MFI_CMD_DATAIN) ||
+			    (cm->cm_frame->header.cmd == MFI_CMD_STP)) {
+				for (i = 0; i < ioc->mfi_sge_count; i++) {
 					addr = ioc->mfi_sgl[i].iov_base;
 					len = ioc->mfi_sgl[i].iov_len;
-#ifdef __x86_64__
-				} else {
-					/* 32bit on 64bit */
-					ioc32 = (struct mfi_ioc_packet32 *)ioc;
-					addr = PTRIN(ioc32->mfi_sgl[i].iov_base);
-					len = ioc32->mfi_sgl[i].iov_len;
+					error = copyout(temp, addr, len);
+					if (error != 0) {
+						device_printf(sc->mfi_dev,
+						    "Copy out failed\n");
+						goto out;
+					}
+					temp = &temp[len];
 				}
-#endif
-				error = copyout(temp, addr, len);
-				if (error != 0) {
-					device_printf(sc->mfi_dev,
-					    "Copy out failed\n");
-					goto out;
-				}
-				temp = &temp[len];
 			}
 		}
 
@@ -2748,14 +3057,6 @@ mfi_ioctl(struct dev_ioctl_args *ap)
 			bcopy(&ioc->mfi_frame.raw[ioc->mfi_sense_off],
 			    &sense_ptr.sense_ptr_data[0],
 			    sizeof(sense_ptr.sense_ptr_data));
-#ifdef __x86_64__
-			if (cmd != MFI_CMD) {
-				/*
-				 * not 64bit native so zero out any address
-				 * over 32bit */
-				sense_ptr.addr.high = 0;
-			}
-#endif
 			error = copyout(cm->cm_sense, sense_ptr.user_space,
 			    ioc->mfi_sense_len);
 			if (error != 0) {
@@ -2770,6 +3071,18 @@ out:
 		mfi_config_unlock(sc, locked);
 		if (data)
 			kfree(data, M_MFIBUF);
+		if(cm->cm_frame->header.cmd == MFI_CMD_STP) {
+			for(i=0; i < 2; i++) {
+				if (sc->kbuff_arr[i]) {
+					if (sc->mfi_kbuff_arr_busaddr != 0)
+						bus_dmamap_unload(sc->mfi_kbuff_arr_dmat[i], sc->mfi_kbuff_arr_dmamap[i]);
+					if (sc->kbuff_arr[i] != NULL)
+						bus_dmamem_free(sc->mfi_kbuff_arr_dmat[i], sc->kbuff_arr[i], sc->mfi_kbuff_arr_dmamap[i]);
+					if (sc->mfi_kbuff_arr_dmat[i] != NULL)
+						bus_dma_tag_destroy(sc->mfi_kbuff_arr_dmat[i]);
+				}
+			}
+		}
 		if (cm) {
 			lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
 			mfi_release_command(cm);
@@ -2826,20 +3139,8 @@ out:
 			    cmd, arg, flag));
 			break;
 		}
-#ifdef __x86_64__
-	case MFIIO_PASSTHRU32:
-		iop_swab.ioc_frame	= iop32->ioc_frame;
-		iop_swab.buf_size	= iop32->buf_size;
-		iop_swab.buf		= PTRIN(iop32->buf);
-		iop			= &iop_swab;
-		/* FALLTHROUGH */
-#endif
 	case MFIIO_PASSTHRU:
 		error = mfi_user_command(sc, iop);
-#ifdef __x86_64__
-		if (cmd == MFIIO_PASSTHRU32)
-			iop32->ioc_frame = iop_swab.ioc_frame;
-#endif
 		break;
 	default:
 		device_printf(sc->mfi_dev, "IOCTL 0x%lx not handled\n", cmd);
@@ -2935,15 +3236,10 @@ mfi_linux_ioctl_int(struct cdev *dev, u_long cmd, caddr_t arg, int flag)
 			locked = mfi_config_lock(sc, cm->cm_frame->dcmd.opcode);
 
 		if (cm->cm_frame->header.cmd == MFI_CMD_PD_SCSI_IO) {
-#if defined(__x86_64__)
 			cm->cm_frame->pass.sense_addr_lo =
-			    (cm->cm_sense_busaddr & 0xFFFFFFFF);
+			    (uint32_t)cm->cm_sense_busaddr;
 			cm->cm_frame->pass.sense_addr_hi =
-			    (cm->cm_sense_busaddr & 0xFFFFFFFF00000000) >> 32;
-#else
-			cm->cm_frame->pass.sense_addr_lo = cm->cm_sense_busaddr;
-			cm->cm_frame->pass.sense_addr_hi = 0;
-#endif
+			    (uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32);
 		}
 
 		lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
@@ -3173,17 +3469,29 @@ mfi_timeout(void *data)
 	int timedout = 0;
 
 	deadline = time_second - MFI_CMD_TIMEOUT;
+	if(sc->adpreset == 0)
+	{
+		if(!mfi_tbolt_reset(sc))
+		{
+			callout_reset(&sc->mfi_watchdog_callout, MFI_CMD_TIMEOUT * hz, mfi_timeout, sc);
+			return;
+		}
+	}
 	lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
 	TAILQ_FOREACH(cm, &sc->mfi_busy, cm_link) {
 		if (sc->mfi_aen_cm == cm)
 			continue;
 		if ((sc->mfi_aen_cm != cm) && (cm->cm_timestamp < deadline)) {
-			device_printf(sc->mfi_dev,
-			    "COMMAND %p TIMEOUT AFTER %d SECONDS\n", cm,
-			    (int)(time_second - cm->cm_timestamp));
-			MFI_PRINT_CMD(cm);
-			MFI_VALIDATE_CMD(sc, cm);
-			timedout++;
+			if (sc->adpreset != 0 && sc->issuepend_done == 0) {
+				cm->cm_timestamp = time_second;
+			} else {
+				device_printf(sc->mfi_dev,
+				    "COMMAND %p TIMEOUT AFTER %d SECONDS\n", cm,
+				    (int)(time_second - cm->cm_timestamp));
+				MFI_PRINT_CMD(cm);
+				MFI_VALIDATE_CMD(sc, cm);
+				timedout++;
+			}
 		}
 	}
 
diff --git a/sys/dev/raid/mfi/mfi_cam.c b/sys/dev/raid/mfi/mfi_cam.c
index f7e43a7..cabd7ef 100644
--- a/sys/dev/raid/mfi/mfi_cam.c
+++ b/sys/dev/raid/mfi/mfi_cam.c
@@ -22,36 +22,6 @@
  * 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.
- */
-/*-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *            Copyright 1994-2009 The FreeBSD Project.
- *            All rights reserved.
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- *    THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT``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 FREEBSD PROJECT 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.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies,either expressed or implied, of the FreeBSD Project.
  *
  * $FreeBSD: src/sys/dev/mfi/mfi_cam.c,v 1.7 2011/10/13 20:06:19 marius Exp $
  */
@@ -152,6 +122,7 @@ mfip_attach(device_t dev)
 				device_get_unit(dev), &mfisc->mfi_io_lock, 1,
 				MFI_SCSI_MAX_CMDS, sc->devq);
 	if (sc->sim == NULL) {
+		cam_simq_release(sc->devq);
 		device_printf(dev, "CAM SIM attach failed\n");
 		return (EINVAL);
 	}
@@ -160,6 +131,7 @@ mfip_attach(device_t dev)
 	if (xpt_bus_register(sc->sim, 0) != 0) {
 		device_printf(dev, "XPT bus registration failed\n");
 		cam_sim_free(sc->sim);
+		cam_simq_release(sc->devq);
 		lockmgr(&mfisc->mfi_io_lock, LK_RELEASE);
 		return (EINVAL);
 	}
@@ -184,6 +156,9 @@ mfip_detach(device_t dev)
 		lockmgr(&sc->mfi_sc->mfi_io_lock, LK_RELEASE);
 	}
 
+	if (sc->devq != NULL)
+		cam_simq_release(sc->devq);
+
 	return (0);
 }
 
diff --git a/sys/dev/raid/mfi/mfi_debug.c b/sys/dev/raid/mfi/mfi_debug.c
index e3b5e74..8ab4955 100644
--- a/sys/dev/raid/mfi/mfi_debug.c
+++ b/sys/dev/raid/mfi/mfi_debug.c
@@ -58,7 +58,8 @@ mfi_print_frame_flags(device_t dev, uint32_t flags)
 	    "\2SGL64"
 	    "\3SENSE64"
 	    "\4WRITE"
-	    "\5READ");
+	    "\5READ"
+	    "\6IEEESGL");
 }
 
 static void
@@ -68,7 +69,15 @@ mfi_print_sgl(struct mfi_frame_header *hdr, union mfi_sgl *sgl, int count)
 
 	kprintf("SG List:\n");
 	for (i = 0; i < count; i++) {
-		if (hdr->flags & MFI_FRAME_SGL64) {
+		if (hdr->flags & MFI_FRAME_IEEE_SGL) {
+			kprintf("0x%lx:%06d ", (u_long)sgl->sg_skinny[i].addr,
+			    sgl->sg_skinny[i].len);
+			columns += 26;
+			if (columns > 77) {
+				kprintf("\n");
+				columns = 0;
+			}
+		} else if (hdr->flags & MFI_FRAME_SGL64) {
 			kprintf("0x%lx:%06d ", (u_long)sgl->sg64[i].addr,
 			    sgl->sg64[i].len);
 			columns += 26;
@@ -235,7 +244,12 @@ mfi_validate_sg(struct mfi_softc *sc, struct mfi_command *cm,
 	hdr = &cm->cm_frame->header;
 	count = 0;
 	for (i = 0; i < hdr->sg_count; i++) {
-		count += cm->cm_sg->sg32[i].len;
+		if (hdr->flags & MFI_FRAME_IEEE_SGL)
+			count += cm->cm_sg->sg_skinny[i].len;
+		else if (hdr->flags & MFI_FRAME_SGL64)
+			count += cm->cm_sg->sg64[i].len;
+		else
+			count += cm->cm_sg->sg32[i].len;
 	}
 	/*
 	count++;
diff --git a/sys/dev/raid/mfi/mfi_disk.c b/sys/dev/raid/mfi/mfi_disk.c
index 53534b1..abe0f78 100644
--- a/sys/dev/raid/mfi/mfi_disk.c
+++ b/sys/dev/raid/mfi/mfi_disk.c
@@ -22,36 +22,6 @@
  * 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.
- */
-/*-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *            Copyright 1994-2009 The FreeBSD Project.
- *            All rights reserved.
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- *    THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT``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 FREEBSD PROJECT 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.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies,either expressed or implied, of the FreeBSD Project.
  *
  * $FreeBSD: src/sys/dev/mfi/mfi_disk.c,v 1.8 2008/11/17 23:30:19 jhb Exp $
  */
@@ -281,7 +251,7 @@ mfi_disk_strategy(struct dev_strategy_args *ap)
 	struct bio *bio = ap->a_bio;
 	struct buf *bp = bio->bio_buf;
 	struct mfi_disk *sc = ap->a_head.a_dev->si_drv1;
-	struct mfi_softc *controller;
+	struct mfi_softc *controller = sc->ld_controller;
 
 	if (sc == NULL) {
 		bp->b_error = EINVAL;
@@ -291,6 +261,16 @@ mfi_disk_strategy(struct dev_strategy_args *ap)
 		return (0);
 	}
 
+	if (controller->hw_crit_error) {
+		bp->b_error = EBUSY;
+		return (0);
+	}
+
+	if (controller->issuepend_done == 0) {
+		bp->b_error = EBUSY;
+		return (0);
+	}
+
 	/*
 	 * XXX swildner
 	 *
@@ -310,7 +290,6 @@ mfi_disk_strategy(struct dev_strategy_args *ap)
 		return (0);
 	}
 
-	controller = sc->ld_controller;
 	bio->bio_driver_info = sc;
 	lockmgr(&controller->mfi_io_lock, LK_EXCLUSIVE);
 	mfi_enqueue_bio(controller, bio);
diff --git a/sys/dev/raid/mfi/mfi_ioctl.h b/sys/dev/raid/mfi/mfi_ioctl.h
index 8450495..eebaafe 100644
--- a/sys/dev/raid/mfi/mfi_ioctl.h
+++ b/sys/dev/raid/mfi/mfi_ioctl.h
@@ -28,14 +28,20 @@
 
 #include <sys/conf.h>
 
+#include <sys/bus_dma.h>
+
 #include <dev/raid/mfi/mfireg.h>
 
-#if defined(__x86_64__) /* Assume amd64 wants 32 bit Linux */
 struct iovec32 {
 	u_int32_t	iov_base;
 	int		iov_len;
 };
-#endif
+
+struct megasas_sge
+{
+	bus_addr_t phys_addr;
+	uint32_t length;
+};
 
 #define MFIQ_FREE	0
 #define MFIQ_BIO	1
@@ -80,23 +86,6 @@ struct mfi_ioc_packet {
 	struct iovec mfi_sgl[MAX_IOCTL_SGE];
 } __packed;
 
-#ifdef __x86_64__
-struct mfi_ioc_packet32 {
-	uint16_t	mfi_adapter_no;
-	uint16_t	mfi_pad1;
-	uint32_t	mfi_sgl_off;
-	uint32_t	mfi_sge_count;
-	uint32_t	mfi_sense_off;
-	uint32_t	mfi_sense_len;
-	union {
-		uint8_t raw[128];
-		struct mfi_frame_header hdr;
-	} mfi_frame;
-
-	struct iovec32 mfi_sgl[MAX_IOCTL_SGE];
-} __packed;
-#endif
-
 struct mfi_ioc_aen {
 	uint16_t	aen_adapter_no;
 	uint16_t	aen_pad1;
@@ -105,9 +94,6 @@ struct mfi_ioc_aen {
 } __packed;
 
 #define MFI_CMD		_IOWR('M', 1, struct mfi_ioc_packet)
-#ifdef __x86_64__
-#define MFI_CMD32	_IOWR('M', 1, struct mfi_ioc_packet32)
-#endif
 #define MFI_SET_AEN	_IOW('M', 3, struct mfi_ioc_aen)
 
 #define MAX_LINUX_IOCTL_SGE	16
@@ -137,19 +123,8 @@ struct mfi_ioc_passthru {
 	uint8_t			*buf;
 } __packed;
 
-#ifdef __x86_64__
-struct mfi_ioc_passthru32 {
-	struct mfi_dcmd_frame	ioc_frame;
-	uint32_t		buf_size;
-	uint32_t		buf;
-} __packed;
-#endif
-
 #define MFIIO_STATS	_IOWR('Q', 101, union mfi_statrequest)
 #define MFIIO_PASSTHRU	_IOWR('C', 102, struct mfi_ioc_passthru)
-#ifdef __x86_64__
-#define MFIIO_PASSTHRU32	_IOWR('C', 102, struct mfi_ioc_passthru32)
-#endif
 
 struct mfi_linux_ioc_aen {
 	uint16_t	laen_adapter_no;
diff --git a/sys/dev/raid/mfi/mfi_pci.c b/sys/dev/raid/mfi/mfi_pci.c
index cb3163d..a079b5d 100644
--- a/sys/dev/raid/mfi/mfi_pci.c
+++ b/sys/dev/raid/mfi/mfi_pci.c
@@ -48,36 +48,6 @@
  * 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.
- */
-/*-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *            Copyright 1994-2009 The FreeBSD Project.
- *            All rights reserved.
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- *    THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT``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 FREEBSD PROJECT 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.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies,either expressed or implied, of the FreeBSD Project.
  *
  * $FreeBSD: src/sys/dev/mfi/mfi_pci.c,v 1.16 2010/03/02 17:34:11 kib Exp $
  */
@@ -96,7 +66,6 @@
 #include <sys/malloc.h>
 #include <sys/uio.h>
 #include <sys/eventhandler.h>
-
 #include <sys/rman.h>
 
 #include <bus/pci/pcireg.h>
@@ -134,6 +103,9 @@ static devclass_t	mfi_devclass;
 DRIVER_MODULE(mfi, pci, mfi_pci_driver, mfi_devclass, NULL, NULL);
 MODULE_VERSION(mfi, 1);
 
+static int	mfi_msi_enable = 1;
+TUNABLE_INT("hw.mfi.msi.enable", &mfi_msi_enable);
+
 struct mfi_ident {
 	uint16_t	vendor;
 	uint16_t	device;
@@ -142,6 +114,12 @@ struct mfi_ident {
 	int		flags;
 	const char	*desc;
 } mfi_identifiers[] = {
+	{0x1000, 0x005B, 0x8086, 0x9265, MFI_FLAGS_SKINNY | MFI_FLAGS_TBOLT,
+	 "Intel (R) RAID Controller RS25DB080"},
+	{0x1000, 0x005B, 0x8086, 0x9285, MFI_FLAGS_SKINNY | MFI_FLAGS_TBOLT,
+	 "Intel (R) RAID Controller RS25NB008"},
+	{0x1000, 0x005B, 0xffff, 0xffff, MFI_FLAGS_SKINNY | MFI_FLAGS_TBOLT,
+	 "ThunderBolt"},
 	{0x1000, 0x0060, 0x1028, 0xffff, MFI_FLAGS_1078,  "Dell PERC 6"},
 	{0x1000, 0x0060, 0xffff, 0xffff, MFI_FLAGS_1078,  "LSI MegaSAS 1078"},
 	{0x1000, 0x0071, 0xffff, 0xffff, MFI_FLAGS_SKINNY, "Drake Skinny"},
@@ -200,6 +178,7 @@ mfi_pci_attach(device_t dev)
 	struct mfi_ident *m;
 	uint32_t command;
 	int error;
+	u_int irq_flags;
 
 	sc = device_get_softc(dev);
 	bzero(sc, sizeof(*sc));
@@ -227,7 +206,8 @@ mfi_pci_attach(device_t dev)
 		/* 1068/1078: Memory mapped BAR is at offset 0x10 */
 		sc->mfi_regs_rid = PCIR_BAR(0);
 	} else if ((sc->mfi_flags & MFI_FLAGS_GEN2) ||
-		   (sc->mfi_flags & MFI_FLAGS_SKINNY)) {
+		   (sc->mfi_flags & MFI_FLAGS_SKINNY) ||
+		   (sc->mfi_flags & MFI_FLAGS_TBOLT)) {
 		/* GEN2/Skinny: Memory mapped BAR is at offset 0x14 */
 		sc->mfi_regs_rid = PCIR_BAR(1);
 	}
@@ -256,6 +236,16 @@ mfi_pci_attach(device_t dev)
 		goto out;
 	}
 
+	/* Allocate IRQ resource. */
+	sc->mfi_irq_rid = 0;
+	sc->mfi_irq_type = pci_alloc_1intr(sc->mfi_dev, mfi_msi_enable,
+	    &sc->mfi_irq_rid, &irq_flags);
+	if ((sc->mfi_irq = bus_alloc_resource_any(sc->mfi_dev, SYS_RES_IRQ,
+	    &sc->mfi_irq_rid, irq_flags)) == NULL) {
+		device_printf(sc->mfi_dev, "Cannot allocate interrupt\n");
+		return (EINVAL);
+	}
+
 	error = mfi_attach(sc);
 out:
 	if (error) {
@@ -270,9 +260,10 @@ static int
 mfi_pci_detach(device_t dev)
 {
 	struct mfi_softc *sc;
-	struct mfi_disk *ld;
-	struct mfi_system_pd *syspd = NULL;
-	int error;
+//	struct mfi_disk *ld;
+//	struct mfi_system_pd *syspd = NULL;
+	device_t *devlist;
+	int error, devcount, i;
 
 	sc = device_get_softc(dev);
 
@@ -286,6 +277,24 @@ mfi_pci_detach(device_t dev)
 	sc->mfi_detaching = 1;
 	lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 
+	/*
+	 * BHARAT: Fixed Kernel Corruption while unloading the driver
+	 */
+	if ((error = device_get_children(sc->mfi_dev, &devlist, &devcount)) != 0) {
+		lockmgr(&sc->mfi_config_lock, LK_RELEASE);
+		return error;
+	}
+	for(i = 0; i < devcount; i++)
+		device_delete_child(sc->mfi_dev, devlist[i]);
+	kfree(devlist, M_TEMP);
+	/*
+	 * BHARAT: Following code causes Kernel corruption during
+	 * multiple driver load/unload, this cleanup code was not
+	 * getting called up in normal run hence OS was maintaining stale dev
+	 * entries which were resulting to crash, so added above
+	 * cleanup code.
+	 */
+#if 0
 	while ((ld = TAILQ_FIRST(&sc->mfi_ld_tqh)) != NULL) {
 		if ((error = device_delete_child(dev, ld->ld_dev)) != 0) {
 			sc->mfi_detaching = 0;
@@ -300,6 +309,7 @@ mfi_pci_detach(device_t dev)
 			return (error);
 		}
 	}
+#endif
 	lockmgr(&sc->mfi_config_lock, LK_RELEASE);
 
 	EVENTHANDLER_DEREGISTER(shutdown_final, sc->mfi_eh);
@@ -318,8 +328,8 @@ mfi_pci_free(struct mfi_softc *sc)
 		bus_release_resource(sc->mfi_dev, SYS_RES_MEMORY,
 		    sc->mfi_regs_rid, sc->mfi_regs_resource);
 	}
-
-	return;
+	if (sc->mfi_irq_type == PCI_INTR_TYPE_MSI)
+		pci_release_msi(sc->mfi_dev);
 }
 
 static int
diff --git a/sys/dev/raid/mfi/mfi_syspd.c b/sys/dev/raid/mfi/mfi_syspd.c
index b929de1..7b8fe5d 100644
--- a/sys/dev/raid/mfi/mfi_syspd.c
+++ b/sys/dev/raid/mfi/mfi_syspd.c
@@ -233,7 +233,7 @@ mfi_syspd_strategy(struct dev_strategy_args *ap)
 	struct bio *bio = ap->a_bio;
 	struct buf *bp = bio->bio_buf;
 	struct mfi_system_pd *sc = ap->a_head.a_dev->si_drv1;
-	struct mfi_softc *controller;
+	struct mfi_softc *controller = sc->pd_controller;
 
 	if (sc == NULL) {
 		bp->b_error = EINVAL;
@@ -243,6 +243,16 @@ mfi_syspd_strategy(struct dev_strategy_args *ap)
 		return (0);
 	}
 
+	if (controller->hw_crit_error) {
+		bp->b_error = EBUSY;
+		return (0);
+	}
+
+	if (controller->issuepend_done == 0) {
+		bp->b_error = EBUSY;
+		return (0);
+	}
+
 	/*
 	 * XXX swildner
 	 *
@@ -262,7 +272,6 @@ mfi_syspd_strategy(struct dev_strategy_args *ap)
 		return (0);
 	}
 
-	controller = sc->pd_controller;
 	bio->bio_driver_info = sc;
 	lockmgr(&controller->mfi_io_lock, LK_EXCLUSIVE);
 	mfi_enqueue_bio(controller, bio);
diff --git a/sys/dev/raid/mfi/mfi_tbolt.c b/sys/dev/raid/mfi/mfi_tbolt.c
new file mode 100644
index 0000000..dd93683
--- /dev/null
+++ b/sys/dev/raid/mfi/mfi_tbolt.c
@@ -0,0 +1,1383 @@
+/*-
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *            Copyright 1994-2009 The FreeBSD Project.
+ *            All rights reserved.
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ *    THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT``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 FREEBSD PROJECT 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.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies,either expressed or implied, of the FreeBSD Project.
+ *
+ * $FreeBSD: src/sys/dev/mfi/mfi_tbolt.c,v 1.00 2010/06/30 16:00:00 Bharat Gusain Exp $
+ */
+
+#include "opt_mfi.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/bio.h>
+#include <sys/buf2.h>
+#include <sys/ioccom.h>
+#include <sys/eventhandler.h>
+#include <sys/callout.h>
+#include <sys/uio.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include <dev/raid/mfi/mfireg.h>
+#include <dev/raid/mfi/mfi_ioctl.h>
+#include <dev/raid/mfi/mfivar.h>
+
+struct mfi_cmd_tbolt *mfi_tbolt_get_cmd(struct mfi_softc *sc);
+union mfi_mpi2_request_descriptor *
+mfi_tbolt_get_request_descriptor(struct mfi_softc *sc, uint16_t index);
+void mfi_tbolt_complete_cmd(struct mfi_softc *sc);
+int mfi_tbolt_build_io(struct mfi_softc *sc, struct mfi_command *mfi_cmd,
+    struct mfi_cmd_tbolt *cmd);
+static inline void mfi_tbolt_return_cmd(struct mfi_softc *sc,
+    struct mfi_cmd_tbolt *cmd);
+union mfi_mpi2_request_descriptor *mfi_tbolt_build_mpt_cmd(struct mfi_softc
+    *sc, struct mfi_command *cmd);
+uint8_t
+mfi_build_mpt_pass_thru(struct mfi_softc *sc, struct mfi_command *mfi_cmd);
+union mfi_mpi2_request_descriptor *mfi_build_and_issue_cmd(struct mfi_softc
+    *sc, struct mfi_command *mfi_cmd);
+int mfi_tbolt_is_ldio(struct mfi_command *mfi_cmd);
+void mfi_tbolt_build_ldio(struct mfi_softc *sc, struct mfi_command *mfi_cmd,
+    struct mfi_cmd_tbolt *cmd);
+static int mfi_tbolt_make_sgl(struct mfi_softc *sc, struct mfi_command
+    *mfi_cmd, pMpi25IeeeSgeChain64_t sgl_ptr, struct mfi_cmd_tbolt *cmd);
+static int mfi_tbolt_build_cdb(struct mfi_softc *sc, struct mfi_command
+    *mfi_cmd, uint8_t *cdb);
+void
+map_tbolt_cmd_status(struct mfi_command *mfi_cmd, uint8_t status,
+     uint8_t ext_status);
+static void mfi_issue_pending_cmds_again (struct mfi_softc *sc);
+static void mfi_kill_hba (struct mfi_softc *sc);
+static void mfi_process_fw_state_chg_isr(void *arg);
+uint8_t mfi_tbolt_get_map_info(struct mfi_softc *sc);
+
+#define MFI_FUSION_ENABLE_INTERRUPT_MASK	(0x00000008)
+
+void
+mfi_tbolt_enable_intr_ppc(struct mfi_softc *sc)
+{
+	//MFI_WRITE4(sc, MFI_ODCR0, 0xFFFFFFFF);
+	MFI_WRITE4(sc, MFI_OMSK, ~MFI_FUSION_ENABLE_INTERRUPT_MASK);
+	MFI_READ4(sc, MFI_OMSK);
+}
+
+void
+mfi_tbolt_disable_intr_ppc(struct mfi_softc *sc)
+{
+	MFI_WRITE4(sc, MFI_OMSK, 0xFFFFFFFF);
+	MFI_READ4(sc, MFI_OMSK);
+}
+
+int32_t
+mfi_tbolt_read_fw_status_ppc(struct mfi_softc *sc)
+{
+	return MFI_READ4(sc, MFI_OSP0);
+}
+
+int32_t
+mfi_tbolt_check_clear_intr_ppc(struct mfi_softc *sc)
+{
+	int32_t status, mfi_status = 0;
+
+	status = MFI_READ4(sc, MFI_OSTS);
+
+	if (status & 1)
+	{
+		MFI_WRITE4(sc, MFI_OSTS, status);
+		MFI_READ4(sc, MFI_OSTS);
+		if (status & MFI_STATE_CHANGE_INTERRUPT){
+			mfi_status |= MFI_FIRMWARE_STATE_CHANGE;
+		}
+
+		return mfi_status;
+	}
+	if(!(status & MFI_FUSION_ENABLE_INTERRUPT_MASK))
+		return 1;
+
+	MFI_READ4(sc, MFI_OSTS);
+	return 0;
+}
+
+
+void
+mfi_tbolt_issue_cmd_ppc(struct mfi_softc *sc, bus_addr_t bus_add,
+   uint32_t frame_cnt)
+{
+	bus_add |= (MFI_REQ_DESCRIPT_FLAGS_MFA
+	    << MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+	MFI_WRITE4(sc, MFI_IQPL, (uint32_t)bus_add);
+	MFI_WRITE4(sc, MFI_IQPH, (uint32_t)((uint64_t)bus_add >> 32));
+}
+
+/**
+ * mfi_tbolt_adp_reset - For controller reset
+ * @regs: MFI register set
+ */
+int mfi_tbolt_adp_reset(struct mfi_softc *sc)
+{
+    int retry = 0, i = 0;
+    int HostDiag;
+
+    MFI_WRITE4(sc, MFI_WSR, 0xF);
+    MFI_WRITE4(sc, MFI_WSR, 4);
+    MFI_WRITE4(sc, MFI_WSR, 0xB);
+    MFI_WRITE4(sc, MFI_WSR, 2);
+    MFI_WRITE4(sc, MFI_WSR, 7);
+    MFI_WRITE4(sc, MFI_WSR, 0xD);
+
+    for (i=0;i<10000;i++) ;
+
+    HostDiag = (uint32_t)MFI_READ4(sc, MFI_HDR);
+
+    while ( !( HostDiag & DIAG_WRITE_ENABLE) )
+    {
+        for (i=0;i<1000;i++) ;
+        HostDiag = (uint32_t)MFI_READ4(sc, MFI_HDR);
+        device_printf(sc->mfi_dev,"ADP_RESET_TBOLT: retry time=%x, "
+	    "hostdiag=%x\n", retry, HostDiag);
+
+        if (retry++ >= 100)
+            return 1;
+
+    }
+
+    device_printf(sc->mfi_dev,"ADP_RESET_TBOLT: HostDiag=%x\n", HostDiag);
+
+    MFI_WRITE4(sc, MFI_HDR, (HostDiag | DIAG_RESET_ADAPTER));
+
+    for (i=0; i < 10; i++) {
+        for (i = 0; i < 10000; i++);
+    }
+
+    HostDiag = (uint32_t)MFI_READ4(sc, MFI_RSR);
+    while (HostDiag & DIAG_RESET_ADAPTER)
+    {
+        for (i=0;i<1000;i++) ;
+        HostDiag = (uint32_t)MFI_READ4(sc, MFI_RSR);
+        device_printf(sc->mfi_dev,"ADP_RESET_TBOLT: retry time=%x, "
+	    "hostdiag=%x\n", retry, HostDiag);
+
+        if (retry++ >= 1000)
+            return 1;
+    }
+    return 0;
+}
+
+/*
+ *******************************************************************************************
+ * Description:
+ *      This routine initialize Thunderbolt specific device information
+ *******************************************************************************************
+ */
+void mfi_tbolt_init_globals(struct mfi_softc *sc)
+{
+	/* Initialize single reply size and Message size */
+	sc->reply_size = MEGASAS_THUNDERBOLT_REPLY_SIZE;
+	sc->raid_io_msg_size = MEGASAS_THUNDERBOLT_NEW_MSG_SIZE;
+
+	/*
+	 * Calculating how many SGEs allowed in a allocated main message
+	 * (size of the Message - Raid SCSI IO message size(except SGE))
+	 * / size of SGE
+	 * (0x100 - (0x90 - 0x10)) / 0x10 = 8
+	 */
+	sc->max_SGEs_in_main_message =
+	    (uint8_t)((sc->raid_io_msg_size
+	    - (sizeof(struct mfi_mpi2_request_raid_scsi_io)
+	    - sizeof(MPI2_SGE_IO_UNION))) / sizeof(MPI2_SGE_IO_UNION));
+	/*
+	 * (Command frame size allocaed in SRB ext - Raid SCSI IO message size)
+	 * / size of SGL ;
+	 * (1280 - 256) / 16 = 64
+	 */
+	sc->max_SGEs_in_chain_message = (MR_COMMAND_SIZE
+	    - sc->raid_io_msg_size) / sizeof(MPI2_SGE_IO_UNION);
+	/*
+	 * (0x08-1) + 0x40 = 0x47 - 0x01 = 0x46  one is left for command
+	 * colscing
+	*/
+	sc->mfi_max_sge = (sc->max_SGEs_in_main_message - 1)
+	    + sc->max_SGEs_in_chain_message - 1;
+	/*
+	* This is the offset in number of 4 * 32bit words to the next chain
+	* (0x100 - 0x10)/0x10 = 0xF(15)
+	*/
+	sc->chain_offset_value_for_main_message = (sc->raid_io_msg_size
+	    - sizeof(MPI2_SGE_IO_UNION))/16;
+	sc->chain_offset_value_for_mpt_ptmsg
+	    = offsetof(struct mfi_mpi2_request_raid_scsi_io, SGL)/16;
+	sc->mfi_cmd_pool_tbolt = NULL;
+	sc->request_desc_pool = NULL;
+
+
+}
+
+/*
+ ****************************************************************************
+ * Description:
+ *      This function calculates the memory requirement for Thunderbolt
+ *      controller
+ * Return Value:
+ *      Total required memory in bytes
+ ****************************************************************************
+ */
+
+uint32_t mfi_tbolt_get_memory_requirement(struct mfi_softc *sc)
+{
+	uint32_t size;
+	size = MEGASAS_THUNDERBOLT_MSG_ALLIGNMENT;	// for Alignment
+	size += sc->raid_io_msg_size * (sc->mfi_max_fw_cmds + 1);
+	size += sc->reply_size * sc->mfi_max_fw_cmds;
+	// this is for SGL's
+	size += MEGASAS_MAX_SZ_CHAIN_FRAME * sc->mfi_max_fw_cmds;
+	return size;
+}
+
+/*
+ ****************************************************************************
+ * Description:
+ *      This function will prepare message pools for the Thunderbolt controller
+ * Arguments:
+ *      DevExt - HBA miniport driver's adapter data storage structure
+ *      pMemLocation - start of the memory allocated for Thunderbolt.
+ * Return Value:
+ *      TRUE if successful
+ *      FALSE if failed
+ ****************************************************************************
+ */
+int mfi_tbolt_init_desc_pool(struct mfi_softc *sc, uint8_t* mem_location,
+    uint32_t tbolt_contg_length)
+{
+	uint32_t     offset = 0;
+	uint8_t      *addr = mem_location;
+
+	/* Request Descriptor Base physical Address */
+
+	/* For Request Decriptors Virtual Memory */
+	/* Initialise the aligned IO Frames Virtual Memory Pointer */
+	if (((uintptr_t)addr) & (0xFF))	{
+		addr = &addr[sc->raid_io_msg_size];
+		addr = (uint8_t *)((uintptr_t)addr & (~0xFF));
+		sc->request_message_pool_align = addr;
+	} else
+		sc->request_message_pool_align = addr;
+
+	offset = sc->request_message_pool_align - sc->request_message_pool;
+	sc->request_msg_busaddr = sc->mfi_tb_busaddr + offset;
+
+	/* DJA XXX should this be bus dma ??? */
+	/* Skip request message pool */
+	addr = &addr[sc->raid_io_msg_size * (sc->mfi_max_fw_cmds + 1)];
+	/* Reply Frame Pool is initialized */
+	sc->reply_frame_pool = (struct mfi_mpi2_reply_header *) addr;
+	if (((uintptr_t)addr) & (0xFF))	{
+		addr = &addr[sc->reply_size];
+		addr = (uint8_t *)((uintptr_t)addr & (~0xFF));
+	}
+	sc->reply_frame_pool_align
+		    = (struct mfi_mpi2_reply_header *)addr;
+
+	offset = (uintptr_t)sc->reply_frame_pool_align
+	    - (uintptr_t)sc->request_message_pool;
+	sc->reply_frame_busaddr = sc->mfi_tb_busaddr + offset;
+
+	/* Skip Reply Frame Pool */
+	addr += sc->reply_size * sc->mfi_max_fw_cmds;
+	sc->reply_pool_limit = addr;
+
+	/* initializing reply address to 0xFFFFFFFF */
+	memset((uint8_t *)sc->reply_frame_pool, 0xFF,
+	       (sc->reply_size * sc->mfi_max_fw_cmds));
+
+	offset = sc->reply_size * sc->mfi_max_fw_cmds;
+	sc->sg_frame_busaddr = sc->reply_frame_busaddr + offset;
+	/* initialize the last_reply_idx to 0 */
+	sc->last_reply_idx = 0;
+	offset = (sc->sg_frame_busaddr + (MEGASAS_MAX_SZ_CHAIN_FRAME *
+	    sc->mfi_max_fw_cmds)) - sc->mfi_tb_busaddr;
+	if(offset > tbolt_contg_length)
+		device_printf(sc->mfi_dev,"Error:Initialized more than "
+		    "allocated\n");
+	return 0;
+}
+
+/*
+ ****************************************************************************
+ * Description:
+ *   This routine prepare and issue INIT2 frame to the Firmware
+ ****************************************************************************
+ */
+
+int
+mfi_tbolt_init_MFI_queue(struct mfi_softc *sc)
+{
+	struct MPI2_IOC_INIT_REQUEST   *mpi2IocInit;
+	struct mfi_init_frame	*mfi_init;
+	uintptr_t			offset = 0;
+	bus_addr_t			phyAddress;
+	MFI_ADDRESS			*mfiAddressTemp;
+	struct mfi_command *cm;
+	int error;
+
+	mpi2IocInit = (struct MPI2_IOC_INIT_REQUEST *)sc->mfi_tb_ioc_init_desc;
+	/* Check if initialization is already completed */
+	if(sc->MFA_enabled) {
+		return 1;
+	}
+
+	lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
+	if ((cm = mfi_dequeue_free(sc)) == NULL) {
+		lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+		return (EBUSY);
+	}
+	cm->cm_frame = (union mfi_frame *)((uintptr_t)sc->mfi_tb_init);
+	cm->cm_frame_busaddr = sc->mfi_tb_init_busaddr;
+	cm->cm_dmamap = sc->mfi_tb_init_dmamap;
+	cm->cm_frame->header.context = 0;
+	cm->cm_sc = sc;
+	cm->cm_index = 0;
+
+	/*
+	 * Abuse the SG list area of the frame to hold the init_qinfo
+	 * object;
+	 */
+	mfi_init = &cm->cm_frame->init;
+
+	bzero(mpi2IocInit, sizeof(struct MPI2_IOC_INIT_REQUEST));
+	mpi2IocInit->Function  = MPI2_FUNCTION_IOC_INIT;
+	mpi2IocInit->WhoInit   = MPI2_WHOINIT_HOST_DRIVER;
+
+	/* set MsgVersion and HeaderVersion host driver was built with */
+	mpi2IocInit->MsgVersion = MPI2_VERSION;
+	mpi2IocInit->HeaderVersion = MPI2_HEADER_VERSION;
+	mpi2IocInit->SystemRequestFrameSize = sc->raid_io_msg_size/4;
+	mpi2IocInit->ReplyDescriptorPostQueueDepth
+	    = (uint16_t)sc->mfi_max_fw_cmds;
+	mpi2IocInit->ReplyFreeQueueDepth = 0; /* Not supported by MR. */
+
+	/* Get physical address of reply frame pool */
+	offset = (uintptr_t) sc->reply_frame_pool_align
+	    - (uintptr_t)sc->request_message_pool;
+	phyAddress = sc->mfi_tb_busaddr + offset;
+	mfiAddressTemp =
+	    (MFI_ADDRESS *)&mpi2IocInit->ReplyDescriptorPostQueueAddress;
+	mfiAddressTemp->u.addressLow = (uint32_t)phyAddress;
+	mfiAddressTemp->u.addressHigh = (uint32_t)((uint64_t)phyAddress >> 32);
+
+	/* Get physical address of request message pool */
+	offset = sc->request_message_pool_align - sc->request_message_pool;
+	phyAddress =  sc->mfi_tb_busaddr + offset;
+	mfiAddressTemp = (MFI_ADDRESS *)&mpi2IocInit->SystemRequestFrameBaseAddress;
+	mfiAddressTemp->u.addressLow = (uint32_t)phyAddress;
+	mfiAddressTemp->u.addressHigh = (uint32_t)((uint64_t)phyAddress >> 32);
+	mpi2IocInit->ReplyFreeQueueAddress =  0; // Not supported by MR.
+	mpi2IocInit->TimeStamp = time_second;
+
+	if (sc->verbuf) {
+		ksnprintf((char *)sc->verbuf, strlen(MEGASAS_VERSION) + 2, "%s\n",
+                MEGASAS_VERSION);
+		mfi_init->driver_ver_lo = (uint32_t)sc->verbuf_h_busaddr;
+		mfi_init->driver_ver_hi =
+		    (uint32_t)((uint64_t)sc->verbuf_h_busaddr >> 32);
+	}
+	/* Get the physical address of the mpi2 ioc init command */
+	phyAddress =  sc->mfi_tb_ioc_init_busaddr;
+	mfi_init->qinfo_new_addr_lo = (uint32_t)phyAddress;
+	mfi_init->qinfo_new_addr_hi = (uint32_t)((uint64_t)phyAddress >> 32);
+	mfi_init->header.flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
+
+	mfi_init->header.cmd = MFI_CMD_INIT;
+	mfi_init->header.data_len = sizeof(struct MPI2_IOC_INIT_REQUEST);
+	mfi_init->header.cmd_status = MFI_STAT_INVALID_STATUS;
+
+	cm->cm_data = NULL;
+	cm->cm_flags |= MFI_CMD_POLLED;
+	cm->cm_timestamp = time_second;
+	if ((error = mfi_mapcmd(sc, cm)) != 0) {
+		device_printf(sc->mfi_dev, "failed to send IOC init2 "
+		    "command %d at %lx\n", error, (long)cm->cm_frame_busaddr);
+		mfi_release_command(cm);
+		lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+		return (error);
+	}
+	mfi_release_command(cm);
+	lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+
+	if(mfi_init->header.cmd_status == 0) {
+		sc->MFA_enabled = 1;
+	}
+	else {
+		device_printf(sc->mfi_dev, "Init command Failed %x\n",
+		    mfi_init->header.cmd_status);
+		return 1;
+	}
+
+	return 0;
+
+}
+
+int mfi_tbolt_alloc_cmd(struct mfi_softc *sc)
+{
+	struct mfi_cmd_tbolt *cmd;
+	bus_addr_t io_req_base_phys;
+	uint8_t *io_req_base;
+	int i = 0, j = 0, offset = 0;
+
+	/*
+	 * sc->mfi_cmd_pool_tbolt is an array of struct mfi_cmd_tbolt pointers.
+	 * Allocate the dynamic array first and then allocate individual
+	 * commands.
+	 */
+	sc->request_desc_pool = kmalloc(sizeof(
+	    union mfi_mpi2_request_descriptor) * sc->mfi_max_fw_cmds,
+	    M_MFIBUF, M_NOWAIT|M_ZERO);
+	sc->mfi_cmd_pool_tbolt = kmalloc(sizeof(struct mfi_cmd_tbolt*)
+	    * sc->mfi_max_fw_cmds, M_MFIBUF, M_NOWAIT|M_ZERO);
+
+	if (!sc->mfi_cmd_pool_tbolt) {
+		device_printf(sc->mfi_dev, "out of memory. Could not alloc "
+		    "memory for cmd_list_fusion\n");
+		return 1;
+	}
+
+	for (i = 0; i < sc->mfi_max_fw_cmds; i++) {
+		sc->mfi_cmd_pool_tbolt[i] = kmalloc(sizeof(
+		    struct mfi_cmd_tbolt),M_MFIBUF, M_NOWAIT|M_ZERO);
+
+		if (!sc->mfi_cmd_pool_tbolt[i]) {
+			device_printf(sc->mfi_dev, "Could not alloc cmd list "
+			    "fusion\n");
+
+			for (j = 0; j < i; j++)
+				kfree(sc->mfi_cmd_pool_tbolt[j], M_MFIBUF);
+
+			kfree(sc->mfi_cmd_pool_tbolt, M_MFIBUF);
+			sc->mfi_cmd_pool_tbolt = NULL;
+		}
+	}
+
+	/*
+	 * The first 256 bytes (SMID 0) is not used. Don't add to the cmd
+	 *list
+	 */
+	io_req_base = sc->request_message_pool_align
+		+ MEGASAS_THUNDERBOLT_NEW_MSG_SIZE;
+	io_req_base_phys = sc->request_msg_busaddr
+		+ MEGASAS_THUNDERBOLT_NEW_MSG_SIZE;
+
+	/*
+	 * Add all the commands to command pool (instance->cmd_pool)
+	 */
+	/* SMID 0 is reserved. Set SMID/index from 1 */
+
+	for (i = 0; i < sc->mfi_max_fw_cmds; i++) {
+		cmd = sc->mfi_cmd_pool_tbolt[i];
+		offset = MEGASAS_THUNDERBOLT_NEW_MSG_SIZE * i;
+		cmd->index = i + 1;
+		cmd->request_desc = (union mfi_mpi2_request_descriptor *)
+		    (sc->request_desc_pool + i);
+		cmd->io_request = (struct mfi_mpi2_request_raid_scsi_io *)
+		    (io_req_base + offset);
+		cmd->io_request_phys_addr = io_req_base_phys + offset;
+		cmd->sg_frame = (MPI2_SGE_IO_UNION *)(sc->reply_pool_limit
+		    + i * MEGASAS_MAX_SZ_CHAIN_FRAME);
+		cmd->sg_frame_phys_addr = sc->sg_frame_busaddr + i
+		    * MEGASAS_MAX_SZ_CHAIN_FRAME;
+
+		TAILQ_INSERT_TAIL(&(sc->mfi_cmd_tbolt_tqh), cmd, next);
+	}
+	return 0;
+}
+
+int mfi_tbolt_reset(struct mfi_softc *sc)
+{
+	uint32_t fw_state;
+
+	lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
+	if (atomic_read(&sc->fw_reset_no_pci_access)){
+		device_printf(sc->mfi_dev,"NO PCI ACCESS\n");
+		lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+		return 1;
+	}
+
+	if (sc->hw_crit_error){
+		device_printf(sc->mfi_dev,"HW CRITICAL ERROR\n");
+		lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+		return 1;
+	}
+
+	if (sc->mfi_flags & MFI_FLAGS_TBOLT){
+		fw_state = sc->mfi_read_fw_status(sc);
+		if((fw_state & MFI_FWSTATE_FAULT) == MFI_FWSTATE_FAULT)
+		{
+			if((sc->disableOnlineCtrlReset == 0)
+			    && (sc->adpreset == 0)){
+				device_printf(sc->mfi_dev,"Adapter RESET "
+				    "condition is detected\n");
+				sc->adpreset = 1;
+				sc->issuepend_done = 0;
+				sc->MFA_enabled = 0;
+				sc->last_reply_idx = 0;
+				mfi_process_fw_state_chg_isr((void *) sc);
+			}
+			lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+			return 0;
+		}
+	}
+	lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+	return 1;
+}
+
+/*
+ * mfi_intr_tbolt - isr entry point
+ */
+void mfi_intr_tbolt(void *arg)
+{
+	struct mfi_softc *sc = (struct mfi_softc *)arg;
+
+	if(sc->mfi_check_clear_intr(sc) == 1)
+	{
+		return;
+	}
+	if(sc->shutdown_issued)
+		return;
+	lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
+	mfi_tbolt_complete_cmd(sc);
+	if(sc->mfi_flags & MFI_FLAGS_QFRZN)
+		sc->mfi_flags &= ~MFI_FLAGS_QFRZN;
+	mfi_startio(sc);
+	lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+	return;
+}
+
+/**
+ * map_cmd_status -	Maps FW cmd status to OS cmd status
+ * @cmd :		Pointer to cmd
+ * @status :		status of cmd returned by FW
+ * @ext_status :	ext status of cmd returned by FW
+ */
+
+void
+map_tbolt_cmd_status(struct mfi_command *mfi_cmd, uint8_t status,
+    uint8_t ext_status)
+{
+
+	switch (status) {
+
+		case MFI_STAT_OK:
+			mfi_cmd->cm_frame->header.cmd_status = 0;
+			mfi_cmd->cm_frame->dcmd.header.cmd_status = 0;
+			break;
+
+		case MFI_STAT_SCSI_IO_FAILED:
+		case MFI_STAT_LD_INIT_IN_PROGRESS:
+			mfi_cmd->cm_frame->header.cmd_status = status;
+			mfi_cmd->cm_frame->header.scsi_status = ext_status;
+			mfi_cmd->cm_frame->dcmd.header.cmd_status = status;
+			mfi_cmd->cm_frame->dcmd.header.scsi_status
+			    = ext_status;
+			break;
+
+		case MFI_STAT_SCSI_DONE_WITH_ERROR:
+			mfi_cmd->cm_frame->header.cmd_status = ext_status;
+			mfi_cmd->cm_frame->dcmd.header.cmd_status = ext_status;
+			break;
+
+		case MFI_STAT_LD_OFFLINE:
+		case MFI_STAT_DEVICE_NOT_FOUND:
+			mfi_cmd->cm_frame->header.cmd_status = status;
+			mfi_cmd->cm_frame->dcmd.header.cmd_status = status;
+			break;
+
+		default:
+			mfi_cmd->cm_frame->header.cmd_status = status;
+			mfi_cmd->cm_frame->dcmd.header.cmd_status = status;
+			break;
+		}
+}
+
+
+
+void mfi_tbolt_complete_cmd(struct mfi_softc *sc)
+{
+	struct mfi_mpi2_reply_header *desc, *reply_desc;
+	struct mfi_command *cmd_mfi;	/* For MFA Cmds */
+	struct mfi_cmd_tbolt *cmd_tbolt;
+	uint16_t smid;
+	uint8_t reply_descript_type;
+	struct mfi_mpi2_request_raid_scsi_io  *scsi_io_req;
+	uint32_t status, extStatus;
+	uint16_t num_completed;
+	union desc_value val;
+
+	desc = (struct mfi_mpi2_reply_header *)
+		((uintptr_t)sc->reply_frame_pool_align
+		+ sc->last_reply_idx * sc->reply_size);
+	reply_desc = desc;
+
+	if (!reply_desc)
+		device_printf(sc->mfi_dev, "reply desc is NULL!!\n");
+
+	reply_descript_type = reply_desc->ReplyFlags
+	     & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
+	if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
+		return;
+
+	num_completed = 0;
+	val.word = ((union mfi_mpi2_reply_descriptor *)desc)->words;
+
+	/* Read Reply descriptor */
+	while ((val.u.low != 0xFFFFFFFF) && (val.u.high != 0xFFFFFFFF)) {
+
+		smid = reply_desc->SMID;
+		if (!smid || smid > sc->mfi_max_fw_cmds + 1) {
+			device_printf(sc->mfi_dev, "smid is %x. Cannot "
+			    "proceed. Returning \n",smid);
+			return;
+		}
+
+		cmd_tbolt = sc->mfi_cmd_pool_tbolt[smid - 1];
+		cmd_mfi = &sc->mfi_commands[cmd_tbolt->sync_cmd_idx];
+		scsi_io_req = cmd_tbolt->io_request;
+
+		/* Check if internal commands */
+		status = cmd_mfi->cm_frame->dcmd.header.cmd_status;
+		extStatus = cmd_mfi->cm_frame->dcmd.header.scsi_status;
+
+		/*
+		switch (scsi_io_req->Function)
+		{
+		case MPI2_FUNCTION_SCSI_IO_REQUEST :
+			kprintf("HELLO MPI2_FUNCTION_SCSI_IO_REQUEST\n");
+			break;
+		case MPI2_FUNCTION_LD_IO_REQUEST :
+			kprintf("HELLO MPI2_FUNCTION_LD_IO_REQUEST\n");
+			break;
+		case MPI2_FUNCTION_PASSTHRU_IO_REQUEST:
+			kprintf("HELLO MPI2_FUNCTION_PASSTHRU_IO_REQUEST\n");
+			break;
+		default:
+			kprintf("HELLO default\n");
+			break;
+		}
+		*/
+
+		switch (scsi_io_req->Function)
+		{
+		case MPI2_FUNCTION_LD_IO_REQUEST:
+			/* Regular Path IO. */
+			/* Map the Fw Error Status. */
+			map_tbolt_cmd_status(cmd_mfi, status,
+			    extStatus);
+			if ((cmd_mfi->cm_frame->dcmd.opcode
+			    == MFI_DCMD_LD_MAP_GET_INFO)
+			    && (cmd_mfi->cm_frame->dcmd.mbox[1] == 1))
+				{
+					if (cmd_mfi->cm_frame->header.cmd_status
+					    != 0)
+						device_printf(sc->mfi_dev,"map sync failed\n");
+					else {
+						sc->map_id++;
+						device_printf(sc->mfi_dev,"map sync completed\n");
+						mfi_release_command(cmd_mfi);
+					}
+				}
+			if ((cmd_mfi->cm_flags & MFI_ON_MFIQ_BUSY)
+			    == MFI_ON_MFIQ_BUSY
+			    && (cmd_mfi->cm_flags & MFI_CMD_POLLED) == 0) {
+				/* BHARAT poll workaround */
+				mfi_remove_busy(cmd_mfi);
+				cmd_mfi->cm_error = 0;
+				mfi_complete(sc, cmd_mfi);
+			}
+			mfi_tbolt_return_cmd(sc, cmd_tbolt);
+			break;
+		case MPI2_FUNCTION_PASSTHRU_IO_REQUEST:
+			map_tbolt_cmd_status(cmd_mfi, status, extStatus);
+			if ((cmd_mfi->cm_frame->dcmd.opcode
+			    == MFI_DCMD_LD_MAP_GET_INFO)
+			    && (cmd_mfi->cm_frame->dcmd.mbox[1] == 1)) {
+				if(cmd_mfi->cm_frame->header.cmd_status != 0)
+					device_printf(sc->mfi_dev,"map sync failed\n");
+				else {
+					sc->map_id++;
+					device_printf(sc->mfi_dev,"map sync completed\n");
+					mfi_release_command(cmd_mfi);
+				}
+			}
+			if ((cmd_mfi->cm_flags & MFI_ON_MFIQ_BUSY)
+			    == MFI_ON_MFIQ_BUSY
+			    && (cmd_mfi->cm_flags & MFI_CMD_POLLED) == 0) {
+				/* BHARAT poll workaround */
+				mfi_remove_busy(cmd_mfi);
+				cmd_mfi->cm_error = 0;
+				mfi_complete(sc, cmd_mfi);
+			}
+			mfi_tbolt_return_cmd(sc, cmd_tbolt);
+			break;
+		}
+
+		sc->last_reply_idx++;
+		if (sc->last_reply_idx >= sc->mfi_max_fw_cmds) {
+			MFI_WRITE4(sc, MFI_RPI, sc->last_reply_idx);
+			sc->last_reply_idx = 0;
+		}
+		/*set it back to all 0xfff.*/
+		((union mfi_mpi2_reply_descriptor*)desc)->words =
+			~((uint64_t)0x00);
+
+		num_completed++;
+
+		/* Get the next reply descriptor */
+		desc = (struct mfi_mpi2_reply_header *)
+		    ((uintptr_t)sc->reply_frame_pool_align
+		    + sc->last_reply_idx * sc->reply_size);
+		reply_desc = desc;
+		val.word = ((union mfi_mpi2_reply_descriptor*)desc)->words;
+		reply_descript_type = reply_desc->ReplyFlags
+		    & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
+		if(reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
+			break;
+	}
+
+	if (!num_completed)
+		return;
+
+	/* update replyIndex to FW */
+	if(sc->last_reply_idx)
+		MFI_WRITE4(sc, MFI_RPI, sc->last_reply_idx);
+
+	return;
+}
+
+/**
+ * mfi_get_cmd -	Get a command from the free pool
+ * @instance:		Adapter soft state
+ *
+ * Returns a free command from the pool
+ */
+
+struct mfi_cmd_tbolt *mfi_tbolt_get_cmd(struct mfi_softc
+						  *sc)
+{
+	struct mfi_cmd_tbolt *cmd = NULL;
+
+	KKASSERT(lockstatus(&sc->mfi_io_lock, curthread) != 0);
+
+	cmd = TAILQ_FIRST(&sc->mfi_cmd_tbolt_tqh);
+	TAILQ_REMOVE(&sc->mfi_cmd_tbolt_tqh, cmd, next);
+	memset((uint8_t *)cmd->sg_frame, 0, MEGASAS_MAX_SZ_CHAIN_FRAME);
+	memset((uint8_t *)cmd->io_request, 0,
+	    MEGASAS_THUNDERBOLT_NEW_MSG_SIZE);
+	return cmd;
+}
+
+/**
+ * mfi_tbolt_return_cmd -	Return a cmd to free command pool
+ * @instance:		Adapter soft state
+ * @cmd:		Command packet to be returned to free command pool
+ */
+static inline void
+mfi_tbolt_return_cmd(struct mfi_softc *sc, struct mfi_cmd_tbolt *cmd)
+{
+	KKASSERT(lockstatus(&sc->mfi_io_lock, curthread) != 0);
+
+	TAILQ_INSERT_TAIL(&sc->mfi_cmd_tbolt_tqh, cmd, next);
+}
+
+
+union mfi_mpi2_request_descriptor *
+mfi_tbolt_get_request_descriptor(struct mfi_softc *sc, uint16_t index)
+{
+	uint8_t *p;
+
+	if (index >= sc->mfi_max_fw_cmds) {
+		device_printf(sc->mfi_dev, "Invalid SMID (0x%x)request "
+		    "for descriptor\n", index);
+		return NULL;
+	}
+	p = sc->request_desc_pool + sizeof(union mfi_mpi2_request_descriptor)
+	    * index;
+	memset(p, 0, sizeof(union mfi_mpi2_request_descriptor));
+	return (union mfi_mpi2_request_descriptor *)p;
+}
+
+
+// Used to build IOCTL cmd
+uint8_t
+mfi_build_mpt_pass_thru(struct mfi_softc *sc, struct mfi_command *mfi_cmd)
+{
+	MPI25_IEEE_SGE_CHAIN64 *mpi25_ieee_chain;
+	struct mfi_mpi2_request_raid_scsi_io *io_req;
+	struct mfi_cmd_tbolt *cmd;
+
+	cmd = mfi_tbolt_get_cmd(sc);
+	if (!cmd)
+		return EBUSY;
+	mfi_cmd->cm_extra_frames = cmd->index; // Frame count used as SMID
+	cmd->sync_cmd_idx = mfi_cmd->cm_index;
+	io_req = cmd->io_request;
+	mpi25_ieee_chain = (MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL.IeeeChain;
+
+	io_req->Function = MPI2_FUNCTION_PASSTHRU_IO_REQUEST;
+	io_req->SGLOffset0 = offsetof(struct mfi_mpi2_request_raid_scsi_io,
+	    SGL) / 4;
+	io_req->ChainOffset = sc->chain_offset_value_for_mpt_ptmsg;
+
+	mpi25_ieee_chain->Address = mfi_cmd->cm_frame_busaddr;
+
+	/*
+	  In MFI pass thru, nextChainOffset will always be zero to
+	  indicate the end of the chain.
+	*/
+	mpi25_ieee_chain->Flags= MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT
+		| MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR;
+
+	/* setting the length to the maximum length */
+	mpi25_ieee_chain->Length = 1024;
+
+	return 0;
+}
+
+void
+mfi_tbolt_build_ldio(struct mfi_softc *sc, struct mfi_command *mfi_cmd,
+    struct mfi_cmd_tbolt *cmd)
+{
+	uint32_t start_lba_lo = 0, start_lba_hi = 0, device_id;
+	struct mfi_mpi2_request_raid_scsi_io	*io_request;
+	struct IO_REQUEST_INFO io_info;
+
+	device_id = mfi_cmd->cm_frame->io.header.target_id;
+	io_request = cmd->io_request;
+	io_request->RaidContext.TargetID = device_id;
+	io_request->RaidContext.Status = 0;
+	io_request->RaidContext.exStatus =0;
+
+	start_lba_lo = mfi_cmd->cm_frame->io.lba_lo;
+	start_lba_hi = mfi_cmd->cm_frame->io.lba_hi;
+
+	memset(&io_info, 0, sizeof(struct IO_REQUEST_INFO));
+	io_info.ldStartBlock = ((uint64_t)start_lba_hi << 32) | start_lba_lo;
+	io_info.numBlocks = mfi_cmd->cm_frame->io.header.data_len;
+	io_info.ldTgtId = device_id;
+	if ((mfi_cmd->cm_frame->header.flags & MFI_FRAME_DIR_READ) ==
+	    MFI_FRAME_DIR_READ)
+		io_info.isRead = 1;
+
+		io_request->RaidContext.timeoutValue
+		     = MFI_FUSION_FP_DEFAULT_TIMEOUT;
+		io_request->Function = MPI2_FUNCTION_LD_IO_REQUEST;
+		io_request->DevHandle = device_id;
+		cmd->request_desc->header.RequestFlags
+		    = (MFI_REQ_DESCRIPT_FLAGS_LD_IO
+		    << MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+	if((io_request->IoFlags == 6) && (io_info.numBlocks == 0))
+		io_request->RaidContext.RegLockLength = 0x100;
+	io_request->DataLength = mfi_cmd->cm_frame->io.header.data_len
+	    * MFI_SECTOR_LEN;
+}
+
+int mfi_tbolt_is_ldio(struct mfi_command *mfi_cmd)
+{
+	if(mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_READ
+	    || mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
+		return 1;
+	else
+		return 0;
+}
+
+
+int
+mfi_tbolt_build_io(struct mfi_softc *sc, struct mfi_command *mfi_cmd, struct mfi_cmd_tbolt *cmd)
+{
+	uint32_t device_id;
+	uint32_t sge_count;
+	uint8_t cdb[32], cdb_len;
+
+	memset(cdb, 0, 32);
+	struct mfi_mpi2_request_raid_scsi_io *io_request = cmd->io_request;
+
+	device_id = mfi_cmd->cm_frame->header.target_id;
+
+	/* Have to build CDB here for TB as BSD don't have a scsi layer */
+	if((cdb_len = mfi_tbolt_build_cdb(sc, mfi_cmd, cdb)) == 1)
+		return 1;
+
+	/* Just the CDB length,rest of the Flags are zero */
+	io_request->IoFlags = cdb_len;
+	memcpy(io_request->CDB.CDB32, cdb, 32);
+
+	if (mfi_tbolt_is_ldio(mfi_cmd))
+		mfi_tbolt_build_ldio(sc, mfi_cmd , cmd);
+	else
+		return 1;
+
+	/*
+	 * Construct SGL
+	 */
+	sge_count = mfi_tbolt_make_sgl(sc, mfi_cmd,
+	    (pMpi25IeeeSgeChain64_t) &io_request->SGL, cmd);
+	if (sge_count > sc->mfi_max_sge) {
+		device_printf(sc->mfi_dev, "Error. sge_count (0x%x) exceeds "
+		    "max (0x%x) allowed\n", sge_count, sc->mfi_max_sge);
+		return 1;
+	}
+	io_request->RaidContext.numSGE = sge_count;
+	io_request->SGLFlags = MPI2_SGE_FLAGS_64_BIT_ADDRESSING;
+
+	if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
+		io_request->Control = MPI2_SCSIIO_CONTROL_WRITE;
+	else
+		io_request->Control = MPI2_SCSIIO_CONTROL_READ;
+
+	io_request->SGLOffset0 = offsetof(
+	    struct mfi_mpi2_request_raid_scsi_io, SGL)/4;
+
+	io_request->SenseBufferLowAddress = mfi_cmd->cm_sense_busaddr;
+	io_request->SenseBufferLength = MFI_SENSE_LEN;
+	return 0;
+}
+
+static int
+mfi_tbolt_build_cdb(struct mfi_softc *sc, struct mfi_command *mfi_cmd,
+    uint8_t *cdb)
+{
+	uint32_t lba_lo, lba_hi, num_lba;
+	uint8_t cdb_len;
+
+	if(mfi_cmd == NULL || cdb == NULL)
+		return 1;
+	num_lba = mfi_cmd->cm_frame->io.header.data_len;
+	lba_lo = mfi_cmd->cm_frame->io.lba_lo;
+	lba_hi = mfi_cmd->cm_frame->io.lba_hi;
+
+	if((num_lba <= 0xFF) && (lba_lo <= 0x1FFFFF))
+	{
+		if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
+			/* Read 6 or Write 6 */
+			cdb[0] = (uint8_t) (0x0A);
+		else
+			cdb[0] = (uint8_t) (0x08);
+
+		cdb[4] = (uint8_t) num_lba;
+		cdb[3] = (uint8_t) (lba_lo & 0xFF);
+		cdb[2] = (uint8_t) (lba_lo >> 8);
+		cdb[1] = (uint8_t) ((lba_lo >> 16) & 0x1F);
+		cdb_len = 6;
+	}
+	else if((num_lba <= 0xFFFF) && (lba_lo <= 0xFFFFFFFF))
+	{
+		if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
+			/* Read 10 or Write 10 */
+			cdb[0] = (uint8_t) (0x2A);
+		else
+			cdb[0] = (uint8_t) (0x28);
+		cdb[8] = (uint8_t) (num_lba & 0xFF);
+		cdb[7] = (uint8_t) (num_lba >> 8);
+		cdb[5] = (uint8_t) (lba_lo & 0xFF);
+		cdb[4] = (uint8_t) (lba_lo >> 8);
+		cdb[3] = (uint8_t) (lba_lo >> 16);
+		cdb[2] = (uint8_t) (lba_lo >> 24);
+		cdb_len = 10;
+	}
+	else if((num_lba > 0xFFFF) && (lba_hi == 0))
+	{
+		if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
+			/* Read 12 or Write 12 */
+			cdb[0] = (uint8_t) (0xAA);
+		else
+			cdb[0] = (uint8_t) (0xA8);
+		cdb[9] = (uint8_t) (num_lba & 0xFF);
+		cdb[8] = (uint8_t) (num_lba >> 8);
+		cdb[7] = (uint8_t) (num_lba >> 16);
+		cdb[6] = (uint8_t) (num_lba >> 24);
+		cdb[5] = (uint8_t) (lba_lo & 0xFF);
+		cdb[4] = (uint8_t) (lba_lo >> 8);
+		cdb[3] = (uint8_t) (lba_lo >> 16);
+		cdb[2] = (uint8_t) (lba_lo >> 24);
+		cdb_len = 12;
+	}
+	else
+	{
+		if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)
+			cdb[0] = (uint8_t) (0x8A);
+		else
+			cdb[0] = (uint8_t) (0x88);
+		cdb[13] = (uint8_t) (num_lba & 0xFF);
+                cdb[12] = (uint8_t) (num_lba >> 8);
+                cdb[11] = (uint8_t) (num_lba >> 16);
+                cdb[10] = (uint8_t) (num_lba >> 24);
+		cdb[9] = (uint8_t) (lba_lo & 0xFF);
+		cdb[8] = (uint8_t) (lba_lo >> 8);
+                cdb[7] = (uint8_t) (lba_lo >> 16);
+                cdb[6] = (uint8_t) (lba_lo >> 24);
+		cdb[5] = (uint8_t) (lba_hi & 0xFF);
+                cdb[4] = (uint8_t) (lba_hi >> 8);
+                cdb[3] = (uint8_t) (lba_hi >> 16);
+                cdb[2] = (uint8_t) (lba_hi >> 24);
+		cdb_len = 16;
+	}
+	return cdb_len;
+}
+
+static int
+mfi_tbolt_make_sgl(struct mfi_softc *sc, struct mfi_command *mfi_cmd,
+		   pMpi25IeeeSgeChain64_t sgl_ptr,struct mfi_cmd_tbolt *cmd)
+{
+	uint8_t i, sg_processed,sg_to_process;
+	uint8_t sge_count, sge_idx;
+	union mfi_sgl *os_sgl;
+
+	/*
+	 * Return 0 if there is no data transfer
+	 */
+	if (!mfi_cmd->cm_sg || !mfi_cmd->cm_len) {
+		device_printf(sc->mfi_dev, "Buffer empty \n");
+		return 0;
+	}
+	os_sgl = mfi_cmd->cm_sg;
+	sge_count = mfi_cmd->cm_frame->header.sg_count;
+
+	if (sge_count > sc->mfi_max_sge) {
+		device_printf(sc->mfi_dev, "sgl ptr %p sg_cnt %d \n",
+		    os_sgl,sge_count);
+		return sge_count;
+	}
+
+	if (sge_count > sc->max_SGEs_in_main_message)
+		/* One element to store the chain info */
+		sge_idx = sc->max_SGEs_in_main_message - 1;
+	else
+		sge_idx = sge_count;
+
+	for (i = 0; i < sge_idx; i++) {
+		/*
+		  For 32bit BSD we are getting 32 bit SGL's from OS
+		  but FW only take 64 bit SGL's so copying from 32 bit
+		  SGL's to 64.
+		*/
+		/*if((sc->mfi_flags & MFI_FLAGS_SG64) == 0)
+		{
+			sgl_ptr->Length = (uint32_t) os_sgl->sg64[0].len;
+			sgl_ptr->Address = (os_sgl->sg64[0].addr);
+		}
+		else*/
+		if (sc->mfi_flags & MFI_FLAGS_SKINNY) {
+			sgl_ptr->Length = os_sgl->sg_skinny[i].len;
+			sgl_ptr->Address = os_sgl->sg_skinny[i].addr;
+		} else {
+			sgl_ptr->Length = os_sgl->sg32[i].len;
+			sgl_ptr->Address = os_sgl->sg32[i].addr;
+		}
+		sgl_ptr->Flags = 0;
+		sgl_ptr++;
+		cmd->io_request->ChainOffset = 0;
+	}
+
+	sg_processed = i;
+
+	if (sg_processed < sge_count) {
+		pMpi25IeeeSgeChain64_t sg_chain;
+		sg_to_process = sge_count - sg_processed;
+		cmd->io_request->ChainOffset =
+		    sc->chain_offset_value_for_main_message;
+		sg_chain = sgl_ptr;
+		/* Prepare chain element */
+		sg_chain->NextChainOffset = 0;
+		sg_chain->Flags = (MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT |
+		    MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR);
+		sg_chain->Length =  (sizeof(MPI2_SGE_IO_UNION) *
+		    (sge_count - sg_processed));
+		sg_chain->Address = cmd->sg_frame_phys_addr;
+		sgl_ptr = (pMpi25IeeeSgeChain64_t)cmd->sg_frame;
+		for (; i < sge_count; i++) {
+			if (sc->mfi_flags & MFI_FLAGS_SKINNY) {
+				sgl_ptr->Length = os_sgl->sg_skinny[i].len;
+				sgl_ptr->Address = os_sgl->sg_skinny[i].addr;
+			} else {
+				sgl_ptr->Length = os_sgl->sg32[i].len;
+				sgl_ptr->Address = os_sgl->sg32[i].addr;
+			}
+			sgl_ptr->Flags = 0;
+			sgl_ptr++;
+		}
+	}
+	return sge_count;
+}
+
+union mfi_mpi2_request_descriptor *
+mfi_build_and_issue_cmd(struct mfi_softc *sc, struct mfi_command *mfi_cmd)
+{
+	struct mfi_cmd_tbolt *cmd;
+	union mfi_mpi2_request_descriptor *req_desc = NULL;
+	uint16_t index;
+	cmd = mfi_tbolt_get_cmd(sc);
+	if (!cmd)
+		return NULL;
+	mfi_cmd->cm_extra_frames = cmd->index;
+	cmd->sync_cmd_idx = mfi_cmd->cm_index;
+
+	index = cmd->index;
+	req_desc = mfi_tbolt_get_request_descriptor(sc, index-1);
+	//req_desc->Words = 0;
+	if(mfi_tbolt_build_io(sc, mfi_cmd, cmd))
+		return NULL;
+	req_desc->header.SMID = index;
+	return req_desc;
+}
+
+union mfi_mpi2_request_descriptor *
+mfi_tbolt_build_mpt_cmd(struct mfi_softc *sc, struct mfi_command *cmd)
+{
+	union mfi_mpi2_request_descriptor *req_desc = NULL;
+	uint16_t index;
+	if (mfi_build_mpt_pass_thru(sc, cmd)) {
+		device_printf(sc->mfi_dev, "Couldn't build MFI pass thru "
+		    "cmd\n");
+		return NULL;
+	}
+	/* For fusion the frame_count variable is used for SMID */
+	index = cmd->cm_extra_frames;
+
+	req_desc = mfi_tbolt_get_request_descriptor(sc, index - 1);
+	if(!req_desc)
+		return NULL;
+
+	bzero(req_desc, sizeof(req_desc));
+	req_desc->header.RequestFlags = (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
+	    MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+	req_desc->header.SMID = index;
+	return req_desc;
+}
+
+int
+mfi_tbolt_send_frame(struct mfi_softc *sc, struct mfi_command *cm)
+{
+	struct mfi_frame_header *hdr;
+	uint8_t *cdb;
+	union mfi_mpi2_request_descriptor *req_desc = NULL;
+	int tm = MFI_POLL_TIMEOUT_SECS * 1000;
+
+	hdr = &cm->cm_frame->header;
+	cdb = cm->cm_frame->pass.cdb;
+	if(sc->adpreset)
+		return 1;
+	if ((cm->cm_flags & MFI_CMD_POLLED) == 0) {
+		cm->cm_timestamp = time_second;
+		mfi_enqueue_busy(cm);
+	}
+	else {
+		hdr->cmd_status = 0xff;
+		hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
+	}
+
+	if (hdr->cmd == MFI_CMD_PD_SCSI_IO) {
+		/* check for inquiry commands coming from CLI */
+		if (cdb[0] != 0x28 || cdb[0] != 0x2A) {
+			if ((req_desc = mfi_tbolt_build_mpt_cmd(sc, cm)) ==
+			    NULL) {
+				device_printf(sc->mfi_dev, "Mapping from MFI "
+				    "to MPT Failed \n");
+				return 1;
+			}
+		}
+		else
+			device_printf(sc->mfi_dev, "DJA NA XXX SYSPDIO\n");
+	}
+	else if (hdr->cmd == MFI_CMD_LD_SCSI_IO ||
+	    hdr->cmd == MFI_CMD_LD_READ || hdr->cmd == MFI_CMD_LD_WRITE) {
+		if ((req_desc = mfi_build_and_issue_cmd(sc, cm)) == NULL) {
+			device_printf(sc->mfi_dev, "LDIO Failed \n");
+			return 1;
+		}
+	} else
+		if ((req_desc = mfi_tbolt_build_mpt_cmd(sc, cm)) == NULL) {
+			device_printf(sc->mfi_dev, "Mapping from MFI to MPT "
+			    "Failed\n");
+			return 1;
+		}
+	MFI_WRITE4(sc, MFI_ILQP, (req_desc->words & 0xFFFFFFFF));
+	MFI_WRITE4(sc, MFI_IHQP, (req_desc->words >>0x20));
+
+	if ((cm->cm_flags & MFI_CMD_POLLED) == 0)
+		return 0;
+
+	/* This is a polled command, so busy-wait for it to complete. */
+	while (hdr->cmd_status == 0xff) {
+		DELAY(1000);
+		tm -= 1;
+		if (tm <= 0)
+			break;
+	}
+
+	if (hdr->cmd_status == 0xff) {
+		device_printf(sc->mfi_dev, "Frame %p timed out "
+		      "command 0x%X\n", hdr, cm->cm_frame->dcmd.opcode);
+		return (ETIMEDOUT);
+	}
+	return 0;
+}
+
+static void mfi_issue_pending_cmds_again (struct mfi_softc *sc)
+{
+	struct mfi_command *cm,*tmp;
+
+	KKASSERT(lockstatus(&sc->mfi_io_lock, curthread) != 0);
+	TAILQ_FOREACH_REVERSE_MUTABLE(cm, &sc->mfi_busy, BUSYQ, cm_link, tmp) {
+
+		cm->retry_for_fw_reset++;
+
+		/*
+		 * If a command has continuously been tried multiple times
+		 * and causing a FW reset condition, no further recoveries
+		 * should be performed on the controller
+		 */
+		if (cm->retry_for_fw_reset == 3) {
+			device_printf(sc->mfi_dev,"megaraid_sas: command %d "
+			    "was tried multiple times during adapter reset"
+			    "Shutting down the HBA\n", cm->cm_index);
+			mfi_kill_hba(sc);
+			sc->hw_crit_error = 1;
+			return;
+		}
+
+		if ((cm->cm_flags & MFI_ON_MFIQ_BUSY) != 0) {
+			struct mfi_cmd_tbolt *cmd;
+			mfi_remove_busy(cm);
+			cmd = sc->mfi_cmd_pool_tbolt[cm->cm_extra_frames -
+			    1 ];
+			mfi_tbolt_return_cmd(sc, cmd);
+			if ((cm->cm_flags & MFI_ON_MFIQ_MASK) == 0) {
+				if (cm->cm_frame->dcmd.opcode !=
+				    MFI_DCMD_CTRL_EVENT_WAIT) {
+					device_printf(sc->mfi_dev,
+					    "APJ ****requeue command %d \n",
+					    cm->cm_index);
+					mfi_requeue_ready(cm);
+				}
+			}
+			else
+				mfi_release_command(cm);
+		}
+	}
+	mfi_startio(sc);
+}
+
+static void mfi_kill_hba (struct mfi_softc *sc)
+{
+	if (sc->mfi_flags & MFI_FLAGS_TBOLT)
+		MFI_WRITE4 (sc, 0x00,MFI_STOP_ADP);
+	else
+		MFI_WRITE4 (sc, MFI_IDB,MFI_STOP_ADP);
+}
+
+static void mfi_process_fw_state_chg_isr(void *arg)
+{
+	struct mfi_softc *sc= (struct mfi_softc *)arg;
+	struct mfi_cmd_tbolt *cmd;
+	int error, status;
+
+	if (sc->adpreset == 1) {
+		device_printf(sc->mfi_dev,"First stage of FW reset "
+		     "initiated...\n");
+
+		sc->mfi_adp_reset(sc);
+		sc->mfi_enable_intr(sc);
+
+		device_printf(sc->mfi_dev,"First stage of reset complete, "
+		    "second stage initiated...\n");
+
+		sc->adpreset = 2;
+
+		/* waiting for about 20 second before start the second init */
+		for(int wait = 0; wait < 20000; wait++)
+			DELAY(1000);
+		device_printf(sc->mfi_dev,"Second stage of FW reset "
+		     "initiated...\n");
+		while((status = MFI_READ4(sc, MFI_RSR)) & 0x04);
+
+		sc->mfi_disable_intr(sc);
+
+		/* We expect the FW state to be READY */
+		if (mfi_transition_firmware(sc)) {
+			device_printf(sc->mfi_dev,"controller is not in ready "
+			    "state\n");
+			mfi_kill_hba(sc);
+			sc->hw_crit_error= 1;
+			return ;
+		}
+		if ((error = mfi_tbolt_init_MFI_queue(sc)) != 0)
+				return;
+
+		lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
+
+		sc->mfi_enable_intr(sc);
+		sc->adpreset = 0;
+		kfree(sc->mfi_aen_cm->cm_data, M_MFIBUF);
+		mfi_remove_busy(sc->mfi_aen_cm);
+		cmd = sc->mfi_cmd_pool_tbolt[sc->mfi_aen_cm->cm_extra_frames
+		    - 1];
+		mfi_tbolt_return_cmd(sc, cmd);
+		if (sc->mfi_aen_cm) {
+			mfi_release_command(sc->mfi_aen_cm);
+			sc->mfi_aen_cm = NULL;
+		}
+		if (sc->map_update_cmd) {
+			mfi_release_command(sc->map_update_cmd);
+			sc->map_update_cmd = NULL;
+		}
+		mfi_issue_pending_cmds_again(sc);
+
+		/*
+		 * Issue pending command can result in adapter being marked
+		 * dead because of too many re-tries. Check for that
+		 * condition before clearing the reset condition on the FW
+		 */
+		if (!sc->hw_crit_error) {
+			/*
+			 * Initiate AEN (Asynchronous Event Notification)
+			 */
+			mfi_aen_setup(sc, sc->last_seq_num);
+			sc->issuepend_done = 1;
+			device_printf(sc->mfi_dev,"second stage of reset "
+			    "complete, FW is ready now.\n");
+		} else {
+			device_printf(sc->mfi_dev,"second stage of reset "
+			     "never completed, hba was marked offline.\n");
+		}
+	} else {
+		device_printf(sc->mfi_dev, "mfi_process_fw_state_chg_isr "
+		    "called with unhandled value:%d\n", sc->adpreset);
+	}
+	lockmgr(&sc->mfi_io_lock, LK_RELEASE);
+}
diff --git a/sys/dev/raid/mfi/mfireg.h b/sys/dev/raid/mfi/mfireg.h
index d64af71..1bf200f 100644
--- a/sys/dev/raid/mfi/mfireg.h
+++ b/sys/dev/raid/mfi/mfireg.h
@@ -48,36 +48,6 @@
  * 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.
- */
-/*-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *            Copyright 1994-2009 The FreeBSD Project.
- *            All rights reserved.
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- *    THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT``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 FREEBSD PROJECT 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.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies,either expressed or implied, of the FreeBSD Project.
  *
  * $FreeBSD: src/sys/dev/mfi/mfireg.h,v 1.16 2011/07/14 20:20:33 jhb Exp $
  */
@@ -94,6 +64,8 @@
  * seems to also call this interface 'MFI', so that will be used here.
  */
 
+#define MEGAMFI_FRAME_SIZE              64
+
 /*
  * Start with the register set.  All registers are 32 bits wide.
  * The usual Intel IOP style setup.
@@ -112,6 +84,14 @@
 #define MFI_OQP		0x44	/* Outbound queue port */
 
 /*
+ * ThunderBolt specific Register
+ */
+
+#define MFI_RPI		0x6c 		/* reply_post_host_index */
+#define MFI_ILQP 	0xc0		/* inbound_low_queue_port */
+#define MFI_IHQP 	0xc4		/* inbound_high_queue_port */
+
+/*
  * 1078 specific related register
  */
 #define MFI_ODR0	0x9c 		/* outbound doorbell register0 */
@@ -122,6 +102,11 @@
 #define MFI_1078_RM	0x80000000 	/* reply 1078 message interrupt  */
 #define MFI_ODC		0x4 		/* outbound doorbell change interrupt */
 
+/* OCR registers */
+#define MFI_WSR		0x004		/* write sequence register */
+#define MFI_HDR		0x008		/* host diagnostic register */
+#define MFI_RSR		0x3c3		/* Reset Status Register */
+
 /*
  * GEN2 specific changes
  */
@@ -129,12 +114,6 @@
 #define MFI_GEN2_RM	0x00000001	/* reply GEN2 message interrupt */
 
 /*
- * gen2 specific changes
- */
-#define MFI_GEN2_EIM	0x00000005	/* gen2 enable interrupt mask */
-#define MFI_GEN2_RM	0x00000001	/* reply gen2 message interrupt */
-
-/*
  * skinny specific changes
  */
 #define MFI_SKINNY_IDB	0x00	/* Inbound doorbell is at 0x00 for skinny */
@@ -145,6 +124,10 @@
 /* Bits for MFI_OSTS */
 #define MFI_OSTS_INTR_VALID	0x00000002
 
+/* OCR specific flags */
+#define MFI_FIRMWARE_STATE_CHANGE	0x00000002
+#define MFI_STATE_CHANGE_INTERRUPT	0x00000004  /* MFI state change interrrupt */
+
 /*
  * Firmware state values.  Found in OMSG0 during initialization.
  */
@@ -164,6 +147,14 @@
 #define MFI_FWSTATE_MAXCMD_MASK		0x0000ffff
 #define MFI_FWSTATE_HOSTMEMREQD_MASK	0x08000000
 #define MFI_FWSTATE_BOOT_MESSAGE_PENDING	0x90000000
+#define MFI_RESET_REQUIRED		0x00000001
+
+/* ThunderBolt Support */
+#define MFI_FWSTATE_TB_MASK		0xf0000000
+#define MFI_FWSTATE_TB_RESET		0x00000000
+#define MFI_FWSTATE_TB_READY		0x10000000
+#define MFI_FWSTATE_TB_OPERATIONAL	0x20000000
+#define MFI_FWSTATE_TB_FAULT		0x40000000
 
 /*
  * Control bits to drive the card to ready state.  These go into the IDB
@@ -175,6 +166,12 @@
 #define MFI_FWINIT_CLEAR_HANDSHAKE 0x00000008 /* Respond to WAIT_HANDSHAKE */
 #define MFI_FWINIT_HOTPLUG	0x00000010
 
+/* ADP reset flags */
+#define MFI_STOP_ADP		0x00000020
+#define MFI_ADP_RESET		0x00000040
+#define DIAG_WRITE_ENABLE	0x00000080
+#define DIAG_RESET_ADAPTER	0x00000004
+
 /* MFI Commands */
 typedef enum {
 	MFI_CMD_INIT =		0x00,
@@ -220,6 +217,8 @@ typedef enum {
 	MFI_DCMD_PD_GET_PROGRESS =	0x02060000,
 	MFI_DCMD_PD_LOCATE_START =	0x02070100,
 	MFI_DCMD_PD_LOCATE_STOP =	0x02070200,
+	MFI_DCMD_LD_MAP_GET_INFO =	0x0300e101,
+	MFI_DCMD_LD_SYNC =		0x0300e102,
 	MFI_DCMD_LD_GET_LIST =		0x03010000,
 	MFI_DCMD_LD_GET_INFO =		0x03020000,
 	MFI_DCMD_LD_GET_PROP =		0x03030000,
@@ -262,6 +261,37 @@ typedef enum {
 #define MFI_FRAME_DIR_BOTH			0x0018
 #define MFI_FRAME_IEEE_SGL			0x0020
 
+/* ThunderBolt Specific */
+
+/*
+ * Pre-TB command size and TB command size.
+ * We will be checking it at the load time for the time being
+ */
+#define MR_COMMAND_SIZE (MFI_FRAME_SIZE*20) /* 1280 bytes */
+
+#define MEGASAS_THUNDERBOLT_MSG_ALLIGNMENT  256
+/*
+ * We are defining only 128 byte message to reduce memory move over head
+ * and also it will reduce the SRB extension size by 128byte compared with
+ * 256 message size
+ */
+#define MEGASAS_THUNDERBOLT_NEW_MSG_SIZE	256
+#define MEGASAS_THUNDERBOLT_MAX_COMMANDS	1024
+#define MEGASAS_THUNDERBOLT_MAX_REPLY_COUNT	1024
+#define MEGASAS_THUNDERBOLT_REPLY_SIZE		8
+#define MEGASAS_THUNDERBOLT_MAX_CHAIN_COUNT	1
+#define MEGASAS_MAX_SZ_CHAIN_FRAME		1024
+
+#define MPI2_FUNCTION_PASSTHRU_IO_REQUEST       0xF0
+#define MPI2_FUNCTION_LD_IO_REQUEST             0xF1
+/* TODO remove this and place the right AEN */
+#define MR_EVT_LD_FAST_PATH_IO_STATUS_CHANGED   (0xFFFF)
+
+#define MR_INTERNAL_MFI_FRAMES_SMID             1
+#define MR_CTRL_EVENT_WAIT_SMID                 2
+#define MR_INTERNAL_DRIVER_RESET_SMID           3
+
+
 /* MFI Status codes */
 typedef enum {
 	MFI_STAT_OK =			0x00,
@@ -406,7 +436,7 @@ typedef enum {
 	MR_PD_QUERY_TYPE_POWER_STATE =	2,
 	MR_PD_QUERY_TYPE_MEDIA_TYPE =	3,
 	MR_PD_QUERY_TYPE_SPEED =	4,
-	MR_PD_QUERY_TYPE_EXPOSED_TO_HOST =	5, /*query for system drives */
+	MR_PD_QUERY_TYPE_EXPOSED_TO_HOST = 5 /*query for system drives */
 } mfi_pd_query_type;
 
 /*
@@ -466,7 +496,7 @@ struct mfi_frame_header {
 	uint32_t	context;
 	/*
 	 * pad0 is MSI Specific. Not used by Driver. Zero the value before
-	 * sending the command to f/w
+	 * sending the command to f/w.
 	 */
 	uint32_t	pad0;
 	uint16_t	flags;
@@ -482,9 +512,29 @@ struct mfi_init_frame {
 	uint32_t	qinfo_new_addr_hi;
 	uint32_t	qinfo_old_addr_lo;
 	uint32_t	qinfo_old_addr_hi;
-	uint32_t	reserved[6];
+	// Start LSIP200113393
+	uint32_t	driver_ver_lo;      /*28h */
+	uint32_t	driver_ver_hi;      /*2Ch */
+
+	uint32_t	reserved[4];
+	// End LSIP200113393
 } __packed;
 
+/*
+ * Define MFI Address Context union.
+ */
+#ifdef MFI_ADDRESS_IS_uint64_t
+    typedef uint64_t     MFI_ADDRESS;
+#else
+    typedef union _MFI_ADDRESS {
+        struct {
+            uint32_t     addressLow;
+            uint32_t     addressHigh;
+        } u;
+        uint64_t     address;
+    } MFI_ADDRESS, *PMFI_ADDRESS;
+#endif
+
 #define MFI_IO_FRAME_SIZE 40
 struct mfi_io_frame {
 	struct mfi_frame_header	header;
@@ -515,6 +565,7 @@ struct mfi_dcmd_frame {
 struct mfi_abort_frame {
 	struct mfi_frame_header header;
 	uint32_t	abort_context;
+	/* pad is changed to reserved.*/
 	uint32_t	reserved0;
 	uint32_t	abort_mfi_addr_lo;
 	uint32_t	abort_mfi_addr_hi;
@@ -543,6 +594,7 @@ struct mfi_stp_frame {
 union mfi_frame {
 	struct mfi_frame_header header;
 	struct mfi_init_frame	init;
+	/* ThunderBolt Initialization */
 	struct mfi_io_frame	io;
 	struct mfi_pass_frame	pass;
 	struct mfi_dcmd_frame	dcmd;
@@ -592,7 +644,61 @@ struct mfi_ctrl_props {
 	uint16_t	ecc_bucket_leak_rate;
 	uint8_t		restore_hotspare_on_insertion;
 	uint8_t		expose_encl_devices;
-	uint8_t		reserved[38];
+	uint8_t		maintainPdFailHistory;
+	uint8_t		disallowHostRequestReordering;
+	/* set TRUE to abort CC on detecting an inconsistency */
+	uint8_t		abortCCOnError;
+	/* load balance mode (MR_LOAD_BALANCE_MODE) */
+	uint8_t		loadBalanceMode;
+	/*
+	 * 0 - use auto detect logic of backplanes like SGPIO, i2c SEP using
+	 *     h/w mechansim like GPIO pins
+	 * 1 - disable auto detect SGPIO,
+	 * 2 - disable i2c SEP auto detect
+	 * 3 - disable both auto detect
+	 */
+	uint8_t		disableAutoDetectBackplane;
+	/*
+	 * % of source LD to be reserved for a VDs snapshot in snapshot
+	 * repository, for metadata and user data: 1=5%, 2=10%, 3=15% and so on
+	 */
+	uint8_t		snapVDSpace;
+
+	/*
+	 * Add properties that can be controlled by a bit in the following
+	 * structure.
+	 */
+	struct {
+		/* set TRUE to disable copyBack (0=copback enabled) */
+		uint32_t	copyBackDisabled		:1;
+		uint32_t	SMARTerEnabled			:1;
+		uint32_t	prCorrectUnconfiguredAreas	:1;
+		uint32_t	useFdeOnly			:1;
+		uint32_t	disableNCQ			:1;
+		uint32_t	SSDSMARTerEnabled		:1;
+		uint32_t	SSDPatrolReadEnabled		:1;
+		uint32_t	enableSpinDownUnconfigured	:1;
+		uint32_t	autoEnhancedImport		:1;
+		uint32_t	enableSecretKeyControl		:1;
+		uint32_t	disableOnlineCtrlReset		:1;
+		uint32_t	allowBootWithPinnedCache	:1;
+		uint32_t	disableSpinDownHS		:1;
+		uint32_t	enableJBOD			:1;
+		uint32_t	reserved			:18;
+	} OnOffProperties;
+	/*
+	 * % of source LD to be reserved for auto snapshot in snapshot
+	 * repository, for metadata and user data: 1=5%, 2=10%, 3=15% and so on.
+	 */
+	uint8_t		autoSnapVDSpace;
+	/*
+	 * Snapshot writeable VIEWs capacity as a % of source LD capacity:
+	 * 0=READ only, 1=5%, 2=10%, 3=15% and so on.
+	 */
+	uint8_t		viewSpace;
+	/* # of idle minutes before device is spun down (0=use FW defaults) */
+	uint16_t	spinDownTime;
+	uint8_t		reserved[24];
 } __packed;
 
 /* PCI information about the card. */
@@ -1152,7 +1258,7 @@ struct mfi_ld_info {
 	uint8_t			reserved2[16];
 } __packed;
 
-#define MAX_ARRAYS 16
+#define MAX_ARRAYS 128
 struct mfi_spare {
 	union mfi_pd_ref	ref;
 	uint8_t			spare_type;
@@ -1301,6 +1407,452 @@ struct mfi_pr_properties {
 	uint32_t		clear_freq;
 };
 
+/* ThunderBolt support */
+
+/*
+ * Raid Context structure which describes MegaRAID specific IO Paramenters
+ * This resides at offset 0x60 where the SGL normally starts in MPT IO Frames
+ */
+typedef struct _MPI2_SCSI_IO_VENDOR_UNIQUE {
+	uint16_t	resvd0;		/* 0x00 - 0x01 */
+	uint16_t	timeoutValue;	/* 0x02 - 0x03 */
+	uint8_t		regLockFlags;
+	uint8_t		armId;
+	uint16_t	TargetID;	/* 0x06 - 0x07 */
+
+	uint64_t	RegLockLBA;	/* 0x08 - 0x0F */
+
+	uint32_t	RegLockLength;	/* 0x10 - 0x13 */
+
+	uint16_t	SMID;		/* 0x14 - 0x15 nextLMId */
+	uint8_t		exStatus;	/* 0x16 */
+	uint8_t		Status;		/* 0x17 status */
+
+	uint8_t		RAIDFlags;	/* 0x18 */
+	uint8_t		numSGE;		/* 0x19 numSge */
+	uint16_t	configSeqNum;	/* 0x1A - 0x1B */
+	uint8_t		spanArm;	/* 0x1C */
+	uint8_t		resvd2[3];	/* 0x1D - 0x1F */
+} MPI2_SCSI_IO_VENDOR_UNIQUE, MPI25_SCSI_IO_VENDOR_UNIQUE;
+
+/*** DJA *****/
+
+/*****************************************************************************
+*
+*        Message Functions
+*
+*****************************************************************************/
+
+#define NA_MPI2_FUNCTION_SCSI_IO_REQUEST            (0x00) /* SCSI IO */
+#define MPI2_FUNCTION_SCSI_TASK_MGMT                (0x01) /* SCSI Task Management */
+#define MPI2_FUNCTION_IOC_INIT                      (0x02) /* IOC Init */
+#define MPI2_FUNCTION_IOC_FACTS                     (0x03) /* IOC Facts */
+#define MPI2_FUNCTION_CONFIG                        (0x04) /* Configuration */
+#define MPI2_FUNCTION_PORT_FACTS                    (0x05) /* Port Facts */
+#define MPI2_FUNCTION_PORT_ENABLE                   (0x06) /* Port Enable */
+#define MPI2_FUNCTION_EVENT_NOTIFICATION            (0x07) /* Event Notification */
+#define MPI2_FUNCTION_EVENT_ACK                     (0x08) /* Event Acknowledge */
+#define MPI2_FUNCTION_FW_DOWNLOAD                   (0x09) /* FW Download */
+#define MPI2_FUNCTION_TARGET_ASSIST                 (0x0B) /* Target Assist */
+#define MPI2_FUNCTION_TARGET_STATUS_SEND            (0x0C) /* Target Status Send */
+#define MPI2_FUNCTION_TARGET_MODE_ABORT             (0x0D) /* Target Mode Abort */
+#define MPI2_FUNCTION_FW_UPLOAD                     (0x12) /* FW Upload */
+#define MPI2_FUNCTION_RAID_ACTION                   (0x15) /* RAID Action */
+#define MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH      (0x16) /* SCSI IO RAID Passthrough */
+#define MPI2_FUNCTION_TOOLBOX                       (0x17) /* Toolbox */
+#define MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR      (0x18) /* SCSI Enclosure Processor */
+#define MPI2_FUNCTION_SMP_PASSTHROUGH               (0x1A) /* SMP Passthrough */
+#define MPI2_FUNCTION_SAS_IO_UNIT_CONTROL           (0x1B) /* SAS IO Unit Control */
+#define MPI2_FUNCTION_SATA_PASSTHROUGH              (0x1C) /* SATA Passthrough */
+#define MPI2_FUNCTION_DIAG_BUFFER_POST              (0x1D) /* Diagnostic Buffer Post */
+#define MPI2_FUNCTION_DIAG_RELEASE                  (0x1E) /* Diagnostic Release */
+#define MPI2_FUNCTION_TARGET_CMD_BUF_BASE_POST      (0x24) /* Target Command Buffer Post Base */
+#define MPI2_FUNCTION_TARGET_CMD_BUF_LIST_POST      (0x25) /* Target Command Buffer Post List */
+#define MPI2_FUNCTION_RAID_ACCELERATOR              (0x2C) /* RAID Accelerator */
+#define MPI2_FUNCTION_HOST_BASED_DISCOVERY_ACTION   (0x2F) /* Host Based Discovery Action */
+#define MPI2_FUNCTION_PWR_MGMT_CONTROL              (0x30) /* Power Management Control */
+#define MPI2_FUNCTION_MIN_PRODUCT_SPECIFIC          (0xF0) /* beginning of product-specific range */
+#define MPI2_FUNCTION_MAX_PRODUCT_SPECIFIC          (0xFF) /* end of product-specific range */
+
+/* Doorbell functions */
+#define MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET        (0x40)
+#define MPI2_FUNCTION_HANDSHAKE                     (0x42)
+
+/*****************************************************************************
+*
+*        MPI Version Definitions
+*
+*****************************************************************************/
+
+#define MPI2_VERSION_MAJOR                  (0x02)
+#define MPI2_VERSION_MINOR                  (0x00)
+#define MPI2_VERSION_MAJOR_MASK             (0xFF00)
+#define MPI2_VERSION_MAJOR_SHIFT            (8)
+#define MPI2_VERSION_MINOR_MASK             (0x00FF)
+#define MPI2_VERSION_MINOR_SHIFT            (0)
+#define MPI2_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) |   \
+                                      MPI2_VERSION_MINOR)
+
+#define MPI2_VERSION_02_00                  (0x0200)
+
+/* versioning for this MPI header set */
+#define MPI2_HEADER_VERSION_UNIT            (0x10)
+#define MPI2_HEADER_VERSION_DEV             (0x00)
+#define MPI2_HEADER_VERSION_UNIT_MASK       (0xFF00)
+#define MPI2_HEADER_VERSION_UNIT_SHIFT      (8)
+#define MPI2_HEADER_VERSION_DEV_MASK        (0x00FF)
+#define MPI2_HEADER_VERSION_DEV_SHIFT       (0)
+#define MPI2_HEADER_VERSION ((MPI2_HEADER_VERSION_UNIT << 8) |		\
+					MPI2_HEADER_VERSION_DEV)
+
+
+/* IOCInit Request message */
+struct MPI2_IOC_INIT_REQUEST {
+	uint8_t		WhoInit;                        /* 0x00 */
+	uint8_t		Reserved1;                      /* 0x01 */
+	uint8_t		ChainOffset;                    /* 0x02 */
+	uint8_t		Function;                       /* 0x03 */
+	uint16_t	Reserved2;                      /* 0x04 */
+	uint8_t		Reserved3;                      /* 0x06 */
+	uint8_t		MsgFlags;                       /* 0x07 */
+	uint8_t		VP_ID;                          /* 0x08 */
+	uint8_t		VF_ID;                          /* 0x09 */
+	uint16_t	Reserved4;                      /* 0x0A */
+	uint16_t	MsgVersion;                     /* 0x0C */
+	uint16_t	HeaderVersion;                  /* 0x0E */
+	uint32_t	Reserved5;                      /* 0x10 */
+	uint16_t	Reserved6;                      /* 0x14 */
+	uint8_t		Reserved7;                      /* 0x16 */
+	uint8_t		HostMSIxVectors;                /* 0x17 */
+	uint16_t	Reserved8;                      /* 0x18 */
+	uint16_t	SystemRequestFrameSize;         /* 0x1A */
+	uint16_t	ReplyDescriptorPostQueueDepth;  /* 0x1C */
+	uint16_t	ReplyFreeQueueDepth;            /* 0x1E */
+	uint32_t	SenseBufferAddressHigh;         /* 0x20 */
+	uint32_t	SystemReplyAddressHigh;         /* 0x24 */
+	uint64_t	SystemRequestFrameBaseAddress;  /* 0x28 */
+	uint64_t	ReplyDescriptorPostQueueAddress;/* 0x30 */
+	uint64_t	ReplyFreeQueueAddress;          /* 0x38 */
+	uint64_t	TimeStamp;                      /* 0x40 */
+};
+
+/* WhoInit values */
+#define MPI2_WHOINIT_NOT_INITIALIZED            (0x00)
+#define MPI2_WHOINIT_SYSTEM_BIOS                (0x01)
+#define MPI2_WHOINIT_ROM_BIOS                   (0x02)
+#define MPI2_WHOINIT_PCI_PEER                   (0x03)
+#define MPI2_WHOINIT_HOST_DRIVER                (0x04)
+#define MPI2_WHOINIT_MANUFACTURER               (0x05)
+
+struct MPI2_SGE_CHAIN_UNION {
+	uint16_t	Length;
+	uint8_t		NextChainOffset;
+	uint8_t		Flags;
+	union {
+		uint32_t	Address32;
+		uint64_t	Address64;
+	} u;
+};
+
+struct MPI2_IEEE_SGE_SIMPLE32 {
+	uint32_t	Address;
+	uint32_t	FlagsLength;
+};
+
+struct MPI2_IEEE_SGE_SIMPLE64 {
+	uint64_t	Address;
+	uint32_t	Length;
+	uint16_t	Reserved1;
+	uint8_t		Reserved2;
+	uint8_t		Flags;
+};
+
+typedef union _MPI2_IEEE_SGE_SIMPLE_UNION {
+	struct MPI2_IEEE_SGE_SIMPLE32	Simple32;
+	struct MPI2_IEEE_SGE_SIMPLE64	Simple64;
+} MPI2_IEEE_SGE_SIMPLE_UNION;
+
+typedef struct _MPI2_SGE_SIMPLE_UNION {
+	uint32_t	FlagsLength;
+	union {
+		uint32_t	Address32;
+		uint64_t	Address64;
+	} u;
+} MPI2_SGE_SIMPLE_UNION;
+
+/****************************************************************************
+*  IEEE SGE field definitions and masks
+****************************************************************************/
+
+/* Flags field bit definitions */
+
+#define MPI2_IEEE_SGE_FLAGS_ELEMENT_TYPE_MASK   (0x80)
+
+#define MPI2_IEEE32_SGE_FLAGS_SHIFT             (24)
+
+#define MPI2_IEEE32_SGE_LENGTH_MASK             (0x00FFFFFF)
+
+/* Element Type */
+
+#define MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT      (0x00)
+#define MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT       (0x80)
+
+/* Data Location Address Space */
+
+#define MPI2_IEEE_SGE_FLAGS_ADDR_MASK           (0x03)
+#define MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR         (0x00)
+#define MPI2_IEEE_SGE_FLAGS_IOCDDR_ADDR         (0x01)
+#define MPI2_IEEE_SGE_FLAGS_IOCPLB_ADDR         (0x02)
+#define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR      (0x03)
+
+/* Address Size */
+
+#define MPI2_SGE_FLAGS_32_BIT_ADDRESSING        (0x00)
+#define MPI2_SGE_FLAGS_64_BIT_ADDRESSING        (0x02)
+
+/*******************/
+/* SCSI IO Control bits */
+#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_MASK      (0xFC000000)
+#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT     (26)
+
+#define MPI2_SCSIIO_CONTROL_DATADIRECTION_MASK  (0x03000000)
+#define MPI2_SCSIIO_CONTROL_NODATATRANSFER      (0x00000000)
+#define MPI2_SCSIIO_CONTROL_WRITE               (0x01000000)
+#define MPI2_SCSIIO_CONTROL_READ                (0x02000000)
+#define MPI2_SCSIIO_CONTROL_BIDIRECTIONAL       (0x03000000)
+
+#define MPI2_SCSIIO_CONTROL_TASKPRI_MASK        (0x00007800)
+#define MPI2_SCSIIO_CONTROL_TASKPRI_SHIFT       (11)
+
+#define MPI2_SCSIIO_CONTROL_TASKATTRIBUTE_MASK  (0x00000700)
+#define MPI2_SCSIIO_CONTROL_SIMPLEQ             (0x00000000)
+#define MPI2_SCSIIO_CONTROL_HEADOFQ             (0x00000100)
+#define MPI2_SCSIIO_CONTROL_ORDEREDQ            (0x00000200)
+#define MPI2_SCSIIO_CONTROL_ACAQ                (0x00000400)
+
+#define MPI2_SCSIIO_CONTROL_TLR_MASK            (0x000000C0)
+#define MPI2_SCSIIO_CONTROL_NO_TLR              (0x00000000)
+#define MPI2_SCSIIO_CONTROL_TLR_ON              (0x00000040)
+#define MPI2_SCSIIO_CONTROL_TLR_OFF             (0x00000080)
+
+/*******************/
+
+typedef struct {
+	uint8_t		CDB[20];                    /* 0x00 */
+	uint32_t	PrimaryReferenceTag;        /* 0x14 */
+	uint16_t	PrimaryApplicationTag;      /* 0x18 */
+	uint16_t	PrimaryApplicationTagMask;  /* 0x1A */
+	uint32_t	TransferLength;             /* 0x1C */
+} MPI2_SCSI_IO_CDB_EEDP32;
+
+
+typedef union _MPI2_IEEE_SGE_CHAIN_UNION {
+	struct MPI2_IEEE_SGE_SIMPLE32	Chain32;
+	struct MPI2_IEEE_SGE_SIMPLE64	Chain64;
+} MPI2_IEEE_SGE_CHAIN_UNION;
+
+typedef union _MPI2_SIMPLE_SGE_UNION {
+	MPI2_SGE_SIMPLE_UNION		MpiSimple;
+	MPI2_IEEE_SGE_SIMPLE_UNION	IeeeSimple;
+} MPI2_SIMPLE_SGE_UNION;
+
+typedef union _MPI2_SGE_IO_UNION {
+	MPI2_SGE_SIMPLE_UNION		MpiSimple;
+	struct MPI2_SGE_CHAIN_UNION	MpiChain;
+	MPI2_IEEE_SGE_SIMPLE_UNION	IeeeSimple;
+	MPI2_IEEE_SGE_CHAIN_UNION	IeeeChain;
+} MPI2_SGE_IO_UNION;
+
+typedef union {
+	uint8_t			CDB32[32];
+	MPI2_SCSI_IO_CDB_EEDP32	EEDP32;
+	MPI2_SGE_SIMPLE_UNION	SGE;
+} MPI2_SCSI_IO_CDB_UNION;
+
+
+/* MPI 2.5 SGLs */
+
+#define MPI25_IEEE_SGE_FLAGS_END_OF_LIST        (0x40)
+
+typedef struct _MPI25_IEEE_SGE_CHAIN64 {
+	uint64_t	Address;
+	uint32_t	Length;
+	uint16_t	Reserved1;
+	uint8_t		NextChainOffset;
+	uint8_t		Flags;
+} MPI25_IEEE_SGE_CHAIN64, *pMpi25IeeeSgeChain64_t;
+
+/* use MPI2_IEEE_SGE_FLAGS_ defines for the Flags field */
+
+
+/********/
+
+/*
+ * RAID SCSI IO Request Message
+ * Total SGE count will be one less than  _MPI2_SCSI_IO_REQUEST
+ */
+struct mfi_mpi2_request_raid_scsi_io {
+	uint16_t		DevHandle;                      /* 0x00 */
+	uint8_t			ChainOffset;                    /* 0x02 */
+	uint8_t			Function;                       /* 0x03 */
+	uint16_t		Reserved1;                      /* 0x04 */
+	uint8_t			Reserved2;                      /* 0x06 */
+	uint8_t			MsgFlags;                       /* 0x07 */
+	uint8_t			VP_ID;                          /* 0x08 */
+	uint8_t			VF_ID;                          /* 0x09 */
+	uint16_t		Reserved3;                      /* 0x0A */
+	uint32_t		SenseBufferLowAddress;          /* 0x0C */
+	uint16_t		SGLFlags;                       /* 0x10 */
+	uint8_t			SenseBufferLength;              /* 0x12 */
+	uint8_t			Reserved4;                      /* 0x13 */
+	uint8_t			SGLOffset0;                     /* 0x14 */
+	uint8_t			SGLOffset1;                     /* 0x15 */
+	uint8_t			SGLOffset2;                     /* 0x16 */
+	uint8_t			SGLOffset3;                     /* 0x17 */
+	uint32_t		SkipCount;                      /* 0x18 */
+	uint32_t		DataLength;                     /* 0x1C */
+	uint32_t		BidirectionalDataLength;        /* 0x20 */
+	uint16_t		IoFlags;                        /* 0x24 */
+	uint16_t		EEDPFlags;                      /* 0x26 */
+	uint32_t		EEDPBlockSize;                  /* 0x28 */
+	uint32_t		SecondaryReferenceTag;          /* 0x2C */
+	uint16_t		SecondaryApplicationTag;        /* 0x30 */
+	uint16_t		ApplicationTagTranslationMask;  /* 0x32 */
+	uint8_t			LUN[8];                         /* 0x34 */
+	uint32_t		Control;                        /* 0x3C */
+	MPI2_SCSI_IO_CDB_UNION	CDB;                            /* 0x40 */
+	MPI2_SCSI_IO_VENDOR_UNIQUE	RaidContext;              /* 0x60 */
+	MPI2_SGE_IO_UNION	SGL;                            /* 0x80 */
+} __packed;
+
+/*
+ * MPT RAID MFA IO Descriptor.
+ */
+typedef struct _MFI_RAID_MFA_IO_DESCRIPTOR {
+	uint32_t	RequestFlags : 8;
+	uint32_t	MessageAddress1 : 24; /* bits 31:8*/
+	uint32_t	MessageAddress2;      /* bits 61:32 */
+} MFI_RAID_MFA_IO_REQUEST_DESCRIPTOR,*PMFI_RAID_MFA_IO_REQUEST_DESCRIPTOR;
+
+struct mfi_mpi2_request_header {
+	uint8_t		RequestFlags;       /* 0x00 */
+	uint8_t		MSIxIndex;          /* 0x01 */
+	uint16_t	SMID;               /* 0x02 */
+	uint16_t	LMID;               /* 0x04 */
+};
+
+/* defines for the RequestFlags field */
+#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK               (0x0E)
+#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO                 (0x00)
+#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET             (0x02)
+#define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY           (0x06)
+#define MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE            (0x08)
+#define MPI2_REQ_DESCRIPT_FLAGS_RAID_ACCELERATOR        (0x0A)
+
+#define MPI2_REQ_DESCRIPT_FLAGS_IOC_FIFO_MARKER (0x01)
+
+struct mfi_mpi2_request_high_priority {
+	struct mfi_mpi2_request_header	header;
+	uint16_t			reserved;
+};
+
+struct mfi_mpi2_request_scsi_io {
+	struct mfi_mpi2_request_header	header;
+	uint16_t			scsi_io_dev_handle;
+};
+
+struct mfi_mpi2_request_scsi_target {
+	struct mfi_mpi2_request_header	header;
+	uint16_t			scsi_target_io_index;
+};
+
+/* Request Descriptors */
+union mfi_mpi2_request_descriptor {
+	struct mfi_mpi2_request_header		header;
+	struct mfi_mpi2_request_high_priority	high_priority;
+	struct mfi_mpi2_request_scsi_io		scsi_io;
+	struct mfi_mpi2_request_scsi_target	scsi_target;
+	uint64_t				words;
+};
+
+
+struct mfi_mpi2_reply_header {
+	uint8_t		ReplyFlags;                 /* 0x00 */
+	uint8_t		MSIxIndex;                  /* 0x01 */
+	uint16_t	SMID;                       /* 0x02 */
+};
+
+/* defines for the ReplyFlags field */
+#define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK                   (0x0F)
+#define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS             (0x00)
+#define MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY               (0x01)
+#define MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS        (0x02)
+#define MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER       (0x03)
+#define MPI2_RPY_DESCRIPT_FLAGS_RAID_ACCELERATOR_SUCCESS    (0x05)
+#define MPI2_RPY_DESCRIPT_FLAGS_UNUSED                      (0x0F)
+
+/* values for marking a reply descriptor as unused */
+#define MPI2_RPY_DESCRIPT_UNUSED_WORD0_MARK             (0xFFFFFFFF)
+#define MPI2_RPY_DESCRIPT_UNUSED_WORD1_MARK             (0xFFFFFFFF)
+
+struct mfi_mpi2_reply_default {
+	struct mfi_mpi2_reply_header	header;
+	uint32_t			DescriptorTypeDependent2;
+};
+
+struct mfi_mpi2_reply_address {
+	struct mfi_mpi2_reply_header	header;
+	uint32_t			ReplyFrameAddress;
+};
+
+struct mfi_mpi2_reply_scsi_io {
+	struct mfi_mpi2_reply_header	header;
+	uint16_t			TaskTag;		/* 0x04 */
+	uint16_t			Reserved1;		/* 0x06 */
+};
+
+struct mfi_mpi2_reply_target_assist {
+	struct mfi_mpi2_reply_header	header;
+	uint8_t				SequenceNumber;		/* 0x04 */
+	uint8_t				Reserved1;		/* 0x04 */
+	uint16_t			IoIndex;		/* 0x06 */
+};
+
+struct mfi_mpi2_reply_target_cmd_buffer {
+	struct mfi_mpi2_reply_header	header;
+	uint8_t				SequenceNumber;		/* 0x04 */
+	uint8_t				Flags;			/* 0x04 */
+	uint16_t			InitiatorDevHandle;	/* 0x06 */
+	uint16_t			IoIndex;		/* 0x06 */
+};
+
+struct mfi_mpi2_reply_raid_accel {
+	struct mfi_mpi2_reply_header	header;
+	uint8_t				SequenceNumber;		/* 0x04 */
+	uint32_t			Reserved;		/* 0x04 */
+};
+
+/* union of Reply Descriptors */
+union mfi_mpi2_reply_descriptor {
+	struct mfi_mpi2_reply_header		header;
+	struct mfi_mpi2_reply_scsi_io		scsi_io;
+	struct mfi_mpi2_reply_target_assist	target_assist;
+	struct mfi_mpi2_reply_target_cmd_buffer	target_cmd;
+	struct mfi_mpi2_reply_raid_accel	raid_accel;
+	struct mfi_mpi2_reply_default		reply_default;
+	uint64_t				words;
+};
+
+struct IO_REQUEST_INFO {
+	uint64_t	ldStartBlock;
+	uint32_t	numBlocks;
+	uint16_t	ldTgtId;
+	uint8_t		isRead;
+	uint16_t	devHandle;
+	uint64_t	pdBlock;
+	uint8_t		fpOkForIo;
+};
+
 #define MFI_SCSI_MAX_TARGETS	128
 #define MFI_SCSI_MAX_LUNS	8
 #define MFI_SCSI_INITIATOR_ID	255
diff --git a/sys/dev/raid/mfi/mfivar.h b/sys/dev/raid/mfi/mfivar.h
index 56518a8..a7ea6d4 100644
--- a/sys/dev/raid/mfi/mfivar.h
+++ b/sys/dev/raid/mfi/mfivar.h
@@ -48,36 +48,6 @@
  * 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.
- */
-/*-
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *            Copyright 1994-2009 The FreeBSD Project.
- *            All rights reserved.
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- *    THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT``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 FREEBSD PROJECT 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.
- *
- * The views and conclusions contained in the software and documentation
- * are those of the authors and should not be interpreted as representing
- * official policies,either expressed or implied, of the FreeBSD Project.
  *
  * $FreeBSD: src/sys/dev/mfi/mfivar.h,v 1.14 2011/09/29 08:37:53 mav Exp $
  */
@@ -90,6 +60,7 @@
 #include <sys/eventhandler.h>
 #include <sys/lock.h>
 #include <sys/sysctl.h>
+#include <sys/taskqueue.h>
 
 /*
  * SCSI structures and definitions are used from here, but no linking
@@ -103,6 +74,9 @@ struct mfi_hwcomms {
 	uint32_t		hw_reply_q[1];
 };
 
+#define	MEGASAS_MAX_NAME	32
+#define	MEGASAS_VERSION		"4.23"
+
 struct mfi_softc;
 struct disk;
 struct ccb_hdr;
@@ -112,17 +86,9 @@ struct mfi_command {
 	time_t			cm_timestamp;
 	struct mfi_softc	*cm_sc;
 	union mfi_frame		*cm_frame;
-#if defined(__x86_64__)
-	uint64_t		cm_frame_busaddr;
-#else
-	uint32_t		cm_frame_busaddr;
-#endif
+	bus_addr_t		cm_frame_busaddr;
 	struct mfi_sense	*cm_sense;
-#if defined(__x86_64__)
-	uint64_t		cm_sense_busaddr;
-#else
-	uint32_t		cm_sense_busaddr;
-#endif
+	bus_addr_t		cm_sense_busaddr;
 	bus_dmamap_t		cm_dmamap;
 	union mfi_sgl		*cm_sg;
 	void			*cm_data;
@@ -141,6 +107,7 @@ struct mfi_command {
 #define MFI_ON_MFIQ_BUSY	(1<<7)
 #define MFI_ON_MFIQ_MASK	((1<<5)|(1<<6)|(1<<7))
 	int			cm_aen_abort;
+	uint8_t			retry_for_fw_reset;
 	void			(* cm_complete)(struct mfi_command *cm);
 	void			*cm_private;
 	int			cm_index;
@@ -182,11 +149,32 @@ struct mfi_system_pd {
 	int		pd_flags;
 };
 
+struct mfi_evt_queue_elm {
+	TAILQ_ENTRY(mfi_evt_queue_elm)	link;
+	uint8_t				probe_sys_pd;
+	struct mfi_evt_detail		detail;
+};
+
 struct mfi_aen {
 	TAILQ_ENTRY(mfi_aen) aen_link;
 	struct proc			*p;
 };
 
+struct mfi_skinny_dma_info {
+	bus_dma_tag_t	dmat[514];
+	bus_dmamap_t	dmamap[514];
+	uint32_t	mem[514];
+	int		noofmaps;
+};
+
+struct mfi_cmd_tbolt;
+typedef struct {
+	volatile unsigned int val;
+} atomic_t;
+
+#define	atomic_read(v)	((v)->val)
+#define	atomic_set(v,i)	((v)->val - (i))
+
 struct mfi_softc {
 	device_t			mfi_dev;
 	int				mfi_flags;
@@ -198,11 +186,21 @@ struct mfi_softc {
 #define MFI_FLAGS_1078		(1<<5)
 #define MFI_FLAGS_GEN2		(1<<6)
 #define MFI_FLAGS_SKINNY	(1<<7)
+#define MFI_FLAGS_TBOLT		(1<<8)
+	// Start: LSIP200113393
+	bus_dma_tag_t			verbuf_h_dmat;
+	bus_dmamap_t			verbuf_h_dmamap;
+	uint32_t			verbuf_h_busaddr;
+	uint32_t			*verbuf;
+	void				*kbuff_arr[MAX_IOCTL_SGE];
+	bus_dma_tag_t			mfi_kbuff_arr_dmat[2];
+	bus_dmamap_t			mfi_kbuff_arr_dmamap[2];
+	bus_addr_t			mfi_kbuff_arr_busaddr[2];
 
 	struct mfi_hwcomms		*mfi_comms;
 	TAILQ_HEAD(,mfi_command)	mfi_free;
 	TAILQ_HEAD(,mfi_command)	mfi_ready;
-	TAILQ_HEAD(,mfi_command)	mfi_busy;
+	TAILQ_HEAD(BUSYQ,mfi_command)	mfi_busy;
 	struct bio_queue_head		mfi_bioq;
 	struct mfi_qstat		mfi_qstat[MFIQ_COUNT];
 
@@ -216,13 +214,21 @@ struct mfi_softc {
 
 	bus_dma_tag_t			mfi_comms_dmat;
 	bus_dmamap_t			mfi_comms_dmamap;
-	uint32_t			mfi_comms_busaddr;
+	bus_addr_t			mfi_comms_busaddr;
 
 	bus_dma_tag_t			mfi_frames_dmat;
 	bus_dmamap_t			mfi_frames_dmamap;
-	uint32_t			mfi_frames_busaddr;
+	bus_addr_t			mfi_frames_busaddr;
 	union mfi_frame			*mfi_frames;
 
+	bus_dma_tag_t			mfi_tb_init_dmat;
+	bus_dmamap_t			mfi_tb_init_dmamap;
+	bus_addr_t			mfi_tb_init_busaddr;
+	bus_addr_t			mfi_tb_ioc_init_busaddr;
+	union mfi_frame			*mfi_tb_init;
+
+	TAILQ_HEAD(,mfi_evt_queue_elm)	mfi_evt_queue;
+	struct task			mfi_evt_task;
 	TAILQ_HEAD(,mfi_aen)		mfi_aen_pids;
 	struct mfi_command		*mfi_aen_cm;
 	struct mfi_command		*mfi_skinny_cm;
@@ -245,6 +251,14 @@ struct mfi_softc {
 
 	struct intr_config_hook		mfi_ich;
 	eventhandler_tag		eh;
+	/* OCR flags */
+	atomic_t fw_reset_no_pci_access;
+	uint8_t adpreset;
+	uint8_t issuepend_done;
+	uint8_t disableOnlineCtrlReset;
+	uint32_t mfiStatus;
+	uint32_t last_seq_num;
+	uint32_t volatile hw_crit_error;
 
 	/*
 	 * Allocation for the command array.  Used as an indexable array to
@@ -295,9 +309,100 @@ struct mfi_softc {
 
 	/* Controller type specific interfaces */
 	void	(*mfi_enable_intr)(struct mfi_softc *sc);
+	void	(*mfi_disable_intr)(struct mfi_softc *sc);
 	int32_t	(*mfi_read_fw_status)(struct mfi_softc *sc);
 	int	(*mfi_check_clear_intr)(struct mfi_softc *sc);
-	void	(*mfi_issue_cmd)(struct mfi_softc *sc,uint32_t bus_add,uint32_t frame_cnt);
+	void	(*mfi_issue_cmd)(struct mfi_softc *sc, bus_addr_t bus_add,
+		    uint32_t frame_cnt);
+	int	(*mfi_adp_reset)(struct mfi_softc *sc);
+	int	(*mfi_adp_check_reset)(struct mfi_softc *sc);
+
+	/* ThunderBolt */
+	uint32_t			mfi_tbolt;
+	uint32_t			MFA_enabled;
+	uint64_t			map_id;
+	struct mfi_command 		*map_update_cmd;
+	/* Single Reply structure size */
+	uint16_t			reply_size;
+	/* Singler message size. */
+	uint16_t			raid_io_msg_size;
+	TAILQ_HEAD(TB, mfi_cmd_tbolt)	mfi_cmd_tbolt_tqh;
+	/* ThunderBolt base contiguous memory mapping. */
+	bus_dma_tag_t			mfi_tb_dmat;
+	bus_dmamap_t			mfi_tb_dmamap;
+	bus_addr_t			mfi_tb_busaddr;
+	/* ThunderBolt Contiguous DMA memory Mapping */
+	uint8_t	*			request_message_pool;
+	uint8_t *			request_message_pool_align;
+	uint8_t *			request_desc_pool;
+	//uint32_t			request_desc_busaddr;
+	bus_addr_t			request_msg_busaddr;
+	bus_addr_t			reply_frame_busaddr;
+	bus_addr_t			sg_frame_busaddr;
+	/* ThunderBolt IOC Init Descriptor */
+	bus_dma_tag_t			mfi_tb_ioc_init_dmat;
+	bus_dmamap_t			mfi_tb_ioc_init_dmamap;
+	uint8_t *			mfi_tb_ioc_init_desc;
+	struct mfi_cmd_tbolt		**mfi_cmd_pool_tbolt;
+	/* Virtual address of reply Frame Pool */
+	struct mfi_mpi2_reply_header*	reply_frame_pool;
+	struct mfi_mpi2_reply_header*	reply_frame_pool_align;
+
+	/* Last reply frame address */
+	uint8_t *			reply_pool_limit;
+	uint16_t			last_reply_idx;
+	uint8_t				max_SGEs_in_chain_message;
+	uint8_t				max_SGEs_in_main_message;
+	uint8_t				chain_offset_value_for_main_message;
+	uint8_t				chain_offset_value_for_mpt_ptmsg;
+	uint64_t			fast_path_io_AEN_data;
+	uint8_t				shutdown_issued;
+};
+
+union desc_value {
+	uint64_t	word;
+	struct {
+		uint32_t	low;
+		uint32_t	high;
+	}u;
+};
+
+// TODO find the right definition
+#define XXX_MFI_CMD_OP_INIT2                    0x9
+/*
+ * Request descriptor types
+ */
+#define MFI_REQ_DESCRIPT_FLAGS_LD_IO           0x7
+#define MFI_REQ_DESCRIPT_FLAGS_MFA             0x1
+#define MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT	0x1
+#define MFI_FUSION_FP_DEFAULT_TIMEOUT		0x14
+#define MFI_LOAD_BALANCE_FLAG			0x1
+#define MFI_DCMD_MBOX_PEND_FLAG			0x1
+
+//#define MR_PROT_INFO_TYPE_CONTROLLER	0x08
+#define	MEGASAS_SCSI_VARIABLE_LENGTH_CMD	0x7f
+#define MEGASAS_SCSI_SERVICE_ACTION_READ32	0x9
+#define MEGASAS_SCSI_SERVICE_ACTION_WRITE32	0xB
+#define	MEGASAS_SCSI_ADDL_CDB_LEN   		0x18
+#define MEGASAS_RD_WR_PROTECT_CHECK_ALL		0x20
+#define MEGASAS_RD_WR_PROTECT_CHECK_NONE	0x60
+#define MEGASAS_EEDPBLOCKSIZE			512
+struct mfi_cmd_tbolt {
+	union mfi_mpi2_request_descriptor *request_desc;
+	struct mfi_mpi2_request_raid_scsi_io *io_request;
+	bus_addr_t		io_request_phys_addr;
+	bus_addr_t		sg_frame_phys_addr;
+	bus_addr_t 		sense_phys_addr;
+	MPI2_SGE_IO_UNION	*sg_frame;
+	uint8_t			*sense;
+	TAILQ_ENTRY(mfi_cmd_tbolt) next;
+	/*
+	 * Context for a MFI frame.
+	 * Used to get the mfi cmd from list when a MFI cmd is completed
+	 */
+	uint32_t		sync_cmd_idx;
+	uint16_t		index;
+	uint8_t			status;
 };
 
 extern int mfi_attach(struct mfi_softc *);
@@ -310,7 +415,28 @@ extern void mfi_disk_enable(struct mfi_disk *);
 extern int mfi_dump_blocks(struct mfi_softc *, int id, uint64_t, void *, int);
 extern int mfi_syspd_disable(struct mfi_system_pd *);
 extern void mfi_syspd_enable(struct mfi_system_pd *);
-extern int mfi_dump_syspd_blocks(struct mfi_softc *, int id, uint64_t, void *, int);
+extern int mfi_dump_syspd_blocks(struct mfi_softc *, int id, uint64_t, void *,
+    int);
+extern int mfi_transition_firmware(struct mfi_softc *sc);
+extern int mfi_aen_setup(struct mfi_softc *sc, uint32_t seq_start);
+extern void mfi_complete(struct mfi_softc *sc, struct mfi_command *cm);
+extern int mfi_mapcmd(struct mfi_softc *sc,struct mfi_command *cm);
+extern int mfi_wait_command(struct mfi_softc *sc, struct mfi_command *cm);
+extern void mfi_tbolt_enable_intr_ppc(struct mfi_softc *);
+extern void mfi_tbolt_disable_intr_ppc(struct mfi_softc *);
+extern int32_t mfi_tbolt_read_fw_status_ppc(struct mfi_softc *);
+extern int32_t mfi_tbolt_check_clear_intr_ppc(struct mfi_softc *);
+extern void mfi_tbolt_issue_cmd_ppc(struct mfi_softc *, bus_addr_t, uint32_t);
+extern void mfi_tbolt_init_globals(struct mfi_softc*);
+extern uint32_t mfi_tbolt_get_memory_requirement(struct mfi_softc *);
+extern int mfi_tbolt_init_desc_pool(struct mfi_softc *, uint8_t *, uint32_t);
+extern int mfi_tbolt_init_MFI_queue(struct mfi_softc *);
+extern void mfi_intr_tbolt(void *arg);
+extern int mfi_tbolt_alloc_cmd(struct mfi_softc *sc);
+extern int mfi_tbolt_send_frame(struct mfi_softc *sc, struct mfi_command *cm);
+extern int mfi_tbolt_adp_reset(struct mfi_softc *sc);
+extern int mfi_tbolt_reset(struct mfi_softc *sc);
+extern int mfi_tbolt_sync_map_info(struct mfi_softc *sc);
 
 #define MFIQ_ADD(sc, qname)					\
 	do {							\
@@ -451,9 +577,10 @@ mfi_print_sense(struct mfi_softc *sc, void *sense)
 
 MALLOC_DECLARE(M_MFIBUF);
 
+#define MFI_RESET_WAIT_TIME 180
 #define MFI_CMD_TIMEOUT 30
-#define MFI_MAXPHYS (128 * 1024)
 #define SKINNY_MEMORY 0x02000000
+#define MFI_MAXPHYS (128 * 1024)
 
 #ifdef MFI_DEBUG
 extern void mfi_print_cmd(struct mfi_command *cm);
-- 
1.7.6.3

