machdep.c revision 1.86 1 /* $NetBSD: machdep.c,v 1.86 2003/07/15 02:46:32 lukem Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5 * Copyright (C) 1995, 1996 TooLs GmbH.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by TooLs GmbH.
19 * 4. The name of TooLs GmbH may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.86 2003/07/15 02:46:32 lukem Exp $");
36
37 #include "opt_compat_netbsd.h"
38 #include "opt_ddb.h"
39
40 #include <sys/param.h>
41 #include <sys/buf.h>
42 #include <sys/exec.h>
43 #include <sys/malloc.h>
44 #include <sys/mbuf.h>
45 #include <sys/mount.h>
46 #include <sys/msgbuf.h>
47 #include <sys/proc.h>
48 #include <sys/reboot.h>
49 #include <sys/sa.h>
50 #include <sys/syscallargs.h>
51 #include <sys/syslog.h>
52 #include <sys/systm.h>
53 #include <sys/kernel.h>
54 #include <sys/user.h>
55 #include <sys/boot_flag.h>
56 #include <sys/ksyms.h>
57
58 #include <uvm/uvm_extern.h>
59
60 #include <net/netisr.h>
61
62 #include <machine/db_machdep.h>
63 #include <ddb/db_extern.h>
64
65 #include <dev/ofw/openfirm.h>
66
67 #include <machine/autoconf.h>
68 #include <machine/bat.h>
69 #include <machine/pmap.h>
70 #include <machine/powerpc.h>
71 #include <machine/trap.h>
72
73 #include <machine/platform.h>
74
75 #include <dev/cons.h>
76
77 #include "ksyms.h"
78 /*
79 * Global variables used here and there
80 */
81 char bootpath[256];
82
83 int lcsplx(int); /* called from locore.S */
84
85 static int fake_spl __P((int));
86 static void fake_splx __P((int));
87 static void fake_setsoft __P((int));
88 static void fake_clock_return __P((struct clockframe *, int));
89 static void *fake_intr_establish __P((int, int, int, int (*)(void *), void *));
90 static void fake_intr_disestablish __P((void *));
91
92 struct machvec machine_interface = {
93 fake_spl,
94 fake_spl,
95 fake_splx,
96 fake_setsoft,
97 fake_clock_return,
98 fake_intr_establish,
99 fake_intr_disestablish,
100 };
101
102 void ofppc_bootstrap_console(void);
103
104 struct pmap ofw_pmap;
105
106 void
107 initppc(startkernel, endkernel, args)
108 u_int startkernel, endkernel;
109 char *args;
110 {
111 #if NKSYMS || defined(DDB) || defined(LKM)
112 extern void *startsym, *endsym;
113 #endif
114
115 /* Initialize the bootstrap console. */
116 ofppc_bootstrap_console();
117
118 /*
119 * Initialize the bat registers
120 */
121 oea_batinit(0);
122
123 /*
124 * Initialize the platform structure. This may add entries
125 * to the BAT table.
126 */
127 platform_init();
128
129 #ifdef __notyet__ /* Needs some rethinking regarding real/virtual OFW */
130 OF_set_callback(callback);
131 #endif
132
133 oea_init(NULL);
134
135 /*
136 * Now that translation is enabled (and we can access bus space),
137 * initialize the console.
138 */
139 (*platform.cons_init)();
140
141 /*
142 * Parse arg string.
143 */
144 strcpy(bootpath, args);
145 while (*++args && *args != ' ');
146 if (*args) {
147 for(*args++ = 0; *args; args++)
148 BOOT_FLAG(*args, boothowto);
149 }
150
151 /*
152 * Set the page size.
153 */
154 uvm_setpagesize();
155
156 /*
157 * Initialize pmap module.
158 */
159 pmap_bootstrap(startkernel, endkernel);
160
161 #if NKSYMS || defined(DDB) || defined(LKM)
162 ksyms_init((int)((u_int)endsym - (u_int)startsym), startsym, endsym);
163 #endif
164 #ifdef DDB
165 if (boothowto & RB_KDB)
166 Debugger();
167 #endif
168 #ifdef IPKDB
169 /*
170 * Now trap to IPKDB
171 */
172 ipkdb_init();
173 if (boothowto & RB_KDB)
174 ipkdb_connect(0);
175 #endif
176 }
177
178 /*
179 * Machine dependent startup code.
180 */
181 void
182 cpu_startup()
183 {
184
185 oea_startup(NULL);
186
187 /*
188 * Now allow hardware interrupts.
189 */
190 splhigh();
191 mtmsr(mfmsr() | PSL_EE | PSL_RI);
192 if (platform.softintr_init != NULL)
193 platform.softintr_init();
194 }
195
196 void
197 consinit()
198 {
199
200 (*cn_tab->cn_probe)(cn_tab);
201 }
202
203 void ofcons_cnprobe(struct consdev *);
204 int ofppc_cngetc(dev_t);
205 void ofppc_cnputc(dev_t, int);
206
207 struct consdev ofppc_bootcons = {
208 ofcons_cnprobe, NULL, ofppc_cngetc, ofppc_cnputc, nullcnpollc, NULL,
209 NULL, NULL, makedev(0,0), 1,
210 };
211
212 int ofppc_stdin_ihandle, ofppc_stdout_ihandle;
213 int ofppc_stdin_phandle, ofppc_stdout_phandle;
214
215 void
216 ofppc_bootstrap_console(void)
217 {
218 int chosen;
219 char data[4];
220
221 chosen = OF_finddevice("/chosen");
222
223 if (OF_getprop(chosen, "stdin", data, sizeof(data)) != sizeof(int))
224 goto nocons;
225 ofppc_stdin_ihandle = of_decode_int(data);
226 ofppc_stdin_phandle = OF_instance_to_package(ofppc_stdin_ihandle);
227
228 if (OF_getprop(chosen, "stdout", data, sizeof(data)) != sizeof(int))
229 goto nocons;
230 ofppc_stdout_ihandle = of_decode_int(data);
231 ofppc_stdout_phandle = OF_instance_to_package(ofppc_stdout_ihandle);
232
233 cn_tab = &ofppc_bootcons;
234
235 nocons:
236 return;
237 }
238
239 int
240 ofppc_cngetc(dev_t dev)
241 {
242 u_char ch = '\0';
243 int l;
244
245 while ((l = OF_read(ofppc_stdin_ihandle, &ch, 1)) != 1)
246 if (l != -2 && l != 0)
247 return (-1);
248
249 return (ch);
250 }
251
252 void
253 ofppc_cnputc(dev_t dev, int c)
254 {
255 char ch = c;
256
257 OF_write(ofppc_stdout_ihandle, &ch, 1);
258 }
259
260 /*
261 * Crash dump handling.
262 */
263
264 /*
265 * Stray interrupts.
266 */
267 void
268 strayintr(irq)
269 int irq;
270 {
271 log(LOG_ERR, "stray interrupt %d\n", irq);
272 }
273
274 /*
275 * Halt or reboot the machine after syncing/dumping according to howto.
276 */
277 void
278 cpu_reboot(howto, what)
279 int howto;
280 char *what;
281 {
282 static int syncing;
283 static char str[256];
284 char *ap = str, *ap1 = ap;
285
286 boothowto = howto;
287 if (!cold && !(howto & RB_NOSYNC) && !syncing) {
288 syncing = 1;
289 vfs_shutdown(); /* sync */
290 resettodr(); /* set wall clock */
291 }
292 splhigh();
293 if (howto & RB_HALT) {
294 doshutdownhooks();
295 printf("halted\n\n");
296 ppc_exit();
297 }
298 if (!cold && (howto & RB_DUMP))
299 oea_dumpsys();
300 doshutdownhooks();
301 printf("rebooting\n\n");
302 if (what && *what) {
303 if (strlen(what) > sizeof str - 5)
304 printf("boot string too large, ignored\n");
305 else {
306 strcpy(str, what);
307 ap1 = ap = str + strlen(str);
308 *ap++ = ' ';
309 }
310 }
311 *ap++ = '-';
312 if (howto & RB_SINGLE)
313 *ap++ = 's';
314 if (howto & RB_KDB)
315 *ap++ = 'd';
316 *ap++ = 0;
317 if (ap[-2] == '-')
318 *ap1 = 0;
319 ppc_boot(str);
320 }
321
322 #ifdef notyet
323 /*
324 * OpenFirmware callback routine
325 */
326 void
327 callback(p)
328 void *p;
329 {
330 panic("callback"); /* for now XXX */
331 }
332 #endif
333
334 /*
335 * Perform an `splx()' for locore.
336 */
337 int
338 lcsplx(int ipl)
339 {
340
341 return (_spllower(ipl));
342 }
343
344 /*
345 * Initial Machine Interface.
346 */
347 static int
348 fake_spl(int new)
349 {
350 int scratch;
351
352 asm volatile ("mfmsr %0; andi. %0,%0,%1; mtmsr %0; isync"
353 : "=r"(scratch) : "K"((u_short)~(PSL_EE|PSL_ME)));
354 return (-1);
355 }
356
357 static void
358 fake_setsoft(int ipl)
359 {
360 /* Do nothing */
361 }
362
363 static void
364 fake_splx(new)
365 int new;
366 {
367
368 (void) fake_spl(0);
369 }
370
371 static void
372 fake_clock_return(frame, nticks)
373 struct clockframe *frame;
374 int nticks;
375 {
376 /* Do nothing */
377 }
378
379 static void *
380 fake_intr_establish(irq, level, ist, handler, arg)
381 int irq, level, ist;
382 int (*handler) __P((void *));
383 void *arg;
384 {
385
386 panic("fake_intr_establish");
387 }
388
389 static void
390 fake_intr_disestablish(cookie)
391 void *cookie;
392 {
393
394 panic("fake_intr_disestablish");
395 }
396