xref: /openbsd-src/sys/arch/alpha/tc/tc_bus_mem.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /* $OpenBSD: tc_bus_mem.c,v 1.13 2002/05/02 22:56:06 miod Exp $ */
2 /* $NetBSD: tc_bus_mem.c,v 1.25 2001/09/04 05:31:28 thorpej Exp $ */
3 
4 /*
5  * Copyright (c) 1996 Carnegie-Mellon University.
6  * All rights reserved.
7  *
8  * Author: Chris G. Demetriou
9  *
10  * Permission to use, copy, modify and distribute this software and
11  * its documentation is hereby granted, provided that both the copyright
12  * notice and this permission notice appear in all copies of the
13  * software, derivative works or modified versions, and any portions
14  * thereof, and that both notices appear in supporting documentation.
15  *
16  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
17  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
18  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19  *
20  * Carnegie Mellon requests users of this software to return to
21  *
22  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
23  *  School of Computer Science
24  *  Carnegie Mellon University
25  *  Pittsburgh PA 15213-3890
26  *
27  * any improvements or extensions that they make and grant Carnegie the
28  * rights to redistribute these changes.
29  */
30 
31 /*
32  * Common TurboChannel Chipset "bus memory" functions.
33  */
34 
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/malloc.h>
38 #include <sys/syslog.h>
39 #include <sys/device.h>
40 
41 #include <uvm/uvm_extern.h>
42 
43 #include <machine/bus.h>
44 #include <dev/tc/tcvar.h>
45 
46 #define	__C(A,B)	__CONCAT(A,B)
47 
48 /* mapping/unmapping */
49 int		tc_mem_map(void *, bus_addr_t, bus_size_t, int,
50 		    bus_space_handle_t *);
51 void		tc_mem_unmap(void *, bus_space_handle_t, bus_size_t);
52 int		tc_mem_subregion(void *, bus_space_handle_t, bus_size_t,
53 		    bus_size_t, bus_space_handle_t *);
54 
55 /* allocation/deallocation */
56 int		tc_mem_alloc(void *, bus_addr_t, bus_addr_t, bus_size_t,
57 		    bus_size_t, bus_addr_t, int, bus_addr_t *,
58 		    bus_space_handle_t *);
59 void		tc_mem_free(void *, bus_space_handle_t, bus_size_t);
60 
61 /* barrier */
62 inline void	tc_mem_barrier(void *, bus_space_handle_t,
63 		    bus_size_t, bus_size_t, int);
64 
65 /* read (single) */
66 inline u_int8_t	tc_mem_read_1(void *, bus_space_handle_t, bus_size_t);
67 inline u_int16_t tc_mem_read_2(void *, bus_space_handle_t, bus_size_t);
68 inline u_int32_t tc_mem_read_4(void *, bus_space_handle_t, bus_size_t);
69 inline u_int64_t tc_mem_read_8(void *, bus_space_handle_t, bus_size_t);
70 
71 /* read multiple */
72 void		tc_mem_read_multi_1(void *, bus_space_handle_t,
73 		    bus_size_t, u_int8_t *, bus_size_t);
74 void		tc_mem_read_multi_2(void *, bus_space_handle_t,
75 		    bus_size_t, u_int16_t *, bus_size_t);
76 void		tc_mem_read_multi_4(void *, bus_space_handle_t,
77 		    bus_size_t, u_int32_t *, bus_size_t);
78 void		tc_mem_read_multi_8(void *, bus_space_handle_t,
79 		    bus_size_t, u_int64_t *, bus_size_t);
80 
81 /* read region */
82 void		tc_mem_read_region_1(void *, bus_space_handle_t,
83 		    bus_size_t, u_int8_t *, bus_size_t);
84 void		tc_mem_read_region_2(void *, bus_space_handle_t,
85 		    bus_size_t, u_int16_t *, bus_size_t);
86 void		tc_mem_read_region_4(void *, bus_space_handle_t,
87 		    bus_size_t, u_int32_t *, bus_size_t);
88 void		tc_mem_read_region_8(void *, bus_space_handle_t,
89 		    bus_size_t, u_int64_t *, bus_size_t);
90 
91 /* write (single) */
92 inline void	tc_mem_write_1(void *, bus_space_handle_t, bus_size_t,
93 		    u_int8_t);
94 inline void	tc_mem_write_2(void *, bus_space_handle_t, bus_size_t,
95 		    u_int16_t);
96 inline void	tc_mem_write_4(void *, bus_space_handle_t, bus_size_t,
97 		    u_int32_t);
98 inline void	tc_mem_write_8(void *, bus_space_handle_t, bus_size_t,
99 		    u_int64_t);
100 
101 /* write multiple */
102 void		tc_mem_write_multi_1(void *, bus_space_handle_t,
103 		    bus_size_t, const u_int8_t *, bus_size_t);
104 void		tc_mem_write_multi_2(void *, bus_space_handle_t,
105 		    bus_size_t, const u_int16_t *, bus_size_t);
106 void		tc_mem_write_multi_4(void *, bus_space_handle_t,
107 		    bus_size_t, const u_int32_t *, bus_size_t);
108 void		tc_mem_write_multi_8(void *, bus_space_handle_t,
109 		    bus_size_t, const u_int64_t *, bus_size_t);
110 
111 /* write region */
112 void		tc_mem_write_region_1(void *, bus_space_handle_t,
113 		    bus_size_t, const u_int8_t *, bus_size_t);
114 void		tc_mem_write_region_2(void *, bus_space_handle_t,
115 		    bus_size_t, const u_int16_t *, bus_size_t);
116 void		tc_mem_write_region_4(void *, bus_space_handle_t,
117 		    bus_size_t, const u_int32_t *, bus_size_t);
118 void		tc_mem_write_region_8(void *, bus_space_handle_t,
119 		    bus_size_t, const u_int64_t *, bus_size_t);
120 
121 /* set multiple */
122 void		tc_mem_set_multi_1(void *, bus_space_handle_t,
123 		    bus_size_t, u_int8_t, bus_size_t);
124 void		tc_mem_set_multi_2(void *, bus_space_handle_t,
125 		    bus_size_t, u_int16_t, bus_size_t);
126 void		tc_mem_set_multi_4(void *, bus_space_handle_t,
127 		    bus_size_t, u_int32_t, bus_size_t);
128 void		tc_mem_set_multi_8(void *, bus_space_handle_t,
129 		    bus_size_t, u_int64_t, bus_size_t);
130 
131 /* set region */
132 void		tc_mem_set_region_1(void *, bus_space_handle_t,
133 		    bus_size_t, u_int8_t, bus_size_t);
134 void		tc_mem_set_region_2(void *, bus_space_handle_t,
135 		    bus_size_t, u_int16_t, bus_size_t);
136 void		tc_mem_set_region_4(void *, bus_space_handle_t,
137 		    bus_size_t, u_int32_t, bus_size_t);
138 void		tc_mem_set_region_8(void *, bus_space_handle_t,
139 		    bus_size_t, u_int64_t, bus_size_t);
140 
141 /* copy */
142 void		tc_mem_copy_region_1(void *, bus_space_handle_t,
143 		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
144 void		tc_mem_copy_region_2(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_4(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_8(void *, bus_space_handle_t,
149 		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
150 
151 struct alpha_bus_space tc_mem_space = {
152 	/* cookie */
153 	NULL,
154 
155 	/* mapping/unmapping */
156 	tc_mem_map,
157 	tc_mem_unmap,
158 	tc_mem_subregion,
159 
160 	/* allocation/deallocation */
161 	tc_mem_alloc,
162 	tc_mem_free,
163 
164 	/* barrier */
165 	tc_mem_barrier,
166 
167 	/* read (single) */
168 	tc_mem_read_1,
169 	tc_mem_read_2,
170 	tc_mem_read_4,
171 	tc_mem_read_8,
172 
173 	/* read multiple */
174 	tc_mem_read_multi_1,
175 	tc_mem_read_multi_2,
176 	tc_mem_read_multi_4,
177 	tc_mem_read_multi_8,
178 
179 	/* read region */
180 	tc_mem_read_region_1,
181 	tc_mem_read_region_2,
182 	tc_mem_read_region_4,
183 	tc_mem_read_region_8,
184 
185 	/* write (single) */
186 	tc_mem_write_1,
187 	tc_mem_write_2,
188 	tc_mem_write_4,
189 	tc_mem_write_8,
190 
191 	/* write multiple */
192 	tc_mem_write_multi_1,
193 	tc_mem_write_multi_2,
194 	tc_mem_write_multi_4,
195 	tc_mem_write_multi_8,
196 
197 	/* write region */
198 	tc_mem_write_region_1,
199 	tc_mem_write_region_2,
200 	tc_mem_write_region_4,
201 	tc_mem_write_region_8,
202 
203 	/* set multiple */
204 	tc_mem_set_multi_1,
205 	tc_mem_set_multi_2,
206 	tc_mem_set_multi_4,
207 	tc_mem_set_multi_8,
208 
209 	/* set region */
210 	tc_mem_set_region_1,
211 	tc_mem_set_region_2,
212 	tc_mem_set_region_4,
213 	tc_mem_set_region_8,
214 
215 	/* copy */
216 	tc_mem_copy_region_1,
217 	tc_mem_copy_region_2,
218 	tc_mem_copy_region_4,
219 	tc_mem_copy_region_8,
220 };
221 
222 bus_space_tag_t
223 tc_bus_mem_init(memv)
224 	void *memv;
225 {
226 	bus_space_tag_t h = &tc_mem_space;
227 
228 	h->abs_cookie = memv;
229 	return (h);
230 }
231 
232 /* ARGSUSED */
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 /* ARGSUSED */
252 void
253 tc_mem_unmap(v, memh, memsize)
254 	void *v;
255 	bus_space_handle_t memh;
256 	bus_size_t memsize;
257 {
258 
259 	/* XXX XX XXX nothing to do. */
260 }
261 
262 int
263 tc_mem_subregion(v, memh, offset, size, nmemh)
264 	void *v;
265 	bus_space_handle_t memh, *nmemh;
266 	bus_size_t offset, size;
267 {
268 
269 	/* Disallow subregioning that would make the handle unaligned. */
270 	if ((offset & 0x7) != 0)
271 		return (1);
272 
273 	if ((memh & TC_SPACE_SPARSE) != 0)
274 		*nmemh = memh + (offset << 1);
275 	else
276 		*nmemh = memh + offset;
277 
278 	return (0);
279 }
280 
281 int
282 tc_mem_alloc(v, rstart, rend, size, align, boundary, flags, addrp, bshp)
283 	void *v;
284 	bus_addr_t rstart, rend, *addrp;
285 	bus_size_t size, align, boundary;
286 	int flags;
287 	bus_space_handle_t *bshp;
288 {
289 
290 	/* XXX XXX XXX XXX XXX XXX */
291 	panic("tc_mem_alloc unimplemented");
292 }
293 
294 void
295 tc_mem_free(v, bsh, size)
296 	void *v;
297 	bus_space_handle_t bsh;
298 	bus_size_t size;
299 {
300 
301 	/* XXX XXX XXX XXX XXX XXX */
302 	panic("tc_mem_free unimplemented");
303 }
304 
305 inline void
306 tc_mem_barrier(v, h, o, l, f)
307 	void *v;
308 	bus_space_handle_t h;
309 	bus_size_t o, l;
310 	int f;
311 {
312 
313 	if ((f & BUS_SPACE_BARRIER_READ) != 0)
314 		alpha_mb();
315 	else if ((f & BUS_SPACE_BARRIER_WRITE) != 0)
316 		alpha_wmb();
317 }
318 
319 inline u_int8_t
320 tc_mem_read_1(v, memh, off)
321 	void *v;
322 	bus_space_handle_t memh;
323 	bus_size_t off;
324 {
325 	volatile u_int8_t *p;
326 
327 	alpha_mb();		/* XXX XXX XXX */
328 
329 	if ((memh & TC_SPACE_SPARSE) != 0)
330 		panic("tc_mem_read_1 not implemented for sparse space");
331 
332 	p = (u_int8_t *)(memh + off);
333 	return (*p);
334 }
335 
336 inline u_int16_t
337 tc_mem_read_2(v, memh, off)
338 	void *v;
339 	bus_space_handle_t memh;
340 	bus_size_t off;
341 {
342 	volatile u_int16_t *p;
343 
344 	alpha_mb();		/* XXX XXX XXX */
345 
346 	if ((memh & TC_SPACE_SPARSE) != 0)
347 		panic("tc_mem_read_2 not implemented for sparse space");
348 
349 	p = (u_int16_t *)(memh + off);
350 	return (*p);
351 }
352 
353 inline u_int32_t
354 tc_mem_read_4(v, memh, off)
355 	void *v;
356 	bus_space_handle_t memh;
357 	bus_size_t off;
358 {
359 	volatile u_int32_t *p;
360 
361 	alpha_mb();		/* XXX XXX XXX */
362 
363 	if ((memh & TC_SPACE_SPARSE) != 0)
364 		/* Nothing special to do for 4-byte sparse space accesses */
365 		p = (u_int32_t *)(memh + (off << 1));
366 	else
367 		p = (u_int32_t *)(memh + off);
368 	return (*p);
369 }
370 
371 inline u_int64_t
372 tc_mem_read_8(v, memh, off)
373 	void *v;
374 	bus_space_handle_t memh;
375 	bus_size_t off;
376 {
377 	volatile u_int64_t *p;
378 
379 	alpha_mb();		/* XXX XXX XXX */
380 
381 	if ((memh & TC_SPACE_SPARSE) != 0)
382 		panic("tc_mem_read_8 not implemented for sparse space");
383 
384 	p = (u_int64_t *)(memh + off);
385 	return (*p);
386 }
387 
388 #define	tc_mem_read_multi_N(BYTES,TYPE)					\
389 void									\
390 __C(tc_mem_read_multi_,BYTES)(v, h, o, a, c)				\
391 	void *v;							\
392 	bus_space_handle_t h;						\
393 	bus_size_t o, c;						\
394 	TYPE *a;							\
395 {									\
396 									\
397 	while (c-- > 0) {						\
398 		tc_mem_barrier(v, h, o, sizeof *a, BUS_SPACE_BARRIER_READ); \
399 		*a++ = __C(tc_mem_read_,BYTES)(v, h, o);		\
400 	}								\
401 }
402 tc_mem_read_multi_N(1,u_int8_t)
403 tc_mem_read_multi_N(2,u_int16_t)
404 tc_mem_read_multi_N(4,u_int32_t)
405 tc_mem_read_multi_N(8,u_int64_t)
406 
407 #define	tc_mem_read_region_N(BYTES,TYPE)				\
408 void									\
409 __C(tc_mem_read_region_,BYTES)(v, h, o, a, c)				\
410 	void *v;							\
411 	bus_space_handle_t h;						\
412 	bus_size_t o, c;						\
413 	TYPE *a;							\
414 {									\
415 									\
416 	while (c-- > 0) {						\
417 		*a++ = __C(tc_mem_read_,BYTES)(v, h, o);		\
418 		o += sizeof *a;						\
419 	}								\
420 }
421 tc_mem_read_region_N(1,u_int8_t)
422 tc_mem_read_region_N(2,u_int16_t)
423 tc_mem_read_region_N(4,u_int32_t)
424 tc_mem_read_region_N(8,u_int64_t)
425 
426 inline void
427 tc_mem_write_1(v, memh, off, val)
428 	void *v;
429 	bus_space_handle_t memh;
430 	bus_size_t off;
431 	u_int8_t val;
432 {
433 
434 	if ((memh & TC_SPACE_SPARSE) != 0) {
435 		volatile u_int64_t *p, v;
436 		u_int64_t shift, msk;
437 
438 		shift = off & 0x3;
439 		off &= 0x3;
440 
441 		p = (u_int64_t *)(memh + (off << 1));
442 
443 		msk = ~(0x1 << shift) & 0xf;
444 		v = (msk << 32) | (((u_int64_t)val) << (shift * 8));
445 
446 		*p = val;
447 	} else {
448 		volatile u_int8_t *p;
449 
450 		p = (u_int8_t *)(memh + off);
451 		*p = val;
452 	}
453         alpha_mb();		/* XXX XXX XXX */
454 }
455 
456 inline void
457 tc_mem_write_2(v, memh, off, val)
458 	void *v;
459 	bus_space_handle_t memh;
460 	bus_size_t off;
461 	u_int16_t val;
462 {
463 
464 	if ((memh & TC_SPACE_SPARSE) != 0) {
465 		volatile u_int64_t *p, v;
466 		u_int64_t shift, msk;
467 
468 		shift = off & 0x2;
469 		off &= 0x3;
470 
471 		p = (u_int64_t *)(memh + (off << 1));
472 
473 		msk = ~(0x3 << shift) & 0xf;
474 		v = (msk << 32) | (((u_int64_t)val) << (shift * 8));
475 
476 		*p = val;
477 	} else {
478 		volatile u_int16_t *p;
479 
480 		p = (u_int16_t *)(memh + off);
481 		*p = val;
482 	}
483         alpha_mb();		/* XXX XXX XXX */
484 }
485 
486 inline void
487 tc_mem_write_4(v, memh, off, val)
488 	void *v;
489 	bus_space_handle_t memh;
490 	bus_size_t off;
491 	u_int32_t val;
492 {
493 	volatile u_int32_t *p;
494 
495 	if ((memh & TC_SPACE_SPARSE) != 0)
496 		/* Nothing special to do for 4-byte sparse space accesses */
497 		p = (u_int32_t *)(memh + (off << 1));
498 	else
499 		p = (u_int32_t *)(memh + off);
500 	*p = val;
501         alpha_mb();		/* XXX XXX XXX */
502 }
503 
504 inline void
505 tc_mem_write_8(v, memh, off, val)
506 	void *v;
507 	bus_space_handle_t memh;
508 	bus_size_t off;
509 	u_int64_t val;
510 {
511 	volatile u_int64_t *p;
512 
513 	if ((memh & TC_SPACE_SPARSE) != 0)
514 		panic("tc_mem_read_8 not implemented for sparse space");
515 
516 	p = (u_int64_t *)(memh + off);
517 	*p = val;
518         alpha_mb();		/* XXX XXX XXX */
519 }
520 
521 #define	tc_mem_write_multi_N(BYTES,TYPE)				\
522 void									\
523 __C(tc_mem_write_multi_,BYTES)(v, h, o, a, c)				\
524 	void *v;							\
525 	bus_space_handle_t h;						\
526 	bus_size_t o, c;						\
527 	const TYPE *a;							\
528 {									\
529 									\
530 	while (c-- > 0) {						\
531 		__C(tc_mem_write_,BYTES)(v, h, o, *a++);		\
532 		tc_mem_barrier(v, h, o, sizeof *a, BUS_SPACE_BARRIER_WRITE); \
533 	}								\
534 }
535 tc_mem_write_multi_N(1,u_int8_t)
536 tc_mem_write_multi_N(2,u_int16_t)
537 tc_mem_write_multi_N(4,u_int32_t)
538 tc_mem_write_multi_N(8,u_int64_t)
539 
540 #define	tc_mem_write_region_N(BYTES,TYPE)				\
541 void									\
542 __C(tc_mem_write_region_,BYTES)(v, h, o, a, c)				\
543 	void *v;							\
544 	bus_space_handle_t h;						\
545 	bus_size_t o, c;						\
546 	const TYPE *a;							\
547 {									\
548 									\
549 	while (c-- > 0) {						\
550 		__C(tc_mem_write_,BYTES)(v, h, o, *a++);		\
551 		o += sizeof *a;						\
552 	}								\
553 }
554 tc_mem_write_region_N(1,u_int8_t)
555 tc_mem_write_region_N(2,u_int16_t)
556 tc_mem_write_region_N(4,u_int32_t)
557 tc_mem_write_region_N(8,u_int64_t)
558 
559 #define	tc_mem_set_multi_N(BYTES,TYPE)					\
560 void									\
561 __C(tc_mem_set_multi_,BYTES)(v, h, o, val, c)				\
562 	void *v;							\
563 	bus_space_handle_t h;						\
564 	bus_size_t o, c;						\
565 	TYPE val;							\
566 {									\
567 									\
568 	while (c-- > 0) {						\
569 		__C(tc_mem_write_,BYTES)(v, h, o, val);			\
570 		tc_mem_barrier(v, h, o, sizeof val, BUS_SPACE_BARRIER_WRITE); \
571 	}								\
572 }
573 tc_mem_set_multi_N(1,u_int8_t)
574 tc_mem_set_multi_N(2,u_int16_t)
575 tc_mem_set_multi_N(4,u_int32_t)
576 tc_mem_set_multi_N(8,u_int64_t)
577 
578 #define	tc_mem_set_region_N(BYTES,TYPE)					\
579 void									\
580 __C(tc_mem_set_region_,BYTES)(v, h, o, val, c)				\
581 	void *v;							\
582 	bus_space_handle_t h;						\
583 	bus_size_t o, c;						\
584 	TYPE val;							\
585 {									\
586 									\
587 	while (c-- > 0) {						\
588 		__C(tc_mem_write_,BYTES)(v, h, o, val);			\
589 		o += sizeof val;					\
590 	}								\
591 }
592 tc_mem_set_region_N(1,u_int8_t)
593 tc_mem_set_region_N(2,u_int16_t)
594 tc_mem_set_region_N(4,u_int32_t)
595 tc_mem_set_region_N(8,u_int64_t)
596 
597 #define	tc_mem_copy_region_N(BYTES)					\
598 void									\
599 __C(tc_mem_copy_region_,BYTES)(v, h1, o1, h2, o2, c)			\
600 	void *v;							\
601 	bus_space_handle_t h1, h2;					\
602 	bus_size_t o1, o2, c;						\
603 {									\
604 	bus_size_t o;							\
605 									\
606 	if ((h1 & TC_SPACE_SPARSE) != 0 &&				\
607 	    (h2 & TC_SPACE_SPARSE) != 0) {				\
608 		bcopy((void *)(h1 + o1), (void *)(h2 + o2), c * BYTES); \
609 		return;							\
610 	}								\
611 									\
612 	if (h1 + o1 >= h2 + o2)						\
613 		/* src after dest: copy forward */			\
614 		for (o = 0; c > 0; c--, o += BYTES)			\
615 			__C(tc_mem_write_,BYTES)(v, h2, o2 + o,		\
616 			    __C(tc_mem_read_,BYTES)(v, h1, o1 + o));	\
617 	else								\
618 		/* dest after src: copy backwards */			\
619 		for (o = (c - 1) * BYTES; c > 0; c--, o -= BYTES)	\
620 			__C(tc_mem_write_,BYTES)(v, h2, o2 + o,		\
621 			    __C(tc_mem_read_,BYTES)(v, h1, o1 + o));	\
622 }
623 tc_mem_copy_region_N(1)
624 tc_mem_copy_region_N(2)
625 tc_mem_copy_region_N(4)
626 tc_mem_copy_region_N(8)
627