Home | History | Annotate | Line # | Download | only in dev
obio.c revision 1.2
      1 /*	$NetBSD: obio.c,v 1.2 2007/09/24 22:55:13 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.2 2007/09/24 22:55:13 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 obio_softc),
     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