xref: /netbsd-src/sys/arch/landisk/dev/obio.c (revision ce2c90c7c172d95d2402a5b3d96d8f8e6d138a21)
1 /*	$NetBSD: obio.c,v 1.1 2006/09/01 21:26:18 uwe 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 Charles M. Hannum.
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  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *        This product includes software developed by the NetBSD
21  *        Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: obio.c,v 1.1 2006/09/01 21:26:18 uwe Exp $");
41 
42 #include "btn_obio.h"
43 #include "pwrsw_obio.h"
44 
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/device.h>
48 
49 #include <uvm/uvm_extern.h>
50 
51 #include <sh3/devreg.h>
52 #include <sh3/mmu.h>
53 #include <sh3/pmap.h>
54 #include <sh3/pte.h>
55 
56 #include <machine/bus.h>
57 #include <machine/cpu.h>
58 #include <machine/intr.h>
59 
60 #include <landisk/dev/obiovar.h>
61 
62 #if (NPWRSW_OBIO > 0) || (NBTN_OBIO > 0)
63 #include <dev/sysmon/sysmonvar.h>
64 #include <dev/sysmon/sysmon_taskq.h>
65 #endif
66 
67 #include "locators.h"
68 
69 static int	obio_match(struct device *, struct cfdata *, void *);
70 static void	obio_attach(struct device *, struct device *, void *);
71 static int	obio_print(void *, const char *);
72 static int	obio_search(struct device *, struct cfdata *,
73 		    const int *, void *);
74 
75 CFATTACH_DECL(obio, sizeof(struct device),
76     obio_match, obio_attach, NULL, NULL);
77 
78 static int
79 obio_match(struct device *parent, struct cfdata *cf, void *aux)
80 {
81 	struct obiobus_attach_args *oba = aux;
82 
83 	if (strcmp(oba->oba_busname, cf->cf_name))
84 		return (0);
85 
86 	return (1);
87 }
88 
89 static void
90 obio_attach(struct device *parent, struct device *self, void *aux)
91 {
92 	struct obio_softc *sc = (struct obio_softc *)self;
93 	struct obiobus_attach_args *oba = aux;
94 
95 	printf("\n");
96 
97 	sc->sc_iot = oba->oba_iot;
98 	sc->sc_memt = oba->oba_memt;
99 
100 #if (NPWRSW_OBIO > 0) || (NBTN_OBIO > 0)
101 	sysmon_power_settype("landisk");
102 	sysmon_task_queue_init();
103 #endif
104 
105 	config_search_ia(obio_search, self, "obio", NULL);
106 }
107 
108 static int
109 obio_search(struct device *parent, struct cfdata *cf,
110     const int *ldesc, void *aux)
111 {
112 	struct obio_io res_io[1];
113 	struct obio_iomem res_mem[1];
114 	struct obio_irq res_irq[1];
115 	struct obio_softc *sc = (struct obio_softc *)parent;
116 	struct obio_attach_args oa;
117 	int tryagain;
118 
119 	do {
120 		oa.oa_iot = sc->sc_iot;
121 		oa.oa_memt = sc->sc_memt;
122 
123 		res_io[0].or_addr = cf->cf_iobase;
124 		res_io[0].or_size = cf->cf_iosize;
125 
126 		res_mem[0].or_addr = cf->cf_maddr;
127 		res_mem[0].or_size = cf->cf_msize;
128 
129 		res_irq[0].or_irq = cf->cf_irq;
130 
131 		oa.oa_io = res_io;
132 		oa.oa_nio = 1;
133 
134 		oa.oa_iomem = res_mem;
135 		oa.oa_niomem = 1;
136 
137 		oa.oa_irq = res_irq;
138 		oa.oa_nirq = 1;
139 
140 		tryagain = 0;
141 		if (config_match(parent, cf, &oa) > 0) {
142 			config_attach(parent, cf, &oa, obio_print);
143 			tryagain = (cf->cf_fstate == FSTATE_STAR);
144 		}
145 	} while (tryagain);
146 
147 	return (0);
148 }
149 
150 static int
151 obio_print(void *args, const char *name)
152 {
153 	struct obio_attach_args *oa = args;
154 	const char *sep;
155 	int i;
156 
157 	if (oa->oa_nio) {
158 		sep = "";
159 		aprint_normal(" port ");
160 		for (i = 0; i < oa->oa_nio; i++) {
161 			if (oa->oa_io[i].or_size == 0)
162 				continue;
163 			aprint_normal("%s0x%x", sep, oa->oa_io[i].or_addr);
164 			if (oa->oa_io[i].or_size > 1)
165 				aprint_normal("-0x%x", oa->oa_io[i].or_addr +
166 				    oa->oa_io[i].or_size - 1);
167 			sep = ",";
168 		}
169 	}
170 
171 	if (oa->oa_niomem) {
172 		sep = "";
173 		aprint_normal(" iomem ");
174 		for (i = 0; i < oa->oa_niomem; i++) {
175 			if (oa->oa_iomem[i].or_size == 0)
176 				continue;
177 			aprint_normal("%s0x%x", sep, oa->oa_iomem[i].or_addr);
178 			if (oa->oa_iomem[i].or_size > 1)
179 				aprint_normal("-0x%x", oa->oa_iomem[i].or_addr +
180 				    oa->oa_iomem[i].or_size - 1);
181 			sep = ",";
182 		}
183 	}
184 
185 	if (oa->oa_nirq) {
186 		sep = "";
187 		aprint_normal(" irq ");
188 		for (i = 0; i < oa->oa_nirq; i++) {
189 			if (oa->oa_irq[i].or_irq == IRQUNK)
190 				continue;
191 			aprint_normal("%s%d", sep, oa->oa_irq[i].or_irq);
192 			sep = ",";
193 		}
194 	}
195 
196 	return (UNCONF);
197 }
198 
199 /*
200  * Set up an interrupt handler to start being called.
201  */
202 void *
203 obio_intr_establish(int irq, int level, int (*ih_fun)(void *), void *ih_arg)
204 {
205 
206 	return extintr_establish(irq, level, ih_fun, ih_arg);
207 }
208 
209 /*
210  * Deregister an interrupt handler.
211  */
212 void
213 obio_intr_disestablish(void *arg)
214 {
215 
216 	extintr_disestablish(arg);
217 }
218 
219 /*
220  * on-board I/O bus space
221  */
222 #define	OBIO_IOMEM_IO		0	/* space is i/o space */
223 #define	OBIO_IOMEM_MEM		1	/* space is mem space */
224 #define	OBIO_IOMEM_PCMCIA_IO	2	/* PCMCIA IO space */
225 #define	OBIO_IOMEM_PCMCIA_MEM	3	/* PCMCIA Mem space */
226 #define	OBIO_IOMEM_PCMCIA_ATT	4	/* PCMCIA Attr space */
227 #define	OBIO_IOMEM_PCMCIA_8BIT	0x8000	/* PCMCIA BUS 8 BIT WIDTH */
228 #define	OBIO_IOMEM_PCMCIA_IO8 \
229 	    (OBIO_IOMEM_PCMCIA_IO|OBIO_IOMEM_PCMCIA_8BIT)
230 #define	OBIO_IOMEM_PCMCIA_MEM8 \
231 	    (OBIO_IOMEM_PCMCIA_MEM|OBIO_IOMEM_PCMCIA_8BIT)
232 #define	OBIO_IOMEM_PCMCIA_ATT8 \
233 	    (OBIO_IOMEM_PCMCIA_ATT|OBIO_IOMEM_PCMCIA_8BIT)
234 
235 int obio_iomem_map(void *v, bus_addr_t bpa, bus_size_t size, int flags,
236     bus_space_handle_t *bshp);
237 void obio_iomem_unmap(void *v, bus_space_handle_t bsh, bus_size_t size);
238 int obio_iomem_subregion(void *v, bus_space_handle_t bsh,
239     bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp);
240 int obio_iomem_alloc(void *v, bus_addr_t rstart, bus_addr_t rend,
241     bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags,
242     bus_addr_t *bpap, bus_space_handle_t *bshp);
243 void obio_iomem_free(void *v, bus_space_handle_t bsh, bus_size_t size);
244 
245 static int obio_iomem_add_mapping(bus_addr_t, bus_size_t, int,
246     bus_space_handle_t *);
247 
248 static int
249 obio_iomem_add_mapping(bus_addr_t bpa, bus_size_t size, int type,
250     bus_space_handle_t *bshp)
251 {
252 	u_long pa, endpa;
253 	vaddr_t va;
254 	pt_entry_t *pte;
255 	unsigned int m = 0;
256 	int io_type = type & ~OBIO_IOMEM_PCMCIA_8BIT;
257 
258 	pa = sh3_trunc_page(bpa);
259 	endpa = sh3_round_page(bpa + size);
260 
261 #ifdef DIAGNOSTIC
262 	if (endpa <= pa)
263 		panic("obio_iomem_add_mapping: overflow");
264 #endif
265 
266 	va = uvm_km_alloc(kernel_map, endpa - pa, 0, UVM_KMF_VAONLY);
267 	if (va == 0){
268 		printf("obio_iomem_add_mapping: nomem\n");
269 		return (ENOMEM);
270 	}
271 
272 	*bshp = (bus_space_handle_t)(va + (bpa & PGOFSET));
273 
274 #define MODE(t, s)							\
275 	((t) & OBIO_IOMEM_PCMCIA_8BIT) ?				\
276 		_PG_PCMCIA_ ## s ## 8 :					\
277 		_PG_PCMCIA_ ## s ## 16
278 	switch (io_type) {
279 	default:
280 		panic("unknown pcmcia space.");
281 		/* NOTREACHED */
282 	case OBIO_IOMEM_PCMCIA_IO:
283 		m = MODE(type, IO);
284 		break;
285 	case OBIO_IOMEM_PCMCIA_MEM:
286 		m = MODE(type, MEM);
287 		break;
288 	case OBIO_IOMEM_PCMCIA_ATT:
289 		m = MODE(type, ATTR);
290 		break;
291 	}
292 #undef MODE
293 
294 	for (; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) {
295 		pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE);
296 		pte = __pmap_kpte_lookup(va);
297 		KDASSERT(pte);
298 		*pte |= m;  /* PTEA PCMCIA assistant bit */
299 		sh_tlb_update(0, va, *pte);
300 	}
301 
302 	return (0);
303 }
304 
305 int
306 obio_iomem_map(void *v, bus_addr_t bpa, bus_size_t size,
307     int flags, bus_space_handle_t *bshp)
308 {
309 	bus_addr_t addr = SH3_PHYS_TO_P2SEG(bpa);
310 	int error;
311 
312 	KASSERT((bpa & SH3_PHYS_MASK) == bpa);
313 
314 	if (bpa < 0x14000000 || bpa >= 0x1c000000) {
315 		/* CS0,1,2,3,4,7 */
316 		*bshp = (bus_space_handle_t)addr;
317 		return (0);
318 	}
319 
320 	/* CS5,6 */
321 	error = obio_iomem_add_mapping(addr, size, (int)(u_long)v, bshp);
322 
323 	return (error);
324 }
325 
326 void
327 obio_iomem_unmap(void *v, bus_space_handle_t bsh, bus_size_t size)
328 {
329 	u_long va, endva;
330 	bus_addr_t bpa;
331 
332 	if (bsh >= SH3_P2SEG_BASE && bsh <= SH3_P2SEG_END) {
333 		/* maybe CS0,1,2,3,4,7 */
334 		return;
335 	}
336 
337 	/* CS5,6 */
338 	va = sh3_trunc_page(bsh);
339 	endva = sh3_round_page(bsh + size);
340 
341 #ifdef DIAGNOSTIC
342 	if (endva <= va)
343 		panic("obio_io_unmap: overflow");
344 #endif
345 
346 	pmap_extract(pmap_kernel(), va, &bpa);
347 	bpa += bsh & PGOFSET;
348 
349 	pmap_kremove(va, endva - va);
350 
351 	/*
352 	 * Free the kernel virtual mapping.
353 	 */
354 	uvm_km_free(kernel_map, va, endva - va, UVM_KMF_VAONLY);
355 }
356 
357 int
358 obio_iomem_subregion(void *v, bus_space_handle_t bsh,
359     bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp)
360 {
361 
362 	*nbshp = bsh + offset;
363 
364 	return (0);
365 }
366 
367 int
368 obio_iomem_alloc(void *v, bus_addr_t rstart, bus_addr_t rend,
369     bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags,
370     bus_addr_t *bpap, bus_space_handle_t *bshp)
371 {
372 
373 	*bshp = *bpap = rstart;
374 
375 	return (0);
376 }
377 
378 void
379 obio_iomem_free(void *v, bus_space_handle_t bsh, bus_size_t size)
380 {
381 
382 	obio_iomem_unmap(v, bsh, size);
383 }
384 
385 /*
386  * on-board I/O bus space read/write
387  */
388 uint8_t obio_iomem_read_1(void *v, bus_space_handle_t bsh, bus_size_t offset);
389 uint16_t obio_iomem_read_2(void *v, bus_space_handle_t bsh, bus_size_t offset);
390 uint32_t obio_iomem_read_4(void *v, bus_space_handle_t bsh, bus_size_t offset);
391 void obio_iomem_read_multi_1(void *v, bus_space_handle_t bsh,
392     bus_size_t offset, uint8_t *addr, bus_size_t count);
393 void obio_iomem_read_multi_2(void *v, bus_space_handle_t bsh,
394     bus_size_t offset, uint16_t *addr, bus_size_t count);
395 void obio_iomem_read_multi_4(void *v, bus_space_handle_t bsh,
396     bus_size_t offset, uint32_t *addr, bus_size_t count);
397 void obio_iomem_read_region_1(void *v, bus_space_handle_t bsh,
398     bus_size_t offset, uint8_t *addr, bus_size_t count);
399 void obio_iomem_read_region_2(void *v, bus_space_handle_t bsh,
400     bus_size_t offset, uint16_t *addr, bus_size_t count);
401 void obio_iomem_read_region_4(void *v, bus_space_handle_t bsh,
402     bus_size_t offset, uint32_t *addr, bus_size_t count);
403 void obio_iomem_write_1(void *v, bus_space_handle_t bsh, bus_size_t offset,
404     uint8_t value);
405 void obio_iomem_write_2(void *v, bus_space_handle_t bsh, bus_size_t offset,
406     uint16_t value);
407 void obio_iomem_write_4(void *v, bus_space_handle_t bsh, bus_size_t offset,
408     uint32_t value);
409 void obio_iomem_write_multi_1(void *v, bus_space_handle_t bsh,
410     bus_size_t offset, const uint8_t *addr, bus_size_t count);
411 void obio_iomem_write_multi_2(void *v, bus_space_handle_t bsh,
412     bus_size_t offset, const uint16_t *addr, bus_size_t count);
413 void obio_iomem_write_multi_4(void *v, bus_space_handle_t bsh,
414     bus_size_t offset, const uint32_t *addr, bus_size_t count);
415 void obio_iomem_write_region_1(void *v, bus_space_handle_t bsh,
416     bus_size_t offset, const uint8_t *addr, bus_size_t count);
417 void obio_iomem_write_region_2(void *v, bus_space_handle_t bsh,
418     bus_size_t offset, const uint16_t *addr, bus_size_t count);
419 void obio_iomem_write_region_4(void *v, bus_space_handle_t bsh,
420     bus_size_t offset, const uint32_t *addr, bus_size_t count);
421 void obio_iomem_set_multi_1(void *v, bus_space_handle_t bsh, bus_size_t offset,
422     uint8_t val, bus_size_t count);
423 void obio_iomem_set_multi_2(void *v, bus_space_handle_t bsh, bus_size_t offset,
424     uint16_t val, bus_size_t count);
425 void obio_iomem_set_multi_4(void *v, bus_space_handle_t bsh, bus_size_t offset,
426     uint32_t val, bus_size_t count);
427 void obio_iomem_set_region_1(void *v, bus_space_handle_t bsh,
428     bus_size_t offset, uint8_t val, bus_size_t count);
429 void obio_iomem_set_region_2(void *v, bus_space_handle_t bsh,
430     bus_size_t offset, uint16_t val, bus_size_t count);
431 void obio_iomem_set_region_4(void *v, bus_space_handle_t bsh,
432     bus_size_t offset, uint32_t val, bus_size_t count);
433 void obio_iomem_copy_region_1(void *v, bus_space_handle_t h1, bus_size_t o1,
434     bus_space_handle_t h2, bus_size_t o2, bus_size_t count);
435 void obio_iomem_copy_region_2(void *v, bus_space_handle_t h1, bus_size_t o1,
436     bus_space_handle_t h2, bus_size_t o2, bus_size_t count);
437 void obio_iomem_copy_region_4(void *v, bus_space_handle_t h1, bus_size_t o1,
438     bus_space_handle_t h2, bus_size_t o2, bus_size_t count);
439 
440 struct _bus_space obio_bus_io =
441 {
442 	.bs_cookie = (void *)OBIO_IOMEM_PCMCIA_IO,
443 
444 	.bs_map = obio_iomem_map,
445 	.bs_unmap = obio_iomem_unmap,
446 	.bs_subregion = obio_iomem_subregion,
447 
448 	.bs_alloc = obio_iomem_alloc,
449 	.bs_free = obio_iomem_free,
450 
451 	.bs_r_1 = obio_iomem_read_1,
452 	.bs_r_2 = obio_iomem_read_2,
453 	.bs_r_4 = obio_iomem_read_4,
454 
455 	.bs_rm_1 = obio_iomem_read_multi_1,
456 	.bs_rm_2 = obio_iomem_read_multi_2,
457 	.bs_rm_4 = obio_iomem_read_multi_4,
458 
459 	.bs_rr_1 = obio_iomem_read_region_1,
460 	.bs_rr_2 = obio_iomem_read_region_2,
461 	.bs_rr_4 = obio_iomem_read_region_4,
462 
463 	.bs_w_1 = obio_iomem_write_1,
464 	.bs_w_2 = obio_iomem_write_2,
465 	.bs_w_4 = obio_iomem_write_4,
466 
467 	.bs_wm_1 = obio_iomem_write_multi_1,
468 	.bs_wm_2 = obio_iomem_write_multi_2,
469 	.bs_wm_4 = obio_iomem_write_multi_4,
470 
471 	.bs_wr_1 = obio_iomem_write_region_1,
472 	.bs_wr_2 = obio_iomem_write_region_2,
473 	.bs_wr_4 = obio_iomem_write_region_4,
474 
475 	.bs_sm_1 = obio_iomem_set_multi_1,
476 	.bs_sm_2 = obio_iomem_set_multi_2,
477 	.bs_sm_4 = obio_iomem_set_multi_4,
478 
479 	.bs_sr_1 = obio_iomem_set_region_1,
480 	.bs_sr_2 = obio_iomem_set_region_2,
481 	.bs_sr_4 = obio_iomem_set_region_4,
482 
483 	.bs_c_1 = obio_iomem_copy_region_1,
484 	.bs_c_2 = obio_iomem_copy_region_2,
485 	.bs_c_4 = obio_iomem_copy_region_4,
486 };
487 
488 struct _bus_space obio_bus_mem =
489 {
490 	.bs_cookie = (void *)OBIO_IOMEM_PCMCIA_MEM,
491 
492 	.bs_map = obio_iomem_map,
493 	.bs_unmap = obio_iomem_unmap,
494 	.bs_subregion = obio_iomem_subregion,
495 
496 	.bs_alloc = obio_iomem_alloc,
497 	.bs_free = obio_iomem_free,
498 
499 	.bs_r_1 = obio_iomem_read_1,
500 	.bs_r_2 = obio_iomem_read_2,
501 	.bs_r_4 = obio_iomem_read_4,
502 
503 	.bs_rm_1 = obio_iomem_read_multi_1,
504 	.bs_rm_2 = obio_iomem_read_multi_2,
505 	.bs_rm_4 = obio_iomem_read_multi_4,
506 
507 	.bs_rr_1 = obio_iomem_read_region_1,
508 	.bs_rr_2 = obio_iomem_read_region_2,
509 	.bs_rr_4 = obio_iomem_read_region_4,
510 
511 	.bs_w_1 = obio_iomem_write_1,
512 	.bs_w_2 = obio_iomem_write_2,
513 	.bs_w_4 = obio_iomem_write_4,
514 
515 	.bs_wm_1 = obio_iomem_write_multi_1,
516 	.bs_wm_2 = obio_iomem_write_multi_2,
517 	.bs_wm_4 = obio_iomem_write_multi_4,
518 
519 	.bs_wr_1 = obio_iomem_write_region_1,
520 	.bs_wr_2 = obio_iomem_write_region_2,
521 	.bs_wr_4 = obio_iomem_write_region_4,
522 
523 	.bs_sm_1 = obio_iomem_set_multi_1,
524 	.bs_sm_2 = obio_iomem_set_multi_2,
525 	.bs_sm_4 = obio_iomem_set_multi_4,
526 
527 	.bs_sr_1 = obio_iomem_set_region_1,
528 	.bs_sr_2 = obio_iomem_set_region_2,
529 	.bs_sr_4 = obio_iomem_set_region_4,
530 
531 	.bs_c_1 = obio_iomem_copy_region_1,
532 	.bs_c_2 = obio_iomem_copy_region_2,
533 	.bs_c_4 = obio_iomem_copy_region_4,
534 };
535 
536 /* read */
537 uint8_t
538 obio_iomem_read_1(void *v, bus_space_handle_t bsh, bus_size_t offset)
539 {
540 
541 	return *(volatile uint8_t *)(bsh + offset);
542 }
543 
544 uint16_t
545 obio_iomem_read_2(void *v, bus_space_handle_t bsh, bus_size_t offset)
546 {
547 
548 	return *(volatile uint16_t *)(bsh + offset);
549 }
550 
551 uint32_t
552 obio_iomem_read_4(void *v, bus_space_handle_t bsh, bus_size_t offset)
553 {
554 
555 	return *(volatile uint32_t *)(bsh + offset);
556 }
557 
558 void
559 obio_iomem_read_multi_1(void *v, bus_space_handle_t bsh,
560     bus_size_t offset, uint8_t *addr, bus_size_t count)
561 {
562 	volatile uint8_t *p = (void *)(bsh + offset);
563 
564 	while (count--) {
565 		*addr++ = *p;
566 	}
567 }
568 
569 void
570 obio_iomem_read_multi_2(void *v, bus_space_handle_t bsh,
571     bus_size_t offset, uint16_t *addr, bus_size_t count)
572 {
573 	volatile uint16_t *p = (void *)(bsh + offset);
574 
575 	while (count--) {
576 		*addr++ = *p;
577 	}
578 }
579 
580 void
581 obio_iomem_read_multi_4(void *v, bus_space_handle_t bsh,
582     bus_size_t offset, uint32_t *addr, bus_size_t count)
583 {
584 	volatile uint32_t *p = (void *)(bsh + offset);
585 
586 	while (count--) {
587 		*addr++ = *p;
588 	}
589 }
590 
591 void
592 obio_iomem_read_region_1(void *v, bus_space_handle_t bsh,
593     bus_size_t offset, uint8_t *addr, bus_size_t count)
594 {
595 	volatile uint8_t *p = (void *)(bsh + offset);
596 
597 	while (count--) {
598 		*addr++ = *p++;
599 	}
600 }
601 
602 void
603 obio_iomem_read_region_2(void *v, bus_space_handle_t bsh,
604     bus_size_t offset, uint16_t *addr, bus_size_t count)
605 {
606 	volatile uint16_t *p = (void *)(bsh + offset);
607 
608 	while (count--) {
609 		*addr++ = *p++;
610 	}
611 }
612 
613 void
614 obio_iomem_read_region_4(void *v, bus_space_handle_t bsh,
615     bus_size_t offset, uint32_t *addr, bus_size_t count)
616 {
617 	volatile uint32_t *p = (void *)(bsh + offset);
618 
619 	while (count--) {
620 		*addr++ = *p++;
621 	}
622 }
623 
624 /* write */
625 void
626 obio_iomem_write_1(void *v, bus_space_handle_t bsh, bus_size_t offset,
627     uint8_t value)
628 {
629 
630 	*(volatile uint8_t *)(bsh + offset) = value;
631 }
632 
633 void
634 obio_iomem_write_2(void *v, bus_space_handle_t bsh, bus_size_t offset,
635     uint16_t value)
636 {
637 
638 	*(volatile uint16_t *)(bsh + offset) = value;
639 }
640 
641 void
642 obio_iomem_write_4(void *v, bus_space_handle_t bsh, bus_size_t offset,
643     uint32_t value)
644 {
645 
646 	*(volatile uint32_t *)(bsh + offset) = value;
647 }
648 
649 void
650 obio_iomem_write_multi_1(void *v, bus_space_handle_t bsh,
651     bus_size_t offset, const uint8_t *addr, bus_size_t count)
652 {
653 	volatile uint8_t *p = (void *)(bsh + offset);
654 
655 	while (count--) {
656 		*p = *addr++;
657 	}
658 }
659 
660 void
661 obio_iomem_write_multi_2(void *v, bus_space_handle_t bsh,
662     bus_size_t offset, const uint16_t *addr, bus_size_t count)
663 {
664 	volatile uint16_t *p = (void *)(bsh + offset);
665 
666 	while (count--) {
667 		*p = *addr++;
668 	}
669 }
670 
671 void
672 obio_iomem_write_multi_4(void *v, bus_space_handle_t bsh,
673     bus_size_t offset, const uint32_t *addr, bus_size_t count)
674 {
675 	volatile uint32_t *p = (void *)(bsh + offset);
676 
677 	while (count--) {
678 		*p = *addr++;
679 	}
680 }
681 
682 void
683 obio_iomem_write_region_1(void *v, bus_space_handle_t bsh,
684     bus_size_t offset, const uint8_t *addr, bus_size_t count)
685 {
686 	volatile uint8_t *p = (void *)(bsh + offset);
687 
688 	while (count--) {
689 		*p++ = *addr++;
690 	}
691 }
692 
693 void
694 obio_iomem_write_region_2(void *v, bus_space_handle_t bsh,
695     bus_size_t offset, const uint16_t *addr, bus_size_t count)
696 {
697 	volatile uint16_t *p = (void *)(bsh + offset);
698 
699 	while (count--) {
700 		*p++ = *addr++;
701 	}
702 }
703 
704 void
705 obio_iomem_write_region_4(void *v, bus_space_handle_t bsh,
706     bus_size_t offset, const uint32_t *addr, bus_size_t count)
707 {
708 	volatile uint32_t *p = (void *)(bsh + offset);
709 
710 	while (count--) {
711 		*p++ = *addr++;
712 	}
713 }
714 
715 void
716 obio_iomem_set_multi_1(void *v, bus_space_handle_t bsh,
717     bus_size_t offset, uint8_t val, bus_size_t count)
718 {
719 	volatile uint8_t *p = (void *)(bsh + offset);
720 
721 	while (count--) {
722 		*p = val;
723 	}
724 }
725 
726 void
727 obio_iomem_set_multi_2(void *v, bus_space_handle_t bsh,
728     bus_size_t offset, uint16_t val, bus_size_t count)
729 {
730 	volatile uint16_t *p = (void *)(bsh + offset);
731 
732 	while (count--) {
733 		*p = val;
734 	}
735 }
736 
737 void
738 obio_iomem_set_multi_4(void *v, bus_space_handle_t bsh,
739     bus_size_t offset, uint32_t val, bus_size_t count)
740 {
741 	volatile uint32_t *p = (void *)(bsh + offset);
742 
743 	while (count--) {
744 		*p = val;
745 	}
746 }
747 
748 void
749 obio_iomem_set_region_1(void *v, bus_space_handle_t bsh,
750     bus_size_t offset, uint8_t val, bus_size_t count)
751 {
752 	volatile uint8_t *addr = (void *)(bsh + offset);
753 
754 	while (count--) {
755 		*addr++ = val;
756 	}
757 }
758 
759 void
760 obio_iomem_set_region_2(void *v, bus_space_handle_t bsh,
761     bus_size_t offset, uint16_t val, bus_size_t count)
762 {
763 	volatile uint16_t *addr = (void *)(bsh + offset);
764 
765 	while (count--) {
766 		*addr++ = val;
767 	}
768 }
769 
770 void
771 obio_iomem_set_region_4(void *v, bus_space_handle_t bsh,
772     bus_size_t offset, uint32_t val, bus_size_t count)
773 {
774 	volatile uint32_t *addr = (void *)(bsh + offset);
775 
776 	while (count--) {
777 		*addr++ = val;
778 	}
779 }
780 
781 void
782 obio_iomem_copy_region_1(void *v, bus_space_handle_t h1, bus_size_t o1,
783     bus_space_handle_t h2, bus_size_t o2, bus_size_t count)
784 {
785 	volatile uint8_t *addr1 = (void *)(h1 + o1);
786 	volatile uint8_t *addr2 = (void *)(h2 + o2);
787 
788 	if (addr1 >= addr2) {	/* src after dest: copy forward */
789 		while (count--) {
790 			*addr2++ = *addr1++;
791 		}
792 	} else {		/* dest after src: copy backwards */
793 		addr1 += count - 1;
794 		addr2 += count - 1;
795 		while (count--) {
796 			*addr2-- = *addr1--;
797 		}
798 	}
799 }
800 
801 void
802 obio_iomem_copy_region_2(void *v, bus_space_handle_t h1, bus_size_t o1,
803     bus_space_handle_t h2, bus_size_t o2, bus_size_t count)
804 {
805 	volatile uint16_t *addr1 = (void *)(h1 + o1);
806 	volatile uint16_t *addr2 = (void *)(h2 + o2);
807 
808 	if (addr1 >= addr2) {	/* src after dest: copy forward */
809 		while (count--) {
810 			*addr2++ = *addr1++;
811 		}
812 	} else {		/* dest after src: copy backwards */
813 		addr1 += count - 1;
814 		addr2 += count - 1;
815 		while (count--) {
816 			*addr2-- = *addr1--;
817 		}
818 	}
819 }
820 
821 void
822 obio_iomem_copy_region_4(void *v, bus_space_handle_t h1, bus_size_t o1,
823     bus_space_handle_t h2, bus_size_t o2, bus_size_t count)
824 {
825 	volatile uint32_t *addr1 = (void *)(h1 + o1);
826 	volatile uint32_t *addr2 = (void *)(h2 + o2);
827 
828 	if (addr1 >= addr2) {	/* src after dest: copy forward */
829 		while (count--) {
830 			*addr2++ = *addr1++;
831 		}
832 	} else {		/* dest after src: copy backwards */
833 		addr1 += count - 1;
834 		addr2 += count - 1;
835 		while (count--) {
836 			*addr2-- = *addr1--;
837 		}
838 	}
839 }
840