xref: /netbsd/sys/arch/bebox/bebox/machdep.c (revision bf9ec67e)
1 /*	$NetBSD: machdep.c,v 1.72 2002/05/13 06:26:45 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_ipkdb.h"
37 
38 #include <sys/param.h>
39 #include <sys/buf.h>
40 #include <sys/conf.h>
41 #include <sys/device.h>
42 #include <sys/exec.h>
43 #include <sys/kernel.h>
44 #include <sys/malloc.h>
45 #include <sys/map.h>
46 #include <sys/mbuf.h>
47 #include <sys/mount.h>
48 #include <sys/msgbuf.h>
49 #include <sys/proc.h>
50 #include <sys/reboot.h>
51 #include <sys/syscallargs.h>
52 #include <sys/syslog.h>
53 #include <sys/systm.h>
54 #include <sys/user.h>
55 
56 #ifdef DDB
57 #include <machine/db_machdep.h>
58 #include <ddb/db_extern.h>
59 #endif
60 
61 #include <uvm/uvm_extern.h>
62 
63 #include <net/netisr.h>
64 
65 #include <powerpc/mpc6xx/bat.h>
66 #include <machine/bootinfo.h>
67 #include <machine/autoconf.h>
68 #define _POWERPC_BUS_DMA_PRIVATE
69 #include <machine/bus.h>
70 #include <machine/intr.h>
71 #include <machine/pmap.h>
72 #include <machine/powerpc.h>
73 #include <machine/trap.h>
74 
75 #include <dev/cons.h>
76 
77 #include "pfb.h"
78 
79 #include "pc.h"
80 #if (NPC > 0)
81 #include <machine/pccons.h>
82 #endif
83 
84 #include "vga.h"
85 #if (NVGA > 0)
86 #include <dev/ic/mc6845reg.h>
87 #include <dev/ic/pcdisplayvar.h>
88 #include <dev/ic/vgareg.h>
89 #include <dev/ic/vgavar.h>
90 #endif
91 
92 #include "pckbc.h"
93 #if (NPCKBC > 0)
94 #include <dev/isa/isareg.h>
95 #include <dev/ic/i8042reg.h>
96 #include <dev/ic/pckbcvar.h>
97 #endif
98 
99 #include "com.h"
100 #if (NCOM > 0)
101 #include <sys/termios.h>
102 #include <dev/ic/comreg.h>
103 #include <dev/ic/comvar.h>
104 #endif
105 
106 /*
107  * Global variables used here and there
108  */
109 struct vm_map *exec_map = NULL;
110 struct vm_map *mb_map = NULL;
111 struct vm_map *phys_map = NULL;
112 
113 char bootinfo[BOOTINFO_MAXSIZE];
114 
115 char machine[] = MACHINE;		/* machine */
116 char machine_arch[] = MACHINE_ARCH;	/* machine architecture */
117 
118 struct pcb *curpcb;
119 struct pmap *curpm;
120 struct proc *fpuproc;
121 
122 extern struct user *proc0paddr;
123 
124 struct bat battable[16];
125 
126 paddr_t bebox_mb_reg;		/* BeBox MotherBoard register */
127 
128 #define	OFMEMREGIONS	32
129 struct mem_region physmemr[OFMEMREGIONS], availmemr[OFMEMREGIONS];
130 
131 char *bootpath;
132 
133 paddr_t msgbuf_paddr;
134 vaddr_t msgbuf_vaddr;
135 
136 paddr_t avail_end;			/* XXX temporary */
137 
138 void install_extint __P((void (*)(void)));
139 
140 void
141 initppc(startkernel, endkernel, args, btinfo)
142 	u_int startkernel, endkernel, args;
143 	void *btinfo;
144 {
145 	extern int trapcode, trapsize;
146 	extern int alitrap, alisize;
147 	extern int dsitrap, dsisize;
148 	extern int isitrap, isisize;
149 	extern int decrint, decrsize;
150 	extern int tlbimiss, tlbimsize;
151 	extern int tlbdlmiss, tlbdlmsize;
152 	extern int tlbdsmiss, tlbdsmsize;
153 #ifdef DDB
154 	extern int ddblow, ddbsize;
155 	extern void *startsym, *endsym;
156 #endif
157 #ifdef IPKDB
158 	extern int ipkdblow, ipkdbsize;
159 #endif
160 	extern void consinit __P((void));
161 	extern void ext_intr __P((void));
162 	int exc, scratch;
163 
164 	/*
165 	 * copy bootinfo
166 	 */
167 	memcpy(bootinfo, btinfo, sizeof (bootinfo));
168 
169 	/*
170 	 * BeBox memory region set
171 	 */
172 	{
173 		struct btinfo_memory *meminfo;
174 
175 		meminfo =
176 			(struct btinfo_memory *)lookup_bootinfo(BTINFO_MEMORY);
177 		if (!meminfo)
178 			panic("not found memory information in bootinfo");
179 		physmemr[0].start = 0;
180 		physmemr[0].size = meminfo->memsize & ~PGOFSET;
181 		availmemr[0].start = (endkernel + PGOFSET) & ~PGOFSET;
182 		availmemr[0].size = meminfo->memsize - availmemr[0].start;
183 	}
184 	avail_end = physmemr[0].start + physmemr[0].size;    /* XXX temporary */
185 
186 	/*
187 	 * Get CPU clock
188 	 */
189 	{
190 		struct btinfo_clock *clockinfo;
191 		extern u_long ticks_per_sec, ns_per_tick;
192 
193 		clockinfo =
194 			(struct btinfo_clock *)lookup_bootinfo(BTINFO_CLOCK);
195 		if (!clockinfo)
196 			panic("not found clock information in bootinfo");
197 		ticks_per_sec = clockinfo->ticks_per_sec;
198 		ns_per_tick = 1000000000 / ticks_per_sec;
199 	}
200 
201 	/*
202 	 * BeBox MotherBoard's Register
203 	 *  Interrupt Mask Reset
204 	 */
205 	*(volatile u_int *)(MOTHER_BOARD_REG + CPU0_INT_MASK) = 0x0ffffffc;
206 	*(volatile u_int *)(MOTHER_BOARD_REG + CPU0_INT_MASK) = 0x80000023;
207 	*(volatile u_int *)(MOTHER_BOARD_REG + CPU1_INT_MASK) = 0x0ffffffc;
208 
209 	proc0.p_addr = proc0paddr;
210 	memset(proc0.p_addr, 0, sizeof *proc0.p_addr);
211 
212 	curpcb = &proc0paddr->u_pcb;
213 
214 	curpm = curpcb->pcb_pmreal = curpcb->pcb_pm = pmap_kernel();
215 
216 	/*
217 	 * boothowto
218 	 */
219 	boothowto = args;
220 
221 	/*
222 	 * Init the I/O stuff before the console
223 	 */
224 	bebox_bus_space_init();
225 
226 	/*
227 	 * i386 port says, that this shouldn't be here,
228 	 * but I really think the console should be initialized
229 	 * as early as possible.
230 	 */
231 	consinit();
232 
233 	/*
234 	 * Initialize BAT registers to unmapped to not generate
235 	 * overlapping mappings below.
236 	 */
237 	asm volatile ("mtibatu 0,%0" :: "r"(0));
238 	asm volatile ("mtibatu 1,%0" :: "r"(0));
239 	asm volatile ("mtibatu 2,%0" :: "r"(0));
240 	asm volatile ("mtibatu 3,%0" :: "r"(0));
241 	asm volatile ("mtdbatu 0,%0" :: "r"(0));
242 	asm volatile ("mtdbatu 1,%0" :: "r"(0));
243 	asm volatile ("mtdbatu 2,%0" :: "r"(0));
244 	asm volatile ("mtdbatu 3,%0" :: "r"(0));
245 
246 	/*
247 	 * Set up initial BAT table
248 	 */
249 	/* map the lowest 256M area */
250 	battable[0x0].batl = BATL(0x00000000, BAT_M, BAT_PP_RW);
251 	battable[0x0].batu = BATU(0x00000000, BAT_BL_256M, BAT_Vs);
252 
253 	/* map the PCI/ISA I/O 256M area */
254 	battable[0x8].batl = BATL(BEBOX_BUS_SPACE_IO, BAT_I, BAT_PP_RW);
255 	battable[0x8].batu = BATU(BEBOX_BUS_SPACE_IO, BAT_BL_256M, BAT_Vs);
256 
257 	/* map the PCI/ISA MEMORY 256M area */
258 	battable[0xc].batl = BATL(BEBOX_BUS_SPACE_MEM, BAT_I, BAT_PP_RW);
259 	battable[0xc].batu = BATU(BEBOX_BUS_SPACE_MEM, BAT_BL_256M, BAT_Vs);
260 
261 	/*
262 	 * Now setup fixed bat registers
263 	 */
264 	asm volatile ("mtibatl 0,%0; mtibatu 0,%1"
265 		      :: "r"(battable[0x0].batl), "r"(battable[0x0].batu));
266 	asm volatile ("mtibatl 1,%0; mtibatu 1,%1"
267 		      :: "r"(battable[0x8].batl), "r"(battable[0x8].batu));
268 	asm volatile ("mtibatl 2,%0; mtibatu 2,%1"
269 		      :: "r"(battable[0xc].batl), "r"(battable[0xc].batu));
270 
271 	asm volatile ("mtdbatl 0,%0; mtdbatu 0,%1"
272 		      :: "r"(battable[0x0].batl), "r"(battable[0x0].batu));
273 	asm volatile ("mtdbatl 1,%0; mtdbatu 1,%1"
274 		      :: "r"(battable[0x8].batl), "r"(battable[0x8].batu));
275 	asm volatile ("mtdbatl 2,%0; mtdbatu 2,%1"
276 		      :: "r"(battable[0xc].batl), "r"(battable[0xc].batu));
277 
278 	/*
279 	 * Set up trap vectors
280 	 */
281 	for (exc = EXC_RSVD; exc <= EXC_LAST; exc += 0x100)
282 		switch (exc) {
283 		default:
284 			memcpy((void *)exc, &trapcode, (size_t)&trapsize);
285 			break;
286 		case EXC_EXI:
287 			/*
288 			 * This one is (potentially) installed during autoconf
289 			 */
290 			break;
291 		case EXC_ALI:
292 			memcpy((void *)EXC_ALI, &alitrap, (size_t)&alisize);
293 			break;
294 		case EXC_DSI:
295 			memcpy((void *)EXC_DSI, &dsitrap, (size_t)&dsisize);
296 			break;
297 		case EXC_ISI:
298 			memcpy((void *)EXC_ISI, &isitrap, (size_t)&isisize);
299 			break;
300 		case EXC_DECR:
301 			memcpy((void *)EXC_DECR, &decrint, (size_t)&decrsize);
302 			break;
303 		case EXC_IMISS:
304 			memcpy((void *)EXC_IMISS, &tlbimiss,
305 			    (size_t)&tlbimsize);
306 			break;
307 		case EXC_DLMISS:
308 			memcpy((void *)EXC_DLMISS, &tlbdlmiss,
309 			    (size_t)&tlbdlmsize);
310 			break;
311 		case EXC_DSMISS:
312 			memcpy((void *)EXC_DSMISS, &tlbdsmiss,
313 			    (size_t)&tlbdsmsize);
314 			break;
315 #if defined(DDB) || defined(IPKDB)
316 		case EXC_PGM:
317 		case EXC_TRC:
318 		case EXC_BPT:
319 #if defined(DDB)
320 			memcpy((void *)exc, &ddblow, (size_t)&ddbsize);
321 #else
322 			memcpy((void *)exc, &ipkdblow, (size_t)&ipkdbsize);
323 #endif
324 			break;
325 #endif /* DDB || IPKDB */
326 		}
327 
328 	__syncicache((void *)EXC_RST, EXC_LAST - EXC_RST + 0x100);
329 
330 	/*
331 	 * external interrupt handler install
332 	 */
333 	install_extint(ext_intr);
334 
335 	/*
336 	 * Now enable translation (and machine checks/recoverable interrupts).
337 	 */
338 	asm volatile ("mfmsr %0; ori %0,%0,%1; mtmsr %0; isync"
339 		      : "=r"(scratch) : "K"(PSL_IR|PSL_DR|PSL_ME|PSL_RI));
340 
341         /*
342 	 * Set the page size.
343 	 */
344 	uvm_setpagesize();
345 
346 	/*
347 	 * Initialize pmap module.
348 	 */
349 	pmap_bootstrap(startkernel, endkernel, NULL);
350 
351 #ifdef DDB
352 	ddb_init((int)((u_int)endsym - (u_int)startsym), startsym, endsym);
353 #endif
354 #ifdef IPKDB
355 	/*
356 	 * Now trap to IPKDB
357 	 */
358 	ipkdb_init();
359 	if (boothowto & RB_KDB)
360 		ipkdb_connect(0);
361 #endif
362 }
363 
364 void
365 mem_regions(mem, avail)
366 	struct mem_region **mem, **avail;
367 {
368 	*mem = physmemr;
369 	*avail = availmemr;
370 }
371 
372 /*
373  * This should probably be in autoconf!				XXX
374  */
375 
376 void
377 install_extint(handler)
378 	void (*handler) __P((void));
379 {
380 	extern int extint, extsize;
381 	extern u_long extint_call;
382 	u_long offset = (u_long)handler - (u_long)&extint_call;
383 	int omsr, msr;
384 
385 #ifdef	DIAGNOSTIC
386 	if (offset > 0x1ffffff)
387 		panic("install_extint: too far away");
388 #endif
389 	asm volatile ("mfmsr %0; andi. %1,%0,%2; mtmsr %1"
390 		      : "=r"(omsr), "=r"(msr) : "K"((u_short)~PSL_EE));
391 	extint_call = (extint_call & 0xfc000003) | offset;
392 	memcpy((void *)EXC_EXI, &extint, (size_t)&extsize);
393 	__syncicache((void *)&extint_call, sizeof extint_call);
394 	__syncicache((void *)EXC_EXI, (int)&extsize);
395 	asm volatile ("mtmsr %0" :: "r"(omsr));
396 }
397 
398 /*
399  * Machine dependent startup code.
400  */
401 void
402 cpu_startup()
403 {
404 	int sz, i;
405 	caddr_t v;
406 	vaddr_t minaddr, maxaddr;
407 	int base, residual;
408 	char pbuf[9];
409 
410 	proc0.p_addr = proc0paddr;
411 	v = (caddr_t)proc0paddr + USPACE;
412 
413 	/*
414 	 * BeBox Mother Board's Register Mapping
415 	 */
416 	if (!(bebox_mb_reg = uvm_km_valloc(kernel_map, round_page(NBPG))))
417 		panic("initppc: no room for interrupt register");
418 	pmap_enter(pmap_kernel(), bebox_mb_reg, MOTHER_BOARD_REG,
419 	    VM_PROT_READ|VM_PROT_WRITE, VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED);
420 	pmap_update(pmap_kernel());
421 
422 	/*
423 	 * Initialize error message buffer (at end of core).
424 	 */
425 	if (!(msgbuf_vaddr = uvm_km_alloc(kernel_map, round_page(MSGBUFSIZE))))
426 		panic("startup: no room for message buffer");
427 	for (i = 0; i < btoc(MSGBUFSIZE); i++)
428 		pmap_enter(pmap_kernel(), msgbuf_vaddr + i * NBPG,
429 		    msgbuf_paddr + i * NBPG, VM_PROT_READ|VM_PROT_WRITE,
430 		    VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED);
431 	pmap_update(pmap_kernel());
432 	initmsgbuf((caddr_t)msgbuf_vaddr, round_page(MSGBUFSIZE));
433 
434 	printf("%s", version);
435 	cpu_identify(NULL, 0);
436 
437 	format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
438 	printf("total memory = %s\n", pbuf);
439 
440 	/*
441 	 * Find out how much space we need, allocate it,
442 	 * and then give everything true virtual addresses.
443 	 */
444 	sz = (int)allocsys(NULL, NULL);
445 	if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(sz))) == 0)
446 		panic("startup: no room for tables");
447 	if (allocsys(v, NULL) - v != sz)
448 		panic("startup: table size inconsistency");
449 
450 	/*
451 	 * Now allocate buffers proper.  They are different than the above
452 	 * in that they usually occupy more virtual memory than physical.
453 	 */
454 	sz = MAXBSIZE * nbuf;
455 	if (uvm_map(kernel_map, (vaddr_t *)&buffers, round_page(sz),
456 		    NULL, UVM_UNKNOWN_OFFSET, 0,
457 		    UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE,
458 				UVM_ADV_NORMAL, 0)) != 0)
459 		panic("startup: cannot allocate VM for buffers");
460 	minaddr = (vaddr_t)buffers;
461 	base = bufpages / nbuf;
462 	residual = bufpages % nbuf;
463 	if (base >= MAXBSIZE) {
464 		/* Don't want to alloc more physical mem than ever needed */
465 		base = MAXBSIZE;
466 		residual = 0;
467 	}
468 	for (i = 0; i < nbuf; i++) {
469 		vsize_t curbufsize;
470 		vaddr_t curbuf;
471 		struct vm_page *pg;
472 
473 		/*
474 		 * Each buffer has MAXBSIZE bytes of VM space allocated.  Of
475 		 * that MAXBSIZE space, we allocate and map (base+1) pages
476 		 * for the first "residual" buffers, and then we allocate
477 		 * "base" pages for the rest.
478 		 */
479 		curbuf = (vaddr_t) buffers + (i * MAXBSIZE);
480 		curbufsize = NBPG * ((i < residual) ? (base+1) : base);
481 
482 		while (curbufsize) {
483 			pg = uvm_pagealloc(NULL, 0, NULL, 0);
484 			if (pg == NULL)
485 				panic("startup: not enough memory for "
486 					"buffer cache");
487 			pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg),
488 			    VM_PROT_READ | VM_PROT_WRITE);
489 			curbuf += PAGE_SIZE;
490 			curbufsize -= PAGE_SIZE;
491 		}
492 	}
493 	pmap_update(kernel_map->pmap);
494 
495 	/*
496 	 * Allocate a submap for exec arguments.  This map effectively
497 	 * limits the number of processes exec'ing at any time.
498 	 */
499 	exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
500 				 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
501 
502 	/*
503 	 * Allocate a submap for physio
504 	 */
505 	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
506 				 VM_PHYS_SIZE, 0, FALSE, NULL);
507 
508 #ifndef PMAP_MAP_POOLPAGE
509 	/*
510 	 * No need to allocate an mbuf cluster submap.  Mbuf clusters
511 	 * are allocated via the pool allocator, and we use direct-mapped
512 	 * pool pages.
513 	 */
514 	mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
515 	    mclbytes*nmbclusters, VM_MAP_INTRSAFE, FALSE, NULL);
516 #endif
517 
518 	/*
519 	 * Now that we have VM, malloc's are OK in bus_space.
520 	 */
521 	bebox_bus_space_mallocok();
522 
523 	format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
524 	printf("avail memory = %s\n", pbuf);
525 	format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG);
526 	printf("using %d buffers containing %s of memory\n", nbuf, pbuf);
527 
528 	/*
529 	 * Set up the buffers.
530 	 */
531 	bufinit();
532 
533 	/*
534 	 * Now allow hardware interrupts.
535 	 */
536 	{
537 		int msr;
538 
539 		splhigh();
540 		asm volatile ("mfmsr %0; ori %0,%0,%1; mtmsr %0"
541 			      : "=r"(msr) : "K"(PSL_EE));
542 	}
543 }
544 
545 /*
546  * lookup_bootinfo:
547  * Look up information in bootinfo of boot loader.
548  */
549 void *
550 lookup_bootinfo(type)
551 	int type;
552 {
553 	struct btinfo_common *bt;
554 	struct btinfo_common *help = (struct btinfo_common *)bootinfo;
555 
556 	do {
557 		bt = help;
558 		if (bt->type == type)
559 			return (help);
560 		help = (struct btinfo_common *)((char*)help + bt->next);
561 	} while (bt->next &&
562 		(size_t)help < (size_t)bootinfo + sizeof (bootinfo));
563 
564 	return (NULL);
565 }
566 
567 /*
568  * consinit
569  * Initialize system console.
570  */
571 void
572 consinit()
573 {
574 	struct btinfo_console *consinfo;
575 	static int initted;
576 
577 	if (initted)
578 		return;
579 	initted = 1;
580 
581 	consinfo = (struct btinfo_console *)lookup_bootinfo(BTINFO_CONSOLE);
582 	if (!consinfo)
583 		panic("not found console information in bootinfo");
584 
585 #if (NPFB > 0)
586 	if (!strcmp(consinfo->devname, "be")) {
587 		pfb_cnattach(consinfo->addr);
588 #if (NPCKBC > 0)
589 		pckbc_cnattach(&bebox_isa_io_bs_tag, IO_KBD, KBCMDP,
590 		    PCKBC_KBD_SLOT);
591 #endif
592 		return;
593 	}
594 #endif
595 
596 #if (NPC > 0) || (NVGA > 0)
597 	if (!strcmp(consinfo->devname, "vga")) {
598 #if (NVGA > 0)
599 		if (!vga_cnattach(&bebox_io_bs_tag, &bebox_mem_bs_tag,
600 				  -1, 1))
601 			goto dokbd;
602 #endif
603 #if (NPC > 0)
604 		pccnattach();
605 #endif
606 dokbd:
607 #if (NPCKBC > 0)
608 		pckbc_cnattach(&bebox_isa_io_bs_tag, IO_KBD, KBCMDP,
609 		    PCKBC_KBD_SLOT);
610 #endif
611 		return;
612 	}
613 #endif /* PC | VGA */
614 
615 #if (NCOM > 0)
616 	if (!strcmp(consinfo->devname, "com")) {
617 		bus_space_tag_t tag = &bebox_isa_io_bs_tag;
618 
619 		if(comcnattach(tag, consinfo->addr, consinfo->speed, COM_FREQ,
620 		    ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8)))
621 			panic("can't init serial console");
622 
623 		return;
624 	}
625 #endif
626 	panic("invalid console device %s", consinfo->devname);
627 }
628 
629 #if (NPCKBC > 0) && (NPCKBD == 0)
630 /*
631  * glue code to support old console code with the
632  * mi keyboard controller driver
633  */
634 int
635 pckbc_machdep_cnattach(kbctag, kbcslot)
636 	pckbc_tag_t kbctag;
637 	pckbc_slot_t kbcslot;
638 {
639 #if (NPC > 0)
640 	return (pcconskbd_cnattach(kbctag, kbcslot));
641 #else
642 	return (ENXIO);
643 #endif
644 }
645 #endif
646 
647 
648 void
649 dumpsys()
650 {
651 	printf("dumpsys: TBD\n");
652 }
653 
654 /*
655  * Soft networking interrupts.
656  */
657 void
658 softnet(isr)
659 	int isr;
660 {
661 #define DONETISR(bit, fn) do {		\
662 	if (isr & (1 << bit))		\
663 		fn();			\
664 } while (0)
665 
666 #include <net/netisr_dispatch.h>
667 
668 #undef DONETISR
669 }
670 
671 /*
672  * Stray interrupts.
673  */
674 void
675 strayintr(irq)
676 	int irq;
677 {
678 	log(LOG_ERR, "stray interrupt %d\n", irq);
679 }
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 	splhigh();
700 	if (howto & RB_HALT) {
701 		doshutdownhooks();
702 		printf("halted\n\n");
703 #if 0
704 		ppc_exit();
705 #endif
706 	}
707 	if (!cold && (howto & RB_DUMP))
708 		dumpsys();
709 	doshutdownhooks();
710 	printf("rebooting\n\n");
711 	if (what && *what) {
712 		if (strlen(what) > sizeof str - 5)
713 			printf("boot string too large, ignored\n");
714 		else {
715 			strcpy(str, what);
716 			ap1 = ap = str + strlen(str);
717 			*ap++ = ' ';
718 		}
719 	}
720 	*ap++ = '-';
721 	if (howto & RB_SINGLE)
722 		*ap++ = 's';
723 	if (howto & RB_KDB)
724 		*ap++ = 'd';
725 	*ap++ = 0;
726 	if (ap[-2] == '-')
727 		*ap1 = 0;
728 #if 0
729 	ppc_boot(str);
730 #endif
731 	while (1);
732 }
733 
734 void
735 lcsplx(ipl)
736 	int ipl;
737 {
738 	splx(ipl);
739 }
740 
741 /*
742  * Allocate vm space and mapin the I/O address
743  */
744 void *
745 mapiodev(pa, len)
746 	paddr_t pa;
747 	psize_t len;
748 {
749 	paddr_t faddr;
750 	vaddr_t taddr, va;
751 	int off;
752 
753 	faddr = trunc_page(pa);
754 	off = pa - faddr;
755 	len = round_page(off + len);
756 	va = taddr = uvm_km_valloc(kernel_map, len);
757 
758 	if (va == 0)
759 		return NULL;
760 
761 	for (; len > 0; len -= NBPG) {
762 		pmap_enter(pmap_kernel(), taddr, faddr,
763 			   VM_PROT_READ | VM_PROT_WRITE, PMAP_WIRED);
764 		faddr += NBPG;
765 		taddr += NBPG;
766 	}
767 	pmap_update(pmap_kernel());
768 	return (void *)(va + off);
769 }
770