1 /* $NetBSD: bus_space.c,v 1.24 2011/01/18 01:02:55 matt Exp $ */ 2 3 /*- 4 * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: bus_space.c,v 1.24 2011/01/18 01:02:55 matt Exp $"); 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/kernel.h> 39 #include <sys/device.h> 40 #include <sys/endian.h> 41 #include <sys/extent.h> 42 #include <sys/malloc.h> 43 44 #include <uvm/uvm.h> 45 46 #define _POWERPC_BUS_SPACE_PRIVATE 47 #include <machine/bus.h> 48 49 #if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE) 50 #include <powerpc/spr.h> 51 #include <powerpc/oea/bat.h> 52 #include <powerpc/oea/cpufeat.h> 53 #include <powerpc/oea/pte.h> 54 #include <powerpc/oea/spr.h> 55 #include <powerpc/oea/sr_601.h> 56 57 extern unsigned long oeacpufeat; 58 #endif 59 60 /* read_N */ 61 u_int8_t bsr1(bus_space_tag_t, bus_space_handle_t, bus_size_t); 62 u_int16_t bsr2(bus_space_tag_t, bus_space_handle_t, bus_size_t); 63 u_int32_t bsr4(bus_space_tag_t, bus_space_handle_t, bus_size_t); 64 u_int64_t bsr8(bus_space_tag_t, bus_space_handle_t, bus_size_t); 65 66 /* write_N */ 67 void bsw1(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int8_t); 68 void bsw2(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int16_t); 69 void bsw4(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t); 70 void bsw8(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int64_t); 71 72 static const struct powerpc_bus_space_scalar scalar_ops = { 73 bsr1, bsr2, bsr4, bsr8, 74 bsw1, bsw2, bsw4, bsw8 75 }; 76 77 /* read_N byte reverse */ 78 u_int16_t bsr2rb(bus_space_tag_t, bus_space_handle_t, bus_size_t); 79 u_int32_t bsr4rb(bus_space_tag_t, bus_space_handle_t, bus_size_t); 80 u_int64_t bsr8rb(bus_space_tag_t, bus_space_handle_t, bus_size_t); 81 82 /* write_N byte reverse */ 83 void bsw2rb(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int16_t); 84 void bsw4rb(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t); 85 void bsw8rb(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int64_t); 86 87 static const struct powerpc_bus_space_scalar scalar_rb_ops = { 88 bsr1, bsr2rb, bsr4rb, bsr8rb, 89 bsw1, bsw2rb, bsw4rb, bsw8rb 90 }; 91 92 /* read_multi_N */ 93 void bsrm1(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int8_t *, 94 size_t); 95 void bsrm2(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int16_t *, 96 size_t); 97 void bsrm4(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t *, 98 size_t); 99 void bsrm8(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int64_t *, 100 size_t); 101 102 /* write_multi_N */ 103 void bswm1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 104 const u_int8_t *, size_t); 105 void bswm2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 106 const u_int16_t *, size_t); 107 void bswm4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 108 const u_int32_t *, size_t); 109 void bswm8(bus_space_tag_t, bus_space_handle_t, bus_size_t, 110 const u_int64_t *, size_t); 111 112 static const struct powerpc_bus_space_group multi_ops = { 113 bsrm1, bsrm2, bsrm4, bsrm8, 114 bswm1, bswm2, bswm4, bswm8 115 }; 116 117 /* read_multi_N byte reversed */ 118 void bsrm2rb(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int16_t *, 119 size_t); 120 void bsrm4rb(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t *, 121 size_t); 122 void bsrm8rb(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int64_t *, 123 size_t); 124 125 /* write_multi_N byte reversed */ 126 void bswm2rb(bus_space_tag_t, bus_space_handle_t, bus_size_t, 127 const u_int16_t *, size_t); 128 void bswm4rb(bus_space_tag_t, bus_space_handle_t, bus_size_t, 129 const u_int32_t *, size_t); 130 void bswm8rb(bus_space_tag_t, bus_space_handle_t, bus_size_t, 131 const u_int64_t *, size_t); 132 133 static const struct powerpc_bus_space_group multi_rb_ops = { 134 bsrm1, bsrm2rb, bsrm4rb, bsrm8rb, 135 bswm1, bswm2rb, bswm4rb, bswm8rb 136 }; 137 138 /* read_region_N */ 139 void bsrr1(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int8_t *, 140 size_t); 141 void bsrr2(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int16_t *, 142 size_t); 143 void bsrr4(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t *, 144 size_t); 145 void bsrr8(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int64_t *, 146 size_t); 147 148 /* write_region_N */ 149 void bswr1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 150 const u_int8_t *, size_t); 151 void bswr2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 152 const u_int16_t *, size_t); 153 void bswr4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 154 const u_int32_t *, size_t); 155 void bswr8(bus_space_tag_t, bus_space_handle_t, bus_size_t, 156 const u_int64_t *, size_t); 157 158 static const struct powerpc_bus_space_group region_ops = { 159 bsrr1, bsrr2, bsrr4, bsrr8, 160 bswr1, bswr2, bswr4, bswr8 161 }; 162 163 void bsrr2rb(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int16_t *, 164 size_t); 165 void bsrr4rb(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t *, 166 size_t); 167 void bsrr8rb(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int64_t *, 168 size_t); 169 170 void bswr2rb(bus_space_tag_t, bus_space_handle_t, bus_size_t, 171 const u_int16_t *, size_t); 172 void bswr4rb(bus_space_tag_t, bus_space_handle_t, bus_size_t, 173 const u_int32_t *, size_t); 174 void bswr8rb(bus_space_tag_t, bus_space_handle_t, bus_size_t, 175 const u_int64_t *, size_t); 176 177 static const struct powerpc_bus_space_group region_rb_ops = { 178 bsrr1, bsrr2rb, bsrr4rb, bsrr8rb, 179 bswr1, bswr2rb, bswr4rb, bswr8rb 180 }; 181 182 /* set_region_n */ 183 void bssr1(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int8_t, 184 size_t); 185 void bssr2(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int16_t, 186 size_t); 187 void bssr4(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t, 188 size_t); 189 void bssr8(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int64_t, 190 size_t); 191 192 static const struct powerpc_bus_space_set set_ops = { 193 bssr1, bssr2, bssr4, bssr8, 194 }; 195 196 void bssr2rb(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int16_t, 197 size_t); 198 void bssr4rb(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t, 199 size_t); 200 void bssr8rb(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int64_t, 201 size_t); 202 203 static const struct powerpc_bus_space_set set_rb_ops = { 204 bssr1, bssr2rb, bssr4rb, bssr8rb, 205 }; 206 207 /* copy_region_N */ 208 void bscr1(bus_space_tag_t, bus_space_handle_t, 209 bus_size_t, bus_space_handle_t, bus_size_t, size_t); 210 void bscr2(bus_space_tag_t, bus_space_handle_t, 211 bus_size_t, bus_space_handle_t, bus_size_t, size_t); 212 void bscr4(bus_space_tag_t, bus_space_handle_t, 213 bus_size_t, bus_space_handle_t, bus_size_t, size_t); 214 void bscr8(bus_space_tag_t, bus_space_handle_t, 215 bus_size_t, bus_space_handle_t, bus_size_t, size_t); 216 217 static const struct powerpc_bus_space_copy copy_ops = { 218 bscr1, bscr2, bscr4, bscr8 219 }; 220 221 /* 222 * Strided versions 223 */ 224 /* read_N */ 225 u_int8_t bsr1_s(bus_space_tag_t, bus_space_handle_t, bus_size_t); 226 u_int16_t bsr2_s(bus_space_tag_t, bus_space_handle_t, bus_size_t); 227 u_int32_t bsr4_s(bus_space_tag_t, bus_space_handle_t, bus_size_t); 228 u_int64_t bsr8_s(bus_space_tag_t, bus_space_handle_t, bus_size_t); 229 230 /* write_N */ 231 void bsw1_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int8_t); 232 void bsw2_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int16_t); 233 void bsw4_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t); 234 void bsw8_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int64_t); 235 236 static const struct powerpc_bus_space_scalar scalar_strided_ops = { 237 bsr1_s, bsr2_s, bsr4_s, bsr8_s, 238 bsw1_s, bsw2_s, bsw4_s, bsw8_s 239 }; 240 241 /* read_N */ 242 u_int16_t bsr2rb_s(bus_space_tag_t, bus_space_handle_t, bus_size_t); 243 u_int32_t bsr4rb_s(bus_space_tag_t, bus_space_handle_t, bus_size_t); 244 u_int64_t bsr8rb_s(bus_space_tag_t, bus_space_handle_t, bus_size_t); 245 246 /* write_N */ 247 void bsw2rb_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int16_t); 248 void bsw4rb_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t); 249 void bsw8rb_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int64_t); 250 251 static const struct powerpc_bus_space_scalar scalar_rb_strided_ops = { 252 bsr1_s, bsr2rb_s, bsr4rb_s, bsr8rb_s, 253 bsw1_s, bsw2rb_s, bsw4rb_s, bsw8rb_s 254 }; 255 256 /* read_multi_N */ 257 void bsrm1_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int8_t *, 258 size_t); 259 void bsrm2_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int16_t *, 260 size_t); 261 void bsrm4_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t *, 262 size_t); 263 void bsrm8_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int64_t *, 264 size_t); 265 266 /* write_multi_N */ 267 void bswm1_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, 268 const u_int8_t *, size_t); 269 void bswm2_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, 270 const u_int16_t *, size_t); 271 void bswm4_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, 272 const u_int32_t *, size_t); 273 void bswm8_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, 274 const u_int64_t *, size_t); 275 276 static const struct powerpc_bus_space_group multi_strided_ops = { 277 bsrm1_s, bsrm2_s, bsrm4_s, bsrm8_s, 278 bswm1_s, bswm2_s, bswm4_s, bswm8_s 279 }; 280 281 /* read_multi_N */ 282 void bsrm2rb_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int16_t *, 283 size_t); 284 void bsrm4rb_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t *, 285 size_t); 286 void bsrm8rb_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int64_t *, 287 size_t); 288 289 /* write_multi_N */ 290 void bswm2rb_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, 291 const u_int16_t *, size_t); 292 void bswm4rb_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, 293 const u_int32_t *, size_t); 294 void bswm8rb_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, 295 const u_int64_t *, size_t); 296 297 static const struct powerpc_bus_space_group multi_rb_strided_ops = { 298 bsrm1_s, bsrm2rb_s, bsrm4rb_s, bsrm8rb_s, 299 bswm1_s, bswm2rb_s, bswm4rb_s, bswm8rb_s 300 }; 301 302 /* read_region_N */ 303 void bsrr1_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int8_t *, 304 size_t); 305 void bsrr2_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int16_t *, 306 size_t); 307 void bsrr4_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t *, 308 size_t); 309 void bsrr8_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int64_t *, 310 size_t); 311 312 /* write_region_N */ 313 void bswr1_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, 314 const u_int8_t *, size_t); 315 void bswr2_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, 316 const u_int16_t *, size_t); 317 void bswr4_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, 318 const u_int32_t *, size_t); 319 void bswr8_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, 320 const u_int64_t *, size_t); 321 322 static const struct powerpc_bus_space_group region_strided_ops = { 323 bsrr1_s, bsrr2_s, bsrr4_s, bsrr8_s, 324 bswr1_s, bswr2_s, bswr4_s, bswr8_s 325 }; 326 327 /* read_region_N */ 328 void bsrr2rb_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int16_t *, 329 size_t); 330 void bsrr4rb_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t *, 331 size_t); 332 void bsrr8rb_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int64_t *, 333 size_t); 334 335 /* write_region_N */ 336 void bswr2rb_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, 337 const u_int16_t *, size_t); 338 void bswr4rb_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, 339 const u_int32_t *, size_t); 340 void bswr8rb_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, 341 const u_int64_t *, size_t); 342 343 static const struct powerpc_bus_space_group region_rb_strided_ops = { 344 bsrr1_s, bsrr2rb_s, bsrr4rb_s, bsrr8rb_s, 345 bswr1_s, bswr2rb_s, bswr4rb_s, bswr8rb_s 346 }; 347 348 /* set_region_N */ 349 void bssr1_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int8_t, 350 size_t); 351 void bssr2_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int16_t, 352 size_t); 353 void bssr4_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t, 354 size_t); 355 void bssr8_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int64_t, 356 size_t); 357 358 static const struct powerpc_bus_space_set set_strided_ops = { 359 bssr1_s, bssr2_s, bssr4_s, bssr8_s, 360 }; 361 362 /* set_region_N */ 363 void bssr2rb_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int16_t, 364 size_t); 365 void bssr4rb_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t, 366 size_t); 367 void bssr8rb_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int64_t, 368 size_t); 369 370 static const struct powerpc_bus_space_set set_rb_strided_ops = { 371 bssr1_s, bssr2rb_s, bssr4rb_s, bssr8rb_s, 372 }; 373 374 /* copy_region_N */ 375 void bscr1_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, 376 bus_space_handle_t, bus_size_t, size_t); 377 void bscr2_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, 378 bus_space_handle_t, bus_size_t, size_t); 379 void bscr4_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, 380 bus_space_handle_t, bus_size_t, size_t); 381 void bscr8_s(bus_space_tag_t, bus_space_handle_t, bus_size_t, 382 bus_space_handle_t, bus_size_t, size_t); 383 384 static const struct powerpc_bus_space_copy copy_strided_ops = { 385 bscr1_s, bscr2_s, bscr4_s, bscr8_s 386 }; 387 388 static paddr_t memio_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int); 389 static int memio_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, 390 bus_space_handle_t *); 391 static int memio_subregion(bus_space_tag_t, bus_space_handle_t, bus_size_t, 392 bus_size_t, bus_space_handle_t *); 393 static void memio_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t); 394 static int memio_alloc(bus_space_tag_t, bus_addr_t, bus_addr_t, bus_size_t, 395 bus_size_t, bus_size_t, int, bus_addr_t *, bus_space_handle_t *); 396 static void memio_free(bus_space_tag_t, bus_space_handle_t, bus_size_t); 397 398 static int extent_flags; 399 400 int 401 bus_space_init(struct powerpc_bus_space *t, const char *extent_name, 402 void *storage, size_t storage_size) 403 { 404 if (t->pbs_extent == NULL && extent_name != NULL) { 405 t->pbs_extent = extent_create(extent_name, t->pbs_base, 406 t->pbs_limit-1, M_DEVBUF, storage, storage_size, 407 EX_NOCOALESCE|EX_NOWAIT); 408 if (t->pbs_extent == NULL) 409 return ENOMEM; 410 } 411 412 t->pbs_mmap = memio_mmap; 413 t->pbs_map = memio_map; 414 t->pbs_subregion = memio_subregion; 415 t->pbs_unmap = memio_unmap; 416 t->pbs_alloc = memio_alloc; 417 t->pbs_free = memio_free; 418 419 if (t->pbs_flags & _BUS_SPACE_STRIDE_MASK) { 420 t->pbs_scalar_stream = scalar_strided_ops; 421 t->pbs_multi_stream = &multi_strided_ops; 422 t->pbs_region_stream = ®ion_strided_ops; 423 t->pbs_set_stream = &set_strided_ops; 424 t->pbs_copy = ©_strided_ops; 425 } else { 426 t->pbs_scalar_stream = scalar_ops; 427 t->pbs_multi_stream = &multi_ops; 428 t->pbs_region_stream = ®ion_ops; 429 t->pbs_set_stream = &set_ops; 430 t->pbs_copy = ©_ops; 431 } 432 433 #if BYTE_ORDER == BIG_ENDIAN 434 if (t->pbs_flags & _BUS_SPACE_BIG_ENDIAN) { 435 if (t->pbs_flags & _BUS_SPACE_STRIDE_MASK) { 436 t->pbs_scalar = scalar_strided_ops; 437 t->pbs_multi = &multi_strided_ops; 438 t->pbs_region = ®ion_strided_ops; 439 t->pbs_set = &set_strided_ops; 440 } else { 441 t->pbs_scalar = scalar_ops; 442 t->pbs_multi = &multi_ops; 443 t->pbs_region = ®ion_ops; 444 t->pbs_set = &set_ops; 445 } 446 } else { 447 if (t->pbs_flags & _BUS_SPACE_STRIDE_MASK) { 448 t->pbs_scalar = scalar_rb_strided_ops; 449 t->pbs_multi = &multi_rb_strided_ops; 450 t->pbs_region = ®ion_rb_strided_ops; 451 t->pbs_set = &set_rb_strided_ops; 452 } else { 453 t->pbs_scalar = scalar_rb_ops; 454 t->pbs_multi = &multi_rb_ops; 455 t->pbs_region = ®ion_rb_ops; 456 t->pbs_set = &set_rb_ops; 457 } 458 } 459 #else 460 if (t->pbs_flags & _BUS_SPACE_LITTLE_ENDIAN) { 461 if (t->pbs_flags & _BUS_SPACE_STRIDE_MASK) { 462 t->pbs_scalar = scalar_strided_ops; 463 t->pbs_multi = &multi_strided_ops; 464 t->pbs_region = ®ion_strided_ops; 465 t->pbs_set = &set_strided_ops; 466 } else { 467 t->pbs_scalar = scalar_ops; 468 t->pbs_multi = &multi_ops; 469 t->pbs_region = ®ion_ops; 470 t->pbs_set = &set_ops; 471 } 472 } else { 473 if (t->pbs_flags & _BUS_SPACE_STRIDE_MASK) { 474 t->pbs_scalar = scalar_rb_strided_ops; 475 t->pbs_multi = &multi_rb_strided_ops; 476 t->pbs_region = ®ion_rb_strided_ops; 477 t->pbs_set = &set_rb_strided_ops; 478 } else { 479 t->pbs_scalar = scalar_rb_ops; 480 t->pbs_multi = &multi_rb_ops; 481 t->pbs_region = ®ion_rb_ops; 482 t->pbs_set = &set_rb_ops; 483 } 484 } 485 #endif 486 return 0; 487 } 488 489 void 490 bus_space_mallocok(void) 491 { 492 extent_flags = EX_MALLOCOK; 493 } 494 495 /* ARGSUSED */ 496 paddr_t 497 memio_mmap(bus_space_tag_t t, bus_addr_t bpa, off_t offset, int prot, int flags) 498 { 499 paddr_t ret; 500 /* XXX what about stride? */ 501 ret = trunc_page(t->pbs_offset + bpa + offset); 502 #ifdef DEBUG 503 if (ret == 0) { 504 printf("%s: [%08x, %08x %08x] mmaps to 0?!\n", __func__, 505 (uint32_t)t->pbs_offset, (uint32_t)bpa, (uint32_t)offset); 506 return -1; 507 } 508 #endif 509 return ret; 510 } 511 512 int 513 memio_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, int flags, 514 bus_space_handle_t *bshp) 515 { 516 int error; 517 paddr_t pa; 518 519 size = _BUS_SPACE_STRIDE(t, size); 520 bpa = _BUS_SPACE_STRIDE(t, bpa); 521 522 if (bpa + size > t->pbs_limit) { 523 #ifdef DEBUG 524 printf("bus_space_map(%p[%x:%x], %#x, %#x) failed: EINVAL\n", 525 t, t->pbs_base, t->pbs_limit, bpa, size); 526 #endif 527 return (EINVAL); 528 } 529 530 /* 531 * Can't map I/O space as linear. 532 */ 533 if ((flags & BUS_SPACE_MAP_LINEAR) && 534 (t->pbs_flags & _BUS_SPACE_IO_TYPE)) { 535 return (EOPNOTSUPP); 536 } 537 538 if (t->pbs_extent != NULL) { 539 #ifdef PPC_IBM4XX 540 /* 541 * XXX: Temporary kludge. 542 * Don't bother checking the extent during very early bootstrap. 543 */ 544 if (extent_flags) { 545 #endif 546 /* 547 * Before we go any further, let's make sure that this 548 * region is available. 549 */ 550 error = extent_alloc_region(t->pbs_extent, bpa, size, 551 EX_NOWAIT | extent_flags); 552 if (error) { 553 #ifdef DEBUG 554 printf("bus_space_map(%p[%x:%x], %#x, %#x) failed" 555 ": %d\n", 556 t, t->pbs_base, t->pbs_limit, bpa, size, error); 557 #endif 558 return (error); 559 } 560 #ifdef PPC_IBM4XX 561 } 562 #endif 563 } 564 565 pa = t->pbs_offset + bpa; 566 #if defined (PPC_OEA) || defined(PPC_OEA601) 567 #ifdef PPC_OEA601 568 if ((mfpvr() >> 16) == MPC601) { 569 /* 570 * Map via the MPC601's I/O segments 571 */ 572 register_t sr = iosrtable[pa >> ADDR_SR_SHFT]; 573 if (SR601_VALID_P(sr) && ((pa >> ADDR_SR_SHFT) == 574 ((pa + size - 1) >> ADDR_SR_SHFT))) { 575 *bshp = pa; 576 return (0); 577 } 578 } else 579 #endif /* PPC_OEA601 */ 580 if ((oeacpufeat & OEACPU_NOBAT) == 0) { 581 /* 582 * Let's try to BAT map this address if possible 583 * (note this assumes 1:1 VA:PA) 584 */ 585 register_t batu = battable[BAT_VA2IDX(pa)].batu; 586 if (BAT_VALID_P(batu, 0) && BAT_VA_MATCH_P(batu, pa) && 587 BAT_VA_MATCH_P(batu, pa + size - 1)) { 588 *bshp = pa; 589 return (0); 590 } 591 } 592 #endif /* defined (PPC_OEA) || defined(PPC_OEA601) */ 593 594 if (t->pbs_extent != NULL) { 595 #if !defined(PPC_IBM4XX) 596 if (extent_flags == 0) { 597 extent_free(t->pbs_extent, bpa, size, EX_NOWAIT); 598 #ifdef DEBUG 599 printf("bus_space_map(%p[%x:%x], %#x, %#x) failed: ENOMEM\n", 600 t, t->pbs_base, t->pbs_limit, bpa, size); 601 #endif 602 return (ENOMEM); 603 } 604 #endif 605 } 606 607 /* 608 * Map this into the kernel pmap. 609 */ 610 *bshp = (bus_space_handle_t) mapiodev(pa, size); 611 if (*bshp == 0) { 612 extent_free(t->pbs_extent, bpa, size, EX_NOWAIT | extent_flags); 613 #ifdef DEBUG 614 printf("bus_space_map(%p[%x:%x], %#x, %#x) failed: ENOMEM\n", 615 t, t->pbs_base, t->pbs_limit, bpa, size); 616 #endif 617 return (ENOMEM); 618 } 619 620 return (0); 621 } 622 623 int 624 memio_subregion(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset, 625 bus_size_t size, bus_space_handle_t *bshp) 626 { 627 *bshp = bsh + _BUS_SPACE_STRIDE(t, offset); 628 return (0); 629 } 630 631 void 632 memio_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) 633 { 634 bus_addr_t bpa; 635 vaddr_t va = bsh; 636 paddr_t pa; 637 638 size = _BUS_SPACE_STRIDE(t, size); 639 640 #if defined (PPC_OEA) || defined(PPC_OEA601) 641 #ifdef PPC_OEA601 642 if ((mfpvr() >> 16) == MPC601) { 643 register_t sr = iosrtable[va >> ADDR_SR_SHFT]; 644 if (SR601_VALID_P(sr) && ((pa >> ADDR_SR_SHFT) == 645 ((pa + size - 1) >> ADDR_SR_SHFT))) { 646 pa = va; 647 va = 0; 648 } else { 649 pmap_extract(pmap_kernel(), va, &pa); 650 } 651 } else 652 #endif /* PPC_OEA601 */ 653 if ((oeacpufeat & OEACPU_NOBAT) == 0) { 654 register_t batu = battable[BAT_VA2IDX(va)].batu; 655 if (BAT_VALID_P(batu, 0) && BAT_VA_MATCH_P(batu, va) && 656 BAT_VA_MATCH_P(batu, va + size - 1)) { 657 pa = va; 658 va = 0; 659 } else { 660 pmap_extract(pmap_kernel(), va, &pa); 661 } 662 } else 663 pmap_extract(pmap_kernel(), va, &pa); 664 #else 665 pmap_extract(pmap_kernel(), va, &pa); 666 #endif /* defined (PPC_OEA) || defined(PPC_OEA601) */ 667 bpa = pa - t->pbs_offset; 668 669 if (t->pbs_extent != NULL 670 && extent_free(t->pbs_extent, bpa, size, 671 EX_NOWAIT | extent_flags)) { 672 printf("memio_unmap: %s 0x%lx, size 0x%lx\n", 673 (t->pbs_flags & _BUS_SPACE_IO_TYPE) ? "port" : "mem", 674 (unsigned long)bpa, (unsigned long)size); 675 printf("memio_unmap: can't free region\n"); 676 } 677 678 unmapiodev(va, size); 679 } 680 681 int 682 memio_alloc(bus_space_tag_t t, bus_addr_t rstart, bus_addr_t rend, 683 bus_size_t size, bus_size_t alignment, bus_size_t boundary, 684 int flags, bus_addr_t *bpap, bus_space_handle_t *bshp) 685 { 686 u_long bpa; 687 paddr_t pa; 688 int error; 689 690 size = _BUS_SPACE_STRIDE(t, size); 691 rstart = _BUS_SPACE_STRIDE(t, rstart); 692 693 if (t->pbs_extent == NULL) 694 return ENOMEM; 695 696 if (rstart + size > t->pbs_limit) { 697 #ifdef DEBUG 698 printf("%s(%p[%x:%x], %#x, %#x) failed: EINVAL\n", 699 __func__, t, t->pbs_base, t->pbs_limit, rstart, size); 700 #endif 701 return (EINVAL); 702 } 703 704 /* 705 * Can't map I/O space as linear. 706 */ 707 if ((flags & BUS_SPACE_MAP_LINEAR) && 708 (t->pbs_flags & _BUS_SPACE_IO_TYPE)) 709 return (EOPNOTSUPP); 710 711 if (rstart < t->pbs_extent->ex_start || rend > t->pbs_extent->ex_end) 712 panic("memio_alloc: bad region start/end"); 713 714 error = extent_alloc_subregion(t->pbs_extent, rstart, rend, size, 715 alignment, boundary, EX_FAST | EX_NOWAIT | extent_flags, &bpa); 716 717 if (error) 718 return (error); 719 720 *bpap = bpa; 721 pa = t->pbs_offset + bpa; 722 #if defined (PPC_OEA) || defined(PPC_OEA601) 723 #ifdef PPC_OEA601 724 if ((mfpvr() >> 16) == MPC601) { 725 register_t sr = iosrtable[pa >> ADDR_SR_SHFT]; 726 if (SR601_VALID_P(sr) && SR601_PA_MATCH_P(sr, pa) && 727 SR601_PA_MATCH_P(sr, pa + size - 1)) { 728 *bshp = pa; 729 return (0); 730 } 731 } else 732 #endif /* PPC_OEA601 */ 733 if ((oeacpufeat & OEACPU_NOBAT) == 0) { 734 register_t batu = battable[BAT_VA2IDX(pa)].batu; 735 if (BAT_VALID_P(batu, 0) && BAT_VA_MATCH_P(batu, pa) && 736 BAT_VA_MATCH_P(batu, pa + size - 1)) { 737 *bshp = pa; 738 return (0); 739 } 740 } 741 #endif /* defined (PPC_OEA) || defined(PPC_OEA601) */ 742 *bshp = (bus_space_handle_t) mapiodev(pa, size); 743 if (*bshp == 0) { 744 extent_free(t->pbs_extent, bpa, size, EX_NOWAIT | extent_flags); 745 return (ENOMEM); 746 } 747 748 return (0); 749 } 750 751 void 752 memio_free(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) 753 { 754 if (t->pbs_extent == NULL) 755 return; 756 757 /* memio_unmap() does all that we need to do. */ 758 memio_unmap(t, bsh, size); 759 } 760