11541Srgrimes/*	$NetBSD: machdep.c,v 1.115 2024/03/05 14:15:33 thorpej Exp $	*/
21541Srgrimes
31541Srgrimes/*
41541Srgrimes * Copyright (c) 1988 University of Utah.
51541Srgrimes * Copyright (c) 1982, 1986, 1990, 1993
61541Srgrimes *	The Regents of the University of California.  All rights reserved.
71541Srgrimes *
81541Srgrimes * This code is derived from software contributed to Berkeley by
91541Srgrimes * the Systems Programming Group of the University of Utah Computer
101541Srgrimes * Science Department.
111541Srgrimes *
121541Srgrimes * Redistribution and use in source and binary forms, with or without
131541Srgrimes * modification, are permitted provided that the following conditions
141541Srgrimes * are met:
151541Srgrimes * 1. Redistributions of source code must retain the above copyright
161541Srgrimes *    notice, this list of conditions and the following disclaimer.
171541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
181541Srgrimes *    notice, this list of conditions and the following disclaimer in the
191541Srgrimes *    documentation and/or other materials provided with the distribution.
201541Srgrimes * 3. Neither the name of the University nor the names of its contributors
211541Srgrimes *    may be used to endorse or promote products derived from this software
221541Srgrimes *    without specific prior written permission.
231541Srgrimes *
241541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
251541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
261541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
271541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
281541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
291541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
301541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
311541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
321541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3314478Shsu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3450477Speter * SUCH DAMAGE.
351541Srgrimes *
361541Srgrimes * from: Utah $Hdr: machdep.c 1.74 92/12/20$
3745260Sbde *
385052Sbde *	@(#)machdep.c	8.10 (Berkeley) 4/20/94
392165Spaul */
4055205Speter
4118444Sbde#include <sys/cdefs.h>
4218444Sbde__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.115 2024/03/05 14:15:33 thorpej Exp $");
4318429Sbde
4418429Sbde#include "opt_ddb.h"
451541Srgrimes#include "opt_compat_netbsd.h"
461541Srgrimes#include "opt_modular.h"
471541Srgrimes#include "opt_newsconf.h"
481541Srgrimes
491541Srgrimes#include <sys/param.h>
501541Srgrimes#include <sys/systm.h>
511541Srgrimes#include <sys/buf.h>
521541Srgrimes#include <sys/conf.h>
531541Srgrimes#include <sys/kernel.h>
541541Srgrimes#include <sys/device.h>
551541Srgrimes#include <sys/mbuf.h>
561541Srgrimes#include <sys/mount.h>
571541Srgrimes#include <sys/msgbuf.h>
581541Srgrimes#include <sys/proc.h>
594027Sphk#include <sys/reboot.h>
601541Srgrimes#include <sys/tty.h>
611541Srgrimes#include <sys/exec.h>
621541Srgrimes#include <sys/exec_aout.h>		/* for MID_* */
631541Srgrimes#include <sys/core.h>
6436735Sdfr#include <sys/kcore.h>
6537601Sdfr#include <sys/ksyms.h>
6637601Sdfr#include <sys/module.h>
6736735Sdfr#include <sys/cpu.h>
6836735Sdfr
691541Srgrimes#ifdef DDB
701541Srgrimes#include <machine/db_machdep.h>
711541Srgrimes#include <ddb/db_sym.h>
721541Srgrimes#include <ddb/db_extern.h>
731541Srgrimes#endif
741541Srgrimes#ifdef __ELF__
751541Srgrimes#include <sys/exec_elf.h>
761541Srgrimes#endif
7714478Shsu
781541Srgrimes#include <machine/autoconf.h>
791541Srgrimes#include <machine/cpu.h>
801541Srgrimes#include <machine/reg.h>
811541Srgrimes#include <machine/pcb.h>
825052Sbde#include <machine/pte.h>
835052Sbde#include <machine/intr.h>
845052Sbde
851541Srgrimes#include <machine/kcore.h>	/* XXX should be pulled in by sys/kcore.h */
861541Srgrimes
871541Srgrimes#include <dev/cons.h>
8814478Shsu#include <dev/mm.h>
8914478Shsu
9014478Shsu#define MAXMEM	64*1024		/* XXX - from cmap.h */
9114478Shsu#include <uvm/uvm_extern.h>
9214478Shsu
9314478Shsu#include <sys/sysctl.h>
941541Srgrimes
951541Srgrimes#include <news68k/news68k/machid.h>
961541Srgrimes#include <news68k/news68k/isr.h>
971541Srgrimes
9842264Sjkh#include "le.h"
991541Srgrimes#include "kb.h"
1001541Srgrimes#include "ms.h"
1011541Srgrimes#include "si.h"
1028876Srgrimes#include "ksyms.h"
1031541Srgrimes#include "romcons.h"
1041541Srgrimes/* XXX etc. etc. */
1051541Srgrimes
1068876Srgrimes/* the following is used externally (sysctl_hw) */
1078876Srgrimeschar	machine[] = MACHINE;	/* from <machine/param.h> */
1081541Srgrimes
1091541Srgrimes/* Our exported CPU info; we can have only one. */
1101541Srgrimesstruct cpu_info cpu_info_store;
11114478Shsu
1121541Srgrimesstruct vm_map *phys_map = NULL;
11314478Shsu
11414478Shsuint	maxmem;			/* max memory per process */
11514478Shsu
11614478Shsuextern paddr_t avail_start, avail_end;
11714478Shsuextern int end, *esym;
11814478Shsuextern u_int lowram;
11914478Shsuextern u_int ctrl_led_phys;
1201541Srgrimes
12114478Shsu/* prototypes for local functions */
12214478Shsustatic void identifycpu(void);
12314478Shsustatic void initcpu(void);
12414478Shsustatic int cpu_dumpsize(void);
1251541Srgrimesstatic int cpu_dump(int (*)(dev_t, daddr_t, void *, size_t), daddr_t *);
12614478Shsustatic void cpu_init_kcore_hdr(void);
12714478Shsu
1281541Srgrimes#ifdef news1700
12914478Shsustatic void news1700_init(void);
13014478Shsustatic void parityenable(void);
1311541Srgrimesstatic void parityerror(void);
13214478Shsu#endif
1331541Srgrimes#ifdef news1200
1341541Srgrimesstatic void news1200_init(void);
1351541Srgrimes#endif
1361541Srgrimes
1371541Srgrimes/* functions called from locore.s */
13814478Shsuvoid dumpsys(void);
13914478Shsuvoid news68k_init(void);
14014478Shsuvoid straytrap(int, u_short);
14114478Shsu
14214478Shsu/*
14314478Shsu * Machine-dependent crash dump header info.
14414478Shsu */
14514478Shsucpu_kcore_hdr_t cpu_kcore_hdr;
14614478Shsu
14714478Shsu/*
14814478Shsu * Note that the value of delay_divisor is roughly
14914478Shsu * 2048 / cpuspeed (where cpuspeed is in MHz) on 68020
1501541Srgrimes * and 68030 systems.
15114478Shsu */
15214478Shsuint	cpuspeed = 25;		/* relative CPU speed; XXX skewed on 68040 */
15314478Shsuint	delay_divisor = 82;	/* delay constant */
15414478Shsu
15514478Shsu/*
15614478Shsu * Early initialization, before main() is called.
15714478Shsu */
1581541Srgrimesvoid
15914478Shsunews68k_init(void)
1601541Srgrimes{
16114478Shsu	int i;
16214478Shsu
16314478Shsu	/*
1641541Srgrimes	 * Tell the VM system about available physical memory.  The
1651541Srgrimes	 * news68k only has one segment.
16614478Shsu	 */
16714478Shsu	uvm_page_physload(atop(avail_start), atop(avail_end),
16814478Shsu	    atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT);
1691541Srgrimes
17014478Shsu	/* Initialize system variables. */
17114478Shsu	switch (systype) {
17214478Shsu#ifdef news1700
17314478Shsu	case NEWS1700:
17414478Shsu		news1700_init();
1751541Srgrimes		break;
17614478Shsu#endif
17714478Shsu#ifdef news1200
1781541Srgrimes	case NEWS1200:
1791541Srgrimes		news1200_init();
1801541Srgrimes		break;
1811541Srgrimes#endif
1821541Srgrimes	default:
18365921Sphk		panic("impossible system type");
18465921Sphk	}
18565921Sphk
18665921Sphk	/*
18765921Sphk	 * Initialize error message buffer (at end of core).
18865921Sphk	 * avail_end was pre-decremented in pmap_bootstrap to compensate.
18965921Sphk	 */
19065921Sphk	for (i = 0; i < btoc(MSGBUFSIZE); i++)
19165921Sphk		pmap_kenter_pa((vaddr_t)msgbufaddr + i * PAGE_SIZE,
19265921Sphk		    avail_end + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, 0);
19365921Sphk	pmap_update(pmap_kernel());
19465921Sphk	initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE));
19565921Sphk}
19665921Sphk
19765921Sphk/*
1981541Srgrimes * cpu_startup: allocate memory for variable-sized tables,
1991541Srgrimes * initialize CPU, and do autoconfiguration.
2001541Srgrimes */
2011541Srgrimesvoid
2021541Srgrimescpu_startup(void)
2031541Srgrimes{
2041541Srgrimes	vaddr_t minaddr, maxaddr;
2051541Srgrimes	char pbuf[9];
2061541Srgrimes#ifdef DEBUG
2071541Srgrimes	extern int pmapdebug;
2081541Srgrimes	int opmapdebug = pmapdebug;
2091541Srgrimes
2101541Srgrimes	pmapdebug = 0;
2111541Srgrimes#endif
2121541Srgrimes
2131541Srgrimes	if (fputype != FPU_NONE)
2141541Srgrimes		m68k_make_fpu_idle_frame();
2151541Srgrimes
2161541Srgrimes	/*
2171541Srgrimes	 * Initialize the kernel crash dump header.
2181541Srgrimes	 */
2191541Srgrimes	cpu_init_kcore_hdr();
2201541Srgrimes
22115571Sasami	/*
22245260Sbde	 * Good {morning,afternoon,evening,night}.
22349617Simp	 */
2241541Srgrimes	printf("%s%s", copyright, version);
22550551Sphk	identifycpu();
22645260Sbde	format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
22716363Sasami	printf("total memory = %s\n", pbuf);
22816363Sasami
2291541Srgrimes	minaddr = 0;
2301541Srgrimes
2311541Srgrimes	/*
2321541Srgrimes	 * Allocate a submap for physio
2331541Srgrimes	 */
2341541Srgrimes	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
2351541Srgrimes	    VM_PHYS_SIZE, 0, false, NULL);
2361541Srgrimes
2371541Srgrimes#ifdef DEBUG
2381541Srgrimes	pmapdebug = opmapdebug;
2391541Srgrimes#endif
2401541Srgrimes	format_bytes(pbuf, sizeof(pbuf), ptoa(uvm_availmem(false)));
2411541Srgrimes	printf("avail memory = %s\n", pbuf);
24215571Sasami
24333469Sjkh	/*
24449617Simp	 * Set up CPU-specific registers, cache, etc.
24514478Shsu	 */
2461541Srgrimes	initcpu();
2471541Srgrimes}
2481541Srgrimes
2491541Srgrimesint news_machine_id;
2501541Srgrimes
2511541Srgrimesstatic void
2521541Srgrimesidentifycpu(void)
2531541Srgrimes{
2541541Srgrimes
2551541Srgrimes	printf("SONY NET WORK STATION, Model %s, ", cpu_getmodel());
2561541Srgrimes	printf("Machine ID #%d\n", news_machine_id);
2571541Srgrimes
2581541Srgrimes	delay_divisor = (20480 / cpuspeed + 5) / 10; /* XXX */
2591541Srgrimes}
2601541Srgrimes
2611541Srgrimes/*
2621541Srgrimes * machine dependent system variables.
2631541Srgrimes */
2641541SrgrimesSYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
2651541Srgrimes{
2661541Srgrimes
2671541Srgrimes	sysctl_createv(clog, 0, NULL, NULL,
2681541Srgrimes	    CTLFLAG_PERMANENT,
26945260Sbde	    CTLTYPE_NODE, "machdep", NULL,
27045260Sbde	    NULL, 0, NULL, 0,
2711541Srgrimes	    CTL_MACHDEP, CTL_EOL);
2721541Srgrimes
2731541Srgrimes	sysctl_createv(clog, 0, NULL, NULL,
2741541Srgrimes	    CTLFLAG_PERMANENT,
2751541Srgrimes	    CTLTYPE_STRUCT, "console_device", NULL,
2761541Srgrimes	    sysctl_consdev, 0, NULL, sizeof(dev_t),
2771541Srgrimes	    CTL_MACHDEP, CPU_CONSDEV, CTL_EOL);
2781541Srgrimes}
2791541Srgrimes
2801541Srgrimesint	waittime = -1;
2811541Srgrimes
2821541Srgrimesvoid
2831541Srgrimescpu_reboot(int howto, char *bootstr)
2841541Srgrimes{
2851541Srgrimes	struct pcb *pcb = lwp_getpcb(curlwp);
2861541Srgrimes
28744948Sgrog	/* take a snap shot before clobbering any registers */
28814478Shsu	if (pcb != NULL)
2891541Srgrimes		savectx(pcb);
2901541Srgrimes
2911541Srgrimes	/* If system is cold, just halt. */
2921541Srgrimes	if (cold) {
2931541Srgrimes		howto |= RB_HALT;
2941541Srgrimes		goto haltsys;
2951541Srgrimes	}
2961541Srgrimes
2971541Srgrimes	boothowto = howto;
2981541Srgrimes	if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
2991541Srgrimes		waittime = 0;
3001541Srgrimes		vfs_shutdown();
3011541Srgrimes	}
3021541Srgrimes
3031541Srgrimes	/* Disable interrupts. */
3041541Srgrimes	splhigh();
3051541Srgrimes
3061541Srgrimes	/* If rebooting and a dump is requested, do it. */
3071541Srgrimes	if (howto & RB_DUMP)
3081541Srgrimes		dumpsys();
3091541Srgrimes
3101541Srgrimes haltsys:
3111541Srgrimes	/* Run any shutdown hooks. */
3121541Srgrimes	doshutdownhooks();
3131541Srgrimes
3141541Srgrimes	pmf_system_shutdown(boothowto);
3151541Srgrimes
3161541Srgrimes#if defined(PANICWAIT) && !defined(DDB)
3171541Srgrimes	if ((howto & RB_HALT) == 0 && panicstr) {
3181541Srgrimes		printf("hit any key to reboot...\n");
3191541Srgrimes		cnpollc(1);
3201541Srgrimes		(void)cngetc();
3211541Srgrimes		cnpollc(0);
3221541Srgrimes		printf("\n");
3231541Srgrimes	}
32414478Shsu#endif
32514478Shsu
3261541Srgrimes	/* Finally, halt/reboot the system. */
3271541Srgrimes	if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
3281541Srgrimes		DELAY(1000000);
3291541Srgrimes		doboot(RB_POWERDOWN);
33045260Sbde		/* NOTREACHED */
33145260Sbde	}
33245260Sbde
3331541Srgrimes	if (howto & RB_HALT) {
3341541Srgrimes		printf("System halted.\n\n");
3351541Srgrimes		doboot(RB_HALT);
33614478Shsu		/* NOTREACHED */
33714478Shsu	}
3381541Srgrimes
3391541Srgrimes	printf("rebooting...\n");
3401541Srgrimes	DELAY(1000000);
3411541Srgrimes	doboot(RB_AUTOBOOT);
3421541Srgrimes	/* NOTREACHED */
3431541Srgrimes}
3441549Srgrimes
3451549Srgrimes/*
34650551Sphk * Initialize the kernel crash dump header.
34716363Sasami */
34816363Sasamistatic void
34916363Sasamicpu_init_kcore_hdr(void)
35016363Sasami{
35116363Sasami	cpu_kcore_hdr_t *h = &cpu_kcore_hdr;
35216363Sasami	struct m68k_kcore_hdr *m = &h->un._m68k;
35316363Sasami
35416363Sasami	memset(&cpu_kcore_hdr, 0, sizeof(cpu_kcore_hdr));
35516363Sasami
35616363Sasami	/*
35716363Sasami	 * Initialize the `dispatcher' portion of the header.
35816363Sasami	 */
35916363Sasami	strcpy(h->name, machine);
36016363Sasami	h->page_size = PAGE_SIZE;
36116363Sasami	h->kernbase = KERNBASE;
36216363Sasami
36316363Sasami	/*
36416363Sasami	 * Fill in information about our MMU configuration.
36516363Sasami	 */
36616363Sasami	m->mmutype	= mmutype;
36716363Sasami	m->sg_v		= SG_V;
36816363Sasami	m->sg_frame	= SG_FRAME;
36916363Sasami	m->sg_ishift	= SG_ISHIFT;
37016363Sasami	m->sg_pmask	= SG_PMASK;
37116363Sasami	m->sg40_shift1	= SG4_SHIFT1;
37216363Sasami	m->sg40_mask2	= SG4_MASK2;
37316363Sasami	m->sg40_shift2	= SG4_SHIFT2;
3741549Srgrimes	m->sg40_mask3	= SG4_MASK3;
3751549Srgrimes	m->sg40_shift3	= SG4_SHIFT3;
3761549Srgrimes	m->sg40_addr1	= SG4_ADDR1;
3773742Spaul	m->sg40_addr2	= SG4_ADDR2;
37859771Sjlemon	m->pg_v		= PG_V;
37959771Sjlemon	m->pg_frame	= PG_FRAME;
38059771Sjlemon
3811549Srgrimes	/*
3821549Srgrimes	 * Initialize pointer to kernel segment table.
3831549Srgrimes	 */
3841549Srgrimes	m->sysseg_pa = (uint32_t)(pmap_kernel()->pm_stpa);
3851549Srgrimes
3861549Srgrimes	/*
3871549Srgrimes	 * Initialize relocation value such that:
3881549Srgrimes	 *
3891549Srgrimes	 *	pa = (va - KERNBASE) + reloc
3901549Srgrimes	 */
39137466Sbde	m->reloc = lowram;
39237466Sbde
3931549Srgrimes	/*
39416363Sasami	 * Define the end of the relocatable range.
3951549Srgrimes	 */
3961549Srgrimes	m->relocend = (uint32_t)&end;
3971549Srgrimes
3981549Srgrimes	/*
3991541Srgrimes	 * news68k has one contiguous memory segment.
4001541Srgrimes	 */
4011541Srgrimes	m->ram_segs[0].start = lowram;
4021541Srgrimes	m->ram_segs[0].size  = ctob(physmem);
4031541Srgrimes}
4041541Srgrimes
4051541Srgrimes/*
4061541Srgrimes * Compute the size of the machine-dependent crash dump header.
4071541Srgrimes * Returns size in disk blocks.
4081541Srgrimes */
4091541Srgrimes
41055205Speter#define CHDRSIZE (ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)))
41151865Sbde#define MDHDRSIZE roundup(CHDRSIZE, dbtob(1))
4125052Sbde
4135052Sbdestatic int
4145052Sbdecpu_dumpsize(void)
4155052Sbde{
4165052Sbde
4175052Sbde	return btodb(MDHDRSIZE);
4188876Srgrimes}
4195052Sbde
4205052Sbde/*
4215052Sbde * Called by dumpsys() to dump the machine-dependent header.
4228193Sjulian */
4238193Sjulianstatic int
4248193Sjuliancpu_dump(int (*dump)(dev_t, daddr_t, void *, size_t), daddr_t *blknop)
4258193Sjulian{
4268193Sjulian	int buf[MDHDRSIZE / sizeof(int)];
4278193Sjulian	cpu_kcore_hdr_t *chdr;
4288193Sjulian	kcore_seg_t *kseg;
42921986Sdg	int error;
4308193Sjulian
4318193Sjulian	kseg = (kcore_seg_t *)buf;
4325052Sbde	chdr = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(kcore_seg_t)) /
43333742Sdg	    sizeof(int)];
43433742Sdg
43546679Sphk	/* Create the segment header. */
43646679Sphk	CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
43746679Sphk	kseg->c_size = MDHDRSIZE - ALIGN(sizeof(kcore_seg_t));
43846679Sphk
43946679Sphk	memcpy(chdr, &cpu_kcore_hdr, sizeof(cpu_kcore_hdr_t));
44046679Sphk	error = (*dump)(dumpdev, *blknop, (void *)buf, sizeof(buf));
44146679Sphk	*blknop += btodb(sizeof(buf));
44246679Sphk	return error;
44346679Sphk}
44446679Sphk
44546679Sphk/*
44646679Sphk * These variables are needed by /sbin/savecore
4475052Sbde */
4485052Sbdeuint32_t dumpmag = 0x8fca0101;	/* magic number */
44921986Sdgint	dumpsize = 0;		/* pages */
4501541Srgrimeslong	dumplo = 0;		/* blocks */
45146679Sphk
45246679Sphk/*
45346679Sphk * This is called by main to set dumplo and dumpsize.
45446679Sphk * Dumps always skip the first PAGE_SIZE of disk space
45546679Sphk * in case there might be a disk label stored there.
45646679Sphk * If there is extra space, put dump at the end to
45758942Sphk * reduce the chance that swapping trashes it.
45832995Sbde */
45912478Sbdevoid
46058942Sphkcpu_dumpconf(void)
46112478Sbde{
46259249Sphk	int chdrsize;	/* size of dump header */
4637090Sbde	int nblks;	/* size of dump area */
46459249Sphk
46551227Sbde	if (dumpdev == NODEV)
4663940Sjkh		return;
46749771Sphk	nblks = bdev_size(dumpdev);
46858942Sphk	chdrsize = cpu_dumpsize();
4695052Sbde
4705052Sbde	dumpsize = btoc(cpu_kcore_hdr.un._m68k.ram_segs[0].size);
47149771Sphk
47248417Speter	/*
47348417Speter	 * Check do see if we will fit.  Note we always skip the
47448417Speter	 * first PAGE_SIZE in case there is a disk label there.
4753940Sjkh	 */
47655205Speter	if (nblks < (ctod(dumpsize) + chdrsize + ctod(1))) {
4775052Sbde		dumpsize = 0;
4785052Sbde		dumplo = -1;
4795052Sbde		return;
48055205Speter	}
4811541Srgrimes
4821541Srgrimes	/*
4831541Srgrimes	 * Put dump at the end of the partition.
4841541Srgrimes	 */
4852165Spaul	dumplo = (nblks - 1) - ctod(dumpsize) - chdrsize;
4865052Sbde}
487
488/*
489 * Dump physical memory onto the dump device.  Called by cpu_reboot().
490 */
491void
492dumpsys(void)
493{
494	const struct bdevsw *bdev;
495	daddr_t blkno;		/* current block to write */
496				/* dump routine */
497	int (*dump)(dev_t, daddr_t, void *, size_t);
498	int pg;			/* page being dumped */
499	paddr_t maddr;		/* PA being dumped */
500	int error;		/* error code from (*dump)() */
501
502	/* XXX initialized here because of gcc lossage */
503	maddr = lowram;
504	pg = 0;
505
506	/* Make sure dump device is valid. */
507	if (dumpdev == NODEV)
508		return;
509	bdev = bdevsw_lookup(dumpdev);
510	if (bdev == NULL)
511		return;
512	if (dumpsize == 0) {
513		cpu_dumpconf();
514		if (dumpsize == 0)
515			return;
516	}
517	if (dumplo <= 0) {
518		printf("\ndump to dev %u,%u not possible\n",
519		    major(dumpdev), minor(dumpdev));
520		return;
521	}
522	dump = bdev->d_dump;
523	blkno = dumplo;
524
525	printf("\ndumping to dev %u,%u offset %ld\n",
526	    major(dumpdev), minor(dumpdev), dumplo);
527
528	printf("dump ");
529
530	/* Write the dump header. */
531	error = cpu_dump(dump, &blkno);
532	if (error)
533		goto bad;
534
535	for (pg = 0; pg < dumpsize; pg++) {
536#define NPGMB	(1024*1024/PAGE_SIZE)
537		/* print out how many MBs we have dumped */
538		if (pg && (pg % NPGMB) == 0)
539			printf_nolog("%d ", pg / NPGMB);
540#undef NPGMB
541		pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr,
542		    VM_PROT_READ, VM_PROT_READ|PMAP_WIRED);
543
544		pmap_update(pmap_kernel());
545		error = (*dump)(dumpdev, blkno, vmmap, PAGE_SIZE);
546 bad:
547		switch (error) {
548		case 0:
549			maddr += PAGE_SIZE;
550			blkno += btodb(PAGE_SIZE);
551			break;
552
553		case ENXIO:
554			printf("device bad\n");
555				return;
556
557		case EFAULT:
558			printf("device not ready\n");
559			return;
560
561		case EINVAL:
562			printf("area improper\n");
563			return;
564
565		case EIO:
566			printf("i/o error\n");
567			return;
568
569		case EINTR:
570			printf("aborted from console\n");
571			return;
572
573		default:
574			printf("error %d\n", error);
575			return;
576		}
577	}
578	printf("succeeded\n");
579}
580
581static void
582initcpu(void)
583{
584}
585
586void
587straytrap(int pc, u_short evec)
588{
589
590	printf("unexpected trap (vector offset %x) from %x\n",
591	    evec & 0xFFF, pc);
592}
593
594/* XXX should change the interface, and make one badaddr() function */
595
596int	*nofault;
597
598int
599badaddr(void *addr, int nbytes)
600{
601	int i;
602	label_t	faultbuf;
603
604#ifdef lint
605	i = *addr; if (i) return 0;
606#endif
607
608	nofault = (int *) &faultbuf;
609	if (setjmp((label_t *)nofault)) {
610		nofault = (int *) 0;
611		return 1;
612	}
613	switch (nbytes) {
614	case 1:
615		i = *(volatile char *)addr;
616		break;
617
618	case 2:
619		i = *(volatile short *)addr;
620		break;
621
622	case 4:
623		i = *(volatile int *)addr;
624		break;
625
626	default:
627		panic("badaddr: bad request");
628	}
629	__USE(i);
630	nofault = (int *) 0;
631	return 0;
632}
633
634int
635badbaddr(void *addr)
636{
637	int i;
638	label_t	faultbuf;
639
640	nofault = (int *) &faultbuf;
641	if (setjmp((label_t *)nofault)) {
642		nofault = (int *) 0;
643		return 1;
644	}
645	i = *(volatile char *)addr;
646	__USE(i);
647	nofault = (int *) 0;
648	return 0;
649}
650
651/*
652 * cpu_exec_aout_makecmds():
653 *	CPU-dependent a.out format hook for execve().
654 *
655 * Determine of the given exec package refers to something which we
656 * understand and, if so, set up the vmcmds for it.
657 *
658 * XXX what are the special cases for the hp300?
659 * XXX why is this COMPAT_NOMID?  was something generating
660 *	hp300 binaries with an a_mid of 0?  i thought that was only
661 *	done on little-endian machines...  -- cgd
662 */
663int
664cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp)
665{
666#if defined(COMPAT_NOMID) || defined(COMPAT_44)
667	u_long midmag, magic;
668	u_short mid;
669	int error;
670	struct exec *execp = epp->ep_hdr;
671
672	midmag = ntohl(execp->a_midmag);
673	mid = (midmag >> 16) & 0xffff;
674	magic = midmag & 0xffff;
675
676	midmag = mid << 16 | magic;
677
678	switch (midmag) {
679#ifdef COMPAT_NOMID
680	case (MID_ZERO << 16) | ZMAGIC:
681		error = exec_aout_prep_oldzmagic(l, epp);
682		return(error);
683#endif
684#ifdef COMPAT_44
685	case (MID_HP300 << 16) | ZMAGIC:
686		error = exec_aout_prep_oldzmagic(l, epp);
687		return error;
688#endif
689	}
690#endif /* !(defined(COMPAT_NOMID) || defined(COMPAT_44)) */
691
692	return ENOEXEC;
693}
694
695/*
696 *  System dependent initilization
697 */
698
699static volatile uint8_t *dip_switch, *int_status;
700
701const uint8_t *idrom_addr;
702volatile uint8_t *ctrl_ast, *ctrl_int2;
703volatile uint8_t *ctrl_led;
704uint32_t sccport0a, lance_mem_phys;
705
706#ifdef news1700
707static volatile u_char *ctrl_parity, *ctrl_parity_clr, *parity_vector;
708
709struct news68k_model {
710	const int id;
711	const char *name;
712};
713
714static const struct news68k_model news68k_models[] = {
715	{ ICK001,	"ICK001"	},	/*  1 */
716	{ ICK00X,	"ICK00X"	},	/*  2 */
717	{ NWS799,	"NWS-799"	},	/*  3 */
718	{ NWS800,	"NWS-800"	},	/*  4 */
719	{ NWS801,	"NWS-801"	},	/*  5 */
720	{ NWS802,	"NWS-802"	},	/*  6 */
721	{ NWS711,	"NWS-711"	},	/*  7 */
722	{ NWS721,	"NWS-721"	},	/*  8 */
723	{ NWS1850,	"NWS-1850"	},	/*  9 */
724	{ NWS810,	"NWS-810"	},	/* 10 */
725	{ NWS811,	"NWS-811"	},	/* 11 */
726	{ NWS1830,	"NWS-1830"	},	/* 12 */
727	{ NWS1750,	"NWS-1750"	},	/* 13 */
728	{ NWS1720,	"NWS-1720"	},	/* 14 */
729	{ NWS1930,	"NWS-1930"	},	/* 15 */
730	{ NWS1960,	"NWS-1960"	},	/* 16 */
731	{ NWS712,	"NWS-712"	},	/* 17 */
732	{ NWS1860,	"NWS-1860"	},	/* 18 */
733	{ PWS1630,	"PWS-1630"	},	/* 19 */
734	{ NWS820,	"NWS-820"	},	/* 20 */
735	{ NWS821,	"NWS-821"	},	/* 21 */
736	{ NWS1760,	"NWS-1760"	},	/* 22 */
737	{ NWS1710,	"NWS-1710"	},	/* 23 */
738	{ NWS830,	"NWS-830"	},	/* 30 */
739	{ NWS831,	"NWS-831"	},	/* 31 */
740	{ NWS841,	"NWS-841"	},	/* 41 */
741	{ PWS1570,	"PWS-1570"	},	/* 52 */
742	{ PWS1590,	"PWS-1590"	},	/* 54 */
743	{ NWS1520,	"NWS-1520"	},	/* 56 */
744	{ PWS1550,	"PWS-1550"	},	/* 73 */
745	{ PWS1520,	"PWS-1520"	},	/* 74 */
746	{ PWS1560,	"PWS-1560"	},	/* 75 */
747	{ NWS1530,	"NWS-1530"	},	/* 76 */
748	{ NWS1580,	"NWS-1580"	},	/* 77 */
749	{ NWS1510,	"NWS-1510"	},	/* 78 */
750	{ NWS1410,	"NWS-1410"	},	/* 81 */
751	{ NWS1450,	"NWS-1450"	},	/* 85 */
752	{ NWS1460,	"NWS-1460"	},	/* 86 */
753	{ NWS891,	"NWS-891"	},	/* 91 */
754	{ NWS911,	"NWS-911"	},	/* 111 */
755	{ NWS921,	"NWS-921"	},	/* 121 */
756	{ 0,		NULL		}
757};
758
759static void
760news1700_init(void)
761{
762	struct oidrom idrom;
763	const char *t;
764	const uint8_t *p;
765	uint8_t *q;
766	u_int i;
767
768	dip_switch	= (uint8_t *)(0xe1c00100);
769	int_status	= (uint8_t *)(0xe1c00200);
770
771	idrom_addr	= (uint8_t *)(0xe1c00000);
772	ctrl_ast	= (uint8_t *)(0xe1280000);
773	ctrl_int2	= (uint8_t *)(0xe1180000);
774	ctrl_led	= (uint8_t *)(ctrl_led_phys);
775
776	sccport0a	= (0xe0d40002);
777	lance_mem_phys	= 0xe0e00000;
778
779	p = idrom_addr;
780	q = (uint8_t *)&idrom;
781
782	for (i = 0; i < sizeof(idrom); i++, p += 2)
783		*q++ = ((*p & 0x0f) << 4) | (*(p + 1) & 0x0f);
784
785	t = NULL;
786	for (i = 0; news68k_models[i].name != NULL; i++) {
787		if (news68k_models[i].id == idrom.id_model) {
788			t = news68k_models[i].name;
789		}
790	}
791	if (t == NULL)
792		panic("unexpected system model.");
793
794	cpu_setmodel("%s", t);
795	news_machine_id = (idrom.id_serial[0] << 8) + idrom.id_serial[1];
796
797	ctrl_parity	= (uint8_t *)(0xe1080000);
798	ctrl_parity_clr	= (uint8_t *)(0xe1a00000);
799	parity_vector	= (uint8_t *)(0xe1c00200);
800
801	parityenable();
802
803	cpuspeed = 25;
804}
805
806/*
807 * parity error handling (vectored NMI?)
808 */
809
810static void
811parityenable(void)
812{
813
814#define PARITY_VECT 0xc0
815#define PARITY_PRI 7
816
817	*parity_vector = PARITY_VECT;
818
819	isrlink_vectored((int (*)(void *))parityerror, NULL,
820	    PARITY_PRI, PARITY_VECT);
821
822	*ctrl_parity_clr = 1;
823	*ctrl_parity = 1;
824
825#ifdef DEBUG
826	printf("enable parity check\n");
827#endif
828}
829
830static int innmihand;	/* simple mutex */
831
832static void
833parityerror(void)
834{
835
836	/* Prevent unwanted recursion. */
837	if (innmihand)
838		return;
839	innmihand = 1;
840
841#if 0 /* XXX need to implement XXX */
842	panic("parity error");
843#else
844	printf("parity error detected.\n");
845	*ctrl_parity_clr = 1;
846#endif
847	innmihand = 0;
848}
849#endif /* news1700 */
850
851#ifdef news1200
852static void
853news1200_init(void)
854{
855	struct idrom idrom;
856	const uint8_t *p;
857	uint8_t *q;
858	int i;
859
860	dip_switch	= (uint8_t *)0xe1680000;
861	int_status	= (uint8_t *)0xe1200000;
862
863	idrom_addr	= (uint8_t *)0xe1400000;
864	ctrl_ast	= (uint8_t *)0xe1100000;
865	ctrl_int2	= (uint8_t *)0xe10c0000;
866	ctrl_led	= (uint8_t *)ctrl_led_phys;
867
868	sccport0a	= 0xe1780002;
869	lance_mem_phys	= 0xe1a00000;
870
871	p = idrom_addr;
872	q = (uint8_t *)&idrom;
873	for (i = 0; i < sizeof(idrom); i++, p += 2)
874		*q++ = ((*p & 0x0f) << 4) | (*(p + 1) & 0x0f);
875
876	cpu_setmodel("%s", idrom.id_model);
877	news_machine_id = idrom.id_serial;
878
879	cpuspeed = 25;
880}
881#endif /* news1200 */
882
883/*
884 * interrupt handlers
885 * XXX should do better handling XXX
886 */
887
888void intrhand_lev3(void);
889void intrhand_lev4(void);
890
891void
892intrhand_lev3(void)
893{
894	int stat;
895
896	stat = *int_status;
897	m68k_count_intr(3);
898#if 1
899	printf("level 3 interrupt: INT_STATUS = 0x%02x\n", stat);
900#endif
901}
902
903extern int leintr(int);
904extern int si_intr(int);
905
906void
907intrhand_lev4(void)
908{
909	int stat;
910
911#define INTST_LANCE	0x04
912#define INTST_SCSI	0x80
913
914	stat = *int_status;
915	m68k_count_intr(4);
916
917#if NSI > 0
918	if (stat & INTST_SCSI) {
919		si_intr(0);
920	}
921#endif
922#if NLE > 0
923	if (stat & INTST_LANCE) {
924		leintr(0);
925	}
926#endif
927#if 0
928	printf("level 4 interrupt\n");
929#endif
930}
931
932/*
933 * consinit() routines - from newsmips/cpu_cons.c
934 */
935
936/*
937 * Console initialization: called early on from main,
938 * before vm init or startup.  Do enough configuration
939 * to choose and initialize a console.
940 * XXX need something better here.
941 */
942#define SCC_CONSOLE	0
943#define SW_CONSOLE	0x07
944#define SW_NWB512	0x04
945#define SW_NWB225	0x01
946#define SW_FBPOP	0x02
947#define SW_FBPOP1	0x06
948#define SW_FBPOP2	0x03
949#define SW_AUTOSEL	0x07
950
951extern struct consdev consdev_rom, consdev_zs;
952
953int tty00_is_console = 0;
954
955void
956consinit(void)
957{
958	uint8_t dipsw;
959
960	dipsw = *dip_switch;
961
962	dipsw = ~dipsw;
963
964	switch (dipsw & SW_CONSOLE) {
965	default: /* XXX no real fb support yet */
966#if NROMCONS > 0
967		cn_tab = &consdev_rom;
968		(*cn_tab->cn_init)(cn_tab);
969		break;
970#endif
971	case 0:
972		tty00_is_console = 1;
973		cn_tab = &consdev_zs;
974		(*cn_tab->cn_init)(cn_tab);
975		break;
976	}
977#if NKSYMS || defined(DDB) || defined(MODULAR)
978	ksyms_addsyms_elf((int)esym - (int)&end - sizeof(Elf32_Ehdr),
979	    (void *)&end, esym);
980#endif
981#ifdef DDB
982	if (boothowto & RB_KDB)
983		Debugger();
984#endif
985}
986
987int
988mm_md_physacc(paddr_t pa, vm_prot_t prot)
989{
990	paddr_t memend;
991
992	/*
993	 * news68k has one contiguous memory segment.
994	 */
995	memend = lowram + ctob(physmem);
996
997	if (lowram <= pa && pa < memend)
998		return 0;
999
1000	return EFAULT;
1001}
1002
1003int
1004mm_md_kernacc(void *ptr, vm_prot_t prot, bool *handled)
1005{
1006
1007	*handled = false;
1008	return ISIIOVA(ptr) ? EFAULT : 0;
1009}
1010
1011#ifdef MODULAR
1012/*
1013 * Push any modules loaded by the bootloader etc.
1014 */
1015void
1016module_init_md(void)
1017{
1018}
1019#endif
1020