1 /* 2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 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. 11 * 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 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22 /* 23 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 24 * 25 * DRI: Josh de Cesare 26 */ 27 28 #include <IOKit/IOPlatformExpert.h> 29 30 #include "GenericInterruptController.h" 31 32 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 33 34 #undef super 35 #define super IOInterruptController 36 37 IODefineMetaClassAndStructors(GenericInterruptController, 38 IOInterruptController); 39 40 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 41 42 43 bool GenericInterruptController::start(IOService *provider) 44 { 45 IOInterruptAction handler; 46 IOSymbol *interruptControllerName; 47 48 // If needed call the parents start. 49 if (!super::start(provider)) 50 return false; 51 52 // Map the device's memory and initalize its state. 53 54 // For now you must allocate storage for the vectors. 55 // This will probably changed to something like: initVectors(numVectors). 56 // In the mean time something like this works well. 57 #if 0 58 // Allocate the memory for the vectors. 59 vectors = (IOInterruptVector *)IOMalloc(numVectors * 60 sizeof(IOInterruptVector)); 61 if (vectors == NULL) return false; 62 bzero(vectors, numVectors * sizeof(IOInterruptVector)); 63 64 // Allocate locks for the vectors. 65 for (cnt = 0; cnt < numVectors; cnt++) { 66 vectors[cnt].interruptLock = IOLockAlloc(); 67 if (vectors[cnt].interruptLock == NULL) { 68 for (cnt = 0; cnt < numVectors; cnt++) { 69 if (vectors[cnt].interruptLock != NULL) 70 IOLockFree(vectors[cnt].interruptLock); 71 } 72 } 73 } 74 #endif 75 76 // If you know that this interrupt controller is the primary 77 // interrupt controller, use this to set it nub properties properly. 78 // This may be done by the nub's creator. 79 getPlatform()->setCPUInterruptProperties(provider); 80 81 // register the interrupt handler so it can receive interrupts. 82 handler = getInterruptHandlerAddress(); 83 provider->registerInterrupt(0, this, handler, 0); 84 85 // Just like any interrupt source, you must enable it to receive interrupts. 86 provider->enableInterrupt(0); 87 88 // Set interruptControllerName to the proper symbol. 89 //interruptControllerName = xxx; 90 91 // Register this interrupt controller so clients can find it. 92 getPlatform()->registerInterruptController(interruptControllerName, this); 93 94 // All done, so return true. 95 return true; 96 } 97 98 IOReturn GenericInterruptController::getInterruptType(IOService *nub, 99 int source, 100 int *interruptType) 101 { 102 if (interruptType == 0) return kIOReturnBadArgument; 103 104 // Given the nub and source, set interruptType to level or edge. 105 106 return kIOReturnSuccess; 107 } 108 109 // Sadly this just has to be replicated in every interrupt controller. 110 IOInterruptAction GenericInterruptController::getInterruptHandlerAddress(void) 111 { 112 return (IOInterruptAction)handleInterrupt; 113 } 114 115 // Handle all current interrupts. 116 IOReturn GenericInterruptController::handleInterrupt(void * refCon, 117 IOService * nub, 118 int source) 119 { 120 IOInterruptVector *vector; 121 int vectorNumber; 122 123 while (1) { 124 // Get vectorNumber from hardware some how and clear the event. 125 126 // Break if there are no more vectors to handle. 127 if (vectorNumber == 0/*kNoVector*/) break; 128 129 // Get the vector's date from the controller's array. 130 vector = &vectors[vectorNumber]; 131 132 // Set the vector as active. This store must compleat before 133 // moving on to prevent the disableInterrupt fuction from 134 // geting out of sync. 135 vector->interruptActive = 1; 136 //sync(); 137 //isync(); 138 139 // If the vector is not disabled soft, handle it. 140 if (!vector->interruptDisabledSoft) { 141 // Prevent speculative exacution as needed on your processor. 142 //isync(); 143 144 // Call the handler if it exists. 145 if (vector->interruptRegistered) { 146 vector->handler(vector->target, vector->refCon, 147 vector->nub, vector->source); 148 } 149 } else { 150 // Hard disable the vector if is was only soft disabled. 151 vector->interruptDisabledHard = 1; 152 disableVectorHard(vectorNumber, vector); 153 } 154 155 // Done with this vector so, set it back to inactive. 156 vector->interruptActive = 0; 157 } 158 159 return kIOReturnSuccess; 160 } 161 162 bool GenericInterruptController::vectorCanBeShared(long vectorNumber, 163 IOInterruptVector *vector) 164 { 165 // Given the vector number and the vector data, return if it can be shared. 166 return true; 167 } 168 169 void GenericInterruptController::initVector(long vectorNumber, 170 IOInterruptVector *vector) 171 { 172 // Given the vector number and the vector data, 173 // get the hardware ready for the vector to generate interrupts. 174 // Make sure the vector is left disabled. 175 } 176 177 void GenericInterruptController::disableVectorHard(long vectorNumber, 178 IOInterruptVector *vector) 179 { 180 // Given the vector number and the vector data, 181 // disable the vector at the hardware. 182 } 183 184 void GenericInterruptController::enableVector(long vectorNumber, 185 IOInterruptVector *vector) 186 { 187 // Given the vector number and the vector data, 188 // enable the vector at the hardware. 189 } 190 191 void GenericInterruptController::causeVector(long vectorNumber, 192 IOInterruptVector *vector) 193 { 194 // Given the vector number and the vector data, 195 // Set the vector pending and cause an interrupt at the parent controller. 196 197 // cause the interrupt at the parent controller. Source is usually zero, 198 // but it could be different for your controller. 199 getPlatform()->causeInterrupt(0); 200 } 201