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. 
  31 #include <IOKit/IOPlatformExpert.h> 
  33 #include "GenericInterruptController.h" 
  35 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
  38 #define super IOInterruptController 
  40 IODefineMetaClassAndStructors(GenericInterruptController
, 
  41                               IOInterruptController
); 
  43 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
  46 bool GenericInterruptController::start(IOService 
*provider
) 
  48   IOInterruptAction    handler
; 
  49   IOSymbol             
*interruptControllerName
; 
  51   // If needed call the parents start. 
  52   if (!super::start(provider
)) 
  55   // Map the device's memory and initalize its state. 
  57   // For now you must allocate storage for the vectors. 
  58   // This will probably changed to something like: initVectors(numVectors). 
  59   // In the mean time something like this works well. 
  61   // Allocate the memory for the vectors. 
  62   vectors 
= (IOInterruptVector 
*)IOMalloc(numVectors 
* 
  63                                           sizeof(IOInterruptVector
)); 
  64   if (vectors 
== NULL
) return false; 
  65   bzero(vectors
, numVectors 
* sizeof(IOInterruptVector
)); 
  67   // Allocate locks for the vectors. 
  68   for (cnt 
= 0; cnt 
< numVectors
; cnt
++) { 
  69     vectors
[cnt
].interruptLock 
= IOLockAlloc(); 
  70     if (vectors
[cnt
].interruptLock 
== NULL
) { 
  71       for (cnt 
= 0; cnt 
< numVectors
; cnt
++) { 
  72         if (vectors
[cnt
].interruptLock 
!= NULL
) 
  73           IOLockFree(vectors
[cnt
].interruptLock
); 
  79   // If you know that this interrupt controller is the primary 
  80   // interrupt controller, use this to set it nub properties properly. 
  81   // This may be done by the nub's creator. 
  82   getPlatform()->setCPUInterruptProperties(provider
); 
  84   // register the interrupt handler so it can receive interrupts. 
  85   handler 
= getInterruptHandlerAddress(); 
  86   provider
->registerInterrupt(0, this, handler
, 0); 
  88   // Just like any interrupt source, you must enable it to receive interrupts. 
  89   provider
->enableInterrupt(0); 
  91   // Set interruptControllerName to the proper symbol. 
  92   //interruptControllerName = xxx; 
  94   // Register this interrupt controller so clients can find it. 
  95   getPlatform()->registerInterruptController(interruptControllerName
, this); 
  97   // All done, so return true. 
 101 IOReturn 
GenericInterruptController::getInterruptType(IOService 
*nub
, 
 105   if (interruptType 
== 0) return kIOReturnBadArgument
; 
 107   // Given the nub and source, set interruptType to level or edge. 
 109   return kIOReturnSuccess
; 
 112 // Sadly this just has to be replicated in every interrupt controller. 
 113 IOInterruptAction 
GenericInterruptController::getInterruptHandlerAddress(void) 
 115   return (IOInterruptAction
)handleInterrupt
; 
 118 // Handle all current interrupts. 
 119 IOReturn 
GenericInterruptController::handleInterrupt(void * refCon
, 
 123   IOInterruptVector 
*vector
; 
 127     // Get vectorNumber from hardware some how and clear the event. 
 129     // Break if there are no more vectors to handle. 
 130     if (vectorNumber 
== 0/*kNoVector*/) break; 
 132     // Get the vector's date from the controller's array. 
 133     vector 
= &vectors
[vectorNumber
]; 
 135     // Set the vector as active. This store must compleat before 
 136     // moving on to prevent the disableInterrupt fuction from 
 137     // geting out of sync. 
 138     vector
->interruptActive 
= 1; 
 142     // If the vector is not disabled soft, handle it. 
 143     if (!vector
->interruptDisabledSoft
) { 
 144       // Prevent speculative exacution as needed on your processor. 
 147       // Call the handler if it exists. 
 148       if (vector
->interruptRegistered
) { 
 149         vector
->handler(vector
->target
, vector
->refCon
, 
 150                         vector
->nub
, vector
->source
); 
 153       // Hard disable the vector if is was only soft disabled. 
 154       vector
->interruptDisabledHard 
= 1; 
 155       disableVectorHard(vectorNumber
, vector
); 
 158     // Done with this vector so, set it back to inactive. 
 159     vector
->interruptActive 
= 0; 
 162   return kIOReturnSuccess
; 
 165 bool GenericInterruptController::vectorCanBeShared(long vectorNumber
, 
 166                                                    IOInterruptVector 
*vector
) 
 168   // Given the vector number and the vector data, return if it can be shared. 
 172 void GenericInterruptController::initVector(long vectorNumber
, 
 173                                             IOInterruptVector 
*vector
) 
 175   // Given the vector number and the vector data, 
 176   // get the hardware ready for the vector to generate interrupts. 
 177   // Make sure the vector is left disabled. 
 180 void GenericInterruptController::disableVectorHard(long vectorNumber
, 
 181                                                    IOInterruptVector 
*vector
) 
 183   // Given the vector number and the vector data, 
 184   // disable the vector at the hardware. 
 187 void GenericInterruptController::enableVector(long vectorNumber
, 
 188                                               IOInterruptVector 
*vector
) 
 190   // Given the vector number and the vector data, 
 191   // enable the vector at the hardware. 
 194 void GenericInterruptController::causeVector(long vectorNumber
, 
 195                                              IOInterruptVector 
*vector
) 
 197   // Given the vector number and the vector data, 
 198   // Set the vector pending and cause an interrupt at the parent controller. 
 200   // cause the interrupt at the parent controller.  Source is usually zero, 
 201   // but it could be different for your controller. 
 202   getPlatform()->causeInterrupt(0);