1 /* 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1992 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * the Systems Programming Group of the University of Utah Computer 8 * Science Department, The Mach Operating System project at 9 * Carnegie-Mellon University, Ralph Campbell, Sony Corp. and Kazumasa 10 * Utashiro of Software Research Associates, Inc. 11 * 12 * %sccs.include.redist.c% 13 * 14 * @(#)machdep.c 7.10 (Berkeley) 04/08/93 15 */ 16 17 /* from: Utah $Hdr: machdep.c 1.63 91/04/24$ */ 18 19 #include <sys/param.h> 20 #include <sys/systm.h> 21 #include <sys/signalvar.h> 22 #include <sys/kernel.h> 23 #include <sys/map.h> 24 #include <sys/proc.h> 25 #include <sys/buf.h> 26 #include <sys/reboot.h> 27 #include <sys/conf.h> 28 #include <sys/file.h> 29 #include <sys/clist.h> 30 #include <sys/callout.h> 31 #include <sys/malloc.h> 32 #include <sys/mbuf.h> 33 #include <sys/msgbuf.h> 34 #include <sys/user.h> 35 #include <sys/exec.h> 36 #ifdef SYSVSHM 37 #include <sys/shm.h> 38 #endif 39 40 #include <vm/vm.h> 41 #include <vm/vm_kern.h> 42 #include <vm/vm_page.h> 43 44 #include <machine/cpu.h> 45 #include <machine/reg.h> 46 #include <machine/psl.h> 47 #include <machine/pte.h> 48 49 #include <machine/adrsmap.h> 50 51 vm_map_t buffer_map; 52 53 /* the following is used externally (sysctl_hw) */ 54 char machine[] = "SONY"; /* cpu "architecture" */ 55 char cpu_model[30]; 56 57 /* 58 * Declare these as initialized data so we can patch them. 59 */ 60 int nswbuf = 0; 61 #ifdef NBUF 62 int nbuf = NBUF; 63 #else 64 int nbuf = 0; 65 #endif 66 #ifdef BUFPAGES 67 int bufpages = BUFPAGES; 68 #else 69 int bufpages = 0; 70 #endif 71 int msgbufmapped = 0; /* set when safe to use msgbuf */ 72 int maxmem; /* max memory per process */ 73 int physmem; /* max supported memory, changes to actual */ 74 /* 75 * safepri is a safe priority for sleep to set for a spin-wait 76 * during autoconfiguration or after a panic. 77 */ 78 int safepri = PSL_LOWIPL; 79 80 struct user *proc0paddr; 81 struct proc nullproc; /* for use by swtch_exit() */ 82 83 /* 84 * Do all the stuff that locore normally does before calling main(). 85 * Process arguments passed to us by the prom monitor. 86 * Return the first page address following the system. 87 */ 88 mach_init(x_boothowto, x_unkown, x_bootdev, x_maxmem) 89 int x_boothowto; 90 int x_unkown; 91 int x_bootdev; 92 int x_maxmem; 93 { 94 register char *cp; 95 register int i; 96 register unsigned firstaddr; 97 register caddr_t v; 98 caddr_t start; 99 extern u_long bootdev; 100 extern char edata[], end[]; 101 extern char MachUTLBMiss[], MachUTLBMissEnd[]; 102 extern char MachException[], MachExceptionEnd[]; 103 #ifdef ATTR 104 extern char *pmap_attributes; 105 #endif 106 107 /* 108 * Save parameters into kernel work area. 109 */ 110 *(int *)(MACH_CACHED_TO_UNCACHED(MACH_MAXMEMSIZE_ADDR)) = x_maxmem; 111 *(int *)(MACH_CACHED_TO_UNCACHED(MACH_BOOTDEV_ADDR)) = x_bootdev; 112 *(int *)(MACH_CACHED_TO_UNCACHED(MACH_BOOTSW_ADDR)) = x_boothowto; 113 114 /* clear the BSS segment */ 115 v = (caddr_t)pmax_round_page(end); 116 bzero(edata, v - edata); 117 118 boothowto = x_boothowto; 119 bootdev = x_bootdev; 120 maxmem = physmem = pmax_btop(x_maxmem); 121 122 /* 123 * Look at arguments passed to us and compute boothowto. 124 */ 125 #ifdef GENERIC 126 boothowto |= RB_SINGLE | RB_ASKNAME; 127 #endif 128 #ifdef KADB 129 boothowto |= RB_KDB; 130 #endif 131 132 #ifdef MFS 133 /* 134 * Check to see if a mini-root was loaded into memory. It resides 135 * at the start of the next page just after the end of BSS. 136 */ 137 if (boothowto & RB_MINIROOT) { 138 boothowto |= RB_DFLTROOT; 139 v += mfs_initminiroot(v); 140 } 141 #endif 142 143 /* 144 * Init mapping for u page(s) for proc[0], pm_tlbpid 1. 145 */ 146 start = v; 147 curproc->p_addr = proc0paddr = (struct user *)v; 148 curproc->p_md.md_regs = proc0paddr->u_pcb.pcb_regs; 149 firstaddr = MACH_CACHED_TO_PHYS(v); 150 for (i = 0; i < UPAGES; i++) { 151 MachTLBWriteIndexed(i, 152 (UADDR + (i << PGSHIFT)) | (1 << VMMACH_TLB_PID_SHIFT), 153 curproc->p_md.md_upte[i] = firstaddr | PG_V | PG_M); 154 firstaddr += NBPG; 155 } 156 v += UPAGES * NBPG; 157 MachSetPID(1); 158 159 /* 160 * init nullproc for swtch_exit(). 161 * init mapping for u page(s), pm_tlbpid 0 162 * This could be used for an idle process. 163 */ 164 nullproc.p_addr = (struct user *)v; 165 nullproc.p_md.md_regs = ((struct user *)v)->u_pcb.pcb_regs; 166 for (i = 0; i < UPAGES; i++) { 167 nullproc.p_md.md_upte[i] = firstaddr | PG_V | PG_M; 168 firstaddr += NBPG; 169 } 170 v += UPAGES * NBPG; 171 172 /* clear pages for u areas */ 173 bzero(start, v - start); 174 175 /* 176 * Copy down exception vector code. 177 */ 178 if (MachUTLBMissEnd - MachUTLBMiss > 0x80) 179 panic("startup: UTLB code too large"); 180 bcopy(MachUTLBMiss, (char *)MACH_UTLB_MISS_EXC_VEC, 181 MachUTLBMissEnd - MachUTLBMiss); 182 bcopy(MachException, (char *)MACH_GEN_EXC_VEC, 183 MachExceptionEnd - MachException); 184 185 /* 186 * Clear out the I and D caches. 187 */ 188 MachConfigCache(); 189 MachFlushCache(); 190 191 /* 192 * Initialize error message buffer (at end of core). 193 */ 194 maxmem -= btoc(sizeof (struct msgbuf)); 195 msgbufp = (struct msgbuf *)(MACH_PHYS_TO_CACHED(maxmem << PGSHIFT)); 196 msgbufmapped = 1; 197 198 /* 199 * Allocate space for system data structures. 200 * The first available kernel virtual address is in "v". 201 * As pages of kernel virtual memory are allocated, "v" is incremented. 202 * 203 * These data structures are allocated here instead of cpu_startup() 204 * because physical memory is directly addressable. We don't have 205 * to map these into virtual address space. 206 */ 207 start = v; 208 209 #define valloc(name, type, num) \ 210 (name) = (type *)v; v = (caddr_t)((name)+(num)) 211 #define valloclim(name, type, num, lim) \ 212 (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num))) 213 valloc(cfree, struct cblock, nclist); 214 valloc(callout, struct callout, ncallout); 215 valloc(swapmap, struct map, nswapmap = maxproc * 2); 216 #ifdef SYSVSHM 217 valloc(shmsegs, struct shmid_ds, shminfo.shmmni); 218 #endif 219 #ifdef ATTR 220 /* this is allocated here just to save a few bytes */ 221 valloc(pmap_attributes, char, physmem); 222 #endif 223 224 /* 225 * Determine how many buffers to allocate. 226 * We allocate more buffer space than the BSD standard of 227 * using 10% of memory for the first 2 Meg, 5% of remaining. 228 * We just allocate a flat 10%. Insure a minimum of 16 buffers. 229 * We allocate 1/2 as many swap buffer headers as file i/o buffers. 230 */ 231 if (bufpages == 0) 232 bufpages = physmem / 10 / CLSIZE; 233 if (nbuf == 0) { 234 nbuf = bufpages; 235 if (nbuf < 16) 236 nbuf = 16; 237 } 238 if (nswbuf == 0) { 239 nswbuf = (nbuf / 2) &~ 1; /* force even */ 240 if (nswbuf > 256) 241 nswbuf = 256; /* sanity */ 242 } 243 valloc(swbuf, struct buf, nswbuf); 244 valloc(buf, struct buf, nbuf); 245 246 /* 247 * Clear allocated memory. 248 */ 249 v = (caddr_t)pmax_round_page(v); 250 bzero(start, v - start); 251 252 /* 253 * Initialize the virtual memory system. 254 */ 255 pmap_bootstrap((vm_offset_t)MACH_CACHED_TO_PHYS(v)); 256 } 257 258 /* 259 * Console initialization: called early on from main, 260 * before vm init or startup. Do enough configuration 261 * to choose and initialize a console. 262 * XXX need something better here. 263 */ 264 #define SCC_CONSOLE 0 265 #define SW_CONSOLE 0x07 266 #define SW_NWB512 0x04 267 #define SW_NWB225 0x01 268 #define SW_FBPOP 0x02 269 #define SW_FBPOP1 0x06 270 #define SW_FBPOP2 0x03 271 #define SW_AUTOSEL 0x07 272 consinit() 273 { 274 extern dev_t consdev; 275 extern struct tty *constty, *cn_tty, *rs_tty; 276 int dipsw = (int)*(volatile u_char *)DIP_SWITCH; 277 278 #include "bm.h" 279 #if NBM > 0 280 #if defined(news3200) || defined(news3400) /* KU:XXX */ 281 fbbm_probe(dipsw|2); 282 #else 283 fbbm_probe(dipsw); 284 #endif 285 vt100_open(); 286 setup_fnt(); 287 setup_fnt24(); 288 #else 289 dipsw &= SW_CONSOLE; 290 #endif 291 292 switch (dipsw & SW_CONSOLE) { 293 case 0: 294 scc_open(SCC_CONSOLE); 295 consdev = makedev(1, 0); 296 constty = rs_tty; 297 break; 298 299 default: 300 #if NBM > 0 301 consdev = makedev(22, 0); 302 constty = cn_tty; 303 #endif 304 break; 305 } 306 return(0); 307 } 308 309 /* 310 * cpu_startup: allocate memory for variable-sized tables, 311 * initialize cpu, and do autoconfiguration. 312 */ 313 cpu_startup() 314 { 315 register unsigned i; 316 register caddr_t v; 317 int base, residual; 318 extern long Usrptsize; 319 extern struct map *useriomap; 320 #ifdef DEBUG 321 extern int pmapdebug; 322 int opmapdebug = pmapdebug; 323 #endif 324 vm_offset_t minaddr, maxaddr; 325 vm_size_t size; 326 327 #ifdef DEBUG 328 pmapdebug = 0; 329 #endif 330 331 /* 332 * Good {morning,afternoon,evening,night}. 333 */ 334 printf(version); 335 printf("real mem = %d\n", ctob(physmem)); 336 337 /* 338 * Allocate virtual address space for file I/O buffers. 339 * Note they are different than the array of headers, 'buf', 340 * and usually occupy more virtual memory than physical. 341 */ 342 size = MAXBSIZE * nbuf; 343 buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers, 344 &maxaddr, size, FALSE); 345 minaddr = (vm_offset_t)buffers; 346 if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0, 347 &minaddr, size, FALSE) != KERN_SUCCESS) 348 panic("startup: cannot allocate buffers"); 349 base = bufpages / nbuf; 350 residual = bufpages % nbuf; 351 for (i = 0; i < nbuf; i++) { 352 vm_size_t curbufsize; 353 vm_offset_t curbuf; 354 355 /* 356 * First <residual> buffers get (base+1) physical pages 357 * allocated for them. The rest get (base) physical pages. 358 * 359 * The rest of each buffer occupies virtual space, 360 * but has no physical memory allocated for it. 361 */ 362 curbuf = (vm_offset_t)buffers + i * MAXBSIZE; 363 curbufsize = CLBYTES * (i < residual ? base+1 : base); 364 vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE); 365 vm_map_simplify(buffer_map, curbuf); 366 } 367 /* 368 * Allocate a submap for exec arguments. This map effectively 369 * limits the number of processes exec'ing at any time. 370 */ 371 exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, 372 16*NCARGS, TRUE); 373 /* 374 * Allocate a submap for physio 375 */ 376 phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, 377 VM_PHYS_SIZE, TRUE); 378 379 /* 380 * Finally, allocate mbuf pool. Since mclrefcnt is an off-size 381 * we use the more space efficient malloc in place of kmem_alloc. 382 */ 383 mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES, 384 M_MBUF, M_NOWAIT); 385 bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES); 386 mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr, 387 VM_MBUF_SIZE, FALSE); 388 /* 389 * Initialize callouts 390 */ 391 callfree = callout; 392 for (i = 1; i < ncallout; i++) 393 callout[i-1].c_next = &callout[i]; 394 callout[i-1].c_next = NULL; 395 396 #ifdef DEBUG 397 pmapdebug = opmapdebug; 398 #endif 399 printf("avail mem = %d\n", ptoa(cnt.v_free_count)); 400 printf("using %d buffers containing %d bytes of memory\n", 401 nbuf, bufpages * CLBYTES); 402 /* 403 * Set up CPU-specific registers, cache, etc. 404 */ 405 initcpu(); 406 407 /* 408 * Set up buffers, so they can be used to read disk labels. 409 */ 410 bufinit(); 411 412 /* 413 * Configure the system. 414 */ 415 configure(); 416 } 417 418 /* 419 * Set registers on exec. 420 * Clear all registers except sp, pc. 421 */ 422 setregs(p, entry, retval) 423 register struct proc *p; 424 u_long entry; 425 int retval[2]; 426 { 427 int sp = p->p_md.md_regs[SP]; 428 extern struct proc *machFPCurProcPtr; 429 430 bzero((caddr_t)p->p_md.md_regs, (FSR + 1) * sizeof(int)); 431 p->p_md.md_regs[SP] = sp; 432 p->p_md.md_regs[PC] = entry & ~3; 433 p->p_md.md_regs[PS] = PSL_USERSET; 434 p->p_md.md_flags & ~MDP_FPUSED; 435 if (machFPCurProcPtr == p) 436 machFPCurProcPtr = (struct proc *)0; 437 } 438 439 /* 440 * WARNING: code in locore.s assumes the layout shown for sf_signum 441 * thru sf_handler so... don't screw with them! 442 */ 443 struct sigframe { 444 int sf_signum; /* signo for handler */ 445 int sf_code; /* additional info for handler */ 446 struct sigcontext *sf_scp; /* context ptr for handler */ 447 sig_t sf_handler; /* handler addr for u_sigc */ 448 struct sigcontext sf_sc; /* actual context */ 449 }; 450 451 #ifdef DEBUG 452 int sigdebug = 0; 453 int sigpid = 0; 454 #define SDB_FOLLOW 0x01 455 #define SDB_KSTACK 0x02 456 #define SDB_FPSTATE 0x04 457 #endif 458 459 /* 460 * Send an interrupt to process. 461 */ 462 void 463 sendsig(catcher, sig, mask, code) 464 sig_t catcher; 465 int sig, mask; 466 unsigned code; 467 { 468 register struct proc *p = curproc; 469 register struct sigframe *fp; 470 register int *regs; 471 register struct sigacts *psp = p->p_sigacts; 472 int oonstack, fsize; 473 struct sigcontext ksc; 474 extern char sigcode[], esigcode[]; 475 476 regs = p->p_md.md_regs; 477 oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK; 478 /* 479 * Allocate and validate space for the signal handler 480 * context. Note that if the stack is in data space, the 481 * call to grow() is a nop, and the copyout() 482 * will fail if the process has not already allocated 483 * the space with a `brk'. 484 */ 485 fsize = sizeof(struct sigframe); 486 if ((psp->ps_flags & SAS_ALTSTACK) && 487 (psp->ps_sigstk.ss_flags & SA_ONSTACK) == 0 && 488 (psp->ps_sigonstack & sigmask(sig))) { 489 fp = (struct sigframe *)(psp->ps_sigstk.ss_base + 490 psp->ps_sigstk.ss_size - fsize); 491 psp->ps_sigstk.ss_flags |= SA_ONSTACK; 492 } else 493 fp = (struct sigframe *)(regs[SP] - fsize); 494 if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize)) 495 (void)grow(p, (unsigned)fp); 496 #ifdef DEBUG 497 if ((sigdebug & SDB_FOLLOW) || 498 (sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 499 printf("sendsig(%d): sig %d ssp %x usp %x scp %x\n", 500 p->p_pid, sig, &oonstack, fp, &fp->sf_sc); 501 #endif 502 /* 503 * Build the signal context to be used by sigreturn. 504 */ 505 ksc.sc_onstack = oonstack; 506 ksc.sc_mask = mask; 507 ksc.sc_pc = regs[PC]; 508 ksc.sc_regs[ZERO] = 0xACEDBADE; /* magic number */ 509 bcopy((caddr_t)®s[1], (caddr_t)&ksc.sc_regs[1], 510 sizeof(ksc.sc_regs) - sizeof(int)); 511 ksc.sc_fpused = p->p_md.md_flags & MDP_FPUSED; 512 if (ksc.sc_fpused) { 513 extern struct proc *machFPCurProcPtr; 514 515 /* if FPU has current state, save it first */ 516 if (p == machFPCurProcPtr) 517 MachSaveCurFPState(p); 518 bcopy((caddr_t)&p->p_md.md_regs[F0], (caddr_t)ksc.sc_fpregs, 519 sizeof(ksc.sc_fpregs)); 520 } 521 if (copyout((caddr_t)&ksc, (caddr_t)&fp->sf_sc, sizeof(ksc))) { 522 /* 523 * Process has trashed its stack; give it an illegal 524 * instruction to halt it in its tracks. 525 */ 526 SIGACTION(p, SIGILL) = SIG_DFL; 527 sig = sigmask(SIGILL); 528 p->p_sigignore &= ~sig; 529 p->p_sigcatch &= ~sig; 530 p->p_sigmask &= ~sig; 531 psignal(p, SIGILL); 532 return; 533 } 534 /* 535 * Build the argument list for the signal handler. 536 */ 537 regs[A0] = sig; 538 regs[A1] = code; 539 regs[A2] = (int)&fp->sf_sc; 540 regs[A3] = (int)catcher; 541 542 regs[PC] = (int)catcher; 543 regs[SP] = (int)fp; 544 /* 545 * Signal trampoline code is at base of user stack. 546 */ 547 regs[RA] = (int)PS_STRINGS - (esigcode - sigcode); 548 #ifdef DEBUG 549 if ((sigdebug & SDB_FOLLOW) || 550 (sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 551 printf("sendsig(%d): sig %d returns\n", 552 p->p_pid, sig); 553 #endif 554 } 555 556 /* 557 * System call to cleanup state after a signal 558 * has been taken. Reset signal mask and 559 * stack state from context left by sendsig (above). 560 * Return to previous pc and psl as specified by 561 * context left by sendsig. Check carefully to 562 * make sure that the user has not modified the 563 * psl to gain improper priviledges or to cause 564 * a machine fault. 565 */ 566 struct sigreturn_args { 567 struct sigcontext *sigcntxp; 568 }; 569 /* ARGSUSED */ 570 sigreturn(p, uap, retval) 571 struct proc *p; 572 struct sigreturn_args *uap; 573 int *retval; 574 { 575 register struct sigcontext *scp; 576 register int *regs; 577 struct sigcontext ksc; 578 int error; 579 580 scp = uap->sigcntxp; 581 #ifdef DEBUG 582 if (sigdebug & SDB_FOLLOW) 583 printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp); 584 #endif 585 regs = p->p_md.md_regs; 586 /* 587 * Test and fetch the context structure. 588 * We grab it all at once for speed. 589 */ 590 error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof(ksc)); 591 if (error || ksc.sc_regs[ZERO] != 0xACEDBADE) { 592 #ifdef DEBUG 593 if (!(sigdebug & SDB_FOLLOW)) 594 printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp); 595 printf(" old sp %x ra %x pc %x\n", 596 regs[SP], regs[RA], regs[PC]); 597 printf(" new sp %x ra %x pc %x err %d z %x\n", 598 ksc.sc_regs[SP], ksc.sc_regs[RA], ksc.sc_regs[PC], 599 error, ksc.sc_regs[ZERO]); 600 #endif 601 return (EINVAL); 602 } 603 scp = &ksc; 604 /* 605 * Restore the user supplied information 606 */ 607 if (scp->sc_onstack & 01) 608 p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK; 609 else 610 p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK; 611 p->p_sigmask = scp->sc_mask &~ sigcantmask; 612 regs[PC] = scp->sc_pc; 613 bcopy((caddr_t)&scp->sc_regs[1], (caddr_t)®s[1], 614 sizeof(scp->sc_regs) - sizeof(int)); 615 if (scp->sc_fpused) 616 bcopy((caddr_t)scp->sc_fpregs, (caddr_t)&p->p_md.md_regs[F0], 617 sizeof(scp->sc_fpregs)); 618 return (EJUSTRETURN); 619 } 620 621 int waittime = -1; 622 623 boot(howto) 624 register int howto; 625 { 626 627 /* take a snap shot before clobbering any registers */ 628 if (curproc) 629 savectx(curproc->p_addr, 0); 630 631 #ifdef DEBUG 632 if (panicstr) 633 traceback(); 634 #endif 635 636 boothowto = howto; 637 if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 638 register struct buf *bp; 639 int iter, nbusy; 640 641 waittime = 0; 642 (void) spl0(); 643 printf("syncing disks... "); 644 /* 645 * Release vnodes held by texts before sync. 646 */ 647 if (panicstr == 0) 648 vnode_pager_umount(NULL); 649 #ifdef notyet 650 #include "fd.h" 651 #if NFD > 0 652 fdshutdown(); 653 #endif 654 #endif 655 sync(&proc0, (void *)NULL, (int *)NULL); 656 657 for (iter = 0; iter < 20; iter++) { 658 nbusy = 0; 659 for (bp = &buf[nbuf]; --bp >= buf; ) 660 if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY) 661 nbusy++; 662 if (nbusy == 0) 663 break; 664 printf("%d ", nbusy); 665 DELAY(40000 * iter); 666 } 667 if (nbusy) 668 printf("giving up\n"); 669 else 670 printf("done\n"); 671 /* 672 * If we've been adjusting the clock, the todr 673 * will be out of synch; adjust it now. 674 */ 675 resettodr(); 676 } 677 (void) splhigh(); /* extreme priority */ 678 if (howto & RB_HALT) { 679 halt(howto); 680 /*NOTREACHED*/ 681 } else { 682 if (howto & RB_DUMP) 683 dumpsys(); 684 halt(howto); 685 /*NOTREACHED*/ 686 } 687 /*NOTREACHED*/ 688 } 689 690 halt(howto) 691 int howto; 692 { 693 if (*(volatile u_char *)DIP_SWITCH & 0x20) 694 howto |= RB_HALT; 695 to_monitor(howto); 696 /*NOTREACHED*/ 697 } 698 699 int dumpmag = 0x8fca0101; /* magic number for savecore */ 700 int dumpsize = 0; /* also for savecore */ 701 long dumplo = 0; 702 703 dumpconf() 704 { 705 int nblks; 706 707 dumpsize = physmem; 708 if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) { 709 nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev); 710 if (dumpsize > btoc(dbtob(nblks - dumplo))) 711 dumpsize = btoc(dbtob(nblks - dumplo)); 712 else if (dumplo == 0) 713 dumplo = nblks - btodb(ctob(physmem)); 714 } 715 /* 716 * Don't dump on the first CLBYTES (why CLBYTES?) 717 * in case the dump device includes a disk label. 718 */ 719 if (dumplo < btodb(CLBYTES)) 720 dumplo = btodb(CLBYTES); 721 } 722 723 /* 724 * Doadump comes here after turning off memory management and 725 * getting on the dump stack, either when called above, or by 726 * the auto-restart code. 727 */ 728 dumpsys() 729 { 730 int error; 731 732 msgbufmapped = 0; 733 if (dumpdev == NODEV) 734 return; 735 /* 736 * For dumps during autoconfiguration, 737 * if dump device has already configured... 738 */ 739 if (dumpsize == 0) 740 dumpconf(); 741 if (dumplo < 0) 742 return; 743 printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo); 744 printf("dump "); 745 switch (error = (*bdevsw[major(dumpdev)].d_dump)(dumpdev)) { 746 747 case ENXIO: 748 printf("device bad\n"); 749 break; 750 751 case EFAULT: 752 printf("device not ready\n"); 753 break; 754 755 case EINVAL: 756 printf("area improper\n"); 757 break; 758 759 case EIO: 760 printf("i/o error\n"); 761 break; 762 763 default: 764 printf("error %d\n", error); 765 break; 766 767 case 0: 768 printf("succeeded\n"); 769 } 770 } 771 772 /* 773 * Return the best possible estimate of the time in the timeval 774 * to which tvp points. Unfortunately, we can't read the hardware registers. 775 * We guarantee that the time will be greater than the value obtained by a 776 * previous call. 777 */ 778 microtime(tvp) 779 register struct timeval *tvp; 780 { 781 int s = splclock(); 782 static struct timeval lasttime; 783 784 *tvp = time; 785 #ifdef notdef 786 tvp->tv_usec += clkread(); 787 while (tvp->tv_usec > 1000000) { 788 tvp->tv_sec++; 789 tvp->tv_usec -= 1000000; 790 } 791 #endif 792 if (tvp->tv_sec == lasttime.tv_sec && 793 tvp->tv_usec <= lasttime.tv_usec && 794 (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) { 795 tvp->tv_sec++; 796 tvp->tv_usec -= 1000000; 797 } 798 lasttime = *tvp; 799 splx(s); 800 } 801 802 initcpu() 803 { 804 805 /* 806 * clear LEDs 807 */ 808 *(char*)DEBUG_PORT = (char)DP_WRITE|DP_LED0|DP_LED1|DP_LED2|DP_LED3; 809 810 /* 811 * clear all interrupts 812 */ 813 *(char*)INTCLR0 = 0; 814 *(char*)INTCLR1 = 0; 815 816 /* 817 * It's not a time to enable timer yet. 818 * 819 * INTEN0: PERR ABORT BERR TIMER KBD MS CFLT CBSY 820 * o o o x o o x x 821 * INTEN1: BEEP SCC LANCE DMA SLOT1 SLOT3 EXT1 EXT3 822 * x o o o o o x x 823 */ 824 825 *(char*)INTEN0 = (char) INTEN0_PERR|INTEN0_ABORT|INTEN0_BERR| 826 INTEN0_KBDINT|INTEN0_MSINT; 827 828 *(char*)INTEN1 = (char) INTEN1_SCC|INTEN1_LANCE|INTEN1_DMA| 829 INTEN1_SLOT1|INTEN1_SLOT3; 830 831 spl0(); /* safe to turn interrupts on now */ 832 } 833 834 /* 835 * Convert an ASCII string into an integer. 836 */ 837 int 838 atoi(s) 839 char *s; 840 { 841 int c; 842 unsigned base = 10, d; 843 int neg = 0, val = 0; 844 845 if (s == 0 || (c = *s++) == 0) 846 goto out; 847 848 /* skip spaces if any */ 849 while (c == ' ' || c == '\t') 850 c = *s++; 851 852 /* parse sign, allow more than one (compat) */ 853 while (c == '-') { 854 neg = !neg; 855 c = *s++; 856 } 857 858 /* parse base specification, if any */ 859 if (c == '0') { 860 c = *s++; 861 switch (c) { 862 case 'X': 863 case 'x': 864 base = 16; 865 break; 866 case 'B': 867 case 'b': 868 base = 2; 869 break; 870 default: 871 base = 8; 872 break; 873 } 874 } 875 876 /* parse number proper */ 877 for (;;) { 878 if (c >= '0' && c <= '9') 879 d = c - '0'; 880 else if (c >= 'a' && c <= 'z') 881 d = c - 'a' + 10; 882 else if (c >= 'A' && c <= 'Z') 883 d = c - 'A' + 10; 884 else 885 break; 886 val *= base; 887 val += d; 888 c = *s++; 889 } 890 if (neg) 891 val = -val; 892 out: 893 return val; 894 } 895 896 #ifdef CPU_SINGLE 897 /* 898 * small ring buffers for keyboard/mouse 899 */ 900 struct ring_buf { 901 u_char head; 902 u_char tail; 903 u_char count; 904 u_char buf[13]; 905 } ring_buf[2]; 906 907 xputc(c, chan) 908 u_char c; 909 int chan; 910 { 911 register struct ring_buf *p = &ring_buf[chan]; 912 int s = splhigh(); 913 914 if (p->count >= sizeof (p->buf)) { 915 (void) splx(s); 916 return (-1); 917 } 918 p->buf[p->head] = c; 919 if (++p->head >= sizeof (p->buf)) 920 p->head = 0; 921 p->count++; 922 (void) splx(s); 923 return (c); 924 } 925 926 xgetc(chan) 927 int chan; 928 { 929 register struct ring_buf *p = &ring_buf[chan]; 930 int c; 931 int s = splhigh(); 932 933 if (p->count == 0) { 934 (void) splx(s); 935 return (-1); 936 } 937 c = p->buf[p->tail]; 938 if (++p->tail >= sizeof (p->buf)) 939 p->tail = 0; 940 p->count--; 941 (void) splx(s); 942 return (c); 943 } 944 #endif /* CPU_SINGLE */ 945