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

unix.superglobalmegacorp.com

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