xref: /netbsd/sys/arch/sun68k/stand/libsa/sun3x.c (revision 6550d01e)
1 /*	$NetBSD: sun3x.c,v 1.12 2009/12/11 18:45:05 tsutsui 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 /* Avoid conflicts on these: */
39 #define get_pte sun3x_get_pte
40 #define set_pte sun3x_set_pte
41 
42 #include <sys/param.h>
43 #include <machine/mon.h>
44 
45 #include <stand.h>
46 
47 #include "libsa.h"
48 #include "dvma.h"
49 #include "saio.h"	/* enum MAPTYPES */
50 
51 #include <arch/sun3/include/pte3x.h>
52 #include <arch/sun3/sun3x/iommu.h>
53 #include <arch/sun3/sun3x/vme.h>
54 
55 /* Names, names... */
56 #define	MON_LOMEM_BASE	0
57 #define	MON_LOMEM_SIZE	0x400000
58 #define MON_LOMEM_END	(MON_LOMEM_BASE+MON_LOMEM_SIZE)
59 #define MON_KDB_BASE	SUN3X_MON_KDB_BASE
60 #define MON_KDB_SIZE	SUN3X_MON_KDB_SIZE
61 #define MON_KDB_END 	(MON_KDB_BASE+MON_KDB_SIZE)
62 #define MON_DVMA_BASE	SUN3X_MON_DVMA_BASE
63 #define MON_DVMA_SIZE	SUN3X_MON_DVMA_SIZE
64 
65 void mmu_atc_flush(vaddr_t);
66 void set_iommupte(vaddr_t, paddr_t);
67 
68 u_int	get_pte(vaddr_t);
69 void	set_pte(vaddr_t, paddr_t);
70 void	dvma3x_init(void);
71 char *	dvma3x_alloc(int);
72 void	dvma3x_free(char *, int);
73 char *	dvma3x_mapin(char *, int);
74 void	dvma3x_mapout(char *, int);
75 char *	dev3x_mapin(int, u_long, int);
76 
77 struct mapinfo {
78 	int maptype;
79 	u_int base;
80 	u_int mask;
81 };
82 
83 struct mapinfo
84 sun3x_mapinfo[MAP__NTYPES] = {
85 	/* On-board memory, I/O */
86 	{ MAP_MAINMEM,   0, ~0 },
87 	{ MAP_OBIO,      0, ~0 },
88 	/* Multibus adapter (A24,A16) */
89 	{ MAP_MBMEM,     VME24D16_BASE, VME24_MASK },
90 	{ MAP_MBIO,      VME16D16_BASE, VME16_MASK },
91 	/* VME A16 */
92 	{ MAP_VME16A16D, VME16D16_BASE, VME16_MASK },
93 	{ MAP_VME16A32D, VME16D32_BASE, VME16_MASK },
94 	/* VME A24 */
95 	{ MAP_VME24A16D, VME24D16_BASE, VME24_MASK },
96 	{ MAP_VME24A32D, VME24D32_BASE, VME24_MASK },
97 	/* VME A32 */
98 	{ MAP_VME32A16D, VME32D16_BASE, VME32_MASK },
99 	{ MAP_VME32A32D, VME32D32_BASE, VME32_MASK },
100 };
101 
102 /* The virtual address we will use for PROM device mappings. */
103 u_int sun3x_devmap = MON_KDB_BASE;
104 
105 char *
106 dev3x_mapin(int maptype, u_long physaddr, int length)
107 {
108 	u_int i, pa, pte, pgva, va;
109 
110 	if ((sun3x_devmap + length) > (MON_KDB_BASE + MON_KDB_SIZE))
111 		panic("dev3x_mapin: length=%d", length);
112 
113 	for (i = 0; i < MAP__NTYPES; i++)
114 		if (sun3x_mapinfo[i].maptype == maptype)
115 			goto found;
116 	panic("dev3x_mapin: bad maptype");
117 found:
118 
119 	if (physaddr & ~(sun3x_mapinfo[i].mask))
120 		panic("dev3x_mapin: bad address");
121 	pa = sun3x_mapinfo[i].base + physaddr;
122 
123 	pte = pa | MMU_DT_PAGE | MMU_SHORT_PTE_CI;
124 
125 	va = pgva = sun3x_devmap;
126 	do {
127 		set_pte(pgva, pte);
128 		pgva += NBPG;
129 		pte += NBPG;
130 		length -= NBPG;
131 	} while (length > 0);
132 	sun3x_devmap = pgva;
133 	va += (physaddr & PGOFSET);
134 
135 #ifdef	DEBUG_PROM
136 	if (debug)
137 		printf("dev3x_mapin: va=0x%x pte=0x%x\n",
138 			   va, get_pte(va));
139 #endif
140 	return ((char*)va);
141 }
142 
143 /*****************************************************************
144  * DVMA support
145  */
146 
147 #define SA_MIN_VA	0x200000
148 #define SA_MAX_VA	(SA_MIN_VA + MON_DVMA_SIZE - (8 * NBPG))
149 
150 #define	MON_DVMA_MAPLEN	(MON_DVMA_SIZE - NBPG)
151 
152 /* This points to the end of the free DVMA space. */
153 u_int dvma3x_end = MON_DVMA_BASE + MON_DVMA_MAPLEN;
154 
155 void
156 dvma3x_init(void)
157 {
158 	u_int va, pa;
159 
160 	pa = SA_MIN_VA;
161 	va = MON_DVMA_BASE;
162 
163 	while (pa < SA_MAX_VA) {
164 		set_pte(va, pa | MMU_DT_PAGE | MMU_SHORT_PTE_CI);
165 		set_iommupte(va, pa | IOMMU_PDE_DT_VALID | IOMMU_PDE_CI);
166 		va += NBPG;
167 		pa += NBPG;
168 	}
169 }
170 
171 /* Convert a local address to a DVMA address. */
172 char *
173 dvma3x_mapin(char *addr, int len)
174 {
175 	int va = (int)addr;
176 
177 	/* Make sure the address is in the DVMA map. */
178 	if ((va < SA_MIN_VA) || (va >= SA_MAX_VA))
179 		panic("dvma3x_mapin");
180 
181 	va -= SA_MIN_VA;
182 	va += MON_DVMA_BASE;
183 
184 	return ((char *) va);
185 }
186 
187 /* Convert a DVMA address to a local address. */
188 void
189 dvma3x_mapout(char *addr, int len)
190 {
191 	int va = (int)addr;
192 
193 	/* Make sure the address is in the DVMA map. */
194 	if ((va < MON_DVMA_BASE) ||
195 		(va >= (MON_DVMA_BASE + MON_DVMA_MAPLEN)))
196 		panic("dvma3x_mapout");
197 }
198 
199 char *
200 dvma3x_alloc(int len)
201 {
202 	len = m68k_round_page(len);
203 	dvma3x_end -= len;
204 	return((char *)dvma3x_end);
205 }
206 
207 void
208 dvma3x_free(char *dvma, int len)
209 {
210 	/* not worth the trouble */
211 }
212 
213 /*****************************************************************
214  * MMU (and I/O MMU) support
215  */
216 
217 u_int
218 get_pte(vaddr_t va)
219 {
220 	u_int	pn;
221 	mmu_short_pte_t *tbl;
222 
223 	if (va >= MON_LOMEM_BASE && va < MON_LOMEM_END) {
224 		tbl = (mmu_short_pte_t *) *romVectorPtr->lomemptaddr;
225 	} else if (va >= MON_KDB_BASE && va < MON_KDB_END) {
226 		va -= MON_KDB_BASE;
227 		tbl = (mmu_short_pte_t *) *romVectorPtr->monptaddr;
228 	} else if (va >= MON_DVMA_BASE) {
229 		va -= MON_DVMA_BASE;
230 		tbl = (mmu_short_pte_t *) *romVectorPtr->shadowpteaddr;
231 	} else {
232 		return 0;
233 	}
234 
235 	/* Calculate the page number within the selected table. */
236 	pn = (va >> MMU_PAGE_SHIFT);
237 	/* Extract the PTE from the table. */
238 	return tbl[pn].attr.raw;
239 }
240 
241 void
242 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 void
278 mmu_atc_flush(vaddr_t va)
279 {
280 
281 	__asm volatile ("pflush	#0,#0,%0@" : : "a" (va));
282 }
283 
284 void
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
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