1/* 2 * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved. 3 * Copyright (c) 2007-2021 Apple Inc. All rights reserved. 4 * 5 * @APPLE_LICENSE_HEADER_START@ 6 * 7 * The contents of this file constitute Original Code as defined in and 8 * are subject to the Apple Public Source License Version 1.1 (the 9 * "License"). You may not use this file except in compliance with the 10 * License. Please obtain a copy of the License at 11 * http://www.apple.com/publicsource and read it before using this file. 12 * 13 * This Original Code and all software distributed under the License are 14 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 18 * License for the specific language governing rights and limitations 19 * under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 26 27#include <IOKit/pci/IOPCIPrivate.h> 28#include <IOKit/system.h> 29#include <IOKit/IODeviceTreeSupport.h> 30#include <IOKit/IOPlatformExpert.h> 31#include <IOKit/IOLib.h> 32 33#define kMSIFreeCountKey "MSIFree" 34 35#ifndef kBaseVectorNumberKey 36#define kBaseVectorNumberKey "Base Vector Number" 37#endif 38 39#ifndef kVectorCountKey 40#define kVectorCountKey "Vector Count" 41#endif 42 43#ifndef kInterruptControllerNameKey 44#define kInterruptControllerNameKey "InterruptControllerName" 45#endif 46 47extern uint32_t gIOPCIFlags; 48 49#undef super 50#define super IOInterruptController 51 52OSDefineMetaClassAndStructors(IOPCIMessagedInterruptController, IOInterruptController) 53 54/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 55 56#define API_ENTRY() \ 57 IOInterruptSource * interruptSources; \ 58 IOInterruptVector * vector; \ 59 IOInterruptVector * subVectors; \ 60 OSData * vectorData; \ 61 IOInterruptVectorNumber vectorNumber; \ 62 \ 63 interruptSources = nub->_interruptSources; \ 64 vectorData = interruptSources[source].vectorData; \ 65 vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy(); \ 66 vector = &vectors[vectorNumber]; \ 67 if ((subVectors = (typeof(subVectors)) vector->sharedController)) \ 68 { \ 69 vectorNumber = source - vector->source; /* now msi index */ \ 70 vector = subVectors + vectorNumber; \ 71 } 72 73/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 74 75IOReturn IOPCIMessagedInterruptController::registerInterrupt(IOService *nub, int source, 76 void *target, 77 IOInterruptHandler handler, 78 void *refCon) 79{ 80 API_ENTRY(); 81 82 // Get the lock for this vector. 83 IOLockLock(vector->interruptLock); 84 85 if (vector->interruptRegistered) 86 { 87 IOLockUnlock(vector->interruptLock); 88 return (kIOReturnNoResources); 89 } 90 91 // Fill in vector with the client's info. 92 vector->handler = handler; 93 vector->nub = nub; 94 vector->source = source; 95 vector->target = target; 96 vector->refCon = refCon; 97 98 // Do any specific initalization for this vector. 99 initVector(vectorNumber, vector); 100 101 // Get the vector ready. It starts hard disabled. 102 vector->interruptDisabledHard = 1; 103 vector->interruptDisabledSoft = 1; 104 vector->interruptRegistered = 1; 105 106 IOLockUnlock(vector->interruptLock); 107 108 IOPCIDevice * device = OSDynamicCast(IOPCIDevice, nub); 109 enableDeviceMSI(device); 110 111 return (kIOReturnSuccess); 112} 113 114IOReturn IOPCIMessagedInterruptController::unregisterInterrupt(IOService *nub, int source) 115{ 116 API_ENTRY(); 117 118 // Get the lock for this vector. 119 IOLockLock(vector->interruptLock); 120 121 // Return success if it is not already registered 122 if (!vector->interruptRegistered) 123 { 124 IOLockUnlock(vector->interruptLock); 125 return (kIOReturnSuccess); 126 } 127 128 // Soft disable the source. 129 disableInterrupt(nub, source); 130 131 // Turn the source off at hardware. 132 disableVectorHard(vectorNumber, vector); 133 134 // Clear all the storage for the vector except for interruptLock. 135 vector->interruptActive = 0; 136 vector->interruptDisabledSoft = 0; 137 vector->interruptDisabledHard = 0; 138 vector->interruptRegistered = 0; 139 vector->nub = 0; 140 vector->source = 0; 141 vector->handler = 0; 142 vector->target = 0; 143 vector->refCon = 0; 144 145 IOLockUnlock(vector->interruptLock); 146 147 IOPCIDevice * device = OSDynamicCast(IOPCIDevice, nub); 148 disableDeviceMSI(device); 149 150 return (kIOReturnSuccess); 151} 152 153IOReturn IOPCIMessagedInterruptController::getInterruptType(IOService *nub, int source, 154 int *interruptType) 155{ 156 if (interruptType == 0) return (kIOReturnBadArgument); 157 158 API_ENTRY(); 159 160 *interruptType = getVectorType(vectorNumber, vector); 161 162 return (kIOReturnSuccess); 163} 164 165IOReturn IOPCIMessagedInterruptController::enableInterrupt(IOService *nub, int source) 166{ 167 API_ENTRY(); 168 169 if (vector->interruptDisabledSoft) 170 { 171 vector->interruptDisabledSoft = 0; 172#if !defined(__i386__) && !defined(__x86_64__) 173 OSMemoryBarrier(); 174#endif 175 if (!getPlatform()->atInterruptLevel()) 176 { 177 while (vector->interruptActive) {} 178 } 179 if (vector->interruptDisabledHard) 180 { 181 vector->interruptDisabledHard = 0; 182 enableVector(vectorNumber, vector); 183 } 184 } 185 186 return (kIOReturnSuccess); 187} 188 189IOReturn IOPCIMessagedInterruptController::disableInterrupt(IOService *nub, int source) 190{ 191 API_ENTRY(); 192 193 vector->interruptDisabledSoft = 1; 194#if !defined(__i386__) && !defined(__x86_64__) 195 OSMemoryBarrier(); 196#endif 197 198 if (!getPlatform()->atInterruptLevel()) 199 { 200 while (vector->interruptActive) {} 201 } 202 203 return (kIOReturnSuccess); 204} 205 206/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 207 208IOInterruptVector * IOPCIMessagedInterruptController::allocVectors(uint32_t count) 209{ 210 IOInterruptVector * vectors; 211 212 vectors = IONew(IOInterruptVector, count); 213 if (!vectors) return (0); 214 bzero(vectors, sizeof(IOInterruptVector) * count); 215 216 // Allocate locks for the vectors. 217 for (uint32_t i = 0; i < count; i++) 218 { 219 vectors[i].interruptLock = IOLockAlloc(); 220 if (!vectors[i].interruptLock) return (0); 221 } 222 223 return (vectors); 224} 225 226bool IOPCIMessagedInterruptController::init(UInt32 numVectors, UInt32 baseVector) 227{ 228 OSNumber * num; 229 const OSSymbol * sym = 0; 230 231 if (!super::init()) 232 return (false); 233 234 _vectorCount = numVectors; 235 setProperty(kVectorCountKey, _vectorCount, 32); 236 if (-1 != baseVector) setProperty(kBaseVectorNumberKey, baseVector, 32); 237 238 // Allocate the memory for the vectors shared with the superclass. 239 vectors = allocVectors(_vectorCount); 240 if (!vectors) return (false); 241 242 attach(getPlatform()); 243 sym = copyName(); 244 setProperty(kInterruptControllerNameKey, (OSObject *) sym); 245 getPlatform()->registerInterruptController( (OSSymbol *) sym, this ); 246 sym->release(); 247 248 num = OSDynamicCast(OSNumber, getProperty(kBaseVectorNumberKey)); 249 if (num) _vectorBase = num->unsigned32BitValue(); 250 251 _messagedInterruptsAllocator = IORangeAllocator::withRange(0, 0, 4, IORangeAllocator::kLocking); 252 _messagedInterruptsAllocator->deallocate(0, _vectorCount); 253 setProperty(kMSIFreeCountKey, _messagedInterruptsAllocator->getFreeCount(), 32); 254 255 registerService(); 256 257 return (true); 258} 259 260bool IOPCIMessagedInterruptController::init(UInt32 numVectors) 261{ 262 return (init(numVectors, -1)); 263} 264 265bool IOPCIMessagedInterruptController::addDeviceInterruptProperties( 266 IORegistryEntry * device, 267 UInt32 controllerIndex, 268 UInt32 interruptFlags, 269 SInt32 * deviceIndex) 270{ 271 OSArray * controllers; 272 OSArray * specifiers; 273 OSArray * liveCtrls; 274 OSArray * liveSpecs; 275 const OSSymbol * symName; 276 OSData * specData; 277 bool success = false; 278 279 if (!device) return false; 280 281 liveCtrls = OSDynamicCast(OSArray, 282 device->getProperty(gIOInterruptControllersKey)); 283 284 liveSpecs = OSDynamicCast(OSArray, 285 device->getProperty(gIOInterruptSpecifiersKey)); 286 287 if (liveCtrls && liveSpecs) 288 { 289 // reserve space for new interrupt vector 290 controllers = OSArray::withArray(liveCtrls, liveCtrls->getCount() + 1); 291 specifiers = OSArray::withArray(liveSpecs, liveSpecs->getCount() + 1); 292 } 293 else 294 { 295 controllers = OSArray::withCapacity(1); 296 specifiers = OSArray::withCapacity(1); 297 } 298 299 specData = OSData::withCapacity(2 * sizeof(UInt32)); 300 symName = copyName(); 301 302 if (!controllers || !specifiers || !specData || !symName) return (false); 303 304 // Specifier data will be 64-bits long, containing: 305 // data[0] = interrupt number 306 // data[1] = interrupt flags 307 // This must agree with interrupt controller drivers. 308 // 309 // << Warning >> 310 // IOInterruptController::registerInterrupt() assumes that 311 // the vectorNumber is the first long in the specifier. 312 313 specData->appendBytes(&controllerIndex, sizeof(controllerIndex)); 314 specData->appendBytes(&interruptFlags, sizeof(interruptFlags)); 315 316 if (deviceIndex) 317 *deviceIndex = specifiers->getCount() - 1; 318 319 success = specifiers->setObject(specData) 320 && controllers->setObject(symName); 321 322 if (success) 323 { 324 device->setProperty(gIOInterruptControllersKey, controllers); 325 device->setProperty(gIOInterruptSpecifiersKey, specifiers); 326 } 327 328 specifiers->release(); 329 controllers->release(); 330 symName->release(); 331 specData->release(); 332 333 return (success); 334} 335 336IOReturn IOPCIMessagedInterruptController::allocateDeviceInterrupts( 337 IOService * entry, uint32_t numVectors, uint32_t msiCapability, 338 uint64_t * msiAddress, uint32_t * msiData) 339{ 340 IOReturn ret; 341 IOPCIDevice * device; 342 uint32_t vector, firstVector = _vectorBase; 343 IORangeScalar rangeStart; 344 uint32_t message[3]; 345 uint32_t msiPhysVectors; 346 uint16_t control = 0; 347 bool allocated; 348 349 device = OSDynamicCast(IOPCIDevice, entry); 350 if (!device) msiCapability = 0; 351 msiPhysVectors = 0; 352 353 if (msiCapability) 354 { 355 uint32_t vendorProd; 356 uint32_t revIDClass; 357 358 msiCapability = device->reserved->msiCapability; 359 control = device->configRead16(msiCapability + 2); 360 if (kMSIX & device->reserved->msiMode) 361 msiPhysVectors = 1 + (0x7ff & control); 362 else 363 msiPhysVectors = 1 << (0x7 & (control >> 1)); 364 365 numVectors = msiPhysVectors; 366 vendorProd = device->savedConfig[kIOPCIConfigVendorID >> 2]; 367 revIDClass = device->savedConfig[kIOPCIConfigRevisionID >> 2]; 368 369 // pci2pci bridges get none or one for hotplug 370 if (0x0604 == (revIDClass >> 16)) 371 { 372 bool tunnelLink = (0 != device->getProperty(kIOPCITunnelLinkChangeKey)); 373 if (tunnelLink 374 || device->getProperty(kIOPCIHotPlugKey) 375 || device->getProperty(kIOPCILinkChangeKey)) 376 { 377 // hot plug bridge, but use legacy if avail 378 uint8_t line = device->configRead8(kIOPCIConfigInterruptLine); 379 if (tunnelLink) 380 { 381 tunnelLink = (0x15138086 != vendorProd) 382 && (0x151a8086 != vendorProd) 383 && (0x151b8086 != vendorProd) 384 && (0x15498086 != vendorProd) 385 && ((0x15478086 != vendorProd) || ((revIDClass & 0xff) > 1)); 386 } 387 if (tunnelLink || (line == 0) || (line == 0xFF)) 388 { 389 // no legacy ints, need one MSI 390 numVectors = 1; 391 } 392 else numVectors = 0; 393 } 394 else 395 { 396 // no hot plug 397 numVectors = 0; 398 } 399 } 400#if !defined(SUPPORT_MULTIPLE_MSI) 401 else if (numVectors) 402 { 403 // max per function is one 404 numVectors = 1; 405 } 406#endif 407 } 408 409 allocated = false; 410 rangeStart = 0; 411 while (!allocated && numVectors > 0) 412 { 413 allocated = allocateInterruptVectors(entry, numVectors, &rangeStart); 414 if (!allocated) numVectors >>= 1; 415 } 416 if (!allocated) return (kIOReturnNoSpace); 417 418 firstVector = rangeStart; 419 ret = entry->callPlatformFunction(gIOPlatformGetMessagedInterruptAddressKey, 420 /* waitForFunction */ false, 421 /* nub */ entry, 422 /* options */ (void *) 0, 423 /* vector */ (void *) (uintptr_t) (firstVector + _vectorBase), 424 /* message */ (void *) &message[0]); 425 426 if (kIOReturnSuccess == ret) 427 { 428 if (msiAddress) *msiAddress = message[0] | (((uint64_t)message[1]) << 32); 429 if (msiData) *msiData = message[2]; 430 431 if (msiCapability) 432 { 433 IOPCIConfigShadow * shadow; 434 435 shadow = configShadow(device); 436 if ((kMSIX & device->reserved->msiMode) 437 && (numVectors < msiPhysVectors)) 438 { 439 device->reserved->msiVectors = allocVectors(msiPhysVectors); 440 IOInterruptVector * ivector = &vectors[firstVector]; 441 // Fill in vector with the IOPCIMessagedInterruptController info 442 ivector->handler = OSMemberFunctionCast(IOInterruptHandler, 443 this, &IOPCIMessagedInterruptController::handleInterrupt); 444 ivector->nub = device; 445 ivector->target = this; 446 ivector->refCon = 0; 447 initVector(firstVector, ivector); 448 ivector->interruptDisabledSoft = 0; 449 ivector->interruptDisabledHard = 0; 450 ivector->interruptRegistered = msiPhysVectors; 451 ivector->sharedController = (IOSharedInterruptController *) device->reserved->msiVectors; 452 453 for (vector = 0; vector < msiPhysVectors; vector++) 454 { 455 SInt32 deviceIndex; 456 addDeviceInterruptProperties(entry, firstVector, 457 kIOInterruptTypeEdge | kIOInterruptTypePCIMessaged, &deviceIndex); 458 if (!vector) ivector->source = deviceIndex; 459 } 460 } 461 else 462 { 463 device->reserved->msiVectors = &vectors[firstVector]; 464 for (vector = firstVector; vector < (firstVector + numVectors); vector++) 465 { 466 addDeviceInterruptProperties(entry, vector, 467 kIOInterruptTypeEdge | kIOInterruptTypePCIMessaged, NULL); 468 } 469 } 470 471 shadow->savedMSIAddress0 = message[0]; 472 shadow->savedMSIAddress1 = message[1]; 473 shadow->savedMSIData = message[2]; 474 device->reserved->msiPhysVectorCount = msiPhysVectors; 475 device->reserved->msiVectorCount = numVectors; 476 477 if (kMSIX & device->reserved->msiMode) 478 { 479 IOMemoryMap * map; 480 uint32_t table; 481 uint8_t bar; 482 483 table = device->configRead32(msiCapability + 8); 484 bar = kIOPCIConfigBaseAddress0 + ((table & 7) << 2); 485 table &= ~7; 486 map = device->mapDeviceMemoryWithRegister(bar); 487 if (map) device->reserved->msiPBA = map->getAddress() + table; 488 489 table = device->configRead32(msiCapability + 4); 490 bar = (kIOPCIConfigBaseAddress0 + ((table & 7) << 2)); 491 table &= ~7; 492 map = device->mapDeviceMemoryWithRegister(bar); 493 if (map) device->reserved->msiTable = map->getAddress() + table; 494 } 495 else 496 { 497 if (numVectors) numVectors = (31 - __builtin_clz(numVectors)); // log2 498 control |= (numVectors << 4); 499 } 500 control &= ~((1 << 15) | 1); // disabled 501 device->reserved->msiControl = control; 502 initDevice(device, shadow); 503 } 504 } 505 506 return (ret); 507} 508 509void IOPCIMessagedInterruptController::initDevice(IOPCIDevice * device, IOPCIConfigShadow * shadow) 510{ 511 IOInterruptVector * vectors; 512 uint32_t numVectors, msiPhysVectors, vector, data; 513 uint16_t control, msiCapability, cmd; 514 515 msiCapability = device->reserved->msiCapability; 516 control = device->reserved->msiControl; 517 numVectors = device->reserved->msiVectorCount; 518 msiPhysVectors = device->reserved->msiPhysVectorCount; 519 520 if (kMSIX & device->reserved->msiMode) 521 { 522 if (device->reserved->msiTable) 523 { 524 vectors = device->reserved->msiVectors; 525 cmd = device->configRead16(kIOPCIConfigCommand); 526 device->configWrite16(kIOPCIConfigCommand, cmd | kIOPCICommandMemorySpace); 527 for (vector = 0; vector < msiPhysVectors; vector++) 528 { 529 data = shadow->savedMSIData; 530 if (vector < numVectors) data += vector; 531 ((uint32_t *) device->reserved->msiTable)[vector*4 + 0] = shadow->savedMSIAddress0; 532 ((uint32_t *) device->reserved->msiTable)[vector*4 + 1] = shadow->savedMSIAddress1; 533 ((uint32_t *) device->reserved->msiTable)[vector*4 + 2] = data; 534 ((uint32_t *) device->reserved->msiTable)[vector*4 + 3] = vectors[vector].interruptDisabledHard; 535 } 536 device->configWrite16(kIOPCIConfigCommand, cmd); 537 } 538 } 539 else 540 { 541 device->configWrite32(msiCapability + 4, shadow->savedMSIAddress0); 542 if (0x0080 & control) 543 { 544 // 64b 545 device->configWrite32(msiCapability + 8, shadow->savedMSIAddress1); 546 device->configWrite16(msiCapability + 12, shadow->savedMSIData); 547 } 548 else 549 { 550 device->configWrite16(msiCapability + 8, shadow->savedMSIData); 551 } 552// if (0x0100 & control) msiBlockSize += 2; 553 } 554 device->configWrite16(msiCapability + 2, control); 555} 556 557void IOPCIMessagedInterruptController::enableDeviceMSI(IOPCIDevice *device) 558{ 559 if (device && device->reserved && !device->isInactive()) 560 { 561 if (!device->reserved->msiEnable) 562 { 563 IOByteCount msi = device->reserved->msiCapability; 564 uint16_t control; 565 566 control = device->reserved->msiControl; 567 if (kMSIX & device->reserved->msiMode) 568 { 569 control |= (1 << 15); 570 } 571 else 572 { 573 control |= 1; 574 } 575 device->reserved->msiControl = control; 576 device->configWrite16(msi + 2, control); 577 578 control = device->configRead16(kIOPCIConfigCommand); 579 control |= kIOPCICommandInterruptDisable | kIOPCICommandBusMaster; 580 device->configWrite16(kIOPCIConfigCommand, control); 581 device->setProperty("IOPCIMSIMode", kOSBooleanTrue); 582 } 583 device->reserved->msiEnable++; 584 } 585} 586 587void IOPCIMessagedInterruptController::disableDeviceMSI(IOPCIDevice *device) 588{ 589 if (device && device->reserved 590 && device->reserved->msiEnable 591 && !(--device->reserved->msiEnable) 592 && !device->isInactive()) 593 { 594 IOByteCount msi = device->reserved->msiCapability; 595 uint16_t control; 596 597 control = device->reserved->msiControl; 598 control &= ~((1 << 15) | 1); 599 device->reserved->msiControl = control; 600 device->configWrite16(msi + 2, control); 601 602 control = device->configRead16(kIOPCIConfigCommand); 603 control &= ~kIOPCICommandInterruptDisable; 604 device->configWrite16(kIOPCIConfigCommand, control); 605 606 device->removeProperty("IOPCIMSIMode"); 607 } 608} 609 610void IOPCIMessagedInterruptController::saveDeviceState(IOPCIDevice * device, IOPCIConfigShadow * shadow) 611{ 612 if (!device->reserved->msiCapability) return; 613} 614 615void IOPCIMessagedInterruptController::restoreDeviceState(IOPCIDevice * device, IOPCIConfigShadow * shadow) 616{ 617 if (!device->reserved->msiCapability) return; 618 initDevice(device, shadow); 619} 620 621bool IOPCIMessagedInterruptController::reserveVectors(UInt32 vector, UInt32 count) 622{ 623 bool result; 624 625 result = _messagedInterruptsAllocator->allocateRange(vector, count); 626 if (result) setProperty(kMSIFreeCountKey, _messagedInterruptsAllocator->getFreeCount(), 32); 627 628 return (result); 629} 630 631bool IOPCIMessagedInterruptController::allocateInterruptVectors( IOService *device, 632 uint32_t numVectors, 633 IORangeScalar *rangeStartOut) 634{ 635 bool result; 636 637 result = _messagedInterruptsAllocator->allocate(numVectors, rangeStartOut, numVectors); 638 if (result) setProperty(kMSIFreeCountKey, _messagedInterruptsAllocator->getFreeCount(), 32); 639 640 return (result); 641} 642 643IOReturn IOPCIMessagedInterruptController::deallocateDeviceInterrupts(IOService * device) 644{ 645 const OSSymbol * myName; 646 OSArray * controllers; 647 OSObject * controller; 648 OSArray * specs; 649 OSData * spec; 650 uint32_t index = 0; 651 uint32_t firstVector; 652 653 myName = copyName(); 654 655 controllers = OSDynamicCast(OSArray, device->getProperty(gIOInterruptControllersKey)); 656 specs = OSDynamicCast(OSArray, device->getProperty(gIOInterruptSpecifiersKey)); 657 658 if (!myName || !controllers || !specs) return (kIOReturnBadArgument); 659 660 for (firstVector = -1U; 661 (spec = OSDynamicCast(OSData, specs->getObject(index))) 662 && (controller = controllers->getObject(index)); 663 index++) 664 { 665 if (!controller->isEqualTo(myName)) continue; 666 667 uint32_t vector = *((uint32_t *) spec->getBytesNoCopy()); 668 if (vector == firstVector) continue; 669 if (-1U == firstVector) firstVector = vector; 670 deallocateInterrupt(vector); 671 } 672 myName->release(); 673 674 return (kIOReturnSuccess); 675} 676 677void IOPCIMessagedInterruptController::deallocateInterrupt(UInt32 vector) 678{ 679 IOInterruptVector * subVectors; 680 IORangeScalar rangeStart; 681 uint32_t count; 682 683 if ((subVectors = (IOInterruptVector *) vectors[vector].sharedController)) 684 { 685 count = vectors[vector].interruptRegistered; 686 vectors[vector].sharedController = 0; 687 IODelete(subVectors, IOInterruptVector, count); 688 } 689 690 rangeStart = vector; 691 _messagedInterruptsAllocator->deallocate(rangeStart, 1); 692 setProperty(kMSIFreeCountKey, _messagedInterruptsAllocator->getFreeCount(), 32); 693} 694 695IOReturn 696IOPCIMessagedInterruptController::handleInterrupt( void * state, 697 IOService * nub, 698 int source) 699{ 700 IOInterruptVector * vector; 701 IOInterruptVector * subVectors; 702 IOPCIDevice * device; 703 uint64_t bits; 704 uint32_t count, bit; 705 706 source -= _vectorBase; 707 if ((source < 0) || (source > (int) _vectorCount)) return (kIOReturnSuccess); 708 709 vector = &vectors[source]; 710 if ((subVectors = (IOInterruptVector *) vector->sharedController)) 711 { 712 device = (IOPCIDevice *) vector->nub; 713// if (!(kIOPCICommandMemorySpace & device->configRead16(kIOPCIConfigCommand))) return (kIOReturnSuccess); 714 715 count = vector->interruptRegistered; 716 bits = 0; 717 for (source = 0; source < count; source++) 718 { 719 bit = (source & 63); 720 if (!bit) bits = ((uint64_t *) device->reserved->msiPBA)[source >> 6]; 721 if (!(bits & (1ULL << bit))) continue; 722 723 vector = &subVectors[source]; 724// if (!vector->interruptRegistered && source) vector = &vectors[0]; 725 vector->interruptActive = 1; 726 if (vector->interruptRegistered) 727 { 728 if (vector->interruptDisabledHard) vector->interruptRegistered = 3; 729 else 730 { 731 vector->handler(vector->target, vector->refCon, vector->nub, vector->source); 732 } 733 } 734 vector->interruptActive = 0; 735 } 736 } 737 else 738 { 739 vector->interruptActive = 1; 740 if (vector->interruptRegistered) 741 { 742 if (vector->interruptDisabledHard) vector->interruptRegistered = 3; 743 else 744 { 745 vector->handler(vector->target, vector->refCon, vector->nub, vector->source); 746 } 747 } 748 vector->interruptActive = 0; 749 } 750 751 return (kIOReturnSuccess); 752} 753 754bool IOPCIMessagedInterruptController::vectorCanBeShared(IOInterruptVectorNumber vectorNumber, 755 IOInterruptVector * vector) 756{ 757 return (false); 758} 759 760void IOPCIMessagedInterruptController::initVector(IOInterruptVectorNumber vectorNumber, 761 IOInterruptVector * vector) 762{ 763} 764 765int IOPCIMessagedInterruptController::getVectorType(IOInterruptVectorNumber vectorNumber, 766 IOInterruptVector * vector) 767{ 768 return (kIOInterruptTypeEdge | kIOInterruptTypePCIMessaged); 769} 770 771void IOPCIMessagedInterruptController::disableVectorHard(IOInterruptVectorNumber vectorNumber, 772 IOInterruptVector * vector) 773{ 774 IOPCIDevice * device; 775 device = (IOPCIDevice *) vector->nub; 776 777 if (device->reserved->msiTable) 778 { 779 // masked 780 ((uint32_t *) device->reserved->msiTable)[vectorNumber * 4 + 3] = 1; 781 } 782} 783 784void IOPCIMessagedInterruptController::enableVector(IOInterruptVectorNumber vectorNumber, 785 IOInterruptVector * vector) 786{ 787 IOPCIDevice * device; 788 device = (IOPCIDevice *) vector->nub; 789 790 if (3 == vector->interruptRegistered) 791 { 792 vector->interruptRegistered = 1; 793 vector->handler(vector->target, vector->refCon, 794 vector->nub, vector->source); 795 } 796 if (device->reserved->msiTable) 797 { 798 // enabled 799 ((uint32_t *) device->reserved->msiTable)[vectorNumber * 4 + 3] = 0; 800 } 801} 802