Annotation of XNU/iokit/Drivers/platform/drvAppleHeathrow/Heathrow.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 "Heathrow.h"
                     40: 
                     41: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                     42: 
                     43: #define super AppleMacIO
                     44: 
                     45: OSDefineMetaClassAndStructors(Heathrow, AppleMacIO);
                     46: 
                     47: bool Heathrow::start(IOService *provider)
                     48: {
                     49:   bool              ret;
                     50:   
                     51:   // Call MacIO's start.
                     52:   if (!super::start(provider))
                     53:     return false;
                     54:   
                     55:   // Figure out which heathrow this is.
                     56:   if (IODTMatchNubWithKeys(provider, "heathrow"))
                     57:     heathrowNum = kPrimaryHeathrow;
                     58:   else if (IODTMatchNubWithKeys(provider, "gatwick"))
                     59:     heathrowNum = kSecondaryHeathrow;
                     60:   else return false; // This should not happen.
                     61:   
                     62:   if (heathrowNum == kPrimaryHeathrow) {
                     63:     if (getPlatform()->getFamily() != 3)
                     64:       getPlatform()->setCPUInterruptProperties(provider);
                     65:   }
                     66:   
                     67:   // get the base address of the this heathrow.
                     68:   heathrowBaseAddress = fMemory->getVirtualAddress();
                     69:   
                     70:   // Make nubs for the children.
                     71:   publishBelow( provider );
                     72: 
                     73:   ret = installInterrupts(provider);
                     74: 
                     75:   return ret;
                     76: }
                     77: 
                     78: bool Heathrow::installInterrupts(IOService *provider)
                     79: {
                     80:   IORegistryEntry    *regEntry;
                     81:   OSSymbol           *interruptControllerName;
                     82:   IOInterruptAction  handler;
                     83:   AppleNMI           *appleNMI;
                     84:   long               nmiSource;
                     85:   OSData             *nmiData;
                     86:   IOReturn           error;
                     87: 
                     88:   // Everything below here is for interrupts, return true if
                     89:   // interrupts are not needed.
                     90:   if (getPlatform()->getFamily() == 3) return true;
                     91:   
                     92:   // get the name of the interrupt controller
                     93:   if( (regEntry = provider->childFromPath("interrupt-controller",
                     94:        gIODTPlane))) {
                     95:     interruptControllerName = (OSSymbol *)IODTInterruptControllerName(regEntry);
                     96:     regEntry->release();
                     97:   } else
                     98:     interruptControllerName = getInterruptControllerName();
                     99:   
                    100:   // Allocate the interruptController instance.
                    101:   interruptController = new HeathrowInterruptController;
                    102:   if (interruptController == NULL) return false;
                    103:   
                    104:   // call the interruptController's init method.
                    105:   error = interruptController->initInterruptController(provider, heathrowBaseAddress);
                    106:   if (error != kIOReturnSuccess) return false;
                    107:   
                    108:   handler = interruptController->getInterruptHandlerAddress();
                    109:   provider->registerInterrupt(0, interruptController, handler, 0);
                    110:   
                    111:   provider->enableInterrupt(0);
                    112:   
                    113:   // Register the interrupt controller so clients can find it.
                    114:   getPlatform()->registerInterruptController(interruptControllerName,
                    115:                                             interruptController);
                    116:   
                    117:   if (heathrowNum != kPrimaryHeathrow) return true;
                    118:   
                    119:   // Create the NMI Driver.
                    120:   nmiSource = 20;
                    121:   nmiData = OSData::withBytes(&nmiSource, sizeof(long));
                    122:   appleNMI = new AppleNMI;
                    123:   if ((nmiData != 0) && (appleNMI != 0)) {
                    124:     appleNMI->initNMI(interruptController, nmiData);
                    125:   } 
                    126:   
                    127:   return true;
                    128: }
                    129: 
                    130: OSSymbol *Heathrow::getInterruptControllerName(void)
                    131: {
                    132:   OSSymbol *interruptControllerName;
                    133:   
                    134:   switch (heathrowNum) {
                    135:   case kPrimaryHeathrow :
                    136:     interruptControllerName = (OSSymbol *)gIODTDefaultInterruptController;
                    137:     break;
                    138:     
                    139:   case kSecondaryHeathrow :
                    140:     interruptControllerName = (OSSymbol *)OSSymbol::withCStringNoCopy("SecondaryInterruptController");
                    141:     break;
                    142:     
                    143:   default:
                    144:     interruptControllerName = (OSSymbol *)OSSymbol::withCStringNoCopy("UnknownInterruptController");
                    145:     break;
                    146:   }
                    147:   
                    148:   return interruptControllerName;
                    149: }
                    150: 
                    151: void Heathrow::processNub(IOService *nub)
                    152: {
                    153:   int           cnt, numSources;
                    154:   OSArray       *controllerNames, *controllerSources;
                    155:   OSSymbol      *interruptControllerName;
                    156:   char          *nubName;
                    157:   unsigned long heathrowIDs, heathrowFCR;
                    158:   
                    159:   nubName = (char *)nub->getName();
                    160:   
                    161:   // Turn on the media bay if this a PowerBook 101.
                    162:   if (IODTMatchNubWithKeys(getPlatform()->getProvider(), "'PowerBook1,1'")) {
                    163:     if (!strcmp(nubName, "media-bay")) {
                    164:       heathrowIDs = lwbrx(heathrowBaseAddress + 0x34);
                    165:       if ((heathrowIDs & 0x0000FF00) == 0x00003000) {
                    166:        heathrowFCR = lwbrx(heathrowBaseAddress + 0x38);
                    167:        heathrowFCR |= 0x00800000;
                    168:        stwbrx(heathrowFCR, heathrowBaseAddress + 0x38);
                    169:        IOSleep(500);
                    170:       }
                    171:     }
                    172:   }
                    173:   
                    174:   // change the interrupt controller name for this nub
                    175:   // if it is on the secondary heathrow.
                    176:   if (heathrowNum == kPrimaryHeathrow) return;
                    177:   
                    178:   interruptControllerName = getInterruptControllerName();
                    179:   
                    180:   if (!strcmp(nubName, "ch-a")) {
                    181:     controllerSources = OSDynamicCast(OSArray, getProperty("vectors-escc-ch-a"));
                    182:   } else if (!strcmp(nubName, "floppy")) {
                    183:       controllerSources = OSDynamicCast(OSArray, getProperty("vectors-floppy"));
                    184:   } else if (!strcmp(nubName, "ata4")) {
                    185:       controllerSources = OSDynamicCast(OSArray, getProperty("vectors-ata4"));
                    186:   } else return;
                    187:   
                    188:   numSources = controllerSources->getCount();
                    189:   
                    190:   controllerNames = OSArray::withCapacity(numSources);
                    191:   for (cnt = 0; cnt < numSources; cnt++) {
                    192:     controllerNames->setObject(interruptControllerName);
                    193:   }
                    194: 
                    195:   nub->setProperty(gIOInterruptControllersKey, controllerNames);
                    196:   nub->setProperty(gIOInterruptSpecifiersKey, controllerSources);
                    197: }
                    198: 
                    199: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    200: 
                    201: #undef  super
                    202: #define super IOInterruptController
                    203: 
                    204: OSDefineMetaClassAndStructors(HeathrowInterruptController, IOInterruptController);
                    205: 
                    206: IOReturn HeathrowInterruptController::initInterruptController(IOService *provider, IOLogicalAddress interruptControllerBase)
                    207: {
                    208:   int cnt;
                    209:   
                    210:   parentNub = provider;
                    211:   
                    212:   // Allocate the task lock.
                    213:   taskLock = IOLockAlloc();
                    214:   if (taskLock == 0) return kIOReturnNoResources;
                    215:   
                    216:   // Allocate the memory for the vectors
                    217:   vectors = (IOInterruptVector *)IOMalloc(kNumVectors * sizeof(IOInterruptVector));
                    218:   if (vectors == NULL) {
                    219:     IOLockFree(taskLock);
                    220:     return kIOReturnNoMemory;
                    221:   }
                    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:       IOLockFree(taskLock);
                    229:       for (cnt = 0; cnt < kNumVectors; cnt++) {
                    230:        if (vectors[cnt].interruptLock != NULL)
                    231:          IOLockFree(vectors[cnt].interruptLock);
                    232:       }
                    233:       return kIOReturnNoResources;
                    234:     }
                    235:   }
                    236:   
                    237:   // Setup the registers accessors
                    238:   events1Reg = (unsigned long)(interruptControllerBase + kEvents1Offset);
                    239:   events2Reg = (unsigned long)(interruptControllerBase + kEvents2Offset);
                    240:   mask1Reg   = (unsigned long)(interruptControllerBase + kMask1Offset);
                    241:   mask2Reg   = (unsigned long)(interruptControllerBase + kMask2Offset);
                    242:   clear1Reg  = (unsigned long)(interruptControllerBase + kClear1Offset);
                    243:   clear2Reg  = (unsigned long)(interruptControllerBase + kClear2Offset);
                    244:   levels1Reg = (unsigned long)(interruptControllerBase + kLevels1Offset);
                    245:   levels2Reg = (unsigned long)(interruptControllerBase + kLevels2Offset);
                    246:   
                    247:   // Initialize the registers.
                    248:   
                    249:   // Disable all interrupts.
                    250:   stwbrx(0x00000000, mask1Reg);
                    251:   stwbrx(0x00000000, mask2Reg);
                    252:   eieio();
                    253:   
                    254:   // Clear all pending interrupts.
                    255:   stwbrx(0xFFFFFFFF, clear1Reg);
                    256:   stwbrx(0xFFFFFFFF, clear2Reg);
                    257:   eieio();
                    258:   
                    259:   // Disable all interrupts. (again?)
                    260:   stwbrx(0x00000000, mask1Reg);
                    261:   stwbrx(0x00000000, mask2Reg);
                    262:   eieio();
                    263:   
                    264:   return kIOReturnSuccess;
                    265: }
                    266: 
                    267: IOInterruptAction HeathrowInterruptController::getInterruptHandlerAddress(void)
                    268: {
                    269:   return (IOInterruptAction)&HeathrowInterruptController::handleInterrupt;
                    270: }
                    271: 
                    272: IOReturn HeathrowInterruptController::handleInterrupt(void * /*refCon*/,
                    273:                                                      IOService * /*nub*/,
                    274:                                                      int /*source*/)
                    275: {
                    276:   int               done;
                    277:   long              events, vectorNumber;
                    278:   IOInterruptVector *vector;
                    279:   unsigned long     maskTmp;
                    280:   
                    281:   do {
                    282:     done = 1;
                    283:     
                    284:     // Do all the sources for events1, plus any pending interrupts.
                    285:     // Also add in the "level" sensitive sources
                    286:     maskTmp = lwbrx(mask1Reg);
                    287:     events = lwbrx(events1Reg) & ~kTypeLevelMask;
                    288:     events |= lwbrx(levels1Reg) & maskTmp & kTypeLevelMask;
                    289:     events |= pendingEvents1 & maskTmp;
                    290:     pendingEvents1 = 0;
                    291:     eieio();
                    292:     
                    293:     // Since we have to clear the level'd one clear the current edge's too.
                    294:     stwbrx(kTypeLevelMask | events, clear1Reg);
                    295:     eieio();
                    296:     
                    297:     if (events) done = 0;
                    298:     
                    299:     while (events) {
                    300:       vectorNumber = 31 - cntlzw(events);
                    301:       events ^= (1 << vectorNumber);
                    302:       vector = &vectors[vectorNumber];
                    303:       
                    304:       vector->interruptActive = 1;
                    305:       sync();
                    306:       isync();
                    307:       if (!vector->interruptDisabledSoft) {
                    308:        isync();
                    309:        
                    310:        // Call the handler if it exists.
                    311:        if (vector->interruptRegistered) {
                    312:          vector->handler(vector->target, vector->refCon,
                    313:                          vector->nub, vector->source);
                    314:        }
                    315:       } else {
                    316:        // Hard disable the source.
                    317:        vector->interruptDisabledHard = 1;
                    318:        disableVectorHard(vectorNumber, vector);
                    319:       }
                    320:       
                    321:       vector->interruptActive = 0;
                    322:     }
                    323:     
                    324:     // Do all the sources for events2, plus any pending interrupts.
                    325:     maskTmp = lwbrx(mask2Reg);
                    326:     events = lwbrx(events2Reg);
                    327:     events |= pendingEvents1 & maskTmp;
                    328:     pendingEvents2 = 0;
                    329:     eieio();
                    330:     
                    331:     if (events) {
                    332:       done = 0;
                    333:       stwbrx(events, clear2Reg);
                    334:       eieio();
                    335:     }
                    336:     
                    337:     while (events) {
                    338:       vectorNumber = 31 - cntlzw(events);
                    339:       events ^= (1 << vectorNumber);
                    340:       vector = &vectors[vectorNumber + kVectorsPerReg];
                    341:       
                    342:       vector->interruptActive = 1;
                    343:       sync();
                    344:       isync();
                    345:       if (!vector->interruptDisabledSoft) {
                    346:        isync();
                    347:        
                    348:        // Call the handler if it exists.
                    349:        if (vector->interruptRegistered) {
                    350:          vector->handler(vector->target, vector->refCon,
                    351:                          vector->nub, vector->source);
                    352:        }
                    353:       } else {
                    354:        // Hard disable the source.
                    355:        vector->interruptDisabledHard = 1;
                    356:        disableVectorHard(vectorNumber + kVectorsPerReg, vector);
                    357:       }
                    358:       
                    359:       vector->interruptActive = 0;
                    360:     }
                    361:   } while (!done);
                    362:   
                    363:   return kIOReturnSuccess;
                    364: }
                    365: 
                    366: bool HeathrowInterruptController::vectorCanBeShared(long /*vectorNumber*/, IOInterruptVector */*vector*/)
                    367: {
                    368:   return true;
                    369: }
                    370: 
                    371: int HeathrowInterruptController::getVectorType(long vectorNumber, IOInterruptVector */*vector*/)
                    372: {
                    373:   int interruptType;
                    374:   
                    375:   if (kTypeLevelMask & (1 << vectorNumber)) {
                    376:     interruptType = kIOInterruptTypeLevel;
                    377:   } else {
                    378:     interruptType = kIOInterruptTypeEdge;
                    379:   }
                    380:   
                    381:   return interruptType;
                    382: }
                    383: 
                    384: void HeathrowInterruptController::disableVectorHard(long vectorNumber, IOInterruptVector */*vector*/)
                    385: {
                    386:   unsigned long     maskTmp;
                    387:   
                    388:   // Turn the source off at hardware.
                    389:   if (vectorNumber < kVectorsPerReg) {
                    390:     maskTmp = lwbrx(mask1Reg);
                    391:     maskTmp &= ~(1 << vectorNumber);
                    392:     stwbrx(maskTmp, mask1Reg);
                    393:     eieio();
                    394:   } else {
                    395:     vectorNumber -= kVectorsPerReg;
                    396:     maskTmp = lwbrx(mask2Reg);
                    397:     maskTmp &= ~(1 << vectorNumber);
                    398:     stwbrx(maskTmp, mask2Reg);
                    399:     eieio();
                    400:   }
                    401: }
                    402: 
                    403: void HeathrowInterruptController::enableVector(long vectorNumber,
                    404:                                               IOInterruptVector *vector)
                    405: {
                    406:   unsigned long     maskTmp;
                    407:   
                    408:   if (vectorNumber < kVectorsPerReg) {
                    409:     maskTmp = lwbrx(mask1Reg);
                    410:     maskTmp |= (1 << vectorNumber);
                    411:     stwbrx(maskTmp, mask1Reg);
                    412:     eieio();
                    413:     if (lwbrx(levels1Reg) & (1 << vectorNumber)) {
                    414:       // lost the interrupt
                    415:       causeVector(vectorNumber, vector);
                    416:     }
                    417:   } else {
                    418:     vectorNumber -= kVectorsPerReg;
                    419:     maskTmp = lwbrx(mask2Reg);
                    420:     maskTmp |= (1 << vectorNumber);
                    421:     stwbrx(maskTmp, mask2Reg);
                    422:     eieio();
                    423:     if (lwbrx(levels1Reg) & (1 << vectorNumber)) {
                    424:       // lost the interrupt
                    425:       causeVector(vectorNumber + kVectorsPerReg, vector);
                    426:     }
                    427:   }
                    428: }
                    429: 
                    430: void HeathrowInterruptController::causeVector(long vectorNumber,
                    431:                                              IOInterruptVector */*vector*/)
                    432: {
                    433:   if (vectorNumber < kVectorsPerReg) {
                    434:     pendingEvents1 |= 1 << vectorNumber;
                    435:   } else {
                    436:     vectorNumber -= kVectorsPerReg;
                    437:     pendingEvents2 |= 1 << vectorNumber;
                    438:   }
                    439: 
                    440:   parentNub->causeInterrupt(0);
                    441: }

unix.superglobalmegacorp.com

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