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