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