Manage both streaming caches on psycho/psycho+.

This commit is contained in:
eeh 2001-10-07 20:30:40 +00:00
parent 5893dbb3e5
commit bb99dc52c7
4 changed files with 102 additions and 60 deletions

View File

@ -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 "

View File

@ -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 */

View File

@ -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

View File

@ -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);