17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
54ab75253Smrj * Common Development and Distribution License (the "License").
64ab75253Smrj * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
214ab75253Smrj
227c478bd9Sstevel@tonic-gate /*
237b93957cSeota * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate #include <sys/dada/dada.h>
287c478bd9Sstevel@tonic-gate #include <sys/vtrace.h>
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate #define A_TO_TRAN(ap) ((ap)->a_hba_tran)
317c478bd9Sstevel@tonic-gate #define P_TO_TRAN(pkt) ((pkt)->pkt_address.a_hba_tran)
327c478bd9Sstevel@tonic-gate #define P_TO_ADDR(pkt) (&((pkt)->pkt_address))
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate /*
357c478bd9Sstevel@tonic-gate * Callback id
367c478bd9Sstevel@tonic-gate */
377c478bd9Sstevel@tonic-gate uintptr_t dcd_callback_id = 0L;
387c478bd9Sstevel@tonic-gate
394ab75253Smrj /* For i_ddi_mem_alloc() in dcd_alloc_consistent_buf() */
404ab75253Smrj static ddi_dma_attr_t standard_dma_attr = {
414ab75253Smrj DMA_ATTR_V0, /* version number */
424ab75253Smrj 0x0, /* lowest usable address */
434ab75253Smrj 0xFFFFFFFFull, /* high DMA address range */
444ab75253Smrj 0xFFFFFFFFull, /* DMA counter register */
454ab75253Smrj 1, /* DMA address alignment */
464ab75253Smrj 1, /* DMA burstsizes */
474ab75253Smrj 1, /* min effective DMA size */
484ab75253Smrj 0xFFFFFFFFull, /* max DMA xfer size */
494ab75253Smrj 0xFFFFFFFFull, /* segment boundary */
504ab75253Smrj 1, /* s/g list length */
514ab75253Smrj 512, /* granularity of device */
524ab75253Smrj 0, /* DMA transfer flags */
534ab75253Smrj };
547c478bd9Sstevel@tonic-gate
557c478bd9Sstevel@tonic-gate struct buf *
dcd_alloc_consistent_buf(struct dcd_address * ap,struct buf * in_bp,size_t datalen,uint_t bflags,int (* callback)(caddr_t),caddr_t callback_arg)567c478bd9Sstevel@tonic-gate dcd_alloc_consistent_buf(struct dcd_address *ap,
57*86ef0a63SRichard Lowe struct buf *in_bp, size_t datalen, uint_t bflags,
58*86ef0a63SRichard Lowe int (*callback)(caddr_t), caddr_t callback_arg)
597c478bd9Sstevel@tonic-gate {
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate dev_info_t *pdip;
62*86ef0a63SRichard Lowe struct buf *bp;
637c478bd9Sstevel@tonic-gate int kmflag;
644ab75253Smrj size_t rlen;
657c478bd9Sstevel@tonic-gate
667c478bd9Sstevel@tonic-gate
677c478bd9Sstevel@tonic-gate if (!in_bp) {
687c478bd9Sstevel@tonic-gate kmflag = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP;
697c478bd9Sstevel@tonic-gate if ((bp = getrbuf(kmflag)) == NULL) {
707c478bd9Sstevel@tonic-gate goto no_resource;
717c478bd9Sstevel@tonic-gate }
727c478bd9Sstevel@tonic-gate } else
737c478bd9Sstevel@tonic-gate bp = in_bp;
747c478bd9Sstevel@tonic-gate
757c478bd9Sstevel@tonic-gate bp->b_un.b_addr = 0;
767c478bd9Sstevel@tonic-gate if (datalen) {
777c478bd9Sstevel@tonic-gate pdip = (A_TO_TRAN(ap))->tran_hba_dip;
784ab75253Smrj if (i_ddi_mem_alloc(pdip, &standard_dma_attr, datalen, 0,
794ab75253Smrj 0, NULL, &bp->b_un.b_addr, &rlen, NULL) != DDI_SUCCESS) {
807c478bd9Sstevel@tonic-gate if (!in_bp)
817c478bd9Sstevel@tonic-gate freerbuf(bp);
827c478bd9Sstevel@tonic-gate goto no_resource;
837c478bd9Sstevel@tonic-gate }
847c478bd9Sstevel@tonic-gate bp->b_flags |= bflags;
857c478bd9Sstevel@tonic-gate }
867c478bd9Sstevel@tonic-gate bp->b_bcount = datalen;
877c478bd9Sstevel@tonic-gate bp->b_resid = 0;
887c478bd9Sstevel@tonic-gate
897c478bd9Sstevel@tonic-gate return (bp);
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate no_resource:
927c478bd9Sstevel@tonic-gate if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
937c478bd9Sstevel@tonic-gate ddi_set_callback(callback, callback_arg, &dcd_callback_id);
947c478bd9Sstevel@tonic-gate }
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate return (NULL);
977c478bd9Sstevel@tonic-gate }
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate
1007c478bd9Sstevel@tonic-gate void
dcd_free_consistent_buf(struct buf * bp)1017c478bd9Sstevel@tonic-gate dcd_free_consistent_buf(struct buf *bp)
1027c478bd9Sstevel@tonic-gate {
1037c478bd9Sstevel@tonic-gate
1047c478bd9Sstevel@tonic-gate if (!bp)
1057c478bd9Sstevel@tonic-gate return;
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate if (bp->b_un.b_addr)
1087b93957cSeota i_ddi_mem_free((caddr_t)bp->b_un.b_addr, NULL);
1097c478bd9Sstevel@tonic-gate freerbuf(bp);
1107c478bd9Sstevel@tonic-gate if (dcd_callback_id != 0L) {
1117c478bd9Sstevel@tonic-gate ddi_run_callback(&dcd_callback_id);
1127c478bd9Sstevel@tonic-gate }
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate }
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate struct dcd_pkt *
dcd_init_pkt(struct dcd_address * ap,struct dcd_pkt * in_pktp,struct buf * bp,int cmdlen,int statuslen,int pplen,int flags,int (* callback)(caddr_t),caddr_t callback_arg)1177c478bd9Sstevel@tonic-gate dcd_init_pkt(struct dcd_address *ap, struct dcd_pkt *in_pktp,
118*86ef0a63SRichard Lowe struct buf *bp, int cmdlen, int statuslen, int pplen,
119*86ef0a63SRichard Lowe int flags, int (*callback)(caddr_t), caddr_t callback_arg)
1207c478bd9Sstevel@tonic-gate {
1217c478bd9Sstevel@tonic-gate struct dcd_pkt *pktp;
1227c478bd9Sstevel@tonic-gate dcd_hba_tran_t *tranp = ap->a_hba_tran;
1237c478bd9Sstevel@tonic-gate int (*func)(caddr_t);
1247c478bd9Sstevel@tonic-gate
125*86ef0a63SRichard Lowe #if defined(__x86)
1267c478bd9Sstevel@tonic-gate if (flags & PKT_CONSISTENT_OLD) {
1277c478bd9Sstevel@tonic-gate flags &= ~PKT_CONSISTENT_OLD;
1287c478bd9Sstevel@tonic-gate flags |= PKT_CONSISTENT;
1297c478bd9Sstevel@tonic-gate }
130*86ef0a63SRichard Lowe #endif /* __x86 */
1317c478bd9Sstevel@tonic-gate
1327c478bd9Sstevel@tonic-gate func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
1337c478bd9Sstevel@tonic-gate
1347c478bd9Sstevel@tonic-gate pktp = (*tranp->tran_init_pkt)(ap, in_pktp, bp, cmdlen,
135*86ef0a63SRichard Lowe statuslen, pplen, flags, func, NULL);
1367c478bd9Sstevel@tonic-gate
1377c478bd9Sstevel@tonic-gate if (pktp == NULL) {
1387c478bd9Sstevel@tonic-gate if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
1397c478bd9Sstevel@tonic-gate ddi_set_callback(callback, callback_arg,
140*86ef0a63SRichard Lowe &dcd_callback_id);
1417c478bd9Sstevel@tonic-gate }
1427c478bd9Sstevel@tonic-gate }
1437c478bd9Sstevel@tonic-gate
1447c478bd9Sstevel@tonic-gate return (pktp);
1457c478bd9Sstevel@tonic-gate }
1467c478bd9Sstevel@tonic-gate
1477c478bd9Sstevel@tonic-gate void
dcd_destroy_pkt(struct dcd_pkt * pkt)1487c478bd9Sstevel@tonic-gate dcd_destroy_pkt(struct dcd_pkt *pkt)
1497c478bd9Sstevel@tonic-gate {
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate struct dcd_address *ap = P_TO_ADDR(pkt);
1527c478bd9Sstevel@tonic-gate
1537c478bd9Sstevel@tonic-gate (*A_TO_TRAN(ap)->tran_destroy_pkt)(ap, pkt);
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate if (dcd_callback_id != 0L) {
1567c478bd9Sstevel@tonic-gate ddi_run_callback(&dcd_callback_id);
1577c478bd9Sstevel@tonic-gate }
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate }
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate struct dcd_pkt *
dcd_resalloc(struct dcd_address * ap,int cmdlen,int statuslen,ataopaque_t dmatoken,int (* callback)())1627c478bd9Sstevel@tonic-gate dcd_resalloc(struct dcd_address *ap, int cmdlen, int statuslen,
163*86ef0a63SRichard Lowe ataopaque_t dmatoken, int (*callback)())
1647c478bd9Sstevel@tonic-gate {
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate register struct dcd_pkt *pkt;
1677c478bd9Sstevel@tonic-gate register dcd_hba_tran_t *tranp = ap->a_hba_tran;
1687c478bd9Sstevel@tonic-gate register int (*func)(caddr_t);
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate
1717c478bd9Sstevel@tonic-gate func = (callback == SLEEP_FUNC) ? SLEEP_FUNC: NULL_FUNC;
1727c478bd9Sstevel@tonic-gate pkt = (*tranp->tran_init_pkt) (ap, NULL, (struct buf *)dmatoken,
173*86ef0a63SRichard Lowe cmdlen, statuslen, 0, 0, func, NULL);
1747c478bd9Sstevel@tonic-gate
1757c478bd9Sstevel@tonic-gate if (pkt == NULL) {
1767c478bd9Sstevel@tonic-gate if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
1777c478bd9Sstevel@tonic-gate ddi_set_callback(callback, NULL, &dcd_callback_id);
1787c478bd9Sstevel@tonic-gate }
1797c478bd9Sstevel@tonic-gate }
1807c478bd9Sstevel@tonic-gate return (pkt);
1817c478bd9Sstevel@tonic-gate }
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate
1847c478bd9Sstevel@tonic-gate struct dcd_pkt *
dcd_pktalloc(struct dcd_address * ap,int cmdlen,int statuslen,int (* callback)())1857c478bd9Sstevel@tonic-gate dcd_pktalloc(struct dcd_address *ap, int cmdlen, int statuslen,
186*86ef0a63SRichard Lowe int (*callback)())
1877c478bd9Sstevel@tonic-gate {
1887c478bd9Sstevel@tonic-gate
189*86ef0a63SRichard Lowe struct dcd_pkt *pkt;
1907c478bd9Sstevel@tonic-gate struct dcd_hba_tran *tran = ap->a_hba_tran;
191*86ef0a63SRichard Lowe register int (*func)(caddr_t);
1927c478bd9Sstevel@tonic-gate
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate func = (callback == SLEEP_FUNC) ? SLEEP_FUNC: NULL_FUNC;
1957c478bd9Sstevel@tonic-gate
1967c478bd9Sstevel@tonic-gate pkt = (*tran->tran_init_pkt) (ap, NULL, NULL, cmdlen, statuslen,
197*86ef0a63SRichard Lowe 0, 0, func, NULL);
1987c478bd9Sstevel@tonic-gate if (pkt == NULL) {
1997c478bd9Sstevel@tonic-gate if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
2007c478bd9Sstevel@tonic-gate ddi_set_callback(callback, NULL, &dcd_callback_id);
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate }
2037c478bd9Sstevel@tonic-gate return (pkt);
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate
2067c478bd9Sstevel@tonic-gate
2077c478bd9Sstevel@tonic-gate struct dcd_pkt *
dcd_dmaget(struct dcd_pkt * pkt,ataopaque_t dmatoken,int (* callback)())2087c478bd9Sstevel@tonic-gate dcd_dmaget(struct dcd_pkt *pkt, ataopaque_t dmatoken, int (*callback)())
2097c478bd9Sstevel@tonic-gate {
2107c478bd9Sstevel@tonic-gate
2117c478bd9Sstevel@tonic-gate struct dcd_pkt *new_pkt;
2127c478bd9Sstevel@tonic-gate register int (*func)(caddr_t);
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
2157c478bd9Sstevel@tonic-gate
2167c478bd9Sstevel@tonic-gate new_pkt = (*P_TO_TRAN(pkt)->tran_init_pkt) (&pkt->pkt_address,
217*86ef0a63SRichard Lowe pkt, (struct buf *)dmatoken, 0, 0, 0, 0, func, NULL);
2187c478bd9Sstevel@tonic-gate
2197c478bd9Sstevel@tonic-gate ASSERT(new_pkt == pkt || new_pkt == NULL);
2207c478bd9Sstevel@tonic-gate if (new_pkt == NULL) {
2217c478bd9Sstevel@tonic-gate if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
2227c478bd9Sstevel@tonic-gate ddi_set_callback(callback, NULL, &dcd_callback_id);
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate }
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate return (pkt);
2277c478bd9Sstevel@tonic-gate }
2287c478bd9Sstevel@tonic-gate
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate /*
2317c478bd9Sstevel@tonic-gate * Generic Resource Allocation Routines
2327c478bd9Sstevel@tonic-gate */
2337c478bd9Sstevel@tonic-gate
2347c478bd9Sstevel@tonic-gate void
dcd_dmafree(struct dcd_pkt * pkt)2357c478bd9Sstevel@tonic-gate dcd_dmafree(struct dcd_pkt *pkt)
2367c478bd9Sstevel@tonic-gate {
2377c478bd9Sstevel@tonic-gate
2387c478bd9Sstevel@tonic-gate register struct dcd_address *ap = P_TO_ADDR(pkt);
2397c478bd9Sstevel@tonic-gate
2407c478bd9Sstevel@tonic-gate (*A_TO_TRAN(ap)->tran_dmafree)(ap, pkt);
2417c478bd9Sstevel@tonic-gate
2427c478bd9Sstevel@tonic-gate if (dcd_callback_id != 0L) {
2437c478bd9Sstevel@tonic-gate ddi_run_callback(&dcd_callback_id);
2447c478bd9Sstevel@tonic-gate }
2457c478bd9Sstevel@tonic-gate
2467c478bd9Sstevel@tonic-gate }
2477c478bd9Sstevel@tonic-gate
2487c478bd9Sstevel@tonic-gate void
dcd_sync_pkt(struct dcd_pkt * pkt)2497c478bd9Sstevel@tonic-gate dcd_sync_pkt(struct dcd_pkt *pkt)
2507c478bd9Sstevel@tonic-gate {
2517c478bd9Sstevel@tonic-gate register struct dcd_address *ap = P_TO_ADDR(pkt);
2527c478bd9Sstevel@tonic-gate
2537c478bd9Sstevel@tonic-gate (*A_TO_TRAN(ap)->tran_sync_pkt) (ap, pkt);
2547c478bd9Sstevel@tonic-gate }
2557c478bd9Sstevel@tonic-gate
2567c478bd9Sstevel@tonic-gate void
dcd_resfree(struct dcd_pkt * pkt)2577c478bd9Sstevel@tonic-gate dcd_resfree(struct dcd_pkt *pkt)
2587c478bd9Sstevel@tonic-gate {
2597c478bd9Sstevel@tonic-gate
2607c478bd9Sstevel@tonic-gate register struct dcd_address *ap = P_TO_ADDR(pkt);
2617c478bd9Sstevel@tonic-gate
2627c478bd9Sstevel@tonic-gate (*A_TO_TRAN(ap)->tran_destroy_pkt)(ap, pkt);
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate if (dcd_callback_id != 0L) {
2657c478bd9Sstevel@tonic-gate ddi_run_callback(&dcd_callback_id);
2667c478bd9Sstevel@tonic-gate }
2677c478bd9Sstevel@tonic-gate }
268