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