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 248 if (vector->interruptDisabledHard) { 249 vector->interruptDisabledHard = 0; 250 251 enableVector(vectorNumber, vector); 252 } 253 } 254 255 return kIOReturnSuccess; 256 } 257 258 IOReturn IOInterruptController::disableInterrupt(IOService *nub, int source) 259 { 260 IOInterruptSource *interruptSources; 261 long vectorNumber; 262 IOInterruptVector *vector; 263 OSData *vectorData; 264 265 interruptSources = nub->_interruptSources; 266 vectorData = interruptSources[source].vectorData; 267 vectorNumber = *(long *)vectorData->getBytesNoCopy(); 268 vector = &vectors[vectorNumber]; 269 270 vector->interruptDisabledSoft = 1; 271 #if __ppc__ 272 sync(); 273 isync(); 274 #endif 275 276 if (!getPlatform()->atInterruptLevel()) { 277 while (vector->interruptActive); 278 #if __ppc__ 279 isync(); 280 #endif 281 } 282 283 return kIOReturnSuccess; 284 } 285 286 IOReturn IOInterruptController::causeInterrupt(IOService *nub, int source) 287 { 288 IOInterruptSource *interruptSources; 289 long vectorNumber; 290 IOInterruptVector *vector; 291 OSData *vectorData; 292 293 interruptSources = nub->_interruptSources; 294 vectorData = interruptSources[source].vectorData; 295 vectorNumber = *(long *)vectorData->getBytesNoCopy(); 296 vector = &vectors[vectorNumber]; 297 298 causeVector(vectorNumber, vector); 299 300 return kIOReturnSuccess; 301 } 302 303 IOInterruptAction IOInterruptController::getInterruptHandlerAddress(void) 304 { 305 return 0; 306 } 307 308 IOReturn IOInterruptController::handleInterrupt(void *refCon, IOService *nub, 309 int source) 310 { 311 return kIOReturnInvalid; 312 } 313 314 315 // Methods to be overridden for simplifed interrupt controller subclasses. 316 317 bool IOInterruptController::vectorCanBeShared(long /*vectorNumber*/, 318 IOInterruptVector */*vector*/) 319 { 320 return false; 321 } 322 323 void IOInterruptController::initVector(long /*vectorNumber*/, 324 IOInterruptVector */*vector*/) 325 { 326 } 327 328 int IOInterruptController::getVectorType(long /*vectorNumber*/, 329 IOInterruptVector */*vector*/) 330 { 331 return kIOInterruptTypeEdge; 332 } 333 334 void IOInterruptController::disableVectorHard(long /*vectorNumber*/, 335 IOInterruptVector */*vector*/) 336 { 337 } 338 339 void IOInterruptController::enableVector(long /*vectorNumber*/, 340 IOInterruptVector */*vector*/) 341 { 342 } 343 344 void IOInterruptController::causeVector(long /*vectorNumber*/, 345 IOInterruptVector */*vector*/) 346 { 347 } 348 349 350 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 351 352 #undef super 353 #define super IOInterruptController 354 355 OSDefineMetaClassAndStructors(IOSharedInterruptController, IOInterruptController); 356 357 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 0); 358 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 1); 359 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 2); 360 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 3); 361 362 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 363 364 IOReturn IOSharedInterruptController::initInterruptController(IOInterruptController *parentController, OSData *parentSource) 365 { 366 int cnt, interruptType; 367 IOReturn error; 368 369 if (!super::init()) 370 return kIOReturnNoResources; 371 372 // Set provider to this so enable/disable nub stuff works. 373 provider = this; 374 375 // Allocate the IOInterruptSource so this can act like a nub. 376 _interruptSources = (IOInterruptSource *)IOMalloc(sizeof(IOInterruptSource)); 377 if (_interruptSources == 0) return kIOReturnNoMemory; 378 _numInterruptSources = 1; 379 380 // Set up the IOInterruptSource to point at this. 381 _interruptSources[0].interruptController = parentController; 382 _interruptSources[0].vectorData = parentSource; 383 384 sourceIsLevel = false; 385 error = provider->getInterruptType(0, &interruptType); 386 if (error == kIOReturnSuccess) { 387 if (interruptType & kIOInterruptTypeLevel) 388 sourceIsLevel = true; 389 } 390 391 // Allocate the memory for the vectors 392 numVectors = 8; // For now a constant number. 393 vectors = (IOInterruptVector *)IOMalloc(numVectors * sizeof(IOInterruptVector)); 394 if (vectors == NULL) { 395 IOFree(_interruptSources, sizeof(IOInterruptSource)); 396 return kIOReturnNoMemory; 397 } 398 bzero(vectors, numVectors * sizeof(IOInterruptVector)); 399 400 // Allocate the lock for the controller. 401 controllerLock = IOSimpleLockAlloc(); 402 if (controllerLock == 0) return kIOReturnNoResources; 403 404 // Allocate locks for the vectors. 405 for (cnt = 0; cnt < numVectors; cnt++) { 406 vectors[cnt].interruptLock = IOLockAlloc(); 407 if (vectors[cnt].interruptLock == NULL) { 408 for (cnt = 0; cnt < numVectors; cnt++) { 409 if (vectors[cnt].interruptLock != NULL) 410 IOLockFree(vectors[cnt].interruptLock); 411 } 412 return kIOReturnNoResources; 413 } 414 } 415 416 vectorsRegistered = 0; 417 vectorsEnabled = 0; 418 controllerDisabled = 1; 419 420 return kIOReturnSuccess; 421 } 422 423 IOReturn IOSharedInterruptController::registerInterrupt(IOService *nub, 424 int source, 425 void *target, 426 IOInterruptHandler handler, 427 void *refCon) 428 { 429 IOInterruptSource *interruptSources; 430 long vectorNumber; 431 IOInterruptVector *vector = 0; 432 OSData *vectorData; 433 IOInterruptState interruptState; 434 435 interruptSources = nub->_interruptSources; 436 437 // Find a free vector. 438 vectorNumber = numVectors; 439 while (vectorsRegistered != numVectors) { 440 for (vectorNumber = 0; vectorNumber < numVectors; vectorNumber++) { 441 vector = &vectors[vectorNumber]; 442 443 // Get the lock for this vector. 444 IOTakeLock(vector->interruptLock); 445 446 // Is it unregistered? 447 if (!vector->interruptRegistered) break; 448 449 // Move along to the next one. 450 IOUnlock(vector->interruptLock); 451 } 452 453 if (vectorNumber != numVectors) break; 454 } 455 456 // Could not find a free one, so give up. 457 if (vectorNumber == numVectors) { 458 return kIOReturnNoResources; 459 } 460 461 // Create the vectorData for the IOInterruptSource. 462 vectorData = OSData::withBytes(&vectorNumber, sizeof(vectorNumber)); 463 if (vectorData == 0) { 464 return kIOReturnNoMemory; 465 } 466 467 // Fill in the IOInterruptSource with the controller's info. 468 interruptSources[source].interruptController = this; 469 interruptSources[source].vectorData = vectorData; 470 471 // Fill in vector with the client's info. 472 vector->handler = handler; 473 vector->nub = nub; 474 vector->source = source; 475 vector->target = target; 476 vector->refCon = refCon; 477 478 // Get the vector ready. It start soft disabled. 479 vector->interruptDisabledSoft = 1; 480 vector->interruptRegistered = 1; 481 482 interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); 483 vectorsRegistered++; 484 IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); 485 486 IOUnlock(vector->interruptLock); 487 return kIOReturnSuccess; 488 } 489 490 IOReturn IOSharedInterruptController::unregisterInterrupt(IOService *nub, 491 int source) 492 { 493 IOInterruptSource *interruptSources; 494 long vectorNumber; 495 IOInterruptVector *vector; 496 OSData *vectorData; 497 IOInterruptState interruptState;; 498 499 interruptSources = nub->_interruptSources; 500 vectorData = interruptSources[source].vectorData; 501 vectorNumber = *(long *)vectorData->getBytesNoCopy(); 502 vector = &vectors[vectorNumber]; 503 504 // Get the lock for this vector. 505 IOTakeLock(vector->interruptLock); 506 507 // Return success if it is not already registered 508 if (!vector->interruptRegistered) { 509 IOUnlock(vector->interruptLock); 510 return kIOReturnSuccess; 511 } 512 513 // Soft disable the source. 514 disableInterrupt(nub, source); 515 516 // Clear all the storage for the vector except for interruptLock. 517 vector->interruptActive = 0; 518 vector->interruptDisabledSoft = 0; 519 vector->interruptDisabledHard = 0; 520 vector->interruptRegistered = 0; 521 vector->nub = 0; 522 vector->source = 0; 523 vector->handler = 0; 524 vector->target = 0; 525 vector->refCon = 0; 526 527 interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); 528 vectorsRegistered--; 529 IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); 530 531 IOUnlock(vector->interruptLock); 532 return kIOReturnSuccess; 533 } 534 535 IOReturn IOSharedInterruptController::getInterruptType(IOService */*nub*/, 536 int /*source*/, 537 int *interruptType) 538 { 539 return provider->getInterruptType(0, interruptType); 540 } 541 542 IOReturn IOSharedInterruptController::enableInterrupt(IOService *nub, 543 int source) 544 { 545 IOInterruptSource *interruptSources; 546 long vectorNumber; 547 IOInterruptVector *vector; 548 OSData *vectorData; 549 IOInterruptState interruptState;; 550 551 interruptSources = nub->_interruptSources; 552 vectorData = interruptSources[source].vectorData; 553 vectorNumber = *(long *)vectorData->getBytesNoCopy(); 554 vector = &vectors[vectorNumber]; 555 556 if (vector->interruptDisabledSoft) { 557 vector->interruptDisabledSoft = 0; 558 559 interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); 560 vectorsEnabled++; 561 IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); 562 563 if (controllerDisabled && (vectorsEnabled == vectorsRegistered)) { 564 controllerDisabled = 0; 565 provider->enableInterrupt(0); 566 } 567 } 568 569 return kIOReturnSuccess; 570 } 571 572 IOReturn IOSharedInterruptController::disableInterrupt(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 if (!vector->interruptDisabledSoft) { 587 vector->interruptDisabledSoft = 1; 588 #if __ppc__ 589 sync(); 590 isync(); 591 #endif 592 593 interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); 594 vectorsEnabled--; 595 IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); 596 } 597 598 if (!getPlatform()->atInterruptLevel()) { 599 while (vector->interruptActive); 600 #if __ppc__ 601 isync(); 602 #endif 603 } 604 605 return kIOReturnSuccess; 606 } 607 608 IOInterruptAction IOSharedInterruptController::getInterruptHandlerAddress(void) 609 { 610 return (IOInterruptAction)&IOSharedInterruptController::handleInterrupt; 611 } 612 613 IOReturn IOSharedInterruptController::handleInterrupt(void * /*refCon*/, 614 IOService * nub, 615 int /*source*/) 616 { 617 long vectorNumber; 618 IOInterruptVector *vector; 619 620 for (vectorNumber = 0; vectorNumber < numVectors; vectorNumber++) { 621 vector = &vectors[vectorNumber]; 622 623 vector->interruptActive = 1; 624 #if __ppc__ 625 sync(); 626 isync(); 627 #endif 628 if (!vector->interruptDisabledSoft) { 629 #if __ppc__ 630 isync(); 631 #endif 632 633 // Call the handler if it exists. 634 if (vector->interruptRegistered) { 635 vector->handler(vector->target, vector->refCon, 636 vector->nub, vector->source); 637 } 638 } 639 640 vector->interruptActive = 0; 641 } 642 643 // if any of the vectors are dissabled, then dissable this controller. 644 IOSimpleLockLock(controllerLock); 645 if (vectorsEnabled != vectorsRegistered) { 646 nub->disableInterrupt(0); 647 controllerDisabled = 1; 648 } 649 IOSimpleLockUnlock(controllerLock); 650 651 return kIOReturnSuccess; 652 } 653 654