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