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 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #ifndef _GHD_WAITQ_H
28 #define	_GHD_WAITQ_H
29 
30 #ifdef	__cplusplus
31 extern "C" {
32 #endif
33 
34 
35 /*
36  * there's a waitq_t per target device and one per HBA
37  */
38 
39 typedef struct ghd_q {
40 	struct ghd_q *Q_nextp;	/* ptr to next level of queuing */
41 	L2el_t	Q_qhead;	/* Q of waiting gcmds */
42 	long	Q_nactive;	/* current # of outstanding gcmds */
43 	long	Q_maxactive;	/* max gcmds to release concurrently */
44 } Q_t;
45 
46 #define	GHD_WAITQ_INIT(qp, nxtp, maxactive)	\
47 	(L2_INIT(&(qp)->Q_qhead), 		\
48 	(qp)->Q_nextp = (nxtp),			\
49 	(qp)->Q_nactive = 0,			\
50 	(qp)->Q_maxactive = (maxactive))
51 /*
52  * one per target device
53  */
54 typedef struct ghd_device {
55 	Q_t	gd_waitq;	/* the queue structure for this device */
56 	L1el_t	gd_devlist;	/* all gdevs for a HBA are linked together */
57 	ulong_t	gd_target;	/*  ... and are located by searching for */
58 	ulong_t	gd_lun;		/*  ... a match on the (target,lun) values */
59 
60 	L1_t 	gd_ilist;	/* linked list of instances for this device */
61 	ulong_t	gd_ninstances;	/* # of instances for this device */
62 } gdev_t;
63 
64 #define	GDEV_QHEAD(gdevp)	((gdevp)->gd_waitq.Q_qhead)
65 #define	GDEV_NACTIVE(gdevp)	((gdevp)->gd_waitq.Q_nactive)
66 #define	GDEV_MAXACTIVE(gdevp)	((gdevp)->gd_waitq.Q_maxactive)
67 
68 /*
69  * Be careful, this macro assumes there's a least one
70  * target instance attached to this dev structure, Otherwise, l1_headp
71  * is NULL.
72  */
73 #define	GDEVP2GTGTP(gdevp)	\
74 	(gtgt_t *)((gdevp)->gd_ilist.l1_headp->le_datap)
75 
76 #define	GDEV_NEXTP(gdevp)						\
77 	((gdevp)->gd_devlist.le_nextp					\
78 		? (gdev_t *)((gdevp)->gd_devlist.le_nextp->le_datap)	\
79 		: (gdev_t *)NULL)
80 
81 #define	GDEV_QATTACH(gdevp, cccp, max)	{				\
82 	GHD_WAITQ_INIT(&(gdevp)->gd_waitq, &(cccp)->ccc_waitq, (max));	\
83 	L1EL_INIT(&gdevp->gd_devlist);					\
84 	L1HEADER_INIT(&gdevp->gd_ilist);				\
85 	/* add the per device structure to the HBA's device list */	\
86 	L1_add(&(cccp)->ccc_devs, &(gdevp)->gd_devlist, (gdevp));	\
87 }
88 
89 #define	GDEV_QDETACH(gdevp, cccp)			\
90 	L1_delete(&(cccp)->ccc_devs, &(gdevp)->gd_devlist)
91 
92 /*
93  * GHD target structure, one per attached target driver instance
94  */
95 typedef	struct	ghd_target_instance {
96 	L1el_t	 gt_ilist;	/* list of other instances for this device */
97 	gdev_t	*gt_gdevp;	/* ptr to info shared by all instances */
98 
99 	/* this would be ccc_t, but is circular with ghd.h.  sigh. */
100 	struct cmd_ctl *gt_ccc;	/* ptr to HBA per-instance struct */
101 
102 	ulong_t	 gt_maxactive;	/* max gcmds to release concurrently */
103 	void	*gt_hba_private; /* ptr to soft state of this HBA instance */
104 	void	*gt_tgt_private; /* ptr to soft state of this target instance */
105 	size_t	 gt_size;	/* size including tgt_private */
106 	ushort_t gt_target;	/* target number of this instance */
107 	uchar_t	 gt_lun;	/* LUN of this instance */
108 } gtgt_t;
109 
110 #define	GTGTP2TARGET(gtgtp)	((gtgtp)->gt_tgt_private)
111 #define	GTGTP2HBA(gtgtp)	((gtgtp)->gt_hba_private)
112 #define	GTGTP2GDEVP(gtgtp)	((gtgtp)->gt_gdevp)
113 
114 #define	GTGT_INIT(gtgtp)	L1EL_INIT(&(gtgtp)->gt_ilist)
115 
116 /* Add the per instance structure to the per device list  */
117 #define	GTGT_ATTACH(gtgtp, gdevp)	{				\
118 	(gdevp)->gd_ninstances++;					\
119 	L1_add(&(gdevp)->gd_ilist, &(gtgtp)->gt_ilist, (gtgtp));	\
120 }
121 
122 
123 /* remove this per-instance-structure from the device list */
124 #define	GTGT_DEATTACH(gtgtp, gdevp)	{			\
125 	(gdevp)->gd_ninstances--;				\
126 	L1_delete(&(gdevp)->gd_ilist, &(gtgtp)->gt_ilist);	\
127 }
128 
129 #ifdef	__cplusplus
130 }
131 #endif
132 #endif  /* _GHD_QUEUE_H */
133