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