xref: /original-bsd/sys/vax/vax/machdep.c (revision 3708840b)
1 /*	machdep.c	4.78	83/05/21	*/
2 
3 #include "../machine/reg.h"
4 #include "../machine/pte.h"
5 #include "../machine/psl.h"
6 
7 #include "../h/param.h"
8 #include "../h/systm.h"
9 #include "../h/dir.h"
10 #include "../h/user.h"
11 #include "../h/kernel.h"
12 #include "../h/map.h"
13 #include "../h/vm.h"
14 #include "../h/proc.h"
15 #include "../h/buf.h"
16 #include "../h/reboot.h"
17 #include "../h/conf.h"
18 #include "../h/inode.h"
19 #include "../h/file.h"
20 #include "../h/text.h"
21 #include "../h/clist.h"
22 #include "../h/callout.h"
23 #include "../h/cmap.h"
24 #include "../h/mbuf.h"
25 #include "../h/msgbuf.h"
26 #include "../h/quota.h"
27 
28 #include "../vax/frame.h"
29 #include "../vax/cons.h"
30 #include "../vax/cpu.h"
31 #include "../vax/mem.h"
32 #include "../vax/mtpr.h"
33 #include "../vax/rpb.h"
34 #include "../vaxuba/ubavar.h"
35 #include "../vaxuba/ubareg.h"
36 
37 int	icode[] =
38 {
39 	0x9f19af9f,	/* pushab [&"init",0]; pushab */
40 	0x02dd09af,	/* "/etc/init"; pushl $2 */
41 	0xbc5c5ed0,	/* movl sp,ap; chmk */
42 	0x2ffe110b,	/* $exec; brb .; "/ */
43 	0x2f637465,	/* etc/ */
44 	0x74696e69,	/* init" */
45 	0x00000000,	/* \0\0\0";  0 */
46 	0x00000014,	/* [&"init", */
47 	0x00000000,	/* 0] */
48 };
49 int	szicode = sizeof(icode);
50 
51 /*
52  * Declare these as initialized data so we can patch them.
53  */
54 int	nbuf = 0;
55 int	nswbuf = 0;
56 int	bufpages = 0;
57 
58 /*
59  * Machine-dependent startup code
60  */
61 startup(firstaddr)
62 	int firstaddr;
63 {
64 	register int unixsize;
65 	register unsigned i;
66 	register struct pte *pte;
67 	int mapaddr, j;
68 	register caddr_t v;
69 	int maxbufs, base, residual;
70 	extern char etext;
71 
72 	/*
73 	 * Initialize error message buffer (at end of core).
74 	 */
75 	maxmem -= btoc(sizeof (struct msgbuf));
76 	pte = msgbufmap;
77 	for (i = 0; i < btoc(sizeof (struct msgbuf)); i++)
78 		*(int *)pte++ = PG_V | PG_KW | (maxmem + i);
79 	mtpr(TBIA, 1);
80 
81 	/*
82 	 * Good {morning,afternoon,evening,night}.
83 	 */
84 	printf(version);
85 	printf("real mem  = %d\n", ctob(maxmem));
86 
87 	/*
88 	 * Determine how many buffers to allocate.
89 	 * Use 10% of memory, with min of 16.
90 	 * We allocate 1/2 as many swap buffer headers as file i/o buffers.
91 	 */
92 	maxbufs = ((SYSPTSIZE * NBPG) - (5 * (int)(&etext - 0x80000000))) /
93 	    MAXBSIZE;
94 	if (bufpages == 0)
95 		bufpages = (physmem * NBPG) / 10 / CLBYTES;
96 	if (nbuf == 0) {
97 		nbuf = bufpages / 2;
98 		if (nbuf < 16)
99 			nbuf = 16;
100 		if (nbuf > maxbufs)
101 			nbuf = maxbufs;
102 	}
103 	if (bufpages > nbuf * (MAXBSIZE / CLBYTES))
104 		bufpages = nbuf * (MAXBSIZE / CLBYTES);
105 	if (nswbuf == 0) {
106 		nswbuf = (nbuf / 2) &~ 1;	/* force even */
107 		if (nswbuf > 256)
108 			nswbuf = 256;		/* sanity */
109 	}
110 
111 	/*
112 	 * Allocate space for system data structures.
113 	 * The first available real memory address is in "firstaddr".
114 	 * As pages of memory are allocated, "firstaddr" is incremented.
115 	 * The first available kernel virtual address is in "v".
116 	 * As pages of kernel virtual memory are allocated, "v" is incremented.
117 	 * An index into the kernel page table corresponding to the
118 	 * virtual memory address maintained in "v" is kept in "mapaddr".
119 	 */
120 	mapaddr = firstaddr;
121 	v = (caddr_t)(0x80000000 | (firstaddr * NBPG));
122 #define	valloc(name, type, num) \
123 	    (name) = (type *)(v); (v) = (caddr_t)((name)+(num))
124 #define	valloclim(name, type, num, lim) \
125 	    (name) = (type *)(v); (v) = (caddr_t)((lim) = ((name)+(num)))
126 	valloc(buffers, char, MAXBSIZE * nbuf);
127 	base = bufpages / nbuf;
128 	residual = bufpages % nbuf;
129 	for (i = 0; i < residual; i++) {
130 		for (j = 0; j < (base + 1) * CLSIZE; j++) {
131 			*(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr;
132 			clearseg((unsigned)firstaddr);
133 			firstaddr++;
134 		}
135 		mapaddr += MAXBSIZE / NBPG;
136 	}
137 	for (i = residual; i < nbuf; i++) {
138 		for (j = 0; j < base * CLSIZE; j++) {
139 			*(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr;
140 			clearseg((unsigned)firstaddr);
141 			firstaddr++;
142 		}
143 		mapaddr += MAXBSIZE / NBPG;
144 	}
145 	valloc(buf, struct buf, nbuf);
146 	valloc(swbuf, struct buf, nswbuf);
147 	valloclim(inode, struct inode, ninode, inodeNINODE);
148 	valloclim(file, struct file, nfile, fileNFILE);
149 	valloclim(proc, struct proc, nproc, procNPROC);
150 	valloclim(text, struct text, ntext, textNTEXT);
151 	valloc(cfree, struct cblock, nclist);
152 	valloc(callout, struct callout, ncallout);
153 	valloc(swapmap, struct map, nswapmap = nproc * 2);
154 	valloc(argmap, struct map, ARGMAPSIZE);
155 	valloc(kernelmap, struct map, nproc);
156 	valloc(mbmap, struct map, nmbclusters/4);
157 #ifdef QUOTA
158 	valloclim(quota, struct quota, nquota, quotaNQUOTA);
159 	valloclim(dquot, struct dquot, ndquot, dquotNDQUOT);
160 #endif
161 	/*
162 	 * Now allocate space for core map
163 	 * Allow space for all of phsical memory minus the amount
164 	 * dedicated to the system. The amount of physical memory
165 	 * dedicated to the system is the total virtual memory of
166 	 * the system minus the space in the buffers which is not
167 	 * allocated real memory.
168 	 */
169 	ncmap = (physmem*NBPG - ((int)v &~ 0x80000000) +
170 		(nbuf * (MAXBSIZE - 2 * CLBYTES))) /
171 		    (NBPG*CLSIZE + sizeof (struct cmap));
172 	valloclim(cmap, struct cmap, ncmap, ecmap);
173 	if ((((int)(ecmap+1))&~0x80000000) > SYSPTSIZE*NBPG)
174 		panic("sys pt too small");
175 
176 	/*
177 	 * Clear allocated space, and make r/w entries
178 	 * for the space in the kernel map.
179 	 */
180 	unixsize = btoc((int)(ecmap+1) &~ 0x80000000);
181 	for (i = mapaddr; i < unixsize; i++) {
182 		*(int *)(&Sysmap[i]) = PG_V | PG_KW | firstaddr;
183 		clearseg((unsigned)firstaddr);
184 		firstaddr++;
185 	}
186 	if (firstaddr >= physmem - 8*UPAGES)
187 		panic("no memory");
188 	mtpr(TBIA, 1);
189 
190 	/*
191 	 * Initialize callouts
192 	 */
193 	callfree = callout;
194 	for (i = 1; i < ncallout; i++)
195 		callout[i-1].c_next = &callout[i];
196 
197 	/*
198 	 * Initialize memory allocator and swap
199 	 * and user page table maps.
200 	 *
201 	 * THE USER PAGE TABLE MAP IS CALLED ``kernelmap''
202 	 * WHICH IS A VERY UNDESCRIPTIVE AND INCONSISTENT NAME.
203 	 */
204 	meminit(firstaddr, maxmem);
205 	maxmem = freemem;
206 	printf("avail mem = %d\n", ctob(maxmem));
207 	printf("using %d buffers containing %d bytes of memory\n",
208 		nbuf, bufpages * CLBYTES);
209 	rminit(kernelmap, (long)USRPTSIZE, (long)1,
210 	    "usrpt", nproc);
211 	rminit(mbmap, (long)((nmbclusters - 1) * CLSIZE), (long)CLSIZE,
212 	    "mbclusters", nmbclusters/4);
213 
214 	/*
215 	 * Configure the system.
216 	 */
217 	configure();
218 
219 	/*
220 	 * Clear restart inhibit flags.
221 	 */
222 	tocons(TXDB_CWSI);
223 	tocons(TXDB_CCSI);
224 }
225 
226 #ifdef PGINPROF
227 /*
228  * Return the difference (in microseconds)
229  * between the  current time and a previous
230  * time as represented  by the arguments.
231  * If there is a pending clock interrupt
232  * which has not been serviced due to high
233  * ipl, return error code.
234  */
235 vmtime(otime, olbolt, oicr)
236 	register int otime, olbolt, oicr;
237 {
238 
239 	if (mfpr(ICCS)&ICCS_INT)
240 		return(-1);
241 	else
242 		return(((time.tv_sec-otime)*60 + lbolt-olbolt)*16667 + mfpr(ICR)-oicr);
243 }
244 #endif
245 
246 /*
247  * Send an interrupt to process
248  *
249  * SHOULD CHANGE THIS TO PASS ONE MORE WORD SO THAT ALL INFORMATION
250  * PROVIDED BY HARDWARE IS AVAILABLE TO THE USER PROCESS.
251  */
252 sendsig(p, n)
253 	int (*p)();
254 {
255 	register int *usp, *regs;
256 
257 	regs = u.u_ar0;
258 	usp = (int *)regs[SP];
259 	usp -= 5;
260 	if ((int)usp <= USRSTACK - ctob(u.u_ssize))
261 		(void) grow((unsigned)usp);
262 	;			/* Avoid asm() label botch */
263 #ifndef lint
264 	asm("probew $3,$20,(r11)");
265 	asm("beql bad");
266 #else
267 	if (useracc((caddr_t)usp, 0x20, 1))
268 		goto bad;
269 #endif
270 	*usp++ = n;
271 	if (n == SIGILL || n == SIGFPE) {
272 		*usp++ = u.u_code;
273 		u.u_code = 0;
274 	} else
275 		*usp++ = 0;
276 	*usp++ = (int)p;
277 	*usp++ = regs[PC];
278 	*usp++ = regs[PS];
279 	regs[SP] = (int)(usp - 5);
280 	regs[PS] &= ~(PSL_CM|PSL_FPD);
281 	regs[PC] = (int)u.u_pcb.pcb_sigc;
282 	return;
283 
284 asm("bad:");
285 bad:
286 	/*
287 	 * Process has trashed its stack; give it an illegal
288 	 * instruction to halt it in its tracks.
289 	 */
290 	u.u_signal[SIGILL] = SIG_DFL;
291 	u.u_procp->p_siga0 &= ~(1<<(SIGILL-1));
292 	u.u_procp->p_siga1 &= ~(1<<(SIGILL-1));
293 	psignal(u.u_procp, SIGILL);
294 }
295 
296 dorti()
297 {
298 	struct frame frame;
299 	register int sp;
300 	register int reg, mask;
301 	extern int ipcreg[];
302 
303 	(void) copyin((caddr_t)u.u_ar0[FP], (caddr_t)&frame, sizeof (frame));
304 	sp = u.u_ar0[FP] + sizeof (frame);
305 	u.u_ar0[PC] = frame.fr_savpc;
306 	u.u_ar0[FP] = frame.fr_savfp;
307 	u.u_ar0[AP] = frame.fr_savap;
308 	mask = frame.fr_mask;
309 	for (reg = 0; reg <= 11; reg++) {
310 		if (mask&1) {
311 			u.u_ar0[ipcreg[reg]] = fuword((caddr_t)sp);
312 			sp += 4;
313 		}
314 		mask >>= 1;
315 	}
316 	sp += frame.fr_spa;
317 	u.u_ar0[PS] = (u.u_ar0[PS] & 0xffff0000) | frame.fr_psw;
318 	if (frame.fr_s)
319 		sp += 4 + 4 * (fuword((caddr_t)sp) & 0xff);
320 	/* phew, now the rei */
321 	u.u_ar0[PC] = fuword((caddr_t)sp);
322 	sp += 4;
323 	u.u_ar0[PS] = fuword((caddr_t)sp);
324 	sp += 4;
325 	u.u_ar0[PS] |= PSL_USERSET;
326 	u.u_ar0[PS] &= ~PSL_USERCLR;
327 	u.u_ar0[SP] = (int)sp;
328 }
329 
330 /*
331  * Memenable enables the memory controlle corrected data reporting.
332  * This runs at regular intervals, turning on the interrupt.
333  * The interrupt is turned off, per memory controller, when error
334  * reporting occurs.  Thus we report at most once per memintvl.
335  */
336 int	memintvl = MEMINTVL;
337 
338 memenable()
339 {
340 	register struct mcr *mcr;
341 	register int m;
342 
343 	for (m = 0; m < nmcr; m++) {
344 		mcr = mcraddr[m];
345 		switch (cpu) {
346 #if VAX780
347 		case VAX_780:
348 			M780_ENA(mcr);
349 			break;
350 #endif
351 #if VAX750
352 		case VAX_750:
353 			M750_ENA(mcr);
354 			break;
355 #endif
356 #if VAX730
357 		case VAX_730:
358 			M730_ENA(mcr);
359 			break;
360 #endif
361 		}
362 	}
363 	if (memintvl > 0)
364 		timeout(memenable, (caddr_t)0, memintvl);
365 }
366 
367 /*
368  * Memerr is the interrupt routine for corrected read data
369  * interrupts.  It looks to see which memory controllers have
370  * unreported errors, reports them, and disables further
371  * reporting for a time on those controller.
372  */
373 memerr()
374 {
375 	register struct mcr *mcr;
376 	register int m;
377 
378 	for (m = 0; m < nmcr; m++) {
379 		mcr = mcraddr[m];
380 		switch (cpu) {
381 #if VAX780
382 		case VAX_780:
383 			if (M780_ERR(mcr)) {
384 				printf("mcr%d: soft ecc addr %x syn %x\n",
385 				    m, M780_ADDR(mcr), M780_SYN(mcr));
386 #ifdef TRENDATA
387 				memlog(m, mcr);
388 #endif
389 				M780_INH(mcr);
390 			}
391 			break;
392 #endif
393 #if VAX750
394 		case VAX_750:
395 			if (M750_ERR(mcr)) {
396 #ifdef notdef
397 				printf("mcr%d: soft ecc addr %x syn %x\n",
398 				    m, M750_ADDR(mcr), M750_SYN(mcr));
399 #endif
400 				M750_INH(mcr);
401 			}
402 			break;
403 #endif
404 #if VAX730
405 		case VAX_730:
406 			if (M730_ERR(mcr)) {
407 				struct mcr amcr;
408 				amcr.mc_reg[0] = mcr->mc_reg[0];
409 				printf("mcr%d: soft ecc addr %x syn %x\n",
410 				    m, M730_ADDR(&amcr), M730_SYN(&amcr));
411 				M730_INH(mcr);
412 			}
413 			break;
414 #endif
415 		}
416 	}
417 }
418 
419 #ifdef TRENDATA
420 /*
421  * Figure out what chip to replace on Trendata boards.
422  * Assumes all your memory is Trendata or the non-Trendata
423  * memory never fails..
424  */
425 struct {
426 	u_char	m_syndrome;
427 	char	m_chip[4];
428 } memlogtab[] = {
429 	0x01,	"C00",	0x02,	"C01",	0x04,	"C02",	0x08,	"C03",
430 	0x10,	"C04",	0x19,	"L01",	0x1A,	"L02",	0x1C,	"L04",
431 	0x1F,	"L07",	0x20,	"C05",	0x38,	"L00",	0x3B,	"L03",
432 	0x3D,	"L05",	0x3E,	"L06",	0x40,	"C06",	0x49,	"L09",
433 	0x4A,	"L10",	0x4c,	"L12",	0x4F,	"L15",	0x51,	"L17",
434 	0x52,	"L18",	0x54,	"L20",	0x57,	"L23",	0x58,	"L24",
435 	0x5B,	"L27",	0x5D,	"L29",	0x5E,	"L30",	0x68,	"L08",
436 	0x6B,	"L11",	0x6D,	"L13",	0x6E,	"L14",	0x70,	"L16",
437 	0x73,	"L19",	0x75,	"L21",	0x76,	"L22",	0x79,	"L25",
438 	0x7A,	"L26",	0x7C,	"L28",	0x7F,	"L31",	0x80,	"C07",
439 	0x89,	"U01",	0x8A,	"U02",	0x8C,	"U04",	0x8F,	"U07",
440 	0x91,	"U09",	0x92,	"U10",	0x94,	"U12",	0x97, 	"U15",
441 	0x98,	"U16",	0x9B,	"U19",	0x9D,	"U21",	0x9E, 	"U22",
442 	0xA8,	"U00",	0xAB,	"U03",	0xAD,	"U05",	0xAE,	"U06",
443 	0xB0,	"U08",	0xB3,	"U11",	0xB5,	"U13",	0xB6,	"U14",
444 	0xB9,	"U17",	0xBA,	"U18",	0xBC,	"U20",	0xBF,	"U23",
445 	0xC1,	"U25",	0xC2,	"U26",	0xC4,	"U28",	0xC7,	"U31",
446 	0xE0,	"U24",	0xE3,	"U27",	0xE5,	"U29",	0xE6,	"U30"
447 };
448 
449 memlog (m, mcr)
450 	int m;
451 	struct mcr *mcr;
452 {
453 	register i;
454 
455 	switch (cpu) {
456 
457 #if VAX780
458 	case VAX_780:
459 	for (i = 0; i < (sizeof (memlogtab) / sizeof (memlogtab[0])); i++)
460 		if ((u_char)(M780_SYN(mcr)) == memlogtab[i].m_syndrome) {
461 			printf (
462 	"mcr%d: replace %s chip in %s bank of memory board %d (0-15)\n",
463 				m,
464 				memlogtab[i].m_chip,
465 				(M780_ADDR(mcr) & 0x8000) ? "upper" : "lower",
466 				(M780_ADDR(mcr) >> 16));
467 			return;
468 		}
469 	printf ("mcr%d: multiple errors, not traceable\n", m);
470 	break;
471 #endif
472 	}
473 }
474 #endif
475 
476 /*
477  * Invalidate single all pte's in a cluster
478  */
479 tbiscl(v)
480 	unsigned v;
481 {
482 	register caddr_t addr;		/* must be first reg var */
483 	register int i;
484 
485 	asm(".set TBIS,58");
486 	addr = ptob(v);
487 	for (i = 0; i < CLSIZE; i++) {
488 #ifdef lint
489 		mtpr(TBIS, addr);
490 #else
491 		asm("mtpr r11,$TBIS");
492 #endif
493 		addr += NBPG;
494 	}
495 }
496 
497 int	waittime = -1;
498 
499 boot(paniced, arghowto)
500 	int paniced, arghowto;
501 {
502 	register int howto;		/* r11 == how to boot */
503 	register int devtype;		/* r10 == major of root dev */
504 
505 #ifdef lint
506 	howto = 0; devtype = 0;
507 	printf("howto %d, devtype %d\n", arghowto, devtype);
508 #endif
509 	(void) spl1();
510 	howto = arghowto;
511 	if ((howto&RB_NOSYNC)==0 && waittime < 0 && bfreelist[0].b_forw) {
512 		waittime = 0;
513 		update();
514 		printf("syncing disks... ");
515 #ifdef notdef
516 		{ register struct buf *bp;
517 		  int iter, nbusy;
518 
519 		  for (iter = 0; iter < 10; iter++) {
520 			nbusy = 0;
521 			for (bp = &buf[nbuf]; --bp >= buf; )
522 				if (bp->b_flags & B_BUSY)
523 					nbusy++;
524 			if (nbusy == 0)
525 				break;
526 			printf("%d ", nbusy);
527 		  }
528 		}
529 #else
530 		DELAY(10000000);
531 #endif
532 		printf("done\n");
533 	}
534 	splx(0x1f);			/* extreme priority */
535 	devtype = major(rootdev);
536 	if (howto&RB_HALT) {
537 		printf("halting (in tight loop); hit\n\t^P\n\tHALT\n\n");
538 		mtpr(IPL, 0x1f);
539 		for (;;)
540 			;
541 	} else {
542 		if (paniced == RB_PANIC) {
543 			doadump();		/* TXDB_BOOT's itsself */
544 			/*NOTREACHED*/
545 		}
546 		tocons(TXDB_BOOT);
547 	}
548 #if defined(VAX750) || defined(VAX730)
549 	if (cpu != VAX_780)
550 		{ asm("movl r11,r5"); }		/* boot flags go in r5 */
551 #endif
552 	for (;;)
553 		asm("halt");
554 	/*NOTREACHED*/
555 }
556 
557 tocons(c)
558 {
559 
560 	while ((mfpr(TXCS)&TXCS_RDY) == 0)
561 		continue;
562 	mtpr(TXDB, c);
563 }
564 
565 int	dumpmag = 0x8fca0101;	/* magic number for savecore */
566 int	dumpsize = 0;		/* also for savecore */
567 /*
568  * Doadump comes here after turning off memory management and
569  * getting on the dump stack, either when called above, or by
570  * the auto-restart code.
571  */
572 dumpsys()
573 {
574 
575 	rpb.rp_flag = 1;
576 	if ((minor(dumpdev)&07) != 1)
577 		return;
578 	dumpsize = physmem;
579 	printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
580 	printf("dump ");
581 	switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
582 
583 	case ENXIO:
584 		printf("device bad\n");
585 		break;
586 
587 	case EFAULT:
588 		printf("device not ready\n");
589 		break;
590 
591 	case EINVAL:
592 		printf("area improper\n");
593 		break;
594 
595 	case EIO:
596 		printf("i/o error");
597 		break;
598 
599 	default:
600 		printf("succeeded");
601 		break;
602 	}
603 }
604 
605 /*
606  * Machine check error recovery code.
607  * Print out the machine check frame and then give up.
608  */
609 #if defined(VAX780) || defined(VAX750)
610 char *mc780[] = {
611 	"cp read",	"ctrl str par",	"cp tbuf par",	"cp cache par",
612 	"cp rdtimo", 	"cp rds",	"ucode lost",	0,
613 	0,		0,		"ib tbuf par",	0,
614 	"ib rds",	"ib rd timo",	0,		"ib cache par"
615 };
616 #define	MC780_TBPAR	2
617 #define	MC750_TBPAR	2
618 #endif
619 #if VAX730
620 #define	NMC730	12
621 char *mc730[] = {
622 	"tb par",	"bad retry",	"bad intr id",	"cant write ptem",
623 	"unkn mcr err",	"iib rd err",	"nxm ref",	"cp rds",
624 	"unalgn ioref",	"nonlw ioref",	"bad ioaddr",	"unalgn ubaddr",
625 };
626 #define	MC730_TBPAR	0
627 #endif
628 
629 /*
630  * Frame for each cpu
631  */
632 struct mc780frame {
633 	int	mc8_bcnt;		/* byte count == 0x28 */
634 	int	mc8_summary;		/* summary parameter (as above) */
635 	int	mc8_cpues;		/* cpu error status */
636 	int	mc8_upc;		/* micro pc */
637 	int	mc8_vaviba;		/* va/viba register */
638 	int	mc8_dreg;		/* d register */
639 	int	mc8_tber0;		/* tbuf error reg 0 */
640 	int	mc8_tber1;		/* tbuf error reg 1 */
641 	int	mc8_timo;		/* timeout address divided by 4 */
642 	int	mc8_parity;		/* parity */
643 	int	mc8_sbier;		/* sbi error register */
644 	int	mc8_pc;			/* trapped pc */
645 	int	mc8_psl;		/* trapped psl */
646 };
647 struct mc750frame {
648 	int	mc5_bcnt;		/* byte count == 0x28 */
649 	int	mc5_summary;		/* summary parameter (as above) */
650 	int	mc5_va;			/* virtual address register */
651 	int	mc5_errpc;		/* error pc */
652 	int	mc5_mdr;
653 	int	mc5_svmode;		/* saved mode register */
654 	int	mc5_rdtimo;		/* read lock timeout */
655 	int	mc5_tbgpar;		/* tb group parity error register */
656 	int	mc5_cacherr;		/* cache error register */
657 	int	mc5_buserr;		/* bus error register */
658 	int	mc5_mcesr;		/* machine check status register */
659 	int	mc5_pc;			/* trapped pc */
660 	int	mc5_psl;		/* trapped psl */
661 };
662 struct mc730frame {
663 	int	mc3_bcnt;		/* byte count == 0xc */
664 	int	mc3_summary;		/* summary parameter */
665 	int	mc3_parm[2];		/* parameter 1 and 2 */
666 	int	mc3_pc;			/* trapped pc */
667 	int	mc3_psl;		/* trapped psl */
668 };
669 
670 machinecheck(cmcf)
671 	caddr_t cmcf;
672 {
673 	register u_int type = ((struct mc780frame *)cmcf)->mc8_summary;
674 
675 	printf("machine check %x: ", type);
676 	switch (cpu) {
677 #if VAX780
678 	case VAX_780:
679 #endif
680 #if VAX750
681 	case VAX_750:
682 #endif
683 #if defined(VAX780) || defined(VAX750)
684 		printf("%s%s\n", mc780[type&0xf],
685 		    (type&0xf0) ? " abort" : " fault");
686 		break;
687 #endif
688 #if VAX730
689 	case VAX_730:
690 		if (type < NMC730)
691 			printf("%s", mc730[type]);
692 		printf("\n");
693 		break;
694 #endif
695 	}
696 	switch (cpu) {
697 #if VAX780
698 	case VAX_780: {
699 		register struct mc780frame *mcf = (struct mc780frame *)cmcf;
700 		register int sbifs;
701 		printf("\tcpues %x upc %x va/viba %x dreg %x tber %x %x\n",
702 		   mcf->mc8_cpues, mcf->mc8_upc, mcf->mc8_vaviba,
703 		   mcf->mc8_dreg, mcf->mc8_tber0, mcf->mc8_tber1);
704 		sbifs = mfpr(SBIFS);
705 		printf("\ttimo %x parity %x sbier %x pc %x psl %x sbifs %x\n",
706 		   mcf->mc8_timo*4, mcf->mc8_parity, mcf->mc8_sbier,
707 		   mcf->mc8_pc, mcf->mc8_psl, sbifs);
708 		/* THE FUNNY BITS IN THE FOLLOWING ARE FROM THE ``BLACK */
709 		/* BOOK'' AND SHOULD BE PUT IN AN ``sbi.h'' */
710 		mtpr(SBIFS, sbifs &~ 0x2000000);
711 		mtpr(SBIER, mfpr(SBIER) | 0x70c0);
712 		break;
713 	}
714 #endif
715 #if VAX750
716 	case VAX_750: {
717 		register struct mc750frame *mcf = (struct mc750frame *)cmcf;
718 		printf("\tva %x errpc %x mdr %x smr %x rdtimo %x tbgpar %x cacherr %x\n",
719 		    mcf->mc5_va, mcf->mc5_errpc, mcf->mc5_mdr, mcf->mc5_svmode,
720 		    mcf->mc5_rdtimo, mcf->mc5_tbgpar, mcf->mc5_cacherr);
721 		printf("\tbuserr %x mcesr %x pc %x psl %x mcsr %x\n",
722 		    mcf->mc5_buserr, mcf->mc5_mcesr, mcf->mc5_pc, mcf->mc5_psl,
723 		    mfpr(MCSR));
724 		mtpr(MCESR, 0xf);
725 		if ((type&0xf)==MC750_TBPAR) {
726 			printf("tbuf par!?!: flushing and returning\n");
727 			mtpr(TBIA, 0);
728 			return;
729 		}
730 		break;
731 		}
732 #endif
733 #if VAX730
734 	case VAX_730: {
735 		register struct mc730frame *mcf = (struct mc730frame *)cmcf;
736 		printf("params %x,%x pc %x psl %x mcesr %x\n",
737 		    mcf->mc3_parm[0], mcf->mc3_parm[1],
738 		    mcf->mc3_pc, mcf->mc3_psl, mfpr(MCESR));
739 		mtpr(MCESR, 0xf);
740 		break;
741 		}
742 #endif
743 	}
744 	memerr();
745 	panic("mchk");
746 }
747 
748 #ifdef notdef
749 microtime(tvp)
750 	struct timeval *tvp;
751 {
752 	int s = spl7();
753 
754 	tvp->tv_sec = time.tv_sec;
755 	tvp->tv_usec = (lbolt+1)*16667 + mfpr(ICR);
756 	while (tvp->tv_usec > 1000000) {
757 		tvp->tv_sec++;
758 		tvp->tv_usec -= 1000000;
759 	}
760 	splx(s);
761 }
762 #endif
763 
764 physstrat(bp, strat, prio)
765 	struct buf *bp;
766 	int (*strat)(), prio;
767 {
768 	int s;
769 
770 	(*strat)(bp);
771 	/* pageout daemon doesn't wait for pushed pages */
772 	if (bp->b_flags & B_DIRTY)
773 		return;
774 	s = spl6();
775 	while ((bp->b_flags & B_DONE) == 0)
776 		sleep((caddr_t)bp, prio);
777 	splx(s);
778 }
779