xref: /netbsd/sys/arch/atari/atari/le_bus.c (revision 60e2ec70)
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 
swap16(uint16_t v)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 
swap32(uint32_t v)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
leb_alloc_bus_space_tag(bus_space_tag_t storage)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
leb_bus_space_peek_1(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o)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
leb_bus_space_peek_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o)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
leb_bus_space_peek_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o)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
leb_bus_space_peek_8(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o)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
leb_bus_space_read_1(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o)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
leb_bus_space_read_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o)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
leb_bus_space_read_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o)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
leb_bus_space_read_8(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o)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
leb_bus_space_write_1(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint8_t v)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
leb_bus_space_write_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint16_t v)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
leb_bus_space_write_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint32_t v)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
leb_bus_space_write_8(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint64_t v)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
leb_bus_space_read_stream_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o)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
leb_bus_space_read_stream_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o)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
leb_bus_space_read_stream_8(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o)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
leb_bus_space_write_stream_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint16_t v)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
leb_bus_space_write_stream_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint32_t v)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
leb_bus_space_write_stream_8(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint64_t v)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
leb_bus_space_read_multi_1(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint8_t * a,bus_size_t c)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
leb_bus_space_read_multi_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint16_t * a,bus_size_t c)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
leb_bus_space_read_multi_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint32_t * a,bus_size_t c)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
leb_bus_space_read_multi_8(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint64_t * a,bus_size_t c)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
leb_bus_space_write_multi_1(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint8_t * a,bus_size_t c)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
leb_bus_space_write_multi_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint16_t * a,bus_size_t c)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
leb_bus_space_write_multi_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint32_t * a,bus_size_t c)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
leb_bus_space_write_multi_8(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint64_t * a,bus_size_t c)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
leb_bus_space_read_multi_stream_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint16_t * a,bus_size_t c)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
leb_bus_space_read_multi_stream_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint32_t * a,bus_size_t c)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
leb_bus_space_read_multi_stream_8(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint64_t * a,bus_size_t c)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
leb_bus_space_write_multi_stream_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint16_t * a,bus_size_t c)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
leb_bus_space_write_multi_stream_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint32_t * a,bus_size_t c)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
leb_bus_space_write_multi_stream_8(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint64_t * a,bus_size_t c)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
leb_bus_space_read_region_1(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint8_t * a,bus_size_t c)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
leb_bus_space_read_region_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint16_t * a,bus_size_t c)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
leb_bus_space_read_region_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint32_t * a,bus_size_t c)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
leb_bus_space_read_region_8(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint64_t * a,bus_size_t c)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
leb_bus_space_write_region_1(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint8_t * a,bus_size_t c)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
leb_bus_space_write_region_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint16_t * a,bus_size_t c)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
leb_bus_space_write_region_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint32_t * a,bus_size_t c)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
leb_bus_space_write_region_8(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint64_t * a,bus_size_t c)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
leb_bus_space_read_region_stream_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint16_t * a,bus_size_t c)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
leb_bus_space_read_region_stream_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint32_t * a,bus_size_t c)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
leb_bus_space_read_region_stream_8(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint64_t * a,bus_size_t c)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
leb_bus_space_write_region_stream_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint16_t * a,bus_size_t c)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
leb_bus_space_write_region_stream_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint32_t * a,bus_size_t c)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
leb_bus_space_write_region_stream_8(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,const uint64_t * a,bus_size_t c)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
leb_bus_space_set_multi_1(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint8_t v,bus_size_t c)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
leb_bus_space_set_multi_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint16_t v,bus_size_t c)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
leb_bus_space_set_multi_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint32_t v,bus_size_t c)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
leb_bus_space_set_multi_8(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint64_t v,bus_size_t c)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
leb_bus_space_set_region_1(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint8_t v,bus_size_t c)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
leb_bus_space_set_region_2(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint16_t v,bus_size_t c)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
leb_bus_space_set_region_4(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint32_t v,bus_size_t c)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
leb_bus_space_set_region_8(bus_space_tag_t t,bus_space_handle_t h,bus_size_t o,uint64_t v,bus_size_t c)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