xref: /netbsd/sys/arch/macppc/macppc/machdep.c (revision bf9ec67e)
1 /*	$NetBSD: machdep.c,v 1.113 2002/05/13 06:05:33 matt 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 "opt_compat_netbsd.h"
35 #include "opt_ddb.h"
36 #include "opt_kgdb.h"
37 #include "opt_ipkdb.h"
38 #include "opt_multiprocessor.h"
39 #include "adb.h"
40 #include "zsc.h"
41 
42 #include <sys/param.h>
43 #include <sys/buf.h>
44 #include <sys/exec.h>
45 #include <sys/malloc.h>
46 #include <sys/map.h>
47 #include <sys/mbuf.h>
48 #include <sys/mount.h>
49 #include <sys/msgbuf.h>
50 #include <sys/proc.h>
51 #include <sys/reboot.h>
52 #include <sys/syscallargs.h>
53 #include <sys/syslog.h>
54 #include <sys/systm.h>
55 #include <sys/kernel.h>
56 #include <sys/user.h>
57 #include <sys/boot_flag.h>
58 
59 #include <uvm/uvm_extern.h>
60 
61 #include <net/netisr.h>
62 
63 #ifdef DDB
64 #include <machine/db_machdep.h>
65 #include <ddb/db_extern.h>
66 #endif
67 
68 #ifdef KGDB
69 #include <sys/kgdb.h>
70 #endif
71 
72 #ifdef IPKDB
73 #include <ipkdb/ipkdb.h>
74 #endif
75 
76 #include <machine/autoconf.h>
77 #include <machine/bat.h>
78 #include <machine/powerpc.h>
79 #include <machine/trap.h>
80 #include <machine/bus.h>
81 #include <machine/fpu.h>
82 
83 #include <dev/cons.h>
84 #include <dev/ofw/openfirm.h>
85 
86 #include <dev/wscons/wsksymvar.h>
87 #include <dev/wscons/wscons_callbacks.h>
88 
89 #include <dev/usb/ukbdvar.h>
90 
91 #include <macppc/dev/adbvar.h>
92 
93 #if NZSC > 0
94 #include <machine/z8530var.h>
95 #endif
96 
97 struct vm_map *exec_map = NULL;
98 struct vm_map *mb_map = NULL;
99 struct vm_map *phys_map = NULL;
100 
101 /*
102  * Global variables used here and there
103  */
104 #ifndef MULTIPROCESSOR
105 struct pcb *curpcb;
106 struct pmap *curpm;
107 struct proc *fpuproc;
108 #endif
109 
110 extern struct user *proc0paddr;
111 extern int ofmsr;
112 
113 struct bat battable[16];
114 char bootpath[256];
115 paddr_t msgbuf_paddr;
116 static int chosen;
117 struct pmap ofw_pmap;
118 int ofkbd_ihandle;
119 
120 #ifdef DDB
121 void *startsym, *endsym;
122 #endif
123 
124 struct ofw_translations {
125 	vaddr_t va;
126 	int len;
127 	paddr_t pa;
128 	int mode;
129 };
130 
131 int ofkbd_cngetc(dev_t);
132 void cninit_kd(void);
133 int lcsplx(int);
134 int save_ofmap(struct ofw_translations *, int);
135 void restore_ofmap(struct ofw_translations *, int);
136 static void dumpsys(void);
137 
138 void
139 initppc(startkernel, endkernel, args)
140 	u_int startkernel, endkernel;
141 	char *args;
142 {
143 	extern int trapcode, trapsize;
144 	extern int alitrap, alisize;
145 	extern int dsitrap, dsisize;
146 	extern int isitrap, isisize;
147 	extern int decrint, decrsize;
148 	extern int tlbimiss, tlbimsize;
149 	extern int tlbdlmiss, tlbdlmsize;
150 	extern int tlbdsmiss, tlbdsmsize;
151 #if defined(DDB) || defined(KGDB)
152 	extern int ddblow, ddbsize;
153 #endif
154 #ifdef IPKDB
155 	extern int ipkdblow, ipkdbsize;
156 #endif
157 	int exc, scratch;
158 	struct mem_region *allmem, *availmem, *mp;
159 	struct ofw_translations *ofmap;
160 	int ofmaplen;
161 #ifdef MULTIPROCESSOR
162 	struct cpu_info *ci = &cpu_info[0];
163 #else
164 	struct cpu_info *ci = &cpu_info_store;
165 #endif
166 
167 	asm volatile ("mtsprg 0,%0" :: "r"(ci));
168 
169 	/*
170 	 * Initialize BAT registers to unmapped to not generate
171 	 * overlapping mappings below.
172 	 */
173 	asm volatile ("mtibatu 0,%0" :: "r"(0));
174 	asm volatile ("mtibatu 1,%0" :: "r"(0));
175 	asm volatile ("mtibatu 2,%0" :: "r"(0));
176 	asm volatile ("mtibatu 3,%0" :: "r"(0));
177 	asm volatile ("mtdbatu 0,%0" :: "r"(0));
178 	asm volatile ("mtdbatu 1,%0" :: "r"(0));
179 	asm volatile ("mtdbatu 2,%0" :: "r"(0));
180 	asm volatile ("mtdbatu 3,%0" :: "r"(0));
181 
182 	/*
183 	 * Set up BAT0 to only map the lowest 256 MB area
184 	 */
185 	battable[0x0].batl = BATL(0x00000000, BAT_M, BAT_PP_RW);
186 	battable[0x0].batu = BATU(0x00000000, BAT_BL_256M, BAT_Vs);
187 
188 	/*
189 	 * Map PCI memory space.
190 	 */
191 	battable[0x8].batl = BATL(0x80000000, BAT_I|BAT_G, BAT_PP_RW);
192 	battable[0x8].batu = BATU(0x80000000, BAT_BL_256M, BAT_Vs);
193 
194 	battable[0x9].batl = BATL(0x90000000, BAT_I|BAT_G, BAT_PP_RW);
195 	battable[0x9].batu = BATU(0x90000000, BAT_BL_256M, BAT_Vs);
196 
197 	battable[0xa].batl = BATL(0xa0000000, BAT_I|BAT_G, BAT_PP_RW);
198 	battable[0xa].batu = BATU(0xa0000000, BAT_BL_256M, BAT_Vs);
199 
200 	battable[0xb].batl = BATL(0xb0000000, BAT_I|BAT_G, BAT_PP_RW);
201 	battable[0xb].batu = BATU(0xb0000000, BAT_BL_256M, BAT_Vs);
202 
203 	/*
204 	 * Map obio devices.
205 	 */
206 	battable[0xf].batl = BATL(0xf0000000, BAT_I|BAT_G, BAT_PP_RW);
207 	battable[0xf].batu = BATU(0xf0000000, BAT_BL_256M, BAT_Vs);
208 
209 	/*
210 	 * Now setup fixed bat registers
211 	 *
212 	 * Note that we still run in real mode, and the BAT
213 	 * registers were cleared above.
214 	 */
215 	/* BAT0 used for initial 256 MB segment */
216 	asm volatile ("mtibatl 0,%0; mtibatu 0,%1;"
217 		      "mtdbatl 0,%0; mtdbatu 0,%1;"
218 		      :: "r"(battable[0].batl), "r"(battable[0].batu));
219 	/* BAT1 used for primary I/O 256 MB segment */
220 	asm volatile ("mtdbatl 1,%0; mtdbatu 1,%1;"
221 		      :: "r"(battable[8].batl), "r"(battable[8].batu));
222 
223 	/*
224 	 * Set up battable to map all RAM regions.
225 	 * This is here because mem_regions() call needs bat0 set up.
226 	 */
227 	mem_regions(&allmem, &availmem);
228 	for (mp = allmem; mp->size; mp++) {
229 		paddr_t pa = mp->start & 0xf0000000;
230 		paddr_t end = mp->start + mp->size;
231 
232 		do {
233 			u_int n = pa >> 28;
234 
235 			battable[n].batl = BATL(pa, BAT_M, BAT_PP_RW);
236 			battable[n].batu = BATU(pa, BAT_BL_256M, BAT_Vs);
237 			pa += 0x10000000;
238 		} while (pa < end);
239 	}
240 
241 	chosen = OF_finddevice("/chosen");
242 
243 	ofmaplen = save_ofmap(NULL, 0);
244 	ofmap = alloca(ofmaplen);
245 	save_ofmap(ofmap, ofmaplen);
246 
247 	proc0.p_cpu = ci;
248 	proc0.p_addr = proc0paddr;
249 	memset(proc0.p_addr, 0, sizeof *proc0.p_addr);
250 
251 	curpcb = &proc0paddr->u_pcb;
252 
253 	curpm = curpcb->pcb_pmreal = curpcb->pcb_pm = pmap_kernel();
254 
255 #ifdef	__notyet__		/* Needs some rethinking regarding real/virtual OFW */
256 	OF_set_callback(callback);
257 #endif
258 
259 	/*
260 	 * Set up trap vectors
261 	 */
262 	for (exc = EXC_RSVD; exc <= EXC_LAST; exc += 0x100)
263 		switch (exc) {
264 		default:
265 			memcpy((void *)exc, &trapcode, (size_t)&trapsize);
266 			break;
267 		case EXC_EXI:
268 			/*
269 			 * This one is (potentially) installed during autoconf
270 			 */
271 			break;
272 		case EXC_ALI:
273 			memcpy((void *)EXC_ALI, &alitrap, (size_t)&alisize);
274 			break;
275 		case EXC_DSI:
276 			memcpy((void *)EXC_DSI, &dsitrap, (size_t)&dsisize);
277 			break;
278 		case EXC_ISI:
279 			memcpy((void *)EXC_ISI, &isitrap, (size_t)&isisize);
280 			break;
281 		case EXC_DECR:
282 			memcpy((void *)EXC_DECR, &decrint, (size_t)&decrsize);
283 			break;
284 		case EXC_IMISS:
285 			memcpy((void *)EXC_IMISS, &tlbimiss, (size_t)&tlbimsize);
286 			break;
287 		case EXC_DLMISS:
288 			memcpy((void *)EXC_DLMISS, &tlbdlmiss, (size_t)&tlbdlmsize);
289 			break;
290 		case EXC_DSMISS:
291 			memcpy((void *)EXC_DSMISS, &tlbdsmiss, (size_t)&tlbdsmsize);
292 			break;
293 #if defined(DDB) || defined(IPKDB) || defined(KGDB)
294 		case EXC_PGM:
295 		case EXC_TRC:
296 		case EXC_BPT:
297 #if defined(DDB) || defined(KGDB)
298 			memcpy((void *)exc, &ddblow, (size_t)&ddbsize);
299 #if defined(IPKDB)
300 #error "cannot enable IPKDB with DDB or KGDB"
301 #endif
302 #else
303 			memcpy((void *)exc, &ipkdblow, (size_t)&ipkdbsize);
304 #endif
305 			break;
306 #endif /* DDB || IPKDB || KGDB */
307 		}
308 
309 	/*
310 	 * external interrupt handler install
311 	 */
312 	install_extint(ext_intr);
313 
314 	__syncicache((void *)EXC_RST, EXC_LAST - EXC_RST + 0x100);
315 
316 	/*
317 	 * Now enable translation (and machine checks/recoverable interrupts).
318 	 */
319 	asm volatile ("mfmsr %0; ori %0,%0,%1; mtmsr %0; isync"
320 		      : "=r"(scratch) : "K"(PSL_IR|PSL_DR|PSL_ME|PSL_RI));
321 
322 	ofmsr &= ~PSL_IP;
323 
324 	/*
325 	 * Parse arg string.
326 	 */
327 #ifdef DDB
328 	memcpy(&startsym, args + strlen(args) + 1, sizeof(startsym));
329 	memcpy(&endsym, args + strlen(args) + 5, sizeof(endsym));
330 	if (startsym == NULL || endsym == NULL)
331 		startsym = endsym = NULL;
332 #endif
333 
334 	strcpy(bootpath, args);
335 	args = bootpath;
336 	while (*++args && *args != ' ');
337 	if (*args) {
338 		*args++ = 0;
339 		while (*args)
340 			BOOT_FLAG(*args++, boothowto);
341 	}
342 
343 	/*
344 	 * If the bootpath doesn't start with a / then it isn't
345 	 * an OFW path and probably is an alias, so look up the alias
346 	 * and regenerate the full bootpath so device_register will work.
347 	 */
348 	if (bootpath[0] != '/' && bootpath[0] != '\0') {
349 		int aliases = OF_finddevice("/aliases");
350 		char tmpbuf[100];
351 		char aliasbuf[256];
352 		if (aliases != 0) {
353 			char *cp1, *cp2, *cp;
354 			char saved_ch = 0;
355 			int len;
356 			cp1 = strchr(bootpath, ':');
357 			cp2 = strchr(bootpath, ',');
358 			cp = cp1;
359 			if (cp1 == NULL || (cp2 != NULL && cp2 < cp1))
360 				cp = cp2;
361 			tmpbuf[0] = '\0';
362 			if (cp != NULL) {
363 				strcpy(tmpbuf, cp);
364 				saved_ch = *cp;
365 				*cp = '\0';
366 			}
367 			len = OF_getprop(aliases, bootpath, aliasbuf,
368 			    sizeof(aliasbuf));
369 			if (len > 0) {
370 				if (aliasbuf[len-1] == '\0')
371 					len--;
372 				memcpy(bootpath, aliasbuf, len);
373 				strcpy(&bootpath[len], tmpbuf);
374 			} else {
375 				*cp = saved_ch;
376 			}
377 		}
378 	}
379 
380 	/*
381 	 * i386 port says, that this shouldn't be here,
382 	 * but I really think the console should be initialized
383 	 * as early as possible.
384 	 */
385 	consinit();
386 
387 	/*
388 	 * Set the page size.
389 	 */
390 	uvm_setpagesize();
391 
392 	/*
393 	 * Initialize pmap module.
394 	 */
395 	pmap_bootstrap(startkernel, endkernel, NULL);
396 
397 	restore_ofmap(ofmap, ofmaplen);
398 }
399 
400 int
401 save_ofmap(ofmap, maxlen)
402 	struct ofw_translations *ofmap;
403 	int maxlen;
404 {
405 	int mmui, mmu, len;
406 
407 	OF_getprop(chosen, "mmu", &mmui, sizeof mmui);
408 	mmu = OF_instance_to_package(mmui);
409 
410 	if (ofmap) {
411 		memset(ofmap, 0, maxlen);	/* to be safe */
412 		len = OF_getprop(mmu, "translations", ofmap, maxlen);
413 	} else
414 		len = OF_getproplen(mmu, "translations");
415 
416 	return len;
417 }
418 
419 void
420 restore_ofmap(ofmap, len)
421 	struct ofw_translations *ofmap;
422 	int len;
423 {
424 	int n = len / sizeof(struct ofw_translations);
425 	int i;
426 
427 	pmap_pinit(&ofw_pmap);
428 
429 	ofw_pmap.pm_sr[KERNEL_SR] = KERNEL_SEGMENT;
430 
431 	for (i = 0; i < n; i++) {
432 		paddr_t pa = ofmap[i].pa;
433 		vaddr_t va = ofmap[i].va;
434 		int len = ofmap[i].len;
435 
436 		if (va < 0xf0000000)			/* XXX */
437 			continue;
438 
439 		while (len > 0) {
440 			pmap_enter(&ofw_pmap, va, pa, VM_PROT_ALL,
441 			    VM_PROT_ALL|PMAP_WIRED);
442 			pa += NBPG;
443 			va += NBPG;
444 			len -= NBPG;
445 		}
446 	}
447 	pmap_update(&ofw_pmap);
448 }
449 
450 /*
451  * This should probably be in autoconf!				XXX
452  */
453 char machine[] = MACHINE;		/* from <machine/param.h> */
454 char machine_arch[] = MACHINE_ARCH;	/* from <machine/param.h> */
455 
456 void
457 install_extint(handler)
458 	void (*handler) __P((void));
459 {
460 	extern int extint, extsize;
461 	extern u_long extint_call;
462 	u_long offset = (u_long)handler - (u_long)&extint_call;
463 	int omsr, msr;
464 
465 #ifdef	DIAGNOSTIC
466 	if (offset > 0x1ffffff)
467 		panic("install_extint: too far away");
468 #endif
469 	asm volatile ("mfmsr %0; andi. %1,%0,%2; mtmsr %1"
470 		      : "=r"(omsr), "=r"(msr) : "K"((u_short)~PSL_EE));
471 	extint_call = (extint_call & 0xfc000003) | offset;
472 	memcpy((void *)EXC_EXI, &extint, (size_t)&extsize);
473 	__syncicache((void *)&extint_call, sizeof extint_call);
474 	__syncicache((void *)EXC_EXI, (int)&extsize);
475 	asm volatile ("mtmsr %0" :: "r"(omsr));
476 }
477 
478 /*
479  * Machine dependent startup code.
480  */
481 void
482 cpu_startup()
483 {
484 	int sz, i;
485 	caddr_t v;
486 	vaddr_t minaddr, maxaddr;
487 	int base, residual;
488 	char pbuf[9];
489 
490 	initmsgbuf((caddr_t)msgbuf_paddr, round_page(MSGBUFSIZE));
491 
492 	proc0.p_addr = proc0paddr;
493 	v = (caddr_t)proc0paddr + USPACE;
494 
495 	printf("%s", version);
496 	cpu_identify(NULL, 0);
497 
498 	format_bytes(pbuf, sizeof(pbuf), ctob((u_int)physmem));
499 	printf("total memory = %s\n", pbuf);
500 
501 	/*
502 	 * Find out how much space we need, allocate it,
503 	 * and then give everything true virtual addresses.
504 	 */
505 	sz = (int)allocsys(NULL, NULL);
506 	if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(sz))) == 0)
507 		panic("startup: no room for tables");
508 	if (allocsys(v, NULL) - v != sz)
509 		panic("startup: table size inconsistency");
510 
511 	/*
512 	 * Now allocate buffers proper.  They are different than the above
513 	 * in that they usually occupy more virtual memory than physical.
514 	 */
515 	sz = MAXBSIZE * nbuf;
516 	minaddr = 0;
517 	if (uvm_map(kernel_map, (vaddr_t *)&minaddr, round_page(sz),
518 		NULL, UVM_UNKNOWN_OFFSET, 0,
519 		UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE,
520 			    UVM_ADV_NORMAL, 0)) != 0)
521 		panic("startup: cannot allocate VM for buffers");
522 	buffers = (char *)minaddr;
523 	base = bufpages / nbuf;
524 	residual = bufpages % nbuf;
525 	if (base >= MAXBSIZE) {
526 		/* Don't want to alloc more physical mem than ever needed */
527 		base = MAXBSIZE;
528 		residual = 0;
529 	}
530 	for (i = 0; i < nbuf; i++) {
531 		vsize_t curbufsize;
532 		vaddr_t curbuf;
533 		struct vm_page *pg;
534 
535 		curbuf = (vaddr_t)buffers + i * MAXBSIZE;
536 		curbufsize = NBPG * (i < residual ? base + 1 : base);
537 
538 		while (curbufsize) {
539 			pg = uvm_pagealloc(NULL, 0, NULL, 0);
540 			if (pg == NULL)
541 				panic("cpu_startup: not enough memory for "
542 				    "buffer cache");
543 			pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg),
544 			    VM_PROT_READ|VM_PROT_WRITE);
545 			curbuf += PAGE_SIZE;
546 			curbufsize -= PAGE_SIZE;
547 		}
548 	}
549 	pmap_update(pmap_kernel());
550 
551 	/*
552 	 * Allocate a submap for exec arguments.  This map effectively
553 	 * limits the number of processes exec'ing at any time.
554 	 */
555 	exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
556 				 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
557 
558 	/*
559 	 * Allocate a submap for physio
560 	 */
561 	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
562 				 VM_PHYS_SIZE, 0, FALSE, NULL);
563 
564 #ifndef PMAP_MAP_POOLPAGE
565 	/*
566 	 * No need to allocate an mbuf cluster submap.  Mbuf clusters
567 	 * are allocated via the pool allocator, and we use direct-mapped
568 	 * pool pages.
569 	 */
570 	mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
571 	    mclbytes*nmbclusters, VM_MAP_INTRSAFE, FALSE, NULL);
572 #endif
573 
574 	format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
575 	printf("avail memory = %s\n", pbuf);
576 	format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG);
577 	printf("using %d buffers containing %s of memory\n", nbuf, pbuf);
578 
579 	/*
580 	 * Set up the buffers.
581 	 */
582 	bufinit();
583 }
584 
585 /*
586  * consinit
587  * Initialize system console.
588  */
589 void
590 consinit()
591 {
592 	static int initted;
593 
594 	if (initted)
595 		return;
596 	initted = 1;
597 	cninit();
598 
599 #ifdef DDB
600 	ddb_init((int)((u_int)endsym - (u_int)startsym), startsym, endsym);
601 	if (boothowto & RB_KDB)
602 		Debugger();
603 #endif
604 
605 #ifdef IPKDB
606 	ipkdb_init();
607 	if (boothowto & RB_KDB)
608 		ipkdb_connect(0);
609 #endif
610 
611 #ifdef KGDB
612 #if NZSC > 0
613 	zs_kgdb_init();
614 #endif
615 	if (boothowto & RB_KDB)
616 		kgdb_connect(1);
617 #endif
618 }
619 
620 /*
621  * Crash dump handling.
622  */
623 
624 void
625 dumpsys()
626 {
627 	printf("dumpsys: TBD\n");
628 }
629 
630 /*
631  * Soft networking interrupts.
632  */
633 void
634 softnet()
635 {
636 	extern volatile int netisr;
637 	int isr;
638 
639 	isr = netisr;
640 	netisr = 0;
641 
642 #define DONETISR(bit, fn) do {		\
643 	if (isr & (1 << bit))		\
644 		fn();			\
645 } while (0)
646 
647 #include <net/netisr_dispatch.h>
648 
649 #undef DONETISR
650 
651 }
652 
653 #include "zsc.h"
654 #include "com.h"
655 /*
656  * Soft tty interrupts.
657  */
658 void
659 softserial()
660 {
661 #if NZSC > 0
662 	zssoft(NULL);
663 #endif
664 #if NCOM > 0
665 	comsoft();
666 #endif
667 }
668 
669 #if 0
670 /*
671  * Stray interrupts.
672  */
673 void
674 strayintr(irq)
675 	int irq;
676 {
677 	log(LOG_ERR, "stray interrupt %d\n", irq);
678 }
679 #endif
680 
681 /*
682  * Halt or reboot the machine after syncing/dumping according to howto.
683  */
684 void
685 cpu_reboot(howto, what)
686 	int howto;
687 	char *what;
688 {
689 	static int syncing;
690 	static char str[256];
691 	char *ap = str, *ap1 = ap;
692 
693 	boothowto = howto;
694 	if (!cold && !(howto & RB_NOSYNC) && !syncing) {
695 		syncing = 1;
696 		vfs_shutdown();		/* sync */
697 		resettodr();		/* set wall clock */
698 	}
699 
700 #ifdef MULTIPROCESSOR
701 	/* Halt other CPU.  XXX for now... */
702 	macppc_send_ipi(&cpu_info[1 - cpu_number()], MACPPC_IPI_HALT);
703 	delay(100000);	/* XXX */
704 #endif
705 
706 	splhigh();
707 
708 	if (!cold && (howto & RB_DUMP))
709 		dumpsys();
710 
711 	doshutdownhooks();
712 
713 	if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
714 #if NADB > 0
715 		delay(1000000);
716 		adb_poweroff();
717 		printf("WARNING: powerdown failed!\n");
718 #endif
719 	}
720 
721 	if (howto & RB_HALT) {
722 		printf("halted\n\n");
723 
724 		/* flush cache for msgbuf */
725 		__syncicache((void *)msgbuf_paddr, round_page(MSGBUFSIZE));
726 
727 		ppc_exit();
728 	}
729 
730 	printf("rebooting\n\n");
731 	if (what && *what) {
732 		if (strlen(what) > sizeof str - 5)
733 			printf("boot string too large, ignored\n");
734 		else {
735 			strcpy(str, what);
736 			ap1 = ap = str + strlen(str);
737 			*ap++ = ' ';
738 		}
739 	}
740 	*ap++ = '-';
741 	if (howto & RB_SINGLE)
742 		*ap++ = 's';
743 	if (howto & RB_KDB)
744 		*ap++ = 'd';
745 	*ap++ = 0;
746 	if (ap[-2] == '-')
747 		*ap1 = 0;
748 
749 	/* flush cache for msgbuf */
750 	__syncicache((void *)msgbuf_paddr, round_page(MSGBUFSIZE));
751 
752 #if NADB > 0
753 	adb_restart();	/* not return */
754 #endif
755 	ppc_exit();
756 }
757 
758 #if 0
759 /*
760  * OpenFirmware callback routine
761  */
762 void
763 callback(p)
764 	void *p;
765 {
766 	panic("callback");	/* for now			XXX */
767 }
768 #endif
769 
770 int
771 lcsplx(ipl)
772 	int ipl;
773 {
774 	return spllower(ipl); 	/* XXX */
775 }
776 
777 /*
778  * Convert kernel VA to physical address
779  */
780 int
781 kvtop(addr)
782 	caddr_t addr;
783 {
784 	vaddr_t va;
785 	paddr_t pa;
786 	int off;
787 	extern char end[];
788 
789 	if (addr < end)
790 		return (int)addr;
791 
792 	va = trunc_page((vaddr_t)addr);
793 	off = (int)addr - va;
794 
795 	if (pmap_extract(pmap_kernel(), va, &pa) == FALSE) {
796 		/*printf("kvtop: zero page frame (va=0x%x)\n", addr);*/
797 		return (int)addr;
798 	}
799 
800 	return((int)pa + off);
801 }
802 
803 /*
804  * Allocate vm space and mapin the I/O address
805  */
806 void *
807 mapiodev(pa, len)
808 	paddr_t pa;
809 	psize_t len;
810 {
811 	paddr_t faddr;
812 	vaddr_t taddr, va;
813 	int off;
814 
815 	faddr = trunc_page(pa);
816 	off = pa - faddr;
817 	len = round_page(off + len);
818 	va = taddr = uvm_km_valloc(kernel_map, len);
819 
820 	if (va == 0)
821 		return NULL;
822 
823 	for (; len > 0; len -= NBPG) {
824 		pmap_kenter_pa(taddr, faddr, VM_PROT_READ | VM_PROT_WRITE);
825 		faddr += NBPG;
826 		taddr += NBPG;
827 	}
828 	pmap_update(pmap_kernel());
829 	return (void *)(va + off);
830 }
831 
832 #include "akbd.h"
833 #include "ukbd.h"
834 #include "ofb.h"
835 #include "ite.h"
836 #include "zstty.h"
837 
838 void
839 cninit()
840 {
841 	struct consdev *cp;
842 	int stdout, node;
843 	char type[16];
844 
845 	if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout))
846 	    != sizeof(stdout))
847 		goto nocons;
848 
849 	node = OF_instance_to_package(stdout);
850 	memset(type, 0, sizeof(type));
851 	if (OF_getprop(node, "device_type", type, sizeof(type)) == -1)
852 		goto nocons;
853 
854 #if NOFB > 0
855 	if (strcmp(type, "display") == 0) {
856 		cninit_kd();
857 		return;
858 	}
859 #endif /* NOFB > 0 */
860 
861 #if NITE > 0
862 	if (strcmp(type, "display") == 0) {
863 		extern struct consdev consdev_ite;
864 
865 		cp = &consdev_ite;
866 		(*cp->cn_probe)(cp);
867 		(*cp->cn_init)(cp);
868 		cn_tab = cp;
869 
870 		return;
871 	}
872 #endif
873 
874 #if NZSTTY > 0
875 	if (strcmp(type, "serial") == 0) {
876 		extern struct consdev consdev_zs;
877 
878 		cp = &consdev_zs;
879 		(*cp->cn_probe)(cp);
880 		(*cp->cn_init)(cp);
881 		cn_tab = cp;
882 
883 		return;
884 	}
885 #endif
886 
887 nocons:
888 	return;
889 }
890 
891 #if NOFB > 0
892 struct usb_kbd_ihandles {
893 	struct usb_kbd_ihandles *next;
894 	int ihandle;
895 };
896 
897 void
898 cninit_kd()
899 {
900 	int stdin, node;
901 	char name[16];
902 #if NAKBD > 0
903 	int akbd;
904 #endif
905 #if NUKBD > 0
906 	struct usb_kbd_ihandles *ukbds;
907 	int ukbd;
908 #endif
909 
910 	/*
911 	 * Attach the console output now (so we can see debugging messages,
912 	 * if any).
913 	 */
914 	ofb_cnattach();
915 
916 	/*
917 	 * We must determine which keyboard type we have.
918 	 */
919 	if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin))
920 	    != sizeof(stdin)) {
921 		printf("WARNING: no `stdin' property in /chosen\n");
922 		return;
923 	}
924 
925 	node = OF_instance_to_package(stdin);
926 	memset(name, 0, sizeof(name));
927 	OF_getprop(node, "name", name, sizeof(name));
928 	if (strcmp(name, "keyboard") != 0) {
929 		printf("WARNING: stdin is not a keyboard: %s\n", name);
930 		return;
931 	}
932 
933 #if NAKBD > 0
934 	memset(name, 0, sizeof(name));
935 	OF_getprop(OF_parent(node), "name", name, sizeof(name));
936 	if (strcmp(name, "adb") == 0) {
937 		printf("console keyboard type: ADB\n");
938 		akbd_cnattach();
939 		goto kbd_found;
940 	}
941 #endif
942 
943 	/*
944 	 * We're not an ADB keyboard; must be USB.  Unfortunately,
945 	 * we have a few problems:
946 	 *
947 	 *	(1) The stupid Macintosh firmware uses a
948 	 *	    `psuedo-hid' (yes, they even spell it
949 	 *	    incorrectly!) which apparently merges
950 	 *	    all USB keyboard input into a single
951 	 *	    input stream.  Because of this, we can't
952 	 *	    actually determine which USB controller
953 	 *	    or keyboard is really the console keyboard!
954 	 *
955 	 *	(2) Even if we could, USB requires a lot of
956 	 *	    the kernel to be running in order for it
957 	 *	    to work.
958 	 *
959 	 * So, what we do is this:
960 	 *
961 	 *	(1) Tell the ukbd driver that it is the console.
962 	 *	    At autoconfiguration time, it will attach the
963 	 *	    first USB keyboard instance as the console
964 	 *	    keyboard.
965 	 *
966 	 *	(2) Until then, so that we have _something_, we
967 	 *	    use the OpenFirmware I/O facilities to read
968 	 *	    the keyboard.
969 	 */
970 
971 	/*
972 	 * stdin is /psuedo-hid/keyboard.  Test `adb-kbd-ihandle and
973 	 * `usb-kbd-ihandles to figure out the real keyboard(s).
974 	 *
975 	 * XXX This must be called before pmap_bootstrap().
976 	 */
977 
978 #if NUKBD > 0
979 	if (OF_call_method("`usb-kbd-ihandles", stdin, 0, 1, &ukbds) != -1 &&
980 	    ukbds != NULL && ukbds->ihandle != 0 &&
981 	    OF_instance_to_package(ukbds->ihandle) != -1) {
982 		printf("console keyboard type: USB\n");
983 		ukbd_cnattach();
984 		goto kbd_found;
985 	}
986 	/* Try old method name. */
987 	if (OF_call_method("`usb-kbd-ihandle", stdin, 0, 1, &ukbd) != -1 &&
988 	    ukbd != 0 &&
989 	    OF_instance_to_package(ukbd) != -1) {
990 		printf("console keyboard type: USB\n");
991 		stdin = ukbd;
992 		ukbd_cnattach();
993 		goto kbd_found;
994 	}
995 #endif
996 
997 #if NAKBD > 0
998 	if (OF_call_method("`adb-kbd-ihandle", stdin, 0, 1, &akbd) != -1 &&
999 	    akbd != 0 &&
1000 	    OF_instance_to_package(akbd) != -1) {
1001 		printf("console keyboard type: ADB\n");
1002 		stdin = akbd;
1003 		akbd_cnattach();
1004 		goto kbd_found;
1005 	}
1006 #endif
1007 
1008 #if NUKBD > 0
1009 	/*
1010 	 * XXX Old firmware does not have `usb-kbd-ihandles method.  Assume
1011 	 * XXX USB keyboard anyway.
1012 	 */
1013 	printf("console keyboard type: USB\n");
1014 	ukbd_cnattach();
1015 	goto kbd_found;
1016 #endif
1017 
1018 	/*
1019 	 * No keyboard is found.  Just return.
1020 	 */
1021 	printf("no console keyboard\n");
1022 	return;
1023 
1024 #if NAKBD + NUKBD > 0
1025 kbd_found:
1026 	/*
1027 	 * XXX This is a little gross, but we don't get to call
1028 	 * XXX wskbd_cnattach() twice.
1029 	 */
1030 	ofkbd_ihandle = stdin;
1031 	wsdisplay_set_cons_kbd(ofkbd_cngetc, NULL, NULL);
1032 #endif
1033 }
1034 #endif
1035 
1036 /*
1037  * Bootstrap console keyboard routines, using OpenFirmware I/O.
1038  */
1039 int
1040 ofkbd_cngetc(dev)
1041 	dev_t dev;
1042 {
1043 	u_char c = '\0';
1044 	int len;
1045 
1046 	do {
1047 		len = OF_read(ofkbd_ihandle, &c, 1);
1048 	} while (len != 1);
1049 
1050 	return c;
1051 }
1052 
1053 #ifdef MULTIPROCESSOR
1054 void
1055 save_fpu_proc(p)
1056 	struct proc *p;
1057 {
1058 	volatile struct cpu_info *fpcpu;
1059 	int i;
1060 	extern volatile int IPI[];	/* XXX */
1061 
1062 	fpcpu = p->p_addr->u_pcb.pcb_fpcpu;
1063 	if (fpcpu == curcpu()) {
1064 		save_fpu(p);
1065 		return;
1066 	}
1067 
1068 #if 0
1069 	printf("save_fpu_proc{%d} pid = %d, fpcpu->ci_cpuid = %d\n",
1070 	    cpu_number(), p->p_pid, fpcpu->ci_cpuid);
1071 #endif
1072 
1073 	macppc_send_ipi(fpcpu, MACPPC_IPI_FLUSH_FPU);
1074 
1075 	/* Wait for flush. */
1076 #if 0
1077 	while (fpcpu->ci_fpuproc);
1078 #else
1079 	for (i = 0; i < 0x3fffffff; i++) {
1080 		if (fpcpu->ci_fpuproc == NULL)
1081 			goto done;
1082 	}
1083 	printf("save_fpu_proc{%d} pid = %d, fpcpu->ci_cpuid = %d\n",
1084 	    cpu_number(), p->p_pid, fpcpu->ci_cpuid);
1085 	printf("IPI[0] = 0x%x, IPI[1] = 0x%x\n", IPI[0], IPI[1]);
1086 	printf("cpl 0x%x 0x%x\n", cpu_info[0].ci_cpl, cpu_info[1].ci_cpl);
1087 	printf("ipending 0x%x 0x%x\n", cpu_info[0].ci_ipending, cpu_info[1].ci_ipending);
1088 	panic("save_fpu_proc");
1089 done:;
1090 
1091 #endif
1092 }
1093 #endif /* MULTIPROCESSOR */
1094