1/*	$NetBSD: machdep.c,v 1.115 2024/03/05 14:15:33 thorpej Exp $	*/
2
3/*
4 * Copyright (c) 1988 University of Utah.
5 * Copyright (c) 1982, 1986, 1990, 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * the Systems Programming Group of the University of Utah Computer
10 * Science Department.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in the
19 *    documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * from: Utah $Hdr: machdep.c 1.74 92/12/20$
37 *
38 *	@(#)machdep.c	8.10 (Berkeley) 4/20/94
39 */
40
41#include <sys/cdefs.h>
42__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.115 2024/03/05 14:15:33 thorpej Exp $");
43
44#include "opt_ddb.h"
45#include "opt_compat_netbsd.h"
46#include "opt_modular.h"
47#include "opt_newsconf.h"
48
49#include <sys/param.h>
50#include <sys/systm.h>
51#include <sys/buf.h>
52#include <sys/conf.h>
53#include <sys/kernel.h>
54#include <sys/device.h>
55#include <sys/mbuf.h>
56#include <sys/mount.h>
57#include <sys/msgbuf.h>
58#include <sys/proc.h>
59#include <sys/reboot.h>
60#include <sys/tty.h>
61#include <sys/exec.h>
62#include <sys/exec_aout.h>		/* for MID_* */
63#include <sys/core.h>
64#include <sys/kcore.h>
65#include <sys/ksyms.h>
66#include <sys/module.h>
67#include <sys/cpu.h>
68
69#ifdef DDB
70#include <machine/db_machdep.h>
71#include <ddb/db_sym.h>
72#include <ddb/db_extern.h>
73#endif
74#ifdef __ELF__
75#include <sys/exec_elf.h>
76#endif
77
78#include <machine/autoconf.h>
79#include <machine/cpu.h>
80#include <machine/reg.h>
81#include <machine/pcb.h>
82#include <machine/pte.h>
83#include <machine/intr.h>
84
85#include <machine/kcore.h>	/* XXX should be pulled in by sys/kcore.h */
86
87#include <dev/cons.h>
88#include <dev/mm.h>
89
90#define MAXMEM	64*1024		/* XXX - from cmap.h */
91#include <uvm/uvm_extern.h>
92
93#include <sys/sysctl.h>
94
95#include <news68k/news68k/machid.h>
96#include <news68k/news68k/isr.h>
97
98#include "le.h"
99#include "kb.h"
100#include "ms.h"
101#include "si.h"
102#include "ksyms.h"
103#include "romcons.h"
104/* XXX etc. etc. */
105
106/* the following is used externally (sysctl_hw) */
107char	machine[] = MACHINE;	/* from <machine/param.h> */
108
109/* Our exported CPU info; we can have only one. */
110struct cpu_info cpu_info_store;
111
112struct vm_map *phys_map = NULL;
113
114int	maxmem;			/* max memory per process */
115
116extern paddr_t avail_start, avail_end;
117extern int end, *esym;
118extern u_int lowram;
119extern u_int ctrl_led_phys;
120
121/* prototypes for local functions */
122static void identifycpu(void);
123static void initcpu(void);
124static int cpu_dumpsize(void);
125static int cpu_dump(int (*)(dev_t, daddr_t, void *, size_t), daddr_t *);
126static void cpu_init_kcore_hdr(void);
127
128#ifdef news1700
129static void news1700_init(void);
130static void parityenable(void);
131static void parityerror(void);
132#endif
133#ifdef news1200
134static void news1200_init(void);
135#endif
136
137/* functions called from locore.s */
138void dumpsys(void);
139void news68k_init(void);
140void straytrap(int, u_short);
141
142/*
143 * Machine-dependent crash dump header info.
144 */
145cpu_kcore_hdr_t cpu_kcore_hdr;
146
147/*
148 * Note that the value of delay_divisor is roughly
149 * 2048 / cpuspeed (where cpuspeed is in MHz) on 68020
150 * and 68030 systems.
151 */
152int	cpuspeed = 25;		/* relative CPU speed; XXX skewed on 68040 */
153int	delay_divisor = 82;	/* delay constant */
154
155/*
156 * Early initialization, before main() is called.
157 */
158void
159news68k_init(void)
160{
161	int i;
162
163	/*
164	 * Tell the VM system about available physical memory.  The
165	 * news68k only has one segment.
166	 */
167	uvm_page_physload(atop(avail_start), atop(avail_end),
168	    atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT);
169
170	/* Initialize system variables. */
171	switch (systype) {
172#ifdef news1700
173	case NEWS1700:
174		news1700_init();
175		break;
176#endif
177#ifdef news1200
178	case NEWS1200:
179		news1200_init();
180		break;
181#endif
182	default:
183		panic("impossible system type");
184	}
185
186	/*
187	 * Initialize error message buffer (at end of core).
188	 * avail_end was pre-decremented in pmap_bootstrap to compensate.
189	 */
190	for (i = 0; i < btoc(MSGBUFSIZE); i++)
191		pmap_kenter_pa((vaddr_t)msgbufaddr + i * PAGE_SIZE,
192		    avail_end + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, 0);
193	pmap_update(pmap_kernel());
194	initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE));
195}
196
197/*
198 * cpu_startup: allocate memory for variable-sized tables,
199 * initialize CPU, and do autoconfiguration.
200 */
201void
202cpu_startup(void)
203{
204	vaddr_t minaddr, maxaddr;
205	char pbuf[9];
206#ifdef DEBUG
207	extern int pmapdebug;
208	int opmapdebug = pmapdebug;
209
210	pmapdebug = 0;
211#endif
212
213	if (fputype != FPU_NONE)
214		m68k_make_fpu_idle_frame();
215
216	/*
217	 * Initialize the kernel crash dump header.
218	 */
219	cpu_init_kcore_hdr();
220
221	/*
222	 * Good {morning,afternoon,evening,night}.
223	 */
224	printf("%s%s", copyright, version);
225	identifycpu();
226	format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
227	printf("total memory = %s\n", pbuf);
228
229	minaddr = 0;
230
231	/*
232	 * Allocate a submap for physio
233	 */
234	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
235	    VM_PHYS_SIZE, 0, false, NULL);
236
237#ifdef DEBUG
238	pmapdebug = opmapdebug;
239#endif
240	format_bytes(pbuf, sizeof(pbuf), ptoa(uvm_availmem(false)));
241	printf("avail memory = %s\n", pbuf);
242
243	/*
244	 * Set up CPU-specific registers, cache, etc.
245	 */
246	initcpu();
247}
248
249int news_machine_id;
250
251static void
252identifycpu(void)
253{
254
255	printf("SONY NET WORK STATION, Model %s, ", cpu_getmodel());
256	printf("Machine ID #%d\n", news_machine_id);
257
258	delay_divisor = (20480 / cpuspeed + 5) / 10; /* XXX */
259}
260
261/*
262 * machine dependent system variables.
263 */
264SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
265{
266
267	sysctl_createv(clog, 0, NULL, NULL,
268	    CTLFLAG_PERMANENT,
269	    CTLTYPE_NODE, "machdep", NULL,
270	    NULL, 0, NULL, 0,
271	    CTL_MACHDEP, CTL_EOL);
272
273	sysctl_createv(clog, 0, NULL, NULL,
274	    CTLFLAG_PERMANENT,
275	    CTLTYPE_STRUCT, "console_device", NULL,
276	    sysctl_consdev, 0, NULL, sizeof(dev_t),
277	    CTL_MACHDEP, CPU_CONSDEV, CTL_EOL);
278}
279
280int	waittime = -1;
281
282void
283cpu_reboot(int howto, char *bootstr)
284{
285	struct pcb *pcb = lwp_getpcb(curlwp);
286
287	/* take a snap shot before clobbering any registers */
288	if (pcb != NULL)
289		savectx(pcb);
290
291	/* If system is cold, just halt. */
292	if (cold) {
293		howto |= RB_HALT;
294		goto haltsys;
295	}
296
297	boothowto = howto;
298	if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
299		waittime = 0;
300		vfs_shutdown();
301	}
302
303	/* Disable interrupts. */
304	splhigh();
305
306	/* If rebooting and a dump is requested, do it. */
307	if (howto & RB_DUMP)
308		dumpsys();
309
310 haltsys:
311	/* Run any shutdown hooks. */
312	doshutdownhooks();
313
314	pmf_system_shutdown(boothowto);
315
316#if defined(PANICWAIT) && !defined(DDB)
317	if ((howto & RB_HALT) == 0 && panicstr) {
318		printf("hit any key to reboot...\n");
319		cnpollc(1);
320		(void)cngetc();
321		cnpollc(0);
322		printf("\n");
323	}
324#endif
325
326	/* Finally, halt/reboot the system. */
327	if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
328		DELAY(1000000);
329		doboot(RB_POWERDOWN);
330		/* NOTREACHED */
331	}
332
333	if (howto & RB_HALT) {
334		printf("System halted.\n\n");
335		doboot(RB_HALT);
336		/* NOTREACHED */
337	}
338
339	printf("rebooting...\n");
340	DELAY(1000000);
341	doboot(RB_AUTOBOOT);
342	/* NOTREACHED */
343}
344
345/*
346 * Initialize the kernel crash dump header.
347 */
348static void
349cpu_init_kcore_hdr(void)
350{
351	cpu_kcore_hdr_t *h = &cpu_kcore_hdr;
352	struct m68k_kcore_hdr *m = &h->un._m68k;
353
354	memset(&cpu_kcore_hdr, 0, sizeof(cpu_kcore_hdr));
355
356	/*
357	 * Initialize the `dispatcher' portion of the header.
358	 */
359	strcpy(h->name, machine);
360	h->page_size = PAGE_SIZE;
361	h->kernbase = KERNBASE;
362
363	/*
364	 * Fill in information about our MMU configuration.
365	 */
366	m->mmutype	= mmutype;
367	m->sg_v		= SG_V;
368	m->sg_frame	= SG_FRAME;
369	m->sg_ishift	= SG_ISHIFT;
370	m->sg_pmask	= SG_PMASK;
371	m->sg40_shift1	= SG4_SHIFT1;
372	m->sg40_mask2	= SG4_MASK2;
373	m->sg40_shift2	= SG4_SHIFT2;
374	m->sg40_mask3	= SG4_MASK3;
375	m->sg40_shift3	= SG4_SHIFT3;
376	m->sg40_addr1	= SG4_ADDR1;
377	m->sg40_addr2	= SG4_ADDR2;
378	m->pg_v		= PG_V;
379	m->pg_frame	= PG_FRAME;
380
381	/*
382	 * Initialize pointer to kernel segment table.
383	 */
384	m->sysseg_pa = (uint32_t)(pmap_kernel()->pm_stpa);
385
386	/*
387	 * Initialize relocation value such that:
388	 *
389	 *	pa = (va - KERNBASE) + reloc
390	 */
391	m->reloc = lowram;
392
393	/*
394	 * Define the end of the relocatable range.
395	 */
396	m->relocend = (uint32_t)&end;
397
398	/*
399	 * news68k has one contiguous memory segment.
400	 */
401	m->ram_segs[0].start = lowram;
402	m->ram_segs[0].size  = ctob(physmem);
403}
404
405/*
406 * Compute the size of the machine-dependent crash dump header.
407 * Returns size in disk blocks.
408 */
409
410#define CHDRSIZE (ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)))
411#define MDHDRSIZE roundup(CHDRSIZE, dbtob(1))
412
413static int
414cpu_dumpsize(void)
415{
416
417	return btodb(MDHDRSIZE);
418}
419
420/*
421 * Called by dumpsys() to dump the machine-dependent header.
422 */
423static int
424cpu_dump(int (*dump)(dev_t, daddr_t, void *, size_t), daddr_t *blknop)
425{
426	int buf[MDHDRSIZE / sizeof(int)];
427	cpu_kcore_hdr_t *chdr;
428	kcore_seg_t *kseg;
429	int error;
430
431	kseg = (kcore_seg_t *)buf;
432	chdr = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(kcore_seg_t)) /
433	    sizeof(int)];
434
435	/* Create the segment header. */
436	CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
437	kseg->c_size = MDHDRSIZE - ALIGN(sizeof(kcore_seg_t));
438
439	memcpy(chdr, &cpu_kcore_hdr, sizeof(cpu_kcore_hdr_t));
440	error = (*dump)(dumpdev, *blknop, (void *)buf, sizeof(buf));
441	*blknop += btodb(sizeof(buf));
442	return error;
443}
444
445/*
446 * These variables are needed by /sbin/savecore
447 */
448uint32_t dumpmag = 0x8fca0101;	/* magic number */
449int	dumpsize = 0;		/* pages */
450long	dumplo = 0;		/* blocks */
451
452/*
453 * This is called by main to set dumplo and dumpsize.
454 * Dumps always skip the first PAGE_SIZE of disk space
455 * in case there might be a disk label stored there.
456 * If there is extra space, put dump at the end to
457 * reduce the chance that swapping trashes it.
458 */
459void
460cpu_dumpconf(void)
461{
462	int chdrsize;	/* size of dump header */
463	int nblks;	/* size of dump area */
464
465	if (dumpdev == NODEV)
466		return;
467	nblks = bdev_size(dumpdev);
468	chdrsize = cpu_dumpsize();
469
470	dumpsize = btoc(cpu_kcore_hdr.un._m68k.ram_segs[0].size);
471
472	/*
473	 * Check do see if we will fit.  Note we always skip the
474	 * first PAGE_SIZE in case there is a disk label there.
475	 */
476	if (nblks < (ctod(dumpsize) + chdrsize + ctod(1))) {
477		dumpsize = 0;
478		dumplo = -1;
479		return;
480	}
481
482	/*
483	 * Put dump at the end of the partition.
484	 */
485	dumplo = (nblks - 1) - ctod(dumpsize) - chdrsize;
486}
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