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