xref: /onnv-gate/usr/src/uts/sun/io/dada/impl/dcd_resource.c (revision 1900:7657500f392a)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51106Smrj  * Common Development and Distribution License (the "License").
61106Smrj  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
211106Smrj 
220Sstevel@tonic-gate /*
23*1900Seota  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #include <sys/dada/dada.h>
300Sstevel@tonic-gate #include <sys/vtrace.h>
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #define	A_TO_TRAN(ap)	((ap)->a_hba_tran)
330Sstevel@tonic-gate #define	P_TO_TRAN(pkt)	((pkt)->pkt_address.a_hba_tran)
340Sstevel@tonic-gate #define	P_TO_ADDR(pkt)	(&((pkt)->pkt_address))
350Sstevel@tonic-gate 
360Sstevel@tonic-gate /*
370Sstevel@tonic-gate  * Callback id
380Sstevel@tonic-gate  */
390Sstevel@tonic-gate uintptr_t	dcd_callback_id = 0L;
400Sstevel@tonic-gate 
411106Smrj /* For i_ddi_mem_alloc() in dcd_alloc_consistent_buf() */
421106Smrj static ddi_dma_attr_t standard_dma_attr = {
431106Smrj 	DMA_ATTR_V0,	/* version number */
441106Smrj 	0x0,		/* lowest usable address */
451106Smrj 	0xFFFFFFFFull,	/* high DMA address range */
461106Smrj 	0xFFFFFFFFull,	/* DMA counter register */
471106Smrj 	1,		/* DMA address alignment */
481106Smrj 	1,		/* DMA burstsizes */
491106Smrj 	1,		/* min effective DMA size */
501106Smrj 	0xFFFFFFFFull,	/* max DMA xfer size */
511106Smrj 	0xFFFFFFFFull,	/* segment boundary */
521106Smrj 	1,		/* s/g list length */
531106Smrj 	512,		/* granularity of device */
541106Smrj 	0,		/* DMA transfer flags */
551106Smrj };
560Sstevel@tonic-gate 
570Sstevel@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)580Sstevel@tonic-gate dcd_alloc_consistent_buf(struct dcd_address *ap,
590Sstevel@tonic-gate 	struct buf *in_bp, size_t datalen, uint_t bflags,
600Sstevel@tonic-gate 	int (*callback)(caddr_t), caddr_t callback_arg)
610Sstevel@tonic-gate {
620Sstevel@tonic-gate 
630Sstevel@tonic-gate 	dev_info_t	*pdip;
640Sstevel@tonic-gate 	struct	buf 	*bp;
650Sstevel@tonic-gate 	int		kmflag;
661106Smrj 	size_t		rlen;
670Sstevel@tonic-gate 
680Sstevel@tonic-gate 
690Sstevel@tonic-gate 	if (!in_bp) {
700Sstevel@tonic-gate 		kmflag = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP;
710Sstevel@tonic-gate 		if ((bp = getrbuf(kmflag)) == NULL) {
720Sstevel@tonic-gate 			goto no_resource;
730Sstevel@tonic-gate 		}
740Sstevel@tonic-gate 	} else
750Sstevel@tonic-gate 		bp = in_bp;
760Sstevel@tonic-gate 
770Sstevel@tonic-gate 	bp->b_un.b_addr = 0;
780Sstevel@tonic-gate 	if (datalen) {
790Sstevel@tonic-gate 		pdip = (A_TO_TRAN(ap))->tran_hba_dip;
801106Smrj 		if (i_ddi_mem_alloc(pdip, &standard_dma_attr, datalen, 0,
811106Smrj 		    0, NULL, &bp->b_un.b_addr, &rlen, NULL) != DDI_SUCCESS) {
820Sstevel@tonic-gate 			if (!in_bp)
830Sstevel@tonic-gate 				freerbuf(bp);
840Sstevel@tonic-gate 			goto no_resource;
850Sstevel@tonic-gate 		}
860Sstevel@tonic-gate 		bp->b_flags |= bflags;
870Sstevel@tonic-gate 	}
880Sstevel@tonic-gate 	bp->b_bcount = datalen;
890Sstevel@tonic-gate 	bp->b_resid = 0;
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 	return (bp);
920Sstevel@tonic-gate 
930Sstevel@tonic-gate no_resource:
940Sstevel@tonic-gate 	if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
950Sstevel@tonic-gate 		ddi_set_callback(callback, callback_arg, &dcd_callback_id);
960Sstevel@tonic-gate 	}
970Sstevel@tonic-gate 
980Sstevel@tonic-gate 	return (NULL);
990Sstevel@tonic-gate }
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate void
dcd_free_consistent_buf(struct buf * bp)1030Sstevel@tonic-gate dcd_free_consistent_buf(struct buf *bp)
1040Sstevel@tonic-gate {
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 	if (!bp)
1070Sstevel@tonic-gate 		return;
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate 	if (bp->b_un.b_addr)
110*1900Seota 		i_ddi_mem_free((caddr_t)bp->b_un.b_addr, NULL);
1110Sstevel@tonic-gate 	freerbuf(bp);
1120Sstevel@tonic-gate 	if (dcd_callback_id != 0L) {
1130Sstevel@tonic-gate 		ddi_run_callback(&dcd_callback_id);
1140Sstevel@tonic-gate 	}
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate }
1170Sstevel@tonic-gate 
1180Sstevel@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)1190Sstevel@tonic-gate dcd_init_pkt(struct dcd_address *ap, struct dcd_pkt *in_pktp,
1200Sstevel@tonic-gate 	struct buf *bp, int cmdlen, int statuslen, int pplen,
1210Sstevel@tonic-gate 	int flags, int (*callback)(caddr_t), caddr_t callback_arg)
1220Sstevel@tonic-gate {
1230Sstevel@tonic-gate 	struct dcd_pkt *pktp;
1240Sstevel@tonic-gate 	dcd_hba_tran_t	*tranp = ap->a_hba_tran;
1250Sstevel@tonic-gate 	int		(*func)(caddr_t);
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate #if defined(__i386) || defined(__amd64)
1280Sstevel@tonic-gate 	if (flags & PKT_CONSISTENT_OLD) {
1290Sstevel@tonic-gate 		flags &= ~PKT_CONSISTENT_OLD;
1300Sstevel@tonic-gate 		flags |= PKT_CONSISTENT;
1310Sstevel@tonic-gate 	}
1320Sstevel@tonic-gate #endif	/* __i386 || __amd64 */
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 	func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate 	pktp = (*tranp->tran_init_pkt)(ap, in_pktp, bp, cmdlen,
1370Sstevel@tonic-gate 		statuslen, pplen, flags, func, NULL);
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 	if (pktp == NULL) {
1400Sstevel@tonic-gate 		if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
1410Sstevel@tonic-gate 			ddi_set_callback(callback, callback_arg,
1420Sstevel@tonic-gate 				&dcd_callback_id);
1430Sstevel@tonic-gate 		}
1440Sstevel@tonic-gate 	}
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate 	return (pktp);
1470Sstevel@tonic-gate }
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate void
dcd_destroy_pkt(struct dcd_pkt * pkt)1500Sstevel@tonic-gate dcd_destroy_pkt(struct dcd_pkt *pkt)
1510Sstevel@tonic-gate {
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 	struct dcd_address *ap = P_TO_ADDR(pkt);
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 	(*A_TO_TRAN(ap)->tran_destroy_pkt)(ap, pkt);
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 	if (dcd_callback_id != 0L) {
1580Sstevel@tonic-gate 		ddi_run_callback(&dcd_callback_id);
1590Sstevel@tonic-gate 	}
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate }
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate struct dcd_pkt *
dcd_resalloc(struct dcd_address * ap,int cmdlen,int statuslen,ataopaque_t dmatoken,int (* callback)())1640Sstevel@tonic-gate dcd_resalloc(struct dcd_address *ap, int cmdlen, int statuslen,
1650Sstevel@tonic-gate 	ataopaque_t dmatoken, int (*callback)())
1660Sstevel@tonic-gate {
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 	register struct dcd_pkt *pkt;
1690Sstevel@tonic-gate 	register dcd_hba_tran_t	*tranp = ap->a_hba_tran;
1700Sstevel@tonic-gate 	register int		(*func)(caddr_t);
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 	func = (callback == SLEEP_FUNC) ? SLEEP_FUNC: NULL_FUNC;
1740Sstevel@tonic-gate 	pkt = (*tranp->tran_init_pkt) (ap, NULL, (struct buf *)dmatoken,
1750Sstevel@tonic-gate 		cmdlen, statuslen, 0, 0, func, NULL);
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 	if (pkt == NULL) {
1780Sstevel@tonic-gate 		if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
1790Sstevel@tonic-gate 			ddi_set_callback(callback, NULL, &dcd_callback_id);
1800Sstevel@tonic-gate 		}
1810Sstevel@tonic-gate 	}
1820Sstevel@tonic-gate 	return (pkt);
1830Sstevel@tonic-gate }
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate struct dcd_pkt *
dcd_pktalloc(struct dcd_address * ap,int cmdlen,int statuslen,int (* callback)())1870Sstevel@tonic-gate dcd_pktalloc(struct dcd_address *ap, int cmdlen, int statuslen,
1880Sstevel@tonic-gate 	int (*callback)())
1890Sstevel@tonic-gate {
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate 	struct dcd_pkt 	*pkt;
1920Sstevel@tonic-gate 	struct dcd_hba_tran	*tran = ap->a_hba_tran;
1930Sstevel@tonic-gate 	register int 		(*func)(caddr_t);
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate 	func = (callback == SLEEP_FUNC) ? SLEEP_FUNC: NULL_FUNC;
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate 	pkt = (*tran->tran_init_pkt) (ap, NULL, NULL, cmdlen, statuslen,
1990Sstevel@tonic-gate 		0, 0, func, NULL);
2000Sstevel@tonic-gate 	if (pkt == NULL) {
2010Sstevel@tonic-gate 		if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
2020Sstevel@tonic-gate 			ddi_set_callback(callback, NULL, &dcd_callback_id);
2030Sstevel@tonic-gate 		}
2040Sstevel@tonic-gate 	}
2050Sstevel@tonic-gate 	return (pkt);
2060Sstevel@tonic-gate }
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate struct dcd_pkt *
dcd_dmaget(struct dcd_pkt * pkt,ataopaque_t dmatoken,int (* callback)())2100Sstevel@tonic-gate dcd_dmaget(struct dcd_pkt *pkt, ataopaque_t dmatoken, int (*callback)())
2110Sstevel@tonic-gate {
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate 	struct dcd_pkt *new_pkt;
2140Sstevel@tonic-gate 	register	int	(*func)(caddr_t);
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate 	func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 	new_pkt = (*P_TO_TRAN(pkt)->tran_init_pkt) (&pkt->pkt_address,
2190Sstevel@tonic-gate 		pkt, (struct buf *)dmatoken, 0, 0, 0, 0, func, NULL);
2200Sstevel@tonic-gate 
2210Sstevel@tonic-gate 	ASSERT(new_pkt == pkt || new_pkt == NULL);
2220Sstevel@tonic-gate 	if (new_pkt == NULL) {
2230Sstevel@tonic-gate 		if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
2240Sstevel@tonic-gate 			ddi_set_callback(callback, NULL, &dcd_callback_id);
2250Sstevel@tonic-gate 		}
2260Sstevel@tonic-gate 	}
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 	return (pkt);
2290Sstevel@tonic-gate }
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate /*
2330Sstevel@tonic-gate  * Generic Resource Allocation Routines
2340Sstevel@tonic-gate  */
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate void
dcd_dmafree(struct dcd_pkt * pkt)2370Sstevel@tonic-gate dcd_dmafree(struct dcd_pkt *pkt)
2380Sstevel@tonic-gate {
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 	register struct dcd_address *ap = P_TO_ADDR(pkt);
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 	(*A_TO_TRAN(ap)->tran_dmafree)(ap, pkt);
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 	if (dcd_callback_id != 0L) {
2450Sstevel@tonic-gate 		ddi_run_callback(&dcd_callback_id);
2460Sstevel@tonic-gate 	}
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate void
dcd_sync_pkt(struct dcd_pkt * pkt)2510Sstevel@tonic-gate dcd_sync_pkt(struct dcd_pkt *pkt)
2520Sstevel@tonic-gate {
2530Sstevel@tonic-gate 	register struct dcd_address *ap = P_TO_ADDR(pkt);
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 	(*A_TO_TRAN(ap)->tran_sync_pkt) (ap, pkt);
2560Sstevel@tonic-gate }
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate void
dcd_resfree(struct dcd_pkt * pkt)2590Sstevel@tonic-gate dcd_resfree(struct dcd_pkt *pkt)
2600Sstevel@tonic-gate {
2610Sstevel@tonic-gate 
2620Sstevel@tonic-gate 	register struct dcd_address *ap = P_TO_ADDR(pkt);
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate 	(*A_TO_TRAN(ap)->tran_destroy_pkt)(ap, pkt);
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate 	if (dcd_callback_id != 0L) {
2670Sstevel@tonic-gate 		ddi_run_callback(&dcd_callback_id);
2680Sstevel@tonic-gate 	}
2690Sstevel@tonic-gate }
270