/* * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. * * DRI: Josh de Cesare * */ #include #include #include #include #include #include #include #include "Heathrow.h" #include /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #define super AppleMacIO OSDefineMetaClassAndStructors(Heathrow, AppleMacIO); bool Heathrow::start(IOService *provider) { bool ret; // Call MacIO's start. if (!super::start(provider)) return false; // callPlatformFunction symbols heathrow_sleepState = OSSymbol::withCString("heathrow_sleepState"); heathrow_powerMediaBay = OSSymbol::withCString("powerMediaBay"); heathrow_set_light = OSSymbol::withCString("heathrow_set_light"); // just initializes this: mediaIsOn = true; // Figure out which heathrow this is. if (IODTMatchNubWithKeys(provider, "heathrow")) heathrowNum = kPrimaryHeathrow; else if (IODTMatchNubWithKeys(provider, "gatwick")) heathrowNum = kSecondaryHeathrow; else return false; // This should not happen. if (heathrowNum == kPrimaryHeathrow) { if (getPlatform()->getChipSetType() != kChipSetTypePowerExpress) getPlatform()->setCPUInterruptProperties(provider); } // get the base address of the this heathrow. heathrowBaseAddress = fMemory->getVirtualAddress(); // Make nubs for the children. publishBelow( provider ); ret = installInterrupts(provider); // register iteself so we can find it: registerService(); // mark the current state as invalid: savedState.thisStateIsValid = false; // attach to the power managment tree: initForPM(provider); //kprintf("Heathrow::start(%s) %d\n", provider->getName(), ret); 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 == heathrow_set_light) { setChassisLightFullpower((bool)param1); return kIOReturnSuccess; } return super::callPlatformFunction(functionName, waitForFunction, param1, param2, param3, param4); } void Heathrow::EnableSCC(bool state) { if (state) { // Enables the SCC cell: *(UInt32*)(heathrowBaseAddress + 0x38) |= 0x00420000; eieio(); // Resets the SCC: *(UInt32*)(heathrowBaseAddress + 0x38) |= 0x00000002; eieio(); IOSleep(15); *(UInt32*)(heathrowBaseAddress + 0x38) &= ~0x00000002; eieio(); } else { // disable } return; } void Heathrow::PowerModem(bool state) { // On PowerMac 1,2 () the modem is always on and this bit // disables the nvram. So on Yikes we exit without doing // anything. Also setting this bit has as bas nvram side // effects. 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; } // -------------------------------------------------------------------------- // Method: initForPM // // Purpose: // initialize the driver for power managment and register ourselves with // superclass policy-maker void Heathrow::initForPM (IOService *provider) { PMinit(); // initialize superclass variables provider->joinPMtree(this); // attach into the power management hierarchy // KeyLargo has only 2 power states:: // 0 OFF // 1 all ON // Pwer state fields: // unsigned long version; // version number of this struct // IOPMPowerFlags capabilityFlags; // bits that describe (to interested drivers) the capability of the device in this state // IOPMPowerFlags outputPowerCharacter; // description (to power domain children) of the power provided in this state // IOPMPowerFlags inputPowerRequirement; // description (to power domain parent) of input power required in this state // unsigned long staticPower; // average consumption in milliwatts // unsigned long unbudgetedPower; // additional consumption from separate power supply (mw) // unsigned long powerToAttain; // additional power to attain this state from next lower state (in mw) // unsigned long timeToAttain; // time required to enter this state from next lower state (in microseconds) // unsigned long settleUpTime; // settle time required after entering this state from next lower state (microseconds) // unsigned long timeToLower; // time required to enter next lower state from this one (in microseconds) // unsigned long settleDownTime; // settle time required after entering next lower state from this state (microseconds) // unsigned long powerDomainBudget; // power in mw a domain in this state can deliver to its children // NOTE: all these values are made up since now I do not have areal clue of what to put. #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} }; // register ourselves with ourself as policy-maker if (pm_vars != NULL) registerPowerDriver(this, ourPowerStates, number_of_power_states); } // Method: setPowerState // // VERY IMPORTANT NOTE: // sleepState(bool) can be called from here or directly. This is NOT an oversight. // What I am trying to resolve here is a problem with those powerbooks that have // 2 Heathrow chips. In these machines the main Heathrow should be powered on // in the CPU driver, and the second here. Since the HeathrowState holds a bit // to remeber if the state is valid, and such a bit is cleared once the state is // restored I am sure that I am not going to overwrite a valid state with an (older) // invalid one. 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"); /* None the CPU driver handles this */ } } 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"); /* None the CPU driver handles this */ } } return IOPMAckImplied; } bool Heathrow::installInterrupts(IOService *provider) { IORegistryEntry *regEntry; OSSymbol *interruptControllerName; IOInterruptAction handler; AppleNMI *appleNMI; long nmiSource; OSData *nmiData; IOReturn error; // Everything below here is for interrupts, return true if // interrupts are not needed. if (getPlatform()->getChipSetType() == kChipSetTypePowerExpress) return true; // get the name of the interrupt controller if( (regEntry = provider->childFromPath("interrupt-controller", gIODTPlane))) { interruptControllerName = (OSSymbol *)IODTInterruptControllerName(regEntry); regEntry->release(); } else interruptControllerName = getInterruptControllerName(); // Allocate the interruptController instance. interruptController = new HeathrowInterruptController; if (interruptController == NULL) return false; // call the interruptController's init method. error = interruptController->initInterruptController(provider, heathrowBaseAddress); if (error != kIOReturnSuccess) return false; // and clears the interrupt state: interruptController->clearAllInterrupts(); handler = interruptController->getInterruptHandlerAddress(); provider->registerInterrupt(0, interruptController, handler, 0); provider->enableInterrupt(0); // Register the interrupt controller so clients can find it. getPlatform()->registerInterruptController(interruptControllerName, interruptController); if (heathrowNum != kPrimaryHeathrow) return true; // Create the NMI Driver. 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; //kprintf("Heathrow::powerMediaBay(%s) 0x%02x\n", (powerOn ? "TRUE" : "FALSE"), powerDevice); ///kprintf(" 0 Heathrow::powerMediaBay = 0x%08lx\n", lwbrx(heathrowBaseAddress + 0x38)); if (mediaIsOn == powerOn) return; // Align the bits of the power device: 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); // make sure media bay is in reset (MB reset bit is low) *heathrowFCR &= ~(1<getName(); if (!strcmp(nubName, "media-bay")) { enableMBATA(); } // change the interrupt controller name for this nub // if it is on the secondary heathrow. 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); } // Set the color of the front panel light on desktop Gossamers. void Heathrow::setChassisLightFullpower(bool fullpwr) { if (fullpwr) { *(UInt32*)(heathrowBaseAddress + kChassisLightColor) = 0x00000000; eieio(); } else { *(UInt32*)(heathrowBaseAddress + kChassisLightColor) = 0xffffffff; eieio(); } } // If sleepMe is true places heatrow to sleep, // Otherwise wakes it up. void Heathrow::sleepState(bool sleepMe) { if (sleepMe) { // Saves the state and creates the conditions for sleep: // Disables and saves all the interrupts: //kprintf("Heathrow::sleepState saveInterruptState\n"); saveInterruptState(); // Saves all the DMA registers: //kprintf("Heathrow::sleepState saveDMAState\n"); saveDMAState(); // Saves the VIA registers: //kprintf("Heathrow::sleepState saveVIAState\n"); saveVIAState(); // Saves the GP registers: //kprintf("Heathrow::sleepState saveGPState\n"); saveGPState(); // Defines the state as valid: savedState.thisStateIsValid = true; } else if (savedState.thisStateIsValid) { // Restores the GP registers: //kprintf("Heathrow::sleepState restoreGPState\n"); restoreGPState(); // Wakes up and restores the state: //kprintf("Heathrow::sleepState restoreVIAState\n"); restoreVIAState(); // Restores the DMA registers: //kprintf("Heathrow::sleepState restoreDMAState\n"); restoreDMAState(); // Restores and enables the interrupts: //kprintf("Heathrow::sleepState restoreInterruptState\n"); restoreInterruptState(); // This state is no more valid: savedState.thisStateIsValid = false; // Turn on the media bay if necessary. enableMBATA(); } } void Heathrow::saveInterruptState() { // Save the interrupt state savedState.interruptMask1 = *(UInt32*)(heathrowBaseAddress + kMask1Offset); eieio(); savedState.interruptMask2 = *(UInt32*)(heathrowBaseAddress + kMask2Offset); eieio(); } void Heathrow::restoreInterruptState() { // Clears all the possible pending interrupts *(UInt32*)(heathrowBaseAddress + kClear1Offset) = 0xFFFFFFFF; eieio(); *(UInt32*)(heathrowBaseAddress + kClear2Offset) = 0xFFFFFFFF; eieio(); // Restores the interrupts *(UInt32*)(heathrowBaseAddress + kMask1Offset) = savedState.interruptMask1; eieio(); *(UInt32*)(heathrowBaseAddress + kMask2Offset) = savedState.interruptMask2; eieio(); // Clears all the possible pending interrupts (again) *(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; // Save VIA state. These registers don't seem to get restored to any known state. 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; // Restore VIA state. These registers don't seem to get restored to any known state. *(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; // Allocate the task lock. taskLock = IOLockAlloc(); if (taskLock == 0) return kIOReturnNoResources; // Allocate the memory for the vectors vectors = (IOInterruptVector *)IOMalloc(kNumVectors * sizeof(IOInterruptVector)); if (vectors == NULL) { IOLockFree(taskLock); return kIOReturnNoMemory; } bzero(vectors, kNumVectors * sizeof(IOInterruptVector)); // Allocate locks for the 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; } } // Setup the registers accessors 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) { // Initialize the registers. // Disable all interrupts. stwbrx(0x00000000, mask1Reg); stwbrx(0x00000000, mask2Reg); eieio(); // Clear all pending interrupts. stwbrx(0xFFFFFFFF, clear1Reg); stwbrx(0xFFFFFFFF, clear2Reg); eieio(); // Disable all interrupts. (again?) stwbrx(0x00000000, mask1Reg); stwbrx(0x00000000, mask2Reg); eieio(); } IOInterruptAction HeathrowInterruptController::getInterruptHandlerAddress(void) { return (IOInterruptAction)&HeathrowInterruptController::handleInterrupt; } IOReturn HeathrowInterruptController::handleInterrupt(void * /*refCon*/, IOService * /*nub*/, int /*source*/) { int done; long events, vectorNumber; IOInterruptVector *vector; unsigned long maskTmp; do { done = 1; // Do all the sources for events1, plus any pending interrupts. // Also add in the "level" sensitive sources maskTmp = lwbrx(mask1Reg); events = lwbrx(events1Reg) & ~kTypeLevelMask; events |= lwbrx(levels1Reg) & maskTmp & kTypeLevelMask; events |= pendingEvents1 & maskTmp; pendingEvents1 = 0; eieio(); // Since we have to clear the level'd one clear the current edge's too. 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(); // Call the handler if it exists. if (vector->interruptRegistered) { vector->handler(vector->target, vector->refCon, vector->nub, vector->source); } } else { // Hard disable the source. vector->interruptDisabledHard = 1; disableVectorHard(vectorNumber, vector); } vector->interruptActive = 0; } // Do all the sources for events2, plus any pending interrupts. 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(); // Call the handler if it exists. if (vector->interruptRegistered) { vector->handler(vector->target, vector->refCon, vector->nub, vector->source); } } else { // Hard disable the source. vector->interruptDisabledHard = 1; disableVectorHard(vectorNumber + kVectorsPerReg, vector); } vector->interruptActive = 0; } } while (!done); return kIOReturnSuccess; } bool HeathrowInterruptController::vectorCanBeShared(long /*vectorNumber*/, IOInterruptVector */*vector*/) { return true; } int HeathrowInterruptController::getVectorType(long vectorNumber, IOInterruptVector */*vector*/) { int interruptType; if (kTypeLevelMask & (1 << vectorNumber)) { interruptType = kIOInterruptTypeLevel; } else { interruptType = kIOInterruptTypeEdge; } return interruptType; } void HeathrowInterruptController::disableVectorHard(long vectorNumber, IOInterruptVector */*vector*/) { unsigned long maskTmp; // Turn the source off at hardware. 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(); } } void HeathrowInterruptController::enableVector(long vectorNumber, IOInterruptVector *vector) { unsigned long maskTmp; if (vectorNumber < kVectorsPerReg) { maskTmp = lwbrx(mask1Reg); maskTmp |= (1 << vectorNumber); stwbrx(maskTmp, mask1Reg); eieio(); if ((lwbrx(levels1Reg) & (1 << vectorNumber)) && (vector != NULL)) { // lost the interrupt causeVector(vectorNumber, vector); } } else { vectorNumber -= kVectorsPerReg; maskTmp = lwbrx(mask2Reg); maskTmp |= (1 << vectorNumber); stwbrx(maskTmp, mask2Reg); eieio(); if ((lwbrx(levels1Reg) & (1 << vectorNumber)) && (vector != NULL)) { // lost the interrupt causeVector(vectorNumber + kVectorsPerReg, vector); } } } void HeathrowInterruptController::causeVector(long vectorNumber, IOInterruptVector */*vector*/) { if (vectorNumber < kVectorsPerReg) { pendingEvents1 |= 1 << vectorNumber; } else { vectorNumber -= kVectorsPerReg; pendingEvents2 |= 1 << vectorNumber; } parentNub->causeInterrupt(0); }