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