diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2007-06-21 20:17:13 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2007-06-21 20:17:13 +0000 |
commit | b03519f8c6e8caccda6520217fb3537d1d063c4a (patch) | |
tree | 3ffa85787ef7a55040b36a3c7d5394a637c2162a /sys/arch | |
parent | 499eb788d359fe4e2415e514679969123e8dd6d2 (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.mips64 | 3 | ||||
-rw-r--r-- | sys/arch/sgi/conf/files.sgi | 3 | ||||
-rw-r--r-- | sys/arch/sgi/include/bus.h | 10 | ||||
-rw-r--r-- | sys/arch/sgi/localbus/crimebus.h | 5 | ||||
-rw-r--r-- | sys/arch/sgi/localbus/macebus.c | 31 | ||||
-rw-r--r-- | sys/arch/sgi/pci/macepcibridge.c | 32 | ||||
-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; |