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