Subject: Re: Interrupts
To: Michael <macallan18@earthlink.net>
From: Michael <macallan18@earthlink.net>
List: port-macppc
Date: 12/06/2004 00:28:41
Hello,
> This 'solution' is far from optimal - an active line without the corresponding interrupt bit set doesn't always mean a lost interrupt,
> and just ORing the level register on the interrupt register also locks things up - no idea why though.
> But I think we need something like this - better call IRQ handlers a little more often than lose interupts and get all kinds of
> nastiness.
Just had a look at the Darwin source ( thanks Allan for kicking me there ) - see http://darwinsource.opendarwin.org/10.0.1/xnu-124.1/iokit/Drivers/platform/drvAppleGrandCentral/ - the interesting part is this:
// Do all the sources for events, plus any pending interrupts.
// Also add in the "level" sensitive sources
maskTmp = lwbrx(maskReg);
events = lwbrx(eventsReg) & ~kTypeLevelMask;
events |= lwbrx(levelsReg) & maskTmp & kTypeLevelMask;
events |= pendingEvents & maskTmp;
pendingEvents = 0;
eieio();
So they OR in a few bits from the level register. kTypeLevelMask is defined as
#define kTypeLevelMask (0x3FF00000)
which means IRQ 20 - 29.
After that:
// Since we have to clear the level'd one clear the current edge's too.
stwbrx(kTypeLevelMask | events, clearReg);
eieio();
So it /always/ clears the PCI interrupts.
Also interesting:
#define kEventsOffset (0x00020)
#define kMaskOffset (0x00024)
#define kClearOffset (0x00028)
#define kLevelsOffset (0x0002C)
apparently Darwin thinks gc uses only 32 IRQs, while NetBSD thinks 64.
#define interrupt_reg (obio_base + 0x10)
#define INT_STATE_REG_H (interrupt_reg + 0x00)
#define INT_ENABLE_REG_H (interrupt_reg + 0x04)
#define INT_CLEAR_REG_H (interrupt_reg + 0x08)
#define INT_LEVEL_REG_H (interrupt_reg + 0x0c)
#define INT_STATE_REG_L (interrupt_reg + 0x10)
#define INT_ENABLE_REG_L (interrupt_reg + 0x14)
#define INT_CLEAR_REG_L (interrupt_reg + 0x18)
#define INT_LEVEL_REG_L (interrupt_reg + 0x1c)
have fun
Michael