busiosubr.c revision 90850
1/* $FreeBSD: head/sys/pc98/pc98/busiosubr.c 90850 2002-02-18 13:44:46Z nyan $ */ 2/* $NecBSD: busiosubr.c,v 1.30.4.4 1999/08/28 02:25:35 honda Exp $ */ 3/* $NetBSD$ */ 4 5/* 6 * [NetBSD for NEC PC-98 series] 7 * Copyright (c) 1996, 1997, 1998 8 * NetBSD/pc98 porting staff. All rights reserved. 9 * 10 * [Ported for FreeBSD] 11 * Copyright (c) 2001 12 * TAKAHASHI Yoshihiro. All rights reserved. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. The name of the author may not be used to endorse or promote products 23 * derived from this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 27 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 28 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 34 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38/* 39 * Copyright (c) 1997, 1998 40 * Naofumi HONDA. All rights reserved. 41 */ 42 43#include <sys/param.h> 44#include <sys/systm.h> 45#include <sys/kernel.h> 46#include <sys/malloc.h> 47#include <machine/bus.h> 48 49static MALLOC_DEFINE(M_BUSSPACEHANDLE, "busspacehandle", "Bus space handle"); 50 51_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int8_t,1) 52_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int16_t,2) 53_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int32_t,4) 54_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_mem,u_int8_t,1) 55_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_mem,u_int16_t,2) 56_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_mem,u_int32_t,4) 57 58_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_io,u_int8_t,1) 59_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_io,u_int16_t,2) 60_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_io,u_int32_t,4) 61_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_mem,u_int8_t,1) 62_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_mem,u_int16_t,2) 63_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_mem,u_int32_t,4) 64 65struct bus_space_tag SBUS_io_space_tag = { 66 BUS_SPACE_IO, 67 68 /* direct bus access methods */ 69 { 70 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int8_t,1), 71 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int16_t,2), 72 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int32_t,4), 73 }, 74 75 /* relocate bus access methods */ 76 { 77 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int8_t,1), 78 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int16_t,2), 79 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int32_t,4), 80 } 81}; 82 83struct bus_space_tag SBUS_mem_space_tag = { 84 BUS_SPACE_MEM, 85 86 /* direct bus access methods */ 87 { 88 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int8_t,1), 89 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int16_t,2), 90 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int32_t,4), 91 }, 92 93 /* relocate bus access methods */ 94 { 95 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int8_t,1), 96 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int16_t,2), 97 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int32_t,4), 98 } 99}; 100 101 102#include "opt_mecia.h" 103#ifdef DEV_MECIA 104 105_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_DA_io,u_int16_t,2) 106_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_DA_io,u_int32_t,4) 107 108_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_RA_io,u_int16_t,2) 109_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_RA_io,u_int32_t,4) 110 111struct bus_space_tag NEPC_io_space_tag = { 112 BUS_SPACE_IO, 113 114 /* direct bus access methods */ 115 { 116 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int8_t,1), 117 _BUS_SPACE_CALL_FUNCS_TAB(NEPC_DA_io,u_int16_t,2), 118 _BUS_SPACE_CALL_FUNCS_TAB(NEPC_DA_io,u_int32_t,4), 119 }, 120 121 /* relocate bus access methods */ 122 { 123 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int8_t,1), 124 _BUS_SPACE_CALL_FUNCS_TAB(NEPC_RA_io,u_int16_t,2), 125 _BUS_SPACE_CALL_FUNCS_TAB(NEPC_RA_io,u_int32_t,4), 126 } 127}; 128 129struct bus_space_tag NEPC_mem_space_tag = { 130 BUS_SPACE_MEM, 131 132 /* direct bus access methods */ 133 { 134 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int8_t,1), 135 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int16_t,2), 136 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int32_t,4), 137 }, 138 139 /* relocate bus access methods */ 140 { 141 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int8_t,1), 142 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int16_t,2), 143 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int32_t,4), 144 } 145}; 146 147#endif /* DEV_MECIA */ 148 149/************************************************************************* 150 * map init 151 *************************************************************************/ 152static __inline void 153bus_space_iat_init(bus_space_handle_t bsh) 154{ 155 int i; 156 157 for (i = 0; i < bsh->bsh_maxiatsz; i++) 158 bsh->bsh_iat[i] = bsh->bsh_base + i; 159} 160 161/************************************************************************* 162 * handle allocation 163 *************************************************************************/ 164int 165i386_bus_space_handle_alloc(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, 166 bus_space_handle_t *bshp) 167{ 168 bus_space_handle_t bsh; 169 170 bsh = (bus_space_handle_t) malloc(sizeof (*bsh), M_BUSSPACEHANDLE, 171 M_NOWAIT | M_ZERO); 172 if (bsh == NULL) 173 return ENOMEM; 174 175 bsh->bsh_maxiatsz = BUS_SPACE_IAT_MAXSIZE; 176 bsh->bsh_iatsz = 0; 177 bsh->bsh_base = bpa; 178 bsh->bsh_sz = size; 179 bsh->bsh_res = NULL; 180 bsh->bsh_ressz = 0; 181 bus_space_iat_init(bsh); 182 183 bsh->bsh_bam = t->bs_da; /* default: direct access */ 184 185 *bshp = bsh; 186 return 0; 187} 188 189void 190i386_bus_space_handle_free(bus_space_tag_t t, bus_space_handle_t bsh, 191 size_t size) 192{ 193 194 free(bsh, M_BUSSPACEHANDLE); 195} 196 197/************************************************************************* 198 * map 199 *************************************************************************/ 200void 201i386_memio_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) 202{ 203 204 i386_bus_space_handle_free(t, bsh, bsh->bsh_sz); 205} 206 207void 208i386_memio_free(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) 209{ 210 211 /* i386_memio_unmap() does all that we need to do. */ 212 i386_memio_unmap(t, bsh, bsh->bsh_sz); 213} 214 215int 216i386_memio_subregion(bus_space_tag_t t, bus_space_handle_t pbsh, 217 bus_size_t offset, bus_size_t size, 218 bus_space_handle_t *tbshp) 219{ 220 int i, error = 0; 221 bus_space_handle_t bsh; 222 bus_addr_t pbase; 223 224 pbase = pbsh->bsh_base + offset; 225 switch (t->bs_tag) { 226 case BUS_SPACE_IO: 227 if (pbsh->bsh_iatsz > 0) { 228 if (offset >= pbsh->bsh_iatsz || 229 offset + size > pbsh->bsh_iatsz) 230 return EINVAL; 231 pbase = pbsh->bsh_base; 232 } 233 break; 234 235 case BUS_SPACE_MEM: 236 if (pbsh->bsh_iatsz > 0) 237 return EINVAL; 238 if (offset > pbsh->bsh_sz || offset + size > pbsh->bsh_sz) 239 return EINVAL; 240 break; 241 242 default: 243 panic("i386_memio_subregion: bad bus space tag"); 244 break; 245 } 246 247 error = i386_bus_space_handle_alloc(t, pbase, size, &bsh); 248 if (error != 0) 249 return error; 250 251 switch (t->bs_tag) { 252 case BUS_SPACE_IO: 253 if (pbsh->bsh_iatsz > 0) { 254 for (i = 0; i < size; i ++) 255 bsh->bsh_iat[i] = pbsh->bsh_iat[i + offset]; 256 bsh->bsh_iatsz = size; 257 } else if (pbsh->bsh_base > bsh->bsh_base || 258 pbsh->bsh_base + pbsh->bsh_sz < 259 bsh->bsh_base + bsh->bsh_sz) { 260 i386_bus_space_handle_free(t, bsh, size); 261 return EINVAL; 262 } 263 break; 264 265 case BUS_SPACE_MEM: 266 break; 267 } 268 269 if (pbsh->bsh_iatsz > 0) 270 bsh->bsh_bam = t->bs_ra; /* relocate access */ 271 *tbshp = bsh; 272 return error; 273} 274