在四种NDIS相关的驱动中,微型端口驱动(也经常翻译为为小端口驱动)位于驱动栈的底部,一般将它理解为NIC设备的驱动程序:
有几种类型的微型端口驱动程序类型:
- 无连接微型端口驱动程序用于控制无连接网络媒体 ,如以太网的网络接口卡 (NIC) 的微型端;
- 面向连接的微型端口驱动程序:面向连接的网络媒体编写微型端口驱动程序;
- WAN 微型端口驱动程序:控制广域网 (WAN) NIC 的微型端口驱动程序;
- 具有 WDM 下部接口的微型端口:该微型端口驱动程序与其他内核驱动程序进行交互,并且具有 Microsoft Windows 驱动程序模型 (WDM) 较低接口;
- IrDA 微型端口驱动程序:控制 IrDA 适配器的微型端口驱动程序;
- 支持可缩放网络的微型端口驱动程序:支持可缩放网络的微型端口驱动程序;
- 支持将 TCP/IP 卸载到硬件的微型端口驱动程序 ;
所有 NDIS 6.0 及更高版本的驱动程序都会反序列化。反序列化的 NDIS 微型端口驱动程序序列化其自己的 MiniportXxx 函数的操作,并在内部对所有发送请求进行排队,而不是依赖于 NDIS 来执行这些函数。 因此,与序列化微型端口驱动程序相比,反序列化的微型端口驱动程序可以实现明显更好的全双工性能。
反序列化的驱动程序模型是 NDIS 微型端口驱动程序的默认模型。 面向连接的微型端口驱动程序以及具有 WDM 下边缘的微型端口驱动程序必须是反序列化的驱动程序。
网络接口卡(NIC)支持
NDIS 微型端口驱动程序可以管理的网络接口卡 (NIC) 类型以及不同类型的 NIC 如何影响驱动程序传输网络数据的方式分类如下:
- 向 NDIS 报告 NIC 的中类型: 若要报告 NIC 的中等类型,微型端口驱动程序会将指针传递到 NdisMSetMiniportAttributes 函数的 MiniportAttributes 参数中的 NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES 结构。 微型端口驱动程序在初始化期间从其 MiniportInitializeEx 函数调用 NdisMSetMiniportAttributes。 微型端口驱动程序应在NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES结构中设置注册属性之后和设置任何其他属性之前设置 MiniportAttributes 属性。 必须设置 MiniportAttributes 属性。 驱动程序在设置 MiniportAttributes 属性时,将 NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES 结构的 MediaType 成员设置为适当的媒体类型。当过度的 NDIS 协议驱动程序调用 NdisOpenAdapterEx 以绑定到指定的微型端口适配器时,它会提供一个可以操作的介质类型的列表。 NDIS 使用微型端口驱动程序和协议驱动程序中的信息来设置绑定。 此绑定提供用于在驱动程序堆栈中上下传输网络数据的路径。
- 物理 NIC: 微型端口驱动程序完成初始化微型端口适配器以及发送和接收网络数据的步骤取决于物理设备的功能,如下所示。
- NDIS-WDM NIC:对于 NDIS-WDM NIC(例如基于 USB 的 NIC),微型端口驱动程序使用 DMA 管理内存的方式对 NDIS 并不重要,也不可见。
- 总线主 DMA NIC: 这些 NIC 可以通过板载 DMA 控制器直接访问主机内存,该控制器无需使用主机 CPU 即可管理网络与主机内存之间的数据传输。若要发送,微型端口驱动程序会设置 NIC 来映射传出缓冲区。 然后,微型端口驱动程序会导致设备从此内存开始传输。 NIC DMA 控制器将数据从共享系统内存传输到网络,并在发送完成后中断 CPU。 为了接收,DMA 控制器在通知主机中断之前将传入数据传输到主机内存。总线主 DMA NIC 通常具有一个板载环形缓冲区,微型端口驱动程序将该缓冲区映射到系统内存中的一组缓冲区。 通常,可以对 NIC 进行编程,以有效地处理多个数据包。 管理此类 NIC 的微型端口驱动程序通常支持多包发送和接收,因为 NIC 可以有效地处理多个数据包,从而提高其 I/O 吞吐量。
- 非总线主机 DMA NIC: 目前,非总线主机 DMA NIC 包括以下内容:
- 系统 DMA NIC:管理此类 NIC 的微型端口驱动程序使用系统 DMA 控制器来管理数据包数据与网络之间的传输。 数据传输需要主机 CPU 的配合。
- 虚拟 NIC 和微型端口: 在虚拟机中,NDIS 微型端口驱动程序可以将仅软件资源作为虚拟微型端口进行管理,也可以管理表示硬件资源的虚拟 NIC。
适配器状态
对于驱动管理的每个微型端口适配器, NDIS 微型端口驱动程序必须支持以下一组操作状态:
停止、关闭、正在初始化、已暂停、重新启动、正在运行、正在暂停,如下图:
注意 重置操作不会影响微型端口适配器的操作状态。 此外,重置操作正在进行时,适配器的状态可能会更改。 例如,当重置操作正在进行时,NDIS 可能会调用驱动程序的暂停处理程序。 在这种情况下,驱动程序可以按任何顺序完成重置或暂停操作,同时遵循每个操作的正常要求。 对于重置操作,驱动程序可能会使传输请求数据包失败,也可以让数据包保持排队并稍后完成。 但是,应注意在传输数据包挂起时,驱动程序无法完成暂停操作。
下面定义了适配器状态:
- “已停止 ”是所有微型端口适配器的初始状态。 当微型端口适配器处于“已停止”状态,并且 NDIS 调用驱动程序的 MiniportInitializeEx 函数来初始化微型端口适配器时,微型端口适配器将进入“正在初始化”状态。 如果 MiniportInitializeEx 失败,微型端口适配器将返回到 Halted 状态。 当微型端口适配器处于“已暂停”状态并且 NDIS 调用 MiniportHaltEx 函数时,微型端口适配器将返回到“已暂停”状态;
- 在系统关闭并重新启动之前,不能使用处于 关闭 状态的微型端口适配器。 当微型端口适配器处于“已暂停”、“正在重启”、“正在运行”或“正在暂停”状态,并且 NDIS 调用微型端口驱动程序的 MiniportShutdownEx 函数时,微型端口适配器将进入“关闭”状态;
- 在 “正在初始化 ”状态下,微型端口驱动程序完成初始化微型端口适配器所需的任何操作。 当微型端口适配器处于“已停止”状态,并且 NDIS 调用微型端口驱动程序的 MiniportInitializeEx 函数时,微型端口适配器将进入“正在初始化”状态。 如果 MiniportInitializeEx 成功,微型端口适配器将进入 Paused 状态。 如果 MiniportInitializeEx 失败,微型端口适配器将返回到 Halted 状态;
- 当微型端口适配器处于 “已暂停” 状态时,微型端口驱动程序不会指示已收到网络数据或接受发送请求。 当微型端口适配器处于暂停状态并且暂停操作完成时,微型端口适配器将进入“已暂停”状态。 当微型端口适配器处于“正在初始化”状态并且 MiniportInitializeEx 成功时,微型端口适配器将进入“已暂停”状态。 当 NDIS 调用微型端口驱动程序的 MiniportRestart 函数时,微型端口适配器将从“已暂停”状态转换为“正在重启”状态。 当 NDIS 调用微型端口驱动程序的 MiniportHaltEx 函数时,微型端口适配器将从“已暂停”状态转换为“已停止”状态;
- 在 “正在重启” 状态下,微型端口驱动程序完成重启微型端口适配器的发送和接收操作所需的任何操作。 当微型端口适配器处于“已暂停”状态并且 NDIS 调用驱动程序的 MiniportRestart 函数时,微型端口适配器将进入“正在重启”状态。 如果重启失败,微型端口适配器将返回到“已暂停”状态。 如果重启成功,微型端口适配器将进入“正在运行”状态;
- 在 “正在运行” 状态下,微型端口驱动程序对微型端口适配器执行正常的发送和接收处理。 当微型端口适配器处于“正在重启”状态,并且驱动程序已准备好执行发送和接收操作时,微型端口适配器将进入“正在运行”状态;
- 在 暂停 状态下,微型端口驱动程序完成停止微型端口适配器的发送和接收操作所需的任何操作。 驱动程序必须等待 NDIS 返回所有未完成的接收指示。 当微型端口适配器处于“正在运行”状态并且 NDIS 调用驱动程序的 MiniportPause 函数时,微型端口适配器将进入暂停状态。 微型端口驱动程序不能使暂停操作失败。 暂停操作完成后,微型端口适配器将进入“已暂停”状态;
初始化
当网络设备可用时,系统加载 NDIS 微型端口驱动程序以管理设备。每个微型端口驱动程序都必须提供 DriverEntry 函数。 系统在加载驱动程序后调用 DriverEntry 。 DriverEntry 将微型端口驱动程序的特征(一个数据结构,封转了NDIS的函数例程)注册到 NDIS (包括支持的 NDIS 版本和驱动程序入口点) 。
系统将两个参数传递给 DriverEntry:
- 指向 I/O 系统创建的驱动程序对象的指针。
- 指向注册表路径的指针,该路径指定特定于驱动程序的参数的存储位置。
在 DriverEntry 中,微型端口驱动程序在调用 NdisMRegisterMiniportDriver 函数时传递这两个指针。 微型端口驱动程序通过将入口点存储在 NDIS_MINIPORT_DRIVER_CHARACTERISTICS 结构中并将该结构传递给 NdisMRegisterMiniportDriver 来导出一组标准 MiniportXxx 函数。
微型端口驱动程序的 DriverEntry 返回由调用 NdisMRegisterMiniportDriver 返回的值。
微型端口驱动程序还会在 DriverEntry 中执行任何其他特定于驱动程序的初始化。 驱动程序在 MiniportInitializeEx 函数中执行特定于适配器的初始化。
DriverEntry 可以在堆栈上分配 NDIS_MINIPORT_DRIVER_CHARACTERISTICS 结构,因为 NDIS 库将相关信息复制到其自己的存储。 DriverEntry 应在其成员中设置驱动程序提供的任何值之前,使用 NdisZeroMemory 清除此结构的内存。 MajorNdisVersion 和 MinorNdisVersion 成员必须包含驱动程序支持的 NDIS 的主要和次要版本。 在特征结构的每个 XxxHandler 成员中, DriverEntry 必须设置驱动程序提供的 MiniportXxx 函数的入口点,否则该成员必须为 NULL。
为了使微型端口驱动程序能够配置可选服务,NDIS 在微型端口驱动程序调用 NdisMRegisterMiniportDriver 的上下文中调用 MiniportSetOptions 函数。
调用 NdisMRegisterMiniportDriver 的驱动程序必须做好准备,以便 NDIS 在 DriverEntry 返回后随时调用其 MiniportInitializeEx 函数。 此类驱动程序必须有足够的安装和配置信息存储在注册表中,或者可以通过调用 特定于 NdisXxx 总线类型的配置函数来设置驱动程序执行网络 I/O 操作所需的任何特定于 NIC 的资源。
微型端口驱动程序最终必须调用 NdisMDeregisterMiniportDriver ,以释放它通过调用 NdisMRegisterMiniportDriver 分配的资源。 如果在调用 NdisMRegisterMiniportDriver 成功后驱动程序初始化失败,驱动程序可以从 DriverEntry 中调用 NdisMDeregisterMiniportDriver。 否则,微型端口驱动程序必须释放其 MiniportDriverUnload 函数中分配的特定于驱动程序的资源。 换句话说,如果 NdisMRegisterMiniportDriver 不返回NDIS_STATUS_SUCCESS, 则 DriverEntry 必须在返回控制权之前释放它分配的任何资源。 如果发生这种情况,将不会加载驱动程序。
卸载
与 NDIS 微型端口驱动程序关联的驱动程序对象指定 Unload 例程。 删除驱动程序服务的所有设备时,系统会调用 Unload 例程。 NDIS 为微型端口驱动程序提供 Unload 例程。 NDIS 从 Unload 例程调用微型端口驱动程序的 MiniportDriverUnload 函数。
微型端口驱动程序必须从 MiniportDriverUnload 调用 NdisMDeregisterMiniportDriver。
微型端口驱动程序的 MiniportDriverUnload 函数还应释放任何特定于驱动程序的资源。 MiniportDriverUnload 返回后,系统将完成驱动程序卸载操作。
MiniportDriverUnload 函数的功能特定于驱动程序。 一般情况下, MiniportDriverUnload 应撤消在驱动程序初始化期间执行的操作。