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