xref: /original-bsd/sys/news3400/news3400/trap.c (revision 77040245)
1 /*
2  * Copyright (c) 1988 University of Utah.
3  * Copyright (c) 1992 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * the Systems Programming Group of the University of Utah Computer
8  * Science Department, Ralph Campbell, Sony Corp. and Kazumasa Utashiro
9  * of Software Research Associates, Inc.
10  *
11  * %sccs.include.redist.c%
12  *
13  * from: Utah $Hdr: trap.c 1.32 91/04/06$
14  *
15  *	@(#)trap.c	7.2 (Berkeley) 06/25/92
16  */
17 
18 #include "../include/fix_machine_type.h"
19 #include "param.h"
20 #include "systm.h"
21 #include "proc.h"
22 #include "kernel.h"
23 #include "signalvar.h"
24 #include "user.h"
25 #include "buf.h"
26 #ifdef KTRACE
27 #include "ktrace.h"
28 #endif
29 #include "net/netisr.h"
30 
31 #include "../include/trap.h"
32 #include "../include/psl.h"
33 #include "../include/reg.h"
34 #include "../include/cpu.h"
35 #include "../include/pte.h"
36 #include "../include/mips_opcode.h"
37 #include "../include/adrsmap.h"
38 
39 #include "vm/vm.h"
40 #include "vm/vm_kern.h"
41 #include "vm/vm_page.h"
42 
43 #include "lp.h"
44 #include "bm.h"
45 #include "ms.h"
46 #include "en.h"
47 #include "../hbdev/dmac_0448.h"
48 #include "../sio/scc.h"
49 
50 /*
51  * This is a kludge to allow X windows to work.
52  */
53 #undef X_KLUGE
54 
55 #ifdef X_KLUGE
56 #define USER_MAP_ADDR	0x4000
57 #define NPTES 300
58 static pt_entry_t UserMapPtes[NPTES];
59 static unsigned nUserMapPtes;
60 static pid_t UserMapPid;
61 #endif
62 
63 struct	proc *machFPCurProcPtr;		/* pointer to last proc to use FP */
64 
65 extern void MachKernGenException();
66 extern void MachUserGenException();
67 extern void MachKernIntr();
68 extern void MachUserIntr();
69 extern void MachTLBModException();
70 extern void MachTLBMissException();
71 extern void MemErrorInterrupt();
72 extern unsigned MachEmulateBranch();
73 
74 void (*machExceptionTable[])() = {
75 /*
76  * The kernel exception handlers.
77  */
78 	MachKernIntr,			/* external interrupt */
79 	MachKernGenException,		/* TLB modification */
80 	MachTLBMissException,		/* TLB miss (load or instr. fetch) */
81 	MachTLBMissException,		/* TLB miss (store) */
82 	MachKernGenException,		/* address error (load or I-fetch) */
83 	MachKernGenException,		/* address error (store) */
84 	MachKernGenException,		/* bus error (I-fetch) */
85 	MachKernGenException,		/* bus error (load or store) */
86 	MachKernGenException,		/* system call */
87 	MachKernGenException,		/* breakpoint */
88 	MachKernGenException,		/* reserved instruction */
89 	MachKernGenException,		/* coprocessor unusable */
90 	MachKernGenException,		/* arithmetic overflow */
91 	MachKernGenException,		/* reserved */
92 	MachKernGenException,		/* reserved */
93 	MachKernGenException,		/* reserved */
94 /*
95  * The user exception handlers.
96  */
97 	MachUserIntr,
98 	MachUserGenException,
99 	MachUserGenException,
100 	MachUserGenException,
101 	MachUserGenException,
102 	MachUserGenException,
103 	MachUserGenException,
104 	MachUserGenException,
105 	MachUserGenException,
106 	MachUserGenException,
107 	MachUserGenException,
108 	MachUserGenException,
109 	MachUserGenException,
110 	MachUserGenException,
111 	MachUserGenException,
112 	MachUserGenException,
113 };
114 
115 char	*trap_type[] = {
116 	"external interrupt",
117 	"TLB modification",
118 	"TLB miss (load or instr. fetch)",
119 	"TLB miss (store)",
120 	"address error (load or I-fetch)",
121 	"address error (store)",
122 	"bus error (I-fetch)",
123 	"bus error (load or store)",
124 	"system call",
125 	"breakpoint",
126 	"reserved instruction",
127 	"coprocessor unusable",
128 	"arithmetic overflow",
129 	"reserved 13",
130 	"reserved 14",
131 	"reserved 15",
132 };
133 
134 #ifdef DEBUG
135 #define TRAPSIZE	10
136 struct trapdebug {		/* trap history buffer for debugging */
137 	u_int	status;
138 	u_int	cause;
139 	u_int	vadr;
140 	u_int	pc;
141 	u_int	ra;
142 	u_int	code;
143 } trapdebug[TRAPSIZE], *trp = trapdebug;
144 #endif
145 
146 /*
147  * Handle an exception.
148  * Called from MachKernGenException() or MachUserGenException()
149  * when a processor trap occurs.
150  * In the case of a kernel trap, we return the pc where to resume if
151  * ((struct pcb *)UADDR)->pcb_onfault is set, otherwise, return old pc.
152  */
153 unsigned
154 trap(statusReg, causeReg, vadr, pc, args)
155 	unsigned statusReg;	/* status register at time of the exception */
156 	unsigned causeReg;	/* cause register at time of exception */
157 	unsigned vadr;		/* address (if any) the fault occured on */
158 	unsigned pc;		/* program counter where to continue */
159 {
160 	register int type, i;
161 	unsigned ucode = 0;
162 	register struct proc *p = curproc;
163 	struct timeval syst;
164 	vm_prot_t ftype;
165 	extern unsigned onfault_table[];
166 
167 #ifdef DEBUG
168 	trp->status = statusReg;
169 	trp->cause = causeReg;
170 	trp->vadr = vadr;
171 	trp->pc = pc;
172 	trp->ra = !USERMODE(statusReg) ? ((int *)&args)[19] :
173 		p->p_md.md_regs[RA];
174 	trp->code = 0;
175 	if (++trp == &trapdebug[TRAPSIZE])
176 		trp = trapdebug;
177 #endif
178 
179 	cnt.v_trap++;
180 	type = (causeReg & MACH_CR_EXC_CODE) >> MACH_CR_EXC_CODE_SHIFT;
181 	if (USERMODE(statusReg)) {
182 		type |= T_USER;
183 		syst = p->p_stime;
184 	}
185 
186 	/*
187 	 * Enable hardware interrupts if they were on before.
188 	 * We only respond to software interrupts when returning to user mode.
189 	 */
190 	if (statusReg & MACH_SR_INT_ENA_PREV)
191 		splx((statusReg & MACH_HARD_INT_MASK) | MACH_SR_INT_ENA_CUR);
192 
193 	switch (type) {
194 	case T_TLB_MOD:
195 		if ((int)vadr < 0) {
196 			register pt_entry_t *pte;
197 			register unsigned entry;
198 #ifndef ATTR
199 			register vm_offset_t pa;
200 #endif
201 
202 			pte = kvtopte(vadr);
203 			entry = pte->pt_entry;
204 			if (entry & PG_RO) {
205 				/* write to read only page in the kernel */
206 				ftype = VM_PROT_WRITE;
207 				goto kernel_fault;
208 			}
209 			entry |= PG_M;
210 			pte->pt_entry = entry;
211 			vadr &= PG_FRAME;
212 			printf("trap: TLBupdate hi %x lo %x i %x\n", vadr,
213 				entry, MachTLBUpdate(vadr, entry)); /* XXX */
214 #ifdef ATTR
215 			pmap_attributes[atop(entry - KERNBASE)] |= PMAP_ATTR_MOD;
216 #else
217 			pa = entry & PG_FRAME;
218 			if (!IS_VM_PHYSADDR(pa))
219 				panic("trap: kmod");
220 			PHYS_TO_VM_PAGE(pa)->clean = FALSE;
221 #endif
222 			return (pc);
223 		}
224 		/* FALLTHROUGH */
225 
226 	case T_TLB_MOD+T_USER:
227 	    {
228 		pmap_hash_t hp;
229 #ifndef ATTR
230 		vm_offset_t pa;
231 #endif
232 #ifdef DIAGNOSTIC
233 		extern pmap_hash_t zero_pmap_hash;
234 		extern pmap_t cur_pmap;
235 
236 		if (cur_pmap->pm_hash == zero_pmap_hash)
237 			panic("tlbmod");
238 #endif
239 		hp = &((pmap_hash_t)PMAP_HASH_UADDR)[PMAP_HASH(vadr)];
240 		if (((hp->pmh_pte[0].high ^ vadr) & ~PGOFSET) == 0)
241 			i = 0;
242 		else if (((hp->pmh_pte[1].high ^ vadr) & ~PGOFSET) == 0)
243 			i = 1;
244 		else
245 			panic("trap: tlb umod not found");
246 		if (hp->pmh_pte[i].low & PG_RO) {
247 			ftype = VM_PROT_WRITE;
248 			goto dofault;
249 		}
250 		hp->pmh_pte[i].low |= PG_M;
251 		printf("trap: TLBupdate hi %x lo %x i %x\n",
252 			hp->pmh_pte[i].high, hp->pmh_pte[i].low,
253 			MachTLBUpdate(hp->pmh_pte[i].high, hp->pmh_pte[i].low)); /* XXX */
254 #ifdef ATTR
255 		pmap_attributes[atop(hp->pmh_pte[i].low - KERNBASE)] |=
256 			PMAP_ATTR_MOD;
257 #else
258 		pa = hp->pmh_pte[i].low & PG_FRAME;
259 		if (!IS_VM_PHYSADDR(pa))
260 			panic("trap: umod");
261 		PHYS_TO_VM_PAGE(pa)->clean = FALSE;
262 #endif
263 		if (!USERMODE(statusReg))
264 			return (pc);
265 		goto out;
266 	    }
267 
268 	case T_TLB_LD_MISS:
269 	case T_TLB_ST_MISS:
270 		ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ;
271 		if ((int)vadr < 0) {
272 			register vm_offset_t va;
273 			int rv;
274 
275 		kernel_fault:
276 			va = trunc_page((vm_offset_t)vadr);
277 			rv = vm_fault(kernel_map, va, ftype, FALSE);
278 			if (rv == KERN_SUCCESS)
279 				return (pc);
280 			if (i = ((struct pcb *)UADDR)->pcb_onfault) {
281 				((struct pcb *)UADDR)->pcb_onfault = 0;
282 				return (onfault_table[i]);
283 			}
284 			goto err;
285 		}
286 		goto dofault;
287 
288 	case T_TLB_LD_MISS+T_USER:
289 		ftype = VM_PROT_READ;
290 		goto dofault;
291 
292 	case T_TLB_ST_MISS+T_USER:
293 		ftype = VM_PROT_WRITE;
294 	dofault:
295 	    {
296 		register vm_offset_t va;
297 		register struct vmspace *vm = p->p_vmspace;
298 		register vm_map_t map = &vm->vm_map;
299 		int rv;
300 
301 #ifdef X_KLUGE
302 		if (p->p_pid == UserMapPid &&
303 		    (va = pmax_btop(vadr - USER_MAP_ADDR)) < nUserMapPtes) {
304 			register pt_entry_t *pte;
305 
306 			pte = &UserMapPtes[va];
307 			MachTLBWriteRandom((vadr & PG_FRAME) |
308 				(vm->vm_pmap.pm_tlbpid << VMMACH_TLB_PID_SHIFT),
309 				pte->pt_entry);
310 			return (pc);
311 		}
312 #endif
313 		va = trunc_page((vm_offset_t)vadr);
314 		rv = vm_fault(map, va, ftype, FALSE);
315 		if (rv != KERN_SUCCESS) {
316 			printf("vm_fault(%x, %x, %x, 0) -> %x ADR %x PC %x RA %x\n",
317 				map, va, ftype, rv, vadr, pc,
318 				!USERMODE(statusReg) ? ((int *)&args)[19] :
319 					p->p_md.md_regs[RA]); /* XXX */
320 			printf("\tpid %d %s PC %x RA %x\n", p->p_pid,
321 				p->p_comm, p->p_md.md_regs[PC],
322 				p->p_md.md_regs[RA]); /* XXX */
323 #ifdef DEBUG
324 			trapDump("vm_fault");
325 #endif
326 		}
327 		/*
328 		 * If this was a stack access we keep track of the maximum
329 		 * accessed stack size.  Also, if vm_fault gets a protection
330 		 * failure it is due to accessing the stack region outside
331 		 * the current limit and we need to reflect that as an access
332 		 * error.
333 		 */
334 		if ((caddr_t)va >= vm->vm_maxsaddr) {
335 			if (rv == KERN_SUCCESS) {
336 				unsigned nss;
337 
338 				nss = clrnd(btoc(USRSTACK-(unsigned)va));
339 				if (nss > vm->vm_ssize)
340 					vm->vm_ssize = nss;
341 			} else if (rv == KERN_PROTECTION_FAILURE)
342 				rv = KERN_INVALID_ADDRESS;
343 		}
344 		if (rv == KERN_SUCCESS) {
345 			if (!USERMODE(statusReg))
346 				return (pc);
347 			goto out;
348 		}
349 		if (!USERMODE(statusReg)) {
350 			if (i = ((struct pcb *)UADDR)->pcb_onfault) {
351 				((struct pcb *)UADDR)->pcb_onfault = 0;
352 				return (onfault_table[i]);
353 			}
354 			goto err;
355 		}
356 		ucode = vadr;
357 		i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
358 		break;
359 	    }
360 
361 	case T_ADDR_ERR_LD+T_USER:	/* misaligned or kseg access */
362 		if (vadr == KERNBASE) {
363 			struct args {
364 				int	i[1];
365 			} args;
366 			int rval[2];
367 
368 			/*
369 			 * Assume a signal handler is trying to return
370 			 * (see sendsig() and sigreturn()). We have to
371 			 * pop the sigframe struct to get the address of
372 			 * the sigcontext.
373 			 */
374 			args.i[0] = p->p_md.md_regs[SP] + 4 * sizeof(int);
375 			(void) sigreturn(curproc, &args, rval);
376 			goto out;
377 		}
378 		/* FALLTHROUGH */
379 
380 	case T_ADDR_ERR_ST+T_USER:	/* misaligned or kseg access */
381 	case T_BUS_ERR_IFETCH+T_USER:	/* BERR asserted to cpu */
382 	case T_BUS_ERR_LD_ST+T_USER:	/* BERR asserted to cpu */
383 		i = SIGSEGV;
384 		break;
385 
386 	case T_SYSCALL+T_USER:
387 	    {
388 		register int *locr0 = p->p_md.md_regs;
389 		register struct sysent *callp;
390 		unsigned int code;
391 		int numsys;
392 		struct args {
393 			int i[8];
394 		} args;
395 		int rval[2];
396 		struct sysent *systab;
397 		extern int nsysent;
398 
399 		cnt.v_syscall++;
400 		/* compute next PC after syscall instruction */
401 		if ((int)causeReg < 0)
402 			locr0[PC] = MachEmulateBranch(locr0, pc, 0, 0);
403 		else
404 			locr0[PC] += 4;
405 		systab = sysent;
406 		numsys = nsysent;
407 		code = locr0[V0];
408 #ifdef COMPAT_NEWSOS
409 		if (code >= 1000)
410 			code -= 1000;			/* too easy */
411 #endif
412 		if (code == 0) {			/* indir */
413 			code = locr0[A0];
414 #ifdef COMPAT_NEWSOS
415 			if (code >= 1000)
416 				code -= 1000;		/* too easy */
417 #endif
418 			if (code >= numsys)
419 				callp = &systab[0];	/* indir (illegal) */
420 			else
421 				callp = &systab[code];
422 			i = callp->sy_narg;
423 			args.i[0] = locr0[A1];
424 			args.i[1] = locr0[A2];
425 			args.i[2] = locr0[A3];
426 			if (i > 3) {
427 				i = copyin((caddr_t)(locr0[SP] +
428 						3 * sizeof(int)),
429 					(caddr_t)&args.i[3],
430 					(u_int)(i - 3) * sizeof(int));
431 				if (i) {
432 					locr0[V0] = i;
433 					locr0[A3] = 1;
434 #ifdef KTRACE
435 					if (KTRPOINT(p, KTR_SYSCALL))
436 						ktrsyscall(p->p_tracep, code,
437 							callp->sy_narg, args.i);
438 #endif
439 					goto done;
440 				}
441 			}
442 		} else {
443 			if (code >= numsys)
444 				callp = &systab[0];	/* indir (illegal) */
445 			else
446 				callp = &systab[code];
447 			i = callp->sy_narg;
448 			args.i[0] = locr0[A0];
449 			args.i[1] = locr0[A1];
450 			args.i[2] = locr0[A2];
451 			args.i[3] = locr0[A3];
452 			if (i > 4) {
453 				i = copyin((caddr_t)(locr0[SP] +
454 						4 * sizeof(int)),
455 					(caddr_t)&args.i[4],
456 					(u_int)(i - 4) * sizeof(int));
457 				if (i) {
458 					locr0[V0] = i;
459 					locr0[A3] = 1;
460 #ifdef KTRACE
461 					if (KTRPOINT(p, KTR_SYSCALL))
462 						ktrsyscall(p->p_tracep, code,
463 							callp->sy_narg, args.i);
464 #endif
465 					goto done;
466 				}
467 			}
468 		}
469 #ifdef KTRACE
470 		if (KTRPOINT(p, KTR_SYSCALL))
471 			ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
472 #endif
473 		rval[0] = 0;
474 		rval[1] = locr0[V1];
475 #ifdef DEBUG
476 		if (trp == trapdebug)
477 			trapdebug[TRAPSIZE - 1].code = code;
478 		else
479 			trp[-1].code = code;
480 #endif
481 #ifdef COMPAT_NEWSOS
482 	/* 151 = setenvp, 152 = sysnews, 162 = getdomainname KU:XXX */
483 	if (code == 151 || code == 152 || code == 162)
484 		i = 0;
485 	else
486 #endif
487 		i = (*callp->sy_call)(p, &args, rval);
488 if(i==EINVAL)
489 printf("EINVAL: pid=%d, code=%d\n", p->p_pid, code);
490 		/*
491 		 * Reinitialize proc pointer `p' as it may be different
492 		 * if this is a child returning from fork syscall.
493 		 */
494 		p = curproc;
495 		locr0 = p->p_md.md_regs;
496 #ifdef DEBUG
497 		{ int s;
498 		s = splhigh();
499 		trp->status = statusReg;
500 		trp->cause = causeReg;
501 		trp->vadr = locr0[SP];
502 		trp->pc = locr0[PC];
503 		trp->ra = locr0[RA];
504 		trp->code = -code;
505 		if (++trp == &trapdebug[TRAPSIZE])
506 			trp = trapdebug;
507 		splx(s);
508 		}
509 #endif
510 		if (i == ERESTART)
511 			locr0[PC] = pc;
512 		else if (i != EJUSTRETURN) {
513 			if (i) {
514 				locr0[V0] = i;
515 				locr0[A3] = 1;
516 			} else {
517 				locr0[V0] = rval[0];
518 				locr0[V1] = rval[1];
519 				locr0[A3] = 0;
520 			}
521 		}
522 		/* else if (i == EJUSTRETURN) */
523 			/* nothing to do */
524 	done:
525 #ifdef KTRACE
526 		if (KTRPOINT(p, KTR_SYSRET))
527 			ktrsysret(p->p_tracep, code, i, rval[0]);
528 #endif
529 
530 		goto out;
531 	    }
532 
533 	case T_BREAK+T_USER:
534 	    {
535 		register unsigned va, instr;
536 
537 		/* compute address of break instruction */
538 		va = pc;
539 		if ((int)causeReg < 0)
540 			va += 4;
541 
542 		/* read break instruction */
543 		instr = fuiword((caddr_t)va);
544 #ifdef KADB
545 		if (instr == MACH_BREAK_BRKPT || instr == MACH_BREAK_SSTEP)
546 			goto err;
547 #endif
548 		if (p->p_md.md_ss_addr != va || instr != MACH_BREAK_SSTEP) {
549 			i = SIGTRAP;
550 			break;
551 		}
552 
553 		/* restore original instruction and clear BP  */
554 		i = suiword((caddr_t)va, p->p_md.md_ss_instr);
555 		if (i < 0) {
556 			vm_offset_t sa, ea;
557 			int rv;
558 
559 			sa = trunc_page((vm_offset_t)va);
560 			ea = round_page((vm_offset_t)va+sizeof(int)-1);
561 			rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,
562 				VM_PROT_DEFAULT, FALSE);
563 			if (rv == KERN_SUCCESS) {
564 				i = suiword((caddr_t)va, p->p_md.md_ss_instr);
565 				(void) vm_map_protect(&p->p_vmspace->vm_map,
566 					sa, ea, VM_PROT_READ|VM_PROT_EXECUTE,
567 					FALSE);
568 			}
569 		}
570 		if (i < 0) {
571 			i = SIGTRAP;
572 			break;
573 		}
574 		p->p_md.md_ss_addr = 0;
575 		goto out;
576 	    }
577 
578 	case T_RES_INST+T_USER:
579 		i = SIGILL;
580 		break;
581 
582 	case T_COP_UNUSABLE+T_USER:
583 		if ((causeReg & MACH_CR_COP_ERR) != 0x10000000) {
584 			i = SIGILL;	/* only FPU instructions allowed */
585 			break;
586 		}
587 		MachSwitchFPState(machFPCurProcPtr, p->p_md.md_regs);
588 		machFPCurProcPtr = p;
589 		p->p_md.md_regs[PS] |= MACH_SR_COP_1_BIT;
590 		p->p_md.md_flags |= MDP_FPUSED;
591 		goto out;
592 
593 	case T_OVFLOW+T_USER:
594 		i = SIGFPE;
595 		break;
596 
597 	case T_ADDR_ERR_LD:	/* misaligned access */
598 	case T_ADDR_ERR_ST:	/* misaligned access */
599 	case T_BUS_ERR_LD_ST:	/* BERR asserted to cpu */
600 		if (i = ((struct pcb *)UADDR)->pcb_onfault) {
601 			((struct pcb *)UADDR)->pcb_onfault = 0;
602 			return (onfault_table[i]);
603 		}
604 		/* FALLTHROUGH */
605 
606 	default:
607 	err:
608 #ifdef KADB
609 	    {
610 		extern struct pcb kdbpcb;
611 
612 		if (USERMODE(statusReg))
613 			kdbpcb = p->p_addr->u_pcb;
614 		else {
615 			kdbpcb.pcb_regs[ZERO] = 0;
616 			kdbpcb.pcb_regs[AST] = ((int *)&args)[2];
617 			kdbpcb.pcb_regs[V0] = ((int *)&args)[3];
618 			kdbpcb.pcb_regs[V1] = ((int *)&args)[4];
619 			kdbpcb.pcb_regs[A0] = ((int *)&args)[5];
620 			kdbpcb.pcb_regs[A1] = ((int *)&args)[6];
621 			kdbpcb.pcb_regs[A2] = ((int *)&args)[7];
622 			kdbpcb.pcb_regs[A3] = ((int *)&args)[8];
623 			kdbpcb.pcb_regs[T0] = ((int *)&args)[9];
624 			kdbpcb.pcb_regs[T1] = ((int *)&args)[10];
625 			kdbpcb.pcb_regs[T2] = ((int *)&args)[11];
626 			kdbpcb.pcb_regs[T3] = ((int *)&args)[12];
627 			kdbpcb.pcb_regs[T4] = ((int *)&args)[13];
628 			kdbpcb.pcb_regs[T5] = ((int *)&args)[14];
629 			kdbpcb.pcb_regs[T6] = ((int *)&args)[15];
630 			kdbpcb.pcb_regs[T7] = ((int *)&args)[16];
631 			kdbpcb.pcb_regs[T8] = ((int *)&args)[17];
632 			kdbpcb.pcb_regs[T9] = ((int *)&args)[18];
633 			kdbpcb.pcb_regs[RA] = ((int *)&args)[19];
634 			kdbpcb.pcb_regs[MULLO] = ((int *)&args)[21];
635 			kdbpcb.pcb_regs[MULHI] = ((int *)&args)[22];
636 			kdbpcb.pcb_regs[PC] = pc;
637 			kdbpcb.pcb_regs[SR] = statusReg;
638 			bzero((caddr_t)&kdbpcb.pcb_regs[F0], 33 * sizeof(int));
639 		}
640 		if (kdb(causeReg, vadr, p, !USERMODE(statusReg)))
641 			return (kdbpcb.pcb_regs[PC]);
642 	    }
643 #else
644 #ifdef DEBUG
645 		trapDump("trap");
646 #endif
647 #endif
648 		panic("trap");
649 	}
650 	printf("trap: pid %d %s sig %d adr %x pc %x ra %x\n", p->p_pid,
651 		p->p_comm, i, vadr, pc, p->p_md.md_regs[RA]); /* XXX */
652 	trapsignal(p, i, ucode);
653 out:
654 	/*
655 	 * Note: we should only get here if returning to user mode.
656 	 */
657 	astpending = 0;
658 	while (i = CURSIG(p))
659 		psig(i);
660 	p->p_pri = p->p_usrpri;
661 	if (want_resched) {
662 		int s;
663 
664 		/*
665 		 * Since we are curproc, clock will normally just change
666 		 * our priority without moving us from one queue to another
667 		 * (since the running process is not on a queue.)
668 		 * If that happened after we setrq ourselves but before we
669 		 * swtch()'ed, we might not be on the queue indicated by
670 		 * our priority.
671 		 */
672 		s = splclock();
673 		setrq(p);
674 		p->p_stats->p_ru.ru_nivcsw++;
675 		swtch();
676 		splx(s);
677 		while (i = CURSIG(p))
678 			psig(i);
679 	}
680 	if (p->p_stats->p_prof.pr_scale) {
681 		int ticks;
682 		struct timeval *tv = &p->p_stime;
683 
684 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
685 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
686 		if (ticks)
687 			addupc(pc, &p->p_stats->p_prof, ticks);
688 	}
689 	curpri = p->p_pri;
690 	return (pc);
691 }
692 
693 /*
694  * Handle an interrupt.
695  * Called from MachKernIntr() or MachUserIntr()
696  * Note: curproc might be NULL.
697  */
698 interrupt(statusReg, causeReg, pc)
699 	unsigned statusReg;	/* status register at time of the exception */
700 	unsigned causeReg;	/* cause register at time of exception */
701 	unsigned pc;		/* program counter where to continue */
702 {
703 	register unsigned mask;
704 	clockframe cf;
705 
706 #ifdef DEBUG
707 	trp->status = statusReg;
708 	trp->cause = causeReg;
709 	trp->vadr = 0;
710 	trp->pc = pc;
711 	trp->ra = 0;
712 	trp->code = 0;
713 	if (++trp == &trapdebug[TRAPSIZE])
714 		trp = trapdebug;
715 #endif
716 
717 	mask = causeReg & statusReg;	/* pending interrupts & enable mask */
718 #ifndef NOPRIORITY
719 	if (mask & MACH_INT_MASK_5) {		/* level 5 interrupt */
720 		splx((MACH_SPL_MASK_8 & ~causeReg) | MACH_SR_INT_ENA_CUR);
721 		printf("level 5 interrupt: PC %x CR %x SR %x\n",
722 			pc, causeReg, statusReg);
723 		causeReg &= ~MACH_INT_MASK_5;
724 	}
725 	if (mask & MACH_INT_MASK_4) {		/* level 4 interrupt */
726 		/*
727 		 * asynchronous bus error
728 		 */
729 		splx((MACH_SPL_MASK_7 & ~causeReg) | MACH_SR_INT_ENA_CUR);
730 		printf("level 4 interrupt: PC %x CR %x SR %x\n",
731 			pc, causeReg, statusReg);
732 		*(char *)INTCLR0 = INTCLR0_BERR;
733 		causeReg &= ~MACH_INT_MASK_4;
734 	}
735 	if (mask & MACH_INT_MASK_3) {		/* level 3 interrupt */
736 		/*
737 		 * fp error
738 		 */
739 		splx((MACH_SPL_MASK_6 & ~causeReg) | MACH_SR_INT_ENA_CUR);
740 		if (!USERMODE(statusReg)) {
741 #ifdef DEBUG
742 			trapDump("fpintr");
743 #else
744 			printf("FPU interrupt: PC %x CR %x SR %x\n",
745 				pc, causeReg, statusReg);
746 #endif
747 		} else
748 			MachFPInterrupt(statusReg, causeReg, pc);
749 		causeReg &= ~MACH_INT_MASK_3;
750 	}
751 	if (mask & MACH_INT_MASK_2) {		/* level 2 interrupt */
752 		register int stat;
753 
754 		splx((MACH_SPL_MASK_5 & ~causeReg) | MACH_SR_INT_ENA_CUR);
755 		stat = *(volatile u_char *)INTST0;
756 		if (stat & INTST0_TIMINT) {	/* timer */
757 			static int led_count = 0;
758 
759 			*(volatile u_char *)INTCLR0 = INTCLR0_TIMINT;
760 			cf.pc = pc;
761 			cf.ps = statusReg;
762 			hardclock(cf);
763 			if (++led_count > hz) {
764 				led_count = 0;
765 				*(volatile u_char *)DEBUG_PORT ^= DP_LED1;
766 			}
767 		}
768 #if NBM > 0
769 		if (stat & INTST0_KBDINT)	/* keyboard */
770 			kbm_rint(SCC_KEYBOARD);
771 #endif
772 #if NMS > 0
773 		if (stat & INTST0_MSINT)	/* mouse */
774 			kbm_rint(SCC_MOUSE);
775 #endif
776 		causeReg &= ~MACH_INT_MASK_2;
777 	}
778 	if (mask & MACH_INT_MASK_1) {		/* level 1 interrupt */
779 		splx((MACH_SPL_MASK_4 & ~causeReg) | MACH_SR_INT_ENA_CUR);
780 		level1_intr();
781 		causeReg &= ~MACH_INT_MASK_1;
782 	}
783 	if (mask & MACH_INT_MASK_0) {		/* level 0 interrupt */
784 		splx((MACH_SPL_MASK_3 & ~causeReg) | MACH_SR_INT_ENA_CUR);
785 		level0_intr();
786 		causeReg &= ~MACH_INT_MASK_0;
787 	}
788 	splx((MACH_SPL_MASK_3 & ~causeReg) | MACH_SR_INT_ENA_CUR);
789 #else /* NOPRIORITY */
790 	/* handle clock interrupts ASAP */
791 	if (mask & MACH_INT_MASK_2) {		/* level 2 interrupt */
792 		register int stat;
793 
794 		stat = *(volatile u_char *)INTST0;
795 		if (stat & INTST0_TIMINT) {	/* timer */
796 			static int led_count = 0;
797 
798 			*(volatile u_char *)INTCLR0 = INTCLR0_TIMINT;
799 			cf.pc = pc;
800 			cf.ps = statusReg;
801 			hardclock(cf);
802 			if (++led_count > hz) {
803 				led_count = 0;
804 				*(volatile u_char *)DEBUG_PORT ^= DP_LED1;
805 			}
806 		}
807 #if NBM > 0
808 		if (stat & INTST0_KBDINT)	/* keyboard */
809 			kbm_rint(SCC_KEYBOARD);
810 #endif
811 #if NMS > 0
812 		if (stat & INTST0_MSINT)	/* mouse */
813 			kbm_rint(SCC_MOUSE);
814 #endif
815 		causeReg &= ~MACH_INT_MASK_2;	/* reenable clock interrupts */
816 	}
817 	/*
818 	 * Enable hardware interrupts which were enabled but not pending.
819 	 * We only respond to software interrupts when returning to spl0.
820 	 */
821 	splx((statusReg & ~causeReg & MACH_HARD_INT_MASK)|MACH_SR_INT_ENA_CUR);
822 
823 	if (mask & MACH_INT_MASK_5) {		/* level 5 interrupt */
824 		printf("level 5 interrupt: PC %x CR %x SR %x\n",
825 			pc, causeReg, statusReg);
826 		;
827 	}
828 	if (mask & MACH_INT_MASK_4) {		/* level 4 interrupt */
829 		/*
830 		 * asynchronous bus error
831 		 */
832 		printf("level 4 interrupt: PC %x CR %x SR %x\n",
833 			pc, causeReg, statusReg);
834 		*(char *)INTCLR0 = INTCLR0_BERR;
835 	}
836 	if (mask & MACH_INT_MASK_3) {		/* level 3 interrupt */
837 		/*
838 		 * fp error
839 		 */
840 		if (!USERMODE(statusReg)) {
841 #ifdef DEBUG
842 			trapDump("fpintr");
843 #else
844 			printf("FPU interrupt: PC %x CR %x SR %x\n",
845 				pc, causeReg, statusReg);
846 #endif
847 		} else
848 			MachFPInterrupt(statusReg, causeReg, pc);
849 	}
850 	if (mask & MACH_INT_MASK_1)		/* level 1 interrupt */
851 		level1_intr();
852 	if (mask & MACH_INT_MASK_0)		/* level 0 interrupt */
853 		level0_intr();
854 #endif /* NOPRIORITY */
855 	if (mask & MACH_SOFT_INT_MASK_0) {
856 		clockframe cf;
857 
858 		clearsoftclock();
859 		cnt.v_soft++;
860 		cf.pc = pc;
861 		cf.ps = statusReg;
862 		softclock(cf);
863 	}
864 	/* process network interrupt if we trapped or will very soon */
865 	if ((mask & MACH_SOFT_INT_MASK_1) ||
866 	    netisr && (statusReg & MACH_SOFT_INT_MASK_1)) {
867 		clearsoftnet();
868 		cnt.v_soft++;
869 #ifdef INET
870 		if (netisr & (1 << NETISR_ARP)) {
871 			netisr &= ~(1 << NETISR_ARP);
872 			arpintr();
873 		}
874 		if (netisr & (1 << NETISR_IP)) {
875 			netisr &= ~(1 << NETISR_IP);
876 			ipintr();
877 		}
878 #endif
879 #ifdef NS
880 		if (netisr & (1 << NETISR_NS)) {
881 			netisr &= ~(1 << NETISR_NS);
882 			nsintr();
883 		}
884 #endif
885 #ifdef ISO
886 		if (netisr & (1 << NETISR_ISO)) {
887 			netisr &= ~(1 << NETISR_ISO);
888 			clnlintr();
889 		}
890 #endif
891 	}
892 }
893 
894 /*
895  * This is called from MachUserIntr() if astpending is set.
896  * This is very similar to the tail of trap().
897  */
898 softintr(statusReg, pc)
899 	unsigned statusReg;	/* status register at time of the exception */
900 	unsigned pc;		/* program counter where to continue */
901 {
902 	register struct proc *p = curproc;
903 	register int i;
904 
905 	cnt.v_soft++;
906 	astpending = 0;
907 	while (i = CURSIG(p))
908 		psig(i);
909 	p->p_pri = p->p_usrpri;
910 	if (want_resched) {
911 		int s;
912 
913 		/*
914 		 * Since we are curproc, clock will normally just change
915 		 * our priority without moving us from one queue to another
916 		 * (since the running process is not on a queue.)
917 		 * If that happened after we setrq ourselves but before we
918 		 * swtch()'ed, we might not be on the queue indicated by
919 		 * our priority.
920 		 */
921 		s = splclock();
922 		setrq(p);
923 		p->p_stats->p_ru.ru_nivcsw++;
924 		swtch();
925 		splx(s);
926 		while (i = CURSIG(p))
927 			psig(i);
928 	}
929 	curpri = p->p_pri;
930 }
931 
932 #ifdef DEBUG
933 trapDump(msg)
934 	char *msg;
935 {
936 	register int i;
937 	int s;
938 
939 	s = splhigh();
940 	printf("trapDump(%s)\n", msg);
941 	for (i = 0; i < TRAPSIZE; i++) {
942 		if (trp == trapdebug)
943 			trp = &trapdebug[TRAPSIZE - 1];
944 		else
945 			trp--;
946 		if (trp->cause == 0)
947 			break;
948 		printf("%s: ADR %x PC %x CR %x SR %x\n",
949 			trap_type[(trp->cause & MACH_CR_EXC_CODE) >>
950 				MACH_CR_EXC_CODE_SHIFT],
951 			trp->vadr, trp->pc, trp->cause, trp->status);
952 		printf("   RA %x code %d\n", trp-> ra, trp->code);
953 	}
954 	bzero(trapdebug, sizeof(trapdebug));
955 	trp = trapdebug;
956 	splx(s);
957 }
958 #endif
959 
960 #ifdef X_KLUGE
961 /*
962  * This is a kludge to allow X windows to work.
963  */
964 caddr_t
965 vmUserMap(size, pa)
966 	int size;
967 	unsigned pa;
968 {
969 	register caddr_t v;
970 	unsigned off, entry;
971 
972 	if (nUserMapPtes == 0)
973 		UserMapPid = curproc->p_pid;
974 	else if (UserMapPid != curproc->p_pid)
975 		return ((caddr_t)0);
976 	off = pa & PGOFSET;
977 	size = btoc(off + size);
978 	if (nUserMapPtes + size > NPTES)
979 		return ((caddr_t)0);
980 	v = (caddr_t)(USER_MAP_ADDR + pmax_ptob(nUserMapPtes) + off);
981 	entry = (pa & 0x9ffff000) | PG_V | PG_M;
982 	if (pa >= MACH_UNCACHED_MEMORY_ADDR)
983 		entry |= PG_N;
984 	while (size > 0) {
985 		UserMapPtes[nUserMapPtes].pt_entry = entry;
986 		entry += NBPG;
987 		nUserMapPtes++;
988 		size--;
989 	}
990 	return (v);
991 }
992 
993 vmUserUnmap()
994 {
995 	int id;
996 
997 	nUserMapPtes = 0;
998 	if (UserMapPid == curproc->p_pid) {
999 		id = curproc->p_vmspace->vm_pmap.pm_tlbpid;
1000 		if (id >= 0)
1001 			MachTLBFlushPID(id);
1002 	}
1003 	UserMapPid = 0;
1004 }
1005 #endif
1006 
1007 /*
1008  *----------------------------------------------------------------------
1009  *
1010  * MemErrorInterrupt --
1011  *
1012  *	Handler an interrupt for the control register.
1013  *
1014  * Results:
1015  *	None.
1016  *
1017  * Side effects:
1018  *	None.
1019  *
1020  *----------------------------------------------------------------------
1021  */
1022 #ifdef NOTDEF
1023 static void
1024 MemErrorInterrupt()
1025 {
1026 
1027 }
1028 #endif
1029 
1030 /*
1031  * Return the resulting PC as if the branch was executed.
1032  */
1033 unsigned
1034 MachEmulateBranch(regsPtr, instPC, fpcCSR, allowNonBranch)
1035 	unsigned *regsPtr;
1036 	unsigned instPC;
1037 	unsigned fpcCSR;
1038 	int allowNonBranch;
1039 {
1040 	InstFmt inst;
1041 	unsigned retAddr;
1042 	int condition;
1043 	extern unsigned GetBranchDest();
1044 
1045 #if 0
1046 	printf("regsPtr=%x PC=%x Inst=%x fpcCsr=%x\n", regsPtr, instPC,
1047 		*(unsigned *)instPC, fpcCSR);
1048 #endif
1049 
1050 	inst = *(InstFmt *)instPC;
1051 	switch ((int)inst.JType.op) {
1052 	case OP_SPECIAL:
1053 		switch ((int)inst.RType.func) {
1054 		case OP_JR:
1055 		case OP_JALR:
1056 			retAddr = regsPtr[inst.RType.rs];
1057 			break;
1058 
1059 		default:
1060 			if (!allowNonBranch)
1061 				panic("MachEmulateBranch: Non-branch");
1062 			retAddr = instPC + 4;
1063 			break;
1064 		}
1065 		break;
1066 
1067 	case OP_BCOND:
1068 		switch ((int)inst.IType.rt) {
1069 		case OP_BLTZ:
1070 		case OP_BLTZAL:
1071 			if ((int)(regsPtr[inst.RType.rs]) < 0)
1072 				retAddr = GetBranchDest((InstFmt *)instPC);
1073 			else
1074 				retAddr = instPC + 8;
1075 			break;
1076 
1077 		case OP_BGEZAL:
1078 		case OP_BGEZ:
1079 			if ((int)(regsPtr[inst.RType.rs]) >= 0)
1080 				retAddr = GetBranchDest((InstFmt *)instPC);
1081 			else
1082 				retAddr = instPC + 8;
1083 			break;
1084 
1085 		default:
1086 			panic("MachEmulateBranch: Bad branch cond");
1087 		}
1088 		break;
1089 
1090 	case OP_J:
1091 	case OP_JAL:
1092 		retAddr = (inst.JType.target << 2) |
1093 			((unsigned)instPC & 0xF0000000);
1094 		break;
1095 
1096 	case OP_BEQ:
1097 		if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
1098 			retAddr = GetBranchDest((InstFmt *)instPC);
1099 		else
1100 			retAddr = instPC + 8;
1101 		break;
1102 
1103 	case OP_BNE:
1104 		if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
1105 			retAddr = GetBranchDest((InstFmt *)instPC);
1106 		else
1107 			retAddr = instPC + 8;
1108 		break;
1109 
1110 	case OP_BLEZ:
1111 		if ((int)(regsPtr[inst.RType.rs]) <= 0)
1112 			retAddr = GetBranchDest((InstFmt *)instPC);
1113 		else
1114 			retAddr = instPC + 8;
1115 		break;
1116 
1117 	case OP_BGTZ:
1118 		if ((int)(regsPtr[inst.RType.rs]) > 0)
1119 			retAddr = GetBranchDest((InstFmt *)instPC);
1120 		else
1121 			retAddr = instPC + 8;
1122 		break;
1123 
1124 	case OP_COP1:
1125 		switch (inst.RType.rs) {
1126 		case OP_BCx:
1127 		case OP_BCy:
1128 			if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
1129 				condition = fpcCSR & MACH_FPC_COND_BIT;
1130 			else
1131 				condition = !(fpcCSR & MACH_FPC_COND_BIT);
1132 			if (condition)
1133 				retAddr = GetBranchDest((InstFmt *)instPC);
1134 			else
1135 				retAddr = instPC + 8;
1136 			break;
1137 
1138 		default:
1139 			if (!allowNonBranch)
1140 				panic("MachEmulateBranch: Bad coproc branch instruction");
1141 			retAddr = instPC + 4;
1142 		}
1143 		break;
1144 
1145 	default:
1146 		if (!allowNonBranch)
1147 			panic("MachEmulateBranch: Non-branch instruction");
1148 		retAddr = instPC + 4;
1149 	}
1150 #if 0
1151 	printf("Target addr=%x\n", retAddr);
1152 #endif
1153 	return (retAddr);
1154 }
1155 
1156 unsigned
1157 GetBranchDest(InstPtr)
1158 	InstFmt *InstPtr;
1159 {
1160 	return ((unsigned)InstPtr + 4 + ((short)InstPtr->IType.imm << 2));
1161 }
1162 
1163 /*
1164  * This routine is called by procxmt() to single step one instruction.
1165  * We do this by storing a break instruction after the current instruction,
1166  * resuming execution, and then restoring the old instruction.
1167  */
1168 cpu_singlestep(p)
1169 	register struct proc *p;
1170 {
1171 	register unsigned va;
1172 	register int *locr0 = p->p_md.md_regs;
1173 	int i;
1174 
1175 	/* compute next address after current location */
1176 	va = MachEmulateBranch(locr0, locr0[PC], 0, 1);
1177 	if (p->p_md.md_ss_addr || p->p_md.md_ss_addr == va ||
1178 	    !useracc((caddr_t)va, 4, B_READ)) {
1179 		printf("SS %s (%d): breakpoint already set at %x (va %x)\n",
1180 			p->p_comm, p->p_pid, p->p_md.md_ss_addr, va); /* XXX */
1181 		return (EFAULT);
1182 	}
1183 	p->p_md.md_ss_addr = va;
1184 	p->p_md.md_ss_instr = fuiword((caddr_t)va);
1185 	i = suiword((caddr_t)va, MACH_BREAK_SSTEP);
1186 	if (i < 0) {
1187 		vm_offset_t sa, ea;
1188 		int rv;
1189 
1190 		sa = trunc_page((vm_offset_t)va);
1191 		ea = round_page((vm_offset_t)va+sizeof(int)-1);
1192 		rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,
1193 			VM_PROT_DEFAULT, FALSE);
1194 		if (rv == KERN_SUCCESS) {
1195 			i = suiword((caddr_t)va, MACH_BREAK_SSTEP);
1196 			(void) vm_map_protect(&p->p_vmspace->vm_map,
1197 				sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
1198 		}
1199 	}
1200 	if (i < 0)
1201 		return (EFAULT);
1202 	printf("SS %s (%d): breakpoint set at %x: %x (pc %x)\n",
1203 		p->p_comm, p->p_pid, p->p_md.md_ss_addr,
1204 		p->p_md.md_ss_instr, locr0[PC]); /* XXX */
1205 	return (0);
1206 }
1207 
1208 /*
1209  * news3400 - INT0 service routine.
1210  *
1211  * INTST0 bit	4:	dma
1212  *		3:	slot #1
1213  *		2:	slot #3
1214  *		1:	external #1
1215  *		0:	external #3
1216  */
1217 
1218 #define	LEVEL0_MASK	\
1219 	(INTST1_DMA|INTST1_SLOT1|INTST1_SLOT3|INTST1_EXT1|INTST1_EXT3)
1220 
1221 level0_intr()
1222 {
1223 	register int stat;
1224 
1225 	stat = *(volatile u_char *)INTST1 & LEVEL0_MASK;
1226 	*(u_char *)INTCLR1 = stat;
1227 
1228 	if (stat & INTST1_DMA)
1229 		dma_intr();
1230 	if (stat & INTST1_SLOT1)
1231 		exec_hb_intr2();
1232 #if NEN > 0
1233 	if (stat & INTST1_SLOT3) {
1234 		int s, t;
1235 
1236 		s = splimp();
1237 		t = lance_intr();
1238 		(void) splx(s);
1239 		if (t == 0)
1240 			exec_hb_intr4();
1241 	}
1242 #endif
1243 #if NLE > 0
1244 	if (stat & INTST1_SLOT3) {
1245 		int s;
1246 
1247 		s = splimp();
1248 		leintr(0);
1249 		(void) splx(s);
1250 	}
1251 #endif
1252 	if (stat & INTST1_EXT1)
1253 		print_int_stat("EXT #1");
1254 	if (stat & INTST1_EXT3)
1255 		print_int_stat("EXT #3");
1256 }
1257 
1258 /*
1259  * news3400 - INT1 service routine.
1260  *
1261  * INTST0 bit	1:	centro fault
1262  *		0:	centro busy
1263  * INTST1 bit	7:	beep
1264  *		6:	scc
1265  *		5:	lance
1266  */
1267 
1268 #define LEVEL1_MASK2	(INTST0_CFLT|INTST0_CBSY)
1269 #define LEVEL1_MASK1	(INTST1_BEEP|INTST1_SCC|INTST1_LANCE)
1270 
1271 level1_intr(pc)
1272 	unsigned pc;
1273 {
1274 	register int stat;
1275 	register u_int saved_inten1 = *(u_char *)INTEN1;
1276 
1277 	*(u_char *)INTEN1 = 0;		/* disable intr: beep, lance, scc */
1278 
1279 	stat = *(volatile u_char *)INTST1 & LEVEL1_MASK1;
1280 	*(u_char *)INTCLR1 = stat;
1281 
1282 	stat &= saved_inten1;
1283 
1284 	if (stat & INTST1_BEEP) {
1285 		*(volatile u_char *)INTCLR1 = INTCLR1_BEEP;
1286 		print_int_stat("BEEP");
1287 	}
1288 	if (stat & INTST1_SCC) {
1289 		scc_intr();
1290 		if (saved_inten1 & *(u_char *)INTST1 & INTST1_SCC)
1291 			scc_intr();
1292 	}
1293 #if NEN > 0
1294 	if (stat & INTST1_LANCE)
1295 		lance_intr();
1296 #endif
1297 #if NLE > 0
1298 	if (stat & INTST1_LANCE)
1299 		leintr(0);
1300 #endif
1301 
1302 	*(u_char *)INTEN1 = saved_inten1;
1303 
1304 #if NLP > 0
1305 	/*
1306 	 * The PARK2 cannot find centro interrupt correctly.
1307 	 * We must check it by reading the cause register of cpu
1308 	 * while other interrupts are disabled.
1309 	 */
1310 	{
1311 		register int causereg;
1312 		int s = splhigh();
1313 
1314 		causereg = get_causereg();
1315 		(void) splx(s);
1316 
1317 		if ((causereg & CAUSE_IP4) == 0)
1318 			return;
1319 	}
1320 #endif
1321 
1322 	stat = (int)(*(u_char *)INTST0) & LEVEL1_MASK2;
1323 	*(u_char *)INTCLR0 = stat;
1324 
1325 	if (stat & INTST0_CBSY)		/* centro busy */
1326 #if NLP > 0
1327 		lpxint(0);
1328 #else
1329 		printf("stray intr: CBSY\n");
1330 #endif
1331 }
1332 
1333 /*
1334  * DMA interrupt service routine.
1335  */
1336 dma_intr()
1337 {
1338         register volatile u_char *gsp = (u_char *)DMAC_GSTAT;
1339         register u_int gstat = *gsp;
1340         register int mrqb, i;
1341 
1342 	/*
1343 	 * when DMA intrrupt occurs there remain some untransferred data.
1344 	 * wait data transfer completion.
1345 	 */
1346 	mrqb = (gstat & (CH0_INT|CH1_INT|CH2_INT|CH3_INT)) << 1;
1347 	if (gstat & mrqb) {
1348 		/*
1349 		 * SHOULD USE DELAY()
1350 		 */
1351 		for (i = 0; i < 50; i++)
1352 			;
1353 		if (*gsp & mrqb)
1354 			printf("dma_intr: MRQ\n");
1355 	}
1356 
1357 	/* SCSI Dispatch */
1358 	if (gstat & CH_INT(CH_SCSI))
1359 		scintr();
1360 
1361 #include "fd.h"
1362 #if NFD > 0
1363         /* FDC Interrupt Dispatch */
1364 	if (gstat & CH_INT(CH_FDC))
1365 		fdc_intr(0);
1366 #endif /* NFD > 0 */
1367 
1368 #include "sb.h"
1369 #if NSB > 0
1370         /* Audio Interface Dispatch */
1371 	sbintr(0);
1372 #endif /* NSB > 0 */
1373 
1374         /* Video I/F Dispatch */
1375 	if (gstat & CH_INT(CH_VIDEO))
1376 		;
1377 }
1378 
1379 /*
1380  * SCC vector interrupt service routine.
1381  */
1382 scc_intr()
1383 {
1384 	int vec;
1385 	extern int scc_xint(), scc_sint(), scc_rint(), scc_cint();
1386 	static int (*func[])() = {
1387 		scc_xint,
1388 		scc_sint,
1389 		scc_rint,
1390 		scc_cint
1391 	};
1392 
1393 	vec = *(volatile u_char *)SCCVECT;
1394 	(*func[(vec & SCC_INT_MASK) >> 1])(vec);
1395 }
1396 
1397 print_int_stat(msg)
1398 	char *msg;
1399 {
1400 	int s0 = *(volatile u_char *)INTST0;
1401 	int s1 = *(volatile u_char *)INTST1;
1402 
1403 	if (msg)
1404 		printf("%s: ", msg);
1405 	else
1406 		printf("intr: ");
1407 	printf("INTST0=0x%x, INTST1=0x%x.\n", s0, s1);
1408 }
1409