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