diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2010-04-20 22:53:25 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2010-04-20 22:53:25 +0000 |
commit | ce628862391593c48e896c49c523d472c7be2fcb (patch) | |
tree | e109af40f76a2d2dc16d1097b497d448b6460fe0 /sys/arch | |
parent | 4c9ab331c312ece85c73a853aa4476db39ec8b8f (diff) |
Add bus_dma and oosiop(4), as found on the AV530 family. Tested on model 4605.
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/aviion/aviion/bus_dma.c | 687 | ||||
-rw-r--r-- | sys/arch/aviion/aviion/bus_space.c | 124 | ||||
-rw-r--r-- | sys/arch/aviion/conf/GENERIC | 19 | ||||
-rw-r--r-- | sys/arch/aviion/conf/files.aviion | 8 | ||||
-rw-r--r-- | sys/arch/aviion/dev/mainbus.c | 39 | ||||
-rw-r--r-- | sys/arch/aviion/dev/oosiop_syscon.c | 92 | ||||
-rw-r--r-- | sys/arch/aviion/dev/vme.c | 245 | ||||
-rw-r--r-- | sys/arch/aviion/include/bus.h | 1003 |
8 files changed, 1488 insertions, 729 deletions
diff --git a/sys/arch/aviion/aviion/bus_dma.c b/sys/arch/aviion/aviion/bus_dma.c new file mode 100644 index 00000000000..81ab9fa1325 --- /dev/null +++ b/sys/arch/aviion/aviion/bus_dma.c @@ -0,0 +1,687 @@ +/* $OpenBSD: bus_dma.c,v 1.1 2010/04/20 22:53:20 miod Exp $ */ +/* $NetBSD: bus_dma.c,v 1.2 2001/06/10 02:31:25 briggs Exp $ */ + +/*- + * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/user.h> +#include <sys/extent.h> +#include <sys/buf.h> +#include <sys/device.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/file.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/mount.h> + +#include <uvm/uvm_extern.h> + +#include <machine/bus.h> +#include <machine/cmmu.h> +#include <machine/intr.h> + +int _bus_dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int, paddr_t *, int *, int); + +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); + +/* + * Common function for DMA map creation. May be called by bus-specific + * DMA map creation functions. + */ +int +bus_dmamap_create(t, size, nsegments, maxsegsz, boundary, flags, dmamp) + bus_dma_tag_t t; + bus_size_t size; + int nsegments; + bus_size_t maxsegsz; + bus_size_t boundary; + int flags; + bus_dmamap_t *dmamp; +{ + struct m88k_bus_dmamap *map; + void *mapstore; + size_t mapsize; + + /* + * Allocate and initialize the DMA map. The end of the map + * is a variable-sized array of segments, so we allocate enough + * room for them in one shot. + * + * Note we don't preserve the WAITOK or NOWAIT flags. Preservation + * of ALLOCNOW notifies others that we've reserved these resources, + * and they are not to be freed. + * + * The bus_dmamap_t includes one bus_dma_segment_t, hence + * the (nsegments - 1). + */ + mapsize = sizeof(struct m88k_bus_dmamap) + + (sizeof(bus_dma_segment_t) * (nsegments - 1)); + if ((mapstore = malloc(mapsize, M_DEVBUF, (flags & BUS_DMA_NOWAIT) ? + (M_NOWAIT | M_ZERO) : (M_WAITOK | M_ZERO))) == NULL) + return (ENOMEM); + + map = (struct m88k_bus_dmamap *)mapstore; + map->_dm_size = size; + map->_dm_segcnt = nsegments; + map->_dm_maxsegsz = maxsegsz; + map->_dm_boundary = boundary; + map->dm_mapsize = 0; /* no valid mappings */ + map->dm_nsegs = 0; + + *dmamp = map; + return (0); +} + +/* + * Common function for DMA map destruction. May be called by bus-specific + * DMA map destruction functions. + */ +void +bus_dmamap_destroy(t, map) + bus_dma_tag_t t; + bus_dmamap_t map; +{ + + free(map, M_DEVBUF); +} + +/* + * Utility function to load a linear buffer. lastaddrp holds state + * between invocations (for multiple-buffer loads). segp contains + * the starting segment on entrance, and the ending segment on exit. + * first indicates if this is the first invocation of this function. + */ +int +_bus_dmamap_load_buffer(t, map, buf, buflen, p, flags, lastaddrp, segp, first) + bus_dma_tag_t t; + bus_dmamap_t map; + void *buf; + bus_size_t buflen; + struct proc *p; + int flags; + paddr_t *lastaddrp; + int *segp; + int first; +{ + bus_size_t sgsize; + bus_addr_t curaddr, lastaddr, baddr, bmask; + vaddr_t vaddr = (vaddr_t)buf; + int seg; + pmap_t pmap; + + if (p != NULL) + pmap = vm_map_pmap(&p->p_vmspace->vm_map); + else + pmap = pmap_kernel(); + + lastaddr = *lastaddrp; + bmask = ~(map->_dm_boundary - 1); + + for (seg = *segp; buflen > 0 ; ) { + /* + * Get the physical address for this segment. + */ + if (pmap_extract(pmap, vaddr, (paddr_t *)&curaddr) == FALSE) + return (EINVAL); + + /* + * Compute the segment size, and adjust counts. + */ + sgsize = PAGE_SIZE - ((u_long)vaddr & PGOFSET); + if (buflen < sgsize) + sgsize = buflen; + + /* + * Make sure we don't cross any boundaries. + */ + if (map->_dm_boundary > 0) { + baddr = (curaddr + map->_dm_boundary) & bmask; + if (sgsize > (baddr - curaddr)) + sgsize = (baddr - curaddr); + } + + /* + * Insert chunk into a segment, coalescing with + * the previous segment if possible. + */ + if (first) { + map->dm_segs[seg].ds_addr = curaddr; + map->dm_segs[seg].ds_len = sgsize; + first = 0; + } else { + if (curaddr == lastaddr && + (map->dm_segs[seg].ds_len + sgsize) <= + map->_dm_maxsegsz && + (map->_dm_boundary == 0 || + (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; + map->dm_segs[seg].ds_len = sgsize; + } + } + + lastaddr = curaddr + sgsize; + vaddr += sgsize; + buflen -= sgsize; + } + + *segp = seg; + *lastaddrp = lastaddr; + + /* + * Did we fit? + */ + if (buflen != 0) + return (EFBIG); /* XXX better return value here? */ + + return (0); +} + +/* + * Common function for loading a DMA map with a linear buffer. May + * be called by bus-specific DMA map load functions. + */ +int +bus_dmamap_load(t, map, buf, buflen, p, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + void *buf; + bus_size_t buflen; + struct proc *p; + int flags; +{ + paddr_t lastaddr; + int seg, error; + + /* + * Make sure that on error condition we return "no valid mappings". + */ + map->dm_mapsize = 0; + map->dm_nsegs = 0; + + if (buflen > map->_dm_size) + return (EINVAL); + + seg = 0; + error = _bus_dmamap_load_buffer(t, map, buf, buflen, p, flags, + &lastaddr, &seg, 1); + if (error == 0) { + map->dm_mapsize = buflen; + map->dm_nsegs = seg + 1; + } + return (error); +} + +/* + * Like _bus_dmamap_load(), but for mbufs. + */ +int +bus_dmamap_load_mbuf(t, map, m0, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + struct mbuf *m0; + int flags; +{ + paddr_t lastaddr; + int seg, error, first; + struct mbuf *m; + + /* + * Make sure that on error condition we return "no valid mappings." + */ + map->dm_mapsize = 0; + map->dm_nsegs = 0; + +#ifdef DIAGNOSTIC + if ((m0->m_flags & M_PKTHDR) == 0) + panic("bus_dmamap_load_mbuf: no packet header"); +#endif + + if (m0->m_pkthdr.len > map->_dm_size) + return (EINVAL); + + first = 1; + seg = 0; + error = 0; + for (m = m0; m != NULL && error == 0; m = m->m_next) { + if (m->m_len == 0) + continue; + error = _bus_dmamap_load_buffer(t, map, m->m_data, m->m_len, + NULL, flags, &lastaddr, &seg, first); + first = 0; + } + if (error == 0) { + map->dm_mapsize = m0->m_pkthdr.len; + map->dm_nsegs = seg + 1; + } + return (error); +} + +/* + * Like _bus_dmamap_load(), but for uios. + */ +int +bus_dmamap_load_uio(t, map, uio, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + struct uio *uio; + int flags; +{ + paddr_t lastaddr; + int seg, i, error, first; + bus_size_t minlen, resid; + struct proc *p = NULL; + struct iovec *iov; + caddr_t addr; + + /* + * Make sure that on error condition we return "no valid mappings." + */ + map->dm_mapsize = 0; + map->dm_nsegs = 0; + + resid = uio->uio_resid; + iov = uio->uio_iov; + + if (resid > map->_dm_size) + return (EINVAL); + + if (uio->uio_segflg == UIO_USERSPACE) { + p = uio->uio_procp; +#ifdef DIAGNOSTIC + if (p == NULL) + panic("bus_dmamap_load_uio: USERSPACE but no proc"); +#endif + } + + first = 1; + seg = 0; + error = 0; + for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0; i++) { + /* + * Now at the first iovec to load. Load each iovec + * until we have exhausted the residual count. + */ + minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len; + addr = (caddr_t)iov[i].iov_base; + + error = _bus_dmamap_load_buffer(t, map, addr, minlen, + p, flags, &lastaddr, &seg, first); + first = 0; + + resid -= minlen; + } + if (error == 0) { + map->dm_mapsize = uio->uio_resid; + map->dm_nsegs = seg + 1; + } + return (error); +} + +/* + * Like bus_dmamap_load(), but for raw memory allocated with + * bus_dmamem_alloc(). + */ +int +bus_dmamap_load_raw(t, map, segs, nsegs, size, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + bus_dma_segment_t *segs; + int nsegs; + bus_size_t size; + int flags; +{ + if (nsegs > map->_dm_segcnt || size > map->_dm_size) + return (EINVAL); + + /* + * Make sure we don't cross any boundaries. + */ + if (map->_dm_boundary) { + bus_addr_t bmask = ~(map->_dm_boundary - 1); + int i; + + for (i = 0; i < nsegs; i++) { + if (segs[i].ds_len > map->_dm_maxsegsz) + return (EINVAL); + if ((segs[i].ds_addr & bmask) != + ((segs[i].ds_addr + segs[i].ds_len - 1) & bmask)) + return (EINVAL); + } + } + + bcopy(segs, map->dm_segs, nsegs * sizeof(*segs)); + map->dm_nsegs = nsegs; + return (0); +} + +/* + * Common function for unloading a DMA map. May be called by + * chipset-specific DMA map unload functions. + */ +void +bus_dmamap_unload(t, map) + bus_dma_tag_t t; + bus_dmamap_t map; +{ + + /* + * No resources to free; just mark the mappings as + * invalid. + */ + map->dm_mapsize = 0; + map->dm_nsegs = 0; +} + +/* + * Common function for DMA map synchronization. May be called + * by chipset-specific DMA map synchronization functions. + */ + +void +bus_dmamap_sync(t, map, offset, len, op) + bus_dma_tag_t t; + bus_dmamap_t map; + bus_addr_t offset; + bus_size_t len; + int op; +{ + u_int nsegs; + bus_dma_segment_t *seg; + + if (op & BUS_DMASYNC_PREREAD) + op = DMA_CACHE_SYNC_INVAL; + else if (op & BUS_DMASYNC_PREWRITE) + op = DMA_CACHE_SYNC; + else if (op & BUS_DMASYNC_POSTREAD) + op = DMA_CACHE_INV; + else + return; + + nsegs = map->dm_nsegs; + seg = map->dm_segs; + while (nsegs != 0 && len != 0) { + if (offset >= seg->ds_len) { + offset -= seg->ds_len; + } else { + bus_addr_t addr; + bus_size_t sublen; + + addr = seg->ds_addr + offset; + sublen = seg->ds_len - offset; + if (sublen > len) + sublen = len; + + dma_cachectl(addr, sublen, op); + + offset = 0; + len -= sublen; + } + seg++; + nsegs--; + } +} + +/* + * Common function for DMA-safe memory allocation. May be called + * by bus-specific DMA memory allocation functions. + */ +int +bus_dmamem_alloc(t, size, alignment, boundary, segs, nsegs, rsegs, flags) + bus_dma_tag_t t; + bus_size_t size, alignment, boundary; + bus_dma_segment_t *segs; + int nsegs; + int *rsegs; + int flags; +{ + return _bus_dmamem_alloc_range(t, size, alignment, boundary, segs, + nsegs, rsegs, flags, 0, -1); +} + +/* + * Common function for freeing DMA-safe memory. May be called by + * bus-specific DMA memory free functions. + */ +void +bus_dmamem_free(t, segs, nsegs) + bus_dma_tag_t t; + bus_dma_segment_t *segs; + int nsegs; +{ + struct vm_page *m; + bus_addr_t addr; + struct pglist mlist; + int curseg; + + /* + * Build a list of pages to free back to the VM system. + */ + TAILQ_INIT(&mlist); + for (curseg = 0; curseg < nsegs; curseg++) { + for (addr = segs[curseg].ds_addr; + addr < (segs[curseg].ds_addr + segs[curseg].ds_len); + addr += PAGE_SIZE) { + m = PHYS_TO_VM_PAGE(addr); + TAILQ_INSERT_TAIL(&mlist, m, pageq); + } + } + + uvm_pglistfree(&mlist); +} + +/* + * Common function for mapping DMA-safe memory. May be called by + * bus-specific DMA memory map functions. + */ +int +bus_dmamem_map(t, segs, nsegs, size, kvap, flags) + bus_dma_tag_t t; + bus_dma_segment_t *segs; + int nsegs; + size_t size; + caddr_t *kvap; + int flags; +{ + vaddr_t va, sva; + size_t ssize; + bus_addr_t addr; + int curseg, error; + + size = round_page(size); + + va = uvm_km_valloc(kernel_map, size); + + if (va == 0) + return (ENOMEM); + + *kvap = (caddr_t)va; + + sva = va; + ssize = size; + for (curseg = 0; curseg < nsegs; curseg++) { + for (addr = segs[curseg].ds_addr; + addr < (segs[curseg].ds_addr + segs[curseg].ds_len); + addr += PAGE_SIZE, va += PAGE_SIZE, size -= PAGE_SIZE) { + if (size == 0) + panic("bus_dmamem_map: size botch"); + error = pmap_enter(pmap_kernel(), va, addr, + VM_PROT_READ | VM_PROT_WRITE, VM_PROT_READ | + VM_PROT_WRITE | PMAP_WIRED | PMAP_CANFAIL); + if (error) { + /* + * Clean up after ourselves. + * XXX uvm_wait on WAITOK + */ + pmap_update(pmap_kernel()); + uvm_km_free(kernel_map, va, ssize); + return (error); + } + } + } + pmap_update(pmap_kernel()); + + return (0); +} + +/* + * Common function for unmapping DMA-safe memory. May be called by + * bus-specific DMA memory unmapping functions. + */ +void +bus_dmamem_unmap(t, kva, size) + bus_dma_tag_t t; + caddr_t kva; + size_t size; +{ + +#ifdef DIAGNOSTIC + if ((u_long)kva & PGOFSET) + panic("bus_dmamem_unmap"); +#endif + + size = round_page(size); + uvm_km_free(kernel_map, (vaddr_t)kva, size); +} + +/* + * Common function for mmap(2)'ing DMA-safe memory. May be called by + * bus-specific DMA mmap(2)'ing functions. + */ +paddr_t +bus_dmamem_mmap(t, segs, nsegs, off, prot, flags) + bus_dma_tag_t t; + bus_dma_segment_t *segs; + int nsegs; + off_t off; + int prot, flags; +{ + int i; + + for (i = 0; i < nsegs; i++) { +#ifdef DIAGNOSTIC + if (off & PGOFSET) + panic("bus_dmamem_mmap: offset unaligned"); + if (segs[i].ds_addr & PGOFSET) + panic("bus_dmamem_mmap: segment unaligned"); + if (segs[i].ds_len & PGOFSET) + panic("bus_dmamem_mmap: segment size not multiple" + " of page size"); +#endif + if (off >= segs[i].ds_len) { + off -= segs[i].ds_len; + continue; + } + + return (atop(segs[i].ds_addr + off)); + } + + /* Page not found. */ + return (-1); +} + +/* + * Allocate physical memory from the given physical address range. + * Called by DMA-safe memory allocation methods. + */ +int +_bus_dmamem_alloc_range(t, size, alignment, boundary, segs, nsegs, rsegs, + flags, low, high) + bus_dma_tag_t t; + bus_size_t size, alignment, boundary; + bus_dma_segment_t *segs; + int nsegs; + int *rsegs; + int flags; + paddr_t low; + paddr_t high; +{ + paddr_t curaddr, lastaddr; + struct vm_page *m; + struct pglist mlist; + int curseg, error, plaflag; + + /* Always round the size. */ + size = round_page(size); + + /* + * Allocate pages from the VM system. + */ + plaflag = flags & BUS_DMA_NOWAIT ? UVM_PLA_NOWAIT : UVM_PLA_WAITOK; + if (flags & BUS_DMA_ZERO) + plaflag |= UVM_PLA_ZERO; + + TAILQ_INIT(&mlist); + error = uvm_pglistalloc(size, low, high, alignment, boundary, + &mlist, nsegs, plaflag); + if (error) + return (error); + + /* + * Compute the location, size, and number of segments actually + * returned by the VM code. + */ + m = TAILQ_FIRST(&mlist); + curseg = 0; + lastaddr = segs[curseg].ds_addr = 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); +#ifdef DIAGNOSTIC + if (curaddr < low || curaddr >= high) { + panic("_bus_dmamem_alloc_range: uvm_pglistalloc " + "returned non-sensical address 0x%lx\n", curaddr); + } +#endif + if (curaddr == (lastaddr + PAGE_SIZE)) + segs[curseg].ds_len += PAGE_SIZE; + else { + curseg++; + segs[curseg].ds_addr = curaddr; + segs[curseg].ds_len = PAGE_SIZE; + } + lastaddr = curaddr; + } + + *rsegs = curseg + 1; + + return (0); +} diff --git a/sys/arch/aviion/aviion/bus_space.c b/sys/arch/aviion/aviion/bus_space.c new file mode 100644 index 00000000000..951379c6cd1 --- /dev/null +++ b/sys/arch/aviion/aviion/bus_space.c @@ -0,0 +1,124 @@ +/* $OpenBSD: bus_space.c,v 1.1 2010/04/20 22:53:20 miod Exp $ */ + +/* + * Copyright (c) 2001-2003 Opsycon AB (www.opsycon.se / www.opsycon.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * Simple generic bus access primitives, for memory mapped space without + * any access restriction or endianness conversion required. + */ + +#include <sys/param.h> +#include <sys/systm.h> + +#include <machine/bus.h> + +uint8_t +generic_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) +{ + return *(volatile uint8_t *)(h + o); +} + +uint16_t +generic_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) +{ + return *(volatile uint16_t *)(h + o); +} + +uint32_t +generic_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) +{ + return *(volatile uint32_t *)(h + o); +} + +void +generic_space_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + uint8_t v) +{ + *(volatile uint8_t *)(h + o) = v; +} + +void +generic_space_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + uint16_t v) +{ + *(volatile uint16_t *)(h + o) = v; +} + +void +generic_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + uint32_t v) +{ + *(volatile uint32_t *)(h + o) = v; +} + +void +generic_space_read_raw_2(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, + uint8_t *buf, bus_size_t len) +{ + volatile uint16_t *addr = (volatile uint16_t *)(h + o); + len >>= 1; + while (len-- != 0) { + *(uint16_t *)buf = *addr; + buf += 2; + } +} + +void +generic_space_write_raw_2(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, + const uint8_t *buf, bus_size_t len) +{ + volatile uint16_t *addr = (volatile uint16_t *)(h + o); + len >>= 1; + while (len-- != 0) { + *addr = *(uint16_t *)buf; + buf += 2; + } +} + +void +generic_space_read_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, + uint8_t *buf, bus_size_t len) +{ + volatile uint32_t *addr = (volatile uint32_t *)(h + o); + len >>= 2; + while (len-- != 0) { + *(uint32_t *)buf = *addr; + buf += 4; + } +} + +void +generic_space_write_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, + const uint8_t *buf, bus_size_t len) +{ + volatile uint32_t *addr = (volatile uint32_t *)(h + o); + len >>= 2; + while (len-- != 0) { + *addr = *(uint32_t *)buf; + buf += 4; + } +} diff --git a/sys/arch/aviion/conf/GENERIC b/sys/arch/aviion/conf/GENERIC index 5b0ba40d1ab..ced7d0af819 100644 --- a/sys/arch/aviion/conf/GENERIC +++ b/sys/arch/aviion/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.3 2010/04/18 22:04:39 miod Exp $ +# $OpenBSD: GENERIC,v 1.4 2010/04/20 22:53:23 miod Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -60,7 +60,7 @@ le0 at syscon? offset 0x8c000 ipl 1 # on-board ethernet dart1 at syscon? offset 0x82040 ipl 3 #ssi0 at syscon? offset 0x8d000 ipl 3 -#oosiop0 at syscon? offset 0xb0000 ipl 2 +oosiop0 at syscon? offset 0xb0000 ipl 2 #ile0 at syscon? offset 0xb00c0 ipl 1 #ile1 at syscon? offset 0xb0140 ipl 1 @@ -80,3 +80,18 @@ le* at vme? a32 0x55980000 a16 0x5000 ipl 1 # VDA/255 Serial Host Adapter (on-board on model 4300) #vda0 at vme? a32 0x60000000 + +# +# SCSI devices +# + +scsibus* at oosiop? + +sd* at scsibus? +st* at scsibus? +cd* at scsibus? +ch* at scsibus? +ss* at scsibus? +safte* at scsibus? +ses* at scsibus? +uk* at scsibus? diff --git a/sys/arch/aviion/conf/files.aviion b/sys/arch/aviion/conf/files.aviion index ff0b53cda0a..c7e5bdce58d 100644 --- a/sys/arch/aviion/conf/files.aviion +++ b/sys/arch/aviion/conf/files.aviion @@ -1,4 +1,4 @@ -# $OpenBSD: files.aviion,v 1.5 2007/12/19 22:05:06 miod Exp $ +# $OpenBSD: files.aviion,v 1.6 2010/04/20 22:53:23 miod Exp $ # maxpartitions 16 @@ -32,6 +32,9 @@ file arch/aviion/dev/if_ile.c ile attach ile at syscon with ile_syscon file arch/aviion/dev/if_ile_syscon.c ile_syscon +attach oosiop at syscon with oosiop_syscon +file arch/aviion/dev/oosiop_syscon.c oosiop_syscon + include "../../../scsi/files.scsi" major {sd = 4} @@ -58,7 +61,8 @@ file arch/aviion/dev/if_ile_vme.c ile_vme file dev/cninit.c file arch/aviion/aviion/autoconf.c -#file arch/aviion/aviion/bus_dma.c +file arch/aviion/aviion/bus_space.c +file arch/aviion/aviion/bus_dma.c file arch/aviion/aviion/conf.c file arch/aviion/aviion/db_machdep.c ddb file arch/aviion/aviion/disksubr.c diff --git a/sys/arch/aviion/dev/mainbus.c b/sys/arch/aviion/dev/mainbus.c index 88449a7c889..403ee92812f 100644 --- a/sys/arch/aviion/dev/mainbus.c +++ b/sys/arch/aviion/dev/mainbus.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mainbus.c,v 1.2 2006/05/21 12:22:02 miod Exp $ */ +/* $OpenBSD: mainbus.c,v 1.3 2010/04/20 22:53:24 miod Exp $ */ /* * Copyright (c) 1998 Steve Murphree, Jr. * Copyright (c) 2004, Miodrag Vallat. @@ -50,17 +50,28 @@ int mainbus_scan(struct device *, void *, void *); * bus_space routines for 1:1 obio mappings */ -int mainbus_map(bus_addr_t, bus_size_t, int, bus_space_handle_t *); -void mainbus_unmap(bus_space_handle_t, bus_size_t); -int mainbus_subregion(bus_space_handle_t, bus_size_t, bus_size_t, +int mainbus_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, bus_space_handle_t *); -void *mainbus_vaddr(bus_space_handle_t); +void mainbus_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t); +int mainbus_subregion(bus_space_tag_t, bus_space_handle_t, bus_size_t, + bus_size_t, bus_space_handle_t *); +void *mainbus_vaddr(bus_space_tag_t, bus_space_handle_t); const struct aviion_bus_space_tag mainbus_bustag = { - mainbus_map, - mainbus_unmap, - mainbus_subregion, - mainbus_vaddr + ._space_map = mainbus_map, + ._space_unmap = mainbus_unmap, + ._space_subregion = mainbus_subregion, + ._space_vaddr = mainbus_vaddr, + ._space_read_1 = generic_space_read_1, + ._space_write_1 = generic_space_write_1, + ._space_read_2 = generic_space_read_2, + ._space_write_2 = generic_space_write_2, + ._space_read_4 = generic_space_read_4, + ._space_write_4 = generic_space_write_4, + ._space_read_raw_2 = generic_space_read_raw_2, + ._space_write_raw_2 = generic_space_write_raw_2, + ._space_read_raw_4 = generic_space_read_raw_4, + ._space_write_raw_4 = generic_space_write_raw_4, }; /* @@ -68,7 +79,7 @@ const struct aviion_bus_space_tag mainbus_bustag = { */ int -mainbus_map(bus_addr_t addr, bus_size_t size, int flags, +mainbus_map(bus_space_tag_t tag, bus_addr_t addr, bus_size_t size, int flags, bus_space_handle_t *ret) { *ret = (bus_space_handle_t)addr; @@ -76,21 +87,21 @@ mainbus_map(bus_addr_t addr, bus_size_t size, int flags, } void -mainbus_unmap(bus_space_handle_t handle, bus_size_t size) +mainbus_unmap(bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t size) { /* nothing to do */ } int -mainbus_subregion(bus_space_handle_t handle, bus_addr_t offset, - bus_size_t size, bus_space_handle_t *ret) +mainbus_subregion(bus_space_tag_t tag, bus_space_handle_t handle, + bus_addr_t offset, bus_size_t size, bus_space_handle_t *ret) { *ret = handle + offset; return (0); } void * -mainbus_vaddr(bus_space_handle_t handle) +mainbus_vaddr(bus_space_tag_t tag, bus_space_handle_t handle) { return (void *)handle; } diff --git a/sys/arch/aviion/dev/oosiop_syscon.c b/sys/arch/aviion/dev/oosiop_syscon.c new file mode 100644 index 00000000000..d0647999cdb --- /dev/null +++ b/sys/arch/aviion/dev/oosiop_syscon.c @@ -0,0 +1,92 @@ +/* $OpenBSD: oosiop_syscon.c,v 1.1 2010/04/20 22:53:24 miod Exp $ */ + +/* + * Copyright (c) 2010 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/buf.h> + +#include <scsi/scsi_all.h> +#include <scsi/scsiconf.h> + +#include <machine/autoconf.h> +#include <machine/board.h> +#include <machine/bus.h> + +#include <aviion/dev/sysconvar.h> + +#include <dev/ic/oosiopreg.h> +#include <dev/ic/oosiopvar.h> + +int oosiop_syscon_match(struct device *, void *, void *); +void oosiop_syscon_attach(struct device *, struct device *, void *); + +struct oosiop_syscon_softc { + struct oosiop_softc sc_base; + struct intrhand sc_ih; +}; + +const struct cfattach oosiop_syscon_ca = { + sizeof(struct oosiop_syscon_softc), + oosiop_syscon_match, oosiop_syscon_attach +}; + +int +oosiop_syscon_match(struct device *parent, void *match, void *aux) +{ + if (avtyp != AV_530) + return 0; + + /* XXX check IOFUSE register */ + return 1; +} + +void +oosiop_syscon_attach(struct device *parent, struct device *self, void *aux) +{ + struct oosiop_syscon_softc *ssc = (struct oosiop_syscon_softc *)self; + struct oosiop_softc *sc = (struct oosiop_softc *)self; + struct confargs *ca = aux; + bus_space_handle_t ioh; + + if (bus_space_map(ca->ca_iot, ca->ca_paddr, OOSIOP_NREGS, 0, + &ioh) != 0) { + printf(": can't map registers\n"); + return; + } + sc->sc_bst = ca->ca_iot; + sc->sc_bsh = ioh; + sc->sc_dmat = NULL; /* no real use of tag yet */ + + sc->sc_freq = 33333333; /* XXX 25MHz models? */ + sc->sc_chip = OOSIOP_700; + sc->sc_id = 7; /* XXX */ + + sc->sc_scntl0 = OOSIOP_SCNTL0_EPC | OOSIOP_SCNTL0_EPG; + sc->sc_dmode = OOSIOP_DMODE_BL_4; + sc->sc_dwt = 0x4f; /* maximum DMA timeout allowable */ + sc->sc_ctest7 = OOSIOP_CTEST7_DC; + + oosiop_attach(sc); + + ssc->sc_ih.ih_fn = (int(*)(void *))oosiop_intr; + ssc->sc_ih.ih_arg = sc; + ssc->sc_ih.ih_flags = 0; + ssc->sc_ih.ih_ipl = ca->ca_ipl; + sysconintr_establish(INTSRC_SCSI1, &ssc->sc_ih, self->dv_xname); +} diff --git a/sys/arch/aviion/dev/vme.c b/sys/arch/aviion/dev/vme.c index faad62acef2..f07c6fb8f2d 100644 --- a/sys/arch/aviion/dev/vme.c +++ b/sys/arch/aviion/dev/vme.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vme.c,v 1.5 2010/04/18 22:04:39 miod Exp $ */ +/* $OpenBSD: vme.c,v 1.6 2010/04/20 22:53:24 miod Exp $ */ /* * Copyright (c) 2006, 2007, Miodrag Vallat. * @@ -66,15 +66,41 @@ struct cfdriver vme_cd = { NULL, "vme", DV_DULL }; -int vme16_map(bus_addr_t, bus_size_t, int, bus_space_handle_t *); -void vme16_unmap(bus_space_handle_t, bus_size_t); -int vme24_map(bus_addr_t, bus_size_t, int, bus_space_handle_t *); -void vme24_unmap(bus_space_handle_t, bus_size_t); -int vme32_map(bus_addr_t, bus_size_t, int, bus_space_handle_t *); -void vme32_unmap(bus_space_handle_t, bus_size_t); -int vme_subregion(bus_space_handle_t, bus_size_t, bus_size_t, +uint16_t vme_d8_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t); +void vme_d8_read_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void vme_d8_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint16_t); +void vme_d8_write_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +uint32_t vme_d8_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t); +void vme_d8_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint32_t); +void vme_d8_read_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void vme_d8_write_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); + +uint32_t vme_d16_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t); +void vme_d16_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint32_t); +void vme_d16_read_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void vme_d16_write_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); + +int vme_a16_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, bus_space_handle_t *); -void * vme_vaddr(bus_space_handle_t); +void vme_a16_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t); +int vme_a24_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, + bus_space_handle_t *); +void vme_a24_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t); +int vme_a32_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, + bus_space_handle_t *); +void vme_a32_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t); +int vme_subregion(bus_space_tag_t, bus_space_handle_t, bus_size_t, + bus_size_t, bus_space_handle_t *); +void * vme_vaddr(bus_space_tag_t, bus_space_handle_t); int vme_map(struct extent *, paddr_t, bus_addr_t, bus_size_t, int, bus_space_handle_t *); @@ -349,7 +375,8 @@ vmeintr_disestablish(u_int vec, struct intrhand *ih) ((addr) >= platform->vme16_start && (addr) <= platform->vme16_end) int -vme16_map(bus_addr_t addr, bus_size_t size, int flags, bus_space_handle_t *ret) +vme_a16_map(bus_space_tag_t tag, bus_addr_t addr, bus_size_t size, int flags, + bus_space_handle_t *ret) { struct vmesoftc *sc = (void *)vme_cd.cd_devs[0]; @@ -361,7 +388,8 @@ vme16_map(bus_addr_t addr, bus_size_t size, int flags, bus_space_handle_t *ret) } int -vme24_map(bus_addr_t addr, bus_size_t size, int flags, bus_space_handle_t *ret) +vme_a24_map(bus_space_tag_t tag, bus_addr_t addr, bus_size_t size, int flags, + bus_space_handle_t *ret) { struct vmesoftc *sc = (void *)vme_cd.cd_devs[0]; @@ -373,7 +401,8 @@ vme24_map(bus_addr_t addr, bus_size_t size, int flags, bus_space_handle_t *ret) } int -vme32_map(bus_addr_t addr, bus_size_t size, int flags, bus_space_handle_t *ret) +vme_a32_map(bus_space_tag_t tag, bus_addr_t addr, bus_size_t size, int flags, + bus_space_handle_t *ret) { struct vmesoftc *sc = (void *)vme_cd.cd_devs[0]; @@ -430,7 +459,7 @@ fail: } void -vme16_unmap(bus_space_handle_t handle, bus_size_t size) +vme_a16_unmap(bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t size) { struct vmesoftc *sc = (void *)vme_cd.cd_devs[0]; paddr_t pa; @@ -443,7 +472,7 @@ vme16_unmap(bus_space_handle_t handle, bus_size_t size) } void -vme24_unmap(bus_space_handle_t handle, bus_size_t size) +vme_a24_unmap(bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t size) { struct vmesoftc *sc = (void *)vme_cd.cd_devs[0]; paddr_t pa; @@ -456,7 +485,7 @@ vme24_unmap(bus_space_handle_t handle, bus_size_t size) } void -vme32_unmap(bus_space_handle_t handle, bus_size_t size) +vme_a32_unmap(bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t size) { struct vmesoftc *sc = (void *)vme_cd.cd_devs[0]; paddr_t pa; @@ -487,8 +516,8 @@ vme_unmap(struct extent *ext, vme_addr_t addr, vaddr_t vaddr, bus_size_t size) } int -vme_subregion(bus_space_handle_t handle, bus_addr_t offset, bus_size_t size, - bus_space_handle_t *ret) +vme_subregion(bus_space_tag_t tag, bus_space_handle_t handle, bus_addr_t offset, + bus_size_t size, bus_space_handle_t *ret) { /* since vme_map produces linear mappings, this is safe */ *ret = handle + offset; @@ -496,12 +525,136 @@ vme_subregion(bus_space_handle_t handle, bus_addr_t offset, bus_size_t size, } void * -vme_vaddr(bus_space_handle_t handle) +vme_vaddr(bus_space_tag_t tag, bus_space_handle_t handle) { return ((void *)handle); } /* + * D8 routines + */ + +uint16_t +vme_d8_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) +{ + volatile uint8_t *addr = (volatile uint8_t *)(h + o); + return ((uint16_t)addr[0] << 8) | ((uint16_t)addr[1]); +} + +uint32_t +vme_d8_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) +{ + volatile uint8_t *addr = (volatile uint8_t *)(h + o); + return ((uint32_t)addr[0] << 24) | ((uint32_t)addr[1] << 16) | + ((uint32_t)addr[2] << 8) | ((uint32_t)addr[3]); +} + +void +vme_d8_space_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + uint16_t v) +{ + volatile uint8_t *addr = (volatile uint8_t *)(h + o); + addr[0] = v >> 8; + addr[1] = v; +} + +void +vme_d8_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + uint32_t v) +{ + volatile uint8_t *addr = (volatile uint8_t *)(h + o); + addr[0] = v >> 24; + addr[1] = v >> 16; + addr[2] = v >> 8; + addr[3] = v; +} + +void +vme_d8_space_read_raw_2(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, + uint8_t *buf, bus_size_t len) +{ + len >>= 1; + while (len-- != 0) { + *(uint16_t *)buf = vme_d8_space_read_2(t, h, o); + buf += 2; + } +} + +void +vme_d8_space_write_raw_2(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, + const uint8_t *buf, bus_size_t len) +{ + len >>= 1; + while (len-- != 0) { + vme_d8_space_write_2(t, h, o, *(uint16_t *)buf); + buf += 2; + } +} + +void +vme_d8_space_read_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, + uint8_t *buf, bus_size_t len) +{ + len >>= 2; + while (len-- != 0) { + *(uint32_t *)buf = vme_d8_space_read_4(t, h, o); + buf += 4; + } +} + +void +vme_d8_space_write_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, + const uint8_t *buf, bus_size_t len) +{ + len >>= 2; + while (len-- != 0) { + vme_d8_space_write_4(t, h, o, *(uint32_t *)buf); + buf += 4; + } +} +/* + * D16 routines + */ + +uint32_t +vme_d16_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) +{ + volatile uint16_t *addr = (volatile uint16_t *)(h + o); + return ((uint32_t)addr[0] << 16) | ((uint32_t)addr[1]); +} + +void +vme_d16_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + uint32_t v) +{ + volatile uint16_t *addr = (volatile uint16_t *)(h + o); + addr[0] = v >> 16; + addr[1] = v; +} + +void +vme_d16_space_read_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, + uint8_t *buf, bus_size_t len) +{ + len >>= 2; + while (len-- != 0) { + *(uint32_t *)buf = vme_d16_space_read_4(t, h, o); + buf += 4; + } +} + +void +vme_d16_space_write_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o, + const uint8_t *buf, bus_size_t len) +{ + len >>= 2; + while (len-- != 0) { + vme_d16_space_write_4(t, h, o, *(uint32_t *)buf); + buf += 4; + } +} + +/* * Get a bus_space_tag for the requested address and data access modes. * * On aviion, we do not honour the dspace yet. @@ -538,22 +691,54 @@ vmebus_get_bst(struct device *vsc, u_int aspace, u_int dspace, switch (aspace) { default: case VME_A32: - tag->bs_map = vme32_map; - tag->bs_unmap = vme32_unmap; - tag->bs_subregion = vme_subregion; - tag->bs_vaddr = vme_vaddr; + tag->_space_map = vme_a32_map; + tag->_space_unmap = vme_a32_unmap; break; case VME_A24: - tag->bs_map = vme24_map; - tag->bs_unmap = vme24_unmap; - tag->bs_subregion = vme_subregion; - tag->bs_vaddr = vme_vaddr; + tag->_space_map = vme_a24_map; + tag->_space_unmap = vme_a24_unmap; break; case VME_A16: - tag->bs_map = vme16_map; - tag->bs_unmap = vme16_unmap; - tag->bs_subregion = vme_subregion; - tag->bs_vaddr = vme_vaddr; + tag->_space_map = vme_a16_map; + tag->_space_unmap = vme_a16_unmap; + break; + } + + tag->_space_subregion = vme_subregion; + tag->_space_vaddr = vme_vaddr; + tag->_space_read_1 = generic_space_read_1; + tag->_space_write_1 = generic_space_write_1; + + switch (dspace) { + case VME_D32: + tag->_space_read_2 = generic_space_read_2; + tag->_space_write_2 = generic_space_write_2; + tag->_space_read_4 = generic_space_read_4; + tag->_space_write_4 = generic_space_write_4; + tag->_space_read_raw_2 = generic_space_read_raw_2; + tag->_space_write_raw_2 = generic_space_write_raw_2; + tag->_space_read_raw_4 = generic_space_read_raw_4; + tag->_space_write_raw_4 = generic_space_write_raw_4; + break; + case VME_D16: + tag->_space_read_2 = generic_space_read_2; + tag->_space_write_2 = generic_space_write_2; + tag->_space_read_4 = vme_d16_space_read_4; + tag->_space_write_4 = vme_d16_space_write_4; + tag->_space_read_raw_2 = generic_space_read_raw_2; + tag->_space_write_raw_2 = generic_space_write_raw_2; + tag->_space_read_raw_4 = vme_d16_space_read_raw_4; + tag->_space_write_raw_4 = vme_d16_space_write_raw_4; + break; + case VME_D8: + tag->_space_read_2 = vme_d8_space_read_2; + tag->_space_write_2 = vme_d8_space_write_2; + tag->_space_read_4 = vme_d8_space_read_4; + tag->_space_write_4 = vme_d8_space_write_4; + tag->_space_read_raw_2 = vme_d8_space_read_raw_2; + tag->_space_write_raw_2 = vme_d8_space_write_raw_2; + tag->_space_read_raw_4 = vme_d8_space_read_raw_4; + tag->_space_write_raw_4 = vme_d8_space_write_raw_4; break; } diff --git a/sys/arch/aviion/include/bus.h b/sys/arch/aviion/include/bus.h index afe9cf8de6a..a81fd5bd92b 100644 --- a/sys/arch/aviion/include/bus.h +++ b/sys/arch/aviion/include/bus.h @@ -1,5 +1,7 @@ -/* $OpenBSD: bus.h,v 1.2 2009/07/30 21:39:52 miod Exp $ */ +/* $OpenBSD: bus.h,v 1.3 2010/04/20 22:53:24 miod Exp $ */ + /* + * Copyright (c) 2003-2004 Opsycon AB Sweden. All rights reserved. * Copyright (c) 2004, Miodrag Vallat. * * Redistribution and use in source and binary forms, with or without @@ -12,713 +14,352 @@ * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * Simple aviion bus_space implementation. - * - * Currently, we only need specific handling for 32 bit read/writes in D16 - * space, and this choice is made at compile time. As a result, all the - * implementation can go through macros or inline functions, except for - * the management functions. - */ - -#ifndef _AVIION_BUS_H_ -#define _AVIION_BUS_H_ +#ifndef _AVIION_BUS_H_ +#define _AVIION_BUS_H_ #include <machine/asm_macro.h> -typedef u_int32_t bus_addr_t; -typedef u_int32_t bus_size_t; +#ifdef __STDC__ +#define CAT(a,b) a##b +#define CAT3(a,b,c) a##b##c +#else +#define CAT(a,b) a/**/b +#define CAT3(a,b,c) a/**/b/**/c +#endif -typedef u_int32_t bus_space_handle_t; +/* + * bus_space implementation + */ -struct aviion_bus_space_tag { - int (*bs_map)(bus_addr_t, bus_size_t, int, bus_space_handle_t *); - void (*bs_unmap)(bus_space_handle_t, bus_size_t); - int (*bs_subregion)(bus_space_handle_t, bus_size_t, bus_size_t, - bus_space_handle_t *); - void * (*bs_vaddr)(bus_space_handle_t); - /* alloc, free not implemented yet */ -}; +typedef uint32_t bus_addr_t; +typedef uint32_t bus_size_t; +struct aviion_bus_space_tag; typedef const struct aviion_bus_space_tag *bus_space_tag_t; +typedef uint32_t bus_space_handle_t; -#define BUS_SPACE_BARRIER_READ 0x01 -#define BUS_SPACE_BARRIER_WRITE 0x02 - -#define BUS_SPACE_MAP_CACHEABLE 0x01 -#define BUS_SPACE_MAP_LINEAR 0x02 - -/* - * General bus_space function set - */ - -#define bus_space_map(t,a,s,f,r) ((t)->bs_map(a,s,f,r)) -#define bus_space_unmap(t,h,s) ((t)->bs_unmap(h,s)) -#define bus_space_subregion(t,h,o,s,r) ((t)->bs_subregion(h,o,s,r)) -#define bus_space_vaddr(t,h) ((t)->bs_vaddr(h)) - -static void bus_space_barrier(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, bus_size_t, int); +struct aviion_bus_space_tag { + int (*_space_map)(bus_space_tag_t, bus_addr_t, + bus_size_t, int, bus_space_handle_t *); + void (*_space_unmap)(bus_space_tag_t, bus_space_handle_t, + bus_size_t); + int (*_space_subregion)(bus_space_tag_t, bus_space_handle_t, + bus_size_t, bus_size_t, bus_space_handle_t *); + void * (*_space_vaddr)(bus_space_tag_t, bus_space_handle_t); + /* alloc, free not implemented yet */ -static __inline__ void -bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, bus_size_t size, int flags) -{ - flush_pipeline(); /* overkill? */ -} + u_int8_t (*_space_read_1)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_1)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int8_t); + u_int16_t (*_space_read_2)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_2)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int16_t); + u_int32_t (*_space_read_4)(bus_space_tag_t , bus_space_handle_t, + bus_size_t); + void (*_space_write_4)(bus_space_tag_t , bus_space_handle_t, + bus_size_t, u_int32_t); + void (*_space_read_raw_2)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_2)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); + void (*_space_read_raw_4)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, u_int8_t *, bus_size_t); + void (*_space_write_raw_4)(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const u_int8_t *, bus_size_t); +}; +#define bus_space_read_1(t, h, o) (*(t)->_space_read_1)((t), (h), (o)) +#define bus_space_read_2(t, h, o) (*(t)->_space_read_2)((t), (h), (o)) +#define bus_space_read_4(t, h, o) (*(t)->_space_read_4)((t), (h), (o)) + +#define bus_space_write_1(t, h, o, v) (*(t)->_space_write_1)((t), (h), (o), (v)) +#define bus_space_write_2(t, h, o, v) (*(t)->_space_write_2)((t), (h), (o), (v)) +#define bus_space_write_4(t, h, o, v) (*(t)->_space_write_4)((t), (h), (o), (v)) + +#define bus_space_read_raw_multi_2(t, h, a, b, l) \ + (*(t)->_space_read_raw_2)((t), (h), (a), (b), (l)) +#define bus_space_read_raw_multi_4(t, h, a, b, l) \ + (*(t)->_space_read_raw_4)((t), (h), (a), (b), (l)) + +#define bus_space_write_raw_multi_2(t, h, a, b, l) \ + (*(t)->_space_write_raw_2)((t), (h), (a), (b), (l)) +#define bus_space_write_raw_multi_4(t, h, a, b, l) \ + (*(t)->_space_write_raw_4)((t), (h), (a), (b), (l)) + +#define bus_space_map(t, o, s, c, p) \ + (*(t)->_space_map)((t), (o), (s), (c), (p)) +#define bus_space_unmap(t, h, s) \ + (*(t)->_space_unmap)((t), (h), (s)) +#define bus_space_subregion(t, h, o, s, p) \ + (*(t)->_space_subregion)((t), (h), (o), (s), (p)) + +#define BUS_SPACE_MAP_CACHEABLE 0x01 +#define BUS_SPACE_MAP_LINEAR 0x02 +#define BUS_SPACE_MAP_PREFETCHABLE 0x04 + +#define bus_space_vaddr(t, h) (*(t)->_space_vaddr)((t), (h)) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_multi(n,m) \ +static __inline void \ +CAT(bus_space_read_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t o, CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) \ + *x++ = CAT(bus_space_read_,n)(bst, bsh, o); \ +} + +bus_space_read_multi(1,8) +bus_space_read_multi(2,16) +bus_space_read_multi(4,32) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_region(n,m) \ +static __inline void \ +CAT(bus_space_read_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) \ + *x++ = CAT(bus_space_read_,n)(bst, bsh, ba++); \ +} + +bus_space_read_region(1,8) +bus_space_read_region(2,16) +bus_space_read_region(4,32) + +/*----------------------------------------------------------------------------*/ +#define bus_space_read_raw_region(n,m) \ +static __inline void \ +CAT(bus_space_read_raw_region_,n)(bus_space_tag_t bst, \ + bus_space_handle_t bsh, \ + bus_addr_t ba, u_int8_t *x, size_t cnt) \ +{ \ + cnt >>= ((n) >> 1); \ + while (cnt--) { \ + CAT(bus_space_read_raw_multi_,n)(bst, bsh, ba, x, (n)); \ + ba += (n); \ + x += (n); \ + } \ +} + +bus_space_read_raw_region(2,16) +bus_space_read_raw_region(4,32) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_multi(n,m) \ +static __inline void \ +CAT(bus_space_write_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t o, const CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh, o, *x++); \ + } \ +} + +bus_space_write_multi(1,8) +bus_space_write_multi(2,16) +bus_space_write_multi(4,32) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_region(n,m) \ +static __inline void \ +CAT(bus_space_write_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, const CAT3(u_int,m,_t) *x, size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh, ba, *x++); \ + ba += sizeof(x); \ + } \ +} + +bus_space_write_region(1,8) +bus_space_write_region(2,16) +bus_space_write_region(4,32) + +/*----------------------------------------------------------------------------*/ +#define bus_space_write_raw_region(n,m) \ +static __inline void \ +CAT(bus_space_write_raw_region_,n)(bus_space_tag_t bst, \ + bus_space_handle_t bsh, \ + bus_addr_t ba, const u_int8_t *x, size_t cnt) \ +{ \ + cnt >>= ((n) >> 1); \ + while (cnt--) { \ + CAT(bus_space_write_raw_multi_,n)(bst, bsh, ba, x, (n)); \ + ba += (n); \ + x += (n); \ + } \ +} + +bus_space_write_raw_region(2,16) +bus_space_write_raw_region(4,32) + +/*----------------------------------------------------------------------------*/ +#define bus_space_set_region(n,m) \ +static __inline void \ +CAT(bus_space_set_region_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(u_int,m,_t) x, size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh, ba, x); \ + ba += sizeof(x); \ + } \ +} + +bus_space_set_region(1,8) +bus_space_set_region(2,16) +bus_space_set_region(4,32) + +/*----------------------------------------------------------------------------*/ +#define bus_space_copy(n) \ +static __inline void \ +CAT(bus_space_copy_,n)(bus_space_tag_t bst, bus_space_handle_t bsh1, \ + bus_size_t o1, bus_space_handle_t bsh2, bus_size_t o2, bus_size_t cnt) \ +{ \ + while (cnt--) { \ + CAT(bus_space_write_,n)(bst, bsh2, o2, \ + CAT(bus_space_read_,n)(bst, bsh1, o1)); \ + o1 += (n); \ + o2 += (n); \ + } \ +} + +bus_space_copy(1) +bus_space_copy(2) +bus_space_copy(4) + +uint8_t generic_space_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint16_t generic_space_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t); +uint32_t generic_space_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t); +void generic_space_read_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint8_t); +void generic_space_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint16_t); +void generic_space_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, + uint32_t); +void generic_space_write_raw_2(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); +void generic_space_read_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, uint8_t *, bus_size_t); +void generic_space_write_raw_4(bus_space_tag_t, bus_space_handle_t, + bus_addr_t, const uint8_t *, bus_size_t); + +/*----------------------------------------------------------------------------*/ /* - * Read/Write/Region functions for D8 and D16 access. - * Most of these are straightforward and assume that everything is properly - * aligned. + * Bus read/write barrier methods. + * + * void bus_space_barrier(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * bus_size_t len, int flags); + * */ - -#define bus_space_read_1(tag, handle, offset) \ - ((void)(tag), *(volatile u_int8_t *)((handle) + (offset))) -#define bus_space_read_2(tag, handle, offset) \ - ((void)(tag), *(volatile u_int16_t *)((handle) + (offset))) - -static void bus_space_read_multi_1(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int8_t *, size_t); - -static __inline__ void -bus_space_read_multi_1(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int8_t *dest, size_t count) +static inline void +bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, + bus_size_t length, int flags) { - offset += handle; - while ((int)--count >= 0) - *dest++ = bus_space_read_1(tag, 0, offset); + flush_pipeline(); } -static void bus_space_read_multi_2(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int16_t *, size_t); - -static __inline__ void -bus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int16_t *dest, size_t count) -{ - offset += handle; - while ((int)--count >= 0) - *dest++ = bus_space_read_2(tag, 0, offset); -} - -static void bus_space_read_raw_multi_2(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int8_t *, size_t); - -static __inline__ void -bus_space_read_raw_multi_2(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int8_t *dest, size_t size) -{ - offset += handle; - size >>= 1; - while ((int)--size >= 0) { - *(u_int16_t *)dest = - bus_space_read_2(tag, 0, offset); - dest += 2; - } -} - -static void bus_space_read_region_1(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int8_t *, size_t); - -static __inline__ void -bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int8_t *dest, size_t count) -{ - offset += handle; - while ((int)--count >= 0) - *dest++ = bus_space_read_1(tag, 0, offset++); -} - -static void bus_space_read_region_2(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int16_t *, size_t); - -static __inline__ void -bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int16_t *dest, size_t count) -{ - offset += handle; - while ((int)--count >= 0) { - *dest++ = bus_space_read_2(tag, 0, offset); - offset += 2; - } -} - -static void bus_space_read_raw_region_2(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int8_t *, size_t); - -static __inline__ void -bus_space_read_raw_region_2(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int8_t *dest, size_t size) -{ - size >>= 1; - offset += handle; - while ((int)--size >= 0) { - *(u_int16_t *)dest = bus_space_read_2(tag, 0, offset); - offset += 2; - dest += 2; - } -} - -#define bus_space_write_1(tag, handle, offset, value) \ - ((void)(tag), *(volatile u_int8_t *)((handle) + (offset)) = (value)) -#define bus_space_write_2(tag, handle, offset, value) \ - ((void)(tag), *(volatile u_int16_t *)((handle) + (offset)) = (value)) - -static void bus_space_write_multi_1(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int8_t *, size_t); - -static __inline__ void -bus_space_write_multi_1(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int8_t *dest, size_t count) -{ - offset += handle; - while ((int)--count >= 0) - bus_space_write_1(tag, 0, offset, *dest++); -} - -static void bus_space_write_multi_2(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int16_t *, size_t); - -static __inline__ void -bus_space_write_multi_2(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int16_t *dest, size_t count) -{ - offset += handle; - while ((int)--count >= 0) - bus_space_write_2(tag, 0, offset, *dest++); -} - -static void bus_space_write_raw_multi_2(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int8_t *, size_t); - -static __inline__ void -bus_space_write_raw_multi_2(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int8_t *dest, size_t size) -{ - offset += handle; - size >>= 1; - while ((int)--size >= 0) { - bus_space_write_2(tag, 0, offset, *(u_int16_t *)dest); - dest += 2; - } -} - -static void bus_space_set_multi_1(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int8_t, size_t); - -static __inline__ void -bus_space_set_multi_1(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int8_t value, size_t count) -{ - offset += handle; - while ((int)--count >= 0) - bus_space_write_1(tag, 0, offset, value); -} - -static void bus_space_set_multi_2(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int16_t, size_t); - -static __inline__ void -bus_space_set_multi_2(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int16_t value, size_t count) -{ - offset += handle; - while ((int)--count >= 0) - bus_space_write_2(tag, 0, offset, value); -} - -static void bus_space_write_region_1(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int8_t *, size_t); - -static __inline__ void -bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int8_t *dest, size_t count) -{ - offset += handle; - while ((int)--count >= 0) - bus_space_write_1(tag, 0, offset++, *dest++); -} - -static void bus_space_write_region_2(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int16_t *, size_t); - -static __inline__ void -bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int16_t *dest, size_t count) -{ - offset += handle; - while ((int)--count >= 0) { - bus_space_write_2(tag, 0, offset, *dest++); - offset += 2; - } -} - -static void bus_space_write_raw_region_2(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int8_t *, size_t); - -static __inline__ void -bus_space_write_raw_region_2(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int8_t *dest, size_t size) -{ - offset += handle; - size >>= 1; - while ((int)--size >= 0) { - bus_space_write_2(tag, 0, offset, *(u_int16_t *)dest); - offset += 2; - dest += 2; - } -} - -static void bus_space_set_region_1(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int8_t, size_t); - -static __inline__ void -bus_space_set_region_1(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int8_t value, size_t count) -{ - offset += handle; - while ((int)--count >= 0) - bus_space_write_1(tag, 0, offset++, value); -} - -static void bus_space_set_region_2(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int16_t, size_t); - -static __inline__ void -bus_space_set_region_2(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int16_t value, size_t count) -{ - offset += handle; - while ((int)--count >= 0) { - bus_space_write_2(tag, 0, offset, value); - offset += 2; - } -} - -static void bus_space_copy_1(bus_space_tag_t, bus_space_handle_t, bus_addr_t, - bus_space_handle_t, bus_addr_t, bus_size_t); - -static __inline__ void -bus_space_copy_1(bus_space_tag_t tag, bus_space_handle_t h1, bus_addr_t o1, - bus_space_handle_t h2, bus_addr_t o2, bus_size_t count) -{ - o1 += h1; - o2 += h2; - while ((int)--count >= 0) { - *((volatile u_int8_t *)o1)++ = *((volatile u_int8_t *)o2)++; - } -} - -static void bus_space_copy_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t, - bus_space_handle_t, bus_addr_t, bus_size_t); - -static __inline__ void -bus_space_copy_2(bus_space_tag_t tag, bus_space_handle_t h1, bus_addr_t o1, - bus_space_handle_t h2, bus_addr_t o2, bus_size_t count) -{ - o1 += h1; - o2 += h2; - while ((int)--count >= 0) { - *(volatile u_int16_t *)o1 = *(volatile u_int16_t *)o2; - o1 += 2; - o2 += 2; - } -} +#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ +#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ /* - * Unrestricted D32 access + * bus_dma implementation */ -#ifndef __BUS_SPACE_RESTRICT_D16__ - -#define bus_space_read_4(tag, handle, offset) \ - ((void)(tag), *(volatile u_int32_t *)((handle) + (offset))) - -static void bus_space_read_multi_4(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int32_t *, size_t); - -static __inline__ void -bus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int32_t *dest, size_t count) -{ - offset += handle; - while ((int)--count >= 0) - *dest++ = bus_space_read_4(tag, 0, offset); -} - -static void bus_space_read_raw_multi_4(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int8_t *, size_t); - -static __inline__ void -bus_space_read_raw_multi_4(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int8_t *dest, size_t size) -{ - offset += handle; - size >>= 2; - while ((int)--size >= 0) { - *(u_int32_t *)dest = - bus_space_read_4(tag, 0, offset); - dest += 4; - } -} - -static void bus_space_read_region_4(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int32_t *, size_t); - -static __inline__ void -bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int32_t *dest, size_t count) -{ - offset += handle; - while ((int)--count >= 0) { - *dest++ = bus_space_read_4(tag, 0, offset); - offset += 4; - } -} - -static void bus_space_read_raw_region_4(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int8_t *, size_t); - -static __inline__ void -bus_space_read_raw_region_4(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int8_t *dest, size_t size) -{ - size >>= 2; - offset += handle; - while ((int)--size >= 0) { - *(u_int32_t *)dest = bus_space_read_4(tag, 0, offset); - offset += 4; - dest += 4; - } -} - -#define bus_space_write_4(tag, handle, offset, value) \ - ((void)(tag), *(volatile u_int32_t *)((handle) + (offset)) = (value)) - -static void bus_space_write_multi_4(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int32_t *, size_t); - -static __inline__ void -bus_space_write_multi_4(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int32_t *dest, size_t count) -{ - offset += handle; - while ((int)--count >= 0) - bus_space_write_4(tag, 0, offset, *dest++); -} - -static void bus_space_write_raw_multi_4(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int8_t *, size_t); - -static __inline__ void -bus_space_write_raw_multi_4(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int8_t *dest, size_t size) -{ - offset += handle; - size >>= 2; - while ((int)--size >= 0) { - bus_space_write_4(tag, 0, offset, *(u_int32_t *)dest); - dest += 4; - } -} - -static void bus_space_set_multi_4(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int32_t, size_t); - -static __inline__ void -bus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int32_t value, size_t count) -{ - offset += handle; - while ((int)--count >= 0) - bus_space_write_4(tag, 0, offset, value); -} - -static void bus_space_write_region_4(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int32_t *, size_t); - -static __inline__ void -bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int32_t *dest, size_t count) -{ - offset += handle; - while ((int)--count >= 0) { - bus_space_write_4(tag, 0, offset, *dest++); - offset += 4; - } -} - -static void bus_space_write_raw_region_4(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int8_t *, size_t); - -static __inline__ void -bus_space_write_raw_region_4(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int8_t *dest, size_t size) -{ - offset += handle; - size >>= 2; - while ((int)--size >= 0) { - bus_space_write_4(tag, 0, offset, *(u_int32_t *)dest); - offset += 4; - dest += 4; - } -} - -static void bus_space_set_region_4(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int32_t, size_t); - -static __inline__ void -bus_space_set_region_4(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int32_t value, size_t count) -{ - offset += handle; - while ((int)--count >= 0) { - bus_space_write_4(tag, 0, offset, value); - offset += 4; - } -} - -static void bus_space_copy_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t, - bus_space_handle_t, bus_addr_t, bus_size_t); - -static __inline__ void -bus_space_copy_4(bus_space_tag_t tag, bus_space_handle_t h1, bus_addr_t o1, - bus_space_handle_t h2, bus_addr_t o2, bus_size_t count) -{ - o1 += h1; - o2 += h2; - while ((int)--count >= 0) { - *(volatile u_int32_t *)o1 = *(volatile u_int32_t *)o2; - o1 += 4; - o2 += 4; - } -} - -#else /* __BUS_SPACE_RESTRICT_D16__ */ +#define BUS_DMA_WAITOK 0x000 /* safe to sleep (pseudo-flag) */ +#define BUS_DMA_NOWAIT 0x001 /* not safe to sleep */ +#define BUS_DMA_ALLOCNOW 0x002 /* perform resource allocation now */ +#define BUS_DMA_COHERENT 0x004 /* hint: map memory DMA coherent */ +#define BUS_DMA_BUS1 0x010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x020 +#define BUS_DMA_BUS3 0x040 +#define BUS_DMA_BUS4 0x080 +#define BUS_DMA_READ 0x100 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x200 /* mapping is memory -> device only */ +#define BUS_DMA_STREAMING 0x400 /* hint: sequential, unidirectional */ +#define BUS_DMA_ZERO 0x800 /* zero memory in dmamem_alloc */ + +#define BUS_DMASYNC_PREREAD 0x01 +#define BUS_DMASYNC_POSTREAD 0x02 +#define BUS_DMASYNC_PREWRITE 0x04 +#define BUS_DMASYNC_POSTWRITE 0x08 + +typedef u_int32_t bus_dma_tag_t; /* ignored, really */ /* - * Restricted D32 access - done through two adjacent D16 access. + * bus_dma_segment_t * - * The speed of the basic read and write routines is critical. - * This implementation uses a temporary variable on stack, and does - * two 16 bit load&store sequences. Since the stack is in Dcache, this - * is faster and spills fewer register than a register-only sequence - * (which would need to ld.h into two distinct registers, then extu - * the second one into itself, and or both in the result register). + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. */ - -static u_int32_t d16_read_4(vaddr_t); -static void d16_write_4(vaddr_t, u_int32_t); - -static __inline__ u_int32_t -d16_read_4(vaddr_t va) -{ - u_int32_t tmp; - - *(u_int16_t *)&tmp = *(volatile u_int16_t *)va; - *(u_int16_t *)((vaddr_t)&tmp + 2) = *(volatile u_int16_t *)(va + 2); - - return tmp; -} - -static __inline__ void -d16_write_4(vaddr_t va, u_int32_t value) -{ - u_int32_t tmp = value; - - *(volatile u_int16_t *)va = *(u_int16_t *)&tmp; - *(volatile u_int16_t *)(va + 2) = *(u_int16_t *)((vaddr_t)&tmp + 2); -} - -#define bus_space_read_4(tag, handle, offset) \ - ((void)(tag), d16_read_4((handle) + (offset))) - -static void bus_space_read_multi_4(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int32_t *, size_t); - -static __inline__ void -bus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int32_t *dest, size_t count) -{ - offset += handle; - while ((int)--count >= 0) - *dest++ = bus_space_read_4(tag, 0, offset); -} - -static void bus_space_read_raw_multi_4(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int8_t *, size_t); - -static __inline__ void -bus_space_read_raw_multi_4(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int8_t *dest, size_t size) -{ - offset += handle; - size >>= 1; - while ((int)--size >= 0) { - *(u_int16_t *)dest = bus_space_read_2(tag, 0, offset); - dest += 2; - } -} - -static void bus_space_read_region_4(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int32_t *, size_t); - -static __inline__ void -bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int32_t *__dest, size_t count) -{ - u_int16_t *dest = (u_int16_t *)__dest; - - offset += handle; - count <<= 1; - while ((int)--count >= 0) { - *dest++ = bus_space_read_2(tag, 0, offset); - offset += 2; - } -} - -static void bus_space_read_raw_region_4(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int8_t *, size_t); - -static __inline__ void -bus_space_read_raw_region_4(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int8_t *dest, size_t size) -{ - size >>= 1; - offset += handle; - while ((int)--size >= 0) { - *(u_int16_t *)dest = bus_space_read_2(tag, 0, offset); - offset += 2; - dest += 2; - } -} - -#define bus_space_write_4(tag, handle, offset, value) \ - ((void)(tag), d16_write_4((handle) + (offset), (value))) - -static void bus_space_write_multi_4(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int32_t *, size_t); - -static __inline__ void -bus_space_write_multi_4(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int32_t *dest, size_t count) -{ - offset += handle; - while ((int)--count >= 0) - bus_space_write_4(tag, 0, offset, *dest++); -} - -static void bus_space_write_raw_multi_4(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int8_t *, size_t); - -static __inline__ void -bus_space_write_raw_multi_4(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int8_t *dest, size_t size) -{ - offset += handle; - size >>= 1; - while ((int)--size >= 0) { - bus_space_write_2(tag, 0, offset, *(u_int16_t *)dest); - dest += 2; - } -} - -static void bus_space_set_multi_4(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int32_t, size_t); - -static __inline__ void -bus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int32_t value, size_t count) -{ - offset += handle; - while ((int)--count >= 0) - bus_space_write_4(tag, 0, offset, value); -} - -static void bus_space_write_region_4(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int32_t *, size_t); - -static __inline__ void -bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int32_t *__dest, size_t count) -{ - u_int16_t *dest = (u_int16_t *)__dest; - - offset += handle; - count <<= 1; - while ((int)--count >= 0) { - bus_space_write_2(tag, 0, offset, *dest++); - offset += 2; - } -} - -static void bus_space_write_raw_region_4(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int8_t *, size_t); - -static __inline__ void -bus_space_write_raw_region_4(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int8_t *dest, size_t size) -{ - offset += handle; - size >>= 1; - while ((int)--size >= 0) { - bus_space_write_2(tag, 0, offset, *(u_int16_t *)dest); - offset += 2; - dest += 2; - } -} - -static void bus_space_set_region_4(bus_space_tag_t, bus_space_handle_t, - bus_addr_t, u_int32_t, size_t); - -static __inline__ void -bus_space_set_region_4(bus_space_tag_t tag, bus_space_handle_t handle, - bus_addr_t offset, u_int32_t value, size_t count) -{ - offset += handle; - while ((int)--count >= 0) { - bus_space_write_4(tag, 0, offset, value); - offset += 4; - } -} - -static void bus_space_copy_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t, - bus_space_handle_t, bus_addr_t, bus_size_t); - -static __inline__ void -bus_space_copy_4(bus_space_tag_t tag, bus_space_handle_t h1, bus_addr_t o1, - bus_space_handle_t h2, bus_addr_t o2, bus_size_t count) -{ - o1 += h1; - o2 += h2; - count <<= 1; - while ((int)--count >= 0) { - *(volatile u_int16_t *)o1 = *(volatile u_int16_t *)o2; - o1 += 2; - o2 += 2; - } -} +struct m88k_bus_dma_segment { + bus_addr_t ds_addr; /* DMA address */ + bus_size_t ds_len; /* length of transfer */ +}; +typedef struct m88k_bus_dma_segment bus_dma_segment_t; /* - * Extra D16 access functions (see vme.c) + * bus_dmamap_t + * + * Describes a DMA mapping. */ - -void d16_bcopy(const void *, void *, size_t); -void d16_bzero(void *, size_t); - -#endif /* __BUS_SPACE_RESTRICT_D16__ */ +struct m88k_bus_dmamap { + bus_size_t _dm_size; /* largest DMA transfer mappable */ + int _dm_segcnt; /* number of segs this map can map */ + bus_size_t _dm_maxsegsz; /* largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; +typedef struct m88k_bus_dmamap *bus_dmamap_t; + +struct mbuf; +struct proc; +struct uio; + +int bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t, + bus_size_t, int, bus_dmamap_t *); +void bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); +int bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); +int bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, + struct mbuf *, int); +int bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, + struct uio *, int); +int bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, bus_dma_segment_t *, + int, bus_size_t, int); +void bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t); +void bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, + bus_size_t, int); + +int bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size, + bus_size_t alignment, bus_size_t boundary, + bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags); +void bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs); +int bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs, size_t size, caddr_t *kvap, int flags); +void bus_dmamem_unmap(bus_dma_tag_t tag, caddr_t kva, + size_t size); +paddr_t bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs, off_t off, int prot, int flags); #endif /* _AVIION_BUS_H_ */ |