Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/sparc64 Move the DVMA mapin/mapout functions from t...
details: https://anonhg.NetBSD.org/src/rev/49ea0d765e84
branches: trunk
changeset: 473802:49ea0d765e84
user: eeh <eeh%NetBSD.org@localhost>
date: Sun Jun 20 00:51:29 1999 +0000
description:
Move the DVMA mapin/mapout functions from the SBus driver to the iommu driver.
diffstat:
sys/arch/sparc64/dev/iommu.c | 209 +++++++++++++++++++++++++++++++++------
sys/arch/sparc64/dev/iommuvar.h | 5 +-
sys/arch/sparc64/dev/sbus.c | 184 +---------------------------------
sys/arch/sparc64/include/cpu.h | 5 +-
4 files changed, 185 insertions(+), 218 deletions(-)
diffs (truncated from 541 to 300 lines):
diff -r 04db33fc4b6c -r 49ea0d765e84 sys/arch/sparc64/dev/iommu.c
--- a/sys/arch/sparc64/dev/iommu.c Sun Jun 20 00:50:08 1999 +0000
+++ b/sys/arch/sparc64/dev/iommu.c Sun Jun 20 00:51:29 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: iommu.c,v 1.1 1999/06/04 13:48:48 mrg Exp $ */
+/* $NetBSD: iommu.c,v 1.2 1999/06/20 00:51:29 eeh Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -136,31 +136,18 @@
/* we want 8K pages */
is->is_cr = IOMMUCR_8KPG | IOMMUCR_EN;
-
- /* set the tsbsize and get the dvmabase */
- switch (tsbsize) {
- case 0:
- is->is_dvmabase = 0x1fffffff;
- is->is_cr |= IOMMUCR_TSB1K;
- break;
-
-#if 0
- /* XXX are these right? got the values from the linux driver */
- case 1:
- is->is_dvmabase = 0x3fffffff;
- is->is_cr |= IOMMUCR_TSB2K;
- break;
-
- case 2:
- is->is_dvmabase = 0x7fffffff;
- is->is_cr |= IOMMUCR_TSB4K;
- break;
-#endif
-
- default:
- panic("unknown tsbsize, fix me");
- }
-
+ /*
+ *
+ * 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 ^
+ * is->is_tsbsize entries, where each entry is 8 bytes. The start of
+ * the map can be calculated by (0xffffe000 << (8 + is->is_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.
+ */
+ is->is_dvmabase = IOTSB_VSTART(is->is_tsbsize) + NBPG;
is->is_tsbsize = tsbsize;
is->is_tsb = malloc(NBPG, M_DMAMAP, M_WAITOK); /* XXX */
is->is_ptsb = pmap_extract(pmap_kernel(), (vaddr_t)is->is_tsb);
@@ -194,18 +181,9 @@
/*
* 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 ^
- * is->is_tsbsize entries, where each entry is 8 bytes. The start of
- * the map can be calculated by (0xffffe000 << (8 + is->is_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.
*/
is->is_dvmamap = extent_create(name,
- IOTSB_VSTART(is->is_tsbsize) + NBPG, IOTSB_VEND,
+ is->is_dvmabase, IOTSB_VEND,
M_DEVBUF, 0, 0, EX_NOWAIT);
}
@@ -220,3 +198,162 @@
/* Enable diagnostics mode? */
bus_space_write_8(is->is_bustag, &is->is_sb->strbuf_ctl, 0, STRBUF_EN);
}
+
+/*
+ * Here are the iommu control routines.
+ */
+void
+iommu_enter(is, va, pa, flags)
+ struct iommu_state *is;
+ vaddr_t va;
+ int64_t pa;
+ int flags;
+{
+ int64_t tte;
+
+#ifdef DIAGNOSTIC
+ if (va < is->is_dvmabase)
+ panic("sbus_enter: va 0x%lx not in DVMA space",va);
+#endif
+
+ tte = MAKEIOTTE(pa, !(flags&BUS_DMA_NOWRITE), !(flags&BUS_DMA_NOCACHE),
+ !(flags&BUS_DMA_COHERENT));
+
+ /* Is the streamcache flush really needed? */
+ bus_space_write_8(is->is_bustag, &is->is_sb->strbuf_pgflush,
+ 0, va);
+ iommu_flush(is);
+#ifdef DEBUG
+ if (iommudebug & IDB_DVMA)
+ printf("Clearing TSB slot %d for va %p\n",
+ (int)IOTSBSLOT(va,is->is_tsbsize), va);
+#endif
+ is->is_tsb[IOTSBSLOT(va,is->is_tsbsize)] = tte;
+ bus_space_write_8(is->is_bustag, &is->is_iommu->iommu_flush,
+ 0, va);
+#ifdef DEBUG
+ if (iommudebug & IDB_DVMA)
+ printf("sbus_enter: va %lx pa %lx TSB[%lx]@%p=%lx\n",
+ va, (long)pa, IOTSBSLOT(va,is->is_tsbsize),
+ &is->is_tsb[IOTSBSLOT(va,is->is_tsbsize)],
+ (long)tte);
+#endif
+}
+
+/*
+ * iommu_remove: removes mappings created by iommu_enter
+ *
+ * Only demap from IOMMU if flag is set.
+ */
+void
+iommu_remove(is, va, len)
+ struct iommu_state *is;
+ vaddr_t va;
+ size_t len;
+{
+
+#ifdef DIAGNOSTIC
+ if (va < is->is_dvmabase)
+ panic("sbus_remove: va 0x%lx not in DVMA space", (long)va);
+ if ((long)(va + len) < (long)va)
+ panic("sbus_remove: va 0x%lx + len 0x%lx wraps",
+ (long) va, (long) len);
+ if (len & ~0xfffffff)
+ panic("sbus_remove: rediculous len 0x%lx", (long)len);
+#endif
+
+ va = trunc_page(va);
+ while (len > 0) {
+
+ /*
+ * Streaming buffer flushes:
+ *
+ * 1 Tell strbuf to flush by storing va to strbuf_pgflush
+ * If we're not on a cache line boundary (64-bits):
+ * 2 Store 0 in flag
+ * 3 Store pointer to flag in flushsync
+ * 4 wait till flushsync becomes 0x1
+ *
+ * If it takes more than .5 sec, something went wrong.
+ */
+#ifdef DEBUG
+ if (iommudebug & IDB_DVMA)
+ printf("sbus_remove: flushing va %p TSB[%lx]@%p=%lx, %lu bytes left\n",
+ (long)va, (long)IOTSBSLOT(va,is->is_tsbsize),
+ (long)&is->is_tsb[IOTSBSLOT(va,is->is_tsbsize)],
+ (long)(is->is_tsb[IOTSBSLOT(va,is->is_tsbsize)]),
+ (u_long)len);
+#endif
+ bus_space_write_8(is->is_bustag, &is->is_sb->strbuf_pgflush, 0, va);
+ if (len <= NBPG) {
+ iommu_flush(is);
+ len = 0;
+ } else len -= NBPG;
+#ifdef DEBUG
+ if (iommudebug & IDB_DVMA)
+ printf("sbus_remove: flushed va %p TSB[%lx]@%p=%lx, %lu bytes left\n",
+ (long)va, (long)IOTSBSLOT(va,is->is_tsbsize),
+ (long)&is->is_tsb[IOTSBSLOT(va,is->is_tsbsize)],
+ (long)(is->is_tsb[IOTSBSLOT(va,is->is_tsbsize)]),
+ (u_long)len);
+#endif
+ is->is_tsb[IOTSBSLOT(va,is->is_tsbsize)] = 0;
+ bus_space_write_8(is->is_bustag, &is->is_iommu->iommu_flush, 0, va);
+ va += NBPG;
+ }
+}
+
+int
+iommu_flush(is)
+ struct iommu_state *is;
+{
+ struct timeval cur, flushtimeout;
+
+#define BUMPTIME(t, usec) { \
+ register volatile struct timeval *tp = (t); \
+ register long us; \
+ \
+ tp->tv_usec = us = tp->tv_usec + (usec); \
+ if (us >= 1000000) { \
+ tp->tv_usec = us - 1000000; \
+ tp->tv_sec++; \
+ } \
+}
+
+ is->is_flush = 0;
+ membar_sync();
+ bus_space_write_8(is->is_bustag, &is->is_sb->strbuf_flushsync, 0, is->is_flushpa);
+ membar_sync();
+
+ microtime(&flushtimeout);
+ cur = flushtimeout;
+ BUMPTIME(&flushtimeout, 500000); /* 1/2 sec */
+
+#ifdef DEBUG
+ if (iommudebug & IDB_DVMA)
+ printf("sbus_flush: 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);
+#endif
+ /* Bypass non-coherent D$ */
+ while (!ldxa(is->is_flushpa, ASI_PHYS_CACHED) &&
+ ((cur.tv_sec <= flushtimeout.tv_sec) &&
+ (cur.tv_usec <= flushtimeout.tv_usec)))
+ microtime(&cur);
+
+#ifdef DIAGNOSTIC
+ if (!is->is_flush) {
+ printf("sbus_flush: flush timeout %p at %p\n", (long)is->is_flush,
+ (long)is->is_flushpa); /* panic? */
+#ifdef DDB
+ Debugger();
+#endif
+ }
+#endif
+#ifdef DEBUG
+ if (iommudebug & IDB_DVMA)
+ printf("sbus_flush: flushed\n");
+#endif
+ return (is->is_flush);
+}
diff -r 04db33fc4b6c -r 49ea0d765e84 sys/arch/sparc64/dev/iommuvar.h
--- a/sys/arch/sparc64/dev/iommuvar.h Sun Jun 20 00:50:08 1999 +0000
+++ b/sys/arch/sparc64/dev/iommuvar.h Sun Jun 20 00:51:29 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: iommuvar.h,v 1.1 1999/06/04 13:48:48 mrg Exp $ */
+/* $NetBSD: iommuvar.h,v 1.2 1999/06/20 00:51:29 eeh Exp $ */
/*
* Copyright (c) 1999 Matthew R. Green
@@ -55,5 +55,8 @@
/* interfaces for PCI/SBUS code */
void iommu_init __P((char *, struct iommu_state *, int));
void iommu_reset __P((struct iommu_state *));
+void iommu_enter __P((struct iommu_state *, vaddr_t, int64_t, int));
+void iommu_remove __P((struct iommu_state *, vaddr_t, size_t));
+int iommu_flush __P((struct iommu_state *));
#endif /* _SPARC64_DEV_IOMMUVAR_H_ */
diff -r 04db33fc4b6c -r 49ea0d765e84 sys/arch/sparc64/dev/sbus.c
--- a/sys/arch/sparc64/dev/sbus.c Sun Jun 20 00:50:08 1999 +0000
+++ b/sys/arch/sparc64/dev/sbus.c Sun Jun 20 00:51:29 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sbus.c,v 1.18 1999/06/07 05:28:03 eeh Exp $ */
+/* $NetBSD: sbus.c,v 1.19 1999/06/20 00:51:30 eeh Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -135,7 +135,6 @@
#endif
void sbusreset __P((int));
-int sbus_flush __P((struct sbus_softc *));
static bus_space_tag_t sbus_alloc_bustag __P((struct sbus_softc *));
static bus_dma_tag_t sbus_alloc_dmatag __P((struct sbus_softc *));
@@ -173,8 +172,6 @@
/*
* DVMA routines
*/
-void sbus_enter __P((struct sbus_softc *, vaddr_t, int64_t, int));
-void sbus_remove __P((struct sbus_softc *, vaddr_t, size_t));
int sbus_dmamap_load __P((bus_dma_tag_t, bus_dmamap_t, void *,
bus_size_t, struct proc *, int));
void sbus_dmamap_unload __P((bus_dma_tag_t, bus_dmamap_t));
@@ -550,165 +547,6 @@
}
/*
- * Here are the iommu control routines.
- */
-void
-sbus_enter(sc, va, pa, flags)
- struct sbus_softc *sc;
- vaddr_t va;
- int64_t pa;
- int flags;
-{
- int64_t tte;
-
-#ifdef DIAGNOSTIC
- if (va < sc->sc_is.is_dvmabase)
- panic("sbus_enter: va 0x%lx not in DVMA space",va);
-#endif
-
Home |
Main Index |
Thread Index |
Old Index