|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 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-2000 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 "AppleMPIC.h" ! 38: ! 39: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 40: ! 41: #undef super ! 42: #define super IOInterruptController ! 43: ! 44: OSDefineMetaClassAndStructors(AppleMPICInterruptController, IOInterruptController); ! 45: ! 46: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 47: ! 48: bool AppleMPICInterruptController::start(IOService *provider) ! 49: { ! 50: long cnt, regTemp; ! 51: IOInterruptAction handler; ! 52: ! 53: if (!super::start(provider)) ! 54: return false; ! 55: ! 56: // If this is a PowerExpress get a different name. ! 57: if (getPlatform()->getFamily() == 3) { ! 58: interruptControllerName = gIODTDefaultInterruptController; ! 59: } else { ! 60: interruptControllerName = IODTInterruptControllerName(provider); ! 61: } ! 62: ! 63: // Map the MPIC's memory. ! 64: mpicMemoryMap = provider->mapDeviceMemoryWithIndex(0); ! 65: ! 66: if (mpicMemoryMap == 0) return false; ! 67: ! 68: // get the base address of the MPIC. ! 69: mpicBaseAddress = mpicMemoryMap->getVirtualAddress(); ! 70: ! 71: // Read the Feature Reporting Register ! 72: regTemp = lwbrx(mpicBaseAddress + kFeatureOffset); ! 73: numCPUs = ((regTemp & kFRRNumCPUMask) >> kFRRNumCPUShift) + 1; ! 74: numVectors = ((regTemp & kFRRNumIRQsMask) >> kFRRNumIRQsShift) + 1; ! 75: ! 76: // Allocate the memory for the senses. ! 77: senses = (long *)IOMalloc(((numVectors + numCPUs + 31) / 32)*sizeof(long)); ! 78: if (senses == NULL) return false; ! 79: for (cnt = 0; cnt < ((numVectors + numCPUs + 31) / 32); cnt++) ! 80: senses[cnt] = 0; ! 81: ! 82: // Allocate the memory for the vectors. ! 83: vectors = (IOInterruptVector *)IOMalloc((numVectors + numCPUs) * ! 84: sizeof(IOInterruptVector)); ! 85: if (vectors == NULL) return false; ! 86: bzero(vectors, (numVectors + numCPUs) * sizeof(IOInterruptVector)); ! 87: ! 88: // Allocate locks for the vectors. ! 89: for (cnt = 0; cnt < (numVectors + numCPUs) ; cnt++) { ! 90: vectors[cnt].interruptLock = IOLockAlloc(); ! 91: if (vectors[cnt].interruptLock == NULL) { ! 92: for (cnt = 0; cnt < (numVectors + numCPUs); cnt++) { ! 93: if (vectors[cnt].interruptLock != NULL) ! 94: IOLockFree(vectors[cnt].interruptLock); ! 95: } ! 96: return false; ! 97: } ! 98: } ! 99: ! 100: // Reset the MPIC. ! 101: stwbrx(kGCR0Reset, mpicBaseAddress + kGlobal0Offset); ! 102: eieio(); ! 103: ! 104: // Wait for the reset to complete. ! 105: do { ! 106: regTemp = lwbrx(mpicBaseAddress + kGlobal0Offset); ! 107: eieio(); ! 108: } while (regTemp & kGCR0Reset); ! 109: ! 110: // Clear and mask all the interrupt vectors. ! 111: for (cnt = 0; cnt < (numVectors + numCPUs); cnt++) { ! 112: stwbrx(kIntnVPRMask, mpicBaseAddress+kIntnVecPriOffset+kIntnStride*cnt); ! 113: } ! 114: eieio(); ! 115: ! 116: // Set the Spurious Vector Register. ! 117: stwbrx(kSpuriousVectorNumber, mpicBaseAddress + kSpurVectOffset); ! 118: ! 119: // Set 8259 Cascade Mode. ! 120: stwbrx(kGCR0Cascade, mpicBaseAddress + kGlobal0Offset); ! 121: ! 122: // Set the all CPUs Current Task Priority to zero. ! 123: for(cnt = 0; cnt < numCPUs; cnt++) { /* Do 'em all */ ! 124: stwbrx(0, mpicBaseAddress + kPnCurrTskPriOffset + (kPnStride * cnt)); ! 125: eieio(); ! 126: } ! 127: ! 128: registerService(); ! 129: ! 130: getPlatform()->setCPUInterruptProperties(provider); ! 131: ! 132: // register the interrupt handler so it can receive interrupts. ! 133: handler = getInterruptHandlerAddress(); ! 134: for (cnt = 0; cnt < numCPUs; cnt++) { ! 135: provider->registerInterrupt(cnt, this, handler, 0); ! 136: provider->enableInterrupt(cnt); ! 137: } ! 138: ! 139: // Register this interrupt controller so clients can find it. ! 140: getPlatform()->registerInterruptController(interruptControllerName, this); ! 141: ! 142: return true; ! 143: } ! 144: ! 145: IOReturn AppleMPICInterruptController::getInterruptType(IOService *nub, ! 146: int source, ! 147: int *interruptType) ! 148: { ! 149: IOInterruptSource *interruptSources; ! 150: OSData *vectorData; ! 151: long vectorNumber; ! 152: ! 153: if (interruptType == 0) return kIOReturnBadArgument; ! 154: ! 155: interruptSources = nub->_interruptSources; ! 156: vectorData = interruptSources[source].vectorData; ! 157: vectorNumber = *(long *)vectorData->getBytesNoCopy(); ! 158: *interruptType = ((long *)vectorData->getBytesNoCopy())[1]; ! 159: ! 160: return kIOReturnSuccess; ! 161: } ! 162: ! 163: IOInterruptAction AppleMPICInterruptController::getInterruptHandlerAddress(void) ! 164: { ! 165: return (IOInterruptAction)&AppleMPICInterruptController::handleInterrupt; ! 166: } ! 167: ! 168: IOReturn AppleMPICInterruptController::handleInterrupt(void */*refCon*/, ! 169: IOService */*nub*/, ! 170: int source) ! 171: { ! 172: long vectorNumber, level; ! 173: IOInterruptVector *vector; ! 174: ! 175: do { ! 176: vectorNumber = lwbrx(mpicBaseAddress + source*kPnStride + kPnIntAckOffset); ! 177: eieio(); ! 178: ! 179: if (vectorNumber == kSpuriousVectorNumber) break; ! 180: ! 181: level = senses[vectorNumber / 32] & (1 << (vectorNumber & 31)); ! 182: ! 183: if (!level) { ! 184: stwbrx(0, mpicBaseAddress + source * kPnStride + kPnEOIOffset); ! 185: eieio(); ! 186: } ! 187: ! 188: vector = &vectors[vectorNumber]; ! 189: ! 190: vector->interruptActive = 1; ! 191: sync(); ! 192: isync(); ! 193: if (!vector->interruptDisabledSoft) { ! 194: isync(); ! 195: ! 196: // Call the handler if it exists. ! 197: if (vector->interruptRegistered) { ! 198: vector->handler(vector->target, vector->refCon, ! 199: vector->nub, vector->source); ! 200: ! 201: if (level && vector->interruptDisabledSoft) { ! 202: // Hard disable the source. ! 203: vector->interruptDisabledHard = 1; ! 204: disableVectorHard(vectorNumber, vector); ! 205: } ! 206: } ! 207: } else { ! 208: // Hard disable the source. ! 209: vector->interruptDisabledHard = 1; ! 210: disableVectorHard(vectorNumber, vector); ! 211: } ! 212: ! 213: if (level) { ! 214: stwbrx(0, mpicBaseAddress + source * kPnStride + kPnEOIOffset); ! 215: eieio(); ! 216: } ! 217: ! 218: vector->interruptActive = 0; ! 219: ! 220: } while (1); ! 221: ! 222: return kIOReturnSuccess; ! 223: } ! 224: ! 225: bool AppleMPICInterruptController::vectorCanBeShared(long /*vectorNumber*/, IOInterruptVector */*vector*/) ! 226: { ! 227: return true; ! 228: } ! 229: ! 230: void AppleMPICInterruptController::initVector(long vectorNumber, IOInterruptVector *vector) ! 231: { ! 232: IOInterruptSource *interruptSources; ! 233: long vectorType; ! 234: OSData *vectorData; ! 235: long regTemp, vectorBase; ! 236: ! 237: // Get the vector's type. ! 238: interruptSources = vector->nub->_interruptSources; ! 239: vectorData = interruptSources[vector->source].vectorData; ! 240: vectorType = ((long *)vectorData->getBytesNoCopy())[1]; ! 241: ! 242: if (vectorType == kIOInterruptTypeEdge) { ! 243: senses[vectorNumber / 32] &= ~(1 << (vectorNumber & 31)); ! 244: } else { ! 245: senses[vectorNumber / 32] |= (1 << (vectorNumber & 31)); ! 246: } ! 247: ! 248: // Set the Vector/Priority and Destination Registers ! 249: if (vectorNumber < numVectors) { ! 250: vectorBase = mpicBaseAddress + kIntnStride * vectorNumber; ! 251: ! 252: regTemp = 0x1; // CPU 0 only. ! 253: stwbrx(regTemp, vectorBase + kIntnDestOffset); ! 254: eieio(); ! 255: ! 256: // Vectors start masked with priority 8. ! 257: regTemp = kIntnVPRMask | (8 << kIntnVPRPriorityShift); ! 258: regTemp |= (vectorType == kIOInterruptTypeLevel) ? kIntnVPRSense : 0; ! 259: regTemp |= vectorNumber << kIntnVPRVectorShift; ! 260: stwbrx(regTemp, vectorBase + kIntnVecPriOffset); ! 261: eieio(); ! 262: } else { ! 263: vectorBase = mpicBaseAddress + kIPInVecPriStride*(vectorNumber-numVectors); ! 264: ! 265: // IPI Vectors start masked with priority 14. ! 266: regTemp = kIntnVPRMask | (14 << kIntnVPRPriorityShift); ! 267: regTemp |= vectorNumber << kIntnVPRVectorShift; ! 268: stwbrx(regTemp, vectorBase + kIPInVecPriOffset); ! 269: eieio(); ! 270: } ! 271: } ! 272: ! 273: void AppleMPICInterruptController::disableVectorHard(long vectorNumber, IOInterruptVector */*vector*/) ! 274: { ! 275: long regTemp, vectorBase; ! 276: ! 277: if (vectorNumber < numVectors) { ! 278: vectorBase = mpicBaseAddress + kIntnVecPriOffset + ! 279: kIntnStride * vectorNumber; ! 280: } else { ! 281: vectorBase = mpicBaseAddress + kIPInVecPriOffset + ! 282: kIPInVecPriStride * (vectorNumber - numVectors); ! 283: } ! 284: ! 285: regTemp = lwbrx(vectorBase); ! 286: regTemp |= kIntnVPRMask; ! 287: stwbrx(regTemp, vectorBase); ! 288: eieio(); ! 289: } ! 290: ! 291: void AppleMPICInterruptController::enableVector(long vectorNumber, ! 292: IOInterruptVector */*vector*/) ! 293: { ! 294: long regTemp, vectorBase; ! 295: ! 296: if (vectorNumber < numVectors) { ! 297: vectorBase = mpicBaseAddress + kIntnVecPriOffset + ! 298: kIntnStride * vectorNumber; ! 299: } else { ! 300: vectorBase = mpicBaseAddress + kIPInVecPriOffset + ! 301: kIPInVecPriStride * (vectorNumber - numVectors); ! 302: } ! 303: ! 304: regTemp = lwbrx(vectorBase); ! 305: regTemp &= ~kIntnVPRMask; ! 306: stwbrx(regTemp, vectorBase); ! 307: eieio(); ! 308: } ! 309: ! 310: OSData *AppleMPICInterruptController::getIPIVector(long physCPU) ! 311: { ! 312: long tmpLongs[2]; ! 313: OSData *tmpData; ! 314: ! 315: if ((physCPU < 0) && (physCPU >= numCPUs)) return 0; ! 316: ! 317: tmpLongs[0] = numVectors + physCPU; ! 318: tmpLongs[1] = kIOInterruptTypeEdge; ! 319: ! 320: tmpData = OSData::withBytes(tmpLongs, 2 * sizeof(long)); ! 321: ! 322: return tmpData; ! 323: } ! 324: ! 325: void AppleMPICInterruptController::dispatchIPI(long source, long targetMask) ! 326: { ! 327: long ipiBase, cnt; ! 328: ! 329: ipiBase = mpicBaseAddress + kPnIPImDispOffset + kPnStride * source; ! 330: ! 331: for (cnt = 0; cnt < numCPUs; cnt++) { ! 332: if (targetMask & (1 << cnt)) { ! 333: stwbrx((1 << cnt), ipiBase + kPnIPImDispStride * cnt); ! 334: eieio(); ! 335: } ! 336: } ! 337: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.