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