Home | History | Annotate | Line # | Download | only in t_sh7706lan
      1 /*	$NetBSD: t_sh7706lan_space.c,v 1.1 2010/04/06 15:54:31 nonaka 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  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __KERNEL_RCSID(0, "$NetBSD: t_sh7706lan_space.c,v 1.1 2010/04/06 15:54:31 nonaka Exp $");
     34 
     35 #include <sys/param.h>
     36 #include <sys/systm.h>
     37 #include <sys/device.h>
     38 #include <sys/bus.h>
     39 #include <sys/intr.h>
     40 
     41 #include <uvm/uvm_extern.h>
     42 
     43 #include <sh3/bscreg.h>
     44 #include <sh3/devreg.h>
     45 #include <sh3/mmu.h>
     46 #include <sh3/pmap.h>
     47 #include <sh3/pte.h>
     48 
     49 #include <machine/cpu.h>
     50 
     51 /*
     52  * I/O bus space
     53  */
     54 #define	T_SH7706LAN_IOMEM_IO		0	/* space is i/o space */
     55 #define	T_SH7706LAN_IOMEM_MEM		1	/* space is mem space */
     56 #define	T_SH7706LAN_IOMEM_PCMCIA_IO	2	/* PCMCIA IO space */
     57 #define	T_SH7706LAN_IOMEM_PCMCIA_MEM	3	/* PCMCIA Mem space */
     58 #define	T_SH7706LAN_IOMEM_PCMCIA_ATT	4	/* PCMCIA Attr space */
     59 #define	T_SH7706LAN_IOMEM_PCMCIA_8BIT	0x8000	/* PCMCIA BUS 8 BIT WIDTH */
     60 #define	T_SH7706LAN_IOMEM_PCMCIA_IO8 \
     61 	    (T_SH7706LAN_IOMEM_PCMCIA_IO|T_SH7706LAN_IOMEM_PCMCIA_8BIT)
     62 #define	T_SH7706LAN_IOMEM_PCMCIA_MEM8 \
     63 	    (T_SH7706LAN_IOMEM_PCMCIA_MEM|T_SH7706LAN_IOMEM_PCMCIA_8BIT)
     64 #define	T_SH7706LAN_IOMEM_PCMCIA_ATT8 \
     65 	    (T_SH7706LAN_IOMEM_PCMCIA_ATT|T_SH7706LAN_IOMEM_PCMCIA_8BIT)
     66 
     67 int t_sh7706lan_iomem_map(void *v, bus_addr_t bpa, bus_size_t size, int flags,
     68     bus_space_handle_t *bshp);
     69 void t_sh7706lan_iomem_unmap(void *v, bus_space_handle_t bsh, bus_size_t size);
     70 int t_sh7706lan_iomem_subregion(void *v, bus_space_handle_t bsh,
     71     bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp);
     72 int t_sh7706lan_iomem_alloc(void *v, bus_addr_t rstart, bus_addr_t rend,
     73     bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags,
     74     bus_addr_t *bpap, bus_space_handle_t *bshp);
     75 void t_sh7706lan_iomem_free(void *v, bus_space_handle_t bsh, bus_size_t size);
     76 
     77 static int t_sh7706lan_iomem_add_mapping(bus_addr_t, bus_size_t, int,
     78     bus_space_handle_t *);
     79 
     80 static int
     81 t_sh7706lan_iomem_add_mapping(bus_addr_t bpa, bus_size_t size, int type,
     82     bus_space_handle_t *bshp)
     83 {
     84 	u_long pa, endpa;
     85 	vaddr_t va;
     86 	pt_entry_t *pte;
     87 	unsigned int m = 0;
     88 	int io_type = type & ~T_SH7706LAN_IOMEM_PCMCIA_8BIT;
     89 
     90 	pa = sh3_trunc_page(bpa);
     91 	endpa = sh3_round_page(bpa + size);
     92 
     93 #ifdef DIAGNOSTIC
     94 	if (endpa <= pa)
     95 		panic("t_sh7706lan_iomem_add_mapping: overflow");
     96 #endif
     97 
     98 	va = uvm_km_alloc(kernel_map, endpa - pa, 0, UVM_KMF_VAONLY);
     99 	if (va == 0){
    100 		printf("t_sh7706lan_iomem_add_mapping: nomem\n");
    101 		return (ENOMEM);
    102 	}
    103 
    104 	*bshp = (bus_space_handle_t)(va + (bpa & PGOFSET));
    105 
    106 #define MODE(t, s)							\
    107 	((t) & T_SH7706LAN_IOMEM_PCMCIA_8BIT) ?				\
    108 		_PG_PCMCIA_ ## s ## 8 :					\
    109 		_PG_PCMCIA_ ## s ## 16
    110 	switch (io_type) {
    111 	default:
    112 		panic("unknown pcmcia space.");
    113 		/* NOTREACHED */
    114 	case T_SH7706LAN_IOMEM_PCMCIA_IO:
    115 		m = MODE(type, IO);
    116 		break;
    117 	case T_SH7706LAN_IOMEM_PCMCIA_MEM:
    118 		m = MODE(type, MEM);
    119 		break;
    120 	case T_SH7706LAN_IOMEM_PCMCIA_ATT:
    121 		m = MODE(type, ATTR);
    122 		break;
    123 	}
    124 #undef MODE
    125 
    126 	for (; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) {
    127 		pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE, 0);
    128 		pte = __pmap_kpte_lookup(va);
    129 		KDASSERT(pte);
    130 		*pte |= m;  /* PTEA PCMCIA assistant bit */
    131 		sh_tlb_update(0, va, *pte);
    132 	}
    133 
    134 	return (0);
    135 }
    136 
    137 int
    138 t_sh7706lan_iomem_map(void *v, bus_addr_t bpa, bus_size_t size,
    139     int flags, bus_space_handle_t *bshp)
    140 {
    141 	bus_addr_t addr = SH3_PHYS_TO_P2SEG(bpa);
    142 	int error;
    143 
    144 	KASSERT((bpa & SH3_PHYS_MASK) == bpa);
    145 
    146 	if (bpa < 0x14000000 || bpa >= 0x1c000000) {
    147 		/* CS0,1,2,3,4,7 */
    148 		*bshp = (bus_space_handle_t)addr;
    149 		return (0);
    150 	}
    151 
    152 	/* CS5,6 */
    153 	error = t_sh7706lan_iomem_add_mapping(addr, size, (int)(u_long)v, bshp);
    154 
    155 	return (error);
    156 }
    157 
    158 void
    159 t_sh7706lan_iomem_unmap(void *v, bus_space_handle_t bsh, bus_size_t size)
    160 {
    161 	u_long va, endva;
    162 	bus_addr_t bpa;
    163 
    164 	if (bsh >= SH3_P2SEG_BASE && bsh <= SH3_P2SEG_END) {
    165 		/* maybe CS0,1,2,3,4,7 */
    166 		return;
    167 	}
    168 
    169 	/* CS5,6 */
    170 	va = sh3_trunc_page(bsh);
    171 	endva = sh3_round_page(bsh + size);
    172 
    173 #ifdef DIAGNOSTIC
    174 	if (endva <= va)
    175 		panic("t_sh7706lan_io_unmap: overflow");
    176 #endif
    177 
    178 	pmap_extract(pmap_kernel(), va, &bpa);
    179 	bpa += bsh & PGOFSET;
    180 
    181 	pmap_kremove(va, endva - va);
    182 
    183 	/*
    184 	 * Free the kernel virtual mapping.
    185 	 */
    186 	uvm_km_free(kernel_map, va, endva - va, UVM_KMF_VAONLY);
    187 }
    188 
    189 int
    190 t_sh7706lan_iomem_subregion(void *v, bus_space_handle_t bsh,
    191     bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp)
    192 {
    193 
    194 	*nbshp = bsh + offset;
    195 
    196 	return (0);
    197 }
    198 
    199 int
    200 t_sh7706lan_iomem_alloc(void *v, bus_addr_t rstart, bus_addr_t rend,
    201     bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags,
    202     bus_addr_t *bpap, bus_space_handle_t *bshp)
    203 {
    204 
    205 	*bshp = *bpap = rstart;
    206 
    207 	return (0);
    208 }
    209 
    210 void
    211 t_sh7706lan_iomem_free(void *v, bus_space_handle_t bsh, bus_size_t size)
    212 {
    213 
    214 	t_sh7706lan_iomem_unmap(v, bsh, size);
    215 }
    216 
    217 /*
    218  * on-board I/O bus space read/write
    219  */
    220 uint8_t t_sh7706lan_iomem_read_1(void *v, bus_space_handle_t bsh, bus_size_t offset);
    221 uint16_t t_sh7706lan_iomem_read_2(void *v, bus_space_handle_t bsh, bus_size_t offset);
    222 uint32_t t_sh7706lan_iomem_read_4(void *v, bus_space_handle_t bsh, bus_size_t offset);
    223 void t_sh7706lan_iomem_read_multi_1(void *v, bus_space_handle_t bsh,
    224     bus_size_t offset, uint8_t *addr, bus_size_t count);
    225 void t_sh7706lan_iomem_read_multi_2(void *v, bus_space_handle_t bsh,
    226     bus_size_t offset, uint16_t *addr, bus_size_t count);
    227 void t_sh7706lan_iomem_read_multi_4(void *v, bus_space_handle_t bsh,
    228     bus_size_t offset, uint32_t *addr, bus_size_t count);
    229 void t_sh7706lan_iomem_read_region_1(void *v, bus_space_handle_t bsh,
    230     bus_size_t offset, uint8_t *addr, bus_size_t count);
    231 void t_sh7706lan_iomem_read_region_2(void *v, bus_space_handle_t bsh,
    232     bus_size_t offset, uint16_t *addr, bus_size_t count);
    233 void t_sh7706lan_iomem_read_region_4(void *v, bus_space_handle_t bsh,
    234     bus_size_t offset, uint32_t *addr, bus_size_t count);
    235 void t_sh7706lan_iomem_write_1(void *v, bus_space_handle_t bsh, bus_size_t offset,
    236     uint8_t value);
    237 void t_sh7706lan_iomem_write_2(void *v, bus_space_handle_t bsh, bus_size_t offset,
    238     uint16_t value);
    239 void t_sh7706lan_iomem_write_4(void *v, bus_space_handle_t bsh, bus_size_t offset,
    240     uint32_t value);
    241 void t_sh7706lan_iomem_write_multi_1(void *v, bus_space_handle_t bsh,
    242     bus_size_t offset, const uint8_t *addr, bus_size_t count);
    243 void t_sh7706lan_iomem_write_multi_2(void *v, bus_space_handle_t bsh,
    244     bus_size_t offset, const uint16_t *addr, bus_size_t count);
    245 void t_sh7706lan_iomem_write_multi_4(void *v, bus_space_handle_t bsh,
    246     bus_size_t offset, const uint32_t *addr, bus_size_t count);
    247 void t_sh7706lan_iomem_write_region_1(void *v, bus_space_handle_t bsh,
    248     bus_size_t offset, const uint8_t *addr, bus_size_t count);
    249 void t_sh7706lan_iomem_write_region_2(void *v, bus_space_handle_t bsh,
    250     bus_size_t offset, const uint16_t *addr, bus_size_t count);
    251 void t_sh7706lan_iomem_write_region_4(void *v, bus_space_handle_t bsh,
    252     bus_size_t offset, const uint32_t *addr, bus_size_t count);
    253 void t_sh7706lan_iomem_set_multi_1(void *v, bus_space_handle_t bsh, bus_size_t offset,
    254     uint8_t val, bus_size_t count);
    255 void t_sh7706lan_iomem_set_multi_2(void *v, bus_space_handle_t bsh, bus_size_t offset,
    256     uint16_t val, bus_size_t count);
    257 void t_sh7706lan_iomem_set_multi_4(void *v, bus_space_handle_t bsh, bus_size_t offset,
    258     uint32_t val, bus_size_t count);
    259 void t_sh7706lan_iomem_set_region_1(void *v, bus_space_handle_t bsh,
    260     bus_size_t offset, uint8_t val, bus_size_t count);
    261 void t_sh7706lan_iomem_set_region_2(void *v, bus_space_handle_t bsh,
    262     bus_size_t offset, uint16_t val, bus_size_t count);
    263 void t_sh7706lan_iomem_set_region_4(void *v, bus_space_handle_t bsh,
    264     bus_size_t offset, uint32_t val, bus_size_t count);
    265 void t_sh7706lan_iomem_copy_region_1(void *v, bus_space_handle_t h1, bus_size_t o1,
    266     bus_space_handle_t h2, bus_size_t o2, bus_size_t count);
    267 void t_sh7706lan_iomem_copy_region_2(void *v, bus_space_handle_t h1, bus_size_t o1,
    268     bus_space_handle_t h2, bus_size_t o2, bus_size_t count);
    269 void t_sh7706lan_iomem_copy_region_4(void *v, bus_space_handle_t h1, bus_size_t o1,
    270     bus_space_handle_t h2, bus_size_t o2, bus_size_t count);
    271 
    272 struct _bus_space t_sh7706lan_bus_io =
    273 {
    274 	.bs_cookie = (void *)T_SH7706LAN_IOMEM_PCMCIA_IO,
    275 
    276 	.bs_map = t_sh7706lan_iomem_map,
    277 	.bs_unmap = t_sh7706lan_iomem_unmap,
    278 	.bs_subregion = t_sh7706lan_iomem_subregion,
    279 
    280 	.bs_alloc = t_sh7706lan_iomem_alloc,
    281 	.bs_free = t_sh7706lan_iomem_free,
    282 
    283 	.bs_r_1 = t_sh7706lan_iomem_read_1,
    284 	.bs_r_2 = t_sh7706lan_iomem_read_2,
    285 	.bs_r_4 = t_sh7706lan_iomem_read_4,
    286 
    287 	.bs_rm_1 = t_sh7706lan_iomem_read_multi_1,
    288 	.bs_rm_2 = t_sh7706lan_iomem_read_multi_2,
    289 	.bs_rm_4 = t_sh7706lan_iomem_read_multi_4,
    290 
    291 	.bs_rr_1 = t_sh7706lan_iomem_read_region_1,
    292 	.bs_rr_2 = t_sh7706lan_iomem_read_region_2,
    293 	.bs_rr_4 = t_sh7706lan_iomem_read_region_4,
    294 
    295 	.bs_rs_1 = t_sh7706lan_iomem_read_1,
    296 	.bs_rs_2 = t_sh7706lan_iomem_read_2,
    297 	.bs_rs_4 = t_sh7706lan_iomem_read_4,
    298 
    299 	.bs_rms_1 = t_sh7706lan_iomem_read_multi_1,
    300 	.bs_rms_2 = t_sh7706lan_iomem_read_multi_2,
    301 	.bs_rms_4 = t_sh7706lan_iomem_read_multi_4,
    302 
    303 	.bs_rrs_1 = t_sh7706lan_iomem_read_region_1,
    304 	.bs_rrs_2 = t_sh7706lan_iomem_read_region_2,
    305 	.bs_rrs_4 = t_sh7706lan_iomem_read_region_4,
    306 
    307 	.bs_w_1 = t_sh7706lan_iomem_write_1,
    308 	.bs_w_2 = t_sh7706lan_iomem_write_2,
    309 	.bs_w_4 = t_sh7706lan_iomem_write_4,
    310 
    311 	.bs_wm_1 = t_sh7706lan_iomem_write_multi_1,
    312 	.bs_wm_2 = t_sh7706lan_iomem_write_multi_2,
    313 	.bs_wm_4 = t_sh7706lan_iomem_write_multi_4,
    314 
    315 	.bs_wr_1 = t_sh7706lan_iomem_write_region_1,
    316 	.bs_wr_2 = t_sh7706lan_iomem_write_region_2,
    317 	.bs_wr_4 = t_sh7706lan_iomem_write_region_4,
    318 
    319 	.bs_ws_1 = t_sh7706lan_iomem_write_1,
    320 	.bs_ws_2 = t_sh7706lan_iomem_write_2,
    321 	.bs_ws_4 = t_sh7706lan_iomem_write_4,
    322 
    323 	.bs_wms_1 = t_sh7706lan_iomem_write_multi_1,
    324 	.bs_wms_2 = t_sh7706lan_iomem_write_multi_2,
    325 	.bs_wms_4 = t_sh7706lan_iomem_write_multi_4,
    326 
    327 	.bs_wrs_1 = t_sh7706lan_iomem_write_region_1,
    328 	.bs_wrs_2 = t_sh7706lan_iomem_write_region_2,
    329 	.bs_wrs_4 = t_sh7706lan_iomem_write_region_4,
    330 
    331 	.bs_sm_1 = t_sh7706lan_iomem_set_multi_1,
    332 	.bs_sm_2 = t_sh7706lan_iomem_set_multi_2,
    333 	.bs_sm_4 = t_sh7706lan_iomem_set_multi_4,
    334 
    335 	.bs_sr_1 = t_sh7706lan_iomem_set_region_1,
    336 	.bs_sr_2 = t_sh7706lan_iomem_set_region_2,
    337 	.bs_sr_4 = t_sh7706lan_iomem_set_region_4,
    338 
    339 	.bs_c_1 = t_sh7706lan_iomem_copy_region_1,
    340 	.bs_c_2 = t_sh7706lan_iomem_copy_region_2,
    341 	.bs_c_4 = t_sh7706lan_iomem_copy_region_4,
    342 };
    343 
    344 struct _bus_space t_sh7706lan_bus_mem =
    345 {
    346 	.bs_cookie = (void *)T_SH7706LAN_IOMEM_PCMCIA_MEM,
    347 
    348 	.bs_map = t_sh7706lan_iomem_map,
    349 	.bs_unmap = t_sh7706lan_iomem_unmap,
    350 	.bs_subregion = t_sh7706lan_iomem_subregion,
    351 
    352 	.bs_alloc = t_sh7706lan_iomem_alloc,
    353 	.bs_free = t_sh7706lan_iomem_free,
    354 
    355 	.bs_r_1 = t_sh7706lan_iomem_read_1,
    356 	.bs_r_2 = t_sh7706lan_iomem_read_2,
    357 	.bs_r_4 = t_sh7706lan_iomem_read_4,
    358 
    359 	.bs_rm_1 = t_sh7706lan_iomem_read_multi_1,
    360 	.bs_rm_2 = t_sh7706lan_iomem_read_multi_2,
    361 	.bs_rm_4 = t_sh7706lan_iomem_read_multi_4,
    362 
    363 	.bs_rr_1 = t_sh7706lan_iomem_read_region_1,
    364 	.bs_rr_2 = t_sh7706lan_iomem_read_region_2,
    365 	.bs_rr_4 = t_sh7706lan_iomem_read_region_4,
    366 
    367 	.bs_rs_1 = t_sh7706lan_iomem_read_1,
    368 	.bs_rs_2 = t_sh7706lan_iomem_read_2,
    369 	.bs_rs_4 = t_sh7706lan_iomem_read_4,
    370 
    371 	.bs_rms_1 = t_sh7706lan_iomem_read_multi_1,
    372 	.bs_rms_2 = t_sh7706lan_iomem_read_multi_2,
    373 	.bs_rms_4 = t_sh7706lan_iomem_read_multi_4,
    374 
    375 	.bs_rrs_1 = t_sh7706lan_iomem_read_region_1,
    376 	.bs_rrs_2 = t_sh7706lan_iomem_read_region_2,
    377 	.bs_rrs_4 = t_sh7706lan_iomem_read_region_4,
    378 
    379 	.bs_w_1 = t_sh7706lan_iomem_write_1,
    380 	.bs_w_2 = t_sh7706lan_iomem_write_2,
    381 	.bs_w_4 = t_sh7706lan_iomem_write_4,
    382 
    383 	.bs_wm_1 = t_sh7706lan_iomem_write_multi_1,
    384 	.bs_wm_2 = t_sh7706lan_iomem_write_multi_2,
    385 	.bs_wm_4 = t_sh7706lan_iomem_write_multi_4,
    386 
    387 	.bs_wr_1 = t_sh7706lan_iomem_write_region_1,
    388 	.bs_wr_2 = t_sh7706lan_iomem_write_region_2,
    389 	.bs_wr_4 = t_sh7706lan_iomem_write_region_4,
    390 
    391 	.bs_ws_1 = t_sh7706lan_iomem_write_1,
    392 	.bs_ws_2 = t_sh7706lan_iomem_write_2,
    393 	.bs_ws_4 = t_sh7706lan_iomem_write_4,
    394 
    395 	.bs_wms_1 = t_sh7706lan_iomem_write_multi_1,
    396 	.bs_wms_2 = t_sh7706lan_iomem_write_multi_2,
    397 	.bs_wms_4 = t_sh7706lan_iomem_write_multi_4,
    398 
    399 	.bs_wrs_1 = t_sh7706lan_iomem_write_region_1,
    400 	.bs_wrs_2 = t_sh7706lan_iomem_write_region_2,
    401 	.bs_wrs_4 = t_sh7706lan_iomem_write_region_4,
    402 
    403 	.bs_sm_1 = t_sh7706lan_iomem_set_multi_1,
    404 	.bs_sm_2 = t_sh7706lan_iomem_set_multi_2,
    405 	.bs_sm_4 = t_sh7706lan_iomem_set_multi_4,
    406 
    407 	.bs_sr_1 = t_sh7706lan_iomem_set_region_1,
    408 	.bs_sr_2 = t_sh7706lan_iomem_set_region_2,
    409 	.bs_sr_4 = t_sh7706lan_iomem_set_region_4,
    410 
    411 	.bs_c_1 = t_sh7706lan_iomem_copy_region_1,
    412 	.bs_c_2 = t_sh7706lan_iomem_copy_region_2,
    413 	.bs_c_4 = t_sh7706lan_iomem_copy_region_4,
    414 };
    415 
    416 /* read */
    417 uint8_t
    418 t_sh7706lan_iomem_read_1(void *v, bus_space_handle_t bsh, bus_size_t offset)
    419 {
    420 
    421 	return *(volatile uint8_t *)(bsh + offset);
    422 }
    423 
    424 uint16_t
    425 t_sh7706lan_iomem_read_2(void *v, bus_space_handle_t bsh, bus_size_t offset)
    426 {
    427 
    428 	return (*(volatile uint8_t *)(bsh + offset)) |
    429 	    (((uint16_t)*(volatile uint8_t *)(bsh + offset + 1)) << 8);
    430 }
    431 
    432 uint32_t
    433 t_sh7706lan_iomem_read_4(void *v, bus_space_handle_t bsh, bus_size_t offset)
    434 {
    435 
    436 	return (*(volatile uint8_t *)(bsh + offset)) |
    437 	    (((uint32_t)*(volatile uint8_t *)(bsh + offset + 1)) << 8) |
    438 	    (((uint32_t)*(volatile uint8_t *)(bsh + offset + 2)) << 16) |
    439 	    (((uint32_t)*(volatile uint8_t *)(bsh + offset + 3)) << 24);
    440 }
    441 
    442 void
    443 t_sh7706lan_iomem_read_multi_1(void *v, bus_space_handle_t bsh,
    444     bus_size_t offset, uint8_t *addr, bus_size_t count)
    445 {
    446 	volatile uint8_t *p = (void *)(bsh + offset);
    447 
    448 	while (count--) {
    449 		*addr++ = *p;
    450 	}
    451 }
    452 
    453 void
    454 t_sh7706lan_iomem_read_multi_2(void *v, bus_space_handle_t bsh,
    455     bus_size_t offset, uint16_t *addr, bus_size_t count)
    456 {
    457 	volatile uint8_t *src = (void *)(bsh + offset);
    458 	volatile uint8_t *dest = (void *)addr;
    459 
    460 	while (count--) {
    461 		*dest++ = src[0];
    462 		*dest++ = src[1];
    463 	}
    464 }
    465 
    466 void
    467 t_sh7706lan_iomem_read_multi_4(void *v, bus_space_handle_t bsh,
    468     bus_size_t offset, uint32_t *addr, bus_size_t count)
    469 {
    470 	volatile uint8_t *src = (void *)(bsh + offset);
    471 	volatile uint8_t *dest = (void *)addr;
    472 
    473 	while (count--) {
    474 		*dest++ = src[0];
    475 		*dest++ = src[1];
    476 		*dest++ = src[2];
    477 		*dest++ = src[3];
    478 	}
    479 }
    480 
    481 void
    482 t_sh7706lan_iomem_read_region_1(void *v, bus_space_handle_t bsh,
    483     bus_size_t offset, uint8_t *addr, bus_size_t count)
    484 {
    485 	volatile uint8_t *p = (void *)(bsh + offset);
    486 
    487 	while (count--) {
    488 		*addr++ = *p++;
    489 	}
    490 }
    491 
    492 void
    493 t_sh7706lan_iomem_read_region_2(void *v, bus_space_handle_t bsh,
    494     bus_size_t offset, uint16_t *addr, bus_size_t count)
    495 {
    496 
    497 	t_sh7706lan_iomem_read_region_1(v, bsh, offset, (void *)addr, count * 2);
    498 }
    499 
    500 void
    501 t_sh7706lan_iomem_read_region_4(void *v, bus_space_handle_t bsh,
    502     bus_size_t offset, uint32_t *addr, bus_size_t count)
    503 {
    504 
    505 	t_sh7706lan_iomem_read_region_1(v, bsh, offset, (void *)addr, count * 4);
    506 }
    507 
    508 /* write */
    509 void
    510 t_sh7706lan_iomem_write_1(void *v, bus_space_handle_t bsh, bus_size_t offset,
    511     uint8_t value)
    512 {
    513 
    514 	*(volatile uint8_t *)(bsh + offset) = value;
    515 }
    516 
    517 void
    518 t_sh7706lan_iomem_write_2(void *v, bus_space_handle_t bsh, bus_size_t offset,
    519     uint16_t value)
    520 {
    521 
    522 	*(volatile uint8_t *)(bsh + offset) = value & 0xff;
    523 	*(volatile uint8_t *)(bsh + offset + 1) = (value >> 8) & 0xff;
    524 }
    525 
    526 void
    527 t_sh7706lan_iomem_write_4(void *v, bus_space_handle_t bsh, bus_size_t offset,
    528     uint32_t value)
    529 {
    530 
    531 	*(volatile uint8_t *)(bsh + offset) = value & 0xff;
    532 	*(volatile uint8_t *)(bsh + offset + 1) = (value >> 8) & 0xff;
    533 	*(volatile uint8_t *)(bsh + offset + 2) = (value >> 16) & 0xff;
    534 	*(volatile uint8_t *)(bsh + offset + 3) = (value >> 24) & 0xff;
    535 }
    536 
    537 void
    538 t_sh7706lan_iomem_write_multi_1(void *v, bus_space_handle_t bsh,
    539     bus_size_t offset, const uint8_t *addr, bus_size_t count)
    540 {
    541 	volatile uint8_t *p = (void *)(bsh + offset);
    542 
    543 	while (count--) {
    544 		*p = *addr++;
    545 	}
    546 }
    547 
    548 void
    549 t_sh7706lan_iomem_write_multi_2(void *v, bus_space_handle_t bsh,
    550     bus_size_t offset, const uint16_t *addr, bus_size_t count)
    551 {
    552 	volatile uint8_t *dest = (void *)(bsh + offset);
    553 	volatile const uint8_t *src = (const void *)addr;
    554 
    555 	while (count--) {
    556 		dest[0] = *src++;
    557 		dest[1] = *src++;
    558 	}
    559 }
    560 
    561 void
    562 t_sh7706lan_iomem_write_multi_4(void *v, bus_space_handle_t bsh,
    563     bus_size_t offset, const uint32_t *addr, bus_size_t count)
    564 {
    565 	volatile uint8_t *dest = (void *)(bsh + offset);
    566 	volatile const uint8_t *src = (const void *)addr;
    567 
    568 	while (count--) {
    569 		dest[0] = *src++;
    570 		dest[1] = *src++;
    571 		dest[2] = *src++;
    572 		dest[3] = *src++;
    573 	}
    574 }
    575 
    576 void
    577 t_sh7706lan_iomem_write_region_1(void *v, bus_space_handle_t bsh,
    578     bus_size_t offset, const uint8_t *addr, bus_size_t count)
    579 {
    580 	volatile uint8_t *p = (void *)(bsh + offset);
    581 
    582 	while (count--) {
    583 		*p++ = *addr++;
    584 	}
    585 }
    586 
    587 void
    588 t_sh7706lan_iomem_write_region_2(void *v, bus_space_handle_t bsh,
    589     bus_size_t offset, const uint16_t *addr, bus_size_t count)
    590 {
    591 
    592 	t_sh7706lan_iomem_write_region_1(v, bsh, offset, (const void*)addr, count * 2);
    593 }
    594 
    595 void
    596 t_sh7706lan_iomem_write_region_4(void *v, bus_space_handle_t bsh,
    597     bus_size_t offset, const uint32_t *addr, bus_size_t count)
    598 {
    599 
    600 	t_sh7706lan_iomem_write_region_1(v, bsh, offset, (const void*)addr, count * 4);
    601 }
    602 
    603 void
    604 t_sh7706lan_iomem_set_multi_1(void *v, bus_space_handle_t bsh,
    605     bus_size_t offset, uint8_t val, bus_size_t count)
    606 {
    607 	volatile uint8_t *p = (void *)(bsh + offset);
    608 
    609 	while (count--) {
    610 		*p = val;
    611 	}
    612 }
    613 
    614 void
    615 t_sh7706lan_iomem_set_multi_2(void *v, bus_space_handle_t bsh,
    616     bus_size_t offset, uint16_t val, bus_size_t count)
    617 {
    618 	volatile uint8_t *dest = (void *)(bsh + offset);
    619 	uint8_t src[2];
    620 
    621 	src[0] = val & 0xff;
    622 	src[1] = (val >> 8) & 0xff;
    623 
    624 	while (count--) {
    625 		dest[0] = src[0];
    626 		dest[1] = src[1];
    627 	}
    628 }
    629 
    630 void
    631 t_sh7706lan_iomem_set_multi_4(void *v, bus_space_handle_t bsh,
    632     bus_size_t offset, uint32_t val, bus_size_t count)
    633 {
    634 	volatile uint8_t *dest = (void *)(bsh + offset);
    635 	uint8_t src[4];
    636 
    637 	src[0] = val & 0xff;
    638 	src[1] = (val >> 8) & 0xff;
    639 	src[2] = (val >> 16) & 0xff;
    640 	src[3] = (val >> 24) & 0xff;
    641 
    642 	while (count--) {
    643 		dest[0] = src[0];
    644 		dest[1] = src[1];
    645 		dest[2] = src[2];
    646 		dest[3] = src[3];
    647 	}
    648 }
    649 
    650 void
    651 t_sh7706lan_iomem_set_region_1(void *v, bus_space_handle_t bsh,
    652     bus_size_t offset, uint8_t val, bus_size_t count)
    653 {
    654 	volatile uint8_t *addr = (void *)(bsh + offset);
    655 
    656 	while (count--) {
    657 		*addr++ = val;
    658 	}
    659 }
    660 
    661 void
    662 t_sh7706lan_iomem_set_region_2(void *v, bus_space_handle_t bsh,
    663     bus_size_t offset, uint16_t val, bus_size_t count)
    664 {
    665 	volatile uint8_t *dest = (void *)(bsh + offset);
    666 	uint8_t src[2];
    667 
    668 	src[0] = val & 0xff;
    669 	src[1] = (val >> 8) & 0xff;
    670 
    671 	while (count--) {
    672 		*dest++ = src[0];
    673 		*dest++ = src[1];
    674 	}
    675 }
    676 
    677 void
    678 t_sh7706lan_iomem_set_region_4(void *v, bus_space_handle_t bsh,
    679     bus_size_t offset, uint32_t val, bus_size_t count)
    680 {
    681 	volatile uint8_t *dest = (void *)(bsh + offset);
    682 	uint8_t src[4];
    683 
    684 	src[0] = val & 0xff;
    685 	src[1] = (val >> 8) & 0xff;
    686 	src[2] = (val >> 16) & 0xff;
    687 	src[3] = (val >> 24) & 0xff;
    688 
    689 	while (count--) {
    690 		*dest++ = src[0];
    691 		*dest++ = src[1];
    692 		*dest++ = src[2];
    693 		*dest++ = src[3];
    694 	}
    695 }
    696 
    697 void
    698 t_sh7706lan_iomem_copy_region_1(void *v, bus_space_handle_t h1, bus_size_t o1,
    699     bus_space_handle_t h2, bus_size_t o2, bus_size_t count)
    700 {
    701 	volatile uint8_t *addr1 = (void *)(h1 + o1);
    702 	volatile uint8_t *addr2 = (void *)(h2 + o2);
    703 
    704 	if (addr1 >= addr2) {	/* src after dest: copy forward */
    705 		while (count--) {
    706 			*addr2++ = *addr1++;
    707 		}
    708 	} else {		/* dest after src: copy backwards */
    709 		addr1 += count - 1;
    710 		addr2 += count - 1;
    711 		while (count--) {
    712 			*addr2-- = *addr1--;
    713 		}
    714 	}
    715 }
    716 
    717 void
    718 t_sh7706lan_iomem_copy_region_2(void *v, bus_space_handle_t h1, bus_size_t o1,
    719     bus_space_handle_t h2, bus_size_t o2, bus_size_t count)
    720 {
    721 
    722 	t_sh7706lan_iomem_copy_region_1(v, h1, o1, h2, o2, count * 2);
    723 }
    724 
    725 void
    726 t_sh7706lan_iomem_copy_region_4(void *v, bus_space_handle_t h1, bus_size_t o1,
    727     bus_space_handle_t h2, bus_size_t o2, bus_size_t count)
    728 {
    729 
    730 	t_sh7706lan_iomem_copy_region_1(v, h1, o1, h2, o2, count * 4);
    731 }
    732