xref: /netbsd/sys/arch/news68k/news68k/machdep.c (revision 6550d01e)
1 /*	$NetBSD: machdep.c,v 1.88 2011/01/17 14:36:33 tsutsui Exp $	*/
2 
3 /*
4  * Copyright (c) 1982, 1986, 1990, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * the Systems Programming Group of the University of Utah Computer
9  * Science Department.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  * from: Utah $Hdr: machdep.c 1.74 92/12/20$
36  *
37  *	@(#)machdep.c	8.10 (Berkeley) 4/20/94
38  */
39 /*
40  * Copyright (c) 1988 University of Utah.
41  *
42  * This code is derived from software contributed to Berkeley by
43  * the Systems Programming Group of the University of Utah Computer
44  * Science Department.
45  *
46  * Redistribution and use in source and binary forms, with or without
47  * modification, are permitted provided that the following conditions
48  * are met:
49  * 1. Redistributions of source code must retain the above copyright
50  *    notice, this list of conditions and the following disclaimer.
51  * 2. Redistributions in binary form must reproduce the above copyright
52  *    notice, this list of conditions and the following disclaimer in the
53  *    documentation and/or other materials provided with the distribution.
54  * 3. All advertising materials mentioning features or use of this software
55  *    must display the following acknowledgement:
56  *	This product includes software developed by the University of
57  *	California, Berkeley and its contributors.
58  * 4. Neither the name of the University nor the names of its contributors
59  *    may be used to endorse or promote products derived from this software
60  *    without specific prior written permission.
61  *
62  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
63  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
66  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
70  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
71  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72  * SUCH DAMAGE.
73  *
74  * from: Utah $Hdr: machdep.c 1.74 92/12/20$
75  *
76  *	@(#)machdep.c	8.10 (Berkeley) 4/20/94
77  */
78 
79 #include <sys/cdefs.h>
80 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.88 2011/01/17 14:36:33 tsutsui Exp $");
81 
82 #include "opt_ddb.h"
83 #include "opt_compat_netbsd.h"
84 #include "opt_modular.h"
85 
86 #include <sys/param.h>
87 #include <sys/systm.h>
88 #include <sys/buf.h>
89 #include <sys/conf.h>
90 #include <sys/kernel.h>
91 #include <sys/device.h>
92 #include <sys/malloc.h>
93 #include <sys/mbuf.h>
94 #include <sys/mount.h>
95 #include <sys/msgbuf.h>
96 #include <sys/proc.h>
97 #include <sys/reboot.h>
98 #include <sys/tty.h>
99 #include <sys/exec.h>
100 #include <sys/exec_aout.h>		/* for MID_* */
101 #include <sys/core.h>
102 #include <sys/kcore.h>
103 #include <sys/ksyms.h>
104 #include <sys/module.h>
105 
106 #ifdef DDB
107 #include <machine/db_machdep.h>
108 #include <ddb/db_sym.h>
109 #include <ddb/db_extern.h>
110 #endif
111 #ifdef __ELF__
112 #include <sys/exec_elf.h>
113 #endif
114 
115 #include <machine/autoconf.h>
116 #include <machine/cpu.h>
117 #include <machine/reg.h>
118 #include <machine/pcb.h>
119 #include <machine/pte.h>
120 #include <machine/intr.h>
121 
122 #include <machine/kcore.h>	/* XXX should be pulled in by sys/kcore.h */
123 
124 #include <dev/cons.h>
125 
126 #define MAXMEM	64*1024		/* XXX - from cmap.h */
127 #include <uvm/uvm_extern.h>
128 
129 #include <sys/sysctl.h>
130 
131 #include <news68k/news68k/machid.h>
132 #include <news68k/news68k/isr.h>
133 
134 #include "le.h"
135 #include "kb.h"
136 #include "ms.h"
137 #include "si.h"
138 #include "ksyms.h"
139 /* XXX etc. etc. */
140 
141 /* the following is used externally (sysctl_hw) */
142 char	machine[] = MACHINE;	/* from <machine/param.h> */
143 
144 /* Our exported CPU info; we can have only one. */
145 struct cpu_info cpu_info_store;
146 
147 struct vm_map *phys_map = NULL;
148 
149 int	maxmem;			/* max memory per process */
150 int	physmem = MAXMEM;	/* max supported memory, changes to actual */
151 /*
152  * safepri is a safe priority for sleep to set for a spin-wait
153  * during autoconfiguration or after a panic.
154  */
155 int	safepri = PSL_LOWIPL;
156 
157 extern paddr_t avail_start, avail_end;
158 extern int end, *esym;
159 extern u_int lowram;
160 extern u_int ctrl_led_phys;
161 
162 /* prototypes for local functions */
163 static void identifycpu(void);
164 static void initcpu(void);
165 static int cpu_dumpsize(void);
166 static int cpu_dump(int (*)(dev_t, daddr_t, void *, size_t), daddr_t *);
167 static void cpu_init_kcore_hdr(void);
168 
169 #ifdef news1700
170 static void news1700_init(void);
171 static void parityenable(void);
172 static void parityerror(void);
173 #endif
174 #ifdef news1200
175 static void news1200_init(void);
176 #endif
177 
178 /* functions called from locore.s */
179 void dumpsys(void);
180 void news68k_init(void);
181 void straytrap(int, u_short);
182 
183 /*
184  * Machine-dependent crash dump header info.
185  */
186 cpu_kcore_hdr_t cpu_kcore_hdr;
187 
188 /*
189  * Note that the value of delay_divisor is roughly
190  * 2048 / cpuspeed (where cpuspeed is in MHz) on 68020
191  * and 68030 systems.
192  */
193 int	cpuspeed = 25;		/* relative CPU speed; XXX skewed on 68040 */
194 int	delay_divisor = 82;	/* delay constant */
195 
196 /*
197  * Early initialization, before main() is called.
198  */
199 void
200 news68k_init(void)
201 {
202 	int i;
203 
204 	/*
205 	 * Tell the VM system about available physical memory.  The
206 	 * news68k only has one segment.
207 	 */
208 	uvm_page_physload(atop(avail_start), atop(avail_end),
209 	    atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT);
210 
211 	/* Initialize system variables. */
212 	switch (systype) {
213 #ifdef news1700
214 	case NEWS1700:
215 		news1700_init();
216 		break;
217 #endif
218 #ifdef news1200
219 	case NEWS1200:
220 		news1200_init();
221 		break;
222 #endif
223 	default:
224 		panic("impossible system type");
225 	}
226 
227 	isrinit();
228 
229 	/*
230 	 * Initialize error message buffer (at end of core).
231 	 * avail_end was pre-decremented in pmap_bootstrap to compensate.
232 	 */
233 	for (i = 0; i < btoc(MSGBUFSIZE); i++)
234 		pmap_kenter_pa((vaddr_t)msgbufaddr + i * PAGE_SIZE,
235 		    avail_end + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, 0)
236 	pmap_update(pmap_kernel());
237 	initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE));
238 }
239 
240 /*
241  * cpu_startup: allocate memory for variable-sized tables,
242  * initialize CPU, and do autoconfiguration.
243  */
244 void
245 cpu_startup(void)
246 {
247 	vaddr_t minaddr, maxaddr;
248 	char pbuf[9];
249 #ifdef DEBUG
250 	extern int pmapdebug;
251 	int opmapdebug = pmapdebug;
252 
253 	pmapdebug = 0;
254 #endif
255 
256 	if (fputype != FPU_NONE)
257 		m68k_make_fpu_idle_frame();
258 
259 	/*
260 	 * Initialize the kernel crash dump header.
261 	 */
262 	cpu_init_kcore_hdr();
263 
264 	/*
265 	 * Good {morning,afternoon,evening,night}.
266 	 */
267 	printf("%s%s", copyright, version);
268 	identifycpu();
269 	format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
270 	printf("total memory = %s\n", pbuf);
271 
272 	minaddr = 0;
273 
274 	/*
275 	 * Allocate a submap for physio
276 	 */
277 	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
278 	    VM_PHYS_SIZE, 0, false, NULL);
279 
280 #ifdef DEBUG
281 	pmapdebug = opmapdebug;
282 #endif
283 	format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
284 	printf("avail memory = %s\n", pbuf);
285 
286 	/*
287 	 * Set up CPU-specific registers, cache, etc.
288 	 */
289 	initcpu();
290 }
291 
292 /*
293  * Set registers on exec.
294  */
295 void
296 setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack)
297 {
298 	struct frame *frame = (struct frame *)l->l_md.md_regs;
299 	struct pcb *pcb = lwp_getpcb(l);
300 
301 	frame->f_sr = PSL_USERSET;
302 	frame->f_pc = pack->ep_entry & ~1;
303 	frame->f_regs[D0] = 0;
304 	frame->f_regs[D1] = 0;
305 	frame->f_regs[D2] = 0;
306 	frame->f_regs[D3] = 0;
307 	frame->f_regs[D4] = 0;
308 	frame->f_regs[D5] = 0;
309 	frame->f_regs[D6] = 0;
310 	frame->f_regs[D7] = 0;
311 	frame->f_regs[A0] = 0;
312 	frame->f_regs[A1] = 0;
313 	frame->f_regs[A2] = (int)l->l_proc->p_psstr;
314 	frame->f_regs[A3] = 0;
315 	frame->f_regs[A4] = 0;
316 	frame->f_regs[A5] = 0;
317 	frame->f_regs[A6] = 0;
318 	frame->f_regs[SP] = stack;
319 
320 	/* restore a null state frame */
321 	pcb->pcb_fpregs.fpf_null = 0;
322 	if (fputype != FPU_NONE)
323 		m68881_restore(&pcb->pcb_fpregs);
324 }
325 
326 /*
327  * Info for CTL_HW
328  */
329 char cpu_model[124];
330 
331 int news_machine_id;
332 
333 static void
334 identifycpu(void)
335 {
336 
337 	printf("SONY NET WORK STATION, Model %s, ", cpu_model);
338 	printf("Machine ID #%d\n", news_machine_id);
339 
340 	delay_divisor = (20480 / cpuspeed + 5) / 10; /* XXX */
341 }
342 
343 /*
344  * machine dependent system variables.
345  */
346 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
347 {
348 
349 	sysctl_createv(clog, 0, NULL, NULL,
350 		       CTLFLAG_PERMANENT,
351 		       CTLTYPE_NODE, "machdep", NULL,
352 		       NULL, 0, NULL, 0,
353 		       CTL_MACHDEP, CTL_EOL);
354 
355 	sysctl_createv(clog, 0, NULL, NULL,
356 		       CTLFLAG_PERMANENT,
357 		       CTLTYPE_STRUCT, "console_device", NULL,
358 		       sysctl_consdev, 0, NULL, sizeof(dev_t),
359 		       CTL_MACHDEP, CPU_CONSDEV, CTL_EOL);
360 }
361 
362 int	waittime = -1;
363 
364 void
365 cpu_reboot(int howto, char *bootstr)
366 {
367 	struct pcb *pcb = lwp_getpcb(curlwp);
368 
369 	/* take a snap shot before clobbering any registers */
370 	if (pcb != NULL)
371 		savectx(pcb);
372 
373 	/* If system is cold, just halt. */
374 	if (cold) {
375 		howto |= RB_HALT;
376 		goto haltsys;
377 	}
378 
379 	boothowto = howto;
380 	if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
381 		waittime = 0;
382 		vfs_shutdown();
383 		/*
384 		 * If we've been adjusting the clock, the todr
385 		 * will be out of synch; adjust it now.
386 		 */
387 		resettodr();
388 	}
389 
390 	/* Disable interrupts. */
391 	splhigh();
392 
393 	/* If rebooting and a dump is requested, do it. */
394 	if (howto & RB_DUMP)
395 		dumpsys();
396 
397  haltsys:
398 	/* Run any shutdown hooks. */
399 	doshutdownhooks();
400 
401 	pmf_system_shutdown(boothowto);
402 
403 #if defined(PANICWAIT) && !defined(DDB)
404 	if ((howto & RB_HALT) == 0 && panicstr) {
405 		printf("hit any key to reboot...\n");
406 		(void)cngetc();
407 		printf("\n");
408 	}
409 #endif
410 
411 	/* Finally, halt/reboot the system. */
412 	if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
413 		DELAY(1000000);
414 		doboot(RB_POWERDOWN);
415 		/* NOTREACHED */
416 	}
417 
418 	if (howto & RB_HALT) {
419 		printf("System halted.\n\n");
420 		doboot(RB_HALT);
421 		/* NOTREACHED */
422 	}
423 
424 	printf("rebooting...\n");
425 	DELAY(1000000);
426 	doboot(RB_AUTOBOOT);
427 	/* NOTREACHED */
428 }
429 
430 /*
431  * Initialize the kernel crash dump header.
432  */
433 static void
434 cpu_init_kcore_hdr(void)
435 {
436 	cpu_kcore_hdr_t *h = &cpu_kcore_hdr;
437 	struct m68k_kcore_hdr *m = &h->un._m68k;
438 
439 	memset(&cpu_kcore_hdr, 0, sizeof(cpu_kcore_hdr));
440 
441 	/*
442 	 * Initialize the `dispatcher' portion of the header.
443 	 */
444 	strcpy(h->name, machine);
445 	h->page_size = PAGE_SIZE;
446 	h->kernbase = KERNBASE;
447 
448 	/*
449 	 * Fill in information about our MMU configuration.
450 	 */
451 	m->mmutype	= mmutype;
452 	m->sg_v		= SG_V;
453 	m->sg_frame	= SG_FRAME;
454 	m->sg_ishift	= SG_ISHIFT;
455 	m->sg_pmask	= SG_PMASK;
456 	m->sg40_shift1	= SG4_SHIFT1;
457 	m->sg40_mask2	= SG4_MASK2;
458 	m->sg40_shift2	= SG4_SHIFT2;
459 	m->sg40_mask3	= SG4_MASK3;
460 	m->sg40_shift3	= SG4_SHIFT3;
461 	m->sg40_addr1	= SG4_ADDR1;
462 	m->sg40_addr2	= SG4_ADDR2;
463 	m->pg_v		= PG_V;
464 	m->pg_frame	= PG_FRAME;
465 
466 	/*
467 	 * Initialize pointer to kernel segment table.
468 	 */
469 	m->sysseg_pa = (uint32_t)(pmap_kernel()->pm_stpa);
470 
471 	/*
472 	 * Initialize relocation value such that:
473 	 *
474 	 *	pa = (va - KERNBASE) + reloc
475 	 */
476 	m->reloc = lowram;
477 
478 	/*
479 	 * Define the end of the relocatable range.
480 	 */
481 	m->relocend = (uint32_t)&end;
482 
483 	/*
484 	 * news68k has one contiguous memory segment.
485 	 */
486 	m->ram_segs[0].start = lowram;
487 	m->ram_segs[0].size  = ctob(physmem);
488 }
489 
490 /*
491  * Compute the size of the machine-dependent crash dump header.
492  * Returns size in disk blocks.
493  */
494 
495 #define CHDRSIZE (ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)))
496 #define MDHDRSIZE roundup(CHDRSIZE, dbtob(1))
497 
498 static int
499 cpu_dumpsize(void)
500 {
501 
502 	return btodb(MDHDRSIZE);
503 }
504 
505 /*
506  * Called by dumpsys() to dump the machine-dependent header.
507  */
508 static int
509 cpu_dump(int (*dump)(dev_t, daddr_t, void *, size_t), daddr_t *blknop)
510 {
511 	int buf[MDHDRSIZE / sizeof(int)];
512 	cpu_kcore_hdr_t *chdr;
513 	kcore_seg_t *kseg;
514 	int error;
515 
516 	kseg = (kcore_seg_t *)buf;
517 	chdr = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(kcore_seg_t)) /
518 	    sizeof(int)];
519 
520 	/* Create the segment header. */
521 	CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
522 	kseg->c_size = MDHDRSIZE - ALIGN(sizeof(kcore_seg_t));
523 
524 	memcpy(chdr, &cpu_kcore_hdr, sizeof(cpu_kcore_hdr_t));
525 	error = (*dump)(dumpdev, *blknop, (void *)buf, sizeof(buf));
526 	*blknop += btodb(sizeof(buf));
527 	return error;
528 }
529 
530 /*
531  * These variables are needed by /sbin/savecore
532  */
533 uint32_t dumpmag = 0x8fca0101;	/* magic number */
534 int	dumpsize = 0;		/* pages */
535 long	dumplo = 0;		/* blocks */
536 
537 /*
538  * This is called by main to set dumplo and dumpsize.
539  * Dumps always skip the first PAGE_SIZE of disk space
540  * in case there might be a disk label stored there.
541  * If there is extra space, put dump at the end to
542  * reduce the chance that swapping trashes it.
543  */
544 void
545 cpu_dumpconf(void)
546 {
547 	const struct bdevsw *bdev;
548 	int chdrsize;	/* size of dump header */
549 	int nblks;	/* size of dump area */
550 
551 	if (dumpdev == NODEV)
552 		return;
553 	bdev = bdevsw_lookup(dumpdev);
554 	if (bdev == NULL) {
555 		dumpdev = NODEV;
556 		return;
557 	}
558 	if (bdev->d_psize == NULL)
559 		return;
560 	nblks = (*bdev->d_psize)(dumpdev);
561 	chdrsize = cpu_dumpsize();
562 
563 	dumpsize = btoc(cpu_kcore_hdr.un._m68k.ram_segs[0].size);
564 
565 	/*
566 	 * Check do see if we will fit.  Note we always skip the
567 	 * first PAGE_SIZE in case there is a disk label there.
568 	 */
569 	if (nblks < (ctod(dumpsize) + chdrsize + ctod(1))) {
570 		dumpsize = 0;
571 		dumplo = -1;
572 		return;
573 	}
574 
575 	/*
576 	 * Put dump at the end of the partition.
577 	 */
578 	dumplo = (nblks - 1) - ctod(dumpsize) - chdrsize;
579 }
580 
581 /*
582  * Dump physical memory onto the dump device.  Called by cpu_reboot().
583  */
584 void
585 dumpsys(void)
586 {
587 	const struct bdevsw *bdev;
588 	daddr_t blkno;		/* current block to write */
589 				/* dump routine */
590 	int (*dump)(dev_t, daddr_t, void *, size_t);
591 	int pg;			/* page being dumped */
592 	paddr_t maddr;		/* PA being dumped */
593 	int error;		/* error code from (*dump)() */
594 
595 	/* XXX initialized here because of gcc lossage */
596 	maddr = lowram;
597 	pg = 0;
598 
599 	/* Make sure dump device is valid. */
600 	if (dumpdev == NODEV)
601 		return;
602 	bdev = bdevsw_lookup(dumpdev);
603 	if (bdev == NULL)
604 		return;
605 	if (dumpsize == 0) {
606 		cpu_dumpconf();
607 		if (dumpsize == 0)
608 			return;
609 	}
610 	if (dumplo <= 0) {
611 		printf("\ndump to dev %u,%u not possible\n",
612 		    major(dumpdev), minor(dumpdev));
613 		return;
614 	}
615 	dump = bdev->d_dump;
616 	blkno = dumplo;
617 
618 	printf("\ndumping to dev %u,%u offset %ld\n",
619 	    major(dumpdev), minor(dumpdev), dumplo);
620 
621 	printf("dump ");
622 
623 	/* Write the dump header. */
624 	error = cpu_dump(dump, &blkno);
625 	if (error)
626 		goto bad;
627 
628 	for (pg = 0; pg < dumpsize; pg++) {
629 #define NPGMB	(1024*1024/PAGE_SIZE)
630 		/* print out how many MBs we have dumped */
631 		if (pg && (pg % NPGMB) == 0)
632 			printf_nolog("%d ", pg / NPGMB);
633 #undef NPGMB
634 		pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr,
635 		    VM_PROT_READ, VM_PROT_READ|PMAP_WIRED);
636 
637 		pmap_update(pmap_kernel());
638 		error = (*dump)(dumpdev, blkno, vmmap, PAGE_SIZE);
639  bad:
640 		switch (error) {
641 		case 0:
642 			maddr += PAGE_SIZE;
643 			blkno += btodb(PAGE_SIZE);
644 			break;
645 
646 		case ENXIO:
647 			printf("device bad\n");
648 				return;
649 
650 		case EFAULT:
651 			printf("device not ready\n");
652 			return;
653 
654 		case EINVAL:
655 			printf("area improper\n");
656 			return;
657 
658 		case EIO:
659 			printf("i/o error\n");
660 			return;
661 
662 		case EINTR:
663 			printf("aborted from console\n");
664 			return;
665 
666 		default:
667 			printf("error %d\n", error);
668 			return;
669 		}
670 	}
671 	printf("succeeded\n");
672 }
673 
674 static void
675 initcpu(void)
676 {
677 
678 #ifdef MAPPEDCOPY
679 	/*
680 	 * Initialize lower bound for doing copyin/copyout using
681 	 * page mapping (if not already set).  We don't do this on
682 	 * VAC machines as it loses big time.
683 	 */
684 	if (ectype == EC_VIRT)
685 		mappedcopysize = -1;	/* in case it was patched */
686 	else
687 		mappedcopysize = PAGE_SIZE;
688 #endif
689 }
690 
691 void
692 straytrap(int pc, u_short evec)
693 {
694 
695 	printf("unexpected trap (vector offset %x) from %x\n",
696 	    evec & 0xFFF, pc);
697 }
698 
699 /* XXX should change the interface, and make one badaddr() function */
700 
701 int	*nofault;
702 
703 int
704 badaddr(void *addr, int nbytes)
705 {
706 	int i;
707 	label_t	faultbuf;
708 
709 #ifdef lint
710 	i = *addr; if (i) return 0;
711 #endif
712 
713 	nofault = (int *) &faultbuf;
714 	if (setjmp((label_t *)nofault)) {
715 		nofault = (int *) 0;
716 		return 1;
717 	}
718 	switch (nbytes) {
719 	case 1:
720 		i = *(volatile char *)addr;
721 		break;
722 
723 	case 2:
724 		i = *(volatile short *)addr;
725 		break;
726 
727 	case 4:
728 		i = *(volatile int *)addr;
729 		break;
730 
731 	default:
732 		panic("badaddr: bad request");
733 	}
734 	nofault = (int *) 0;
735 	return 0;
736 }
737 
738 int
739 badbaddr(void *addr)
740 {
741 	int i;
742 	label_t	faultbuf;
743 
744 	nofault = (int *) &faultbuf;
745 	if (setjmp((label_t *)nofault)) {
746 		nofault = (int *) 0;
747 		return 1;
748 	}
749 	i = *(volatile char *)addr;
750 	nofault = (int *) 0;
751 	return 0;
752 }
753 
754 /*
755  * cpu_exec_aout_makecmds():
756  *	CPU-dependent a.out format hook for execve().
757  *
758  * Determine of the given exec package refers to something which we
759  * understand and, if so, set up the vmcmds for it.
760  *
761  * XXX what are the special cases for the hp300?
762  * XXX why is this COMPAT_NOMID?  was something generating
763  *	hp300 binaries with an a_mid of 0?  i thought that was only
764  *	done on little-endian machines...  -- cgd
765  */
766 int
767 cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp)
768 {
769 #if defined(COMPAT_NOMID) || defined(COMPAT_44)
770 	u_long midmag, magic;
771 	u_short mid;
772 	int error;
773 	struct exec *execp = epp->ep_hdr;
774 
775 	midmag = ntohl(execp->a_midmag);
776 	mid = (midmag >> 16) & 0xffff;
777 	magic = midmag & 0xffff;
778 
779 	midmag = mid << 16 | magic;
780 
781 	switch (midmag) {
782 #ifdef COMPAT_NOMID
783 	case (MID_ZERO << 16) | ZMAGIC:
784 		error = exec_aout_prep_oldzmagic(l->l_proc, epp);
785 		return(error);
786 #endif
787 #ifdef COMPAT_44
788 	case (MID_HP300 << 16) | ZMAGIC:
789 		error = exec_aout_prep_oldzmagic(p, epp);
790 		return error;
791 #endif
792 	}
793 #endif /* !(defined(COMPAT_NOMID) || defined(COMPAT_44)) */
794 
795 	return ENOEXEC;
796 }
797 
798 /*
799  *  System dependent initilization
800  */
801 
802 static volatile uint8_t *dip_switch, *int_status;
803 
804 const uint8_t *idrom_addr;
805 volatile uint8_t *ctrl_ast, *ctrl_int2;
806 volatile uint8_t *ctrl_led;
807 uint32_t sccport0a, lance_mem_phys;
808 
809 #ifdef news1700
810 static volatile u_char *ctrl_parity, *ctrl_parity_clr, *parity_vector;
811 
812 struct news68k_model {
813 	const int id;
814 	const char *name;
815 };
816 
817 static const struct news68k_model news68k_models[] = {
818 	{ ICK001,	"ICK001"	},	/*  1 */
819 	{ ICK00X,	"ICK00X"	},	/*  2 */
820 	{ NWS799,	"NWS-799"	},	/*  3 */
821 	{ NWS800,	"NWS-800"	},	/*  4 */
822 	{ NWS801,	"NWS-801"	},	/*  5 */
823 	{ NWS802,	"NWS-802"	},	/*  6 */
824 	{ NWS711,	"NWS-711"	},	/*  7 */
825 	{ NWS721,	"NWS-721"	},	/*  8 */
826 	{ NWS1850,	"NWS-1850"	},	/*  9 */
827 	{ NWS810,	"NWS-810"	},	/* 10 */
828 	{ NWS811,	"NWS-811"	},	/* 11 */
829 	{ NWS1830,	"NWS-1830"	},	/* 12 */
830 	{ NWS1750,	"NWS-1750"	},	/* 13 */
831 	{ NWS1720,	"NWS-1720"	},	/* 14 */
832 	{ NWS1930,	"NWS-1930"	},	/* 15 */
833 	{ NWS1960,	"NWS-1960"	},	/* 16 */
834 	{ NWS712,	"NWS-712"	},	/* 17 */
835 	{ NWS1860,	"NWS-1860"	},	/* 18 */
836 	{ PWS1630,	"PWS-1630"	},	/* 19 */
837 	{ NWS820,	"NWS-820"	},	/* 20 */
838 	{ NWS821,	"NWS-821"	},	/* 21 */
839 	{ NWS1760,	"NWS-1760"	},	/* 22 */
840 	{ NWS1710,	"NWS-1710"	},	/* 23 */
841 	{ NWS830,	"NWS-830"	},	/* 30 */
842 	{ NWS831,	"NWS-831"	},	/* 31 */
843 	{ NWS841,	"NWS-841"	},	/* 41 */
844 	{ PWS1570,	"PWS-1570"	},	/* 52 */
845 	{ PWS1590,	"PWS-1590"	},	/* 54 */
846 	{ NWS1520,	"NWS-1520"	},	/* 56 */
847 	{ PWS1550,	"PWS-1550"	},	/* 73 */
848 	{ PWS1520,	"PWS-1520"	},	/* 74 */
849 	{ PWS1560,	"PWS-1560"	},	/* 75 */
850 	{ NWS1530,	"NWS-1530"	},	/* 76 */
851 	{ NWS1580,	"NWS-1580"	},	/* 77 */
852 	{ NWS1510,	"NWS-1510"	},	/* 78 */
853 	{ NWS1410,	"NWS-1410"	},	/* 81 */
854 	{ NWS1450,	"NWS-1450"	},	/* 85 */
855 	{ NWS1460,	"NWS-1460"	},	/* 86 */
856 	{ NWS891,	"NWS-891"	},	/* 91 */
857 	{ NWS911,	"NWS-911"	},	/* 111 */
858 	{ NWS921,	"NWS-921"	},	/* 121 */
859 	{ 0,		NULL		}
860 };
861 
862 static void
863 news1700_init(void)
864 {
865 	struct oidrom idrom;
866 	const char *t;
867 	const uint8_t *p;
868 	uint8_t *q;
869 	u_int i;
870 
871 	dip_switch	= (uint8_t *)IIOV(0xe1c00100);
872 	int_status	= (uint8_t *)IIOV(0xe1c00200);
873 
874 	idrom_addr	= (uint8_t *)IIOV(0xe1c00000);
875 	ctrl_ast	= (uint8_t *)IIOV(0xe1280000);
876 	ctrl_int2	= (uint8_t *)IIOV(0xe1180000);
877 	ctrl_led	= (uint8_t *)IIOV(ctrl_led_phys);
878 
879 	sccport0a	= IIOV(0xe0d40002);
880 	lance_mem_phys	= 0xe0e00000;
881 
882 	p = idrom_addr;
883 	q = (uint8_t *)&idrom;
884 
885 	for (i = 0; i < sizeof(idrom); i++, p += 2)
886 		*q++ = ((*p & 0x0f) << 4) | (*(p + 1) & 0x0f);
887 
888 	t = NULL;
889 	for (i = 0; news68k_models[i].name != NULL; i++) {
890 		if (news68k_models[i].id == idrom.id_model) {
891 			t = news68k_models[i].name;
892 		}
893 	}
894 	if (t == NULL)
895 		panic("unexpected system model.");
896 
897 	strcat(cpu_model, t);
898 	news_machine_id = (idrom.id_serial[0] << 8) + idrom.id_serial[1];
899 
900 	ctrl_parity	= (uint8_t *)IIOV(0xe1080000);
901 	ctrl_parity_clr	= (uint8_t *)IIOV(0xe1a00000);
902 	parity_vector	= (uint8_t *)IIOV(0xe1c00200);
903 
904 	parityenable();
905 
906 	cpuspeed = 25;
907 }
908 
909 /*
910  * parity error handling (vectored NMI?)
911  */
912 
913 static void
914 parityenable(void)
915 {
916 
917 #define PARITY_VECT 0xc0
918 #define PARITY_PRI 7
919 
920 	*parity_vector = PARITY_VECT;
921 
922 	isrlink_vectored((int (*)(void *))parityerror, NULL,
923 	    PARITY_PRI, PARITY_VECT);
924 
925 	*ctrl_parity_clr = 1;
926 	*ctrl_parity = 1;
927 
928 #ifdef DEBUG
929 	printf("enable parity check\n");
930 #endif
931 }
932 
933 static int innmihand;	/* simple mutex */
934 
935 static void
936 parityerror(void)
937 {
938 
939 	/* Prevent unwanted recursion. */
940 	if (innmihand)
941 		return;
942 	innmihand = 1;
943 
944 #if 0 /* XXX need to implement XXX */
945 	panic("parity error");
946 #else
947 	printf("parity error detected.\n");
948 	*ctrl_parity_clr = 1;
949 #endif
950 	innmihand = 0;
951 }
952 #endif /* news1700 */
953 
954 #ifdef news1200
955 static void
956 news1200_init(void)
957 {
958 	struct idrom idrom;
959 	const uint8_t *p;
960 	uint8_t *q;
961 	int i;
962 
963 	dip_switch	= (uint8_t *)IIOV(0xe1680000);
964 	int_status	= (uint8_t *)IIOV(0xe1200000);
965 
966 	idrom_addr	= (uint8_t *)IIOV(0xe1400000);
967 	ctrl_ast	= (uint8_t *)IIOV(0xe1100000);
968 	ctrl_int2	= (uint8_t *)IIOV(0xe10c0000);
969 	ctrl_led	= (uint8_t *)IIOV(ctrl_led_phys);
970 
971 	sccport0a	= IIOV(0xe1780002);
972 	lance_mem_phys	= 0xe1a00000;
973 
974 	p = idrom_addr;
975 	q = (uint8_t *)&idrom;
976 	for (i = 0; i < sizeof(idrom); i++, p += 2)
977 		*q++ = ((*p & 0x0f) << 4) | (*(p + 1) & 0x0f);
978 
979 	strcat(cpu_model, idrom.id_model);
980 	news_machine_id = idrom.id_serial;
981 
982 	cpuspeed = 25;
983 }
984 #endif /* news1200 */
985 
986 /*
987  * interrupt handlers
988  * XXX should do better handling XXX
989  */
990 
991 void intrhand_lev3(void);
992 void intrhand_lev4(void);
993 
994 void
995 intrhand_lev3(void)
996 {
997 	int stat;
998 
999 	stat = *int_status;
1000 	intrcnt[3]++;
1001 	curcpu()->ci_data.cpu_nintr++;
1002 #if 1
1003 	printf("level 3 interrupt: INT_STATUS = 0x%02x\n", stat);
1004 #endif
1005 }
1006 
1007 extern int leintr(int);
1008 extern int si_intr(int);
1009 
1010 void
1011 intrhand_lev4(void)
1012 {
1013 	int stat;
1014 
1015 #define INTST_LANCE	0x04
1016 #define INTST_SCSI	0x80
1017 
1018 	stat = *int_status;
1019 	intrcnt[4]++;
1020 	curcpu()->ci_data.cpu_nintr++;
1021 
1022 #if NSI > 0
1023 	if (stat & INTST_SCSI) {
1024 		si_intr(0);
1025 	}
1026 #endif
1027 #if NLE > 0
1028 	if (stat & INTST_LANCE) {
1029 		leintr(0);
1030 	}
1031 #endif
1032 #if 0
1033 	printf("level 4 interrupt\n");
1034 #endif
1035 }
1036 
1037 /*
1038  * consinit() routines - from newsmips/cpu_cons.c
1039  */
1040 
1041 /*
1042  * Console initialization: called early on from main,
1043  * before vm init or startup.  Do enough configuration
1044  * to choose and initialize a console.
1045  * XXX need something better here.
1046  */
1047 #define SCC_CONSOLE	0
1048 #define SW_CONSOLE	0x07
1049 #define SW_NWB512	0x04
1050 #define SW_NWB225	0x01
1051 #define SW_FBPOP	0x02
1052 #define SW_FBPOP1	0x06
1053 #define SW_FBPOP2	0x03
1054 #define SW_AUTOSEL	0x07
1055 
1056 struct consdev *cn_tab = NULL;
1057 extern struct consdev consdev_bm, consdev_zs;
1058 
1059 int tty00_is_console = 0;
1060 
1061 void
1062 consinit(void)
1063 {
1064 
1065 	int dipsw = *dip_switch;
1066 
1067 	dipsw &= ~SW_CONSOLE;
1068 
1069 	switch (dipsw & SW_CONSOLE) {
1070 	    default: /* XXX no fb support yet */
1071 	    case 0:
1072 		tty00_is_console = 1;
1073 		cn_tab = &consdev_zs;
1074 		(*cn_tab->cn_init)(cn_tab);
1075 		break;
1076 	}
1077 #if NKSYMS || defined(DDB) || defined(MODULAR)
1078 	ksyms_addsyms_elf((int)esym - (int)&end - sizeof(Elf32_Ehdr),
1079 		    (void *)&end, esym);
1080 #endif
1081 #ifdef DDB
1082 	if (boothowto & RB_KDB)
1083 		Debugger();
1084 #endif
1085 }
1086 
1087 #ifdef MODULAR
1088 /*
1089  * Push any modules loaded by the bootloader etc.
1090  */
1091 void
1092 module_init_md(void)
1093 {
1094 }
1095 #endif
1096