summaryrefslogtreecommitdiff
path: root/sys/arch/sgi
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/sgi')
-rw-r--r--sys/arch/sgi/include/bus.h6
-rw-r--r--sys/arch/sgi/localbus/macebus.c3
-rw-r--r--sys/arch/sgi/pci/macepcibridge.c3
-rw-r--r--sys/arch/sgi/sgi/bus_dma.c441
-rw-r--r--sys/arch/sgi/xbow/xbridge.c165
5 files changed, 271 insertions, 347 deletions
diff --git a/sys/arch/sgi/include/bus.h b/sys/arch/sgi/include/bus.h
index 6b5d7490712..1f6e5585f5c 100644
--- a/sys/arch/sgi/include/bus.h
+++ b/sys/arch/sgi/include/bus.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bus.h,v 1.15 2009/05/31 17:42:13 miod Exp $ */
+/* $OpenBSD: bus.h,v 1.16 2009/07/17 18:06:49 miod Exp $ */
/*
* Copyright (c) 2003-2004 Opsycon AB Sweden. All rights reserved.
@@ -370,6 +370,8 @@ struct machine_bus_dma_tag {
struct uio *, int);
int (*_dmamap_load_raw)(bus_dma_tag_t , bus_dmamap_t,
bus_dma_segment_t *, int, bus_size_t, int);
+ int (*_dmamap_load_buffer)(bus_dma_tag_t, bus_dmamap_t, void *,
+ bus_size_t, struct proc *, int, paddr_t *, int *, int);
void (*_dmamap_unload)(bus_dma_tag_t , bus_dmamap_t);
void (*_dmamap_sync)(bus_dma_tag_t , bus_dmamap_t,
bus_addr_t, bus_size_t, int);
@@ -432,6 +434,8 @@ int _dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *, int);
int _dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int);
int _dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t,
bus_dma_segment_t *, int, bus_size_t, int);
+int _dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *,
+ bus_size_t, struct proc *, int, paddr_t *, int *, int);
void _dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
void _dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
bus_size_t, int);
diff --git a/sys/arch/sgi/localbus/macebus.c b/sys/arch/sgi/localbus/macebus.c
index 01c769f9624..64e069dc9e2 100644
--- a/sys/arch/sgi/localbus/macebus.c
+++ b/sys/arch/sgi/localbus/macebus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: macebus.c,v 1.38 2009/03/20 18:41:07 miod Exp $ */
+/* $OpenBSD: macebus.c,v 1.39 2009/07/17 18:06:51 miod Exp $ */
/*
* Copyright (c) 2000-2004 Opsycon AB (www.opsycon.se)
@@ -151,6 +151,7 @@ struct machine_bus_dma_tag mace_bus_dma_tag = {
_dmamap_load_mbuf,
_dmamap_load_uio,
_dmamap_load_raw,
+ _dmamap_load_buffer,
_dmamap_unload,
_dmamap_sync,
_dmamem_alloc,
diff --git a/sys/arch/sgi/pci/macepcibridge.c b/sys/arch/sgi/pci/macepcibridge.c
index 2c6653810ad..cdf4b5247ce 100644
--- a/sys/arch/sgi/pci/macepcibridge.c
+++ b/sys/arch/sgi/pci/macepcibridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: macepcibridge.c,v 1.23 2009/07/16 21:02:56 miod Exp $ */
+/* $OpenBSD: macepcibridge.c,v 1.24 2009/07/17 18:06:51 miod Exp $ */
/*
* Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se)
@@ -133,6 +133,7 @@ struct machine_bus_dma_tag pci_bus_dma_tag = {
_dmamap_load_mbuf,
_dmamap_load_uio,
_dmamap_load_raw,
+ _dmamap_load_buffer,
_dmamap_unload,
_dmamap_sync,
_dmamem_alloc,
diff --git a/sys/arch/sgi/sgi/bus_dma.c b/sys/arch/sgi/sgi/bus_dma.c
index a3969275f41..a9f52aa0194 100644
--- a/sys/arch/sgi/sgi/bus_dma.c
+++ b/sys/arch/sgi/sgi/bus_dma.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bus_dma.c,v 1.13 2009/05/24 17:31:07 miod Exp $ */
+/* $OpenBSD: bus_dma.c,v 1.14 2009/07/17 18:06:51 miod Exp $ */
/*
* Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -25,6 +25,35 @@
* SUCH DAMAGE.
*
*/
+/*-
+ * Copyright (c) 1996, 1997, 1998 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:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 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>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -40,21 +69,14 @@
#include <machine/autoconf.h>
#include <machine/bus.h>
-#include <sgi/sgi/ip30.h>
/*
* Common function for DMA map creation. May be called by bus-specific
* DMA map creation functions.
*/
int
-_dmamap_create(t, size, nsegments, maxsegsz, boundary, flags, dmamp)
- bus_dma_tag_t t;
- bus_size_t size;
- int nsegments;
- bus_size_t maxsegsz;
- bus_size_t boundary;
- int flags;
- bus_dmamap_t *dmamp;
+_dmamap_create(bus_dma_tag_t t, bus_size_t size, int nsegments,
+ bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp)
{
struct machine_bus_dmamap *map;
void *mapstore;
@@ -104,20 +126,11 @@ _dmamap_destroy(bus_dma_tag_t t, bus_dmamap_t map)
* be called by bus-specific DMA map load functions.
*/
int
-_dmamap_load(t, map, buf, buflen, p, flags)
- bus_dma_tag_t t;
- bus_dmamap_t map;
- void *buf;
- bus_size_t buflen;
- struct proc *p;
- int flags;
+_dmamap_load(bus_dma_tag_t t, bus_dmamap_t map, void *buf, bus_size_t buflen,
+ struct proc *p, int flags)
{
- bus_size_t sgsize;
- bus_addr_t curaddr, lastaddr, baddr, bmask;
- caddr_t vaddr = buf;
- int first, seg;
- pmap_t pmap;
- bus_size_t saved_buflen;
+ paddr_t lastaddr;
+ int seg, error;
/*
* Make sure that on error condition we return "no valid mappings".
@@ -128,154 +141,112 @@ _dmamap_load(t, map, buf, buflen, p, flags)
if (buflen > map->_dm_size)
return (EINVAL);
- if (p != NULL)
- pmap = p->p_vmspace->vm_map.pmap;
- else
- pmap = pmap_kernel();
-
- lastaddr = ~0; /* XXX gcc */
- bmask = ~(map->_dm_boundary - 1);
- if (t->_dma_mask != 0)
- bmask &= t->_dma_mask;
-
- saved_buflen = buflen;
- for (first = 1, seg = 0; buflen > 0; ) {
- /*
- * Get the physical address for this segment.
- */
- if (pmap_extract(pmap, (vaddr_t)vaddr, (paddr_t *)&curaddr) ==
- FALSE)
- panic("_dmapmap_load: pmap_extract(%x, %x) failed!",
- pmap, vaddr);
-
- /*
- * Compute the segment size, and adjust counts.
- */
- sgsize = NBPG - ((u_long)vaddr & PGOFSET);
- if (buflen < sgsize)
- sgsize = buflen;
-
- /*
- * Make sure we don't cross any boundaries.
- */
- if (map->_dm_boundary > 0) {
- baddr = (curaddr + map->_dm_boundary) & bmask;
- if (sgsize > (baddr - curaddr))
- sgsize = (baddr - curaddr);
- }
-
- /*
- * Insert chunk into a segment, coalescing with
- * previous segment if possible.
- */
- if (first) {
- map->dm_segs[seg].ds_addr =
- (*t->_pa_to_device)(curaddr);
- map->dm_segs[seg].ds_len = sgsize;
- map->dm_segs[seg]._ds_vaddr = (vaddr_t)vaddr;
- first = 0;
- } else {
- if (curaddr == lastaddr &&
- (map->dm_segs[seg].ds_len + sgsize) <=
- map->_dm_maxsegsz &&
- (map->_dm_boundary == 0 ||
- (map->dm_segs[seg].ds_addr & bmask) ==
- (curaddr & bmask)))
- map->dm_segs[seg].ds_len += sgsize;
- else {
- if (++seg >= map->_dm_segcnt)
- break;
- map->dm_segs[seg].ds_addr =
- (*t->_pa_to_device)(curaddr);
- map->dm_segs[seg].ds_len = sgsize;
- map->dm_segs[seg]._ds_vaddr = (vaddr_t)vaddr;
- }
- }
-
- lastaddr = curaddr + sgsize;
- vaddr += sgsize;
- buflen -= sgsize;
+ seg = 0;
+ error = (*t->_dmamap_load_buffer)(t, map, buf, buflen, p, flags,
+ &lastaddr, &seg, 1);
+ if (error == 0) {
+ map->dm_nsegs = seg + 1;
+ map->dm_mapsize = buflen;
}
- /*
- * Did we fit?
- */
- if (buflen != 0)
- return (EFBIG); /* XXX better return value here? */
-
- map->dm_nsegs = seg + 1;
- map->dm_mapsize = saved_buflen;
- return (0);
+ return (error);
}
/*
* Like _bus_dmamap_load(), but for mbufs.
*/
int
-_dmamap_load_mbuf(t, map, m, flags)
- bus_dma_tag_t t;
- bus_dmamap_t map;
- struct mbuf *m;
- int flags;
+_dmamap_load_mbuf(bus_dma_tag_t t, bus_dmamap_t map, struct mbuf *m0, int flags)
{
- int i;
- size_t len;
+ paddr_t lastaddr;
+ int seg, error, first;
+ struct mbuf *m;
+ /*
+ * Make sure that on error condition we return "no valid mappings".
+ */
map->dm_nsegs = 0;
map->dm_mapsize = 0;
- i = 0;
- len = 0;
- while (m) {
- vaddr_t vaddr = mtod(m, vaddr_t);
- long buflen = (long)m->m_len;
-
- len += buflen;
- while (buflen > 0 && i < map->_dm_segcnt) {
- paddr_t pa;
- long incr;
-
- incr = min(buflen, NBPG);
- buflen -= incr;
- if (pmap_extract(pmap_kernel(), vaddr, &pa) == FALSE)
- panic("_dmamap_load_mbuf: pmap_extract(%x, %x) failed!",
- pmap_kernel(), vaddr);
-
- if (i > 0 && pa == (*t->_device_to_pa)(map->dm_segs[i-1].ds_addr + map->dm_segs[i-1].ds_len)
- && ((map->dm_segs[i-1].ds_len + incr) < map->_dm_maxsegsz)) {
- /* Hey, waddyaknow, they're contiguous */
- map->dm_segs[i-1].ds_len += incr;
- continue;
- }
- map->dm_segs[i].ds_addr =
- (*t->_pa_to_device)(pa);
- map->dm_segs[i]._ds_vaddr = vaddr;
- map->dm_segs[i].ds_len = incr;
- i++;
- vaddr += incr;
- }
- m = m->m_next;
- if (m && i >= map->_dm_segcnt) {
- /* Exceeded the size of our dmamap */
- return EFBIG;
- }
+#ifdef DIAGNOSTIC
+ if ((m0->m_flags & M_PKTHDR) == 0)
+ panic("_dmamap_load_mbuf: no packet header");
+#endif
+
+ if (m0->m_pkthdr.len > map->_dm_size)
+ return (EINVAL);
+
+ first = 1;
+ seg = 0;
+ error = 0;
+ for (m = m0; m != NULL && error == 0; m = m->m_next) {
+ if (m->m_len == 0)
+ continue;
+ error = (*t->_dmamap_load_buffer)(t, map, m->m_data, m->m_len,
+ NULL, flags, &lastaddr, &seg, first);
+ first = 0;
}
- map->dm_nsegs = i;
- map->dm_mapsize = len;
- return (0);
+ if (error == 0) {
+ map->dm_nsegs = seg + 1;
+ map->dm_mapsize = m0->m_pkthdr.len;
+ }
+
+ return (error);
}
/*
* Like _dmamap_load(), but for uios.
*/
int
-_dmamap_load_uio(t, map, uio, flags)
- bus_dma_tag_t t;
- bus_dmamap_t map;
- struct uio *uio;
- int flags;
+_dmamap_load_uio(bus_dma_tag_t t, bus_dmamap_t map, struct uio *uio, int flags)
{
- return (EOPNOTSUPP);
+ paddr_t lastaddr;
+ int seg, i, error, first;
+ bus_size_t minlen, resid;
+ struct proc *p = NULL;
+ struct iovec *iov;
+ void *addr;
+
+ /*
+ * Make sure that on error condition we return "no valid mappings".
+ */
+ map->dm_nsegs = 0;
+ map->dm_mapsize = 0;
+
+ resid = uio->uio_resid;
+ iov = uio->uio_iov;
+
+ if (uio->uio_segflg == UIO_USERSPACE) {
+ p = uio->uio_procp;
+#ifdef DIAGNOSTIC
+ if (p == NULL)
+ panic("_dmamap_load_uio: USERSPACE but no proc");
+#endif
+ }
+
+ first = 1;
+ seg = 0;
+ error = 0;
+ for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0; i++) {
+ /*
+ * Now at the first iovec to load. Load each iovec
+ * until we have exhausted the residual count.
+ */
+ minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len;
+ addr = (void *)iov[i].iov_base;
+
+ error = (*t->_dmamap_load_buffer)(t, map, addr, minlen,
+ p, flags, &lastaddr, &seg, first);
+ first = 0;
+
+ resid -= minlen;
+ }
+ if (error == 0) {
+ map->dm_nsegs = seg + 1;
+ map->dm_mapsize = uio->uio_resid;
+ }
+
+ return (error);
}
/*
@@ -283,13 +254,8 @@ _dmamap_load_uio(t, map, uio, flags)
* bus_dmamem_alloc().
*/
int
-_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;
+_dmamap_load_raw(bus_dma_tag_t t, bus_dmamap_t map, bus_dma_segment_t *segs,
+ int nsegs, bus_size_t size, int flags)
{
if (nsegs > map->_dm_segcnt || size > map->_dm_size)
return (EINVAL);
@@ -323,11 +289,8 @@ _dmamap_load_raw(t, map, segs, nsegs, size, flags)
* bus-specific DMA map unload functions.
*/
void
-_dmamap_unload(t, map)
- bus_dma_tag_t t;
- bus_dmamap_t map;
+_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t map)
{
-
/*
* No resources to free; just mark the mappings as
* invalid.
@@ -341,12 +304,8 @@ _dmamap_unload(t, map)
* by bus-specific DMA map synchronization functions.
*/
void
-_dmamap_sync(t, map, addr, size, op)
- bus_dma_tag_t t;
- bus_dmamap_t map;
- bus_addr_t addr;
- bus_size_t size;
- int op;
+_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t addr,
+ bus_size_t size, int op)
{
#define SYNC_R 0 /* WB invalidate, WT invalidate */
#define SYNC_W 1 /* WB writeback + invalidate, WT unaffected */
@@ -432,13 +391,9 @@ _dmamap_sync(t, map, addr, size, op)
* by bus-specific DMA memory allocation functions.
*/
int
-_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;
+_dmamem_alloc(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment,
+ bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs,
+ int flags)
{
return _dmamem_alloc_range(t, size, alignment, boundary,
segs, nsegs, rsegs, flags, (vaddr_t)0, (vaddr_t)-1);
@@ -449,10 +404,7 @@ _dmamem_alloc(t, size, alignment, boundary, segs, nsegs, rsegs, flags)
* bus-specific DMA memory free functions.
*/
void
-_dmamem_free(t, segs, nsegs)
- bus_dma_tag_t t;
- bus_dma_segment_t *segs;
- int nsegs;
+_dmamem_free(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs)
{
vm_page_t m;
bus_addr_t addr;
@@ -480,13 +432,8 @@ _dmamem_free(t, segs, nsegs)
* bus-specific DMA memory map functions.
*/
int
-_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;
+_dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, size_t size,
+ caddr_t *kvap, int flags)
{
vaddr_t va;
paddr_t pa;
@@ -540,10 +487,7 @@ _dmamem_map(t, segs, nsegs, size, kvap, flags)
* bus-specific DMA memory unmapping functions.
*/
void
-_dmamem_unmap(t, kva, size)
- bus_dma_tag_t t;
- caddr_t kva;
- size_t size;
+_dmamem_unmap(bus_dma_tag_t t, caddr_t kva, size_t size)
{
if (IS_XKPHYS((vaddr_t)kva))
return;
@@ -559,12 +503,8 @@ _dmamem_unmap(t, kva, size)
* bus-specific DMA mmap(2)'ing functions.
*/
paddr_t
-_dmamem_mmap(t, segs, nsegs, off, prot, flags)
- bus_dma_tag_t t;
- bus_dma_segment_t *segs;
- int nsegs;
- off_t off;
- int prot, flags;
+_dmamem_mmap(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, off_t off,
+ int prot, int flags)
{
int i;
@@ -595,20 +535,111 @@ _dmamem_mmap(t, segs, nsegs, off, prot, flags)
**********************************************************************/
/*
+ * Utility function to load a linear buffer. lastaddrp holds state
+ * between invocations (for multiple-buffer loads). segp contains
+ * the starting segment on entrance, and the ending segment on exit.
+ * first indicates if this is the first invocation of this function.
+ */
+int
+_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
+ bus_size_t buflen, struct proc *p, int flags, paddr_t *lastaddrp,
+ int *segp, int first)
+{
+ bus_size_t sgsize;
+ bus_addr_t lastaddr, baddr, bmask;
+ paddr_t curaddr;
+ vaddr_t vaddr = (vaddr_t)buf;
+ int seg;
+ pmap_t pmap;
+
+ if (p != NULL)
+ pmap = p->p_vmspace->vm_map.pmap;
+ else
+ pmap = pmap_kernel();
+
+ lastaddr = *lastaddrp;
+ bmask = ~(map->_dm_boundary - 1);
+ if (t->_dma_mask != 0)
+ bmask &= t->_dma_mask;
+
+ for (seg = *segp; buflen > 0; ) {
+ /*
+ * Get the physical address for this segment.
+ */
+ if (pmap_extract(pmap, vaddr, &curaddr) == FALSE)
+ panic("_dmapmap_load_buffer: pmap_extract(%x, %x) failed!",
+ pmap, vaddr);
+
+ /*
+ * Compute the segment size, and adjust counts.
+ */
+ sgsize = NBPG - ((u_long)vaddr & PGOFSET);
+ if (buflen < sgsize)
+ sgsize = buflen;
+
+ /*
+ * Make sure we don't cross any boundaries.
+ */
+ if (map->_dm_boundary > 0) {
+ baddr = ((bus_addr_t)curaddr + map->_dm_boundary) &
+ bmask;
+ if (sgsize > (baddr - (bus_addr_t)curaddr))
+ sgsize = (baddr - (bus_addr_t)curaddr);
+ }
+
+ /*
+ * Insert chunk into a segment, coalescing with
+ * previous segment if possible.
+ */
+ if (first) {
+ map->dm_segs[seg].ds_addr =
+ (*t->_pa_to_device)(curaddr);
+ map->dm_segs[seg].ds_len = sgsize;
+ map->dm_segs[seg]._ds_vaddr = (vaddr_t)vaddr;
+ first = 0;
+ } else {
+ if ((bus_addr_t)curaddr == lastaddr &&
+ (map->dm_segs[seg].ds_len + sgsize) <=
+ map->_dm_maxsegsz &&
+ (map->_dm_boundary == 0 ||
+ (map->dm_segs[seg].ds_addr & bmask) ==
+ ((bus_addr_t)curaddr & bmask)))
+ map->dm_segs[seg].ds_len += sgsize;
+ else {
+ if (++seg >= map->_dm_segcnt)
+ break;
+ map->dm_segs[seg].ds_addr =
+ (*t->_pa_to_device)(curaddr);
+ map->dm_segs[seg].ds_len = sgsize;
+ map->dm_segs[seg]._ds_vaddr = (vaddr_t)vaddr;
+ }
+ }
+
+ lastaddr = (bus_addr_t)curaddr + sgsize;
+ vaddr += sgsize;
+ buflen -= sgsize;
+ }
+
+ *segp = seg;
+ *lastaddrp = lastaddr;
+
+ /*
+ * Did we fit?
+ */
+ if (buflen != 0)
+ return (EFBIG); /* XXX better return value here? */
+
+ return (0);
+}
+
+/*
* Allocate physical memory from the given physical address range.
* Called by DMA-safe memory allocation methods.
*/
int
-_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;
- vaddr_t low;
- vaddr_t high;
+_dmamem_alloc_range(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment,
+ bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs,
+ int flags, vaddr_t low, vaddr_t high)
{
vaddr_t curaddr, lastaddr;
vm_page_t m;
diff --git a/sys/arch/sgi/xbow/xbridge.c b/sys/arch/sgi/xbow/xbridge.c
index da6ba7e3e63..d1c65e0552f 100644
--- a/sys/arch/sgi/xbow/xbridge.c
+++ b/sys/arch/sgi/xbow/xbridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xbridge.c,v 1.36 2009/07/17 07:14:00 miod Exp $ */
+/* $OpenBSD: xbridge.c,v 1.37 2009/07/17 18:06:51 miod Exp $ */
/*
* Copyright (c) 2008, 2009 Miodrag Vallat.
@@ -154,11 +154,8 @@ int xbridge_space_map_io(bus_space_tag_t, bus_addr_t, bus_size_t, int,
int xbridge_space_map_mem(bus_space_tag_t, bus_addr_t, bus_size_t, int,
bus_space_handle_t *);
-int xbridge_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t,
- struct proc *, int);
-int xbridge_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *,
- int);
-int xbridge_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int);
+int xbridge_dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *,
+ bus_size_t, struct proc *, int, paddr_t *, int *, int);
void xbridge_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
int xbridge_dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, bus_size_t,
bus_dma_segment_t *, int, int *, int);
@@ -195,10 +192,11 @@ const struct machine_bus_dma_tag xbridge_dma_tag = {
NULL, /* _cookie */
_dmamap_create,
_dmamap_destroy,
- xbridge_dmamap_load,
- xbridge_dmamap_load_mbuf,
- xbridge_dmamap_load_uio,
+ _dmamap_load,
+ _dmamap_load_mbuf,
+ _dmamap_load_uio,
_dmamap_load_raw,
+ xbridge_dmamap_load_buffer,
xbridge_dmamap_unload,
_dmamap_sync,
xbridge_dmamem_alloc,
@@ -1351,49 +1349,43 @@ xbridge_address_unmap(struct xbridge_softc *sc, bus_addr_t ba, bus_size_t len)
}
/*
- * bus_dmamap_load() implementation.
+ * bus_dmamap_loadXXX() bowels implementation.
*/
int
-xbridge_dmamap_load(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
- bus_size_t buflen, struct proc *p, int flags)
+xbridge_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
+ bus_size_t buflen, struct proc *p, int flags, paddr_t *lastaddrp,
+ int *segp, int first)
{
struct xbridge_softc *sc = t->_cookie;
- paddr_t pa;
- bus_addr_t lastaddr, busaddr, endaddr;
bus_size_t sgsize;
- bus_addr_t baddr, bmask;
- caddr_t vaddr = buf;
- int first, seg;
+ bus_addr_t lastaddr, baddr, bmask;
+ bus_addr_t busaddr, endaddr;
+ paddr_t pa;
+ vaddr_t vaddr = (vaddr_t)buf;
+ int seg;
pmap_t pmap;
- bus_size_t saved_buflen;
int rc;
- /*
- * Make sure that on error condition we return "no valid mappings".
- */
- map->dm_nsegs = 0;
- map->dm_mapsize = 0;
- for (seg = 0; seg < map->_dm_segcnt; seg++)
- map->dm_segs[seg].ds_addr = 0;
-
- if (buflen > map->_dm_size)
- return EINVAL;
+ if (first) {
+ for (seg = 0; seg < map->_dm_segcnt; seg++)
+ map->dm_segs[seg].ds_addr = 0;
+ }
if (p != NULL)
pmap = p->p_vmspace->vm_map.pmap;
else
pmap = pmap_kernel();
+ lastaddr = *lastaddrp;
bmask = ~(map->_dm_boundary - 1);
if (t->_dma_mask != 0)
bmask &= t->_dma_mask;
- saved_buflen = buflen;
- for (first = 1, seg = 0; buflen > 0; ) {
+ for (seg = *segp; buflen > 0; ) {
/*
* Get the physical address for this segment.
*/
- if (pmap_extract(pmap, (vaddr_t)vaddr, &pa) == FALSE)
+ if (pmap_extract(pmap, vaddr, &pa) == FALSE)
panic("%s: pmap_extract(%x, %x) failed",
__func__, pmap, vaddr);
@@ -1461,6 +1453,9 @@ xbridge_dmamap_load(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
buflen -= sgsize;
}
+ *segp = seg;
+ *lastaddrp = lastaddr;
+
/*
* Did we fit?
*/
@@ -1469,8 +1464,6 @@ xbridge_dmamap_load(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
goto fail_unmap;
}
- map->dm_nsegs = seg + 1;
- map->dm_mapsize = saved_buflen;
return 0;
fail_unmap:
@@ -1487,112 +1480,6 @@ fail_unmap:
}
/*
- * bus_dmamap_load_mbuf() implementation.
- */
-int
-xbridge_dmamap_load_mbuf(bus_dma_tag_t t, bus_dmamap_t map, struct mbuf *m,
- int flags)
-{
- struct xbridge_softc *sc = t->_cookie;
- bus_addr_t lastaddr, busaddr, endaddr;
- bus_size_t sgsize;
- paddr_t pa;
- vaddr_t lastva;
- int seg;
- size_t len;
- int rc;
-
- map->dm_nsegs = 0;
- map->dm_mapsize = 0;
- for (seg = 0; seg < map->_dm_segcnt; seg++)
- map->dm_segs[seg].ds_addr = 0;
-
- seg = 0;
- len = 0;
- while (m != NULL) {
- vaddr_t vaddr = mtod(m, vaddr_t);
- long buflen = (long)m->m_len;
-
- len += buflen;
- while (buflen > 0 && seg < map->_dm_segcnt) {
- if (pmap_extract(pmap_kernel(), vaddr, &pa) == FALSE)
- panic("%s: pmap_extract(%x, %x) failed",
- __func__, pmap_kernel(), vaddr);
-
- /*
- * Compute the DMA address and the physical range
- * this mapping can cover.
- */
- if (xbridge_address_map(sc, pa, &busaddr,
- &endaddr) != 0) {
- rc = ENOMEM;
- goto fail_unmap;
- }
-
- sgsize = PAGE_SIZE - ((u_long)vaddr & PGOFSET);
- sgsize = min(buflen, sgsize);
- sgsize = min(endaddr - busaddr, sgsize);
-
- /*
- * Try to coalesce with previous entry.
- * We need both the physical addresses and
- * the virtual address to be contiguous, for
- * bus_dmamap_sync() to behave correctly.
- */
- if (seg > 0 &&
- busaddr == lastaddr && vaddr == lastva &&
- (map->dm_segs[seg - 1].ds_len + sgsize <=
- map->_dm_maxsegsz))
- map->dm_segs[seg - 1].ds_len += sgsize;
- else {
- map->dm_segs[seg].ds_addr = busaddr;
- map->dm_segs[seg].ds_len = sgsize;
- map->dm_segs[seg]._ds_vaddr = vaddr;
- seg++;
- }
-
- lastaddr = busaddr + sgsize;
- if (lastaddr == endaddr)
- lastaddr = ~0; /* can't coalesce */
- vaddr += sgsize;
- lastva = vaddr;
- buflen -= sgsize;
- }
- m = m->m_next;
- if (m && seg >= map->_dm_segcnt) {
- /* Exceeded the size of our dmamap */
- rc = EFBIG;
- goto fail_unmap;
- }
- }
- map->dm_nsegs = seg;
- map->dm_mapsize = len;
- return 0;
-
-fail_unmap:
- /*
- * If control goes there, we need to unref all our ATE, if any.
- */
- for (seg = 0; seg < map->_dm_segcnt; seg++) {
- xbridge_address_unmap(sc, map->dm_segs[seg].ds_addr,
- map->dm_segs[seg].ds_len);
- map->dm_segs[seg].ds_addr = 0;
- }
-
- return rc;
-}
-
-/*
- * bus_dmamap_load_uio() non-implementation.
- */
-int
-xbridge_dmamap_load_uio(bus_dma_tag_t t, bus_dmamap_t map, struct uio *uio,
- int flags)
-{
- return EOPNOTSUPP;
-}
-
-/*
* bus_dmamap_unload() implementation.
*/
void