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)
126*7b93957cSeota 		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 
135cab28b2dStaylor void scsi_free_cache_pkt(struct scsi_address *, struct scsi_pkt *);
136cab28b2dStaylor 
137cab28b2dStaylor struct scsi_pkt *
138cab28b2dStaylor scsi_init_cache_pkt(struct scsi_address *ap, struct scsi_pkt *in_pktp,
139cab28b2dStaylor     struct buf *bp, int cmdlen, int statuslen, int pplen,
140cab28b2dStaylor     int flags, int (*callback)(caddr_t), caddr_t callback_arg)
141cab28b2dStaylor {
142cab28b2dStaylor 	struct scsi_pkt_cache_wrapper *pktw;
143cab28b2dStaylor 	scsi_hba_tran_t *tranp = ap->a_hba_tran;
144cab28b2dStaylor 	int		(*func)(caddr_t);
145cab28b2dStaylor 
146cab28b2dStaylor 	func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
147cab28b2dStaylor 
148cab28b2dStaylor 	if (in_pktp == NULL) {
149cab28b2dStaylor 		int kf;
150cab28b2dStaylor 
151cab28b2dStaylor 		if (callback == SLEEP_FUNC)
152cab28b2dStaylor 			kf = KM_SLEEP;
153cab28b2dStaylor 		else
154cab28b2dStaylor 			kf = KM_NOSLEEP;
155cab28b2dStaylor 		pktw = kmem_cache_alloc(tranp->tran_pkt_cache_ptr,
156cab28b2dStaylor 			    kf);
157cab28b2dStaylor 		if (pktw == NULL)
158cab28b2dStaylor 			goto fail1;
159cab28b2dStaylor 
160cab28b2dStaylor 		pktw->pcw_kmflags = 0;
161cab28b2dStaylor 		in_pktp = &(pktw->pcw_pkt);
162cab28b2dStaylor 		/*
163830363f4Staylor 		 * target drivers should initialize pkt_comp and
164830363f4Staylor 		 * pkt_time, but sometimes they don't so initialize
165830363f4Staylor 		 * them here to be safe.
166cab28b2dStaylor 		 */
167cab28b2dStaylor 		in_pktp->pkt_address = *ap;
168830363f4Staylor 		in_pktp->pkt_flags = 0;
169830363f4Staylor 		in_pktp->pkt_time = 0;
170cab28b2dStaylor 		in_pktp->pkt_resid = 0;
171cab28b2dStaylor 		in_pktp->pkt_state = 0;
172cab28b2dStaylor 		in_pktp->pkt_statistics = 0;
173cab28b2dStaylor 		in_pktp->pkt_reason = 0;
174cab28b2dStaylor 
175cab28b2dStaylor 		in_pktp->pkt_cdblen = cmdlen;
176cab28b2dStaylor 		if ((tranp->tran_hba_flags & SCSI_HBA_TRAN_CDB) &&
177cab28b2dStaylor 		    (cmdlen > DEFAULT_CDBLEN)) {
178cab28b2dStaylor 			pktw->pcw_kmflags |= NEED_EXT_CDB;
179830363f4Staylor 			in_pktp->pkt_cdbp = kmem_alloc(cmdlen, kf);
180cab28b2dStaylor 			if (in_pktp->pkt_cdbp == NULL)
181cab28b2dStaylor 				goto fail2;
182cab28b2dStaylor 		}
183cab28b2dStaylor 		in_pktp->pkt_tgtlen = pplen;
184cab28b2dStaylor 		if (pplen > DEFAULT_PRIVLEN) {
185cab28b2dStaylor 			pktw->pcw_kmflags |= NEED_EXT_TGT;
186830363f4Staylor 			in_pktp->pkt_private = kmem_alloc(pplen, kf);
187cab28b2dStaylor 			if (in_pktp->pkt_private == NULL)
188cab28b2dStaylor 				goto fail3;
189cab28b2dStaylor 		}
190cab28b2dStaylor 		in_pktp->pkt_scblen = statuslen;
191cab28b2dStaylor 		if ((tranp->tran_hba_flags & SCSI_HBA_TRAN_SCB) &&
192cab28b2dStaylor 		    (statuslen > DEFAULT_SCBLEN)) {
193cab28b2dStaylor 			pktw->pcw_kmflags |= NEED_EXT_SCB;
194830363f4Staylor 			in_pktp->pkt_scbp = kmem_alloc(statuslen, kf);
195cab28b2dStaylor 			if (in_pktp->pkt_scbp == NULL)
196cab28b2dStaylor 				goto fail4;
197cab28b2dStaylor 		}
198cab28b2dStaylor 		if ((*tranp->tran_setup_pkt) (in_pktp,
199cab28b2dStaylor 			func, NULL) == -1) {
200cab28b2dStaylor 				goto fail5;
201cab28b2dStaylor 		}
202830363f4Staylor 		if (cmdlen)
203830363f4Staylor 			bzero((void *)in_pktp->pkt_cdbp, cmdlen);
204830363f4Staylor 		if (pplen)
205830363f4Staylor 			bzero((void *)in_pktp->pkt_private, pplen);
206830363f4Staylor 		if (statuslen)
207830363f4Staylor 			bzero((void *)in_pktp->pkt_scbp, statuslen);
208cab28b2dStaylor 	}
209cab28b2dStaylor 	if (bp && bp->b_bcount) {
210cab28b2dStaylor 		if ((*tranp->tran_setup_bp) (in_pktp, bp,
211cab28b2dStaylor 		    flags, func, NULL) == -1) {
212cab28b2dStaylor 			scsi_free_cache_pkt(ap, in_pktp);
213cab28b2dStaylor 			in_pktp = NULL;
214cab28b2dStaylor 		}
215cab28b2dStaylor 	}
216cab28b2dStaylor 	return (in_pktp);
217cab28b2dStaylor 
218cab28b2dStaylor fail5:
219cab28b2dStaylor 	if (pktw->pcw_kmflags & NEED_EXT_SCB) {
220cab28b2dStaylor 		kmem_free(in_pktp->pkt_scbp, statuslen);
221cab28b2dStaylor 		in_pktp->pkt_scbp = (opaque_t)((char *)in_pktp +
222cab28b2dStaylor 		    tranp->tran_hba_len + DEFAULT_PRIVLEN +
223cab28b2dStaylor 		    sizeof (struct scsi_pkt));
224cab28b2dStaylor 		if ((A_TO_TRAN(ap))->tran_hba_flags & SCSI_HBA_TRAN_CDB)
225cab28b2dStaylor 			in_pktp->pkt_scbp = (opaque_t)((in_pktp->pkt_scbp) +
226cab28b2dStaylor 				DEFAULT_CDBLEN);
227cab28b2dStaylor 		in_pktp->pkt_scblen = 0;
228cab28b2dStaylor 	}
229cab28b2dStaylor fail4:
230cab28b2dStaylor 	if (pktw->pcw_kmflags & NEED_EXT_TGT) {
231cab28b2dStaylor 		kmem_free(in_pktp->pkt_private, pplen);
232cab28b2dStaylor 		in_pktp->pkt_tgtlen = 0;
233cab28b2dStaylor 		in_pktp->pkt_private = NULL;
234cab28b2dStaylor 	}
235cab28b2dStaylor fail3:
236cab28b2dStaylor 	if (pktw->pcw_kmflags & NEED_EXT_CDB) {
237cab28b2dStaylor 		kmem_free(in_pktp->pkt_cdbp, cmdlen);
238cab28b2dStaylor 		in_pktp->pkt_cdbp = (opaque_t)((char *)in_pktp +
239cab28b2dStaylor 		    tranp->tran_hba_len +
240cab28b2dStaylor 		    sizeof (struct scsi_pkt));
241cab28b2dStaylor 		in_pktp->pkt_cdblen = 0;
242cab28b2dStaylor 	}
243cab28b2dStaylor 	pktw->pcw_kmflags &=
244cab28b2dStaylor 	    ~(NEED_EXT_CDB|NEED_EXT_TGT|NEED_EXT_SCB);
245cab28b2dStaylor fail2:
246cab28b2dStaylor 	kmem_cache_free(tranp->tran_pkt_cache_ptr, pktw);
247cab28b2dStaylor fail1:
248cab28b2dStaylor 	if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
249cab28b2dStaylor 		ddi_set_callback(callback, callback_arg,
250cab28b2dStaylor 			&scsi_callback_id);
251cab28b2dStaylor 	}
252cab28b2dStaylor 
253cab28b2dStaylor 	return (NULL);
254cab28b2dStaylor }
255cab28b2dStaylor 
256cab28b2dStaylor void
257cab28b2dStaylor scsi_free_cache_pkt(struct scsi_address *ap, struct scsi_pkt *pktp)
258cab28b2dStaylor {
259cab28b2dStaylor 	struct scsi_pkt_cache_wrapper *pktw;
260cab28b2dStaylor 
261cab28b2dStaylor 	(*A_TO_TRAN(ap)->tran_teardown_pkt)(pktp);
262cab28b2dStaylor 	pktw = (struct scsi_pkt_cache_wrapper *)pktp;
263cab28b2dStaylor 
264cab28b2dStaylor 	/*
265cab28b2dStaylor 	 * if we allocated memory for anything that wouldn't fit, free
266cab28b2dStaylor 	 * the memory and restore the pointers
267cab28b2dStaylor 	 */
268cab28b2dStaylor 	if (pktw->pcw_kmflags & NEED_EXT_SCB) {
269cab28b2dStaylor 		kmem_free(pktp->pkt_scbp, pktp->pkt_scblen);
270cab28b2dStaylor 		pktp->pkt_scbp = (opaque_t)((char *)pktp +
271cab28b2dStaylor 		    (A_TO_TRAN(ap))->tran_hba_len +
272cab28b2dStaylor 		    DEFAULT_PRIVLEN + sizeof (struct scsi_pkt_cache_wrapper));
273cab28b2dStaylor 		if ((A_TO_TRAN(ap))->tran_hba_flags & SCSI_HBA_TRAN_CDB)
274cab28b2dStaylor 			pktp->pkt_scbp = (opaque_t)((pktp->pkt_scbp) +
275cab28b2dStaylor 				DEFAULT_CDBLEN);
276cab28b2dStaylor 		pktp->pkt_scblen = 0;
277cab28b2dStaylor 	}
278cab28b2dStaylor 	if (pktw->pcw_kmflags & NEED_EXT_TGT) {
279cab28b2dStaylor 		kmem_free(pktp->pkt_private, pktp->pkt_tgtlen);
280cab28b2dStaylor 		pktp->pkt_tgtlen = 0;
281cab28b2dStaylor 		pktp->pkt_private = NULL;
282cab28b2dStaylor 	}
283cab28b2dStaylor 	if (pktw->pcw_kmflags & NEED_EXT_CDB) {
284cab28b2dStaylor 		kmem_free(pktp->pkt_cdbp, pktp->pkt_cdblen);
285cab28b2dStaylor 		pktp->pkt_cdbp = (opaque_t)((char *)pktp +
286cab28b2dStaylor 		    (A_TO_TRAN(ap))->tran_hba_len +
287cab28b2dStaylor 		    sizeof (struct scsi_pkt_cache_wrapper));
288cab28b2dStaylor 		pktp->pkt_cdblen = 0;
289cab28b2dStaylor 	}
290cab28b2dStaylor 	pktw->pcw_kmflags &=
291cab28b2dStaylor 	    ~(NEED_EXT_CDB|NEED_EXT_TGT|NEED_EXT_SCB);
292cab28b2dStaylor 	ASSERT(pktw->pcw_kmflags == 0);
293cab28b2dStaylor 	kmem_cache_free(A_TO_TRAN(ap)->tran_pkt_cache_ptr, pktw);
294cab28b2dStaylor 
295cab28b2dStaylor 	if (scsi_callback_id != 0) {
296cab28b2dStaylor 		ddi_run_callback(&scsi_callback_id);
297cab28b2dStaylor 	}
298cab28b2dStaylor 
299cab28b2dStaylor }
300cab28b2dStaylor 
3017c478bd9Sstevel@tonic-gate struct scsi_pkt *
3027c478bd9Sstevel@tonic-gate scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *in_pktp,
3037c478bd9Sstevel@tonic-gate     struct buf *bp, int cmdlen, int statuslen, int pplen,
3047c478bd9Sstevel@tonic-gate     int flags, int (*callback)(caddr_t), caddr_t callback_arg)
3057c478bd9Sstevel@tonic-gate {
3067c478bd9Sstevel@tonic-gate 	struct scsi_pkt *pktp;
3077c478bd9Sstevel@tonic-gate 	scsi_hba_tran_t *tranp = ap->a_hba_tran;
3087c478bd9Sstevel@tonic-gate 	int		(*func)(caddr_t);
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 	TRACE_5(TR_FAC_SCSI_RES, TR_SCSI_INIT_PKT_START,
3117c478bd9Sstevel@tonic-gate "scsi_init_pkt_start: addr %p in_pktp %p cmdlen %d statuslen %d pplen %d",
3127c478bd9Sstevel@tonic-gate 	    ap, in_pktp, cmdlen, statuslen, pplen);
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate #if defined(__i386) || defined(__amd64)
3157c478bd9Sstevel@tonic-gate 	if (flags & PKT_CONSISTENT_OLD) {
3167c478bd9Sstevel@tonic-gate 		flags &= ~PKT_CONSISTENT_OLD;
3177c478bd9Sstevel@tonic-gate 		flags |= PKT_CONSISTENT;
3187c478bd9Sstevel@tonic-gate 	}
3197c478bd9Sstevel@tonic-gate #endif
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate 	func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 	pktp = (*tranp->tran_init_pkt) (ap, in_pktp, bp, cmdlen,
3247c478bd9Sstevel@tonic-gate 		statuslen, pplen, flags, func, NULL);
3257c478bd9Sstevel@tonic-gate 	if (pktp == NULL) {
3267c478bd9Sstevel@tonic-gate 		if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
3277c478bd9Sstevel@tonic-gate 			ddi_set_callback(callback, callback_arg,
3287c478bd9Sstevel@tonic-gate 				&scsi_callback_id);
3297c478bd9Sstevel@tonic-gate 		}
3307c478bd9Sstevel@tonic-gate 	}
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 	TRACE_1(TR_FAC_SCSI_RES, TR_SCSI_INIT_PKT_END,
3337c478bd9Sstevel@tonic-gate 		"scsi_init_pkt_end: pktp %p", pktp);
3347c478bd9Sstevel@tonic-gate 	return (pktp);
3357c478bd9Sstevel@tonic-gate }
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate void
3387c478bd9Sstevel@tonic-gate scsi_destroy_pkt(struct scsi_pkt *pkt)
3397c478bd9Sstevel@tonic-gate {
3407c478bd9Sstevel@tonic-gate 	struct scsi_address	*ap = P_TO_ADDR(pkt);
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 	TRACE_1(TR_FAC_SCSI_RES, TR_SCSI_DESTROY_PKT_START,
3437c478bd9Sstevel@tonic-gate 		"scsi_destroy_pkt_start: pkt %p", pkt);
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 	(*A_TO_TRAN(ap)->tran_destroy_pkt)(ap, pkt);
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 	if (scsi_callback_id != 0) {
3487c478bd9Sstevel@tonic-gate 		ddi_run_callback(&scsi_callback_id);
3497c478bd9Sstevel@tonic-gate 	}
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate 	TRACE_0(TR_FAC_SCSI_RES, TR_SCSI_DESTROY_PKT_END,
3527c478bd9Sstevel@tonic-gate 		"scsi_destroy_pkt_end");
3537c478bd9Sstevel@tonic-gate }
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate /*
3577c478bd9Sstevel@tonic-gate  *	Generic Resource Allocation Routines
3587c478bd9Sstevel@tonic-gate  */
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate struct scsi_pkt *
3617c478bd9Sstevel@tonic-gate scsi_resalloc(struct scsi_address *ap, int cmdlen, int statuslen,
3627c478bd9Sstevel@tonic-gate     opaque_t dmatoken, int (*callback)())
3637c478bd9Sstevel@tonic-gate {
3647c478bd9Sstevel@tonic-gate 	register struct	scsi_pkt *pkt;
3657c478bd9Sstevel@tonic-gate 	register scsi_hba_tran_t *tranp = ap->a_hba_tran;
3667c478bd9Sstevel@tonic-gate 	register int			(*func)(caddr_t);
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 	pkt = (*tranp->tran_init_pkt) (ap, NULL, (struct buf *)dmatoken,
3717c478bd9Sstevel@tonic-gate 		cmdlen, statuslen, 0, 0, func, NULL);
3727c478bd9Sstevel@tonic-gate 	if (pkt == NULL) {
3737c478bd9Sstevel@tonic-gate 		if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
3747c478bd9Sstevel@tonic-gate 			ddi_set_callback(callback, NULL, &scsi_callback_id);
3757c478bd9Sstevel@tonic-gate 		}
3767c478bd9Sstevel@tonic-gate 	}
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	return (pkt);
3797c478bd9Sstevel@tonic-gate }
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate struct scsi_pkt *
3827c478bd9Sstevel@tonic-gate scsi_pktalloc(struct scsi_address *ap, int cmdlen, int statuslen,
3837c478bd9Sstevel@tonic-gate     int (*callback)())
3847c478bd9Sstevel@tonic-gate {
3857c478bd9Sstevel@tonic-gate 	struct scsi_pkt		*pkt;
3867c478bd9Sstevel@tonic-gate 	struct scsi_hba_tran	*tran = ap->a_hba_tran;
3877c478bd9Sstevel@tonic-gate 	register int			(*func)(caddr_t);
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 	func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 	pkt = (*tran->tran_init_pkt) (ap, NULL, NULL, cmdlen,
3927c478bd9Sstevel@tonic-gate 		statuslen, 0, 0, func, NULL);
3937c478bd9Sstevel@tonic-gate 	if (pkt == NULL) {
3947c478bd9Sstevel@tonic-gate 		if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
3957c478bd9Sstevel@tonic-gate 			ddi_set_callback(callback, NULL, &scsi_callback_id);
3967c478bd9Sstevel@tonic-gate 		}
3977c478bd9Sstevel@tonic-gate 	}
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	return (pkt);
4007c478bd9Sstevel@tonic-gate }
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate struct scsi_pkt *
4037c478bd9Sstevel@tonic-gate scsi_dmaget(struct scsi_pkt *pkt, opaque_t dmatoken, int (*callback)())
4047c478bd9Sstevel@tonic-gate {
4057c478bd9Sstevel@tonic-gate 	struct scsi_pkt		*new_pkt;
4067c478bd9Sstevel@tonic-gate 	register int		(*func)(caddr_t);
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate 	func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 	new_pkt = (*P_TO_TRAN(pkt)->tran_init_pkt) (&pkt->pkt_address,
4117c478bd9Sstevel@tonic-gate 		pkt, (struct buf *)dmatoken,
4127c478bd9Sstevel@tonic-gate 		0, 0, 0, 0, func, NULL);
4137c478bd9Sstevel@tonic-gate 	ASSERT(new_pkt == pkt || new_pkt == NULL);
4147c478bd9Sstevel@tonic-gate 	if (new_pkt == NULL) {
4157c478bd9Sstevel@tonic-gate 		if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
4167c478bd9Sstevel@tonic-gate 			ddi_set_callback(callback, NULL, &scsi_callback_id);
4177c478bd9Sstevel@tonic-gate 		}
4187c478bd9Sstevel@tonic-gate 	}
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 	return (new_pkt);
4217c478bd9Sstevel@tonic-gate }
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate /*
4257c478bd9Sstevel@tonic-gate  *	Generic Resource Deallocation Routines
4267c478bd9Sstevel@tonic-gate  */
4277c478bd9Sstevel@tonic-gate 
4287c478bd9Sstevel@tonic-gate void
4297c478bd9Sstevel@tonic-gate scsi_dmafree(struct scsi_pkt *pkt)
4307c478bd9Sstevel@tonic-gate {
4317c478bd9Sstevel@tonic-gate 	register struct scsi_address	*ap = P_TO_ADDR(pkt);
4327c478bd9Sstevel@tonic-gate 	(*A_TO_TRAN(ap)->tran_dmafree)(ap, pkt);
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 	if (scsi_callback_id != 0) {
4357c478bd9Sstevel@tonic-gate 		ddi_run_callback(&scsi_callback_id);
4367c478bd9Sstevel@tonic-gate 	}
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate void
4407c478bd9Sstevel@tonic-gate scsi_sync_pkt(struct scsi_pkt *pkt)
4417c478bd9Sstevel@tonic-gate {
4427c478bd9Sstevel@tonic-gate 	register struct scsi_address	*ap = P_TO_ADDR(pkt);
4437c478bd9Sstevel@tonic-gate 	(*A_TO_TRAN(ap)->tran_sync_pkt)(ap, pkt);
4447c478bd9Sstevel@tonic-gate }
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate void
4477c478bd9Sstevel@tonic-gate scsi_resfree(struct scsi_pkt *pkt)
4487c478bd9Sstevel@tonic-gate {
4497c478bd9Sstevel@tonic-gate 	register struct scsi_address	*ap = P_TO_ADDR(pkt);
4507c478bd9Sstevel@tonic-gate 	(*A_TO_TRAN(ap)->tran_destroy_pkt)(ap, pkt);
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 	if (scsi_callback_id != 0) {
4537c478bd9Sstevel@tonic-gate 		ddi_run_callback(&scsi_callback_id);
4547c478bd9Sstevel@tonic-gate 	}
4557c478bd9Sstevel@tonic-gate }
456