1 /*- 2 * Copyright (c) 2012 EMC Corp. 3 * All rights reserved. 4 * 5 * Copyright (c) 1997, 1998 Justin T. Gibbs. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include "opt_bus.h" 34 35 #include <sys/param.h> 36 #include <sys/conf.h> 37 #include <sys/systm.h> 38 #include <sys/bio.h> 39 #include <sys/bus.h> 40 #include <sys/callout.h> 41 #include <sys/mbuf.h> 42 #include <sys/memdesc.h> 43 #include <sys/proc.h> 44 #include <sys/uio.h> 45 46 #include <vm/vm.h> 47 #include <vm/vm_page.h> 48 #include <vm/vm_map.h> 49 #include <vm/pmap.h> 50 51 #include <cam/cam.h> 52 #include <cam/cam_ccb.h> 53 54 #include <machine/bus.h> 55 56 /* 57 * Load a list of virtual addresses. 58 */ 59 static int 60 _bus_dmamap_load_vlist(bus_dma_tag_t dmat, bus_dmamap_t map, 61 bus_dma_segment_t *list, int sglist_cnt, struct pmap *pmap, int *nsegs, 62 int flags) 63 { 64 int error; 65 66 error = 0; 67 for (; sglist_cnt > 0; sglist_cnt--, list++) { 68 error = _bus_dmamap_load_buffer(dmat, map, 69 (void *)(uintptr_t)list->ds_addr, list->ds_len, pmap, 70 flags, NULL, nsegs); 71 if (error) 72 break; 73 } 74 return (error); 75 } 76 77 /* 78 * Load a list of physical addresses. 79 */ 80 static int 81 _bus_dmamap_load_plist(bus_dma_tag_t dmat, bus_dmamap_t map, 82 bus_dma_segment_t *list, int sglist_cnt, int *nsegs, int flags) 83 { 84 int error; 85 86 error = 0; 87 for (; sglist_cnt > 0; sglist_cnt--, list++) { 88 error = _bus_dmamap_load_phys(dmat, map, 89 (vm_paddr_t)list->ds_addr, list->ds_len, flags, NULL, 90 nsegs); 91 if (error) 92 break; 93 } 94 return (error); 95 } 96 97 /* 98 * Load an mbuf chain. 99 */ 100 static int 101 _bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, 102 struct mbuf *m0, bus_dma_segment_t *segs, int *nsegs, int flags) 103 { 104 struct mbuf *m; 105 int error; 106 107 error = 0; 108 for (m = m0; m != NULL && error == 0; m = m->m_next) { 109 if (m->m_len > 0) { 110 error = _bus_dmamap_load_buffer(dmat, map, m->m_data, 111 m->m_len, kernel_pmap, flags | BUS_DMA_LOAD_MBUF, 112 segs, nsegs); 113 } 114 } 115 CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", 116 __func__, dmat, flags, error, *nsegs); 117 return (error); 118 } 119 120 /* 121 * Load from block io. 122 */ 123 static int 124 _bus_dmamap_load_bio(bus_dma_tag_t dmat, bus_dmamap_t map, struct bio *bio, 125 int *nsegs, int flags) 126 { 127 int error; 128 129 if ((bio->bio_flags & BIO_UNMAPPED) == 0) { 130 error = _bus_dmamap_load_buffer(dmat, map, bio->bio_data, 131 bio->bio_bcount, kernel_pmap, flags, NULL, nsegs); 132 } else { 133 error = _bus_dmamap_load_ma(dmat, map, bio->bio_ma, 134 bio->bio_bcount, bio->bio_ma_offset, flags, NULL, nsegs); 135 } 136 return (error); 137 } 138 139 int 140 bus_dmamap_load_ma_triv(bus_dma_tag_t dmat, bus_dmamap_t map, 141 struct vm_page **ma, bus_size_t tlen, int ma_offs, int flags, 142 bus_dma_segment_t *segs, int *segp) 143 { 144 vm_paddr_t paddr; 145 bus_size_t len; 146 int error, i; 147 148 error = 0; 149 for (i = 0; tlen > 0; i++, tlen -= len) { 150 len = min(PAGE_SIZE - ma_offs, tlen); 151 paddr = VM_PAGE_TO_PHYS(ma[i]) + ma_offs; 152 error = _bus_dmamap_load_phys(dmat, map, paddr, len, 153 flags, segs, segp); 154 if (error != 0) 155 break; 156 ma_offs = 0; 157 } 158 return (error); 159 } 160 161 /* 162 * Load a cam control block. 163 */ 164 static int 165 _bus_dmamap_load_ccb(bus_dma_tag_t dmat, bus_dmamap_t map, union ccb *ccb, 166 int *nsegs, int flags) 167 { 168 struct ccb_hdr *ccb_h; 169 void *data_ptr; 170 int error; 171 uint32_t dxfer_len; 172 uint16_t sglist_cnt; 173 174 error = 0; 175 ccb_h = &ccb->ccb_h; 176 switch (ccb_h->func_code) { 177 case XPT_SCSI_IO: { 178 struct ccb_scsiio *csio; 179 180 csio = &ccb->csio; 181 data_ptr = csio->data_ptr; 182 dxfer_len = csio->dxfer_len; 183 sglist_cnt = csio->sglist_cnt; 184 break; 185 } 186 case XPT_CONT_TARGET_IO: { 187 struct ccb_scsiio *ctio; 188 189 ctio = &ccb->ctio; 190 data_ptr = ctio->data_ptr; 191 dxfer_len = ctio->dxfer_len; 192 sglist_cnt = ctio->sglist_cnt; 193 break; 194 } 195 case XPT_ATA_IO: { 196 struct ccb_ataio *ataio; 197 198 ataio = &ccb->ataio; 199 data_ptr = ataio->data_ptr; 200 dxfer_len = ataio->dxfer_len; 201 sglist_cnt = 0; 202 break; 203 } 204 default: 205 panic("_bus_dmamap_load_ccb: Unsupported func code %d", 206 ccb_h->func_code); 207 } 208 209 switch ((ccb_h->flags & CAM_DATA_MASK)) { 210 case CAM_DATA_VADDR: 211 error = _bus_dmamap_load_buffer(dmat, map, data_ptr, dxfer_len, 212 kernel_pmap, flags, NULL, nsegs); 213 break; 214 case CAM_DATA_PADDR: 215 error = _bus_dmamap_load_phys(dmat, map, 216 (vm_paddr_t)(uintptr_t)data_ptr, dxfer_len, flags, NULL, 217 nsegs); 218 break; 219 case CAM_DATA_SG: 220 error = _bus_dmamap_load_vlist(dmat, map, 221 (bus_dma_segment_t *)data_ptr, sglist_cnt, kernel_pmap, 222 nsegs, flags); 223 break; 224 case CAM_DATA_SG_PADDR: 225 error = _bus_dmamap_load_plist(dmat, map, 226 (bus_dma_segment_t *)data_ptr, sglist_cnt, nsegs, flags); 227 break; 228 case CAM_DATA_BIO: 229 error = _bus_dmamap_load_bio(dmat, map, (struct bio *)data_ptr, 230 nsegs, flags); 231 break; 232 default: 233 panic("_bus_dmamap_load_ccb: flags 0x%X unimplemented", 234 ccb_h->flags); 235 } 236 return (error); 237 } 238 239 /* 240 * Load a uio. 241 */ 242 static int 243 _bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio, 244 int *nsegs, int flags) 245 { 246 bus_size_t resid; 247 bus_size_t minlen; 248 struct iovec *iov; 249 pmap_t pmap; 250 caddr_t addr; 251 int error, i; 252 253 if (uio->uio_segflg == UIO_USERSPACE) { 254 KASSERT(uio->uio_td != NULL, 255 ("bus_dmamap_load_uio: USERSPACE but no proc")); 256 pmap = vmspace_pmap(uio->uio_td->td_proc->p_vmspace); 257 } else 258 pmap = kernel_pmap; 259 resid = uio->uio_resid; 260 iov = uio->uio_iov; 261 error = 0; 262 263 for (i = 0; i < uio->uio_iovcnt && resid != 0 && !error; i++) { 264 /* 265 * Now at the first iovec to load. Load each iovec 266 * until we have exhausted the residual count. 267 */ 268 269 addr = (caddr_t) iov[i].iov_base; 270 minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len; 271 if (minlen > 0) { 272 error = _bus_dmamap_load_buffer(dmat, map, addr, 273 minlen, pmap, flags, NULL, nsegs); 274 resid -= minlen; 275 } 276 } 277 278 return (error); 279 } 280 281 /* 282 * Map the buffer buf into bus space using the dmamap map. 283 */ 284 int 285 bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, 286 bus_size_t buflen, bus_dmamap_callback_t *callback, 287 void *callback_arg, int flags) 288 { 289 bus_dma_segment_t *segs; 290 struct memdesc mem; 291 int error; 292 int nsegs; 293 294 if ((flags & BUS_DMA_NOWAIT) == 0) { 295 mem = memdesc_vaddr(buf, buflen); 296 _bus_dmamap_waitok(dmat, map, &mem, callback, callback_arg); 297 } 298 299 nsegs = -1; 300 error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, kernel_pmap, 301 flags, NULL, &nsegs); 302 nsegs++; 303 304 CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", 305 __func__, dmat, flags, error, nsegs); 306 307 if (error == EINPROGRESS) 308 return (error); 309 310 segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error); 311 if (error) 312 (*callback)(callback_arg, segs, 0, error); 313 else 314 (*callback)(callback_arg, segs, nsegs, 0); 315 316 /* 317 * Return ENOMEM to the caller so that it can pass it up the stack. 318 * This error only happens when NOWAIT is set, so deferral is disabled. 319 */ 320 if (error == ENOMEM) 321 return (error); 322 323 return (0); 324 } 325 326 int 327 bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0, 328 bus_dmamap_callback2_t *callback, void *callback_arg, int flags) 329 { 330 bus_dma_segment_t *segs; 331 int nsegs, error; 332 333 M_ASSERTPKTHDR(m0); 334 335 flags |= BUS_DMA_NOWAIT; 336 nsegs = -1; 337 error = _bus_dmamap_load_mbuf_sg(dmat, map, m0, NULL, &nsegs, flags); 338 ++nsegs; 339 340 segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error); 341 if (error) 342 (*callback)(callback_arg, segs, 0, 0, error); 343 else 344 (*callback)(callback_arg, segs, nsegs, m0->m_pkthdr.len, error); 345 346 CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", 347 __func__, dmat, flags, error, nsegs); 348 return (error); 349 } 350 351 int 352 bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0, 353 bus_dma_segment_t *segs, int *nsegs, int flags) 354 { 355 int error; 356 357 flags |= BUS_DMA_NOWAIT; 358 *nsegs = -1; 359 error = _bus_dmamap_load_mbuf_sg(dmat, map, m0, segs, nsegs, flags); 360 ++*nsegs; 361 _bus_dmamap_complete(dmat, map, segs, *nsegs, error); 362 return (error); 363 } 364 365 int 366 bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio, 367 bus_dmamap_callback2_t *callback, void *callback_arg, int flags) 368 { 369 bus_dma_segment_t *segs; 370 int nsegs, error; 371 372 flags |= BUS_DMA_NOWAIT; 373 nsegs = -1; 374 error = _bus_dmamap_load_uio(dmat, map, uio, &nsegs, flags); 375 nsegs++; 376 377 segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error); 378 if (error) 379 (*callback)(callback_arg, segs, 0, 0, error); 380 else 381 (*callback)(callback_arg, segs, nsegs, uio->uio_resid, error); 382 383 CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", 384 __func__, dmat, flags, error, nsegs); 385 return (error); 386 } 387 388 int 389 bus_dmamap_load_ccb(bus_dma_tag_t dmat, bus_dmamap_t map, union ccb *ccb, 390 bus_dmamap_callback_t *callback, void *callback_arg, 391 int flags) 392 { 393 bus_dma_segment_t *segs; 394 struct ccb_hdr *ccb_h; 395 struct memdesc mem; 396 int error; 397 int nsegs; 398 399 ccb_h = &ccb->ccb_h; 400 if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_NONE) { 401 callback(callback_arg, NULL, 0, 0); 402 return (0); 403 } 404 if ((flags & BUS_DMA_NOWAIT) == 0) { 405 mem = memdesc_ccb(ccb); 406 _bus_dmamap_waitok(dmat, map, &mem, callback, callback_arg); 407 } 408 nsegs = -1; 409 error = _bus_dmamap_load_ccb(dmat, map, ccb, &nsegs, flags); 410 nsegs++; 411 412 CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", 413 __func__, dmat, flags, error, nsegs); 414 415 if (error == EINPROGRESS) 416 return (error); 417 418 segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error); 419 if (error) 420 (*callback)(callback_arg, segs, 0, error); 421 else 422 (*callback)(callback_arg, segs, nsegs, error); 423 /* 424 * Return ENOMEM to the caller so that it can pass it up the stack. 425 * This error only happens when NOWAIT is set, so deferral is disabled. 426 */ 427 if (error == ENOMEM) 428 return (error); 429 430 return (0); 431 } 432 433 int 434 bus_dmamap_load_bio(bus_dma_tag_t dmat, bus_dmamap_t map, struct bio *bio, 435 bus_dmamap_callback_t *callback, void *callback_arg, 436 int flags) 437 { 438 bus_dma_segment_t *segs; 439 struct memdesc mem; 440 int error; 441 int nsegs; 442 443 if ((flags & BUS_DMA_NOWAIT) == 0) { 444 mem = memdesc_bio(bio); 445 _bus_dmamap_waitok(dmat, map, &mem, callback, callback_arg); 446 } 447 nsegs = -1; 448 error = _bus_dmamap_load_bio(dmat, map, bio, &nsegs, flags); 449 nsegs++; 450 451 CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", 452 __func__, dmat, flags, error, nsegs); 453 454 if (error == EINPROGRESS) 455 return (error); 456 457 segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error); 458 if (error) 459 (*callback)(callback_arg, segs, 0, error); 460 else 461 (*callback)(callback_arg, segs, nsegs, error); 462 /* 463 * Return ENOMEM to the caller so that it can pass it up the stack. 464 * This error only happens when NOWAIT is set, so deferral is disabled. 465 */ 466 if (error == ENOMEM) 467 return (error); 468 469 return (0); 470 } 471 472 int 473 bus_dmamap_load_mem(bus_dma_tag_t dmat, bus_dmamap_t map, 474 struct memdesc *mem, bus_dmamap_callback_t *callback, 475 void *callback_arg, int flags) 476 { 477 bus_dma_segment_t *segs; 478 int error; 479 int nsegs; 480 481 if ((flags & BUS_DMA_NOWAIT) == 0) 482 _bus_dmamap_waitok(dmat, map, mem, callback, callback_arg); 483 484 nsegs = -1; 485 error = 0; 486 switch (mem->md_type) { 487 case MEMDESC_VADDR: 488 error = _bus_dmamap_load_buffer(dmat, map, mem->u.md_vaddr, 489 mem->md_opaque, kernel_pmap, flags, NULL, &nsegs); 490 break; 491 case MEMDESC_PADDR: 492 error = _bus_dmamap_load_phys(dmat, map, mem->u.md_paddr, 493 mem->md_opaque, flags, NULL, &nsegs); 494 break; 495 case MEMDESC_VLIST: 496 error = _bus_dmamap_load_vlist(dmat, map, mem->u.md_list, 497 mem->md_opaque, kernel_pmap, &nsegs, flags); 498 break; 499 case MEMDESC_PLIST: 500 error = _bus_dmamap_load_plist(dmat, map, mem->u.md_list, 501 mem->md_opaque, &nsegs, flags); 502 break; 503 case MEMDESC_BIO: 504 error = _bus_dmamap_load_bio(dmat, map, mem->u.md_bio, 505 &nsegs, flags); 506 break; 507 case MEMDESC_UIO: 508 error = _bus_dmamap_load_uio(dmat, map, mem->u.md_uio, 509 &nsegs, flags); 510 break; 511 case MEMDESC_MBUF: 512 error = _bus_dmamap_load_mbuf_sg(dmat, map, mem->u.md_mbuf, 513 NULL, &nsegs, flags); 514 break; 515 case MEMDESC_CCB: 516 error = _bus_dmamap_load_ccb(dmat, map, mem->u.md_ccb, &nsegs, 517 flags); 518 break; 519 } 520 nsegs++; 521 522 CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", 523 __func__, dmat, flags, error, nsegs); 524 525 if (error == EINPROGRESS) 526 return (error); 527 528 segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error); 529 if (error) 530 (*callback)(callback_arg, segs, 0, error); 531 else 532 (*callback)(callback_arg, segs, nsegs, 0); 533 534 /* 535 * Return ENOMEM to the caller so that it can pass it up the stack. 536 * This error only happens when NOWAIT is set, so deferral is disabled. 537 */ 538 if (error == ENOMEM) 539 return (error); 540 541 return (0); 542 } 543