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