view usr/src/uts/common/io/mr_sas/mr_sas.h @ 13880:267f693f357e

3178 Support for LSI 2208 chipset in mr_sas Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com> Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com> Reviewed by: Garrett D'Amore <garrett@damore.org> Approved by: Richard Lowe <richlowe@richlowe.net>
author Dan McDonald <danmcd@nexenta.com>
date Wed, 07 Nov 2012 15:57:25 -0500
parents e25e7e1b3c65
children f0c04f0fa2ad
line wrap: on
line source

/*
 * mr_sas.h: header for mr_sas
 *
 * Solaris MegaRAID driver for SAS2.0 controllers
 * Copyright (c) 2008-2012, LSI Logic Corporation.
 * All rights reserved.
 *
 * Version:
 * Author:
 *		Swaminathan K S
 *		Arun Chandrashekhar
 *		Manju R
 *		Rasheed
 *		Shakeel Bukhari
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the author nor the names of its contributors may be
 *    used to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 */

/*
 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
 */

#ifndef	_MR_SAS_H_
#define	_MR_SAS_H_

#ifdef	__cplusplus
extern "C" {
#endif

#include <sys/scsi/scsi.h>
#include "mr_sas_list.h"
#include "ld_pd_map.h"

/*
 * MegaRAID SAS2.0 Driver meta data
 */
#define	MRSAS_VERSION				"6.503.00.00ILLUMOS"
#define	MRSAS_RELDATE				"July 30, 2012"

#define	MRSAS_TRUE				1
#define	MRSAS_FALSE				0

#define	ADAPTER_RESET_NOT_REQUIRED		0
#define	ADAPTER_RESET_REQUIRED			1

#define	PDSUPPORT	1

/*
 * MegaRAID SAS2.0 device id conversion definitions.
 */
#define	INST2LSIRDCTL(x)		((x) << INST_MINOR_SHIFT)
#define	MRSAS_GET_BOUNDARY_ALIGNED_LEN(len, new_len, boundary_len)  { \
	int rem; \
	rem = (len / boundary_len); \
	if ((rem * boundary_len) != len) { \
		new_len = len + ((rem + 1) * boundary_len - len); \
	} else { \
		new_len = len; \
	} \
}


/*
 * MegaRAID SAS2.0 supported controllers
 */
#define	PCI_DEVICE_ID_LSI_2108VDE		0x0078
#define	PCI_DEVICE_ID_LSI_2108V			0x0079
#define	PCI_DEVICE_ID_LSI_TBOLT			0x005b
#define	PCI_DEVICE_ID_LSI_INVADER		0x005d

/*
 * Register Index for 2108 Controllers.
 */
#define	REGISTER_SET_IO_2108			(2)

#define	MRSAS_MAX_SGE_CNT			0x50
#define	MRSAS_APP_RESERVED_CMDS			32

#define	MRSAS_IOCTL_DRIVER			0x12341234
#define	MRSAS_IOCTL_FIRMWARE			0x12345678
#define	MRSAS_IOCTL_AEN				0x87654321

#define	MRSAS_1_SECOND				1000000

#ifdef PDSUPPORT

#define	UNCONFIGURED_GOOD			0x0
#define	PD_SYSTEM				0x40
#define	MR_EVT_PD_STATE_CHANGE			0x0072
#define	MR_EVT_PD_REMOVED_EXT		0x00f8
#define	MR_EVT_PD_INSERTED_EXT		0x00f7
#define	MR_DCMD_PD_GET_INFO			0x02020000
#define	MRSAS_TBOLT_PD_LUN		1
#define	MRSAS_TBOLT_PD_TGT_MAX	255
#define	MRSAS_TBOLT_GET_PD_MAX(s)	((s)->mr_tbolt_pd_max)

#endif

/* Raid Context Flags */
#define	MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT 0x4
#define	MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_MASK 0x30
typedef enum MR_RAID_FLAGS_IO_SUB_TYPE {
	MR_RAID_FLAGS_IO_SUB_TYPE_NONE = 0,
	MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD = 1
} MR_RAID_FLAGS_IO_SUB_TYPE;

/* Dynamic Enumeration Flags */
#define	MRSAS_LD_LUN		0
#define	WWN_STRLEN		17
#define	LD_SYNC_BIT	1
#define	LD_SYNC_SHIFT	14
/* ThunderBolt (TB) specific */
#define	MRSAS_THUNDERBOLT_MSG_SIZE		256
#define	MRSAS_THUNDERBOLT_MAX_COMMANDS		1024
#define	MRSAS_THUNDERBOLT_MAX_REPLY_COUNT	1024
#define	MRSAS_THUNDERBOLT_REPLY_SIZE		8
#define	MRSAS_THUNDERBOLT_MAX_CHAIN_COUNT	1

#define	MPI2_FUNCTION_PASSTHRU_IO_REQUEST	0xF0
#define	MPI2_FUNCTION_LD_IO_REQUEST		0xF1

#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


/*
 * =====================================
 * MegaRAID SAS2.0 MFI firmware definitions
 * =====================================
 */
/*
 * MFI stands for  MegaRAID SAS2.0 FW Interface. This is just a moniker for
 * protocol between the software and firmware. Commands are issued using
 * "message frames"
 */

/*
 * FW posts its state in upper 4 bits of outbound_msg_0 register
 */
#define	MFI_STATE_MASK				0xF0000000
#define	MFI_STATE_UNDEFINED			0x00000000
#define	MFI_STATE_BB_INIT			0x10000000
#define	MFI_STATE_FW_INIT			0x40000000
#define	MFI_STATE_WAIT_HANDSHAKE		0x60000000
#define	MFI_STATE_FW_INIT_2			0x70000000
#define	MFI_STATE_DEVICE_SCAN			0x80000000
#define	MFI_STATE_BOOT_MESSAGE_PENDING		0x90000000
#define	MFI_STATE_FLUSH_CACHE			0xA0000000
#define	MFI_STATE_READY				0xB0000000
#define	MFI_STATE_OPERATIONAL			0xC0000000
#define	MFI_STATE_FAULT				0xF0000000

#define	MRMFI_FRAME_SIZE			64

/*
 * During FW init, clear pending cmds & reset state using inbound_msg_0
 *
 * ABORT	: Abort all pending cmds
 * READY	: Move from OPERATIONAL to READY state; discard queue info
 * MFIMODE	: Discard (possible) low MFA posted in 64-bit mode (??)
 * CLR_HANDSHAKE: FW is waiting for HANDSHAKE from BIOS or Driver
 */
#define	MFI_INIT_ABORT				0x00000001
#define	MFI_INIT_READY				0x00000002
#define	MFI_INIT_MFIMODE			0x00000004
#define	MFI_INIT_CLEAR_HANDSHAKE		0x00000008
#define	MFI_INIT_HOTPLUG			0x00000010
#define	MFI_STOP_ADP				0x00000020
#define	MFI_RESET_FLAGS		MFI_INIT_READY|MFI_INIT_MFIMODE|MFI_INIT_ABORT

/*
 * MFI frame flags
 */
#define	MFI_FRAME_POST_IN_REPLY_QUEUE		0x0000
#define	MFI_FRAME_DONT_POST_IN_REPLY_QUEUE	0x0001
#define	MFI_FRAME_SGL32				0x0000
#define	MFI_FRAME_SGL64				0x0002
#define	MFI_FRAME_SENSE32			0x0000
#define	MFI_FRAME_SENSE64			0x0004
#define	MFI_FRAME_DIR_NONE			0x0000
#define	MFI_FRAME_DIR_WRITE			0x0008
#define	MFI_FRAME_DIR_READ			0x0010
#define	MFI_FRAME_DIR_BOTH			0x0018
#define	MFI_FRAME_IEEE				0x0020

/*
 * Definition for cmd_status
 */
#define	MFI_CMD_STATUS_POLL_MODE		0xFF
#define	MFI_CMD_STATUS_SYNC_MODE		0xFF

/*
 * MFI command opcodes
 */
#define	MFI_CMD_OP_INIT				0x00
#define	MFI_CMD_OP_LD_READ			0x01
#define	MFI_CMD_OP_LD_WRITE			0x02
#define	MFI_CMD_OP_LD_SCSI			0x03
#define	MFI_CMD_OP_PD_SCSI			0x04
#define	MFI_CMD_OP_DCMD				0x05
#define	MFI_CMD_OP_ABORT			0x06
#define	MFI_CMD_OP_SMP				0x07
#define	MFI_CMD_OP_STP				0x08

#define	MR_DCMD_CTRL_GET_INFO			0x01010000

#define	MR_DCMD_CTRL_CACHE_FLUSH		0x01101000
#define	MR_FLUSH_CTRL_CACHE			0x01
#define	MR_FLUSH_DISK_CACHE			0x02

#define	MR_DCMD_CTRL_SHUTDOWN			0x01050000
#define	MRSAS_ENABLE_DRIVE_SPINDOWN		0x01

#define	MR_DCMD_CTRL_EVENT_GET_INFO		0x01040100
#define	MR_DCMD_CTRL_EVENT_GET			0x01040300
#define	MR_DCMD_CTRL_EVENT_WAIT			0x01040500
#define	MR_DCMD_LD_GET_PROPERTIES		0x03030000

/*
 * Solaris Specific MAX values
 */
#define	MAX_SGL					24

/*
 * MFI command completion codes
 */
enum MFI_STAT {
	MFI_STAT_OK				= 0x00,
	MFI_STAT_INVALID_CMD			= 0x01,
	MFI_STAT_INVALID_DCMD			= 0x02,
	MFI_STAT_INVALID_PARAMETER		= 0x03,
	MFI_STAT_INVALID_SEQUENCE_NUMBER	= 0x04,
	MFI_STAT_ABORT_NOT_POSSIBLE		= 0x05,
	MFI_STAT_APP_HOST_CODE_NOT_FOUND	= 0x06,
	MFI_STAT_APP_IN_USE			= 0x07,
	MFI_STAT_APP_NOT_INITIALIZED		= 0x08,
	MFI_STAT_ARRAY_INDEX_INVALID		= 0x09,
	MFI_STAT_ARRAY_ROW_NOT_EMPTY		= 0x0a,
	MFI_STAT_CONFIG_RESOURCE_CONFLICT	= 0x0b,
	MFI_STAT_DEVICE_NOT_FOUND		= 0x0c,
	MFI_STAT_DRIVE_TOO_SMALL		= 0x0d,
	MFI_STAT_FLASH_ALLOC_FAIL		= 0x0e,
	MFI_STAT_FLASH_BUSY			= 0x0f,
	MFI_STAT_FLASH_ERROR			= 0x10,
	MFI_STAT_FLASH_IMAGE_BAD		= 0x11,
	MFI_STAT_FLASH_IMAGE_INCOMPLETE		= 0x12,
	MFI_STAT_FLASH_NOT_OPEN			= 0x13,
	MFI_STAT_FLASH_NOT_STARTED		= 0x14,
	MFI_STAT_FLUSH_FAILED			= 0x15,
	MFI_STAT_HOST_CODE_NOT_FOUNT		= 0x16,
	MFI_STAT_LD_CC_IN_PROGRESS		= 0x17,
	MFI_STAT_LD_INIT_IN_PROGRESS		= 0x18,
	MFI_STAT_LD_LBA_OUT_OF_RANGE		= 0x19,
	MFI_STAT_LD_MAX_CONFIGURED		= 0x1a,
	MFI_STAT_LD_NOT_OPTIMAL			= 0x1b,
	MFI_STAT_LD_RBLD_IN_PROGRESS		= 0x1c,
	MFI_STAT_LD_RECON_IN_PROGRESS		= 0x1d,
	MFI_STAT_LD_WRONG_RAID_LEVEL		= 0x1e,
	MFI_STAT_MAX_SPARES_EXCEEDED		= 0x1f,
	MFI_STAT_MEMORY_NOT_AVAILABLE		= 0x20,
	MFI_STAT_MFC_HW_ERROR			= 0x21,
	MFI_STAT_NO_HW_PRESENT			= 0x22,
	MFI_STAT_NOT_FOUND			= 0x23,
	MFI_STAT_NOT_IN_ENCL			= 0x24,
	MFI_STAT_PD_CLEAR_IN_PROGRESS		= 0x25,
	MFI_STAT_PD_TYPE_WRONG			= 0x26,
	MFI_STAT_PR_DISABLED			= 0x27,
	MFI_STAT_ROW_INDEX_INVALID		= 0x28,
	MFI_STAT_SAS_CONFIG_INVALID_ACTION	= 0x29,
	MFI_STAT_SAS_CONFIG_INVALID_DATA	= 0x2a,
	MFI_STAT_SAS_CONFIG_INVALID_PAGE	= 0x2b,
	MFI_STAT_SAS_CONFIG_INVALID_TYPE	= 0x2c,
	MFI_STAT_SCSI_DONE_WITH_ERROR		= 0x2d,
	MFI_STAT_SCSI_IO_FAILED			= 0x2e,
	MFI_STAT_SCSI_RESERVATION_CONFLICT	= 0x2f,
	MFI_STAT_SHUTDOWN_FAILED		= 0x30,
	MFI_STAT_TIME_NOT_SET			= 0x31,
	MFI_STAT_WRONG_STATE			= 0x32,
	MFI_STAT_LD_OFFLINE			= 0x33,
	MFI_STAT_INVALID_STATUS			= 0xFF
};

enum MR_EVT_CLASS {
	MR_EVT_CLASS_DEBUG		= -2,
	MR_EVT_CLASS_PROGRESS		= -1,
	MR_EVT_CLASS_INFO		=  0,
	MR_EVT_CLASS_WARNING		=  1,
	MR_EVT_CLASS_CRITICAL		=  2,
	MR_EVT_CLASS_FATAL		=  3,
	MR_EVT_CLASS_DEAD		=  4
};

enum MR_EVT_LOCALE {
	MR_EVT_LOCALE_LD		= 0x0001,
	MR_EVT_LOCALE_PD		= 0x0002,
	MR_EVT_LOCALE_ENCL		= 0x0004,
	MR_EVT_LOCALE_BBU		= 0x0008,
	MR_EVT_LOCALE_SAS		= 0x0010,
	MR_EVT_LOCALE_CTRL		= 0x0020,
	MR_EVT_LOCALE_CONFIG		= 0x0040,
	MR_EVT_LOCALE_CLUSTER		= 0x0080,
	MR_EVT_LOCALE_ALL		= 0xffff
};

enum MR_EVT_ARGS {
	MR_EVT_ARGS_NONE,
	MR_EVT_ARGS_CDB_SENSE,
	MR_EVT_ARGS_LD,
	MR_EVT_ARGS_LD_COUNT,
	MR_EVT_ARGS_LD_LBA,
	MR_EVT_ARGS_LD_OWNER,
	MR_EVT_ARGS_LD_LBA_PD_LBA,
	MR_EVT_ARGS_LD_PROG,
	MR_EVT_ARGS_LD_STATE,
	MR_EVT_ARGS_LD_STRIP,
	MR_EVT_ARGS_PD,
	MR_EVT_ARGS_PD_ERR,
	MR_EVT_ARGS_PD_LBA,
	MR_EVT_ARGS_PD_LBA_LD,
	MR_EVT_ARGS_PD_PROG,
	MR_EVT_ARGS_PD_STATE,
	MR_EVT_ARGS_PCI,
	MR_EVT_ARGS_RATE,
	MR_EVT_ARGS_STR,
	MR_EVT_ARGS_TIME,
	MR_EVT_ARGS_ECC
};

#define	MR_EVT_CFG_CLEARED		0x0004
#define	MR_EVT_LD_CREATED		0x008a
#define	MR_EVT_LD_DELETED		0x008b
#define	MR_EVT_CFG_FP_CHANGE		0x017B

enum LD_STATE {
	LD_OFFLINE		= 0,
	LD_PARTIALLY_DEGRADED	= 1,
	LD_DEGRADED		= 2,
	LD_OPTIMAL		= 3,
	LD_INVALID		= 0xFF
};

enum MRSAS_EVT {
	MRSAS_EVT_CONFIG_TGT	= 0,
	MRSAS_EVT_UNCONFIG_TGT	= 1,
	MRSAS_EVT_UNCONFIG_SMP	= 2
};

#define	DMA_OBJ_ALLOCATED	1
#define	DMA_OBJ_REALLOCATED	2
#define	DMA_OBJ_FREED		3

/*
 * dma_obj_t	- Our DMA object
 * @param buffer	: kernel virtual address
 * @param size		: size of the data to be allocated
 * @param acc_handle	: access handle
 * @param dma_handle	: dma handle
 * @param dma_cookie	: scatter-gather list
 * @param dma_attr	: dma attributes for this buffer
 *
 * Our DMA object. The caller must initialize the size and dma attributes
 * (dma_attr) fields before allocating the resources.
 */
typedef struct {
	caddr_t			buffer;
	uint32_t		size;
	ddi_acc_handle_t	acc_handle;
	ddi_dma_handle_t	dma_handle;
	ddi_dma_cookie_t	dma_cookie[MRSAS_MAX_SGE_CNT];
	ddi_dma_attr_t		dma_attr;
	uint8_t			status;
	uint8_t			reserved[3];
} dma_obj_t;

struct mrsas_eventinfo {
	struct mrsas_instance	*instance;
	int 			tgt;
	int 			lun;
	int 			event;
	uint64_t		wwn;
};

struct mrsas_ld {
	dev_info_t		*dip;
	uint8_t 		lun_type;
	uint8_t			flag;
	uint8_t 		reserved[2];
};


#ifdef PDSUPPORT
struct mrsas_tbolt_pd {
	dev_info_t		*dip;
	uint8_t 		lun_type;
	uint8_t 		dev_id;
	uint8_t 		flag;
	uint8_t 		reserved;
};
struct mrsas_tbolt_pd_info {
	uint16_t	deviceId;
	uint16_t	seqNum;
	uint8_t		inquiryData[96];
	uint8_t		vpdPage83[64];
	uint8_t		notSupported;
	uint8_t		scsiDevType;
	uint8_t		a;
	uint8_t		device_speed;
	uint32_t	mediaerrcnt;
	uint32_t	other;
	uint32_t	pred;
	uint32_t	lastpred;
	uint16_t	fwState;
	uint8_t		disabled;
	uint8_t		linkspwwd;
	uint32_t	ddfType;
	struct {
		uint8_t	count;
		uint8_t	isPathBroken;
		uint8_t	connectorIndex[2];
		uint8_t	reserved[4];
		uint64_t sasAddr[2];
		uint8_t	reserved2[16];
	} pathInfo;
};
#endif

typedef struct mrsas_instance {
	uint32_t	*producer;
	uint32_t	*consumer;

	uint32_t	*reply_queue;
	dma_obj_t	mfi_internal_dma_obj;
	uint16_t	adapterresetinprogress;
	uint16_t	deadadapter;
	/* ThunderBolt (TB) specific */
	dma_obj_t	mpi2_frame_pool_dma_obj;
	dma_obj_t	request_desc_dma_obj;
	dma_obj_t	reply_desc_dma_obj;
	dma_obj_t	ld_map_obj[2];

	uint8_t		init_id;
	uint8_t		flag_ieee;
	uint8_t		disable_online_ctrl_reset;
	uint8_t		fw_fault_count_after_ocr;

	uint16_t	max_num_sge;
	uint16_t	max_fw_cmds;
	uint32_t	max_sectors_per_req;

	struct mrsas_cmd **cmd_list;

	mlist_t		cmd_pool_list;
	kmutex_t	cmd_pool_mtx;
	kmutex_t	sync_map_mtx;

	mlist_t		app_cmd_pool_list;
	kmutex_t	app_cmd_pool_mtx;
	mlist_t		cmd_app_pool_list;
	kmutex_t	cmd_app_pool_mtx;


	mlist_t		cmd_pend_list;
	kmutex_t	cmd_pend_mtx;

	dma_obj_t	mfi_evt_detail_obj;
	struct mrsas_cmd *aen_cmd;

	uint32_t	aen_seq_num;
	uint32_t	aen_class_locale_word;

	scsi_hba_tran_t		*tran;

	kcondvar_t	int_cmd_cv;
	kmutex_t	int_cmd_mtx;

	kcondvar_t	aen_cmd_cv;
	kmutex_t	aen_cmd_mtx;

	kcondvar_t	abort_cmd_cv;
	kmutex_t	abort_cmd_mtx;

	kmutex_t	reg_write_mtx;
	kmutex_t	chip_mtx;

	dev_info_t		*dip;
	ddi_acc_handle_t	pci_handle;

	timeout_id_t	timeout_id;
	uint32_t	unique_id;
	uint16_t	fw_outstanding;
	caddr_t		regmap;
	ddi_acc_handle_t	regmap_handle;
	uint8_t		isr_level;
	ddi_iblock_cookie_t	iblock_cookie;
	ddi_iblock_cookie_t	soft_iblock_cookie;
	ddi_softintr_t		soft_intr_id;
	uint8_t		softint_running;
	uint8_t		tbolt_softint_running;
	kmutex_t	completed_pool_mtx;
	mlist_t		completed_pool_list;

	caddr_t		internal_buf;
	uint32_t	internal_buf_dmac_add;
	uint32_t	internal_buf_size;

	uint16_t	vendor_id;
	uint16_t	device_id;
	uint16_t	subsysvid;
	uint16_t	subsysid;
	int		instance;
	int		baseaddress;
	char		iocnode[16];

	int		fm_capabilities;
	/*
	 * Driver resources unroll flags.  The flag is set for resources that
	 * are needed to be free'd at detach() time.
	 */
	struct _unroll {
		uint8_t softs;		/* The software state was allocated. */
		uint8_t regs;		/* Controller registers mapped. */
		uint8_t intr;		/* Interrupt handler added. */
		uint8_t reqs;		/* Request structs allocated. */
		uint8_t mutexs;		/* Mutex's allocated. */
		uint8_t taskq;		/* Task q's created. */
		uint8_t tran;		/* Tran struct allocated */
		uint8_t tranSetup;	/* Tran attached to the ddi. */
		uint8_t devctl;		/* Device nodes for cfgadm created. */
		uint8_t scsictl;	/* Device nodes for cfgadm created. */
		uint8_t ioctl;		/* Device nodes for ioctl's created. */
		uint8_t timer;		/* Timer started. */
		uint8_t aenPend;	/* AEN cmd pending f/w. */
		uint8_t mapUpdate_pend; /* LD MAP update cmd pending f/w. */
		uint8_t soft_isr;	/* Soft interrupt handler allocated. */
		uint8_t ldlist_buff;	/* Logical disk list allocated. */
		uint8_t pdlist_buff;	/* Physical disk list allocated. */
		uint8_t syncCmd;	/* Sync map command allocated. */
		uint8_t verBuff;	/* 2108 MFI buffer allocated. */
		uint8_t alloc_space_mfi;  /* Allocated space for 2108 MFI. */
		uint8_t alloc_space_mpi2; /* Allocated space for 2208 MPI2. */
	} unroll;


	/* function template pointer */
	struct mrsas_function_template *func_ptr;


	/* MSI interrupts specific */
	ddi_intr_handle_t *intr_htable;		/* Interrupt handle array */
	size_t		intr_htable_size;	/* Int. handle array size */
	int		intr_type;
	int		intr_cnt;
	uint_t		intr_pri;
	int		intr_cap;

	ddi_taskq_t	*taskq;
	struct mrsas_ld	*mr_ld_list;
	kmutex_t	config_dev_mtx;
	/* ThunderBolt (TB) specific */
	ddi_softintr_t	tbolt_soft_intr_id;

#ifdef PDSUPPORT
	uint32_t	mr_tbolt_pd_max;
	struct mrsas_tbolt_pd *mr_tbolt_pd_list;
#endif

	uint8_t		fast_path_io;

	uint16_t	tbolt;
	uint16_t	reply_read_index;
	uint16_t	reply_size; 		/* Single Reply struct size */
	uint16_t	raid_io_msg_size; 	/* Single message size */
	uint32_t	io_request_frames_phy;
	uint8_t 	*io_request_frames;
	/* Virtual address of request desc frame pool */
	MRSAS_REQUEST_DESCRIPTOR_UNION	*request_message_pool;
	/* Physical address of request desc frame pool */
	uint32_t	request_message_pool_phy;
	/* Virtual address of reply Frame */
	MPI2_REPLY_DESCRIPTORS_UNION	*reply_frame_pool;
	/* Physical address of reply Frame */
	uint32_t	reply_frame_pool_phy;
	uint8_t		*reply_pool_limit;	/* Last reply frame address */
	/* Physical address of Last reply frame */
	uint32_t	reply_pool_limit_phy;
	uint32_t	reply_q_depth;		/* Reply Queue Depth */
	uint8_t		max_sge_in_main_msg;
	uint8_t		max_sge_in_chain;
	uint8_t    	chain_offset_io_req;
	uint8_t		chain_offset_mpt_msg;
	MR_FW_RAID_MAP_ALL *ld_map[2];
	uint32_t 	ld_map_phy[2];
	uint32_t	size_map_info;
	uint64_t 	map_id;
	LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES];
	struct mrsas_cmd *map_update_cmd;
	uint32_t	SyncRequired;
	kmutex_t	ocr_flags_mtx;
	dma_obj_t	drv_ver_dma_obj;
} mrsas_t;


/*
 * Function templates for various controller specific functions
 */
struct mrsas_function_template {
	uint32_t (*read_fw_status_reg)(struct mrsas_instance *);
	void (*issue_cmd)(struct mrsas_cmd *, struct mrsas_instance *);
	int (*issue_cmd_in_sync_mode)(struct mrsas_instance *,
	    struct mrsas_cmd *);
	int (*issue_cmd_in_poll_mode)(struct mrsas_instance *,
	    struct mrsas_cmd *);
	void (*enable_intr)(struct mrsas_instance *);
	void (*disable_intr)(struct mrsas_instance *);
	int (*intr_ack)(struct mrsas_instance *);
	int (*init_adapter)(struct mrsas_instance *);
/*	int (*reset_adapter)(struct mrsas_instance *); */
};

/*
 * ### Helper routines ###
 */

/*
 * con_log() - console log routine
 * @param level		: indicates the severity of the message.
 * @fparam mt		: format string
 *
 * con_log displays the error messages on the console based on the current
 * debug level. Also it attaches the appropriate kernel severity level with
 * the message.
 *
 *
 * console messages debug levels
 */
#define	CL_NONE		0	/* No debug information */
#define	CL_ANN		1	/* print unconditionally, announcements */
#define	CL_ANN1		2	/* No-op  */
#define	CL_DLEVEL1	3	/* debug level 1, informative */
#define	CL_DLEVEL2	4	/* debug level 2, verbose */
#define	CL_DLEVEL3	5	/* debug level 3, very verbose */

#ifdef __SUNPRO_C
#define	__func__ ""
#endif

#define	con_log(level, fmt) { if (debug_level_g >= level) cmn_err fmt; }

/*
 * ### SCSA definitions ###
 */
#define	PKT2TGT(pkt)	((pkt)->pkt_address.a_target)
#define	PKT2LUN(pkt)	((pkt)->pkt_address.a_lun)
#define	PKT2TRAN(pkt)	((pkt)->pkt_adress.a_hba_tran)
#define	ADDR2TRAN(ap)	((ap)->a_hba_tran)

#define	TRAN2MR(tran)	(struct mrsas_instance *)(tran)->tran_hba_private)
#define	ADDR2MR(ap)	(TRAN2MR(ADDR2TRAN(ap))

#define	PKT2CMD(pkt)	((struct scsa_cmd *)(pkt)->pkt_ha_private)
#define	CMD2PKT(sp)	((sp)->cmd_pkt)
#define	PKT2REQ(pkt)	(&(PKT2CMD(pkt)->request))

#define	CMD2ADDR(cmd)	(&CMD2PKT(cmd)->pkt_address)
#define	CMD2TRAN(cmd)	(CMD2PKT(cmd)->pkt_address.a_hba_tran)
#define	CMD2MR(cmd)	(TRAN2MR(CMD2TRAN(cmd)))

#define	CFLAG_DMAVALID		0x0001	/* requires a dma operation */
#define	CFLAG_DMASEND		0x0002	/* Transfer from the device */
#define	CFLAG_CONSISTENT	0x0040	/* consistent data transfer */

/*
 * ### Data structures for ioctl inteface and internal commands ###
 */

/*
 * Data direction flags
 */
#define	UIOC_RD		0x00001
#define	UIOC_WR		0x00002

#define	SCP2HOST(scp)		(scp)->device->host	/* to host */
#define	SCP2HOSTDATA(scp)	SCP2HOST(scp)->hostdata	/* to soft state */
#define	SCP2CHANNEL(scp)	(scp)->device->channel	/* to channel */
#define	SCP2TARGET(scp)		(scp)->device->id	/* to target */
#define	SCP2LUN(scp)		(scp)->device->lun	/* to LUN */

#define	SCSIHOST2ADAP(host)	(((caddr_t *)(host->hostdata))[0])
#define	SCP2ADAPTER(scp)				\
	(struct mrsas_instance *)SCSIHOST2ADAP(SCP2HOST(scp))

#define	MRDRV_IS_LOGICAL_SCSA(instance, acmd)		\
	(acmd->device_id < MRDRV_MAX_LD) ? 1 : 0
#define	MRDRV_IS_LOGICAL(ap)				\
	((ap->a_target < MRDRV_MAX_LD) && (ap->a_lun == 0)) ? 1 : 0
#define	MAP_DEVICE_ID(instance, ap)			\
	(ap->a_target)

#define	HIGH_LEVEL_INTR			1
#define	NORMAL_LEVEL_INTR		0

#define		IO_TIMEOUT_VAL		0
#define		IO_RETRY_COUNT		3
#define		MAX_FW_RESET_COUNT	3
/*
 * scsa_cmd  - Per-command mr private data
 * @param cmd_dmahandle		:  dma handle
 * @param cmd_dmacookies	:  current dma cookies
 * @param cmd_pkt		:  scsi_pkt reference
 * @param cmd_dmacount		:  dma count
 * @param cmd_cookie		:  next cookie
 * @param cmd_ncookies		:  cookies per window
 * @param cmd_cookiecnt		:  cookies per sub-win
 * @param cmd_nwin		:  number of dma windows
 * @param cmd_curwin		:  current dma window
 * @param cmd_dma_offset	:  current window offset
 * @param cmd_dma_len		:  current window length
 * @param cmd_flags		:  private flags
 * @param cmd_cdblen		:  length of cdb
 * @param cmd_scblen		:  length of scb
 * @param cmd_buf		:  command buffer
 * @param channel		:  channel for scsi sub-system
 * @param target		:  target for scsi sub-system
 * @param lun			:  LUN for scsi sub-system
 *
 * - Allocated at same time as scsi_pkt by scsi_hba_pkt_alloc(9E)
 * - Pointed to by pkt_ha_private field in scsi_pkt
 */
struct scsa_cmd {
	ddi_dma_handle_t	cmd_dmahandle;
	ddi_dma_cookie_t	cmd_dmacookies[MRSAS_MAX_SGE_CNT];
	struct scsi_pkt		*cmd_pkt;
	ulong_t			cmd_dmacount;
	uint_t			cmd_cookie;
	uint_t			cmd_ncookies;
	uint_t			cmd_cookiecnt;
	uint_t			cmd_nwin;
	uint_t			cmd_curwin;
	off_t			cmd_dma_offset;
	ulong_t			cmd_dma_len;
	ulong_t			cmd_flags;
	uint_t			cmd_cdblen;
	uint_t			cmd_scblen;
	struct buf		*cmd_buf;
	ushort_t		device_id;
	uchar_t			islogical;
	uchar_t			lun;
	struct mrsas_device	*mrsas_dev;
};


struct mrsas_cmd {
	/*
	 * ThunderBolt(TB) We would be needing to have a placeholder
	 * for RAID_MSG_IO_REQUEST inside this structure. We are
	 * supposed to embed the mr_frame inside the RAID_MSG and post
	 * it down to the firmware.
	 */
	union mrsas_frame	*frame;
	uint32_t		frame_phys_addr;
	uint8_t			*sense;
	uint8_t			*sense1;
	uint32_t		sense_phys_addr;
	uint32_t		sense_phys_addr1;
	dma_obj_t		frame_dma_obj;
	uint8_t			frame_dma_obj_status;
	uint32_t		index;
	uint8_t			sync_cmd;
	uint8_t			cmd_status;
	uint16_t		abort_aen;
	mlist_t			list;
	uint32_t		frame_count;
	struct scsa_cmd		*cmd;
	struct scsi_pkt		*pkt;
	Mpi2RaidSCSIIORequest_t *scsi_io_request;
	Mpi2SGEIOUnion_t	*sgl;
	uint32_t		sgl_phys_addr;
	uint32_t		scsi_io_request_phys_addr;
	MRSAS_REQUEST_DESCRIPTOR_UNION	*request_desc;
	uint16_t		SMID;
	uint16_t		retry_count_for_ocr;
	uint16_t		drv_pkt_time;
	uint16_t		load_balance_flag;

};

#define	MAX_MGMT_ADAPTERS			1024
#define	IOC_SIGNATURE				"MR-SAS"

#define	IOC_CMD_FIRMWARE			0x0
#define	MRSAS_DRIVER_IOCTL_COMMON		0xF0010000
#define	MRSAS_DRIVER_IOCTL_DRIVER_VERSION	0xF0010100
#define	MRSAS_DRIVER_IOCTL_PCI_INFORMATION	0xF0010200
#define	MRSAS_DRIVER_IOCTL_MRRAID_STATISTICS	0xF0010300


#define	MRSAS_MAX_SENSE_LENGTH			32

struct mrsas_mgmt_info {

	uint16_t			count;
	struct mrsas_instance		*instance[MAX_MGMT_ADAPTERS];
	uint16_t			map[MAX_MGMT_ADAPTERS];
	int				max_index;
};


#pragma pack(1)
/*
 * SAS controller properties
 */
struct mrsas_ctrl_prop {
	uint16_t	seq_num;
	uint16_t	pred_fail_poll_interval;
	uint16_t	intr_throttle_count;
	uint16_t	intr_throttle_timeouts;

	uint8_t		rebuild_rate;
	uint8_t		patrol_read_rate;
	uint8_t		bgi_rate;
	uint8_t		cc_rate;
	uint8_t		recon_rate;

	uint8_t		cache_flush_interval;

	uint8_t		spinup_drv_count;
	uint8_t		spinup_delay;

	uint8_t		cluster_enable;
	uint8_t		coercion_mode;
	uint8_t		alarm_enable;

	uint8_t		reserved_1[13];
	uint32_t	on_off_properties;
	uint8_t		reserved_4[28];
};


/*
 * SAS controller information
 */
struct mrsas_ctrl_info {
	/* PCI device information */
	struct {
		uint16_t	vendor_id;
		uint16_t	device_id;
		uint16_t	sub_vendor_id;
		uint16_t	sub_device_id;
		uint8_t	reserved[24];
	} pci;

	/* Host interface information */
	struct {
		uint8_t	PCIX		: 1;
		uint8_t	PCIE		: 1;
		uint8_t	iSCSI		: 1;
		uint8_t	SAS_3G		: 1;
		uint8_t	reserved_0	: 4;
		uint8_t	reserved_1[6];
		uint8_t	port_count;
		uint64_t	port_addr[8];
	} host_interface;

	/* Device (backend) interface information */
	struct {
		uint8_t	SPI		: 1;
		uint8_t	SAS_3G		: 1;
		uint8_t	SATA_1_5G	: 1;
		uint8_t	SATA_3G		: 1;
		uint8_t	reserved_0	: 4;
		uint8_t	reserved_1[6];
		uint8_t	port_count;
		uint64_t	port_addr[8];
	} device_interface;

	/* List of components residing in flash. All str are null terminated */
	uint32_t	image_check_word;
	uint32_t	image_component_count;

	struct {
		char	name[8];
		char	version[32];
		char	build_date[16];
		char	built_time[16];
	} image_component[8];

	/*
	 * List of flash components that have been flashed on the card, but
	 * are not in use, pending reset of the adapter. This list will be
	 * empty if a flash operation has not occurred. All stings are null
	 * terminated
	 */
	uint32_t	pending_image_component_count;

	struct {
		char	name[8];
		char	version[32];
		char	build_date[16];
		char	build_time[16];
	} pending_image_component[8];

	uint8_t		max_arms;
	uint8_t		max_spans;
	uint8_t		max_arrays;
	uint8_t		max_lds;

	char		product_name[80];
	char		serial_no[32];

	/*
	 * Other physical/controller/operation information. Indicates the
	 * presence of the hardware
	 */
	struct {
		uint32_t	bbu		: 1;
		uint32_t	alarm		: 1;
		uint32_t	nvram		: 1;
		uint32_t	uart		: 1;
		uint32_t	reserved	: 28;
	} hw_present;

	uint32_t	current_fw_time;

	/* Maximum data transfer sizes */
	uint16_t		max_concurrent_cmds;
	uint16_t		max_sge_count;
	uint32_t		max_request_size;

	/* Logical and physical device counts */
	uint16_t		ld_present_count;
	uint16_t		ld_degraded_count;
	uint16_t		ld_offline_count;

	uint16_t		pd_present_count;
	uint16_t		pd_disk_present_count;
	uint16_t		pd_disk_pred_failure_count;
	uint16_t		pd_disk_failed_count;

	/* Memory size information */
	uint16_t		nvram_size;
	uint16_t		memory_size;
	uint16_t		flash_size;

	/* Error counters */
	uint16_t		mem_correctable_error_count;
	uint16_t		mem_uncorrectable_error_count;

	/* Cluster information */
	uint8_t		cluster_permitted;
	uint8_t		cluster_active;
	uint8_t		reserved_1[2];

	/* Controller capabilities structures */
	struct {
		uint32_t	raid_level_0	: 1;
		uint32_t	raid_level_1	: 1;
		uint32_t	raid_level_5	: 1;
		uint32_t	raid_level_1E	: 1;
		uint32_t	reserved	: 28;
	} raid_levels;

	struct {
		uint32_t	rbld_rate		: 1;
		uint32_t	cc_rate			: 1;
		uint32_t	bgi_rate		: 1;
		uint32_t	recon_rate		: 1;
		uint32_t	patrol_rate		: 1;
		uint32_t	alarm_control		: 1;
		uint32_t	cluster_supported	: 1;
		uint32_t	bbu			: 1;
		uint32_t	spanning_allowed	: 1;
		uint32_t	dedicated_hotspares	: 1;
		uint32_t	revertible_hotspares	: 1;
		uint32_t	foreign_config_import	: 1;
		uint32_t	self_diagnostic		: 1;
		uint32_t	reserved		: 19;
	} adapter_operations;

	struct {
		uint32_t	read_policy	: 1;
		uint32_t	write_policy	: 1;
		uint32_t	io_policy	: 1;
		uint32_t	access_policy	: 1;
		uint32_t	reserved	: 28;
	} ld_operations;

	struct {
		uint8_t	min;
		uint8_t	max;
		uint8_t	reserved[2];
	} stripe_size_operations;

	struct {
		uint32_t	force_online	: 1;
		uint32_t	force_offline	: 1;
		uint32_t	force_rebuild	: 1;
		uint32_t	reserved	: 29;
	} pd_operations;

	struct {
		uint32_t	ctrl_supports_sas	: 1;
		uint32_t	ctrl_supports_sata	: 1;
		uint32_t	allow_mix_in_encl	: 1;
		uint32_t	allow_mix_in_ld		: 1;
		uint32_t	allow_sata_in_cluster	: 1;
		uint32_t	reserved		: 27;
	} pd_mix_support;

	/* Include the controller properties (changeable items) */
	uint8_t				reserved_2[12];
	struct mrsas_ctrl_prop		properties;

	uint8_t				pad[0x800 - 0x640];
};

/*
 * ==================================
 * MegaRAID SAS2.0 driver definitions
 * ==================================
 */
#define	MRDRV_MAX_NUM_CMD			1024

#define	MRDRV_MAX_PD_CHANNELS			2
#define	MRDRV_MAX_LD_CHANNELS			2
#define	MRDRV_MAX_CHANNELS			(MRDRV_MAX_PD_CHANNELS + \
						MRDRV_MAX_LD_CHANNELS)
#define	MRDRV_MAX_DEV_PER_CHANNEL		128
#define	MRDRV_DEFAULT_INIT_ID			-1
#define	MRDRV_MAX_CMD_PER_LUN			1000
#define	MRDRV_MAX_LUN				1
#define	MRDRV_MAX_LD				64

#define	MRDRV_RESET_WAIT_TIME			300
#define	MRDRV_RESET_NOTICE_INTERVAL		5

#define	MRSAS_IOCTL_CMD				0

#define	MRDRV_TGT_VALID				1

/*
 * FW can accept both 32 and 64 bit SGLs. We want to allocate 32/64 bit
 * SGLs based on the size of dma_addr_t
 */
#define	IS_DMA64		(sizeof (dma_addr_t) == 8)

#define	RESERVED0_REGISTER		0x00	/* XScale */
#define	IB_MSG_0_OFF			0x10	/* XScale */
#define	OB_MSG_0_OFF			0x18	/* XScale */
#define	IB_DOORBELL_OFF			0x20	/* XScale & ROC */
#define	OB_INTR_STATUS_OFF		0x30	/* XScale & ROC */
#define	OB_INTR_MASK_OFF		0x34	/* XScale & ROC */
#define	IB_QPORT_OFF			0x40	/* XScale & ROC */
#define	OB_DOORBELL_CLEAR_OFF		0xA0	/* ROC */
#define	OB_SCRATCH_PAD_0_OFF		0xB0	/* ROC */
#define	OB_INTR_MASK			0xFFFFFFFF
#define	OB_DOORBELL_CLEAR_MASK		0xFFFFFFFF
#define	SYSTOIOP_INTERRUPT_MASK		0x80000000
#define	OB_SCRATCH_PAD_2_OFF		0xB4
#define	WRITE_TBOLT_SEQ_OFF		0x00000004
#define	DIAG_TBOLT_RESET_ADAPTER	0x00000004
#define	HOST_TBOLT_DIAG_OFF		0x00000008
#define	RESET_TBOLT_STATUS_OFF		0x000003C3
#define	WRITE_SEQ_OFF			0x000000FC
#define	HOST_DIAG_OFF			0x000000F8
#define	DIAG_RESET_ADAPTER		0x00000004
#define	DIAG_WRITE_ENABLE		0x00000080
#define	SYSTOIOP_INTERRUPT_MASK		0x80000000

#define	WR_IB_WRITE_SEQ(v, instance) 	ddi_put32((instance)->regmap_handle, \
	(uint32_t *)((uintptr_t)(instance)->regmap + WRITE_SEQ_OFF), (v))

#define	RD_OB_DRWE(instance) 		ddi_get32((instance)->regmap_handle, \
	(uint32_t *)((uintptr_t)(instance)->regmap + HOST_DIAG_OFF))

#define	WR_IB_DRWE(v, instance) 	ddi_put32((instance)->regmap_handle, \
	(uint32_t *)((uintptr_t)(instance)->regmap + HOST_DIAG_OFF), (v))

#define	IB_LOW_QPORT			0xC0
#define	IB_HIGH_QPORT			0xC4
#define	OB_DOORBELL_REGISTER		0x9C	/* 1078 implementation */

/*
 * All MFI register set macros accept mrsas_register_set*
 */
#define	WR_IB_MSG_0(v, instance) 	ddi_put32((instance)->regmap_handle, \
	(uint32_t *)((uintptr_t)(instance)->regmap + IB_MSG_0_OFF), (v))

#define	RD_OB_MSG_0(instance) 		ddi_get32((instance)->regmap_handle, \
	(uint32_t *)((uintptr_t)(instance)->regmap + OB_MSG_0_OFF))

#define	WR_IB_DOORBELL(v, instance)	ddi_put32((instance)->regmap_handle, \
	(uint32_t *)((uintptr_t)(instance)->regmap + IB_DOORBELL_OFF), (v))

#define	RD_IB_DOORBELL(instance)	ddi_get32((instance)->regmap_handle, \
	(uint32_t *)((uintptr_t)(instance)->regmap + IB_DOORBELL_OFF))

#define	WR_OB_INTR_STATUS(v, instance) 	ddi_put32((instance)->regmap_handle, \
	(uint32_t *)((uintptr_t)(instance)->regmap + OB_INTR_STATUS_OFF), (v))

#define	RD_OB_INTR_STATUS(instance) 	ddi_get32((instance)->regmap_handle, \
	(uint32_t *)((uintptr_t)(instance)->regmap + OB_INTR_STATUS_OFF))

#define	WR_OB_INTR_MASK(v, instance) 	ddi_put32((instance)->regmap_handle, \
	(uint32_t *)((uintptr_t)(instance)->regmap + OB_INTR_MASK_OFF), (v))

#define	RD_OB_INTR_MASK(instance) 	ddi_get32((instance)->regmap_handle, \
	(uint32_t *)((uintptr_t)(instance)->regmap + OB_INTR_MASK_OFF))

#define	WR_IB_QPORT(v, instance) 	ddi_put32((instance)->regmap_handle, \
	(uint32_t *)((uintptr_t)(instance)->regmap + IB_QPORT_OFF), (v))

#define	WR_OB_DOORBELL_CLEAR(v, instance) ddi_put32((instance)->regmap_handle, \
	(uint32_t *)((uintptr_t)(instance)->regmap + OB_DOORBELL_CLEAR_OFF), \
	(v))

#define	RD_OB_SCRATCH_PAD_0(instance) 	ddi_get32((instance)->regmap_handle, \
	(uint32_t *)((uintptr_t)(instance)->regmap + OB_SCRATCH_PAD_0_OFF))

/* Thunderbolt specific registers */
#define	RD_OB_SCRATCH_PAD_2(instance)	ddi_get32((instance)->regmap_handle, \
	(uint32_t *)((uintptr_t)(instance)->regmap + OB_SCRATCH_PAD_2_OFF))

#define	WR_TBOLT_IB_WRITE_SEQ(v, instance) \
	ddi_put32((instance)->regmap_handle, \
	(uint32_t *)((uintptr_t)(instance)->regmap + WRITE_TBOLT_SEQ_OFF), (v))

#define	RD_TBOLT_HOST_DIAG(instance)	ddi_get32((instance)->regmap_handle, \
	(uint32_t *)((uintptr_t)(instance)->regmap + HOST_TBOLT_DIAG_OFF))

#define	WR_TBOLT_HOST_DIAG(v, instance)	ddi_put32((instance)->regmap_handle, \
	(uint32_t *)((uintptr_t)(instance)->regmap + HOST_TBOLT_DIAG_OFF), (v))

#define	RD_TBOLT_RESET_STAT(instance)	ddi_get32((instance)->regmap_handle, \
	(uint32_t *)((uintptr_t)(instance)->regmap + RESET_TBOLT_STATUS_OFF))


#define	WR_MPI2_REPLY_POST_INDEX(v, instance)\
	ddi_put32((instance)->regmap_handle,\
	(uint32_t *)\
	((uintptr_t)(instance)->regmap + MPI2_REPLY_POST_HOST_INDEX_OFFSET),\
	(v))


#define	RD_MPI2_REPLY_POST_INDEX(instance)\
	ddi_get32((instance)->regmap_handle,\
	(uint32_t *)\
	((uintptr_t)(instance)->regmap + MPI2_REPLY_POST_HOST_INDEX_OFFSET))

#define	WR_IB_LOW_QPORT(v, instance) 	ddi_put32((instance)->regmap_handle, \
	(uint32_t *)((uintptr_t)(instance)->regmap + IB_LOW_QPORT), (v))

#define	WR_IB_HIGH_QPORT(v, instance) 	ddi_put32((instance)->regmap_handle, \
	(uint32_t *)((uintptr_t)(instance)->regmap + IB_HIGH_QPORT), (v))

#define	WR_OB_DOORBELL_REGISTER_CLEAR(v, instance)\
	ddi_put32((instance)->regmap_handle,\
	(uint32_t *)((uintptr_t)(instance)->regmap + OB_DOORBELL_REGISTER), \
	(v))

#define	WR_RESERVED0_REGISTER(v, instance) ddi_put32((instance)->regmap_handle,\
	(uint32_t *)((uintptr_t)(instance)->regmap + RESERVED0_REGISTER), \
	(v))

#define	RD_RESERVED0_REGISTER(instance) ddi_get32((instance)->regmap_handle, \
	(uint32_t *)((uintptr_t)(instance)->regmap + RESERVED0_REGISTER))



/*
 * When FW is in MFI_STATE_READY or MFI_STATE_OPERATIONAL, the state data
 * of Outbound Msg Reg 0 indicates max concurrent cmds supported, max SGEs
 * supported per cmd and if 64-bit MFAs (M64) is enabled or disabled.
 */
#define	MFI_OB_INTR_STATUS_MASK		0x00000002

/*
 * This MFI_REPLY_2108_MESSAGE_INTR flag is used also
 * in enable_intr_ppc also. Hence bit 2, i.e. 0x4 has
 * been set in this flag along with bit 1.
 */
#define	MFI_REPLY_2108_MESSAGE_INTR		0x00000001
#define	MFI_REPLY_2108_MESSAGE_INTR_MASK	0x00000005

/* Fusion interrupt mask */
#define	MFI_FUSION_ENABLE_INTERRUPT_MASK	(0x00000008)

#define	MFI_POLL_TIMEOUT_SECS		60

#define	MFI_ENABLE_INTR(instance)  ddi_put32((instance)->regmap_handle, \
	(uint32_t *)((uintptr_t)(instance)->regmap + OB_INTR_MASK_OFF), 1)
#define	MFI_DISABLE_INTR(instance)					\
{									\
	uint32_t disable = 1;						\
	uint32_t mask =  ddi_get32((instance)->regmap_handle, 		\
	    (uint32_t *)((uintptr_t)(instance)->regmap + OB_INTR_MASK_OFF));\
	mask &= ~disable;						\
	ddi_put32((instance)->regmap_handle, (uint32_t *)		\
	    (uintptr_t)((instance)->regmap + OB_INTR_MASK_OFF), mask);	\
}

/* By default, the firmware programs for 8 Kbytes of memory */
#define	DEFAULT_MFI_MEM_SZ	8192
#define	MINIMUM_MFI_MEM_SZ	4096

/* DCMD Message Frame MAILBOX0-11 */
#define	DCMD_MBOX_SZ		12

/*
 * on_off_property of mrsas_ctrl_prop
 * bit0-9, 11-31 are reserved
 */
#define	DISABLE_OCR_PROP_FLAG   0x00000400 /* bit 10 */

struct mrsas_register_set {
	uint32_t	reserved_0[4];			/* 0000h */

	uint32_t	inbound_msg_0;			/* 0010h */
	uint32_t	inbound_msg_1;			/* 0014h */
	uint32_t	outbound_msg_0;			/* 0018h */
	uint32_t	outbound_msg_1;			/* 001Ch */

	uint32_t	inbound_doorbell;		/* 0020h */
	uint32_t	inbound_intr_status;		/* 0024h */
	uint32_t	inbound_intr_mask;		/* 0028h */

	uint32_t	outbound_doorbell;		/* 002Ch */
	uint32_t	outbound_intr_status;		/* 0030h */
	uint32_t	outbound_intr_mask;		/* 0034h */

	uint32_t	reserved_1[2];			/* 0038h */

	uint32_t	inbound_queue_port;		/* 0040h */
	uint32_t	outbound_queue_port;		/* 0044h */

	uint32_t 	reserved_2[22];			/* 0048h */

	uint32_t 	outbound_doorbell_clear;	/* 00A0h */

	uint32_t 	reserved_3[3];			/* 00A4h */

	uint32_t 	outbound_scratch_pad;		/* 00B0h */

	uint32_t 	reserved_4[3];			/* 00B4h */

	uint32_t 	inbound_low_queue_port;		/* 00C0h */

	uint32_t 	inbound_high_queue_port;	/* 00C4h */

	uint32_t 	reserved_5;			/* 00C8h */
	uint32_t 	index_registers[820];		/* 00CCh */
};

struct mrsas_sge32 {
	uint32_t	phys_addr;
	uint32_t	length;
};

struct mrsas_sge64 {
	uint64_t	phys_addr;
	uint32_t	length;
};

struct mrsas_sge_ieee {
	uint64_t 	phys_addr;
	uint32_t	length;
	uint32_t	flag;
};

union mrsas_sgl {
	struct mrsas_sge32	sge32[1];
	struct mrsas_sge64	sge64[1];
	struct mrsas_sge_ieee	sge_ieee[1];
};

struct mrsas_header {
	uint8_t		cmd;				/* 00h */
	uint8_t		sense_len;			/* 01h */
	uint8_t		cmd_status;			/* 02h */
	uint8_t		scsi_status;			/* 03h */

	uint8_t		target_id;			/* 04h */
	uint8_t		lun;				/* 05h */
	uint8_t		cdb_len;			/* 06h */
	uint8_t		sge_count;			/* 07h */

	uint32_t	context;			/* 08h */
	uint8_t		req_id;				/* 0Ch */
	uint8_t		msgvector;			/* 0Dh */
	uint16_t	pad_0;				/* 0Eh */

	uint16_t	flags;				/* 10h */
	uint16_t	timeout;			/* 12h */
	uint32_t	data_xferlen;			/* 14h */
};

union mrsas_sgl_frame {
	struct mrsas_sge32	sge32[8];
	struct mrsas_sge64	sge64[5];
};

struct mrsas_init_frame {
	uint8_t		cmd;				/* 00h */
	uint8_t		reserved_0;			/* 01h */
	uint8_t		cmd_status;			/* 02h */

	uint8_t		reserved_1;			/* 03h */
	uint32_t	reserved_2;			/* 04h */

	uint32_t	context;			/* 08h */
	uint8_t		req_id;				/* 0Ch */
	uint8_t		msgvector;			/* 0Dh */
	uint16_t	pad_0;				/* 0Eh */

	uint16_t	flags;				/* 10h */
	uint16_t	reserved_3;			/* 12h */
	uint32_t	data_xfer_len;			/* 14h */

	uint32_t	queue_info_new_phys_addr_lo;	/* 18h */
	uint32_t	queue_info_new_phys_addr_hi;	/* 1Ch */
	uint32_t	queue_info_old_phys_addr_lo;	/* 20h */
	uint32_t	queue_info_old_phys_addr_hi;	/* 24h */
	uint64_t 	driverversion;			/* 28h */
	uint32_t	reserved_4[4];			/* 30h */
};

struct mrsas_init_queue_info {
	uint32_t		init_flags;			/* 00h */
	uint32_t		reply_queue_entries;		/* 04h */

	uint32_t		reply_queue_start_phys_addr_lo;	/* 08h */
	uint32_t		reply_queue_start_phys_addr_hi;	/* 0Ch */
	uint32_t		producer_index_phys_addr_lo;	/* 10h */
	uint32_t		producer_index_phys_addr_hi;	/* 14h */
	uint32_t		consumer_index_phys_addr_lo;	/* 18h */
	uint32_t		consumer_index_phys_addr_hi;	/* 1Ch */
};

struct mrsas_io_frame {
	uint8_t			cmd;			/* 00h */
	uint8_t			sense_len;		/* 01h */
	uint8_t			cmd_status;		/* 02h */
	uint8_t			scsi_status;		/* 03h */

	uint8_t			target_id;		/* 04h */
	uint8_t			access_byte;		/* 05h */
	uint8_t			reserved_0;		/* 06h */
	uint8_t			sge_count;		/* 07h */

	uint32_t		context;		/* 08h */
	uint8_t			req_id;			/* 0Ch */
	uint8_t			msgvector;		/* 0Dh */
	uint16_t		pad_0;			/* 0Eh */

	uint16_t		flags;			/* 10h */
	uint16_t		timeout;		/* 12h */
	uint32_t		lba_count;		/* 14h */

	uint32_t		sense_buf_phys_addr_lo;	/* 18h */
	uint32_t		sense_buf_phys_addr_hi;	/* 1Ch */

	uint32_t		start_lba_lo;		/* 20h */
	uint32_t		start_lba_hi;		/* 24h */

	union mrsas_sgl		sgl;			/* 28h */
};

struct mrsas_pthru_frame {
	uint8_t			cmd;			/* 00h */
	uint8_t			sense_len;		/* 01h */
	uint8_t			cmd_status;		/* 02h */
	uint8_t			scsi_status;		/* 03h */

	uint8_t			target_id;		/* 04h */
	uint8_t			lun;			/* 05h */
	uint8_t			cdb_len;		/* 06h */
	uint8_t			sge_count;		/* 07h */

	uint32_t		context;		/* 08h */
	uint8_t			req_id;			/* 0Ch */
	uint8_t			msgvector;		/* 0Dh */
	uint16_t		pad_0;			/* 0Eh */

	uint16_t		flags;			/* 10h */
	uint16_t		timeout;		/* 12h */
	uint32_t		data_xfer_len;		/* 14h */

	uint32_t		sense_buf_phys_addr_lo;	/* 18h */
	uint32_t		sense_buf_phys_addr_hi;	/* 1Ch */

	uint8_t			cdb[16];		/* 20h */
	union mrsas_sgl		sgl;			/* 30h */
};

struct mrsas_dcmd_frame {
	uint8_t			cmd;			/* 00h */
	uint8_t			reserved_0;		/* 01h */
	uint8_t			cmd_status;		/* 02h */
	uint8_t			reserved_1[4];		/* 03h */
	uint8_t			sge_count;		/* 07h */

	uint32_t		context;		/* 08h */
	uint8_t			req_id;			/* 0Ch */
	uint8_t			msgvector;		/* 0Dh */
	uint16_t		pad_0;			/* 0Eh */

	uint16_t		flags;			/* 10h */
	uint16_t		timeout;		/* 12h */

	uint32_t		data_xfer_len;		/* 14h */
	uint32_t		opcode;			/* 18h */

	/* uint8_t		mbox[DCMD_MBOX_SZ]; */	/* 1Ch */
	union {						/* 1Ch */
		uint8_t b[DCMD_MBOX_SZ];
		uint16_t s[6];
		uint32_t w[3];
	} mbox;

	union mrsas_sgl		sgl;			/* 28h */
};

struct mrsas_abort_frame {
	uint8_t		cmd;				/* 00h */
	uint8_t		reserved_0;			/* 01h */
	uint8_t		cmd_status;			/* 02h */

	uint8_t		reserved_1;			/* 03h */
	uint32_t	reserved_2;			/* 04h */

	uint32_t	context;			/* 08h */
	uint8_t		req_id;				/* 0Ch */
	uint8_t		msgvector;			/* 0Dh */
	uint16_t	pad_0;				/* 0Eh */

	uint16_t	flags;				/* 10h */
	uint16_t	reserved_3;			/* 12h */
	uint32_t	reserved_4;			/* 14h */

	uint32_t	abort_context;			/* 18h */
	uint32_t	pad_1;				/* 1Ch */

	uint32_t	abort_mfi_phys_addr_lo;		/* 20h */
	uint32_t	abort_mfi_phys_addr_hi;		/* 24h */

	uint32_t	reserved_5[6];			/* 28h */
};

struct mrsas_smp_frame {
	uint8_t		cmd;				/* 00h */
	uint8_t		reserved_1;			/* 01h */
	uint8_t		cmd_status;			/* 02h */
	uint8_t		connection_status;		/* 03h */

	uint8_t		reserved_2[3];			/* 04h */
	uint8_t		sge_count;			/* 07h */

	uint32_t	context;			/* 08h */
	uint8_t		req_id;				/* 0Ch */
	uint8_t		msgvector;			/* 0Dh */
	uint16_t	pad_0;				/* 0Eh */

	uint16_t	flags;				/* 10h */
	uint16_t	timeout;			/* 12h */

	uint32_t	data_xfer_len;			/* 14h */

	uint64_t	sas_addr;			/* 20h */

	union mrsas_sgl	sgl[2];				/* 28h */
};

struct mrsas_stp_frame {
	uint8_t		cmd;				/* 00h */
	uint8_t		reserved_1;			/* 01h */
	uint8_t		cmd_status;			/* 02h */
	uint8_t		connection_status;		/* 03h */

	uint8_t		target_id;			/* 04h */
	uint8_t		reserved_2[2];			/* 04h */
	uint8_t		sge_count;			/* 07h */

	uint32_t	context;			/* 08h */
	uint8_t		req_id;				/* 0Ch */
	uint8_t		msgvector;			/* 0Dh */
	uint16_t	pad_0;				/* 0Eh */

	uint16_t	flags;				/* 10h */
	uint16_t	timeout;			/* 12h */

	uint32_t	data_xfer_len;			/* 14h */

	uint16_t	fis[10];			/* 28h */
	uint32_t	stp_flags;			/* 3C */
	union mrsas_sgl	sgl;				/* 40 */
};

union mrsas_frame {
	struct mrsas_header		hdr;
	struct mrsas_init_frame		init;
	struct mrsas_io_frame		io;
	struct mrsas_pthru_frame	pthru;
	struct mrsas_dcmd_frame		dcmd;
	struct mrsas_abort_frame	abort;
	struct mrsas_smp_frame		smp;
	struct mrsas_stp_frame		stp;

	uint8_t			raw_bytes[64];
};

typedef struct mrsas_pd_address {
	uint16_t	device_id;
	uint16_t	encl_id;

	union {
		struct {
			uint8_t encl_index;
			uint8_t slot_number;
		} pd_address;
		struct {
			uint8_t	encl_position;
			uint8_t	encl_connector_index;
		} encl_address;
	}address;

	uint8_t	scsi_dev_type;

	union {
		uint8_t		port_bitmap;
		uint8_t		port_numbers;
	} connected;

	uint64_t		sas_addr[2];
} mrsas_pd_address_t;

union mrsas_evt_class_locale {
	struct {
		uint16_t	locale;
		uint8_t		reserved;
		int8_t		class;
	} members;

	uint32_t	word;
};

struct mrsas_evt_log_info {
	uint32_t	newest_seq_num;
	uint32_t	oldest_seq_num;
	uint32_t	clear_seq_num;
	uint32_t	shutdown_seq_num;
	uint32_t	boot_seq_num;
};

struct mrsas_progress {
	uint16_t	progress;
	uint16_t	elapsed_seconds;
};

struct mrsas_evtarg_ld {
	uint16_t	target_id;
	uint8_t		ld_index;
	uint8_t		reserved;
};

struct mrsas_evtarg_pd {
	uint16_t	device_id;
	uint8_t		encl_index;
	uint8_t		slot_number;
};

struct mrsas_evt_detail {
	uint32_t	seq_num;
	uint32_t	time_stamp;
	uint32_t	code;
	union mrsas_evt_class_locale	cl;
	uint8_t		arg_type;
	uint8_t		reserved1[15];

	union {
		struct {
			struct mrsas_evtarg_pd	pd;
			uint8_t			cdb_length;
			uint8_t			sense_length;
			uint8_t			reserved[2];
			uint8_t			cdb[16];
			uint8_t			sense[64];
		} cdbSense;

		struct mrsas_evtarg_ld		ld;

		struct {
			struct mrsas_evtarg_ld	ld;
			uint64_t		count;
		} ld_count;

		struct {
			uint64_t		lba;
			struct mrsas_evtarg_ld	ld;
		} ld_lba;

		struct {
			struct mrsas_evtarg_ld	ld;
			uint32_t		prevOwner;
			uint32_t		newOwner;
		} ld_owner;

		struct {
			uint64_t		ld_lba;
			uint64_t		pd_lba;
			struct mrsas_evtarg_ld	ld;
			struct mrsas_evtarg_pd	pd;
		} ld_lba_pd_lba;

		struct {
			struct mrsas_evtarg_ld	ld;
			struct mrsas_progress	prog;
		} ld_prog;

		struct {
			struct mrsas_evtarg_ld	ld;
			uint32_t		prev_state;
			uint32_t		new_state;
		} ld_state;

		struct {
			uint64_t		strip;
			struct mrsas_evtarg_ld	ld;
		} ld_strip;

		struct mrsas_evtarg_pd		pd;

		struct {
			struct mrsas_evtarg_pd	pd;
			uint32_t		err;
		} pd_err;

		struct {
			uint64_t		lba;
			struct mrsas_evtarg_pd	pd;
		} pd_lba;

		struct {
			uint64_t		lba;
			struct mrsas_evtarg_pd	pd;
			struct mrsas_evtarg_ld	ld;
		} pd_lba_ld;

		struct {
			struct mrsas_evtarg_pd	pd;
			struct mrsas_progress	prog;
		} pd_prog;

		struct {
			struct mrsas_evtarg_pd	pd;
			uint32_t		prevState;
			uint32_t		newState;
		} pd_state;

		struct {
			uint16_t	vendorId;
			uint16_t	deviceId;
			uint16_t	subVendorId;
			uint16_t	subDeviceId;
		} pci;

		uint32_t	rate;
		char		str[96];

		struct {
			uint32_t	rtc;
			uint32_t	elapsedSeconds;
		} time;

		struct {
			uint32_t	ecar;
			uint32_t	elog;
			char		str[64];
		} ecc;

		mrsas_pd_address_t	pd_addr;

		uint8_t		b[96];
		uint16_t	s[48];
		uint32_t	w[24];
		uint64_t	d[12];
	} args;

	char	description[128];

};

/* only 63 are usable by the application */
#define	MAX_LOGICAL_DRIVES			64
/* only 255 physical devices may be used */
#define	MAX_PHYSICAL_DEVICES			256
#define	MAX_PD_PER_ENCLOSURE			64
/* maximum disks per array */
#define	MAX_ROW_SIZE				32
/* maximum spans per logical drive */
#define	MAX_SPAN_DEPTH				8
/* maximum number of arrays a hot spare may be dedicated to */
#define	MAX_ARRAYS_DEDICATED			16
/* maximum number of arrays which may exist */
#define	MAX_ARRAYS				128
/* maximum number of foreign configs that may ha managed at once */
#define	MAX_FOREIGN_CONFIGS			8
/* maximum spares (global and dedicated combined) */
#define	MAX_SPARES_FOR_THE_CONTROLLER		MAX_PHYSICAL_DEVICES
/* maximum possible Target IDs (i.e. 0 to 63) */
#define	MAX_TARGET_ID				63
/* maximum number of supported enclosures */
#define	MAX_ENCLOSURES				32
/* maximum number of PHYs per controller */
#define	MAX_PHYS_PER_CONTROLLER			16
/* maximum number of LDs per array (due to DDF limitations) */
#define	MAX_LDS_PER_ARRAY			16

/*
 * -----------------------------------------------------------------------------
 * -----------------------------------------------------------------------------
 *
 * Logical Drive commands
 *
 * -----------------------------------------------------------------------------
 * -----------------------------------------------------------------------------
 */
#define	MR_DCMD_LD	0x03000000,	/* Logical Device (LD) opcodes */

/*
 * Input:	dcmd.opcode	- MR_DCMD_LD_GET_LIST
 *		dcmd.mbox	- reserved
 *		dcmd.sge IN	- ptr to returned MR_LD_LIST structure
 * Desc:	Return the logical drive list structure
 * Status:	No error
 */

/*
 * defines the logical drive reference structure
 */
typedef	union _MR_LD_REF {	/* LD reference structure */
	struct {
		uint8_t	targetId; /* LD target id (0 to MAX_TARGET_ID) */
		uint8_t	reserved; /* reserved for in line with MR_PD_REF */
		uint16_t seqNum;  /* Sequence Number */
	} ld_ref;
	uint32_t ref;		/* shorthand reference to full 32-bits */
} MR_LD_REF;			/* 4 bytes */

/*
 * defines the logical drive list structure
 */
typedef struct _MR_LD_LIST {
	uint32_t	ldCount;	/* number of LDs */
	uint32_t	reserved;	/* pad to 8-byte boundary */
	struct {
		MR_LD_REF ref;	/* LD reference */
		uint8_t	state;		/* current LD state (MR_LD_STATE) */
		uint8_t	reserved[3];	/* pad to 8-byte boundary */
		uint64_t size;		/* LD size */
	} ldList[MAX_LOGICAL_DRIVES];
} MR_LD_LIST;

struct mrsas_drv_ver {
	uint8_t	signature[12];
	uint8_t	os_name[16];
	uint8_t	os_ver[12];
	uint8_t	drv_name[20];
	uint8_t	drv_ver[32];
	uint8_t	drv_rel_date[20];
};

#define	PCI_TYPE0_ADDRESSES		6
#define	PCI_TYPE1_ADDRESSES		2
#define	PCI_TYPE2_ADDRESSES		5

struct mrsas_pci_common_header {
	uint16_t	vendorID;		/* (ro) */
	uint16_t	deviceID;		/* (ro) */
	uint16_t	command;		/* Device control */
	uint16_t	status;
	uint8_t		revisionID;		/* (ro) */
	uint8_t		progIf;			/* (ro) */
	uint8_t		subClass;		/* (ro) */
	uint8_t		baseClass;		/* (ro) */
	uint8_t		cacheLineSize;		/* (ro+) */
	uint8_t		latencyTimer;		/* (ro+) */
	uint8_t		headerType;		/* (ro) */
	uint8_t		bist;			/* Built in self test */

	union {
	    struct {
		uint32_t	baseAddresses[PCI_TYPE0_ADDRESSES];
		uint32_t	cis;
		uint16_t	subVendorID;
		uint16_t	subSystemID;
		uint32_t	romBaseAddress;
		uint8_t		capabilitiesPtr;
		uint8_t		reserved1[3];
		uint32_t	reserved2;
		uint8_t		interruptLine;
		uint8_t		interruptPin;	/* (ro) */
		uint8_t		minimumGrant;	/* (ro) */
		uint8_t		maximumLatency;	/* (ro) */
	    } type_0;

	    struct {
		uint32_t	baseAddresses[PCI_TYPE1_ADDRESSES];
		uint8_t		primaryBus;
		uint8_t		secondaryBus;
		uint8_t		subordinateBus;
		uint8_t		secondaryLatency;
		uint8_t		ioBase;
		uint8_t		ioLimit;
		uint16_t	secondaryStatus;
		uint16_t	memoryBase;
		uint16_t	memoryLimit;
		uint16_t	prefetchBase;
		uint16_t	prefetchLimit;
		uint32_t	prefetchBaseUpper32;
		uint32_t	prefetchLimitUpper32;
		uint16_t	ioBaseUpper16;
		uint16_t	ioLimitUpper16;
		uint8_t		capabilitiesPtr;
		uint8_t		reserved1[3];
		uint32_t	romBaseAddress;
		uint8_t		interruptLine;
		uint8_t		interruptPin;
		uint16_t	bridgeControl;
	    } type_1;

	    struct {
		uint32_t	socketRegistersBaseAddress;
		uint8_t		capabilitiesPtr;
		uint8_t		reserved;
		uint16_t	secondaryStatus;
		uint8_t		primaryBus;
		uint8_t		secondaryBus;
		uint8_t		subordinateBus;
		uint8_t		secondaryLatency;
		struct {
			uint32_t	base;
			uint32_t	limit;
		} range[PCI_TYPE2_ADDRESSES-1];
		uint8_t		interruptLine;
		uint8_t		interruptPin;
		uint16_t	bridgeControl;
	    } type_2;
	} header;
};

struct mrsas_pci_link_capability {
	union {
	    struct {
		uint32_t linkSpeed		:4;
		uint32_t linkWidth		:6;
		uint32_t aspmSupport		:2;
		uint32_t losExitLatency		:3;
		uint32_t l1ExitLatency		:3;
		uint32_t rsvdp			:6;
		uint32_t portNumber		:8;
	    } bits;

	    uint32_t asUlong;
	} cap;

};

struct mrsas_pci_link_status_capability {
	union {
	    struct {
		uint16_t linkSpeed		:4;
		uint16_t negotiatedLinkWidth	:6;
		uint16_t linkTrainingError	:1;
		uint16_t linkTraning		:1;
		uint16_t slotClockConfig	:1;
		uint16_t rsvdZ			:3;
	    } bits;

	    uint16_t asUshort;
	} stat_cap;

	uint16_t reserved;

};

struct mrsas_pci_capabilities {
	struct mrsas_pci_link_capability	linkCapability;
	struct mrsas_pci_link_status_capability linkStatusCapability;
};

struct mrsas_pci_information
{
	uint32_t		busNumber;
	uint8_t			deviceNumber;
	uint8_t			functionNumber;
	uint8_t			interruptVector;
	uint8_t			reserved;
	struct mrsas_pci_common_header pciHeaderInfo;
	struct mrsas_pci_capabilities capability;
	uint8_t			reserved2[32];
};

struct mrsas_ioctl {
	uint16_t	version;
	uint16_t	controller_id;
	uint8_t		signature[8];
	uint32_t	reserved_1;
	uint32_t	control_code;
	uint32_t	reserved_2[2];
	uint8_t		frame[64];
	union mrsas_sgl_frame sgl_frame;
	uint8_t		sense_buff[MRSAS_MAX_SENSE_LENGTH];
	uint8_t		data[1];
};

struct mrsas_aen {
	uint16_t	host_no;
	uint16_t	cmd_status;
	uint32_t	seq_num;
	uint32_t	class_locale_word;
};

#pragma pack()

#ifndef	DDI_VENDOR_LSI
#define	DDI_VENDOR_LSI		"LSI"
#endif /* DDI_VENDOR_LSI */

int mrsas_config_scsi_device(struct mrsas_instance *,
    struct scsi_device *, dev_info_t **);

#ifdef PDSUPPORT
int mrsas_tbolt_config_pd(struct mrsas_instance *, uint16_t,
    uint8_t, dev_info_t **);
#endif

dev_info_t *mrsas_find_child(struct mrsas_instance *, uint16_t, uint8_t);
int mrsas_service_evt(struct mrsas_instance *, int, int, int, uint64_t);
void return_raid_msg_pkt(struct mrsas_instance *, struct mrsas_cmd *);
struct mrsas_cmd *get_raid_msg_mfi_pkt(struct mrsas_instance *);
void return_raid_msg_mfi_pkt(struct mrsas_instance *, struct mrsas_cmd *);

int	alloc_space_for_mpi2(struct mrsas_instance *);
void	fill_up_drv_ver(struct mrsas_drv_ver *dv);

int	mrsas_issue_init_mpi2(struct mrsas_instance *);
struct scsi_pkt *mrsas_tbolt_tran_init_pkt(struct scsi_address *, register
		    struct scsi_pkt *, struct buf *, int, int, int, int,
		    int (*)(), caddr_t);
int	mrsas_tbolt_tran_start(struct scsi_address *,
		    register struct scsi_pkt *);
uint32_t tbolt_read_fw_status_reg(struct mrsas_instance *);
void 	tbolt_issue_cmd(struct mrsas_cmd *, struct mrsas_instance *);
int	tbolt_issue_cmd_in_poll_mode(struct mrsas_instance *,
		    struct mrsas_cmd *);
int	tbolt_issue_cmd_in_sync_mode(struct mrsas_instance *,
		    struct mrsas_cmd *);
void	tbolt_enable_intr(struct mrsas_instance *);
void	tbolt_disable_intr(struct mrsas_instance *);
int	tbolt_intr_ack(struct mrsas_instance *);
uint_t	mr_sas_tbolt_process_outstanding_cmd(struct mrsas_instance *);
    uint_t tbolt_softintr();
int 	mrsas_tbolt_dma(struct mrsas_instance *, uint32_t, int, int (*)());
int	mrsas_check_dma_handle(ddi_dma_handle_t handle);
int	mrsas_check_acc_handle(ddi_acc_handle_t handle);
int	mrsas_dma_alloc(struct mrsas_instance *, struct scsi_pkt *,
		    struct buf *, int, int (*)());
int	mrsas_dma_move(struct mrsas_instance *,
			struct scsi_pkt *, struct buf *);
int	mrsas_alloc_dma_obj(struct mrsas_instance *, dma_obj_t *,
		    uchar_t);
void 	mr_sas_tbolt_build_mfi_cmd(struct mrsas_instance *, struct mrsas_cmd *);
int 	mrsas_dma_alloc_dmd(struct mrsas_instance *, dma_obj_t *);
void 	tbolt_complete_cmd_in_sync_mode(struct mrsas_instance *,
	struct mrsas_cmd *);
int 	alloc_req_rep_desc(struct mrsas_instance *);
int		mrsas_mode_sense_build(struct scsi_pkt *);
void		push_pending_mfi_pkt(struct mrsas_instance *,
			struct mrsas_cmd *);
int	mrsas_issue_pending_cmds(struct mrsas_instance *);
int 	mrsas_print_pending_cmds(struct mrsas_instance *);
int  	mrsas_complete_pending_cmds(struct mrsas_instance *);

int	create_mfi_frame_pool(struct mrsas_instance *);
void	destroy_mfi_frame_pool(struct mrsas_instance *);
int 	create_mfi_mpi_frame_pool(struct mrsas_instance *);
void 	destroy_mfi_mpi_frame_pool(struct mrsas_instance *);
int 	create_mpi2_frame_pool(struct mrsas_instance *);
void 	destroy_mpi2_frame_pool(struct mrsas_instance *);
int	mrsas_free_dma_obj(struct mrsas_instance *, dma_obj_t);
void 	mrsas_tbolt_free_additional_dma_buffer(struct mrsas_instance *);
void 	free_req_desc_pool(struct mrsas_instance *);
void 	free_space_for_mpi2(struct mrsas_instance *);
void 	mrsas_dump_reply_desc(struct mrsas_instance *);
void 	tbolt_complete_cmd(struct mrsas_instance *, struct mrsas_cmd *);
void	display_scsi_inquiry(caddr_t);
void	service_mfi_aen(struct mrsas_instance *, struct mrsas_cmd *);
int	mrsas_mode_sense_build(struct scsi_pkt *);
int 	mrsas_tbolt_get_ld_map_info(struct mrsas_instance *);
struct mrsas_cmd *mrsas_tbolt_build_poll_cmd(struct mrsas_instance *,
	struct scsi_address *, struct scsi_pkt *, uchar_t *);
int	mrsas_tbolt_reset_ppc(struct mrsas_instance *instance);
void	mrsas_tbolt_kill_adapter(struct mrsas_instance *instance);
int 	abort_syncmap_cmd(struct mrsas_instance *, struct mrsas_cmd *);
void	mrsas_tbolt_prepare_cdb(struct mrsas_instance *instance, U8 cdb[],
    struct IO_REQUEST_INFO *, Mpi2RaidSCSIIORequest_t *, U32);


int mrsas_init_adapter_ppc(struct mrsas_instance *instance);
int mrsas_init_adapter_tbolt(struct mrsas_instance *instance);
int mrsas_init_adapter(struct mrsas_instance *instance);

int mrsas_alloc_cmd_pool(struct mrsas_instance *instance);
void mrsas_free_cmd_pool(struct mrsas_instance *instance);

void mrsas_print_cmd_details(struct mrsas_instance *, struct mrsas_cmd *, int);
struct mrsas_cmd *get_raid_msg_pkt(struct mrsas_instance *);

int mfi_state_transition_to_ready(struct mrsas_instance *);


/* FMA functions. */
int mrsas_common_check(struct mrsas_instance *, struct  mrsas_cmd *);
void mrsas_fm_ereport(struct mrsas_instance *, char *);


#ifdef	__cplusplus
}
#endif

#endif /* _MR_SAS_H_ */