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