Home | History | Annotate | Line # | Download | only in powerpc
      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 = &region_strided_ops;
    431 		t->pbs_set_stream = &set_strided_ops;
    432 		t->pbs_copy = &copy_strided_ops;
    433 	} else {
    434 		t->pbs_scalar_stream = scalar_ops;
    435 		t->pbs_multi_stream = &multi_ops;
    436 		t->pbs_region_stream = &region_ops;
    437 		t->pbs_set_stream = &set_ops;
    438 		t->pbs_copy = &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 = &region_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 = &region_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 = &region_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 = &region_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 = &region_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 = &region_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 = &region_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 = &region_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