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