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