- IOInterruptSource *interruptSources;
- long vectorNumber;
- IOInterruptVector *vector;
- long wasDisabledSoft;
- IOReturn error;
- OSData *vectorData;
- IOService *originalNub;
- int originalSource;
- IOOptionBits options;
- bool canBeShared, shouldBeShared, wasAlreadyRegisterd;
-
- interruptSources = nub->_interruptSources;
- vectorData = interruptSources[source].vectorData;
- vectorNumber = *(long *)vectorData->getBytesNoCopy();
- vector = &vectors[vectorNumber];
-
- // Get the lock for this vector.
- IOTakeLock(vector->interruptLock);
-
- // Check if the interrupt source can/should be shared.
- canBeShared = vectorCanBeShared(vectorNumber, vector);
- IODTGetInterruptOptions(nub, source, &options);
- 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);
- return kIOReturnNoResources;
- }
-
- // If this vector is already in use, and can be shared (implied),
- // or it is not registered and should be shared,
- // register as a shared interrupt.
- if (wasAlreadyRegisterd || shouldBeShared) {
- // If this vector is not already shared, break it out.
- if (vector->sharedController == 0) {
- // Make the IOShareInterruptController instance
- vector->sharedController = new IOSharedInterruptController;
- if (vector->sharedController == 0) {
- IOUnlock(vector->interruptLock);
- return kIOReturnNoMemory;
- }
-
- if (wasAlreadyRegisterd) {
- // Save the nub and source for the original consumer.
- originalNub = vector->nub;
- originalSource = vector->source;
-
- // Physically disable the interrupt, but mark it as being enabled in the hardware.
- // The interruptDisabledSoft now indicates the driver's request for enablement.
- disableVectorHard(vectorNumber, vector);
- vector->interruptDisabledHard = 0;
- }
-
- // Initialize the new shared interrupt controller.
- error = vector->sharedController->initInterruptController(this, vectorData);
- // If the IOSharedInterruptController could not be initalized,
- // if needed, put the original consumer's interrupt back to normal and
- // get rid of whats left of the shared controller.
- if (error != kIOReturnSuccess) {
- if (wasAlreadyRegisterd) enableInterrupt(originalNub, originalSource);
- vector->sharedController->release();
- vector->sharedController = 0;
- IOUnlock(vector->interruptLock);
- return error;
- }
-
- // If there was an original consumer try to register it on the shared controller.
- if (wasAlreadyRegisterd) {
- error = vector->sharedController->registerInterrupt(originalNub,
- originalSource,
- vector->target,
- vector->handler,
- vector->refCon);
- // If the original consumer could not be moved to the shared controller,
- // put the original consumor's interrupt back to normal and
- // get rid of whats left of the shared controller.
- if (error != kIOReturnSuccess) {
- // Save the driver's interrupt enablement state.
- wasDisabledSoft = vector->interruptDisabledSoft;
-
- // Make the interrupt really hard disabled.
- vector->interruptDisabledSoft = 1;
- vector->interruptDisabledHard = 1;
-
- // Enable the original consumer's interrupt if needed.
- if (!wasDisabledSoft) originalNub->enableInterrupt(originalSource);
- enableInterrupt(originalNub, originalSource);
-
- vector->sharedController->release();
- vector->sharedController = 0;
- IOUnlock(vector->interruptLock);
- return error;
+ IOInterruptSource *interruptSources;
+ IOInterruptVectorNumber vectorNumber;
+ IOInterruptVector *vector;
+ int wasDisabledSoft;
+ IOReturn error;
+ OSData *vectorData;
+ 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 = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
+ vector = &vectors[vectorNumber];
+
+ // Get the lock for this vector.
+ 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) {
+ IOLockUnlock(vector->interruptLock);
+ return kIOReturnNoResources;
+ }
+
+ // If this vector is already in use, and can be shared (implied),
+ // or it is not registered and should be shared,
+ // register as a shared interrupt.
+ if (wasAlreadyRegisterd || shouldBeShared) {
+ // If this vector is not already shared, break it out.
+ if (vector->sharedController == 0) {
+ // Make the IOShareInterruptController instance
+ vector->sharedController = new IOSharedInterruptController;
+ if (vector->sharedController == 0) {
+ IOLockUnlock(vector->interruptLock);
+ return kIOReturnNoMemory;
+ }
+
+ if (wasAlreadyRegisterd) {
+ // Save the nub and source for the original consumer.
+ originalNub = vector->nub;
+ originalSource = vector->source;
+
+ // Physically disable the interrupt, but mark it as being enabled in the hardware.
+ // The interruptDisabledSoft now indicates the driver's request for enablement.
+ disableVectorHard(vectorNumber, vector);
+ vector->interruptDisabledHard = 0;
+ }
+
+ // Initialize the new shared interrupt controller.
+ error = vector->sharedController->initInterruptController(this, vectorData);
+ // If the IOSharedInterruptController could not be initalized,
+ // if needed, put the original consumer's interrupt back to normal and
+ // get rid of whats left of the shared controller.
+ if (error != kIOReturnSuccess) {
+ if (wasAlreadyRegisterd) {
+ enableInterrupt(originalNub, originalSource);
+ }
+ vector->sharedController->release();
+ vector->sharedController = 0;
+ IOLockUnlock(vector->interruptLock);
+ return error;
+ }
+
+ // If there was an original consumer try to register it on the shared controller.
+ if (wasAlreadyRegisterd) {
+ error = vector->sharedController->registerInterrupt(originalNub,
+ originalSource,
+ vector->target,
+ vector->handler,
+ vector->refCon);
+ // If the original consumer could not be moved to the shared controller,
+ // put the original consumor's interrupt back to normal and
+ // get rid of whats left of the shared controller.
+ if (error != kIOReturnSuccess) {
+ // Save the driver's interrupt enablement state.
+ wasDisabledSoft = vector->interruptDisabledSoft;
+
+ // Make the interrupt really hard disabled.
+ vector->interruptDisabledSoft = 1;
+ vector->interruptDisabledHard = 1;
+
+ // Enable the original consumer's interrupt if needed.
+ if (!wasDisabledSoft) {
+ originalNub->enableInterrupt(originalSource);
+ }
+ enableInterrupt(originalNub, originalSource);
+
+ vector->sharedController->release();
+ vector->sharedController = 0;
+ IOLockUnlock(vector->interruptLock);
+ return error;
+ }
+ }
+
+ // Fill in vector with the shared controller's info.
+ vector->handler = (IOInterruptHandler)vector->sharedController->getInterruptHandlerAddress();
+ vector->nub = vector->sharedController;
+ vector->source = 0;
+ vector->target = vector->sharedController;
+ vector->refCon = 0;
+
+ // If the interrupt was already registered,
+ // save the driver's interrupt enablement state.
+ if (wasAlreadyRegisterd) {
+ wasDisabledSoft = vector->interruptDisabledSoft;
+ } else {
+ wasDisabledSoft = true;
+ }
+
+ // Do any specific initalization for this vector if it has not yet been used.
+ if (!wasAlreadyRegisterd) {
+ initVector(vectorNumber, vector);
+ }
+
+ // Make the interrupt really hard disabled.
+ vector->interruptDisabledSoft = 1;
+ vector->interruptDisabledHard = 1;
+ 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);
+ IOLockUnlock(vector->interruptLock);
+ return error;