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 /*
2332141dfcSNikko He  * Copyright 2009 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/scsi/scsi.h>
287c478bd9Sstevel@tonic-gate #include <sys/vtrace.h>
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #define	A_TO_TRAN(ap)	((ap)->a_hba_tran)
327c478bd9Sstevel@tonic-gate #define	P_TO_TRAN(pkt)	((pkt)->pkt_address.a_hba_tran)
337c478bd9Sstevel@tonic-gate #define	P_TO_ADDR(pkt)	(&((pkt)->pkt_address))
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate /*
367c478bd9Sstevel@tonic-gate  * Callback id
377c478bd9Sstevel@tonic-gate  */
387c478bd9Sstevel@tonic-gate uintptr_t scsi_callback_id = 0;
397c478bd9Sstevel@tonic-gate 
404ab75253Smrj extern ddi_dma_attr_t scsi_alloc_attr;
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate struct buf *
437c478bd9Sstevel@tonic-gate scsi_alloc_consistent_buf(struct scsi_address *ap,
447c478bd9Sstevel@tonic-gate     struct buf *in_bp, size_t datalen, uint_t bflags,
457c478bd9Sstevel@tonic-gate     int (*callback)(caddr_t), caddr_t callback_arg)
467c478bd9Sstevel@tonic-gate {
477c478bd9Sstevel@tonic-gate 	dev_info_t	*pdip;
487c478bd9Sstevel@tonic-gate 	struct		buf *bp;
497c478bd9Sstevel@tonic-gate 	int		kmflag;
504ab75253Smrj 	size_t		rlen;
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate 	TRACE_0(TR_FAC_SCSI_RES, TR_SCSI_ALLOC_CONSISTENT_BUF_START,
53c6c44d06Sjw 	    "scsi_alloc_consistent_buf_start");
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate 	if (!in_bp) {
567c478bd9Sstevel@tonic-gate 		kmflag = (callback == SLEEP_FUNC) ? KM_SLEEP : KM_NOSLEEP;
577c478bd9Sstevel@tonic-gate 		if ((bp = getrbuf(kmflag)) == NULL) {
587c478bd9Sstevel@tonic-gate 			goto no_resource;
597c478bd9Sstevel@tonic-gate 		}
607c478bd9Sstevel@tonic-gate 	} else {
617c478bd9Sstevel@tonic-gate 		bp = in_bp;
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate 		/* we are establishing a new buffer memory association */
647c478bd9Sstevel@tonic-gate 		bp->b_flags &= ~(B_PAGEIO | B_PHYS | B_REMAPPED | B_SHADOW);
657c478bd9Sstevel@tonic-gate 		bp->b_proc = NULL;
667c478bd9Sstevel@tonic-gate 		bp->b_pages = NULL;
677c478bd9Sstevel@tonic-gate 		bp->b_shadow = NULL;
687c478bd9Sstevel@tonic-gate 	}
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate 	/* limit bits that can be set by bflags argument */
717c478bd9Sstevel@tonic-gate 	ASSERT(!(bflags & ~(B_READ | B_WRITE)));
727c478bd9Sstevel@tonic-gate 	bflags &= (B_READ | B_WRITE);
737c478bd9Sstevel@tonic-gate 	bp->b_un.b_addr = 0;
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate 	if (datalen) {
767c478bd9Sstevel@tonic-gate 		pdip = (A_TO_TRAN(ap))->tran_hba_dip;
777c478bd9Sstevel@tonic-gate 
784ab75253Smrj 		/*
794ab75253Smrj 		 * use i_ddi_mem_alloc() for now until we have an interface to
804ab75253Smrj 		 * allocate memory for DMA which doesn't require a DMA handle.
814ab75253Smrj 		 * ddi_iopb_alloc() is obsolete and we want more flexibility in
824ab75253Smrj 		 * controlling the DMA address constraints.
834ab75253Smrj 		 */
844ab75253Smrj 		while (i_ddi_mem_alloc(pdip, &scsi_alloc_attr, datalen,
854ab75253Smrj 		    ((callback == SLEEP_FUNC) ? 1 : 0), 0, NULL,
864ab75253Smrj 		    &bp->b_un.b_addr, &rlen, NULL) != DDI_SUCCESS) {
877c478bd9Sstevel@tonic-gate 			if (callback == SLEEP_FUNC) {
887c478bd9Sstevel@tonic-gate 				delay(drv_usectohz(10000));
897c478bd9Sstevel@tonic-gate 			} else {
907c478bd9Sstevel@tonic-gate 				if (!in_bp)
917c478bd9Sstevel@tonic-gate 					freerbuf(bp);
927c478bd9Sstevel@tonic-gate 				goto no_resource;
937c478bd9Sstevel@tonic-gate 			}
947c478bd9Sstevel@tonic-gate 		}
957c478bd9Sstevel@tonic-gate 		bp->b_flags |= bflags;
967c478bd9Sstevel@tonic-gate 	}
977c478bd9Sstevel@tonic-gate 	bp->b_bcount = datalen;
987c478bd9Sstevel@tonic-gate 	bp->b_resid = 0;
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 	TRACE_0(TR_FAC_SCSI_RES, TR_SCSI_ALLOC_CONSISTENT_BUF_END,
101c6c44d06Sjw 	    "scsi_alloc_consistent_buf_end");
1027c478bd9Sstevel@tonic-gate 	return (bp);
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate no_resource:
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
1077c478bd9Sstevel@tonic-gate 		ddi_set_callback(callback, callback_arg,
108c6c44d06Sjw 		    &scsi_callback_id);
1097c478bd9Sstevel@tonic-gate 	}
1107c478bd9Sstevel@tonic-gate 	TRACE_0(TR_FAC_SCSI_RES,
1117c478bd9Sstevel@tonic-gate 	    TR_SCSI_ALLOC_CONSISTENT_BUF_RETURN1_END,
1127c478bd9Sstevel@tonic-gate 	    "scsi_alloc_consistent_buf_end (return1)");
1137c478bd9Sstevel@tonic-gate 	return (NULL);
1147c478bd9Sstevel@tonic-gate }
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate void
1177c478bd9Sstevel@tonic-gate scsi_free_consistent_buf(struct buf *bp)
1187c478bd9Sstevel@tonic-gate {
1197c478bd9Sstevel@tonic-gate 	TRACE_0(TR_FAC_SCSI_RES, TR_SCSI_FREE_CONSISTENT_BUF_START,
120c6c44d06Sjw 	    "scsi_free_consistent_buf_start");
1217c478bd9Sstevel@tonic-gate 	if (!bp)
1227c478bd9Sstevel@tonic-gate 		return;
1237c478bd9Sstevel@tonic-gate 	if (bp->b_un.b_addr)
1247b93957cSeota 		i_ddi_mem_free((caddr_t)bp->b_un.b_addr, NULL);
1257c478bd9Sstevel@tonic-gate 	freerbuf(bp);
1267c478bd9Sstevel@tonic-gate 	if (scsi_callback_id != 0) {
1277c478bd9Sstevel@tonic-gate 		ddi_run_callback(&scsi_callback_id);
1287c478bd9Sstevel@tonic-gate 	}
1297c478bd9Sstevel@tonic-gate 	TRACE_0(TR_FAC_SCSI_RES, TR_SCSI_FREE_CONSISTENT_BUF_END,
130c6c44d06Sjw 	    "scsi_free_consistent_buf_end");
1317c478bd9Sstevel@tonic-gate }
1327c478bd9Sstevel@tonic-gate 
1338faf39b2Staylor void
1348faf39b2Staylor scsi_dmafree_attr(struct scsi_pkt *pktp)
1358faf39b2Staylor {
1368faf39b2Staylor 	struct scsi_pkt_cache_wrapper *pktw =
137c6c44d06Sjw 	    (struct scsi_pkt_cache_wrapper *)pktp;
1388faf39b2Staylor 
1398faf39b2Staylor 	if (pktw->pcw_flags & PCW_BOUND) {
1408faf39b2Staylor 		if (ddi_dma_unbind_handle(pktp->pkt_handle) !=
1418faf39b2Staylor 		    DDI_SUCCESS)
1428faf39b2Staylor 			cmn_err(CE_WARN, "scsi_dmafree_attr: "
1438faf39b2Staylor 			    "unbind handle failed");
1448faf39b2Staylor 		pktw->pcw_flags &= ~PCW_BOUND;
1458faf39b2Staylor 	}
1468faf39b2Staylor 	pktp->pkt_numcookies = 0;
14732141dfcSNikko He 	pktw->pcw_totalwin = 0;
1488faf39b2Staylor }
1498faf39b2Staylor 
1508faf39b2Staylor struct buf *
1518faf39b2Staylor scsi_pkt2bp(struct scsi_pkt *pkt)
1528faf39b2Staylor {
1538faf39b2Staylor 	return (((struct scsi_pkt_cache_wrapper *)pkt)->pcw_bp);
1548faf39b2Staylor }
1558faf39b2Staylor 
1568faf39b2Staylor int
1578faf39b2Staylor scsi_dma_buf_bind_attr(struct scsi_pkt_cache_wrapper *pktw,
1588faf39b2Staylor 			struct buf	*bp,
1598faf39b2Staylor 			int		 dma_flags,
1608faf39b2Staylor 			int		(*callback)(),
1618faf39b2Staylor 			caddr_t		 arg)
1628faf39b2Staylor {
1638faf39b2Staylor 	struct scsi_pkt *pktp = &(pktw->pcw_pkt);
1648faf39b2Staylor 	int	 status;
1658faf39b2Staylor 
1668faf39b2Staylor 	/*
1678faf39b2Staylor 	 * First time, need to establish the handle.
1688faf39b2Staylor 	 */
1698faf39b2Staylor 
1708faf39b2Staylor 	ASSERT(pktp->pkt_numcookies == 0);
1718faf39b2Staylor 	ASSERT(pktw->pcw_totalwin == 0);
1728faf39b2Staylor 
1738faf39b2Staylor 	status = ddi_dma_buf_bind_handle(pktp->pkt_handle, bp, dma_flags,
174c6c44d06Sjw 	    callback, arg, &pktw->pcw_cookie,
175c6c44d06Sjw 	    &pktp->pkt_numcookies);
1768faf39b2Staylor 
1778faf39b2Staylor 	switch (status) {
1788faf39b2Staylor 	case DDI_DMA_MAPPED:
1798faf39b2Staylor 		pktw->pcw_totalwin = 1;
1808faf39b2Staylor 		break;
1818faf39b2Staylor 
1828faf39b2Staylor 	case DDI_DMA_PARTIAL_MAP:
1838faf39b2Staylor 		/* enable first call to ddi_dma_getwin */
1848faf39b2Staylor 		if (ddi_dma_numwin(pktp->pkt_handle,
1858faf39b2Staylor 		    &pktw->pcw_totalwin) != DDI_SUCCESS) {
1868faf39b2Staylor 			bp->b_error = 0;
1878faf39b2Staylor 			return (0);
1888faf39b2Staylor 		}
1898faf39b2Staylor 		break;
1908faf39b2Staylor 
1918faf39b2Staylor 	case DDI_DMA_NORESOURCES:
1928faf39b2Staylor 		bp->b_error = 0;
1938faf39b2Staylor 		return (0);
1948faf39b2Staylor 
1958faf39b2Staylor 	case DDI_DMA_TOOBIG:
1968faf39b2Staylor 		bioerror(bp, EINVAL);
1978faf39b2Staylor 		return (0);
1988faf39b2Staylor 
1998faf39b2Staylor 	case DDI_DMA_NOMAPPING:
2008faf39b2Staylor 	case DDI_DMA_INUSE:
2018faf39b2Staylor 	default:
2028faf39b2Staylor 		bioerror(bp, EFAULT);
2038faf39b2Staylor 		return (0);
2048faf39b2Staylor 	}
2058faf39b2Staylor 
2068faf39b2Staylor 	/* initialize the loop controls for scsi_dmaget_attr() */
2078faf39b2Staylor 	pktw->pcw_curwin = 0;
2088faf39b2Staylor 	pktw->pcw_total_xfer = 0;
2098faf39b2Staylor 	pktp->pkt_dma_flags = dma_flags;
2108faf39b2Staylor 	return (1);
2118faf39b2Staylor }
2128faf39b2Staylor 
2138faf39b2Staylor #if defined(_DMA_USES_PHYSADDR)
2148faf39b2Staylor int
2158faf39b2Staylor scsi_dmaget_attr(struct scsi_pkt_cache_wrapper *pktw)
2168faf39b2Staylor {
2178faf39b2Staylor 	struct scsi_pkt *pktp = &(pktw->pcw_pkt);
2188faf39b2Staylor 
2198faf39b2Staylor 	int		status;
2208faf39b2Staylor 	int		num_segs = 0;
2218faf39b2Staylor 	ddi_dma_impl_t	*hp = (ddi_dma_impl_t *)pktp->pkt_handle;
2228faf39b2Staylor 	ddi_dma_cookie_t *cp;
2238faf39b2Staylor 
2248faf39b2Staylor 	if (pktw->pcw_curwin != 0) {
2258faf39b2Staylor 		ddi_dma_cookie_t	cookie;
2268faf39b2Staylor 
2278faf39b2Staylor 		/*
2288faf39b2Staylor 		 * start the next window, and get its first cookie
2298faf39b2Staylor 		 */
2308faf39b2Staylor 		status = ddi_dma_getwin(pktp->pkt_handle,
231c6c44d06Sjw 		    pktw->pcw_curwin, &pktp->pkt_dma_offset,
232c6c44d06Sjw 		    &pktp->pkt_dma_len, &cookie,
233c6c44d06Sjw 		    &pktp->pkt_numcookies);
2348faf39b2Staylor 		if (status != DDI_SUCCESS)
2358faf39b2Staylor 			return (0);
2368faf39b2Staylor 	}
2378faf39b2Staylor 
2388faf39b2Staylor 	/*
2398faf39b2Staylor 	 * start the Scatter/Gather loop
2408faf39b2Staylor 	 */
2418faf39b2Staylor 	cp = hp->dmai_cookie - 1;
2428faf39b2Staylor 	pktp->pkt_dma_len = 0;
2438faf39b2Staylor 	for (;;) {
2448faf39b2Staylor 
2458faf39b2Staylor 		/* take care of the loop-bookkeeping */
2468faf39b2Staylor 		pktp->pkt_dma_len += cp->dmac_size;
2478faf39b2Staylor 		num_segs++;
2488faf39b2Staylor 		/*
2498faf39b2Staylor 		 * if this was the last cookie in the current window
2508faf39b2Staylor 		 * set the loop controls start the next window and
2518faf39b2Staylor 		 * exit so the HBA can do this partial transfer
2528faf39b2Staylor 		 */
2538faf39b2Staylor 		if (num_segs >= pktp->pkt_numcookies) {
2548faf39b2Staylor 			pktw->pcw_curwin++;
2558faf39b2Staylor 			break;
2568faf39b2Staylor 		}
2578faf39b2Staylor 
2588faf39b2Staylor 		cp++;
2598faf39b2Staylor 	}
2608faf39b2Staylor 	pktw->pcw_total_xfer += pktp->pkt_dma_len;
2618faf39b2Staylor 	pktp->pkt_cookies = hp->dmai_cookie - 1;
2628faf39b2Staylor 	hp->dmai_cookie = cp;
2638faf39b2Staylor 
2648faf39b2Staylor 	return (1);
2658faf39b2Staylor }
2668faf39b2Staylor #endif
2678faf39b2Staylor 
268cab28b2dStaylor void scsi_free_cache_pkt(struct scsi_address *, struct scsi_pkt *);
269cab28b2dStaylor 
270cab28b2dStaylor struct scsi_pkt *
271cab28b2dStaylor scsi_init_cache_pkt(struct scsi_address *ap, struct scsi_pkt *in_pktp,
272cab28b2dStaylor     struct buf *bp, int cmdlen, int statuslen, int pplen,
273cab28b2dStaylor     int flags, int (*callback)(caddr_t), caddr_t callback_arg)
274cab28b2dStaylor {
275cab28b2dStaylor 	struct scsi_pkt_cache_wrapper *pktw;
276cab28b2dStaylor 	scsi_hba_tran_t *tranp = ap->a_hba_tran;
277cab28b2dStaylor 	int		(*func)(caddr_t);
278cab28b2dStaylor 
279cab28b2dStaylor 	func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
280cab28b2dStaylor 
281cab28b2dStaylor 	if (in_pktp == NULL) {
282cab28b2dStaylor 		int kf;
283cab28b2dStaylor 
284cab28b2dStaylor 		if (callback == SLEEP_FUNC)
285cab28b2dStaylor 			kf = KM_SLEEP;
286cab28b2dStaylor 		else
287cab28b2dStaylor 			kf = KM_NOSLEEP;
288*66027529SNikko He 		/*
289*66027529SNikko He 		 * By using kmem_cache_alloc(), the layout of the
290*66027529SNikko He 		 * scsi_pkt, scsi_pkt_cache_wrapper, hba private data,
291*66027529SNikko He 		 * cdb, tgt driver private data, and status block is
292*66027529SNikko He 		 * as below.
293*66027529SNikko He 		 *
294*66027529SNikko He 		 * This is a piece of contiguous memory starting from
295*66027529SNikko He 		 * the first structure field scsi_pkt in the struct
296*66027529SNikko He 		 * scsi_pkt_cache_wrapper, followed by the hba private
297*66027529SNikko He 		 * data, pkt_cdbp, the tgt driver private data and
298*66027529SNikko He 		 * pkt_scbp.
299*66027529SNikko He 		 *
300*66027529SNikko He 		 * |----------------------------|--------------------->
301*66027529SNikko He 		 * |	struct scsi_pkt		|	struct
302*66027529SNikko He 		 * |	......			|scsi_pkt_cache_wrapper
303*66027529SNikko He 		 * |	pcw_flags		|
304*66027529SNikko He 		 * |----------------------------|<---------------------
305*66027529SNikko He 		 * |	hba private data	|tranp->tran_hba_len
306*66027529SNikko He 		 * |----------------------------|
307*66027529SNikko He 		 * |	pkt_cdbp		|DEFAULT_CDBLEN
308*66027529SNikko He 		 * |----------------------------|
309*66027529SNikko He 		 * |	tgt private data	|DEFAULT_PRIVLEN
310*66027529SNikko He 		 * |----------------------------|
311*66027529SNikko He 		 * |	pkt_scbp		|DEFAULT_SCBLEN
312*66027529SNikko He 		 * |----------------------------|
313*66027529SNikko He 		 *
314*66027529SNikko He 		 * If the actual data length of the cdb, or the tgt
315*66027529SNikko He 		 * driver private data, or the status block is bigger
316*66027529SNikko He 		 * than the default data length, kmem_alloc() will be
317*66027529SNikko He 		 * called to get extra space.
318*66027529SNikko He 		 */
319cab28b2dStaylor 		pktw = kmem_cache_alloc(tranp->tran_pkt_cache_ptr,
320c6c44d06Sjw 		    kf);
321cab28b2dStaylor 		if (pktw == NULL)
322cab28b2dStaylor 			goto fail1;
323cab28b2dStaylor 
3248faf39b2Staylor 		pktw->pcw_flags = 0;
325cab28b2dStaylor 		in_pktp = &(pktw->pcw_pkt);
3268faf39b2Staylor 		in_pktp->pkt_address = *ap;
327cab28b2dStaylor 		/*
328830363f4Staylor 		 * target drivers should initialize pkt_comp and
329830363f4Staylor 		 * pkt_time, but sometimes they don't so initialize
330830363f4Staylor 		 * them here to be safe.
331cab28b2dStaylor 		 */
332cab28b2dStaylor 		in_pktp->pkt_address = *ap;
333830363f4Staylor 		in_pktp->pkt_flags = 0;
334830363f4Staylor 		in_pktp->pkt_time = 0;
335cab28b2dStaylor 		in_pktp->pkt_resid = 0;
336cab28b2dStaylor 		in_pktp->pkt_state = 0;
337cab28b2dStaylor 		in_pktp->pkt_statistics = 0;
338cab28b2dStaylor 		in_pktp->pkt_reason = 0;
3398faf39b2Staylor 		in_pktp->pkt_dma_offset = 0;
3408faf39b2Staylor 		in_pktp->pkt_dma_len = 0;
3418faf39b2Staylor 		in_pktp->pkt_dma_flags = 0;
342602ca9eaScth 		in_pktp->pkt_path_instance = 0;
3438faf39b2Staylor 		ASSERT(in_pktp->pkt_numcookies == 0);
3448faf39b2Staylor 		pktw->pcw_curwin = 0;
3458faf39b2Staylor 		pktw->pcw_totalwin = 0;
3468faf39b2Staylor 		pktw->pcw_total_xfer = 0;
347cab28b2dStaylor 
348cab28b2dStaylor 		in_pktp->pkt_cdblen = cmdlen;
349cab28b2dStaylor 		if ((tranp->tran_hba_flags & SCSI_HBA_TRAN_CDB) &&
350cab28b2dStaylor 		    (cmdlen > DEFAULT_CDBLEN)) {
3518faf39b2Staylor 			pktw->pcw_flags |= PCW_NEED_EXT_CDB;
352830363f4Staylor 			in_pktp->pkt_cdbp = kmem_alloc(cmdlen, kf);
353cab28b2dStaylor 			if (in_pktp->pkt_cdbp == NULL)
354cab28b2dStaylor 				goto fail2;
355cab28b2dStaylor 		}
356cab28b2dStaylor 		in_pktp->pkt_tgtlen = pplen;
357cab28b2dStaylor 		if (pplen > DEFAULT_PRIVLEN) {
3588faf39b2Staylor 			pktw->pcw_flags |= PCW_NEED_EXT_TGT;
359830363f4Staylor 			in_pktp->pkt_private = kmem_alloc(pplen, kf);
360cab28b2dStaylor 			if (in_pktp->pkt_private == NULL)
361cab28b2dStaylor 				goto fail3;
362cab28b2dStaylor 		}
363cab28b2dStaylor 		in_pktp->pkt_scblen = statuslen;
364cab28b2dStaylor 		if ((tranp->tran_hba_flags & SCSI_HBA_TRAN_SCB) &&
365cab28b2dStaylor 		    (statuslen > DEFAULT_SCBLEN)) {
3668faf39b2Staylor 			pktw->pcw_flags |= PCW_NEED_EXT_SCB;
367830363f4Staylor 			in_pktp->pkt_scbp = kmem_alloc(statuslen, kf);
368cab28b2dStaylor 			if (in_pktp->pkt_scbp == NULL)
369cab28b2dStaylor 				goto fail4;
370cab28b2dStaylor 		}
371cab28b2dStaylor 		if ((*tranp->tran_setup_pkt) (in_pktp,
372c6c44d06Sjw 		    func, NULL) == -1) {
373cab28b2dStaylor 				goto fail5;
374cab28b2dStaylor 		}
375830363f4Staylor 		if (cmdlen)
376830363f4Staylor 			bzero((void *)in_pktp->pkt_cdbp, cmdlen);
377830363f4Staylor 		if (pplen)
378830363f4Staylor 			bzero((void *)in_pktp->pkt_private, pplen);
379830363f4Staylor 		if (statuslen)
380830363f4Staylor 			bzero((void *)in_pktp->pkt_scbp, statuslen);
3818faf39b2Staylor 	} else
3828faf39b2Staylor 		pktw = (struct scsi_pkt_cache_wrapper *)in_pktp;
3838faf39b2Staylor 
384cab28b2dStaylor 	if (bp && bp->b_bcount) {
3858faf39b2Staylor 
3868faf39b2Staylor 		int dma_flags = 0;
3878faf39b2Staylor 
3888faf39b2Staylor 		/*
3898faf39b2Staylor 		 * we need to transfer data, so we alloc dma resources
3908faf39b2Staylor 		 * for this packet
3918faf39b2Staylor 		 */
3928faf39b2Staylor 		/*CONSTCOND*/
3938faf39b2Staylor 		ASSERT(SLEEP_FUNC == DDI_DMA_SLEEP);
3948faf39b2Staylor 		/*CONSTCOND*/
3958faf39b2Staylor 		ASSERT(NULL_FUNC == DDI_DMA_DONTWAIT);
3968faf39b2Staylor 
3978faf39b2Staylor #if defined(_DMA_USES_PHYSADDR)
3988faf39b2Staylor 		/*
3998faf39b2Staylor 		 * with an IOMMU we map everything, so we don't
4008faf39b2Staylor 		 * need to bother with this
4018faf39b2Staylor 		 */
4028faf39b2Staylor 		if (tranp->tran_dma_attr.dma_attr_granular !=
403c6c44d06Sjw 		    pktw->pcw_granular) {
4048faf39b2Staylor 
4058faf39b2Staylor 			ddi_dma_free_handle(&in_pktp->pkt_handle);
4068faf39b2Staylor 			if (ddi_dma_alloc_handle(tranp->tran_hba_dip,
407c6c44d06Sjw 			    &tranp->tran_dma_attr,
408c6c44d06Sjw 			    func, NULL,
409c6c44d06Sjw 			    &in_pktp->pkt_handle) != DDI_SUCCESS) {
4108faf39b2Staylor 
4118faf39b2Staylor 				in_pktp->pkt_handle = NULL;
4128faf39b2Staylor 				return (NULL);
4138faf39b2Staylor 			}
4148faf39b2Staylor 			pktw->pcw_granular =
415c6c44d06Sjw 			    tranp->tran_dma_attr.dma_attr_granular;
416cab28b2dStaylor 		}
4178faf39b2Staylor #endif
4188faf39b2Staylor 
4198faf39b2Staylor 		if (in_pktp->pkt_numcookies == 0) {
4208faf39b2Staylor 			pktw->pcw_bp = bp;
4218faf39b2Staylor 			/*
4228faf39b2Staylor 			 * set dma flags; the "read" case must be first
4238faf39b2Staylor 			 * since B_WRITE isn't always be set for writes.
4248faf39b2Staylor 			 */
4258faf39b2Staylor 			if (bp->b_flags & B_READ) {
4268faf39b2Staylor 				dma_flags |= DDI_DMA_READ;
4278faf39b2Staylor 			} else {
4288faf39b2Staylor 				dma_flags |= DDI_DMA_WRITE;
4298faf39b2Staylor 			}
4308faf39b2Staylor 			if (flags & PKT_CONSISTENT)
4318faf39b2Staylor 				dma_flags |= DDI_DMA_CONSISTENT;
4328faf39b2Staylor 			if (flags & PKT_DMA_PARTIAL)
4338faf39b2Staylor 				dma_flags |= DDI_DMA_PARTIAL;
4348faf39b2Staylor 
4358faf39b2Staylor #if defined(__sparc)
4368faf39b2Staylor 			/*
4378faf39b2Staylor 			 * workaround for byte hole issue on psycho and
4388faf39b2Staylor 			 * schizo pre 2.1
4398faf39b2Staylor 			 */
4408faf39b2Staylor 			if ((bp->b_flags & B_READ) && ((bp->b_flags &
4418faf39b2Staylor 			    (B_PAGEIO|B_REMAPPED)) != B_PAGEIO) &&
4428faf39b2Staylor 			    (((uintptr_t)bp->b_un.b_addr & 0x7) ||
4438faf39b2Staylor 			    ((uintptr_t)bp->b_bcount & 0x7))) {
4448faf39b2Staylor 				dma_flags |= DDI_DMA_CONSISTENT;
4458faf39b2Staylor 			}
4468faf39b2Staylor #endif
4478faf39b2Staylor 			if (!scsi_dma_buf_bind_attr(pktw, bp,
4488faf39b2Staylor 			    dma_flags, callback, callback_arg)) {
4498faf39b2Staylor 				return (NULL);
4508faf39b2Staylor 			} else {
4518faf39b2Staylor 				pktw->pcw_flags |= PCW_BOUND;
4528faf39b2Staylor 			}
4538faf39b2Staylor 		}
4548faf39b2Staylor 
4558faf39b2Staylor #if defined(_DMA_USES_PHYSADDR)
4568faf39b2Staylor 		if (!scsi_dmaget_attr(pktw)) {
4578faf39b2Staylor 			scsi_dmafree_attr(in_pktp);
4588faf39b2Staylor 			goto fail5;
4598faf39b2Staylor 		}
4608faf39b2Staylor #else
4618faf39b2Staylor 		in_pktp->pkt_cookies = &pktw->pcw_cookie;
4628faf39b2Staylor 		in_pktp->pkt_dma_len = pktw->pcw_cookie.dmac_size;
4638faf39b2Staylor 		pktw->pcw_total_xfer += in_pktp->pkt_dma_len;
4648faf39b2Staylor #endif
4658faf39b2Staylor 		ASSERT(in_pktp->pkt_numcookies <=
466c6c44d06Sjw 		    tranp->tran_dma_attr.dma_attr_sgllen);
4678faf39b2Staylor 		ASSERT(pktw->pcw_total_xfer <= bp->b_bcount);
4688faf39b2Staylor 		in_pktp->pkt_resid = bp->b_bcount -
469c6c44d06Sjw 		    pktw->pcw_total_xfer;
4708faf39b2Staylor 
4718faf39b2Staylor 		ASSERT((in_pktp->pkt_resid % pktw->pcw_granular) ==
472c6c44d06Sjw 		    0);
4738faf39b2Staylor 	} else {
4748faf39b2Staylor 		/* !bp or no b_bcount */
4758faf39b2Staylor 		in_pktp->pkt_resid = 0;
476cab28b2dStaylor 	}
477cab28b2dStaylor 	return (in_pktp);
478cab28b2dStaylor 
479cab28b2dStaylor fail5:
4808faf39b2Staylor 	if (pktw->pcw_flags & PCW_NEED_EXT_SCB) {
481cab28b2dStaylor 		kmem_free(in_pktp->pkt_scbp, statuslen);
482cab28b2dStaylor 		in_pktp->pkt_scbp = (opaque_t)((char *)in_pktp +
483cab28b2dStaylor 		    tranp->tran_hba_len + DEFAULT_PRIVLEN +
484*66027529SNikko He 		    sizeof (struct scsi_pkt_cache_wrapper));
485cab28b2dStaylor 		if ((A_TO_TRAN(ap))->tran_hba_flags & SCSI_HBA_TRAN_CDB)
486cab28b2dStaylor 			in_pktp->pkt_scbp = (opaque_t)((in_pktp->pkt_scbp) +
487c6c44d06Sjw 			    DEFAULT_CDBLEN);
488cab28b2dStaylor 		in_pktp->pkt_scblen = 0;
489cab28b2dStaylor 	}
490cab28b2dStaylor fail4:
4918faf39b2Staylor 	if (pktw->pcw_flags & PCW_NEED_EXT_TGT) {
492cab28b2dStaylor 		kmem_free(in_pktp->pkt_private, pplen);
493cab28b2dStaylor 		in_pktp->pkt_tgtlen = 0;
494cab28b2dStaylor 		in_pktp->pkt_private = NULL;
495cab28b2dStaylor 	}
496cab28b2dStaylor fail3:
4978faf39b2Staylor 	if (pktw->pcw_flags & PCW_NEED_EXT_CDB) {
498cab28b2dStaylor 		kmem_free(in_pktp->pkt_cdbp, cmdlen);
499cab28b2dStaylor 		in_pktp->pkt_cdbp = (opaque_t)((char *)in_pktp +
500cab28b2dStaylor 		    tranp->tran_hba_len +
501*66027529SNikko He 		    sizeof (struct scsi_pkt_cache_wrapper));
502cab28b2dStaylor 		in_pktp->pkt_cdblen = 0;
503cab28b2dStaylor 	}
5048faf39b2Staylor 	pktw->pcw_flags &=
5058faf39b2Staylor 	    ~(PCW_NEED_EXT_CDB|PCW_NEED_EXT_TGT|PCW_NEED_EXT_SCB);
506cab28b2dStaylor fail2:
507cab28b2dStaylor 	kmem_cache_free(tranp->tran_pkt_cache_ptr, pktw);
508cab28b2dStaylor fail1:
509cab28b2dStaylor 	if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
510cab28b2dStaylor 		ddi_set_callback(callback, callback_arg,
511c6c44d06Sjw 		    &scsi_callback_id);
512cab28b2dStaylor 	}
513cab28b2dStaylor 
514cab28b2dStaylor 	return (NULL);
515cab28b2dStaylor }
516cab28b2dStaylor 
517cab28b2dStaylor void
518cab28b2dStaylor scsi_free_cache_pkt(struct scsi_address *ap, struct scsi_pkt *pktp)
519cab28b2dStaylor {
520cab28b2dStaylor 	struct scsi_pkt_cache_wrapper *pktw;
521cab28b2dStaylor 
522cab28b2dStaylor 	(*A_TO_TRAN(ap)->tran_teardown_pkt)(pktp);
523cab28b2dStaylor 	pktw = (struct scsi_pkt_cache_wrapper *)pktp;
5248faf39b2Staylor 	if (pktw->pcw_flags & PCW_BOUND)
5258faf39b2Staylor 		scsi_dmafree_attr(pktp);
526cab28b2dStaylor 
527cab28b2dStaylor 	/*
528cab28b2dStaylor 	 * if we allocated memory for anything that wouldn't fit, free
529cab28b2dStaylor 	 * the memory and restore the pointers
530cab28b2dStaylor 	 */
5318faf39b2Staylor 	if (pktw->pcw_flags & PCW_NEED_EXT_SCB) {
532cab28b2dStaylor 		kmem_free(pktp->pkt_scbp, pktp->pkt_scblen);
533cab28b2dStaylor 		pktp->pkt_scbp = (opaque_t)((char *)pktp +
534cab28b2dStaylor 		    (A_TO_TRAN(ap))->tran_hba_len +
535cab28b2dStaylor 		    DEFAULT_PRIVLEN + sizeof (struct scsi_pkt_cache_wrapper));
536cab28b2dStaylor 		if ((A_TO_TRAN(ap))->tran_hba_flags & SCSI_HBA_TRAN_CDB)
537cab28b2dStaylor 			pktp->pkt_scbp = (opaque_t)((pktp->pkt_scbp) +
538c6c44d06Sjw 			    DEFAULT_CDBLEN);
539cab28b2dStaylor 		pktp->pkt_scblen = 0;
540cab28b2dStaylor 	}
5418faf39b2Staylor 	if (pktw->pcw_flags & PCW_NEED_EXT_TGT) {
542cab28b2dStaylor 		kmem_free(pktp->pkt_private, pktp->pkt_tgtlen);
543cab28b2dStaylor 		pktp->pkt_tgtlen = 0;
544cab28b2dStaylor 		pktp->pkt_private = NULL;
545cab28b2dStaylor 	}
5468faf39b2Staylor 	if (pktw->pcw_flags & PCW_NEED_EXT_CDB) {
547cab28b2dStaylor 		kmem_free(pktp->pkt_cdbp, pktp->pkt_cdblen);
548cab28b2dStaylor 		pktp->pkt_cdbp = (opaque_t)((char *)pktp +
549cab28b2dStaylor 		    (A_TO_TRAN(ap))->tran_hba_len +
550cab28b2dStaylor 		    sizeof (struct scsi_pkt_cache_wrapper));
551cab28b2dStaylor 		pktp->pkt_cdblen = 0;
552cab28b2dStaylor 	}
5538faf39b2Staylor 	pktw->pcw_flags &=
5548faf39b2Staylor 	    ~(PCW_NEED_EXT_CDB|PCW_NEED_EXT_TGT|PCW_NEED_EXT_SCB);
555cab28b2dStaylor 	kmem_cache_free(A_TO_TRAN(ap)->tran_pkt_cache_ptr, pktw);
556cab28b2dStaylor 
557cab28b2dStaylor 	if (scsi_callback_id != 0) {
558cab28b2dStaylor 		ddi_run_callback(&scsi_callback_id);
559cab28b2dStaylor 	}
560cab28b2dStaylor 
561cab28b2dStaylor }
562cab28b2dStaylor 
5638faf39b2Staylor 
5647c478bd9Sstevel@tonic-gate struct scsi_pkt *
5657c478bd9Sstevel@tonic-gate scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *in_pktp,
5667c478bd9Sstevel@tonic-gate     struct buf *bp, int cmdlen, int statuslen, int pplen,
5677c478bd9Sstevel@tonic-gate     int flags, int (*callback)(caddr_t), caddr_t callback_arg)
5687c478bd9Sstevel@tonic-gate {
5697c478bd9Sstevel@tonic-gate 	struct scsi_pkt *pktp;
5707c478bd9Sstevel@tonic-gate 	scsi_hba_tran_t *tranp = ap->a_hba_tran;
5717c478bd9Sstevel@tonic-gate 	int		(*func)(caddr_t);
5727c478bd9Sstevel@tonic-gate 
5737c478bd9Sstevel@tonic-gate 	TRACE_5(TR_FAC_SCSI_RES, TR_SCSI_INIT_PKT_START,
5747c478bd9Sstevel@tonic-gate "scsi_init_pkt_start: addr %p in_pktp %p cmdlen %d statuslen %d pplen %d",
5757c478bd9Sstevel@tonic-gate 	    ap, in_pktp, cmdlen, statuslen, pplen);
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate #if defined(__i386) || defined(__amd64)
5787c478bd9Sstevel@tonic-gate 	if (flags & PKT_CONSISTENT_OLD) {
5797c478bd9Sstevel@tonic-gate 		flags &= ~PKT_CONSISTENT_OLD;
5807c478bd9Sstevel@tonic-gate 		flags |= PKT_CONSISTENT;
5817c478bd9Sstevel@tonic-gate 	}
5827c478bd9Sstevel@tonic-gate #endif
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 	func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate 	pktp = (*tranp->tran_init_pkt) (ap, in_pktp, bp, cmdlen,
587c6c44d06Sjw 	    statuslen, pplen, flags, func, NULL);
5887c478bd9Sstevel@tonic-gate 	if (pktp == NULL) {
5897c478bd9Sstevel@tonic-gate 		if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
5907c478bd9Sstevel@tonic-gate 			ddi_set_callback(callback, callback_arg,
591c6c44d06Sjw 			    &scsi_callback_id);
5927c478bd9Sstevel@tonic-gate 		}
5937c478bd9Sstevel@tonic-gate 	}
5947c478bd9Sstevel@tonic-gate 
5957c478bd9Sstevel@tonic-gate 	TRACE_1(TR_FAC_SCSI_RES, TR_SCSI_INIT_PKT_END,
596c6c44d06Sjw 	    "scsi_init_pkt_end: pktp %p", pktp);
5977c478bd9Sstevel@tonic-gate 	return (pktp);
5987c478bd9Sstevel@tonic-gate }
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate void
6017c478bd9Sstevel@tonic-gate scsi_destroy_pkt(struct scsi_pkt *pkt)
6027c478bd9Sstevel@tonic-gate {
6037c478bd9Sstevel@tonic-gate 	struct scsi_address	*ap = P_TO_ADDR(pkt);
6047c478bd9Sstevel@tonic-gate 
6057c478bd9Sstevel@tonic-gate 	TRACE_1(TR_FAC_SCSI_RES, TR_SCSI_DESTROY_PKT_START,
606c6c44d06Sjw 	    "scsi_destroy_pkt_start: pkt %p", pkt);
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 	(*A_TO_TRAN(ap)->tran_destroy_pkt)(ap, pkt);
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 	if (scsi_callback_id != 0) {
6117c478bd9Sstevel@tonic-gate 		ddi_run_callback(&scsi_callback_id);
6127c478bd9Sstevel@tonic-gate 	}
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate 	TRACE_0(TR_FAC_SCSI_RES, TR_SCSI_DESTROY_PKT_END,
615c6c44d06Sjw 	    "scsi_destroy_pkt_end");
6167c478bd9Sstevel@tonic-gate }
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate /*
6207c478bd9Sstevel@tonic-gate  *	Generic Resource Allocation Routines
6217c478bd9Sstevel@tonic-gate  */
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate struct scsi_pkt *
6247c478bd9Sstevel@tonic-gate scsi_resalloc(struct scsi_address *ap, int cmdlen, int statuslen,
6257c478bd9Sstevel@tonic-gate     opaque_t dmatoken, int (*callback)())
6267c478bd9Sstevel@tonic-gate {
6277c478bd9Sstevel@tonic-gate 	register struct	scsi_pkt *pkt;
6287c478bd9Sstevel@tonic-gate 	register scsi_hba_tran_t *tranp = ap->a_hba_tran;
6297c478bd9Sstevel@tonic-gate 	register int			(*func)(caddr_t);
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate 	func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate 	pkt = (*tranp->tran_init_pkt) (ap, NULL, (struct buf *)dmatoken,
634c6c44d06Sjw 	    cmdlen, statuslen, 0, 0, func, NULL);
6357c478bd9Sstevel@tonic-gate 	if (pkt == NULL) {
6367c478bd9Sstevel@tonic-gate 		if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
6377c478bd9Sstevel@tonic-gate 			ddi_set_callback(callback, NULL, &scsi_callback_id);
6387c478bd9Sstevel@tonic-gate 		}
6397c478bd9Sstevel@tonic-gate 	}
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate 	return (pkt);
6427c478bd9Sstevel@tonic-gate }
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate struct scsi_pkt *
6457c478bd9Sstevel@tonic-gate scsi_pktalloc(struct scsi_address *ap, int cmdlen, int statuslen,
6467c478bd9Sstevel@tonic-gate     int (*callback)())
6477c478bd9Sstevel@tonic-gate {
6487c478bd9Sstevel@tonic-gate 	struct scsi_pkt		*pkt;
6497c478bd9Sstevel@tonic-gate 	struct scsi_hba_tran	*tran = ap->a_hba_tran;
6507c478bd9Sstevel@tonic-gate 	register int			(*func)(caddr_t);
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate 	func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate 	pkt = (*tran->tran_init_pkt) (ap, NULL, NULL, cmdlen,
655c6c44d06Sjw 	    statuslen, 0, 0, func, NULL);
6567c478bd9Sstevel@tonic-gate 	if (pkt == NULL) {
6577c478bd9Sstevel@tonic-gate 		if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
6587c478bd9Sstevel@tonic-gate 			ddi_set_callback(callback, NULL, &scsi_callback_id);
6597c478bd9Sstevel@tonic-gate 		}
6607c478bd9Sstevel@tonic-gate 	}
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate 	return (pkt);
6637c478bd9Sstevel@tonic-gate }
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate struct scsi_pkt *
6667c478bd9Sstevel@tonic-gate scsi_dmaget(struct scsi_pkt *pkt, opaque_t dmatoken, int (*callback)())
6677c478bd9Sstevel@tonic-gate {
6687c478bd9Sstevel@tonic-gate 	struct scsi_pkt		*new_pkt;
6697c478bd9Sstevel@tonic-gate 	register int		(*func)(caddr_t);
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate 	func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate 	new_pkt = (*P_TO_TRAN(pkt)->tran_init_pkt) (&pkt->pkt_address,
674c6c44d06Sjw 	    pkt, (struct buf *)dmatoken,
675c6c44d06Sjw 	    0, 0, 0, 0, func, NULL);
6767c478bd9Sstevel@tonic-gate 	ASSERT(new_pkt == pkt || new_pkt == NULL);
6777c478bd9Sstevel@tonic-gate 	if (new_pkt == NULL) {
6787c478bd9Sstevel@tonic-gate 		if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
6797c478bd9Sstevel@tonic-gate 			ddi_set_callback(callback, NULL, &scsi_callback_id);
6807c478bd9Sstevel@tonic-gate 		}
6817c478bd9Sstevel@tonic-gate 	}
6827c478bd9Sstevel@tonic-gate 
6837c478bd9Sstevel@tonic-gate 	return (new_pkt);
6847c478bd9Sstevel@tonic-gate }
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate 
6877c478bd9Sstevel@tonic-gate /*
6887c478bd9Sstevel@tonic-gate  *	Generic Resource Deallocation Routines
6897c478bd9Sstevel@tonic-gate  */
6907c478bd9Sstevel@tonic-gate 
6917c478bd9Sstevel@tonic-gate void
6927c478bd9Sstevel@tonic-gate scsi_dmafree(struct scsi_pkt *pkt)
6937c478bd9Sstevel@tonic-gate {
6947c478bd9Sstevel@tonic-gate 	register struct scsi_address	*ap = P_TO_ADDR(pkt);
6958faf39b2Staylor 
6967c478bd9Sstevel@tonic-gate 	(*A_TO_TRAN(ap)->tran_dmafree)(ap, pkt);
6977c478bd9Sstevel@tonic-gate 
6987c478bd9Sstevel@tonic-gate 	if (scsi_callback_id != 0) {
6997c478bd9Sstevel@tonic-gate 		ddi_run_callback(&scsi_callback_id);
7007c478bd9Sstevel@tonic-gate 	}
7017c478bd9Sstevel@tonic-gate }
7027c478bd9Sstevel@tonic-gate 
7038faf39b2Staylor /*ARGSUSED*/
7048faf39b2Staylor void
7058faf39b2Staylor scsi_cache_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
7068faf39b2Staylor {
707a231f2c8SNikko He 	ASSERT(pkt->pkt_numcookies == 0 ||
708a231f2c8SNikko He 	    ((struct scsi_pkt_cache_wrapper *)pkt)->pcw_flags & PCW_BOUND);
7098faf39b2Staylor 	ASSERT(pkt->pkt_handle != NULL);
7108faf39b2Staylor 	scsi_dmafree_attr(pkt);
7118faf39b2Staylor 
7128faf39b2Staylor 	if (scsi_callback_id != 0) {
7138faf39b2Staylor 		ddi_run_callback(&scsi_callback_id);
7148faf39b2Staylor 	}
7158faf39b2Staylor }
7168faf39b2Staylor 
7177c478bd9Sstevel@tonic-gate void
7187c478bd9Sstevel@tonic-gate scsi_sync_pkt(struct scsi_pkt *pkt)
7197c478bd9Sstevel@tonic-gate {
7207c478bd9Sstevel@tonic-gate 	register struct scsi_address	*ap = P_TO_ADDR(pkt);
721c6c44d06Sjw 
722c6c44d06Sjw 	if (pkt->pkt_state & STATE_XFERRED_DATA)
723c6c44d06Sjw 		(*A_TO_TRAN(ap)->tran_sync_pkt)(ap, pkt);
7247c478bd9Sstevel@tonic-gate }
7257c478bd9Sstevel@tonic-gate 
7268faf39b2Staylor /*ARGSUSED*/
7278faf39b2Staylor void
7288faf39b2Staylor scsi_sync_cache_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
7298faf39b2Staylor {
730afcdc791Scth 	if (pkt->pkt_handle &&
731afcdc791Scth 	    (pkt->pkt_dma_flags & (DDI_DMA_WRITE | DDI_DMA_READ))) {
7328faf39b2Staylor 		(void) ddi_dma_sync(pkt->pkt_handle,
733afcdc791Scth 		    pkt->pkt_dma_offset, pkt->pkt_dma_len,
734afcdc791Scth 		    (pkt->pkt_dma_flags & DDI_DMA_WRITE) ?
735afcdc791Scth 		    DDI_DMA_SYNC_FORDEV : DDI_DMA_SYNC_FORCPU);
7368faf39b2Staylor 	}
7378faf39b2Staylor }
7388faf39b2Staylor 
7397c478bd9Sstevel@tonic-gate void
7407c478bd9Sstevel@tonic-gate scsi_resfree(struct scsi_pkt *pkt)
7417c478bd9Sstevel@tonic-gate {
7427c478bd9Sstevel@tonic-gate 	register struct scsi_address	*ap = P_TO_ADDR(pkt);
7437c478bd9Sstevel@tonic-gate 	(*A_TO_TRAN(ap)->tran_destroy_pkt)(ap, pkt);
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate 	if (scsi_callback_id != 0) {
7467c478bd9Sstevel@tonic-gate 		ddi_run_callback(&scsi_callback_id);
7477c478bd9Sstevel@tonic-gate 	}
7487c478bd9Sstevel@tonic-gate }
749