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