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