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