xref: /onnv-gate/usr/src/uts/common/sys/idm/idm_impl.h (revision 7978:4559e57ec313)
1*7978SPeter.Dunlap@Sun.COM /*
2*7978SPeter.Dunlap@Sun.COM  * CDDL HEADER START
3*7978SPeter.Dunlap@Sun.COM  *
4*7978SPeter.Dunlap@Sun.COM  * The contents of this file are subject to the terms of the
5*7978SPeter.Dunlap@Sun.COM  * Common Development and Distribution License (the "License").
6*7978SPeter.Dunlap@Sun.COM  * You may not use this file except in compliance with the License.
7*7978SPeter.Dunlap@Sun.COM  *
8*7978SPeter.Dunlap@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7978SPeter.Dunlap@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*7978SPeter.Dunlap@Sun.COM  * See the License for the specific language governing permissions
11*7978SPeter.Dunlap@Sun.COM  * and limitations under the License.
12*7978SPeter.Dunlap@Sun.COM  *
13*7978SPeter.Dunlap@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*7978SPeter.Dunlap@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7978SPeter.Dunlap@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*7978SPeter.Dunlap@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*7978SPeter.Dunlap@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*7978SPeter.Dunlap@Sun.COM  *
19*7978SPeter.Dunlap@Sun.COM  * CDDL HEADER END
20*7978SPeter.Dunlap@Sun.COM  */
21*7978SPeter.Dunlap@Sun.COM /*
22*7978SPeter.Dunlap@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*7978SPeter.Dunlap@Sun.COM  * Use is subject to license terms.
24*7978SPeter.Dunlap@Sun.COM  */
25*7978SPeter.Dunlap@Sun.COM #ifndef	_IDM_IMPL_H_
26*7978SPeter.Dunlap@Sun.COM #define	_IDM_IMPL_H_
27*7978SPeter.Dunlap@Sun.COM 
28*7978SPeter.Dunlap@Sun.COM #ifdef	__cplusplus
29*7978SPeter.Dunlap@Sun.COM extern "C" {
30*7978SPeter.Dunlap@Sun.COM #endif
31*7978SPeter.Dunlap@Sun.COM 
32*7978SPeter.Dunlap@Sun.COM #include <sys/avl.h>
33*7978SPeter.Dunlap@Sun.COM #include <sys/socket_impl.h>
34*7978SPeter.Dunlap@Sun.COM 
35*7978SPeter.Dunlap@Sun.COM /*
36*7978SPeter.Dunlap@Sun.COM  * IDM lock order:
37*7978SPeter.Dunlap@Sun.COM  *
38*7978SPeter.Dunlap@Sun.COM  * idm_taskid_table_lock, idm_task_t.idt_mutex
39*7978SPeter.Dunlap@Sun.COM  */
40*7978SPeter.Dunlap@Sun.COM 
41*7978SPeter.Dunlap@Sun.COM #define	CF_LOGIN_READY		0x00000001
42*7978SPeter.Dunlap@Sun.COM #define	CF_INITIAL_LOGIN	0x00000002
43*7978SPeter.Dunlap@Sun.COM #define	CF_ERROR		0x80000000
44*7978SPeter.Dunlap@Sun.COM 
45*7978SPeter.Dunlap@Sun.COM typedef enum {
46*7978SPeter.Dunlap@Sun.COM 	CONN_TYPE_INI = 1,
47*7978SPeter.Dunlap@Sun.COM 	CONN_TYPE_TGT
48*7978SPeter.Dunlap@Sun.COM } idm_conn_type_t;
49*7978SPeter.Dunlap@Sun.COM 
50*7978SPeter.Dunlap@Sun.COM /*
51*7978SPeter.Dunlap@Sun.COM  * Watchdog interval in seconds
52*7978SPeter.Dunlap@Sun.COM  */
53*7978SPeter.Dunlap@Sun.COM #define	IDM_WD_INTERVAL			5
54*7978SPeter.Dunlap@Sun.COM 
55*7978SPeter.Dunlap@Sun.COM /*
56*7978SPeter.Dunlap@Sun.COM  * Timeout period before a TRANSPORT_FAIL event is generated in seconds
57*7978SPeter.Dunlap@Sun.COM  * if the connection is idle.
58*7978SPeter.Dunlap@Sun.COM  */
59*7978SPeter.Dunlap@Sun.COM #define	IDM_TRANSPORT_FAIL_IDLE_TIMEOUT	30
60*7978SPeter.Dunlap@Sun.COM 
61*7978SPeter.Dunlap@Sun.COM /*
62*7978SPeter.Dunlap@Sun.COM  * IDM reference count structure.  Audit code is shamelessly adapted
63*7978SPeter.Dunlap@Sun.COM  * from CIFS server.
64*7978SPeter.Dunlap@Sun.COM  */
65*7978SPeter.Dunlap@Sun.COM 
66*7978SPeter.Dunlap@Sun.COM #define	REFCNT_AUDIT_STACK_DEPTH	16
67*7978SPeter.Dunlap@Sun.COM #define	REFCNT_AUDIT_BUF_MAX_REC	16
68*7978SPeter.Dunlap@Sun.COM 
69*7978SPeter.Dunlap@Sun.COM typedef struct {
70*7978SPeter.Dunlap@Sun.COM 	uint32_t		anr_refcnt;
71*7978SPeter.Dunlap@Sun.COM 	int			anr_depth;
72*7978SPeter.Dunlap@Sun.COM 	pc_t			anr_stack[REFCNT_AUDIT_STACK_DEPTH];
73*7978SPeter.Dunlap@Sun.COM } refcnt_audit_record_t;
74*7978SPeter.Dunlap@Sun.COM 
75*7978SPeter.Dunlap@Sun.COM typedef struct {
76*7978SPeter.Dunlap@Sun.COM 	int			anb_index;
77*7978SPeter.Dunlap@Sun.COM 	int			anb_max_index;
78*7978SPeter.Dunlap@Sun.COM 	refcnt_audit_record_t	anb_records[REFCNT_AUDIT_BUF_MAX_REC];
79*7978SPeter.Dunlap@Sun.COM } refcnt_audit_buf_t;
80*7978SPeter.Dunlap@Sun.COM 
81*7978SPeter.Dunlap@Sun.COM #define	REFCNT_AUDIT(_rf_) {				\
82*7978SPeter.Dunlap@Sun.COM 	refcnt_audit_record_t	*anr;			\
83*7978SPeter.Dunlap@Sun.COM 							\
84*7978SPeter.Dunlap@Sun.COM 	anr = (_rf_)->ir_audit_buf.anb_records;		\
85*7978SPeter.Dunlap@Sun.COM 	anr += (_rf_)->ir_audit_buf.anb_index;		\
86*7978SPeter.Dunlap@Sun.COM 	(_rf_)->ir_audit_buf.anb_index++;		\
87*7978SPeter.Dunlap@Sun.COM 	(_rf_)->ir_audit_buf.anb_index &=		\
88*7978SPeter.Dunlap@Sun.COM 	    (_rf_)->ir_audit_buf.anb_max_index;		\
89*7978SPeter.Dunlap@Sun.COM 	anr->anr_refcnt = (_rf_)->ir_refcnt;		\
90*7978SPeter.Dunlap@Sun.COM 	anr->anr_depth = getpcstack(anr->anr_stack,	\
91*7978SPeter.Dunlap@Sun.COM 	    REFCNT_AUDIT_STACK_DEPTH);			\
92*7978SPeter.Dunlap@Sun.COM }
93*7978SPeter.Dunlap@Sun.COM 
94*7978SPeter.Dunlap@Sun.COM struct idm_refcnt_s;
95*7978SPeter.Dunlap@Sun.COM 
96*7978SPeter.Dunlap@Sun.COM typedef void (idm_refcnt_cb_t)(void *ref_obj);
97*7978SPeter.Dunlap@Sun.COM 
98*7978SPeter.Dunlap@Sun.COM typedef enum {
99*7978SPeter.Dunlap@Sun.COM 	REF_NOWAIT,
100*7978SPeter.Dunlap@Sun.COM 	REF_WAIT_SYNC,
101*7978SPeter.Dunlap@Sun.COM 	REF_WAIT_ASYNC
102*7978SPeter.Dunlap@Sun.COM } idm_refcnt_wait_t;
103*7978SPeter.Dunlap@Sun.COM 
104*7978SPeter.Dunlap@Sun.COM typedef struct idm_refcnt_s {
105*7978SPeter.Dunlap@Sun.COM 	int			ir_refcnt;
106*7978SPeter.Dunlap@Sun.COM 	void			*ir_referenced_obj;
107*7978SPeter.Dunlap@Sun.COM 	idm_refcnt_wait_t	ir_waiting;
108*7978SPeter.Dunlap@Sun.COM 	kmutex_t		ir_mutex;
109*7978SPeter.Dunlap@Sun.COM 	kcondvar_t		ir_cv;
110*7978SPeter.Dunlap@Sun.COM 	idm_refcnt_cb_t		*ir_cb;
111*7978SPeter.Dunlap@Sun.COM 	refcnt_audit_buf_t	ir_audit_buf;
112*7978SPeter.Dunlap@Sun.COM } idm_refcnt_t;
113*7978SPeter.Dunlap@Sun.COM 
114*7978SPeter.Dunlap@Sun.COM /*
115*7978SPeter.Dunlap@Sun.COM  * connection parameters - These parameters would be populated at
116*7978SPeter.Dunlap@Sun.COM  * connection create, or during key-value negotiation at login
117*7978SPeter.Dunlap@Sun.COM  */
118*7978SPeter.Dunlap@Sun.COM typedef struct idm_conn_params_s {
119*7978SPeter.Dunlap@Sun.COM 	uint32_t		max_dataseglen;
120*7978SPeter.Dunlap@Sun.COM } idm_conn_param_t;
121*7978SPeter.Dunlap@Sun.COM 
122*7978SPeter.Dunlap@Sun.COM typedef struct idm_svc_s {
123*7978SPeter.Dunlap@Sun.COM 	list_node_t		is_list_node;
124*7978SPeter.Dunlap@Sun.COM 	kmutex_t		is_mutex;
125*7978SPeter.Dunlap@Sun.COM 	kcondvar_t		is_cv;
126*7978SPeter.Dunlap@Sun.COM 	kmutex_t		is_count_mutex;
127*7978SPeter.Dunlap@Sun.COM 	kcondvar_t		is_count_cv;
128*7978SPeter.Dunlap@Sun.COM 	idm_refcnt_t		is_refcnt;
129*7978SPeter.Dunlap@Sun.COM 	int			is_online;
130*7978SPeter.Dunlap@Sun.COM 	/* transport-specific service components */
131*7978SPeter.Dunlap@Sun.COM 	void			*is_so_svc;
132*7978SPeter.Dunlap@Sun.COM 	void			*is_iser_svc;
133*7978SPeter.Dunlap@Sun.COM 	idm_svc_req_t		is_svc_req;
134*7978SPeter.Dunlap@Sun.COM } idm_svc_t;
135*7978SPeter.Dunlap@Sun.COM 
136*7978SPeter.Dunlap@Sun.COM typedef struct idm_conn_s {
137*7978SPeter.Dunlap@Sun.COM 	list_node_t		ic_list_node;
138*7978SPeter.Dunlap@Sun.COM 	void			*ic_handle;
139*7978SPeter.Dunlap@Sun.COM 	idm_refcnt_t		ic_refcnt;
140*7978SPeter.Dunlap@Sun.COM 	idm_svc_t		*ic_svc_binding; /* Target conn. only */
141*7978SPeter.Dunlap@Sun.COM 	idm_sockaddr_t 		ic_ini_dst_addr;
142*7978SPeter.Dunlap@Sun.COM 	struct sockaddr_storage	ic_laddr;	/* conn local address */
143*7978SPeter.Dunlap@Sun.COM 	struct sockaddr_storage	ic_raddr;	/* conn remote address */
144*7978SPeter.Dunlap@Sun.COM 	idm_conn_state_t	ic_state;
145*7978SPeter.Dunlap@Sun.COM 	idm_conn_state_t	ic_last_state;
146*7978SPeter.Dunlap@Sun.COM 	sm_audit_buf_t		ic_state_audit;
147*7978SPeter.Dunlap@Sun.COM 	kmutex_t		ic_state_mutex;
148*7978SPeter.Dunlap@Sun.COM 	kcondvar_t		ic_state_cv;
149*7978SPeter.Dunlap@Sun.COM 	uint32_t		ic_state_flags;
150*7978SPeter.Dunlap@Sun.COM 	timeout_id_t		ic_state_timeout;
151*7978SPeter.Dunlap@Sun.COM 	struct idm_conn_s	*ic_reinstate_conn; /* For conn reinst. */
152*7978SPeter.Dunlap@Sun.COM 	struct idm_conn_s	*ic_logout_conn; /* For other conn logout */
153*7978SPeter.Dunlap@Sun.COM 	taskq_t			*ic_state_taskq;
154*7978SPeter.Dunlap@Sun.COM 	int			ic_pdu_events;
155*7978SPeter.Dunlap@Sun.COM 	boolean_t		ic_login_info_valid;
156*7978SPeter.Dunlap@Sun.COM 	boolean_t		ic_rdma_extensions;
157*7978SPeter.Dunlap@Sun.COM 	uint16_t		ic_login_cid;
158*7978SPeter.Dunlap@Sun.COM 
159*7978SPeter.Dunlap@Sun.COM 	kmutex_t		ic_mutex;
160*7978SPeter.Dunlap@Sun.COM 	kcondvar_t		ic_cv;
161*7978SPeter.Dunlap@Sun.COM 	idm_status_t		ic_conn_sm_status;
162*7978SPeter.Dunlap@Sun.COM 
163*7978SPeter.Dunlap@Sun.COM 	boolean_t		ic_ffp;
164*7978SPeter.Dunlap@Sun.COM 	uint32_t		ic_internal_cid;
165*7978SPeter.Dunlap@Sun.COM 
166*7978SPeter.Dunlap@Sun.COM 	uint32_t		ic_conn_flags;
167*7978SPeter.Dunlap@Sun.COM 	idm_conn_type_t		ic_conn_type;
168*7978SPeter.Dunlap@Sun.COM 	idm_conn_ops_t		ic_conn_ops;
169*7978SPeter.Dunlap@Sun.COM 	idm_transport_ops_t	*ic_transport_ops;
170*7978SPeter.Dunlap@Sun.COM 	idm_transport_type_t	ic_transport_type;
171*7978SPeter.Dunlap@Sun.COM 	int			ic_transport_hdrlen;
172*7978SPeter.Dunlap@Sun.COM 	void			*ic_transport_private;
173*7978SPeter.Dunlap@Sun.COM 	idm_conn_param_t	ic_conn_params;
174*7978SPeter.Dunlap@Sun.COM 	/*
175*7978SPeter.Dunlap@Sun.COM 	 * Save client callback to interpose idm callback
176*7978SPeter.Dunlap@Sun.COM 	 */
177*7978SPeter.Dunlap@Sun.COM 	idm_pdu_cb_t		*ic_client_callback;
178*7978SPeter.Dunlap@Sun.COM 	clock_t			ic_timestamp;
179*7978SPeter.Dunlap@Sun.COM } idm_conn_t;
180*7978SPeter.Dunlap@Sun.COM 
181*7978SPeter.Dunlap@Sun.COM #define	IDM_CONN_HEADER_DIGEST	0x00000001
182*7978SPeter.Dunlap@Sun.COM #define	IDM_CONN_DATA_DIGEST	0x00000002
183*7978SPeter.Dunlap@Sun.COM #define	IDM_CONN_USE_SCOREBOARD	0x00000004
184*7978SPeter.Dunlap@Sun.COM 
185*7978SPeter.Dunlap@Sun.COM #define	IDM_CONN_ISINI(ICI_IC)	((ICI_IC)->ic_conn_type == CONN_TYPE_INI)
186*7978SPeter.Dunlap@Sun.COM #define	IDM_CONN_ISTGT(ICI_IC)	((ICI_IC)->ic_conn_type == CONN_TYPE_TGT)
187*7978SPeter.Dunlap@Sun.COM 
188*7978SPeter.Dunlap@Sun.COM /*
189*7978SPeter.Dunlap@Sun.COM  * An IDM target task can transfer data using multiple buffers. The task
190*7978SPeter.Dunlap@Sun.COM  * will maintain a list of buffers, and each buffer will contain the relative
191*7978SPeter.Dunlap@Sun.COM  * offset of the transfer and a pointer to the next buffer in the list.
192*7978SPeter.Dunlap@Sun.COM  *
193*7978SPeter.Dunlap@Sun.COM  * Note on client private data:
194*7978SPeter.Dunlap@Sun.COM  * idt_private is intended to be a pointer to some sort of client-
195*7978SPeter.Dunlap@Sun.COM  * specific state.
196*7978SPeter.Dunlap@Sun.COM  *
197*7978SPeter.Dunlap@Sun.COM  * idt_client_handle is a more generic client-private piece of data that can
198*7978SPeter.Dunlap@Sun.COM  * be used by the client for the express purpose of task lookup.  The driving
199*7978SPeter.Dunlap@Sun.COM  * use case for this is for the client to store the initiator task tag for
200*7978SPeter.Dunlap@Sun.COM  * a given task so that it may be more easily retrieved for task management.
201*7978SPeter.Dunlap@Sun.COM  *
202*7978SPeter.Dunlap@Sun.COM  * The key take away here is that clients should never call
203*7978SPeter.Dunlap@Sun.COM  * idm_task_find_by_handle in the performance path.
204*7978SPeter.Dunlap@Sun.COM  *
205*7978SPeter.Dunlap@Sun.COM  * An initiator will require only one buffer per task, the offset will be 0.
206*7978SPeter.Dunlap@Sun.COM  */
207*7978SPeter.Dunlap@Sun.COM 
208*7978SPeter.Dunlap@Sun.COM typedef struct idm_task_s {
209*7978SPeter.Dunlap@Sun.COM 	idm_conn_t		*idt_ic;	/* Associated connection */
210*7978SPeter.Dunlap@Sun.COM 	/* connection type is in idt_ic->ic_conn_type */
211*7978SPeter.Dunlap@Sun.COM 	kmutex_t		idt_mutex;
212*7978SPeter.Dunlap@Sun.COM 	void			*idt_private;	/* Client private data */
213*7978SPeter.Dunlap@Sun.COM 	uintptr_t		idt_client_handle;	/* Client private */
214*7978SPeter.Dunlap@Sun.COM 	uint32_t		idt_tt;		/* Task tag */
215*7978SPeter.Dunlap@Sun.COM 	uint32_t		idt_r2t_ttt;	/* R2T Target Task tag */
216*7978SPeter.Dunlap@Sun.COM 	idm_task_state_t	idt_state;
217*7978SPeter.Dunlap@Sun.COM 	idm_refcnt_t		idt_refcnt;
218*7978SPeter.Dunlap@Sun.COM 
219*7978SPeter.Dunlap@Sun.COM 	/*
220*7978SPeter.Dunlap@Sun.COM 	 * Statistics
221*7978SPeter.Dunlap@Sun.COM 	 */
222*7978SPeter.Dunlap@Sun.COM 	int			idt_tx_to_ini_start;
223*7978SPeter.Dunlap@Sun.COM 	int			idt_tx_to_ini_done;
224*7978SPeter.Dunlap@Sun.COM 	int			idt_rx_from_ini_start;
225*7978SPeter.Dunlap@Sun.COM 	int			idt_rx_from_ini_done;
226*7978SPeter.Dunlap@Sun.COM 
227*7978SPeter.Dunlap@Sun.COM 	uint32_t		idt_exp_datasn;	/* expected datasn */
228*7978SPeter.Dunlap@Sun.COM 	uint32_t		idt_exp_rttsn;	/* expected rttsn */
229*7978SPeter.Dunlap@Sun.COM 	list_t			idt_inbufv;	/* chunks of IN buffers */
230*7978SPeter.Dunlap@Sun.COM 	list_t			idt_outbufv;	/* chunks of OUT buffers */
231*7978SPeter.Dunlap@Sun.COM 
232*7978SPeter.Dunlap@Sun.COM 	/*
233*7978SPeter.Dunlap@Sun.COM 	 * Transport header, which describes this tasks remote tagged buffer
234*7978SPeter.Dunlap@Sun.COM 	 */
235*7978SPeter.Dunlap@Sun.COM 	int			idt_transport_hdrlen;
236*7978SPeter.Dunlap@Sun.COM 	void			*idt_transport_hdr;
237*7978SPeter.Dunlap@Sun.COM } idm_task_t;
238*7978SPeter.Dunlap@Sun.COM 
239*7978SPeter.Dunlap@Sun.COM int idm_task_constructor(void *task_void, void *arg, int flags);
240*7978SPeter.Dunlap@Sun.COM void idm_task_destructor(void *task_void, void *arg);
241*7978SPeter.Dunlap@Sun.COM 
242*7978SPeter.Dunlap@Sun.COM #define	IDM_TASKIDS_MAX		16384
243*7978SPeter.Dunlap@Sun.COM #define	IDM_BUF_MAGIC		0x49425546	/* "IBUF" */
244*7978SPeter.Dunlap@Sun.COM 
245*7978SPeter.Dunlap@Sun.COM /* Protect with task mutex */
246*7978SPeter.Dunlap@Sun.COM typedef struct idm_buf_s {
247*7978SPeter.Dunlap@Sun.COM 	uint32_t	idb_magic;	/* "IBUF" */
248*7978SPeter.Dunlap@Sun.COM 
249*7978SPeter.Dunlap@Sun.COM 	/*
250*7978SPeter.Dunlap@Sun.COM 	 * Note: idm_tx_link *must* be the second element in the list for
251*7978SPeter.Dunlap@Sun.COM 	 * proper TX PDU ordering.
252*7978SPeter.Dunlap@Sun.COM 	 */
253*7978SPeter.Dunlap@Sun.COM 	list_node_t	idm_tx_link;	/* link in a list of TX objects */
254*7978SPeter.Dunlap@Sun.COM 
255*7978SPeter.Dunlap@Sun.COM 	list_node_t	idb_buflink;	/* link in a multi-buffer data xfer */
256*7978SPeter.Dunlap@Sun.COM 	idm_conn_t	*idb_ic;	/* Associated connection */
257*7978SPeter.Dunlap@Sun.COM 	void		*idb_buf;	/* data */
258*7978SPeter.Dunlap@Sun.COM 	uint64_t	idb_buflen;	/* length of buffer */
259*7978SPeter.Dunlap@Sun.COM 	size_t		idb_bufoffset;	/* offset in a multi-buffer xfer */
260*7978SPeter.Dunlap@Sun.COM 	boolean_t	idb_bufalloc;  /* true if alloc'd in idm_buf_alloc */
261*7978SPeter.Dunlap@Sun.COM 	/*
262*7978SPeter.Dunlap@Sun.COM 	 * DataPDUInOrder=Yes, so to track that the PDUs in a sequence are sent
263*7978SPeter.Dunlap@Sun.COM 	 * in continuously increasing address order, check that offsets for a
264*7978SPeter.Dunlap@Sun.COM 	 * single buffer xfer are in order.
265*7978SPeter.Dunlap@Sun.COM 	 */
266*7978SPeter.Dunlap@Sun.COM 	uint32_t	idb_exp_offset;
267*7978SPeter.Dunlap@Sun.COM 	size_t		idb_xfer_len;	/* Current requested xfer len */
268*7978SPeter.Dunlap@Sun.COM 	void		*idb_buf_private; /* transport-specific buf handle */
269*7978SPeter.Dunlap@Sun.COM 	void		*idb_reg_private; /* transport-specific reg handle */
270*7978SPeter.Dunlap@Sun.COM 	idm_buf_cb_t	*idb_buf_cb;	/* Data Completion Notify, tgt only */
271*7978SPeter.Dunlap@Sun.COM 	void		*idb_cb_arg;	/* Client private data */
272*7978SPeter.Dunlap@Sun.COM 	idm_task_t	*idb_task_binding;
273*7978SPeter.Dunlap@Sun.COM 	boolean_t	idb_in_transport;
274*7978SPeter.Dunlap@Sun.COM 	boolean_t	idb_tx_thread;		/* Sockets only */
275*7978SPeter.Dunlap@Sun.COM 	iscsi_hdr_t	idb_data_hdr_tmpl;	/* Sockets only */
276*7978SPeter.Dunlap@Sun.COM 	idm_status_t	idb_status;
277*7978SPeter.Dunlap@Sun.COM } idm_buf_t;
278*7978SPeter.Dunlap@Sun.COM 
279*7978SPeter.Dunlap@Sun.COM #define	PDU_MAX_IOVLEN	12
280*7978SPeter.Dunlap@Sun.COM #define	IDM_PDU_MAGIC	0x49504455	/* "IPDU" */
281*7978SPeter.Dunlap@Sun.COM 
282*7978SPeter.Dunlap@Sun.COM typedef struct idm_pdu_s {
283*7978SPeter.Dunlap@Sun.COM 	uint32_t	isp_magic;	/* "IPDU" */
284*7978SPeter.Dunlap@Sun.COM 
285*7978SPeter.Dunlap@Sun.COM 	/*
286*7978SPeter.Dunlap@Sun.COM 	 * Internal - Order is vital.  idm_tx_link *must* be the second
287*7978SPeter.Dunlap@Sun.COM 	 * element in this structure for proper TX PDU ordering.
288*7978SPeter.Dunlap@Sun.COM 	 */
289*7978SPeter.Dunlap@Sun.COM 	list_node_t	idm_tx_link;
290*7978SPeter.Dunlap@Sun.COM 
291*7978SPeter.Dunlap@Sun.COM 	list_node_t	isp_client_lnd;
292*7978SPeter.Dunlap@Sun.COM 
293*7978SPeter.Dunlap@Sun.COM 	idm_conn_t	*isp_ic;	/* Must be set */
294*7978SPeter.Dunlap@Sun.COM 	iscsi_hdr_t	*isp_hdr;
295*7978SPeter.Dunlap@Sun.COM 	uint_t		isp_hdrlen;
296*7978SPeter.Dunlap@Sun.COM 	uint8_t		*isp_data;
297*7978SPeter.Dunlap@Sun.COM 	uint_t		isp_datalen;
298*7978SPeter.Dunlap@Sun.COM 
299*7978SPeter.Dunlap@Sun.COM 	/* Transport header */
300*7978SPeter.Dunlap@Sun.COM 	void		*isp_transport_hdr;
301*7978SPeter.Dunlap@Sun.COM 	uint32_t	isp_transport_hdrlen;
302*7978SPeter.Dunlap@Sun.COM 	void		*isp_transport_private;
303*7978SPeter.Dunlap@Sun.COM 
304*7978SPeter.Dunlap@Sun.COM 	/*
305*7978SPeter.Dunlap@Sun.COM 	 * isp_data is used for sending SCSI status, NOP, text, scsi and
306*7978SPeter.Dunlap@Sun.COM 	 * non-scsi data. Data is received using isp_iov and isp_iovlen
307*7978SPeter.Dunlap@Sun.COM 	 * to support data over multiple buffers.
308*7978SPeter.Dunlap@Sun.COM 	 */
309*7978SPeter.Dunlap@Sun.COM 	void		*isp_private;
310*7978SPeter.Dunlap@Sun.COM 	idm_pdu_cb_t	*isp_callback;
311*7978SPeter.Dunlap@Sun.COM 	idm_status_t	isp_status;
312*7978SPeter.Dunlap@Sun.COM 
313*7978SPeter.Dunlap@Sun.COM 	/*
314*7978SPeter.Dunlap@Sun.COM 	 * The following four elements are only used in
315*7978SPeter.Dunlap@Sun.COM 	 * idm_sorecv_scsidata() currently.
316*7978SPeter.Dunlap@Sun.COM 	 */
317*7978SPeter.Dunlap@Sun.COM 	struct iovec	isp_iov[PDU_MAX_IOVLEN];
318*7978SPeter.Dunlap@Sun.COM 	int		isp_iovlen;
319*7978SPeter.Dunlap@Sun.COM 	idm_buf_t	*isp_sorx_buf;
320*7978SPeter.Dunlap@Sun.COM 
321*7978SPeter.Dunlap@Sun.COM 	/* Implementation data for idm_pdu_alloc and sorx PDU cache */
322*7978SPeter.Dunlap@Sun.COM 	uint32_t	isp_flags;
323*7978SPeter.Dunlap@Sun.COM 	uint_t		isp_hdrbuflen;
324*7978SPeter.Dunlap@Sun.COM 	uint_t		isp_databuflen;
325*7978SPeter.Dunlap@Sun.COM } idm_pdu_t;
326*7978SPeter.Dunlap@Sun.COM 
327*7978SPeter.Dunlap@Sun.COM /*
328*7978SPeter.Dunlap@Sun.COM  * This "generic" object is used when removing an item from the ic_tx_list
329*7978SPeter.Dunlap@Sun.COM  * in order to determine whether it's an idm_pdu_t or an idm_buf_t
330*7978SPeter.Dunlap@Sun.COM  */
331*7978SPeter.Dunlap@Sun.COM 
332*7978SPeter.Dunlap@Sun.COM typedef struct {
333*7978SPeter.Dunlap@Sun.COM 	uint32_t	idm_tx_obj_magic;
334*7978SPeter.Dunlap@Sun.COM 	/*
335*7978SPeter.Dunlap@Sun.COM 	 * idm_tx_link *must* be the second element in this structure.
336*7978SPeter.Dunlap@Sun.COM 	 */
337*7978SPeter.Dunlap@Sun.COM 	list_node_t	idm_tx_link;
338*7978SPeter.Dunlap@Sun.COM } idm_tx_obj_t;
339*7978SPeter.Dunlap@Sun.COM 
340*7978SPeter.Dunlap@Sun.COM 
341*7978SPeter.Dunlap@Sun.COM #define	IDM_PDU_OPCODE(PDU) \
342*7978SPeter.Dunlap@Sun.COM 	((PDU)->isp_hdr->opcode & ISCSI_OPCODE_MASK)
343*7978SPeter.Dunlap@Sun.COM 
344*7978SPeter.Dunlap@Sun.COM #define	IDM_PDU_ALLOC		0x00000001
345*7978SPeter.Dunlap@Sun.COM #define	IDM_PDU_ADDL_HDR	0x00000002
346*7978SPeter.Dunlap@Sun.COM #define	IDM_PDU_ADDL_DATA	0x00000004
347*7978SPeter.Dunlap@Sun.COM #define	IDM_PDU_LOGIN_TX	0x00000008
348*7978SPeter.Dunlap@Sun.COM 
349*7978SPeter.Dunlap@Sun.COM #define	OSD_EXT_CDB_AHSLEN	(200 - 15)
350*7978SPeter.Dunlap@Sun.COM #define	BIDI_AHS_LENGTH		5
351*7978SPeter.Dunlap@Sun.COM #define	IDM_SORX_CACHE_AHSLEN \
352*7978SPeter.Dunlap@Sun.COM 	(((OSD_EXT_CDB_AHSLEN + 3) + \
353*7978SPeter.Dunlap@Sun.COM 	    (BIDI_AHS_LENGTH + 3)) / sizeof (uint32_t))
354*7978SPeter.Dunlap@Sun.COM #define	IDM_SORX_CACHE_HDRLEN	(sizeof (iscsi_hdr_t) + IDM_SORX_CACHE_AHSLEN)
355*7978SPeter.Dunlap@Sun.COM 
356*7978SPeter.Dunlap@Sun.COM /*
357*7978SPeter.Dunlap@Sun.COM  * ID pool
358*7978SPeter.Dunlap@Sun.COM  */
359*7978SPeter.Dunlap@Sun.COM 
360*7978SPeter.Dunlap@Sun.COM #define	IDM_IDPOOL_MAGIC	0x4944504C	/* IDPL */
361*7978SPeter.Dunlap@Sun.COM #define	IDM_IDPOOL_MIN_SIZE	64	/* Number of IDs to begin with */
362*7978SPeter.Dunlap@Sun.COM #define	IDM_IDPOOL_MAX_SIZE	64 * 1024
363*7978SPeter.Dunlap@Sun.COM 
364*7978SPeter.Dunlap@Sun.COM typedef struct idm_idpool {
365*7978SPeter.Dunlap@Sun.COM 	uint32_t	id_magic;
366*7978SPeter.Dunlap@Sun.COM 	kmutex_t	id_mutex;
367*7978SPeter.Dunlap@Sun.COM 	uint8_t		*id_pool;
368*7978SPeter.Dunlap@Sun.COM 	uint32_t	id_size;
369*7978SPeter.Dunlap@Sun.COM 	uint8_t		id_bit;
370*7978SPeter.Dunlap@Sun.COM 	uint8_t		id_bit_idx;
371*7978SPeter.Dunlap@Sun.COM 	uint32_t	id_idx;
372*7978SPeter.Dunlap@Sun.COM 	uint32_t	id_idx_msk;
373*7978SPeter.Dunlap@Sun.COM 	uint32_t	id_free_counter;
374*7978SPeter.Dunlap@Sun.COM 	uint32_t	id_max_free_counter;
375*7978SPeter.Dunlap@Sun.COM } idm_idpool_t;
376*7978SPeter.Dunlap@Sun.COM 
377*7978SPeter.Dunlap@Sun.COM /*
378*7978SPeter.Dunlap@Sun.COM  * Global IDM state structure
379*7978SPeter.Dunlap@Sun.COM  */
380*7978SPeter.Dunlap@Sun.COM typedef struct {
381*7978SPeter.Dunlap@Sun.COM 	kmutex_t	idm_global_mutex;
382*7978SPeter.Dunlap@Sun.COM 	taskq_t		*idm_global_taskq;
383*7978SPeter.Dunlap@Sun.COM 	kthread_t	*idm_wd_thread;
384*7978SPeter.Dunlap@Sun.COM 	kt_did_t	idm_wd_thread_did;
385*7978SPeter.Dunlap@Sun.COM 	boolean_t	idm_wd_thread_running;
386*7978SPeter.Dunlap@Sun.COM 	kcondvar_t	idm_wd_cv;
387*7978SPeter.Dunlap@Sun.COM 	list_t		idm_tgt_svc_list;
388*7978SPeter.Dunlap@Sun.COM 	kcondvar_t	idm_tgt_svc_cv;
389*7978SPeter.Dunlap@Sun.COM 	list_t		idm_tgt_conn_list;
390*7978SPeter.Dunlap@Sun.COM 	int		idm_tgt_conn_count;
391*7978SPeter.Dunlap@Sun.COM 	list_t		idm_ini_conn_list;
392*7978SPeter.Dunlap@Sun.COM 	kmem_cache_t	*idm_buf_cache;
393*7978SPeter.Dunlap@Sun.COM 	kmem_cache_t	*idm_task_cache;
394*7978SPeter.Dunlap@Sun.COM 	krwlock_t	idm_taskid_table_lock;
395*7978SPeter.Dunlap@Sun.COM 	idm_task_t	**idm_taskid_table;
396*7978SPeter.Dunlap@Sun.COM 	uint32_t	idm_taskid_next;
397*7978SPeter.Dunlap@Sun.COM 	uint32_t	idm_taskid_max;
398*7978SPeter.Dunlap@Sun.COM 	idm_idpool_t	idm_conn_id_pool;
399*7978SPeter.Dunlap@Sun.COM 	kmem_cache_t	*idm_sotx_pdu_cache;
400*7978SPeter.Dunlap@Sun.COM 	kmem_cache_t	*idm_sorx_pdu_cache;
401*7978SPeter.Dunlap@Sun.COM } idm_global_t;
402*7978SPeter.Dunlap@Sun.COM 
403*7978SPeter.Dunlap@Sun.COM idm_global_t	idm; /* Global state */
404*7978SPeter.Dunlap@Sun.COM 
405*7978SPeter.Dunlap@Sun.COM int
406*7978SPeter.Dunlap@Sun.COM idm_idpool_create(idm_idpool_t	*pool);
407*7978SPeter.Dunlap@Sun.COM 
408*7978SPeter.Dunlap@Sun.COM void
409*7978SPeter.Dunlap@Sun.COM idm_idpool_destroy(idm_idpool_t *pool);
410*7978SPeter.Dunlap@Sun.COM 
411*7978SPeter.Dunlap@Sun.COM int
412*7978SPeter.Dunlap@Sun.COM idm_idpool_alloc(idm_idpool_t *pool, uint16_t *id);
413*7978SPeter.Dunlap@Sun.COM 
414*7978SPeter.Dunlap@Sun.COM void
415*7978SPeter.Dunlap@Sun.COM idm_idpool_free(idm_idpool_t *pool, uint16_t id);
416*7978SPeter.Dunlap@Sun.COM 
417*7978SPeter.Dunlap@Sun.COM void
418*7978SPeter.Dunlap@Sun.COM idm_pdu_rx(idm_conn_t *ic, idm_pdu_t *pdu);
419*7978SPeter.Dunlap@Sun.COM 
420*7978SPeter.Dunlap@Sun.COM void
421*7978SPeter.Dunlap@Sun.COM idm_pdu_tx_forward(idm_conn_t *ic, idm_pdu_t *pdu);
422*7978SPeter.Dunlap@Sun.COM 
423*7978SPeter.Dunlap@Sun.COM boolean_t
424*7978SPeter.Dunlap@Sun.COM idm_pdu_rx_forward_ffp(idm_conn_t *ic, idm_pdu_t *pdu);
425*7978SPeter.Dunlap@Sun.COM 
426*7978SPeter.Dunlap@Sun.COM void
427*7978SPeter.Dunlap@Sun.COM idm_pdu_rx_forward(idm_conn_t *ic, idm_pdu_t *pdu);
428*7978SPeter.Dunlap@Sun.COM 
429*7978SPeter.Dunlap@Sun.COM void
430*7978SPeter.Dunlap@Sun.COM idm_pdu_tx_protocol_error(idm_conn_t *ic, idm_pdu_t *pdu);
431*7978SPeter.Dunlap@Sun.COM 
432*7978SPeter.Dunlap@Sun.COM void
433*7978SPeter.Dunlap@Sun.COM idm_pdu_rx_protocol_error(idm_conn_t *ic, idm_pdu_t *pdu);
434*7978SPeter.Dunlap@Sun.COM 
435*7978SPeter.Dunlap@Sun.COM void idm_parse_login_rsp(idm_conn_t *ic, idm_pdu_t *logout_req_pdu,
436*7978SPeter.Dunlap@Sun.COM     boolean_t rx);
437*7978SPeter.Dunlap@Sun.COM 
438*7978SPeter.Dunlap@Sun.COM void idm_parse_logout_req(idm_conn_t *ic, idm_pdu_t *logout_req_pdu,
439*7978SPeter.Dunlap@Sun.COM     boolean_t rx);
440*7978SPeter.Dunlap@Sun.COM 
441*7978SPeter.Dunlap@Sun.COM void idm_parse_logout_rsp(idm_conn_t *ic, idm_pdu_t *login_rsp_pdu,
442*7978SPeter.Dunlap@Sun.COM     boolean_t rx);
443*7978SPeter.Dunlap@Sun.COM 
444*7978SPeter.Dunlap@Sun.COM idm_status_t idm_svc_conn_create(idm_svc_t *is, idm_transport_type_t type,
445*7978SPeter.Dunlap@Sun.COM     idm_conn_t **ic_result);
446*7978SPeter.Dunlap@Sun.COM 
447*7978SPeter.Dunlap@Sun.COM void idm_svc_conn_destroy(idm_conn_t *ic);
448*7978SPeter.Dunlap@Sun.COM 
449*7978SPeter.Dunlap@Sun.COM idm_status_t idm_ini_conn_finish(idm_conn_t *ic);
450*7978SPeter.Dunlap@Sun.COM 
451*7978SPeter.Dunlap@Sun.COM idm_status_t idm_tgt_conn_finish(idm_conn_t *ic);
452*7978SPeter.Dunlap@Sun.COM 
453*7978SPeter.Dunlap@Sun.COM idm_conn_t *idm_conn_create_common(idm_conn_type_t conn_type,
454*7978SPeter.Dunlap@Sun.COM     idm_transport_type_t tt, idm_conn_ops_t *conn_ops);
455*7978SPeter.Dunlap@Sun.COM 
456*7978SPeter.Dunlap@Sun.COM void idm_conn_destroy_common(idm_conn_t *ic);
457*7978SPeter.Dunlap@Sun.COM 
458*7978SPeter.Dunlap@Sun.COM void idm_conn_close(idm_conn_t *ic);
459*7978SPeter.Dunlap@Sun.COM 
460*7978SPeter.Dunlap@Sun.COM uint32_t idm_cid_alloc(void);
461*7978SPeter.Dunlap@Sun.COM 
462*7978SPeter.Dunlap@Sun.COM void idm_cid_free(uint32_t cid);
463*7978SPeter.Dunlap@Sun.COM 
464*7978SPeter.Dunlap@Sun.COM uint32_t idm_crc32c(void *address, unsigned long length);
465*7978SPeter.Dunlap@Sun.COM 
466*7978SPeter.Dunlap@Sun.COM uint32_t idm_crc32c_continued(void *address, unsigned long length,
467*7978SPeter.Dunlap@Sun.COM     uint32_t crc);
468*7978SPeter.Dunlap@Sun.COM 
469*7978SPeter.Dunlap@Sun.COM void idm_listbuf_insert(list_t *lst, idm_buf_t *buf);
470*7978SPeter.Dunlap@Sun.COM 
471*7978SPeter.Dunlap@Sun.COM int idm_task_compare(const void *v1, const void *v2);
472*7978SPeter.Dunlap@Sun.COM 
473*7978SPeter.Dunlap@Sun.COM idm_conn_t *idm_lookup_conn(uint8_t *isid, uint16_t tsih, uint16_t cid);
474*7978SPeter.Dunlap@Sun.COM 
475*7978SPeter.Dunlap@Sun.COM #ifdef	__cplusplus
476*7978SPeter.Dunlap@Sun.COM }
477*7978SPeter.Dunlap@Sun.COM #endif
478*7978SPeter.Dunlap@Sun.COM 
479*7978SPeter.Dunlap@Sun.COM #endif /* _IDM_IMPL_H_ */
480