1 /* 2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. 7 * 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 13 * file. 14 * 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. 22 * 23 * @APPLE_LICENSE_HEADER_END@ 24 */ 25 /* 26 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 27 * 28 * DRI: Josh de Cesare 29 */ 30 31 #include <IOKit/IOPlatformExpert.h> 32 33 #include "GenericInterruptController.h" 34 35 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 36 37 #undef super 38 #define super IOInterruptController 39 40 IODefineMetaClassAndStructors(GenericInterruptController, 41 IOInterruptController); 42 43 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 44 45 46 bool GenericInterruptController::start(IOService *provider) 47 { 48 IOInterruptAction handler; 49 IOSymbol *interruptControllerName; 50 51 // If needed call the parents start. 52 if (!super::start(provider)) 53 return false; 54 55 // Map the device's memory and initalize its state. 56 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. 60 #if 0 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)); 66 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); 74 } 75 } 76 } 77 #endif 78 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); 83 84 // register the interrupt handler so it can receive interrupts. 85 handler = getInterruptHandlerAddress(); 86 provider->registerInterrupt(0, this, handler, 0); 87 88 // Just like any interrupt source, you must enable it to receive interrupts. 89 provider->enableInterrupt(0); 90 91 // Set interruptControllerName to the proper symbol. 92 //interruptControllerName = xxx; 93 94 // Register this interrupt controller so clients can find it. 95 getPlatform()->registerInterruptController(interruptControllerName, this); 96 97 // All done, so return true. 98 return true; 99 } 100 101 IOReturn GenericInterruptController::getInterruptType(IOService *nub, 102 int source, 103 int *interruptType) 104 { 105 if (interruptType == 0) return kIOReturnBadArgument; 106 107 // Given the nub and source, set interruptType to level or edge. 108 109 return kIOReturnSuccess; 110 } 111 112 // Sadly this just has to be replicated in every interrupt controller. 113 IOInterruptAction GenericInterruptController::getInterruptHandlerAddress(void) 114 { 115 return (IOInterruptAction)handleInterrupt; 116 } 117 118 // Handle all current interrupts. 119 IOReturn GenericInterruptController::handleInterrupt(void * refCon, 120 IOService * nub, 121 int source) 122 { 123 IOInterruptVector *vector; 124 int vectorNumber; 125 126 while (1) { 127 // Get vectorNumber from hardware some how and clear the event. 128 129 // Break if there are no more vectors to handle. 130 if (vectorNumber == 0/*kNoVector*/) break; 131 132 // Get the vector's date from the controller's array. 133 vector = &vectors[vectorNumber]; 134 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; 139 //sync(); 140 //isync(); 141 142 // If the vector is not disabled soft, handle it. 143 if (!vector->interruptDisabledSoft) { 144 // Prevent speculative exacution as needed on your processor. 145 //isync(); 146 147 // Call the handler if it exists. 148 if (vector->interruptRegistered) { 149 vector->handler(vector->target, vector->refCon, 150 vector->nub, vector->source); 151 } 152 } else { 153 // Hard disable the vector if is was only soft disabled. 154 vector->interruptDisabledHard = 1; 155 disableVectorHard(vectorNumber, vector); 156 } 157 158 // Done with this vector so, set it back to inactive. 159 vector->interruptActive = 0; 160 } 161 162 return kIOReturnSuccess; 163 } 164 165 bool GenericInterruptController::vectorCanBeShared(long vectorNumber, 166 IOInterruptVector *vector) 167 { 168 // Given the vector number and the vector data, return if it can be shared. 169 return true; 170 } 171 172 void GenericInterruptController::initVector(long vectorNumber, 173 IOInterruptVector *vector) 174 { 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. 178 } 179 180 void GenericInterruptController::disableVectorHard(long vectorNumber, 181 IOInterruptVector *vector) 182 { 183 // Given the vector number and the vector data, 184 // disable the vector at the hardware. 185 } 186 187 void GenericInterruptController::enableVector(long vectorNumber, 188 IOInterruptVector *vector) 189 { 190 // Given the vector number and the vector data, 191 // enable the vector at the hardware. 192 } 193 194 void GenericInterruptController::causeVector(long vectorNumber, 195 IOInterruptVector *vector) 196 { 197 // Given the vector number and the vector data, 198 // Set the vector pending and cause an interrupt at the parent controller. 199 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); 203 } 204