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

Working Psigintr call...



Ok, life is much happier with MiNT 1.10. Here's my working version of the
stuff I sent out for comment before. Psigintr takes two arguments, an
exception vector number, and a signal number. It uses setexc to point the
exception handler for the given vector at a routine which just calls
post_sig. So, the requested signal is sent to the process that originally
called Psigintr... If you would care to see my double-buffered direct-to-disk
sound play/record program that uses this, drop me a line.
 -- Howard

*** 1.1	1994/02/17 16:16:26
--- dos.c	1994/02/17 16:17:52
***************
*** 603,605 ****
--- 603,606 ----
  	dos_tab[0x13c] = s_alert;
  	dos_tab[0x13d] = t_malarm;
+ 	dos_tab[0x13e] = p_sigintr;
  }
*** 1.1	1994/02/17 20:17:08
--- dosmem.c	1994/02/17 20:19:58
***************
*** 736,739 ****
--- 736,741 ----
  	}
  
+ /* cancel all user-specified interrupt signals */
+ 	cancelsigintrs();
  /* cancel all pending timeouts for this process */
  	cancelalltimeouts();
*** 1.1	1994/02/17 16:16:26
--- dossig.c	1994/02/17 23:35:26
***************
*** 211,212 ****
--- 211,319 ----
  	return 0;
  }
+ 
+ /*
+  * p_sigintr: Set an exception vector to send us the specified signal.
+  */
+ 
+ typedef struct usig {
+ 	int vec;		/* exception vector number */
+ 	int sig;		/* signal to send */
+ 	PROC *proc;		/* process to get signal */
+ 	long oldv;		/* old exception vector value */
+ 	struct usig *next;	/* next entry ... */
+ } usig;
+ 
+ static usig *usiglst;
+ extern long mcpu;
+ 
+ long ARGS_ON_STACK
+ p_sigintr(vec, sig)
+ 	int vec;
+ 	int sig;
+ {
+ 	extern void new_intr();	/* in intr.spp */
+ 	long vec2;
+ 	usig *new;
+ 
+ 	if (!sig)		/* ignore signal 0 */
+ 		return 0;
+ 
+ 	vec2 = (long) new_intr;
+ 
+ #ifndef ONLY030
+ 	if (mcpu == 0)			/* put vector number in high */
+ 		vec2 |= vec << 24;	/* byte of vector address */
+ #endif
+ 	new = kmalloc(sizeof(usig));
+ 	if (!new)			/* hope this never happens...! */
+ 		return ENSMEM;
+ 	new->vec = vec;
+ 	new->sig = sig;
+ 	new->proc = curproc;
+ 	new->next = usiglst;		/* simple unsorted list... */
+ 	usiglst = new;
+ 
+ 	new->oldv = setexc(vec, vec2);
+ 	return new->oldv;
+ }
+ 
+ /*
+  * Find the process that requested this interrupt, and send it a signal.
+  * Called at interrupt time by new_intr() from intr.spp, with interrupt
+  * vector number on the stack.
+  */
+ 
+ void ARGS_ON_STACK
+ sig_user(vec)
+ 	int vec;
+ {
+ 	usig *ptr;
+ 
+ 	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 0	/* Search entire list, to allow multiple processes to respond to
+ 	   the same interrupt. (Why/when would you want that?) */
+ 			break;
+ #endif
+ 		}
+ 	/*
+ 	 * Clear in-service bit for ST MFP interrupts
+ 	 */
+ 	if (vec >= 64 && vec < 80) {
+ 		char *mfp, c;
+ 
+ 		if (vec < 72)		/* Register B */
+ 			mfp = (char *)0xfffffa11L;
+ 		else			/* Register A */
+ 			mfp = (char *)0xfffffa0fL;
+ 		c = 1 << (vec & 7);
+ 
+ 		*mfp = ~c;
+ 	}
+ }
+ 
+ /*
+  * cancelsigintrs: remove any interrupts requested by this process, called
+  * at process termination.
+  */
+ void ARGS_ON_STACK
+ cancelsigintrs()
+ {
+ 	usig *ptr, *old;
+ 	short s = spl7();
+ 
+ 	for (old=NULL, ptr=usiglst; ptr; old=ptr, ptr=ptr->next)
+ 		if (ptr->proc == curproc) {
+ 			setexc(ptr->vec, ptr->oldv);
+ 			if (old)
+ 				old->next = ptr->next;
+ 			else
+ 				usiglst = ptr->next;
+ 			kfree(ptr);
+ 		}
+ 	spl(s);
+ }
*** 1.1	1994/02/17 16:16:26
--- intr.spp	1994/02/17 23:27:04
***************
*** 71,75 ****
  	clr.w	-(sp)			; yes, long frames: push a frame word
  L_short1:
! 	pea	L_comeback		; push fake PC
  	move.w	sr,-(sp)		; push status register
  	move.l	_old_vbl+8,-(sp)	; go service the interrupt
--- 71,75 ----
  	clr.w	-(sp)			; yes, long frames: push a frame word
  L_short1:
! 	pea	L_comeback(pc)		; push fake PC
  	move.w	sr,-(sp)		; push status register
  	move.l	_old_vbl+8,-(sp)	; go service the interrupt
***************
*** 235,238 ****
--- 235,268 ----
  	
  ;
+ ; 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:
+ 	movem.l	d0-d2/a0-a2,-(sp)	; save regs
+ 
+ %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.w	(sp)+,d0	; pop hi(PC) to d0
+ 	addq.w	#2,sp		; pop lo(PC) off stack
+ 	lsr.w	#8,d0		; move hi byte to vector number
+ 	bra.s	ngot		; continue
+ nvec:
+ %endif
+ 	move.w	30(sp),d0	; get frame word
+ 	lsr.w	#2,d0		; move vector offset to vector number
+ ngot:
+ 	move.w	d0,-(sp)	; push vector offset
+ 	jsr	_sig_user	; send signal
+ 	addq.w	#2,sp			; pop vector offset
+ 	movem.l	(sp)+,d0-d2/a0-a2	; restore regs
+ 	rte
+ 
+ ;
  ; New bus error handler for memory protection: get the ssp and
  ; put it in the proc structure before calling
*** 1.1	1994/02/17 16:33:50
--- proto.h	1994/02/17 20:30:28
***************
*** 167,170 ****
--- 167,172 ----
  long ARGS_ON_STACK p_sigpending P_((void));
  long ARGS_ON_STACK p_sigpause P_((ulong mask));
+ long ARGS_ON_STACK p_sigintr P_((int vec, int sig));
+ void cancelsigintrs P_((void));
  
  /* filesys.c */