Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/hp700/dev Fixup uturn DMA for real mode. That is, u...



details:   https://anonhg.NetBSD.org/src/rev/aaf9ee71fae3
branches:  trunk
changeset: 755789:aaf9ee71fae3
user:      skrll <skrll%NetBSD.org@localhost>
date:      Mon Jun 21 07:09:59 2010 +0000

description:
Fixup uturn DMA for real mode. That is, use uncacheable directly mapped
pages.

diffstat:

 sys/arch/hp700/dev/uturn.c |  275 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 271 insertions(+), 4 deletions(-)

diffs (truncated from 342 to 300 lines):

diff -r 3cccc05eca8e -r aaf9ee71fae3 sys/arch/hp700/dev/uturn.c
--- a/sys/arch/hp700/dev/uturn.c        Sun Jun 20 21:57:59 2010 +0000
+++ b/sys/arch/hp700/dev/uturn.c        Mon Jun 21 07:09:59 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uturn.c,v 1.8 2010/06/18 06:30:53 skrll Exp $  */
+/*     $NetBSD: uturn.c,v 1.9 2010/06/21 07:09:59 skrll Exp $  */
 
 /*     $OpenBSD: uturn.c,v 1.6 2007/12/29 01:26:14 kettenis Exp $      */
 
@@ -34,7 +34,13 @@
 #include <sys/systm.h>
 #include <sys/device.h>
 #include <sys/reboot.h>
+#include <sys/malloc.h>
+#include <sys/extent.h>
+#include <sys/mbuf.h>
 
+#include <uvm/uvm_extern.h>
+
+#include <machine/bus.h>
 #include <machine/iomod.h>
 #include <machine/autoconf.h>
 
@@ -99,7 +105,10 @@
 struct uturn_softc {
        device_t sc_dv;
 
+       bus_dma_tag_t sc_dmat;
        struct uturn_regs volatile *sc_regs;
+
+       struct hppa_bus_dma_tag sc_dmatag;
 };
 
 int    uturnmatch(device_t, cfdata_t, void *);
@@ -111,6 +120,35 @@
 
 extern struct cfdriver uturn_cd;
 
+int uturn_dmamap_create(void *, bus_size_t, int, bus_size_t, bus_size_t, int,
+    bus_dmamap_t *);
+void uturn_dmamap_destroy(void *, bus_dmamap_t);
+int uturn_dmamap_load(void *, bus_dmamap_t, void *, bus_size_t, struct proc *,
+    int);
+int uturn_dmamap_load_mbuf(void *, bus_dmamap_t, struct mbuf *, int);
+int uturn_dmamap_load_uio(void *, bus_dmamap_t, struct uio *, int);
+int uturn_dmamap_load_raw(void *, bus_dmamap_t, bus_dma_segment_t *, int,
+    bus_size_t, int);
+void uturn_dmamap_unload(void *, bus_dmamap_t);
+void uturn_dmamap_sync(void *, bus_dmamap_t, bus_addr_t, bus_size_t, int);
+int uturn_dmamem_alloc(void *, bus_size_t, bus_size_t, bus_size_t,
+    bus_dma_segment_t *, int, int *, int);
+void uturn_dmamem_free(void *, bus_dma_segment_t *, int);
+int uturn_dmamem_map(void *, bus_dma_segment_t *, int, size_t, void **, int);
+void uturn_dmamem_unmap(void *, void *, size_t);
+paddr_t uturn_dmamem_mmap(void *, bus_dma_segment_t *, int, off_t, int, int);
+
+const struct hppa_bus_dma_tag uturn_dmat = {
+       NULL,
+       uturn_dmamap_create, uturn_dmamap_destroy,
+       uturn_dmamap_load, uturn_dmamap_load_mbuf,
+       uturn_dmamap_load_uio, uturn_dmamap_load_raw,
+       uturn_dmamap_unload, uturn_dmamap_sync,
+
+       uturn_dmamem_alloc, uturn_dmamem_free, uturn_dmamem_map,
+       uturn_dmamem_unmap, uturn_dmamem_mmap
+};
+
 int
 uturnmatch(device_t parent, cfdata_t cf, void *aux)
 {
@@ -134,6 +172,7 @@
        struct confargs *ca = aux, nca;
        struct uturn_softc *sc = device_private(self);
        bus_space_handle_t ioh;
+       volatile struct uturn_regs *r;
 
        if (bus_space_map(ca->ca_iot, ca->ca_hpa, IOMOD_HPASIZE, 0, &ioh)) {
                aprint_error(": can't map IO space\n");
@@ -141,13 +180,20 @@
        }
 
        sc->sc_dv = self;
-       sc->sc_regs = (struct uturn_regs *)ca->ca_hpa;
+       sc->sc_dmat = ca->ca_dmatag;
+       sc->sc_regs = r = bus_space_vaddr(ca->ca_iot, ioh);
+
+       aprint_normal(": %x-%x", r->io_io_low << 16, r->io_io_high << 16);
+       aprint_normal(": %x-%x", r->io_io_low_hv << 16, r->io_io_high_hv << 16);
 
        aprint_normal(": %s rev %d\n",
            ca->ca_type.iodc_revision < 0x10 ? "U2" : "UTurn",
            ca->ca_type.iodc_revision & 0xf);
 
-       ((struct iomod *)ioh)->io_control = UTURN_REAL_MODE;
+       r->io_control = UTURN_REAL_MODE;
+
+       sc->sc_dmatag = uturn_dmat;
+       sc->sc_dmatag._cookie = sc;
 
        /*
         * U2/UTurn is actually a combination of an Upper Bus Converter (UBC)
@@ -157,6 +203,7 @@
         */
        nca = *ca;
        nca.ca_hpabase = 0;
+       nca.ca_dmatag = &sc->sc_dmatag;
        nca.ca_nmodules = MAXMODBUS - 1;
        pdc_scanbus(self, &nca, uturn_callback);
 
@@ -172,7 +219,7 @@
 
        case HPPA_BOARD_HP800D:
        case HPPA_BOARD_HP821:
-               nca.ca_hpabase = ((struct iomod *)ioh)->io_io_low << 16;
+               nca.ca_hpabase = r->io_io_low << 16;
                pdc_scanbus(self, &nca, uturn_callback);
                break;
        default:
@@ -186,3 +233,223 @@
 
        config_found_sm_loc(self, "gedoens", NULL, ca, mbprint, mbsubmatch);
 }
+
+
+int
+uturn_dmamap_create(void *v, bus_size_t size, int nsegments, 
+    bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamap)
+{
+       struct uturn_softc *sc = v;
+       int err;
+
+       DPRINTF(("%s: size %lx nsegs %d maxsegsz %lx boundary %lx flags %x\n",
+           __func__, size, nsegments, maxsegsz, boundary, flags));
+       err = bus_dmamap_create(sc->sc_dmat, size, nsegments, maxsegsz,
+           boundary, flags, dmamap);
+
+       return err;
+}
+
+void
+uturn_dmamap_destroy(void *v, bus_dmamap_t map)
+{
+       struct uturn_softc *sc = v;
+
+       DPRINTF(("%s: map %p\n", __func__, map));
+
+       bus_dmamap_destroy(sc->sc_dmat, map);
+}
+
+
+int
+uturn_dmamap_load(void *v, bus_dmamap_t map, void *addr, bus_size_t size,
+    struct proc *p, int flags)
+{
+       struct uturn_softc *sc = v;
+       int err;
+       int i;
+       int d = 0;
+
+       DPRINTF(("%s: map %p addr %p size %lx proc %p flags %x\n", __func__,
+           map, addr, size, p, flags));
+
+       err = bus_dmamap_load(sc->sc_dmat, map, addr, size, p, flags);
+
+       DPRINTF(("%s: nsegs %2d dm_mapsize %lx\n", __func__, map->dm_nsegs,
+           map->dm_mapsize));
+       for (i = 0; i < map->dm_nsegs; i++) {
+               DPRINTF(("%s: seg %2d ds_addr %lx _ds_va %lx\n", __func__, i,
+                   map->dm_segs[i].ds_addr, map->dm_segs[i]._ds_va)); 
+               if (map->dm_segs[i].ds_addr != map->dm_segs[i]._ds_va)
+                       d = 1;
+       }
+       DPRINTF(("%s:\n", __func__));
+       if (uturndebug && d)
+               Debugger();
+
+       return err;
+}
+
+
+int
+uturn_dmamap_load_mbuf(void *v, bus_dmamap_t map, struct mbuf *m, int flags)
+{
+       struct uturn_softc *sc = v;
+       int err;
+       int i;
+
+       DPRINTF(("%s: map %p mbuf %p flags %x\n", __func__, map, m, flags));
+
+       err = bus_dmamap_load_mbuf(sc->sc_dmat, map, m, flags);
+
+       DPRINTF(("%s: nsegs %2d dm_mapsize %lx\n", __func__, map->dm_nsegs,
+           map->dm_mapsize));
+       for (i = 0; i < map->dm_nsegs; i++)
+               DPRINTF(("%s: seg %2d ds_addr %lx _ds_va %lx\n", __func__, i,
+                   map->dm_segs[i].ds_addr, map->dm_segs[i]._ds_va)); 
+
+       return err;
+}
+
+
+int
+uturn_dmamap_load_uio(void *v, bus_dmamap_t map, struct uio *uio, int flags)
+{
+       struct uturn_softc *sc = v;
+       int ret;
+       int i;
+
+       ret = bus_dmamap_load_uio(sc->sc_dmat, map, uio, flags);
+       DPRINTF(("%s: nsegs %2d dm_mapsize %lx\n", __func__, map->dm_nsegs,
+           map->dm_mapsize));
+       for (i = 0; i < map->dm_nsegs; i++)
+               DPRINTF(("%s: seg %2d ds_addr %lx _ds_va %lx\n", __func__, i,
+                   map->dm_segs[i].ds_addr, map->dm_segs[i]._ds_va)); 
+
+       return ret;
+}
+
+
+int
+uturn_dmamap_load_raw(void *v, bus_dmamap_t map, bus_dma_segment_t *segs,
+    int nsegs, bus_size_t size, int flags)
+{
+
+       return 0;
+}
+
+void
+uturn_dmamap_unload(void *v, bus_dmamap_t map)
+{
+       struct uturn_softc *sc = v;
+
+       DPRINTF(("%s: map %p\n", __func__, map));
+
+       bus_dmamap_unload(sc->sc_dmat, map);
+}
+
+
+void
+uturn_dmamap_sync(void *v, bus_dmamap_t map, bus_addr_t off,
+    bus_size_t len, int ops)
+{
+       struct uturn_softc *sc = v;
+
+       DPRINTF(("%s: map %p off %lx len %lx ops %x\n", __func__, map, off,
+           len, ops));
+
+       bus_dmamap_sync(sc->sc_dmat, map, off, len, ops);
+}
+
+int
+uturn_dmamem_alloc(void *v, bus_size_t size, bus_size_t alignment,
+    bus_size_t boundary, bus_dma_segment_t *segs,
+    int nsegs, int *rsegs, int flags)
+{
+       struct pglist pglist;
+       struct vm_page *pg;
+
+       DPRINTF(("%s: size %lx algn %lx bndry %lx segs %p nsegs %d flags %x\n",
+           __func__, size, alignment, boundary, segs, nsegs, flags));
+
+       size = round_page(size);
+
+       TAILQ_INIT(&pglist);
+       if (uvm_pglistalloc(size, 0, -1, alignment, boundary,
+           &pglist, 1, (flags & BUS_DMA_NOWAIT) == 0))
+               return ENOMEM;
+
+       pg = TAILQ_FIRST(&pglist);
+       segs[0]._ds_va = segs[0].ds_addr = VM_PAGE_TO_PHYS(pg);
+       segs[0].ds_len = size;
+       *rsegs = 1;
+
+       TAILQ_FOREACH(pg, &pglist, pageq.queue) {
+               DPRINTF(("%s: pg %p (pa %lx)\n", __func__, pg, VM_PAGE_TO_PHYS(pg)));
+               pmap_changebit(pg, PTE_PROT(TLB_UNCACHEABLE), 0);
+       }
+       pmap_update(pmap_kernel());
+
+       return 0;
+}
+
+
+void
+uturn_dmamem_free(void *v, bus_dma_segment_t *segs, int nsegs)
+{
+       struct pglist pglist;
+       paddr_t pa, epa;
+
+       DPRINTF(("%s: segs %p nsegs %d\n", __func__, segs, nsegs));
+
+       TAILQ_INIT(&pglist);
+       for (; nsegs--; segs++) {
+               for (pa = segs->ds_addr, epa = pa + segs->ds_len;
+                   pa < epa; pa += PAGE_SIZE) {
+                       struct vm_page *pg = PHYS_TO_VM_PAGE(pa);
+
+                       KASSERT(pg != NULL);
+                       TAILQ_INSERT_TAIL(&pglist, pg, pageq.queue);
+                       pmap_changebit(pg, 0, PTE_PROT(TLB_UNCACHEABLE));



Home | Main Index | Thread Index | Old Index