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