summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorDale S. Rahn <rahnds@cvs.openbsd.org>2000-08-03 03:02:51 +0000
committerDale S. Rahn <rahnds@cvs.openbsd.org>2000-08-03 03:02:51 +0000
commit512236a12d50067ded4dd94ac1aa8c45ebf12d90 (patch)
treea07f5ce87693a78cb8f67830ba37310536da70a3 /sys
parenta2a41a863b468fc461b2c55e7f8cab074afa7da4 (diff)
Fixes to bus dmamem code.
(Fixed by replacing the code with the version from the i386 port.)
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/powerpc/include/bus.h54
-rw-r--r--sys/arch/powerpc/powerpc/dma.c388
2 files changed, 316 insertions, 126 deletions
diff --git a/sys/arch/powerpc/include/bus.h b/sys/arch/powerpc/include/bus.h
index 7e99a8785fc..cd469104d7f 100644
--- a/sys/arch/powerpc/include/bus.h
+++ b/sys/arch/powerpc/include/bus.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bus.h,v 1.7 2000/07/07 13:11:04 rahnds Exp $ */
+/* $OpenBSD: bus.h,v 1.8 2000/08/03 03:02:50 rahnds Exp $ */
/*
* Copyright (c) 1997 Per Fogelstrom. All rights reserved.
@@ -214,30 +214,30 @@ struct powerpc_bus_dma_tag {
/*
* DMA mapping methods.
*/
- int (*_dmamap_create) __P((void *, bus_size_t, int,
+ int (*_dmamap_create) __P((bus_dma_tag_t , bus_size_t, int,
bus_size_t, bus_size_t, int, bus_dmamap_t *));
- void (*_dmamap_destroy) __P((void *, bus_dmamap_t));
- int (*_dmamap_load) __P((void *, bus_dmamap_t, void *,
+ void (*_dmamap_destroy) __P((bus_dma_tag_t , bus_dmamap_t));
+ int (*_dmamap_load) __P((bus_dma_tag_t , bus_dmamap_t, void *,
bus_size_t, struct proc *, int));
- int (*_dmamap_load_mbuf) __P((void *, bus_dmamap_t,
+ int (*_dmamap_load_mbuf) __P((bus_dma_tag_t , bus_dmamap_t,
struct mbuf *, int));
- int (*_dmamap_load_uio) __P((void *, bus_dmamap_t,
+ int (*_dmamap_load_uio) __P((bus_dma_tag_t , bus_dmamap_t,
struct uio *, int));
- int (*_dmamap_load_raw) __P((void *, bus_dmamap_t,
+ int (*_dmamap_load_raw) __P((bus_dma_tag_t , bus_dmamap_t,
bus_dma_segment_t *, int, bus_size_t, int));
- void (*_dmamap_unload) __P((void *, bus_dmamap_t));
- void (*_dmamap_sync) __P((void *, bus_dmamap_t, bus_dmasync_op_t));
+ void (*_dmamap_unload) __P((bus_dma_tag_t , bus_dmamap_t));
+ void (*_dmamap_sync) __P((bus_dma_tag_t , bus_dmamap_t, bus_dmasync_op_t));
/*
* DMA memory utility functions.
*/
- int (*_dmamem_alloc) __P((void *, bus_size_t, bus_size_t,
+ int (*_dmamem_alloc) __P((bus_dma_tag_t, bus_size_t, bus_size_t,
bus_size_t, bus_dma_segment_t *, int, int *, int));
- void (*_dmamem_free) __P((void *, bus_dma_segment_t *, int));
- int (*_dmamem_map) __P((void *, bus_dma_segment_t *,
+ void (*_dmamem_free) __P((bus_dma_tag_t, bus_dma_segment_t *, int));
+ int (*_dmamem_map) __P((bus_dma_tag_t, bus_dma_segment_t *,
int, size_t, caddr_t *, int));
- void (*_dmamem_unmap) __P((void *, caddr_t, size_t));
- int (*_dmamem_mmap) __P((void *, bus_dma_segment_t *,
+ void (*_dmamem_unmap) __P((bus_dma_tag_t, caddr_t, size_t));
+ int (*_dmamem_mmap) __P((bus_dma_tag_t, bus_dma_segment_t *,
int, int, int, int));
};
@@ -270,25 +270,25 @@ struct powerpc_bus_dma_tag {
#define bus_dmamem_mmap(t, sg, n, o, p, f) \
(*(t)->_dmamem_mmap)((t)->_cookie, (sg), (n), (o), (p), (f))
-int _dmamap_create __P((void *, bus_size_t, int,
+int _dmamap_create __P((bus_dma_tag_t, bus_size_t, int,
bus_size_t, bus_size_t, int, bus_dmamap_t *));
-void _dmamap_destroy __P((void *, bus_dmamap_t));
-int _dmamap_load __P((void *, bus_dmamap_t, void *,
+void _dmamap_destroy __P((bus_dma_tag_t, bus_dmamap_t));
+int _dmamap_load __P((bus_dma_tag_t, bus_dmamap_t, void *,
bus_size_t, struct proc *, int));
-int _dmamap_load_mbuf __P((void *, bus_dmamap_t, struct mbuf *, int));
-int _dmamap_load_uio __P((void *, bus_dmamap_t, struct uio *, int));
-int _dmamap_load_raw __P((void *, bus_dmamap_t,
+int _dmamap_load_mbuf __P((bus_dma_tag_t, bus_dmamap_t, struct mbuf *, int));
+int _dmamap_load_uio __P((bus_dma_tag_t, bus_dmamap_t, struct uio *, int));
+int _dmamap_load_raw __P((bus_dma_tag_t, bus_dmamap_t,
bus_dma_segment_t *, int, bus_size_t, int));
-void _dmamap_unload __P((void *, bus_dmamap_t));
-void _dmamap_sync __P((void *, bus_dmamap_t, bus_dmasync_op_t));
+void _dmamap_unload __P((bus_dma_tag_t, bus_dmamap_t));
+void _dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t, bus_dmasync_op_t));
-int _dmamem_alloc __P((void *, bus_size_t, bus_size_t,
+int _dmamem_alloc __P((bus_dma_tag_t, bus_size_t, bus_size_t,
bus_size_t, bus_dma_segment_t *, int, int *, int));
-void _dmamem_free __P((void *, bus_dma_segment_t *, int));
-int _dmamem_map __P((void *, bus_dma_segment_t *,
+void _dmamem_free __P((bus_dma_tag_t, bus_dma_segment_t *, int));
+int _dmamem_map __P((bus_dma_tag_t, bus_dma_segment_t *,
int, size_t, caddr_t *, int));
-void _dmamem_unmap __P((void *, caddr_t, size_t));
-int _dmamem_mmap __P((void *, bus_dma_segment_t *, int, int, int, int));
+void _dmamem_unmap __P((bus_dma_tag_t, caddr_t, size_t));
+int _dmamem_mmap __P((bus_dma_tag_t, bus_dma_segment_t *, int, int, int, int));
/*
* bus_dmamap_t
diff --git a/sys/arch/powerpc/powerpc/dma.c b/sys/arch/powerpc/powerpc/dma.c
index cb7d5c74f37..e441e55062d 100644
--- a/sys/arch/powerpc/powerpc/dma.c
+++ b/sys/arch/powerpc/powerpc/dma.c
@@ -1,9 +1,14 @@
-/* $OpenBSD: dma.c,v 1.2 2000/03/31 04:12:58 rahnds Exp $ */
+/* $OpenBSD: dma.c,v 1.3 2000/08/03 03:02:50 rahnds Exp $ */
+/* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */
-/*
- * Copyright (c) 1998 Michael Shalayeff
+/*-
+ * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
* All rights reserved.
*
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -14,20 +19,23 @@
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
- * This product includes software developed by Michael Shalayeff.
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/param.h>
@@ -53,9 +61,13 @@
#include <machine/bus.h>
+/*
+ * Common function for DMA map creation. May be called by bus-specific
+ * DMA map creation functions.
+ */
int
-_dmamap_create(v, size, nsegments, maxsegsz, boundary, flags, dmamp)
- void *v;
+_dmamap_create(t, size, nsegments, maxsegsz, boundary, flags, dmamp)
+ bus_dma_tag_t t;
bus_size_t size;
int nsegments;
bus_size_t maxsegsz;
@@ -63,32 +75,51 @@ _dmamap_create(v, size, nsegments, maxsegsz, boundary, flags, dmamp)
int flags;
bus_dmamap_t *dmamp;
{
- register struct powerpc_bus_dmamap *map;
- register size_t mapsize;
+ struct powerpc_bus_dmamap *map;
+ void *mapstore;
+ size_t mapsize;
+ /*
+ * Allocate and initialize the DMA map. The end of the map
+ * is a variable-sized array of segments, so we allocate enough
+ * room for them in one shot.
+ *
+ * Note we don't preserve the WAITOK or NOWAIT flags. Preservation
+ * of ALLOCNOW notifies others that we've reserved these resources,
+ * and they are not to be freed.
+ *
+ * The bus_dmamap_t includes one bus_dma_segment_t, hence
+ * the (nsegments - 1).
+ */
mapsize = sizeof(struct powerpc_bus_dmamap) +
(sizeof(bus_dma_segment_t) * (nsegments - 1));
- MALLOC(map, struct powerpc_bus_dmamap *, mapsize, M_DEVBUF,
- (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK);
- if (!map)
+ if ((mapstore = malloc(mapsize, M_DEVBUF,
+ (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK)) == NULL)
return (ENOMEM);
- bzero(map, mapsize);
+ bzero(mapstore, mapsize);
+ map = (struct powerpc_bus_dmamap *)mapstore;
map->_dm_size = size;
map->_dm_segcnt = nsegments;
map->_dm_maxsegsz = maxsegsz;
map->_dm_boundary = boundary;
map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT);
+ map->dm_nsegs = 0; /* no valid mappings */
*dmamp = map;
return (0);
}
+/*
+ * Common function for DMA map destruction. May be called by bus-specific
+ * DMA map destruction functions.
+ */
void
-_dmamap_destroy(v, map)
- void *v;
+_dmamap_destroy(t, map)
+ bus_dma_tag_t t;
bus_dmamap_t map;
{
+
free(map, M_DEVBUF);
}
@@ -98,7 +129,7 @@ _dmamap_destroy(v, map)
*/
int
_dmamap_load(t, map, buf, buflen, p, flags)
- void * t;
+ bus_dma_tag_t t;
bus_dmamap_t map;
void *buf;
bus_size_t buflen;
@@ -115,6 +146,7 @@ _dmamap_load(t, map, buf, buflen, p, flags)
* Make sure that on error condition we return "no valid mappings".
*/
map->dm_nsegs = 0;
+
if (buflen > map->_dm_size)
return (EINVAL);
@@ -187,151 +219,309 @@ _dmamap_load(t, map, buf, buflen, p, flags)
return (0);
}
+/*
+ * Like _bus_dmamap_load(), but for mbufs.
+ */
int
-_dmamap_load_mbuf(v, map, m, flags)
- void *v;
+_dmamap_load_mbuf(t, map, m, flags)
+ bus_dma_tag_t t;
bus_dmamap_t map;
struct mbuf *m;
int flags;
{
- panic("_dmamap_load_mbuf: not implemented");
+
+ panic("_bus_dmamap_load: not implemented");
}
+/*
+ * Like _bus_dmamap_load(), but for uios.
+ */
int
-_dmamap_load_uio(v, map, uio, flags)
- void *v;
+_dmamap_load_uio(t, map, uio, flags)
+ bus_dma_tag_t t;
bus_dmamap_t map;
struct uio *uio;
int flags;
{
- panic("_dmamap_load_uio: not implemented");
+
+ panic("_bus_dmamap_load_uio: not implemented");
}
+/*
+ * Like _bus_dmamap_load(), but for raw memory allocated with
+ * bus_dmamem_alloc().
+ */
int
-_dmamap_load_raw(v, map, segs, nsegs, size, flags)
- void *v;
+_dmamap_load_raw(t, map, segs, nsegs, size, flags)
+ bus_dma_tag_t t;
bus_dmamap_t map;
bus_dma_segment_t *segs;
int nsegs;
bus_size_t size;
int flags;
{
- panic("_dmamap_load_raw: not implemented");
+
+ panic("_bus_dmamap_load_raw: not implemented");
}
+/*
+ * Common function for unloading a DMA map. May be called by
+ * bus-specific DMA map unload functions.
+ */
void
-_dmamap_unload(v, map)
- void *v;
+_dmamap_unload(t, map)
+ bus_dma_tag_t t;
bus_dmamap_t map;
{
- panic("_dmamap_unload: not implemented");
+
+ /*
+ * No resources to free; just mark the mappings as
+ * invalid.
+ */
+ map->dm_nsegs = 0;
}
+/*
+ * Common function for DMA map synchronization. May be called
+ * by bus-specific DMA map synchronization functions.
+ */
void
-_dmamap_sync(v, map, ops)
- void *v;
+_dmamap_sync(t, map, op)
+ bus_dma_tag_t t;
bus_dmamap_t map;
- bus_dmasync_op_t ops;
+ bus_dmasync_op_t op;
{
-#if 0
- __asm __volatile ("syncdma");
-#endif
+
+ /* Nothing to do here. */
}
+/*
+ * Common function for DMA-safe memory allocation. May be called
+ * by bus-specific DMA memory allocation functions.
+ */
int
-_dmamem_alloc(v, size, alignment, boundary, segs, nsegs, rsegs, flags)
- void *v;
+_dmamem_alloc(t, size, alignment, boundary, segs, nsegs, rsegs, flags)
+ bus_dma_tag_t t;
bus_size_t size, alignment, boundary;
bus_dma_segment_t *segs;
int nsegs;
int *rsegs;
int flags;
{
- vaddr_t va;
- paddr_t spa, epa;
-
- size = round_page(size);
-
-#if defined(UVM)
- va = uvm_pagealloc_contig(size, VM_MIN_KERNEL_ADDRESS,
- VM_MAX_KERNEL_ADDRESS, NBPG);
-#else
-# if 0
- vm_page_alloc_memory(size, VM_MIN_KERNEL_ADDRESS,
- VM_MAX_KERNEL_ADDRESS,
- alignment, boundary, (void *)&va, nsegs, (flags & BUS_DMA_NOWAIT));
-# else
- va = kmem_alloc_wait(phys_map, NBPG); /* XXX */
-# endif
-#endif
- if (va == NULL)
- return (ENOMEM);
-
- segs[0].ds_addr = va;
- segs[0].ds_len = size;
- *rsegs = nsegs;
-
-#if 0
- /* XXX for now */
- for (epa = size + (spa = kvtop((caddr_t)va)); spa < epa; spa += NBPG)
- pmap_changebit(spa, TLB_UNCACHEABLE, 0);
-#endif
-
- return 0;
+ extern int avail_end;
+ return (_dmamem_alloc_range(t, size, alignment, boundary,
+ segs, nsegs, rsegs, flags, 0, 0xf0000000));
}
+/*
+ * Common function for freeing DMA-safe memory. May be called by
+ * bus-specific DMA memory free functions.
+ */
void
-_dmamem_free(v, segs, nsegs)
- void *v;
+_dmamem_free(t, segs, nsegs)
+ bus_dma_tag_t t;
bus_dma_segment_t *segs;
int nsegs;
{
-#if defined (UVM)
- uvm_km_free(kmem_map, segs[0].ds_addr, M_DEVBUF);
+ vm_page_t m;
+ bus_addr_t addr;
+ struct pglist mlist;
+ int curseg;
+
+ /*
+ * Build a list of pages to free back to the VM system.
+ */
+ TAILQ_INIT(&mlist);
+ for (curseg = 0; curseg < nsegs; curseg++) {
+ for (addr = segs[curseg].ds_addr;
+ addr < (segs[curseg].ds_addr + segs[curseg].ds_len);
+ addr += PAGE_SIZE) {
+ m = PHYS_TO_VM_PAGE(addr);
+ TAILQ_INSERT_TAIL(&mlist, m, pageq);
+ }
+ }
+
+#if defined(UVM)
+ uvm_pglistfree(&mlist);
#else
- kmem_free(kernel_map, segs[0].ds_addr, segs[0].ds_len);
+ vm_page_free_memory(&mlist);
#endif
}
+/*
+ * Common function for mapping DMA-safe memory. May be called by
+ * bus-specific DMA memory map functions.
+ */
int
-_dmamem_map(v, segs, nsegs, size, kvap, flags)
- void *v;
+_dmamem_map(t, segs, nsegs, size, kvap, flags)
+ bus_dma_tag_t t;
bus_dma_segment_t *segs;
int nsegs;
size_t size;
caddr_t *kvap;
int flags;
{
- *kvap = (caddr_t)segs[0].ds_addr;
- return 0;
+ vm_offset_t va;
+ bus_addr_t addr;
+ int curseg;
+
+ size = round_page(size);
+#if defined(UVM)
+ va = uvm_km_valloc(kmem_map, size);
+#else
+ va = kmem_alloc_pageable(kmem_map, size);
+#endif
+ if (va == 0)
+ return (ENOMEM);
+
+ *kvap = (caddr_t)va;
+
+ for (curseg = 0; curseg < nsegs; curseg++) {
+ for (addr = segs[curseg].ds_addr;
+ addr < (segs[curseg].ds_addr + segs[curseg].ds_len);
+ addr += NBPG, va += NBPG, size -= NBPG) {
+ if (size == 0)
+ panic("_bus_dmamem_map: size botch");
+ pmap_enter(pmap_kernel(), va, addr,
+ VM_PROT_READ | VM_PROT_WRITE, TRUE,
+ VM_PROT_READ | VM_PROT_WRITE);
+ }
+ }
+
+ return (0);
}
+/*
+ * Common function for unmapping DMA-safe memory. May be called by
+ * bus-specific DMA memory unmapping functions.
+ */
void
-_dmamem_unmap(v, kva, size)
- void *v;
+_dmamem_unmap(t, kva, size)
+ bus_dma_tag_t t;
caddr_t kva;
size_t size;
{
+
+#ifdef DIAGNOSTIC
+ if ((u_long)kva & PGOFSET)
+ panic("_bus_dmamem_unmap");
+#endif
+
+ size = round_page(size);
+#if defined(UVM)
+ uvm_km_free(kmem_map, (vm_offset_t)kva, size);
+#else
+ kmem_free(kmem_map, (vm_offset_t)kva, size);
+#endif
}
+/*
+ * Common functin for mmap(2)'ing DMA-safe memory. May be called by
+ * bus-specific DMA mmap(2)'ing functions.
+ */
int
-_dmamem_mmap(v, segs, nsegs, off, prot, flags)
- void *v;
+_dmamem_mmap(t, segs, nsegs, off, prot, flags)
+ bus_dma_tag_t t;
bus_dma_segment_t *segs;
int nsegs, off, prot, flags;
{
- panic("_dmamem_mmap: not implemented");
+ int i;
+
+ for (i = 0; i < nsegs; i++) {
+#ifdef DIAGNOSTIC
+ if (off & PGOFSET)
+ panic("_bus_dmamem_mmap: offset unaligned");
+ if (segs[i].ds_addr & PGOFSET)
+ panic("_bus_dmamem_mmap: segment unaligned");
+ if (segs[i].ds_len & PGOFSET)
+ panic("_bus_dmamem_mmap: segment size not multiple"
+ " of page size");
+#endif
+ if (off >= segs[i].ds_len) {
+ off -= segs[i].ds_len;
+ continue;
+ }
+
+ return (powerpc_btop((caddr_t)segs[i].ds_addr + off));
+ }
+
+ /* Page not found. */
+ return (-1);
}
+/**********************************************************************
+ * DMA utility functions
+ **********************************************************************/
+
+/*
+ * Allocate physical memory from the given physical address range.
+ * Called by DMA-safe memory allocation methods.
+ */
int
-dma_cachectl(p, size)
- caddr_t p;
- int size;
+_dmamem_alloc_range(t, size, alignment, boundary, segs, nsegs, rsegs,
+ flags, low, high)
+ bus_dma_tag_t t;
+ bus_size_t size, alignment, boundary;
+ bus_dma_segment_t *segs;
+ int nsegs;
+ int *rsegs;
+ int flags;
+ vm_offset_t low;
+ vm_offset_t high;
{
-#if 0
- fdcache(HPPA_SID_KERNEL, (vaddr_t)p, size);
- sync_caches();
+ vm_offset_t curaddr, lastaddr;
+ vm_page_t m;
+ struct pglist mlist;
+ int curseg, error;
+
+ /* Always round the size. */
+ size = round_page(size);
+
+ /*
+ * Allocate pages from the VM system.
+ */
+ TAILQ_INIT(&mlist);
+#if defined(UVM)
+ error = uvm_pglistalloc(size, low, high,
+ alignment, boundary, &mlist, nsegs, (flags & BUS_DMA_NOWAIT) == 0);
+#else
+ error = vm_page_alloc_memory(size, low, high,
+ alignment, boundary, &mlist, nsegs, (flags & BUS_DMA_NOWAIT) == 0);
#endif
- return 0;
+ if (error)
+ return (error);
+
+ /*
+ * Compute the location, size, and number of segments actually
+ * returned by the VM code.
+ */
+ m = mlist.tqh_first;
+ curseg = 0;
+ lastaddr = segs[curseg].ds_addr = VM_PAGE_TO_PHYS(m);
+ segs[curseg].ds_len = PAGE_SIZE;
+ m = m->pageq.tqe_next;
+
+ for (; m != NULL; m = m->pageq.tqe_next) {
+ curaddr = VM_PAGE_TO_PHYS(m);
+#ifdef DIAGNOSTIC
+ if (curaddr < low || curaddr >= high) {
+ printf("vm_page_alloc_memory returned non-sensical"
+ " address 0x%lx\n", curaddr);
+ panic("dmamem_alloc_range");
+ }
+#endif
+ if (curaddr == (lastaddr + PAGE_SIZE))
+ segs[curseg].ds_len += PAGE_SIZE;
+ else {
+ curseg++;
+ segs[curseg].ds_addr = curaddr;
+ segs[curseg].ds_len = PAGE_SIZE;
+ }
+ lastaddr = curaddr;
+ }
+
+ *rsegs = curseg + 1;
+
+ return (0);
}