Home | History | Annotate | Line # | Download | only in tc
tc_bus_mem.c revision 1.26
      1 /* $NetBSD: tc_bus_mem.c,v 1.26 2005/06/08 22:38:16 he Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1996 Carnegie-Mellon University.
      5  * All rights reserved.
      6  *
      7  * Author: Chris G. Demetriou
      8  *
      9  * Permission to use, copy, modify and distribute this software and
     10  * its documentation is hereby granted, provided that both the copyright
     11  * notice and this permission notice appear in all copies of the
     12  * software, derivative works or modified versions, and any portions
     13  * thereof, and that both notices appear in supporting documentation.
     14  *
     15  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     16  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
     17  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     18  *
     19  * Carnegie Mellon requests users of this software to return to
     20  *
     21  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     22  *  School of Computer Science
     23  *  Carnegie Mellon University
     24  *  Pittsburgh PA 15213-3890
     25  *
     26  * any improvements or extensions that they make and grant Carnegie the
     27  * rights to redistribute these changes.
     28  */
     29 
     30 /*
     31  * Common TurboChannel Chipset "bus memory" functions.
     32  */
     33 
     34 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
     35 
     36 __KERNEL_RCSID(0, "$NetBSD: tc_bus_mem.c,v 1.26 2005/06/08 22:38:16 he Exp $");
     37 
     38 #include <sys/param.h>
     39 #include <sys/systm.h>
     40 #include <sys/malloc.h>
     41 #include <sys/syslog.h>
     42 #include <sys/device.h>
     43 
     44 #include <uvm/uvm_extern.h>
     45 
     46 #include <machine/bus.h>
     47 #include <dev/tc/tcvar.h>
     48 
     49 #define	__C(A,B)	__CONCAT(A,B)
     50 
     51 /* mapping/unmapping */
     52 int		tc_mem_map __P((void *, bus_addr_t, bus_size_t, int,
     53 		    bus_space_handle_t *, int));
     54 void		tc_mem_unmap __P((void *, bus_space_handle_t, bus_size_t, int));
     55 int		tc_mem_subregion __P((void *, bus_space_handle_t, bus_size_t,
     56 		    bus_size_t, bus_space_handle_t *));
     57 
     58 int		tc_mem_translate __P((void *, bus_addr_t, bus_size_t,
     59 		    int, struct alpha_bus_space_translation *));
     60 int		tc_mem_get_window __P((void *, int,
     61 		    struct alpha_bus_space_translation *));
     62 
     63 /* allocation/deallocation */
     64 int		tc_mem_alloc __P((void *, bus_addr_t, bus_addr_t, bus_size_t,
     65 		    bus_size_t, bus_addr_t, int, bus_addr_t *,
     66 		    bus_space_handle_t *));
     67 void		tc_mem_free __P((void *, bus_space_handle_t, bus_size_t));
     68 
     69 /* get kernel virtual address */
     70 void *		tc_mem_vaddr __P((void *, bus_space_handle_t));
     71 
     72 /* mmap for user */
     73 paddr_t		tc_mem_mmap __P((void *, bus_addr_t, off_t, int, int));
     74 
     75 /* barrier */
     76 inline void	tc_mem_barrier __P((void *, bus_space_handle_t,
     77 		    bus_size_t, bus_size_t, int));
     78 
     79 /* read (single) */
     80 inline u_int8_t	tc_mem_read_1 __P((void *, bus_space_handle_t, bus_size_t));
     81 inline u_int16_t tc_mem_read_2 __P((void *, bus_space_handle_t, bus_size_t));
     82 inline u_int32_t tc_mem_read_4 __P((void *, bus_space_handle_t, bus_size_t));
     83 inline u_int64_t tc_mem_read_8 __P((void *, bus_space_handle_t, bus_size_t));
     84 
     85 /* read multiple */
     86 void		tc_mem_read_multi_1 __P((void *, bus_space_handle_t,
     87 		    bus_size_t, u_int8_t *, bus_size_t));
     88 void		tc_mem_read_multi_2 __P((void *, bus_space_handle_t,
     89 		    bus_size_t, u_int16_t *, bus_size_t));
     90 void		tc_mem_read_multi_4 __P((void *, bus_space_handle_t,
     91 		    bus_size_t, u_int32_t *, bus_size_t));
     92 void		tc_mem_read_multi_8 __P((void *, bus_space_handle_t,
     93 		    bus_size_t, u_int64_t *, bus_size_t));
     94 
     95 /* read region */
     96 void		tc_mem_read_region_1 __P((void *, bus_space_handle_t,
     97 		    bus_size_t, u_int8_t *, bus_size_t));
     98 void		tc_mem_read_region_2 __P((void *, bus_space_handle_t,
     99 		    bus_size_t, u_int16_t *, bus_size_t));
    100 void		tc_mem_read_region_4 __P((void *, bus_space_handle_t,
    101 		    bus_size_t, u_int32_t *, bus_size_t));
    102 void		tc_mem_read_region_8 __P((void *, bus_space_handle_t,
    103 		    bus_size_t, u_int64_t *, bus_size_t));
    104 
    105 /* write (single) */
    106 inline void	tc_mem_write_1 __P((void *, bus_space_handle_t, bus_size_t,
    107 		    u_int8_t));
    108 inline void	tc_mem_write_2 __P((void *, bus_space_handle_t, bus_size_t,
    109 		    u_int16_t));
    110 inline void	tc_mem_write_4 __P((void *, bus_space_handle_t, bus_size_t,
    111 		    u_int32_t));
    112 inline void	tc_mem_write_8 __P((void *, bus_space_handle_t, bus_size_t,
    113 		    u_int64_t));
    114 
    115 /* write multiple */
    116 void		tc_mem_write_multi_1 __P((void *, bus_space_handle_t,
    117 		    bus_size_t, const u_int8_t *, bus_size_t));
    118 void		tc_mem_write_multi_2 __P((void *, bus_space_handle_t,
    119 		    bus_size_t, const u_int16_t *, bus_size_t));
    120 void		tc_mem_write_multi_4 __P((void *, bus_space_handle_t,
    121 		    bus_size_t, const u_int32_t *, bus_size_t));
    122 void		tc_mem_write_multi_8 __P((void *, bus_space_handle_t,
    123 		    bus_size_t, const u_int64_t *, bus_size_t));
    124 
    125 /* write region */
    126 void		tc_mem_write_region_1 __P((void *, bus_space_handle_t,
    127 		    bus_size_t, const u_int8_t *, bus_size_t));
    128 void		tc_mem_write_region_2 __P((void *, bus_space_handle_t,
    129 		    bus_size_t, const u_int16_t *, bus_size_t));
    130 void		tc_mem_write_region_4 __P((void *, bus_space_handle_t,
    131 		    bus_size_t, const u_int32_t *, bus_size_t));
    132 void		tc_mem_write_region_8 __P((void *, bus_space_handle_t,
    133 		    bus_size_t, const u_int64_t *, bus_size_t));
    134 
    135 /* set multiple */
    136 void		tc_mem_set_multi_1 __P((void *, bus_space_handle_t,
    137 		    bus_size_t, u_int8_t, bus_size_t));
    138 void		tc_mem_set_multi_2 __P((void *, bus_space_handle_t,
    139 		    bus_size_t, u_int16_t, bus_size_t));
    140 void		tc_mem_set_multi_4 __P((void *, bus_space_handle_t,
    141 		    bus_size_t, u_int32_t, bus_size_t));
    142 void		tc_mem_set_multi_8 __P((void *, bus_space_handle_t,
    143 		    bus_size_t, u_int64_t, bus_size_t));
    144 
    145 /* set region */
    146 void		tc_mem_set_region_1 __P((void *, bus_space_handle_t,
    147 		    bus_size_t, u_int8_t, bus_size_t));
    148 void		tc_mem_set_region_2 __P((void *, bus_space_handle_t,
    149 		    bus_size_t, u_int16_t, bus_size_t));
    150 void		tc_mem_set_region_4 __P((void *, bus_space_handle_t,
    151 		    bus_size_t, u_int32_t, bus_size_t));
    152 void		tc_mem_set_region_8 __P((void *, bus_space_handle_t,
    153 		    bus_size_t, u_int64_t, bus_size_t));
    154 
    155 /* copy */
    156 void		tc_mem_copy_region_1 __P((void *, bus_space_handle_t,
    157 		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t));
    158 void		tc_mem_copy_region_2 __P((void *, bus_space_handle_t,
    159 		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t));
    160 void		tc_mem_copy_region_4 __P((void *, bus_space_handle_t,
    161 		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t));
    162 void		tc_mem_copy_region_8 __P((void *, bus_space_handle_t,
    163 		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t));
    164 
    165 static struct alpha_bus_space tc_mem_space = {
    166 	/* cookie */
    167 	NULL,
    168 
    169 	/* mapping/unmapping */
    170 	tc_mem_map,
    171 	tc_mem_unmap,
    172 	tc_mem_subregion,
    173 
    174 	tc_mem_translate,
    175 	tc_mem_get_window,
    176 
    177 	/* allocation/deallocation */
    178 	tc_mem_alloc,
    179 	tc_mem_free,
    180 
    181 	/* get kernel virtual address */
    182 	tc_mem_vaddr,
    183 
    184 	/* mmap for user */
    185 	tc_mem_mmap,
    186 
    187 	/* barrier */
    188 	tc_mem_barrier,
    189 
    190 	/* read (single) */
    191 	tc_mem_read_1,
    192 	tc_mem_read_2,
    193 	tc_mem_read_4,
    194 	tc_mem_read_8,
    195 
    196 	/* read multiple */
    197 	tc_mem_read_multi_1,
    198 	tc_mem_read_multi_2,
    199 	tc_mem_read_multi_4,
    200 	tc_mem_read_multi_8,
    201 
    202 	/* read region */
    203 	tc_mem_read_region_1,
    204 	tc_mem_read_region_2,
    205 	tc_mem_read_region_4,
    206 	tc_mem_read_region_8,
    207 
    208 	/* write (single) */
    209 	tc_mem_write_1,
    210 	tc_mem_write_2,
    211 	tc_mem_write_4,
    212 	tc_mem_write_8,
    213 
    214 	/* write multiple */
    215 	tc_mem_write_multi_1,
    216 	tc_mem_write_multi_2,
    217 	tc_mem_write_multi_4,
    218 	tc_mem_write_multi_8,
    219 
    220 	/* write region */
    221 	tc_mem_write_region_1,
    222 	tc_mem_write_region_2,
    223 	tc_mem_write_region_4,
    224 	tc_mem_write_region_8,
    225 
    226 	/* set multiple */
    227 	tc_mem_set_multi_1,
    228 	tc_mem_set_multi_2,
    229 	tc_mem_set_multi_4,
    230 	tc_mem_set_multi_8,
    231 
    232 	/* set region */
    233 	tc_mem_set_region_1,
    234 	tc_mem_set_region_2,
    235 	tc_mem_set_region_4,
    236 	tc_mem_set_region_8,
    237 
    238 	/* copy */
    239 	tc_mem_copy_region_1,
    240 	tc_mem_copy_region_2,
    241 	tc_mem_copy_region_4,
    242 	tc_mem_copy_region_8,
    243 };
    244 
    245 bus_space_tag_t
    246 tc_bus_mem_init(memv)
    247 	void *memv;
    248 {
    249 	bus_space_tag_t h = &tc_mem_space;
    250 
    251 	h->abs_cookie = memv;
    252 	return (h);
    253 }
    254 
    255 /* ARGSUSED */
    256 int
    257 tc_mem_translate(v, memaddr, memlen, flags, abst)
    258 	void *v;
    259 	bus_addr_t memaddr;
    260 	bus_size_t memlen;
    261 	int flags;
    262 	struct alpha_bus_space_translation *abst;
    263 {
    264 
    265 	return (EOPNOTSUPP);
    266 }
    267 
    268 /* ARGSUSED */
    269 int
    270 tc_mem_get_window(v, window, abst)
    271 	void *v;
    272 	int window;
    273 	struct alpha_bus_space_translation *abst;
    274 {
    275 
    276 	return (EOPNOTSUPP);
    277 }
    278 
    279 /* ARGSUSED */
    280 int
    281 tc_mem_map(v, memaddr, memsize, flags, memhp, acct)
    282 	void *v;
    283 	bus_addr_t memaddr;
    284 	bus_size_t memsize;
    285 	int flags;
    286 	bus_space_handle_t *memhp;
    287 	int acct;
    288 {
    289 	int cacheable = flags & BUS_SPACE_MAP_CACHEABLE;
    290 	int linear = flags & BUS_SPACE_MAP_LINEAR;
    291 
    292 	/* Requests for linear uncacheable space can't be satisfied. */
    293 	if (linear && !cacheable)
    294 		return (EOPNOTSUPP);
    295 
    296 	if (memaddr & 0x7)
    297 		panic("tc_mem_map needs 8 byte alignment");
    298 	if (cacheable)
    299 		*memhp = ALPHA_PHYS_TO_K0SEG(memaddr);
    300 	else
    301 		*memhp = ALPHA_PHYS_TO_K0SEG(TC_DENSE_TO_SPARSE(memaddr));
    302 	return (0);
    303 }
    304 
    305 /* ARGSUSED */
    306 void
    307 tc_mem_unmap(v, memh, memsize, acct)
    308 	void *v;
    309 	bus_space_handle_t memh;
    310 	bus_size_t memsize;
    311 	int acct;
    312 {
    313 
    314 	/* XXX XX XXX nothing to do. */
    315 }
    316 
    317 int
    318 tc_mem_subregion(v, memh, offset, size, nmemh)
    319 	void *v;
    320 	bus_space_handle_t memh, *nmemh;
    321 	bus_size_t offset, size;
    322 {
    323 
    324 	/* Disallow subregioning that would make the handle unaligned. */
    325 	if ((offset & 0x7) != 0)
    326 		return (1);
    327 
    328 	if ((memh & TC_SPACE_SPARSE) != 0)
    329 		*nmemh = memh + (offset << 1);
    330 	else
    331 		*nmemh = memh + offset;
    332 
    333 	return (0);
    334 }
    335 
    336 int
    337 tc_mem_alloc(v, rstart, rend, size, align, boundary, flags, addrp, bshp)
    338 	void *v;
    339 	bus_addr_t rstart, rend, *addrp;
    340 	bus_size_t size, align, boundary;
    341 	int flags;
    342 	bus_space_handle_t *bshp;
    343 {
    344 
    345 	/* XXX XXX XXX XXX XXX XXX */
    346 	panic("tc_mem_alloc unimplemented");
    347 }
    348 
    349 void
    350 tc_mem_free(v, bsh, size)
    351 	void *v;
    352 	bus_space_handle_t bsh;
    353 	bus_size_t size;
    354 {
    355 
    356 	/* XXX XXX XXX XXX XXX XXX */
    357 	panic("tc_mem_free unimplemented");
    358 }
    359 
    360 void *
    361 tc_mem_vaddr(v, bsh)
    362 	void *v;
    363 	bus_space_handle_t bsh;
    364 {
    365 #ifdef DIAGNOSTIC
    366 	if ((bsh & TC_SPACE_SPARSE) != 0) {
    367 		/*
    368 		 * tc_mem_map() catches linear && !cacheable,
    369 		 * so we shouldn't come here
    370 		 */
    371 		panic("tc_mem_vaddr");
    372 	}
    373 #endif
    374 	return ((void *)bsh);
    375 }
    376 
    377 paddr_t
    378 tc_mem_mmap(v, addr, off, prot, flags)
    379 	void *v;
    380 	bus_addr_t addr;
    381 	off_t off;
    382 	int prot;
    383 	int flags;
    384 {
    385 	int linear = flags & BUS_SPACE_MAP_LINEAR;
    386 	bus_addr_t rv;
    387 
    388 	if (linear)
    389 		rv = addr + off;
    390 	else
    391 		rv = TC_DENSE_TO_SPARSE(addr + off);
    392 
    393 	return (alpha_btop(rv));
    394 }
    395 
    396 inline void
    397 tc_mem_barrier(v, h, o, l, f)
    398 	void *v;
    399 	bus_space_handle_t h;
    400 	bus_size_t o, l;
    401 	int f;
    402 {
    403 
    404 	if ((f & BUS_SPACE_BARRIER_READ) != 0)
    405 		alpha_mb();
    406 	else if ((f & BUS_SPACE_BARRIER_WRITE) != 0)
    407 		alpha_wmb();
    408 }
    409 
    410 inline u_int8_t
    411 tc_mem_read_1(v, memh, off)
    412 	void *v;
    413 	bus_space_handle_t memh;
    414 	bus_size_t off;
    415 {
    416 	volatile u_int8_t *p;
    417 
    418 	alpha_mb();		/* XXX XXX XXX */
    419 
    420 	if ((memh & TC_SPACE_SPARSE) != 0)
    421 		panic("tc_mem_read_1 not implemented for sparse space");
    422 
    423 	p = (u_int8_t *)(memh + off);
    424 	return (*p);
    425 }
    426 
    427 inline u_int16_t
    428 tc_mem_read_2(v, memh, off)
    429 	void *v;
    430 	bus_space_handle_t memh;
    431 	bus_size_t off;
    432 {
    433 	volatile u_int16_t *p;
    434 
    435 	alpha_mb();		/* XXX XXX XXX */
    436 
    437 	if ((memh & TC_SPACE_SPARSE) != 0)
    438 		panic("tc_mem_read_2 not implemented for sparse space");
    439 
    440 	p = (u_int16_t *)(memh + off);
    441 	return (*p);
    442 }
    443 
    444 inline u_int32_t
    445 tc_mem_read_4(v, memh, off)
    446 	void *v;
    447 	bus_space_handle_t memh;
    448 	bus_size_t off;
    449 {
    450 	volatile u_int32_t *p;
    451 
    452 	alpha_mb();		/* XXX XXX XXX */
    453 
    454 	if ((memh & TC_SPACE_SPARSE) != 0)
    455 		/* Nothing special to do for 4-byte sparse space accesses */
    456 		p = (u_int32_t *)(memh + (off << 1));
    457 	else
    458 		p = (u_int32_t *)(memh + off);
    459 	return (*p);
    460 }
    461 
    462 inline u_int64_t
    463 tc_mem_read_8(v, memh, off)
    464 	void *v;
    465 	bus_space_handle_t memh;
    466 	bus_size_t off;
    467 {
    468 	volatile u_int64_t *p;
    469 
    470 	alpha_mb();		/* XXX XXX XXX */
    471 
    472 	if ((memh & TC_SPACE_SPARSE) != 0)
    473 		panic("tc_mem_read_8 not implemented for sparse space");
    474 
    475 	p = (u_int64_t *)(memh + off);
    476 	return (*p);
    477 }
    478 
    479 #define	tc_mem_read_multi_N(BYTES,TYPE)					\
    480 void									\
    481 __C(tc_mem_read_multi_,BYTES)(v, h, o, a, c)				\
    482 	void *v;							\
    483 	bus_space_handle_t h;						\
    484 	bus_size_t o, c;						\
    485 	TYPE *a;							\
    486 {									\
    487 									\
    488 	while (c-- > 0) {						\
    489 		tc_mem_barrier(v, h, o, sizeof *a, BUS_SPACE_BARRIER_READ); \
    490 		*a++ = __C(tc_mem_read_,BYTES)(v, h, o);		\
    491 	}								\
    492 }
    493 tc_mem_read_multi_N(1,u_int8_t)
    494 tc_mem_read_multi_N(2,u_int16_t)
    495 tc_mem_read_multi_N(4,u_int32_t)
    496 tc_mem_read_multi_N(8,u_int64_t)
    497 
    498 #define	tc_mem_read_region_N(BYTES,TYPE)				\
    499 void									\
    500 __C(tc_mem_read_region_,BYTES)(v, h, o, a, c)				\
    501 	void *v;							\
    502 	bus_space_handle_t h;						\
    503 	bus_size_t o, c;						\
    504 	TYPE *a;							\
    505 {									\
    506 									\
    507 	while (c-- > 0) {						\
    508 		*a++ = __C(tc_mem_read_,BYTES)(v, h, o);		\
    509 		o += sizeof *a;						\
    510 	}								\
    511 }
    512 tc_mem_read_region_N(1,u_int8_t)
    513 tc_mem_read_region_N(2,u_int16_t)
    514 tc_mem_read_region_N(4,u_int32_t)
    515 tc_mem_read_region_N(8,u_int64_t)
    516 
    517 inline void
    518 tc_mem_write_1(v, memh, off, val)
    519 	void *v;
    520 	bus_space_handle_t memh;
    521 	bus_size_t off;
    522 	u_int8_t val;
    523 {
    524 
    525 	if ((memh & TC_SPACE_SPARSE) != 0) {
    526 		volatile u_int64_t *p, vl;
    527 		u_int64_t shift, msk;
    528 
    529 		shift = off & 0x3;
    530 		off &= 0x3;
    531 
    532 		p = (u_int64_t *)(memh + (off << 1));
    533 
    534 		msk = ~(0x1 << shift) & 0xf;
    535 		vl = (msk << 32) | (((u_int64_t)val) << (shift * 8));
    536 
    537 		*p = val;
    538 	} else {
    539 		volatile u_int8_t *p;
    540 
    541 		p = (u_int8_t *)(memh + off);
    542 		*p = val;
    543 	}
    544         alpha_mb();		/* XXX XXX XXX */
    545 }
    546 
    547 inline void
    548 tc_mem_write_2(v, memh, off, val)
    549 	void *v;
    550 	bus_space_handle_t memh;
    551 	bus_size_t off;
    552 	u_int16_t val;
    553 {
    554 
    555 	if ((memh & TC_SPACE_SPARSE) != 0) {
    556 		volatile u_int64_t *p, vl;
    557 		u_int64_t shift, msk;
    558 
    559 		shift = off & 0x2;
    560 		off &= 0x3;
    561 
    562 		p = (u_int64_t *)(memh + (off << 1));
    563 
    564 		msk = ~(0x3 << shift) & 0xf;
    565 		vl = (msk << 32) | (((u_int64_t)val) << (shift * 8));
    566 
    567 		*p = val;
    568 	} else {
    569 		volatile u_int16_t *p;
    570 
    571 		p = (u_int16_t *)(memh + off);
    572 		*p = val;
    573 	}
    574         alpha_mb();		/* XXX XXX XXX */
    575 }
    576 
    577 inline void
    578 tc_mem_write_4(v, memh, off, val)
    579 	void *v;
    580 	bus_space_handle_t memh;
    581 	bus_size_t off;
    582 	u_int32_t val;
    583 {
    584 	volatile u_int32_t *p;
    585 
    586 	if ((memh & TC_SPACE_SPARSE) != 0)
    587 		/* Nothing special to do for 4-byte sparse space accesses */
    588 		p = (u_int32_t *)(memh + (off << 1));
    589 	else
    590 		p = (u_int32_t *)(memh + off);
    591 	*p = val;
    592         alpha_mb();		/* XXX XXX XXX */
    593 }
    594 
    595 inline void
    596 tc_mem_write_8(v, memh, off, val)
    597 	void *v;
    598 	bus_space_handle_t memh;
    599 	bus_size_t off;
    600 	u_int64_t val;
    601 {
    602 	volatile u_int64_t *p;
    603 
    604 	if ((memh & TC_SPACE_SPARSE) != 0)
    605 		panic("tc_mem_read_8 not implemented for sparse space");
    606 
    607 	p = (u_int64_t *)(memh + off);
    608 	*p = val;
    609         alpha_mb();		/* XXX XXX XXX */
    610 }
    611 
    612 #define	tc_mem_write_multi_N(BYTES,TYPE)				\
    613 void									\
    614 __C(tc_mem_write_multi_,BYTES)(v, h, o, a, c)				\
    615 	void *v;							\
    616 	bus_space_handle_t h;						\
    617 	bus_size_t o, c;						\
    618 	const TYPE *a;							\
    619 {									\
    620 									\
    621 	while (c-- > 0) {						\
    622 		__C(tc_mem_write_,BYTES)(v, h, o, *a++);		\
    623 		tc_mem_barrier(v, h, o, sizeof *a, BUS_SPACE_BARRIER_WRITE); \
    624 	}								\
    625 }
    626 tc_mem_write_multi_N(1,u_int8_t)
    627 tc_mem_write_multi_N(2,u_int16_t)
    628 tc_mem_write_multi_N(4,u_int32_t)
    629 tc_mem_write_multi_N(8,u_int64_t)
    630 
    631 #define	tc_mem_write_region_N(BYTES,TYPE)				\
    632 void									\
    633 __C(tc_mem_write_region_,BYTES)(v, h, o, a, c)				\
    634 	void *v;							\
    635 	bus_space_handle_t h;						\
    636 	bus_size_t o, c;						\
    637 	const TYPE *a;							\
    638 {									\
    639 									\
    640 	while (c-- > 0) {						\
    641 		__C(tc_mem_write_,BYTES)(v, h, o, *a++);		\
    642 		o += sizeof *a;						\
    643 	}								\
    644 }
    645 tc_mem_write_region_N(1,u_int8_t)
    646 tc_mem_write_region_N(2,u_int16_t)
    647 tc_mem_write_region_N(4,u_int32_t)
    648 tc_mem_write_region_N(8,u_int64_t)
    649 
    650 #define	tc_mem_set_multi_N(BYTES,TYPE)					\
    651 void									\
    652 __C(tc_mem_set_multi_,BYTES)(v, h, o, val, c)				\
    653 	void *v;							\
    654 	bus_space_handle_t h;						\
    655 	bus_size_t o, c;						\
    656 	TYPE val;							\
    657 {									\
    658 									\
    659 	while (c-- > 0) {						\
    660 		__C(tc_mem_write_,BYTES)(v, h, o, val);			\
    661 		tc_mem_barrier(v, h, o, sizeof val, BUS_SPACE_BARRIER_WRITE); \
    662 	}								\
    663 }
    664 tc_mem_set_multi_N(1,u_int8_t)
    665 tc_mem_set_multi_N(2,u_int16_t)
    666 tc_mem_set_multi_N(4,u_int32_t)
    667 tc_mem_set_multi_N(8,u_int64_t)
    668 
    669 #define	tc_mem_set_region_N(BYTES,TYPE)					\
    670 void									\
    671 __C(tc_mem_set_region_,BYTES)(v, h, o, val, c)				\
    672 	void *v;							\
    673 	bus_space_handle_t h;						\
    674 	bus_size_t o, c;						\
    675 	TYPE val;							\
    676 {									\
    677 									\
    678 	while (c-- > 0) {						\
    679 		__C(tc_mem_write_,BYTES)(v, h, o, val);			\
    680 		o += sizeof val;					\
    681 	}								\
    682 }
    683 tc_mem_set_region_N(1,u_int8_t)
    684 tc_mem_set_region_N(2,u_int16_t)
    685 tc_mem_set_region_N(4,u_int32_t)
    686 tc_mem_set_region_N(8,u_int64_t)
    687 
    688 #define	tc_mem_copy_region_N(BYTES)					\
    689 void									\
    690 __C(tc_mem_copy_region_,BYTES)(v, h1, o1, h2, o2, c)			\
    691 	void *v;							\
    692 	bus_space_handle_t h1, h2;					\
    693 	bus_size_t o1, o2, c;						\
    694 {									\
    695 	bus_size_t o;							\
    696 									\
    697 	if ((h1 & TC_SPACE_SPARSE) != 0 &&				\
    698 	    (h2 & TC_SPACE_SPARSE) != 0) {				\
    699 		memmove((void *)(h2 + o2), (void *)(h1 + o1), c * BYTES); \
    700 		return;							\
    701 	}								\
    702 									\
    703 	if (h1 + o1 >= h2 + o2)						\
    704 		/* src after dest: copy forward */			\
    705 		for (o = 0; c > 0; c--, o += BYTES)			\
    706 			__C(tc_mem_write_,BYTES)(v, h2, o2 + o,		\
    707 			    __C(tc_mem_read_,BYTES)(v, h1, o1 + o));	\
    708 	else								\
    709 		/* dest after src: copy backwards */			\
    710 		for (o = (c - 1) * BYTES; c > 0; c--, o -= BYTES)	\
    711 			__C(tc_mem_write_,BYTES)(v, h2, o2 + o,		\
    712 			    __C(tc_mem_read_,BYTES)(v, h1, o1 + o));	\
    713 }
    714 tc_mem_copy_region_N(1)
    715 tc_mem_copy_region_N(2)
    716 tc_mem_copy_region_N(4)
    717 tc_mem_copy_region_N(8)
    718