1 /* $NetBSD: bus_space.c,v 1.40 2026/06/17 15:08:54 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.40 2026/06/17 15:08:54 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 511 #ifdef DEBUG 512 if (ret == 0) { 513 printf("%s: [%08x, %08x %08x] mmaps to 0?!\n", __func__, 514 (uint32_t)t->pbs_offset, (uint32_t)bpa, (uint32_t)offset); 515 return -1; 516 } 517 #endif 518 519 #ifdef POWERPC_MMAP_FLAG_MASK 520 if (flags & BUS_SPACE_MAP_PREFETCHABLE) 521 ret |= POWERPC_MMAP_FLAG_PREFETCHABLE; 522 if (flags & BUS_SPACE_MAP_CACHEABLE) 523 ret |= POWERPC_MMAP_FLAG_CACHEABLE; 524 #endif 525 526 return ret; 527 } 528 529 int 530 memio_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, int flags, 531 bus_space_handle_t *bshp) 532 { 533 int error; 534 paddr_t pa; 535 536 size = _BUS_SPACE_STRIDE(t, size); 537 bpa = _BUS_SPACE_STRIDE(t, bpa); 538 539 if (t->pbs_limit != 0 && bpa + size - 1 > t->pbs_limit) { 540 #ifdef DEBUG 541 printf("bus_space_map(%p[%x:%x], %#x, %#x) failed: EINVAL\n", 542 t, t->pbs_base, t->pbs_limit, bpa, size); 543 #endif 544 return (EINVAL); 545 } 546 547 /* 548 * Can't map I/O space as linear. 549 */ 550 if ((flags & BUS_SPACE_MAP_LINEAR) && 551 (t->pbs_flags & _BUS_SPACE_IO_TYPE)) { 552 return (EOPNOTSUPP); 553 } 554 555 if (t->pbs_extent != NULL) { 556 #ifdef PPC_IBM4XX 557 /* 558 * XXX: Temporary kludge. 559 * Don't bother checking the extent during very early bootstrap. 560 */ 561 if (extent_flags) { 562 #endif 563 /* 564 * Before we go any further, let's make sure that this 565 * region is available. 566 */ 567 error = extent_alloc_region(t->pbs_extent, bpa, size, 568 EX_NOWAIT | extent_flags); 569 if (error) { 570 #ifdef DEBUG 571 printf("bus_space_map(%p[%x:%x], %#x, %#x)" 572 " failed: %d\n", 573 t, t->pbs_base, t->pbs_limit, 574 bpa, size, error); 575 #endif 576 return (error); 577 } 578 #ifdef PPC_IBM4XX 579 } 580 #endif 581 } 582 583 pa = t->pbs_offset + bpa; 584 #if defined (PPC_OEA) || defined(PPC_OEA601) 585 #ifdef PPC_OEA601 586 if ((mfpvr() >> 16) == MPC601) { 587 /* 588 * Map via the MPC601's I/O segments 589 */ 590 register_t sr = iosrtable[pa >> ADDR_SR_SHFT]; 591 if (SR601_VALID_P(sr) && ((pa >> ADDR_SR_SHFT) == 592 ((pa + size - 1) >> ADDR_SR_SHFT))) { 593 *bshp = pa; 594 return (0); 595 } 596 } else 597 #endif /* PPC_OEA601 */ 598 if ((oeacpufeat & OEACPU_NOBAT) == 0) { 599 /* 600 * Let's try to BAT map this address if possible 601 * (note this assumes 1:1 VA:PA) 602 */ 603 register_t batu = battable[BAT_VA2IDX(pa)].batu; 604 if (BAT_VALID_P(batu, 0) && BAT_VA_MATCH_P(batu, pa) && 605 BAT_VA_MATCH_P(batu, pa + size - 1)) { 606 *bshp = pa; 607 return (0); 608 } 609 } 610 #endif /* defined (PPC_OEA) || defined(PPC_OEA601) */ 611 612 /* 613 * Map this into the kernel pmap. 614 */ 615 *bshp = (bus_space_handle_t) mapiodev(pa, size, 616 (flags & BUS_SPACE_MAP_PREFETCHABLE) != 0); 617 if (*bshp == 0) { 618 if (t->pbs_extent != NULL) { 619 extent_free(t->pbs_extent, bpa, size, 620 EX_NOWAIT | extent_flags); 621 } 622 #ifdef DEBUG 623 printf("bus_space_map(%p[%x:%x], %#x, %#x) failed: ENOMEM\n", 624 t, t->pbs_base, t->pbs_limit, bpa, size); 625 #endif 626 return (ENOMEM); 627 } 628 629 return (0); 630 } 631 632 int 633 memio_subregion(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset, 634 bus_size_t size, bus_space_handle_t *bshp) 635 { 636 *bshp = bsh + _BUS_SPACE_STRIDE(t, offset); 637 return (0); 638 } 639 640 void 641 memio_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) 642 { 643 bus_addr_t bpa; 644 vaddr_t va = bsh; 645 paddr_t pa; 646 647 size = _BUS_SPACE_STRIDE(t, size); 648 649 #if defined (PPC_OEA) || defined(PPC_OEA601) 650 #ifdef PPC_OEA601 651 if ((mfpvr() >> 16) == MPC601) { 652 register_t sr = iosrtable[va >> ADDR_SR_SHFT]; 653 if (SR601_VALID_P(sr) && ((va >> ADDR_SR_SHFT) == 654 ((va + size - 1) >> ADDR_SR_SHFT))) { 655 pa = va; 656 va = 0; 657 } else { 658 pmap_extract(pmap_kernel(), va, &pa); 659 } 660 } else 661 #endif /* PPC_OEA601 */ 662 if ((oeacpufeat & OEACPU_NOBAT) == 0) { 663 register_t batu = battable[BAT_VA2IDX(va)].batu; 664 if (BAT_VALID_P(batu, 0) && BAT_VA_MATCH_P(batu, va) && 665 BAT_VA_MATCH_P(batu, va + size - 1)) { 666 pa = va; 667 va = 0; 668 } else { 669 pmap_extract(pmap_kernel(), va, &pa); 670 } 671 } else 672 pmap_extract(pmap_kernel(), va, &pa); 673 #elif defined(PPC_IBM440) 674 /* 675 * On 440, bus_space mappings use pinned reserved TLB entries 676 */ 677 if (!ppc44x_tlb_reverse(va, &pa)) 678 pmap_extract(pmap_kernel(), va, &pa); 679 #else 680 pmap_extract(pmap_kernel(), va, &pa); 681 #endif /* defined (PPC_OEA) || defined(PPC_OEA601) */ 682 bpa = pa - t->pbs_offset; 683 684 if (t->pbs_extent != NULL 685 #ifdef PPC_IBM4XX 686 && extent_flags 687 #endif 688 && extent_free(t->pbs_extent, bpa, size, 689 EX_NOWAIT | extent_flags)) { 690 printf("memio_unmap: %s 0x%lx, size 0x%lx\n", 691 (t->pbs_flags & _BUS_SPACE_IO_TYPE) ? "port" : "mem", 692 (unsigned long)bpa, (unsigned long)size); 693 printf("memio_unmap: can't free region\n"); 694 } 695 696 if (va) 697 unmapiodev(va, size); 698 } 699 700 int 701 memio_alloc(bus_space_tag_t t, bus_addr_t rstart, bus_addr_t rend, 702 bus_size_t size, bus_size_t alignment, bus_size_t boundary, 703 int flags, bus_addr_t *bpap, bus_space_handle_t *bshp) 704 { 705 u_long bpa; 706 paddr_t pa; 707 int error; 708 709 size = _BUS_SPACE_STRIDE(t, size); 710 rstart = _BUS_SPACE_STRIDE(t, rstart); 711 712 if (t->pbs_extent == NULL) 713 return ENOMEM; 714 715 if (t->pbs_limit != 0 && rstart + size - 1 > t->pbs_limit) { 716 #ifdef DEBUG 717 printf("%s(%p[%x:%x], %#x, %#x) failed: EINVAL\n", 718 __func__, t, t->pbs_base, t->pbs_limit, rstart, size); 719 #endif 720 return (EINVAL); 721 } 722 723 /* 724 * Can't map I/O space as linear. 725 */ 726 if ((flags & BUS_SPACE_MAP_LINEAR) && 727 (t->pbs_flags & _BUS_SPACE_IO_TYPE)) 728 return (EOPNOTSUPP); 729 730 if (rstart < t->pbs_extent->ex_start || rend > t->pbs_extent->ex_end) 731 panic("memio_alloc: bad region start/end"); 732 733 error = extent_alloc_subregion(t->pbs_extent, rstart, rend, size, 734 alignment, boundary, EX_FAST | EX_NOWAIT | extent_flags, &bpa); 735 736 if (error) 737 return (error); 738 739 *bpap = bpa; 740 pa = t->pbs_offset + bpa; 741 #if defined (PPC_OEA) || defined(PPC_OEA601) 742 #ifdef PPC_OEA601 743 if ((mfpvr() >> 16) == MPC601) { 744 register_t sr = iosrtable[pa >> ADDR_SR_SHFT]; 745 if (SR601_VALID_P(sr) && SR601_PA_MATCH_P(sr, pa) && 746 SR601_PA_MATCH_P(sr, pa + size - 1)) { 747 *bshp = pa; 748 return (0); 749 } 750 } else 751 #endif /* PPC_OEA601 */ 752 if ((oeacpufeat & OEACPU_NOBAT) == 0) { 753 register_t batu = battable[BAT_VA2IDX(pa)].batu; 754 if (BAT_VALID_P(batu, 0) && BAT_VA_MATCH_P(batu, pa) && 755 BAT_VA_MATCH_P(batu, pa + size - 1)) { 756 *bshp = pa; 757 return (0); 758 } 759 } 760 #endif /* defined (PPC_OEA) || defined(PPC_OEA601) */ 761 *bshp = (bus_space_handle_t) mapiodev(pa, size, false); 762 if (*bshp == 0) { 763 extent_free(t->pbs_extent, bpa, size, EX_NOWAIT | extent_flags); 764 return (ENOMEM); 765 } 766 767 return (0); 768 } 769 770 void 771 memio_free(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) 772 { 773 if (t->pbs_extent == NULL) 774 return; 775 776 /* memio_unmap() does all that we need to do. */ 777 memio_unmap(t, bsh, size); 778 } 779 780 void 781 memio_barrier(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size, 782 bus_size_t offset, int flags) 783 { 784 __asm volatile("eieio" ::: "memory"); 785 } 786