|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982,1986,1988,1990 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: * ! 6: * @(#)machdep.c 7.30 (Berkeley) 6/28/90 ! 7: */ ! 8: ! 9: #include "param.h" ! 10: #include "systm.h" ! 11: #include "user.h" ! 12: #include "kernel.h" ! 13: #include "malloc.h" ! 14: #include "map.h" ! 15: #include "vm.h" ! 16: #include "proc.h" ! 17: #include "buf.h" ! 18: #include "reboot.h" ! 19: #include "conf.h" ! 20: #include "file.h" ! 21: #include "text.h" ! 22: #include "clist.h" ! 23: #include "callout.h" ! 24: #include "cmap.h" ! 25: #include "mbuf.h" ! 26: #include "msgbuf.h" ! 27: #ifdef SYSVSHM ! 28: #include "shm.h" ! 29: #endif ! 30: ! 31: #include "reg.h" ! 32: #include "pte.h" ! 33: #include "psl.h" ! 34: #include "frame.h" ! 35: #include "clock.h" ! 36: #include "cons.h" ! 37: #include "cpu.h" ! 38: #include "mem.h" ! 39: #include "mtpr.h" ! 40: #include "rpb.h" ! 41: #include "ka630.h" ! 42: #include "ka650.h" ! 43: ! 44: #include "../vaxuba/ubavar.h" ! 45: #include "../vaxuba/ubareg.h" ! 46: ! 47: /* ! 48: * Declare these as initialized data so we can patch them. ! 49: */ ! 50: int nswbuf = 0; ! 51: #ifdef NBUF ! 52: int nbuf = NBUF; ! 53: #else ! 54: int nbuf = 0; ! 55: #endif ! 56: #ifdef BUFPAGES ! 57: int bufpages = BUFPAGES; ! 58: #else ! 59: int bufpages = 0; ! 60: #endif ! 61: int msgbufmapped; /* set when safe to use msgbuf */ ! 62: int physmem = MAXMEM; /* max supported memory, changes to actual */ ! 63: ! 64: /* ! 65: * Machine-dependent startup code ! 66: */ ! 67: startup(firstaddr) ! 68: int firstaddr; ! 69: { ! 70: register int unixsize; ! 71: register unsigned i; ! 72: register struct pte *pte; ! 73: int mapaddr, j, n; ! 74: register caddr_t v; ! 75: int maxbufs, base, residual; ! 76: ! 77: /* ! 78: * Initialize error message buffer (at end of core). ! 79: */ ! 80: maxmem = physmem - btoc(sizeof (struct msgbuf)); ! 81: pte = msgbufmap; ! 82: for (i = 1; i < btoc(sizeof (struct msgbuf)) + 1; i++) ! 83: *(int *)pte++ = PG_V | PG_KW | (physmem - i); ! 84: mtpr(TBIA, 0); ! 85: msgbufmapped = 1; ! 86: ! 87: #ifdef QBA ! 88: #include "qv.h" ! 89: #if NQV > 0 ! 90: /* ! 91: * redirect console to qvss if it exists ! 92: */ ! 93: qvcons_init(); ! 94: #endif ! 95: #include "qd.h" ! 96: #if NQD > 0 ! 97: /* ! 98: * redirect console to qdss if it exists ! 99: */ ! 100: qdcons_init(); ! 101: #endif ! 102: #endif ! 103: ! 104: #ifdef KADB ! 105: kdb_init(); ! 106: (void) cnopen(makedev(0, 0), 0); /* open console XXX */ ! 107: #endif ! 108: /* ! 109: * Good {morning,afternoon,evening,night}. ! 110: */ ! 111: printf(version); ! 112: printf("real mem = %d\n", ctob(physmem)); ! 113: ! 114: /* ! 115: * Allocate space for system data structures. ! 116: * The first available real memory address is in "firstaddr". ! 117: * The first available kernel virtual address is in "v". ! 118: * As pages of kernel virtual memory are allocated, "v" is incremented. ! 119: * As pages of memory are allocated and cleared, ! 120: * "firstaddr" is incremented. ! 121: * An index into the kernel page table corresponding to the ! 122: * virtual memory address maintained in "v" is kept in "mapaddr". ! 123: */ ! 124: v = (caddr_t)(KERNBASE | (firstaddr * NBPG)); ! 125: #define valloc(name, type, num) \ ! 126: (name) = (type *)v; v = (caddr_t)((name)+(num)) ! 127: #define valloclim(name, type, num, lim) \ ! 128: (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num))) ! 129: valloclim(file, struct file, nfile, fileNFILE); ! 130: valloclim(proc, struct proc, nproc, procNPROC); ! 131: valloclim(text, struct text, ntext, textNTEXT); ! 132: valloc(cfree, struct cblock, nclist); ! 133: valloc(callout, struct callout, ncallout); ! 134: valloc(swapmap, struct map, nswapmap = nproc * 2); ! 135: valloc(argmap, struct map, ARGMAPSIZE); ! 136: valloc(kernelmap, struct map, nproc); ! 137: valloc(mbmap, struct map, nmbclusters/4); ! 138: valloc(kmemmap, struct map, ekmempt - kmempt); ! 139: valloc(kmemusage, struct kmemusage, ekmempt - kmempt); ! 140: #ifdef SYSVSHM ! 141: valloc(shmsegs, struct shmid_ds, shminfo.shmmni); ! 142: #endif ! 143: ! 144: /* ! 145: * Determine how many buffers to allocate. ! 146: * Use 10% of memory for the first 2 Meg, 5% of the remaining ! 147: * memory. Insure a minimum of 16 buffers. ! 148: * We allocate 1/2 as many swap buffer headers as file i/o buffers. ! 149: */ ! 150: if (bufpages == 0) ! 151: if (physmem < (2 * 1024 * CLSIZE)) ! 152: bufpages = physmem / 10 / CLSIZE; ! 153: else ! 154: bufpages = ((2 * 1024 * CLSIZE + physmem) / 20) / CLSIZE; ! 155: if (nbuf == 0) { ! 156: nbuf = bufpages / 2; ! 157: if (nbuf < 16) ! 158: nbuf = 16; ! 159: } ! 160: if (nswbuf == 0) { ! 161: nswbuf = (nbuf / 2) &~ 1; /* force even */ ! 162: if (nswbuf > 256) ! 163: nswbuf = 256; /* sanity */ ! 164: } ! 165: valloc(swbuf, struct buf, nswbuf); ! 166: ! 167: /* ! 168: * Now the amount of virtual memory remaining for buffers ! 169: * can be calculated, estimating needs for the cmap. ! 170: */ ! 171: ncmap = (maxmem*NBPG - ((int)v &~ KERNBASE)) / ! 172: (CLBYTES + sizeof(struct cmap)) + 2; ! 173: maxbufs = ((SYSPTSIZE * NBPG) - ! 174: ((int)(v + ncmap * sizeof(struct cmap)) - KERNBASE)) / ! 175: (MAXBSIZE + sizeof(struct buf)); ! 176: if (maxbufs < 16) ! 177: panic("sys pt too small"); ! 178: if (nbuf > maxbufs) { ! 179: printf("SYSPTSIZE limits number of buffers to %d\n", maxbufs); ! 180: nbuf = maxbufs; ! 181: } ! 182: if (bufpages > nbuf * (MAXBSIZE / CLBYTES)) ! 183: bufpages = nbuf * (MAXBSIZE / CLBYTES); ! 184: valloc(buf, struct buf, nbuf); ! 185: ! 186: /* ! 187: * Allocate space for core map. ! 188: * Allow space for all of phsical memory minus the amount ! 189: * dedicated to the system. The amount of physical memory ! 190: * dedicated to the system is the total virtual memory of ! 191: * the system thus far, plus core map, buffer pages, ! 192: * and buffer headers not yet allocated. ! 193: * Add 2: 1 because the 0th entry is unused, 1 for rounding. ! 194: */ ! 195: ncmap = (maxmem*NBPG - ((int)(v + bufpages*CLBYTES) &~ KERNBASE)) / ! 196: (CLBYTES + sizeof(struct cmap)) + 2; ! 197: valloclim(cmap, struct cmap, ncmap, ecmap); ! 198: ! 199: /* ! 200: * Clear space allocated thus far, and make r/w entries ! 201: * for the space in the kernel map. ! 202: */ ! 203: unixsize = btoc((int)v &~ KERNBASE); ! 204: while (firstaddr < unixsize) { ! 205: *(int *)(&Sysmap[firstaddr]) = PG_V | PG_KW | firstaddr; ! 206: clearseg((unsigned)firstaddr); ! 207: firstaddr++; ! 208: } ! 209: ! 210: /* ! 211: * Now allocate buffers proper. They are different than the above ! 212: * in that they usually occupy more virtual memory than physical. ! 213: */ ! 214: v = (caddr_t) ((int)(v + PGOFSET) &~ PGOFSET); ! 215: valloc(buffers, char, MAXBSIZE * nbuf); ! 216: base = bufpages / nbuf; ! 217: residual = bufpages % nbuf; ! 218: mapaddr = firstaddr; ! 219: for (i = 0; i < nbuf; i++) { ! 220: n = (i < residual ? base + 1 : base) * CLSIZE; ! 221: for (j = 0; j < n; j++) { ! 222: *(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr; ! 223: clearseg((unsigned)firstaddr); ! 224: firstaddr++; ! 225: } ! 226: mapaddr += MAXBSIZE / NBPG; ! 227: } ! 228: ! 229: unixsize = btoc((int)v &~ KERNBASE); ! 230: if (firstaddr >= physmem - 8*UPAGES) ! 231: panic("no memory"); ! 232: mtpr(TBIA, 0); /* After we just cleared it all! */ ! 233: ! 234: /* ! 235: * Initialize callouts ! 236: */ ! 237: callfree = callout; ! 238: for (i = 1; i < ncallout; i++) ! 239: callout[i-1].c_next = &callout[i]; ! 240: ! 241: /* ! 242: * Initialize memory allocator and swap ! 243: * and user page table maps. ! 244: * ! 245: * THE USER PAGE TABLE MAP IS CALLED ``kernelmap'' ! 246: * WHICH IS A VERY UNDESCRIPTIVE AND INCONSISTENT NAME. ! 247: */ ! 248: meminit(firstaddr, maxmem); ! 249: maxmem = freemem; ! 250: printf("avail mem = %d\n", ctob(maxmem)); ! 251: printf("using %d buffers containing %d bytes of memory\n", ! 252: nbuf, bufpages * CLBYTES); ! 253: rminit(kernelmap, (long)USRPTSIZE, (long)1, ! 254: "usrpt", nproc); ! 255: rminit(mbmap, (long)(nmbclusters * CLSIZE), (long)CLSIZE, ! 256: "mbclusters", nmbclusters/4); ! 257: kmeminit(); /* now safe to do malloc/free */ ! 258: ! 259: /* ! 260: * Set up CPU-specific registers, cache, etc. ! 261: */ ! 262: initcpu(); ! 263: ! 264: /* ! 265: * Set up buffers, so they can be used to read disk labels. ! 266: */ ! 267: bhinit(); ! 268: binit(); ! 269: ! 270: /* ! 271: * Configure the system. ! 272: */ ! 273: configure(); ! 274: ! 275: /* ! 276: * Clear restart inhibit flags. ! 277: */ ! 278: tocons(TXDB_CWSI); ! 279: tocons(TXDB_CCSI); ! 280: } ! 281: ! 282: #ifdef PGINPROF ! 283: /* ! 284: * Return the difference (in microseconds) ! 285: * between the current time and a previous ! 286: * time as represented by the arguments. ! 287: * If there is a pending clock interrupt ! 288: * which has not been serviced due to high ! 289: * ipl, return error code. ! 290: */ ! 291: vmtime(otime, olbolt, oicr) ! 292: register int otime, olbolt, oicr; ! 293: { ! 294: ! 295: if (mfpr(ICCS)&ICCS_INT) ! 296: return(-1); ! 297: else ! 298: return(((time.tv_sec-otime)*60 + lbolt-olbolt)*16667 + mfpr(ICR)-oicr); ! 299: } ! 300: #endif ! 301: ! 302: /* ! 303: * Clear registers on exec ! 304: */ ! 305: /* ARGSUSED */ ! 306: setregs(entry, retval) ! 307: u_long entry; ! 308: int *retval; ! 309: { ! 310: #ifdef notdef ! 311: register int *rp; ! 312: ! 313: /* should pass args to init on the stack */ ! 314: /* should also fix this code before using it, it's wrong */ ! 315: /* wanna clear the scb? */ ! 316: for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];) ! 317: *rp++ = 0; ! 318: #endif ! 319: u.u_ar0[PC] = entry + 2; ! 320: } ! 321: ! 322: /* ! 323: * Send an interrupt to process. ! 324: * ! 325: * Stack is set up to allow sigcode stored ! 326: * in u. to call routine, followed by chmk ! 327: * to sigreturn routine below. After sigreturn ! 328: * resets the signal mask, the stack, the frame ! 329: * pointer, and the argument pointer, it returns ! 330: * to the user specified pc, psl. ! 331: */ ! 332: sendsig(catcher, sig, mask, code) ! 333: sig_t catcher; ! 334: int sig, mask; ! 335: unsigned code; ! 336: { ! 337: register struct sigcontext *scp; ! 338: register struct proc *p = u.u_procp; ! 339: register int *regs; ! 340: register struct sigframe { ! 341: int sf_signum; ! 342: int sf_code; ! 343: struct sigcontext *sf_scp; ! 344: sig_t sf_handler; ! 345: int sf_argcount; ! 346: struct sigcontext *sf_scpcopy; ! 347: } *fp; ! 348: int oonstack; ! 349: ! 350: regs = u.u_ar0; ! 351: oonstack = u.u_onstack; ! 352: /* ! 353: * Allocate and validate space for the signal handler ! 354: * context. Note that if the stack is in P0 space, the ! 355: * call to grow() is a nop, and the useracc() check ! 356: * will fail if the process has not already allocated ! 357: * the space with a `brk'. ! 358: */ ! 359: if (!u.u_onstack && (u.u_sigonstack & sigmask(sig))) { ! 360: scp = (struct sigcontext *)u.u_sigsp - 1; ! 361: u.u_onstack = 1; ! 362: } else ! 363: scp = (struct sigcontext *)regs[SP] - 1; ! 364: fp = (struct sigframe *)scp - 1; ! 365: if ((int)fp <= USRSTACK - ctob(u.u_ssize)) ! 366: (void)grow((unsigned)fp); ! 367: if (useracc((caddr_t)fp, sizeof (*fp) + sizeof (*scp), B_WRITE) == 0) { ! 368: /* ! 369: * Process has trashed its stack; give it an illegal ! 370: * instruction to halt it in its tracks. ! 371: */ ! 372: SIGACTION(p, SIGILL) = SIG_DFL; ! 373: sig = sigmask(SIGILL); ! 374: p->p_sigignore &= ~sig; ! 375: p->p_sigcatch &= ~sig; ! 376: p->p_sigmask &= ~sig; ! 377: psignal(p, SIGILL); ! 378: return; ! 379: } ! 380: /* ! 381: * Build the argument list for the signal handler. ! 382: */ ! 383: fp->sf_signum = sig; ! 384: fp->sf_code = code; ! 385: fp->sf_scp = scp; ! 386: fp->sf_handler = catcher; ! 387: /* ! 388: * Build the calls argument frame to be used to call sigreturn ! 389: */ ! 390: fp->sf_argcount = 1; ! 391: fp->sf_scpcopy = scp; ! 392: /* ! 393: * Build the signal context to be used by sigreturn. ! 394: */ ! 395: scp->sc_onstack = oonstack; ! 396: scp->sc_mask = mask; ! 397: scp->sc_sp = regs[SP]; ! 398: scp->sc_fp = regs[FP]; ! 399: scp->sc_ap = regs[AP]; ! 400: scp->sc_pc = regs[PC]; ! 401: scp->sc_ps = regs[PS]; ! 402: regs[SP] = (int)fp; ! 403: regs[PS] &= ~(PSL_CM|PSL_FPD); ! 404: regs[PC] = (int)u.u_pcb.pcb_sigc; ! 405: return; ! 406: } ! 407: ! 408: /* ! 409: * System call to cleanup state after a signal ! 410: * has been taken. Reset signal mask and ! 411: * stack state from context left by sendsig (above). ! 412: * Return to previous pc and psl as specified by ! 413: * context left by sendsig. Check carefully to ! 414: * make sure that the user has not modified the ! 415: * psl to gain improper priviledges or to cause ! 416: * a machine fault. ! 417: */ ! 418: /* ARGSUSED */ ! 419: sigreturn(p, uap, retval) ! 420: struct proc *p; ! 421: struct args { ! 422: struct sigcontext *sigcntxp; ! 423: } *uap; ! 424: int *retval; ! 425: { ! 426: register struct sigcontext *scp; ! 427: register int *regs = u.u_ar0; ! 428: ! 429: scp = uap->sigcntxp; ! 430: if (useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0) ! 431: return (EINVAL); ! 432: if ((scp->sc_ps & (PSL_MBZ|PSL_IPL|PSL_IS)) != 0 || ! 433: (scp->sc_ps & (PSL_PRVMOD|PSL_CURMOD)) != (PSL_PRVMOD|PSL_CURMOD) || ! 434: ((scp->sc_ps & PSL_CM) && ! 435: (scp->sc_ps & (PSL_FPD|PSL_DV|PSL_FU|PSL_IV)) != 0)) ! 436: return (EINVAL); ! 437: u.u_onstack = scp->sc_onstack & 01; ! 438: p->p_sigmask = scp->sc_mask &~ sigcantmask; ! 439: regs[FP] = scp->sc_fp; ! 440: regs[AP] = scp->sc_ap; ! 441: regs[SP] = scp->sc_sp; ! 442: regs[PC] = scp->sc_pc; ! 443: regs[PS] = scp->sc_ps; ! 444: return (EJUSTRETURN); ! 445: } ! 446: ! 447: /* ! 448: * Memenable enables memory controller corrected data reporting. ! 449: * This runs at regular intervals, turning on the interrupt. ! 450: * The interrupt is turned off, per memory controller, when error ! 451: * reporting occurs. Thus we report at most once per memintvl. ! 452: */ ! 453: int memintvl = MEMINTVL; ! 454: ! 455: memenable() ! 456: { ! 457: ! 458: (*cpuops->cpu_memenable)(); ! 459: if (memintvl > 0) ! 460: timeout(memenable, (caddr_t)0, memintvl*hz); ! 461: } ! 462: ! 463: /* ! 464: * Memerr is the interrupt routine for corrected read data ! 465: * interrupts. It looks to see which memory controllers have ! 466: * unreported errors, reports them, and disables further ! 467: * reporting for a time on those controller. ! 468: */ ! 469: memerr() ! 470: { ! 471: ! 472: (*cpuops->cpu_memerr)(); ! 473: } ! 474: ! 475: /* ! 476: * Invalidate single all pte's in a cluster ! 477: */ ! 478: tbiscl(v) ! 479: unsigned v; ! 480: { ! 481: register caddr_t addr; /* must be first reg var */ ! 482: register int i; ! 483: ! 484: asm(".set TBIS,58"); ! 485: addr = ptob(v); ! 486: for (i = 0; i < CLSIZE; i++) { ! 487: #ifdef lint ! 488: mtpr(TBIS, addr); ! 489: #else ! 490: asm("mtpr r11,$TBIS"); ! 491: #endif ! 492: addr += NBPG; ! 493: } ! 494: } ! 495: ! 496: int waittime = -1; ! 497: ! 498: boot(howto) ! 499: register int howto; /* r11 == how to boot */ ! 500: { ! 501: register int devtype; /* r10 == major of root dev */ ! 502: extern char *panicstr; ! 503: ! 504: if ((howto&RB_NOSYNC)==0 && waittime < 0 && bfreelist[0].b_forw) { ! 505: register struct buf *bp; ! 506: int iter, nbusy; ! 507: ! 508: waittime = 0; ! 509: (void) splnet(); ! 510: printf("syncing disks... "); ! 511: /* ! 512: * Release vnodes held by texts before sync. ! 513: */ ! 514: if (panicstr == 0) ! 515: xumount(NULL); ! 516: sync(); ! 517: ! 518: for (iter = 0; iter < 20; iter++) { ! 519: nbusy = 0; ! 520: for (bp = &buf[nbuf]; --bp >= buf; ) ! 521: if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY) ! 522: nbusy++; ! 523: if (nbusy == 0) ! 524: break; ! 525: printf("%d ", nbusy); ! 526: DELAY(40000 * iter); ! 527: } ! 528: if (nbusy) ! 529: printf("giving up\n"); ! 530: else ! 531: printf("done\n"); ! 532: /* ! 533: * If we've been adjusting the clock, the todr ! 534: * will be out of synch; adjust it now. ! 535: */ ! 536: resettodr(); ! 537: } ! 538: splx(0x1f); /* extreme priority */ ! 539: devtype = major(rootdev); ! 540: if (howto&RB_HALT) { ! 541: switch (cpu) { ! 542: ! 543: /* 630 can be told to halt, but how? */ ! 544: #if VAX650 ! 545: case VAX_650: ! 546: ka650ssc.ssc_cpmbx &= ~CPMB650_HALTACT; ! 547: ka650ssc.ssc_cpmbx |= CPMB650_HALT; ! 548: asm("halt"); ! 549: #endif ! 550: } ! 551: printf("halting (in tight loop); hit\n\t^P\n\tHALT\n\n"); ! 552: for (;;) ! 553: ; ! 554: } else { ! 555: if (howto & RB_DUMP) ! 556: doadump(); ! 557: vaxboot(); ! 558: } ! 559: #ifdef lint ! 560: devtype = devtype; ! 561: #endif ! 562: /*NOTREACHED*/ ! 563: } ! 564: ! 565: /* ! 566: * Reboot after panic or via reboot system call. Note that r11 ! 567: * and r10 must already have the proper boot values (`call by voodoo'). ! 568: */ ! 569: vaxboot() ! 570: { ! 571: ! 572: switch (cpu) { ! 573: ! 574: #ifdef VAX8200 ! 575: case VAX_8200: ! 576: /* ! 577: * TXDB_BOOT erases memory! Instead we set the `did ! 578: * a dump' flag in the rpb. ! 579: */ ! 580: *(int *)&Sysmap[0] &= ~PG_PROT; ! 581: *(int *)&Sysmap[0] |= PG_KW; ! 582: mtpr(TBIS, &rpb); ! 583: rpb.rp_flag = 1; ! 584: break; ! 585: #endif ! 586: ! 587: #ifdef VAX650 ! 588: case VAX_650: ! 589: /* set boot-on-halt flag in "console mailbox" */ ! 590: ka650ssc.ssc_cpmbx &= ~CPMB650_HALTACT; ! 591: ka650ssc.ssc_cpmbx |= CPMB650_REBOOT; ! 592: break; ! 593: #endif ! 594: ! 595: default: ! 596: tocons(TXDB_BOOT); ! 597: } ! 598: ! 599: /* ! 600: * Except on 780s and 8600s, boot flags go in r5. SBI ! 601: * VAXen do not care, so copy boot flags to r5 always. ! 602: */ ! 603: asm("movl r11,r5"); ! 604: for (;;) { ! 605: asm("halt"); ! 606: } ! 607: } ! 608: ! 609: tocons(c) ! 610: { ! 611: register int oldmask; ! 612: ! 613: while (((oldmask = mfpr(TXCS)) & TXCS_RDY) == 0) ! 614: continue; ! 615: ! 616: switch (cpu) { ! 617: ! 618: #if VAX8200 || VAX780 || VAX750 || VAX730 || VAX630 ! 619: case VAX_8200: ! 620: case VAX_780: ! 621: case VAX_750: ! 622: case VAX_730: ! 623: case VAX_630: ! 624: c |= TXDB_CONS; ! 625: break; ! 626: #endif ! 627: ! 628: #if VAX8600 ! 629: case VAX_8600: ! 630: mtpr(TXCS, TXCS_LCONS | TXCS_WMASK); ! 631: while ((mfpr(TXCS) & TXCS_RDY) == 0) ! 632: continue; ! 633: break; ! 634: #endif ! 635: ! 636: #if VAX650 ! 637: case VAX_650: ! 638: /* everything is a real console terminal character on ka650 */ ! 639: return; ! 640: #endif ! 641: } ! 642: ! 643: mtpr(TXDB, c); ! 644: ! 645: #if VAX8600 ! 646: switch (cpu) { ! 647: ! 648: case VAX_8600: ! 649: while ((mfpr(TXCS) & TXCS_RDY) == 0) ! 650: continue; ! 651: mtpr(TXCS, oldmask | TXCS_WMASK); ! 652: break; ! 653: } ! 654: #endif ! 655: #ifdef lint ! 656: oldmask = oldmask; ! 657: #endif ! 658: } ! 659: ! 660: int dumpmag = 0x8fca0101; /* magic number for savecore */ ! 661: int dumpsize = 0; /* also for savecore */ ! 662: ! 663: dumpconf() ! 664: { ! 665: int nblks; ! 666: ! 667: dumpsize = physmem; ! 668: if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) { ! 669: nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev); ! 670: if (dumpsize > btoc(dbtob(nblks - dumplo))) ! 671: dumpsize = btoc(dbtob(nblks - dumplo)); ! 672: else if (dumplo == 0) ! 673: dumplo = nblks - btodb(ctob(physmem)); ! 674: } ! 675: /* ! 676: * Don't dump on the first CLSIZE pages, ! 677: * in case the dump device includes a disk label. ! 678: */ ! 679: if (dumplo < CLSIZE) ! 680: dumplo = CLSIZE; ! 681: } ! 682: ! 683: /* ! 684: * Doadump comes here after turning off memory management and ! 685: * getting on the dump stack, either when called above, or by ! 686: * the auto-restart code. ! 687: */ ! 688: dumpsys() ! 689: { ! 690: ! 691: rpb.rp_flag = 1; ! 692: msgbufmapped = 0; ! 693: if (dumpdev == NODEV) ! 694: return; ! 695: /* ! 696: * For dumps during autoconfiguration, ! 697: * if dump device has already configured... ! 698: */ ! 699: if (dumpsize == 0) ! 700: dumpconf(); ! 701: if (dumplo < 0) ! 702: return; ! 703: printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo); ! 704: printf("dump "); ! 705: switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) { ! 706: ! 707: case ENXIO: ! 708: printf("device bad\n"); ! 709: break; ! 710: ! 711: case EFAULT: ! 712: printf("device not ready\n"); ! 713: break; ! 714: ! 715: case EINVAL: /* XXX */ ! 716: printf("area improper\n"); ! 717: break; ! 718: ! 719: case EIO: ! 720: printf("i/o error"); ! 721: break; ! 722: ! 723: default: ! 724: printf("succeeded"); ! 725: break; ! 726: } ! 727: } ! 728: ! 729: /* ! 730: * Machine check error recovery code. ! 731: */ ! 732: machinecheck(cmcf) ! 733: caddr_t cmcf; ! 734: { ! 735: ! 736: if ((*cpuops->cpu_mchk)(cmcf) == MCHK_RECOVERED) ! 737: return; ! 738: (*cpuops->cpu_memerr)(); ! 739: panic("mchk"); ! 740: } ! 741: ! 742: #if defined(VAX780) || defined(VAX750) ! 743: /* ! 744: * These strings are shared between the 780 and 750 machine check code ! 745: * in ka780.c and ka730.c. ! 746: */ ! 747: char *mc780750[16] = { ! 748: "cp read", "ctrl str par", "cp tbuf par", "cp cache par", ! 749: "cp rdtimo", "cp rds", "ucode lost", 0, ! 750: 0, 0, "ib tbuf par", 0, ! 751: "ib rds", "ib rd timo", 0, "ib cache par" ! 752: }; ! 753: #endif ! 754: ! 755: /* ! 756: * Return the best possible estimate of the time in the timeval ! 757: * to which tvp points. We do this by reading the interval count ! 758: * register to determine the time remaining to the next clock tick. ! 759: * We must compensate for wraparound which is not yet reflected in the time ! 760: * (which happens when the ICR hits 0 and wraps after the splhigh(), ! 761: * but before the mfpr(ICR)). Also check that this time is no less than ! 762: * any previously-reported time, which could happen around the time ! 763: * of a clock adjustment. Just for fun, we guarantee that the time ! 764: * will be greater than the value obtained by a previous call. ! 765: */ ! 766: microtime(tvp) ! 767: register struct timeval *tvp; ! 768: { ! 769: int s = splhigh(); ! 770: static struct timeval lasttime; ! 771: register long t; ! 772: ! 773: *tvp = time; ! 774: t = mfpr(ICR); ! 775: if (t < -tick / 2 && (mfpr(ICCS) & ICCS_INT)) ! 776: t += tick; ! 777: tvp->tv_usec += tick + t; ! 778: if (tvp->tv_usec > 1000000) { ! 779: tvp->tv_sec++; ! 780: tvp->tv_usec -= 1000000; ! 781: } ! 782: if (tvp->tv_sec == lasttime.tv_sec && ! 783: tvp->tv_usec <= lasttime.tv_usec && ! 784: (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) { ! 785: tvp->tv_sec++; ! 786: tvp->tv_usec -= 1000000; ! 787: } ! 788: lasttime = *tvp; ! 789: splx(s); ! 790: } ! 791: ! 792: initcpu() ! 793: { ! 794: /* ! 795: * Enable cache. ! 796: */ ! 797: switch (cpu) { ! 798: ! 799: #if VAX8600 ! 800: case VAX_8600: ! 801: mtpr(CSWP, 3); ! 802: break; ! 803: #endif ! 804: #if VAX8200 ! 805: case VAX_8200: ! 806: mtpr(CADR, 0); ! 807: break; ! 808: #endif ! 809: #if VAX780 ! 810: case VAX_780: ! 811: mtpr(SBIMT, 0x200000); ! 812: break; ! 813: #endif ! 814: #if VAX750 ! 815: case VAX_750: ! 816: mtpr(CADR, 0); ! 817: break; ! 818: #endif ! 819: default: ! 820: break; ! 821: } ! 822: ! 823: /* ! 824: * Enable floating point accelerator if it exists ! 825: * and has control register. ! 826: */ ! 827: switch(cpu) { ! 828: ! 829: #if VAX8600 || VAX780 ! 830: case VAX_8600: ! 831: case VAX_780: ! 832: if ((mfpr(ACCS) & 0xff) != 0) { ! 833: printf("Enabling FPA\n"); ! 834: mtpr(ACCS, 0x8000); ! 835: } ! 836: #endif ! 837: default: ! 838: break; ! 839: } ! 840: } ! 841: ! 842: /* ! 843: * Return a reasonable approximation of the time of day register. ! 844: * More precisely, return a number that increases by one about ! 845: * once every ten milliseconds. ! 846: */ ! 847: todr() ! 848: { ! 849: ! 850: switch (cpu) { ! 851: ! 852: #if VAX8600 || VAX8200 || VAX780 || VAX750 || VAX730 || VAX650 ! 853: case VAX_8600: ! 854: case VAX_8200: ! 855: case VAX_780: ! 856: case VAX_750: ! 857: case VAX_730: ! 858: case VAX_650: ! 859: return (mfpr(TODR)); ! 860: #endif ! 861: ! 862: #if VAX630 ! 863: case VAX_630: ! 864: /* XXX crude */ ! 865: { static int t; DELAY(10000); return (++t); } ! 866: #endif ! 867: ! 868: default: ! 869: panic("todr"); ! 870: } ! 871: /* NOTREACHED */ ! 872: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.