1 /* $NetBSD: machdep.c,v 1.88 2011/01/17 14:36:33 tsutsui Exp $ */ 2 3 /* 4 * Copyright (c) 1982, 1986, 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * the Systems Programming Group of the University of Utah Computer 9 * Science Department. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * from: Utah $Hdr: machdep.c 1.74 92/12/20$ 36 * 37 * @(#)machdep.c 8.10 (Berkeley) 4/20/94 38 */ 39 /* 40 * Copyright (c) 1988 University of Utah. 41 * 42 * This code is derived from software contributed to Berkeley by 43 * the Systems Programming Group of the University of Utah Computer 44 * Science Department. 45 * 46 * Redistribution and use in source and binary forms, with or without 47 * modification, are permitted provided that the following conditions 48 * are met: 49 * 1. Redistributions of source code must retain the above copyright 50 * notice, this list of conditions and the following disclaimer. 51 * 2. Redistributions in binary form must reproduce the above copyright 52 * notice, this list of conditions and the following disclaimer in the 53 * documentation and/or other materials provided with the distribution. 54 * 3. All advertising materials mentioning features or use of this software 55 * must display the following acknowledgement: 56 * This product includes software developed by the University of 57 * California, Berkeley and its contributors. 58 * 4. Neither the name of the University nor the names of its contributors 59 * may be used to endorse or promote products derived from this software 60 * without specific prior written permission. 61 * 62 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 63 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 64 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 65 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 66 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 67 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 68 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 69 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 70 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 71 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 72 * SUCH DAMAGE. 73 * 74 * from: Utah $Hdr: machdep.c 1.74 92/12/20$ 75 * 76 * @(#)machdep.c 8.10 (Berkeley) 4/20/94 77 */ 78 79 #include <sys/cdefs.h> 80 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.88 2011/01/17 14:36:33 tsutsui Exp $"); 81 82 #include "opt_ddb.h" 83 #include "opt_compat_netbsd.h" 84 #include "opt_modular.h" 85 86 #include <sys/param.h> 87 #include <sys/systm.h> 88 #include <sys/buf.h> 89 #include <sys/conf.h> 90 #include <sys/kernel.h> 91 #include <sys/device.h> 92 #include <sys/malloc.h> 93 #include <sys/mbuf.h> 94 #include <sys/mount.h> 95 #include <sys/msgbuf.h> 96 #include <sys/proc.h> 97 #include <sys/reboot.h> 98 #include <sys/tty.h> 99 #include <sys/exec.h> 100 #include <sys/exec_aout.h> /* for MID_* */ 101 #include <sys/core.h> 102 #include <sys/kcore.h> 103 #include <sys/ksyms.h> 104 #include <sys/module.h> 105 106 #ifdef DDB 107 #include <machine/db_machdep.h> 108 #include <ddb/db_sym.h> 109 #include <ddb/db_extern.h> 110 #endif 111 #ifdef __ELF__ 112 #include <sys/exec_elf.h> 113 #endif 114 115 #include <machine/autoconf.h> 116 #include <machine/cpu.h> 117 #include <machine/reg.h> 118 #include <machine/pcb.h> 119 #include <machine/pte.h> 120 #include <machine/intr.h> 121 122 #include <machine/kcore.h> /* XXX should be pulled in by sys/kcore.h */ 123 124 #include <dev/cons.h> 125 126 #define MAXMEM 64*1024 /* XXX - from cmap.h */ 127 #include <uvm/uvm_extern.h> 128 129 #include <sys/sysctl.h> 130 131 #include <news68k/news68k/machid.h> 132 #include <news68k/news68k/isr.h> 133 134 #include "le.h" 135 #include "kb.h" 136 #include "ms.h" 137 #include "si.h" 138 #include "ksyms.h" 139 /* XXX etc. etc. */ 140 141 /* the following is used externally (sysctl_hw) */ 142 char machine[] = MACHINE; /* from <machine/param.h> */ 143 144 /* Our exported CPU info; we can have only one. */ 145 struct cpu_info cpu_info_store; 146 147 struct vm_map *phys_map = NULL; 148 149 int maxmem; /* max memory per process */ 150 int physmem = MAXMEM; /* max supported memory, changes to actual */ 151 /* 152 * safepri is a safe priority for sleep to set for a spin-wait 153 * during autoconfiguration or after a panic. 154 */ 155 int safepri = PSL_LOWIPL; 156 157 extern paddr_t avail_start, avail_end; 158 extern int end, *esym; 159 extern u_int lowram; 160 extern u_int ctrl_led_phys; 161 162 /* prototypes for local functions */ 163 static void identifycpu(void); 164 static void initcpu(void); 165 static int cpu_dumpsize(void); 166 static int cpu_dump(int (*)(dev_t, daddr_t, void *, size_t), daddr_t *); 167 static void cpu_init_kcore_hdr(void); 168 169 #ifdef news1700 170 static void news1700_init(void); 171 static void parityenable(void); 172 static void parityerror(void); 173 #endif 174 #ifdef news1200 175 static void news1200_init(void); 176 #endif 177 178 /* functions called from locore.s */ 179 void dumpsys(void); 180 void news68k_init(void); 181 void straytrap(int, u_short); 182 183 /* 184 * Machine-dependent crash dump header info. 185 */ 186 cpu_kcore_hdr_t cpu_kcore_hdr; 187 188 /* 189 * Note that the value of delay_divisor is roughly 190 * 2048 / cpuspeed (where cpuspeed is in MHz) on 68020 191 * and 68030 systems. 192 */ 193 int cpuspeed = 25; /* relative CPU speed; XXX skewed on 68040 */ 194 int delay_divisor = 82; /* delay constant */ 195 196 /* 197 * Early initialization, before main() is called. 198 */ 199 void 200 news68k_init(void) 201 { 202 int i; 203 204 /* 205 * Tell the VM system about available physical memory. The 206 * news68k only has one segment. 207 */ 208 uvm_page_physload(atop(avail_start), atop(avail_end), 209 atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT); 210 211 /* Initialize system variables. */ 212 switch (systype) { 213 #ifdef news1700 214 case NEWS1700: 215 news1700_init(); 216 break; 217 #endif 218 #ifdef news1200 219 case NEWS1200: 220 news1200_init(); 221 break; 222 #endif 223 default: 224 panic("impossible system type"); 225 } 226 227 isrinit(); 228 229 /* 230 * Initialize error message buffer (at end of core). 231 * avail_end was pre-decremented in pmap_bootstrap to compensate. 232 */ 233 for (i = 0; i < btoc(MSGBUFSIZE); i++) 234 pmap_kenter_pa((vaddr_t)msgbufaddr + i * PAGE_SIZE, 235 avail_end + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, 0) 236 pmap_update(pmap_kernel()); 237 initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE)); 238 } 239 240 /* 241 * cpu_startup: allocate memory for variable-sized tables, 242 * initialize CPU, and do autoconfiguration. 243 */ 244 void 245 cpu_startup(void) 246 { 247 vaddr_t minaddr, maxaddr; 248 char pbuf[9]; 249 #ifdef DEBUG 250 extern int pmapdebug; 251 int opmapdebug = pmapdebug; 252 253 pmapdebug = 0; 254 #endif 255 256 if (fputype != FPU_NONE) 257 m68k_make_fpu_idle_frame(); 258 259 /* 260 * Initialize the kernel crash dump header. 261 */ 262 cpu_init_kcore_hdr(); 263 264 /* 265 * Good {morning,afternoon,evening,night}. 266 */ 267 printf("%s%s", copyright, version); 268 identifycpu(); 269 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 270 printf("total memory = %s\n", pbuf); 271 272 minaddr = 0; 273 274 /* 275 * Allocate a submap for physio 276 */ 277 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 278 VM_PHYS_SIZE, 0, false, NULL); 279 280 #ifdef DEBUG 281 pmapdebug = opmapdebug; 282 #endif 283 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 284 printf("avail memory = %s\n", pbuf); 285 286 /* 287 * Set up CPU-specific registers, cache, etc. 288 */ 289 initcpu(); 290 } 291 292 /* 293 * Set registers on exec. 294 */ 295 void 296 setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) 297 { 298 struct frame *frame = (struct frame *)l->l_md.md_regs; 299 struct pcb *pcb = lwp_getpcb(l); 300 301 frame->f_sr = PSL_USERSET; 302 frame->f_pc = pack->ep_entry & ~1; 303 frame->f_regs[D0] = 0; 304 frame->f_regs[D1] = 0; 305 frame->f_regs[D2] = 0; 306 frame->f_regs[D3] = 0; 307 frame->f_regs[D4] = 0; 308 frame->f_regs[D5] = 0; 309 frame->f_regs[D6] = 0; 310 frame->f_regs[D7] = 0; 311 frame->f_regs[A0] = 0; 312 frame->f_regs[A1] = 0; 313 frame->f_regs[A2] = (int)l->l_proc->p_psstr; 314 frame->f_regs[A3] = 0; 315 frame->f_regs[A4] = 0; 316 frame->f_regs[A5] = 0; 317 frame->f_regs[A6] = 0; 318 frame->f_regs[SP] = stack; 319 320 /* restore a null state frame */ 321 pcb->pcb_fpregs.fpf_null = 0; 322 if (fputype != FPU_NONE) 323 m68881_restore(&pcb->pcb_fpregs); 324 } 325 326 /* 327 * Info for CTL_HW 328 */ 329 char cpu_model[124]; 330 331 int news_machine_id; 332 333 static void 334 identifycpu(void) 335 { 336 337 printf("SONY NET WORK STATION, Model %s, ", cpu_model); 338 printf("Machine ID #%d\n", news_machine_id); 339 340 delay_divisor = (20480 / cpuspeed + 5) / 10; /* XXX */ 341 } 342 343 /* 344 * machine dependent system variables. 345 */ 346 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") 347 { 348 349 sysctl_createv(clog, 0, NULL, NULL, 350 CTLFLAG_PERMANENT, 351 CTLTYPE_NODE, "machdep", NULL, 352 NULL, 0, NULL, 0, 353 CTL_MACHDEP, CTL_EOL); 354 355 sysctl_createv(clog, 0, NULL, NULL, 356 CTLFLAG_PERMANENT, 357 CTLTYPE_STRUCT, "console_device", NULL, 358 sysctl_consdev, 0, NULL, sizeof(dev_t), 359 CTL_MACHDEP, CPU_CONSDEV, CTL_EOL); 360 } 361 362 int waittime = -1; 363 364 void 365 cpu_reboot(int howto, char *bootstr) 366 { 367 struct pcb *pcb = lwp_getpcb(curlwp); 368 369 /* take a snap shot before clobbering any registers */ 370 if (pcb != NULL) 371 savectx(pcb); 372 373 /* If system is cold, just halt. */ 374 if (cold) { 375 howto |= RB_HALT; 376 goto haltsys; 377 } 378 379 boothowto = howto; 380 if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 381 waittime = 0; 382 vfs_shutdown(); 383 /* 384 * If we've been adjusting the clock, the todr 385 * will be out of synch; adjust it now. 386 */ 387 resettodr(); 388 } 389 390 /* Disable interrupts. */ 391 splhigh(); 392 393 /* If rebooting and a dump is requested, do it. */ 394 if (howto & RB_DUMP) 395 dumpsys(); 396 397 haltsys: 398 /* Run any shutdown hooks. */ 399 doshutdownhooks(); 400 401 pmf_system_shutdown(boothowto); 402 403 #if defined(PANICWAIT) && !defined(DDB) 404 if ((howto & RB_HALT) == 0 && panicstr) { 405 printf("hit any key to reboot...\n"); 406 (void)cngetc(); 407 printf("\n"); 408 } 409 #endif 410 411 /* Finally, halt/reboot the system. */ 412 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { 413 DELAY(1000000); 414 doboot(RB_POWERDOWN); 415 /* NOTREACHED */ 416 } 417 418 if (howto & RB_HALT) { 419 printf("System halted.\n\n"); 420 doboot(RB_HALT); 421 /* NOTREACHED */ 422 } 423 424 printf("rebooting...\n"); 425 DELAY(1000000); 426 doboot(RB_AUTOBOOT); 427 /* NOTREACHED */ 428 } 429 430 /* 431 * Initialize the kernel crash dump header. 432 */ 433 static void 434 cpu_init_kcore_hdr(void) 435 { 436 cpu_kcore_hdr_t *h = &cpu_kcore_hdr; 437 struct m68k_kcore_hdr *m = &h->un._m68k; 438 439 memset(&cpu_kcore_hdr, 0, sizeof(cpu_kcore_hdr)); 440 441 /* 442 * Initialize the `dispatcher' portion of the header. 443 */ 444 strcpy(h->name, machine); 445 h->page_size = PAGE_SIZE; 446 h->kernbase = KERNBASE; 447 448 /* 449 * Fill in information about our MMU configuration. 450 */ 451 m->mmutype = mmutype; 452 m->sg_v = SG_V; 453 m->sg_frame = SG_FRAME; 454 m->sg_ishift = SG_ISHIFT; 455 m->sg_pmask = SG_PMASK; 456 m->sg40_shift1 = SG4_SHIFT1; 457 m->sg40_mask2 = SG4_MASK2; 458 m->sg40_shift2 = SG4_SHIFT2; 459 m->sg40_mask3 = SG4_MASK3; 460 m->sg40_shift3 = SG4_SHIFT3; 461 m->sg40_addr1 = SG4_ADDR1; 462 m->sg40_addr2 = SG4_ADDR2; 463 m->pg_v = PG_V; 464 m->pg_frame = PG_FRAME; 465 466 /* 467 * Initialize pointer to kernel segment table. 468 */ 469 m->sysseg_pa = (uint32_t)(pmap_kernel()->pm_stpa); 470 471 /* 472 * Initialize relocation value such that: 473 * 474 * pa = (va - KERNBASE) + reloc 475 */ 476 m->reloc = lowram; 477 478 /* 479 * Define the end of the relocatable range. 480 */ 481 m->relocend = (uint32_t)&end; 482 483 /* 484 * news68k has one contiguous memory segment. 485 */ 486 m->ram_segs[0].start = lowram; 487 m->ram_segs[0].size = ctob(physmem); 488 } 489 490 /* 491 * Compute the size of the machine-dependent crash dump header. 492 * Returns size in disk blocks. 493 */ 494 495 #define CHDRSIZE (ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t))) 496 #define MDHDRSIZE roundup(CHDRSIZE, dbtob(1)) 497 498 static int 499 cpu_dumpsize(void) 500 { 501 502 return btodb(MDHDRSIZE); 503 } 504 505 /* 506 * Called by dumpsys() to dump the machine-dependent header. 507 */ 508 static int 509 cpu_dump(int (*dump)(dev_t, daddr_t, void *, size_t), daddr_t *blknop) 510 { 511 int buf[MDHDRSIZE / sizeof(int)]; 512 cpu_kcore_hdr_t *chdr; 513 kcore_seg_t *kseg; 514 int error; 515 516 kseg = (kcore_seg_t *)buf; 517 chdr = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(kcore_seg_t)) / 518 sizeof(int)]; 519 520 /* Create the segment header. */ 521 CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU); 522 kseg->c_size = MDHDRSIZE - ALIGN(sizeof(kcore_seg_t)); 523 524 memcpy(chdr, &cpu_kcore_hdr, sizeof(cpu_kcore_hdr_t)); 525 error = (*dump)(dumpdev, *blknop, (void *)buf, sizeof(buf)); 526 *blknop += btodb(sizeof(buf)); 527 return error; 528 } 529 530 /* 531 * These variables are needed by /sbin/savecore 532 */ 533 uint32_t dumpmag = 0x8fca0101; /* magic number */ 534 int dumpsize = 0; /* pages */ 535 long dumplo = 0; /* blocks */ 536 537 /* 538 * This is called by main to set dumplo and dumpsize. 539 * Dumps always skip the first PAGE_SIZE of disk space 540 * in case there might be a disk label stored there. 541 * If there is extra space, put dump at the end to 542 * reduce the chance that swapping trashes it. 543 */ 544 void 545 cpu_dumpconf(void) 546 { 547 const struct bdevsw *bdev; 548 int chdrsize; /* size of dump header */ 549 int nblks; /* size of dump area */ 550 551 if (dumpdev == NODEV) 552 return; 553 bdev = bdevsw_lookup(dumpdev); 554 if (bdev == NULL) { 555 dumpdev = NODEV; 556 return; 557 } 558 if (bdev->d_psize == NULL) 559 return; 560 nblks = (*bdev->d_psize)(dumpdev); 561 chdrsize = cpu_dumpsize(); 562 563 dumpsize = btoc(cpu_kcore_hdr.un._m68k.ram_segs[0].size); 564 565 /* 566 * Check do see if we will fit. Note we always skip the 567 * first PAGE_SIZE in case there is a disk label there. 568 */ 569 if (nblks < (ctod(dumpsize) + chdrsize + ctod(1))) { 570 dumpsize = 0; 571 dumplo = -1; 572 return; 573 } 574 575 /* 576 * Put dump at the end of the partition. 577 */ 578 dumplo = (nblks - 1) - ctod(dumpsize) - chdrsize; 579 } 580 581 /* 582 * Dump physical memory onto the dump device. Called by cpu_reboot(). 583 */ 584 void 585 dumpsys(void) 586 { 587 const struct bdevsw *bdev; 588 daddr_t blkno; /* current block to write */ 589 /* dump routine */ 590 int (*dump)(dev_t, daddr_t, void *, size_t); 591 int pg; /* page being dumped */ 592 paddr_t maddr; /* PA being dumped */ 593 int error; /* error code from (*dump)() */ 594 595 /* XXX initialized here because of gcc lossage */ 596 maddr = lowram; 597 pg = 0; 598 599 /* Make sure dump device is valid. */ 600 if (dumpdev == NODEV) 601 return; 602 bdev = bdevsw_lookup(dumpdev); 603 if (bdev == NULL) 604 return; 605 if (dumpsize == 0) { 606 cpu_dumpconf(); 607 if (dumpsize == 0) 608 return; 609 } 610 if (dumplo <= 0) { 611 printf("\ndump to dev %u,%u not possible\n", 612 major(dumpdev), minor(dumpdev)); 613 return; 614 } 615 dump = bdev->d_dump; 616 blkno = dumplo; 617 618 printf("\ndumping to dev %u,%u offset %ld\n", 619 major(dumpdev), minor(dumpdev), dumplo); 620 621 printf("dump "); 622 623 /* Write the dump header. */ 624 error = cpu_dump(dump, &blkno); 625 if (error) 626 goto bad; 627 628 for (pg = 0; pg < dumpsize; pg++) { 629 #define NPGMB (1024*1024/PAGE_SIZE) 630 /* print out how many MBs we have dumped */ 631 if (pg && (pg % NPGMB) == 0) 632 printf_nolog("%d ", pg / NPGMB); 633 #undef NPGMB 634 pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr, 635 VM_PROT_READ, VM_PROT_READ|PMAP_WIRED); 636 637 pmap_update(pmap_kernel()); 638 error = (*dump)(dumpdev, blkno, vmmap, PAGE_SIZE); 639 bad: 640 switch (error) { 641 case 0: 642 maddr += PAGE_SIZE; 643 blkno += btodb(PAGE_SIZE); 644 break; 645 646 case ENXIO: 647 printf("device bad\n"); 648 return; 649 650 case EFAULT: 651 printf("device not ready\n"); 652 return; 653 654 case EINVAL: 655 printf("area improper\n"); 656 return; 657 658 case EIO: 659 printf("i/o error\n"); 660 return; 661 662 case EINTR: 663 printf("aborted from console\n"); 664 return; 665 666 default: 667 printf("error %d\n", error); 668 return; 669 } 670 } 671 printf("succeeded\n"); 672 } 673 674 static void 675 initcpu(void) 676 { 677 678 #ifdef MAPPEDCOPY 679 /* 680 * Initialize lower bound for doing copyin/copyout using 681 * page mapping (if not already set). We don't do this on 682 * VAC machines as it loses big time. 683 */ 684 if (ectype == EC_VIRT) 685 mappedcopysize = -1; /* in case it was patched */ 686 else 687 mappedcopysize = PAGE_SIZE; 688 #endif 689 } 690 691 void 692 straytrap(int pc, u_short evec) 693 { 694 695 printf("unexpected trap (vector offset %x) from %x\n", 696 evec & 0xFFF, pc); 697 } 698 699 /* XXX should change the interface, and make one badaddr() function */ 700 701 int *nofault; 702 703 int 704 badaddr(void *addr, int nbytes) 705 { 706 int i; 707 label_t faultbuf; 708 709 #ifdef lint 710 i = *addr; if (i) return 0; 711 #endif 712 713 nofault = (int *) &faultbuf; 714 if (setjmp((label_t *)nofault)) { 715 nofault = (int *) 0; 716 return 1; 717 } 718 switch (nbytes) { 719 case 1: 720 i = *(volatile char *)addr; 721 break; 722 723 case 2: 724 i = *(volatile short *)addr; 725 break; 726 727 case 4: 728 i = *(volatile int *)addr; 729 break; 730 731 default: 732 panic("badaddr: bad request"); 733 } 734 nofault = (int *) 0; 735 return 0; 736 } 737 738 int 739 badbaddr(void *addr) 740 { 741 int i; 742 label_t faultbuf; 743 744 nofault = (int *) &faultbuf; 745 if (setjmp((label_t *)nofault)) { 746 nofault = (int *) 0; 747 return 1; 748 } 749 i = *(volatile char *)addr; 750 nofault = (int *) 0; 751 return 0; 752 } 753 754 /* 755 * cpu_exec_aout_makecmds(): 756 * CPU-dependent a.out format hook for execve(). 757 * 758 * Determine of the given exec package refers to something which we 759 * understand and, if so, set up the vmcmds for it. 760 * 761 * XXX what are the special cases for the hp300? 762 * XXX why is this COMPAT_NOMID? was something generating 763 * hp300 binaries with an a_mid of 0? i thought that was only 764 * done on little-endian machines... -- cgd 765 */ 766 int 767 cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp) 768 { 769 #if defined(COMPAT_NOMID) || defined(COMPAT_44) 770 u_long midmag, magic; 771 u_short mid; 772 int error; 773 struct exec *execp = epp->ep_hdr; 774 775 midmag = ntohl(execp->a_midmag); 776 mid = (midmag >> 16) & 0xffff; 777 magic = midmag & 0xffff; 778 779 midmag = mid << 16 | magic; 780 781 switch (midmag) { 782 #ifdef COMPAT_NOMID 783 case (MID_ZERO << 16) | ZMAGIC: 784 error = exec_aout_prep_oldzmagic(l->l_proc, epp); 785 return(error); 786 #endif 787 #ifdef COMPAT_44 788 case (MID_HP300 << 16) | ZMAGIC: 789 error = exec_aout_prep_oldzmagic(p, epp); 790 return error; 791 #endif 792 } 793 #endif /* !(defined(COMPAT_NOMID) || defined(COMPAT_44)) */ 794 795 return ENOEXEC; 796 } 797 798 /* 799 * System dependent initilization 800 */ 801 802 static volatile uint8_t *dip_switch, *int_status; 803 804 const uint8_t *idrom_addr; 805 volatile uint8_t *ctrl_ast, *ctrl_int2; 806 volatile uint8_t *ctrl_led; 807 uint32_t sccport0a, lance_mem_phys; 808 809 #ifdef news1700 810 static volatile u_char *ctrl_parity, *ctrl_parity_clr, *parity_vector; 811 812 struct news68k_model { 813 const int id; 814 const char *name; 815 }; 816 817 static const struct news68k_model news68k_models[] = { 818 { ICK001, "ICK001" }, /* 1 */ 819 { ICK00X, "ICK00X" }, /* 2 */ 820 { NWS799, "NWS-799" }, /* 3 */ 821 { NWS800, "NWS-800" }, /* 4 */ 822 { NWS801, "NWS-801" }, /* 5 */ 823 { NWS802, "NWS-802" }, /* 6 */ 824 { NWS711, "NWS-711" }, /* 7 */ 825 { NWS721, "NWS-721" }, /* 8 */ 826 { NWS1850, "NWS-1850" }, /* 9 */ 827 { NWS810, "NWS-810" }, /* 10 */ 828 { NWS811, "NWS-811" }, /* 11 */ 829 { NWS1830, "NWS-1830" }, /* 12 */ 830 { NWS1750, "NWS-1750" }, /* 13 */ 831 { NWS1720, "NWS-1720" }, /* 14 */ 832 { NWS1930, "NWS-1930" }, /* 15 */ 833 { NWS1960, "NWS-1960" }, /* 16 */ 834 { NWS712, "NWS-712" }, /* 17 */ 835 { NWS1860, "NWS-1860" }, /* 18 */ 836 { PWS1630, "PWS-1630" }, /* 19 */ 837 { NWS820, "NWS-820" }, /* 20 */ 838 { NWS821, "NWS-821" }, /* 21 */ 839 { NWS1760, "NWS-1760" }, /* 22 */ 840 { NWS1710, "NWS-1710" }, /* 23 */ 841 { NWS830, "NWS-830" }, /* 30 */ 842 { NWS831, "NWS-831" }, /* 31 */ 843 { NWS841, "NWS-841" }, /* 41 */ 844 { PWS1570, "PWS-1570" }, /* 52 */ 845 { PWS1590, "PWS-1590" }, /* 54 */ 846 { NWS1520, "NWS-1520" }, /* 56 */ 847 { PWS1550, "PWS-1550" }, /* 73 */ 848 { PWS1520, "PWS-1520" }, /* 74 */ 849 { PWS1560, "PWS-1560" }, /* 75 */ 850 { NWS1530, "NWS-1530" }, /* 76 */ 851 { NWS1580, "NWS-1580" }, /* 77 */ 852 { NWS1510, "NWS-1510" }, /* 78 */ 853 { NWS1410, "NWS-1410" }, /* 81 */ 854 { NWS1450, "NWS-1450" }, /* 85 */ 855 { NWS1460, "NWS-1460" }, /* 86 */ 856 { NWS891, "NWS-891" }, /* 91 */ 857 { NWS911, "NWS-911" }, /* 111 */ 858 { NWS921, "NWS-921" }, /* 121 */ 859 { 0, NULL } 860 }; 861 862 static void 863 news1700_init(void) 864 { 865 struct oidrom idrom; 866 const char *t; 867 const uint8_t *p; 868 uint8_t *q; 869 u_int i; 870 871 dip_switch = (uint8_t *)IIOV(0xe1c00100); 872 int_status = (uint8_t *)IIOV(0xe1c00200); 873 874 idrom_addr = (uint8_t *)IIOV(0xe1c00000); 875 ctrl_ast = (uint8_t *)IIOV(0xe1280000); 876 ctrl_int2 = (uint8_t *)IIOV(0xe1180000); 877 ctrl_led = (uint8_t *)IIOV(ctrl_led_phys); 878 879 sccport0a = IIOV(0xe0d40002); 880 lance_mem_phys = 0xe0e00000; 881 882 p = idrom_addr; 883 q = (uint8_t *)&idrom; 884 885 for (i = 0; i < sizeof(idrom); i++, p += 2) 886 *q++ = ((*p & 0x0f) << 4) | (*(p + 1) & 0x0f); 887 888 t = NULL; 889 for (i = 0; news68k_models[i].name != NULL; i++) { 890 if (news68k_models[i].id == idrom.id_model) { 891 t = news68k_models[i].name; 892 } 893 } 894 if (t == NULL) 895 panic("unexpected system model."); 896 897 strcat(cpu_model, t); 898 news_machine_id = (idrom.id_serial[0] << 8) + idrom.id_serial[1]; 899 900 ctrl_parity = (uint8_t *)IIOV(0xe1080000); 901 ctrl_parity_clr = (uint8_t *)IIOV(0xe1a00000); 902 parity_vector = (uint8_t *)IIOV(0xe1c00200); 903 904 parityenable(); 905 906 cpuspeed = 25; 907 } 908 909 /* 910 * parity error handling (vectored NMI?) 911 */ 912 913 static void 914 parityenable(void) 915 { 916 917 #define PARITY_VECT 0xc0 918 #define PARITY_PRI 7 919 920 *parity_vector = PARITY_VECT; 921 922 isrlink_vectored((int (*)(void *))parityerror, NULL, 923 PARITY_PRI, PARITY_VECT); 924 925 *ctrl_parity_clr = 1; 926 *ctrl_parity = 1; 927 928 #ifdef DEBUG 929 printf("enable parity check\n"); 930 #endif 931 } 932 933 static int innmihand; /* simple mutex */ 934 935 static void 936 parityerror(void) 937 { 938 939 /* Prevent unwanted recursion. */ 940 if (innmihand) 941 return; 942 innmihand = 1; 943 944 #if 0 /* XXX need to implement XXX */ 945 panic("parity error"); 946 #else 947 printf("parity error detected.\n"); 948 *ctrl_parity_clr = 1; 949 #endif 950 innmihand = 0; 951 } 952 #endif /* news1700 */ 953 954 #ifdef news1200 955 static void 956 news1200_init(void) 957 { 958 struct idrom idrom; 959 const uint8_t *p; 960 uint8_t *q; 961 int i; 962 963 dip_switch = (uint8_t *)IIOV(0xe1680000); 964 int_status = (uint8_t *)IIOV(0xe1200000); 965 966 idrom_addr = (uint8_t *)IIOV(0xe1400000); 967 ctrl_ast = (uint8_t *)IIOV(0xe1100000); 968 ctrl_int2 = (uint8_t *)IIOV(0xe10c0000); 969 ctrl_led = (uint8_t *)IIOV(ctrl_led_phys); 970 971 sccport0a = IIOV(0xe1780002); 972 lance_mem_phys = 0xe1a00000; 973 974 p = idrom_addr; 975 q = (uint8_t *)&idrom; 976 for (i = 0; i < sizeof(idrom); i++, p += 2) 977 *q++ = ((*p & 0x0f) << 4) | (*(p + 1) & 0x0f); 978 979 strcat(cpu_model, idrom.id_model); 980 news_machine_id = idrom.id_serial; 981 982 cpuspeed = 25; 983 } 984 #endif /* news1200 */ 985 986 /* 987 * interrupt handlers 988 * XXX should do better handling XXX 989 */ 990 991 void intrhand_lev3(void); 992 void intrhand_lev4(void); 993 994 void 995 intrhand_lev3(void) 996 { 997 int stat; 998 999 stat = *int_status; 1000 intrcnt[3]++; 1001 curcpu()->ci_data.cpu_nintr++; 1002 #if 1 1003 printf("level 3 interrupt: INT_STATUS = 0x%02x\n", stat); 1004 #endif 1005 } 1006 1007 extern int leintr(int); 1008 extern int si_intr(int); 1009 1010 void 1011 intrhand_lev4(void) 1012 { 1013 int stat; 1014 1015 #define INTST_LANCE 0x04 1016 #define INTST_SCSI 0x80 1017 1018 stat = *int_status; 1019 intrcnt[4]++; 1020 curcpu()->ci_data.cpu_nintr++; 1021 1022 #if NSI > 0 1023 if (stat & INTST_SCSI) { 1024 si_intr(0); 1025 } 1026 #endif 1027 #if NLE > 0 1028 if (stat & INTST_LANCE) { 1029 leintr(0); 1030 } 1031 #endif 1032 #if 0 1033 printf("level 4 interrupt\n"); 1034 #endif 1035 } 1036 1037 /* 1038 * consinit() routines - from newsmips/cpu_cons.c 1039 */ 1040 1041 /* 1042 * Console initialization: called early on from main, 1043 * before vm init or startup. Do enough configuration 1044 * to choose and initialize a console. 1045 * XXX need something better here. 1046 */ 1047 #define SCC_CONSOLE 0 1048 #define SW_CONSOLE 0x07 1049 #define SW_NWB512 0x04 1050 #define SW_NWB225 0x01 1051 #define SW_FBPOP 0x02 1052 #define SW_FBPOP1 0x06 1053 #define SW_FBPOP2 0x03 1054 #define SW_AUTOSEL 0x07 1055 1056 struct consdev *cn_tab = NULL; 1057 extern struct consdev consdev_bm, consdev_zs; 1058 1059 int tty00_is_console = 0; 1060 1061 void 1062 consinit(void) 1063 { 1064 1065 int dipsw = *dip_switch; 1066 1067 dipsw &= ~SW_CONSOLE; 1068 1069 switch (dipsw & SW_CONSOLE) { 1070 default: /* XXX no fb support yet */ 1071 case 0: 1072 tty00_is_console = 1; 1073 cn_tab = &consdev_zs; 1074 (*cn_tab->cn_init)(cn_tab); 1075 break; 1076 } 1077 #if NKSYMS || defined(DDB) || defined(MODULAR) 1078 ksyms_addsyms_elf((int)esym - (int)&end - sizeof(Elf32_Ehdr), 1079 (void *)&end, esym); 1080 #endif 1081 #ifdef DDB 1082 if (boothowto & RB_KDB) 1083 Debugger(); 1084 #endif 1085 } 1086 1087 #ifdef MODULAR 1088 /* 1089 * Push any modules loaded by the bootloader etc. 1090 */ 1091 void 1092 module_init_md(void) 1093 { 1094 } 1095 #endif 1096