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