Annotation of XNU/iokit/Drivers/platform/drvAppleOHare/OHare.cpp, revision 1.1

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 "OHare.h"
        !            40: 
        !            41: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
        !            42: 
        !            43: #define super AppleMacIO
        !            44: 
        !            45: OSDefineMetaClassAndStructors(OHare, AppleMacIO);
        !            46: 
        !            47: bool OHare::start(IOService *provider)
        !            48: {
        !            49:   IOInterruptAction  handler;
        !            50:   OSSymbol           *interruptControllerName;
        !            51:   AppleNMI           *appleNMI;
        !            52:   long               nmiSource;
        !            53:   OSData             *nmiData;
        !            54:   IOReturn           error;
        !            55:   
        !            56:   // Call MacIO's start.
        !            57:   if (!super::start(provider))
        !            58:     return false;
        !            59:   
        !            60:   // Figure out which ohare this is.
        !            61:   if (IODTMatchNubWithKeys(provider, "ohare"))
        !            62:     ohareNum = kPrimaryOHare;
        !            63:   else if (IODTMatchNubWithKeys(provider, "'pci106b,7'"))
        !            64:     ohareNum = kSecondaryOHare;
        !            65:   else return false;  // This should not happen.
        !            66:   
        !            67:   if (ohareNum == kPrimaryOHare) {
        !            68:     getPlatform()->setCPUInterruptProperties(provider);
        !            69:   }
        !            70:   
        !            71:   // Make nubs for the children.
        !            72:   publishBelow( provider );
        !            73:   
        !            74:   // get the base address of the this OHare.
        !            75:   ohareBaseAddress = fMemory->getVirtualAddress();
        !            76:   
        !            77:   // get the name of the interrupt controller
        !            78:   interruptControllerName  = getInterruptControllerName();
        !            79:   
        !            80:   // Allocate the interruptController instance.
        !            81:   interruptController = new OHareInterruptController;
        !            82:   if (interruptController == NULL) return false;
        !            83:   
        !            84:   // call the interruptController's init method.
        !            85:   error = interruptController->initInterruptController(provider, ohareBaseAddress);
        !            86:   if (error != kIOReturnSuccess) return false;
        !            87:   
        !            88:   handler = interruptController->getInterruptHandlerAddress();
        !            89:   provider->registerInterrupt(0, interruptController, handler, 0);
        !            90:   
        !            91:   provider->enableInterrupt(0);
        !            92:   
        !            93:   // Register the interrupt controller so clients can find it.
        !            94:   getPlatform()->registerInterruptController(interruptControllerName,
        !            95:                                             interruptController);
        !            96:   
        !            97:   if (ohareNum != kPrimaryOHare) return true;
        !            98:   
        !            99:   // Create the NMI Driver.
        !           100:   nmiSource = 20;
        !           101:   nmiData = OSData::withBytes(&nmiSource, sizeof(long));
        !           102:   appleNMI = new AppleNMI;
        !           103:   if ((nmiData != 0) && (appleNMI != 0)) {
        !           104:     appleNMI->initNMI(interruptController, nmiData);
        !           105:   } 
        !           106:   
        !           107:   return true;
        !           108: }
        !           109: 
        !           110: OSSymbol *OHare::getInterruptControllerName(void)
        !           111: {
        !           112:   OSSymbol *interruptControllerName;
        !           113:   
        !           114:   switch (ohareNum) {
        !           115:   case kPrimaryOHare :
        !           116:     interruptControllerName = gIODTDefaultInterruptController;
        !           117:     break;
        !           118:     
        !           119:   case kSecondaryOHare :
        !           120:     interruptControllerName = OSSymbol::withCStringNoCopy("SecondaryInterruptController");
        !           121:     break;
        !           122:     
        !           123:   default:
        !           124:     interruptControllerName = OSSymbol::withCStringNoCopy("UnknownInterruptController");
        !           125:     break;
        !           126:   }
        !           127:   
        !           128:   return interruptControllerName;
        !           129: }
        !           130: 
        !           131: 
        !           132: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
        !           133: 
        !           134: #undef  super
        !           135: #define super IOInterruptController
        !           136: 
        !           137: OSDefineMetaClassAndStructors(OHareInterruptController, IOInterruptController);
        !           138: 
        !           139: IOReturn OHareInterruptController::initInterruptController(IOService *provider, IOLogicalAddress interruptControllerBase)
        !           140: {
        !           141:   int cnt;
        !           142:   
        !           143:   parentNub = provider;
        !           144:   
        !           145:   // Allocate the task lock.
        !           146:   taskLock = IOLockAlloc();
        !           147:   if (taskLock == 0) return kIOReturnNoResources;
        !           148:   
        !           149:   // Allocate the memory for the vectors
        !           150:   vectors = (IOInterruptVector *)IOMalloc(kNumVectors * sizeof(IOInterruptVector));
        !           151:   if (vectors == NULL) {
        !           152:     IOLockFree(taskLock);
        !           153:     return kIOReturnNoMemory;
        !           154:   }
        !           155:   bzero(vectors, kNumVectors * sizeof(IOInterruptVector));
        !           156:   
        !           157:   // Allocate locks for the 
        !           158:   for (cnt = 0; cnt < kNumVectors; cnt++) {
        !           159:     vectors[cnt].interruptLock = IOLockAlloc();
        !           160:     if (vectors[cnt].interruptLock == NULL) {
        !           161:       for (cnt = 0; cnt < kNumVectors; cnt++) {
        !           162:        IOLockFree(taskLock);
        !           163:        if (vectors[cnt].interruptLock != NULL)
        !           164:          IOLockFree(vectors[cnt].interruptLock);
        !           165:       }
        !           166:       return kIOReturnNoResources;
        !           167:     }
        !           168:   }
        !           169:   
        !           170:   // Setup the registers accessors
        !           171:   eventsReg = (unsigned long)(interruptControllerBase + kEventsOffset);
        !           172:   maskReg   = (unsigned long)(interruptControllerBase + kMaskOffset);
        !           173:   clearReg  = (unsigned long)(interruptControllerBase + kClearOffset);
        !           174:   levelsReg = (unsigned long)(interruptControllerBase + kLevelsOffset);
        !           175:   
        !           176:   // Initialize the registers.
        !           177:   
        !           178:   // Disable all interrupts.
        !           179:   stwbrx(0x00000000, maskReg);
        !           180:   eieio();
        !           181:   
        !           182:   // Clear all pending interrupts.
        !           183:   stwbrx(0xFFFFFFFF, clearReg);
        !           184:   eieio();
        !           185:   
        !           186:   // Disable all interrupts. (again?)
        !           187:   stwbrx(0x00000000, maskReg);
        !           188:   eieio();
        !           189:   
        !           190:   return kIOReturnSuccess;
        !           191: }
        !           192: 
        !           193: IOInterruptAction OHareInterruptController::getInterruptHandlerAddress(void)
        !           194: {
        !           195:   return (IOInterruptAction)&OHareInterruptController::handleInterrupt;
        !           196: }
        !           197: 
        !           198: IOReturn OHareInterruptController::handleInterrupt(void * /*refCon*/,
        !           199:                                                   IOService * /*nub*/,
        !           200:                                                   int /*source*/)
        !           201: {
        !           202:   int               done;
        !           203:   long              events, vectorNumber;
        !           204:   IOInterruptVector *vector;
        !           205:   unsigned long     maskTmp;
        !           206: 
        !           207:   do {
        !           208:     done = 1;
        !           209:     
        !           210:     // Do all the sources for events, plus any pending interrupts.
        !           211:     // Also add in the "level" sensitive sources
        !           212:     maskTmp = lwbrx(maskReg);
        !           213:     events = lwbrx(eventsReg) & ~kTypeLevelMask;
        !           214:     events |= lwbrx(levelsReg) & maskTmp & kTypeLevelMask;
        !           215:     events |= pendingEvents & maskTmp;
        !           216:     pendingEvents = 0;
        !           217:     eieio();
        !           218: 
        !           219:     // Since we have to clear the level'd one clear the current edge's too.
        !           220:     stwbrx(kTypeLevelMask | events, clearReg);
        !           221:     eieio();
        !           222:     
        !           223:     if (events) done = 0;
        !           224:     
        !           225:     while (events) {
        !           226:       vectorNumber = 31 - cntlzw(events);
        !           227:       events ^= (1 << vectorNumber);
        !           228:       vector = &vectors[vectorNumber];
        !           229:       
        !           230:       vector->interruptActive = 1;
        !           231:       sync();
        !           232:       isync();
        !           233:       if (!vector->interruptDisabledSoft) {
        !           234:        isync();
        !           235:        
        !           236:        // Call the handler if it exists.
        !           237:        if (vector->interruptRegistered) {
        !           238:          vector->handler(vector->target, vector->refCon,
        !           239:                          vector->nub, vector->source);
        !           240:        }
        !           241:       } else {
        !           242:        // Hard disable the source.
        !           243:        vector->interruptDisabledHard = 1;
        !           244:        disableVectorHard(vectorNumber, vector);
        !           245:       }
        !           246:       
        !           247:       vector->interruptActive = 0;
        !           248:     }
        !           249:   } while (!done);
        !           250:   
        !           251:   return kIOReturnSuccess;
        !           252: }
        !           253: 
        !           254: bool OHareInterruptController::vectorCanBeShared(long /*vectorNumber*/, IOInterruptVector */*vector*/)
        !           255: {
        !           256:   return true;
        !           257: }
        !           258: 
        !           259: int OHareInterruptController::getVectorType(long vectorNumber, IOInterruptVector */*vector*/)
        !           260: {
        !           261:   int interruptType;
        !           262:   
        !           263:   if (kTypeLevelMask & (1 << vectorNumber)) {
        !           264:     interruptType = kIOInterruptTypeLevel;
        !           265:   } else {
        !           266:     interruptType = kIOInterruptTypeEdge;
        !           267:   }
        !           268:   
        !           269:   return interruptType;
        !           270: }
        !           271: 
        !           272: void OHareInterruptController::disableVectorHard(long vectorNumber, IOInterruptVector */*vector*/)
        !           273: {
        !           274:   unsigned long     maskTmp;
        !           275:   
        !           276:   // Turn the source off at hardware.
        !           277:   maskTmp = lwbrx(maskReg);
        !           278:   maskTmp &= ~(1 << vectorNumber);
        !           279:   stwbrx(maskTmp, maskReg);
        !           280:   eieio();
        !           281: }
        !           282: 
        !           283: void OHareInterruptController::enableVector(long vectorNumber,
        !           284:                                            IOInterruptVector *vector)
        !           285: {
        !           286:   unsigned long     maskTmp;
        !           287:   
        !           288:   maskTmp = lwbrx(maskReg);
        !           289:   maskTmp |= (1 << vectorNumber);
        !           290:   stwbrx(maskTmp, maskReg);
        !           291:   eieio();
        !           292:   if (lwbrx(levelsReg) & (1 << vectorNumber)) {
        !           293:     // lost the interrupt
        !           294:     causeVector(vectorNumber, vector);
        !           295:   }
        !           296: }
        !           297: 
        !           298: void OHareInterruptController::causeVector(long vectorNumber,
        !           299:                                           IOInterruptVector */*vector*/)
        !           300: {
        !           301:   pendingEvents |= 1 << vectorNumber;
        !           302:   parentNub->causeInterrupt(0);
        !           303: }

unix.superglobalmegacorp.com

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