1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 #ifndef _STMF_IMPL_H
26 #define	_STMF_IMPL_H
27 
28 #include <sys/stmf_defines.h>
29 #include <sys/stmf_ioctl.h>
30 
31 #ifdef	__cplusplus
32 extern "C" {
33 #endif
34 
35 typedef	uint32_t stmf_event_handle_t;
36 #define	STMF_MAX_NUM_EVENTS		(sizeof (stmf_event_handle_t) * 8)
37 #define	STMF_EVENT_ADD(h, e)		(atomic_or_32(&(h), \
38 						((uint32_t)1) << (e)))
39 #define	STMF_EVENT_REMOVE(h, e)		(atomic_and_32(&(h), \
40 						~(((uint32_t)1) << (e))))
41 #define	STMF_EVENT_ENABLED(h, e)	(((h) & ((uint32_t)1) << (e)) != 0)
42 #define	STMF_EVENT_CLEAR_ALL(h)		((h) = 0)
43 #define	STMF_EVENT_ALLOC_HANDLE(h)	((h) = 0)
44 #define	STMF_EVENT_FREE_HANDLE(h)	((h) = 0)
45 
46 struct stmf_i_scsi_task;
47 struct stmf_itl_data;
48 
49 typedef struct stmf_i_lu_provider {
50 	stmf_lu_provider_t	*ilp_lp;
51 	uint32_t		ilp_alloc_size;
52 	uint32_t		ilp_nlus;	/* # LUNs being exported */
53 	uint32_t		ilp_cb_in_progress:1,
54 				ilp_rsvd:31;
55 	struct stmf_i_lu_provider *ilp_next;
56 	struct stmf_pp_data	*ilp_ppd;
57 } stmf_i_lu_provider_t;
58 
59 typedef struct stmf_i_lu {
60 	stmf_lu_t	*ilu_lu;
61 	uint32_t	ilu_alloc_size;
62 	uint32_t	ilu_flags;
63 	uint32_t	ilu_ref_cnt;
64 	uint8_t		ilu_state;
65 	uint8_t		ilu_prev_state;
66 	stmf_event_handle_t ilu_event_hdl;
67 	struct stmf_i_lu *ilu_next;
68 	struct stmf_i_lu *ilu_prev;
69 	char		*ilu_alias;
70 	kmutex_t	ilu_task_lock;
71 	uint32_t	ilu_task_cntr1;
72 	uint32_t	ilu_task_cntr2;
73 	uint32_t	*ilu_cur_task_cntr;
74 	uint32_t	ilu_ntasks;	 /* # of tasks in the ilu_task list */
75 	uint32_t	ilu_ntasks_free;	/* # of tasks that are free */
76 	uint32_t	ilu_ntasks_min_free; /* # minimal free tasks */
77 	struct stmf_i_scsi_task	*ilu_tasks;
78 	struct stmf_i_scsi_task *ilu_free_tasks;
79 	struct stmf_itl_data	*ilu_itl_list;
80 
81 	/* point to the luid entry in stmf_state.stmf_luid_list */
82 	void		*ilu_luid;
83 } stmf_i_lu_t;
84 
85 /*
86  * ilu_flags
87  */
88 #define	ILU_STALL_DEREGISTER		0x0001
89 #define	ILU_RESET_ACTIVE		0x0002
90 
91 typedef struct stmf_i_port_provider {
92 	stmf_port_provider_t	*ipp_pp;
93 	uint32_t		ipp_alloc_size;
94 	uint32_t		ipp_npps;
95 	uint32_t		ipp_cb_in_progress:1,
96 				ipp_rsvd:31;
97 	struct stmf_i_port_provider *ipp_next;
98 	struct stmf_pp_data	*ipp_ppd;
99 } stmf_i_port_provider_t;
100 
101 typedef struct stmf_i_local_port {
102 	stmf_local_port_t	*ilport_lport;
103 	uint32_t		ilport_alloc_size;
104 	uint32_t		ilport_nsessions;
105 	struct stmf_i_scsi_session *ilport_ss_list;
106 	krwlock_t		ilport_lock;
107 	struct stmf_i_local_port *ilport_next;
108 	struct stmf_i_local_port *ilport_prev;
109 	uint8_t			ilport_state;
110 	uint8_t			ilport_prev_state;
111 	uint16_t		ilport_rtpid; /* relative tpid */
112 	stmf_event_handle_t	ilport_event_hdl;
113 	clock_t			ilport_last_online_clock;
114 	clock_t			ilport_avg_interval;
115 	uint32_t		ilport_online_times;
116 	uint32_t		ilport_flags;
117 	/* which target group this port belongs to in stmf_state.stmf_tg_list */
118 	void			*ilport_tg;
119 	/* XXX Need something to track all the remote ports also */
120 } stmf_i_local_port_t;
121 
122 #define	STMF_AVG_ONLINE_INTERVAL	(30 * drv_usectohz(1000000))
123 
124 /*
125  * ilport flags
126  */
127 #define	ILPORT_FORCED_OFFLINE		0x01
128 #define	ILPORT_SS_GOT_INITIAL_LUNS	0x02
129 
130 typedef struct stmf_i_scsi_session {
131 	stmf_scsi_session_t	*iss_ss;
132 	uint32_t		iss_alloc_size;
133 	uint32_t		iss_flags;
134 	struct stmf_i_scsi_session *iss_next;
135 	/*
136 	 * Ideally we should maintain 2 maps. One would indicate a new map
137 	 * which will become available only upon receipt of a REPORT LUN
138 	 * cmd.
139 	 */
140 	struct stmf_lun_map	*iss_sm;
141 	/*
142 	 * which host group the host of this session belongs to in
143 	 * stmf_state.stmf_hg_list
144 	 */
145 	void			*iss_hg;
146 	krwlock_t		*iss_lockp;
147 	time_t			iss_creation_time;
148 } stmf_i_scsi_session_t;
149 
150 /*
151  * iss flags
152  */
153 #define	ISS_LUN_INVENTORY_CHANGED		0x0001
154 #define	ISS_RESET_ACTIVE			0x0002
155 #define	ISS_BEING_CREATED			0x0004
156 #define	ISS_GOT_INITIAL_LUNS			0x0008
157 #define	ISS_EVENT_ACTIVE			0x0010
158 
159 #define	ITASK_MAX_NCMDS			14
160 #define	ITASK_DEFAULT_POLL_TIMEOUT	0
161 struct stmf_worker;
162 typedef struct stmf_i_scsi_task {
163 	scsi_task_t		*itask_task;
164 	uint32_t		itask_alloc_size;
165 	uint32_t		itask_flags;
166 	struct stmf_worker	*itask_worker;
167 	uint32_t		*itask_ilu_task_cntr;
168 	struct stmf_i_scsi_task	*itask_worker_next;
169 	struct stmf_i_scsi_task	*itask_lu_next;
170 	struct stmf_i_scsi_task	*itask_lu_prev;
171 	struct stmf_i_scsi_task	*itask_lu_free_next;
172 	struct stmf_i_scsi_task	*itask_abort_next;
173 	struct stmf_itl_data	*itask_itl_datap;
174 	clock_t			itask_start_time;	/* abort and normal */
175 	/* For now we only support 4 parallel buffers. Should be enough. */
176 	stmf_data_buf_t		*itask_dbufs[4];
177 	clock_t			itask_poll_timeout;
178 	uint8_t			itask_cmd_stack[ITASK_MAX_NCMDS];
179 	uint8_t			itask_ncmds;
180 	uint8_t			itask_allocated_buf_map;
181 	uint16_t		itask_cdb_buf_size;
182 } stmf_i_scsi_task_t;
183 
184 #define	ITASK_DEFAULT_ABORT_TIMEOUT	5
185 
186 /*
187  * itask_flags
188  */
189 #define	ITASK_IN_FREE_LIST		0x0001
190 #define	ITASK_IN_TRANSITION		0x0002
191 #define	ITASK_IN_WORKER_QUEUE		0x0004
192 #define	ITASK_BEING_ABORTED		0x0008
193 #define	ITASK_BEING_COMPLETED		0x0010
194 #define	ITASK_KNOWN_TO_TGT_PORT		0x0020
195 #define	ITASK_KNOWN_TO_LU		0x0040
196 #define	ITASK_LU_ABORT_CALLED		0x0080
197 #define	ITASK_TGT_PORT_ABORT_CALLED	0x0100
198 #define	ITASK_DEFAULT_HANDLING		0x0200
199 #define	ITASK_CAUSING_LU_RESET		0x0400
200 #define	ITASK_CAUSING_TARGET_RESET	0x0800
201 
202 /*
203  * itask cmds.
204  */
205 #define	ITASK_CMD_MASK			0x1F
206 #define	ITASK_CMD_BUF_NDX(cmd)		(((uint8_t)(cmd)) >> 5)
207 #define	ITASK_CMD_NEW_TASK		0x1
208 #define	ITASK_CMD_DATA_XFER_DONE	0x2
209 #define	ITASK_CMD_STATUS_DONE		0x3
210 #define	ITASK_CMD_ABORT			0x4
211 #define	ITASK_CMD_SEND_STATUS		0x5
212 #define	ITASK_CMD_POLL			0x10
213 #define	ITASK_CMD_POLL_LU		(ITASK_CMD_POLL | 1)
214 #define	ITASK_CMD_POLL_LPORT		(ITASK_CMD_POLL | 2)
215 
216 /*
217  * struct maintained on a per itl basis when the lu registers ITL handle.
218  */
219 typedef struct stmf_itl_data {
220 	uint32_t			itl_counter;
221 	uint8_t				itl_flags;
222 	uint8_t				itl_hdlrm_reason;
223 	uint16_t			itl_lun;
224 	void				*itl_handle;
225 	struct stmf_i_scsi_session	*itl_session;
226 	struct stmf_itl_data		*itl_next;
227 } stmf_itl_data_t;
228 
229 /*
230  * itl flags
231  */
232 #define	STMF_ITL_BEING_TERMINATED	0x01
233 
234 /*
235  * data structures to maintain provider private data.
236  */
237 typedef struct stmf_pp_data {
238 	struct stmf_pp_data	*ppd_next;
239 	void			*ppd_provider;
240 	nvlist_t		*ppd_nv;
241 	uint32_t		ppd_lu_provider:1,
242 				ppd_port_provider:1,
243 				ppd_rsvd:30;
244 	uint32_t		ppd_alloc_size;
245 	char			ppd_name[8];
246 } stmf_pp_data_t;
247 
248 typedef struct stmf_worker {
249 	kthread_t		*worker_tid;
250 	stmf_i_scsi_task_t	*worker_task_head;
251 	stmf_i_scsi_task_t	*worker_task_tail;
252 	stmf_i_scsi_task_t	*worker_wait_head;
253 	stmf_i_scsi_task_t	*worker_wait_tail;
254 	kmutex_t		worker_lock;
255 	kcondvar_t		worker_cv;
256 	uint32_t		worker_flags;
257 	uint32_t		worker_queue_depth;	/* ntasks cur queued */
258 	uint32_t		worker_max_qdepth_pu;	/* maxqd / unit time */
259 	uint32_t		worker_max_sys_qdepth_pu; /* for all workers */
260 	uint32_t		worker_ref_count;	/* # IOs referencing */
261 } stmf_worker_t;
262 
263 /*
264  * worker flags
265  */
266 #define	STMF_WORKER_STARTED		1
267 #define	STMF_WORKER_ACTIVE		2
268 #define	STMF_WORKER_TERMINATE		4
269 
270 /*
271  * data struct for managing transfers.
272  */
273 typedef struct stmf_xfer_data {
274 	uint32_t	alloc_size;	/* Including this struct */
275 	uint32_t	size_done;
276 	uint32_t	size_left;
277 	uint8_t		buf[4];
278 } stmf_xfer_data_t;
279 
280 /*
281  * Define frequently used macros
282  */
283 #define	TASK_TO_ITASK(x_task)	\
284 	((stmf_i_scsi_task_t *)(x_task)->task_stmf_private)
285 
286 void stmf_dlun_init();
287 stmf_status_t stmf_dlun_fini();
288 void stmf_worker_init();
289 stmf_status_t stmf_worker_fini();
290 void stmf_task_free(scsi_task_t *task);
291 void stmf_task_lu_free(scsi_task_t *task);
292 void stmf_do_task_abort(scsi_task_t *task);
293 void stmf_do_itl_dereg(stmf_lu_t *lu, stmf_itl_data_t *itl,
294 		uint8_t hdlrm_reason);
295 void stmf_generate_lu_event(stmf_i_lu_t *ilu, int eventid,
296 				void *arg, uint32_t flags);
297 void stmf_generate_lport_event(stmf_i_local_port_t *ilport, int eventid,
298 						void *arg, uint32_t flags);
299 
300 #ifdef	__cplusplus
301 }
302 #endif
303 
304 #endif /* _STMF_IMPL_H */
305