Annotation of src/sys/arch/evbarm/integrator/int_bus_dma.c, Revision 1.1
1.1 ! rearnsha 1: /* $NetBSD: bus_dma.c,v 1.1 2001/07/28 13:28:03 chris Exp $ */
! 2:
! 3: /*-
! 4: * Copyright (c) 1996, 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: * 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: * The integrator board has memory steering hardware that means that
! 41: * the normal physical addresses used by the processor cannot be used
! 42: * for DMA. Instead we have to use the "core module alias mapping
! 43: * addresses". We don't use these for normal processor accesses since
! 44: * they are much slower than the direct addresses when accessing
! 45: * memory on the local board.
! 46: */
! 47:
! 48: #include <sys/param.h>
! 49: #include <sys/systm.h>
! 50: #include <sys/kernel.h>
! 51: #include <sys/map.h>
! 52: #include <sys/proc.h>
! 53: #include <sys/buf.h>
! 54: #include <sys/reboot.h>
! 55: #include <sys/conf.h>
! 56: #include <sys/file.h>
! 57: #include <sys/malloc.h>
! 58: #include <sys/mbuf.h>
! 59: #include <sys/vnode.h>
! 60: #include <sys/device.h>
! 61:
! 62: #include <uvm/uvm_extern.h>
! 63:
! 64: #define _ARM32_BUS_DMA_PRIVATE
! 65: #include <evbarm/integrator/int_bus_dma.h>
! 66:
! 67: #include <machine/cpu.h>
! 68: #include <machine/cpufunc.h>
! 69: #include <machine/psl.h>
! 70:
! 71: static int integrator_bus_dmamap_load_buffer __P((bus_dma_tag_t,
! 72: bus_dmamap_t, void *, bus_size_t, struct proc *, int,
! 73: vm_offset_t *, int *, int));
! 74: static int integrator_bus_dma_inrange __P((bus_dma_segment_t *, int,
! 75: bus_addr_t));
! 76:
! 77: /*
! 78: * Common function for loading a DMA map with a linear buffer. May
! 79: * be called by bus-specific DMA map load functions.
! 80: */
! 81: int
! 82: integrator_bus_dmamap_load(t, map, buf, buflen, p, flags)
! 83: bus_dma_tag_t t;
! 84: bus_dmamap_t map;
! 85: void *buf;
! 86: bus_size_t buflen;
! 87: struct proc *p;
! 88: int flags;
! 89: {
! 90: vm_offset_t lastaddr;
! 91: int seg, error;
! 92:
! 93: #ifdef DEBUG_DMA
! 94: printf("dmamap_load: t=%p map=%p buf=%p len=%lx p=%p f=%d\n",
! 95: t, map, buf, buflen, p, flags);
! 96: #endif /* DEBUG_DMA */
! 97:
! 98: /*
! 99: * Make sure that on error condition we return "no valid mappings".
! 100: */
! 101: map->dm_mapsize = 0;
! 102: map->dm_nsegs = 0;
! 103:
! 104: if (buflen > map->_dm_size)
! 105: return (EINVAL);
! 106:
! 107: seg = 0;
! 108: error = integrator_bus_dmamap_load_buffer(t, map, buf, buflen, p, flags,
! 109: &lastaddr, &seg, 1);
! 110: if (error == 0) {
! 111: map->dm_mapsize = buflen;
! 112: map->dm_nsegs = seg + 1;
! 113: }
! 114: #ifdef DEBUG_DMA
! 115: printf("dmamap_load: error=%d\n", error);
! 116: #endif /* DEBUG_DMA */
! 117: return (error);
! 118: }
! 119:
! 120: /*
! 121: * Like _bus_dmamap_load(), but for mbufs.
! 122: */
! 123: int
! 124: integrator_bus_dmamap_load_mbuf(t, map, m0, flags)
! 125: bus_dma_tag_t t;
! 126: bus_dmamap_t map;
! 127: struct mbuf *m0;
! 128: int flags;
! 129: {
! 130: vm_offset_t lastaddr;
! 131: int seg, error, first;
! 132: struct mbuf *m;
! 133:
! 134: #ifdef DEBUG_DMA
! 135: printf("dmamap_load_mbuf: t=%p map=%p m0=%p f=%d\n",
! 136: t, map, m0, flags);
! 137: #endif /* DEBUG_DMA */
! 138:
! 139: /*
! 140: * Make sure that on error condition we return "no valid mappings."
! 141: */
! 142: map->dm_mapsize = 0;
! 143: map->dm_nsegs = 0;
! 144:
! 145: #ifdef DIAGNOSTIC
! 146: if ((m0->m_flags & M_PKTHDR) == 0)
! 147: panic("integrator_bus_dmamap_load_mbuf: no packet header");
! 148: #endif /* DIAGNOSTIC */
! 149:
! 150: if (m0->m_pkthdr.len > map->_dm_size)
! 151: return (EINVAL);
! 152:
! 153: first = 1;
! 154: seg = 0;
! 155: error = 0;
! 156: for (m = m0; m != NULL && error == 0; m = m->m_next) {
! 157: error = integrator_bus_dmamap_load_buffer(t, map, m->m_data,
! 158: m->m_len, NULL, flags, &lastaddr, &seg, first);
! 159: first = 0;
! 160: }
! 161: if (error == 0) {
! 162: map->dm_mapsize = m0->m_pkthdr.len;
! 163: map->dm_nsegs = seg + 1;
! 164: }
! 165: #ifdef DEBUG_DMA
! 166: printf("dmamap_load_mbuf: error=%d\n", error);
! 167: #endif /* DEBUG_DMA */
! 168: return (error);
! 169: }
! 170:
! 171: /*
! 172: * Like _bus_dmamap_load(), but for uios.
! 173: */
! 174: int
! 175: integrator_bus_dmamap_load_uio(t, map, uio, flags)
! 176: bus_dma_tag_t t;
! 177: bus_dmamap_t map;
! 178: struct uio *uio;
! 179: int flags;
! 180: {
! 181: vm_offset_t lastaddr;
! 182: int seg, i, error, first;
! 183: bus_size_t minlen, resid;
! 184: struct proc *p = NULL;
! 185: struct iovec *iov;
! 186: caddr_t addr;
! 187:
! 188: /*
! 189: * Make sure that on error condition we return "no valid mappings."
! 190: */
! 191: map->dm_mapsize = 0;
! 192: map->dm_nsegs = 0;
! 193:
! 194: resid = uio->uio_resid;
! 195: iov = uio->uio_iov;
! 196:
! 197: if (uio->uio_segflg == UIO_USERSPACE) {
! 198: p = uio->uio_procp;
! 199: #ifdef DIAGNOSTIC
! 200: if (p == NULL)
! 201: panic("integrator_bus_dmamap_load_uio: USERSPACE but no proc");
! 202: #endif
! 203: }
! 204:
! 205: first = 1;
! 206: seg = 0;
! 207: error = 0;
! 208: for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0; i++) {
! 209: /*
! 210: * Now at the first iovec to load. Load each iovec
! 211: * until we have exhausted the residual count.
! 212: */
! 213: minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len;
! 214: addr = (caddr_t)iov[i].iov_base;
! 215:
! 216: error = integrator_bus_dmamap_load_buffer(t, map, addr, minlen,
! 217: p, flags, &lastaddr, &seg, first);
! 218: first = 0;
! 219:
! 220: resid -= minlen;
! 221: }
! 222: if (error == 0) {
! 223: map->dm_mapsize = uio->uio_resid;
! 224: map->dm_nsegs = seg + 1;
! 225: }
! 226: return (error);
! 227: }
! 228:
! 229: /*
! 230: * Common function for DMA-safe memory allocation. May be called
! 231: * by bus-specific DMA memory allocation functions.
! 232: */
! 233:
! 234: extern vm_offset_t physical_start;
! 235: extern vm_offset_t physical_freestart;
! 236: extern vm_offset_t physical_freeend;
! 237: extern vm_offset_t physical_end;
! 238:
! 239: int
! 240: integrator_bus_dmamem_alloc(t, size, alignment, boundary, segs, nsegs, rsegs, flags)
! 241: bus_dma_tag_t t;
! 242: bus_size_t size, alignment, boundary;
! 243: bus_dma_segment_t *segs;
! 244: int nsegs;
! 245: int *rsegs;
! 246: int flags;
! 247: {
! 248: int error;
! 249: #ifdef DEBUG_DMA
! 250: printf("dmamem_alloc t=%p size=%lx align=%lx boundary=%lx segs=%p nsegs=%x rsegs=%p flags=%x\n",
! 251: t, size, alignment, boundary, segs, nsegs, rsegs, flags);
! 252: #endif /* DEBUG_DMA */
! 253: error = (integrator_bus_dmamem_alloc_range(t, size, alignment, boundary,
! 254: segs, nsegs, rsegs, flags, trunc_page(physical_start), trunc_page(physical_end)));
! 255: #ifdef DEBUG_DMA
! 256: printf("dmamem_alloc: =%d\n", error);
! 257: #endif /* DEBUG_DMA */
! 258: return(error);
! 259: }
! 260:
! 261: /*
! 262: * Common function for freeing DMA-safe memory. May be called by
! 263: * bus-specific DMA memory free functions.
! 264: */
! 265: void
! 266: integrator_bus_dmamem_free(t, segs, nsegs)
! 267: bus_dma_tag_t t;
! 268: bus_dma_segment_t *segs;
! 269: int nsegs;
! 270: {
! 271: struct vm_page *m;
! 272: bus_addr_t addr;
! 273: struct pglist mlist;
! 274: int curseg;
! 275:
! 276: #ifdef DEBUG_DMA
! 277: printf("dmamem_free: t=%p segs=%p nsegs=%x\n", t, segs, nsegs);
! 278: #endif /* DEBUG_DMA */
! 279:
! 280: /*
! 281: * Build a list of pages to free back to the VM system.
! 282: */
! 283: TAILQ_INIT(&mlist);
! 284: for (curseg = 0; curseg < nsegs; curseg++) {
! 285: for (addr = segs[curseg].ds_addr;
! 286: addr < (segs[curseg].ds_addr + segs[curseg].ds_len);
! 287: addr += PAGE_SIZE) {
! 288: m = PHYS_TO_VM_PAGE(CM_ALIAS_TO_LOCAL(addr));
! 289: TAILQ_INSERT_TAIL(&mlist, m, pageq);
! 290: }
! 291: }
! 292: uvm_pglistfree(&mlist);
! 293: }
! 294:
! 295: /*
! 296: * Common function for mapping DMA-safe memory. May be called by
! 297: * bus-specific DMA memory map functions.
! 298: */
! 299: int
! 300: integrator_bus_dmamem_map(t, segs, nsegs, size, kvap, flags)
! 301: bus_dma_tag_t t;
! 302: bus_dma_segment_t *segs;
! 303: int nsegs;
! 304: size_t size;
! 305: caddr_t *kvap;
! 306: int flags;
! 307: {
! 308: vm_offset_t va;
! 309: bus_addr_t addr;
! 310: int curseg;
! 311: pt_entry_t *ptep/*, pte*/;
! 312:
! 313: #ifdef DEBUG_DMA
! 314: printf("dmamem_map: t=%p segs=%p nsegs=%x size=%lx flags=%x\n", t,
! 315: segs, nsegs, (unsigned long)size, flags);
! 316: #endif /* DEBUG_DMA */
! 317:
! 318: size = round_page(size);
! 319: va = uvm_km_valloc(kernel_map, size);
! 320:
! 321: if (va == 0)
! 322: return (ENOMEM);
! 323:
! 324: *kvap = (caddr_t)va;
! 325:
! 326: for (curseg = 0; curseg < nsegs; curseg++) {
! 327: for (addr = segs[curseg].ds_addr;
! 328: addr < (segs[curseg].ds_addr + segs[curseg].ds_len);
! 329: addr += NBPG, va += NBPG, size -= NBPG) {
! 330: #ifdef DEBUG_DMA
! 331: printf("wiring p%lx to v%lx", CM_ALIAS_TO_LOCAL(addr),
! 332: va);
! 333: #endif /* DEBUG_DMA */
! 334: if (size == 0)
! 335: panic("integrator_bus_dmamem_map: size botch");
! 336: pmap_enter(pmap_kernel(), va, CM_ALIAS_TO_LOCAL(addr),
! 337: VM_PROT_READ | VM_PROT_WRITE,
! 338: VM_PROT_READ | VM_PROT_WRITE | PMAP_WIRED);
! 339: /*
! 340: * If the memory must remain coherent with the
! 341: * cache then we must make the memory uncacheable
! 342: * in order to maintain virtual cache coherency.
! 343: * We must also guarentee the cache does not already
! 344: * contain the virtal addresses we are making
! 345: * uncacheable.
! 346: */
! 347: if (flags & BUS_DMA_COHERENT) {
! 348: cpu_cache_purgeD_rng(va, NBPG);
! 349: cpu_drain_writebuf();
! 350: ptep = vtopte(va);
! 351: *ptep = ((*ptep) & (~PT_C | PT_B));
! 352: tlb_flush();
! 353: }
! 354: #ifdef DEBUG_DMA
! 355: ptep = vtopte(va);
! 356: printf(" pte=v%p *pte=%x\n", ptep, *ptep);
! 357: #endif /* DEBUG_DMA */
! 358: }
! 359: }
! 360: pmap_update(pmap_kernel());
! 361: #ifdef DEBUG_DMA
! 362: printf("dmamem_map: =%p\n", *kvap);
! 363: #endif /* DEBUG_DMA */
! 364: return (0);
! 365: }
! 366:
! 367: /*
! 368: * Common functin for mmap(2)'ing DMA-safe memory. May be called by
! 369: * bus-specific DMA mmap(2)'ing functions.
! 370: */
! 371: paddr_t
! 372: integrator_bus_dmamem_mmap(t, segs, nsegs, off, prot, flags)
! 373: bus_dma_tag_t t;
! 374: bus_dma_segment_t *segs;
! 375: int nsegs;
! 376: off_t off;
! 377: int prot, flags;
! 378: {
! 379: int i;
! 380:
! 381: for (i = 0; i < nsegs; i++) {
! 382: #ifdef DIAGNOSTIC
! 383: if (off & PGOFSET)
! 384: panic("integrator_bus_dmamem_mmap: offset unaligned");
! 385: if (segs[i].ds_addr & PGOFSET)
! 386: panic("integrator_bus_dmamem_mmap: segment unaligned");
! 387: if (segs[i].ds_len & PGOFSET)
! 388: panic("integrator_bus_dmamem_mmap: segment size not multiple"
! 389: " of page size");
! 390: #endif /* DIAGNOSTIC */
! 391: if (off >= segs[i].ds_len) {
! 392: off -= segs[i].ds_len;
! 393: continue;
! 394: }
! 395:
! 396: return arm_byte_to_page((u_long)CM_ALIAS_TO_LOCAL(segs[i].ds_addr) + off);
! 397: }
! 398:
! 399: /* Page not found. */
! 400: return -1;
! 401: }
! 402:
! 403: /**********************************************************************
! 404: * DMA utility functions
! 405: **********************************************************************/
! 406:
! 407: /*
! 408: * Utility function to load a linear buffer. lastaddrp holds state
! 409: * between invocations (for multiple-buffer loads). segp contains
! 410: * the starting segment on entrace, and the ending segment on exit.
! 411: * first indicates if this is the first invocation of this function.
! 412: */
! 413: static int
! 414: integrator_bus_dmamap_load_buffer(t, map, buf, buflen, p, flags, lastaddrp,
! 415: segp, first)
! 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: vm_offset_t *lastaddrp;
! 423: int *segp;
! 424: int first;
! 425: {
! 426: bus_size_t sgsize;
! 427: bus_addr_t curaddr, lastaddr, baddr, bmask;
! 428: vm_offset_t vaddr = (vm_offset_t)buf;
! 429: int seg;
! 430: pmap_t pmap;
! 431:
! 432: #ifdef DEBUG_DMA
! 433: printf("integrator_bus_dmamem_load_buffer(buf=%p, len=%lx, flags=%d, 1st=%d)\n",
! 434: buf, buflen, flags, first);
! 435: #endif /* DEBUG_DMA */
! 436:
! 437: if (p != NULL)
! 438: pmap = p->p_vmspace->vm_map.pmap;
! 439: else
! 440: pmap = pmap_kernel();
! 441:
! 442: lastaddr = *lastaddrp;
! 443: bmask = ~(map->_dm_boundary - 1);
! 444:
! 445: for (seg = *segp; buflen > 0; ) {
! 446: /*
! 447: * Get the physical address for this segment.
! 448: */
! 449: (void) pmap_extract(pmap, (vaddr_t)vaddr, &curaddr);
! 450:
! 451: /*
! 452: * Make sure we're in an allowed DMA range.
! 453: */
! 454: if (t->_ranges != NULL &&
! 455: integrator_bus_dma_inrange(t->_ranges, t->_nranges, curaddr) == 0)
! 456: return (EINVAL);
! 457:
! 458: /*
! 459: * Compute the segment size, and adjust counts.
! 460: */
! 461: sgsize = NBPG - ((u_long)vaddr & PGOFSET);
! 462: if (buflen < sgsize)
! 463: sgsize = buflen;
! 464:
! 465: /*
! 466: * Make sure we don't cross any boundaries.
! 467: */
! 468: if (map->_dm_boundary > 0) {
! 469: baddr = (curaddr + map->_dm_boundary) & bmask;
! 470: if (sgsize > (baddr - curaddr))
! 471: sgsize = (baddr - curaddr);
! 472: }
! 473:
! 474: /*
! 475: * Insert chunk into a segment, coalescing with
! 476: * previous segment if possible.
! 477: */
! 478: if (first) {
! 479: map->dm_segs[seg].ds_addr = LOCAL_TO_CM_ALIAS(curaddr);
! 480: map->dm_segs[seg].ds_len = sgsize;
! 481: map->dm_segs[seg]._ds_vaddr = vaddr;
! 482: first = 0;
! 483: } else {
! 484: if (curaddr == lastaddr &&
! 485: (map->dm_segs[seg].ds_len + sgsize) <=
! 486: map->_dm_maxsegsz &&
! 487: (map->_dm_boundary == 0 ||
! 488: (map->dm_segs[seg].ds_addr & bmask) ==
! 489: (LOCAL_TO_CM_ALIAS(curaddr) & bmask)))
! 490: map->dm_segs[seg].ds_len += sgsize;
! 491: else {
! 492: if (++seg >= map->_dm_segcnt)
! 493: break;
! 494: map->dm_segs[seg].ds_addr = LOCAL_TO_CM_ALIAS(curaddr);
! 495: map->dm_segs[seg].ds_len = sgsize;
! 496: map->dm_segs[seg]._ds_vaddr = vaddr;
! 497: }
! 498: }
! 499:
! 500: lastaddr = curaddr + sgsize;
! 501: vaddr += sgsize;
! 502: buflen -= sgsize;
! 503: }
! 504:
! 505: *segp = seg;
! 506: *lastaddrp = lastaddr;
! 507:
! 508: /*
! 509: * Did we fit?
! 510: */
! 511: if (buflen != 0)
! 512: return (EFBIG); /* XXX better return value here? */
! 513: return (0);
! 514: }
! 515:
! 516: /*
! 517: * Check to see if the specified page is in an allowed DMA range.
! 518: */
! 519: static int
! 520: integrator_bus_dma_inrange(ranges, nranges, curaddr)
! 521: bus_dma_segment_t *ranges;
! 522: int nranges;
! 523: bus_addr_t curaddr;
! 524: {
! 525: bus_dma_segment_t *ds;
! 526: int i;
! 527:
! 528: for (i = 0, ds = ranges; i < nranges; i++, ds++) {
! 529: if (curaddr >= CM_ALIAS_TO_LOCAL(ds->ds_addr) &&
! 530: round_page(curaddr) <= (CM_ALIAS_TO_LOCAL(ds->ds_addr) + ds->ds_len))
! 531: return (1);
! 532: }
! 533:
! 534: return (0);
! 535: }
! 536:
! 537: /*
! 538: * Allocate physical memory from the given physical address range.
! 539: * Called by DMA-safe memory allocation methods.
! 540: */
! 541: int
! 542: integrator_bus_dmamem_alloc_range(t, size, alignment, boundary, segs, nsegs, rsegs,
! 543: flags, low, high)
! 544: bus_dma_tag_t t;
! 545: bus_size_t size, alignment, boundary;
! 546: bus_dma_segment_t *segs;
! 547: int nsegs;
! 548: int *rsegs;
! 549: int flags;
! 550: vm_offset_t low;
! 551: vm_offset_t high;
! 552: {
! 553: vm_offset_t curaddr, lastaddr;
! 554: struct vm_page *m;
! 555: struct pglist mlist;
! 556: int curseg, error;
! 557:
! 558: #ifdef DEBUG_DMA
! 559: printf("alloc_range: t=%p size=%lx align=%lx boundary=%lx segs=%p nsegs=%x rsegs=%p flags=%x lo=%lx hi=%lx\n",
! 560: t, size, alignment, boundary, segs, nsegs, rsegs, flags, low, high);
! 561: #endif /* DEBUG_DMA */
! 562:
! 563: /* Always round the size. */
! 564: size = round_page(size);
! 565:
! 566: /*
! 567: * Allocate pages from the VM system.
! 568: */
! 569: TAILQ_INIT(&mlist);
! 570: error = uvm_pglistalloc(size, low, high, alignment, boundary,
! 571: &mlist, nsegs, (flags & BUS_DMA_NOWAIT) == 0);
! 572: if (error)
! 573: return (error);
! 574:
! 575: /*
! 576: * Compute the location, size, and number of segments actually
! 577: * returned by the VM code.
! 578: */
! 579: m = mlist.tqh_first;
! 580: curseg = 0;
! 581: lastaddr = VM_PAGE_TO_PHYS(m);
! 582: segs[curseg].ds_addr = LOCAL_TO_CM_ALIAS(lastaddr);
! 583: segs[curseg].ds_len = PAGE_SIZE;
! 584: #ifdef DEBUG_DMA
! 585: printf("alloc: page %lx\n", lastaddr);
! 586: #endif /* DEBUG_DMA */
! 587: m = m->pageq.tqe_next;
! 588:
! 589: for (; m != NULL; m = m->pageq.tqe_next) {
! 590: curaddr = VM_PAGE_TO_PHYS(m);
! 591: #ifdef DIAGNOSTIC
! 592: if (curaddr < low || curaddr >= high) {
! 593: printf("uvm_pglistalloc returned non-sensical"
! 594: " address 0x%lx\n", curaddr);
! 595: panic("integrator_bus_dmamem_alloc_range");
! 596: }
! 597: #endif /* DIAGNOSTIC */
! 598: #ifdef DEBUG_DMA
! 599: printf("alloc: page %lx\n", curaddr);
! 600: #endif /* DEBUG_DMA */
! 601: if (curaddr == (lastaddr + PAGE_SIZE))
! 602: segs[curseg].ds_len += PAGE_SIZE;
! 603: else {
! 604: curseg++;
! 605: segs[curseg].ds_addr = LOCAL_TO_CM_ALIAS(curaddr);
! 606: segs[curseg].ds_len = PAGE_SIZE;
! 607: }
! 608: lastaddr = curaddr;
! 609: }
! 610:
! 611: *rsegs = curseg + 1;
! 612:
! 613: return (0);
! 614: }
CVSweb <webmaster@jp.NetBSD.org>