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