camap is replaced by kmempt
[unix-history] / usr / src / sys / vax / vax / machdep.c
CommitLineData
da7c5cc6 1/*
41f2548c 2 * Copyright (c) 1982 Regents of the University of California.
da7c5cc6
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
4a3fcdaa 6 * @(#)machdep.c 7.5 (Berkeley) %G%
da7c5cc6 7 */
961945a8 8
1884f3f6
JB
9#include "reg.h"
10#include "pte.h"
11#include "psl.h"
79821b2c 12
1884f3f6
JB
13#include "param.h"
14#include "systm.h"
15#include "dir.h"
16#include "user.h"
17#include "kernel.h"
18#include "map.h"
19#include "vm.h"
20#include "proc.h"
21#include "buf.h"
22#include "reboot.h"
23#include "conf.h"
24#include "inode.h"
25#include "file.h"
26#include "text.h"
27#include "clist.h"
28#include "callout.h"
29#include "cmap.h"
30#include "mbuf.h"
31#include "msgbuf.h"
32#include "quota.h"
79821b2c 33
1884f3f6 34#include "frame.h"
f0266f2b 35#include "clock.h"
1884f3f6
JB
36#include "cons.h"
37#include "cpu.h"
38#include "mem.h"
39#include "mtpr.h"
40#include "rpb.h"
90dc7048 41#include "ka630.h"
cd3da95f
BJ
42#include "../vaxuba/ubavar.h"
43#include "../vaxuba/ubareg.h"
44
3dc04a07
BJ
45/*
46 * Declare these as initialized data so we can patch them.
47 */
3dc04a07 48int nswbuf = 0;
7cb2e3f5
MK
49#ifdef NBUF
50int nbuf = NBUF;
51#else
52int nbuf = 0;
53#endif
54#ifdef BUFPAGES
55int bufpages = BUFPAGES;
56#else
6e4812d6 57int bufpages = 0;
7cb2e3f5 58#endif
3dc04a07 59
79821b2c
BJ
60/*
61 * Machine-dependent startup code
62 */
63startup(firstaddr)
c34926db 64 int firstaddr;
79821b2c
BJ
65{
66 register int unixsize;
a0eab615 67 register unsigned i;
a53ab6ba 68 register struct pte *pte;
3b1e560f 69 int mapaddr, j;
c34926db 70 register caddr_t v;
6e4812d6 71 int maxbufs, base, residual;
79821b2c 72
90dc7048
BK
73#if VAX630
74 /*
75 * Leave last 5k of phys. memory as console work area.
76 */
77 if (cpu == VAX_630)
78 maxmem -= 10;
79#endif
90f8d91f
BJ
80 /*
81 * Initialize error message buffer (at end of core).
82 */
690a7ad7 83 maxmem -= btoc(sizeof (struct msgbuf));
90f8d91f 84 pte = msgbufmap;
690a7ad7 85 for (i = 0; i < btoc(sizeof (struct msgbuf)); i++)
90f8d91f 86 *(int *)pte++ = PG_V | PG_KW | (maxmem + i);
654b7651 87 mtpr(TBIA, 0);
90f8d91f 88
41f2548c
MK
89#if VAX630
90#include "qv.h"
91#if NQV > 0
92 /*
93 * redirect console to qvss if it exists
94 */
95 if (!qvcons_init())
96 printf("qvss not initialized\n");
97#endif
233e2ac3
MK
98#endif
99
100#ifdef KDB
101 kdb_init();
41f2548c 102#endif
79821b2c
BJ
103 /*
104 * Good {morning,afternoon,evening,night}.
105 */
90f8d91f 106 printf(version);
7cb2e3f5 107 printf("real mem = %d\n", ctob(physmem));
a53ab6ba
BJ
108
109 /*
c34926db 110 * Allocate space for system data structures.
3b1e560f 111 * The first available real memory address is in "firstaddr".
3b1e560f
SL
112 * The first available kernel virtual address is in "v".
113 * As pages of kernel virtual memory are allocated, "v" is incremented.
7cb2e3f5
MK
114 * As pages of memory are allocated and cleared,
115 * "firstaddr" is incremented.
3b1e560f
SL
116 * An index into the kernel page table corresponding to the
117 * virtual memory address maintained in "v" is kept in "mapaddr".
a53ab6ba 118 */
c34926db
BJ
119 v = (caddr_t)(0x80000000 | (firstaddr * NBPG));
120#define valloc(name, type, num) \
7cb2e3f5 121 (name) = (type *)v; v = (caddr_t)((name)+(num))
c34926db 122#define valloclim(name, type, num, lim) \
7cb2e3f5 123 (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
c34926db
BJ
124 valloclim(inode, struct inode, ninode, inodeNINODE);
125 valloclim(file, struct file, nfile, fileNFILE);
126 valloclim(proc, struct proc, nproc, procNPROC);
127 valloclim(text, struct text, ntext, textNTEXT);
128 valloc(cfree, struct cblock, nclist);
129 valloc(callout, struct callout, ncallout);
233328fc
BJ
130 valloc(swapmap, struct map, nswapmap = nproc * 2);
131 valloc(argmap, struct map, ARGMAPSIZE);
c34926db 132 valloc(kernelmap, struct map, nproc);
e32d6e7d 133 valloc(mbmap, struct map, nmbclusters/4);
7dba1c03 134 valloc(namecache, struct namecache, nchsize);
3b1e560f 135#ifdef QUOTA
831f59be
RE
136 valloclim(quota, struct quota, nquota, quotaNQUOTA);
137 valloclim(dquot, struct dquot, ndquot, dquotNDQUOT);
138#endif
7cb2e3f5
MK
139
140 /*
141 * Determine how many buffers to allocate.
ec02650a
KM
142 * Use 10% of memory for the first 2 Meg, 5% of the remaining
143 * memory. Insure a minimum of 16 buffers.
7cb2e3f5
MK
144 * We allocate 1/2 as many swap buffer headers as file i/o buffers.
145 */
146 if (bufpages == 0)
6692a5c8 147 if (physmem < (2 * 1024 * CLSIZE))
ec02650a
KM
148 bufpages = physmem / 10 / CLSIZE;
149 else
6692a5c8 150 bufpages = ((2 * 1024 * CLSIZE + physmem) / 20) / CLSIZE;
7cb2e3f5
MK
151 if (nbuf == 0) {
152 nbuf = bufpages / 2;
153 if (nbuf < 16)
154 nbuf = 16;
155 }
156 if (nswbuf == 0) {
157 nswbuf = (nbuf / 2) &~ 1; /* force even */
158 if (nswbuf > 256)
159 nswbuf = 256; /* sanity */
160 }
161 valloc(swbuf, struct buf, nswbuf);
162
163 /*
164 * Now the amount of virtual memory remaining for buffers
165 * can be calculated, estimating needs for the cmap.
166 */
167 ncmap = (maxmem*NBPG - ((int)v &~ 0x80000000)) /
168 (CLBYTES + sizeof(struct cmap)) + 2;
169 maxbufs = ((SYSPTSIZE * NBPG) -
170 ((int)(v + ncmap * sizeof(struct cmap)) - 0x80000000)) /
171 (MAXBSIZE + sizeof(struct buf));
172 if (maxbufs < 16)
173 panic("sys pt too small");
174 if (nbuf > maxbufs) {
175 printf("SYSPTSIZE limits number of buffers to %d\n", maxbufs);
176 nbuf = maxbufs;
177 }
178 if (bufpages > nbuf * (MAXBSIZE / CLBYTES))
179 bufpages = nbuf * (MAXBSIZE / CLBYTES);
180 valloc(buf, struct buf, nbuf);
181
c34926db 182 /*
7cb2e3f5 183 * Allocate space for core map.
3b1e560f
SL
184 * Allow space for all of phsical memory minus the amount
185 * dedicated to the system. The amount of physical memory
186 * dedicated to the system is the total virtual memory of
7cb2e3f5
MK
187 * the system thus far, plus core map, buffer pages,
188 * and buffer headers not yet allocated.
189 * Add 2: 1 because the 0th entry is unused, 1 for rounding.
c34926db 190 */
7cb2e3f5
MK
191 ncmap = (maxmem*NBPG - ((int)(v + bufpages*CLBYTES) &~ 0x80000000)) /
192 (CLBYTES + sizeof(struct cmap)) + 2;
c34926db
BJ
193 valloclim(cmap, struct cmap, ncmap, ecmap);
194
195 /*
7cb2e3f5 196 * Clear space allocated thus far, and make r/w entries
c34926db
BJ
197 * for the space in the kernel map.
198 */
7cb2e3f5
MK
199 unixsize = btoc((int)v &~ 0x80000000);
200 while (firstaddr < unixsize) {
201 *(int *)(&Sysmap[firstaddr]) = PG_V | PG_KW | firstaddr;
3b1e560f
SL
202 clearseg((unsigned)firstaddr);
203 firstaddr++;
c34926db 204 }
7cb2e3f5
MK
205
206 /*
207 * Now allocate buffers proper. They are different than the above
208 * in that they usually occupy more virtual memory than physical.
209 */
210 v = (caddr_t) ((int)(v + PGOFSET) &~ PGOFSET);
211 valloc(buffers, char, MAXBSIZE * nbuf);
212 base = bufpages / nbuf;
213 residual = bufpages % nbuf;
214 mapaddr = firstaddr;
215 for (i = 0; i < residual; i++) {
216 for (j = 0; j < (base + 1) * CLSIZE; j++) {
217 *(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr;
218 clearseg((unsigned)firstaddr);
219 firstaddr++;
220 }
221 mapaddr += MAXBSIZE / NBPG;
222 }
223 for (i = residual; i < nbuf; i++) {
224 for (j = 0; j < base * CLSIZE; j++) {
225 *(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr;
226 clearseg((unsigned)firstaddr);
227 firstaddr++;
228 }
229 mapaddr += MAXBSIZE / NBPG;
230 }
231
232 unixsize = btoc((int)v &~ 0x80000000);
3b1e560f
SL
233 if (firstaddr >= physmem - 8*UPAGES)
234 panic("no memory");
654b7651 235 mtpr(TBIA, 0); /* After we just cleared it all! */
79821b2c 236
c4710996
BJ
237 /*
238 * Initialize callouts
239 */
240 callfree = callout;
241 for (i = 1; i < ncallout; i++)
242 callout[i-1].c_next = &callout[i];
243
79821b2c 244 /*
233328fc
BJ
245 * Initialize memory allocator and swap
246 * and user page table maps.
247 *
248 * THE USER PAGE TABLE MAP IS CALLED ``kernelmap''
249 * WHICH IS A VERY UNDESCRIPTIVE AND INCONSISTENT NAME.
79821b2c 250 */
3b1e560f 251 meminit(firstaddr, maxmem);
a53ab6ba 252 maxmem = freemem;
79821b2c 253 printf("avail mem = %d\n", ctob(maxmem));
6e4812d6
KM
254 printf("using %d buffers containing %d bytes of memory\n",
255 nbuf, bufpages * CLBYTES);
a29f7995
BJ
256 rminit(kernelmap, (long)USRPTSIZE, (long)1,
257 "usrpt", nproc);
06126147 258 rminit(mbmap, (long)(nmbclusters * CLSIZE), (long)CLSIZE,
a29f7995 259 "mbclusters", nmbclusters/4);
fc814008 260
cf19cacc 261 /*
06126147 262 * Set up CPU-specific registers, cache, etc.
cf19cacc 263 */
06126147 264 initcpu();
cf19cacc 265
233e2ac3
MK
266 /*
267 * Set up buffers, so they can be used to read disk labels.
268 */
269 bhinit();
270 binit();
271
6692a5c8 272 /*
06126147 273 * Configure the system.
6692a5c8 274 */
06126147
MK
275 configure();
276
cf19cacc
BJ
277 /*
278 * Clear restart inhibit flags.
279 */
280 tocons(TXDB_CWSI);
281 tocons(TXDB_CCSI);
79821b2c
BJ
282}
283
79821b2c
BJ
284#ifdef PGINPROF
285/*
286 * Return the difference (in microseconds)
287 * between the current time and a previous
288 * time as represented by the arguments.
289 * If there is a pending clock interrupt
290 * which has not been serviced due to high
291 * ipl, return error code.
292 */
293vmtime(otime, olbolt, oicr)
294 register int otime, olbolt, oicr;
295{
296
297 if (mfpr(ICCS)&ICCS_INT)
298 return(-1);
299 else
9f159248 300 return(((time.tv_sec-otime)*60 + lbolt-olbolt)*16667 + mfpr(ICR)-oicr);
79821b2c
BJ
301}
302#endif
303
f835d7b3
MK
304/*
305 * Clear registers on exec
306 */
307setregs(entry)
308 u_long entry;
309{
310#ifdef notdef
311 register int *rp;
312
313 /* should pass args to init on the stack */
314 /* should also fix this code before using it, it's wrong */
315 /* wanna clear the scb? */
316 for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];)
317 *rp++ = 0;
318#endif
319 u.u_ar0[PC] = entry + 2;
320}
321
79821b2c 322/*
dd012d1e 323 * Send an interrupt to process.
f815f998 324 *
dd012d1e
SL
325 * Stack is set up to allow sigcode stored
326 * in u. to call routine, followed by chmk
120dfe64
KM
327 * to sigreturn routine below. After sigreturn
328 * resets the signal mask, the stack, the frame
329 * pointer, and the argument pointer, it returns
330 * to the user specified pc, psl.
79821b2c 331 */
56652904
MK
332sendsig(p, sig, mask)
333 int (*p)(), sig, mask;
79821b2c 334{
120dfe64 335 register struct sigcontext *scp;
4e207164
SL
336 register int *regs;
337 register struct sigframe {
338 int sf_signum;
339 int sf_code;
340 struct sigcontext *sf_scp;
341 int (*sf_handler)();
120dfe64 342 int sf_argcount;
4e207164 343 struct sigcontext *sf_scpcopy;
120dfe64 344 } *fp;
457aa395 345 int oonstack;
79821b2c
BJ
346
347 regs = u.u_ar0;
457aa395 348 oonstack = u.u_onstack;
120dfe64
KM
349 /*
350 * Allocate and validate space for the signal handler
351 * context. Note that if the stack is in P0 space, the
352 * call to grow() is a nop, and the useracc() check
353 * will fail if the process has not already allocated
354 * the space with a `brk'.
355 */
56652904 356 if (!u.u_onstack && (u.u_sigonstack & sigmask(sig))) {
120dfe64 357 scp = (struct sigcontext *)u.u_sigsp - 1;
457aa395 358 u.u_onstack = 1;
dd012d1e 359 } else
120dfe64
KM
360 scp = (struct sigcontext *)regs[SP] - 1;
361 fp = (struct sigframe *)scp - 1;
362 if ((int)fp <= USRSTACK - ctob(u.u_ssize))
8011f5df 363 (void)grow((unsigned)fp);
2cce526e 364 if (useracc((caddr_t)fp, sizeof (*fp) + sizeof (*scp), B_WRITE) == 0) {
120dfe64
KM
365 /*
366 * Process has trashed its stack; give it an illegal
367 * instruction to halt it in its tracks.
368 */
369 u.u_signal[SIGILL] = SIG_DFL;
370 sig = sigmask(SIGILL);
371 u.u_procp->p_sigignore &= ~sig;
372 u.u_procp->p_sigcatch &= ~sig;
373 u.u_procp->p_sigmask &= ~sig;
374 psignal(u.u_procp, SIGILL);
375 return;
376 }
377 /*
378 * Build the argument list for the signal handler.
379 */
4e207164 380 fp->sf_signum = sig;
dd012d1e 381 if (sig == SIGILL || sig == SIGFPE) {
4e207164 382 fp->sf_code = u.u_code;
dca3793c
BJ
383 u.u_code = 0;
384 } else
4e207164
SL
385 fp->sf_code = 0;
386 fp->sf_scp = scp;
387 fp->sf_handler = p;
e4c50b16 388 /*
120dfe64 389 * Build the calls argument frame to be used to call sigreturn
e4c50b16 390 */
120dfe64 391 fp->sf_argcount = 1;
4e207164 392 fp->sf_scpcopy = scp;
120dfe64
KM
393 /*
394 * Build the signal context to be used by sigreturn.
395 */
4e207164 396 scp->sc_onstack = oonstack;
56652904 397 scp->sc_mask = mask;
120dfe64
KM
398 scp->sc_sp = regs[SP];
399 scp->sc_fp = regs[FP];
400 scp->sc_ap = regs[AP];
4e207164
SL
401 scp->sc_pc = regs[PC];
402 scp->sc_ps = regs[PS];
403 regs[SP] = (int)fp;
79821b2c
BJ
404 regs[PS] &= ~(PSL_CM|PSL_FPD);
405 regs[PC] = (int)u.u_pcb.pcb_sigc;
406 return;
79821b2c
BJ
407}
408
dd012d1e 409/*
120dfe64 410 * System call to cleanup state after a signal
dd012d1e 411 * has been taken. Reset signal mask and
e4c50b16 412 * stack state from context left by sendsig (above).
120dfe64
KM
413 * Return to previous pc and psl as specified by
414 * context left by sendsig. Check carefully to
415 * make sure that the user has not modified the
6692a5c8 416 * psl to gain improper priviledges or to cause
120dfe64 417 * a machine fault.
dd012d1e 418 */
120dfe64 419sigreturn()
dd012d1e 420{
120dfe64
KM
421 struct a {
422 struct sigcontext *sigcntxp;
423 };
e4c50b16 424 register struct sigcontext *scp;
120dfe64
KM
425 register int *regs = u.u_ar0;
426
427 scp = ((struct a *)(u.u_ap))->sigcntxp;
2cce526e 428 if (useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0)
120dfe64
KM
429 return;
430 if ((scp->sc_ps & (PSL_MBZ|PSL_IPL|PSL_IS)) != 0 ||
431 (scp->sc_ps & (PSL_PRVMOD|PSL_CURMOD)) != (PSL_PRVMOD|PSL_CURMOD) ||
432 ((scp->sc_ps & PSL_CM) &&
433 (scp->sc_ps & (PSL_FPD|PSL_DV|PSL_FU|PSL_IV)) != 0)) {
434 u.u_error = EINVAL;
435 return;
436 }
437 u.u_eosys = JUSTRETURN;
438 u.u_onstack = scp->sc_onstack & 01;
439 u.u_procp->p_sigmask = scp->sc_mask &~
440 (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP));
441 regs[FP] = scp->sc_fp;
442 regs[AP] = scp->sc_ap;
443 regs[SP] = scp->sc_sp;
444 regs[PC] = scp->sc_pc;
445 regs[PS] = scp->sc_ps;
446}
dd012d1e 447
120dfe64
KM
448/* XXX - BEGIN 4.2 COMPATIBILITY */
449/*
450 * Compatibility with 4.2 chmk $139 used by longjmp()
451 */
452osigcleanup()
453{
454 register struct sigcontext *scp;
455 register int *regs = u.u_ar0;
456
457 scp = (struct sigcontext *)fuword((caddr_t)regs[SP]);
e4c50b16
SL
458 if ((int)scp == -1)
459 return;
2cce526e 460 if (useracc((caddr_t)scp, 3 * sizeof (int), B_WRITE) == 0)
dd012d1e 461 return;
e4c50b16 462 u.u_onstack = scp->sc_onstack & 01;
120dfe64
KM
463 u.u_procp->p_sigmask = scp->sc_mask &~
464 (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP));
465 regs[SP] = scp->sc_sp;
dd012d1e 466}
120dfe64 467/* XXX - END 4.2 COMPATIBILITY */
dd012d1e
SL
468
469#ifdef notdef
9a3561c2
BJ
470dorti()
471{
2de46def 472 struct frame frame;
9a3561c2
BJ
473 register int sp;
474 register int reg, mask;
475 extern int ipcreg[];
9a3561c2
BJ
476
477 (void) copyin((caddr_t)u.u_ar0[FP], (caddr_t)&frame, sizeof (frame));
478 sp = u.u_ar0[FP] + sizeof (frame);
2de46def
BJ
479 u.u_ar0[PC] = frame.fr_savpc;
480 u.u_ar0[FP] = frame.fr_savfp;
481 u.u_ar0[AP] = frame.fr_savap;
482 mask = frame.fr_mask;
9a3561c2
BJ
483 for (reg = 0; reg <= 11; reg++) {
484 if (mask&1) {
858ecf0f 485 u.u_ar0[ipcreg[reg]] = fuword((caddr_t)sp);
9a3561c2
BJ
486 sp += 4;
487 }
488 mask >>= 1;
489 }
2de46def
BJ
490 sp += frame.fr_spa;
491 u.u_ar0[PS] = (u.u_ar0[PS] & 0xffff0000) | frame.fr_psw;
492 if (frame.fr_s)
858ecf0f 493 sp += 4 + 4 * (fuword((caddr_t)sp) & 0xff);
9a3561c2 494 /* phew, now the rei */
858ecf0f 495 u.u_ar0[PC] = fuword((caddr_t)sp);
9a3561c2 496 sp += 4;
858ecf0f 497 u.u_ar0[PS] = fuword((caddr_t)sp);
9a3561c2 498 sp += 4;
aea14351 499 u.u_ar0[PS] |= PSL_USERSET;
9a3561c2 500 u.u_ar0[PS] &= ~PSL_USERCLR;
cdc19302 501 u.u_ar0[SP] = (int)sp;
9a3561c2 502}
dd012d1e 503#endif
9a3561c2 504
79821b2c 505/*
dca3793c
BJ
506 * Memenable enables the memory controlle corrected data reporting.
507 * This runs at regular intervals, turning on the interrupt.
508 * The interrupt is turned off, per memory controller, when error
509 * reporting occurs. Thus we report at most once per memintvl.
79821b2c 510 */
79821b2c
BJ
511int memintvl = MEMINTVL;
512
dca3793c 513memenable()
79821b2c 514{
8ae22d0f
BJ
515 register struct mcr *mcr;
516 register int m;
d96afe11 517
90dc7048
BK
518#if VAX630
519 if (cpu == VAX_630)
520 return;
521#endif
b5dd6ff7
JB
522#ifdef VAX8600
523 if (cpu == VAX_8600) {
524 M8600_ENA;
525 } else
526#endif
8ae22d0f
BJ
527 for (m = 0; m < nmcr; m++) {
528 mcr = mcraddr[m];
2d192058 529 switch (mcrtype[m]) {
8ae22d0f 530#if VAX780
2d192058
MK
531 case M780C:
532 M780C_ENA(mcr);
533 break;
534 case M780EL:
535 M780EL_ENA(mcr);
536 break;
537 case M780EU:
538 M780EU_ENA(mcr);
8ae22d0f 539 break;
48575cec 540#endif
8ae22d0f 541#if VAX750
2d192058 542 case M750:
dca3793c 543 M750_ENA(mcr);
8ae22d0f 544 break;
fca14b6b 545#endif
10f66600 546#if VAX730
2d192058 547 case M730:
10f66600 548 M730_ENA(mcr);
fca14b6b 549 break;
48575cec 550#endif
8ae22d0f 551 }
dca3793c
BJ
552 }
553 if (memintvl > 0)
5ec8e3cb 554 timeout(memenable, (caddr_t)0, memintvl*hz);
dca3793c
BJ
555}
556
557/*
558 * Memerr is the interrupt routine for corrected read data
559 * interrupts. It looks to see which memory controllers have
560 * unreported errors, reports them, and disables further
561 * reporting for a time on those controller.
562 */
563memerr()
564{
b5dd6ff7
JB
565#ifdef VAX8600
566 register int reg11; /* known to be r11 below */
567#endif
dca3793c
BJ
568 register struct mcr *mcr;
569 register int m;
570
90dc7048
BK
571#if VAX630
572 if (cpu == VAX_630)
573 return;
574#endif
b5dd6ff7
JB
575#ifdef VAX8600
576 if (cpu == VAX_8600) {
577 int mdecc, mear, mstat1, mstat2, array;
578
579 /*
580 * Scratchpad registers in the Ebox must be read by
581 * storing their ID number in ESPA and then immediately
582 * reading ESPD's contents with no other intervening
583 * machine instructions!
584 *
585 * The asm's below have a number of constants which
586 * are defined correctly in mem.h and mtpr.h.
587 */
f0266f2b
MK
588#ifdef lint
589 reg11 = 0;
590#else
b5dd6ff7 591 asm("mtpr $0x27,$0x4e; mfpr $0x4f,r11");
f0266f2b 592#endif
b5dd6ff7
JB
593 mdecc = reg11; /* must acknowledge interrupt? */
594 if (M8600_MEMERR(mdecc)) {
595 asm("mtpr $0x2a,$0x4e; mfpr $0x4f,r11");
596 mear = reg11;
597 asm("mtpr $0x25,$0x4e; mfpr $0x4f,r11");
598 mstat1 = reg11;
599 asm("mtpr $0x26,$0x4e; mfpr $0x4f,r11");
600 mstat2 = reg11;
601 array = M8600_ARRAY(mear);
602
603 printf("mcr0: ecc error, addr %x (array %d) syn %x\n",
604 M8600_ADDR(mear), array, M8600_SYN(mdecc));
605 printf("\tMSTAT1 = %b\n\tMSTAT2 = %b\n",
606 mstat1, M8600_MSTAT1_BITS,
607 mstat2, M8600_MSTAT2_BITS);
608 M8600_INH;
609 }
610 } else
611#endif
dca3793c
BJ
612 for (m = 0; m < nmcr; m++) {
613 mcr = mcraddr[m];
2d192058 614 switch (mcrtype[m]) {
8ae22d0f 615#if VAX780
2d192058
MK
616 case M780C:
617 if (M780C_ERR(mcr)) {
060517c4 618 printf("mcr%d: soft ecc addr %x syn %x\n",
2d192058 619 m, M780C_ADDR(mcr), M780C_SYN(mcr));
f25ccb7b
SL
620#ifdef TRENDATA
621 memlog(m, mcr);
622#endif
2d192058
MK
623 M780C_INH(mcr);
624 }
625 break;
626
627 case M780EL:
628 if (M780EL_ERR(mcr)) {
629 printf("mcr%d: soft ecc addr %x syn %x\n",
630 m, M780EL_ADDR(mcr), M780EL_SYN(mcr));
631 M780EL_INH(mcr);
632 }
633 break;
634
635 case M780EU:
636 if (M780EU_ERR(mcr)) {
637 printf("mcr%d: soft ecc addr %x syn %x\n",
638 m, M780EU_ADDR(mcr), M780EU_SYN(mcr));
639 M780EU_INH(mcr);
dca3793c 640 }
8ae22d0f 641 break;
d96afe11 642#endif
8ae22d0f 643#if VAX750
2d192058 644 case M750:
dca3793c 645 if (M750_ERR(mcr)) {
5ec8e3cb
RE
646 struct mcr amcr;
647 amcr.mc_reg[0] = mcr->mc_reg[0];
a88bd072
MK
648 printf("mcr%d: %s",
649 m, (amcr.mc_reg[0] & M750_UNCORR) ?
650 "hard error" : "soft ecc");
651 printf(" addr %x syn %x\n",
652 M750_ADDR(&amcr), M750_SYN(&amcr));
dca3793c
BJ
653 M750_INH(mcr);
654 }
8ae22d0f 655 break;
fca14b6b 656#endif
10f66600 657#if VAX730
2d192058 658 case M730: {
b359d7d6
MK
659 struct mcr amcr;
660
661 /*
662 * Must be careful on the 730 not to use invalid
663 * instructions in I/O space, so make a copy;
664 */
665 amcr.mc_reg[0] = mcr->mc_reg[0];
666 amcr.mc_reg[1] = mcr->mc_reg[1];
667 if (M730_ERR(&amcr)) {
668 printf("mcr%d: %s",
669 m, (amcr.mc_reg[1] & M730_UNCORR) ?
670 "hard error" : "soft ecc");
671 printf(" addr %x syn %x\n",
672 M730_ADDR(&amcr), M730_SYN(&amcr));
10f66600 673 M730_INH(mcr);
fca14b6b
BJ
674 }
675 break;
c2b69d3e 676 }
8ae22d0f
BJ
677#endif
678 }
679 }
79821b2c
BJ
680}
681
f25ccb7b
SL
682#ifdef TRENDATA
683/*
684 * Figure out what chip to replace on Trendata boards.
685 * Assumes all your memory is Trendata or the non-Trendata
686 * memory never fails..
687 */
688struct {
689 u_char m_syndrome;
690 char m_chip[4];
691} memlogtab[] = {
692 0x01, "C00", 0x02, "C01", 0x04, "C02", 0x08, "C03",
693 0x10, "C04", 0x19, "L01", 0x1A, "L02", 0x1C, "L04",
694 0x1F, "L07", 0x20, "C05", 0x38, "L00", 0x3B, "L03",
695 0x3D, "L05", 0x3E, "L06", 0x40, "C06", 0x49, "L09",
696 0x4A, "L10", 0x4c, "L12", 0x4F, "L15", 0x51, "L17",
697 0x52, "L18", 0x54, "L20", 0x57, "L23", 0x58, "L24",
698 0x5B, "L27", 0x5D, "L29", 0x5E, "L30", 0x68, "L08",
699 0x6B, "L11", 0x6D, "L13", 0x6E, "L14", 0x70, "L16",
700 0x73, "L19", 0x75, "L21", 0x76, "L22", 0x79, "L25",
701 0x7A, "L26", 0x7C, "L28", 0x7F, "L31", 0x80, "C07",
702 0x89, "U01", 0x8A, "U02", 0x8C, "U04", 0x8F, "U07",
703 0x91, "U09", 0x92, "U10", 0x94, "U12", 0x97, "U15",
704 0x98, "U16", 0x9B, "U19", 0x9D, "U21", 0x9E, "U22",
705 0xA8, "U00", 0xAB, "U03", 0xAD, "U05", 0xAE, "U06",
706 0xB0, "U08", 0xB3, "U11", 0xB5, "U13", 0xB6, "U14",
707 0xB9, "U17", 0xBA, "U18", 0xBC, "U20", 0xBF, "U23",
708 0xC1, "U25", 0xC2, "U26", 0xC4, "U28", 0xC7, "U31",
709 0xE0, "U24", 0xE3, "U27", 0xE5, "U29", 0xE6, "U30"
710};
711
712memlog (m, mcr)
713 int m;
714 struct mcr *mcr;
715{
716 register i;
717
2d192058 718 switch (mcrtype[m]) {
f25ccb7b
SL
719
720#if VAX780
2d192058 721 case M780C:
f25ccb7b 722 for (i = 0; i < (sizeof (memlogtab) / sizeof (memlogtab[0])); i++)
2d192058 723 if ((u_char)(M780C_SYN(mcr)) == memlogtab[i].m_syndrome) {
f25ccb7b
SL
724 printf (
725 "mcr%d: replace %s chip in %s bank of memory board %d (0-15)\n",
726 m,
727 memlogtab[i].m_chip,
2d192058
MK
728 (M780C_ADDR(mcr) & 0x8000) ? "upper" : "lower",
729 (M780C_ADDR(mcr) >> 16));
f25ccb7b
SL
730 return;
731 }
732 printf ("mcr%d: multiple errors, not traceable\n", m);
733 break;
734#endif
735 }
736}
737#endif
738
79821b2c
BJ
739/*
740 * Invalidate single all pte's in a cluster
741 */
742tbiscl(v)
743 unsigned v;
744{
745 register caddr_t addr; /* must be first reg var */
746 register int i;
747
748 asm(".set TBIS,58");
749 addr = ptob(v);
750 for (i = 0; i < CLSIZE; i++) {
751#ifdef lint
752 mtpr(TBIS, addr);
753#else
754 asm("mtpr r11,$TBIS");
755#endif
756 addr += NBPG;
757 }
758}
b559a38a 759
0dc06be8
BJ
760int waittime = -1;
761
ee0d32a8
MK
762boot(arghowto)
763 int arghowto;
0dc06be8
BJ
764{
765 register int howto; /* r11 == how to boot */
766 register int devtype; /* r10 == major of root dev */
767
768 howto = arghowto;
cf19cacc 769 if ((howto&RB_NOSYNC)==0 && waittime < 0 && bfreelist[0].b_forw) {
4a3fcdaa
MK
770 register struct buf *bp;
771 int iter, nbusy;
772
0dc06be8 773 waittime = 0;
56652904 774 (void) splnet();
87771f34 775 printf("syncing disks... ");
75395bd6
MK
776 /*
777 * Release inodes held by texts before update.
778 */
779 xumount(NODEV);
56652904 780 update();
62364f0e 781
4a3fcdaa 782 for (iter = 0; iter < 20; iter++) {
68503f9a
BJ
783 nbusy = 0;
784 for (bp = &buf[nbuf]; --bp >= buf; )
cd0e9146 785 if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
68503f9a
BJ
786 nbusy++;
787 if (nbusy == 0)
788 break;
789 printf("%d ", nbusy);
b359d7d6 790 DELAY(40000 * iter);
68503f9a 791 }
4a3fcdaa
MK
792 if (nbusy)
793 printf("giving up\n");
794 else
795 printf("done\n");
75395bd6
MK
796 /*
797 * If we've been adjusting the clock, the todr
798 * will be out of synch; adjust it now.
799 */
800 resettodr();
0dc06be8
BJ
801 }
802 splx(0x1f); /* extreme priority */
803 devtype = major(rootdev);
2de46def
BJ
804 if (howto&RB_HALT) {
805 printf("halting (in tight loop); hit\n\t^P\n\tHALT\n\n");
806 mtpr(IPL, 0x1f);
807 for (;;)
808 ;
809 } else {
ee0d32a8 810 if (howto & RB_DUMP) {
2cce526e 811 doadump(); /* TXDB_BOOT's itself */
68503f9a
BJ
812 /*NOTREACHED*/
813 }
48575cec 814 tocons(TXDB_BOOT);
2de46def 815 }
90dc7048
BK
816#if defined(VAX750) || defined(VAX730) || defined(VAX630)
817 if (cpu == VAX_750 || cpu == VAX_730 || cpu == VAX_630)
e5a79c70 818 { asm("movl r11,r5"); } /* boot flags go in r5 */
48575cec 819#endif
0dc06be8
BJ
820 for (;;)
821 asm("halt");
4a3fcdaa
MK
822#ifdef lint
823 printf("howto %d, devtype %d\n", arghowto, devtype);
824#endif
858ecf0f
BJ
825 /*NOTREACHED*/
826}
827
828tocons(c)
829{
2cce526e 830 register oldmask;
858ecf0f 831
2cce526e 832 while (((oldmask = mfpr(TXCS)) & TXCS_RDY) == 0)
858ecf0f 833 continue;
2cce526e
MK
834
835 switch (cpu) {
836
90dc7048 837#if VAX780 || VAX750 || VAX730 || VAX630
2cce526e
MK
838 case VAX_780:
839 case VAX_750:
840 case VAX_730:
90dc7048 841 case VAX_630:
2cce526e
MK
842 c |= TXDB_CONS;
843 break;
844#endif
845
846#if VAX8600
847 case VAX_8600:
848 mtpr(TXCS, TXCS_LCONS | TXCS_WMASK);
849 while ((mfpr(TXCS) & TXCS_RDY) == 0)
850 continue;
851 break;
852#endif
853 }
854
858ecf0f 855 mtpr(TXDB, c);
2cce526e
MK
856
857#if VAX8600
858 switch (cpu) {
859
860 case VAX_8600:
861 while ((mfpr(TXCS) & TXCS_RDY) == 0)
862 continue;
863 mtpr(TXCS, oldmask | TXCS_WMASK);
864 break;
865 }
866#endif
0dc06be8 867}
2de46def 868
cb9c8b95
SL
869int dumpmag = 0x8fca0101; /* magic number for savecore */
870int dumpsize = 0; /* also for savecore */
2de46def
BJ
871/*
872 * Doadump comes here after turning off memory management and
873 * getting on the dump stack, either when called above, or by
874 * the auto-restart code.
875 */
876dumpsys()
877{
878
4b1492fc 879 rpb.rp_flag = 1;
233e2ac3
MK
880 if (dumpdev == NODEV)
881 return;
ed28af96 882#ifdef notdef
2de46def
BJ
883 if ((minor(dumpdev)&07) != 1)
884 return;
ed28af96 885#endif
233e2ac3
MK
886 /*
887 * For dumps during autoconfiguration,
888 * if dump device has already configured...
889 */
890 if (dumplo == 0 && bdevsw[major(dumpdev)].d_psize)
891 dumplo = (*bdevsw[major(dumpdev)].d_psize)(dumpdev) - physmem;
892 if (dumplo < 0)
893 dumplo = 0;
cb9c8b95 894 dumpsize = physmem;
2de46def 895 printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
dca3793c
BJ
896 printf("dump ");
897 switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
898
899 case ENXIO:
900 printf("device bad\n");
901 break;
902
903 case EFAULT:
904 printf("device not ready\n");
905 break;
906
907 case EINVAL:
908 printf("area improper\n");
909 break;
910
911 case EIO:
912 printf("i/o error");
913 break;
914
915 default:
916 printf("succeeded");
917 break;
918 }
2de46def 919}
a58c4eb5 920
dca3793c
BJ
921/*
922 * Machine check error recovery code.
923 * Print out the machine check frame and then give up.
924 */
6692a5c8 925#if VAX8600
b5dd6ff7 926#define NMC8600 7
6692a5c8
JB
927char *mc8600[] = {
928 "unkn type", "fbox error", "ebox error", "ibox error",
b5dd6ff7 929 "mbox error", "tbuf error", "mbox 1D error"
6692a5c8 930};
b5dd6ff7
JB
931/* codes for above */
932#define MC_FBOX 1
933#define MC_EBOX 2
934#define MC_IBOX 3
935#define MC_MBOX 4
936#define MC_TBUF 5
937#define MC_MBOX1D 6
938
939/* error bits */
940#define MBOX_FE 0x8000 /* Mbox fatal error */
941#define FBOX_SERV 0x10000000 /* Fbox service error */
942#define IBOX_ERR 0x2000 /* Ibox error */
943#define EBOX_ERR 0x1e00 /* Ebox error */
944#define MBOX_1D 0x81d0000 /* Mbox 1D error */
945#define EDP_PE 0x200
6692a5c8 946#endif
b5dd6ff7 947
fca14b6b 948#if defined(VAX780) || defined(VAX750)
a58c4eb5
BJ
949char *mc780[] = {
950 "cp read", "ctrl str par", "cp tbuf par", "cp cache par",
951 "cp rdtimo", "cp rds", "ucode lost", 0,
952 0, 0, "ib tbuf par", 0,
953 "ib rds", "ib rd timo", 0, "ib cache par"
954};
b359d7d6
MK
955#define MC750_TBERR 2 /* type code of cp tbuf par */
956#define MC750_TBPAR 4 /* tbuf par bit in mcesr */
fca14b6b 957#endif
b5dd6ff7 958
10f66600
SL
959#if VAX730
960#define NMC730 12
961char *mc730[] = {
fca14b6b
BJ
962 "tb par", "bad retry", "bad intr id", "cant write ptem",
963 "unkn mcr err", "iib rd err", "nxm ref", "cp rds",
964 "unalgn ioref", "nonlw ioref", "bad ioaddr", "unalgn ubaddr",
965};
966#endif
90dc7048
BK
967#if VAX630
968#define NMC630 10
969extern struct ka630cpu ka630cpu;
970char *mc630[] = {
971 0, "immcr (fsd)", "immcr (ssd)", "fpu err 0",
972 "fpu err 7", "mmu st(tb)", "mmu st(m=0)", "pte in p0",
973 "pte in p1", "un intr id",
974};
975#endif
a58c4eb5 976
dca3793c 977/*
fca14b6b 978 * Frame for each cpu
dca3793c 979 */
a58c4eb5 980struct mc780frame {
fca14b6b 981 int mc8_bcnt; /* byte count == 0x28 */
dca3793c
BJ
982 int mc8_summary; /* summary parameter (as above) */
983 int mc8_cpues; /* cpu error status */
984 int mc8_upc; /* micro pc */
985 int mc8_vaviba; /* va/viba register */
986 int mc8_dreg; /* d register */
987 int mc8_tber0; /* tbuf error reg 0 */
988 int mc8_tber1; /* tbuf error reg 1 */
989 int mc8_timo; /* timeout address divided by 4 */
990 int mc8_parity; /* parity */
991 int mc8_sbier; /* sbi error register */
992 int mc8_pc; /* trapped pc */
993 int mc8_psl; /* trapped psl */
a78738a8
BJ
994};
995struct mc750frame {
fca14b6b 996 int mc5_bcnt; /* byte count == 0x28 */
dca3793c
BJ
997 int mc5_summary; /* summary parameter (as above) */
998 int mc5_va; /* virtual address register */
999 int mc5_errpc; /* error pc */
a78738a8 1000 int mc5_mdr;
dca3793c
BJ
1001 int mc5_svmode; /* saved mode register */
1002 int mc5_rdtimo; /* read lock timeout */
1003 int mc5_tbgpar; /* tb group parity error register */
1004 int mc5_cacherr; /* cache error register */
1005 int mc5_buserr; /* bus error register */
1006 int mc5_mcesr; /* machine check status register */
1007 int mc5_pc; /* trapped pc */
1008 int mc5_psl; /* trapped psl */
a58c4eb5 1009};
10f66600 1010struct mc730frame {
fca14b6b
BJ
1011 int mc3_bcnt; /* byte count == 0xc */
1012 int mc3_summary; /* summary parameter */
1013 int mc3_parm[2]; /* parameter 1 and 2 */
1014 int mc3_pc; /* trapped pc */
1015 int mc3_psl; /* trapped psl */
1016};
90dc7048
BK
1017struct mc630frame {
1018 int mc63_bcnt; /* byte count == 0xc */
1019 int mc63_summary; /* summary parameter */
1020 int mc63_mrvaddr; /* most recent vad */
1021 int mc63_istate; /* internal state */
1022 int mc63_pc; /* trapped pc */
1023 int mc63_psl; /* trapped psl */
1024};
6692a5c8
JB
1025struct mc8600frame {
1026 int mc6_bcnt; /* byte count == 0x58 */
1027 int mc6_ehmsts;
1028 int mc6_evmqsav;
1029 int mc6_ebcs;
1030 int mc6_edpsr;
1031 int mc6_cslint;
1032 int mc6_ibesr;
1033 int mc6_ebxwd1;
1034 int mc6_ebxwd2;
1035 int mc6_ivasav;
1036 int mc6_vibasav;
1037 int mc6_esasav;
1038 int mc6_isasav;
1039 int mc6_cpc;
1040 int mc6_mstat1;
1041 int mc6_mstat2;
1042 int mc6_mdecc;
1043 int mc6_merg;
1044 int mc6_cshctl;
1045 int mc6_mear;
1046 int mc6_medr;
1047 int mc6_accs;
1048 int mc6_cses;
1049 int mc6_pc; /* trapped pc */
1050 int mc6_psl; /* trapped psl */
1051};
a58c4eb5 1052
a78738a8
BJ
1053machinecheck(cmcf)
1054 caddr_t cmcf;
a58c4eb5 1055{
fca14b6b 1056 register u_int type = ((struct mc780frame *)cmcf)->mc8_summary;
a58c4eb5 1057
fca14b6b
BJ
1058 printf("machine check %x: ", type);
1059 switch (cpu) {
6692a5c8
JB
1060#if VAX8600
1061 case VAX_8600: {
1062 register struct mc8600frame *mcf = (struct mc8600frame *)cmcf;
1063
b5dd6ff7
JB
1064 if (mcf->mc6_ebcs & MBOX_FE)
1065 mcf->mc6_ehmsts |= MC_MBOX;
1066 else if (mcf->mc6_ehmsts & FBOX_SERV)
1067 mcf->mc6_ehmsts |= MC_FBOX;
1068 else if (mcf->mc6_ebcs & EBOX_ERR) {
1069 if (mcf->mc6_ebcs & EDP_PE)
1070 mcf->mc6_ehmsts |= MC_MBOX;
6692a5c8 1071 else
b5dd6ff7
JB
1072 mcf->mc6_ehmsts |= MC_EBOX;
1073 } else if (mcf->mc6_ehmsts & IBOX_ERR)
1074 mcf->mc6_ehmsts |= MC_IBOX;
1075 else if (mcf->mc6_mstat1 & M8600_TB_ERR)
1076 mcf->mc6_ehmsts |= MC_TBUF;
1077 else if ((mcf->mc6_cslint & MBOX_1D) == MBOX_1D)
1078 mcf->mc6_ehmsts |= MC_MBOX1D;
1079
6692a5c8
JB
1080 type = mcf->mc6_ehmsts & 0x7;
1081 if (type < NMC8600)
1082 printf("machine check %x: %s", type, mc8600[type]);
fca14b6b 1083 printf("\n");
6692a5c8
JB
1084 printf("\tehm.sts %x evmqsav %x ebcs %x edpsr %x cslint %x\n",
1085 mcf->mc6_ehmsts, mcf->mc6_evmqsav, mcf->mc6_ebcs,
1086 mcf->mc6_edpsr, mcf->mc6_cslint);
1087 printf("\tibesr %x ebxwd %x %x ivasav %x vibasav %x\n",
1088 mcf->mc6_ibesr, mcf->mc6_ebxwd1, mcf->mc6_ebxwd2,
1089 mcf->mc6_ivasav, mcf->mc6_vibasav);
1090 printf("\tesasav %x isasav %x cpc %x mstat %x %x mdecc %x\n",
1091 mcf->mc6_esasav, mcf->mc6_isasav, mcf->mc6_cpc,
1092 mcf->mc6_mstat1, mcf->mc6_mstat2, mcf->mc6_mdecc);
1093 printf("\tmerg %x cshctl %x mear %x medr %x accs %x cses %x\n",
1094 mcf->mc6_merg, mcf->mc6_cshctl, mcf->mc6_mear,
1095 mcf->mc6_medr, mcf->mc6_accs, mcf->mc6_cses);
1096 printf("\tpc %x psl %x\n", mcf->mc6_pc, mcf->mc6_psl);
1097 mtpr(EHSR, 0);
fca14b6b 1098 break;
6692a5c8 1099 };
fca14b6b 1100#endif
a78738a8
BJ
1101#if VAX780
1102 case VAX_780: {
1103 register struct mc780frame *mcf = (struct mc780frame *)cmcf;
6692a5c8 1104
a78738a8 1105 register int sbifs;
6692a5c8
JB
1106 printf("%s%s\n", mc780[type&0xf],
1107 (type&0xf0) ? " abort" : " fault");
a78738a8
BJ
1108 printf("\tcpues %x upc %x va/viba %x dreg %x tber %x %x\n",
1109 mcf->mc8_cpues, mcf->mc8_upc, mcf->mc8_vaviba,
1110 mcf->mc8_dreg, mcf->mc8_tber0, mcf->mc8_tber1);
1111 sbifs = mfpr(SBIFS);
1112 printf("\ttimo %x parity %x sbier %x pc %x psl %x sbifs %x\n",
1113 mcf->mc8_timo*4, mcf->mc8_parity, mcf->mc8_sbier,
1114 mcf->mc8_pc, mcf->mc8_psl, sbifs);
1115 /* THE FUNNY BITS IN THE FOLLOWING ARE FROM THE ``BLACK */
c063c4d3 1116 /* BOOK'' AND SHOULD BE PUT IN AN ``sbi.h'' */
a78738a8
BJ
1117 mtpr(SBIFS, sbifs &~ 0x2000000);
1118 mtpr(SBIER, mfpr(SBIER) | 0x70c0);
1119 break;
1120 }
1121#endif
1122#if VAX750
1123 case VAX_750: {
1124 register struct mc750frame *mcf = (struct mc750frame *)cmcf;
b359d7d6 1125
6692a5c8
JB
1126 int mcsr = mfpr(MCSR);
1127 printf("%s%s\n", mc780[type&0xf],
1128 (type&0xf0) ? " abort" : " fault");
b359d7d6
MK
1129 mtpr(TBIA, 0);
1130 mtpr(MCESR, 0xf);
4cc46db6 1131 printf("\tva %x errpc %x mdr %x smr %x rdtimo %x tbgpar %x cacherr %x\n",
a78738a8
BJ
1132 mcf->mc5_va, mcf->mc5_errpc, mcf->mc5_mdr, mcf->mc5_svmode,
1133 mcf->mc5_rdtimo, mcf->mc5_tbgpar, mcf->mc5_cacherr);
1134 printf("\tbuserr %x mcesr %x pc %x psl %x mcsr %x\n",
1135 mcf->mc5_buserr, mcf->mc5_mcesr, mcf->mc5_pc, mcf->mc5_psl,
b359d7d6
MK
1136 mcsr);
1137 if (type == MC750_TBERR && (mcf->mc5_mcesr&0xe) == MC750_TBPAR){
2fbfffcf 1138 printf("tbuf par: flushing and returning\n");
1ebc7878
BJ
1139 return;
1140 }
a78738a8
BJ
1141 break;
1142 }
fca14b6b 1143#endif
10f66600
SL
1144#if VAX730
1145 case VAX_730: {
1146 register struct mc730frame *mcf = (struct mc730frame *)cmcf;
6692a5c8
JB
1147
1148 if (type < NMC730)
1149 printf("%s", mc730[type]);
1150 printf("\n");
fca14b6b
BJ
1151 printf("params %x,%x pc %x psl %x mcesr %x\n",
1152 mcf->mc3_parm[0], mcf->mc3_parm[1],
1153 mcf->mc3_pc, mcf->mc3_psl, mfpr(MCESR));
1154 mtpr(MCESR, 0xf);
1155 break;
1156 }
a78738a8 1157#endif
90dc7048
BK
1158#if VAX630
1159 case VAX_630: {
1160 register struct ka630cpu *ka630addr = &ka630cpu;
1161 register struct mc630frame *mcf = (struct mc630frame *)cmcf;
1162 printf("vap %x istate %x pc %x psl %x\n",
1163 mcf->mc63_mrvaddr, mcf->mc63_istate,
1164 mcf->mc63_pc, mcf->mc63_psl);
1165 if (ka630addr->ka630_mser & KA630MSER_MERR) {
1166 printf("mser=0x%x ",ka630addr->ka630_mser);
1167 if (ka630addr->ka630_mser & KA630MSER_CPUER)
1168 printf("page=%d",ka630addr->ka630_cear);
1169 if (ka630addr->ka630_mser & KA630MSER_DQPE)
1170 printf("page=%d",ka630addr->ka630_dear);
1171 printf("\n");
1172 }
1173 break;
1174 }
1175#endif
a78738a8 1176 }
af9a9a62 1177 memerr();
a58c4eb5
BJ
1178 panic("mchk");
1179}
9f159248 1180
f0266f2b
MK
1181/*
1182 * Return the best possible estimate of the time in the timeval
1183 * to which tvp points. We do this by reading the interval count
1184 * register to determine the time remaining to the next clock tick.
1185 * We must compensate for wraparound which is not yet reflected in the time
1186 * (which happens when the ICR hits 0 and wraps after the splhigh(),
1187 * but before the mfpr(ICR)). Also check that this time is no less than
1188 * any previously-reported time, which could happen around the time
1189 * of a clock adjustment. Just for fun, we guarantee that the time
1190 * will be greater than the value obtained by a previous call.
1191 */
9f159248 1192microtime(tvp)
75395bd6 1193 register struct timeval *tvp;
9f159248 1194{
75395bd6 1195 int s = splhigh();
f0266f2b
MK
1196 static struct timeval lasttime;
1197 register long t;
9f159248 1198
75395bd6 1199 *tvp = time;
f0266f2b
MK
1200 t = mfpr(ICR);
1201 if (t < -tick / 2 && (mfpr(ICCS) & ICCS_INT))
1202 t += tick;
1203 tvp->tv_usec += tick + t;
1204 if (tvp->tv_usec > 1000000) {
1205 tvp->tv_sec++;
1206 tvp->tv_usec -= 1000000;
1207 }
1208 if (tvp->tv_sec == lasttime.tv_sec &&
1209 tvp->tv_usec <= lasttime.tv_usec &&
626f8a2f 1210 (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) {
9f159248
BJ
1211 tvp->tv_sec++;
1212 tvp->tv_usec -= 1000000;
1213 }
f0266f2b 1214 lasttime = *tvp;
9f159248
BJ
1215 splx(s);
1216}
3df747ec
BJ
1217
1218physstrat(bp, strat, prio)
1219 struct buf *bp;
1220 int (*strat)(), prio;
1221{
1222 int s;
1223
1224 (*strat)(bp);
06e3ae9a
SL
1225 /* pageout daemon doesn't wait for pushed pages */
1226 if (bp->b_flags & B_DIRTY)
1227 return;
75395bd6 1228 s = splbio();
3df747ec
BJ
1229 while ((bp->b_flags & B_DONE) == 0)
1230 sleep((caddr_t)bp, prio);
1231 splx(s);
1232}
6692a5c8 1233
06126147 1234initcpu()
6692a5c8 1235{
06126147
MK
1236 /*
1237 * Enable cache.
1238 */
1239 switch (cpu) {
1240
6692a5c8
JB
1241#if VAX780
1242 case VAX_780:
06126147 1243 mtpr(SBIMT, 0x200000);
6692a5c8
JB
1244 break;
1245#endif
1246#if VAX750
1247 case VAX_750:
06126147 1248 mtpr(CADR, 0);
6692a5c8
JB
1249 break;
1250#endif
1251#if VAX8600
1252 case VAX_8600:
06126147 1253 mtpr(CSWP, 3);
6692a5c8 1254 break;
06126147
MK
1255#endif
1256 default:
1257 break;
1258 }
1259
1260 /*
1261 * Enable floating point accelerator if it exists
1262 * and has control register.
1263 */
1264 switch(cpu) {
1265
1266#if VAX8600 || VAX780
1267 case VAX_780:
1268 case VAX_8600:
1269 if ((mfpr(ACCS) & 0xff) != 0) {
1270 printf("Enabling FPA\n");
1271 mtpr(ACCS, 0x8000);
1272 }
6692a5c8
JB
1273#endif
1274 default:
1275 break;
1276 }
1277}