xref: /netbsd/sys/arch/vax/vax/locore.c (revision bf9ec67e)
1 /*	$NetBSD: locore.c,v 1.63 2001/09/28 11:59:54 chs Exp $	*/
2 /*
3  * Copyright (c) 1994, 1998 Ludd, University of Lule}, Sweden.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *     This product includes software developed at Ludd, University of Lule}.
17  * 4. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32  /* All bugs are subject to removal without further notice */
33 
34 #include "opt_compat_netbsd.h"
35 
36 #include <sys/param.h>
37 #include <sys/reboot.h>
38 #include <sys/device.h>
39 #include <sys/systm.h>
40 #include <sys/user.h>
41 #include <sys/proc.h>
42 
43 #include <uvm/uvm_extern.h>
44 
45 #include <machine/cpu.h>
46 #include <machine/sid.h>
47 #include <machine/param.h>
48 #include <machine/vmparam.h>
49 #include <machine/pcb.h>
50 #include <machine/pte.h>
51 #include <machine/pmap.h>
52 #include <machine/nexus.h>
53 #include <machine/rpb.h>
54 
55 #include "opt_cputype.h"
56 
57 void	_start(struct rpb *);
58 void	main(void);
59 
60 extern	paddr_t avail_end;
61 paddr_t esym;
62 u_int	proc0paddr;
63 
64 /*
65  * The strict cpu-dependent information is set up here, in
66  * form of a pointer to a struct that is specific for each cpu.
67  */
68 extern struct cpu_dep ka780_calls;
69 extern struct cpu_dep ka750_calls;
70 extern struct cpu_dep ka860_calls;
71 extern struct cpu_dep ka820_calls;
72 extern struct cpu_dep ka6400_calls;
73 extern struct cpu_dep ka88_calls;
74 extern struct cpu_dep ka43_calls;
75 extern struct cpu_dep ka46_calls;
76 extern struct cpu_dep ka48_calls;
77 extern struct cpu_dep ka49_calls;
78 extern struct cpu_dep ka53_calls;
79 extern struct cpu_dep ka410_calls;
80 extern struct cpu_dep ka610_calls;
81 extern struct cpu_dep ka630_calls;
82 extern struct cpu_dep ka650_calls;
83 extern struct cpu_dep ka660_calls;
84 extern struct cpu_dep ka670_calls;
85 extern struct cpu_dep ka680_calls;
86 
87 /*
88  * Start is called from boot; the first routine that is called
89  * in kernel. Kernel stack is setup somewhere in a safe place;
90  * but we need to move it to a better known place. Memory
91  * management is disabled, and no interrupt system is active.
92  */
93 void
94 _start(struct rpb *prpb)
95 {
96 	extern void *scratch;
97 	struct pte *pt;
98 
99 	mtpr(AST_NO, PR_ASTLVL); /* Turn off ASTs */
100 
101 	findcpu(); /* Set up the CPU identifying variables */
102 
103 	cpu_model[0] = 0; /* Be sure */
104 	if (vax_confdata & 0x80)
105 		strcpy(cpu_model, "MicroVAX ");
106 	else
107 		strcpy(cpu_model, "VAXstation ");
108 
109 	switch (vax_boardtype) {
110 #if VAX780 || VAXANY
111 	case VAX_BTYP_780:
112 		dep_call = &ka780_calls;
113 		strcpy(cpu_model,"VAX 11/780");
114 		if (vax_cpudata & 0x100)
115 			cpu_model[9] = '5';
116 		break;
117 #endif
118 #if VAX750 || VAXANY
119 	case VAX_BTYP_750:
120 		dep_call = &ka750_calls;
121 		strcpy(cpu_model, "VAX 11/750");
122 		break;
123 #endif
124 #if VAX8600 || VAXANY
125 	case VAX_BTYP_790:
126 		dep_call = &ka860_calls;
127 		strcpy(cpu_model,"VAX 8600");
128 		if (vax_cpudata & 0x100)
129 			cpu_model[6] = '5';
130 		break;
131 #endif
132 #if VAX410 || VAXANY
133 	case VAX_BTYP_420: /* They are very similar */
134 		dep_call = &ka410_calls;
135 		strcat(cpu_model, "3100");
136 		if (((vax_siedata >> 8) & 0xff) == 1)
137 			strcat(cpu_model, "/m{38,48}");
138 		else if (((vax_siedata >> 8) & 0xff) == 0)
139 			strcat(cpu_model, "/m{30,40}");
140 		break;
141 
142 	case VAX_BTYP_410:
143 		dep_call = &ka410_calls;
144 		strcat(cpu_model, "2000");
145 		break;
146 #endif
147 #if VAX43 || VAXANY
148 	case VAX_BTYP_43:
149 		dep_call = &ka43_calls;
150 		strcat(cpu_model, "3100/m76");
151 		break;
152 #endif
153 #if VAX46 || VAXANY
154 	case VAX_BTYP_46:
155 		dep_call = &ka46_calls;
156 		switch(vax_siedata & 0x3) {
157 			case 1: strcpy(cpu_model, "MicroVAX 3100/80"); break;
158 			case 2: strcpy(cpu_model, "VAXstation 4000/60"); break;
159 			default: strcpy(cpu_model, "unknown"); break;
160 		}
161 		break;
162 #endif
163 #if VAX48 || VAXANY
164 	case VAX_BTYP_48:
165 		dep_call = &ka48_calls;
166 		switch (vax_siedata & 3) {
167 		case 1: strcpy(cpu_model, "MicroVAX 3100/m{30,40}"); break;
168 		case 2: strcpy(cpu_model, "VAXstation 4000 VLC"); break;
169 		default: strcpy(cpu_model, "unknown SOC"); break;
170 		}
171 		break;
172 #endif
173 #if VAX49 || VAXANY
174 	case VAX_BTYP_49:
175 		dep_call = &ka49_calls;
176 		strcat(cpu_model, "4000/90");
177 		break;
178 #endif
179 #if VAX53 || VAXANY
180 	case VAX_BTYP_53:
181 		dep_call = &ka53_calls;
182 		switch((vax_siedata & 0xff00) >> 8) {
183 		case VAX_STYP_51:
184 			strcpy(cpu_model, "MicroVAX 3100/m{90,95}"); break;
185 		case VAX_STYP_52:
186 			strcpy(cpu_model, "VAX 4000/100"); break;
187 		case VAX_STYP_53:
188 			strcpy(cpu_model, "VAX 4000/{105A,106A,108}"); break;
189 		case VAX_STYP_55:
190 			strcpy(cpu_model, "MicroVAX 3100/m85"); break;
191 		default:
192 			strcpy(cpu_model,"unknown 1303");
193 		}
194 		break;
195 #endif
196 #if VAX610 || VAXANY
197 	case VAX_BTYP_610:
198 		dep_call = &ka610_calls;
199 		strcpy(cpu_model,"MicroVAX I");
200 		break;
201 #endif
202 #if VAX630 || VAXANY
203 	case VAX_BTYP_630:
204 		dep_call = &ka630_calls;
205 		strcpy(cpu_model,"MicroVAX II");
206 		break;
207 #endif
208 #if VAX650 || VAXANY
209 	case VAX_BTYP_650:
210 		dep_call = &ka650_calls;
211 		strcpy(cpu_model,"MicroVAX ");
212 		switch ((vax_siedata >> 8) & 255) {
213 		case VAX_SIE_KA640:
214 			strcat(cpu_model, "3300/3400");
215 			break;
216 
217 		case VAX_SIE_KA650:
218 			strcat(cpu_model, "3500/3600");
219 			break;
220 
221 		case VAX_SIE_KA655:
222 			strcat(cpu_model, "3800/3900");
223 			break;
224 
225 		default:
226 			strcat(cpu_model, "III");
227 			break;
228 		}
229 		break;
230 #endif
231 #if VAX660 || VAXANY
232 	case VAX_BTYP_660:
233 		dep_call = &ka660_calls;
234 		strcpy(cpu_model,"VAX 4000/200");
235 		break;
236 #endif
237 #if VAX670 || VAXANY
238 	case VAX_BTYP_670:
239 		dep_call = &ka670_calls;
240 		strcpy(cpu_model,"VAX 4000/300");
241 		break;
242 #endif
243 #if VAX680 || VAXANY
244 	case VAX_BTYP_680:
245 		dep_call = &ka680_calls;
246 		switch((vax_siedata & 0xff00) >> 8) {
247 		case VAX_STYP_675:
248 			strcpy(cpu_model,"VAX 4000/400"); break;
249 		case VAX_STYP_680:
250 			strcpy(cpu_model,"VAX 4000/500"); break;
251 		default:
252 			strcpy(cpu_model,"unknown 1301");
253 		}
254 		break;
255 	case VAX_BTYP_681:
256 		dep_call = &ka680_calls;
257 		switch((vax_siedata & 0xff00) >> 8) {
258 		case VAX_STYP_681:
259 			strcpy(cpu_model,"VAX 4000/500A"); break;
260 		case VAX_STYP_691:
261 			strcpy(cpu_model,"VAX 4000/600A"); break;
262 		case VAX_STYP_694:
263 			strcpy(cpu_model,"VAX 4000/705A"); break;
264 		default:
265 			strcpy(cpu_model,"unknown 1305");
266 		}
267 		break;
268 #endif
269 #if VAX8200 || VAXANY
270 	case VAX_BTYP_8000:
271 		dep_call = &ka820_calls;
272 		strcpy(cpu_model, "VAX 8200");
273 		break;
274 #endif
275 #if VAX8800 || VAXANY
276 	case VAX_BTYP_8PS:
277 	case VAX_BTYP_8800: /* Matches all other KA88-machines also */
278 		strcpy(cpu_model, "VAX 8800");
279 		dep_call = &ka88_calls;
280 		break;
281 #endif
282 #if VAX6400 || VAXANY
283 	case VAX_BTYP_9RR:
284 		/* cpu_model set in steal_pages */
285 		dep_call = &ka6400_calls;
286 		break;
287 #endif
288 	default:
289 		/* CPU not supported, just give up */
290 		asm("halt");
291 	}
292 
293 	/*
294 	 * Machines older than MicroVAX II have their boot blocks
295 	 * loaded directly or the boot program loaded from console
296 	 * media, so we need to figure out their memory size.
297 	 * This is not easily done on MicroVAXen, so we get it from
298 	 * VMB instead.
299 	 *
300 	 * In post-1.4 a RPB is always provided from the boot blocks.
301 	 */
302 #if defined(COMPAT_14)
303 	if (prpb == 0) {
304 		bzero((caddr_t)proc0paddr + REDZONEADDR, sizeof(struct rpb));
305 		prpb = (struct rpb *)(proc0paddr + REDZONEADDR);
306 		prpb->pfncnt = avail_end >> VAX_PGSHIFT;
307 		prpb->rpb_base = (void *)-1;	/* RPB is fake */
308 	} else
309 #endif
310 	bcopy(prpb, (caddr_t)proc0paddr + REDZONEADDR, sizeof(struct rpb));
311 	if (prpb->pfncnt)
312 		avail_end = prpb->pfncnt << VAX_PGSHIFT;
313 	else
314 		while (badaddr((caddr_t)avail_end, 4) == 0)
315 			avail_end += VAX_NBPG * 128;
316 	boothowto = prpb->rpb_bootr5;
317 
318 	avail_end &= ~PGOFSET; /* be sure */
319 
320 	proc0.p_addr = (void *)proc0paddr; /* XXX */
321 
322 	/* Clear the used parts of the uarea except for the pcb */
323 	bzero(&proc0.p_addr->u_stats, sizeof(struct user) - sizeof(struct pcb));
324 
325 	pmap_bootstrap();
326 
327 	/* Now running virtual. set red zone for proc0 */
328 	pt = kvtopte((u_int)proc0.p_addr + REDZONEADDR);
329 	pt->pg_v = 0;
330 
331 	((struct pcb *)proc0paddr)->framep = scratch;
332 
333 	/*
334 	 * Change mode down to userspace is done by faking a stack
335 	 * frame that is setup in cpu_set_kpc(). Not done by returning
336 	 * from main anymore.
337 	 */
338 	main();
339 	/* NOTREACHED */
340 }
341