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