Manage both streaming caches on psycho/psycho+.
This commit is contained in:
parent
5893dbb3e5
commit
bb99dc52c7
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: iommu.c,v 1.41 2001/09/28 11:59:53 chs Exp $ */
|
||||
/* $NetBSD: iommu.c,v 1.42 2001/10/07 20:30:40 eeh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999, 2000 Matthew R. Green
|
||||
|
@ -142,8 +142,19 @@ int iommudebug = 0x0;
|
|||
#define DPRINTF(l, s)
|
||||
#endif
|
||||
|
||||
#define iommu_strbuf_flush(i,v) bus_space_write_8((i)->is_bustag, \
|
||||
(bus_space_handle_t)(u_long)&(i)->is_sb->strbuf_pgflush, 0, (v))
|
||||
#define iommu_strbuf_flush(i,v) do { \
|
||||
if ((i)->is_sb[0]) \
|
||||
bus_space_write_8((i)->is_bustag, \
|
||||
(bus_space_handle_t)(u_long) \
|
||||
&(i)->is_sb[0]->strbuf_pgflush, \
|
||||
0, (v)); \
|
||||
if ((i)->is_sb[1]) \
|
||||
bus_space_write_8((i)->is_bustag, \
|
||||
(bus_space_handle_t)(u_long) \
|
||||
&(i)->is_sb[1]->strbuf_pgflush, \
|
||||
0, (v)); \
|
||||
} while (0)
|
||||
|
||||
static int iommu_strbuf_flush_done __P((struct iommu_state *));
|
||||
|
||||
/*
|
||||
|
@ -231,8 +242,8 @@ iommu_init(name, is, tsbsize, iovabase)
|
|||
/*
|
||||
* Initialize streaming buffer, if it is there.
|
||||
*/
|
||||
if (is->is_sb)
|
||||
(void)pmap_extract(pmap_kernel(), (vaddr_t)&is->is_flush,
|
||||
if (is->is_sb[0] || is->is_sb[1])
|
||||
(void)pmap_extract(pmap_kernel(), (vaddr_t)&is->is_flush[0],
|
||||
(paddr_t *)&is->is_flushpa);
|
||||
|
||||
/*
|
||||
|
@ -263,27 +274,40 @@ iommu_reset(is)
|
|||
|
||||
/* Need to do 64-bit stores */
|
||||
bus_space_write_8(is->is_bustag,
|
||||
(bus_space_handle_t)(u_long)&is->is_iommu->iommu_tsb,
|
||||
0, is->is_ptsb);
|
||||
(bus_space_handle_t)(u_long)&is->is_iommu->iommu_tsb,
|
||||
0, is->is_ptsb);
|
||||
/* Enable IOMMU in diagnostic mode */
|
||||
bus_space_write_8(is->is_bustag,
|
||||
(bus_space_handle_t)(u_long)&is->is_iommu->iommu_cr, 0,
|
||||
is->is_cr|IOMMUCR_DE);
|
||||
(bus_space_handle_t)(u_long)&is->is_iommu->iommu_cr,
|
||||
0, is->is_cr|IOMMUCR_DE);
|
||||
|
||||
if (is->is_sb[0]) {
|
||||
|
||||
if (!is->is_sb)
|
||||
return;
|
||||
/* Enable diagnostics mode? */
|
||||
bus_space_write_8(is->is_bustag,
|
||||
(bus_space_handle_t)(u_long)&is->is_sb[0]->strbuf_ctl,
|
||||
0, STRBUF_EN);
|
||||
|
||||
/* Enable diagnostics mode? */
|
||||
bus_space_write_8(is->is_bustag,
|
||||
(bus_space_handle_t)(u_long)&is->is_sb->strbuf_ctl,
|
||||
0, STRBUF_EN);
|
||||
/* No streaming buffers? Disable them */
|
||||
if (bus_space_read_8(is->is_bustag,
|
||||
(bus_space_handle_t)(u_long)&is->is_sb[0]->strbuf_ctl,
|
||||
0) == 0)
|
||||
is->is_sb[0] = 0;
|
||||
}
|
||||
|
||||
/* No streaming buffers? Disable them */
|
||||
if (bus_space_read_8(is->is_bustag,
|
||||
(bus_space_handle_t)(u_long)&is->is_sb->strbuf_ctl,
|
||||
0) == 0)
|
||||
is->is_sb = 0;
|
||||
if (is->is_sb[1]) {
|
||||
|
||||
/* Enable diagnostics mode? */
|
||||
bus_space_write_8(is->is_bustag,
|
||||
(bus_space_handle_t)(u_long)&is->is_sb[1]->strbuf_ctl,
|
||||
0, STRBUF_EN);
|
||||
|
||||
/* No streaming buffers? Disable them */
|
||||
if (bus_space_read_8(is->is_bustag,
|
||||
(bus_space_handle_t)(u_long)&is->is_sb[1]->strbuf_ctl,
|
||||
0) == 0)
|
||||
is->is_sb[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -307,7 +331,7 @@ iommu_enter(is, va, pa, flags)
|
|||
(flags&BUS_DMA_STREAMING));
|
||||
|
||||
/* Is the streamcache flush really needed? */
|
||||
if (is->is_sb) {
|
||||
if (is->is_sb[0] || is->is_sb[1]) {
|
||||
iommu_strbuf_flush(is, va);
|
||||
iommu_strbuf_flush_done(is);
|
||||
}
|
||||
|
@ -372,7 +396,7 @@ iommu_remove(is, va, len)
|
|||
while (len > 0) {
|
||||
DPRINTF(IDB_IOMMU, ("iommu_remove: clearing TSB slot %d for va %p size %lx\n",
|
||||
(int)IOTSBSLOT(va,is->is_tsbsize), (void *)(u_long)va, (u_long)len));
|
||||
if (is->is_sb) {
|
||||
if (is->is_sb[0] || is->is_sb[0]) {
|
||||
DPRINTF(IDB_IOMMU, ("iommu_remove: flushing va %p TSB[%lx]@%p=%lx, %lu bytes left\n",
|
||||
(void *)(u_long)va, (long)IOTSBSLOT(va,is->is_tsbsize),
|
||||
(void *)(u_long)&is->is_tsb[IOTSBSLOT(va,is->is_tsbsize)],
|
||||
|
@ -417,7 +441,7 @@ iommu_strbuf_flush_done(is)
|
|||
} \
|
||||
}
|
||||
|
||||
if (!is->is_sb)
|
||||
if (!is->is_sb[0] && !is->is_sb[1])
|
||||
return (0);
|
||||
|
||||
/*
|
||||
|
@ -433,38 +457,51 @@ iommu_strbuf_flush_done(is)
|
|||
* went wrong.
|
||||
*/
|
||||
|
||||
is->is_flush = 0;
|
||||
membar_sync(); /* #StoreStore is prolly enuf. */
|
||||
bus_space_write_8(is->is_bustag, (bus_space_handle_t)(u_long)
|
||||
&is->is_sb->strbuf_flushsync, 0, is->is_flushpa);
|
||||
membar_sync(); /* Prolly not needed at all. */
|
||||
is->is_flush[0] = 1;
|
||||
is->is_flush[1] = 1;
|
||||
if (is->is_sb[0]) {
|
||||
is->is_flush[0] = 0;
|
||||
bus_space_write_8(is->is_bustag, (bus_space_handle_t)(u_long)
|
||||
&is->is_sb[0]->strbuf_flushsync, 0, is->is_flushpa);
|
||||
}
|
||||
if (is->is_sb[1]) {
|
||||
is->is_flush[0] = 1;
|
||||
bus_space_write_8(is->is_bustag, (bus_space_handle_t)(u_long)
|
||||
&is->is_sb[1]->strbuf_flushsync, 0, is->is_flushpa + 8);
|
||||
}
|
||||
|
||||
microtime(&flushtimeout);
|
||||
cur = flushtimeout;
|
||||
BUMPTIME(&flushtimeout, 500000); /* 1/2 sec */
|
||||
|
||||
DPRINTF(IDB_IOMMU, ("iommu_strbuf_flush_done: flush = %lx at va = %lx pa = %lx now=%lx:%lx until = %lx:%lx\n",
|
||||
(long)is->is_flush, (long)&is->is_flush,
|
||||
(long)is->is_flushpa, cur.tv_sec, cur.tv_usec,
|
||||
flushtimeout.tv_sec, flushtimeout.tv_usec));
|
||||
DPRINTF(IDB_IOMMU, ("iommu_strbuf_flush_done: flush = %lx,%lx "
|
||||
"at va = %lx pa = %lx now=%lx:%lx until = %lx:%lx\n",
|
||||
(long)is->is_flush[0], (long)is->is_flush[1],
|
||||
(long)&is->is_flush[0], (long)is->is_flushpa,
|
||||
cur.tv_sec, cur.tv_usec,
|
||||
flushtimeout.tv_sec, flushtimeout.tv_usec));
|
||||
|
||||
/* Bypass non-coherent D$ */
|
||||
while (!ldxa(is->is_flushpa, ASI_PHYS_CACHED) &&
|
||||
((cur.tv_sec <= flushtimeout.tv_sec) &&
|
||||
(cur.tv_usec <= flushtimeout.tv_usec)))
|
||||
while ((!ldxa(is->is_flushpa, ASI_PHYS_CACHED) ||
|
||||
!ldxa(is->is_flushpa + 8, ASI_PHYS_CACHED)) &&
|
||||
((cur.tv_sec <= flushtimeout.tv_sec) &&
|
||||
(cur.tv_usec <= flushtimeout.tv_usec)))
|
||||
microtime(&cur);
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (!ldxa(is->is_flushpa, ASI_PHYS_CACHED)) {
|
||||
printf("iommu_strbuf_flush_done: flush timeout %p at %p\n",
|
||||
(void *)(u_long)is->is_flush,
|
||||
(void *)(u_long)is->is_flushpa); /* panic? */
|
||||
if ((!ldxa(is->is_flushpa, ASI_PHYS_CACHED) ||
|
||||
!ldxa(is->is_flushpa + 8, ASI_PHYS_CACHED)) {
|
||||
printf("iommu_strbuf_flush_done: flush timeout %p,%p at %p\n",
|
||||
(void *)(u_long)is->is_flush[0],
|
||||
(void *)(u_long)is->is_flush[1],
|
||||
(void *)(u_long)is->is_flushpa); /* panic? */
|
||||
#ifdef DDB
|
||||
Debugger();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
DPRINTF(IDB_IOMMU, ("iommu_strbuf_flush_done: flushed\n"));
|
||||
return (is->is_flush);
|
||||
return (is->is_flush[0] && is->is_flush[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -938,7 +975,7 @@ iommu_dvmamap_sync(t, is, map, offset, len, ops)
|
|||
("iommu_dvmamap_sync: syncing va %p len %lu "
|
||||
"BUS_DMASYNC_POSTREAD\n", (void *)(u_long)va, (u_long)len));
|
||||
/* if we have a streaming buffer, flush it here first */
|
||||
if (is->is_sb)
|
||||
if (is->is_sb[0] || is->is_sb[1])
|
||||
while (len > 0) {
|
||||
DPRINTF(IDB_BUSDMA,
|
||||
("iommu_dvmamap_sync: flushing va %p, %lu "
|
||||
|
@ -957,7 +994,7 @@ iommu_dvmamap_sync(t, is, map, offset, len, ops)
|
|||
("iommu_dvmamap_sync: syncing va %p len %lu "
|
||||
"BUS_DMASYNC_PREWRITE\n", (void *)(u_long)va, (u_long)len));
|
||||
/* if we have a streaming buffer, flush it here first */
|
||||
if (is->is_sb)
|
||||
if (is->is_sb[0] || is->is_sb[1])
|
||||
while (len > 0) {
|
||||
DPRINTF(IDB_BUSDMA,
|
||||
("iommu_dvmamap_sync: flushing va %p, %lu "
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: iommuvar.h,v 1.8 2001/09/15 06:55:50 eeh Exp $ */
|
||||
/* $NetBSD: iommuvar.h,v 1.9 2001/10/07 20:30:41 eeh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999 Matthew R. Green
|
||||
|
@ -44,12 +44,12 @@ struct iommu_state {
|
|||
|
||||
paddr_t is_flushpa; /* used to flush the SBUS */
|
||||
/* Needs to be volatile or egcs optimizes away loads */
|
||||
volatile int64_t is_flush;
|
||||
volatile int64_t is_flush[2];
|
||||
|
||||
/* copies of our parents state, to allow us to be self contained */
|
||||
bus_space_tag_t is_bustag; /* our bus tag */
|
||||
struct iommureg *is_iommu; /* IOMMU registers */
|
||||
struct iommu_strbuf *is_sb; /* streaming buffer */
|
||||
struct iommu_strbuf *is_sb[2]; /* streaming buffer(s) */
|
||||
};
|
||||
|
||||
/* interfaces for PCI/SBUS code */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: psycho.c,v 1.38 2001/09/26 20:53:11 eeh Exp $ */
|
||||
/* $NetBSD: psycho.c,v 1.39 2001/10/07 20:30:41 eeh Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999, 2000 Matthew R. Green
|
||||
|
@ -455,6 +455,17 @@ found:
|
|||
*
|
||||
* For the moment, 32KB should be more than enough.
|
||||
*/
|
||||
sc->sc_is = malloc(sizeof(struct iommu_state),
|
||||
M_DEVBUF, M_NOWAIT);
|
||||
if (sc->sc_is == NULL)
|
||||
panic("psycho_attach: malloc iommu_state");
|
||||
|
||||
|
||||
sc->sc_is->is_sb[0] = 0;
|
||||
sc->sc_is->is_sb[1] = 0;
|
||||
if (PROM_getproplen(sc->sc_node, "no-streaming-cache") >= 0)
|
||||
sc->sc_is->is_sb[0] = &pci_ctl->pci_strbuf;
|
||||
|
||||
psycho_iommu_init(sc, 2);
|
||||
|
||||
sc->sc_configtag = psycho_alloc_config_tag(sc->sc_psycho_this);
|
||||
|
@ -472,6 +483,10 @@ found:
|
|||
sc->sc_is = osc->sc_is;
|
||||
sc->sc_configtag = osc->sc_configtag;
|
||||
sc->sc_configaddr = osc->sc_configaddr;
|
||||
|
||||
if (PROM_getproplen(sc->sc_node, "no-streaming-cache") >= 0)
|
||||
sc->sc_is->is_sb[1] = &pci_ctl->pci_strbuf;
|
||||
iommu_reset(sc->sc_is);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -685,26 +700,15 @@ psycho_iommu_init(sc, tsbsize)
|
|||
int tsbsize;
|
||||
{
|
||||
char *name;
|
||||
struct iommu_state *is;
|
||||
struct iommu_state *is = sc->sc_is;
|
||||
u_int32_t iobase = -1;
|
||||
int *vdma = NULL;
|
||||
int nitem;
|
||||
|
||||
is = malloc(sizeof(struct iommu_state), M_DEVBUF, M_NOWAIT);
|
||||
if (is == NULL)
|
||||
panic("psycho_iommu_init: malloc is");
|
||||
|
||||
sc->sc_is = is;
|
||||
|
||||
/* punch in our copies */
|
||||
is->is_bustag = sc->sc_bustag;
|
||||
is->is_iommu = &sc->sc_regs->psy_iommu;
|
||||
|
||||
if (PROM_getproplen(sc->sc_node, "no-streaming-cache") < 0)
|
||||
is->is_sb = 0;
|
||||
else
|
||||
is->is_sb = &sc->sc_regs->psy_iommu_strbuf;
|
||||
|
||||
/*
|
||||
* Separate the men from the boys. Get the `virtual-dma'
|
||||
* property for sabre and use that to make sure the damn
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: sbus.c,v 1.45 2001/09/26 20:53:11 eeh Exp $ */
|
||||
/* $NetBSD: sbus.c,v 1.46 2001/10/07 20:30:41 eeh Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -320,7 +320,8 @@ sbus_attach(parent, self, aux)
|
|||
/* punch in our copies */
|
||||
sc->sc_is.is_bustag = sc->sc_bustag;
|
||||
sc->sc_is.is_iommu = &sc->sc_sysio->sys_iommu;
|
||||
sc->sc_is.is_sb = &sc->sc_sysio->sys_strbuf;
|
||||
sc->sc_is.is_sb[0] = &sc->sc_sysio->sys_strbuf;
|
||||
sc->sc_is.is_sb[1] = NULL;
|
||||
|
||||
/* give us a nice name.. */
|
||||
name = (char *)malloc(32, M_DEVBUF, M_NOWAIT);
|
||||
|
|
Loading…
Reference in New Issue