2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
31 #include <ppc/proc_reg.h>
34 #include <IOKit/IOLib.h>
35 #include <IOKit/IOService.h>
36 #include <IOKit/IOPlatformExpert.h>
37 #include <IOKit/IODeviceTreeSupport.h>
38 #include <IOKit/IOInterrupts.h>
39 #include <IOKit/IOInterruptController.h>
42 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
44 #define super IOService
46 OSDefineMetaClassAndAbstractStructors(IOInterruptController
, IOService
);
48 OSMetaClassDefineReservedUnused(IOInterruptController
, 0);
49 OSMetaClassDefineReservedUnused(IOInterruptController
, 1);
50 OSMetaClassDefineReservedUnused(IOInterruptController
, 2);
51 OSMetaClassDefineReservedUnused(IOInterruptController
, 3);
52 OSMetaClassDefineReservedUnused(IOInterruptController
, 4);
53 OSMetaClassDefineReservedUnused(IOInterruptController
, 5);
55 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
57 IOReturn
IOInterruptController::registerInterrupt(IOService
*nub
, int source
,
59 IOInterruptHandler handler
,
62 IOInterruptSource
*interruptSources
;
64 IOInterruptVector
*vector
;
68 IOService
*originalNub
;
71 bool canBeShared
, shouldBeShared
, wasAlreadyRegisterd
;
73 interruptSources
= nub
->_interruptSources
;
74 vectorData
= interruptSources
[source
].vectorData
;
75 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
76 vector
= &vectors
[vectorNumber
];
78 // Get the lock for this vector.
79 IOTakeLock(vector
->interruptLock
);
81 // Check if the interrupt source can/should be shared.
82 canBeShared
= vectorCanBeShared(vectorNumber
, vector
);
83 IODTGetInterruptOptions(nub
, source
, &options
);
84 shouldBeShared
= canBeShared
&& (options
& kIODTInterruptShared
);
85 wasAlreadyRegisterd
= vector
->interruptRegistered
;
87 // If the vector is registered and can not be shared return error.
88 if (wasAlreadyRegisterd
&& !canBeShared
) {
89 IOUnlock(vector
->interruptLock
);
90 return kIOReturnNoResources
;
93 // If this vector is already in use, and can be shared (implied),
94 // or it is not registered and should be shared,
95 // register as a shared interrupt.
96 if (wasAlreadyRegisterd
|| shouldBeShared
) {
97 // If this vector is not already shared, break it out.
98 if (vector
->sharedController
== 0) {
99 // Make the IOShareInterruptController instance
100 vector
->sharedController
= new IOSharedInterruptController
;
101 if (vector
->sharedController
== 0) {
102 IOUnlock(vector
->interruptLock
);
103 return kIOReturnNoMemory
;
106 if (wasAlreadyRegisterd
) {
107 // Save the nub and source for the original consumer.
108 originalNub
= vector
->nub
;
109 originalSource
= vector
->source
;
111 // Physically disable the interrupt, but mark it as being enabled in the hardware.
112 // The interruptDisabledSoft now indicates the driver's request for enablement.
113 disableVectorHard(vectorNumber
, vector
);
114 vector
->interruptDisabledHard
= 0;
117 // Initialize the new shared interrupt controller.
118 error
= vector
->sharedController
->initInterruptController(this, vectorData
);
119 // If the IOSharedInterruptController could not be initalized,
120 // if needed, put the original consumer's interrupt back to normal and
121 // get rid of whats left of the shared controller.
122 if (error
!= kIOReturnSuccess
) {
123 if (wasAlreadyRegisterd
) enableInterrupt(originalNub
, originalSource
);
124 vector
->sharedController
->release();
125 vector
->sharedController
= 0;
126 IOUnlock(vector
->interruptLock
);
130 // If there was an original consumer try to register it on the shared controller.
131 if (wasAlreadyRegisterd
) {
132 error
= vector
->sharedController
->registerInterrupt(originalNub
,
137 // If the original consumer could not be moved to the shared controller,
138 // put the original consumor's interrupt back to normal and
139 // get rid of whats left of the shared controller.
140 if (error
!= kIOReturnSuccess
) {
141 // Save the driver's interrupt enablement state.
142 wasDisabledSoft
= vector
->interruptDisabledSoft
;
144 // Make the interrupt really hard disabled.
145 vector
->interruptDisabledSoft
= 1;
146 vector
->interruptDisabledHard
= 1;
148 // Enable the original consumer's interrupt if needed.
149 if (!wasDisabledSoft
) originalNub
->enableInterrupt(originalSource
);
150 enableInterrupt(originalNub
, originalSource
);
152 vector
->sharedController
->release();
153 vector
->sharedController
= 0;
154 IOUnlock(vector
->interruptLock
);
159 // Fill in vector with the shared controller's info.
160 vector
->handler
= (IOInterruptHandler
)vector
->sharedController
->getInterruptHandlerAddress();
161 vector
->nub
= vector
->sharedController
;
163 vector
->target
= vector
->sharedController
;
166 // If the interrupt was already registered,
167 // save the driver's interrupt enablement state.
168 if (wasAlreadyRegisterd
) wasDisabledSoft
= vector
->interruptDisabledSoft
;
169 else wasDisabledSoft
= true;
171 // Do any specific initalization for this vector if it has not yet been used.
172 if (!wasAlreadyRegisterd
) initVector(vectorNumber
, vector
);
174 // Make the interrupt really hard disabled.
175 vector
->interruptDisabledSoft
= 1;
176 vector
->interruptDisabledHard
= 1;
177 vector
->interruptRegistered
= 1;
179 // Enable the original consumer's interrupt if needed.
180 if (!wasDisabledSoft
) originalNub
->enableInterrupt(originalSource
);
183 error
= vector
->sharedController
->registerInterrupt(nub
, source
, target
,
185 IOUnlock(vector
->interruptLock
);
189 // Fill in vector with the client's info.
190 vector
->handler
= handler
;
192 vector
->source
= source
;
193 vector
->target
= target
;
194 vector
->refCon
= refCon
;
196 // Do any specific initalization for this vector.
197 initVector(vectorNumber
, vector
);
199 // Get the vector ready. It starts hard disabled.
200 vector
->interruptDisabledHard
= 1;
201 vector
->interruptDisabledSoft
= 1;
202 vector
->interruptRegistered
= 1;
204 IOUnlock(vector
->interruptLock
);
205 return kIOReturnSuccess
;
208 IOReturn
IOInterruptController::unregisterInterrupt(IOService
*nub
, int source
)
210 IOInterruptSource
*interruptSources
;
212 IOInterruptVector
*vector
;
215 interruptSources
= nub
->_interruptSources
;
216 vectorData
= interruptSources
[source
].vectorData
;
217 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
218 vector
= &vectors
[vectorNumber
];
220 // Get the lock for this vector.
221 IOTakeLock(vector
->interruptLock
);
223 // Return success if it is not already registered
224 if (!vector
->interruptRegistered
) {
225 IOUnlock(vector
->interruptLock
);
226 return kIOReturnSuccess
;
229 // Soft disable the source.
230 disableInterrupt(nub
, source
);
232 // Turn the source off at hardware.
233 disableVectorHard(vectorNumber
, vector
);
235 // Clear all the storage for the vector except for interruptLock.
236 vector
->interruptActive
= 0;
237 vector
->interruptDisabledSoft
= 0;
238 vector
->interruptDisabledHard
= 0;
239 vector
->interruptRegistered
= 0;
246 IOUnlock(vector
->interruptLock
);
247 return kIOReturnSuccess
;
250 IOReturn
IOInterruptController::getInterruptType(IOService
*nub
, int source
,
253 IOInterruptSource
*interruptSources
;
255 IOInterruptVector
*vector
;
258 if (interruptType
== 0) return kIOReturnBadArgument
;
260 interruptSources
= nub
->_interruptSources
;
261 vectorData
= interruptSources
[source
].vectorData
;
262 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
263 vector
= &vectors
[vectorNumber
];
265 *interruptType
= getVectorType(vectorNumber
, vector
);
267 return kIOReturnSuccess
;
270 IOReturn
IOInterruptController::enableInterrupt(IOService
*nub
, int source
)
272 IOInterruptSource
*interruptSources
;
274 IOInterruptVector
*vector
;
277 interruptSources
= nub
->_interruptSources
;
278 vectorData
= interruptSources
[source
].vectorData
;
279 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
280 vector
= &vectors
[vectorNumber
];
282 if (vector
->interruptDisabledSoft
) {
283 vector
->interruptDisabledSoft
= 0;
289 if (!getPlatform()->atInterruptLevel()) {
290 while (vector
->interruptActive
);
295 if (vector
->interruptDisabledHard
) {
296 vector
->interruptDisabledHard
= 0;
298 enableVector(vectorNumber
, vector
);
302 return kIOReturnSuccess
;
305 IOReturn
IOInterruptController::disableInterrupt(IOService
*nub
, int source
)
307 IOInterruptSource
*interruptSources
;
309 IOInterruptVector
*vector
;
312 interruptSources
= nub
->_interruptSources
;
313 vectorData
= interruptSources
[source
].vectorData
;
314 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
315 vector
= &vectors
[vectorNumber
];
317 vector
->interruptDisabledSoft
= 1;
323 if (!getPlatform()->atInterruptLevel()) {
324 while (vector
->interruptActive
);
330 return kIOReturnSuccess
;
333 IOReturn
IOInterruptController::causeInterrupt(IOService
*nub
, int source
)
335 IOInterruptSource
*interruptSources
;
337 IOInterruptVector
*vector
;
340 interruptSources
= nub
->_interruptSources
;
341 vectorData
= interruptSources
[source
].vectorData
;
342 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
343 vector
= &vectors
[vectorNumber
];
345 causeVector(vectorNumber
, vector
);
347 return kIOReturnSuccess
;
350 IOInterruptAction
IOInterruptController::getInterruptHandlerAddress(void)
355 IOReturn
IOInterruptController::handleInterrupt(void *refCon
, IOService
*nub
,
358 return kIOReturnInvalid
;
362 // Methods to be overridden for simplifed interrupt controller subclasses.
364 bool IOInterruptController::vectorCanBeShared(long /*vectorNumber*/,
365 IOInterruptVector */
*vector*/
)
370 void IOInterruptController::initVector(long /*vectorNumber*/,
371 IOInterruptVector */
*vector*/
)
375 int IOInterruptController::getVectorType(long /*vectorNumber*/,
376 IOInterruptVector */
*vector*/
)
378 return kIOInterruptTypeEdge
;
381 void IOInterruptController::disableVectorHard(long /*vectorNumber*/,
382 IOInterruptVector */
*vector*/
)
386 void IOInterruptController::enableVector(long /*vectorNumber*/,
387 IOInterruptVector */
*vector*/
)
391 void IOInterruptController::causeVector(long /*vectorNumber*/,
392 IOInterruptVector */
*vector*/
)
397 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
400 #define super IOInterruptController
402 OSDefineMetaClassAndStructors(IOSharedInterruptController
, IOInterruptController
);
404 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 0);
405 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 1);
406 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 2);
407 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 3);
409 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
411 #define kIOSharedInterruptControllerDefaultVectors (128)
413 IOReturn
IOSharedInterruptController::initInterruptController(IOInterruptController
*parentController
, OSData
*parentSource
)
415 int cnt
, interruptType
;
419 return kIOReturnNoResources
;
421 // Set provider to this so enable/disable nub stuff works.
424 // Allocate the IOInterruptSource so this can act like a nub.
425 _interruptSources
= (IOInterruptSource
*)IOMalloc(sizeof(IOInterruptSource
));
426 if (_interruptSources
== 0) return kIOReturnNoMemory
;
427 _numInterruptSources
= 1;
429 // Set up the IOInterruptSource to point at this.
430 _interruptSources
[0].interruptController
= parentController
;
431 _interruptSources
[0].vectorData
= parentSource
;
433 sourceIsLevel
= false;
434 error
= provider
->getInterruptType(0, &interruptType
);
435 if (error
== kIOReturnSuccess
) {
436 if (interruptType
& kIOInterruptTypeLevel
)
437 sourceIsLevel
= true;
440 // Allocate the memory for the vectors
441 numVectors
= kIOSharedInterruptControllerDefaultVectors
; // For now a constant number.
442 vectors
= (IOInterruptVector
*)IOMalloc(numVectors
* sizeof(IOInterruptVector
));
443 if (vectors
== NULL
) {
444 IOFree(_interruptSources
, sizeof(IOInterruptSource
));
445 return kIOReturnNoMemory
;
447 bzero(vectors
, numVectors
* sizeof(IOInterruptVector
));
449 // Allocate the lock for the controller.
450 controllerLock
= IOSimpleLockAlloc();
451 if (controllerLock
== 0) return kIOReturnNoResources
;
453 // Allocate locks for the vectors.
454 for (cnt
= 0; cnt
< numVectors
; cnt
++) {
455 vectors
[cnt
].interruptLock
= IOLockAlloc();
456 if (vectors
[cnt
].interruptLock
== NULL
) {
457 for (cnt
= 0; cnt
< numVectors
; cnt
++) {
458 if (vectors
[cnt
].interruptLock
!= NULL
)
459 IOLockFree(vectors
[cnt
].interruptLock
);
461 return kIOReturnNoResources
;
465 numVectors
= 0; // reset the high water mark for used vectors
466 vectorsRegistered
= 0;
468 controllerDisabled
= 1;
470 return kIOReturnSuccess
;
473 IOReturn
IOSharedInterruptController::registerInterrupt(IOService
*nub
,
476 IOInterruptHandler handler
,
479 IOInterruptSource
*interruptSources
;
481 IOInterruptVector
*vector
= 0;
483 IOInterruptState interruptState
;
485 interruptSources
= nub
->_interruptSources
;
487 // Find a free vector.
488 vectorNumber
= kIOSharedInterruptControllerDefaultVectors
;
489 while (vectorsRegistered
!= kIOSharedInterruptControllerDefaultVectors
) {
490 for (vectorNumber
= 0; vectorNumber
< kIOSharedInterruptControllerDefaultVectors
; vectorNumber
++) {
491 vector
= &vectors
[vectorNumber
];
493 // Get the lock for this vector.
494 IOTakeLock(vector
->interruptLock
);
496 // Is it unregistered?
497 if (!vector
->interruptRegistered
) break;
499 // Move along to the next one.
500 IOUnlock(vector
->interruptLock
);
503 if (vectorNumber
!= kIOSharedInterruptControllerDefaultVectors
) break;
506 // Could not find a free one, so give up.
507 if (vectorNumber
== kIOSharedInterruptControllerDefaultVectors
) {
508 return kIOReturnNoResources
;
511 // Create the vectorData for the IOInterruptSource.
512 vectorData
= OSData::withBytes(&vectorNumber
, sizeof(vectorNumber
));
513 if (vectorData
== 0) {
514 return kIOReturnNoMemory
;
517 // Fill in the IOInterruptSource with the controller's info.
518 interruptSources
[source
].interruptController
= this;
519 interruptSources
[source
].vectorData
= vectorData
;
521 // Fill in vector with the client's info.
522 vector
->handler
= handler
;
524 vector
->source
= source
;
525 vector
->target
= target
;
526 vector
->refCon
= refCon
;
528 // Get the vector ready. It starts off soft disabled.
529 vector
->interruptDisabledSoft
= 1;
530 vector
->interruptRegistered
= 1;
532 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
533 // Move the high water mark if needed
534 if (++vectorsRegistered
> numVectors
) numVectors
= vectorsRegistered
;
535 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
537 IOUnlock(vector
->interruptLock
);
538 return kIOReturnSuccess
;
541 IOReturn
IOSharedInterruptController::unregisterInterrupt(IOService
*nub
,
544 IOInterruptSource
*interruptSources
;
546 IOInterruptVector
*vector
;
548 IOInterruptState interruptState
;
550 interruptSources
= nub
->_interruptSources
;
551 vectorData
= interruptSources
[source
].vectorData
;
552 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
553 vector
= &vectors
[vectorNumber
];
555 // Get the lock for this vector.
556 IOTakeLock(vector
->interruptLock
);
558 // Return success if it is not already registered
559 if (!vector
->interruptRegistered
) {
560 IOUnlock(vector
->interruptLock
);
561 return kIOReturnSuccess
;
564 // Soft disable the source and the controller too.
565 disableInterrupt(nub
, source
);
567 // Clear all the storage for the vector except for interruptLock.
568 vector
->interruptActive
= 0;
569 vector
->interruptDisabledSoft
= 0;
570 vector
->interruptDisabledHard
= 0;
571 vector
->interruptRegistered
= 0;
578 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
580 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
582 IOUnlock(vector
->interruptLock
);
584 // Re-enable the controller if all vectors are enabled.
585 if (vectorsEnabled
== vectorsRegistered
) {
586 controllerDisabled
= 0;
587 provider
->enableInterrupt(0);
590 return kIOReturnSuccess
;
593 IOReturn
IOSharedInterruptController::getInterruptType(IOService */
*nub*/
,
597 return provider
->getInterruptType(0, interruptType
);
600 IOReturn
IOSharedInterruptController::enableInterrupt(IOService
*nub
,
603 IOInterruptSource
*interruptSources
;
605 IOInterruptVector
*vector
;
607 IOInterruptState interruptState
;
609 interruptSources
= nub
->_interruptSources
;
610 vectorData
= interruptSources
[source
].vectorData
;
611 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
612 vector
= &vectors
[vectorNumber
];
614 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
615 if (!vector
->interruptDisabledSoft
) {
616 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
617 return kIOReturnSuccess
;
620 vector
->interruptDisabledSoft
= 0;
622 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
624 if (controllerDisabled
&& (vectorsEnabled
== vectorsRegistered
)) {
625 controllerDisabled
= 0;
626 provider
->enableInterrupt(0);
629 return kIOReturnSuccess
;
632 IOReturn
IOSharedInterruptController::disableInterrupt(IOService
*nub
,
635 IOInterruptSource
*interruptSources
;
637 IOInterruptVector
*vector
;
639 IOInterruptState interruptState
;
641 interruptSources
= nub
->_interruptSources
;
642 vectorData
= interruptSources
[source
].vectorData
;
643 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
644 vector
= &vectors
[vectorNumber
];
646 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
647 if (!vector
->interruptDisabledSoft
) {
648 vector
->interruptDisabledSoft
= 1;
655 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
657 if (!getPlatform()->atInterruptLevel()) {
658 while (vector
->interruptActive
);
664 return kIOReturnSuccess
;
667 IOInterruptAction
IOSharedInterruptController::getInterruptHandlerAddress(void)
669 return (IOInterruptAction
)&IOSharedInterruptController::handleInterrupt
;
672 IOReturn
IOSharedInterruptController::handleInterrupt(void * /*refCon*/,
677 IOInterruptVector
*vector
;
679 for (vectorNumber
= 0; vectorNumber
< numVectors
; vectorNumber
++) {
680 vector
= &vectors
[vectorNumber
];
682 vector
->interruptActive
= 1;
687 if (!vector
->interruptDisabledSoft
) {
692 // Call the handler if it exists.
693 if (vector
->interruptRegistered
) {
694 vector
->handler(vector
->target
, vector
->refCon
,
695 vector
->nub
, vector
->source
);
699 vector
->interruptActive
= 0;
702 // if any of the vectors are dissabled, then dissable this controller.
703 IOSimpleLockLock(controllerLock
);
704 if (vectorsEnabled
!= vectorsRegistered
) {
705 nub
->disableInterrupt(0);
706 controllerDisabled
= 1;
708 IOSimpleLockUnlock(controllerLock
);
710 return kIOReturnSuccess
;