xref: /netbsd/sys/arch/sun68k/stand/libsa/sun3.c (revision 6550d01e)
1 /*	$NetBSD: sun3.c,v 1.9 2009/12/11 18:42: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 Gordon W. 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 Sun3.
34  */
35 
36 #define _SUN3_ XXX
37 
38 /* Need to avoid conflicts on these: */
39 #define get_pte sun3_get_pte
40 #define set_pte sun3_set_pte
41 #define get_segmap sun3_get_segmap
42 #define set_segmap sun3_set_segmap
43 
44 /*
45  * We need to get the sun3 NBSG definition, even if we're
46  * building this with a different sun68k target.
47  */
48 #include <arch/sun3/include/pmap3.h>
49 
50 #include <sys/param.h>
51 #include <machine/idprom.h>
52 #include <machine/mon.h>
53 
54 #include <arch/sun3/include/pte3.h>
55 #include <arch/sun3/sun3/control.h>
56 #include <arch/sun3/sun3/vme.h>
57 
58 #include <stand.h>
59 
60 #include "libsa.h"
61 #include "dvma.h"
62 #include "saio.h"	/* enum MAPTYPES */
63 
64 #define OBIO_MASK 0xFFFFFF
65 
66 u_int	get_pte(vaddr_t);
67 void	set_pte(vaddr_t, u_int);
68 void	dvma3_init(void);
69 char *	dvma3_alloc(int);
70 void	dvma3_free(char *, int);
71 char *	dvma3_mapin(char *, int);
72 void	dvma3_mapout(char *, int);
73 char *	dev3_mapin(int, u_long, int);
74 
75 struct mapinfo {
76 	int maptype;
77 	int pgtype;
78 	u_int base;
79 	u_int mask;
80 };
81 
82 struct mapinfo
83 sun3_mapinfo[MAP__NTYPES] = {
84 	/* On-board memory, I/O */
85 	{ MAP_MAINMEM,   PGT_OBMEM,   0,          ~0 },
86 	{ MAP_OBIO,      PGT_OBIO,    0,          OBIO_MASK },
87 	/* Multibus adapter (A24,A16) */
88 	{ MAP_MBMEM,     PGT_VME_D16, VME24_BASE, VME24_MASK },
89 	{ MAP_MBIO,      PGT_VME_D16, VME16_BASE, VME16_MASK },
90 	/* VME A16 */
91 	{ MAP_VME16A16D, PGT_VME_D16, VME16_BASE, VME16_MASK },
92 	{ MAP_VME16A32D, PGT_VME_D32, VME16_BASE, VME16_MASK },
93 	/* VME A24 */
94 	{ MAP_VME24A16D, PGT_VME_D16, VME24_BASE, VME24_MASK },
95 	{ MAP_VME24A32D, PGT_VME_D32, VME24_BASE, VME24_MASK },
96 	/* VME A32 */
97 	{ MAP_VME32A16D, PGT_VME_D16, VME32_BASE, VME32_MASK },
98 	{ MAP_VME32A32D, PGT_VME_D32, VME32_BASE, VME32_MASK },
99 };
100 
101 /* The virtual address we will use for PROM device mappings. */
102 int sun3_devmap = SUN3_MONSHORTSEG;
103 
104 char *
105 dev3_mapin(int maptype, u_long physaddr, int length)
106 {
107 	u_int i, pa, pte, pgva, va;
108 
109 	if ((sun3_devmap + length) > SUN3_MONSHORTPAGE)
110 		panic("dev3_mapin: length=%d", length);
111 
112 	for (i = 0; i < MAP__NTYPES; i++)
113 		if (sun3_mapinfo[i].maptype == maptype)
114 			goto found;
115 	panic("dev3_mapin: bad maptype");
116 found:
117 
118 	if (physaddr & ~(sun3_mapinfo[i].mask))
119 		panic("dev3_mapin: bad address");
120 	pa = sun3_mapinfo[i].base += physaddr;
121 
122 	pte = PA_PGNUM(pa) | PG_PERM | sun3_mapinfo[i].pgtype;
123 
124 	va = pgva = sun3_devmap;
125 	do {
126 		set_pte(pgva, pte);
127 		pgva += NBPG;
128 		pte += 1;
129 		length -= NBPG;
130 	} while (length > 0);
131 	sun3_devmap = pgva;
132 	va += (physaddr & PGOFSET);
133 
134 #ifdef	DEBUG_PROM
135 	if (debug)
136 		printf("dev3_mapin: va=0x%x pte=0x%x\n",
137 			   va, get_pte(va));
138 #endif
139 	return ((char*)va);
140 }
141 
142 /*****************************************************************
143  * DVMA support
144  */
145 
146 /*
147  * The easiest way to deal with the need for DVMA mappings is to
148  * create a DVMA alias mapping of the entire address range used by
149  * the boot program.  That way, dvma_mapin can just compute the
150  * DVMA alias address, and dvma_mapout does nothing.
151  *
152  * Note that this assumes that standalone programs will do I/O
153  * operations only within range (SA_MIN_VA .. SA_MAX_VA) checked.
154  */
155 
156 #define	DVMA_BASE 0xFFf00000
157 #define DVMA_MAPLEN  0xE0000	/* 1 MB - 128K (save MONSHORTSEG) */
158 
159 #define SA_MIN_VA	0x200000
160 #define SA_MAX_VA	(SA_MIN_VA + DVMA_MAPLEN)
161 
162 /* This points to the end of the free DVMA space. */
163 u_int dvma3_end = DVMA_BASE + DVMA_MAPLEN;
164 
165 void
166 dvma3_init(void)
167 {
168 	int segva, dmava, sme;
169 
170 	segva = SA_MIN_VA;
171 	dmava = DVMA_BASE;
172 
173 	while (segva < SA_MAX_VA) {
174 		sme = get_segmap(segva);
175 		set_segmap(dmava, sme);
176 		segva += NBSG;
177 		dmava += NBSG;
178 	}
179 }
180 
181 /* Convert a local address to a DVMA address. */
182 char *
183 dvma3_mapin(char *addr, int len)
184 {
185 	int va = (int)addr;
186 
187 	/* Make sure the address is in the DVMA map. */
188 	if ((va < SA_MIN_VA) || (va >= SA_MAX_VA))
189 		panic("dvma3_mapin");
190 
191 	va -= SA_MIN_VA;
192 	va += DVMA_BASE;
193 
194 	return ((char *) va);
195 }
196 
197 /* Destroy a DVMA address alias. */
198 void
199 dvma3_mapout(char *addr, int len)
200 {
201 	int va = (int)addr;
202 
203 	/* Make sure the address is in the DVMA map. */
204 	if ((va < DVMA_BASE) || (va >= (DVMA_BASE + DVMA_MAPLEN)))
205 		panic("dvma3_mapout");
206 }
207 
208 char *
209 dvma3_alloc(int len)
210 {
211 	len = m68k_round_page(len);
212 	dvma3_end -= len;
213 	return((char*)dvma3_end);
214 }
215 
216 void
217 dvma3_free(char *dvma, int len)
218 {
219 	/* not worth the trouble */
220 }
221 
222 /*****************************************************************
223  * Control space stuff...
224  */
225 
226 u_int
227 get_pte(vaddr_t va)
228 {
229 	va = CONTROL_ADDR_BUILD(PGMAP_BASE, va);
230 	return (get_control_word(va));
231 }
232 
233 void
234 set_pte(vaddr_t va, u_int pte)
235 {
236 	va = CONTROL_ADDR_BUILD(PGMAP_BASE, va);
237 	set_control_word(va, pte);
238 }
239 
240 int
241 get_segmap(vaddr_t va)
242 {
243 	va = CONTROL_ADDR_BUILD(SEGMAP_BASE, va);
244 	return (get_control_byte(va));
245 }
246 
247 void
248 set_segmap(vaddr_t va, int sme)
249 {
250 	va = CONTROL_ADDR_BUILD(SEGMAP_BASE, va);
251 	set_control_byte(va, sme);
252 }
253 
254 /*
255  * Copy the IDPROM contents into the passed buffer.
256  * The caller (idprom.c) will do the checksum.
257  */
258 void
259 sun3_getidprom(u_char *dst)
260 {
261 	vaddr_t src;	/* control space address */
262 	int len, x;
263 
264 	src = IDPROM_BASE;
265 	len = sizeof(struct idprom);
266 	do {
267 		x = get_control_byte(src++);
268 		*dst++ = x;
269 	} while (--len > 0);
270 }
271 
272 /*****************************************************************
273  * Init our function pointers, etc.
274  */
275 
276 void
277 sun3_init(void)
278 {
279 
280 	/* Set the function pointers. */
281 	dev_mapin_p   = dev3_mapin;
282 	dvma_alloc_p  = dvma3_alloc;
283 	dvma_free_p   = dvma3_free;
284 	dvma_mapin_p  = dvma3_mapin;
285 	dvma_mapout_p = dvma3_mapout;
286 
287 	/* Prepare DVMA segment. */
288 	dvma3_init();
289 }
290