busiosubr.c revision 139825
184615Snyan/* $FreeBSD: head/sys/pc98/pc98/busiosubr.c 139825 2005-01-07 02:29:27Z imp $ */ 284615Snyan/* $NecBSD: busiosubr.c,v 1.30.4.4 1999/08/28 02:25:35 honda Exp $ */ 384615Snyan/* $NetBSD$ */ 484615Snyan 5139825Simp/*- 684615Snyan * [NetBSD for NEC PC-98 series] 784615Snyan * Copyright (c) 1996, 1997, 1998 884615Snyan * NetBSD/pc98 porting staff. All rights reserved. 984615Snyan * 1084615Snyan * [Ported for FreeBSD] 1184615Snyan * Copyright (c) 2001 1284615Snyan * TAKAHASHI Yoshihiro. All rights reserved. 1384615Snyan * 1484615Snyan * Redistribution and use in source and binary forms, with or without 1584615Snyan * modification, are permitted provided that the following conditions 1684615Snyan * are met: 1784615Snyan * 1. Redistributions of source code must retain the above copyright 1884615Snyan * notice, this list of conditions and the following disclaimer. 1984615Snyan * 2. Redistributions in binary form must reproduce the above copyright 2084615Snyan * notice, this list of conditions and the following disclaimer in the 2184615Snyan * documentation and/or other materials provided with the distribution. 2284615Snyan * 3. The name of the author may not be used to endorse or promote products 2384615Snyan * derived from this software without specific prior written permission. 2484615Snyan * 2584615Snyan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2684615Snyan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 2784615Snyan * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2884615Snyan * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 2984615Snyan * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 3084615Snyan * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 3184615Snyan * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3284615Snyan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3384615Snyan * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 3484615Snyan * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3584615Snyan * POSSIBILITY OF SUCH DAMAGE. 3684615Snyan */ 3784615Snyan 3884615Snyan/* 3984615Snyan * Copyright (c) 1997, 1998 4084615Snyan * Naofumi HONDA. All rights reserved. 4184615Snyan */ 4284615Snyan 4384615Snyan#include <sys/param.h> 4484615Snyan#include <sys/systm.h> 4584615Snyan#include <sys/kernel.h> 4690762Snyan#include <sys/malloc.h> 4784615Snyan#include <machine/bus.h> 4884615Snyan 4990762Snyanstatic MALLOC_DEFINE(M_BUSSPACEHANDLE, "busspacehandle", "Bus space handle"); 5090762Snyan 5184615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int8_t,1) 5284615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int16_t,2) 5384615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int32_t,4) 5484615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_mem,u_int8_t,1) 5584615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_mem,u_int16_t,2) 5684615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_mem,u_int32_t,4) 5784615Snyan 5884615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_io,u_int8_t,1) 5984615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_io,u_int16_t,2) 6084615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_io,u_int32_t,4) 6184615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_mem,u_int8_t,1) 6284615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_mem,u_int16_t,2) 6384615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_mem,u_int32_t,4) 6484615Snyan 6584615Snyanstruct bus_space_tag SBUS_io_space_tag = { 6684615Snyan BUS_SPACE_IO, 6784615Snyan 6884615Snyan /* direct bus access methods */ 6984615Snyan { 7084615Snyan _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int8_t,1), 7184615Snyan _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int16_t,2), 7284615Snyan _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int32_t,4), 7384615Snyan }, 7484615Snyan 7584615Snyan /* relocate bus access methods */ 7684615Snyan { 7784615Snyan _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int8_t,1), 7884615Snyan _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int16_t,2), 7984615Snyan _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int32_t,4), 8084615Snyan } 8184615Snyan}; 8284615Snyan 8384615Snyanstruct bus_space_tag SBUS_mem_space_tag = { 8484615Snyan BUS_SPACE_MEM, 8584615Snyan 8684615Snyan /* direct bus access methods */ 8784615Snyan { 8884615Snyan _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int8_t,1), 8984615Snyan _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int16_t,2), 9084615Snyan _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int32_t,4), 9184615Snyan }, 9284615Snyan 9384615Snyan /* relocate bus access methods */ 9484615Snyan { 9584615Snyan _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int8_t,1), 9684615Snyan _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int16_t,2), 9784615Snyan _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int32_t,4), 9884615Snyan } 9984615Snyan}; 10084615Snyan 10184615Snyan 10284615Snyan#include "opt_mecia.h" 10384615Snyan#ifdef DEV_MECIA 10484615Snyan 10584615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_DA_io,u_int16_t,2) 10684615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_DA_io,u_int32_t,4) 10784615Snyan 10884615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_RA_io,u_int16_t,2) 10984615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_RA_io,u_int32_t,4) 11084615Snyan 11184615Snyanstruct bus_space_tag NEPC_io_space_tag = { 11284615Snyan BUS_SPACE_IO, 11384615Snyan 11484615Snyan /* direct bus access methods */ 11584615Snyan { 11684615Snyan _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int8_t,1), 11784615Snyan _BUS_SPACE_CALL_FUNCS_TAB(NEPC_DA_io,u_int16_t,2), 11884615Snyan _BUS_SPACE_CALL_FUNCS_TAB(NEPC_DA_io,u_int32_t,4), 11984615Snyan }, 12084615Snyan 12184615Snyan /* relocate bus access methods */ 12284615Snyan { 12384615Snyan _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int8_t,1), 12484615Snyan _BUS_SPACE_CALL_FUNCS_TAB(NEPC_RA_io,u_int16_t,2), 12584615Snyan _BUS_SPACE_CALL_FUNCS_TAB(NEPC_RA_io,u_int32_t,4), 12684615Snyan } 12784615Snyan}; 12884615Snyan 12984615Snyanstruct bus_space_tag NEPC_mem_space_tag = { 13084615Snyan BUS_SPACE_MEM, 13184615Snyan 13284615Snyan /* direct bus access methods */ 13384615Snyan { 13484615Snyan _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int8_t,1), 13584615Snyan _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int16_t,2), 13684615Snyan _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int32_t,4), 13784615Snyan }, 13884615Snyan 13984615Snyan /* relocate bus access methods */ 14084615Snyan { 14184615Snyan _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int8_t,1), 14284615Snyan _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int16_t,2), 14384615Snyan _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int32_t,4), 14484615Snyan } 14584615Snyan}; 14684615Snyan 14784615Snyan#endif /* DEV_MECIA */ 14890762Snyan 14990762Snyan/************************************************************************* 15090762Snyan * map init 15190762Snyan *************************************************************************/ 15290762Snyanstatic __inline void 15390762Snyanbus_space_iat_init(bus_space_handle_t bsh) 15490762Snyan{ 15590762Snyan int i; 15690762Snyan 15790762Snyan for (i = 0; i < bsh->bsh_maxiatsz; i++) 15890762Snyan bsh->bsh_iat[i] = bsh->bsh_base + i; 15990762Snyan} 16090762Snyan 16190762Snyan/************************************************************************* 16290762Snyan * handle allocation 16390762Snyan *************************************************************************/ 16490762Snyanint 16590762Snyani386_bus_space_handle_alloc(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, 16690762Snyan bus_space_handle_t *bshp) 16790762Snyan{ 16890762Snyan bus_space_handle_t bsh; 16990762Snyan 17090762Snyan bsh = (bus_space_handle_t) malloc(sizeof (*bsh), M_BUSSPACEHANDLE, 17190762Snyan M_NOWAIT | M_ZERO); 17290762Snyan if (bsh == NULL) 17390762Snyan return ENOMEM; 17490762Snyan 17590762Snyan bsh->bsh_maxiatsz = BUS_SPACE_IAT_MAXSIZE; 17690762Snyan bsh->bsh_iatsz = 0; 17790762Snyan bsh->bsh_base = bpa; 17890762Snyan bsh->bsh_sz = size; 17990762Snyan bsh->bsh_res = NULL; 18090762Snyan bsh->bsh_ressz = 0; 18190762Snyan bus_space_iat_init(bsh); 18290762Snyan 18390762Snyan bsh->bsh_bam = t->bs_da; /* default: direct access */ 18490762Snyan 18590762Snyan *bshp = bsh; 18690762Snyan return 0; 18790762Snyan} 18890762Snyan 18990762Snyanvoid 19090762Snyani386_bus_space_handle_free(bus_space_tag_t t, bus_space_handle_t bsh, 19190762Snyan size_t size) 19290762Snyan{ 19390762Snyan 19490762Snyan free(bsh, M_BUSSPACEHANDLE); 19590762Snyan} 19690762Snyan 19790762Snyan/************************************************************************* 19890762Snyan * map 19990762Snyan *************************************************************************/ 200120375Snyanint 201120375Snyani386_memio_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, int flags, 202120375Snyan bus_space_handle_t *bshp) 203120375Snyan{ 204120375Snyan 205120375Snyan return i386_bus_space_handle_alloc(t, bpa, size, bshp); 206120375Snyan} 207120375Snyan 20890850Snyanvoid 20990850Snyani386_memio_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) 21090850Snyan{ 21190850Snyan 21290850Snyan i386_bus_space_handle_free(t, bsh, bsh->bsh_sz); 21390850Snyan} 21490850Snyan 21590850Snyanvoid 21690850Snyani386_memio_free(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) 21790850Snyan{ 21890850Snyan 21990850Snyan /* i386_memio_unmap() does all that we need to do. */ 22090850Snyan i386_memio_unmap(t, bsh, bsh->bsh_sz); 22190850Snyan} 22290850Snyan 22390762Snyanint 22490762Snyani386_memio_subregion(bus_space_tag_t t, bus_space_handle_t pbsh, 22590762Snyan bus_size_t offset, bus_size_t size, 22690762Snyan bus_space_handle_t *tbshp) 22790762Snyan{ 22890762Snyan int i, error = 0; 22990762Snyan bus_space_handle_t bsh; 23090762Snyan bus_addr_t pbase; 23190762Snyan 23290762Snyan pbase = pbsh->bsh_base + offset; 23390762Snyan switch (t->bs_tag) { 23490762Snyan case BUS_SPACE_IO: 23590762Snyan if (pbsh->bsh_iatsz > 0) { 23690762Snyan if (offset >= pbsh->bsh_iatsz || 23790762Snyan offset + size > pbsh->bsh_iatsz) 23890762Snyan return EINVAL; 23990762Snyan pbase = pbsh->bsh_base; 24090762Snyan } 24190762Snyan break; 24290762Snyan 24390762Snyan case BUS_SPACE_MEM: 24490762Snyan if (pbsh->bsh_iatsz > 0) 24590762Snyan return EINVAL; 24690762Snyan if (offset > pbsh->bsh_sz || offset + size > pbsh->bsh_sz) 24790762Snyan return EINVAL; 24890762Snyan break; 24990762Snyan 25090762Snyan default: 25190762Snyan panic("i386_memio_subregion: bad bus space tag"); 25290762Snyan break; 25390762Snyan } 25490762Snyan 25590762Snyan error = i386_bus_space_handle_alloc(t, pbase, size, &bsh); 25690762Snyan if (error != 0) 25790762Snyan return error; 25890762Snyan 25990762Snyan switch (t->bs_tag) { 26090762Snyan case BUS_SPACE_IO: 26190762Snyan if (pbsh->bsh_iatsz > 0) { 26290762Snyan for (i = 0; i < size; i ++) 26390762Snyan bsh->bsh_iat[i] = pbsh->bsh_iat[i + offset]; 26490762Snyan bsh->bsh_iatsz = size; 26590762Snyan } else if (pbsh->bsh_base > bsh->bsh_base || 26690762Snyan pbsh->bsh_base + pbsh->bsh_sz < 26790762Snyan bsh->bsh_base + bsh->bsh_sz) { 26890762Snyan i386_bus_space_handle_free(t, bsh, size); 26990762Snyan return EINVAL; 27090762Snyan } 27190762Snyan break; 27290762Snyan 27390762Snyan case BUS_SPACE_MEM: 27490762Snyan break; 27590762Snyan } 27690762Snyan 27790762Snyan if (pbsh->bsh_iatsz > 0) 27890762Snyan bsh->bsh_bam = t->bs_ra; /* relocate access */ 27990762Snyan *tbshp = bsh; 28090762Snyan return error; 28190762Snyan} 282