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

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

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

编译设置

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

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

  2. 在项目属性中,打开 Driver 设置->Network Adapter Driver,并将“链接到网络适配器类扩展”设置为“是”。

    • 如果转换后的驱动程序仍会调用 NDIS API,请继续链接到 ndis.lib该 API。
  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. 将新的所需网络关键字 (keyword)添加到 INF 的 NT 部分:

    • *If连接orPresent

    • *连接ionType

    • *DirectionType

    • *AccessType

    • *HardwareLoopback

      有关这些关键字 (keyword)和示例的详细信息,请参阅 NetAdapterCx 客户端驱动程序的 INF 文件。

驱动程序初始化

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 客户端驱动程序的 Power-Up 序列。

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

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

从注册表读取配置

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

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

从用户模式接收 I/O 控制代码(IOCTL)

如果 NDIS 驱动程序调用 NdisRegisterDeviceEx(一个用于创建控制设备对象(CDO)的例程来从用户模式接收 IOCTL,请阅读此部分。

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

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

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

完成设备初始化

此时 ,在EVT_WDF_DRIVER_DEVICE_ADD中,可以执行任何要初始化设备的其他操作,例如分配中断。

处理电源状态更改通知

WDF 客户端驱动程序不会收到电源状态更改OID_PNP_标准版T_POWER

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

通常,OID_PNP_标准版T_POWER处理程序中的代码将移动到EVT_WDF_DEVICE_D0_EXITEVT_WDF_DEVICE_D0_ENTRY

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

具体而言,在 MiniportInitializeEx 回调函数中,NDIS 微型端口驱动程序执行一次性初始化任务,以及将设备引入 D0 状态的工作。 然后,它会重复工作以转到其OID_PNP_标准版T_POWER处理程序中的 D0。

相比之下,WDF 客户端在EVT_WDF_DEVICE_D0_ENTRY之前在事件回调中执行一次性初始化任务,在此期间设备处于低功率状态。 然后,它会在EVT_WDF_DEVICE_D0_ENTRY中执行 D0 的工作。

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

有关回调序列的详细信息,请参阅 NetAdapterCx 客户端驱动程序的 Power-Up 序列。

查询和设置电源管理功能

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

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

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

移动此代码后,可以删除用于OID_PNP_标准版T_POWEROID_PM_PARAMETERSOID 处理程序。

由于 NetAdapter 框架在主机使用网络接口时将设备保持在 D0,因此客户端通常不实现电源逻辑;默认的 NetAdapter 电源行为已足够。

数据路径

数据路径编程模型发生了显著变化。 下面是一些主要差异:

删除设备

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

MiniportHaltEx 处理程序很可能在EVT_WDF_DEVICE_D0_EXITEVT_WDF_DEVICE_RELEA标准版_HARDWARE之间分布。

WDF 客户端不需要删除 NetAdapter 或其创建的任何数据路径队列。 WDF 会自动删除这些对象。

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

NDIS-WDF 函数等效项

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

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

调试

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

!ndiskd.netadapter 调试器扩展显示的结果与 NDIS 6 驱动程序的 !ndiskd.miniport 显示的结果类似。

结束语

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

注意:NetAdapterCx 当前不支持 iSCSI 启动。