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