|
|
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 "Heathrow.h" ! 40: ! 41: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 42: ! 43: #define super AppleMacIO ! 44: ! 45: OSDefineMetaClassAndStructors(Heathrow, AppleMacIO); ! 46: ! 47: bool Heathrow::start(IOService *provider) ! 48: { ! 49: bool ret; ! 50: ! 51: // Call MacIO's start. ! 52: if (!super::start(provider)) ! 53: return false; ! 54: ! 55: // Figure out which heathrow this is. ! 56: if (IODTMatchNubWithKeys(provider, "heathrow")) ! 57: heathrowNum = kPrimaryHeathrow; ! 58: else if (IODTMatchNubWithKeys(provider, "gatwick")) ! 59: heathrowNum = kSecondaryHeathrow; ! 60: else return false; // This should not happen. ! 61: ! 62: if (heathrowNum == kPrimaryHeathrow) { ! 63: if (getPlatform()->getFamily() != 3) ! 64: getPlatform()->setCPUInterruptProperties(provider); ! 65: } ! 66: ! 67: // get the base address of the this heathrow. ! 68: heathrowBaseAddress = fMemory->getVirtualAddress(); ! 69: ! 70: // Make nubs for the children. ! 71: publishBelow( provider ); ! 72: ! 73: ret = installInterrupts(provider); ! 74: ! 75: return ret; ! 76: } ! 77: ! 78: bool Heathrow::installInterrupts(IOService *provider) ! 79: { ! 80: IORegistryEntry *regEntry; ! 81: OSSymbol *interruptControllerName; ! 82: IOInterruptAction handler; ! 83: AppleNMI *appleNMI; ! 84: long nmiSource; ! 85: OSData *nmiData; ! 86: IOReturn error; ! 87: ! 88: // Everything below here is for interrupts, return true if ! 89: // interrupts are not needed. ! 90: if (getPlatform()->getFamily() == 3) return true; ! 91: ! 92: // get the name of the interrupt controller ! 93: if( (regEntry = provider->childFromPath("interrupt-controller", ! 94: gIODTPlane))) { ! 95: interruptControllerName = (OSSymbol *)IODTInterruptControllerName(regEntry); ! 96: regEntry->release(); ! 97: } else ! 98: interruptControllerName = getInterruptControllerName(); ! 99: ! 100: // Allocate the interruptController instance. ! 101: interruptController = new HeathrowInterruptController; ! 102: if (interruptController == NULL) return false; ! 103: ! 104: // call the interruptController's init method. ! 105: error = interruptController->initInterruptController(provider, heathrowBaseAddress); ! 106: if (error != kIOReturnSuccess) return false; ! 107: ! 108: handler = interruptController->getInterruptHandlerAddress(); ! 109: provider->registerInterrupt(0, interruptController, handler, 0); ! 110: ! 111: provider->enableInterrupt(0); ! 112: ! 113: // Register the interrupt controller so clients can find it. ! 114: getPlatform()->registerInterruptController(interruptControllerName, ! 115: interruptController); ! 116: ! 117: if (heathrowNum != kPrimaryHeathrow) return true; ! 118: ! 119: // Create the NMI Driver. ! 120: nmiSource = 20; ! 121: nmiData = OSData::withBytes(&nmiSource, sizeof(long)); ! 122: appleNMI = new AppleNMI; ! 123: if ((nmiData != 0) && (appleNMI != 0)) { ! 124: appleNMI->initNMI(interruptController, nmiData); ! 125: } ! 126: ! 127: return true; ! 128: } ! 129: ! 130: OSSymbol *Heathrow::getInterruptControllerName(void) ! 131: { ! 132: OSSymbol *interruptControllerName; ! 133: ! 134: switch (heathrowNum) { ! 135: case kPrimaryHeathrow : ! 136: interruptControllerName = (OSSymbol *)gIODTDefaultInterruptController; ! 137: break; ! 138: ! 139: case kSecondaryHeathrow : ! 140: interruptControllerName = (OSSymbol *)OSSymbol::withCStringNoCopy("SecondaryInterruptController"); ! 141: break; ! 142: ! 143: default: ! 144: interruptControllerName = (OSSymbol *)OSSymbol::withCStringNoCopy("UnknownInterruptController"); ! 145: break; ! 146: } ! 147: ! 148: return interruptControllerName; ! 149: } ! 150: ! 151: void Heathrow::processNub(IOService *nub) ! 152: { ! 153: int cnt, numSources; ! 154: OSArray *controllerNames, *controllerSources; ! 155: OSSymbol *interruptControllerName; ! 156: char *nubName; ! 157: unsigned long heathrowIDs, heathrowFCR; ! 158: ! 159: nubName = (char *)nub->getName(); ! 160: ! 161: // Turn on the media bay if this a PowerBook 101. ! 162: if (IODTMatchNubWithKeys(getPlatform()->getProvider(), "'PowerBook1,1'")) { ! 163: if (!strcmp(nubName, "media-bay")) { ! 164: heathrowIDs = lwbrx(heathrowBaseAddress + 0x34); ! 165: if ((heathrowIDs & 0x0000FF00) == 0x00003000) { ! 166: heathrowFCR = lwbrx(heathrowBaseAddress + 0x38); ! 167: heathrowFCR |= 0x00800000; ! 168: stwbrx(heathrowFCR, heathrowBaseAddress + 0x38); ! 169: IOSleep(500); ! 170: } ! 171: } ! 172: } ! 173: ! 174: // change the interrupt controller name for this nub ! 175: // if it is on the secondary heathrow. ! 176: if (heathrowNum == kPrimaryHeathrow) return; ! 177: ! 178: interruptControllerName = getInterruptControllerName(); ! 179: ! 180: if (!strcmp(nubName, "ch-a")) { ! 181: controllerSources = OSDynamicCast(OSArray, getProperty("vectors-escc-ch-a")); ! 182: } else if (!strcmp(nubName, "floppy")) { ! 183: controllerSources = OSDynamicCast(OSArray, getProperty("vectors-floppy")); ! 184: } else if (!strcmp(nubName, "ata4")) { ! 185: controllerSources = OSDynamicCast(OSArray, getProperty("vectors-ata4")); ! 186: } else return; ! 187: ! 188: numSources = controllerSources->getCount(); ! 189: ! 190: controllerNames = OSArray::withCapacity(numSources); ! 191: for (cnt = 0; cnt < numSources; cnt++) { ! 192: controllerNames->setObject(interruptControllerName); ! 193: } ! 194: ! 195: nub->setProperty(gIOInterruptControllersKey, controllerNames); ! 196: nub->setProperty(gIOInterruptSpecifiersKey, controllerSources); ! 197: } ! 198: ! 199: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 200: ! 201: #undef super ! 202: #define super IOInterruptController ! 203: ! 204: OSDefineMetaClassAndStructors(HeathrowInterruptController, IOInterruptController); ! 205: ! 206: IOReturn HeathrowInterruptController::initInterruptController(IOService *provider, IOLogicalAddress interruptControllerBase) ! 207: { ! 208: int cnt; ! 209: ! 210: parentNub = provider; ! 211: ! 212: // Allocate the task lock. ! 213: taskLock = IOLockAlloc(); ! 214: if (taskLock == 0) return kIOReturnNoResources; ! 215: ! 216: // Allocate the memory for the vectors ! 217: vectors = (IOInterruptVector *)IOMalloc(kNumVectors * sizeof(IOInterruptVector)); ! 218: if (vectors == NULL) { ! 219: IOLockFree(taskLock); ! 220: return kIOReturnNoMemory; ! 221: } ! 222: bzero(vectors, kNumVectors * sizeof(IOInterruptVector)); ! 223: ! 224: // Allocate locks for the ! 225: for (cnt = 0; cnt < kNumVectors; cnt++) { ! 226: vectors[cnt].interruptLock = IOLockAlloc(); ! 227: if (vectors[cnt].interruptLock == NULL) { ! 228: IOLockFree(taskLock); ! 229: for (cnt = 0; cnt < kNumVectors; cnt++) { ! 230: if (vectors[cnt].interruptLock != NULL) ! 231: IOLockFree(vectors[cnt].interruptLock); ! 232: } ! 233: return kIOReturnNoResources; ! 234: } ! 235: } ! 236: ! 237: // Setup the registers accessors ! 238: events1Reg = (unsigned long)(interruptControllerBase + kEvents1Offset); ! 239: events2Reg = (unsigned long)(interruptControllerBase + kEvents2Offset); ! 240: mask1Reg = (unsigned long)(interruptControllerBase + kMask1Offset); ! 241: mask2Reg = (unsigned long)(interruptControllerBase + kMask2Offset); ! 242: clear1Reg = (unsigned long)(interruptControllerBase + kClear1Offset); ! 243: clear2Reg = (unsigned long)(interruptControllerBase + kClear2Offset); ! 244: levels1Reg = (unsigned long)(interruptControllerBase + kLevels1Offset); ! 245: levels2Reg = (unsigned long)(interruptControllerBase + kLevels2Offset); ! 246: ! 247: // Initialize the registers. ! 248: ! 249: // Disable all interrupts. ! 250: stwbrx(0x00000000, mask1Reg); ! 251: stwbrx(0x00000000, mask2Reg); ! 252: eieio(); ! 253: ! 254: // Clear all pending interrupts. ! 255: stwbrx(0xFFFFFFFF, clear1Reg); ! 256: stwbrx(0xFFFFFFFF, clear2Reg); ! 257: eieio(); ! 258: ! 259: // Disable all interrupts. (again?) ! 260: stwbrx(0x00000000, mask1Reg); ! 261: stwbrx(0x00000000, mask2Reg); ! 262: eieio(); ! 263: ! 264: return kIOReturnSuccess; ! 265: } ! 266: ! 267: IOInterruptAction HeathrowInterruptController::getInterruptHandlerAddress(void) ! 268: { ! 269: return (IOInterruptAction)&HeathrowInterruptController::handleInterrupt; ! 270: } ! 271: ! 272: IOReturn HeathrowInterruptController::handleInterrupt(void * /*refCon*/, ! 273: IOService * /*nub*/, ! 274: int /*source*/) ! 275: { ! 276: int done; ! 277: long events, vectorNumber; ! 278: IOInterruptVector *vector; ! 279: unsigned long maskTmp; ! 280: ! 281: do { ! 282: done = 1; ! 283: ! 284: // Do all the sources for events1, plus any pending interrupts. ! 285: // Also add in the "level" sensitive sources ! 286: maskTmp = lwbrx(mask1Reg); ! 287: events = lwbrx(events1Reg) & ~kTypeLevelMask; ! 288: events |= lwbrx(levels1Reg) & maskTmp & kTypeLevelMask; ! 289: events |= pendingEvents1 & maskTmp; ! 290: pendingEvents1 = 0; ! 291: eieio(); ! 292: ! 293: // Since we have to clear the level'd one clear the current edge's too. ! 294: stwbrx(kTypeLevelMask | events, clear1Reg); ! 295: eieio(); ! 296: ! 297: if (events) done = 0; ! 298: ! 299: while (events) { ! 300: vectorNumber = 31 - cntlzw(events); ! 301: events ^= (1 << vectorNumber); ! 302: vector = &vectors[vectorNumber]; ! 303: ! 304: vector->interruptActive = 1; ! 305: sync(); ! 306: isync(); ! 307: if (!vector->interruptDisabledSoft) { ! 308: isync(); ! 309: ! 310: // Call the handler if it exists. ! 311: if (vector->interruptRegistered) { ! 312: vector->handler(vector->target, vector->refCon, ! 313: vector->nub, vector->source); ! 314: } ! 315: } else { ! 316: // Hard disable the source. ! 317: vector->interruptDisabledHard = 1; ! 318: disableVectorHard(vectorNumber, vector); ! 319: } ! 320: ! 321: vector->interruptActive = 0; ! 322: } ! 323: ! 324: // Do all the sources for events2, plus any pending interrupts. ! 325: maskTmp = lwbrx(mask2Reg); ! 326: events = lwbrx(events2Reg); ! 327: events |= pendingEvents1 & maskTmp; ! 328: pendingEvents2 = 0; ! 329: eieio(); ! 330: ! 331: if (events) { ! 332: done = 0; ! 333: stwbrx(events, clear2Reg); ! 334: eieio(); ! 335: } ! 336: ! 337: while (events) { ! 338: vectorNumber = 31 - cntlzw(events); ! 339: events ^= (1 << vectorNumber); ! 340: vector = &vectors[vectorNumber + kVectorsPerReg]; ! 341: ! 342: vector->interruptActive = 1; ! 343: sync(); ! 344: isync(); ! 345: if (!vector->interruptDisabledSoft) { ! 346: isync(); ! 347: ! 348: // Call the handler if it exists. ! 349: if (vector->interruptRegistered) { ! 350: vector->handler(vector->target, vector->refCon, ! 351: vector->nub, vector->source); ! 352: } ! 353: } else { ! 354: // Hard disable the source. ! 355: vector->interruptDisabledHard = 1; ! 356: disableVectorHard(vectorNumber + kVectorsPerReg, vector); ! 357: } ! 358: ! 359: vector->interruptActive = 0; ! 360: } ! 361: } while (!done); ! 362: ! 363: return kIOReturnSuccess; ! 364: } ! 365: ! 366: bool HeathrowInterruptController::vectorCanBeShared(long /*vectorNumber*/, IOInterruptVector */*vector*/) ! 367: { ! 368: return true; ! 369: } ! 370: ! 371: int HeathrowInterruptController::getVectorType(long vectorNumber, IOInterruptVector */*vector*/) ! 372: { ! 373: int interruptType; ! 374: ! 375: if (kTypeLevelMask & (1 << vectorNumber)) { ! 376: interruptType = kIOInterruptTypeLevel; ! 377: } else { ! 378: interruptType = kIOInterruptTypeEdge; ! 379: } ! 380: ! 381: return interruptType; ! 382: } ! 383: ! 384: void HeathrowInterruptController::disableVectorHard(long vectorNumber, IOInterruptVector */*vector*/) ! 385: { ! 386: unsigned long maskTmp; ! 387: ! 388: // Turn the source off at hardware. ! 389: if (vectorNumber < kVectorsPerReg) { ! 390: maskTmp = lwbrx(mask1Reg); ! 391: maskTmp &= ~(1 << vectorNumber); ! 392: stwbrx(maskTmp, mask1Reg); ! 393: eieio(); ! 394: } else { ! 395: vectorNumber -= kVectorsPerReg; ! 396: maskTmp = lwbrx(mask2Reg); ! 397: maskTmp &= ~(1 << vectorNumber); ! 398: stwbrx(maskTmp, mask2Reg); ! 399: eieio(); ! 400: } ! 401: } ! 402: ! 403: void HeathrowInterruptController::enableVector(long vectorNumber, ! 404: IOInterruptVector *vector) ! 405: { ! 406: unsigned long maskTmp; ! 407: ! 408: if (vectorNumber < kVectorsPerReg) { ! 409: maskTmp = lwbrx(mask1Reg); ! 410: maskTmp |= (1 << vectorNumber); ! 411: stwbrx(maskTmp, mask1Reg); ! 412: eieio(); ! 413: if (lwbrx(levels1Reg) & (1 << vectorNumber)) { ! 414: // lost the interrupt ! 415: causeVector(vectorNumber, vector); ! 416: } ! 417: } else { ! 418: vectorNumber -= kVectorsPerReg; ! 419: maskTmp = lwbrx(mask2Reg); ! 420: maskTmp |= (1 << vectorNumber); ! 421: stwbrx(maskTmp, mask2Reg); ! 422: eieio(); ! 423: if (lwbrx(levels1Reg) & (1 << vectorNumber)) { ! 424: // lost the interrupt ! 425: causeVector(vectorNumber + kVectorsPerReg, vector); ! 426: } ! 427: } ! 428: } ! 429: ! 430: void HeathrowInterruptController::causeVector(long vectorNumber, ! 431: IOInterruptVector */*vector*/) ! 432: { ! 433: if (vectorNumber < kVectorsPerReg) { ! 434: pendingEvents1 |= 1 << vectorNumber; ! 435: } else { ! 436: vectorNumber -= kVectorsPerReg; ! 437: pendingEvents2 |= 1 << vectorNumber; ! 438: } ! 439: ! 440: parentNub->causeInterrupt(0); ! 441: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.