#include <ppc/proc_reg.h>
#include <IOKit/IOLib.h>
#include <IOKit/IODeviceTreeSupport.h>
#include <IOKit/IODeviceMemory.h>
#include <IOKit/IOPlatformExpert.h>
#include <IOKit/platform/ApplePlatformExpert.h>
#include <IOKit/platform/AppleNMI.h>
#include "Heathrow.h"
#include <IOKit/ppc/IODBDMA.h>
#define super AppleMacIO
OSDefineMetaClassAndStructors(Heathrow, AppleMacIO);
bool Heathrow::start(IOService *provider)
{
bool ret;
if (!super::start(provider))
return false;
heathrow_sleepState = OSSymbol::withCString("heathrow_sleepState");
heathrow_powerMediaBay = OSSymbol::withCString("powerMediaBay");
heathrow_set_light = OSSymbol::withCString("heathrow_set_light");
heathrow_writeRegUInt8 = OSSymbol::withCString("heathrow_writeRegUInt8");
heathrow_safeWriteRegUInt8 = OSSymbol::withCString("heathrow_safeWriteRegUInt8");
heathrow_safeReadRegUInt8 = OSSymbol::withCString("heathrow_safeReadRegUInt8");
heathrow_safeWriteRegUInt32 = OSSymbol::withCString("heathrow_safeWriteRegUInt32");
heathrow_safeReadRegUInt32 = OSSymbol::withCString("heathrow_safeReadRegUInt32");
mediaIsOn = true;
mutex = IOSimpleLockAlloc();
if (IODTMatchNubWithKeys(provider, "heathrow"))
heathrowNum = kPrimaryHeathrow;
else if (IODTMatchNubWithKeys(provider, "gatwick"))
heathrowNum = kSecondaryHeathrow;
else return false;
if (heathrowNum == kPrimaryHeathrow) {
if (getPlatform()->getChipSetType() != kChipSetTypePowerExpress)
getPlatform()->setCPUInterruptProperties(provider);
}
heathrowBaseAddress = fMemory->getVirtualAddress();
publishBelow( provider );
ret = installInterrupts(provider);
registerService();
savedState.thisStateIsValid = false;
initForPM(provider);
return ret;
}
IOReturn Heathrow::callPlatformFunction(const OSSymbol *functionName,
bool waitForFunction,
void *param1, void *param2,
void *param3, void *param4)
{
if (functionName == heathrow_sleepState)
{
sleepState((bool)param1);
return kIOReturnSuccess;
}
if (functionName == heathrow_powerMediaBay) {
bool powerOn = (param1 != NULL);
powerMediaBay(powerOn, (UInt8)param2);
return kIOReturnSuccess;
}
if (functionName->isEqualTo("EnableSCC"))
{
EnableSCC((bool)param1);
return kIOReturnSuccess;
}
if (functionName->isEqualTo("PowerModem"))
{
PowerModem((bool)param1);
return kIOReturnSuccess;
}
if (functionName->isEqualTo("ModemResetLow"))
{
ModemResetLow();
return kIOReturnSuccess;
}
if (functionName->isEqualTo("ModemResetHigh"))
{
ModemResetHigh();
return kIOReturnSuccess;
}
if (functionName == heathrow_set_light)
{
setChassisLightFullpower((bool)param1);
return kIOReturnSuccess;
}
if (functionName == heathrow_writeRegUInt8)
{
writeRegUInt8(*(unsigned long *)param1, (UInt8)param2);
return kIOReturnSuccess;
}
if (functionName == heathrow_safeWriteRegUInt8)
{
safeWriteRegUInt8((unsigned long)param1, (UInt8)param2, (UInt8)param3);
return kIOReturnSuccess;
}
if (functionName == heathrow_safeReadRegUInt8)
{
UInt8 *returnval = (UInt8 *)param2;
*returnval = safeReadRegUInt8((unsigned long)param1);
return kIOReturnSuccess;
}
if (functionName == heathrow_safeWriteRegUInt32)
{
safeWriteRegUInt32((unsigned long)param1, (UInt32)param2, (UInt32)param3);
return kIOReturnSuccess;
}
if (functionName == heathrow_safeReadRegUInt32)
{
UInt32 *returnval = param2;
*returnval = safeReadRegUInt32((unsigned long)param1);
return kIOReturnSuccess;
}
return super::callPlatformFunction(functionName, waitForFunction, param1, param2, param3, param4);
}
void Heathrow::EnableSCC(bool state)
{
if (state)
{
*(UInt32*)(heathrowBaseAddress + 0x38) |= 0x00420000;
eieio();
*(UInt32*)(heathrowBaseAddress + 0x38) |= 0x00000002;
eieio();
IOSleep(15);
*(UInt32*)(heathrowBaseAddress + 0x38) &= ~0x00000002;
eieio();
}
else
{
}
return;
}
void Heathrow::PowerModem(bool state)
{
if (IODTMatchNubWithKeys(getPlatform()->getProvider(), "'PowerMac1,1'") ||
IODTMatchNubWithKeys(getPlatform()->getProvider(), "'PowerMac1,2'"))
return;
if (state)
{
*(UInt32*)(heathrowBaseAddress + 0x38) &= ~0x01000000;
eieio();
}
else
{
*(UInt32*)(heathrowBaseAddress + 0x38) |= 0x01000000;
eieio();
}
return;
}
void Heathrow::ModemResetLow()
{
*(UInt8*)(heathrowBaseAddress + 0x6D) &= ~0x01;
eieio();
}
void Heathrow::ModemResetHigh()
{
*(UInt8*)(heathrowBaseAddress + 0x6D) |= 0x01;
eieio();
}
UInt8 Heathrow::readRegUInt8(unsigned long offset)
{
return *(UInt8 *)(heathrowBaseAddress + offset);
}
void Heathrow::writeRegUInt8(unsigned long offset, UInt8 data)
{
*(UInt8 *)(heathrowBaseAddress + offset) = data;
eieio();
}
void Heathrow::safeWriteRegUInt8(unsigned long offset, UInt8 mask, UInt8 data)
{
IOInterruptState intState;
if ( mutex != NULL )
intState = IOSimpleLockLockDisableInterrupt(mutex);
UInt8 currentReg = readRegUInt8(offset);
currentReg = (currentReg & ~mask) | (data & mask);
writeRegUInt8(offset, currentReg);
if ( mutex != NULL )
IOSimpleLockUnlockEnableInterrupt(mutex, intState);
}
UInt8 Heathrow::safeReadRegUInt8(unsigned long offset)
{
IOInterruptState intState;
if ( mutex != NULL )
intState = IOSimpleLockLockDisableInterrupt(mutex);
UInt8 currentReg = readRegUInt8(offset);
if ( mutex != NULL )
IOSimpleLockUnlockEnableInterrupt(mutex, intState);
return (currentReg);
}
UInt32 Heathrow::readRegUInt32(unsigned long offset)
{
return lwbrx(heathrowBaseAddress + offset);
}
void Heathrow::writeRegUInt32(unsigned long offset, UInt32 data)
{
stwbrx(data, heathrowBaseAddress + offset);
eieio();
}
void Heathrow::safeWriteRegUInt32(unsigned long offset, UInt32 mask, UInt32 data)
{
IOInterruptState intState;
if ( mutex != NULL )
intState = IOSimpleLockLockDisableInterrupt(mutex);
UInt32 currentReg = readRegUInt32(offset);
currentReg = (currentReg & ~mask) | (data & mask);
writeRegUInt32(offset, currentReg);
if ( mutex != NULL )
IOSimpleLockUnlockEnableInterrupt(mutex, intState);
}
UInt32 Heathrow::safeReadRegUInt32(unsigned long offset)
{
IOInterruptState intState;
if ( mutex != NULL )
intState = IOSimpleLockLockDisableInterrupt(mutex);
UInt32 currentReg = readRegUInt32(offset);
if ( mutex != NULL )
IOSimpleLockUnlockEnableInterrupt(mutex, intState);
return (currentReg);
}
void Heathrow::initForPM (IOService *provider)
{
PMinit(); provider->joinPMtree(this);
#define number_of_power_states 2
static IOPMPowerState ourPowerStates[number_of_power_states] = {
{1,0,0,0,0,0,0,0,0,0,0,0},
{1,IOPMDeviceUsable,IOPMPowerOn,IOPMPowerOn,0,0,0,0,0,0,0,0}
};
if (pm_vars != NULL)
registerPowerDriver(this, ourPowerStates, number_of_power_states);
}
IOReturn Heathrow::setPowerState(unsigned long powerStateOrdinal, IOService* whatDevice)
{
if ( powerStateOrdinal == 0 ) {
if (heathrowNum == kSecondaryHeathrow) {
kprintf("Gatwick would be powered off here\n");
sleepState(true);
}
else if (heathrowNum == kPrimaryHeathrow) {
kprintf("Heathrow would be powered off here\n");
}
}
if ( powerStateOrdinal == 1 ) {
if (heathrowNum == kSecondaryHeathrow) {
kprintf("Gatwick would be powered on here\n");
sleepState(false);
}
else if (heathrowNum == kPrimaryHeathrow) {
kprintf("Heathrow would be powered on here\n");
}
}
return IOPMAckImplied;
}
bool Heathrow::installInterrupts(IOService *provider)
{
IORegistryEntry *regEntry;
OSSymbol *interruptControllerName;
IOInterruptAction handler;
AppleNMI *appleNMI;
long nmiSource;
OSData *nmiData;
IOReturn error;
if (getPlatform()->getChipSetType() == kChipSetTypePowerExpress) return true;
if( (regEntry = provider->childFromPath("interrupt-controller",
gIODTPlane))) {
interruptControllerName = (OSSymbol *)IODTInterruptControllerName(regEntry);
regEntry->release();
} else
interruptControllerName = getInterruptControllerName();
interruptController = new HeathrowInterruptController;
if (interruptController == NULL) return false;
error = interruptController->initInterruptController(provider, heathrowBaseAddress);
if (error != kIOReturnSuccess) return false;
interruptController->clearAllInterrupts();
handler = interruptController->getInterruptHandlerAddress();
provider->registerInterrupt(0, interruptController, handler, 0);
provider->enableInterrupt(0);
getPlatform()->registerInterruptController(interruptControllerName,
interruptController);
if (heathrowNum != kPrimaryHeathrow) return true;
nmiSource = 20;
nmiData = OSData::withBytes(&nmiSource, sizeof(long));
appleNMI = new AppleNMI;
if ((nmiData != 0) && (appleNMI != 0)) {
appleNMI->initNMI(interruptController, nmiData);
}
return true;
}
OSSymbol *Heathrow::getInterruptControllerName(void)
{
OSSymbol *interruptControllerName;
switch (heathrowNum) {
case kPrimaryHeathrow :
interruptControllerName = (OSSymbol *)gIODTDefaultInterruptController;
break;
case kSecondaryHeathrow :
interruptControllerName = (OSSymbol *)OSSymbol::withCStringNoCopy("SecondaryInterruptController");
break;
default:
interruptControllerName = (OSSymbol *)OSSymbol::withCStringNoCopy("UnknownInterruptController");
break;
}
return interruptControllerName;
}
void Heathrow::enableMBATA()
{
unsigned long heathrowIDs, heathrowFCR;
heathrowIDs = lwbrx(heathrowBaseAddress + 0x34);
if ((heathrowIDs & 0x0000FF00) == 0x00003000) {
heathrowFCR = lwbrx(heathrowBaseAddress + 0x38);
heathrowFCR |= 0x00800000;
stwbrx(heathrowFCR, heathrowBaseAddress + 0x38);
IODelay(100);
}
}
void Heathrow::powerMediaBay(bool powerOn, UInt8 deviceOn)
{
unsigned long heathrowIDs;
unsigned long powerDevice = deviceOn;
if (mediaIsOn == powerOn)
return;
powerDevice = powerDevice << 26;
powerDevice &= heathrowFCMediaBaybits;
heathrowIDs = lwbrx(heathrowBaseAddress + 0x34);
if ((heathrowIDs & 0x0000FF00) == 0x00003000) {
unsigned long *heathrowFCR = (unsigned long*)(heathrowBaseAddress + 0x38);
kprintf(" 1 Heathrow::powerMediaBay = 0x%08lx\n", *heathrowFCR);
*heathrowFCR &= ~(1<<heathrowFCMBReset);
eieio();
if (powerOn) {
*heathrowFCR &= ~(1<<heathrowFCMBPwr);
eieio();
IODelay(50000);
}
*heathrowFCR &= ~(heathrowFCMediaBaybits);
eieio();
*heathrowFCR |= powerDevice;
eieio();
if (!powerOn) {
*heathrowFCR |= 1<<heathrowFCMBPwr;
eieio();
}
else {
*heathrowFCR |= 1<<heathrowFCMBReset;
eieio();
enableMBATA();
}
IODelay(50000);
}
mediaIsOn = powerOn;
}
void Heathrow::processNub(IOService *nub)
{
int cnt, numSources;
OSArray *controllerNames, *controllerSources;
OSSymbol *interruptControllerName;
char *nubName;
nubName = (char *)nub->getName();
if (!strcmp(nubName, "media-bay")) {
enableMBATA();
}
if (heathrowNum == kPrimaryHeathrow) return;
interruptControllerName = getInterruptControllerName();
if (!strcmp(nubName, "media-bay")) {
controllerSources = OSDynamicCast(OSArray, getProperty("vectors-media-bay"));
} else if (!strcmp(nubName, "ch-a")) {
controllerSources = OSDynamicCast(OSArray, getProperty("vectors-escc-ch-a"));
} else if (!strcmp(nubName, "floppy")) {
controllerSources = OSDynamicCast(OSArray, getProperty("vectors-floppy"));
} else if (!strcmp(nubName, "ata4")) {
controllerSources = OSDynamicCast(OSArray, getProperty("vectors-ata4"));
} else return;
numSources = controllerSources->getCount();
controllerNames = OSArray::withCapacity(numSources);
for (cnt = 0; cnt < numSources; cnt++) {
controllerNames->setObject(interruptControllerName);
}
nub->setProperty(gIOInterruptControllersKey, controllerNames);
nub->setProperty(gIOInterruptSpecifiersKey, controllerSources);
}
void Heathrow::setChassisLightFullpower(bool fullpwr)
{
if (fullpwr)
{
*(UInt32*)(heathrowBaseAddress + kChassisLightColor) = 0x00000000;
eieio();
}
else
{
*(UInt32*)(heathrowBaseAddress + kChassisLightColor) = 0xffffffff;
eieio();
}
}
void Heathrow::sleepState(bool sleepMe)
{
if (sleepMe) {
saveInterruptState();
saveDMAState();
saveVIAState();
saveGPState();
savedState.thisStateIsValid = true;
}
else if (savedState.thisStateIsValid) {
restoreGPState();
restoreVIAState();
restoreDMAState();
restoreInterruptState();
savedState.thisStateIsValid = false;
enableMBATA();
}
}
void Heathrow::saveInterruptState()
{
savedState.interruptMask1 = *(UInt32*)(heathrowBaseAddress + kMask1Offset);
eieio();
savedState.interruptMask2 = *(UInt32*)(heathrowBaseAddress + kMask2Offset);
eieio();
}
void Heathrow::restoreInterruptState()
{
*(UInt32*)(heathrowBaseAddress + kClear1Offset) = 0xFFFFFFFF;
eieio();
*(UInt32*)(heathrowBaseAddress + kClear2Offset) = 0xFFFFFFFF;
eieio();
*(UInt32*)(heathrowBaseAddress + kMask1Offset) = savedState.interruptMask1;
eieio();
*(UInt32*)(heathrowBaseAddress + kMask2Offset) = savedState.interruptMask2;
eieio();
*(UInt32*)(heathrowBaseAddress + kClear1Offset) = 0xFFFFFFFF;
eieio();
*(UInt32*)(heathrowBaseAddress + kClear2Offset) = 0xFFFFFFFF;
eieio();
}
void Heathrow::saveGPState()
{
savedState.featureControlReg = *(UInt32*)(heathrowBaseAddress + 0x00000038);
savedState.auxControlReg = *(UInt32*)(heathrowBaseAddress + 0x0000003C);
}
void Heathrow::restoreGPState()
{
*(UInt32*)(heathrowBaseAddress + 0x00000038) = savedState.featureControlReg;
eieio();
IODelay(1000);
*(UInt32*)(heathrowBaseAddress + 0x0000003C) = savedState.auxControlReg;
eieio();
IODelay(1000);
}
void Heathrow::saveDMAState()
{
int i;
UInt32 channelOffset;
for (i = 0, channelOffset = 0; i < 12; i++, channelOffset += 0x0100)
{
volatile DBDMAChannelRegisters* currentChannel;
currentChannel = (volatile DBDMAChannelRegisters *) (heathrowBaseAddress + 0x8000 + channelOffset);
savedState.savedDBDMAState[i].commandPtrLo = IOGetDBDMACommandPtr(currentChannel);
savedState.savedDBDMAState[i].interruptSelect = IOGetDBDMAInterruptSelect(currentChannel);
savedState.savedDBDMAState[i].branchSelect = IOGetDBDMABranchSelect(currentChannel);
savedState.savedDBDMAState[i].waitSelect = IOGetDBDMAWaitSelect(currentChannel);
}
}
void Heathrow::restoreDMAState()
{
int i;
UInt32 channelOffset;
for (i = 0, channelOffset = 0; i < 12; i++, channelOffset += 0x0100)
{
volatile DBDMAChannelRegisters* currentChannel;
currentChannel = (volatile DBDMAChannelRegisters *) (heathrowBaseAddress + 0x8000 + channelOffset);
IODBDMAReset((IODBDMAChannelRegisters*)currentChannel);
IOSetDBDMACommandPtr(currentChannel, savedState.savedDBDMAState[i].commandPtrLo);
IOSetDBDMAInterruptSelect(currentChannel, savedState.savedDBDMAState[i].interruptSelect);
IOSetDBDMABranchSelect(currentChannel, savedState.savedDBDMAState[i].branchSelect);
IOSetDBDMAWaitSelect(currentChannel, savedState.savedDBDMAState[i].waitSelect);
}
}
void Heathrow::saveVIAState(void)
{
UInt8* viaBase = (UInt8*)heathrowBaseAddress + 0x16000;
UInt8* savedViaState = savedState.savedVIAState;
savedViaState[0] = *(UInt8*)(viaBase + vBufA);
savedViaState[1] = *(UInt8*)(viaBase + vDIRA);
savedViaState[2] = *(UInt8*)(viaBase + vBufB);
savedViaState[3] = *(UInt8*)(viaBase + vDIRB);
savedViaState[4] = *(UInt8*)(viaBase + vPCR);
savedViaState[5] = *(UInt8*)(viaBase + vACR);
savedViaState[6] = *(UInt8*)(viaBase + vIER);
savedViaState[7] = *(UInt8*)(viaBase + vT1C);
savedViaState[8] = *(UInt8*)(viaBase + vT1CH);
}
void Heathrow::restoreVIAState(void)
{
UInt8* viaBase = (UInt8*)heathrowBaseAddress + 0x16000;
UInt8* savedViaState = savedState.savedVIAState;
*(UInt8*)(viaBase + vBufA) = savedViaState[0];
eieio();
*(UInt8*)(viaBase + vDIRA) = savedViaState[1];
eieio();
*(UInt8*)(viaBase + vBufB) = savedViaState[2];
eieio();
*(UInt8*)(viaBase + vDIRB) = savedViaState[3];
eieio();
*(UInt8*)(viaBase + vPCR) = savedViaState[4];
eieio();
*(UInt8*)(viaBase + vACR) = savedViaState[5];
eieio();
*(UInt8*)(viaBase + vIER) = savedViaState[6];
eieio();
*(UInt8*)(viaBase + vT1C) = savedViaState[7];
eieio();
*(UInt8*)(viaBase + vT1CH) = savedViaState[8];
eieio();
}
#undef super
#define super IOInterruptController
OSDefineMetaClassAndStructors(HeathrowInterruptController, IOInterruptController);
IOReturn HeathrowInterruptController::initInterruptController(IOService *provider, IOLogicalAddress iBase)
{
int cnt;
interruptControllerBase = iBase;
parentNub = provider;
taskLock = IOLockAlloc();
if (taskLock == 0) return kIOReturnNoResources;
vectors = (IOInterruptVector *)IOMalloc(kNumVectors * sizeof(IOInterruptVector));
if (vectors == NULL) {
IOLockFree(taskLock);
return kIOReturnNoMemory;
}
bzero(vectors, kNumVectors * sizeof(IOInterruptVector));
for (cnt = 0; cnt < kNumVectors; cnt++) {
vectors[cnt].interruptLock = IOLockAlloc();
if (vectors[cnt].interruptLock == NULL) {
IOLockFree(taskLock);
for (cnt = 0; cnt < kNumVectors; cnt++) {
if (vectors[cnt].interruptLock != NULL)
IOLockFree(vectors[cnt].interruptLock);
}
return kIOReturnNoResources;
}
}
events1Reg = (unsigned long)(interruptControllerBase + kEvents1Offset);
events2Reg = (unsigned long)(interruptControllerBase + kEvents2Offset);
mask1Reg = (unsigned long)(interruptControllerBase + kMask1Offset);
mask2Reg = (unsigned long)(interruptControllerBase + kMask2Offset);
clear1Reg = (unsigned long)(interruptControllerBase + kClear1Offset);
clear2Reg = (unsigned long)(interruptControllerBase + kClear2Offset);
levels1Reg = (unsigned long)(interruptControllerBase + kLevels1Offset);
levels2Reg = (unsigned long)(interruptControllerBase + kLevels2Offset);
return kIOReturnSuccess;
}
void HeathrowInterruptController::clearAllInterrupts(void)
{
stwbrx(0x00000000, mask1Reg);
stwbrx(0x00000000, mask2Reg);
eieio();
stwbrx(0xFFFFFFFF, clear1Reg);
stwbrx(0xFFFFFFFF, clear2Reg);
eieio();
stwbrx(0x00000000, mask1Reg);
stwbrx(0x00000000, mask2Reg);
eieio();
}
IOInterruptAction HeathrowInterruptController::getInterruptHandlerAddress(void)
{
return (IOInterruptAction)&HeathrowInterruptController::handleInterrupt;
}
IOReturn HeathrowInterruptController::handleInterrupt(void * ,
IOService * ,
int )
{
int done;
long events, vectorNumber;
IOInterruptVector *vector;
unsigned long maskTmp;
do {
done = 1;
maskTmp = lwbrx(mask1Reg);
events = lwbrx(events1Reg) & ~kTypeLevelMask;
events |= lwbrx(levels1Reg) & maskTmp & kTypeLevelMask;
events |= pendingEvents1 & maskTmp;
pendingEvents1 = 0;
eieio();
stwbrx(kTypeLevelMask | events, clear1Reg);
eieio();
if (events) done = 0;
while (events) {
vectorNumber = 31 - cntlzw(events);
events ^= (1 << vectorNumber);
vector = &vectors[vectorNumber];
vector->interruptActive = 1;
sync();
isync();
if (!vector->interruptDisabledSoft) {
isync();
if (vector->interruptRegistered) {
vector->handler(vector->target, vector->refCon,
vector->nub, vector->source);
}
} else {
vector->interruptDisabledHard = 1;
disableVectorHard(vectorNumber, vector);
}
vector->interruptActive = 0;
}
maskTmp = lwbrx(mask2Reg);
events = lwbrx(events2Reg);
events |= pendingEvents1 & maskTmp;
pendingEvents2 = 0;
eieio();
if (events) {
done = 0;
stwbrx(events, clear2Reg);
eieio();
}
while (events) {
vectorNumber = 31 - cntlzw(events);
events ^= (1 << vectorNumber);
vector = &vectors[vectorNumber + kVectorsPerReg];
vector->interruptActive = 1;
sync();
isync();
if (!vector->interruptDisabledSoft) {
isync();
if (vector->interruptRegistered) {
vector->handler(vector->target, vector->refCon,
vector->nub, vector->source);
}
} else {
vector->interruptDisabledHard = 1;
disableVectorHard(vectorNumber + kVectorsPerReg, vector);
}
vector->interruptActive = 0;
}
} while (!done);
return kIOReturnSuccess;
}
bool HeathrowInterruptController::vectorCanBeShared(long , IOInterruptVector *)
{
return true;
}
int HeathrowInterruptController::getVectorType(long vectorNumber, IOInterruptVector *)
{
int interruptType;
if (kTypeLevelMask & (1 << vectorNumber)) {
interruptType = kIOInterruptTypeLevel;
} else {
interruptType = kIOInterruptTypeEdge;
}
return interruptType;
}
void HeathrowInterruptController::disableVectorHard(long vectorNumber, IOInterruptVector *)
{
unsigned long maskTmp;
boolean_t interruptState = ml_set_interrupts_enabled(FALSE);
if (vectorNumber < kVectorsPerReg) {
maskTmp = lwbrx(mask1Reg);
maskTmp &= ~(1 << vectorNumber);
stwbrx(maskTmp, mask1Reg);
eieio();
} else {
vectorNumber -= kVectorsPerReg;
maskTmp = lwbrx(mask2Reg);
maskTmp &= ~(1 << vectorNumber);
stwbrx(maskTmp, mask2Reg);
eieio();
}
ml_set_interrupts_enabled(interruptState);
}
void HeathrowInterruptController::enableVector(long vectorNumber,
IOInterruptVector *vector)
{
unsigned long maskTmp;
boolean_t interruptState;
if (vectorNumber < kVectorsPerReg) {
interruptState = ml_set_interrupts_enabled(FALSE);
maskTmp = lwbrx(mask1Reg);
maskTmp |= (1 << vectorNumber);
stwbrx(maskTmp, mask1Reg);
eieio();
ml_set_interrupts_enabled(interruptState);
if ((lwbrx(levels1Reg) & (1 << vectorNumber)) && (vector != NULL)) {
causeVector(vectorNumber, vector);
}
} else {
vectorNumber -= kVectorsPerReg;
interruptState = ml_set_interrupts_enabled(FALSE);
maskTmp = lwbrx(mask2Reg);
maskTmp |= (1 << vectorNumber);
stwbrx(maskTmp, mask2Reg);
eieio();
ml_set_interrupts_enabled(interruptState);
if ((lwbrx(levels1Reg) & (1 << vectorNumber)) && (vector != NULL)) {
causeVector(vectorNumber + kVectorsPerReg, vector);
}
}
}
void HeathrowInterruptController::causeVector(long vectorNumber,
IOInterruptVector *)
{
boolean_t interruptState = ml_set_interrupts_enabled(FALSE);
if (vectorNumber < kVectorsPerReg) {
pendingEvents1 |= 1 << vectorNumber;
} else {
vectorNumber -= kVectorsPerReg;
pendingEvents2 |= 1 << vectorNumber;
}
ml_set_interrupts_enabled(interruptState);
parentNub->causeInterrupt(0);
}