1 /* $NetBSD: bus_space.c,v 1.35 2024/02/11 10:36:40 andvar 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 Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: bus_space.c,v 1.35 2024/02/11 10:36:40 andvar Exp $");
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/extent.h>
39 #include <sys/bus.h>
40
41 #include <uvm/uvm_extern.h>
42
43 #include <mips/cache.h>
44 #include <mips/locore.h>
45 #include <mips/pte.h>
46
47 #include <machine/bus_space_hpcmips.h>
48
49 #ifdef BUS_SPACE_DEBUG
50 #define DPRINTF(arg) printf arg
51 #else
52 #define DPRINTF(arg)
53 #endif
54
55 #define MAX_BUSSPACE_TAG 10
56
57 /* proto types */
58 bus_space_handle_t __hpcmips_cacheable(struct bus_space_tag_hpcmips*,
59 bus_addr_t, bus_size_t, int);
60 bus_space_protos(_);
61 bus_space_protos(bs_notimpl);
62
63 /* variables */
64 static struct bus_space_tag_hpcmips __bus_space[MAX_BUSSPACE_TAG];
65 static int __bus_space_index;
66 static struct bus_space_tag_hpcmips __sys_bus_space = {
67 {
68 NULL,
69 {
70 /* mapping/unmapping */
71 __bs_map,
72 __bs_unmap,
73 __bs_subregion,
74
75 /* allocation/deallocation */
76 __bs_alloc,
77 __bs_free,
78
79 /* get kernel virtual address */
80 bs_notimpl_bs_vaddr, /* there is no linear mapping */
81
82 /* Mmap bus space for user */
83 bs_notimpl_bs_mmap,
84
85 /* barrier */
86 __bs_barrier,
87
88 /* probe */
89 __bs_peek,
90 __bs_poke,
91
92 /* read (single) */
93 __bs_r_1,
94 __bs_r_2,
95 __bs_r_4,
96 bs_notimpl_bs_r_8,
97
98 /* read multiple */
99 __bs_rm_1,
100 __bs_rm_2,
101 __bs_rm_4,
102 bs_notimpl_bs_rm_8,
103
104 /* read region */
105 __bs_rr_1,
106 __bs_rr_2,
107 __bs_rr_4,
108 bs_notimpl_bs_rr_8,
109
110 /* write (single) */
111 __bs_w_1,
112 __bs_w_2,
113 __bs_w_4,
114 bs_notimpl_bs_w_8,
115
116 /* write multiple */
117 __bs_wm_1,
118 __bs_wm_2,
119 __bs_wm_4,
120 bs_notimpl_bs_wm_8,
121
122 /* write region */
123 __bs_wr_1,
124 __bs_wr_2,
125 __bs_wr_4,
126 bs_notimpl_bs_wr_8,
127
128 /* set multi */
129 __bs_sm_1,
130 __bs_sm_2,
131 __bs_sm_4,
132 bs_notimpl_bs_sm_8,
133
134 /* set region */
135 __bs_sr_1,
136 __bs_sr_2,
137 __bs_sr_4,
138 bs_notimpl_bs_sr_8,
139
140 /* copy */
141 __bs_c_1,
142 __bs_c_2,
143 __bs_c_4,
144 bs_notimpl_bs_c_8,
145 },
146 },
147
148 "whole bus space", /* bus name */
149 0, /* extent base */
150 0xffffffff, /* extent size */
151 NULL, /* pointer for extent structure */
152 };
153 static bus_space_tag_t __sys_bus_space_tag = &__sys_bus_space.bst;
154
155 bus_space_tag_t
hpcmips_system_bus_space(void)156 hpcmips_system_bus_space(void)
157 {
158
159 return (__sys_bus_space_tag);
160 }
161
162 struct bus_space_tag_hpcmips *
hpcmips_system_bus_space_hpcmips(void)163 hpcmips_system_bus_space_hpcmips(void)
164 {
165
166 return (&__sys_bus_space);
167 }
168
169 struct bus_space_tag_hpcmips *
hpcmips_alloc_bus_space_tag(void)170 hpcmips_alloc_bus_space_tag(void)
171 {
172
173 if (__bus_space_index >= MAX_BUSSPACE_TAG) {
174 panic("hpcmips_internal_alloc_bus_space_tag: tag full.");
175 }
176
177 return (&__bus_space[__bus_space_index++]);
178 }
179
180 void
hpcmips_init_bus_space(struct bus_space_tag_hpcmips * t,struct bus_space_tag_hpcmips * basetag,const char * name,u_int32_t base,u_int32_t size)181 hpcmips_init_bus_space(struct bus_space_tag_hpcmips *t,
182 struct bus_space_tag_hpcmips *basetag,
183 const char *name, u_int32_t base, u_int32_t size)
184 {
185 u_int32_t pa, endpa;
186 vaddr_t va;
187
188 if (basetag != NULL)
189 memcpy(t, basetag, sizeof(struct bus_space_tag_hpcmips));
190 strncpy(t->name, name, sizeof(t->name));
191 t->name[sizeof(t->name) - 1] = '\0';
192 t->base = base;
193 t->size = size;
194
195 /*
196 * If request physical address is greater than 512MByte,
197 * mapping it to kseg2.
198 */
199 if (t->base >= 0x20000000) {
200 pa = mips_trunc_page(t->base);
201 endpa = mips_round_page(t->base + t->size);
202
203 if (!(va = uvm_km_alloc(kernel_map, endpa - pa, 0,
204 UVM_KMF_VAONLY))) {
205 panic("hpcmips_init_bus_space_extent:"
206 "can't allocate kernel virtual");
207 }
208 DPRINTF(("pa:0x%08x -> kv:0x%08x+0x%08x",
209 (unsigned int)t->base, (unsigned int)va, t->size));
210 t->base = va; /* kseg2 addr */
211
212 for (; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) {
213 pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE, 0);
214 }
215 pmap_update(pmap_kernel());
216 }
217
218 t->extent = (void*)extent_create(t->name, t->base,
219 t->base + t->size,
220 0, 0, EX_NOWAIT);
221 if (!t->extent) {
222 panic("hpcmips_init_bus_space_extent:"
223 "unable to allocate %s map", t->name);
224 }
225 }
226
227 static bool
mips_pte_cachechange(struct pmap * pmap,vaddr_t sva,vaddr_t eva,pt_entry_t * ptep,uintptr_t flags)228 mips_pte_cachechange(struct pmap *pmap, vaddr_t sva, vaddr_t eva,
229 pt_entry_t *ptep, uintptr_t flags)
230 {
231 mips_dcache_wbinv_range(sva, eva - sva);
232
233 for (; sva < eva; sva += PAGE_SIZE) {
234 pt_entry_t pte = pte_cached_change(*ptep, flags);
235 /*
236 * Update the same virtual address entry.
237 */
238 *ptep = pte;
239 tlb_update_addr(sva, KERNEL_PID, pte, 0);
240 }
241
242 return false;
243 }
244
245 bus_space_handle_t
__hpcmips_cacheable(struct bus_space_tag_hpcmips * t,bus_addr_t bpa,bus_size_t size,int cacheable)246 __hpcmips_cacheable(struct bus_space_tag_hpcmips *t, bus_addr_t bpa,
247 bus_size_t size, int cacheable)
248 {
249 if (t->base >= MIPS_KSEG2_START) {
250 const vaddr_t sva = mips_trunc_page(bpa);
251 const vaddr_t eva = mips_round_page(bpa + size);
252 pmap_pte_process(pmap_kernel(), sva, eva,
253 mips_pte_cachechange, cacheable);
254 return bpa;
255 }
256
257 return cacheable ? MIPS_PHYS_TO_KSEG0(bpa) : MIPS_PHYS_TO_KSEG1(bpa);
258 }
259
260 /* ARGSUSED */
261 int
__bs_map(bus_space_tag_t tx,bus_addr_t bpa,bus_size_t size,int flags,bus_space_handle_t * bshp)262 __bs_map(bus_space_tag_t tx, bus_addr_t bpa, bus_size_t size, int flags,
263 bus_space_handle_t *bshp)
264 {
265 struct bus_space_tag_hpcmips *t = (struct bus_space_tag_hpcmips *)tx;
266 int err;
267 int cacheable = flags & BUS_SPACE_MAP_CACHEABLE;
268
269 DPRINTF(("\tbus_space_map:%#lx(%#lx)+%#lx\n",
270 bpa, bpa + t->base, size));
271
272 if (!t->extent) { /* Before autoconfiguration, can't use extent */
273 DPRINTF(("bus_space_map: map temporary region:"
274 "0x%08lx-0x%08lx\n", bpa, bpa+size));
275 bpa += t->base;
276 } else {
277 bpa += t->base;
278 if ((err = extent_alloc_region(t->extent, bpa, size,
279 EX_NOWAIT|EX_MALLOCOK))) {
280 DPRINTF(("\tbus_space_map: "
281 "extent_alloc_region() failed\n"));
282 return (err);
283 }
284 }
285 *bshp = __hpcmips_cacheable(t, bpa, size, cacheable);
286
287 return (0);
288 }
289
290 /* ARGSUSED */
291 void
__bs_unmap(bus_space_tag_t tx,bus_space_handle_t bsh,bus_size_t size)292 __bs_unmap(bus_space_tag_t tx, bus_space_handle_t bsh, bus_size_t size)
293 {
294 struct bus_space_tag_hpcmips *t = (struct bus_space_tag_hpcmips *)tx;
295 int err;
296 u_int32_t addr;
297
298 if (!t->extent) {
299 return; /* Before autoconfiguration, can't use extent */
300 }
301
302 if (t->base < MIPS_KSEG2_START) {
303 addr = MIPS_KSEG1_TO_PHYS(bsh);
304 } else {
305 addr = bsh;
306 }
307
308 if ((err = extent_free(t->extent, addr, size, EX_NOWAIT))) {
309 DPRINTF(("warning: %#lx-%#lx of %s space lost\n",
310 bsh, bsh+size, t->name));
311 }
312 }
313
314 /* ARGSUSED */
315 int
__bs_subregion(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,bus_size_t size,bus_space_handle_t * nbshp)316 __bs_subregion(bus_space_tag_t t, bus_space_handle_t bsh,
317 bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp)
318 {
319
320 *nbshp = bsh + offset;
321
322 return (0);
323 }
324
325 /* ARGSUSED */
326 int
__bs_alloc(bus_space_tag_t tx,bus_addr_t rstart,bus_addr_t rend,bus_size_t size,bus_size_t alignment,bus_size_t boundary,int flags,bus_addr_t * bpap,bus_space_handle_t * bshp)327 __bs_alloc(bus_space_tag_t tx, bus_addr_t rstart, bus_addr_t rend,
328 bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags,
329 bus_addr_t *bpap, bus_space_handle_t *bshp)
330 {
331 struct bus_space_tag_hpcmips *t = (struct bus_space_tag_hpcmips *)tx;
332 int cacheable = flags & BUS_SPACE_MAP_CACHEABLE;
333 u_long bpa;
334 int err;
335
336 if (!t->extent)
337 panic("bus_space_alloc: no extent");
338
339 rstart += t->base;
340 rend += t->base;
341 if ((err = extent_alloc_subregion(t->extent, rstart, rend, size,
342 alignment, boundary, EX_FAST|EX_NOWAIT|EX_MALLOCOK, &bpa))) {
343 return (err);
344 }
345
346 DPRINTF(("\tbus_space_alloc:%#lx(%#lx)+%#lx\n", bpa,
347 bpa - t->base, size));
348
349 *bshp = __hpcmips_cacheable(t, bpa, size, cacheable);
350
351 if (bpap) {
352 *bpap = bpa;
353 }
354
355 return (0);
356 }
357
358 /* ARGSUSED */
359 void
__bs_free(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t size)360 __bs_free(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
361 {
362 /* bus_space_unmap() does all that we need to do. */
363 bus_space_unmap(t, bsh, size);
364 }
365
366 void
__bs_barrier(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,bus_size_t len,int flags)367 __bs_barrier(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset,
368 bus_size_t len, int flags)
369 {
370 wbflush();
371 }
372
373 int
__bs_peek(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,size_t size,void * ptr)374 __bs_peek(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset,
375 size_t size, void *ptr)
376 {
377 u_int32_t tmp;
378
379 if (badaddr((void *)(bsh + offset), size))
380 return (-1);
381
382 if (ptr == NULL)
383 ptr = &tmp;
384
385 switch(size) {
386 case 1:
387 *((u_int8_t *)ptr) = bus_space_read_1(t, bsh, offset);
388 break;
389 case 2:
390 *((u_int16_t *)ptr) = bus_space_read_2(t, bsh, offset);
391 break;
392 case 4:
393 *((u_int32_t *)ptr) = bus_space_read_4(t, bsh, offset);
394 break;
395 default:
396 panic("bus_space_peek: bad size, %d", size);
397 }
398
399 return (0);
400 }
401
402 int
__bs_poke(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,size_t size,u_int32_t val)403 __bs_poke(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset,
404 size_t size, u_int32_t val)
405 {
406
407 if (badaddr((void *)(bsh + offset), size))
408 return (-1);
409
410 switch(size) {
411 case 1:
412 bus_space_write_1(t, bsh, offset, val);
413 break;
414 case 2:
415 bus_space_write_2(t, bsh, offset, val);
416 break;
417 case 4:
418 bus_space_write_4(t, bsh, offset, val);
419 break;
420 default:
421 panic("bus_space_poke: bad size, %d", size);
422 }
423
424 return (0);
425 }
426
427 u_int8_t
__bs_r_1(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset)428 __bs_r_1(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset)
429 {
430 wbflush();
431 return (*(volatile u_int8_t *)(bsh + offset));
432 }
433
434 u_int16_t
__bs_r_2(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset)435 __bs_r_2(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset)
436 {
437 wbflush();
438 return (*(volatile u_int16_t *)(bsh + offset));
439 }
440
441 u_int32_t
__bs_r_4(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset)442 __bs_r_4(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset)
443 {
444 wbflush();
445 return (*(volatile u_int32_t *)(bsh + offset));
446 }
447
448 void
__bs_rm_1(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,u_int8_t * addr,bus_size_t count)449 __bs_rm_1(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset,
450 u_int8_t *addr, bus_size_t count) {
451 while (count--)
452 *addr++ = bus_space_read_1(t, bsh, offset);
453 }
454
455 void
__bs_rm_2(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,u_int16_t * addr,bus_size_t count)456 __bs_rm_2(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset,
457 u_int16_t *addr, bus_size_t count)
458 {
459 while (count--)
460 *addr++ = bus_space_read_2(t, bsh, offset);
461 }
462
463 void
__bs_rm_4(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,u_int32_t * addr,bus_size_t count)464 __bs_rm_4(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset,
465 u_int32_t *addr, bus_size_t count)
466 {
467 while (count--)
468 *addr++ = bus_space_read_4(t, bsh, offset);
469 }
470
471 void
__bs_rr_1(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,u_int8_t * addr,bus_size_t count)472 __bs_rr_1(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset,
473 u_int8_t *addr, bus_size_t count)
474 {
475 while (count--) {
476 *addr++ = bus_space_read_1(t, bsh, offset);
477 offset += sizeof(*addr);
478 }
479 }
480
481 void
__bs_rr_2(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,u_int16_t * addr,bus_size_t count)482 __bs_rr_2(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset,
483 u_int16_t *addr, bus_size_t count)
484 {
485 while (count--) {
486 *addr++ = bus_space_read_2(t, bsh, offset);
487 offset += sizeof(*addr);
488 }
489 }
490
491 void
__bs_rr_4(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,u_int32_t * addr,bus_size_t count)492 __bs_rr_4(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset,
493 u_int32_t *addr, bus_size_t count)
494 {
495 while (count--) {
496 *addr++ = bus_space_read_4(t, bsh, offset);
497 offset += sizeof(*addr);
498 }
499 }
500
501 void
__bs_w_1(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,u_int8_t value)502 __bs_w_1(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset,
503 u_int8_t value)
504 {
505 *(volatile u_int8_t *)(bsh + offset) = value;
506 wbflush();
507 }
508
509 void
__bs_w_2(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,u_int16_t value)510 __bs_w_2(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset,
511 u_int16_t value)
512 {
513 *(volatile u_int16_t *)(bsh + offset) = value;
514 wbflush();
515 }
516
517 void
__bs_w_4(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,u_int32_t value)518 __bs_w_4(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset,
519 u_int32_t value)
520 {
521 *(volatile u_int32_t *)(bsh + offset) = value;
522 wbflush();
523 }
524
525 void
__bs_wm_1(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,const u_int8_t * addr,bus_size_t count)526 __bs_wm_1(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset,
527 const u_int8_t *addr, bus_size_t count)
528 {
529 while (count--)
530 bus_space_write_1(t, bsh, offset, *addr++);
531 }
532
533 void
__bs_wm_2(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,const u_int16_t * addr,bus_size_t count)534 __bs_wm_2(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset,
535 const u_int16_t *addr, bus_size_t count)
536 {
537 while (count--)
538 bus_space_write_2(t, bsh, offset, *addr++);
539 }
540
541 void
__bs_wm_4(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,const u_int32_t * addr,bus_size_t count)542 __bs_wm_4(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset,
543 const u_int32_t *addr, bus_size_t count)
544 {
545 while (count--)
546 bus_space_write_4(t, bsh, offset, *addr++);
547 }
548
549 void
__bs_wr_1(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,const u_int8_t * addr,bus_size_t count)550 __bs_wr_1(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset,
551 const u_int8_t *addr, bus_size_t count)
552 {
553 while (count--) {
554 bus_space_write_1(t, bsh, offset, *addr++);
555 offset += sizeof(*addr);
556 }
557 }
558
559 void
__bs_wr_2(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,const u_int16_t * addr,bus_size_t count)560 __bs_wr_2(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset,
561 const u_int16_t *addr, bus_size_t count)
562 {
563 while (count--) {
564 bus_space_write_2(t, bsh, offset, *addr++);
565 offset += sizeof(*addr);
566 }
567 }
568
569 void
__bs_wr_4(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,const u_int32_t * addr,bus_size_t count)570 __bs_wr_4(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset,
571 const u_int32_t *addr, bus_size_t count)
572 {
573 while (count--) {
574 bus_space_write_4(t, bsh, offset, *addr++);
575 offset += sizeof(*addr);
576 }
577 }
578
579 void
__bs_sm_1(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,u_int8_t value,bus_size_t count)580 __bs_sm_1(bus_space_tag_t t, bus_space_handle_t bsh,
581 bus_size_t offset, u_int8_t value, bus_size_t count)
582 {
583 while (count--)
584 bus_space_write_1(t, bsh, offset, value);
585 }
586
587 void
__bs_sm_2(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,u_int16_t value,bus_size_t count)588 __bs_sm_2(bus_space_tag_t t, bus_space_handle_t bsh,
589 bus_size_t offset, u_int16_t value, bus_size_t count)
590 {
591 while (count--)
592 bus_space_write_2(t, bsh, offset, value);
593 }
594
595 void
__bs_sm_4(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,u_int32_t value,bus_size_t count)596 __bs_sm_4(bus_space_tag_t t, bus_space_handle_t bsh,
597 bus_size_t offset, u_int32_t value, bus_size_t count)
598 {
599 while (count--)
600 bus_space_write_4(t, bsh, offset, value);
601 }
602
603
604 void
__bs_sr_1(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,u_int8_t value,bus_size_t count)605 __bs_sr_1(bus_space_tag_t t, bus_space_handle_t bsh,
606 bus_size_t offset, u_int8_t value, bus_size_t count)
607 {
608 while (count--) {
609 bus_space_write_1(t, bsh, offset, value);
610 offset += (value);
611 }
612 }
613
614 void
__bs_sr_2(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,u_int16_t value,bus_size_t count)615 __bs_sr_2(bus_space_tag_t t, bus_space_handle_t bsh,
616 bus_size_t offset, u_int16_t value, bus_size_t count)
617 {
618 while (count--) {
619 bus_space_write_2(t, bsh, offset, value);
620 offset += (value);
621 }
622 }
623
624 void
__bs_sr_4(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t offset,u_int32_t value,bus_size_t count)625 __bs_sr_4(bus_space_tag_t t, bus_space_handle_t bsh,
626 bus_size_t offset, u_int32_t value, bus_size_t count)
627 {
628 while (count--) {
629 bus_space_write_4(t, bsh, offset, value);
630 offset += (value);
631 }
632 }
633
634 #define __bs_c_n(n) \
635 void __CONCAT(__bs_c_,n)(bus_space_tag_t t, bus_space_handle_t h1, \
636 bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) \
637 { \
638 bus_size_t o; \
639 \
640 if ((h1 + o1) >= (h2 + o2)) { \
641 /* src after dest: copy forward */ \
642 for (o = 0; c != 0; c--, o += n) \
643 __CONCAT(bus_space_write_,n)(t, h2, o2 + o, \
644 __CONCAT(bus_space_read_,n)(t, h1, o1 + o));\
645 } else { \
646 /* dest after src: copy backwards */ \
647 for (o = (c - 1) * n; c != 0; c--, o -= n) \
648 __CONCAT(bus_space_write_,n)(t, h2, o2 + o, \
649 __CONCAT(bus_space_read_,n)(t, h1, o1 + o));\
650 } \
651 }
652
653 __bs_c_n(1)
654 __bs_c_n(2)
655 __bs_c_n(4)
656