X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/c0fea4742e91338fffdcf79f86a7c1d5e2b97eb1..b7266188b87f3620ec3f9f717e57194a7dd989fe:/iokit/Kernel/IOInterruptController.cpp?ds=inline diff --git a/iokit/Kernel/IOInterruptController.cpp b/iokit/Kernel/IOInterruptController.cpp index 2c8304e33..beedc1a8b 100644 --- a/iokit/Kernel/IOInterruptController.cpp +++ b/iokit/Kernel/IOInterruptController.cpp @@ -1,23 +1,29 @@ /* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1998-2008 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * @APPLE_OSREFERENCE_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 file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The 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. + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. * - * @APPLE_LICENSE_HEADER_END@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. @@ -38,7 +44,6 @@ #include #include - /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #define super IOService @@ -60,19 +65,21 @@ 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. @@ -81,6 +88,15 @@ IOReturn IOInterruptController::registerInterrupt(IOService *nub, int source, // 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; @@ -177,6 +193,7 @@ 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); } @@ -208,13 +225,13 @@ IOReturn IOInterruptController::registerInterrupt(IOService *nub, int source, 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. @@ -251,7 +268,7 @@ IOReturn IOInterruptController::getInterruptType(IOService *nub, int source, int *interruptType) { IOInterruptSource *interruptSources; - long vectorNumber; + IOInterruptVectorNumber vectorNumber; IOInterruptVector *vector; OSData *vectorData; @@ -259,7 +276,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); @@ -270,13 +287,13 @@ 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) { @@ -287,7 +304,8 @@ IOReturn IOInterruptController::enableInterrupt(IOService *nub, int source) #endif if (!getPlatform()->atInterruptLevel()) { - while (vector->interruptActive); + while (vector->interruptActive) + {} #if __ppc__ isync(); #endif @@ -305,13 +323,13 @@ 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; @@ -321,7 +339,8 @@ IOReturn IOInterruptController::disableInterrupt(IOService *nub, int source) #endif if (!getPlatform()->atInterruptLevel()) { - while (vector->interruptActive); + while (vector->interruptActive) + {} #if __ppc__ isync(); #endif @@ -333,13 +352,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); @@ -361,34 +380,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*/) { } @@ -427,6 +446,8 @@ IOReturn IOSharedInterruptController::initInterruptController(IOInterruptControl _numInterruptSources = 1; // Set up the IOInterruptSource to point at this. + parentController->retain(); + parentSource->retain(); _interruptSources[0].interruptController = parentController; _interruptSources[0].vectorData = parentSource; @@ -477,7 +498,7 @@ IOReturn IOSharedInterruptController::registerInterrupt(IOService *nub, void *refCon) { IOInterruptSource *interruptSources; - long vectorNumber; + IOInterruptVectorNumber vectorNumber; IOInterruptVector *vector = 0; OSData *vectorData; IOInterruptState interruptState; @@ -541,52 +562,51 @@ IOReturn IOSharedInterruptController::registerInterrupt(IOService *nub, 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) { + + for (vectorNumber = 0; vectorNumber < kIOSharedInterruptControllerDefaultVectors; vectorNumber++) { + vector = &vectors[vectorNumber]; + + // Get the lock for this vector. + IOTakeLock(vector->interruptLock); + + // Return success if it is not already registered + if (!vector->interruptRegistered + || (vector->nub != nub) || (vector->source != source)) { + IOUnlock(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. IOUnlock(vector->interruptLock); - return kIOReturnSuccess; } - - // 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; } @@ -601,14 +621,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); @@ -633,14 +653,14 @@ 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); @@ -655,7 +675,8 @@ IOReturn IOSharedInterruptController::disableInterrupt(IOService *nub, IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); if (!getPlatform()->atInterruptLevel()) { - while (vector->interruptActive); + while (vector->interruptActive) + {} #if __ppc__ isync(); #endif @@ -674,7 +695,7 @@ IOReturn IOSharedInterruptController::handleInterrupt(void * /*refCon*/, IOService * nub, int /*source*/) { - long vectorNumber; + IOInterruptVectorNumber vectorNumber; IOInterruptVector *vector; for (vectorNumber = 0; vectorNumber < numVectors; vectorNumber++) {