Subject: help with amiga interupts
To: None <amiga-dev@netbsd.org>
From: Tim Newsham <newsham@zang.kcc.hawaii.edu>
List: amiga-dev
Date: 11/07/1994 22:28:07
Hi,
  I'm having problems with some interupt stuff for another OS.
This is not for NetBSD so if you're not interested hit delete
now.

If you're still here, thank you for your time.  I'm trying to
break-out the interupts into the possible handlers.  The problem
is that the device drivers arent in the kernel.  Interupts
are delivered as messages by the kernel by deliver_isr(the_type);
Since its a message-passing scheme I cant chain interupts..
I cant call each possible routine in turn until one says
"it was for me, thanks" so I have to know what sort of interupt
types I expect to get ahead of time.  My biggest problem right
now is with the CIA chips.  when I get an interupt from PORTS
or EXTERN from the cia chip, I clear the flags as I should.  I
usually (but not always) get a second interupt right afterwards
to PORTS or EXTERNS but the CIA reports that it isnt from it.
The strange thing is that it happens very regularly.  Ie. If
I hit a key and get a PORTS interupt for CIA, I then get another
PORTS interupt right afterwards.  Almost every time I hit
a key.  

Here's the code fragment,  I included a bit extra at the start
for context but the important stuff is all in the big switch().
Any comments on the feasibility of this approach (should I
just give up with the message passing scheme on the amiga
hardware for PORTS and EXTERN?) or any suggestions or flaws
you see I'd appreciate it.  Thank you.


----


/*
 * interrupt()
 *	Common code for all CPU interrupts
 */
void
interrupt(ulong place_holder)
{
	struct trapframe *f = (struct trapframe *)&place_holder;
	int level = f->traptype;
	unsigned short ireq;
	unsigned char ciairq;
	extern void hardclock();

	extern ushort custom_mask;
	extern ushort ciaa_mask, ciab_mask;

#ifdef KDB
	dbg_trap_frame = f;
#endif
	/*
	 * Sanity check and fold into range 0..MAX_IRQ-1.  Enable
	 * further interrupts from the ICU--interrupts are still
	 * masked on-chip.
	 */
	ASSERT(level < 8 && level > 0, "interrupt: bad level from locore");

	/* 
	 * get list of interupts.  clear all
	 * and ignore what we dont care about 
	 */
	ireq = CUSTOMbase->intreqr;
	CUSTOMbase->intreq = ireq;
	ireq &= custom_mask;
	if(!ireq)
		return;

	switch(level) {
	case 1:
		if(ireq & INTF_TBE) 
			deliver_isr(ISR_TBE);
		if(ireq & INTF_DSKBLK) 
			deliver_isr(ISR_DSKBLK);
		if(ireq & INTF_SOFTINT)
			deliver_isr(ISR_SOFTINT);
		break;
	case 2:
		if(ireq & INTF_PORTS) {
			ciairq = CIAAbase->icr;
			
			if((ciairq & CIA_ICR_IR_SC)) {
				ciairq &= ciaa_mask;

				if(ciairq & CIA_ICR_TA)
					deliver_isr(ISR_A_TA);
				if(ciairq & CIA_ICR_TB)
					deliver_isr(ISR_A_TB);
				if(ciairq & CIA_ICR_ALARM)
					deliver_isr(ISR_A_ALARM);
				if(ciairq & CIA_ICR_SP)
					deliver_isr(ISR_A_SP);
				if(ciairq & CIA_ICR_FLG)
					deliver_isr(ISR_A_FLG);
			} else {
				deliver_isr(ISR_PORTS);
			}
		}
		break;
	case 3:
		if(ireq & INTF_BLIT) 
			deliver_isr(ISR_BLIT);
		if(ireq & INTF_COPER) 
			deliver_isr(ISR_COPER);
		if(ireq & INTF_VERTB) 
			deliver_isr(ISR_VERTB);
		break;
	case 4:
		if(ireq & INTF_AUD3) 
			deliver_isr(ISR_AUD3);
		if(ireq & INTF_AUD2)
			deliver_isr(ISR_AUD2);
		if(ireq & INTF_AUD1)
			deliver_isr(ISR_AUD1);
		if(ireq & INTF_AUD0)
			deliver_isr(ISR_AUD0);
		break;
	case 5:
		if(ireq & INTF_RBF)
			deliver_isr(ISR_RBF);
		if(ireq & INTF_DSKSYNC)
			deliver_isr(ISR_DSKSYNC);
		break;
	case 6:
		/* cia timer A is hardwired -> hardclock */
		if(ireq & INTF_EXTER) {
			ciairq = CIABbase->icr;

			if(ciairq & CIA_ICR_IR_SC) {
				ciairq &= ciab_mask;

				/* HARDWIRED */
				if(ciairq & CIA_ICR_TA) 
					hardclock(f);

				if(ciairq & CIA_ICR_TB)
					deliver_isr(ISR_B_TA);
				if(ciairq & CIA_ICR_ALARM)
					deliver_isr(ISR_B_ALARM);
				if(ciairq & CIA_ICR_SP)
					deliver_isr(ISR_B_SP);
				if(ciairq & CIA_ICR_FLG)
					deliver_isr(ISR_B_FLG);
			}
#ifdef nope 
			 else
				deliver_isr(ISR_EXTER);
#endif
		}
		break;
	case 7: 
		printf("got nmi.  ignoring\n");
/*		deliver_isr(ISR_NMI); */
		break;
	}

....