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