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