xref: /netbsd/sys/arch/sun68k/stand/libsa/sun3x.c (revision f9e02bcc)
1 /*	$NetBSD: sun3x.c,v 1.14 2020/06/20 18:46:14 riastradh Exp $	*/
2 
3 /*-
4  * Copyright (c) 1998 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Jeremy Cooper and Gordon Ross
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * Standalone functions specific to the Sun3X.
34  */
35 
36 #define _SUN3X_ XXX
37 
38 #include <sys/param.h>
39 #include <machine/mon.h>
40 
41 #include <stand.h>
42 
43 #include "libsa.h"
44 #include "dvma.h"
45 #include "saio.h"	/* enum MAPTYPES */
46 
47 #include <arch/sun3/include/pte3x.h>
48 #include <arch/sun3/sun3x/iommu.h>
49 #include <arch/sun3/sun3x/vme.h>
50 
51 /* Names, names... */
52 #define	MON_LOMEM_BASE	0
53 #define	MON_LOMEM_SIZE	0x400000
54 #define MON_LOMEM_END	(MON_LOMEM_BASE+MON_LOMEM_SIZE)
55 #define MON_KDB_BASE	SUN3X_MON_KDB_BASE
56 #define MON_KDB_SIZE	SUN3X_MON_KDB_SIZE
57 #define MON_KDB_END 	(MON_KDB_BASE+MON_KDB_SIZE)
58 #define MON_DVMA_BASE	SUN3X_MON_DVMA_BASE
59 #define MON_DVMA_SIZE	SUN3X_MON_DVMA_SIZE
60 
61 static void mmu_atc_flush(vaddr_t);
62 static void set_iommupte(vaddr_t, paddr_t);
63 
64 #ifdef	DEBUG_PROM
65 static u_int	sun3x_get_pte(vaddr_t);
66 #endif
67 static void	sun3x_set_pte(vaddr_t, paddr_t);
68 static void	dvma3x_init(void);
69 static char *	dvma3x_alloc(int);
70 static void	dvma3x_free(char *, int);
71 static char *	dvma3x_mapin(char *, int);
72 static void	dvma3x_mapout(char *, int);
73 static char *	dev3x_mapin(int, u_long, int);
74 
75 struct mapinfo {
76 	int maptype;
77 	u_int base;
78 	u_int mask;
79 };
80 
81 struct mapinfo
82 sun3x_mapinfo[MAP__NTYPES] = {
83 	/* On-board memory, I/O */
84 	{ MAP_MAINMEM,   0, ~0 },
85 	{ MAP_OBIO,      0, ~0 },
86 	/* Multibus adapter (A24,A16) */
87 	{ MAP_MBMEM,     VME24D16_BASE, VME24_MASK },
88 	{ MAP_MBIO,      VME16D16_BASE, VME16_MASK },
89 	/* VME A16 */
90 	{ MAP_VME16A16D, VME16D16_BASE, VME16_MASK },
91 	{ MAP_VME16A32D, VME16D32_BASE, VME16_MASK },
92 	/* VME A24 */
93 	{ MAP_VME24A16D, VME24D16_BASE, VME24_MASK },
94 	{ MAP_VME24A32D, VME24D32_BASE, VME24_MASK },
95 	/* VME A32 */
96 	{ MAP_VME32A16D, VME32D16_BASE, VME32_MASK },
97 	{ MAP_VME32A32D, VME32D32_BASE, VME32_MASK },
98 };
99 
100 /* The virtual address we will use for PROM device mappings. */
101 u_int sun3x_devmap = MON_KDB_BASE;
102 
103 static char *
dev3x_mapin(int maptype,u_long physaddr,int length)104 dev3x_mapin(int maptype, u_long physaddr, int length)
105 {
106 	u_int i, pa, pte, pgva, va;
107 
108 	if ((sun3x_devmap + length) > (MON_KDB_BASE + MON_KDB_SIZE))
109 		panic("dev3x_mapin: length=%d", length);
110 
111 	for (i = 0; i < MAP__NTYPES; i++)
112 		if (sun3x_mapinfo[i].maptype == maptype)
113 			goto found;
114 	panic("dev3x_mapin: bad maptype");
115 found:
116 
117 	if (physaddr & ~(sun3x_mapinfo[i].mask))
118 		panic("dev3x_mapin: bad address");
119 	pa = sun3x_mapinfo[i].base + physaddr;
120 
121 	pte = pa | MMU_DT_PAGE | MMU_SHORT_PTE_CI;
122 
123 	va = pgva = sun3x_devmap;
124 	do {
125 		sun3x_set_pte(pgva, pte);
126 		pgva += NBPG;
127 		pte += NBPG;
128 		length -= NBPG;
129 	} while (length > 0);
130 	sun3x_devmap = pgva;
131 	va += (physaddr & PGOFSET);
132 
133 #ifdef	DEBUG_PROM
134 	if (debug)
135 		printf("dev3x_mapin: va=0x%x pte=0x%x\n",
136 			   va, sun3x_get_pte(va));
137 #endif
138 	return ((char*)va);
139 }
140 
141 /*****************************************************************
142  * DVMA support
143  */
144 
145 #define SA_MIN_VA	0x200000
146 #define SA_MAX_VA	(SA_MIN_VA + MON_DVMA_SIZE - (8 * NBPG))
147 
148 #define	MON_DVMA_MAPLEN	(MON_DVMA_SIZE - NBPG)
149 
150 /* This points to the end of the free DVMA space. */
151 u_int dvma3x_end = MON_DVMA_BASE + MON_DVMA_MAPLEN;
152 
153 static void
dvma3x_init(void)154 dvma3x_init(void)
155 {
156 	u_int va, pa;
157 
158 	pa = SA_MIN_VA;
159 	va = MON_DVMA_BASE;
160 
161 	while (pa < SA_MAX_VA) {
162 		sun3x_set_pte(va, pa | MMU_DT_PAGE | MMU_SHORT_PTE_CI);
163 		set_iommupte(va, pa | IOMMU_PDE_DT_VALID | IOMMU_PDE_CI);
164 		va += NBPG;
165 		pa += NBPG;
166 	}
167 }
168 
169 /* Convert a local address to a DVMA address. */
170 char *
dvma3x_mapin(char * addr,int len)171 dvma3x_mapin(char *addr, int len)
172 {
173 	int va = (int)addr;
174 
175 	/* Make sure the address is in the DVMA map. */
176 	if ((va < SA_MIN_VA) || (va >= SA_MAX_VA))
177 		panic("dvma3x_mapin");
178 
179 	va -= SA_MIN_VA;
180 	va += MON_DVMA_BASE;
181 
182 	return ((char *) va);
183 }
184 
185 /* Convert a DVMA address to a local address. */
186 static void
dvma3x_mapout(char * addr,int len)187 dvma3x_mapout(char *addr, int len)
188 {
189 	int va = (int)addr;
190 
191 	/* Make sure the address is in the DVMA map. */
192 	if ((va < MON_DVMA_BASE) ||
193 		(va >= (MON_DVMA_BASE + MON_DVMA_MAPLEN)))
194 		panic("dvma3x_mapout");
195 }
196 
197 static char *
dvma3x_alloc(int len)198 dvma3x_alloc(int len)
199 {
200 	len = m68k_round_page(len);
201 	dvma3x_end -= len;
202 	return((char *)dvma3x_end);
203 }
204 
205 static void
dvma3x_free(char * dvma,int len)206 dvma3x_free(char *dvma, int len)
207 {
208 	/* not worth the trouble */
209 }
210 
211 /*****************************************************************
212  * MMU (and I/O MMU) support
213  */
214 
215 #ifdef	DEBUG_PROM
216 static u_int
sun3x_get_pte(vaddr_t va)217 sun3x_get_pte(vaddr_t va)
218 {
219 	u_int	pn;
220 	mmu_short_pte_t *tbl;
221 
222 	if (va >= MON_LOMEM_BASE && va < MON_LOMEM_END) {
223 		tbl = (mmu_short_pte_t *) *romVectorPtr->lomemptaddr;
224 	} else if (va >= MON_KDB_BASE && va < MON_KDB_END) {
225 		va -= MON_KDB_BASE;
226 		tbl = (mmu_short_pte_t *) *romVectorPtr->monptaddr;
227 	} else if (va >= MON_DVMA_BASE) {
228 		va -= MON_DVMA_BASE;
229 		tbl = (mmu_short_pte_t *) *romVectorPtr->shadowpteaddr;
230 	} else {
231 		return 0;
232 	}
233 
234 	/* Calculate the page number within the selected table. */
235 	pn = (va >> MMU_PAGE_SHIFT);
236 	/* Extract the PTE from the table. */
237 	return tbl[pn].attr.raw;
238 }
239 #endif
240 
241 static void
sun3x_set_pte(vaddr_t va,paddr_t pa)242 sun3x_set_pte(vaddr_t va, paddr_t pa)
243 {
244 	u_int	pn;
245 	mmu_short_pte_t *tbl;
246 
247 	if (va >= MON_LOMEM_BASE && va < (MON_LOMEM_BASE + MON_LOMEM_SIZE)) {
248 		/*
249 		 * Main memory range.
250 		 */
251 		tbl = (mmu_short_pte_t *) *romVectorPtr->lomemptaddr;
252 	} else if (va >= MON_KDB_BASE && va < (MON_KDB_BASE + MON_KDB_SIZE)) {
253 		/*
254 		 * Kernel Debugger range.
255 		 */
256 		va -= MON_KDB_BASE;
257 		tbl = (mmu_short_pte_t *) *romVectorPtr->monptaddr;
258 	} else if (va >= MON_DVMA_BASE) {
259 		/*
260 		 * DVMA range.
261 		 */
262 		va -= MON_DVMA_BASE;
263 		tbl = (mmu_short_pte_t *) *romVectorPtr->shadowpteaddr;
264 	} else {
265 		/* invalid range */
266 		return;
267 	}
268 
269 	/* Calculate the page number within the selected table. */
270 	pn = (va >> MMU_PAGE_SHIFT);
271 	/* Enter the PTE into the table. */
272 	tbl[pn].attr.raw = pa;
273 	/* Flush the ATC of any cached entries for the va. */
274 	mmu_atc_flush(va);
275 }
276 
277 static void
mmu_atc_flush(vaddr_t va)278 mmu_atc_flush(vaddr_t va)
279 {
280 
281 	__asm volatile ("pflush	#0,#0,%0@" : : "a" (va));
282 }
283 
284 static void
set_iommupte(vaddr_t va,paddr_t pa)285 set_iommupte(vaddr_t va, paddr_t pa)
286 {
287 	iommu_pde_t *iommu_va;
288 	int pn;
289 
290 	iommu_va = (iommu_pde_t *) *romVectorPtr->dvmaptaddr;
291 
292 	/* Adjust the virtual address into an offset within the DVMA map. */
293 	va -= MON_DVMA_BASE;
294 
295 	/* Convert the slave address into a page index. */
296 	pn = IOMMU_BTOP(va);
297 
298 	iommu_va[pn].addr.raw = pa;
299 }
300 
301 /*****************************************************************
302  * Init our function pointers, etc.
303  */
304 
305 void
sun3x_init(void)306 sun3x_init(void)
307 {
308 
309 	/* Set the function pointers. */
310 	dev_mapin_p   = dev3x_mapin;
311 	dvma_alloc_p  = dvma3x_alloc;
312 	dvma_free_p   = dvma3x_free;
313 	dvma_mapin_p  = dvma3x_mapin;
314 	dvma_mapout_p = dvma3x_mapout;
315 
316 	dvma3x_init();
317 }
318