]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOInterruptController.cpp
xnu-2050.48.11.tar.gz
[apple/xnu.git] / iokit / Kernel / IOInterruptController.cpp
1 /*
2 * Copyright (c) 1998-2010 Apple 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 #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>
37
38
39 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
40
41 #define super IOService
42
43 OSDefineMetaClassAndAbstractStructors(IOInterruptController, IOService);
44
45 OSMetaClassDefineReservedUnused(IOInterruptController, 0);
46 OSMetaClassDefineReservedUnused(IOInterruptController, 1);
47 OSMetaClassDefineReservedUnused(IOInterruptController, 2);
48 OSMetaClassDefineReservedUnused(IOInterruptController, 3);
49 OSMetaClassDefineReservedUnused(IOInterruptController, 4);
50 OSMetaClassDefineReservedUnused(IOInterruptController, 5);
51
52 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
53
54 IOReturn IOInterruptController::registerInterrupt(IOService *nub, int source,
55 void *target,
56 IOInterruptHandler handler,
57 void *refCon)
58 {
59 IOInterruptSource *interruptSources;
60 IOInterruptVectorNumber vectorNumber;
61 IOInterruptVector *vector;
62 int wasDisabledSoft;
63 IOReturn error;
64 OSData *vectorData;
65 IOOptionBits options;
66 bool canBeShared, shouldBeShared, wasAlreadyRegisterd;
67
68 IOService *originalNub = NULL; // Protected by wasAlreadyRegisterd
69 int originalSource = 0; // Protected by wasAlreadyRegisterd
70
71
72 interruptSources = nub->_interruptSources;
73 vectorData = interruptSources[source].vectorData;
74 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
75 vector = &vectors[vectorNumber];
76
77 // Get the lock for this vector.
78 IOLockLock(vector->interruptLock);
79
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__)
84 int interruptType;
85 if (OSDynamicCast(IOPlatformDevice, getProvider()) &&
86 (getInterruptType(nub, source, &interruptType) == kIOReturnSuccess) &&
87 (kIOInterruptTypeLevel & interruptType))
88 {
89 options |= kIODTInterruptShared;
90 }
91 #endif
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 IOLockUnlock(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 IOLockUnlock(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 IOLockUnlock(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 IOLockUnlock(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 // originalNub is protected by wasAlreadyRegisterd here (see line 184).
189 if (!wasDisabledSoft) originalNub->enableInterrupt(originalSource);
190 }
191
192 error = vector->sharedController->registerInterrupt(nub, source, target,
193 handler, refCon);
194 IOLockUnlock(vector->interruptLock);
195 return error;
196 }
197
198 // Fill in vector with the client's info.
199 vector->handler = handler;
200 vector->nub = nub;
201 vector->source = source;
202 vector->target = target;
203 vector->refCon = refCon;
204
205 // Do any specific initalization for this vector.
206 initVector(vectorNumber, vector);
207
208 // Get the vector ready. It starts hard disabled.
209 vector->interruptDisabledHard = 1;
210 vector->interruptDisabledSoft = 1;
211 vector->interruptRegistered = 1;
212
213 IOLockUnlock(vector->interruptLock);
214 return kIOReturnSuccess;
215 }
216
217 IOReturn IOInterruptController::unregisterInterrupt(IOService *nub, int source)
218 {
219 IOInterruptSource *interruptSources;
220 IOInterruptVectorNumber vectorNumber;
221 IOInterruptVector *vector;
222 OSData *vectorData;
223
224 interruptSources = nub->_interruptSources;
225 vectorData = interruptSources[source].vectorData;
226 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
227 vector = &vectors[vectorNumber];
228
229 // Get the lock for this vector.
230 IOLockLock(vector->interruptLock);
231
232 // Return success if it is not already registered
233 if (!vector->interruptRegistered) {
234 IOLockUnlock(vector->interruptLock);
235 return kIOReturnSuccess;
236 }
237
238 // Soft disable the source.
239 disableInterrupt(nub, source);
240
241 // Turn the source off at hardware.
242 disableVectorHard(vectorNumber, vector);
243
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;
249 vector->nub = 0;
250 vector->source = 0;
251 vector->handler = 0;
252 vector->target = 0;
253 vector->refCon = 0;
254
255 IOLockUnlock(vector->interruptLock);
256 return kIOReturnSuccess;
257 }
258
259 IOReturn IOInterruptController::getInterruptType(IOService *nub, int source,
260 int *interruptType)
261 {
262 IOInterruptSource *interruptSources;
263 IOInterruptVectorNumber vectorNumber;
264 IOInterruptVector *vector;
265 OSData *vectorData;
266
267 if (interruptType == 0) return kIOReturnBadArgument;
268
269 interruptSources = nub->_interruptSources;
270 vectorData = interruptSources[source].vectorData;
271 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
272 vector = &vectors[vectorNumber];
273
274 *interruptType = getVectorType(vectorNumber, vector);
275
276 return kIOReturnSuccess;
277 }
278
279 IOReturn IOInterruptController::enableInterrupt(IOService *nub, int source)
280 {
281 IOInterruptSource *interruptSources;
282 IOInterruptVectorNumber vectorNumber;
283 IOInterruptVector *vector;
284 OSData *vectorData;
285
286 interruptSources = nub->_interruptSources;
287 vectorData = interruptSources[source].vectorData;
288 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
289 vector = &vectors[vectorNumber];
290
291 if (vector->interruptDisabledSoft) {
292 vector->interruptDisabledSoft = 0;
293
294 if (!getPlatform()->atInterruptLevel()) {
295 while (vector->interruptActive)
296 {}
297 }
298 if (vector->interruptDisabledHard) {
299 vector->interruptDisabledHard = 0;
300
301 enableVector(vectorNumber, vector);
302 }
303 }
304
305 return kIOReturnSuccess;
306 }
307
308 IOReturn IOInterruptController::disableInterrupt(IOService *nub, int source)
309 {
310 IOInterruptSource *interruptSources;
311 IOInterruptVectorNumber vectorNumber;
312 IOInterruptVector *vector;
313 OSData *vectorData;
314
315 interruptSources = nub->_interruptSources;
316 vectorData = interruptSources[source].vectorData;
317 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
318 vector = &vectors[vectorNumber];
319
320 vector->interruptDisabledSoft = 1;
321
322 if (!getPlatform()->atInterruptLevel()) {
323 while (vector->interruptActive)
324 {}
325 }
326
327 return kIOReturnSuccess;
328 }
329
330 IOReturn IOInterruptController::causeInterrupt(IOService *nub, int source)
331 {
332 IOInterruptSource *interruptSources;
333 IOInterruptVectorNumber vectorNumber;
334 IOInterruptVector *vector;
335 OSData *vectorData;
336
337 interruptSources = nub->_interruptSources;
338 vectorData = interruptSources[source].vectorData;
339 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
340 vector = &vectors[vectorNumber];
341
342 causeVector(vectorNumber, vector);
343
344 return kIOReturnSuccess;
345 }
346
347 IOInterruptAction IOInterruptController::getInterruptHandlerAddress(void)
348 {
349 return 0;
350 }
351
352 IOReturn IOInterruptController::handleInterrupt(void *refCon, IOService *nub,
353 int source)
354 {
355 return kIOReturnInvalid;
356 }
357
358
359 // Methods to be overridden for simplifed interrupt controller subclasses.
360
361 bool IOInterruptController::vectorCanBeShared(IOInterruptVectorNumber /*vectorNumber*/,
362 IOInterruptVector */*vector*/)
363 {
364 return false;
365 }
366
367 void IOInterruptController::initVector(IOInterruptVectorNumber /*vectorNumber*/,
368 IOInterruptVector */*vector*/)
369 {
370 }
371
372 int IOInterruptController::getVectorType(IOInterruptVectorNumber /*vectorNumber*/,
373 IOInterruptVector */*vector*/)
374 {
375 return kIOInterruptTypeEdge;
376 }
377
378 void IOInterruptController::disableVectorHard(IOInterruptVectorNumber /*vectorNumber*/,
379 IOInterruptVector */*vector*/)
380 {
381 }
382
383 void IOInterruptController::enableVector(IOInterruptVectorNumber /*vectorNumber*/,
384 IOInterruptVector */*vector*/)
385 {
386 }
387
388 void IOInterruptController::causeVector(IOInterruptVectorNumber /*vectorNumber*/,
389 IOInterruptVector */*vector*/)
390 {
391 }
392
393
394 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
395
396 #undef super
397 #define super IOInterruptController
398
399 OSDefineMetaClassAndStructors(IOSharedInterruptController, IOInterruptController);
400
401 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 0);
402 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 1);
403 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 2);
404 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 3);
405
406 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
407
408 #define kIOSharedInterruptControllerDefaultVectors (128)
409
410 IOReturn IOSharedInterruptController::initInterruptController(IOInterruptController *parentController, OSData *parentSource)
411 {
412 int cnt, interruptType;
413 IOReturn error;
414
415 if (!super::init())
416 return kIOReturnNoResources;
417
418 // Set provider to this so enable/disable nub stuff works.
419 provider = this;
420
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;
425
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;
431
432 sourceIsLevel = false;
433 error = provider->getInterruptType(0, &interruptType);
434 if (error == kIOReturnSuccess) {
435 if (interruptType & kIOInterruptTypeLevel)
436 sourceIsLevel = true;
437 }
438
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;
445 }
446 bzero(vectors, numVectors * sizeof(IOInterruptVector));
447
448 // Allocate the lock for the controller.
449 controllerLock = IOSimpleLockAlloc();
450 if (controllerLock == 0) return kIOReturnNoResources;
451
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);
459 }
460 return kIOReturnNoResources;
461 }
462 }
463
464 numVectors = 0; // reset the high water mark for used vectors
465 vectorsRegistered = 0;
466 vectorsEnabled = 0;
467 controllerDisabled = 1;
468
469 return kIOReturnSuccess;
470 }
471
472 IOReturn IOSharedInterruptController::registerInterrupt(IOService *nub,
473 int source,
474 void *target,
475 IOInterruptHandler handler,
476 void *refCon)
477 {
478 IOInterruptSource *interruptSources;
479 IOInterruptVectorNumber vectorNumber;
480 IOInterruptVector *vector = 0;
481 OSData *vectorData;
482 IOInterruptState interruptState;
483
484 interruptSources = nub->_interruptSources;
485
486 // Find a free vector.
487 vectorNumber = kIOSharedInterruptControllerDefaultVectors;
488 while (vectorsRegistered != kIOSharedInterruptControllerDefaultVectors) {
489 for (vectorNumber = 0; vectorNumber < kIOSharedInterruptControllerDefaultVectors; vectorNumber++) {
490 vector = &vectors[vectorNumber];
491
492 // Get the lock for this vector.
493 IOLockLock(vector->interruptLock);
494
495 // Is it unregistered?
496 if (!vector->interruptRegistered) break;
497
498 // Move along to the next one.
499 IOLockUnlock(vector->interruptLock);
500 }
501
502 if (vectorNumber != kIOSharedInterruptControllerDefaultVectors) break;
503 }
504
505 // Could not find a free one, so give up.
506 if (vectorNumber == kIOSharedInterruptControllerDefaultVectors) {
507 return kIOReturnNoResources;
508 }
509
510 // Create the vectorData for the IOInterruptSource.
511 vectorData = OSData::withBytes(&vectorNumber, sizeof(vectorNumber));
512 if (vectorData == 0) {
513 return kIOReturnNoMemory;
514 }
515
516 // Fill in the IOInterruptSource with the controller's info.
517 interruptSources[source].interruptController = this;
518 interruptSources[source].vectorData = vectorData;
519
520 // Fill in vector with the client's info.
521 vector->handler = handler;
522 vector->nub = nub;
523 vector->source = source;
524 vector->target = target;
525 vector->refCon = refCon;
526
527 // Get the vector ready. It starts off soft disabled.
528 vector->interruptDisabledSoft = 1;
529 vector->interruptRegistered = 1;
530
531 interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
532 // Move the high water mark if needed
533 if (++vectorsRegistered > numVectors) numVectors = vectorsRegistered;
534 IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
535
536 IOLockUnlock(vector->interruptLock);
537 return kIOReturnSuccess;
538 }
539
540 IOReturn IOSharedInterruptController::unregisterInterrupt(IOService *nub,
541 int source)
542 {
543 IOInterruptVectorNumber vectorNumber;
544 IOInterruptVector *vector;
545 IOInterruptState interruptState;
546
547 for (vectorNumber = 0; vectorNumber < kIOSharedInterruptControllerDefaultVectors; vectorNumber++) {
548 vector = &vectors[vectorNumber];
549
550 // Get the lock for this vector.
551 IOLockLock(vector->interruptLock);
552
553 // Return success if it is not already registered
554 if (!vector->interruptRegistered
555 || (vector->nub != nub) || (vector->source != source)) {
556 IOLockUnlock(vector->interruptLock);
557 continue;
558 }
559
560 // Soft disable the source and the controller too.
561 disableInterrupt(nub, source);
562
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;
568 vector->nub = 0;
569 vector->source = 0;
570 vector->handler = 0;
571 vector->target = 0;
572 vector->refCon = 0;
573
574 interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
575 vectorsRegistered--;
576 IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
577
578 // Move along to the next one.
579 IOLockUnlock(vector->interruptLock);
580 }
581
582 // Re-enable the controller if all vectors are enabled.
583 if (vectorsEnabled == vectorsRegistered) {
584 controllerDisabled = 0;
585 provider->enableInterrupt(0);
586 }
587
588 return kIOReturnSuccess;
589 }
590
591 IOReturn IOSharedInterruptController::getInterruptType(IOService */*nub*/,
592 int /*source*/,
593 int *interruptType)
594 {
595 return provider->getInterruptType(0, interruptType);
596 }
597
598 IOReturn IOSharedInterruptController::enableInterrupt(IOService *nub,
599 int source)
600 {
601 IOInterruptSource *interruptSources;
602 IOInterruptVectorNumber vectorNumber;
603 IOInterruptVector *vector;
604 OSData *vectorData;
605 IOInterruptState interruptState;
606
607 interruptSources = nub->_interruptSources;
608 vectorData = interruptSources[source].vectorData;
609 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
610 vector = &vectors[vectorNumber];
611
612 interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
613 if (!vector->interruptDisabledSoft) {
614 IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
615 return kIOReturnSuccess;
616 }
617
618 vector->interruptDisabledSoft = 0;
619 vectorsEnabled++;
620 IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
621
622 if (controllerDisabled && (vectorsEnabled == vectorsRegistered)) {
623 controllerDisabled = 0;
624 provider->enableInterrupt(0);
625 }
626
627 return kIOReturnSuccess;
628 }
629
630 IOReturn IOSharedInterruptController::disableInterrupt(IOService *nub,
631 int source)
632 {
633 IOInterruptSource *interruptSources;
634 IOInterruptVectorNumber vectorNumber;
635 IOInterruptVector *vector;
636 OSData *vectorData;
637 IOInterruptState interruptState;
638
639 interruptSources = nub->_interruptSources;
640 vectorData = interruptSources[source].vectorData;
641 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
642 vector = &vectors[vectorNumber];
643
644 interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
645 if (!vector->interruptDisabledSoft) {
646 vector->interruptDisabledSoft = 1;
647 vectorsEnabled--;
648 }
649 IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
650
651 if (!getPlatform()->atInterruptLevel()) {
652 while (vector->interruptActive)
653 {}
654 }
655
656 return kIOReturnSuccess;
657 }
658
659 IOInterruptAction IOSharedInterruptController::getInterruptHandlerAddress(void)
660 {
661 return OSMemberFunctionCast(IOInterruptAction,
662 this, &IOSharedInterruptController::handleInterrupt);
663 }
664
665 IOReturn IOSharedInterruptController::handleInterrupt(void * /*refCon*/,
666 IOService * nub,
667 int /*source*/)
668 {
669 IOInterruptVectorNumber vectorNumber;
670 IOInterruptVector *vector;
671
672 for (vectorNumber = 0; vectorNumber < numVectors; vectorNumber++) {
673 vector = &vectors[vectorNumber];
674
675 vector->interruptActive = 1;
676 if (!vector->interruptDisabledSoft) {
677
678 // Call the handler if it exists.
679 if (vector->interruptRegistered) {
680
681 bool trace = (gIOKitTrace & kIOTraceInterrupts) ? true : false;
682
683 if (trace)
684 IOTimeStampStartConstant(IODBG_INTC(IOINTC_HANDLER),
685 (uintptr_t) vectorNumber, (uintptr_t) vector->handler, (uintptr_t)vector->target);
686
687 // Call handler.
688 vector->handler(vector->target, vector->refCon, vector->nub, vector->source);
689
690 if (trace)
691 IOTimeStampEndConstant(IODBG_INTC(IOINTC_HANDLER),
692 (uintptr_t) vectorNumber, (uintptr_t) vector->handler, (uintptr_t)vector->target);
693
694 }
695 }
696
697 vector->interruptActive = 0;
698 }
699
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;
705 }
706 IOSimpleLockUnlock(controllerLock);
707
708 return kIOReturnSuccess;
709 }
710