diff options
| author | karlf <[email protected]> | 2016-08-11 13:28:13 -0700 |
|---|---|---|
| committer | karlf <[email protected]> | 2016-08-11 13:28:13 -0700 |
| commit | 96eb96dfb613e4c745db6bd1f53a92fe7e2290fc (patch) | |
| tree | ad5f3ede5cbcd6b598677ce41bcf8318471bdd92 /usb/UcmCxUcsi/Fdo.cpp | |
| parent | 687b274aa38fd05c8c26e3068932121876d7f745 (diff) | |
Updated for "Windows 10 Anniversary Update" (Version 1607)
Diffstat (limited to 'usb/UcmCxUcsi/Fdo.cpp')
| -rw-r--r-- | usb/UcmCxUcsi/Fdo.cpp | 385 |
1 files changed, 385 insertions, 0 deletions
diff --git a/usb/UcmCxUcsi/Fdo.cpp b/usb/UcmCxUcsi/Fdo.cpp new file mode 100644 index 00000000..88aa9129 --- /dev/null +++ b/usb/UcmCxUcsi/Fdo.cpp @@ -0,0 +1,385 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + Fdo.cpp + +Abstract: + + FDO callbacks, functions, and types. + +Environment: + + Kernel-mode only. + +--*/ + +#include "Pch.h" +#include "Fdo.tmh" + +EXTERN_C_START + +EVT_WDF_DEVICE_PREPARE_HARDWARE Fdo_EvtDevicePrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE Fdo_EvtDeviceReleaseHardware; +EVT_WDF_DEVICE_D0_ENTRY Fdo_EvtDeviceD0Entry; +EVT_WDF_DEVICE_D0_EXIT Fdo_EvtDeviceD0Exit; +EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT Fdo_EvtDeviceSelfManagedIoInit; +EVT_WDF_DEVICE_SELF_MANAGED_IO_RESTART Fdo_EvtDeviceSelfManagedIoRestart; + +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS +Fdo_Initialize ( + _In_ PFDO_CONTEXT FdoCtx + ); + +EXTERN_C_END + +#pragma alloc_text(PAGE, Fdo_Create) +#pragma alloc_text(PAGE, Fdo_Initialize) +#pragma alloc_text(PAGE, Fdo_EvtDevicePrepareHardware) +#pragma alloc_text(PAGE, Fdo_EvtDeviceReleaseHardware) +#pragma alloc_text(PAGE, Fdo_EvtDeviceD0Entry) +#pragma alloc_text(PAGE, Fdo_EvtDeviceD0Exit) +#pragma alloc_text(PAGE, Fdo_EvtDeviceSelfManagedIoInit) +#pragma alloc_text(PAGE, Fdo_EvtDeviceSelfManagedIoRestart) + + +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS +Fdo_Create ( + _Inout_ PWDFDEVICE_INIT DeviceInit + ) +{ + WDF_OBJECT_ATTRIBUTES attributes; + WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; + PFDO_CONTEXT fdoCtx; + WDFDEVICE wdfDevice; + NTSTATUS status; + + PAGED_CODE(); + + TRACE_FUNC_ENTRY(TRACE_FLAG_FDO); + + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); + pnpPowerCallbacks.EvtDevicePrepareHardware = Fdo_EvtDevicePrepareHardware; + pnpPowerCallbacks.EvtDeviceReleaseHardware = Fdo_EvtDeviceReleaseHardware; + pnpPowerCallbacks.EvtDeviceD0Entry = Fdo_EvtDeviceD0Entry; + pnpPowerCallbacks.EvtDeviceD0Exit = Fdo_EvtDeviceD0Exit; + pnpPowerCallbacks.EvtDeviceSelfManagedIoInit = Fdo_EvtDeviceSelfManagedIoInit; + pnpPowerCallbacks.EvtDeviceSelfManagedIoRestart = Fdo_EvtDeviceSelfManagedIoRestart; + WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); + + WdfDeviceInitSetPowerPageable(DeviceInit); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, FDO_CONTEXT); + status = WdfDeviceCreate(&DeviceInit, &attributes, &wdfDevice); + if (!NT_SUCCESS(status)) + { + TRACE_ERROR(TRACE_FLAG_FDO, "[DeviceInit: 0x%p] WdfDeviceCreate failed - %!STATUS!", DeviceInit, status); + goto Exit; + } + + fdoCtx = Fdo_GetContext(wdfDevice); + fdoCtx->WdfDevice = wdfDevice; + + status = Fdo_Initialize(fdoCtx); + if (!NT_SUCCESS(status)) + { + goto Exit; + } + + status = Ppm_Initialize(&fdoCtx->PpmCtx); + if (!NT_SUCCESS(status)) + { + goto Exit; + } + + TRACE_INFO(TRACE_FLAG_FDO, "[Device: 0x%p] Device created", wdfDevice); + +Exit: + + TRACE_FUNC_EXIT(TRACE_FLAG_FDO); + + return status; +} + + +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS +Fdo_Initialize ( + _In_ PFDO_CONTEXT FdoCtx + ) +{ + WDFDEVICE device; + WDF_DEVICE_STATE deviceState; + + PAGED_CODE(); + + TRACE_FUNC_ENTRY(TRACE_FLAG_FDO); + + device = FdoCtx->WdfDevice; + + // + // ACPI-enumerated devices are not disableable by default. Override that, + // since there is no need for that restriction. + // + + WDF_DEVICE_STATE_INIT(&deviceState); + deviceState.NotDisableable = WdfFalse; + WdfDeviceSetDeviceState(device, &deviceState); + + TRACE_INFO(TRACE_FLAG_FDO, "[Device: 0x%p] FDO initialized", device); + + TRACE_FUNC_EXIT(TRACE_FLAG_FDO); + + return STATUS_SUCCESS; +} + + +NTSTATUS +Fdo_EvtDevicePrepareHardware ( + _In_ WDFDEVICE Device, + _In_ WDFCMRESLIST ResourcesRaw, + _In_ WDFCMRESLIST ResourcesTranslated + ) +{ + NTSTATUS status; + PFDO_CONTEXT fdoCtx; + ULONG index; + ULONG resourceCount; + BOOLEAN allResourcesFound; + PCM_PARTIAL_RESOURCE_DESCRIPTOR res; + PCM_PARTIAL_RESOURCE_DESCRIPTOR rawRes; + + PAGED_CODE(); + + TRACE_FUNC_ENTRY(TRACE_FLAG_FDO); + + fdoCtx = Fdo_GetContext(Device); + resourceCount = WdfCmResourceListGetCount(ResourcesTranslated); + allResourcesFound = FALSE; + + for (index = 0; !allResourcesFound && (index < resourceCount); ++index) + { + res = WdfCmResourceListGetDescriptor(ResourcesTranslated, index); + if (res->Type != CmResourceTypeMemory) + { + continue; + } + + rawRes = WdfCmResourceListGetDescriptor(ResourcesRaw, index); + + // + // Verify if address is below 4GB and not straddling the 4GB boundary. + // + + if ((rawRes->u.Memory.Start.HighPart != 0) || + ((rawRes->u.Memory.Start.LowPart + rawRes->u.Memory.Length) < + rawRes->u.Memory.Start.LowPart)) + { + status = STATUS_INSUFFICIENT_RESOURCES; + TRACE_ERROR(TRACE_FLAG_FDO, "[Device: 0x%p] Memory resource address (%I64x) not below 4GB", Device, rawRes->u.Memory.Start.QuadPart); + goto Exit; + } + + status = Ppm_PrepareHardware(&fdoCtx->PpmCtx, res->u.Memory.Start, res->u.Memory.Length); + if (!NT_SUCCESS(status)) + { + goto Exit; + } + + allResourcesFound = TRUE; + } + + if (allResourcesFound == FALSE) + { + status = STATUS_INSUFFICIENT_RESOURCES; + TRACE_ERROR(TRACE_FLAG_FDO, "[Device: 0x%p] Could not find required resources", Device); + goto Exit; + } + + status = Acpi_PrepareHardware(&fdoCtx->AcpiCtx); + if (!NT_SUCCESS(status)) + { + goto Exit; + } + + TRACE_INFO(TRACE_FLAG_FDO, "[Device: 0x%p] Prepare hardware completed", Device); + +Exit: + + TRACE_FUNC_EXIT(TRACE_FLAG_FDO); + + return status; +} + + +NTSTATUS +Fdo_EvtDeviceReleaseHardware ( + _In_ WDFDEVICE Device, + _In_ WDFCMRESLIST ResourcesTranslated + ) +{ + PFDO_CONTEXT fdoCtx; + + UNREFERENCED_PARAMETER(ResourcesTranslated); + + PAGED_CODE(); + + TRACE_FUNC_ENTRY(TRACE_FLAG_FDO); + + fdoCtx = Fdo_GetContext(Device); + + Acpi_ReleaseHardware(&fdoCtx->AcpiCtx); + + Ppm_ReleaseHardware(&fdoCtx->PpmCtx); + + TRACE_INFO(TRACE_FLAG_FDO, "[Device: 0x%p] Release hardware completed", Device); + + TRACE_FUNC_EXIT(TRACE_FLAG_FDO); + + return STATUS_SUCCESS; +} + + +NTSTATUS +Fdo_EvtDeviceD0Entry ( + _In_ WDFDEVICE Device, + _In_ WDF_POWER_DEVICE_STATE PreviousState + ) +{ + NTSTATUS status; + PFDO_CONTEXT fdoCtx; + + PAGED_CODE(); + + TRACE_FUNC_ENTRY(TRACE_FLAG_FDO); + + fdoCtx = Fdo_GetContext(Device); + + TRACE_INFO(TRACE_FLAG_FDO, "[Device: 0x%p] Entering D0 from %!WDF_POWER_DEVICE_STATE!", Device, PreviousState); + + status = Ppm_PowerOn(&fdoCtx->PpmCtx); + if (!NT_SUCCESS(status)) + { + goto Exit; + } + +Exit: + + TRACE_FUNC_EXIT(TRACE_FLAG_FDO); + + return status; +} + + +NTSTATUS +Fdo_EvtDeviceD0Exit ( + _In_ WDFDEVICE Device, + _In_ WDF_POWER_DEVICE_STATE TargetState + ) +{ + PFDO_CONTEXT fdoCtx; + + PAGED_CODE(); + + TRACE_FUNC_ENTRY(TRACE_FLAG_FDO); + + fdoCtx = Fdo_GetContext(Device); + + TRACE_INFO(TRACE_FLAG_FDO, "[Device: 0x%p] Exiting D0 to %!WDF_POWER_DEVICE_STATE!", Device, TargetState); + + Ppm_PowerOff(&fdoCtx->PpmCtx); + + TRACE_FUNC_EXIT(TRACE_FLAG_FDO); + + return STATUS_SUCCESS; +} + + +NTSTATUS +Fdo_EvtDeviceSelfManagedIoInit ( + _In_ WDFDEVICE Device + ) +{ + NTSTATUS status; + PPPM_CONTEXT ppmCtx; + UCM_MANAGER_CONFIG ucmConfig; + + PAGED_CODE(); + + TRACE_FUNC_ENTRY(TRACE_FLAG_FDO); + + ppmCtx = &Fdo_GetContext(Device)->PpmCtx; + + // + // Since the PPM uses a power-managed queue to handle command requests, self-managed I/O init + // is when we can start processing commands. + // + + UCM_MANAGER_CONFIG_INIT(&ucmConfig); + + // + // Initialize our device with UCM. + // + + status = UcmInitializeDevice(Device, &ucmConfig); + if (!NT_SUCCESS(status)) + { + TRACE_ERROR(TRACE_FLAG_FDO, "[Device: 0x%p] UcmInitializeDevice failed - %!STATUS!", Device, status); + goto Exit; + } + + + status = Ucm_CreateConnectors(ppmCtx); + if (!NT_SUCCESS(status)) + { + goto Exit; + } + + // + // Connector objects are ready. Now we can enable all notifications. + // + + status = Ppm_EnableNotifications(ppmCtx); + if (!NT_SUCCESS(status)) + { + goto Exit; + } + +Exit: + + TRACE_FUNC_EXIT(TRACE_FLAG_FDO); + + return status; +} + + +NTSTATUS +Fdo_EvtDeviceSelfManagedIoRestart ( + _In_ WDFDEVICE Device + ) +{ + NTSTATUS status; + PPPM_CONTEXT ppmCtx; + + PAGED_CODE(); + + TRACE_FUNC_ENTRY(TRACE_FLAG_FDO); + + ppmCtx = &Fdo_GetContext(Device)->PpmCtx; + + status = Ppm_EnableNotifications(ppmCtx); + if (!NT_SUCCESS(status)) + { + goto Exit; + } + +Exit: + + TRACE_FUNC_EXIT(TRACE_FLAG_FDO); + + return status; +} |
