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