[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: user-written interrupt handlers



>Date: Mon, 14 Feb 1994 11:47:04 -0800
>From: ersmith@netcom.com (Eric R. Smith)
>
>I would think that any user-supplied interrupt handlers should be provided
>as device drivers; they can then call into the kernel via the table that
>MiNT provides, and don't have to worry about going through trap #1.

Well, I decided I was taking an impossible tack, so I tried again from a
different angle... Now I have a new DOS call Psiginter(vec,sig) which will
install an interrupt handler for the user, that will send the calling process
the signal sig when the given interrupt occurs. I basically copied the Do_sig
code in intr.spp, pointing it to a routine that just does post_sig as
specified. Unfortunately, this doesn't work reliably; I get all kinds of
bizarre crashes. I don't suppose any of you could look it over and point out
what I'm not catching...?

The particular application is to handle DMA sound interrupts, fyi...


*** 1.1	1994/02/13 11:00:22
--- intr.spp	1994/02/14 21:40:17
***************
*** 225,228 ****
--- 225,283 ----
  	
  ;
+ ; Generic routine for handling any user-specified interrupts. On 68000, the
+ ; vector number is stored in the high byte of the program counter.
+ ;
+ 	XDEF	_new_intr
+ 
+ _new_intr:
+ ;	ori.w	#$0700,sr
+ 	subq.w	#2,sp		; reserve space for fake frame word
+ 	move.l	d0,-(sp)	; save d0
+ 
+ %ifndef ONLY030
+ 	tst.w	($59e.w)	; is frame format on stack?
+ 	bne.s	nvec		; yes, go use it
+ 	bsr.s	ndummy		; push PC to stack
+ 	nop
+ ndummy:	
+ 	move.l	(sp)+,d0	; pop PC to d0
+ 	swap	d0		; move hi word to lo word
+ 	lsr.w	#6,d0		; move hi byte into vector offset position
+ 	andi.b	#$fc,d0		; clear any garbage from lo 2 bits
+ 	bra.s	ngot		; continue
+ nvec:
+ %endif
+ 	move.w	12(sp),d0	; get frame word
+ 	andi.w	#$ffc,d0	; mask down to vector offset
+ ngot:
+ 	move.w	d0,4(sp)	; store vector offset
+ 	move.l	(sp)+,d0	; restore d0
+ 	tst.w	_in_kernel	; did we interrupt the kernel?
+ 	bne.s	kern_intr	; yes ...
+ 	move.l	_curproc,-(sp)
+ 	addq.l	#4,(sp)		; push offset of save area
+ 	jsr	_build_context	
+ 	move.w	4(sp),d0	; pull vector offset from stack to d0
+ 	move.l	_curproc,a4
+ 	move.l	(a4),sp		; get into system stack
+ 	move.w	d0,-(sp)	; save vector offset
+ 	jsr	_enter_kernel	
+ 	jsr	_sig_user	; send signal
+ 	ori.w	#$0700,sr		; spl7()
+ 	jsr	_leave_kernel		; leave kernel
+ 	addq.w	#4,a4			; get context save area address
+ 	move.l	a4,-(sp)		; push it
+ 	jsr	_restore_context	; restore the context
+ 
+ kern_intr:
+ 	movem.l	d0-d2/a0-a2,-(sp)	; save regs
+ 	move.w	24(sp),-(sp)		; copy vector offset up
+ 	jsr	_sig_user		; send signal
+ 	addq.w	#2,sp			; pop copy of vector offset
+ 	movem.l	(sp)+,d0-d2/a0-a2	; restore regs
+ 	addq.w	#2,sp			; pop vector offset
+ 	rte
+ 
+ ;
  ; New bus error handler for memory protection: get the ssp and
  ; put it in the proc structure before calling
*** 1.1	1994/02/14 21:38:04
--- dossig.c	1994/02/14 21:35:30
***************
*** 211,212 ****
--- 211,289 ----
  	return 0;
  }
+ 
+ /*
+  * p_sigintr: Set an exception vector to send us the specified signal.
+  */
+ 
+ typedef struct usig {
+ 	int vec;
+ 	int sig;
+ 	PROC *proc;
+ 	struct usig *next;
+ } usig;
+ 
+ static usig *usiglst;
+ extern long mcpu;	
+ 
+ long ARGS_ON_STACK
+ p_siginter(vec, sig)
+ 	int vec;
+ 	int sig;
+ {
+ 	extern void new_intr();
+ 	long vec2;
+ 	usig *new;
+ 
+ 	if (!sig)		/* ignore signal 0 */
+ 		return 0;
+ 
+ 	vec2 = (long) new_intr;
+ 
+ #ifndef ONLY030
+ 	if (mcpu == 0)
+ 		vec2 |= vec << 24;
+ #endif
+ 	new = kmalloc(sizeof(usig));
+ 	new->vec = vec;
+ 	new->sig = sig;
+ 	new->proc = curproc;
+ 	new->next = usiglst;
+ 	usiglst = new;
+ 
+ 	return setexc(vec, vec2);
+ }
+ 
+ /*
+  * Find the process that requested this interrupt, and send it a signal.
+  */
+ void ARGS_ON_STACK
+ sig_user(vec)
+ 	int vec;
+ {
+ 	usig *ptr;
+ 
+ 	vec >>= 2;
+ 	for (ptr = usiglst; ptr; ptr=ptr->next)
+ 		if (vec == ptr->vec) {
+ 			if (ptr->proc->wait_q != ZOMBIE_Q &&
+ 			    ptr->proc->wait_q != TSR_Q) {
+ 				post_sig(ptr->proc, ptr->sig);
+ 			}
+ 			if (vec >= 64 && vec < 80) {
+ 				/*
+ 				 * Clear in-service bit for ST MFP interrupts
+ 				 */
+ 				char *mfp, c;
+ 
+ 				if (vec < 72)		/* Register B */
+ 					mfp = (char *)0xfffffa11L;
+ 				else			/* Register A */
+ 					mfp = (char *)0xfffffa0fL;
+ 				c = 1 << (vec & 7);
+ 
+ 				*mfp = ~c;
+ 			}
+ 				
+ 			break;
+ 		}
+ }