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