xref: /illumos-gate/usr/src/uts/sun/io/dada/impl/dcd_resource.c (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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/dada/dada.h>
30 #include <sys/vtrace.h>
31 
32 #define	A_TO_TRAN(ap)	((ap)->a_hba_tran)
33 #define	P_TO_TRAN(pkt)	((pkt)->pkt_address.a_hba_tran)
34 #define	P_TO_ADDR(pkt)	(&((pkt)->pkt_address))
35 
36 /*
37  * Callback id
38  */
39 uintptr_t	dcd_callback_id = 0L;
40 
41 
42 struct buf *
43 dcd_alloc_consistent_buf(struct dcd_address *ap,
44 	struct buf *in_bp, size_t datalen, uint_t bflags,
45 	int (*callback)(caddr_t), caddr_t callback_arg)
46 {
47 
48 	dev_info_t	*pdip;
49 	struct	buf 	*bp;
50 	int		kmflag;
51 
52 
53 	if (!in_bp) {
54 		kmflag = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP;
55 		if ((bp = getrbuf(kmflag)) == NULL) {
56 			goto no_resource;
57 		}
58 	} else
59 		bp = in_bp;
60 
61 	bp->b_un.b_addr = 0;
62 	if (datalen) {
63 		pdip = (A_TO_TRAN(ap))->tran_hba_dip;
64 
65 		if (ddi_iopb_alloc(pdip, (ddi_dma_lim_t *)0, datalen,
66 			&bp->b_un.b_addr)) {
67 			if (!in_bp)
68 				freerbuf(bp);
69 			goto no_resource;
70 		}
71 		bp->b_flags |= bflags;
72 	}
73 	bp->b_bcount = datalen;
74 	bp->b_resid = 0;
75 
76 	return (bp);
77 
78 no_resource:
79 	if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
80 		ddi_set_callback(callback, callback_arg, &dcd_callback_id);
81 	}
82 
83 	return (NULL);
84 }
85 
86 
87 void
88 dcd_free_consistent_buf(struct buf *bp)
89 {
90 
91 	if (!bp)
92 		return;
93 
94 	if (bp->b_un.b_addr)
95 		ddi_iopb_free((caddr_t)bp->b_un.b_addr);
96 	freerbuf(bp);
97 	if (dcd_callback_id != 0L) {
98 		ddi_run_callback(&dcd_callback_id);
99 	}
100 
101 }
102 
103 struct dcd_pkt *
104 dcd_init_pkt(struct dcd_address *ap, struct dcd_pkt *in_pktp,
105 	struct buf *bp, int cmdlen, int statuslen, int pplen,
106 	int flags, int (*callback)(caddr_t), caddr_t callback_arg)
107 {
108 	struct dcd_pkt *pktp;
109 	dcd_hba_tran_t	*tranp = ap->a_hba_tran;
110 	int		(*func)(caddr_t);
111 
112 #if defined(__i386) || defined(__amd64)
113 	if (flags & PKT_CONSISTENT_OLD) {
114 		flags &= ~PKT_CONSISTENT_OLD;
115 		flags |= PKT_CONSISTENT;
116 	}
117 #endif	/* __i386 || __amd64 */
118 
119 	func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
120 
121 	pktp = (*tranp->tran_init_pkt)(ap, in_pktp, bp, cmdlen,
122 		statuslen, pplen, flags, func, NULL);
123 
124 	if (pktp == NULL) {
125 		if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
126 			ddi_set_callback(callback, callback_arg,
127 				&dcd_callback_id);
128 		}
129 	}
130 
131 	return (pktp);
132 }
133 
134 void
135 dcd_destroy_pkt(struct dcd_pkt *pkt)
136 {
137 
138 	struct dcd_address *ap = P_TO_ADDR(pkt);
139 
140 	(*A_TO_TRAN(ap)->tran_destroy_pkt)(ap, pkt);
141 
142 	if (dcd_callback_id != 0L) {
143 		ddi_run_callback(&dcd_callback_id);
144 	}
145 
146 }
147 
148 struct dcd_pkt *
149 dcd_resalloc(struct dcd_address *ap, int cmdlen, int statuslen,
150 	ataopaque_t dmatoken, int (*callback)())
151 {
152 
153 	register struct dcd_pkt *pkt;
154 	register dcd_hba_tran_t	*tranp = ap->a_hba_tran;
155 	register int		(*func)(caddr_t);
156 
157 
158 	func = (callback == SLEEP_FUNC) ? SLEEP_FUNC: NULL_FUNC;
159 	pkt = (*tranp->tran_init_pkt) (ap, NULL, (struct buf *)dmatoken,
160 		cmdlen, statuslen, 0, 0, func, NULL);
161 
162 	if (pkt == NULL) {
163 		if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
164 			ddi_set_callback(callback, NULL, &dcd_callback_id);
165 		}
166 	}
167 	return (pkt);
168 }
169 
170 
171 struct dcd_pkt *
172 dcd_pktalloc(struct dcd_address *ap, int cmdlen, int statuslen,
173 	int (*callback)())
174 {
175 
176 	struct dcd_pkt 	*pkt;
177 	struct dcd_hba_tran	*tran = ap->a_hba_tran;
178 	register int 		(*func)(caddr_t);
179 
180 
181 	func = (callback == SLEEP_FUNC) ? SLEEP_FUNC: NULL_FUNC;
182 
183 	pkt = (*tran->tran_init_pkt) (ap, NULL, NULL, cmdlen, statuslen,
184 		0, 0, func, NULL);
185 	if (pkt == NULL) {
186 		if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
187 			ddi_set_callback(callback, NULL, &dcd_callback_id);
188 		}
189 	}
190 	return (pkt);
191 }
192 
193 
194 struct dcd_pkt *
195 dcd_dmaget(struct dcd_pkt *pkt, ataopaque_t dmatoken, int (*callback)())
196 {
197 
198 	struct dcd_pkt *new_pkt;
199 	register	int	(*func)(caddr_t);
200 
201 	func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
202 
203 	new_pkt = (*P_TO_TRAN(pkt)->tran_init_pkt) (&pkt->pkt_address,
204 		pkt, (struct buf *)dmatoken, 0, 0, 0, 0, func, NULL);
205 
206 	ASSERT(new_pkt == pkt || new_pkt == NULL);
207 	if (new_pkt == NULL) {
208 		if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
209 			ddi_set_callback(callback, NULL, &dcd_callback_id);
210 		}
211 	}
212 
213 	return (pkt);
214 }
215 
216 
217 /*
218  * Generic Resource Allocation Routines
219  */
220 
221 void
222 dcd_dmafree(struct dcd_pkt *pkt)
223 {
224 
225 	register struct dcd_address *ap = P_TO_ADDR(pkt);
226 
227 	(*A_TO_TRAN(ap)->tran_dmafree)(ap, pkt);
228 
229 	if (dcd_callback_id != 0L) {
230 		ddi_run_callback(&dcd_callback_id);
231 	}
232 
233 }
234 
235 void
236 dcd_sync_pkt(struct dcd_pkt *pkt)
237 {
238 	register struct dcd_address *ap = P_TO_ADDR(pkt);
239 
240 	(*A_TO_TRAN(ap)->tran_sync_pkt) (ap, pkt);
241 }
242 
243 void
244 dcd_resfree(struct dcd_pkt *pkt)
245 {
246 
247 	register struct dcd_address *ap = P_TO_ADDR(pkt);
248 
249 	(*A_TO_TRAN(ap)->tran_destroy_pkt)(ap, pkt);
250 
251 	if (dcd_callback_id != 0L) {
252 		ddi_run_callback(&dcd_callback_id);
253 	}
254 }
255