1 /* $NetBSD: bus.c,v 1.13 2002/03/13 13:12:29 simonb Exp $ */ 2 3 /* 4 * Copyright (c) 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 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/endian.h> 43 #include <sys/bswap.h> 44 #include <sys/kernel.h> 45 #include <sys/device.h> 46 #include <sys/malloc.h> 47 #include <sys/proc.h> 48 #include <sys/mbuf.h> 49 50 #define _SGIMIPS_BUS_DMA_PRIVATE 51 #include <machine/bus.h> 52 #include <machine/cpu.h> 53 54 #include <uvm/uvm_extern.h> 55 56 #include <mips/cpuregs.h> 57 #include <mips/locore.h> 58 #include <mips/cache.h> 59 60 static int _bus_dmamap_load_buffer(bus_dmamap_t, void *, bus_size_t, 61 struct proc *, int, vaddr_t *, int *, int); 62 63 struct sgimips_bus_dma_tag sgimips_default_bus_dma_tag = { 64 _bus_dmamap_create, 65 _bus_dmamap_destroy, 66 _bus_dmamap_load, 67 _bus_dmamap_load_mbuf, 68 _bus_dmamap_load_uio, 69 _bus_dmamap_load_raw, 70 _bus_dmamap_unload, 71 _bus_dmamap_sync, 72 _bus_dmamem_alloc, 73 _bus_dmamem_free, 74 _bus_dmamem_map, 75 _bus_dmamem_unmap, 76 _bus_dmamem_mmap, 77 }; 78 79 u_int8_t 80 bus_space_read_1(t, h, o) 81 bus_space_tag_t t; 82 bus_space_handle_t h; 83 bus_size_t o; 84 { 85 wbflush(); /* XXX ? */ 86 87 switch (t) { 88 case 0: 89 return *(volatile u_int8_t *)(h + o); 90 case 1: /* XXX HPC */ 91 return *(volatile u_int8_t *)(h + (o << 2) + 3); 92 case 2: /* mem */ 93 case 4: /* I/O */ 94 return *(volatile u_int8_t *)(h + (o | 3) - (o & 3)); 95 case 3: /* mace devices */ 96 return *(volatile u_int8_t *)(h + (o << 8) + 7); 97 default: 98 panic("no bus tag"); 99 } 100 } 101 102 void 103 bus_space_write_1(t, h, o, v) 104 bus_space_tag_t t; 105 bus_space_handle_t h; 106 bus_size_t o; 107 u_int8_t v; 108 { 109 switch (t) { 110 case 0: 111 *(volatile u_int8_t *)(h + o) = v; 112 break; 113 case 1: /* XXX HPC */ 114 *(volatile u_int8_t *)(h + (o << 2) + 3) = v; 115 break; 116 case 2: /* mem */ 117 case 4: /* I/O */ 118 *(volatile u_int8_t *)(h + (o | 3) - (o & 3)) = v; 119 break; 120 case 3: /* mace devices */ 121 *(volatile u_int8_t *)(h + (o << 8) + 7) = v; 122 break; 123 default: 124 panic("no bus tag"); 125 } 126 127 wbflush(); /* XXX */ 128 } 129 130 u_int16_t 131 bus_space_read_2(t, h, o) 132 bus_space_tag_t t; 133 bus_space_handle_t h; 134 bus_size_t o; 135 { 136 wbflush(); /* XXX ? */ 137 138 switch (t) { 139 case 0: 140 return *(volatile u_int16_t *)(h + o); 141 case 1: /* XXX HPC */ 142 return *(volatile u_int16_t *)(h + (o << 2) + 1); 143 case 2: /* mem */ 144 return *(volatile u_int16_t *)(h + (o | 2) - (o & 3)); 145 case 4: /* I/O */ 146 return bswap16(*(volatile u_int16_t *)(h + (o | 2) - (o & 3))); 147 default: 148 panic("no bus tag"); 149 } 150 } 151 152 void 153 bus_space_write_2(t, h, o, v) 154 bus_space_tag_t t; 155 bus_space_handle_t h; 156 bus_size_t o; 157 u_int16_t v; 158 { 159 switch (t) { 160 case 0: 161 *(volatile u_int16_t *)(h + o) = v; 162 break; 163 case 1: /* XXX HPC */ 164 *(volatile u_int16_t *)(h + (o << 2) + 1) = v; 165 break; 166 case 2: /* mem */ 167 *(volatile u_int16_t *)(h + (o | 2) - (o & 3)) = v; 168 break; 169 case 4: /* I/O */ 170 *(volatile u_int16_t *)(h + (o | 2) - (o & 3)) = bswap16(v); 171 break; 172 default: 173 panic("no bus tag"); 174 } 175 176 wbflush(); /* XXX */ 177 } 178 179 int 180 bus_space_map(t, bpa, size, flags, bshp) 181 bus_space_tag_t t; 182 bus_addr_t bpa; 183 bus_size_t size; 184 int flags; 185 bus_space_handle_t *bshp; 186 { 187 int cacheable = flags & BUS_SPACE_MAP_CACHEABLE; 188 189 if (cacheable) 190 *bshp = MIPS_PHYS_TO_KSEG0(bpa); 191 else 192 *bshp = MIPS_PHYS_TO_KSEG1(bpa); 193 194 /* 195 * XXX 196 */ 197 198 #define PCI_LOW_MEMORY 0x1A000000 199 #define PCI_LOW_IO 0x18000000 200 201 /* XXX O2 */ 202 if (bpa > 0x80000000 && bpa < 0x82000000) 203 *bshp = MIPS_PHYS_TO_KSEG1(PCI_LOW_MEMORY + (bpa & 0xfffffff)); 204 if (bpa < 0x00010000) 205 *bshp = MIPS_PHYS_TO_KSEG1(PCI_LOW_IO + bpa); 206 207 return 0; 208 } 209 210 int 211 bus_space_alloc(t, rstart, rend, size, alignment, boundary, flags, bpap, bshp) 212 bus_space_tag_t t; 213 bus_addr_t rstart, rend; 214 bus_size_t size, alignment, boundary; 215 int flags; 216 bus_addr_t *bpap; 217 bus_space_handle_t *bshp; 218 { 219 panic("bus_space_alloc: not implemented"); 220 } 221 222 void 223 bus_space_free(t, bsh, size) 224 bus_space_tag_t t; 225 bus_space_handle_t bsh; 226 bus_size_t size; 227 { 228 panic("bus_space_free: not implemented"); 229 } 230 231 void 232 bus_space_unmap(t, bsh, size) 233 bus_space_tag_t t; 234 bus_space_handle_t bsh; 235 bus_size_t size; 236 { 237 return; 238 } 239 240 int 241 bus_space_subregion(t, bsh, offset, size, nbshp) 242 bus_space_tag_t t; 243 bus_space_handle_t bsh; 244 bus_size_t offset, size; 245 bus_space_handle_t *nbshp; 246 { 247 248 *nbshp = bsh + offset; 249 return 0; 250 } 251 252 /* 253 * Common function for DMA map creation. May be called by bus-specific 254 * DMA map creation functions. 255 */ 256 int 257 _bus_dmamap_create(t, size, nsegments, maxsegsz, boundary, flags, dmamp) 258 bus_dma_tag_t t; 259 bus_size_t size; 260 int nsegments; 261 bus_size_t maxsegsz; 262 bus_size_t boundary; 263 int flags; 264 bus_dmamap_t *dmamp; 265 { 266 struct sgimips_bus_dmamap *map; 267 void *mapstore; 268 size_t mapsize; 269 270 /* 271 * Allcoate and initialize the DMA map. The end of the map 272 * is a variable-sized array of segments, so we allocate enough 273 * room for them in one shot. 274 * 275 * Note we don't preserve the WAITOK or NOWAIT flags. Preservation 276 * of ALLOCNOW notifes others that we've reserved these resources, 277 * and they are not to be freed. 278 * 279 * The bus_dmamap_t includes one bus_dma_segment_t, hence 280 * the (nsegments - 1). 281 */ 282 mapsize = sizeof(struct sgimips_bus_dmamap) + 283 (sizeof(bus_dma_segment_t) * (nsegments - 1)); 284 if ((mapstore = malloc(mapsize, M_DMAMAP, 285 (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK)) == NULL) 286 return ENOMEM; 287 288 memset(mapstore, 0, mapsize); 289 map = (struct sgimips_bus_dmamap *)mapstore; 290 map->_dm_size = size; 291 map->_dm_segcnt = nsegments; 292 map->_dm_maxsegsz = maxsegsz; 293 map->_dm_boundary = boundary; 294 map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT); 295 map->dm_mapsize = 0; /* no valid mappings */ 296 map->dm_nsegs = 0; 297 298 *dmamp = map; 299 return 0; 300 } 301 302 /* 303 * Common function for DMA map destruction. May be called by bus-specific 304 * DMA map destruction functions. 305 */ 306 void 307 _bus_dmamap_destroy(t, map) 308 bus_dma_tag_t t; 309 bus_dmamap_t map; 310 { 311 312 free(map, M_DMAMAP); 313 } 314 extern paddr_t kvtophys(vaddr_t); /* XXX */ 315 316 /* 317 * Utility function to load a linear buffer. lastaddrp holds state 318 * between invocations (for multiple-buffer loads). segp contains 319 * the starting segment on entrance, and the ending segment on exit. 320 * first indicates if this is the first invocation of this function. 321 */ 322 int 323 _bus_dmamap_load_buffer(map, buf, buflen, p, flags, lastaddrp, segp, first) 324 bus_dmamap_t map; 325 void *buf; 326 bus_size_t buflen; 327 struct proc *p; 328 int flags; 329 vaddr_t *lastaddrp; 330 int *segp; 331 int first; 332 { 333 bus_size_t sgsize; 334 bus_addr_t curaddr, lastaddr, baddr, bmask; 335 vaddr_t vaddr = (vaddr_t)buf; 336 int seg; 337 338 lastaddr = *lastaddrp; 339 bmask = ~(map->_dm_boundary - 1); 340 341 for (seg = *segp; buflen > 0 ; ) { 342 /* 343 * Get the physical address for this segment. 344 */ 345 if (p != NULL) 346 (void) pmap_extract(p->p_vmspace->vm_map.pmap, 347 vaddr, &curaddr); 348 else 349 curaddr = kvtophys(vaddr); 350 351 /* 352 * Compute the segment size, and adjust counts. 353 */ 354 sgsize = NBPG - ((u_long)vaddr & PGOFSET); 355 if (buflen < sgsize) 356 sgsize = buflen; 357 358 /* 359 * Make sure we don't cross any boundaries. 360 */ 361 if (map->_dm_boundary > 0) { 362 baddr = (curaddr + map->_dm_boundary) & bmask; 363 if (sgsize > (baddr - curaddr)) 364 sgsize = (baddr - curaddr); 365 } 366 367 /* 368 * Insert chunk into a segment, coalescing with 369 * the previous segment if possible. 370 */ 371 if (first) { 372 map->dm_segs[seg].ds_addr = curaddr; 373 map->dm_segs[seg].ds_len = sgsize; 374 map->dm_segs[seg]._ds_vaddr = vaddr; 375 first = 0; 376 } else { 377 if (curaddr == lastaddr && 378 (map->dm_segs[seg].ds_len + sgsize) <= 379 map->_dm_maxsegsz && 380 (map->_dm_boundary == 0 || 381 (map->dm_segs[seg].ds_addr & bmask) == 382 (curaddr & bmask))) 383 map->dm_segs[seg].ds_len += sgsize; 384 else { 385 if (++seg >= map->_dm_segcnt) 386 break; 387 map->dm_segs[seg].ds_addr = curaddr; 388 map->dm_segs[seg].ds_len = sgsize; 389 map->dm_segs[seg]._ds_vaddr = vaddr; 390 } 391 } 392 393 lastaddr = curaddr + sgsize; 394 vaddr += sgsize; 395 buflen -= sgsize; 396 } 397 398 *segp = seg; 399 *lastaddrp = lastaddr; 400 401 /* 402 * Did we fit? 403 */ 404 if (buflen != 0) 405 return EFBIG; /* XXX Better return value here? */ 406 407 return 0; 408 } 409 410 /* 411 * Common function for loading a direct-mapped DMA map with a linear 412 * buffer. 413 */ 414 int 415 _bus_dmamap_load(t, map, buf, buflen, p, flags) 416 bus_dma_tag_t t; 417 bus_dmamap_t map; 418 void *buf; 419 bus_size_t buflen; 420 struct proc *p; 421 int flags; 422 { 423 vaddr_t lastaddr; 424 int seg, error; 425 426 /* 427 * Make sure that on error condition we return "no valid mappings". 428 */ 429 map->dm_mapsize = 0; 430 map->dm_nsegs = 0; 431 432 if (buflen > map->_dm_size) 433 return EINVAL; 434 435 seg = 0; 436 error = _bus_dmamap_load_buffer(map, buf, buflen, 437 p, flags, &lastaddr, &seg, 1); 438 if (error == 0) { 439 map->dm_mapsize = buflen; 440 map->dm_nsegs = seg + 1; 441 442 /* 443 * For linear buffers, we support marking the mapping 444 * as COHERENT. 445 * 446 * XXX Check TLB entries for cache-inhibit bits? 447 */ 448 if (buf >= (void *)MIPS_KSEG1_START && 449 buf < (void *)MIPS_KSEG2_START) 450 map->_dm_flags |= SGIMIPS_DMAMAP_COHERENT; 451 } 452 return error; 453 } 454 455 /* 456 * Like _bus_dmamap_load(), but for mbufs. 457 */ 458 int 459 _bus_dmamap_load_mbuf(t, map, m0, flags) 460 bus_dma_tag_t t; 461 bus_dmamap_t map; 462 struct mbuf *m0; 463 int flags; 464 { 465 vaddr_t lastaddr; 466 int seg, error, first; 467 struct mbuf *m; 468 469 /* 470 * Make sure that on error condition we return "no valid mappings." 471 */ 472 map->dm_mapsize = 0; 473 map->dm_nsegs = 0; 474 475 #ifdef DIAGNOSTIC 476 if ((m0->m_flags & M_PKTHDR) == 0) 477 panic("_bus_dmamap_load_mbuf: no packet header"); 478 #endif 479 480 if (m0->m_pkthdr.len > map->_dm_size) 481 return EINVAL; 482 483 first = 1; 484 seg = 0; 485 error = 0; 486 for (m = m0; m != NULL && error == 0; m = m->m_next) { 487 error = _bus_dmamap_load_buffer(map, 488 m->m_data, m->m_len, NULL, flags, &lastaddr, &seg, first); 489 first = 0; 490 } 491 if (error == 0) { 492 map->dm_mapsize = m0->m_pkthdr.len; 493 map->dm_nsegs = seg + 1; 494 } 495 return error; 496 } 497 498 /* 499 * Like _bus_dmamap_load(), but for uios. 500 */ 501 int 502 _bus_dmamap_load_uio(t, map, uio, flags) 503 bus_dma_tag_t t; 504 bus_dmamap_t map; 505 struct uio *uio; 506 int flags; 507 { 508 vaddr_t lastaddr; 509 int seg, i, error, first; 510 bus_size_t minlen, resid; 511 struct proc *p = NULL; 512 struct iovec *iov; 513 caddr_t addr; 514 515 /* 516 * Make sure that on error condition we return "no valid mappings." 517 */ 518 map->dm_mapsize = 0; 519 map->dm_nsegs = 0; 520 521 resid = uio->uio_resid; 522 iov = uio->uio_iov; 523 524 if (uio->uio_segflg == UIO_USERSPACE) { 525 p = uio->uio_procp; 526 #ifdef DIAGNOSTIC 527 if (p == NULL) 528 panic("_bus_dmamap_load_uio: USERSPACE but no proc"); 529 #endif 530 } 531 532 first = 1; 533 seg = 0; 534 error = 0; 535 for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0; i++) { 536 /* 537 * Now at the first iovec to load. Load each iovec 538 * until we have exhausted the residual count. 539 */ 540 minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len; 541 addr = (caddr_t)iov[i].iov_base; 542 543 error = _bus_dmamap_load_buffer(map, addr, minlen, 544 p, flags, &lastaddr, &seg, first); 545 first = 0; 546 547 resid -= minlen; 548 } 549 if (error == 0) { 550 map->dm_mapsize = uio->uio_resid; 551 map->dm_nsegs = seg + 1; 552 } 553 return error; 554 } 555 556 /* 557 * Like _bus_dmamap_load(), but for raw memory. 558 */ 559 int 560 _bus_dmamap_load_raw(t, map, segs, nsegs, size, flags) 561 bus_dma_tag_t t; 562 bus_dmamap_t map; 563 bus_dma_segment_t *segs; 564 int nsegs; 565 bus_size_t size; 566 int flags; 567 { 568 569 panic("_bus_dmamap_load_raw: not implemented"); 570 } 571 572 /* 573 * Common function for unloading a DMA map. May be called by 574 * chipset-specific DMA map unload functions. 575 */ 576 void 577 _bus_dmamap_unload(t, map) 578 bus_dma_tag_t t; 579 bus_dmamap_t map; 580 { 581 582 /* 583 * No resources to free; just mark the mappings as 584 * invalid. 585 */ 586 map->dm_mapsize = 0; 587 map->dm_nsegs = 0; 588 map->_dm_flags &= ~SGIMIPS_DMAMAP_COHERENT; 589 } 590 591 /* 592 * Common function for DMA map synchronization. May be called 593 * by chipset-specific DMA map synchronization functions. 594 */ 595 void 596 _bus_dmamap_sync(t, map, offset, len, ops) 597 bus_dma_tag_t t; 598 bus_dmamap_t map; 599 bus_addr_t offset; 600 bus_size_t len; 601 int ops; 602 { 603 bus_size_t minlen; 604 bus_addr_t addr; 605 int i; 606 607 /* 608 * Mising PRE and POST operations is not allowed. 609 */ 610 if ((ops & (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)) != 0 && 611 (ops & (BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE)) != 0) 612 panic("_bus_dmamap_sync: mix PRE and POST"); 613 614 #ifdef DIAGNOSTIC 615 if (offset >= map->dm_mapsize) 616 panic("_bus_dmamap_sync: bad offset %lu (map size is %lu)", 617 offset, map->dm_mapsize); 618 if (len == 0 || (offset + len) > map->dm_mapsize) 619 panic("_bus_dmamap_sync: bad length"); 620 #endif 621 622 /* 623 * Flush the write buffer. 624 */ 625 wbflush(); 626 627 /* 628 * If the mapping is of COHERENT DMA-safe memory, no cache 629 * flush is necessary. 630 */ 631 if (map->_dm_flags & SGIMIPS_DMAMAP_COHERENT) 632 return; 633 634 /* 635 * No cache flushes are necessary if we're only doing 636 * POSTREAD or POSTWRITE (i.e. not doing PREREAD or PREWRITE). 637 */ 638 if ((ops & (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)) == 0) 639 return; 640 641 /* 642 * Flush data cache for PREREAD. This has the side-effect 643 * of invalidating the cache. Done at PREREAD since it 644 * causes the cache line(s) to be written back to memory. 645 * 646 * Flush data cache for PREWRITE, so that the contents of 647 * the data buffer in memory reflect reality. 648 * 649 * Given the test above, we know we're doing one of these 650 * two operations, so no additional tests are necessary. 651 */ 652 653 for (i = 0; i < map->dm_nsegs && len != 0; i++) { 654 /* Find the beginning segment. */ 655 if (offset >= map->dm_segs[i].ds_len) { 656 offset -= map->dm_segs[i].ds_len; 657 continue; 658 } 659 660 /* 661 * Now at the first segment to sync; nail 662 * each segment until we have exhausted the 663 * length. 664 */ 665 minlen = len < map->dm_segs[i].ds_len - offset ? 666 len : map->dm_segs[i].ds_len - offset; 667 668 addr = map->dm_segs[i]._ds_vaddr; 669 670 #ifdef BUS_DMA_DEBUG 671 printf("bus_dmamap_sync: flushing segment %d " 672 "(0x%lx+%lx, 0x%lx+0x%lx) (olen = %ld)...", i, 673 addr, offset, addr, offset + minlen - 1, len); 674 #endif 675 #if 0 676 MachFlushDCache(addr + offset, minlen); 677 #endif 678 #if 1 679 mips_dcache_wbinv_range(addr + offset, minlen); 680 #endif 681 #if 0 682 MachFlushCache(); 683 #endif 684 685 #ifdef BUS_DMA_DEBUG 686 printf("\n"); 687 #endif 688 offset = 0; 689 len -= minlen; 690 } 691 } 692 693 /* 694 * Common function for DMA-safe memory allocation. May be called 695 * by bus-specific DMA memory allocation functions. 696 */ 697 int 698 _bus_dmamem_alloc(t, size, alignment, boundary, segs, nsegs, rsegs, flags) 699 bus_dma_tag_t t; 700 bus_size_t size, alignment, boundary; 701 bus_dma_segment_t *segs; 702 int nsegs; 703 int *rsegs; 704 int flags; 705 { 706 extern paddr_t avail_start, avail_end; 707 vaddr_t curaddr, lastaddr; 708 psize_t high; 709 struct vm_page *m; 710 struct pglist mlist; 711 int curseg, error; 712 713 /* Always round the size. */ 714 size = round_page(size); 715 716 high = avail_end - PAGE_SIZE; 717 718 /* 719 * Allocate pages from the VM system. 720 */ 721 TAILQ_INIT(&mlist); 722 error = uvm_pglistalloc(size, avail_start, high, alignment, boundary, 723 &mlist, nsegs, (flags & BUS_DMA_NOWAIT) == 0); 724 if (error) 725 return error; 726 727 /* 728 * Compute the location, size, and number of segments actually 729 * returned by the VM code. 730 */ 731 m = mlist.tqh_first; 732 curseg = 0; 733 lastaddr = segs[curseg].ds_addr = VM_PAGE_TO_PHYS(m); 734 segs[curseg].ds_len = PAGE_SIZE; 735 m = m->pageq.tqe_next; 736 737 for (; m != NULL; m = m->pageq.tqe_next) { 738 curaddr = VM_PAGE_TO_PHYS(m); 739 #ifdef DIAGNOSTIC 740 if (curaddr < avail_start || curaddr >= high) { 741 printf("uvm_pglistalloc returned non-sensical" 742 " address 0x%lx\n", curaddr); 743 panic("_bus_dmamem_alloc"); 744 } 745 #endif 746 if (curaddr == (lastaddr + PAGE_SIZE)) 747 segs[curseg].ds_len += PAGE_SIZE; 748 else { 749 curseg++; 750 segs[curseg].ds_addr = curaddr; 751 segs[curseg].ds_len = PAGE_SIZE; 752 } 753 lastaddr = curaddr; 754 } 755 756 *rsegs = curseg + 1; 757 758 return 0; 759 } 760 761 /* 762 * Common function for freeing DMA-safe memory. May be called by 763 * bus-specific DMA memory free functions. 764 */ 765 void 766 _bus_dmamem_free(t, segs, nsegs) 767 bus_dma_tag_t t; 768 bus_dma_segment_t *segs; 769 int nsegs; 770 { 771 struct vm_page *m; 772 bus_addr_t addr; 773 struct pglist mlist; 774 int curseg; 775 776 /* 777 * Build a list of pages to free back to the VM system. 778 */ 779 TAILQ_INIT(&mlist); 780 for (curseg = 0; curseg < nsegs; curseg++) { 781 for (addr = segs[curseg].ds_addr; 782 addr < (segs[curseg].ds_addr + segs[curseg].ds_len); 783 addr += PAGE_SIZE) { 784 m = PHYS_TO_VM_PAGE(addr); 785 TAILQ_INSERT_TAIL(&mlist, m, pageq); 786 } 787 } 788 789 uvm_pglistfree(&mlist); 790 } 791 792 /* 793 * Common function for mapping DMA-safe memory. May be called by 794 * bus-specific DMA memory map functions. 795 */ 796 int 797 _bus_dmamem_map(t, segs, nsegs, size, kvap, flags) 798 bus_dma_tag_t t; 799 bus_dma_segment_t *segs; 800 int nsegs; 801 size_t size; 802 caddr_t *kvap; 803 int flags; 804 { 805 vaddr_t va; 806 bus_addr_t addr; 807 int curseg; 808 809 /* 810 * If we're only mapping 1 segment, use KSEG0 or KSEG1, to avoid 811 * TLB thrashing. 812 */ 813 if (nsegs == 1) { 814 if (flags & BUS_DMA_COHERENT) 815 *kvap = (caddr_t)MIPS_PHYS_TO_KSEG1(segs[0].ds_addr); 816 else 817 *kvap = (caddr_t)MIPS_PHYS_TO_KSEG0(segs[0].ds_addr); 818 return 0; 819 } 820 821 size = round_page(size); 822 823 va = uvm_km_valloc(kernel_map, size); 824 825 if (va == 0) 826 return (ENOMEM); 827 828 *kvap = (caddr_t)va; 829 830 for (curseg = 0; curseg < nsegs; curseg++) { 831 for (addr = segs[curseg].ds_addr; 832 addr < (segs[curseg].ds_addr + segs[curseg].ds_len); 833 addr += NBPG, va += NBPG, size -= NBPG) { 834 if (size == 0) 835 panic("_bus_dmamem_map: size botch"); 836 pmap_enter(pmap_kernel(), va, addr, 837 VM_PROT_READ | VM_PROT_WRITE, 838 VM_PROT_READ | VM_PROT_WRITE | PMAP_WIRED); 839 840 /* XXX Do something about COHERENT here. */ 841 } 842 } 843 pmap_update(pmap_kernel()); 844 845 return 0; 846 } 847 848 /* 849 * Common function for unmapping DMA-safe memory. May be called by 850 * bus-specific DMA memory unmapping functions. 851 */ 852 void 853 _bus_dmamem_unmap(t, kva, size) 854 bus_dma_tag_t t; 855 caddr_t kva; 856 size_t size; 857 { 858 859 #ifdef DIAGNOSTIC 860 if ((u_long)kva & PGOFSET) 861 panic("_bus_dmamem_unmap"); 862 #endif 863 864 /* 865 * Nothing to do if we mapped it with KSEG0 or KSEG1 (i.e. 866 * not in KSEG2). 867 */ 868 if (kva >= (caddr_t)MIPS_KSEG0_START && 869 kva < (caddr_t)MIPS_KSEG2_START) 870 return; 871 872 size = round_page(size); 873 uvm_km_free(kernel_map, (vaddr_t)kva, size); 874 } 875 876 /* 877 * Common functin for mmap(2)'ing DMA-safe memory. May be called by 878 * bus-specific DMA mmap(2)'ing functions. 879 */ 880 paddr_t 881 _bus_dmamem_mmap(t, segs, nsegs, off, prot, flags) 882 bus_dma_tag_t t; 883 bus_dma_segment_t *segs; 884 int nsegs; 885 off_t off; 886 int prot, flags; 887 { 888 int i; 889 890 for (i = 0; i < nsegs; i++) { 891 #ifdef DIAGNOSTIC 892 if (off & PGOFSET) 893 panic("_bus_dmamem_mmap: offset unaligned"); 894 if (segs[i].ds_addr & PGOFSET) 895 panic("_bus_dmamem_mmap: segment unaligned"); 896 if (segs[i].ds_len & PGOFSET) 897 panic("_bus_dmamem_mmap: segment size not multiple" 898 " of page size"); 899 #endif 900 if (off >= segs[i].ds_len) { 901 off -= segs[i].ds_len; 902 continue; 903 } 904 905 return mips_btop((caddr_t)segs[i].ds_addr + off); 906 } 907 908 /* Page not found. */ 909 return -1; 910 } 911