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

#ifndef	_SYS_FIBRE_CHANNEL_ULP_FCIP_H
#define	_SYS_FIBRE_CHANNEL_ULP_FCIP_H

#pragma ident	"@(#)fcip.h	1.6	00/08/18 SMI"

/*
 * Header file for FCIP: IP/ARP ULP over FibreChannel
 */

#include <sys/kstat.h>
#include <sys/socket.h>
#include <netinet/arp.h>

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * Definitions for module_info.
 */
#define		FCIPIDNUM	(77)		/* module ID number */
#define		FCIPNAME	"fcip"		/* module name */
#define		FCIPMINPSZ	(0)		/* min packet size */
#define		FCIPMAXPSZ	1514		/* max packet size */
#define		FCIPHIWAT	(32 * 1024)	/* hi-water mark */
#define		FCIPLOWAT	(1)		/* lo-water mark */
#define		FCIPMTU		ETHERMTU		/* MTU of network */
#define		FCIPMIN		(ETHERMIN + sizeof (llc_snap_hdr_t) + \
				sizeof (fcph_network_hdr_t))

/*
 * Per-Stream instance state information.
 *
 * Each instance is dynamically allocated at open() and free'd
 * at close().  Each per-Stream instance points to at most one
 * per-device structure using the sl_fcip field.  All instances
 * are threaded together into one list of active instances
 * ordered on minor device number.
 */

#define	NMCHASH			64	/* no. of multicast hash buckets */
#define	INIT_BUCKET_SIZE	16	/* Initial hash bucket size */

#define	FCIP_MAX_MTU_SIZE	65280	/* theoritcal max for now */

struct	fcipstr {
	struct fcipstr	*sl_nextp;	/* next in list */
	queue_t		*sl_rq;		/* pointer to our rq */
	struct fcip 	*sl_fcip;	/* attached device */
	t_uscalar_t	sl_state;	/* current DL state */
	t_uscalar_t	sl_sap;		/* bound sap */
	uint32_t	sl_flags;	/* misc. flags */
	uint32_t	sl_minor;	/* minor device number */
	la_wwn_t	*sl_mctab[NMCHASH]; /* multicast addr table */
	uint_t		sl_mccount[NMCHASH]; /* # valid addr in mctab[i] */
	uint_t		sl_mcsize[NMCHASH]; /* size of mctab[i] */
	ushort_t	sl_ladrf[4];	/* Multicast filter bits */
	ushort_t	sl_ladrf_refcnt[64]; /* ref. count for filter bits */
	kmutex_t	sl_lock;	/* protect this structure */
};

/* per-stream flags */
#define	FCIP_SLFAST	0x01	/* "M_DATA fastpath" mode */
#define	FCIP_SLRAW	0x02	/* M_DATA plain raw mode */
#define	FCIP_SLALLPHYS	0x04	/* "promiscuous mode" */
#define	FCIP_SLALLMULTI	0x08	/* enable all multicast addresses */
#define	FCIP_SLALLSAP	0x10	/* enable all ether type values */

/*
 * Maximum # of multicast addresses per Stream.
 */
#define	FCIPMAXMC	64
#define	FCIPMCALLOC	(FCIPMAXMC * sizeof (la_wwn_t))

/*
 * Full DLSAP address length (in struct dladdr format).
 */
#define	FCIPADDRL	(sizeof (ushort_t) + sizeof (struct ether_addr))


typedef struct fcip_port_info {
	struct fcip_port_info	*fcipp_next;	/* next port in list */
	opaque_t		*fcipp_handle;
	struct modlinkage	fcipp_linkage;
	dev_info_t		*fcipp_dip;
	uint32_t		fcipp_topology;
	uint32_t		fcipp_pstate;
	la_wwn_t		fcipp_pwwn;
	la_wwn_t		fcipp_nwwn;
	uchar_t			fcipp_naa;	/* This port's NAA */
	int			fcipp_fca_pkt_size;
	ddi_dma_attr_t		fcipp_fca_dma_attr;
	ddi_device_acc_attr_t	fcipp_fca_acc_attr;
	fc_portid_t		fcipp_sid;	/* this port's S_ID */
	struct fcip		*fcipp_fcip;	/* this port's fcip struct */
} fcip_port_info_t;

#define	FCIP_SUCCESS		(0)
#define	FCIP_FAILURE		(1)
#define	FCIP_FARP_TIMEOUT	10	/* seconds */
#define	FCIP_WAIT_CMDS		5	/* 5 retries at 1 sec between retries */

/*
 * Num ports supported for soft_state_init
 */
#define	FCIP_NUM_INSTANCES	5

#define	FCIP_UB_NBUFS		60
#define	FCIP_UB_SIZE		2048
#define	FCIP_UB_DECREMENT	4
#define	FCIP_UB_MINBUFS		8
#define	FCIP_INIT_DELAY		10000000	/* 10 seconds */
#define	FCIP_PKT_TTL		120		/* 120 secs */
#define	FCIP_TIMEOUT_INTERVAL	10		/* 10 seconds */
#define	FCIP_OFFLINE_TIMEOUT	60		/* 60 seconds */
#define	FCIP_MAX_PORTS		127		/* for private loop/pt_pt */
#define	FCIP_RTE_TIMEOUT	60		/* 60 seconds */

/*
 * Add fcip specific port_map flags for broadcast entry
 */
#define	FCIP_PORT_DEVICE_IGNORE		(-3)


#define	ETHERSTRL		((2 * ETHERADDRL) + 1)
/*
 * Hash lists
 */
#define	FCIP_RT_HASH_ELEMS	32
#define	FCIP_DEST_HASH_ELEMS	16


#if defined(_BIT_FIELDS_LTOH)
#define	FCIP_RT_HASH(x)		((x[0] + x[1] + x[2] + x[3] + x[4] + x[5]) \
				& (FCIP_RT_HASH_ELEMS - 1))

#define	FCIP_DEST_HASH(x)	((x[0] + x[1] + x[2] + x[3] + x[4] + x[5]) \
				& (FCIP_DEST_HASH_ELEMS - 1))
#elif defined(_BIT_FIELDS_HTOL)
#define	FCIP_RT_HASH(x)		((x[2] + x[3] + x[4] + x[5] + x[6] + x[7]) \
				& (FCIP_RT_HASH_ELEMS - 1))

#define	FCIP_DEST_HASH(x)	((x[2] + x[3] + x[4] + x[5] + x[6] + x[7]) \
				& (FCIP_DEST_HASH_ELEMS - 1))
#endif

#define	FCIP_HDR_SIZE		8
#define	FCIP_RT_INVALID		(-1)
#define	FCIP_RT_RETIRED		(-2)
#define	FCIP_RT_SUSPENDED	(-3)

#define	FCIP_RTE_UNAVAIL(state)	(((state) == FCIP_RT_INVALID) || \
					((state) == FCIP_RT_RETIRED) || \
					((state) == FCIP_RT_SUSPENDED)) ? 1 : 0

/*
 * Taskq related
 */
#define	FCIP_NUM_THREADS	4
#define	FCIP_MIN_TASKS		12
#define	FCIP_MAX_TASKS		128


/*
 * Per-Device instance state information.
 *
 * Each instance is dynamically allocated on first attach.
 */
struct fcip {
	dev_info_t		*fcip_dip;	/* parent's dev_info */
	int			fcip_instance;	/* parent's instance */
	struct fcip		*fcip_sibling;	/* The other FCA port */
	uint32_t		fcip_flags;	/* misc. flags */
	uint32_t		fcip_port_state; /* Link State */
	fcip_port_info_t	*fcip_port_info; /* info about port */
	struct fcip		*fcip_next;

	struct fcip_pkt		*fcip_farp_pkt;	/* Packet for FARP ELS */
	struct la_els_farp	*fcip_farp_resp;	/* FARP REPLY pkt */
	struct fcip_inarp	*fcip_inarp_resp;	/* InARP REPLY pkt */

#ifdef	INARP_SUPPORT
	struct farp_resp_list	*fcip_farp_resp;	/* FARP REPLY pkts */
	struct inarp_resp_list	*fcip_inarp_resp;	/* InARP REPLY pkts */
#endif

	kcondvar_t		fcip_farp_cv;	/* For perport serialization */
	kmutex_t		fcip_farp_mutex; /* To serialize FARP req */
	kmutex_t		fcip_mutex;	/* protect this structure */
	kmutex_t		fcip_ub_mutex;	/* protect the unsol bufs */

	uint32_t		fcip_ub_nbufs;	/* no. of Unsol. Buffers */
	uint32_t		fcip_ub_upstream; /* no ubufs in use */
	kcondvar_t		fcip_ub_cv;
	timeout_id_t		fcip_timeout_id; /* for timeout routine */
	uint32_t		fcip_timeout_ticks;
	uint32_t		fcip_mark_offline;

	uint64_t		*fcip_ub_tokens; /* unsol buf tokens */
	kmutex_t		fcip_dest_mutex; /* dest table lock */
	struct fcip_dest	*fcip_dest[FCIP_DEST_HASH_ELEMS];
					/* hash table of remote dest. ports */
	kmutex_t		fcip_rt_mutex;	/* routing table lock */
	struct fcip_routing_table *fcip_rtable[FCIP_RT_HASH_ELEMS];
					/* hash table of WWN to D_ID maps */

	int			fcip_intr_flag;	/* init. flag for fcipintr() */
	uint32_t		fcip_addrflags;	/* type of MAC address */
	struct ether_addr	fcip_factmacaddr; /* local mac address */
	struct ether_addr	fcip_macaddr;	/* MAC addr */
	la_wwn_t		fcip_ouraddr;	/* individual address */
	uchar_t			fcip_ouripaddr[16]; /* Our IP address */
	struct kmem_cache	*fcip_xmit_cache; /* cache of xmit pkts */
	uint32_t		fcip_wantw;	/* out of xmit resources */
	queue_t			*fcip_ipq;	/* ip read queue */
	taskq_t			*fcip_tq;

	kstat_t			*fcip_intrstats; /* interrupt statistics */
	kstat_t			*fcip_kstatp;	/* kstat pointer */

	ulong_t			fcip_ipackets;  /* # packets received */
	ulong_t			fcip_ierrors;	/* # total input errors */
	ulong_t			fcip_opackets;  /* # packets sent */
	ulong_t			fcip_oerrors;	/* # total output errors */
	ulong_t			fcip_collisions;  /* # collisions */
	ulong_t			fcip_defer;	/* # defers */
	ulong_t			fcip_fram;	/* # receive framing errors */
	ulong_t			fcip_crc;	/* # receive crc errors */
	ulong_t			fcip_oflo;	/* # receiver overflows */
	ulong_t			fcip_uflo;	/* # transmit underflows */
	ulong_t			fcip_missed;	/* # receive missed */
	ulong_t			fcip_tlcol;	/* # xmit late collisions */
	ulong_t			fcip_trtry;	/* # transmit retry failures */
	ulong_t			fcip_tnocar;	/* # loss of carrier errors */
	ulong_t			fcip_inits;	/* # driver inits */
	ulong_t			fcip_notbufs;	/* # out of pkts for xmit */
	ulong_t			fcip_norbufs;	/* # out of buffers for rcv */
	ulong_t			fcip_nocanput;  /* # input canputret.false */
	ulong_t			fcip_allocbfail;  /* # allocb failed */
	int 			fcip_tx_lbolt;  /* time of last tx interrupt */
	int 			fcip_rx_lbolt; 	/* time of last rx interrupt */

	/*
	 * MIB II variables
	 */
	ulong_t			fcip_rcvbytes; /* # bytes received */
	ulong_t			fcip_xmtbytes; /* # bytes transmitted */
	ulong_t			fcip_multircv; /* # multicast pkts received */
	ulong_t			fcip_multixmt; /* # multicast pkts for xmit */
	ulong_t			fcip_brdcstrcv; /* # broadcast pkts received */
	ulong_t			fcip_brdcstxmt; /* # broadcast pkts for xmit */
	ulong_t			fcip_norcvbuf; /* # rcv pkts discarded */
	ulong_t			fcip_noxmtbuf; /* # xmit pkts discarded */
};

#define	FCIP_FACTADDR_PRESENT		0x01
#define	FCIP_FACTADDR_USE		0x02

/* flags */
#define	FCIP_RUNNING			0x01
#define	FCIP_INITED			0x02
#define	FCIP_PROMISC			0x04
#define	FCIP_SUSPENDED			0x08
#define	FCIP_NOTIMEOUTS			0x10
#define	FCIP_DETACHING			0x20
#define	FCIP_DETACHED			0x40
#define	FCIP_ATTACHING			0x80
#define	FCIP_LINK_DOWN			0x100
#define	FCIP_IN_CALLBACK		0x200
#define	FCIP_IN_TIMEOUT			0x400
#define	FCIP_POWER_DOWN			0x800


/*
 * FCIP routing table maintains the FC Layer and the ARP layer
 * mapping for a destination port.
 */
struct fcip_routing_table {
	struct fcip_routing_table *fcipr_next;	/* next elem */
	la_wwn_t	fcipr_pwwn;	/* Destination Port's Port WWN */
	la_wwn_t	fcipr_nwwn;	/* Destination Port's Node WWN */
	fc_portid_t	fcipr_d_id;	/* Destination Port's D_ID */
	void		*fcipr_pd;	/* pointer to port device struct */
	uchar_t		fcipr_ipaddr[16]; /* Port's IP address */
	int		fcipr_state;	/* login state etc */
	clock_t		fcipr_invalid_timeout;	/* wait after marked inval */
	opaque_t	fcipr_fca_dev;	/* FCA device pointer */
};

#define	FCIP_COMPARE_NWWN		0x001
#define	FCIP_COMPARE_PWWN		0x010
#define	FCIP_COMPARE_BROADCAST		0x100

#define	IS_BROADCAST_ADDR(wwn)	(((wwn)->w.wwn_hi == 0xffff) && \
				((wwn)->w.wwn_lo == 0xffffffff))

/*
 * Define a fcip_pkt structure. We can stuff information about
 * the message block and queue for which the packet was built. We can
 * then free up the message once the transport layer has confirmed
 * that the packet has been successfully transported.
 */
typedef struct fcip_pkt {
	mblk_t			*fcip_pkt_mp;	/* message blk pointer */
	queue_t			*fcip_pkt_wq;	/* queue pointer if needed */
	uint32_t		fcip_pkt_ttl;	/* time to live */
	uint32_t		fcip_pkt_retries; /* retries if needed */
	fc_packet_t		*fcip_pkt_fcpktp; /* the actual fc packet */
	struct fcip_dest	*fcip_pkt_dest;	/* destination of pkt */
	struct fcip		*fcip_pkt_fptr;	/* fcip structure */
	struct fcip_pkt		*fcip_pkt_next;	/* next pkt */
	struct fcip_pkt		*fcip_pkt_prev;	/* prev pkt */
	uint32_t		fcip_pkt_state;	/* pkt state */
	uint32_t		fcip_pkt_reason;	/* pkt reason */
	uint32_t		fcip_pkt_flags;	/* pkt flags */
	uint32_t		fcip_pkt_dma_flags; /* DMA flags */
	fc_packet_t		fcip_pkt_fcpkt;	/* the actual fc packet */
} fcip_pkt_t;

/* fcipp_dma_flags */
#define	FCIP_CMD_DMA_MEM	0x01
#define	FCIP_CMD_DMA_BOUND	0x02
#define	FCIP_RESP_DMA_MEM	0x04
#define	FCIP_RESP_DMA_BOUND	0x08

/* fcipp_flags */
#define	FCIP_PKT_INTERNAL	0x01
#define	FCIP_PKT_IN_TIMEOUT	0x02
#define	FCIP_PKT_RETURNED	0x04
#define	FCIP_PKT_IN_LIST	0x08

#define	FCIP_PKT_TO_FC_PKT(fcip_pkt)	&(fcip_pkt)->fcip_pkt_fcpkt
/*
 * For each remote port we have a active session with (logged in and
 * having active exchanges) setup a Destination Port structure. Maintain
 * a Hash list of destination structures in the fcip structure. Before
 * starting a new session with the destination port, lookup the hash
 * table to see if we are already having active exchanges with a remote
 * port and if yes bump the reference count and continue use the same
 * destination port. Hash on Port WWNs.
 */
struct fcip_dest {
	struct fcip_dest	*fcipd_next;	/* next element of hashtable */
	fcip_pkt_t		*fcipd_head;	/* packet head for this port */
	kmutex_t		fcipd_mutex;	/* packet list mutex */
	uint32_t		fcipd_refcnt;	/* no.of active sessions */
	struct fcip_routing_table *fcipd_rtable;

#define	fcipd_nwwn	fcipd_rtable->fcipr_nwwn
#define	fcipd_pwwn	fcipd_rtable->fcipr_pwwn
#define	fcipd_did	fcipd_rtable->fcipr_d_id
#define	fcipd_pd	fcipd_rtable->fcipr_pd
#define	fcipd_state	fcipd_rtable->fcipr_state
#define	fcipd_fca_dev	fcipd_rtable->fcipr_fca_dev;

	uint32_t		fcipd_retries;	/* retries if needed ?? */
	uint32_t		fcipd_flags;	/* flags ?? */
	ulong_t			fcipd_ncmds;	/* no. of transport cmds */
};


#define	FCIP_PORT_OFFLINE	0
#define	FCIP_PORT_ONLINE	1
#define	FCIP_PORT_NOTLOGGED	2

#define	FCIP_INVALID_WWN	-1

#define	SLFAST			0x01	/* MDATA fastpath mode */
#define	SLRAW			0x02	/* M_DATA plain raw mode */
#define	SLALLPHYS		0x04	/* promiscuous mode */
#define	SLALLMULTI		0x05	/* enable all multicast addr */
#define	SLALLSAP		0x10	/* enable all ethertype values */



/*
 * Private DLPI full dlsap address format.
 */
struct	fcipdladdr {
	struct	ether_addr	dl_phys;
	uint16_t		dl_sap;
};


typedef struct llc_snap_hdr {
	uchar_t		dsap;
	uchar_t		ssap;
	uchar_t		ctrl;
	uchar_t		oui[3];
	ushort_t	pid;
} llc_snap_hdr_t;

/*
 * "Export" a few of the error counters via the kstats mechanism.
 */
struct	fcipstat {
	struct	kstat_named	fcips_ipackets;
	struct	kstat_named	fcips_ierrors;
	struct	kstat_named	fcips_opackets;
	struct	kstat_named	fcips_oerrors;
	struct	kstat_named	fcips_collisions;
	struct	kstat_named	fcips_defer;
	struct	kstat_named	fcips_fram;
	struct	kstat_named	fcips_crc;
	struct	kstat_named	fcips_oflo;
	struct	kstat_named	fcips_uflo;
	struct	kstat_named	fcips_missed;
	struct	kstat_named	fcips_tlcol;
	struct	kstat_named	fcips_trtry;
	struct	kstat_named	fcips_tnocar;
	struct	kstat_named	fcips_inits;
	struct	kstat_named	fcips_notmds;
	struct	kstat_named	fcips_notbufs;
	struct	kstat_named	fcips_norbufs;
	struct	kstat_named	fcips_nocanput;
	struct	kstat_named	fcips_allocbfail;

	/*
	 * required by kstat for MIB II objects(RFC 1213)
	 */
	struct  kstat_named	fcips_rcvbytes;	/* # octets received */
						/* MIB - ifInOctets */
	struct  kstat_named	fcips_xmtbytes; /* # octets xmitted */
						/* MIB - ifOutOctets */
	struct  kstat_named	fcips_multircv;	/* # multicast packets */
						/* delivered to upper layer */
						/* MIB - ifInNUcastPkts */
	struct  kstat_named	fcips_multixmt;	/* # multicast packets */
						/* requested to be sent */
						/* MIB - ifOutNUcastPkts */
	struct  kstat_named	fcips_brdcstrcv; /* # broadcast packets */
						/* delivered to upper layer */
						/* MIB - ifInNUcastPkts */
	struct  kstat_named	fcips_brdcstxmt; /* # broadcast packets */
						/* requested to be sent */
						/* MIB - ifOutNUcastPkts */
	struct  kstat_named	fcips_norcvbuf;	/* # rcv packets discarded */
						/* MIB - ifInDiscards */
	struct  kstat_named	fcips_noxmtbuf;	/* # xmt packets discarded */
						/* MIB - ifOutDiscards */
};


#define	FC_OFF		0x00
#define	DA_OFF		0x01
#define	SA_OFF		0x07
#define	DLSAP_OFF	0x0D
#define	SLSAP_OFF	0x0E
#define	ORG_OFF		0x0F
#define	TYPE_OFF	0x13

#define	FCIP_IPV4_LEN	0x04;

#define	FCIP_CP_IN(s, d, handle, len)	(ddi_rep_get8((handle), \
					(uint8_t *)(d), (uint8_t *)(s), \
					(len), DDI_DEV_AUTOINCR))

#define	FCIP_CP_OUT(s, d, handle, len)	(ddi_rep_put8((handle), \
					(uint8_t *)(d), (uint8_t *)(s), \
					(len), DDI_DEV_AUTOINCR))

#define	LA_ELS_FARP_REQ			0x54
#define	LA_ELS_FARP_REPLY		0x55

/* Match address code points */
#define	FARP_MATCH_RSVD			0x00
#define	FARP_MATCH_WW_PN		0x01
#define	FARP_MATCH_WW_NN		0x02
#define	FARP_MATCH_WW_PN_NN		0x03
#define	FARP_MATCH_IPv4			0x04
#define	FARP_MATCH_WW_PN_IPv4		0x05
#define	FARP_MATCH_WW_NN_IPv4		0x06
#define	FARP_MATCH_WW_PN_NN_IPv4	0x07

/* Responder flags */
#define	FARP_INIT_P_LOGI		0x0
#define	FARP_INIT_REPLY			0x1


/*
 * Structure for FARP ELS request and Response
 */
typedef struct la_els_farp {
	ls_code_t	ls_code;  /* FARP ELS code - 0x54/0x55 */
	uchar_t		match_addr; /* match addr. code points */
	fc_portid_t	req_id; /* Requester Port_ID */
	uchar_t		resp_flags; /* Responder flags */
	fc_portid_t	dest_id; /* Responder Port_ID */
	la_wwn_t	req_pwwn; /* Port WWN of Requester */
	la_wwn_t	req_nwwn; /* Node WWN of Requester */
	la_wwn_t	resp_pwwn; /* Port WWN of Responder */
	la_wwn_t	resp_nwwn; /* Node WWN of Responder */
	uchar_t		req_ip[16]; /* IP address or Requester */
	uchar_t		resp_ip[16]; /* IP address or Responder */
} la_els_farp_t;

/*
 * Linked list of farp responses
 */
struct farp_resp_list {
	struct farp_resp_list *farpl_next;
	struct farp_resp_list *farpl_prev;
	la_els_farp_t *farpl_resp;
};

/*
 * FCPH Optional network Header
 */
typedef struct network_header {
	la_wwn_t	net_dest_addr;
	la_wwn_t	net_src_addr;
} fcph_network_hdr_t;

/*
 * InArp request structure
 */
typedef struct fcip_inarp {
	fcph_network_hdr_t	fcip_inarp_nh;
	llc_snap_hdr_t		fcip_inarp_snap;
	struct ether_arp	fcip_inarp_data;
} fcip_inarp_t;

/*
 * InArp Response list
 */
struct inarp_resp_list {
	struct inarp_resp_list *inarpl_next;
	struct inarp_resp_list *inarpl_prev;
	fcip_inarp_t *inarpl_resp;
};

/*
 * Structure to define args for esballoc frtn function
 */
struct fcip_esballoc_arg {
	fc_unsol_buf_t	*buf;
	opaque_t	phandle;
	frtn_t		*frtnp;
};

/*
 * Having TNF probe points can be lethal during reconfiguration boot. Enable
 * TNF using a compile time define.
 */

#ifdef lint
#define	FCIP_TNF_ENABLED
#else
#undef	FCIP_TNF_ENABLED
#endif


#ifdef	FCIP_TNF_ENABLED

extern int tnf_mod_load(void);
extern int tnf_mod_unload(struct modlinkage *e);

#define	FCIP_TNF_LOAD()			(void) tnf_mod_load()
#define	FCIP_TNF_UNLOAD(x)		(void) tnf_mod_unload(x)
#define	FCIP_TNF_PROBE_0(x)		TNF_PROBE_0 x
#define	FCIP_TNF_PROBE_1(x)		TNF_PROBE_1 x
#define	FCIP_TNF_PROBE_2(x)		TNF_PROBE_2 x
#define	FCIP_TNF_PROBE_3(x)		TNF_PROBE_3 x
#define	FCIP_TNF_PROBE_4(x)		TNF_PROBE_4 x
#define	FCIP_TNF_PROBE_5(x)		TNF_PROBE_5 x

#else

#define	FCIP_TNF_LOAD()
#define	FCIP_TNF_UNLOAD(x)
#define	FCIP_TNF_PROBE_0(x)
#define	FCIP_TNF_PROBE_1(x)
#define	FCIP_TNF_PROBE_2(x)
#define	FCIP_TNF_PROBE_3(x)
#define	FCIP_TNF_PROBE_4(x)
#define	FCIP_TNF_PROBE_5(x)

#endif	/* FCIP_TNF_ENABLED */

/*
 * Macros to help with complex TNF output
 */

#ifdef FCIP_TNF_ENABLED

#define	FCIP_TNF_BYTE_ARRAY(name, keys, detail, mesg, barray_name, \
barray, len) \
{ \
	TNF_PROBE_1(name, keys, detail, tnf_string, msg, mesg); \
	{ \
		int i = 0; \
		char str[36] = ""; \
		char *strp = str; \
		while (i < 32 && i < len) { \
			(void) sprintf(strp, "%02x", \
				((char *)(barray))[i++] & 0xff); \
			strp += 2; \
		} \
		TNF_PROBE_1(name, keys, "", \
			tnf_string, barray_name, str); \
	} \
}

#else

#define	FCIP_TNF_BYTE_ARRAY(name, keys, detail, mesg, barray_name, barray, len)

#endif	/* FCIP_TNF_ENABLED */

#ifdef	__cplusplus
}
#endif

#endif /* !_SYS_FIBRE_CHANNEL_ULP_FCIP_H */
