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#define __IOPCIDEVICE_INTERNAL__ 1 24 25#include <IOKit/system.h> 26 27#include <IOKit/pci/IOPCIBridge.h> 28#include <IOKit/pci/IOPCIPrivate.h> 29#include <IOKit/pci/IOAGPDevice.h> 30#include <IOKit/pci/IOPCIConfigurator.h> 31#include <IOKit/pci/IOPCIPrivate.h> 32#include <IOKit/IOPlatformExpert.h> 33#include <IOKit/IODeviceTreeSupport.h> 34#include <IOKit/IOUserClient.h> 35 36#include <IOKit/IOLib.h> 37#include <IOKit/assert.h> 38 39#include <libkern/c++/OSContainers.h> 40#include <libkern/version.h> 41 42#if ACPI_SUPPORT 43#include <IOKit/acpi/IOACPIPlatformDevice.h> 44#endif 45 46#ifndef VERSION_MAJOR 47#error VERSION_MAJOR 48#endif 49 50enum 51{ 52 // reserved->pmSleepEnabled 53 kPMEnable = 0x01, 54 kPMEOption = 0x02 55}; 56 57#define DLOG(fmt, args...) \ 58 do { \ 59 if ((gIOPCIFlags & kIOPCIConfiguratorIOLog) && !ml_at_interrupt_context()) \ 60 IOLog(fmt, ## args); \ 61 if (gIOPCIFlags & kIOPCIConfiguratorKPrintf) \ 62 kprintf(fmt, ## args); \ 63 } while(0) 64 65 66/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 67 68#define super IOService 69 70OSDefineMetaClassAndStructors(IOPCIDevice, IOService) 71OSMetaClassDefineReservedUnused(IOPCIDevice, 3); 72OSMetaClassDefineReservedUnused(IOPCIDevice, 4); 73OSMetaClassDefineReservedUnused(IOPCIDevice, 5); 74OSMetaClassDefineReservedUnused(IOPCIDevice, 6); 75OSMetaClassDefineReservedUnused(IOPCIDevice, 7); 76OSMetaClassDefineReservedUnused(IOPCIDevice, 8); 77OSMetaClassDefineReservedUnused(IOPCIDevice, 9); 78OSMetaClassDefineReservedUnused(IOPCIDevice, 10); 79OSMetaClassDefineReservedUnused(IOPCIDevice, 11); 80OSMetaClassDefineReservedUnused(IOPCIDevice, 12); 81OSMetaClassDefineReservedUnused(IOPCIDevice, 13); 82OSMetaClassDefineReservedUnused(IOPCIDevice, 14); 83OSMetaClassDefineReservedUnused(IOPCIDevice, 15); 84 85/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 86 87//********************************************************************************* 88// [public] maxCapabilityForDomainState 89// 90// Finds the highest power state in the array whose input power 91// requirement is equal to the input parameter. Where a more intelligent 92// decision is possible, override this in the subclassed driver. 93//********************************************************************************* 94 95unsigned long 96IOPCIDevice::maxCapabilityForDomainState ( IOPMPowerFlags domainState ) 97{ 98 if (domainState & kIOPMPowerOn) return (kIOPCIDeviceOnState); 99 if (domainState & kIOPMSoftSleep) return (kIOPCIDeviceDozeState); 100 if (domainState & kIOPMConfigRetained) return (kIOPCIDevicePausedState); 101 return (kIOPCIDeviceOffState); 102} 103 104//********************************************************************************* 105// [public] initialPowerStateForDomainState 106// 107// Finds the highest power state in the array whose input power 108// requirement is equal to the input parameter. Where a more intelligent 109// decision is possible, override this in the subclassed driver. 110//********************************************************************************* 111 112unsigned long 113IOPCIDevice::initialPowerStateForDomainState ( IOPMPowerFlags domainState ) 114{ 115 if (domainState & kIOPMPowerOn) return (kIOPCIDeviceOnState); 116 if (domainState & kIOPMSoftSleep) return (kIOPCIDeviceDozeState); 117 if (domainState & kIOPMConfigRetained) return (kIOPCIDevicePausedState); 118 return (kIOPCIDeviceOffState); 119} 120 121//********************************************************************************* 122// [public] powerStateForDomainState 123// 124// Finds the highest power state in the array whose input power 125// requirement is equal to the input parameter. Where a more intelligent 126// decision is possible, override this in the subclassed driver. 127//********************************************************************************* 128 129unsigned long 130IOPCIDevice::powerStateForDomainState ( IOPMPowerFlags domainState ) 131{ 132 if (domainState & kIOPMPowerOn) return (kIOPCIDeviceOnState); 133 if (domainState & kIOPMSoftSleep) return (kIOPCIDeviceDozeState); 134 if (domainState & kIOPMConfigRetained) return (kIOPCIDevicePausedState); 135 return (kIOPCIDeviceOffState); 136} 137 138/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 139// attach 140// 141/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 142 143bool IOPCIDevice::attach( IOService * provider ) 144{ 145 if (!super::attach(provider)) return (false); 146 147#if ACPI_SUPPORT 148 IOACPIPlatformDevice * device; 149 uint32_t idx; 150 bool hasPS; 151 152 device = 0; 153 if (reserved->configEntry 154 && (device = (IOACPIPlatformDevice *) reserved->configEntry->acpiDevice) 155 && !device->metaCast("IOACPIPlatformDevice")) device = 0; 156 157 for (idx = kIOPCIDeviceOffState, hasPS = false; idx <= kIOPCIDeviceOnState; idx++) 158 { 159 reserved->psMethods[idx] = -1; 160 if (!device) continue; 161 if (kIOReturnSuccess == device->validateObject(gIOPCIPSMethods[idx])) 162 { 163 reserved->psMethods[idx] = idx; 164 hasPS = true; 165 } 166 else if (kIOPCIDeviceDozeState == idx) 167 { 168 reserved->psMethods[idx] = reserved->psMethods[kIOPCIDeviceOffState]; 169 } 170 } 171 reserved->psMethods[kIOPCIDevicePausedState] = reserved->psMethods[kIOPCIDeviceOnState]; 172 if (hasPS) DLOG("%s: _PSx %d, %d, %d, %d\n", getName(), 173 reserved->psMethods[0], reserved->psMethods[1], 174 reserved->psMethods[2], reserved->psMethods[3]); 175 reserved->lastPSMethod = reserved->psMethods[kIOPCIDeviceOnState]; 176#endif 177 reserved->pciPMState = kIOPCIDeviceOnState; 178 179 if (reserved->powerCapability) 180 { 181 uint16_t pmcsr; 182 reserved->pmControlStatus = reserved->powerCapability + 4; 183 pmcsr = extendedConfigRead16(reserved->pmControlStatus); 184 if (pmcsr & kPCIPMCSPMEStatus) 185 { 186 // R/WC PME_Status 187 extendedConfigWrite16(reserved->pmControlStatus, pmcsr); 188 } 189 } 190 191 // initialize superclass variables 192 PMinit(); 193 // clamp power on 194 temporaryPowerClampOn(); 195 // register as controlling driver 196 IOPCIRegisterPowerDriver(this, false); 197 198 // join the tree 199 reserved->pmState = kIOPCIDeviceOnState; 200 reserved->pmActive = true; 201 provider->joinPMtree( this); 202 203#if 0 204 // clamp power on if this is a slot device 205 slotNameProperty = provider->getProperty ("AAPL,slot-name"); 206 if (slotNameProperty != NULL) 207 changePowerStateToPriv (1); 208#endif 209 return (true); 210} 211 212void IOPCIDevice::detach( IOService * provider ) 213{ 214 IOPCIConfigShadow * shadow; 215 216 if ((shadow = configShadow(this)) && shadow->tunnelRoot) 217 { 218 setTunnelL1Enable(this, true); 219 } 220 221 if (parent) parent->removeDevice(this); 222 223 PMstop(); 224 225 IOLockLock(reserved->lock); 226 while (reserved->pmActive) 227 { 228 reserved->pmWait = true; 229 IOLockSleep(reserved->lock, &reserved->pmActive, THREAD_UNINT); 230 } 231 IOLockUnlock(reserved->lock); 232 233 super::detach(provider); 234 235 detachAbove(gIODTPlane); 236} 237 238void 239IOPCIDevice::detachAbove( const IORegistryPlane * plane ) 240{ 241 super::detachAbove(plane); 242 243 if (plane == gIOPowerPlane) 244 { 245 IOLockLock(reserved->lock); 246 reserved->pmActive = false; 247 if (reserved->pmWait) 248 IOLockWakeup(reserved->lock, &reserved->pmActive, true); 249 IOLockUnlock(reserved->lock); 250 } 251} 252 253bool 254IOPCIDevice::initReserved(void) 255{ 256 // allocate our expansion data 257 if (!reserved) 258 { 259 reserved = IONew(IOPCIDeviceExpansionData, 1); 260 if (!reserved) 261 return (false); 262 bzero(reserved, sizeof(IOPCIDeviceExpansionData)); 263 reserved->lock = IOLockAlloc(); 264 } 265 return (true); 266} 267 268bool 269IOPCIDevice::init(OSDictionary * propTable) 270{ 271 if (!super::init(propTable)) return (false); 272 return (initReserved()); 273} 274 275bool IOPCIDevice::init( IORegistryEntry * from, const IORegistryPlane * inPlane ) 276{ 277 if (!super::init(from, inPlane)) return (false); 278 return (initReserved()); 279} 280 281void IOPCIDevice::free() 282{ 283 if (savedConfig) 284 { 285 IODelete(savedConfig, IOPCIConfigShadow, 1); 286 savedConfig = 0; 287 } 288 // This needs to be the LAST thing we do, as it disposes of our "fake" member 289 // variables. 290 // 291 if (reserved) 292 { 293 if (reserved->lock) 294 IOLockFree(reserved->lock); 295 IODelete(reserved, IOPCIDeviceExpansionData, 1); 296 } 297 298 super::free(); 299} 300 301/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 302 303IOReturn IOPCIDevice::powerStateWillChangeTo (IOPMPowerFlags capabilities, 304 unsigned long stateNumber, 305 IOService* whatDevice) 306{ 307 uint16_t pmcsr; 308 309 if (stateNumber == kIOPCIDeviceOffState) 310 { 311 if ((kPMEOption & reserved->pmSleepEnabled) && reserved->pmControlStatus && (reserved->sleepControlBits & kPCIPMCSPMEStatus)) 312 { 313 // if we would normally reset the PME_Status bit when going to sleep, do it now 314 // at the beginning of the power change. that way any PME event generated from this point 315 // until we go to sleep should wake the machine back up. 316 pmcsr = extendedConfigRead16(reserved->pmControlStatus); 317 if (pmcsr & kPCIPMCSPMEStatus) 318 { 319 // the the PME_Status bit is set at this point, we clear it but leave all other bits 320 // untouched by writing the exact same value back to the register. This is because the 321 // PME_Status bit is R/WC. 322 DLOG("%s[%p]::powerStateWillChangeTo(OFF) - PMCS has PME set(0x%x) - CLEARING\n", getName(), this, pmcsr); 323 extendedConfigWrite16(reserved->pmControlStatus, pmcsr); 324 DLOG("%s[%p]::powerStateWillChangeTo(OFF) - PMCS now is(0x%x)\n", getName(), this, extendedConfigRead16(reserved->pmControlStatus)); 325 } 326 else 327 { 328 DLOG("%s[%p]::powerStateWillChangeTo(OFF) - PMCS has PME clear(0x%x) - not touching\n", getName(), this, pmcsr); 329 } 330 } 331 } 332 else if ((stateNumber == kIOPCIDeviceOnState) && reserved->pmControlStatus) 333 { 334 pmcsr = (kIOPCIDeviceOnState == reserved->pciPMState) 335 ? reserved->pmLastWakeBits : extendedConfigRead16(reserved->pmControlStatus); 336 updateWakeReason(pmcsr); 337 } 338 339 return super::powerStateWillChangeTo(capabilities, stateNumber, whatDevice); 340} 341 342/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 343// PCI setPowerState 344// 345/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 346 347IOReturn IOPCIDevice::setPCIPowerState(uint8_t powerState, uint32_t options) 348{ 349 uint16_t pmeState; 350 uint8_t prevState; 351 352 DLOG("%s[%p]::pciSetPowerState(%d->%d)\n", getName(), this, reserved->pciPMState, powerState); 353 354#if ACPI_SUPPORT 355 IOACPIPlatformDevice * device; 356 int8_t idx; 357 IOReturn ret; 358 uint64_t time; 359 if ((idx = reserved->psMethods[powerState]) >= 0) 360 { 361 if ((idx != reserved->lastPSMethod) && !(kMachineRestoreDehibernate & options)) 362 { 363 IOPCIConfigShadow * shadow = configShadow(this); 364 if ((powerState >= kIOPCIDeviceOnState) 365 && !space.s.busNum 366 && (shadow) 367 && (shadow->bridge) 368 && (kIOPCIConfigShadowValid 369 == ((kIOPCIConfigShadowValid | kIOPCIConfigShadowBridgeDriver) & shadow->flags)) 370 && (!(0x00FFFFFF & extendedConfigRead32(kPCI2PCIPrimaryBus)))) 371 { 372 DLOG("%s::restore bus(0x%x)\n", getName(), shadow->savedConfig[kPCI2PCIPrimaryBus >> 2]); 373 extendedConfigWrite32(kPCI2PCIPrimaryBus, shadow->savedConfig[kPCI2PCIPrimaryBus >> 2]); 374 } 375 device = (IOACPIPlatformDevice *) reserved->configEntry->acpiDevice; 376 DLOG("%s::evaluateObject(%s)\n", getName(), gIOPCIPSMethods[idx]->getCStringNoCopy()); 377 time = mach_absolute_time(); 378 ret = device->evaluateObject(gIOPCIPSMethods[idx]); 379 time = mach_absolute_time() - time; 380 absolutetime_to_nanoseconds(time, &time); 381 DLOG("%s::evaluateObject(%s) ret 0x%x %qd ms\n", 382 getName(), gIOPCIPSMethods[idx]->getCStringNoCopy(), ret, time / 1000000ULL); 383 384 if ((powerState < kIOPCIDeviceOnState) && shadow) shadow->restoreCount = 0; 385 } 386 reserved->lastPSMethod = idx; 387 } 388 389// void * p3 = (void *) 0; 390// if (doMsg) device->callPlatformFunction(gIOPlatformDeviceMessageKey, false, 391// (void *) kIOMessageDeviceWillPowerOff, device, p3, (void *) 0); 392// if (doMsg) device->callPlatformFunction(gIOPlatformDeviceMessageKey, false, 393// (void *) kIOMessageDeviceHasPoweredOn, device, p3, (void *) 0); 394 395#endif 396 397 if (kMachineRestoreDehibernate & options) return (kIOReturnSuccess); 398 prevState = reserved->pciPMState; 399 if (powerState != prevState) 400 { 401 reserved->pciPMState = powerState; 402 if (!isInactive()) switch (powerState) 403 { 404 case kIOPCIDeviceOffState: 405 case kIOPCIDeviceDozeState: 406 407 if (reserved->pmSleepEnabled && reserved->pmControlStatus && reserved->sleepControlBits) 408 { 409 UInt16 bits = reserved->sleepControlBits; 410 if (kPMEOption & reserved->pmSleepEnabled) 411 { 412 // we don't clear the PME_Status at this time. Instead, we cleared it in powerStateWillChangeTo 413 // so this write will change our power state to the desired state and will also set PME_En 414 bits &= ~kPCIPMCSPMEStatus; 415 } 416 DLOG("%s[%p]::setPCIPowerState(OFF) - writing 0x%x to PMCS currently (0x%x)\n", getName(), this, bits, extendedConfigRead16(reserved->pmControlStatus)); 417 extendedConfigWrite16(reserved->pmControlStatus, bits); 418 DLOG("%s[%p]::setPCIPowerState(OFF) - after writing, PMCS is (0x%x)\n", getName(), this, extendedConfigRead16(reserved->pmControlStatus)); 419 } 420 break; 421 422 case kIOPCIDevicePausedState: 423 case kIOPCIDeviceOnState: 424 pmeState = reserved->pmControlStatus ? extendedConfigRead16(reserved->pmControlStatus) : 0; 425 if (reserved->pmSleepEnabled && reserved->pmControlStatus && reserved->sleepControlBits) 426 { 427 if ((pmeState & kPCIPMCSPowerStateMask) != kPCIPMCSPowerStateD0) 428 { 429 DLOG("%s[%p]::setPCIPowerState(ON) - moving PMCS from 0x%x to D0\n", 430 getName(), this, extendedConfigRead16(reserved->pmControlStatus)); 431 // the write below will clear PME_Status, clear PME_En, and set the Power State to D0 432 extendedConfigWrite16(reserved->pmControlStatus, kPCIPMCSPMEStatus | kPCIPMCSPowerStateD0); 433 IOSleep(10); 434 DLOG("%s[%p]::setPCIPowerState(ON) - did move PMCS to 0x%x\n", 435 getName(), this, extendedConfigRead16(reserved->pmControlStatus)); 436 } 437 else 438 { 439 DLOG("%s[%p]::setPCIPowerState(ON) - PMCS already at D0 (0x%x)\n", 440 getName(), this, extendedConfigRead16(reserved->pmControlStatus)); 441 // the write below will clear PME_Status, clear PME_En, and set the Power State to D0 442 extendedConfigWrite16(reserved->pmControlStatus, kPCIPMCSPMEStatus); 443 } 444 reserved->pmLastWakeBits = pmeState; 445 reserved->pmeUpdate = (kIOPCIDeviceOffState == prevState); 446 } 447 break; 448 } 449 } 450 451 if ((kIOPCIDeviceOnState == powerState) 452 && reserved->pmeUpdate 453 && !(kMachineRestoreDehibernate & options)) 454 { 455 reserved->pmeUpdate = false; 456 updateWakeReason(reserved->pmLastWakeBits); 457 } 458 459 return (kIOReturnSuccess); 460} 461 462/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 463 464void IOPCIDevice::updateWakeReason(uint16_t pmeState) 465{ 466 enum { kDidWake = kPCIPMCSPMEStatus | kPCIPMCSPMEEnable }; 467 OSNumber * num; 468 469 if (0xFFFF == pmeState) removeProperty(kIOPCIPMCSStateKey); 470 else 471 { 472 if (kDidWake == (kDidWake & pmeState)) 473 { 474 parent->updateWakeReason(this); 475 } 476 num = OSNumber::withNumber(pmeState, 16); 477 if (num) 478 { 479 setProperty(kIOPCIPMCSStateKey, num); 480 num->release(); 481 } 482 } 483} 484 485/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 486// PM setPowerState 487// 488/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 489 490IOReturn IOPCIDevice::setPowerState( unsigned long newState, 491 IOService * whatDevice ) 492{ 493 IOReturn ret; 494 unsigned long prevState; 495 496 if (isInactive()) 497 return (kIOPMAckImplied); 498 499 prevState = reserved->pmState; 500 ret = parent->setDevicePowerState(this, kIOPCIConfigShadowVolatile, 501 prevState, newState); 502 reserved->pmState = newState; 503 return (ret); 504} 505 506IOReturn IOPCIDevice::saveDeviceState( IOOptionBits options ) 507{ 508 IOReturn ret; 509 ret = parent->setDevicePowerState(this, 0, 510 kIOPCIDeviceOnState, kIOPCIDeviceDozeState); 511 return (ret); 512} 513 514IOReturn IOPCIDevice::restoreDeviceState( IOOptionBits options ) 515{ 516 IOReturn ret; 517 ret = parent->setDevicePowerState(this, 0, 518 kIOPCIDeviceDozeState, kIOPCIDeviceOnState); 519 return (ret); 520} 521 522/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 523 524bool IOPCIDevice::matchPropertyTable( OSDictionary * table, SInt32 * score ) 525{ 526 return (parent->matchNubWithPropertyTable(this, table, score)); 527} 528 529bool IOPCIDevice::compareName( OSString * name, OSString ** matched ) const 530{ 531 return (parent->compareNubName(this, name, matched)); 532} 533 534IOReturn IOPCIDevice::getResources( void ) 535{ 536 return (parent->getNubResources(this)); 537} 538 539/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 540 541UInt32 IOPCIDevice::configRead32( IOPCIAddressSpace _space, 542 UInt8 offset ) 543{ 544 return (parent->configRead32(_space, offset)); 545} 546 547void IOPCIDevice::configWrite32( IOPCIAddressSpace _space, 548 UInt8 offset, UInt32 data ) 549{ 550 parent->configWrite32( _space, offset, data ); 551} 552 553UInt16 IOPCIDevice::configRead16( IOPCIAddressSpace _space, 554 UInt8 offset ) 555{ 556 return (parent->configRead16(_space, offset)); 557} 558 559void IOPCIDevice::configWrite16( IOPCIAddressSpace _space, 560 UInt8 offset, UInt16 data ) 561{ 562 parent->configWrite16( _space, offset, data ); 563} 564 565UInt8 IOPCIDevice::configRead8( IOPCIAddressSpace _space, 566 UInt8 offset ) 567{ 568 return (parent->configRead8(_space, offset)); 569} 570 571void IOPCIDevice::configWrite8( IOPCIAddressSpace _space, 572 UInt8 offset, UInt8 data ) 573{ 574 parent->configWrite8( _space, offset, data ); 575} 576 577/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 578 579bool IOPCIDevice::configAccess(bool write) 580{ 581 bool ok = (!isInactive() 582 && reserved 583 && (0 == ((write ? VM_PROT_WRITE : VM_PROT_READ) & reserved->configProt))); 584 if (!ok) 585 { 586 OSReportWithBacktrace("config protect fail(2) for device %u:%u:%u\n", 587 PCI_ADDRESS_TUPLE(this)); 588 } 589 return (ok); 590} 591 592#if APPLE_KEXT_VTABLE_PADDING 593 594UInt32 IOPCIDevice::configRead32( UInt8 offset ) 595{ 596 if (!configAccess(false)) return (0xFFFFFFFF); 597 return (parent->configRead32(space, offset)); 598} 599 600void IOPCIDevice::configWrite32( UInt8 offset, UInt32 data ) 601{ 602 if (!configAccess(true)) return; 603 parent->configWrite32( space, offset, data ); 604} 605 606UInt16 IOPCIDevice::configRead16( UInt8 offset ) 607{ 608 if (!configAccess(false)) return (0xFFFF); 609 return (parent->configRead16(space, offset)); 610} 611 612void IOPCIDevice::configWrite16( UInt8 offset, UInt16 data ) 613{ 614 if (!configAccess(true)) return; 615 parent->configWrite16( space, offset, data ); 616} 617 618UInt8 IOPCIDevice::configRead8( UInt8 offset ) 619{ 620 if (!configAccess(false)) return (0xFF); 621 return (parent->configRead8(space, offset)); 622} 623 624void IOPCIDevice::configWrite8( UInt8 offset, UInt8 data ) 625{ 626 if (!configAccess(true)) return; 627 parent->configWrite8( space, offset, data ); 628} 629 630#endif /* APPLE_KEXT_VTABLE_PADDING */ 631 632// -- 633 634UInt32 IOPCIDevice::extendedConfigRead32( IOByteCount offset ) 635{ 636 if (!configAccess(false)) return (0xFFFFFFFF); 637 IOPCIAddressSpace _space = space; 638 _space.es.registerNumExtended = (offset >> 8); 639 return (configRead32(_space, offset)); 640} 641 642void IOPCIDevice::extendedConfigWrite32( IOByteCount offset, UInt32 data ) 643{ 644 if (!configAccess(true)) return; 645 IOPCIAddressSpace _space = space; 646 _space.es.registerNumExtended = (offset >> 8); 647 configWrite32(_space, offset, data); 648} 649 650UInt16 IOPCIDevice::extendedConfigRead16( IOByteCount offset ) 651{ 652 if (!configAccess(false)) return (0xFFFF); 653 IOPCIAddressSpace _space = space; 654 _space.es.registerNumExtended = (offset >> 8); 655 return (configRead16(_space, offset)); 656} 657 658void IOPCIDevice::extendedConfigWrite16( IOByteCount offset, UInt16 data ) 659{ 660 if (!configAccess(true)) return; 661 IOPCIAddressSpace _space = space; 662 _space.es.registerNumExtended = (offset >> 8); 663 configWrite16(_space, offset, data); 664} 665 666UInt8 IOPCIDevice::extendedConfigRead8( IOByteCount offset ) 667{ 668 if (!configAccess(false)) return (0xFF); 669 IOPCIAddressSpace _space = space; 670 _space.es.registerNumExtended = (offset >> 8); 671 return (configRead8(_space, offset)); 672} 673 674void IOPCIDevice::extendedConfigWrite8( IOByteCount offset, UInt8 data ) 675{ 676 if (!configAccess(true)) return; 677 IOPCIAddressSpace _space = space; 678 _space.es.registerNumExtended = (offset >> 8); 679 configWrite8(_space, offset, data); 680} 681 682// -- 683 684UInt32 IOPCIDevice::findPCICapability( UInt8 capabilityID, UInt8 * offset ) 685{ 686 return (parent->findPCICapability(space, capabilityID, offset)); 687} 688 689UInt32 IOPCIDevice::extendedFindPCICapability( UInt32 capabilityID, IOByteCount * offset ) 690{ 691 return (parent->extendedFindPCICapability(space, capabilityID, offset)); 692} 693 694UInt32 IOPCIDevice::setConfigBits( UInt8 reg, UInt32 mask, UInt32 value ) 695{ 696 UInt32 was; 697 UInt32 bits; 698 699 bits = extendedConfigRead32( reg ); 700 was = (bits & mask); 701 bits &= ~mask; 702 bits |= (value & mask); 703 extendedConfigWrite32( reg, bits ); 704 705 return (was); 706} 707 708bool IOPCIDevice::setBusMasterEnable( bool enable ) 709{ 710 return (0 != setConfigBits(kIOPCIConfigCommand, kIOPCICommandBusMaster, 711 enable ? kIOPCICommandBusMaster : 0)); 712} 713 714bool IOPCIDevice::setMemoryEnable( bool enable ) 715{ 716 return (0 != setConfigBits(kIOPCIConfigCommand, kIOPCICommandMemorySpace, 717 enable ? kIOPCICommandMemorySpace : 0)); 718} 719 720bool IOPCIDevice::setIOEnable( bool enable, bool /* exclusive = false */ ) 721{ 722 // exclusive is TODO. 723 return (0 != setConfigBits(kIOPCIConfigCommand, kIOPCICommandIOSpace, 724 enable ? kIOPCICommandIOSpace : 0)); 725} 726 727UInt8 IOPCIDevice::getBusNumber( void ) 728{ 729 return (space.s.busNum); 730} 731 732UInt8 IOPCIDevice::getDeviceNumber( void ) 733{ 734 return (space.s.deviceNum); 735} 736 737UInt8 IOPCIDevice::getFunctionNumber( void ) 738{ 739 return (space.s.functionNum); 740} 741 742/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 743 744IODeviceMemory * IOPCIDevice::getDeviceMemoryWithIndex(unsigned int index) 745{ 746 if (kTunnelL1NotSet == reserved->tunnelL1Allow) setTunnelL1Enable(this, false); 747 748 return (super::getDeviceMemoryWithIndex(index)); 749} 750 751IODeviceMemory * IOPCIDevice::getDeviceMemoryWithRegister( UInt8 reg ) 752{ 753 OSArray * array; 754 IODeviceMemory * range; 755 unsigned int i = 0; 756 757 if (kTunnelL1NotSet == reserved->tunnelL1Allow) setTunnelL1Enable(this, false); 758 759 array = (OSArray *) getProperty( gIODeviceMemoryKey); 760 if (0 == array) 761 return (0); 762 763 while ((range = (IODeviceMemory *) array->getObject(i++))) 764 { 765 if (reg == (range->getTag() & 0xff)) 766 break; 767 } 768 769 return (range); 770} 771 772IOMemoryMap * IOPCIDevice:: mapDeviceMemoryWithRegister( UInt8 reg, 773 IOOptionBits options ) 774{ 775 IODeviceMemory * range; 776 IOMemoryMap * map; 777 778 range = getDeviceMemoryWithRegister( reg ); 779 if (range) 780 map = range->map( options ); 781 else 782 map = 0; 783 784 return (map); 785} 786 787/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 788 789IODeviceMemory * IOPCIDevice::ioDeviceMemory( void ) 790{ 791 return (parent->ioDeviceMemory()); 792} 793 794/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 795 796IOService * IOPCIDevice::matchLocation( IOService * /* client */ ) 797{ 798 return (this); 799} 800 801/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 802 803OSMetaClassDefineReservedUsed(IOPCIDevice, 0); 804bool IOPCIDevice::hasPCIPowerManagement(IOOptionBits state) 805{ 806 UInt16 pciPMCapReg, checkMask; 807 OSData *aString; 808 809 reserved->sleepControlBits = 0; // on a new query, we reset the proper sleep control bits 810 if (!reserved->pmControlStatus) return (false); 811 812 pciPMCapReg = extendedConfigRead16(reserved->pmControlStatus - sizeof(uint16_t)); 813// DLOG("%s[%p]::hasPCIPwrMgmt found pciPMCapReg %x\n", 814// getName(), this, pciPMCapReg); 815 816 if (state) 817 { 818 checkMask = state; 819 switch (state) 820 { 821 case kPCIPMCPMESupportFromD3Cold: 822 case kPCIPMCPMESupportFromD3Hot: 823 reserved->sleepControlBits = (kPCIPMCSPMEStatus | kPCIPMCSPMEEnable | kPCIPMCSPowerStateD3); 824 break; 825 case kPCIPMCPMESupportFromD2: 826 reserved->sleepControlBits = (kPCIPMCSPMEStatus | kPCIPMCSPMEEnable | kPCIPMCSPowerStateD2); 827 break; 828 case kPCIPMCPMESupportFromD1: 829 reserved->sleepControlBits = (kPCIPMCSPMEStatus | kPCIPMCSPMEEnable | kPCIPMCSPowerStateD1); 830 break; 831 case kPCIPMCD2Support: 832 reserved->sleepControlBits = kPCIPMCSPowerStateD2; 833 break; 834 case kPCIPMCD1Support: 835 reserved->sleepControlBits = kPCIPMCSPowerStateD1; 836 break; 837 case kPCIPMCD3Support: 838 reserved->sleepControlBits = kPCIPMCSPowerStateD3; 839 checkMask = 0; 840 break; 841 default: 842 break; 843 } 844 if (checkMask && !(checkMask & pciPMCapReg)) 845 reserved->sleepControlBits = 0; 846 } 847 else 848 { 849 if ((aString = OSDynamicCast(OSData, getProperty("sleep-power-state")))) 850 { 851 DLOG("%s[%p]::hasPCIPwrMgmt found sleep-power-state string %p\n", getName(), this, aString); 852 if (aString->isEqualTo("D3cold", strlen("D3cold"))) 853 reserved->sleepControlBits = (kPCIPMCSPMEStatus | kPCIPMCSPMEEnable | kPCIPMCSPowerStateD3); 854 else if (aString->isEqualTo("D3Hot", strlen("D3Hot"))) 855 reserved->sleepControlBits = (kPCIPMCSPMEStatus | kPCIPMCSPMEEnable | kPCIPMCSPowerStateD3); 856 } 857 } 858 859 return (reserved->sleepControlBits ? true : false); 860} 861 862/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 863 864OSMetaClassDefineReservedUsed(IOPCIDevice, 1); 865IOReturn IOPCIDevice::enablePCIPowerManagement(IOOptionBits state) 866{ 867 IOReturn ret = kIOReturnSuccess; 868 869 if (!reserved->pmControlStatus) 870 { 871 ret = kIOReturnBadArgument; 872 return ret; 873 } 874 875 if ( state == kPCIPMCSPowerStateD0 ) 876 { 877 reserved->sleepControlBits = 0; 878 reserved->pmSleepEnabled = false; 879 return ret; 880 } 881 else 882 { 883 UInt32 oldBits = reserved->sleepControlBits; 884 885 reserved->sleepControlBits = state & kPCIPMCSPowerStateMask; 886 887 if ( oldBits & kPCIPMCSPMEStatus ) 888 reserved->sleepControlBits |= kPCIPMCSPMEStatus; 889 890 if ( oldBits & kPCIPMCSPMEEnable ) 891 reserved->sleepControlBits |= kPCIPMCSPMEEnable; 892 893 if (!reserved->sleepControlBits) 894 { 895 DLOG("%s[%p] - enablePCIPwrMgmt - no sleep control bits - not enabling\n", getName(), this); 896 ret = kIOReturnBadArgument; 897 } 898 else 899 { 900 DLOG("%s[%p] - enablePCIPwrMgmt, enabling\n", getName(), this); 901 reserved->pmSleepEnabled = true; 902#if VERSION_MAJOR < 10 903 if (getProperty(kIOPCIPMEOptionsKey)) 904#endif 905 reserved->pmSleepEnabled |= kPMEOption; 906 } 907 } 908 return ret; 909} 910 911/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 912 913IOReturn 914IOPCIDevice::callPlatformFunction(const OSSymbol * functionName, 915 bool waitForFunction, 916 void * p1, void * p2, 917 void * p3, void * p4) 918{ 919 IOReturn result; 920 921 result = super::callPlatformFunction(functionName, waitForFunction, 922 p1, p2, p3, p4); 923 924 if ((kIOReturnUnsupported == result) 925 && (gIOPlatformDeviceASPMEnableKey == functionName) 926 && getProperty(kIOPCIDeviceASPMSupportedKey)) 927 { 928 IOOptionBits state = (p2 != 0) ? reserved->expressASPMDefault : 0; 929 result = parent->setDeviceASPMState(this, (IOService *) p1, state); 930 } 931 932 return (result); 933} 934 935IOReturn 936IOPCIDevice::callPlatformFunction(const char * functionName, 937 bool waitForFunction, 938 void * p1, void * p2, 939 void * p3, void * p4) 940{ 941 return (super::callPlatformFunction(functionName, waitForFunction, 942 p1, p2, p3, p4)); 943} 944 945/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 946 947IOReturn IOPCIDevice::enableLTR(IOPCIDevice * device, bool enable) 948{ 949 uint32_t reg; 950 951 if (!reserved->expressCapability || !expressV2(this)) return (kIOReturnUnsupported); 952 953 reg = extendedConfigRead32(reserved->expressCapability + 0x24); 954 if (!((1 << 11) & reg)) return (kIOReturnUnsupported); 955 956 reg = extendedConfigRead32(reserved->expressCapability + 0x28); 957 reg &= ~(1 << 10); 958 if (enable) reg |= ( 1 << 10); 959 extendedConfigWrite32(reserved->expressCapability + 0x28, reg); 960 961 return (kIOReturnSuccess); 962} 963 964IOReturn 965IOPCIDevice::setLatencyTolerance(IOOptionBits type, uint64_t nanoseconds) 966{ 967 static const uint32_t ltrScales[] = { 1, 32, 1024, 32768, 1048576, 33554432 }; 968 969 OSData * data; 970 uint64_t ltrScale, ltrValue; 971 uint32_t idx; 972 uint32_t reg1; 973 uint8_t reg2; 974 uint8_t reg3; 975 976 if (!reserved->ltrDevice) 977 { 978 IOPCIDevice * next; 979 next = this; 980 reserved->ltrDevice = (IOPCIDevice *) 1L; 981 while (next) 982 { 983 if ((data = OSDynamicCast(OSData, next->getProperty("reg-ltrovr")))) 984 { 985 reserved->ltrDevice = next; 986 uint64_t off = *((uint64_t *)data->getBytesNoCopy()); 987 reserved->ltrOffset = off; 988 reserved->ltrReg1 = reserved->ltrDevice->extendedConfigRead32(reserved->ltrOffset); 989 reserved->ltrReg2 = reserved->ltrDevice->extendedConfigRead8(reserved->ltrOffset + 4); 990 break; 991 } 992 next = OSDynamicCast(IOPCIDevice, next->getParentEntry(gIODTPlane)); 993 } 994 } 995 996 if (((uintptr_t) reserved->ltrDevice) <= 1) return (kIOReturnUnsupported); 997 998 for (ltrValue = idx = 0; idx < arrayCount(ltrScales); idx++) 999 { 1000 ltrScale = ltrScales[idx]; 1001 ltrValue = (nanoseconds / ltrScale); 1002 if (ltrValue < (1<<10)) break; 1003 } 1004 1005 if (idx >= arrayCount(ltrScales)) return (kIOReturnMessageTooLarge); 1006 1007 reg1 = reserved->ltrReg1; 1008 reg2 = reserved->ltrReg2; 1009 reg3 = reg2; 1010 1011 if (kIOPCILatencySnooped & type) 1012 { 1013 reg1 &= 0x0000FFFF; 1014 reg1 |= (1 << 31) | (idx << 26) | (ltrValue << 16); 1015 reg2 &= ~(1 << 0); 1016 reg3 |= (1 << 3) | (1 << 0); 1017 } 1018 if (kIOPCILatencyUnsnooped & type) 1019 { 1020 reg1 &= 0xFFFF0000; 1021 reg1 |= (1 << 15) | (idx << 10) | (ltrValue << 0); 1022 reg2 &= ~(1 << 1); 1023 reg3 |= (1 << 3) | (1 << 1); 1024 } 1025 reserved->ltrDevice->extendedConfigWrite32(reserved->ltrOffset, reg1); 1026 reserved->ltrDevice->extendedConfigWrite8(reserved->ltrOffset + 4, reg2); 1027 reserved->ltrDevice->extendedConfigWrite8(reserved->ltrOffset + 4, reg3); 1028 reserved->ltrReg1 = reg1; 1029 reserved->ltrReg2 = reg3; 1030 1031#if 0 1032 DLOG("%s: ltr 0x%x = 0x%x, 0x%x\n", 1033 reserved->ltrDevice->getName(), 1034 (int)reserved->ltrOffset, 1035 reserved->ltrDevice->extendedConfigRead32(reserved->ltrOffset), 1036 reserved->ltrDevice->extendedConfigRead8(reserved->ltrOffset + 4)); 1037#endif 1038 1039 return (kIOReturnSuccess); 1040} 1041 1042/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1043 1044IOReturn 1045IOPCIDevice::setASPMState(IOService * client, IOOptionBits state) 1046{ 1047 IOPCI2PCIBridge * pcib; 1048 1049 if (!(pcib = OSDynamicCast(IOPCI2PCIBridge, parent))) return (kIOReturnUnsupported); 1050 1051 return (pcib->setDeviceASPMState(this, client, state)); 1052} 1053 1054IOReturn 1055IOPCIDevice::setTunnelL1Enable(IOService * client, bool l1Enable) 1056{ 1057 IOPCI2PCIBridge * pcib; 1058 1059 if (!(pcib = OSDynamicCast(IOPCI2PCIBridge, parent))) return (kIOReturnUnsupported); 1060 1061 return (pcib->setTunnelL1Enable(this, client, l1Enable)); 1062} 1063 1064/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1065 1066IOPCIEventSource * 1067IOPCIDevice::createEventSource(OSObject * owner, IOPCIEventSource::Action action, uint32_t options) 1068{ 1069 return (parent->createEventSource(this, owner, action, options)); 1070} 1071 1072/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1073 1074IOReturn 1075IOPCIDevice::setProperties(OSObject * properties) 1076{ 1077 IOReturn ret = kIOReturnUnsupported; 1078 OSDictionary * dict; 1079 IOService * ejectable; 1080 IOService * topEjectable = NULL; 1081 1082 dict = OSDynamicCast(OSDictionary, properties); 1083 if (dict) 1084 { 1085 if (kOSBooleanFalse == dict->getObject(kIOPCIOnlineKey)) 1086 { 1087 ejectable = this; 1088 do 1089 { 1090 if (ejectable->getProperty(kIOPCIEjectableKey)) 1091 { 1092 ejectable->setProperty(kIOPCIOnlineKey, kOSBooleanFalse); 1093 topEjectable = ejectable; 1094 } 1095 ejectable = ejectable->getProvider(); 1096 } 1097 while (ejectable); 1098 if (topEjectable) 1099 { 1100 ret = topEjectable->requestProbe(kIOPCIProbeOptionEject | kIOPCIProbeOptionDone); 1101 } 1102 return (ret); 1103 } 1104 } 1105 1106 return (super::setProperties(properties)); 1107} 1108 1109IOReturn IOPCIDevice::requestProbe(IOOptionBits options) 1110{ 1111 if (kIOReturnSuccess != IOUserClient::clientHasPrivilege(current_task(), 1112 kIOClientPrivilegeLocalUser)) 1113 { 1114 IOLog("IOPCIDevice requestProbe failed insufficient privileges\n"); 1115 return (kIOReturnNotPrivileged); 1116 } 1117 1118 // debug 1119 return (kernelRequestProbe(options)); 1120} 1121 1122IOReturn IOPCIDevice::kernelRequestProbe(uint32_t options) 1123{ 1124 return (parent->kernelRequestProbe(this, options)); 1125} 1126 1127IOReturn IOPCIDevice::protectDevice(uint32_t space, uint32_t prot) 1128{ 1129 if (space != kIOPCIConfigSpace) 1130 return (kIOReturnUnsupported); 1131 1132 reserved->configProt = prot; 1133 1134 return (parent->protectDevice(this, space, prot)); 1135} 1136 1137IOReturn IOPCIDevice::checkLink(uint32_t options) 1138{ 1139 return (parent->checkLink(options)); 1140} 1141 1142IOReturn IOPCIDevice::relocate(uint32_t options) 1143{ 1144 return (parent->relocate(this, options)); 1145} 1146 1147/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1148 1149IOReturn 1150IOPCIDevice::setConfigHandler(IOPCIDeviceConfigHandler handler, void * ref, 1151 IOPCIDeviceConfigHandler * currentHandler, void ** currentRef) 1152{ 1153 if (!configShadow(this)) 1154 return (kIOReturnError); 1155 1156 if (currentHandler) 1157 *currentHandler = configShadow(this)->handler; 1158 if (currentRef) 1159 *currentRef = configShadow(this)->handlerRef; 1160 1161 configShadow(this)->handler = handler; 1162 configShadow(this)->handlerRef = ref; 1163 1164 return (kIOReturnSuccess); 1165} 1166 1167/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1168 1169IOReturn IOPCIDevice::newUserClient(task_t owningTask, void * securityID, 1170 UInt32 type, OSDictionary * properties, 1171 IOUserClient ** handler) 1172{ 1173 return (kIOReturnUnsupported); 1174} 1175 1176/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1177 1178#undef super 1179#define super IOPCIDevice 1180 1181OSDefineMetaClassAndStructors(IOAGPDevice, IOPCIDevice) 1182OSMetaClassDefineReservedUnused(IOAGPDevice, 0); 1183OSMetaClassDefineReservedUnused(IOAGPDevice, 1); 1184OSMetaClassDefineReservedUnused(IOAGPDevice, 2); 1185OSMetaClassDefineReservedUnused(IOAGPDevice, 3); 1186OSMetaClassDefineReservedUnused(IOAGPDevice, 4); 1187OSMetaClassDefineReservedUnused(IOAGPDevice, 5); 1188OSMetaClassDefineReservedUnused(IOAGPDevice, 6); 1189OSMetaClassDefineReservedUnused(IOAGPDevice, 7); 1190OSMetaClassDefineReservedUnused(IOAGPDevice, 8); 1191OSMetaClassDefineReservedUnused(IOAGPDevice, 9); 1192OSMetaClassDefineReservedUnused(IOAGPDevice, 10); 1193OSMetaClassDefineReservedUnused(IOAGPDevice, 11); 1194OSMetaClassDefineReservedUnused(IOAGPDevice, 12); 1195OSMetaClassDefineReservedUnused(IOAGPDevice, 13); 1196OSMetaClassDefineReservedUnused(IOAGPDevice, 14); 1197OSMetaClassDefineReservedUnused(IOAGPDevice, 15); 1198OSMetaClassDefineReservedUnused(IOAGPDevice, 16); 1199 1200/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1201 1202IOReturn IOAGPDevice::createAGPSpace( IOOptionBits options, 1203 IOPhysicalAddress * address, 1204 IOPhysicalLength * length ) 1205{ 1206 return (parent->createAGPSpace(this, options, address, length)); 1207} 1208 1209IOReturn IOAGPDevice::destroyAGPSpace( void ) 1210{ 1211 return (parent->destroyAGPSpace(this)); 1212} 1213 1214IORangeAllocator * IOAGPDevice::getAGPRangeAllocator( void ) 1215{ 1216 return (parent->getAGPRangeAllocator(this)); 1217} 1218 1219IOOptionBits IOAGPDevice::getAGPStatus( IOOptionBits options ) 1220{ 1221 return (parent->getAGPStatus(this, options)); 1222} 1223 1224IOReturn IOAGPDevice::resetAGP( IOOptionBits options ) 1225{ 1226 return (parent->resetAGPDevice(this, options)); 1227} 1228 1229IOReturn IOAGPDevice::getAGPSpace( IOPhysicalAddress * address, 1230 IOPhysicalLength * length ) 1231{ 1232 return (parent->getAGPSpace(this, address, length)); 1233} 1234 1235IOReturn IOAGPDevice::commitAGPMemory( IOMemoryDescriptor * memory, 1236 IOByteCount agpOffset, 1237 IOOptionBits options ) 1238{ 1239 return (parent->commitAGPMemory(this, memory, agpOffset, options)); 1240} 1241 1242IOReturn IOAGPDevice::releaseAGPMemory( IOMemoryDescriptor * memory, 1243 IOByteCount agpOffset, 1244 IOOptionBits options ) 1245{ 1246 return (parent->releaseAGPMemory(this, memory, agpOffset, options)); 1247} 1248 1249