Home | History | Annotate | Line # | Download | only in atari
      1 /*	$NetBSD: le_bus.c,v 1.23 2023/01/06 10:28:27 tsutsui Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Leo Weppelman.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __KERNEL_RCSID(0, "$NetBSD: le_bus.c,v 1.23 2023/01/06 10:28:27 tsutsui Exp $");
     34 
     35 #include <sys/types.h>
     36 #include <sys/param.h>
     37 #include <sys/systm.h>
     38 #include <sys/kmem.h>
     39 #include <sys/bswap.h>
     40 #include <machine/cpu.h>
     41 #include <sys/bus.h>
     42 
     43 /*
     44  * This file contains the common functions for using a little endian (linear)
     45  * bus on a big endian atari.
     46  */
     47 
     48 	/* Autoconf detection stuff */
     49 static int		leb_bus_space_peek_1(bus_space_tag_t,
     50 				bus_space_handle_t, bus_size_t);
     51 static int		leb_bus_space_peek_2(bus_space_tag_t,
     52 				bus_space_handle_t, bus_size_t);
     53 static int		leb_bus_space_peek_4(bus_space_tag_t,
     54 				bus_space_handle_t, bus_size_t);
     55 static int		leb_bus_space_peek_8(bus_space_tag_t,
     56 				bus_space_handle_t, bus_size_t);
     57 
     58 	/* read (single) */
     59 static uint8_t		leb_bus_space_read_1(bus_space_tag_t,
     60 				bus_space_handle_t, bus_size_t);
     61 static uint16_t		leb_bus_space_read_2(bus_space_tag_t,
     62 				bus_space_handle_t, bus_size_t);
     63 static uint32_t		leb_bus_space_read_4(bus_space_tag_t,
     64 				bus_space_handle_t, bus_size_t);
     65 static uint64_t		leb_bus_space_read_8(bus_space_tag_t,
     66 				bus_space_handle_t, bus_size_t);
     67 
     68 	/* write (single) */
     69 static void		leb_bus_space_write_1(bus_space_tag_t,
     70 				bus_space_handle_t, bus_size_t, uint8_t);
     71 static void		leb_bus_space_write_2(bus_space_tag_t,
     72 				bus_space_handle_t, bus_size_t, uint16_t);
     73 static void		leb_bus_space_write_4(bus_space_tag_t,
     74 				bus_space_handle_t, bus_size_t, uint32_t);
     75 static void		leb_bus_space_write_8(bus_space_tag_t,
     76 				bus_space_handle_t, bus_size_t, uint64_t);
     77 
     78 	/* read (single) stream */
     79 static uint16_t		leb_bus_space_read_stream_2(bus_space_tag_t,
     80 				bus_space_handle_t, bus_size_t);
     81 static uint32_t		leb_bus_space_read_stream_4(bus_space_tag_t,
     82 				bus_space_handle_t, bus_size_t);
     83 static uint64_t		leb_bus_space_read_stream_8(bus_space_tag_t,
     84 				bus_space_handle_t, bus_size_t);
     85 
     86 	/* write (single) stream */
     87 static void		leb_bus_space_write_stream_2(bus_space_tag_t,
     88 				bus_space_handle_t, bus_size_t, uint16_t);
     89 static void		leb_bus_space_write_stream_4(bus_space_tag_t,
     90 				bus_space_handle_t, bus_size_t, uint32_t);
     91 static void		leb_bus_space_write_stream_8(bus_space_tag_t,
     92 				bus_space_handle_t, bus_size_t, uint64_t);
     93 
     94 	/* read multiple */
     95 static void		leb_bus_space_read_multi_1(bus_space_tag_t,
     96 				bus_space_handle_t, bus_size_t, uint8_t *,
     97 				bus_size_t);
     98 static void		leb_bus_space_read_multi_2(bus_space_tag_t,
     99 				bus_space_handle_t, bus_size_t, uint16_t *,
    100 				bus_size_t);
    101 static void		leb_bus_space_read_multi_4(bus_space_tag_t,
    102 				bus_space_handle_t, bus_size_t, uint32_t *,
    103 				bus_size_t);
    104 static void		leb_bus_space_read_multi_8(bus_space_tag_t,
    105 				bus_space_handle_t, bus_size_t, uint64_t *,
    106 				bus_size_t);
    107 
    108 	/* write multiple */
    109 static void		leb_bus_space_write_multi_1(bus_space_tag_t,
    110 				bus_space_handle_t, bus_size_t,
    111 				const uint8_t *, bus_size_t);
    112 static void		leb_bus_space_write_multi_2(bus_space_tag_t,
    113 				bus_space_handle_t, bus_size_t,
    114 				const uint16_t *, bus_size_t);
    115 static void		leb_bus_space_write_multi_4(bus_space_tag_t,
    116 				bus_space_handle_t, bus_size_t,
    117 				const uint32_t *, bus_size_t);
    118 static void		leb_bus_space_write_multi_8(bus_space_tag_t,
    119 				bus_space_handle_t, bus_size_t,
    120 				const uint64_t *, bus_size_t);
    121 
    122 	/* read multiple stream */
    123 static void		leb_bus_space_read_multi_stream_2(bus_space_tag_t,
    124 				bus_space_handle_t, bus_size_t, uint16_t *,
    125 				bus_size_t);
    126 static void		leb_bus_space_read_multi_stream_4(bus_space_tag_t,
    127 				bus_space_handle_t, bus_size_t, uint32_t *,
    128 				bus_size_t);
    129 static void		leb_bus_space_read_multi_stream_8(bus_space_tag_t,
    130 				bus_space_handle_t, bus_size_t, uint64_t *,
    131 				bus_size_t);
    132 
    133 	/* write multiple stream */
    134 static void		leb_bus_space_write_multi_stream_2(bus_space_tag_t,
    135 				bus_space_handle_t, bus_size_t,
    136 				const uint16_t *, bus_size_t);
    137 static void		leb_bus_space_write_multi_stream_4(bus_space_tag_t,
    138 				bus_space_handle_t, bus_size_t,
    139 				const uint32_t *, bus_size_t);
    140 static void		leb_bus_space_write_multi_stream_8(bus_space_tag_t,
    141 				bus_space_handle_t, bus_size_t,
    142 				const uint64_t *, bus_size_t);
    143 
    144 	/* read region */
    145 static void		leb_bus_space_read_region_1(bus_space_tag_t,
    146 				bus_space_handle_t, bus_size_t, uint8_t *,
    147 				bus_size_t);
    148 static void		leb_bus_space_read_region_2(bus_space_tag_t,
    149 				bus_space_handle_t, bus_size_t, uint16_t *,
    150 				bus_size_t);
    151 static void		leb_bus_space_read_region_4(bus_space_tag_t,
    152 				bus_space_handle_t, bus_size_t, uint32_t *,
    153 				bus_size_t);
    154 static void		leb_bus_space_read_region_8(bus_space_tag_t,
    155 				bus_space_handle_t, bus_size_t, uint64_t *,
    156 				bus_size_t);
    157 
    158 	/* write region */
    159 static void		leb_bus_space_write_region_1(bus_space_tag_t,
    160 				bus_space_handle_t, bus_size_t,
    161 				const uint8_t *, bus_size_t);
    162 static void		leb_bus_space_write_region_2(bus_space_tag_t,
    163 				bus_space_handle_t, bus_size_t,
    164 				const uint16_t *, bus_size_t);
    165 static void		leb_bus_space_write_region_4(bus_space_tag_t,
    166 				bus_space_handle_t, bus_size_t,
    167 				const uint32_t *, bus_size_t);
    168 static void		leb_bus_space_write_region_8(bus_space_tag_t,
    169 				bus_space_handle_t, bus_size_t,
    170 				const uint64_t *, bus_size_t);
    171 
    172 	/* read region stream */
    173 static void		leb_bus_space_read_region_stream_2(bus_space_tag_t,
    174 				bus_space_handle_t, bus_size_t, uint16_t *,
    175 				bus_size_t);
    176 static void		leb_bus_space_read_region_stream_4(bus_space_tag_t,
    177 				bus_space_handle_t, bus_size_t, uint32_t *,
    178 				bus_size_t);
    179 static void		leb_bus_space_read_region_stream_8(bus_space_tag_t,
    180 				bus_space_handle_t, bus_size_t, uint64_t *,
    181 				bus_size_t);
    182 
    183 	/* write region */
    184 static void		leb_bus_space_write_region_stream_2(bus_space_tag_t,
    185 				bus_space_handle_t, bus_size_t,
    186 				const uint16_t *, bus_size_t);
    187 static void		leb_bus_space_write_region_stream_4(bus_space_tag_t,
    188 				bus_space_handle_t, bus_size_t,
    189 				const uint32_t *, bus_size_t);
    190 static void		leb_bus_space_write_region_stream_8(bus_space_tag_t,
    191 				bus_space_handle_t, bus_size_t,
    192 				const uint64_t *, bus_size_t);
    193 
    194 	/* set multi */
    195 static void		leb_bus_space_set_multi_1(bus_space_tag_t,
    196 				bus_space_handle_t, bus_size_t, uint8_t,
    197 				bus_size_t);
    198 static void		leb_bus_space_set_multi_2(bus_space_tag_t,
    199 				bus_space_handle_t, bus_size_t, uint16_t,
    200 				bus_size_t);
    201 static void		leb_bus_space_set_multi_4(bus_space_tag_t,
    202 				bus_space_handle_t, bus_size_t, uint32_t,
    203 				bus_size_t);
    204 static void		leb_bus_space_set_multi_8(bus_space_tag_t,
    205 				bus_space_handle_t, bus_size_t, uint64_t,
    206 				bus_size_t);
    207 
    208 	/* set region */
    209 static void		leb_bus_space_set_region_1(bus_space_tag_t,
    210 				bus_space_handle_t, bus_size_t, uint8_t,
    211 				bus_size_t);
    212 static void		leb_bus_space_set_region_2(bus_space_tag_t,
    213 				bus_space_handle_t, bus_size_t, uint16_t,
    214 				bus_size_t);
    215 static void		leb_bus_space_set_region_4(bus_space_tag_t,
    216 				bus_space_handle_t, bus_size_t, uint32_t,
    217 				bus_size_t);
    218 static void		leb_bus_space_set_region_8(bus_space_tag_t,
    219 				bus_space_handle_t, bus_size_t, uint64_t,
    220 				bus_size_t);
    221 
    222 /*
    223  * Define these inline, to avoid function call overhead.
    224  * XXX: Maybe move to an m68k include file?
    225  */
    226 static uint16_t swap16(uint16_t v);
    227 static uint32_t swap32(uint32_t v);
    228 
    229 static inline uint16_t swap16(uint16_t v)
    230 {
    231 
    232 	__asm volatile ("rolw	#8, %0" : "=d"(v) : "0"(v));
    233 	return v;
    234 }
    235 
    236 static inline uint32_t swap32(uint32_t v)
    237 {
    238 
    239 	__asm volatile ("	rolw	#8, %0	\n"
    240 			"	swap	%0	\n"
    241 			"	rolw	#8, %0" : "=d"(v) : "0"(v));
    242 	return v;
    243 }
    244 
    245 /*
    246  * Don't force a function call overhead on these primitives...
    247  */
    248 #define __read_1(h, o)		*((volatile uint8_t *)((h) + (o)))
    249 #define __read_2(h, o)		swap16(*((volatile uint16_t *)((h) + (o))))
    250 #define __read_4(h, o)		swap32(*((volatile uint32_t *)((h) + (o))))
    251 #define __read_8(h, o)		bswap64(*((volatile uint64_t *)((h) + (o))))
    252 
    253 #define __write_1(h, o, v)	*((volatile uint8_t *)((h) + (o))) = (v)
    254 #define __write_2(h, o, v)	*((volatile uint16_t *)((h) + (o))) = swap16(v)
    255 #define __write_4(h, o, v)	*((volatile uint32_t *)((h) + (o))) = swap32(v)
    256 #define __write_8(h, o, v)	*((volatile uint64_t *)((h) + (o))) = bswap64(v)
    257 
    258 bus_space_tag_t
    259 leb_alloc_bus_space_tag(bus_space_tag_t storage)
    260 {
    261 	bus_space_tag_t			leb_t;
    262 
    263 	/*
    264 	 * Allow the caller to specify storage space for the tag. This
    265 	 * is used during console config (when kmem_alloc() can't be used).
    266 	 */
    267 	if (storage != NULL)
    268 		leb_t = storage;
    269 	else {
    270 		leb_t = kmem_alloc(sizeof(*leb_t), KM_SLEEP);
    271 	}
    272 	memset(leb_t, 0, sizeof(*leb_t));
    273 
    274 	leb_t->abs_p_1   = leb_bus_space_peek_1;
    275 	leb_t->abs_p_2   = leb_bus_space_peek_2;
    276 	leb_t->abs_p_4   = leb_bus_space_peek_4;
    277 	leb_t->abs_p_8   = leb_bus_space_peek_8;
    278 	leb_t->abs_r_1   = leb_bus_space_read_1;
    279 	leb_t->abs_r_2   = leb_bus_space_read_2;
    280 	leb_t->abs_r_4   = leb_bus_space_read_4;
    281 	leb_t->abs_r_8   = leb_bus_space_read_8;
    282 	leb_t->abs_rs_1  = leb_bus_space_read_1;
    283 	leb_t->abs_rs_2  = leb_bus_space_read_stream_2;
    284 	leb_t->abs_rs_4  = leb_bus_space_read_stream_4;
    285 	leb_t->abs_rs_8  = leb_bus_space_read_stream_8;
    286 	leb_t->abs_rm_1  = leb_bus_space_read_multi_1;
    287 	leb_t->abs_rm_2  = leb_bus_space_read_multi_2;
    288 	leb_t->abs_rm_4  = leb_bus_space_read_multi_4;
    289 	leb_t->abs_rm_8  = leb_bus_space_read_multi_8;
    290 	leb_t->abs_rms_1 = leb_bus_space_read_multi_1;
    291 	leb_t->abs_rms_2 = leb_bus_space_read_multi_stream_2;
    292 	leb_t->abs_rms_4 = leb_bus_space_read_multi_stream_4;
    293 	leb_t->abs_rms_8 = leb_bus_space_read_multi_stream_8;
    294 	leb_t->abs_rr_1  = leb_bus_space_read_region_1;
    295 	leb_t->abs_rr_2  = leb_bus_space_read_region_2;
    296 	leb_t->abs_rr_4  = leb_bus_space_read_region_4;
    297 	leb_t->abs_rr_8  = leb_bus_space_read_region_8;
    298 	leb_t->abs_rrs_1 = leb_bus_space_read_region_1;
    299 	leb_t->abs_rrs_2 = leb_bus_space_read_region_stream_2;
    300 	leb_t->abs_rrs_4 = leb_bus_space_read_region_stream_4;
    301 	leb_t->abs_rrs_8 = leb_bus_space_read_region_stream_8;
    302 	leb_t->abs_w_1   = leb_bus_space_write_1;
    303 	leb_t->abs_w_2   = leb_bus_space_write_2;
    304 	leb_t->abs_w_4   = leb_bus_space_write_4;
    305 	leb_t->abs_w_8   = leb_bus_space_write_8;
    306 	leb_t->abs_ws_1  = leb_bus_space_write_1;
    307 	leb_t->abs_ws_2  = leb_bus_space_write_stream_2;
    308 	leb_t->abs_ws_4  = leb_bus_space_write_stream_4;
    309 	leb_t->abs_ws_8  = leb_bus_space_write_stream_8;
    310 	leb_t->abs_wm_1  = leb_bus_space_write_multi_1;
    311 	leb_t->abs_wm_2  = leb_bus_space_write_multi_2;
    312 	leb_t->abs_wm_4  = leb_bus_space_write_multi_4;
    313 	leb_t->abs_wm_8  = leb_bus_space_write_multi_8;
    314 	leb_t->abs_wms_1 = leb_bus_space_write_multi_1;
    315 	leb_t->abs_wms_2 = leb_bus_space_write_multi_stream_2;
    316 	leb_t->abs_wms_4 = leb_bus_space_write_multi_stream_4;
    317 	leb_t->abs_wms_8 = leb_bus_space_write_multi_stream_8;
    318 	leb_t->abs_wr_1  = leb_bus_space_write_region_1;
    319 	leb_t->abs_wr_2  = leb_bus_space_write_region_2;
    320 	leb_t->abs_wr_4  = leb_bus_space_write_region_4;
    321 	leb_t->abs_wr_8  = leb_bus_space_write_region_8;
    322 	leb_t->abs_wrs_1 = leb_bus_space_write_region_1;
    323 	leb_t->abs_wrs_2 = leb_bus_space_write_region_stream_2;
    324 	leb_t->abs_wrs_4 = leb_bus_space_write_region_stream_4;
    325 	leb_t->abs_wrs_8 = leb_bus_space_write_region_stream_8;
    326 	leb_t->abs_sm_1  = leb_bus_space_set_multi_1;
    327 	leb_t->abs_sm_2  = leb_bus_space_set_multi_2;
    328 	leb_t->abs_sm_4  = leb_bus_space_set_multi_4;
    329 	leb_t->abs_sm_8  = leb_bus_space_set_multi_8;
    330 	leb_t->abs_sr_1  = leb_bus_space_set_region_1;
    331 	leb_t->abs_sr_2  = leb_bus_space_set_region_2;
    332 	leb_t->abs_sr_4  = leb_bus_space_set_region_4;
    333 	leb_t->abs_sr_8  = leb_bus_space_set_region_8;
    334 
    335 	return leb_t;
    336 }
    337 
    338 
    339 /*
    340  * The various access functions
    341  */
    342 
    343 /*
    344  *	int bus_space_peek_N(bus_space_tag_t tag,
    345  *		bus_space_handle_t sh, bus_size_t offset);
    346  *
    347  * Check if the address is suitable for reading N-byte quantities.
    348  */
    349 static int
    350 leb_bus_space_peek_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
    351 {
    352 
    353 	return !badbaddr((void *)(h + o), 1);
    354 }
    355 
    356 static int
    357 leb_bus_space_peek_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
    358 {
    359 
    360 	return !badbaddr((void *)(h + o), 2);
    361 }
    362 
    363 static int
    364 leb_bus_space_peek_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
    365 {
    366 
    367 	return !badbaddr((void *)(h + o), 4);
    368 }
    369 
    370 static int
    371 leb_bus_space_peek_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
    372 {
    373 
    374 	return !badbaddr((void *)(h + o), 8);
    375 }
    376 
    377 /*
    378  *	uintX_t bus_space_read_N(bus_space_tag_t tag,
    379  *		bus_space_handle_t bsh, bus_size_t offset);
    380  *
    381  * Return an 1, 2, 4, or 8 byte value read from the bus_space described
    382  * by tag/handle at `offset'. The value is converted to host-endian.
    383  */
    384 static uint8_t
    385 leb_bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
    386 {
    387 
    388 	return __read_1(h, o);
    389 }
    390 
    391 static uint16_t
    392 leb_bus_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
    393 {
    394 
    395 	return __read_2(h, o);
    396 }
    397 
    398 static uint32_t
    399 leb_bus_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
    400 {
    401 
    402 	return __read_4(h, o);
    403 }
    404 
    405 static uint64_t
    406 leb_bus_space_read_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
    407 {
    408 
    409 	return __read_8(h, o);
    410 }
    411 
    412 /*
    413  *	uintX_t bus_space_write_N(bus_space_tag_t tag,
    414  *		bus_space_handle_t bsh, bus_size_t offset, uintX_t val);
    415  *
    416  * Write an 1, 2, 4, or 8 byte value to the bus_space described by tag/handle
    417  * at `offset'. The value `val' is converted from host to bus endianness
    418  * before being written.
    419  */
    420 static void
    421 leb_bus_space_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
    422     uint8_t v)
    423 {
    424 
    425 	__write_1(h, o, v);
    426 }
    427 
    428 static void
    429 leb_bus_space_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
    430     uint16_t v)
    431 {
    432 
    433 	__write_2(h, o, v);
    434 }
    435 
    436 static void
    437 leb_bus_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
    438     uint32_t v)
    439 {
    440 
    441 	__write_4(h, o, v);
    442 }
    443 
    444 static void
    445 leb_bus_space_write_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
    446     uint64_t v)
    447 {
    448 
    449 	__write_8(h, o, v);
    450 }
    451 
    452 /*
    453  *	uintX_t bus_space_read_stream_N(bus_space_tag_t tag,
    454  *		bus_space_handle_t bsh, bus_size_t offset);
    455  *
    456  * Return an 1, 2, 4, or 8 byte value read from the bus_space described
    457  * by tag/handle at `offset'. No endian conversion is done.
    458  */
    459 static uint16_t
    460 leb_bus_space_read_stream_2(bus_space_tag_t t, bus_space_handle_t h,
    461     bus_size_t o)
    462 {
    463 
    464 	return *((volatile uint16_t *)(h + o));
    465 }
    466 
    467 static uint32_t
    468 leb_bus_space_read_stream_4(bus_space_tag_t t, bus_space_handle_t h,
    469     bus_size_t o)
    470 {
    471 
    472 	return *((volatile uint32_t *)(h + o));
    473 }
    474 
    475 static uint64_t
    476 leb_bus_space_read_stream_8(bus_space_tag_t t, bus_space_handle_t h,
    477     bus_size_t o)
    478 {
    479 
    480 	return *((volatile uint64_t *)(h + o));
    481 }
    482 
    483 /*
    484  *	uintX_t bus_space_write_stream_N(bus_space_tag_t tag,
    485  *		bus_space_handle_t bsh, bus_size_t offset, uintX_t val);
    486  *
    487  * Write an 1, 2, 4, or 8 byte value to the bus_space described by tag/handle
    488  * at `offset'. No endian conversion is done.
    489  */
    490 static void
    491 leb_bus_space_write_stream_2(bus_space_tag_t t, bus_space_handle_t h,
    492     bus_size_t o, uint16_t v)
    493 {
    494 
    495 	*((volatile uint16_t *)(h + o)) = v;
    496 }
    497 
    498 static void
    499 leb_bus_space_write_stream_4(bus_space_tag_t t, bus_space_handle_t h,
    500     bus_size_t o, uint32_t v)
    501 {
    502 
    503 	*((volatile uint32_t *)(h + o)) = v;
    504 }
    505 
    506 static void
    507 leb_bus_space_write_stream_8(bus_space_tag_t t, bus_space_handle_t h,
    508     bus_size_t o, uint64_t v)
    509 {
    510 
    511 	*((volatile uint64_t *)(h + o)) = v;
    512 }
    513 
    514 /*
    515  *	void bus_space_read_multi_N(bus_space_tag_t tag,
    516  *		bus_space_handle_t bsh, bus_size_t offset, uintX_t *address,
    517  *		bus_size_t count);
    518  *
    519  * Read 'count' 1, 2, 4, or 8 byte values from the bus_space described by
    520  * tag/handle at `offset' and store them in the address range starting at
    521  * 'address'. The values are converted to CPU endian order before being
    522  * being stored.
    523  */
    524 static void
    525 leb_bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t h,
    526     bus_size_t o, uint8_t *a, bus_size_t c)
    527 {
    528 
    529 	for (; c; a++, c--)
    530 		*a = __read_1(h, o);
    531 }
    532 static void
    533 leb_bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h,
    534     bus_size_t o, uint16_t *a, bus_size_t c)
    535 {
    536 
    537 	for (; c; a++, c--)
    538 		*a = __read_2(h, o);
    539 }
    540 
    541 static void
    542 leb_bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t h,
    543     bus_size_t o, uint32_t *a, bus_size_t c)
    544 {
    545 
    546 	for (; c; a++, c--)
    547 		*a = __read_4(h, o);
    548 }
    549 
    550 static void
    551 leb_bus_space_read_multi_8(bus_space_tag_t t, bus_space_handle_t h,
    552     bus_size_t o, uint64_t *a, bus_size_t c)
    553 {
    554 
    555 	for (; c; a++, c--)
    556 		*a = __read_8(h, o);
    557 }
    558 
    559 /*
    560  *	void bus_space_write_multi_N(bus_space_tag_t tag,
    561  *		bus_space_handle_t bsh, bus_size_t offset,
    562  *		const uintX_t *address, bus_size_t count);
    563  *
    564  * Write 'count' 1, 2, 4, or 8 byte values from the address range starting
    565  * at 'address' to the bus_space described by tag/handle at `offset'.
    566  * The values are converted to bus endian order before being written to
    567  * the bus.
    568  */
    569 static void
    570 leb_bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t h,
    571     bus_size_t o, const uint8_t *a, bus_size_t c)
    572 {
    573 
    574 	for (; c; a++, c--)
    575 		__write_1(h, o, *a);
    576 }
    577 
    578 static void
    579 leb_bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t h,
    580     bus_size_t o, const uint16_t *a, bus_size_t c)
    581 {
    582 
    583 	for (; c; a++, c--)
    584 		__write_2(h, o, *a);
    585 }
    586 
    587 static void
    588 leb_bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t h,
    589     bus_size_t o, const uint32_t *a, bus_size_t c)
    590 {
    591 
    592 	for (; c; a++, c--)
    593 		__write_4(h, o, *a);
    594 }
    595 
    596 static void
    597 leb_bus_space_write_multi_8(bus_space_tag_t t, bus_space_handle_t h,
    598     bus_size_t o, const uint64_t *a, bus_size_t c)
    599 {
    600 
    601 	for (; c; a++, c--)
    602 		__write_8(h, o, *a);
    603 }
    604 
    605 /*
    606  *	void bus_space_read_multi_stream_N(bus_space_tag_t tag,
    607  *		bus_space_handle_t bsh, bus_size_t offset, uintX_t *address,
    608  *		bus_size_t count);
    609  *
    610  * Read 'count' 1, 2, 4, or 8 byte values from the bus_space described by
    611  * tag/handle at `offset' and store them in the address range starting at
    612  * 'address'. No endian conversion is being done.
    613  */
    614 static void
    615 leb_bus_space_read_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h,
    616     bus_size_t o, uint16_t *a, bus_size_t c)
    617 {
    618 
    619 	for (; c; a++, c--)
    620 		*a = *((volatile uint16_t *)(h + o));
    621 }
    622 
    623 static void
    624 leb_bus_space_read_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h,
    625     bus_size_t o, uint32_t *a, bus_size_t c)
    626 {
    627 
    628 	for (; c; a++, c--)
    629 		*a = *((volatile uint32_t *)(h + o));
    630 }
    631 
    632 static void
    633 leb_bus_space_read_multi_stream_8(bus_space_tag_t t, bus_space_handle_t h,
    634     bus_size_t o, uint64_t *a, bus_size_t c)
    635 {
    636 
    637 	for (; c; a++, c--)
    638 		*a = *((volatile uint64_t *)(h + o));
    639 }
    640 
    641 /*
    642  *	void bus_space_write_multi_stream_N(bus_space_tag_t tag,
    643  *		bus_space_handle_t bsh, bus_size_t offset,
    644  *		const uintX_t *address, bus_size_t count);
    645  *
    646  * Write 'count' 1, 2, 4, or 8 byte values from the address range starting
    647  * at 'address' to the bus_space described by tag/handle at `offset'.
    648  * No endian conversion is being done.
    649  */
    650 static void
    651 leb_bus_space_write_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h,
    652     bus_size_t o, const uint16_t *a, bus_size_t c)
    653 {
    654 
    655 	for (; c; a++, c--)
    656 		*((volatile uint16_t *)(h + o)) = *a;
    657 }
    658 
    659 static void
    660 leb_bus_space_write_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h,
    661     bus_size_t o, const uint32_t *a, bus_size_t c)
    662 {
    663 
    664 	for (; c; a++, c--)
    665 		*((volatile uint32_t *)(h + o)) = *a;
    666 }
    667 
    668 static void
    669 leb_bus_space_write_multi_stream_8(bus_space_tag_t t, bus_space_handle_t h,
    670     bus_size_t o, const uint64_t *a, bus_size_t c)
    671 {
    672 
    673 	for (; c; a++, c--)
    674 		*((volatile uint64_t *)(h + o)) = *a;
    675 }
    676 
    677 /*
    678  *	void bus_space_read_region_N(bus_space_tag_t tag,
    679  *		bus_space_handle_t bsh, bus_size_t offset,
    680  *		uintN_t *addr, bus_size_t count);
    681  *
    682  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
    683  * described by tag/handle and starting at `offset' and copy into
    684  * buffer provided.
    685  */
    686 static void
    687 leb_bus_space_read_region_1(bus_space_tag_t t, bus_space_handle_t h,
    688     bus_size_t o, uint8_t *a, bus_size_t c)
    689 {
    690 
    691 	for (; c; a++, o++, c--)
    692 		*a = __read_1(h, o);
    693 }
    694 
    695 static void
    696 leb_bus_space_read_region_2(bus_space_tag_t t, bus_space_handle_t h,
    697     bus_size_t o, uint16_t *a, bus_size_t c)
    698 {
    699 
    700 	for (; c; a++, o += 2, c--)
    701 		*a = __read_2(h, o);
    702 }
    703 
    704 static void
    705 leb_bus_space_read_region_4(bus_space_tag_t t, bus_space_handle_t h,
    706     bus_size_t o, uint32_t *a, bus_size_t c)
    707 {
    708 
    709 	for (; c; a++, o += 4, c--)
    710 		*a = __read_4(h, o);
    711 }
    712 
    713 static void
    714 leb_bus_space_read_region_8(bus_space_tag_t t, bus_space_handle_t h,
    715     bus_size_t o, uint64_t *a, bus_size_t c)
    716 {
    717 
    718 	for (; c; a++, o += 8, c--)
    719 		*a = __read_8(h, o);
    720 }
    721 
    722 /*
    723  *	void bus_space_write_region_N(bus_space_tag_t tag,
    724  *		bus_space_handle_t bsh, bus_size_t offset,
    725  *		uintN_t *addr, bus_size_t count);
    726  *
    727  * Copy `count' 1, 2, 4, or 8 byte quantities from the buffer provided
    728  * into the bus space described by tag/handle and starting at `offset'.
    729  */
    730 static void
    731 leb_bus_space_write_region_1(bus_space_tag_t t, bus_space_handle_t h,
    732     bus_size_t o, const uint8_t *a, bus_size_t c)
    733 {
    734 
    735 	for (; c; a++, o++, c--)
    736 		__write_1(h, o, *a);
    737 }
    738 
    739 static void
    740 leb_bus_space_write_region_2(bus_space_tag_t t, bus_space_handle_t h,
    741     bus_size_t o, const uint16_t *a, bus_size_t c)
    742 {
    743 
    744 	for (; c; a++, o += 2, c--)
    745 		__write_2(h, o, *a);
    746 }
    747 
    748 static void
    749 leb_bus_space_write_region_4(bus_space_tag_t t, bus_space_handle_t h,
    750     bus_size_t o, const uint32_t *a, bus_size_t c)
    751 {
    752 
    753 	for (; c; a++, o += 4, c--)
    754 		__write_4(h, o, *a);
    755 }
    756 
    757 static void
    758 leb_bus_space_write_region_8(bus_space_tag_t t, bus_space_handle_t h,
    759     bus_size_t o, const uint64_t *a, bus_size_t c)
    760 {
    761 
    762 	for (; c; a++, o += 8, c--)
    763 		__write_8(h, o, *a);
    764 }
    765 
    766 /*
    767  *	void bus_space_read_region_stream_N(bus_space_tag_t tag,
    768  *		bus_space_handle_t bsh, bus_size_t offset,
    769  *		uintN_t *addr, bus_size_t count);
    770  *
    771  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
    772  * described by tag/handle and starting at `offset' and copy into
    773  * buffer provided.
    774  * No endian conversion is being done.
    775  */
    776 static void
    777 leb_bus_space_read_region_stream_2(bus_space_tag_t t, bus_space_handle_t h,
    778     bus_size_t o, uint16_t *a, bus_size_t c)
    779 {
    780 
    781 	for (; c; a++, o += 2, c--)
    782 		*a = *(volatile uint16_t *)(h + o);
    783 }
    784 
    785 static void
    786 leb_bus_space_read_region_stream_4(bus_space_tag_t t, bus_space_handle_t h,
    787     bus_size_t o, uint32_t *a, bus_size_t c)
    788 {
    789 
    790 	for (; c; a++, o += 4, c--)
    791 		*a = *(volatile uint32_t *)(h + o);
    792 }
    793 
    794 static void
    795 leb_bus_space_read_region_stream_8(bus_space_tag_t t, bus_space_handle_t h,
    796     bus_size_t o, uint64_t *a, bus_size_t c)
    797 {
    798 
    799 	for (; c; a++, o += 8, c--)
    800 		*a = *(volatile uint64_t *)(h + o);
    801 }
    802 
    803 /*
    804  *	void bus_space_write_region_stream_N(bus_space_tag_t tag,
    805  *		bus_space_handle_t bsh, bus_size_t offset,
    806  *		uintN_t *addr, bus_size_t count);
    807  *
    808  * Copy `count' 1, 2, 4, or 8 byte quantities from the buffer provided
    809  * into the bus space described by tag/handle and starting at `offset'.
    810  * No endian conversion is being done.
    811  */
    812 static void
    813 leb_bus_space_write_region_stream_2(bus_space_tag_t t, bus_space_handle_t h,
    814     bus_size_t o, const uint16_t *a, bus_size_t c)
    815 {
    816 
    817 	for (; c; a++, o += 2, c--)
    818 		*((volatile uint16_t *)(h + o)) = *a;
    819 }
    820 
    821 static void
    822 leb_bus_space_write_region_stream_4(bus_space_tag_t t, bus_space_handle_t h,
    823     bus_size_t o, const uint32_t *a, bus_size_t c)
    824 {
    825 
    826 	for (; c; a++, o += 4, c--)
    827 		*((volatile uint32_t *)(h + o)) = *a;
    828 }
    829 
    830 static void
    831 leb_bus_space_write_region_stream_8(bus_space_tag_t t, bus_space_handle_t h,
    832     bus_size_t o, const uint64_t *a, bus_size_t c)
    833 {
    834 
    835 	for (; c; a++, o += 8, c--)
    836 		*((volatile uint64_t *)(h + o)) = *a;
    837 }
    838 
    839 /*
    840  *	void bus_space_set_multi_N(bus_space_tag_t tag,
    841  *		bus_space_handle_t bsh, bus_size_t offset, uintN_t val,
    842  *		bus_size_t count);
    843  *
    844  * Write the 1, 2, 4, or 8 byte value `val' to bus space described
    845  * by tag/handle/offset `count' times.
    846  */
    847 
    848 static void
    849 leb_bus_space_set_multi_1(bus_space_tag_t t, bus_space_handle_t h,
    850     bus_size_t o, uint8_t v, bus_size_t c)
    851 {
    852 
    853 	for (; c; c--)
    854 		__write_1(h, o, v);
    855 }
    856 
    857 static void
    858 leb_bus_space_set_multi_2(bus_space_tag_t t, bus_space_handle_t h,
    859     bus_size_t o, uint16_t v, bus_size_t c)
    860 {
    861 
    862 	v = swap16(v);
    863 	for (; c; c--)
    864 		*((volatile uint16_t *)(h + o)) = v;
    865 }
    866 
    867 static void
    868 leb_bus_space_set_multi_4(bus_space_tag_t t, bus_space_handle_t h,
    869     bus_size_t o, uint32_t v, bus_size_t c)
    870 {
    871 
    872 	v = swap32(v);
    873 	for (; c; c--)
    874 		*((volatile uint32_t *)(h + o)) = v;
    875 }
    876 
    877 static void
    878 leb_bus_space_set_multi_8(bus_space_tag_t t, bus_space_handle_t h,
    879     bus_size_t o, uint64_t v, bus_size_t c)
    880 {
    881 
    882 	v = bswap64(v);
    883 	for (; c; c--)
    884 		*((volatile uint64_t *)(h + o)) = v;
    885 }
    886 
    887 /*
    888  *	void bus_space_set_region_N(bus_space_tag_t tag,
    889  *		bus_space_handle_t bsh, bus_size_t offset, uintN_t val,
    890  *		bus_size_t count);
    891  *
    892  * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
    893  * by tag/handle starting at `offset'.
    894  */
    895 static void
    896 leb_bus_space_set_region_1(bus_space_tag_t t, bus_space_handle_t h,
    897     bus_size_t o, uint8_t v, bus_size_t c)
    898 {
    899 
    900 	for (; c; o++, c--)
    901 		__write_1(h, o, v);
    902 }
    903 
    904 static void
    905 leb_bus_space_set_region_2(bus_space_tag_t t, bus_space_handle_t h,
    906     bus_size_t o, uint16_t v, bus_size_t c)
    907 {
    908 
    909 	v = swap16(v);
    910 	for (; c; o += 2, c--)
    911 		*((volatile uint16_t *)(h + o)) = v;
    912 }
    913 
    914 static void
    915 leb_bus_space_set_region_4(bus_space_tag_t t, bus_space_handle_t h,
    916     bus_size_t o, uint32_t v, bus_size_t c)
    917 {
    918 
    919 	v = swap32(v);
    920 	for (; c; o += 4, c--)
    921 		*((volatile uint32_t *)(h + o)) = v;
    922 }
    923 
    924 static void
    925 leb_bus_space_set_region_8(bus_space_tag_t t, bus_space_handle_t h,
    926     bus_size_t o, uint64_t v, bus_size_t c)
    927 {
    928 
    929 	v = bswap64(v);
    930 	for (; c; o += 8, c--)
    931 		*((volatile uint64_t *)(h + o)) = v;
    932 }
    933