2 * Copyright (c) 2007-2012 Apple Inc. All rights reserved.
3 * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.
5 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. The rights granted to you under the License
11 * may not be used to create, or enable the creation or redistribution of,
12 * unlawful or unlicensed copies of an Apple operating system, or to
13 * circumvent, violate, or enable the circumvention or violation of, any
14 * terms of an Apple operating system software license agreement.
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this file.
19 * The Original Code and all software distributed under the License are
20 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
21 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
22 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
24 * Please see the License for the specific language governing rights and
25 * limitations under the License.
27 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 #include <IOKit/IOLib.h>
31 #include <IOKit/IOService.h>
32 #include <IOKit/IOPlatformExpert.h>
33 #include <IOKit/IODeviceTreeSupport.h>
34 #include <IOKit/IOInterrupts.h>
35 #include <IOKit/IOInterruptController.h>
36 #include <IOKit/IOKitDebug.h>
37 #include <IOKit/IOTimeStamp.h>
40 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
42 #define super IOService
44 OSDefineMetaClassAndAbstractStructors(IOInterruptController
, IOService
);
46 OSMetaClassDefineReservedUsedX86(IOInterruptController
, 0);
47 OSMetaClassDefineReservedUsedX86(IOInterruptController
, 1);
48 OSMetaClassDefineReservedUsedX86(IOInterruptController
, 2);
49 OSMetaClassDefineReservedUnused(IOInterruptController
, 3);
50 OSMetaClassDefineReservedUnused(IOInterruptController
, 4);
51 OSMetaClassDefineReservedUnused(IOInterruptController
, 5);
53 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
56 IOInterruptController::registerInterrupt(IOService
*nub
, int source
,
58 IOInterruptHandler handler
,
61 IOInterruptSource
*interruptSources
;
62 IOInterruptVectorNumber vectorNumber
;
63 IOInterruptVector
*vector
;
68 bool canBeShared
, shouldBeShared
, wasAlreadyRegisterd
;
70 IOService
*originalNub
= NULL
;// Protected by wasAlreadyRegisterd
71 int originalSource
= 0;// Protected by wasAlreadyRegisterd
74 interruptSources
= nub
->_interruptSources
;
75 vectorData
= interruptSources
[source
].vectorData
;
76 vectorNumber
= *(IOInterruptVectorNumber
*)vectorData
->getBytesNoCopy();
77 vector
= &vectors
[vectorNumber
];
79 // Get the lock for this vector.
80 IOLockLock(vector
->interruptLock
);
82 // Check if the interrupt source can/should be shared.
83 canBeShared
= vectorCanBeShared(vectorNumber
, vector
);
84 IODTGetInterruptOptions(nub
, source
, &options
);
85 #if defined(__i386__) || defined(__x86_64__)
87 if (OSDynamicCast(IOPlatformDevice
, getProvider()) &&
88 (getInterruptType(nub
, source
, &interruptType
) == kIOReturnSuccess
) &&
89 (kIOInterruptTypeLevel
& interruptType
)) {
90 options
|= kIODTInterruptShared
;
93 shouldBeShared
= canBeShared
&& (options
& kIODTInterruptShared
);
94 wasAlreadyRegisterd
= vector
->interruptRegistered
;
96 // If the vector is registered and can not be shared return error.
97 if (wasAlreadyRegisterd
&& !canBeShared
) {
98 IOLockUnlock(vector
->interruptLock
);
99 return kIOReturnNoResources
;
102 // If this vector is already in use, and can be shared (implied),
103 // or it is not registered and should be shared,
104 // register as a shared interrupt.
105 if (wasAlreadyRegisterd
|| shouldBeShared
) {
106 // If this vector is not already shared, break it out.
107 if (vector
->sharedController
== NULL
) {
108 // Make the IOShareInterruptController instance
109 vector
->sharedController
= new IOSharedInterruptController
;
110 if (vector
->sharedController
== NULL
) {
111 IOLockUnlock(vector
->interruptLock
);
112 return kIOReturnNoMemory
;
115 if (wasAlreadyRegisterd
) {
116 // Save the nub and source for the original consumer.
117 originalNub
= vector
->nub
;
118 originalSource
= vector
->source
;
120 // Physically disable the interrupt, but mark it as being enabled in the hardware.
121 // The interruptDisabledSoft now indicates the driver's request for enablement.
122 disableVectorHard(vectorNumber
, vector
);
123 vector
->interruptDisabledHard
= 0;
126 // Initialize the new shared interrupt controller.
127 error
= vector
->sharedController
->initInterruptController(this, vectorData
);
128 // If the IOSharedInterruptController could not be initalized,
129 // if needed, put the original consumer's interrupt back to normal and
130 // get rid of whats left of the shared controller.
131 if (error
!= kIOReturnSuccess
) {
132 if (wasAlreadyRegisterd
) {
133 enableInterrupt(originalNub
, originalSource
);
135 vector
->sharedController
->release();
136 vector
->sharedController
= NULL
;
137 IOLockUnlock(vector
->interruptLock
);
141 // If there was an original consumer try to register it on the shared controller.
142 if (wasAlreadyRegisterd
) {
143 error
= vector
->sharedController
->registerInterrupt(originalNub
,
148 // If the original consumer could not be moved to the shared controller,
149 // put the original consumor's interrupt back to normal and
150 // get rid of whats left of the shared controller.
151 if (error
!= kIOReturnSuccess
) {
152 // Save the driver's interrupt enablement state.
153 wasDisabledSoft
= vector
->interruptDisabledSoft
;
155 // Make the interrupt really hard disabled.
156 vector
->interruptDisabledSoft
= 1;
157 vector
->interruptDisabledHard
= 1;
159 // Enable the original consumer's interrupt if needed.
160 if (!wasDisabledSoft
) {
161 originalNub
->enableInterrupt(originalSource
);
163 enableInterrupt(originalNub
, originalSource
);
165 vector
->sharedController
->release();
166 vector
->sharedController
= NULL
;
167 IOLockUnlock(vector
->interruptLock
);
172 // Fill in vector with the shared controller's info.
173 vector
->handler
= (IOInterruptHandler
)vector
->sharedController
->getInterruptHandlerAddress();
174 vector
->nub
= vector
->sharedController
;
176 vector
->target
= vector
->sharedController
;
177 vector
->refCon
= NULL
;
179 // If the interrupt was already registered,
180 // save the driver's interrupt enablement state.
181 if (wasAlreadyRegisterd
) {
182 wasDisabledSoft
= vector
->interruptDisabledSoft
;
184 wasDisabledSoft
= true;
187 // Do any specific initalization for this vector if it has not yet been used.
188 if (!wasAlreadyRegisterd
) {
189 initVector(vectorNumber
, vector
);
192 // Make the interrupt really hard disabled.
193 vector
->interruptDisabledSoft
= 1;
194 vector
->interruptDisabledHard
= 1;
195 vector
->interruptRegistered
= 1;
197 // Enable the original consumer's interrupt if needed.
198 // originalNub is protected by wasAlreadyRegisterd here (see line 184).
199 if (!wasDisabledSoft
) {
200 originalNub
->enableInterrupt(originalSource
);
204 error
= vector
->sharedController
->registerInterrupt(nub
, source
, target
,
206 IOLockUnlock(vector
->interruptLock
);
210 // Fill in vector with the client's info.
211 vector
->handler
= handler
;
213 vector
->source
= source
;
214 vector
->target
= target
;
215 vector
->refCon
= refCon
;
217 // Do any specific initalization for this vector.
218 initVector(vectorNumber
, vector
);
220 // Get the vector ready. It starts hard disabled.
221 vector
->interruptDisabledHard
= 1;
222 vector
->interruptDisabledSoft
= 1;
223 vector
->interruptRegistered
= 1;
225 IOLockUnlock(vector
->interruptLock
);
226 return kIOReturnSuccess
;
230 IOInterruptController::unregisterInterrupt(IOService
*nub
, int source
)
232 IOInterruptSource
*interruptSources
;
233 IOInterruptVectorNumber vectorNumber
;
234 IOInterruptVector
*vector
;
237 interruptSources
= nub
->_interruptSources
;
238 vectorData
= interruptSources
[source
].vectorData
;
239 vectorNumber
= *(IOInterruptVectorNumber
*)vectorData
->getBytesNoCopy();
240 vector
= &vectors
[vectorNumber
];
242 // Get the lock for this vector.
243 IOLockLock(vector
->interruptLock
);
245 // Return success if it is not already registered
246 if (!vector
->interruptRegistered
) {
247 IOLockUnlock(vector
->interruptLock
);
248 return kIOReturnSuccess
;
251 // Soft disable the source.
252 disableInterrupt(nub
, source
);
254 // Turn the source off at hardware.
255 disableVectorHard(vectorNumber
, vector
);
257 // Clear all the storage for the vector except for interruptLock.
258 vector
->interruptActive
= 0;
259 vector
->interruptDisabledSoft
= 0;
260 vector
->interruptDisabledHard
= 0;
261 vector
->interruptRegistered
= 0;
264 vector
->handler
= NULL
;
265 vector
->target
= NULL
;
266 vector
->refCon
= NULL
;
268 IOLockUnlock(vector
->interruptLock
);
269 return kIOReturnSuccess
;
273 IOInterruptController::getInterruptType(IOService
*nub
, int source
,
276 IOInterruptSource
*interruptSources
;
277 IOInterruptVectorNumber vectorNumber
;
278 IOInterruptVector
*vector
;
281 if (interruptType
== NULL
) {
282 return kIOReturnBadArgument
;
285 interruptSources
= nub
->_interruptSources
;
286 vectorData
= interruptSources
[source
].vectorData
;
287 vectorNumber
= *(IOInterruptVectorNumber
*)vectorData
->getBytesNoCopy();
288 vector
= &vectors
[vectorNumber
];
290 *interruptType
= getVectorType(vectorNumber
, vector
);
292 return kIOReturnSuccess
;
296 IOInterruptController::enableInterrupt(IOService
*nub
, int source
)
298 IOInterruptSource
*interruptSources
;
299 IOInterruptVectorNumber vectorNumber
;
300 IOInterruptVector
*vector
;
303 interruptSources
= nub
->_interruptSources
;
304 vectorData
= interruptSources
[source
].vectorData
;
305 vectorNumber
= *(IOInterruptVectorNumber
*)vectorData
->getBytesNoCopy();
306 vector
= &vectors
[vectorNumber
];
308 if (vector
->interruptDisabledSoft
) {
309 vector
->interruptDisabledSoft
= 0;
310 #if !defined(__i386__) && !defined(__x86_64__)
314 if (!getPlatform()->atInterruptLevel()) {
315 while (vector
->interruptActive
) {
318 if (vector
->interruptDisabledHard
) {
319 vector
->interruptDisabledHard
= 0;
321 // A DSB ISH on ARM is needed to make sure the vector data are
322 // properly initialized before the MMIO enabling the interrupts
323 // in hardware. OSMemoryBarrier(), which maps to DMB, is not
324 // sufficient here as the CPUs are not consumers of the device
325 // write. Hence, the DMB does not guarantee the CPUs won't see an
326 // interrupt before it initalizes the vector data properly.
329 enableVector(vectorNumber
, vector
);
333 return kIOReturnSuccess
;
337 IOInterruptController::disableInterrupt(IOService
*nub
, int source
)
339 IOInterruptSource
*interruptSources
;
340 IOInterruptVectorNumber vectorNumber
;
341 IOInterruptVector
*vector
;
344 interruptSources
= nub
->_interruptSources
;
345 vectorData
= interruptSources
[source
].vectorData
;
346 vectorNumber
= *(IOInterruptVectorNumber
*)vectorData
->getBytesNoCopy();
347 vector
= &vectors
[vectorNumber
];
349 vector
->interruptDisabledSoft
= 1;
350 #if !defined(__i386__) && !defined(__x86_64__)
354 if (!getPlatform()->atInterruptLevel()) {
355 while (vector
->interruptActive
) {
359 return kIOReturnSuccess
;
363 IOInterruptController::causeInterrupt(IOService
*nub
, int source
)
365 IOInterruptSource
*interruptSources
;
366 IOInterruptVectorNumber vectorNumber
;
367 IOInterruptVector
*vector
;
370 interruptSources
= nub
->_interruptSources
;
371 vectorData
= interruptSources
[source
].vectorData
;
372 vectorNumber
= *(IOInterruptVectorNumber
*)vectorData
->getBytesNoCopy();
373 vector
= &vectors
[vectorNumber
];
375 causeVector(vectorNumber
, vector
);
377 return kIOReturnSuccess
;
381 IOInterruptController::getInterruptHandlerAddress(void)
387 IOInterruptController::handleInterrupt(void *refCon
, IOService
*nub
,
390 return kIOReturnInvalid
;
394 // Methods to be overridden for simplifed interrupt controller subclasses.
397 IOInterruptController::vectorCanBeShared(IOInterruptVectorNumber
/*vectorNumber*/,
398 IOInterruptVector */
*vector*/
)
404 IOInterruptController::initVector(IOInterruptVectorNumber
/*vectorNumber*/,
405 IOInterruptVector */
*vector*/
)
410 IOInterruptController::getVectorType(IOInterruptVectorNumber
/*vectorNumber*/,
411 IOInterruptVector */
*vector*/
)
413 return kIOInterruptTypeEdge
;
417 IOInterruptController::disableVectorHard(IOInterruptVectorNumber
/*vectorNumber*/,
418 IOInterruptVector */
*vector*/
)
423 IOInterruptController::enableVector(IOInterruptVectorNumber
/*vectorNumber*/,
424 IOInterruptVector */
*vector*/
)
429 IOInterruptController::causeVector(IOInterruptVectorNumber
/*vectorNumber*/,
430 IOInterruptVector */
*vector*/
)
435 IOInterruptController::setCPUInterruptProperties(IOService */
*service*/
)
440 IOInterruptController::sendIPI(unsigned int /*cpu_id*/, bool /*deferred*/)
445 IOInterruptController::cancelDeferredIPI(unsigned int /*cpu_id*/)
450 IOInterruptController::timeStampSpuriousInterrupt(void)
452 uint64_t providerID
= 0;
453 IOService
* provider
= getProvider();
456 providerID
= provider
->getRegistryEntryID();
459 IOTimeStampConstant(IODBG_INTC(IOINTC_SPURIOUS
), providerID
);
463 IOInterruptController::timeStampInterruptHandlerInternal(bool isStart
, IOInterruptVectorNumber vectorNumber
, IOInterruptVector
*vector
)
465 uint64_t providerID
= 0;
466 vm_offset_t unslidHandler
= 0;
467 vm_offset_t unslidTarget
= 0;
469 IOService
* provider
= getProvider();
472 providerID
= provider
->getRegistryEntryID();
476 unslidHandler
= VM_KERNEL_UNSLIDE((vm_offset_t
)vector
->handler
);
477 unslidTarget
= VM_KERNEL_UNSLIDE_OR_PERM((vm_offset_t
)vector
->target
);
482 #if INTERRUPT_MASKED_DEBUG
483 ml_irq_debug_start((uintptr_t)vector
->handler
, (uintptr_t)vector
);
485 IOTimeStampStartConstant(IODBG_INTC(IOINTC_HANDLER
), (uintptr_t)vectorNumber
, (uintptr_t)unslidHandler
,
486 (uintptr_t)unslidTarget
, (uintptr_t)providerID
);
488 IOTimeStampEndConstant(IODBG_INTC(IOINTC_HANDLER
), (uintptr_t)vectorNumber
, (uintptr_t)unslidHandler
,
489 (uintptr_t)unslidTarget
, (uintptr_t)providerID
);
490 #if INTERRUPT_MASKED_DEBUG
497 IOInterruptController::timeStampInterruptHandlerStart(IOInterruptVectorNumber vectorNumber
, IOInterruptVector
*vector
)
499 timeStampInterruptHandlerInternal(true, vectorNumber
, vector
);
503 IOInterruptController::timeStampInterruptHandlerEnd(IOInterruptVectorNumber vectorNumber
, IOInterruptVector
*vector
)
505 timeStampInterruptHandlerInternal(false, vectorNumber
, vector
);
508 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
511 #define super IOInterruptController
513 OSDefineMetaClassAndStructors(IOSharedInterruptController
, IOInterruptController
);
515 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 0);
516 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 1);
517 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 2);
518 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 3);
520 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
522 #define kIOSharedInterruptControllerDefaultVectors (128)
525 IOSharedInterruptController::initInterruptController(IOInterruptController
*parentController
, OSData
*parentSource
)
527 int cnt
, interruptType
;
530 if (!super::init()) {
531 return kIOReturnNoResources
;
534 // Set provider to this so enable/disable nub stuff works.
537 // Allocate the IOInterruptSource so this can act like a nub.
538 _interruptSources
= (IOInterruptSource
*)IOMalloc(sizeof(IOInterruptSource
));
539 if (_interruptSources
== NULL
) {
540 return kIOReturnNoMemory
;
542 _numInterruptSources
= 1;
544 // Set up the IOInterruptSource to point at this.
545 parentController
->retain();
546 parentSource
->retain();
547 _interruptSources
[0].interruptController
= parentController
;
548 _interruptSources
[0].vectorData
= parentSource
;
550 sourceIsLevel
= false;
551 error
= provider
->getInterruptType(0, &interruptType
);
552 if (error
== kIOReturnSuccess
) {
553 if (interruptType
& kIOInterruptTypeLevel
) {
554 sourceIsLevel
= true;
558 // Allocate the memory for the vectors
559 numVectors
= kIOSharedInterruptControllerDefaultVectors
; // For now a constant number.
560 vectors
= (IOInterruptVector
*)IOMalloc(numVectors
* sizeof(IOInterruptVector
));
561 if (vectors
== NULL
) {
562 IOFree(_interruptSources
, sizeof(IOInterruptSource
));
563 return kIOReturnNoMemory
;
565 bzero(vectors
, numVectors
* sizeof(IOInterruptVector
));
567 // Allocate the lock for the controller.
568 controllerLock
= IOSimpleLockAlloc();
569 if (controllerLock
== NULL
) {
570 return kIOReturnNoResources
;
573 // Allocate locks for the vectors.
574 for (cnt
= 0; cnt
< numVectors
; cnt
++) {
575 vectors
[cnt
].interruptLock
= IOLockAlloc();
576 if (vectors
[cnt
].interruptLock
== NULL
) {
577 for (cnt
= 0; cnt
< numVectors
; cnt
++) {
578 if (vectors
[cnt
].interruptLock
!= NULL
) {
579 IOLockFree(vectors
[cnt
].interruptLock
);
582 return kIOReturnNoResources
;
586 numVectors
= 0; // reset the high water mark for used vectors
587 vectorsRegistered
= 0;
589 controllerDisabled
= 1;
591 return kIOReturnSuccess
;
595 IOSharedInterruptController::registerInterrupt(IOService
*nub
,
598 IOInterruptHandler handler
,
601 IOInterruptSource
*interruptSources
;
602 IOInterruptVectorNumber vectorNumber
;
603 IOInterruptVector
*vector
= NULL
;
605 IOInterruptState interruptState
;
607 interruptSources
= nub
->_interruptSources
;
609 // Find a free vector.
610 vectorNumber
= kIOSharedInterruptControllerDefaultVectors
;
611 while (vectorsRegistered
!= kIOSharedInterruptControllerDefaultVectors
) {
612 for (vectorNumber
= 0; vectorNumber
< kIOSharedInterruptControllerDefaultVectors
; vectorNumber
++) {
613 vector
= &vectors
[vectorNumber
];
615 // Get the lock for this vector.
616 IOLockLock(vector
->interruptLock
);
618 // Is it unregistered?
619 if (!vector
->interruptRegistered
) {
623 // Move along to the next one.
624 IOLockUnlock(vector
->interruptLock
);
627 if (vectorNumber
!= kIOSharedInterruptControllerDefaultVectors
) {
632 // Could not find a free one, so give up.
633 if (vectorNumber
== kIOSharedInterruptControllerDefaultVectors
) {
634 return kIOReturnNoResources
;
637 // Create the vectorData for the IOInterruptSource.
638 vectorData
= OSData::withBytes(&vectorNumber
, sizeof(vectorNumber
));
639 if (vectorData
== NULL
) {
640 IOLockUnlock(vector
->interruptLock
);
641 return kIOReturnNoMemory
;
644 // Fill in the IOInterruptSource with the controller's info.
645 interruptSources
[source
].interruptController
= this;
646 interruptSources
[source
].vectorData
= vectorData
;
648 // Fill in vector with the client's info.
649 vector
->handler
= handler
;
651 vector
->source
= source
;
652 vector
->target
= target
;
653 vector
->refCon
= refCon
;
655 // Get the vector ready. It starts off soft disabled.
656 vector
->interruptDisabledSoft
= 1;
657 vector
->interruptRegistered
= 1;
659 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
660 // Move the high water mark if needed
661 if (++vectorsRegistered
> numVectors
) {
662 numVectors
= vectorsRegistered
;
664 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
666 IOLockUnlock(vector
->interruptLock
);
667 return kIOReturnSuccess
;
671 IOSharedInterruptController::unregisterInterrupt(IOService
*nub
,
674 IOInterruptVectorNumber vectorNumber
;
675 IOInterruptVector
*vector
;
676 IOInterruptState interruptState
;
678 for (vectorNumber
= 0; vectorNumber
< kIOSharedInterruptControllerDefaultVectors
; vectorNumber
++) {
679 vector
= &vectors
[vectorNumber
];
681 // Get the lock for this vector.
682 IOLockLock(vector
->interruptLock
);
684 // Return success if it is not already registered
685 if (!vector
->interruptRegistered
686 || (vector
->nub
!= nub
) || (vector
->source
!= source
)) {
687 IOLockUnlock(vector
->interruptLock
);
691 // Soft disable the source and the controller too.
692 disableInterrupt(nub
, source
);
694 // Clear all the storage for the vector except for interruptLock.
695 vector
->interruptActive
= 0;
696 vector
->interruptDisabledSoft
= 0;
697 vector
->interruptDisabledHard
= 0;
698 vector
->interruptRegistered
= 0;
701 vector
->handler
= NULL
;
702 vector
->target
= NULL
;
703 vector
->refCon
= NULL
;
705 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
707 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
709 // Move along to the next one.
710 IOLockUnlock(vector
->interruptLock
);
713 // Re-enable the controller if all vectors are enabled.
714 if (vectorsEnabled
== vectorsRegistered
) {
715 controllerDisabled
= 0;
716 provider
->enableInterrupt(0);
719 return kIOReturnSuccess
;
723 IOSharedInterruptController::getInterruptType(IOService */
*nub*/
,
727 return provider
->getInterruptType(0, interruptType
);
731 IOSharedInterruptController::enableInterrupt(IOService
*nub
,
734 IOInterruptSource
*interruptSources
;
735 IOInterruptVectorNumber vectorNumber
;
736 IOInterruptVector
*vector
;
738 IOInterruptState interruptState
;
740 interruptSources
= nub
->_interruptSources
;
741 vectorData
= interruptSources
[source
].vectorData
;
742 vectorNumber
= *(IOInterruptVectorNumber
*)vectorData
->getBytesNoCopy();
743 vector
= &vectors
[vectorNumber
];
745 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
746 if (!vector
->interruptDisabledSoft
) {
747 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
748 return kIOReturnSuccess
;
751 vector
->interruptDisabledSoft
= 0;
753 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
755 if (controllerDisabled
&& (vectorsEnabled
== vectorsRegistered
)) {
756 controllerDisabled
= 0;
757 provider
->enableInterrupt(0);
760 return kIOReturnSuccess
;
764 IOSharedInterruptController::disableInterrupt(IOService
*nub
,
767 IOInterruptSource
*interruptSources
;
768 IOInterruptVectorNumber vectorNumber
;
769 IOInterruptVector
*vector
;
771 IOInterruptState interruptState
;
773 interruptSources
= nub
->_interruptSources
;
774 vectorData
= interruptSources
[source
].vectorData
;
775 vectorNumber
= *(IOInterruptVectorNumber
*)vectorData
->getBytesNoCopy();
776 vector
= &vectors
[vectorNumber
];
778 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
779 if (!vector
->interruptDisabledSoft
) {
780 vector
->interruptDisabledSoft
= 1;
781 #if !defined(__i386__) && !defined(__x86_64__)
787 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
789 if (!getPlatform()->atInterruptLevel()) {
790 while (vector
->interruptActive
) {
794 return kIOReturnSuccess
;
798 IOSharedInterruptController::getInterruptHandlerAddress(void)
800 return OSMemberFunctionCast(IOInterruptAction
,
801 this, &IOSharedInterruptController::handleInterrupt
);
805 IOSharedInterruptController::handleInterrupt(void * /*refCon*/,
809 IOInterruptVectorNumber vectorNumber
;
810 IOInterruptVector
*vector
;
812 for (vectorNumber
= 0; vectorNumber
< numVectors
; vectorNumber
++) {
813 vector
= &vectors
[vectorNumber
];
815 vector
->interruptActive
= 1;
816 #if !defined(__i386__) && !defined(__x86_64__)
820 if (!vector
->interruptDisabledSoft
) {
821 // Call the handler if it exists.
822 if (vector
->interruptRegistered
) {
823 bool trace
= (gIOKitTrace
& kIOTraceInterrupts
) ? true : false;
826 timeStampInterruptHandlerStart(vectorNumber
, vector
);
830 vector
->handler(vector
->target
, vector
->refCon
, vector
->nub
, vector
->source
);
833 timeStampInterruptHandlerEnd(vectorNumber
, vector
);
838 vector
->interruptActive
= 0;
841 // if any of the vectors are dissabled, then dissable this controller.
842 IOSimpleLockLock(controllerLock
);
843 if (vectorsEnabled
!= vectorsRegistered
) {
844 nub
->disableInterrupt(0);
845 controllerDisabled
= 1;
847 IOSimpleLockUnlock(controllerLock
);
849 return kIOReturnSuccess
;