Well, looks like the MI allocsys() broke the dvmamap, so instead of using a
single map move it to the bus controller driver so each bus can handle its own IOMMU without conflicts.
This commit is contained in:
parent
bb0f8ef559
commit
60b89ebf96
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: sbus.c,v 1.11 1999/03/26 23:41:36 mycroft Exp $ */
|
||||
/* $NetBSD: sbus.c,v 1.12 1999/05/22 20:33:56 eeh Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
@ -86,6 +86,7 @@
|
||||
#include "opt_ddb.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/extent.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
@ -307,9 +308,19 @@ sbus_attach(parent, self, aux)
|
||||
*
|
||||
* The sun4u iommu is part of the SBUS controller so we will
|
||||
* deal with it here. We could try to fake a device node so
|
||||
* we can eventually share it with the PCI bus run by psyco,
|
||||
* we can eventually share it with the PCI bus run by psycho,
|
||||
* but I don't want to get into that sort of cruft.
|
||||
*
|
||||
* First we need to allocate a IOTSB. Problem is that the IOMMU
|
||||
* can only access the IOTSB by physical address, so all the
|
||||
* pages must be contiguous. Luckily, the smallest IOTSB size
|
||||
* is one 8K page.
|
||||
*/
|
||||
#if 1
|
||||
sc->sc_tsbsize = 0;
|
||||
sc->sc_tsb = malloc(NBPG, M_DMAMAP, M_WAITOK);
|
||||
sc->sc_ptsb = pmap_extract(pmap_kernel(), (vaddr_t)sc->sc_tsb);
|
||||
#else
|
||||
|
||||
/*
|
||||
* All IOMMUs will share the same TSB which is allocated in pmap_bootstrap.
|
||||
@ -325,6 +336,7 @@ sbus_attach(parent, self, aux)
|
||||
sc->sc_tsb = iotsb;
|
||||
sc->sc_ptsb = iotsbp;
|
||||
}
|
||||
#endif
|
||||
#if 1
|
||||
/* Need to do 64-bit stores */
|
||||
bus_space_write_8(sc->sc_bustag, &sc->sc_sysio->sys_iommu.iommu_cr,
|
||||
@ -364,6 +376,22 @@ sbus_attach(parent, self, aux)
|
||||
stxa(&sc->sc_sysio->sys_strbuf.strbuf_ctl,ASI_NUCLEUS,STRBUF_EN);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Now all the hardware's working we need to allocate a dvma map.
|
||||
*
|
||||
* The IOMMU address space always ends at 0xffffe000, but the starting
|
||||
* address depends on the size of the map. The map size is 1024 * 2 ^
|
||||
* sc->sc_tsbsize entries, where each entry is 8 bytes. The start of
|
||||
* the map can be calculated by (0xffffe000 << (8 + sc->sc_tsbsize)).
|
||||
*
|
||||
* Note: the stupid IOMMU ignores the high bits of an address, so a
|
||||
* NULL DMA pointer will be translated by the first page of the IOTSB.
|
||||
* To trap bugs we'll skip the first entry in the IOTSB.
|
||||
*/
|
||||
sc->sc_dvmamap = extent_create("SBus dvma", /* XXXX should have instance number */
|
||||
IOTSB_VSTART(sc->sc_tsbsize) + NBPG, IOTSB_VEND,
|
||||
M_DEVBUF, 0, 0, EX_NOWAIT);
|
||||
|
||||
/*
|
||||
* Loop through ROM children, fixing any relative addresses
|
||||
* and then configuring each device.
|
||||
@ -579,7 +607,7 @@ sbusreset(sbus)
|
||||
}
|
||||
#if 1
|
||||
/* Reload iommu regs */
|
||||
bus_space_write_8(sc->ma_bustag, &sc->sc_sysio->sys_iommu.iommu_cr,
|
||||
bus_space_write_8(sc->sc_bustag, &sc->sc_sysio->sys_iommu.iommu_cr,
|
||||
0, (IOMMUCR_TSB1K|IOMMUCR_8KPG|IOMMUCR_EN));
|
||||
bus_space_write_8(sc->sc_bustag, &sc->sc_sysio->sys_iommu.iommu_tsb,
|
||||
0, sc->sc_ptsb);
|
||||
@ -621,6 +649,10 @@ sbus_enter(sc, va, pa, flags)
|
||||
stxa(&(sc->sc_sysio->sys_strbuf.strbuf_pgflush), ASI_NUCLEUS, va);
|
||||
#endif
|
||||
sbus_flush(sc);
|
||||
#ifdef DEBUG
|
||||
if (sbusdebug & SDB_DVMA)
|
||||
printf("Clearing TSB slot %d for va %p\n", (int)IOTSBSLOT(va,sc->sc_tsbsize), va);
|
||||
#endif
|
||||
sc->sc_tsb[IOTSBSLOT(va,sc->sc_tsbsize)] = tte;
|
||||
#if 1
|
||||
bus_space_write_8(sc->sc_bustag, &sc->sc_sysio->sys_iommu.iommu_flush,
|
||||
@ -950,7 +982,7 @@ sbus_alloc_bustag(sc)
|
||||
bzero(sbt, sizeof *sbt);
|
||||
sbt->cookie = sc;
|
||||
sbt->parent = sc->sc_bustag;
|
||||
sbt->type = ASI_PRIMARY;
|
||||
sbt->type = SBUS_BUS_SPACE;
|
||||
sbt->sparc_bus_map = _sbus_bus_map;
|
||||
sbt->sparc_bus_mmap = sbus_bus_mmap;
|
||||
sbt->sparc_intr_establish = sbus_intr_establish;
|
||||
@ -1000,10 +1032,11 @@ sbus_dmamap_load(t, map, buf, buflen, p, flags)
|
||||
struct proc *p;
|
||||
int flags;
|
||||
{
|
||||
int err;
|
||||
int err, s;
|
||||
bus_size_t sgsize;
|
||||
paddr_t curaddr;
|
||||
vaddr_t dvmaddr, vaddr = (vaddr_t)buf;
|
||||
u_long dvmaddr;
|
||||
vaddr_t vaddr = (vaddr_t)buf;
|
||||
pmap_t pmap;
|
||||
struct sbus_softc *sc = (struct sbus_softc *)t->_cookie;
|
||||
|
||||
@ -1014,9 +1047,59 @@ sbus_dmamap_load(t, map, buf, buflen, p, flags)
|
||||
#endif
|
||||
bus_dmamap_unload(t, map);
|
||||
}
|
||||
if ((err = bus_dmamap_load(t->_parent, map, buf, buflen, p, flags)))
|
||||
#if 1
|
||||
/*
|
||||
* Make sure that on error condition we return "no valid mappings".
|
||||
*/
|
||||
map->dm_nsegs = 0;
|
||||
|
||||
if (buflen > map->_dm_size)
|
||||
#ifdef DEBUG
|
||||
{
|
||||
printf("_bus_dmamap_load(): error %d > %d -- map size exceeded!\n", buflen, map->_dm_size);
|
||||
Debugger();
|
||||
return (EINVAL);
|
||||
}
|
||||
#else
|
||||
return (EINVAL);
|
||||
#endif
|
||||
|
||||
sgsize = round_page(buflen + ((int)vaddr & PGOFSET));
|
||||
|
||||
/*
|
||||
* XXX Need to implement "don't dma across this boundry".
|
||||
*/
|
||||
|
||||
s = splhigh();
|
||||
err = extent_alloc(sc->sc_dvmamap, sgsize, NBPG,
|
||||
map->_dm_boundary, EX_NOWAIT, (u_long *)&dvmaddr);
|
||||
splx(s);
|
||||
|
||||
if (err != 0)
|
||||
return (err);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (dvmaddr == (bus_addr_t)-1)
|
||||
{
|
||||
printf("_bus_dmamap_load(): dvmamap_alloc(%d, %x) failed!\n", sgsize, flags);
|
||||
Debugger();
|
||||
}
|
||||
#endif
|
||||
if (dvmaddr == (bus_addr_t)-1)
|
||||
return (ENOMEM);
|
||||
|
||||
/*
|
||||
* We always use just one segment.
|
||||
*/
|
||||
map->dm_mapsize = buflen;
|
||||
map->dm_nsegs = 1;
|
||||
map->dm_segs[0].ds_addr = dvmaddr + (vaddr & PGOFSET);
|
||||
map->dm_segs[0].ds_len = sgsize;
|
||||
|
||||
#else
|
||||
if ((err = bus_dmamap_load(t->_parent, map, buf, buflen, p, flags)))
|
||||
return (err);
|
||||
#endif
|
||||
if (p != NULL)
|
||||
pmap = p->p_vmspace->vm_map.pmap;
|
||||
else
|
||||
@ -1060,7 +1143,9 @@ sbus_dmamap_unload(t, map)
|
||||
bus_dmamap_t map;
|
||||
{
|
||||
vaddr_t addr;
|
||||
int len;
|
||||
int len, error, s;
|
||||
bus_addr_t dvmaddr;
|
||||
bus_size_t sgsize;
|
||||
struct sbus_softc *sc = (struct sbus_softc *)t->_cookie;
|
||||
|
||||
if (map->dm_nsegs != 1)
|
||||
@ -1075,7 +1160,25 @@ sbus_dmamap_unload(t, map)
|
||||
map, (long)addr, (long)len);
|
||||
#endif
|
||||
sbus_remove(sc, addr, len);
|
||||
#if 1
|
||||
dvmaddr = (map->dm_segs[0].ds_addr & ~PGOFSET);
|
||||
sgsize = map->dm_segs[0].ds_len;
|
||||
|
||||
/* Mark the mappings as invalid. */
|
||||
map->dm_mapsize = 0;
|
||||
map->dm_nsegs = 0;
|
||||
|
||||
/* Unmapping is bus dependent */
|
||||
s = splhigh();
|
||||
error = extent_free(sc->sc_dvmamap, dvmaddr, sgsize, EX_NOWAIT);
|
||||
splx(s);
|
||||
if (error != 0)
|
||||
printf("warning: %ld of DVMA space lost\n", (long)sgsize);
|
||||
|
||||
cache_flush((caddr_t)dvmaddr, (u_int) sgsize);
|
||||
#else
|
||||
bus_dmamap_unload(t->_parent, map);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -1177,11 +1280,11 @@ sbus_dmamem_alloc(t, size, alignment, boundary, segs, nsegs, rsegs, flags)
|
||||
int flags;
|
||||
{
|
||||
paddr_t curaddr;
|
||||
bus_addr_t dvmaddr;
|
||||
u_long dvmaddr;
|
||||
vm_page_t m;
|
||||
struct pglist *mlist;
|
||||
int error;
|
||||
int n;
|
||||
int n, s;
|
||||
struct sbus_softc *sc = (struct sbus_softc *)t->_cookie;
|
||||
|
||||
if ((error = bus_dmamem_alloc(t->_parent, size, alignment,
|
||||
@ -1192,12 +1295,24 @@ sbus_dmamem_alloc(t, size, alignment, boundary, segs, nsegs, rsegs, flags)
|
||||
* Allocate a DVMA mapping for our new memory.
|
||||
*/
|
||||
for (n=0; n<*rsegs; n++) {
|
||||
#if 1
|
||||
s = splhigh();
|
||||
if (extent_alloc(sc->sc_dvmamap, segs[0].ds_len, alignment,
|
||||
boundary, EX_NOWAIT, (u_long *)&dvmaddr)) {
|
||||
splx(s);
|
||||
/* Free what we got and exit */
|
||||
bus_dmamem_free(t->_parent, segs, nsegs);
|
||||
return (ENOMEM);
|
||||
}
|
||||
splx(s);
|
||||
#else
|
||||
dvmaddr = dvmamap_alloc(segs[0].ds_len, flags);
|
||||
if (dvmaddr == (bus_addr_t)-1) {
|
||||
/* Free what we got and exit */
|
||||
bus_dmamem_free(t->_parent, segs, nsegs);
|
||||
return (ENOMEM);
|
||||
}
|
||||
#endif
|
||||
segs[n].ds_addr = dvmaddr;
|
||||
size = segs[n].ds_len;
|
||||
mlist = segs[n]._ds_mlist;
|
||||
@ -1205,6 +1320,11 @@ sbus_dmamem_alloc(t, size, alignment, boundary, segs, nsegs, rsegs, flags)
|
||||
/* Map memory into DVMA space */
|
||||
for (m = mlist->tqh_first; m != NULL; m = m->pageq.tqe_next) {
|
||||
curaddr = VM_PAGE_TO_PHYS(m);
|
||||
#ifdef DEBUG
|
||||
if (sbusdebug & SDB_DVMA)
|
||||
printf("sbus_dmamem_alloc: map %p loading va %lx at pa %lx\n",
|
||||
(long)m, (long)dvmaddr, (long)(curaddr & ~(NBPG-1)));
|
||||
#endif
|
||||
sbus_enter(sc, dvmaddr, curaddr, flags);
|
||||
dvmaddr += PAGE_SIZE;
|
||||
}
|
||||
@ -1220,7 +1340,7 @@ sbus_dmamem_free(t, segs, nsegs)
|
||||
{
|
||||
vaddr_t addr;
|
||||
int len;
|
||||
int n;
|
||||
int n, s, error;
|
||||
struct sbus_softc *sc = (struct sbus_softc *)t->_cookie;
|
||||
|
||||
|
||||
@ -1228,7 +1348,15 @@ sbus_dmamem_free(t, segs, nsegs)
|
||||
addr = segs[n].ds_addr;
|
||||
len = segs[n].ds_len;
|
||||
sbus_remove(sc, addr, len);
|
||||
#if 1
|
||||
s = splhigh();
|
||||
error = extent_free(sc->sc_dvmamap, addr, len, EX_NOWAIT);
|
||||
splx(s);
|
||||
if (error != 0)
|
||||
printf("warning: %ld of DVMA space lost\n", (long)len);
|
||||
#else
|
||||
dvmamap_free(addr, len);
|
||||
#endif
|
||||
}
|
||||
bus_dmamem_free(t->_parent, segs, nsegs);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: sbusreg.h,v 1.3 1998/09/05 23:57:25 eeh Exp $ */
|
||||
/* $NetBSD: sbusreg.h,v 1.4 1999/05/22 20:33:56 eeh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
@ -251,13 +251,16 @@ struct sysioreg {
|
||||
#define IOTTE_C 0x0000000000000010LL /* Accesses to cacheable space */
|
||||
#define IOTTE_W 0x0000000000000002LL /* Writeable */
|
||||
|
||||
#define IOTSB_VEND 0xffffe000
|
||||
#define IOTSB_VSTART(sz) (u_int)(IOTSB_VEND << (PGSHIFT + (sz)))
|
||||
|
||||
#define MAKEIOTTE(pa,w,c,s) (((pa)&IOTTE_PAMASK)|((w)?IOTTE_W:0)|((c)?IOTTE_C:0)|((s)?IOTTE_STREAM:0)|(IOTTE_V|IOTTE_8K))
|
||||
#if 0
|
||||
/* This version generates a pointer to a int64_t */
|
||||
#define IOTSBSLOT(va,sz) ((((((vaddr_t)(va))-(((vaddr_t)0xff800000)<<(sz))))>>(13-3))&(~7))
|
||||
#define IOTSBSLOT(va,sz) ((((((vaddr_t)(va))-((vaddr_t)IOTSB_VSTART(sz))))>>(PGSHIFT-3))&(~7))
|
||||
#else
|
||||
/* Here we just try to create an array index */
|
||||
#define IOTSBSLOT(va,sz) ((u_int)((((((vaddr_t)(va))-(((vaddr_t)0xff800000)<<(sz))))>>(13))))
|
||||
#define IOTSBSLOT(va,sz) ((u_int)((((((vaddr_t)(va))-((vaddr_t)IOTSB_VSTART(sz))))>>(PGSHIFT))))
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: sbusvar.h,v 1.5 1998/09/05 23:57:25 eeh Exp $ */
|
||||
/* $NetBSD: sbusvar.h,v 1.6 1999/05/22 20:33:56 eeh Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
@ -113,7 +113,7 @@ struct sbus_softc {
|
||||
int sc_tsbsize;
|
||||
u_int sc_pagesize;
|
||||
u_int sc_dvmabase;
|
||||
int sc_hasiocache;
|
||||
struct extent *sc_dvmamap; /* DVMA map for this instance */
|
||||
int sc_ign; /* Interrupt group number for this sysio */
|
||||
|
||||
paddr_t sc_flushpa; /* used to flush the SBUS */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: autoconf.c,v 1.14 1999/04/25 16:18:46 eeh Exp $ */
|
||||
/* $NetBSD: autoconf.c,v 1.15 1999/05/22 20:33:55 eeh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996
|
||||
@ -95,7 +95,9 @@ int printspl = 0;
|
||||
* the machine.
|
||||
*/
|
||||
int cold; /* if 1, still working on cold-start */
|
||||
int fbnode; /* node ID of ROM's console frame buffer */
|
||||
int fbnode; /* node ID of ROM's framebuffer XXXX deprecated */
|
||||
int stdinnode; /* node ID of ROM's console input device */
|
||||
int stdoutnode; /* node ID of ROM's console output device */
|
||||
int optionsnode; /* node ID of ROM's options */
|
||||
|
||||
#ifdef KGDB
|
||||
|
Loading…
Reference in New Issue
Block a user