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