Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch Overhaul how DMA ranges work in the ARM bus_dma imp...



details:   https://anonhg.NetBSD.org/src/rev/9766368e34fd
branches:  trunk
changeset: 534653:9766368e34fd
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Wed Jul 31 17:34:23 2002 +0000

description:
Overhaul how DMA ranges work in the ARM bus_dma implementation.

A new "arm32_dma_range" structure now describes a DMA window, with
a system address base, bus address base, and length.  In addition to
providing info about which memory regions are legal for DMA, the new
structure provides address translation support, as well.

As before, if a tag does not list any ranges, then all addresses are
considered valid, and no DMA address translation is performed.

This allows us to remove a large chunk of code which was duplicated and
tweaked slightly (to do the address translation) from the stock ARM
bus_dma in the XScale IOP and ARM Integrator ports.

Test compiled on all ARM platforms, test booted on Intel IQ80321 and Shark.

diffstat:

 sys/arch/arm/arm32/bus_dma.c                     |  115 +++-
 sys/arch/arm/arm32/pmap.c                        |   59 +--
 sys/arch/arm/footbridge/isa/isadma_machdep.c     |   26 +-
 sys/arch/arm/include/arm32/pmap.h                |    5 +-
 sys/arch/arm/include/bus.h                       |   18 +-
 sys/arch/arm/ixp12x0/ixp12x0_pci_dma.c           |   12 +-
 sys/arch/arm/xscale/i80312_pci_dma.c             |  321 +-----------
 sys/arch/arm/xscale/i80312var.h                  |    7 +-
 sys/arch/arm/xscale/i80321.c                     |   12 +-
 sys/arch/arm/xscale/i80321_local_dma.c           |  286 +----------
 sys/arch/arm/xscale/i80321_pci_dma.c             |  317 +-----------
 sys/arch/arm/xscale/i80321var.h                  |    5 +-
 sys/arch/cats/cats/cats_machdep.c                |   11 +-
 sys/arch/cats/isa/isa_machdep.c                  |   18 +-
 sys/arch/evbarm/ifpga/ifpga.c                    |    6 +-
 sys/arch/evbarm/ifpga/ifpga_pci.c                |   16 +-
 sys/arch/evbarm/integrator/int_bus_dma.c         |  617 +---------------------
 sys/arch/evbarm/integrator/int_bus_dma.h         |   28 +-
 sys/arch/netwinder/isa/isa_machdep.c             |   18 +-
 sys/arch/netwinder/netwinder/netwinder_machdep.c |   11 +-
 sys/arch/shark/isa/isadma_machdep.c              |   25 +-
 sys/arch/shark/ofw/ofw.c                         |   33 +-
 22 files changed, 298 insertions(+), 1668 deletions(-)

diffs (truncated from 2536 to 300 lines):

diff -r 46dcd42d8004 -r 9766368e34fd sys/arch/arm/arm32/bus_dma.c
--- a/sys/arch/arm/arm32/bus_dma.c      Wed Jul 31 16:23:37 2002 +0000
+++ b/sys/arch/arm/arm32/bus_dma.c      Wed Jul 31 17:34:23 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bus_dma.c,v 1.14 2002/07/28 17:54:05 thorpej Exp $     */
+/*     $NetBSD: bus_dma.c,v 1.15 2002/07/31 17:34:23 thorpej Exp $     */
 
 /*-
  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
@@ -62,7 +62,8 @@
 
 int    _bus_dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *,
            bus_size_t, struct proc *, int, paddr_t *, int *, int);
-int    _bus_dma_inrange(bus_dma_segment_t *, int, bus_addr_t);
+struct arm32_dma_range *_bus_dma_inrange(struct arm32_dma_range *,
+           int, bus_addr_t);
 
 /*
  * Common function for DMA map creation.  May be called by bus-specific
@@ -571,16 +572,38 @@
     bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs,
     int flags)
 {
-       int error;
+       struct arm32_dma_range *dr;
+       int error, i;
+
 #ifdef DEBUG_DMA
-       printf("dmamem_alloc t=%p size=%lx align=%lx boundary=%lx segs=%p nsegs=%x rsegs=%p flags=%x\n",
-           t, size, alignment, boundary, segs, nsegs, rsegs, flags);
-#endif /* DEBUG_DMA */
-       error =  (_bus_dmamem_alloc_range(t, size, alignment, boundary,
-           segs, nsegs, rsegs, flags, trunc_page(physical_start), trunc_page(physical_end)));
+       printf("dmamem_alloc t=%p size=%lx align=%lx boundary=%lx "
+           "segs=%p nsegs=%x rsegs=%p flags=%x\n", t, size, alignment,
+           boundary, segs, nsegs, rsegs, flags);
+#endif
+
+       if ((dr = t->_ranges) != NULL) {
+               for (i = 0; i < t->_nranges; i++, dr++) {
+                       if (dr->dr_len == 0) {
+                               error = ENOMEM;
+                               continue;
+                       }
+                       error = _bus_dmamem_alloc_range(t, size, alignment,
+                           boundary, segs, nsegs, rsegs, flags,
+                           trunc_page(dr->dr_sysbase),
+                           trunc_page(dr->dr_sysbase + dr->dr_len));
+                       if (error == 0)
+                               break;
+               }
+       } else {
+               error = _bus_dmamem_alloc_range(t, size, alignment, boundary,
+                   segs, nsegs, rsegs, flags, trunc_page(physical_start),
+                   trunc_page(physical_end));
+       }
+
 #ifdef DEBUG_DMA
        printf("dmamem_alloc: =%d\n", error);
-#endif /* DEBUG_DMA */
+#endif
+
        return(error);
 }
 
@@ -749,6 +772,7 @@
     bus_size_t buflen, struct proc *p, int flags, paddr_t *lastaddrp,
     int *segp, int first)
 {
+       struct arm32_dma_range *dr;
        bus_size_t sgsize;
        bus_addr_t curaddr, lastaddr, baddr, bmask;
        vaddr_t vaddr = (vaddr_t)buf;
@@ -777,9 +801,19 @@
                /*
                 * Make sure we're in an allowed DMA range.
                 */
-               if (t->_ranges != NULL &&
-                   _bus_dma_inrange(t->_ranges, t->_nranges, curaddr) == 0)
-                       return (EINVAL);
+               if (t->_ranges != NULL) {
+                       /* XXX cache last result? */
+                       dr = _bus_dma_inrange(t->_ranges, t->_nranges,
+                           curaddr);
+                       if (dr == NULL)
+                               return (EINVAL);
+                       
+                       /*
+                        * In a valid DMA range.  Translate the physical
+                        * memory address to an address in the DMA window.
+                        */
+                       curaddr = (curaddr - dr->dr_sysbase) + dr->dr_busbase;
+               }
 
                /*
                 * Compute the segment size, and adjust counts.
@@ -840,19 +874,20 @@
 /*
  * Check to see if the specified page is in an allowed DMA range.
  */
-int
-_bus_dma_inrange(bus_dma_segment_t *ranges, int nranges, bus_addr_t curaddr)
+struct arm32_dma_range *
+_bus_dma_inrange(struct arm32_dma_range *ranges, int nranges,
+    bus_addr_t curaddr)
 {
-       bus_dma_segment_t *ds;
+       struct arm32_dma_range *dr;
        int i;
 
-       for (i = 0, ds = ranges; i < nranges; i++, ds++) {
-               if (curaddr >= ds->ds_addr &&
-                   round_page(curaddr) <= (ds->ds_addr + ds->ds_len))
-                       return (1);
+       for (i = 0, dr = ranges; i < nranges; i++, dr++) {
+               if (curaddr >= dr->dr_sysbase &&
+                   round_page(curaddr) <= (dr->dr_sysbase + dr->dr_len))
+                       return (dr);
        }
 
-       return (0);
+       return (NULL);
 }
 
 /*
@@ -924,3 +959,43 @@
 
        return (0);
 }
+
+/*
+ * Check if a memory region intersects with a DMA range, and return the
+ * page-rounded intersection if it does.
+ */
+int
+arm32_dma_range_intersect(struct arm32_dma_range *ranges, int nranges,
+    paddr_t pa, psize_t size, paddr_t *pap, psize_t *sizep)
+{
+       struct arm32_dma_range *dr;
+       int i;
+
+       if (ranges == NULL)
+               return (0);
+
+       for (i = 0, dr = ranges; i < nranges; i++, dr++) {
+               if (dr->dr_sysbase <= pa &&
+                   pa < (dr->dr_sysbase + dr->dr_len)) {
+                       /*
+                        * Beginning of region intersects with this range.
+                        */
+                       *pap = trunc_page(pa);
+                       *sizep = round_page(min(pa + size,
+                           dr->dr_sysbase + dr->dr_len) - pa);
+                       return (1);
+               }
+               if (pa < dr->dr_sysbase && dr->dr_sysbase < (pa + size)) {
+                       /*
+                        * End of region intersects with this range.
+                        */
+                       *pap = trunc_page(dr->dr_sysbase);
+                       *sizep = round_page(min((pa + size) - dr->dr_sysbase,
+                           dr->dr_len));
+                       return (1);
+               }
+       }
+
+       /* No intersection found. */
+       return (0);
+}
diff -r 46dcd42d8004 -r 9766368e34fd sys/arch/arm/arm32/pmap.c
--- a/sys/arch/arm/arm32/pmap.c Wed Jul 31 16:23:37 2002 +0000
+++ b/sys/arch/arm/arm32/pmap.c Wed Jul 31 17:34:23 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pmap.c,v 1.102 2002/07/31 00:20:52 thorpej Exp $       */
+/*     $NetBSD: pmap.c,v 1.103 2002/07/31 17:34:23 thorpej Exp $       */
 
 /*
  * Copyright (c) 2002 Wasabi Systems, Inc.
@@ -143,7 +143,7 @@
 #include <machine/param.h>
 #include <arm/arm32/katelib.h>
 
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.102 2002/07/31 00:20:52 thorpej Exp $");        
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.103 2002/07/31 17:34:23 thorpej Exp $");        
 #ifdef PMAP_DEBUG
 #define        PDEBUG(_lev_,_stat_) \
        if (pmap_debug_level >= (_lev_)) \
@@ -406,61 +406,6 @@
        return (FALSE);
 }
 
-#include "isadma.h"
-
-#if NISADMA > 0
-/*
- * Used to protect memory for ISA DMA bounce buffers.  If, when loading
- * pages into the system, memory intersects with any of these ranges,
- * the intersecting memory will be loaded into a lower-priority free list.
- */
-bus_dma_segment_t *pmap_isa_dma_ranges;
-int pmap_isa_dma_nranges;
-
-/*
- * Check if a memory range intersects with an ISA DMA range, and
- * return the page-rounded intersection if it does.  The intersection
- * will be placed on a lower-priority free list.
- */
-boolean_t
-pmap_isa_dma_range_intersect(paddr_t pa, psize_t size, paddr_t *pap,
-    psize_t *sizep)
-{
-       bus_dma_segment_t *ds;
-       int i;
-
-       if (pmap_isa_dma_ranges == NULL)
-               return (FALSE);
-
-       for (i = 0, ds = pmap_isa_dma_ranges;
-            i < pmap_isa_dma_nranges; i++, ds++) {
-               if (ds->ds_addr <= pa && pa < (ds->ds_addr + ds->ds_len)) {
-                       /*
-                        * Beginning of region intersects with this range.
-                        */
-                       *pap = trunc_page(pa);
-                       *sizep = round_page(min(pa + size,
-                           ds->ds_addr + ds->ds_len) - pa);
-                       return (TRUE);
-               }
-               if (pa < ds->ds_addr && ds->ds_addr < (pa + size)) {
-                       /*
-                        * End of region intersects with this range.
-                        */
-                       *pap = trunc_page(ds->ds_addr);
-                       *sizep = round_page(min((pa + size) - ds->ds_addr,
-                           ds->ds_len));
-                       return (TRUE);
-               }
-       }
-
-       /*
-        * No intersection found.
-        */
-       return (FALSE);
-}
-#endif /* NISADMA > 0 */
-
 /*
  * p v _ e n t r y   f u n c t i o n s
  */
diff -r 46dcd42d8004 -r 9766368e34fd sys/arch/arm/footbridge/isa/isadma_machdep.c
--- a/sys/arch/arm/footbridge/isa/isadma_machdep.c      Wed Jul 31 16:23:37 2002 +0000
+++ b/sys/arch/arm/footbridge/isa/isadma_machdep.c      Wed Jul 31 17:34:23 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: isadma_machdep.c,v 1.1 2002/02/10 12:26:01 chris Exp $ */
+/*     $NetBSD: isadma_machdep.c,v 1.2 2002/07/31 17:34:24 thorpej Exp $       */
 
 #define ISA_DMA_STATS
 
@@ -65,8 +65,9 @@
  * etc. (unless we've run out of memory elsewhere).
  */
 #define        ISA_DMA_BOUNCE_THRESHOLD        (16 * 1024 * 1024)
-extern bus_dma_segment_t *pmap_isa_dma_ranges;
-extern int pmap_isa_dma_nranges;
+
+struct arm32_dma_range *footbridge_isa_dma_ranges;
+int footbridge_isa_dma_nranges;
 
 int    _isa_bus_dmamap_create __P((bus_dma_tag_t, bus_size_t, int,
            bus_size_t, bus_size_t, int, bus_dmamap_t *));
@@ -120,8 +121,8 @@
 isa_dma_init()
 {
 
-       isa_bus_dma_tag._ranges = pmap_isa_dma_ranges;
-       isa_bus_dma_tag._nranges = pmap_isa_dma_nranges;
+       isa_bus_dma_tag._ranges = footbridge_isa_dma_ranges;
+       isa_bus_dma_tag._nranges = footbridge_isa_dma_nranges;
 }
 
 /**********************************************************************
@@ -606,22 +607,13 @@
        int *rsegs;
        int flags;
 {
-       bus_dma_segment_t *ds;
-       int i, error;
 
        if (t->_ranges == NULL)
                return (ENOMEM);
 
-       for (i = 0, error = ENOMEM, ds = t->_ranges;
-            i < t->_nranges; i++, ds++) {
-               error = _bus_dmamem_alloc_range(t, size, alignment, boundary,
-                   segs, nsegs, rsegs, flags, ds->ds_addr,
-                   ds->ds_addr + ds->ds_len);
-               if (error == 0)
-                       break;
-       }
-



Home | Main Index | Thread Index | Old Index