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#include <IOKit/system.h> 24 25#include <IOKit/pci/IOPCIBridge.h> 26#include <IOKit/pci/IOPCIPrivate.h> 27#include <IOKit/pci/IOAGPDevice.h> 28#include <IOKit/pci/IOPCIConfigurator.h> 29#if ACPI_SUPPORT 30#include <IOKit/acpi/IOACPIPlatformDevice.h> 31#endif 32 33#include <IOKit/IODeviceTreeSupport.h> 34#include <IOKit/IOSubMemoryDescriptor.h> 35#include <IOKit/IORangeAllocator.h> 36#include <IOKit/IOPlatformExpert.h> 37#include <IOKit/pwr_mgt/IOPMPrivate.h> 38#include <IOKit/IOLib.h> 39#include <IOKit/IOKitKeys.h> 40#include <IOKit/IOMessage.h> 41#include <IOKit/assert.h> 42#include <IOKit/IOCatalogue.h> 43#include <IOKit/IOFilterInterruptEventSource.h> 44#include <IOKit/IOTimerEventSource.h> 45#include <IOKit/IOPolledInterface.h> 46#include <IOKit/IOUserClient.h> 47 48#include <libkern/c++/OSContainers.h> 49#include <libkern/OSKextLib.h> 50#include <libkern/version.h> 51 52extern "C" 53{ 54#include <machine/machine_routines.h> 55}; 56 57/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 58 59#ifndef VERSION_MAJOR 60#error VERSION_MAJOR 61#endif 62 63#if VERSION_MAJOR < 10 64#define ROM_KEXTS 1 65#endif 66 67#ifndef kIOPolledInterfaceActiveKey 68#define kIOPolledInterfaceActiveKey "IOPolledInterfaceActive" 69#endif 70 71// #define DEADTEST "UPS0" 72// #define DEFERTEST 1 73 74enum 75{ 76 kIOPCIClassBridge = 0x06, 77 kIOPCIClassNetwork = 0x02, 78 kIOPCIClassGraphics = 0x03, 79 kIOPCIClassMultimedia = 0x04, 80 81 kIOPCISubClassBridgeHost = 0x00, 82 kIOPCISubClassBridgeISA = 0x01, 83 kIOPCISubClassBridgeEISA = 0x02, 84 kIOPCISubClassBridgeMCA = 0x03, 85 kIOPCISubClassBridgePCI = 0x04, 86 kIOPCISubClassBridgePCMCIA = 0x05, 87 kIOPCISubClassBridgeNuBus = 0x06, 88 kIOPCISubClassBridgeCardBus = 0x07, 89 kIOPCISubClassBridgeRaceWay = 0x08, 90 kIOPCISubClassBridgeOther = 0x80, 91}; 92 93enum 94{ 95 kCheckLinkParents = 0x00000001, 96}; 97 98enum { kAERISRNum = 4 }; 99enum { kIOPCIEventNum = 8 }; 100 101/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 102 103const IORegistryPlane * gIOPCIACPIPlane; 104 105static class IOPCIMessagedInterruptController * gIOPCIMessagedInterruptController; 106 107static IOSimpleLock * gIOPCIEventSourceLock; 108static queue_head_t gIOPCIEventSourceQueue; 109 110static IOSimpleLock * gIOAllPCI2PCIBridgesLock; 111static UInt32 gIOAllPCI2PCIBridgeState; 112static uint64_t gIOPCIWakeCount = 0x100000001ULL; 113 114static IOLock * gIOPCIWakeReasonLock; 115 116const OSSymbol * gIOPCITunnelIDKey; 117const OSSymbol * gIOPCITunnelledKey; 118const OSSymbol * gIOPCIThunderboltKey; 119const OSSymbol * gIOPCITunnelL1EnableKey; 120 121const OSSymbol * gIOPlatformDeviceMessageKey; 122const OSSymbol * gIOPlatformDeviceASPMEnableKey; 123const OSSymbol * gIOPlatformSetDeviceInterruptsKey; 124const OSSymbol * gIOPlatformResolvePCIInterruptKey; 125const OSSymbol * gIOPlatformFreeDeviceResourcesKey; 126const OSSymbol * gIOPlatformGetMessagedInterruptControllerKey; 127const OSSymbol * gIOPlatformGetMessagedInterruptAddressKey; 128const OSSymbol * gIOPolledInterfaceActiveKey; 129 130#if ACPI_SUPPORT 131const OSSymbol * gIOPCIPSMethods[kIOPCIDevicePowerStateCount]; 132#endif 133 134static queue_head_t gIOAllPCIDeviceRestoreQ; 135static uint32_t gIOPCITunnelSleep; 136static uint32_t gIOPCITunnelWait; 137 138static IOWorkLoop * gIOPCIConfigWorkLoop; 139static IOPCIConfigurator * gIOPCIConfigurator; 140 141uint32_t gIOPCIFlags = 0 142 | kIOPCIConfiguratorAllocate 143 | kIOPCIConfiguratorPFM64 144 | kIOPCIConfiguratorCheckTunnel 145 | kIOPCIConfiguratorTBMSIEnable 146#if !ACPI_SUPPORT 147 | kIOPCIConfiguratorAER 148#endif 149// | kIOPCIConfiguratorDeepIdle 150// | kIOPCIConfiguratorNoSplay 151// | kIOPCIConfiguratorNoTB 152// | kIOPCIConfiguratorIOLog | kIOPCIConfiguratorKPrintf 153; 154 155#define DLOG(fmt, args...) \ 156 do { \ 157 if ((gIOPCIFlags & kIOPCIConfiguratorIOLog) && !ml_at_interrupt_context()) \ 158 IOLog(fmt, ## args); \ 159 if (gIOPCIFlags & kIOPCIConfiguratorKPrintf) \ 160 kprintf(fmt, ## args); \ 161 } while(0) 162 163 164/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 165 166enum 167{ 168 // data link change, hot plug, presence detect change 169 kSlotControlEnables = ((1 << 12) | (1 << 5) | (1 << 3)) 170}; 171 172/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 173 174struct IOPCIAERISREntry 175{ 176 uint32_t source; 177 uint32_t status; 178}; 179 180struct IOPCIAERRoot 181{ 182 IOPCIAERISREntry * fISRErrors; 183 uint8_t fAERReadIndex; 184 uint8_t fAERWriteIndex; 185}; 186 187/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 188 189#undef super 190#include "vtd.c" 191 192/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 193 194#undef super 195#define super IOService 196OSDefineMetaClassAndAbstractStructorsWithInit( IOPCIBridge, IOService, IOPCIBridge::initialize() ) 197 198OSMetaClassDefineReservedUsed(IOPCIBridge, 0); 199OSMetaClassDefineReservedUsed(IOPCIBridge, 1); 200OSMetaClassDefineReservedUsed(IOPCIBridge, 2); 201OSMetaClassDefineReservedUsed(IOPCIBridge, 3); 202OSMetaClassDefineReservedUsed(IOPCIBridge, 4); 203OSMetaClassDefineReservedUsed(IOPCIBridge, 5); 204OSMetaClassDefineReservedUnused(IOPCIBridge, 6); 205OSMetaClassDefineReservedUnused(IOPCIBridge, 7); 206OSMetaClassDefineReservedUnused(IOPCIBridge, 8); 207OSMetaClassDefineReservedUnused(IOPCIBridge, 9); 208OSMetaClassDefineReservedUnused(IOPCIBridge, 10); 209OSMetaClassDefineReservedUnused(IOPCIBridge, 11); 210OSMetaClassDefineReservedUnused(IOPCIBridge, 12); 211OSMetaClassDefineReservedUnused(IOPCIBridge, 13); 212OSMetaClassDefineReservedUnused(IOPCIBridge, 14); 213OSMetaClassDefineReservedUnused(IOPCIBridge, 15); 214OSMetaClassDefineReservedUnused(IOPCIBridge, 16); 215OSMetaClassDefineReservedUnused(IOPCIBridge, 17); 216OSMetaClassDefineReservedUnused(IOPCIBridge, 18); 217OSMetaClassDefineReservedUnused(IOPCIBridge, 19); 218OSMetaClassDefineReservedUnused(IOPCIBridge, 20); 219OSMetaClassDefineReservedUnused(IOPCIBridge, 21); 220OSMetaClassDefineReservedUnused(IOPCIBridge, 22); 221OSMetaClassDefineReservedUnused(IOPCIBridge, 23); 222OSMetaClassDefineReservedUnused(IOPCIBridge, 24); 223OSMetaClassDefineReservedUnused(IOPCIBridge, 25); 224OSMetaClassDefineReservedUnused(IOPCIBridge, 26); 225OSMetaClassDefineReservedUnused(IOPCIBridge, 27); 226OSMetaClassDefineReservedUnused(IOPCIBridge, 28); 227OSMetaClassDefineReservedUnused(IOPCIBridge, 29); 228OSMetaClassDefineReservedUnused(IOPCIBridge, 30); 229OSMetaClassDefineReservedUnused(IOPCIBridge, 31); 230 231/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 232 233#ifndef kIOPlatformDeviceMessageKey 234#define kIOPlatformDeviceMessageKey "IOPlatformDeviceMessage" 235#endif 236 237#ifndef kIOPlatformSetDeviceInterruptsKey 238#define kIOPlatformSetDeviceInterruptsKey "SetDeviceInterrupts" 239#endif 240 241#ifndef kIOPlatformResolvePCIInterruptKey 242#define kIOPlatformResolvePCIInterruptKey "ResolvePCIInterrupt" 243#endif 244 245#ifndef kIOPlatformFreeDeviceResourcesKey 246#define kIOPlatformFreeDeviceResourcesKey "IOPlatformFreeDeviceResources" 247#endif 248 249#ifndef kIOPlatformGetMessagedInterruptAddressKey 250#define kIOPlatformGetMessagedInterruptAddressKey "GetMessagedInterruptAddress" 251#endif 252 253#ifndef kIOPlatformGetMessagedInterruptControllerKey 254#define kIOPlatformGetMessagedInterruptControllerKey "GetMessagedInterruptController" 255#endif 256 257/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 258 259void IOPCIBridge::initialize(void) 260{ 261 if (!gIOAllPCI2PCIBridgesLock) 262 { 263 gIOAllPCI2PCIBridgesLock = IOSimpleLockAlloc(); 264 gIOPCIEventSourceLock = IOSimpleLockAlloc(); 265 queue_init(&gIOAllPCIDeviceRestoreQ); 266 queue_init(&gIOPCIEventSourceQueue); 267 gIOPCIWakeReasonLock = IOLockAlloc(); 268 269 gIOPlatformDeviceMessageKey 270 = OSSymbol::withCStringNoCopy(kIOPlatformDeviceMessageKey); 271 gIOPlatformDeviceASPMEnableKey 272 = OSSymbol::withCStringNoCopy(kIOPlatformDeviceASPMEnableKey); 273 gIOPlatformSetDeviceInterruptsKey 274 = OSSymbol::withCStringNoCopy(kIOPlatformSetDeviceInterruptsKey); 275 gIOPlatformResolvePCIInterruptKey 276 = OSSymbol::withCStringNoCopy(kIOPlatformResolvePCIInterruptKey); 277 gIOPlatformFreeDeviceResourcesKey 278 = OSSymbol::withCStringNoCopy(kIOPlatformFreeDeviceResourcesKey); 279 gIOPlatformGetMessagedInterruptAddressKey 280 = OSSymbol::withCStringNoCopy(kIOPlatformGetMessagedInterruptAddressKey); 281 gIOPlatformGetMessagedInterruptControllerKey 282 = OSSymbol::withCStringNoCopy(kIOPlatformGetMessagedInterruptControllerKey); 283#if ACPI_SUPPORT 284 gIOPCIPSMethods[kIOPCIDeviceOffState] = OSSymbol::withCStringNoCopy("_PS3"); 285 gIOPCIPSMethods[kIOPCIDeviceDozeState] = OSSymbol::withCStringNoCopy("RPS3"); 286 gIOPCIPSMethods[kIOPCIDeviceOnState] = OSSymbol::withCStringNoCopy("_PS0"); 287#endif 288 gIOPCIConfigWorkLoop = IOWorkLoop::workLoop(); 289 } 290} 291 292IOWorkLoop * IOPCIBridge::getConfiguratorWorkLoop(void) const 293{ 294 return (gIOPCIConfigWorkLoop); 295} 296 297IOReturn IOPCIBridge::configOp(IOService * device, uintptr_t op, void * result, void * arg) 298{ 299 static OSSet * gIOPCIWaitingPauseSet; 300 static OSSet * gIOPCIPausedSet; 301 static OSSet * gIOPCIProbeSet; 302 303 IOReturn ret = kIOReturnSuccess; 304 OSSet * changed; 305 IOPCIDevice * next; 306 uint32_t state; 307 308 if (!gIOPCIConfigWorkLoop->inGate()) 309 return (gIOPCIConfigWorkLoop->runAction((IOWorkLoop::Action) &IOPCIBridge::configOp, 310 device, (void *) op, result, arg)); 311 if (!gIOPCIConfigurator) 312 { 313 uint32_t debug; 314 315 if (getPMRootDomain()->getProperty(kIOPMDeepIdleSupportedKey)) 316 { 317 if (PE_parse_boot_argn("acpi", &debug, sizeof(debug)) && (0x10000 & debug)) {} 318 else 319 gIOPCIFlags |= kIOPCIConfiguratorDeepIdle; 320 } 321#if VERSION_MAJOR >= 13 322 gIOPCIFlags |= kIOPCIConfiguratorUsePause; 323#endif 324 if (PE_parse_boot_argn("pci", &debug, sizeof(debug))) 325 gIOPCIFlags |= debug; 326 if (PE_parse_boot_argn("npci", &debug, sizeof(debug))) 327 gIOPCIFlags &= ~debug; 328 329 gIOPCIACPIPlane = IORegistryEntry::getPlane("IOACPIPlane"); 330 gIOPCITunnelIDKey = OSSymbol::withCStringNoCopy(kIOPCITunnelIDKey); 331 gIOPCITunnelledKey = OSSymbol::withCStringNoCopy(kIOPCITunnelledKey); 332 gIOPCITunnelL1EnableKey = OSSymbol::withCStringNoCopy(kIOPCITunnelL1EnableKey); 333 gIOPCIThunderboltKey = OSSymbol::withCStringNoCopy("PCI-Thunderbolt"); 334 gIOPolledInterfaceActiveKey = OSSymbol::withCStringNoCopy(kIOPolledInterfaceActiveKey); 335 336 gIOPCIWaitingPauseSet = OSSet::withCapacity(4); 337 gIOPCIPausedSet = OSSet::withCapacity(4); 338 gIOPCIProbeSet = OSSet::withCapacity(4); 339 340 gIOPCIConfigurator = OSTypeAlloc(IOPCIConfigurator); 341 if (!gIOPCIConfigurator || !gIOPCIConfigurator->init(gIOPCIConfigWorkLoop, gIOPCIFlags)) 342 panic("!IOPCIConfigurator"); 343 344#if defined(__i386__) || defined(__x86_64__) 345 if (!gIOPCIMessagedInterruptController) 346 { 347 enum { 348 // LAPIC_DEFAULT_INTERRUPT_BASE (mp.h) 349 kBaseMessagedInterruptVectors = 0x70, 350 kNumMessagedInterruptVectors = 0xFF - kBaseMessagedInterruptVectors 351 }; 352 bool ok = true; 353 IOPCIMessagedInterruptController * 354 ic = new IOPCIMessagedInterruptController; 355 if (ic && !ic->init(kNumMessagedInterruptVectors, kBaseMessagedInterruptVectors)) 356 { 357 ic->release(); 358 ic = 0; 359 } 360 if (ic) 361 { 362 ok = ic->reserveVectors(0x7F - kBaseMessagedInterruptVectors, 4); 363 ok &= ic->reserveVectors(0xD0 - kBaseMessagedInterruptVectors, 16); 364 } 365 if (!ic || !ok) panic("IOPCIMessagedInterruptController"); 366 gIOPCIMessagedInterruptController = ic; 367 } 368#endif 369 370#if ACPI_SUPPORT 371 IOACPIPlatformDevice * acpiDevice; 372 if (!(acpiDevice = (typeof(acpiDevice)) device->getProvider()->metaCast("IOACPIPlatformDevice"))) 373 panic("host!IOACPIPlatformDevice"); 374 AppleVTD::install(gIOPCIConfigWorkLoop, gIOPCIFlags, acpiDevice, acpiDevice->getACPITableData("DMAR", 0)); 375#endif 376 } 377 378 if (kConfigOpScan != op) 379 { 380 ret = gIOPCIConfigurator->configOp(device, op, result, arg); 381 if (kIOReturnSuccess != ret) return (ret); 382 383 next = (IOPCIDevice *) device; 384 if (kConfigOpTerminated == op) 385 { 386 gIOPCIWaitingPauseSet->removeObject(next); 387 gIOPCIPausedSet->removeObject(next); 388 gIOPCIProbeSet->removeObject(next); 389 } 390 else if (kConfigOpTestPause == op) 391 { 392 if (gIOPCIWaitingPauseSet->setObject(next)) 393 { 394 next->changePowerStateToPriv(kIOPCIDevicePausedState); 395 next->powerOverrideOnPriv(); 396 } 397 } 398 399 if (op != kConfigOpPaused) op = 0; 400 else 401 { 402 op = 0; 403 404 DLOG("configOp:->pause: %s(0x%qx)\n", device->getName(), device->getRegistryEntryID()); 405 if (gIOPCIWaitingPauseSet->containsObject(device)) 406 { 407 gIOPCIPausedSet->setObject(device); 408 gIOPCIWaitingPauseSet->removeObject(device); 409 if (!gIOPCIWaitingPauseSet->getCount()) op = kConfigOpRealloc; 410 } 411 } 412 } 413 414 while (op) 415 { 416 ret = gIOPCIConfigurator->configOp(device, op, &changed); 417 op = 0; 418 if (kIOReturnSuccess != ret) break; 419 if (!changed) break; 420 421 while ((next = (IOPCIDevice *) changed->getAnyObject())) 422 { 423 ret = gIOPCIConfigurator->configOp(next, kConfigOpGetState, &state); 424 if (kIOReturnSuccess == ret) 425 { 426 if (kPCIDeviceStateDead & state) 427 { 428 DLOG("configOp:->dead: %s(0x%qx), 0x%x\n", next->getName(), next->getRegistryEntryID(), state); 429 next->terminate(); 430 } 431 else if (kPCIDeviceStateRequestPause & state) 432 { 433 DLOG("configOp:->pause: %s(0x%qx), 0x%x\n", next->getName(), next->getRegistryEntryID(), state); 434 if (gIOPCIWaitingPauseSet->setObject(next)) 435 { 436 next->changePowerStateToPriv(kIOPCIDevicePausedState); 437 next->powerOverrideOnPriv(); 438 } 439 } 440 else 441 { 442 DLOG("configOp:->probe: %s(0x%qx), 0x%x\n", next->getName(), next->getRegistryEntryID(), state); 443 gIOPCIProbeSet->setObject(next); 444 } 445 } 446 changed->removeObject(next); 447 } 448 changed->release(); 449 } 450 451 if (!gIOPCIWaitingPauseSet->getCount()) 452 { 453 while ((next = (IOPCIDevice *) gIOPCIPausedSet->getAnyObject())) 454 { 455 DLOG("configOp:<-unpause: %s(0x%qx)\n", next->getName(), next->getRegistryEntryID()); 456 if (2 != next->reserved->pauseFlags) 457 { 458 next->changePowerStateToPriv(kIOPCIDeviceOnState); 459 next->powerOverrideOffPriv(); 460 } 461 next->reserved->pauseFlags = 0; 462 gIOPCIPausedSet->removeObject(next); 463 } 464 while ((next = (IOPCIDevice *) gIOPCIProbeSet->getAnyObject())) 465 { 466 DLOG("configOp:<-probe: %s(0x%qx), pm %d\n", next->getName(), next->getRegistryEntryID(), next->reserved->pciPMState); 467 if (kIOPCIDeviceOnState == next->reserved->pciPMState) deferredProbe(next); 468 else next->reserved->needsProbe = true; 469 gIOPCIProbeSet->removeObject(next); 470 } 471 } 472 473 return (ret); 474} 475 476void IOPCIBridge::deferredProbe(IOPCIDevice * device) 477{ 478 IOService * client; 479 IOPCIBridge * bridge; 480 481 client = device->copyClientWithCategory(gIODefaultMatchCategoryKey); 482 if ((bridge = OSDynamicCast(IOPCIBridge, client))) 483 { 484 DLOG("configOp:<-probe: %s(0x%qx)\n", device->getName(), device->getRegistryEntryID()); 485 bridge->probeBus(device, bridge->firstBusNum()); 486 } 487 if (client) client->release(); 488 489 device->reserved->needsProbe = false; 490} 491 492//********************************************************************************* 493 494static const IOPMPowerState gIOPCIPowerStates[kIOPCIDevicePowerStateCount] = { 495 // version, capabilityFlags, outputPowerCharacter, inputPowerRequirement, staticPower, stateOrder 496 { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 497 { 2, 0, kIOPMSoftSleep, kIOPMSoftSleep, 0, 1, 0, 0, 0, 0, 0, 0 }, 498 { 2, kIOPMPowerOn, kIOPMPowerOn, kIOPMPowerOn, 0, 3, 0, 0, 0, 0, 0, 0 }, 499 { 2, kIOPMConfigRetained, kIOPMConfigRetained, kIOPMConfigRetained, 0, 2, 0, 0, 0, 0, 0, 0 } 500}; 501 502static const IOPMPowerState gIOPCIHostPowerStates[kIOPCIDevicePowerStateCount] = { 503 // version, capabilityFlags, outputPowerCharacter, inputPowerRequirement, staticPower, stateOrder 504 { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 505 { 2, 0, kIOPMSoftSleep, kIOPMSoftSleep, 0, 1, 0, 0, 0, 0, 0, 0 }, 506 { 2, kIOPMPowerOn, kIOPMPowerOn, kIOPMPowerOn, 0, 3, 0, 0, 0, 0, 0, 0 }, 507 { 2, kIOPMConfigRetained, kIOPMConfigRetained, kIOPMPowerOn, 0, 2, 0, 0, 0, 0, 0, 0 } 508}; 509 510 511// version without kIOPCIDevicePausedState 512static const IOPMPowerState gIOPCIPowerStatesV1[kIOPCIDevicePowerStateCount - 1] = { 513 // version, capabilityFlags, outputPowerCharacter, inputPowerRequirement, 514 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 515 { 1, 0, kIOPMSoftSleep, kIOPMSoftSleep, 0, 0, 0, 0, 0, 0, 0, 0 }, 516 { 1, kIOPMPowerOn, kIOPMPowerOn, kIOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 } 517}; 518 519//********************************************************************************* 520 521IOReturn 522IOPCIRegisterPowerDriver(IOService * service, bool hostbridge) 523{ 524 IOReturn ret; 525 IOPMPowerState * powerStates = hostbridge 526 ? (IOPMPowerState *) gIOPCIHostPowerStates 527 : (IOPMPowerState *) gIOPCIPowerStates; 528 529 ret = service->registerPowerDriver(service, powerStates, kIOPCIDevicePowerStateCount); 530 if (kIOReturnSuccess != ret) 531 { 532 ret = service->registerPowerDriver(service, 533 (IOPMPowerState *) gIOPCIPowerStatesV1, 534 arrayCount(gIOPCIPowerStatesV1)); 535 } 536 return (ret); 537} 538 539//********************************************************************************* 540// [public] maxCapabilityForDomainState 541// 542// Finds the highest power state in the array whose input power 543// requirement is equal to the input parameter. Where a more intelligent 544// decision is possible, override this in the subclassed driver. 545//********************************************************************************* 546 547unsigned long 548IOPCIBridge::maxCapabilityForDomainState ( IOPMPowerFlags domainState ) 549{ 550 if (domainState & kIOPMPowerOn) return (kIOPCIDeviceOnState); 551 if (domainState & kIOPMSoftSleep) return (kIOPCIDeviceDozeState); 552 if (domainState & kIOPMConfigRetained) return (kIOPCIDevicePausedState); 553 return (kIOPCIDeviceOffState); 554} 555 556//********************************************************************************* 557// [public] initialPowerStateForDomainState 558// 559// Finds the highest power state in the array whose input power 560// requirement is equal to the input parameter. Where a more intelligent 561// decision is possible, override this in the subclassed driver. 562//********************************************************************************* 563 564unsigned long 565IOPCIBridge::initialPowerStateForDomainState ( IOPMPowerFlags domainState ) 566{ 567 if (domainState & kIOPMPowerOn) return (kIOPCIDeviceOnState); 568 if (domainState & kIOPMSoftSleep) return (kIOPCIDeviceDozeState); 569 if (domainState & kIOPMConfigRetained) return (kIOPCIDevicePausedState); 570 return (kIOPCIDeviceOffState); 571} 572 573//********************************************************************************* 574// [public] powerStateForDomainState 575// 576// Finds the highest power state in the array whose input power 577// requirement is equal to the input parameter. Where a more intelligent 578// decision is possible, override this in the subclassed driver. 579//********************************************************************************* 580 581unsigned long 582IOPCIBridge::powerStateForDomainState ( IOPMPowerFlags domainState ) 583{ 584 if (domainState & kIOPMPowerOn) return (kIOPCIDeviceOnState); 585 if (domainState & kIOPMSoftSleep) return (kIOPCIDeviceDozeState); 586 if (domainState & kIOPMConfigRetained) return (kIOPCIDevicePausedState); 587 return (kIOPCIDeviceOffState); 588} 589 590//********************************************************************************* 591 592bool IOPCIBridge::start( IOService * provider ) 593{ 594 IOPCIDevice * pciDevice; 595 596 if (!super::start(provider)) 597 return (false); 598 599 reserved = IONew(ExpansionData, 1); 600 if (reserved == 0) return (false); 601 bzero(reserved, sizeof(ExpansionData)); 602 603 if (!configure(provider)) return (false); 604 pciDevice = OSDynamicCast(IOPCIDevice, provider); 605 606 // initialize superclass variables 607 PMinit(); 608 // clamp power on 609// temporaryPowerClampOn(); 610 // register as controlling driver 611 IOPCIRegisterPowerDriver(this, !pciDevice); 612 613 // join the tree 614 provider->joinPMtree(this); 615 616 pciDevice = OSDynamicCast(IOPCIDevice, provider); 617 if (!pciDevice) 618 { 619 IOReturn 620 ret = configOp(this, kConfigOpAddHostBridge, 0); 621 if (kIOReturnSuccess != ret) 622 return (false); 623 } 624 625 probeBus( provider, firstBusNum() ); 626 627 if ((kIOPCIConfiguratorDeepIdle & gIOPCIFlags) 628 && (!provider->getProperty(kIOPCIHotPlugKey)) 629 && (!provider->getProperty(kIOPCITunnelLinkChangeKey)) 630 && !(getChildEntry(gIOServicePlane))) 631 { 632 DLOG("%s: no child D3\n", provider->getName()); 633 634 if (pciDevice 635 && pciDevice->hasPCIPowerManagement(kPCIPMCPMESupportFromD3Hot)) 636 { 637 pciDevice->enablePCIPowerManagement(kPCIPMCSPowerStateD3); 638 } 639 powerOverrideOnPriv(); 640 changePowerStateToPriv(kIOPCIDeviceOffState); 641 changePowerStateTo(kIOPCIDeviceOffState); 642 } 643 644 registerService(); 645 646 return (true); 647} 648 649void IOPCIBridge::stop( IOService * provider ) 650{ 651 PMstop(); 652 super::stop( provider); 653} 654 655void IOPCIBridge::free( void ) 656{ 657 if (reserved) IODelete(reserved, ExpansionData, 1); 658 659 super::free(); 660} 661 662IOReturn IOPCIBridge::setDeviceASPMBits(IOPCIDevice * device, uint32_t bits) 663{ 664 if (!device->reserved->expressCapability) return (kIOReturnUnsupported); 665 666 uint16_t control; 667 control = device->configRead16(device->reserved->expressCapability + 0x10); 668 control &= ~(kIOPCIExpressASPML0s | kIOPCIExpressASPML1); 669 control |= bits; 670 device->configWrite16(device->reserved->expressCapability + 0x10, control); 671 672 return (kIOReturnSuccess); 673} 674 675IOReturn IOPCIBridge::setDeviceL1PMBits(IOPCIDevice * device, uint32_t bits) 676{ 677 OSData * data; 678 679 if (!device->reserved->l1pmCapability) return (kIOReturnUnsupported); 680 681 if (bits 682 && (data = OSDynamicCast(OSData, device->getProperty(kIOPCIExpressL1PMControlKey))) 683 && (data->getLength() >= 2*sizeof(uint32_t))) 684 { 685 uint32_t * l1bits = (typeof(l1bits)) data->getBytesNoCopy(); 686 device->configWrite32(device->reserved->l1pmCapability + 0x0C, l1bits[1]); 687 device->configWrite32(device->reserved->l1pmCapability + 0x08, l1bits[0] & bits); 688 } 689 else 690 { 691 device->configWrite32(device->reserved->l1pmCapability + 0x08, 0); 692 device->configWrite32(device->reserved->l1pmCapability + 0x0C, 0); 693 } 694 695 return (kIOReturnSuccess); 696} 697 698IOReturn IOPCIBridge::setDeviceASPMState(IOPCIDevice * device, 699 IOService * client, IOOptionBits state) 700{ 701 IOOptionBits aspmBits, l1pmBits; 702 703 if (state) 704 { 705 aspmBits = (device->reserved->aspmCaps & state); 706 l1pmBits = (device->reserved->l1pmCaps); 707 } 708 else 709 { 710 aspmBits = l1pmBits = 0; 711 } 712 713 setDeviceL1PMBits(device, l1pmBits); 714 setDeviceASPMBits(device, aspmBits); 715 716 return (kIOReturnSuccess); 717} 718 719IOReturn IOPCI2PCIBridge::setDeviceASPMState(IOPCIDevice * device, 720 IOService * client, IOOptionBits state) 721{ 722 uint32_t aspmBits, l1pmBits; 723 724 // Need to enable upstream first then downstream, reverse for disable 725 if (state) 726 { 727 l1pmBits = (fBridgeDevice->reserved->l1pmCaps & device->reserved->l1pmCaps); 728 setDeviceL1PMBits(fBridgeDevice, l1pmBits); 729 setDeviceL1PMBits(device, l1pmBits); 730 731 // L1 and L0s need to be supported on both ends to enable 732 aspmBits = (state 733 & fBridgeDevice->reserved->aspmCaps 734 & device->reserved->aspmCaps 735 & (kIOPCIExpressASPML0s | kIOPCIExpressASPML1)); 736 737 setDeviceASPMBits(fBridgeDevice, aspmBits); 738 setDeviceASPMBits(device, aspmBits); 739 } 740 else 741 { 742 aspmBits = l1pmBits = 0; 743 setDeviceL1PMBits(device, l1pmBits); 744 setDeviceL1PMBits(fBridgeDevice, l1pmBits); 745 setDeviceASPMBits(device, aspmBits); 746 setDeviceASPMBits(fBridgeDevice, aspmBits); 747 } 748 749 return (kIOReturnSuccess); 750} 751 752IOReturn IOPCIBridge::enableLTR(IOPCIDevice * device, bool enable) 753{ 754 return (kIOReturnSuccess); 755} 756 757IOReturn IOPCI2PCIBridge::enableLTR(IOPCIDevice * device, bool enable) 758{ 759 IOReturn status; 760 761 status = fBridgeDevice->enableLTR(device, enable); 762 if (status != kIOReturnSuccess) return status; 763 return (device->enableLTR(device, enable)); 764} 765 766IOReturn 767IOPCI2PCIBridge::setTunnelL1Enable(IOPCIDevice * device, IOService * client, bool l1Enable) 768{ 769 IOReturn ret; 770 IOPCIConfigShadow * shadow; 771 bool was, now; 772 int32_t incr; 773 774 if (l1Enable == device->reserved->tunnelL1Allow) return (kIOReturnSuccess); 775 776 shadow = configShadow(device); 777 778 DLOG("setTunnelL1Enable(0x%llx) %d->%d\n", 779 device->getRegistryEntryID(), device->reserved->tunnelL1Allow, l1Enable); 780 781 if (!shadow->tunnelRoot) return (kIOReturnUnsupported); 782 783 if ((client != device) 784 && !device->isChild(client, gIOServicePlane)) return (kIOReturnNotAttached); 785 786 device->setProperty(gIOPCITunnelL1EnableKey, l1Enable ? kOSBooleanTrue : kOSBooleanFalse); 787 788 IOLockLock(gIOPCIWakeReasonLock); 789 incr = l1Enable; 790 incr -= (kTunnelL1Disable != device->reserved->tunnelL1Allow); 791 device->reserved->tunnelL1Allow = l1Enable; 792 was = (fTunnelL1EnableCount >= 0); 793 fTunnelL1EnableCount += incr; 794 now = (fTunnelL1EnableCount >= 0); 795 IOLockUnlock(gIOPCIWakeReasonLock); 796 797 if (was == now) ret = kIOReturnSuccess; 798 else 799 { 800 if (device == shadow->tunnelRoot) 801 { 802 IOOptionBits state = 0; 803 if (now) state |= kIOPCIExpressASPML1; 804 DLOG("set tunnel ASPM %s -> %d\n", device->getName(), state); 805 ret = device->setASPMState(this, state); 806 } 807 else 808 { 809 ret = fBridgeDevice->setTunnelL1Enable(this, now); 810 } 811 } 812 813 return (ret); 814} 815 816IOReturn IOPCIBridge::setDevicePowerState(IOPCIDevice * device, IOOptionBits options, 817 unsigned long prevState, unsigned long newState) 818{ 819 bool noSave; 820 821 noSave = ((kIOPCIConfigShadowVolatile & options) 822 && (kOSBooleanFalse == device->getProperty(kIOPMPCIConfigSpaceVolatileKey))); 823 824 DLOG("%s[%p]::setDevicePowerState(%ld, %ld, %d)\n", device->getName(), device, prevState, newState, noSave); 825 826 if (newState == prevState) return (kIOReturnSuccess); 827 828 switch (newState) 829 { 830 case kIOPCIDeviceOffState: 831 if (noSave) break; 832 saveDeviceState(device, options); 833 if (kOSBooleanTrue == device->getProperty(kIOPolledInterfaceActiveKey)) 834 { 835 newState = kIOPCIDeviceOnState; 836 } 837 else if (kIOPCIConfiguratorDeepIdle & gIOPCIFlags) 838 { 839 newState = kIOPCIDeviceDozeState; 840 } 841 device->setPCIPowerState(newState, 0); 842 break; 843 844 case kIOPCIDeviceDozeState: 845 if (noSave) break; 846 saveDeviceState(device, options); 847 device->setPCIPowerState(newState, 0); 848 break; 849 850 case kIOPCIDeviceOnState: 851 configOp(device, kConfigOpUnpaused, 0); 852 if (noSave) break; 853 if (kIOPCIDevicePausedState != prevState) 854 { 855 if ((kIOPCIDeviceOffState == prevState) 856 && ((kIOPCIClassGraphics == (device->savedConfig[kIOPCIConfigRevisionID >> 2] >> 24)) 857 || (kIOPCIClassMultimedia == (device->savedConfig[kIOPCIConfigRevisionID >> 2] >> 24)))) 858 { 859 tunnelsWait(device); 860 } 861 } 862 device->setPCIPowerState(newState, 0); 863 if (kIOPCIDevicePausedState == prevState) break; 864 restoreDeviceState(device, options); 865 break; 866 867 case kIOPCIDevicePausedState: 868 IOLog("pci pause: %s\n", device->getName()); 869 configOp(device, kConfigOpPaused, 0); 870 if (noSave) break; 871 device->setPCIPowerState(newState, 0); 872 restoreDeviceState(device, options); 873 break; 874 } 875 876 return (kIOReturnSuccess); 877} 878 879IOReturn IOPCIBridge::setDevicePowerState( IOPCIDevice * device, 880 unsigned long whatToDo ) 881{ 882 // Special for pci/pci-bridge devices - 883 // kSaveBridgeState(2) to save immediately, kRestoreBridgeState(3) to restore immediately 884 885 if (kRestoreBridgeState == whatToDo) 886 { 887 if (kSaveBridgeState == gIOAllPCI2PCIBridgeState) 888 { 889 restoreMachineState(kMachineRestoreBridges, 0); 890 restoreMachineState(kMachineRestoreEarlyDevices, 0); 891 } 892 gIOAllPCI2PCIBridgeState = kRestoreBridgeState; 893 gIOPCITunnelWait = gIOPCITunnelSleep; 894 } 895 else if (kSaveBridgeState == whatToDo) 896 { 897 gIOAllPCI2PCIBridgeState = whatToDo; 898 gIOPCIWakeCount++; 899 } 900 else panic("setDevicePowerState"); 901 902 return (kIOReturnSuccess); 903} 904 905static void IOPCILogDevice(const char * log, IOPCIDevice * device, bool dump) 906{ 907 int slen, len, pos; 908 char * string; 909 uint32_t offset, data = 0; 910 911 slen = 2048; 912 pos = 0; 913 string = IONew(char, slen); 914 if (!string) return; 915 len = 256; 916 pos = snprintf(string, slen - pos, "%s : ints(%d) ", log, ml_get_interrupts_enabled()); 917 if (device->getPath(string + pos, &len, gIOServicePlane)) pos += len; 918 if (dump) 919 { 920 pos += snprintf(string + pos, slen - pos, "\n 0 1 2 3 4 5 6 7 8 9 A B C D E F"); 921 for (offset = 0; offset < 256; offset++) 922 { 923 if (0 == (offset & 3)) data = device->configRead32(offset); 924 if (0 == (offset & 15)) pos += snprintf(string + pos, slen - pos, "\n %02X:", offset); 925 pos += snprintf(string + pos, slen - pos, " %02x", data & 0xff); 926 data >>= 8; 927 } 928 } 929 pos += snprintf(string + pos, slen - pos, "\n"); 930 DLOG(string); 931 IODelete(string, char, slen); 932} 933 934IOReturn IOPCIBridge::saveDeviceState( IOPCIDevice * device, 935 IOOptionBits options ) 936{ 937 IOPCIConfigShadow * shadow; 938 IOReturn ret; 939 UInt32 flags; 940 uint32_t data; 941 int i; 942 bool ok; 943 uint64_t time; 944 945 if (!device->savedConfig) return (kIOReturnNotReady); 946 947 shadow = configShadow(device); 948 flags = shadow->flags; 949 950 if (kIOPCIConfigShadowValid & flags) return (kIOReturnSuccess); 951 952 DLOG("%s::saveDeviceState(0x%x)\n", device->getName(), options); 953 954 flags |= kIOPCIConfigShadowValid | options; 955 shadow->flags = flags; 956 shadow->restoreCount = 0; 957 958 if (device->getProperty(gIOPCITunnelledKey)) 959 { 960 shadow->tunnelID = device->copyProperty(gIOPCITunnelIDKey, gIOServicePlane); 961 } 962 963 if (shadow->handler) 964 { 965 time = mach_absolute_time(); 966 (*shadow->handler)(shadow->handlerRef, kIOMessageDeviceWillPowerOff, device, 3); 967 time = mach_absolute_time() - time; 968 absolutetime_to_nanoseconds(time, &time); 969 DLOG("%s::configHandler(kIOMessageDeviceWillPowerOff) %lld ms\n", device->getName(), time / 1000000ULL); 970 } 971 972 if (kIOPCIConfiguratorLogSaveRestore & gIOPCIFlags) 973 IOPCILogDevice("save device", device, true); 974 else if ((kIOPCIConfiguratorIOLog | kIOPCIConfiguratorKPrintf) & gIOPCIFlags) 975 IOPCILogDevice("save device", device, false); 976 977 if (kIOPCIConfigShadowHostBridge & flags) {} 978 else 979 { 980 uint32_t regCount = kIOPCIConfigEPShadowRegs; 981 if (shadow->bridge) 982 { 983 regCount = kIOPCIConfigBridgeShadowRegs; 984 shadow->bridge->saveBridgeState(); 985 } 986 for (i = 0; i < regCount; i++) 987 { 988 if (kIOPCISaveRegsMask & (1 << i)) device->savedConfig[i] = device->configRead32(i * 4); 989 } 990 } 991 992 if (device->reserved->l1pmCapability) 993 { 994 shadow->savedL1PM0 995 = device->configRead32(device->reserved->l1pmCapability + 0x08); 996 shadow->savedL1PM1 997 = device->configRead32(device->reserved->l1pmCapability + 0x0C); 998 if (kIOPCIConfigShadowWakeL1PMDisable & shadow->flags) shadow->savedL1PM0 &= ~(0xF); 999 } 1000 1001 if (device->reserved->latencyToleranceCapability) 1002 { 1003 shadow->savedLTR 1004 = device->configRead32(device->reserved->latencyToleranceCapability + 0x04); 1005 } 1006 1007 if (device->reserved->aerCapability) 1008 { 1009 shadow->savedAERCapsControl 1010 = device->configRead32(device->reserved->aerCapability + 0x18); 1011 shadow->savedAERSeverity 1012 = device->configRead32(device->reserved->aerCapability + 0x0C); 1013 shadow->savedAERUMask 1014 = device->configRead32(device->reserved->aerCapability + 0x08); 1015 shadow->savedAERCMask 1016 = device->configRead32(device->reserved->aerCapability + 0x14); 1017 if (device->reserved->rootPort) shadow->savedAERRootCommand 1018 = device->configRead32(device->reserved->aerCapability + 0x30); 1019 } 1020 1021 if (device->reserved->expressCapability) 1022 { 1023 shadow->savedDeviceControl 1024 = device->configRead16( device->reserved->expressCapability + 0x08 ); 1025 shadow->savedLinkControl 1026 = device->configRead16( device->reserved->expressCapability + 0x10 ); 1027 if ((kIOPCIConfigShadowBridgeInterrupts & shadow->flags) 1028 || (0x100 & device->reserved->expressCapabilities)) 1029 { 1030 shadow->savedSlotControl 1031 = device->configRead16( device->reserved->expressCapability + 0x18 ); 1032 } 1033 if (expressV2(device)) 1034 { 1035 shadow->savedDeviceControl2 1036 = device->configRead16( device->reserved->expressCapability + 0x28 ); 1037 shadow->savedLinkControl2 1038 = device->configRead16( device->reserved->expressCapability + 0x30 ); 1039 shadow->savedSlotControl2 1040 = device->configRead16( device->reserved->expressCapability + 0x38 ); 1041 } 1042 if (kIOPCIConfigShadowSleepLinkDisable & shadow->flags) 1043 { 1044 device->configWrite16(device->reserved->expressCapability + 0x10, 1045 (1 << 4) | shadow->savedLinkControl); 1046 } 1047 if (kIOPCIConfigShadowSleepReset & shadow->flags) 1048 { 1049 UInt16 bridgeControl; 1050 bridgeControl = device->configRead16(kPCI2PCIBridgeControl); 1051 device->configWrite16(kPCI2PCIBridgeControl, bridgeControl | 0x40); 1052 IOSleep(10); 1053 device->configWrite16(kPCI2PCIBridgeControl, bridgeControl); 1054 } 1055 if (kIOPCIConfigShadowWakeL1PMDisable & shadow->flags) shadow->savedLinkControl &= ~(0x100); 1056 } 1057 1058 IOPCIMessagedInterruptController::saveDeviceState(device, shadow); 1059 1060 if (shadow->handler) 1061 { 1062 time = mach_absolute_time(); 1063 (*shadow->handler)(shadow->handlerRef, kIOMessageDeviceHasPoweredOff, device, 3); 1064 time = mach_absolute_time() - time; 1065 absolutetime_to_nanoseconds(time, &time); 1066 DLOG("%s::configHandler(kIOMessageDeviceHasPoweredOff) %lld ms\n", device->getName(), time / 1000000ULL); 1067 } 1068 1069 if (kIOPCIConfigShadowHotplug & shadow->flags) 1070 { 1071 data = device->configRead32(kIOPCIConfigVendorID); 1072#ifdef DEADTEST 1073 if (!strcmp(DEADTEST, device->getName())) data = 0xFFFFFFFF; 1074#endif 1075 ok = (data && (data != 0xFFFFFFFF)); 1076 if (!ok) 1077 { 1078 DLOG("saveDeviceState kill device %s\n", device->getName()); 1079 ret = configOp(device, kConfigOpKill, 0); 1080 shadow->flags &= ~kIOPCIConfigShadowValid; 1081 } 1082 } 1083 1084 if (kIOPCIConfigShadowValid & shadow->flags) 1085 { 1086 configOp(device, kConfigOpShadowed, &shadow->savedConfig[0]); 1087 restoreQEnter(device); 1088 } 1089 1090 return (kIOReturnSuccess); 1091} 1092 1093IOReturn IOPCIBridge::_restoreDeviceState(IOPCIDevice * device, IOOptionBits options) 1094{ 1095 AbsoluteTime deadline, start, now = 0; 1096 IOPCIConfigShadow * shadow; 1097 uint32_t retries; 1098 uint32_t data; 1099 bool ok; 1100 UInt32 flags; 1101 int i; 1102 uint64_t time; 1103 IOReturn ret; 1104 1105 shadow = configShadow(device); 1106 flags = shadow->flags; 1107 1108 if (!(kIOPCIConfigShadowValid & flags)) return (kIOReturnNoResources); 1109 if (shadow->restoreCount == gIOPCIWakeCount) return (kIOReturnNoResources); 1110 shadow->restoreCount = gIOPCIWakeCount; 1111 1112 if (shadow->handler) 1113 { 1114 time = mach_absolute_time(); 1115 ret = (*shadow->handler)(configShadow(device)->handlerRef, 1116 kIOMessageDeviceWillPowerOn, device, 3); 1117 if ((kIOPCIRestoreDeviceStateEarly & options) && (kIOReturnNotReady == ret)) return (ret); 1118 time = mach_absolute_time() - time; 1119 absolutetime_to_nanoseconds(time, &time); 1120 DLOG("%s::configHandler(kIOMessageDeviceWillPowerOn) %lld ms\n", device->getName(), time / 1000000ULL); 1121 } 1122 1123 if (!device->reserved->dead) 1124 { 1125 if (kIOReturnSuccess != device->parent->checkLink(kCheckLinkParents)) 1126 { 1127 DLOG("%s: pci restore no link\n", device->getName()); 1128 device->reserved->dead = true; 1129 } 1130 } 1131 1132 if ((!device->reserved->dead) && !(kIOPCIConfigShadowBridgeDriver & flags)) 1133 { 1134 retries = 0; 1135 clock_get_uptime(&start); 1136 clock_interval_to_deadline(200, kMillisecondScale, &deadline); 1137 do 1138 { 1139 if (retries) IOSleep(2); 1140 data = device->configRead32(kIOPCIConfigVendorID); 1141 ok = (data && (data != 0xFFFFFFFF)); 1142 if (ok) break; 1143 retries++; 1144 clock_get_uptime(&now); 1145 } 1146 while (AbsoluteTime_to_scalar(&now) < AbsoluteTime_to_scalar(&deadline)); 1147 1148 if (retries) 1149 { 1150 absolutetime_to_nanoseconds(now - start, &now); 1151 DLOG("%s: pci restore waited for %qd ms %s\n", 1152 device->getName(), now / 1000000ULL, ok ? "ok" : "fail"); 1153 } 1154 if (data != device->savedConfig[kIOPCIConfigVendorID >> 2]) 1155 { 1156 DLOG("%s: pci restore invalid deviceid 0x%08lx\n", device->getName(), data); 1157 device->reserved->dead = true; 1158#if !ACPI_SUPPORT 1159 if (data && (data != 0xFFFFFFFF)) panic("%s: pci restore invalid deviceid 0x%08lx\n", device->getName(), data); 1160#endif 1161 } 1162 } 1163 1164 if (!device->reserved->dead) 1165 { 1166 if (kIOPCIConfiguratorLogSaveRestore & gIOPCIFlags) 1167 IOPCILogDevice("before restore", device, true); 1168 else if ((kIOPCIConfiguratorIOLog | kIOPCIConfiguratorKPrintf) & gIOPCIFlags) 1169 IOPCILogDevice("restore device", device, false); 1170 1171 if (kIOPCIConfigShadowHostBridge & flags) {} 1172 else 1173 { 1174 uint32_t regCount = kIOPCIConfigEPShadowRegs; 1175 if (shadow->bridge) 1176 { 1177 regCount = kIOPCIConfigBridgeShadowRegs; 1178 shadow->bridge->restoreBridgeState(); 1179 } 1180 for (i = (kIOPCIConfigRevisionID >> 2); i < regCount; i++) 1181 { 1182 if (kIOPCISaveRegsMask & (1 << i)) 1183 device->configWrite32( i * 4, device->savedConfig[ i ]); 1184 } 1185 device->configWrite32(kIOPCIConfigCommand, device->savedConfig[1]); 1186 } 1187 1188 if (device->reserved->l1pmCapability) 1189 { 1190 device->configWrite32(device->reserved->l1pmCapability + 0x0C, 1191 shadow->savedL1PM1); 1192 device->configWrite32(device->reserved->l1pmCapability + 0x08, 1193 shadow->savedL1PM0); 1194 } 1195 1196 if (device->reserved->latencyToleranceCapability) 1197 { 1198 device->configWrite32(device->reserved->latencyToleranceCapability + 0x04, 1199 shadow->savedLTR); 1200 } 1201 1202 if (device->reserved->aerCapability) 1203 { 1204 device->configWrite32(device->reserved->aerCapability + 0x18, 1205 shadow->savedAERCapsControl); 1206 device->configWrite32(device->reserved->aerCapability + 0x0C, 1207 shadow->savedAERSeverity); 1208 device->configWrite32(device->reserved->aerCapability + 0x08, 1209 shadow->savedAERUMask); 1210 device->configWrite32(device->reserved->aerCapability + 0x14, 1211 shadow->savedAERCMask); 1212 if (device->reserved->rootPort) 1213 { 1214 device->configWrite32(device->reserved->aerCapability + 0x30, 0xFF); 1215 device->configWrite32(device->reserved->aerCapability + 0x2c, 1216 shadow->savedAERRootCommand); 1217 } 1218 } 1219 1220 if (device->reserved->expressCapability) 1221 { 1222 device->configWrite16(device->reserved->expressCapability + 0x08, 1223 shadow->savedDeviceControl); 1224 1225 if (expressV2(device)) 1226 { 1227 device->configWrite16(device->reserved->expressCapability + 0x28, 1228 shadow->savedDeviceControl2); 1229 } 1230 device->configWrite16(device->reserved->expressCapability + 0x10, 1231 shadow->savedLinkControl); 1232 if ((kIOPCIConfigShadowBridgeInterrupts & configShadow(device)->flags) 1233 || (0x100 & device->reserved->expressCapabilities)) 1234 { 1235 device->configWrite16(device->reserved->expressCapability + 0x18, 1236 shadow->savedSlotControl); 1237 } 1238 if (expressV2(device)) 1239 { 1240 device->configWrite16(device->reserved->expressCapability + 0x30, 1241 shadow->savedLinkControl2); 1242 device->configWrite16(device->reserved->expressCapability + 0x38, 1243 shadow->savedSlotControl2); 1244 } 1245 } 1246 1247 IOPCIMessagedInterruptController::restoreDeviceState(device, shadow); 1248 1249 if (kIOPCIConfiguratorLogSaveRestore & gIOPCIFlags) 1250 IOPCILogDevice("after restore", device, true); 1251 1252 if (configShadow(device)->handler) 1253 { 1254 time = mach_absolute_time(); 1255 (*configShadow(device)->handler)(configShadow(device)->handlerRef, 1256 kIOMessageDeviceHasPoweredOn, device, 3); 1257 time = mach_absolute_time() - time; 1258 absolutetime_to_nanoseconds(time, &time); 1259 DLOG("%s::configHandler(kIOMessageDeviceHasPoweredOn) %lld ms\n", device->getName(), time / 1000000ULL); 1260 } 1261 } 1262 1263 configOp(device, kConfigOpShadowed, NULL); 1264 1265 return (kIOReturnSuccess); 1266} 1267 1268void IOPCIBridge::restoreQEnter(IOPCIDevice * device) 1269{ 1270 queue_head_t * que = NULL; 1271 IOPCIConfigShadow * shadow; 1272 1273 shadow = configShadow(device); 1274 if (shadow->tunnelRoot) 1275 { 1276 DLOG("queued %s on %s\n", device->getName(), shadow->tunnelRoot->getName()); 1277 que = &configShadow(shadow->tunnelRoot)->dependents; 1278 if (device == shadow->tunnelRoot) 1279 { 1280 IOLockLock(gIOPCIWakeReasonLock); 1281 gIOPCITunnelSleep++; 1282 IOLockUnlock(gIOPCIWakeReasonLock); 1283 } 1284 } 1285 else 1286 { 1287 que = &gIOAllPCIDeviceRestoreQ; 1288 } 1289 1290 IOSimpleLockLock(gIOAllPCI2PCIBridgesLock); 1291 queue_enter_first(que, 1292 shadow, 1293 IOPCIConfigShadow *, 1294 link ); 1295 IOSimpleLockUnlock(gIOAllPCI2PCIBridgesLock); 1296} 1297 1298void IOPCIBridge::restoreQRemove(IOPCIDevice * device) 1299{ 1300 queue_head_t * que = NULL; 1301 IOPCIConfigShadow * shadow; 1302 1303 shadow = configShadow(device); 1304 1305 if (!configShadow(device)->link.next) return; 1306 1307 if (shadow->tunnelRoot) 1308 { 1309 que = &configShadow(shadow->tunnelRoot)->dependents; 1310 } 1311 else 1312 { 1313 que = &gIOAllPCIDeviceRestoreQ; 1314 } 1315 1316 IOSimpleLockLock(gIOAllPCI2PCIBridgesLock); 1317 queue_remove(que, 1318 shadow, 1319 IOPCIConfigShadow *, 1320 link ); 1321 IOSimpleLockUnlock(gIOAllPCI2PCIBridgesLock); 1322} 1323 1324void IOPCIBridge::tunnelsWait(IOPCIDevice * device) 1325{ 1326 IOLockLock(gIOPCIWakeReasonLock); 1327 DLOG("%s: tunnel stall(%d, %d)\n", device->getName(), gIOPCITunnelWait, gIOPCITunnelSleep); 1328 if (gIOPCITunnelWait) 1329 { 1330 IOLockSleep(gIOPCIWakeReasonLock, &gIOPCITunnelWait, THREAD_UNINT); 1331 DLOG("%s: tunnels done\n", device->getName()); 1332 } 1333 IOLockUnlock(gIOPCIWakeReasonLock); 1334} 1335 1336IOReturn IOPCIBridge::restoreTunnelState(IOPCIDevice * rootDevice, IOOptionBits options) 1337{ 1338 IOReturn ret; 1339 IOPCIConfigShadow * root; 1340 IOPCIConfigShadow * shadow; 1341 IOPCIConfigShadow * next; 1342 1343 DLOG("restoreTunnelState(%s, %d)\n", rootDevice->getName(), options); 1344 root = configShadow(rootDevice); 1345 IOSimpleLockLock(gIOAllPCI2PCIBridgesLock); 1346 1347 next = (IOPCIConfigShadow *) queue_first(&root->dependents); 1348 while (!queue_end(&root->dependents, (queue_entry_t) next)) 1349 { 1350 shadow = next; 1351 next = (IOPCIConfigShadow *) queue_next(&shadow->link); 1352 1353 if (kMachineRestoreBridges & options) 1354 { 1355 if (!(kIOPCIConfigShadowBridge & shadow->flags)) continue; 1356 } 1357 1358 if (!(kMachineRestoreTunnels & options)) 1359 { 1360 if (shadow->tunnelID) continue; 1361 } 1362 1363 IOSimpleLockUnlock(gIOAllPCI2PCIBridgesLock); 1364 1365 if (kIOPCIConfigShadowVolatile & shadow->flags) 1366 { 1367 shadow->device->setPCIPowerState(kIOPCIDeviceOnState, options); 1368 1369 ret = _restoreDeviceState(shadow->device, kIOPCIRestoreDeviceStateEarly); 1370 if (kIOReturnNotReady == ret) 1371 { 1372 ret = _restoreDeviceState(shadow->device, 0); 1373 } 1374 } 1375 if (shadow->tunnelID) 1376 { 1377 shadow->tunnelID->release(); 1378 shadow->tunnelID = 0; 1379 } 1380 1381 IOSimpleLockLock(gIOAllPCI2PCIBridgesLock); 1382 1383 next = (IOPCIConfigShadow *) queue_next(&shadow->link); 1384 queue_remove(&root->dependents, 1385 shadow, 1386 IOPCIConfigShadow *, 1387 link); 1388 shadow->link.next = shadow->link.prev = NULL; 1389 } 1390 1391 1392 IOSimpleLockUnlock(gIOAllPCI2PCIBridgesLock); 1393 1394 return (kIOReturnSuccess); 1395} 1396 1397IOReturn IOPCIBridge::restoreMachineState(IOOptionBits options, IOPCIDevice * device) 1398{ 1399 IOReturn ret; 1400 IOPCIConfigShadow * shadow; 1401 IOPCIConfigShadow * next; 1402 1403 DLOG("restoreMachineState(%d)\n", options); 1404 1405 IOSimpleLockLock(gIOAllPCI2PCIBridgesLock); 1406 1407 next = (IOPCIConfigShadow *) queue_first(&gIOAllPCIDeviceRestoreQ); 1408 while (!queue_end(&gIOAllPCIDeviceRestoreQ, (queue_entry_t) next)) 1409 { 1410 shadow = next; 1411 next = (IOPCIConfigShadow *) queue_next(&shadow->link); 1412 1413 if (shadow->tunnelRoot || shadow->tunnelID) panic("tunnel"); 1414 1415 if (shadow->device != device) 1416 { 1417 if (kMachineRestoreBridges & options) 1418 { 1419 if (!(kIOPCIConfigShadowBridge & shadow->flags)) continue; 1420 } 1421 1422 if (!(kIOPCIConfigShadowVolatile & shadow->flags)) continue; 1423#if ACPI_SUPPORT 1424 if (!(kMachineRestoreDehibernate & options) 1425 // skip any slow PS methods 1426 && (shadow->device->reserved->psMethods[0] >= 0) 1427 // except for nvidia bus zero devices 1428 && (shadow->device->space.s.busNum 1429 || (0x10de != (shadow->savedConfig[kIOPCIConfigVendorID >> 2] & 0xffff)))) 1430 continue; 1431#endif 1432 if (kMachineRestoreEarlyDevices & options) 1433 { 1434 if (shadow->device->space.s.busNum) continue; 1435 if (shadow->handler) continue; 1436 if (shadow->device->reserved->pmSleepEnabled) continue; 1437 } 1438 } 1439 1440 IOSimpleLockUnlock(gIOAllPCI2PCIBridgesLock); 1441 1442 shadow->device->setPCIPowerState(kIOPCIDeviceOnState, options); 1443 1444 ret = _restoreDeviceState(shadow->device, kIOPCIRestoreDeviceStateEarly); 1445 1446 IOSimpleLockLock(gIOAllPCI2PCIBridgesLock); 1447 1448 next = (IOPCIConfigShadow *) queue_next(&shadow->link); 1449 queue_remove(&gIOAllPCIDeviceRestoreQ, 1450 shadow, 1451 IOPCIConfigShadow *, 1452 link); 1453 shadow->link.next = shadow->link.prev = NULL; 1454 } 1455 1456 IOSimpleLockUnlock(gIOAllPCI2PCIBridgesLock); 1457 1458 return (kIOReturnSuccess); 1459} 1460 1461IOReturn IOPCIBridge::restoreDeviceState( IOPCIDevice * device, IOOptionBits options ) 1462{ 1463 IOReturn ret = kIOReturnNotFound; 1464 1465 if (!device->savedConfig) 1466 return (kIOReturnNotReady); 1467 1468 if (kSaveBridgeState == gIOAllPCI2PCIBridgeState) 1469 { 1470 ret = restoreMachineState(kMachineRestoreDehibernate | kMachineRestoreBridges, device); 1471 } 1472 1473 if (kIOReturnSuccess != ret) 1474 { 1475 if (!queue_empty(&configShadow(device)->dependents)) 1476 { 1477 ret = restoreTunnelState(device, kMachineRestoreBridges); 1478 ret = restoreTunnelState(device, 0); 1479 ret = restoreTunnelState(device, kMachineRestoreTunnels); 1480 if (!queue_empty(&configShadow(device)->dependents)) panic("tunnelq"); 1481 1482 IOLockLock(gIOPCIWakeReasonLock); 1483 gIOPCITunnelSleep--; 1484 if (gIOPCITunnelWait && !--gIOPCITunnelWait) 1485 { 1486 IOLockWakeup(gIOPCIWakeReasonLock, &gIOPCITunnelWait, false); 1487 } 1488 IOLockUnlock(gIOPCIWakeReasonLock); 1489 } 1490 else 1491 { 1492 restoreQRemove(device); 1493 ret = _restoreDeviceState(device, 0); 1494 } 1495 } 1496 1497 configShadow(device)->flags &= ~kIOPCIConfigShadowValid; 1498 1499 // callers expect success 1500 return (kIOReturnSuccess); 1501} 1502 1503IOReturn 1504IOPCIBridge::callPlatformFunction(const OSSymbol * functionName, 1505 bool waitForFunction, 1506 void * p1, void * p2, 1507 void * p3, void * p4) 1508{ 1509 IOReturn result; 1510 1511 result = super::callPlatformFunction(functionName, waitForFunction, 1512 p1, p2, p3, p4); 1513 1514#if 0 1515 if ((kIOReturnUnsupported == result) 1516 && (gIOPlatformDeviceASPMEnableKey == functionName) 1517 && getProperty(kIOPCIDeviceASPMSupportedKey)) 1518 { 1519 result = parent->setDeviceASPMState(this, (IOService *) p1, (IOOptionBits)(uintptr_t) p2); 1520 } 1521#endif 1522 if ((kIOReturnUnsupported == result) 1523 && (gIOPlatformGetMessagedInterruptControllerKey == functionName)) 1524 { 1525 *(IOPCIMessagedInterruptController **)p2 = 1526 gIOPCIMessagedInterruptController; 1527 } 1528 1529 return (result); 1530} 1531 1532/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1533 1534bool IOPCIBridge::configure( IOService * provider ) 1535{ 1536 return (true); 1537} 1538 1539#if !defined(__LP64__) || defined(__x86_64__) 1540SInt32 IOPCIBridge::compareAddressCell( UInt32 /* cellCount */, UInt32 cleft[], UInt32 cright[] ) 1541{ 1542 IOPCIPhysicalAddress * left = (IOPCIPhysicalAddress *) cleft; 1543 IOPCIPhysicalAddress * right = (IOPCIPhysicalAddress *) cright; 1544 static const UInt8 spacesEq[] = { 0, 1, 2, 2 }; 1545 if (spacesEq[ left->physHi.s.space ] != spacesEq[ right->physHi.s.space ]) 1546 return (-1); 1547 1548 return (left->physLo - right->physLo); 1549} 1550#else 1551SInt64 IOPCIBridge::compareAddressCell( UInt32 /* cellCount */, UInt32 cleft[], UInt32 cright[] ) 1552{ 1553 IOPCIPhysicalAddress * left = (IOPCIPhysicalAddress *) cleft; 1554 IOPCIPhysicalAddress * right = (IOPCIPhysicalAddress *) cright; 1555 static const UInt8 spacesEq[] = { 0, 1, 2, 2 }; 1556 1557 if (spacesEq[ left->physHi.s.space ] != spacesEq[ right->physHi.s.space ]) 1558 return (-1); 1559 1560 return IOPhysical32(left->physMid, left->physLo) - IOPhysical32(right->physMid, right->physLo); 1561} 1562#endif 1563 1564void IOPCIBridge::nvLocation( IORegistryEntry * entry, 1565 UInt8 * busNum, UInt8 * deviceNum, UInt8 * functionNum ) 1566{ 1567 IOPCIDevice * nub; 1568 1569 nub = OSDynamicCast( IOPCIDevice, entry ); 1570 assert( nub ); 1571 1572 *busNum = nub->space.s.busNum; 1573 *deviceNum = nub->space.s.deviceNum; 1574 *functionNum = nub->space.s.functionNum; 1575} 1576 1577void IOPCIBridge::spaceFromProperties( OSDictionary * propTable, 1578 IOPCIAddressSpace * space ) 1579{ 1580 OSData * regProp; 1581 IOPCIAddressSpace * inSpace; 1582 1583 space->bits = 0; 1584 1585 if ((regProp = (OSData *) propTable->getObject("reg"))) 1586 { 1587 inSpace = (IOPCIAddressSpace *) regProp->getBytesNoCopy(); 1588 space->s.busNum = inSpace->s.busNum; 1589 space->s.deviceNum = inSpace->s.deviceNum; 1590 space->s.functionNum = inSpace->s.functionNum; 1591 } 1592} 1593 1594void IOPCIBridge::spaceFromProperties( IORegistryEntry * regEntry, 1595 IOPCIAddressSpace * space ) 1596{ 1597 OSData * regProp; 1598 IOPCIAddressSpace * inSpace; 1599 1600 space->bits = 0; 1601 1602 if ((regProp = (OSData *) regEntry->copyProperty("reg"))) 1603 { 1604 inSpace = (IOPCIAddressSpace *) regProp->getBytesNoCopy(); 1605 space->s.busNum = inSpace->s.busNum; 1606 space->s.deviceNum = inSpace->s.deviceNum; 1607 space->s.functionNum = inSpace->s.functionNum; 1608 regProp->release(); 1609 } 1610} 1611 1612IORegistryEntry * IOPCIBridge::findMatching( OSIterator * kids, 1613 IOPCIAddressSpace space ) 1614{ 1615 IORegistryEntry * found = 0; 1616 IOPCIAddressSpace regSpace; 1617 1618 if (kids) 1619 { 1620 kids->reset(); 1621 while ((0 == found) 1622 && (found = (IORegistryEntry *) kids->getNextObject())) 1623 { 1624 spaceFromProperties(found, ®Space); 1625 if (space.bits != regSpace.bits) 1626 found = 0; 1627 } 1628 } 1629 return (found); 1630} 1631 1632bool IOPCIBridge::checkProperties( IOPCIDevice * entry ) 1633{ 1634 uint32_t vendor, product, classCode, revID; 1635 uint32_t subVendor = 0, subProduct = 0; 1636 IOByteCount offset; 1637 OSData * data; 1638 1639 if ((data = OSDynamicCast(OSData, entry->getProperty("vendor-id")))) 1640 vendor = *((uint32_t *) data->getBytesNoCopy()); 1641 else 1642 return (false); 1643 if ((data = OSDynamicCast(OSData, entry->getProperty("device-id")))) 1644 product = *((uint32_t *) data->getBytesNoCopy()); 1645 else 1646 return (false); 1647 if ((data = OSDynamicCast(OSData, entry->getProperty("class-code")))) 1648 classCode = *((uint32_t *) data->getBytesNoCopy()); 1649 else 1650 return (false); 1651 if ((data = OSDynamicCast(OSData, entry->getProperty("revision-id")))) 1652 revID = *((uint32_t *) data->getBytesNoCopy()); 1653 else 1654 return (false); 1655 if ((data = OSDynamicCast(OSData, entry->getProperty("subsystem-vendor-id")))) 1656 subVendor = *((uint32_t *) data->getBytesNoCopy()); 1657 if ((data = OSDynamicCast(OSData, entry->getProperty("subsystem-id")))) 1658 subProduct = *((uint32_t *) data->getBytesNoCopy()); 1659 1660 if (entry->savedConfig) 1661 { 1662 // update matching config space regs from properties 1663 entry->savedConfig[kIOPCIConfigVendorID >> 2] = (product << 16) | vendor; 1664 entry->savedConfig[kIOPCIConfigRevisionID >> 2] = (classCode << 8) | revID; 1665 if (subVendor && subProduct) 1666 entry->savedConfig[kIOPCIConfigSubSystemVendorID >> 2] = (subProduct << 16) | subVendor; 1667 } 1668 1669 if ((offset = entry->reserved->expressCapability)) 1670 { 1671 uint32_t value, expressCaps; 1672 1673 expressCaps = entry->configRead16(offset + 0x02); 1674 entry->setProperty(kIOPCIExpressCapabilitiesKey, expressCaps, 32); 1675 value = entry->configRead16(offset + 0x12); 1676 entry->setProperty(kIOPCIExpressLinkStatusKey, value, 32); 1677 value = entry->configRead32(offset + 0x0c); 1678 entry->setProperty(kIOPCIExpressLinkCapabilitiesKey, value, 32); 1679 if (0x100 & expressCaps) 1680 { 1681 value = entry->configRead16(offset + 0x1a); 1682 entry->setProperty(kIOPCIExpressSlotStatusKey, value, 32); 1683 value = entry->configRead32(offset + 0x14); 1684 entry->setProperty(kIOPCIExpressSlotCapabilitiesKey, value, 32); 1685 } 1686 } 1687 1688 return (true); 1689} 1690 1691#if VERSION_MAJOR < 13 1692static char * 1693strnstr(char *s, const char *find, size_t slen) 1694{ 1695 char c, sc; 1696 size_t len; 1697 1698 if ((c = *find++) != '\0') { 1699 len = strlen(find); 1700 do { 1701 do { 1702 if ((sc = *s++) == '\0' || slen-- < 1) 1703 return (NULL); 1704 } while (sc != c); 1705 if (len > slen) 1706 return (NULL); 1707 } while (strncmp(s, find, len) != 0); 1708 s--; 1709 } 1710 return (s); 1711} 1712#endif 1713 1714#ifndef kIOPMRootDomainWakeTypeNetwork 1715#define kIOPMRootDomainWakeTypeNetwork "Network" 1716#endif 1717 1718void IOPCIBridge::updateWakeReason(IOPCIDevice * device) 1719{ 1720 OSObject * obj; 1721 OSString * reasonProp; 1722 const char * reason; 1723 const char * propCStr; 1724 unsigned int len; 1725 char wakeBuffer[128]; 1726 1727 reason = device->getName(); 1728 IOLockLock(gIOPCIWakeReasonLock); 1729 do 1730 { 1731 obj = getPMRootDomain()->copyProperty(kIOPMRootDomainWakeReasonKey); 1732 reasonProp = OSDynamicCast(OSString, obj); 1733 if (reasonProp && (len = reasonProp->getLength())) 1734 { 1735 propCStr = reasonProp->getCStringNoCopy(); 1736 if (strnstr((char *) propCStr, reason, len + 1)) break; 1737 snprintf(wakeBuffer, sizeof(wakeBuffer), "%s %s", propCStr, reason); 1738 reason = wakeBuffer; 1739 } 1740 getPMRootDomain()->setProperty(kIOPMRootDomainWakeReasonKey, reason); 1741 if (obj) obj->release(); 1742 } 1743 while (false); 1744 1745 if ((kIOPCIClassNetwork == (device->savedConfig[kIOPCIConfigRevisionID >> 2] >> 24)) 1746 && (!getPMRootDomain()->getProperty(kIOPMRootDomainWakeTypeKey))) 1747 { 1748 getPMRootDomain()->setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeNetwork); 1749 } 1750 IOLockUnlock(gIOPCIWakeReasonLock); 1751} 1752 1753OSDictionary * IOPCIBridge::constructProperties( IOPCIAddressSpace space ) 1754{ 1755 return (0); 1756} 1757 1758IOPCIDevice * IOPCIBridge::createNub( OSDictionary * from ) 1759{ 1760 return (new IOPCIDevice); 1761} 1762 1763bool IOPCIBridge::initializeNub( IOPCIDevice * nub, 1764 OSDictionary * from ) 1765{ 1766 spaceFromProperties( from, &nub->space); 1767 nub->parent = this; 1768 1769 if (ioDeviceMemory()) 1770 nub->ioMap = ioDeviceMemory()->map(); 1771 1772 return (true); 1773} 1774 1775void IOPCIBridge::removeDevice( IOPCIDevice * device, IOOptionBits options ) 1776{ 1777 IOReturn ret = kIOReturnSuccess; 1778 1779#if USE_MSI 1780 if (device->reserved->msiCapability && reserved->messagedInterruptController) 1781 ret = reserved->messagedInterruptController->deallocateDeviceInterrupts(device); 1782#endif /* USE_MSI */ 1783 1784 getPlatform()->callPlatformFunction(gIOPlatformFreeDeviceResourcesKey, 1785 /* waitForFunction */ false, 1786 /* nub */ device, NULL, NULL, NULL); 1787 restoreQRemove(device); 1788 configOp(device, kConfigOpTerminated, 0); 1789} 1790 1791bool IOPCIBridge::publishNub( IOPCIDevice * nub, UInt32 /* index */ ) 1792{ 1793 IOPCIDevice * root; 1794 char location[ 24 ]; 1795 bool ok; 1796#if ROM_KEXTS 1797 OSData * data; 1798 OSData * driverData; 1799 UInt32 *regData, expRomReg; 1800 IOMemoryMap * memoryMap; 1801 IOVirtualAddress virtAddr; 1802#endif 1803 1804 if (nub) 1805 { 1806 if (nub->space.s.functionNum) 1807 snprintf( location, sizeof(location), "%X,%X", nub->space.s.deviceNum, 1808 nub->space.s.functionNum ); 1809 else 1810 snprintf( location, sizeof(location), "%X", nub->space.s.deviceNum ); 1811 nub->setLocation( location ); 1812 IODTFindSlotName( nub, nub->space.s.deviceNum ); 1813 1814 // set up config space shadow 1815 1816 IOPCIConfigShadow * shadow = IONew(IOPCIConfigShadow, 1); 1817 if (shadow) 1818 { 1819 bzero(shadow, sizeof(IOPCIConfigShadow)); 1820 queue_init(&shadow->dependents); 1821 shadow->device = nub; 1822 for (root = nub; 1823 (!root->getProperty(gIOPCIThunderboltKey)) 1824 && (root = OSDynamicCast(IOPCIDevice, root->getParentEntry(gIODTPlane)));) 1825 {} 1826 shadow->tunnelRoot = root; 1827 nub->reserved->tunnelL1Allow = kTunnelL1NotSet; 1828 1829 nub->savedConfig = (UInt32 *) &shadow->savedConfig[0]; 1830 for (int i = 0; i < kIOPCIConfigEPShadowRegs; i++) 1831 { 1832 if (kIOPCISaveRegsMask & (1 << i)) 1833 nub->savedConfig[i] = nub->configRead32( i << 2 ); 1834 } 1835 } 1836 1837 checkProperties( nub ); 1838 1839 if (shadow && (kIOPCIClassBridge == (nub->savedConfig[kIOPCIConfigRevisionID >> 2] >> 24))) 1840 { 1841 shadow->flags |= kIOPCIConfigShadowBridge; 1842#if 0 1843 if (kIOPCISubClassBridgeMCA >= (0xff & (nub->savedConfig[kIOPCIConfigRevisionID >> 2] >> 16))) 1844 { 1845 shadow->flags |= kIOPCIConfigShadowHostBridge; 1846 } 1847#endif 1848 } 1849 1850#if ROM_KEXTS 1851 // look for a "driver-reg,AAPL,MacOSX,PowerPC" property. 1852 1853 if ((data = (OSData *)nub->getProperty("driver-reg,AAPL,MacOSX,PowerPC"))) 1854 { 1855 if (data->getLength() == (2 * sizeof(UInt32))) 1856 { 1857 regData = (UInt32 *)data->getBytesNoCopy(); 1858 1859 getNubResources(nub); 1860 memoryMap = nub->mapDeviceMemoryWithRegister(kIOPCIConfigExpansionROMBase); 1861 if (memoryMap != 0) 1862 { 1863 virtAddr = memoryMap->getVirtualAddress(); 1864 virtAddr += regData[0]; 1865 1866 nub->setMemoryEnable(true); 1867 1868 expRomReg = nub->configRead32(kIOPCIConfigExpansionROMBase); 1869 nub->configWrite32(kIOPCIConfigExpansionROMBase, expRomReg | 1); 1870 1871 driverData = OSData::withBytesNoCopy((void *)virtAddr, regData[1]); 1872 if (driverData != 0) 1873 { 1874 gIOCatalogue->addExtensionsFromArchive(driverData); 1875 1876 driverData->release(); 1877 } 1878 1879 nub->configWrite32(kIOPCIConfigExpansionROMBase, expRomReg); 1880 1881 nub->setMemoryEnable(false); 1882 1883 memoryMap->release(); 1884 } 1885 } 1886 } 1887#endif 1888 ok = nub->attach( this ); 1889 1890 if (ok) 1891 { 1892 nub->callPlatformFunction(gIOPlatformDeviceMessageKey, false, 1893 (void *) kIOMessageDeviceWillPowerOff, nub, (void *) 0, (void *) 0); 1894 1895 nub->callPlatformFunction(gIOPlatformDeviceMessageKey, false, 1896 (void *) kIOMessageDeviceHasPoweredOn, nub, (void *) 0, (void *) 0); 1897 1898 nub->registerService(); 1899 } 1900 } 1901 else 1902 ok = false; 1903 1904 return (ok); 1905} 1906 1907UInt8 IOPCIBridge::firstBusNum( void ) 1908{ 1909 return (0); 1910} 1911 1912UInt8 IOPCIBridge::lastBusNum( void ) 1913{ 1914 return (255); 1915} 1916 1917IOReturn IOPCIBridge::kernelRequestProbe(IOPCIDevice * device, uint32_t options) 1918{ 1919 IOReturn ret = kIOReturnUnsupported; 1920 1921 DLOG("%s::kernelRequestProbe(%x)\n", device->getName(), options); 1922 1923 if ((kIOPCIProbeOptionEject & options) && device->getProperty(kIOPCIEjectableKey)) 1924 { 1925 ret = configOp(device, kConfigOpEject, 0); 1926 device = OSDynamicCast(IOPCIDevice, getProvider()); 1927 if (!device) 1928 return (ret); 1929 options |= kIOPCIProbeOptionNeedsScan; 1930 options &= ~kIOPCIProbeOptionEject; 1931 } 1932 1933 if (kIOPCIProbeOptionNeedsScan & options) 1934 { 1935 bool bootDefer = (0 != device->getProperty(kIOPCITunnelBootDeferKey)); 1936 if (bootDefer) 1937 { 1938 IOPCI2PCIBridge * p2pBridge; 1939 if ((p2pBridge = OSDynamicCast(IOPCI2PCIBridge, this))) 1940 p2pBridge->startBootDefer(device); 1941 1942 return (kIOReturnSuccess); 1943 } 1944 1945 ret = configOp(device, kConfigOpNeedsScan, 0); 1946 } 1947 1948 if (kIOPCIProbeOptionDone & options) ret = configOp(device, kConfigOpScan, NULL); 1949 1950 return (ret); 1951} 1952 1953IOReturn IOPCIBridge::protectDevice(IOPCIDevice * device, uint32_t space, uint32_t prot) 1954{ 1955 IOReturn ret; 1956 1957 prot &= (VM_PROT_READ|VM_PROT_WRITE); 1958 prot <<= kPCIDeviceStateConfigProtectShift; 1959 1960 DLOG("%s::protectDevice(%x, %x)\n", device->getName(), space, prot); 1961 1962 ret = configOp(device, kConfigOpProtect, &prot); 1963 1964 return (ret); 1965} 1966 1967void IOPCIBridge::probeBus( IOService * provider, UInt8 busNum ) 1968{ 1969 IORegistryEntry * found; 1970 OSDictionary * propTable; 1971 IOPCIDevice * nub = 0; 1972 OSIterator * kidsIter; 1973 UInt32 index = 0; 1974 UInt32 idx = 0; 1975 bool hotplugBus; 1976 1977// kprintf("probe: %s\n", provider->getName()); 1978 1979 hotplugBus = (0 != getProperty(kIOPCIHotPlugKey)); 1980 if (hotplugBus && !provider->getProperty(kIOPCIOnlineKey)) 1981 { 1982 DLOG("offline\n"); 1983 return; 1984 } 1985 1986 IODTSetResolving(provider, &compareAddressCell, &nvLocation); 1987 1988 kidsIter = provider->getChildIterator( gIODTPlane ); 1989 1990 // find and copy over any devices from the device tree 1991 OSArray * nubs = OSArray::withCapacity(0x10); 1992 assert(nubs); 1993 1994 if (kidsIter) { 1995 kidsIter->reset(); 1996 while ((found = (IORegistryEntry *) kidsIter->getNextObject())) 1997 { 1998// kprintf("probe: %s, %s\n", provider->getName(), found->getName()); 1999 if (!found->getProperty("vendor-id")) continue; 2000 if (found->inPlane(gIOServicePlane)) continue; 2001 nub = OSDynamicCast(IOPCIDevice, found); 2002 if (!nub) continue; 2003 propTable = found->getPropertyTable(); 2004 nub->retain(); 2005 initializeNub(nub, propTable); 2006 2007 { 2008 IOByteCount capa, msiCapa; 2009 OSData * data; 2010 2011 nubs->setObject(index++, nub); 2012 2013 nub->reserved->headerType = (0x7F & nub->configRead8(kIOPCIConfigHeaderType)); 2014 capa = 0; 2015 if (nub->extendedFindPCICapability(kIOPCIPowerManagementCapability, &capa)) 2016 nub->reserved->powerCapability = capa; 2017 2018 msiCapa = 0; 2019 nub->extendedFindPCICapability(kIOPCIMSICapability, &msiCapa); 2020 capa = 0; 2021 if ((!msiCapa 2022// || !strcmp("ethernet", nub->getName()) 2023 ) && nub->extendedFindPCICapability(kIOPCIMSIXCapability, &capa)) 2024 { 2025 nub->reserved->msiCapability = capa; 2026 nub->reserved->msiMode |= kMSIX; 2027 } 2028 else nub->reserved->msiCapability = msiCapa; 2029 2030 capa = 0; 2031 if (nub->extendedFindPCICapability(kIOPCIExpressLatencyTolerenceReportingCapability, &capa)) 2032 nub->reserved->latencyToleranceCapability = capa; 2033 2034 capa = 0; 2035 if (nub->extendedFindPCICapability(kIOPCIExpressL1PMSubstatesCapability, &capa)) 2036 { 2037 nub->reserved->l1pmCapability = capa; 2038 nub->reserved->l1pmCaps = (0xFFFFFFF0 | nub->configRead32(capa + 0x04)); 2039 } 2040 2041 capa = 0; 2042 if (nub->extendedFindPCICapability(kIOPCIPCIExpressCapability, &capa)) { 2043 nub->reserved->expressCapability = capa; 2044 nub->reserved->expressCapabilities = nub->configRead16(capa + 0x02); 2045 nub->reserved->aspmCaps = (3 & (nub->configRead32(capa + 0xc) >> 10)); 2046#if ACPI_SUPPORT 2047 // current aspm mode 2048 nub->reserved->expressASPMDefault = (3 & (nub->configRead16(capa + 0x10))); 2049#else 2050 nub->reserved->expressASPMDefault = nub->reserved->aspmCaps; 2051#endif 2052 } 2053 2054 if (nub->reserved->expressCapability && nub->reserved->latencyToleranceCapability 2055 && (data = OSDynamicCast(OSData, nub->getProperty(kIOPCIExpressMaxLatencyKey, gIOServicePlane)))) 2056 { 2057 nub->extendedConfigWrite32(nub->reserved->latencyToleranceCapability + 0x04, 2058 *((uint32_t *) data->getBytesNoCopy())); 2059 enableLTR(nub, true); 2060 } 2061 2062 if (nub->reserved->expressCapability) 2063 { 2064 if ((data = OSDynamicCast(OSData, nub->getProperty(kIOPCIExpressASPMDefaultKey)))) 2065 { 2066 nub->reserved->expressASPMDefault = *((uint32_t *) data->getBytesNoCopy()); 2067 setDeviceASPMState(nub, this, nub->reserved->expressASPMDefault); 2068 } 2069 else 2070 { 2071 nub->setProperty(kIOPCIExpressASPMDefaultKey, nub->reserved->expressASPMDefault, 32); 2072 } 2073 } 2074 2075 if (kPCIHeaderType1 == nub->reserved->headerType) 2076 { 2077 nub->reserved->rootPort = ((0xF0 & nub->reserved->expressCapabilities) == 0x40); 2078 uint16_t bridgeControl = nub->configRead16(kPCI2PCIBridgeControl); 2079 bridgeControl |= 0x0002; // SERR forward 2080 nub->configWrite16(kPCI2PCIBridgeControl, bridgeControl); 2081 } 2082 capa = 0; 2083 if (nub->extendedFindPCICapability(kIOPCIExpressErrorReportingCapability, &capa)) 2084 { 2085 nub->reserved->aerCapability = capa; 2086 2087 uint32_t dcEnables = 0; 2088 uint32_t sdata = 0; 2089 2090 enum { kDeviceControlAllErrors = ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)) }; 2091 if (kIOPCIConfiguratorAER & gIOPCIFlags) dcEnables |= kDeviceControlAllErrors; 2092 2093 if ((data = OSDynamicCast(OSData, nub->getProperty(kIOPCIExpressErrorControlKey, gIOServicePlane)))) 2094 { 2095 nub->configWrite32(nub->reserved->aerCapability + 0x18, 2096 *((uint32_t *) data->getBytesNoCopy())); 2097 } 2098 if ((data = OSDynamicCast(OSData, nub->getProperty(kIOPCIExpressErrorUncorrectableSeverityKey, gIOServicePlane)))) 2099 { 2100 nub->configWrite32(nub->reserved->aerCapability + 0x0C, 2101 *((uint32_t *) data->getBytesNoCopy())); 2102 } 2103 if ((data = OSDynamicCast(OSData, nub->getProperty(kIOPCIExpressErrorUncorrectableMaskKey, gIOServicePlane)))) 2104 { 2105 sdata = ((uint32_t *) data->getBytesNoCopy())[0]; 2106 nub->configWrite32(nub->reserved->aerCapability + 0x04, sdata); 2107 nub->configWrite32(nub->reserved->aerCapability + 0x08, sdata); 2108 } 2109 if ((data = OSDynamicCast(OSData, nub->getProperty(kIOPCIExpressErrorCorrectableMaskKey, gIOServicePlane)))) 2110 { 2111 sdata = ((uint32_t *) data->getBytesNoCopy())[0]; 2112 nub->configWrite32(nub->reserved->aerCapability + 0x10, sdata); 2113 nub->configWrite32(nub->reserved->aerCapability + 0x14, sdata); 2114 } 2115 2116 if (dcEnables) 2117 { 2118 uint32_t deviceControl = nub->configRead32(nub->reserved->expressCapability + 0x08); 2119 deviceControl |= dcEnables; 2120 nub->configWrite32(nub->reserved->expressCapability + 0x08, deviceControl); 2121#if 0 2122 uint16_t cmd = nub->configRead32(kIOPCIConfigCommand); 2123 cmd |= kIOPCICommandSERR; 2124 nub->configWrite32(kIOPCIConfigCommand, cmd); 2125#endif 2126 } 2127 } 2128 2129 nub->release(); 2130 } 2131 } 2132 } 2133 2134 idx = 0; 2135 while ((nub = (IOPCIDevice *)nubs->getObject(idx++))) 2136 { 2137 if (hotplugBus || provider->getProperty(kIOPCIEjectableKey)) 2138 { 2139 nub->setProperty(kIOPCIEjectableKey, kOSBooleanTrue); 2140 } 2141 2142 publishNub(nub , idx); 2143 } 2144 2145 nubs->release(); 2146 if (kidsIter) 2147 kidsIter->release(); 2148} 2149 2150/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2151 2152bool IOPCIBridge::addBridgeIORange( IOByteCount start, IOByteCount length ) 2153{ 2154 bool ok; 2155 2156 // fix - ACPIPCI makes this up for hosts with zero space 2157 if ((0x0 == start) && (0x10000 == length)) 2158 return (false); 2159 2160 ok = IOPCIRangeListAddRange(&reserved->rangeLists[kIOPCIResourceTypeIO], 2161 kIOPCIResourceTypeIO, 2162 start, length); 2163 return (ok); 2164} 2165 2166bool IOPCIBridge::addBridgeMemoryRange( IOPhysicalAddress start, 2167 IOPhysicalLength length, bool host ) 2168{ 2169 bool ok; 2170 2171 // fix - ACPIPCI makes this up for hosts with zero space 2172 if ((0x80000000 == start) && (0x7f000000 == length)) 2173 return (false); 2174 2175 ok = IOPCIRangeListAddRange(&reserved->rangeLists[kIOPCIResourceTypeMemory], 2176 kIOPCIResourceTypeMemory, 2177 start, length); 2178 return (ok); 2179 2180} 2181 2182bool IOPCIBridge::addBridgePrefetchableMemoryRange( addr64_t start, 2183 addr64_t length ) 2184{ 2185 bool ok; 2186 ok = IOPCIRangeListAddRange(&reserved->rangeLists[kIOPCIResourceTypePrefetchMemory], 2187 kIOPCIResourceTypePrefetchMemory, 2188 start, length); 2189 return (ok); 2190} 2191 2192bool IOPCIBridge::addBridgePrefetchableMemoryRange( IOPhysicalAddress start, 2193 IOPhysicalLength length, 2194 bool host ) 2195{ 2196 return (addBridgePrefetchableMemoryRange(start, length)); 2197} 2198 2199/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2200 2201bool IOPCIBridge::constructRange( IOPCIAddressSpace * flags, 2202 IOPhysicalAddress64 phys, 2203 IOPhysicalLength64 len, 2204 OSArray * array ) 2205{ 2206 IOMemoryDescriptor * md; 2207 IOMemoryDescriptor * ioMemory; 2208 IOSubMemoryDescriptor * subMem; 2209 IOAddressRange range; 2210 bool ok; 2211 unsigned int idx; 2212 2213 for (idx = 0; 2214 (md = (IODeviceMemory *) array->getObject(idx)) 2215 && (flags->s.registerNum != (md->getTag() & 0xff)); 2216 idx++) {} 2217 2218 if (md) 2219 { 2220 md->retain(); 2221 md->redirect(TASK_NULL, true); 2222 2223 DLOG("reloc at (%u:%u:%u:0x%x) 0x%qx, 0x%qx -> 0x%qx, 0x%qx\n", 2224 flags->s.busNum, flags->s.deviceNum, flags->s.functionNum, flags->s.registerNum, 2225 md->getPhysicalSegment(0, 0, kIOMemoryMapperNone), (uint64_t) md->getLength(), 2226 phys, len); 2227 2228 if ((subMem = OSDynamicCast(IOSubMemoryDescriptor, md))) 2229 { 2230 ok = subMem->initSubRange(ioDeviceMemory(), phys, len, (IODirection) kIOMemoryThreadSafe); 2231 } 2232 else 2233 { 2234 range.address = phys; 2235 range.length = len; 2236 ok = md->initWithOptions(&range, 1, 0, TASK_NULL, 2237 kIOMemoryTypePhysical64 2238 // | kIOMemoryRedirected 2239 | kIODirectionNone 2240 | kIOMemoryMapperNone, 2241 NULL); 2242 } 2243 if (!ok) panic("IOMD::initWithOptions"); 2244 md->redirect(TASK_NULL, false); 2245 } 2246 else 2247 { 2248 if (kIOPCIIOSpace == flags->s.space) 2249 { 2250 if (!(ioMemory = ioDeviceMemory())) 2251 md = 0; 2252 else 2253 { 2254 phys &= 0x00ffffff; // seems bogus 2255 md = IOSubMemoryDescriptor::withSubRange(ioMemory, phys, len, kIOMemoryThreadSafe); 2256 if (md == 0) 2257 { 2258 /* didn't fit */ 2259 md = IOMemoryDescriptor::withAddressRange( 2260 phys + ioMemory->getPhysicalSegment(0, 0, kIOMemoryMapperNone), 2261 len, kIODirectionNone | kIOMemoryHostOnly, NULL ); 2262 } 2263 } 2264 } 2265 else 2266 { 2267 md = IOMemoryDescriptor::withAddressRange( 2268 phys, len, kIODirectionNone | kIOMemoryMapperNone, NULL); 2269 } 2270 ok = array->setObject(md); 2271 } 2272 2273 if (md) 2274 { 2275 md->setTag( flags->bits ); 2276 md->release(); 2277 } 2278 else 2279 ok = false; 2280 2281 return (ok); 2282} 2283 2284IOReturn IOPCIBridge::getDTNubAddressing( IOPCIDevice * regEntry ) 2285{ 2286 OSArray * array; 2287 IORegistryEntry * parentEntry; 2288 OSData * addressProperty; 2289#if defined(__i386__) || defined(__x86_64__) 2290 IOPhysicalAddress64 phys; 2291 IOPhysicalLength64 len; 2292#else 2293 IOPhysicalAddress phys; 2294 IOPhysicalLength len; 2295#endif 2296 UInt32 cells = 5; 2297 int i, num; 2298 UInt32 * reg; 2299 2300 addressProperty = (OSData *) regEntry->getProperty( "assigned-addresses" ); 2301 if (0 == addressProperty) 2302 return (kIOReturnSuccess); 2303 2304 parentEntry = regEntry->getParentEntry( gIODTPlane ); 2305 if (0 == parentEntry) 2306 return (kIOReturnBadArgument); 2307 2308 array = (OSArray *) regEntry->copyProperty(gIODeviceMemoryKey); 2309 if (array) 2310 { 2311 OSArray * newArray; 2312 newArray = OSArray::withArray(array); 2313 array->release(); 2314 array = newArray; 2315 } 2316 2317 if (!array) array = OSArray::withCapacity(4); 2318 if (!array) return (kIOReturnNoMemory); 2319 2320 reg = (UInt32 *) addressProperty->getBytesNoCopy(); 2321 num = addressProperty->getLength() / (sizeof(UInt32) * cells); 2322 2323 for (i = 0; i < num; i++) 2324 { 2325#if defined(__i386__) || defined(__x86_64__) 2326 phys = ((IOPhysicalAddress64) reg[1] << 32) | reg[2]; 2327 len = ((IOPhysicalLength64) reg[3] << 32) | reg[4]; 2328 constructRange( (IOPCIAddressSpace *) reg, phys, len, array ); 2329#else 2330 if (IODTResolveAddressCell(parentEntry, reg, &phys, &len)) 2331 constructRange( (IOPCIAddressSpace *) reg, phys, len, array ); 2332#endif 2333 reg += cells; 2334 } 2335 2336 if (array->getCount()) 2337 regEntry->setProperty( gIODeviceMemoryKey, array); 2338 2339 array->release(); 2340 2341 return (kIOReturnSuccess); 2342} 2343 2344IOReturn IOPCIBridge::getNubAddressing( IOPCIDevice * nub ) 2345{ 2346 return (kIOReturnError); 2347} 2348 2349bool IOPCIBridge::isDTNub( IOPCIDevice * nub ) 2350{ 2351 return (true); 2352} 2353 2354IOReturn IOPCIBridge::getNubResources( IOService * service ) 2355{ 2356 IOPCIDevice * nub = (IOPCIDevice *) service; 2357 IOReturn err; 2358 2359 if (service->getProperty(kIOPCIResourcedKey)) 2360 return (kIOReturnSuccess); 2361 service->setProperty(kIOPCIResourcedKey, kOSBooleanTrue); 2362 2363 err = getDTNubAddressing( nub ); 2364 2365 bool 2366 msiDefault = (false 2367#if 0 2368 || (0 == strcmp("display", nub->getName())) 2369 || (0 == strcmp("GFX0", nub->getName())) 2370 || (0 == strcmp("PXS1", nub->getName())) // yukon 2371 || (0 == strcmp("HDEF", nub->getName())) 2372 || (0 == strcmp("SATA", nub->getName())) 2373 || (0 == strcmp("LAN0", nub->getName())) 2374 || (0 == strcmp("LAN1", nub->getName())) 2375 || (0 == strcmp("PXS2", nub->getName())) // airport 2376 || (0 == strcmp("PXS3", nub->getName())) // express 2377#endif 2378 ); 2379 2380 IOService * provider = getProvider(); 2381 if (msiDefault) 2382 resolveMSIInterrupts( provider, nub ); 2383 resolveLegacyInterrupts( provider, nub ); 2384 if (!msiDefault) 2385 resolveMSIInterrupts( provider, nub ); 2386 2387 return (err); 2388} 2389 2390IOReturn IOPCIBridge::relocate(IOPCIDevice * device, uint32_t options) 2391{ 2392 spaceFromProperties(device, &device->space); 2393 return (getDTNubAddressing(device)); 2394} 2395 2396bool IOPCIBridge::matchKeys( IOPCIDevice * nub, const char * keys, 2397 UInt32 defaultMask, UInt8 regNum ) 2398{ 2399 const char * next; 2400 UInt32 mask, value, reg; 2401 bool found = false; 2402 2403 do 2404 { 2405 value = strtoul( keys, (char **) &next, 16); 2406 if (next == keys) 2407 break; 2408 2409 while ((*next) == ' ') 2410 next++; 2411 2412 if ((*next) == '&') 2413 mask = strtoul( next + 1, (char **) &next, 16); 2414 else 2415 mask = defaultMask; 2416 2417 reg = nub->savedConfig[ regNum >> 2 ]; 2418 found = ((value & mask) == (reg & mask)); 2419 keys = next; 2420 } 2421 while (!found); 2422 2423 return (found); 2424} 2425 2426 2427bool IOPCIBridge::pciMatchNub( IOPCIDevice * nub, 2428 OSDictionary * table, 2429 SInt32 * score ) 2430{ 2431 OSString * prop; 2432 const char * keys; 2433 bool match = true; 2434 UInt8 regNum; 2435 int i; 2436 2437 struct IOPCIMatchingKeys 2438 { 2439 const char * propName; 2440 UInt8 regs[ 4 ]; 2441 UInt32 defaultMask; 2442 }; 2443 const IOPCIMatchingKeys * look; 2444 static const IOPCIMatchingKeys matching[] = { 2445 { kIOPCIMatchKey, 2446 { 0x00 + 1, 0x2c }, 0xffffffff }, 2447 { kIOPCIPrimaryMatchKey, 2448 { 0x00 }, 0xffffffff }, 2449 { kIOPCISecondaryMatchKey, 2450 { 0x2c }, 0xffffffff }, 2451 { kIOPCIClassMatchKey, 2452 { 0x08 }, 0xffffff00 }}; 2453 2454 for (look = matching; 2455 (match && (look < &matching[4])); 2456 look++) 2457 { 2458 prop = (OSString *) table->getObject( look->propName ); 2459 if (prop) 2460 { 2461 keys = prop->getCStringNoCopy(); 2462 match = false; 2463 for (i = 0; 2464 ((false == match) && (i < 4)); 2465 i++) 2466 { 2467 regNum = look->regs[ i ]; 2468 match = matchKeys( nub, keys, 2469 look->defaultMask, regNum & 0xfc ); 2470 if (0 == (1 & regNum)) 2471 break; 2472 } 2473 } 2474 } 2475 2476 return (match); 2477} 2478 2479bool IOPCIBridge::matchNubWithPropertyTable( IOService * nub, 2480 OSDictionary * table, 2481 SInt32 * score ) 2482{ 2483 bool matches; 2484 2485 matches = pciMatchNub( (IOPCIDevice *) nub, table, score); 2486 2487 if (matches) 2488 { 2489 OSString * classProp; 2490 classProp = OSDynamicCast(OSString, table->getObject(kIOClassKey)); 2491// classProp = OSDynamicCast(OSString, table->getObject(kCFBundleIdentifierKey)); 2492 if (classProp) 2493 { 2494 if (nub->getProperty(gIOPCITunnelledKey)) 2495 { 2496 if (!classProp->isEqualTo("IOPCI2PCIBridge")) 2497 { 2498 if (!table->getObject(kIOPCITunnelCompatibleKey)) 2499 { 2500 IOLog("Driver \"%s\" needs \"%s\" key in plist\n", 2501 classProp->getCStringNoCopy(), kIOPCITunnelCompatibleKey); 2502 } 2503 if ((kIOPCIConfiguratorNoTunnelDrv & gIOPCIFlags) 2504 || (kOSBooleanFalse == table->getObject(kIOPCITunnelCompatibleKey)) 2505 || ((kOSBooleanTrue != table->getObject(kIOPCITunnelCompatibleKey)) 2506 && (kIOPCIConfiguratorCheckTunnel & gIOPCIFlags)) 2507 ) 2508 { 2509 matches = false; 2510 } 2511 } 2512 } 2513 } 2514 } 2515 2516// if (matches && (!strncmp("pci1033", nub->getName(), strlen("pci1033")))) matches = false; 2517 2518 return (matches); 2519} 2520 2521bool IOPCIBridge::compareNubName( const IOService * nub, 2522 OSString * name, OSString ** matched ) const 2523{ 2524 return (IODTCompareNubName(nub, name, matched)); 2525} 2526 2527UInt32 IOPCIBridge::findPCICapability( IOPCIAddressSpace space, 2528 UInt8 capabilityID, UInt8 * found ) 2529{ 2530 UInt32 data = 0; 2531 UInt8 offset; 2532 2533 if (found) 2534 *found = 0; 2535 2536 if (0 == ((kIOPCIStatusCapabilities << 16) 2537 & (configRead32(space, kIOPCIConfigCommand)))) 2538 return (0); 2539 2540 offset = (0xff & configRead32(space, kIOPCIConfigCapabilitiesPtr)); 2541 if (offset & 3) 2542 offset = 0; 2543 while (offset) 2544 { 2545 data = configRead32( space, offset ); 2546 if (capabilityID == (data & 0xff)) 2547 { 2548 if (found) 2549 *found = offset; 2550 break; 2551 } 2552 offset = (data >> 8) & 0xff; 2553 if (offset & 3) 2554 offset = 0; 2555 } 2556 2557 return (offset ? data : 0); 2558} 2559 2560UInt32 IOPCIBridge::extendedFindPCICapability( IOPCIAddressSpace space, 2561 UInt32 capabilityID, IOByteCount * found ) 2562{ 2563 uint32_t result; 2564 uint32_t firstOffset = 0; 2565 2566 if (found) 2567 firstOffset = *found; 2568 result = gIOPCIConfigurator->findPCICapability(space, capabilityID, &firstOffset); 2569 if (found) 2570 *found = firstOffset; 2571 2572 return ((UInt32) result); 2573} 2574 2575/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2576 2577IOReturn IOPCIBridge::createAGPSpace( IOAGPDevice * master, 2578 IOOptionBits options, 2579 IOPhysicalAddress * address, 2580 IOPhysicalLength * length ) 2581{ 2582 return (kIOReturnUnsupported); 2583} 2584 2585IOReturn IOPCIBridge::destroyAGPSpace( IOAGPDevice * master ) 2586{ 2587 return (kIOReturnUnsupported); 2588} 2589 2590IORangeAllocator * IOPCIBridge::getAGPRangeAllocator( IOAGPDevice * master ) 2591{ 2592 return (0); 2593} 2594 2595IOOptionBits IOPCIBridge::getAGPStatus( IOAGPDevice * master, 2596 IOOptionBits options ) 2597{ 2598 return (0); 2599} 2600 2601IOReturn IOPCIBridge::commitAGPMemory( IOAGPDevice * master, 2602 IOMemoryDescriptor * memory, 2603 IOByteCount agpOffset, 2604 IOOptionBits options ) 2605{ 2606 return (kIOReturnUnsupported); 2607} 2608 2609IOReturn IOPCIBridge::releaseAGPMemory( IOAGPDevice * master, 2610 IOMemoryDescriptor * memory, 2611 IOByteCount agpOffset, 2612 IOOptionBits options ) 2613{ 2614 return (kIOReturnUnsupported); 2615} 2616 2617IOReturn IOPCIBridge::resetAGPDevice( IOAGPDevice * master, 2618 IOOptionBits options ) 2619{ 2620 return (kIOReturnUnsupported); 2621} 2622 2623IOReturn IOPCIBridge::getAGPSpace( IOAGPDevice * master, 2624 IOPhysicalAddress * address, 2625 IOPhysicalLength * length ) 2626{ 2627 return (kIOReturnUnsupported); 2628} 2629 2630/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2631 2632#undef super 2633#define super IOPCIBridge 2634 2635OSDefineMetaClassAndStructors(IOPCI2PCIBridge, IOPCIBridge) 2636OSMetaClassDefineReservedUnused(IOPCI2PCIBridge, 0); 2637OSMetaClassDefineReservedUnused(IOPCI2PCIBridge, 1); 2638OSMetaClassDefineReservedUnused(IOPCI2PCIBridge, 2); 2639OSMetaClassDefineReservedUnused(IOPCI2PCIBridge, 3); 2640OSMetaClassDefineReservedUnused(IOPCI2PCIBridge, 4); 2641OSMetaClassDefineReservedUnused(IOPCI2PCIBridge, 5); 2642OSMetaClassDefineReservedUnused(IOPCI2PCIBridge, 6); 2643OSMetaClassDefineReservedUnused(IOPCI2PCIBridge, 7); 2644OSMetaClassDefineReservedUnused(IOPCI2PCIBridge, 8); 2645 2646/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2647 2648IOService * IOPCI2PCIBridge::probe( IOService * provider, 2649 SInt32 * score ) 2650{ 2651 if (0 == (fBridgeDevice = OSDynamicCast(IOPCIDevice, provider))) 2652 return (0); 2653 2654 *score -= 100; 2655 2656 return (this); 2657} 2658 2659bool IOPCI2PCIBridge::serializeProperties( OSSerialize * serialize ) const 2660{ 2661 return (super::serializeProperties(serialize)); 2662} 2663 2664IOReturn IOPCIBridge::checkLink(uint32_t options) 2665{ 2666 return (kIOReturnSuccess); 2667} 2668 2669IOReturn IOPCI2PCIBridge::checkLink(uint32_t options) 2670{ 2671 IOReturn ret; 2672 bool present; 2673 uint16_t linkStatus; 2674 2675 AbsoluteTime startTime, endTime; 2676 uint64_t nsec, nsec2; 2677 2678 ret = fBridgeDevice->checkLink(options & ~kCheckLinkParents); 2679 if (kIOReturnSuccess != ret) return (kIOReturnNoDevice); 2680 2681 if ((kCheckLinkParents & options) || !fHotPlugInts || !fBridgeInterruptSource) return (ret); 2682 2683 clock_get_uptime(&startTime); 2684 linkStatus = fBridgeDevice->configRead16(fBridgeDevice->reserved->expressCapability + 0x12); 2685 2686#if 1 2687 clock_get_uptime(&endTime); 2688 absolutetime_to_nanoseconds(startTime, &nsec2); 2689 SUB_ABSOLUTETIME(&endTime, &startTime); 2690 absolutetime_to_nanoseconds(endTime, &nsec); 2691 2692 if (nsec > 1000*1000) 2693 { 2694 DLOG("%s: @%lld link %x took %lld us link %x\n", 2695 fLogName, nsec2 / 1000, 2696 linkStatus, nsec / 1000, 2697 fBridgeDevice->checkLink(options)); 2698 } 2699#endif 2700 2701 if (0xffff == linkStatus) 2702 return (kIOReturnNoDevice); 2703 2704 present = (0 != ((1 << 13) & linkStatus)); 2705 if (fPresenceInt != present) 2706 { 2707 fPresenceInt = present; 2708 if (!present) 2709 { 2710 fBridgeDevice->configWrite32(kPCI2PCIMemoryRange, 0); 2711 fBridgeDevice->configWrite32(kPCI2PCIPrefetchMemoryRange, 0); 2712 fBridgeDevice->configWrite32(kPCI2PCIPrefetchUpperBase, 0); 2713 fBridgeDevice->configWrite32(kPCI2PCIPrefetchUpperLimit, 0); 2714 } 2715 DLOG("%s: @%lld -> present %d\n", 2716 fLogName, nsec / 1000, present); 2717 } 2718 2719 return (present ? kIOReturnSuccess : kIOReturnOffline); 2720} 2721 2722enum { 2723 kIntsHP = 0x00000001, 2724 kIntsAER = 0x00000002, 2725}; 2726 2727bool IOPCI2PCIBridge::filterInterrupt(IOFilterInterruptEventSource * source) 2728{ 2729 IOReturn ret; 2730 uint8_t intsPending = 0; 2731 2732// DLOG("%s: filterInterrupt\n", 2733// fLogName); 2734 2735 if (kIOPCIDeviceOffState == fPowerState) return (false); 2736 if (fNoDevice) return (false); 2737 ret = checkLink(); 2738 if (kIOReturnNoDevice == ret) 2739 { 2740 fNoDevice = true; 2741 return (false); 2742 } 2743 2744 if (fHotPlugInts) 2745 { 2746 enum { kNeedMask = ((1 << 8) | (1 << 3)) }; 2747 2748 uint16_t slotStatus = fBridgeDevice->configRead16( fBridgeDevice->reserved->expressCapability + 0x1a ); 2749// if (kNeedMask & slotStatus) 2750 fBridgeDevice->configWrite16( fBridgeDevice->reserved->expressCapability + 0x1a, slotStatus ); 2751 2752 if (0 != (kNeedMask & slotStatus)) intsPending |= kIntsHP; 2753 } 2754 2755 IOPCIAERRoot * root; 2756 if ((root = fAERRoot)) 2757 { 2758 enum { kNeedMask = ((1 << 2) | (1 << 0)) }; 2759 2760 uint32_t status = fBridgeDevice->configRead32(fBridgeDevice->reserved->aerCapability + 0x30); 2761 if (0 != (kNeedMask & status)) 2762 { 2763 IOInterruptState ints; 2764 uint8_t nextIdx; 2765 2766 ints = IOSimpleLockLockDisableInterrupt(fISRLock); 2767 nextIdx = root->fAERWriteIndex + 1; 2768 if (nextIdx == kAERISRNum) nextIdx = 0; 2769 if (nextIdx != root->fAERReadIndex) 2770 { 2771 root->fISRErrors[root->fAERWriteIndex].status = status; 2772 root->fISRErrors[root->fAERWriteIndex].source = fBridgeDevice->configRead32(fBridgeDevice->reserved->aerCapability + 0x34); 2773 root->fAERWriteIndex = nextIdx; 2774 } 2775 IOSimpleLockUnlockEnableInterrupt(fISRLock, ints); 2776 intsPending |= kIntsAER; 2777 } 2778 fBridgeDevice->configWrite16(fBridgeDevice->reserved->aerCapability + 0x30, status); 2779 } 2780 2781 OSBitOrAtomic8(intsPending, &fIntsPending); 2782 2783 return (intsPending != 0); 2784} 2785 2786void IOPCI2PCIBridge::handleInterrupt(IOInterruptEventSource * source, int count) 2787{ 2788 uint8_t intsPending = 0; 2789 2790 intsPending = fIntsPending; 2791 OSBitAndAtomic8(~intsPending, &fIntsPending); 2792 2793 if (kIntsHP & intsPending) 2794 { 2795 bool present; 2796 UInt32 probeTimeMS = 1; 2797 2798 fHotplugCount++; 2799 2800 uint16_t slotStatus = fBridgeDevice->configRead16( fBridgeDevice->reserved->expressCapability + 0x1a ); 2801 uint16_t linkStatus = fBridgeDevice->configRead16( fBridgeDevice->reserved->expressCapability + 0x12 ); 2802 uint16_t linkControl = fBridgeDevice->configRead16( fBridgeDevice->reserved->expressCapability + 0x10 ); 2803 2804 DLOG("%s: hotpInt (%d), fNeedProbe %d, slotStatus %x, linkStatus %x, linkControl %x\n", 2805 fLogName, 2806 fHotplugCount, fNeedProbe, slotStatus, linkStatus, linkControl); 2807 2808 present = (0 != ((1 << 6) & slotStatus)); 2809 2810 if (fLinkControlWithPM) 2811 { 2812 uint16_t pmBits = fBridgeDevice->configRead16(fBridgeDevice->reserved->powerCapability + 4); 2813 if (present && (kPCIPMCSPowerStateD0 != (kPCIPMCSPowerStateMask & pmBits))) 2814 { 2815 DLOG("%s: pwr on\n", fLogName); 2816 fBridgeDevice->configWrite16(fBridgeDevice->reserved->powerCapability + 4, kPCIPMCSPMEStatus | kPCIPMCSPowerStateD0); 2817 IOSleep(10); 2818 } 2819 } 2820 2821 if (present && ((1 << 4) & linkControl)) 2822 { 2823 DLOG("%s: enabling link\n", fLogName); 2824 linkControl &= ~((1 << 4) | (1 << 6)); 2825 fBridgeDevice->configWrite16( fBridgeDevice->reserved->expressCapability + 0x10, linkControl ); 2826 fWaitingLinkEnable = true; 2827 present = false; 2828 } 2829 else if (!present) 2830 { 2831 if (fLinkControlWithPM) 2832 { 2833 DLOG("%s: pwr off\n", fLogName); 2834 fBridgeDevice->configWrite16(fBridgeDevice->reserved->powerCapability + 4, (kPCIPMCSPMEStatus | kPCIPMCSPMEEnable | kPCIPMCSPowerStateD3)); 2835 } 2836 else if (!((1 << 4) & linkControl)) 2837 { 2838 if (fWaitingLinkEnable) 2839 fWaitingLinkEnable = false; 2840 else 2841 { 2842 DLOG("%s: disabling link\n", fLogName); 2843 linkControl &= ~(1 << 6); 2844 linkControl |= (1 << 4); 2845 fBridgeDevice->configWrite16(fBridgeDevice->reserved->expressCapability + 0x10, linkControl); 2846 } 2847 } 2848 } 2849 if (fLinkChangeOnly) 2850 return; 2851 2852 present &= (0 != ((1 << 13) & linkStatus)); 2853 2854 if (fPresence != present) 2855 { 2856 DLOG("%s: now present %d\n", fLogName, present); 2857 2858 fBridgeDevice->removeProperty(kIOPCIConfiguredKey); 2859 fNeedProbe = true; 2860 fPresence = present; 2861 if (!present) 2862 { 2863 // not present 2864 fBridgeDevice->removeProperty(kIOPCIOnlineKey); 2865 } 2866 else 2867 { 2868 // present 2869 fBridgeDevice->setProperty(kIOPCIOnlineKey, true); 2870 probeTimeMS = 2000; 2871 } 2872 } 2873 2874 if (fNeedProbe) 2875 { 2876 if (kIOPMUndefinedDriverAssertionID == fPMAssertion) 2877 { 2878 fPMAssertion = getPMRootDomain()->createPMAssertion( 2879 kIOPMDriverAssertionCPUBit, kIOPMDriverAssertionLevelOn, 2880 this, "com.apple.iokit.iopcifamily"); 2881 } 2882 fTimerProbeES->setTimeoutMS(probeTimeMS); 2883 } 2884 } 2885 2886 if (kIntsAER & intsPending) 2887 { 2888 IOPCIAERRoot * root = fAERRoot; 2889 IOPCIAddressSpace space; 2890 IOInterruptState ints; 2891 IOService * result; 2892 IOPCIDevice * device; 2893 IOPCIEventSource * src; 2894 IOReturn ret; 2895 uint8_t nextIdx; 2896 uint32_t correctable, source, rstatus, status, severity; 2897 IOPCIEvent newEvent; 2898 2899 ints = IOSimpleLockLockDisableInterrupt(fISRLock); 2900 while (root->fAERReadIndex != root->fAERWriteIndex) 2901 { 2902 rstatus = root->fISRErrors[root->fAERReadIndex].status; 2903 source = root->fISRErrors[root->fAERReadIndex].source; 2904 nextIdx = root->fAERReadIndex + 1; 2905 if (nextIdx == kAERISRNum) nextIdx = 0; 2906 root->fAERReadIndex = nextIdx; 2907 IOSimpleLockUnlockEnableInterrupt(fISRLock, ints); 2908 2909 DLOG("%s: AER root status %x\n", fLogName, rstatus); 2910 for (correctable = 0; correctable < 2; correctable++, source <<= 16) 2911 { 2912 if (!((correctable ? 1 : 4) & rstatus)) continue; 2913 space.s.busNum = (source >> 24); 2914 space.s.deviceNum = (31 & (source >> 19)); 2915 space.s.functionNum = (7 & (source >> 16)); 2916 ret = configOp(NULL, kConfigOpFindEntry, &result, &space); 2917 DLOG("AER source %d %d %d: find %x %p %s 0x%qx\n", 2918 space.s.busNum, space.s.deviceNum, space.s.functionNum, ret, result, 2919 result ? result->getName() : "", 2920 result ? result->getRegistryEntryID() : 0); 2921 if (kIOReturnSuccess != ret) continue; 2922 2923 if ((device = OSDynamicCast(IOPCIDevice, result)) 2924 && device->reserved->aerCapability) 2925 { 2926 status = device->configRead32(device->reserved->aerCapability + (correctable ? 0x10 : 0x04)); 2927 severity = (correctable ? 0 : device->configRead32(device->reserved->aerCapability + 0x0c)); 2928 newEvent.data[0] = status; 2929 newEvent.data[1] = device->configRead32(device->reserved->aerCapability + 0x1c); 2930 newEvent.data[2] = device->configRead32(device->reserved->aerCapability + 0x20); 2931 newEvent.data[3] = device->configRead32(device->reserved->aerCapability + 0x24); 2932 newEvent.data[4] = device->configRead32(device->reserved->aerCapability + 0x28); 2933 2934 DLOG("AER %scorrectable status 0x%08x sev 0x%08x TLP 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", 2935 correctable ? "" : "un", status, severity, 2936 newEvent.data[1], newEvent.data[2], newEvent.data[3], newEvent.data[4]); 2937 2938 IOSimpleLockLock(gIOPCIEventSourceLock); 2939 queue_iterate(&gIOPCIEventSourceQueue, src, IOPCIEventSource *, fQ) 2940 { 2941 if (src->fRoot && (this != src->fRoot)) continue; 2942 nextIdx = src->fWriteIndex + 1; 2943 if (nextIdx == kIOPCIEventNum) nextIdx = 0; 2944 if (nextIdx != src->fReadIndex) 2945 { 2946 src->fEvents[src->fWriteIndex].event = 2947 correctable ? kIOPCIEventCorrectableError 2948 : ((status & severity) ? kIOPCIEventFatalError : kIOPCIEventNonFatalError); 2949 device->retain(); 2950 src->fEvents[src->fWriteIndex].reporter = device; 2951 memcpy(&src->fEvents[src->fWriteIndex].data[0], 2952 &newEvent.data[0], 2953 sizeof(src->fEvents[src->fWriteIndex].data)); 2954 src->fWriteIndex = nextIdx; 2955 } 2956 if (src->isEnabled()) src->signalWorkAvailable(); 2957 } 2958 IOSimpleLockUnlock(gIOPCIEventSourceLock); 2959 } 2960 result->release(); 2961 } 2962 ints = IOSimpleLockLockDisableInterrupt(fISRLock); 2963 } 2964 IOSimpleLockUnlockEnableInterrupt(fISRLock, ints); 2965 } 2966} 2967 2968void IOPCI2PCIBridge::timerProbe(IOTimerEventSource * es) 2969{ 2970 if (fNeedProbe && (kIOPCIDeviceOnState == fPowerState)) 2971 { 2972 fNeedProbe = false; 2973 DLOG("%s: probe\n", fLogName); 2974 fBridgeDevice->kernelRequestProbe(kIOPCIProbeOptionDone | kIOPCIProbeOptionLinkInt | kIOPCIProbeOptionNeedsScan); 2975 } 2976 if (kIOPMUndefinedDriverAssertionID != fPMAssertion) 2977 { 2978 getPMRootDomain()->releasePMAssertion(fPMAssertion); 2979 fPMAssertion = kIOPMUndefinedDriverAssertionID; 2980 } 2981} 2982 2983bool IOPCI2PCIBridge::start( IOService * provider ) 2984{ 2985 bool ok; 2986 2987 fPMAssertion = kIOPMUndefinedDriverAssertionID; 2988 2989 setName(kIOPCI2PCIBridgeName); 2990 2991 snprintf(fLogName, sizeof(fLogName), "%s(%u:%u:%u)(%u-%u)", 2992 fBridgeDevice->getName(), PCI_ADDRESS_TUPLE(fBridgeDevice), firstBusNum(), lastBusNum()); 2993 2994 ok = super::start(provider); 2995 2996 if (ok && fBridgeInterruptSource) 2997 changePowerStateTo(kIOPCIDeviceOnState); 2998 2999 return (ok); 3000} 3001 3002bool IOPCI2PCIBridge::configure( IOService * provider ) 3003{ 3004 fPowerState = kIOPCIDeviceOnState; 3005 if (fBridgeDevice->reserved->powerCapability) 3006 { 3007 fLinkControlWithPM = fBridgeDevice->savedConfig 3008 && (0x3B488086 == fBridgeDevice->savedConfig[kIOPCIConfigVendorID >> 2]); 3009 } 3010 3011 if (fBridgeDevice->reserved->expressCapability) 3012 do 3013 { 3014 if (fBridgeDevice->getProperty(kIOPCIHotPlugKey)) 3015 { 3016 fHotPlugInts = true; 3017 setProperty(kIOPCIHotPlugKey, kOSBooleanTrue); 3018 } 3019 else if (fBridgeDevice->getProperty(kIOPCILinkChangeKey)) 3020 { 3021 setProperty(kIOPCILinkChangeKey, kOSBooleanTrue); 3022 fHotPlugInts = true; 3023 fLinkChangeOnly = true; 3024 } 3025 else if (fBridgeDevice->getProperty(kIOPCITunnelLinkChangeKey)) 3026 { 3027 fHotPlugInts = true; 3028 } 3029 fIsAERRoot = (fBridgeDevice->reserved->rootPort && fBridgeDevice->reserved->aerCapability); 3030 if (fHotPlugInts || fIsAERRoot) 3031 { 3032 allocateBridgeInterrupts(provider); 3033 } 3034 3035 if (fBridgeInterruptSource && !fBridgeDevice->getProperty(kIOPCITunnelBootDeferKey)) startBridgeInterrupts(provider); 3036 } 3037 while(false); 3038 3039 saveBridgeState(); 3040 if (fBridgeDevice->savedConfig) 3041 { 3042 configShadow(fBridgeDevice)->bridge = this; 3043 configShadow(fBridgeDevice)->flags |= kIOPCIConfigShadowBridge; 3044 if (fHotPlugInts) 3045 configShadow(fBridgeDevice)->flags |= kIOPCIConfigShadowBridgeInterrupts; 3046 if (OSTypeIDInst(this) != OSTypeID(IOPCI2PCIBridge)) 3047 configShadow(fBridgeDevice)->flags |= kIOPCIConfigShadowBridgeDriver; 3048 } 3049 3050 return (super::configure(provider)); 3051} 3052 3053 3054void IOPCI2PCIBridge::allocateBridgeInterrupts(IOService * provider) 3055{ 3056 IOReturn ret = kIOReturnSuccess; 3057 do 3058 { 3059 int interruptType; 3060 int intIdx = 1; 3061 for (intIdx = 1; intIdx >= 0; intIdx--) 3062 { 3063 ret = fBridgeDevice->getInterruptType(intIdx, &interruptType); 3064 if (kIOReturnSuccess == ret) 3065 { 3066 fBridgeMSI = (0 != (kIOInterruptTypePCIMessaged & interruptType)); 3067 break; 3068 } 3069 } 3070 if (kIOReturnSuccess != ret) break; 3071 3072 fBridgeInterruptSource = IOFilterInterruptEventSource::filterInterruptEventSource( 3073 this, 3074 OSMemberFunctionCast(IOInterruptEventSource::Action, 3075 this, &IOPCI2PCIBridge::handleInterrupt), 3076 OSMemberFunctionCast(IOFilterInterruptEventSource::Filter, 3077 this, &IOPCI2PCIBridge::filterInterrupt), 3078 provider, intIdx); 3079 } 3080 while(false); 3081} 3082 3083 3084void IOPCI2PCIBridge::startBridgeInterrupts(IOService * provider) 3085{ 3086 IOReturn ret = kIOReturnSuccess; 3087 do 3088 { 3089 if (!fBridgeInterruptSource) break; 3090 3091 fWorkLoop = gIOPCIConfigurator->getWorkLoop(); 3092 fTimerProbeES = IOTimerEventSource::timerEventSource(this, 3093 OSMemberFunctionCast(IOTimerEventSource::Action, 3094 this, &IOPCI2PCIBridge::timerProbe)); 3095 if (!fTimerProbeES) break; 3096 ret = fWorkLoop->addEventSource(fTimerProbeES); 3097 if (kIOReturnSuccess != ret) break; 3098 ret = fWorkLoop->addEventSource(fBridgeInterruptSource); 3099 if (kIOReturnSuccess != ret) break; 3100 3101 fISRLock = IOSimpleLockAlloc(); 3102 if (!fISRLock) break; 3103 if (fIsAERRoot) 3104 { 3105 fAERRoot = IONew(IOPCIAERRoot, 1); 3106 if (!fAERRoot) break; 3107 bzero(fAERRoot, sizeof(IOPCIAERRoot)); 3108 fAERRoot->fISRErrors = IONew(IOPCIAERISREntry, kAERISRNum); 3109 if (!fAERRoot->fISRErrors) break; 3110 } 3111 3112 if (fHotPlugInts) 3113 { 3114 fPresence = (0 != fBridgeDevice->getProperty(kIOPCIOnlineKey)); 3115 fPresenceInt = fPresence; 3116 } 3117 3118 fBridgeInterruptEnablePending = true; 3119 enableBridgeInterrupts(); 3120 } 3121 while(false); 3122} 3123 3124void IOPCI2PCIBridge::enableBridgeInterrupts(void) 3125{ 3126 if (fHotPlugInts) 3127 { 3128 uint16_t slotControl = fBridgeDevice->configRead16( fBridgeDevice->reserved->expressCapability + 0x18 ); 3129 fBridgeDevice->configWrite16( fBridgeDevice->reserved->expressCapability + 0x1a, 1 << 3 ); 3130 slotControl |= kSlotControlEnables; 3131 fBridgeDevice->configWrite16( fBridgeDevice->reserved->expressCapability + 0x18, slotControl ); 3132 } 3133 if (fIsAERRoot) 3134 { 3135 DLOG("%s: start AER\n", fBridgeDevice->getName()); 3136 uint16_t command = fBridgeDevice->configRead32(fBridgeDevice->reserved->aerCapability + 0x2c); 3137 fBridgeDevice->configWrite32(fBridgeDevice->reserved->aerCapability + 0x30, 0xff); 3138 command |= (1 << 0) | (1 << 1) | (1 << 2); 3139 fBridgeDevice->configWrite32(fBridgeDevice->reserved->aerCapability + 0x2c, command); 3140 } 3141} 3142 3143void IOPCI2PCIBridge::disableBridgeInterrupts(void) 3144{ 3145 if (fHotPlugInts) 3146 { 3147 uint16_t slotControl = fBridgeDevice->configRead16( fBridgeDevice->reserved->expressCapability + 0x18 ); 3148 slotControl &= ~kSlotControlEnables; 3149 fBridgeDevice->configWrite16( fBridgeDevice->reserved->expressCapability + 0x18, slotControl ); 3150 } 3151 if (fIsAERRoot) 3152 { 3153 fBridgeDevice->configWrite32(fBridgeDevice->reserved->aerCapability + 0x2c, 0); 3154 } 3155} 3156 3157 3158void IOPCI2PCIBridge::startBootDefer(IOService * provider) 3159{ 3160 DLOG("%s: start boot deferred\n", provider->getName()); 3161 provider->removeProperty(kIOPCITunnelBootDeferKey); 3162 startBridgeInterrupts(provider); 3163 if (fBridgeInterruptEnablePending) 3164 { 3165 // enable int source 3166 fBridgeInterruptSource->enable(); 3167 fBridgeInterruptSource->signalInterrupt(); 3168 fBridgeInterruptEnablePending = false; 3169 } 3170} 3171 3172void IOPCI2PCIBridge::probeBus( IOService * provider, UInt8 busNum ) 3173{ 3174 bool bootDefer = (0 != provider->getProperty(kIOPCITunnelBootDeferKey)); 3175 if (!bootDefer) 3176 { 3177 snprintf(fLogName, sizeof(fLogName), "%s(%u:%u:%u)(%u-%u)", 3178 fBridgeDevice->getName(), PCI_ADDRESS_TUPLE(fBridgeDevice), firstBusNum(), lastBusNum()); 3179 super::probeBus(provider, busNum); 3180 if (fBridgeInterruptEnablePending) 3181 { 3182 // enable hotp ints 3183 fBridgeInterruptSource->enable(); 3184 fBridgeInterruptSource->signalInterrupt(); 3185 fBridgeInterruptEnablePending = false; 3186 } 3187 return; 3188 } 3189 3190 DLOG("%s: boot probe deferred\n", provider->getName()); 3191#if 0 3192 startBootDefer(provider); 3193#endif 3194} 3195 3196IOReturn IOPCI2PCIBridge::requestProbe( IOOptionBits options ) 3197{ 3198 return (super::requestProbe(options)); 3199} 3200 3201IOReturn IOPCI2PCIBridge::setPowerState( unsigned long powerState, 3202 IOService * whatDevice ) 3203{ 3204 IOReturn ret; 3205 3206 if ((powerState != fPowerState) 3207 && fBridgeInterruptSource 3208 && !fBridgeInterruptEnablePending) 3209 do 3210 { 3211 unsigned long fromPowerState; 3212 3213 fromPowerState = fPowerState; 3214 fPowerState = powerState; 3215 3216 if (kIOPCIDeviceOffState == powerState) 3217 { 3218 if (fHotPlugInts && fNeedProbe) DLOG("%s: sleeping with fNeedProbe\n", fLogName); 3219 disableBridgeInterrupts(); 3220 break; 3221 } 3222 if (kIOPCIDeviceOffState == fromPowerState) 3223 { 3224 if (fHotPlugInts) 3225 { 3226 if (fNoDevice) break; 3227 ret = checkLink(); 3228 if (kIOReturnNoDevice == ret) 3229 { 3230 fNoDevice = true; 3231 break; 3232 } 3233 fNeedProbe |= fPresence; 3234 OSBitOrAtomic8(kIntsHP, &fIntsPending); 3235 } 3236 enableBridgeInterrupts(); 3237 } 3238 if (kIOPCIDeviceOnState == powerState) 3239 { 3240 if (fBridgeDevice->reserved->needsProbe) deferredProbe(fBridgeDevice); 3241 fBridgeInterruptSource->signalInterrupt(); 3242 } 3243 } 3244 while (false); 3245 3246 return (super::setPowerState(powerState, whatDevice)); 3247} 3248 3249void IOPCI2PCIBridge::adjustPowerState(unsigned long state) 3250{ 3251 DLOG("%s: adjustPowerState(%ld)\n", fBridgeDevice->getName(), state); 3252 if (state < kIOPCIDeviceOnState) 3253 { 3254 fBridgeDevice->powerOverrideOnPriv(); 3255 } 3256 else 3257 { 3258 state = kIOPCIDeviceOnState; 3259 fBridgeDevice->powerOverrideOffPriv(); 3260 } 3261 3262 fBridgeDevice->changePowerStateToPriv(state); 3263} 3264 3265IOReturn IOPCI2PCIBridge::saveDeviceState(IOPCIDevice * device, 3266 IOOptionBits options) 3267{ 3268 // bridge flags 3269 if (device->getProperty(kIOPMPCISleepLinkDisableKey)) 3270 configShadow(fBridgeDevice)->flags |= kIOPCIConfigShadowSleepLinkDisable; 3271 else 3272 configShadow(fBridgeDevice)->flags &= ~kIOPCIConfigShadowSleepLinkDisable; 3273 if (device->getProperty(kIOPMPCISleepResetKey)) 3274 configShadow(fBridgeDevice)->flags |= kIOPCIConfigShadowSleepReset; 3275 else 3276 configShadow(fBridgeDevice)->flags &= ~kIOPCIConfigShadowSleepReset; 3277 if (device->getProperty(gIOPCITunnelledKey) || device->getProperty(kIOPCIEjectableKey)) 3278 configShadow(fBridgeDevice)->flags |= kIOPCIConfigShadowHotplug; 3279 else 3280 configShadow(fBridgeDevice)->flags &= ~kIOPCIConfigShadowHotplug; 3281 3282 // device flags 3283 if (device->getProperty(kIOPMPCIWakeL1PMDisableKey)) 3284 configShadow(device)->flags |= kIOPCIConfigShadowWakeL1PMDisable; 3285 else 3286 configShadow(device)->flags &= ~kIOPCIConfigShadowWakeL1PMDisable; 3287 3288 3289 return super::saveDeviceState(device, options); 3290} 3291 3292void IOPCI2PCIBridge::stop( IOService * provider ) 3293{ 3294 super::stop( provider); 3295 3296 IOWorkLoop * tempWL; 3297 if (fBridgeInterruptSource) 3298 { 3299 fBridgeInterruptSource->disable(); 3300 if ((tempWL = fBridgeInterruptSource->getWorkLoop())) 3301 tempWL->removeEventSource(fBridgeInterruptSource); 3302 fBridgeInterruptSource->release(); 3303 fBridgeInterruptSource = 0; 3304 } 3305 if (fTimerProbeES) 3306 { 3307 fTimerProbeES->cancelTimeout(); 3308 if ((tempWL = fTimerProbeES->getWorkLoop())) 3309 tempWL->removeEventSource(fTimerProbeES); 3310 fTimerProbeES->release(); 3311 fTimerProbeES = 0; 3312 } 3313 if (kIOPMUndefinedDriverAssertionID != fPMAssertion) 3314 { 3315 getPMRootDomain()->releasePMAssertion(fPMAssertion); 3316 fPMAssertion = kIOPMUndefinedDriverAssertionID; 3317 } 3318 if (fISRLock) 3319 { 3320 IOSimpleLockFree(fISRLock); 3321 fISRLock = 0; 3322 } 3323 if (fAERRoot) 3324 { 3325 if (fAERRoot->fISRErrors) IODelete(fAERRoot->fISRErrors, IOPCIAERISREntry, kAERISRNum); 3326 IODelete(fAERRoot, IOPCIAERRoot, 1); 3327 } 3328} 3329 3330void IOPCI2PCIBridge::free() 3331{ 3332 super::free(); 3333} 3334 3335void IOPCI2PCIBridge::saveBridgeState( void ) 3336{ 3337} 3338 3339void IOPCI2PCIBridge::restoreBridgeState( void ) 3340{ 3341} 3342 3343UInt8 IOPCI2PCIBridge::firstBusNum( void ) 3344{ 3345 return fBridgeDevice->configRead8( kPCI2PCISecondaryBus ); 3346} 3347 3348UInt8 IOPCI2PCIBridge::lastBusNum( void ) 3349{ 3350 return fBridgeDevice->configRead8( kPCI2PCISubordinateBus ); 3351} 3352 3353IOPCIAddressSpace IOPCI2PCIBridge::getBridgeSpace( void ) 3354{ 3355 return (fBridgeDevice->space); 3356} 3357 3358UInt32 IOPCI2PCIBridge::configRead32( IOPCIAddressSpace space, 3359 UInt8 offset ) 3360{ 3361 return (fBridgeDevice->configRead32(space, offset)); 3362} 3363 3364void IOPCI2PCIBridge::configWrite32( IOPCIAddressSpace space, 3365 UInt8 offset, UInt32 data ) 3366{ 3367 fBridgeDevice->configWrite32( space, offset, data ); 3368} 3369 3370UInt16 IOPCI2PCIBridge::configRead16( IOPCIAddressSpace space, 3371 UInt8 offset ) 3372{ 3373 return (fBridgeDevice->configRead16(space, offset)); 3374} 3375 3376void IOPCI2PCIBridge::configWrite16( IOPCIAddressSpace space, 3377 UInt8 offset, UInt16 data ) 3378{ 3379 fBridgeDevice->configWrite16( space, offset, data ); 3380} 3381 3382UInt8 IOPCI2PCIBridge::configRead8( IOPCIAddressSpace space, 3383 UInt8 offset ) 3384{ 3385 return (fBridgeDevice->configRead8(space, offset)); 3386} 3387 3388void IOPCI2PCIBridge::configWrite8( IOPCIAddressSpace space, 3389 UInt8 offset, UInt8 data ) 3390{ 3391 fBridgeDevice->configWrite8( space, offset, data ); 3392} 3393 3394IODeviceMemory * IOPCI2PCIBridge::ioDeviceMemory( void ) 3395{ 3396 return (fBridgeDevice->ioDeviceMemory()); 3397} 3398 3399bool IOPCI2PCIBridge::publishNub( IOPCIDevice * nub, UInt32 index ) 3400{ 3401 if (nub) 3402 nub->setProperty( "IOChildIndex" , index, 32 ); 3403 3404 return (super::publishNub(nub, index)); 3405} 3406 3407 3408IOReturn IOPCIBridge::resolveMSIInterrupts( IOService * provider, IOPCIDevice * nub ) 3409{ 3410 IOReturn ret = kIOReturnUnsupported; 3411 3412 if (!(kIOPCIConfiguratorTBMSIEnable & gIOPCIFlags) 3413 && nub->getProperty(gIOPCITunnelledKey)) 3414 { 3415 return (ret); 3416 } 3417 3418 if (reserved && !reserved->messagedInterruptController) 3419 { 3420 callPlatformFunction(gIOPlatformGetMessagedInterruptControllerKey, false, 3421 (void *)provider, 3422 (void *)&reserved->messagedInterruptController, 3423 (void *)0, (void *)0); 3424 } 3425 3426#if USE_MSI 3427 3428 IOByteCount msiCapability = nub->reserved->msiCapability; 3429 if (msiCapability && reserved && reserved->messagedInterruptController) 3430 { 3431 ret = reserved->messagedInterruptController->allocateDeviceInterrupts( 3432 nub, 0, msiCapability); 3433 } 3434 3435#endif /* USE_MSI */ 3436 3437 return (ret); 3438} 3439 3440IOReturn IOPCIBridge::resolveLegacyInterrupts( IOService * provider, IOPCIDevice * nub ) 3441{ 3442#if USE_LEGACYINTS 3443 3444 uint32_t pin; 3445 uint32_t irq = 0; 3446 3447 pin = nub->configRead8( kIOPCIConfigInterruptPin ); 3448 if ( pin == 0 || pin > 4 ) 3449 return (kIOReturnUnsupported); // assume no interrupt usage 3450 3451 pin--; // make pin zero based, INTA=0, INTB=1, INTC=2, INTD=3 3452 3453 // Ask the platform driver to resolve the PCI interrupt route, 3454 // and return its corresponding system interrupt vector. 3455 3456 if ( kIOReturnSuccess == provider->callPlatformFunction(gIOPlatformResolvePCIInterruptKey, 3457 /* waitForFunction */ false, 3458 /* provider nub */ provider, 3459 /* device number */ (void *)(uintptr_t) nub->space.s.deviceNum, 3460 /* interrupt pin */ (void *)(uintptr_t) pin, 3461 /* resolved IRQ */ &irq )) 3462 { 3463 DLOG("%s: Resolved interrupt %d (%d) for %s\n", 3464 provider->getName(), 3465 irq, pin, 3466 nub->getName()); 3467 3468 nub->configWrite8( kIOPCIConfigInterruptLine, irq & 0xff ); 3469 } 3470 else 3471 { 3472 irq = nub->configRead8( kIOPCIConfigInterruptLine ); 3473 if ( 0 == irq || 0xff == irq ) return (kIOReturnUnsupported); 3474 irq &= 0xf; // what about IO-APIC and irq > 15? 3475 } 3476 3477 provider->callPlatformFunction(gIOPlatformSetDeviceInterruptsKey, 3478 /* waitForFunction */ false, 3479 /* nub */ nub, 3480 /* vectors */ (void *) &irq, 3481 /* vectorCount */ (void *) 1, 3482 /* exclusive */ (void *) false ); 3483 3484#endif /* USE_LEGACYINTS */ 3485 3486 return (kIOReturnSuccess); 3487} 3488 3489/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3490 3491IOPCIEventSource * IOPCIBridge::createEventSource( 3492 OSObject * owner, IOPCIEventSource::Action action, uint32_t options) 3493{ 3494 IOPCIEventSource * src; 3495 bool ok = false; 3496 3497 src = OSTypeAlloc(IOPCIEventSource); 3498 if (!src) return (0); 3499 do 3500 { 3501 if (!src->init(owner, (IOEventSource::Action) action)) break; 3502 src->fEvents = IONew(IOPCIEvent, kIOPCIEventNum); 3503 if (!src->fEvents) break; 3504 src->fRoot = 0; 3505 src->fDevice = 0; 3506 ok = true; 3507 } 3508 while (false); 3509 3510 if (!ok) 3511 { 3512 src->release(); 3513 src = 0; 3514 } 3515 return (src); 3516} 3517 3518IOPCIEventSource * IOPCIBridge::createEventSource(IOPCIDevice * device, 3519 OSObject * owner, IOPCIEventSource::Action action, uint32_t options) 3520{ 3521 return (0); 3522} 3523 3524IOPCIEventSource * IOPCI2PCIBridge::createEventSource(IOPCIDevice * device, 3525 OSObject * owner, IOPCIEventSource::Action action, uint32_t options) 3526{ 3527 IOPCIEventSource * src; 3528 3529 if (!fIsAERRoot) return (fBridgeDevice->parent->createEventSource(device, owner, action, options)); 3530 3531 src = IOPCIBridge::createEventSource(owner, action, options); 3532 if (src) 3533 { 3534 src->fRoot = this; 3535 src->fDevice = device; 3536 if (device) device->retain(); 3537 } 3538 3539 return (src); 3540} 3541 3542/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3543 3544#undef super 3545#define super IOEventSource 3546 3547OSDefineMetaClassAndStructors(IOPCIEventSource, IOEventSource) 3548 3549void IOPCIEventSource::free(void) 3550{ 3551 IOPCIEvent event; 3552 uint32_t nextIdx; 3553 3554 if (fEvents) 3555 { 3556 IOSimpleLockLock(gIOPCIEventSourceLock); 3557 while (fReadIndex != fWriteIndex) 3558 { 3559 event = fEvents[fReadIndex]; 3560 nextIdx = fReadIndex + 1; 3561 if (nextIdx == kIOPCIEventNum) nextIdx = 0; 3562 fReadIndex = nextIdx; 3563 if (event.reporter) 3564 { 3565 IOSimpleLockUnlock(gIOPCIEventSourceLock); 3566 event.reporter->release(); 3567 IOSimpleLockLock(gIOPCIEventSourceLock); 3568 } 3569 } 3570 IOSimpleLockUnlock(gIOPCIEventSourceLock); 3571 IODelete(fEvents, IOPCIEvent, kIOPCIEventNum); 3572 } 3573 3574 if (fDevice) fDevice->release(); 3575 super::free(); 3576} 3577 3578void IOPCIEventSource::enable() 3579{ 3580 super::enable(); 3581 IOSimpleLockLock(gIOPCIEventSourceLock); 3582 if (!fQ.next) queue_enter(&gIOPCIEventSourceQueue, this, IOPCIEventSource *, fQ); 3583 IOSimpleLockUnlock(gIOPCIEventSourceLock); 3584} 3585 3586void IOPCIEventSource::disable() 3587{ 3588 super::disable(); 3589 IOSimpleLockLock(gIOPCIEventSourceLock); 3590 if (fQ.next) 3591 { 3592 queue_remove(&gIOPCIEventSourceQueue, this, IOPCIEventSource *, fQ); 3593 fQ.next = 0; 3594 } 3595 IOSimpleLockUnlock(gIOPCIEventSourceLock); 3596} 3597 3598bool IOPCIEventSource::checkForWork(void) 3599{ 3600 IOPCIEventAction pciAction = (IOPCIEventAction) action; 3601 IOPCIEvent event; 3602 uint32_t nextIdx; 3603 3604 IOSimpleLockLock(gIOPCIEventSourceLock); 3605 while (enabled && (fReadIndex != fWriteIndex)) 3606 { 3607 event = fEvents[fReadIndex]; 3608 nextIdx = fReadIndex + 1; 3609 if (nextIdx == kIOPCIEventNum) nextIdx = 0; 3610 fReadIndex = nextIdx; 3611 IOSimpleLockUnlock(gIOPCIEventSourceLock); 3612 (*pciAction)(owner, this, &event); 3613 if (event.reporter) event.reporter->release(); 3614 IOSimpleLockLock(gIOPCIEventSourceLock); 3615 } 3616 IOSimpleLockUnlock(gIOPCIEventSourceLock); 3617 3618 return (false); 3619} 3620 3621/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3622 3623#undef super 3624#define super IOService 3625 3626static void 3627PCIEventTest(OSObject * owner, IOPCIEventSource * es, const IOPCIEvent * event ) 3628{ 3629 kprintf("PCIEventTest %s, 0x%08qx : 0x%08x 0x%08x, 0x%08x 0x%08x 0x%08x 0x%08x\n", 3630 event->reporter->getName(), event->reporter->getRegistryEntryID(), 3631 event->event, event->data[0], 3632 event->data[1], event->data[2], event->data[3], event->data[4]); 3633} 3634 3635IOReturn 3636IOPCIBridge::setProperties(OSObject * properties) 3637{ 3638 IOReturn ret = kIOReturnUnsupported; 3639 OSDictionary * dict; 3640 OSDictionary * matching; 3641 OSArray * array; 3642 OSString * str; 3643 IOService * victimS = 0; 3644 IOPCIDevice * victim = 0; 3645 const char * cmdstr; 3646 uint64_t arg = 0; 3647 3648 dict = OSDynamicCast(OSDictionary, properties); 3649 if (dict 3650 && (array = OSDynamicCast(OSArray, dict->getObject(kIODebugArgumentsKey))) 3651 && (str = OSDynamicCast(OSString, array->getObject(0)))) 3652 { 3653 ret = IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator); 3654 if (kIOReturnSuccess != ret) return (ret); 3655 3656 cmdstr = str->getCStringNoCopy(); 3657 kprintf("pcicmd: %s\n", cmdstr); 3658 3659 str = OSDynamicCast(OSString, array->getObject(1)); 3660 3661 if (!strncmp("find", cmdstr, strlen("find"))) 3662 { 3663 IOPCIAddressSpace space; 3664 IOService * result; 3665 3666 space.s.busNum = strtoq(str ? str->getCStringNoCopy() : 0, NULL, 0); 3667 str = OSDynamicCast(OSString, array->getObject(2)); 3668 space.s.deviceNum = strtoq(str ? str->getCStringNoCopy() : 0, NULL, 0);; 3669 str = OSDynamicCast(OSString, array->getObject(3)); 3670 space.s.functionNum = strtoq(str ? str->getCStringNoCopy() : 0, NULL, 0);; 3671 IOReturn ret = configOp(NULL, kConfigOpFindEntry, &result, &space); 3672 kprintf("%d %d %d: find %x %p %s 0x%qx\n", 3673 space.s.busNum, space.s.deviceNum, space.s.functionNum, ret, result, 3674 result ? result->getName() : "", 3675 result ? result->getRegistryEntryID() : 0); 3676 3677 } 3678 else if (!strcmp("esg", cmdstr)) 3679 { 3680 IOPCIEventSource * src = createEventSource(this, &PCIEventTest, 0); 3681 getWorkLoop()->addEventSource(src); 3682 src->enable(); 3683 IOSleep(10*1000); 3684 getWorkLoop()->removeEventSource(src); 3685 src->release(); 3686 } 3687 else if (str) 3688 { 3689 arg = strtoq(str->getCStringNoCopy(), NULL, 0); 3690 if (arg) matching = registryEntryIDMatching(arg); 3691 else matching = nameMatching(str->getCStringNoCopy()); 3692 victimS = copyMatchingService(matching); 3693 matching->release(); 3694 victim = OSDynamicCast(IOPCIDevice, victimS); 3695 } 3696 if (victim) 3697 { 3698 if (!strncmp("pause", cmdstr, strlen("pause"))) 3699 { 3700 victim->reserved->pauseFlags = true; 3701 if ('d' == cmdstr[strlen("pause")]) victim->reserved->pauseFlags++; 3702 configOp(victim, kConfigOpTestPause, NULL); 3703 ret = kIOReturnSuccess; 3704 } 3705 else if (!strcmp("unpause", cmdstr)) 3706 { 3707 victim->changePowerStateToPriv(kIOPCIDeviceOnState); 3708 victim->powerOverrideOffPriv(); 3709 ret = kIOReturnSuccess; 3710 } 3711 else if (!strcmp("reset", cmdstr)) 3712 { 3713 uint16_t control; 3714 control = victim->configRead16(kPCI2PCIBridgeControl); 3715 control |= (1 << 6); 3716 victim->configWrite16(kPCI2PCIBridgeControl, control); 3717 IOSleep(10); 3718 control &= ~(1 << 6); 3719 victim->configWrite16(kPCI2PCIBridgeControl, control); 3720 ret = kIOReturnSuccess; 3721 } 3722 else if (!strncmp("gen", cmdstr, strlen("gen"))) 3723 { 3724 uint16_t control; 3725 control = (('1' == cmdstr[strlen("gen")]) ? 1 : 2); 3726 control |= 0x30; 3727 victim->configWrite16(victim->reserved->expressCapability + 0x30, control); 3728 control = victim->configRead16(victim->reserved->expressCapability + 0x10); 3729 control |= (1 << 5); 3730 victim->configWrite16(victim->reserved->expressCapability + 0x10, control); 3731 IOSleep(100); 3732 kprintf("link speed %d\n", (15 & victim->configRead16(victim->reserved->expressCapability + 0x12))); 3733 ret = kIOReturnSuccess; 3734 } 3735 else if (!strcmp("ltr", cmdstr)) 3736 { 3737 IOOptionBits type = 0; 3738 uint64_t nsecs = 0; 3739 str = OSDynamicCast(OSString, array->getObject(2)); 3740 if (str) type = strtoq(str->getCStringNoCopy(), NULL, 0); 3741 str = OSDynamicCast(OSString, array->getObject(3)); 3742 if (str) nsecs = strtoq(str->getCStringNoCopy(), NULL, 0); 3743 ret = victim->setLatencyTolerance(type, nsecs); 3744 kprintf("setLatencyTolerance 0x%x\n", ret); 3745 ret = kIOReturnSuccess; 3746 } 3747 else if (!strcmp("cycle", cmdstr)) 3748 { 3749 uint32_t idx, did; 3750 IOPCIBridge * bridge; 3751 IOPCIBridge * pbridge; 3752 IOPCIDevice * parent; 3753 bridge = OSDynamicCast(IOPCIBridge, victim->getProvider()); 3754 parent = OSDynamicCast(IOPCIDevice, bridge->getProvider()); 3755 pbridge = OSDynamicCast(IOPCIBridge, parent->getProvider()); 3756 3757 for (idx = 0; idx < 100; idx++) 3758 { 3759 bridge->setDevicePowerState(victim, 0, kIOPCIDeviceOnState, kIOPCIDeviceOffState); 3760 pbridge->setDevicePowerState(parent, 0, kIOPCIDeviceOnState, kIOPCIDeviceOffState); 3761 pbridge->setDevicePowerState(parent, 0, kIOPCIDeviceOffState, kIOPCIDeviceOnState); 3762 bridge->setDevicePowerState(victim, 0, kIOPCIDeviceOffState, kIOPCIDeviceOnState); 3763 did = victim->configRead32(0); 3764 if (0xffffffff == did) panic("did"); 3765 } 3766 ret = kIOReturnSuccess; 3767 } 3768 else if (!strcmp("es", cmdstr)) 3769 { 3770 IOPCIEventSource * src = victim->createEventSource(this, &PCIEventTest, 0); 3771 victim->getWorkLoop()->addEventSource(src); 3772 src->enable(); 3773 IOSleep(10*1000); 3774 victim->getWorkLoop()->removeEventSource(src); 3775 src->release(); 3776 } 3777 else if (!strcmp("l1ena", cmdstr)) 3778 { 3779 ret = victim->setTunnelL1Enable(victim, true); 3780 } 3781 else if (!strcmp("l1dis", cmdstr)) 3782 { 3783 ret = victim->setTunnelL1Enable(victim, false); 3784 } 3785 } 3786 if (victimS) victimS->release(); 3787 } 3788 else ret = super::setProperties(properties); 3789 3790 return (ret); 3791} 3792/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3793 3794IOReturn 3795IOPCIBridge::newUserClient(task_t owningTask, void * securityID, 3796 UInt32 type, OSDictionary * properties, 3797 IOUserClient ** handler) 3798{ 3799 IOPCIDiagnosticsClient * uc; 3800 bool ok; 3801 int bootArg; 3802 3803 if (type != kIOPCIDiagnosticsClientType) 3804 return (super::newUserClient(owningTask, securityID, type, properties, handler)); 3805 3806 ok = false; 3807 uc = NULL; 3808 do 3809 { 3810 if (kIOReturnSuccess != IOUserClient::clientHasPrivilege( 3811 securityID, kIOClientPrivilegeAdministrator)) break; 3812 if (!PE_parse_boot_argn("debug", &bootArg, sizeof(bootArg)) || !bootArg) break; 3813 3814 uc = OSTypeAlloc(IOPCIDiagnosticsClient); 3815 if (!uc) break; 3816 ok = uc->initWithTask(owningTask, securityID, type, properties); 3817 uc->owner = this; 3818 if (!ok) break; 3819 ok = uc->attach(this); 3820 if (!ok) break; 3821 ok = uc->start(this); 3822 } 3823 while (false); 3824 3825 if (ok) 3826 { 3827 *handler = uc; 3828 return (kIOReturnSuccess); 3829 } 3830 else 3831 { 3832 if (uc && uc->inPlane(gIOServicePlane)) 3833 uc->detach(this); 3834 if (uc) uc->release(); 3835 *handler = NULL; 3836 return (kIOReturnUnsupported); 3837 } 3838} 3839 3840/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3841 3842#undef super 3843#define super IOUserClient 3844 3845OSDefineMetaClassAndStructors(IOPCIDiagnosticsClient, IOUserClient) 3846 3847/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3848 3849IOReturn IOPCIDiagnosticsClient::clientClose(void) 3850{ 3851 terminate(); 3852 return (kIOReturnSuccess); 3853} 3854 3855IOService * IOPCIDiagnosticsClient::getService(void) 3856{ 3857 return (owner); 3858} 3859 3860IOReturn IOPCIDiagnosticsClient::setProperties(OSObject * properties) 3861{ 3862 IOReturn kr = kIOReturnUnsupported; 3863 return (kr); 3864} 3865 3866IOReturn IOPCIDiagnosticsClient::externalMethod(uint32_t selector, IOExternalMethodArguments * args, 3867 IOExternalMethodDispatch * dispatch, OSObject * target, void * reference) 3868{ 3869 IOReturn ret = kIOReturnBadArgument; 3870 IOPCIDiagnosticsParameters * params; 3871 IOMemoryDescriptor * md; 3872 IOMemoryMap * map; 3873 void * vmaddr; 3874 3875 switch (selector) 3876 { 3877 case kIOPCIDiagnosticsMethodWrite: 3878 if (args->structureInputSize != sizeof(IOPCIDiagnosticsParameters)) return (kIOReturnBadArgument); 3879 3880 params = (typeof(params)) args->structureInput; 3881 break; 3882 3883 case kIOPCIDiagnosticsMethodRead: 3884 if (args->structureInputSize != sizeof(IOPCIDiagnosticsParameters)) return (kIOReturnBadArgument); 3885 if (args->structureOutputSize != sizeof(IOPCIDiagnosticsParameters)) return (kIOReturnBadArgument); 3886 3887 bcopy(args->structureInput, args->structureOutput, sizeof(IOPCIDiagnosticsParameters)); 3888 params = (typeof(params)) args->structureOutput; 3889 break; 3890 3891 default: 3892 return (kIOReturnBadArgument); 3893 break; 3894 } 3895 3896 map = 0; 3897 vmaddr = 0; 3898 if (kIOPCI64BitMemorySpace == params->spaceType) 3899 { 3900 md = IOMemoryDescriptor::withAddressRange(params->address.addr64, 3901 (params->bitWidth >> 3), kIODirectionOutIn | kIOMemoryMapperNone, NULL); 3902 if (md) 3903 { 3904 map = md->map(); 3905 md->release(); 3906 } 3907 if (!map) return (kIOReturnVMError); 3908 vmaddr = (void *)(uintptr_t) map->getAddress(); 3909 } 3910 3911 switch (selector) 3912 { 3913 case kIOPCIDiagnosticsMethodWrite: 3914 3915 if (kIOPCI64BitMemorySpace == params->spaceType) 3916 { 3917 switch (params->bitWidth) 3918 { 3919 case 8: 3920 *((uint8_t *) vmaddr) = params->value; 3921 ret = kIOReturnSuccess; 3922 break; 3923 case 16: 3924 *((uint16_t *) vmaddr) = params->value; 3925 ret = kIOReturnSuccess; 3926 break; 3927 case 32: 3928 *((uint32_t *) vmaddr) = params->value; 3929 ret = kIOReturnSuccess; 3930 break; 3931 case 64: 3932 *((uint64_t *) vmaddr) = params->value; 3933 ret = kIOReturnSuccess; 3934 break; 3935 default: 3936 break; 3937 } 3938 } 3939 else if (kIOPCIConfigSpace == params->spaceType) 3940 { 3941 IOPCIAddressSpace space; 3942 space.bits = 0; 3943 space.es.busNum = params->address.pci.bus; 3944 space.es.deviceNum = params->address.pci.device; 3945 space.es.functionNum = params->address.pci.function; 3946 space.es.registerNumExtended = (0xF & (params->address.pci.offset >> 8)); 3947 switch (params->bitWidth) 3948 { 3949 case 8: 3950 owner->configWrite8(space, params->address.pci.offset, params->value); 3951 ret = kIOReturnSuccess; 3952 break; 3953 case 16: 3954 owner->configWrite16(space, params->address.pci.offset, params->value); 3955 ret = kIOReturnSuccess; 3956 break; 3957 case 32: 3958 owner->configWrite32(space, params->address.pci.offset, params->value); 3959 ret = kIOReturnSuccess; 3960 break; 3961 default: 3962 break; 3963 } 3964 } 3965 break; 3966 3967 case kIOPCIDiagnosticsMethodRead: 3968 3969 if (kIOPCI64BitMemorySpace == params->spaceType) 3970 { 3971 switch (params->bitWidth) 3972 { 3973 case 8: 3974 params->value = *((uint8_t *) vmaddr); 3975 ret = kIOReturnSuccess; 3976 break; 3977 case 16: 3978 params->value = *((uint16_t *) vmaddr); 3979 ret = kIOReturnSuccess; 3980 break; 3981 case 32: 3982 params->value = *((uint32_t *) vmaddr); 3983 ret = kIOReturnSuccess; 3984 break; 3985 case 64: 3986 params->value = *((uint64_t *) vmaddr); 3987 ret = kIOReturnSuccess; 3988 break; 3989 default: 3990 break; 3991 } 3992 } 3993 else if (kIOPCIConfigSpace == params->spaceType) 3994 { 3995 IOPCIAddressSpace space; 3996 space.bits = 0; 3997 space.es.busNum = params->address.pci.bus; 3998 space.es.deviceNum = params->address.pci.device; 3999 space.es.functionNum = params->address.pci.function; 4000 space.es.registerNumExtended = (0xF & (params->address.pci.offset >> 8)); 4001 switch (params->bitWidth) 4002 { 4003 case 8: 4004 params->value = owner->configRead8(space, params->address.pci.offset); 4005 ret = kIOReturnSuccess; 4006 break; 4007 case 16: 4008 params->value = owner->configRead16(space, params->address.pci.offset); 4009 ret = kIOReturnSuccess; 4010 break; 4011 case 32: 4012 params->value = owner->configRead32(space, params->address.pci.offset); 4013 ret = kIOReturnSuccess; 4014 break; 4015 default: 4016 break; 4017 } 4018 } 4019 break; 4020 4021 default: 4022 break; 4023 } 4024 4025 if (map) map->release(); 4026 4027 return (ret); 4028} 4029 4030/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 4031 4032