code:
/*-
 * Copyright (c) 2006 IronPort Systems
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */
/*-
 * Copyright (c) 2007 LSI Corp.
 * Copyright (c) 2007 Rajesh Prabhakaran.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef _MFIREG_H
#define _MFIREG_H

#include <sys/cdefs.h>
__FBSDID("$FreeBSD: release/9.0.0/sys/dev/mfi/mfireg.h 224041 2011-07-14 20:20:33Z jhb $");

/*
 * MegaRAID SAS MFI firmware definitions
 *
 * Calling this driver 'MegaRAID SAS' is a bit misleading.  It's a completely
 * new firmware interface from the old AMI MegaRAID one, and there is no
 * reason why this interface should be limited to just SAS.  In any case, LSI
 * seems to also call this interface 'MFI', so that will be used here.
 */

/*
 * Start with the register set.  All registers are 32 bits wide.
 * The usual Intel IOP style setup.
 */
#define MFI_IMSG0	0x10	/* Inbound message 0 */
#define MFI_IMSG1	0x14	/* Inbound message 1 */
#define MFI_OMSG0	0x18	/* Outbound message 0 */
#define MFI_OMSG1	0x1c	/* Outbound message 1 */
#define MFI_IDB		0x20	/* Inbound doorbell */
#define MFI_ISTS	0x24	/* Inbound interrupt status */
#define MFI_IMSK	0x28	/* Inbound interrupt mask */
#define MFI_ODB		0x2c	/* Outbound doorbell */
#define MFI_OSTS	0x30	/* Outbound interrupt status */
#define MFI_OMSK	0x34	/* Outbound interrupt mask */
#define MFI_IQP		0x40	/* Inbound queue port */
#define MFI_OQP		0x44	/* Outbound queue port */

/*
 * 1078 specific related register
 */
#define MFI_ODR0	0x9c 		/* outbound doorbell register0 */
#define MFI_ODCR0	0xa0 		/* outbound doorbell clear register0  */
#define MFI_OSP0	0xb0 		/* outbound scratch pad0  */
#define MFI_1078_EIM	0x80000004 	/* 1078 enable intrrupt mask  */
#define MFI_RMI		0x2 		/* reply message interrupt  */
#define MFI_1078_RM	0x80000000 	/* reply 1078 message interrupt  */
#define MFI_ODC		0x4 		/* outbound doorbell change interrupt */

/*
 * GEN2 specific changes
 */
#define MFI_GEN2_EIM	0x00000005	/* GEN2 enable interrupt mask */
#define MFI_GEN2_RM	0x00000001	/* reply GEN2 message interrupt */

/* Bits for MFI_OSTS */
#define MFI_OSTS_INTR_VALID	0x00000002

/*
 * Firmware state values.  Found in OMSG0 during initialization.
 */
#define MFI_FWSTATE_MASK		0xf0000000
#define MFI_FWSTATE_UNDEFINED		0x00000000
#define MFI_FWSTATE_BB_INIT		0x10000000
#define MFI_FWSTATE_FW_INIT		0x40000000
#define MFI_FWSTATE_WAIT_HANDSHAKE	0x60000000
#define MFI_FWSTATE_FW_INIT_2		0x70000000
#define MFI_FWSTATE_DEVICE_SCAN		0x80000000
#define MFI_FWSTATE_BOOT_MESSAGE_PENDING	0x90000000
#define MFI_FWSTATE_FLUSH_CACHE		0xa0000000
#define MFI_FWSTATE_READY		0xb0000000
#define MFI_FWSTATE_OPERATIONAL		0xc0000000
#define MFI_FWSTATE_FAULT		0xf0000000
#define MFI_FWSTATE_MAXSGL_MASK		0x00ff0000
#define MFI_FWSTATE_MAXCMD_MASK		0x0000ffff

/*
 * Control bits to drive the card to ready state.  These go into the IDB
 * register.
 */
#define MFI_FWINIT_ABORT	0x00000000 /* Abort all pending commands */
#define MFI_FWINIT_READY	0x00000002 /* Move from operational to ready */
#define MFI_FWINIT_MFIMODE	0x00000004 /* unknown */
#define MFI_FWINIT_CLEAR_HANDSHAKE 0x00000008 /* Respond to WAIT_HANDSHAKE */
#define MFI_FWINIT_HOTPLUG	0x00000010

/* MFI Commands */
typedef enum {
	MFI_CMD_INIT =		0x00,
	MFI_CMD_LD_READ,
	MFI_CMD_LD_WRITE,
	MFI_CMD_LD_SCSI_IO,
	MFI_CMD_PD_SCSI_IO,
	MFI_CMD_DCMD,
	MFI_CMD_ABORT,
	MFI_CMD_SMP,
	MFI_CMD_STP
} mfi_cmd_t;

/* Direct commands */
typedef enum {
	MFI_DCMD_CTRL_GETINFO =		0x01010000,
	MFI_DCMD_CTRL_MFC_DEFAULTS_GET =0x010e0201,
	MFI_DCMD_CTRL_MFC_DEFAULTS_SET =0x010e0202,
	MFI_DCMD_CTRL_FLUSHCACHE =	0x01101000,
	MFI_DCMD_CTRL_SHUTDOWN =	0x01050000,
	MFI_DCMD_CTRL_EVENT_GETINFO =	0x01040100,
	MFI_DCMD_CTRL_EVENT_GET =	0x01040300,
	MFI_DCMD_CTRL_EVENT_WAIT =	0x01040500,
	MFI_DCMD_PR_GET_STATUS =	0x01070100,
	MFI_DCMD_PR_GET_PROPERTIES =	0x01070200,
	MFI_DCMD_PR_SET_PROPERTIES =	0x01070300,
	MFI_DCMD_PR_START =		0x01070400,
	MFI_DCMD_PR_STOP =		0x01070500,
	MFI_DCMD_TIME_SECS_GET =	0x01080201,
	MFI_DCMD_FLASH_FW_OPEN =	0x010f0100,
	MFI_DCMD_FLASH_FW_DOWNLOAD =	0x010f0200,
	MFI_DCMD_FLASH_FW_FLASH =	0x010f0300,
	MFI_DCMD_FLASH_FW_CLOSE =	0x010f0400,
	MFI_DCMD_PD_GET_LIST =		0x02010000,
	MFI_DCMD_PD_GET_INFO = 		0x02020000,
	MFI_DCMD_PD_STATE_SET =		0x02030100,
	MFI_DCMD_PD_REBUILD_START =	0x02040100,
	MFI_DCMD_PD_REBUILD_ABORT =	0x02040200,
	MFI_DCMD_PD_CLEAR_START =	0x02050100,
	MFI_DCMD_PD_CLEAR_ABORT =	0x02050200,
	MFI_DCMD_PD_GET_PROGRESS =	0x02060000,
	MFI_DCMD_PD_LOCATE_START =	0x02070100,
	MFI_DCMD_PD_LOCATE_STOP =	0x02070200,
	MFI_DCMD_LD_GET_LIST =		0x03010000,
	MFI_DCMD_LD_GET_INFO =		0x03020000,
	MFI_DCMD_LD_GET_PROP =		0x03030000,
	MFI_DCMD_LD_SET_PROP =		0x03040000,
	MFI_DCMD_LD_INIT_START =	0x03060100,
	MFI_DCMD_LD_DELETE =		0x03090000,
	MFI_DCMD_CFG_READ =		0x04010000,
	MFI_DCMD_CFG_ADD =		0x04020000,
	MFI_DCMD_CFG_CLEAR =		0x04030000,
	MFI_DCMD_CFG_MAKE_SPARE =	0x04040000,
	MFI_DCMD_CFG_REMOVE_SPARE =	0x04050000,
	MFI_DCMD_CFG_FOREIGN_IMPORT =	0x04060400,
	MFI_DCMD_BBU_GET_STATUS =	0x05010000,
	MFI_DCMD_BBU_GET_CAPACITY_INFO =0x05020000,
	MFI_DCMD_BBU_GET_DESIGN_INFO =	0x05030000,
	MFI_DCMD_CLUSTER =		0x08000000,
	MFI_DCMD_CLUSTER_RESET_ALL =	0x08010100,
	MFI_DCMD_CLUSTER_RESET_LD =	0x08010200
} mfi_dcmd_t;

/* Modifiers for MFI_DCMD_CTRL_FLUSHCACHE */
#define MFI_FLUSHCACHE_CTRL	0x01
#define MFI_FLUSHCACHE_DISK	0x02

/* Modifiers for MFI_DCMD_CTRL_SHUTDOWN */
#define MFI_SHUTDOWN_SPINDOWN	0x01

/*
 * 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

/* MFI Status codes */
typedef enum {
	MFI_STAT_OK =			0x00,
	MFI_STAT_INVALID_CMD,
	MFI_STAT_INVALID_DCMD,
	MFI_STAT_INVALID_PARAMETER,
	MFI_STAT_INVALID_SEQUENCE_NUMBER,
	MFI_STAT_ABORT_NOT_POSSIBLE,
	MFI_STAT_APP_HOST_CODE_NOT_FOUND,
	MFI_STAT_APP_IN_USE,
	MFI_STAT_APP_NOT_INITIALIZED,
	MFI_STAT_ARRAY_INDEX_INVALID,
	MFI_STAT_ARRAY_ROW_NOT_EMPTY,
	MFI_STAT_CONFIG_RESOURCE_CONFLICT,
	MFI_STAT_DEVICE_NOT_FOUND,
	MFI_STAT_DRIVE_TOO_SMALL,
	MFI_STAT_FLASH_ALLOC_FAIL,
	MFI_STAT_FLASH_BUSY,
	MFI_STAT_FLASH_ERROR =		0x10,
	MFI_STAT_FLASH_IMAGE_BAD,
	MFI_STAT_FLASH_IMAGE_INCOMPLETE,
	MFI_STAT_FLASH_NOT_OPEN,
	MFI_STAT_FLASH_NOT_STARTED,
	MFI_STAT_FLUSH_FAILED,
	MFI_STAT_HOST_CODE_NOT_FOUNT,
	MFI_STAT_LD_CC_IN_PROGRESS,
	MFI_STAT_LD_INIT_IN_PROGRESS,
	MFI_STAT_LD_LBA_OUT_OF_RANGE,
	MFI_STAT_LD_MAX_CONFIGURED,
	MFI_STAT_LD_NOT_OPTIMAL,
	MFI_STAT_LD_RBLD_IN_PROGRESS,
	MFI_STAT_LD_RECON_IN_PROGRESS,
	MFI_STAT_LD_WRONG_RAID_LEVEL,
	MFI_STAT_MAX_SPARES_EXCEEDED,
	MFI_STAT_MEMORY_NOT_AVAILABLE =	0x20,
	MFI_STAT_MFC_HW_ERROR,
	MFI_STAT_NO_HW_PRESENT,
	MFI_STAT_NOT_FOUND,
	MFI_STAT_NOT_IN_ENCL,
	MFI_STAT_PD_CLEAR_IN_PROGRESS,
	MFI_STAT_PD_TYPE_WRONG,
	MFI_STAT_PR_DISABLED,
	MFI_STAT_ROW_INDEX_INVALID,
	MFI_STAT_SAS_CONFIG_INVALID_ACTION,
	MFI_STAT_SAS_CONFIG_INVALID_DATA,
	MFI_STAT_SAS_CONFIG_INVALID_PAGE,
	MFI_STAT_SAS_CONFIG_INVALID_TYPE,
	MFI_STAT_SCSI_DONE_WITH_ERROR,
	MFI_STAT_SCSI_IO_FAILED,
	MFI_STAT_SCSI_RESERVATION_CONFLICT,
	MFI_STAT_SHUTDOWN_FAILED =	0x30,
	MFI_STAT_TIME_NOT_SET,
	MFI_STAT_WRONG_STATE,
	MFI_STAT_LD_OFFLINE,
	MFI_STAT_PEER_NOTIFICATION_REJECTED,
	MFI_STAT_PEER_NOTIFICATION_FAILED,
	MFI_STAT_RESERVATION_IN_PROGRESS,
	MFI_STAT_I2C_ERRORS_DETECTED,
	MFI_STAT_PCI_ERRORS_DETECTED,
	MFI_STAT_DIAG_FAILED,
	MFI_STAT_BOOT_MSG_PENDING,
	MFI_STAT_FOREIGN_CONFIG_INCOMPLETE,
	MFI_STAT_INVALID_STATUS =	0xFF
} mfi_status_t;

typedef enum {
	MFI_EVT_CLASS_DEBUG =		-2,
	MFI_EVT_CLASS_PROGRESS =	-1,
	MFI_EVT_CLASS_INFO =		0,
	MFI_EVT_CLASS_WARNING =		1,
	MFI_EVT_CLASS_CRITICAL =	2,
	MFI_EVT_CLASS_FATAL =		3,
	MFI_EVT_CLASS_DEAD =		4
} mfi_evt_class_t;

typedef enum {
	MFI_EVT_LOCALE_LD =		0x0001,
	MFI_EVT_LOCALE_PD =		0x0002,
	MFI_EVT_LOCALE_ENCL =		0x0004,
	MFI_EVT_LOCALE_BBU =		0x0008,
	MFI_EVT_LOCALE_SAS =		0x0010,
	MFI_EVT_LOCALE_CTRL =		0x0020,
	MFI_EVT_LOCALE_CONFIG =		0x0040,
	MFI_EVT_LOCALE_CLUSTER =	0x0080,
	MFI_EVT_LOCALE_ALL =		0xffff
} mfi_evt_locale_t;

typedef enum {
	MR_EVT_ARGS_NONE =		0x00,
	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
} mfi_evt_args;

typedef enum {
	MR_LD_CACHE_WRITE_BACK =	0x01,
	MR_LD_CACHE_WRITE_ADAPTIVE =	0x02,
	MR_LD_CACHE_READ_AHEAD =	0x04,
	MR_LD_CACHE_READ_ADAPTIVE =	0x08,
	MR_LD_CACHE_WRITE_CACHE_BAD_BBU=0x10,
	MR_LD_CACHE_ALLOW_WRITE_CACHE =	0x20,
	MR_LD_CACHE_ALLOW_READ_CACHE =	0x40
} mfi_ld_cache;
#define	MR_LD_CACHE_MASK	0x7f

#define	MR_LD_CACHE_POLICY_READ_AHEAD_NONE		0
#define	MR_LD_CACHE_POLICY_READ_AHEAD_ALWAYS		MR_LD_CACHE_READ_AHEAD
#define	MR_LD_CACHE_POLICY_READ_AHEAD_ADAPTIVE		\
	(MR_LD_CACHE_READ_AHEAD | MR_LD_CACHE_READ_ADAPTIVE)
#define	MR_LD_CACHE_POLICY_WRITE_THROUGH		0
#define	MR_LD_CACHE_POLICY_WRITE_BACK			MR_LD_CACHE_WRITE_BACK
#define	MR_LD_CACHE_POLICY_IO_CACHED			\
	(MR_LD_CACHE_ALLOW_WRITE_CACHE | MR_LD_CACHE_ALLOW_READ_CACHE)
#define	MR_LD_CACHE_POLICY_IO_DIRECT			0

typedef enum {
	MR_PD_CACHE_UNCHANGED  =	0,
	MR_PD_CACHE_ENABLE =		1,
	MR_PD_CACHE_DISABLE =		2
} mfi_pd_cache;

/*
 * Other propertities and definitions
 */
#define MFI_MAX_PD_CHANNELS	2
#define MFI_MAX_LD_CHANNELS	2
#define MFI_MAX_CHANNELS	(MFI_MAX_PD_CHANNELS + MFI_MAX_LD_CHANNELS)
#define MFI_MAX_CHANNEL_DEVS	128
#define MFI_DEFAULT_ID		-1
#define MFI_MAX_LUN		8
#define MFI_MAX_LD		64
#define	MFI_MAX_PD		256

#define MFI_FRAME_SIZE		64
#define MFI_MBOX_SIZE		12

/* Firmware flashing can take 40s */
#define MFI_POLL_TIMEOUT_SECS	50

/* Allow for speedier math calculations */
#define MFI_SECTOR_LEN		512

/* Scatter Gather elements */
struct mfi_sg32 {
	uint32_t	addr;
	uint32_t	len;
} __packed;

struct mfi_sg64 {
	uint64_t	addr;
	uint32_t	len;
} __packed;

union mfi_sgl {
	struct mfi_sg32	sg32[1];
	struct mfi_sg64	sg64[1];
} __packed;

/* Message frames.  All messages have a common header */
struct mfi_frame_header {
	uint8_t		cmd;
	uint8_t		sense_len;
	uint8_t		cmd_status;
	uint8_t		scsi_status;
	uint8_t		target_id;
	uint8_t		lun_id;
	uint8_t		cdb_len;
	uint8_t		sg_count;
	uint32_t	context;
	uint32_t	pad0;
	uint16_t	flags;
#define MFI_FRAME_DATAOUT	0x08
#define MFI_FRAME_DATAIN	0x10
	uint16_t	timeout;
	uint32_t	data_len;
} __packed;

struct mfi_init_frame {
	struct mfi_frame_header	header;
	uint32_t	qinfo_new_addr_lo;
	uint32_t	qinfo_new_addr_hi;
	uint32_t	qinfo_old_addr_lo;
	uint32_t	qinfo_old_addr_hi;
	uint32_t	reserved[6];
} __packed;

#define MFI_IO_FRAME_SIZE 40
struct mfi_io_frame {
	struct mfi_frame_header	header;
	uint32_t	sense_addr_lo;
	uint32_t	sense_addr_hi;
	uint32_t	lba_lo;
	uint32_t	lba_hi;
	union mfi_sgl	sgl;
} __packed;

#define MFI_PASS_FRAME_SIZE 48
struct mfi_pass_frame {
	struct mfi_frame_header header;
	uint32_t	sense_addr_lo;
	uint32_t	sense_addr_hi;
	uint8_t		cdb[16];
	union mfi_sgl	sgl;
} __packed;

#define MFI_DCMD_FRAME_SIZE 40
struct mfi_dcmd_frame {
	struct mfi_frame_header header;
	uint32_t	opcode;
	uint8_t		mbox[MFI_MBOX_SIZE];
	union mfi_sgl	sgl;
} __packed;

struct mfi_abort_frame {
	struct mfi_frame_header header;
	uint32_t	abort_context;
	uint32_t	pad;
	uint32_t	abort_mfi_addr_lo;
	uint32_t	abort_mfi_addr_hi;
	uint32_t	reserved[6];
} __packed;

struct mfi_smp_frame {
	struct mfi_frame_header header;
	uint64_t	sas_addr;
	union {
		struct mfi_sg32 sg32[2];
		struct mfi_sg64 sg64[2];
	} sgl;
} __packed;

struct mfi_stp_frame {
	struct mfi_frame_header header;
	uint16_t	fis[10];
	uint32_t	stp_flags;
	union {
		struct mfi_sg32 sg32[2];
		struct mfi_sg64 sg64[2];
	} sgl;
} __packed;

union mfi_frame {
	struct mfi_frame_header header;
	struct mfi_init_frame	init;
	struct mfi_io_frame	io;
	struct mfi_pass_frame	pass;
	struct mfi_dcmd_frame	dcmd;
	struct mfi_abort_frame	abort;
	struct mfi_smp_frame	smp;
	struct mfi_stp_frame	stp;
	uint8_t			bytes[MFI_FRAME_SIZE];
};

#define MFI_SENSE_LEN 128
struct mfi_sense {
	uint8_t		data[MFI_SENSE_LEN];
};

/* The queue init structure that is passed with the init message */
struct mfi_init_qinfo {
	uint32_t	flags;
	uint32_t	rq_entries;
	uint32_t	rq_addr_lo;
	uint32_t	rq_addr_hi;
	uint32_t	pi_addr_lo;
	uint32_t	pi_addr_hi;
	uint32_t	ci_addr_lo;
	uint32_t	ci_addr_hi;
} __packed;

/* SAS (?) controller properties, part of mfi_ctrl_info */
struct mfi_ctrl_props {
	uint16_t	seq_num;
	uint16_t	pred_fail_poll_interval;
	uint16_t	intr_throttle_cnt;
	uint16_t	intr_throttle_timeout;
	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_cnt;
	uint8_t		spinup_delay;
	uint8_t		cluster_enable;
	uint8_t		coercion_mode;
	uint8_t		alarm_enable;
	uint8_t		disable_auto_rebuild;
	uint8_t		disable_battery_warn;
	uint8_t		ecc_bucket_size;
	uint16_t	ecc_bucket_leak_rate;
	uint8_t		restore_hotspare_on_insertion;
	uint8_t		expose_encl_devices;
	uint8_t		reserved[38];
} __packed;

/* PCI information about the card. */
struct mfi_info_pci {
	uint16_t	vendor;
	uint16_t	device;
	uint16_t	subvendor;
	uint16_t	subdevice;
	uint8_t		reserved[24];
} __packed;

/* Host (front end) interface information */
struct mfi_info_host {
	uint8_t		type;
#define MFI_INFO_HOST_PCIX	0x01
#define MFI_INFO_HOST_PCIE	0x02
#define MFI_INFO_HOST_ISCSI	0x04
#define MFI_INFO_HOST_SAS3G	0x08
	uint8_t		reserved[6];
	uint8_t		port_count;
	uint64_t	port_addr[8];
} __packed;

/* Device (back end) interface information */
struct mfi_info_device {
	uint8_t		type;
#define MFI_INFO_DEV_SPI	0x01
#define MFI_INFO_DEV_SAS3G	0x02
#define MFI_INFO_DEV_SATA1	0x04
#define MFI_INFO_DEV_SATA3G	0x08
	uint8_t		reserved[6];
	uint8_t		port_count;
	uint64_t	port_addr[8];
} __packed;

/* Firmware component information */
struct mfi_info_component {
	char		 name[8];
	char		 version[32];
	char		 build_date[16];
	char		 build_time[16];
} __packed;

/* Controller default settings */
struct mfi_defaults {
	uint64_t	sas_addr;
	uint8_t		phy_polarity;
	uint8_t		background_rate;
	uint8_t		stripe_size;
	uint8_t		flush_time;
	uint8_t		write_back;
	uint8_t		read_ahead;
	uint8_t		cache_when_bbu_bad;
	uint8_t		cached_io;
	uint8_t		smart_mode;
	uint8_t		alarm_disable;
	uint8_t		coercion;
	uint8_t		zrc_config;
	uint8_t		dirty_led_shows_drive_activity;
	uint8_t		bios_continue_on_error;
	uint8_t		spindown_mode;
	uint8_t		allowed_device_types;
	uint8_t		allow_mix_in_enclosure;
	uint8_t		allow_mix_in_ld;
	uint8_t		allow_sata_in_cluster;
	uint8_t		max_chained_enclosures;
	uint8_t		disable_ctrl_r;
	uint8_t		enabel_web_bios;
	uint8_t		phy_polarity_split;
	uint8_t		direct_pd_mapping;
	uint8_t		bios_enumerate_lds;
	uint8_t		restored_hot_spare_on_insertion;
	uint8_t		expose_enclosure_devices;
	uint8_t		maintain_pd_fail_history;
	uint8_t		resv[28];
} __packed;

/* Controller default settings */
struct mfi_bios_data {
	uint16_t	boot_target_id;
	uint8_t		do_not_int_13;
	uint8_t		continue_on_error;
	uint8_t		verbose;
	uint8_t		geometry;
	uint8_t		expose_all_drives;
	uint8_t		reserved[56];
	uint8_t		check_sum;
} __packed;

/* SAS (?) controller info, returned from MFI_DCMD_CTRL_GETINFO. */
struct mfi_ctrl_info {
	struct mfi_info_pci	pci;
	struct mfi_info_host	host;
	struct mfi_info_device	device;

	/* Firmware components that are present and active. */
	uint32_t		image_check_word;
	uint32_t		image_component_count;
	struct mfi_info_component image_component[8];

	/* Firmware components that have been flashed but are inactive */
	uint32_t		pending_image_component_count;
	struct mfi_info_component 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_number[32];
	uint32_t		hw_present;
#define MFI_INFO_HW_BBU		0x01
#define MFI_INFO_HW_ALARM	0x02
#define MFI_INFO_HW_NVRAM	0x04
#define MFI_INFO_HW_UART	0x08
	uint32_t		current_fw_time;
	uint16_t		max_cmds;
	uint16_t		max_sg_elements;
	uint32_t		max_request_size;
	uint16_t		lds_present;
	uint16_t		lds_degraded;
	uint16_t		lds_offline;
	uint16_t		pd_present;
	uint16_t		pd_disks_present;
	uint16_t		pd_disks_pred_failure;
	uint16_t		pd_disks_failed;
	uint16_t		nvram_size;
	uint16_t		memory_size;
	uint16_t		flash_size;
	uint16_t		ram_correctable_errors;
	uint16_t		ram_uncorrectable_errors;
	uint8_t			cluster_allowed;
	uint8_t			cluster_active;
	uint16_t		max_strips_per_io;

	uint32_t		raid_levels;
#define MFI_INFO_RAID_0		0x01
#define MFI_INFO_RAID_1		0x02
#define MFI_INFO_RAID_5		0x04
#define MFI_INFO_RAID_1E	0x08
#define MFI_INFO_RAID_6		0x10

	uint32_t		adapter_ops;
#define MFI_INFO_AOPS_RBLD_RATE		0x0001
#define MFI_INFO_AOPS_CC_RATE		0x0002
#define MFI_INFO_AOPS_BGI_RATE		0x0004
#define MFI_INFO_AOPS_RECON_RATE	0x0008
#define MFI_INFO_AOPS_PATROL_RATE	0x0010
#define MFI_INFO_AOPS_ALARM_CONTROL	0x0020
#define MFI_INFO_AOPS_CLUSTER_SUPPORTED	0x0040
#define MFI_INFO_AOPS_BBU		0x0080
#define MFI_INFO_AOPS_SPANNING_ALLOWED	0x0100
#define MFI_INFO_AOPS_DEDICATED_SPARES	0x0200
#define MFI_INFO_AOPS_REVERTIBLE_SPARES	0x0400
#define MFI_INFO_AOPS_FOREIGN_IMPORT	0x0800
#define MFI_INFO_AOPS_SELF_DIAGNOSTIC	0x1000
#define MFI_INFO_AOPS_MIXED_ARRAY	0x2000
#define MFI_INFO_AOPS_GLOBAL_SPARES	0x4000

	uint32_t		ld_ops;
#define MFI_INFO_LDOPS_READ_POLICY	0x01
#define MFI_INFO_LDOPS_WRITE_POLICY	0x02
#define MFI_INFO_LDOPS_IO_POLICY	0x04
#define MFI_INFO_LDOPS_ACCESS_POLICY	0x08
#define MFI_INFO_LDOPS_DISK_CACHE_POLICY 0x10

	struct {
		uint8_t		min;
		uint8_t		max;
		uint8_t		reserved[2];
	} __packed stripe_sz_ops;

	uint32_t		pd_ops;
#define MFI_INFO_PDOPS_FORCE_ONLINE	0x01
#define MFI_INFO_PDOPS_FORCE_OFFLINE	0x02
#define MFI_INFO_PDOPS_FORCE_REBUILD	0x04

	uint32_t		pd_mix_support;
#define MFI_INFO_PDMIX_SAS		0x01
#define MFI_INFO_PDMIX_SATA		0x02
#define MFI_INFO_PDMIX_ENCL		0x04
#define MFI_INFO_PDMIX_LD		0x08
#define MFI_INFO_PDMIX_SATA_CLUSTER	0x10

	uint8_t			ecc_bucket_count;
	uint8_t			reserved2[11];
	struct mfi_ctrl_props	properties;
	char			package_version[0x60];
	uint8_t			pad[0x800 - 0x6a0];
} __packed;

/* keep track of an event. */
union mfi_evt {
	struct {
		uint16_t	locale;
		uint8_t		reserved;
		int8_t		evt_class;
	} members;
	uint32_t		word;
} __packed;

/* event log state. */
struct mfi_evt_log_state {
	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;
} __packed;

struct mfi_progress {
	uint16_t		progress;
	uint16_t		elapsed_seconds;
} __packed;

struct mfi_evt_ld {
	uint16_t		target_id;
	uint8_t			ld_index;
	uint8_t			reserved;
} __packed;

struct mfi_evt_pd {
	uint16_t		device_id;
	uint8_t			enclosure_index;
	uint8_t			slot_number;
} __packed;

/* SAS (?) event detail, returned from MFI_DCMD_CTRL_EVENT_WAIT. */
struct mfi_evt_detail {
	uint32_t		seq;
	uint32_t		time;
	uint32_t		code;
	union mfi_evt		evt_class;
	uint8_t			arg_type;
	uint8_t			reserved1[15];

	union {
		struct {
			struct mfi_evt_pd	pd;
			uint8_t			cdb_len;
			uint8_t			sense_len;
			uint8_t			reserved[2];
			uint8_t			cdb[16];
			uint8_t			sense[64];
		} cdb_sense;

		struct mfi_evt_ld		ld;

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

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

		struct {
			struct mfi_evt_ld	ld;
			uint32_t		pre_owner;
			uint32_t		new_owner;
		} ld_owner;

		struct {
			uint64_t		ld_lba;
			uint64_t		pd_lba;
			struct mfi_evt_ld	ld;
			struct mfi_evt_pd	pd;
		} ld_lba_pd_lba;

		struct {
			struct mfi_evt_ld	ld;
			struct mfi_progress	prog;
		} ld_prog;

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

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

		struct mfi_evt_pd		pd;

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

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

		struct {
			uint64_t		lba;
			struct mfi_evt_pd	pd;
			struct mfi_evt_ld	ld;
		} pd_lba_ld;

		struct {
			struct mfi_evt_pd	pd;
			struct mfi_progress	prog;
		} pd_prog;

		struct {
			struct mfi_evt_pd	ld;
			uint32_t		prev_state;
			uint32_t		new_state;
		} pd_state;

		struct {
			uint16_t		venderId;
			uint16_t		deviceId;
			uint16_t		subVenderId;
			uint16_t		subDeviceId;
		} pci;

		uint32_t			rate;

		char				str[96];

		struct {
			uint32_t		rtc;
			uint16_t		elapsedSeconds;
		} time;

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

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

	char description[128];
} __packed;

struct mfi_evt_list {
	uint32_t		count;
	uint32_t		reserved;
	struct mfi_evt_detail	event[1];
} __packed;

union mfi_pd_ref {
	struct {
		uint16_t	device_id;
		uint16_t	seq_num;
	} v;
	uint32_t	ref;
} __packed;

union mfi_pd_ddf_type {
	struct {
		union {
			struct {
				uint16_t	forced_pd_guid	: 1;
				uint16_t	in_vd		: 1;
				uint16_t	is_global_spare	: 1;
				uint16_t	is_spare	: 1;
				uint16_t	is_foreign	: 1;
				uint16_t	reserved	: 7;
				uint16_t	intf		: 4;
			} pd_type;
			uint16_t	type;
		} v;
		uint16_t		reserved;
	} ddf;
	struct {
		uint32_t		reserved;
	} non_disk;
	uint32_t			type;
} __packed;

struct mfi_pd_progress {
	uint32_t			active;
#define	MFI_PD_PROGRESS_REBUILD	(1<<0)
#define	MFI_PD_PROGRESS_PATROL	(1<<1)
#define	MFI_PD_PROGRESS_CLEAR	(1<<2)
	struct mfi_progress		rbld;
	struct mfi_progress		patrol;
	struct mfi_progress		clear;
	struct mfi_progress		reserved[4];
} __packed;

struct mfi_pd_info {
	union mfi_pd_ref		ref;
	uint8_t				inquiry_data[96];
	uint8_t				vpd_page83[64];
	uint8_t				not_supported;
	uint8_t				scsi_dev_type;
	uint8_t				connected_port_bitmap;
	uint8_t				device_speed;
	uint32_t			media_err_count;
	uint32_t			other_err_count;
	uint32_t			pred_fail_count;
	uint32_t			last_pred_fail_event_seq_num;
	uint16_t			fw_state;	/* MFI_PD_STATE_* */
	uint8_t				disabled_for_removal;
	uint8_t				link_speed;
	union mfi_pd_ddf_type		state;
	struct {
		uint8_t			count;
		uint8_t			is_path_broken;
		uint8_t			reserved[6];
		uint64_t		sas_addr[4];
	} path_info;
	uint64_t			raw_size;
	uint64_t			non_coerced_size;
	uint64_t			coerced_size;
	uint16_t			encl_device_id;
	uint8_t				encl_index;
	uint8_t				slot_number;
	struct mfi_pd_progress		prog_info;
	uint8_t				bad_block_table_full;
	uint8_t				unusable_in_current_config;
	uint8_t				vpd_page83_ext[64];
	uint8_t				reserved[512-358];
} __packed;

struct mfi_pd_address {
	uint16_t		device_id;
	uint16_t		encl_device_id;
	uint8_t			encl_index;
	uint8_t			slot_number;
	uint8_t			scsi_dev_type;	/* 0 = disk */
	uint8_t			connect_port_bitmap;
	uint64_t		sas_addr[2];
} __packed;

struct mfi_pd_list {
	uint32_t		size;
	uint32_t		count;
	struct mfi_pd_address	addr[0];
} __packed;

enum mfi_pd_state {
	MFI_PD_STATE_UNCONFIGURED_GOOD = 0x00,
	MFI_PD_STATE_UNCONFIGURED_BAD = 0x01,
	MFI_PD_STATE_HOT_SPARE = 0x02,
	MFI_PD_STATE_OFFLINE = 0x10,
	MFI_PD_STATE_FAILED = 0x11,
	MFI_PD_STATE_REBUILD = 0x14,
	MFI_PD_STATE_ONLINE = 0x18,
	MFI_PD_STATE_COPYBACK = 0x20,
	MFI_PD_STATE_SYSTEM = 0x40
};

union mfi_ld_ref {
	struct {
		uint8_t		target_id;
		uint8_t		reserved;
		uint16_t	seq;
	} v;
	uint32_t		ref;
} __packed;

struct mfi_ld_list {
	uint32_t		ld_count;
	uint32_t		reserved1;
	struct {
		union mfi_ld_ref	ld;
		uint8_t		state;
		uint8_t		reserved2[3];
		uint64_t	size;
	} ld_list[MFI_MAX_LD];
} __packed;

enum mfi_ld_access {
	MFI_LD_ACCESS_RW =	0,
	MFI_LD_ACCSSS_RO = 	2,
	MFI_LD_ACCESS_BLOCKED =	3,
};
#define MFI_LD_ACCESS_MASK	3

enum mfi_ld_state {
	MFI_LD_STATE_OFFLINE =			0,
	MFI_LD_STATE_PARTIALLY_DEGRADED =	1,
	MFI_LD_STATE_DEGRADED =			2,
	MFI_LD_STATE_OPTIMAL =			3
};

struct mfi_ld_props {
	union mfi_ld_ref	ld;
	char			name[16];
	uint8_t			default_cache_policy;
	uint8_t			access_policy;
	uint8_t			disk_cache_policy;
	uint8_t			current_cache_policy;
	uint8_t			no_bgi;
	uint8_t			reserved[7];
} __packed;

struct mfi_ld_params {
	uint8_t			primary_raid_level;
	uint8_t			raid_level_qualifier;
	uint8_t			secondary_raid_level;
	uint8_t			stripe_size;
	uint8_t			num_drives;
	uint8_t			span_depth;
	uint8_t			state;
	uint8_t			init_state;
#define	MFI_LD_PARAMS_INIT_NO		0
#define	MFI_LD_PARAMS_INIT_QUICK	1
#define	MFI_LD_PARAMS_INIT_FULL		2
	uint8_t			is_consistent;
	uint8_t			reserved[23];
} __packed;

struct mfi_ld_progress {
	uint32_t		active;
#define	MFI_LD_PROGRESS_CC	(1<<0)
#define	MFI_LD_PROGRESS_BGI	(1<<1)
#define	MFI_LD_PROGRESS_FGI	(1<<2)
#define	MFI_LD_PROGRESS_RECON	(1<<3)
	struct mfi_progress	cc;
	struct mfi_progress	bgi;
	struct mfi_progress	fgi;
	struct mfi_progress	recon;
	struct mfi_progress	reserved[4];
} __packed;

struct mfi_span {
	uint64_t		start_block;
	uint64_t		num_blocks;
	uint16_t		array_ref;
	uint8_t			reserved[6];
} __packed;

#define	MFI_MAX_SPAN_DEPTH	8
struct mfi_ld_config {
	struct mfi_ld_props	properties;
	struct mfi_ld_params	params;
	struct mfi_span		span[MFI_MAX_SPAN_DEPTH];
} __packed;

struct mfi_ld_info {
	struct mfi_ld_config	ld_config;
	uint64_t		size;
	struct mfi_ld_progress	progress;
	uint16_t		cluster_owner;
	uint8_t			reconstruct_active;
	uint8_t			reserved1[1];
	uint8_t			vpd_page83[64];
	uint8_t			reserved2[16];
} __packed;

#define MAX_ARRAYS 16
struct mfi_spare {
	union mfi_pd_ref	ref;
	uint8_t			spare_type;
#define	MFI_SPARE_DEDICATED	(1 << 0)
#define	MFI_SPARE_REVERTIBLE	(1 << 1)
#define	MFI_SPARE_ENCL_AFFINITY	(1 << 2)
	uint8_t			reserved[2];
	uint8_t			array_count;
	uint16_t		array_ref[MAX_ARRAYS];
} __packed;

struct mfi_array {
	uint64_t			size;
	uint8_t				num_drives;
	uint8_t				reserved;
	uint16_t			array_ref;
	uint8_t				pad[20];
	struct {
		union mfi_pd_ref	ref;	/* 0xffff == missing drive */
		uint16_t		fw_state;	/* MFI_PD_STATE_* */
		struct {
			uint8_t		pd;
			uint8_t		slot;
		} encl;
	} pd[0];
} __packed;

struct mfi_config_data {
	uint32_t		size;
	uint16_t		array_count;
	uint16_t		array_size;
	uint16_t		log_drv_count;
	uint16_t		log_drv_size;
	uint16_t		spares_count;
	uint16_t		spares_size;
	uint8_t			reserved[16];
	struct mfi_array	array[0];
	struct mfi_ld_config	ld[0];
	struct mfi_spare	spare[0];
} __packed;

struct mfi_bbu_capacity_info {
	uint16_t		relative_charge;
	uint16_t		absolute_charge;
	uint16_t		remaining_capacity;
	uint16_t		full_charge_capacity;
	uint16_t		run_time_to_empty;
	uint16_t		average_time_to_empty;
	uint16_t		average_time_to_full;
	uint16_t		cycle_count;
	uint16_t		max_error;
	uint16_t		remaining_capacity_alarm;
	uint16_t		remaining_time_alarm;
	uint8_t			reserved[26];
} __packed;

struct mfi_bbu_design_info {
	uint32_t		mfg_date;
	uint16_t		design_capacity;
	uint16_t		design_voltage;
	uint16_t		spec_info;
	uint16_t		serial_number;
	uint16_t		pack_stat_config;
	uint8_t			mfg_name[12];
	uint8_t			device_name[8];
	uint8_t			device_chemistry[8];
	uint8_t			mfg_data[8];
	uint8_t			reserved[17];
} __packed;

struct mfi_ibbu_state {
	uint16_t		gas_guage_status;
	uint16_t		relative_charge;
	uint16_t		charger_system_state;
	uint16_t		charger_system_ctrl;
	uint16_t		charging_current;
	uint16_t		absolute_charge;
	uint16_t		max_error;
	uint8_t			reserved[18];
} __packed;

struct mfi_bbu_state {
	uint16_t		gas_guage_status;
	uint16_t		relative_charge;
	uint16_t		charger_status;
	uint16_t		remaining_capacity;
	uint16_t		full_charge_capacity;
	uint8_t			is_SOH_good;
	uint8_t			reserved[21];
} __packed;

union mfi_bbu_status_detail {
	struct mfi_ibbu_state	ibbu;
	struct mfi_bbu_state	bbu;
};

struct mfi_bbu_status {
	uint8_t			battery_type;
#define	MFI_BBU_TYPE_NONE	0
#define	MFI_BBU_TYPE_IBBU	1
#define	MFI_BBU_TYPE_BBU	2
	uint8_t			reserved;
	uint16_t		voltage;
	int16_t			current;
	uint16_t		temperature;
	uint32_t		fw_status;
#define	MFI_BBU_STATE_PACK_MISSING	(1 << 0)
#define	MFI_BBU_STATE_VOLTAGE_LOW	(1 << 1)
#define	MFI_BBU_STATE_TEMPERATURE_HIGH	(1 << 2)
#define	MFI_BBU_STATE_CHARGE_ACTIVE	(1 << 0)
#define	MFI_BBU_STATE_DISCHARGE_ACTIVE	(1 << 0)
	uint8_t			pad[20];
	union mfi_bbu_status_detail detail;
} __packed;

enum mfi_pr_state {
	MFI_PR_STATE_STOPPED = 0,
	MFI_PR_STATE_READY = 1,
	MFI_PR_STATE_ACTIVE = 2,
	MFI_PR_STATE_ABORTED = 0xff
};

struct mfi_pr_status {
	uint32_t		num_iteration;
	uint8_t			state;
	uint8_t			num_pd_done;
	uint8_t			reserved[10];
};

enum mfi_pr_opmode {
	MFI_PR_OPMODE_AUTO = 0,
	MFI_PR_OPMODE_MANUAL = 1,
	MFI_PR_OPMODE_DISABLED = 2
};

struct mfi_pr_properties {
	uint8_t			op_mode;
	uint8_t			max_pd;
	uint8_t			reserved;
	uint8_t			exclude_ld_count;
	uint16_t		excluded_ld[MFI_MAX_LD];
	uint8_t			cur_pd_map[MFI_MAX_PD / 8];
	uint8_t			last_pd_map[MFI_MAX_PD / 8];
	uint32_t		next_exec;
	uint32_t		exec_freq;
	uint32_t		clear_freq;
};

#define MFI_SCSI_MAX_TARGETS	128
#define MFI_SCSI_MAX_LUNS	8
#define MFI_SCSI_INITIATOR_ID	255
#define MFI_SCSI_MAX_CMDS	8
#define MFI_SCSI_MAX_CDB_LEN	16

#endif /* _MFIREG_H */


code:
/*-
 * Copyright (c) 2006 IronPort Systems
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */
/*-
 * Copyright (c) 2007 LSI Corp.
 * Copyright (c) 2007 Rajesh Prabhakaran.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef _MFIVAR_H
#define _MFIVAR_H

#include <sys/cdefs.h>
__FBSDID("$FreeBSD: release/9.0.0/sys/dev/mfi/mfivar.h 227117 2011-11-05 18:27:47Z kib $");

#include <sys/lock.h>
#include <sys/sx.h>

/*
 * SCSI structures and definitions are used from here, but no linking
 * requirements are made to CAM.
 */
#include <cam/scsi/scsi_all.h>

struct mfi_hwcomms {
	uint32_t		hw_pi;
	uint32_t		hw_ci;
	uint32_t		hw_reply_q[1];
};

struct mfi_softc;
struct disk;
struct ccb_hdr;

struct mfi_command {
	TAILQ_ENTRY(mfi_command) cm_link;
	time_t			cm_timestamp;
	struct mfi_softc	*cm_sc;
	union mfi_frame		*cm_frame;
	uint32_t		cm_frame_busaddr;
	struct mfi_sense	*cm_sense;
	uint32_t		cm_sense_busaddr;
	bus_dmamap_t		cm_dmamap;
	union mfi_sgl		*cm_sg;
	void			*cm_data;
	int			cm_len;
	int			cm_stp_len;
	int			cm_total_frame_size;
	int			cm_extra_frames;
	int			cm_flags;
#define MFI_CMD_MAPPED		(1<<0)
#define MFI_CMD_DATAIN		(1<<1)
#define MFI_CMD_DATAOUT		(1<<2)
#define MFI_CMD_COMPLETED	(1<<3)
#define MFI_CMD_POLLED		(1<<4)
#define MFI_ON_MFIQ_FREE	(1<<5)
#define MFI_ON_MFIQ_READY	(1<<6)
#define MFI_ON_MFIQ_BUSY	(1<<7)
#define MFI_ON_MFIQ_MASK	((1<<5)|(1<<6)|(1<<7))
	int			cm_aen_abort;
	void			(* cm_complete)(struct mfi_command *cm);
	void			*cm_private;
	int			cm_index;
	int			cm_error;
};

struct mfi_disk {
	TAILQ_ENTRY(mfi_disk)	ld_link;
	device_t	ld_dev;
	int		ld_id;
	int		ld_unit;
	struct mfi_softc *ld_controller;
	struct mfi_ld_info	*ld_info;
	struct disk	*ld_disk;
	int		ld_flags;
#define MFI_DISK_FLAGS_OPEN	0x01
#define	MFI_DISK_FLAGS_DISABLED	0x02
};

struct mfi_aen {
	TAILQ_ENTRY(mfi_aen) aen_link;
	struct proc			*p;
};

struct mfi_softc {
	device_t			mfi_dev;
	int				mfi_flags;
#define MFI_FLAGS_SG64		(1<<0)
#define MFI_FLAGS_QFRZN		(1<<1)
#define MFI_FLAGS_OPEN		(1<<2)
#define MFI_FLAGS_STOP		(1<<3)
#define MFI_FLAGS_1064R		(1<<4)
#define MFI_FLAGS_1078		(1<<5)
#define MFI_FLAGS_GEN2		(1<<6)

	struct mfi_hwcomms		*mfi_comms;
	TAILQ_HEAD(,mfi_command)	mfi_free;
	TAILQ_HEAD(,mfi_command)	mfi_ready;
	TAILQ_HEAD(,mfi_command)	mfi_busy;
	struct bio_queue_head		mfi_bioq;
	struct mfi_qstat		mfi_qstat[MFIQ_COUNT];

	struct resource			*mfi_regs_resource;
	bus_space_handle_t		mfi_bhandle;
	bus_space_tag_t			mfi_btag;
	int				mfi_regs_rid;

	bus_dma_tag_t			mfi_parent_dmat;
	bus_dma_tag_t			mfi_buffer_dmat;

	bus_dma_tag_t			mfi_comms_dmat;
	bus_dmamap_t			mfi_comms_dmamap;
	uint32_t			mfi_comms_busaddr;

	bus_dma_tag_t			mfi_frames_dmat;
	bus_dmamap_t			mfi_frames_dmamap;
	uint32_t			mfi_frames_busaddr;
	union mfi_frame			*mfi_frames;

	TAILQ_HEAD(,mfi_aen)		mfi_aen_pids;
	struct mfi_command		*mfi_aen_cm;
	uint32_t			mfi_aen_triggered;
	uint32_t			mfi_poll_waiting;
	struct selinfo			mfi_select;
	int				mfi_delete_busy_volumes;
	int				mfi_keep_deleted_volumes;
	int				mfi_detaching;

	bus_dma_tag_t			mfi_sense_dmat;
	bus_dmamap_t			mfi_sense_dmamap;
	uint32_t			mfi_sense_busaddr;
	struct mfi_sense		*mfi_sense;

	struct resource			*mfi_irq;
	void				*mfi_intr;
	int				mfi_irq_rid;

	struct intr_config_hook		mfi_ich;
	eventhandler_tag		eh;

	/*
	 * Allocation for the command array.  Used as an indexable array to
	 * recover completed commands.
	 */
	struct mfi_command		*mfi_commands;
	/*
	 * How many commands were actually allocated
	 */
	int				mfi_total_cmds;
	/*
	 * How many commands the firmware can handle.  Also how big the reply
	 * queue is, minus 1.
	 */
	int				mfi_max_fw_cmds;
	/*
	 * How many S/G elements we'll ever actually use
	 */
	int				mfi_max_sge;
	/*
	 * How many bytes a compound frame is, including all of the extra frames
	 * that are used for S/G elements.
	 */
	int				mfi_cmd_size;
	/*
	 * How large an S/G element is.  Used to calculate the number of single
	 * frames in a command.
	 */
	int				mfi_sge_size;
	/*
	 * Max number of sectors that the firmware allows
	 */
	uint32_t			mfi_max_io;

	TAILQ_HEAD(,mfi_disk)		mfi_ld_tqh;
	eventhandler_tag		mfi_eh;
	struct cdev			*mfi_cdev;

	TAILQ_HEAD(, ccb_hdr)		mfi_cam_ccbq;
	struct mfi_command *		(* mfi_cam_start)(void *);
	struct callout			mfi_watchdog_callout;
	struct mtx			mfi_io_lock;
	struct sx			mfi_config_lock;

	/* Controller type specific interfaces */
	void	(*mfi_enable_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);
};

extern int mfi_attach(struct mfi_softc *);
extern void mfi_free(struct mfi_softc *);
extern int mfi_shutdown(struct mfi_softc *);
extern void mfi_startio(struct mfi_softc *);
extern void mfi_disk_complete(struct bio *);
extern int mfi_disk_disable(struct mfi_disk *);
extern void mfi_disk_enable(struct mfi_disk *);
extern int mfi_dump_blocks(struct mfi_softc *, int id, uint64_t, void *, int);

#define MFIQ_ADD(sc, qname)					\
	do {							\
		struct mfi_qstat *qs;				\
								\
		qs = &(sc)->mfi_qstat[qname];			\
		qs->q_length++;					\
		if (qs->q_length > qs->q_max)			\
			qs->q_max = qs->q_length;		\
	} while (0)

#define MFIQ_REMOVE(sc, qname)	(sc)->mfi_qstat[qname].q_length--

#define MFIQ_INIT(sc, qname)					\
	do {							\
		sc->mfi_qstat[qname].q_length = 0;		\
		sc->mfi_qstat[qname].q_max = 0;			\
	} while (0)

#define MFIQ_COMMAND_QUEUE(name, index)					\
	static __inline void						\
	mfi_initq_ ## name (struct mfi_softc *sc)			\
	{								\
		TAILQ_INIT(&sc->mfi_ ## name);				\
		MFIQ_INIT(sc, index);					\
	}								\
	static __inline void						\
	mfi_enqueue_ ## name (struct mfi_command *cm)			\
	{								\
		if ((cm->cm_flags & MFI_ON_MFIQ_MASK) != 0) {		\
			printf("command %p is on another queue, "	\
			    "flags = %#x\n", cm, cm->cm_flags);		\
			panic("command is on another queue");		\
		}							\
		TAILQ_INSERT_TAIL(&cm->cm_sc->mfi_ ## name, cm, cm_link); \
		cm->cm_flags |= MFI_ON_ ## index;			\
		MFIQ_ADD(cm->cm_sc, index);				\
	}								\
	static __inline void						\
	mfi_requeue_ ## name (struct mfi_command *cm)			\
	{								\
		if ((cm->cm_flags & MFI_ON_MFIQ_MASK) != 0) {		\
			printf("command %p is on another queue, "	\
			    "flags = %#x\n", cm, cm->cm_flags);		\
			panic("command is on another queue");		\
		}							\
		TAILQ_INSERT_HEAD(&cm->cm_sc->mfi_ ## name, cm, cm_link); \
		cm->cm_flags |= MFI_ON_ ## index;			\
		MFIQ_ADD(cm->cm_sc, index);				\
	}								\
	static __inline struct mfi_command *				\
	mfi_dequeue_ ## name (struct mfi_softc *sc)			\
	{								\
		struct mfi_command *cm;					\
									\
		if ((cm = TAILQ_FIRST(&sc->mfi_ ## name)) != NULL) {	\
			if ((cm->cm_flags & MFI_ON_ ## index) == 0) {	\
				printf("command %p not in queue, "	\
				    "flags = %#x, bit = %#x\n", cm,	\
				    cm->cm_flags, MFI_ON_ ## index);	\
				panic("command not in queue");		\
			}						\
			TAILQ_REMOVE(&sc->mfi_ ## name, cm, cm_link);	\
			cm->cm_flags &= ~MFI_ON_ ## index;		\
			MFIQ_REMOVE(sc, index);				\
		}							\
		return (cm);						\
	}								\
	static __inline void						\
	mfi_remove_ ## name (struct mfi_command *cm)			\
	{								\
		if ((cm->cm_flags & MFI_ON_ ## index) == 0) {		\
			printf("command %p not in queue, flags = %#x, " \
			    "bit = %#x\n", cm, cm->cm_flags,		\
			    MFI_ON_ ## index);				\
			panic("command not in queue");			\
		}							\
		TAILQ_REMOVE(&cm->cm_sc->mfi_ ## name, cm, cm_link);	\
		cm->cm_flags &= ~MFI_ON_ ## index;			\
		MFIQ_REMOVE(cm->cm_sc, index);				\
	}								\
struct hack

MFIQ_COMMAND_QUEUE(free, MFIQ_FREE);
MFIQ_COMMAND_QUEUE(ready, MFIQ_READY);
MFIQ_COMMAND_QUEUE(busy, MFIQ_BUSY);

static __inline void
mfi_initq_bio(struct mfi_softc *sc)
{
	bioq_init(&sc->mfi_bioq);
	MFIQ_INIT(sc, MFIQ_BIO);
}

static __inline void
mfi_enqueue_bio(struct mfi_softc *sc, struct bio *bp)
{
	bioq_insert_tail(&sc->mfi_bioq, bp);
	MFIQ_ADD(sc, MFIQ_BIO);
}

static __inline struct bio *
mfi_dequeue_bio(struct mfi_softc *sc)
{
	struct bio *bp;

	if ((bp = bioq_first(&sc->mfi_bioq)) != NULL) {
		bioq_remove(&sc->mfi_bioq, bp);
		MFIQ_REMOVE(sc, MFIQ_BIO);
	}
	return (bp);
}

/*
 * This is from the original scsi_extract_sense() in CAM.  It's copied
 * here because CAM now uses a non-inline version that follows more complex
 * additions to the SPC spec, and we don't want to force a dependency on
 * the CAM module for such a trivial action.
 */
static __inline void
mfi_extract_sense(struct scsi_sense_data_fixed *sense,
    int *error_code, int *sense_key, int *asc, int *ascq)
{

	*error_code = sense->error_code & SSD_ERRCODE;
	*sense_key = sense->flags & SSD_KEY;
	*asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0;
	*ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0;
}

static __inline void
mfi_print_sense(struct mfi_softc *sc, void *sense)
{
	int error, key, asc, ascq;

	mfi_extract_sense((struct scsi_sense_data_fixed *)sense,
	    &error, &key, &asc, &ascq);
	device_printf(sc->mfi_dev, "sense error %d, sense_key %d, "
	    "asc %d, ascq %d\n", error, key, asc, ascq);
}

#define MFI_WRITE4(sc, reg, val)	bus_space_write_4((sc)->mfi_btag, \
	sc->mfi_bhandle, (reg), (val))
#define MFI_READ4(sc, reg)		bus_space_read_4((sc)->mfi_btag, \
	(sc)->mfi_bhandle, (reg))
#define MFI_WRITE2(sc, reg, val)	bus_space_write_2((sc)->mfi_btag, \
	sc->mfi_bhandle, (reg), (val))
#define MFI_READ2(sc, reg)		bus_space_read_2((sc)->mfi_btag, \
	(sc)->mfi_bhandle, (reg))
#define MFI_WRITE1(sc, reg, val)	bus_space_write_1((sc)->mfi_btag, \
	sc->mfi_bhandle, (reg), (val))
#define MFI_READ1(sc, reg)		bus_space_read_1((sc)->mfi_btag, \
	(sc)->mfi_bhandle, (reg))

MALLOC_DECLARE(M_MFIBUF);

#define MFI_CMD_TIMEOUT 30
#define MFI_MAXPHYS (128 * 1024)

#ifdef MFI_DEBUG
extern void mfi_print_cmd(struct mfi_command *cm);
extern void mfi_dump_cmds(struct mfi_softc *sc);
extern void mfi_validate_sg(struct mfi_softc *, struct mfi_command *, const char *, int );
#define MFI_PRINT_CMD(cm)	mfi_print_cmd(cm)
#define MFI_DUMP_CMDS(sc)	mfi_dump_cmds(sc)
#define MFI_VALIDATE_CMD(sc, cm) mfi_validate_sg(sc, cm, __FUNCTION__, __LINE__)
#else
#define MFI_PRINT_CMD(cm)
#define MFI_DUMP_CMDS(sc)
#define MFI_VALIDATE_CMD(sc, cm)
#endif

extern void mfi_release_command(struct mfi_command *cm);

#endif /* _MFIVAR_H */

repo_name: veiledmerc/mira

license: mit


code:
/* $FreeBSD: release/9.0.0/sys/dev/mpt/mpilib/mpi.h 170251 2007-06-03 22:58:27Z scottl $ */
/*-
 * Copyright (c) 2000-2005, LSI Logic Corporation and its contributors.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
 *    substantially similar to the "NO WARRANTY" disclaimer below
 *    ("Disclaimer") and any redistribution must be conditioned upon including
 *    a substantially similar Disclaimer requirement for further binary
 *    redistribution.
 * 3. Neither the name of the LSI Logic Corporation 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 THE COPYRIGHT
 * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *           Name:  mpi.h
 *          Title:  MPI Message independent structures and definitions
 *  Creation Date:  July 27, 2000
 *
 *    mpi.h Version:  01.05.13
 *
 *  Version History
 *  ---------------
 *
 *  Date      Version   Description
 *  --------  --------  ------------------------------------------------------
 *  05-08-00  00.10.01  Original release for 0.10 spec dated 4/26/2000.
 *  05-24-00  00.10.02  Added MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH definition.
 *  06-06-00  01.00.01  Update MPI_VERSION_MAJOR and MPI_VERSION_MINOR.
 *  06-22-00  01.00.02  Added MPI_IOCSTATUS_LAN_ definitions.
 *                      Removed LAN_SUSPEND function definition.
 *                      Added MPI_MSGFLAGS_CONTINUATION_REPLY definition.
 *  06-30-00  01.00.03  Added MPI_CONTEXT_REPLY_TYPE_LAN definition.
 *                      Added MPI_GET/SET_CONTEXT_REPLY_TYPE macros.
 *  07-27-00  01.00.04  Added MPI_FAULT_ definitions.
 *                      Removed MPI_IOCSTATUS_MSG/DATA_XFER_ERROR definitions.
 *                      Added MPI_IOCSTATUS_INTERNAL_ERROR definition.
 *                      Added MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH.
 *  11-02-00  01.01.01  Original release for post 1.0 work.
 *  12-04-00  01.01.02  Added new function codes.
 *  01-09-01  01.01.03  Added more definitions to the system interface section
 *                      Added MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT.
 *  01-25-01  01.01.04  Changed MPI_VERSION_MINOR from 0x00 to 0x01.
 *  02-20-01  01.01.05  Started using MPI_POINTER.
 *                      Fixed value for MPI_DIAG_RW_ENABLE.
 *                      Added defines for MPI_DIAG_PREVENT_IOC_BOOT and
 *                      MPI_DIAG_CLEAR_FLASH_BAD_SIG.
 *                      Obsoleted MPI_IOCSTATUS_TARGET_FC_ defines.
 *  02-27-01  01.01.06  Removed MPI_HOST_INDEX_REGISTER define.
 *                      Added function codes for RAID.
 *  04-09-01  01.01.07  Added alternate define for MPI_DOORBELL_ACTIVE,
 *                      MPI_DOORBELL_USED, to better match the spec.
 *  08-08-01  01.02.01  Original release for v1.2 work.
 *                      Changed MPI_VERSION_MINOR from 0x01 to 0x02.
 *                      Added define MPI_FUNCTION_TOOLBOX.
 *  09-28-01  01.02.02  New function code MPI_SCSI_ENCLOSURE_PROCESSOR.
 *  11-01-01  01.02.03  Changed name to MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR.
 *  03-14-02  01.02.04  Added MPI_HEADER_VERSION_ defines.
 *  05-31-02  01.02.05  Bumped MPI_HEADER_VERSION_UNIT.
 *  07-12-02  01.02.06  Added define for MPI_FUNCTION_MAILBOX.
 *  09-16-02  01.02.07  Bumped value for MPI_HEADER_VERSION_UNIT.
 *  11-15-02  01.02.08  Added define MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX and
 *                      obsoleted define MPI_IOCSTATUS_TARGET_INVALID_IOCINDEX.
 *  04-01-03  01.02.09  New IOCStatus code: MPI_IOCSTATUS_FC_EXCHANGE_CANCELED
 *  06-26-03  01.02.10  Bumped MPI_HEADER_VERSION_UNIT value.
 *  01-16-04  01.02.11  Added define for MPI_IOCLOGINFO_TYPE_SHIFT.
 *  04-29-04  01.02.12  Added function codes for MPI_FUNCTION_DIAG_BUFFER_POST
 *                      and MPI_FUNCTION_DIAG_RELEASE.
 *                      Added MPI_IOCSTATUS_DIAGNOSTIC_RELEASED define.
 *                      Bumped MPI_HEADER_VERSION_UNIT value.
 *  05-11-04  01.03.01  Bumped MPI_VERSION_MINOR for MPI v1.3.
 *                      Added codes for Inband.
 *  08-19-04  01.05.01  Added defines for Host Buffer Access Control doorbell.
 *                      Added define for offset of High Priority Request Queue.
 *                      Added new function codes and new IOCStatus codes.
 *                      Added a IOCLogInfo type of SAS.
 *  12-07-04  01.05.02  Bumped MPI_HEADER_VERSION_UNIT.
 *  12-09-04  01.05.03  Bumped MPI_HEADER_VERSION_UNIT.
 *  01-15-05  01.05.04  Bumped MPI_HEADER_VERSION_UNIT.
 *  02-09-05  01.05.05  Bumped MPI_HEADER_VERSION_UNIT.
 *  02-22-05  01.05.06  Bumped MPI_HEADER_VERSION_UNIT.
 *  03-11-05  01.05.07  Removed function codes for SCSI IO 32 and
 *                      TargetAssistExtended requests.
 *                      Removed EEDP IOCStatus codes.
 *  06-24-05  01.05.08  Added function codes for SCSI IO 32 and
 *                      TargetAssistExtended requests.
 *                      Added EEDP IOCStatus codes.
 *  08-03-05  01.05.09  Bumped MPI_HEADER_VERSION_UNIT.
 *  08-30-05  01.05.10  Added 2 new IOCStatus codes for Target.
 *  03-27-06  01.05.11  Bumped MPI_HEADER_VERSION_UNIT.
 *  10-11-06  01.05.12  Bumped MPI_HEADER_VERSION_UNIT.
 *  05-24-07  01.05.13  Bumped MPI_HEADER_VERSION_UNIT.
 *  --------------------------------------------------------------------------
 */

#ifndef MPI_H
#define MPI_H

/*****************************************************************************
*
*        M P I    V e r s i o n    D e f i n i t i o n s
*
*****************************************************************************/

#define MPI_VERSION_MAJOR                   (0x01)
#define MPI_VERSION_MINOR                   (0x05)
#define MPI_VERSION_MAJOR_MASK              (0xFF00)
#define MPI_VERSION_MAJOR_SHIFT             (8)
#define MPI_VERSION_MINOR_MASK              (0x00FF)
#define MPI_VERSION_MINOR_SHIFT             (0)
#define MPI_VERSION ((MPI_VERSION_MAJOR << MPI_VERSION_MAJOR_SHIFT) |   \
                                      MPI_VERSION_MINOR)

#define MPI_VERSION_01_00                   (0x0100)
#define MPI_VERSION_01_01                   (0x0101)
#define MPI_VERSION_01_02                   (0x0102)
#define MPI_VERSION_01_03                   (0x0103)
#define MPI_VERSION_01_05                   (0x0105)
/* Note: The major versions of 0xe0 through 0xff are reserved */

/* versioning for this MPI header set */
#define MPI_HEADER_VERSION_UNIT             (0x10)
#define MPI_HEADER_VERSION_DEV              (0x00)
#define MPI_HEADER_VERSION_UNIT_MASK        (0xFF00)
#define MPI_HEADER_VERSION_UNIT_SHIFT       (8)
#define MPI_HEADER_VERSION_DEV_MASK         (0x00FF)
#define MPI_HEADER_VERSION_DEV_SHIFT        (0)
#define MPI_HEADER_VERSION ((MPI_HEADER_VERSION_UNIT << 8) | MPI_HEADER_VERSION_DEV)

/*****************************************************************************
*
*        I O C    S t a t e    D e f i n i t i o n s
*
*****************************************************************************/

#define MPI_IOC_STATE_RESET                 (0x00000000)
#define MPI_IOC_STATE_READY                 (0x10000000)
#define MPI_IOC_STATE_OPERATIONAL           (0x20000000)
#define MPI_IOC_STATE_FAULT                 (0x40000000)

#define MPI_IOC_STATE_MASK                  (0xF0000000)
#define MPI_IOC_STATE_SHIFT                 (28)

/* Fault state codes (product independent range 0x8000-0xFFFF) */

#define MPI_FAULT_REQUEST_MESSAGE_PCI_PARITY_ERROR  (0x8111)
#define MPI_FAULT_REQUEST_MESSAGE_PCI_BUS_FAULT     (0x8112)
#define MPI_FAULT_REPLY_MESSAGE_PCI_PARITY_ERROR    (0x8113)
#define MPI_FAULT_REPLY_MESSAGE_PCI_BUS_FAULT       (0x8114)
#define MPI_FAULT_DATA_SEND_PCI_PARITY_ERROR        (0x8115)
#define MPI_FAULT_DATA_SEND_PCI_BUS_FAULT           (0x8116)
#define MPI_FAULT_DATA_RECEIVE_PCI_PARITY_ERROR     (0x8117)
#define MPI_FAULT_DATA_RECEIVE_PCI_BUS_FAULT        (0x8118)

/*****************************************************************************
*
*        P C I    S y s t e m    I n t e r f a c e    R e g i s t e r s
*
*****************************************************************************/

/*
 * Defines for working with the System Doorbell register.
 * Values for doorbell function codes are included in the section that defines
 * all the function codes (further on in this file).
 */
#define MPI_DOORBELL_OFFSET                 (0x00000000)
#define MPI_DOORBELL_ACTIVE                 (0x08000000) /* DoorbellUsed */
#define MPI_DOORBELL_USED                   (MPI_DOORBELL_ACTIVE)
#define MPI_DOORBELL_ACTIVE_SHIFT           (27)
#define MPI_DOORBELL_WHO_INIT_MASK          (0x07000000)
#define MPI_DOORBELL_WHO_INIT_SHIFT         (24)
#define MPI_DOORBELL_FUNCTION_MASK          (0xFF000000)
#define MPI_DOORBELL_FUNCTION_SHIFT         (24)
#define MPI_DOORBELL_ADD_DWORDS_MASK        (0x00FF0000)
#define MPI_DOORBELL_ADD_DWORDS_SHIFT       (16)
#define MPI_DOORBELL_DATA_MASK              (0x0000FFFF)
#define MPI_DOORBELL_FUNCTION_SPECIFIC_MASK (0x0000FFFF)

/* values for Host Buffer Access Control doorbell function */
#define MPI_DB_HPBAC_VALUE_MASK             (0x0000F000)
#define MPI_DB_HPBAC_ENABLE_ACCESS          (0x01)
#define MPI_DB_HPBAC_DISABLE_ACCESS         (0x02)
#define MPI_DB_HPBAC_FREE_BUFFER            (0x03)

#define MPI_WRITE_SEQUENCE_OFFSET           (0x00000004)
#define MPI_WRSEQ_KEY_VALUE_MASK            (0x0000000F)
#define MPI_WRSEQ_1ST_KEY_VALUE             (0x04)
#define MPI_WRSEQ_2ND_KEY_VALUE             (0x0B)
#define MPI_WRSEQ_3RD_KEY_VALUE             (0x02)
#define MPI_WRSEQ_4TH_KEY_VALUE             (0x07)
#define MPI_WRSEQ_5TH_KEY_VALUE             (0x0D)

#define MPI_DIAGNOSTIC_OFFSET               (0x00000008)
#define MPI_DIAG_CLEAR_FLASH_BAD_SIG        (0x00000400)
#define MPI_DIAG_PREVENT_IOC_BOOT           (0x00000200)
#define MPI_DIAG_DRWE                       (0x00000080)
#define MPI_DIAG_FLASH_BAD_SIG              (0x00000040)
#define MPI_DIAG_RESET_HISTORY              (0x00000020)
#define MPI_DIAG_RW_ENABLE                  (0x00000010)
#define MPI_DIAG_RESET_ADAPTER              (0x00000004)
#define MPI_DIAG_DISABLE_ARM                (0x00000002)
#define MPI_DIAG_MEM_ENABLE                 (0x00000001)

#define MPI_TEST_BASE_ADDRESS_OFFSET        (0x0000000C)

#define MPI_DIAG_RW_DATA_OFFSET             (0x00000010)

#define MPI_DIAG_RW_ADDRESS_OFFSET          (0x00000014)

#define MPI_HOST_INTERRUPT_STATUS_OFFSET    (0x00000030)
#define MPI_HIS_IOP_DOORBELL_STATUS         (0x80000000)
#define MPI_HIS_REPLY_MESSAGE_INTERRUPT     (0x00000008)
#define MPI_HIS_DOORBELL_INTERRUPT          (0x00000001)

#define MPI_HOST_INTERRUPT_MASK_OFFSET      (0x00000034)
#define MPI_HIM_RIM                         (0x00000008)
#define MPI_HIM_DIM                         (0x00000001)

#define MPI_REQUEST_QUEUE_OFFSET            (0x00000040)
#define MPI_REQUEST_POST_FIFO_OFFSET        (0x00000040)

#define MPI_REPLY_QUEUE_OFFSET              (0x00000044)
#define MPI_REPLY_POST_FIFO_OFFSET          (0x00000044)
#define MPI_REPLY_FREE_FIFO_OFFSET          (0x00000044)

#define MPI_HI_PRI_REQUEST_QUEUE_OFFSET     (0x00000048)

/*****************************************************************************
*
*        M e s s a g e    F r a m e    D e s c r i p t o r s
*
*****************************************************************************/

#define MPI_REQ_MF_DESCRIPTOR_NB_MASK       (0x00000003)
#define MPI_REQ_MF_DESCRIPTOR_F_BIT         (0x00000004)
#define MPI_REQ_MF_DESCRIPTOR_ADDRESS_MASK  (0xFFFFFFF8)

#define MPI_ADDRESS_REPLY_A_BIT             (0x80000000)
#define MPI_ADDRESS_REPLY_ADDRESS_MASK      (0x7FFFFFFF)

#define MPI_CONTEXT_REPLY_A_BIT             (0x80000000)
#define MPI_CONTEXT_REPLY_TYPE_MASK         (0x60000000)
#define MPI_CONTEXT_REPLY_TYPE_SCSI_INIT    (0x00)
#define MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET  (0x01)
#define MPI_CONTEXT_REPLY_TYPE_LAN          (0x02)
#define MPI_CONTEXT_REPLY_TYPE_SHIFT        (29)
#define MPI_CONTEXT_REPLY_CONTEXT_MASK      (0x1FFFFFFF)

/****************************************************************************/
/* Context Reply macros                                                     */
/****************************************************************************/

#define MPI_GET_CONTEXT_REPLY_TYPE(x)  (((x) & MPI_CONTEXT_REPLY_TYPE_MASK) \
                                          >> MPI_CONTEXT_REPLY_TYPE_SHIFT)

#define MPI_SET_CONTEXT_REPLY_TYPE(x, typ)                                  \
            ((x) = ((x) & ~MPI_CONTEXT_REPLY_TYPE_MASK) |                   \
                            (((typ) << MPI_CONTEXT_REPLY_TYPE_SHIFT) &      \
                                        MPI_CONTEXT_REPLY_TYPE_MASK))

/*****************************************************************************
*
*        M e s s a g e    F u n c t i o n s
*              0x80 -> 0x8F reserved for private message use per product
*
*
*****************************************************************************/

#define MPI_FUNCTION_SCSI_IO_REQUEST                (0x00)
#define MPI_FUNCTION_SCSI_TASK_MGMT                 (0x01)
#define MPI_FUNCTION_IOC_INIT                       (0x02)
#define MPI_FUNCTION_IOC_FACTS                      (0x03)
#define MPI_FUNCTION_CONFIG                         (0x04)
#define MPI_FUNCTION_PORT_FACTS                     (0x05)
#define MPI_FUNCTION_PORT_ENABLE                    (0x06)
#define MPI_FUNCTION_EVENT_NOTIFICATION             (0x07)
#define MPI_FUNCTION_EVENT_ACK                      (0x08)
#define MPI_FUNCTION_FW_DOWNLOAD                    (0x09)
#define MPI_FUNCTION_TARGET_CMD_BUFFER_POST         (0x0A)
#define MPI_FUNCTION_TARGET_ASSIST                  (0x0B)
#define MPI_FUNCTION_TARGET_STATUS_SEND             (0x0C)
#define MPI_FUNCTION_TARGET_MODE_ABORT              (0x0D)
#define MPI_FUNCTION_FC_LINK_SRVC_BUF_POST          (0x0E)
#define MPI_FUNCTION_FC_LINK_SRVC_RSP               (0x0F)
#define MPI_FUNCTION_FC_EX_LINK_SRVC_SEND           (0x10)
#define MPI_FUNCTION_FC_ABORT                       (0x11)
#define MPI_FUNCTION_FW_UPLOAD                      (0x12)
#define MPI_FUNCTION_FC_COMMON_TRANSPORT_SEND       (0x13)
#define MPI_FUNCTION_FC_PRIMITIVE_SEND              (0x14)

#define MPI_FUNCTION_RAID_ACTION                    (0x15)
#define MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH       (0x16)

#define MPI_FUNCTION_TOOLBOX                        (0x17)

#define MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR       (0x18)

#define MPI_FUNCTION_MAILBOX                        (0x19)

#define MPI_FUNCTION_SMP_PASSTHROUGH                (0x1A)
#define MPI_FUNCTION_SAS_IO_UNIT_CONTROL            (0x1B)
#define MPI_FUNCTION_SATA_PASSTHROUGH               (0x1C)

#define MPI_FUNCTION_DIAG_BUFFER_POST               (0x1D)
#define MPI_FUNCTION_DIAG_RELEASE                   (0x1E)

#define MPI_FUNCTION_SCSI_IO_32                     (0x1F)

#define MPI_FUNCTION_LAN_SEND                       (0x20)
#define MPI_FUNCTION_LAN_RECEIVE                    (0x21)
#define MPI_FUNCTION_LAN_RESET                      (0x22)

#define MPI_FUNCTION_TARGET_ASSIST_EXTENDED         (0x23)
#define MPI_FUNCTION_TARGET_CMD_BUF_BASE_POST       (0x24)
#define MPI_FUNCTION_TARGET_CMD_BUF_LIST_POST       (0x25)

#define MPI_FUNCTION_INBAND_BUFFER_POST             (0x28)
#define MPI_FUNCTION_INBAND_SEND                    (0x29)
#define MPI_FUNCTION_INBAND_RSP                     (0x2A)
#define MPI_FUNCTION_INBAND_ABORT                   (0x2B)

#define MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET         (0x40)
#define MPI_FUNCTION_IO_UNIT_RESET                  (0x41)
#define MPI_FUNCTION_HANDSHAKE                      (0x42)
#define MPI_FUNCTION_REPLY_FRAME_REMOVAL            (0x43)
#define MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL    (0x44)

/* standard version format */
typedef struct _MPI_VERSION_STRUCT
{
    U8                      Dev;                        /* 00h */
    U8                      Unit;                       /* 01h */
    U8                      Minor;                      /* 02h */
    U8                      Major;                      /* 03h */
} MPI_VERSION_STRUCT, MPI_POINTER PTR_MPI_VERSION_STRUCT,
  MpiVersionStruct_t, MPI_POINTER pMpiVersionStruct;

typedef union _MPI_VERSION_FORMAT
{
    MPI_VERSION_STRUCT      Struct;
    U32                     Word;
} MPI_VERSION_FORMAT, MPI_POINTER PTR_MPI_VERSION_FORMAT,
  MpiVersionFormat_t, MPI_POINTER pMpiVersionFormat_t;

/*****************************************************************************
*
*        S c a t t e r    G a t h e r    E l e m e n t s
*
*****************************************************************************/

/****************************************************************************/
/*  Simple element structures                                               */
/****************************************************************************/

typedef struct _SGE_SIMPLE32
{
    U32                     FlagsLength;
    U32                     Address;
} SGE_SIMPLE32, MPI_POINTER PTR_SGE_SIMPLE32,
  SGESimple32_t, MPI_POINTER pSGESimple32_t;

typedef struct _SGE_SIMPLE64
{
    U32                     FlagsLength;
    U64                     Address;
} SGE_SIMPLE64, MPI_POINTER PTR_SGE_SIMPLE64,
  SGESimple64_t, MPI_POINTER pSGESimple64_t;

typedef struct _SGE_SIMPLE_UNION
{
    U32                     FlagsLength;
    union
    {
        U32                 Address32;
        U64                 Address64;
    }u;
} SGE_SIMPLE_UNION, MPI_POINTER PTR_SGE_SIMPLE_UNION,
  SGESimpleUnion_t, MPI_POINTER pSGESimpleUnion_t;

/****************************************************************************/
/*  Chain element structures                                                */
/****************************************************************************/

typedef struct _SGE_CHAIN32
{
    U16                     Length;
    U8                      NextChainOffset;
    U8                      Flags;
    U32                     Address;
} SGE_CHAIN32, MPI_POINTER PTR_SGE_CHAIN32,
  SGEChain32_t, MPI_POINTER pSGEChain32_t;

typedef struct _SGE_CHAIN64
{
    U16                     Length;
    U8                      NextChainOffset;
    U8                      Flags;
    U64                     Address;
} SGE_CHAIN64, MPI_POINTER PTR_SGE_CHAIN64,
  SGEChain64_t, MPI_POINTER pSGEChain64_t;

typedef struct _SGE_CHAIN_UNION
{
    U16                     Length;
    U8                      NextChainOffset;
    U8                      Flags;
    union
    {
        U32                 Address32;
        U64                 Address64;
    }u;
} SGE_CHAIN_UNION, MPI_POINTER PTR_SGE_CHAIN_UNION,
  SGEChainUnion_t, MPI_POINTER pSGEChainUnion_t;

/****************************************************************************/
/*  Transaction Context element                                             */
/****************************************************************************/

typedef struct _SGE_TRANSACTION32
{
    U8                      Reserved;
    U8                      ContextSize;
    U8                      DetailsLength;
    U8                      Flags;
    U32                     TransactionContext[1];
    U32                     TransactionDetails[1];
} SGE_TRANSACTION32, MPI_POINTER PTR_SGE_TRANSACTION32,
  SGETransaction32_t, MPI_POINTER pSGETransaction32_t;

typedef struct _SGE_TRANSACTION64
{
    U8                      Reserved;
    U8                      ContextSize;
    U8                      DetailsLength;
    U8                      Flags;
    U32                     TransactionContext[2];
    U32                     TransactionDetails[1];
} SGE_TRANSACTION64, MPI_POINTER PTR_SGE_TRANSACTION64,
  SGETransaction64_t, MPI_POINTER pSGETransaction64_t;

typedef struct _SGE_TRANSACTION96
{
    U8                      Reserved;
    U8                      ContextSize;
    U8                      DetailsLength;
    U8                      Flags;
    U32                     TransactionContext[3];
    U32                     TransactionDetails[1];
} SGE_TRANSACTION96, MPI_POINTER PTR_SGE_TRANSACTION96,
  SGETransaction96_t, MPI_POINTER pSGETransaction96_t;

typedef struct _SGE_TRANSACTION128
{
    U8                      Reserved;
    U8                      ContextSize;
    U8                      DetailsLength;
    U8                      Flags;
    U32                     TransactionContext[4];
    U32                     TransactionDetails[1];
} SGE_TRANSACTION128, MPI_POINTER PTR_SGE_TRANSACTION128,
  SGETransaction_t128, MPI_POINTER pSGETransaction_t128;

typedef struct _SGE_TRANSACTION_UNION
{
    U8                      Reserved;
    U8                      ContextSize;
    U8                      DetailsLength;
    U8                      Flags;
    union
    {
        U32                 TransactionContext32[1];
        U32                 TransactionContext64[2];
        U32                 TransactionContext96[3];
        U32                 TransactionContext128[4];
    }u;
    U32                     TransactionDetails[1];
} SGE_TRANSACTION_UNION, MPI_POINTER PTR_SGE_TRANSACTION_UNION,
  SGETransactionUnion_t, MPI_POINTER pSGETransactionUnion_t;

/****************************************************************************/
/*  SGE IO types union  for IO SGL's                                        */
/****************************************************************************/

typedef struct _SGE_IO_UNION
{
    union
    {
        SGE_SIMPLE_UNION    Simple;
        SGE_CHAIN_UNION     Chain;
    } u;
} SGE_IO_UNION, MPI_POINTER PTR_SGE_IO_UNION,
  SGEIOUnion_t, MPI_POINTER pSGEIOUnion_t;

/****************************************************************************/
/*  SGE union for SGL's with Simple and Transaction elements                */
/****************************************************************************/

typedef struct _SGE_TRANS_SIMPLE_UNION
{
    union
    {
        SGE_SIMPLE_UNION        Simple;
        SGE_TRANSACTION_UNION   Transaction;
    } u;
} SGE_TRANS_SIMPLE_UNION, MPI_POINTER PTR_SGE_TRANS_SIMPLE_UNION,
  SGETransSimpleUnion_t, MPI_POINTER pSGETransSimpleUnion_t;

/****************************************************************************/
/*  All SGE types union                                                     */
/****************************************************************************/

typedef struct _SGE_MPI_UNION
{
    union
    {
        SGE_SIMPLE_UNION        Simple;
        SGE_CHAIN_UNION         Chain;
        SGE_TRANSACTION_UNION   Transaction;
    } u;
} SGE_MPI_UNION, MPI_POINTER PTR_SGE_MPI_UNION,
  MPI_SGE_UNION_t, MPI_POINTER pMPI_SGE_UNION_t,
  SGEAllUnion_t, MPI_POINTER pSGEAllUnion_t;

/****************************************************************************/
/*  SGE field definition and masks                                          */
/****************************************************************************/

/* Flags field bit definitions */

#define MPI_SGE_FLAGS_LAST_ELEMENT              (0x80)
#define MPI_SGE_FLAGS_END_OF_BUFFER             (0x40)
#define MPI_SGE_FLAGS_ELEMENT_TYPE_MASK         (0x30)
#define MPI_SGE_FLAGS_LOCAL_ADDRESS             (0x08)
#define MPI_SGE_FLAGS_DIRECTION                 (0x04)
#define MPI_SGE_FLAGS_ADDRESS_SIZE              (0x02)
#define MPI_SGE_FLAGS_END_OF_LIST               (0x01)

#define MPI_SGE_FLAGS_SHIFT                     (24)

#define MPI_SGE_LENGTH_MASK                     (0x00FFFFFF)
#define MPI_SGE_CHAIN_LENGTH_MASK               (0x0000FFFF)

/* Element Type */

#define MPI_SGE_FLAGS_TRANSACTION_ELEMENT       (0x00)
#define MPI_SGE_FLAGS_SIMPLE_ELEMENT            (0x10)
#define MPI_SGE_FLAGS_CHAIN_ELEMENT             (0x30)
#define MPI_SGE_FLAGS_ELEMENT_MASK              (0x30)

/* Address location */

#define MPI_SGE_FLAGS_SYSTEM_ADDRESS            (0x00)

/* Direction */

#define MPI_SGE_FLAGS_IOC_TO_HOST               (0x00)
#define MPI_SGE_FLAGS_HOST_TO_IOC               (0x04)

/* Address Size */

#define MPI_SGE_FLAGS_32_BIT_ADDRESSING         (0x00)
#define MPI_SGE_FLAGS_64_BIT_ADDRESSING         (0x02)

/* Context Size */

#define MPI_SGE_FLAGS_32_BIT_CONTEXT            (0x00)
#define MPI_SGE_FLAGS_64_BIT_CONTEXT            (0x02)
#define MPI_SGE_FLAGS_96_BIT_CONTEXT            (0x04)
#define MPI_SGE_FLAGS_128_BIT_CONTEXT           (0x06)

#define MPI_SGE_CHAIN_OFFSET_MASK               (0x00FF0000)
#define MPI_SGE_CHAIN_OFFSET_SHIFT              (16)

/****************************************************************************/
/*  SGE operation Macros                                                    */
/****************************************************************************/

         /* SIMPLE FlagsLength manipulations... */
#define  MPI_SGE_SET_FLAGS(f)           ((U32)(f) << MPI_SGE_FLAGS_SHIFT)
#define  MPI_SGE_GET_FLAGS(fl)          (((fl) & ~MPI_SGE_LENGTH_MASK) >> MPI_SGE_FLAGS_SHIFT)
#define  MPI_SGE_LENGTH(fl)             ((fl) & MPI_SGE_LENGTH_MASK)
#define  MPI_SGE_CHAIN_LENGTH(fl)       ((fl) & MPI_SGE_CHAIN_LENGTH_MASK)

#define  MPI_SGE_SET_FLAGS_LENGTH(f,l)  (MPI_SGE_SET_FLAGS(f) | MPI_SGE_LENGTH(l))

#define  MPI_pSGE_GET_FLAGS(psg)        MPI_SGE_GET_FLAGS((psg)->FlagsLength)
#define  MPI_pSGE_GET_LENGTH(psg)       MPI_SGE_LENGTH((psg)->FlagsLength)
#define  MPI_pSGE_SET_FLAGS_LENGTH(psg,f,l)  (psg)->FlagsLength = MPI_SGE_SET_FLAGS_LENGTH(f,l)
         /* CAUTION - The following are READ-MODIFY-WRITE! */
#define  MPI_pSGE_SET_FLAGS(psg,f)      (psg)->FlagsLength |= MPI_SGE_SET_FLAGS(f)
#define  MPI_pSGE_SET_LENGTH(psg,l)     (psg)->FlagsLength |= MPI_SGE_LENGTH(l)

#define  MPI_GET_CHAIN_OFFSET(x) ((x&MPI_SGE_CHAIN_OFFSET_MASK)>>MPI_SGE_CHAIN_OFFSET_SHIFT)

/*****************************************************************************
*
*        S t a n d a r d    M e s s a g e    S t r u c t u r e s
*
*****************************************************************************/

/****************************************************************************/
/* Standard message request header for all request messages                 */
/****************************************************************************/

typedef struct _MSG_REQUEST_HEADER
{
    U8                      Reserved[2];      /* function specific */
    U8                      ChainOffset;
    U8                      Function;
    U8                      Reserved1[3];     /* function specific */
    U8                      MsgFlags;
    U32                     MsgContext;
} MSG_REQUEST_HEADER, MPI_POINTER PTR_MSG_REQUEST_HEADER,
  MPIHeader_t, MPI_POINTER pMPIHeader_t;

/****************************************************************************/
/*  Default Reply                                                           */
/****************************************************************************/

typedef struct _MSG_DEFAULT_REPLY
{
    U8                      Reserved[2];      /* function specific */
    U8                      MsgLength;
    U8                      Function;
    U8                      Reserved1[3];     /* function specific */
    U8                      MsgFlags;
    U32                     MsgContext;
    U8                      Reserved2[2];     /* function specific */
    U16                     IOCStatus;
    U32                     IOCLogInfo;
} MSG_DEFAULT_REPLY, MPI_POINTER PTR_MSG_DEFAULT_REPLY,
  MPIDefaultReply_t, MPI_POINTER pMPIDefaultReply_t;

/* MsgFlags definition for all replies */

#define MPI_MSGFLAGS_CONTINUATION_REPLY         (0x80)

/*****************************************************************************
*
*               I O C    S t a t u s   V a l u e s
*
*****************************************************************************/

/****************************************************************************/
/*  Common IOCStatus values for all replies                                 */
/****************************************************************************/

#define MPI_IOCSTATUS_SUCCESS                   (0x0000)
#define MPI_IOCSTATUS_INVALID_FUNCTION          (0x0001)
#define MPI_IOCSTATUS_BUSY                      (0x0002)
#define MPI_IOCSTATUS_INVALID_SGL               (0x0003)
#define MPI_IOCSTATUS_INTERNAL_ERROR            (0x0004)
#define MPI_IOCSTATUS_RESERVED                  (0x0005)
#define MPI_IOCSTATUS_INSUFFICIENT_RESOURCES    (0x0006)
#define MPI_IOCSTATUS_INVALID_FIELD             (0x0007)
#define MPI_IOCSTATUS_INVALID_STATE             (0x0008)
#define MPI_IOCSTATUS_OP_STATE_NOT_SUPPORTED    (0x0009)

/****************************************************************************/
/*  Config IOCStatus values                                                 */
/****************************************************************************/

#define MPI_IOCSTATUS_CONFIG_INVALID_ACTION     (0x0020)
#define MPI_IOCSTATUS_CONFIG_INVALID_TYPE       (0x0021)
#define MPI_IOCSTATUS_CONFIG_INVALID_PAGE       (0x0022)
#define MPI_IOCSTATUS_CONFIG_INVALID_DATA       (0x0023)
#define MPI_IOCSTATUS_CONFIG_NO_DEFAULTS        (0x0024)
#define MPI_IOCSTATUS_CONFIG_CANT_COMMIT        (0x0025)

/****************************************************************************/
/*  SCSIIO Reply (SPI & FCP) initiator values                               */
/****************************************************************************/

#define MPI_IOCSTATUS_SCSI_RECOVERED_ERROR      (0x0040)
#define MPI_IOCSTATUS_SCSI_INVALID_BUS          (0x0041)
#define MPI_IOCSTATUS_SCSI_INVALID_TARGETID     (0x0042)
#define MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE     (0x0043)
#define MPI_IOCSTATUS_SCSI_DATA_OVERRUN         (0x0044)
#define MPI_IOCSTATUS_SCSI_DATA_UNDERRUN        (0x0045)
#define MPI_IOCSTATUS_SCSI_IO_DATA_ERROR        (0x0046)
#define MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR       (0x0047)
#define MPI_IOCSTATUS_SCSI_TASK_TERMINATED      (0x0048)
#define MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH    (0x0049)
#define MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED     (0x004A)
#define MPI_IOCSTATUS_SCSI_IOC_TERMINATED       (0x004B)
#define MPI_IOCSTATUS_SCSI_EXT_TERMINATED       (0x004C)

/****************************************************************************/
/*  For use by SCSI Initiator and SCSI Target end-to-end data protection    */
/****************************************************************************/

#define MPI_IOCSTATUS_EEDP_GUARD_ERROR          (0x004D)
#define MPI_IOCSTATUS_EEDP_REF_TAG_ERROR        (0x004E)
#define MPI_IOCSTATUS_EEDP_APP_TAG_ERROR        (0x004F)

/****************************************************************************/
/*  SCSI Target values                                                      */
/****************************************************************************/

#define MPI_IOCSTATUS_TARGET_PRIORITY_IO         (0x0060)
#define MPI_IOCSTATUS_TARGET_INVALID_PORT        (0x0061)
#define MPI_IOCSTATUS_TARGET_INVALID_IOCINDEX    (0x0062)   /* obsolete name */
#define MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX    (0x0062)
#define MPI_IOCSTATUS_TARGET_ABORTED             (0x0063)
#define MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE   (0x0064)
#define MPI_IOCSTATUS_TARGET_NO_CONNECTION       (0x0065)
#define MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH (0x006A)
#define MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT   (0x006B)
#define MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR   (0x006D)
#define MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E)
#define MPI_IOCSTATUS_TARGET_IU_TOO_SHORT        (0x006F)
#define MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT     (0x0070)
#define MPI_IOCSTATUS_TARGET_NAK_RECEIVED        (0x0071)

/****************************************************************************/
/*  Additional FCP target values (obsolete)                                 */
/****************************************************************************/

#define MPI_IOCSTATUS_TARGET_FC_ABORTED         (0x0066)    /* obsolete */
#define MPI_IOCSTATUS_TARGET_FC_RX_ID_INVALID   (0x0067)    /* obsolete */
#define MPI_IOCSTATUS_TARGET_FC_DID_INVALID     (0x0068)    /* obsolete */
#define MPI_IOCSTATUS_TARGET_FC_NODE_LOGGED_OUT (0x0069)    /* obsolete */

/****************************************************************************/
/*  Fibre Channel Direct Access values                                      */
/****************************************************************************/

#define MPI_IOCSTATUS_FC_ABORTED                (0x0066)
#define MPI_IOCSTATUS_FC_RX_ID_INVALID          (0x0067)
#define MPI_IOCSTATUS_FC_DID_INVALID            (0x0068)
#define MPI_IOCSTATUS_FC_NODE_LOGGED_OUT        (0x0069)
#define MPI_IOCSTATUS_FC_EXCHANGE_CANCELED      (0x006C)

/****************************************************************************/
/*  LAN values                                                              */
/****************************************************************************/

#define MPI_IOCSTATUS_LAN_DEVICE_NOT_FOUND      (0x0080)
#define MPI_IOCSTATUS_LAN_DEVICE_FAILURE        (0x0081)
#define MPI_IOCSTATUS_LAN_TRANSMIT_ERROR        (0x0082)
#define MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED      (0x0083)
#define MPI_IOCSTATUS_LAN_RECEIVE_ERROR         (0x0084)
#define MPI_IOCSTATUS_LAN_RECEIVE_ABORTED       (0x0085)
#define MPI_IOCSTATUS_LAN_PARTIAL_PACKET        (0x0086)
#define MPI_IOCSTATUS_LAN_CANCELED              (0x0087)

/****************************************************************************/
/*  Serial Attached SCSI values                                             */
/****************************************************************************/

#define MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED    (0x0090)
#define MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN      (0x0091)

/****************************************************************************/
/*  Inband values                                                           */
/****************************************************************************/

#define MPI_IOCSTATUS_INBAND_ABORTED            (0x0098)
#define MPI_IOCSTATUS_INBAND_NO_CONNECTION      (0x0099)

/****************************************************************************/
/*  Diagnostic Tools values                                                 */
/****************************************************************************/

#define MPI_IOCSTATUS_DIAGNOSTIC_RELEASED       (0x00A0)

/****************************************************************************/
/*  IOCStatus flag to indicate that log info is available                   */
/****************************************************************************/

#define MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE   (0x8000)
#define MPI_IOCSTATUS_MASK                      (0x7FFF)

/****************************************************************************/
/*  LogInfo Types                                                           */
/****************************************************************************/

#define MPI_IOCLOGINFO_TYPE_MASK                (0xF0000000)
#define MPI_IOCLOGINFO_TYPE_SHIFT               (28)
#define MPI_IOCLOGINFO_TYPE_NONE                (0x0)
#define MPI_IOCLOGINFO_TYPE_SCSI                (0x1)
#define MPI_IOCLOGINFO_TYPE_FC                  (0x2)
#define MPI_IOCLOGINFO_TYPE_SAS                 (0x3)
#define MPI_IOCLOGINFO_TYPE_ISCSI               (0x4)
#define MPI_IOCLOGINFO_LOG_DATA_MASK            (0x0FFFFFFF)

#endif