The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/iokit/Kernel/IOInterruptController.cpp

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
    5  * 
    6  * This file contains Original Code and/or Modifications of Original Code
    7  * as defined in and that are subject to the Apple Public Source License
    8  * Version 2.0 (the 'License'). You may not use this file except in
    9  * compliance with the License. The rights granted to you under the License
   10  * may not be used to create, or enable the creation or redistribution of,
   11  * unlawful or unlicensed copies of an Apple operating system, or to
   12  * circumvent, violate, or enable the circumvention or violation of, any
   13  * terms of an Apple operating system software license agreement.
   14  * 
   15  * Please obtain a copy of the License at
   16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
   17  * 
   18  * The Original Code and all software distributed under the License are
   19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   23  * Please see the License for the specific language governing rights and
   24  * limitations under the License.
   25  * 
   26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
   27  */
   28 /*
   29  * Copyright (c) 1999 Apple Computer, Inc.  All rights reserved. 
   30  *
   31  *  DRI: Josh de Cesare
   32  *
   33  */
   34 
   35 
   36 #if __ppc__
   37 #include <ppc/proc_reg.h> 
   38 #endif
   39 
   40 #include <IOKit/IOLib.h>
   41 #include <IOKit/IOService.h>
   42 #include <IOKit/IOPlatformExpert.h>
   43 #include <IOKit/IODeviceTreeSupport.h>
   44 #include <IOKit/IOInterrupts.h>
   45 #include <IOKit/IOInterruptController.h>
   46 
   47 
   48 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
   49 
   50 #define super IOService
   51 
   52 OSDefineMetaClassAndAbstractStructors(IOInterruptController, IOService);
   53 
   54 OSMetaClassDefineReservedUnused(IOInterruptController, 0);
   55 OSMetaClassDefineReservedUnused(IOInterruptController, 1);
   56 OSMetaClassDefineReservedUnused(IOInterruptController, 2);
   57 OSMetaClassDefineReservedUnused(IOInterruptController, 3);
   58 OSMetaClassDefineReservedUnused(IOInterruptController, 4);
   59 OSMetaClassDefineReservedUnused(IOInterruptController, 5);
   60 
   61 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
   62 
   63 IOReturn IOInterruptController::registerInterrupt(IOService *nub, int source,
   64                                                   void *target,
   65                                                   IOInterruptHandler handler,
   66                                                   void *refCon)
   67 {
   68   IOInterruptSource *interruptSources;
   69   long              vectorNumber;
   70   IOInterruptVector *vector;
   71   long              wasDisabledSoft;
   72   IOReturn          error;
   73   OSData            *vectorData;
   74   IOService         *originalNub;
   75   int               originalSource;
   76   IOOptionBits      options;
   77   bool              canBeShared, shouldBeShared, wasAlreadyRegisterd;
   78   
   79   interruptSources = nub->_interruptSources;
   80   vectorData = interruptSources[source].vectorData;
   81   vectorNumber = *(long *)vectorData->getBytesNoCopy();
   82   vector = &vectors[vectorNumber];
   83   
   84   // Get the lock for this vector.
   85   IOTakeLock(vector->interruptLock);
   86   
   87   // Check if the interrupt source can/should be shared.
   88   canBeShared = vectorCanBeShared(vectorNumber, vector);
   89   IODTGetInterruptOptions(nub, source, &options);
   90   shouldBeShared = canBeShared && (options & kIODTInterruptShared);
   91   wasAlreadyRegisterd = vector->interruptRegistered;
   92   
   93   // If the vector is registered and can not be shared return error.
   94   if (wasAlreadyRegisterd && !canBeShared) {
   95     IOUnlock(vector->interruptLock);
   96     return kIOReturnNoResources;
   97   }
   98   
   99   // If this vector is already in use, and can be shared (implied),
  100   // or it is not registered and should be shared,
  101   // register as a shared interrupt.
  102   if (wasAlreadyRegisterd || shouldBeShared) {
  103     // If this vector is not already shared, break it out.
  104     if (vector->sharedController == 0) {
  105       // Make the IOShareInterruptController instance
  106       vector->sharedController = new IOSharedInterruptController;
  107       if (vector->sharedController == 0) {
  108         IOUnlock(vector->interruptLock);
  109         return kIOReturnNoMemory;
  110       }
  111       
  112       if (wasAlreadyRegisterd) {
  113         // Save the nub and source for the original consumer.
  114         originalNub = vector->nub;
  115         originalSource = vector->source;
  116         
  117         // Physically disable the interrupt, but mark it as being enabled in the hardware.
  118         // The interruptDisabledSoft now indicates the driver's request for enablement.
  119         disableVectorHard(vectorNumber, vector);
  120         vector->interruptDisabledHard = 0;
  121       }
  122       
  123       // Initialize the new shared interrupt controller.
  124       error = vector->sharedController->initInterruptController(this, vectorData);
  125       // If the IOSharedInterruptController could not be initalized,
  126       // if needed, put the original consumer's interrupt back to normal and
  127       // get rid of whats left of the shared controller.
  128       if (error != kIOReturnSuccess) {
  129         if (wasAlreadyRegisterd) enableInterrupt(originalNub, originalSource);
  130         vector->sharedController->release();
  131         vector->sharedController = 0;
  132         IOUnlock(vector->interruptLock);
  133         return error;
  134       }
  135       
  136       // If there was an original consumer try to register it on the shared controller.
  137       if (wasAlreadyRegisterd) {
  138         error = vector->sharedController->registerInterrupt(originalNub,
  139                                                             originalSource,
  140                                                             vector->target,
  141                                                             vector->handler,
  142                                                             vector->refCon);
  143         // If the original consumer could not be moved to the shared controller,
  144         // put the original consumor's interrupt back to normal and
  145         // get rid of whats left of the shared controller.
  146         if (error != kIOReturnSuccess) {
  147           // Save the driver's interrupt enablement state.
  148           wasDisabledSoft = vector->interruptDisabledSoft;
  149           
  150           // Make the interrupt really hard disabled.
  151           vector->interruptDisabledSoft = 1;
  152           vector->interruptDisabledHard = 1;
  153           
  154           // Enable the original consumer's interrupt if needed.
  155           if (!wasDisabledSoft) originalNub->enableInterrupt(originalSource);
  156           enableInterrupt(originalNub, originalSource);
  157           
  158           vector->sharedController->release();
  159           vector->sharedController = 0;
  160           IOUnlock(vector->interruptLock);
  161           return error;
  162         }
  163       }
  164       
  165       // Fill in vector with the shared controller's info.
  166       vector->handler = (IOInterruptHandler)vector->sharedController->getInterruptHandlerAddress();
  167       vector->nub     = vector->sharedController;
  168       vector->source  = 0;
  169       vector->target  = vector->sharedController;
  170       vector->refCon  = 0;
  171       
  172       // If the interrupt was already registered,
  173       // save the driver's interrupt enablement state.
  174       if (wasAlreadyRegisterd) wasDisabledSoft = vector->interruptDisabledSoft;
  175       else wasDisabledSoft = true;
  176       
  177       // Do any specific initalization for this vector if it has not yet been used.
  178       if (!wasAlreadyRegisterd) initVector(vectorNumber, vector);
  179       
  180       // Make the interrupt really hard disabled.
  181       vector->interruptDisabledSoft = 1;
  182       vector->interruptDisabledHard = 1;
  183       vector->interruptRegistered   = 1;
  184       
  185       // Enable the original consumer's interrupt if needed.
  186       if (!wasDisabledSoft) originalNub->enableInterrupt(originalSource);
  187     }
  188     
  189     error = vector->sharedController->registerInterrupt(nub, source, target,
  190                                                         handler, refCon);
  191     IOUnlock(vector->interruptLock);
  192     return error;
  193   }
  194   
  195   // Fill in vector with the client's info.
  196   vector->handler = handler;
  197   vector->nub     = nub;
  198   vector->source  = source;
  199   vector->target  = target;
  200   vector->refCon  = refCon;
  201   
  202   // Do any specific initalization for this vector.
  203   initVector(vectorNumber, vector);
  204   
  205   // Get the vector ready.  It starts hard disabled.
  206   vector->interruptDisabledHard = 1;
  207   vector->interruptDisabledSoft = 1;
  208   vector->interruptRegistered   = 1;
  209   
  210   IOUnlock(vector->interruptLock);
  211   return kIOReturnSuccess;
  212 }
  213 
  214 IOReturn IOInterruptController::unregisterInterrupt(IOService *nub, int source)
  215 {
  216   IOInterruptSource *interruptSources;
  217   long              vectorNumber;
  218   IOInterruptVector *vector;
  219   OSData            *vectorData;
  220   
  221   interruptSources = nub->_interruptSources;
  222   vectorData = interruptSources[source].vectorData;
  223   vectorNumber = *(long *)vectorData->getBytesNoCopy();
  224   vector = &vectors[vectorNumber];
  225   
  226   // Get the lock for this vector.
  227   IOTakeLock(vector->interruptLock);
  228   
  229   // Return success if it is not already registered
  230   if (!vector->interruptRegistered) {
  231     IOUnlock(vector->interruptLock);
  232     return kIOReturnSuccess;
  233   }
  234   
  235   // Soft disable the source.
  236   disableInterrupt(nub, source);
  237   
  238   // Turn the source off at hardware. 
  239   disableVectorHard(vectorNumber, vector);
  240   
  241   // Clear all the storage for the vector except for interruptLock.
  242   vector->interruptActive = 0;
  243   vector->interruptDisabledSoft = 0;
  244   vector->interruptDisabledHard = 0;
  245   vector->interruptRegistered = 0;
  246   vector->nub = 0;
  247   vector->source = 0;
  248   vector->handler = 0;
  249   vector->target = 0;
  250   vector->refCon = 0;
  251   
  252   IOUnlock(vector->interruptLock);
  253   return kIOReturnSuccess;
  254 }
  255 
  256 IOReturn IOInterruptController::getInterruptType(IOService *nub, int source,
  257                                                  int *interruptType)
  258 {
  259   IOInterruptSource *interruptSources;
  260   long              vectorNumber;
  261   IOInterruptVector *vector;
  262   OSData            *vectorData;
  263   
  264   if (interruptType == 0) return kIOReturnBadArgument;
  265   
  266   interruptSources = nub->_interruptSources;
  267   vectorData = interruptSources[source].vectorData;
  268   vectorNumber = *(long *)vectorData->getBytesNoCopy();
  269   vector = &vectors[vectorNumber];
  270   
  271   *interruptType = getVectorType(vectorNumber, vector);
  272   
  273   return kIOReturnSuccess;
  274 }
  275 
  276 IOReturn IOInterruptController::enableInterrupt(IOService *nub, int source)
  277 {
  278   IOInterruptSource *interruptSources;
  279   long              vectorNumber;
  280   IOInterruptVector *vector;
  281   OSData            *vectorData;
  282   
  283   interruptSources = nub->_interruptSources;
  284   vectorData = interruptSources[source].vectorData;
  285   vectorNumber = *(long *)vectorData->getBytesNoCopy();
  286   vector = &vectors[vectorNumber];
  287   
  288   if (vector->interruptDisabledSoft) {
  289     vector->interruptDisabledSoft = 0;
  290 #if __ppc__
  291     sync();
  292     isync();
  293 #endif
  294     
  295     if (!getPlatform()->atInterruptLevel()) {
  296       while (vector->interruptActive);
  297 #if __ppc__
  298       isync();
  299 #endif
  300     }
  301     if (vector->interruptDisabledHard) {
  302       vector->interruptDisabledHard = 0;
  303       
  304       enableVector(vectorNumber, vector);
  305     }
  306   }
  307   
  308   return kIOReturnSuccess;
  309 }
  310 
  311 IOReturn IOInterruptController::disableInterrupt(IOService *nub, int source)
  312 {
  313   IOInterruptSource *interruptSources;
  314   long              vectorNumber;
  315   IOInterruptVector *vector;
  316   OSData            *vectorData;
  317   
  318   interruptSources = nub->_interruptSources;
  319   vectorData = interruptSources[source].vectorData;
  320   vectorNumber = *(long *)vectorData->getBytesNoCopy();
  321   vector = &vectors[vectorNumber];
  322   
  323   vector->interruptDisabledSoft = 1;
  324 #if __ppc__
  325   sync();
  326   isync();
  327 #endif
  328   
  329   if (!getPlatform()->atInterruptLevel()) {
  330     while (vector->interruptActive);
  331 #if __ppc__
  332     isync();
  333 #endif
  334   }
  335   
  336   return kIOReturnSuccess;
  337 }
  338 
  339 IOReturn IOInterruptController::causeInterrupt(IOService *nub, int source)
  340 {
  341   IOInterruptSource *interruptSources;
  342   long              vectorNumber;
  343   IOInterruptVector *vector;
  344   OSData            *vectorData;
  345 
  346   interruptSources = nub->_interruptSources;
  347   vectorData = interruptSources[source].vectorData;
  348   vectorNumber = *(long *)vectorData->getBytesNoCopy();
  349   vector = &vectors[vectorNumber];
  350   
  351   causeVector(vectorNumber, vector);
  352   
  353   return kIOReturnSuccess;
  354 }
  355 
  356 IOInterruptAction IOInterruptController::getInterruptHandlerAddress(void)
  357 {
  358   return 0;
  359 }
  360 
  361 IOReturn IOInterruptController::handleInterrupt(void *refCon, IOService *nub,
  362                                                 int source)
  363 {
  364   return kIOReturnInvalid;
  365 }
  366 
  367 
  368 // Methods to be overridden for simplifed interrupt controller subclasses.
  369 
  370 bool IOInterruptController::vectorCanBeShared(long /*vectorNumber*/,
  371                                               IOInterruptVector */*vector*/)
  372 {
  373   return false;
  374 }
  375 
  376 void IOInterruptController::initVector(long /*vectorNumber*/,
  377                                        IOInterruptVector */*vector*/)
  378 {
  379 }
  380 
  381 int IOInterruptController::getVectorType(long /*vectorNumber*/,
  382                                           IOInterruptVector */*vector*/)
  383 {
  384   return kIOInterruptTypeEdge;
  385 }
  386 
  387 void IOInterruptController::disableVectorHard(long /*vectorNumber*/,
  388                                               IOInterruptVector */*vector*/)
  389 {
  390 }
  391 
  392 void IOInterruptController::enableVector(long /*vectorNumber*/,
  393                                          IOInterruptVector */*vector*/)
  394 {
  395 }
  396 
  397 void IOInterruptController::causeVector(long /*vectorNumber*/,
  398                                         IOInterruptVector */*vector*/)
  399 {
  400 }
  401 
  402 
  403 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  404 
  405 #undef  super
  406 #define super IOInterruptController
  407 
  408 OSDefineMetaClassAndStructors(IOSharedInterruptController, IOInterruptController);
  409 
  410 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 0);
  411 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 1);
  412 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 2);
  413 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 3);
  414 
  415 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  416 
  417 #define kIOSharedInterruptControllerDefaultVectors (128)
  418 
  419 IOReturn IOSharedInterruptController::initInterruptController(IOInterruptController *parentController, OSData *parentSource)
  420 {
  421   int      cnt, interruptType;
  422   IOReturn error;
  423   
  424   if (!super::init())
  425     return kIOReturnNoResources;
  426   
  427   // Set provider to this so enable/disable nub stuff works.
  428   provider = this;
  429   
  430   // Allocate the IOInterruptSource so this can act like a nub.
  431   _interruptSources = (IOInterruptSource *)IOMalloc(sizeof(IOInterruptSource));
  432   if (_interruptSources == 0) return kIOReturnNoMemory;
  433   _numInterruptSources = 1;
  434   
  435   // Set up the IOInterruptSource to point at this.
  436   parentController->retain();
  437   parentSource->retain();
  438   _interruptSources[0].interruptController = parentController;
  439   _interruptSources[0].vectorData = parentSource;
  440   
  441   sourceIsLevel = false;
  442   error = provider->getInterruptType(0, &interruptType);
  443   if (error == kIOReturnSuccess) {
  444     if (interruptType & kIOInterruptTypeLevel)
  445       sourceIsLevel = true;
  446   }
  447   
  448   // Allocate the memory for the vectors
  449   numVectors = kIOSharedInterruptControllerDefaultVectors; // For now a constant number.
  450   vectors = (IOInterruptVector *)IOMalloc(numVectors * sizeof(IOInterruptVector));
  451   if (vectors == NULL) {
  452     IOFree(_interruptSources, sizeof(IOInterruptSource));
  453     return kIOReturnNoMemory;
  454   }
  455   bzero(vectors, numVectors * sizeof(IOInterruptVector));
  456   
  457   // Allocate the lock for the controller.
  458   controllerLock = IOSimpleLockAlloc();
  459   if (controllerLock == 0) return kIOReturnNoResources;
  460   
  461   // Allocate locks for the vectors.
  462   for (cnt = 0; cnt < numVectors; cnt++) {
  463     vectors[cnt].interruptLock = IOLockAlloc();
  464     if (vectors[cnt].interruptLock == NULL) {
  465       for (cnt = 0; cnt < numVectors; cnt++) {
  466         if (vectors[cnt].interruptLock != NULL)
  467           IOLockFree(vectors[cnt].interruptLock);
  468       }
  469       return kIOReturnNoResources;
  470     }
  471   }
  472   
  473   numVectors = 0; // reset the high water mark for used vectors
  474   vectorsRegistered = 0;
  475   vectorsEnabled = 0;
  476   controllerDisabled = 1;
  477   
  478   return kIOReturnSuccess;
  479 }
  480 
  481 IOReturn IOSharedInterruptController::registerInterrupt(IOService *nub,
  482                                                         int source,
  483                                                         void *target,
  484                                                         IOInterruptHandler handler,
  485                                                         void *refCon)
  486 {
  487   IOInterruptSource *interruptSources;
  488   long              vectorNumber;
  489   IOInterruptVector *vector = 0;
  490   OSData            *vectorData;
  491   IOInterruptState  interruptState;
  492   
  493   interruptSources = nub->_interruptSources;
  494   
  495   // Find a free vector.
  496   vectorNumber = kIOSharedInterruptControllerDefaultVectors;
  497   while (vectorsRegistered != kIOSharedInterruptControllerDefaultVectors) {
  498     for (vectorNumber = 0; vectorNumber < kIOSharedInterruptControllerDefaultVectors; vectorNumber++) {
  499       vector = &vectors[vectorNumber];
  500       
  501       // Get the lock for this vector.
  502       IOTakeLock(vector->interruptLock);
  503       
  504       // Is it unregistered?
  505       if (!vector->interruptRegistered) break;
  506       
  507       // Move along to the next one.
  508       IOUnlock(vector->interruptLock);
  509     }
  510     
  511     if (vectorNumber != kIOSharedInterruptControllerDefaultVectors) break;
  512   }
  513   
  514   // Could not find a free one, so give up.
  515   if (vectorNumber == kIOSharedInterruptControllerDefaultVectors) {
  516     return kIOReturnNoResources;
  517   }
  518   
  519   // Create the vectorData for the IOInterruptSource.
  520   vectorData = OSData::withBytes(&vectorNumber, sizeof(vectorNumber));
  521   if (vectorData == 0) {
  522     return kIOReturnNoMemory;
  523   }
  524   
  525   // Fill in the IOInterruptSource with the controller's info.
  526   interruptSources[source].interruptController = this;
  527   interruptSources[source].vectorData = vectorData;
  528   
  529   // Fill in vector with the client's info.
  530   vector->handler = handler;
  531   vector->nub     = nub;
  532   vector->source  = source;
  533   vector->target  = target;
  534   vector->refCon  = refCon;
  535   
  536   // Get the vector ready.  It starts off soft disabled.
  537   vector->interruptDisabledSoft = 1;
  538   vector->interruptRegistered   = 1;
  539   
  540   interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
  541   // Move the high water mark if needed
  542   if (++vectorsRegistered > numVectors) numVectors = vectorsRegistered;
  543   IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
  544   
  545   IOUnlock(vector->interruptLock);
  546   return kIOReturnSuccess;
  547 }
  548 
  549 IOReturn IOSharedInterruptController::unregisterInterrupt(IOService *nub,
  550                                                           int source)
  551 {
  552   IOInterruptSource *interruptSources;
  553   long              vectorNumber;
  554   IOInterruptVector *vector;
  555   OSData            *vectorData;
  556   IOInterruptState  interruptState;
  557   
  558   interruptSources = nub->_interruptSources;
  559   vectorData = interruptSources[source].vectorData;
  560   vectorNumber = *(long *)vectorData->getBytesNoCopy();
  561   vector = &vectors[vectorNumber];
  562   
  563   // Get the lock for this vector.
  564   IOTakeLock(vector->interruptLock);
  565   
  566   // Return success if it is not already registered
  567   if (!vector->interruptRegistered) {
  568     IOUnlock(vector->interruptLock);
  569     return kIOReturnSuccess;
  570   }
  571   
  572   // Soft disable the source and the controller too.
  573   disableInterrupt(nub, source);
  574   
  575   // Clear all the storage for the vector except for interruptLock.
  576   vector->interruptActive = 0;
  577   vector->interruptDisabledSoft = 0;
  578   vector->interruptDisabledHard = 0;
  579   vector->interruptRegistered = 0;
  580   vector->nub = 0;
  581   vector->source = 0;
  582   vector->handler = 0;
  583   vector->target = 0;
  584   vector->refCon = 0;
  585   
  586   interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
  587   vectorsRegistered--;
  588   IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
  589   
  590   IOUnlock(vector->interruptLock);
  591   
  592   // Re-enable the controller if all vectors are enabled.
  593   if (vectorsEnabled == vectorsRegistered) {
  594     controllerDisabled = 0;
  595     provider->enableInterrupt(0);
  596   }
  597   
  598   return kIOReturnSuccess;
  599 }
  600 
  601 IOReturn IOSharedInterruptController::getInterruptType(IOService */*nub*/,
  602                                                        int /*source*/,
  603                                                        int *interruptType)
  604 {
  605   return provider->getInterruptType(0, interruptType);
  606 }
  607 
  608 IOReturn IOSharedInterruptController::enableInterrupt(IOService *nub,
  609                                                       int source)
  610 {
  611   IOInterruptSource *interruptSources;
  612   long              vectorNumber;
  613   IOInterruptVector *vector;
  614   OSData            *vectorData;
  615   IOInterruptState  interruptState;
  616   
  617   interruptSources = nub->_interruptSources;
  618   vectorData = interruptSources[source].vectorData;
  619   vectorNumber = *(long *)vectorData->getBytesNoCopy();
  620   vector = &vectors[vectorNumber];
  621   
  622   interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
  623   if (!vector->interruptDisabledSoft) {
  624     IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
  625     return kIOReturnSuccess;
  626   }
  627   
  628   vector->interruptDisabledSoft = 0;
  629   vectorsEnabled++;
  630   IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
  631   
  632   if (controllerDisabled && (vectorsEnabled == vectorsRegistered)) {
  633     controllerDisabled = 0;
  634     provider->enableInterrupt(0);
  635   }
  636   
  637   return kIOReturnSuccess;
  638 }
  639 
  640 IOReturn IOSharedInterruptController::disableInterrupt(IOService *nub,
  641                                                        int source)
  642 {
  643   IOInterruptSource *interruptSources;
  644   long              vectorNumber;
  645   IOInterruptVector *vector;
  646   OSData            *vectorData;
  647   IOInterruptState  interruptState;
  648   
  649   interruptSources = nub->_interruptSources;
  650   vectorData = interruptSources[source].vectorData;
  651   vectorNumber = *(long *)vectorData->getBytesNoCopy();
  652   vector = &vectors[vectorNumber];
  653   
  654   interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); 
  655   if (!vector->interruptDisabledSoft) {
  656     vector->interruptDisabledSoft = 1;
  657 #if __ppc__
  658     sync();
  659     isync();
  660 #endif
  661     vectorsEnabled--;
  662   }
  663   IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
  664   
  665   if (!getPlatform()->atInterruptLevel()) {
  666     while (vector->interruptActive);
  667 #if __ppc__
  668     isync();
  669 #endif
  670   }
  671   
  672   return kIOReturnSuccess;
  673 }
  674 
  675 IOInterruptAction IOSharedInterruptController::getInterruptHandlerAddress(void)
  676 {
  677     return OSMemberFunctionCast(IOInterruptAction,
  678                         this, &IOSharedInterruptController::handleInterrupt);
  679 }
  680 
  681 IOReturn IOSharedInterruptController::handleInterrupt(void * /*refCon*/,
  682                                                       IOService * nub,
  683                                                       int /*source*/)
  684 {
  685   long              vectorNumber;
  686   IOInterruptVector *vector;
  687   
  688   for (vectorNumber = 0; vectorNumber < numVectors; vectorNumber++) {
  689     vector = &vectors[vectorNumber];
  690     
  691     vector->interruptActive = 1;
  692 #if __ppc__
  693     sync();
  694     isync();
  695 #endif
  696     if (!vector->interruptDisabledSoft) {
  697 #if __ppc__
  698       isync();
  699 #endif
  700       
  701       // Call the handler if it exists.
  702       if (vector->interruptRegistered) {
  703         vector->handler(vector->target, vector->refCon,
  704                         vector->nub, vector->source);
  705       }
  706     }
  707     
  708     vector->interruptActive = 0;
  709   }
  710   
  711   // if any of the vectors are dissabled, then dissable this controller.
  712   IOSimpleLockLock(controllerLock);
  713   if (vectorsEnabled != vectorsRegistered) {
  714     nub->disableInterrupt(0);
  715     controllerDisabled = 1;
  716   }
  717   IOSimpleLockUnlock(controllerLock);
  718   
  719   return kIOReturnSuccess;
  720 }
  721 

Cache object: d676c4320e3eed60f6be21d6b43e0ef8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.