]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOInterruptController.cpp
xnu-3789.51.2.tar.gz
[apple/xnu.git] / iokit / Kernel / IOInterruptController.cpp
CommitLineData
1c79356b 1/*
39236c6e
A
2 * Copyright (c) 2007-2012 Apple Inc. All rights reserved.
3 * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.
1c79356b 4 *
2d21ac55 5 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 6 *
2d21ac55
A
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.
8f6c56a5 15 *
2d21ac55
A
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
8f6c56a5
A
21 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
22 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
8f6c56a5 26 *
2d21ac55 27 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b 28 */
1c79356b 29
1c79356b
A
30#include <IOKit/IOLib.h>
31#include <IOKit/IOService.h>
32#include <IOKit/IOPlatformExpert.h>
91447636 33#include <IOKit/IODeviceTreeSupport.h>
1c79356b
A
34#include <IOKit/IOInterrupts.h>
35#include <IOKit/IOInterruptController.h>
060df5ea
A
36#include <IOKit/IOKitDebug.h>
37#include <IOKit/IOTimeStamp.h>
38
1c79356b 39
1c79356b
A
40/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
41
42#define super IOService
43
44OSDefineMetaClassAndAbstractStructors(IOInterruptController, IOService);
45
46OSMetaClassDefineReservedUnused(IOInterruptController, 0);
47OSMetaClassDefineReservedUnused(IOInterruptController, 1);
48OSMetaClassDefineReservedUnused(IOInterruptController, 2);
49OSMetaClassDefineReservedUnused(IOInterruptController, 3);
50OSMetaClassDefineReservedUnused(IOInterruptController, 4);
51OSMetaClassDefineReservedUnused(IOInterruptController, 5);
52
53/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
54
55IOReturn IOInterruptController::registerInterrupt(IOService *nub, int source,
56 void *target,
57 IOInterruptHandler handler,
58 void *refCon)
59{
60 IOInterruptSource *interruptSources;
b0d623f7 61 IOInterruptVectorNumber vectorNumber;
1c79356b 62 IOInterruptVector *vector;
b0d623f7 63 int wasDisabledSoft;
1c79356b
A
64 IOReturn error;
65 OSData *vectorData;
91447636
A
66 IOOptionBits options;
67 bool canBeShared, shouldBeShared, wasAlreadyRegisterd;
b0d623f7
A
68
69 IOService *originalNub = NULL; // Protected by wasAlreadyRegisterd
70 int originalSource = 0; // Protected by wasAlreadyRegisterd
71
72
1c79356b
A
73 interruptSources = nub->_interruptSources;
74 vectorData = interruptSources[source].vectorData;
b0d623f7 75 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
1c79356b
A
76 vector = &vectors[vectorNumber];
77
78 // Get the lock for this vector.
060df5ea 79 IOLockLock(vector->interruptLock);
1c79356b 80
91447636
A
81 // Check if the interrupt source can/should be shared.
82 canBeShared = vectorCanBeShared(vectorNumber, vector);
83 IODTGetInterruptOptions(nub, source, &options);
cf7d32b8
A
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
91447636
A
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) {
060df5ea 98 IOLockUnlock(vector->interruptLock);
91447636
A
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,
1c79356b 104 // register as a shared interrupt.
91447636 105 if (wasAlreadyRegisterd || shouldBeShared) {
1c79356b
A
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) {
060df5ea 111 IOLockUnlock(vector->interruptLock);
1c79356b
A
112 return kIOReturnNoMemory;
113 }
114
91447636
A
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 }
1c79356b
A
125
126 // Initialize the new shared interrupt controller.
91447636 127 error = vector->sharedController->initInterruptController(this, vectorData);
1c79356b 128 // If the IOSharedInterruptController could not be initalized,
91447636 129 // if needed, put the original consumer's interrupt back to normal and
1c79356b
A
130 // get rid of whats left of the shared controller.
131 if (error != kIOReturnSuccess) {
91447636 132 if (wasAlreadyRegisterd) enableInterrupt(originalNub, originalSource);
1c79356b
A
133 vector->sharedController->release();
134 vector->sharedController = 0;
060df5ea 135 IOLockUnlock(vector->interruptLock);
1c79356b
A
136 return error;
137 }
138
91447636
A
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;
060df5ea 163 IOLockUnlock(vector->interruptLock);
91447636
A
164 return error;
165 }
1c79356b
A
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
91447636
A
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);
ac5ea4a9
A
182
183 // Make the interrupt really hard disabled.
184 vector->interruptDisabledSoft = 1;
185 vector->interruptDisabledHard = 1;
91447636 186 vector->interruptRegistered = 1;
ac5ea4a9 187
1c79356b 188 // Enable the original consumer's interrupt if needed.
b0d623f7 189 // originalNub is protected by wasAlreadyRegisterd here (see line 184).
1c79356b
A
190 if (!wasDisabledSoft) originalNub->enableInterrupt(originalSource);
191 }
192
193 error = vector->sharedController->registerInterrupt(nub, source, target,
194 handler, refCon);
060df5ea 195 IOLockUnlock(vector->interruptLock);
1c79356b
A
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
060df5ea 214 IOLockUnlock(vector->interruptLock);
1c79356b
A
215 return kIOReturnSuccess;
216}
217
218IOReturn IOInterruptController::unregisterInterrupt(IOService *nub, int source)
219{
220 IOInterruptSource *interruptSources;
b0d623f7 221 IOInterruptVectorNumber vectorNumber;
1c79356b
A
222 IOInterruptVector *vector;
223 OSData *vectorData;
224
225 interruptSources = nub->_interruptSources;
226 vectorData = interruptSources[source].vectorData;
b0d623f7 227 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
1c79356b
A
228 vector = &vectors[vectorNumber];
229
230 // Get the lock for this vector.
060df5ea 231 IOLockLock(vector->interruptLock);
1c79356b
A
232
233 // Return success if it is not already registered
234 if (!vector->interruptRegistered) {
060df5ea 235 IOLockUnlock(vector->interruptLock);
1c79356b
A
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
060df5ea 256 IOLockUnlock(vector->interruptLock);
1c79356b
A
257 return kIOReturnSuccess;
258}
259
260IOReturn IOInterruptController::getInterruptType(IOService *nub, int source,
261 int *interruptType)
262{
263 IOInterruptSource *interruptSources;
b0d623f7 264 IOInterruptVectorNumber vectorNumber;
1c79356b
A
265 IOInterruptVector *vector;
266 OSData *vectorData;
267
268 if (interruptType == 0) return kIOReturnBadArgument;
269
270 interruptSources = nub->_interruptSources;
271 vectorData = interruptSources[source].vectorData;
b0d623f7 272 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
1c79356b
A
273 vector = &vectors[vectorNumber];
274
275 *interruptType = getVectorType(vectorNumber, vector);
276
277 return kIOReturnSuccess;
278}
279
280IOReturn IOInterruptController::enableInterrupt(IOService *nub, int source)
281{
282 IOInterruptSource *interruptSources;
b0d623f7 283 IOInterruptVectorNumber vectorNumber;
1c79356b
A
284 IOInterruptVector *vector;
285 OSData *vectorData;
286
287 interruptSources = nub->_interruptSources;
288 vectorData = interruptSources[source].vectorData;
b0d623f7 289 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
1c79356b
A
290 vector = &vectors[vectorNumber];
291
292 if (vector->interruptDisabledSoft) {
293 vector->interruptDisabledSoft = 0;
39236c6e
A
294#if !defined(__i386__) && !defined(__x86_64__)
295 OSMemoryBarrier();
296#endif
297
0b4e3aa0 298 if (!getPlatform()->atInterruptLevel()) {
b0d623f7
A
299 while (vector->interruptActive)
300 {}
0b4e3aa0 301 }
1c79356b
A
302 if (vector->interruptDisabledHard) {
303 vector->interruptDisabledHard = 0;
304
305 enableVector(vectorNumber, vector);
306 }
307 }
308
309 return kIOReturnSuccess;
310}
311
312IOReturn IOInterruptController::disableInterrupt(IOService *nub, int source)
313{
314 IOInterruptSource *interruptSources;
b0d623f7 315 IOInterruptVectorNumber vectorNumber;
1c79356b
A
316 IOInterruptVector *vector;
317 OSData *vectorData;
318
319 interruptSources = nub->_interruptSources;
320 vectorData = interruptSources[source].vectorData;
b0d623f7 321 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
1c79356b
A
322 vector = &vectors[vectorNumber];
323
324 vector->interruptDisabledSoft = 1;
39236c6e
A
325#if !defined(__i386__) && !defined(__x86_64__)
326 OSMemoryBarrier();
327#endif
1c79356b
A
328
329 if (!getPlatform()->atInterruptLevel()) {
b0d623f7
A
330 while (vector->interruptActive)
331 {}
1c79356b
A
332 }
333
334 return kIOReturnSuccess;
335}
336
337IOReturn IOInterruptController::causeInterrupt(IOService *nub, int source)
338{
339 IOInterruptSource *interruptSources;
b0d623f7 340 IOInterruptVectorNumber vectorNumber;
1c79356b
A
341 IOInterruptVector *vector;
342 OSData *vectorData;
343
344 interruptSources = nub->_interruptSources;
345 vectorData = interruptSources[source].vectorData;
b0d623f7 346 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
1c79356b
A
347 vector = &vectors[vectorNumber];
348
349 causeVector(vectorNumber, vector);
350
351 return kIOReturnSuccess;
352}
353
354IOInterruptAction IOInterruptController::getInterruptHandlerAddress(void)
355{
356 return 0;
357}
358
359IOReturn 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
b0d623f7 368bool IOInterruptController::vectorCanBeShared(IOInterruptVectorNumber /*vectorNumber*/,
1c79356b
A
369 IOInterruptVector */*vector*/)
370{
371 return false;
372}
373
b0d623f7 374void IOInterruptController::initVector(IOInterruptVectorNumber /*vectorNumber*/,
1c79356b
A
375 IOInterruptVector */*vector*/)
376{
377}
378
b0d623f7 379int IOInterruptController::getVectorType(IOInterruptVectorNumber /*vectorNumber*/,
1c79356b
A
380 IOInterruptVector */*vector*/)
381{
382 return kIOInterruptTypeEdge;
383}
384
b0d623f7 385void IOInterruptController::disableVectorHard(IOInterruptVectorNumber /*vectorNumber*/,
1c79356b
A
386 IOInterruptVector */*vector*/)
387{
388}
389
b0d623f7 390void IOInterruptController::enableVector(IOInterruptVectorNumber /*vectorNumber*/,
1c79356b
A
391 IOInterruptVector */*vector*/)
392{
393}
394
b0d623f7 395void IOInterruptController::causeVector(IOInterruptVectorNumber /*vectorNumber*/,
1c79356b
A
396 IOInterruptVector */*vector*/)
397{
398}
399
400
401/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
402
403#undef super
404#define super IOInterruptController
405
406OSDefineMetaClassAndStructors(IOSharedInterruptController, IOInterruptController);
407
408OSMetaClassDefineReservedUnused(IOSharedInterruptController, 0);
409OSMetaClassDefineReservedUnused(IOSharedInterruptController, 1);
410OSMetaClassDefineReservedUnused(IOSharedInterruptController, 2);
411OSMetaClassDefineReservedUnused(IOSharedInterruptController, 3);
412
413/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
414
91447636
A
415#define kIOSharedInterruptControllerDefaultVectors (128)
416
1c79356b
A
417IOReturn IOSharedInterruptController::initInterruptController(IOInterruptController *parentController, OSData *parentSource)
418{
419 int cnt, interruptType;
420 IOReturn error;
39236c6e
A
421
422 reserved = NULL;
1c79356b
A
423
424 if (!super::init())
425 return kIOReturnNoResources;
426
427 // Set provider to this so enable/disable nub stuff works.
428 provider = this;
429
430 // Allocate the IOInterruptSource so this can act like a nub.
431 _interruptSources = (IOInterruptSource *)IOMalloc(sizeof(IOInterruptSource));
432 if (_interruptSources == 0) return kIOReturnNoMemory;
433 _numInterruptSources = 1;
434
435 // Set up the IOInterruptSource to point at this.
0c530ab8
A
436 parentController->retain();
437 parentSource->retain();
1c79356b
A
438 _interruptSources[0].interruptController = parentController;
439 _interruptSources[0].vectorData = parentSource;
440
441 sourceIsLevel = false;
442 error = provider->getInterruptType(0, &interruptType);
443 if (error == kIOReturnSuccess) {
444 if (interruptType & kIOInterruptTypeLevel)
445 sourceIsLevel = true;
446 }
447
448 // Allocate the memory for the vectors
91447636 449 numVectors = kIOSharedInterruptControllerDefaultVectors; // For now a constant number.
1c79356b
A
450 vectors = (IOInterruptVector *)IOMalloc(numVectors * sizeof(IOInterruptVector));
451 if (vectors == NULL) {
452 IOFree(_interruptSources, sizeof(IOInterruptSource));
453 return kIOReturnNoMemory;
454 }
455 bzero(vectors, numVectors * sizeof(IOInterruptVector));
456
457 // Allocate the lock for the controller.
458 controllerLock = IOSimpleLockAlloc();
459 if (controllerLock == 0) return kIOReturnNoResources;
460
461 // Allocate locks for the vectors.
462 for (cnt = 0; cnt < numVectors; cnt++) {
463 vectors[cnt].interruptLock = IOLockAlloc();
464 if (vectors[cnt].interruptLock == NULL) {
465 for (cnt = 0; cnt < numVectors; cnt++) {
466 if (vectors[cnt].interruptLock != NULL)
467 IOLockFree(vectors[cnt].interruptLock);
468 }
469 return kIOReturnNoResources;
470 }
471 }
472
91447636 473 numVectors = 0; // reset the high water mark for used vectors
1c79356b
A
474 vectorsRegistered = 0;
475 vectorsEnabled = 0;
476 controllerDisabled = 1;
477
478 return kIOReturnSuccess;
479}
480
481IOReturn IOSharedInterruptController::registerInterrupt(IOService *nub,
482 int source,
483 void *target,
484 IOInterruptHandler handler,
485 void *refCon)
486{
487 IOInterruptSource *interruptSources;
b0d623f7 488 IOInterruptVectorNumber vectorNumber;
1c79356b
A
489 IOInterruptVector *vector = 0;
490 OSData *vectorData;
491 IOInterruptState interruptState;
492
493 interruptSources = nub->_interruptSources;
494
495 // Find a free vector.
91447636
A
496 vectorNumber = kIOSharedInterruptControllerDefaultVectors;
497 while (vectorsRegistered != kIOSharedInterruptControllerDefaultVectors) {
498 for (vectorNumber = 0; vectorNumber < kIOSharedInterruptControllerDefaultVectors; vectorNumber++) {
1c79356b
A
499 vector = &vectors[vectorNumber];
500
501 // Get the lock for this vector.
060df5ea 502 IOLockLock(vector->interruptLock);
1c79356b
A
503
504 // Is it unregistered?
505 if (!vector->interruptRegistered) break;
506
507 // Move along to the next one.
060df5ea 508 IOLockUnlock(vector->interruptLock);
1c79356b
A
509 }
510
91447636 511 if (vectorNumber != kIOSharedInterruptControllerDefaultVectors) break;
1c79356b
A
512 }
513
514 // Could not find a free one, so give up.
91447636 515 if (vectorNumber == kIOSharedInterruptControllerDefaultVectors) {
1c79356b
A
516 return kIOReturnNoResources;
517 }
518
519 // Create the vectorData for the IOInterruptSource.
520 vectorData = OSData::withBytes(&vectorNumber, sizeof(vectorNumber));
521 if (vectorData == 0) {
39037602 522 IOLockUnlock(vector->interruptLock);
1c79356b
A
523 return kIOReturnNoMemory;
524 }
525
526 // Fill in the IOInterruptSource with the controller's info.
527 interruptSources[source].interruptController = this;
528 interruptSources[source].vectorData = vectorData;
529
530 // Fill in vector with the client's info.
531 vector->handler = handler;
532 vector->nub = nub;
533 vector->source = source;
534 vector->target = target;
535 vector->refCon = refCon;
536
91447636 537 // Get the vector ready. It starts off soft disabled.
1c79356b
A
538 vector->interruptDisabledSoft = 1;
539 vector->interruptRegistered = 1;
540
541 interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
91447636
A
542 // Move the high water mark if needed
543 if (++vectorsRegistered > numVectors) numVectors = vectorsRegistered;
1c79356b
A
544 IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
545
060df5ea 546 IOLockUnlock(vector->interruptLock);
1c79356b
A
547 return kIOReturnSuccess;
548}
549
550IOReturn IOSharedInterruptController::unregisterInterrupt(IOService *nub,
551 int source)
552{
b0d623f7 553 IOInterruptVectorNumber vectorNumber;
1c79356b 554 IOInterruptVector *vector;
91447636 555 IOInterruptState interruptState;
b0d623f7
A
556
557 for (vectorNumber = 0; vectorNumber < kIOSharedInterruptControllerDefaultVectors; vectorNumber++) {
558 vector = &vectors[vectorNumber];
559
560 // Get the lock for this vector.
060df5ea 561 IOLockLock(vector->interruptLock);
b0d623f7
A
562
563 // Return success if it is not already registered
564 if (!vector->interruptRegistered
565 || (vector->nub != nub) || (vector->source != source)) {
060df5ea 566 IOLockUnlock(vector->interruptLock);
b0d623f7
A
567 continue;
568 }
569
570 // Soft disable the source and the controller too.
571 disableInterrupt(nub, source);
572
573 // Clear all the storage for the vector except for interruptLock.
574 vector->interruptActive = 0;
575 vector->interruptDisabledSoft = 0;
576 vector->interruptDisabledHard = 0;
577 vector->interruptRegistered = 0;
578 vector->nub = 0;
579 vector->source = 0;
580 vector->handler = 0;
581 vector->target = 0;
582 vector->refCon = 0;
583
584 interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
585 vectorsRegistered--;
586 IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
587
588 // Move along to the next one.
060df5ea 589 IOLockUnlock(vector->interruptLock);
1c79356b 590 }
b0d623f7 591
91447636
A
592 // Re-enable the controller if all vectors are enabled.
593 if (vectorsEnabled == vectorsRegistered) {
594 controllerDisabled = 0;
595 provider->enableInterrupt(0);
596 }
b0d623f7 597
1c79356b
A
598 return kIOReturnSuccess;
599}
600
601IOReturn IOSharedInterruptController::getInterruptType(IOService */*nub*/,
602 int /*source*/,
603 int *interruptType)
604{
605 return provider->getInterruptType(0, interruptType);
606}
607
608IOReturn IOSharedInterruptController::enableInterrupt(IOService *nub,
609 int source)
610{
611 IOInterruptSource *interruptSources;
b0d623f7 612 IOInterruptVectorNumber vectorNumber;
1c79356b
A
613 IOInterruptVector *vector;
614 OSData *vectorData;
14353aa8 615 IOInterruptState interruptState;
1c79356b
A
616
617 interruptSources = nub->_interruptSources;
618 vectorData = interruptSources[source].vectorData;
b0d623f7 619 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
1c79356b
A
620 vector = &vectors[vectorNumber];
621
14353aa8
A
622 interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
623 if (!vector->interruptDisabledSoft) {
1c79356b 624 IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
14353aa8
A
625 return kIOReturnSuccess;
626 }
627
628 vector->interruptDisabledSoft = 0;
629 vectorsEnabled++;
630 IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
631
632 if (controllerDisabled && (vectorsEnabled == vectorsRegistered)) {
633 controllerDisabled = 0;
634 provider->enableInterrupt(0);
1c79356b
A
635 }
636
637 return kIOReturnSuccess;
638}
639
640IOReturn IOSharedInterruptController::disableInterrupt(IOService *nub,
641 int source)
642{
643 IOInterruptSource *interruptSources;
b0d623f7 644 IOInterruptVectorNumber vectorNumber;
1c79356b
A
645 IOInterruptVector *vector;
646 OSData *vectorData;
14353aa8 647 IOInterruptState interruptState;
1c79356b
A
648
649 interruptSources = nub->_interruptSources;
650 vectorData = interruptSources[source].vectorData;
b0d623f7 651 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
1c79356b
A
652 vector = &vectors[vectorNumber];
653
14353aa8 654 interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
1c79356b
A
655 if (!vector->interruptDisabledSoft) {
656 vector->interruptDisabledSoft = 1;
39236c6e
A
657#if !defined(__i386__) && !defined(__x86_64__)
658 OSMemoryBarrier();
659#endif
660
1c79356b 661 vectorsEnabled--;
1c79356b 662 }
14353aa8 663 IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
1c79356b
A
664
665 if (!getPlatform()->atInterruptLevel()) {
b0d623f7
A
666 while (vector->interruptActive)
667 {}
1c79356b
A
668 }
669
670 return kIOReturnSuccess;
671}
672
673IOInterruptAction IOSharedInterruptController::getInterruptHandlerAddress(void)
674{
0c530ab8
A
675 return OSMemberFunctionCast(IOInterruptAction,
676 this, &IOSharedInterruptController::handleInterrupt);
1c79356b
A
677}
678
679IOReturn IOSharedInterruptController::handleInterrupt(void * /*refCon*/,
680 IOService * nub,
681 int /*source*/)
682{
b0d623f7 683 IOInterruptVectorNumber vectorNumber;
1c79356b
A
684 IOInterruptVector *vector;
685
686 for (vectorNumber = 0; vectorNumber < numVectors; vectorNumber++) {
687 vector = &vectors[vectorNumber];
688
689 vector->interruptActive = 1;
39236c6e
A
690#if !defined(__i386__) && !defined(__x86_64__)
691 OSMemoryBarrier();
692#endif
693
6d2010ae
A
694 if (!vector->interruptDisabledSoft) {
695
696 // Call the handler if it exists.
697 if (vector->interruptRegistered) {
698
699 bool trace = (gIOKitTrace & kIOTraceInterrupts) ? true : false;
060df5ea
A
700
701 if (trace)
702 IOTimeStampStartConstant(IODBG_INTC(IOINTC_HANDLER),
703 (uintptr_t) vectorNumber, (uintptr_t) vector->handler, (uintptr_t)vector->target);
704
060df5ea
A
705 // Call handler.
706 vector->handler(vector->target, vector->refCon, vector->nub, vector->source);
060df5ea
A
707
708 if (trace)
709 IOTimeStampEndConstant(IODBG_INTC(IOINTC_HANDLER),
710 (uintptr_t) vectorNumber, (uintptr_t) vector->handler, (uintptr_t)vector->target);
711
6d2010ae
A
712 }
713 }
1c79356b
A
714
715 vector->interruptActive = 0;
716 }
717
718 // if any of the vectors are dissabled, then dissable this controller.
719 IOSimpleLockLock(controllerLock);
720 if (vectorsEnabled != vectorsRegistered) {
721 nub->disableInterrupt(0);
722 controllerDisabled = 1;
723 }
724 IOSimpleLockUnlock(controllerLock);
725
726 return kIOReturnSuccess;
727}
728