NTSTATUS CyEvtDeviceReleaseHardware ( IN WDFDEVICE Device, IN WDFCMRESLIST ResourcesTranslated ) { PDEVICE_CONTEXT pDeviceContext; NTSTATUS NTStatus = STATUS_SUCCESS; WDF_IO_QUEUE_STATE queueStatus; PAGED_CODE(); CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "Start CyEvtDeviceReleaseHardware\n"); pDeviceContext = CyGetDeviceContext(Device); if(pDeviceContext->bIsMultiplInterface) { if(pDeviceContext->MultipleInterfacePair) ExFreePoolWithTag(pDeviceContext->MultipleInterfacePair,CYMEM_TAG); } /*The default queue does not stop even after device get disconnected and due to this the application device IO which are dependent on the driver get stuck at that point and application hangs. To roslve this issue the queue should be stopped once the device is disconnected.*/ WdfIoQueueStop( pDeviceContext->hQueue, EvtIoQueueState, WDF_NO_CONTEXT ); WdfIoQueuePurge( pDeviceContext->hQueue, EvtIoQueueState, WDF_NO_CONTEXT ); /* queueStatus = WdfIoQueueGetState(pDeviceContext->hQueue, NULL, NULL); CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "Queue Purge states :%d\n",(WDF_IO_QUEUE_PURGED(queueStatus)) ? TRUE : FALSE); CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "Queue Ready states :%d\n",(WDF_IO_QUEUE_READY(queueStatus)) ? TRUE : FALSE); CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "Queue Drain states :%d\n",(WDF_IO_QUEUE_DRAINED(queueStatus)) ? TRUE : FALSE); CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "Queue Stopped states :%d\n",(WDF_IO_QUEUE_STOPPED(queueStatus)) ? TRUE : FALSE); CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "Queue IDLE states :%d\n",(WDF_IO_QUEUE_IDLE(queueStatus)) ? TRUE : FALSE); */ CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "End CyEvtDeviceReleaseHardware\n"); return NTStatus; }
/////////////////////////////////////////////////////////////////////////////// // SmplPoFxComponentIdleConditionCallback // // IMPORTANT NOTE // ============== // Given that the idle transition does not complete until all the power- // managed queues have been stopped, it is extremely important for the // driver to ensure that stopping of power-managed queues is reasonably // quick. If the driver fails to ensure this, the power framework can remain // stuck in the idle transition for a long time, which could hamper its // ability to put the component in a low-power F-state. This could // negatively impact any power savings that can be gained via component // power management. // // In order to ensure that idle transitions can complete quickly, the driver // should quickly process any requests that are dispatched to it via a // power-managed queue. If the driver forwards a request (that was received // via a power-managed queue) to an I/O target that might keep the request // pending for a long time, then the driver should cancel the request when // the component idle condition callback is invoked. This is because the // power-managed queue cannot be stopped while the request is pending in the // I/O target. // /////////////////////////////////////////////////////////////////////////////// VOID SmplPoFxComponentIdleConditionCallback( _In_ PVOID Context, _In_ ULONG Component ) { DEVICE_CONTEXT *pDeviceContext = DeviceGetContext((WDFDEVICE) Context); DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234,"SmplPoFxComponentIdleConditionCallback Component:%d\n", Component); WdfIoQueueStop(pDeviceContext->Queue, SmplQueueEvtStatePoFxStopComplete, NULL); // // The idle transition will complete asynchronously. We'll call // PoFxCompleteIdleCondition to complete it when all the queues have been // stopped. } // end SmplPoFxComponentIdleConditionCallback
VOID SingleCompWdmIdleConditionCallback( _In_ PVOID Context, _In_ ULONG Component ) /*++ Routine Description: This callback is invoked by Power Framework to notify driver that one of its components has become idle. Arguments: Context - Context that we supplied when calling WdfDeviceWdmAssignPowerFrameworkSettings. Component - Component that have become idle. Since we have only one component this value is always 0. Return Value: None --*/ { WDFDEVICE device; FDO_DATA *fdoContext = NULL; UCHAR i = 0; // // We have only component 0 // if (0 != Component) { Trace(TRACE_LEVEL_ERROR,"%!FUNC! - Unexpected component %d",Component); ASSERT(FALSE); } // // Get the device // device = (WDFDEVICE) Context; // // Get the device context // fdoContext = FdoGetContext(device); // // Initialize the count of queues to be stopped. // // Until we complete this idle transition there cannot be other idle // transitions, which is only where we use this count. Thus nothing races // with it. // // If you have other code that stops/starts queues, it may be simpler // to queue a work-item from this callback which stops all the queues // synchronously. Synchronous queue stop cannot be done from here since // this callback may be called at DISPATCH_LEVEL. // fdoContext->QueueStopCount = QUEUE_COUNT; // // Stop power-managed queues // for (i = 0; i < QUEUE_COUNT; i++) { #pragma warning(suppress: 6387) // passing NULL Context parameter is safe in this instance WdfIoQueueStop(fdoContext->Queues[i], SingleCompEvtQueueStopComplete, NULL /* Context */); } // // The idle transition will complete asynchronously. We'll call // PoFxCompleteIdleCondition to complete it when all the queues have been // stopped. // // IMPORTANT NOTE // ============== // Given that the idle transition does not complete until all the power- // managed queues have been stopped, it is extremely important for the // driver to ensure that stopping of power-managed queues is reasonably // quick. If the driver fails to ensure this, the power framework can remain // stuck in the idle transition for a long time, which could hamper its // ability to put the component in a low-power F-state. This could // negatively impact any power savings that can be gained via component // power management. // // In order to ensure that idle transitions can complete quickly, the driver // should quickly process any requests that are dispatched to it via a // power-managed queue. If the driver forwards a request (that was received // via a power-managed queue) to an I/O target that might keep the request // pending for a long time, then the driver should cancel the request when // the component idle condition callback is invoked. This is because the // power-managed queue cannot be stopped while the request is pending in the // I/O target. // return; }