summaryrefslogtreecommitdiff
path: root/sys/arch/sparc64/dev/iommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/sparc64/dev/iommu.c')
-rw-r--r--sys/arch/sparc64/dev/iommu.c44
1 files changed, 37 insertions, 7 deletions
diff --git a/sys/arch/sparc64/dev/iommu.c b/sys/arch/sparc64/dev/iommu.c
index 529fb42e027..97366a664b0 100644
--- a/sys/arch/sparc64/dev/iommu.c
+++ b/sys/arch/sparc64/dev/iommu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: iommu.c,v 1.13 2002/03/07 17:58:24 jason Exp $ */
+/* $OpenBSD: iommu.c,v 1.14 2002/03/12 19:41:05 jason Exp $ */
/* $NetBSD: iommu.c,v 1.47 2002/02/08 20:03:45 eeh Exp $ */
/*
@@ -83,6 +83,7 @@ int iommu_dvmamap_sync_seg(bus_dma_tag_t, struct iommu_state *,
} while (0)
static int iommu_strbuf_flush_done __P((struct iommu_state *));
+int64_t iommu_tsb_entry __P((struct iommu_state *, vaddr_t));
static int iommu_tv_comp(struct timeval *, struct timeval *);
/*
@@ -294,6 +295,27 @@ iommu_extract(is, dva)
}
/*
+ * Fetch a tsb entry with some sanity checking.
+ */
+int64_t
+iommu_tsb_entry(is, dva)
+ struct iommu_state *is;
+ vaddr_t dva;
+{
+ int64_t tte;
+
+ if (dva < is->is_dvmabase && dva >= is->is_dvmaend)
+ panic("invalid dva: %llx", (long long)dva);
+
+ tte = is->is_tsb[IOTSBSLOT(dva,is->is_tsbsize)];
+
+ if ((tte & IOTTE_V) == 0)
+ panic("iommu_tsb_entry: invalid entry %llx\n", (long long)dva);
+
+ return (tte);
+}
+
+/*
* iommu_remove: removes mappings created by iommu_enter
*
* Only demap from IOMMU if flag is set.
@@ -980,6 +1002,10 @@ iommu_dvmamap_sync(t, is, map, offset, len, ops)
iommu_strbuf_flush_done(is);
}
+/*
+ * Flush an individual dma segment, returns non-zero if the streaming buffers
+ * need flushing afterwards.
+ */
int
iommu_dvmamap_sync_seg(t, is, seg, offset, len, ops)
bus_dma_tag_t t;
@@ -1015,11 +1041,13 @@ iommu_dvmamap_sync_seg(t, is, seg, offset, len, ops)
DPRINTF(IDB_BUSDMA,
("iommu_dvmamap_sync_seg: flushing va %p, %lu "
"bytes left\n", (void *)(u_long)va, (u_long)len));
- iommu_strbuf_flush(is, va);
- if (len <= NBPG) {
+ if (iommu_tsb_entry(is, va) & IOTTE_STREAM) {
+ iommu_strbuf_flush(is, va);
needsflush = 1;
+ }
+ if (len <= NBPG)
len = 0;
- } else
+ else
len -= NBPG;
va += NBPG;
}
@@ -1034,11 +1062,13 @@ iommu_dvmamap_sync_seg(t, is, seg, offset, len, ops)
DPRINTF(IDB_BUSDMA,
("iommu_dvmamap_sync_seg: flushing va %p, %lu "
"bytes left\n", (void *)(u_long)va, (u_long)len));
- iommu_strbuf_flush(is, va);
- if (len <= NBPG) {
+ if (iommu_tsb_entry(is, va) & IOTTE_STREAM) {
+ iommu_strbuf_flush(is, va);
needsflush = 1;
+ }
+ if (len <= NBPG)
len = 0;
- } else
+ else
len -= NBPG;
va += NBPG;
}