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