xref: /onnv-gate/usr/src/uts/common/sys/idm/idm_impl.h (revision 9247:331d3de1fc0f)
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 /*
567978SPeter.Dunlap@Sun.COM  * Timeout period before a TRANSPORT_FAIL event is generated in seconds
577978SPeter.Dunlap@Sun.COM  * if the connection is idle.
587978SPeter.Dunlap@Sun.COM  */
597978SPeter.Dunlap@Sun.COM #define	IDM_TRANSPORT_FAIL_IDLE_TIMEOUT	30
607978SPeter.Dunlap@Sun.COM 
617978SPeter.Dunlap@Sun.COM /*
627978SPeter.Dunlap@Sun.COM  * IDM reference count structure.  Audit code is shamelessly adapted
637978SPeter.Dunlap@Sun.COM  * from CIFS server.
647978SPeter.Dunlap@Sun.COM  */
657978SPeter.Dunlap@Sun.COM 
667978SPeter.Dunlap@Sun.COM #define	REFCNT_AUDIT_STACK_DEPTH	16
677978SPeter.Dunlap@Sun.COM #define	REFCNT_AUDIT_BUF_MAX_REC	16
687978SPeter.Dunlap@Sun.COM 
697978SPeter.Dunlap@Sun.COM typedef struct {
707978SPeter.Dunlap@Sun.COM 	uint32_t		anr_refcnt;
717978SPeter.Dunlap@Sun.COM 	int			anr_depth;
727978SPeter.Dunlap@Sun.COM 	pc_t			anr_stack[REFCNT_AUDIT_STACK_DEPTH];
737978SPeter.Dunlap@Sun.COM } refcnt_audit_record_t;
747978SPeter.Dunlap@Sun.COM 
757978SPeter.Dunlap@Sun.COM typedef struct {
767978SPeter.Dunlap@Sun.COM 	int			anb_index;
777978SPeter.Dunlap@Sun.COM 	int			anb_max_index;
787978SPeter.Dunlap@Sun.COM 	refcnt_audit_record_t	anb_records[REFCNT_AUDIT_BUF_MAX_REC];
797978SPeter.Dunlap@Sun.COM } refcnt_audit_buf_t;
807978SPeter.Dunlap@Sun.COM 
817978SPeter.Dunlap@Sun.COM #define	REFCNT_AUDIT(_rf_) {				\
827978SPeter.Dunlap@Sun.COM 	refcnt_audit_record_t	*anr;			\
837978SPeter.Dunlap@Sun.COM 							\
847978SPeter.Dunlap@Sun.COM 	anr = (_rf_)->ir_audit_buf.anb_records;		\
857978SPeter.Dunlap@Sun.COM 	anr += (_rf_)->ir_audit_buf.anb_index;		\
867978SPeter.Dunlap@Sun.COM 	(_rf_)->ir_audit_buf.anb_index++;		\
877978SPeter.Dunlap@Sun.COM 	(_rf_)->ir_audit_buf.anb_index &=		\
887978SPeter.Dunlap@Sun.COM 	    (_rf_)->ir_audit_buf.anb_max_index;		\
897978SPeter.Dunlap@Sun.COM 	anr->anr_refcnt = (_rf_)->ir_refcnt;		\
907978SPeter.Dunlap@Sun.COM 	anr->anr_depth = getpcstack(anr->anr_stack,	\
917978SPeter.Dunlap@Sun.COM 	    REFCNT_AUDIT_STACK_DEPTH);			\
927978SPeter.Dunlap@Sun.COM }
937978SPeter.Dunlap@Sun.COM 
947978SPeter.Dunlap@Sun.COM struct idm_refcnt_s;
957978SPeter.Dunlap@Sun.COM 
967978SPeter.Dunlap@Sun.COM typedef void (idm_refcnt_cb_t)(void *ref_obj);
977978SPeter.Dunlap@Sun.COM 
987978SPeter.Dunlap@Sun.COM typedef enum {
997978SPeter.Dunlap@Sun.COM 	REF_NOWAIT,
1007978SPeter.Dunlap@Sun.COM 	REF_WAIT_SYNC,
1017978SPeter.Dunlap@Sun.COM 	REF_WAIT_ASYNC
1027978SPeter.Dunlap@Sun.COM } idm_refcnt_wait_t;
1037978SPeter.Dunlap@Sun.COM 
1047978SPeter.Dunlap@Sun.COM typedef struct idm_refcnt_s {
1057978SPeter.Dunlap@Sun.COM 	int			ir_refcnt;
1067978SPeter.Dunlap@Sun.COM 	void			*ir_referenced_obj;
1077978SPeter.Dunlap@Sun.COM 	idm_refcnt_wait_t	ir_waiting;
1087978SPeter.Dunlap@Sun.COM 	kmutex_t		ir_mutex;
1097978SPeter.Dunlap@Sun.COM 	kcondvar_t		ir_cv;
1107978SPeter.Dunlap@Sun.COM 	idm_refcnt_cb_t		*ir_cb;
1117978SPeter.Dunlap@Sun.COM 	refcnt_audit_buf_t	ir_audit_buf;
1127978SPeter.Dunlap@Sun.COM } idm_refcnt_t;
1137978SPeter.Dunlap@Sun.COM 
1147978SPeter.Dunlap@Sun.COM /*
1157978SPeter.Dunlap@Sun.COM  * connection parameters - These parameters would be populated at
1167978SPeter.Dunlap@Sun.COM  * connection create, or during key-value negotiation at login
1177978SPeter.Dunlap@Sun.COM  */
1187978SPeter.Dunlap@Sun.COM typedef struct idm_conn_params_s {
1197978SPeter.Dunlap@Sun.COM 	uint32_t		max_dataseglen;
1207978SPeter.Dunlap@Sun.COM } idm_conn_param_t;
1217978SPeter.Dunlap@Sun.COM 
1227978SPeter.Dunlap@Sun.COM typedef struct idm_svc_s {
1237978SPeter.Dunlap@Sun.COM 	list_node_t		is_list_node;
1247978SPeter.Dunlap@Sun.COM 	kmutex_t		is_mutex;
1257978SPeter.Dunlap@Sun.COM 	kcondvar_t		is_cv;
1267978SPeter.Dunlap@Sun.COM 	kmutex_t		is_count_mutex;
1277978SPeter.Dunlap@Sun.COM 	kcondvar_t		is_count_cv;
1287978SPeter.Dunlap@Sun.COM 	idm_refcnt_t		is_refcnt;
1297978SPeter.Dunlap@Sun.COM 	int			is_online;
1307978SPeter.Dunlap@Sun.COM 	/* transport-specific service components */
1317978SPeter.Dunlap@Sun.COM 	void			*is_so_svc;
1327978SPeter.Dunlap@Sun.COM 	void			*is_iser_svc;
1337978SPeter.Dunlap@Sun.COM 	idm_svc_req_t		is_svc_req;
1347978SPeter.Dunlap@Sun.COM } idm_svc_t;
1357978SPeter.Dunlap@Sun.COM 
1367978SPeter.Dunlap@Sun.COM typedef struct idm_conn_s {
1377978SPeter.Dunlap@Sun.COM 	list_node_t		ic_list_node;
1387978SPeter.Dunlap@Sun.COM 	void			*ic_handle;
1397978SPeter.Dunlap@Sun.COM 	idm_refcnt_t		ic_refcnt;
1407978SPeter.Dunlap@Sun.COM 	idm_svc_t		*ic_svc_binding; /* Target conn. only */
1417978SPeter.Dunlap@Sun.COM 	idm_sockaddr_t 		ic_ini_dst_addr;
1427978SPeter.Dunlap@Sun.COM 	struct sockaddr_storage	ic_laddr;	/* conn local address */
1437978SPeter.Dunlap@Sun.COM 	struct sockaddr_storage	ic_raddr;	/* conn remote address */
1447978SPeter.Dunlap@Sun.COM 	idm_conn_state_t	ic_state;
1457978SPeter.Dunlap@Sun.COM 	idm_conn_state_t	ic_last_state;
1467978SPeter.Dunlap@Sun.COM 	sm_audit_buf_t		ic_state_audit;
1477978SPeter.Dunlap@Sun.COM 	kmutex_t		ic_state_mutex;
1487978SPeter.Dunlap@Sun.COM 	kcondvar_t		ic_state_cv;
1497978SPeter.Dunlap@Sun.COM 	uint32_t		ic_state_flags;
1507978SPeter.Dunlap@Sun.COM 	timeout_id_t		ic_state_timeout;
1517978SPeter.Dunlap@Sun.COM 	struct idm_conn_s	*ic_reinstate_conn; /* For conn reinst. */
1527978SPeter.Dunlap@Sun.COM 	struct idm_conn_s	*ic_logout_conn; /* For other conn logout */
1537978SPeter.Dunlap@Sun.COM 	taskq_t			*ic_state_taskq;
1547978SPeter.Dunlap@Sun.COM 	int			ic_pdu_events;
1557978SPeter.Dunlap@Sun.COM 	boolean_t		ic_login_info_valid;
1567978SPeter.Dunlap@Sun.COM 	boolean_t		ic_rdma_extensions;
1577978SPeter.Dunlap@Sun.COM 	uint16_t		ic_login_cid;
1587978SPeter.Dunlap@Sun.COM 
1597978SPeter.Dunlap@Sun.COM 	kmutex_t		ic_mutex;
1607978SPeter.Dunlap@Sun.COM 	kcondvar_t		ic_cv;
1617978SPeter.Dunlap@Sun.COM 	idm_status_t		ic_conn_sm_status;
1627978SPeter.Dunlap@Sun.COM 
1637978SPeter.Dunlap@Sun.COM 	boolean_t		ic_ffp;
1647978SPeter.Dunlap@Sun.COM 	uint32_t		ic_internal_cid;
1657978SPeter.Dunlap@Sun.COM 
1667978SPeter.Dunlap@Sun.COM 	uint32_t		ic_conn_flags;
1677978SPeter.Dunlap@Sun.COM 	idm_conn_type_t		ic_conn_type;
1687978SPeter.Dunlap@Sun.COM 	idm_conn_ops_t		ic_conn_ops;
1697978SPeter.Dunlap@Sun.COM 	idm_transport_ops_t	*ic_transport_ops;
1707978SPeter.Dunlap@Sun.COM 	idm_transport_type_t	ic_transport_type;
1717978SPeter.Dunlap@Sun.COM 	int			ic_transport_hdrlen;
1727978SPeter.Dunlap@Sun.COM 	void			*ic_transport_private;
1737978SPeter.Dunlap@Sun.COM 	idm_conn_param_t	ic_conn_params;
1747978SPeter.Dunlap@Sun.COM 	/*
1757978SPeter.Dunlap@Sun.COM 	 * Save client callback to interpose idm callback
1767978SPeter.Dunlap@Sun.COM 	 */
1777978SPeter.Dunlap@Sun.COM 	idm_pdu_cb_t		*ic_client_callback;
1787978SPeter.Dunlap@Sun.COM 	clock_t			ic_timestamp;
1797978SPeter.Dunlap@Sun.COM } idm_conn_t;
1807978SPeter.Dunlap@Sun.COM 
1817978SPeter.Dunlap@Sun.COM #define	IDM_CONN_HEADER_DIGEST	0x00000001
1827978SPeter.Dunlap@Sun.COM #define	IDM_CONN_DATA_DIGEST	0x00000002
1837978SPeter.Dunlap@Sun.COM #define	IDM_CONN_USE_SCOREBOARD	0x00000004
1847978SPeter.Dunlap@Sun.COM 
1857978SPeter.Dunlap@Sun.COM #define	IDM_CONN_ISINI(ICI_IC)	((ICI_IC)->ic_conn_type == CONN_TYPE_INI)
1867978SPeter.Dunlap@Sun.COM #define	IDM_CONN_ISTGT(ICI_IC)	((ICI_IC)->ic_conn_type == CONN_TYPE_TGT)
1877978SPeter.Dunlap@Sun.COM 
1887978SPeter.Dunlap@Sun.COM /*
1897978SPeter.Dunlap@Sun.COM  * An IDM target task can transfer data using multiple buffers. The task
1907978SPeter.Dunlap@Sun.COM  * will maintain a list of buffers, and each buffer will contain the relative
1917978SPeter.Dunlap@Sun.COM  * offset of the transfer and a pointer to the next buffer in the list.
1927978SPeter.Dunlap@Sun.COM  *
1937978SPeter.Dunlap@Sun.COM  * Note on client private data:
1947978SPeter.Dunlap@Sun.COM  * idt_private is intended to be a pointer to some sort of client-
1957978SPeter.Dunlap@Sun.COM  * specific state.
1967978SPeter.Dunlap@Sun.COM  *
1977978SPeter.Dunlap@Sun.COM  * idt_client_handle is a more generic client-private piece of data that can
1987978SPeter.Dunlap@Sun.COM  * be used by the client for the express purpose of task lookup.  The driving
1997978SPeter.Dunlap@Sun.COM  * use case for this is for the client to store the initiator task tag for
2007978SPeter.Dunlap@Sun.COM  * a given task so that it may be more easily retrieved for task management.
2017978SPeter.Dunlap@Sun.COM  *
2027978SPeter.Dunlap@Sun.COM  * The key take away here is that clients should never call
2037978SPeter.Dunlap@Sun.COM  * idm_task_find_by_handle in the performance path.
2047978SPeter.Dunlap@Sun.COM  *
2057978SPeter.Dunlap@Sun.COM  * An initiator will require only one buffer per task, the offset will be 0.
2067978SPeter.Dunlap@Sun.COM  */
2077978SPeter.Dunlap@Sun.COM 
2087978SPeter.Dunlap@Sun.COM typedef struct idm_task_s {
2097978SPeter.Dunlap@Sun.COM 	idm_conn_t		*idt_ic;	/* Associated connection */
2107978SPeter.Dunlap@Sun.COM 	/* connection type is in idt_ic->ic_conn_type */
2117978SPeter.Dunlap@Sun.COM 	kmutex_t		idt_mutex;
2127978SPeter.Dunlap@Sun.COM 	void			*idt_private;	/* Client private data */
2137978SPeter.Dunlap@Sun.COM 	uintptr_t		idt_client_handle;	/* Client private */
2147978SPeter.Dunlap@Sun.COM 	uint32_t		idt_tt;		/* Task tag */
2157978SPeter.Dunlap@Sun.COM 	uint32_t		idt_r2t_ttt;	/* R2T Target Task tag */
2167978SPeter.Dunlap@Sun.COM 	idm_task_state_t	idt_state;
2177978SPeter.Dunlap@Sun.COM 	idm_refcnt_t		idt_refcnt;
2187978SPeter.Dunlap@Sun.COM 
2197978SPeter.Dunlap@Sun.COM 	/*
2207978SPeter.Dunlap@Sun.COM 	 * Statistics
2217978SPeter.Dunlap@Sun.COM 	 */
2227978SPeter.Dunlap@Sun.COM 	int			idt_tx_to_ini_start;
2237978SPeter.Dunlap@Sun.COM 	int			idt_tx_to_ini_done;
2247978SPeter.Dunlap@Sun.COM 	int			idt_rx_from_ini_start;
2257978SPeter.Dunlap@Sun.COM 	int			idt_rx_from_ini_done;
2269162SPeter.Dunlap@Sun.COM 	int			idt_tx_bytes;	/* IDM_CONN_USE_SCOREBOARD */
2279162SPeter.Dunlap@Sun.COM 	int			idt_rx_bytes;	/* IDM_CONN_USE_SCOREBOARD */
2287978SPeter.Dunlap@Sun.COM 
2297978SPeter.Dunlap@Sun.COM 	uint32_t		idt_exp_datasn;	/* expected datasn */
2307978SPeter.Dunlap@Sun.COM 	uint32_t		idt_exp_rttsn;	/* expected rttsn */
2317978SPeter.Dunlap@Sun.COM 	list_t			idt_inbufv;	/* chunks of IN buffers */
2327978SPeter.Dunlap@Sun.COM 	list_t			idt_outbufv;	/* chunks of OUT buffers */
2337978SPeter.Dunlap@Sun.COM 
2347978SPeter.Dunlap@Sun.COM 	/*
2357978SPeter.Dunlap@Sun.COM 	 * Transport header, which describes this tasks remote tagged buffer
2367978SPeter.Dunlap@Sun.COM 	 */
2377978SPeter.Dunlap@Sun.COM 	int			idt_transport_hdrlen;
2387978SPeter.Dunlap@Sun.COM 	void			*idt_transport_hdr;
2397978SPeter.Dunlap@Sun.COM } idm_task_t;
2407978SPeter.Dunlap@Sun.COM 
2417978SPeter.Dunlap@Sun.COM int idm_task_constructor(void *task_void, void *arg, int flags);
2427978SPeter.Dunlap@Sun.COM void idm_task_destructor(void *task_void, void *arg);
2437978SPeter.Dunlap@Sun.COM 
2447978SPeter.Dunlap@Sun.COM #define	IDM_TASKIDS_MAX		16384
2457978SPeter.Dunlap@Sun.COM #define	IDM_BUF_MAGIC		0x49425546	/* "IBUF" */
2467978SPeter.Dunlap@Sun.COM 
2477978SPeter.Dunlap@Sun.COM /* Protect with task mutex */
2487978SPeter.Dunlap@Sun.COM typedef struct idm_buf_s {
2497978SPeter.Dunlap@Sun.COM 	uint32_t	idb_magic;	/* "IBUF" */
2507978SPeter.Dunlap@Sun.COM 
2517978SPeter.Dunlap@Sun.COM 	/*
2527978SPeter.Dunlap@Sun.COM 	 * Note: idm_tx_link *must* be the second element in the list for
2537978SPeter.Dunlap@Sun.COM 	 * proper TX PDU ordering.
2547978SPeter.Dunlap@Sun.COM 	 */
2557978SPeter.Dunlap@Sun.COM 	list_node_t	idm_tx_link;	/* link in a list of TX objects */
2567978SPeter.Dunlap@Sun.COM 
2577978SPeter.Dunlap@Sun.COM 	list_node_t	idb_buflink;	/* link in a multi-buffer data xfer */
2587978SPeter.Dunlap@Sun.COM 	idm_conn_t	*idb_ic;	/* Associated connection */
2597978SPeter.Dunlap@Sun.COM 	void		*idb_buf;	/* data */
2607978SPeter.Dunlap@Sun.COM 	uint64_t	idb_buflen;	/* length of buffer */
2617978SPeter.Dunlap@Sun.COM 	size_t		idb_bufoffset;	/* offset in a multi-buffer xfer */
2627978SPeter.Dunlap@Sun.COM 	boolean_t	idb_bufalloc;  /* true if alloc'd in idm_buf_alloc */
2637978SPeter.Dunlap@Sun.COM 	/*
2647978SPeter.Dunlap@Sun.COM 	 * DataPDUInOrder=Yes, so to track that the PDUs in a sequence are sent
2657978SPeter.Dunlap@Sun.COM 	 * in continuously increasing address order, check that offsets for a
2667978SPeter.Dunlap@Sun.COM 	 * single buffer xfer are in order.
2677978SPeter.Dunlap@Sun.COM 	 */
2687978SPeter.Dunlap@Sun.COM 	uint32_t	idb_exp_offset;
2697978SPeter.Dunlap@Sun.COM 	size_t		idb_xfer_len;	/* Current requested xfer len */
2707978SPeter.Dunlap@Sun.COM 	void		*idb_buf_private; /* transport-specific buf handle */
2717978SPeter.Dunlap@Sun.COM 	void		*idb_reg_private; /* transport-specific reg handle */
2729162SPeter.Dunlap@Sun.COM 	void		*idb_bufptr; /* transport-specific bcopy pointer */
2739162SPeter.Dunlap@Sun.COM 	boolean_t	idb_bufbcopy;	/* true if bcopy required */
2749162SPeter.Dunlap@Sun.COM 
2757978SPeter.Dunlap@Sun.COM 	idm_buf_cb_t	*idb_buf_cb;	/* Data Completion Notify, tgt only */
2767978SPeter.Dunlap@Sun.COM 	void		*idb_cb_arg;	/* Client private data */
2777978SPeter.Dunlap@Sun.COM 	idm_task_t	*idb_task_binding;
2789162SPeter.Dunlap@Sun.COM 	timespec_t	idb_xfer_start;
2799162SPeter.Dunlap@Sun.COM 	timespec_t	idb_xfer_done;
2807978SPeter.Dunlap@Sun.COM 	boolean_t	idb_in_transport;
2817978SPeter.Dunlap@Sun.COM 	boolean_t	idb_tx_thread;		/* Sockets only */
2827978SPeter.Dunlap@Sun.COM 	iscsi_hdr_t	idb_data_hdr_tmpl;	/* Sockets only */
2837978SPeter.Dunlap@Sun.COM 	idm_status_t	idb_status;
2847978SPeter.Dunlap@Sun.COM } idm_buf_t;
2857978SPeter.Dunlap@Sun.COM 
2869162SPeter.Dunlap@Sun.COM typedef enum {
2879162SPeter.Dunlap@Sun.COM 	BP_CHECK_QUICK,
2889162SPeter.Dunlap@Sun.COM 	BP_CHECK_THOROUGH,
2899162SPeter.Dunlap@Sun.COM 	BP_CHECK_ASSERT
2909162SPeter.Dunlap@Sun.COM } idm_bufpat_check_type_t;
2919162SPeter.Dunlap@Sun.COM 
2929162SPeter.Dunlap@Sun.COM #define	BUFPAT_MATCH(bc_bufpat, bc_idb) 		\
2939162SPeter.Dunlap@Sun.COM 	((bufpat->bufpat_idb == bc_idb) &&		\
2949162SPeter.Dunlap@Sun.COM 	    (bufpat->bufpat_bufmagic == IDM_BUF_MAGIC))
2959162SPeter.Dunlap@Sun.COM 
2969162SPeter.Dunlap@Sun.COM typedef struct idm_bufpat_s {
2979162SPeter.Dunlap@Sun.COM 	void		*bufpat_idb;
2989162SPeter.Dunlap@Sun.COM 	uint32_t	bufpat_bufmagic;
2999162SPeter.Dunlap@Sun.COM 	uint32_t	bufpat_offset;
3009162SPeter.Dunlap@Sun.COM } idm_bufpat_t;
3019162SPeter.Dunlap@Sun.COM 
3027978SPeter.Dunlap@Sun.COM #define	PDU_MAX_IOVLEN	12
3037978SPeter.Dunlap@Sun.COM #define	IDM_PDU_MAGIC	0x49504455	/* "IPDU" */
3047978SPeter.Dunlap@Sun.COM 
3057978SPeter.Dunlap@Sun.COM typedef struct idm_pdu_s {
3067978SPeter.Dunlap@Sun.COM 	uint32_t	isp_magic;	/* "IPDU" */
3077978SPeter.Dunlap@Sun.COM 
3087978SPeter.Dunlap@Sun.COM 	/*
3097978SPeter.Dunlap@Sun.COM 	 * Internal - Order is vital.  idm_tx_link *must* be the second
3107978SPeter.Dunlap@Sun.COM 	 * element in this structure for proper TX PDU ordering.
3117978SPeter.Dunlap@Sun.COM 	 */
3127978SPeter.Dunlap@Sun.COM 	list_node_t	idm_tx_link;
3137978SPeter.Dunlap@Sun.COM 
3147978SPeter.Dunlap@Sun.COM 	list_node_t	isp_client_lnd;
3157978SPeter.Dunlap@Sun.COM 
3167978SPeter.Dunlap@Sun.COM 	idm_conn_t	*isp_ic;	/* Must be set */
3177978SPeter.Dunlap@Sun.COM 	iscsi_hdr_t	*isp_hdr;
3187978SPeter.Dunlap@Sun.COM 	uint_t		isp_hdrlen;
3197978SPeter.Dunlap@Sun.COM 	uint8_t		*isp_data;
3207978SPeter.Dunlap@Sun.COM 	uint_t		isp_datalen;
3217978SPeter.Dunlap@Sun.COM 
3227978SPeter.Dunlap@Sun.COM 	/* Transport header */
3237978SPeter.Dunlap@Sun.COM 	void		*isp_transport_hdr;
3247978SPeter.Dunlap@Sun.COM 	uint32_t	isp_transport_hdrlen;
3257978SPeter.Dunlap@Sun.COM 	void		*isp_transport_private;
3267978SPeter.Dunlap@Sun.COM 
3277978SPeter.Dunlap@Sun.COM 	/*
3287978SPeter.Dunlap@Sun.COM 	 * isp_data is used for sending SCSI status, NOP, text, scsi and
3297978SPeter.Dunlap@Sun.COM 	 * non-scsi data. Data is received using isp_iov and isp_iovlen
3307978SPeter.Dunlap@Sun.COM 	 * to support data over multiple buffers.
3317978SPeter.Dunlap@Sun.COM 	 */
3327978SPeter.Dunlap@Sun.COM 	void		*isp_private;
3337978SPeter.Dunlap@Sun.COM 	idm_pdu_cb_t	*isp_callback;
3347978SPeter.Dunlap@Sun.COM 	idm_status_t	isp_status;
3357978SPeter.Dunlap@Sun.COM 
3367978SPeter.Dunlap@Sun.COM 	/*
3377978SPeter.Dunlap@Sun.COM 	 * The following four elements are only used in
3387978SPeter.Dunlap@Sun.COM 	 * idm_sorecv_scsidata() currently.
3397978SPeter.Dunlap@Sun.COM 	 */
3407978SPeter.Dunlap@Sun.COM 	struct iovec	isp_iov[PDU_MAX_IOVLEN];
3417978SPeter.Dunlap@Sun.COM 	int		isp_iovlen;
3427978SPeter.Dunlap@Sun.COM 	idm_buf_t	*isp_sorx_buf;
3437978SPeter.Dunlap@Sun.COM 
3447978SPeter.Dunlap@Sun.COM 	/* Implementation data for idm_pdu_alloc and sorx PDU cache */
3457978SPeter.Dunlap@Sun.COM 	uint32_t	isp_flags;
3467978SPeter.Dunlap@Sun.COM 	uint_t		isp_hdrbuflen;
3477978SPeter.Dunlap@Sun.COM 	uint_t		isp_databuflen;
3487978SPeter.Dunlap@Sun.COM } idm_pdu_t;
3497978SPeter.Dunlap@Sun.COM 
3507978SPeter.Dunlap@Sun.COM /*
3517978SPeter.Dunlap@Sun.COM  * This "generic" object is used when removing an item from the ic_tx_list
3527978SPeter.Dunlap@Sun.COM  * in order to determine whether it's an idm_pdu_t or an idm_buf_t
3537978SPeter.Dunlap@Sun.COM  */
3547978SPeter.Dunlap@Sun.COM 
3557978SPeter.Dunlap@Sun.COM typedef struct {
3567978SPeter.Dunlap@Sun.COM 	uint32_t	idm_tx_obj_magic;
3577978SPeter.Dunlap@Sun.COM 	/*
3587978SPeter.Dunlap@Sun.COM 	 * idm_tx_link *must* be the second element in this structure.
3597978SPeter.Dunlap@Sun.COM 	 */
3607978SPeter.Dunlap@Sun.COM 	list_node_t	idm_tx_link;
3617978SPeter.Dunlap@Sun.COM } idm_tx_obj_t;
3627978SPeter.Dunlap@Sun.COM 
3637978SPeter.Dunlap@Sun.COM 
3647978SPeter.Dunlap@Sun.COM #define	IDM_PDU_OPCODE(PDU) \
3657978SPeter.Dunlap@Sun.COM 	((PDU)->isp_hdr->opcode & ISCSI_OPCODE_MASK)
3667978SPeter.Dunlap@Sun.COM 
3677978SPeter.Dunlap@Sun.COM #define	IDM_PDU_ALLOC		0x00000001
3687978SPeter.Dunlap@Sun.COM #define	IDM_PDU_ADDL_HDR	0x00000002
3697978SPeter.Dunlap@Sun.COM #define	IDM_PDU_ADDL_DATA	0x00000004
3707978SPeter.Dunlap@Sun.COM #define	IDM_PDU_LOGIN_TX	0x00000008
3717978SPeter.Dunlap@Sun.COM 
3727978SPeter.Dunlap@Sun.COM #define	OSD_EXT_CDB_AHSLEN	(200 - 15)
3737978SPeter.Dunlap@Sun.COM #define	BIDI_AHS_LENGTH		5
3747978SPeter.Dunlap@Sun.COM #define	IDM_SORX_CACHE_AHSLEN \
3757978SPeter.Dunlap@Sun.COM 	(((OSD_EXT_CDB_AHSLEN + 3) + \
3767978SPeter.Dunlap@Sun.COM 	    (BIDI_AHS_LENGTH + 3)) / sizeof (uint32_t))
3777978SPeter.Dunlap@Sun.COM #define	IDM_SORX_CACHE_HDRLEN	(sizeof (iscsi_hdr_t) + IDM_SORX_CACHE_AHSLEN)
3787978SPeter.Dunlap@Sun.COM 
3797978SPeter.Dunlap@Sun.COM /*
3807978SPeter.Dunlap@Sun.COM  * ID pool
3817978SPeter.Dunlap@Sun.COM  */
3827978SPeter.Dunlap@Sun.COM 
3837978SPeter.Dunlap@Sun.COM #define	IDM_IDPOOL_MAGIC	0x4944504C	/* IDPL */
3847978SPeter.Dunlap@Sun.COM #define	IDM_IDPOOL_MIN_SIZE	64	/* Number of IDs to begin with */
3857978SPeter.Dunlap@Sun.COM #define	IDM_IDPOOL_MAX_SIZE	64 * 1024
3867978SPeter.Dunlap@Sun.COM 
3877978SPeter.Dunlap@Sun.COM typedef struct idm_idpool {
3887978SPeter.Dunlap@Sun.COM 	uint32_t	id_magic;
3897978SPeter.Dunlap@Sun.COM 	kmutex_t	id_mutex;
3907978SPeter.Dunlap@Sun.COM 	uint8_t		*id_pool;
3917978SPeter.Dunlap@Sun.COM 	uint32_t	id_size;
3927978SPeter.Dunlap@Sun.COM 	uint8_t		id_bit;
3937978SPeter.Dunlap@Sun.COM 	uint8_t		id_bit_idx;
3947978SPeter.Dunlap@Sun.COM 	uint32_t	id_idx;
3957978SPeter.Dunlap@Sun.COM 	uint32_t	id_idx_msk;
3967978SPeter.Dunlap@Sun.COM 	uint32_t	id_free_counter;
3977978SPeter.Dunlap@Sun.COM 	uint32_t	id_max_free_counter;
3987978SPeter.Dunlap@Sun.COM } idm_idpool_t;
3997978SPeter.Dunlap@Sun.COM 
4007978SPeter.Dunlap@Sun.COM /*
4017978SPeter.Dunlap@Sun.COM  * Global IDM state structure
4027978SPeter.Dunlap@Sun.COM  */
4037978SPeter.Dunlap@Sun.COM typedef struct {
4047978SPeter.Dunlap@Sun.COM 	kmutex_t	idm_global_mutex;
4057978SPeter.Dunlap@Sun.COM 	taskq_t		*idm_global_taskq;
4067978SPeter.Dunlap@Sun.COM 	kthread_t	*idm_wd_thread;
4077978SPeter.Dunlap@Sun.COM 	kt_did_t	idm_wd_thread_did;
4087978SPeter.Dunlap@Sun.COM 	boolean_t	idm_wd_thread_running;
4097978SPeter.Dunlap@Sun.COM 	kcondvar_t	idm_wd_cv;
4107978SPeter.Dunlap@Sun.COM 	list_t		idm_tgt_svc_list;
4117978SPeter.Dunlap@Sun.COM 	kcondvar_t	idm_tgt_svc_cv;
4127978SPeter.Dunlap@Sun.COM 	list_t		idm_tgt_conn_list;
4137978SPeter.Dunlap@Sun.COM 	int		idm_tgt_conn_count;
4147978SPeter.Dunlap@Sun.COM 	list_t		idm_ini_conn_list;
4157978SPeter.Dunlap@Sun.COM 	kmem_cache_t	*idm_buf_cache;
4167978SPeter.Dunlap@Sun.COM 	kmem_cache_t	*idm_task_cache;
4177978SPeter.Dunlap@Sun.COM 	krwlock_t	idm_taskid_table_lock;
4187978SPeter.Dunlap@Sun.COM 	idm_task_t	**idm_taskid_table;
4197978SPeter.Dunlap@Sun.COM 	uint32_t	idm_taskid_next;
4207978SPeter.Dunlap@Sun.COM 	uint32_t	idm_taskid_max;
4217978SPeter.Dunlap@Sun.COM 	idm_idpool_t	idm_conn_id_pool;
4227978SPeter.Dunlap@Sun.COM 	kmem_cache_t	*idm_sotx_pdu_cache;
4237978SPeter.Dunlap@Sun.COM 	kmem_cache_t	*idm_sorx_pdu_cache;
424*9247SPeter.Dunlap@Sun.COM 	kmem_cache_t	*idm_so_128k_buf_cache;
4257978SPeter.Dunlap@Sun.COM } idm_global_t;
4267978SPeter.Dunlap@Sun.COM 
4277978SPeter.Dunlap@Sun.COM idm_global_t	idm; /* Global state */
4287978SPeter.Dunlap@Sun.COM 
4297978SPeter.Dunlap@Sun.COM int
4307978SPeter.Dunlap@Sun.COM idm_idpool_create(idm_idpool_t	*pool);
4317978SPeter.Dunlap@Sun.COM 
4327978SPeter.Dunlap@Sun.COM void
4337978SPeter.Dunlap@Sun.COM idm_idpool_destroy(idm_idpool_t *pool);
4347978SPeter.Dunlap@Sun.COM 
4357978SPeter.Dunlap@Sun.COM int
4367978SPeter.Dunlap@Sun.COM idm_idpool_alloc(idm_idpool_t *pool, uint16_t *id);
4377978SPeter.Dunlap@Sun.COM 
4387978SPeter.Dunlap@Sun.COM void
4397978SPeter.Dunlap@Sun.COM idm_idpool_free(idm_idpool_t *pool, uint16_t id);
4407978SPeter.Dunlap@Sun.COM 
4417978SPeter.Dunlap@Sun.COM void
4427978SPeter.Dunlap@Sun.COM idm_pdu_rx(idm_conn_t *ic, idm_pdu_t *pdu);
4437978SPeter.Dunlap@Sun.COM 
4447978SPeter.Dunlap@Sun.COM void
4457978SPeter.Dunlap@Sun.COM idm_pdu_tx_forward(idm_conn_t *ic, idm_pdu_t *pdu);
4467978SPeter.Dunlap@Sun.COM 
4477978SPeter.Dunlap@Sun.COM boolean_t
4487978SPeter.Dunlap@Sun.COM idm_pdu_rx_forward_ffp(idm_conn_t *ic, idm_pdu_t *pdu);
4497978SPeter.Dunlap@Sun.COM 
4507978SPeter.Dunlap@Sun.COM void
4517978SPeter.Dunlap@Sun.COM idm_pdu_rx_forward(idm_conn_t *ic, idm_pdu_t *pdu);
4527978SPeter.Dunlap@Sun.COM 
4537978SPeter.Dunlap@Sun.COM void
4547978SPeter.Dunlap@Sun.COM idm_pdu_tx_protocol_error(idm_conn_t *ic, idm_pdu_t *pdu);
4557978SPeter.Dunlap@Sun.COM 
4567978SPeter.Dunlap@Sun.COM void
4577978SPeter.Dunlap@Sun.COM idm_pdu_rx_protocol_error(idm_conn_t *ic, idm_pdu_t *pdu);
4587978SPeter.Dunlap@Sun.COM 
4597978SPeter.Dunlap@Sun.COM void idm_parse_login_rsp(idm_conn_t *ic, idm_pdu_t *logout_req_pdu,
4607978SPeter.Dunlap@Sun.COM     boolean_t rx);
4617978SPeter.Dunlap@Sun.COM 
4627978SPeter.Dunlap@Sun.COM void idm_parse_logout_req(idm_conn_t *ic, idm_pdu_t *logout_req_pdu,
4637978SPeter.Dunlap@Sun.COM     boolean_t rx);
4647978SPeter.Dunlap@Sun.COM 
4657978SPeter.Dunlap@Sun.COM void idm_parse_logout_rsp(idm_conn_t *ic, idm_pdu_t *login_rsp_pdu,
4667978SPeter.Dunlap@Sun.COM     boolean_t rx);
4677978SPeter.Dunlap@Sun.COM 
4687978SPeter.Dunlap@Sun.COM idm_status_t idm_svc_conn_create(idm_svc_t *is, idm_transport_type_t type,
4697978SPeter.Dunlap@Sun.COM     idm_conn_t **ic_result);
4707978SPeter.Dunlap@Sun.COM 
4717978SPeter.Dunlap@Sun.COM void idm_svc_conn_destroy(idm_conn_t *ic);
4727978SPeter.Dunlap@Sun.COM 
4737978SPeter.Dunlap@Sun.COM idm_status_t idm_ini_conn_finish(idm_conn_t *ic);
4747978SPeter.Dunlap@Sun.COM 
4757978SPeter.Dunlap@Sun.COM idm_status_t idm_tgt_conn_finish(idm_conn_t *ic);
4767978SPeter.Dunlap@Sun.COM 
4777978SPeter.Dunlap@Sun.COM idm_conn_t *idm_conn_create_common(idm_conn_type_t conn_type,
4787978SPeter.Dunlap@Sun.COM     idm_transport_type_t tt, idm_conn_ops_t *conn_ops);
4797978SPeter.Dunlap@Sun.COM 
4807978SPeter.Dunlap@Sun.COM void idm_conn_destroy_common(idm_conn_t *ic);
4817978SPeter.Dunlap@Sun.COM 
4827978SPeter.Dunlap@Sun.COM void idm_conn_close(idm_conn_t *ic);
4837978SPeter.Dunlap@Sun.COM 
4847978SPeter.Dunlap@Sun.COM uint32_t idm_cid_alloc(void);
4857978SPeter.Dunlap@Sun.COM 
4867978SPeter.Dunlap@Sun.COM void idm_cid_free(uint32_t cid);
4877978SPeter.Dunlap@Sun.COM 
4887978SPeter.Dunlap@Sun.COM uint32_t idm_crc32c(void *address, unsigned long length);
4897978SPeter.Dunlap@Sun.COM 
4907978SPeter.Dunlap@Sun.COM uint32_t idm_crc32c_continued(void *address, unsigned long length,
4917978SPeter.Dunlap@Sun.COM     uint32_t crc);
4927978SPeter.Dunlap@Sun.COM 
4937978SPeter.Dunlap@Sun.COM void idm_listbuf_insert(list_t *lst, idm_buf_t *buf);
4947978SPeter.Dunlap@Sun.COM 
4957978SPeter.Dunlap@Sun.COM int idm_task_compare(const void *v1, const void *v2);
4967978SPeter.Dunlap@Sun.COM 
4977978SPeter.Dunlap@Sun.COM idm_conn_t *idm_lookup_conn(uint8_t *isid, uint16_t tsih, uint16_t cid);
4987978SPeter.Dunlap@Sun.COM 
4997978SPeter.Dunlap@Sun.COM #ifdef	__cplusplus
5007978SPeter.Dunlap@Sun.COM }
5017978SPeter.Dunlap@Sun.COM #endif
5027978SPeter.Dunlap@Sun.COM 
5037978SPeter.Dunlap@Sun.COM #endif /* _IDM_IMPL_H_ */
504