X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/89b3af67bb32e691275bf6fa803d1834b2284115..c7d2c2c6ee645e10cbccdd01c6191873ec77239d:/iokit/Kernel/IOInterruptController.cpp?ds=sidebyside diff --git a/iokit/Kernel/IOInterruptController.cpp b/iokit/Kernel/IOInterruptController.cpp index f65dbe3b6..95287f584 100644 --- a/iokit/Kernel/IOInterruptController.cpp +++ b/iokit/Kernel/IOInterruptController.cpp @@ -1,5 +1,6 @@ /* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2007-2012 Apple Inc. All rights reserved. + * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -25,17 +26,6 @@ * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * DRI: Josh de Cesare - * - */ - - -#if __ppc__ -#include -#endif #include #include @@ -43,6 +33,8 @@ #include #include #include +#include +#include /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -66,33 +58,44 @@ IOReturn IOInterruptController::registerInterrupt(IOService *nub, int source, void *refCon) { IOInterruptSource *interruptSources; - long vectorNumber; + IOInterruptVectorNumber vectorNumber; IOInterruptVector *vector; - long wasDisabledSoft; + int wasDisabledSoft; IOReturn error; OSData *vectorData; - IOService *originalNub; - int originalSource; IOOptionBits options; bool canBeShared, shouldBeShared, wasAlreadyRegisterd; - + + IOService *originalNub = NULL; // Protected by wasAlreadyRegisterd + int originalSource = 0; // Protected by wasAlreadyRegisterd + + interruptSources = nub->_interruptSources; vectorData = interruptSources[source].vectorData; - vectorNumber = *(long *)vectorData->getBytesNoCopy(); + vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy(); vector = &vectors[vectorNumber]; // Get the lock for this vector. - IOTakeLock(vector->interruptLock); + IOLockLock(vector->interruptLock); // Check if the interrupt source can/should be shared. canBeShared = vectorCanBeShared(vectorNumber, vector); IODTGetInterruptOptions(nub, source, &options); +#if defined(__i386__) || defined(__x86_64__) + int interruptType; + if (OSDynamicCast(IOPlatformDevice, getProvider()) && + (getInterruptType(nub, source, &interruptType) == kIOReturnSuccess) && + (kIOInterruptTypeLevel & interruptType)) + { + options |= kIODTInterruptShared; + } +#endif shouldBeShared = canBeShared && (options & kIODTInterruptShared); wasAlreadyRegisterd = vector->interruptRegistered; // If the vector is registered and can not be shared return error. if (wasAlreadyRegisterd && !canBeShared) { - IOUnlock(vector->interruptLock); + IOLockUnlock(vector->interruptLock); return kIOReturnNoResources; } @@ -105,7 +108,7 @@ IOReturn IOInterruptController::registerInterrupt(IOService *nub, int source, // Make the IOShareInterruptController instance vector->sharedController = new IOSharedInterruptController; if (vector->sharedController == 0) { - IOUnlock(vector->interruptLock); + IOLockUnlock(vector->interruptLock); return kIOReturnNoMemory; } @@ -129,7 +132,7 @@ IOReturn IOInterruptController::registerInterrupt(IOService *nub, int source, if (wasAlreadyRegisterd) enableInterrupt(originalNub, originalSource); vector->sharedController->release(); vector->sharedController = 0; - IOUnlock(vector->interruptLock); + IOLockUnlock(vector->interruptLock); return error; } @@ -157,7 +160,7 @@ IOReturn IOInterruptController::registerInterrupt(IOService *nub, int source, vector->sharedController->release(); vector->sharedController = 0; - IOUnlock(vector->interruptLock); + IOLockUnlock(vector->interruptLock); return error; } } @@ -183,12 +186,13 @@ IOReturn IOInterruptController::registerInterrupt(IOService *nub, int source, vector->interruptRegistered = 1; // Enable the original consumer's interrupt if needed. + // originalNub is protected by wasAlreadyRegisterd here (see line 184). if (!wasDisabledSoft) originalNub->enableInterrupt(originalSource); } error = vector->sharedController->registerInterrupt(nub, source, target, handler, refCon); - IOUnlock(vector->interruptLock); + IOLockUnlock(vector->interruptLock); return error; } @@ -207,28 +211,28 @@ IOReturn IOInterruptController::registerInterrupt(IOService *nub, int source, vector->interruptDisabledSoft = 1; vector->interruptRegistered = 1; - IOUnlock(vector->interruptLock); + IOLockUnlock(vector->interruptLock); return kIOReturnSuccess; } IOReturn IOInterruptController::unregisterInterrupt(IOService *nub, int source) { IOInterruptSource *interruptSources; - long vectorNumber; + IOInterruptVectorNumber vectorNumber; IOInterruptVector *vector; OSData *vectorData; interruptSources = nub->_interruptSources; vectorData = interruptSources[source].vectorData; - vectorNumber = *(long *)vectorData->getBytesNoCopy(); + vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy(); vector = &vectors[vectorNumber]; // Get the lock for this vector. - IOTakeLock(vector->interruptLock); + IOLockLock(vector->interruptLock); // Return success if it is not already registered if (!vector->interruptRegistered) { - IOUnlock(vector->interruptLock); + IOLockUnlock(vector->interruptLock); return kIOReturnSuccess; } @@ -249,7 +253,7 @@ IOReturn IOInterruptController::unregisterInterrupt(IOService *nub, int source) vector->target = 0; vector->refCon = 0; - IOUnlock(vector->interruptLock); + IOLockUnlock(vector->interruptLock); return kIOReturnSuccess; } @@ -257,7 +261,7 @@ IOReturn IOInterruptController::getInterruptType(IOService *nub, int source, int *interruptType) { IOInterruptSource *interruptSources; - long vectorNumber; + IOInterruptVectorNumber vectorNumber; IOInterruptVector *vector; OSData *vectorData; @@ -265,7 +269,7 @@ IOReturn IOInterruptController::getInterruptType(IOService *nub, int source, interruptSources = nub->_interruptSources; vectorData = interruptSources[source].vectorData; - vectorNumber = *(long *)vectorData->getBytesNoCopy(); + vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy(); vector = &vectors[vectorNumber]; *interruptType = getVectorType(vectorNumber, vector); @@ -276,27 +280,24 @@ IOReturn IOInterruptController::getInterruptType(IOService *nub, int source, IOReturn IOInterruptController::enableInterrupt(IOService *nub, int source) { IOInterruptSource *interruptSources; - long vectorNumber; + IOInterruptVectorNumber vectorNumber; IOInterruptVector *vector; OSData *vectorData; interruptSources = nub->_interruptSources; vectorData = interruptSources[source].vectorData; - vectorNumber = *(long *)vectorData->getBytesNoCopy(); + vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy(); vector = &vectors[vectorNumber]; if (vector->interruptDisabledSoft) { vector->interruptDisabledSoft = 0; -#if __ppc__ - sync(); - isync(); +#if !defined(__i386__) && !defined(__x86_64__) + OSMemoryBarrier(); #endif - + if (!getPlatform()->atInterruptLevel()) { - while (vector->interruptActive); -#if __ppc__ - isync(); -#endif + while (vector->interruptActive) + {} } if (vector->interruptDisabledHard) { vector->interruptDisabledHard = 0; @@ -311,26 +312,23 @@ IOReturn IOInterruptController::enableInterrupt(IOService *nub, int source) IOReturn IOInterruptController::disableInterrupt(IOService *nub, int source) { IOInterruptSource *interruptSources; - long vectorNumber; + IOInterruptVectorNumber vectorNumber; IOInterruptVector *vector; OSData *vectorData; interruptSources = nub->_interruptSources; vectorData = interruptSources[source].vectorData; - vectorNumber = *(long *)vectorData->getBytesNoCopy(); + vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy(); vector = &vectors[vectorNumber]; vector->interruptDisabledSoft = 1; -#if __ppc__ - sync(); - isync(); +#if !defined(__i386__) && !defined(__x86_64__) + OSMemoryBarrier(); #endif if (!getPlatform()->atInterruptLevel()) { - while (vector->interruptActive); -#if __ppc__ - isync(); -#endif + while (vector->interruptActive) + {} } return kIOReturnSuccess; @@ -339,13 +337,13 @@ IOReturn IOInterruptController::disableInterrupt(IOService *nub, int source) IOReturn IOInterruptController::causeInterrupt(IOService *nub, int source) { IOInterruptSource *interruptSources; - long vectorNumber; + IOInterruptVectorNumber vectorNumber; IOInterruptVector *vector; OSData *vectorData; interruptSources = nub->_interruptSources; vectorData = interruptSources[source].vectorData; - vectorNumber = *(long *)vectorData->getBytesNoCopy(); + vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy(); vector = &vectors[vectorNumber]; causeVector(vectorNumber, vector); @@ -367,34 +365,34 @@ IOReturn IOInterruptController::handleInterrupt(void *refCon, IOService *nub, // Methods to be overridden for simplifed interrupt controller subclasses. -bool IOInterruptController::vectorCanBeShared(long /*vectorNumber*/, +bool IOInterruptController::vectorCanBeShared(IOInterruptVectorNumber /*vectorNumber*/, IOInterruptVector */*vector*/) { return false; } -void IOInterruptController::initVector(long /*vectorNumber*/, +void IOInterruptController::initVector(IOInterruptVectorNumber /*vectorNumber*/, IOInterruptVector */*vector*/) { } -int IOInterruptController::getVectorType(long /*vectorNumber*/, +int IOInterruptController::getVectorType(IOInterruptVectorNumber /*vectorNumber*/, IOInterruptVector */*vector*/) { return kIOInterruptTypeEdge; } -void IOInterruptController::disableVectorHard(long /*vectorNumber*/, +void IOInterruptController::disableVectorHard(IOInterruptVectorNumber /*vectorNumber*/, IOInterruptVector */*vector*/) { } -void IOInterruptController::enableVector(long /*vectorNumber*/, +void IOInterruptController::enableVector(IOInterruptVectorNumber /*vectorNumber*/, IOInterruptVector */*vector*/) { } -void IOInterruptController::causeVector(long /*vectorNumber*/, +void IOInterruptController::causeVector(IOInterruptVectorNumber /*vectorNumber*/, IOInterruptVector */*vector*/) { } @@ -420,6 +418,8 @@ IOReturn IOSharedInterruptController::initInterruptController(IOInterruptControl { int cnt, interruptType; IOReturn error; + + reserved = NULL; if (!super::init()) return kIOReturnNoResources; @@ -485,7 +485,7 @@ IOReturn IOSharedInterruptController::registerInterrupt(IOService *nub, void *refCon) { IOInterruptSource *interruptSources; - long vectorNumber; + IOInterruptVectorNumber vectorNumber; IOInterruptVector *vector = 0; OSData *vectorData; IOInterruptState interruptState; @@ -499,13 +499,13 @@ IOReturn IOSharedInterruptController::registerInterrupt(IOService *nub, vector = &vectors[vectorNumber]; // Get the lock for this vector. - IOTakeLock(vector->interruptLock); + IOLockLock(vector->interruptLock); // Is it unregistered? if (!vector->interruptRegistered) break; // Move along to the next one. - IOUnlock(vector->interruptLock); + IOLockUnlock(vector->interruptLock); } if (vectorNumber != kIOSharedInterruptControllerDefaultVectors) break; @@ -542,59 +542,58 @@ IOReturn IOSharedInterruptController::registerInterrupt(IOService *nub, if (++vectorsRegistered > numVectors) numVectors = vectorsRegistered; IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); - IOUnlock(vector->interruptLock); + IOLockUnlock(vector->interruptLock); return kIOReturnSuccess; } IOReturn IOSharedInterruptController::unregisterInterrupt(IOService *nub, int source) { - IOInterruptSource *interruptSources; - long vectorNumber; + IOInterruptVectorNumber vectorNumber; IOInterruptVector *vector; - OSData *vectorData; IOInterruptState interruptState; - - interruptSources = nub->_interruptSources; - vectorData = interruptSources[source].vectorData; - vectorNumber = *(long *)vectorData->getBytesNoCopy(); - vector = &vectors[vectorNumber]; - - // Get the lock for this vector. - IOTakeLock(vector->interruptLock); - - // Return success if it is not already registered - if (!vector->interruptRegistered) { - IOUnlock(vector->interruptLock); - return kIOReturnSuccess; + + for (vectorNumber = 0; vectorNumber < kIOSharedInterruptControllerDefaultVectors; vectorNumber++) { + vector = &vectors[vectorNumber]; + + // Get the lock for this vector. + IOLockLock(vector->interruptLock); + + // Return success if it is not already registered + if (!vector->interruptRegistered + || (vector->nub != nub) || (vector->source != source)) { + IOLockUnlock(vector->interruptLock); + continue; + } + + // Soft disable the source and the controller too. + disableInterrupt(nub, source); + + // Clear all the storage for the vector except for interruptLock. + vector->interruptActive = 0; + vector->interruptDisabledSoft = 0; + vector->interruptDisabledHard = 0; + vector->interruptRegistered = 0; + vector->nub = 0; + vector->source = 0; + vector->handler = 0; + vector->target = 0; + vector->refCon = 0; + + interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); + vectorsRegistered--; + IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); + + // Move along to the next one. + IOLockUnlock(vector->interruptLock); } - - // Soft disable the source and the controller too. - disableInterrupt(nub, source); - - // Clear all the storage for the vector except for interruptLock. - vector->interruptActive = 0; - vector->interruptDisabledSoft = 0; - vector->interruptDisabledHard = 0; - vector->interruptRegistered = 0; - vector->nub = 0; - vector->source = 0; - vector->handler = 0; - vector->target = 0; - vector->refCon = 0; - - interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); - vectorsRegistered--; - IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); - - IOUnlock(vector->interruptLock); - + // Re-enable the controller if all vectors are enabled. if (vectorsEnabled == vectorsRegistered) { controllerDisabled = 0; provider->enableInterrupt(0); } - + return kIOReturnSuccess; } @@ -609,14 +608,14 @@ IOReturn IOSharedInterruptController::enableInterrupt(IOService *nub, int source) { IOInterruptSource *interruptSources; - long vectorNumber; + IOInterruptVectorNumber vectorNumber; IOInterruptVector *vector; OSData *vectorData; IOInterruptState interruptState; interruptSources = nub->_interruptSources; vectorData = interruptSources[source].vectorData; - vectorNumber = *(long *)vectorData->getBytesNoCopy(); + vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy(); vector = &vectors[vectorNumber]; interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); @@ -641,32 +640,30 @@ IOReturn IOSharedInterruptController::disableInterrupt(IOService *nub, int source) { IOInterruptSource *interruptSources; - long vectorNumber; + IOInterruptVectorNumber vectorNumber; IOInterruptVector *vector; OSData *vectorData; IOInterruptState interruptState; interruptSources = nub->_interruptSources; vectorData = interruptSources[source].vectorData; - vectorNumber = *(long *)vectorData->getBytesNoCopy(); + vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy(); vector = &vectors[vectorNumber]; interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); if (!vector->interruptDisabledSoft) { vector->interruptDisabledSoft = 1; -#if __ppc__ - sync(); - isync(); +#if !defined(__i386__) && !defined(__x86_64__) + OSMemoryBarrier(); #endif + vectorsEnabled--; } IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); if (!getPlatform()->atInterruptLevel()) { - while (vector->interruptActive); -#if __ppc__ - isync(); -#endif + while (vector->interruptActive) + {} } return kIOReturnSuccess; @@ -682,28 +679,37 @@ IOReturn IOSharedInterruptController::handleInterrupt(void * /*refCon*/, IOService * nub, int /*source*/) { - long vectorNumber; + IOInterruptVectorNumber vectorNumber; IOInterruptVector *vector; for (vectorNumber = 0; vectorNumber < numVectors; vectorNumber++) { vector = &vectors[vectorNumber]; vector->interruptActive = 1; -#if __ppc__ - sync(); - isync(); -#endif - if (!vector->interruptDisabledSoft) { -#if __ppc__ - isync(); +#if !defined(__i386__) && !defined(__x86_64__) + OSMemoryBarrier(); #endif - - // Call the handler if it exists. - if (vector->interruptRegistered) { - vector->handler(vector->target, vector->refCon, - vector->nub, vector->source); - } - } + + if (!vector->interruptDisabledSoft) { + + // Call the handler if it exists. + if (vector->interruptRegistered) { + + bool trace = (gIOKitTrace & kIOTraceInterrupts) ? true : false; + + if (trace) + IOTimeStampStartConstant(IODBG_INTC(IOINTC_HANDLER), + (uintptr_t) vectorNumber, (uintptr_t) vector->handler, (uintptr_t)vector->target); + + // Call handler. + vector->handler(vector->target, vector->refCon, vector->nub, vector->source); + + if (trace) + IOTimeStampEndConstant(IODBG_INTC(IOINTC_HANDLER), + (uintptr_t) vectorNumber, (uintptr_t) vector->handler, (uintptr_t)vector->target); + + } + } vector->interruptActive = 0; }