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