Skip to main content

Source code file content

Revision: 13149

6973228 Cannot download firmware 2.103.x.x on Emulex FCoE HBAs 6960289 fiber side of emulex cna does not connect to the storage
» Project Revision History

» Checkout URL

on-src / usr / src / uts / common / sys / fibre-channel / fca / emlxs / emlxs_fc.h

Size: 58533 bytes, 1 line
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2010 Emulex.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _EMLXS_FC_H
#define	_EMLXS_FC_H

#ifdef	__cplusplus
extern "C" {
#endif

typedef struct emlxs_buf
{
	fc_packet_t		*pkt;		/* scsi_pkt reference */
	struct emlxs_port	*port;		/* pointer to port */
	void			*bmp;		/* Save the buffer pointer */
						/* list for later use. */
	struct emlxs_buf	*fc_fwd;	/* Use it by chip_Q */
	struct emlxs_buf	*fc_bkwd;	/* Use it by chip_Q */
	struct emlxs_buf	*next;		/* Use it when the iodone */
	void 			*node;		/* Save node and used by */
						/* abort */
	void			*channel;	/* Save channel and used by */
						/* abort */
	struct emlxs_buf	*fpkt;		/* Flush pkt pointer */
	struct XRIobject	*xp;		/* Exchange resource */
	IOCBQ			iocbq;
	kmutex_t		mtx;
	uint32_t		pkt_flags;
	uint32_t		iotag;		/* iotag for this cmd */
	uint32_t		ticks;		/* save the timeout ticks */
						/* for the fc_packet_t */
	uint32_t		abort_attempts;
	uint32_t		lun;		/* Save LUN id and used by */
						/* abort */
	uint32_t		class;		/* Save class and used by */
						/* abort */
	uint32_t		ucmd;		/* Unsolicted command that */
						/* this packet is responding */
						/* to, if any */
	int32_t			flush_count;	/* Valid only in flush pkts */
	uint32_t		did;

#ifdef SFCT_SUPPORT
	kmutex_t		fct_mtx;
	fc_packet_t		*fct_pkt;
	fct_cmd_t		*fct_cmd;

	uint8_t			fct_type;

#define	EMLXS_FCT_ELS_CMD		0x01	/* Unsolicted */
#define	EMLXS_FCT_ELS_REQ		0x02	/* Solicited */
#define	EMLXS_FCT_ELS_RSP		0x04
#define	EMLXS_FCT_CT_REQ		0x08	/* Solicited */
#define	EMLXS_FCT_FCP_CMD		0x10	/* Unsolicted */
#define	EMLXS_FCT_FCP_DATA		0x20
#define	EMLXS_FCT_FCP_STATUS		0x40


	uint8_t			fct_flags;

#define	EMLXS_FCT_SEND_STATUS		0x01
#define	EMLXS_FCT_ABORT_INP		0x02
#define	EMLXS_FCT_IO_INP		0x04
#define	EMLXS_FCT_REGISTERED		0x10
#define	EMLXS_FCT_PLOGI_RECEIVED	0x20
#define	EMLXS_FCT_FLOGI			0x40

	uint16_t		fct_state;

#define	EMLXS_FCT_FCP_CMD_RECEIVED	1
#define	EMLXS_FCT_ELS_CMD_RECEIVED	2
#define	EMLXS_FCT_CMD_POSTED		3
#define	EMLXS_FCT_CMD_WAITQ		4
#define	EMLXS_FCT_SEND_CMD_RSP		5
#define	EMLXS_FCT_SEND_ELS_RSP		6
#define	EMLXS_FCT_SEND_ELS_REQ		7
#define	EMLXS_FCT_SEND_CT_REQ		8
#define	EMLXS_FCT_RSP_PENDING		9
#define	EMLXS_FCT_REQ_PENDING		10
#define	EMLXS_FCT_REG_PENDING		11
#define	EMLXS_FCT_REG_COMPLETE		12
#define	EMLXS_FCT_OWNED			13
#define	EMLXS_FCT_SEND_FCP_DATA		14
#define	EMLXS_FCT_SEND_FCP_STATUS	15
#define	EMLXS_FCT_DATA_PENDING		16
#define	EMLXS_FCT_STATUS_PENDING	17
#define	EMLXS_FCT_PKT_COMPLETE		18
#define	EMLXS_FCT_PKT_FCPRSP_COMPLETE	19
#define	EMLXS_FCT_PKT_ELSRSP_COMPLETE	20
#define	EMLXS_FCT_PKT_ELSCMD_COMPLETE	21
#define	EMLXS_FCT_PKT_CTCMD_COMPLETE	22
#define	EMLXS_FCT_REQ_COMPLETE		23
#define	EMLXS_FCT_CLOSE_PENDING		24
#define	EMLXS_FCT_ABORT_PENDING		25
#define	EMLXS_FCT_ABORT_DONE		26
#define	EMLXS_FCT_IO_DONE		27

#define	EMLXS_FCT_IOCB_ISSUED		256 /* For tracing only */
#define	EMLXS_FCT_IOCB_COMPLETE		257 /* For tracing only */

	stmf_data_buf_t		*fct_buf;

#endif /* SFCT_SUPPORT */

#ifdef SAN_DIAG_SUPPORT
	hrtime_t		sd_start_time;
#endif
} emlxs_buf_t;



#ifdef FCT_IO_TRACE
#define	EMLXS_FCT_STATE_CHG(_fct_cmd, _cmd_sbp, _state)	\
	(_cmd_sbp)->fct_state = _state;			\
	emlxs_fct_io_trace((_cmd_sbp)->port, _fct_cmd, _state)
#else
/* define to set fct_state */
#define	EMLXS_FCT_STATE_CHG(_fct_cmd, _cmd_sbp, _state)	\
	(_cmd_sbp)->fct_state = _state
#endif /* FCT_IO_TRACE */


/* pkt_flags */
#define	PACKET_IN_COMPLETION	0x00000001
#define	PACKET_IN_TXQ		0x00000002
#define	PACKET_IN_CHIPQ		0x00000004
#define	PACKET_IN_DONEQ		0x00000008

#define	PACKET_FCP_RESET	0x00000030
#define	PACKET_FCP_TGT_RESET	0x00000010
#define	PACKET_FCP_LUN_RESET	0x00000020
#define	PACKET_POLLED		0x00000040

#ifdef EMLXS_I386
#define	PACKET_FCP_SWAPPED	0x00000100
#define	PACKET_ELS_SWAPPED	0x00000200
#define	PACKET_CT_SWAPPED	0x00000400
#define	PACKET_CSP_SWAPPED	0x00000800
#endif	/* EMLXS_I386 */

#define	PACKET_STALE		0x00001000

#define	PACKET_IN_TIMEOUT	0x00010000
#define	PACKET_IN_FLUSH		0x00020000
#define	PACKET_IN_ABORT		0x00040000
#define	PACKET_XRI_CLOSED	0x00080000 /* An XRI abort/close was issued */

#define	PACKET_CHIP_COMP	0x00100000
#define	PACKET_COMPLETED	0x00200000
#define	PACKET_ULP_OWNED	0x00400000

#define	PACKET_STATE_VALID	0x01000000
#define	PACKET_FCP_RSP_VALID	0x02000000
#define	PACKET_ELS_RSP_VALID	0x04000000
#define	PACKET_CT_RSP_VALID	0x08000000

#define	PACKET_DELAY_REQUIRED	0x10000000
#define	PACKET_ALLOCATED	0x40000000
#define	PACKET_VALID		0x80000000


#define	STALE_PACKET		((emlxs_buf_t *)0xFFFFFFFF)


/*
 * From fc_error.h pkt_reason (except for state = NPORT_RJT, FABRIC_RJT,
 * NPORT_BSY, FABRIC_BSY, LS_RJT, BA_RJT, FS_RJT)
 *
 * FCA unique error codes can begin after FC_REASON_FCA_UNIQUE.
 * Each FCA defines its own set with values greater >= 0x7F
 */
#define	FC_REASON_FCA_DEFINED   0x100


/*
 * Device VPD save area
 */

typedef struct emlxs_vpd
{
	uint32_t	biuRev;
	uint32_t	smRev;
	uint32_t	smFwRev;
	uint32_t	endecRev;
	uint16_t	rBit;
	uint8_t		fcphHigh;
	uint8_t		fcphLow;
	uint8_t		feaLevelHigh;
	uint8_t		feaLevelLow;

	uint32_t	postKernRev;
	char		postKernName[32];

	uint32_t	opFwRev;
	char		opFwName[32];
	char		opFwLabel[32];

	uint32_t	sli1FwRev;
	char		sli1FwName[32];
	char		sli1FwLabel[32];

	uint32_t	sli2FwRev;
	char		sli2FwName[32];
	char		sli2FwLabel[32];

	uint32_t	sli3FwRev;
	char		sli3FwName[32];
	char		sli3FwLabel[32];

	uint32_t	sli4FwRev;
	char		sli4FwName[32];
	char		sli4FwLabel[32];

	char		fw_version[32];
	char		fw_label[32];

	char		fcode_version[32];
	char		boot_version[32];

	char		serial_num[32];
	char		part_num[32];
	char		port_num[20];
	char		eng_change[32];
	char		manufacturer[80];
	char		model[80];
	char		model_desc[256];
	char		prog_types[256];
	char		id[80];

	uint32_t	port_index;
	uint8_t		link_speed;
} emlxs_vpd_t;


typedef struct emlxs_queue
{
	uint8_t		*q_first;	/* queue first element */
	uint8_t		*q_last;	/* queue last element */
	uint16_t	q_cnt;	/* current length of queue */
	uint16_t	q_max;	/* max length queue can get */
} emlxs_queue_t;
typedef emlxs_queue_t Q;



/*
 * This structure is used when allocating a buffer pool.
 * Note: this should be identical to gasket buf_info (fldl.h).
 */
typedef struct emlxs_buf_info
{
	int32_t		size;	/* Specifies the number of bytes to allocate. */
	int32_t		align;	/* The desired address boundary. */

	int32_t		flags;

#define	FC_MBUF_DMA		0x01	/* blocks are for DMA */
#define	FC_MBUF_PHYSONLY	0x02	/* For malloc - map a given virtual */
					/* address to physical address (skip */
					/* the malloc). */
					/* For free - just unmap the given */
					/* physical address (skip the free). */
#define	FC_MBUF_IOCTL		0x04	/* called from dfc_ioctl */
#define	FC_MBUF_UNLOCK		0x08	/* called with driver unlocked */
#define	FC_MBUF_SNGLSG		0x10	/* allocate a single contiguous */
					/* physical memory */
#define	FC_MBUF_DMA32		0x20

	uint64_t	phys;		/* specifies physical buffer pointer */
	void		*virt;		/* specifies virtual buffer pointer */
	void		*data_handle;
	void		*dma_handle;
} emlxs_buf_info_t;
typedef emlxs_buf_info_t MBUF_INFO;


#define	EMLXS_MAX_HBQ   	16	/* Max HBQs handled by firmware */
#define	EMLXS_ELS_HBQ_ID	0
#define	EMLXS_IP_HBQ_ID		1
#define	EMLXS_CT_HBQ_ID		2
#define	EMLXS_FCT_HBQ_ID	3

#ifdef SFCT_SUPPORT
#define	EMLXS_NUM_HBQ		4	/* Number of HBQs supported by driver */
#else
#define	EMLXS_NUM_HBQ		3	/* Number of HBQs supported by driver */
#endif /* SFCT_SUPPORT */


/*
 * An IO Channel is a object that comprises a xmit/cmpl
 * path for IOs.
 * For SLI3, an IO path maps to a ring (cmd/rsp)
 * For SLI4, an IO path map to a queue pair (WQ/CQ)
 */
typedef struct emlxs_channel
{
	struct emlxs_hba *hba;			/* ptr to hba for channel */
	void		*iopath;		/* ptr to SLI3/4 io path */

	kmutex_t	rsp_lock;
	IOCBQ		*rsp_head;	/* deferred completion head */
	IOCBQ		*rsp_tail;	/* deferred completion tail */
	emlxs_thread_t  intr_thread;


	uint16_t	channelno;
	uint16_t	chan_flag;

#define	EMLXS_NEEDS_TRIGGER 1

	/* Protected by EMLXS_TX_CHANNEL_LOCK */
	emlxs_queue_t	nodeq;			/* Node service queue */

	kmutex_t	channel_cmd_lock;
	uint32_t	timeout;

	/* Channel command counters */
	uint32_t	ulpSendCmd;
	uint32_t	ulpCmplCmd;
	uint32_t	hbaSendCmd;
	uint32_t	hbaCmplCmd;
	uint32_t	hbaSendCmd_sbp;
	uint32_t	hbaCmplCmd_sbp;

} emlxs_channel_t;
typedef emlxs_channel_t CHANNEL;

/*
 * Should be able to handle max number of io paths for a
 * SLI4 HBA (EMLXS_MAX_WQS) or for a SLI3 HBA (MAX_RINGS)
 */
#define	MAX_CHANNEL EMLXS_MSI_MAX_INTRS


/* Structure used to access adapter rings */
typedef struct emlxs_ring
{
	void		*fc_cmdringaddr;	/* virtual offset for cmd */
						/* rings */
	void		*fc_rspringaddr;	/* virtual offset for rsp */
						/* rings */

	uint8_t		*fc_mpon;		/* index ptr for match */
						/* structure */
	uint8_t		*fc_mpoff;		/* index ptr for match */
						/* structure */
	struct emlxs_hba *hba;			/* ptr to hba for ring */

	uint8_t		fc_numCiocb;		/* number of command iocb's */
						/* per ring */
	uint8_t		fc_numRiocb;		/* number of response iocb's */
						/* per ring */
	uint8_t		fc_rspidx;		/* current index in response */
						/* ring */
	uint8_t		fc_cmdidx;		/* current index in command */
						/* ring */
	uint8_t		fc_port_rspidx;
	uint8_t		fc_port_cmdidx;
	uint8_t		ringno;

	uint16_t	fc_missbufcnt;		/* buf cnt we need to repost */
	CHANNEL		*channelp;


} emlxs_ring_t;
typedef emlxs_ring_t RING;


#ifdef SAN_DIAG_SUPPORT
/*
 * Although right now it's just 1 field, SAN Diag anticipates that this
 * structure will grow in the future.
 */
typedef struct sd_timestat_level0 {
	int		count;
} sd_timestat_level0_t;
#endif

typedef struct emlxs_node
{
	struct emlxs_node	*nlp_list_next;
	struct emlxs_node	*nlp_list_prev;

	NAME_TYPE		nlp_portname;	/* port name */
	NAME_TYPE		nlp_nodename;	/* node name */

	uint32_t		nlp_DID;	/* fibre channel D_ID */
	uint32_t		nlp_oldDID;

	uint16_t		nlp_Rpi;	/* login id returned by */
						/* REG_LOGIN */
	uint16_t		nlp_Xri;	/* login id returned by */
						/* REG_LOGIN */

	uint8_t			nlp_fcp_info;	/* Remote class info */

	/* nlp_fcp_info */
#define	NLP_FCP_TGT_DEVICE	0x10	/* FCP TGT device */
#define	NLP_FCP_INI_DEVICE	0x20	/* FCP Initiator device */
#define	NLP_FCP_2_DEVICE	0x40	/* FCP-2 TGT device */
#define	NLP_EMLX_VPORT		0x80    /* Virtual port */

	uint32_t		nlp_force_rscn;
	uint32_t		nlp_tag;	/* Tag used by port_offline */
	uint32_t		flag;

#define	NODE_POOL_ALLOCATED 	0x00000001

	SERV_PARM		sparm;

	/* Protected by EMLXS_TX_CHANNEL_LOCK */
	uint32_t		nlp_active;	/* Node active flag */
	uint32_t		nlp_base;
	uint32_t		nlp_flag[MAX_CHANNEL];	/* Node level channel */
							/* flags */

	/* nlp_flag */
#define	NLP_CLOSED		0x1
#define	NLP_OFFLINE		0x2
#define	NLP_RPI_XRI		0x4

	uint32_t		nlp_tics[MAX_CHANNEL];	/* gate timeout */
	emlxs_queue_t		nlp_tx[MAX_CHANNEL];	/* Transmit Q head */
	emlxs_queue_t		nlp_ptx[MAX_CHANNEL];	/* Priority transmit */
							/* Queue head */
	void			*nlp_next[MAX_CHANNEL];	/* Service Request */
							/* Queue pointer used */
							/* when node needs */
							/* servicing */
#ifdef DHCHAP_SUPPORT
	emlxs_node_dhc_t	node_dhc;
#endif	/* DHCHAP_SUPPORT */

#ifdef SAN_DIAG_SUPPORT
	sd_timestat_level0_t	sd_dev_bucket[SD_IO_LATENCY_MAX_BUCKETS];
#endif

	struct RPIobject	*RPIp;	/* SLI4 only */
#define	EMLXS_NODE_TO_RPI(_h, _n)	\
	((_n)?((_n->RPIp)?_n->RPIp:emlxs_sli4_find_rpi(_h, _n->nlp_Rpi)):NULL)

} emlxs_node_t;
typedef emlxs_node_t NODELIST;



#define	NADDR_LEN	6	/* MAC network address length */
typedef struct emlxs_fcip_nethdr
{
	NAME_TYPE	fc_destname;	/* destination port name */
	NAME_TYPE	fc_srcname;	/* source port name */
} emlxs_fcip_nethdr_t;
typedef emlxs_fcip_nethdr_t NETHDR;


#define	MEM_NLP		0	/* memory segment to hold node list entries */
#define	MEM_IOCB	1	/* memory segment to hold iocb commands */
#define	MEM_MBOX	2	/* memory segment to hold mailbox cmds  */
#define	MEM_BPL		3	/* and to hold buffer ptr lists - SLI2   */
#define	MEM_BUF		4	/* memory segment to hold buffer data   */
#define	MEM_ELSBUF	4	/* memory segment to hold buffer data   */
#define	MEM_IPBUF	5	/* memory segment to hold IP buffer data */
#define	MEM_CTBUF	6	/* memory segment to hold CT buffer data */
#define	MEM_FCTBUF	7	/* memory segment to hold FCT buffer data */

#ifdef SFCT_SUPPORT
#define	FC_MAX_SEG	8
#else
#define	FC_MAX_SEG	7
#endif /* SFCT_SUPPORT */


/* A BPL entry is 12 bytes. Subtract 2 for command and response buffers */
#define	BPL_TO_SGLLEN(_bpl)   ((_bpl/12)-2)
#define	MEM_BPL_SIZE		1024  /* Default size */

/* A SGL entry is 16 bytes. Subtract 2 for command and response buffers */
#define	SGL_TO_SGLLEN(_sgl)   ((_sgl/16)-2)
#define	MEM_SGL_SIZE		4096  /* Default size */

#ifdef EMLXS_I386
#define	EMLXS_SGLLEN		BPL_TO_SGLLEN(MEM_BPL_SIZE)
#else	/* EMLXS_SPARC */
#define	EMLXS_SGLLEN		1
#endif	/* EMLXS_I386 */

#define	MEM_BUF_SIZE		1024
#define	MEM_BUF_COUNT		64

#define	MEM_ELSBUF_SIZE   	MEM_BUF_SIZE
#define	MEM_ELSBUF_COUNT  	hba->max_nodes
#define	MEM_IPBUF_SIZE  	65535
#define	MEM_IPBUF_COUNT		60
#define	MEM_CTBUF_SIZE		MAX_CT_PAYLOAD	/* (1024*320) */
#define	MEM_CTBUF_COUNT		8
#define	MEM_FCTBUF_SIZE  	65535
#define	MEM_FCTBUF_COUNT	128

typedef struct emlxs_memseg
{
	uint8_t			*fc_memget_ptr;
	uint8_t			*fc_memget_end;
	uint8_t			*fc_memput_ptr;
	uint8_t			*fc_memput_end;

	uint8_t			*fc_memstart_virt;	/* beginning address */
							/* of memory block */
	uint64_t		fc_memstart_phys;	/* beginning address */
							/* of memory block */
	ddi_dma_handle_t	fc_mem_dma_handle;
	ddi_acc_handle_t	fc_mem_dat_handle;
	uint32_t		fc_total_memsize;
	uint32_t		fc_memsize;		/* size of mem blks */
	uint32_t		fc_numblks;		/* no of mem blks */
	uint32_t		fc_memget_cnt;		/* no of mem get blks */
	uint32_t		fc_memput_cnt;		/* no of mem put blks */
	uint32_t		fc_memflag;  /* emlxs_buf_info_t FLAGS */
	uint32_t		fc_reserved; /* used with priority flag */
	uint32_t		fc_memalign;
	uint32_t		fc_memtag;
	char			fc_label[32];

} emlxs_memseg_t;
typedef emlxs_memseg_t MEMSEG;


/* Board stat counters */
typedef struct emlxs_stats
{
	uint32_t	LinkUp;
	uint32_t	LinkDown;
	uint32_t	LinkEvent;
	uint32_t	LinkMultiEvent;

	uint32_t	MboxIssued;
	uint32_t	MboxCompleted;	/* MboxError + MbxGood */
	uint32_t	MboxGood;
	uint32_t	MboxError;
	uint32_t	MboxBusy;
	uint32_t	MboxInvalid;

	uint32_t	IocbIssued[MAX_CHANNEL];
	uint32_t	IocbReceived[MAX_CHANNEL];
	uint32_t	IocbTxPut[MAX_CHANNEL];
	uint32_t	IocbTxGet[MAX_CHANNEL];
	uint32_t	IocbRingFull[MAX_CHANNEL];
	uint32_t	IocbThrottled;

	uint32_t	IntrEvent[8];

	uint32_t	FcpIssued;
	uint32_t	FcpCompleted;	/* FcpGood + FcpError */
	uint32_t	FcpGood;
	uint32_t	FcpError;

	uint32_t	FcpEvent;	/* FcpStray + FcpCompleted */
	uint32_t	FcpStray;
#ifdef SFCT_SUPPORT
	uint32_t	FctRingEvent;
	uint32_t	FctRingError;
	uint32_t	FctRingDropped;
#endif /* SFCT_SUPPORT */

	uint32_t	ElsEvent;	/* ElsStray + ElsCmplt (cmd + rsp) */
	uint32_t	ElsStray;

	uint32_t	ElsCmdIssued;
	uint32_t	ElsCmdCompleted;	/* ElsCmdGood + ElsCmdError */
	uint32_t	ElsCmdGood;
	uint32_t	ElsCmdError;

	uint32_t	ElsRspIssued;
	uint32_t	ElsRspCompleted;

	uint32_t	ElsRcvEvent;	/* ElsRcvErr + ElsRcvDrop + ElsCmdRcv */
	uint32_t	ElsRcvError;
	uint32_t	ElsRcvDropped;
	uint32_t	ElsCmdReceived;	/* ElsRscnRcv + ElsPlogiRcv + ... */
	uint32_t	ElsRscnReceived;
	uint32_t	ElsFlogiReceived;
	uint32_t	ElsPlogiReceived;
	uint32_t	ElsPrliReceived;
	uint32_t	ElsPrloReceived;
	uint32_t	ElsLogoReceived;
	uint32_t	ElsAdiscReceived;
	uint32_t	ElsAuthReceived;
	uint32_t	ElsGenReceived;

	uint32_t	CtEvent;	/* CtStray + CtCompleted (cmd + rsp) */
	uint32_t	CtStray;

	uint32_t	CtCmdIssued;
	uint32_t	CtCmdCompleted;	/* CtCmdGood + CtCmdError */
	uint32_t	CtCmdGood;
	uint32_t	CtCmdError;

	uint32_t	CtRspIssued;
	uint32_t	CtRspCompleted;

	uint32_t	CtRcvEvent;	/* CtRcvError + CtRcvDrop + CtCmdRcvd */
	uint32_t	CtRcvError;
	uint32_t	CtRcvDropped;
	uint32_t	CtCmdReceived;

	uint32_t	IpEvent;	/* IpStray + IpSeqCmpl + IpBcastCmpl */
	uint32_t	IpStray;

	uint32_t	IpSeqIssued;
	uint32_t	IpSeqCompleted;	/* IpSeqGood + IpSeqError */
	uint32_t	IpSeqGood;
	uint32_t	IpSeqError;

	uint32_t	IpBcastIssued;
	uint32_t	IpBcastCompleted;	/* IpBcastGood + IpBcastError */
	uint32_t	IpBcastGood;
	uint32_t	IpBcastError;

	uint32_t	IpRcvEvent;	/* IpDrop + IpSeqRcv + IpBcastRcv */
	uint32_t	IpDropped;
	uint32_t	IpSeqReceived;
	uint32_t	IpBcastReceived;

	uint32_t	IpUbPosted;
	uint32_t	ElsUbPosted;
	uint32_t	CtUbPosted;
#ifdef SFCT_SUPPORT
	uint32_t	FctUbPosted;
#endif /* SFCT_SUPPORT */

	uint32_t	ResetTime;	/* Time of last reset */
} emlxs_stats_t;


#define	FC_MAX_ADPTMSG   (8*28)	/* max size of a msg from adapter */

#define	EMLXS_NUM_THREADS	8
#define	EMLXS_MIN_TASKS		8
#define	EMLXS_MAX_TASKS		8

#define	EMLXS_NUM_HASH_QUES	32
#define	EMLXS_DID_HASH(x)	((x) & (EMLXS_NUM_HASH_QUES - 1))


/* pkt_tran_flag */
#define	FC_TRAN_COMPLETED	0x8000


typedef struct emlxs_dfc_event
{
	uint32_t	pid;
	uint32_t	event;
	uint32_t	last_id;

	void		*dataout;
	uint32_t	size;
	uint32_t	mode;
} emlxs_dfc_event_t;


typedef struct emlxs_hba_event
{
	uint32_t	last_id;
	uint32_t	new;
	uint32_t	missed;
} emlxs_hba_event_t;


#ifdef SFCT_SUPPORT

#define	TGTPORTSTAT			port->fct_stat

/*
 * FctP2IOXcnt will count IOs by their fcpDL. Counters
 * are for buckets of various power of 2 sizes.
 * Bucket 0  <  512  > 0
 * Bucket 1  >= 512  < 1024
 * Bucket 2  >= 1024 < 2048
 * Bucket 3  >= 2048 < 4096
 * Bucket 4  >= 4096 < 8192
 * Bucket 5  >= 8192 < 16K
 * Bucket 6  >= 16K  < 32K
 * Bucket 7  >= 32K  < 64K
 * Bucket 8  >= 64K  < 128K
 * Bucket 9  >= 128K < 256K
 * Bucket 10 >= 256K < 512K
 * Bucket 11 >= 512K < 1MB
 * Bucket 12 >= 1MB  < 2MB
 * Bucket 13 >= 2MB  < 4MB
 * Bucket 14 >= 4MB  < 8MB
 * Bucket 15 >= 8MB
 */
#define	MAX_TGTPORT_IOCNT  16


/*
 * These routines will bump the right counter, based on
 * the size of the IO inputed, with the least number of
 * comparisions.  A max of 5 comparisions is only needed
 * to classify the IO in one of 16 ranges. A binary search
 * to locate the high bit in the size is used.
 */
#define	EMLXS_BUMP_RDIOCTR(port, cnt) \
{ \
	/* Use binary search to find the first high bit */ \
	if (cnt & 0xffff0000) { \
		if (cnt & 0xff800000) { \
			TGTPORTSTAT.FctP2IORcnt[15]++; \
		} \
		else { \
			/* It must be 0x007f0000 */ \
			if (cnt & 0x00700000) { \
				if (cnt & 0x00400000) { \
					TGTPORTSTAT.FctP2IORcnt[14]++; \
				} \
				else { \
					/* it must be 0x00300000 */ \
					if (cnt & 0x00200000) { \
						TGTPORTSTAT.FctP2IORcnt[13]++; \
					} \
					else { \
						/* It must be 0x00100000 */ \
						TGTPORTSTAT.FctP2IORcnt[12]++; \
					} \
				} \
			} \
			else { \
				/* It must be 0x000f0000 */ \
				if (cnt & 0x000c0000) {	\
					if (cnt & 0x00080000) {	\
						TGTPORTSTAT.FctP2IORcnt[11]++; \
					} \
					else { \
						/* It must be 0x00040000 */ \
						TGTPORTSTAT.FctP2IORcnt[10]++; \
					} \
				} \
				else { \
					/* It must be 0x00030000 */ \
					if (cnt & 0x00020000) {	\
						TGTPORTSTAT.FctP2IORcnt[9]++; \
					} \
					else { \
						/* It must be 0x00010000 */ \
						TGTPORTSTAT.FctP2IORcnt[8]++; \
					} \
				} \
			} \
		} \
	} \
	else { \
		if (cnt & 0x0000fe00) { \
			if (cnt & 0x0000f000) { \
				if (cnt & 0x0000c000) { \
					if (cnt & 0x00008000) { \
						TGTPORTSTAT.FctP2IORcnt[7]++; \
					} \
					else { \
						/* It must be 0x00004000 */ \
						TGTPORTSTAT.FctP2IORcnt[6]++; \
					} \
				} \
				else { \
					/* It must be 0x00000300 */ \
					if (cnt & 0x00000200) { \
						TGTPORTSTAT.FctP2IORcnt[5]++; \
					} \
					else { \
						/* It must be 0x00000100 */ \
						TGTPORTSTAT.FctP2IORcnt[4]++; \
					} \
				} \
			} \
			else { \
				/* It must be 0x00000e00 */ \
				if (cnt & 0x00000800) { \
					TGTPORTSTAT.FctP2IORcnt[3]++; \
				} \
				else { \
					/* It must be 0x00000600 */ \
					if (cnt & 0x00000400) { \
						TGTPORTSTAT.FctP2IORcnt[2]++; \
					} \
					else { \
						/* It must be 0x00000200 */ \
						TGTPORTSTAT.FctP2IORcnt[1]++; \
					} \
				} \
			} \
		} \
		else { \
			/* It must be 0x000001ff */ \
			TGTPORTSTAT.FctP2IORcnt[0]++; \
		} \
	} \
}


#define	EMLXS_BUMP_WRIOCTR(port, cnt) \
{ \
/* Use binary search to find the first high bit */ \
	if (cnt & 0xffff0000) { \
		if (cnt & 0xff800000) { \
			TGTPORTSTAT.FctP2IOWcnt[15]++; \
		} \
		else { \
			/* It must be 0x007f0000 */ \
			if (cnt & 0x00700000) { \
				if (cnt & 0x00400000) { \
					TGTPORTSTAT.FctP2IOWcnt[14]++; \
				} \
				else { \
					/* It must be 0x00300000 */ \
					if (cnt & 0x00200000) { \
						TGTPORTSTAT.FctP2IOWcnt[13]++; \
					} \
					else { \
						/* It must be 0x00100000 */ \
						TGTPORTSTAT.FctP2IOWcnt[12]++; \
					} \
				} \
			} \
			else { \
				/* It must be 0x000f0000 */ \
				if (cnt & 0x000c0000) { \
					if (cnt & 0x00080000) { \
						TGTPORTSTAT.FctP2IOWcnt[11]++; \
					} \
					else { \
						/* it must be 0x00040000 */ \
						TGTPORTSTAT.FctP2IOWcnt[10]++; \
					} \
				} \
				else { \
					/* It must be 0x00030000 */ \
					if (cnt & 0x00020000) { \
						TGTPORTSTAT.FctP2IOWcnt[9]++; \
					} \
					else { \
						/* It must be 0x00010000 */ \
						TGTPORTSTAT.FctP2IOWcnt[8]++; \
					} \
				} \
			} \
		} \
	} \
	else { \
		if (cnt & 0x0000fe00) { \
			if (cnt & 0x0000f000) { \
				if (cnt & 0x0000c000) { \
					if (cnt & 0x00008000) { \
						TGTPORTSTAT.FctP2IOWcnt[7]++; \
					} \
					else { \
						/* It must be 0x00004000 */ \
						TGTPORTSTAT.FctP2IOWcnt[6]++; \
					} \
				} \
				else { \
					/* It must be 0x00000300 */ \
					if (cnt & 0x00000200) { \
						TGTPORTSTAT.FctP2IOWcnt[5]++; \
					} \
					else { \
						/* It must be 0x00000100 */ \
						TGTPORTSTAT.FctP2IOWcnt[4]++; \
					} \
				} \
			} \
			else { \
				/* It must be 0x00000e00 */ \
				if (cnt & 0x00000800) { \
					TGTPORTSTAT.FctP2IOWcnt[3]++; \
				} \
				else { \
					/* It must be 0x00000600 */ \
					if (cnt & 0x00000400) { \
						TGTPORTSTAT.FctP2IOWcnt[2]++; \
					} \
					else { \
						/* It must be 0x00000200 */ \
						TGTPORTSTAT.FctP2IOWcnt[1]++; \
					} \
				} \
			} \
		} \
		else { \
			/* It must be 0x000001ff */ \
			TGTPORTSTAT.FctP2IOWcnt[0]++; \
		} \
	} \
}

typedef struct emlxs_tgtport_stat
{
	/* IO counters */
	uint64_t	FctP2IOWcnt[MAX_TGTPORT_IOCNT]; /* Writes */
	uint64_t	FctP2IORcnt[MAX_TGTPORT_IOCNT]; /* Reads  */
	uint64_t	FctIOCmdCnt;			/* Other, ie TUR */
	uint64_t	FctCmdReceived;			/* total IOs */
	uint64_t	FctReadBytes;			/* total read bytes */
	uint64_t	FctWriteBytes;			/* total write bytes */

	/* IOCB handling counters */
	uint64_t	FctEvent;	/* FctStray + FctCompleted */
	uint64_t	FctCompleted;	/* FctCmplGood + FctCmplError */
	uint64_t	FctCmplGood;

	uint32_t	FctCmplError;
	uint32_t	FctStray;

	/* Fct event counters */
	uint32_t	FctRcvDropped;
	uint32_t	FctOverQDepth;
	uint32_t	FctOutstandingIO;
	uint32_t	FctFailedPortRegister;
	uint32_t	FctPortRegister;
	uint32_t	FctPortDeregister;

	uint32_t	FctAbortSent;
	uint32_t	FctNoBuffer;
	uint32_t	FctScsiStatusErr;
	uint32_t	FctScsiQfullErr;
	uint32_t	FctScsiResidOver;
	uint32_t	FctScsiResidUnder;
	uint32_t	FctScsiSenseErr;

	uint32_t	FctFiller1;
} emlxs_tgtport_stat_t;

#ifdef FCT_IO_TRACE
#define	MAX_IO_TRACE	67
typedef struct emlxs_iotrace
{
	fct_cmd_t	*fct_cmd;
	uint32_t	xri;
	uint8_t		marker;  /* 0xff */
	uint8_t		trc[MAX_IO_TRACE]; /* trc[0] = index */
} emlxs_iotrace_t;
#endif /* FCT_IO_TRACE */
#endif /* SFCT_SUPPORT */


/*
 *     Port Information Data Structure
 */

typedef struct emlxs_port
{
	struct emlxs_hba	*hba;

	/* Virtual port management */
	uint32_t		vpi;
	uint32_t		flag;
#define	EMLXS_PORT_ENABLE		0x00000001
#define	EMLXS_PORT_BOUND		0x00000002

#define	EMLXS_PORT_REGISTERED		0x00010000	/* VPI registered */
#define	EMLXS_PORT_INIT_VPI_CMPL	0x00020000	/* Init VPI - SLI4 */
#define	EMLXS_PORT_REG_VPI_CMPL		0x00040000	/* Reg VPI - SLI4 */
#define	EMLXS_PORT_IP_UP		0x00000010
#define	EMLXS_PORT_CONFIG		0x00000020
#define	EMLXS_PORT_RESTRICTED		0x00000040	/* Restrict logins */
							/* flag */
#define	EMLXS_PORT_FLOGI_CMPL		0x00000080	/* Fabric login */
							/* completed */

#define	EMLXS_PORT_RESET_MASK		0x0000FFFF	/* Flags to keep */
							/* across hard reset */
#define	EMLXS_PORT_LINKDOWN_MASK	0xFFFFFFFF	/* Flags to keep */
							/* across link reset */

	uint32_t		options;
#define	EMLXS_OPT_RESTRICT		0x00000001	/* Force restricted */
							/* logins */
#define	EMLXS_OPT_UNRESTRICT		0x00000002	/* Force Unrestricted */
							/* logins */
#define	EMLXS_OPT_RESTRICT_MASK		0x00000003


	/* FC world wide names */
	NAME_TYPE		wwnn;
	NAME_TYPE		wwpn;
	char			snn[256];
	char			spn[256];

	/* Common service paramters */
	SERV_PARM		sparam;
	SERV_PARM		fabric_sparam;

	/* fc_id management */
	uint32_t		did;
	uint32_t		prev_did;

	/* support FC_PORT_GET_P2P_INFO only */
	uint32_t		rdid;

	/* FC_AL management */
	uint8_t			lip_type;
	uint8_t			alpa_map[128];

	/* Node management */
	emlxs_node_t		node_base;
	uint32_t		node_count;
	krwlock_t		node_rwlock;
	emlxs_node_t		*node_table[EMLXS_NUM_HASH_QUES];

	/* Polled packet management */
	kcondvar_t		pkt_lock_cv;	/* pkt polling */
	kmutex_t		pkt_lock;	/* pkt polling */

	/* ULP */
	uint32_t		ulp_statec;
	void			(*ulp_statec_cb) ();	/* Port state change */
							/* callback routine */
	void			(*ulp_unsol_cb) ();	/* unsolicited event */
							/* callback routine */
	opaque_t		ulp_handle;

	/* ULP unsolicited buffers */
	kmutex_t		ub_lock;
	uint32_t		ub_count;
	emlxs_unsol_buf_t	*ub_pool;
	uint32_t		ub_post[MAX_CHANNEL];
	uint32_t		ub_timer;

	emlxs_ub_priv_t		*ub_wait_head;	/* Unsolicited IO received */
						/* before link up */
	emlxs_ub_priv_t		*ub_wait_tail;	/* Unsolicited IO received */
						/* before link up */


#ifdef DHCHAP_SUPPORT
	emlxs_port_dhc_t	port_dhc;
#endif	/* DHCHAP_SUPPORT */

	uint16_t		ini_mode;
	uint16_t		tgt_mode;

#ifdef SFCT_SUPPORT

#define	FCT_BUF_COUNT_512		256
#define	FCT_BUF_COUNT_8K		128
#define	FCT_BUF_COUNT_64K		64
#define	FCT_BUF_COUNT_128K		64
#define	FCT_MAX_BUCKETS			16
#define	FCT_DMEM_MAX_BUF_SIZE		131072   /* 128K */
#define	FCT_DMEM_MAX_BUF_SEGMENT	8388608  /* 8M */

	struct emlxs_fct_dmem_bucket dmem_bucket[FCT_MAX_BUCKETS];

	char			cfd_name[24];
	stmf_port_provider_t	*port_provider;
	fct_local_port_t	*fct_port;
	uint32_t		fct_flags;

#define	FCT_STATE_PORT_ONLINE		0x00000001
#define	FCT_STATE_NOT_ACKED		0x00000002
#define	FCT_STATE_LINK_UP		0x00000010
#define	FCT_STATE_LINK_UP_ACKED		0x00000020

	emlxs_tgtport_stat_t	fct_stat;

	/* Used to save fct_cmd for deferred unsol ELS commands, except FLOGI */
	emlxs_buf_t		*fct_wait_head;
	emlxs_buf_t		*fct_wait_tail;

	/* Used to save context for deferred unsol FLOGIs */
	fct_flogi_xchg_t	fx;

#ifdef FCT_IO_TRACE
	emlxs_iotrace_t		*iotrace;
	uint16_t		iotrace_cnt;
	uint16_t		iotrace_index;
	kmutex_t		iotrace_mtx;
#endif /* FCT_IO_TRACE */

#endif /* SFCT_SUPPORT */

#ifdef SAN_DIAG_SUPPORT
	uint8_t			sd_io_latency_state;
#define	SD_INVALID	0x00
#define	SD_COLLECTING	0x01
#define	SD_STOPPED	0x02

	/* SD event management list */
	uint32_t		sd_event_mask;   /* bit-mask */
	emlxs_dfc_event_t	sd_events[MAX_DFC_EVENTS];
#endif
	/* Used for SLI4 */
	uint16_t	outstandingRPIs;
	struct VFIobject *VFIp;
} emlxs_port_t;



/* Host Attn reg */
#define	FC_HA_REG(_hba)		((volatile uint32_t *) \
				    ((_hba)->sli.sli3.ha_reg_addr))

/* Chip Attn reg */
#define	FC_CA_REG(_hba)		((volatile uint32_t *) \
				    ((_hba)->sli.sli3.ca_reg_addr))

/* Host Status reg */
#define	FC_HS_REG(_hba)		((volatile uint32_t *) \
				    ((_hba)->sli.sli3.hs_reg_addr))

/* Host Cntl reg */
#define	FC_HC_REG(_hba)		((volatile uint32_t *) \
				    ((_hba)->sli.sli3.hc_reg_addr))

/* BIU Configuration reg */
#define	FC_BC_REG(_hba)		((volatile uint32_t *) \
				    ((_hba)->sli.sli3.bc_reg_addr))

/* Used by SBUS adapter */
/* TITAN Cntl reg */
#define	FC_SHC_REG(_hba)	((volatile uint32_t *) \
				    ((_hba)->sli.sli3.shc_reg_addr))

/* TITAN Status reg */
#define	FC_SHS_REG(_hba)	((volatile uint32_t *) \
				    ((_hba)->sli.sli3.shs_reg_addr))

/* TITAN Update reg */
#define	FC_SHU_REG(_hba)	((volatile uint32_t *) \
				    ((_hba)->sli.sli3.shu_reg_addr))

/* MPU Semaphore reg */
#define	FC_SEMA_REG(_hba)	((volatile uint32_t *)\
				    ((_hba)->sli.sli4.MPUEPSemaphore_reg_addr))

/* Bootstrap Mailbox Doorbell reg */
#define	FC_MBDB_REG(_hba)	((volatile uint32_t *) \
				    ((_hba)->sli.sli4.MBDB_reg_addr))

/* MQ Doorbell reg */
#define	FC_MQDB_REG(_hba)	((volatile uint32_t *) \
				    ((_hba)->sli.sli4.MQDB_reg_addr))

/* CQ Doorbell reg */
#define	FC_CQDB_REG(_hba)	((volatile uint32_t *) \
				    ((_hba)->sli.sli4.CQDB_reg_addr))

/* WQ Doorbell reg */
#define	FC_WQDB_REG(_hba)	((volatile uint32_t *) \
				    ((_hba)->sli.sli4.WQDB_reg_addr))

/* RQ Doorbell reg */
#define	FC_RQDB_REG(_hba)	((volatile uint32_t *) \
				    ((_hba)->sli.sli4.RQDB_reg_addr))


#define	FC_SLIM2_MAILBOX(_hba)	((MAILBOX *)(_hba)->sli.sli3.slim2.virt)

#define	FC_SLIM1_MAILBOX(_hba)	((MAILBOX *)(_hba)->sli.sli3.slim_addr)

#define	FC_MAILBOX(_hba)	(((_hba)->flag & FC_SLIM2_MODE) ? \
	FC_SLIM2_MAILBOX(_hba) : FC_SLIM1_MAILBOX(_hba))

#define	WRITE_CSR_REG(_hba, _regp, _value) ddi_put32(\
	(_hba)->sli.sli3.csr_acc_handle, (uint32_t *)(_regp), \
	(uint32_t)(_value))

#define	READ_CSR_REG(_hba, _regp) ddi_get32(\
	(_hba)->sli.sli3.csr_acc_handle, (uint32_t *)(_regp))

#define	WRITE_SLIM_ADDR(_hba, _regp, _value) ddi_put32(\
	(_hba)->sli.sli3.slim_acc_handle, (uint32_t *)(_regp), \
	(uint32_t)(_value))

#define	READ_SLIM_ADDR(_hba, _regp) ddi_get32(\
	(_hba)->sli.sli3.slim_acc_handle, (uint32_t *)(_regp))

#define	WRITE_SLIM_COPY(_hba, _bufp, _slimp, _wcnt) ddi_rep_put32(\
	(_hba)->sli.sli3.slim_acc_handle, (uint32_t *)(_bufp), \
	(uint32_t *)(_slimp), (_wcnt), DDI_DEV_AUTOINCR)

#define	READ_SLIM_COPY(_hba, _bufp, _slimp, _wcnt) ddi_rep_get32(\
	(_hba)->sli.sli3.slim_acc_handle, (uint32_t *)(_bufp), \
	(uint32_t *)(_slimp), (_wcnt), DDI_DEV_AUTOINCR)

/* Used by SBUS adapter */
#define	WRITE_SBUS_CSR_REG(_hba, _regp, _value)	ddi_put32(\
	(_hba)->sli.sli3.sbus_csr_handle, (uint32_t *)(_regp), \
	(uint32_t)(_value))

#define	READ_SBUS_CSR_REG(_hba, _regp) ddi_get32(\
	(_hba)->sli.sli3.sbus_csr_handle, (uint32_t *)(_regp))

#define	SBUS_WRITE_FLASH_COPY(_hba, _offset, _value) ddi_put8(\
	(_hba)->sli.sli3.sbus_flash_acc_handle, \
	(uint8_t *)((volatile uint8_t *)(_hba)->sli.sli3.sbus_flash_addr + \
	(_offset)), (uint8_t)(_value))

#define	SBUS_READ_FLASH_COPY(_hba, _offset) ddi_get8(\
	(_hba)->sli.sli3.sbus_flash_acc_handle, \
	(uint8_t *)((volatile uint8_t *)(_hba)->sli.sli3.sbus_flash_addr + \
	(_offset)))

/* SLI4 registers */
#define	WRITE_BAR1_REG(_hba, _regp, _value) ddi_put32(\
	(_hba)->sli.sli4.bar1_acc_handle, (uint32_t *)(_regp), \
	(uint32_t)(_value))

#define	READ_BAR1_REG(_hba, _regp) ddi_get32(\
	(_hba)->sli.sli4.bar1_acc_handle, (uint32_t *)(_regp))

#define	WRITE_BAR2_REG(_hba, _regp, _value) ddi_put32(\
	(_hba)->sli.sli4.bar2_acc_handle, (uint32_t *)(_regp), \
	(uint32_t)(_value))

#define	READ_BAR2_REG(_hba, _regp) ddi_get32(\
	(_hba)->sli.sli4.bar2_acc_handle, (uint32_t *)(_regp))


#define	EMLXS_STATE_CHANGE(_hba, _state)\
{									\
	mutex_enter(&EMLXS_PORT_LOCK);					\
	EMLXS_STATE_CHANGE_LOCKED((_hba), (_state));			\
	mutex_exit(&EMLXS_PORT_LOCK);					\
}

/* Used when EMLXS_PORT_LOCK is already held */
#define	EMLXS_STATE_CHANGE_LOCKED(_hba, _state)			\
{									\
	if ((_hba)->state != (_state))					\
	{								\
		uint32_t _st = _state;					\
		EMLXS_MSGF(EMLXS_CONTEXT,				\
			&emlxs_state_msg, "%s --> %s",			\
			emlxs_ffstate_xlate((_hba)->state),		\
			emlxs_ffstate_xlate(_state));			\
			(_hba)->state = (_state);			\
		if ((_st) == FC_ERROR)					\
		{							\
			(_hba)->flag |= FC_HARDWARE_ERROR;		\
		}							\
	}								\
}

#ifdef FMA_SUPPORT
#define	EMLXS_CHK_ACC_HANDLE(_hba, _acc) \
	if (emlxs_fm_check_acc_handle(_hba, _acc) != DDI_FM_OK) { \
		EMLXS_MSGF(EMLXS_CONTEXT, \
		    &emlxs_invalid_access_handle_msg, NULL); \
	}
#endif  /* FMA_SUPPORT */

/*
 * This is the HBA control area for the adapter
 */

#ifdef MODSYM_SUPPORT

typedef struct emlxs_modsym
{
	ddi_modhandle_t  mod_fctl;	/* For Leadville */

	/* Leadville (fctl) */
	int		(*fc_fca_attach)(dev_info_t *, fc_fca_tran_t *);
	int		(*fc_fca_detach)(dev_info_t *);
	int		(*fc_fca_init)(struct dev_ops *);

#ifdef SFCT_SUPPORT
	uint32_t	fct_modopen;
	uint32_t	reserved;  /* Padding for alignment */

	ddi_modhandle_t  mod_fct;	/* For Comstar */
	ddi_modhandle_t  mod_stmf;	/* For Comstar */

	/* Comstar (fct) */
	void*	(*fct_alloc)(fct_struct_id_t, int, int);
	void	(*fct_free)(void *);
	void*	(*fct_scsi_task_alloc)(void *, uint16_t, uint32_t, uint8_t *,
			uint16_t, uint16_t);
	int	(*fct_register_local_port)(fct_local_port_t *);
	void	(*fct_deregister_local_port)(fct_local_port_t *);
	void	(*fct_handle_event)(fct_local_port_t *, int, uint32_t, caddr_t);
	void	(*fct_post_rcvd_cmd)(fct_cmd_t *, stmf_data_buf_t *);
	void	(*fct_ctl)(void *, int, void *);
	void	(*fct_queue_cmd_for_termination)(fct_cmd_t *, fct_status_t);
	void	(*fct_send_response_done)(fct_cmd_t *, fct_status_t, uint32_t);
	void	(*fct_send_cmd_done)(fct_cmd_t *, fct_status_t, uint32_t);
	void	(*fct_scsi_data_xfer_done)(fct_cmd_t *, stmf_data_buf_t *,
			uint32_t);
	fct_status_t	(*fct_port_shutdown)
				(fct_local_port_t *, uint32_t, char *);
	fct_status_t	(*fct_port_initialize)
				(fct_local_port_t *, uint32_t, char *);
	void		(*fct_cmd_fca_aborted)
				(fct_cmd_t *, fct_status_t, int);
	fct_status_t	(*fct_handle_rcvd_flogi)
				(fct_local_port_t *, fct_flogi_xchg_t *);

	/* Comstar (stmf) */
	void*  (*stmf_alloc)(stmf_struct_id_t, int, int);
	void   (*stmf_free)(void *);
	void	(*stmf_deregister_port_provider) (stmf_port_provider_t *);
	int	(*stmf_register_port_provider) (stmf_port_provider_t *);
#endif /* SFCT_SUPPORT */
} emlxs_modsym_t;
extern emlxs_modsym_t emlxs_modsym;

#define	MODSYM(_f)	emlxs_modsym._f

#else

#define	MODSYM(_f)	_f

#endif /* MODSYM_SUPPORT */



/* defines for resource state */
#define	RESOURCE_FREE		0
#define	RESOURCE_ALLOCATED	1

#define	RESOURCE_FCFI_REG	2
#define	RESOURCE_FCFI_DISC	4
#define	RESOURCE_FCFI_VLAN_ID	8

#define	RESOURCE_VFI_REG	2

#define	RESOURCE_RPI_PAUSED	2

#define	RESOURCE_XRI_RESERVED		2
#define	RESOURCE_XRI_PENDING_IO		4
#define	RESOURCE_XRI_ABORT_INP		8

typedef struct VFIobject
{
	uint16_t	index;
	uint16_t	VFI;
	uint16_t	state;
	uint16_t	outstandingVPIs;
	struct FCFIobject *FCFIp;
} VFIobj_t;

typedef struct RPIobject
{
	uint16_t	index;
	uint16_t	RPI;
	uint16_t	state;
	uint16_t	outstandingXRIs;
	emlxs_port_t	*VPIp;
	uint32_t	did;
	emlxs_node_t	*node;
} RPIobj_t;

typedef struct XRIobject
{
	struct XRIobject *_f;
	struct XRIobject *_b;
	uint16_t	XRI;
	uint16_t	state;
	uint16_t	sge_count;
	uint16_t	iotag;
	MBUF_INFO	SGList;
	RPIobj_t	*RPIp;
	emlxs_buf_t	*sbp;
	uint32_t 	rx_id; /* Used for unsol exchanges */
} XRIobj_t;

typedef struct FCFIobject
{
	uint16_t	index;
	uint16_t	FCFI;
	uint16_t	FCF_index;
	uint16_t	state;
	uint16_t	outstandingVFIs;
	uint16_t	vlan_id;
	uint32_t	EventTag;
	struct VFIobject *fcf_vfi;
	emlxs_port_t	*fcf_vpi;
	struct RPIobject scratch_rpi;
	SERV_PARM	fcf_sparam;
	FCF_RECORD_t	fcf_rec;
} FCFIobj_t;

typedef struct RPIHdrTmplate
{
	uint32_t	Word[16];  /* 64 bytes */
} RPIHdrTmplate_t;

typedef struct EQ_DESC
{
	uint16_t	host_index;
	uint16_t	max_index;
	uint16_t	qid;
	uint16_t	msix_vector;
	kmutex_t	lastwq_lock;
	uint16_t	lastwq;
	MBUF_INFO	addr;
} EQ_DESC_t;

typedef struct CQ_DESC
{
	uint16_t	host_index;
	uint16_t	max_index;
	uint16_t	qid;
	uint16_t	eqid;
	uint16_t	type;
#define	EMLXS_CQ_TYPE_GROUP1	1  /* associated with a MQ and async events */
#define	EMLXS_CQ_TYPE_GROUP2	2  /* associated with a WQ and RQ */
	uint16_t	rsvd;

	MBUF_INFO	addr;
	CHANNEL		*channelp; /* ptr to CHANNEL associated with CQ */

} CQ_DESC_t;

typedef struct WQ_DESC
{
	uint16_t	host_index;
	uint16_t	max_index;
	uint16_t	port_index;
	uint16_t	release_depth;
#define	WQE_RELEASE_DEPTH	(8 * EMLXS_NUM_WQ_PAGES)
	uint16_t	qid;
	uint16_t	cqid;
	MBUF_INFO	addr;
} WQ_DESC_t;

typedef struct RQ_DESC
{
	uint16_t	host_index;
	uint16_t	max_index;
	uint16_t	qid;
	uint16_t	cqid;

	MBUF_INFO	addr;
	MBUF_INFO	rqb[RQ_DEPTH];

	kmutex_t	lock;

} RQ_DESC_t;


typedef struct RXQ_DESC
{
	kmutex_t	lock;
	emlxs_queue_t	active;

} RXQ_DESC_t;


typedef struct MQ_DESC
{
	uint16_t	host_index;
	uint16_t	max_index;
	uint16_t	qid;
	uint16_t	cqid;
	MBUF_INFO	addr;
} MQ_DESC_t;

/* Define the number of queues the driver will be using */
#define	EMLXS_MAX_EQS	EMLXS_MSI_MAX_INTRS
#define	EMLXS_MAX_WQS	EMLXS_MSI_MAX_INTRS
#define	EMLXS_MAX_RQS	2	/* ONLY 1 pair is allowed */
#define	EMLXS_MAX_MQS	1

/* One CQ for each WQ & (RQ pair) plus one for the MQ */
#define	EMLXS_MAX_CQS	(EMLXS_MAX_WQS + (EMLXS_MAX_RQS/2) + 1)

/* The First CQ created is ALWAYS for mbox / event handling */
#define	EMLXS_CQ_MBOX		0

/* The Second CQ created is ALWAYS for unsol rcv handling */
/* At this time we are allowing ONLY 1 pair of RQs */
#define	EMLXS_CQ_RCV		1

/* The remaining CQs are for WQ completions */
#define	EMLXS_CQ_OFFSET_WQ	2


/* FCFI RQ Configuration */
#define	EMLXS_FCFI_RQ0_INDEX	0
#define	EMLXS_FCFI_RQ0_RMASK	0 /* match all */
#define	EMLXS_FCFI_RQ0_RCTL	0 /* match all */
#define	EMLXS_FCFI_RQ0_TMASK	0 /* match all */
#define	EMLXS_FCFI_RQ0_TYPE	0 /* match all */

/* Define the maximum value for a Queue Id */
#define	EMLXS_MAX_EQ_IDS	256
#define	EMLXS_MAX_CQ_IDS	1024
#define	EMLXS_MAX_WQ_IDS	1024
#define	EMLXS_MAX_RQ_IDS	4

#define	EMLXS_RXQ_ELS		0
#define	EMLXS_RXQ_CT		1
#define	EMLXS_MAX_RXQS		2

#define	PCI_CONFIG_SIZE   0x80

typedef struct emlxs_sli3
{
	/* SLIM management */
	MATCHMAP	slim2;

	/* HBQ management */
	uint32_t	hbq_count;	/* Total number of HBQs */
					/* configured */
	HBQ_INIT_t	hbq_table[EMLXS_NUM_HBQ];

	/* Adapter memory management */
	caddr_t		csr_addr;
	caddr_t		slim_addr;
	ddi_acc_handle_t csr_acc_handle;
	ddi_acc_handle_t slim_acc_handle;

	/* SBUS adapter management */
	caddr_t		sbus_flash_addr;	/* Virt addr of R/W */
						/* Flash */
	caddr_t		sbus_core_addr;		/* Virt addr of TITAN */
						/* CORE */
	caddr_t		sbus_csr_addr;		/* Virt addr of TITAN */
						/* CSR */
	ddi_acc_handle_t sbus_flash_acc_handle;
	ddi_acc_handle_t sbus_core_acc_handle;
	ddi_acc_handle_t sbus_csr_handle;

	/* SLI 2/3 Adapter register management */
	uint32_t	*bc_reg_addr;	/* virtual offset for BIU */
					/* config reg */
	uint32_t	*ha_reg_addr;	/* virtual offset for host */
					/* attn reg */
	uint32_t	*hc_reg_addr;	/* virtual offset for host */
					/* ctl reg */
	uint32_t	*ca_reg_addr;	/* virtual offset for FF */
					/* attn reg */
	uint32_t	*hs_reg_addr;	/* virtual offset for */
					/* status reg */
	uint32_t	*shc_reg_addr;	/* virtual offset for SBUS */
					/* Ctrl reg */
	uint32_t	*shs_reg_addr;	/* virtual offset for SBUS */
					/* Status reg */
	uint32_t	*shu_reg_addr;	/* virtual offset for SBUS */
					/* Update reg */
	uint16_t	hgp_ring_offset;
	uint16_t	hgp_hbq_offset;
	uint16_t	iocb_cmd_size;
	uint16_t	iocb_rsp_size;
	uint32_t	hc_copy;	/* local copy of HC register */

	/* Ring management */
	uint32_t	ring_count;
	emlxs_ring_t	ring[MAX_RINGS];
	kmutex_t	ring_cmd_lock[MAX_RINGS];
	uint8_t		ring_masks[4];	/* number of masks/rings used */
	uint8_t		ring_rval[6];
	uint8_t		ring_rmask[6];
	uint8_t		ring_tval[6];
	uint8_t		ring_tmask[6];

	/* Protected by EMLXS_FCTAB_LOCK */
#ifdef EMLXS_SPARC
	MEMSEG		fcp_bpl_seg;
	MATCHMAP	**fcp_bpl_table; /* iotag table for */
					/* bpl buffers */
#endif	/* EMLXS_SPARC */
	uint32_t	mem_bpl_size;
} emlxs_sli3_t;

typedef struct emlxs_sli4
{
	MATCHMAP	bootstrapmb;
	caddr_t		bar1_addr;
	caddr_t		bar2_addr;
	ddi_acc_handle_t bar1_acc_handle;
	ddi_acc_handle_t bar2_acc_handle;

	/* SLI4 Adapter register management */
	uint32_t	*MPUEPSemaphore_reg_addr;
	uint32_t	*MBDB_reg_addr;

	uint32_t	*CQDB_reg_addr;
	uint32_t	*MQDB_reg_addr;
	uint32_t	*WQDB_reg_addr;
	uint32_t	*RQDB_reg_addr;

	uint32_t	flag;
#define	EMLXS_SLI4_INTR_ENABLED		0x1

	uint16_t	XRICount;
	uint16_t	XRIBase;
	uint16_t	RPICount;
	uint16_t	RPIBase;
	uint16_t	VPICount;
	uint16_t	VPIBase;
	uint16_t	VFICount;
	uint16_t	VFIBase;
	uint16_t	FCFICount;

	kmutex_t	id_lock; /* for FCFI, VFI, VPI, RPI, XRI mgmt */
	FCFIobj_t	*FCFIp;
	VFIobj_t	*VFIp;

	/* Save Config Region 23 info */
	tlv_fcoe_t	cfgFCOE;
	tlv_fcfconnectlist_t	cfgFCF;

	MBUF_INFO	slim2;
	MBUF_INFO	dump_region;
#define	EMLXS_DUMP_REGION_SIZE	1024

	RPIobj_t	*RPIp;
	MBUF_INFO	HeaderTmplate;
	XRIobj_t	*XRIp;

	/* Double linked list for available XRIs */
	XRIobj_t	*XRIfree_f;
	XRIobj_t	*XRIfree_b;
	uint32_t	xrif_count;
	uint32_t	mem_sgl_size;

	/* Double linked list for XRIs in use */
	XRIobj_t	*XRIinuse_f;
	XRIobj_t	*XRIinuse_b;
	uint32_t	xria_count;

	EQ_DESC_t	eq[EMLXS_MAX_EQS];
	CQ_DESC_t	cq[EMLXS_MAX_CQS];
	WQ_DESC_t	wq[EMLXS_MAX_WQS];
	RQ_DESC_t	rq[EMLXS_MAX_RQS];
	MQ_DESC_t	mq;

	/* Used to map a queue ID to a queue DESC_t */
	uint16_t	eq_map[EMLXS_MAX_EQ_IDS];
	uint16_t	cq_map[EMLXS_MAX_CQ_IDS];
	uint16_t	wq_map[EMLXS_MAX_WQ_IDS];
	uint16_t	rq_map[EMLXS_MAX_RQ_IDS];

	RXQ_DESC_t	rxq[EMLXS_MAX_RXQS];

	uint32_t	ue_mask_lo;
	uint32_t	ue_mask_hi;
} emlxs_sli4_t;


typedef struct emlxs_sli_api
{
	int		(*sli_map_hdw)();
	void		(*sli_unmap_hdw)();
	int32_t		(*sli_online)();
	void		(*sli_offline)();
	uint32_t	(*sli_hba_reset)();
	void		(*sli_hba_kill)();
	void		(*sli_issue_iocb_cmd)();
	uint32_t	(*sli_issue_mbox_cmd)();
	uint32_t	(*sli_prep_fct_iocb)();
	uint32_t	(*sli_prep_fcp_iocb)();
	uint32_t	(*sli_prep_ip_iocb)();
	uint32_t	(*sli_prep_els_iocb)();
	uint32_t	(*sli_prep_ct_iocb)();
	void		(*sli_poll_intr)();
	int32_t		(*sli_intx_intr)();
	uint32_t	(*sli_msi_intr)();
	void		(*sli_disable_intr)();
	void		(*sli_timer)();
	void		(*sli_poll_erratt)();

} emlxs_sli_api_t;


typedef struct emlxs_hba
{
	dev_info_t	*dip;
	int32_t		emlxinst;
	int32_t		ddiinst;
	uint8_t		pci_function_number;
	uint8_t		pci_device_number;
	uint8_t		pci_bus_number;
#ifdef FMA_SUPPORT
	int32_t		fm_caps;	/* FMA capabilities */
#endif	/* FMA_SUPPORT */
	fc_fca_tran_t	*fca_tran;

	/* DMA attributes */
	ddi_dma_attr_t	dma_attr;
	ddi_dma_attr_t	dma_attr_ro;
	ddi_dma_attr_t	dma_attr_1sg;
	ddi_dma_attr_t	dma_attr_fcip_rsp;

	/* HBA Info */
	emlxs_model_t	model_info;
	emlxs_vpd_t	vpd;	/* vital product data */
	NAME_TYPE	wwnn;
	NAME_TYPE	wwpn;
	char		snn[256];
	char		spn[256];
	PROG_ID		load_list[MAX_LOAD_ENTRY];
	WAKE_UP_PARMS	wakeup_parms;
	uint32_t	max_nodes;
	uint32_t	io_throttle;
	uint32_t	io_active;
	uint32_t	bus_type;
#define	PCI_FC  	0
#define	SBUS_FC		1

	/* Link management */
	uint32_t	link_event_tag;
	uint8_t		topology;
	uint8_t		linkspeed;
	uint16_t	qos_linkspeed;
	uint32_t	linkup_wait_flag;
	kcondvar_t	linkup_lock_cv;
	kmutex_t	linkup_lock;

	/* Memory Pool management */
	emlxs_memseg_t	memseg[FC_MAX_SEG];	/* memory for buffer */
							/* structures */
	kmutex_t	memget_lock;	/* locks all memory pools get */
	kmutex_t	memput_lock;	/* locks all memory pools put */

	/* Fibre Channel Service Parameters */
	SERV_PARM	sparam;
	uint32_t	fc_edtov;	/* E_D_TOV timer value */
	uint32_t	fc_arbtov;	/* ARB_TOV timer value */
	uint32_t	fc_ratov;	/* R_A_TOV timer value */
	uint32_t	fc_rttov;	/* R_T_TOV timer value */
	uint32_t	fc_altov;	/* AL_TOV timer value */
	uint32_t	fc_crtov;	/* C_R_TOV timer value */
	uint32_t	fc_citov;	/* C_I_TOV timer value */

	/* Adapter State management */
	int32_t		state;
#define	FC_ERROR		0x01	/* Adapter shutdown */
#define	FC_KILLED		0x02	/* Adapter interlocked/killed */
#define	FC_WARM_START		0x03	/* Adapter reset, but not restarted */
#define	FC_INIT_START		0x10	/* Adapter restarted */
#define	FC_INIT_NVPARAMS	0x11
#define	FC_INIT_REV		0x12
#define	FC_INIT_CFGPORT		0x13
#define	FC_INIT_CFGRING		0x14
#define	FC_INIT_INITLINK	0x15
#define	FC_LINK_DOWN		0x20
#define	FC_LINK_DOWN_PERSIST	0x21
#define	FC_LINK_UP		0x30
#define	FC_CLEAR_LA		0x31
#define	FC_READY		0x40

	uint32_t	flag;
#define	FC_ONLINING_MODE	0x00000001
#define	FC_ONLINE_MODE		0x00000002
#define	FC_OFFLINING_MODE	0x00000004
#define	FC_OFFLINE_MODE		0x00000008

#define	FC_NPIV_ENABLED		0x00000010	/* NPIV enabled on adapter    */
#define	FC_NPIV_SUPPORTED	0x00000020	/* NPIV supported on fabric   */
#define	FC_NPIV_UNSUPPORTED	0x00000040	/* NPIV unsupported on fabric */
#define	FC_NPIV_LINKUP		0x00000100	/* NPIV enabled, supported, */
						/* and link is ready */
#define	FC_NPIV_DELAY_REQUIRED	0x00000200	/* Delay issuing FLOGI/FDISC */
						/* and NameServer cmds */

#define	FC_BOOTSTRAPMB_INIT	0x00000400
#define	FC_FIP_SUPPORTED	0x00000800	/* FIP supported */

#define	FC_FABRIC_ATTACHED	0x00001000
#define	FC_PT_TO_PT		0x00002000
#define	FC_BYPASSED_MODE	0x00004000
#define	FC_MENLO_MODE		0x00008000	/* Menlo maintenance mode */

#define	FC_DUMP_SAFE		0x00010000	/* Safe to DUMP */
#define	FC_DUMP_ACTIVE		0x00020000	/* DUMP in progress */

#define	FC_SLIM2_MODE		0x00100000	/* SLIM in host memory */
#define	FC_INTERLOCKED		0x00200000
#define	FC_HBQ_ENABLED		0x00400000
#define	FC_ASYNC_EVENTS		0x00800000

#define	FC_ILB_MODE		0x01000000
#define	FC_ELB_MODE		0x02000000
#define	FC_LOOPBACK_MODE	0x03000000	/* Loopback Mode Mask */
#define	FC_DUMP			0x04000000	/* DUMP in progress */
#define	FC_SHUTDOWN		0x08000000	/* SHUTDOWN in progress */

#define	FC_OVERTEMP_EVENT	0x10000000	/* FC_ERROR reason: */
						/* over temperature event */
#define	FC_MBOX_TIMEOUT		0x20000000	/* FC_ERROR reason: */
						/* mailbox timeout event */
#define	FC_DMA_CHECK_ERROR	0x40000000	/* Shared memory (slim,..) */
						/* DMA handle went bad */
#define	FC_HARDWARE_ERROR	0x80000000	/* FC_ERROR state triggered */

#define	FC_RESET_MASK		0x00030C1F	/* Bits to protect during */
						/* a hard reset */
#define	FC_LINKDOWN_MASK	0xFFF30C1F	/* Bits to protect during */
						/* a linkdown */

	uint32_t fw_timer;
	uint32_t fw_flag;
#define	FW_UPDATE_NEEDED	0x00000001
#define	FW_UPDATE_KERNEL	0x00000002

	uint32_t temperature;			/* Last reported temperature */

	/* SBUS adapter management */
	caddr_t		sbus_pci_addr;		/* Virt addr of TITAN */
						/* pci config */
	ddi_acc_handle_t sbus_pci_handle;

	/* PCI BUS adapter management */
	caddr_t		pci_addr;
	ddi_acc_handle_t pci_acc_handle;

	uint32_t	sli_mode;
#define	EMLXS_HBA_SLI1_MODE	1
#define	EMLXS_HBA_SLI2_MODE	2
#define	EMLXS_HBA_SLI3_MODE	3
#define	EMLXS_HBA_SLI4_MODE	4

	/* SLI private data */
	union {
		emlxs_sli3_t sli3;
		emlxs_sli4_t sli4;
	} sli;

	/* SLI API entry point routines */
	emlxs_sli_api_t sli_api;

	uint32_t	io_poll_count;	/* Number of poll commands */
					/* in progress */

	/* IO Completion management */
	uint32_t	iodone_count;	/* Number of IO's on done Q */
	/* Protected by EMLXS_PORT_LOCK  */
	emlxs_buf_t	*iodone_list;	/* fc_packet being deferred */
	emlxs_buf_t	*iodone_tail;	/* fc_packet being deferred */
	emlxs_thread_t	iodone_thread;
	emlxs_thread_t	*spawn_thread_head;
	emlxs_thread_t	*spawn_thread_tail;
	kmutex_t	spawn_lock;
	uint32_t	spawn_open;

	/* IO Channel management */
	int32_t		chan_count;
	emlxs_channel_t	chan[MAX_CHANNEL];
	kmutex_t	channel_tx_lock;
	uint8_t		channel_fcp;	/* Default channel to use for FCP IO */
#define	CHANNEL_FCT channel_fcp
	uint8_t		channel_ip;	/* Default channel to use for IP IO */
	uint8_t		channel_els;	/* Default channel to use for ELS IO */
	uint8_t		channel_ct;	/* Default channel to use for CT IO */

	/* IOTag management */
	emlxs_buf_t	**fc_table;	/* sc_buf pointers indexed by */
					/* iotag */
	uint16_t	fc_iotag;	/* used to identify I/Os */
	uint16_t	fc_oor_iotag;	/* OutOfRange (fc_table) iotags */
					/* typically used for Abort/close */
#define	EMLXS_MAX_ABORT_TAG	0x7fff
	uint16_t	max_iotag;	/* ALL IOCBs except aborts */
	kmutex_t	iotag_lock;
	uint32_t	io_count;		/* No of IO holding */
						/* regular iotag */
	uint32_t	channel_tx_count;	/* No of IO on tx Q */

	/* Mailbox Management */
	uint32_t	mbox_queue_flag;
	emlxs_queue_t	mbox_queue;
	uint32_t	*mbox_mqe;	/* active mbox mqe */
	uint8_t		*mbox_mbq;	/* active MAILBOXQ */
	kcondvar_t	mbox_lock_cv;	/* MBX_SLEEP */
	kmutex_t	mbox_lock;	/* MBX_SLEEP */
	uint32_t	mbox_timer;

	/* Interrupt management */
	void		*intr_arg;
	uint32_t	intr_unclaimed;
	uint32_t	intr_autoClear;
	uint32_t	intr_flags;
#define	EMLXS_INTX_INITED	0x0001
#define	EMLXS_INTX_ADDED	0x0002
#define	EMLXS_MSI_ENABLED	0x0010
#define	EMLXS_MSI_INITED	0x0020
#define	EMLXS_MSI_ADDED		0x0040
#define	EMLXS_INTR_INITED	(EMLXS_INTX_INITED|EMLXS_MSI_INITED)
#define	EMLXS_INTR_ADDED	(EMLXS_INTX_ADDED|EMLXS_MSI_ADDED)

#ifdef MSI_SUPPORT
	ddi_intr_handle_t *intr_htable;
	uint32_t	*intr_pri;
	int32_t		*intr_cap;
	uint32_t	intr_count;
	uint32_t	intr_type;
	uint32_t	intr_cond;
	uint32_t	intr_map[EMLXS_MSI_MAX_INTRS];
	uint32_t	intr_mask;
	uint32_t	msi_cap_offset;
#define	MSI_CAP_ID	0x05

	uint32_t	msix_cap_offset;
#define	MSIX_CAP_ID	0x11

	kmutex_t	intr_lock[EMLXS_MSI_MAX_INTRS];
#endif	/* MSI_SUPPORT */

	uint32_t	heartbeat_timer;
	uint32_t	heartbeat_flag;
	uint32_t	heartbeat_active;

	/* IOCTL management */
	kmutex_t	ioctl_lock;
	uint32_t	ioctl_flags;
#define	EMLXS_OPEN		0x00000001
#define	EMLXS_OPEN_EXCLUSIVE	0x00000002

	/* Timer management */
	kcondvar_t	timer_lock_cv;
	kmutex_t	timer_lock;
	timeout_id_t	timer_id;
	uint32_t	timer_tics;
	uint32_t	timer_flags;
#define	EMLXS_TIMER_STARTED	0x0000001
#define	EMLXS_TIMER_BUSY	0x0000002
#define	EMLXS_TIMER_KILL	0x0000004
#define	EMLXS_TIMER_ENDED	0x0000008

	/* Misc Timers */
	uint32_t	linkup_timer;
	uint32_t	discovery_timer;
	uint32_t	pkt_timer;

	/* Power Management */
	uint32_t	pm_state;
	/* pm_state */
#define	EMLXS_PM_IN_ATTACH	0x00000001
#define	EMLXS_PM_IN_DETACH	0x00000002
#define	EMLXS_PM_IN_SOL_CB	0x00000010
#define	EMLXS_PM_IN_UNSOL_CB	0x00000020
#define	EMLXS_PM_IN_LINK_RESET	0x00000100
#define	EMLXS_PM_IN_HARD_RESET	0x00000200
#define	EMLXS_PM_SUSPENDED	0x01000000

	uint32_t	pm_level;
	/* pm_level */
#define	EMLXS_PM_ADAPTER_DOWN	0
#define	EMLXS_PM_ADAPTER_UP	1

	uint32_t	pm_busy;
	kmutex_t	pm_lock;
	uint8_t		pm_config[PCI_CONFIG_SIZE];
#ifdef IDLE_TIMER
	uint32_t	pm_idle_timer;
	uint32_t	pm_active;	/* Only used by timer */
#endif	/* IDLE_TIMER */

	/* Loopback management */
	uint32_t	loopback_tics;
	void		*loopback_pkt;

	/* Event management */
	emlxs_event_queue_t event_queue;
	uint32_t	event_mask;
	uint32_t	event_timer;
	emlxs_dfc_event_t dfc_event[MAX_DFC_EVENTS];
	emlxs_hba_event_t hba_event;

	/* Parameter management */
	emlxs_config_t	config[NUM_CFG_PARAM];

	/* Driver stat management */
	kstat_t		*kstat;
	emlxs_stats_t	stats;

	/* Log management */
	emlxs_msg_log_t	log;

	/* Port managment */
	uint32_t	vpi_base;
	uint32_t	vpi_max;
	uint32_t	vpi_high;
	uint32_t	num_of_ports;

	kmutex_t	port_lock;	/* locks port, nodes, rings */
	emlxs_port_t	port[MAX_VPORTS + 1];	/* port specific info */
						/* Last one is for */
						/* NPIV ready test */

#ifdef DHCHAP_SUPPORT
	kmutex_t	dhc_lock;
	kmutex_t	auth_lock;
	emlxs_auth_cfg_t	auth_cfg;	/* Default auth_cfg. */
						/* Points to list of entries. */
						/* Protected by auth_lock */
	uint32_t	auth_cfg_count;
	emlxs_auth_key_t	auth_key;	/* Default auth_key. */
						/* Points to list of entries. */
						/* Protected by auth_lock */
	uint32_t	auth_key_count;
	uint32_t	rdn_flag;
#endif	/* DHCHAP_SUPPORT */

	uint16_t	ini_mode;
	uint16_t	tgt_mode;

#ifdef TEST_SUPPORT
	uint32_t	underrun_counter;
#endif /* TEST_SUPPORT */

#ifdef MODFW_SUPPORT
	ddi_modhandle_t	fw_modhandle;
#endif /* MODFW_SUPPORT */

#ifdef DUMP_SUPPORT
	emlxs_file_t	dump_txtfile;
	emlxs_file_t	dump_dmpfile;
	emlxs_file_t	dump_ceefile;
	kmutex_t	dump_lock;
#define	EMLXS_DUMP_LOCK		hba->dump_lock
#define	EMLXS_TXT_FILE		1
#define	EMLXS_DMP_FILE		2
#define	EMLXS_CEE_FILE		3

#define	EMLXS_DRV_DUMP		0
#define	EMLXS_TEMP_DUMP		1
#define	EMLXS_USER_DUMP		2

#endif /* DUMP_SUPPORT */

} emlxs_hba_t;

#define	EMLXS_SLI_MAP_HDW 		(hba->sli_api.sli_map_hdw)
#define	EMLXS_SLI_UNMAP_HDW		(hba->sli_api.sli_unmap_hdw)
#define	EMLXS_SLI_ONLINE		(hba->sli_api.sli_online)
#define	EMLXS_SLI_OFFLINE		(hba->sli_api.sli_offline)
#define	EMLXS_SLI_HBA_RESET		(hba->sli_api.sli_hba_reset)
#define	EMLXS_SLI_HBA_KILL		(hba->sli_api.sli_hba_kill)
#define	EMLXS_SLI_ISSUE_IOCB_CMD	(hba->sli_api.sli_issue_iocb_cmd)
#define	EMLXS_SLI_ISSUE_MBOX_CMD	(hba->sli_api.sli_issue_mbox_cmd)
#define	EMLXS_SLI_PREP_FCT_IOCB		(hba->sli_api.sli_prep_fct_iocb)
#define	EMLXS_SLI_PREP_FCP_IOCB		(hba->sli_api.sli_prep_fcp_iocb)
#define	EMLXS_SLI_PREP_IP_IOCB		(hba->sli_api.sli_prep_ip_iocb)
#define	EMLXS_SLI_PREP_ELS_IOCB		(hba->sli_api.sli_prep_els_iocb)
#define	EMLXS_SLI_PREP_CT_IOCB		(hba->sli_api.sli_prep_ct_iocb)
#define	EMLXS_SLI_POLL_INTR		(hba->sli_api.sli_poll_intr)
#define	EMLXS_SLI_INTX_INTR		(hba->sli_api.sli_intx_intr)
#define	EMLXS_SLI_MSI_INTR		(hba->sli_api.sli_msi_intr)
#define	EMLXS_SLI_DISABLE_INTR		(hba->sli_api.sli_disable_intr)
#define	EMLXS_SLI_TIMER			(hba->sli_api.sli_timer)
#define	EMLXS_SLI_POLL_ERRATT		(hba->sli_api.sli_poll_erratt)

#define	EMLXS_HBA_T  1  /* flag emlxs_hba_t is already typedefed */

#ifdef MSI_SUPPORT
#define	EMLXS_INTR_INIT(_hba, _m)		emlxs_msi_init(_hba, _m)
#define	EMLXS_INTR_UNINIT(_hba)			emlxs_msi_uninit(_hba)
#define	EMLXS_INTR_ADD(_hba)			emlxs_msi_add(_hba)
#define	EMLXS_INTR_REMOVE(_hba)			emlxs_msi_remove(_hba)
#else
#define	EMLXS_INTR_INIT(_hba, _m)		emlxs_intx_init(_hba, _m)
#define	EMLXS_INTR_UNINIT(_hba)			emlxs_intx_uninit(_hba)
#define	EMLXS_INTR_ADD(_hba)			emlxs_intx_add(_hba)
#define	EMLXS_INTR_REMOVE(_hba)			emlxs_intx_remove(_hba)
#endif	/* MSI_SUPPORT */


/* Power Management Component */
#define	EMLXS_PM_ADAPTER	0


#define	DRV_TIME	(uint32_t)(ddi_get_time() - emlxs_device.drv_timestamp)

#define	HBA			port->hba
#define	PPORT			hba->port[0]
#define	VPORT(x)		hba->port[x]
#define	EMLXS_TIMER_LOCK	hba->timer_lock
#define	VPD			hba->vpd
#define	CFG			hba->config[0]
#define	LOG			hba->log
#define	EVENTQ			hba->event_queue
#define	EMLXS_MBOX_LOCK		hba->mbox_lock
#define	EMLXS_MBOX_CV		hba->mbox_lock_cv
#define	EMLXS_LINKUP_LOCK	hba->linkup_lock
#define	EMLXS_LINKUP_CV		hba->linkup_lock_cv
#define	EMLXS_TX_CHANNEL_LOCK	hba->channel_tx_lock	/* ring txq lock */
#define	EMLXS_MEMGET_LOCK	hba->memget_lock	/* mempool get lock */
#define	EMLXS_MEMPUT_LOCK	hba->memput_lock	/* mempool put lock */
#define	EMLXS_IOCTL_LOCK	hba->ioctl_lock		/* ioctl lock */
#define	EMLXS_SPAWN_LOCK	hba->spawn_lock		/* spawn lock */
#define	EMLXS_PM_LOCK		hba->pm_lock		/* pm lock */
#define	HBASTATS		hba->stats
#define	EMLXS_CMD_RING_LOCK(n)	hba->sli.sli3.ring_cmd_lock[n]
#define	EMLXS_FCTAB_LOCK	hba->iotag_lock
#define	EMLXS_PORT_LOCK		hba->port_lock		/* locks ports, */
							/* nodes, rings */
#define	EMLXS_INTR_LOCK(_id)	hba->intr_lock[_id]	/* locks intr threads */

#define	EMLXS_PKT_LOCK		port->pkt_lock		/* used for pkt */
							/* polling */
#define	EMLXS_PKT_CV		port->pkt_lock_cv	/* Used for pkt */
							/* polling */
#define	EMLXS_UB_LOCK		port->ub_lock		/* locks unsolicited */
							/* buffer pool */

/* These SWAPs will swap on any platform */
#define	SWAP32_BUFFER(_b, _c)		emlxs_swap32_buffer(_b, _c)
#define	SWAP32_BCOPY(_s, _d, _c)	emlxs_swap32_bcopy(_s, _d, _c)

#define	SWAP64(_x)	((((uint64_t)(_x) & 0xFF)<<56) | \
			    (((uint64_t)(_x) & 0xFF00)<<40) | \
			    (((uint64_t)(_x) & 0xFF0000)<<24) | \
			    (((uint64_t)(_x) & 0xFF000000)<<8) | \
			    (((uint64_t)(_x) & 0xFF00000000)>>8) | \
			    (((uint64_t)(_x) & 0xFF0000000000)>>24) | \
			    (((uint64_t)(_x) & 0xFF000000000000)>>40) | \
			    (((uint64_t)(_x) & 0xFF00000000000000)>>56))

#define	SWAP32(_x)	((((uint32_t)(_x) & 0xFF)<<24) | \
			    (((uint32_t)(_x) & 0xFF00)<<8) | \
			    (((uint32_t)(_x) & 0xFF0000)>>8) | \
			    (((uint32_t)(_x) & 0xFF000000)>>24))

#define	SWAP16(_x)	((((uint16_t)(_x) & 0xFF)<<8) | \
			    (((uint16_t)(_x) & 0xFF00)>>8))

#define	SWAP24_LO(_x)	((((uint32_t)(_x) & 0xFF)<<16) | \
			    ((uint32_t)(_x) & 0xFF00FF00) | \
			    (((uint32_t)(_x) & 0x00FF0000)>>16))

#define	SWAP24_HI(_x)	(((uint32_t)(_x) & 0x00FF00FF) | \
			    (((uint32_t)(_x) & 0x0000FF00)<<16) | \
			    (((uint32_t)(_x) & 0xFF000000)>>16))

/* These LE_SWAPs will only swap on a LE platform */
#ifdef EMLXS_LITTLE_ENDIAN
#define	LE_SWAP32_BUFFER(_b, _c)	SWAP32_BUFFER(_b, _c)
#define	LE_SWAP32_BCOPY(_s, _d, _c)	SWAP32_BCOPY(_s, _d, _c)
#define	LE_SWAP64(_x)			SWAP64(_x)
#define	LE_SWAP32(_x)			SWAP32(_x)
#define	LE_SWAP16(_x)			SWAP16(_x)
#define	LE_SWAP24_LO(_x)		SWAP24_LO(X)
#define	LE_SWAP24_HI(_x)		SWAP24_HI(X)

#if (EMLXS_MODREVX == EMLXS_MODREV2X)
#undef	LE_SWAP24_LO
#define	LE_SWAP24_LO(_x)		(_x)
#undef	LE_SWAP24_HI
#define	LE_SWAP24_HI(_x)		(_x)
#endif	/* EMLXS_MODREV2X */

#else /* BIG ENDIAN */
#define	LE_SWAP32_BUFFER(_b, _c)
#define	LE_SWAP32_BCOPY(_s, _d, _c)	bcopy(_s, _d, _c)
#define	LE_SWAP64(_x)			(_x)
#define	LE_SWAP32(_x)			(_x)
#define	LE_SWAP16(_x)			(_x)
#define	LE_SWAP24_LO(_x)		(_x)
#define	LE_SWAP24_HI(_x)		(_x)
#endif /* EMLXS_LITTLE_ENDIAN */

/* These BE_SWAPs will only swap on a BE platform */
#ifdef EMLXS_BIG_ENDIAN
#define	BE_SWAP32_BUFFER(_b, _c)	SWAP32_BUFFER(_b, _c)
#define	BE_SWAP32_BCOPY(_s, _d, _c)	SWAP32_BCOPY(_s, _d, _c)
#define	BE_SWAP64(_x)			SWAP64(_x)
#define	BE_SWAP32(_x)			SWAP32(_x)
#define	BE_SWAP16(_x)			SWAP16(_x)
#else /* LITTLE ENDIAN */
#define	BE_SWAP32_BUFFER(_b, _c)
#define	BE_SWAP32_BCOPY(_s, _d, _c)	bcopy(_s, _d, _c)
#define	BE_SWAP64(_x)			(_x)
#define	BE_SWAP32(_x)			(_x)
#define	BE_SWAP16(_x)			(_x)
#endif /* EMLXS_BIG_ENDIAN */

#ifdef	__cplusplus
}
#endif

#endif	/* _EMLXS_FC_H */
 
 
Close
loading
Please Confirm
Close