From 51b546d0bb634f1ed6b54c4d73fa0edfcc219df8 Mon Sep 17 00:00:00 2001 From: thorpej Date: Sun, 25 Aug 2002 16:02:53 +0000 Subject: [PATCH] Move the DMA tag and DVMA map into the iommu_softc, and pass the iommu_softc in the DMA tag cookie. This gives us a chance of supporting systems (such as the Sun4d) which have multiple iommus. --- sys/arch/sparc/sparc/iommu.c | 116 ++++++++++++++------------------ sys/arch/sparc/sparc/iommuvar.h | 5 +- 2 files changed, 50 insertions(+), 71 deletions(-) diff --git a/sys/arch/sparc/sparc/iommu.c b/sys/arch/sparc/sparc/iommu.c index 9ad496af35ee..1f7318ffaff2 100644 --- a/sys/arch/sparc/sparc/iommu.c +++ b/sys/arch/sparc/sparc/iommu.c @@ -1,4 +1,4 @@ -/* $NetBSD: iommu.c,v 1.66 2002/08/23 02:53:12 thorpej Exp $ */ +/* $NetBSD: iommu.c,v 1.67 2002/08/25 16:02:53 thorpej Exp $ */ /* * Copyright (c) 1996 @@ -65,17 +65,15 @@ struct iommu_softc { bus_addr_t sc_dvmabase; iopte_t *sc_ptes; int sc_hasiocache; -}; -struct iommu_softc *iommu_sc;/*XXX*/ -int has_iocache; - /* * Note: operations on the extent map are being protected with * splhigh(), since we cannot predict at which interrupt priority * our clients will run. */ -struct extent *iommu_dvmamap; - + struct sparc_bus_dma_tag sc_dmatag; + struct extent *sc_dvmamap; +}; +static int has_iocache; /* autoconfiguration driver */ int iommu_print __P((void *, const char *)); @@ -109,27 +107,9 @@ int iommu_dmamem_map __P((bus_dma_tag_t tag, bus_dma_segment_t *segs, int nsegs, size_t size, caddr_t *kvap, int flags)); paddr_t iommu_dmamem_mmap __P((bus_dma_tag_t tag, bus_dma_segment_t *segs, int nsegs, off_t off, int prot, int flags)); -int iommu_dvma_alloc(bus_dmamap_t, vaddr_t, bus_size_t, int, - bus_addr_t *, bus_size_t *); +int iommu_dvma_alloc(struct iommu_softc *, bus_dmamap_t, vaddr_t, + bus_size_t, int, bus_addr_t *, bus_size_t *); - -struct sparc_bus_dma_tag iommu_dma_tag = { - NULL, - iommu_dmamap_create, - _bus_dmamap_destroy, - iommu_dmamap_load, - iommu_dmamap_load_mbuf, - iommu_dmamap_load_uio, - iommu_dmamap_load_raw, - iommu_dmamap_unload, - iommu_dmamap_sync, - - _bus_dmamem_alloc, - _bus_dmamem_free, - iommu_dmamem_map, - _bus_dmamem_unmap, - iommu_dmamem_mmap -}; /* * Print the location of some iommu-attached device (called just * before attaching that device). If `iommu' is not NULL, the @@ -173,6 +153,7 @@ iommu_attach(parent, self, aux) #if defined(SUN4M) struct iommu_softc *sc = (struct iommu_softc *)self; struct mainbus_attach_args *ma = aux; + struct sparc_bus_dma_tag *dmat = &sc->sc_dmatag; bus_space_handle_t bh; int node; int js1_implicit_iommu; @@ -183,15 +164,21 @@ iommu_attach(parent, self, aux) struct vm_page *m; vaddr_t va; - /* - * XXX there is only one iommu, for now -- do not know how to - * address children on others - */ - if (sc->sc_dev.dv_unit > 0) { - printf(" unsupported\n"); - return; - } - iommu_sc = sc; + dmat->_cookie = sc; + dmat->_dmamap_create = iommu_dmamap_create; + dmat->_dmamap_destroy = _bus_dmamap_destroy; + dmat->_dmamap_load = iommu_dmamap_load; + dmat->_dmamap_load_mbuf = iommu_dmamap_load_mbuf; + dmat->_dmamap_load_uio = iommu_dmamap_load_uio; + dmat->_dmamap_load_raw = iommu_dmamap_load_raw; + dmat->_dmamap_unload = iommu_dmamap_unload; + dmat->_dmamap_sync = iommu_dmamap_sync; + + dmat->_dmamem_alloc = _bus_dmamem_alloc; + dmat->_dmamem_free = _bus_dmamem_free; + dmat->_dmamem_map = iommu_dmamem_map; + dmat->_dmamem_unmap = _bus_dmamem_unmap; + dmat->_dmamem_mmap = iommu_dmamem_mmap; /* * JS1/OF device tree does not have an iommu node and sbus @@ -213,12 +200,8 @@ iommu_attach(parent, self, aux) * XXX struct iommureg is bigger than ra->ra_len; what are the * other fields for? */ - if (bus_space_map( - ma->ma_bustag, - ma->ma_paddr, - sizeof(struct iommureg), - 0, - &bh) != 0) { + if (bus_space_map(ma->ma_bustag, ma->ma_paddr, + sizeof(struct iommureg), 0, &bh) != 0) { printf("iommu_attach: cannot map registers\n"); return; } @@ -297,10 +280,10 @@ iommu_attach(parent, self, aux) sc->sc_pagesize, sc->sc_range >> 20); - iommu_dvmamap = extent_create("iommudvma", + sc->sc_dvmamap = extent_create("iommudvma", IOMMU_DVMA_BASE, IOMMU_DVMA_END, M_DEVBUF, 0, 0, EX_NOWAIT); - if (iommu_dvmamap == NULL) + if (sc->sc_dvmamap == NULL) panic("iommu: unable to allocate DVMA map"); /* @@ -316,7 +299,7 @@ iommu_attach(parent, self, aux) /* Propagate BUS & DMA tags */ ia.iom_bustag = ma->ma_bustag; - ia.iom_dmatag = &iommu_dma_tag; + ia.iom_dmatag = &sc->sc_dmatag; ia.iom_name = "sbus"; ia.iom_node = node; @@ -338,7 +321,7 @@ iommu_attach(parent, self, aux) /* Propagate BUS & DMA tags */ ia.iom_bustag = ma->ma_bustag; - ia.iom_dmatag = &iommu_dma_tag; + ia.iom_dmatag = &sc->sc_dmatag; ia.iom_node = node; @@ -412,12 +395,9 @@ iommu_copy_prom_entries(sc) } #endif -void -iommu_enter(dva, pa) - bus_addr_t dva; - paddr_t pa; +static void +iommu_enter(struct iommu_softc *sc, bus_addr_t dva, paddr_t pa) { - struct iommu_softc *sc = iommu_sc; int pte; /* This routine relies on the fact that sc->sc_pagesize == PAGE_SIZE */ @@ -435,14 +415,11 @@ iommu_enter(dva, pa) } /* - * iommu_clear: clears mappings created by iommu_enter + * iommu_remove: removes mappings created by iommu_enter */ -void -iommu_remove(dva, len) - bus_addr_t dva; - bus_size_t len; +static void +iommu_remove(struct iommu_softc *sc, bus_addr_t dva, bus_size_t len) { - struct iommu_softc *sc = iommu_sc; u_int pagesz = sc->sc_pagesize; bus_addr_t base = sc->sc_dvmabase; @@ -526,6 +503,7 @@ iommu_dmamap_create(t, size, nsegments, maxsegsz, boundary, flags, dmamp) int flags; bus_dmamap_t *dmamp; { + struct iommu_softc *sc = t->_cookie; bus_dmamap_t map; int error; @@ -539,8 +517,8 @@ iommu_dmamap_create(t, size, nsegments, maxsegsz, boundary, flags, dmamp) map->_dm_ex_end = D24_DVMA_END; } else { /* Enable allocations from the entire map */ - map->_dm_ex_start = iommu_dvmamap->ex_start; - map->_dm_ex_end = iommu_dvmamap->ex_end; + map->_dm_ex_start = sc->sc_dvmamap->ex_start; + map->_dm_ex_end = sc->sc_dvmamap->ex_end; } *dmamp = map; @@ -551,7 +529,8 @@ iommu_dmamap_create(t, size, nsegments, maxsegsz, boundary, flags, dmamp) * Internal routine to allocate space in the IOMMU map. */ int -iommu_dvma_alloc(map, va, len, flags, dvap, sgsizep) +iommu_dvma_alloc(sc, map, va, len, flags, dvap, sgsizep) + struct iommu_softc *sc; bus_dmamap_t map; vaddr_t va; bus_size_t len; @@ -578,7 +557,7 @@ iommu_dvma_alloc(map, va, len, flags, dvap, sgsizep) align = dvma_cachealign ? dvma_cachealign : map->_dm_align; s = splhigh(); - error = extent_alloc_subregion1(iommu_dvmamap, + error = extent_alloc_subregion1(sc->sc_dvmamap, map->_dm_ex_start, map->_dm_ex_end, sgsize, align, va & (align-1), map->_dm_boundary, @@ -603,6 +582,7 @@ iommu_dmamap_load(t, map, buf, buflen, p, flags) struct proc *p; int flags; { + struct iommu_softc *sc = t->_cookie; bus_size_t sgsize; bus_addr_t dva; vaddr_t va = (vaddr_t)buf; @@ -616,7 +596,7 @@ iommu_dmamap_load(t, map, buf, buflen, p, flags) map->dm_nsegs = 0; /* Allocate IOMMU resources */ - if ((error = iommu_dvma_alloc(map, va, buflen, flags, + if ((error = iommu_dvma_alloc(sc, map, va, buflen, flags, &dva, &sgsize)) != 0) return (error); @@ -643,7 +623,7 @@ iommu_dmamap_load(t, map, buf, buflen, p, flags) */ (void) pmap_extract(pmap, va, &pa); - iommu_enter(dva, pa); + iommu_enter(sc, dva, pa); dva += pagesz; va += pagesz; @@ -694,6 +674,7 @@ iommu_dmamap_load_raw(t, map, segs, nsegs, size, flags) bus_size_t size; int flags; { + struct iommu_softc *sc = t->_cookie; struct vm_page *m; paddr_t pa; bus_addr_t dva; @@ -705,7 +686,7 @@ iommu_dmamap_load_raw(t, map, segs, nsegs, size, flags) map->dm_nsegs = 0; /* Allocate IOMMU resources */ - if ((error = iommu_dvma_alloc(map, segs[0]._ds_va, size, + if ((error = iommu_dvma_alloc(sc, map, segs[0]._ds_va, size, flags, &dva, &sgsize)) != 0) return (error); @@ -727,7 +708,7 @@ iommu_dmamap_load_raw(t, map, segs, nsegs, size, flags) if (sgsize == 0) panic("iommu_dmamap_load_raw: size botch"); pa = VM_PAGE_TO_PHYS(m); - iommu_enter(dva, pa); + iommu_enter(sc, dva, pa); dva += pagesz; sgsize -= pagesz; } @@ -746,6 +727,7 @@ iommu_dmamap_unload(t, map) bus_dma_tag_t t; bus_dmamap_t map; { + struct iommu_softc *sc = t->_cookie; bus_dma_segment_t *segs = map->dm_segs; int nsegs = map->dm_nsegs; bus_addr_t dva; @@ -756,9 +738,9 @@ iommu_dmamap_unload(t, map) dva = segs[i].ds_addr & -PAGE_SIZE; len = segs[i]._ds_sgsize; - iommu_remove(dva, len); + iommu_remove(sc, dva, len); s = splhigh(); - error = extent_free(iommu_dvmamap, dva, len, EX_NOWAIT); + error = extent_free(sc->sc_dvmamap, dva, len, EX_NOWAIT); splx(s); if (error != 0) printf("warning: %ld of DVMA space lost\n", (long)len); diff --git a/sys/arch/sparc/sparc/iommuvar.h b/sys/arch/sparc/sparc/iommuvar.h index 02cc755b8aaf..8484613929f9 100644 --- a/sys/arch/sparc/sparc/iommuvar.h +++ b/sys/arch/sparc/sparc/iommuvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: iommuvar.h,v 1.6 2002/08/23 02:53:12 thorpej Exp $ */ +/* $NetBSD: iommuvar.h,v 1.7 2002/08/25 16:02:54 thorpej Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -50,7 +50,4 @@ struct iommu_attach_args { int iom_nreg; }; -void iommu_enter __P((bus_addr_t, paddr_t)); -void iommu_remove __P((bus_addr_t, bus_size_t)); - #endif /* _IOMMU_VAR_H */