xref: /netbsd-src/sys/arch/news68k/news68k/machdep.c (revision f36002f244a49908fef9cba8789032bdbf48d572)
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) */
107 char	machine[] = MACHINE;	/* from <machine/param.h> */
108 
109 /* Our exported CPU info; we can have only one. */
110 struct cpu_info cpu_info_store;
111 
112 struct vm_map *phys_map = NULL;
113 
114 int	maxmem;			/* max memory per process */
115 
116 extern paddr_t avail_start, avail_end;
117 extern int end, *esym;
118 extern u_int lowram;
119 extern u_int ctrl_led_phys;
120 
121 /* prototypes for local functions */
122 static void identifycpu(void);
123 static void initcpu(void);
124 static int cpu_dumpsize(void);
125 static int cpu_dump(int (*)(dev_t, daddr_t, void *, size_t), daddr_t *);
126 static void cpu_init_kcore_hdr(void);
127 
128 #ifdef news1700
129 static void news1700_init(void);
130 static void parityenable(void);
131 static void parityerror(void);
132 #endif
133 #ifdef news1200
134 static void news1200_init(void);
135 #endif
136 
137 /* functions called from locore.s */
138 void dumpsys(void);
139 void news68k_init(void);
140 void straytrap(int, u_short);
141 
142 /*
143  * Machine-dependent crash dump header info.
144  */
145 cpu_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  */
152 int	cpuspeed = 25;		/* relative CPU speed; XXX skewed on 68040 */
153 int	delay_divisor = 82;	/* delay constant */
154 
155 /*
156  * Early initialization, before main() is called.
157  */
158 void
news68k_init(void)159 news68k_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  */
201 void
cpu_startup(void)202 cpu_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 
249 int news_machine_id;
250 
251 static void
identifycpu(void)252 identifycpu(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  */
264 SYSCTL_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 
280 int	waittime = -1;
281 
282 void
cpu_reboot(int howto,char * bootstr)283 cpu_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  */
348 static void
cpu_init_kcore_hdr(void)349 cpu_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 
413 static int
cpu_dumpsize(void)414 cpu_dumpsize(void)
415 {
416 
417 	return btodb(MDHDRSIZE);
418 }
419 
420 /*
421  * Called by dumpsys() to dump the machine-dependent header.
422  */
423 static int
cpu_dump(int (* dump)(dev_t,daddr_t,void *,size_t),daddr_t * blknop)424 cpu_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  */
448 uint32_t dumpmag = 0x8fca0101;	/* magic number */
449 int	dumpsize = 0;		/* pages */
450 long	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  */
459 void
cpu_dumpconf(void)460 cpu_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  */
491 void
dumpsys(void)492 dumpsys(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 
581 static void
initcpu(void)582 initcpu(void)
583 {
584 }
585 
586 void
straytrap(int pc,u_short evec)587 straytrap(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 
596 int	*nofault;
597 
598 int
badaddr(void * addr,int nbytes)599 badaddr(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 
634 int
badbaddr(void * addr)635 badbaddr(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  */
663 int
cpu_exec_aout_makecmds(struct lwp * l,struct exec_package * epp)664 cpu_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 
699 static volatile uint8_t *dip_switch, *int_status;
700 
701 const uint8_t *idrom_addr;
702 volatile uint8_t *ctrl_ast, *ctrl_int2;
703 volatile uint8_t *ctrl_led;
704 uint32_t sccport0a, lance_mem_phys;
705 
706 #ifdef news1700
707 static volatile u_char *ctrl_parity, *ctrl_parity_clr, *parity_vector;
708 
709 struct news68k_model {
710 	const int id;
711 	const char *name;
712 };
713 
714 static 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 
759 static void
news1700_init(void)760 news1700_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 
810 static void
parityenable(void)811 parityenable(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 
830 static int innmihand;	/* simple mutex */
831 
832 static void
parityerror(void)833 parityerror(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
852 static void
news1200_init(void)853 news1200_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 
888 void intrhand_lev3(void);
889 void intrhand_lev4(void);
890 
891 void
intrhand_lev3(void)892 intrhand_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 
903 extern int leintr(int);
904 extern int si_intr(int);
905 
906 void
intrhand_lev4(void)907 intrhand_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 
951 extern struct consdev consdev_rom, consdev_zs;
952 
953 int tty00_is_console = 0;
954 
955 void
consinit(void)956 consinit(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 
987 int
mm_md_physacc(paddr_t pa,vm_prot_t prot)988 mm_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 
1003 int
mm_md_kernacc(void * ptr,vm_prot_t prot,bool * handled)1004 mm_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  */
1015 void
module_init_md(void)1016 module_init_md(void)
1017 {
1018 }
1019 #endif
1020