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