1 /* 2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 /* 29 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 30 * 31 * DRI: Josh de Cesare 32 */ 33 34 #include <IOKit/IOPlatformExpert.h> 35 36 #include "GenericInterruptController.h" 37 38 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 39 40 #undef super 41 #define super IOInterruptController 42 43 IODefineMetaClassAndStructors(GenericInterruptController, 44 IOInterruptController); 45 46 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 47 48 49 bool 50 GenericInterruptController::start(IOService *provider) 51 { 52 IOInterruptAction handler; 53 IOSymbol *interruptControllerName; 54 55 // If needed call the parents start. 56 if (!super::start(provider)) { 57 return false; 58 } 59 60 // Map the device's memory and initalize its state. 61 62 // For now you must allocate storage for the vectors. 63 // This will probably changed to something like: initVectors(numVectors). 64 // In the mean time something like this works well. 65 #if 0 66 // Allocate the memory for the vectors. 67 vectors = (IOInterruptVector *)IOMalloc(numVectors * 68 sizeof(IOInterruptVector)); 69 if (vectors == NULL) { 70 return false; 71 } 72 bzero(vectors, numVectors * sizeof(IOInterruptVector)); 73 74 // Allocate locks for the vectors. 75 for (cnt = 0; cnt < numVectors; cnt++) { 76 vectors[cnt].interruptLock = IOLockAlloc(); 77 if (vectors[cnt].interruptLock == NULL) { 78 for (cnt = 0; cnt < numVectors; cnt++) { 79 if (vectors[cnt].interruptLock != NULL) { 80 IOLockFree(vectors[cnt].interruptLock); 81 } 82 } 83 } 84 } 85 #endif 86 87 // If you know that this interrupt controller is the primary 88 // interrupt controller, use this to set it nub properties properly. 89 // This may be done by the nub's creator. 90 getPlatform()->setCPUInterruptProperties(provider); 91 92 // register the interrupt handler so it can receive interrupts. 93 handler = getInterruptHandlerAddress(); 94 provider->registerInterrupt(0, this, handler, 0); 95 96 // Just like any interrupt source, you must enable it to receive interrupts. 97 provider->enableInterrupt(0); 98 99 // Set interruptControllerName to the proper symbol. 100 //interruptControllerName = xxx; 101 102 // Register this interrupt controller so clients can find it. 103 getPlatform()->registerInterruptController(interruptControllerName, this); 104 105 // All done, so return true. 106 return true; 107 } 108 109 IOReturn 110 GenericInterruptController::getInterruptType(IOService *nub, 111 int source, 112 int *interruptType) 113 { 114 if (interruptType == 0) { 115 return kIOReturnBadArgument; 116 } 117 118 // Given the nub and source, set interruptType to level or edge. 119 120 return kIOReturnSuccess; 121 } 122 123 // Sadly this just has to be replicated in every interrupt controller. 124 IOInterruptAction 125 GenericInterruptController::getInterruptHandlerAddress(void) 126 { 127 return (IOInterruptAction)handleInterrupt; 128 } 129 130 // Handle all current interrupts. 131 IOReturn 132 GenericInterruptController::handleInterrupt(void * refCon, 133 IOService * nub, 134 int source) 135 { 136 IOInterruptVector *vector; 137 int vectorNumber; 138 139 while (1) { 140 // Get vectorNumber from hardware some how and clear the event. 141 142 // Break if there are no more vectors to handle. 143 if (vectorNumber == 0 /*kNoVector*/) { 144 break; 145 } 146 147 // Get the vector's date from the controller's array. 148 vector = &vectors[vectorNumber]; 149 150 // Set the vector as active. This store must compleat before 151 // moving on to prevent the disableInterrupt fuction from 152 // geting out of sync. 153 vector->interruptActive = 1; 154 //sync(); 155 //isync(); 156 157 // If the vector is not disabled soft, handle it. 158 if (!vector->interruptDisabledSoft) { 159 // Prevent speculative exacution as needed on your processor. 160 //isync(); 161 162 // Call the handler if it exists. 163 if (vector->interruptRegistered) { 164 vector->handler(vector->target, vector->refCon, 165 vector->nub, vector->source); 166 } 167 } else { 168 // Hard disable the vector if is was only soft disabled. 169 vector->interruptDisabledHard = 1; 170 disableVectorHard(vectorNumber, vector); 171 } 172 173 // Done with this vector so, set it back to inactive. 174 vector->interruptActive = 0; 175 } 176 177 return kIOReturnSuccess; 178 } 179 180 bool 181 GenericInterruptController::vectorCanBeShared(long vectorNumber, 182 IOInterruptVector *vector) 183 { 184 // Given the vector number and the vector data, return if it can be shared. 185 return true; 186 } 187 188 void 189 GenericInterruptController::initVector(long vectorNumber, 190 IOInterruptVector *vector) 191 { 192 // Given the vector number and the vector data, 193 // get the hardware ready for the vector to generate interrupts. 194 // Make sure the vector is left disabled. 195 } 196 197 void 198 GenericInterruptController::disableVectorHard(long vectorNumber, 199 IOInterruptVector *vector) 200 { 201 // Given the vector number and the vector data, 202 // disable the vector at the hardware. 203 } 204 205 void 206 GenericInterruptController::enableVector(long vectorNumber, 207 IOInterruptVector *vector) 208 { 209 // Given the vector number and the vector data, 210 // enable the vector at the hardware. 211 } 212 213 void 214 GenericInterruptController::causeVector(long vectorNumber, 215 IOInterruptVector *vector) 216 { 217 // Given the vector number and the vector data, 218 // Set the vector pending and cause an interrupt at the parent controller. 219 220 // cause the interrupt at the parent controller. Source is usually zero, 221 // but it could be different for your controller. 222 getPlatform()->causeInterrupt(0); 223 } 224