summaryrefslogtreecommitdiff
path: root/usb/UcmCxUcsi/Fdo.cpp
diff options
context:
space:
mode:
authorkarlf <[email protected]>2016-08-11 13:28:13 -0700
committerkarlf <[email protected]>2016-08-11 13:28:13 -0700
commit96eb96dfb613e4c745db6bd1f53a92fe7e2290fc (patch)
treead5f3ede5cbcd6b598677ce41bcf8318471bdd92 /usb/UcmCxUcsi/Fdo.cpp
parent687b274aa38fd05c8c26e3068932121876d7f745 (diff)
Updated for "Windows 10 Anniversary Update" (Version 1607)
Diffstat (limited to 'usb/UcmCxUcsi/Fdo.cpp')
-rw-r--r--usb/UcmCxUcsi/Fdo.cpp385
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;
+}