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 /*
23830363f4Staylor  * 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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #include <sys/scsi/scsi.h>
307c478bd9Sstevel@tonic-gate #include <sys/vtrace.h>
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #define	A_TO_TRAN(ap)	((ap)->a_hba_tran)
347c478bd9Sstevel@tonic-gate #define	P_TO_TRAN(pkt)	((pkt)->pkt_address.a_hba_tran)
357c478bd9Sstevel@tonic-gate #define	P_TO_ADDR(pkt)	(&((pkt)->pkt_address))
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate /*
387c478bd9Sstevel@tonic-gate  * Callback id
397c478bd9Sstevel@tonic-gate  */
407c478bd9Sstevel@tonic-gate uintptr_t scsi_callback_id = 0;
417c478bd9Sstevel@tonic-gate 
424ab75253Smrj extern ddi_dma_attr_t scsi_alloc_attr;
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate struct buf *
457c478bd9Sstevel@tonic-gate scsi_alloc_consistent_buf(struct scsi_address *ap,
467c478bd9Sstevel@tonic-gate     struct buf *in_bp, size_t datalen, uint_t bflags,
477c478bd9Sstevel@tonic-gate     int (*callback)(caddr_t), caddr_t callback_arg)
487c478bd9Sstevel@tonic-gate {
497c478bd9Sstevel@tonic-gate 	dev_info_t	*pdip;
507c478bd9Sstevel@tonic-gate 	struct		buf *bp;
517c478bd9Sstevel@tonic-gate 	int		kmflag;
524ab75253Smrj 	size_t		rlen;
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate 	TRACE_0(TR_FAC_SCSI_RES, TR_SCSI_ALLOC_CONSISTENT_BUF_START,
557c478bd9Sstevel@tonic-gate 		"scsi_alloc_consistent_buf_start");
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate 	if (!in_bp) {
587c478bd9Sstevel@tonic-gate 		kmflag = (callback == SLEEP_FUNC) ? KM_SLEEP : KM_NOSLEEP;
597c478bd9Sstevel@tonic-gate 		if ((bp = getrbuf(kmflag)) == NULL) {
607c478bd9Sstevel@tonic-gate 			goto no_resource;
617c478bd9Sstevel@tonic-gate 		}
627c478bd9Sstevel@tonic-gate 	} else {
637c478bd9Sstevel@tonic-gate 		bp = in_bp;
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate 		/* we are establishing a new buffer memory association */
667c478bd9Sstevel@tonic-gate 		bp->b_flags &= ~(B_PAGEIO | B_PHYS | B_REMAPPED | B_SHADOW);
677c478bd9Sstevel@tonic-gate 		bp->b_proc = NULL;
687c478bd9Sstevel@tonic-gate 		bp->b_pages = NULL;
697c478bd9Sstevel@tonic-gate 		bp->b_shadow = NULL;
707c478bd9Sstevel@tonic-gate 	}
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate 	/* limit bits that can be set by bflags argument */
737c478bd9Sstevel@tonic-gate 	ASSERT(!(bflags & ~(B_READ | B_WRITE)));
747c478bd9Sstevel@tonic-gate 	bflags &= (B_READ | B_WRITE);
757c478bd9Sstevel@tonic-gate 	bp->b_un.b_addr = 0;
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 	if (datalen) {
787c478bd9Sstevel@tonic-gate 		pdip = (A_TO_TRAN(ap))->tran_hba_dip;
797c478bd9Sstevel@tonic-gate 
804ab75253Smrj 		/*
814ab75253Smrj 		 * use i_ddi_mem_alloc() for now until we have an interface to
824ab75253Smrj 		 * allocate memory for DMA which doesn't require a DMA handle.
834ab75253Smrj 		 * ddi_iopb_alloc() is obsolete and we want more flexibility in
844ab75253Smrj 		 * controlling the DMA address constraints.
854ab75253Smrj 		 */
864ab75253Smrj 		while (i_ddi_mem_alloc(pdip, &scsi_alloc_attr, datalen,
874ab75253Smrj 		    ((callback == SLEEP_FUNC) ? 1 : 0), 0, NULL,
884ab75253Smrj 		    &bp->b_un.b_addr, &rlen, NULL) != DDI_SUCCESS) {
897c478bd9Sstevel@tonic-gate 			if (callback == SLEEP_FUNC) {
907c478bd9Sstevel@tonic-gate 				delay(drv_usectohz(10000));
917c478bd9Sstevel@tonic-gate 			} else {
927c478bd9Sstevel@tonic-gate 				if (!in_bp)
937c478bd9Sstevel@tonic-gate 					freerbuf(bp);
947c478bd9Sstevel@tonic-gate 				goto no_resource;
957c478bd9Sstevel@tonic-gate 			}
967c478bd9Sstevel@tonic-gate 		}
977c478bd9Sstevel@tonic-gate 		bp->b_flags |= bflags;
987c478bd9Sstevel@tonic-gate 	}
997c478bd9Sstevel@tonic-gate 	bp->b_bcount = datalen;
1007c478bd9Sstevel@tonic-gate 	bp->b_resid = 0;
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 	TRACE_0(TR_FAC_SCSI_RES, TR_SCSI_ALLOC_CONSISTENT_BUF_END,
1037c478bd9Sstevel@tonic-gate 		"scsi_alloc_consistent_buf_end");
1047c478bd9Sstevel@tonic-gate 	return (bp);
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate no_resource:
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
1097c478bd9Sstevel@tonic-gate 		ddi_set_callback(callback, callback_arg,
1107c478bd9Sstevel@tonic-gate 			&scsi_callback_id);
1117c478bd9Sstevel@tonic-gate 	}
1127c478bd9Sstevel@tonic-gate 	TRACE_0(TR_FAC_SCSI_RES,
1137c478bd9Sstevel@tonic-gate 	    TR_SCSI_ALLOC_CONSISTENT_BUF_RETURN1_END,
1147c478bd9Sstevel@tonic-gate 	    "scsi_alloc_consistent_buf_end (return1)");
1157c478bd9Sstevel@tonic-gate 	return (NULL);
1167c478bd9Sstevel@tonic-gate }
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate void
1197c478bd9Sstevel@tonic-gate scsi_free_consistent_buf(struct buf *bp)
1207c478bd9Sstevel@tonic-gate {
1217c478bd9Sstevel@tonic-gate 	TRACE_0(TR_FAC_SCSI_RES, TR_SCSI_FREE_CONSISTENT_BUF_START,
1227c478bd9Sstevel@tonic-gate 		"scsi_free_consistent_buf_start");
1237c478bd9Sstevel@tonic-gate 	if (!bp)
1247c478bd9Sstevel@tonic-gate 		return;
1257c478bd9Sstevel@tonic-gate 	if (bp->b_un.b_addr)
1267b93957cSeota 		i_ddi_mem_free((caddr_t)bp->b_un.b_addr, NULL);
1277c478bd9Sstevel@tonic-gate 	freerbuf(bp);
1287c478bd9Sstevel@tonic-gate 	if (scsi_callback_id != 0) {
1297c478bd9Sstevel@tonic-gate 		ddi_run_callback(&scsi_callback_id);
1307c478bd9Sstevel@tonic-gate 	}
1317c478bd9Sstevel@tonic-gate 	TRACE_0(TR_FAC_SCSI_RES, TR_SCSI_FREE_CONSISTENT_BUF_END,
1327c478bd9Sstevel@tonic-gate 		"scsi_free_consistent_buf_end");
1337c478bd9Sstevel@tonic-gate }
1347c478bd9Sstevel@tonic-gate 
135*8faf39b2Staylor void
136*8faf39b2Staylor scsi_dmafree_attr(struct scsi_pkt *pktp)
137*8faf39b2Staylor {
138*8faf39b2Staylor 	struct scsi_pkt_cache_wrapper *pktw =
139*8faf39b2Staylor 		(struct scsi_pkt_cache_wrapper *)pktp;
140*8faf39b2Staylor 
141*8faf39b2Staylor 	if (pktw->pcw_flags & PCW_BOUND) {
142*8faf39b2Staylor 		if (ddi_dma_unbind_handle(pktp->pkt_handle) !=
143*8faf39b2Staylor 		    DDI_SUCCESS)
144*8faf39b2Staylor 			cmn_err(CE_WARN, "scsi_dmafree_attr: "
145*8faf39b2Staylor 			    "unbind handle failed");
146*8faf39b2Staylor 		pktw->pcw_flags &= ~PCW_BOUND;
147*8faf39b2Staylor 	}
148*8faf39b2Staylor 	pktp->pkt_numcookies = 0;
149*8faf39b2Staylor }
150*8faf39b2Staylor 
151*8faf39b2Staylor struct buf *
152*8faf39b2Staylor scsi_pkt2bp(struct scsi_pkt *pkt)
153*8faf39b2Staylor {
154*8faf39b2Staylor 	return (((struct scsi_pkt_cache_wrapper *)pkt)->pcw_bp);
155*8faf39b2Staylor }
156*8faf39b2Staylor 
157*8faf39b2Staylor int
158*8faf39b2Staylor scsi_dma_buf_bind_attr(struct scsi_pkt_cache_wrapper *pktw,
159*8faf39b2Staylor 			struct buf	*bp,
160*8faf39b2Staylor 			int		 dma_flags,
161*8faf39b2Staylor 			int		(*callback)(),
162*8faf39b2Staylor 			caddr_t		 arg)
163*8faf39b2Staylor {
164*8faf39b2Staylor 	struct scsi_pkt *pktp = &(pktw->pcw_pkt);
165*8faf39b2Staylor 	int	 status;
166*8faf39b2Staylor 
167*8faf39b2Staylor 	/*
168*8faf39b2Staylor 	 * First time, need to establish the handle.
169*8faf39b2Staylor 	 */
170*8faf39b2Staylor 
171*8faf39b2Staylor 	ASSERT(pktp->pkt_numcookies == 0);
172*8faf39b2Staylor 	ASSERT(pktw->pcw_totalwin == 0);
173*8faf39b2Staylor 
174*8faf39b2Staylor 	status = ddi_dma_buf_bind_handle(pktp->pkt_handle, bp, dma_flags,
175*8faf39b2Staylor 		    callback, arg, &pktw->pcw_cookie,
176*8faf39b2Staylor 		    &pktp->pkt_numcookies);
177*8faf39b2Staylor 
178*8faf39b2Staylor 	switch (status) {
179*8faf39b2Staylor 	case DDI_DMA_MAPPED:
180*8faf39b2Staylor 		pktw->pcw_totalwin = 1;
181*8faf39b2Staylor 		break;
182*8faf39b2Staylor 
183*8faf39b2Staylor 	case DDI_DMA_PARTIAL_MAP:
184*8faf39b2Staylor 		/* enable first call to ddi_dma_getwin */
185*8faf39b2Staylor 		if (ddi_dma_numwin(pktp->pkt_handle,
186*8faf39b2Staylor 		    &pktw->pcw_totalwin) != DDI_SUCCESS) {
187*8faf39b2Staylor 			bp->b_error = 0;
188*8faf39b2Staylor 			return (0);
189*8faf39b2Staylor 		}
190*8faf39b2Staylor 		break;
191*8faf39b2Staylor 
192*8faf39b2Staylor 	case DDI_DMA_NORESOURCES:
193*8faf39b2Staylor 		bp->b_error = 0;
194*8faf39b2Staylor 		return (0);
195*8faf39b2Staylor 
196*8faf39b2Staylor 	case DDI_DMA_TOOBIG:
197*8faf39b2Staylor 		bioerror(bp, EINVAL);
198*8faf39b2Staylor 		return (0);
199*8faf39b2Staylor 
200*8faf39b2Staylor 	case DDI_DMA_NOMAPPING:
201*8faf39b2Staylor 	case DDI_DMA_INUSE:
202*8faf39b2Staylor 	default:
203*8faf39b2Staylor 		bioerror(bp, EFAULT);
204*8faf39b2Staylor 		return (0);
205*8faf39b2Staylor 	}
206*8faf39b2Staylor 
207*8faf39b2Staylor 	/* initialize the loop controls for scsi_dmaget_attr() */
208*8faf39b2Staylor 	pktw->pcw_curwin = 0;
209*8faf39b2Staylor 	pktw->pcw_total_xfer = 0;
210*8faf39b2Staylor 	pktp->pkt_dma_flags = dma_flags;
211*8faf39b2Staylor 	return (1);
212*8faf39b2Staylor }
213*8faf39b2Staylor 
214*8faf39b2Staylor #if defined(_DMA_USES_PHYSADDR)
215*8faf39b2Staylor int
216*8faf39b2Staylor scsi_dmaget_attr(struct scsi_pkt_cache_wrapper *pktw)
217*8faf39b2Staylor {
218*8faf39b2Staylor 	struct scsi_pkt *pktp = &(pktw->pcw_pkt);
219*8faf39b2Staylor 
220*8faf39b2Staylor 	int		status;
221*8faf39b2Staylor 	int		num_segs = 0;
222*8faf39b2Staylor 	ddi_dma_impl_t	*hp = (ddi_dma_impl_t *)pktp->pkt_handle;
223*8faf39b2Staylor 	ddi_dma_cookie_t *cp;
224*8faf39b2Staylor 
225*8faf39b2Staylor 	if (pktw->pcw_curwin != 0) {
226*8faf39b2Staylor 		ddi_dma_cookie_t	cookie;
227*8faf39b2Staylor 
228*8faf39b2Staylor 		/*
229*8faf39b2Staylor 		 * start the next window, and get its first cookie
230*8faf39b2Staylor 		 */
231*8faf39b2Staylor 		status = ddi_dma_getwin(pktp->pkt_handle,
232*8faf39b2Staylor 				pktw->pcw_curwin, &pktp->pkt_dma_offset,
233*8faf39b2Staylor 				&pktp->pkt_dma_len, &cookie,
234*8faf39b2Staylor 				&pktp->pkt_numcookies);
235*8faf39b2Staylor 		if (status != DDI_SUCCESS)
236*8faf39b2Staylor 			return (0);
237*8faf39b2Staylor 	}
238*8faf39b2Staylor 
239*8faf39b2Staylor 	/*
240*8faf39b2Staylor 	 * start the Scatter/Gather loop
241*8faf39b2Staylor 	 */
242*8faf39b2Staylor 	cp = hp->dmai_cookie - 1;
243*8faf39b2Staylor 	pktp->pkt_dma_len = 0;
244*8faf39b2Staylor 	for (;;) {
245*8faf39b2Staylor 
246*8faf39b2Staylor 		/* take care of the loop-bookkeeping */
247*8faf39b2Staylor 		pktp->pkt_dma_len += cp->dmac_size;
248*8faf39b2Staylor 		num_segs++;
249*8faf39b2Staylor 		/*
250*8faf39b2Staylor 		 * if this was the last cookie in the current window
251*8faf39b2Staylor 		 * set the loop controls start the next window and
252*8faf39b2Staylor 		 * exit so the HBA can do this partial transfer
253*8faf39b2Staylor 		 */
254*8faf39b2Staylor 		if (num_segs >= pktp->pkt_numcookies) {
255*8faf39b2Staylor 			pktw->pcw_curwin++;
256*8faf39b2Staylor 			break;
257*8faf39b2Staylor 		}
258*8faf39b2Staylor 
259*8faf39b2Staylor 		cp++;
260*8faf39b2Staylor 	}
261*8faf39b2Staylor 	pktw->pcw_total_xfer += pktp->pkt_dma_len;
262*8faf39b2Staylor 	pktp->pkt_cookies = hp->dmai_cookie - 1;
263*8faf39b2Staylor 	hp->dmai_cookie = cp;
264*8faf39b2Staylor 
265*8faf39b2Staylor 	return (1);
266*8faf39b2Staylor }
267*8faf39b2Staylor #endif
268*8faf39b2Staylor 
269cab28b2dStaylor void scsi_free_cache_pkt(struct scsi_address *, struct scsi_pkt *);
270cab28b2dStaylor 
271cab28b2dStaylor struct scsi_pkt *
272cab28b2dStaylor scsi_init_cache_pkt(struct scsi_address *ap, struct scsi_pkt *in_pktp,
273cab28b2dStaylor     struct buf *bp, int cmdlen, int statuslen, int pplen,
274cab28b2dStaylor     int flags, int (*callback)(caddr_t), caddr_t callback_arg)
275cab28b2dStaylor {
276cab28b2dStaylor 	struct scsi_pkt_cache_wrapper *pktw;
277cab28b2dStaylor 	scsi_hba_tran_t *tranp = ap->a_hba_tran;
278cab28b2dStaylor 	int		(*func)(caddr_t);
279cab28b2dStaylor 
280cab28b2dStaylor 	func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
281cab28b2dStaylor 
282cab28b2dStaylor 	if (in_pktp == NULL) {
283cab28b2dStaylor 		int kf;
284cab28b2dStaylor 
285cab28b2dStaylor 		if (callback == SLEEP_FUNC)
286cab28b2dStaylor 			kf = KM_SLEEP;
287cab28b2dStaylor 		else
288cab28b2dStaylor 			kf = KM_NOSLEEP;
289cab28b2dStaylor 		pktw = kmem_cache_alloc(tranp->tran_pkt_cache_ptr,
290cab28b2dStaylor 			    kf);
291cab28b2dStaylor 		if (pktw == NULL)
292cab28b2dStaylor 			goto fail1;
293cab28b2dStaylor 
294*8faf39b2Staylor 		pktw->pcw_flags = 0;
295cab28b2dStaylor 		in_pktp = &(pktw->pcw_pkt);
296*8faf39b2Staylor 		in_pktp->pkt_address = *ap;
297cab28b2dStaylor 		/*
298830363f4Staylor 		 * target drivers should initialize pkt_comp and
299830363f4Staylor 		 * pkt_time, but sometimes they don't so initialize
300830363f4Staylor 		 * them here to be safe.
301cab28b2dStaylor 		 */
302cab28b2dStaylor 		in_pktp->pkt_address = *ap;
303830363f4Staylor 		in_pktp->pkt_flags = 0;
304830363f4Staylor 		in_pktp->pkt_time = 0;
305cab28b2dStaylor 		in_pktp->pkt_resid = 0;
306cab28b2dStaylor 		in_pktp->pkt_state = 0;
307cab28b2dStaylor 		in_pktp->pkt_statistics = 0;
308cab28b2dStaylor 		in_pktp->pkt_reason = 0;
309*8faf39b2Staylor 		in_pktp->pkt_dma_offset = 0;
310*8faf39b2Staylor 		in_pktp->pkt_dma_len = 0;
311*8faf39b2Staylor 		in_pktp->pkt_dma_flags = 0;
312*8faf39b2Staylor 		ASSERT(in_pktp->pkt_numcookies == 0);
313*8faf39b2Staylor 		pktw->pcw_curwin = 0;
314*8faf39b2Staylor 		pktw->pcw_totalwin = 0;
315*8faf39b2Staylor 		pktw->pcw_total_xfer = 0;
316cab28b2dStaylor 
317cab28b2dStaylor 		in_pktp->pkt_cdblen = cmdlen;
318cab28b2dStaylor 		if ((tranp->tran_hba_flags & SCSI_HBA_TRAN_CDB) &&
319cab28b2dStaylor 		    (cmdlen > DEFAULT_CDBLEN)) {
320*8faf39b2Staylor 			pktw->pcw_flags |= PCW_NEED_EXT_CDB;
321830363f4Staylor 			in_pktp->pkt_cdbp = kmem_alloc(cmdlen, kf);
322cab28b2dStaylor 			if (in_pktp->pkt_cdbp == NULL)
323cab28b2dStaylor 				goto fail2;
324cab28b2dStaylor 		}
325cab28b2dStaylor 		in_pktp->pkt_tgtlen = pplen;
326cab28b2dStaylor 		if (pplen > DEFAULT_PRIVLEN) {
327*8faf39b2Staylor 			pktw->pcw_flags |= PCW_NEED_EXT_TGT;
328830363f4Staylor 			in_pktp->pkt_private = kmem_alloc(pplen, kf);
329cab28b2dStaylor 			if (in_pktp->pkt_private == NULL)
330cab28b2dStaylor 				goto fail3;
331cab28b2dStaylor 		}
332cab28b2dStaylor 		in_pktp->pkt_scblen = statuslen;
333cab28b2dStaylor 		if ((tranp->tran_hba_flags & SCSI_HBA_TRAN_SCB) &&
334cab28b2dStaylor 		    (statuslen > DEFAULT_SCBLEN)) {
335*8faf39b2Staylor 			pktw->pcw_flags |= PCW_NEED_EXT_SCB;
336830363f4Staylor 			in_pktp->pkt_scbp = kmem_alloc(statuslen, kf);
337cab28b2dStaylor 			if (in_pktp->pkt_scbp == NULL)
338cab28b2dStaylor 				goto fail4;
339cab28b2dStaylor 		}
340cab28b2dStaylor 		if ((*tranp->tran_setup_pkt) (in_pktp,
341cab28b2dStaylor 			func, NULL) == -1) {
342cab28b2dStaylor 				goto fail5;
343cab28b2dStaylor 		}
344830363f4Staylor 		if (cmdlen)
345830363f4Staylor 			bzero((void *)in_pktp->pkt_cdbp, cmdlen);
346830363f4Staylor 		if (pplen)
347830363f4Staylor 			bzero((void *)in_pktp->pkt_private, pplen);
348830363f4Staylor 		if (statuslen)
349830363f4Staylor 			bzero((void *)in_pktp->pkt_scbp, statuslen);
350*8faf39b2Staylor 	} else
351*8faf39b2Staylor 		pktw = (struct scsi_pkt_cache_wrapper *)in_pktp;
352*8faf39b2Staylor 
353cab28b2dStaylor 	if (bp && bp->b_bcount) {
354*8faf39b2Staylor 
355*8faf39b2Staylor 		int dma_flags = 0;
356*8faf39b2Staylor 
357*8faf39b2Staylor 		/*
358*8faf39b2Staylor 		 * we need to transfer data, so we alloc dma resources
359*8faf39b2Staylor 		 * for this packet
360*8faf39b2Staylor 		 */
361*8faf39b2Staylor 		/*CONSTCOND*/
362*8faf39b2Staylor 		ASSERT(SLEEP_FUNC == DDI_DMA_SLEEP);
363*8faf39b2Staylor 		/*CONSTCOND*/
364*8faf39b2Staylor 		ASSERT(NULL_FUNC == DDI_DMA_DONTWAIT);
365*8faf39b2Staylor 
366*8faf39b2Staylor #if defined(_DMA_USES_PHYSADDR)
367*8faf39b2Staylor 		/*
368*8faf39b2Staylor 		 * with an IOMMU we map everything, so we don't
369*8faf39b2Staylor 		 * need to bother with this
370*8faf39b2Staylor 		 */
371*8faf39b2Staylor 		if (tranp->tran_dma_attr.dma_attr_granular !=
372*8faf39b2Staylor 			pktw->pcw_granular) {
373*8faf39b2Staylor 
374*8faf39b2Staylor 			ddi_dma_free_handle(&in_pktp->pkt_handle);
375*8faf39b2Staylor 			if (ddi_dma_alloc_handle(tranp->tran_hba_dip,
376*8faf39b2Staylor 				&tranp->tran_dma_attr,
377*8faf39b2Staylor 				func, NULL,
378*8faf39b2Staylor 				&in_pktp->pkt_handle) != DDI_SUCCESS) {
379*8faf39b2Staylor 
380*8faf39b2Staylor 				in_pktp->pkt_handle = NULL;
381*8faf39b2Staylor 				return (NULL);
382*8faf39b2Staylor 			}
383*8faf39b2Staylor 			pktw->pcw_granular =
384*8faf39b2Staylor 				tranp->tran_dma_attr.dma_attr_granular;
385cab28b2dStaylor 		}
386*8faf39b2Staylor #endif
387*8faf39b2Staylor 
388*8faf39b2Staylor 		if (in_pktp->pkt_numcookies == 0) {
389*8faf39b2Staylor 			pktw->pcw_bp = bp;
390*8faf39b2Staylor 			/*
391*8faf39b2Staylor 			 * set dma flags; the "read" case must be first
392*8faf39b2Staylor 			 * since B_WRITE isn't always be set for writes.
393*8faf39b2Staylor 			 */
394*8faf39b2Staylor 			if (bp->b_flags & B_READ) {
395*8faf39b2Staylor 				dma_flags |= DDI_DMA_READ;
396*8faf39b2Staylor 			} else {
397*8faf39b2Staylor 				dma_flags |= DDI_DMA_WRITE;
398*8faf39b2Staylor 			}
399*8faf39b2Staylor 			if (flags & PKT_CONSISTENT)
400*8faf39b2Staylor 				dma_flags |= DDI_DMA_CONSISTENT;
401*8faf39b2Staylor 			if (flags & PKT_DMA_PARTIAL)
402*8faf39b2Staylor 				dma_flags |= DDI_DMA_PARTIAL;
403*8faf39b2Staylor 
404*8faf39b2Staylor #if defined(__sparc)
405*8faf39b2Staylor 			/*
406*8faf39b2Staylor 			 * workaround for byte hole issue on psycho and
407*8faf39b2Staylor 			 * schizo pre 2.1
408*8faf39b2Staylor 			 */
409*8faf39b2Staylor 			if ((bp->b_flags & B_READ) && ((bp->b_flags &
410*8faf39b2Staylor 			    (B_PAGEIO|B_REMAPPED)) != B_PAGEIO) &&
411*8faf39b2Staylor 			    (((uintptr_t)bp->b_un.b_addr & 0x7) ||
412*8faf39b2Staylor 			    ((uintptr_t)bp->b_bcount & 0x7))) {
413*8faf39b2Staylor 				dma_flags |= DDI_DMA_CONSISTENT;
414*8faf39b2Staylor 			}
415*8faf39b2Staylor #endif
416*8faf39b2Staylor 			if (!scsi_dma_buf_bind_attr(pktw, bp,
417*8faf39b2Staylor 			    dma_flags, callback, callback_arg)) {
418*8faf39b2Staylor 				return (NULL);
419*8faf39b2Staylor 			} else {
420*8faf39b2Staylor 				pktw->pcw_flags |= PCW_BOUND;
421*8faf39b2Staylor 			}
422*8faf39b2Staylor 		}
423*8faf39b2Staylor 
424*8faf39b2Staylor #if defined(_DMA_USES_PHYSADDR)
425*8faf39b2Staylor 		if (!scsi_dmaget_attr(pktw)) {
426*8faf39b2Staylor 			scsi_dmafree_attr(in_pktp);
427*8faf39b2Staylor 			goto fail5;
428*8faf39b2Staylor 		}
429*8faf39b2Staylor #else
430*8faf39b2Staylor 		in_pktp->pkt_cookies = &pktw->pcw_cookie;
431*8faf39b2Staylor 		in_pktp->pkt_dma_len = pktw->pcw_cookie.dmac_size;
432*8faf39b2Staylor 		pktw->pcw_total_xfer += in_pktp->pkt_dma_len;
433*8faf39b2Staylor #endif
434*8faf39b2Staylor 		ASSERT(in_pktp->pkt_numcookies <=
435*8faf39b2Staylor 			tranp->tran_dma_attr.dma_attr_sgllen);
436*8faf39b2Staylor 		ASSERT(pktw->pcw_total_xfer <= bp->b_bcount);
437*8faf39b2Staylor 		in_pktp->pkt_resid = bp->b_bcount -
438*8faf39b2Staylor 			pktw->pcw_total_xfer;
439*8faf39b2Staylor 
440*8faf39b2Staylor 		ASSERT((in_pktp->pkt_resid % pktw->pcw_granular) ==
441*8faf39b2Staylor 			0);
442*8faf39b2Staylor 	} else {
443*8faf39b2Staylor 		/* !bp or no b_bcount */
444*8faf39b2Staylor 		in_pktp->pkt_resid = 0;
445cab28b2dStaylor 	}
446cab28b2dStaylor 	return (in_pktp);
447cab28b2dStaylor 
448cab28b2dStaylor fail5:
449*8faf39b2Staylor 	if (pktw->pcw_flags & PCW_NEED_EXT_SCB) {
450cab28b2dStaylor 		kmem_free(in_pktp->pkt_scbp, statuslen);
451cab28b2dStaylor 		in_pktp->pkt_scbp = (opaque_t)((char *)in_pktp +
452cab28b2dStaylor 		    tranp->tran_hba_len + DEFAULT_PRIVLEN +
453cab28b2dStaylor 		    sizeof (struct scsi_pkt));
454cab28b2dStaylor 		if ((A_TO_TRAN(ap))->tran_hba_flags & SCSI_HBA_TRAN_CDB)
455cab28b2dStaylor 			in_pktp->pkt_scbp = (opaque_t)((in_pktp->pkt_scbp) +
456cab28b2dStaylor 				DEFAULT_CDBLEN);
457cab28b2dStaylor 		in_pktp->pkt_scblen = 0;
458cab28b2dStaylor 	}
459cab28b2dStaylor fail4:
460*8faf39b2Staylor 	if (pktw->pcw_flags & PCW_NEED_EXT_TGT) {
461cab28b2dStaylor 		kmem_free(in_pktp->pkt_private, pplen);
462cab28b2dStaylor 		in_pktp->pkt_tgtlen = 0;
463cab28b2dStaylor 		in_pktp->pkt_private = NULL;
464cab28b2dStaylor 	}
465cab28b2dStaylor fail3:
466*8faf39b2Staylor 	if (pktw->pcw_flags & PCW_NEED_EXT_CDB) {
467cab28b2dStaylor 		kmem_free(in_pktp->pkt_cdbp, cmdlen);
468cab28b2dStaylor 		in_pktp->pkt_cdbp = (opaque_t)((char *)in_pktp +
469cab28b2dStaylor 		    tranp->tran_hba_len +
470cab28b2dStaylor 		    sizeof (struct scsi_pkt));
471cab28b2dStaylor 		in_pktp->pkt_cdblen = 0;
472cab28b2dStaylor 	}
473*8faf39b2Staylor 	pktw->pcw_flags &=
474*8faf39b2Staylor 	    ~(PCW_NEED_EXT_CDB|PCW_NEED_EXT_TGT|PCW_NEED_EXT_SCB);
475cab28b2dStaylor fail2:
476cab28b2dStaylor 	kmem_cache_free(tranp->tran_pkt_cache_ptr, pktw);
477cab28b2dStaylor fail1:
478cab28b2dStaylor 	if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
479cab28b2dStaylor 		ddi_set_callback(callback, callback_arg,
480cab28b2dStaylor 			&scsi_callback_id);
481cab28b2dStaylor 	}
482cab28b2dStaylor 
483cab28b2dStaylor 	return (NULL);
484cab28b2dStaylor }
485cab28b2dStaylor 
486cab28b2dStaylor void
487cab28b2dStaylor scsi_free_cache_pkt(struct scsi_address *ap, struct scsi_pkt *pktp)
488cab28b2dStaylor {
489cab28b2dStaylor 	struct scsi_pkt_cache_wrapper *pktw;
490cab28b2dStaylor 
491cab28b2dStaylor 	(*A_TO_TRAN(ap)->tran_teardown_pkt)(pktp);
492cab28b2dStaylor 	pktw = (struct scsi_pkt_cache_wrapper *)pktp;
493*8faf39b2Staylor 	if (pktw->pcw_flags & PCW_BOUND)
494*8faf39b2Staylor 		scsi_dmafree_attr(pktp);
495cab28b2dStaylor 
496cab28b2dStaylor 	/*
497cab28b2dStaylor 	 * if we allocated memory for anything that wouldn't fit, free
498cab28b2dStaylor 	 * the memory and restore the pointers
499cab28b2dStaylor 	 */
500*8faf39b2Staylor 	if (pktw->pcw_flags & PCW_NEED_EXT_SCB) {
501cab28b2dStaylor 		kmem_free(pktp->pkt_scbp, pktp->pkt_scblen);
502cab28b2dStaylor 		pktp->pkt_scbp = (opaque_t)((char *)pktp +
503cab28b2dStaylor 		    (A_TO_TRAN(ap))->tran_hba_len +
504cab28b2dStaylor 		    DEFAULT_PRIVLEN + sizeof (struct scsi_pkt_cache_wrapper));
505cab28b2dStaylor 		if ((A_TO_TRAN(ap))->tran_hba_flags & SCSI_HBA_TRAN_CDB)
506cab28b2dStaylor 			pktp->pkt_scbp = (opaque_t)((pktp->pkt_scbp) +
507cab28b2dStaylor 				DEFAULT_CDBLEN);
508cab28b2dStaylor 		pktp->pkt_scblen = 0;
509cab28b2dStaylor 	}
510*8faf39b2Staylor 	if (pktw->pcw_flags & PCW_NEED_EXT_TGT) {
511cab28b2dStaylor 		kmem_free(pktp->pkt_private, pktp->pkt_tgtlen);
512cab28b2dStaylor 		pktp->pkt_tgtlen = 0;
513cab28b2dStaylor 		pktp->pkt_private = NULL;
514cab28b2dStaylor 	}
515*8faf39b2Staylor 	if (pktw->pcw_flags & PCW_NEED_EXT_CDB) {
516cab28b2dStaylor 		kmem_free(pktp->pkt_cdbp, pktp->pkt_cdblen);
517cab28b2dStaylor 		pktp->pkt_cdbp = (opaque_t)((char *)pktp +
518cab28b2dStaylor 		    (A_TO_TRAN(ap))->tran_hba_len +
519cab28b2dStaylor 		    sizeof (struct scsi_pkt_cache_wrapper));
520cab28b2dStaylor 		pktp->pkt_cdblen = 0;
521cab28b2dStaylor 	}
522*8faf39b2Staylor 	pktw->pcw_flags &=
523*8faf39b2Staylor 	    ~(PCW_NEED_EXT_CDB|PCW_NEED_EXT_TGT|PCW_NEED_EXT_SCB);
524cab28b2dStaylor 	kmem_cache_free(A_TO_TRAN(ap)->tran_pkt_cache_ptr, pktw);
525cab28b2dStaylor 
526cab28b2dStaylor 	if (scsi_callback_id != 0) {
527cab28b2dStaylor 		ddi_run_callback(&scsi_callback_id);
528cab28b2dStaylor 	}
529cab28b2dStaylor 
530cab28b2dStaylor }
531cab28b2dStaylor 
532*8faf39b2Staylor 
5337c478bd9Sstevel@tonic-gate struct scsi_pkt *
5347c478bd9Sstevel@tonic-gate scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *in_pktp,
5357c478bd9Sstevel@tonic-gate     struct buf *bp, int cmdlen, int statuslen, int pplen,
5367c478bd9Sstevel@tonic-gate     int flags, int (*callback)(caddr_t), caddr_t callback_arg)
5377c478bd9Sstevel@tonic-gate {
5387c478bd9Sstevel@tonic-gate 	struct scsi_pkt *pktp;
5397c478bd9Sstevel@tonic-gate 	scsi_hba_tran_t *tranp = ap->a_hba_tran;
5407c478bd9Sstevel@tonic-gate 	int		(*func)(caddr_t);
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate 	TRACE_5(TR_FAC_SCSI_RES, TR_SCSI_INIT_PKT_START,
5437c478bd9Sstevel@tonic-gate "scsi_init_pkt_start: addr %p in_pktp %p cmdlen %d statuslen %d pplen %d",
5447c478bd9Sstevel@tonic-gate 	    ap, in_pktp, cmdlen, statuslen, pplen);
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate #if defined(__i386) || defined(__amd64)
5477c478bd9Sstevel@tonic-gate 	if (flags & PKT_CONSISTENT_OLD) {
5487c478bd9Sstevel@tonic-gate 		flags &= ~PKT_CONSISTENT_OLD;
5497c478bd9Sstevel@tonic-gate 		flags |= PKT_CONSISTENT;
5507c478bd9Sstevel@tonic-gate 	}
5517c478bd9Sstevel@tonic-gate #endif
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate 	pktp = (*tranp->tran_init_pkt) (ap, in_pktp, bp, cmdlen,
5567c478bd9Sstevel@tonic-gate 		statuslen, pplen, flags, func, NULL);
5577c478bd9Sstevel@tonic-gate 	if (pktp == NULL) {
5587c478bd9Sstevel@tonic-gate 		if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
5597c478bd9Sstevel@tonic-gate 			ddi_set_callback(callback, callback_arg,
5607c478bd9Sstevel@tonic-gate 				&scsi_callback_id);
5617c478bd9Sstevel@tonic-gate 		}
5627c478bd9Sstevel@tonic-gate 	}
5637c478bd9Sstevel@tonic-gate 
5647c478bd9Sstevel@tonic-gate 	TRACE_1(TR_FAC_SCSI_RES, TR_SCSI_INIT_PKT_END,
5657c478bd9Sstevel@tonic-gate 		"scsi_init_pkt_end: pktp %p", pktp);
5667c478bd9Sstevel@tonic-gate 	return (pktp);
5677c478bd9Sstevel@tonic-gate }
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate void
5707c478bd9Sstevel@tonic-gate scsi_destroy_pkt(struct scsi_pkt *pkt)
5717c478bd9Sstevel@tonic-gate {
5727c478bd9Sstevel@tonic-gate 	struct scsi_address	*ap = P_TO_ADDR(pkt);
5737c478bd9Sstevel@tonic-gate 
5747c478bd9Sstevel@tonic-gate 	TRACE_1(TR_FAC_SCSI_RES, TR_SCSI_DESTROY_PKT_START,
5757c478bd9Sstevel@tonic-gate 		"scsi_destroy_pkt_start: pkt %p", pkt);
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate 	(*A_TO_TRAN(ap)->tran_destroy_pkt)(ap, pkt);
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 	if (scsi_callback_id != 0) {
5807c478bd9Sstevel@tonic-gate 		ddi_run_callback(&scsi_callback_id);
5817c478bd9Sstevel@tonic-gate 	}
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 	TRACE_0(TR_FAC_SCSI_RES, TR_SCSI_DESTROY_PKT_END,
5847c478bd9Sstevel@tonic-gate 		"scsi_destroy_pkt_end");
5857c478bd9Sstevel@tonic-gate }
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate /*
5897c478bd9Sstevel@tonic-gate  *	Generic Resource Allocation Routines
5907c478bd9Sstevel@tonic-gate  */
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate struct scsi_pkt *
5937c478bd9Sstevel@tonic-gate scsi_resalloc(struct scsi_address *ap, int cmdlen, int statuslen,
5947c478bd9Sstevel@tonic-gate     opaque_t dmatoken, int (*callback)())
5957c478bd9Sstevel@tonic-gate {
5967c478bd9Sstevel@tonic-gate 	register struct	scsi_pkt *pkt;
5977c478bd9Sstevel@tonic-gate 	register scsi_hba_tran_t *tranp = ap->a_hba_tran;
5987c478bd9Sstevel@tonic-gate 	register int			(*func)(caddr_t);
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate 	func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate 	pkt = (*tranp->tran_init_pkt) (ap, NULL, (struct buf *)dmatoken,
6037c478bd9Sstevel@tonic-gate 		cmdlen, statuslen, 0, 0, func, NULL);
6047c478bd9Sstevel@tonic-gate 	if (pkt == NULL) {
6057c478bd9Sstevel@tonic-gate 		if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
6067c478bd9Sstevel@tonic-gate 			ddi_set_callback(callback, NULL, &scsi_callback_id);
6077c478bd9Sstevel@tonic-gate 		}
6087c478bd9Sstevel@tonic-gate 	}
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 	return (pkt);
6117c478bd9Sstevel@tonic-gate }
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate struct scsi_pkt *
6147c478bd9Sstevel@tonic-gate scsi_pktalloc(struct scsi_address *ap, int cmdlen, int statuslen,
6157c478bd9Sstevel@tonic-gate     int (*callback)())
6167c478bd9Sstevel@tonic-gate {
6177c478bd9Sstevel@tonic-gate 	struct scsi_pkt		*pkt;
6187c478bd9Sstevel@tonic-gate 	struct scsi_hba_tran	*tran = ap->a_hba_tran;
6197c478bd9Sstevel@tonic-gate 	register int			(*func)(caddr_t);
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 	func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate 	pkt = (*tran->tran_init_pkt) (ap, NULL, NULL, cmdlen,
6247c478bd9Sstevel@tonic-gate 		statuslen, 0, 0, func, NULL);
6257c478bd9Sstevel@tonic-gate 	if (pkt == NULL) {
6267c478bd9Sstevel@tonic-gate 		if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
6277c478bd9Sstevel@tonic-gate 			ddi_set_callback(callback, NULL, &scsi_callback_id);
6287c478bd9Sstevel@tonic-gate 		}
6297c478bd9Sstevel@tonic-gate 	}
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate 	return (pkt);
6327c478bd9Sstevel@tonic-gate }
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate struct scsi_pkt *
6357c478bd9Sstevel@tonic-gate scsi_dmaget(struct scsi_pkt *pkt, opaque_t dmatoken, int (*callback)())
6367c478bd9Sstevel@tonic-gate {
6377c478bd9Sstevel@tonic-gate 	struct scsi_pkt		*new_pkt;
6387c478bd9Sstevel@tonic-gate 	register int		(*func)(caddr_t);
6397c478bd9Sstevel@tonic-gate 
6407c478bd9Sstevel@tonic-gate 	func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate 	new_pkt = (*P_TO_TRAN(pkt)->tran_init_pkt) (&pkt->pkt_address,
6437c478bd9Sstevel@tonic-gate 		pkt, (struct buf *)dmatoken,
6447c478bd9Sstevel@tonic-gate 		0, 0, 0, 0, func, NULL);
6457c478bd9Sstevel@tonic-gate 	ASSERT(new_pkt == pkt || new_pkt == NULL);
6467c478bd9Sstevel@tonic-gate 	if (new_pkt == NULL) {
6477c478bd9Sstevel@tonic-gate 		if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
6487c478bd9Sstevel@tonic-gate 			ddi_set_callback(callback, NULL, &scsi_callback_id);
6497c478bd9Sstevel@tonic-gate 		}
6507c478bd9Sstevel@tonic-gate 	}
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate 	return (new_pkt);
6537c478bd9Sstevel@tonic-gate }
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate 
6567c478bd9Sstevel@tonic-gate /*
6577c478bd9Sstevel@tonic-gate  *	Generic Resource Deallocation Routines
6587c478bd9Sstevel@tonic-gate  */
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate void
6617c478bd9Sstevel@tonic-gate scsi_dmafree(struct scsi_pkt *pkt)
6627c478bd9Sstevel@tonic-gate {
6637c478bd9Sstevel@tonic-gate 	register struct scsi_address	*ap = P_TO_ADDR(pkt);
664*8faf39b2Staylor 
6657c478bd9Sstevel@tonic-gate 	(*A_TO_TRAN(ap)->tran_dmafree)(ap, pkt);
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate 	if (scsi_callback_id != 0) {
6687c478bd9Sstevel@tonic-gate 		ddi_run_callback(&scsi_callback_id);
6697c478bd9Sstevel@tonic-gate 	}
6707c478bd9Sstevel@tonic-gate }
6717c478bd9Sstevel@tonic-gate 
672*8faf39b2Staylor /*ARGSUSED*/
673*8faf39b2Staylor void
674*8faf39b2Staylor scsi_cache_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
675*8faf39b2Staylor {
676*8faf39b2Staylor 	ASSERT(pkt->pkt_numcookies == 0);
677*8faf39b2Staylor 	ASSERT(pkt->pkt_handle != NULL);
678*8faf39b2Staylor 	scsi_dmafree_attr(pkt);
679*8faf39b2Staylor 
680*8faf39b2Staylor 	if (scsi_callback_id != 0) {
681*8faf39b2Staylor 		ddi_run_callback(&scsi_callback_id);
682*8faf39b2Staylor 	}
683*8faf39b2Staylor }
684*8faf39b2Staylor 
6857c478bd9Sstevel@tonic-gate void
6867c478bd9Sstevel@tonic-gate scsi_sync_pkt(struct scsi_pkt *pkt)
6877c478bd9Sstevel@tonic-gate {
6887c478bd9Sstevel@tonic-gate 	register struct scsi_address	*ap = P_TO_ADDR(pkt);
6897c478bd9Sstevel@tonic-gate 	(*A_TO_TRAN(ap)->tran_sync_pkt)(ap, pkt);
6907c478bd9Sstevel@tonic-gate }
6917c478bd9Sstevel@tonic-gate 
692*8faf39b2Staylor /*ARGSUSED*/
693*8faf39b2Staylor void
694*8faf39b2Staylor scsi_sync_cache_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
695*8faf39b2Staylor {
696*8faf39b2Staylor 	if (pkt->pkt_handle) {
697*8faf39b2Staylor 		ASSERT((pkt->pkt_dma_flags & DDI_DMA_WRITE) ||
698*8faf39b2Staylor 			(pkt->pkt_dma_flags & DDI_DMA_READ));
699*8faf39b2Staylor 		(void) ddi_dma_sync(pkt->pkt_handle,
700*8faf39b2Staylor 			pkt->pkt_dma_offset, pkt->pkt_dma_len,
701*8faf39b2Staylor 			(pkt->pkt_dma_flags & DDI_DMA_WRITE) ?
702*8faf39b2Staylor 			DDI_DMA_SYNC_FORDEV : DDI_DMA_SYNC_FORCPU);
703*8faf39b2Staylor 	}
704*8faf39b2Staylor }
705*8faf39b2Staylor 
7067c478bd9Sstevel@tonic-gate void
7077c478bd9Sstevel@tonic-gate scsi_resfree(struct scsi_pkt *pkt)
7087c478bd9Sstevel@tonic-gate {
7097c478bd9Sstevel@tonic-gate 	register struct scsi_address	*ap = P_TO_ADDR(pkt);
7107c478bd9Sstevel@tonic-gate 	(*A_TO_TRAN(ap)->tran_destroy_pkt)(ap, pkt);
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate 	if (scsi_callback_id != 0) {
7137c478bd9Sstevel@tonic-gate 		ddi_run_callback(&scsi_callback_id);
7147c478bd9Sstevel@tonic-gate 	}
7157c478bd9Sstevel@tonic-gate }
716