/*
 * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
 * All rights reserved.
 */

#ifndef	_SYS_FIBRE_CHANNEL_FCA_QLC_H
#define	_SYS_FIBRE_CHANNEL_FCA_QLC_H

#pragma ident	"@(#)qlc.h	1.4	00/08/18 SMI"

/*
 * Qlogic ISP2200/ISP2202 FCA driver header
 */

/*
 * ISP2200 Extended LUN Solaris SPARC v2.7/v2.8
 * Fibre Channel Adapter (FCA) driver include file.
 *
 * ***********************************************************************
 * *									**
 * *				NOTICE					**
 * *		COPYRIGHT (C) 1996-2000 QLOGIC CORPORATION		**
 * *			ALL RIGHTS RESERVED				**
 * *									**
 * *	This  computer program is CONFIDENTIAL and contains TRADE	**
 * *	SECRETS of QLOGIC CORPORATION. The receipt or possession of	**
 * *	this program does not convey any rights to reproduce or		**
 * *	disclose its contents, or to manufacture, use, or sell anything **
 * *	that it may describe, in whole or in part, without the specific **
 * *	written consent of QLOGIC CORPORATION. Any reproduction of this **
 * *	program without the express written consent of  QLOGIC		**
 * *	CORPORATION is a violation of the copyright laws and may	**
 * *	subject you to civil liability and criminal prosecution.	**
 * *									**
 * ***********************************************************************
 */

#ifdef	__cplusplus
extern "C" {
#endif

#include <sys/fibre-channel/ulp/fcp.h>

#ifndef QLC_DRV_HARDENING
#define	ddi_devstate_t			int
#define	DDI_DEVSTATE_UP			0
#define	ddi_get_devstate(a)		DDI_DEVSTATE_UP
#define	ddi_dev_report_fault(a, b, c, d)
#define	ddi_check_dma_handle(a)		DDI_SUCCESS
#define	ddi_check_acc_handle(a)		DDI_SUCCESS
#define	QLC_CLEAR_DMA_HANDLE(x)
#else
#define	QLC_CLEAR_DMA_HANDLE(x)	((ddi_dma_impl_t *)x)->dmai_fault_notify = 0; \
				((ddi_dma_impl_t *)x)->dmai_fault_check  = 0; \
				((ddi_dma_impl_t *)x)->dmai_fault	 = 0
#endif

/*
 * Data bit definitions.
 */
#define	BIT_0   0x1
#define	BIT_1   0x2
#define	BIT_2   0x4
#define	BIT_3   0x8
#define	BIT_4   0x10
#define	BIT_5   0x20
#define	BIT_6   0x40
#define	BIT_7   0x80
#define	BIT_8   0x100
#define	BIT_9   0x200
#define	BIT_10  0x400
#define	BIT_11  0x800
#define	BIT_12  0x1000
#define	BIT_13  0x2000
#define	BIT_14  0x4000
#define	BIT_15  0x8000
#define	BIT_16  0x10000
#define	BIT_17  0x20000
#define	BIT_18  0x40000
#define	BIT_19  0x80000
#define	BIT_20  0x100000
#define	BIT_21  0x200000
#define	BIT_22  0x400000
#define	BIT_23  0x800000
#define	BIT_24  0x1000000
#define	BIT_25  0x2000000
#define	BIT_26  0x4000000
#define	BIT_27  0x8000000
#define	BIT_28  0x10000000
#define	BIT_29  0x20000000
#define	BIT_30  0x40000000
#define	BIT_31  0x80000000

/*
 *  Local Macro Definitions.
 */
#ifndef TRUE
#define	TRUE  1
#endif

#ifndef FALSE
#define	FALSE 0
#endif

#define	QLC_MAX_WORDS		256

/*
 * I/O register
 */
#ifdef _SDEBUG_1
#define	RD_REG_BYTE(ha, addr) \
    qlc_getbyte(ha, (uint8_t *)addr)
#define	RD_REG_WORD(ha, addr) \
    qlc_getword(ha, (uint16_t *)addr)
#define	RD_REG_DWORD(ha, addr) \
    qlc_getdword(ha, (uint32_t *)addr)
#define	WRT_REG_BYTE(ha, addr, data) \
    qlc_putbyte(ha, (uint8_t *)addr, data)
#define	WRT_REG_WORD(ha, addr, data) \
    qlc_putword(ha, (uint16_t *)addr, data)
#define	WRT_REG_DWORD(ha, addr, data) \
    qlc_putdword(ha, (uint32_t *)addr, data)
#else
#define	RD_REG_BYTE(ha, addr) \
    ddi_get8(ha->dev_handle, (uint8_t *)addr)

#define	RD_REG_WORD(ha, addr) \
    ddi_get16((ha)->dev_handle, (uint16_t *)addr)
#define	RD_REG_DWORD(ha, addr) \
    ddi_get32(ha->dev_handle, (uint32_t *)addr)
#define	WRT_REG_BYTE(ha, addr, data)  \
    ddi_put8(ha->dev_handle, (uint8_t *)addr, data)
#define	WRT_REG_WORD(ha, addr, data) \
    ddi_put16(ha->dev_handle, (uint16_t *)addr, data)


#define	WRT_REG_DWORD(ha, addr, data) \
    ddi_put32(ha->dev_handle, (uint32_t *)addr, data)
#endif

/*
 * FCA definitions
 */
#define	MAX_LUNS	256
#define	QLC_FCA_BRAND	0x0fca2200

/* Following to be removed when defined by OS. */
/* ************************************************************************ */
#define	LA_ELS_FARP_REQ		0x54
#define	LA_ELS_FARP_REPLY	0x55
#define	LA_ELS_LPC		0x71
#define	LA_ELS_LSTS		0x72

typedef struct {
	ls_code_t ls_code;
	uint8_t rsvd[3];
	uint8_t port_control;
	uint8_t lpb[16];
	uint8_t lpe[16];
} qlc_lpc_t;

typedef struct {
	ls_code_t ls_code;
} qlc_acc_rjt_t;

typedef	fc_linit_resp_t qlc_lpc_resp_t;
typedef	fc_scr_resp_t qlc_rscn_resp_t;

typedef struct {
	uint16_t    class_valid_svc_opt;
	uint16_t    initiator_ctl;
	uint16_t    recipient_ctl;
	uint16_t    rcv_data_size;
	uint16_t    conc_sequences;
	uint16_t    n_port_end_to_end_credit;
	uint16_t    open_sequences_per_exch;
	uint16_t    unused;
} class_svc_param_t;

typedef struct {
	uint16_t    type;
	uint16_t    process_assoc_flags;
	uint32_t    originator_process;
	uint32_t    responder_process;
	uint32_t    process_flags;
} prli_svc_param_t;
/* *********************************************************************** */

/*
 * Qlogic 220x supported Frame length
 */
#define	QLC_FRAME_512			512
#define	QLC_FRAME_1024			1024
#define	QLC_FRAME_2048			2048

#define	QLC_IOCB_COUNT			256
#define	QLC_EXECUTION_THROTTLE		32
#define	QLC_LOGIN_TIMEOUT		3	/* seconds */
#define	QLC_LOGIN_RETRY_COUNT		4
#define	QLC_ADAPTER_RESET_DELAY		5
#define	QLC_PORT_DOWN_RETRY_COUNT	0
#define	QLC_LOOP_DOWN_TIMEOUT		0
#define	QLC_IP_BUFFER_COUNT		128
#define	QLC_IP_LOW_WATER		10
#define	QLC_IP_FAST_POST_COUNT		5	/* should be <= 13 */
#define	QLC_HARD_ADDRESS		0

/*
 * Qlogic 220x connection mode
 */
#define	QLC_TOP_LOOP_ONLY		0
#define	QLC_TOP_PT_PT_ONLY		1
#define	QLC_TOP_LOOP_PREFERRED		2	/* pt-pt otherwise */
#define	QLC_TOP_PT_PT_PREFERRED		3	/* loop otherwise */

#define	QLC_ENABLE_HARD_ADDRESS		0x0001
#define	QLC_ENABLE_64BIT_ADDRESS	0x0002
#define	QLC_ENABLE_LIP_RESET		0x0004
#define	QLC_ENABLE_FULL_LIP_LOGIN	0x0008
#define	QLC_ENABLE_TARGET_RESET		0x0010
#define	QLC_ENABLE_LINK_DOWN_REPORTING	0x0020
#define	QLC_ENABLE_TARGET_MODE		0x0040
#define	QLC_ENABLE_FC_TAPE_SUPPORT	0x0080

/*
 * Fibre Channel device definitions.
 */
#define	MAX_FIBRE_DEVICES	256

#define	LAST_LOCAL_LOOP_ID		 0x7d
#define	FL_PORT_LOOP_ID			 0x7e /* FFFFFE Fabric F_Port */
#define	SWITCH_FABRIC_CONTROLLER_LOOP_ID 0x7f /* FFFFFD Fabric Controller */
#define	SIMPLE_NAME_SERVER_LOOP_ID	 0x80 /* FFFFFC Directory Server */
#define	SWITCH_EMBEDDED_PORT_LOOP_ID	 0x81 /* FFFC4X Brocade only */
#define	SNS_FIRST_LOOP_ID		 0x82
#define	SNS_LAST_LOOP_ID		 0xfe
#define	IP_BROADCAST_LOOP_ID		 0xff /* FFFFFF Broadcast */

/* Loop ID's used as flags, must be higher than any valid Loop ID */
#define	PORT_NO_LOOP_ID	0x100		/* Device does not have loop ID. */
#define	PORT_LOST_ID	0x200		/* Device has been lost. */

/* Fibre Channel Topoploy. */
#define	QLC_N_PORT		BIT_0
#define	QLC_NL_PORT		BIT_1
#define	QLC_F_PORT		BIT_2
#define	QLC_FL_PORT		BIT_3
#define	QLC_SNS_CONNECTION	BIT_4
#define	QLC_LOOP_CONNECTION	(QLC_NL_PORT | QLC_FL_PORT)
#define	QLC_P2P_CONNECTION	(QLC_F_PORT | QLC_N_PORT)

/* Timeout timer counts in seconds (must greater than 1 second). */
#define	WATCHDOG_TIME		5			/* 0 - 255 */
#define	PORT_RETRY_TIME		2			/* 0 - 255 */
#define	LOOP_DOWN_TIME		240			/* 0 - 255 */
#define	LOOP_DOWN_RESET		(LOOP_DOWN_TIME - 45)	/* 0 - 255 */
#define	IDLE_CHECK_TIMER	300			/* 0 - 65535 */
#define	MAX_DEVICE_LOST_RETRY	16			/* 0 - 255 */

/* Maximum outstanding commands in ISP queues (1-65535) */
#define	MAX_OUTSTANDING_COMMANDS   1024

/* Maximum unsolicited buffers (1-65535) */
#define	QLC_UB_LIMIT	128

/* ISP request, response and receive buffer entry counts */
#define	REQUEST_ENTRY_CNT	256   /* Request entries (54-65535) */
#define	RESPONSE_ENTRY_CNT	64    /* Response entries (1-65535) */
#define	RCVBUF_CONTAINER_CNT	64    /* Receive buffer containers (8-1024) */

/*
 * DMA attributes definitions.
 */
#define	QLC_DMA_LOW_ADDRESS		(uint64_t)0
#define	QLC_DMA_HIGH_64BIT_ADDRESS	(uint64_t)0xffffffffffffffff
#define	QLC_DMA_HIGH_32BIT_ADDRESS	(uint64_t)0xffffffff
#define	QLC_DMA_XFER_COUNTER		(uint64_t)0xffffffff
#define	QLC_DMA_ADDRESS_ALIGNMENT	(uint64_t)8
#define	QLC_DMA_BURSTSIZES		0xff
#define	QLC_DMA_MIN_XFER_SIZE		1
#define	QLC_DMA_MAX_XFER_SIZE		(uint64_t)0xffffffff
#define	QLC_DMA_SEGMENT_BOUNDARY	(uint64_t)0xffffffff

#ifdef sparc
#define	QLC_DMA_SG_LIST_LIMIT   1
#define	QLC_DMA_SG_LIST_LENGTH  1
#else
#define	QLC_DMA_SG_LIST_LIMIT   (((REQUEST_ENTRY_CNT - 1) * 7) - 3)
#define	QLC_DMA_SG_LIST_LENGTH  256
#endif

#define	QLC_DMA_GRANULARITY	1
#define	QLC_DMA_XFER_FLAGS	0

typedef union  {
	uint64_t size64;	/* 1 X 64 bit number */
	uint32_t size32[2];	/* 2 x 32 bit number */
	uint8_t	 size16[4];	/* 4 x 16 bit number */
	uint8_t	 size8[8];	/* 8 x  8 bit number */
} conv_num_t;

/*
 *  ISP PCI Configuration.
 */
#define	PCI_VENDER_ID   0x1077
#define	PCI_DEVICE_ID   0x2200

/*
 *  ISP I/O Register Set structure definitions.
 */
#define	MAILBOX_REGISTER_COUNT  24

typedef volatile struct {
	volatile uint16_t flash_address; /* Flash BIOS address */
	volatile uint16_t flash_data;	/* Flash BIOS data */
	volatile uint16_t unused_1[1];	/* Gap */
	volatile uint16_t ctrl_status;	/* Control/Status */
#define	ISP_FLASH_64K_BANK	BIT_3	/* Flash BIOS 64K Bank Select */
#define	ISP_FLASH_ENABLE	BIT_1	/* Flash BIOS Read/Write enable */
#define	ISP_RESET		BIT_0   /* ISP soft reset */
	volatile uint16_t ictrl;	/* Interrupt control */
#define	ISP_EN_INT		BIT_15  /* ISP enable interrupts. */
#define	ISP_EN_RISC		BIT_3   /* ISP enable RISC interrupts. */
	volatile uint16_t istatus;	/* Interrupt status */
#define	RISC_INT		BIT_3   /* RISC interrupt */
	volatile uint16_t semaphore;	/* Semaphore */
	volatile uint16_t nvram;	/* NVRAM register. */
#define	NV_DESELECT		0
#define	NV_CLOCK		BIT_0
#define	NV_SELECT		BIT_1
#define	NV_DATA_OUT		BIT_2
#define	NV_DATA_IN		BIT_3
	volatile uint16_t mailbox0;
	volatile uint16_t mailbox1;
	volatile uint16_t mailbox2;
	volatile uint16_t mailbox3;
	volatile uint16_t mailbox4;
	volatile uint16_t mailbox5;
	volatile uint16_t mailbox6;
	volatile uint16_t mailbox7;
	uint16_t unused_2[0x3b];	/* Gap */
	volatile uint16_t fpm_diag_config;
	uint16_t unused_3[0x6];		/* Gap */
	volatile uint16_t pcr;		/* Processor Control Register. */
	uint16_t unused_4[0x5];		/* Gap */
	volatile uint16_t mctr;		/* Memory Configuration and Timing. */
	uint16_t unused_5[0x3];		/* Gap */
	volatile uint16_t fb_cmd;
	uint16_t unused_6[0x3];		/* Gap */
	volatile uint16_t hccr;		/* Host command & control register. */
#define	HC_RESET_RISC		0x1000	/* Reset RISC */
#define	HC_PAUSE_RISC		0x2000	/* Pause RISC */
#define	HC_RELEASE_RISC		0x3000	/* Release RISC from reset. */
#define	HC_DISABLE_PARITY_PAUSE	0x4001	/* Disable parity error RISC pause. */
#define	HC_SET_HOST_INT		0x5000	/* Set host interrupt */
#define	HC_CLR_HOST_INT		0x6000	/* Clear HOST interrupt */
#define	HC_CLR_RISC_INT		0x7000	/* Clear RISC interrupt */
#define	HC_HOST_INT	BIT_7		/* Host interrupt bit */
#define	HC_RISC_PAUSE	BIT_5		/* Pause mode bit */
	uint16_t unused_7[5];		/* Gap */
	volatile uint16_t gpiod;	/* GPIO Data register. */
	volatile uint16_t gpioe;	/* GPIO Enable register. */
	uint16_t unused_8[8];		/* Gap */
	volatile uint16_t mailbox8;
	volatile uint16_t mailbox9;
	volatile uint16_t mailbox10;
	volatile uint16_t mailbox11;
	volatile uint16_t mailbox12;
	volatile uint16_t mailbox13;
	volatile uint16_t mailbox14;
	volatile uint16_t mailbox15;
	volatile uint16_t mailbox16;
	volatile uint16_t mailbox17;
	volatile uint16_t mailbox18;
	volatile uint16_t mailbox19;
	volatile uint16_t mailbox20;
	volatile uint16_t mailbox21;
	volatile uint16_t mailbox22;
	volatile uint16_t mailbox23;
} device_reg_t;

/*
 *  ISP product identification definitions in mailboxes after reset.
 */
#define	PROD_ID_1	0x4953
#define	PROD_ID_2	0x0000
#define	PROD_ID_2a	0x5020
#define	PROD_ID_3	0x2020
#define	PROD_ID_4	0x1

/*
 * ISP mailbox Self-Test status codes
 */
#define	MBS_FRM_ALIVE	0	/* Firmware Alive. */
#define	MBS_CHKSUM_ERR	1	/* Checksum Error. */
#define	MBS_BUSY	4	/* Busy. */

/*
 * ISP mailbox command complete status codes
 */
#define	MBS_COMMAND_COMPLETE		0x4000
#define	MBS_INVALID_COMMAND		0x4001
#define	MBS_HOST_INTERFACE_ERROR	0x4002
#define	MBS_TEST_FAILED			0x4003
#define	MBS_COMMAND_ERROR		0x4005
#define	MBS_COMMAND_PARAMETER_ERROR	0x4006
#define	MBS_PORT_ID_USED		0x4007
#define	MBS_LOOP_ID_USED		0x4008
#define	MBS_ALL_IDS_IN_USE		0x4009
#define	MBS_NOT_LOGGED_IN		0x400A
#define	MBS_LOOP_DOWN			0x400B
#define	MBS_LOOP_BACK_ERROR		0x400C

#define	MBS_MASK			0x3fff
#define	MBS_END				0x100

/*
 * ISP mailbox asynchronous event status codes
 */
#define	MBA_ASYNC_EVENT		0x8000  /* Asynchronous event. */
#define	MBA_RESET		0x8001  /* Reset Detected. */
#define	MBA_SYSTEM_ERR		0x8002  /* System Error. */
#define	MBA_REQ_TRANSFER_ERR	0x8003  /* Request Transfer Error. */
#define	MBA_RSP_TRANSFER_ERR	0x8004  /* Response Transfer Error. */
#define	MBA_WAKEUP_THRES	0x8005  /* Request Queue Wake-up. */
#define	MBA_LIP_OCCURRED	0x8010  /* Loop Initialization Procedure */
					/* occurred. */
#define	MBA_LOOP_UP		0x8011  /* FC Loop UP. */
#define	MBA_LOOP_DOWN		0x8012  /* FC Loop Down. */
#define	MBA_LIP_RESET		0x8013	/* LIP reset occurred. */
#define	MBA_PORT_UPDATE		0x8014  /* Port Database update. */
#define	MBA_SCR_UPDATE		0x8015  /* State Change Registration. */
#define	MBA_SCSI_COMPLETION	0x8020  /* SCSI Command Complete. */
#define	MBA_CTIO_COMPLETION	0x8021  /* CTIO Complete. */
#define	MBA_IP_COMPLETION	0x8022  /* IP Transmit Command Complete. */
#define	MBA_IP_RECEIVE		0x8023  /* IP Received. */
#define	MBA_IP_BROADCAST	0x8024  /* IP Broadcast Received. */
#define	MBA_IP_LOW_WATER_MARK   0x8025  /* IP Low Water Mark reached. */
#define	MBA_IP_RCV_BUFFER_EMPTY 0x8026  /* IP receive buffer queue empty. */
#define	MBA_IP_HDR_DATA_SPLIT   0x8027  /* IP header/data splitting feature */
					/* used. */
#define	MBA_POINT_TO_POINT	0x8030  /* Point to point mode. */
#define	MBA_CHG_IN_CONNECTION   0x8036  /* Change in connection mode. */

/*
 * Mailbox 23 event codes
 */
#define	MBX23_MBX_OR_ASYNC_EVENT	0x0
#define	MBX23_RESPONSE_QUEUE_UPDATE	0x1
#define	MBX23_SCSI_COMPLETION		0x2

/*
 * ISP mailbox commands
 */
#define	MBC_LOAD_RAM			1	/* Load RAM. */
#define	MBC_EXECUTE_FIRMWARE		2	/* Execute firmware. */
#define	MBC_DUMP_RAM			3	/* Dump RAM. */
#define	MBC_WRITE_RAM_WORD		4	/* Write RAM word. */
#define	MBC_READ_RAM_WORD		5	/* Read RAM word. */
#define	MBC_MAILBOX_REGISTER_TEST	6	/* Wrap incoming mailboxes */
#define	MBC_VERIFY_CHECKSUM		7	/* Verify checksum. */
#define	MBC_GET_FIRMWARE_VERSION	8	/* Get firmware revision. */
#define	MBC_ABORT_COMMAND_IOCB		0x15	/* Abort IOCB command. */
#define	MBC_ABORT_DEVICE		0x16	/* Abort device (ID/LUN). */
#define	MBC_ABORT_TARGET		0x17	/* Abort target (ID). */
#define	MBC_RESET			0x18	/* Target reset. */
#define	MBC_GET_LOOP_ID			0x20	/* Get loop id of ISP2200. */
#define	MBC_LOOP_PORT_BYPASS		0x40	/* Loop Port Bypass. */
#define	MBC_LOOP_PORT_ENABLE		0x41	/* Loop Port Enable. */
#define	MBC_NON_PARTICIPATE		0x43	/* Non-Participating Mode. */
#define	MBC_DIAGNOSTIC_LOOP_BACK	0x45	/* Diagnostic loop back. */
#define	MBC_ONLINE_SELF_TEST		0x46	/* Online self-test. */
#define	MBC_ENHANCED_GET_PORT_DATABASE	0x47	/* Get Port Database + login */
#define	MBC_INITIALIZE_FIRMWARE		0x60	/* Initialize firmware */
#define	MBC_INITIATE_LIP		0x62	/* Initiate LIP */
#define	MBC_GET_FC_AL_POSITION_MAP	0x63	/* Get FC_AL Position Map. */
#define	MBC_GET_PORT_DATABASE		0x64	/* Get Port Database. */
#define	MBC_CLEAR_ACA			0x65	/* Clear ACA. */
#define	MBC_TARGET_RESET		0x66	/* Target Reset. */
#define	MBC_CLEAR_TASK_SET		0x67	/* Clear Task Set. */
#define	MBC_ABORT_TASK_SET		0x68	/* Abort Task Set. */
#define	MBC_GET_FIRMWARE_STATE		0x69	/* Get firmware state. */
#define	MBC_GET_PORT_NAME		0x6a	/* Get port name. */
#define	MBC_GET_LINK_STATUS		0x6b	/* Get Link Status. */
#define	MBC_LIP_RESET			0x6c	/* LIP reset. */
#define	MBC_SEND_SNS_COMMAND		0x6e	/* Send Simple Name Server */
#define	MBC_LOGIN_FABRIC_PORT		0x6f	/* Login fabric port. */
#define	MBC_SEND_CHANGE_REQUEST		0x70	/* Send Change Request. */
#define	MBC_LOGOUT_FABRIC_PORT		0x71	/* Logout fabric port. */
#define	MBC_LIP_FULL_LOGIN		0x72	/* Full login LIP. */
#define	MBC_LOGIN_LOOP_PORT		0x74	/* Login Loop Port. */
#define	MBC_PORT_NODE_NAME_LIST		0x75	/* Get port/node name list */
#define	MBC_INITIALIZE_RECEIVE_QUEUE	0x77	/* Initialize receive queue */
#define	MBC_SEND_FARP_REQ_COMMAND	0x78	/* FARP request. */
#define	MBC_SHUTDOWN_IP			0x79	/* Shutdown IP */
#define	MBC_PORT_LOOP_NAME_LIST		0x7C	/* Get port/node name list. */
#define	MBC_SEND_LFA_COMMAND		0x7D	/* Send Loop Fabric Address */

/*
 * Driver Mailbox command definitions.
 */
#define	MAILBOX_BUFFER_SIZE	0xc00

/* Mailbox command parameter structure definition. */
typedef struct {
	uint32_t out_mb;		/* Outgoing from driver */
	uint32_t in_mb;			/* Incomming from RISC */
	uint16_t mb[MAILBOX_REGISTER_COUNT];
	size_t   buf_size;
	caddr_t  bufp;
	clock_t  timeout;		/* Timeout in seconds. */
} mbx_cmd_t;

/* Mailbox bit definitions for out_mb and in_mb */
#define	MBX_DMA_OUT	BIT_31
#define	MBX_DMA_IN	BIT_30
#define	MBX_23		BIT_23
#define	MBX_22		BIT_22
#define	MBX_21		BIT_21
#define	MBX_20		BIT_20
#define	MBX_19		BIT_19
#define	MBX_18		BIT_18
#define	MBX_17		BIT_17
#define	MBX_16		BIT_16
#define	MBX_15		BIT_15
#define	MBX_14		BIT_14
#define	MBX_13		BIT_13
#define	MBX_12		BIT_12
#define	MBX_11		BIT_11
#define	MBX_10		BIT_10
#define	MBX_9		BIT_9
#define	MBX_8		BIT_8
#define	MBX_7		BIT_7
#define	MBX_6		BIT_6
#define	MBX_5		BIT_5
#define	MBX_4		BIT_4
#define	MBX_3		BIT_3
#define	MBX_2		BIT_2
#define	MBX_1		BIT_1
#define	MBX_0		BIT_0

/*
 * Firmware state codes from get firmware state mailbox command
 */
#define	FSTATE_CONFIG_WAIT	0
#define	FSTATE_WAIT_AL_PA	1
#define	FSTATE_WAIT_LOGIN	2
#define	FSTATE_READY		3
#define	FSTATE_ERROR		4
#define	FSTATE_REINIT		5
#define	FSTATE_NON_PART		6

/* Diagnostic loop back parameter structure definition. */
typedef struct {
	uint16_t  options;
	uint32_t  transfer_count;
	uint16_t  transfer_segment_count;
	uint16_t  receive_segment_count;
	uint32_t  transfer_data_address;
	uint32_t  receive_data_address;
	uint32_t  iteration_count;
} lbp_t;

/* Define size of Loop Position Map. */
#define	LOOP_POSITION_MAP_SIZE  128	/* bytes */

/*
 * Port Database structure definition
 * Little endian except where noted.
 */
#define	PORT_DATABASE_SIZE	128	/* bytes */
typedef struct {
	uint8_t  options;
	uint8_t  control;
	uint8_t  master_state;
	uint8_t  slave_state;
#define	PD_STATE_DISCOVERY			0
#define	PD_STATE_WAIT_DISCOVERY_ACK		1
#define	PD_STATE_PORT_LOGIN			2
#define	PD_STATE_WAIT_PORT_LOGIN_ACK		3
#define	PD_STATE_PROCESS_LOGIN			4
#define	PD_STATE_WAIT_PROCESS_LOGIN_ACK		5
#define	PD_STATE_PORT_LOGGED_IN			6
#define	PD_STATE_PORT_UNAVAILABLE		7
#define	PD_STATE_PROCESS_LOGOUT			8
#define	PD_STATE_WAIT_PROCESS_LOGOUT_ACK	9
#define	PD_STATE_PORT_LOGOUT			10
#define	PD_STATE_WAIT_PORT_LOGOUT_ACK		11
	uint32_t hard_address : 24,
		rsvd : 8;
	uint32_t port_id;
	uint8_t  node_name[8];		/* Big endian. */
	uint8_t  port_name[8];		/* Big endian. */
	uint16_t execution_throttle;
	uint16_t execution_count;
	uint8_t  reset_count;
	uint8_t  reserved_2;
	uint16_t resource_allocation;
	uint16_t current_allocation;
	uint16_t queue_head;
	uint16_t queue_tail;
	uint16_t transmit_execution_list_next;
	uint16_t transmit_execution_list_previous;
	uint16_t common_features;
	uint16_t total_concurrent_sequences;
	uint16_t RO_by_information_category;
	uint8_t  recipient;
	uint8_t  initiator;
	uint16_t receive_data_size;
	uint16_t concurrent_sequences;
	uint16_t open_sequences_per_exchange;
	uint16_t lun_abort_flags;
	uint16_t lun_stop_flags;
	uint16_t stop_queue_head;
	uint16_t stop_queue_tail;
	uint16_t port_retry_timer;
	uint16_t next_sequence_id;
	uint16_t frame_count;
	uint16_t PRLI_payload_length;
	uint16_t PRLI_service_parameter_word_0; /* Big endian */
						/* Bits 15-0 of word 0 */
	uint16_t PRLI_service_parameter_word_3; /* Big endian */
						/* Bits 15-0 of word 3 */
	uint16_t loop_id;
	uint16_t extended_lun_info_list_pointer;
	uint16_t extended_lun_stop_list_pointer;
} port_database_t;

/*
 * Firmware Dump structure definition
 */
#define	QLC_FW_DUMP_SIZE	0x68000		/* bytes */

typedef struct qlc_fw_dump {
	uint16_t pbiu_reg[8];
	uint16_t mailbox_reg[8];
	uint16_t dma_reg[48];
	uint16_t risc_hdw_reg[16];
	uint16_t risc_gp0_reg[16];
	uint16_t risc_gp1_reg[16];
	uint16_t risc_gp2_reg[16];
	uint16_t risc_gp3_reg[16];
	uint16_t risc_gp4_reg[16];
	uint16_t risc_gp5_reg[16];
	uint16_t risc_gp6_reg[16];
	uint16_t risc_gp7_reg[16];
	uint16_t frame_buf_hdw_reg[16];
	uint16_t fpm_b0_reg[64];
	uint16_t fpm_b1_reg[64];
	uint16_t risc_ram[0xf000];
} qlc_fw_dump_t;

/*
 * ISP Initialization Control Block.
 * Little endian except where noted.
 */
typedef struct qlc_init_cb {
	uint8_t  version;
#define	ICB_VERSION	1
	uint8_t  reserved;

	/*
	 * LSB BIT 0  = enable_hard_loop_id
	 * LSB BIT 1  = enable_fairness
	 * LSB BIT 2  = enable_full_duplex
	 * LSB BIT 3  = enable_fast_posting
	 * LSB BIT 4  = enable_target_mode
	 * LSB BIT 5  = disable_initiator_mode
	 * LSB BIT 6  = enable_adisc
	 * LSB BIT 7  = enable_target_inquiry_data
	 *
	 * MSB BIT 0  = enable_port_update_ae
	 * MSB BIT 1  = disable_initial_lip
	 * MSB BIT 2  = enable_decending_soft_assign
	 * MSB BIT 3  = previous_assigned_addressing
	 * MSB BIT 4  = enable_stop_q_on_full
	 * MSB BIT 5  = enable_full_login_on_lip
	 * MSB BIT 6  = enable_node_name
	 * MSB BIT 7  = extended_control_block
	 */
	uint8_t firmware_options[2];

	uint8_t max_frame_length[2];
	uint8_t max_iocb_allocation[2];
	uint8_t execution_throttle[2];
	uint8_t login_retry_count;
	uint8_t retry_delay;			/* unused */
	uint8_t port_name[8];			/* Big endian. */
	uint8_t hard_address[2];		/* option bit 0 */
	uint8_t inquiry;			/* option bit 7 */
	uint8_t login_timeout;
	uint8_t node_name[8];			/* Big endian, opt bit 14 */
	uint8_t request_q_outpointer[2];
	uint8_t response_q_inpointer[2];
	uint8_t request_q_length[2];
	uint8_t response_q_length[2];
	uint8_t request_q_address[8];
	uint8_t response_q_address[8];
	uint8_t lun_enables[2];
	uint8_t command_resouce_count;
	uint8_t immediate_notify_resouce_count;
	uint8_t timeout[2];
	uint8_t reserved_2[2];

	/*
	 * LSB BIT 0 = Timer operation mode bit 0
	 * LSB BIT 1 = Timer operation mode bit 1
	 * LSB BIT 2 = Timer operation mode bit 2
	 * LSB BIT 3 = Timer operation mode bit 3
	 * LSB BIT 4 = P2P Connection option bit 0
	 * LSB BIT 5 = P2P Connection option bit 1
	 * LSB BIT 6 = P2P Connection option bit 2
	 * LSB BIT 7 = Enable Non part on LIHA failure
	 *
	 * MSB BIT 0 = Enable class 2
	 * MSB BIT 1 = Enable ACK0
	 * MSB BIT 2 =
	 * MSB BIT 3 =
	 * MSB BIT 4 = FC Tape Enable
	 * MSB BIT 5 = Enable FC Confirm
	 * MSB BIT 6 = Enable CRN
	 * MSB BIT 7 =
	 */
	uint8_t  add_fw_opt[2];

	uint8_t  response_accumulation_timer;
	uint8_t  interrupt_delay_timer;

	/*
	 * LSB BIT 0 = Enable Read xfr_rdy
	 * LSB BIT 1 = not re-acquire ALPA during LIFA/LIPA
	 * LSB BIT 2 =
	 * LSB BIT 3 =
	 * LSB BIT 4 =
	 * LSB BIT 5 =
	 * LSB BIT 6 =
	 * LSB BIT 7 =
	 *
	 * MSB BIT 0 =
	 * MSB BIT 1 =
	 * MSB BIT 2 =
	 * MSB BIT 3 =
	 * MSB BIT 4 =
	 * MSB BIT 5 =
	 * MSB BIT 6 =
	 * MSB BIT 7 =
	 */
	uint8_t  special_options[2];

	uint8_t  reserved_3[26];
} qlc_init_cb_t;

/*
 * ISP IP Initialization Control Block.
 * Little endian except where noted.
 */
typedef struct qlc_ip_init_cb {
	uint8_t  version;
#define	IP_ICB_VERSION	1
	uint8_t  reserved;

	/*
	 * LSB BIT 0  = receive_buffer_address_length
	 * LSB BIT 1  = fast post broadcast received
	 * LSB BIT 2  = allow out of receive buffers AE
	 */
	uint8_t ip_firmware_options[2];
	uint8_t ip_header_size[2];
	uint8_t mtu_size[2];			/* max value is 65280 */
	uint8_t buf_size[2];
	uint8_t reserved_1[8];
	uint8_t queue_size[2];			/* 8-1024 */
	uint8_t low_water_mark[2];
	uint8_t queue_address[8];
	uint8_t queue_inpointer[2];
	uint8_t fast_post_reg_count[2];		/* 0-14 */
	uint8_t cc[2];
	uint8_t reserved_2[2];
} qlc_ip_init_cb_t;

/*
 * NVRAM Command values.
 */
#define	NV_START_BIT	BIT_2
#define	NV_WRITE_OP	(BIT_26+BIT_24)
#define	NV_READ_OP	(BIT_26+BIT_25)
#define	NV_ERASE_OP	(BIT_26+BIT_25+BIT_24)
#define	NV_MASK_OP	(BIT_26+BIT_25+BIT_24)
#define	NV_DELAY_COUNT	10

/*
 * ISP2200 NVRAM structure definition.
 * Little endian except where noted.
 */
typedef struct {

	/*
	 * NVRAM header
	 */
	uint8_t	 id[4];
	uint8_t	 nvram_version;
	uint8_t	 reserved_0;

	/*
	 * NVRAM RISC parameter block
	 */
	uint8_t	 parameter_block_version;
	uint8_t	 reserved_1;

	/*
	 * LSB BIT 0  = enable_hard_loop_id
	 * LSB BIT 1  = enable_fairness
	 * LSB BIT 2  = enable_full_duplex
	 * LSB BIT 3  = enable_fast_posting
	 * LSB BIT 4  = enable_target_mode
	 * LSB BIT 5  = disable_initiator_mode
	 * LSB BIT 6  = enable_adisc
	 * LSB BIT 7  = enable_target_inquiry_data
	 *
	 * MSB BIT 0  = enable_port_update_ae
	 * MSB BIT 1  = disable_initial_lip
	 * MSB BIT 2  = enable_decending_soft_assign
	 * MSB BIT 3  = previous_assigned_addressing
	 * MSB BIT 4  = enable_stop_q_on_full
	 * MSB BIT 5  = enable_full_login_on_lip
	 * MSB BIT 6  = enable_node_name
	 * MSB BIT 7  = extended_control_block
	 */
	uint8_t	 firmware_options[2];

	uint8_t	 max_frame_length[2];
	uint8_t	 max_iocb_allocation[2];
	uint8_t	 execution_throttle[2];
	uint8_t	 login_retry_count;
	uint8_t	 retry_delay;			/* unused */
	uint8_t	 port_name[8];			/* Big endian. */
	uint8_t	 hard_address[2];
	uint8_t	 inquiry;
	uint8_t	 login_timeout;
	uint8_t	 node_name[8];			/* Big endian. */

	/*
	 * LSB BIT 0 = Timer operation mode bit 0
	 * LSB BIT 1 = Timer operation mode bit 1
	 * LSB BIT 2 = Timer operation mode bit 2
	 * LSB BIT 3 = Timer operation mode bit 3
	 * LSB BIT 4 = P2P Connection option bit 0
	 * LSB BIT 5 = P2P Connection option bit 1
	 * LSB BIT 6 = P2P Connection option bit 2
	 * LSB BIT 7 = Enable Non part on LIHA failure
	 *
	 * MSB BIT 0 = Enable class 2
	 * MSB BIT 1 = Enable ACK0
	 * MSB BIT 2 =
	 * MSB BIT 3 =
	 * MSB BIT 4 = FC Tape Enable
	 * MSB BIT 5 = Enable FC Confirm
	 * MSB BIT 6 = Enable CRN
	 * MSB BIT 7 =
	 */
	uint8_t	 add_fw_opt[2];
	uint8_t	 response_accumulation_timer;
	uint8_t	 interrupt_delay_timer;

	/*
	 * LSB BIT 0 = Enable Read xfr_rdy
	 * LSB BIT 1 = not re-acquire ALPA during LIFA/LIPA
	 * LSB BIT 2 =
	 * LSB BIT 3 =
	 * LSB BIT 4 =
	 * LSB BIT 5 =
	 * LSB BIT 6 =
	 * LSB BIT 7 =
	 *
	 * MSB BIT 0 =
	 * MSB BIT 1 =
	 * MSB BIT 2 =
	 * MSB BIT 3 =
	 * MSB BIT 4 =
	 * MSB BIT 5 =
	 * MSB BIT 6 =
	 * MSB BIT 7 =
	 */
	uint8_t	 special_options[2];

	/* Reserved for expanded RISC parameter block */
	uint8_t reserved_4[26];

	/*
	 * NVRAM host parameter block
	 *
	 * LSB BIT 0 = unused
	 * LSB BIT 1 = disable_bios
	 * LSB BIT 2 = disable_luns
	 * LSB BIT 3 = enable_selectable_boot
	 * LSB BIT 4 = disable_risc_code_load
	 * LSB BIT 5 = set_cache_line_size_1
	 * LSB BIT 6 = pci_parity_disable
	 * LSB BIT 7 = enable_extended_logging
	 *
	 * MSB BIT 0 = enable_64bit_addressing
	 * MSB BIT 1 = enable_lip_reset
	 * MSB BIT 2 = enable_lip_full_login
	 * MSB BIT 3 = enable_target_reset
	 * MSB BIT 4 = enable_database_storage
	 * MSB BIT 5 = unused
	 * MSB BIT 6 = unused
	 * MSB BIT 7 = unused
	 */
	uint8_t	 host_p[2];

	uint8_t	 boot_node_name[8];
	uint8_t	 boot_lun_number;
	uint8_t	 reset_delay;
	uint8_t	 port_down_retry_count;
	uint8_t	 reserved_5;

	uint8_t  maximum_luns_per_target[2];

	uint8_t reserved_6[14];

	/* Offset 100 */
	uint8_t reserved_7[50];

	/* Offset 150 */
	uint8_t reserved_8[50];

	/* Offset 200 */
	uint8_t reserved_9[32];

	/*
	 * NVRAM Adapter Features offset 232-239
	 *
	 * LSB BIT 0 = External GBIC
	 * LSB BIT 1 = Risc RAM parity
	 * LSB BIT 2 = Buffer Plus Module
	 * LSB BIT 3 = Multi Chip Adapter
	 * LSB BIT 4 =
	 * LSB BIT 5 =
	 * LSB BIT 6 =
	 * LSB BIT 7 =
	 *
	 * MSB BIT 0 =
	 * MSB BIT 1 =
	 * MSB BIT 2 =
	 * MSB BIT 3 =
	 * MSB BIT 4 =
	 * MSB BIT 5 =
	 * MSB BIT 6 =
	 * MSB BIT 7 =
	 */
	uint8_t  adapter_features[2];
	uint8_t reserved_10[6];

	/*
	 * Resrved for use with ISP2300 - offset 240
	 */
	uint8_t reserved_11[4];

	/* Subsystem ID must be at offset 244 */
	uint8_t subsystem_vendor_id[2];

	uint8_t reserved_12[2];

	/* Subsystem device ID must be at offset 248 */
	uint8_t subsystem_device_id[2];

	/* Subsystem vendor ID for ISP2200 */
	uint8_t subsystem_vendor_id_2200[2];

	/* Subsystem device ID for ISP2200 */
	uint8_t subsystem_device_id_2200[2];

	uint8_t	 reserved_13;
	uint8_t	 checksum;
} nvram_t;

/*
 * ISP queue -	32-Bit DMA addressing command with extended LUN support
 *		entry structure definition.
 */
#define	MAX_CMDSZ   16			/* SCSI maximum CDB size. */
typedef struct cmd_entry {
	uint8_t  entry_type;		/* Entry type. */
#define	COMMAND_TYPE	0x11		/* Command entry */
	uint8_t  entry_count;		/* Entry count. */
	uint8_t  sys_define;		/* System defined. */
	uint8_t  entry_status;		/* Entry Status. */
	uint8_t  handle_l_l;		/* System handle - LSW-LSB */
	uint8_t  handle_l_h;		/* System handle - LSW-MSB */
	uint16_t handle_h;		/* System handle - MSW. */
	uint8_t  reserved;
	uint8_t  target;		/* SCSI ID */
	uint8_t  lun_l;			/* SCSI LUN - LSB */
	uint8_t  lun_h;			/* SCSI LUN - MSB */
	uint8_t  control_flags_l;	/* Control flags - LSB. */
#define	CF_HTAG		BIT_1
#define	CF_OTAG		BIT_2
#define	CF_STAG		BIT_3
#define	CF_DATA_IN	BIT_5
#define	CF_DATA_OUT	BIT_6
	uint8_t  control_flags_h;	/* Control flags - MSB. */
	uint8_t  reserved_1[2];
	uint8_t  timeout_l;		/* Command timeout - LSB. */
	uint8_t  timeout_h;		/* Command timeout - MSB. */
	uint8_t  dseg_count_l;		/* Data segment count - LSB. */
	uint8_t  dseg_count_h;		/* Data segment count - MSB. */
	uint8_t  scsi_cdb[MAX_CMDSZ];	/* SCSI command words. */
	uint32_t byte_count;		/* Total byte count. */
	uint32_t dseg_0_address;	/* Data segment 0 address. */
	uint32_t dseg_0_length;		/* Data segment 0 length. */
	uint32_t dseg_1_address;	/* Data segment 1 address. */
	uint32_t dseg_1_length;		/* Data segment 1 length. */
	uint32_t dseg_2_address;	/* Data segment 2 address. */
	uint32_t dseg_2_length;		/* Data segment 2 length. */
} cmd_entry_t, request_t;

/*
 * ISP queue -	64-Bit DMA addressing command with extended LUN support
 *		entry structure definition.
 */
typedef struct {
	uint8_t  entry_type;		/* Entry type. */
#define	COMMAND_A64_TYPE	0x19	/* Command A64 entry */
	uint8_t  entry_count;		/* Entry count. */
	uint8_t  sys_define;		/* System defined. */
	uint8_t  entry_status;		/* Entry Status. */
	uint8_t  handle_l_l;		/* System handle - LSW - LSB. */
	uint8_t  handle_l_h;		/* System handle - LSW - MSB. */
	uint16_t handle_h;		/* System handle - MSW. */
	uint8_t  reserved;
	uint8_t  target;		/* SCSI ID */
	uint8_t  lun_l;			/* SCSI LUN - LSB */
	uint8_t  lun_h;			/* SCSI LUN - MSB */
	uint8_t  control_flags_l;	/* Control flags - LSB. */
	uint8_t  control_flags_h;	/* Control flags - MSB. */
	uint8_t  reserved_1[2];
	uint8_t  timeout_l;		/* Command timeout - LSB. */
	uint8_t  timeout_h;		/* Command timeout - MSB. */
	uint8_t  dseg_count_l;		/* Data segment count - LSB. */
	uint8_t  dseg_count_h;		/* Data segment count - MSB. */
	uint8_t  scsi_cdb[MAX_CMDSZ];	/* SCSI command words. */
	uint32_t byte_count;		/* Total byte count. */
	uint32_t dseg_0_address[2];	/* Data segment 0 address. */
	uint32_t dseg_0_length;		/* Data segment 0 length. */
	uint32_t dseg_1_address[2];	/* Data segment 1 address. */
	uint32_t dseg_1_length;		/* Data segment 1 length. */
} cmd_a64_entry_t;

/*
 * ISP queue - status entry structure definition.
 */
typedef struct {
	uint8_t  entry_type;		/* Entry type. */
#define	STATUS_TYPE	0x03		/* Status entry. */
	uint8_t  entry_count;		/* Entry count. */
	uint8_t  sys_define;		/* System defined. */
	uint8_t  entry_status;		/* Entry Status. */
#define	RF_INV_E_ORDER	BIT_5		/* Invalid entry order. */
#define	RF_INV_E_COUNT  BIT_4		/* Invalid entry count. */
#define	RF_INV_E_PARAM  BIT_3		/* Invalid entry parameter. */
#define	RF_INV_E_TYPE   BIT_2		/* Invalid entry type. */
#define	RF_BUSY		BIT_1		/* Busy */
	uint32_t handle;		/* System handle. */
	uint8_t  scsi_status_l;		/* SCSI status - LSB. */
	uint8_t  scsi_status_h;		/* SCSI status - MSB. */
	uint8_t  comp_status;		/* Completion status. */
	uint8_t  unused_cs;		/* Completion status - MSB. */
	uint8_t  unused_sf;		/* State flags - LSB. */
	uint8_t  state_flags;		/* State flags. */
	uint8_t  status_flags;		/* Status flags. */
	uint8_t  unused_stf;		/* Status flags - MSB. */
	uint8_t  rsp_info_length_l;	/* Response Info Length. */
	uint8_t  rsp_info_length_h;	/* Response Info Length. */
	uint16_t req_sense_length;	/* Request sense data length. */
	uint32_t residual_length;	/* Residual transfer length. */
	uint8_t  rsp_info[8];		/* FCP response information. */
	uint8_t  req_sense_data[32];	/* Request sense data. */
} sts_entry_t, response_t;

/*
 * ISP queue - status continuation entry structure definition.
 */
typedef struct {
	uint8_t  entry_type;		/* Entry type. */
#define	STATUS_CONT_TYPE	0x10	/* Status continuation entry. */
	uint8_t  entry_count;		/* Entry count. */
	uint8_t  sys_define;		/* System defined. */
	uint8_t  entry_status;		/* Entry Status. */
	uint8_t  req_sense_data[60];	/* Request sense data. */
} sts_cont_entry_t;

/*
 * ISP queue -	marker with extended LUN support
 *		entry structure definition.
 */
typedef struct {
	uint8_t  entry_type;		/* Entry type. */
#define	MARKER_TYPE	0x04		/* Marker entry. */
	uint8_t  entry_count;		/* Entry count. */
	uint8_t  sys_define;		/* System defined. */
	uint8_t  entry_status;		/* Entry Status. */
	uint32_t sys_define_2;		/* System defined. */
	uint8_t  reserved;
	uint8_t  target;		/* SCSI ID */
	uint8_t  modifier;		/* Modifier (7-0). */
#define	MK_SYNC_ID_LUN	0		/* Synchronize ID/LUN */
#define	MK_SYNC_ID	1		/* Synchronize ID */
#define	MK_SYNC_ALL	2		/* Synchronize all ID/LUN */
#define	MK_SYNC_LIP	3		/* Synchronize all ID/LUN, */
					/* clear port changed, */
					/* use sequence number. */
	uint8_t  reserved_1;
	uint8_t  sequence_number[2];	/* Sequence number of event. */
	uint8_t  lun_l;			/* SCSI LUN - LSB */
	uint8_t  lun_h;			/* SCSI LUN - MSB */
	uint8_t  reserved_2[48];
} mrk_entry_t;

/*
 * ISP queue -	Enable LUN with extended LUN support
 *		entry structure definition.
 */
typedef struct {
	uint8_t  entry_type;		/* Entry type. */
#define	ENABLE_LUN_TYPE	0xB		/* Enable LUN entry */
	uint8_t  entry_count;		/* Entry count. */
	uint8_t  sys_define;		/* System defined. */
	uint8_t  entry_status;		/* Entry Status. */
	uint8_t  handle_l_l;		/* System handle - LSW - LSB. */
	uint8_t  handle_l_h;		/* System handle - LSW - MSB. */
	uint16_t handle_h;		/* System handle - MSW. */
	uint8_t  reserved[8];
	uint8_t  status;
	uint8_t  reserved_1;
	uint8_t  command_count;
	uint8_t  immediate_notify_count;
	uint8_t  reserved_2[2];
	uint8_t  timeout_l;		/* Timeout - LSB. */
	uint8_t  timeout_h;		/* Timeout - MSB. */
	uint8_t  reserved_3[40];
} enable_lun_entry_t;

/*
 * ISP queue -	Modify LUN with extended LUN support
 *		entry structure definition.
 */
typedef struct {
	uint8_t  entry_type;		/* Entry type. */
#define	MODIFY_LUN_TYPE	0xC		/* Modify LUN entry */
	uint8_t  entry_count;		/* Entry count. */
	uint8_t  sys_define;		/* System defined. */
	uint8_t  entry_status;		/* Entry Status. */
	uint8_t  handle_l_l;		/* System handle - LSW - LSB. */
	uint8_t  handle_l_h;		/* System handle - LSW - MSB. */
	uint16_t handle_h;		/* System handle - MSW. */
	uint8_t  reserved[2];
	uint8_t  operators;
	uint8_t  reserved_1[5];
	uint8_t  status;
	uint8_t  reserved_2;
	uint8_t  command_count;
	uint8_t  immediate_notify_count;
	uint8_t  reserved_3[2];
	uint8_t  timeout_l;		/* Timeout - LSB. */
	uint8_t  timeout_h;		/* Timeout - MSB. */
	uint8_t  reserved_4[40];
} modify_lun_entry_t;

/*
 * ISP queue -	Immediate Notify with extended LUN support
 *		entry structure definition.
 */
typedef struct {
	uint8_t  entry_type;		/* Entry type. */
#define	IMMEDIATE_NOTIFY_TYPE	0xD	/* Immediate notify entry */
	uint8_t  entry_count;		/* Entry count. */
	uint8_t  sys_define;		/* System defined. */
	uint8_t  entry_status;		/* Entry Status. */
	uint8_t  handle_l_l;		/* System handle - LSW - LSB. */
	uint8_t  handle_l_h;		/* System handle - LSW - MSB. */
	uint16_t handle_h;		/* System handle - MSW. */
	uint8_t  reserved;
	uint8_t  initiator_id;
	uint8_t  lun_l;
	uint8_t  lun_h;
	uint8_t  reserved_1[4];
	uint8_t  status_l;
	uint8_t  status_h;
	uint8_t  task_flags_l;
	uint8_t  task_flags_h;
	uint16_t sequence_id;
	uint8_t  reserved_3[40];
	uint16_t ox_id;
} immediate_notify_entry_t;

/*
 * ISP queue -	Notify Acknowledge extended LUN support
 *		entry structure definition.
 */
typedef struct {
	uint8_t  entry_type;		/* Entry type. */
#define	NOTIFY_ACKNOWLEDGE_TYPE	0xE	/* Immediate notify entry */
	uint8_t  entry_count;		/* Entry count. */
	uint8_t  sys_define;		/* System defined. */
	uint8_t  entry_status;		/* Entry Status. */
	uint8_t  handle_l_l;		/* System handle - LSW - LSB. */
	uint8_t  handle_l_h;		/* System handle - LSW - MSB. */
	uint16_t handle_h;		/* System handle - MSW. */
	uint8_t  reserved;
	uint8_t  initiator_id;
	uint8_t  reserved_1[2];
	uint8_t  flags_l;
	uint8_t  flags_h;
	uint8_t  reserved_2[2];
	uint8_t  status_l;
	uint8_t  status_h;
	uint8_t  task_flags_l;
	uint8_t  task_flags_h;
	uint16_t sequence_id;
	uint8_t  reserved_3[42];
} notify_acknowledge_entry_t;

/*
 * ISP queue -	Accept Target I/O with extended LUN support
 *		entry structure definition.
 */
typedef struct {
	uint8_t  entry_type;		/* Entry type. */
#define	ATIO_TYPE	0x16		/* ATIO entry */
	uint8_t  entry_count;		/* Entry count. */
	uint8_t  sys_define;		/* System defined. */
	uint8_t  entry_status;		/* Entry Status. */
	uint8_t  handle_l_l;		/* System handle - LSW - LSB. */
	uint8_t  handle_l_h;		/* System handle - LSW - MSB. */
	uint16_t handle_h;		/* System handle - MSW. */
	uint8_t  reserved;
	uint8_t  initiator_id;
	uint16_t rx_id;
	uint8_t  flags_l;
	uint8_t  flags_h;
	uint8_t  status_l;
	uint8_t  status_h;
	uint8_t  reserved_1;
	uint8_t  task_codes : 3,
	    reserved_2 : 5;
	uint8_t  task_flags;
	uint8_t  execution_codes;
	uint8_t  cdb[MAX_CMDSZ];
	uint32_t data_length;
	uint8_t  lun_l;
	uint8_t  lun_h;
	uint8_t  reserved_3[20];
	uint16_t ox_id;
} atio_entry_t;

/*
 * ISP queue -	Continue Target I/O with extended LUN support
 *		entry structure definition.
 */
typedef struct {
	uint8_t  entry_type;		/* Entry type. */
#define	CTIO_TYPE_2   0x17
#define	CTIO_TYPE_3   0x1F
	uint8_t  entry_count;		/* Entry count. */
	uint8_t  sys_define;		/* System defined. */
	uint8_t  entry_status;		/* Entry Status. */
	uint8_t  handle_l_l;		/* System handle - LSW - LSB. */
	uint8_t  handle_l_h;		/* System handle - LSW - MSB. */
	uint16_t handle_h;		/* System handle - MSW. */
	uint8_t  reserved;
	uint8_t  initiator_id;
	uint16_t rx_id;
	uint8_t  flags_l;
	uint8_t  flags_h;
	uint8_t  status_l;
	uint8_t  status_h;
	uint8_t  timeout_l;
	uint8_t  timeout_h;
	uint8_t  dseg_count_l;
	uint8_t  dseg_count_h;
	uint32_t relative_offset;
	uint32_t residual_transfer_length;
	uint8_t  reserved_1[4];

	union {
		struct {
			uint8_t  reserved_2[2];
			uint8_t  scsi_status_l;
			uint8_t  scsi_status_h;
			uint32_t byte_count;
			uint32_t dseg_0_address;
			uint32_t dseg_0_length;
			uint32_t dseg_1_address;
			uint32_t dseg_1_length;
			uint32_t dseg_2_address;
			uint32_t dseg_2_length;
		}s0_32bit;

		struct {
			uint8_t  reserved_3[2];
			uint8_t  scsi_status_l;
			uint8_t  scsi_status_h;
			uint32_t byte_count;
			uint64_t dseg_0_address;
			uint32_t dseg_0_length;
			uint64_t dseg_1_address;
			uint32_t dseg_1_length;
		}s0_64bit;

		struct {
			uint8_t  sense_length_l;
			uint8_t  sense_length_h;
			uint8_t  scsi_status_l;
			uint8_t  scsi_status_h;
			uint8_t  response_length_l;
			uint8_t  response_length_h;
			uint8_t  response_info[26];
		}s1;

		struct {
			uint8_t  reserved_4[2];
			uint32_t response_length;
			uint32_t response_pointer;
			uint8_t  reserved[16];
		}s2;
	}type;
} ctio_entry_t;

/*
 * ISP queue -	32-Bit DMA addressing IP entry structure definition.
 */
typedef struct {
	uint8_t  entry_type;		/* Entry type. */
#define	IP_TYPE	0x13			/* IP entry */
	uint8_t  entry_count;		/* Entry count. */
	uint8_t  sys_define;		/* System defined. */
	uint8_t  entry_status;		/* Entry Status. */
	uint8_t  handle_l_l;		/* System handle - LSW - LSB. */
	uint8_t  handle_l_h;		/* System handle - LSW - MSB. */
	uint16_t handle_h;		/* System handle - MSW. */
	uint8_t  reserved;
	uint8_t  loop_id;		/* Loop ID */
	uint8_t  comp_status;		/* Completion status. */
	uint8_t  unused_cs;		/* Completion status - MSB. */
	uint8_t  control_flags_l;	/* Control flags - LSB. */
	uint8_t  control_flags_h;	/* Control flags - MSB. */
	uint8_t  reserved_1[2];
	uint8_t  timeout_l;		/* Command timeout - LSB. */
	uint8_t  timeout_h;		/* Command timeout - MSB. */
	uint8_t  dseg_count_l;		/* Data segment count - LSB. */
	uint8_t  dseg_count_h;		/* Data segment count - MSB. */
	uint8_t  reserved_2[16];
	uint32_t byte_count;		/* Total byte count. */
	uint32_t dseg_0_address;	/* Data segment 0 address. */
	uint32_t dseg_0_length;		/* Data segment 0 length. */
	uint32_t dseg_1_address;	/* Data segment 1 address. */
	uint32_t dseg_1_length;		/* Data segment 1 length. */
	uint32_t dseg_2_address;	/* Data segment 2 address. */
	uint32_t dseg_2_length;		/* Data segment 2 length. */
} ip_entry_t;

/*
 * ISP queue -	64-Bit DMA addressing IP entry structure definition.
 */
typedef struct {
	uint8_t  entry_type;		/* Entry type. */
#define	IP_A64_TYPE	0x1B		/* IP entry */
	uint8_t  entry_count;		/* Entry count. */
	uint8_t  sys_define;		/* System defined. */
	uint8_t  entry_status;		/* Entry Status. */
	uint8_t  handle_l_l;		/* System handle - LSW - LSB. */
	uint8_t  handle_l_h;		/* System handle - LSW - MSB. */
	uint16_t handle_h;		/* System handle - MSW. */
	uint8_t  reserved;
	uint8_t  loop_id;		/* Loop ID */
	uint8_t  comp_status;		/* Completion status. */
	uint8_t  unused_cs;		/* Completion status - MSB. */
	uint8_t  control_flags_l;	/* Control flags - LSB. */
	uint8_t  control_flags_h;	/* Control flags - MSB. */
	uint8_t  reserved_1[2];
	uint8_t  timeout_l;		/* Command timeout - LSB. */
	uint8_t  timeout_h;		/* Command timeout - MSB. */
	uint8_t  dseg_count_l;		/* Data segment count - LSB. */
	uint8_t  dseg_count_h;		/* Data segment count - MSB. */
	uint8_t  reserved_2[16];
	uint32_t byte_count;		/* Total byte count. */
	uint32_t dseg_0_address[2];	/* Data segment 0 address. */
	uint32_t dseg_0_length;		/* Data segment 0 length. */
	uint32_t dseg_1_address[2];	/* Data segment 1 address. */
	uint32_t dseg_1_length;		/* Data segment 1 length. */
} ip_a64_entry_t;

/*
 * ISP queue - Receive IP buffer entry structure definition.
 */
#define	IP_RCVBUF_HANDLES	24	/* Buffer handles in entry. */
typedef struct {
	uint8_t  entry_type;		/* Entry type. */
#define	IP_RECEIVE_TYPE	0x23		/* IP receive entry */
	uint8_t  entry_count;		/* Entry count. */
	uint8_t  segment_count;		/* Segment count. */
	uint8_t  entry_status;		/* Entry Status. */
	uint8_t  s_id[3];		/* Source ID. */
	uint8_t  reserved[2];
	uint8_t  loop_id;		/* Loop ID */
	uint8_t  comp_status_l;		/* Completion status - LSB. */
	uint8_t  comp_status_h;		/* Completion status - MSB. */
	uint8_t  class_of_srv_l;	/* Class of service - LSB. */
	uint8_t  class_of_srv_h;	/* Class of service - MSB. */
	uint8_t  seg_length_l;		/* Sequence length - LSB. */
	uint8_t  seg_length_h;		/* Sequence length - MSB. */
	uint8_t  buffer_handle[IP_RCVBUF_HANDLES][2]; /* Buffer handles. */
} ip_rcv_entry_t;

/*
 * ISP queue - Receive IP buffer continuation entry structure definition.
 */
#define	IP_RCVBUF_CONT_HANDLES	30	/* Buffer handles in entry. */
typedef struct {
	uint8_t  entry_type;		/* Entry type. */
#define	IP_RECEIVE_CONT_TYPE	0x2B	/* IP receive continuation entry */
	uint8_t  entry_count;		/* Entry count. */
	uint8_t  reserved;
	uint8_t  entry_status;		/* Entry Status. */
	uint8_t  buffer_handle[IP_RCVBUF_CONT_HANDLES][2]; /* Buf handles */
} ip_rcv_cont_entry_t;

/*
 * ISP status entry - completion status definitions.
 */
#define	CS_COMPLETE		0x0	/* No errors */
#define	CS_DMA_ERROR		0x2	/* A DMA direction error. */
#define	CS_RESET		0x4	/* SCSI bus reset occurred */
#define	CS_ABORTED		0x5	/* System aborted command. */
#define	CS_TIMEOUT		0x6	/* Timeout error. */
#define	CS_DATA_OVERRUN		0x7	/* Data overrun. */
#define	CS_DATA_UNDERRUN	0x15	/* Data Underrun. */
#define	CS_QUEUE_FULL		0x1C	/* Queue Full. */
#define	CS_PORT_UNAVAILABLE	0x28	/* Port unavailable */
					/* (selection timeout) */
#define	CS_PORT_LOGGED_OUT	0x29	/* Port Logged Out */
#define	CS_PORT_CONFIG_CHG	0x2A	/* Port Configuration Changed */
#define	CS_PORT_BUSY		0x2B	/* Port Busy */

#define	CS_BAD_PAYLOAD		0x80	/* Driver defined */
#define	CS_UNKNOWN		0x81	/* Driver defined */
#define	CS_CMD_FAILED		0x82	/* Driver defined - Command failed. */

/*
 * ISP status entry - Upper status byte bit definitions.
 */
#define	SS_RESIDUAL_UNDER		BIT_3
#define	SS_RESIDUAL_OVER		BIT_2
#define	SS_SENSE_LEN_VALID		BIT_1
#define	SS_FCP_RSP_INFO_LEN_VALID	BIT_0

/*
 * ISP status entry - SCSI status byte bit definitions.
 */
#define	SS_RESERVE_CONFLICT	(BIT_4 | BIT_3)
#define	SS_BUSY_CONDITION	BIT_3
#define	SS_CONDITION_MET	BIT_2
#define	SS_CHECK_CONDITION	BIT_1

/*
 * LFA command structure.
 */
#define	LFA_PAYLOAD_SIZE	38
typedef struct {
	uint8_t	 resp_buffer_length[2];		/* length in 16bit words. */
	uint8_t	 reserved[2];
	uint8_t	 resp_buffer_address[8];
	uint8_t	 subcommand_length[2];		/* length in 16bit words. */
	uint8_t	 reserved_1[2];
	uint8_t	 addr[4];
	uint8_t  subcommand[2];
	uint8_t	 payload[LFA_PAYLOAD_SIZE];
} lfa_cmd_t;

/*
 * SNS command structure.
 */
#define	SNS_PAYLOAD_SIZE	64
typedef struct {
	uint8_t	 resp_buffer_length[2];		/* length in 16bit words. */
	uint8_t	 reserved[2];
	uint8_t	 resp_buffer_address[8];
	uint8_t	 subcommand_length[2];		/* length in 16bit words. */
	uint8_t	 reserved_1[2];
	uint16_t subcommand;
	uint8_t	 reserved_2[2];
	uint8_t	 reserved_3[4];
	uint32_t payload[SNS_PAYLOAD_SIZE / 4];
} sns_cmd_t;

/*
 * ISP receive buffer container structure definition.
 */
typedef struct {
	uint32_t bufp[2];		/* Buffer pointer. */
	uint8_t  handle_l;		/* Buffer handle - LSB. */
	uint8_t  handle_h;		/* Buffer handle - MSB. */
	uint8_t  reserved[2];
} rcvbuf_t;

/*
 * 24 bit port ID type definition.
 */
typedef union {
	struct {
		uint8_t d_id[3];
		uint8_t rsvd_1;
	}r;
#if defined(_BIT_FIELDS_LTOH)
	uint32_t	b24  : 24,
			rsvd : 8;
	struct {
		uint8_t al_pa;
		uint8_t domain_l;
		uint8_t domain_h;
		uint8_t rsvd_1;
	}b;
#else
	uint32_t	rsvd : 8,
			b24  : 24;
	struct {
		uint8_t domain_h;
		uint8_t domain_l;
		uint8_t al_pa;
		uint8_t rsvd_1;
	}b;
#endif
} port_id_t;

/*
 * Link list definitions.
 */
typedef struct qlc_link {
	struct qlc_link *prev;
	struct qlc_link *next;
	void   *base_address;
} qlc_link_t;

typedef struct qlc_head {
	qlc_link_t  *first;
	qlc_link_t  *last;
} qlc_head_t;

/*
 * This is the driver target command structure
 */
typedef struct {
	/* Command link. */
	qlc_link_t cmd;

	struct qlc_device *devq;
	uint8_t	 type;
	uint8_t	 initiator_id;
	uint16_t rx_id;

	uint8_t	 status_l;
	uint8_t	 status_h;
	uint8_t	 task_flags_l;
	uint8_t	 task_flags_h;
	uint8_t	 execution_codes;

	uint8_t  busy;
	uint8_t  free;
	uint_t	state;
} tgt_cmd_t;

/* Target cmd states */
#define	TGT_CMD_RECEIVED	0x00
#define	TGT_CMD_SENT_UP		0x01
#define	TGT_CMD_IN_FW		0x02

/*
 * This is the per-command structure
 */
typedef struct qlc_srb {
	/* Command link. */
	qlc_link_t		cmd;

	/* Watchdog link and timer. */
	qlc_link_t		wdg;
	time_t			wdg_q_time;

	/* FCA and FC Transport data. */
	fc_packet_t			*pkt;
	struct qlc_adapter_state	*ha;
	uint32_t			magic_number;

	/* unsolicited buffer context. */
	ddi_dma_handle_t	buffer_dma_handle;
	ddi_acc_handle_t	buffer_acc_handle;
	ddi_dma_cookie_t	buffer_dma_cookie;
	uint32_t		ub_type;
	uint32_t		ub_size;
	uint32_t		ub_bytecount;

	/* FCP command. */
	fcp_cmd_t		*fcp;

	/* Request sense. */
	uint32_t		request_sense_length;
	caddr_t			request_sense_ptr;

	/* Device queue pointer. */
	struct qlc_device	*device_queue;

	/* Target command pointer. */
	tgt_cmd_t		*tgt_cmd;

	/* Command state/status flags. */
	volatile uint32_t	flags;
#define	SRB_ISP_STARTED		  BIT_0   /* Command sent to ISP. */
#define	SRB_ISP_COMPLETED	  BIT_1   /* ISP finished with command. */
#define	SRB_RETRY		  BIT_2   /* Driver retrying command. */
#define	SRB_POLL		  BIT_3   /* Poll for completion. */
#define	SRB_WATCHDOG_ENABLED	  BIT_4   /* Command on watchdog list. */
#define	SRB_ABORT		  BIT_5   /* SRB to be aborted. */
#define	SRB_UB_IN_FCA		  BIT_6   /* FCA holds unsolicited buffer */
#define	SRB_UB_IN_ISP		  BIT_7   /* ISP holds unsolicited buffer */
#define	SRB_UB_CALLBACK		  BIT_8   /* Unsolicited callback needed. */
#define	SRB_UB_RSCN		  BIT_9   /* Unsolicited RSCN callback. */
#define	SRB_UB_FCP		  BIT_10  /* Unsolicited RSCN callback. */
#define	SRB_FCP_CMD_PKT		  BIT_11  /* FCP command type packet. */
#define	SRB_FCP_DATA_PKT	  BIT_12  /* FCP data type packet. */
#define	SRB_FCP_RSP_PKT		  BIT_13  /* FCP response type packet. */
#define	SRB_IP_PKT		  BIT_14  /* IP type packet. */
#define	SRB_GENERIC_SERVICES_PKT  BIT_15  /* Generic services type packet */
#define	SRB_COMMAND_TIMEOUT	  BIT_16  /* Command timed out. */
#define	SRB_ABORTING		  BIT_17  /* SRB aborting. */
#define	SRB_IN_DEVICE_QUEUE	  BIT_18  /* In Device Queue */
#define	SRB_IN_TOKEN_ARRAY	  BIT_19  /* In Token Array */
#define	SRB_UB_FREE_REQUESTED	  BIT_20  /* UB Free requested */
#define	SRB_UB_ACQUIRED		  BIT_21  /* UB selected for upcall */

	/* Command array index. */
	uint16_t		array_index;
} qlc_srb_t;

/*
 * Fibre Channel Device Queue structure
 */
typedef struct qlc_device {
	/* Device queue lock. */
	kmutex_t  mutex;

	/* Head command link. */
	qlc_head_t	  cmd;

	/* Head target command link. */
	qlc_head_t	  tgt_cmd;

	volatile uint8_t flags;
	port_id_t d_id;
	uint16_t  loop_id;
	volatile uint16_t outcnt; 	/* Number of commands running in ISP. */

	/* Device link. */
	qlc_link_t	  device;

	/* Head watchdog link. */
	qlc_head_t	  wdg;

	/* Device state/status flags. */
	uint8_t	  master_state;
	uint8_t	  slave_state;
#define	SD_BUSY			BIT_0  /* reached hi-water mark */
#define	SD_QUEUE_SUSPENDED	BIT_1  /* Queue suspended. */
#define	SD_FABRIC_DEVICE	BIT_2
#define	SD_INITIATOR_DEVICE	BIT_3

	/* Port down retry counter. */
	uint8_t	  port_down_retry_count;

	/* logout sent state */
	uint8_t   logout_sent;

	/* LUN execution throttle. */
	uint16_t  lun_outcnt[MAX_LUNS];

	/* Data from Port database matches machine type. */
	port_id_t hard_addr;
	uint8_t	  port_name[8];
	uint8_t	  node_name[8];
	uint16_t  cmn_features;
	uint16_t  conc_sequences;
	uint16_t  relative_offset;
	uint16_t  class3_recipient_ctl;
	uint16_t  class3_rcv_data_size;
	uint16_t  class3_conc_sequences;
	uint16_t  class3_open_sequences_per_exch;
	uint16_t  prli_payload_length;
	uint16_t  prli_svc_param_word_0;
	uint16_t  prli_svc_param_word_3;
} qlc_dev_t;

/*
 * Kernel statistic structure definitions.
 */
typedef struct qlc_device_stat {
	int logouts_recvd;
	int task_mgmt_failures;
	int data_ro_mismatches;
	int dl_len_mismatches;
} qlc_device_stat_t;

typedef struct qlc_adapter_revlvl {
	uint16_t isp2200;			/* 2200 chip rev level */
	uint16_t risc;				/* risc rev level */
	uint16_t frmbfr;			/* frame buffer rev level */
	uint16_t riscrom;			/* risc rom rev level */
	char qlcddv[16];			/* qlc driver version string */
} qlc_adapter_revlvl_t;

typedef struct qlc_adapter_stat {
	int version;			/* version of this struct */
	int lip_count;			/* lips forced  */
	int ncmds;			/* outstanding commands */
	qlc_adapter_revlvl_t revlvl;	/* adapter revision levels */
	qlc_device_stat_t d_stats[MAX_FIBRE_DEVICES]; /* per device stats */
} qlc_adapter_stat_t;

/*
 * ISP request, response and receive buffer queue sizes
 */
#define	REQUEST_ENTRY_SIZE	(sizeof (request_t))
#define	REQUEST_QUEUE_SIZE	(REQUEST_ENTRY_SIZE * REQUEST_ENTRY_CNT)
#define	RESPONSE_ENTRY_SIZE	(sizeof (response_t))
#define	RESPONSE_QUEUE_SIZE	(RESPONSE_ENTRY_SIZE * RESPONSE_ENTRY_CNT)
#define	RCVBUF_CONTAINER_SIZE	(sizeof (rcvbuf_t))
#define	RCVBUF_QUEUE_SIZE	(RCVBUF_CONTAINER_SIZE * RCVBUF_CONTAINER_CNT)

/*
 * ISP DMA buffer definitions
 */
#define	REQUEST_Q_BUFFER_OFFSET  0

#define	RESPONSE_Q_BUFFER_OFFSET (REQUEST_Q_BUFFER_OFFSET + REQUEST_QUEUE_SIZE)

#define	RCVBUF_Q_BUFFER_OFFSET  (RESPONSE_Q_BUFFER_OFFSET + \
    RESPONSE_QUEUE_SIZE)

#define	MAILBOX_BUFFER_OFFSET	(RCVBUF_Q_BUFFER_OFFSET + RCVBUF_QUEUE_SIZE)

#define	ISP_TOTAL_BUFFER_SIZE	(REQUEST_QUEUE_SIZE + RESPONSE_QUEUE_SIZE + \
    RCVBUF_QUEUE_SIZE + MAILBOX_BUFFER_SIZE)

/* Device queue head list size (based on AL_PA address). */
#define	DEVICE_HEAD_LIST_SIZE	0x81

/*
 * adapter state flags
 */
#define	FCA_BOUND			BIT_0
#define	QLC_OPENED			BIT_1
#define	ONLINE				BIT_2
#define	INTERRUPTS_ENABLED		BIT_3
#define	ENABLE_64BIT_ADDRESSING		BIT_4
#define	ENABLE_LIP_RESET		BIT_5
#define	ENABLE_LIP_FULL_LOGIN		BIT_6
#define	ENABLE_TARGET_RESET		BIT_7
#define	DISABLE_RISC_CODE_LOAD		BIT_8
#define	SET_CACHE_LINE_SIZE_1		BIT_9
#define	POINT_TO_POINT			BIT_10
#define	IP_ENABLED			BIT_11
#define	IP_INITIALIZED			BIT_12
#define	LINK_DOWN_ERROR_DISABLE		BIT_13
#define	TARGET_MODE_ENABLE		BIT_14
#define	TARGET_MODE_INITIALIZED		BIT_15
#define	FC_TAPE_ENABLE			BIT_16
#define	QLC_MULTI_CHIP_ADAPTER		BIT_17
#define	ADAPTER_SUSPENDED		BIT_18
#define	ADAPTER_TIMER_BUSY		BIT_19

/*
 * task daemon flags
 */
#define	TASK_DAEMON_STOP_FLG		BIT_0
#define	TASK_DAEMON_SLEEPING_FLG	BIT_1
#define	TASK_DAEMON_ALIVE_FLG		BIT_2
#define	TASK_DAEMON_IDLE_CHK_FLG	BIT_3
#define	SUSPENDED_WAKEUP_FLG		BIT_4
#define	FC_STATE_CHANGE			BIT_5
#define	NEED_UNSOLICITED_BUFFERS	BIT_6
#define	RESET_MARKER_NEEDED		BIT_7
#define	RESET_ACTIVE			BIT_8
#define	ISP_ABORT_NEEDED		BIT_9
#define	ABORT_ISP_ACTIVE		BIT_10
#define	LOOP_RESYNC_NEEDED		BIT_11
#define	LOOP_RESYNC_ACTIVE		BIT_12
#define	LOOP_DOWN			BIT_13
#define	DRIVER_STALL			BIT_14
#define	COMMAND_WAIT_NEEDED		BIT_15
#define	COMMAND_WAIT_ACTIVE		BIT_16
#define	STATE_ONLINE			BIT_17
#define	ABORT_QUEUES_NEEDED		BIT_18
#define	ABORT_QUEUES_ACTIVE		BIT_19
#define	TASK_THREAD_CALLED		BIT_20
#define	FIRMWARE_UP			BIT_21
#define	LIP_RESET_PENDING		BIT_22
#define	FIRMWARE_LOADED			BIT_23

/*
 * Mailbox flags
 */
#define	MBX_WANT_FLG			BIT_0
#define	MBX_BUSY_FLG			BIT_1
#define	MBX_INTERRUPT			BIT_2

/*
 * Interrupt status
 */
#define	SPURIOUS_INTERRUPT	BIT_0
#define	MBX_CMD_INTERRUPT	BIT_1

#define	QLC_LOOP_TRANSITION	(RESET_MARKER_NEEDED | RESET_ACTIVE | \
				ISP_ABORT_NEEDED | ABORT_ISP_ACTIVE | \
				LOOP_RESYNC_NEEDED | LOOP_RESYNC_ACTIVE | \
				COMMAND_WAIT_NEEDED | COMMAND_WAIT_ACTIVE)

#define	QLC_SUSPENDED		(QLC_LOOP_TRANSITION | LOOP_DOWN | DRIVER_STALL)

#define	QLC_TASK_PENDING(ha)	( \
    ha->task_daemon_flags & (QLC_LOOP_TRANSITION | ABORT_QUEUES_NEEDED) || \
    ha->callback_queue.first != NULL)

#define	QLC_DAEMON_NOT_ACTIVE(ha)	( \
	!(ha->task_daemon_flags & TASK_DAEMON_ALIVE_FLG) || \
	ha->task_daemon_flags & (TASK_DAEMON_SLEEPING_FLG | \
	TASK_DAEMON_STOP_FLG))

#define	QLC_DAEMON_SUSPENDED(ha)	(\
	(((ha)->cprinfo.cc_events & CALLB_CPR_START) ||\
	((ha)->flags & ADAPTER_SUSPENDED)))

/*
 * Device state structure.
 */
typedef struct qlc_adapter_state {
	kmutex_t		mutex;
	volatile uint32_t	flags; 			/* State flags. */
	uint32_t		state;
	port_id_t		d_id;
	uint16_t		loop_id;
	uint8_t			topology;

	uint16_t		minimum_timeout;
	uint16_t		idle_timer;
	uint8_t			loop_down_abort_time;
	uint8_t			queue_restart_timer;
	uint8_t			loop_down_timer;
	uint8_t			watchdog_timer;

	kmutex_t		task_daemon_mutex;
	kcondvar_t		cv_dr_suspended;
	kcondvar_t		cv_task_daemon;
	volatile uint32_t	task_daemon_flags;
	qlc_head_t		callback_queue;

	kmutex_t		intr_mutex;
	device_reg_t		*iobase;
	qlc_srb_t		*status_srb;
	volatile uint8_t	intr_claimed;

	/* Mailbox context. */
	kmutex_t		mbx_mutex;
	caddr_t			mbx_buffer;
	mbx_cmd_t		*mcp;
	uint32_t		mbx_dvma;
	kcondvar_t		cv_mbx_wait;
	kcondvar_t		cv_mbx_intr;
	volatile uint8_t	mailbox_flags;

	/* ISP request queue context. */
	kmutex_t		req_ring_mutex;
	uint16_t		req_ring_index;
	uint16_t		req_q_cnt;	/* # of available entries. */
	uint16_t		osc_index;
	request_t		*request_ring_ptr;
	request_t		*request_ring;
	uint32_t		request_dvma;

	/* ISP response queue context. */
	uint32_t		response_dvma;
	response_t		*response_ring;
	response_t		*response_ring_ptr;
	uint16_t		rsp_ring_index;

	rcvbuf_t		*rcvbuf_ring;
	rcvbuf_t		*rcvbuf_ring_ptr;
	uint16_t		rcvbuf_ring_index;

	/* Unsolicited buffer data. */
	uint8_t			ub_total_seg_cnt;
	uint8_t			ub_s_id[3];
	uint8_t			ub_seq_id;
	uint16_t		ub_outcnt;
	uint8_t			ub_seq_cnt;
	uint8_t			ub_command_count;
	uint8_t			ub_notify_count;
	uint32_t		ub_allocated;

	/* Head of device queue list. */
	qlc_head_t		*dev;
	qlc_srb_t		**outstanding_cmds;

	kmutex_t		ub_mutex;
	kcondvar_t		cv_ub;
	fc_unsol_buf_t		**ub_array;

	qlc_link_t		hba;

	/* Kernel statistics. */
	kstat_t			*k_stats;
	qlc_adapter_stat_t	*adapter_stats;

	/* Solaris adapter configuration data */
	ddi_acc_handle_t	dev_handle;
	ddi_acc_handle_t	pci_handle;	/* config space */

	dev_info_t		*dip;
	ddi_iblock_cookie_t	iblock_cookie;
	fc_fca_tran_t		*tran;
	caddr_t			risc_code;
	int			instance;
	uint32_t		risc_code_size;
	la_els_logi_t		loginparams;
	fc_fca_bind_info_t	bind_info;
	uint16_t		fw_major_version;
	uint16_t		fw_minor_version;
	uint16_t		fw_subminor_version;

	tgt_cmd_t		*nack_cmd;

	/* NVRAM configuration data */
	qlc_init_cb_t		init_ctrl_blk;
	qlc_ip_init_cb_t	ip_init_ctrl_blk;
	uint32_t		fw_transfer_size;
	uint16_t		cmd_high_water;
	uint16_t		execution_throttle;
	uint8_t			loop_reset_delay;
	uint8_t			port_down_retry_count;

	/* ISP DMA buffer (request queue, response queue, mailbox buffer). */
	ddi_dma_handle_t	buffer_dma_handle;
	ddi_acc_handle_t	buffer_acc_handle;
	ddi_dma_cookie_t	buffer_dma_cookie;
	caddr_t			dma_buffer;
	uint32_t		rcvbuf_dvma;

	/* Power management context. */
	kmutex_t		pm_mutex;
	uint32_t		busy;
	uint8_t			power_level;
	uint8_t			pm_capable;
	uint8_t			config_saved;
	uint8_t			lip_on_panic;

	uint32_t		port_knobs;
	uint32_t 		port_hard_address : 24,
				rsvd : 8;
	uint8_t			knobs_adjusted;

	callb_cpr_t		cprinfo;
} qlc_adapter_state_t;

/*
 * Macros to help code, maintain, etc.
 */
#define	LSB(x)		  (uint8_t)(x)
#define	MSB(x)		  (uint8_t)((uint16_t)(x) >> 8)

#define	MSW(x)		  (uint16_t)((uint32_t)(x) >> 16)
#define	LSW(x)		  (uint16_t)(x)

#define	MSW_LSB(x)	  (uint8_t)(LSB(MSW(x)))
#define	MSW_MSB(x)	  (uint8_t)(MSB(MSW(x)))

#define	SHORT_TO_LONG(a, b) (uint32_t)((uint16_t)b << 16 | (uint16_t)a)
#define	CHAR_TO_SHORT(a, b) (uint16_t)((uint8_t)b << 8 | (uint8_t)a)

/* Little endian machine correction defines. */
#ifdef _LITTLE_ENDIAN
#define	LITTLE_ENDIAN_16(x)
#define	LITTLE_ENDIAN_24(x)
#define	LITTLE_ENDIAN_32(x)
#define	LITTLE_ENDIAN_64(x)
#define	BIG_ENDIAN_16(x)	qlc_chg_endian((uint8_t *)&(x), 2)
#define	BIG_ENDIAN_24(x)	qlc_chg_endian((uint8_t *)&(x), 3)
#define	BIG_ENDIAN_32(x)	qlc_chg_endian((uint8_t *)&(x), 4)
#define	BIG_ENDIAN_64(x)	qlc_chg_endian((uint8_t *)&(x), 8)
#endif

/* Big endian machine correction defines. */
#ifdef _BIG_ENDIAN
#define	LITTLE_ENDIAN_16(x)	qlc_chg_endian((uint8_t *)&(x), 2)
#define	LITTLE_ENDIAN_24(x)	qlc_chg_endian((uint8_t *)&(x), 3)
#define	LITTLE_ENDIAN_32(x)	qlc_chg_endian((uint8_t *)&(x), 4)
#define	LITTLE_ENDIAN_64(x)	qlc_chg_endian((uint8_t *)&(x), 8)
#define	BIG_ENDIAN_16(x)
#define	BIG_ENDIAN_24(x)
#define	BIG_ENDIAN_32(x)
#define	BIG_ENDIAN_64(x)
#endif

#define	LOCAL_LOOP_ID(x)	(x <= LAST_LOCAL_LOOP_ID)

#define	FABRIC_LOOP_ID(x)	(x == FL_PORT_LOOP_ID || \
    x == SIMPLE_NAME_SERVER_LOOP_ID)

#define	SNS_LOOP_ID(x)		(x >= SNS_FIRST_LOOP_ID && \
    x <= SNS_LAST_LOOP_ID)

#define	BROADCAST_LOOP_ID(x)	(x == IP_BROADCAST_LOOP_ID)

#define	VALID_LOOP_ID(x)	(LOCAL_LOOP_ID(x) || SNS_LOOP_ID(x) || \
    FABRIC_LOOP_ID(x) || BROADCAST_LOOP_ID(x))

#define	RESERVED_LOOP_ID(x)	(x >= FL_PORT_LOOP_ID && \
    x <= SWITCH_EMBEDDED_PORT_LOOP_ID)

/*
 * Locking Macro Definitions
 */
#define	GLOBAL_STATE_LOCK()		mutex_enter(&qlc_global_mutex)
#define	GLOBAL_STATE_UNLOCK()		mutex_exit(&qlc_global_mutex)

#define	TRY_DEVICE_QUEUE_LOCK(q)	mutex_tryenter(&q->mutex)
#define	DEVICE_QUEUE_LOCK(q)		mutex_enter(&q->mutex)
#define	DEVICE_QUEUE_UNLOCK(q)		mutex_exit(&q->mutex)

#define	MBX_REGISTER_LOCK(ha)		mutex_enter(&ha->mbx_mutex)
#define	MBX_REGISTER_UNLOCK(ha)		mutex_exit(&ha->mbx_mutex)

#define	INTR_LOCK(ha)			mutex_enter(&ha->intr_mutex)
#define	INTR_UNLOCK(ha)			mutex_exit(&ha->intr_mutex)

#define	TASK_DAEMON_LOCK(ha)		mutex_enter(&ha->task_daemon_mutex)
#define	TASK_DAEMON_UNLOCK(ha)		mutex_exit(&ha->task_daemon_mutex)

#define	REQUEST_RING_LOCK(ha)		mutex_enter(&ha->req_ring_mutex)
#define	REQUEST_RING_UNLOCK(ha)		mutex_exit(&ha->req_ring_mutex)

#define	ADAPTER_STATE_LOCK(ha)		mutex_enter(&ha->mutex)
#define	ADAPTER_STATE_UNLOCK(ha)	mutex_exit(&ha->mutex)

#define	QLC_PM_LOCK(ha)			mutex_enter(&ha->pm_mutex)
#define	QLC_PM_UNLOCK(ha)		mutex_exit(&ha->pm_mutex)

#define	QLC_UB_LOCK(ha)			mutex_enter(&(ha)->ub_mutex)
#define	QLC_UB_UNLOCK(ha)		mutex_exit(&(ha)->ub_mutex)

/*
 * PCI power management control/status register location
 */
#define	QLC_PM_CS_REG			0x48

/*
 * qlc component
 */
#define	QLC_POWER_COMPONENT		0

typedef struct qlc_config_space {
	uint16_t	chs_command;
	uint8_t		chs_cache_line_size;
	uint8_t		chs_latency_timer;
	uint8_t		chs_header_type;
	uint8_t		chs_sec_latency_timer;
	uint8_t		chs_bridge_control;
	uint32_t	chs_base0;
	uint32_t	chs_base1;
	uint32_t	chs_base2;
	uint32_t	chs_base3;
	uint32_t	chs_base4;
	uint32_t	chs_base5;
} qlc_config_space_t;

#ifdef	USE_DDI_INTERFACES

#define	QLC_SAVE_CONFIG_REGS(dip)		pci_save_config_regs(dip)
#define	QLC_RESTORE_CONFIG_REGS(dip)		pci_restore_config_regs(dip)

#else /* USE_DDI_INTERFACES */

#define	QLC_SAVE_CONFIG_REGS(dip)		qlc_save_config_regs(dip)
#define	QLC_RESTORE_CONFIG_REGS(dip)		qlc_restore_config_regs(dip)

#endif /* USE_DDI_INTERFACES */

#define	QLC_IS_SET(x, y)	(((x) & (y)) == (y))

/*
 * QLC local function return status codes
 */
#define	QLC_SUCCESS		(MBS_COMMAND_COMPLETE & MBS_MASK)
#define	QLC_INVALID_COMMAND	(MBS_INVALID_COMMAND & MBS_MASK)
#define	QLC_INTERFACE_ERROR	(MBS_HOST_INTERFACE_ERROR & MBS_MASK)
#define	QLC_TEST_FAILED		(MBS_TEST_FAILED & MBS_MASK)
#define	QLC_COMMAND_ERROR	(MBS_COMMAND_ERROR & MBS_MASK)
#define	QLC_PARAMETER_ERROR	(MBS_COMMAND_PARAMETER_ERROR & MBS_MASK)
#define	QLC_PORT_ID_USED	(MBS_PORT_ID_USED & MBS_MASK)
#define	QLC_LOOP_ID_USED	(MBS_LOOP_ID_USED & MBS_MASK)
#define	QLC_ALL_IDS_IN_USE	(MBS_ALL_IDS_IN_USE & MBS_MASK)
#define	QLC_NOT_LOGGED_IN	(MBS_NOT_LOGGED_IN & MBS_MASK)

#define	QLC_FUNCTION_TIMEOUT		MBS_END
#define	QLC_FUNCTION_PARAMETER_ERROR	(MBS_END + 1)
#define	QLC_FUNCTION_FAILED		(MBS_END + 2)
#define	QLC_MEMORY_ALLOC_FAILED		(MBS_END + 3)

/*
 * Global Data in qlc.c source file.
 */
extern void *qlc_state;		/* for soft state routine */

/*
 * Global Function Prototypes in qlc.c source file.
 */
void qlc_nv_write(qlc_adapter_state_t *, uint16_t);
void qlc_nv_delay(void);
uint16_t qlc_get_nvram_word(qlc_adapter_state_t *, uint32_t);
void qlc_chg_endian(uint8_t *, size_t);

#ifdef	__cplusplus
}
#endif

#endif /* !_SYS_FIBRE_CHANNEL_FCA_QLC_H */
