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