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