Annotation of XNU/iokit/Drivers/platform/drvAppleMPIC/AppleMPIC.cpp, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.