xref: /netbsd/sys/arch/sun68k/stand/libsa/sun3.c (revision bf9ec67e)
1 /*	$NetBSD: sun3.c,v 1.3 2002/05/23 03:50:37 nathanw 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  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *        This product includes software developed by the NetBSD
21  *        Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 /*
40  * Standalone functions specific to the Sun3.
41  */
42 
43 #define _SUN3_ XXX
44 
45 /* Need to avoid conflicts on these: */
46 #define get_pte sun3_get_pte
47 #define set_pte sun3_set_pte
48 #define get_segmap sun3_get_segmap
49 #define set_segmap sun3_set_segmap
50 
51 /*
52  * We need to get the sun3 NBSG definition, even if we're
53  * building this with a different sun68k target.
54  */
55 #include <arch/sun3/include/param.h>
56 
57 #include <sys/param.h>
58 #include <machine/idprom.h>
59 #include <machine/mon.h>
60 
61 #include <arch/sun3/include/pte3.h>
62 #include <arch/sun3/sun3/control.h>
63 #include <arch/sun3/sun3/vme.h>
64 
65 #include <stand.h>
66 
67 #include "libsa.h"
68 #include "dvma.h"
69 #include "saio.h"	/* enum MAPTYPES */
70 
71 #define OBIO_MASK 0xFFFFFF
72 
73 u_int	get_pte __P((vaddr_t va));
74 void	set_pte __P((vaddr_t va, u_int pte));
75 char *	dvma3_alloc  __P((int len));
76 void	dvma3_free  __P((char *dvma, int len));
77 char *	dvma3_mapin  __P((char *pkt, int len));
78 void	dvma3_mapout  __P((char *dmabuf, int len));
79 char *	dev3_mapin  __P((int type, u_long addr, int len));
80 
81 struct mapinfo {
82 	int maptype;
83 	int pgtype;
84 	u_int base;
85 	u_int mask;
86 };
87 
88 struct mapinfo
89 sun3_mapinfo[MAP__NTYPES] = {
90 	/* On-board memory, I/O */
91 	{ MAP_MAINMEM,   PGT_OBMEM,   0,          ~0 },
92 	{ MAP_OBIO,      PGT_OBIO,    0,          OBIO_MASK },
93 	/* Multibus adapter (A24,A16) */
94 	{ MAP_MBMEM,     PGT_VME_D16, VME24_BASE, VME24_MASK },
95 	{ MAP_MBIO,      PGT_VME_D16, VME16_BASE, VME16_MASK },
96 	/* VME A16 */
97 	{ MAP_VME16A16D, PGT_VME_D16, VME16_BASE, VME16_MASK },
98 	{ MAP_VME16A32D, PGT_VME_D32, VME16_BASE, VME16_MASK },
99 	/* VME A24 */
100 	{ MAP_VME24A16D, PGT_VME_D16, VME24_BASE, VME24_MASK },
101 	{ MAP_VME24A32D, PGT_VME_D32, VME24_BASE, VME24_MASK },
102 	/* VME A32 */
103 	{ MAP_VME32A16D, PGT_VME_D16, VME32_BASE, VME32_MASK },
104 	{ MAP_VME32A32D, PGT_VME_D32, VME32_BASE, VME32_MASK },
105 };
106 
107 /* The virtual address we will use for PROM device mappings. */
108 int sun3_devmap = SUN3_MONSHORTSEG;
109 
110 char *
111 dev3_mapin(maptype, physaddr, length)
112 	int maptype;
113 	u_long physaddr;
114 	int length;
115 {
116 	u_int i, pa, pte, pgva, va;
117 
118 	if ((sun3_devmap + length) > SUN3_MONSHORTPAGE)
119 		panic("dev3_mapin: length=%d\n", length);
120 
121 	for (i = 0; i < MAP__NTYPES; i++)
122 		if (sun3_mapinfo[i].maptype == maptype)
123 			goto found;
124 	panic("dev3_mapin: bad maptype");
125 found:
126 
127 	if (physaddr & ~(sun3_mapinfo[i].mask))
128 		panic("dev3_mapin: bad address");
129 	pa = sun3_mapinfo[i].base += physaddr;
130 
131 	pte = PA_PGNUM(pa) | PG_PERM |
132 		sun3_mapinfo[i].pgtype;
133 
134 	va = pgva = sun3_devmap;
135 	do {
136 		set_pte(pgva, pte);
137 		pgva += NBPG;
138 		pte += 1;
139 		length -= NBPG;
140 	} while (length > 0);
141 	sun3_devmap = pgva;
142 	va += (physaddr & PGOFSET);
143 
144 #ifdef	DEBUG_PROM
145 	if (debug)
146 		printf("dev3_mapin: va=0x%x pte=0x%x\n",
147 			   va, get_pte(va));
148 #endif
149 	return ((char*)va);
150 }
151 
152 /*****************************************************************
153  * DVMA support
154  */
155 
156 /*
157  * The easiest way to deal with the need for DVMA mappings is to
158  * create a DVMA alias mapping of the entire address range used by
159  * the boot program.  That way, dvma_mapin can just compute the
160  * DVMA alias address, and dvma_mapout does nothing.
161  *
162  * Note that this assumes that standalone programs will do I/O
163  * operations only within range (SA_MIN_VA .. SA_MAX_VA) checked.
164  */
165 
166 #define	DVMA_BASE 0xFFf00000
167 #define DVMA_MAPLEN  0xE0000	/* 1 MB - 128K (save MONSHORTSEG) */
168 
169 #define SA_MIN_VA	0x200000
170 #define SA_MAX_VA	(SA_MIN_VA + DVMA_MAPLEN)
171 
172 /* This points to the end of the free DVMA space. */
173 u_int dvma3_end = DVMA_BASE + DVMA_MAPLEN;
174 
175 void
176 dvma3_init()
177 {
178 	int segva, dmava, sme;
179 
180 	segva = SA_MIN_VA;
181 	dmava = DVMA_BASE;
182 
183 	while (segva < SA_MAX_VA) {
184 		sme = get_segmap(segva);
185 		set_segmap(dmava, sme);
186 		segva += NBSG;
187 		dmava += NBSG;
188 	}
189 }
190 
191 /* Convert a local address to a DVMA address. */
192 char *
193 dvma3_mapin(char *addr, int len)
194 {
195 	int va = (int)addr;
196 
197 	/* Make sure the address is in the DVMA map. */
198 	if ((va < SA_MIN_VA) || (va >= SA_MAX_VA))
199 		panic("dvma3_mapin");
200 
201 	va -= SA_MIN_VA;
202 	va += DVMA_BASE;
203 
204 	return ((char *) va);
205 }
206 
207 /* Destroy a DVMA address alias. */
208 void
209 dvma3_mapout(char *addr, int len)
210 {
211 	int va = (int)addr;
212 
213 	/* Make sure the address is in the DVMA map. */
214 	if ((va < DVMA_BASE) || (va >= (DVMA_BASE + DVMA_MAPLEN)))
215 		panic("dvma3_mapout");
216 }
217 
218 char *
219 dvma3_alloc(int len)
220 {
221 	len = m68k_round_page(len);
222 	dvma3_end -= len;
223 	return((char*)dvma3_end);
224 }
225 
226 void
227 dvma3_free(char *dvma, int len)
228 {
229 	/* not worth the trouble */
230 }
231 
232 /*****************************************************************
233  * Control space stuff...
234  */
235 
236 u_int
237 get_pte(va)
238 	vaddr_t va;
239 {
240 	va = CONTROL_ADDR_BUILD(PGMAP_BASE, va);
241 	return (get_control_word(va));
242 }
243 
244 void
245 set_pte(va, pte)
246 	vaddr_t va;
247 	u_int pte;
248 {
249 	va = CONTROL_ADDR_BUILD(PGMAP_BASE, va);
250 	set_control_word(va, pte);
251 }
252 
253 int
254 get_segmap(va)
255 	vaddr_t va;
256 {
257 	va = CONTROL_ADDR_BUILD(SEGMAP_BASE, va);
258 	return (get_control_byte(va));
259 }
260 
261 void
262 set_segmap(va, sme)
263 	vaddr_t va;
264 	int sme;
265 {
266 	va = CONTROL_ADDR_BUILD(SEGMAP_BASE, va);
267 	set_control_byte(va, sme);
268 }
269 
270 /*
271  * Copy the IDPROM contents into the passed buffer.
272  * The caller (idprom.c) will do the checksum.
273  */
274 void
275 sun3_getidprom(u_char *dst)
276 {
277 	vaddr_t src;	/* control space address */
278 	int len, x;
279 
280 	src = IDPROM_BASE;
281 	len = sizeof(struct idprom);
282 	do {
283 		x = get_control_byte(src++);
284 		*dst++ = x;
285 	} while (--len > 0);
286 }
287 
288 /*****************************************************************
289  * Init our function pointers, etc.
290  */
291 
292 void
293 sun3_init()
294 {
295 
296 	/* Set the function pointers. */
297 	dev_mapin_p   = dev3_mapin;
298 	dvma_alloc_p  = dvma3_alloc;
299 	dvma_free_p   = dvma3_free;
300 	dvma_mapin_p  = dvma3_mapin;
301 	dvma_mapout_p = dvma3_mapout;
302 
303 	/* Prepare DVMA segment. */
304 	dvma3_init();
305 }
306