Annotation of XNU/iokit/Drivers/platform/drvAppleVIA/AppleVIA.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: #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 "AppleVIA.h"
                     38: 
                     39: 
                     40: extern "C" {
                     41: extern void PE_Determine_Clock_Speeds(unsigned int via_addr,
                     42:                                      int num_speeds,
                     43:                                      unsigned long *speed_list);
                     44: }
                     45: 
                     46: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                     47: 
                     48: #define super IOService
                     49: 
                     50: OSDefineMetaClassAndStructors(AppleVIA, IOService);
                     51: 
                     52: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                     53: 
                     54: bool AppleVIA::start(IOService *provider)
                     55: {
                     56:   AppleVIADevice     *nub;
                     57:   IOInterruptAction  handler;
                     58:   IOReturn           error;
                     59:   IOMemoryMap        *viaMemoryMap;
                     60:   OSSymbol           *interruptControllerName;
                     61:   int                numSpeeds;
                     62:   unsigned long      *speedList;
                     63:   
                     64:   // Call super's start.
                     65:   if (!super::start(provider))
                     66:     return false;
                     67:   
                     68:   // Figure out what kind of via device nub to make.
                     69:   if (IODTMatchNubWithKeys(provider, "'via-cuda'"))
                     70:     viaDeviceType = kVIADeviceTypeCuda;
                     71:   else if (IODTMatchNubWithKeys(provider, "'via-pmu'"))
                     72:     viaDeviceType = kVIADeviceTypePMU;
                     73:   else viaDeviceType = -1;  // This should not happen.
                     74:   
                     75:   // get the via's base address
                     76:   viaMemoryMap = provider->mapDeviceMemoryWithIndex(0);
                     77:   if (viaMemoryMap == 0) return false;
                     78:   viaBaseAddress = viaMemoryMap->getVirtualAddress();
                     79:   viaMemoryMap->release();
                     80:   
                     81:   // Calculate the bus and cpu speeds.
                     82:   getPlatform()->getDefaultBusSpeeds(&numSpeeds, &speedList);
                     83:   PE_Determine_Clock_Speeds(viaBaseAddress, numSpeeds, speedList);
                     84:   
                     85:   // Allocate the interruptController instance.
                     86:   interruptController = new AppleVIAInterruptController;
                     87:   if (interruptController == NULL) return false;
                     88:   
                     89:   // call the interruptController's init method.
                     90:   error = interruptController->initInterruptController(provider,
                     91:                                                       viaBaseAddress);
                     92:   if (error != kIOReturnSuccess) return false;
                     93:   
                     94:   handler = interruptController->getInterruptHandlerAddress();
                     95:   provider->registerInterrupt(0, interruptController, handler, 0);
                     96:   
                     97:   provider->enableInterrupt(0);
                     98:   
                     99:   // Register the interrupt controller so clients can find it.
                    100:   interruptControllerName = OSSymbol::withCStringNoCopy(kInterruptControllerName);
                    101:   getPlatform()->registerInterruptController(interruptControllerName,
                    102:                                             interruptController);
                    103:   
                    104:   nub = createNub();
                    105:   if (nub == 0) return false;
                    106:   
                    107:   nub->attach(this);
                    108:   nub->registerService();
                    109:   
                    110:   return true;
                    111: }
                    112: 
                    113: AppleVIADevice *AppleVIA::createNub(void)
                    114: {
                    115:   int               cnt;
                    116:   bool              err;
                    117:   OSSymbol          *cName;
                    118:   OSSymbol          *name = 0;
                    119:   OSArray           *array = 0, *vecArray = 0, *deviceMemoryArray;
                    120:   OSDictionary      *dict = 0;
                    121:   AppleVIADevice    *nub = 0;
                    122:   
                    123:   do {
                    124:     // create the name symbol for the interrupt controller.
                    125:     cName = OSSymbol::withCStringNoCopy(kInterruptControllerName);
                    126:     if (cName == 0) continue;
                    127:     
                    128:     // create the vector array.
                    129:     vecArray = OSDynamicCast(OSArray, getProperty("vectors"));
                    130:     if ((vecArray == 0) || (vecArray->getCount() != kNumVectors)) continue;
                    131:     
                    132:     // create the controller array.
                    133:     array = OSArray::withCapacity(kNumVectors);
                    134:     if (array == 0) continue;
                    135:     
                    136:     // populate the names array
                    137:     err = false;
                    138:     for (cnt = 0; cnt < kNumVectors; cnt++) {
                    139:       if (!array->setObject(cName)) {
                    140:         err = true;
                    141:         break;
                    142:       }
                    143:     }
                    144:     if (err) continue;
                    145:     
                    146:     // create the deviceMemory array.
                    147:     deviceMemoryArray = getProvider()->getDeviceMemory();
                    148:     if (deviceMemoryArray == 0) continue;
                    149:     
                    150:     // create the name for the viaDevice nub
                    151:     if (viaDeviceType == kVIADeviceTypeCuda)
                    152:       name = OSSymbol::withCStringNoCopy("cuda");
                    153:     else if (viaDeviceType == kVIADeviceTypePMU)
                    154:       name = OSSymbol::withCStringNoCopy("pmu");
                    155:     else name = 0;
                    156:     if (name == 0) continue;
                    157:     
                    158:     // Create the dictionary for the viaDevice nub.
                    159:     dict = OSDictionary::withCapacity(1);
                    160:     if (dict == 0) continue;
                    161:     
                    162:     // add the interrupt numbers and parents to the dictionary.
                    163:     err = !dict->setObject("name", name);
                    164:     err |= !dict->setObject(gIOInterruptSpecifiersKey, vecArray);
                    165:     err |= !dict->setObject(gIOInterruptControllersKey, array);
                    166:     if (err) continue;
                    167:     
                    168:     // Create the viaDevice nub
                    169:     nub = new AppleVIADevice;
                    170:     if (nub == 0) continue;
                    171:     
                    172:     if (!nub->init(dict)) {
                    173:       nub->release();
                    174:       nub = 0;
                    175:       continue;
                    176:     }
                    177:     
                    178:     // set the nub's name.
                    179:     nub->setName(name);
                    180:     
                    181:     // set the nub's deviceMemory.
                    182:     nub->setDeviceMemory(deviceMemoryArray);
                    183:     
                    184:   } while(false);
                    185:   
                    186:   if(name) name->release();
                    187:   if(cName) cName->release();
                    188:   if(array) array->release();
                    189:   if(dict) dict->release();
                    190:   
                    191:   return nub;
                    192: }
                    193: 
                    194: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    195: 
                    196: #undef  super
                    197: #define super IOService
                    198: 
                    199: OSDefineMetaClassAndStructors(AppleVIADevice, IOService);
                    200: 
                    201: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    202: 
                    203: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    204: 
                    205: #undef  super
                    206: #define super IOInterruptController
                    207: 
                    208: OSDefineMetaClassAndStructors(AppleVIAInterruptController, IOInterruptController);
                    209: 
                    210: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    211: 
                    212: IOReturn AppleVIAInterruptController::initInterruptController(IOService *provider, IOLogicalAddress interruptControllerBase)
                    213: {
                    214:   int cnt;
                    215:   
                    216:   parentNub = provider;
                    217:   
                    218:   // Allocate the memory for the vectors
                    219:   vectors = (IOInterruptVector *)IOMalloc(kNumVectors *
                    220:                                          sizeof(IOInterruptVector));
                    221:   if (vectors == NULL) return kIOReturnNoMemory;
                    222:   bzero(vectors, kNumVectors * sizeof(IOInterruptVector));
                    223:   
                    224:   // Allocate locks for the
                    225:   for (cnt = 0; cnt < kNumVectors; cnt++) {
                    226:     vectors[cnt].interruptLock = IOLockAlloc();
                    227:     if (vectors[cnt].interruptLock == NULL) {
                    228:       for (cnt = 0; cnt < kNumVectors; cnt++) {
                    229:        if (vectors[cnt].interruptLock != NULL)
                    230:          IOLockFree(vectors[cnt].interruptLock);
                    231:       }
                    232:       return kIOReturnNoResources;
                    233:     }
                    234:   }
                    235:   
                    236:   // Initialize the registers.
                    237:   IEReg = (volatile unsigned char *)(interruptControllerBase + kIEOffset);
                    238:   IFReg = (volatile unsigned char *)(interruptControllerBase + kIFOffset);
                    239:   PCReg = (volatile unsigned char *)(interruptControllerBase + kPCOffset);
                    240:   
                    241:   // Disable all interrupts.
                    242:   *PCReg = 0x00; eieio();
                    243:   *IEReg = 0x00; eieio();
                    244:   *IFReg = 0x7F; eieio();
                    245:   
                    246:   return kIOReturnSuccess;
                    247: }
                    248: 
                    249: IOInterruptAction AppleVIAInterruptController::getInterruptHandlerAddress(void)
                    250: {
                    251:   return (IOInterruptAction)&AppleVIAInterruptController::handleInterrupt;
                    252: }
                    253: 
                    254: IOReturn AppleVIAInterruptController::handleInterrupt(void */*refCon*/,
                    255:                                                      IOService */*nub*/,
                    256:                                                      int /*source*/)
                    257: {
                    258:   int               done;
                    259:   long              events, vectorNumber;
                    260:   IOInterruptVector *vector;
                    261:   
                    262:   do {
                    263:     done = 1;
                    264:     
                    265:     // Do all the sources for events.
                    266:     events = *IFReg; eieio();
                    267:     events |= pendingEvents;
                    268:     pendingEvents = 0;
                    269:     events &= *IEReg & 0x7F; eieio();
                    270:     
                    271:     if (events) {
                    272:       done = 0;
                    273:       *IFReg = events; eieio();
                    274:     }
                    275:     
                    276:     while (events) {
                    277:       vectorNumber = 31 - cntlzw(events);
                    278:       events ^= (1 << vectorNumber);
                    279:       vector = &vectors[vectorNumber];
                    280:       
                    281:       vector->interruptActive = 1;
                    282:       sync();
                    283:       isync();
                    284:       if (!vector->interruptDisabledSoft) {
                    285:        isync();
                    286:        
                    287:        // Call the handler if it exists.
                    288:        if (vector->interruptRegistered) {
                    289:          vector->handler(vector->target, vector->refCon,
                    290:                          vector->nub, vector->source);
                    291:        }
                    292:       } else {
                    293:        // Hard disable the source.
                    294:        vector->interruptDisabledHard = 1;
                    295:        disableVectorHard(vectorNumber, vector);
                    296:       }
                    297:       
                    298:       vector->interruptActive = 0;
                    299:     }
                    300:     
                    301:   } while (!done);
                    302:   
                    303:   return kIOReturnSuccess;
                    304: }
                    305: 
                    306: void AppleVIAInterruptController::disableVectorHard(long vectorNumber, IOInterruptVector */*vector*/)
                    307: {
                    308:   *IEReg &= ~(1 << vectorNumber);
                    309:   eieio();
                    310: }
                    311: 
                    312: void AppleVIAInterruptController::enableVector(long vectorNumber,
                    313:                                               IOInterruptVector *vector)
                    314: {
                    315:   *IEReg |= (1 << vectorNumber);
                    316:   eieio();
                    317: }
                    318: 
                    319: void AppleVIAInterruptController::causeVector(long vectorNumber,
                    320:                                              IOInterruptVector */*vector*/)
                    321: {
                    322:   pendingEvents |= 1 << vectorNumber;
                    323:   parentNub->causeInterrupt(0);
                    324: }

unix.superglobalmegacorp.com

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