Module Name:    src
Committed By:   skrll
Date:           Mon Jun 21 07:09:59 UTC 2010

Modified Files:
        src/sys/arch/hp700/dev: uturn.c

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


To generate a diff of this commit:
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/hp700/dev/uturn.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/hp700/dev/uturn.c
diff -u src/sys/arch/hp700/dev/uturn.c:1.8 src/sys/arch/hp700/dev/uturn.c:1.9
--- src/sys/arch/hp700/dev/uturn.c:1.8	Fri Jun 18 06:30:53 2010
+++ src/sys/arch/hp700/dev/uturn.c	Mon Jun 21 07:09:59 2010
@@ -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));
+			pdcache(HPPA_SID_KERNEL, pa, PAGE_SIZE);
+			pdtlb(HPPA_SID_KERNEL, pa);
+		}
+	}
+	pmap_update(pmap_kernel());
+	uvm_pglistfree(&pglist);
+}
+
+
+int
+uturn_dmamem_map(void *v, bus_dma_segment_t *segs, int nsegs, size_t size,
+    void **kvap, int flags)
+{
+
+	DPRINTF(("%s: segs %p nsegs %d size %lx kvap %p flags %x: ", __func__,
+	    segs, nsegs, size, kvap, flags));
+
+	*kvap = (void *)segs[0].ds_addr;
+
+	DPRINTF((" kvap %p\n", *kvap));
+
+	return 0;
+}
+
+
+void
+uturn_dmamem_unmap(void *v, void *kva, size_t size)
+{
+
+	DPRINTF(("%s: kva %p size %zu\n", __func__, kva, size));
+}
+
+
+paddr_t
+uturn_dmamem_mmap(void *v, bus_dma_segment_t *segs, int nsegs, off_t off,
+    int prot, int flags)
+{
+	DPRINTF(("%s: segs %p nsegs %d off %llx prot %d flags %x", __func__,
+	    segs, nsegs, off, prot, flags));
+		 
+	return -1;
+}

Reply via email to