1 // 2 // Copyright (C) Microsoft. All rights reserved. 3 // 4 #include "pnppriv.hpp" 5 6 #include <initguid.h> 7 #include <wdmguid.h> 8 9 extern "C" { 10 #if defined(EVENT_TRACING) 11 #include "PoxInterfaceKm.tmh" 12 #endif 13 } 14 15 VOID 16 FxPoxInterface::StateCallback( 17 __in PVOID Context, 18 __in ULONG Component, 19 __in ULONG State 20 ) 21 { 22 PPOX_SETTINGS poxSettings = NULL; 23 FxPoxInterface * pThis = NULL; 24 25 pThis = (FxPoxInterface*) Context; 26 27 DoTraceLevelMessage( 28 pThis->m_PkgPnp->GetDriverGlobals(), 29 TRACE_LEVEL_VERBOSE, 30 TRACINGPNP, 31 "WDFDEVICE 0x%p !devobj 0x%p PO_FX_COMPONENT_IDLE_STATE_CALLBACK " 32 "invoked.", 33 pThis->m_PkgPnp->GetDevice()->GetHandle(), 34 pThis->m_PkgPnp->GetDevice()->GetDeviceObject() 35 ); 36 37 // 38 // If the client driver has specified power framework settings, retrieve 39 // them. 40 // 41 poxSettings = pThis->GetPowerFrameworkSettings(); 42 43 // 44 // If the client driver has specified an F-state change callback, invoke it. 45 // 46 if ((NULL != poxSettings) && 47 (NULL != poxSettings->ComponentIdleStateCallback)) { 48 49 DoTraceLevelMessage( 50 pThis->m_PkgPnp->GetDriverGlobals(), 51 TRACE_LEVEL_VERBOSE, 52 TRACINGPNP, 53 "WDFDEVICE 0x%p !devobj 0x%p Invoking client driver's " 54 "PO_FX_COMPONENT_IDLE_STATE_CALLBACK.", 55 pThis->m_PkgPnp->GetDevice()->GetHandle(), 56 pThis->m_PkgPnp->GetDevice()->GetDeviceObject() 57 ); 58 59 poxSettings->ComponentIdleStateCallback( 60 poxSettings->PoFxDeviceContext, 61 Component, 62 State); 63 } else { 64 PoFxCompleteIdleState(pThis->m_PoHandle, Component); 65 } 66 } 67 68 VOID 69 FxPoxInterface::ComponentActiveCallback( 70 __in PVOID Context, 71 __in ULONG Component 72 ) 73 { 74 PPOX_SETTINGS poxSettings = NULL; 75 FxPoxInterface * pThis = NULL; 76 77 pThis = (FxPoxInterface*) Context; 78 79 DoTraceLevelMessage( 80 pThis->m_PkgPnp->GetDriverGlobals(), 81 TRACE_LEVEL_VERBOSE, 82 TRACINGPNP, 83 "WDFDEVICE 0x%p !devobj 0x%p PO_FX_COMPONENT_ACTIVE_CONDITION_CALLBACK " 84 "invoked.", 85 pThis->m_PkgPnp->GetDevice()->GetHandle(), 86 pThis->m_PkgPnp->GetDevice()->GetDeviceObject() 87 ); 88 89 // 90 // If the client driver has specified power framework settings, retrieve 91 // them. 92 // 93 poxSettings = pThis->GetPowerFrameworkSettings(); 94 95 // 96 // If the client driver has specified a component-active callback, invoke it 97 // 98 if ((NULL != poxSettings) && 99 (NULL != poxSettings->ComponentActiveConditionCallback)) { 100 101 DoTraceLevelMessage( 102 pThis->m_PkgPnp->GetDriverGlobals(), 103 TRACE_LEVEL_VERBOSE, 104 TRACINGPNP, 105 "WDFDEVICE 0x%p !devobj 0x%p Invoking client driver's " 106 "PO_FX_COMPONENT_ACTIVE_CONDITION_CALLBACK.", 107 pThis->m_PkgPnp->GetDevice()->GetHandle(), 108 pThis->m_PkgPnp->GetDevice()->GetDeviceObject() 109 ); 110 111 poxSettings->ComponentActiveConditionCallback( 112 poxSettings->PoFxDeviceContext, 113 Component 114 ); 115 } else { 116 // 117 // Nothing to do. 118 // 119 DO_NOTHING(); 120 } 121 122 return; 123 } 124 125 VOID 126 FxPoxInterface::ComponentIdleCallback( 127 __in PVOID Context, 128 __in ULONG Component 129 ) 130 { 131 PPOX_SETTINGS poxSettings = NULL; 132 FxPoxInterface * pThis = NULL; 133 134 pThis = (FxPoxInterface*) Context; 135 136 DoTraceLevelMessage( 137 pThis->m_PkgPnp->GetDriverGlobals(), 138 TRACE_LEVEL_VERBOSE, 139 TRACINGPNP, 140 "WDFDEVICE 0x%p !devobj 0x%p PO_FX_COMPONENT_IDLE_CONDITION_CALLBACK " 141 "invoked.", 142 pThis->m_PkgPnp->GetDevice()->GetHandle(), 143 pThis->m_PkgPnp->GetDevice()->GetDeviceObject() 144 ); 145 146 // 147 // If the client driver has specified power framework settings, retrieve 148 // them. 149 // 150 poxSettings = pThis->GetPowerFrameworkSettings(); 151 152 // 153 // If the client driver has specified a component-idle callback, invoke it 154 // 155 if ((NULL != poxSettings) && 156 (NULL != poxSettings->ComponentIdleConditionCallback)) { 157 158 DoTraceLevelMessage( 159 pThis->m_PkgPnp->GetDriverGlobals(), 160 TRACE_LEVEL_VERBOSE, 161 TRACINGPNP, 162 "WDFDEVICE 0x%p !devobj 0x%p Invoking client driver's " 163 "PO_FX_COMPONENT_IDLE_CONDITION_CALLBACK.", 164 pThis->m_PkgPnp->GetDevice()->GetHandle(), 165 pThis->m_PkgPnp->GetDevice()->GetDeviceObject() 166 ); 167 168 poxSettings->ComponentIdleConditionCallback( 169 poxSettings->PoFxDeviceContext, 170 Component 171 ); 172 } else { 173 // 174 // We're being notified that we're idle, but there is no action that we 175 // need to take here. We power down the device only when we get the 176 // device-power-not-required event. 177 // 178 PoFxCompleteIdleCondition(pThis->m_PoHandle, Component); 179 } 180 return; 181 } 182 183 VOID 184 FxPoxInterface::PowerRequiredCallback( 185 __in PVOID Context 186 ) 187 { 188 FxPoxInterface * pThis = NULL; 189 190 pThis = (FxPoxInterface*) Context; 191 pThis->PowerRequiredCallbackWorker(TRUE /* InvokedFromPoxCallback */); 192 return; 193 } 194 195 VOID 196 FxPoxInterface::PowerNotRequiredCallback( 197 __in PVOID Context 198 ) 199 { 200 FxPoxInterface * pThis = NULL; 201 202 pThis = (FxPoxInterface*) Context; 203 pThis->PowerNotRequiredCallbackWorker(TRUE /* InvokedFromPoxCallback */); 204 PoFxCompleteDevicePowerNotRequired(pThis->m_PoHandle); 205 return; 206 } 207 208 _Function_class_(PO_FX_POWER_CONTROL_CALLBACK) 209 _IRQL_requires_max_(DISPATCH_LEVEL) 210 NTSTATUS 211 FxPoxInterface::PowerControlCallback( 212 _In_ PVOID Context, 213 _In_ LPCGUID PowerControlCode, 214 _In_reads_bytes_opt_(InBufferSize) PVOID InBuffer, 215 _In_ SIZE_T InBufferSize, 216 _Out_writes_bytes_opt_(OutBufferSize) PVOID OutBuffer, 217 _In_ SIZE_T OutBufferSize, 218 _Out_opt_ PSIZE_T BytesReturned 219 ) 220 { 221 NTSTATUS status; 222 PPOX_SETTINGS poxSettings = NULL; 223 FxPoxInterface * pThis = NULL; 224 225 pThis = (FxPoxInterface*) Context; 226 227 DoTraceLevelMessage( 228 pThis->m_PkgPnp->GetDriverGlobals(), 229 TRACE_LEVEL_VERBOSE, 230 TRACINGPNP, 231 "WDFDEVICE 0x%p !devobj 0x%p PO_FX_POWER_CONTROL_CALLBACK invoked.", 232 pThis->m_PkgPnp->GetDevice()->GetHandle(), 233 pThis->m_PkgPnp->GetDevice()->GetDeviceObject() 234 ); 235 236 // 237 // If the client driver has specified power framework settings, retrieve 238 // them. 239 // 240 poxSettings = pThis->GetPowerFrameworkSettings(); 241 242 // 243 // The client driver must have specified a power control callback 244 // 245 ASSERT((NULL != poxSettings) && 246 (NULL != poxSettings->PowerControlCallback)); 247 248 // 249 // Invoke the client driver's power control callback 250 // 251 status = poxSettings->PowerControlCallback(poxSettings->PoFxDeviceContext, 252 PowerControlCode, 253 InBuffer, 254 InBufferSize, 255 OutBuffer, 256 OutBufferSize, 257 BytesReturned); 258 259 DoTraceLevelMessage( 260 pThis->m_PkgPnp->GetDriverGlobals(), 261 TRACE_LEVEL_VERBOSE, 262 TRACINGPNP, 263 "WDFDEVICE 0x%p !devobj 0x%p Client driver's " 264 "PO_FX_POWER_CONTROL_CALLBACK returned %!STATUS!.", 265 pThis->m_PkgPnp->GetDevice()->GetHandle(), 266 pThis->m_PkgPnp->GetDevice()->GetDeviceObject(), 267 status 268 ); 269 270 return status; 271 } 272 273 NTSTATUS 274 FxPoxInterface::PoxRegisterDevice( 275 VOID 276 ) 277 { 278 279 NTSTATUS status; 280 PO_FX_DEVICE poxDevice; 281 PO_FX_COMPONENT_IDLE_STATE idleState; 282 PPOX_SETTINGS poxSettings = NULL; 283 284 RtlZeroMemory(&poxDevice, sizeof(poxDevice)); 285 RtlZeroMemory(&idleState, sizeof(idleState)); 286 287 poxDevice.Version = PO_FX_VERSION_V1; 288 289 // 290 // Specify callbacks and context 291 // 292 poxDevice.ComponentIdleStateCallback = 293 FxPoxInterface::StateCallback; 294 poxDevice.ComponentActiveConditionCallback = 295 FxPoxInterface::ComponentActiveCallback; 296 poxDevice.ComponentIdleConditionCallback = 297 FxPoxInterface::ComponentIdleCallback; 298 poxDevice.DevicePowerRequiredCallback = 299 FxPoxInterface::PowerRequiredCallback; 300 poxDevice.DevicePowerNotRequiredCallback = 301 FxPoxInterface::PowerNotRequiredCallback; 302 poxDevice.DeviceContext = this; 303 304 // 305 // We register as a single component device 306 // 307 poxDevice.ComponentCount = 1; 308 309 // 310 // If the client driver has specified power framework settings, retrieve 311 // them. 312 // 313 poxSettings = GetPowerFrameworkSettings(); 314 315 // 316 // We specify a power control callback only if the client driver supplies us 317 // a power control callback 318 // 319 poxDevice.PowerControlCallback = 320 ((NULL == poxSettings) || (NULL == poxSettings->PowerControlCallback)) ? 321 NULL : 322 FxPoxInterface::PowerControlCallback; 323 324 // 325 // If the client driver has specified any settings for component 0, use 326 // them. Otherwise use the default settings. 327 // 328 if ((NULL == poxSettings) || (NULL == poxSettings->Component)) { 329 // 330 // Default settings 331 // 332 333 // 334 // We only support F0 335 // 336 poxDevice.Components[0].IdleStateCount = 1; 337 338 // 339 // Transition latency should be 0 for F0 340 // 341 idleState.TransitionLatency = 0; 342 343 // 344 // Residency requirement should be 0 for F0 345 // 346 idleState.ResidencyRequirement = 0; 347 348 // 349 // The value doesn't matter because we do not support multiple F-states. 350 // 351 idleState.NominalPower = PO_FX_UNKNOWN_POWER; 352 353 // 354 // Specify the state information for F0 355 // 356 poxDevice.Components[0].IdleStates = &idleState; 357 } 358 else { 359 // 360 // Client driver's settings 361 // 362 RtlCopyMemory(&(poxDevice.Components[0]), 363 poxSettings->Component, 364 sizeof(poxDevice.Components[0])); 365 } 366 367 // 368 // Register with the power framework 369 // 370 status = PoFxRegisterDevice( 371 m_PkgPnp->GetDevice()->GetPhysicalDevice(), 372 &poxDevice, 373 &(m_PoHandle) 374 ); 375 if (FALSE == NT_SUCCESS(status)) { 376 DoTraceLevelMessage( 377 m_PkgPnp->GetDriverGlobals(), 378 TRACE_LEVEL_ERROR, TRACINGPNP, 379 "WDFDEVICE 0x%p !devobj 0x%p FxPox::PoxRegisterDevice failed. " 380 "%!STATUS!.", 381 m_PkgPnp->GetDevice()->GetHandle(), 382 m_PkgPnp->GetDevice()->GetDeviceObject(), 383 status); 384 goto exit; 385 } 386 387 status = STATUS_SUCCESS; 388 389 exit: 390 return status; 391 392 } 393 394 VOID 395 FxPoxInterface::PoxStartDevicePowerManagement( 396 VOID 397 ) 398 { 399 PoFxStartDevicePowerManagement(m_PoHandle); 400 } 401 402 403 VOID 404 FxPoxInterface::PoxUnregisterDevice( 405 VOID 406 ) 407 { 408 PoFxUnregisterDevice(m_PoHandle); 409 } 410 411 412 VOID 413 FxPoxInterface::PoxActivateComponent( 414 VOID 415 ) 416 { 417 // 418 // We only support single component and don't 419 // need to set any flags 420 // 421 PoFxActivateComponent(m_PoHandle, 422 0, //component 423 0 //flags 424 ); 425 } 426 427 428 VOID 429 FxPoxInterface::PoxIdleComponent( 430 VOID 431 ) 432 { 433 // 434 // We only support single component and don't 435 // need to set any flags 436 // 437 PoFxIdleComponent(m_PoHandle, 438 0, //component 439 0 //flags 440 ); 441 } 442 443 444 VOID 445 FxPoxInterface::PoxReportDevicePoweredOn( 446 VOID 447 ) 448 { 449 PoFxReportDevicePoweredOn(m_PoHandle); 450 } 451 452 453 VOID 454 FxPoxInterface::PoxSetDeviceIdleTimeout( 455 __in ULONGLONG IdleTimeout 456 ) 457 { 458 PoFxSetDeviceIdleTimeout(m_PoHandle, IdleTimeout); 459 } 460 461