NTSTATUS VIOSerialPortEvtDeviceD0Exit( IN WDFDEVICE Device, IN WDF_POWER_DEVICE_STATE TargetState ) { PVIOSERIAL_PORT Port = RawPdoSerialPortGetData(Device)->port; PPORT_BUFFER buf; PSINGLE_LIST_ENTRY iter; UNREFERENCED_PARAMETER(TargetState); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "--> %s\n", __FUNCTION__); WdfIoQueuePurge(Port->ReadQueue, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT); WdfIoQueuePurge(Port->WriteQueue, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT); WdfIoQueuePurge(Port->IoctlQueue, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT); VIOSerialDisableInterruptQueue(GetInQueue(Port)); WdfSpinLockAcquire(Port->InBufLock); VIOSerialDiscardPortDataLocked(Port); Port->InBuf = NULL; WdfSpinLockRelease(Port->InBufLock); WdfSpinLockAcquire(Port->OutVqLock); VIOSerialReclaimConsumedBuffers(Port); WdfSpinLockRelease(Port->OutVqLock); while (buf = (PPORT_BUFFER)VirtIODeviceDetachUnusedBuf(GetInQueue(Port))) { VIOSerialFreeBuffer(buf); } iter = PopEntryList(&Port->WriteBuffersList); while (iter != NULL) { PWRITE_BUFFER_ENTRY entry = CONTAINING_RECORD(iter, WRITE_BUFFER_ENTRY, ListEntry); ExFreePoolWithTag(entry->Buffer, VIOSERIAL_DRIVER_MEMORY_TAG); ExFreePoolWithTag(entry, VIOSERIAL_DRIVER_MEMORY_TAG); iter = PopEntryList(&Port->WriteBuffersList); }; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "<-- %s\n", __FUNCTION__); return STATUS_SUCCESS; }
VOID FfbActiveSet( BOOLEAN active, int id, PDEVICE_EXTENSION pDevContext ) { size_t szarry, szelement; int sz; // Check id szarry = sizeof(pDevContext->FfbEnable); szelement = sizeof(pDevContext->FfbEnable[0]); sz = szarry/szelement; if (id<1 || id>sz) return; // Has there been a change? if not do nothing // NO if (active == pDevContext->FfbEnable[id-1]) return; // YES if (active) { // FFB Activated //////////// ReadQ ///////////////////////////////////////// // Start queue WdfIoQueueStart(pDevContext->FfbReadQ[id - 1]); //////////// WriteQ ///////////////////////////////////////// // Start queue WdfIoQueueStart(pDevContext->FfbWriteQ[id - 1]); // Mark FFB as active pDevContext->FfbEnable[id-1] = TRUE; } else { // FFB Deactivated pDevContext->FfbEnable[id-1] = FALSE; // Purge queues WdfIoQueuePurge(pDevContext->FfbWriteQ[id - 1], NULL, NULL); WdfIoQueuePurge(pDevContext->FfbReadQ[id - 1], NULL, NULL); }; }
VOID SerialPurgeRequests( IN WDFQUEUE QueueToClean, IN WDFREQUEST *CurrentOpRequest ) /*++ Routine Description: This function is used to cancel all queued and the current irps for reads or for writes. Called at DPC level. Arguments: QueueToClean - A pointer to the queue which we're going to clean out. CurrentOpRequest - Pointer to a pointer to the current request. Return Value: None. --*/ { NTSTATUS status; PREQUEST_CONTEXT reqContext; WdfIoQueuePurge(QueueToClean, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT); // // The queue is clean. Now go after the current if // it's there. // if (*CurrentOpRequest) { PFN_WDF_REQUEST_CANCEL CancelRoutine; reqContext = SerialGetRequestContext(*CurrentOpRequest); CancelRoutine = reqContext->CancelRoutine; // // Clear the common cancel routine but don't clear the reference because the // request specific cancel routine called below will clear the reference. // status = SerialClearCancelRoutine(*CurrentOpRequest, FALSE); if (NT_SUCCESS(status)) { // // Let us just call the CancelRoutine to start the next request. // if(CancelRoutine) { CancelRoutine(*CurrentOpRequest); } } } }
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; }