2 * Copyright (c) 1998-2010 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <IOKit/IOLib.h>
30 #include <IOKit/IOService.h>
31 #include <IOKit/IOPlatformExpert.h>
32 #include <IOKit/IODeviceTreeSupport.h>
33 #include <IOKit/IOInterrupts.h>
34 #include <IOKit/IOInterruptController.h>
35 #include <IOKit/IOKitDebug.h>
36 #include <IOKit/IOTimeStamp.h>
39 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
41 #define super IOService
43 OSDefineMetaClassAndAbstractStructors(IOInterruptController
, IOService
);
45 OSMetaClassDefineReservedUnused(IOInterruptController
, 0);
46 OSMetaClassDefineReservedUnused(IOInterruptController
, 1);
47 OSMetaClassDefineReservedUnused(IOInterruptController
, 2);
48 OSMetaClassDefineReservedUnused(IOInterruptController
, 3);
49 OSMetaClassDefineReservedUnused(IOInterruptController
, 4);
50 OSMetaClassDefineReservedUnused(IOInterruptController
, 5);
52 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
54 IOReturn
IOInterruptController::registerInterrupt(IOService
*nub
, int source
,
56 IOInterruptHandler handler
,
59 IOInterruptSource
*interruptSources
;
60 IOInterruptVectorNumber vectorNumber
;
61 IOInterruptVector
*vector
;
66 bool canBeShared
, shouldBeShared
, wasAlreadyRegisterd
;
68 IOService
*originalNub
= NULL
; // Protected by wasAlreadyRegisterd
69 int originalSource
= 0; // Protected by wasAlreadyRegisterd
72 interruptSources
= nub
->_interruptSources
;
73 vectorData
= interruptSources
[source
].vectorData
;
74 vectorNumber
= *(IOInterruptVectorNumber
*)vectorData
->getBytesNoCopy();
75 vector
= &vectors
[vectorNumber
];
77 // Get the lock for this vector.
78 IOLockLock(vector
->interruptLock
);
80 // Check if the interrupt source can/should be shared.
81 canBeShared
= vectorCanBeShared(vectorNumber
, vector
);
82 IODTGetInterruptOptions(nub
, source
, &options
);
83 #if defined(__i386__) || defined(__x86_64__)
85 if (OSDynamicCast(IOPlatformDevice
, getProvider()) &&
86 (getInterruptType(nub
, source
, &interruptType
) == kIOReturnSuccess
) &&
87 (kIOInterruptTypeLevel
& interruptType
))
89 options
|= kIODTInterruptShared
;
92 shouldBeShared
= canBeShared
&& (options
& kIODTInterruptShared
);
93 wasAlreadyRegisterd
= vector
->interruptRegistered
;
95 // If the vector is registered and can not be shared return error.
96 if (wasAlreadyRegisterd
&& !canBeShared
) {
97 IOLockUnlock(vector
->interruptLock
);
98 return kIOReturnNoResources
;
101 // If this vector is already in use, and can be shared (implied),
102 // or it is not registered and should be shared,
103 // register as a shared interrupt.
104 if (wasAlreadyRegisterd
|| shouldBeShared
) {
105 // If this vector is not already shared, break it out.
106 if (vector
->sharedController
== 0) {
107 // Make the IOShareInterruptController instance
108 vector
->sharedController
= new IOSharedInterruptController
;
109 if (vector
->sharedController
== 0) {
110 IOLockUnlock(vector
->interruptLock
);
111 return kIOReturnNoMemory
;
114 if (wasAlreadyRegisterd
) {
115 // Save the nub and source for the original consumer.
116 originalNub
= vector
->nub
;
117 originalSource
= vector
->source
;
119 // Physically disable the interrupt, but mark it as being enabled in the hardware.
120 // The interruptDisabledSoft now indicates the driver's request for enablement.
121 disableVectorHard(vectorNumber
, vector
);
122 vector
->interruptDisabledHard
= 0;
125 // Initialize the new shared interrupt controller.
126 error
= vector
->sharedController
->initInterruptController(this, vectorData
);
127 // If the IOSharedInterruptController could not be initalized,
128 // if needed, put the original consumer's interrupt back to normal and
129 // get rid of whats left of the shared controller.
130 if (error
!= kIOReturnSuccess
) {
131 if (wasAlreadyRegisterd
) enableInterrupt(originalNub
, originalSource
);
132 vector
->sharedController
->release();
133 vector
->sharedController
= 0;
134 IOLockUnlock(vector
->interruptLock
);
138 // If there was an original consumer try to register it on the shared controller.
139 if (wasAlreadyRegisterd
) {
140 error
= vector
->sharedController
->registerInterrupt(originalNub
,
145 // If the original consumer could not be moved to the shared controller,
146 // put the original consumor's interrupt back to normal and
147 // get rid of whats left of the shared controller.
148 if (error
!= kIOReturnSuccess
) {
149 // Save the driver's interrupt enablement state.
150 wasDisabledSoft
= vector
->interruptDisabledSoft
;
152 // Make the interrupt really hard disabled.
153 vector
->interruptDisabledSoft
= 1;
154 vector
->interruptDisabledHard
= 1;
156 // Enable the original consumer's interrupt if needed.
157 if (!wasDisabledSoft
) originalNub
->enableInterrupt(originalSource
);
158 enableInterrupt(originalNub
, originalSource
);
160 vector
->sharedController
->release();
161 vector
->sharedController
= 0;
162 IOLockUnlock(vector
->interruptLock
);
167 // Fill in vector with the shared controller's info.
168 vector
->handler
= (IOInterruptHandler
)vector
->sharedController
->getInterruptHandlerAddress();
169 vector
->nub
= vector
->sharedController
;
171 vector
->target
= vector
->sharedController
;
174 // If the interrupt was already registered,
175 // save the driver's interrupt enablement state.
176 if (wasAlreadyRegisterd
) wasDisabledSoft
= vector
->interruptDisabledSoft
;
177 else wasDisabledSoft
= true;
179 // Do any specific initalization for this vector if it has not yet been used.
180 if (!wasAlreadyRegisterd
) initVector(vectorNumber
, vector
);
182 // Make the interrupt really hard disabled.
183 vector
->interruptDisabledSoft
= 1;
184 vector
->interruptDisabledHard
= 1;
185 vector
->interruptRegistered
= 1;
187 // Enable the original consumer's interrupt if needed.
188 // originalNub is protected by wasAlreadyRegisterd here (see line 184).
189 if (!wasDisabledSoft
) originalNub
->enableInterrupt(originalSource
);
192 error
= vector
->sharedController
->registerInterrupt(nub
, source
, target
,
194 IOLockUnlock(vector
->interruptLock
);
198 // Fill in vector with the client's info.
199 vector
->handler
= handler
;
201 vector
->source
= source
;
202 vector
->target
= target
;
203 vector
->refCon
= refCon
;
205 // Do any specific initalization for this vector.
206 initVector(vectorNumber
, vector
);
208 // Get the vector ready. It starts hard disabled.
209 vector
->interruptDisabledHard
= 1;
210 vector
->interruptDisabledSoft
= 1;
211 vector
->interruptRegistered
= 1;
213 IOLockUnlock(vector
->interruptLock
);
214 return kIOReturnSuccess
;
217 IOReturn
IOInterruptController::unregisterInterrupt(IOService
*nub
, int source
)
219 IOInterruptSource
*interruptSources
;
220 IOInterruptVectorNumber vectorNumber
;
221 IOInterruptVector
*vector
;
224 interruptSources
= nub
->_interruptSources
;
225 vectorData
= interruptSources
[source
].vectorData
;
226 vectorNumber
= *(IOInterruptVectorNumber
*)vectorData
->getBytesNoCopy();
227 vector
= &vectors
[vectorNumber
];
229 // Get the lock for this vector.
230 IOLockLock(vector
->interruptLock
);
232 // Return success if it is not already registered
233 if (!vector
->interruptRegistered
) {
234 IOLockUnlock(vector
->interruptLock
);
235 return kIOReturnSuccess
;
238 // Soft disable the source.
239 disableInterrupt(nub
, source
);
241 // Turn the source off at hardware.
242 disableVectorHard(vectorNumber
, vector
);
244 // Clear all the storage for the vector except for interruptLock.
245 vector
->interruptActive
= 0;
246 vector
->interruptDisabledSoft
= 0;
247 vector
->interruptDisabledHard
= 0;
248 vector
->interruptRegistered
= 0;
255 IOLockUnlock(vector
->interruptLock
);
256 return kIOReturnSuccess
;
259 IOReturn
IOInterruptController::getInterruptType(IOService
*nub
, int source
,
262 IOInterruptSource
*interruptSources
;
263 IOInterruptVectorNumber vectorNumber
;
264 IOInterruptVector
*vector
;
267 if (interruptType
== 0) return kIOReturnBadArgument
;
269 interruptSources
= nub
->_interruptSources
;
270 vectorData
= interruptSources
[source
].vectorData
;
271 vectorNumber
= *(IOInterruptVectorNumber
*)vectorData
->getBytesNoCopy();
272 vector
= &vectors
[vectorNumber
];
274 *interruptType
= getVectorType(vectorNumber
, vector
);
276 return kIOReturnSuccess
;
279 IOReturn
IOInterruptController::enableInterrupt(IOService
*nub
, int source
)
281 IOInterruptSource
*interruptSources
;
282 IOInterruptVectorNumber vectorNumber
;
283 IOInterruptVector
*vector
;
286 interruptSources
= nub
->_interruptSources
;
287 vectorData
= interruptSources
[source
].vectorData
;
288 vectorNumber
= *(IOInterruptVectorNumber
*)vectorData
->getBytesNoCopy();
289 vector
= &vectors
[vectorNumber
];
291 if (vector
->interruptDisabledSoft
) {
292 vector
->interruptDisabledSoft
= 0;
294 if (!getPlatform()->atInterruptLevel()) {
295 while (vector
->interruptActive
)
298 if (vector
->interruptDisabledHard
) {
299 vector
->interruptDisabledHard
= 0;
301 enableVector(vectorNumber
, vector
);
305 return kIOReturnSuccess
;
308 IOReturn
IOInterruptController::disableInterrupt(IOService
*nub
, int source
)
310 IOInterruptSource
*interruptSources
;
311 IOInterruptVectorNumber vectorNumber
;
312 IOInterruptVector
*vector
;
315 interruptSources
= nub
->_interruptSources
;
316 vectorData
= interruptSources
[source
].vectorData
;
317 vectorNumber
= *(IOInterruptVectorNumber
*)vectorData
->getBytesNoCopy();
318 vector
= &vectors
[vectorNumber
];
320 vector
->interruptDisabledSoft
= 1;
322 if (!getPlatform()->atInterruptLevel()) {
323 while (vector
->interruptActive
)
327 return kIOReturnSuccess
;
330 IOReturn
IOInterruptController::causeInterrupt(IOService
*nub
, int source
)
332 IOInterruptSource
*interruptSources
;
333 IOInterruptVectorNumber vectorNumber
;
334 IOInterruptVector
*vector
;
337 interruptSources
= nub
->_interruptSources
;
338 vectorData
= interruptSources
[source
].vectorData
;
339 vectorNumber
= *(IOInterruptVectorNumber
*)vectorData
->getBytesNoCopy();
340 vector
= &vectors
[vectorNumber
];
342 causeVector(vectorNumber
, vector
);
344 return kIOReturnSuccess
;
347 IOInterruptAction
IOInterruptController::getInterruptHandlerAddress(void)
352 IOReturn
IOInterruptController::handleInterrupt(void *refCon
, IOService
*nub
,
355 return kIOReturnInvalid
;
359 // Methods to be overridden for simplifed interrupt controller subclasses.
361 bool IOInterruptController::vectorCanBeShared(IOInterruptVectorNumber
/*vectorNumber*/,
362 IOInterruptVector */
*vector*/
)
367 void IOInterruptController::initVector(IOInterruptVectorNumber
/*vectorNumber*/,
368 IOInterruptVector */
*vector*/
)
372 int IOInterruptController::getVectorType(IOInterruptVectorNumber
/*vectorNumber*/,
373 IOInterruptVector */
*vector*/
)
375 return kIOInterruptTypeEdge
;
378 void IOInterruptController::disableVectorHard(IOInterruptVectorNumber
/*vectorNumber*/,
379 IOInterruptVector */
*vector*/
)
383 void IOInterruptController::enableVector(IOInterruptVectorNumber
/*vectorNumber*/,
384 IOInterruptVector */
*vector*/
)
388 void IOInterruptController::causeVector(IOInterruptVectorNumber
/*vectorNumber*/,
389 IOInterruptVector */
*vector*/
)
394 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
397 #define super IOInterruptController
399 OSDefineMetaClassAndStructors(IOSharedInterruptController
, IOInterruptController
);
401 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 0);
402 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 1);
403 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 2);
404 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 3);
406 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
408 #define kIOSharedInterruptControllerDefaultVectors (128)
410 IOReturn
IOSharedInterruptController::initInterruptController(IOInterruptController
*parentController
, OSData
*parentSource
)
412 int cnt
, interruptType
;
416 return kIOReturnNoResources
;
418 // Set provider to this so enable/disable nub stuff works.
421 // Allocate the IOInterruptSource so this can act like a nub.
422 _interruptSources
= (IOInterruptSource
*)IOMalloc(sizeof(IOInterruptSource
));
423 if (_interruptSources
== 0) return kIOReturnNoMemory
;
424 _numInterruptSources
= 1;
426 // Set up the IOInterruptSource to point at this.
427 parentController
->retain();
428 parentSource
->retain();
429 _interruptSources
[0].interruptController
= parentController
;
430 _interruptSources
[0].vectorData
= parentSource
;
432 sourceIsLevel
= false;
433 error
= provider
->getInterruptType(0, &interruptType
);
434 if (error
== kIOReturnSuccess
) {
435 if (interruptType
& kIOInterruptTypeLevel
)
436 sourceIsLevel
= true;
439 // Allocate the memory for the vectors
440 numVectors
= kIOSharedInterruptControllerDefaultVectors
; // For now a constant number.
441 vectors
= (IOInterruptVector
*)IOMalloc(numVectors
* sizeof(IOInterruptVector
));
442 if (vectors
== NULL
) {
443 IOFree(_interruptSources
, sizeof(IOInterruptSource
));
444 return kIOReturnNoMemory
;
446 bzero(vectors
, numVectors
* sizeof(IOInterruptVector
));
448 // Allocate the lock for the controller.
449 controllerLock
= IOSimpleLockAlloc();
450 if (controllerLock
== 0) return kIOReturnNoResources
;
452 // Allocate locks for the vectors.
453 for (cnt
= 0; cnt
< numVectors
; cnt
++) {
454 vectors
[cnt
].interruptLock
= IOLockAlloc();
455 if (vectors
[cnt
].interruptLock
== NULL
) {
456 for (cnt
= 0; cnt
< numVectors
; cnt
++) {
457 if (vectors
[cnt
].interruptLock
!= NULL
)
458 IOLockFree(vectors
[cnt
].interruptLock
);
460 return kIOReturnNoResources
;
464 numVectors
= 0; // reset the high water mark for used vectors
465 vectorsRegistered
= 0;
467 controllerDisabled
= 1;
469 return kIOReturnSuccess
;
472 IOReturn
IOSharedInterruptController::registerInterrupt(IOService
*nub
,
475 IOInterruptHandler handler
,
478 IOInterruptSource
*interruptSources
;
479 IOInterruptVectorNumber vectorNumber
;
480 IOInterruptVector
*vector
= 0;
482 IOInterruptState interruptState
;
484 interruptSources
= nub
->_interruptSources
;
486 // Find a free vector.
487 vectorNumber
= kIOSharedInterruptControllerDefaultVectors
;
488 while (vectorsRegistered
!= kIOSharedInterruptControllerDefaultVectors
) {
489 for (vectorNumber
= 0; vectorNumber
< kIOSharedInterruptControllerDefaultVectors
; vectorNumber
++) {
490 vector
= &vectors
[vectorNumber
];
492 // Get the lock for this vector.
493 IOLockLock(vector
->interruptLock
);
495 // Is it unregistered?
496 if (!vector
->interruptRegistered
) break;
498 // Move along to the next one.
499 IOLockUnlock(vector
->interruptLock
);
502 if (vectorNumber
!= kIOSharedInterruptControllerDefaultVectors
) break;
505 // Could not find a free one, so give up.
506 if (vectorNumber
== kIOSharedInterruptControllerDefaultVectors
) {
507 return kIOReturnNoResources
;
510 // Create the vectorData for the IOInterruptSource.
511 vectorData
= OSData::withBytes(&vectorNumber
, sizeof(vectorNumber
));
512 if (vectorData
== 0) {
513 return kIOReturnNoMemory
;
516 // Fill in the IOInterruptSource with the controller's info.
517 interruptSources
[source
].interruptController
= this;
518 interruptSources
[source
].vectorData
= vectorData
;
520 // Fill in vector with the client's info.
521 vector
->handler
= handler
;
523 vector
->source
= source
;
524 vector
->target
= target
;
525 vector
->refCon
= refCon
;
527 // Get the vector ready. It starts off soft disabled.
528 vector
->interruptDisabledSoft
= 1;
529 vector
->interruptRegistered
= 1;
531 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
532 // Move the high water mark if needed
533 if (++vectorsRegistered
> numVectors
) numVectors
= vectorsRegistered
;
534 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
536 IOLockUnlock(vector
->interruptLock
);
537 return kIOReturnSuccess
;
540 IOReturn
IOSharedInterruptController::unregisterInterrupt(IOService
*nub
,
543 IOInterruptVectorNumber vectorNumber
;
544 IOInterruptVector
*vector
;
545 IOInterruptState interruptState
;
547 for (vectorNumber
= 0; vectorNumber
< kIOSharedInterruptControllerDefaultVectors
; vectorNumber
++) {
548 vector
= &vectors
[vectorNumber
];
550 // Get the lock for this vector.
551 IOLockLock(vector
->interruptLock
);
553 // Return success if it is not already registered
554 if (!vector
->interruptRegistered
555 || (vector
->nub
!= nub
) || (vector
->source
!= source
)) {
556 IOLockUnlock(vector
->interruptLock
);
560 // Soft disable the source and the controller too.
561 disableInterrupt(nub
, source
);
563 // Clear all the storage for the vector except for interruptLock.
564 vector
->interruptActive
= 0;
565 vector
->interruptDisabledSoft
= 0;
566 vector
->interruptDisabledHard
= 0;
567 vector
->interruptRegistered
= 0;
574 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
576 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
578 // Move along to the next one.
579 IOLockUnlock(vector
->interruptLock
);
582 // Re-enable the controller if all vectors are enabled.
583 if (vectorsEnabled
== vectorsRegistered
) {
584 controllerDisabled
= 0;
585 provider
->enableInterrupt(0);
588 return kIOReturnSuccess
;
591 IOReturn
IOSharedInterruptController::getInterruptType(IOService */
*nub*/
,
595 return provider
->getInterruptType(0, interruptType
);
598 IOReturn
IOSharedInterruptController::enableInterrupt(IOService
*nub
,
601 IOInterruptSource
*interruptSources
;
602 IOInterruptVectorNumber vectorNumber
;
603 IOInterruptVector
*vector
;
605 IOInterruptState interruptState
;
607 interruptSources
= nub
->_interruptSources
;
608 vectorData
= interruptSources
[source
].vectorData
;
609 vectorNumber
= *(IOInterruptVectorNumber
*)vectorData
->getBytesNoCopy();
610 vector
= &vectors
[vectorNumber
];
612 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
613 if (!vector
->interruptDisabledSoft
) {
614 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
615 return kIOReturnSuccess
;
618 vector
->interruptDisabledSoft
= 0;
620 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
622 if (controllerDisabled
&& (vectorsEnabled
== vectorsRegistered
)) {
623 controllerDisabled
= 0;
624 provider
->enableInterrupt(0);
627 return kIOReturnSuccess
;
630 IOReturn
IOSharedInterruptController::disableInterrupt(IOService
*nub
,
633 IOInterruptSource
*interruptSources
;
634 IOInterruptVectorNumber vectorNumber
;
635 IOInterruptVector
*vector
;
637 IOInterruptState interruptState
;
639 interruptSources
= nub
->_interruptSources
;
640 vectorData
= interruptSources
[source
].vectorData
;
641 vectorNumber
= *(IOInterruptVectorNumber
*)vectorData
->getBytesNoCopy();
642 vector
= &vectors
[vectorNumber
];
644 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
645 if (!vector
->interruptDisabledSoft
) {
646 vector
->interruptDisabledSoft
= 1;
649 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
651 if (!getPlatform()->atInterruptLevel()) {
652 while (vector
->interruptActive
)
656 return kIOReturnSuccess
;
659 IOInterruptAction
IOSharedInterruptController::getInterruptHandlerAddress(void)
661 return OSMemberFunctionCast(IOInterruptAction
,
662 this, &IOSharedInterruptController::handleInterrupt
);
665 IOReturn
IOSharedInterruptController::handleInterrupt(void * /*refCon*/,
669 IOInterruptVectorNumber vectorNumber
;
670 IOInterruptVector
*vector
;
672 for (vectorNumber
= 0; vectorNumber
< numVectors
; vectorNumber
++) {
673 vector
= &vectors
[vectorNumber
];
675 vector
->interruptActive
= 1;
676 if (!vector
->interruptDisabledSoft
) {
678 // Call the handler if it exists.
679 if (vector
->interruptRegistered
) {
681 bool trace
= (gIOKitTrace
& kIOTraceInterrupts
) ? true : false;
684 IOTimeStampStartConstant(IODBG_INTC(IOINTC_HANDLER
),
685 (uintptr_t) vectorNumber
, (uintptr_t) vector
->handler
, (uintptr_t)vector
->target
);
688 vector
->handler(vector
->target
, vector
->refCon
, vector
->nub
, vector
->source
);
691 IOTimeStampEndConstant(IODBG_INTC(IOINTC_HANDLER
),
692 (uintptr_t) vectorNumber
, (uintptr_t) vector
->handler
, (uintptr_t)vector
->target
);
697 vector
->interruptActive
= 0;
700 // if any of the vectors are dissabled, then dissable this controller.
701 IOSimpleLockLock(controllerLock
);
702 if (vectorsEnabled
!= vectorsRegistered
) {
703 nub
->disableInterrupt(0);
704 controllerDisabled
= 1;
706 IOSimpleLockUnlock(controllerLock
);
708 return kIOReturnSuccess
;