summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2009-02-18 20:48:56 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2009-02-18 20:48:56 +0000
commita21e48ecc1227742fb0e02b4d8ee2342fb72b97c (patch)
treea2a4c4a63c4ef8bde6c1810da69c5b3c22bee4dd /sys
parent975a37533326b572d52e5b0c92855b5eedd3fb65 (diff)
Better bus_dmamap_sync() routine, lets vsbic(4) run on 68060 systems, so
let it attach on them now.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/mvme68k/dev/vsbic.c8
-rw-r--r--sys/arch/mvme68k/mvme68k/bus_dma.c70
2 files changed, 48 insertions, 30 deletions
diff --git a/sys/arch/mvme68k/dev/vsbic.c b/sys/arch/mvme68k/dev/vsbic.c
index b4f72b79d93..ba1c32c2147 100644
--- a/sys/arch/mvme68k/dev/vsbic.c
+++ b/sys/arch/mvme68k/dev/vsbic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vsbic.c,v 1.1 2009/02/17 22:28:41 miod Exp $ */
+/* $OpenBSD: vsbic.c,v 1.2 2009/02/18 20:48:53 miod Exp $ */
/*
* Copyright (c) 2008, 2009 Miodrag Vallat.
@@ -426,7 +426,7 @@ struct cfdriver vsbic_cd = {
struct scsi_adapter vsbic_swtch = {
vsbic_scsicmd,
- minphys
+ scsi_minphys
};
struct scsi_device vsbic_scsidev = {
@@ -448,10 +448,6 @@ vsbic_match(struct device *device, void *cf, void *args)
int rc;
uint8_t id;
- /* XXX does not work on 68060 yet, likely a cache handling bug */
- if (mmutype == MMU_68060)
- return 0;
-
if (bus_space_map(iot, ca->ca_paddr, MVME327_CSR_SIZE, 0, &ioh) != 0)
return 0;
diff --git a/sys/arch/mvme68k/mvme68k/bus_dma.c b/sys/arch/mvme68k/mvme68k/bus_dma.c
index fd5ae7f3920..cdb73e4fc75 100644
--- a/sys/arch/mvme68k/mvme68k/bus_dma.c
+++ b/sys/arch/mvme68k/mvme68k/bus_dma.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bus_dma.c,v 1.1 2009/02/17 22:28:41 miod Exp $ */
+/* $OpenBSD: bus_dma.c,v 1.2 2009/02/18 20:48:55 miod Exp $ */
/* $NetBSD: bus_dma.c,v 1.2 2001/06/10 02:31:25 briggs Exp $ */
/*-
@@ -55,7 +55,7 @@ int _bus_dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *,
int _bus_dmamem_alloc_range(bus_dma_tag_t, bus_size_t, bus_size_t,
bus_size_t, bus_dma_segment_t *, int, int *, int, paddr_t, paddr_t);
-void cachectl_pa(paddr_t, psize_t, int);
+int cachectl_pa(paddr_t, psize_t, int);
/*
* Common function for DMA map creation. May be called by bus-specific
@@ -426,11 +426,8 @@ bus_dmamap_sync(t, map, offset, len, op)
u_int nsegs;
bus_dma_segment_t *seg;
- if (op & BUS_DMASYNC_PREREAD)
- op = CC_PURGE;
- else if (op & BUS_DMASYNC_PREWRITE)
- op = CC_FLUSH;
- else
+ /* nothing to do for POSTWRITE */
+ if ((op & ~BUS_DMASYNC_POSTWRITE) == 0)
return;
nsegs = map->dm_nsegs;
@@ -447,7 +444,8 @@ bus_dmamap_sync(t, map, offset, len, op)
if (sublen > len)
sublen = len;
- cachectl_pa(addr, sublen, op);
+ if (cachectl_pa(addr, sublen, op) != 0)
+ break;
offset = 0;
len -= sublen;
@@ -680,49 +678,73 @@ _bus_dmamem_alloc_range(t, size, alignment, boundary, segs, nsegs, rsegs,
}
/*
- * A variant of cachectl(), but which directly takes physical addresses, and
- * only CC_PURGE or CC_FLUSH.
+ * Helper function for bus_dmamap_sync(). Returns nonzero if the whole
+ * cache has been affected.
*/
-void
-cachectl_pa(paddr_t pa, psize_t len, int req)
+int
+cachectl_pa(paddr_t pa, psize_t len, int op)
{
#if defined(M68040) || defined(M68060)
if (mmutype <= MMU_68040) {
int inc;
paddr_t end;
- if (len > 2 * PAGE_SIZE) {
+ /*
+ * 68040 and 68060 only have the ``write back and
+ * invalidate'' (flush) and ``invalidate'' cache operations.
+ *
+ * The logic is thus:
+ * BUS_DMASYNC_PREREAD: flush D$, purge I$
+ * BUS_DMASYNC_PREWRITE: flush D$ (only write back necessary)
+ * BUS_DMASYNC_POSTREAD: purge D$ and I$
+ */
+
+ /*
+ * If the size is larger than two pages, don't try
+ * to be smart and operate on the whole cache.
+ * Remember the largest L1 cache is 8KB anyway (on 68060).
+ */
+ if (len >= 2 * PAGE_SIZE) {
DCFA();
- return;
+ if (op & (BUS_DMASYNC_PREREAD | BUS_DMASYNC_POSTREAD))
+ ICPA();
+ return 1;
}
end = pa + len;
if (len <= 1024) {
- if (((pa | len) & 0x0f) != 0)
- req = CC_FLUSH;
pa = pa & ~0x0f;
inc = 16;
} else {
- if (((pa | len) & PAGE_MASK) != 0)
- req = CC_FLUSH;
pa = pa & ~PAGE_MASK;
inc = PAGE_SIZE;
}
do {
- if (req == CC_PURGE) {
+ if (op & (BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE)) {
+ if (inc == 16)
+ DCFL(pa);
+ else
+ DCFP(pa);
+ } else {
if (inc == 16)
DCPL(pa);
else
DCPP(pa);
- } else {
+ }
+ if (op & (BUS_DMASYNC_PREREAD | BUS_DMASYNC_POSTREAD)) {
if (inc == 16)
- DCFL(pa);
+ ICPL(pa);
else
- DCFP(pa);
+ ICPP(pa);
}
pa += inc;
} while (pa < end);
- } else
+
+ return 0;
+ }
#endif
- DCIA();
+
+ DCIA();
+ ICIA();
+ return 1;
}