[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;
+ }
+ }