Annotation of XNU/iokit/Drivers/platform/drvAppleMPIC/AppleMPIC.cpp, revision 1.1.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.