]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOInterruptController.cpp
81ef62db2edc02d5e656e88807554d1f064a6dff
[apple/xnu.git] / iokit / Kernel / IOInterruptController.cpp
1 /*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
30 *
31 * DRI: Josh de Cesare
32 *
33 */
34
35
36 #if __ppc__
37 #include <ppc/proc_reg.h>
38 #endif
39
40 #include <IOKit/IOLib.h>
41 #include <IOKit/IOService.h>
42 #include <IOKit/IOPlatformExpert.h>
43 #include <IOKit/IODeviceTreeSupport.h>
44 #include <IOKit/IOInterrupts.h>
45 #include <IOKit/IOInterruptController.h>
46
47
48 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
49
50 #define super IOService
51
52 OSDefineMetaClassAndAbstractStructors(IOInterruptController, IOService);
53
54 OSMetaClassDefineReservedUnused(IOInterruptController, 0);
55 OSMetaClassDefineReservedUnused(IOInterruptController, 1);
56 OSMetaClassDefineReservedUnused(IOInterruptController, 2);
57 OSMetaClassDefineReservedUnused(IOInterruptController, 3);
58 OSMetaClassDefineReservedUnused(IOInterruptController, 4);
59 OSMetaClassDefineReservedUnused(IOInterruptController, 5);
60
61 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
62
63 IOReturn IOInterruptController::registerInterrupt(IOService *nub, int source,
64 void *target,
65 IOInterruptHandler handler,
66 void *refCon)
67 {
68 IOInterruptSource *interruptSources;
69 long vectorNumber;
70 IOInterruptVector *vector;
71 long wasDisabledSoft;
72 IOReturn error;
73 OSData *vectorData;
74 IOService *originalNub;
75 int originalSource;
76 IOOptionBits options;
77 bool canBeShared, shouldBeShared, wasAlreadyRegisterd;
78
79 interruptSources = nub->_interruptSources;
80 vectorData = interruptSources[source].vectorData;
81 vectorNumber = *(long *)vectorData->getBytesNoCopy();
82 vector = &vectors[vectorNumber];
83
84 // Get the lock for this vector.
85 IOTakeLock(vector->interruptLock);
86
87 // Check if the interrupt source can/should be shared.
88 canBeShared = vectorCanBeShared(vectorNumber, vector);
89 IODTGetInterruptOptions(nub, source, &options);
90 shouldBeShared = canBeShared && (options & kIODTInterruptShared);
91 wasAlreadyRegisterd = vector->interruptRegistered;
92
93 // If the vector is registered and can not be shared return error.
94 if (wasAlreadyRegisterd && !canBeShared) {
95 IOUnlock(vector->interruptLock);
96 return kIOReturnNoResources;
97 }
98
99 // If this vector is already in use, and can be shared (implied),
100 // or it is not registered and should be shared,
101 // register as a shared interrupt.
102 if (wasAlreadyRegisterd || shouldBeShared) {
103 // If this vector is not already shared, break it out.
104 if (vector->sharedController == 0) {
105 // Make the IOShareInterruptController instance
106 vector->sharedController = new IOSharedInterruptController;
107 if (vector->sharedController == 0) {
108 IOUnlock(vector->interruptLock);
109 return kIOReturnNoMemory;
110 }
111
112 if (wasAlreadyRegisterd) {
113 // Save the nub and source for the original consumer.
114 originalNub = vector->nub;
115 originalSource = vector->source;
116
117 // Physically disable the interrupt, but mark it as being enabled in the hardware.
118 // The interruptDisabledSoft now indicates the driver's request for enablement.
119 disableVectorHard(vectorNumber, vector);
120 vector->interruptDisabledHard = 0;
121 }
122
123 // Initialize the new shared interrupt controller.
124 error = vector->sharedController->initInterruptController(this, vectorData);
125 // If the IOSharedInterruptController could not be initalized,
126 // if needed, put the original consumer's interrupt back to normal and
127 // get rid of whats left of the shared controller.
128 if (error != kIOReturnSuccess) {
129 if (wasAlreadyRegisterd) enableInterrupt(originalNub, originalSource);
130 vector->sharedController->release();
131 vector->sharedController = 0;
132 IOUnlock(vector->interruptLock);
133 return error;
134 }
135
136 // If there was an original consumer try to register it on the shared controller.
137 if (wasAlreadyRegisterd) {
138 error = vector->sharedController->registerInterrupt(originalNub,
139 originalSource,
140 vector->target,
141 vector->handler,
142 vector->refCon);
143 // If the original consumer could not be moved to the shared controller,
144 // put the original consumor's interrupt back to normal and
145 // get rid of whats left of the shared controller.
146 if (error != kIOReturnSuccess) {
147 // Save the driver's interrupt enablement state.
148 wasDisabledSoft = vector->interruptDisabledSoft;
149
150 // Make the interrupt really hard disabled.
151 vector->interruptDisabledSoft = 1;
152 vector->interruptDisabledHard = 1;
153
154 // Enable the original consumer's interrupt if needed.
155 if (!wasDisabledSoft) originalNub->enableInterrupt(originalSource);
156 enableInterrupt(originalNub, originalSource);
157
158 vector->sharedController->release();
159 vector->sharedController = 0;
160 IOUnlock(vector->interruptLock);
161 return error;
162 }
163 }
164
165 // Fill in vector with the shared controller's info.
166 vector->handler = (IOInterruptHandler)vector->sharedController->getInterruptHandlerAddress();
167 vector->nub = vector->sharedController;
168 vector->source = 0;
169 vector->target = vector->sharedController;
170 vector->refCon = 0;
171
172 // If the interrupt was already registered,
173 // save the driver's interrupt enablement state.
174 if (wasAlreadyRegisterd) wasDisabledSoft = vector->interruptDisabledSoft;
175 else wasDisabledSoft = true;
176
177 // Do any specific initalization for this vector if it has not yet been used.
178 if (!wasAlreadyRegisterd) initVector(vectorNumber, vector);
179
180 // Make the interrupt really hard disabled.
181 vector->interruptDisabledSoft = 1;
182 vector->interruptDisabledHard = 1;
183 vector->interruptRegistered = 1;
184
185 // Enable the original consumer's interrupt if needed.
186 if (!wasDisabledSoft) originalNub->enableInterrupt(originalSource);
187 }
188
189 error = vector->sharedController->registerInterrupt(nub, source, target,
190 handler, refCon);
191 IOUnlock(vector->interruptLock);
192 return error;
193 }
194
195 // Fill in vector with the client's info.
196 vector->handler = handler;
197 vector->nub = nub;
198 vector->source = source;
199 vector->target = target;
200 vector->refCon = refCon;
201
202 // Do any specific initalization for this vector.
203 initVector(vectorNumber, vector);
204
205 // Get the vector ready. It starts hard disabled.
206 vector->interruptDisabledHard = 1;
207 vector->interruptDisabledSoft = 1;
208 vector->interruptRegistered = 1;
209
210 IOUnlock(vector->interruptLock);
211 return kIOReturnSuccess;
212 }
213
214 IOReturn IOInterruptController::unregisterInterrupt(IOService *nub, int source)
215 {
216 IOInterruptSource *interruptSources;
217 long vectorNumber;
218 IOInterruptVector *vector;
219 OSData *vectorData;
220
221 interruptSources = nub->_interruptSources;
222 vectorData = interruptSources[source].vectorData;
223 vectorNumber = *(long *)vectorData->getBytesNoCopy();
224 vector = &vectors[vectorNumber];
225
226 // Get the lock for this vector.
227 IOTakeLock(vector->interruptLock);
228
229 // Return success if it is not already registered
230 if (!vector->interruptRegistered) {
231 IOUnlock(vector->interruptLock);
232 return kIOReturnSuccess;
233 }
234
235 // Soft disable the source.
236 disableInterrupt(nub, source);
237
238 // Turn the source off at hardware.
239 disableVectorHard(vectorNumber, vector);
240
241 // Clear all the storage for the vector except for interruptLock.
242 vector->interruptActive = 0;
243 vector->interruptDisabledSoft = 0;
244 vector->interruptDisabledHard = 0;
245 vector->interruptRegistered = 0;
246 vector->nub = 0;
247 vector->source = 0;
248 vector->handler = 0;
249 vector->target = 0;
250 vector->refCon = 0;
251
252 IOUnlock(vector->interruptLock);
253 return kIOReturnSuccess;
254 }
255
256 IOReturn IOInterruptController::getInterruptType(IOService *nub, int source,
257 int *interruptType)
258 {
259 IOInterruptSource *interruptSources;
260 long vectorNumber;
261 IOInterruptVector *vector;
262 OSData *vectorData;
263
264 if (interruptType == 0) return kIOReturnBadArgument;
265
266 interruptSources = nub->_interruptSources;
267 vectorData = interruptSources[source].vectorData;
268 vectorNumber = *(long *)vectorData->getBytesNoCopy();
269 vector = &vectors[vectorNumber];
270
271 *interruptType = getVectorType(vectorNumber, vector);
272
273 return kIOReturnSuccess;
274 }
275
276 IOReturn IOInterruptController::enableInterrupt(IOService *nub, int source)
277 {
278 IOInterruptSource *interruptSources;
279 long vectorNumber;
280 IOInterruptVector *vector;
281 OSData *vectorData;
282
283 interruptSources = nub->_interruptSources;
284 vectorData = interruptSources[source].vectorData;
285 vectorNumber = *(long *)vectorData->getBytesNoCopy();
286 vector = &vectors[vectorNumber];
287
288 if (vector->interruptDisabledSoft) {
289 vector->interruptDisabledSoft = 0;
290 #if __ppc__
291 sync();
292 isync();
293 #endif
294
295 if (!getPlatform()->atInterruptLevel()) {
296 while (vector->interruptActive);
297 #if __ppc__
298 isync();
299 #endif
300 }
301 if (vector->interruptDisabledHard) {
302 vector->interruptDisabledHard = 0;
303
304 enableVector(vectorNumber, vector);
305 }
306 }
307
308 return kIOReturnSuccess;
309 }
310
311 IOReturn IOInterruptController::disableInterrupt(IOService *nub, int source)
312 {
313 IOInterruptSource *interruptSources;
314 long vectorNumber;
315 IOInterruptVector *vector;
316 OSData *vectorData;
317
318 interruptSources = nub->_interruptSources;
319 vectorData = interruptSources[source].vectorData;
320 vectorNumber = *(long *)vectorData->getBytesNoCopy();
321 vector = &vectors[vectorNumber];
322
323 vector->interruptDisabledSoft = 1;
324 #if __ppc__
325 sync();
326 isync();
327 #endif
328
329 if (!getPlatform()->atInterruptLevel()) {
330 while (vector->interruptActive);
331 #if __ppc__
332 isync();
333 #endif
334 }
335
336 return kIOReturnSuccess;
337 }
338
339 IOReturn IOInterruptController::causeInterrupt(IOService *nub, int source)
340 {
341 IOInterruptSource *interruptSources;
342 long vectorNumber;
343 IOInterruptVector *vector;
344 OSData *vectorData;
345
346 interruptSources = nub->_interruptSources;
347 vectorData = interruptSources[source].vectorData;
348 vectorNumber = *(long *)vectorData->getBytesNoCopy();
349 vector = &vectors[vectorNumber];
350
351 causeVector(vectorNumber, vector);
352
353 return kIOReturnSuccess;
354 }
355
356 IOInterruptAction IOInterruptController::getInterruptHandlerAddress(void)
357 {
358 return 0;
359 }
360
361 IOReturn IOInterruptController::handleInterrupt(void *refCon, IOService *nub,
362 int source)
363 {
364 return kIOReturnInvalid;
365 }
366
367
368 // Methods to be overridden for simplifed interrupt controller subclasses.
369
370 bool IOInterruptController::vectorCanBeShared(long /*vectorNumber*/,
371 IOInterruptVector */*vector*/)
372 {
373 return false;
374 }
375
376 void IOInterruptController::initVector(long /*vectorNumber*/,
377 IOInterruptVector */*vector*/)
378 {
379 }
380
381 int IOInterruptController::getVectorType(long /*vectorNumber*/,
382 IOInterruptVector */*vector*/)
383 {
384 return kIOInterruptTypeEdge;
385 }
386
387 void IOInterruptController::disableVectorHard(long /*vectorNumber*/,
388 IOInterruptVector */*vector*/)
389 {
390 }
391
392 void IOInterruptController::enableVector(long /*vectorNumber*/,
393 IOInterruptVector */*vector*/)
394 {
395 }
396
397 void IOInterruptController::causeVector(long /*vectorNumber*/,
398 IOInterruptVector */*vector*/)
399 {
400 }
401
402
403 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
404
405 #undef super
406 #define super IOInterruptController
407
408 OSDefineMetaClassAndStructors(IOSharedInterruptController, IOInterruptController);
409
410 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 0);
411 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 1);
412 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 2);
413 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 3);
414
415 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
416
417 #define kIOSharedInterruptControllerDefaultVectors (128)
418
419 IOReturn IOSharedInterruptController::initInterruptController(IOInterruptController *parentController, OSData *parentSource)
420 {
421 int cnt, interruptType;
422 IOReturn error;
423
424 if (!super::init())
425 return kIOReturnNoResources;
426
427 // Set provider to this so enable/disable nub stuff works.
428 provider = this;
429
430 // Allocate the IOInterruptSource so this can act like a nub.
431 _interruptSources = (IOInterruptSource *)IOMalloc(sizeof(IOInterruptSource));
432 if (_interruptSources == 0) return kIOReturnNoMemory;
433 _numInterruptSources = 1;
434
435 // Set up the IOInterruptSource to point at this.
436 _interruptSources[0].interruptController = parentController;
437 _interruptSources[0].vectorData = parentSource;
438
439 sourceIsLevel = false;
440 error = provider->getInterruptType(0, &interruptType);
441 if (error == kIOReturnSuccess) {
442 if (interruptType & kIOInterruptTypeLevel)
443 sourceIsLevel = true;
444 }
445
446 // Allocate the memory for the vectors
447 numVectors = kIOSharedInterruptControllerDefaultVectors; // For now a constant number.
448 vectors = (IOInterruptVector *)IOMalloc(numVectors * sizeof(IOInterruptVector));
449 if (vectors == NULL) {
450 IOFree(_interruptSources, sizeof(IOInterruptSource));
451 return kIOReturnNoMemory;
452 }
453 bzero(vectors, numVectors * sizeof(IOInterruptVector));
454
455 // Allocate the lock for the controller.
456 controllerLock = IOSimpleLockAlloc();
457 if (controllerLock == 0) return kIOReturnNoResources;
458
459 // Allocate locks for the vectors.
460 for (cnt = 0; cnt < numVectors; cnt++) {
461 vectors[cnt].interruptLock = IOLockAlloc();
462 if (vectors[cnt].interruptLock == NULL) {
463 for (cnt = 0; cnt < numVectors; cnt++) {
464 if (vectors[cnt].interruptLock != NULL)
465 IOLockFree(vectors[cnt].interruptLock);
466 }
467 return kIOReturnNoResources;
468 }
469 }
470
471 numVectors = 0; // reset the high water mark for used vectors
472 vectorsRegistered = 0;
473 vectorsEnabled = 0;
474 controllerDisabled = 1;
475
476 return kIOReturnSuccess;
477 }
478
479 IOReturn IOSharedInterruptController::registerInterrupt(IOService *nub,
480 int source,
481 void *target,
482 IOInterruptHandler handler,
483 void *refCon)
484 {
485 IOInterruptSource *interruptSources;
486 long vectorNumber;
487 IOInterruptVector *vector = 0;
488 OSData *vectorData;
489 IOInterruptState interruptState;
490
491 interruptSources = nub->_interruptSources;
492
493 // Find a free vector.
494 vectorNumber = kIOSharedInterruptControllerDefaultVectors;
495 while (vectorsRegistered != kIOSharedInterruptControllerDefaultVectors) {
496 for (vectorNumber = 0; vectorNumber < kIOSharedInterruptControllerDefaultVectors; vectorNumber++) {
497 vector = &vectors[vectorNumber];
498
499 // Get the lock for this vector.
500 IOTakeLock(vector->interruptLock);
501
502 // Is it unregistered?
503 if (!vector->interruptRegistered) break;
504
505 // Move along to the next one.
506 IOUnlock(vector->interruptLock);
507 }
508
509 if (vectorNumber != kIOSharedInterruptControllerDefaultVectors) break;
510 }
511
512 // Could not find a free one, so give up.
513 if (vectorNumber == kIOSharedInterruptControllerDefaultVectors) {
514 return kIOReturnNoResources;
515 }
516
517 // Create the vectorData for the IOInterruptSource.
518 vectorData = OSData::withBytes(&vectorNumber, sizeof(vectorNumber));
519 if (vectorData == 0) {
520 return kIOReturnNoMemory;
521 }
522
523 // Fill in the IOInterruptSource with the controller's info.
524 interruptSources[source].interruptController = this;
525 interruptSources[source].vectorData = vectorData;
526
527 // Fill in vector with the client's info.
528 vector->handler = handler;
529 vector->nub = nub;
530 vector->source = source;
531 vector->target = target;
532 vector->refCon = refCon;
533
534 // Get the vector ready. It starts off soft disabled.
535 vector->interruptDisabledSoft = 1;
536 vector->interruptRegistered = 1;
537
538 interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
539 // Move the high water mark if needed
540 if (++vectorsRegistered > numVectors) numVectors = vectorsRegistered;
541 IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
542
543 IOUnlock(vector->interruptLock);
544 return kIOReturnSuccess;
545 }
546
547 IOReturn IOSharedInterruptController::unregisterInterrupt(IOService *nub,
548 int source)
549 {
550 IOInterruptSource *interruptSources;
551 long vectorNumber;
552 IOInterruptVector *vector;
553 OSData *vectorData;
554 IOInterruptState interruptState;
555
556 interruptSources = nub->_interruptSources;
557 vectorData = interruptSources[source].vectorData;
558 vectorNumber = *(long *)vectorData->getBytesNoCopy();
559 vector = &vectors[vectorNumber];
560
561 // Get the lock for this vector.
562 IOTakeLock(vector->interruptLock);
563
564 // Return success if it is not already registered
565 if (!vector->interruptRegistered) {
566 IOUnlock(vector->interruptLock);
567 return kIOReturnSuccess;
568 }
569
570 // Soft disable the source and the controller too.
571 disableInterrupt(nub, source);
572
573 // Clear all the storage for the vector except for interruptLock.
574 vector->interruptActive = 0;
575 vector->interruptDisabledSoft = 0;
576 vector->interruptDisabledHard = 0;
577 vector->interruptRegistered = 0;
578 vector->nub = 0;
579 vector->source = 0;
580 vector->handler = 0;
581 vector->target = 0;
582 vector->refCon = 0;
583
584 interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
585 vectorsRegistered--;
586 IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
587
588 IOUnlock(vector->interruptLock);
589
590 // Re-enable the controller if all vectors are enabled.
591 if (vectorsEnabled == vectorsRegistered) {
592 controllerDisabled = 0;
593 provider->enableInterrupt(0);
594 }
595
596 return kIOReturnSuccess;
597 }
598
599 IOReturn IOSharedInterruptController::getInterruptType(IOService */*nub*/,
600 int /*source*/,
601 int *interruptType)
602 {
603 return provider->getInterruptType(0, interruptType);
604 }
605
606 IOReturn IOSharedInterruptController::enableInterrupt(IOService *nub,
607 int source)
608 {
609 IOInterruptSource *interruptSources;
610 long vectorNumber;
611 IOInterruptVector *vector;
612 OSData *vectorData;
613 IOInterruptState interruptState;
614
615 interruptSources = nub->_interruptSources;
616 vectorData = interruptSources[source].vectorData;
617 vectorNumber = *(long *)vectorData->getBytesNoCopy();
618 vector = &vectors[vectorNumber];
619
620 interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
621 if (!vector->interruptDisabledSoft) {
622 IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
623 return kIOReturnSuccess;
624 }
625
626 vector->interruptDisabledSoft = 0;
627 vectorsEnabled++;
628 IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
629
630 if (controllerDisabled && (vectorsEnabled == vectorsRegistered)) {
631 controllerDisabled = 0;
632 provider->enableInterrupt(0);
633 }
634
635 return kIOReturnSuccess;
636 }
637
638 IOReturn IOSharedInterruptController::disableInterrupt(IOService *nub,
639 int source)
640 {
641 IOInterruptSource *interruptSources;
642 long vectorNumber;
643 IOInterruptVector *vector;
644 OSData *vectorData;
645 IOInterruptState interruptState;
646
647 interruptSources = nub->_interruptSources;
648 vectorData = interruptSources[source].vectorData;
649 vectorNumber = *(long *)vectorData->getBytesNoCopy();
650 vector = &vectors[vectorNumber];
651
652 interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
653 if (!vector->interruptDisabledSoft) {
654 vector->interruptDisabledSoft = 1;
655 #if __ppc__
656 sync();
657 isync();
658 #endif
659 vectorsEnabled--;
660 }
661 IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
662
663 if (!getPlatform()->atInterruptLevel()) {
664 while (vector->interruptActive);
665 #if __ppc__
666 isync();
667 #endif
668 }
669
670 return kIOReturnSuccess;
671 }
672
673 IOInterruptAction IOSharedInterruptController::getInterruptHandlerAddress(void)
674 {
675 return (IOInterruptAction)&IOSharedInterruptController::handleInterrupt;
676 }
677
678 IOReturn IOSharedInterruptController::handleInterrupt(void * /*refCon*/,
679 IOService * nub,
680 int /*source*/)
681 {
682 long vectorNumber;
683 IOInterruptVector *vector;
684
685 for (vectorNumber = 0; vectorNumber < numVectors; vectorNumber++) {
686 vector = &vectors[vectorNumber];
687
688 vector->interruptActive = 1;
689 #if __ppc__
690 sync();
691 isync();
692 #endif
693 if (!vector->interruptDisabledSoft) {
694 #if __ppc__
695 isync();
696 #endif
697
698 // Call the handler if it exists.
699 if (vector->interruptRegistered) {
700 vector->handler(vector->target, vector->refCon,
701 vector->nub, vector->source);
702 }
703 }
704
705 vector->interruptActive = 0;
706 }
707
708 // if any of the vectors are dissabled, then dissable this controller.
709 IOSimpleLockLock(controllerLock);
710 if (vectorsEnabled != vectorsRegistered) {
711 nub->disableInterrupt(0);
712 controllerDisabled = 1;
713 }
714 IOSimpleLockUnlock(controllerLock);
715
716 return kIOReturnSuccess;
717 }
718