xref: /illumos-gate/usr/src/uts/sun/sys/dada/adapters/ghd/ghd.h (revision bdfc6d18da790deeec2e0eb09c625902defe2498)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #ifndef _GHD_H
28 #define	_GHD_H
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #ifdef	__cplusplus
33 extern "C" {
34 #endif
35 
36 #include <sys/types.h>
37 #include <sys/conf.h>
38 #include <sys/kmem.h>
39 #include <sys/ddi.h>
40 #include <sys/sunddi.h>
41 #include <sys/debug.h>
42 #include <sys/scsi/scsi.h>
43 
44 #include "ghd_queue.h"		/* linked list structures */
45 #include "ghd_scsi.h"
46 #include "ghd_waitq.h"
47 #include "ghd_debug.h"
48 
49 #ifndef	TRUE
50 #define	TRUE	1
51 #endif
52 
53 #ifndef	FALSE
54 #define	FALSE	0
55 #endif
56 
57 /*
58  * values for cmd_state:
59  */
60 
61 typedef enum {
62 	GCMD_STATE_IDLE = 0,
63 	GCMD_STATE_WAITQ,
64 	GCMD_STATE_ACTIVE,
65 	GCMD_STATE_DONEQ,
66 	GCMD_STATE_ABORTING_CMD,
67 	GCMD_STATE_ABORTING_DEV,
68 	GCMD_STATE_RESETTING_DEV,
69 	GCMD_STATE_RESETTING_BUS,
70 	GCMD_STATE_HUNG,
71 	GCMD_NSTATES
72 } cmdstate_t;
73 
74 /*
75  * action codes for the HBA timeout function
76  */
77 
78 typedef enum {
79 	GACTION_EARLY_TIMEOUT = 0,	/* timed-out before started */
80 	GACTION_EARLY_ABORT,		/* scsi_abort() before started */
81 	GACTION_ABORT_CMD,		/* abort a specific request */
82 	GACTION_ABORT_DEV,		/* abort everything on specifici dev */
83 	GACTION_RESET_TARGET,		/* reset a specific dev */
84 	GACTION_RESET_BUS,		/* reset the whole bus */
85 	GACTION_INCOMPLETE		/* giving up on incomplete request */
86 } gact_t;
87 
88 
89 /*
90  * the common portion of the Command Control Block
91  */
92 
93 typedef struct ghd_cmd {
94 	L2el_t		 cmd_q;		/* link for for done/active CCB Qs */
95 	cmdstate_t	 cmd_state;	/* request's current state */
96 	uint32_t	 cmd_waitq_level; /* which wait Q this request is on */
97 
98 	L2el_t		 cmd_timer_link; /* ccb timer doubly linked list */
99 	clock_t		 cmd_start_time; /* lbolt at start of request */
100 	clock_t		 cmd_timeout;	/* how long to wait */
101 
102 	opaque_t	 cmd_private;	/* used by the HBA driver */
103 	void		*cmd_pktp;	/* request packet */
104 	gtgt_t		*cmd_gtgtp;	/* dev instance for this request */
105 
106 	ddi_dma_handle_t cmd_dma_handle;
107 	ddi_dma_win_t	 cmd_dmawin;
108 	ddi_dma_seg_t	 cmd_dmaseg;
109 	int		 cmd_dma_flags;
110 	long		 cmd_totxfer;
111 	long		 cmd_resid;
112 } gcmd_t;
113 
114 
115 
116 
117 /*
118  * Initialize the gcmd_t structure
119  */
120 
121 #define	GHD_GCMD_INIT(gcmdp, cmdp, gtgtp)	\
122 	(L2_INIT(&(gcmdp)->cmd_q),		\
123 	L2_INIT(&(gcmdp)->cmd_timer_link),	\
124 	(gcmdp)->cmd_private = (cmdp),		\
125 	(gcmdp)->cmd_gtgtp = (gtgtp)		\
126 )
127 
128 
129 /*
130  * CMD/CCB timer config structure - one per HBA driver module
131  */
132 typedef struct tmr_conf {
133 	kmutex_t	t_mutex;	/* mutex to protect t_ccc_listp */
134 	timeout_id_t	t_timeout_id;	/* handle for timeout() function */
135 	clock_t		t_ticks;	/* periodic timeout in clock ticks */
136 	int		t_refs;		/* reference count */
137 	struct cmd_ctl	*t_ccc_listp;	/* control struct list, one per HBA */
138 } tmr_t;
139 
140 
141 
142 /*
143  * CMD/CCB timer control structure - one per HBA instance (per board)
144  */
145 typedef struct cmd_ctl {
146 	struct cmd_ctl	*ccc_nextp;	/* list of control structs */
147 	struct tmr_conf	*ccc_tmrp;	/* back ptr to config struct */
148 	char		*ccc_label;	/* name of this HBA driver */
149 	int		ccc_chno;	/* Channle number */
150 
151 	kmutex_t ccc_activel_mutex;	/* mutex to protect list ... */
152 	L2el_t	 ccc_activel;		/* ... list of active CMD/CCBs */
153 
154 	dev_info_t *ccc_hba_dip;
155 	ddi_iblock_cookie_t ccc_iblock;
156 	ddi_softintr_t  ccc_soft_id;	/* ID for timeout softintr */
157 
158 	kmutex_t ccc_hba_mutex;		/* mutex for HBA soft-state */
159 	int	 ccc_hba_pollmode;	/* FLAG_NOINTR mode active? */
160 
161 	L1_t	 ccc_devs;		/* unsorted list of attached devs */
162 	kmutex_t ccc_waitq_mutex;	/* mutex to protect device wait Qs */
163 	Q_t	 ccc_waitq;		/* the HBA's wait queue */
164 
165 	ddi_softintr_t  ccc_doneq_softid; /* ID for doneq softintr */
166 	kmutex_t ccc_doneq_mutex;	/* mutex to protect the doneq */
167 	L2el_t	 ccc_doneq; 		/* completed cmd_t's */
168 
169 	void	*ccc_hba_handle;
170 	int	(*ccc_ccballoc)();	/* alloc/init gcmd and ccb */
171 	void	(*ccc_ccbfree)();
172 	void	(*ccc_sg_func)();
173 	int	(*ccc_hba_start)(void *handle, gcmd_t *);
174 	void    (*ccc_hba_complete)(void *handle, gcmd_t *, int);
175 	void	(*ccc_process_intr)(void *handle, void *intr_status, int chno);
176 	int	(*ccc_get_status)(void *handle, void *intr_status, int chno);
177 	int	(*ccc_timeout_func)(void *handle, gcmd_t *cmdp, gtgt_t *gtgtp,
178 				    gact_t action, int calltype);
179 } ccc_t;
180 
181 #define	GHBA_QHEAD(cccp)	((cccp)->ccc_waitq.Q_qhead)
182 #define	GHBA_MAXACTIVE(cccp)	((cccp)->ccc_waitq.Q_maxactive)
183 #define	GHBA_NACTIVE(cccp)	((cccp)->ccc_waitq.Q_nactive)
184 
185 /* Initialize the HBA's list headers */
186 #define	CCCP_INIT(cccp)	{				\
187 		L1HEADER_INIT(&(cccp)->ccc_devs);	\
188 		L2_INIT(&(cccp)->ccc_doneq);		\
189 }
190 
191 
192 #define	CCCP2GDEVP(cccp)					\
193 	(L1_EMPTY(&(cccp)->ccc_devs)				\
194 	? (gdev_t *)NULL					\
195 	: (gdev_t *)((cccp)->ccc_devs.l1_headp->le_datap))
196 
197 /* ******************************************************************* */
198 
199 #include "ghd_scsa.h"
200 #include "ghd_dma.h"
201 
202 /*
203  * GHD Entry Points
204  */
205 void	 ghd_complete(ccc_t *cccp, gcmd_t *cmdp);
206 void	 ghd_async_complete(ccc_t *cccp, gcmd_t *cmdp);
207 void	 ghd_doneq_put(ccc_t *cccp, gcmd_t *cmdp);
208 
209 int	 ghd_intr(ccc_t *cccp, void *status, int chno);
210 int	 ghd_register(char *, ccc_t *, dev_info_t *, int, void *hba_handle,
211 			int (*ccc_ccballoc)(gtgt_t *, gcmd_t *, int, int,
212 					    int, int),
213 			void (*ccc_ccbfree)(gcmd_t *),
214 			void (*ccc_sg_func)(gcmd_t *, ddi_dma_cookie_t *,
215 					    int, int),
216 			int  (*hba_start)(void *, gcmd_t *),
217 			void (*hba_complete)(void *, gcmd_t *, int),
218 			uint_t (*int_handler)(caddr_t),
219 			int  (*get_status)(void *, void *, int),
220 			void (*process_intr)(void *, void *, int),
221 			int  (*timeout_func)(void *, gcmd_t *, gtgt_t *,
222 						gact_t, int calltype),
223 			tmr_t *tmrp,
224 			ddi_iblock_cookie_t iblock,
225 			int chno);
226 void	 ghd_unregister(ccc_t *cccp);
227 
228 int	 ghd_transport(ccc_t *cccp, gcmd_t *cmdp, gtgt_t *gtgtp,
229 		uint32_t timeout, int polled, void *intr_status);
230 
231 int	 ghd_tran_abort(ccc_t *cccp, gcmd_t *cmdp, gtgt_t *gtgtp,
232 				void *intr_status);
233 int	 ghd_tran_abort_lun(ccc_t *cccp, gtgt_t *gtgtp, void *intr_status);
234 int	 ghd_tran_reset_target(ccc_t *cccp, gtgt_t *gtgtp, void *intr_status);
235 int	 ghd_tran_reset_bus(ccc_t *cccp, gtgt_t *gtgtp, void *intr_status);
236 
237 
238 /*
239  * Allocate a gcmd_t wrapper and HBA private area
240  */
241 gcmd_t	*ghd_gcmd_alloc(gtgt_t *gtgtp, int ccblen, int sleep);
242 
243 /*
244  * Free the gcmd_t wrapper and HBA private area
245  */
246 void	ghd_gcmd_free(gcmd_t *gcmdp);
247 
248 
249 /*
250  * GHD CMD/CCB timer Entry points
251  */
252 
253 int	ghd_timer_attach(ccc_t *cccp, tmr_t *tmrp,
254 		int (*timeout_func)(void *handle, gcmd_t *, gtgt_t *,
255 		    gact_t, int));
256 void	ghd_timer_detach(ccc_t *cccp);
257 void	ghd_timer_fini(tmr_t *tmrp);
258 void	ghd_timer_init(tmr_t *tmrp, clock_t ticks);
259 void	ghd_timer_newstate(ccc_t *cccp, gcmd_t *cmdp, gtgt_t *gtgtp,
260 				gact_t action, int calltype);
261 void	ghd_timer_poll(ccc_t *cccp);
262 void	ghd_timer_start(ccc_t *cccp, gcmd_t *cmdp, uint32_t cmd_timeout);
263 void	ghd_timer_stop(ccc_t *cccp, gcmd_t *cmdp);
264 
265 
266 /*
267  * Wait queue utility routines
268  */
269 
270 gtgt_t	*ghd_target_init(dev_info_t *, dev_info_t *, ccc_t *, size_t,
271 				void *, uint32_t, uint32_t);
272 void	 ghd_target_free(dev_info_t *, dev_info_t *, ccc_t *, gtgt_t *);
273 void	 ghd_waitq_shuffle_up(ccc_t *, gdev_t *);
274 void	 ghd_waitq_delete(ccc_t *, gcmd_t *);
275 int	 ghd_waitq_process_and_mutex_hold(ccc_t *);
276 void	 ghd_waitq_process_and_mutex_exit(ccc_t *);
277 
278 
279 /*
280  * The values for the calltype arg for the ghd_timer_newstate() function
281  */
282 
283 #define	GHD_NEWSTATE_TGTREQ	0
284 #define	GHD_NEWSTATE_TIMEOUT	1
285 
286 /* ******************************************************************* */
287 
288 /*
289  * specify GHD_INLINE to get optimized versions
290  */
291 #define	GHD_INLINE	1
292 #if defined(GHD_DEBUG) || defined(DEBUG) || defined(__lint)
293 #undef GHD_INLINE
294 #endif
295 
296 #if defined(GHD_INLINE)
297 #define	GHD_COMPLETE(cccp, gcmpd)	GHD_COMPLETE_INLINE(cccp, gcmdp)
298 #define	GHD_TIMER_STOP(cccp, gcmdp)	GHD_TIMER_STOP_INLINE(cccp, gcmdp)
299 #define	GHD_DONEQ_PUT(cccp, gcmdp)	GHD_DONEQ_PUT_INLINE(cccp, gcmdp)
300 #else
301 #define	GHD_COMPLETE(cccp, gcmpd)	ghd_complete(cccp, gcmdp)
302 #define	GHD_TIMER_STOP(cccp, gcmdp)	ghd_timer_stop(cccp, gcmdp)
303 #define	GHD_DONEQ_PUT(cccp, gcmdp)	ghd_doneq_put(cccp, gcmdp)
304 #endif
305 
306 /*
307  * request is complete, stop the request timer and add to doneq
308  */
309 #define	GHD_COMPLETE_INLINE(cccp, gcmdp)		\
310 {						\
311 	ghd_waitq_delete(cccp, gcmdp);		\
312 	(gcmdp)->cmd_state = GCMD_STATE_DONEQ;	\
313 	GHD_TIMER_STOP((cccp), (gcmdp));	\
314 	GHD_DONEQ_PUT((cccp), (gcmdp));		\
315 }
316 
317 #define	GHD_TIMER_STOP_INLINE(cccp, gcmdp)		\
318 {							\
319 	mutex_enter(&(cccp)->ccc_activel_mutex);	\
320 	L2_delete(&(gcmdp)->cmd_timer_link);		\
321 	mutex_exit(&(cccp)->ccc_activel_mutex);		\
322 }
323 
324 /*
325  * mark the request done and append it to the doneq
326  */
327 #define	GHD_DONEQ_PUT_INLINE(cccp, gcmdp)			\
328 {								\
329 								\
330 	mutex_enter(&(cccp)->ccc_doneq_mutex);			\
331 	(gcmdp)->cmd_state = GCMD_STATE_DONEQ;			\
332 	L2_add(&(cccp)->ccc_doneq, &(gcmdp)->cmd_q, (gcmdp));	\
333 	if (!(cccp)->ccc_hba_pollmode)				\
334 		ddi_trigger_softintr((cccp)->ccc_doneq_softid);	\
335 	mutex_exit(&(cccp)->ccc_doneq_mutex);			\
336 }
337 
338 
339 /* ******************************************************************* */
340 
341 /*
342  * These are shortcut macros for linkages setup by GHD
343  */
344 
345 /*
346  * (gcmd_t *) to (struct scsi_pkt *)
347  */
348 #define	GCMDP2PKTP(gcmdp)	((gcmdp)->cmd_pktp)
349 
350 /*
351  * (gcmd_t *) to (gtgt_t *)
352  */
353 #define	GCMDP2GTGTP(gcmdp)	((gcmdp)->cmd_gtgtp)
354 
355 /*
356  * (struct scsi_pkt *) to (gcmd_t *)
357  */
358 #define	PKTP2GCMDP(pktp)	((gcmd_t *)(pktp)->pkt_ha_private)
359 
360 
361 /* These are shortcut macros for linkages setup by SCSA */
362 
363 /*
364  * (struct scsi_address *) to (scsi_hba_tran *)
365  */
366 #define	ADDR2TRAN(ap)		((ap)->a_hba_tran)
367 
368 /*
369  * (struct scsi_device *) to (scsi_address *)
370  */
371 #define	SDEV2ADDR(sdp)		(&(sdp)->sd_address)
372 
373 /*
374  * (struct scsi_device *) to (scsi_hba_tran *)
375  */
376 #define	SDEV2TRAN(sdp)		ADDR2TRAN(SDEV2ADDR(sdp))
377 
378 /*
379  * (struct scsi_pkt *) to (scsi_hba_tran *)
380  */
381 #define	PKTP2TRAN(pktp)		ADDR2TRAN(&(pktp)->pkt_address)
382 
383 /*
384  * (scsi_hba_tran_t *) to (per-target-soft-state *)
385  */
386 #define	TRAN2GTGTP(tranp)	((gtgt_t *)((tranp)->tran_tgt_private))
387 
388 /*
389  * (struct scsi_device *) to (per-target-soft-state *)
390  */
391 #define	SDEV2GTGTP(sd)  	TRAN2GTGTP(SDEV2TRAN(sd))
392 
393 /*
394  * (struct scsi_pkt *) to (per-target-soft-state *)
395  */
396 #define	PKTP2GTGTP(pktp)	TRAN2GTGTP(PKTP2TRAN(pktp))
397 
398 
399 /*
400  * (scsi_hba_tran_t *) to (per-HBA-soft-state *)
401  */
402 #define	TRAN2HBA(tranp)		((tranp)->tran_hba_private)
403 
404 
405 /*
406  * (struct scsi_device *) to (per-HBA-soft-state *)
407  */
408 #define	SDEV2HBA(sd)		TRAN2HBA(SDEV2TRAN(sd))
409 
410 /*
411  * (struct scsi_address *) to (per-target-soft-state *)
412  */
413 #define	ADDR2GTGTP(ap)  	TRAN2GTGTP(ADDR2TRAN(ap))
414 
415 /* ******************************************************************* */
416 
417 
418 #ifdef	__cplusplus
419 }
420 #endif
421 
422 #endif /* _GHD_H */
423