xref: /netbsd/sys/arch/atari/atari/le_bus.c (revision 6550d01e)
1 /*	$NetBSD: le_bus.c,v 1.17 2009/03/18 16:00:10 cegger 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.17 2009/03/18 16:00:10 cegger Exp $");
34 
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/malloc.h>
39 #include <sys/bswap.h>
40 #include <machine/cpu.h>
41 #include <machine/bus.h>
42 
43 /*
44  * This file contains the common functions for using a litte 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 malloc() can't be used).
266 	 */
267 	if (storage != NULL)
268 		leb_t = storage;
269 	else {
270 		if ((leb_t = malloc(sizeof(*leb_t), M_TEMP, M_NOWAIT)) == NULL)
271 		return NULL;
272 	}
273 	memset(leb_t, 0, sizeof(*leb_t));
274 
275 	leb_t->abs_p_1   = leb_bus_space_peek_1;
276 	leb_t->abs_p_2   = leb_bus_space_peek_2;
277 	leb_t->abs_p_4   = leb_bus_space_peek_4;
278 	leb_t->abs_p_8   = leb_bus_space_peek_8;
279 	leb_t->abs_r_1   = leb_bus_space_read_1;
280 	leb_t->abs_r_2   = leb_bus_space_read_2;
281 	leb_t->abs_r_4   = leb_bus_space_read_4;
282 	leb_t->abs_r_8   = leb_bus_space_read_8;
283 	leb_t->abs_rs_1  = leb_bus_space_read_1;
284 	leb_t->abs_rs_2  = leb_bus_space_read_stream_2;
285 	leb_t->abs_rs_4  = leb_bus_space_read_stream_4;
286 	leb_t->abs_rs_8  = leb_bus_space_read_stream_8;
287 	leb_t->abs_rm_1  = leb_bus_space_read_multi_1;
288 	leb_t->abs_rm_2  = leb_bus_space_read_multi_2;
289 	leb_t->abs_rm_4  = leb_bus_space_read_multi_4;
290 	leb_t->abs_rm_8  = leb_bus_space_read_multi_8;
291 	leb_t->abs_rms_1 = leb_bus_space_read_multi_1;
292 	leb_t->abs_rms_2 = leb_bus_space_read_multi_stream_2;
293 	leb_t->abs_rms_4 = leb_bus_space_read_multi_stream_4;
294 	leb_t->abs_rms_8 = leb_bus_space_read_multi_stream_8;
295 	leb_t->abs_rr_1  = leb_bus_space_read_region_1;
296 	leb_t->abs_rr_2  = leb_bus_space_read_region_2;
297 	leb_t->abs_rr_4  = leb_bus_space_read_region_4;
298 	leb_t->abs_rr_8  = leb_bus_space_read_region_8;
299 	leb_t->abs_rrs_1 = leb_bus_space_read_region_1;
300 	leb_t->abs_rrs_2 = leb_bus_space_read_region_stream_2;
301 	leb_t->abs_rrs_4 = leb_bus_space_read_region_stream_4;
302 	leb_t->abs_rrs_8 = leb_bus_space_read_region_stream_8;
303 	leb_t->abs_w_1   = leb_bus_space_write_1;
304 	leb_t->abs_w_2   = leb_bus_space_write_2;
305 	leb_t->abs_w_4   = leb_bus_space_write_4;
306 	leb_t->abs_w_8   = leb_bus_space_write_8;
307 	leb_t->abs_ws_1  = leb_bus_space_write_1;
308 	leb_t->abs_ws_2  = leb_bus_space_write_stream_2;
309 	leb_t->abs_ws_4  = leb_bus_space_write_stream_4;
310 	leb_t->abs_ws_8  = leb_bus_space_write_stream_8;
311 	leb_t->abs_wm_1  = leb_bus_space_write_multi_1;
312 	leb_t->abs_wm_2  = leb_bus_space_write_multi_2;
313 	leb_t->abs_wm_4  = leb_bus_space_write_multi_4;
314 	leb_t->abs_wm_8  = leb_bus_space_write_multi_8;
315 	leb_t->abs_wms_1 = leb_bus_space_write_multi_1;
316 	leb_t->abs_wms_2 = leb_bus_space_write_multi_stream_2;
317 	leb_t->abs_wms_4 = leb_bus_space_write_multi_stream_4;
318 	leb_t->abs_wms_8 = leb_bus_space_write_multi_stream_8;
319 	leb_t->abs_wr_1  = leb_bus_space_write_region_1;
320 	leb_t->abs_wr_2  = leb_bus_space_write_region_2;
321 	leb_t->abs_wr_4  = leb_bus_space_write_region_4;
322 	leb_t->abs_wr_8  = leb_bus_space_write_region_8;
323 	leb_t->abs_wrs_1 = leb_bus_space_write_region_1;
324 	leb_t->abs_wrs_2 = leb_bus_space_write_region_stream_2;
325 	leb_t->abs_wrs_4 = leb_bus_space_write_region_stream_4;
326 	leb_t->abs_wrs_8 = leb_bus_space_write_region_stream_8;
327 	leb_t->abs_sm_1  = leb_bus_space_set_multi_1;
328 	leb_t->abs_sm_2  = leb_bus_space_set_multi_2;
329 	leb_t->abs_sm_4  = leb_bus_space_set_multi_4;
330 	leb_t->abs_sm_8  = leb_bus_space_set_multi_8;
331 	leb_t->abs_sr_1  = leb_bus_space_set_region_1;
332 	leb_t->abs_sr_2  = leb_bus_space_set_region_2;
333 	leb_t->abs_sr_4  = leb_bus_space_set_region_4;
334 	leb_t->abs_sr_8  = leb_bus_space_set_region_8;
335 
336 	return leb_t;
337 }
338 
339 
340 /*
341  * The various access functions
342  */
343 
344 /*
345  *	int bus_space_peek_N(bus_space_tag_t tag,
346  *		bus_space_handle_t sh, bus_size_t offset);
347  *
348  * Check if the address is suitable for reading N-byte quantities.
349  */
350 static int
351 leb_bus_space_peek_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
352 {
353 
354 	return !badbaddr((void *)(h + o), 1);
355 }
356 
357 static int
358 leb_bus_space_peek_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
359 {
360 
361 	return !badbaddr((void *)(h + o), 2);
362 }
363 
364 static int
365 leb_bus_space_peek_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
366 {
367 
368 	return !badbaddr((void *)(h + o), 4);
369 }
370 
371 static int
372 leb_bus_space_peek_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
373 {
374 
375 	return !badbaddr((void *)(h + o), 8);
376 }
377 
378 /*
379  *	uintX_t bus_space_read_N(bus_space_tag_t tag,
380  *		bus_space_handle_t bsh, bus_size_t offset);
381  *
382  * Return an 1, 2, 4, or 8 byte value read from the bus_space described
383  * by tag/handle at `offset'. The value is converted to host-endian.
384  */
385 static uint8_t
386 leb_bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
387 {
388 
389 	return __read_1(h, o);
390 }
391 
392 static uint16_t
393 leb_bus_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
394 {
395 
396 	return __read_2(h, o);
397 }
398 
399 static uint32_t
400 leb_bus_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
401 {
402 
403 	return __read_4(h, o);
404 }
405 
406 static uint64_t
407 leb_bus_space_read_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
408 {
409 
410 	return __read_8(h, o);
411 }
412 
413 /*
414  *	uintX_t bus_space_write_N(bus_space_tag_t tag,
415  *		bus_space_handle_t bsh, bus_size_t offset, uintX_t val);
416  *
417  * Write an 1, 2, 4, or 8 byte value to the bus_space described by tag/handle
418  * at `offset'. The value `val' is converted from host to bus endianness
419  * before being written.
420  */
421 static void
422 leb_bus_space_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
423     uint8_t v)
424 {
425 
426 	__write_1(h, o, v);
427 }
428 
429 static void
430 leb_bus_space_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
431     uint16_t v)
432 {
433 
434 	__write_2(h, o, v);
435 }
436 
437 static void
438 leb_bus_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
439     uint32_t v)
440 {
441 
442 	__write_4(h, o, v);
443 }
444 
445 static void
446 leb_bus_space_write_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
447     uint64_t v)
448 {
449 
450 	__write_8(h, o, v);
451 }
452 
453 /*
454  *	uintX_t bus_space_read_stream_N(bus_space_tag_t tag,
455  *		bus_space_handle_t bsh, bus_size_t offset);
456  *
457  * Return an 1, 2, 4, or 8 byte value read from the bus_space described
458  * by tag/handle at `offset'. No endian conversion is done.
459  */
460 static uint16_t
461 leb_bus_space_read_stream_2(bus_space_tag_t t, bus_space_handle_t h,
462     bus_size_t o)
463 {
464 
465 	return *((volatile uint16_t *)(h + o));
466 }
467 
468 static uint32_t
469 leb_bus_space_read_stream_4(bus_space_tag_t t, bus_space_handle_t h,
470     bus_size_t o)
471 {
472 
473 	return *((volatile uint32_t *)(h + o));
474 }
475 
476 static uint64_t
477 leb_bus_space_read_stream_8(bus_space_tag_t t, bus_space_handle_t h,
478     bus_size_t o)
479 {
480 
481 	return *((volatile uint64_t *)(h + o));
482 }
483 
484 /*
485  *	uintX_t bus_space_write_stream_N(bus_space_tag_t tag,
486  *		bus_space_handle_t bsh, bus_size_t offset, uintX_t val);
487  *
488  * Write an 1, 2, 4, or 8 byte value to the bus_space described by tag/handle
489  * at `offset'. No endian conversion is done.
490  */
491 static void
492 leb_bus_space_write_stream_2(bus_space_tag_t t, bus_space_handle_t h,
493     bus_size_t o, uint16_t v)
494 {
495 
496 	*((volatile uint16_t *)(h + o)) = v;
497 }
498 
499 static void
500 leb_bus_space_write_stream_4(bus_space_tag_t t, bus_space_handle_t h,
501     bus_size_t o, uint32_t v)
502 {
503 
504 	*((volatile uint32_t *)(h + o)) = v;
505 }
506 
507 static void
508 leb_bus_space_write_stream_8(bus_space_tag_t t, bus_space_handle_t h,
509     bus_size_t o, uint64_t v)
510 {
511 
512 	*((volatile uint64_t *)(h + o)) = v;
513 }
514 
515 /*
516  *	void bus_space_read_multi_N(bus_space_tag_t tag,
517  *		bus_space_handle_t bsh, bus_size_t offset, uintX_t *address,
518  *	 	bus_size_t count);
519  *
520  * Read 'count' 1, 2, 4, or 8 byte values from the bus_space described by
521  * tag/handle at `offset' and store them in the address range starting at
522  * 'address'. The values are converted to CPU endian order before being
523  * being stored.
524  */
525 static void
526 leb_bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t h,
527     bus_size_t o, uint8_t *a, bus_size_t c)
528 {
529 
530 	for (; c; a++, c--)
531 		*a = __read_1(h, o);
532 }
533 static void
534 leb_bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h,
535     bus_size_t o, uint16_t *a, bus_size_t c)
536 {
537 
538 	for (; c; a++, c--)
539 		*a = __read_2(h, o);
540 }
541 
542 static void
543 leb_bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t h,
544     bus_size_t o, uint32_t *a, bus_size_t c)
545 {
546 
547 	for (; c; a++, c--)
548 		*a = __read_4(h, o);
549 }
550 
551 static void
552 leb_bus_space_read_multi_8(bus_space_tag_t t, bus_space_handle_t h,
553     bus_size_t o, uint64_t *a, bus_size_t c)
554 {
555 
556 	for (; c; a++, c--)
557 		*a = __read_8(h, o);
558 }
559 
560 /*
561  *	void bus_space_write_multi_N(bus_space_tag_t tag,
562  *		bus_space_handle_t bsh, bus_size_t offset,
563  *		const uintX_t *address, bus_size_t count);
564  *
565  * Write 'count' 1, 2, 4, or 8 byte values from the address range starting
566  * at 'address' to the bus_space described by tag/handle at `offset'.
567  * The values are converted to bus endian order before being written to
568  * the bus.
569  */
570 static void
571 leb_bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t h,
572     bus_size_t o, const uint8_t *a, bus_size_t c)
573 {
574 
575 	for (; c; a++, c--)
576 		__write_1(h, o, *a);
577 }
578 
579 static void
580 leb_bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t h,
581     bus_size_t o, const uint16_t *a, bus_size_t c)
582 {
583 
584 	for (; c; a++, c--)
585 		__write_2(h, o, *a);
586 }
587 
588 static void
589 leb_bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t h,
590     bus_size_t o, const uint32_t *a, bus_size_t c)
591 {
592 
593 	for (; c; a++, c--)
594 		__write_4(h, o, *a);
595 }
596 
597 static void
598 leb_bus_space_write_multi_8(bus_space_tag_t t, bus_space_handle_t h,
599     bus_size_t o, const uint64_t *a, bus_size_t c)
600 {
601 
602 	for (; c; a++, c--)
603 		__write_8(h, o, *a);
604 }
605 
606 /*
607  *	void bus_space_read_multi_stream_N(bus_space_tag_t tag,
608  *		bus_space_handle_t bsh, bus_size_t offset, uintX_t *address,
609  *	 	bus_size_t count);
610  *
611  * Read 'count' 1, 2, 4, or 8 byte values from the bus_space described by
612  * tag/handle at `offset' and store them in the address range starting at
613  * 'address'. No endian conversion is being done.
614  */
615 static void
616 leb_bus_space_read_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h,
617     bus_size_t o, uint16_t *a, bus_size_t c)
618 {
619 
620 	for (; c; a++, c--)
621 		*a = *((volatile uint16_t *)(h + o));
622 }
623 
624 static void
625 leb_bus_space_read_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h,
626     bus_size_t o, uint32_t *a, bus_size_t c)
627 {
628 
629 	for (; c; a++, c--)
630 		*a = *((volatile uint32_t *)(h + o));
631 }
632 
633 static void
634 leb_bus_space_read_multi_stream_8(bus_space_tag_t t, bus_space_handle_t h,
635     bus_size_t o, uint64_t *a, bus_size_t c)
636 {
637 
638 	for (; c; a++, c--)
639 		*a = *((volatile uint64_t *)(h + o));
640 }
641 
642 /*
643  *	void bus_space_write_multi_stream_N(bus_space_tag_t tag,
644  *		bus_space_handle_t bsh, bus_size_t offset,
645  *		const uintX_t *address, bus_size_t count);
646  *
647  * Write 'count' 1, 2, 4, or 8 byte values from the address range starting
648  * at 'address' to the bus_space described by tag/handle at `offset'.
649  * No endian conversion is being done.
650  */
651 static void
652 leb_bus_space_write_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h,
653     bus_size_t o, const uint16_t *a, bus_size_t c)
654 {
655 
656 	for (; c; a++, c--)
657 		*((volatile uint16_t *)(h + o)) = *a;
658 }
659 
660 static void
661 leb_bus_space_write_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h,
662     bus_size_t o, const uint32_t *a, bus_size_t c)
663 {
664 
665 	for (; c; a++, c--)
666 		*((volatile uint32_t *)(h + o)) = *a;
667 }
668 
669 static void
670 leb_bus_space_write_multi_stream_8(bus_space_tag_t t, bus_space_handle_t h,
671     bus_size_t o, const uint64_t *a, bus_size_t c)
672 {
673 
674 	for (; c; a++, c--)
675 		*((volatile uint64_t *)(h + o)) = *a;
676 }
677 
678 /*
679  *	void bus_space_read_region_N(bus_space_tag_t tag,
680  *		bus_space_handle_t bsh, bus_size_t offset,
681  *		uintN_t *addr, bus_size_t count);
682  *
683  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
684  * described by tag/handle and starting at `offset' and copy into
685  * buffer provided.
686  */
687 static void
688 leb_bus_space_read_region_1(bus_space_tag_t t, bus_space_handle_t h,
689     bus_size_t o, uint8_t *a, bus_size_t c)
690 {
691 
692 	for (; c; a++, o++, c--)
693 		*a = __read_1(h, o);
694 }
695 
696 static void
697 leb_bus_space_read_region_2(bus_space_tag_t t, bus_space_handle_t h,
698     bus_size_t o, uint16_t *a, bus_size_t c)
699 {
700 
701 	for (; c; a++, o += 2, c--)
702 		*a = __read_2(h, o);
703 }
704 
705 static void
706 leb_bus_space_read_region_4(bus_space_tag_t t, bus_space_handle_t h,
707     bus_size_t o, uint32_t *a, bus_size_t c)
708 {
709 
710 	for (; c; a++, o += 4, c--)
711 		*a = __read_4(h, o);
712 }
713 
714 static void
715 leb_bus_space_read_region_8(bus_space_tag_t t, bus_space_handle_t h,
716     bus_size_t o, uint64_t *a, bus_size_t c)
717 {
718 
719 	for (; c; a++, o += 8, c--)
720 		*a = __read_8(h, o);
721 }
722 
723 /*
724  *	void bus_space_write_region_N(bus_space_tag_t tag,
725  *		bus_space_handle_t bsh, bus_size_t offset,
726  *		uintN_t *addr, bus_size_t count);
727  *
728  * Copy `count' 1, 2, 4, or 8 byte quantities from the buffer provided
729  * into the bus space described by tag/handle and starting at `offset'.
730  */
731 static void
732 leb_bus_space_write_region_1(bus_space_tag_t t, bus_space_handle_t h,
733     bus_size_t o, const uint8_t *a, bus_size_t c)
734 {
735 
736 	for (; c; a++, o++, c--)
737 		__write_1(h, o, *a);
738 }
739 
740 static void
741 leb_bus_space_write_region_2(bus_space_tag_t t, bus_space_handle_t h,
742     bus_size_t o, const uint16_t *a, bus_size_t c)
743 {
744 
745 	for (; c; a++, o += 2, c--)
746 		__write_2(h, o, *a);
747 }
748 
749 static void
750 leb_bus_space_write_region_4(bus_space_tag_t t, bus_space_handle_t h,
751     bus_size_t o, const uint32_t *a, bus_size_t c)
752 {
753 
754 	for (; c; a++, o += 4, c--)
755 		__write_4(h, o, *a);
756 }
757 
758 static void
759 leb_bus_space_write_region_8(bus_space_tag_t t, bus_space_handle_t h,
760     bus_size_t o, const uint64_t *a, bus_size_t c)
761 {
762 
763 	for (; c; a++, o += 8, c--)
764 		__write_8(h, o, *a);
765 }
766 
767 /*
768  *	void bus_space_read_region_stream_N(bus_space_tag_t tag,
769  *		bus_space_handle_t bsh, bus_size_t offset,
770  *		uintN_t *addr, bus_size_t count);
771  *
772  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
773  * described by tag/handle and starting at `offset' and copy into
774  * buffer provided.
775  * No endian conversion is being done.
776  */
777 static void
778 leb_bus_space_read_region_stream_2(bus_space_tag_t t, bus_space_handle_t h,
779     bus_size_t o, uint16_t *a, bus_size_t c)
780 {
781 
782 	for (; c; a++, o += 2, c--)
783 		*a = *(volatile uint16_t *)(h + o);
784 }
785 
786 static void
787 leb_bus_space_read_region_stream_4(bus_space_tag_t t, bus_space_handle_t h,
788     bus_size_t o, uint32_t *a, bus_size_t c)
789 {
790 
791 	for (; c; a++, o += 4, c--)
792 		*a = *(volatile uint32_t *)(h + o);
793 }
794 
795 static void
796 leb_bus_space_read_region_stream_8(bus_space_tag_t t, bus_space_handle_t h,
797     bus_size_t o, uint64_t *a, bus_size_t c)
798 {
799 
800 	for (; c; a++, o += 8, c--)
801 		*a = *(volatile uint64_t *)(h + o);
802 }
803 
804 /*
805  *	void bus_space_write_region_stream_N(bus_space_tag_t tag,
806  *		bus_space_handle_t bsh, bus_size_t offset,
807  *		uintN_t *addr, bus_size_t count);
808  *
809  * Copy `count' 1, 2, 4, or 8 byte quantities from the buffer provided
810  * into the bus space described by tag/handle and starting at `offset'.
811  * No endian conversion is being done.
812  */
813 static void
814 leb_bus_space_write_region_stream_2(bus_space_tag_t t, bus_space_handle_t h,
815     bus_size_t o, const uint16_t *a, bus_size_t c)
816 {
817 
818 	for (; c; a++, o += 2, c--)
819 		*((volatile uint16_t *)(h + o)) = *a;
820 }
821 
822 static void
823 leb_bus_space_write_region_stream_4(bus_space_tag_t t, bus_space_handle_t h,
824     bus_size_t o, const uint32_t *a, bus_size_t c)
825 {
826 
827 	for (; c; a++, o += 4, c--)
828 		*((volatile uint32_t *)(h + o)) = *a;
829 }
830 
831 static void
832 leb_bus_space_write_region_stream_8(bus_space_tag_t t, bus_space_handle_t h,
833     bus_size_t o, const uint64_t *a, bus_size_t c)
834 {
835 
836 	for (; c; a++, o += 8, c--)
837 		*((volatile uint64_t *)(h + o)) = *a;
838 }
839 
840 /*
841  *	void bus_space_set_multi_N(bus_space_tag_t tag,
842  *		bus_space_handle_t bsh, bus_size_t offset, uintN_t val,
843  *		bus_size_t count);
844  *
845  * Write the 1, 2, 4, or 8 byte value `val' to bus space described
846  * by tag/handle/offset `count' times.
847  */
848 
849 static void
850 leb_bus_space_set_multi_1(bus_space_tag_t t, bus_space_handle_t h,
851     bus_size_t o, uint8_t v, bus_size_t c)
852 {
853 
854 	for (; c; c--)
855 		__write_1(h, o, v);
856 }
857 
858 static void
859 leb_bus_space_set_multi_2(bus_space_tag_t t, bus_space_handle_t h,
860     bus_size_t o, uint16_t v, bus_size_t c)
861 {
862 
863 	v = swap16(v);
864 	for (; c; c--)
865 		*((volatile uint16_t *)(h + o)) = v;
866 }
867 
868 static void
869 leb_bus_space_set_multi_4(bus_space_tag_t t, bus_space_handle_t h,
870     bus_size_t o, uint32_t v, bus_size_t c)
871 {
872 
873 	v = swap32(v);
874 	for (; c; c--)
875 		*((volatile uint32_t *)(h + o)) = v;
876 }
877 
878 static void
879 leb_bus_space_set_multi_8(bus_space_tag_t t, bus_space_handle_t h,
880     bus_size_t o, uint64_t v, bus_size_t c)
881 {
882 
883 	v = bswap64(v);
884 	for (; c; c--)
885 		*((volatile uint64_t *)(h + o)) = v;
886 }
887 
888 /*
889  *	void bus_space_set_region_N(bus_space_tag_t tag,
890  *		bus_space_handle_t bsh, bus_size_t offset, uintN_t val,
891  *		bus_size_t count);
892  *
893  * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
894  * by tag/handle starting at `offset'.
895  */
896 static void
897 leb_bus_space_set_region_1(bus_space_tag_t t, bus_space_handle_t h,
898     bus_size_t o, uint8_t v, bus_size_t c)
899 {
900 
901 	for (; c; o++, c--)
902 		__write_1(h, o, v);
903 }
904 
905 static void
906 leb_bus_space_set_region_2(bus_space_tag_t t, bus_space_handle_t h,
907     bus_size_t o, uint16_t v, bus_size_t c)
908 {
909 
910 	v = swap16(v);
911 	for (; c; o += 2, c--)
912 		*((volatile uint16_t *)(h + o)) = v;
913 }
914 
915 static void
916 leb_bus_space_set_region_4(bus_space_tag_t t, bus_space_handle_t h,
917     bus_size_t o, uint32_t v, bus_size_t c)
918 {
919 
920 	v = swap32(v);
921 	for (; c; o += 4, c--)
922 		*((volatile uint32_t *)(h + o)) = v;
923 }
924 
925 static void
926 leb_bus_space_set_region_8(bus_space_tag_t t, bus_space_handle_t h,
927     bus_size_t o, uint64_t v, bus_size_t c)
928 {
929 
930 	v = bswap64(v);
931 	for (; c; o += 8, c--)
932 		*((volatile uint64_t *)(h + o)) = v;
933 }
934