1 /* $NetBSD: bus_dma.c,v 1.49 2024/10/21 06:47:10 skrll Exp $ */ 2 3 /*- 4 * Copyright (c) 1997, 1998, 2001, 2020 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 34 35 __KERNEL_RCSID(0, "$NetBSD: bus_dma.c,v 1.49 2024/10/21 06:47:10 skrll Exp $"); 36 37 #define _MIPS_BUS_DMA_PRIVATE 38 39 #include <sys/param.h> 40 #include <sys/bus.h> 41 #include <sys/cpu.h> 42 #include <sys/device.h> 43 #include <sys/evcnt.h> 44 #include <sys/kernel.h> 45 #include <sys/kmem.h> 46 #include <sys/mbuf.h> 47 #include <sys/proc.h> 48 #include <sys/systm.h> 49 50 #include <uvm/uvm.h> 51 52 #include <mips/cache.h> 53 #ifdef _LP64 54 #include <mips/mips3_pte.h> 55 #endif 56 57 #include <mips/locore.h> 58 59 const struct mips_bus_dmamap_ops mips_bus_dmamap_ops = 60 _BUS_DMAMAP_OPS_INITIALIZER; 61 const struct mips_bus_dmamem_ops mips_bus_dmamem_ops = 62 _BUS_DMAMEM_OPS_INITIALIZER; 63 const struct mips_bus_dmatag_ops mips_bus_dmatag_ops = 64 _BUS_DMATAG_OPS_INITIALIZER; 65 66 static struct evcnt bus_dma_creates = 67 EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "creates"); 68 static struct evcnt bus_dma_bounced_creates = 69 EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "bounced creates"); 70 static struct evcnt bus_dma_loads = 71 EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "loads"); 72 static struct evcnt bus_dma_bounced_loads = 73 EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "bounced loads"); 74 static struct evcnt bus_dma_read_bounces = 75 EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "read bounces"); 76 static struct evcnt bus_dma_write_bounces = 77 EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "write bounces"); 78 static struct evcnt bus_dma_bounced_unloads = 79 EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "bounced unloads"); 80 static struct evcnt bus_dma_unloads = 81 EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "unloads"); 82 static struct evcnt bus_dma_bounced_destroys = 83 EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "bounced destroys"); 84 static struct evcnt bus_dma_destroys = 85 EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "destroys"); 86 87 EVCNT_ATTACH_STATIC(bus_dma_creates); 88 EVCNT_ATTACH_STATIC(bus_dma_bounced_creates); 89 EVCNT_ATTACH_STATIC(bus_dma_loads); 90 EVCNT_ATTACH_STATIC(bus_dma_bounced_loads); 91 EVCNT_ATTACH_STATIC(bus_dma_read_bounces); 92 EVCNT_ATTACH_STATIC(bus_dma_write_bounces); 93 EVCNT_ATTACH_STATIC(bus_dma_unloads); 94 EVCNT_ATTACH_STATIC(bus_dma_bounced_unloads); 95 EVCNT_ATTACH_STATIC(bus_dma_destroys); 96 EVCNT_ATTACH_STATIC(bus_dma_bounced_destroys); 97 98 #define STAT_INCR(x) (bus_dma_ ## x.ev_count++) 99 100 paddr_t kvtophys(vaddr_t); /* XXX */ 101 102 /* 103 * Utility function to load a linear buffer. segp contains the starting 104 * segment on entrance, and the ending segment on exit. first indicates 105 * if this is the first invocation of this function. 106 */ 107 static int 108 _bus_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map, 109 void *buf, bus_size_t buflen, struct vmspace *vm, int flags, 110 int *segp, vaddr_t lastvaddr, bool first) 111 { 112 paddr_t baddr, curaddr, lastaddr; 113 vaddr_t vaddr = (vaddr_t)buf; 114 bus_dma_segment_t *ds = &map->dm_segs[*segp]; 115 bus_dma_segment_t * const eds = &map->dm_segs[map->_dm_segcnt]; 116 const bus_addr_t bmask = ~(map->_dm_boundary - 1); 117 const bool d_cache_coherent = 118 (mips_options.mips_cpu_flags & CPU_MIPS_D_CACHE_COHERENT) != 0; 119 120 lastaddr = ds->ds_addr + ds->ds_len; 121 122 while (buflen > 0) { 123 /* 124 * Get the physical address for this segment. 125 */ 126 if (!VMSPACE_IS_KERNEL_P(vm)) 127 (void) pmap_extract(vm_map_pmap(&vm->vm_map), vaddr, 128 &curaddr); 129 else 130 curaddr = kvtophys(vaddr); 131 132 /* 133 * If we're beyond the current DMA window, indicate 134 * that and try to fall back onto something else. 135 */ 136 if (curaddr < t->_bounce_alloc_lo 137 || (t->_bounce_alloc_hi != 0 138 && curaddr >= t->_bounce_alloc_hi)) 139 return EINVAL; 140 #if BUS_DMA_DEBUG 141 printf("dma: addr %#"PRIxPADDR" -> %#"PRIxPADDR"\n", curaddr, 142 (curaddr - t->_bounce_alloc_lo) + t->_wbase); 143 #endif 144 curaddr = (curaddr - t->_bounce_alloc_lo) + t->_wbase; 145 146 /* 147 * Compute the segment size, and adjust counts. 148 */ 149 bus_size_t sgsize = PAGE_SIZE - ((uintptr_t)vaddr & PGOFSET); 150 if (sgsize > buflen) { 151 sgsize = buflen; 152 } 153 if (sgsize > map->dm_maxsegsz) { 154 sgsize = map->dm_maxsegsz; 155 } 156 157 /* 158 * Make sure we don't cross any boundaries. 159 */ 160 if (map->_dm_boundary > 0) { 161 baddr = (curaddr + map->_dm_boundary) & bmask; 162 if (sgsize > baddr - curaddr) { 163 sgsize = baddr - curaddr; 164 } 165 } 166 167 /* 168 * Insert chunk into a segment, coalescing with 169 * the previous segment if possible. 170 */ 171 if (!first 172 && curaddr == lastaddr 173 && (d_cache_coherent 174 #ifndef __mips_o32 175 || !MIPS_CACHE_VIRTUAL_ALIAS 176 #endif 177 || vaddr == lastvaddr) 178 && (ds->ds_len + sgsize) <= map->dm_maxsegsz 179 && (map->_dm_boundary == 0 180 || ((ds->ds_addr ^ curaddr) & bmask) == 0)) { 181 ds->ds_len += sgsize; 182 } else { 183 if (!first && ++ds >= eds) 184 break; 185 ds->ds_addr = curaddr; 186 ds->ds_len = sgsize; 187 ds->_ds_vaddr = (intptr_t)vaddr; 188 first = false; 189 /* 190 * If this segment uses the correct color, try to see 191 * if we can use a direct-mapped VA for the segment. 192 */ 193 if (!mips_cache_badalias(curaddr, vaddr)) { 194 #ifdef __mips_o32 195 if (MIPS_KSEG0_P(curaddr + sgsize - 1)) { 196 ds->_ds_vaddr = 197 MIPS_PHYS_TO_KSEG0(curaddr); 198 } 199 #else 200 /* 201 * All physical addresses can be accessed 202 * via XKPHYS. 203 */ 204 ds->_ds_vaddr = 205 MIPS_PHYS_TO_XKPHYS_CACHED(curaddr); 206 #endif 207 } 208 /* Make sure this is a valid kernel address */ 209 KASSERTMSG(ds->_ds_vaddr < 0, 210 "_ds_vaddr %#"PRIxREGISTER, ds->_ds_vaddr); 211 } 212 213 lastaddr = curaddr + sgsize; 214 vaddr += sgsize; 215 buflen -= sgsize; 216 lastvaddr = vaddr; 217 } 218 219 *segp = ds - map->dm_segs; 220 221 /* 222 * Did we fit? 223 */ 224 if (buflen != 0) { 225 /* 226 * If there is a chained window, we will automatically 227 * fall back to it. 228 */ 229 return EFBIG; /* XXX better return value here? */ 230 } 231 232 return 0; 233 } 234 235 #ifdef _MIPS_NEED_BUS_DMA_BOUNCE 236 static int _bus_dma_alloc_bouncebuf(bus_dma_tag_t t, bus_dmamap_t map, 237 bus_size_t size, int flags); 238 static void _bus_dma_free_bouncebuf(bus_dma_tag_t t, bus_dmamap_t map); 239 static int _bus_dma_uiomove(void *buf, struct uio *uio, size_t n, 240 int direction); 241 242 static int 243 _bus_dma_load_bouncebuf(bus_dma_tag_t t, bus_dmamap_t map, void *buf, 244 size_t buflen, int buftype, int flags) 245 { 246 struct mips_bus_dma_cookie * const cookie = map->_dm_cookie; 247 struct vmspace * const vm = vmspace_kernel(); 248 int seg, error; 249 250 KASSERT(cookie != NULL); 251 KASSERT(cookie->id_flags & _BUS_DMA_MIGHT_NEED_BOUNCE); 252 253 /* 254 * Allocate bounce pages, if necessary. 255 */ 256 if ((cookie->id_flags & _BUS_DMA_HAS_BOUNCE) == 0) { 257 error = _bus_dma_alloc_bouncebuf(t, map, buflen, flags); 258 if (error) 259 return error; 260 } 261 262 /* 263 * Cache a pointer to the caller's buffer and load the DMA map 264 * with the bounce buffer. 265 */ 266 cookie->id_origbuf = buf; 267 cookie->id_origbuflen = buflen; 268 cookie->id_buftype = buftype; 269 seg = 0; 270 error = _bus_dmamap_load_buffer(t, map, cookie->id_bouncebuf, 271 buflen, vm, flags, &seg, 0, true); 272 if (error) 273 return error; 274 275 STAT_INCR(bounced_loads); 276 map->dm_mapsize = buflen; 277 map->dm_nsegs = seg + 1; 278 map->_dm_vmspace = vm; 279 /* 280 * If our cache is coherent, then the map must be coherent too. 281 */ 282 if (mips_options.mips_cpu_flags & CPU_MIPS_D_CACHE_COHERENT) 283 map->_dm_flags |= _BUS_DMAMAP_COHERENT; 284 285 /* ...so _bus_dmamap_sync() knows we're bouncing */ 286 cookie->id_flags |= _BUS_DMA_IS_BOUNCING; 287 return 0; 288 } 289 #endif /* _MIPS_NEED_BUS_DMA_BOUNCE */ 290 291 static size_t 292 _bus_dmamap_mapsize(int const nsegments) 293 { 294 KASSERT(nsegments > 0); 295 return sizeof(struct mips_bus_dmamap) + 296 (sizeof(bus_dma_segment_t) * (nsegments - 1)); 297 } 298 299 #ifdef _MIPS_NEED_BUS_DMA_BOUNCE 300 static size_t 301 _bus_dmamap_cookiesize(int const nsegments) 302 { 303 KASSERT(nsegments > 0); 304 return sizeof(struct mips_bus_dma_cookie) + 305 (sizeof(bus_dma_segment_t) * nsegments); 306 } 307 #endif 308 309 /* 310 * Common function for DMA map creation. May be called by bus-specific 311 * DMA map creation functions. 312 */ 313 int 314 _bus_dmamap_create(bus_dma_tag_t t, bus_size_t size, int nsegments, 315 bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp) 316 { 317 struct mips_bus_dmamap *map; 318 void *mapstore; 319 const int allocflags = 320 ((flags & BUS_DMA_NOWAIT) ? KM_NOSLEEP : KM_SLEEP); 321 322 int error = 0; 323 324 /* 325 * Allocate and initialize the DMA map. The end of the map 326 * is a variable-sized array of segments, so we allocate enough 327 * room for them in one shot. 328 * 329 * Note we don't preserve the WAITOK or NOWAIT flags. Preservation 330 * of ALLOCNOW notifies others that we've reserved these resources, 331 * and they are not to be freed. 332 * 333 * The bus_dmamap_t includes one bus_dma_segment_t, hence 334 * the (nsegments - 1). 335 */ 336 if ((mapstore = kmem_zalloc(_bus_dmamap_mapsize(nsegments), 337 allocflags)) == NULL) 338 return ENOMEM; 339 340 map = mapstore; 341 map->_dm_size = size; 342 map->_dm_segcnt = nsegments; 343 map->_dm_maxmaxsegsz = maxsegsz; 344 map->_dm_boundary = boundary; 345 map->_dm_bounce_thresh = t->_bounce_thresh; 346 map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT); 347 map->_dm_vmspace = NULL; 348 map->dm_maxsegsz = maxsegsz; 349 map->dm_mapsize = 0; /* no valid mappings */ 350 map->dm_nsegs = 0; 351 352 *dmamp = map; 353 354 #ifdef _MIPS_NEED_BUS_DMA_BOUNCE 355 struct mips_bus_dma_cookie *cookie; 356 int cookieflags; 357 void *cookiestore; 358 359 if (t->_bounce_thresh == 0 || _BUS_AVAIL_END <= t->_bounce_thresh - 1) 360 map->_dm_bounce_thresh = 0; 361 cookieflags = 0; 362 363 if (t->_may_bounce != NULL) { 364 error = (*t->_may_bounce)(t, map, flags, &cookieflags); 365 if (error != 0) 366 goto out; 367 } 368 369 if (map->_dm_bounce_thresh != 0) 370 cookieflags |= _BUS_DMA_MIGHT_NEED_BOUNCE; 371 372 if ((cookieflags & _BUS_DMA_MIGHT_NEED_BOUNCE) == 0) { 373 STAT_INCR(creates); 374 return 0; 375 } 376 377 /* 378 * Allocate our cookie. 379 */ 380 if ((cookiestore = kmem_zalloc(_bus_dmamap_cookiesize(nsegments), 381 allocflags)) == NULL) { 382 error = ENOMEM; 383 goto out; 384 } 385 cookie = (struct mips_bus_dma_cookie *)cookiestore; 386 cookie->id_flags = cookieflags; 387 map->_dm_cookie = cookie; 388 STAT_INCR(bounced_creates); 389 390 error = _bus_dma_alloc_bouncebuf(t, map, size, flags); 391 out: 392 if (error) 393 _bus_dmamap_destroy(t, map); 394 #else 395 STAT_INCR(creates); 396 #endif /* _MIPS_NEED_BUS_DMA_BOUNCE */ 397 398 return error; 399 } 400 401 /* 402 * Common function for DMA map destruction. May be called by bus-specific 403 * DMA map destruction functions. 404 */ 405 void 406 _bus_dmamap_destroy(bus_dma_tag_t t, bus_dmamap_t map) 407 { 408 409 #ifdef _MIPS_NEED_BUS_DMA_BOUNCE 410 struct mips_bus_dma_cookie *cookie = map->_dm_cookie; 411 412 /* 413 * Free any bounce pages this map might hold. 414 */ 415 if (cookie != NULL) { 416 if (cookie->id_flags & _BUS_DMA_IS_BOUNCING) 417 STAT_INCR(bounced_unloads); 418 map->dm_nsegs = 0; 419 if (cookie->id_flags & _BUS_DMA_HAS_BOUNCE) 420 _bus_dma_free_bouncebuf(t, map); 421 STAT_INCR(bounced_destroys); 422 kmem_free(cookie, _bus_dmamap_cookiesize(map->_dm_segcnt)); 423 } else 424 #endif 425 STAT_INCR(destroys); 426 if (map->dm_nsegs > 0) 427 STAT_INCR(unloads); 428 kmem_free(map, _bus_dmamap_mapsize(map->_dm_segcnt)); 429 } 430 431 /* 432 * Common function for loading a direct-mapped DMA map with a linear 433 * buffer. Called by bus-specific DMA map load functions with the 434 * OR value appropriate for indicating "direct-mapped" for that 435 * chipset. 436 */ 437 int 438 _bus_dmamap_load(bus_dma_tag_t t, bus_dmamap_t map, void *buf, 439 bus_size_t buflen, struct proc *p, int flags) 440 { 441 int seg, error; 442 struct vmspace *vm; 443 444 if (map->dm_nsegs > 0) { 445 #ifdef _MIPS_NEED_BUS_DMA_BOUNCE 446 struct mips_bus_dma_cookie *cookie = map->_dm_cookie; 447 if (cookie != NULL) { 448 if (cookie->id_flags & _BUS_DMA_IS_BOUNCING) { 449 STAT_INCR(bounced_unloads); 450 cookie->id_flags &= ~_BUS_DMA_IS_BOUNCING; 451 } 452 cookie->id_buftype = _BUS_DMA_BUFTYPE_INVALID; 453 } else 454 #endif 455 STAT_INCR(unloads); 456 } 457 /* 458 * Make sure that on error condition we return "no valid mappings". 459 */ 460 map->dm_mapsize = 0; 461 map->dm_nsegs = 0; 462 KASSERT(map->dm_maxsegsz <= map->_dm_maxmaxsegsz); 463 464 if (buflen > map->_dm_size) 465 return EINVAL; 466 467 if (p != NULL) { 468 vm = p->p_vmspace; 469 } else { 470 vm = vmspace_kernel(); 471 } 472 473 seg = 0; 474 error = _bus_dmamap_load_buffer(t, map, buf, buflen, 475 vm, flags, &seg, 0, true); 476 if (error == 0) { 477 map->dm_mapsize = buflen; 478 map->dm_nsegs = seg + 1; 479 map->_dm_vmspace = vm; 480 481 STAT_INCR(loads); 482 483 /* 484 * For linear buffers, we support marking the mapping 485 * as COHERENT. 486 * 487 * XXX Check TLB entries for cache-inhibit bits? 488 */ 489 if (mips_options.mips_cpu_flags & CPU_MIPS_D_CACHE_COHERENT) 490 map->_dm_flags |= _BUS_DMAMAP_COHERENT; 491 else if (MIPS_KSEG1_P(buf)) 492 map->_dm_flags |= _BUS_DMAMAP_COHERENT; 493 #ifdef _LP64 494 else if (MIPS_XKPHYS_P((vaddr_t)buf) && 495 (MIPS_XKPHYS_TO_CCA((vaddr_t)buf) == 496 MIPS3_PG_TO_CCA(MIPS3_PG_UNCACHED))) 497 map->_dm_flags |= _BUS_DMAMAP_COHERENT; 498 #endif 499 return 0; 500 } 501 #ifdef _MIPS_NEED_BUS_DMA_BOUNCE 502 struct mips_bus_dma_cookie *cookie = map->_dm_cookie; 503 if (cookie != NULL && 504 (cookie->id_flags & _BUS_DMA_MIGHT_NEED_BOUNCE)) { 505 error = _bus_dma_load_bouncebuf(t, map, buf, buflen, 506 _BUS_DMA_BUFTYPE_LINEAR, flags); 507 } 508 #endif 509 return error; 510 } 511 512 /* 513 * Like _bus_dmamap_load(), but for mbufs. 514 */ 515 int 516 _bus_dmamap_load_mbuf(bus_dma_tag_t t, bus_dmamap_t map, 517 struct mbuf *m0, int flags) 518 { 519 int seg, error; 520 struct mbuf *m; 521 struct vmspace *vm = vmspace_kernel(); 522 523 if (map->dm_nsegs > 0) { 524 #ifdef _MIPS_NEED_BUS_DMA_BOUNCE 525 struct mips_bus_dma_cookie *cookie = map->_dm_cookie; 526 if (cookie != NULL) { 527 if (cookie->id_flags & _BUS_DMA_IS_BOUNCING) { 528 STAT_INCR(bounced_unloads); 529 cookie->id_flags &= ~_BUS_DMA_IS_BOUNCING; 530 } 531 cookie->id_buftype = _BUS_DMA_BUFTYPE_INVALID; 532 } else 533 #endif 534 STAT_INCR(unloads); 535 } 536 537 /* 538 * Make sure that on error condition we return "no valid mappings." 539 */ 540 map->dm_mapsize = 0; 541 map->dm_nsegs = 0; 542 KASSERT(map->dm_maxsegsz <= map->_dm_maxmaxsegsz); 543 544 KASSERT(m0->m_flags & M_PKTHDR); 545 546 if (m0->m_pkthdr.len > map->_dm_size) 547 return EINVAL; 548 549 vaddr_t lastvaddr = 0; 550 bool first = true; 551 seg = 0; 552 error = 0; 553 for (m = m0; m != NULL && error == 0; m = m->m_next) { 554 if (m->m_len == 0) 555 continue; 556 error = _bus_dmamap_load_buffer(t, map, m->m_data, m->m_len, 557 vm, flags, &seg, lastvaddr, first); 558 first = false; 559 lastvaddr = (vaddr_t)m->m_data + m->m_len; 560 } 561 if (error == 0) { 562 map->dm_mapsize = m0->m_pkthdr.len; 563 map->dm_nsegs = seg + 1; 564 map->_dm_vmspace = vm; /* always kernel */ 565 /* 566 * If our cache is coherent, then the map must be coherent too. 567 */ 568 if (mips_options.mips_cpu_flags & CPU_MIPS_D_CACHE_COHERENT) 569 map->_dm_flags |= _BUS_DMAMAP_COHERENT; 570 return 0; 571 } 572 #ifdef _MIPS_NEED_BUS_DMA_BOUNCE 573 struct mips_bus_dma_cookie *cookie = map->_dm_cookie; 574 if (cookie != NULL && 575 (cookie->id_flags & _BUS_DMA_MIGHT_NEED_BOUNCE)) { 576 error = _bus_dma_load_bouncebuf(t, map, m0, m0->m_pkthdr.len, 577 _BUS_DMA_BUFTYPE_MBUF, flags); 578 } 579 #endif /* _MIPS_NEED_BUS_DMA_BOUNCE */ 580 return error; 581 } 582 583 /* 584 * Like _bus_dmamap_load(), but for uios. 585 */ 586 int 587 _bus_dmamap_load_uio(bus_dma_tag_t t, bus_dmamap_t map, 588 struct uio *uio, int flags) 589 { 590 int seg, i, error; 591 bus_size_t minlen, resid; 592 struct iovec *iov; 593 void *addr; 594 595 if (map->dm_nsegs > 0) { 596 #ifdef _MIPS_NEED_BUS_DMA_BOUNCE 597 struct mips_bus_dma_cookie *const cookie = map->_dm_cookie; 598 if (cookie != NULL) { 599 if (cookie->id_flags & _BUS_DMA_IS_BOUNCING) { 600 STAT_INCR(bounced_unloads); 601 cookie->id_flags &= ~_BUS_DMA_IS_BOUNCING; 602 } 603 cookie->id_buftype = _BUS_DMA_BUFTYPE_INVALID; 604 } else 605 #endif 606 STAT_INCR(unloads); 607 } 608 /* 609 * Make sure that on error condition we return "no valid mappings." 610 */ 611 map->dm_mapsize = 0; 612 map->dm_nsegs = 0; 613 KASSERT(map->dm_maxsegsz <= map->_dm_maxmaxsegsz); 614 615 resid = uio->uio_resid; 616 iov = uio->uio_iov; 617 618 vaddr_t lastvaddr = 0; 619 bool first = true; 620 seg = 0; 621 error = 0; 622 for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0; i++) { 623 /* 624 * Now at the first iovec to load. Load each iovec 625 * until we have exhausted the residual count. 626 */ 627 minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len; 628 addr = (void *)iov[i].iov_base; 629 630 error = _bus_dmamap_load_buffer(t, map, addr, minlen, 631 uio->uio_vmspace, flags, &seg, lastvaddr, first); 632 first = false; 633 lastvaddr = (vaddr_t)addr + minlen; 634 635 resid -= minlen; 636 } 637 if (error == 0) { 638 map->dm_mapsize = uio->uio_resid; 639 map->dm_nsegs = seg + 1; 640 map->_dm_vmspace = uio->uio_vmspace; 641 /* 642 * If our cache is coherent, then the map must be coherent too. 643 */ 644 if (mips_options.mips_cpu_flags & CPU_MIPS_D_CACHE_COHERENT) 645 map->_dm_flags |= _BUS_DMAMAP_COHERENT; 646 return 0; 647 } 648 #ifdef _MIPS_NEED_BUS_DMA_BOUNCE 649 struct mips_bus_dma_cookie *cookie = map->_dm_cookie; 650 if (cookie != NULL && 651 (cookie->id_flags & _BUS_DMA_MIGHT_NEED_BOUNCE)) { 652 error = _bus_dma_load_bouncebuf(t, map, uio, uio->uio_resid, 653 _BUS_DMA_BUFTYPE_UIO, flags); 654 } 655 #endif 656 return error; 657 } 658 659 /* 660 * Like _bus_dmamap_load(), but for raw memory. 661 */ 662 int 663 _bus_dmamap_load_raw(bus_dma_tag_t t, bus_dmamap_t map, 664 bus_dma_segment_t *segs, int nsegs, bus_size_t size, int flags) 665 { 666 667 struct vmspace *const vm = vmspace_kernel(); 668 const bool coherent_p = 669 (mips_options.mips_cpu_flags & CPU_MIPS_D_CACHE_COHERENT); 670 const bool cached_p = coherent_p || (flags & BUS_DMA_COHERENT) == 0; 671 bus_size_t mapsize = 0; 672 vaddr_t lastvaddr = 0; 673 bool first = true; 674 int curseg = 0; 675 int error = 0; 676 677 for (; error == 0 && nsegs-- > 0; segs++) { 678 void *kva; 679 #ifdef _LP64 680 if (cached_p) { 681 kva = (void *)MIPS_PHYS_TO_XKPHYS_CACHED( 682 segs->ds_addr); 683 } else { 684 kva = (void *)MIPS_PHYS_TO_XKPHYS_UNCACHED( 685 segs->ds_addr); 686 } 687 #else 688 if (segs->ds_addr >= MIPS_PHYS_MASK) 689 return EFBIG; 690 if (cached_p) { 691 kva = (void *)MIPS_PHYS_TO_KSEG0(segs->ds_addr); 692 } else { 693 kva = (void *)MIPS_PHYS_TO_KSEG1(segs->ds_addr); 694 } 695 #endif /* _LP64 */ 696 mapsize += segs->ds_len; 697 error = _bus_dmamap_load_buffer(t, map, kva, segs->ds_len, 698 vm, flags, &curseg, lastvaddr, first); 699 first = false; 700 lastvaddr = (vaddr_t)kva + segs->ds_len; 701 } 702 if (error == 0) { 703 map->dm_mapsize = mapsize; 704 map->dm_nsegs = curseg + 1; 705 map->_dm_vmspace = vm; /* always kernel */ 706 /* 707 * If our cache is coherent, then the map must be coherent too. 708 */ 709 if (coherent_p) 710 map->_dm_flags |= _BUS_DMAMAP_COHERENT; 711 return 0; 712 } 713 /* 714 * If bus_dmamem_alloc didn't return memory that didn't need bouncing 715 * that's a bug which we will not workaround. 716 */ 717 return error; 718 } 719 720 /* 721 * Common function for unloading a DMA map. May be called by 722 * chipset-specific DMA map unload functions. 723 */ 724 void 725 _bus_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t map) 726 { 727 if (map->dm_nsegs > 0) { 728 #ifdef _MIPS_NEED_BUS_DMA_BOUNCE 729 struct mips_bus_dma_cookie *cookie = map->_dm_cookie; 730 if (cookie != NULL) { 731 if (cookie->id_flags & _BUS_DMA_IS_BOUNCING) { 732 cookie->id_flags &= ~_BUS_DMA_IS_BOUNCING; 733 STAT_INCR(bounced_unloads); 734 } 735 cookie->id_buftype = _BUS_DMA_BUFTYPE_INVALID; 736 } else 737 #endif 738 739 STAT_INCR(unloads); 740 } 741 /* 742 * No resources to free; just mark the mappings as 743 * invalid. 744 */ 745 map->dm_maxsegsz = map->_dm_maxmaxsegsz; 746 map->dm_mapsize = 0; 747 map->dm_nsegs = 0; 748 map->_dm_flags &= ~_BUS_DMAMAP_COHERENT; 749 } 750 751 /* 752 * Common function for DMA map synchronization. May be called 753 * by chipset-specific DMA map synchronization functions. 754 * 755 * This version works with the virtually-indexed, write-back cache 756 * found in the MIPS-3/MIPS-4 CPUs available for the Algorithmics. 757 */ 758 void 759 _bus_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset, 760 bus_size_t len, int ops) 761 { 762 bus_size_t minlen; 763 764 #ifdef DIAGNOSTIC 765 /* 766 * Mixing PRE and POST operations is not allowed. 767 */ 768 if ((ops & (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)) != 0 && 769 (ops & (BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE)) != 0) 770 panic("_bus_dmamap_sync: mix PRE and POST"); 771 772 if (offset >= map->dm_mapsize) 773 panic("%s: bad offset 0x%jx >= 0x%jx", __func__, 774 (intmax_t)offset, (intmax_t)map->dm_mapsize); 775 if ((offset + len) > map->dm_mapsize) 776 panic("%s: bad length 0x%jx + 0x%jx > 0x%jx", __func__, 777 (intmax_t)offset, (intmax_t)len, 778 (intmax_t)map->dm_mapsize); 779 #endif 780 781 /* 782 * Since we're dealing with a virtually-indexed, write-back 783 * cache, we need to do the following things: 784 * 785 * PREREAD -- Invalidate D-cache. Note we might have 786 * to also write-back here if we have to use an Index 787 * op, or if the buffer start/end is not cache-line aligned. 788 * 789 * PREWRITE -- Write-back the D-cache. If we have to use 790 * an Index op, we also have to invalidate. Note that if 791 * we are doing PREREAD|PREWRITE, we can collapse everything 792 * into a single op. 793 * 794 * POSTREAD -- Nothing. 795 * 796 * POSTWRITE -- Nothing. 797 */ 798 #ifdef _MIPS_NEED_BUS_DMA_BOUNCE 799 struct mips_bus_dma_cookie * const cookie = map->_dm_cookie; 800 if (cookie != NULL && (cookie->id_flags & _BUS_DMA_IS_BOUNCING) 801 && (ops & BUS_DMASYNC_PREWRITE) && len != 0) { 802 STAT_INCR(write_bounces); 803 /* 804 * Copy the caller's buffer to the bounce buffer. 805 */ 806 switch (cookie->id_buftype) { 807 case _BUS_DMA_BUFTYPE_LINEAR: 808 memcpy((char *)cookie->id_bouncebuf + offset, 809 cookie->id_origlinearbuf + offset, len); 810 break; 811 case _BUS_DMA_BUFTYPE_MBUF: 812 m_copydata(cookie->id_origmbuf, offset, len, 813 (char *)cookie->id_bouncebuf + offset); 814 break; 815 case _BUS_DMA_BUFTYPE_UIO: 816 _bus_dma_uiomove((char *)cookie->id_bouncebuf + offset, 817 cookie->id_origuio, len, UIO_WRITE); 818 break; 819 #ifdef DIAGNOSTIC 820 case _BUS_DMA_BUFTYPE_RAW: 821 panic("_bus_dmamap_sync: _BUS_DMA_BUFTYPE_RAW"); 822 break; 823 824 case _BUS_DMA_BUFTYPE_INVALID: 825 panic("_bus_dmamap_sync: _BUS_DMA_BUFTYPE_INVALID"); 826 break; 827 828 default: 829 panic("_bus_dmamap_sync: unknown buffer type %d\n", 830 cookie->id_buftype); 831 break; 832 #endif /* DIAGNOSTIC */ 833 } 834 } 835 #endif /* _MIPS_NEED_BUS_DMA_BOUNCE */ 836 837 /* 838 * Flush the write buffer. 839 * XXX Is this always necessary? 840 */ 841 wbflush(); 842 843 /* 844 * If the mapping is of COHERENT DMA-safe memory or this isn't a 845 * PREREAD or PREWRITE, no cache flush is necessary. Check to see 846 * if we need to bounce it. 847 */ 848 if ((map->_dm_flags & _BUS_DMAMAP_COHERENT) || 849 (ops & (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)) == 0) 850 goto bounce_it; 851 852 #ifdef __mips_o32 853 /* 854 * If the mapping belongs to the kernel, or it belongs 855 * to the currently-running process (XXX actually, vmspace), 856 * then we can use Hit ops. Otherwise, Index ops. 857 * 858 * This should be true the vast majority of the time. 859 */ 860 const bool useindex = (!VMSPACE_IS_KERNEL_P(map->_dm_vmspace) && 861 map->_dm_vmspace != curproc->p_vmspace); 862 #endif 863 864 bus_dma_segment_t *seg = map->dm_segs; 865 bus_dma_segment_t *const lastseg = seg + map->dm_nsegs; 866 /* 867 * Skip segments until offset are within a segment. 868 */ 869 for (; offset >= seg->ds_len; seg++) { 870 offset -= seg->ds_len; 871 } 872 873 for (; seg < lastseg && len != 0; seg++, offset = 0, len -= minlen) { 874 /* 875 * Now at the first segment to sync; nail each segment until we 876 * have exhausted the length. 877 */ 878 register_t vaddr = seg->_ds_vaddr + offset; 879 minlen = ulmin(len, seg->ds_len - offset); 880 881 #ifdef BUS_DMA_DEBUG 882 printf("bus_dmamap_sync(ops=%d: flushing segment %p " 883 "(0x%"PRIxREGISTER"+%"PRIxBUSADDR 884 ", 0x%"PRIxREGISTER"+0x%"PRIxBUSADDR 885 ") (olen = %"PRIxBUSADDR")...", ops, seg, 886 vaddr - offset, offset, 887 vaddr - offset, offset + minlen - 1, len); 888 #endif 889 890 /* 891 * If we are forced to use Index ops, it's always a 892 * Write-back,Invalidate, so just do one test. 893 */ 894 #ifdef __mips_o32 895 if (__predict_false(useindex || vaddr == 0)) { 896 mips_dcache_wbinv_range_index(vaddr, minlen); 897 #ifdef BUS_DMA_DEBUG 898 printf("\n"); 899 #endif 900 continue; 901 } 902 #endif 903 904 switch (ops) { 905 case BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE: 906 mips_dcache_wbinv_range(vaddr, minlen); 907 break; 908 909 case BUS_DMASYNC_PREREAD: { 910 struct mips_cache_info *const mci = &mips_cache_info; 911 register_t start = vaddr; 912 register_t end = vaddr + minlen; 913 register_t preboundary, firstboundary, lastboundary; 914 register_t mask = mci->mci_dcache_align_mask; 915 916 preboundary = start & ~mask; 917 firstboundary = (start + mask) & ~mask; 918 lastboundary = end & ~mask; 919 if (preboundary < start && preboundary < lastboundary) 920 mips_dcache_wbinv_range(preboundary, 921 mci->mci_dcache_align); 922 if (firstboundary < lastboundary) 923 mips_dcache_inv_range(firstboundary, 924 lastboundary - firstboundary); 925 if (lastboundary < end) 926 mips_dcache_wbinv_range(lastboundary, 927 mci->mci_dcache_align); 928 break; 929 } 930 931 case BUS_DMASYNC_PREWRITE: 932 mips_dcache_wb_range(vaddr, minlen); 933 break; 934 } 935 #ifdef BUS_DMA_DEBUG 936 printf("\n"); 937 #endif 938 } 939 940 bounce_it: 941 #ifdef _MIPS_NEED_BUS_DMA_BOUNCE 942 if ((ops & BUS_DMASYNC_POSTREAD) == 0 || 943 cookie == NULL || 944 (cookie->id_flags & _BUS_DMA_IS_BOUNCING) == 0 || 945 len == 0) 946 return; 947 948 STAT_INCR(read_bounces); 949 /* 950 * Copy the bounce buffer to the caller's buffer. 951 */ 952 switch (cookie->id_buftype) { 953 case _BUS_DMA_BUFTYPE_LINEAR: 954 memcpy(cookie->id_origlinearbuf + offset, 955 (char *)cookie->id_bouncebuf + offset, len); 956 break; 957 958 case _BUS_DMA_BUFTYPE_MBUF: 959 m_copyback(cookie->id_origmbuf, offset, len, 960 (char *)cookie->id_bouncebuf + offset); 961 break; 962 963 case _BUS_DMA_BUFTYPE_UIO: 964 _bus_dma_uiomove((char *)cookie->id_bouncebuf + offset, 965 cookie->id_origuio, len, UIO_READ); 966 break; 967 #ifdef DIAGNOSTIC 968 case _BUS_DMA_BUFTYPE_RAW: 969 panic("_bus_dmamap_sync: _BUS_DMA_BUFTYPE_RAW"); 970 break; 971 972 case _BUS_DMA_BUFTYPE_INVALID: 973 panic("_bus_dmamap_sync: _BUS_DMA_BUFTYPE_INVALID"); 974 break; 975 976 default: 977 panic("_bus_dmamap_sync: unknown buffer type %d\n", 978 cookie->id_buftype); 979 break; 980 #endif 981 } 982 #endif /* _MIPS_NEED_BUS_DMA_BOUNCE */ 983 return; 984 } 985 986 /* 987 * Common function for DMA-safe memory allocation. May be called 988 * by bus-specific DMA memory allocation functions. 989 */ 990 int 991 _bus_dmamem_alloc(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment, 992 bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs, 993 int flags) 994 { 995 bus_addr_t high; 996 997 if (t->_bounce_alloc_hi != 0 && 998 _BUS_AVAIL_END > t->_bounce_alloc_hi - 1) 999 high = t->_bounce_alloc_hi - 1; 1000 else 1001 high = _BUS_AVAIL_END; 1002 1003 return _bus_dmamem_alloc_range(t, size, alignment, boundary, 1004 segs, nsegs, rsegs, flags, t->_bounce_alloc_lo, high); 1005 } 1006 1007 /* 1008 * Allocate physical memory from the given physical address range. 1009 * Called by DMA-safe memory allocation methods. 1010 */ 1011 int 1012 _bus_dmamem_alloc_range(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment, 1013 bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs, 1014 int flags, paddr_t low, paddr_t high) 1015 { 1016 paddr_t curaddr, lastaddr; 1017 struct vm_page *m; 1018 struct pglist mlist; 1019 int curseg, error; 1020 1021 /* Always round the size. */ 1022 size = round_page(size); 1023 1024 /* 1025 * Allocate pages from the VM system. 1026 */ 1027 error = uvm_pglistalloc(size, low, high, alignment, boundary, 1028 &mlist, nsegs, (flags & BUS_DMA_NOWAIT) == 0); 1029 if (error) 1030 return error; 1031 1032 /* 1033 * Compute the location, size, and number of segments actually 1034 * returned by the VM code. 1035 */ 1036 m = TAILQ_FIRST(&mlist); 1037 curseg = 0; 1038 lastaddr = segs[curseg].ds_addr = VM_PAGE_TO_PHYS(m); 1039 segs[curseg].ds_len = PAGE_SIZE; 1040 m = TAILQ_NEXT(m, pageq.queue); 1041 1042 for (; m != NULL; m = TAILQ_NEXT(m, pageq.queue)) { 1043 curaddr = VM_PAGE_TO_PHYS(m); 1044 #ifdef DIAGNOSTIC 1045 if (curaddr < low || curaddr >= high) { 1046 printf("uvm_pglistalloc returned non-sensical" 1047 " address 0x%"PRIxPADDR"\n", curaddr); 1048 panic("_bus_dmamem_alloc"); 1049 } 1050 #endif 1051 if (curaddr == (lastaddr + PAGE_SIZE)) 1052 segs[curseg].ds_len += PAGE_SIZE; 1053 else { 1054 curseg++; 1055 segs[curseg].ds_addr = curaddr; 1056 segs[curseg].ds_len = PAGE_SIZE; 1057 } 1058 lastaddr = curaddr; 1059 } 1060 1061 *rsegs = curseg + 1; 1062 1063 return 0; 1064 } 1065 1066 /* 1067 * Common function for freeing DMA-safe memory. May be called by 1068 * bus-specific DMA memory free functions. 1069 */ 1070 void 1071 _bus_dmamem_free(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs) 1072 { 1073 struct vm_page *m; 1074 bus_addr_t addr; 1075 struct pglist mlist; 1076 int curseg; 1077 1078 /* 1079 * Build a list of pages to free back to the VM system. 1080 */ 1081 TAILQ_INIT(&mlist); 1082 for (curseg = 0; curseg < nsegs; curseg++) { 1083 for (addr = segs[curseg].ds_addr; 1084 addr < (segs[curseg].ds_addr + segs[curseg].ds_len); 1085 addr += PAGE_SIZE) { 1086 m = PHYS_TO_VM_PAGE(addr); 1087 TAILQ_INSERT_TAIL(&mlist, m, pageq.queue); 1088 } 1089 } 1090 1091 uvm_pglistfree(&mlist); 1092 } 1093 1094 /* 1095 * Common function for mapping DMA-safe memory. May be called by 1096 * bus-specific DMA memory map functions. 1097 */ 1098 int 1099 _bus_dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, 1100 size_t size, void **kvap, int flags) 1101 { 1102 vaddr_t va; 1103 bus_addr_t addr; 1104 int curseg; 1105 const uvm_flag_t kmflags = 1106 (flags & BUS_DMA_NOWAIT) != 0 ? UVM_KMF_NOWAIT : 0; 1107 1108 /* 1109 * If we're only mapping 1 segment, use K0SEG, to avoid 1110 * TLB thrashing. 1111 */ 1112 #ifdef _LP64 1113 if (nsegs == 1) { 1114 if (((mips_options.mips_cpu_flags & CPU_MIPS_D_CACHE_COHERENT) 1115 == 0) && 1116 (flags & BUS_DMA_COHERENT)) 1117 *kvap = (void *)MIPS_PHYS_TO_XKPHYS_UNCACHED( 1118 segs[0].ds_addr); 1119 else 1120 *kvap = (void *)MIPS_PHYS_TO_XKPHYS_CACHED( 1121 segs[0].ds_addr); 1122 return 0; 1123 } 1124 #else 1125 if ((nsegs == 1) && (segs[0].ds_addr < MIPS_PHYS_MASK)) { 1126 if (((mips_options.mips_cpu_flags & CPU_MIPS_D_CACHE_COHERENT) 1127 == 0) && 1128 (flags & BUS_DMA_COHERENT)) 1129 *kvap = (void *)MIPS_PHYS_TO_KSEG1(segs[0].ds_addr); 1130 else 1131 *kvap = (void *)MIPS_PHYS_TO_KSEG0(segs[0].ds_addr); 1132 return 0; 1133 } 1134 #endif /* _LP64 */ 1135 1136 size = round_page(size); 1137 1138 va = uvm_km_alloc(kernel_map, size, 0, UVM_KMF_VAONLY | kmflags); 1139 1140 if (va == 0) 1141 return ENOMEM; 1142 1143 *kvap = (void *)va; 1144 1145 for (curseg = 0; curseg < nsegs; curseg++) { 1146 for (addr = trunc_page(segs[curseg].ds_addr); 1147 addr < (segs[curseg].ds_addr + segs[curseg].ds_len); 1148 addr += PAGE_SIZE, va += PAGE_SIZE, size -= PAGE_SIZE) { 1149 if (size == 0) 1150 panic("_bus_dmamem_map: size botch"); 1151 pmap_enter(pmap_kernel(), va, addr, 1152 VM_PROT_READ | VM_PROT_WRITE, 1153 PMAP_WIRED | VM_PROT_READ | VM_PROT_WRITE); 1154 } 1155 } 1156 pmap_update(pmap_kernel()); 1157 1158 return 0; 1159 } 1160 1161 /* 1162 * Common function for unmapping DMA-safe memory. May be called by 1163 * bus-specific DMA memory unmapping functions. 1164 */ 1165 void 1166 _bus_dmamem_unmap(bus_dma_tag_t t, void *kva, size_t size) 1167 { 1168 1169 #ifdef DIAGNOSTIC 1170 if ((uintptr_t)kva & PGOFSET) 1171 panic("_bus_dmamem_unmap: bad alignment on %p", kva); 1172 #endif 1173 1174 /* 1175 * Nothing to do if we mapped it with KSEG0 or KSEG1 (i.e. 1176 * not in KSEG2 or XKSEG). 1177 */ 1178 if (MIPS_KSEG0_P(kva) || MIPS_KSEG1_P(kva)) 1179 return; 1180 #ifdef _LP64 1181 if (MIPS_XKPHYS_P((vaddr_t)kva)) 1182 return; 1183 #endif 1184 1185 size = round_page(size); 1186 pmap_remove(pmap_kernel(), (vaddr_t)kva, (vaddr_t)kva + size); 1187 pmap_update(pmap_kernel()); 1188 uvm_km_free(kernel_map, (vaddr_t)kva, size, UVM_KMF_VAONLY); 1189 } 1190 1191 /* 1192 * Common function for mmap(2)'ing DMA-safe memory. May be called by 1193 * bus-specific DMA mmap(2)'ing functions. 1194 */ 1195 paddr_t 1196 _bus_dmamem_mmap(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, 1197 off_t off, int prot, int flags) 1198 { 1199 int i; 1200 paddr_t pa; 1201 1202 for (i = 0; i < nsegs; i++) { 1203 #ifdef DIAGNOSTIC 1204 if (off & PGOFSET) 1205 panic("_bus_dmamem_mmap: offset unaligned"); 1206 if (segs[i].ds_addr & PGOFSET) 1207 panic("_bus_dmamem_mmap: segment unaligned"); 1208 if (segs[i].ds_len & PGOFSET) 1209 panic("_bus_dmamem_mmap: segment size not multiple" 1210 " of page size"); 1211 #endif 1212 if (off >= segs[i].ds_len) { 1213 off -= segs[i].ds_len; 1214 continue; 1215 } 1216 1217 pa = (paddr_t)segs[i].ds_addr + off; 1218 1219 /* 1220 * This is for machines which use normal RAM as video memory, so userland can 1221 * mmap() it and treat it like device memory, which is normally uncached. 1222 * Needed for X11 on SGI O2, will likely be needed on things like CI20. 1223 */ 1224 #if defined(_MIPS_PADDR_T_64BIT) || defined(_LP64) 1225 if (flags & BUS_DMA_PREFETCHABLE) 1226 return mips_btop(pa | PGC_NOCACHE); 1227 else 1228 return mips_btop(pa); 1229 #else 1230 return mips_btop(pa); 1231 #endif 1232 } 1233 1234 /* Page not found. */ 1235 return -1; 1236 } 1237 1238 #ifdef _MIPS_NEED_BUS_DMA_BOUNCE 1239 static int 1240 _bus_dma_alloc_bouncebuf(bus_dma_tag_t t, bus_dmamap_t map, 1241 bus_size_t size, int flags) 1242 { 1243 struct mips_bus_dma_cookie *cookie = map->_dm_cookie; 1244 int error = 0; 1245 1246 #ifdef DIAGNOSTIC 1247 if (cookie == NULL) 1248 panic("_bus_dma_alloc_bouncebuf: no cookie"); 1249 #endif 1250 1251 cookie->id_bouncebuflen = round_page(size); 1252 error = _bus_dmamem_alloc(t, cookie->id_bouncebuflen, 1253 PAGE_SIZE, map->_dm_boundary, cookie->id_bouncesegs, 1254 map->_dm_segcnt, &cookie->id_nbouncesegs, flags); 1255 if (error) 1256 goto out; 1257 error = _bus_dmamem_map(t, cookie->id_bouncesegs, 1258 cookie->id_nbouncesegs, cookie->id_bouncebuflen, 1259 (void **)&cookie->id_bouncebuf, flags); 1260 1261 out: 1262 if (error) { 1263 _bus_dmamem_free(t, cookie->id_bouncesegs, 1264 cookie->id_nbouncesegs); 1265 cookie->id_bouncebuflen = 0; 1266 cookie->id_nbouncesegs = 0; 1267 } else { 1268 cookie->id_flags |= _BUS_DMA_HAS_BOUNCE; 1269 } 1270 1271 return error; 1272 } 1273 1274 static void 1275 _bus_dma_free_bouncebuf(bus_dma_tag_t t, bus_dmamap_t map) 1276 { 1277 struct mips_bus_dma_cookie *cookie = map->_dm_cookie; 1278 1279 #ifdef DIAGNOSTIC 1280 if (cookie == NULL) 1281 panic("_bus_dma_alloc_bouncebuf: no cookie"); 1282 #endif 1283 1284 _bus_dmamem_unmap(t, cookie->id_bouncebuf, cookie->id_bouncebuflen); 1285 _bus_dmamem_free(t, cookie->id_bouncesegs, cookie->id_nbouncesegs); 1286 cookie->id_bouncebuflen = 0; 1287 cookie->id_nbouncesegs = 0; 1288 cookie->id_flags &= ~_BUS_DMA_HAS_BOUNCE; 1289 } 1290 1291 /* 1292 * This function does the same as uiomove, but takes an explicit 1293 * direction, and does not update the uio structure. 1294 */ 1295 static int 1296 _bus_dma_uiomove(void *buf, struct uio *uio, size_t n, int direction) 1297 { 1298 struct iovec *iov; 1299 int error; 1300 struct vmspace *vm; 1301 char *cp; 1302 size_t resid, cnt; 1303 int i; 1304 1305 iov = uio->uio_iov; 1306 vm = uio->uio_vmspace; 1307 cp = buf; 1308 resid = n; 1309 1310 for (i = 0; i < uio->uio_iovcnt && resid > 0; i++) { 1311 iov = &uio->uio_iov[i]; 1312 if (iov->iov_len == 0) 1313 continue; 1314 cnt = MIN(resid, iov->iov_len); 1315 1316 if (!VMSPACE_IS_KERNEL_P(vm)) { 1317 preempt_point(); 1318 } 1319 if (direction == UIO_READ) { 1320 error = copyout_vmspace(vm, cp, iov->iov_base, cnt); 1321 } else { 1322 error = copyin_vmspace(vm, iov->iov_base, cp, cnt); 1323 } 1324 if (error) 1325 return error; 1326 cp += cnt; 1327 resid -= cnt; 1328 } 1329 return 0; 1330 } 1331 #endif /* _MIPS_NEED_BUS_DMA_BOUNCE */ 1332 1333 int 1334 _bus_dmatag_subregion(bus_dma_tag_t tag, bus_addr_t min_addr, 1335 bus_addr_t max_addr, bus_dma_tag_t *newtag, int flags) 1336 { 1337 1338 #ifdef _MIPS_NEED_BUS_DMA_BOUNCE 1339 if (((tag->_bounce_thresh != 0 && 1340 max_addr >= tag->_bounce_thresh - 1 && 1341 tag->_bounce_alloc_hi != 0 && 1342 max_addr >= tag->_bounce_alloc_hi - 1) || 1343 (tag->_bounce_alloc_hi == 0 && max_addr > _BUS_AVAIL_END)) && 1344 (min_addr <= tag->_bounce_alloc_lo)) { 1345 *newtag = tag; 1346 /* if the tag must be freed, add a reference */ 1347 if (tag->_tag_needs_free) 1348 tag->_tag_needs_free++; 1349 return 0; 1350 } 1351 1352 if ((*newtag = kmem_alloc(sizeof(struct mips_bus_dma_tag), 1353 (flags & BUS_DMA_NOWAIT) ? KM_NOSLEEP : KM_SLEEP)) == NULL) 1354 return ENOMEM; 1355 1356 **newtag = *tag; 1357 (*newtag)->_tag_needs_free = 1; 1358 1359 if (tag->_bounce_thresh == 0 || max_addr < tag->_bounce_thresh) 1360 (*newtag)->_bounce_thresh = max_addr; 1361 if (tag->_bounce_alloc_hi == 0 || max_addr < tag->_bounce_alloc_hi) 1362 (*newtag)->_bounce_alloc_hi = max_addr; 1363 if (min_addr > tag->_bounce_alloc_lo) 1364 (*newtag)->_bounce_alloc_lo = min_addr; 1365 (*newtag)->_wbase += 1366 (*newtag)->_bounce_alloc_lo - tag->_bounce_alloc_lo; 1367 1368 return 0; 1369 #else 1370 return EOPNOTSUPP; 1371 #endif /* _MIPS_NEED_BUS_DMA_BOUNCE */ 1372 } 1373 1374 void 1375 _bus_dmatag_destroy(bus_dma_tag_t tag) 1376 { 1377 #ifdef _MIPS_NEED_BUS_DMA_BOUNCE 1378 switch (tag->_tag_needs_free) { 1379 case 0: 1380 break; /* not allocated with malloc */ 1381 case 1: 1382 kmem_free(tag, sizeof(*tag)); /* last reference to tag */ 1383 break; 1384 default: 1385 tag->_tag_needs_free--; /* one less reference */ 1386 } 1387 #endif 1388 } 1389