xref: /netbsd-src/sys/arch/sun68k/stand/libsa/sun3x.c (revision 0f00d469bace4f1eb4f6b51acfc7c22fba0effac)
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