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