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