184615Snyan/* $FreeBSD$ */ 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 = { 66214584Snyan BUS_SPACE_TAG_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 = { 84214584Snyan BUS_SPACE_TAG_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 = { 112214584Snyan BUS_SPACE_TAG_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 = { 130214584Snyan BUS_SPACE_TAG_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 224182836Snyani386_memio_map_load(bus_space_tag_t t, bus_space_handle_t bsh, 225182836Snyan bus_size_t size, bus_space_iat_t iat, u_int flags __unused) 226182836Snyan{ 227182836Snyan int i; 228182836Snyan 229182836Snyan if (size > bsh->bsh_maxiatsz) { 230182836Snyan printf("i386_memio_map_load: map size too large\n"); 231182836Snyan return EINVAL; 232182836Snyan } 233182836Snyan 234182836Snyan for (i = 0; i < bsh->bsh_maxiatsz; i++) { 235182836Snyan if (i < size) 236182836Snyan bsh->bsh_iat[i] = iat[i]; 237182836Snyan else 238182836Snyan bsh->bsh_iat[i] = 0; 239182836Snyan bsh->bsh_iat[i] += bsh->bsh_base; 240182836Snyan } 241182836Snyan 242182836Snyan bsh->bsh_iatsz = size; 243182836Snyan bsh->bsh_bam = t->bs_ra; /* relocate access */ 244182836Snyan 245182836Snyan return 0; 246182836Snyan} 247182836Snyan 248182836Snyanint 24990762Snyani386_memio_subregion(bus_space_tag_t t, bus_space_handle_t pbsh, 25090762Snyan bus_size_t offset, bus_size_t size, 25190762Snyan bus_space_handle_t *tbshp) 25290762Snyan{ 25390762Snyan int i, error = 0; 25490762Snyan bus_space_handle_t bsh; 25590762Snyan bus_addr_t pbase; 25690762Snyan 25790762Snyan pbase = pbsh->bsh_base + offset; 25890762Snyan switch (t->bs_tag) { 259214584Snyan case BUS_SPACE_TAG_IO: 26090762Snyan if (pbsh->bsh_iatsz > 0) { 26190762Snyan if (offset >= pbsh->bsh_iatsz || 26290762Snyan offset + size > pbsh->bsh_iatsz) 26390762Snyan return EINVAL; 26490762Snyan pbase = pbsh->bsh_base; 26590762Snyan } 26690762Snyan break; 26790762Snyan 268214584Snyan case BUS_SPACE_TAG_MEM: 26990762Snyan if (pbsh->bsh_iatsz > 0) 27090762Snyan return EINVAL; 27190762Snyan if (offset > pbsh->bsh_sz || offset + size > pbsh->bsh_sz) 27290762Snyan return EINVAL; 27390762Snyan break; 27490762Snyan 27590762Snyan default: 27690762Snyan panic("i386_memio_subregion: bad bus space tag"); 27790762Snyan break; 27890762Snyan } 27990762Snyan 28090762Snyan error = i386_bus_space_handle_alloc(t, pbase, size, &bsh); 28190762Snyan if (error != 0) 28290762Snyan return error; 28390762Snyan 28490762Snyan switch (t->bs_tag) { 285214584Snyan case BUS_SPACE_TAG_IO: 28690762Snyan if (pbsh->bsh_iatsz > 0) { 28790762Snyan for (i = 0; i < size; i ++) 28890762Snyan bsh->bsh_iat[i] = pbsh->bsh_iat[i + offset]; 28990762Snyan bsh->bsh_iatsz = size; 29090762Snyan } else if (pbsh->bsh_base > bsh->bsh_base || 29190762Snyan pbsh->bsh_base + pbsh->bsh_sz < 29290762Snyan bsh->bsh_base + bsh->bsh_sz) { 29390762Snyan i386_bus_space_handle_free(t, bsh, size); 29490762Snyan return EINVAL; 29590762Snyan } 29690762Snyan break; 29790762Snyan 298214584Snyan case BUS_SPACE_TAG_MEM: 29990762Snyan break; 30090762Snyan } 30190762Snyan 30290762Snyan if (pbsh->bsh_iatsz > 0) 30390762Snyan bsh->bsh_bam = t->bs_ra; /* relocate access */ 30490762Snyan *tbshp = bsh; 30590762Snyan return error; 30690762Snyan} 307180303Snyan 308180303Snyanint 309180303Snyani386_memio_compare(bus_space_tag_t t1, bus_space_handle_t bsh1, 310180303Snyan bus_space_tag_t t2, bus_space_handle_t bsh2) 311180303Snyan{ 312180303Snyan int i; 313180303Snyan 314180303Snyan if (t1->bs_tag != t2->bs_tag) 315180303Snyan return (1); 316180303Snyan if (bsh1->bsh_base != bsh2->bsh_base) 317180303Snyan return (1); 318180303Snyan if (bsh1->bsh_sz != bsh2->bsh_sz) 319180303Snyan return (1); 320180303Snyan if (bsh1->bsh_bam.bs_read_1 != bsh2->bsh_bam.bs_read_1) /* XXX */ 321180303Snyan return (1); 322180303Snyan 323180303Snyan if (bsh1->bsh_iatsz != bsh2->bsh_iatsz) 324180303Snyan return (1); 325180303Snyan for (i = 0; i < bsh1->bsh_iatsz; i++) { 326180303Snyan if (bsh1->bsh_iat[i] != bsh2->bsh_iat[i]) 327180303Snyan return (1); 328180303Snyan } 329180303Snyan 330180303Snyan return (0); 331180303Snyan} 332