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