Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/sparc64 Well, looks like the MI allocsys() broke th...



details:   https://anonhg.NetBSD.org/src/rev/c6ca2be896ef
branches:  trunk
changeset: 473157:c6ca2be896ef
user:      eeh <eeh%NetBSD.org@localhost>
date:      Sat May 22 20:33:55 1999 +0000

description:
Well, looks like the MI allocsys() broke the dvmamap, so instead of using a
single map move it to the bus controller driver so each bus can handle its own
IOMMU without conflicts.

diffstat:

 sys/arch/sparc64/dev/sbus.c         |  150 +++++++++++++++++++++++++++++++++--
 sys/arch/sparc64/dev/sbusreg.h      |    9 +-
 sys/arch/sparc64/dev/sbusvar.h      |    4 +-
 sys/arch/sparc64/sparc64/autoconf.c |    6 +-
 4 files changed, 151 insertions(+), 18 deletions(-)

diffs (truncated from 352 to 300 lines):

diff -r 305381a96029 -r c6ca2be896ef sys/arch/sparc64/dev/sbus.c
--- a/sys/arch/sparc64/dev/sbus.c       Sat May 22 20:30:54 1999 +0000
+++ b/sys/arch/sparc64/dev/sbus.c       Sat May 22 20:33:55 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sbus.c,v 1.11 1999/03/26 23:41:36 mycroft Exp $ */
+/*     $NetBSD: sbus.c,v 1.12 1999/05/22 20:33:56 eeh Exp $ */
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -86,6 +86,7 @@
 #include "opt_ddb.h"
 
 #include <sys/param.h>
+#include <sys/extent.h>
 #include <sys/malloc.h>
 #include <sys/systm.h>
 #include <sys/device.h>
@@ -307,9 +308,19 @@
         *
         * The sun4u iommu is part of the SBUS controller so we will
         * deal with it here.  We could try to fake a device node so
-        * we can eventually share it with the PCI bus run by psyco,
+        * we can eventually share it with the PCI bus run by psycho,
         * but I don't want to get into that sort of cruft.
+        *
+        * First we need to allocate a IOTSB.  Problem is that the IOMMU
+        * can only access the IOTSB by physical address, so all the 
+        * pages must be contiguous.  Luckily, the smallest IOTSB size
+        * is one 8K page.
         */
+#if 1
+       sc->sc_tsbsize = 0;
+       sc->sc_tsb = malloc(NBPG, M_DMAMAP, M_WAITOK);
+       sc->sc_ptsb = pmap_extract(pmap_kernel(), (vaddr_t)sc->sc_tsb);
+#else
 
        /* 
         * All IOMMUs will share the same TSB which is allocated in pmap_bootstrap.
@@ -325,6 +336,7 @@
                sc->sc_tsb = iotsb;
                sc->sc_ptsb = iotsbp;
        }
+#endif
 #if 1
        /* Need to do 64-bit stores */
        bus_space_write_8(sc->sc_bustag, &sc->sc_sysio->sys_iommu.iommu_cr, 
@@ -365,6 +377,22 @@
 #endif
 
        /*
+        * Now all the hardware's working we need to allocate a dvma map.
+        *
+        * The IOMMU address space always ends at 0xffffe000, but the starting
+        * address depends on the size of the map.  The map size is 1024 * 2 ^
+        * sc->sc_tsbsize entries, where each entry is 8 bytes.  The start of
+        * the map can be calculated by (0xffffe000 << (8 + sc->sc_tsbsize)).
+        *
+        * Note: the stupid IOMMU ignores the high bits of an address, so a
+        * NULL DMA pointer will be translated by the first page of the IOTSB.
+        * To trap bugs we'll skip the first entry in the IOTSB.
+        */
+       sc->sc_dvmamap = extent_create("SBus dvma", /* XXXX should have instance number */
+                                      IOTSB_VSTART(sc->sc_tsbsize) + NBPG, IOTSB_VEND,
+                                      M_DEVBUF, 0, 0, EX_NOWAIT);
+
+       /*
         * Loop through ROM children, fixing any relative addresses
         * and then configuring each device.
         * `specials' is an array of device names that are treated
@@ -579,7 +607,7 @@
        }
 #if 1
        /* Reload iommu regs */
-       bus_space_write_8(sc->ma_bustag, &sc->sc_sysio->sys_iommu.iommu_cr, 
+       bus_space_write_8(sc->sc_bustag, &sc->sc_sysio->sys_iommu.iommu_cr, 
                          0, (IOMMUCR_TSB1K|IOMMUCR_8KPG|IOMMUCR_EN));
        bus_space_write_8(sc->sc_bustag, &sc->sc_sysio->sys_iommu.iommu_tsb, 
                          0, sc->sc_ptsb);
@@ -621,6 +649,10 @@
        stxa(&(sc->sc_sysio->sys_strbuf.strbuf_pgflush), ASI_NUCLEUS, va);
 #endif
        sbus_flush(sc);
+#ifdef DEBUG
+       if (sbusdebug & SDB_DVMA)
+               printf("Clearing TSB slot %d for va %p\n", (int)IOTSBSLOT(va,sc->sc_tsbsize), va);
+#endif
        sc->sc_tsb[IOTSBSLOT(va,sc->sc_tsbsize)] = tte;
 #if 1
        bus_space_write_8(sc->sc_bustag, &sc->sc_sysio->sys_iommu.iommu_flush, 
@@ -950,7 +982,7 @@
        bzero(sbt, sizeof *sbt);
        sbt->cookie = sc;
        sbt->parent = sc->sc_bustag;
-       sbt->type = ASI_PRIMARY;
+       sbt->type = SBUS_BUS_SPACE;
        sbt->sparc_bus_map = _sbus_bus_map;
        sbt->sparc_bus_mmap = sbus_bus_mmap;
        sbt->sparc_intr_establish = sbus_intr_establish;
@@ -1000,10 +1032,11 @@
        struct proc *p;
        int flags;
 {
-       int err;
+       int err, s;
        bus_size_t sgsize;
        paddr_t curaddr;
-       vaddr_t  dvmaddr, vaddr = (vaddr_t)buf;
+       u_long dvmaddr;
+       vaddr_t vaddr = (vaddr_t)buf;
        pmap_t pmap;
        struct sbus_softc *sc = (struct sbus_softc *)t->_cookie;
 
@@ -1014,9 +1047,59 @@
 #endif
                bus_dmamap_unload(t, map);
        }
+#if 1
+       /*
+        * Make sure that on error condition we return "no valid mappings".
+        */
+       map->dm_nsegs = 0;
+
+       if (buflen > map->_dm_size)
+#ifdef DEBUG
+       { 
+               printf("_bus_dmamap_load(): error %d > %d -- map size exceeded!\n", buflen, map->_dm_size);
+               Debugger();
+               return (EINVAL);
+       }               
+#else  
+               return (EINVAL);
+#endif
+
+       sgsize = round_page(buflen + ((int)vaddr & PGOFSET));
+
+       /*
+        * XXX Need to implement "don't dma across this boundry".
+        */
+       
+       s = splhigh();
+       err = extent_alloc(sc->sc_dvmamap, sgsize, NBPG,
+                            map->_dm_boundary, EX_NOWAIT, (u_long *)&dvmaddr);
+       splx(s);
+
+       if (err != 0)
+               return (err);
+
+#ifdef DEBUG
+       if (dvmaddr == (bus_addr_t)-1)  
+       { 
+               printf("_bus_dmamap_load(): dvmamap_alloc(%d, %x) failed!\n", sgsize, flags);
+               Debugger();
+       }               
+#endif 
+       if (dvmaddr == (bus_addr_t)-1)
+               return (ENOMEM);
+
+       /*
+        * We always use just one segment.
+        */
+       map->dm_mapsize = buflen;
+       map->dm_nsegs = 1;
+       map->dm_segs[0].ds_addr = dvmaddr + (vaddr & PGOFSET);
+       map->dm_segs[0].ds_len = sgsize;
+
+#else
        if ((err = bus_dmamap_load(t->_parent, map, buf, buflen, p, flags)))
                return (err);
-
+#endif
        if (p != NULL)
                pmap = p->p_vmspace->vm_map.pmap;
        else
@@ -1060,7 +1143,9 @@
        bus_dmamap_t map;
 {
        vaddr_t addr;
-       int len;
+       int len, error, s;
+       bus_addr_t dvmaddr;
+       bus_size_t sgsize;
        struct sbus_softc *sc = (struct sbus_softc *)t->_cookie;
 
        if (map->dm_nsegs != 1)
@@ -1075,7 +1160,25 @@
                       map, (long)addr, (long)len);
 #endif
        sbus_remove(sc, addr, len);
+#if 1
+       dvmaddr = (map->dm_segs[0].ds_addr & ~PGOFSET);
+       sgsize = map->dm_segs[0].ds_len;
+
+       /* Mark the mappings as invalid. */
+       map->dm_mapsize = 0;
+       map->dm_nsegs = 0;
+       
+       /* Unmapping is bus dependent */
+       s = splhigh();
+       error = extent_free(sc->sc_dvmamap, dvmaddr, sgsize, EX_NOWAIT);
+       splx(s);
+       if (error != 0)
+               printf("warning: %ld of DVMA space lost\n", (long)sgsize);
+
+       cache_flush((caddr_t)dvmaddr, (u_int) sgsize);  
+#else
        bus_dmamap_unload(t->_parent, map);
+#endif
 }
 
 
@@ -1177,11 +1280,11 @@
        int flags;
 {
        paddr_t curaddr;
-       bus_addr_t dvmaddr;
+       u_long dvmaddr;
        vm_page_t m;
        struct pglist *mlist;
        int error;
-       int n;
+       int n, s;
        struct sbus_softc *sc = (struct sbus_softc *)t->_cookie;
 
        if ((error = bus_dmamem_alloc(t->_parent, size, alignment, 
@@ -1192,12 +1295,24 @@
         * Allocate a DVMA mapping for our new memory.
         */
        for (n=0; n<*rsegs; n++) {
+#if 1
+               s = splhigh();
+               if (extent_alloc(sc->sc_dvmamap, segs[0].ds_len, alignment,
+                                boundary, EX_NOWAIT, (u_long *)&dvmaddr)) {
+                       splx(s);
+                               /* Free what we got and exit */
+                       bus_dmamem_free(t->_parent, segs, nsegs);
+                       return (ENOMEM);
+               }
+               splx(s);
+#else
                dvmaddr = dvmamap_alloc(segs[0].ds_len, flags);
                if (dvmaddr == (bus_addr_t)-1) {
                        /* Free what we got and exit */
                        bus_dmamem_free(t->_parent, segs, nsegs);
                        return (ENOMEM);
                }
+#endif
                segs[n].ds_addr = dvmaddr;
                size = segs[n].ds_len;
                mlist = segs[n]._ds_mlist;
@@ -1205,6 +1320,11 @@
                /* Map memory into DVMA space */
                for (m = mlist->tqh_first; m != NULL; m = m->pageq.tqe_next) {
                        curaddr = VM_PAGE_TO_PHYS(m);
+#ifdef DEBUG
+                       if (sbusdebug & SDB_DVMA)
+                               printf("sbus_dmamem_alloc: map %p loading va %lx at pa %lx\n",
+                                      (long)m, (long)dvmaddr, (long)(curaddr & ~(NBPG-1)));
+#endif
                        sbus_enter(sc, dvmaddr, curaddr, flags);
                        dvmaddr += PAGE_SIZE;
                }
@@ -1220,7 +1340,7 @@
 {
        vaddr_t addr;
        int len;
-       int n;
+       int n, s, error;
        struct sbus_softc *sc = (struct sbus_softc *)t->_cookie;
 
 
@@ -1228,7 +1348,15 @@
                addr = segs[n].ds_addr;
                len = segs[n].ds_len;
                sbus_remove(sc, addr, len);
+#if 1
+               s = splhigh();
+               error = extent_free(sc->sc_dvmamap, addr, len, EX_NOWAIT);
+               splx(s);
+               if (error != 0)
+                       printf("warning: %ld of DVMA space lost\n", (long)len);
+#else
                dvmamap_free(addr, len);
+#endif
        }
        bus_dmamem_free(t->_parent, segs, nsegs);
 }
diff -r 305381a96029 -r c6ca2be896ef sys/arch/sparc64/dev/sbusreg.h
--- a/sys/arch/sparc64/dev/sbusreg.h    Sat May 22 20:30:54 1999 +0000
+++ b/sys/arch/sparc64/dev/sbusreg.h    Sat May 22 20:33:55 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sbusreg.h,v 1.3 1998/09/05 23:57:25 eeh Exp $ */
+/*     $NetBSD: sbusreg.h,v 1.4 1999/05/22 20:33:56 eeh Exp $ */
 
 /*
  * Copyright (c) 1992, 1993
@@ -251,13 +251,16 @@
 #define IOTTE_C                0x0000000000000010LL    /* Accesses to cacheable space */
 #define IOTTE_W                0x0000000000000002LL    /* Writeable */
 
+#define IOTSB_VEND     0xffffe000



Home | Main Index | Thread Index | Old Index