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