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