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