1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/scsi/scsi.h> 28 #include <sys/vtrace.h> 29 30 31 #define A_TO_TRAN(ap) ((ap)->a_hba_tran) 32 #define P_TO_TRAN(pkt) ((pkt)->pkt_address.a_hba_tran) 33 #define P_TO_ADDR(pkt) (&((pkt)->pkt_address)) 34 35 /* 36 * Callback id 37 */ 38 uintptr_t scsi_callback_id = 0; 39 40 extern ddi_dma_attr_t scsi_alloc_attr; 41 42 struct buf * 43 scsi_alloc_consistent_buf(struct scsi_address *ap, 44 struct buf *in_bp, size_t datalen, uint_t bflags, 45 int (*callback)(caddr_t), caddr_t callback_arg) 46 { 47 dev_info_t *pdip; 48 struct buf *bp; 49 int kmflag; 50 size_t rlen; 51 52 TRACE_0(TR_FAC_SCSI_RES, TR_SCSI_ALLOC_CONSISTENT_BUF_START, 53 "scsi_alloc_consistent_buf_start"); 54 55 if (!in_bp) { 56 kmflag = (callback == SLEEP_FUNC) ? KM_SLEEP : KM_NOSLEEP; 57 if ((bp = getrbuf(kmflag)) == NULL) { 58 goto no_resource; 59 } 60 } else { 61 bp = in_bp; 62 63 /* we are establishing a new buffer memory association */ 64 bp->b_flags &= ~(B_PAGEIO | B_PHYS | B_REMAPPED | B_SHADOW); 65 bp->b_proc = NULL; 66 bp->b_pages = NULL; 67 bp->b_shadow = NULL; 68 } 69 70 /* limit bits that can be set by bflags argument */ 71 ASSERT(!(bflags & ~(B_READ | B_WRITE))); 72 bflags &= (B_READ | B_WRITE); 73 bp->b_un.b_addr = 0; 74 75 if (datalen) { 76 pdip = (A_TO_TRAN(ap))->tran_hba_dip; 77 78 /* 79 * use i_ddi_mem_alloc() for now until we have an interface to 80 * allocate memory for DMA which doesn't require a DMA handle. 81 * ddi_iopb_alloc() is obsolete and we want more flexibility in 82 * controlling the DMA address constraints. 83 */ 84 while (i_ddi_mem_alloc(pdip, &scsi_alloc_attr, datalen, 85 ((callback == SLEEP_FUNC) ? 1 : 0), 0, NULL, 86 &bp->b_un.b_addr, &rlen, NULL) != DDI_SUCCESS) { 87 if (callback == SLEEP_FUNC) { 88 delay(drv_usectohz(10000)); 89 } else { 90 if (!in_bp) 91 freerbuf(bp); 92 goto no_resource; 93 } 94 } 95 bp->b_flags |= bflags; 96 } 97 bp->b_bcount = datalen; 98 bp->b_resid = 0; 99 100 TRACE_0(TR_FAC_SCSI_RES, TR_SCSI_ALLOC_CONSISTENT_BUF_END, 101 "scsi_alloc_consistent_buf_end"); 102 return (bp); 103 104 no_resource: 105 106 if (callback != NULL_FUNC && callback != SLEEP_FUNC) { 107 ddi_set_callback(callback, callback_arg, 108 &scsi_callback_id); 109 } 110 TRACE_0(TR_FAC_SCSI_RES, 111 TR_SCSI_ALLOC_CONSISTENT_BUF_RETURN1_END, 112 "scsi_alloc_consistent_buf_end (return1)"); 113 return (NULL); 114 } 115 116 void 117 scsi_free_consistent_buf(struct buf *bp) 118 { 119 TRACE_0(TR_FAC_SCSI_RES, TR_SCSI_FREE_CONSISTENT_BUF_START, 120 "scsi_free_consistent_buf_start"); 121 if (!bp) 122 return; 123 if (bp->b_un.b_addr) 124 i_ddi_mem_free((caddr_t)bp->b_un.b_addr, NULL); 125 freerbuf(bp); 126 if (scsi_callback_id != 0) { 127 ddi_run_callback(&scsi_callback_id); 128 } 129 TRACE_0(TR_FAC_SCSI_RES, TR_SCSI_FREE_CONSISTENT_BUF_END, 130 "scsi_free_consistent_buf_end"); 131 } 132 133 void 134 scsi_dmafree_attr(struct scsi_pkt *pktp) 135 { 136 struct scsi_pkt_cache_wrapper *pktw = 137 (struct scsi_pkt_cache_wrapper *)pktp; 138 139 if (pktw->pcw_flags & PCW_BOUND) { 140 if (ddi_dma_unbind_handle(pktp->pkt_handle) != 141 DDI_SUCCESS) 142 cmn_err(CE_WARN, "scsi_dmafree_attr: " 143 "unbind handle failed"); 144 pktw->pcw_flags &= ~PCW_BOUND; 145 } 146 pktp->pkt_numcookies = 0; 147 pktw->pcw_totalwin = 0; 148 } 149 150 struct buf * 151 scsi_pkt2bp(struct scsi_pkt *pkt) 152 { 153 return (((struct scsi_pkt_cache_wrapper *)pkt)->pcw_bp); 154 } 155 156 int 157 scsi_dma_buf_bind_attr(struct scsi_pkt_cache_wrapper *pktw, 158 struct buf *bp, 159 int dma_flags, 160 int (*callback)(), 161 caddr_t arg) 162 { 163 struct scsi_pkt *pktp = &(pktw->pcw_pkt); 164 int status; 165 166 /* 167 * First time, need to establish the handle. 168 */ 169 170 ASSERT(pktp->pkt_numcookies == 0); 171 ASSERT(pktw->pcw_totalwin == 0); 172 173 status = ddi_dma_buf_bind_handle(pktp->pkt_handle, bp, dma_flags, 174 callback, arg, &pktw->pcw_cookie, 175 &pktp->pkt_numcookies); 176 177 switch (status) { 178 case DDI_DMA_MAPPED: 179 pktw->pcw_totalwin = 1; 180 break; 181 182 case DDI_DMA_PARTIAL_MAP: 183 /* enable first call to ddi_dma_getwin */ 184 if (ddi_dma_numwin(pktp->pkt_handle, 185 &pktw->pcw_totalwin) != DDI_SUCCESS) { 186 bp->b_error = 0; 187 return (0); 188 } 189 break; 190 191 case DDI_DMA_NORESOURCES: 192 bp->b_error = 0; 193 return (0); 194 195 case DDI_DMA_TOOBIG: 196 bioerror(bp, EINVAL); 197 return (0); 198 199 case DDI_DMA_NOMAPPING: 200 case DDI_DMA_INUSE: 201 default: 202 bioerror(bp, EFAULT); 203 return (0); 204 } 205 206 /* initialize the loop controls for scsi_dmaget_attr() */ 207 pktw->pcw_curwin = 0; 208 pktw->pcw_total_xfer = 0; 209 pktp->pkt_dma_flags = dma_flags; 210 return (1); 211 } 212 213 #if defined(_DMA_USES_PHYSADDR) 214 int 215 scsi_dmaget_attr(struct scsi_pkt_cache_wrapper *pktw) 216 { 217 struct scsi_pkt *pktp = &(pktw->pcw_pkt); 218 219 int status; 220 int num_segs = 0; 221 ddi_dma_impl_t *hp = (ddi_dma_impl_t *)pktp->pkt_handle; 222 ddi_dma_cookie_t *cp; 223 224 if (pktw->pcw_curwin != 0) { 225 ddi_dma_cookie_t cookie; 226 227 /* 228 * start the next window, and get its first cookie 229 */ 230 status = ddi_dma_getwin(pktp->pkt_handle, 231 pktw->pcw_curwin, &pktp->pkt_dma_offset, 232 &pktp->pkt_dma_len, &cookie, 233 &pktp->pkt_numcookies); 234 if (status != DDI_SUCCESS) 235 return (0); 236 } 237 238 /* 239 * start the Scatter/Gather loop 240 */ 241 cp = hp->dmai_cookie - 1; 242 pktp->pkt_dma_len = 0; 243 for (;;) { 244 245 /* take care of the loop-bookkeeping */ 246 pktp->pkt_dma_len += cp->dmac_size; 247 num_segs++; 248 /* 249 * if this was the last cookie in the current window 250 * set the loop controls start the next window and 251 * exit so the HBA can do this partial transfer 252 */ 253 if (num_segs >= pktp->pkt_numcookies) { 254 pktw->pcw_curwin++; 255 break; 256 } 257 258 cp++; 259 } 260 pktw->pcw_total_xfer += pktp->pkt_dma_len; 261 pktp->pkt_cookies = hp->dmai_cookie - 1; 262 hp->dmai_cookie = cp; 263 264 return (1); 265 } 266 #endif 267 268 void scsi_free_cache_pkt(struct scsi_address *, struct scsi_pkt *); 269 270 struct scsi_pkt * 271 scsi_init_cache_pkt(struct scsi_address *ap, struct scsi_pkt *in_pktp, 272 struct buf *bp, int cmdlen, int statuslen, int pplen, 273 int flags, int (*callback)(caddr_t), caddr_t callback_arg) 274 { 275 struct scsi_pkt_cache_wrapper *pktw; 276 scsi_hba_tran_t *tranp = ap->a_hba_tran; 277 int (*func)(caddr_t); 278 279 func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC; 280 281 if (in_pktp == NULL) { 282 int kf; 283 284 if (callback == SLEEP_FUNC) 285 kf = KM_SLEEP; 286 else 287 kf = KM_NOSLEEP; 288 pktw = kmem_cache_alloc(tranp->tran_pkt_cache_ptr, 289 kf); 290 if (pktw == NULL) 291 goto fail1; 292 293 pktw->pcw_flags = 0; 294 in_pktp = &(pktw->pcw_pkt); 295 in_pktp->pkt_address = *ap; 296 /* 297 * target drivers should initialize pkt_comp and 298 * pkt_time, but sometimes they don't so initialize 299 * them here to be safe. 300 */ 301 in_pktp->pkt_address = *ap; 302 in_pktp->pkt_flags = 0; 303 in_pktp->pkt_time = 0; 304 in_pktp->pkt_resid = 0; 305 in_pktp->pkt_state = 0; 306 in_pktp->pkt_statistics = 0; 307 in_pktp->pkt_reason = 0; 308 in_pktp->pkt_dma_offset = 0; 309 in_pktp->pkt_dma_len = 0; 310 in_pktp->pkt_dma_flags = 0; 311 in_pktp->pkt_path_instance = 0; 312 ASSERT(in_pktp->pkt_numcookies == 0); 313 pktw->pcw_curwin = 0; 314 pktw->pcw_totalwin = 0; 315 pktw->pcw_total_xfer = 0; 316 317 in_pktp->pkt_cdblen = cmdlen; 318 if ((tranp->tran_hba_flags & SCSI_HBA_TRAN_CDB) && 319 (cmdlen > DEFAULT_CDBLEN)) { 320 pktw->pcw_flags |= PCW_NEED_EXT_CDB; 321 in_pktp->pkt_cdbp = kmem_alloc(cmdlen, kf); 322 if (in_pktp->pkt_cdbp == NULL) 323 goto fail2; 324 } 325 in_pktp->pkt_tgtlen = pplen; 326 if (pplen > DEFAULT_PRIVLEN) { 327 pktw->pcw_flags |= PCW_NEED_EXT_TGT; 328 in_pktp->pkt_private = kmem_alloc(pplen, kf); 329 if (in_pktp->pkt_private == NULL) 330 goto fail3; 331 } 332 in_pktp->pkt_scblen = statuslen; 333 if ((tranp->tran_hba_flags & SCSI_HBA_TRAN_SCB) && 334 (statuslen > DEFAULT_SCBLEN)) { 335 pktw->pcw_flags |= PCW_NEED_EXT_SCB; 336 in_pktp->pkt_scbp = kmem_alloc(statuslen, kf); 337 if (in_pktp->pkt_scbp == NULL) 338 goto fail4; 339 } 340 if ((*tranp->tran_setup_pkt) (in_pktp, 341 func, NULL) == -1) { 342 goto fail5; 343 } 344 if (cmdlen) 345 bzero((void *)in_pktp->pkt_cdbp, cmdlen); 346 if (pplen) 347 bzero((void *)in_pktp->pkt_private, pplen); 348 if (statuslen) 349 bzero((void *)in_pktp->pkt_scbp, statuslen); 350 } else 351 pktw = (struct scsi_pkt_cache_wrapper *)in_pktp; 352 353 if (bp && bp->b_bcount) { 354 355 int dma_flags = 0; 356 357 /* 358 * we need to transfer data, so we alloc dma resources 359 * for this packet 360 */ 361 /*CONSTCOND*/ 362 ASSERT(SLEEP_FUNC == DDI_DMA_SLEEP); 363 /*CONSTCOND*/ 364 ASSERT(NULL_FUNC == DDI_DMA_DONTWAIT); 365 366 #if defined(_DMA_USES_PHYSADDR) 367 /* 368 * with an IOMMU we map everything, so we don't 369 * need to bother with this 370 */ 371 if (tranp->tran_dma_attr.dma_attr_granular != 372 pktw->pcw_granular) { 373 374 ddi_dma_free_handle(&in_pktp->pkt_handle); 375 if (ddi_dma_alloc_handle(tranp->tran_hba_dip, 376 &tranp->tran_dma_attr, 377 func, NULL, 378 &in_pktp->pkt_handle) != DDI_SUCCESS) { 379 380 in_pktp->pkt_handle = NULL; 381 return (NULL); 382 } 383 pktw->pcw_granular = 384 tranp->tran_dma_attr.dma_attr_granular; 385 } 386 #endif 387 388 if (in_pktp->pkt_numcookies == 0) { 389 pktw->pcw_bp = bp; 390 /* 391 * set dma flags; the "read" case must be first 392 * since B_WRITE isn't always be set for writes. 393 */ 394 if (bp->b_flags & B_READ) { 395 dma_flags |= DDI_DMA_READ; 396 } else { 397 dma_flags |= DDI_DMA_WRITE; 398 } 399 if (flags & PKT_CONSISTENT) 400 dma_flags |= DDI_DMA_CONSISTENT; 401 if (flags & PKT_DMA_PARTIAL) 402 dma_flags |= DDI_DMA_PARTIAL; 403 404 #if defined(__sparc) 405 /* 406 * workaround for byte hole issue on psycho and 407 * schizo pre 2.1 408 */ 409 if ((bp->b_flags & B_READ) && ((bp->b_flags & 410 (B_PAGEIO|B_REMAPPED)) != B_PAGEIO) && 411 (((uintptr_t)bp->b_un.b_addr & 0x7) || 412 ((uintptr_t)bp->b_bcount & 0x7))) { 413 dma_flags |= DDI_DMA_CONSISTENT; 414 } 415 #endif 416 if (!scsi_dma_buf_bind_attr(pktw, bp, 417 dma_flags, callback, callback_arg)) { 418 return (NULL); 419 } else { 420 pktw->pcw_flags |= PCW_BOUND; 421 } 422 } 423 424 #if defined(_DMA_USES_PHYSADDR) 425 if (!scsi_dmaget_attr(pktw)) { 426 scsi_dmafree_attr(in_pktp); 427 goto fail5; 428 } 429 #else 430 in_pktp->pkt_cookies = &pktw->pcw_cookie; 431 in_pktp->pkt_dma_len = pktw->pcw_cookie.dmac_size; 432 pktw->pcw_total_xfer += in_pktp->pkt_dma_len; 433 #endif 434 ASSERT(in_pktp->pkt_numcookies <= 435 tranp->tran_dma_attr.dma_attr_sgllen); 436 ASSERT(pktw->pcw_total_xfer <= bp->b_bcount); 437 in_pktp->pkt_resid = bp->b_bcount - 438 pktw->pcw_total_xfer; 439 440 ASSERT((in_pktp->pkt_resid % pktw->pcw_granular) == 441 0); 442 } else { 443 /* !bp or no b_bcount */ 444 in_pktp->pkt_resid = 0; 445 } 446 return (in_pktp); 447 448 fail5: 449 if (pktw->pcw_flags & PCW_NEED_EXT_SCB) { 450 kmem_free(in_pktp->pkt_scbp, statuslen); 451 in_pktp->pkt_scbp = (opaque_t)((char *)in_pktp + 452 tranp->tran_hba_len + DEFAULT_PRIVLEN + 453 sizeof (struct scsi_pkt)); 454 if ((A_TO_TRAN(ap))->tran_hba_flags & SCSI_HBA_TRAN_CDB) 455 in_pktp->pkt_scbp = (opaque_t)((in_pktp->pkt_scbp) + 456 DEFAULT_CDBLEN); 457 in_pktp->pkt_scblen = 0; 458 } 459 fail4: 460 if (pktw->pcw_flags & PCW_NEED_EXT_TGT) { 461 kmem_free(in_pktp->pkt_private, pplen); 462 in_pktp->pkt_tgtlen = 0; 463 in_pktp->pkt_private = NULL; 464 } 465 fail3: 466 if (pktw->pcw_flags & PCW_NEED_EXT_CDB) { 467 kmem_free(in_pktp->pkt_cdbp, cmdlen); 468 in_pktp->pkt_cdbp = (opaque_t)((char *)in_pktp + 469 tranp->tran_hba_len + 470 sizeof (struct scsi_pkt)); 471 in_pktp->pkt_cdblen = 0; 472 } 473 pktw->pcw_flags &= 474 ~(PCW_NEED_EXT_CDB|PCW_NEED_EXT_TGT|PCW_NEED_EXT_SCB); 475 fail2: 476 kmem_cache_free(tranp->tran_pkt_cache_ptr, pktw); 477 fail1: 478 if (callback != NULL_FUNC && callback != SLEEP_FUNC) { 479 ddi_set_callback(callback, callback_arg, 480 &scsi_callback_id); 481 } 482 483 return (NULL); 484 } 485 486 void 487 scsi_free_cache_pkt(struct scsi_address *ap, struct scsi_pkt *pktp) 488 { 489 struct scsi_pkt_cache_wrapper *pktw; 490 491 (*A_TO_TRAN(ap)->tran_teardown_pkt)(pktp); 492 pktw = (struct scsi_pkt_cache_wrapper *)pktp; 493 if (pktw->pcw_flags & PCW_BOUND) 494 scsi_dmafree_attr(pktp); 495 496 /* 497 * if we allocated memory for anything that wouldn't fit, free 498 * the memory and restore the pointers 499 */ 500 if (pktw->pcw_flags & PCW_NEED_EXT_SCB) { 501 kmem_free(pktp->pkt_scbp, pktp->pkt_scblen); 502 pktp->pkt_scbp = (opaque_t)((char *)pktp + 503 (A_TO_TRAN(ap))->tran_hba_len + 504 DEFAULT_PRIVLEN + sizeof (struct scsi_pkt_cache_wrapper)); 505 if ((A_TO_TRAN(ap))->tran_hba_flags & SCSI_HBA_TRAN_CDB) 506 pktp->pkt_scbp = (opaque_t)((pktp->pkt_scbp) + 507 DEFAULT_CDBLEN); 508 pktp->pkt_scblen = 0; 509 } 510 if (pktw->pcw_flags & PCW_NEED_EXT_TGT) { 511 kmem_free(pktp->pkt_private, pktp->pkt_tgtlen); 512 pktp->pkt_tgtlen = 0; 513 pktp->pkt_private = NULL; 514 } 515 if (pktw->pcw_flags & PCW_NEED_EXT_CDB) { 516 kmem_free(pktp->pkt_cdbp, pktp->pkt_cdblen); 517 pktp->pkt_cdbp = (opaque_t)((char *)pktp + 518 (A_TO_TRAN(ap))->tran_hba_len + 519 sizeof (struct scsi_pkt_cache_wrapper)); 520 pktp->pkt_cdblen = 0; 521 } 522 pktw->pcw_flags &= 523 ~(PCW_NEED_EXT_CDB|PCW_NEED_EXT_TGT|PCW_NEED_EXT_SCB); 524 kmem_cache_free(A_TO_TRAN(ap)->tran_pkt_cache_ptr, pktw); 525 526 if (scsi_callback_id != 0) { 527 ddi_run_callback(&scsi_callback_id); 528 } 529 530 } 531 532 533 struct scsi_pkt * 534 scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *in_pktp, 535 struct buf *bp, int cmdlen, int statuslen, int pplen, 536 int flags, int (*callback)(caddr_t), caddr_t callback_arg) 537 { 538 struct scsi_pkt *pktp; 539 scsi_hba_tran_t *tranp = ap->a_hba_tran; 540 int (*func)(caddr_t); 541 542 TRACE_5(TR_FAC_SCSI_RES, TR_SCSI_INIT_PKT_START, 543 "scsi_init_pkt_start: addr %p in_pktp %p cmdlen %d statuslen %d pplen %d", 544 ap, in_pktp, cmdlen, statuslen, pplen); 545 546 #if defined(__i386) || defined(__amd64) 547 if (flags & PKT_CONSISTENT_OLD) { 548 flags &= ~PKT_CONSISTENT_OLD; 549 flags |= PKT_CONSISTENT; 550 } 551 #endif 552 553 func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC; 554 555 pktp = (*tranp->tran_init_pkt) (ap, in_pktp, bp, cmdlen, 556 statuslen, pplen, flags, func, NULL); 557 if (pktp == NULL) { 558 if (callback != NULL_FUNC && callback != SLEEP_FUNC) { 559 ddi_set_callback(callback, callback_arg, 560 &scsi_callback_id); 561 } 562 } 563 564 TRACE_1(TR_FAC_SCSI_RES, TR_SCSI_INIT_PKT_END, 565 "scsi_init_pkt_end: pktp %p", pktp); 566 return (pktp); 567 } 568 569 void 570 scsi_destroy_pkt(struct scsi_pkt *pkt) 571 { 572 struct scsi_address *ap = P_TO_ADDR(pkt); 573 574 TRACE_1(TR_FAC_SCSI_RES, TR_SCSI_DESTROY_PKT_START, 575 "scsi_destroy_pkt_start: pkt %p", pkt); 576 577 (*A_TO_TRAN(ap)->tran_destroy_pkt)(ap, pkt); 578 579 if (scsi_callback_id != 0) { 580 ddi_run_callback(&scsi_callback_id); 581 } 582 583 TRACE_0(TR_FAC_SCSI_RES, TR_SCSI_DESTROY_PKT_END, 584 "scsi_destroy_pkt_end"); 585 } 586 587 588 /* 589 * Generic Resource Allocation Routines 590 */ 591 592 struct scsi_pkt * 593 scsi_resalloc(struct scsi_address *ap, int cmdlen, int statuslen, 594 opaque_t dmatoken, int (*callback)()) 595 { 596 register struct scsi_pkt *pkt; 597 register scsi_hba_tran_t *tranp = ap->a_hba_tran; 598 register int (*func)(caddr_t); 599 600 func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC; 601 602 pkt = (*tranp->tran_init_pkt) (ap, NULL, (struct buf *)dmatoken, 603 cmdlen, statuslen, 0, 0, func, NULL); 604 if (pkt == NULL) { 605 if (callback != NULL_FUNC && callback != SLEEP_FUNC) { 606 ddi_set_callback(callback, NULL, &scsi_callback_id); 607 } 608 } 609 610 return (pkt); 611 } 612 613 struct scsi_pkt * 614 scsi_pktalloc(struct scsi_address *ap, int cmdlen, int statuslen, 615 int (*callback)()) 616 { 617 struct scsi_pkt *pkt; 618 struct scsi_hba_tran *tran = ap->a_hba_tran; 619 register int (*func)(caddr_t); 620 621 func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC; 622 623 pkt = (*tran->tran_init_pkt) (ap, NULL, NULL, cmdlen, 624 statuslen, 0, 0, func, NULL); 625 if (pkt == NULL) { 626 if (callback != NULL_FUNC && callback != SLEEP_FUNC) { 627 ddi_set_callback(callback, NULL, &scsi_callback_id); 628 } 629 } 630 631 return (pkt); 632 } 633 634 struct scsi_pkt * 635 scsi_dmaget(struct scsi_pkt *pkt, opaque_t dmatoken, int (*callback)()) 636 { 637 struct scsi_pkt *new_pkt; 638 register int (*func)(caddr_t); 639 640 func = (callback == SLEEP_FUNC) ? SLEEP_FUNC : NULL_FUNC; 641 642 new_pkt = (*P_TO_TRAN(pkt)->tran_init_pkt) (&pkt->pkt_address, 643 pkt, (struct buf *)dmatoken, 644 0, 0, 0, 0, func, NULL); 645 ASSERT(new_pkt == pkt || new_pkt == NULL); 646 if (new_pkt == NULL) { 647 if (callback != NULL_FUNC && callback != SLEEP_FUNC) { 648 ddi_set_callback(callback, NULL, &scsi_callback_id); 649 } 650 } 651 652 return (new_pkt); 653 } 654 655 656 /* 657 * Generic Resource Deallocation Routines 658 */ 659 660 void 661 scsi_dmafree(struct scsi_pkt *pkt) 662 { 663 register struct scsi_address *ap = P_TO_ADDR(pkt); 664 665 (*A_TO_TRAN(ap)->tran_dmafree)(ap, pkt); 666 667 if (scsi_callback_id != 0) { 668 ddi_run_callback(&scsi_callback_id); 669 } 670 } 671 672 /*ARGSUSED*/ 673 void 674 scsi_cache_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt) 675 { 676 ASSERT(pkt->pkt_numcookies == 0 || 677 ((struct scsi_pkt_cache_wrapper *)pkt)->pcw_flags & PCW_BOUND); 678 ASSERT(pkt->pkt_handle != NULL); 679 scsi_dmafree_attr(pkt); 680 681 if (scsi_callback_id != 0) { 682 ddi_run_callback(&scsi_callback_id); 683 } 684 } 685 686 void 687 scsi_sync_pkt(struct scsi_pkt *pkt) 688 { 689 register struct scsi_address *ap = P_TO_ADDR(pkt); 690 691 if (pkt->pkt_state & STATE_XFERRED_DATA) 692 (*A_TO_TRAN(ap)->tran_sync_pkt)(ap, pkt); 693 } 694 695 /*ARGSUSED*/ 696 void 697 scsi_sync_cache_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) 698 { 699 if (pkt->pkt_handle && 700 (pkt->pkt_dma_flags & (DDI_DMA_WRITE | DDI_DMA_READ))) { 701 (void) ddi_dma_sync(pkt->pkt_handle, 702 pkt->pkt_dma_offset, pkt->pkt_dma_len, 703 (pkt->pkt_dma_flags & DDI_DMA_WRITE) ? 704 DDI_DMA_SYNC_FORDEV : DDI_DMA_SYNC_FORCPU); 705 } 706 } 707 708 void 709 scsi_resfree(struct scsi_pkt *pkt) 710 { 711 register struct scsi_address *ap = P_TO_ADDR(pkt); 712 (*A_TO_TRAN(ap)->tran_destroy_pkt)(ap, pkt); 713 714 if (scsi_callback_id != 0) { 715 ddi_run_callback(&scsi_callback_id); 716 } 717 } 718