diff options
| author | 5an7y-Microsoft <[email protected]> | 2026-07-09 14:59:40 -0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-07-09 14:59:40 -0700 |
| commit | 15640356a5a6eeafefff403f6d287821213635cd (patch) | |
| tree | 49e5fcd168d50912decc42dda76767b3566887b1 /network/netadaptercx/netvadapter/drivercode | |
| parent | 7c8087c61eb674e321458f935b6676652c39924d (diff) | |
| parent | 2ee527bfeb0aeb6be11f0a8b6dce4011b358ce89 (diff) | |
Merge pull request #1402 from microsoft/main
FI: Main -> Develop
Diffstat (limited to 'network/netadaptercx/netvadapter/drivercode')
7 files changed, 460 insertions, 0 deletions
diff --git a/network/netadaptercx/netvadapter/drivercode/device.cpp b/network/netadaptercx/netvadapter/drivercode/device.cpp new file mode 100644 index 00000000..6cbad327 --- /dev/null +++ b/network/netadaptercx/netvadapter/drivercode/device.cpp @@ -0,0 +1,126 @@ +// Copyright (c) Microsoft Corporation. All rights reserved + +#include "pch.hpp" + +#include <wil/resource.h> + +#include "netvadapter.h" +#include "device.h" +#include "trace.h" +#include "device.tmh" +#include "power.h" + +static +EVT_NET_ADAPTER_CREATE_TXQUEUE + EvtAdapterCreateTxQueue; + +static +EVT_NET_ADAPTER_CREATE_RXQUEUE + EvtAdapterCreateRxQueue; + +NetvDevice::NetvDevice( + WDFDEVICE Handle +) + : m_triage(WdfGetTriageInfo()) + , m_handle(Handle) +{ +} + +_Use_decl_annotations_ +NTSTATUS +NetvDevice::Initialize( + void +) +{ + using unique_adapterinit = wil::unique_any<NETADAPTER_INIT*, + decltype(&::NetAdapterInitFree), + ::NetAdapterInitFree>; + + unique_adapterinit adapterInit{NetAdapterInitAllocate(m_handle)}; + RETURN_NTSTATUS_IF( + STATUS_INSUFFICIENT_RESOURCES, + ! adapterInit); + + NET_ADAPTER_DATAPATH_CALLBACKS datapathCallbacks; + NET_ADAPTER_DATAPATH_CALLBACKS_INIT( + &datapathCallbacks, + EvtAdapterCreateTxQueue, + EvtAdapterCreateRxQueue); + + NetAdapterInitSetDatapathCallbacks( + adapterInit.get(), + &datapathCallbacks); + + WDF_OBJECT_ATTRIBUTES adapterAttributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&adapterAttributes, NetvAdapter); + adapterAttributes.EvtDestroyCallback = [](WDFOBJECT Handle) { + NetvAdapterGetContext(static_cast<NETADAPTER>(Handle))->Destroy(); + }; + + NETADAPTER netAdapter; + RETURN_IF_NOT_STATUS_SUCCESS( + NetAdapterCreate(adapterInit.get(), &adapterAttributes, &netAdapter)); + + m_adapter = new (NetvAdapterGetContext(netAdapter)) NetvAdapter(netAdapter, m_handle); + + RETURN_IF_NOT_STATUS_SUCCESS( + m_adapter->Initialize()); + + RETURN_STATUS_SUCCESS(); +} + +NTSTATUS +NetvDevice::PrepareHardware( + WDFCMRESLIST ResourcesRaw, + WDFCMRESLIST ResourcesTranslated +) +{ + UNREFERENCED_PARAMETER(ResourcesRaw); + UNREFERENCED_PARAMETER(ResourcesTranslated); + + NetvDeviceInitializePowerManagement(this); + + RETURN_IF_NOT_STATUS_SUCCESS( + m_adapter->ConfigureDataCapabilities()); + + RETURN_IF_NOT_STATUS_SUCCESS( + NetAdapterStart(m_adapter->m_handle)); + + RETURN_STATUS_SUCCESS(); +} + +_Use_decl_annotations_ +NTSTATUS +EvtDevicePrepareHardware( + WDFDEVICE Device, + WDFCMRESLIST ResourcesRaw, + WDFCMRESLIST ResourcesTranslated + ) +{ + return NetvDeviceGetContext(Device)->PrepareHardware(ResourcesRaw, ResourcesTranslated); +} + +_Use_decl_annotations_ +NTSTATUS +EvtAdapterCreateTxQueue( + NETADAPTER Adapter, + NETTXQUEUE_INIT * Init +) +{ + return NetvAdapterGetContext(Adapter)->CreateTxQueue(Init); +} + +_Use_decl_annotations_ +NTSTATUS +EvtAdapterCreateRxQueue( + NETADAPTER Adapter, + NETRXQUEUE_INIT * Init +) +{ + return NetvAdapterGetContext(Adapter)->CreateRxQueue(Init); +} + +NetvAdapter* NetvAdapterGetContextFromWDFObject(NETADAPTER netAdapter) +{ + return NetvAdapterGetContext(netAdapter); +} diff --git a/network/netadaptercx/netvadapter/drivercode/device.h b/network/netadaptercx/netvadapter/drivercode/device.h new file mode 100644 index 00000000..3b8e5d2d --- /dev/null +++ b/network/netadaptercx/netvadapter/drivercode/device.h @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved + +#pragma once + +#include "netvadapter.h" + +class NetvDevice +{ + +public: + + // + // Do not add variable before WdfTriageInfoPtr. + // NetAdapterCx carving code requires the first field of + // WDF context to be a pointer to WDF_TRIAGE_INFO. + // + void * + m_triage = nullptr; + + NetvDevice( + WDFDEVICE Handle + ); + + NTSTATUS + Initialize( + void + ); + + NTSTATUS + PrepareHardware( + WDFCMRESLIST ResourcesRaw, + WDFCMRESLIST ResourcesTranslated + ); + +public: // private: + + WDFDEVICE + m_handle = WDF_NO_HANDLE; + + NetvAdapter * + m_adapter = nullptr; + +}; +static_assert(FIELD_OFFSET(NetvDevice, m_triage) == 0u); + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(NetvDevice, NetvDeviceGetContext); +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(NetvAdapter, NetvAdapterGetContext); + +EVT_WDF_DEVICE_PREPARE_HARDWARE + EvtDevicePrepareHardware; diff --git a/network/netadaptercx/netvadapter/drivercode/driver.cpp b/network/netadaptercx/netvadapter/drivercode/driver.cpp new file mode 100644 index 00000000..393292c1 --- /dev/null +++ b/network/netadaptercx/netvadapter/drivercode/driver.cpp @@ -0,0 +1,98 @@ +// Copyright (c) Microsoft Corporation. All rights reserved + +#include "pch.hpp" + +#include <wil/resource.h> + +#include "netvadapter.h" +#include "trace.h" +#include "driver.tmh" +#include "device.h" +#include "power.h" + +GLOBAL_CONTEXT NetvGlobalContext; + +EXTERN_C +DRIVER_INITIALIZE + DriverEntry; + +EVT_WDF_DRIVER_DEVICE_ADD EvtDriverDeviceAdd; +EVT_WDF_DRIVER_UNLOAD EvtDriverUnload; + +_Use_decl_annotations_ +NTSTATUS +DriverEntry( + PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath + ) +{ + WPP_INIT_TRACING(DriverObject, RegistryPath); + + WDF_DRIVER_CONFIG config; + WDF_DRIVER_CONFIG_INIT(&config, EvtDriverDeviceAdd); + config.EvtDriverUnload = EvtDriverUnload; + + NTSTATUS status = WdfDriverCreate(DriverObject, + RegistryPath, + WDF_NO_OBJECT_ATTRIBUTES, + &config, + NULL); + + if (!NT_SUCCESS(status)) + { + LogError(FLAG_DRIVER, "%!STATUS! WdfDriverCreate", status); + WPP_CLEANUP(DriverObject); + + return status; + } + + RETURN_STATUS_SUCCESS(); +} + +_Use_decl_annotations_ +NTSTATUS +EvtDriverDeviceAdd( + WDFDRIVER Driver, + PWDFDEVICE_INIT DeviceInit + ) +{ + UNREFERENCED_PARAMETER(Driver); + + RETURN_IF_NOT_STATUS_SUCCESS( + NetDeviceInitConfig(DeviceInit)); + + WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); + pnpPowerCallbacks.EvtDevicePrepareHardware = EvtDevicePrepareHardware; + WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); + + WDF_POWER_POLICY_EVENT_CALLBACKS powerPolicyCallbacks; + WDF_POWER_POLICY_EVENT_CALLBACKS_INIT(&powerPolicyCallbacks); + powerPolicyCallbacks.EvtDeviceArmWakeFromS0 = EvtDeviceArmWakeFromS0; + powerPolicyCallbacks.EvtDeviceDisarmWakeFromS0 = EvtDeviceDisarmWakeFromS0; + WdfDeviceInitSetPowerPolicyEventCallbacks(DeviceInit, &powerPolicyCallbacks); + + WDF_OBJECT_ATTRIBUTES deviceAttributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, NetvDevice); + + WDFDEVICE wdfDevice; + RETURN_IF_NOT_STATUS_SUCCESS( + WdfDeviceCreate(&DeviceInit, &deviceAttributes, &wdfDevice)); + + auto device = new (NetvDeviceGetContext(wdfDevice)) NetvDevice(wdfDevice); + + RETURN_IF_NOT_STATUS_SUCCESS( + device->Initialize()); + + RETURN_STATUS_SUCCESS(); +} + +_Use_decl_annotations_ +VOID +EvtDriverUnload( + WDFDRIVER Driver +) +{ + UNREFERENCED_PARAMETER(Driver); + WPP_CLEANUP(WdfDriverWdmGetDriverObject(Driver)); +} diff --git a/network/netadaptercx/netvadapter/drivercode/memorymanagement.cpp b/network/netadaptercx/netvadapter/drivercode/memorymanagement.cpp new file mode 100644 index 00000000..29a2006a --- /dev/null +++ b/network/netadaptercx/netvadapter/drivercode/memorymanagement.cpp @@ -0,0 +1,89 @@ +// Copyright (c) Microsoft Corporation. All rights reserved +// +// Global operator new / delete for the driver. +// +// The shared netvadapterlibrary routes its allocations through the global +// operator new (see memory.cpp in the library, which provides the nothrow +// variant that forwards to operator new(size_t)). The client driver is +// responsible for providing the backing implementation. We use WDF managed +// memory so that the same implementation works for both KMDF and UMDF, the +// same approach used by the WIFICX sample. + +#include "pch.hpp" + +#define NETV_POOL_TAG 'vteN' + +struct NETV_MEMORY_HEADER +{ + size_t HeaderSize; + WDFMEMORY WdfMemoryHandle; +}; + +static void* AllocateBuffer(size_t Size) +{ + const size_t totalSize = Size + sizeof(NETV_MEMORY_HEADER); + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + WDFMEMORY wdfMemory = WDF_NO_HANDLE; + void* buffer = nullptr; + + if (!NT_SUCCESS(WdfMemoryCreate(&attributes, NonPagedPoolNx, NETV_POOL_TAG, totalSize, &wdfMemory, &buffer))) + { + return nullptr; + } + + RtlZeroMemory(buffer, totalSize); + + auto header = static_cast<NETV_MEMORY_HEADER*>(buffer); + header->HeaderSize = sizeof(NETV_MEMORY_HEADER); + header->WdfMemoryHandle = wdfMemory; + + return reinterpret_cast<void*>(reinterpret_cast<ULONG_PTR>(buffer) + sizeof(NETV_MEMORY_HEADER)); +} + +static void FreeBuffer(void* Buffer) +{ + if (Buffer == nullptr) + { + return; + } + + auto header = reinterpret_cast<NETV_MEMORY_HEADER*>( + reinterpret_cast<ULONG_PTR>(Buffer) - sizeof(NETV_MEMORY_HEADER)); + + NT_ASSERT(header->HeaderSize == sizeof(NETV_MEMORY_HEADER)); + + WdfObjectDelete(header->WdfMemoryHandle); +} + +void* __cdecl operator new(size_t Size) +{ + return AllocateBuffer(Size); +} + +void* __cdecl operator new[](size_t Size) +{ + return AllocateBuffer(Size); +} + +void __cdecl operator delete(void* Buffer) noexcept +{ + FreeBuffer(Buffer); +} + +void __cdecl operator delete[](void* Buffer) noexcept +{ + FreeBuffer(Buffer); +} + +void __cdecl operator delete(void* Buffer, size_t) noexcept +{ + FreeBuffer(Buffer); +} + +void __cdecl operator delete[](void* Buffer, size_t) noexcept +{ + FreeBuffer(Buffer); +} diff --git a/network/netadaptercx/netvadapter/drivercode/pch.hpp b/network/netadaptercx/netvadapter/drivercode/pch.hpp new file mode 100644 index 00000000..b0e017ef --- /dev/null +++ b/network/netadaptercx/netvadapter/drivercode/pch.hpp @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved +#pragma once + +#include <initguid.h> + +#ifdef _KERNEL_MODE +#include <ntddk.h> +#else +#include <windows.h> +#include <new> +#endif + +#include <wdf.h> +#include <netadaptercx.h> diff --git a/network/netadaptercx/netvadapter/drivercode/power.cpp b/network/netadaptercx/netvadapter/drivercode/power.cpp new file mode 100644 index 00000000..68b057ff --- /dev/null +++ b/network/netadaptercx/netvadapter/drivercode/power.cpp @@ -0,0 +1,73 @@ +// Copyright (c) Microsoft Corporation. All rights reserved + +#include "pch.hpp" +#include "netvadapter.h" +#include "device.h" +#include "trace.h" +#include "power.h" +#include "power.tmh" + +void +NetvDeviceInitializePowerManagement( + _In_ NetvDevice * Device +) +{ +#ifdef _KERNEL_MODE + WDFDEVICE wdfDevice = Device->m_handle; + NetvAdapter * adapter = Device->m_adapter; + + if (!adapter->S0Idle) + { + return; + } + + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings; + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT( + &idleSettings, + IdleCanWakeFromS0); + + idleSettings.IdleTimeout = 3000; + idleSettings.IdleTimeoutType = SystemManagedIdleTimeoutWithHint; + + NTSTATUS ntStatus = WdfDeviceAssignS0IdleSettings( + wdfDevice, + &idleSettings); + + if (ntStatus != STATUS_SUCCESS) + { + // MSDN says we should ignore error codes from assign S0 idle settings, do that + return; + } + + // Now tell NetAdapterCx we support wake on packet filter match + NET_ADAPTER_WAKE_PACKET_FILTER_CAPABILITIES wakeOnPacketFilterMatch; + NET_ADAPTER_WAKE_PACKET_FILTER_CAPABILITIES_INIT(&wakeOnPacketFilterMatch); + wakeOnPacketFilterMatch.PacketFilterMatch = TRUE; + + NetAdapterWakeSetPacketFilterCapabilities(adapter->m_handle, &wakeOnPacketFilterMatch); +#else + UNREFERENCED_PARAMETER(Device); +#endif +} + +_Use_decl_annotations_ +NTSTATUS +EvtDeviceArmWakeFromS0( + WDFDEVICE Device +) +{ + auto adapter = NetvDeviceGetContext(Device)->m_adapter; + adapter->ArmWakeFromS0(); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +void +EvtDeviceDisarmWakeFromS0( + WDFDEVICE Device +) +{ + auto adapter = NetvDeviceGetContext(Device)->m_adapter; + adapter->DisarmWakeFromS0(); +} diff --git a/network/netadaptercx/netvadapter/drivercode/power.h b/network/netadaptercx/netvadapter/drivercode/power.h new file mode 100644 index 00000000..6a5e2399 --- /dev/null +++ b/network/netadaptercx/netvadapter/drivercode/power.h @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved +#pragma once + +EVT_WDF_DEVICE_ARM_WAKE_FROM_S0 EvtDeviceArmWakeFromS0; +EVT_WDF_DEVICE_DISARM_WAKE_FROM_S0 EvtDeviceDisarmWakeFromS0; + +void +NetvDeviceInitializePowerManagement( + _In_ NetvDevice * Device +); |
