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 722