|
|
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.