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.
This commit is contained in:
parent
f54ddc3c17
commit
51b546d0bb
|
@ -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
|
* Copyright (c) 1996
|
||||||
|
@ -65,17 +65,15 @@ struct iommu_softc {
|
||||||
bus_addr_t sc_dvmabase;
|
bus_addr_t sc_dvmabase;
|
||||||
iopte_t *sc_ptes;
|
iopte_t *sc_ptes;
|
||||||
int sc_hasiocache;
|
int sc_hasiocache;
|
||||||
};
|
|
||||||
struct iommu_softc *iommu_sc;/*XXX*/
|
|
||||||
int has_iocache;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: operations on the extent map are being protected with
|
* Note: operations on the extent map are being protected with
|
||||||
* splhigh(), since we cannot predict at which interrupt priority
|
* splhigh(), since we cannot predict at which interrupt priority
|
||||||
* our clients will run.
|
* 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 */
|
/* autoconfiguration driver */
|
||||||
int iommu_print __P((void *, const char *));
|
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));
|
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,
|
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 nsegs, off_t off, int prot, int flags));
|
||||||
int iommu_dvma_alloc(bus_dmamap_t, vaddr_t, bus_size_t, int,
|
int iommu_dvma_alloc(struct iommu_softc *, bus_dmamap_t, vaddr_t,
|
||||||
bus_addr_t *, bus_size_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
|
* Print the location of some iommu-attached device (called just
|
||||||
* before attaching that device). If `iommu' is not NULL, the
|
* before attaching that device). If `iommu' is not NULL, the
|
||||||
|
@ -173,6 +153,7 @@ iommu_attach(parent, self, aux)
|
||||||
#if defined(SUN4M)
|
#if defined(SUN4M)
|
||||||
struct iommu_softc *sc = (struct iommu_softc *)self;
|
struct iommu_softc *sc = (struct iommu_softc *)self;
|
||||||
struct mainbus_attach_args *ma = aux;
|
struct mainbus_attach_args *ma = aux;
|
||||||
|
struct sparc_bus_dma_tag *dmat = &sc->sc_dmatag;
|
||||||
bus_space_handle_t bh;
|
bus_space_handle_t bh;
|
||||||
int node;
|
int node;
|
||||||
int js1_implicit_iommu;
|
int js1_implicit_iommu;
|
||||||
|
@ -183,15 +164,21 @@ iommu_attach(parent, self, aux)
|
||||||
struct vm_page *m;
|
struct vm_page *m;
|
||||||
vaddr_t va;
|
vaddr_t va;
|
||||||
|
|
||||||
/*
|
dmat->_cookie = sc;
|
||||||
* XXX there is only one iommu, for now -- do not know how to
|
dmat->_dmamap_create = iommu_dmamap_create;
|
||||||
* address children on others
|
dmat->_dmamap_destroy = _bus_dmamap_destroy;
|
||||||
*/
|
dmat->_dmamap_load = iommu_dmamap_load;
|
||||||
if (sc->sc_dev.dv_unit > 0) {
|
dmat->_dmamap_load_mbuf = iommu_dmamap_load_mbuf;
|
||||||
printf(" unsupported\n");
|
dmat->_dmamap_load_uio = iommu_dmamap_load_uio;
|
||||||
return;
|
dmat->_dmamap_load_raw = iommu_dmamap_load_raw;
|
||||||
}
|
dmat->_dmamap_unload = iommu_dmamap_unload;
|
||||||
iommu_sc = sc;
|
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
|
* 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
|
* XXX struct iommureg is bigger than ra->ra_len; what are the
|
||||||
* other fields for?
|
* other fields for?
|
||||||
*/
|
*/
|
||||||
if (bus_space_map(
|
if (bus_space_map(ma->ma_bustag, ma->ma_paddr,
|
||||||
ma->ma_bustag,
|
sizeof(struct iommureg), 0, &bh) != 0) {
|
||||||
ma->ma_paddr,
|
|
||||||
sizeof(struct iommureg),
|
|
||||||
0,
|
|
||||||
&bh) != 0) {
|
|
||||||
printf("iommu_attach: cannot map registers\n");
|
printf("iommu_attach: cannot map registers\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -297,10 +280,10 @@ iommu_attach(parent, self, aux)
|
||||||
sc->sc_pagesize,
|
sc->sc_pagesize,
|
||||||
sc->sc_range >> 20);
|
sc->sc_range >> 20);
|
||||||
|
|
||||||
iommu_dvmamap = extent_create("iommudvma",
|
sc->sc_dvmamap = extent_create("iommudvma",
|
||||||
IOMMU_DVMA_BASE, IOMMU_DVMA_END,
|
IOMMU_DVMA_BASE, IOMMU_DVMA_END,
|
||||||
M_DEVBUF, 0, 0, EX_NOWAIT);
|
M_DEVBUF, 0, 0, EX_NOWAIT);
|
||||||
if (iommu_dvmamap == NULL)
|
if (sc->sc_dvmamap == NULL)
|
||||||
panic("iommu: unable to allocate DVMA map");
|
panic("iommu: unable to allocate DVMA map");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -316,7 +299,7 @@ iommu_attach(parent, self, aux)
|
||||||
|
|
||||||
/* Propagate BUS & DMA tags */
|
/* Propagate BUS & DMA tags */
|
||||||
ia.iom_bustag = ma->ma_bustag;
|
ia.iom_bustag = ma->ma_bustag;
|
||||||
ia.iom_dmatag = &iommu_dma_tag;
|
ia.iom_dmatag = &sc->sc_dmatag;
|
||||||
|
|
||||||
ia.iom_name = "sbus";
|
ia.iom_name = "sbus";
|
||||||
ia.iom_node = node;
|
ia.iom_node = node;
|
||||||
|
@ -338,7 +321,7 @@ iommu_attach(parent, self, aux)
|
||||||
|
|
||||||
/* Propagate BUS & DMA tags */
|
/* Propagate BUS & DMA tags */
|
||||||
ia.iom_bustag = ma->ma_bustag;
|
ia.iom_bustag = ma->ma_bustag;
|
||||||
ia.iom_dmatag = &iommu_dma_tag;
|
ia.iom_dmatag = &sc->sc_dmatag;
|
||||||
|
|
||||||
ia.iom_node = node;
|
ia.iom_node = node;
|
||||||
|
|
||||||
|
@ -412,12 +395,9 @@ iommu_copy_prom_entries(sc)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
static void
|
||||||
iommu_enter(dva, pa)
|
iommu_enter(struct iommu_softc *sc, bus_addr_t dva, paddr_t pa)
|
||||||
bus_addr_t dva;
|
|
||||||
paddr_t pa;
|
|
||||||
{
|
{
|
||||||
struct iommu_softc *sc = iommu_sc;
|
|
||||||
int pte;
|
int pte;
|
||||||
|
|
||||||
/* This routine relies on the fact that sc->sc_pagesize == PAGE_SIZE */
|
/* 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
|
static void
|
||||||
iommu_remove(dva, len)
|
iommu_remove(struct iommu_softc *sc, bus_addr_t dva, bus_size_t len)
|
||||||
bus_addr_t dva;
|
|
||||||
bus_size_t len;
|
|
||||||
{
|
{
|
||||||
struct iommu_softc *sc = iommu_sc;
|
|
||||||
u_int pagesz = sc->sc_pagesize;
|
u_int pagesz = sc->sc_pagesize;
|
||||||
bus_addr_t base = sc->sc_dvmabase;
|
bus_addr_t base = sc->sc_dvmabase;
|
||||||
|
|
||||||
|
@ -526,6 +503,7 @@ iommu_dmamap_create(t, size, nsegments, maxsegsz, boundary, flags, dmamp)
|
||||||
int flags;
|
int flags;
|
||||||
bus_dmamap_t *dmamp;
|
bus_dmamap_t *dmamp;
|
||||||
{
|
{
|
||||||
|
struct iommu_softc *sc = t->_cookie;
|
||||||
bus_dmamap_t map;
|
bus_dmamap_t map;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
@ -539,8 +517,8 @@ iommu_dmamap_create(t, size, nsegments, maxsegsz, boundary, flags, dmamp)
|
||||||
map->_dm_ex_end = D24_DVMA_END;
|
map->_dm_ex_end = D24_DVMA_END;
|
||||||
} else {
|
} else {
|
||||||
/* Enable allocations from the entire map */
|
/* Enable allocations from the entire map */
|
||||||
map->_dm_ex_start = iommu_dvmamap->ex_start;
|
map->_dm_ex_start = sc->sc_dvmamap->ex_start;
|
||||||
map->_dm_ex_end = iommu_dvmamap->ex_end;
|
map->_dm_ex_end = sc->sc_dvmamap->ex_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
*dmamp = map;
|
*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.
|
* Internal routine to allocate space in the IOMMU map.
|
||||||
*/
|
*/
|
||||||
int
|
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;
|
bus_dmamap_t map;
|
||||||
vaddr_t va;
|
vaddr_t va;
|
||||||
bus_size_t len;
|
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;
|
align = dvma_cachealign ? dvma_cachealign : map->_dm_align;
|
||||||
|
|
||||||
s = splhigh();
|
s = splhigh();
|
||||||
error = extent_alloc_subregion1(iommu_dvmamap,
|
error = extent_alloc_subregion1(sc->sc_dvmamap,
|
||||||
map->_dm_ex_start, map->_dm_ex_end,
|
map->_dm_ex_start, map->_dm_ex_end,
|
||||||
sgsize, align, va & (align-1),
|
sgsize, align, va & (align-1),
|
||||||
map->_dm_boundary,
|
map->_dm_boundary,
|
||||||
|
@ -603,6 +582,7 @@ iommu_dmamap_load(t, map, buf, buflen, p, flags)
|
||||||
struct proc *p;
|
struct proc *p;
|
||||||
int flags;
|
int flags;
|
||||||
{
|
{
|
||||||
|
struct iommu_softc *sc = t->_cookie;
|
||||||
bus_size_t sgsize;
|
bus_size_t sgsize;
|
||||||
bus_addr_t dva;
|
bus_addr_t dva;
|
||||||
vaddr_t va = (vaddr_t)buf;
|
vaddr_t va = (vaddr_t)buf;
|
||||||
|
@ -616,7 +596,7 @@ iommu_dmamap_load(t, map, buf, buflen, p, flags)
|
||||||
map->dm_nsegs = 0;
|
map->dm_nsegs = 0;
|
||||||
|
|
||||||
/* Allocate IOMMU resources */
|
/* 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)
|
&dva, &sgsize)) != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
|
@ -643,7 +623,7 @@ iommu_dmamap_load(t, map, buf, buflen, p, flags)
|
||||||
*/
|
*/
|
||||||
(void) pmap_extract(pmap, va, &pa);
|
(void) pmap_extract(pmap, va, &pa);
|
||||||
|
|
||||||
iommu_enter(dva, pa);
|
iommu_enter(sc, dva, pa);
|
||||||
|
|
||||||
dva += pagesz;
|
dva += pagesz;
|
||||||
va += pagesz;
|
va += pagesz;
|
||||||
|
@ -694,6 +674,7 @@ iommu_dmamap_load_raw(t, map, segs, nsegs, size, flags)
|
||||||
bus_size_t size;
|
bus_size_t size;
|
||||||
int flags;
|
int flags;
|
||||||
{
|
{
|
||||||
|
struct iommu_softc *sc = t->_cookie;
|
||||||
struct vm_page *m;
|
struct vm_page *m;
|
||||||
paddr_t pa;
|
paddr_t pa;
|
||||||
bus_addr_t dva;
|
bus_addr_t dva;
|
||||||
|
@ -705,7 +686,7 @@ iommu_dmamap_load_raw(t, map, segs, nsegs, size, flags)
|
||||||
map->dm_nsegs = 0;
|
map->dm_nsegs = 0;
|
||||||
|
|
||||||
/* Allocate IOMMU resources */
|
/* 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)
|
flags, &dva, &sgsize)) != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
|
@ -727,7 +708,7 @@ iommu_dmamap_load_raw(t, map, segs, nsegs, size, flags)
|
||||||
if (sgsize == 0)
|
if (sgsize == 0)
|
||||||
panic("iommu_dmamap_load_raw: size botch");
|
panic("iommu_dmamap_load_raw: size botch");
|
||||||
pa = VM_PAGE_TO_PHYS(m);
|
pa = VM_PAGE_TO_PHYS(m);
|
||||||
iommu_enter(dva, pa);
|
iommu_enter(sc, dva, pa);
|
||||||
dva += pagesz;
|
dva += pagesz;
|
||||||
sgsize -= pagesz;
|
sgsize -= pagesz;
|
||||||
}
|
}
|
||||||
|
@ -746,6 +727,7 @@ iommu_dmamap_unload(t, map)
|
||||||
bus_dma_tag_t t;
|
bus_dma_tag_t t;
|
||||||
bus_dmamap_t map;
|
bus_dmamap_t map;
|
||||||
{
|
{
|
||||||
|
struct iommu_softc *sc = t->_cookie;
|
||||||
bus_dma_segment_t *segs = map->dm_segs;
|
bus_dma_segment_t *segs = map->dm_segs;
|
||||||
int nsegs = map->dm_nsegs;
|
int nsegs = map->dm_nsegs;
|
||||||
bus_addr_t dva;
|
bus_addr_t dva;
|
||||||
|
@ -756,9 +738,9 @@ iommu_dmamap_unload(t, map)
|
||||||
dva = segs[i].ds_addr & -PAGE_SIZE;
|
dva = segs[i].ds_addr & -PAGE_SIZE;
|
||||||
len = segs[i]._ds_sgsize;
|
len = segs[i]._ds_sgsize;
|
||||||
|
|
||||||
iommu_remove(dva, len);
|
iommu_remove(sc, dva, len);
|
||||||
s = splhigh();
|
s = splhigh();
|
||||||
error = extent_free(iommu_dvmamap, dva, len, EX_NOWAIT);
|
error = extent_free(sc->sc_dvmamap, dva, len, EX_NOWAIT);
|
||||||
splx(s);
|
splx(s);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
printf("warning: %ld of DVMA space lost\n", (long)len);
|
printf("warning: %ld of DVMA space lost\n", (long)len);
|
||||||
|
|
|
@ -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.
|
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||||
|
@ -50,7 +50,4 @@ struct iommu_attach_args {
|
||||||
int iom_nreg;
|
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 */
|
#endif /* _IOMMU_VAR_H */
|
||||||
|
|
Loading…
Reference in New Issue