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 *
scsi_alloc_consistent_buf(struct scsi_address * ap,struct buf * in_bp,size_t datalen,uint_t bflags,int (* callback)(caddr_t),caddr_t callback_arg)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 */
824ab75253Smrj while (i_ddi_mem_alloc(pdip, &scsi_alloc_attr, datalen,
834ab75253Smrj ((callback == SLEEP_FUNC) ? 1 : 0), 0, NULL,
844ab75253Smrj &bp->b_un.b_addr, &rlen, NULL) != DDI_SUCCESS) {
857c478bd9Sstevel@tonic-gate if (callback == SLEEP_FUNC) {
867c478bd9Sstevel@tonic-gate delay(drv_usectohz(10000));
877c478bd9Sstevel@tonic-gate } else {
887c478bd9Sstevel@tonic-gate if (!in_bp)
897c478bd9Sstevel@tonic-gate freerbuf(bp);
907c478bd9Sstevel@tonic-gate goto no_resource;
917c478bd9Sstevel@tonic-gate }
927c478bd9Sstevel@tonic-gate }
937c478bd9Sstevel@tonic-gate bp->b_flags |= bflags;
947c478bd9Sstevel@tonic-gate }
957c478bd9Sstevel@tonic-gate bp->b_bcount = datalen;
967c478bd9Sstevel@tonic-gate bp->b_resid = 0;
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate TRACE_0(TR_FAC_SCSI_RES, TR_SCSI_ALLOC_CONSISTENT_BUF_END,
99c6c44d06Sjw "scsi_alloc_consistent_buf_end");
1007c478bd9Sstevel@tonic-gate return (bp);
1017c478bd9Sstevel@tonic-gate
1027c478bd9Sstevel@tonic-gate no_resource:
1037c478bd9Sstevel@tonic-gate
1047c478bd9Sstevel@tonic-gate if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
1057c478bd9Sstevel@tonic-gate ddi_set_callback(callback, callback_arg,
106c6c44d06Sjw &scsi_callback_id);
1077c478bd9Sstevel@tonic-gate }
1087c478bd9Sstevel@tonic-gate TRACE_0(TR_FAC_SCSI_RES,
1097c478bd9Sstevel@tonic-gate TR_SCSI_ALLOC_CONSISTENT_BUF_RETURN1_END,
1107c478bd9Sstevel@tonic-gate "scsi_alloc_consistent_buf_end (return1)");
1117c478bd9Sstevel@tonic-gate return (NULL);
1127c478bd9Sstevel@tonic-gate }
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate void
scsi_free_consistent_buf(struct buf * bp)1157c478bd9Sstevel@tonic-gate scsi_free_consistent_buf(struct buf *bp)
1167c478bd9Sstevel@tonic-gate {
1177c478bd9Sstevel@tonic-gate TRACE_0(TR_FAC_SCSI_RES, TR_SCSI_FREE_CONSISTENT_BUF_START,
118c6c44d06Sjw "scsi_free_consistent_buf_start");
1197c478bd9Sstevel@tonic-gate if (!bp)
1207c478bd9Sstevel@tonic-gate return;
1217c478bd9Sstevel@tonic-gate if (bp->b_un.b_addr)
1227b93957cSeota i_ddi_mem_free((caddr_t)bp->b_un.b_addr, NULL);
1237c478bd9Sstevel@tonic-gate freerbuf(bp);
1247c478bd9Sstevel@tonic-gate if (scsi_callback_id != 0) {
1257c478bd9Sstevel@tonic-gate ddi_run_callback(&scsi_callback_id);
1267c478bd9Sstevel@tonic-gate }
1277c478bd9Sstevel@tonic-gate TRACE_0(TR_FAC_SCSI_RES, TR_SCSI_FREE_CONSISTENT_BUF_END,
128c6c44d06Sjw "scsi_free_consistent_buf_end");
1297c478bd9Sstevel@tonic-gate }
1307c478bd9Sstevel@tonic-gate
1318faf39b2Staylor void
scsi_dmafree_attr(struct scsi_pkt * pktp)1328faf39b2Staylor scsi_dmafree_attr(struct scsi_pkt *pktp)
1338faf39b2Staylor {
1348faf39b2Staylor struct scsi_pkt_cache_wrapper *pktw =
135c6c44d06Sjw (struct scsi_pkt_cache_wrapper *)pktp;
1368faf39b2Staylor
1378faf39b2Staylor if (pktw->pcw_flags & PCW_BOUND) {
1388faf39b2Staylor if (ddi_dma_unbind_handle(pktp->pkt_handle) !=
1398faf39b2Staylor DDI_SUCCESS)
1408faf39b2Staylor cmn_err(CE_WARN, "scsi_dmafree_attr: "
1418faf39b2Staylor "unbind handle failed");
1428faf39b2Staylor pktw->pcw_flags &= ~PCW_BOUND;
1438faf39b2Staylor }
1448faf39b2Staylor pktp->pkt_numcookies = 0;
14532141dfcSNikko He pktw->pcw_totalwin = 0;
1468faf39b2Staylor }
1478faf39b2Staylor
1488faf39b2Staylor struct buf *
scsi_pkt2bp(struct scsi_pkt * pkt)1498faf39b2Staylor scsi_pkt2bp(struct scsi_pkt *pkt)
1508faf39b2Staylor {
1518faf39b2Staylor return (((struct scsi_pkt_cache_wrapper *)pkt)->pcw_bp);
1528faf39b2Staylor }
1538faf39b2Staylor
1548faf39b2Staylor int
scsi_dma_buf_bind_attr(struct scsi_pkt_cache_wrapper * pktw,struct buf * bp,int dma_flags,int (* callback)(),caddr_t arg)1558faf39b2Staylor scsi_dma_buf_bind_attr(struct scsi_pkt_cache_wrapper *pktw,
156*86ef0a63SRichard Lowe struct buf *bp,
157*86ef0a63SRichard Lowe int dma_flags,
158*86ef0a63SRichard Lowe int (*callback)(),
159*86ef0a63SRichard Lowe caddr_t arg)
1608faf39b2Staylor {
1618faf39b2Staylor struct scsi_pkt *pktp = &(pktw->pcw_pkt);
1628faf39b2Staylor int status;
1638faf39b2Staylor
1648faf39b2Staylor /*
1658faf39b2Staylor * First time, need to establish the handle.
1668faf39b2Staylor */
1678faf39b2Staylor
1688faf39b2Staylor ASSERT(pktp->pkt_numcookies == 0);
1698faf39b2Staylor ASSERT(pktw->pcw_totalwin == 0);
1708faf39b2Staylor
1718faf39b2Staylor status = ddi_dma_buf_bind_handle(pktp->pkt_handle, bp, dma_flags,
172c6c44d06Sjw callback, arg, &pktw->pcw_cookie,
173c6c44d06Sjw &pktp->pkt_numcookies);
1748faf39b2Staylor
1758faf39b2Staylor switch (status) {
1768faf39b2Staylor case DDI_DMA_MAPPED:
1778faf39b2Staylor pktw->pcw_totalwin = 1;
1788faf39b2Staylor break;
1798faf39b2Staylor
1808faf39b2Staylor case DDI_DMA_PARTIAL_MAP:
1818faf39b2Staylor /* enable first call to ddi_dma_getwin */
1828faf39b2Staylor if (ddi_dma_numwin(pktp->pkt_handle,
1838faf39b2Staylor &pktw->pcw_totalwin) != DDI_SUCCESS) {
1848faf39b2Staylor bp->b_error = 0;
1858faf39b2Staylor return (0);
1868faf39b2Staylor }
1878faf39b2Staylor break;
1888faf39b2Staylor
1898faf39b2Staylor case DDI_DMA_NORESOURCES:
1908faf39b2Staylor bp->b_error = 0;
1918faf39b2Staylor return (0);
1928faf39b2Staylor
1938faf39b2Staylor case DDI_DMA_TOOBIG:
1948faf39b2Staylor bioerror(bp, EINVAL);
1958faf39b2Staylor return (0);
1968faf39b2Staylor
1978faf39b2Staylor case DDI_DMA_NOMAPPING:
1988faf39b2Staylor case DDI_DMA_INUSE:
1998faf39b2Staylor default:
2008faf39b2Staylor bioerror(bp, EFAULT);
2018faf39b2Staylor return (0);
2028faf39b2Staylor }
2038faf39b2Staylor
2048faf39b2Staylor /* initialize the loop controls for scsi_dmaget_attr() */
2058faf39b2Staylor pktw->pcw_curwin = 0;
2068faf39b2Staylor pktw->pcw_total_xfer = 0;
2078faf39b2Staylor pktp->pkt_dma_flags = dma_flags;
2088faf39b2Staylor return (1);
2098faf39b2Staylor }
2108faf39b2Staylor
2118faf39b2Staylor #if defined(_DMA_USES_PHYSADDR)
2128faf39b2Staylor int
scsi_dmaget_attr(struct scsi_pkt_cache_wrapper * pktw)2138faf39b2Staylor scsi_dmaget_attr(struct scsi_pkt_cache_wrapper *pktw)
2148faf39b2Staylor {
2158faf39b2Staylor struct scsi_pkt *pktp = &(pktw->pcw_pkt);
2168faf39b2Staylor
2178faf39b2Staylor int status;
2188faf39b2Staylor int num_segs = 0;
2198faf39b2Staylor ddi_dma_impl_t *hp = (ddi_dma_impl_t *)pktp->pkt_handle;
2208faf39b2Staylor ddi_dma_cookie_t *cp;
2218faf39b2Staylor
2228faf39b2Staylor if (pktw->pcw_curwin != 0) {
2238faf39b2Staylor ddi_dma_cookie_t cookie;
2248faf39b2Staylor
2258faf39b2Staylor /*
2268faf39b2Staylor * start the next window, and get its first cookie
2278faf39b2Staylor */
2288faf39b2Staylor status = ddi_dma_getwin(pktp->pkt_handle,
229c6c44d06Sjw pktw->pcw_curwin, &pktp->pkt_dma_offset,
230c6c44d06Sjw &pktp->pkt_dma_len, &cookie,
231c6c44d06Sjw &pktp->pkt_numcookies);
2328faf39b2Staylor if (status != DDI_SUCCESS)
2338faf39b2Staylor return (0);
2348faf39b2Staylor }
2358faf39b2Staylor
2368faf39b2Staylor /*
2378faf39b2Staylor * start the Scatter/Gather loop
2388faf39b2Staylor */
2398faf39b2Staylor cp = hp->dmai_cookie - 1;
2408faf39b2Staylor pktp->pkt_dma_len = 0;
2418faf39b2Staylor for (;;) {
2428faf39b2Staylor
2438faf39b2Staylor /* take care of the loop-bookkeeping */
2448faf39b2Staylor pktp->pkt_dma_len += cp->dmac_size;
2458faf39b2Staylor num_segs++;
2468faf39b2Staylor /*
2478faf39b2Staylor * if this was the last cookie in the current window
2488faf39b2Staylor * set the loop controls start the next window and
2498faf39b2Staylor * exit so the HBA can do this partial transfer
2508faf39b2Staylor */
2518faf39b2Staylor if (num_segs >= pktp->pkt_numcookies) {
2528faf39b2Staylor pktw->pcw_curwin++;
2538faf39b2Staylor break;
2548faf39b2Staylor }
2558faf39b2Staylor
2568faf39b2Staylor cp++;
2578faf39b2Staylor }
2588faf39b2Staylor pktw->pcw_total_xfer += pktp->pkt_dma_len;
2598faf39b2Staylor pktp->pkt_cookies = hp->dmai_cookie - 1;
2608faf39b2Staylor hp->dmai_cookie = cp;
2619a63ec27SRobert Mustacchi hp->dmai_curcookie = num_segs;
2628faf39b2Staylor
2638faf39b2Staylor return (1);
2648faf39b2Staylor }
2658faf39b2Staylor #endif
2668faf39b2Staylor
267cab28b2dStaylor void scsi_free_cache_pkt(struct scsi_address *, struct scsi_pkt *);
268cab28b2dStaylor
269cab28b2dStaylor struct scsi_pkt *
scsi_init_cache_pkt(struct scsi_address * ap,struct scsi_pkt * in_pktp,struct buf * bp,int cmdlen,int statuslen,int pplen,int flags,int (* callback)(caddr_t),caddr_t callback_arg)270cab28b2dStaylor scsi_init_cache_pkt(struct scsi_address *ap, struct scsi_pkt *in_pktp,
271cab28b2dStaylor struct buf *bp, int cmdlen, int statuslen, int pplen,
272cab28b2dStaylor int flags, int (*callback)(caddr_t), caddr_t callback_arg)
273cab28b2dStaylor {
274cab28b2dStaylor struct scsi_pkt_cache_wrapper *pktw;
275cab28b2dStaylor scsi_hba_tran_t *tranp = ap->a_hba_tran;
276cab28b2dStaylor int (*func)(caddr_t);
277cab28b2dStaylor
278cab28b2dStaylor func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
279cab28b2dStaylor
280cab28b2dStaylor if (in_pktp == NULL) {
281cab28b2dStaylor int kf;
282cab28b2dStaylor
283cab28b2dStaylor if (callback == SLEEP_FUNC)
284cab28b2dStaylor kf = KM_SLEEP;
285cab28b2dStaylor else
286cab28b2dStaylor kf = KM_NOSLEEP;
28766027529SNikko He /*
28866027529SNikko He * By using kmem_cache_alloc(), the layout of the
28966027529SNikko He * scsi_pkt, scsi_pkt_cache_wrapper, hba private data,
29066027529SNikko He * cdb, tgt driver private data, and status block is
29166027529SNikko He * as below.
29266027529SNikko He *
29366027529SNikko He * This is a piece of contiguous memory starting from
29466027529SNikko He * the first structure field scsi_pkt in the struct
29566027529SNikko He * scsi_pkt_cache_wrapper, followed by the hba private
29666027529SNikko He * data, pkt_cdbp, the tgt driver private data and
29766027529SNikko He * pkt_scbp.
29866027529SNikko He *
29966027529SNikko He * |----------------------------|--------------------->
30066027529SNikko He * | struct scsi_pkt | struct
30166027529SNikko He * | ...... |scsi_pkt_cache_wrapper
30266027529SNikko He * | pcw_flags |
30366027529SNikko He * |----------------------------|<---------------------
30466027529SNikko He * | hba private data |tranp->tran_hba_len
30566027529SNikko He * |----------------------------|
30666027529SNikko He * | pkt_cdbp |DEFAULT_CDBLEN
30766027529SNikko He * |----------------------------|
30866027529SNikko He * | tgt private data |DEFAULT_PRIVLEN
30966027529SNikko He * |----------------------------|
31066027529SNikko He * | pkt_scbp |DEFAULT_SCBLEN
31166027529SNikko He * |----------------------------|
31266027529SNikko He *
31366027529SNikko He * If the actual data length of the cdb, or the tgt
31466027529SNikko He * driver private data, or the status block is bigger
31566027529SNikko He * than the default data length, kmem_alloc() will be
31666027529SNikko He * called to get extra space.
31766027529SNikko He */
318cab28b2dStaylor pktw = kmem_cache_alloc(tranp->tran_pkt_cache_ptr,
319c6c44d06Sjw kf);
320cab28b2dStaylor if (pktw == NULL)
321cab28b2dStaylor goto fail1;
322cab28b2dStaylor
3238faf39b2Staylor pktw->pcw_flags = 0;
324cab28b2dStaylor in_pktp = &(pktw->pcw_pkt);
3258faf39b2Staylor in_pktp->pkt_address = *ap;
3264c06356bSdh
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 */
332830363f4Staylor in_pktp->pkt_flags = 0;
333830363f4Staylor in_pktp->pkt_time = 0;
334cab28b2dStaylor in_pktp->pkt_resid = 0;
335cab28b2dStaylor in_pktp->pkt_state = 0;
336cab28b2dStaylor in_pktp->pkt_statistics = 0;
337cab28b2dStaylor in_pktp->pkt_reason = 0;
3388faf39b2Staylor in_pktp->pkt_dma_offset = 0;
3398faf39b2Staylor in_pktp->pkt_dma_len = 0;
3408faf39b2Staylor in_pktp->pkt_dma_flags = 0;
341602ca9eaScth in_pktp->pkt_path_instance = 0;
3428faf39b2Staylor ASSERT(in_pktp->pkt_numcookies == 0);
3438faf39b2Staylor pktw->pcw_curwin = 0;
3448faf39b2Staylor pktw->pcw_totalwin = 0;
3458faf39b2Staylor pktw->pcw_total_xfer = 0;
346cab28b2dStaylor
347cab28b2dStaylor in_pktp->pkt_cdblen = cmdlen;
348cab28b2dStaylor if ((tranp->tran_hba_flags & SCSI_HBA_TRAN_CDB) &&
349cab28b2dStaylor (cmdlen > DEFAULT_CDBLEN)) {
3508faf39b2Staylor pktw->pcw_flags |= PCW_NEED_EXT_CDB;
351830363f4Staylor in_pktp->pkt_cdbp = kmem_alloc(cmdlen, kf);
352cab28b2dStaylor if (in_pktp->pkt_cdbp == NULL)
353cab28b2dStaylor goto fail2;
354cab28b2dStaylor }
355cab28b2dStaylor in_pktp->pkt_tgtlen = pplen;
356cab28b2dStaylor if (pplen > DEFAULT_PRIVLEN) {
3578faf39b2Staylor pktw->pcw_flags |= PCW_NEED_EXT_TGT;
358830363f4Staylor in_pktp->pkt_private = kmem_alloc(pplen, kf);
359cab28b2dStaylor if (in_pktp->pkt_private == NULL)
360cab28b2dStaylor goto fail3;
361cab28b2dStaylor }
362cab28b2dStaylor in_pktp->pkt_scblen = statuslen;
363cab28b2dStaylor if ((tranp->tran_hba_flags & SCSI_HBA_TRAN_SCB) &&
364cab28b2dStaylor (statuslen > DEFAULT_SCBLEN)) {
3658faf39b2Staylor pktw->pcw_flags |= PCW_NEED_EXT_SCB;
366830363f4Staylor in_pktp->pkt_scbp = kmem_alloc(statuslen, kf);
367cab28b2dStaylor if (in_pktp->pkt_scbp == NULL)
368cab28b2dStaylor goto fail4;
369cab28b2dStaylor }
370cab28b2dStaylor if ((*tranp->tran_setup_pkt) (in_pktp,
371c6c44d06Sjw func, NULL) == -1) {
372cab28b2dStaylor goto fail5;
373cab28b2dStaylor }
374830363f4Staylor if (cmdlen)
375830363f4Staylor bzero((void *)in_pktp->pkt_cdbp, cmdlen);
376830363f4Staylor if (pplen)
377830363f4Staylor bzero((void *)in_pktp->pkt_private, pplen);
378830363f4Staylor if (statuslen)
379830363f4Staylor bzero((void *)in_pktp->pkt_scbp, statuslen);
3808faf39b2Staylor } else
3818faf39b2Staylor pktw = (struct scsi_pkt_cache_wrapper *)in_pktp;
3828faf39b2Staylor
383cab28b2dStaylor if (bp && bp->b_bcount) {
3848faf39b2Staylor
3858faf39b2Staylor int dma_flags = 0;
3868faf39b2Staylor
3878faf39b2Staylor /*
3888faf39b2Staylor * we need to transfer data, so we alloc dma resources
3898faf39b2Staylor * for this packet
3908faf39b2Staylor */
3918faf39b2Staylor /*CONSTCOND*/
3928faf39b2Staylor ASSERT(SLEEP_FUNC == DDI_DMA_SLEEP);
3938faf39b2Staylor /*CONSTCOND*/
3948faf39b2Staylor ASSERT(NULL_FUNC == DDI_DMA_DONTWAIT);
3958faf39b2Staylor
3968faf39b2Staylor #if defined(_DMA_USES_PHYSADDR)
3978faf39b2Staylor /*
3988faf39b2Staylor * with an IOMMU we map everything, so we don't
3998faf39b2Staylor * need to bother with this
4008faf39b2Staylor */
4018faf39b2Staylor if (tranp->tran_dma_attr.dma_attr_granular !=
402c6c44d06Sjw pktw->pcw_granular) {
4038faf39b2Staylor
4048faf39b2Staylor ddi_dma_free_handle(&in_pktp->pkt_handle);
4058faf39b2Staylor if (ddi_dma_alloc_handle(tranp->tran_hba_dip,
406c6c44d06Sjw &tranp->tran_dma_attr,
407c6c44d06Sjw func, NULL,
408c6c44d06Sjw &in_pktp->pkt_handle) != DDI_SUCCESS) {
4098faf39b2Staylor
4108faf39b2Staylor in_pktp->pkt_handle = NULL;
4118faf39b2Staylor return (NULL);
4128faf39b2Staylor }
4138faf39b2Staylor pktw->pcw_granular =
414c6c44d06Sjw tranp->tran_dma_attr.dma_attr_granular;
415cab28b2dStaylor }
4168faf39b2Staylor #endif
4178faf39b2Staylor
4188faf39b2Staylor if (in_pktp->pkt_numcookies == 0) {
4198faf39b2Staylor pktw->pcw_bp = bp;
4208faf39b2Staylor /*
4218faf39b2Staylor * set dma flags; the "read" case must be first
4228faf39b2Staylor * since B_WRITE isn't always be set for writes.
4238faf39b2Staylor */
4248faf39b2Staylor if (bp->b_flags & B_READ) {
4258faf39b2Staylor dma_flags |= DDI_DMA_READ;
4268faf39b2Staylor } else {
4278faf39b2Staylor dma_flags |= DDI_DMA_WRITE;
4288faf39b2Staylor }
4298faf39b2Staylor if (flags & PKT_CONSISTENT)
4308faf39b2Staylor dma_flags |= DDI_DMA_CONSISTENT;
4318faf39b2Staylor if (flags & PKT_DMA_PARTIAL)
4328faf39b2Staylor dma_flags |= DDI_DMA_PARTIAL;
4338faf39b2Staylor
4348faf39b2Staylor #if defined(__sparc)
4358faf39b2Staylor /*
4368faf39b2Staylor * workaround for byte hole issue on psycho and
4378faf39b2Staylor * schizo pre 2.1
4388faf39b2Staylor */
4398faf39b2Staylor if ((bp->b_flags & B_READ) && ((bp->b_flags &
4408faf39b2Staylor (B_PAGEIO|B_REMAPPED)) != B_PAGEIO) &&
4418faf39b2Staylor (((uintptr_t)bp->b_un.b_addr & 0x7) ||
4428faf39b2Staylor ((uintptr_t)bp->b_bcount & 0x7))) {
4438faf39b2Staylor dma_flags |= DDI_DMA_CONSISTENT;
4448faf39b2Staylor }
4458faf39b2Staylor #endif
4468faf39b2Staylor if (!scsi_dma_buf_bind_attr(pktw, bp,
4478faf39b2Staylor dma_flags, callback, callback_arg)) {
4488faf39b2Staylor return (NULL);
4498faf39b2Staylor } else {
4508faf39b2Staylor pktw->pcw_flags |= PCW_BOUND;
4518faf39b2Staylor }
4528faf39b2Staylor }
4538faf39b2Staylor
4548faf39b2Staylor #if defined(_DMA_USES_PHYSADDR)
4558faf39b2Staylor if (!scsi_dmaget_attr(pktw)) {
4568faf39b2Staylor scsi_dmafree_attr(in_pktp);
4578faf39b2Staylor goto fail5;
4588faf39b2Staylor }
4598faf39b2Staylor #else
4608faf39b2Staylor in_pktp->pkt_cookies = &pktw->pcw_cookie;
4618faf39b2Staylor in_pktp->pkt_dma_len = pktw->pcw_cookie.dmac_size;
4628faf39b2Staylor pktw->pcw_total_xfer += in_pktp->pkt_dma_len;
4638faf39b2Staylor #endif
4648faf39b2Staylor ASSERT(in_pktp->pkt_numcookies <=
465c6c44d06Sjw tranp->tran_dma_attr.dma_attr_sgllen);
4668faf39b2Staylor ASSERT(pktw->pcw_total_xfer <= bp->b_bcount);
4678faf39b2Staylor in_pktp->pkt_resid = bp->b_bcount -
468c6c44d06Sjw pktw->pcw_total_xfer;
4698faf39b2Staylor
4708faf39b2Staylor ASSERT((in_pktp->pkt_resid % pktw->pcw_granular) ==
471c6c44d06Sjw 0);
4728faf39b2Staylor } else {
4738faf39b2Staylor /* !bp or no b_bcount */
4748faf39b2Staylor in_pktp->pkt_resid = 0;
475cab28b2dStaylor }
476cab28b2dStaylor return (in_pktp);
477cab28b2dStaylor
478cab28b2dStaylor fail5:
4798faf39b2Staylor if (pktw->pcw_flags & PCW_NEED_EXT_SCB) {
480cab28b2dStaylor kmem_free(in_pktp->pkt_scbp, statuslen);
481cab28b2dStaylor in_pktp->pkt_scbp = (opaque_t)((char *)in_pktp +
482cab28b2dStaylor tranp->tran_hba_len + DEFAULT_PRIVLEN +
48366027529SNikko He sizeof (struct scsi_pkt_cache_wrapper));
484cab28b2dStaylor if ((A_TO_TRAN(ap))->tran_hba_flags & SCSI_HBA_TRAN_CDB)
485cab28b2dStaylor in_pktp->pkt_scbp = (opaque_t)((in_pktp->pkt_scbp) +
486c6c44d06Sjw DEFAULT_CDBLEN);
487cab28b2dStaylor in_pktp->pkt_scblen = 0;
488cab28b2dStaylor }
489cab28b2dStaylor fail4:
4908faf39b2Staylor if (pktw->pcw_flags & PCW_NEED_EXT_TGT) {
491cab28b2dStaylor kmem_free(in_pktp->pkt_private, pplen);
492cab28b2dStaylor in_pktp->pkt_tgtlen = 0;
493cab28b2dStaylor in_pktp->pkt_private = NULL;
494cab28b2dStaylor }
495cab28b2dStaylor fail3:
4968faf39b2Staylor if (pktw->pcw_flags & PCW_NEED_EXT_CDB) {
497cab28b2dStaylor kmem_free(in_pktp->pkt_cdbp, cmdlen);
498cab28b2dStaylor in_pktp->pkt_cdbp = (opaque_t)((char *)in_pktp +
499cab28b2dStaylor tranp->tran_hba_len +
50066027529SNikko He sizeof (struct scsi_pkt_cache_wrapper));
501cab28b2dStaylor in_pktp->pkt_cdblen = 0;
502cab28b2dStaylor }
5038faf39b2Staylor pktw->pcw_flags &=
5048faf39b2Staylor ~(PCW_NEED_EXT_CDB|PCW_NEED_EXT_TGT|PCW_NEED_EXT_SCB);
505cab28b2dStaylor fail2:
506cab28b2dStaylor kmem_cache_free(tranp->tran_pkt_cache_ptr, pktw);
507cab28b2dStaylor fail1:
508cab28b2dStaylor if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
509cab28b2dStaylor ddi_set_callback(callback, callback_arg,
510c6c44d06Sjw &scsi_callback_id);
511cab28b2dStaylor }
512cab28b2dStaylor
513cab28b2dStaylor return (NULL);
514cab28b2dStaylor }
515cab28b2dStaylor
516cab28b2dStaylor void
scsi_free_cache_pkt(struct scsi_address * ap,struct scsi_pkt * pktp)517cab28b2dStaylor scsi_free_cache_pkt(struct scsi_address *ap, struct scsi_pkt *pktp)
518cab28b2dStaylor {
519cab28b2dStaylor struct scsi_pkt_cache_wrapper *pktw;
520cab28b2dStaylor
521cab28b2dStaylor (*A_TO_TRAN(ap)->tran_teardown_pkt)(pktp);
522cab28b2dStaylor pktw = (struct scsi_pkt_cache_wrapper *)pktp;
5238faf39b2Staylor if (pktw->pcw_flags & PCW_BOUND)
5248faf39b2Staylor scsi_dmafree_attr(pktp);
525cab28b2dStaylor
526cab28b2dStaylor /*
527cab28b2dStaylor * if we allocated memory for anything that wouldn't fit, free
528cab28b2dStaylor * the memory and restore the pointers
529cab28b2dStaylor */
5308faf39b2Staylor if (pktw->pcw_flags & PCW_NEED_EXT_SCB) {
531cab28b2dStaylor kmem_free(pktp->pkt_scbp, pktp->pkt_scblen);
532cab28b2dStaylor pktp->pkt_scbp = (opaque_t)((char *)pktp +
533cab28b2dStaylor (A_TO_TRAN(ap))->tran_hba_len +
534cab28b2dStaylor DEFAULT_PRIVLEN + sizeof (struct scsi_pkt_cache_wrapper));
535cab28b2dStaylor if ((A_TO_TRAN(ap))->tran_hba_flags & SCSI_HBA_TRAN_CDB)
536cab28b2dStaylor pktp->pkt_scbp = (opaque_t)((pktp->pkt_scbp) +
537c6c44d06Sjw DEFAULT_CDBLEN);
538cab28b2dStaylor pktp->pkt_scblen = 0;
539cab28b2dStaylor }
5408faf39b2Staylor if (pktw->pcw_flags & PCW_NEED_EXT_TGT) {
541cab28b2dStaylor kmem_free(pktp->pkt_private, pktp->pkt_tgtlen);
542cab28b2dStaylor pktp->pkt_tgtlen = 0;
543cab28b2dStaylor pktp->pkt_private = NULL;
544cab28b2dStaylor }
5458faf39b2Staylor if (pktw->pcw_flags & PCW_NEED_EXT_CDB) {
546cab28b2dStaylor kmem_free(pktp->pkt_cdbp, pktp->pkt_cdblen);
547cab28b2dStaylor pktp->pkt_cdbp = (opaque_t)((char *)pktp +
548cab28b2dStaylor (A_TO_TRAN(ap))->tran_hba_len +
549cab28b2dStaylor sizeof (struct scsi_pkt_cache_wrapper));
550cab28b2dStaylor pktp->pkt_cdblen = 0;
551cab28b2dStaylor }
5528faf39b2Staylor pktw->pcw_flags &=
5538faf39b2Staylor ~(PCW_NEED_EXT_CDB|PCW_NEED_EXT_TGT|PCW_NEED_EXT_SCB);
554cab28b2dStaylor kmem_cache_free(A_TO_TRAN(ap)->tran_pkt_cache_ptr, pktw);
555cab28b2dStaylor
556cab28b2dStaylor if (scsi_callback_id != 0) {
557cab28b2dStaylor ddi_run_callback(&scsi_callback_id);
558cab28b2dStaylor }
559cab28b2dStaylor
560cab28b2dStaylor }
561cab28b2dStaylor
5628faf39b2Staylor
5637c478bd9Sstevel@tonic-gate struct scsi_pkt *
scsi_init_pkt(struct scsi_address * ap,struct scsi_pkt * in_pktp,struct buf * bp,int cmdlen,int statuslen,int pplen,int flags,int (* callback)(caddr_t),caddr_t callback_arg)5647c478bd9Sstevel@tonic-gate scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *in_pktp,
5657c478bd9Sstevel@tonic-gate struct buf *bp, int cmdlen, int statuslen, int pplen,
5667c478bd9Sstevel@tonic-gate int flags, int (*callback)(caddr_t), caddr_t callback_arg)
5677c478bd9Sstevel@tonic-gate {
5687c478bd9Sstevel@tonic-gate struct scsi_pkt *pktp;
5697c478bd9Sstevel@tonic-gate scsi_hba_tran_t *tranp = ap->a_hba_tran;
5707c478bd9Sstevel@tonic-gate int (*func)(caddr_t);
5717c478bd9Sstevel@tonic-gate
5727c478bd9Sstevel@tonic-gate TRACE_5(TR_FAC_SCSI_RES, TR_SCSI_INIT_PKT_START,
5737c478bd9Sstevel@tonic-gate "scsi_init_pkt_start: addr %p in_pktp %p cmdlen %d statuslen %d pplen %d",
5747c478bd9Sstevel@tonic-gate ap, in_pktp, cmdlen, statuslen, pplen);
5757c478bd9Sstevel@tonic-gate
576*86ef0a63SRichard Lowe #if defined(__x86)
5777c478bd9Sstevel@tonic-gate if (flags & PKT_CONSISTENT_OLD) {
5787c478bd9Sstevel@tonic-gate flags &= ~PKT_CONSISTENT_OLD;
5797c478bd9Sstevel@tonic-gate flags |= PKT_CONSISTENT;
5807c478bd9Sstevel@tonic-gate }
5817c478bd9Sstevel@tonic-gate #endif
5827c478bd9Sstevel@tonic-gate
5837c478bd9Sstevel@tonic-gate func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
5847c478bd9Sstevel@tonic-gate
5857c478bd9Sstevel@tonic-gate pktp = (*tranp->tran_init_pkt) (ap, in_pktp, bp, cmdlen,
586c6c44d06Sjw statuslen, pplen, flags, func, NULL);
5877c478bd9Sstevel@tonic-gate if (pktp == NULL) {
5887c478bd9Sstevel@tonic-gate if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
5897c478bd9Sstevel@tonic-gate ddi_set_callback(callback, callback_arg,
590c6c44d06Sjw &scsi_callback_id);
5917c478bd9Sstevel@tonic-gate }
5927c478bd9Sstevel@tonic-gate }
5937c478bd9Sstevel@tonic-gate
5947c478bd9Sstevel@tonic-gate TRACE_1(TR_FAC_SCSI_RES, TR_SCSI_INIT_PKT_END,
595c6c44d06Sjw "scsi_init_pkt_end: pktp %p", pktp);
5967c478bd9Sstevel@tonic-gate return (pktp);
5977c478bd9Sstevel@tonic-gate }
5987c478bd9Sstevel@tonic-gate
5997c478bd9Sstevel@tonic-gate void
scsi_destroy_pkt(struct scsi_pkt * pkt)6007c478bd9Sstevel@tonic-gate scsi_destroy_pkt(struct scsi_pkt *pkt)
6017c478bd9Sstevel@tonic-gate {
6027c478bd9Sstevel@tonic-gate struct scsi_address *ap = P_TO_ADDR(pkt);
6037c478bd9Sstevel@tonic-gate
6047c478bd9Sstevel@tonic-gate TRACE_1(TR_FAC_SCSI_RES, TR_SCSI_DESTROY_PKT_START,
605c6c44d06Sjw "scsi_destroy_pkt_start: pkt %p", pkt);
6067c478bd9Sstevel@tonic-gate
6077c478bd9Sstevel@tonic-gate (*A_TO_TRAN(ap)->tran_destroy_pkt)(ap, pkt);
6087c478bd9Sstevel@tonic-gate
6097c478bd9Sstevel@tonic-gate if (scsi_callback_id != 0) {
6107c478bd9Sstevel@tonic-gate ddi_run_callback(&scsi_callback_id);
6117c478bd9Sstevel@tonic-gate }
6127c478bd9Sstevel@tonic-gate
6137c478bd9Sstevel@tonic-gate TRACE_0(TR_FAC_SCSI_RES, TR_SCSI_DESTROY_PKT_END,
614c6c44d06Sjw "scsi_destroy_pkt_end");
6157c478bd9Sstevel@tonic-gate }
6167c478bd9Sstevel@tonic-gate
6177c478bd9Sstevel@tonic-gate
6187c478bd9Sstevel@tonic-gate /*
6197c478bd9Sstevel@tonic-gate * Generic Resource Allocation Routines
6207c478bd9Sstevel@tonic-gate */
6217c478bd9Sstevel@tonic-gate
6227c478bd9Sstevel@tonic-gate struct scsi_pkt *
scsi_resalloc(struct scsi_address * ap,int cmdlen,int statuslen,opaque_t dmatoken,int (* callback)())6237c478bd9Sstevel@tonic-gate scsi_resalloc(struct scsi_address *ap, int cmdlen, int statuslen,
6247c478bd9Sstevel@tonic-gate opaque_t dmatoken, int (*callback)())
6257c478bd9Sstevel@tonic-gate {
6267c478bd9Sstevel@tonic-gate register struct scsi_pkt *pkt;
6277c478bd9Sstevel@tonic-gate register scsi_hba_tran_t *tranp = ap->a_hba_tran;
6287c478bd9Sstevel@tonic-gate register int (*func)(caddr_t);
6297c478bd9Sstevel@tonic-gate
6307c478bd9Sstevel@tonic-gate func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
6317c478bd9Sstevel@tonic-gate
6327c478bd9Sstevel@tonic-gate pkt = (*tranp->tran_init_pkt) (ap, NULL, (struct buf *)dmatoken,
633c6c44d06Sjw cmdlen, statuslen, 0, 0, func, NULL);
6347c478bd9Sstevel@tonic-gate if (pkt == NULL) {
6357c478bd9Sstevel@tonic-gate if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
6367c478bd9Sstevel@tonic-gate ddi_set_callback(callback, NULL, &scsi_callback_id);
6377c478bd9Sstevel@tonic-gate }
6387c478bd9Sstevel@tonic-gate }
6397c478bd9Sstevel@tonic-gate
6407c478bd9Sstevel@tonic-gate return (pkt);
6417c478bd9Sstevel@tonic-gate }
6427c478bd9Sstevel@tonic-gate
6437c478bd9Sstevel@tonic-gate struct scsi_pkt *
scsi_pktalloc(struct scsi_address * ap,int cmdlen,int statuslen,int (* callback)())6447c478bd9Sstevel@tonic-gate scsi_pktalloc(struct scsi_address *ap, int cmdlen, int statuslen,
6457c478bd9Sstevel@tonic-gate int (*callback)())
6467c478bd9Sstevel@tonic-gate {
6477c478bd9Sstevel@tonic-gate struct scsi_pkt *pkt;
6487c478bd9Sstevel@tonic-gate struct scsi_hba_tran *tran = ap->a_hba_tran;
6497c478bd9Sstevel@tonic-gate register int (*func)(caddr_t);
6507c478bd9Sstevel@tonic-gate
6517c478bd9Sstevel@tonic-gate func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
6527c478bd9Sstevel@tonic-gate
6537c478bd9Sstevel@tonic-gate pkt = (*tran->tran_init_pkt) (ap, NULL, NULL, cmdlen,
654c6c44d06Sjw statuslen, 0, 0, func, NULL);
6557c478bd9Sstevel@tonic-gate if (pkt == NULL) {
6567c478bd9Sstevel@tonic-gate if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
6577c478bd9Sstevel@tonic-gate ddi_set_callback(callback, NULL, &scsi_callback_id);
6587c478bd9Sstevel@tonic-gate }
6597c478bd9Sstevel@tonic-gate }
6607c478bd9Sstevel@tonic-gate
6617c478bd9Sstevel@tonic-gate return (pkt);
6627c478bd9Sstevel@tonic-gate }
6637c478bd9Sstevel@tonic-gate
6647c478bd9Sstevel@tonic-gate struct scsi_pkt *
scsi_dmaget(struct scsi_pkt * pkt,opaque_t dmatoken,int (* callback)())6657c478bd9Sstevel@tonic-gate scsi_dmaget(struct scsi_pkt *pkt, opaque_t dmatoken, int (*callback)())
6667c478bd9Sstevel@tonic-gate {
6677c478bd9Sstevel@tonic-gate struct scsi_pkt *new_pkt;
6687c478bd9Sstevel@tonic-gate register int (*func)(caddr_t);
6697c478bd9Sstevel@tonic-gate
6707c478bd9Sstevel@tonic-gate func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC;
6717c478bd9Sstevel@tonic-gate
6727c478bd9Sstevel@tonic-gate new_pkt = (*P_TO_TRAN(pkt)->tran_init_pkt) (&pkt->pkt_address,
673c6c44d06Sjw pkt, (struct buf *)dmatoken,
674c6c44d06Sjw 0, 0, 0, 0, func, NULL);
6757c478bd9Sstevel@tonic-gate ASSERT(new_pkt == pkt || new_pkt == NULL);
6767c478bd9Sstevel@tonic-gate if (new_pkt == NULL) {
6777c478bd9Sstevel@tonic-gate if (callback != NULL_FUNC && callback != SLEEP_FUNC) {
6787c478bd9Sstevel@tonic-gate ddi_set_callback(callback, NULL, &scsi_callback_id);
6797c478bd9Sstevel@tonic-gate }
6807c478bd9Sstevel@tonic-gate }
6817c478bd9Sstevel@tonic-gate
6827c478bd9Sstevel@tonic-gate return (new_pkt);
6837c478bd9Sstevel@tonic-gate }
6847c478bd9Sstevel@tonic-gate
6857c478bd9Sstevel@tonic-gate
6867c478bd9Sstevel@tonic-gate /*
6877c478bd9Sstevel@tonic-gate * Generic Resource Deallocation Routines
6887c478bd9Sstevel@tonic-gate */
6897c478bd9Sstevel@tonic-gate
6907c478bd9Sstevel@tonic-gate void
scsi_dmafree(struct scsi_pkt * pkt)6917c478bd9Sstevel@tonic-gate scsi_dmafree(struct scsi_pkt *pkt)
6927c478bd9Sstevel@tonic-gate {
6937c478bd9Sstevel@tonic-gate register struct scsi_address *ap = P_TO_ADDR(pkt);
6948faf39b2Staylor
6957c478bd9Sstevel@tonic-gate (*A_TO_TRAN(ap)->tran_dmafree)(ap, pkt);
6967c478bd9Sstevel@tonic-gate
6977c478bd9Sstevel@tonic-gate if (scsi_callback_id != 0) {
6987c478bd9Sstevel@tonic-gate ddi_run_callback(&scsi_callback_id);
6997c478bd9Sstevel@tonic-gate }
7007c478bd9Sstevel@tonic-gate }
7017c478bd9Sstevel@tonic-gate
7028faf39b2Staylor /*ARGSUSED*/
7038faf39b2Staylor void
scsi_cache_dmafree(struct scsi_address * ap,struct scsi_pkt * pkt)7048faf39b2Staylor scsi_cache_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
7058faf39b2Staylor {
706a231f2c8SNikko He ASSERT(pkt->pkt_numcookies == 0 ||
707a231f2c8SNikko He ((struct scsi_pkt_cache_wrapper *)pkt)->pcw_flags & PCW_BOUND);
7088faf39b2Staylor ASSERT(pkt->pkt_handle != NULL);
7098faf39b2Staylor scsi_dmafree_attr(pkt);
7108faf39b2Staylor
7118faf39b2Staylor if (scsi_callback_id != 0) {
7128faf39b2Staylor ddi_run_callback(&scsi_callback_id);
7138faf39b2Staylor }
7148faf39b2Staylor }
7158faf39b2Staylor
7167c478bd9Sstevel@tonic-gate void
scsi_sync_pkt(struct scsi_pkt * pkt)7177c478bd9Sstevel@tonic-gate scsi_sync_pkt(struct scsi_pkt *pkt)
7187c478bd9Sstevel@tonic-gate {
7197c478bd9Sstevel@tonic-gate register struct scsi_address *ap = P_TO_ADDR(pkt);
720c6c44d06Sjw
721c6c44d06Sjw if (pkt->pkt_state & STATE_XFERRED_DATA)
722c6c44d06Sjw (*A_TO_TRAN(ap)->tran_sync_pkt)(ap, pkt);
7237c478bd9Sstevel@tonic-gate }
7247c478bd9Sstevel@tonic-gate
7258faf39b2Staylor /*ARGSUSED*/
7268faf39b2Staylor void
scsi_sync_cache_pkt(struct scsi_address * ap,struct scsi_pkt * pkt)7278faf39b2Staylor scsi_sync_cache_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
7288faf39b2Staylor {
729afcdc791Scth if (pkt->pkt_handle &&
730afcdc791Scth (pkt->pkt_dma_flags & (DDI_DMA_WRITE | DDI_DMA_READ))) {
7318faf39b2Staylor (void) ddi_dma_sync(pkt->pkt_handle,
732afcdc791Scth pkt->pkt_dma_offset, pkt->pkt_dma_len,
733afcdc791Scth (pkt->pkt_dma_flags & DDI_DMA_WRITE) ?
734afcdc791Scth DDI_DMA_SYNC_FORDEV : DDI_DMA_SYNC_FORCPU);
7358faf39b2Staylor }
7368faf39b2Staylor }
7378faf39b2Staylor
7387c478bd9Sstevel@tonic-gate void
scsi_resfree(struct scsi_pkt * pkt)7397c478bd9Sstevel@tonic-gate scsi_resfree(struct scsi_pkt *pkt)
7407c478bd9Sstevel@tonic-gate {
7417c478bd9Sstevel@tonic-gate register struct scsi_address *ap = P_TO_ADDR(pkt);
7427c478bd9Sstevel@tonic-gate (*A_TO_TRAN(ap)->tran_destroy_pkt)(ap, pkt);
7437c478bd9Sstevel@tonic-gate
7447c478bd9Sstevel@tonic-gate if (scsi_callback_id != 0) {
7457c478bd9Sstevel@tonic-gate ddi_run_callback(&scsi_callback_id);
7467c478bd9Sstevel@tonic-gate }
7477c478bd9Sstevel@tonic-gate }
748