xref: /onnv-gate/usr/src/uts/common/sys/idm/idm_impl.h (revision 9721:4f7e194c7c37)
17978SPeter.Dunlap@Sun.COM /*
27978SPeter.Dunlap@Sun.COM  * CDDL HEADER START
37978SPeter.Dunlap@Sun.COM  *
47978SPeter.Dunlap@Sun.COM  * The contents of this file are subject to the terms of the
57978SPeter.Dunlap@Sun.COM  * Common Development and Distribution License (the "License").
67978SPeter.Dunlap@Sun.COM  * You may not use this file except in compliance with the License.
77978SPeter.Dunlap@Sun.COM  *
87978SPeter.Dunlap@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97978SPeter.Dunlap@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107978SPeter.Dunlap@Sun.COM  * See the License for the specific language governing permissions
117978SPeter.Dunlap@Sun.COM  * and limitations under the License.
127978SPeter.Dunlap@Sun.COM  *
137978SPeter.Dunlap@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147978SPeter.Dunlap@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157978SPeter.Dunlap@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167978SPeter.Dunlap@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177978SPeter.Dunlap@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187978SPeter.Dunlap@Sun.COM  *
197978SPeter.Dunlap@Sun.COM  * CDDL HEADER END
207978SPeter.Dunlap@Sun.COM  */
217978SPeter.Dunlap@Sun.COM /*
229162SPeter.Dunlap@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237978SPeter.Dunlap@Sun.COM  * Use is subject to license terms.
247978SPeter.Dunlap@Sun.COM  */
257978SPeter.Dunlap@Sun.COM #ifndef	_IDM_IMPL_H_
267978SPeter.Dunlap@Sun.COM #define	_IDM_IMPL_H_
277978SPeter.Dunlap@Sun.COM 
287978SPeter.Dunlap@Sun.COM #ifdef	__cplusplus
297978SPeter.Dunlap@Sun.COM extern "C" {
307978SPeter.Dunlap@Sun.COM #endif
317978SPeter.Dunlap@Sun.COM 
327978SPeter.Dunlap@Sun.COM #include <sys/avl.h>
337978SPeter.Dunlap@Sun.COM #include <sys/socket_impl.h>
347978SPeter.Dunlap@Sun.COM 
357978SPeter.Dunlap@Sun.COM /*
367978SPeter.Dunlap@Sun.COM  * IDM lock order:
377978SPeter.Dunlap@Sun.COM  *
387978SPeter.Dunlap@Sun.COM  * idm_taskid_table_lock, idm_task_t.idt_mutex
397978SPeter.Dunlap@Sun.COM  */
407978SPeter.Dunlap@Sun.COM 
417978SPeter.Dunlap@Sun.COM #define	CF_LOGIN_READY		0x00000001
427978SPeter.Dunlap@Sun.COM #define	CF_INITIAL_LOGIN	0x00000002
437978SPeter.Dunlap@Sun.COM #define	CF_ERROR		0x80000000
447978SPeter.Dunlap@Sun.COM 
457978SPeter.Dunlap@Sun.COM typedef enum {
467978SPeter.Dunlap@Sun.COM 	CONN_TYPE_INI = 1,
477978SPeter.Dunlap@Sun.COM 	CONN_TYPE_TGT
487978SPeter.Dunlap@Sun.COM } idm_conn_type_t;
497978SPeter.Dunlap@Sun.COM 
507978SPeter.Dunlap@Sun.COM /*
517978SPeter.Dunlap@Sun.COM  * Watchdog interval in seconds
527978SPeter.Dunlap@Sun.COM  */
537978SPeter.Dunlap@Sun.COM #define	IDM_WD_INTERVAL			5
547978SPeter.Dunlap@Sun.COM 
557978SPeter.Dunlap@Sun.COM /*
569586SPeter.Dunlap@Sun.COM  * Timeout period before the client "keepalive" callback is invoked in
579586SPeter.Dunlap@Sun.COM  * seconds if the connection is idle.
589586SPeter.Dunlap@Sun.COM  */
599586SPeter.Dunlap@Sun.COM #define	IDM_TRANSPORT_KEEPALIVE_IDLE_TIMEOUT	20
609586SPeter.Dunlap@Sun.COM 
619586SPeter.Dunlap@Sun.COM /*
627978SPeter.Dunlap@Sun.COM  * Timeout period before a TRANSPORT_FAIL event is generated in seconds
637978SPeter.Dunlap@Sun.COM  * if the connection is idle.
647978SPeter.Dunlap@Sun.COM  */
657978SPeter.Dunlap@Sun.COM #define	IDM_TRANSPORT_FAIL_IDLE_TIMEOUT	30
667978SPeter.Dunlap@Sun.COM 
677978SPeter.Dunlap@Sun.COM /*
687978SPeter.Dunlap@Sun.COM  * IDM reference count structure.  Audit code is shamelessly adapted
697978SPeter.Dunlap@Sun.COM  * from CIFS server.
707978SPeter.Dunlap@Sun.COM  */
717978SPeter.Dunlap@Sun.COM 
727978SPeter.Dunlap@Sun.COM #define	REFCNT_AUDIT_STACK_DEPTH	16
737978SPeter.Dunlap@Sun.COM #define	REFCNT_AUDIT_BUF_MAX_REC	16
747978SPeter.Dunlap@Sun.COM 
757978SPeter.Dunlap@Sun.COM typedef struct {
767978SPeter.Dunlap@Sun.COM 	uint32_t		anr_refcnt;
777978SPeter.Dunlap@Sun.COM 	int			anr_depth;
787978SPeter.Dunlap@Sun.COM 	pc_t			anr_stack[REFCNT_AUDIT_STACK_DEPTH];
797978SPeter.Dunlap@Sun.COM } refcnt_audit_record_t;
807978SPeter.Dunlap@Sun.COM 
817978SPeter.Dunlap@Sun.COM typedef struct {
827978SPeter.Dunlap@Sun.COM 	int			anb_index;
837978SPeter.Dunlap@Sun.COM 	int			anb_max_index;
847978SPeter.Dunlap@Sun.COM 	refcnt_audit_record_t	anb_records[REFCNT_AUDIT_BUF_MAX_REC];
857978SPeter.Dunlap@Sun.COM } refcnt_audit_buf_t;
867978SPeter.Dunlap@Sun.COM 
877978SPeter.Dunlap@Sun.COM #define	REFCNT_AUDIT(_rf_) {				\
887978SPeter.Dunlap@Sun.COM 	refcnt_audit_record_t	*anr;			\
897978SPeter.Dunlap@Sun.COM 							\
907978SPeter.Dunlap@Sun.COM 	anr = (_rf_)->ir_audit_buf.anb_records;		\
917978SPeter.Dunlap@Sun.COM 	anr += (_rf_)->ir_audit_buf.anb_index;		\
927978SPeter.Dunlap@Sun.COM 	(_rf_)->ir_audit_buf.anb_index++;		\
937978SPeter.Dunlap@Sun.COM 	(_rf_)->ir_audit_buf.anb_index &=		\
947978SPeter.Dunlap@Sun.COM 	    (_rf_)->ir_audit_buf.anb_max_index;		\
957978SPeter.Dunlap@Sun.COM 	anr->anr_refcnt = (_rf_)->ir_refcnt;		\
967978SPeter.Dunlap@Sun.COM 	anr->anr_depth = getpcstack(anr->anr_stack,	\
977978SPeter.Dunlap@Sun.COM 	    REFCNT_AUDIT_STACK_DEPTH);			\
987978SPeter.Dunlap@Sun.COM }
997978SPeter.Dunlap@Sun.COM 
1007978SPeter.Dunlap@Sun.COM struct idm_refcnt_s;
1017978SPeter.Dunlap@Sun.COM 
1027978SPeter.Dunlap@Sun.COM typedef void (idm_refcnt_cb_t)(void *ref_obj);
1037978SPeter.Dunlap@Sun.COM 
1047978SPeter.Dunlap@Sun.COM typedef enum {
1057978SPeter.Dunlap@Sun.COM 	REF_NOWAIT,
1067978SPeter.Dunlap@Sun.COM 	REF_WAIT_SYNC,
1077978SPeter.Dunlap@Sun.COM 	REF_WAIT_ASYNC
1087978SPeter.Dunlap@Sun.COM } idm_refcnt_wait_t;
1097978SPeter.Dunlap@Sun.COM 
1107978SPeter.Dunlap@Sun.COM typedef struct idm_refcnt_s {
1117978SPeter.Dunlap@Sun.COM 	int			ir_refcnt;
1127978SPeter.Dunlap@Sun.COM 	void			*ir_referenced_obj;
1137978SPeter.Dunlap@Sun.COM 	idm_refcnt_wait_t	ir_waiting;
1147978SPeter.Dunlap@Sun.COM 	kmutex_t		ir_mutex;
1157978SPeter.Dunlap@Sun.COM 	kcondvar_t		ir_cv;
1167978SPeter.Dunlap@Sun.COM 	idm_refcnt_cb_t		*ir_cb;
1177978SPeter.Dunlap@Sun.COM 	refcnt_audit_buf_t	ir_audit_buf;
1187978SPeter.Dunlap@Sun.COM } idm_refcnt_t;
1197978SPeter.Dunlap@Sun.COM 
1207978SPeter.Dunlap@Sun.COM /*
1217978SPeter.Dunlap@Sun.COM  * connection parameters - These parameters would be populated at
1227978SPeter.Dunlap@Sun.COM  * connection create, or during key-value negotiation at login
1237978SPeter.Dunlap@Sun.COM  */
1247978SPeter.Dunlap@Sun.COM typedef struct idm_conn_params_s {
1257978SPeter.Dunlap@Sun.COM 	uint32_t		max_dataseglen;
1267978SPeter.Dunlap@Sun.COM } idm_conn_param_t;
1277978SPeter.Dunlap@Sun.COM 
1287978SPeter.Dunlap@Sun.COM typedef struct idm_svc_s {
1297978SPeter.Dunlap@Sun.COM 	list_node_t		is_list_node;
1307978SPeter.Dunlap@Sun.COM 	kmutex_t		is_mutex;
1317978SPeter.Dunlap@Sun.COM 	kcondvar_t		is_cv;
1327978SPeter.Dunlap@Sun.COM 	kmutex_t		is_count_mutex;
1337978SPeter.Dunlap@Sun.COM 	kcondvar_t		is_count_cv;
1347978SPeter.Dunlap@Sun.COM 	idm_refcnt_t		is_refcnt;
1357978SPeter.Dunlap@Sun.COM 	int			is_online;
1367978SPeter.Dunlap@Sun.COM 	/* transport-specific service components */
1377978SPeter.Dunlap@Sun.COM 	void			*is_so_svc;
1387978SPeter.Dunlap@Sun.COM 	void			*is_iser_svc;
1397978SPeter.Dunlap@Sun.COM 	idm_svc_req_t		is_svc_req;
1407978SPeter.Dunlap@Sun.COM } idm_svc_t;
1417978SPeter.Dunlap@Sun.COM 
142*9721SPriya.Krishnan@Sun.COM #define	ISCSI_MAX_TSIH_LEN	6	/* 0x%04x */
143*9721SPriya.Krishnan@Sun.COM #define	ISCSI_MAX_ISID_LEN	ISCSI_ISID_LEN * 2
144*9721SPriya.Krishnan@Sun.COM 
1457978SPeter.Dunlap@Sun.COM typedef struct idm_conn_s {
1467978SPeter.Dunlap@Sun.COM 	list_node_t		ic_list_node;
1477978SPeter.Dunlap@Sun.COM 	void			*ic_handle;
1487978SPeter.Dunlap@Sun.COM 	idm_refcnt_t		ic_refcnt;
1497978SPeter.Dunlap@Sun.COM 	idm_svc_t		*ic_svc_binding; /* Target conn. only */
1507978SPeter.Dunlap@Sun.COM 	idm_sockaddr_t 		ic_ini_dst_addr;
1517978SPeter.Dunlap@Sun.COM 	struct sockaddr_storage	ic_laddr;	/* conn local address */
1527978SPeter.Dunlap@Sun.COM 	struct sockaddr_storage	ic_raddr;	/* conn remote address */
153*9721SPriya.Krishnan@Sun.COM 
154*9721SPriya.Krishnan@Sun.COM 	/*
155*9721SPriya.Krishnan@Sun.COM 	 * the target_name, initiator_name, initiator session
156*9721SPriya.Krishnan@Sun.COM 	 * identifier and target session identifying handle
157*9721SPriya.Krishnan@Sun.COM 	 * are only used for target connections.
158*9721SPriya.Krishnan@Sun.COM 	 */
159*9721SPriya.Krishnan@Sun.COM 	char			ic_target_name[ISCSI_MAX_NAME_LEN + 1];
160*9721SPriya.Krishnan@Sun.COM 	char			ic_initiator_name[ISCSI_MAX_NAME_LEN + 1];
161*9721SPriya.Krishnan@Sun.COM 	char			ic_tsih[ISCSI_MAX_TSIH_LEN + 1];
162*9721SPriya.Krishnan@Sun.COM 	char			ic_isid[ISCSI_MAX_ISID_LEN + 1];
1637978SPeter.Dunlap@Sun.COM 	idm_conn_state_t	ic_state;
1647978SPeter.Dunlap@Sun.COM 	idm_conn_state_t	ic_last_state;
1657978SPeter.Dunlap@Sun.COM 	sm_audit_buf_t		ic_state_audit;
1667978SPeter.Dunlap@Sun.COM 	kmutex_t		ic_state_mutex;
1677978SPeter.Dunlap@Sun.COM 	kcondvar_t		ic_state_cv;
1687978SPeter.Dunlap@Sun.COM 	uint32_t		ic_state_flags;
1697978SPeter.Dunlap@Sun.COM 	timeout_id_t		ic_state_timeout;
1707978SPeter.Dunlap@Sun.COM 	struct idm_conn_s	*ic_reinstate_conn; /* For conn reinst. */
1717978SPeter.Dunlap@Sun.COM 	struct idm_conn_s	*ic_logout_conn; /* For other conn logout */
1727978SPeter.Dunlap@Sun.COM 	taskq_t			*ic_state_taskq;
1737978SPeter.Dunlap@Sun.COM 	int			ic_pdu_events;
1747978SPeter.Dunlap@Sun.COM 	boolean_t		ic_login_info_valid;
1757978SPeter.Dunlap@Sun.COM 	boolean_t		ic_rdma_extensions;
1767978SPeter.Dunlap@Sun.COM 	uint16_t		ic_login_cid;
1777978SPeter.Dunlap@Sun.COM 
1787978SPeter.Dunlap@Sun.COM 	kmutex_t		ic_mutex;
1797978SPeter.Dunlap@Sun.COM 	kcondvar_t		ic_cv;
1807978SPeter.Dunlap@Sun.COM 	idm_status_t		ic_conn_sm_status;
1817978SPeter.Dunlap@Sun.COM 
1827978SPeter.Dunlap@Sun.COM 	boolean_t		ic_ffp;
1839586SPeter.Dunlap@Sun.COM 	boolean_t		ic_keepalive;
1847978SPeter.Dunlap@Sun.COM 	uint32_t		ic_internal_cid;
1857978SPeter.Dunlap@Sun.COM 
1867978SPeter.Dunlap@Sun.COM 	uint32_t		ic_conn_flags;
1877978SPeter.Dunlap@Sun.COM 	idm_conn_type_t		ic_conn_type;
1887978SPeter.Dunlap@Sun.COM 	idm_conn_ops_t		ic_conn_ops;
1897978SPeter.Dunlap@Sun.COM 	idm_transport_ops_t	*ic_transport_ops;
1907978SPeter.Dunlap@Sun.COM 	idm_transport_type_t	ic_transport_type;
1917978SPeter.Dunlap@Sun.COM 	int			ic_transport_hdrlen;
1927978SPeter.Dunlap@Sun.COM 	void			*ic_transport_private;
1937978SPeter.Dunlap@Sun.COM 	idm_conn_param_t	ic_conn_params;
1947978SPeter.Dunlap@Sun.COM 	/*
1957978SPeter.Dunlap@Sun.COM 	 * Save client callback to interpose idm callback
1967978SPeter.Dunlap@Sun.COM 	 */
1977978SPeter.Dunlap@Sun.COM 	idm_pdu_cb_t		*ic_client_callback;
1987978SPeter.Dunlap@Sun.COM 	clock_t			ic_timestamp;
1997978SPeter.Dunlap@Sun.COM } idm_conn_t;
2007978SPeter.Dunlap@Sun.COM 
2017978SPeter.Dunlap@Sun.COM #define	IDM_CONN_HEADER_DIGEST	0x00000001
2027978SPeter.Dunlap@Sun.COM #define	IDM_CONN_DATA_DIGEST	0x00000002
2037978SPeter.Dunlap@Sun.COM #define	IDM_CONN_USE_SCOREBOARD	0x00000004
2047978SPeter.Dunlap@Sun.COM 
2057978SPeter.Dunlap@Sun.COM #define	IDM_CONN_ISINI(ICI_IC)	((ICI_IC)->ic_conn_type == CONN_TYPE_INI)
2067978SPeter.Dunlap@Sun.COM #define	IDM_CONN_ISTGT(ICI_IC)	((ICI_IC)->ic_conn_type == CONN_TYPE_TGT)
2077978SPeter.Dunlap@Sun.COM 
2087978SPeter.Dunlap@Sun.COM /*
2097978SPeter.Dunlap@Sun.COM  * An IDM target task can transfer data using multiple buffers. The task
2107978SPeter.Dunlap@Sun.COM  * will maintain a list of buffers, and each buffer will contain the relative
2117978SPeter.Dunlap@Sun.COM  * offset of the transfer and a pointer to the next buffer in the list.
2127978SPeter.Dunlap@Sun.COM  *
2137978SPeter.Dunlap@Sun.COM  * Note on client private data:
2147978SPeter.Dunlap@Sun.COM  * idt_private is intended to be a pointer to some sort of client-
2157978SPeter.Dunlap@Sun.COM  * specific state.
2167978SPeter.Dunlap@Sun.COM  *
2177978SPeter.Dunlap@Sun.COM  * idt_client_handle is a more generic client-private piece of data that can
2187978SPeter.Dunlap@Sun.COM  * be used by the client for the express purpose of task lookup.  The driving
2197978SPeter.Dunlap@Sun.COM  * use case for this is for the client to store the initiator task tag for
2207978SPeter.Dunlap@Sun.COM  * a given task so that it may be more easily retrieved for task management.
2217978SPeter.Dunlap@Sun.COM  *
2227978SPeter.Dunlap@Sun.COM  * The key take away here is that clients should never call
2237978SPeter.Dunlap@Sun.COM  * idm_task_find_by_handle in the performance path.
2247978SPeter.Dunlap@Sun.COM  *
2257978SPeter.Dunlap@Sun.COM  * An initiator will require only one buffer per task, the offset will be 0.
2267978SPeter.Dunlap@Sun.COM  */
2277978SPeter.Dunlap@Sun.COM 
2287978SPeter.Dunlap@Sun.COM typedef struct idm_task_s {
2297978SPeter.Dunlap@Sun.COM 	idm_conn_t		*idt_ic;	/* Associated connection */
2307978SPeter.Dunlap@Sun.COM 	/* connection type is in idt_ic->ic_conn_type */
2317978SPeter.Dunlap@Sun.COM 	kmutex_t		idt_mutex;
2327978SPeter.Dunlap@Sun.COM 	void			*idt_private;	/* Client private data */
2337978SPeter.Dunlap@Sun.COM 	uintptr_t		idt_client_handle;	/* Client private */
2347978SPeter.Dunlap@Sun.COM 	uint32_t		idt_tt;		/* Task tag */
2357978SPeter.Dunlap@Sun.COM 	uint32_t		idt_r2t_ttt;	/* R2T Target Task tag */
2367978SPeter.Dunlap@Sun.COM 	idm_task_state_t	idt_state;
2377978SPeter.Dunlap@Sun.COM 	idm_refcnt_t		idt_refcnt;
2387978SPeter.Dunlap@Sun.COM 
2397978SPeter.Dunlap@Sun.COM 	/*
2407978SPeter.Dunlap@Sun.COM 	 * Statistics
2417978SPeter.Dunlap@Sun.COM 	 */
2427978SPeter.Dunlap@Sun.COM 	int			idt_tx_to_ini_start;
2437978SPeter.Dunlap@Sun.COM 	int			idt_tx_to_ini_done;
2447978SPeter.Dunlap@Sun.COM 	int			idt_rx_from_ini_start;
2457978SPeter.Dunlap@Sun.COM 	int			idt_rx_from_ini_done;
2469162SPeter.Dunlap@Sun.COM 	int			idt_tx_bytes;	/* IDM_CONN_USE_SCOREBOARD */
2479162SPeter.Dunlap@Sun.COM 	int			idt_rx_bytes;	/* IDM_CONN_USE_SCOREBOARD */
2487978SPeter.Dunlap@Sun.COM 
2497978SPeter.Dunlap@Sun.COM 	uint32_t		idt_exp_datasn;	/* expected datasn */
2507978SPeter.Dunlap@Sun.COM 	uint32_t		idt_exp_rttsn;	/* expected rttsn */
2517978SPeter.Dunlap@Sun.COM 	list_t			idt_inbufv;	/* chunks of IN buffers */
2527978SPeter.Dunlap@Sun.COM 	list_t			idt_outbufv;	/* chunks of OUT buffers */
2537978SPeter.Dunlap@Sun.COM 
2547978SPeter.Dunlap@Sun.COM 	/*
2557978SPeter.Dunlap@Sun.COM 	 * Transport header, which describes this tasks remote tagged buffer
2567978SPeter.Dunlap@Sun.COM 	 */
2577978SPeter.Dunlap@Sun.COM 	int			idt_transport_hdrlen;
2587978SPeter.Dunlap@Sun.COM 	void			*idt_transport_hdr;
2597978SPeter.Dunlap@Sun.COM } idm_task_t;
2607978SPeter.Dunlap@Sun.COM 
2617978SPeter.Dunlap@Sun.COM int idm_task_constructor(void *task_void, void *arg, int flags);
2627978SPeter.Dunlap@Sun.COM void idm_task_destructor(void *task_void, void *arg);
2637978SPeter.Dunlap@Sun.COM 
2647978SPeter.Dunlap@Sun.COM #define	IDM_TASKIDS_MAX		16384
2657978SPeter.Dunlap@Sun.COM #define	IDM_BUF_MAGIC		0x49425546	/* "IBUF" */
2667978SPeter.Dunlap@Sun.COM 
2677978SPeter.Dunlap@Sun.COM /* Protect with task mutex */
2687978SPeter.Dunlap@Sun.COM typedef struct idm_buf_s {
2697978SPeter.Dunlap@Sun.COM 	uint32_t	idb_magic;	/* "IBUF" */
2707978SPeter.Dunlap@Sun.COM 
2717978SPeter.Dunlap@Sun.COM 	/*
2727978SPeter.Dunlap@Sun.COM 	 * Note: idm_tx_link *must* be the second element in the list for
2737978SPeter.Dunlap@Sun.COM 	 * proper TX PDU ordering.
2747978SPeter.Dunlap@Sun.COM 	 */
2757978SPeter.Dunlap@Sun.COM 	list_node_t	idm_tx_link;	/* link in a list of TX objects */
2767978SPeter.Dunlap@Sun.COM 
2777978SPeter.Dunlap@Sun.COM 	list_node_t	idb_buflink;	/* link in a multi-buffer data xfer */
2787978SPeter.Dunlap@Sun.COM 	idm_conn_t	*idb_ic;	/* Associated connection */
2797978SPeter.Dunlap@Sun.COM 	void		*idb_buf;	/* data */
2807978SPeter.Dunlap@Sun.COM 	uint64_t	idb_buflen;	/* length of buffer */
2817978SPeter.Dunlap@Sun.COM 	size_t		idb_bufoffset;	/* offset in a multi-buffer xfer */
2827978SPeter.Dunlap@Sun.COM 	boolean_t	idb_bufalloc;  /* true if alloc'd in idm_buf_alloc */
2837978SPeter.Dunlap@Sun.COM 	/*
2847978SPeter.Dunlap@Sun.COM 	 * DataPDUInOrder=Yes, so to track that the PDUs in a sequence are sent
2857978SPeter.Dunlap@Sun.COM 	 * in continuously increasing address order, check that offsets for a
2867978SPeter.Dunlap@Sun.COM 	 * single buffer xfer are in order.
2877978SPeter.Dunlap@Sun.COM 	 */
2887978SPeter.Dunlap@Sun.COM 	uint32_t	idb_exp_offset;
2897978SPeter.Dunlap@Sun.COM 	size_t		idb_xfer_len;	/* Current requested xfer len */
2907978SPeter.Dunlap@Sun.COM 	void		*idb_buf_private; /* transport-specific buf handle */
2917978SPeter.Dunlap@Sun.COM 	void		*idb_reg_private; /* transport-specific reg handle */
2929162SPeter.Dunlap@Sun.COM 	void		*idb_bufptr; /* transport-specific bcopy pointer */
2939162SPeter.Dunlap@Sun.COM 	boolean_t	idb_bufbcopy;	/* true if bcopy required */
2949162SPeter.Dunlap@Sun.COM 
2957978SPeter.Dunlap@Sun.COM 	idm_buf_cb_t	*idb_buf_cb;	/* Data Completion Notify, tgt only */
2967978SPeter.Dunlap@Sun.COM 	void		*idb_cb_arg;	/* Client private data */
2977978SPeter.Dunlap@Sun.COM 	idm_task_t	*idb_task_binding;
2989162SPeter.Dunlap@Sun.COM 	timespec_t	idb_xfer_start;
2999162SPeter.Dunlap@Sun.COM 	timespec_t	idb_xfer_done;
3007978SPeter.Dunlap@Sun.COM 	boolean_t	idb_in_transport;
3017978SPeter.Dunlap@Sun.COM 	boolean_t	idb_tx_thread;		/* Sockets only */
3027978SPeter.Dunlap@Sun.COM 	iscsi_hdr_t	idb_data_hdr_tmpl;	/* Sockets only */
3037978SPeter.Dunlap@Sun.COM 	idm_status_t	idb_status;
3047978SPeter.Dunlap@Sun.COM } idm_buf_t;
3057978SPeter.Dunlap@Sun.COM 
3069162SPeter.Dunlap@Sun.COM typedef enum {
3079162SPeter.Dunlap@Sun.COM 	BP_CHECK_QUICK,
3089162SPeter.Dunlap@Sun.COM 	BP_CHECK_THOROUGH,
3099162SPeter.Dunlap@Sun.COM 	BP_CHECK_ASSERT
3109162SPeter.Dunlap@Sun.COM } idm_bufpat_check_type_t;
3119162SPeter.Dunlap@Sun.COM 
3129162SPeter.Dunlap@Sun.COM #define	BUFPAT_MATCH(bc_bufpat, bc_idb) 		\
3139162SPeter.Dunlap@Sun.COM 	((bufpat->bufpat_idb == bc_idb) &&		\
3149162SPeter.Dunlap@Sun.COM 	    (bufpat->bufpat_bufmagic == IDM_BUF_MAGIC))
3159162SPeter.Dunlap@Sun.COM 
3169162SPeter.Dunlap@Sun.COM typedef struct idm_bufpat_s {
3179162SPeter.Dunlap@Sun.COM 	void		*bufpat_idb;
3189162SPeter.Dunlap@Sun.COM 	uint32_t	bufpat_bufmagic;
3199162SPeter.Dunlap@Sun.COM 	uint32_t	bufpat_offset;
3209162SPeter.Dunlap@Sun.COM } idm_bufpat_t;
3219162SPeter.Dunlap@Sun.COM 
3227978SPeter.Dunlap@Sun.COM #define	PDU_MAX_IOVLEN	12
3237978SPeter.Dunlap@Sun.COM #define	IDM_PDU_MAGIC	0x49504455	/* "IPDU" */
3247978SPeter.Dunlap@Sun.COM 
3257978SPeter.Dunlap@Sun.COM typedef struct idm_pdu_s {
3267978SPeter.Dunlap@Sun.COM 	uint32_t	isp_magic;	/* "IPDU" */
3277978SPeter.Dunlap@Sun.COM 
3287978SPeter.Dunlap@Sun.COM 	/*
3297978SPeter.Dunlap@Sun.COM 	 * Internal - Order is vital.  idm_tx_link *must* be the second
3307978SPeter.Dunlap@Sun.COM 	 * element in this structure for proper TX PDU ordering.
3317978SPeter.Dunlap@Sun.COM 	 */
3327978SPeter.Dunlap@Sun.COM 	list_node_t	idm_tx_link;
3337978SPeter.Dunlap@Sun.COM 
3347978SPeter.Dunlap@Sun.COM 	list_node_t	isp_client_lnd;
3357978SPeter.Dunlap@Sun.COM 
3367978SPeter.Dunlap@Sun.COM 	idm_conn_t	*isp_ic;	/* Must be set */
3377978SPeter.Dunlap@Sun.COM 	iscsi_hdr_t	*isp_hdr;
3387978SPeter.Dunlap@Sun.COM 	uint_t		isp_hdrlen;
3397978SPeter.Dunlap@Sun.COM 	uint8_t		*isp_data;
3407978SPeter.Dunlap@Sun.COM 	uint_t		isp_datalen;
3417978SPeter.Dunlap@Sun.COM 
3427978SPeter.Dunlap@Sun.COM 	/* Transport header */
3437978SPeter.Dunlap@Sun.COM 	void		*isp_transport_hdr;
3447978SPeter.Dunlap@Sun.COM 	uint32_t	isp_transport_hdrlen;
3457978SPeter.Dunlap@Sun.COM 	void		*isp_transport_private;
3467978SPeter.Dunlap@Sun.COM 
3477978SPeter.Dunlap@Sun.COM 	/*
3487978SPeter.Dunlap@Sun.COM 	 * isp_data is used for sending SCSI status, NOP, text, scsi and
3497978SPeter.Dunlap@Sun.COM 	 * non-scsi data. Data is received using isp_iov and isp_iovlen
3507978SPeter.Dunlap@Sun.COM 	 * to support data over multiple buffers.
3517978SPeter.Dunlap@Sun.COM 	 */
3527978SPeter.Dunlap@Sun.COM 	void		*isp_private;
3537978SPeter.Dunlap@Sun.COM 	idm_pdu_cb_t	*isp_callback;
3547978SPeter.Dunlap@Sun.COM 	idm_status_t	isp_status;
3557978SPeter.Dunlap@Sun.COM 
3567978SPeter.Dunlap@Sun.COM 	/*
3577978SPeter.Dunlap@Sun.COM 	 * The following four elements are only used in
3587978SPeter.Dunlap@Sun.COM 	 * idm_sorecv_scsidata() currently.
3597978SPeter.Dunlap@Sun.COM 	 */
3607978SPeter.Dunlap@Sun.COM 	struct iovec	isp_iov[PDU_MAX_IOVLEN];
3617978SPeter.Dunlap@Sun.COM 	int		isp_iovlen;
3627978SPeter.Dunlap@Sun.COM 	idm_buf_t	*isp_sorx_buf;
3637978SPeter.Dunlap@Sun.COM 
3647978SPeter.Dunlap@Sun.COM 	/* Implementation data for idm_pdu_alloc and sorx PDU cache */
3657978SPeter.Dunlap@Sun.COM 	uint32_t	isp_flags;
3667978SPeter.Dunlap@Sun.COM 	uint_t		isp_hdrbuflen;
3677978SPeter.Dunlap@Sun.COM 	uint_t		isp_databuflen;
3687978SPeter.Dunlap@Sun.COM } idm_pdu_t;
3697978SPeter.Dunlap@Sun.COM 
3707978SPeter.Dunlap@Sun.COM /*
3717978SPeter.Dunlap@Sun.COM  * This "generic" object is used when removing an item from the ic_tx_list
3727978SPeter.Dunlap@Sun.COM  * in order to determine whether it's an idm_pdu_t or an idm_buf_t
3737978SPeter.Dunlap@Sun.COM  */
3747978SPeter.Dunlap@Sun.COM 
3757978SPeter.Dunlap@Sun.COM typedef struct {
3767978SPeter.Dunlap@Sun.COM 	uint32_t	idm_tx_obj_magic;
3777978SPeter.Dunlap@Sun.COM 	/*
3787978SPeter.Dunlap@Sun.COM 	 * idm_tx_link *must* be the second element in this structure.
3797978SPeter.Dunlap@Sun.COM 	 */
3807978SPeter.Dunlap@Sun.COM 	list_node_t	idm_tx_link;
3817978SPeter.Dunlap@Sun.COM } idm_tx_obj_t;
3827978SPeter.Dunlap@Sun.COM 
3837978SPeter.Dunlap@Sun.COM 
3847978SPeter.Dunlap@Sun.COM #define	IDM_PDU_OPCODE(PDU) \
3857978SPeter.Dunlap@Sun.COM 	((PDU)->isp_hdr->opcode & ISCSI_OPCODE_MASK)
3867978SPeter.Dunlap@Sun.COM 
3877978SPeter.Dunlap@Sun.COM #define	IDM_PDU_ALLOC		0x00000001
3887978SPeter.Dunlap@Sun.COM #define	IDM_PDU_ADDL_HDR	0x00000002
3897978SPeter.Dunlap@Sun.COM #define	IDM_PDU_ADDL_DATA	0x00000004
3907978SPeter.Dunlap@Sun.COM #define	IDM_PDU_LOGIN_TX	0x00000008
3917978SPeter.Dunlap@Sun.COM 
3927978SPeter.Dunlap@Sun.COM #define	OSD_EXT_CDB_AHSLEN	(200 - 15)
3937978SPeter.Dunlap@Sun.COM #define	BIDI_AHS_LENGTH		5
3947978SPeter.Dunlap@Sun.COM #define	IDM_SORX_CACHE_AHSLEN \
3957978SPeter.Dunlap@Sun.COM 	(((OSD_EXT_CDB_AHSLEN + 3) + \
3967978SPeter.Dunlap@Sun.COM 	    (BIDI_AHS_LENGTH + 3)) / sizeof (uint32_t))
3977978SPeter.Dunlap@Sun.COM #define	IDM_SORX_CACHE_HDRLEN	(sizeof (iscsi_hdr_t) + IDM_SORX_CACHE_AHSLEN)
3987978SPeter.Dunlap@Sun.COM 
3997978SPeter.Dunlap@Sun.COM /*
4007978SPeter.Dunlap@Sun.COM  * ID pool
4017978SPeter.Dunlap@Sun.COM  */
4027978SPeter.Dunlap@Sun.COM 
4037978SPeter.Dunlap@Sun.COM #define	IDM_IDPOOL_MAGIC	0x4944504C	/* IDPL */
4047978SPeter.Dunlap@Sun.COM #define	IDM_IDPOOL_MIN_SIZE	64	/* Number of IDs to begin with */
4057978SPeter.Dunlap@Sun.COM #define	IDM_IDPOOL_MAX_SIZE	64 * 1024
4067978SPeter.Dunlap@Sun.COM 
4077978SPeter.Dunlap@Sun.COM typedef struct idm_idpool {
4087978SPeter.Dunlap@Sun.COM 	uint32_t	id_magic;
4097978SPeter.Dunlap@Sun.COM 	kmutex_t	id_mutex;
4107978SPeter.Dunlap@Sun.COM 	uint8_t		*id_pool;
4117978SPeter.Dunlap@Sun.COM 	uint32_t	id_size;
4127978SPeter.Dunlap@Sun.COM 	uint8_t		id_bit;
4137978SPeter.Dunlap@Sun.COM 	uint8_t		id_bit_idx;
4147978SPeter.Dunlap@Sun.COM 	uint32_t	id_idx;
4157978SPeter.Dunlap@Sun.COM 	uint32_t	id_idx_msk;
4167978SPeter.Dunlap@Sun.COM 	uint32_t	id_free_counter;
4177978SPeter.Dunlap@Sun.COM 	uint32_t	id_max_free_counter;
4187978SPeter.Dunlap@Sun.COM } idm_idpool_t;
4197978SPeter.Dunlap@Sun.COM 
4207978SPeter.Dunlap@Sun.COM /*
4217978SPeter.Dunlap@Sun.COM  * Global IDM state structure
4227978SPeter.Dunlap@Sun.COM  */
4237978SPeter.Dunlap@Sun.COM typedef struct {
4247978SPeter.Dunlap@Sun.COM 	kmutex_t	idm_global_mutex;
4257978SPeter.Dunlap@Sun.COM 	taskq_t		*idm_global_taskq;
4267978SPeter.Dunlap@Sun.COM 	kthread_t	*idm_wd_thread;
4277978SPeter.Dunlap@Sun.COM 	kt_did_t	idm_wd_thread_did;
4287978SPeter.Dunlap@Sun.COM 	boolean_t	idm_wd_thread_running;
4297978SPeter.Dunlap@Sun.COM 	kcondvar_t	idm_wd_cv;
4307978SPeter.Dunlap@Sun.COM 	list_t		idm_tgt_svc_list;
4317978SPeter.Dunlap@Sun.COM 	kcondvar_t	idm_tgt_svc_cv;
4327978SPeter.Dunlap@Sun.COM 	list_t		idm_tgt_conn_list;
4337978SPeter.Dunlap@Sun.COM 	int		idm_tgt_conn_count;
4347978SPeter.Dunlap@Sun.COM 	list_t		idm_ini_conn_list;
4357978SPeter.Dunlap@Sun.COM 	kmem_cache_t	*idm_buf_cache;
4367978SPeter.Dunlap@Sun.COM 	kmem_cache_t	*idm_task_cache;
4377978SPeter.Dunlap@Sun.COM 	krwlock_t	idm_taskid_table_lock;
4387978SPeter.Dunlap@Sun.COM 	idm_task_t	**idm_taskid_table;
4397978SPeter.Dunlap@Sun.COM 	uint32_t	idm_taskid_next;
4407978SPeter.Dunlap@Sun.COM 	uint32_t	idm_taskid_max;
4417978SPeter.Dunlap@Sun.COM 	idm_idpool_t	idm_conn_id_pool;
4427978SPeter.Dunlap@Sun.COM 	kmem_cache_t	*idm_sotx_pdu_cache;
4437978SPeter.Dunlap@Sun.COM 	kmem_cache_t	*idm_sorx_pdu_cache;
4449247SPeter.Dunlap@Sun.COM 	kmem_cache_t	*idm_so_128k_buf_cache;
4457978SPeter.Dunlap@Sun.COM } idm_global_t;
4467978SPeter.Dunlap@Sun.COM 
4477978SPeter.Dunlap@Sun.COM idm_global_t	idm; /* Global state */
4487978SPeter.Dunlap@Sun.COM 
4497978SPeter.Dunlap@Sun.COM int
4507978SPeter.Dunlap@Sun.COM idm_idpool_create(idm_idpool_t	*pool);
4517978SPeter.Dunlap@Sun.COM 
4527978SPeter.Dunlap@Sun.COM void
4537978SPeter.Dunlap@Sun.COM idm_idpool_destroy(idm_idpool_t *pool);
4547978SPeter.Dunlap@Sun.COM 
4557978SPeter.Dunlap@Sun.COM int
4567978SPeter.Dunlap@Sun.COM idm_idpool_alloc(idm_idpool_t *pool, uint16_t *id);
4577978SPeter.Dunlap@Sun.COM 
4587978SPeter.Dunlap@Sun.COM void
4597978SPeter.Dunlap@Sun.COM idm_idpool_free(idm_idpool_t *pool, uint16_t id);
4607978SPeter.Dunlap@Sun.COM 
4617978SPeter.Dunlap@Sun.COM void
4627978SPeter.Dunlap@Sun.COM idm_pdu_rx(idm_conn_t *ic, idm_pdu_t *pdu);
4637978SPeter.Dunlap@Sun.COM 
4647978SPeter.Dunlap@Sun.COM void
4657978SPeter.Dunlap@Sun.COM idm_pdu_tx_forward(idm_conn_t *ic, idm_pdu_t *pdu);
4667978SPeter.Dunlap@Sun.COM 
4677978SPeter.Dunlap@Sun.COM boolean_t
4687978SPeter.Dunlap@Sun.COM idm_pdu_rx_forward_ffp(idm_conn_t *ic, idm_pdu_t *pdu);
4697978SPeter.Dunlap@Sun.COM 
4707978SPeter.Dunlap@Sun.COM void
4717978SPeter.Dunlap@Sun.COM idm_pdu_rx_forward(idm_conn_t *ic, idm_pdu_t *pdu);
4727978SPeter.Dunlap@Sun.COM 
4737978SPeter.Dunlap@Sun.COM void
4747978SPeter.Dunlap@Sun.COM idm_pdu_tx_protocol_error(idm_conn_t *ic, idm_pdu_t *pdu);
4757978SPeter.Dunlap@Sun.COM 
4767978SPeter.Dunlap@Sun.COM void
4777978SPeter.Dunlap@Sun.COM idm_pdu_rx_protocol_error(idm_conn_t *ic, idm_pdu_t *pdu);
4787978SPeter.Dunlap@Sun.COM 
4797978SPeter.Dunlap@Sun.COM void idm_parse_login_rsp(idm_conn_t *ic, idm_pdu_t *logout_req_pdu,
4807978SPeter.Dunlap@Sun.COM     boolean_t rx);
4817978SPeter.Dunlap@Sun.COM 
4827978SPeter.Dunlap@Sun.COM void idm_parse_logout_req(idm_conn_t *ic, idm_pdu_t *logout_req_pdu,
4837978SPeter.Dunlap@Sun.COM     boolean_t rx);
4847978SPeter.Dunlap@Sun.COM 
4857978SPeter.Dunlap@Sun.COM void idm_parse_logout_rsp(idm_conn_t *ic, idm_pdu_t *login_rsp_pdu,
4867978SPeter.Dunlap@Sun.COM     boolean_t rx);
4877978SPeter.Dunlap@Sun.COM 
4887978SPeter.Dunlap@Sun.COM idm_status_t idm_svc_conn_create(idm_svc_t *is, idm_transport_type_t type,
4897978SPeter.Dunlap@Sun.COM     idm_conn_t **ic_result);
4907978SPeter.Dunlap@Sun.COM 
4917978SPeter.Dunlap@Sun.COM void idm_svc_conn_destroy(idm_conn_t *ic);
4927978SPeter.Dunlap@Sun.COM 
4937978SPeter.Dunlap@Sun.COM idm_status_t idm_ini_conn_finish(idm_conn_t *ic);
4947978SPeter.Dunlap@Sun.COM 
4957978SPeter.Dunlap@Sun.COM idm_status_t idm_tgt_conn_finish(idm_conn_t *ic);
4967978SPeter.Dunlap@Sun.COM 
4977978SPeter.Dunlap@Sun.COM idm_conn_t *idm_conn_create_common(idm_conn_type_t conn_type,
4987978SPeter.Dunlap@Sun.COM     idm_transport_type_t tt, idm_conn_ops_t *conn_ops);
4997978SPeter.Dunlap@Sun.COM 
5007978SPeter.Dunlap@Sun.COM void idm_conn_destroy_common(idm_conn_t *ic);
5017978SPeter.Dunlap@Sun.COM 
5027978SPeter.Dunlap@Sun.COM void idm_conn_close(idm_conn_t *ic);
5037978SPeter.Dunlap@Sun.COM 
5047978SPeter.Dunlap@Sun.COM uint32_t idm_cid_alloc(void);
5057978SPeter.Dunlap@Sun.COM 
5067978SPeter.Dunlap@Sun.COM void idm_cid_free(uint32_t cid);
5077978SPeter.Dunlap@Sun.COM 
5087978SPeter.Dunlap@Sun.COM uint32_t idm_crc32c(void *address, unsigned long length);
5097978SPeter.Dunlap@Sun.COM 
5107978SPeter.Dunlap@Sun.COM uint32_t idm_crc32c_continued(void *address, unsigned long length,
5117978SPeter.Dunlap@Sun.COM     uint32_t crc);
5127978SPeter.Dunlap@Sun.COM 
5137978SPeter.Dunlap@Sun.COM void idm_listbuf_insert(list_t *lst, idm_buf_t *buf);
5147978SPeter.Dunlap@Sun.COM 
5157978SPeter.Dunlap@Sun.COM int idm_task_compare(const void *v1, const void *v2);
5167978SPeter.Dunlap@Sun.COM 
5177978SPeter.Dunlap@Sun.COM idm_conn_t *idm_lookup_conn(uint8_t *isid, uint16_t tsih, uint16_t cid);
5187978SPeter.Dunlap@Sun.COM 
5197978SPeter.Dunlap@Sun.COM #ifdef	__cplusplus
5207978SPeter.Dunlap@Sun.COM }
5217978SPeter.Dunlap@Sun.COM #endif
5227978SPeter.Dunlap@Sun.COM 
5237978SPeter.Dunlap@Sun.COM #endif /* _IDM_IMPL_H_ */
524