summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2007-06-21 20:17:13 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2007-06-21 20:17:13 +0000
commitb03519f8c6e8caccda6520217fb3537d1d063c4a (patch)
tree3ffa85787ef7a55040b36a3c7d5394a637c2162a /sys/arch
parent499eb788d359fe4e2415e514679969123e8dd6d2 (diff)
Extent sgi bus_dma to cope with different views of memory: non-contiguous
for the cpu, contiguous from different bases for devices. This allows memory above 256MB to be used with bus_dma (and we had really been lucky with the first few large-memory builds). Information about memory accesses taken from Linux.
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/mips64/conf/files.mips643
-rw-r--r--sys/arch/sgi/conf/files.sgi3
-rw-r--r--sys/arch/sgi/include/bus.h10
-rw-r--r--sys/arch/sgi/localbus/crimebus.h5
-rw-r--r--sys/arch/sgi/localbus/macebus.c31
-rw-r--r--sys/arch/sgi/pci/macepcibridge.c32
-rw-r--r--sys/arch/sgi/sgi/bus_dma.c (renamed from sys/arch/mips64/mips64/busdma.c)34
7 files changed, 92 insertions, 26 deletions
diff --git a/sys/arch/mips64/conf/files.mips64 b/sys/arch/mips64/conf/files.mips64
index c70c94557b8..3c3ed75da03 100644
--- a/sys/arch/mips64/conf/files.mips64
+++ b/sys/arch/mips64/conf/files.mips64
@@ -1,4 +1,4 @@
-# $OpenBSD: files.mips64,v 1.8 2007/06/18 21:46:41 deraadt Exp $
+# $OpenBSD: files.mips64,v 1.9 2007/06/21 20:17:12 miod Exp $
file arch/mips64/mips64/mem.c
file arch/mips64/mips64/process_machdep.c
@@ -8,7 +8,6 @@ file arch/mips64/mips64/vm_machdep.c
file arch/mips64/mips64/arcbios.c arcbios
file arch/mips64/mips64/clock.c
file arch/mips64/mips64/cpu.c
-file arch/mips64/mips64/busdma.c
file arch/mips64/mips64/interrupt.c
file arch/mips64/mips64/mainbus.c
file arch/mips64/mips64/pmap.c
diff --git a/sys/arch/sgi/conf/files.sgi b/sys/arch/sgi/conf/files.sgi
index d6404ef02f5..0b9fd20ada1 100644
--- a/sys/arch/sgi/conf/files.sgi
+++ b/sys/arch/sgi/conf/files.sgi
@@ -1,4 +1,4 @@
-# $OpenBSD: files.sgi,v 1.12 2007/06/18 21:46:41 deraadt Exp $
+# $OpenBSD: files.sgi,v 1.13 2007/06/21 20:17:12 miod Exp $
#
# maxpartitions must be first item in files.${ARCH}
#
@@ -10,6 +10,7 @@ maxusers 2 8 64
file arch/sgi/sgi/disksubr.c disk
file arch/sgi/sgi/autoconf.c
+file arch/sgi/sgi/bus_dma.c
file arch/sgi/sgi/conf.c
file arch/sgi/sgi/machdep.c
file arch/sgi/sgi/mutex.c
diff --git a/sys/arch/sgi/include/bus.h b/sys/arch/sgi/include/bus.h
index 1d84ced752b..4e191878a71 100644
--- a/sys/arch/sgi/include/bus.h
+++ b/sys/arch/sgi/include/bus.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bus.h,v 1.5 2006/05/27 00:29:55 krw Exp $ */
+/* $OpenBSD: bus.h,v 1.6 2007/06/21 20:17:12 miod Exp $ */
/*
* Copyright (c) 2003-2004 Opsycon AB Sweden. All rights reserved.
@@ -345,7 +345,13 @@ struct machine_bus_dma_tag {
void (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t);
paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *,
int, off_t, int, int);
- paddr_t dma_offs;
+
+ /*
+ * internal memory address translation information.
+ */
+ bus_addr_t (*_pa_to_device)(paddr_t);
+ paddr_t (*_device_to_pa)(bus_addr_t);
+ bus_addr_t _dma_mask;
};
#define bus_dmamap_create(t, s, n, m, b, f, p) \
diff --git a/sys/arch/sgi/localbus/crimebus.h b/sys/arch/sgi/localbus/crimebus.h
index 8eb35227c9b..67f7f7b4719 100644
--- a/sys/arch/sgi/localbus/crimebus.h
+++ b/sys/arch/sgi/localbus/crimebus.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: crimebus.h,v 1.5 2007/05/03 19:34:00 miod Exp $ */
+/* $OpenBSD: crimebus.h,v 1.6 2007/06/21 20:17:12 miod Exp $ */
/*
* Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se).
@@ -100,6 +100,9 @@
#define CRIME_MEM_BANK_128MB 0x100
#define CRIME_MAX_BANKS 8
+#define CRIME_MEMORY_OFFSET 0x40000000 /* 1GB */
+#define CRIME_MEMORY_MASK 0x3fffffff
+
#define CRIME_MEM_ERROR_STAT 0x0250
#define CRIME_MEM_ERROR_ADDR 0x0258
diff --git a/sys/arch/sgi/localbus/macebus.c b/sys/arch/sgi/localbus/macebus.c
index 93e50b71b8e..555275d380d 100644
--- a/sys/arch/sgi/localbus/macebus.c
+++ b/sys/arch/sgi/localbus/macebus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: macebus.c,v 1.24 2007/06/20 20:47:34 miod Exp $ */
+/* $OpenBSD: macebus.c,v 1.25 2007/06/21 20:17:12 miod Exp $ */
/*
* Copyright (c) 2000-2004 Opsycon AB (www.opsycon.se)
@@ -69,6 +69,9 @@ void macebus_do_pending_int(int);
intrmask_t macebus_iointr(intrmask_t, struct trap_frame *);
intrmask_t macebus_aux(intrmask_t, struct trap_frame *);
+bus_addr_t macebus_pa_to_device(paddr_t);
+paddr_t macebus_device_to_pa(bus_addr_t);
+
int maceticks; /* Time tracker for special events */
struct cfattach macebus_ca = {
@@ -121,7 +124,9 @@ struct machine_bus_dma_tag mace_bus_dma_tag = {
_dmamem_map,
_dmamem_unmap,
_dmamem_mmap,
- NULL
+ macebus_pa_to_device,
+ macebus_device_to_pa,
+ CRIME_MEMORY_MASK
};
/*
@@ -430,6 +435,28 @@ mace_space_region(bus_space_tag_t t, bus_space_handle_t bsh,
}
/*
+ * Macebus bus_dma helpers.
+ * Mace accesses memory contiguously at 0x40000000 onwards.
+ */
+
+bus_addr_t
+macebus_pa_to_device(paddr_t pa)
+{
+ return (pa | CRIME_MEMORY_OFFSET);
+}
+
+paddr_t
+macebus_device_to_pa(bus_addr_t addr)
+{
+ paddr_t pa = (paddr_t)addr & CRIME_MEMORY_MASK;
+
+ if (pa >= 256 * 1024 * 1024)
+ pa |= CRIME_MEMORY_OFFSET;
+
+ return (pa);
+}
+
+/*
* Macebus interrupt handler driver.
*/
diff --git a/sys/arch/sgi/pci/macepcibridge.c b/sys/arch/sgi/pci/macepcibridge.c
index ae9801c6e40..64830ea9f26 100644
--- a/sys/arch/sgi/pci/macepcibridge.c
+++ b/sys/arch/sgi/pci/macepcibridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: macepcibridge.c,v 1.11 2006/12/14 17:36:12 kettenis Exp $ */
+/* $OpenBSD: macepcibridge.c,v 1.12 2007/06/21 20:17:12 miod Exp $ */
/*
* Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se)
@@ -49,6 +49,7 @@
#include <dev/pci/pcivar.h>
#include <mips64/archtype.h>
+#include <sgi/localbus/crimebus.h>
#include <sgi/localbus/macebus.h>
#include <sgi/pci/macepcibrvar.h>
@@ -77,6 +78,8 @@ void *mace_pcibr_intr_establish(void *, pci_intr_handle_t,
int, int (*func)(void *), void *, char *);
void mace_pcibr_intr_disestablish(void *, void *);
+bus_addr_t mace_pcibr_pa_to_device(paddr_t);
+paddr_t mace_pcibr_device_to_pa(bus_addr_t);
struct cfattach macepcibr_ca = {
sizeof(struct mace_pcibr_softc), mace_pcibrmatch, mace_pcibrattach,
@@ -132,7 +135,9 @@ struct machine_bus_dma_tag pci_bus_dma_tag = {
_dmamem_map,
_dmamem_unmap,
_dmamem_mmap,
- NULL
+ mace_pcibr_pa_to_device,
+ mace_pcibr_device_to_pa,
+ CRIME_MEMORY_MASK
};
struct _perr_map {
@@ -239,7 +244,6 @@ mace_pcibrattach(struct device *parent, struct device *self, void *aux)
pba.pba_iot = sc->sc_io_bus_space;
pba.pba_memt = sc->sc_mem_bus_space;
pba.pba_dmat = malloc(sizeof(pci_bus_dma_tag), M_DEVBUF, M_NOWAIT);
- pci_bus_dma_tag.dma_offs = 0x00000000;
*pba.pba_dmat = pci_bus_dma_tag;
pba.pba_pc = &sc->sc_pc;
pba.pba_domain = pci_ndomains++;
@@ -563,3 +567,25 @@ mace_pcib_space_region(bus_space_tag_t t, bus_space_handle_t bsh,
*nbshp = bsh + offset;
return (0);
}
+
+/*
+ * Mace PCI bus_dma helpers.
+ * The PCI bus accesses memory contiguously at 0x00000000 onwards.
+ */
+
+bus_addr_t
+mace_pcibr_pa_to_device(paddr_t pa)
+{
+ return (pa & CRIME_MEMORY_MASK);
+}
+
+paddr_t
+mace_pcibr_device_to_pa(bus_addr_t addr)
+{
+ paddr_t pa = (paddr_t)addr & CRIME_MEMORY_MASK;
+
+ if (pa >= 256 * 1024 * 1024)
+ pa |= CRIME_MEMORY_OFFSET;
+
+ return (pa);
+}
diff --git a/sys/arch/mips64/mips64/busdma.c b/sys/arch/sgi/sgi/bus_dma.c
index 426130d7884..0a0fd0faca6 100644
--- a/sys/arch/mips64/mips64/busdma.c
+++ b/sys/arch/sgi/sgi/bus_dma.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: busdma.c,v 1.13 2007/05/30 19:44:26 miod Exp $ */
+/* $OpenBSD: bus_dma.c,v 1.1 2007/06/21 20:17:10 miod Exp $ */
/*
* Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -135,6 +135,7 @@ _dmamap_load(t, map, buf, buflen, p, flags)
lastaddr = ~0; /* XXX gcc */
bmask = ~(map->_dm_boundary - 1);
+ bmask &= t->_dma_mask;
saved_buflen = buflen;
for (first = 1, seg = 0; buflen > 0; ) {
@@ -167,7 +168,8 @@ _dmamap_load(t, map, buf, buflen, p, flags)
* previous segment if possible.
*/
if (first) {
- map->dm_segs[seg].ds_addr = curaddr + t->dma_offs;
+ map->dm_segs[seg].ds_addr =
+ (*t->_pa_to_device)(curaddr);
map->dm_segs[seg].ds_len = sgsize;
map->dm_segs[seg].ds_vaddr = (vaddr_t)vaddr;
first = 0;
@@ -176,13 +178,14 @@ _dmamap_load(t, map, buf, buflen, p, flags)
(map->dm_segs[seg].ds_len + sgsize) <=
map->_dm_maxsegsz &&
(map->_dm_boundary == 0 ||
- ((map->dm_segs[seg].ds_addr - t->dma_offs) & bmask) ==
+ (map->dm_segs[seg].ds_addr & bmask) ==
(curaddr & bmask)))
map->dm_segs[seg].ds_len += sgsize;
else {
if (++seg >= map->_dm_segcnt)
break;
- map->dm_segs[seg].ds_addr = curaddr + t->dma_offs;
+ map->dm_segs[seg].ds_addr =
+ (*t->_pa_to_device)(curaddr);
map->dm_segs[seg].ds_len = sgsize;
map->dm_segs[seg].ds_vaddr = (vaddr_t)vaddr;
}
@@ -236,15 +239,15 @@ _dmamap_load_mbuf(t, map, m, flags)
if (pmap_extract(pmap_kernel(), vaddr, &pa) == FALSE)
panic("_dmamap_load_mbuf: pmap_extract(%x, %x) failed!",
pmap_kernel(), vaddr);
- pa += t->dma_offs;
- if (i > 0 && pa == (map->dm_segs[i-1].ds_addr + map->dm_segs[i-1].ds_len)
+ if (i > 0 && pa == (*t->_device_to_pa)(map->dm_segs[i-1].ds_addr + map->dm_segs[i-1].ds_len)
&& ((map->dm_segs[i-1].ds_len + incr) < map->_dm_maxsegsz)) {
/* Hey, waddyaknow, they're contiguous */
map->dm_segs[i-1].ds_len += incr;
continue;
}
- map->dm_segs[i].ds_addr = pa;
+ map->dm_segs[i].ds_addr =
+ (*t->_pa_to_device)(pa);
map->dm_segs[i].ds_vaddr = vaddr;
map->dm_segs[i].ds_len = incr;
i++;
@@ -297,6 +300,7 @@ _dmamap_load_raw(t, map, segs, nsegs, size, flags)
bus_addr_t bmask = ~(map->_dm_boundary - 1);
int i;
+ bmask &= t->_dma_mask;
for (i = 0; i < nsegs; i++) {
if (segs[i].ds_len > map->_dm_maxsegsz)
return (EINVAL);
@@ -457,7 +461,7 @@ _dmamem_free(t, segs, nsegs)
for (addr = segs[curseg].ds_addr;
addr < (segs[curseg].ds_addr + segs[curseg].ds_len);
addr += PAGE_SIZE) {
- m = PHYS_TO_VM_PAGE(addr - t->dma_offs);
+ m = PHYS_TO_VM_PAGE((*t->_device_to_pa)(addr));
TAILQ_INSERT_TAIL(&mlist, m, pageq);
}
}
@@ -495,14 +499,14 @@ _dmamem_map(t, segs, nsegs, size, kvap, flags)
addr += NBPG, va += NBPG, size -= NBPG) {
if (size == 0)
panic("_dmamem_map: size botch");
- pmap_enter(pmap_kernel(), va, addr - t->dma_offs,
+ pmap_enter(pmap_kernel(), va, (*t->_device_to_pa)(addr),
VM_PROT_READ | VM_PROT_WRITE,
VM_PROT_READ | VM_PROT_WRITE | PMAP_WIRED);
segs[curseg].ds_vaddr = va;
if (flags & BUS_DMA_COHERENT &&
sys_config.system_type == SGI_O2)
- pmap_page_cache(PHYS_TO_VM_PAGE(addr - t->dma_offs), PV_UNCACHED);
+ pmap_page_cache(PHYS_TO_VM_PAGE((*t->_device_to_pa)(addr)), PV_UNCACHED);
}
}
@@ -558,7 +562,7 @@ _dmamem_mmap(t, segs, nsegs, off, prot, flags)
continue;
}
- return (atop(segs[i].ds_addr + off - t->dma_offs));
+ return (atop((*t->_device_to_pa)(segs[i].ds_addr) + off));
}
/* Page not found. */
@@ -608,13 +612,13 @@ _dmamem_alloc_range(t, size, alignment, boundary, segs, nsegs, rsegs,
*/
m = TAILQ_FIRST(&mlist);
curseg = 0;
- lastaddr = segs[curseg].ds_addr = VM_PAGE_TO_PHYS(m);
- segs[curseg].ds_addr += t->dma_offs;
+ lastaddr = segs[curseg].ds_addr =
+ (*t->_pa_to_device)(VM_PAGE_TO_PHYS(m));
segs[curseg].ds_len = PAGE_SIZE;
m = TAILQ_NEXT(m, pageq);
for (; m != TAILQ_END(&mlist); m = TAILQ_NEXT(m, pageq)) {
- curaddr = VM_PAGE_TO_PHYS(m);
+ curaddr = (*t->_pa_to_device)(VM_PAGE_TO_PHYS(m));
#ifdef DIAGNOSTIC
if (curaddr < low || curaddr >= high) {
printf("vm_page_alloc_memory returned non-sensical"
@@ -626,7 +630,7 @@ _dmamem_alloc_range(t, size, alignment, boundary, segs, nsegs, rsegs,
segs[curseg].ds_len += PAGE_SIZE;
else {
curseg++;
- segs[curseg].ds_addr = curaddr + t->dma_offs;
+ segs[curseg].ds_addr = curaddr;
segs[curseg].ds_len = PAGE_SIZE;
}
lastaddr = curaddr;