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