Annotation of XNU/iokit/Kernel/IOInterruptController.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: #ifdef __ppc__
                     31: #include <ppc/proc_reg.h> 
                     32: #endif
                     33: 
                     34: #include <IOKit/IOLib.h>
                     35: #include <IOKit/IOService.h>
                     36: #include <IOKit/IOPlatformExpert.h>
                     37: #include <IOKit/IOInterrupts.h>
                     38: #include <IOKit/IOInterruptController.h>
                     39: 
                     40: 
                     41: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                     42: 
                     43: #define super IOService
                     44: 
                     45: OSDefineMetaClass(IOInterruptController, IOService);
                     46: OSDefineAbstractStructors(IOInterruptController, IOService);
                     47: 
                     48: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                     49: 
                     50: IOReturn IOInterruptController::registerInterrupt(IOService *nub, int source,
                     51:                                                  void *target,
                     52:                                                  IOInterruptHandler handler,
                     53:                                                  void *refCon)
                     54: {
                     55:   IOInterruptSource *interruptSources;
                     56:   long              vectorNumber;
                     57:   IOInterruptVector *vector;
                     58:   long              wasDisabledSoft;
                     59:   IOReturn          error;
                     60:   OSData            *vectorData;
                     61:   IOService         *originalNub;
                     62:   int               originalSource;
                     63:   
                     64:   interruptSources = nub->_interruptSources;
                     65:   vectorData = interruptSources[source].vectorData;
                     66:   vectorNumber = *(long *)vectorData->getBytesNoCopy();
                     67:   vector = &vectors[vectorNumber];
                     68:   
                     69:   // Get the lock for this vector.
                     70:   IOTakeLock(vector->interruptLock);
                     71:   
                     72:   // If this vector is already in use, and can be shared,
                     73:   // register as a shared interrupt.
                     74:   if (vector->interruptRegistered) {
                     75:     if (!vectorCanBeShared(vectorNumber, vector)) {
                     76:       IOUnlock(vector->interruptLock);
                     77:       return kIOReturnNoResources;
                     78:     }
                     79:     
                     80:     // If this vector is not already shared, break it out.
                     81:     if (vector->sharedController == 0) {
                     82:       // Make the IOShareInterruptController instance
                     83:       vector->sharedController = new IOSharedInterruptController;
                     84:       if (vector->sharedController == 0) {
                     85:         IOUnlock(vector->interruptLock);
                     86:         return kIOReturnNoMemory;
                     87:       }
                     88:       
                     89:       // Save the nub and source for the original consumer.
                     90:       originalNub = vector->nub;
                     91:       originalSource = vector->source;
                     92:       
                     93:       // Save the dis/enable state for the original consumer's interrupt.
                     94:       // Then disable the source
                     95:       wasDisabledSoft = vector->interruptDisabledSoft;
                     96:       disableInterrupt(originalNub, originalSource);
                     97:       
                     98:       // Initialize the new shared interrupt controller.
                     99:       error = vector->sharedController->initInterruptController(this,
                    100:                                                                 vectorData);
                    101:       // If the IOSharedInterruptController could not be initalized,
                    102:       // put the original consumor's interrupt back to normal and
                    103:       // get rid of whats left of the shared controller.
                    104:       if (error != kIOReturnSuccess) {
                    105:         enableInterrupt(originalNub, originalSource);
                    106:         vector->sharedController->release();
                    107:         vector->sharedController = 0;
                    108:         IOUnlock(vector->interruptLock);
                    109:         return error;
                    110:       }
                    111:       
                    112:       // Try to register the original consumer on the shared controller.
                    113:       error = vector->sharedController->registerInterrupt(originalNub,
                    114:                                                           originalSource,
                    115:                                                           vector->target,
                    116:                                                           vector->handler,
                    117:                                                           vector->refCon);
                    118:       // If the original consumer could not be moved to the shared controller,
                    119:       // put the original consumor's interrupt back to normal and
                    120:       // get rid of whats left of the shared controller.
                    121:       if (error != kIOReturnSuccess) {
                    122:         enableInterrupt(originalNub, originalSource);
                    123:         vector->sharedController->release();
                    124:         vector->sharedController = 0;
                    125:         IOUnlock(vector->interruptLock);
                    126:         return error;
                    127:       }
                    128:       
                    129:       // Fill in vector with the shared controller's info.
                    130:       vector->handler = (IOInterruptHandler)vector->sharedController->getInterruptHandlerAddress();
                    131:       vector->nub     = vector->sharedController;
                    132:       vector->source  = 0;
                    133:       vector->target  = vector->sharedController;
                    134:       vector->refCon  = 0;
                    135:       
                    136:       // Enable the original consumer's interrupt if needed.
                    137:       if (!wasDisabledSoft) originalNub->enableInterrupt(originalSource);
                    138:     }
                    139:     
                    140:     error = vector->sharedController->registerInterrupt(nub, source, target,
                    141:                                                         handler, refCon);
                    142:     IOUnlock(vector->interruptLock);
                    143:     return error;
                    144:   }
                    145:   
                    146:   // Fill in vector with the client's info.
                    147:   vector->handler = handler;
                    148:   vector->nub     = nub;
                    149:   vector->source  = source;
                    150:   vector->target  = target;
                    151:   vector->refCon  = refCon;
                    152:   
                    153:   // Do any specific initalization for this vector.
                    154:   initVector(vectorNumber, vector);
                    155:   
                    156:   // Get the vector ready.  It starts hard disabled.
                    157:   vector->interruptDisabledHard = 1;
                    158:   vector->interruptDisabledSoft = 1;
                    159:   vector->interruptRegistered   = 1;
                    160:   
                    161:   IOUnlock(vector->interruptLock);
                    162:   return kIOReturnSuccess;
                    163: }
                    164: 
                    165: IOReturn IOInterruptController::unregisterInterrupt(IOService *nub, int source)
                    166: {
                    167:   IOInterruptSource *interruptSources;
                    168:   long              vectorNumber;
                    169:   IOInterruptVector *vector;
                    170:   OSData            *vectorData;
                    171:   
                    172:   interruptSources = nub->_interruptSources;
                    173:   vectorData = interruptSources[source].vectorData;
                    174:   vectorNumber = *(long *)vectorData->getBytesNoCopy();
                    175:   vector = &vectors[vectorNumber];
                    176:   
                    177:   // Get the lock for this vector.
                    178:   IOTakeLock(vector->interruptLock);
                    179:   
                    180:   // Return success if it is not already registered
                    181:   if (vector->interruptRegistered) {
                    182:     IOUnlock(vector->interruptLock);
                    183:     return kIOReturnSuccess;
                    184:   }
                    185:   
                    186:   // Soft disable the source.
                    187:   disableInterrupt(nub, source);
                    188:   
                    189:   // Turn the source off at hardware. 
                    190:   disableVectorHard(vectorNumber, vector);
                    191:   
                    192:   // Clear all the storage for the vector except for interruptLock.
                    193:   vector->interruptActive = 0;
                    194:   vector->interruptDisabledSoft = 0;
                    195:   vector->interruptDisabledHard = 0;
                    196:   vector->interruptRegistered = 0;
                    197:   vector->nub = 0;
                    198:   vector->source = 0;
                    199:   vector->handler = 0;
                    200:   vector->target = 0;
                    201:   vector->refCon = 0;
                    202:   
                    203:   IOUnlock(vector->interruptLock);
                    204:   return kIOReturnSuccess;
                    205: }
                    206: 
                    207: IOReturn IOInterruptController::getInterruptType(IOService *nub, int source,
                    208:                                                 int *interruptType)
                    209: {
                    210:   IOInterruptSource *interruptSources;
                    211:   long              vectorNumber;
                    212:   IOInterruptVector *vector;
                    213:   OSData            *vectorData;
                    214:   
                    215:   if (interruptType == 0) return kIOReturnBadArgument;
                    216:   
                    217:   interruptSources = nub->_interruptSources;
                    218:   vectorData = interruptSources[source].vectorData;
                    219:   vectorNumber = *(long *)vectorData->getBytesNoCopy();
                    220:   vector = &vectors[vectorNumber];
                    221:   
                    222:   *interruptType = getVectorType(vectorNumber, vector);
                    223:   
                    224:   return kIOReturnSuccess;
                    225: }
                    226: 
                    227: IOReturn IOInterruptController::enableInterrupt(IOService *nub, int source)
                    228: {
                    229:   IOInterruptSource *interruptSources;
                    230:   long              vectorNumber;
                    231:   IOInterruptVector *vector;
                    232:   OSData            *vectorData;
                    233:   
                    234:   interruptSources = nub->_interruptSources;
                    235:   vectorData = interruptSources[source].vectorData;
                    236:   vectorNumber = *(long *)vectorData->getBytesNoCopy();
                    237:   vector = &vectors[vectorNumber];
                    238:   
                    239:   if (vector->interruptDisabledSoft) {
                    240:     vector->interruptDisabledSoft = 0;
                    241:     
                    242:     if (vector->interruptDisabledHard) {
                    243:       vector->interruptDisabledHard = 0;
                    244:       
                    245:       enableVector(vectorNumber, vector);
                    246:     }
                    247:   }
                    248:   
                    249:   return kIOReturnSuccess;
                    250: }
                    251: 
                    252: IOReturn IOInterruptController::disableInterrupt(IOService *nub, int source)
                    253: {
                    254:   IOInterruptSource *interruptSources;
                    255:   long              vectorNumber;
                    256:   IOInterruptVector *vector;
                    257:   OSData            *vectorData;
                    258:   
                    259:   interruptSources = nub->_interruptSources;
                    260:   vectorData = interruptSources[source].vectorData;
                    261:   vectorNumber = *(long *)vectorData->getBytesNoCopy();
                    262:   vector = &vectors[vectorNumber];
                    263:   
                    264:   vector->interruptDisabledSoft = 1;
                    265: #ifdef __ppc__
                    266:   sync();
                    267:   isync();
                    268: #endif
                    269:   
                    270:   if (!getPlatform()->atInterruptLevel()) {
                    271:     while (vector->interruptActive);
                    272: #ifdef __ppc__
                    273:     isync();
                    274: #endif
                    275:   }
                    276:   
                    277:   return kIOReturnSuccess;
                    278: }
                    279: 
                    280: IOReturn IOInterruptController::causeInterrupt(IOService *nub, int source)
                    281: {
                    282:   IOInterruptSource *interruptSources;
                    283:   long              vectorNumber;
                    284:   IOInterruptVector *vector;
                    285:   OSData            *vectorData;
                    286: 
                    287:   interruptSources = nub->_interruptSources;
                    288:   vectorData = interruptSources[source].vectorData;
                    289:   vectorNumber = *(long *)vectorData->getBytesNoCopy();
                    290:   vector = &vectors[vectorNumber];
                    291:   
                    292:   causeVector(vectorNumber, vector);
                    293:   
                    294:   return kIOReturnSuccess;
                    295: }
                    296: 
                    297: IOInterruptAction IOInterruptController::getInterruptHandlerAddress(void)
                    298: {
                    299:   return 0;
                    300: }
                    301: 
                    302: IOReturn IOInterruptController::handleInterrupt(void *refCon, IOService *nub,
                    303:                                                int source)
                    304: {
                    305:   return kIOReturnInvalid;
                    306: }
                    307: 
                    308: 
                    309: // Methods to be overridden for simplifed interrupt controller subclasses.
                    310: 
                    311: bool IOInterruptController::vectorCanBeShared(long /*vectorNumber*/,
                    312:                                              IOInterruptVector */*vector*/)
                    313: {
                    314:   return false;
                    315: }
                    316: 
                    317: void IOInterruptController::initVector(long /*vectorNumber*/,
                    318:                                       IOInterruptVector */*vector*/)
                    319: {
                    320: }
                    321: 
                    322: int IOInterruptController::getVectorType(long /*vectorNumber*/,
                    323:                                          IOInterruptVector */*vector*/)
                    324: {
                    325:   return kIOInterruptTypeEdge;
                    326: }
                    327: 
                    328: void IOInterruptController::disableVectorHard(long /*vectorNumber*/,
                    329:                                              IOInterruptVector */*vector*/)
                    330: {
                    331: }
                    332: 
                    333: void IOInterruptController::enableVector(long /*vectorNumber*/,
                    334:                                         IOInterruptVector */*vector*/)
                    335: {
                    336: }
                    337: 
                    338: void IOInterruptController::causeVector(long /*vectorNumber*/,
                    339:                                        IOInterruptVector */*vector*/)
                    340: {
                    341: }
                    342: 
                    343: 
                    344: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    345: 
                    346: #undef  super
                    347: #define super IOInterruptController
                    348: 
                    349: OSDefineMetaClassAndStructors(IOSharedInterruptController, IOInterruptController);
                    350: 
                    351: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    352: 
                    353: IOReturn IOSharedInterruptController::initInterruptController(IOInterruptController *parentController, OSData *parentSource)
                    354: {
                    355:   int      cnt, interruptType;
                    356:   IOReturn error;
                    357:   
                    358:   if (!super::init())
                    359:     return kIOReturnNoResources;
                    360:   
                    361:   // Set provider to this so enable/disable nub stuff works.
                    362:   provider = this;
                    363:   
                    364:   // Allocate the IOInterruptSource so this can act like a nub.
                    365:   _interruptSources = (IOInterruptSource *)IOMalloc(sizeof(IOInterruptSource));
                    366:   if (_interruptSources == 0) return kIOReturnNoMemory;
                    367:   _numInterruptSources = 1;
                    368:   
                    369:   // Set up the IOInterruptSource to point at this.
                    370:   _interruptSources[0].interruptController = parentController;
                    371:   _interruptSources[0].vectorData = parentSource;
                    372:   
                    373:   sourceIsLevel = false;
                    374:   error = provider->getInterruptType(0, &interruptType);
                    375:   if (error == kIOReturnSuccess) {
                    376:     if (interruptType & kIOInterruptTypeLevel)
                    377:       sourceIsLevel = true;
                    378:   }
                    379:   
                    380:   // Allocate the memory for the vectors
                    381:   numVectors = 8; // For now a constant number.
                    382:   vectors = (IOInterruptVector *)IOMalloc(numVectors * sizeof(IOInterruptVector));
                    383:   if (vectors == NULL) {
                    384:     IOFree(_interruptSources, sizeof(IOInterruptSource));
                    385:     return kIOReturnNoMemory;
                    386:   }
                    387:   bzero(vectors, numVectors * sizeof(IOInterruptVector));
                    388:   
                    389:   // Allocate locks for the
                    390:   for (cnt = 0; cnt < numVectors; cnt++) {
                    391:     vectors[cnt].interruptLock = IOLockAlloc();
                    392:     if (vectors[cnt].interruptLock == NULL) {
                    393:       for (cnt = 0; cnt < numVectors; cnt++) {
                    394:        if (vectors[cnt].interruptLock != NULL)
                    395:          IOLockFree(vectors[cnt].interruptLock);
                    396:       }
                    397:       return kIOReturnNoResources;
                    398:     }
                    399:   }
                    400:   
                    401:   vectorsRegistered = 0;
                    402:   vectorsEnabled = 0;
                    403:   controllerDisabled = 1;
                    404:   
                    405:   return kIOReturnSuccess;
                    406: }
                    407: 
                    408: IOReturn IOSharedInterruptController::registerInterrupt(IOService *nub,
                    409:                                                        int source,
                    410:                                                        void *target,
                    411:                                                        IOInterruptHandler handler,
                    412:                                                        void *refCon)
                    413: {
                    414:   IOInterruptSource *interruptSources;
                    415:   long              vectorNumber;
                    416:   IOInterruptVector *vector = 0;
                    417:   OSData            *vectorData;
                    418:   
                    419:   interruptSources = nub->_interruptSources;
                    420:   
                    421:   // Find a free vector.
                    422:   vectorNumber = numVectors;
                    423:   while (vectorsRegistered != numVectors) {
                    424:     for (vectorNumber = 0; vectorNumber < numVectors; vectorNumber++) {
                    425:       vector = &vectors[vectorNumber];
                    426:       
                    427:       // Get the lock for this vector.
                    428:       IOTakeLock(vector->interruptLock);
                    429:       
                    430:       // Is it unregistered?
                    431:       if (!vector->interruptRegistered) break;
                    432:       
                    433:       // Move along to the next one.
                    434:       IOUnlock(vector->interruptLock);
                    435:     }
                    436:     
                    437:     if (vectorNumber != numVectors) break;
                    438:   }
                    439:   
                    440:   // Could not find a free one, so give up.
                    441:   if (vectorNumber == numVectors) {
                    442:     return kIOReturnNoResources;
                    443:   }
                    444:   
                    445:   // Create the vectorData for the IOInterruptSource.
                    446:   vectorData = OSData::withBytes(&vectorNumber, sizeof(vectorNumber));
                    447:   if (vectorData == 0) {
                    448:     return kIOReturnNoMemory;
                    449:   }
                    450:   
                    451:   // Fill in the IOInterruptSource with the controller's info.
                    452:   interruptSources[source].interruptController = this;
                    453:   interruptSources[source].vectorData = vectorData;
                    454:   
                    455:   // Fill in vector with the client's info.
                    456:   vector->handler = handler;
                    457:   vector->nub     = nub;
                    458:   vector->source  = source;
                    459:   vector->target  = target;
                    460:   vector->refCon  = refCon;
                    461:   
                    462:   // Get the vector ready.  It start soft disabled.
                    463:   vector->interruptDisabledSoft = 1;
                    464:   vector->interruptRegistered   = 1;
                    465:   
                    466:   vectorsRegistered++;
                    467:   
                    468:   IOUnlock(vector->interruptLock);
                    469:   return kIOReturnSuccess;
                    470: }
                    471: 
                    472: IOReturn IOSharedInterruptController::unregisterInterrupt(IOService *nub,
                    473:                                                          int source)
                    474: {
                    475:   IOInterruptSource *interruptSources;
                    476:   long              vectorNumber;
                    477:   IOInterruptVector *vector;
                    478:   OSData            *vectorData;
                    479:   
                    480:   interruptSources = nub->_interruptSources;
                    481:   vectorData = interruptSources[source].vectorData;
                    482:   vectorNumber = *(long *)vectorData->getBytesNoCopy();
                    483:   vector = &vectors[vectorNumber];
                    484:   
                    485:   // Get the lock for this vector.
                    486:   IOTakeLock(vector->interruptLock);
                    487:   
                    488:   // Return success if it is not already registered
                    489:   if (vector->interruptRegistered) {
                    490:     IOUnlock(vector->interruptLock);
                    491:     return kIOReturnSuccess;
                    492:   }
                    493:   
                    494:   // Soft disable the source.
                    495:   disableInterrupt(nub, source);
                    496:   
                    497:   // Clear all the storage for the vector except for interruptLock.
                    498:   vector->interruptActive = 0;
                    499:   vector->interruptDisabledSoft = 0;
                    500:   vector->interruptDisabledHard = 0;
                    501:   vector->interruptRegistered = 0;
                    502:   vector->nub = 0;
                    503:   vector->source = 0;
                    504:   vector->handler = 0;
                    505:   vector->target = 0;
                    506:   vector->refCon = 0;
                    507:   
                    508:   vectorsRegistered--;
                    509:   
                    510:   IOUnlock(vector->interruptLock);
                    511:   return kIOReturnSuccess;
                    512: }
                    513: 
                    514: IOReturn IOSharedInterruptController::getInterruptType(IOService */*nub*/,
                    515:                                                       int /*source*/,
                    516:                                                       int *interruptType)
                    517: {
                    518:   return provider->getInterruptType(0, interruptType);
                    519: }
                    520: 
                    521: IOReturn IOSharedInterruptController::enableInterrupt(IOService *nub,
                    522:                                                      int source)
                    523: {
                    524:   IOInterruptSource *interruptSources;
                    525:   long              vectorNumber;
                    526:   IOInterruptVector *vector;
                    527:   OSData            *vectorData;
                    528:   
                    529:   interruptSources = nub->_interruptSources;
                    530:   vectorData = interruptSources[source].vectorData;
                    531:   vectorNumber = *(long *)vectorData->getBytesNoCopy();
                    532:   vector = &vectors[vectorNumber];
                    533:   
                    534:   if (vector->interruptDisabledSoft) {
                    535:     vector->interruptDisabledSoft = 0;
                    536:     
                    537:     vectorsEnabled++;
                    538:     
                    539:     if (controllerDisabled && (vectorsEnabled == vectorsRegistered)) {
                    540:       controllerDisabled = 0;
                    541:       provider->enableInterrupt(0);
                    542:     }
                    543:   }
                    544:   
                    545:   return kIOReturnSuccess;
                    546: }
                    547: 
                    548: IOReturn IOSharedInterruptController::disableInterrupt(IOService *nub,
                    549:                                                       int source)
                    550: {
                    551:   IOInterruptSource *interruptSources;
                    552:   long              vectorNumber;
                    553:   IOInterruptVector *vector;
                    554:   OSData            *vectorData;
                    555:   
                    556:   interruptSources = nub->_interruptSources;
                    557:   vectorData = interruptSources[source].vectorData;
                    558:   vectorNumber = *(long *)vectorData->getBytesNoCopy();
                    559:   vector = &vectors[vectorNumber];
                    560:   
                    561:   if (!vector->interruptDisabledSoft) {
                    562:     vector->interruptDisabledSoft = 1;
                    563: #ifdef __ppc__
                    564:     sync();
                    565:     isync();
                    566: #endif
                    567:     
                    568:     vectorsEnabled--;
                    569:   }
                    570:   
                    571:   if (!getPlatform()->atInterruptLevel()) {
                    572:     while (vector->interruptActive);
                    573: #ifdef __ppc__
                    574:     isync();
                    575: #endif
                    576:   }
                    577:   
                    578:   return kIOReturnSuccess;
                    579: }
                    580: 
                    581: IOInterruptAction IOSharedInterruptController::getInterruptHandlerAddress(void)
                    582: {
                    583:     return (IOInterruptAction)&IOSharedInterruptController::handleInterrupt;
                    584: }
                    585: 
                    586: IOReturn IOSharedInterruptController::handleInterrupt(void * /*refCon*/,
                    587:                                                      IOService * nub,
                    588:                                                      int /*source*/)
                    589: {
                    590:   long              vectorNumber;
                    591:   IOInterruptVector *vector;
                    592:   
                    593:   for (vectorNumber = 0; vectorNumber < numVectors; vectorNumber++) {
                    594:     vector = &vectors[vectorNumber];
                    595:     
                    596:     vector->interruptActive = 1;
                    597: #ifdef __ppc__
                    598:     sync();
                    599:     isync();
                    600: #endif
                    601:     if (!vector->interruptDisabledSoft) {
                    602: #ifdef __ppc__
                    603:       isync();
                    604: #endif
                    605:       
                    606:       // Call the handler if it exists.
                    607:       if (vector->interruptRegistered) {
                    608:        vector->handler(vector->target, vector->refCon,
                    609:                        vector->nub, vector->source);
                    610:       }
                    611:     }
                    612:     
                    613:     vector->interruptActive = 0;
                    614:   }
                    615:   
                    616:   // if any fo the vectors are dissabled, then dissable this controller.
                    617:   if (vectorsEnabled != vectorsRegistered) {
                    618:     nub->disableInterrupt(0);
                    619:     controllerDisabled = 1;
                    620:   }
                    621:   
                    622:   return kIOReturnSuccess;
                    623: }

unix.superglobalmegacorp.com

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