Module Name:    src
Committed By:   matt
Date:           Tue Sep 18 05:47:28 UTC 2012

Modified Files:
        src/sys/arch/arm/arm32: bus_dma.c
        src/sys/arch/arm/at91: at91_bus_dma.c
        src/sys/arch/arm/broadcom: bcm2835_dma.c bcm53xx_board.c
        src/sys/arch/arm/ep93xx: ep93xx_busdma.c
        src/sys/arch/arm/footbridge: footbridge_pci.c
        src/sys/arch/arm/gemini: gemini_dma.c
        src/sys/arch/arm/imx: imx_dma.c
        src/sys/arch/arm/include: bus_defs.h bus_funcs.h
        src/sys/arch/arm/ixp12x0: ixp12x0_pci_dma.c
        src/sys/arch/arm/marvell: mvsoc_dma.c
        src/sys/arch/arm/omap: omap_dma.c
        src/sys/arch/arm/s3c2xx0: s3c2xx0_busdma.c
        src/sys/arch/arm/xscale: becc.c i80312.c i80321.c ixp425_ixme.c
            ixp425_pci_dma.c pxa2x0_dma.c

Log Message:
Add bounce buffer support for ARM bus_dma(9).  Add macros to help initialize
bus_dma_tag structures.


To generate a diff of this commit:
cvs rdiff -u -r1.57 -r1.58 src/sys/arch/arm/arm32/bus_dma.c
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/at91/at91_bus_dma.c
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/broadcom/bcm2835_dma.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/broadcom/bcm53xx_board.c
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/ep93xx/ep93xx_busdma.c
cvs rdiff -u -r1.22 -r1.23 src/sys/arch/arm/footbridge/footbridge_pci.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/gemini/gemini_dma.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/imx/imx_dma.c
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/include/bus_defs.h
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/include/bus_funcs.h
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/arm/ixp12x0/ixp12x0_pci_dma.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/marvell/mvsoc_dma.c
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/omap/omap_dma.c
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/s3c2xx0/s3c2xx0_busdma.c
cvs rdiff -u -r1.14 -r1.15 src/sys/arch/arm/xscale/becc.c
cvs rdiff -u -r1.21 -r1.22 src/sys/arch/arm/xscale/i80312.c
cvs rdiff -u -r1.23 -r1.24 src/sys/arch/arm/xscale/i80321.c
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/xscale/ixp425_ixme.c
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/arm/xscale/ixp425_pci_dma.c \
    src/sys/arch/arm/xscale/pxa2x0_dma.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/arm32/bus_dma.c
diff -u src/sys/arch/arm/arm32/bus_dma.c:1.57 src/sys/arch/arm/arm32/bus_dma.c:1.58
--- src/sys/arch/arm/arm32/bus_dma.c:1.57	Tue Sep 11 17:54:12 2012
+++ src/sys/arch/arm/arm32/bus_dma.c	Tue Sep 18 05:47:26 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: bus_dma.c,v 1.57 2012/09/11 17:54:12 matt Exp $	*/
+/*	$NetBSD: bus_dma.c,v 1.58 2012/09/18 05:47:26 matt Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
@@ -33,7 +33,7 @@
 #define _ARM32_BUS_DMA_PRIVATE
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bus_dma.c,v 1.57 2012/09/11 17:54:12 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bus_dma.c,v 1.58 2012/09/18 05:47:26 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -55,10 +55,44 @@ __KERNEL_RCSID(0, "$NetBSD: bus_dma.c,v 
 
 #include <arm/cpufunc.h>
 
+static struct evcnt bus_dma_creates =
+	EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "creates");
+static struct evcnt bus_dma_bounced_creates =
+	EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "bounced creates");
+static struct evcnt bus_dma_loads =
+	EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "loads");
+static struct evcnt bus_dma_bounced_loads =
+	EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "bounced loads");
+static struct evcnt bus_dma_read_bounces =
+	EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "read bounces");
+static struct evcnt bus_dma_write_bounces =
+	EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "write bounces");
+static struct evcnt bus_dma_bounced_unloads =
+	EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "bounced unloads");
+static struct evcnt bus_dma_unloads =
+	EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "unloads");
+static struct evcnt bus_dma_bounced_destroys =
+	EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "bounced destroys");
+static struct evcnt bus_dma_destroys =
+	EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "destroys");
+
+EVCNT_ATTACH_STATIC(bus_dma_creates);
+EVCNT_ATTACH_STATIC(bus_dma_bounced_creates);
+EVCNT_ATTACH_STATIC(bus_dma_loads);
+EVCNT_ATTACH_STATIC(bus_dma_bounced_loads);
+EVCNT_ATTACH_STATIC(bus_dma_read_bounces);
+EVCNT_ATTACH_STATIC(bus_dma_write_bounces);
+EVCNT_ATTACH_STATIC(bus_dma_unloads);
+EVCNT_ATTACH_STATIC(bus_dma_bounced_unloads);
+EVCNT_ATTACH_STATIC(bus_dma_destroys);
+EVCNT_ATTACH_STATIC(bus_dma_bounced_destroys);
+
+#define	STAT_INCR(x)	(bus_dma_ ## x.ev_count++)
+
 int	_bus_dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *,
 	    bus_size_t, struct vmspace *, int);
-struct arm32_dma_range *_bus_dma_inrange(struct arm32_dma_range *,
-	    int, bus_addr_t);
+static struct arm32_dma_range *
+	_bus_dma_inrange(struct arm32_dma_range *, int, bus_addr_t);
 
 /*
  * Check to see if the specified page is in an allowed DMA range.
@@ -89,13 +123,16 @@ _bus_dmamap_load_paddr(bus_dma_tag_t t, 
 {
 	bus_dma_segment_t * const segs = map->dm_segs;
 	int nseg = map->dm_nsegs;
-	bus_addr_t lastaddr = 0xdead;	/* XXX gcc */
+	bus_addr_t lastaddr;
 	bus_addr_t bmask = ~(map->_dm_boundary - 1);
 	bus_addr_t curaddr;
 	bus_size_t sgsize;
 
 	if (nseg > 0)
 		lastaddr = segs[nseg-1].ds_addr + segs[nseg-1].ds_len;
+	else
+		lastaddr = 0xdead;
+	
  again:
 	sgsize = size;
 
@@ -156,6 +193,55 @@ _bus_dmamap_load_paddr(bus_dma_tag_t t, 
 	return (0);
 }
 
+#ifdef _ARM32_NEED_BUS_DMA_BOUNCE
+static int _bus_dma_alloc_bouncebuf(bus_dma_tag_t t, bus_dmamap_t map,
+	    bus_size_t size, int flags);
+static void _bus_dma_free_bouncebuf(bus_dma_tag_t t, bus_dmamap_t map);
+static int _bus_dma_uiomove(void *buf, struct uio *uio, size_t n,
+	    int direction);
+
+static int
+_bus_dma_load_bouncebuf(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
+	size_t buflen, int buftype, int flags)
+{
+	struct arm32_bus_dma_cookie * const cookie = map->_dm_cookie;
+	struct vmspace * const vm = vmspace_kernel();
+	int error;
+
+	KASSERT(cookie != NULL);
+	KASSERT(cookie->id_flags & _BUS_DMA_MIGHT_NEED_BOUNCE);
+
+	/*
+	 * Allocate bounce pages, if necessary.
+	 */
+	if ((cookie->id_flags & _BUS_DMA_HAS_BOUNCE) == 0) {
+		error = _bus_dma_alloc_bouncebuf(t, map, buflen, flags);
+		if (error)
+			return (error);
+	}
+
+	/*
+	 * Cache a pointer to the caller's buffer and load the DMA map
+	 * with the bounce buffer.
+	 */
+	cookie->id_origbuf = buf;
+	cookie->id_origbuflen = buflen;
+	error = _bus_dmamap_load_buffer(t, map, cookie->id_bouncebuf,
+	    buflen, vm, flags);
+	if (error)
+		return (error);
+
+	STAT_INCR(bounced_loads);
+	map->dm_mapsize = buflen;
+	map->_dm_vmspace = vm;
+	map->_dm_buftype = buftype;
+
+	/* ...so _bus_dmamap_sync() knows we're bouncing */
+	cookie->id_flags |= _BUS_DMA_IS_BOUNCING;
+	return 0;
+}
+#endif /* _ARM32_NEED_BUS_DMA_BOUNCE */
+
 /*
  * Common function for DMA map creation.  May be called by bus-specific
  * DMA map creation functions.
@@ -187,11 +273,10 @@ _bus_dmamap_create(bus_dma_tag_t t, bus_
 	 */
 	mapsize = sizeof(struct arm32_bus_dmamap) +
 	    (sizeof(bus_dma_segment_t) * (nsegments - 1));
-	if ((mapstore = malloc(mapsize, M_DMAMAP,
-	    (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK)) == NULL)
+	const int mallocflags = M_ZERO|(flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK;
+	if ((mapstore = malloc(mapsize, M_DMAMAP, mallocflags)) == NULL)
 		return (ENOMEM);
 
-	memset(mapstore, 0, mapsize);
 	map = (struct arm32_bus_dmamap *)mapstore;
 	map->_dm_size = size;
 	map->_dm_segcnt = nsegments;
@@ -199,13 +284,61 @@ _bus_dmamap_create(bus_dma_tag_t t, bus_
 	map->_dm_boundary = boundary;
 	map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT);
 	map->_dm_origbuf = NULL;
-	map->_dm_buftype = ARM32_BUFTYPE_INVALID;
+	map->_dm_buftype = _BUS_DMA_BUFTYPE_INVALID;
 	map->_dm_vmspace = vmspace_kernel();
+	map->_dm_cookie = NULL;
 	map->dm_maxsegsz = maxsegsz;
 	map->dm_mapsize = 0;		/* no valid mappings */
 	map->dm_nsegs = 0;
 
 	*dmamp = map;
+
+#ifdef _ARM32_NEED_BUS_DMA_BOUNCE
+	struct arm32_bus_dma_cookie *cookie;
+	int cookieflags;
+	void *cookiestore;
+	size_t cookiesize;
+	int error;
+
+	cookieflags = 0;
+
+	if (t->_may_bounce != NULL) {
+		error = (*t->_may_bounce)(t, map, flags, &cookieflags);
+		if (error != 0)
+			goto out;
+	}
+
+	if (t->_ranges != NULL)
+		cookieflags |= _BUS_DMA_MIGHT_NEED_BOUNCE;
+
+	if ((cookieflags & _BUS_DMA_MIGHT_NEED_BOUNCE) == 0) {
+		STAT_INCR(creates);
+		return 0;
+	}
+
+	cookiesize = sizeof(struct arm32_bus_dma_cookie) +
+	    (sizeof(bus_dma_segment_t) * map->_dm_segcnt);
+
+	/*
+	 * Allocate our cookie.
+	 */
+	if ((cookiestore = malloc(cookiesize, M_DMAMAP, mallocflags)) == NULL) {
+		error = ENOMEM;
+		goto out;
+	}
+	cookie = (struct arm32_bus_dma_cookie *)cookiestore;
+	cookie->id_flags = cookieflags;
+	map->_dm_cookie = cookie;
+	STAT_INCR(bounced_creates);
+
+	error = _bus_dma_alloc_bouncebuf(t, map, size, flags);
+ out:
+	if (error)
+		_bus_dmamap_destroy(t, map);
+#else
+	STAT_INCR(creates);
+#endif /* _ARM32_NEED_BUS_DMA_BOUNCE */
+
 #ifdef DEBUG_DMA
 	printf("dmamap_create:map=%p\n", map);
 #endif	/* DEBUG_DMA */
@@ -223,16 +356,26 @@ _bus_dmamap_destroy(bus_dma_tag_t t, bus
 #ifdef DEBUG_DMA
 	printf("dmamap_destroy: t=%p map=%p\n", t, map);
 #endif	/* DEBUG_DMA */
+#ifdef _ARM32_NEED_BUS_DMA_BOUNCE
+	struct arm32_bus_dma_cookie *cookie = map->_dm_cookie;
 
 	/*
-	 * Explicit unload.
+	 * Free any bounce pages this map might hold.
 	 */
-	map->dm_maxsegsz = map->_dm_maxmaxsegsz;
-	map->dm_mapsize = 0;
-	map->dm_nsegs = 0;
-	map->_dm_origbuf = NULL;
-	map->_dm_buftype = ARM32_BUFTYPE_INVALID;
-	map->_dm_vmspace = NULL;
+	if (cookie != NULL) {
+		if (cookie->id_flags & _BUS_DMA_IS_BOUNCING)
+			STAT_INCR(bounced_unloads);
+		map->dm_nsegs = 0;
+		if (cookie->id_flags & _BUS_DMA_HAS_BOUNCE)
+			_bus_dma_free_bouncebuf(t, map);
+		STAT_INCR(bounced_destroys);
+		free(cookie, M_DMAMAP);
+	} else
+#endif
+	STAT_INCR(destroys);
+
+	if (map->dm_nsegs > 0)
+		STAT_INCR(unloads);
 
 	free(map, M_DMAMAP);
 }
@@ -245,19 +388,33 @@ int
 _bus_dmamap_load(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
     bus_size_t buflen, struct proc *p, int flags)
 {
-	int error;
 	struct vmspace *vm;
+	int error;
 
 #ifdef DEBUG_DMA
 	printf("dmamap_load: t=%p map=%p buf=%p len=%lx p=%p f=%d\n",
 	    t, map, buf, buflen, p, flags);
 #endif	/* DEBUG_DMA */
 
+	if (map->dm_nsegs > 0) {
+#ifdef _ARM32_NEED_BUS_DMA_BOUNCE
+		struct arm32_bus_dma_cookie *cookie = map->_dm_cookie;
+		if (cookie != NULL) {
+			if (cookie->id_flags & _BUS_DMA_IS_BOUNCING) {
+				STAT_INCR(bounced_unloads);
+				cookie->id_flags &= ~_BUS_DMA_IS_BOUNCING;
+			}
+		} else
+#endif
+		STAT_INCR(unloads);
+	}
+
 	/*
 	 * Make sure that on error condition we return "no valid mappings".
 	 */
 	map->dm_mapsize = 0;
 	map->dm_nsegs = 0;
+	map->_dm_buftype = _BUS_DMA_BUFTYPE_INVALID;
 	KASSERT(map->dm_maxsegsz <= map->_dm_maxmaxsegsz);
 
 	if (buflen > map->_dm_size)
@@ -270,18 +427,23 @@ _bus_dmamap_load(bus_dma_tag_t t, bus_dm
 	}
 
 	/* _bus_dmamap_load_buffer() clears this if we're not... */
-	map->_dm_flags |= ARM32_DMAMAP_COHERENT;
+	map->_dm_flags |= _BUS_DMAMAP_COHERENT;
 
 	error = _bus_dmamap_load_buffer(t, map, buf, buflen, vm, flags);
 	if (error == 0) {
 		map->dm_mapsize = buflen;
-		map->_dm_origbuf = buf;
-		map->_dm_buftype = ARM32_BUFTYPE_LINEAR;
 		map->_dm_vmspace = vm;
+		map->_dm_origbuf = buf;
+		map->_dm_buftype = _BUS_DMA_BUFTYPE_LINEAR;
+		return 0;
 	}
-#ifdef DEBUG_DMA
-	printf("dmamap_load: error=%d\n", error);
-#endif	/* DEBUG_DMA */
+#ifdef _ARM32_NEED_BUS_DMA_BOUNCE
+	struct arm32_bus_dma_cookie * const cookie = map->_dm_cookie;
+	if (cookie != NULL && (cookie->id_flags & _BUS_DMA_MIGHT_NEED_BOUNCE)) {
+		error = _bus_dma_load_bouncebuf(t, map, buf, buflen,
+		    _BUS_DMA_BUFTYPE_LINEAR, flags);
+	}        
+#endif           
 	return (error);
 }
 
@@ -300,11 +462,25 @@ _bus_dmamap_load_mbuf(bus_dma_tag_t t, b
 	    t, map, m0, flags);
 #endif	/* DEBUG_DMA */
 
+	if (map->dm_nsegs > 0) {
+#ifdef _ARM32_NEED_BUS_DMA_BOUNCE
+		struct arm32_bus_dma_cookie *cookie = map->_dm_cookie;
+		if (cookie != NULL) {
+			if (cookie->id_flags & _BUS_DMA_IS_BOUNCING) {
+				STAT_INCR(bounced_unloads);
+				cookie->id_flags &= ~_BUS_DMA_IS_BOUNCING;
+			}
+		} else
+#endif
+		STAT_INCR(unloads);
+	}
+
 	/*
 	 * Make sure that on error condition we return "no valid mappings."
 	 */
 	map->dm_mapsize = 0;
 	map->dm_nsegs = 0;
+	map->_dm_buftype = _BUS_DMA_BUFTYPE_INVALID;
 	KASSERT(map->dm_maxsegsz <= map->_dm_maxmaxsegsz);
 
 #ifdef DIAGNOSTIC
@@ -319,7 +495,7 @@ _bus_dmamap_load_mbuf(bus_dma_tag_t t, b
 	 * Mbuf chains should almost never have coherent (i.e.
 	 * un-cached) mappings, so clear that flag now.
 	 */
-	map->_dm_flags &= ~ARM32_DMAMAP_COHERENT;
+	map->_dm_flags &= ~_BUS_DMAMAP_COHERENT;
 
 	error = 0;
 	for (m = m0; m != NULL && error == 0; m = m->m_next) {
@@ -397,12 +573,17 @@ _bus_dmamap_load_mbuf(bus_dma_tag_t t, b
 	if (error == 0) {
 		map->dm_mapsize = m0->m_pkthdr.len;
 		map->_dm_origbuf = m0;
-		map->_dm_buftype = ARM32_BUFTYPE_MBUF;
+		map->_dm_buftype = _BUS_DMA_BUFTYPE_MBUF;
 		map->_dm_vmspace = vmspace_kernel();	/* always kernel */
+		return 0;
 	}
-#ifdef DEBUG_DMA
-	printf("dmamap_load_mbuf: error=%d\n", error);
-#endif	/* DEBUG_DMA */
+#ifdef _ARM32_NEED_BUS_DMA_BOUNCE
+	struct arm32_bus_dma_cookie * const cookie = map->_dm_cookie;
+	if (cookie != NULL && (cookie->id_flags & _BUS_DMA_MIGHT_NEED_BOUNCE)) {
+		error = _bus_dma_load_bouncebuf(t, map, m0, m0->m_pkthdr.len,
+		    _BUS_DMA_BUFTYPE_MBUF, flags);
+	}        
+#endif           
 	return (error);
 }
 
@@ -429,7 +610,7 @@ _bus_dmamap_load_uio(bus_dma_tag_t t, bu
 	iov = uio->uio_iov;
 
 	/* _bus_dmamap_load_buffer() clears this if we're not... */
-	map->_dm_flags |= ARM32_DMAMAP_COHERENT;
+	map->_dm_flags |= _BUS_DMAMAP_COHERENT;
 
 	error = 0;
 	for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0; i++) {
@@ -448,7 +629,7 @@ _bus_dmamap_load_uio(bus_dma_tag_t t, bu
 	if (error == 0) {
 		map->dm_mapsize = uio->uio_resid;
 		map->_dm_origbuf = uio;
-		map->_dm_buftype = ARM32_BUFTYPE_UIO;
+		map->_dm_buftype = _BUS_DMA_BUFTYPE_UIO;
 		map->_dm_vmspace = uio->uio_vmspace;
 	}
 	return (error);
@@ -485,7 +666,7 @@ _bus_dmamap_unload(bus_dma_tag_t t, bus_
 	map->dm_mapsize = 0;
 	map->dm_nsegs = 0;
 	map->_dm_origbuf = NULL;
-	map->_dm_buftype = ARM32_BUFTYPE_INVALID;
+	map->_dm_buftype = _BUS_DMA_BUFTYPE_INVALID;
 	map->_dm_vmspace = NULL;
 }
 
@@ -540,8 +721,17 @@ static inline void
 _bus_dmamap_sync_linear(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset,
     bus_size_t len, int ops)
 {
+#ifdef _ARM32_NEED_BUS_DMA_BOUNCE
+	struct arm32_bus_dma_cookie * const cookie = map->_dm_cookie;
+	bool bouncing = (cookie != NULL && (cookie->id_flags & _BUS_DMA_IS_BOUNCING));
+#endif
 	bus_dma_segment_t *ds = map->dm_segs;
 	vaddr_t va = (vaddr_t) map->_dm_origbuf;
+#ifdef _ARM32_NEED_BUS_DMA_BOUNCE
+	if (bouncing) {
+		va = (vaddr_t) cookie->id_bouncebuf;
+	}
+#endif
 
 	while (len > 0) {
 		while (offset >= ds->ds_len) {
@@ -668,6 +858,7 @@ void
 _bus_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset,
     bus_size_t len, int ops)
 {
+	bool bouncing = false;
 
 #ifdef DEBUG_DMA
 	printf("dmamap_sync: t=%p map=%p offset=%lx len=%lx ops=%x\n",
@@ -704,18 +895,63 @@ _bus_dmamap_sync(bus_dma_tag_t t, bus_dm
 	 *
 	 *	POSTWRITE -- Nothing.
 	 */
+#ifdef _ARM32_NEED_BUS_DMA_BOUNCE
+	struct arm32_bus_dma_cookie * const cookie = map->_dm_cookie;
+	bouncing = (cookie != NULL && (cookie->id_flags & _BUS_DMA_IS_BOUNCING));
+#endif
 
-	ops &= (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
-	if (ops == 0)
+	const int pre_ops = ops & (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
+	if (!bouncing && pre_ops == 0)
 		return;
 
+#ifdef _ARM32_NEED_BUS_DMA_BOUNCE
+	if (bouncing && (ops & BUS_DMASYNC_PREWRITE)) {
+		STAT_INCR(write_bounces);
+		char * const dataptr = (char *)cookie->id_bouncebuf + offset;
+		/*
+		 * Copy the caller's buffer to the bounce buffer.
+		 */
+		switch (map->_dm_buftype) {
+		case _BUS_DMA_BUFTYPE_LINEAR:
+			memcpy(dataptr, cookie->id_origlinearbuf + offset, len);
+			break;
+		case _BUS_DMA_BUFTYPE_MBUF:
+			m_copydata(cookie->id_origmbuf, offset, len, dataptr);
+			break;
+		case _BUS_DMA_BUFTYPE_UIO:
+			_bus_dma_uiomove(dataptr, cookie->id_origuio, len, UIO_WRITE);
+			break;
+#ifdef DIAGNOSTIC
+		case _BUS_DMA_BUFTYPE_RAW:
+			panic("_bus_dmamap_sync(pre): _BUS_DMA_BUFTYPE_RAW");
+			break;
+
+		case _BUS_DMA_BUFTYPE_INVALID:
+			panic("_bus_dmamap_sync(pre): _BUS_DMA_BUFTYPE_INVALID");
+			break;
+
+		default:
+			panic("_bus_dmamap_sync(pre): map %p: unknown buffer type %d\n",
+			    map, map->_dm_buftype);
+			break;
+#endif /* DIAGNOSTIC */
+		}
+	}
+#endif /* _ARM32_NEED_BUS_DMA_BOUNCE */
+
 	/* Skip cache frobbing if mapping was COHERENT. */
-	if (map->_dm_flags & ARM32_DMAMAP_COHERENT) {
+	if (!bouncing && (map->_dm_flags & _BUS_DMAMAP_COHERENT)) {
 		/* Drain the write buffer. */
 		cpu_drain_writebuf();
 		return;
 	}
 
+#ifdef _ARM32_NEED_BUS_DMA_BOUNCE
+	if (bouncing && ((map->_dm_flags & _BUS_DMAMAP_COHERENT) || pre_ops == 0)) {
+		goto bounce_it;
+	}
+#endif /* _ARM32_NEED_BUS_DMA_BOUNCE */
+
 	/*
 	 * If the mapping belongs to a non-kernel vmspace, and the
 	 * vmspace has not been active since the last time a full
@@ -725,34 +961,82 @@ _bus_dmamap_sync(bus_dma_tag_t t, bus_dm
 	    vm_map_pmap(&map->_dm_vmspace->vm_map)->pm_cstate.cs_cache_d == 0))
 		return;
 
-	switch (map->_dm_buftype) {
-	case ARM32_BUFTYPE_LINEAR:
+	int buftype = map->_dm_buftype;
+#ifdef _ARM32_NEED_BUS_DMA_BOUNCE
+	if (bouncing) {
+		buftype = _BUS_DMA_BUFTYPE_LINEAR;
+	}
+#endif
+
+	switch (buftype) {
+	case _BUS_DMA_BUFTYPE_LINEAR:
 		_bus_dmamap_sync_linear(t, map, offset, len, ops);
 		break;
 
-	case ARM32_BUFTYPE_MBUF:
+	case _BUS_DMA_BUFTYPE_MBUF:
 		_bus_dmamap_sync_mbuf(t, map, offset, len, ops);
 		break;
 
-	case ARM32_BUFTYPE_UIO:
+	case _BUS_DMA_BUFTYPE_UIO:
 		_bus_dmamap_sync_uio(t, map, offset, len, ops);
 		break;
 
-	case ARM32_BUFTYPE_RAW:
-		panic("_bus_dmamap_sync: ARM32_BUFTYPE_RAW");
+	case _BUS_DMA_BUFTYPE_RAW:
+		panic("_bus_dmamap_sync: _BUS_DMA_BUFTYPE_RAW");
 		break;
 
-	case ARM32_BUFTYPE_INVALID:
-		panic("_bus_dmamap_sync: ARM32_BUFTYPE_INVALID");
+	case _BUS_DMA_BUFTYPE_INVALID:
+		panic("_bus_dmamap_sync: _BUS_DMA_BUFTYPE_INVALID");
 		break;
 
 	default:
-		printf("unknown buffer type %d\n", map->_dm_buftype);
-		panic("_bus_dmamap_sync");
+		panic("_bus_dmamap_sync: map %p: unknown buffer type %d\n",
+		    map, map->_dm_buftype);
 	}
 
 	/* Drain the write buffer. */
 	cpu_drain_writebuf();
+
+#ifdef _ARM32_NEED_BUS_DMA_BOUNCE
+  bounce_it:
+	if ((ops & BUS_DMASYNC_POSTREAD) == 0
+	    || cookie == NULL
+	    || (cookie->id_flags & _BUS_DMA_IS_BOUNCING) == 0)
+		return;
+
+	char * const dataptr = (char *)cookie->id_bouncebuf + offset;
+	STAT_INCR(read_bounces);
+	/*
+	 * Copy the bounce buffer to the caller's buffer.
+	 */
+	switch (map->_dm_buftype) {
+	case _BUS_DMA_BUFTYPE_LINEAR:
+		memcpy(cookie->id_origlinearbuf + offset, dataptr, len);
+		break;
+
+	case _BUS_DMA_BUFTYPE_MBUF:
+		m_copyback(cookie->id_origmbuf, offset, len, dataptr);
+		break;
+
+	case _BUS_DMA_BUFTYPE_UIO:
+		_bus_dma_uiomove(dataptr, cookie->id_origuio, len, UIO_READ);
+		break;
+#ifdef DIAGNOSTIC
+	case _BUS_DMA_BUFTYPE_RAW:
+		panic("_bus_dmamap_sync(post): _BUS_DMA_BUFTYPE_RAW");
+		break;
+
+	case _BUS_DMA_BUFTYPE_INVALID:
+		panic("_bus_dmamap_sync(post): _BUS_DMA_BUFTYPE_INVALID");
+		break;
+
+	default:
+		panic("_bus_dmamap_sync(post): map %p: unknown buffer type %d\n",
+		    map, map->_dm_buftype);
+		break;
+#endif
+	}
+#endif /* _ARM32_NEED_BUS_DMA_BOUNCE */
 }
 
 /*
@@ -1009,7 +1293,7 @@ _bus_dmamap_load_buffer(bus_dma_tag_t t,
 #endif
 				curaddr = (*pde & s_frame) | (vaddr & s_offset);
 				if (*pde & L1_S_CACHE_MASK) {
-					map->_dm_flags &= ~ARM32_DMAMAP_COHERENT;
+					map->_dm_flags &= ~_BUS_DMAMAP_COHERENT;
 				}
 			} else {
 				pte = *ptep;
@@ -1020,20 +1304,20 @@ _bus_dmamap_load_buffer(bus_dma_tag_t t,
 					    (vaddr & L2_L_OFFSET);
 					if (pte & L2_L_CACHE_MASK) {
 						map->_dm_flags &=
-						    ~ARM32_DMAMAP_COHERENT;
+						    ~_BUS_DMAMAP_COHERENT;
 					}
 				} else {
 					curaddr = (pte & L2_S_FRAME) |
 					    (vaddr & L2_S_OFFSET);
 					if (pte & L2_S_CACHE_MASK) {
 						map->_dm_flags &=
-						    ~ARM32_DMAMAP_COHERENT;
+						    ~_BUS_DMAMAP_COHERENT;
 					}
 				}
 			}
 		} else {
 			(void) pmap_extract(pmap, vaddr, &curaddr);
-			map->_dm_flags &= ~ARM32_DMAMAP_COHERENT;
+			map->_dm_flags &= ~_BUS_DMAMAP_COHERENT;
 		}
 
 		/*
@@ -1163,3 +1447,189 @@ arm32_dma_range_intersect(struct arm32_d
 	/* No intersection found. */
 	return (0);
 }
+
+#ifdef _ARM32_NEED_BUS_DMA_BOUNCE
+static int
+_bus_dma_alloc_bouncebuf(bus_dma_tag_t t, bus_dmamap_t map,
+    bus_size_t size, int flags)
+{
+	struct arm32_bus_dma_cookie *cookie = map->_dm_cookie;
+	int error = 0;
+
+#ifdef DIAGNOSTIC
+	if (cookie == NULL)
+		panic("_bus_dma_alloc_bouncebuf: no cookie");
+#endif
+
+	cookie->id_bouncebuflen = round_page(size);
+	error = _bus_dmamem_alloc(t, cookie->id_bouncebuflen,
+	    PAGE_SIZE, map->_dm_boundary, cookie->id_bouncesegs,
+	    map->_dm_segcnt, &cookie->id_nbouncesegs, flags);
+	if (error)
+		goto out;
+	error = _bus_dmamem_map(t, cookie->id_bouncesegs,
+	    cookie->id_nbouncesegs, cookie->id_bouncebuflen,
+	    (void **)&cookie->id_bouncebuf, flags);
+
+ out:
+	if (error) {
+		_bus_dmamem_free(t, cookie->id_bouncesegs,
+		    cookie->id_nbouncesegs);
+		cookie->id_bouncebuflen = 0;
+		cookie->id_nbouncesegs = 0;
+	} else {
+		cookie->id_flags |= _BUS_DMA_HAS_BOUNCE;
+	}
+
+	return (error);
+}
+
+static void
+_bus_dma_free_bouncebuf(bus_dma_tag_t t, bus_dmamap_t map)
+{
+	struct arm32_bus_dma_cookie *cookie = map->_dm_cookie;
+
+#ifdef DIAGNOSTIC
+	if (cookie == NULL)
+		panic("_bus_dma_alloc_bouncebuf: no cookie");
+#endif
+
+	_bus_dmamem_unmap(t, cookie->id_bouncebuf, cookie->id_bouncebuflen);
+	_bus_dmamem_free(t, cookie->id_bouncesegs,
+	    cookie->id_nbouncesegs);
+	cookie->id_bouncebuflen = 0;
+	cookie->id_nbouncesegs = 0;
+	cookie->id_flags &= ~_BUS_DMA_HAS_BOUNCE;
+}
+
+/*
+ * This function does the same as uiomove, but takes an explicit
+ * direction, and does not update the uio structure.
+ */
+static int
+_bus_dma_uiomove(void *buf, struct uio *uio, size_t n, int direction)
+{
+	struct iovec *iov;
+	int error;
+	struct vmspace *vm;
+	char *cp;
+	size_t resid, cnt;
+	int i;
+
+	iov = uio->uio_iov;
+	vm = uio->uio_vmspace;
+	cp = buf;
+	resid = n;
+
+	for (i = 0; i < uio->uio_iovcnt && resid > 0; i++) {
+		iov = &uio->uio_iov[i];
+		if (iov->iov_len == 0)
+			continue;
+		cnt = MIN(resid, iov->iov_len);
+
+		if (!VMSPACE_IS_KERNEL_P(vm) &&
+		    (curlwp->l_cpu->ci_schedstate.spc_flags & SPCF_SHOULDYIELD)
+		    != 0) {
+			preempt();
+		}
+		if (direction == UIO_READ) {
+			error = copyout_vmspace(vm, cp, iov->iov_base, cnt);
+		} else {
+			error = copyin_vmspace(vm, iov->iov_base, cp, cnt);
+		}
+		if (error)
+			return (error);
+		cp += cnt;
+		resid -= cnt;
+	}
+	return (0);
+}
+#endif /* _ARM32_NEED_BUS_DMA_BOUNCE */
+
+int
+_bus_dmatag_subregion(bus_dma_tag_t tag, bus_addr_t min_addr,
+    bus_addr_t max_addr, bus_dma_tag_t *newtag, int flags)
+{
+
+#ifdef _ARM32_NEED_BUS_DMA_BOUNCE
+	struct arm32_dma_range *dr;
+	bool subset = false;
+	size_t nranges = 0;
+	size_t i;
+	for (i = 0, dr = tag->_ranges; i < tag->_nranges; i++, dr++) {
+		if (dr->dr_sysbase <= min_addr 
+		    && max_addr <= dr->dr_sysbase + dr->dr_len - 1) {
+			subset = true;
+		}
+		if (min_addr <= dr->dr_sysbase + dr->dr_len
+		    && max_addr >= dr->dr_sysbase) {
+			nranges++;
+		}
+	}
+	if (subset) {
+		*newtag = tag;
+		/* if the tag must be freed, add a reference */
+		if (tag->_tag_needs_free)
+			(tag->_tag_needs_free)++;
+		return 0;
+	}
+	if (nranges == 0) {
+		nranges = 1;
+	}
+
+	size_t mallocsize = sizeof(*tag) + nranges * sizeof(*dr);
+	if ((*newtag = malloc(mallocsize, M_DMAMAP,
+	    (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK)) == NULL)
+		return ENOMEM;
+
+	dr = (void *)(*newtag + 1);
+	**newtag = *tag;
+	(*newtag)->_tag_needs_free = 1;
+	(*newtag)->_ranges = dr;
+	(*newtag)->_nranges = nranges;
+
+	if (tag->_ranges == NULL) {
+		dr->dr_sysbase = min_addr;
+		dr->dr_busbase = min_addr;
+		dr->dr_len = max_addr + 1 - min_addr;
+	} else {
+		for (i = 0; i < nranges; i++) {
+			if (min_addr > dr->dr_sysbase + dr->dr_len
+			    || max_addr < dr->dr_sysbase)
+				continue;
+			dr[0] = tag->_ranges[i];
+			if (dr->dr_sysbase < min_addr) {
+				psize_t diff = min_addr - dr->dr_sysbase;
+				dr->dr_busbase += diff;
+				dr->dr_len -= diff;
+				dr->dr_sysbase += diff;
+			}
+			if (max_addr != 0xffffffff
+			    && max_addr + 1 < dr->dr_sysbase + dr->dr_len) {
+				dr->dr_len = max_addr + 1 - dr->dr_sysbase;
+			}
+			dr++;
+		}
+	}
+
+	return 0;
+#else
+	return EOPNOTSUPP;
+#endif /* _ARM32_NEED_BUS_DMA_BOUNCE */
+}
+
+void
+_bus_dmatag_destroy(bus_dma_tag_t tag)
+{
+#ifdef _ARM32_NEED_BUS_DMA_BOUNCE
+	switch (tag->_tag_needs_free) {
+	case 0:
+		break;				/* not allocated with malloc */
+	case 1:
+		free(tag, M_DMAMAP);		/* last reference to tag */
+		break;
+	default:
+		(tag->_tag_needs_free)--;	/* one less reference */
+	}
+#endif
+}

Index: src/sys/arch/arm/at91/at91_bus_dma.c
diff -u src/sys/arch/arm/at91/at91_bus_dma.c:1.4 src/sys/arch/arm/at91/at91_bus_dma.c:1.5
--- src/sys/arch/arm/at91/at91_bus_dma.c:1.4	Fri Jul  1 19:31:16 2011
+++ src/sys/arch/arm/at91/at91_bus_dma.c	Tue Sep 18 05:47:27 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: at91_bus_dma.c,v 1.4 2011/07/01 19:31:16 dyoung Exp $ */
+/*	$NetBSD: at91_bus_dma.c,v 1.5 2012/09/18 05:47:27 matt Exp $ */
 
 /*
  * Copyright (c) 2004 Jesse Off
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: at91_bus_dma.c,v 1.4 2011/07/01 19:31:16 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: at91_bus_dma.c,v 1.5 2012/09/18 05:47:27 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -47,24 +47,7 @@ __KERNEL_RCSID(0, "$NetBSD: at91_bus_dma
 #include <arm/at91/at91var.h>
 
 struct arm32_bus_dma_tag at91_bd_tag = {
-	NULL,			/* _ranges: set by platform specific routine */
-	0,			/* _nranges */
-
-	NULL,			/* _cookie */
-
-	_bus_dmamap_create,
-	_bus_dmamap_destroy,
-	_bus_dmamap_load,
-	_bus_dmamap_load_mbuf,
-	_bus_dmamap_load_uio,
-	_bus_dmamap_load_raw,
-	_bus_dmamap_unload,
-	_bus_dmamap_sync,
-	NULL,			/* sync_post */
-
-	_bus_dmamem_alloc,
-	_bus_dmamem_free,
-	_bus_dmamem_map,
-	_bus_dmamem_unmap,
-	_bus_dmamem_mmap,
+	_BUS_DMAMAP_FUNCS,
+	_BUS_DMAMEM_FUNCS,
+	_BUS_DMAMAP_FUNCS,
 };

Index: src/sys/arch/arm/broadcom/bcm2835_dma.c
diff -u src/sys/arch/arm/broadcom/bcm2835_dma.c:1.1 src/sys/arch/arm/broadcom/bcm2835_dma.c:1.2
--- src/sys/arch/arm/broadcom/bcm2835_dma.c:1.1	Thu Jul 26 06:21:57 2012
+++ src/sys/arch/arm/broadcom/bcm2835_dma.c	Tue Sep 18 05:47:27 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: bcm2835_dma.c,v 1.1 2012/07/26 06:21:57 skrll Exp $	*/
+/*	$NetBSD: bcm2835_dma.c,v 1.2 2012/09/18 05:47:27 matt Exp $	*/
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bcm2835_dma.c,v 1.1 2012/07/26 06:21:57 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bcm2835_dma.c,v 1.2 2012/09/18 05:47:27 matt Exp $");
 
 #define _ARM32_BUS_DMA_PRIVATE
 
@@ -38,24 +38,7 @@ __KERNEL_RCSID(0, "$NetBSD: bcm2835_dma.
 #include <sys/bus.h>
 
 struct arm32_bus_dma_tag bcm2835_bus_dma_tag = {
-	NULL,			/* _ranges: set by platform specific routine */
-	0,			/* _nranges */
-
-	NULL,			/* _cookie */
-
-	_bus_dmamap_create,
-	_bus_dmamap_destroy,
-	_bus_dmamap_load,
-	_bus_dmamap_load_mbuf,
-	_bus_dmamap_load_uio,
-	_bus_dmamap_load_raw,
-	_bus_dmamap_unload,
-	_bus_dmamap_sync,
-	NULL,			/* sync_post */
-
-	_bus_dmamem_alloc,
-	_bus_dmamem_free,
-	_bus_dmamem_map,
-	_bus_dmamem_unmap,
-	_bus_dmamem_mmap,
+	_BUS_DMAMAP_FUNCS,
+	_BUS_DMAMEM_FUNCS,
+	_BUS_DMATAG_FUNCS,
 };

Index: src/sys/arch/arm/broadcom/bcm53xx_board.c
diff -u src/sys/arch/arm/broadcom/bcm53xx_board.c:1.2 src/sys/arch/arm/broadcom/bcm53xx_board.c:1.3
--- src/sys/arch/arm/broadcom/bcm53xx_board.c:1.2	Fri Sep  7 11:52:30 2012
+++ src/sys/arch/arm/broadcom/bcm53xx_board.c	Tue Sep 18 05:47:27 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: bcm53xx_board.c,v 1.2 2012/09/07 11:52:30 matt Exp $	*/
+/*	$NetBSD: bcm53xx_board.c,v 1.3 2012/09/18 05:47:27 matt Exp $	*/
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -34,7 +34,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(1, "$NetBSD: bcm53xx_board.c,v 1.2 2012/09/07 11:52:30 matt Exp $");
+__KERNEL_RCSID(1, "$NetBSD: bcm53xx_board.c,v 1.3 2012/09/18 05:47:27 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -64,20 +64,9 @@ static struct cpu_softc cpu_softc;
 static struct bcm53xx_clock_info clk_info;
 
 struct arm32_bus_dma_tag bcm53xx_dma_tag = {
-	._dmamap_create = _bus_dmamap_create,
-	._dmamap_destroy = _bus_dmamap_destroy,
-	._dmamap_load = _bus_dmamap_load,
-	._dmamap_load_mbuf = _bus_dmamap_load_mbuf,
-	._dmamap_load_uio = _bus_dmamap_load_uio,
-	._dmamap_load_raw = _bus_dmamap_load_raw,
-	._dmamap_unload = _bus_dmamap_unload,
-	._dmamap_sync_pre = _bus_dmamap_sync,
-	._dmamap_sync_post = NULL,
-	._dmamem_alloc = _bus_dmamem_alloc,
-	._dmamem_free = _bus_dmamem_free,
-	._dmamem_map = _bus_dmamem_map,
-	._dmamem_unmap = _bus_dmamem_unmap,
-	._dmamem_mmap = _bus_dmamem_mmap
+	_BUS_DMAMAP_FUNCS,
+	_BUS_DMAMEM_FUNCS,
+	_BUS_DMATAG_FUNCS,
 };
 
 #ifdef BCM53XX_CONSOLE_EARLY

Index: src/sys/arch/arm/ep93xx/ep93xx_busdma.c
diff -u src/sys/arch/arm/ep93xx/ep93xx_busdma.c:1.4 src/sys/arch/arm/ep93xx/ep93xx_busdma.c:1.5
--- src/sys/arch/arm/ep93xx/ep93xx_busdma.c:1.4	Fri Jul  1 19:31:17 2011
+++ src/sys/arch/arm/ep93xx/ep93xx_busdma.c	Tue Sep 18 05:47:27 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: ep93xx_busdma.c,v 1.4 2011/07/01 19:31:17 dyoung Exp $ */
+/*	$NetBSD: ep93xx_busdma.c,v 1.5 2012/09/18 05:47:27 matt Exp $ */
 
 /*
  * Copyright (c) 2004 Jesse Off
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ep93xx_busdma.c,v 1.4 2011/07/01 19:31:17 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ep93xx_busdma.c,v 1.5 2012/09/18 05:47:27 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -47,24 +47,7 @@ __KERNEL_RCSID(0, "$NetBSD: ep93xx_busdm
 #include <arm/ep93xx/ep93xxvar.h>
 
 struct arm32_bus_dma_tag ep93xx_bus_dma = {
-	NULL,			/* _ranges: set by platform specific routine */
-	0,			/* _nranges */
-
-	NULL,			/* _cookie */
-
-	_bus_dmamap_create,
-	_bus_dmamap_destroy,
-	_bus_dmamap_load,
-	_bus_dmamap_load_mbuf,
-	_bus_dmamap_load_uio,
-	_bus_dmamap_load_raw,
-	_bus_dmamap_unload,
-	_bus_dmamap_sync,
-	NULL,			/* sync_post */
-
-	_bus_dmamem_alloc,
-	_bus_dmamem_free,
-	_bus_dmamem_map,
-	_bus_dmamem_unmap,
-	_bus_dmamem_mmap,
+	_BUS_DMAMAP_FUNCS,
+	_BUS_DMAMEM_FUNCS,
+	_BUS_DMATAG_FUNCS,
 };

Index: src/sys/arch/arm/footbridge/footbridge_pci.c
diff -u src/sys/arch/arm/footbridge/footbridge_pci.c:1.22 src/sys/arch/arm/footbridge/footbridge_pci.c:1.23
--- src/sys/arch/arm/footbridge/footbridge_pci.c:1.22	Sun Feb 12 16:34:07 2012
+++ src/sys/arch/arm/footbridge/footbridge_pci.c	Tue Sep 18 05:47:27 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: footbridge_pci.c,v 1.22 2012/02/12 16:34:07 matt Exp $	*/
+/*	$NetBSD: footbridge_pci.c,v 1.23 2012/09/18 05:47:27 matt Exp $	*/
 
 /*
  * Copyright (c) 1997,1998 Mark Brinicombe.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: footbridge_pci.c,v 1.22 2012/02/12 16:34:07 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: footbridge_pci.c,v 1.23 2012/09/18 05:47:27 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -102,23 +102,11 @@ struct arm32_dma_range footbridge_dma_ra
  * of these functions.
  */
 struct arm32_bus_dma_tag footbridge_pci_bus_dma_tag = {
-	footbridge_dma_ranges,
-	1,
-	NULL,
-	_bus_dmamap_create, 
-	_bus_dmamap_destroy,
-	_bus_dmamap_load,
-	_bus_dmamap_load_mbuf,
-	_bus_dmamap_load_uio,
-	_bus_dmamap_load_raw,
-	_bus_dmamap_unload,
-	_bus_dmamap_sync,	/* pre */
-	NULL,			/* post */
-	_bus_dmamem_alloc,
-	_bus_dmamem_free,
-	_bus_dmamem_map,
-	_bus_dmamem_unmap,
-	_bus_dmamem_mmap,
+	._ranges = footbridge_dma_ranges,
+	._nranges = 1,
+	_BUS_DMAMAP_FUNCS,
+	_BUS_DMAMEM_FUNCS,
+	_BUS_DMATAG_FUNCS,
 };
 
 /*

Index: src/sys/arch/arm/gemini/gemini_dma.c
diff -u src/sys/arch/arm/gemini/gemini_dma.c:1.2 src/sys/arch/arm/gemini/gemini_dma.c:1.3
--- src/sys/arch/arm/gemini/gemini_dma.c:1.2	Fri Jul  1 19:32:28 2011
+++ src/sys/arch/arm/gemini/gemini_dma.c	Tue Sep 18 05:47:27 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: gemini_dma.c,v 1.2 2011/07/01 19:32:28 dyoung Exp $	*/
+/*	$NetBSD: gemini_dma.c,v 1.3 2012/09/18 05:47:27 matt Exp $	*/
 
 /* adapted from:
  *	NetBSD: pxa2x0_dma.c,v 1.4 2005/12/11 12:16:51 christos Exp
@@ -43,7 +43,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: gemini_dma.c,v 1.2 2011/07/01 19:32:28 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gemini_dma.c,v 1.3 2012/09/18 05:47:27 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -57,22 +57,8 @@ __KERNEL_RCSID(0, "$NetBSD: gemini_dma.c
 #include <sys/bus.h>
 
 struct arm32_bus_dma_tag gemini_bus_dma_tag = {
-	0,
-	0,
-	NULL,			/* _cookie */
-	_bus_dmamap_create,
-	_bus_dmamap_destroy,
-	_bus_dmamap_load,
-	_bus_dmamap_load_mbuf,
-	_bus_dmamap_load_uio,
-	_bus_dmamap_load_raw,
-	_bus_dmamap_unload,
-	_bus_dmamap_sync,
-	NULL,			/* sync_post */
-	_bus_dmamem_alloc,
-	_bus_dmamem_free,
-	_bus_dmamem_map,
-	_bus_dmamem_unmap,
-	_bus_dmamem_mmap
+	_BUS_DMAMAP_FUNCS,
+	_BUS_DMAMEM_FUNCS,
+	_BUS_DMATAG_FUNCS,
 };
 

Index: src/sys/arch/arm/imx/imx_dma.c
diff -u src/sys/arch/arm/imx/imx_dma.c:1.2 src/sys/arch/arm/imx/imx_dma.c:1.3
--- src/sys/arch/arm/imx/imx_dma.c:1.2	Fri Jul  1 20:27:50 2011
+++ src/sys/arch/arm/imx/imx_dma.c	Tue Sep 18 05:47:27 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: imx_dma.c,v 1.2 2011/07/01 20:27:50 dyoung Exp $ */
+/*	$NetBSD: imx_dma.c,v 1.3 2012/09/18 05:47:27 matt Exp $ */
 
 /*
  * Copyright (c) 2009  Genetec Corporation.  All rights reserved.
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: imx_dma.c,v 1.2 2011/07/01 20:27:50 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: imx_dma.c,v 1.3 2012/09/18 05:47:27 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -46,22 +46,8 @@ __KERNEL_RCSID(0, "$NetBSD: imx_dma.c,v 
 #include <sys/bus.h>
 
 struct arm32_bus_dma_tag imx_bus_dma_tag = {
-	0,
-	0,
-	NULL,			/* _cookie */
-	_bus_dmamap_create,
-	_bus_dmamap_destroy,
-	_bus_dmamap_load,
-	_bus_dmamap_load_mbuf,
-	_bus_dmamap_load_uio,
-	_bus_dmamap_load_raw,
-	_bus_dmamap_unload,
-	_bus_dmamap_sync,
-	NULL,			/* sync_post */
-	_bus_dmamem_alloc,
-	_bus_dmamem_free,
-	_bus_dmamem_map,
-	_bus_dmamem_unmap,
-	_bus_dmamem_mmap
+	_BUS_DMAMAP_FUNCS,
+	_BUS_DMAMEM_FUNCS,
+	_BUS_DMATAG_FUNCS,
 };
 

Index: src/sys/arch/arm/include/bus_defs.h
diff -u src/sys/arch/arm/include/bus_defs.h:1.1 src/sys/arch/arm/include/bus_defs.h:1.2
--- src/sys/arch/arm/include/bus_defs.h:1.1	Fri Jul  1 17:09:58 2011
+++ src/sys/arch/arm/include/bus_defs.h	Tue Sep 18 05:47:27 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: bus_defs.h,v 1.1 2011/07/01 17:09:58 dyoung Exp $	*/
+/*	$NetBSD: bus_defs.h,v 1.2 2012/09/18 05:47:27 matt Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 2001 The NetBSD Foundation, Inc.
@@ -299,7 +299,7 @@ struct bus_space {
 /*
  * Private flags stored in the DMA map.
  */
-#define	ARM32_DMAMAP_COHERENT	0x10000	/* no cache flush necessary on sync */
+#define	_BUS_DMAMAP_COHERENT	0x10000	/* no cache flush necessary on sync */
 
 /* Forwards needed by prototypes below. */
 struct mbuf;
@@ -398,6 +398,19 @@ struct arm32_bus_dma_tag {
 	void	(*_dmamem_unmap)(bus_dma_tag_t, void *, size_t);
 	paddr_t	(*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *,
 		    int, off_t, int, int);
+
+	/*
+	 * DMA tag utility functions
+	 */
+	int	(*_dmatag_subregion)(bus_dma_tag_t, bus_addr_t, bus_addr_t,
+		     bus_dma_tag_t *, int);
+	void	(*_dmatag_destroy)(bus_dma_tag_t);
+
+	/*
+	 * State for bounce buffers
+	 */
+	int	_tag_needs_free;
+	int	(*_may_bounce)(bus_dma_tag_t, bus_dmamap_t, int, int *);
 };
 
 /*
@@ -430,15 +443,51 @@ struct arm32_bus_dmamap {
 	bus_dma_segment_t dm_segs[1];	/* segments; variable length */
 };
 
+/* _dm_buftype */
+#define	_BUS_DMA_BUFTYPE_INVALID	0
+#define	_BUS_DMA_BUFTYPE_LINEAR		1
+#define	_BUS_DMA_BUFTYPE_MBUF		2
+#define	_BUS_DMA_BUFTYPE_UIO		3
+#define	_BUS_DMA_BUFTYPE_RAW		4
+
 #ifdef _ARM32_BUS_DMA_PRIVATE
+#define	_BUS_AVAIL_END	physical_end
+/*
+ * Cookie used for bounce buffers. A pointer to one of these it stashed in
+ * the DMA map.
+ */
+struct arm32_bus_dma_cookie {
+	int	id_flags;		/* flags; see below */
 
-/* _dm_buftype */
-#define	ARM32_BUFTYPE_INVALID		0
-#define	ARM32_BUFTYPE_LINEAR		1
-#define	ARM32_BUFTYPE_MBUF		2
-#define	ARM32_BUFTYPE_UIO		3
-#define	ARM32_BUFTYPE_RAW		4
+	/*
+	 * Information about the original buffer used during
+	 * DMA map syncs.  Note that origibuflen is only used
+	 * for ID_BUFTYPE_LINEAR.
+	 */
+	union {
+		void	*un_origbuf;		/* pointer to orig buffer if
+						   bouncing */
+		char	*un_linearbuf;
+		struct mbuf	*un_mbuf;
+		struct uio	*un_uio;
+	} id_origbuf_un;
+#define	id_origbuf		id_origbuf_un.un_origbuf
+#define	id_origlinearbuf	id_origbuf_un.un_linearbuf
+#define	id_origmbuf		id_origbuf_un.un_mbuf
+#define	id_origuio		id_origbuf_un.un_uio
+	bus_size_t id_origbuflen;	/* ...and size */
+
+	void	*id_bouncebuf;		/* pointer to the bounce buffer */
+	bus_size_t id_bouncebuflen;	/* ...and size */
+	int	id_nbouncesegs;		/* number of valid bounce segs */
+	bus_dma_segment_t id_bouncesegs[0]; /* array of bounce buffer
+					       physical memory segments */
+};
 
+/* id_flags */
+#define	_BUS_DMA_IS_BOUNCING		0x04	/* is bouncing current xfer */
+#define	_BUS_DMA_HAS_BOUNCE		0x02	/* has bounce buffers */
 #endif /* _ARM32_BUS_DMA_PRIVATE */
+#define	_BUS_DMA_MIGHT_NEED_BOUNCE	0x01	/* may need bounce buffers */
 
 #endif /* _ARM32_BUS_DEFS_H_ */

Index: src/sys/arch/arm/include/bus_funcs.h
diff -u src/sys/arch/arm/include/bus_funcs.h:1.2 src/sys/arch/arm/include/bus_funcs.h:1.3
--- src/sys/arch/arm/include/bus_funcs.h:1.2	Sun Jul 15 20:44:20 2012
+++ src/sys/arch/arm/include/bus_funcs.h	Tue Sep 18 05:47:27 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: bus_funcs.h,v 1.2 2012/07/15 20:44:20 matt Exp $	*/
+/*	$NetBSD: bus_funcs.h,v 1.3 2012/09/18 05:47:27 matt Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 2001 The NetBSD Foundation, Inc.
@@ -606,11 +606,15 @@ do {									\
 #define	bus_dmamem_mmap(t, sg, n, o, p, f)			\
 	(*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f))
 
-#define bus_dmatag_subregion(t, mna, mxa, nt, f) EOPNOTSUPP
-#define bus_dmatag_destroy(t)
+#define	bus_dmatag_subregion(t, mna, mxa, nt, f)		\
+	(*(t)->_dmatag_subregion)((t), (mna), (mxa), (nt), (f))
+#define	bus_dmatag_destroy(t)					\
+	(*(t)->_dmatag_destroy)(t)
 
 #ifdef _ARM32_BUS_DMA_PRIVATE
 
+extern paddr_t physical_start, physical_end;
+
 int	arm32_dma_range_intersect(struct arm32_dma_range *, int,
 	    paddr_t pa, psize_t size, paddr_t *pap, psize_t *sizep);
 
@@ -629,6 +633,25 @@ void	_bus_dmamap_unload(bus_dma_tag_t, b
 void	_bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
 	    bus_size_t, int);
 
+#ifdef _ARM32_NEED_BUS_DMA_BOUNCE
+#define	_BUS_DMAMAP_SYNC_FUNCS \
+	._dmamap_sync_pre = _bus_dmamap_sync,	\
+	._dmamap_sync_post = _bus_dmamap_sync
+#else
+#define	_BUS_DMAMAP_SYNC_FUNCS \
+	._dmamap_sync_pre = _bus_dmamap_sync
+#endif
+
+#define	_BUS_DMAMAP_FUNCS \
+	._dmamap_create = _bus_dmamap_create,		\
+	._dmamap_destroy = _bus_dmamap_destroy,		\
+	._dmamap_load = _bus_dmamap_load,		\
+	._dmamap_load_mbuf = _bus_dmamap_load_mbuf,	\
+	._dmamap_load_raw = _bus_dmamap_load_raw,	\
+	._dmamap_load_uio = _bus_dmamap_load_uio,	\
+	._dmamap_unload = _bus_dmamap_unload,		\
+	_BUS_DMAMAP_SYNC_FUNCS
+
 int	_bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size,
 	    bus_size_t alignment, bus_size_t boundary,
 	    bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags);
@@ -641,10 +664,26 @@ void	_bus_dmamem_unmap(bus_dma_tag_t tag
 paddr_t	_bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs,
 	    int nsegs, off_t off, int prot, int flags);
 
+#define	_BUS_DMAMEM_FUNCS \
+	._dmamem_alloc = _bus_dmamem_alloc,	\
+	._dmamem_free = _bus_dmamem_free,	\
+	._dmamem_map = _bus_dmamem_map,		\
+	._dmamem_unmap = _bus_dmamem_unmap,	\
+	._dmamem_mmap = _bus_dmamem_mmap
+
 int	_bus_dmamem_alloc_range(bus_dma_tag_t tag, 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);
+
+int	_bus_dmatag_subregion(bus_dma_tag_t, bus_addr_t, bus_addr_t,
+	    bus_dma_tag_t *, int);
+void 	_bus_dmatag_destroy(bus_dma_tag_t);
+
+#define	_BUS_DMATAG_FUNCS \
+	._dmatag_subregion = _bus_dmatag_subregion,	\
+	._dmatag_destroy = _bus_dmatag_destroy
+
 #endif /* _ARM32_BUS_DMA_PRIVATE */
 
 #endif /* _ARM32_BUS_FUNCS_H_ */

Index: src/sys/arch/arm/ixp12x0/ixp12x0_pci_dma.c
diff -u src/sys/arch/arm/ixp12x0/ixp12x0_pci_dma.c:1.8 src/sys/arch/arm/ixp12x0/ixp12x0_pci_dma.c:1.9
--- src/sys/arch/arm/ixp12x0/ixp12x0_pci_dma.c:1.8	Fri Jul  1 20:27:50 2011
+++ src/sys/arch/arm/ixp12x0/ixp12x0_pci_dma.c	Tue Sep 18 05:47:27 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: ixp12x0_pci_dma.c,v 1.8 2011/07/01 20:27:50 dyoung Exp $ */
+/*	$NetBSD: ixp12x0_pci_dma.c,v 1.9 2012/09/18 05:47:27 matt Exp $ */
 /*
  * Copyright (c) 2002, 2003
  *	Ichiro FUKUHARA <ich...@ichiro.org>.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ixp12x0_pci_dma.c,v 1.8 2011/07/01 20:27:50 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ixp12x0_pci_dma.c,v 1.9 2012/09/18 05:47:27 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -74,4 +74,7 @@ ixp12x0_pci_dma_init(struct ixp12x0_soft
 	dmat->_dmamem_map = _bus_dmamem_map;
 	dmat->_dmamem_unmap = _bus_dmamem_unmap;
 	dmat->_dmamem_mmap = _bus_dmamem_mmap;
+
+	dmat->_dmatag_subregion = _bus_dmatag_subregion;
+	dmat->_dmatag_destroy = _bus_dmatag_destroy;
 }

Index: src/sys/arch/arm/marvell/mvsoc_dma.c
diff -u src/sys/arch/arm/marvell/mvsoc_dma.c:1.2 src/sys/arch/arm/marvell/mvsoc_dma.c:1.3
--- src/sys/arch/arm/marvell/mvsoc_dma.c:1.2	Fri Jul  1 20:30:21 2011
+++ src/sys/arch/arm/marvell/mvsoc_dma.c	Tue Sep 18 05:47:27 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: mvsoc_dma.c,v 1.2 2011/07/01 20:30:21 dyoung Exp $ */
+/*	$NetBSD: mvsoc_dma.c,v 1.3 2012/09/18 05:47:27 matt Exp $ */
 
 /*
  * Copyright (c) 2004 Jesse Off
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mvsoc_dma.c,v 1.2 2011/07/01 20:30:21 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mvsoc_dma.c,v 1.3 2012/09/18 05:47:27 matt Exp $");
 
 #define _ARM32_BUS_DMA_PRIVATE
 
@@ -51,24 +51,7 @@ __KERNEL_RCSID(0, "$NetBSD: mvsoc_dma.c,
 #include <arm/marvell/mvsocvar.h>
 
 struct arm32_bus_dma_tag mvsoc_bus_dma_tag = {
-	NULL,			/* _ranges: set by platform specific routine */
-	0,			/* _nranges */
-
-	NULL,			/* _cookie */
-
-	_bus_dmamap_create,
-	_bus_dmamap_destroy,
-	_bus_dmamap_load,
-	_bus_dmamap_load_mbuf,
-	_bus_dmamap_load_uio,
-	_bus_dmamap_load_raw,
-	_bus_dmamap_unload,
-	_bus_dmamap_sync,
-	NULL,			/* sync_post */
-
-	_bus_dmamem_alloc,
-	_bus_dmamem_free,
-	_bus_dmamem_map,
-	_bus_dmamem_unmap,
-	_bus_dmamem_mmap,
+	_BUS_DMAMAP_FUNCS,
+	_BUS_DMAMEM_FUNCS,
+	_BUS_DMATAG_FUNCS,
 };

Index: src/sys/arch/arm/omap/omap_dma.c
diff -u src/sys/arch/arm/omap/omap_dma.c:1.3 src/sys/arch/arm/omap/omap_dma.c:1.4
--- src/sys/arch/arm/omap/omap_dma.c:1.3	Fri Jul  1 20:30:21 2011
+++ src/sys/arch/arm/omap/omap_dma.c	Tue Sep 18 05:47:28 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: omap_dma.c,v 1.3 2011/07/01 20:30:21 dyoung Exp $	*/
+/*	$NetBSD: omap_dma.c,v 1.4 2012/09/18 05:47:28 matt Exp $	*/
 
 /*
  * Copyright (c) 2010 Michael Lorenz
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: omap_dma.c,v 1.3 2011/07/01 20:30:21 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: omap_dma.c,v 1.4 2012/09/18 05:47:28 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -40,22 +40,7 @@ __KERNEL_RCSID(0, "$NetBSD: omap_dma.c,v
 #include <sys/bus.h>
 
 struct arm32_bus_dma_tag omap_bus_dma_tag = {
-	0,
-	0,
-	NULL,			/* _cookie */
-	_bus_dmamap_create,
-	_bus_dmamap_destroy,
-	_bus_dmamap_load,
-	_bus_dmamap_load_mbuf,
-	_bus_dmamap_load_uio,
-	_bus_dmamap_load_raw,
-	_bus_dmamap_unload,
-	_bus_dmamap_sync,
-	NULL,			/* sync_post */
-	_bus_dmamem_alloc,
-	_bus_dmamem_free,
-	_bus_dmamem_map,
-	_bus_dmamem_unmap,
-	_bus_dmamem_mmap
+	_BUS_DMAMAP_FUNCS,
+	_BUS_DMAMEM_FUNCS,
+	_BUS_DMATAG_FUNCS,
 };
-

Index: src/sys/arch/arm/s3c2xx0/s3c2xx0_busdma.c
diff -u src/sys/arch/arm/s3c2xx0/s3c2xx0_busdma.c:1.4 src/sys/arch/arm/s3c2xx0/s3c2xx0_busdma.c:1.5
--- src/sys/arch/arm/s3c2xx0/s3c2xx0_busdma.c:1.4	Fri Jul  1 20:31:39 2011
+++ src/sys/arch/arm/s3c2xx0/s3c2xx0_busdma.c	Tue Sep 18 05:47:28 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: s3c2xx0_busdma.c,v 1.4 2011/07/01 20:31:39 dyoung Exp $ */
+/*	$NetBSD: s3c2xx0_busdma.c,v 1.5 2012/09/18 05:47:28 matt Exp $ */
 
 /*
  * Copyright (c) 2002, 2003 Fujitsu Component Limited
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: s3c2xx0_busdma.c,v 1.4 2011/07/01 20:31:39 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: s3c2xx0_busdma.c,v 1.5 2012/09/18 05:47:28 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -51,24 +51,7 @@ __KERNEL_RCSID(0, "$NetBSD: s3c2xx0_busd
 #include <arm/s3c2xx0/s3c2xx0var.h>
 
 struct arm32_bus_dma_tag s3c2xx0_bus_dma = {
-	NULL,			/* _ranges: set by platform specific routine */
-	0,			/* _nranges */
-
-	NULL,			/* _cookie */
-
-	_bus_dmamap_create,
-	_bus_dmamap_destroy,
-	_bus_dmamap_load,
-	_bus_dmamap_load_mbuf,
-	_bus_dmamap_load_uio,
-	_bus_dmamap_load_raw,
-	_bus_dmamap_unload,
-	_bus_dmamap_sync,
-	NULL,			/* sync_post */
-
-	_bus_dmamem_alloc,
-	_bus_dmamem_free,
-	_bus_dmamem_map,
-	_bus_dmamem_unmap,
-	_bus_dmamem_mmap,
+	_BUS_DMAMAP_FUNCS,
+	_BUS_DMAMEM_FUNCS,
+	_BUS_DMATAG_FUNCS,
 };

Index: src/sys/arch/arm/xscale/becc.c
diff -u src/sys/arch/arm/xscale/becc.c:1.14 src/sys/arch/arm/xscale/becc.c:1.15
--- src/sys/arch/arm/xscale/becc.c:1.14	Fri Jul  1 20:32:51 2011
+++ src/sys/arch/arm/xscale/becc.c	Tue Sep 18 05:47:28 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: becc.c,v 1.14 2011/07/01 20:32:51 dyoung Exp $	*/
+/*	$NetBSD: becc.c,v 1.15 2012/09/18 05:47:28 matt Exp $	*/
 
 /*
  * Copyright (c) 2002, 2003 Wasabi Systems, Inc.
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: becc.c,v 1.14 2011/07/01 20:32:51 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: becc.c,v 1.15 2012/09/18 05:47:28 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -297,6 +297,9 @@ becc_pci_dma_init(struct becc_softc *sc)
 	dmat->_dmamem_map = _bus_dmamem_map;
 	dmat->_dmamem_unmap = _bus_dmamem_unmap;
 	dmat->_dmamem_mmap = _bus_dmamem_mmap;
+
+	dmat->_dmatag_subregion = _bus_dmatag_subregion;
+	dmat->_dmatag_destroy = _bus_dmatag_destroy;
 }
 
 /*

Index: src/sys/arch/arm/xscale/i80312.c
diff -u src/sys/arch/arm/xscale/i80312.c:1.21 src/sys/arch/arm/xscale/i80312.c:1.22
--- src/sys/arch/arm/xscale/i80312.c:1.21	Fri Jul  1 20:32:51 2011
+++ src/sys/arch/arm/xscale/i80312.c	Tue Sep 18 05:47:28 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: i80312.c,v 1.21 2011/07/01 20:32:51 dyoung Exp $	*/
+/*	$NetBSD: i80312.c,v 1.22 2012/09/18 05:47:28 matt Exp $	*/
 
 /*
  * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
@@ -40,7 +40,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: i80312.c,v 1.21 2011/07/01 20:32:51 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: i80312.c,v 1.22 2012/09/18 05:47:28 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -368,6 +368,9 @@ i80312_pci_dma_init(struct i80312_softc 
 	dmat->_dmamem_map = _bus_dmamem_map;
 	dmat->_dmamem_unmap = _bus_dmamem_unmap;
 	dmat->_dmamem_mmap = _bus_dmamem_mmap;
+
+	dmat->_dmatag_subregion = _bus_dmatag_subregion;
+	dmat->_dmatag_destroy = _bus_dmatag_destroy;
 }
 
 /*

Index: src/sys/arch/arm/xscale/i80321.c
diff -u src/sys/arch/arm/xscale/i80321.c:1.23 src/sys/arch/arm/xscale/i80321.c:1.24
--- src/sys/arch/arm/xscale/i80321.c:1.23	Sun Feb 12 16:31:01 2012
+++ src/sys/arch/arm/xscale/i80321.c	Tue Sep 18 05:47:28 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: i80321.c,v 1.23 2012/02/12 16:31:01 matt Exp $	*/
+/*	$NetBSD: i80321.c,v 1.24 2012/09/18 05:47:28 matt Exp $	*/
 
 /*
  * Copyright (c) 2002 Wasabi Systems, Inc.
@@ -40,7 +40,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: i80321.c,v 1.23 2012/02/12 16:31:01 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: i80321.c,v 1.24 2012/09/18 05:47:28 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -337,6 +337,9 @@ i80321_pci_dma_init(struct i80321_softc 
 	dmat->_dmamem_map = _bus_dmamem_map;
 	dmat->_dmamem_unmap = _bus_dmamem_unmap;
 	dmat->_dmamem_mmap = _bus_dmamem_mmap;
+
+	dmat->_dmatag_subregion = _bus_dmatag_subregion;
+	dmat->_dmatag_destroy = _bus_dmatag_destroy;
 }
 
 /*

Index: src/sys/arch/arm/xscale/ixp425_ixme.c
diff -u src/sys/arch/arm/xscale/ixp425_ixme.c:1.3 src/sys/arch/arm/xscale/ixp425_ixme.c:1.4
--- src/sys/arch/arm/xscale/ixp425_ixme.c:1.3	Fri Jul  1 20:32:51 2011
+++ src/sys/arch/arm/xscale/ixp425_ixme.c	Tue Sep 18 05:47:28 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: ixp425_ixme.c,v 1.3 2011/07/01 20:32:51 dyoung Exp $	*/
+/*	$NetBSD: ixp425_ixme.c,v 1.4 2012/09/18 05:47:28 matt Exp $	*/
 
 /*-
  * Copyright (c) 2006 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ixp425_ixme.c,v 1.3 2011/07/01 20:32:51 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ixp425_ixme.c,v 1.4 2012/09/18 05:47:28 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -99,12 +99,16 @@ ixme_attach(struct device *parent, struc
 	sc->sc_dt._dmamap_unload = _bus_dmamap_unload;
 	sc->sc_dt._dmamap_sync_pre = _bus_dmamap_sync;
 	sc->sc_dt._dmamap_sync_post = NULL;
+
 	sc->sc_dt._dmamem_alloc = _bus_dmamem_alloc;
 	sc->sc_dt._dmamem_free = _bus_dmamem_free;
 	sc->sc_dt._dmamem_map = _bus_dmamem_map;
 	sc->sc_dt._dmamem_unmap = _bus_dmamem_unmap;
 	sc->sc_dt._dmamem_mmap = _bus_dmamem_mmap;
 
+	sc->sc_dt._dmatag_subregion = _bus_dmatag_subregion;
+	sc->sc_dt._dmatag_destroy = _bus_dmatag_destroy;
+
 	config_search_ia(ixme_search, self, "ixme", NULL);
 }
 

Index: src/sys/arch/arm/xscale/ixp425_pci_dma.c
diff -u src/sys/arch/arm/xscale/ixp425_pci_dma.c:1.5 src/sys/arch/arm/xscale/ixp425_pci_dma.c:1.6
--- src/sys/arch/arm/xscale/ixp425_pci_dma.c:1.5	Fri Jul  1 20:32:51 2011
+++ src/sys/arch/arm/xscale/ixp425_pci_dma.c	Tue Sep 18 05:47:28 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: ixp425_pci_dma.c,v 1.5 2011/07/01 20:32:51 dyoung Exp $ */
+/*	$NetBSD: ixp425_pci_dma.c,v 1.6 2012/09/18 05:47:28 matt Exp $ */
 
 /*
  * Copyright (c) 2003
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ixp425_pci_dma.c,v 1.5 2011/07/01 20:32:51 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ixp425_pci_dma.c,v 1.6 2012/09/18 05:47:28 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -74,4 +74,7 @@ ixp425_pci_dma_init(struct ixp425_softc 
 	dmat->_dmamem_map = _bus_dmamem_map;
 	dmat->_dmamem_unmap = _bus_dmamem_unmap;
 	dmat->_dmamem_mmap = _bus_dmamem_mmap;
+
+	dmat->_dmatag_subregion = _bus_dmatag_subregion;
+	dmat->_dmatag_destroy = _bus_dmatag_destroy;
 }
Index: src/sys/arch/arm/xscale/pxa2x0_dma.c
diff -u src/sys/arch/arm/xscale/pxa2x0_dma.c:1.5 src/sys/arch/arm/xscale/pxa2x0_dma.c:1.6
--- src/sys/arch/arm/xscale/pxa2x0_dma.c:1.5	Fri Jul  1 20:32:51 2011
+++ src/sys/arch/arm/xscale/pxa2x0_dma.c	Tue Sep 18 05:47:28 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: pxa2x0_dma.c,v 1.5 2011/07/01 20:32:51 dyoung Exp $ */
+/*	$NetBSD: pxa2x0_dma.c,v 1.6 2012/09/18 05:47:28 matt Exp $ */
 
 /*
  * Copyright (c) 2002  Genetec Corporation.  All rights reserved.
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pxa2x0_dma.c,v 1.5 2011/07/01 20:32:51 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pxa2x0_dma.c,v 1.6 2012/09/18 05:47:28 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -53,22 +53,7 @@ __KERNEL_RCSID(0, "$NetBSD: pxa2x0_dma.c
 #include <sys/bus.h>
 
 struct arm32_bus_dma_tag pxa2x0_bus_dma_tag = {
-	0,
-	0,
-	NULL,			/* _cookie */
-	_bus_dmamap_create,
-	_bus_dmamap_destroy,
-	_bus_dmamap_load,
-	_bus_dmamap_load_mbuf,
-	_bus_dmamap_load_uio,
-	_bus_dmamap_load_raw,
-	_bus_dmamap_unload,
-	_bus_dmamap_sync,
-	NULL,			/* sync_post */
-	_bus_dmamem_alloc,
-	_bus_dmamem_free,
-	_bus_dmamem_map,
-	_bus_dmamem_unmap,
-	_bus_dmamem_mmap
+	_BUS_DMAMAP_FUNCS,
+	_BUS_DMAMEM_FUNCS,
+	_BUS_DMATAG_FUNCS,
 };
-

Reply via email to