Home | History | Annotate | Line # | Download | only in tc
tc_bus_mem.c revision 1.21
      1 /* $NetBSD: tc_bus_mem.c,v 1.21 2000/02/26 18:53:13 thorpej 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.21 2000/02/26 18:53:13 thorpej 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 #include <vm/vm.h>
     44 
     45 #include <machine/bus.h>
     46 #include <dev/tc/tcvar.h>
     47 
     48 #define	__C(A,B)	__CONCAT(A,B)
     49 
     50 /* mapping/unmapping */
     51 int		tc_mem_map __P((void *, bus_addr_t, bus_size_t, int,
     52 		    bus_space_handle_t *, int));
     53 void		tc_mem_unmap __P((void *, bus_space_handle_t, bus_size_t, int));
     54 int		tc_mem_subregion __P((void *, bus_space_handle_t, bus_size_t,
     55 		    bus_size_t, bus_space_handle_t *));
     56 
     57 int		tc_mem_translate __P((void *, bus_addr_t, bus_size_t,
     58 		    int, struct alpha_bus_space_translation *));
     59 int		tc_mem_get_window __P((void *, int,
     60 		    struct alpha_bus_space_translation *));
     61 
     62 /* allocation/deallocation */
     63 int		tc_mem_alloc __P((void *, bus_addr_t, bus_addr_t, bus_size_t,
     64 		    bus_size_t, bus_addr_t, int, bus_addr_t *,
     65 		    bus_space_handle_t *));
     66 void		tc_mem_free __P((void *, bus_space_handle_t, bus_size_t));
     67 
     68 /* barrier */
     69 inline void	tc_mem_barrier __P((void *, bus_space_handle_t,
     70 		    bus_size_t, bus_size_t, int));
     71 
     72 /* read (single) */
     73 inline u_int8_t	tc_mem_read_1 __P((void *, bus_space_handle_t, bus_size_t));
     74 inline u_int16_t tc_mem_read_2 __P((void *, bus_space_handle_t, bus_size_t));
     75 inline u_int32_t tc_mem_read_4 __P((void *, bus_space_handle_t, bus_size_t));
     76 inline u_int64_t tc_mem_read_8 __P((void *, bus_space_handle_t, bus_size_t));
     77 
     78 /* read multiple */
     79 void		tc_mem_read_multi_1 __P((void *, bus_space_handle_t,
     80 		    bus_size_t, u_int8_t *, bus_size_t));
     81 void		tc_mem_read_multi_2 __P((void *, bus_space_handle_t,
     82 		    bus_size_t, u_int16_t *, bus_size_t));
     83 void		tc_mem_read_multi_4 __P((void *, bus_space_handle_t,
     84 		    bus_size_t, u_int32_t *, bus_size_t));
     85 void		tc_mem_read_multi_8 __P((void *, bus_space_handle_t,
     86 		    bus_size_t, u_int64_t *, bus_size_t));
     87 
     88 /* read region */
     89 void		tc_mem_read_region_1 __P((void *, bus_space_handle_t,
     90 		    bus_size_t, u_int8_t *, bus_size_t));
     91 void		tc_mem_read_region_2 __P((void *, bus_space_handle_t,
     92 		    bus_size_t, u_int16_t *, bus_size_t));
     93 void		tc_mem_read_region_4 __P((void *, bus_space_handle_t,
     94 		    bus_size_t, u_int32_t *, bus_size_t));
     95 void		tc_mem_read_region_8 __P((void *, bus_space_handle_t,
     96 		    bus_size_t, u_int64_t *, bus_size_t));
     97 
     98 /* write (single) */
     99 inline void	tc_mem_write_1 __P((void *, bus_space_handle_t, bus_size_t,
    100 		    u_int8_t));
    101 inline void	tc_mem_write_2 __P((void *, bus_space_handle_t, bus_size_t,
    102 		    u_int16_t));
    103 inline void	tc_mem_write_4 __P((void *, bus_space_handle_t, bus_size_t,
    104 		    u_int32_t));
    105 inline void	tc_mem_write_8 __P((void *, bus_space_handle_t, bus_size_t,
    106 		    u_int64_t));
    107 
    108 /* write multiple */
    109 void		tc_mem_write_multi_1 __P((void *, bus_space_handle_t,
    110 		    bus_size_t, const u_int8_t *, bus_size_t));
    111 void		tc_mem_write_multi_2 __P((void *, bus_space_handle_t,
    112 		    bus_size_t, const u_int16_t *, bus_size_t));
    113 void		tc_mem_write_multi_4 __P((void *, bus_space_handle_t,
    114 		    bus_size_t, const u_int32_t *, bus_size_t));
    115 void		tc_mem_write_multi_8 __P((void *, bus_space_handle_t,
    116 		    bus_size_t, const u_int64_t *, bus_size_t));
    117 
    118 /* write region */
    119 void		tc_mem_write_region_1 __P((void *, bus_space_handle_t,
    120 		    bus_size_t, const u_int8_t *, bus_size_t));
    121 void		tc_mem_write_region_2 __P((void *, bus_space_handle_t,
    122 		    bus_size_t, const u_int16_t *, bus_size_t));
    123 void		tc_mem_write_region_4 __P((void *, bus_space_handle_t,
    124 		    bus_size_t, const u_int32_t *, bus_size_t));
    125 void		tc_mem_write_region_8 __P((void *, bus_space_handle_t,
    126 		    bus_size_t, const u_int64_t *, bus_size_t));
    127 
    128 /* set multiple */
    129 void		tc_mem_set_multi_1 __P((void *, bus_space_handle_t,
    130 		    bus_size_t, u_int8_t, bus_size_t));
    131 void		tc_mem_set_multi_2 __P((void *, bus_space_handle_t,
    132 		    bus_size_t, u_int16_t, bus_size_t));
    133 void		tc_mem_set_multi_4 __P((void *, bus_space_handle_t,
    134 		    bus_size_t, u_int32_t, bus_size_t));
    135 void		tc_mem_set_multi_8 __P((void *, bus_space_handle_t,
    136 		    bus_size_t, u_int64_t, bus_size_t));
    137 
    138 /* set region */
    139 void		tc_mem_set_region_1 __P((void *, bus_space_handle_t,
    140 		    bus_size_t, u_int8_t, bus_size_t));
    141 void		tc_mem_set_region_2 __P((void *, bus_space_handle_t,
    142 		    bus_size_t, u_int16_t, bus_size_t));
    143 void		tc_mem_set_region_4 __P((void *, bus_space_handle_t,
    144 		    bus_size_t, u_int32_t, bus_size_t));
    145 void		tc_mem_set_region_8 __P((void *, bus_space_handle_t,
    146 		    bus_size_t, u_int64_t, bus_size_t));
    147 
    148 /* copy */
    149 void		tc_mem_copy_region_1 __P((void *, bus_space_handle_t,
    150 		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t));
    151 void		tc_mem_copy_region_2 __P((void *, bus_space_handle_t,
    152 		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t));
    153 void		tc_mem_copy_region_4 __P((void *, bus_space_handle_t,
    154 		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t));
    155 void		tc_mem_copy_region_8 __P((void *, bus_space_handle_t,
    156 		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t));
    157 
    158 static struct alpha_bus_space tc_mem_space = {
    159 	/* cookie */
    160 	NULL,
    161 
    162 	/* mapping/unmapping */
    163 	tc_mem_map,
    164 	tc_mem_unmap,
    165 	tc_mem_subregion,
    166 
    167 	tc_mem_translate,
    168 	tc_mem_get_window,
    169 
    170 	/* allocation/deallocation */
    171 	tc_mem_alloc,
    172 	tc_mem_free,
    173 
    174 	/* barrier */
    175 	tc_mem_barrier,
    176 
    177 	/* read (single) */
    178 	tc_mem_read_1,
    179 	tc_mem_read_2,
    180 	tc_mem_read_4,
    181 	tc_mem_read_8,
    182 
    183 	/* read multiple */
    184 	tc_mem_read_multi_1,
    185 	tc_mem_read_multi_2,
    186 	tc_mem_read_multi_4,
    187 	tc_mem_read_multi_8,
    188 
    189 	/* read region */
    190 	tc_mem_read_region_1,
    191 	tc_mem_read_region_2,
    192 	tc_mem_read_region_4,
    193 	tc_mem_read_region_8,
    194 
    195 	/* write (single) */
    196 	tc_mem_write_1,
    197 	tc_mem_write_2,
    198 	tc_mem_write_4,
    199 	tc_mem_write_8,
    200 
    201 	/* write multiple */
    202 	tc_mem_write_multi_1,
    203 	tc_mem_write_multi_2,
    204 	tc_mem_write_multi_4,
    205 	tc_mem_write_multi_8,
    206 
    207 	/* write region */
    208 	tc_mem_write_region_1,
    209 	tc_mem_write_region_2,
    210 	tc_mem_write_region_4,
    211 	tc_mem_write_region_8,
    212 
    213 	/* set multiple */
    214 	tc_mem_set_multi_1,
    215 	tc_mem_set_multi_2,
    216 	tc_mem_set_multi_4,
    217 	tc_mem_set_multi_8,
    218 
    219 	/* set region */
    220 	tc_mem_set_region_1,
    221 	tc_mem_set_region_2,
    222 	tc_mem_set_region_4,
    223 	tc_mem_set_region_8,
    224 
    225 	/* copy */
    226 	tc_mem_copy_region_1,
    227 	tc_mem_copy_region_2,
    228 	tc_mem_copy_region_4,
    229 	tc_mem_copy_region_8,
    230 };
    231 
    232 bus_space_tag_t
    233 tc_bus_mem_init(memv)
    234 	void *memv;
    235 {
    236 	bus_space_tag_t h = &tc_mem_space;
    237 
    238 	h->abs_cookie = memv;
    239 	return (h);
    240 }
    241 
    242 /* ARGSUSED */
    243 int
    244 tc_mem_translate(v, memaddr, memlen, flags, abst)
    245 	void *v;
    246 	bus_addr_t memaddr;
    247 	bus_size_t memlen;
    248 	int flags;
    249 	struct alpha_bus_space_translation *abst;
    250 {
    251 
    252 	return (EOPNOTSUPP);
    253 }
    254 
    255 /* ARGSUSED */
    256 int
    257 tc_mem_get_window(v, window, abst)
    258 	void *v;
    259 	int window;
    260 	struct alpha_bus_space_translation *abst;
    261 {
    262 
    263 	return (EOPNOTSUPP);
    264 }
    265 
    266 /* ARGSUSED */
    267 int
    268 tc_mem_map(v, memaddr, memsize, flags, memhp, acct)
    269 	void *v;
    270 	bus_addr_t memaddr;
    271 	bus_size_t memsize;
    272 	int flags;
    273 	bus_space_handle_t *memhp;
    274 	int acct;
    275 {
    276 	int cacheable = flags & BUS_SPACE_MAP_CACHEABLE;
    277 	int linear = flags & BUS_SPACE_MAP_LINEAR;
    278 
    279 	/* Requests for linear uncacheable space can't be satisfied. */
    280 	if (linear && !cacheable)
    281 		return (EOPNOTSUPP);
    282 
    283 	if (memaddr & 0x7)
    284 		panic("tc_mem_map needs 8 byte alignment");
    285 	if (cacheable)
    286 		*memhp = ALPHA_PHYS_TO_K0SEG(memaddr);
    287 	else
    288 		*memhp = ALPHA_PHYS_TO_K0SEG(TC_DENSE_TO_SPARSE(memaddr));
    289 	return (0);
    290 }
    291 
    292 /* ARGSUSED */
    293 void
    294 tc_mem_unmap(v, memh, memsize, acct)
    295 	void *v;
    296 	bus_space_handle_t memh;
    297 	bus_size_t memsize;
    298 	int acct;
    299 {
    300 
    301 	/* XXX XX XXX nothing to do. */
    302 }
    303 
    304 int
    305 tc_mem_subregion(v, memh, offset, size, nmemh)
    306 	void *v;
    307 	bus_space_handle_t memh, *nmemh;
    308 	bus_size_t offset, size;
    309 {
    310 
    311 	/* Disallow subregioning that would make the handle unaligned. */
    312 	if ((offset & 0x7) != 0)
    313 		return (1);
    314 
    315 	if ((memh & TC_SPACE_SPARSE) != 0)
    316 		*nmemh = memh + (offset << 1);
    317 	else
    318 		*nmemh = memh + offset;
    319 
    320 	return (0);
    321 }
    322 
    323 int
    324 tc_mem_alloc(v, rstart, rend, size, align, boundary, flags, addrp, bshp)
    325 	void *v;
    326 	bus_addr_t rstart, rend, *addrp;
    327 	bus_size_t size, align, boundary;
    328 	int flags;
    329 	bus_space_handle_t *bshp;
    330 {
    331 
    332 	/* XXX XXX XXX XXX XXX XXX */
    333 	panic("tc_mem_alloc unimplemented");
    334 }
    335 
    336 void
    337 tc_mem_free(v, bsh, size)
    338 	void *v;
    339 	bus_space_handle_t bsh;
    340 	bus_size_t size;
    341 {
    342 
    343 	/* XXX XXX XXX XXX XXX XXX */
    344 	panic("tc_mem_free unimplemented");
    345 }
    346 
    347 inline void
    348 tc_mem_barrier(v, h, o, l, f)
    349 	void *v;
    350 	bus_space_handle_t h;
    351 	bus_size_t o, l;
    352 	int f;
    353 {
    354 
    355 	if ((f & BUS_SPACE_BARRIER_READ) != 0)
    356 		alpha_mb();
    357 	else if ((f & BUS_SPACE_BARRIER_WRITE) != 0)
    358 		alpha_wmb();
    359 }
    360 
    361 inline u_int8_t
    362 tc_mem_read_1(v, memh, off)
    363 	void *v;
    364 	bus_space_handle_t memh;
    365 	bus_size_t off;
    366 {
    367 	volatile u_int8_t *p;
    368 
    369 	alpha_mb();		/* XXX XXX XXX */
    370 
    371 	if ((memh & TC_SPACE_SPARSE) != 0)
    372 		panic("tc_mem_read_1 not implemented for sparse space");
    373 
    374 	p = (u_int8_t *)(memh + off);
    375 	return (*p);
    376 }
    377 
    378 inline u_int16_t
    379 tc_mem_read_2(v, memh, off)
    380 	void *v;
    381 	bus_space_handle_t memh;
    382 	bus_size_t off;
    383 {
    384 	volatile u_int16_t *p;
    385 
    386 	alpha_mb();		/* XXX XXX XXX */
    387 
    388 	if ((memh & TC_SPACE_SPARSE) != 0)
    389 		panic("tc_mem_read_2 not implemented for sparse space");
    390 
    391 	p = (u_int16_t *)(memh + off);
    392 	return (*p);
    393 }
    394 
    395 inline u_int32_t
    396 tc_mem_read_4(v, memh, off)
    397 	void *v;
    398 	bus_space_handle_t memh;
    399 	bus_size_t off;
    400 {
    401 	volatile u_int32_t *p;
    402 
    403 	alpha_mb();		/* XXX XXX XXX */
    404 
    405 	if ((memh & TC_SPACE_SPARSE) != 0)
    406 		/* Nothing special to do for 4-byte sparse space accesses */
    407 		p = (u_int32_t *)(memh + (off << 1));
    408 	else
    409 		p = (u_int32_t *)(memh + off);
    410 	return (*p);
    411 }
    412 
    413 inline u_int64_t
    414 tc_mem_read_8(v, memh, off)
    415 	void *v;
    416 	bus_space_handle_t memh;
    417 	bus_size_t off;
    418 {
    419 	volatile u_int64_t *p;
    420 
    421 	alpha_mb();		/* XXX XXX XXX */
    422 
    423 	if ((memh & TC_SPACE_SPARSE) != 0)
    424 		panic("tc_mem_read_8 not implemented for sparse space");
    425 
    426 	p = (u_int64_t *)(memh + off);
    427 	return (*p);
    428 }
    429 
    430 #define	tc_mem_read_multi_N(BYTES,TYPE)					\
    431 void									\
    432 __C(tc_mem_read_multi_,BYTES)(v, h, o, a, c)				\
    433 	void *v;							\
    434 	bus_space_handle_t h;						\
    435 	bus_size_t o, c;						\
    436 	TYPE *a;							\
    437 {									\
    438 									\
    439 	while (c-- > 0) {						\
    440 		tc_mem_barrier(v, h, o, sizeof *a, BUS_SPACE_BARRIER_READ); \
    441 		*a++ = __C(tc_mem_read_,BYTES)(v, h, o);		\
    442 	}								\
    443 }
    444 tc_mem_read_multi_N(1,u_int8_t)
    445 tc_mem_read_multi_N(2,u_int16_t)
    446 tc_mem_read_multi_N(4,u_int32_t)
    447 tc_mem_read_multi_N(8,u_int64_t)
    448 
    449 #define	tc_mem_read_region_N(BYTES,TYPE)				\
    450 void									\
    451 __C(tc_mem_read_region_,BYTES)(v, h, o, a, c)				\
    452 	void *v;							\
    453 	bus_space_handle_t h;						\
    454 	bus_size_t o, c;						\
    455 	TYPE *a;							\
    456 {									\
    457 									\
    458 	while (c-- > 0) {						\
    459 		*a++ = __C(tc_mem_read_,BYTES)(v, h, o);		\
    460 		o += sizeof *a;						\
    461 	}								\
    462 }
    463 tc_mem_read_region_N(1,u_int8_t)
    464 tc_mem_read_region_N(2,u_int16_t)
    465 tc_mem_read_region_N(4,u_int32_t)
    466 tc_mem_read_region_N(8,u_int64_t)
    467 
    468 inline void
    469 tc_mem_write_1(v, memh, off, val)
    470 	void *v;
    471 	bus_space_handle_t memh;
    472 	bus_size_t off;
    473 	u_int8_t val;
    474 {
    475 
    476 	if ((memh & TC_SPACE_SPARSE) != 0) {
    477 		volatile u_int64_t *p, v;
    478 		u_int64_t shift, msk;
    479 
    480 		shift = off & 0x3;
    481 		off &= 0x3;
    482 
    483 		p = (u_int64_t *)(memh + (off << 1));
    484 
    485 		msk = ~(0x1 << shift) & 0xf;
    486 		v = (msk << 32) | (((u_int64_t)val) << (shift * 8));
    487 
    488 		*p = val;
    489 	} else {
    490 		volatile u_int8_t *p;
    491 
    492 		p = (u_int8_t *)(memh + off);
    493 		*p = val;
    494 	}
    495         alpha_mb();		/* XXX XXX XXX */
    496 }
    497 
    498 inline void
    499 tc_mem_write_2(v, memh, off, val)
    500 	void *v;
    501 	bus_space_handle_t memh;
    502 	bus_size_t off;
    503 	u_int16_t val;
    504 {
    505 
    506 	if ((memh & TC_SPACE_SPARSE) != 0) {
    507 		volatile u_int64_t *p, v;
    508 		u_int64_t shift, msk;
    509 
    510 		shift = off & 0x2;
    511 		off &= 0x3;
    512 
    513 		p = (u_int64_t *)(memh + (off << 1));
    514 
    515 		msk = ~(0x3 << shift) & 0xf;
    516 		v = (msk << 32) | (((u_int64_t)val) << (shift * 8));
    517 
    518 		*p = val;
    519 	} else {
    520 		volatile u_int16_t *p;
    521 
    522 		p = (u_int16_t *)(memh + off);
    523 		*p = val;
    524 	}
    525         alpha_mb();		/* XXX XXX XXX */
    526 }
    527 
    528 inline void
    529 tc_mem_write_4(v, memh, off, val)
    530 	void *v;
    531 	bus_space_handle_t memh;
    532 	bus_size_t off;
    533 	u_int32_t val;
    534 {
    535 	volatile u_int32_t *p;
    536 
    537 	if ((memh & TC_SPACE_SPARSE) != 0)
    538 		/* Nothing special to do for 4-byte sparse space accesses */
    539 		p = (u_int32_t *)(memh + (off << 1));
    540 	else
    541 		p = (u_int32_t *)(memh + off);
    542 	*p = val;
    543         alpha_mb();		/* XXX XXX XXX */
    544 }
    545 
    546 inline void
    547 tc_mem_write_8(v, memh, off, val)
    548 	void *v;
    549 	bus_space_handle_t memh;
    550 	bus_size_t off;
    551 	u_int64_t val;
    552 {
    553 	volatile u_int64_t *p;
    554 
    555 	if ((memh & TC_SPACE_SPARSE) != 0)
    556 		panic("tc_mem_read_8 not implemented for sparse space");
    557 
    558 	p = (u_int64_t *)(memh + off);
    559 	*p = val;
    560         alpha_mb();		/* XXX XXX XXX */
    561 }
    562 
    563 #define	tc_mem_write_multi_N(BYTES,TYPE)				\
    564 void									\
    565 __C(tc_mem_write_multi_,BYTES)(v, h, o, a, c)				\
    566 	void *v;							\
    567 	bus_space_handle_t h;						\
    568 	bus_size_t o, c;						\
    569 	const TYPE *a;							\
    570 {									\
    571 									\
    572 	while (c-- > 0) {						\
    573 		__C(tc_mem_write_,BYTES)(v, h, o, *a++);		\
    574 		tc_mem_barrier(v, h, o, sizeof *a, BUS_SPACE_BARRIER_WRITE); \
    575 	}								\
    576 }
    577 tc_mem_write_multi_N(1,u_int8_t)
    578 tc_mem_write_multi_N(2,u_int16_t)
    579 tc_mem_write_multi_N(4,u_int32_t)
    580 tc_mem_write_multi_N(8,u_int64_t)
    581 
    582 #define	tc_mem_write_region_N(BYTES,TYPE)				\
    583 void									\
    584 __C(tc_mem_write_region_,BYTES)(v, h, o, a, c)				\
    585 	void *v;							\
    586 	bus_space_handle_t h;						\
    587 	bus_size_t o, c;						\
    588 	const TYPE *a;							\
    589 {									\
    590 									\
    591 	while (c-- > 0) {						\
    592 		__C(tc_mem_write_,BYTES)(v, h, o, *a++);		\
    593 		o += sizeof *a;						\
    594 	}								\
    595 }
    596 tc_mem_write_region_N(1,u_int8_t)
    597 tc_mem_write_region_N(2,u_int16_t)
    598 tc_mem_write_region_N(4,u_int32_t)
    599 tc_mem_write_region_N(8,u_int64_t)
    600 
    601 #define	tc_mem_set_multi_N(BYTES,TYPE)					\
    602 void									\
    603 __C(tc_mem_set_multi_,BYTES)(v, h, o, val, c)				\
    604 	void *v;							\
    605 	bus_space_handle_t h;						\
    606 	bus_size_t o, c;						\
    607 	TYPE val;							\
    608 {									\
    609 									\
    610 	while (c-- > 0) {						\
    611 		__C(tc_mem_write_,BYTES)(v, h, o, val);			\
    612 		tc_mem_barrier(v, h, o, sizeof val, BUS_SPACE_BARRIER_WRITE); \
    613 	}								\
    614 }
    615 tc_mem_set_multi_N(1,u_int8_t)
    616 tc_mem_set_multi_N(2,u_int16_t)
    617 tc_mem_set_multi_N(4,u_int32_t)
    618 tc_mem_set_multi_N(8,u_int64_t)
    619 
    620 #define	tc_mem_set_region_N(BYTES,TYPE)					\
    621 void									\
    622 __C(tc_mem_set_region_,BYTES)(v, h, o, val, c)				\
    623 	void *v;							\
    624 	bus_space_handle_t h;						\
    625 	bus_size_t o, c;						\
    626 	TYPE val;							\
    627 {									\
    628 									\
    629 	while (c-- > 0) {						\
    630 		__C(tc_mem_write_,BYTES)(v, h, o, val);			\
    631 		o += sizeof val;					\
    632 	}								\
    633 }
    634 tc_mem_set_region_N(1,u_int8_t)
    635 tc_mem_set_region_N(2,u_int16_t)
    636 tc_mem_set_region_N(4,u_int32_t)
    637 tc_mem_set_region_N(8,u_int64_t)
    638 
    639 #define	tc_mem_copy_region_N(BYTES)					\
    640 void									\
    641 __C(tc_mem_copy_region_,BYTES)(v, h1, o1, h2, o2, c)			\
    642 	void *v;							\
    643 	bus_space_handle_t h1, h2;					\
    644 	bus_size_t o1, o2, c;						\
    645 {									\
    646 	bus_size_t o;							\
    647 									\
    648 	if ((h1 & TC_SPACE_SPARSE) != 0 &&				\
    649 	    (h2 & TC_SPACE_SPARSE) != 0) {				\
    650 		memmove((void *)(h2 + o2), (void *)(h1 + o1), c * BYTES); \
    651 		return;							\
    652 	}								\
    653 									\
    654 	if (h1 + o1 >= h2 + o2)						\
    655 		/* src after dest: copy forward */			\
    656 		for (o = 0; c > 0; c--, o += BYTES)			\
    657 			__C(tc_mem_write_,BYTES)(v, h2, o2 + o,		\
    658 			    __C(tc_mem_read_,BYTES)(v, h1, o1 + o));	\
    659 	else								\
    660 		/* dest after src: copy backwards */			\
    661 		for (o = (c - 1) * BYTES; c > 0; c--, o -= BYTES)	\
    662 			__C(tc_mem_write_,BYTES)(v, h2, o2 + o,		\
    663 			    __C(tc_mem_read_,BYTES)(v, h1, o1 + o));	\
    664 }
    665 tc_mem_copy_region_N(1)
    666 tc_mem_copy_region_N(2)
    667 tc_mem_copy_region_N(4)
    668 tc_mem_copy_region_N(8)
    669