1c1dac77fSApple OSS Distributions /* 2186b8fceSApple OSS Distributions * Copyright (c) 2007-2012 Apple Inc. All rights reserved. 3186b8fceSApple OSS Distributions * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved. 4c1dac77fSApple OSS Distributions * 5e13b1fa5SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 6c1dac77fSApple OSS Distributions * 7e13b1fa5SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code 8e13b1fa5SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License 9e13b1fa5SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in 10e13b1fa5SApple OSS Distributions * compliance with the License. The rights granted to you under the License 11e13b1fa5SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of, 12e13b1fa5SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to 13e13b1fa5SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any 14e13b1fa5SApple OSS Distributions * terms of an Apple operating system software license agreement. 15c1dac77fSApple OSS Distributions * 16e13b1fa5SApple OSS Distributions * Please obtain a copy of the License at 17e13b1fa5SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file. 18e13b1fa5SApple OSS Distributions * 19e13b1fa5SApple OSS Distributions * The Original Code and all software distributed under the License are 20e13b1fa5SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 21c1dac77fSApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 22c1dac77fSApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 23e13b1fa5SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 24e13b1fa5SApple OSS Distributions * Please see the License for the specific language governing rights and 25e13b1fa5SApple OSS Distributions * limitations under the License. 26c1dac77fSApple OSS Distributions * 27e13b1fa5SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 28c1dac77fSApple OSS Distributions */ 29c1dac77fSApple OSS Distributions 30c1dac77fSApple OSS Distributions #include <IOKit/IOLib.h> 31c1dac77fSApple OSS Distributions #include <IOKit/IOService.h> 32c1dac77fSApple OSS Distributions #include <IOKit/IOPlatformExpert.h> 3314e3d835SApple OSS Distributions #include <IOKit/IODeviceTreeSupport.h> 34c1dac77fSApple OSS Distributions #include <IOKit/IOInterrupts.h> 35c1dac77fSApple OSS Distributions #include <IOKit/IOInterruptController.h> 36855239e5SApple OSS Distributions #include <IOKit/IOKitDebug.h> 37855239e5SApple OSS Distributions #include <IOKit/IOTimeStamp.h> 38855239e5SApple OSS Distributions 39c1dac77fSApple OSS Distributions 40c1dac77fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 41c1dac77fSApple OSS Distributions 42c1dac77fSApple OSS Distributions #define super IOService 43c1dac77fSApple OSS Distributions 44c1dac77fSApple OSS Distributions OSDefineMetaClassAndAbstractStructors(IOInterruptController, IOService); 45c1dac77fSApple OSS Distributions 46*bb611c8fSApple OSS Distributions OSMetaClassDefineReservedUsedX86(IOInterruptController, 0); 47*bb611c8fSApple OSS Distributions OSMetaClassDefineReservedUsedX86(IOInterruptController, 1); 48*bb611c8fSApple OSS Distributions OSMetaClassDefineReservedUsedX86(IOInterruptController, 2); 49c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptController, 3); 50c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptController, 4); 51c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptController, 5); 52c1dac77fSApple OSS Distributions 53c1dac77fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 54c1dac77fSApple OSS Distributions 55a5e72196SApple OSS Distributions IOReturn 56a5e72196SApple OSS Distributions IOInterruptController::registerInterrupt(IOService *nub, int source, 57c1dac77fSApple OSS Distributions void *target, 58c1dac77fSApple OSS Distributions IOInterruptHandler handler, 59c1dac77fSApple OSS Distributions void *refCon) 60c1dac77fSApple OSS Distributions { 61c1dac77fSApple OSS Distributions IOInterruptSource *interruptSources; 623ca3bd55SApple OSS Distributions IOInterruptVectorNumber vectorNumber; 63c1dac77fSApple OSS Distributions IOInterruptVector *vector; 643ca3bd55SApple OSS Distributions int wasDisabledSoft; 65c1dac77fSApple OSS Distributions IOReturn error; 66c1dac77fSApple OSS Distributions OSData *vectorData; 6714e3d835SApple OSS Distributions IOOptionBits options; 6814e3d835SApple OSS Distributions bool canBeShared, shouldBeShared, wasAlreadyRegisterd; 69c1dac77fSApple OSS Distributions 703ca3bd55SApple OSS Distributions IOService *originalNub = NULL;// Protected by wasAlreadyRegisterd 713ca3bd55SApple OSS Distributions int originalSource = 0;// Protected by wasAlreadyRegisterd 723ca3bd55SApple OSS Distributions 733ca3bd55SApple OSS Distributions 74c1dac77fSApple OSS Distributions interruptSources = nub->_interruptSources; 75c1dac77fSApple OSS Distributions vectorData = interruptSources[source].vectorData; 763ca3bd55SApple OSS Distributions vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy(); 77c1dac77fSApple OSS Distributions vector = &vectors[vectorNumber]; 78c1dac77fSApple OSS Distributions 79c1dac77fSApple OSS Distributions // Get the lock for this vector. 80855239e5SApple OSS Distributions IOLockLock(vector->interruptLock); 81c1dac77fSApple OSS Distributions 8214e3d835SApple OSS Distributions // Check if the interrupt source can/should be shared. 8314e3d835SApple OSS Distributions canBeShared = vectorCanBeShared(vectorNumber, vector); 8414e3d835SApple OSS Distributions IODTGetInterruptOptions(nub, source, &options); 853ca3bd55SApple OSS Distributions #if defined(__i386__) || defined(__x86_64__) 863ca3bd55SApple OSS Distributions int interruptType; 873ca3bd55SApple OSS Distributions if (OSDynamicCast(IOPlatformDevice, getProvider()) && 883ca3bd55SApple OSS Distributions (getInterruptType(nub, source, &interruptType) == kIOReturnSuccess) && 89a5e72196SApple OSS Distributions (kIOInterruptTypeLevel & interruptType)) { 903ca3bd55SApple OSS Distributions options |= kIODTInterruptShared; 913ca3bd55SApple OSS Distributions } 923ca3bd55SApple OSS Distributions #endif 9314e3d835SApple OSS Distributions shouldBeShared = canBeShared && (options & kIODTInterruptShared); 9414e3d835SApple OSS Distributions wasAlreadyRegisterd = vector->interruptRegistered; 9514e3d835SApple OSS Distributions 9614e3d835SApple OSS Distributions // If the vector is registered and can not be shared return error. 9714e3d835SApple OSS Distributions if (wasAlreadyRegisterd && !canBeShared) { 98855239e5SApple OSS Distributions IOLockUnlock(vector->interruptLock); 99c1dac77fSApple OSS Distributions return kIOReturnNoResources; 100c1dac77fSApple OSS Distributions } 101c1dac77fSApple OSS Distributions 10214e3d835SApple OSS Distributions // If this vector is already in use, and can be shared (implied), 10314e3d835SApple OSS Distributions // or it is not registered and should be shared, 10414e3d835SApple OSS Distributions // register as a shared interrupt. 10514e3d835SApple OSS Distributions if (wasAlreadyRegisterd || shouldBeShared) { 106c1dac77fSApple OSS Distributions // If this vector is not already shared, break it out. 107a5e72196SApple OSS Distributions if (vector->sharedController == NULL) { 108c1dac77fSApple OSS Distributions // Make the IOShareInterruptController instance 109c1dac77fSApple OSS Distributions vector->sharedController = new IOSharedInterruptController; 110a5e72196SApple OSS Distributions if (vector->sharedController == NULL) { 111855239e5SApple OSS Distributions IOLockUnlock(vector->interruptLock); 112c1dac77fSApple OSS Distributions return kIOReturnNoMemory; 113c1dac77fSApple OSS Distributions } 114c1dac77fSApple OSS Distributions 11514e3d835SApple OSS Distributions if (wasAlreadyRegisterd) { 116c1dac77fSApple OSS Distributions // Save the nub and source for the original consumer. 117c1dac77fSApple OSS Distributions originalNub = vector->nub; 118c1dac77fSApple OSS Distributions originalSource = vector->source; 119c1dac77fSApple OSS Distributions 12014e3d835SApple OSS Distributions // Physically disable the interrupt, but mark it as being enabled in the hardware. 121368ad365SApple OSS Distributions // The interruptDisabledSoft now indicates the driver's request for enablement. 122368ad365SApple OSS Distributions disableVectorHard(vectorNumber, vector); 123368ad365SApple OSS Distributions vector->interruptDisabledHard = 0; 12414e3d835SApple OSS Distributions } 125c1dac77fSApple OSS Distributions 126c1dac77fSApple OSS Distributions // Initialize the new shared interrupt controller. 12714e3d835SApple OSS Distributions error = vector->sharedController->initInterruptController(this, vectorData); 128c1dac77fSApple OSS Distributions // If the IOSharedInterruptController could not be initalized, 12914e3d835SApple OSS Distributions // if needed, put the original consumer's interrupt back to normal and 130c1dac77fSApple OSS Distributions // get rid of whats left of the shared controller. 131c1dac77fSApple OSS Distributions if (error != kIOReturnSuccess) { 132a5e72196SApple OSS Distributions if (wasAlreadyRegisterd) { 133a5e72196SApple OSS Distributions enableInterrupt(originalNub, originalSource); 134a5e72196SApple OSS Distributions } 135c1dac77fSApple OSS Distributions vector->sharedController->release(); 136a5e72196SApple OSS Distributions vector->sharedController = NULL; 137855239e5SApple OSS Distributions IOLockUnlock(vector->interruptLock); 138c1dac77fSApple OSS Distributions return error; 139c1dac77fSApple OSS Distributions } 140c1dac77fSApple OSS Distributions 14114e3d835SApple OSS Distributions // If there was an original consumer try to register it on the shared controller. 14214e3d835SApple OSS Distributions if (wasAlreadyRegisterd) { 143c1dac77fSApple OSS Distributions error = vector->sharedController->registerInterrupt(originalNub, 144c1dac77fSApple OSS Distributions originalSource, 145c1dac77fSApple OSS Distributions vector->target, 146c1dac77fSApple OSS Distributions vector->handler, 147c1dac77fSApple OSS Distributions vector->refCon); 148c1dac77fSApple OSS Distributions // If the original consumer could not be moved to the shared controller, 149c1dac77fSApple OSS Distributions // put the original consumor's interrupt back to normal and 150c1dac77fSApple OSS Distributions // get rid of whats left of the shared controller. 151c1dac77fSApple OSS Distributions if (error != kIOReturnSuccess) { 152368ad365SApple OSS Distributions // Save the driver's interrupt enablement state. 153368ad365SApple OSS Distributions wasDisabledSoft = vector->interruptDisabledSoft; 154368ad365SApple OSS Distributions 155368ad365SApple OSS Distributions // Make the interrupt really hard disabled. 156368ad365SApple OSS Distributions vector->interruptDisabledSoft = 1; 157368ad365SApple OSS Distributions vector->interruptDisabledHard = 1; 158368ad365SApple OSS Distributions 159368ad365SApple OSS Distributions // Enable the original consumer's interrupt if needed. 160a5e72196SApple OSS Distributions if (!wasDisabledSoft) { 161a5e72196SApple OSS Distributions originalNub->enableInterrupt(originalSource); 162a5e72196SApple OSS Distributions } 163c1dac77fSApple OSS Distributions enableInterrupt(originalNub, originalSource); 164368ad365SApple OSS Distributions 165c1dac77fSApple OSS Distributions vector->sharedController->release(); 166a5e72196SApple OSS Distributions vector->sharedController = NULL; 167855239e5SApple OSS Distributions IOLockUnlock(vector->interruptLock); 168c1dac77fSApple OSS Distributions return error; 169c1dac77fSApple OSS Distributions } 17014e3d835SApple OSS Distributions } 171c1dac77fSApple OSS Distributions 172c1dac77fSApple OSS Distributions // Fill in vector with the shared controller's info. 173c1dac77fSApple OSS Distributions vector->handler = (IOInterruptHandler)vector->sharedController->getInterruptHandlerAddress(); 174c1dac77fSApple OSS Distributions vector->nub = vector->sharedController; 175c1dac77fSApple OSS Distributions vector->source = 0; 176c1dac77fSApple OSS Distributions vector->target = vector->sharedController; 177a5e72196SApple OSS Distributions vector->refCon = NULL; 178c1dac77fSApple OSS Distributions 17914e3d835SApple OSS Distributions // If the interrupt was already registered, 18014e3d835SApple OSS Distributions // save the driver's interrupt enablement state. 181a5e72196SApple OSS Distributions if (wasAlreadyRegisterd) { 182a5e72196SApple OSS Distributions wasDisabledSoft = vector->interruptDisabledSoft; 183a5e72196SApple OSS Distributions } else { 184a5e72196SApple OSS Distributions wasDisabledSoft = true; 185a5e72196SApple OSS Distributions } 18614e3d835SApple OSS Distributions 18714e3d835SApple OSS Distributions // Do any specific initalization for this vector if it has not yet been used. 188a5e72196SApple OSS Distributions if (!wasAlreadyRegisterd) { 189a5e72196SApple OSS Distributions initVector(vectorNumber, vector); 190a5e72196SApple OSS Distributions } 191368ad365SApple OSS Distributions 192368ad365SApple OSS Distributions // Make the interrupt really hard disabled. 193368ad365SApple OSS Distributions vector->interruptDisabledSoft = 1; 194368ad365SApple OSS Distributions vector->interruptDisabledHard = 1; 19514e3d835SApple OSS Distributions vector->interruptRegistered = 1; 196368ad365SApple OSS Distributions 197c1dac77fSApple OSS Distributions // Enable the original consumer's interrupt if needed. 1983ca3bd55SApple OSS Distributions // originalNub is protected by wasAlreadyRegisterd here (see line 184). 199a5e72196SApple OSS Distributions if (!wasDisabledSoft) { 200a5e72196SApple OSS Distributions originalNub->enableInterrupt(originalSource); 201a5e72196SApple OSS Distributions } 202c1dac77fSApple OSS Distributions } 203c1dac77fSApple OSS Distributions 204c1dac77fSApple OSS Distributions error = vector->sharedController->registerInterrupt(nub, source, target, 205c1dac77fSApple OSS Distributions handler, refCon); 206855239e5SApple OSS Distributions IOLockUnlock(vector->interruptLock); 207c1dac77fSApple OSS Distributions return error; 208c1dac77fSApple OSS Distributions } 209c1dac77fSApple OSS Distributions 210c1dac77fSApple OSS Distributions // Fill in vector with the client's info. 211c1dac77fSApple OSS Distributions vector->handler = handler; 212c1dac77fSApple OSS Distributions vector->nub = nub; 213c1dac77fSApple OSS Distributions vector->source = source; 214c1dac77fSApple OSS Distributions vector->target = target; 215c1dac77fSApple OSS Distributions vector->refCon = refCon; 216c1dac77fSApple OSS Distributions 217c1dac77fSApple OSS Distributions // Do any specific initalization for this vector. 218c1dac77fSApple OSS Distributions initVector(vectorNumber, vector); 219c1dac77fSApple OSS Distributions 220c1dac77fSApple OSS Distributions // Get the vector ready. It starts hard disabled. 221c1dac77fSApple OSS Distributions vector->interruptDisabledHard = 1; 222c1dac77fSApple OSS Distributions vector->interruptDisabledSoft = 1; 223c1dac77fSApple OSS Distributions vector->interruptRegistered = 1; 224c1dac77fSApple OSS Distributions 225855239e5SApple OSS Distributions IOLockUnlock(vector->interruptLock); 226c1dac77fSApple OSS Distributions return kIOReturnSuccess; 227c1dac77fSApple OSS Distributions } 228c1dac77fSApple OSS Distributions 229a5e72196SApple OSS Distributions IOReturn 230a5e72196SApple OSS Distributions IOInterruptController::unregisterInterrupt(IOService *nub, int source) 231c1dac77fSApple OSS Distributions { 232c1dac77fSApple OSS Distributions IOInterruptSource *interruptSources; 2333ca3bd55SApple OSS Distributions IOInterruptVectorNumber vectorNumber; 234c1dac77fSApple OSS Distributions IOInterruptVector *vector; 235c1dac77fSApple OSS Distributions OSData *vectorData; 236c1dac77fSApple OSS Distributions 237c1dac77fSApple OSS Distributions interruptSources = nub->_interruptSources; 238c1dac77fSApple OSS Distributions vectorData = interruptSources[source].vectorData; 2393ca3bd55SApple OSS Distributions vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy(); 240c1dac77fSApple OSS Distributions vector = &vectors[vectorNumber]; 241c1dac77fSApple OSS Distributions 242c1dac77fSApple OSS Distributions // Get the lock for this vector. 243855239e5SApple OSS Distributions IOLockLock(vector->interruptLock); 244c1dac77fSApple OSS Distributions 245c1dac77fSApple OSS Distributions // Return success if it is not already registered 246c1dac77fSApple OSS Distributions if (!vector->interruptRegistered) { 247855239e5SApple OSS Distributions IOLockUnlock(vector->interruptLock); 248c1dac77fSApple OSS Distributions return kIOReturnSuccess; 249c1dac77fSApple OSS Distributions } 250c1dac77fSApple OSS Distributions 251c1dac77fSApple OSS Distributions // Soft disable the source. 252c1dac77fSApple OSS Distributions disableInterrupt(nub, source); 253c1dac77fSApple OSS Distributions 254c1dac77fSApple OSS Distributions // Turn the source off at hardware. 255c1dac77fSApple OSS Distributions disableVectorHard(vectorNumber, vector); 256c1dac77fSApple OSS Distributions 257c1dac77fSApple OSS Distributions // Clear all the storage for the vector except for interruptLock. 258c1dac77fSApple OSS Distributions vector->interruptActive = 0; 259c1dac77fSApple OSS Distributions vector->interruptDisabledSoft = 0; 260c1dac77fSApple OSS Distributions vector->interruptDisabledHard = 0; 261c1dac77fSApple OSS Distributions vector->interruptRegistered = 0; 262a5e72196SApple OSS Distributions vector->nub = NULL; 263c1dac77fSApple OSS Distributions vector->source = 0; 264a5e72196SApple OSS Distributions vector->handler = NULL; 265a5e72196SApple OSS Distributions vector->target = NULL; 266a5e72196SApple OSS Distributions vector->refCon = NULL; 267c1dac77fSApple OSS Distributions 268855239e5SApple OSS Distributions IOLockUnlock(vector->interruptLock); 269c1dac77fSApple OSS Distributions return kIOReturnSuccess; 270c1dac77fSApple OSS Distributions } 271c1dac77fSApple OSS Distributions 272a5e72196SApple OSS Distributions IOReturn 273a5e72196SApple OSS Distributions IOInterruptController::getInterruptType(IOService *nub, int source, 274c1dac77fSApple OSS Distributions int *interruptType) 275c1dac77fSApple OSS Distributions { 276c1dac77fSApple OSS Distributions IOInterruptSource *interruptSources; 2773ca3bd55SApple OSS Distributions IOInterruptVectorNumber vectorNumber; 278c1dac77fSApple OSS Distributions IOInterruptVector *vector; 279c1dac77fSApple OSS Distributions OSData *vectorData; 280c1dac77fSApple OSS Distributions 281a5e72196SApple OSS Distributions if (interruptType == NULL) { 282a5e72196SApple OSS Distributions return kIOReturnBadArgument; 283a5e72196SApple OSS Distributions } 284c1dac77fSApple OSS Distributions 285c1dac77fSApple OSS Distributions interruptSources = nub->_interruptSources; 286c1dac77fSApple OSS Distributions vectorData = interruptSources[source].vectorData; 2873ca3bd55SApple OSS Distributions vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy(); 288c1dac77fSApple OSS Distributions vector = &vectors[vectorNumber]; 289c1dac77fSApple OSS Distributions 290c1dac77fSApple OSS Distributions *interruptType = getVectorType(vectorNumber, vector); 291c1dac77fSApple OSS Distributions 292c1dac77fSApple OSS Distributions return kIOReturnSuccess; 293c1dac77fSApple OSS Distributions } 294c1dac77fSApple OSS Distributions 295a5e72196SApple OSS Distributions IOReturn 296a5e72196SApple OSS Distributions IOInterruptController::enableInterrupt(IOService *nub, int source) 297c1dac77fSApple OSS Distributions { 298c1dac77fSApple OSS Distributions IOInterruptSource *interruptSources; 2993ca3bd55SApple OSS Distributions IOInterruptVectorNumber vectorNumber; 300c1dac77fSApple OSS Distributions IOInterruptVector *vector; 301c1dac77fSApple OSS Distributions OSData *vectorData; 302c1dac77fSApple OSS Distributions 303c1dac77fSApple OSS Distributions interruptSources = nub->_interruptSources; 304c1dac77fSApple OSS Distributions vectorData = interruptSources[source].vectorData; 3053ca3bd55SApple OSS Distributions vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy(); 306c1dac77fSApple OSS Distributions vector = &vectors[vectorNumber]; 307c1dac77fSApple OSS Distributions 308c1dac77fSApple OSS Distributions if (vector->interruptDisabledSoft) { 309c1dac77fSApple OSS Distributions vector->interruptDisabledSoft = 0; 310186b8fceSApple OSS Distributions #if !defined(__i386__) && !defined(__x86_64__) 311186b8fceSApple OSS Distributions OSMemoryBarrier(); 312186b8fceSApple OSS Distributions #endif 313c1dac77fSApple OSS Distributions 3148149afccSApple OSS Distributions if (!getPlatform()->atInterruptLevel()) { 315a5e72196SApple OSS Distributions while (vector->interruptActive) { 316a5e72196SApple OSS Distributions } 3178149afccSApple OSS Distributions } 318c1dac77fSApple OSS Distributions if (vector->interruptDisabledHard) { 319c1dac77fSApple OSS Distributions vector->interruptDisabledHard = 0; 320c1dac77fSApple OSS Distributions 321*bb611c8fSApple OSS Distributions // A DSB ISH on ARM is needed to make sure the vector data are 322*bb611c8fSApple OSS Distributions // properly initialized before the MMIO enabling the interrupts 323*bb611c8fSApple OSS Distributions // in hardware. OSMemoryBarrier(), which maps to DMB, is not 324*bb611c8fSApple OSS Distributions // sufficient here as the CPUs are not consumers of the device 325*bb611c8fSApple OSS Distributions // write. Hence, the DMB does not guarantee the CPUs won't see an 326*bb611c8fSApple OSS Distributions // interrupt before it initalizes the vector data properly. 327*bb611c8fSApple OSS Distributions OSSynchronizeIO(); 328*bb611c8fSApple OSS Distributions 329c1dac77fSApple OSS Distributions enableVector(vectorNumber, vector); 330c1dac77fSApple OSS Distributions } 331c1dac77fSApple OSS Distributions } 332c1dac77fSApple OSS Distributions 333c1dac77fSApple OSS Distributions return kIOReturnSuccess; 334c1dac77fSApple OSS Distributions } 335c1dac77fSApple OSS Distributions 336a5e72196SApple OSS Distributions IOReturn 337a5e72196SApple OSS Distributions IOInterruptController::disableInterrupt(IOService *nub, int source) 338c1dac77fSApple OSS Distributions { 339c1dac77fSApple OSS Distributions IOInterruptSource *interruptSources; 3403ca3bd55SApple OSS Distributions IOInterruptVectorNumber vectorNumber; 341c1dac77fSApple OSS Distributions IOInterruptVector *vector; 342c1dac77fSApple OSS Distributions OSData *vectorData; 343c1dac77fSApple OSS Distributions 344c1dac77fSApple OSS Distributions interruptSources = nub->_interruptSources; 345c1dac77fSApple OSS Distributions vectorData = interruptSources[source].vectorData; 3463ca3bd55SApple OSS Distributions vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy(); 347c1dac77fSApple OSS Distributions vector = &vectors[vectorNumber]; 348c1dac77fSApple OSS Distributions 349c1dac77fSApple OSS Distributions vector->interruptDisabledSoft = 1; 350186b8fceSApple OSS Distributions #if !defined(__i386__) && !defined(__x86_64__) 351186b8fceSApple OSS Distributions OSMemoryBarrier(); 352186b8fceSApple OSS Distributions #endif 353c1dac77fSApple OSS Distributions 354c1dac77fSApple OSS Distributions if (!getPlatform()->atInterruptLevel()) { 355a5e72196SApple OSS Distributions while (vector->interruptActive) { 356a5e72196SApple OSS Distributions } 357c1dac77fSApple OSS Distributions } 358c1dac77fSApple OSS Distributions 359c1dac77fSApple OSS Distributions return kIOReturnSuccess; 360c1dac77fSApple OSS Distributions } 361c1dac77fSApple OSS Distributions 362a5e72196SApple OSS Distributions IOReturn 363a5e72196SApple OSS Distributions IOInterruptController::causeInterrupt(IOService *nub, int source) 364c1dac77fSApple OSS Distributions { 365c1dac77fSApple OSS Distributions IOInterruptSource *interruptSources; 3663ca3bd55SApple OSS Distributions IOInterruptVectorNumber vectorNumber; 367c1dac77fSApple OSS Distributions IOInterruptVector *vector; 368c1dac77fSApple OSS Distributions OSData *vectorData; 369c1dac77fSApple OSS Distributions 370c1dac77fSApple OSS Distributions interruptSources = nub->_interruptSources; 371c1dac77fSApple OSS Distributions vectorData = interruptSources[source].vectorData; 3723ca3bd55SApple OSS Distributions vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy(); 373c1dac77fSApple OSS Distributions vector = &vectors[vectorNumber]; 374c1dac77fSApple OSS Distributions 375c1dac77fSApple OSS Distributions causeVector(vectorNumber, vector); 376c1dac77fSApple OSS Distributions 377c1dac77fSApple OSS Distributions return kIOReturnSuccess; 378c1dac77fSApple OSS Distributions } 379c1dac77fSApple OSS Distributions 380a5e72196SApple OSS Distributions IOInterruptAction 381a5e72196SApple OSS Distributions IOInterruptController::getInterruptHandlerAddress(void) 382c1dac77fSApple OSS Distributions { 383a5e72196SApple OSS Distributions return NULL; 384c1dac77fSApple OSS Distributions } 385c1dac77fSApple OSS Distributions 386a5e72196SApple OSS Distributions IOReturn 387a5e72196SApple OSS Distributions IOInterruptController::handleInterrupt(void *refCon, IOService *nub, 388c1dac77fSApple OSS Distributions int source) 389c1dac77fSApple OSS Distributions { 390c1dac77fSApple OSS Distributions return kIOReturnInvalid; 391c1dac77fSApple OSS Distributions } 392c1dac77fSApple OSS Distributions 393c1dac77fSApple OSS Distributions 394c1dac77fSApple OSS Distributions // Methods to be overridden for simplifed interrupt controller subclasses. 395c1dac77fSApple OSS Distributions 396a5e72196SApple OSS Distributions bool 397a5e72196SApple OSS Distributions IOInterruptController::vectorCanBeShared(IOInterruptVectorNumber /*vectorNumber*/, 398c1dac77fSApple OSS Distributions IOInterruptVector */*vector*/) 399c1dac77fSApple OSS Distributions { 400c1dac77fSApple OSS Distributions return false; 401c1dac77fSApple OSS Distributions } 402c1dac77fSApple OSS Distributions 403a5e72196SApple OSS Distributions void 404a5e72196SApple OSS Distributions IOInterruptController::initVector(IOInterruptVectorNumber /*vectorNumber*/, 405c1dac77fSApple OSS Distributions IOInterruptVector */*vector*/) 406c1dac77fSApple OSS Distributions { 407c1dac77fSApple OSS Distributions } 408c1dac77fSApple OSS Distributions 409a5e72196SApple OSS Distributions int 410a5e72196SApple OSS Distributions IOInterruptController::getVectorType(IOInterruptVectorNumber /*vectorNumber*/, 411c1dac77fSApple OSS Distributions IOInterruptVector */*vector*/) 412c1dac77fSApple OSS Distributions { 413c1dac77fSApple OSS Distributions return kIOInterruptTypeEdge; 414c1dac77fSApple OSS Distributions } 415c1dac77fSApple OSS Distributions 416a5e72196SApple OSS Distributions void 417a5e72196SApple OSS Distributions IOInterruptController::disableVectorHard(IOInterruptVectorNumber /*vectorNumber*/, 418c1dac77fSApple OSS Distributions IOInterruptVector */*vector*/) 419c1dac77fSApple OSS Distributions { 420c1dac77fSApple OSS Distributions } 421c1dac77fSApple OSS Distributions 422a5e72196SApple OSS Distributions void 423a5e72196SApple OSS Distributions IOInterruptController::enableVector(IOInterruptVectorNumber /*vectorNumber*/, 424c1dac77fSApple OSS Distributions IOInterruptVector */*vector*/) 425c1dac77fSApple OSS Distributions { 426c1dac77fSApple OSS Distributions } 427c1dac77fSApple OSS Distributions 428a5e72196SApple OSS Distributions void 429a5e72196SApple OSS Distributions IOInterruptController::causeVector(IOInterruptVectorNumber /*vectorNumber*/, 430c1dac77fSApple OSS Distributions IOInterruptVector */*vector*/) 431c1dac77fSApple OSS Distributions { 432c1dac77fSApple OSS Distributions } 433c1dac77fSApple OSS Distributions 434a5e72196SApple OSS Distributions void 435*bb611c8fSApple OSS Distributions IOInterruptController::setCPUInterruptProperties(IOService */*service*/) 436*bb611c8fSApple OSS Distributions { 437*bb611c8fSApple OSS Distributions } 438*bb611c8fSApple OSS Distributions 439*bb611c8fSApple OSS Distributions void 440*bb611c8fSApple OSS Distributions IOInterruptController::sendIPI(unsigned int /*cpu_id*/, bool /*deferred*/) 441*bb611c8fSApple OSS Distributions { 442*bb611c8fSApple OSS Distributions } 443*bb611c8fSApple OSS Distributions 444*bb611c8fSApple OSS Distributions void 445*bb611c8fSApple OSS Distributions IOInterruptController::cancelDeferredIPI(unsigned int /*cpu_id*/) 446*bb611c8fSApple OSS Distributions { 447*bb611c8fSApple OSS Distributions } 448*bb611c8fSApple OSS Distributions 449*bb611c8fSApple OSS Distributions void 450a5e72196SApple OSS Distributions IOInterruptController::timeStampSpuriousInterrupt(void) 45176e12aa3SApple OSS Distributions { 45276e12aa3SApple OSS Distributions uint64_t providerID = 0; 45376e12aa3SApple OSS Distributions IOService * provider = getProvider(); 45476e12aa3SApple OSS Distributions 45576e12aa3SApple OSS Distributions if (provider) { 45676e12aa3SApple OSS Distributions providerID = provider->getRegistryEntryID(); 45776e12aa3SApple OSS Distributions } 45876e12aa3SApple OSS Distributions 45976e12aa3SApple OSS Distributions IOTimeStampConstant(IODBG_INTC(IOINTC_SPURIOUS), providerID); 46076e12aa3SApple OSS Distributions } 46176e12aa3SApple OSS Distributions 462a5e72196SApple OSS Distributions void 463a5e72196SApple OSS Distributions IOInterruptController::timeStampInterruptHandlerInternal(bool isStart, IOInterruptVectorNumber vectorNumber, IOInterruptVector *vector) 46476e12aa3SApple OSS Distributions { 46576e12aa3SApple OSS Distributions uint64_t providerID = 0; 46676e12aa3SApple OSS Distributions vm_offset_t unslidHandler = 0; 46776e12aa3SApple OSS Distributions vm_offset_t unslidTarget = 0; 46876e12aa3SApple OSS Distributions 46976e12aa3SApple OSS Distributions IOService * provider = getProvider(); 47076e12aa3SApple OSS Distributions 47176e12aa3SApple OSS Distributions if (provider) { 47276e12aa3SApple OSS Distributions providerID = provider->getRegistryEntryID(); 47376e12aa3SApple OSS Distributions } 47476e12aa3SApple OSS Distributions 47576e12aa3SApple OSS Distributions if (vector) { 47676e12aa3SApple OSS Distributions unslidHandler = VM_KERNEL_UNSLIDE((vm_offset_t)vector->handler); 47776e12aa3SApple OSS Distributions unslidTarget = VM_KERNEL_UNSLIDE_OR_PERM((vm_offset_t)vector->target); 47876e12aa3SApple OSS Distributions } 47976e12aa3SApple OSS Distributions 48076e12aa3SApple OSS Distributions 48176e12aa3SApple OSS Distributions if (isStart) { 482*bb611c8fSApple OSS Distributions #if INTERRUPT_MASKED_DEBUG 483*bb611c8fSApple OSS Distributions ml_irq_debug_start((uintptr_t)vector->handler, (uintptr_t)vector); 484*bb611c8fSApple OSS Distributions #endif 48576e12aa3SApple OSS Distributions IOTimeStampStartConstant(IODBG_INTC(IOINTC_HANDLER), (uintptr_t)vectorNumber, (uintptr_t)unslidHandler, 48676e12aa3SApple OSS Distributions (uintptr_t)unslidTarget, (uintptr_t)providerID); 48776e12aa3SApple OSS Distributions } else { 48876e12aa3SApple OSS Distributions IOTimeStampEndConstant(IODBG_INTC(IOINTC_HANDLER), (uintptr_t)vectorNumber, (uintptr_t)unslidHandler, 48976e12aa3SApple OSS Distributions (uintptr_t)unslidTarget, (uintptr_t)providerID); 490*bb611c8fSApple OSS Distributions #if INTERRUPT_MASKED_DEBUG 491*bb611c8fSApple OSS Distributions ml_irq_debug_end(); 492*bb611c8fSApple OSS Distributions #endif 49376e12aa3SApple OSS Distributions } 49476e12aa3SApple OSS Distributions } 49576e12aa3SApple OSS Distributions 496a5e72196SApple OSS Distributions void 497a5e72196SApple OSS Distributions IOInterruptController::timeStampInterruptHandlerStart(IOInterruptVectorNumber vectorNumber, IOInterruptVector *vector) 49876e12aa3SApple OSS Distributions { 49976e12aa3SApple OSS Distributions timeStampInterruptHandlerInternal(true, vectorNumber, vector); 50076e12aa3SApple OSS Distributions } 50176e12aa3SApple OSS Distributions 502a5e72196SApple OSS Distributions void 503a5e72196SApple OSS Distributions IOInterruptController::timeStampInterruptHandlerEnd(IOInterruptVectorNumber vectorNumber, IOInterruptVector *vector) 50476e12aa3SApple OSS Distributions { 50576e12aa3SApple OSS Distributions timeStampInterruptHandlerInternal(false, vectorNumber, vector); 50676e12aa3SApple OSS Distributions } 507c1dac77fSApple OSS Distributions 508c1dac77fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 509c1dac77fSApple OSS Distributions 510c1dac77fSApple OSS Distributions #undef super 511c1dac77fSApple OSS Distributions #define super IOInterruptController 512c1dac77fSApple OSS Distributions 513c1dac77fSApple OSS Distributions OSDefineMetaClassAndStructors(IOSharedInterruptController, IOInterruptController); 514c1dac77fSApple OSS Distributions 515c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedInterruptController, 0); 516c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedInterruptController, 1); 517c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedInterruptController, 2); 518c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedInterruptController, 3); 519c1dac77fSApple OSS Distributions 520c1dac77fSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 521c1dac77fSApple OSS Distributions 52214e3d835SApple OSS Distributions #define kIOSharedInterruptControllerDefaultVectors (128) 52314e3d835SApple OSS Distributions 524a5e72196SApple OSS Distributions IOReturn 525a5e72196SApple OSS Distributions IOSharedInterruptController::initInterruptController(IOInterruptController *parentController, OSData *parentSource) 526c1dac77fSApple OSS Distributions { 527c1dac77fSApple OSS Distributions int cnt, interruptType; 528c1dac77fSApple OSS Distributions IOReturn error; 529186b8fceSApple OSS Distributions 530a5e72196SApple OSS Distributions if (!super::init()) { 531c1dac77fSApple OSS Distributions return kIOReturnNoResources; 532a5e72196SApple OSS Distributions } 533c1dac77fSApple OSS Distributions 534c1dac77fSApple OSS Distributions // Set provider to this so enable/disable nub stuff works. 535c1dac77fSApple OSS Distributions provider = this; 536c1dac77fSApple OSS Distributions 537c1dac77fSApple OSS Distributions // Allocate the IOInterruptSource so this can act like a nub. 538c1dac77fSApple OSS Distributions _interruptSources = (IOInterruptSource *)IOMalloc(sizeof(IOInterruptSource)); 539a5e72196SApple OSS Distributions if (_interruptSources == NULL) { 540a5e72196SApple OSS Distributions return kIOReturnNoMemory; 541a5e72196SApple OSS Distributions } 542c1dac77fSApple OSS Distributions _numInterruptSources = 1; 543c1dac77fSApple OSS Distributions 544c1dac77fSApple OSS Distributions // Set up the IOInterruptSource to point at this. 545e13b1fa5SApple OSS Distributions parentController->retain(); 546e13b1fa5SApple OSS Distributions parentSource->retain(); 547c1dac77fSApple OSS Distributions _interruptSources[0].interruptController = parentController; 548c1dac77fSApple OSS Distributions _interruptSources[0].vectorData = parentSource; 549c1dac77fSApple OSS Distributions 550c1dac77fSApple OSS Distributions sourceIsLevel = false; 551c1dac77fSApple OSS Distributions error = provider->getInterruptType(0, &interruptType); 552c1dac77fSApple OSS Distributions if (error == kIOReturnSuccess) { 553a5e72196SApple OSS Distributions if (interruptType & kIOInterruptTypeLevel) { 554c1dac77fSApple OSS Distributions sourceIsLevel = true; 555c1dac77fSApple OSS Distributions } 556a5e72196SApple OSS Distributions } 557c1dac77fSApple OSS Distributions 558c1dac77fSApple OSS Distributions // Allocate the memory for the vectors 55914e3d835SApple OSS Distributions numVectors = kIOSharedInterruptControllerDefaultVectors; // For now a constant number. 560c1dac77fSApple OSS Distributions vectors = (IOInterruptVector *)IOMalloc(numVectors * sizeof(IOInterruptVector)); 561c1dac77fSApple OSS Distributions if (vectors == NULL) { 562c1dac77fSApple OSS Distributions IOFree(_interruptSources, sizeof(IOInterruptSource)); 563c1dac77fSApple OSS Distributions return kIOReturnNoMemory; 564c1dac77fSApple OSS Distributions } 565c1dac77fSApple OSS Distributions bzero(vectors, numVectors * sizeof(IOInterruptVector)); 566c1dac77fSApple OSS Distributions 567c1dac77fSApple OSS Distributions // Allocate the lock for the controller. 568c1dac77fSApple OSS Distributions controllerLock = IOSimpleLockAlloc(); 569a5e72196SApple OSS Distributions if (controllerLock == NULL) { 570a5e72196SApple OSS Distributions return kIOReturnNoResources; 571a5e72196SApple OSS Distributions } 572c1dac77fSApple OSS Distributions 573c1dac77fSApple OSS Distributions // Allocate locks for the vectors. 574c1dac77fSApple OSS Distributions for (cnt = 0; cnt < numVectors; cnt++) { 575c1dac77fSApple OSS Distributions vectors[cnt].interruptLock = IOLockAlloc(); 576c1dac77fSApple OSS Distributions if (vectors[cnt].interruptLock == NULL) { 577c1dac77fSApple OSS Distributions for (cnt = 0; cnt < numVectors; cnt++) { 578a5e72196SApple OSS Distributions if (vectors[cnt].interruptLock != NULL) { 579c1dac77fSApple OSS Distributions IOLockFree(vectors[cnt].interruptLock); 580c1dac77fSApple OSS Distributions } 581a5e72196SApple OSS Distributions } 582c1dac77fSApple OSS Distributions return kIOReturnNoResources; 583c1dac77fSApple OSS Distributions } 584c1dac77fSApple OSS Distributions } 585c1dac77fSApple OSS Distributions 58614e3d835SApple OSS Distributions numVectors = 0; // reset the high water mark for used vectors 587c1dac77fSApple OSS Distributions vectorsRegistered = 0; 588c1dac77fSApple OSS Distributions vectorsEnabled = 0; 589c1dac77fSApple OSS Distributions controllerDisabled = 1; 590c1dac77fSApple OSS Distributions 591c1dac77fSApple OSS Distributions return kIOReturnSuccess; 592c1dac77fSApple OSS Distributions } 593c1dac77fSApple OSS Distributions 594a5e72196SApple OSS Distributions IOReturn 595a5e72196SApple OSS Distributions IOSharedInterruptController::registerInterrupt(IOService *nub, 596c1dac77fSApple OSS Distributions int source, 597c1dac77fSApple OSS Distributions void *target, 598c1dac77fSApple OSS Distributions IOInterruptHandler handler, 599c1dac77fSApple OSS Distributions void *refCon) 600c1dac77fSApple OSS Distributions { 601c1dac77fSApple OSS Distributions IOInterruptSource *interruptSources; 6023ca3bd55SApple OSS Distributions IOInterruptVectorNumber vectorNumber; 603a5e72196SApple OSS Distributions IOInterruptVector *vector = NULL; 604c1dac77fSApple OSS Distributions OSData *vectorData; 605c1dac77fSApple OSS Distributions IOInterruptState interruptState; 606c1dac77fSApple OSS Distributions 607c1dac77fSApple OSS Distributions interruptSources = nub->_interruptSources; 608c1dac77fSApple OSS Distributions 609c1dac77fSApple OSS Distributions // Find a free vector. 61014e3d835SApple OSS Distributions vectorNumber = kIOSharedInterruptControllerDefaultVectors; 61114e3d835SApple OSS Distributions while (vectorsRegistered != kIOSharedInterruptControllerDefaultVectors) { 61214e3d835SApple OSS Distributions for (vectorNumber = 0; vectorNumber < kIOSharedInterruptControllerDefaultVectors; vectorNumber++) { 613c1dac77fSApple OSS Distributions vector = &vectors[vectorNumber]; 614c1dac77fSApple OSS Distributions 615c1dac77fSApple OSS Distributions // Get the lock for this vector. 616855239e5SApple OSS Distributions IOLockLock(vector->interruptLock); 617c1dac77fSApple OSS Distributions 618c1dac77fSApple OSS Distributions // Is it unregistered? 619a5e72196SApple OSS Distributions if (!vector->interruptRegistered) { 620a5e72196SApple OSS Distributions break; 621a5e72196SApple OSS Distributions } 622c1dac77fSApple OSS Distributions 623c1dac77fSApple OSS Distributions // Move along to the next one. 624855239e5SApple OSS Distributions IOLockUnlock(vector->interruptLock); 625c1dac77fSApple OSS Distributions } 626c1dac77fSApple OSS Distributions 627a5e72196SApple OSS Distributions if (vectorNumber != kIOSharedInterruptControllerDefaultVectors) { 628a5e72196SApple OSS Distributions break; 629a5e72196SApple OSS Distributions } 630c1dac77fSApple OSS Distributions } 631c1dac77fSApple OSS Distributions 632c1dac77fSApple OSS Distributions // Could not find a free one, so give up. 63314e3d835SApple OSS Distributions if (vectorNumber == kIOSharedInterruptControllerDefaultVectors) { 634c1dac77fSApple OSS Distributions return kIOReturnNoResources; 635c1dac77fSApple OSS Distributions } 636c1dac77fSApple OSS Distributions 637c1dac77fSApple OSS Distributions // Create the vectorData for the IOInterruptSource. 638c1dac77fSApple OSS Distributions vectorData = OSData::withBytes(&vectorNumber, sizeof(vectorNumber)); 639a5e72196SApple OSS Distributions if (vectorData == NULL) { 64088cc0b97SApple OSS Distributions IOLockUnlock(vector->interruptLock); 641c1dac77fSApple OSS Distributions return kIOReturnNoMemory; 642c1dac77fSApple OSS Distributions } 643c1dac77fSApple OSS Distributions 644c1dac77fSApple OSS Distributions // Fill in the IOInterruptSource with the controller's info. 645c1dac77fSApple OSS Distributions interruptSources[source].interruptController = this; 646c1dac77fSApple OSS Distributions interruptSources[source].vectorData = vectorData; 647c1dac77fSApple OSS Distributions 648c1dac77fSApple OSS Distributions // Fill in vector with the client's info. 649c1dac77fSApple OSS Distributions vector->handler = handler; 650c1dac77fSApple OSS Distributions vector->nub = nub; 651c1dac77fSApple OSS Distributions vector->source = source; 652c1dac77fSApple OSS Distributions vector->target = target; 653c1dac77fSApple OSS Distributions vector->refCon = refCon; 654c1dac77fSApple OSS Distributions 65514e3d835SApple OSS Distributions // Get the vector ready. It starts off soft disabled. 656c1dac77fSApple OSS Distributions vector->interruptDisabledSoft = 1; 657c1dac77fSApple OSS Distributions vector->interruptRegistered = 1; 658c1dac77fSApple OSS Distributions 659c1dac77fSApple OSS Distributions interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); 66014e3d835SApple OSS Distributions // Move the high water mark if needed 661a5e72196SApple OSS Distributions if (++vectorsRegistered > numVectors) { 662a5e72196SApple OSS Distributions numVectors = vectorsRegistered; 663a5e72196SApple OSS Distributions } 664c1dac77fSApple OSS Distributions IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); 665c1dac77fSApple OSS Distributions 666855239e5SApple OSS Distributions IOLockUnlock(vector->interruptLock); 667c1dac77fSApple OSS Distributions return kIOReturnSuccess; 668c1dac77fSApple OSS Distributions } 669c1dac77fSApple OSS Distributions 670a5e72196SApple OSS Distributions IOReturn 671a5e72196SApple OSS Distributions IOSharedInterruptController::unregisterInterrupt(IOService *nub, 672c1dac77fSApple OSS Distributions int source) 673c1dac77fSApple OSS Distributions { 6743ca3bd55SApple OSS Distributions IOInterruptVectorNumber vectorNumber; 675c1dac77fSApple OSS Distributions IOInterruptVector *vector; 67614e3d835SApple OSS Distributions IOInterruptState interruptState; 677c1dac77fSApple OSS Distributions 6783ca3bd55SApple OSS Distributions for (vectorNumber = 0; vectorNumber < kIOSharedInterruptControllerDefaultVectors; vectorNumber++) { 679c1dac77fSApple OSS Distributions vector = &vectors[vectorNumber]; 680c1dac77fSApple OSS Distributions 681c1dac77fSApple OSS Distributions // Get the lock for this vector. 682855239e5SApple OSS Distributions IOLockLock(vector->interruptLock); 683c1dac77fSApple OSS Distributions 684c1dac77fSApple OSS Distributions // Return success if it is not already registered 6853ca3bd55SApple OSS Distributions if (!vector->interruptRegistered 6863ca3bd55SApple OSS Distributions || (vector->nub != nub) || (vector->source != source)) { 687855239e5SApple OSS Distributions IOLockUnlock(vector->interruptLock); 6883ca3bd55SApple OSS Distributions continue; 689c1dac77fSApple OSS Distributions } 690c1dac77fSApple OSS Distributions 69114e3d835SApple OSS Distributions // Soft disable the source and the controller too. 692c1dac77fSApple OSS Distributions disableInterrupt(nub, source); 693c1dac77fSApple OSS Distributions 694c1dac77fSApple OSS Distributions // Clear all the storage for the vector except for interruptLock. 695c1dac77fSApple OSS Distributions vector->interruptActive = 0; 696c1dac77fSApple OSS Distributions vector->interruptDisabledSoft = 0; 697c1dac77fSApple OSS Distributions vector->interruptDisabledHard = 0; 698c1dac77fSApple OSS Distributions vector->interruptRegistered = 0; 699a5e72196SApple OSS Distributions vector->nub = NULL; 700c1dac77fSApple OSS Distributions vector->source = 0; 701a5e72196SApple OSS Distributions vector->handler = NULL; 702a5e72196SApple OSS Distributions vector->target = NULL; 703a5e72196SApple OSS Distributions vector->refCon = NULL; 704c1dac77fSApple OSS Distributions 705c1dac77fSApple OSS Distributions interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); 706c1dac77fSApple OSS Distributions vectorsRegistered--; 707c1dac77fSApple OSS Distributions IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); 708c1dac77fSApple OSS Distributions 7093ca3bd55SApple OSS Distributions // Move along to the next one. 710855239e5SApple OSS Distributions IOLockUnlock(vector->interruptLock); 7113ca3bd55SApple OSS Distributions } 71214e3d835SApple OSS Distributions 71314e3d835SApple OSS Distributions // Re-enable the controller if all vectors are enabled. 71414e3d835SApple OSS Distributions if (vectorsEnabled == vectorsRegistered) { 71514e3d835SApple OSS Distributions controllerDisabled = 0; 71614e3d835SApple OSS Distributions provider->enableInterrupt(0); 71714e3d835SApple OSS Distributions } 71814e3d835SApple OSS Distributions 719c1dac77fSApple OSS Distributions return kIOReturnSuccess; 720c1dac77fSApple OSS Distributions } 721c1dac77fSApple OSS Distributions 722a5e72196SApple OSS Distributions IOReturn 723a5e72196SApple OSS Distributions IOSharedInterruptController::getInterruptType(IOService */*nub*/, 724c1dac77fSApple OSS Distributions int /*source*/, 725c1dac77fSApple OSS Distributions int *interruptType) 726c1dac77fSApple OSS Distributions { 727c1dac77fSApple OSS Distributions return provider->getInterruptType(0, interruptType); 728c1dac77fSApple OSS Distributions } 729c1dac77fSApple OSS Distributions 730a5e72196SApple OSS Distributions IOReturn 731a5e72196SApple OSS Distributions IOSharedInterruptController::enableInterrupt(IOService *nub, 732c1dac77fSApple OSS Distributions int source) 733c1dac77fSApple OSS Distributions { 734c1dac77fSApple OSS Distributions IOInterruptSource *interruptSources; 7353ca3bd55SApple OSS Distributions IOInterruptVectorNumber vectorNumber; 736c1dac77fSApple OSS Distributions IOInterruptVector *vector; 737c1dac77fSApple OSS Distributions OSData *vectorData; 738fad439e7SApple OSS Distributions IOInterruptState interruptState; 739c1dac77fSApple OSS Distributions 740c1dac77fSApple OSS Distributions interruptSources = nub->_interruptSources; 741c1dac77fSApple OSS Distributions vectorData = interruptSources[source].vectorData; 7423ca3bd55SApple OSS Distributions vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy(); 743c1dac77fSApple OSS Distributions vector = &vectors[vectorNumber]; 744c1dac77fSApple OSS Distributions 745c1dac77fSApple OSS Distributions interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); 746fad439e7SApple OSS Distributions if (!vector->interruptDisabledSoft) { 747fad439e7SApple OSS Distributions IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); 748fad439e7SApple OSS Distributions return kIOReturnSuccess; 749fad439e7SApple OSS Distributions } 750fad439e7SApple OSS Distributions 7518149afccSApple OSS Distributions vector->interruptDisabledSoft = 0; 752c1dac77fSApple OSS Distributions vectorsEnabled++; 753c1dac77fSApple OSS Distributions IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); 754c1dac77fSApple OSS Distributions 755c1dac77fSApple OSS Distributions if (controllerDisabled && (vectorsEnabled == vectorsRegistered)) { 756c1dac77fSApple OSS Distributions controllerDisabled = 0; 757c1dac77fSApple OSS Distributions provider->enableInterrupt(0); 758c1dac77fSApple OSS Distributions } 759c1dac77fSApple OSS Distributions 760c1dac77fSApple OSS Distributions return kIOReturnSuccess; 761c1dac77fSApple OSS Distributions } 762c1dac77fSApple OSS Distributions 763a5e72196SApple OSS Distributions IOReturn 764a5e72196SApple OSS Distributions IOSharedInterruptController::disableInterrupt(IOService *nub, 765c1dac77fSApple OSS Distributions int source) 766c1dac77fSApple OSS Distributions { 767c1dac77fSApple OSS Distributions IOInterruptSource *interruptSources; 7683ca3bd55SApple OSS Distributions IOInterruptVectorNumber vectorNumber; 769c1dac77fSApple OSS Distributions IOInterruptVector *vector; 770c1dac77fSApple OSS Distributions OSData *vectorData; 771fad439e7SApple OSS Distributions IOInterruptState interruptState; 772c1dac77fSApple OSS Distributions 773c1dac77fSApple OSS Distributions interruptSources = nub->_interruptSources; 774c1dac77fSApple OSS Distributions vectorData = interruptSources[source].vectorData; 7753ca3bd55SApple OSS Distributions vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy(); 776c1dac77fSApple OSS Distributions vector = &vectors[vectorNumber]; 777c1dac77fSApple OSS Distributions 7788149afccSApple OSS Distributions interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); 779fad439e7SApple OSS Distributions if (!vector->interruptDisabledSoft) { 780c1dac77fSApple OSS Distributions vector->interruptDisabledSoft = 1; 781186b8fceSApple OSS Distributions #if !defined(__i386__) && !defined(__x86_64__) 782186b8fceSApple OSS Distributions OSMemoryBarrier(); 783186b8fceSApple OSS Distributions #endif 784186b8fceSApple OSS Distributions 785c1dac77fSApple OSS Distributions vectorsEnabled--; 786c1dac77fSApple OSS Distributions } 787fad439e7SApple OSS Distributions IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); 788c1dac77fSApple OSS Distributions 789c1dac77fSApple OSS Distributions if (!getPlatform()->atInterruptLevel()) { 790a5e72196SApple OSS Distributions while (vector->interruptActive) { 791a5e72196SApple OSS Distributions } 792c1dac77fSApple OSS Distributions } 793c1dac77fSApple OSS Distributions 794c1dac77fSApple OSS Distributions return kIOReturnSuccess; 795c1dac77fSApple OSS Distributions } 796c1dac77fSApple OSS Distributions 797a5e72196SApple OSS Distributions IOInterruptAction 798a5e72196SApple OSS Distributions IOSharedInterruptController::getInterruptHandlerAddress(void) 799c1dac77fSApple OSS Distributions { 800e13b1fa5SApple OSS Distributions return OSMemberFunctionCast(IOInterruptAction, 801e13b1fa5SApple OSS Distributions this, &IOSharedInterruptController::handleInterrupt); 802c1dac77fSApple OSS Distributions } 803c1dac77fSApple OSS Distributions 804a5e72196SApple OSS Distributions IOReturn 805a5e72196SApple OSS Distributions IOSharedInterruptController::handleInterrupt(void * /*refCon*/, 806c1dac77fSApple OSS Distributions IOService * nub, 807c1dac77fSApple OSS Distributions int /*source*/) 808c1dac77fSApple OSS Distributions { 8093ca3bd55SApple OSS Distributions IOInterruptVectorNumber vectorNumber; 810c1dac77fSApple OSS Distributions IOInterruptVector *vector; 811c1dac77fSApple OSS Distributions 812c1dac77fSApple OSS Distributions for (vectorNumber = 0; vectorNumber < numVectors; vectorNumber++) { 813c1dac77fSApple OSS Distributions vector = &vectors[vectorNumber]; 814c1dac77fSApple OSS Distributions 815c1dac77fSApple OSS Distributions vector->interruptActive = 1; 816186b8fceSApple OSS Distributions #if !defined(__i386__) && !defined(__x86_64__) 817186b8fceSApple OSS Distributions OSMemoryBarrier(); 818186b8fceSApple OSS Distributions #endif 819186b8fceSApple OSS Distributions 820c1dac77fSApple OSS Distributions if (!vector->interruptDisabledSoft) { 821c1dac77fSApple OSS Distributions // Call the handler if it exists. 822c1dac77fSApple OSS Distributions if (vector->interruptRegistered) { 823855239e5SApple OSS Distributions bool trace = (gIOKitTrace & kIOTraceInterrupts) ? true : false; 824855239e5SApple OSS Distributions 825a5e72196SApple OSS Distributions if (trace) { 82676e12aa3SApple OSS Distributions timeStampInterruptHandlerStart(vectorNumber, vector); 827a5e72196SApple OSS Distributions } 828855239e5SApple OSS Distributions 829855239e5SApple OSS Distributions // Call handler. 830855239e5SApple OSS Distributions vector->handler(vector->target, vector->refCon, vector->nub, vector->source); 831855239e5SApple OSS Distributions 832a5e72196SApple OSS Distributions if (trace) { 83376e12aa3SApple OSS Distributions timeStampInterruptHandlerEnd(vectorNumber, vector); 834c1dac77fSApple OSS Distributions } 835c1dac77fSApple OSS Distributions } 836a5e72196SApple OSS Distributions } 837c1dac77fSApple OSS Distributions 838c1dac77fSApple OSS Distributions vector->interruptActive = 0; 839c1dac77fSApple OSS Distributions } 840c1dac77fSApple OSS Distributions 841c1dac77fSApple OSS Distributions // if any of the vectors are dissabled, then dissable this controller. 842c1dac77fSApple OSS Distributions IOSimpleLockLock(controllerLock); 843c1dac77fSApple OSS Distributions if (vectorsEnabled != vectorsRegistered) { 844c1dac77fSApple OSS Distributions nub->disableInterrupt(0); 845c1dac77fSApple OSS Distributions controllerDisabled = 1; 846c1dac77fSApple OSS Distributions } 847c1dac77fSApple OSS Distributions IOSimpleLockUnlock(controllerLock); 848c1dac77fSApple OSS Distributions 849c1dac77fSApple OSS Distributions return kIOReturnSuccess; 850c1dac77fSApple OSS Distributions } 851