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/IOInterrupts.h>
38 #include <IOKit/IOInterruptController.h>
41 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
43 #define super IOService
45 OSDefineMetaClassAndAbstractStructors(IOInterruptController
, IOService
);
47 OSMetaClassDefineReservedUnused(IOInterruptController
, 0);
48 OSMetaClassDefineReservedUnused(IOInterruptController
, 1);
49 OSMetaClassDefineReservedUnused(IOInterruptController
, 2);
50 OSMetaClassDefineReservedUnused(IOInterruptController
, 3);
51 OSMetaClassDefineReservedUnused(IOInterruptController
, 4);
52 OSMetaClassDefineReservedUnused(IOInterruptController
, 5);
54 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
56 IOReturn
IOInterruptController::registerInterrupt(IOService
*nub
, int source
,
58 IOInterruptHandler handler
,
61 IOInterruptSource
*interruptSources
;
63 IOInterruptVector
*vector
;
67 IOService
*originalNub
;
70 interruptSources
= nub
->_interruptSources
;
71 vectorData
= interruptSources
[source
].vectorData
;
72 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
73 vector
= &vectors
[vectorNumber
];
75 // Get the lock for this vector.
76 IOTakeLock(vector
->interruptLock
);
78 // If this vector is already in use, and can be shared,
79 // register as a shared interrupt.
80 if (vector
->interruptRegistered
) {
81 if (!vectorCanBeShared(vectorNumber
, vector
)) {
82 IOUnlock(vector
->interruptLock
);
83 return kIOReturnNoResources
;
86 // If this vector is not already shared, break it out.
87 if (vector
->sharedController
== 0) {
88 // Make the IOShareInterruptController instance
89 vector
->sharedController
= new IOSharedInterruptController
;
90 if (vector
->sharedController
== 0) {
91 IOUnlock(vector
->interruptLock
);
92 return kIOReturnNoMemory
;
95 // Save the nub and source for the original consumer.
96 originalNub
= vector
->nub
;
97 originalSource
= vector
->source
;
99 // Save the dis/enable state for the original consumer's interrupt.
100 // Then disable the source
101 wasDisabledSoft
= vector
->interruptDisabledSoft
;
102 disableInterrupt(originalNub
, originalSource
);
104 // Initialize the new shared interrupt controller.
105 error
= vector
->sharedController
->initInterruptController(this,
107 // If the IOSharedInterruptController could not be initalized,
108 // put the original consumor's interrupt back to normal and
109 // get rid of whats left of the shared controller.
110 if (error
!= kIOReturnSuccess
) {
111 enableInterrupt(originalNub
, originalSource
);
112 vector
->sharedController
->release();
113 vector
->sharedController
= 0;
114 IOUnlock(vector
->interruptLock
);
118 // Try to register the original consumer on the shared controller.
119 error
= vector
->sharedController
->registerInterrupt(originalNub
,
124 // If the original consumer could not be moved to the shared controller,
125 // put the original consumor's interrupt back to normal and
126 // get rid of whats left of the shared controller.
127 if (error
!= kIOReturnSuccess
) {
128 enableInterrupt(originalNub
, originalSource
);
129 vector
->sharedController
->release();
130 vector
->sharedController
= 0;
131 IOUnlock(vector
->interruptLock
);
135 // Fill in vector with the shared controller's info.
136 vector
->handler
= (IOInterruptHandler
)vector
->sharedController
->getInterruptHandlerAddress();
137 vector
->nub
= vector
->sharedController
;
139 vector
->target
= vector
->sharedController
;
142 // Enable the original consumer's interrupt if needed.
143 if (!wasDisabledSoft
) originalNub
->enableInterrupt(originalSource
);
146 error
= vector
->sharedController
->registerInterrupt(nub
, source
, target
,
148 IOUnlock(vector
->interruptLock
);
152 // Fill in vector with the client's info.
153 vector
->handler
= handler
;
155 vector
->source
= source
;
156 vector
->target
= target
;
157 vector
->refCon
= refCon
;
159 // Do any specific initalization for this vector.
160 initVector(vectorNumber
, vector
);
162 // Get the vector ready. It starts hard disabled.
163 vector
->interruptDisabledHard
= 1;
164 vector
->interruptDisabledSoft
= 1;
165 vector
->interruptRegistered
= 1;
167 IOUnlock(vector
->interruptLock
);
168 return kIOReturnSuccess
;
171 IOReturn
IOInterruptController::unregisterInterrupt(IOService
*nub
, int source
)
173 IOInterruptSource
*interruptSources
;
175 IOInterruptVector
*vector
;
178 interruptSources
= nub
->_interruptSources
;
179 vectorData
= interruptSources
[source
].vectorData
;
180 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
181 vector
= &vectors
[vectorNumber
];
183 // Get the lock for this vector.
184 IOTakeLock(vector
->interruptLock
);
186 // Return success if it is not already registered
187 if (!vector
->interruptRegistered
) {
188 IOUnlock(vector
->interruptLock
);
189 return kIOReturnSuccess
;
192 // Soft disable the source.
193 disableInterrupt(nub
, source
);
195 // Turn the source off at hardware.
196 disableVectorHard(vectorNumber
, vector
);
198 // Clear all the storage for the vector except for interruptLock.
199 vector
->interruptActive
= 0;
200 vector
->interruptDisabledSoft
= 0;
201 vector
->interruptDisabledHard
= 0;
202 vector
->interruptRegistered
= 0;
209 IOUnlock(vector
->interruptLock
);
210 return kIOReturnSuccess
;
213 IOReturn
IOInterruptController::getInterruptType(IOService
*nub
, int source
,
216 IOInterruptSource
*interruptSources
;
218 IOInterruptVector
*vector
;
221 if (interruptType
== 0) return kIOReturnBadArgument
;
223 interruptSources
= nub
->_interruptSources
;
224 vectorData
= interruptSources
[source
].vectorData
;
225 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
226 vector
= &vectors
[vectorNumber
];
228 *interruptType
= getVectorType(vectorNumber
, vector
);
230 return kIOReturnSuccess
;
233 IOReturn
IOInterruptController::enableInterrupt(IOService
*nub
, int source
)
235 IOInterruptSource
*interruptSources
;
237 IOInterruptVector
*vector
;
240 interruptSources
= nub
->_interruptSources
;
241 vectorData
= interruptSources
[source
].vectorData
;
242 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
243 vector
= &vectors
[vectorNumber
];
245 if (vector
->interruptDisabledSoft
) {
246 vector
->interruptDisabledSoft
= 0;
252 if (!getPlatform()->atInterruptLevel()) {
253 while (vector
->interruptActive
);
258 if (vector
->interruptDisabledHard
) {
259 vector
->interruptDisabledHard
= 0;
261 enableVector(vectorNumber
, vector
);
265 return kIOReturnSuccess
;
268 IOReturn
IOInterruptController::disableInterrupt(IOService
*nub
, int source
)
270 IOInterruptSource
*interruptSources
;
272 IOInterruptVector
*vector
;
275 interruptSources
= nub
->_interruptSources
;
276 vectorData
= interruptSources
[source
].vectorData
;
277 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
278 vector
= &vectors
[vectorNumber
];
280 vector
->interruptDisabledSoft
= 1;
286 if (!getPlatform()->atInterruptLevel()) {
287 while (vector
->interruptActive
);
293 return kIOReturnSuccess
;
296 IOReturn
IOInterruptController::causeInterrupt(IOService
*nub
, int source
)
298 IOInterruptSource
*interruptSources
;
300 IOInterruptVector
*vector
;
303 interruptSources
= nub
->_interruptSources
;
304 vectorData
= interruptSources
[source
].vectorData
;
305 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
306 vector
= &vectors
[vectorNumber
];
308 causeVector(vectorNumber
, vector
);
310 return kIOReturnSuccess
;
313 IOInterruptAction
IOInterruptController::getInterruptHandlerAddress(void)
318 IOReturn
IOInterruptController::handleInterrupt(void *refCon
, IOService
*nub
,
321 return kIOReturnInvalid
;
325 // Methods to be overridden for simplifed interrupt controller subclasses.
327 bool IOInterruptController::vectorCanBeShared(long /*vectorNumber*/,
328 IOInterruptVector */
*vector*/
)
333 void IOInterruptController::initVector(long /*vectorNumber*/,
334 IOInterruptVector */
*vector*/
)
338 int IOInterruptController::getVectorType(long /*vectorNumber*/,
339 IOInterruptVector */
*vector*/
)
341 return kIOInterruptTypeEdge
;
344 void IOInterruptController::disableVectorHard(long /*vectorNumber*/,
345 IOInterruptVector */
*vector*/
)
349 void IOInterruptController::enableVector(long /*vectorNumber*/,
350 IOInterruptVector */
*vector*/
)
354 void IOInterruptController::causeVector(long /*vectorNumber*/,
355 IOInterruptVector */
*vector*/
)
360 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
363 #define super IOInterruptController
365 OSDefineMetaClassAndStructors(IOSharedInterruptController
, IOInterruptController
);
367 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 0);
368 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 1);
369 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 2);
370 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 3);
372 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
374 IOReturn
IOSharedInterruptController::initInterruptController(IOInterruptController
*parentController
, OSData
*parentSource
)
376 int cnt
, interruptType
;
380 return kIOReturnNoResources
;
382 // Set provider to this so enable/disable nub stuff works.
385 // Allocate the IOInterruptSource so this can act like a nub.
386 _interruptSources
= (IOInterruptSource
*)IOMalloc(sizeof(IOInterruptSource
));
387 if (_interruptSources
== 0) return kIOReturnNoMemory
;
388 _numInterruptSources
= 1;
390 // Set up the IOInterruptSource to point at this.
391 _interruptSources
[0].interruptController
= parentController
;
392 _interruptSources
[0].vectorData
= parentSource
;
394 sourceIsLevel
= false;
395 error
= provider
->getInterruptType(0, &interruptType
);
396 if (error
== kIOReturnSuccess
) {
397 if (interruptType
& kIOInterruptTypeLevel
)
398 sourceIsLevel
= true;
401 // Allocate the memory for the vectors
402 numVectors
= 8; // For now a constant number.
403 vectors
= (IOInterruptVector
*)IOMalloc(numVectors
* sizeof(IOInterruptVector
));
404 if (vectors
== NULL
) {
405 IOFree(_interruptSources
, sizeof(IOInterruptSource
));
406 return kIOReturnNoMemory
;
408 bzero(vectors
, numVectors
* sizeof(IOInterruptVector
));
410 // Allocate the lock for the controller.
411 controllerLock
= IOSimpleLockAlloc();
412 if (controllerLock
== 0) return kIOReturnNoResources
;
414 // Allocate locks for the vectors.
415 for (cnt
= 0; cnt
< numVectors
; cnt
++) {
416 vectors
[cnt
].interruptLock
= IOLockAlloc();
417 if (vectors
[cnt
].interruptLock
== NULL
) {
418 for (cnt
= 0; cnt
< numVectors
; cnt
++) {
419 if (vectors
[cnt
].interruptLock
!= NULL
)
420 IOLockFree(vectors
[cnt
].interruptLock
);
422 return kIOReturnNoResources
;
426 vectorsRegistered
= 0;
428 controllerDisabled
= 1;
430 return kIOReturnSuccess
;
433 IOReturn
IOSharedInterruptController::registerInterrupt(IOService
*nub
,
436 IOInterruptHandler handler
,
439 IOInterruptSource
*interruptSources
;
441 IOInterruptVector
*vector
= 0;
443 IOInterruptState interruptState
;
445 interruptSources
= nub
->_interruptSources
;
447 // Find a free vector.
448 vectorNumber
= numVectors
;
449 while (vectorsRegistered
!= numVectors
) {
450 for (vectorNumber
= 0; vectorNumber
< numVectors
; vectorNumber
++) {
451 vector
= &vectors
[vectorNumber
];
453 // Get the lock for this vector.
454 IOTakeLock(vector
->interruptLock
);
456 // Is it unregistered?
457 if (!vector
->interruptRegistered
) break;
459 // Move along to the next one.
460 IOUnlock(vector
->interruptLock
);
463 if (vectorNumber
!= numVectors
) break;
466 // Could not find a free one, so give up.
467 if (vectorNumber
== numVectors
) {
468 return kIOReturnNoResources
;
471 // Create the vectorData for the IOInterruptSource.
472 vectorData
= OSData::withBytes(&vectorNumber
, sizeof(vectorNumber
));
473 if (vectorData
== 0) {
474 return kIOReturnNoMemory
;
477 // Fill in the IOInterruptSource with the controller's info.
478 interruptSources
[source
].interruptController
= this;
479 interruptSources
[source
].vectorData
= vectorData
;
481 // Fill in vector with the client's info.
482 vector
->handler
= handler
;
484 vector
->source
= source
;
485 vector
->target
= target
;
486 vector
->refCon
= refCon
;
488 // Get the vector ready. It start soft disabled.
489 vector
->interruptDisabledSoft
= 1;
490 vector
->interruptRegistered
= 1;
492 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
494 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
496 IOUnlock(vector
->interruptLock
);
497 return kIOReturnSuccess
;
500 IOReturn
IOSharedInterruptController::unregisterInterrupt(IOService
*nub
,
503 IOInterruptSource
*interruptSources
;
505 IOInterruptVector
*vector
;
507 IOInterruptState interruptState
;;
509 interruptSources
= nub
->_interruptSources
;
510 vectorData
= interruptSources
[source
].vectorData
;
511 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
512 vector
= &vectors
[vectorNumber
];
514 // Get the lock for this vector.
515 IOTakeLock(vector
->interruptLock
);
517 // Return success if it is not already registered
518 if (!vector
->interruptRegistered
) {
519 IOUnlock(vector
->interruptLock
);
520 return kIOReturnSuccess
;
523 // Soft disable the source.
524 disableInterrupt(nub
, source
);
526 // Clear all the storage for the vector except for interruptLock.
527 vector
->interruptActive
= 0;
528 vector
->interruptDisabledSoft
= 0;
529 vector
->interruptDisabledHard
= 0;
530 vector
->interruptRegistered
= 0;
537 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
539 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
541 IOUnlock(vector
->interruptLock
);
542 return kIOReturnSuccess
;
545 IOReturn
IOSharedInterruptController::getInterruptType(IOService */
*nub*/
,
549 return provider
->getInterruptType(0, interruptType
);
552 IOReturn
IOSharedInterruptController::enableInterrupt(IOService
*nub
,
555 IOInterruptSource
*interruptSources
;
557 IOInterruptVector
*vector
;
559 IOInterruptState interruptState
;
561 interruptSources
= nub
->_interruptSources
;
562 vectorData
= interruptSources
[source
].vectorData
;
563 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
564 vector
= &vectors
[vectorNumber
];
566 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
567 if (!vector
->interruptDisabledSoft
) {
568 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
569 return kIOReturnSuccess
;
572 vector
->interruptDisabledSoft
= 0;
574 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
576 if (controllerDisabled
&& (vectorsEnabled
== vectorsRegistered
)) {
577 controllerDisabled
= 0;
578 provider
->enableInterrupt(0);
581 return kIOReturnSuccess
;
584 IOReturn
IOSharedInterruptController::disableInterrupt(IOService
*nub
,
587 IOInterruptSource
*interruptSources
;
589 IOInterruptVector
*vector
;
591 IOInterruptState interruptState
;
593 interruptSources
= nub
->_interruptSources
;
594 vectorData
= interruptSources
[source
].vectorData
;
595 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
596 vector
= &vectors
[vectorNumber
];
598 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
599 if (!vector
->interruptDisabledSoft
) {
600 vector
->interruptDisabledSoft
= 1;
607 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
609 if (!getPlatform()->atInterruptLevel()) {
610 while (vector
->interruptActive
);
616 return kIOReturnSuccess
;
619 IOInterruptAction
IOSharedInterruptController::getInterruptHandlerAddress(void)
621 return (IOInterruptAction
)&IOSharedInterruptController::handleInterrupt
;
624 IOReturn
IOSharedInterruptController::handleInterrupt(void * /*refCon*/,
629 IOInterruptVector
*vector
;
631 for (vectorNumber
= 0; vectorNumber
< numVectors
; vectorNumber
++) {
632 vector
= &vectors
[vectorNumber
];
634 vector
->interruptActive
= 1;
639 if (!vector
->interruptDisabledSoft
) {
644 // Call the handler if it exists.
645 if (vector
->interruptRegistered
) {
646 vector
->handler(vector
->target
, vector
->refCon
,
647 vector
->nub
, vector
->source
);
651 vector
->interruptActive
= 0;
654 // if any of the vectors are dissabled, then dissable this controller.
655 IOSimpleLockLock(controllerLock
);
656 if (vectorsEnabled
!= vectorsRegistered
) {
657 nub
->disableInterrupt(0);
658 controllerDisabled
= 1;
660 IOSimpleLockUnlock(controllerLock
);
662 return kIOReturnSuccess
;