1 /* $NetBSD: machdep.c,v 1.110 2021/10/09 20:00:42 tsutsui 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.110 2021/10/09 20:00:42 tsutsui Exp $");
43
44 #include "opt_ddb.h"
45 #include "opt_compat_netbsd.h"
46 #include "opt_modular.h"
47
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/buf.h>
51 #include <sys/conf.h>
52 #include <sys/kernel.h>
53 #include <sys/device.h>
54 #include <sys/malloc.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 * If we've been adjusting the clock, the todr
303 * will be out of synch; adjust it now.
304 */
305 resettodr();
306 }
307
308 /* Disable interrupts. */
309 splhigh();
310
311 /* If rebooting and a dump is requested, do it. */
312 if (howto & RB_DUMP)
313 dumpsys();
314
315 haltsys:
316 /* Run any shutdown hooks. */
317 doshutdownhooks();
318
319 pmf_system_shutdown(boothowto);
320
321 #if defined(PANICWAIT) && !defined(DDB)
322 if ((howto & RB_HALT) == 0 && panicstr) {
323 printf("hit any key to reboot...\n");
324 cnpollc(1);
325 (void)cngetc();
326 cnpollc(0);
327 printf("\n");
328 }
329 #endif
330
331 /* Finally, halt/reboot the system. */
332 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
333 DELAY(1000000);
334 doboot(RB_POWERDOWN);
335 /* NOTREACHED */
336 }
337
338 if (howto & RB_HALT) {
339 printf("System halted.\n\n");
340 doboot(RB_HALT);
341 /* NOTREACHED */
342 }
343
344 printf("rebooting...\n");
345 DELAY(1000000);
346 doboot(RB_AUTOBOOT);
347 /* NOTREACHED */
348 }
349
350 /*
351 * Initialize the kernel crash dump header.
352 */
353 static void
cpu_init_kcore_hdr(void)354 cpu_init_kcore_hdr(void)
355 {
356 cpu_kcore_hdr_t *h = &cpu_kcore_hdr;
357 struct m68k_kcore_hdr *m = &h->un._m68k;
358
359 memset(&cpu_kcore_hdr, 0, sizeof(cpu_kcore_hdr));
360
361 /*
362 * Initialize the `dispatcher' portion of the header.
363 */
364 strcpy(h->name, machine);
365 h->page_size = PAGE_SIZE;
366 h->kernbase = KERNBASE;
367
368 /*
369 * Fill in information about our MMU configuration.
370 */
371 m->mmutype = mmutype;
372 m->sg_v = SG_V;
373 m->sg_frame = SG_FRAME;
374 m->sg_ishift = SG_ISHIFT;
375 m->sg_pmask = SG_PMASK;
376 m->sg40_shift1 = SG4_SHIFT1;
377 m->sg40_mask2 = SG4_MASK2;
378 m->sg40_shift2 = SG4_SHIFT2;
379 m->sg40_mask3 = SG4_MASK3;
380 m->sg40_shift3 = SG4_SHIFT3;
381 m->sg40_addr1 = SG4_ADDR1;
382 m->sg40_addr2 = SG4_ADDR2;
383 m->pg_v = PG_V;
384 m->pg_frame = PG_FRAME;
385
386 /*
387 * Initialize pointer to kernel segment table.
388 */
389 m->sysseg_pa = (uint32_t)(pmap_kernel()->pm_stpa);
390
391 /*
392 * Initialize relocation value such that:
393 *
394 * pa = (va - KERNBASE) + reloc
395 */
396 m->reloc = lowram;
397
398 /*
399 * Define the end of the relocatable range.
400 */
401 m->relocend = (uint32_t)&end;
402
403 /*
404 * news68k has one contiguous memory segment.
405 */
406 m->ram_segs[0].start = lowram;
407 m->ram_segs[0].size = ctob(physmem);
408 }
409
410 /*
411 * Compute the size of the machine-dependent crash dump header.
412 * Returns size in disk blocks.
413 */
414
415 #define CHDRSIZE (ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)))
416 #define MDHDRSIZE roundup(CHDRSIZE, dbtob(1))
417
418 static int
cpu_dumpsize(void)419 cpu_dumpsize(void)
420 {
421
422 return btodb(MDHDRSIZE);
423 }
424
425 /*
426 * Called by dumpsys() to dump the machine-dependent header.
427 */
428 static int
cpu_dump(int (* dump)(dev_t,daddr_t,void *,size_t),daddr_t * blknop)429 cpu_dump(int (*dump)(dev_t, daddr_t, void *, size_t), daddr_t *blknop)
430 {
431 int buf[MDHDRSIZE / sizeof(int)];
432 cpu_kcore_hdr_t *chdr;
433 kcore_seg_t *kseg;
434 int error;
435
436 kseg = (kcore_seg_t *)buf;
437 chdr = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(kcore_seg_t)) /
438 sizeof(int)];
439
440 /* Create the segment header. */
441 CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
442 kseg->c_size = MDHDRSIZE - ALIGN(sizeof(kcore_seg_t));
443
444 memcpy(chdr, &cpu_kcore_hdr, sizeof(cpu_kcore_hdr_t));
445 error = (*dump)(dumpdev, *blknop, (void *)buf, sizeof(buf));
446 *blknop += btodb(sizeof(buf));
447 return error;
448 }
449
450 /*
451 * These variables are needed by /sbin/savecore
452 */
453 uint32_t dumpmag = 0x8fca0101; /* magic number */
454 int dumpsize = 0; /* pages */
455 long dumplo = 0; /* blocks */
456
457 /*
458 * This is called by main to set dumplo and dumpsize.
459 * Dumps always skip the first PAGE_SIZE of disk space
460 * in case there might be a disk label stored there.
461 * If there is extra space, put dump at the end to
462 * reduce the chance that swapping trashes it.
463 */
464 void
cpu_dumpconf(void)465 cpu_dumpconf(void)
466 {
467 int chdrsize; /* size of dump header */
468 int nblks; /* size of dump area */
469
470 if (dumpdev == NODEV)
471 return;
472 nblks = bdev_size(dumpdev);
473 chdrsize = cpu_dumpsize();
474
475 dumpsize = btoc(cpu_kcore_hdr.un._m68k.ram_segs[0].size);
476
477 /*
478 * Check do see if we will fit. Note we always skip the
479 * first PAGE_SIZE in case there is a disk label there.
480 */
481 if (nblks < (ctod(dumpsize) + chdrsize + ctod(1))) {
482 dumpsize = 0;
483 dumplo = -1;
484 return;
485 }
486
487 /*
488 * Put dump at the end of the partition.
489 */
490 dumplo = (nblks - 1) - ctod(dumpsize) - chdrsize;
491 }
492
493 /*
494 * Dump physical memory onto the dump device. Called by cpu_reboot().
495 */
496 void
dumpsys(void)497 dumpsys(void)
498 {
499 const struct bdevsw *bdev;
500 daddr_t blkno; /* current block to write */
501 /* dump routine */
502 int (*dump)(dev_t, daddr_t, void *, size_t);
503 int pg; /* page being dumped */
504 paddr_t maddr; /* PA being dumped */
505 int error; /* error code from (*dump)() */
506
507 /* XXX initialized here because of gcc lossage */
508 maddr = lowram;
509 pg = 0;
510
511 /* Make sure dump device is valid. */
512 if (dumpdev == NODEV)
513 return;
514 bdev = bdevsw_lookup(dumpdev);
515 if (bdev == NULL)
516 return;
517 if (dumpsize == 0) {
518 cpu_dumpconf();
519 if (dumpsize == 0)
520 return;
521 }
522 if (dumplo <= 0) {
523 printf("\ndump to dev %u,%u not possible\n",
524 major(dumpdev), minor(dumpdev));
525 return;
526 }
527 dump = bdev->d_dump;
528 blkno = dumplo;
529
530 printf("\ndumping to dev %u,%u offset %ld\n",
531 major(dumpdev), minor(dumpdev), dumplo);
532
533 printf("dump ");
534
535 /* Write the dump header. */
536 error = cpu_dump(dump, &blkno);
537 if (error)
538 goto bad;
539
540 for (pg = 0; pg < dumpsize; pg++) {
541 #define NPGMB (1024*1024/PAGE_SIZE)
542 /* print out how many MBs we have dumped */
543 if (pg && (pg % NPGMB) == 0)
544 printf_nolog("%d ", pg / NPGMB);
545 #undef NPGMB
546 pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr,
547 VM_PROT_READ, VM_PROT_READ|PMAP_WIRED);
548
549 pmap_update(pmap_kernel());
550 error = (*dump)(dumpdev, blkno, vmmap, PAGE_SIZE);
551 bad:
552 switch (error) {
553 case 0:
554 maddr += PAGE_SIZE;
555 blkno += btodb(PAGE_SIZE);
556 break;
557
558 case ENXIO:
559 printf("device bad\n");
560 return;
561
562 case EFAULT:
563 printf("device not ready\n");
564 return;
565
566 case EINVAL:
567 printf("area improper\n");
568 return;
569
570 case EIO:
571 printf("i/o error\n");
572 return;
573
574 case EINTR:
575 printf("aborted from console\n");
576 return;
577
578 default:
579 printf("error %d\n", error);
580 return;
581 }
582 }
583 printf("succeeded\n");
584 }
585
586 static void
initcpu(void)587 initcpu(void)
588 {
589 }
590
591 void
straytrap(int pc,u_short evec)592 straytrap(int pc, u_short evec)
593 {
594
595 printf("unexpected trap (vector offset %x) from %x\n",
596 evec & 0xFFF, pc);
597 }
598
599 /* XXX should change the interface, and make one badaddr() function */
600
601 int *nofault;
602
603 int
badaddr(void * addr,int nbytes)604 badaddr(void *addr, int nbytes)
605 {
606 int i;
607 label_t faultbuf;
608
609 #ifdef lint
610 i = *addr; if (i) return 0;
611 #endif
612
613 nofault = (int *) &faultbuf;
614 if (setjmp((label_t *)nofault)) {
615 nofault = (int *) 0;
616 return 1;
617 }
618 switch (nbytes) {
619 case 1:
620 i = *(volatile char *)addr;
621 break;
622
623 case 2:
624 i = *(volatile short *)addr;
625 break;
626
627 case 4:
628 i = *(volatile int *)addr;
629 break;
630
631 default:
632 panic("badaddr: bad request");
633 }
634 __USE(i);
635 nofault = (int *) 0;
636 return 0;
637 }
638
639 int
badbaddr(void * addr)640 badbaddr(void *addr)
641 {
642 int i;
643 label_t faultbuf;
644
645 nofault = (int *) &faultbuf;
646 if (setjmp((label_t *)nofault)) {
647 nofault = (int *) 0;
648 return 1;
649 }
650 i = *(volatile char *)addr;
651 __USE(i);
652 nofault = (int *) 0;
653 return 0;
654 }
655
656 /*
657 * cpu_exec_aout_makecmds():
658 * CPU-dependent a.out format hook for execve().
659 *
660 * Determine of the given exec package refers to something which we
661 * understand and, if so, set up the vmcmds for it.
662 *
663 * XXX what are the special cases for the hp300?
664 * XXX why is this COMPAT_NOMID? was something generating
665 * hp300 binaries with an a_mid of 0? i thought that was only
666 * done on little-endian machines... -- cgd
667 */
668 int
cpu_exec_aout_makecmds(struct lwp * l,struct exec_package * epp)669 cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp)
670 {
671 #if defined(COMPAT_NOMID) || defined(COMPAT_44)
672 u_long midmag, magic;
673 u_short mid;
674 int error;
675 struct exec *execp = epp->ep_hdr;
676
677 midmag = ntohl(execp->a_midmag);
678 mid = (midmag >> 16) & 0xffff;
679 magic = midmag & 0xffff;
680
681 midmag = mid << 16 | magic;
682
683 switch (midmag) {
684 #ifdef COMPAT_NOMID
685 case (MID_ZERO << 16) | ZMAGIC:
686 error = exec_aout_prep_oldzmagic(l, epp);
687 return(error);
688 #endif
689 #ifdef COMPAT_44
690 case (MID_HP300 << 16) | ZMAGIC:
691 error = exec_aout_prep_oldzmagic(l, epp);
692 return error;
693 #endif
694 }
695 #endif /* !(defined(COMPAT_NOMID) || defined(COMPAT_44)) */
696
697 return ENOEXEC;
698 }
699
700 /*
701 * System dependent initilization
702 */
703
704 static volatile uint8_t *dip_switch, *int_status;
705
706 const uint8_t *idrom_addr;
707 volatile uint8_t *ctrl_ast, *ctrl_int2;
708 volatile uint8_t *ctrl_led;
709 uint32_t sccport0a, lance_mem_phys;
710
711 #ifdef news1700
712 static volatile u_char *ctrl_parity, *ctrl_parity_clr, *parity_vector;
713
714 struct news68k_model {
715 const int id;
716 const char *name;
717 };
718
719 static const struct news68k_model news68k_models[] = {
720 { ICK001, "ICK001" }, /* 1 */
721 { ICK00X, "ICK00X" }, /* 2 */
722 { NWS799, "NWS-799" }, /* 3 */
723 { NWS800, "NWS-800" }, /* 4 */
724 { NWS801, "NWS-801" }, /* 5 */
725 { NWS802, "NWS-802" }, /* 6 */
726 { NWS711, "NWS-711" }, /* 7 */
727 { NWS721, "NWS-721" }, /* 8 */
728 { NWS1850, "NWS-1850" }, /* 9 */
729 { NWS810, "NWS-810" }, /* 10 */
730 { NWS811, "NWS-811" }, /* 11 */
731 { NWS1830, "NWS-1830" }, /* 12 */
732 { NWS1750, "NWS-1750" }, /* 13 */
733 { NWS1720, "NWS-1720" }, /* 14 */
734 { NWS1930, "NWS-1930" }, /* 15 */
735 { NWS1960, "NWS-1960" }, /* 16 */
736 { NWS712, "NWS-712" }, /* 17 */
737 { NWS1860, "NWS-1860" }, /* 18 */
738 { PWS1630, "PWS-1630" }, /* 19 */
739 { NWS820, "NWS-820" }, /* 20 */
740 { NWS821, "NWS-821" }, /* 21 */
741 { NWS1760, "NWS-1760" }, /* 22 */
742 { NWS1710, "NWS-1710" }, /* 23 */
743 { NWS830, "NWS-830" }, /* 30 */
744 { NWS831, "NWS-831" }, /* 31 */
745 { NWS841, "NWS-841" }, /* 41 */
746 { PWS1570, "PWS-1570" }, /* 52 */
747 { PWS1590, "PWS-1590" }, /* 54 */
748 { NWS1520, "NWS-1520" }, /* 56 */
749 { PWS1550, "PWS-1550" }, /* 73 */
750 { PWS1520, "PWS-1520" }, /* 74 */
751 { PWS1560, "PWS-1560" }, /* 75 */
752 { NWS1530, "NWS-1530" }, /* 76 */
753 { NWS1580, "NWS-1580" }, /* 77 */
754 { NWS1510, "NWS-1510" }, /* 78 */
755 { NWS1410, "NWS-1410" }, /* 81 */
756 { NWS1450, "NWS-1450" }, /* 85 */
757 { NWS1460, "NWS-1460" }, /* 86 */
758 { NWS891, "NWS-891" }, /* 91 */
759 { NWS911, "NWS-911" }, /* 111 */
760 { NWS921, "NWS-921" }, /* 121 */
761 { 0, NULL }
762 };
763
764 static void
news1700_init(void)765 news1700_init(void)
766 {
767 struct oidrom idrom;
768 const char *t;
769 const uint8_t *p;
770 uint8_t *q;
771 u_int i;
772
773 dip_switch = (uint8_t *)(0xe1c00100);
774 int_status = (uint8_t *)(0xe1c00200);
775
776 idrom_addr = (uint8_t *)(0xe1c00000);
777 ctrl_ast = (uint8_t *)(0xe1280000);
778 ctrl_int2 = (uint8_t *)(0xe1180000);
779 ctrl_led = (uint8_t *)(ctrl_led_phys);
780
781 sccport0a = (0xe0d40002);
782 lance_mem_phys = 0xe0e00000;
783
784 p = idrom_addr;
785 q = (uint8_t *)&idrom;
786
787 for (i = 0; i < sizeof(idrom); i++, p += 2)
788 *q++ = ((*p & 0x0f) << 4) | (*(p + 1) & 0x0f);
789
790 t = NULL;
791 for (i = 0; news68k_models[i].name != NULL; i++) {
792 if (news68k_models[i].id == idrom.id_model) {
793 t = news68k_models[i].name;
794 }
795 }
796 if (t == NULL)
797 panic("unexpected system model.");
798
799 cpu_setmodel("%s", t);
800 news_machine_id = (idrom.id_serial[0] << 8) + idrom.id_serial[1];
801
802 ctrl_parity = (uint8_t *)(0xe1080000);
803 ctrl_parity_clr = (uint8_t *)(0xe1a00000);
804 parity_vector = (uint8_t *)(0xe1c00200);
805
806 parityenable();
807
808 cpuspeed = 25;
809 }
810
811 /*
812 * parity error handling (vectored NMI?)
813 */
814
815 static void
parityenable(void)816 parityenable(void)
817 {
818
819 #define PARITY_VECT 0xc0
820 #define PARITY_PRI 7
821
822 *parity_vector = PARITY_VECT;
823
824 isrlink_vectored((int (*)(void *))parityerror, NULL,
825 PARITY_PRI, PARITY_VECT);
826
827 *ctrl_parity_clr = 1;
828 *ctrl_parity = 1;
829
830 #ifdef DEBUG
831 printf("enable parity check\n");
832 #endif
833 }
834
835 static int innmihand; /* simple mutex */
836
837 static void
parityerror(void)838 parityerror(void)
839 {
840
841 /* Prevent unwanted recursion. */
842 if (innmihand)
843 return;
844 innmihand = 1;
845
846 #if 0 /* XXX need to implement XXX */
847 panic("parity error");
848 #else
849 printf("parity error detected.\n");
850 *ctrl_parity_clr = 1;
851 #endif
852 innmihand = 0;
853 }
854 #endif /* news1700 */
855
856 #ifdef news1200
857 static void
news1200_init(void)858 news1200_init(void)
859 {
860 struct idrom idrom;
861 const uint8_t *p;
862 uint8_t *q;
863 int i;
864
865 dip_switch = (uint8_t *)0xe1680000;
866 int_status = (uint8_t *)0xe1200000;
867
868 idrom_addr = (uint8_t *)0xe1400000;
869 ctrl_ast = (uint8_t *)0xe1100000;
870 ctrl_int2 = (uint8_t *)0xe10c0000;
871 ctrl_led = (uint8_t *)ctrl_led_phys;
872
873 sccport0a = 0xe1780002;
874 lance_mem_phys = 0xe1a00000;
875
876 p = idrom_addr;
877 q = (uint8_t *)&idrom;
878 for (i = 0; i < sizeof(idrom); i++, p += 2)
879 *q++ = ((*p & 0x0f) << 4) | (*(p + 1) & 0x0f);
880
881 cpu_setmodel("%s", idrom.id_model);
882 news_machine_id = idrom.id_serial;
883
884 cpuspeed = 25;
885 }
886 #endif /* news1200 */
887
888 /*
889 * interrupt handlers
890 * XXX should do better handling XXX
891 */
892
893 void intrhand_lev3(void);
894 void intrhand_lev4(void);
895
896 void
intrhand_lev3(void)897 intrhand_lev3(void)
898 {
899 int stat;
900
901 stat = *int_status;
902 intrcnt[3]++;
903 curcpu()->ci_data.cpu_nintr++;
904 #if 1
905 printf("level 3 interrupt: INT_STATUS = 0x%02x\n", stat);
906 #endif
907 }
908
909 extern int leintr(int);
910 extern int si_intr(int);
911
912 void
intrhand_lev4(void)913 intrhand_lev4(void)
914 {
915 int stat;
916
917 #define INTST_LANCE 0x04
918 #define INTST_SCSI 0x80
919
920 stat = *int_status;
921 intrcnt[4]++;
922 curcpu()->ci_data.cpu_nintr++;
923
924 #if NSI > 0
925 if (stat & INTST_SCSI) {
926 si_intr(0);
927 }
928 #endif
929 #if NLE > 0
930 if (stat & INTST_LANCE) {
931 leintr(0);
932 }
933 #endif
934 #if 0
935 printf("level 4 interrupt\n");
936 #endif
937 }
938
939 /*
940 * consinit() routines - from newsmips/cpu_cons.c
941 */
942
943 /*
944 * Console initialization: called early on from main,
945 * before vm init or startup. Do enough configuration
946 * to choose and initialize a console.
947 * XXX need something better here.
948 */
949 #define SCC_CONSOLE 0
950 #define SW_CONSOLE 0x07
951 #define SW_NWB512 0x04
952 #define SW_NWB225 0x01
953 #define SW_FBPOP 0x02
954 #define SW_FBPOP1 0x06
955 #define SW_FBPOP2 0x03
956 #define SW_AUTOSEL 0x07
957
958 extern struct consdev consdev_rom, consdev_zs;
959
960 int tty00_is_console = 0;
961
962 void
consinit(void)963 consinit(void)
964 {
965 uint8_t dipsw;
966
967 dipsw = *dip_switch;
968
969 dipsw = ~dipsw;
970
971 switch (dipsw & SW_CONSOLE) {
972 default: /* XXX no real fb support yet */
973 #if NROMCONS > 0
974 cn_tab = &consdev_rom;
975 (*cn_tab->cn_init)(cn_tab);
976 break;
977 #endif
978 case 0:
979 tty00_is_console = 1;
980 cn_tab = &consdev_zs;
981 (*cn_tab->cn_init)(cn_tab);
982 break;
983 }
984 #if NKSYMS || defined(DDB) || defined(MODULAR)
985 ksyms_addsyms_elf((int)esym - (int)&end - sizeof(Elf32_Ehdr),
986 (void *)&end, esym);
987 #endif
988 #ifdef DDB
989 if (boothowto & RB_KDB)
990 Debugger();
991 #endif
992 }
993
994 int
mm_md_physacc(paddr_t pa,vm_prot_t prot)995 mm_md_physacc(paddr_t pa, vm_prot_t prot)
996 {
997 paddr_t memend;
998
999 /*
1000 * news68k has one contiguous memory segment.
1001 */
1002 memend = lowram + ctob(physmem);
1003
1004 if (lowram <= pa && pa < memend)
1005 return 0;
1006
1007 return EFAULT;
1008 }
1009
1010 int
mm_md_kernacc(void * ptr,vm_prot_t prot,bool * handled)1011 mm_md_kernacc(void *ptr, vm_prot_t prot, bool *handled)
1012 {
1013
1014 *handled = false;
1015 return ISIIOVA(ptr) ? EFAULT : 0;
1016 }
1017
1018 #ifdef MODULAR
1019 /*
1020 * Push any modules loaded by the bootloader etc.
1021 */
1022 void
module_init_md(void)1023 module_init_md(void)
1024 {
1025 }
1026 #endif
1027