2  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved. 
   8  * This file contains Original Code and/or Modifications of Original Code 
   9  * as defined in and that are subject to the Apple Public Source License 
  10  * Version 2.0 (the 'License'). You may not use this file except in 
  11  * compliance with the License. Please obtain a copy of the License at 
  12  * http://www.opensource.apple.com/apsl/ and read it before using this 
  15  * The Original Code and all software distributed under the License are 
  16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  20  * Please see the License for the specific language governing rights and 
  21  * limitations under the License. 
  23  * @APPLE_LICENSE_HEADER_END@ 
  26  * Copyright (c) 1999 Apple Computer, Inc.  All rights reserved.  
  34 #include <ppc/proc_reg.h>  
  37 #include <IOKit/IOLib.h> 
  38 #include <IOKit/IOService.h> 
  39 #include <IOKit/IOPlatformExpert.h> 
  40 #include <IOKit/IOInterrupts.h> 
  41 #include <IOKit/IOInterruptController.h> 
  44 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
  46 #define super IOService 
  48 OSDefineMetaClassAndAbstractStructors(IOInterruptController
, IOService
); 
  50 OSMetaClassDefineReservedUnused(IOInterruptController
, 0); 
  51 OSMetaClassDefineReservedUnused(IOInterruptController
, 1); 
  52 OSMetaClassDefineReservedUnused(IOInterruptController
, 2); 
  53 OSMetaClassDefineReservedUnused(IOInterruptController
, 3); 
  54 OSMetaClassDefineReservedUnused(IOInterruptController
, 4); 
  55 OSMetaClassDefineReservedUnused(IOInterruptController
, 5); 
  57 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
  59 IOReturn 
IOInterruptController::registerInterrupt(IOService 
*nub
, int source
, 
  61                                                   IOInterruptHandler handler
, 
  64   IOInterruptSource 
*interruptSources
; 
  66   IOInterruptVector 
*vector
; 
  70   IOService         
*originalNub
; 
  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   // If this vector is already in use, and can be shared, 
  82   // register as a shared interrupt. 
  83   if (vector
->interruptRegistered
) { 
  84     if (!vectorCanBeShared(vectorNumber
, vector
)) { 
  85       IOUnlock(vector
->interruptLock
); 
  86       return kIOReturnNoResources
; 
  89     // If this vector is not already shared, break it out. 
  90     if (vector
->sharedController 
== 0) { 
  91       // Make the IOShareInterruptController instance 
  92       vector
->sharedController 
= new IOSharedInterruptController
; 
  93       if (vector
->sharedController 
== 0) { 
  94         IOUnlock(vector
->interruptLock
); 
  95         return kIOReturnNoMemory
; 
  98       // Save the nub and source for the original consumer. 
  99       originalNub 
= vector
->nub
; 
 100       originalSource 
= vector
->source
; 
 102       // Physically disable the interrupt, but mark it as being enables in the hardware. 
 103       // The interruptDisabledSoft now indicates the driver's request for enablement. 
 104       disableVectorHard(vectorNumber
, vector
); 
 105       vector
->interruptDisabledHard 
= 0; 
 107       // Initialize the new shared interrupt controller. 
 108       error 
= vector
->sharedController
->initInterruptController(this, 
 110       // If the IOSharedInterruptController could not be initalized, 
 111       // put the original consumor's interrupt back to normal and 
 112       // get rid of whats left of the shared controller. 
 113       if (error 
!= kIOReturnSuccess
) { 
 114         enableInterrupt(originalNub
, originalSource
); 
 115         vector
->sharedController
->release(); 
 116         vector
->sharedController 
= 0; 
 117         IOUnlock(vector
->interruptLock
); 
 121       // Try to register the original consumer on the shared controller. 
 122       error 
= vector
->sharedController
->registerInterrupt(originalNub
, 
 127       // If the original consumer could not be moved to the shared controller, 
 128       // put the original consumor's interrupt back to normal and 
 129       // get rid of whats left of the shared controller. 
 130       if (error 
!= kIOReturnSuccess
) { 
 131         // Save the driver's interrupt enablement state. 
 132         wasDisabledSoft 
= vector
->interruptDisabledSoft
; 
 134         // Make the interrupt really hard disabled. 
 135         vector
->interruptDisabledSoft 
= 1; 
 136         vector
->interruptDisabledHard 
= 1; 
 138         // Enable the original consumer's interrupt if needed. 
 139         if (!wasDisabledSoft
) originalNub
->enableInterrupt(originalSource
); 
 140         enableInterrupt(originalNub
, originalSource
); 
 142         vector
->sharedController
->release(); 
 143         vector
->sharedController 
= 0; 
 144         IOUnlock(vector
->interruptLock
); 
 148       // Fill in vector with the shared controller's info. 
 149       vector
->handler 
= (IOInterruptHandler
)vector
->sharedController
->getInterruptHandlerAddress(); 
 150       vector
->nub     
= vector
->sharedController
; 
 152       vector
->target  
= vector
->sharedController
; 
 155       // Save the driver's interrupt enablement state. 
 156       wasDisabledSoft 
= vector
->interruptDisabledSoft
; 
 158       // Make the interrupt really hard disabled. 
 159       vector
->interruptDisabledSoft 
= 1; 
 160       vector
->interruptDisabledHard 
= 1; 
 162       // Enable the original consumer's interrupt if needed. 
 163       if (!wasDisabledSoft
) originalNub
->enableInterrupt(originalSource
); 
 166     error 
= vector
->sharedController
->registerInterrupt(nub
, source
, target
, 
 168     IOUnlock(vector
->interruptLock
); 
 172   // Fill in vector with the client's info. 
 173   vector
->handler 
= handler
; 
 175   vector
->source  
= source
; 
 176   vector
->target  
= target
; 
 177   vector
->refCon  
= refCon
; 
 179   // Do any specific initalization for this vector. 
 180   initVector(vectorNumber
, vector
); 
 182   // Get the vector ready.  It starts hard disabled. 
 183   vector
->interruptDisabledHard 
= 1; 
 184   vector
->interruptDisabledSoft 
= 1; 
 185   vector
->interruptRegistered   
= 1; 
 187   IOUnlock(vector
->interruptLock
); 
 188   return kIOReturnSuccess
; 
 191 IOReturn 
IOInterruptController::unregisterInterrupt(IOService 
*nub
, int source
) 
 193   IOInterruptSource 
*interruptSources
; 
 195   IOInterruptVector 
*vector
; 
 198   interruptSources 
= nub
->_interruptSources
; 
 199   vectorData 
= interruptSources
[source
].vectorData
; 
 200   vectorNumber 
= *(long *)vectorData
->getBytesNoCopy(); 
 201   vector 
= &vectors
[vectorNumber
]; 
 203   // Get the lock for this vector. 
 204   IOTakeLock(vector
->interruptLock
); 
 206   // Return success if it is not already registered 
 207   if (!vector
->interruptRegistered
) { 
 208     IOUnlock(vector
->interruptLock
); 
 209     return kIOReturnSuccess
; 
 212   // Soft disable the source. 
 213   disableInterrupt(nub
, source
); 
 215   // Turn the source off at hardware.  
 216   disableVectorHard(vectorNumber
, vector
); 
 218   // Clear all the storage for the vector except for interruptLock. 
 219   vector
->interruptActive 
= 0; 
 220   vector
->interruptDisabledSoft 
= 0; 
 221   vector
->interruptDisabledHard 
= 0; 
 222   vector
->interruptRegistered 
= 0; 
 229   IOUnlock(vector
->interruptLock
); 
 230   return kIOReturnSuccess
; 
 233 IOReturn 
IOInterruptController::getInterruptType(IOService 
*nub
, int source
, 
 236   IOInterruptSource 
*interruptSources
; 
 238   IOInterruptVector 
*vector
; 
 241   if (interruptType 
== 0) return kIOReturnBadArgument
; 
 243   interruptSources 
= nub
->_interruptSources
; 
 244   vectorData 
= interruptSources
[source
].vectorData
; 
 245   vectorNumber 
= *(long *)vectorData
->getBytesNoCopy(); 
 246   vector 
= &vectors
[vectorNumber
]; 
 248   *interruptType 
= getVectorType(vectorNumber
, vector
); 
 250   return kIOReturnSuccess
; 
 253 IOReturn 
IOInterruptController::enableInterrupt(IOService 
*nub
, int source
) 
 255   IOInterruptSource 
*interruptSources
; 
 257   IOInterruptVector 
*vector
; 
 260   interruptSources 
= nub
->_interruptSources
; 
 261   vectorData 
= interruptSources
[source
].vectorData
; 
 262   vectorNumber 
= *(long *)vectorData
->getBytesNoCopy(); 
 263   vector 
= &vectors
[vectorNumber
]; 
 265   if (vector
->interruptDisabledSoft
) { 
 266     vector
->interruptDisabledSoft 
= 0; 
 272     if (!getPlatform()->atInterruptLevel()) { 
 273       while (vector
->interruptActive
); 
 278     if (vector
->interruptDisabledHard
) { 
 279       vector
->interruptDisabledHard 
= 0; 
 281       enableVector(vectorNumber
, vector
); 
 285   return kIOReturnSuccess
; 
 288 IOReturn 
IOInterruptController::disableInterrupt(IOService 
*nub
, int source
) 
 290   IOInterruptSource 
*interruptSources
; 
 292   IOInterruptVector 
*vector
; 
 295   interruptSources 
= nub
->_interruptSources
; 
 296   vectorData 
= interruptSources
[source
].vectorData
; 
 297   vectorNumber 
= *(long *)vectorData
->getBytesNoCopy(); 
 298   vector 
= &vectors
[vectorNumber
]; 
 300   vector
->interruptDisabledSoft 
= 1; 
 306   if (!getPlatform()->atInterruptLevel()) { 
 307     while (vector
->interruptActive
); 
 313   return kIOReturnSuccess
; 
 316 IOReturn 
IOInterruptController::causeInterrupt(IOService 
*nub
, int source
) 
 318   IOInterruptSource 
*interruptSources
; 
 320   IOInterruptVector 
*vector
; 
 323   interruptSources 
= nub
->_interruptSources
; 
 324   vectorData 
= interruptSources
[source
].vectorData
; 
 325   vectorNumber 
= *(long *)vectorData
->getBytesNoCopy(); 
 326   vector 
= &vectors
[vectorNumber
]; 
 328   causeVector(vectorNumber
, vector
); 
 330   return kIOReturnSuccess
; 
 333 IOInterruptAction 
IOInterruptController::getInterruptHandlerAddress(void) 
 338 IOReturn 
IOInterruptController::handleInterrupt(void *refCon
, IOService 
*nub
, 
 341   return kIOReturnInvalid
; 
 345 // Methods to be overridden for simplifed interrupt controller subclasses. 
 347 bool IOInterruptController::vectorCanBeShared(long /*vectorNumber*/, 
 348                                               IOInterruptVector */
*vector*/
) 
 353 void IOInterruptController::initVector(long /*vectorNumber*/, 
 354                                        IOInterruptVector */
*vector*/
) 
 358 int IOInterruptController::getVectorType(long /*vectorNumber*/, 
 359                                           IOInterruptVector */
*vector*/
) 
 361   return kIOInterruptTypeEdge
; 
 364 void IOInterruptController::disableVectorHard(long /*vectorNumber*/, 
 365                                               IOInterruptVector */
*vector*/
) 
 369 void IOInterruptController::enableVector(long /*vectorNumber*/, 
 370                                          IOInterruptVector */
*vector*/
) 
 374 void IOInterruptController::causeVector(long /*vectorNumber*/, 
 375                                         IOInterruptVector */
*vector*/
) 
 380 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 383 #define super IOInterruptController 
 385 OSDefineMetaClassAndStructors(IOSharedInterruptController
, IOInterruptController
); 
 387 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 0); 
 388 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 1); 
 389 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 2); 
 390 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 3); 
 392 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
 394 IOReturn 
IOSharedInterruptController::initInterruptController(IOInterruptController 
*parentController
, OSData 
*parentSource
) 
 396   int      cnt
, interruptType
; 
 400     return kIOReturnNoResources
; 
 402   // Set provider to this so enable/disable nub stuff works. 
 405   // Allocate the IOInterruptSource so this can act like a nub. 
 406   _interruptSources 
= (IOInterruptSource 
*)IOMalloc(sizeof(IOInterruptSource
)); 
 407   if (_interruptSources 
== 0) return kIOReturnNoMemory
; 
 408   _numInterruptSources 
= 1; 
 410   // Set up the IOInterruptSource to point at this. 
 411   _interruptSources
[0].interruptController 
= parentController
; 
 412   _interruptSources
[0].vectorData 
= parentSource
; 
 414   sourceIsLevel 
= false; 
 415   error 
= provider
->getInterruptType(0, &interruptType
); 
 416   if (error 
== kIOReturnSuccess
) { 
 417     if (interruptType 
& kIOInterruptTypeLevel
) 
 418       sourceIsLevel 
= true; 
 421   // Allocate the memory for the vectors 
 422   numVectors 
= 32; // For now a constant number. 
 423   vectors 
= (IOInterruptVector 
*)IOMalloc(numVectors 
* sizeof(IOInterruptVector
)); 
 424   if (vectors 
== NULL
) { 
 425     IOFree(_interruptSources
, sizeof(IOInterruptSource
)); 
 426     return kIOReturnNoMemory
; 
 428   bzero(vectors
, numVectors 
* sizeof(IOInterruptVector
)); 
 430   // Allocate the lock for the controller. 
 431   controllerLock 
= IOSimpleLockAlloc(); 
 432   if (controllerLock 
== 0) return kIOReturnNoResources
; 
 434   // Allocate locks for the vectors. 
 435   for (cnt 
= 0; cnt 
< numVectors
; cnt
++) { 
 436     vectors
[cnt
].interruptLock 
= IOLockAlloc(); 
 437     if (vectors
[cnt
].interruptLock 
== NULL
) { 
 438       for (cnt 
= 0; cnt 
< numVectors
; cnt
++) { 
 439         if (vectors
[cnt
].interruptLock 
!= NULL
) 
 440           IOLockFree(vectors
[cnt
].interruptLock
); 
 442       return kIOReturnNoResources
; 
 446   vectorsRegistered 
= 0; 
 448   controllerDisabled 
= 1; 
 450   return kIOReturnSuccess
; 
 453 IOReturn 
IOSharedInterruptController::registerInterrupt(IOService 
*nub
, 
 456                                                         IOInterruptHandler handler
, 
 459   IOInterruptSource 
*interruptSources
; 
 461   IOInterruptVector 
*vector 
= 0; 
 463   IOInterruptState  interruptState
; 
 465   interruptSources 
= nub
->_interruptSources
; 
 467   // Find a free vector. 
 468   vectorNumber 
= numVectors
; 
 469   while (vectorsRegistered 
!= numVectors
) { 
 470     for (vectorNumber 
= 0; vectorNumber 
< numVectors
; vectorNumber
++) { 
 471       vector 
= &vectors
[vectorNumber
]; 
 473       // Get the lock for this vector. 
 474       IOTakeLock(vector
->interruptLock
); 
 476       // Is it unregistered? 
 477       if (!vector
->interruptRegistered
) break; 
 479       // Move along to the next one. 
 480       IOUnlock(vector
->interruptLock
); 
 483     if (vectorNumber 
!= numVectors
) break; 
 486   // Could not find a free one, so give up. 
 487   if (vectorNumber 
== numVectors
) { 
 488     return kIOReturnNoResources
; 
 491   // Create the vectorData for the IOInterruptSource. 
 492   vectorData 
= OSData::withBytes(&vectorNumber
, sizeof(vectorNumber
)); 
 493   if (vectorData 
== 0) { 
 494     return kIOReturnNoMemory
; 
 497   // Fill in the IOInterruptSource with the controller's info. 
 498   interruptSources
[source
].interruptController 
= this; 
 499   interruptSources
[source
].vectorData 
= vectorData
; 
 501   // Fill in vector with the client's info. 
 502   vector
->handler 
= handler
; 
 504   vector
->source  
= source
; 
 505   vector
->target  
= target
; 
 506   vector
->refCon  
= refCon
; 
 508   // Get the vector ready.  It start soft disabled. 
 509   vector
->interruptDisabledSoft 
= 1; 
 510   vector
->interruptRegistered   
= 1; 
 512   interruptState 
= IOSimpleLockLockDisableInterrupt(controllerLock
); 
 514   IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
); 
 516   IOUnlock(vector
->interruptLock
); 
 517   return kIOReturnSuccess
; 
 520 IOReturn 
IOSharedInterruptController::unregisterInterrupt(IOService 
*nub
, 
 523   IOInterruptSource 
*interruptSources
; 
 525   IOInterruptVector 
*vector
; 
 527   IOInterruptState  interruptState
;; 
 529   interruptSources 
= nub
->_interruptSources
; 
 530   vectorData 
= interruptSources
[source
].vectorData
; 
 531   vectorNumber 
= *(long *)vectorData
->getBytesNoCopy(); 
 532   vector 
= &vectors
[vectorNumber
]; 
 534   // Get the lock for this vector. 
 535   IOTakeLock(vector
->interruptLock
); 
 537   // Return success if it is not already registered 
 538   if (!vector
->interruptRegistered
) { 
 539     IOUnlock(vector
->interruptLock
); 
 540     return kIOReturnSuccess
; 
 543   // Soft disable the source. 
 544   disableInterrupt(nub
, source
); 
 546   // Clear all the storage for the vector except for interruptLock. 
 547   vector
->interruptActive 
= 0; 
 548   vector
->interruptDisabledSoft 
= 0; 
 549   vector
->interruptDisabledHard 
= 0; 
 550   vector
->interruptRegistered 
= 0; 
 557   interruptState 
= IOSimpleLockLockDisableInterrupt(controllerLock
); 
 559   IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
); 
 561   IOUnlock(vector
->interruptLock
); 
 562   return kIOReturnSuccess
; 
 565 IOReturn 
IOSharedInterruptController::getInterruptType(IOService */
*nub*/
, 
 569   return provider
->getInterruptType(0, interruptType
); 
 572 IOReturn 
IOSharedInterruptController::enableInterrupt(IOService 
*nub
, 
 575   IOInterruptSource 
*interruptSources
; 
 577   IOInterruptVector 
*vector
; 
 579   IOInterruptState  interruptState
; 
 581   interruptSources 
= nub
->_interruptSources
; 
 582   vectorData 
= interruptSources
[source
].vectorData
; 
 583   vectorNumber 
= *(long *)vectorData
->getBytesNoCopy(); 
 584   vector 
= &vectors
[vectorNumber
]; 
 586   interruptState 
= IOSimpleLockLockDisableInterrupt(controllerLock
); 
 587   if (!vector
->interruptDisabledSoft
) { 
 588     IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
); 
 589     return kIOReturnSuccess
; 
 592   vector
->interruptDisabledSoft 
= 0; 
 594   IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
); 
 596   if (controllerDisabled 
&& (vectorsEnabled 
== vectorsRegistered
)) { 
 597     controllerDisabled 
= 0; 
 598     provider
->enableInterrupt(0); 
 601   return kIOReturnSuccess
; 
 604 IOReturn 
IOSharedInterruptController::disableInterrupt(IOService 
*nub
, 
 607   IOInterruptSource 
*interruptSources
; 
 609   IOInterruptVector 
*vector
; 
 611   IOInterruptState  interruptState
; 
 613   interruptSources 
= nub
->_interruptSources
; 
 614   vectorData 
= interruptSources
[source
].vectorData
; 
 615   vectorNumber 
= *(long *)vectorData
->getBytesNoCopy(); 
 616   vector 
= &vectors
[vectorNumber
]; 
 618   interruptState 
= IOSimpleLockLockDisableInterrupt(controllerLock
);  
 619   if (!vector
->interruptDisabledSoft
) { 
 620     vector
->interruptDisabledSoft 
= 1; 
 627   IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
); 
 629   if (!getPlatform()->atInterruptLevel()) { 
 630     while (vector
->interruptActive
); 
 636   return kIOReturnSuccess
; 
 639 IOInterruptAction 
IOSharedInterruptController::getInterruptHandlerAddress(void) 
 641     return (IOInterruptAction
)&IOSharedInterruptController::handleInterrupt
; 
 644 IOReturn 
IOSharedInterruptController::handleInterrupt(void * /*refCon*/, 
 649   IOInterruptVector 
*vector
; 
 651   for (vectorNumber 
= 0; vectorNumber 
< numVectors
; vectorNumber
++) { 
 652     vector 
= &vectors
[vectorNumber
]; 
 654     vector
->interruptActive 
= 1; 
 659     if (!vector
->interruptDisabledSoft
) { 
 664       // Call the handler if it exists. 
 665       if (vector
->interruptRegistered
) { 
 666         vector
->handler(vector
->target
, vector
->refCon
, 
 667                         vector
->nub
, vector
->source
); 
 671     vector
->interruptActive 
= 0; 
 674   // if any of the vectors are dissabled, then dissable this controller. 
 675   IOSimpleLockLock(controllerLock
); 
 676   if (vectorsEnabled 
!= vectorsRegistered
) { 
 677     nub
->disableInterrupt(0); 
 678     controllerDisabled 
= 1; 
 680   IOSimpleLockUnlock(controllerLock
); 
 682   return kIOReturnSuccess
;