summaryrefslogtreecommitdiff
path: root/network/netadaptercx/netvadapter/drivercode
diff options
context:
space:
mode:
author5an7y-Microsoft <[email protected]>2026-06-19 13:23:44 -0700
committerGitHub <[email protected]>2026-06-19 13:23:44 -0700
commit26741c75857c7df2fd95efe632f8f5f70b71fdbb (patch)
tree58d74336b33f09a11d9427f8eba76f7fa84d9d47 /network/netadaptercx/netvadapter/drivercode
parente99ae832b48b245404f9bd750af4864247b061e8 (diff)
parent8315a48cc6aac0c02d2218b0147457a01de4f885 (diff)
Merge pull request #1394 from youyanggit/WifiihvsampleDataPath
Add End-to-End NetAdapterCx/WiFiCx Sample Drivers and OEM Communication Examples
Diffstat (limited to 'network/netadaptercx/netvadapter/drivercode')
-rw-r--r--network/netadaptercx/netvadapter/drivercode/device.cpp126
-rw-r--r--network/netadaptercx/netvadapter/drivercode/device.h50
-rw-r--r--network/netadaptercx/netvadapter/drivercode/driver.cpp98
-rw-r--r--network/netadaptercx/netvadapter/drivercode/memorymanagement.cpp89
-rw-r--r--network/netadaptercx/netvadapter/drivercode/pch.hpp14
-rw-r--r--network/netadaptercx/netvadapter/drivercode/power.cpp73
-rw-r--r--network/netadaptercx/netvadapter/drivercode/power.h10
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
+);