busiosubr.c revision 214584
11558Srgrimes/* $FreeBSD: head/sys/pc98/pc98/busiosubr.c 214584 2010-10-31 03:03:20Z nyan $ */ 21558Srgrimes/* $NecBSD: busiosubr.c,v 1.30.4.4 1999/08/28 02:25:35 honda Exp $ */ 31558Srgrimes/* $NetBSD$ */ 41558Srgrimes 51558Srgrimes/*- 61558Srgrimes * [NetBSD for NEC PC-98 series] 71558Srgrimes * 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_TAG_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_TAG_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_TAG_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_TAG_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 *************************************************************************/ 200int 201i386_memio_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, int flags, 202 bus_space_handle_t *bshp) 203{ 204 205 return i386_bus_space_handle_alloc(t, bpa, size, bshp); 206} 207 208void 209i386_memio_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) 210{ 211 212 i386_bus_space_handle_free(t, bsh, bsh->bsh_sz); 213} 214 215void 216i386_memio_free(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) 217{ 218 219 /* i386_memio_unmap() does all that we need to do. */ 220 i386_memio_unmap(t, bsh, bsh->bsh_sz); 221} 222 223int 224i386_memio_map_load(bus_space_tag_t t, bus_space_handle_t bsh, 225 bus_size_t size, bus_space_iat_t iat, u_int flags __unused) 226{ 227 int i; 228 229 if (size > bsh->bsh_maxiatsz) { 230 printf("i386_memio_map_load: map size too large\n"); 231 return EINVAL; 232 } 233 234 for (i = 0; i < bsh->bsh_maxiatsz; i++) { 235 if (i < size) 236 bsh->bsh_iat[i] = iat[i]; 237 else 238 bsh->bsh_iat[i] = 0; 239 bsh->bsh_iat[i] += bsh->bsh_base; 240 } 241 242 bsh->bsh_iatsz = size; 243 bsh->bsh_bam = t->bs_ra; /* relocate access */ 244 245 return 0; 246} 247 248int 249i386_memio_subregion(bus_space_tag_t t, bus_space_handle_t pbsh, 250 bus_size_t offset, bus_size_t size, 251 bus_space_handle_t *tbshp) 252{ 253 int i, error = 0; 254 bus_space_handle_t bsh; 255 bus_addr_t pbase; 256 257 pbase = pbsh->bsh_base + offset; 258 switch (t->bs_tag) { 259 case BUS_SPACE_TAG_IO: 260 if (pbsh->bsh_iatsz > 0) { 261 if (offset >= pbsh->bsh_iatsz || 262 offset + size > pbsh->bsh_iatsz) 263 return EINVAL; 264 pbase = pbsh->bsh_base; 265 } 266 break; 267 268 case BUS_SPACE_TAG_MEM: 269 if (pbsh->bsh_iatsz > 0) 270 return EINVAL; 271 if (offset > pbsh->bsh_sz || offset + size > pbsh->bsh_sz) 272 return EINVAL; 273 break; 274 275 default: 276 panic("i386_memio_subregion: bad bus space tag"); 277 break; 278 } 279 280 error = i386_bus_space_handle_alloc(t, pbase, size, &bsh); 281 if (error != 0) 282 return error; 283 284 switch (t->bs_tag) { 285 case BUS_SPACE_TAG_IO: 286 if (pbsh->bsh_iatsz > 0) { 287 for (i = 0; i < size; i ++) 288 bsh->bsh_iat[i] = pbsh->bsh_iat[i + offset]; 289 bsh->bsh_iatsz = size; 290 } else if (pbsh->bsh_base > bsh->bsh_base || 291 pbsh->bsh_base + pbsh->bsh_sz < 292 bsh->bsh_base + bsh->bsh_sz) { 293 i386_bus_space_handle_free(t, bsh, size); 294 return EINVAL; 295 } 296 break; 297 298 case BUS_SPACE_TAG_MEM: 299 break; 300 } 301 302 if (pbsh->bsh_iatsz > 0) 303 bsh->bsh_bam = t->bs_ra; /* relocate access */ 304 *tbshp = bsh; 305 return error; 306} 307 308int 309i386_memio_compare(bus_space_tag_t t1, bus_space_handle_t bsh1, 310 bus_space_tag_t t2, bus_space_handle_t bsh2) 311{ 312 int i; 313 314 if (t1->bs_tag != t2->bs_tag) 315 return (1); 316 if (bsh1->bsh_base != bsh2->bsh_base) 317 return (1); 318 if (bsh1->bsh_sz != bsh2->bsh_sz) 319 return (1); 320 if (bsh1->bsh_bam.bs_read_1 != bsh2->bsh_bam.bs_read_1) /* XXX */ 321 return (1); 322 323 if (bsh1->bsh_iatsz != bsh2->bsh_iatsz) 324 return (1); 325 for (i = 0; i < bsh1->bsh_iatsz; i++) { 326 if (bsh1->bsh_iat[i] != bsh2->bsh_iat[i]) 327 return (1); 328 } 329 330 return (0); 331} 332