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.
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.
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]
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <sys/dada/dada.h>
30 #include <sys/vtrace.h>
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))
39 uintptr_t dcd_callback_id
= 0L;
41 /* For i_ddi_mem_alloc() in dcd_alloc_consistent_buf() */
42 static ddi_dma_attr_t standard_dma_attr
= {
43 DMA_ATTR_V0
, /* version number */
44 0x0, /* lowest usable address */
45 0xFFFFFFFFull
, /* high DMA address range */
46 0xFFFFFFFFull
, /* DMA counter register */
47 1, /* DMA address alignment */
48 1, /* DMA burstsizes */
49 1, /* min effective DMA size */
50 0xFFFFFFFFull
, /* max DMA xfer size */
51 0xFFFFFFFFull
, /* segment boundary */
52 1, /* s/g list length */
53 512, /* granularity of device */
54 0, /* DMA transfer flags */
58 dcd_alloc_consistent_buf(struct dcd_address
*ap
,
59 struct buf
*in_bp
, size_t datalen
, uint_t bflags
,
60 int (*callback
)(caddr_t
), caddr_t callback_arg
)
70 kmflag
= (callback
== SLEEP_FUNC
) ? KM_SLEEP
: KM_NOSLEEP
;
71 if ((bp
= getrbuf(kmflag
)) == NULL
) {
79 pdip
= (A_TO_TRAN(ap
))->tran_hba_dip
;
80 if (i_ddi_mem_alloc(pdip
, &standard_dma_attr
, datalen
, 0,
81 0, NULL
, &bp
->b_un
.b_addr
, &rlen
, NULL
) != DDI_SUCCESS
) {
86 bp
->b_flags
|= bflags
;
88 bp
->b_bcount
= datalen
;
94 if (callback
!= NULL_FUNC
&& callback
!= SLEEP_FUNC
) {
95 ddi_set_callback(callback
, callback_arg
, &dcd_callback_id
);
103 dcd_free_consistent_buf(struct buf
*bp
)
110 i_ddi_mem_free((caddr_t
)bp
->b_un
.b_addr
, NULL
);
112 if (dcd_callback_id
!= 0L) {
113 ddi_run_callback(&dcd_callback_id
);
119 dcd_init_pkt(struct dcd_address
*ap
, struct dcd_pkt
*in_pktp
,
120 struct buf
*bp
, int cmdlen
, int statuslen
, int pplen
,
121 int flags
, int (*callback
)(caddr_t
), caddr_t callback_arg
)
123 struct dcd_pkt
*pktp
;
124 dcd_hba_tran_t
*tranp
= ap
->a_hba_tran
;
125 int (*func
)(caddr_t
);
127 #if defined(__i386) || defined(__amd64)
128 if (flags
& PKT_CONSISTENT_OLD
) {
129 flags
&= ~PKT_CONSISTENT_OLD
;
130 flags
|= PKT_CONSISTENT
;
132 #endif /* __i386 || __amd64 */
134 func
= (callback
== SLEEP_FUNC
) ? SLEEP_FUNC
: NULL_FUNC
;
136 pktp
= (*tranp
->tran_init_pkt
)(ap
, in_pktp
, bp
, cmdlen
,
137 statuslen
, pplen
, flags
, func
, NULL
);
140 if (callback
!= NULL_FUNC
&& callback
!= SLEEP_FUNC
) {
141 ddi_set_callback(callback
, callback_arg
,
150 dcd_destroy_pkt(struct dcd_pkt
*pkt
)
153 struct dcd_address
*ap
= P_TO_ADDR(pkt
);
155 (*A_TO_TRAN(ap
)->tran_destroy_pkt
)(ap
, pkt
);
157 if (dcd_callback_id
!= 0L) {
158 ddi_run_callback(&dcd_callback_id
);
164 dcd_resalloc(struct dcd_address
*ap
, int cmdlen
, int statuslen
,
165 ataopaque_t dmatoken
, int (*callback
)())
168 register struct dcd_pkt
*pkt
;
169 register dcd_hba_tran_t
*tranp
= ap
->a_hba_tran
;
170 register int (*func
)(caddr_t
);
173 func
= (callback
== SLEEP_FUNC
) ? SLEEP_FUNC
: NULL_FUNC
;
174 pkt
= (*tranp
->tran_init_pkt
) (ap
, NULL
, (struct buf
*)dmatoken
,
175 cmdlen
, statuslen
, 0, 0, func
, NULL
);
178 if (callback
!= NULL_FUNC
&& callback
!= SLEEP_FUNC
) {
179 ddi_set_callback(callback
, NULL
, &dcd_callback_id
);
187 dcd_pktalloc(struct dcd_address
*ap
, int cmdlen
, int statuslen
,
192 struct dcd_hba_tran
*tran
= ap
->a_hba_tran
;
193 register int (*func
)(caddr_t
);
196 func
= (callback
== SLEEP_FUNC
) ? SLEEP_FUNC
: NULL_FUNC
;
198 pkt
= (*tran
->tran_init_pkt
) (ap
, NULL
, NULL
, cmdlen
, statuslen
,
201 if (callback
!= NULL_FUNC
&& callback
!= SLEEP_FUNC
) {
202 ddi_set_callback(callback
, NULL
, &dcd_callback_id
);
210 dcd_dmaget(struct dcd_pkt
*pkt
, ataopaque_t dmatoken
, int (*callback
)())
213 struct dcd_pkt
*new_pkt
;
214 register int (*func
)(caddr_t
);
216 func
= (callback
== SLEEP_FUNC
) ? SLEEP_FUNC
: NULL_FUNC
;
218 new_pkt
= (*P_TO_TRAN(pkt
)->tran_init_pkt
) (&pkt
->pkt_address
,
219 pkt
, (struct buf
*)dmatoken
, 0, 0, 0, 0, func
, NULL
);
221 ASSERT(new_pkt
== pkt
|| new_pkt
== NULL
);
222 if (new_pkt
== NULL
) {
223 if (callback
!= NULL_FUNC
&& callback
!= SLEEP_FUNC
) {
224 ddi_set_callback(callback
, NULL
, &dcd_callback_id
);
233 * Generic Resource Allocation Routines
237 dcd_dmafree(struct dcd_pkt
*pkt
)
240 register struct dcd_address
*ap
= P_TO_ADDR(pkt
);
242 (*A_TO_TRAN(ap
)->tran_dmafree
)(ap
, pkt
);
244 if (dcd_callback_id
!= 0L) {
245 ddi_run_callback(&dcd_callback_id
);
251 dcd_sync_pkt(struct dcd_pkt
*pkt
)
253 register struct dcd_address
*ap
= P_TO_ADDR(pkt
);
255 (*A_TO_TRAN(ap
)->tran_sync_pkt
) (ap
, pkt
);
259 dcd_resfree(struct dcd_pkt
*pkt
)
262 register struct dcd_address
*ap
= P_TO_ADDR(pkt
);
264 (*A_TO_TRAN(ap
)->tran_destroy_pkt
)(ap
, pkt
);
266 if (dcd_callback_id
!= 0L) {
267 ddi_run_callback(&dcd_callback_id
);