NTSTATUS PcPowerFxRegisterDevice( _In_ PVOID PoFxDeviceContext, _In_ POHANDLE PoHandle ) { PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)PoFxDeviceContext; PortClassDeviceContext* pExtension = static_cast<PortClassDeviceContext*>(DeviceObject->DeviceExtension); PAGED_CODE(); DPF(D_VERBOSE, ("PcPowerFxRegisterDevice Context %p, PoHandle %p", PoFxDeviceContext, PoHandle)); pExtension->m_poHandle = PoHandle; // // Set latency and residency hints so that the power framework chooses lower // powered F-states when we are idle. // The values used here are for illustration purposes only. The driver // should use values that are appropriate for its device. // PoFxSetComponentLatency( PoHandle, 0, // Component (WDF_ABS_TIMEOUT_IN_MS(SYSVAD_DEEPEST_FSTATE_LATENCY_IN_MS) + 1) ); PoFxSetComponentResidency( PoHandle, 0, // Component (WDF_ABS_TIMEOUT_IN_SEC(SYSVAD_DEEPEST_FSTATE_RESIDENCY_IN_SEC) + 1) ); return STATUS_SUCCESS; }
NTSTATUS SingleCompWdmEvtDeviceWdmPostPoFxRegisterDevice( _In_ WDFDEVICE Device, _In_ POHANDLE PoHandle ) /*++ Routine Description: KMDF calls this routine after it has registered with the Power Framework and supplies the registration handle that driver can use directly. Arguments: Device - Handle to the framework device object PoHandle - Handle of registration with Power Framework. Return Value: An NTSTATUS value representing success or failure of the function. --*/ { FDO_DATA *fdoContext = NULL; PAGED_CODE(); // // Get the device context // fdoContext = FdoGetContext(Device); // // Save the POHANDLE // fdoContext->PoHandle = PoHandle; // // Set latency and residency hints so that the power framework chooses lower // powered F-states when we are idle. // The values used here are for illustration purposes only. The driver // should use values that are appropriate for its device. // PoFxSetComponentLatency( PoHandle, 0, // Component (WDF_ABS_TIMEOUT_IN_MS(DEEPEST_FSTATE_LATENCY_IN_MS) + 1) ); PoFxSetComponentResidency( PoHandle, 0, // Component (WDF_ABS_TIMEOUT_IN_SEC(DEEPEST_FSTATE_RESIDENCY_IN_SEC) + 1) ); return STATUS_SUCCESS; }
VOID ForwardRequestToIoTarget( _In_ WDFQUEUE queue, _In_ WDFREQUEST request, _In_ size_t length) { TraceEntry(); Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! - Queue 0x%p, Request 0x%p Length %Iu", queue, request, length); auto device = WdfIoQueueGetDevice(queue); auto context = GetDeviceContext(device); if (length > context->MaxLengthInBytesForRWTransfers) { TraceError("%!FUNC! - Buffer Length to big %Iu, Max is %Iu. Status - %!STATUS!", length, context->MaxLengthInBytesForRWTransfers, STATUS_BUFFER_OVERFLOW); WdfRequestCompleteWithInformation(request, STATUS_BUFFER_OVERFLOW, NULL); return; } auto targetDevice = WdfDeviceGetIoTarget(device); WdfRequestFormatRequestUsingCurrentType(request); WDF_REQUEST_SEND_OPTIONS options; WDF_REQUEST_SEND_OPTIONS_INIT( &options, WDF_REQUEST_SEND_OPTION_SYNCHRONOUS | WDF_REQUEST_SEND_OPTION_TIMEOUT); WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&options, WDF_ABS_TIMEOUT_IN_SEC(10)); auto sendSuccess = WdfRequestSend(request, targetDevice, &options); auto status = WdfRequestGetStatus(request); if (!sendSuccess || !NT_SUCCESS(status)) { TraceError("%!FUNC! - WdfRequestSend returned %d with status: %!STATUS!", sendSuccess, status); WdfRequestCompleteWithInformation(request, status, NULL); return; } WdfRequestComplete(request, status); }
/////////////////////////////////////////////////////////////////////////////// // SmplDeviceEvtWdmPostPoFxRegisterDevice // KMDF calls this routine after it has registered with the Power Framework // and supplies the registration handle that driver can use directly. /////////////////////////////////////////////////////////////////////////////// NTSTATUS SmplDeviceEvtWdmPostPoFxRegisterDevice( _In_ WDFDEVICE Device, _In_ POHANDLE PoHandle ) { DEVICE_CONTEXT *pDeviceContext = DeviceGetContext(Device); pDeviceContext->PoHandle = PoHandle; // // Set latency and residency hints so that the power framework chooses lower // powered F-states when we are idle. // The values used here are for illustration purposes only. The driver // should use values that are appropriate for its device. // PoFxSetComponentLatency(PoHandle, 0, (WDF_ABS_TIMEOUT_IN_MS(DEEPEST_FSTATE_LATENCY_IN_MS) + 1)); PoFxSetComponentResidency(PoHandle, 0, (WDF_ABS_TIMEOUT_IN_SEC(DEEPEST_FSTATE_RESIDENCY_IN_SEC) + 1)); return STATUS_SUCCESS; } // end SmplDeviceEvtWdmPostPoFxRegisterDevice
/////////////////////////////////////////////////////////////////////////////// // Initialization of component level power management. /////////////////////////////////////////////////////////////////////////////// VOID SmplPoFxSingleComponentInitialize( _In_ WDFDEVICE Device ) { WDF_POWER_FRAMEWORK_SETTINGS Settings; PO_FX_COMPONENT Component; PO_FX_COMPONENT_IDLE_STATE IdleStates[FSTATE_COUNT]; NTSTATUS Status; // // Initialization // RtlZeroMemory(&Component, sizeof(Component)); RtlZeroMemory(&IdleStates, sizeof(IdleStates)); // // The transition latency and residency requirement values used here are for // illustration purposes only. The driver should use values that are // appropriate for its device. // // // F0 // IdleStates[0].TransitionLatency = 0; IdleStates[0].ResidencyRequirement = 0; IdleStates[0].NominalPower = 0; // // F1 // IdleStates[1].TransitionLatency = WDF_ABS_TIMEOUT_IN_MS(200); IdleStates[1].ResidencyRequirement = WDF_ABS_TIMEOUT_IN_SEC(3); IdleStates[1].NominalPower = 0; // // F2 // IdleStates[2].TransitionLatency = WDF_ABS_TIMEOUT_IN_MS(400); IdleStates[2].ResidencyRequirement = WDF_ABS_TIMEOUT_IN_SEC(6); IdleStates[2].NominalPower = 0; // // F3 // IdleStates[3].TransitionLatency = WDF_ABS_TIMEOUT_IN_MS(DEEPEST_FSTATE_LATENCY_IN_MS); IdleStates[3].ResidencyRequirement = WDF_ABS_TIMEOUT_IN_SEC(DEEPEST_FSTATE_RESIDENCY_IN_SEC); IdleStates[3].NominalPower = 0; // // Component 0 (the only component) // Component.IdleStateCount = FSTATE_COUNT; Component.IdleStates = IdleStates; WDF_POWER_FRAMEWORK_SETTINGS_INIT(&Settings); Settings.EvtDeviceWdmPostPoFxRegisterDevice = SmplDeviceEvtWdmPostPoFxRegisterDevice; Settings.Component = &Component; Settings.ComponentActiveConditionCallback = SmplPoFxComponentActiveConditionCallback; Settings.ComponentIdleConditionCallback = SmplPoFxComponentIdleConditionCallback; Settings.ComponentIdleStateCallback = SmplPoFxComponentIdleStateCallback; Settings.PoFxDeviceContext = (PVOID) Device; Status = WdfDeviceWdmAssignPowerFrameworkSettings(Device, &Settings); if (FALSE == NT_SUCCESS(Status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234,"WdfDeviceWdmAssignPowerFrameworkSettings failed! 0x%x\n", Status); } } // end SmplPoFxSingleComponentInitialize
NTSTATUS AssignPowerFrameworkSettings( _In_ WDFDEVICE Device ) /*++ Routine Description: Helper function to assign Power Framework related settings for the device Arguments: Device - Handle to the framework device object Return Value: An NTSTATUS value representing success or failure of the function. --*/ { NTSTATUS status; WDF_POWER_FRAMEWORK_SETTINGS poFxSettings; PO_FX_COMPONENT component; PO_FX_COMPONENT_IDLE_STATE idleStates[FSTATE_COUNT]; // // Note that we initialize the 'idleStates' array below based on the // assumption that MAX_FSTATE_COUNT is 4. // If we increase the value of MAX_FSTATE_COUNT, we need to initialize those // additional F-states below. If we decrease the value of MAX_FSTATE_COUNT, // we need to remove the corresponding initializations below. // C_ASSERT(FSTATE_COUNT == 4); PAGED_CODE(); // // Initialization // RtlZeroMemory(&component, sizeof(component)); RtlZeroMemory(idleStates, sizeof(idleStates)); // // The transition latency and residency requirement values used here are for // illustration purposes only. The driver should use values that are // appropriate for its device. // // // F0 // idleStates[0].TransitionLatency = 0; idleStates[0].ResidencyRequirement = 0; idleStates[0].NominalPower = 0; // // F1 // idleStates[1].TransitionLatency = WDF_ABS_TIMEOUT_IN_MS(200); idleStates[1].ResidencyRequirement = WDF_ABS_TIMEOUT_IN_SEC(3); idleStates[1].NominalPower = 0; // // F2 // idleStates[2].TransitionLatency = WDF_ABS_TIMEOUT_IN_MS(400); idleStates[2].ResidencyRequirement = WDF_ABS_TIMEOUT_IN_SEC(6); idleStates[2].NominalPower = 0; // // F3 // idleStates[3].TransitionLatency = WDF_ABS_TIMEOUT_IN_MS(DEEPEST_FSTATE_LATENCY_IN_MS); idleStates[3].ResidencyRequirement = WDF_ABS_TIMEOUT_IN_SEC(DEEPEST_FSTATE_RESIDENCY_IN_SEC); idleStates[3].NominalPower = 0; // // Component 0 (the only component) // component.IdleStateCount = FSTATE_COUNT; component.IdleStates = idleStates; WDF_POWER_FRAMEWORK_SETTINGS_INIT(&poFxSettings); poFxSettings.EvtDeviceWdmPostPoFxRegisterDevice = SingleCompWdmEvtDeviceWdmPostPoFxRegisterDevice; poFxSettings.EvtDeviceWdmPrePoFxUnregisterDevice = SingleCompWdmEvtDeviceWdmPrePoFxUnregisterDevice; poFxSettings.Component = &component; poFxSettings.ComponentActiveConditionCallback = SingleCompWdmActiveConditionCallback; poFxSettings.ComponentIdleConditionCallback = SingleCompWdmIdleConditionCallback; poFxSettings.ComponentIdleStateCallback = SingleCompWdmIdleStateCallback; poFxSettings.PoFxDeviceContext = (PVOID) Device; status = WdfDeviceWdmAssignPowerFrameworkSettings(Device, &poFxSettings); if (FALSE == NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfDeviceWdmAssignPowerFrameworkSettings failed with " "%!status!.", status); } return status; }