xref: /original-bsd/sys/vax/vax/machdep.c (revision fbed46ce)
1 /*	machdep.c	4.52	82/03/15	*/
2 
3 #include "../h/param.h"
4 #include "../h/systm.h"
5 #include "../h/dir.h"
6 #include "../h/user.h"
7 #include "../h/map.h"
8 #include "../h/reg.h"
9 #include "../h/mtpr.h"
10 #include "../h/clock.h"
11 #include "../h/pte.h"
12 #include "../h/vm.h"
13 #include "../h/proc.h"
14 #include "../h/psl.h"
15 #include "../h/buf.h"
16 #include "../h/ubavar.h"
17 #include "../h/ubareg.h"
18 #include "../h/cons.h"
19 #include "../h/reboot.h"
20 #include "../h/conf.h"
21 #include "../h/mem.h"
22 #include "../h/cpu.h"
23 #include "../h/inode.h"
24 #include "../h/file.h"
25 #include "../h/text.h"
26 #include "../h/clist.h"
27 #include "../h/callout.h"
28 #include "../h/cmap.h"
29 #include <frame.h>
30 #include "../h/mbuf.h"
31 #include "../h/rpb.h"
32 #include "../h/msgbuf.h"
33 
34 int	icode[] =
35 {
36 	0x9f19af9f,	/* pushab [&"init",0]; pushab */
37 	0x02dd09af,	/* "/etc/init"; pushl $2 */
38 	0xbc5c5ed0,	/* movl sp,ap; chmk */
39 	0x2ffe110b,	/* $exec; brb .; "/ */
40 	0x2f637465,	/* etc/ */
41 	0x74696e69,	/* init" */
42 	0x00000000,	/* \0\0\0";  0 */
43 	0x00000014,	/* [&"init", */
44 	0x00000000,	/* 0] */
45 };
46 int	szicode = sizeof(icode);
47 
48 /*
49  * Declare these as initialized data so we can patch them.
50  */
51 int	nbuf = 0;
52 int	nswbuf = 0;
53 
54 /*
55  * Machine-dependent startup code
56  */
57 startup(firstaddr)
58 	int firstaddr;
59 {
60 	register int unixsize;
61 	register unsigned i;
62 	register struct pte *pte;
63 	register caddr_t v;
64 
65 	/*
66 	 * Initialize error message buffer (at end of core).
67 	 */
68 	maxmem -= btoc(sizeof (struct msgbuf));
69 	pte = msgbufmap;
70 	for (i = 0; i < btoc(sizeof (struct msgbuf)); i++)
71 		*(int *)pte++ = PG_V | PG_KW | (maxmem + i);
72 	mtpr(TBIA, 1);
73 
74 	/*
75 	 * Good {morning,afternoon,evening,night}.
76 	 */
77 	printf(version);
78 	printf("real mem  = %d\n", ctob(maxmem));
79 
80 	/*
81 	 * First determine how many buffers are reasonable.
82 	 * Current alg is 32 per megabyte, with min of 32.
83 	 * We allocate 1/2 as many swap buffer headers as file i/o buffers.
84 	 */
85 	if (nbuf == 0) {
86 		nbuf = (32 * physmem) / btoc(1024*1024);
87 		if (nbuf < 32)
88 			nbuf = 32;
89 	}
90 	if (nswbuf == 0) {
91 		nswbuf = (nbuf / 2) &~ 1;	/* force even */
92 		if (nswbuf > 256)
93 			nswbuf = 256;		/* sanity */
94 	}
95 
96 	/*
97 	 * Allocate space for system data structures.
98 	 */
99 	v = (caddr_t)(0x80000000 | (firstaddr * NBPG));
100 #define	valloc(name, type, num) \
101 	    (name) = (type *)(v); (v) = (caddr_t)((name)+(num))
102 #define	valloclim(name, type, num, lim) \
103 	    (name) = (type *)(v); (v) = (caddr_t)((lim) = ((name)+(num)))
104 	valloc(buffers, char, BSIZE*nbuf);
105 	valloc(buf, struct buf, nbuf);
106 	valloc(swbuf, struct buf, nswbuf);
107 	valloc(swsize, short, nswbuf);	/* note: nswbuf is even */
108 	valloc(swpf, int, nswbuf);
109 	valloclim(inode, struct inode, ninode, inodeNINODE);
110 	valloclim(file, struct file, nfile, fileNFILE);
111 	valloclim(proc, struct proc, nproc, procNPROC);
112 	valloclim(text, struct text, ntext, textNTEXT);
113 	valloc(cfree, struct cblock, nclist);
114 	valloc(callout, struct callout, ncallout);
115 	valloc(swapmap, struct map, nswapmap = nproc * 2);
116 	valloc(argmap, struct map, ARGMAPSIZE);
117 	valloc(kernelmap, struct map, nproc);
118 	valloc(mbmap, struct map, nmbclusters/4);
119 	/*
120 	 * Now allocate space for core map
121 	 */
122 	ncmap = (physmem*NBPG - ((int)v &~ 0x80000000)) /
123 		    (NBPG*CLSIZE + sizeof (struct cmap));
124 	valloclim(cmap, struct cmap, ncmap, ecmap);
125 	if ((((int)(ecmap+1))&~0x80000000) > SYSPTSIZE*NBPG)
126 		panic("sys pt too small");
127 
128 	/*
129 	 * Clear allocated space, and make r/w entries
130 	 * for the space in the kernel map.
131 	 */
132 	unixsize = btoc((int)(ecmap+1) &~ 0x80000000);
133 	if (unixsize >= physmem - 8*UPAGES)
134 		panic("no memory");
135 	pte = &Sysmap[firstaddr];
136 	for (i = firstaddr; i < unixsize; i++) {
137 		*(int *)(&Sysmap[i]) = PG_V | PG_KW | i;
138 		clearseg(i);
139 	}
140 	mtpr(TBIA, 1);
141 
142 	/*
143 	 * Initialize callouts
144 	 */
145 	callfree = callout;
146 	for (i = 1; i < ncallout; i++)
147 		callout[i-1].c_next = &callout[i];
148 
149 	/*
150 	 * Initialize memory allocator and swap
151 	 * and user page table maps.
152 	 *
153 	 * THE USER PAGE TABLE MAP IS CALLED ``kernelmap''
154 	 * WHICH IS A VERY UNDESCRIPTIVE AND INCONSISTENT NAME.
155 	 */
156 	meminit(unixsize, maxmem);
157 	maxmem = freemem;
158 	printf("avail mem = %d\n", ctob(maxmem));
159 	rminit(kernelmap, USRPTSIZE, 1, "usrpt", nproc);
160 	rminit(mbmap, nmbclusters-CLSIZE, CLSIZE, "mbclusters", nmbclusters/4);
161 
162 	/*
163 	 * Configure the system.
164 	 */
165 	configure();
166 
167 	/*
168 	 * Clear restart inhibit flags.
169 	 */
170 	tocons(TXDB_CWSI);
171 	tocons(TXDB_CCSI);
172 }
173 
174 /*
175  * set up a physical address
176  * into users virtual address space.
177  */
178 sysphys()
179 {
180 
181 	if(!suser())
182 		return;
183 	u.u_error = EINVAL;
184 }
185 
186 /*
187  * Initialze the clock, based on the time base which is, e.g.
188  * from a filesystem.  Base provides the time to within six months,
189  * and the time of year clock provides the rest.
190  */
191 clkinit(base)
192 	time_t base;
193 {
194 	register unsigned todr = mfpr(TODR);
195 	long deltat;
196 	int year = YRREF;
197 
198 	if (base < 5*SECYR) {
199 		printf("WARNING: preposterous time in file system");
200 		time = 6*SECYR + 186*SECDAY + SECDAY/2;
201 		clkset();
202 		goto check;
203 	}
204 	/*
205 	 * Have been told that VMS keeps time internally with base TODRZERO.
206 	 * If this is correct, then this routine and VMS should maintain
207 	 * the same date, and switching shouldn't be painful.
208 	 * (Unfortunately, VMS keeps local time, so when you run UNIX
209 	 * and VMS, VMS runs on GMT...).
210 	 */
211 	if (todr < TODRZERO) {
212 		printf("WARNING: todr too small");
213 		time = base;
214 		/*
215 		 * Believe the time in the file system for lack of
216 		 * anything better, resetting the TODR.
217 		 */
218 		clkset();
219 		goto check;
220 	}
221 	/*
222 	 * Sneak to within 6 month of the time in the filesystem,
223 	 * by starting with the time of the year suggested by the TODR,
224 	 * and advancing through succesive years.  Adding the number of
225 	 * seconds in the current year takes us to the end of the current year
226 	 * and then around into the next year to the same position.
227 	 */
228 	for (time = (todr-TODRZERO)/100; time < base-SECYR/2; time += SECYR) {
229 		if (LEAPYEAR(year))
230 			time += SECDAY;
231 		year++;
232 	}
233 
234 	/*
235 	 * See if we gained/lost two or more days;
236 	 * if so, assume something is amiss.
237 	 */
238 	deltat = time - base;
239 	if (deltat < 0)
240 		deltat = -deltat;
241 	if (deltat < 2*SECDAY)
242 		return;
243 	printf("WARNING: clock %s %d days",
244 	    time < base ? "lost" : "gained", deltat / SECDAY);
245 check:
246 	printf(" -- CHECK AND RESET THE DATE!\n");
247 }
248 
249 /*
250  * Reset the TODR based on the time value; used when the TODR
251  * has a preposterous value and also when the time is reset
252  * by the stime system call.  Also called when the TODR goes past
253  * TODRZERO + 100*(SECYEAR+2*SECDAY) (e.g. on Jan 2 just after midnight)
254  * to wrap the TODR around.
255  */
256 clkset()
257 {
258 	int year = YRREF;
259 	unsigned secyr;
260 	unsigned yrtime = time;
261 
262 	/*
263 	 * Whittle the time down to an offset in the current year,
264 	 * by subtracting off whole years as long as possible.
265 	 */
266 	for (;;) {
267 		secyr = SECYR;
268 		if (LEAPYEAR(year))
269 			secyr += SECDAY;
270 		if (yrtime < secyr)
271 			break;
272 		yrtime -= secyr;
273 		year++;
274 	}
275 	mtpr(TODR, TODRZERO + yrtime*100);
276 }
277 
278 #ifdef PGINPROF
279 /*
280  * Return the difference (in microseconds)
281  * between the  current time and a previous
282  * time as represented  by the arguments.
283  * If there is a pending clock interrupt
284  * which has not been serviced due to high
285  * ipl, return error code.
286  */
287 vmtime(otime, olbolt, oicr)
288 	register int otime, olbolt, oicr;
289 {
290 
291 	if (mfpr(ICCS)&ICCS_INT)
292 		return(-1);
293 	else
294 		return(((time-otime)*60 + lbolt-olbolt)*16667 + mfpr(ICR)-oicr);
295 }
296 #endif
297 
298 /*
299  * Send an interrupt to process
300  *
301  * SHOULD CHANGE THIS TO PASS ONE MORE WORK SO THAT ALL INFORMATION
302  * PROVIDED BY HARDWARE IS AVAILABLE TO THE USER PROCESS.
303  */
304 sendsig(p, n)
305 	int (*p)();
306 {
307 	register int *usp, *regs;
308 
309 	regs = u.u_ar0;
310 	usp = (int *)regs[SP];
311 	usp -= 5;
312 	if ((int)usp <= USRSTACK - ctob(u.u_ssize))
313 		(void) grow((unsigned)usp);
314 	;			/* Avoid asm() label botch */
315 #ifndef lint
316 	asm("probew $3,$20,(r11)");
317 	asm("beql bad");
318 #else
319 	if (useracc((caddr_t)usp, 0x20, 1))
320 		goto bad;
321 #endif
322 	*usp++ = n;
323 	if (n == SIGILL || n == SIGFPE) {
324 		*usp++ = u.u_code;
325 		u.u_code = 0;
326 	} else
327 		*usp++ = 0;
328 	*usp++ = (int)p;
329 	*usp++ = regs[PC];
330 	*usp++ = regs[PS];
331 	regs[SP] = (int)(usp - 5);
332 	regs[PS] &= ~(PSL_CM|PSL_FPD);
333 	regs[PC] = (int)u.u_pcb.pcb_sigc;
334 	return;
335 
336 asm("bad:");
337 bad:
338 	/*
339 	 * Process has trashed its stack; give it an illegal
340 	 * instruction to halt it in its tracks.
341 	 */
342 	u.u_signal[SIGILL] = SIG_DFL;
343 	u.u_procp->p_siga0 &= ~(1<<(SIGILL-1));
344 	u.u_procp->p_siga1 &= ~(1<<(SIGILL-1));
345 	psignal(u.u_procp, SIGILL);
346 }
347 
348 dorti()
349 {
350 	struct frame frame;
351 	register int sp;
352 	register int reg, mask;
353 	extern int ipcreg[];
354 
355 	(void) copyin((caddr_t)u.u_ar0[FP], (caddr_t)&frame, sizeof (frame));
356 	sp = u.u_ar0[FP] + sizeof (frame);
357 	u.u_ar0[PC] = frame.fr_savpc;
358 	u.u_ar0[FP] = frame.fr_savfp;
359 	u.u_ar0[AP] = frame.fr_savap;
360 	mask = frame.fr_mask;
361 	for (reg = 0; reg <= 11; reg++) {
362 		if (mask&1) {
363 			u.u_ar0[ipcreg[reg]] = fuword((caddr_t)sp);
364 			sp += 4;
365 		}
366 		mask >>= 1;
367 	}
368 	sp += frame.fr_spa;
369 	u.u_ar0[PS] = (u.u_ar0[PS] & 0xffff0000) | frame.fr_psw;
370 	if (frame.fr_s)
371 		sp += 4 + 4 * (fuword((caddr_t)sp) & 0xff);
372 	/* phew, now the rei */
373 	u.u_ar0[PC] = fuword((caddr_t)sp);
374 	sp += 4;
375 	u.u_ar0[PS] = fuword((caddr_t)sp);
376 	sp += 4;
377 	u.u_ar0[PS] |= PSL_USERSET;
378 	u.u_ar0[PS] &= ~PSL_USERCLR;
379 	u.u_ar0[SP] = (int)sp;
380 }
381 
382 /*
383  * Memenable enables the memory controlle corrected data reporting.
384  * This runs at regular intervals, turning on the interrupt.
385  * The interrupt is turned off, per memory controller, when error
386  * reporting occurs.  Thus we report at most once per memintvl.
387  */
388 int	memintvl = MEMINTVL;
389 
390 memenable()
391 {
392 	register struct mcr *mcr;
393 	register int m;
394 
395 	for (m = 0; m < nmcr; m++) {
396 		mcr = mcraddr[m];
397 		switch (cpu) {
398 #if VAX780
399 		case VAX_780:
400 			M780_ENA(mcr);
401 			break;
402 #endif
403 #if VAX750
404 		case VAX_750:
405 			M750_ENA(mcr);
406 			break;
407 #endif
408 #if VAX7ZZ
409 		case VAX_7ZZ:
410 			M7ZZ_ENA(mcr);
411 			break;
412 #endif
413 		}
414 	}
415 	if (memintvl > 0)
416 		timeout(memenable, (caddr_t)0, memintvl);
417 }
418 
419 /*
420  * Memerr is the interrupt routine for corrected read data
421  * interrupts.  It looks to see which memory controllers have
422  * unreported errors, reports them, and disables further
423  * reporting for a time on those controller.
424  */
425 memerr()
426 {
427 	register struct mcr *mcr;
428 	register int m;
429 
430 	for (m = 0; m < nmcr; m++) {
431 		mcr = mcraddr[m];
432 		switch (cpu) {
433 #if VAX780
434 		case VAX_780:
435 			if (M780_ERR(mcr)) {
436 				printf("mcr%d: soft ecc addr %x syn %x\n",
437 				    m, M780_ADDR(mcr), M780_SYN(mcr));
438 				M780_INH(mcr);
439 			}
440 			break;
441 #endif
442 #if VAX750
443 		case VAX_750:
444 			if (M750_ERR(mcr)) {
445 				printf("mcr%d: soft ecc addr %x syn %x\n",
446 				    m, M750_ADDR(mcr), M750_SYN(mcr));
447 				M750_INH(mcr);
448 			}
449 			break;
450 #endif
451 #if VAX7ZZ
452 		case VAX_7ZZ:
453 			if (M7ZZ_ERR(mcr)) {
454 				struct mcr amcr;
455 				amcr.mc_reg[0] = mcr->mc_reg[0];
456 				printf("mcr%d: soft ecc addr %x syn %x\n",
457 				    m, M7ZZ_ADDR(&amcr), M7ZZ_SYN(&amcr));
458 				M7ZZ_INH(mcr);
459 			}
460 			break;
461 #endif
462 		}
463 	}
464 }
465 
466 /*
467  * Invalidate single all pte's in a cluster
468  */
469 tbiscl(v)
470 	unsigned v;
471 {
472 	register caddr_t addr;		/* must be first reg var */
473 	register int i;
474 
475 	asm(".set TBIS,58");
476 	addr = ptob(v);
477 	for (i = 0; i < CLSIZE; i++) {
478 #ifdef lint
479 		mtpr(TBIS, addr);
480 #else
481 		asm("mtpr r11,$TBIS");
482 #endif
483 		addr += NBPG;
484 	}
485 }
486 
487 int	waittime = -1;
488 
489 boot(paniced, arghowto)
490 	int paniced, arghowto;
491 {
492 	register int howto;		/* r11 == how to boot */
493 	register int devtype;		/* r10 == major of root dev */
494 
495 #ifdef lint
496 	howto = 0; devtype = 0;
497 	printf("howto %d, devtype %d\n", arghowto, devtype);
498 #endif
499 	(void) spl1();
500 	howto = arghowto;
501 	if ((howto&RB_NOSYNC)==0 && waittime < 0 && bfreelist[0].b_forw) {
502 		waittime = 0;
503 		update(1);
504 		printf("syncing disks... ");
505 #ifdef notdef
506 		{ register struct buf *bp;
507 		  int iter, nbusy;
508 
509 		  for (iter = 0; iter < 10; iter++) {
510 			nbusy = 0;
511 			for (bp = &buf[nbuf]; --bp >= buf; )
512 				if (bp->b_flags & B_BUSY)
513 					nbusy++;
514 			if (nbusy == 0)
515 				break;
516 			printf("%d ", nbusy);
517 		  }
518 		}
519 #else
520 		DELAY(10000000);
521 #endif
522 		printf("done\n");
523 	}
524 	splx(0x1f);			/* extreme priority */
525 	devtype = major(rootdev);
526 	if (howto&RB_HALT) {
527 		printf("halting (in tight loop); hit\n\t^P\n\tHALT\n\n");
528 		mtpr(IPL, 0x1f);
529 		for (;;)
530 			;
531 	} else {
532 		if (paniced == RB_PANIC) {
533 			doadump();		/* TXDB_BOOT's itsself */
534 			/*NOTREACHED*/
535 		}
536 		tocons(TXDB_BOOT);
537 	}
538 #if defined(VAX750) || defined(VAX7ZZ)
539 	if (cpu != VAX_780)
540 		{ asm("movl r11,r5"); }		/* boot flags go in r5 */
541 #endif
542 	for (;;)
543 		asm("halt");
544 	/*NOTREACHED*/
545 }
546 
547 tocons(c)
548 {
549 
550 	while ((mfpr(TXCS)&TXCS_RDY) == 0)
551 		continue;
552 	mtpr(TXDB, c);
553 }
554 
555 /*
556  * Doadump comes here after turning off memory management and
557  * getting on the dump stack, either when called above, or by
558  * the auto-restart code.
559  */
560 dumpsys()
561 {
562 
563 	rpb.rp_flag = 1;
564 	if ((minor(dumpdev)&07) != 1)
565 		return;
566 	printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
567 	printf("dump ");
568 	switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
569 
570 	case ENXIO:
571 		printf("device bad\n");
572 		break;
573 
574 	case EFAULT:
575 		printf("device not ready\n");
576 		break;
577 
578 	case EINVAL:
579 		printf("area improper\n");
580 		break;
581 
582 	case EIO:
583 		printf("i/o error");
584 		break;
585 
586 	default:
587 		printf("succeeded");
588 		break;
589 	}
590 }
591 
592 /*
593  * Machine check error recovery code.
594  * Print out the machine check frame and then give up.
595  */
596 #if defined(VAX780) || defined(VAX750)
597 char *mc780[] = {
598 	"cp read",	"ctrl str par",	"cp tbuf par",	"cp cache par",
599 	"cp rdtimo", 	"cp rds",	"ucode lost",	0,
600 	0,		0,		"ib tbuf par",	0,
601 	"ib rds",	"ib rd timo",	0,		"ib cache par"
602 };
603 #endif
604 #if VAX7ZZ
605 #define	NMC7ZZ	12
606 char *mc7ZZ[] = {
607 	"tb par",	"bad retry",	"bad intr id",	"cant write ptem",
608 	"unkn mcr err",	"iib rd err",	"nxm ref",	"cp rds",
609 	"unalgn ioref",	"nonlw ioref",	"bad ioaddr",	"unalgn ubaddr",
610 };
611 #endif
612 
613 /*
614  * Frame for each cpu
615  */
616 struct mc780frame {
617 	int	mc8_bcnt;		/* byte count == 0x28 */
618 	int	mc8_summary;		/* summary parameter (as above) */
619 	int	mc8_cpues;		/* cpu error status */
620 	int	mc8_upc;		/* micro pc */
621 	int	mc8_vaviba;		/* va/viba register */
622 	int	mc8_dreg;		/* d register */
623 	int	mc8_tber0;		/* tbuf error reg 0 */
624 	int	mc8_tber1;		/* tbuf error reg 1 */
625 	int	mc8_timo;		/* timeout address divided by 4 */
626 	int	mc8_parity;		/* parity */
627 	int	mc8_sbier;		/* sbi error register */
628 	int	mc8_pc;			/* trapped pc */
629 	int	mc8_psl;		/* trapped psl */
630 };
631 struct mc750frame {
632 	int	mc5_bcnt;		/* byte count == 0x28 */
633 	int	mc5_summary;		/* summary parameter (as above) */
634 	int	mc5_va;			/* virtual address register */
635 	int	mc5_errpc;		/* error pc */
636 	int	mc5_mdr;
637 	int	mc5_svmode;		/* saved mode register */
638 	int	mc5_rdtimo;		/* read lock timeout */
639 	int	mc5_tbgpar;		/* tb group parity error register */
640 	int	mc5_cacherr;		/* cache error register */
641 	int	mc5_buserr;		/* bus error register */
642 	int	mc5_mcesr;		/* machine check status register */
643 	int	mc5_pc;			/* trapped pc */
644 	int	mc5_psl;		/* trapped psl */
645 };
646 struct mc7ZZframe {
647 	int	mc3_bcnt;		/* byte count == 0xc */
648 	int	mc3_summary;		/* summary parameter */
649 	int	mc3_parm[2];		/* parameter 1 and 2 */
650 	int	mc3_pc;			/* trapped pc */
651 	int	mc3_psl;		/* trapped psl */
652 };
653 
654 machinecheck(cmcf)
655 	caddr_t cmcf;
656 {
657 	register u_int type = ((struct mc780frame *)cmcf)->mc8_summary;
658 
659 	printf("machine check %x: ", type);
660 	switch (cpu) {
661 #if VAX780
662 	case VAX_780:
663 #endif
664 #if VAX750
665 	case VAX_750:
666 #endif
667 #if defined(VAX780) || defined(VAX750)
668 		printf("%s%s\n", mc780[type&0xf],
669 		    (type&0xf0) ? " abort" : " fault");
670 		break;
671 #endif
672 #if VAX7ZZ
673 	case VAX_7ZZ:
674 		if (type < NMC7ZZ)
675 			printf("%s", mc7ZZ[type]);
676 		printf("\n");
677 		break;
678 #endif
679 	}
680 	switch (cpu) {
681 #if VAX780
682 	case VAX_780: {
683 		register struct mc780frame *mcf = (struct mc780frame *)cmcf;
684 		register int sbifs;
685 		printf("\tcpues %x upc %x va/viba %x dreg %x tber %x %x\n",
686 		   mcf->mc8_cpues, mcf->mc8_upc, mcf->mc8_vaviba,
687 		   mcf->mc8_dreg, mcf->mc8_tber0, mcf->mc8_tber1);
688 		sbifs = mfpr(SBIFS);
689 		printf("\ttimo %x parity %x sbier %x pc %x psl %x sbifs %x\n",
690 		   mcf->mc8_timo*4, mcf->mc8_parity, mcf->mc8_sbier,
691 		   mcf->mc8_pc, mcf->mc8_psl, sbifs);
692 		/* THE FUNNY BITS IN THE FOLLOWING ARE FROM THE ``BLACK */
693 		/* BOOK AND SHOULD BE PUT IN AN ``sbi.h'' */
694 		mtpr(SBIFS, sbifs &~ 0x2000000);
695 		mtpr(SBIER, mfpr(SBIER) | 0x70c0);
696 		break;
697 	}
698 #endif
699 #if VAX750
700 	case VAX_750: {
701 		register struct mc750frame *mcf = (struct mc750frame *)cmcf;
702 		printf("\tva %x errpc %x mdr %x smr %x rdtimo %x tbgpar %x cacherr %x\n",
703 		    mcf->mc5_va, mcf->mc5_errpc, mcf->mc5_mdr, mcf->mc5_svmode,
704 		    mcf->mc5_rdtimo, mcf->mc5_tbgpar, mcf->mc5_cacherr);
705 		printf("\tbuserr %x mcesr %x pc %x psl %x mcsr %x\n",
706 		    mcf->mc5_buserr, mcf->mc5_mcesr, mcf->mc5_pc, mcf->mc5_psl,
707 		    mfpr(MCSR));
708 		mtpr(MCESR, 0xf);
709 		break;
710 		}
711 #endif
712 #if VAX7ZZ
713 	case VAX_7ZZ: {
714 		register struct mc7ZZframe *mcf = (struct mc7ZZframe *)cmcf;
715 		printf("params %x,%x pc %x psl %x mcesr %x\n",
716 		    mcf->mc3_parm[0], mcf->mc3_parm[1],
717 		    mcf->mc3_pc, mcf->mc3_psl, mfpr(MCESR));
718 		mtpr(MCESR, 0xf);
719 		break;
720 		}
721 #endif
722 	}
723 	memerr();
724 	panic("mchk");
725 }
726