1 /* $NetBSD: bus_dma.c,v 1.44 2026/05/06 04:45:03 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1997, 1998 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 "opt_m68k_arch.h" 34 35 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 36 37 __KERNEL_RCSID(0, "$NetBSD: bus_dma.c,v 1.44 2026/05/06 04:45:03 thorpej Exp $"); 38 39 #define _M68K_BUS_DMA_PRIVATE 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/kernel.h> 44 #include <sys/device.h> 45 #include <sys/kmem.h> 46 #include <sys/proc.h> 47 #include <sys/mbuf.h> 48 49 #include <uvm/uvm.h> 50 51 #include <machine/cpu.h> 52 #include <machine/bus.h> 53 #include <m68k/cacheops.h> 54 55 static size_t 56 _bus_dmamap_mapsize(int const nsegments) 57 { 58 KASSERT(nsegments > 0); 59 return sizeof(struct m68k_bus_dmamap) + 60 (sizeof(bus_dma_segment_t) * (nsegments - 1)); 61 } 62 63 /* 64 * Common function for DMA map creation. May be called by bus-specific 65 * DMA map creation functions. 66 */ 67 int 68 _bus_dmamap_create(bus_dma_tag_t t, bus_size_t size, int nsegments, 69 bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp) 70 { 71 struct m68k_bus_dmamap *map; 72 void *mapstore; 73 74 /* 75 * Allocate and initialize the DMA map. The end of the map 76 * is a variable-sized array of segments, so we allocate enough 77 * room for them in one shot. 78 * 79 * Note we don't preserve the WAITOK or NOWAIT flags. Preservation 80 * of ALLOCNOW notifies others that we've reserved these resources, 81 * and they are not to be freed. 82 * 83 * The bus_dmamap_t includes one bus_dma_segment_t, hence 84 * the (nsegments - 1). 85 */ 86 if ((mapstore = kmem_zalloc(_bus_dmamap_mapsize(nsegments), 87 (flags & BUS_DMA_NOWAIT) ? KM_NOSLEEP : KM_SLEEP)) == NULL) 88 return ENOMEM; 89 90 map = (struct m68k_bus_dmamap *)mapstore; 91 map->_dm_size = size; 92 map->_dm_segcnt = nsegments; 93 map->_dm_maxmaxsegsz = maxsegsz; 94 if (t->_boundary != 0 && (boundary == 0 || t->_boundary < boundary)) 95 map->_dm_boundary = t->_boundary; 96 else 97 map->_dm_boundary = boundary; 98 map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT); 99 map->dm_maxsegsz = maxsegsz; 100 map->dm_mapsize = 0; /* no valid mappings */ 101 map->dm_nsegs = 0; 102 103 *dmamp = map; 104 return 0; 105 } 106 107 /* 108 * Common function for DMA map destruction. May be called by bus-specific 109 * DMA map destruction functions. 110 */ 111 void 112 _bus_dmamap_destroy(bus_dma_tag_t t, bus_dmamap_t map) 113 { 114 115 kmem_free(map, _bus_dmamap_mapsize(map->_dm_segcnt)); 116 } 117 118 /* 119 * Utility function to load a linear buffer. lastaddrp holds state 120 * between invocations (for multiple-buffer loads). segp contains 121 * the starting segment on entrance, and the ending segment on exit. 122 * first indicates if this is the first invocation of this function. 123 */ 124 static int 125 _bus_dmamap_load_buffer_direct_common(bus_dma_tag_t t, bus_dmamap_t map, 126 void *buf, bus_size_t buflen, struct vmspace *vm, int flags, 127 paddr_t *lastaddrp, int *segp, int first) 128 { 129 bus_size_t sgsize; 130 bus_addr_t curaddr, lastaddr, baddr, bmask; 131 vaddr_t vaddr = (vaddr_t)buf; 132 int seg, cacheable, coherent = BUS_DMA_COHERENT; 133 pmap_t pmap; 134 bool rv __diagused; 135 136 lastaddr = *lastaddrp; 137 bmask = ~(map->_dm_boundary - 1); 138 139 if (!VMSPACE_IS_KERNEL_P(vm)) 140 pmap = vm_map_pmap(&vm->vm_map); 141 else 142 pmap = pmap_kernel(); 143 144 for (seg = *segp; buflen > 0 ; ) { 145 /* 146 * Get the physical address for this segment. 147 */ 148 #if defined(__HAVE_NEW_PMAP_68K) 149 rv = pmap_extract_info(pmap, vaddr, &curaddr, &cacheable); 150 KASSERT(rv); 151 cacheable = !(cacheable & PMAP_NOCACHE); 152 #else 153 rv = pmap_extract(pmap, vaddr, (paddr_t *) &curaddr); 154 KASSERT(rv); 155 cacheable = _pmap_page_is_cacheable(pmap, vaddr); 156 #endif /* __HAVE_NEW_PMAP_68K */ 157 158 if (cacheable) 159 coherent = 0; 160 161 /* 162 * Compute the segment size, and adjust counts. 163 */ 164 sgsize = PAGE_SIZE - ((u_long)vaddr & PAGE_MASK); 165 if (buflen < sgsize) 166 sgsize = buflen; 167 168 /* 169 * Make sure we don't cross any boundaries. 170 */ 171 if (map->_dm_boundary > 0) { 172 baddr = (curaddr + map->_dm_boundary) & bmask; 173 if (sgsize > (baddr - curaddr)) 174 sgsize = (baddr - curaddr); 175 } 176 177 /* 178 * Insert chunk into a segment, coalescing with 179 * the previous segment if possible. 180 */ 181 if (first) { 182 map->dm_segs[seg].ds_addr = 183 map->dm_segs[seg]._ds_cpuaddr = curaddr; 184 map->dm_segs[seg].ds_len = sgsize; 185 map->dm_segs[seg]._ds_flags = 186 cacheable ? 0 : BUS_DMA_COHERENT; 187 first = 0; 188 } else { 189 if (curaddr == lastaddr && 190 (map->dm_segs[seg].ds_len + sgsize) <= 191 map->dm_maxsegsz && 192 (map->_dm_boundary == 0 || 193 (map->dm_segs[seg].ds_addr & bmask) == 194 (curaddr & bmask))) 195 map->dm_segs[seg].ds_len += sgsize; 196 else { 197 if (++seg >= map->_dm_segcnt) 198 break; 199 map->dm_segs[seg].ds_addr = 200 map->dm_segs[seg]._ds_cpuaddr = curaddr; 201 map->dm_segs[seg].ds_len = sgsize; 202 map->dm_segs[seg]._ds_flags = 203 cacheable ? 0 : BUS_DMA_COHERENT; 204 } 205 } 206 207 lastaddr = curaddr + sgsize; 208 vaddr += sgsize; 209 buflen -= sgsize; 210 } 211 212 *segp = seg; 213 *lastaddrp = lastaddr; 214 215 /* BUS_DMA_COHERENT is set only if all segments are uncached */ 216 map->_dm_flags &= ~BUS_DMA_COHERENT; 217 map->_dm_flags |= coherent; 218 219 /* 220 * Did we fit? 221 */ 222 if (buflen != 0) { 223 /* 224 * If there is a chained window, we will automatically 225 * fall back to it. 226 */ 227 return EFBIG; /* XXX better return value here? */ 228 } 229 230 return 0; 231 } 232 233 /* 234 * Common function for loading a direct-mapped DMA map with a linear 235 * buffer. Called by bus-specific DMA map load functions with the 236 * OR value appropriate for indicating "direct-mapped" for that 237 * chipset. 238 */ 239 int 240 _bus_dmamap_load_direct(bus_dma_tag_t t, bus_dmamap_t map, void *buf, 241 bus_size_t buflen, struct proc *p, int flags) 242 { 243 paddr_t lastaddr; 244 int seg, error; 245 struct vmspace *vm; 246 247 /* 248 * Make sure that on error condition we return "no valid mappings". 249 */ 250 map->dm_mapsize = 0; 251 map->dm_nsegs = 0; 252 KASSERT(map->dm_maxsegsz <= map->_dm_maxmaxsegsz); 253 254 if (buflen > map->_dm_size) 255 return (EINVAL); 256 257 if (p != NULL) { 258 vm = p->p_vmspace; 259 } else { 260 vm = vmspace_kernel(); 261 } 262 263 seg = 0; 264 error = _bus_dmamap_load_buffer_direct_common(t, map, buf, buflen, 265 vm, flags, &lastaddr, &seg, 1); 266 if (error == 0) { 267 map->dm_mapsize = buflen; 268 map->dm_nsegs = seg + 1; 269 } 270 return error; 271 } 272 273 /* 274 * Like _bus_dmamap_load_direct_common(), but for mbufs. 275 */ 276 int 277 _bus_dmamap_load_mbuf_direct(bus_dma_tag_t t, bus_dmamap_t map, 278 struct mbuf *m0, int flags) 279 { 280 paddr_t lastaddr; 281 int seg, error, first; 282 struct mbuf *m; 283 284 /* 285 * Make sure that on error condition we return "no valid mappings." 286 */ 287 map->dm_mapsize = 0; 288 map->dm_nsegs = 0; 289 KASSERT(map->dm_maxsegsz <= map->_dm_maxmaxsegsz); 290 291 KASSERT((m0->m_flags & M_PKTHDR) != 0); 292 293 if (m0->m_pkthdr.len > map->_dm_size) 294 return EINVAL; 295 296 first = 1; 297 seg = 0; 298 error = 0; 299 for (m = m0; m != NULL && error == 0; m = m->m_next) { 300 if (m->m_len == 0) 301 continue; 302 error = _bus_dmamap_load_buffer_direct_common(t, map, 303 m->m_data, m->m_len, vmspace_kernel(), flags, &lastaddr, 304 &seg, first); 305 first = 0; 306 } 307 if (error == 0) { 308 map->dm_mapsize = m0->m_pkthdr.len; 309 map->dm_nsegs = seg + 1; 310 } 311 return error; 312 } 313 314 /* 315 * Like _bus_dmamap_load_direct_common(), but for uios. 316 */ 317 int 318 _bus_dmamap_load_uio_direct(bus_dma_tag_t t, bus_dmamap_t map, struct uio *uio, 319 int flags) 320 { 321 paddr_t lastaddr; 322 int seg, i, error, first; 323 bus_size_t minlen, resid; 324 struct iovec *iov; 325 void *addr; 326 327 /* 328 * Make sure that on error condition we return "no valid mappings." 329 */ 330 map->dm_mapsize = 0; 331 map->dm_nsegs = 0; 332 KASSERT(map->dm_maxsegsz <= map->_dm_maxmaxsegsz); 333 334 resid = uio->uio_resid; 335 iov = uio->uio_iov; 336 337 first = 1; 338 seg = 0; 339 error = 0; 340 for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0; i++) { 341 /* 342 * Now at the first iovec to load. Load each iovec 343 * until we have exhausted the residual count. 344 */ 345 minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len; 346 addr = (void *)iov[i].iov_base; 347 348 error = _bus_dmamap_load_buffer_direct_common(t, map, 349 addr, minlen, uio->uio_vmspace, flags, &lastaddr, &seg, 350 first); 351 first = 0; 352 353 resid -= minlen; 354 } 355 if (error == 0) { 356 map->dm_mapsize = uio->uio_resid; 357 map->dm_nsegs = seg + 1; 358 } 359 return error; 360 } 361 362 /* 363 * Like _bus_dmamap_load_direct_common(), but for raw memory. 364 */ 365 int 366 _bus_dmamap_load_raw_direct(bus_dma_tag_t t, bus_dmamap_t map, 367 bus_dma_segment_t *segs, int nsegs, bus_size_t size, int flags) 368 { 369 int i; 370 371 /* 372 * @@@ This routine doesn't enforce map boundary requirement 373 * @@@ perhaps it should return an error instead of panicking 374 */ 375 376 KASSERT(size <= map->_dm_size); 377 KASSERT(nsegs <= map->_dm_segcnt); 378 379 for (i = 0; i < nsegs; i++) { 380 KASSERT(map->dm_segs[i].ds_len <= map->dm_maxsegsz); 381 map->dm_segs[i] = segs[i]; 382 } 383 384 map->dm_nsegs = nsegs; 385 map->dm_mapsize = size; 386 387 return 0; 388 } 389 390 /* 391 * Common function for unloading a DMA map. May be called by 392 * chipset-specific DMA map unload functions. 393 */ 394 void 395 _bus_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t map) 396 { 397 398 /* 399 * No resources to free; just mark the mappings as 400 * invalid. 401 */ 402 map->dm_maxsegsz = map->_dm_maxmaxsegsz; 403 map->dm_mapsize = 0; 404 map->dm_nsegs = 0; 405 map->_dm_flags &= ~BUS_DMA_COHERENT; 406 } 407 408 #if defined(M68010) || defined(M68020) 409 /* 410 * DMA map synchronization for the 68010 and 68020. These CPUs don't 411 * have on-chip data caches at all, so this is a no-op unless there's 412 * an external cache. 413 */ 414 void 415 _bus_dmamap_sync_1020(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset, 416 bus_size_t len, int ops) 417 { 418 #ifdef M68K_EC 419 /* If the whole DMA map is uncached, do nothing. */ 420 if (map->_dm_flags & BUS_DMA_COHERENT) 421 return; 422 423 if (ectype != EC_NONE) { 424 /* 425 * See explainer below in _bus_dmamap_sync_30(). 426 */ 427 if (ops & BUS_DMASYNC_PREREAD) { 428 PCIA(); 429 } 430 } 431 #endif 432 return; 433 } 434 #endif /* M68010 || M68020 */ 435 436 #if defined(M68030) 437 /* 438 * 68030 DMA map synchronization. May be called 439 * by chipset-specific DMA map synchronization functions. 440 */ 441 void 442 _bus_dmamap_sync_30(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset, 443 bus_size_t len, int ops) 444 { 445 /* If the whole DMA map is uncached, do nothing. */ 446 if (map->_dm_flags & BUS_DMA_COHERENT) 447 return; 448 449 /* 450 * 68030 caches are write-through, so this is trivial; we only 451 * need to invalidate the cache (on-chip and external, if present) 452 * before a DMA read. 453 * 454 * We do this in PREREAD to remain aligned with the 68040/68060 455 * implementation, which also needs to do this work in PREREAD 456 * (since write-backs may be involved). We obviously don't have 457 * to worry about write-backs here, but this should mean that 458 * programming errors that cause cache-fills from the memory region 459 * that's part of the DMA operation would tend to show up on both 460 * CPU types. 461 */ 462 if (ops & BUS_DMASYNC_PREREAD) { 463 PCIA(); 464 } 465 } 466 #endif /* M68030 */ 467 468 #if defined(M68040) || defined(M68060) 469 /* 470 * 68040/68060 DMA map synchronization. May be called 471 * by chipset-specific DMA map synchronization functions. 472 */ 473 void 474 _bus_dmamap_sync_4060(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset, 475 bus_size_t len, int ops) 476 { 477 bus_addr_t p, e, ps, pe; 478 bus_size_t seglen; 479 bus_dma_segment_t *seg; 480 int i; 481 482 /* If the whole DMA map is uncached, do nothing. */ 483 if ((map->_dm_flags & BUS_DMA_COHERENT) != 0) 484 return; 485 486 /* Short-circuit for unsupported `ops' */ 487 if ((ops & (BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE)) == 0) 488 return; 489 490 for (i = 0; i < map->dm_nsegs && len != 0; i++) { 491 seg = &map->dm_segs[i]; 492 if (seg->ds_len <= offset) { 493 /* Segment irrelevant - before requested offset */ 494 offset -= seg->ds_len; 495 continue; 496 } 497 498 /* 499 * Now at the first segment to sync; nail 500 * each segment until we have exhausted the 501 * length. 502 */ 503 seglen = seg->ds_len - offset; 504 if (seglen > len) 505 seglen = len; 506 len -= seglen; 507 offset = 0; 508 509 /* Ignore cache-inhibited segments */ 510 if ((seg->_ds_flags & BUS_DMA_COHERENT) != 0) 511 continue; 512 513 ps = seg->_ds_cpuaddr + offset; 514 pe = ps + seglen; 515 516 /* N.B. '40 cache ops are the same as '60 */ 517 518 if (ops & BUS_DMASYNC_PREWRITE) { 519 p = ps & ~CACHELINE_MASK; 520 e = (pe + CACHELINE_MASK) & ~CACHELINE_MASK; 521 522 /* flush cacheline */ 523 while ((p < e) && (p & (CACHELINE_SIZE * 8 - 1)) != 0) { 524 DCFL_40(p); 525 p += CACHELINE_SIZE; 526 } 527 528 /* flush cachelines per 128bytes */ 529 while ((p + CACHELINE_SIZE * 8 <= e) && 530 (p & PAGE_MASK) != 0) { 531 DCFL_40(p); 532 p += CACHELINE_SIZE; 533 DCFL_40(p); 534 p += CACHELINE_SIZE; 535 DCFL_40(p); 536 p += CACHELINE_SIZE; 537 DCFL_40(p); 538 p += CACHELINE_SIZE; 539 DCFL_40(p); 540 p += CACHELINE_SIZE; 541 DCFL_40(p); 542 p += CACHELINE_SIZE; 543 DCFL_40(p); 544 p += CACHELINE_SIZE; 545 DCFL_40(p); 546 p += CACHELINE_SIZE; 547 } 548 549 /* flush page */ 550 while (p + PAGE_SIZE <= e) { 551 DCFP_40(p); 552 p += PAGE_SIZE; 553 } 554 555 /* flush cachelines per 128bytes */ 556 while (p + CACHELINE_SIZE * 8 <= e) { 557 DCFL_40(p); 558 p += CACHELINE_SIZE; 559 DCFL_40(p); 560 p += CACHELINE_SIZE; 561 DCFL_40(p); 562 p += CACHELINE_SIZE; 563 DCFL_40(p); 564 p += CACHELINE_SIZE; 565 DCFL_40(p); 566 p += CACHELINE_SIZE; 567 DCFL_40(p); 568 p += CACHELINE_SIZE; 569 DCFL_40(p); 570 p += CACHELINE_SIZE; 571 DCFL_40(p); 572 p += CACHELINE_SIZE; 573 } 574 575 /* flush cacheline */ 576 while (p < e) { 577 DCFL_40(p); 578 p += CACHELINE_SIZE; 579 } 580 } 581 582 /* 583 * Normally, the `PREREAD' flag instructs us to purge the 584 * cache for the specified offset and length. However, if 585 * the offset/length is not aligned to a cacheline boundary, 586 * we may end up purging some legitimate data from the 587 * start/end of the cache. In such a case, *flush* the 588 * cachelines at the start and end of the required region. 589 */ 590 else if (ops & BUS_DMASYNC_PREREAD) { 591 /* flush cacheline on start boundary */ 592 if (ps & CACHELINE_MASK) { 593 DCFL_40(ps & ~CACHELINE_MASK); 594 } 595 596 p = (ps + CACHELINE_MASK) & ~CACHELINE_MASK; 597 e = pe & ~CACHELINE_MASK; 598 599 /* purge cacheline */ 600 while ((p < e) && (p & (CACHELINE_SIZE * 8 - 1)) != 0) { 601 DCPL_40(p); 602 p += CACHELINE_SIZE; 603 } 604 605 /* purge cachelines per 128bytes */ 606 while ((p + CACHELINE_SIZE * 8 <= e) && 607 (p & PAGE_MASK) != 0) { 608 DCPL_40(p); 609 p += CACHELINE_SIZE; 610 DCPL_40(p); 611 p += CACHELINE_SIZE; 612 DCPL_40(p); 613 p += CACHELINE_SIZE; 614 DCPL_40(p); 615 p += CACHELINE_SIZE; 616 DCPL_40(p); 617 p += CACHELINE_SIZE; 618 DCPL_40(p); 619 p += CACHELINE_SIZE; 620 DCPL_40(p); 621 p += CACHELINE_SIZE; 622 DCPL_40(p); 623 p += CACHELINE_SIZE; 624 } 625 626 /* purge page */ 627 while (p + PAGE_SIZE <= e) { 628 DCPP_40(p); 629 ICPP_40(p); 630 p += PAGE_SIZE; 631 } 632 633 /* purge cachelines per 128bytes */ 634 while (p + CACHELINE_SIZE * 8 <= e) { 635 DCPL_40(p); 636 p += CACHELINE_SIZE; 637 DCPL_40(p); 638 p += CACHELINE_SIZE; 639 DCPL_40(p); 640 p += CACHELINE_SIZE; 641 DCPL_40(p); 642 p += CACHELINE_SIZE; 643 DCPL_40(p); 644 p += CACHELINE_SIZE; 645 DCPL_40(p); 646 p += CACHELINE_SIZE; 647 DCPL_40(p); 648 p += CACHELINE_SIZE; 649 DCPL_40(p); 650 p += CACHELINE_SIZE; 651 } 652 653 /* purge cacheline */ 654 while (p < e) { 655 DCPL_40(p); 656 p += CACHELINE_SIZE; 657 } 658 659 /* flush cacheline on end boundary */ 660 if (p < pe) { 661 DCFL_40(p); 662 } 663 } 664 } 665 } 666 #endif /* M68040 || M68060 */ 667 668 /* 669 * If we're configured for only a single CPU cache class, then resolve 670 * the DMA map sync routine at compile time. 671 */ 672 #if (defined(M68010) || defined(M68020)) && \ 673 !(defined(M68030) || defined(M68040) || defined(M68060)) 674 __strong_alias(_bus_dmamap_sync,_bus_dmamap_sync_1020) 675 #elif defined(M68030) && \ 676 !(defined(M68010) || defined(M68020) || defined(M68040) || \ 677 defined(M68060)) 678 __strong_alias(_bus_dmamap_sync,_bus_dmamap_sync_30) 679 #elif (defined(M68040) || defined(M68060)) && \ 680 !(defined(M68010) || defined(M68020) || defined(M68030)) 681 __strong_alias(_bus_dmamap_sync,_bus_dmamap_sync_4060) 682 #else /* run-time */ 683 void 684 _bus_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset, 685 bus_size_t len, int ops) 686 { 687 switch (cputype) { 688 #if defined(M68010) || defined(M68020) 689 case CPU_68010: 690 case CPU_68020: 691 _bus_dmamap_sync_1020(t, map, offset, len, ops); 692 break; 693 #endif 694 #if defined(M68030) 695 case CPU_68030: 696 _bus_dmamap_sync_30(t, map, offset, len, ops); 697 break; 698 #endif 699 #if defined(M68040) || defined(M68060) 700 case CPU_68040: 701 case CPU_68060: 702 _bus_dmamap_sync_4060(t, map, offset, len, ops); 703 break; 704 #endif 705 default: 706 panic("%s", __func__); 707 } 708 } 709 #endif /* CPU cache class */ 710 711 /* 712 * Common function for DMA-safe memory allocation. May be called 713 * by bus-specific DMA memory allocation functions. 714 */ 715 int 716 _bus_dmamem_alloc_common(bus_dma_tag_t t, bus_addr_t low, bus_addr_t high, 717 bus_size_t size, bus_size_t alignment, bus_size_t boundary, 718 bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags) 719 { 720 paddr_t curaddr, lastaddr; 721 struct vm_page *m; 722 struct pglist mlist; 723 int curseg, error; 724 725 /* Constrain the upper-bound, if needed. */ 726 if (flags & BUS_DMA_24BIT) { 727 if (low >= 0x01000000u) { 728 /* Can't satisfy the request. */ 729 return EINVAL; 730 } 731 if (high & 0xff000000u) { 732 high = 0x01000000u; 733 } 734 } 735 736 /* Always round the size. */ 737 size = round_page(size); 738 high -= PAGE_SIZE; 739 740 /* 741 * Allocate pages from the VM system. 742 * 743 * XXX mvme68k-specific comment 744 * XXXSCW: This will be sub-optimal if the base-address of offboard 745 * RAM is significantly higher than the end-address of onboard RAM. 746 * (Due to how uvm_pglistalloc() is implemented.) 747 * 748 * uvm_pglistalloc() also currently ignores the 'nsegs' parameter, 749 * and always returns only one (contiguous) segment. 750 */ 751 error = uvm_pglistalloc(size, low, high, alignment, boundary, 752 &mlist, nsegs, (flags & BUS_DMA_NOWAIT) == 0); 753 if (error) 754 return error; 755 756 /* 757 * Compute the location, size, and number of segments actually 758 * returned by the VM code. 759 */ 760 m = mlist.tqh_first; 761 curseg = 0; 762 lastaddr = VM_PAGE_TO_PHYS(m); 763 segs[curseg].ds_addr = segs[curseg]._ds_cpuaddr = lastaddr; 764 segs[curseg].ds_len = PAGE_SIZE; 765 segs[curseg]._ds_flags = 0; 766 m = m->pageq.queue.tqe_next; 767 768 for (; m != NULL; m = m->pageq.queue.tqe_next) { 769 curaddr = VM_PAGE_TO_PHYS(m); 770 KASSERT(curaddr >= low); 771 KASSERT(curaddr < high); 772 773 if (curaddr == (lastaddr + PAGE_SIZE)) 774 segs[curseg].ds_len += PAGE_SIZE; 775 else { 776 if (++curseg >= nsegs) { 777 #ifdef DIAGNOSTIC 778 printf("%s: too many segments\n", __func__); 779 #ifdef DEBUG 780 panic("%s", __func__); 781 #endif 782 #endif 783 uvm_pglistfree(&mlist); 784 return -1; 785 } 786 segs[curseg].ds_addr = 787 segs[curseg]._ds_cpuaddr = curaddr; 788 segs[curseg].ds_len = PAGE_SIZE; 789 segs[curseg]._ds_flags = 0; 790 } 791 lastaddr = curaddr; 792 } 793 794 *rsegs = curseg + 1; 795 796 return 0; 797 } 798 799 /* 800 * Common function for DMA-safe memory allocation. May be called 801 * by bus-specific DMA memory allocation functions. 802 */ 803 int 804 _bus_dmamem_alloc(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment, 805 bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs, 806 int flags) 807 { 808 extern paddr_t avail_start, avail_end; 809 810 return _bus_dmamem_alloc_common(t, avail_start, avail_end, 811 size, alignment, boundary, segs, nsegs, rsegs, flags); 812 } 813 814 /* 815 * Common function for freeing DMA-safe memory. May be called by 816 * bus-specific DMA memory free functions. 817 */ 818 void 819 _bus_dmamem_free(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs) 820 { 821 struct vm_page *m; 822 bus_addr_t addr; 823 struct pglist mlist; 824 int curseg; 825 826 /* 827 * Build a list of pages to free back to the VM system. 828 */ 829 TAILQ_INIT(&mlist); 830 for (curseg = 0; curseg < nsegs; curseg++) { 831 for (addr = segs[curseg]._ds_cpuaddr; 832 addr < (segs[curseg]._ds_cpuaddr + segs[curseg].ds_len); 833 addr += PAGE_SIZE) { 834 m = PHYS_TO_VM_PAGE(addr); 835 TAILQ_INSERT_TAIL(&mlist, m, pageq.queue); 836 } 837 } 838 839 uvm_pglistfree(&mlist); 840 } 841 842 /* 843 * Common function for mapping DMA-safe memory. May be called by 844 * bus-specific DMA memory map functions. 845 */ 846 int 847 _bus_dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, 848 size_t size, void **kvap, int flags) 849 { 850 vaddr_t va; 851 bus_addr_t addr; 852 int curseg; 853 const uvm_flag_t kmflags = 854 (flags & BUS_DMA_NOWAIT) != 0 ? UVM_KMF_NOWAIT : 0; 855 const int pmap_flags = 856 VM_PROT_READ | VM_PROT_WRITE | PMAP_WIRED | 857 ((flags & BUS_DMA_COHERENT) ? PMAP_NOCACHE : 0); 858 859 size = round_page(size); 860 861 va = uvm_km_alloc(kernel_map, size, 0, UVM_KMF_VAONLY | kmflags); 862 863 if (va == 0) 864 return ENOMEM; 865 866 *kvap = (void *)va; 867 868 for (curseg = 0; curseg < nsegs; curseg++) { 869 for (addr = segs[curseg]._ds_cpuaddr; 870 addr < (segs[curseg]._ds_cpuaddr + segs[curseg].ds_len); 871 addr += PAGE_SIZE, va += PAGE_SIZE, size -= PAGE_SIZE) { 872 if (size == 0) 873 panic("%s: size botch", __func__); 874 875 pmap_enter(pmap_kernel(), va, addr, 876 VM_PROT_READ | VM_PROT_WRITE, pmap_flags); 877 878 #if !defined(__HAVE_NEW_PMAP_68K) 879 /* Cache-inhibit the page if necessary */ 880 if ((flags & BUS_DMA_COHERENT) != 0) 881 _pmap_set_page_cacheinhibit(pmap_kernel(), va); 882 #endif /* ! __HAVE_NEW_PMAP_68K */ 883 884 segs[curseg]._ds_flags &= ~BUS_DMA_COHERENT; 885 segs[curseg]._ds_flags |= (flags & BUS_DMA_COHERENT); 886 } 887 } 888 pmap_update(pmap_kernel()); 889 890 if ((flags & BUS_DMA_COHERENT) != 0) 891 TBIAS(); 892 893 return 0; 894 } 895 896 /* 897 * Common function for unmapping DMA-safe memory. May be called by 898 * bus-specific DMA memory unmapping functions. 899 */ 900 void 901 _bus_dmamem_unmap(bus_dma_tag_t t, void *kva, size_t size) 902 { 903 vaddr_t va; 904 905 KASSERT(((vaddr_t)kva & PAGE_MASK) == 0); 906 907 size = round_page(size); 908 909 #if !defined(__HAVE_NEW_PMAP_68K) 910 /* 911 * Re-enable cacheing on the range 912 * XXXSCW: There should be some way to indicate that the pages 913 * were mapped DMA_MAP_COHERENT in the first place... 914 */ 915 size_t s; 916 917 for (s = 0, va = (vaddr_t)kva; s < size; 918 s += PAGE_SIZE, va += PAGE_SIZE) 919 _pmap_set_page_cacheable(pmap_kernel(), va); 920 #endif /* __HAVE_NEW_PMAP_68K */ 921 922 va = (vaddr_t)kva; 923 pmap_remove(pmap_kernel(), va, (vaddr_t)kva + size); 924 pmap_update(pmap_kernel()); 925 uvm_km_free(kernel_map, (vaddr_t)kva, size, UVM_KMF_VAONLY); 926 } 927 928 /* 929 * Common function for mmap(2)'ing DMA-safe memory. May be called by 930 * bus-specific DMA mmap(2)'ing functions. 931 */ 932 paddr_t 933 _bus_dmamem_mmap(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, off_t off, 934 int prot, int flags) 935 { 936 int i; 937 938 for (i = 0; i < nsegs; i++) { 939 KASSERT((off & PAGE_MASK) == 0); 940 KASSERT((segs[i].ds_addr & PAGE_MASK) == 0); 941 KASSERT((segs[i].ds_len & PAGE_MASK) == 0); 942 943 if (off >= segs[i].ds_len) { 944 off -= segs[i].ds_len; 945 continue; 946 } 947 948 /* 949 * XXXSCW: What about BUS_DMA_COHERENT ?? 950 */ 951 952 return m68k_btop((char *)segs[i]._ds_cpuaddr + off); 953 } 954 955 /* Page not found. */ 956 return -1; 957 } 958