]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOInterruptController.cpp
xnu-2050.48.11.tar.gz
[apple/xnu.git] / iokit / Kernel / IOInterruptController.cpp
CommitLineData
1c79356b 1/*
6d2010ae 2 * Copyright (c) 1998-2010 Apple Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
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.
8f6c56a5 14 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b 27 */
1c79356b 28
1c79356b
A
29#include <IOKit/IOLib.h>
30#include <IOKit/IOService.h>
31#include <IOKit/IOPlatformExpert.h>
91447636 32#include <IOKit/IODeviceTreeSupport.h>
1c79356b
A
33#include <IOKit/IOInterrupts.h>
34#include <IOKit/IOInterruptController.h>
060df5ea
A
35#include <IOKit/IOKitDebug.h>
36#include <IOKit/IOTimeStamp.h>
37
1c79356b 38
1c79356b
A
39/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
40
41#define super IOService
42
43OSDefineMetaClassAndAbstractStructors(IOInterruptController, IOService);
44
45OSMetaClassDefineReservedUnused(IOInterruptController, 0);
46OSMetaClassDefineReservedUnused(IOInterruptController, 1);
47OSMetaClassDefineReservedUnused(IOInterruptController, 2);
48OSMetaClassDefineReservedUnused(IOInterruptController, 3);
49OSMetaClassDefineReservedUnused(IOInterruptController, 4);
50OSMetaClassDefineReservedUnused(IOInterruptController, 5);
51
52/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
53
54IOReturn IOInterruptController::registerInterrupt(IOService *nub, int source,
55 void *target,
56 IOInterruptHandler handler,
57 void *refCon)
58{
59 IOInterruptSource *interruptSources;
b0d623f7 60 IOInterruptVectorNumber vectorNumber;
1c79356b 61 IOInterruptVector *vector;
b0d623f7 62 int wasDisabledSoft;
1c79356b
A
63 IOReturn error;
64 OSData *vectorData;
91447636
A
65 IOOptionBits options;
66 bool canBeShared, shouldBeShared, wasAlreadyRegisterd;
b0d623f7
A
67
68 IOService *originalNub = NULL; // Protected by wasAlreadyRegisterd
69 int originalSource = 0; // Protected by wasAlreadyRegisterd
70
71
1c79356b
A
72 interruptSources = nub->_interruptSources;
73 vectorData = interruptSources[source].vectorData;
b0d623f7 74 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
1c79356b
A
75 vector = &vectors[vectorNumber];
76
77 // Get the lock for this vector.
060df5ea 78 IOLockLock(vector->interruptLock);
1c79356b 79
91447636
A
80 // Check if the interrupt source can/should be shared.
81 canBeShared = vectorCanBeShared(vectorNumber, vector);
82 IODTGetInterruptOptions(nub, source, &options);
cf7d32b8
A
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
91447636
A
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) {
060df5ea 97 IOLockUnlock(vector->interruptLock);
91447636
A
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,
1c79356b 103 // register as a shared interrupt.
91447636 104 if (wasAlreadyRegisterd || shouldBeShared) {
1c79356b
A
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) {
060df5ea 110 IOLockUnlock(vector->interruptLock);
1c79356b
A
111 return kIOReturnNoMemory;
112 }
113
91447636
A
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 }
1c79356b
A
124
125 // Initialize the new shared interrupt controller.
91447636 126 error = vector->sharedController->initInterruptController(this, vectorData);
1c79356b 127 // If the IOSharedInterruptController could not be initalized,
91447636 128 // if needed, put the original consumer's interrupt back to normal and
1c79356b
A
129 // get rid of whats left of the shared controller.
130 if (error != kIOReturnSuccess) {
91447636 131 if (wasAlreadyRegisterd) enableInterrupt(originalNub, originalSource);
1c79356b
A
132 vector->sharedController->release();
133 vector->sharedController = 0;
060df5ea 134 IOLockUnlock(vector->interruptLock);
1c79356b
A
135 return error;
136 }
137
91447636
A
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;
060df5ea 162 IOLockUnlock(vector->interruptLock);
91447636
A
163 return error;
164 }
1c79356b
A
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
91447636
A
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);
ac5ea4a9
A
181
182 // Make the interrupt really hard disabled.
183 vector->interruptDisabledSoft = 1;
184 vector->interruptDisabledHard = 1;
91447636 185 vector->interruptRegistered = 1;
ac5ea4a9 186
1c79356b 187 // Enable the original consumer's interrupt if needed.
b0d623f7 188 // originalNub is protected by wasAlreadyRegisterd here (see line 184).
1c79356b
A
189 if (!wasDisabledSoft) originalNub->enableInterrupt(originalSource);
190 }
191
192 error = vector->sharedController->registerInterrupt(nub, source, target,
193 handler, refCon);
060df5ea 194 IOLockUnlock(vector->interruptLock);
1c79356b
A
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
060df5ea 213 IOLockUnlock(vector->interruptLock);
1c79356b
A
214 return kIOReturnSuccess;
215}
216
217IOReturn IOInterruptController::unregisterInterrupt(IOService *nub, int source)
218{
219 IOInterruptSource *interruptSources;
b0d623f7 220 IOInterruptVectorNumber vectorNumber;
1c79356b
A
221 IOInterruptVector *vector;
222 OSData *vectorData;
223
224 interruptSources = nub->_interruptSources;
225 vectorData = interruptSources[source].vectorData;
b0d623f7 226 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
1c79356b
A
227 vector = &vectors[vectorNumber];
228
229 // Get the lock for this vector.
060df5ea 230 IOLockLock(vector->interruptLock);
1c79356b
A
231
232 // Return success if it is not already registered
233 if (!vector->interruptRegistered) {
060df5ea 234 IOLockUnlock(vector->interruptLock);
1c79356b
A
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
060df5ea 255 IOLockUnlock(vector->interruptLock);
1c79356b
A
256 return kIOReturnSuccess;
257}
258
259IOReturn IOInterruptController::getInterruptType(IOService *nub, int source,
260 int *interruptType)
261{
262 IOInterruptSource *interruptSources;
b0d623f7 263 IOInterruptVectorNumber vectorNumber;
1c79356b
A
264 IOInterruptVector *vector;
265 OSData *vectorData;
266
267 if (interruptType == 0) return kIOReturnBadArgument;
268
269 interruptSources = nub->_interruptSources;
270 vectorData = interruptSources[source].vectorData;
b0d623f7 271 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
1c79356b
A
272 vector = &vectors[vectorNumber];
273
274 *interruptType = getVectorType(vectorNumber, vector);
275
276 return kIOReturnSuccess;
277}
278
279IOReturn IOInterruptController::enableInterrupt(IOService *nub, int source)
280{
281 IOInterruptSource *interruptSources;
b0d623f7 282 IOInterruptVectorNumber vectorNumber;
1c79356b
A
283 IOInterruptVector *vector;
284 OSData *vectorData;
285
286 interruptSources = nub->_interruptSources;
287 vectorData = interruptSources[source].vectorData;
b0d623f7 288 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
1c79356b
A
289 vector = &vectors[vectorNumber];
290
291 if (vector->interruptDisabledSoft) {
292 vector->interruptDisabledSoft = 0;
293
0b4e3aa0 294 if (!getPlatform()->atInterruptLevel()) {
b0d623f7
A
295 while (vector->interruptActive)
296 {}
0b4e3aa0 297 }
1c79356b
A
298 if (vector->interruptDisabledHard) {
299 vector->interruptDisabledHard = 0;
300
301 enableVector(vectorNumber, vector);
302 }
303 }
304
305 return kIOReturnSuccess;
306}
307
308IOReturn IOInterruptController::disableInterrupt(IOService *nub, int source)
309{
310 IOInterruptSource *interruptSources;
b0d623f7 311 IOInterruptVectorNumber vectorNumber;
1c79356b
A
312 IOInterruptVector *vector;
313 OSData *vectorData;
314
315 interruptSources = nub->_interruptSources;
316 vectorData = interruptSources[source].vectorData;
b0d623f7 317 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
1c79356b
A
318 vector = &vectors[vectorNumber];
319
320 vector->interruptDisabledSoft = 1;
1c79356b
A
321
322 if (!getPlatform()->atInterruptLevel()) {
b0d623f7
A
323 while (vector->interruptActive)
324 {}
1c79356b
A
325 }
326
327 return kIOReturnSuccess;
328}
329
330IOReturn IOInterruptController::causeInterrupt(IOService *nub, int source)
331{
332 IOInterruptSource *interruptSources;
b0d623f7 333 IOInterruptVectorNumber vectorNumber;
1c79356b
A
334 IOInterruptVector *vector;
335 OSData *vectorData;
336
337 interruptSources = nub->_interruptSources;
338 vectorData = interruptSources[source].vectorData;
b0d623f7 339 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
1c79356b
A
340 vector = &vectors[vectorNumber];
341
342 causeVector(vectorNumber, vector);
343
344 return kIOReturnSuccess;
345}
346
347IOInterruptAction IOInterruptController::getInterruptHandlerAddress(void)
348{
349 return 0;
350}
351
352IOReturn 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
b0d623f7 361bool IOInterruptController::vectorCanBeShared(IOInterruptVectorNumber /*vectorNumber*/,
1c79356b
A
362 IOInterruptVector */*vector*/)
363{
364 return false;
365}
366
b0d623f7 367void IOInterruptController::initVector(IOInterruptVectorNumber /*vectorNumber*/,
1c79356b
A
368 IOInterruptVector */*vector*/)
369{
370}
371
b0d623f7 372int IOInterruptController::getVectorType(IOInterruptVectorNumber /*vectorNumber*/,
1c79356b
A
373 IOInterruptVector */*vector*/)
374{
375 return kIOInterruptTypeEdge;
376}
377
b0d623f7 378void IOInterruptController::disableVectorHard(IOInterruptVectorNumber /*vectorNumber*/,
1c79356b
A
379 IOInterruptVector */*vector*/)
380{
381}
382
b0d623f7 383void IOInterruptController::enableVector(IOInterruptVectorNumber /*vectorNumber*/,
1c79356b
A
384 IOInterruptVector */*vector*/)
385{
386}
387
b0d623f7 388void IOInterruptController::causeVector(IOInterruptVectorNumber /*vectorNumber*/,
1c79356b
A
389 IOInterruptVector */*vector*/)
390{
391}
392
393
394/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
395
396#undef super
397#define super IOInterruptController
398
399OSDefineMetaClassAndStructors(IOSharedInterruptController, IOInterruptController);
400
401OSMetaClassDefineReservedUnused(IOSharedInterruptController, 0);
402OSMetaClassDefineReservedUnused(IOSharedInterruptController, 1);
403OSMetaClassDefineReservedUnused(IOSharedInterruptController, 2);
404OSMetaClassDefineReservedUnused(IOSharedInterruptController, 3);
405
406/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
407
91447636
A
408#define kIOSharedInterruptControllerDefaultVectors (128)
409
1c79356b
A
410IOReturn 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.
0c530ab8
A
427 parentController->retain();
428 parentSource->retain();
1c79356b
A
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
91447636 440 numVectors = kIOSharedInterruptControllerDefaultVectors; // For now a constant number.
1c79356b
A
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
91447636 464 numVectors = 0; // reset the high water mark for used vectors
1c79356b
A
465 vectorsRegistered = 0;
466 vectorsEnabled = 0;
467 controllerDisabled = 1;
468
469 return kIOReturnSuccess;
470}
471
472IOReturn IOSharedInterruptController::registerInterrupt(IOService *nub,
473 int source,
474 void *target,
475 IOInterruptHandler handler,
476 void *refCon)
477{
478 IOInterruptSource *interruptSources;
b0d623f7 479 IOInterruptVectorNumber vectorNumber;
1c79356b
A
480 IOInterruptVector *vector = 0;
481 OSData *vectorData;
482 IOInterruptState interruptState;
483
484 interruptSources = nub->_interruptSources;
485
486 // Find a free vector.
91447636
A
487 vectorNumber = kIOSharedInterruptControllerDefaultVectors;
488 while (vectorsRegistered != kIOSharedInterruptControllerDefaultVectors) {
489 for (vectorNumber = 0; vectorNumber < kIOSharedInterruptControllerDefaultVectors; vectorNumber++) {
1c79356b
A
490 vector = &vectors[vectorNumber];
491
492 // Get the lock for this vector.
060df5ea 493 IOLockLock(vector->interruptLock);
1c79356b
A
494
495 // Is it unregistered?
496 if (!vector->interruptRegistered) break;
497
498 // Move along to the next one.
060df5ea 499 IOLockUnlock(vector->interruptLock);
1c79356b
A
500 }
501
91447636 502 if (vectorNumber != kIOSharedInterruptControllerDefaultVectors) break;
1c79356b
A
503 }
504
505 // Could not find a free one, so give up.
91447636 506 if (vectorNumber == kIOSharedInterruptControllerDefaultVectors) {
1c79356b
A
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
91447636 527 // Get the vector ready. It starts off soft disabled.
1c79356b
A
528 vector->interruptDisabledSoft = 1;
529 vector->interruptRegistered = 1;
530
531 interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
91447636
A
532 // Move the high water mark if needed
533 if (++vectorsRegistered > numVectors) numVectors = vectorsRegistered;
1c79356b
A
534 IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
535
060df5ea 536 IOLockUnlock(vector->interruptLock);
1c79356b
A
537 return kIOReturnSuccess;
538}
539
540IOReturn IOSharedInterruptController::unregisterInterrupt(IOService *nub,
541 int source)
542{
b0d623f7 543 IOInterruptVectorNumber vectorNumber;
1c79356b 544 IOInterruptVector *vector;
91447636 545 IOInterruptState interruptState;
b0d623f7
A
546
547 for (vectorNumber = 0; vectorNumber < kIOSharedInterruptControllerDefaultVectors; vectorNumber++) {
548 vector = &vectors[vectorNumber];
549
550 // Get the lock for this vector.
060df5ea 551 IOLockLock(vector->interruptLock);
b0d623f7
A
552
553 // Return success if it is not already registered
554 if (!vector->interruptRegistered
555 || (vector->nub != nub) || (vector->source != source)) {
060df5ea 556 IOLockUnlock(vector->interruptLock);
b0d623f7
A
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.
060df5ea 579 IOLockUnlock(vector->interruptLock);
1c79356b 580 }
b0d623f7 581
91447636
A
582 // Re-enable the controller if all vectors are enabled.
583 if (vectorsEnabled == vectorsRegistered) {
584 controllerDisabled = 0;
585 provider->enableInterrupt(0);
586 }
b0d623f7 587
1c79356b
A
588 return kIOReturnSuccess;
589}
590
591IOReturn IOSharedInterruptController::getInterruptType(IOService */*nub*/,
592 int /*source*/,
593 int *interruptType)
594{
595 return provider->getInterruptType(0, interruptType);
596}
597
598IOReturn IOSharedInterruptController::enableInterrupt(IOService *nub,
599 int source)
600{
601 IOInterruptSource *interruptSources;
b0d623f7 602 IOInterruptVectorNumber vectorNumber;
1c79356b
A
603 IOInterruptVector *vector;
604 OSData *vectorData;
14353aa8 605 IOInterruptState interruptState;
1c79356b
A
606
607 interruptSources = nub->_interruptSources;
608 vectorData = interruptSources[source].vectorData;
b0d623f7 609 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
1c79356b
A
610 vector = &vectors[vectorNumber];
611
14353aa8
A
612 interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
613 if (!vector->interruptDisabledSoft) {
1c79356b 614 IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
14353aa8
A
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);
1c79356b
A
625 }
626
627 return kIOReturnSuccess;
628}
629
630IOReturn IOSharedInterruptController::disableInterrupt(IOService *nub,
631 int source)
632{
633 IOInterruptSource *interruptSources;
b0d623f7 634 IOInterruptVectorNumber vectorNumber;
1c79356b
A
635 IOInterruptVector *vector;
636 OSData *vectorData;
14353aa8 637 IOInterruptState interruptState;
1c79356b
A
638
639 interruptSources = nub->_interruptSources;
640 vectorData = interruptSources[source].vectorData;
b0d623f7 641 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
1c79356b
A
642 vector = &vectors[vectorNumber];
643
14353aa8 644 interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
1c79356b
A
645 if (!vector->interruptDisabledSoft) {
646 vector->interruptDisabledSoft = 1;
1c79356b 647 vectorsEnabled--;
1c79356b 648 }
14353aa8 649 IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
1c79356b
A
650
651 if (!getPlatform()->atInterruptLevel()) {
b0d623f7
A
652 while (vector->interruptActive)
653 {}
1c79356b
A
654 }
655
656 return kIOReturnSuccess;
657}
658
659IOInterruptAction IOSharedInterruptController::getInterruptHandlerAddress(void)
660{
0c530ab8
A
661 return OSMemberFunctionCast(IOInterruptAction,
662 this, &IOSharedInterruptController::handleInterrupt);
1c79356b
A
663}
664
665IOReturn IOSharedInterruptController::handleInterrupt(void * /*refCon*/,
666 IOService * nub,
667 int /*source*/)
668{
b0d623f7 669 IOInterruptVectorNumber vectorNumber;
1c79356b
A
670 IOInterruptVector *vector;
671
672 for (vectorNumber = 0; vectorNumber < numVectors; vectorNumber++) {
673 vector = &vectors[vectorNumber];
674
675 vector->interruptActive = 1;
6d2010ae
A
676 if (!vector->interruptDisabledSoft) {
677
678 // Call the handler if it exists.
679 if (vector->interruptRegistered) {
680
681 bool trace = (gIOKitTrace & kIOTraceInterrupts) ? true : false;
060df5ea
A
682
683 if (trace)
684 IOTimeStampStartConstant(IODBG_INTC(IOINTC_HANDLER),
685 (uintptr_t) vectorNumber, (uintptr_t) vector->handler, (uintptr_t)vector->target);
686
060df5ea
A
687 // Call handler.
688 vector->handler(vector->target, vector->refCon, vector->nub, vector->source);
060df5ea
A
689
690 if (trace)
691 IOTimeStampEndConstant(IODBG_INTC(IOINTC_HANDLER),
692 (uintptr_t) vectorNumber, (uintptr_t) vector->handler, (uintptr_t)vector->target);
693
6d2010ae
A
694 }
695 }
1c79356b
A
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