|
|
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: #include <ppc/proc_reg.h> ! 30: ! 31: #include <IOKit/IOLib.h> ! 32: #include <IOKit/IOService.h> ! 33: #include <IOKit/IODeviceTreeSupport.h> ! 34: #include <IOKit/IODeviceMemory.h> ! 35: #include <IOKit/IOPlatformExpert.h> ! 36: ! 37: #include "AppleVIA.h" ! 38: ! 39: ! 40: extern "C" { ! 41: extern void PE_Determine_Clock_Speeds(unsigned int via_addr, ! 42: int num_speeds, ! 43: unsigned long *speed_list); ! 44: } ! 45: ! 46: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 47: ! 48: #define super IOService ! 49: ! 50: OSDefineMetaClassAndStructors(AppleVIA, IOService); ! 51: ! 52: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 53: ! 54: bool AppleVIA::start(IOService *provider) ! 55: { ! 56: AppleVIADevice *nub; ! 57: IOInterruptAction handler; ! 58: IOReturn error; ! 59: IOMemoryMap *viaMemoryMap; ! 60: OSSymbol *interruptControllerName; ! 61: int numSpeeds; ! 62: unsigned long *speedList; ! 63: ! 64: // Call super's start. ! 65: if (!super::start(provider)) ! 66: return false; ! 67: ! 68: // Figure out what kind of via device nub to make. ! 69: if (IODTMatchNubWithKeys(provider, "'via-cuda'")) ! 70: viaDeviceType = kVIADeviceTypeCuda; ! 71: else if (IODTMatchNubWithKeys(provider, "'via-pmu'")) ! 72: viaDeviceType = kVIADeviceTypePMU; ! 73: else viaDeviceType = -1; // This should not happen. ! 74: ! 75: // get the via's base address ! 76: viaMemoryMap = provider->mapDeviceMemoryWithIndex(0); ! 77: if (viaMemoryMap == 0) return false; ! 78: viaBaseAddress = viaMemoryMap->getVirtualAddress(); ! 79: viaMemoryMap->release(); ! 80: ! 81: // Calculate the bus and cpu speeds. ! 82: getPlatform()->getDefaultBusSpeeds(&numSpeeds, &speedList); ! 83: PE_Determine_Clock_Speeds(viaBaseAddress, numSpeeds, speedList); ! 84: ! 85: // Allocate the interruptController instance. ! 86: interruptController = new AppleVIAInterruptController; ! 87: if (interruptController == NULL) return false; ! 88: ! 89: // call the interruptController's init method. ! 90: error = interruptController->initInterruptController(provider, ! 91: viaBaseAddress); ! 92: if (error != kIOReturnSuccess) return false; ! 93: ! 94: handler = interruptController->getInterruptHandlerAddress(); ! 95: provider->registerInterrupt(0, interruptController, handler, 0); ! 96: ! 97: provider->enableInterrupt(0); ! 98: ! 99: // Register the interrupt controller so clients can find it. ! 100: interruptControllerName = OSSymbol::withCStringNoCopy(kInterruptControllerName); ! 101: getPlatform()->registerInterruptController(interruptControllerName, ! 102: interruptController); ! 103: ! 104: nub = createNub(); ! 105: if (nub == 0) return false; ! 106: ! 107: nub->attach(this); ! 108: nub->registerService(); ! 109: ! 110: return true; ! 111: } ! 112: ! 113: AppleVIADevice *AppleVIA::createNub(void) ! 114: { ! 115: int cnt; ! 116: bool err; ! 117: OSSymbol *cName; ! 118: OSSymbol *name = 0; ! 119: OSArray *array = 0, *vecArray = 0, *deviceMemoryArray; ! 120: OSDictionary *dict = 0; ! 121: AppleVIADevice *nub = 0; ! 122: ! 123: do { ! 124: // create the name symbol for the interrupt controller. ! 125: cName = OSSymbol::withCStringNoCopy(kInterruptControllerName); ! 126: if (cName == 0) continue; ! 127: ! 128: // create the vector array. ! 129: vecArray = OSDynamicCast(OSArray, getProperty("vectors")); ! 130: if ((vecArray == 0) || (vecArray->getCount() != kNumVectors)) continue; ! 131: ! 132: // create the controller array. ! 133: array = OSArray::withCapacity(kNumVectors); ! 134: if (array == 0) continue; ! 135: ! 136: // populate the names array ! 137: err = false; ! 138: for (cnt = 0; cnt < kNumVectors; cnt++) { ! 139: if (!array->setObject(cName)) { ! 140: err = true; ! 141: break; ! 142: } ! 143: } ! 144: if (err) continue; ! 145: ! 146: // create the deviceMemory array. ! 147: deviceMemoryArray = getProvider()->getDeviceMemory(); ! 148: if (deviceMemoryArray == 0) continue; ! 149: ! 150: // create the name for the viaDevice nub ! 151: if (viaDeviceType == kVIADeviceTypeCuda) ! 152: name = OSSymbol::withCStringNoCopy("cuda"); ! 153: else if (viaDeviceType == kVIADeviceTypePMU) ! 154: name = OSSymbol::withCStringNoCopy("pmu"); ! 155: else name = 0; ! 156: if (name == 0) continue; ! 157: ! 158: // Create the dictionary for the viaDevice nub. ! 159: dict = OSDictionary::withCapacity(1); ! 160: if (dict == 0) continue; ! 161: ! 162: // add the interrupt numbers and parents to the dictionary. ! 163: err = !dict->setObject("name", name); ! 164: err |= !dict->setObject(gIOInterruptSpecifiersKey, vecArray); ! 165: err |= !dict->setObject(gIOInterruptControllersKey, array); ! 166: if (err) continue; ! 167: ! 168: // Create the viaDevice nub ! 169: nub = new AppleVIADevice; ! 170: if (nub == 0) continue; ! 171: ! 172: if (!nub->init(dict)) { ! 173: nub->release(); ! 174: nub = 0; ! 175: continue; ! 176: } ! 177: ! 178: // set the nub's name. ! 179: nub->setName(name); ! 180: ! 181: // set the nub's deviceMemory. ! 182: nub->setDeviceMemory(deviceMemoryArray); ! 183: ! 184: } while(false); ! 185: ! 186: if(name) name->release(); ! 187: if(cName) cName->release(); ! 188: if(array) array->release(); ! 189: if(dict) dict->release(); ! 190: ! 191: return nub; ! 192: } ! 193: ! 194: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 195: ! 196: #undef super ! 197: #define super IOService ! 198: ! 199: OSDefineMetaClassAndStructors(AppleVIADevice, IOService); ! 200: ! 201: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 202: ! 203: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 204: ! 205: #undef super ! 206: #define super IOInterruptController ! 207: ! 208: OSDefineMetaClassAndStructors(AppleVIAInterruptController, IOInterruptController); ! 209: ! 210: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 211: ! 212: IOReturn AppleVIAInterruptController::initInterruptController(IOService *provider, IOLogicalAddress interruptControllerBase) ! 213: { ! 214: int cnt; ! 215: ! 216: parentNub = provider; ! 217: ! 218: // Allocate the memory for the vectors ! 219: vectors = (IOInterruptVector *)IOMalloc(kNumVectors * ! 220: sizeof(IOInterruptVector)); ! 221: if (vectors == NULL) return kIOReturnNoMemory; ! 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: for (cnt = 0; cnt < kNumVectors; cnt++) { ! 229: if (vectors[cnt].interruptLock != NULL) ! 230: IOLockFree(vectors[cnt].interruptLock); ! 231: } ! 232: return kIOReturnNoResources; ! 233: } ! 234: } ! 235: ! 236: // Initialize the registers. ! 237: IEReg = (volatile unsigned char *)(interruptControllerBase + kIEOffset); ! 238: IFReg = (volatile unsigned char *)(interruptControllerBase + kIFOffset); ! 239: PCReg = (volatile unsigned char *)(interruptControllerBase + kPCOffset); ! 240: ! 241: // Disable all interrupts. ! 242: *PCReg = 0x00; eieio(); ! 243: *IEReg = 0x00; eieio(); ! 244: *IFReg = 0x7F; eieio(); ! 245: ! 246: return kIOReturnSuccess; ! 247: } ! 248: ! 249: IOInterruptAction AppleVIAInterruptController::getInterruptHandlerAddress(void) ! 250: { ! 251: return (IOInterruptAction)&AppleVIAInterruptController::handleInterrupt; ! 252: } ! 253: ! 254: IOReturn AppleVIAInterruptController::handleInterrupt(void */*refCon*/, ! 255: IOService */*nub*/, ! 256: int /*source*/) ! 257: { ! 258: int done; ! 259: long events, vectorNumber; ! 260: IOInterruptVector *vector; ! 261: ! 262: do { ! 263: done = 1; ! 264: ! 265: // Do all the sources for events. ! 266: events = *IFReg; eieio(); ! 267: events |= pendingEvents; ! 268: pendingEvents = 0; ! 269: events &= *IEReg & 0x7F; eieio(); ! 270: ! 271: if (events) { ! 272: done = 0; ! 273: *IFReg = events; eieio(); ! 274: } ! 275: ! 276: while (events) { ! 277: vectorNumber = 31 - cntlzw(events); ! 278: events ^= (1 << vectorNumber); ! 279: vector = &vectors[vectorNumber]; ! 280: ! 281: vector->interruptActive = 1; ! 282: sync(); ! 283: isync(); ! 284: if (!vector->interruptDisabledSoft) { ! 285: isync(); ! 286: ! 287: // Call the handler if it exists. ! 288: if (vector->interruptRegistered) { ! 289: vector->handler(vector->target, vector->refCon, ! 290: vector->nub, vector->source); ! 291: } ! 292: } else { ! 293: // Hard disable the source. ! 294: vector->interruptDisabledHard = 1; ! 295: disableVectorHard(vectorNumber, vector); ! 296: } ! 297: ! 298: vector->interruptActive = 0; ! 299: } ! 300: ! 301: } while (!done); ! 302: ! 303: return kIOReturnSuccess; ! 304: } ! 305: ! 306: void AppleVIAInterruptController::disableVectorHard(long vectorNumber, IOInterruptVector */*vector*/) ! 307: { ! 308: *IEReg &= ~(1 << vectorNumber); ! 309: eieio(); ! 310: } ! 311: ! 312: void AppleVIAInterruptController::enableVector(long vectorNumber, ! 313: IOInterruptVector *vector) ! 314: { ! 315: *IEReg |= (1 << vectorNumber); ! 316: eieio(); ! 317: } ! 318: ! 319: void AppleVIAInterruptController::causeVector(long vectorNumber, ! 320: IOInterruptVector */*vector*/) ! 321: { ! 322: pendingEvents |= 1 << vectorNumber; ! 323: parentNub->causeInterrupt(0); ! 324: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.