Annotation of XNU/iokit/Drivers/platform/drvAppleHeathrow/Heathrow.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 "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.