diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-01-20 18:34:01 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-01-20 18:34:01 +0000 |
commit | ea3f377d3a56172916334dc76dcf436d0f1e97be (patch) | |
tree | 98f0ab8c77cd5bd170ae6028f61449677689921a /sys/arch/powerpc | |
parent | d6c8b32347fc87a189709a2a67f355a7a7107605 (diff) |
Merge two copies of the (almost) identical bus space code into one file.
This brings bus_space_mmap(9) to socppc and change its bus_space_map(9)
implementation to use kernel_map instead of phys_map like macppc and
everybody else.
Diffstat (limited to 'sys/arch/powerpc')
-rw-r--r-- | sys/arch/powerpc/conf/files.powerpc | 3 | ||||
-rw-r--r-- | sys/arch/powerpc/powerpc/bus_space.c | 376 |
2 files changed, 378 insertions, 1 deletions
diff --git a/sys/arch/powerpc/conf/files.powerpc b/sys/arch/powerpc/conf/files.powerpc index 5c72c873f68..c5ee14b8f0f 100644 --- a/sys/arch/powerpc/conf/files.powerpc +++ b/sys/arch/powerpc/conf/files.powerpc @@ -1,4 +1,4 @@ -# $OpenBSD: files.powerpc,v 1.49 2015/01/20 17:08:35 mpi Exp $ +# $OpenBSD: files.powerpc,v 1.50 2015/01/20 18:34:00 mpi Exp $ # file arch/powerpc/powerpc/setjmp.S ddb @@ -7,6 +7,7 @@ file arch/powerpc/powerpc/cpu_subr.c file arch/powerpc/powerpc/fpu.c file arch/powerpc/powerpc/in_cksum.c inet file arch/powerpc/powerpc/bus_dma.c +file arch/powerpc/powerpc/bus_space.c file arch/powerpc/powerpc/pmap.c file arch/powerpc/powerpc/process_machdep.c file arch/powerpc/powerpc/sys_machdep.c diff --git a/sys/arch/powerpc/powerpc/bus_space.c b/sys/arch/powerpc/powerpc/bus_space.c new file mode 100644 index 00000000000..8aee3581309 --- /dev/null +++ b/sys/arch/powerpc/powerpc/bus_space.c @@ -0,0 +1,376 @@ +/* $OpenBSD: bus_space.c,v 1.1 2015/01/20 18:34:00 mpi Exp $ */ +/* $NetBSD: machdep.c,v 1.4 1996/10/16 19:33:11 ws Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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/systm.h> +#include <sys/malloc.h> +#include <sys/extent.h> + +#include <uvm/uvm_extern.h> + +#include <machine/bus.h> + +extern int ppc_malloc_ok; +extern struct extent *devio_ex; + +int bus_mem_add_mapping(bus_addr_t, bus_size_t, int, bus_space_handle_t *); +bus_addr_t bus_space_unmap_p(bus_space_tag_t, bus_space_handle_t, bus_size_t); +void bus_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t); + + +/* BUS functions */ +int +bus_space_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, + int flags, bus_space_handle_t *bshp) +{ + int error; + + if (POWERPC_BUS_TAG_BASE(t) == 0) { + /* if bus has base of 0 fail. */ + return EINVAL; + } + bpa |= POWERPC_BUS_TAG_BASE(t); + if ((error = extent_alloc_region(devio_ex, bpa, size, EX_NOWAIT | + (ppc_malloc_ok ? EX_MALLOCOK : 0)))) + return error; + + if ((error = bus_mem_add_mapping(bpa, size, flags, bshp))) { + if (extent_free(devio_ex, bpa, size, EX_NOWAIT | + (ppc_malloc_ok ? EX_MALLOCOK : 0))) + { + printf("bus_space_map: pa 0x%lx, size 0x%lx\n", + bpa, size); + printf("bus_space_map: can't free region\n"); + } + } + return error; +} + +bus_addr_t +bus_space_unmap_p(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) +{ + bus_addr_t paddr; + + pmap_extract(pmap_kernel(), bsh, &paddr); + bus_space_unmap((t), (bsh), (size)); + return paddr ; +} + +void +bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) +{ + bus_addr_t sva; + bus_size_t off, len; + bus_addr_t bpa; + + /* should this verify that the proper size is freed? */ + sva = trunc_page(bsh); + off = bsh - sva; + len = size+off; + + if (pmap_extract(pmap_kernel(), sva, &bpa) == TRUE) { + if (extent_free(devio_ex, bpa | (bsh & PAGE_MASK), size, EX_NOWAIT | + (ppc_malloc_ok ? EX_MALLOCOK : 0))) + { + printf("bus_space_map: pa 0x%lx, size 0x%lx\n", + bpa, size); + printf("bus_space_map: can't free region\n"); + } + } + /* do not free memory which was stolen from the vm system */ + if (ppc_malloc_ok && + ((sva >= VM_MIN_KERNEL_ADDRESS) && (sva < VM_MAX_KERNEL_ADDRESS))) + uvm_km_free(kernel_map, sva, len); + else { + pmap_remove(pmap_kernel(), sva, sva + len); + pmap_update(pmap_kernel()); + } +} + +paddr_t +bus_space_mmap(bus_space_tag_t t, bus_addr_t bpa, off_t off, int prot, + int flags) +{ + int pmapflags = PMAP_NOCACHE; + + if (POWERPC_BUS_TAG_BASE(t) == 0) + return (-1); + + bpa |= POWERPC_BUS_TAG_BASE(t); + + if (flags & BUS_SPACE_MAP_CACHEABLE) + pmapflags &= ~PMAP_NOCACHE; + + return ((bpa + off) | pmapflags); +} + +vaddr_t ppc_kvm_stolen = VM_KERN_ADDRESS_SIZE; + +int +bus_mem_add_mapping(bus_addr_t bpa, bus_size_t size, int flags, + bus_space_handle_t *bshp) +{ + bus_addr_t vaddr; + bus_addr_t spa, epa; + bus_size_t off; + int len; + + spa = trunc_page(bpa); + epa = bpa + size; + off = bpa - spa; + len = size+off; + +#if 0 + if (epa <= spa) { + panic("bus_mem_add_mapping: overflow"); + } +#endif + if (ppc_malloc_ok == 0) { + bus_size_t alloc_size; + + /* need to steal vm space before kernel vm is initialized */ + alloc_size = round_page(len); + + vaddr = VM_MIN_KERNEL_ADDRESS + ppc_kvm_stolen; + ppc_kvm_stolen += alloc_size; + if (ppc_kvm_stolen > PPC_SEGMENT_LENGTH) { + panic("ppc_kvm_stolen, out of space"); + } + } else { + vaddr = uvm_km_valloc(kernel_map, len); + if (vaddr == 0) + return (ENOMEM); + } + *bshp = vaddr + off; +#ifdef DEBUG_BUS_MEM_ADD_MAPPING + printf("mapping %x size %x to %x vbase %x\n", + bpa, size, *bshp, spa); +#endif + for (; len > 0; len -= PAGE_SIZE) { + pmap_kenter_cache(vaddr, spa, PROT_READ | PROT_WRITE, + (flags & BUS_SPACE_MAP_CACHEABLE) ? + PMAP_CACHE_WT : PMAP_CACHE_CI); + spa += PAGE_SIZE; + vaddr += PAGE_SIZE; + } + return 0; +} + +int +bus_space_alloc(bus_space_tag_t tag, bus_addr_t rstart, bus_addr_t rend, + bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags, + bus_addr_t *addrp, bus_space_handle_t *handlep) +{ + + panic("bus_space_alloc: unimplemented"); +} + +void +bus_space_free(bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t size) +{ + + panic("bus_space_free: unimplemented"); +} + +void * +mapiodev(paddr_t pa, psize_t len) +{ + paddr_t spa; + vaddr_t vaddr, va; + int off; + int size; + + spa = trunc_page(pa); + off = pa - spa; + size = round_page(off+len); + if (ppc_malloc_ok == 0) { + /* need to steal vm space before kernel vm is initialized */ + va = VM_MIN_KERNEL_ADDRESS + ppc_kvm_stolen; + ppc_kvm_stolen += size; + if (ppc_kvm_stolen > PPC_SEGMENT_LENGTH) { + panic("ppc_kvm_stolen, out of space"); + } + } else { + va = uvm_km_valloc(kernel_map, size); + } + + if (va == 0) + return NULL; + + for (vaddr = va; size > 0; size -= PAGE_SIZE) { + pmap_kenter_cache(vaddr, spa, + PROT_READ | PROT_WRITE, PMAP_CACHE_DEFAULT); + spa += PAGE_SIZE; + vaddr += PAGE_SIZE; + } + return (void *) (va+off); +} + +void +unmapiodev(void *kva, psize_t p_size) +{ + vaddr_t vaddr; + int size; + + size = p_size; + + vaddr = trunc_page((vaddr_t)kva); + + uvm_km_free(kernel_map, vaddr, size); + + for (; size > 0; size -= PAGE_SIZE) { + pmap_remove(pmap_kernel(), vaddr, vaddr + PAGE_SIZE - 1); + vaddr += PAGE_SIZE; + } + pmap_update(pmap_kernel()); +} + + +/* + * probably should be ppc_space_copy + */ + +#define _CONCAT(A,B) A ## B +#define __C(A,B) _CONCAT(A,B) + +#define BUS_SPACE_COPY_N(BYTES,TYPE) \ +void \ +__C(bus_space_copy_,BYTES)(void *v, bus_space_handle_t h1, \ + bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, \ + bus_size_t c) \ +{ \ + TYPE *src, *dst; \ + int i; \ + \ + src = (TYPE *) (h1+o1); \ + dst = (TYPE *) (h2+o2); \ + \ + if (h1 == h2 && o2 > o1) \ + for (i = c-1; i >= 0; i--) \ + dst[i] = src[i]; \ + else \ + for (i = 0; i < c; i++) \ + dst[i] = src[i]; \ +} +BUS_SPACE_COPY_N(1,u_int8_t) +BUS_SPACE_COPY_N(2,u_int16_t) +BUS_SPACE_COPY_N(4,u_int32_t) + +void +bus_space_set_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + u_int8_t val, bus_size_t c) +{ + u_int8_t *dst; + int i; + + dst = (u_int8_t *) (h+o); + + for (i = 0; i < c; i++) + dst[i] = val; +} + +void +bus_space_set_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + u_int16_t val, bus_size_t c) +{ + u_int16_t *dst; + int i; + + dst = (u_int16_t *) (h+o); + val = swap16(val); + + for (i = 0; i < c; i++) + dst[i] = val; +} +void +bus_space_set_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + u_int32_t val, bus_size_t c) +{ + u_int32_t *dst; + int i; + + dst = (u_int32_t *) (h+o); + val = swap32(val); + + for (i = 0; i < c; i++) + dst[i] = val; +} + +#define BUS_SPACE_READ_RAW_MULTI_N(BYTES,SHIFT,TYPE) \ +void \ +__C(bus_space_read_raw_multi_,BYTES)(bus_space_tag_t bst, \ + bus_space_handle_t h, bus_addr_t o, u_int8_t *dst, bus_size_t size) \ +{ \ + TYPE *src; \ + TYPE *rdst = (TYPE *)dst; \ + int i; \ + int count = size >> SHIFT; \ + \ + src = (TYPE *)(h+o); \ + for (i = 0; i < count; i++) { \ + rdst[i] = *src; \ + __asm__("eieio"); \ + } \ +} +BUS_SPACE_READ_RAW_MULTI_N(2,1,u_int16_t) +BUS_SPACE_READ_RAW_MULTI_N(4,2,u_int32_t) + +#define BUS_SPACE_WRITE_RAW_MULTI_N(BYTES,SHIFT,TYPE) \ +void \ +__C(bus_space_write_raw_multi_,BYTES)( bus_space_tag_t bst, \ + bus_space_handle_t h, bus_addr_t o, const u_int8_t *src, \ + bus_size_t size) \ +{ \ + int i; \ + TYPE *dst; \ + TYPE *rsrc = (TYPE *)src; \ + int count = size >> SHIFT; \ + \ + dst = (TYPE *)(h+o); \ + for (i = 0; i < count; i++) { \ + *dst = rsrc[i]; \ + __asm__("eieio"); \ + } \ +} + +BUS_SPACE_WRITE_RAW_MULTI_N(2,1,u_int16_t) +BUS_SPACE_WRITE_RAW_MULTI_N(4,2,u_int32_t) + +int +bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp) +{ + *nbshp = bsh + offset; + return (0); +} |