|
|
1.1 ! root 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: ! 29: ! 30: #include <ppc/proc_reg.h> ! 31: ! 32: #include <IOKit/IOLib.h> ! 33: #include <IOKit/IODeviceTreeSupport.h> ! 34: #include <IOKit/IODeviceMemory.h> ! 35: #include <IOKit/IOPlatformExpert.h> ! 36: ! 37: #include "../drvAppleNMI/AppleNMI.h" ! 38: ! 39: #include "OHare.h" ! 40: ! 41: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 42: ! 43: #define super AppleMacIO ! 44: ! 45: OSDefineMetaClassAndStructors(OHare, AppleMacIO); ! 46: ! 47: bool OHare::start(IOService *provider) ! 48: { ! 49: IOInterruptAction handler; ! 50: OSSymbol *interruptControllerName; ! 51: AppleNMI *appleNMI; ! 52: long nmiSource; ! 53: OSData *nmiData; ! 54: IOReturn error; ! 55: ! 56: // Call MacIO's start. ! 57: if (!super::start(provider)) ! 58: return false; ! 59: ! 60: // Figure out which ohare this is. ! 61: if (IODTMatchNubWithKeys(provider, "ohare")) ! 62: ohareNum = kPrimaryOHare; ! 63: else if (IODTMatchNubWithKeys(provider, "'pci106b,7'")) ! 64: ohareNum = kSecondaryOHare; ! 65: else return false; // This should not happen. ! 66: ! 67: if (ohareNum == kPrimaryOHare) { ! 68: getPlatform()->setCPUInterruptProperties(provider); ! 69: } ! 70: ! 71: // Make nubs for the children. ! 72: publishBelow( provider ); ! 73: ! 74: // get the base address of the this OHare. ! 75: ohareBaseAddress = fMemory->getVirtualAddress(); ! 76: ! 77: // get the name of the interrupt controller ! 78: interruptControllerName = getInterruptControllerName(); ! 79: ! 80: // Allocate the interruptController instance. ! 81: interruptController = new OHareInterruptController; ! 82: if (interruptController == NULL) return false; ! 83: ! 84: // call the interruptController's init method. ! 85: error = interruptController->initInterruptController(provider, ohareBaseAddress); ! 86: if (error != kIOReturnSuccess) return false; ! 87: ! 88: handler = interruptController->getInterruptHandlerAddress(); ! 89: provider->registerInterrupt(0, interruptController, handler, 0); ! 90: ! 91: provider->enableInterrupt(0); ! 92: ! 93: // Register the interrupt controller so clients can find it. ! 94: getPlatform()->registerInterruptController(interruptControllerName, ! 95: interruptController); ! 96: ! 97: if (ohareNum != kPrimaryOHare) return true; ! 98: ! 99: // Create the NMI Driver. ! 100: nmiSource = 20; ! 101: nmiData = OSData::withBytes(&nmiSource, sizeof(long)); ! 102: appleNMI = new AppleNMI; ! 103: if ((nmiData != 0) && (appleNMI != 0)) { ! 104: appleNMI->initNMI(interruptController, nmiData); ! 105: } ! 106: ! 107: return true; ! 108: } ! 109: ! 110: OSSymbol *OHare::getInterruptControllerName(void) ! 111: { ! 112: OSSymbol *interruptControllerName; ! 113: ! 114: switch (ohareNum) { ! 115: case kPrimaryOHare : ! 116: interruptControllerName = gIODTDefaultInterruptController; ! 117: break; ! 118: ! 119: case kSecondaryOHare : ! 120: interruptControllerName = OSSymbol::withCStringNoCopy("SecondaryInterruptController"); ! 121: break; ! 122: ! 123: default: ! 124: interruptControllerName = OSSymbol::withCStringNoCopy("UnknownInterruptController"); ! 125: break; ! 126: } ! 127: ! 128: return interruptControllerName; ! 129: } ! 130: ! 131: ! 132: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 133: ! 134: #undef super ! 135: #define super IOInterruptController ! 136: ! 137: OSDefineMetaClassAndStructors(OHareInterruptController, IOInterruptController); ! 138: ! 139: IOReturn OHareInterruptController::initInterruptController(IOService *provider, IOLogicalAddress interruptControllerBase) ! 140: { ! 141: int cnt; ! 142: ! 143: parentNub = provider; ! 144: ! 145: // Allocate the task lock. ! 146: taskLock = IOLockAlloc(); ! 147: if (taskLock == 0) return kIOReturnNoResources; ! 148: ! 149: // Allocate the memory for the vectors ! 150: vectors = (IOInterruptVector *)IOMalloc(kNumVectors * sizeof(IOInterruptVector)); ! 151: if (vectors == NULL) { ! 152: IOLockFree(taskLock); ! 153: return kIOReturnNoMemory; ! 154: } ! 155: bzero(vectors, kNumVectors * sizeof(IOInterruptVector)); ! 156: ! 157: // Allocate locks for the ! 158: for (cnt = 0; cnt < kNumVectors; cnt++) { ! 159: vectors[cnt].interruptLock = IOLockAlloc(); ! 160: if (vectors[cnt].interruptLock == NULL) { ! 161: for (cnt = 0; cnt < kNumVectors; cnt++) { ! 162: IOLockFree(taskLock); ! 163: if (vectors[cnt].interruptLock != NULL) ! 164: IOLockFree(vectors[cnt].interruptLock); ! 165: } ! 166: return kIOReturnNoResources; ! 167: } ! 168: } ! 169: ! 170: // Setup the registers accessors ! 171: eventsReg = (unsigned long)(interruptControllerBase + kEventsOffset); ! 172: maskReg = (unsigned long)(interruptControllerBase + kMaskOffset); ! 173: clearReg = (unsigned long)(interruptControllerBase + kClearOffset); ! 174: levelsReg = (unsigned long)(interruptControllerBase + kLevelsOffset); ! 175: ! 176: // Initialize the registers. ! 177: ! 178: // Disable all interrupts. ! 179: stwbrx(0x00000000, maskReg); ! 180: eieio(); ! 181: ! 182: // Clear all pending interrupts. ! 183: stwbrx(0xFFFFFFFF, clearReg); ! 184: eieio(); ! 185: ! 186: // Disable all interrupts. (again?) ! 187: stwbrx(0x00000000, maskReg); ! 188: eieio(); ! 189: ! 190: return kIOReturnSuccess; ! 191: } ! 192: ! 193: IOInterruptAction OHareInterruptController::getInterruptHandlerAddress(void) ! 194: { ! 195: return (IOInterruptAction)&OHareInterruptController::handleInterrupt; ! 196: } ! 197: ! 198: IOReturn OHareInterruptController::handleInterrupt(void * /*refCon*/, ! 199: IOService * /*nub*/, ! 200: int /*source*/) ! 201: { ! 202: int done; ! 203: long events, vectorNumber; ! 204: IOInterruptVector *vector; ! 205: unsigned long maskTmp; ! 206: ! 207: do { ! 208: done = 1; ! 209: ! 210: // Do all the sources for events, plus any pending interrupts. ! 211: // Also add in the "level" sensitive sources ! 212: maskTmp = lwbrx(maskReg); ! 213: events = lwbrx(eventsReg) & ~kTypeLevelMask; ! 214: events |= lwbrx(levelsReg) & maskTmp & kTypeLevelMask; ! 215: events |= pendingEvents & maskTmp; ! 216: pendingEvents = 0; ! 217: eieio(); ! 218: ! 219: // Since we have to clear the level'd one clear the current edge's too. ! 220: stwbrx(kTypeLevelMask | events, clearReg); ! 221: eieio(); ! 222: ! 223: if (events) done = 0; ! 224: ! 225: while (events) { ! 226: vectorNumber = 31 - cntlzw(events); ! 227: events ^= (1 << vectorNumber); ! 228: vector = &vectors[vectorNumber]; ! 229: ! 230: vector->interruptActive = 1; ! 231: sync(); ! 232: isync(); ! 233: if (!vector->interruptDisabledSoft) { ! 234: isync(); ! 235: ! 236: // Call the handler if it exists. ! 237: if (vector->interruptRegistered) { ! 238: vector->handler(vector->target, vector->refCon, ! 239: vector->nub, vector->source); ! 240: } ! 241: } else { ! 242: // Hard disable the source. ! 243: vector->interruptDisabledHard = 1; ! 244: disableVectorHard(vectorNumber, vector); ! 245: } ! 246: ! 247: vector->interruptActive = 0; ! 248: } ! 249: } while (!done); ! 250: ! 251: return kIOReturnSuccess; ! 252: } ! 253: ! 254: bool OHareInterruptController::vectorCanBeShared(long /*vectorNumber*/, IOInterruptVector */*vector*/) ! 255: { ! 256: return true; ! 257: } ! 258: ! 259: int OHareInterruptController::getVectorType(long vectorNumber, IOInterruptVector */*vector*/) ! 260: { ! 261: int interruptType; ! 262: ! 263: if (kTypeLevelMask & (1 << vectorNumber)) { ! 264: interruptType = kIOInterruptTypeLevel; ! 265: } else { ! 266: interruptType = kIOInterruptTypeEdge; ! 267: } ! 268: ! 269: return interruptType; ! 270: } ! 271: ! 272: void OHareInterruptController::disableVectorHard(long vectorNumber, IOInterruptVector */*vector*/) ! 273: { ! 274: unsigned long maskTmp; ! 275: ! 276: // Turn the source off at hardware. ! 277: maskTmp = lwbrx(maskReg); ! 278: maskTmp &= ~(1 << vectorNumber); ! 279: stwbrx(maskTmp, maskReg); ! 280: eieio(); ! 281: } ! 282: ! 283: void OHareInterruptController::enableVector(long vectorNumber, ! 284: IOInterruptVector *vector) ! 285: { ! 286: unsigned long maskTmp; ! 287: ! 288: maskTmp = lwbrx(maskReg); ! 289: maskTmp |= (1 << vectorNumber); ! 290: stwbrx(maskTmp, maskReg); ! 291: eieio(); ! 292: if (lwbrx(levelsReg) & (1 << vectorNumber)) { ! 293: // lost the interrupt ! 294: causeVector(vectorNumber, vector); ! 295: } ! 296: } ! 297: ! 298: void OHareInterruptController::causeVector(long vectorNumber, ! 299: IOInterruptVector */*vector*/) ! 300: { ! 301: pendingEvents |= 1 << vectorNumber; ! 302: parentNub->causeInterrupt(0); ! 303: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.