- }
-
- // 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.
- if (!wasDisabledSoft) originalNub->enableInterrupt(originalSource);
- }
-
- error = vector->sharedController->registerInterrupt(nub, source, target,
- handler, refCon);
- IOUnlock(vector->interruptLock);
- return error;
- }
-
- // Fill in vector with the client's info.
- vector->handler = handler;
- vector->nub = nub;
- vector->source = source;
- vector->target = target;
- vector->refCon = refCon;
-
- // Do any specific initalization for this vector.
- initVector(vectorNumber, vector);
-
- // Get the vector ready. It starts hard disabled.
- vector->interruptDisabledHard = 1;
- vector->interruptDisabledSoft = 1;
- vector->interruptRegistered = 1;
-
- IOUnlock(vector->interruptLock);
- return kIOReturnSuccess;
+#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 == NULL) {
+ // Make the IOShareInterruptController instance
+ vector->sharedController = new IOSharedInterruptController;
+ if (vector->sharedController == NULL) {
+ 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 = NULL;
+ 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 = NULL;
+ 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 = NULL;
+
+ // 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;
+ }
+
+ // Fill in vector with the client's info.
+ vector->handler = handler;
+ vector->nub = nub;
+ vector->source = source;
+ vector->target = target;
+ vector->refCon = refCon;
+
+ // Do any specific initalization for this vector.
+ initVector(vectorNumber, vector);
+
+ // Get the vector ready. It starts hard disabled.
+ vector->interruptDisabledHard = 1;
+ vector->interruptDisabledSoft = 1;
+ vector->interruptRegistered = 1;
+
+ IOLockUnlock(vector->interruptLock);
+ return kIOReturnSuccess;