将 NDIS 微型端口驱动程序移植到 NetAdapterCx

本页介绍如何将 NDIS 6. x 微型端口驱动程序转换为 NetAdapterCx 客户端驱动程序。

有关 WDF 的一般信息,请查看 Wdf 驱动程序开发指南

编译设置

在 Visual Studio 中打开现有的 NDIS 微型端口驱动程序项目,并使用以下步骤将其转换为 KMDF 项目。

  1. 首先,导航到 "配置属性- > 驱动程序设置 > 驱动程序模型",并验证 "驱动程序类型" 是否设置为 "KMDF",并且KMDF "主版本" 和 " KMDF 版本" 是空的。

  2. 在项目属性中,打开驱动程序设置 > 网络适配器驱动程序,然后将网络适配器类扩展的链接设置为"是"

    • 如果转换后的驱动程序仍将调用 NDIS Api,请继续与链接 ndis.lib
  3. 删除 NDIS 预处理器宏,如 NDIS650_MINIPORT=1

  4. 将以下标头添加到 (的每个源文件,或添加到公共/预编译标头) :

    #include <ntddk.h>
    #include <wdf.h>
    #include <netadaptercx.h>
    
  5. 标准 WDF 修饰 添加到 INF:

    [Yourdriver.Wdf]
    KmdfService = Yourdriverservice, Yourdriver.wdfsect
    
    [Yourdriver.wdfsect]
    KmdfLibraryVersion = <insert here>
    
  6. 将新的所需的网络关键字添加到 INF 的 NT 部分:

驱动程序初始化

DriverEntry中删除对NdisMRegisterMiniportDriver的调用,并添加以下内容:

WDF_DRIVER_CONFIG_INIT(&config, EvtDriverDeviceAdd);
status = WdfDriverCreate(. . . );
if (!NT_SUCCESS(status)) {
  return status;
}

如果已设置,则从对WdfDriverCreate的调用中删除WdfDriverInitNoDispatchOverride标志。

DriverUnload 是 WDF 网络客户端驱动程序的可选例程,因此可以根据需要将其删除。 不要从DriverUnload调用NdisMDeregisterMiniportDriver

设备初始化

接下来,你要将 MiniportInitializeEx 中的代码分发到适当的 WDF 事件回调处理程序中,其中几个是可选的。 有关回调序列的详细信息,请参阅 网络适配器 WDF 客户端驱动程序的启动顺序

当你启动网络适配器时,但在调用NetAdapterStart之前,你将调用等效于NdisMSetMiniportAttributes的方法。 但是,客户端驱动程序将调用不同的功能来设置不同类型的功能,而不是使用泛型 NDIS_MINIPORT_ADAPTER_ATTRIBUTES 结构调用一个例程。

有关回调的信息,需要提供和何时启动网络适配器,请参阅 设备和适配器初始化

正在从注册表读取配置

接下来,将 NetConfiguration*NdisOpenConfigurationEx和相关函数的调用替换为方法。 这些 NetConfiguration* 方法类似 Ndis*Configuration* 于函数,无需重构代码。

有关详细信息,请参阅 访问配置信息

从用户模式接收 i/o 控制代码 (IOTCLs)

如果 NDIS 驱动程序调用 NdisRegisterDeviceEx(用于创建控制设备对象 (CDO) 从用户模式接收 IOCTLs),请阅读本部分。

下面是在 WDF 网络客户端驱动程序中执行此操作的两种方法。

最简单的方法是通过从客户端的EVT_WDF_DRIVER_DEVICE_ADD回调调用WdfControlDeviceInitAllocate来创建控制设备对象。 有关详细信息,请参阅 使用控制设备对象

但是,建议的解决方法是创建设备接口,如 使用设备接口中所述。

完成设备初始化

EVT_WDF_DRIVER_DEVICE_ADD中,你可以执行任何其他操作,例如分配中断。

处理电源状态更改通知

WDF 客户端驱动程序不会收到电源状态更改的 OID_PNP_SET_POWER

而 WDF 客户端将注册可选的回调函数以接收电源状态更改通知。 有关概述,请参阅 支持功能驱动程序中的 PnP 和电源管理

通常, OID_PNP_SET_POWER 处理程序中的代码会移动到 EVT_WDF_DEVICE_D0_EXITEVT_WDF_DEVICE_D0_ENTRY

由于 WDF 电源状态计算机略有不同,因此你可能需要对代码进行细微的修改。

具体而言,在其 MiniportInitializeEx 回调函数中,NDIS 微型端口驱动程序执行一次性初始化任务,并执行工作以使设备进入 D0 状态。 然后,它重复工作以在其 OID_PNP_SET_POWER 处理程序中转向 D0。

与此相反,WDF 客户端会在 EVT_WDF_DEVICE_D0_ENTRY之前在事件回调中执行一次性初始化任务,在这种情况下,设备处于低功耗状态。 然后,它会执行 EVT_WDF_DEVICE_D0_ENTRY中的 D0 操作。

总之,在 WDF 中,将 "转到 D0" 代码放在一个位置,而不是两个位置。

有关回调序列的详细信息,请参阅 NetAdapterCx 客户端驱动程序的启动顺序

查询和设置电源管理功能

同样,WDF 客户端驱动程序不会接收 OID_PM_PARAMETERS 来查询或设置网络适配器的电源管理硬件功能。

相反,驱动程序从 NETPOWERSETTINGS 对象查询必要的 LAN 唤醒 (WoL) 配置。 有关详细信息,请参阅 配置电源管理

返回的实际标志与对 NDIS 6 微型端口的语义相同,因此不需要对逻辑进行深层更改。 主要区别在于,你现在可以在关机序列中查询这些标志。 请参阅 NetAdapterCx 客户端驱动程序的关闭顺序

移动此代码后,可以删除 OID_PNP_SET_POWEROID_PM_PARAMETERS的 OID 处理程序。

由于 Get-netadapter 框架使你的设备处于 D0 状态,而主机使用网络接口,因此,客户端通常不实现电源逻辑;默认的 Get-netadapter 电源行为已经足够。

数据路径

数据路径编程模型发生了重大更改。 下面是一些重要的区别:

删除设备

WDF NIC 驱动程序的设备删除与任何其他 WDF 设备驱动程序中的相同,无需进行网络特定的处理。 网络数据路径首先关闭,然后是 WDF 设备。 有关 WDF 关闭的信息,请参阅 断开 a 设备的用户

你的 MiniportHaltEx 处理程序可能分布 EVT_WDF_DEVICE_D0_EXITEVT_WDF_DEVICE_RELEASE_HARDWARE之间。

WDF 客户端无需删除它创建的 Get-netadapter 或任何数据路径队列。 WDF 会自动删除这些对象。

可以删除 MiniportShutdownExMiniportResetExMiniportCheckForHangEx。 不再支持这些回调。

NDIS-WDF 函数等效项

大多数 NdisXxx 函数可以替换为 WDF 等效项。 通常,您应该会发现您需要从中 NDIS.SYS 导入的功能非常少。

有关函数等效项的列表,请参阅 NDIS-WDF 函数等效项

调试

请参阅 调试 NetAdapterCx 客户端驱动程序

! Ndiskd get-netadapter调试程序扩展显示了与 NDIS 6 驱动程序的结果类似的结果。

结论

使用本主题中的步骤,应该有一个可启动和停止设备的工作驱动程序。