NDIS小端口驱动开发(八)

在最开始的时候,网络接口卡 (NIC) 基本都是PCI接口的,由于PCI本身是不支持PNP的,随着USB和移动互联网的兴起,慢慢的NDIS小端口驱动也需要支持PNP了。

网络接口卡 (NIC) 的函数驱动程序作为 NDIS 和微型端口驱动程序对实现。 将 NIC 添加到系统后,NDIS 会创建功能设备对象 (NIC )的 FDO 。 然后,NDIS 会处理传递给此 FDO 的所有 IRP,包括即插即用 (PnP) 和电源管理 IRP。 NIC 的微型端口驱动程序为 NIC 提供操作接口。

导出 MiniportDevicePnPEventNotify 函数

NDIS 调用微型端口驱动程序的 MiniportDevicePnPEventNotify 函数,以通知微型端口驱动程序以下即插即用 (PnP) 事件:

  • 意外删除微型端口驱动程序控制的 NIC;
  • 系统电源的变化;

如果微型端口驱动程序不导出 MiniportDevicePnPEventNotify 函数,则 NDIS 无法通知驱动程序这些 PnP 事件。

所有 NDIS 6.0 及更高版本的微型端口驱动程序 都必须导出 MiniportDevicePnPEventNotify 函数。 此外,具有 WDM 下边缘的所有微型端口驱动程序 都应 导出 MiniportDevicePnPEventNotify 函数。

处理 NIC 意外删除

当用户从正在运行的系统中删除网络接口卡 (NIC) 而不事先通过用户界面 (UI) 通知系统时,会发生意外删除。

适用于 Windows Vista 和更高版本的操作系统的微型端口驱动程序应该能够处理意外删除。 具体而言,具有 Windows 驱动程序模型 (WDM) 下边缘的 NDIS 微型端口驱动程序应能够处理此类事件。 如果 NDIS-WDM 微型端口驱动程序不处理意外删除,则在意外删除之前,微型端口驱动程序发送给基础总线驱动程序的任何挂起 IRP 都无法完成。

对于 Windows Vista 及更高版本,微型端口驱动程序 (例如具有 WDM 下边缘) 不直接控制硬件的微型端口驱动程序,应在调用 NdisMSetMiniportAttributes 时设置NDIS_MINIPORT_ATTRIBUTES_SURPRISE_REMOVE_OK属性标志。 设置此标志可防止在用户意外删除 NIC 时显示警告。 无法处理意外删除的微型端口驱动程序不应设置此标志。

支持意外删除的微型端口驱动程序本身应尝试在正常操作期间(在 MiniportDevicePnPEventNotify 的上下文之外)检测到意外删除。 删除 NIC 后,尝试读取 NIC 的 I/O 端口通常会导致所有位都设置为 1 的返回值。 如果微型端口驱动程序读取此类值,则应检查硬件是否存在具有更决定性的测试。 例如,微型端口驱动程序可以将值写入 I/O 端口,然后尝试从该端口读取值。 微型端口驱动程序还可以检查 NIC 的 I/O 寄存器中的有效值。 以这种方式检测意外删除,可防止微型端口驱动程序在尝试读取中断 DPC 中已删除的 NIC 寄存器时在无限循环中挂起。 以这种方式停止响应的微型端口驱动程序会阻止 NDIS 调用驱动程序的 MiniportDevicePnPEventNotify 函数。

处理系统电源的更改

系统可以从电池电源更改为交流电源,反之亦然。

初始化微型端口驱动程序后,NDIS 调用微型端口驱动程序的 MiniportDevicePnPEventNotify 函数,以通知微型端口驱动程序系统电源。 微型端口驱动程序可以使用此信息来调整 NIC 的功耗。 例如,如果系统使用电池电源运行,则无线 LAN (WLAN) 设备的微型端口驱动程序可以减少功耗;如果系统使用交流电源运行,则会增加功耗。

添加 NIC

以下说明从微型端口驱动程序的加载开始,并介绍了如何添加 NIC:

1. 如果尚未加载 NIC 的微型端口驱动程序,PnP 管理器将加载驱动程序,然后调用微型端口驱动程序的 DriverEntry 函数。 如果驱动程序已加载,则将继续执行步骤 4 的处理;

2. 从 其 DriverEntry 函数中,微型端口驱动程序注册为微型端口驱动程序并执行其他驱动程序初始化; 

3. NDIS 在微型端口驱动程序的驱动程序对象中填充以下条目:

  • AddDevice 例程的入口点;
  • 用于处理 IRP 的 DispatchXxx 入口点;
  • Unload 例程的入口点;

4. NDIS 从注册表中读取信息以获取 NIC 的配置信息, 此信息包括绑定信息和 NIC 的硬件属性;

5. 如有必要,PnP 管理器会将资源分配给 NIC;

启动 NIC

以下步骤介绍了 NDIS 如何参与 NIC 的启动:

  • PnP 管理器发出 IRP_MN_START_DEVICE 请求。 此 IRP 包含可通知 NDIS 有关 PnP 管理器已为 NIC 分配的资源的信息;
  • NDIS 设置一个 IoCompletion 例程,并将IRP_MN_START_DEVICE请求向下传递到设备堆栈中的下一个最低驱动程序,该驱动程序通常是总线驱动程序。 当总线驱动程序收到IRP_MN_START_DEVICE请求时,总线驱动程序会在设备上执行其启动操作,并将已完成IRP_MN_START_DEVICE请求传回设备堆栈;
  • 当 NDIS 收到已完成IRP_MN_START_DEVICE请求 (即,当 NDIS 的 DispatchPnP 例程在所有较低驱动程序完成 IRP) 后获得控制权时,NDIS 调用微型端口驱动程序的 MiniportInitializeEx 函数;
  • 如果 MiniportInitializeEx 函数返回NDIS_STATUS_SUCCESS,则 NDIS 将计划一个事件来调用应绑定到适配器的所有协议驱动程序的 ProtocolBindAdapterEx 函数,如注册表中的绑定信息所示。 请注意,微型端口驱动程序没有有关绑定的信息;
  • NDIS 完成IRP_MN_START_DEVICE请求;
停止 NIC

PnP 管理器停止 NIC,以便可以重新配置或重新平衡分配给 NIC 的硬件资源。 以下步骤介绍 NDIS 如何参与停止 NIC:

1. PnP 管理器发出 IRP_MN_QUERY_STOP_DEVICE 请求;

2. 当 NDIS 收到此 IRP 时,它会调用附加到驱动程序堆栈中 NIC 的最低Filter驱动程序的 FilterNetPnPEvent 函数。 在此调用中,NDIS 指定 NetEventQueryRemoveDevice 的事件代码,注意 NDIS 仅对播发 FilterNetPnPEvent 函数入口点的Filter驱动程序执行此步骤。 Filter驱动程序在调用 NdisFRegisterFilterDriver 函数时播发此入口点;

3. 在调用 FilterNetPnPEvent 函数的上下文中,Filter驱动程序必须调用 NdisFNetPnPEvent ,将 NetEventQueryRemoveDevice 事件转发到驱动程序堆栈中的下一个Filter驱动程序。 这会导致 NDIS 使用 NetEventQueryRemoveDevice 的事件代码调用该Filter驱动程序的 FilterNetPnPEvent 函数。注意 NDIS 仅对驱动程序堆栈中播发 FilterNetPnPEvent 函数入口点的下一个Filter驱动程序执行此步骤;

4. 驱动程序堆栈中的每个Filter驱动程序重复上一步,直到堆栈中最高的Filter驱动程序转发 NetEventQueryRemoveDevice 事件,发生这种情况时,NDIS 会调用绑定到 NIC 的所有协议驱动程序的 ProtocolNetPnPEvent 函数。 在此调用中,NDIS 指定 NetEventQueryRemoveDevice 的事件代码;

5. 如果协议驱动程序通过从 ProtocolNetPnPEvent 返回失败代码来失败 NetEventQueryRemoveDevice 事件,则 NDIS 或 PnP 管理器可能会忽略该失败,并随后成功执行IRP_MN_QUERY_STOP_DEVICE请求。 因此,即使协议驱动程序未能通过 NetEventQueryRemoveDevice 事件,协议驱动程序也必须准备好处理删除 NIC 的操作;

6. PnP 管理器发出 IRP_MN_STOP_DEVICE 请求来停止设备,或 发出IRP_MN_CANCEL_STOP_DEVICE 请求来取消挂起的停止。

7. 如果 PnP 管理器发出IRP_MN_CANCEL_STOP_DEVICE请求,NDIS 将调用附加到驱动程序堆栈中 NIC 的最低Filter驱动程序的 FilterNetPnPEvent 函数。 在此调用中,NDIS 指定 NetEventCancelRemoveDevice 的事件代码。注意 NDIS 仅对播发 FilterNetPnPEvent 函数入口点的Filter驱动程序执行此步骤;

8. 在调用 FilterNetPnPEvent 函数的上下文中,Filter驱动程序必须调用 NdisFNetPnPEvent ,以将 NetEventCancelRemoveDevice 事件转发到驱动程序堆栈中的下一个Filter驱动程序。 这会导致 NDIS 使用 NetEventCancelRemoveDevice 的事件代码调用该Filter驱动程序的 FilterNetPnPEvent 函数,注意 NDIS 仅对驱动程序堆栈中播发 FilterNetPnPEvent 函数入口点的下一个Filter驱动程序执行此步骤。

9. 驱动程序堆栈中的每个Filter驱动程序重复上一步,直到堆栈中最高的Filter驱动程序转发了 NetEventCancelRemoveDevice 事件。发生这种情况时,NDIS 会调用绑定到 NIC 的所有协议驱动程序的 ProtocolNetPnPEvent 函数。 在此调用中,NDIS 指定 NetEventCancelRemoveDevice 的事件代码。

10. 如果 PnP 管理器发出IRP_MN_STOP_DEVICE请求,NDIS 将执行以下步骤:

  • 它会暂停绑定到 NIC 的所有协议驱动程序;
  • 它会暂停附加到 NIC 的所有Filter驱动程序;
  • 它会暂停 NIC 的微型端口驱动程序;
  • 它调用绑定到 NIC 的所有协议驱动程序的 ProtocolUnbindAdapterEx 函数;
  • 它调用附加到 NIC 的所有Filter模块的 FilterDetach 函数;

11. 在所有协议和Filter驱动程序未绑定并脱离 NIC 后,NDIS 会调用微型端口驱动程序的 MiniportHaltEx 函数。 NDIS 将 MiniportHaltEx 的 HaltAction 参数设置为 NdisHaltDeviceStopped;

12. 处理IRP_MN_STOP_DEVICE请求时,NDIS 不会销毁功能设备对象 (调用 AddDevice 例程时为 NIC 创建的 FDO) 。 只有在收到针对 NIC 的 IRP_MN_REMOVE_DEVICE 请求后,NDIS 才会销毁设备对象。

如果 PnP 管理器发出重启 NIC 的IRP_MN_START_DEVICE,则 NDIS 将重复使用以前为 NIC 创建的 FDO。 然后,NDIS 将重启 NIC。

移除 NIC

以下步骤介绍 NDIS 如何参与删除 NIC:

1. PnP 管理器发出 IRP_MN_QUERY_REMOVE_DEVICE 请求,以查询是否可以在不中断计算机的情况下删除 NIC;

2. 当 NDIS 收到此 IRP 时,它会调用附加到驱动程序堆栈中 NIC 的最低Filter驱动程序的 FilterNetPnPEvent 函数。 在此调用中,NDIS 指定 NetEventQueryRemoveDevice 的事件代码,注意 NDIS 仅对播发 FilterNetPnPEvent 函数入口点的Filter驱动程序执行此步骤。 Filter驱动程序在调用 NdisFRegisterFilterDriver 函数时播发此入口点;

3. 在调用 FilterNetPnPEvent 函数的上下文中,Filter驱动程序必须调用 NdisFNetPnPEvent ,将 NetEventQueryRemoveDevice 事件转发到驱动程序堆栈中的下一个Filter驱动程序。 这会导致 NDIS 使用 NetEventQueryRemoveDevice 的事件代码调用该Filter驱动程序的 FilterNetPnPEvent 函数,注意 NDIS 仅对驱动程序堆栈中播发 FilterNetPnPEvent 函数入口点的下一个Filter驱动程序执行此步骤;

4. 驱动程序堆栈中的每个Filter驱动程序重复上一步,直到堆栈中最高的Filter驱动程序转发 NetEventQueryRemoveDevice 事件。发生这种情况时,NDIS 会调用绑定到 NIC 的所有协议驱动程序的 ProtocolNetPnPEvent 函数。 在此调用中,NDIS 指定 NetEventQueryRemoveDevice 的事件代码;

5. 如果协议驱动程序通过从 ProtocolNetPnPEvent 返回失败代码NDIS_STATUS_FAILURE,导致 NetEventQueryRemoveDevice 事件失败,NDIS 或 PnP 管理器可能会忽略该失败,并随后成功IRP_MN_QUERY_REMOVE_DEVICE请求。 因此,即使协议驱动程序未能通过 NetEventQueryRemoveDevice 事件,协议驱动程序也必须准备好处理删除 NIC 的操作;

6. PnP 管理器发出 IRP_MN_REMOVE_DEVICE 请求,要求删除软件表示 设备对象的NIC 或 IRP_MN_CANCEL_REMOVE_DEVICE 请求取消挂起的删除。 请注意,IRP_MN_REMOVE_DEVICE请求的前面并不总是IRP_MN_QUERY_REMOVE_DEVICE请求;

7. 如果 PnP 管理器发出IRP_MN_CANCEL_REMOVE_DEVICE请求,NDIS 将调用附加到驱动程序堆栈中 NIC 的最低Filter驱动程序的 FilterNetPnPEvent 函数。 在此调用中,NDIS 指定 NetEventCancelRemoveDevice 的事件代码,注意 NDIS 仅对播发 FilterNetPnPEvent 函数入口点的Filter驱动程序执行此步骤;

8. 在调用 FilterNetPnPEvent 函数的上下文中,Filter驱动程序必须调用 NdisFNetPnPEvent ,以将 NetEventCancelRemoveDevice 事件转发到驱动程序堆栈中的下一个Filter驱动程序。 这会导致 NDIS 使用 NetEventCancelRemoveDevice 的事件代码调用该Filter驱动程序的 FilterNetPnPEvent 函数,注意 NDIS 仅对驱动程序堆栈中播发 FilterNetPnPEvent 函数入口点的下一个Filter驱动程序执行此步骤;

9. 驱动程序堆栈中的每个Filter驱动程序重复上一步,直到堆栈中最高的Filter驱动程序转发了 NetEventCancelRemoveDevice 事件,发生这种情况时,NDIS 会调用绑定到 NIC 的所有协议驱动程序的 ProtocolNetPnPEvent 函数。 在此调用中,NDIS 指定 NetEventCancelRemoveDevice 的事件代码。 此事件代码结束删除序列;

10. 如果 PnP 管理器发出IRP_MN_REMOVE_DEVICE请求,NDIS 将执行以下步骤:

  • 它会暂停绑定到 NIC 的所有协议驱动程序;
  • 它会暂停附加到 NIC 的所有Filter驱动程序;
  • 它会暂停 NIC 的微型端口驱动程序;
  • 它调用绑定到 NIC 的所有协议驱动程序的 ProtocolUnbindAdapterEx 函数;
  • 它调用附加到 NIC 的所有Filter模块的 FilterDetach 函数;

11. 如果微型端口驱动程序已成功初始化,NDIS 将调用微型端口驱动程序的 MiniportHaltEx 函数。 NDIS 将 MiniportHaltEx 的 HaltAction 参数设置为 NdisHaltDeviceDisabled;

12. NDIS 将IRP_MN_REMOVE_DEVICE请求发送到堆栈中的下一个下一个设备对象;

13. 当 NDIS 收到来自堆栈中下一个下一个下一个设备对象的已完成IRP_MN_REMOVE_DEVICE请求时,NDIS 会销毁它为 NIC 创建的 FDO功能设备对象;

处理 NIC 意外删除 (Windows Vista)

以下步骤介绍了 NDIS 如何参与 Windows Vista 和 Windows Server 2008 中意外删除 NIC:

1. PnP 管理器向 NIC 的设备堆栈发出 IRP_MN_SURPRISE_REMOVAL 请求;

2. 当 NDIS 收到此 IRP 时,它会调用附加到驱动程序堆栈中 NIC 的最低Filter驱动程序的 FilterNetPnPEvent 函数。 在此调用中,NDIS 指定 NetEventQueryRemoveDevice 的事件代码,注意 NDIS 仅对播发 FilterNetPnPEvent 函数入口点的Filter驱动程序执行此步骤。 Filter驱动程序在调用 NdisFRegisterFilterDriver 函数时播发此入口点;

3. 在调用 FilterNetPnPEvent 函数的上下文中,Filter驱动程序必须调用 NdisFNetPnPEvent ,将 NetEventQueryRemoveDevice 事件转发到驱动程序堆栈中的下一个Filter驱动程序。 这会导致 NDIS 使用 NetEventQueryRemoveDevice.的事件代码调用该Filter驱动程序的 FilterNetPnPEvent 函数,注意 NDIS 仅对驱动程序堆栈中播发 FilterNetPnPEvent 函数入口点的下一个Filter驱动程序执行此步骤;

4. 驱动程序堆栈中的每个Filter驱动程序重复上一步,直到堆栈中最高的Filter驱动程序转发 NetEventQueryRemoveDevice 事件,发生这种情况时,NDIS 会调用绑定到 NIC 的所有协议驱动程序的 ProtocolNetPnPEvent 函数。 在此调用中,NDIS 指定 NetEventQueryRemoveDevice.的事件代码;

5. 如果微型端口驱动程序已成功初始化,NDIS 使用事件代码 NdisDevicePnPEventSurpriseRemoved 调用 MiniportDevicePnPEventNotify 函数。 微型端口驱动程序应注意该设备已被物理删除。 如果微型端口驱动程序是 NDIS-WDM 驱动程序,它应取消发送到基础总线驱动程序的任何挂起的 IRP。 如果微型端口驱动程序未成功初始化,则继续处理;

6. NDIS 将IRP_MN_SURPRISE_REMOVAL请求发送到堆栈中的下一个较低设备对象。 收到来自堆栈中下一个较低设备对象的返回IRP_MN_SURPRISE_REMOVAL请求后,NDIS 将完成IRP_MN_SURPRISE_REMOVAL请求;

7. PnP 管理器发出 IRP_MN_REMOVE_DEVICE 请求,要求删除 设备对象的软件表示的 NIC;

8. NDIS 执行以下步骤:

  • 它会暂停绑定到 NIC 的所有协议驱动程序;
  • 它会暂停附加到 NIC 的所有Filter驱动程序;
  • 它将暂停 NIC 的微型端口驱动程序;
  • 它调用绑定到 NIC 的所有协议驱动程序的 ProtocolUnbindAdapterEx 函数;
  • 它调用附加到 NIC 的所有Filter模块的 FilterDetach 函数;

9. 在所有协议和Filter驱动程序未绑定并从 NIC 分离后,NDIS 调用微型端口驱动程序的 MiniportHaltEx 函数。 NDIS 将 MiniportHaltEx 的 HaltAction 参数设置为 NdisHaltDeviceSurpriseRemoved;

10. NDIS 将IRP_MN_REMOVE_DEVICE请求发送到堆栈中的下一个较低设备对象;

11. 当 NDIS 收到来自堆栈中下一个较低设备对象的已完成IRP_MN_REMOVE_DEVICE请求时,NDIS 会销毁它为 NIC 创建的 FDO 的功能设备对象;

处理 NIC 意外删除(Windows 7 和更高版本)

在 Windows 7 和 Windows Server 2008 R2 及更高版本中,NDIS 可能会参与意外删除网络接口,卡 (NIC) 与以前版本的 Windows 不同。 如果满足以下任一条件,NDIS 将执行修订后的意外删除过程:

  • 操作系统为 Windows 8/Windows Server 2012 或更高版本;
  • 操作系统为 Windows 7,已安装 KB2471472 的修补程序;
  • 操作系统为 Windows 7,网络适配器是移动宽带 (MBB) 设备;

如果这些条件均未满足,则 NDIS 会像以前版本的 Windows 一样参与意外删除过程。 

以下步骤描述了 NDIS 参与意外删除 NIC 的修订方式:

1. PnP 管理器向 NIC 的设备堆栈发出 IRP_MN_SURPRISE_REMOVAL 请求;

2. 当 NDIS 收到此 IRP 时,它会调用附加到驱动程序堆栈中 NIC 的最低Filter驱动程序的 FilterNetPnPEvent 函数。 在此调用中,NDIS 指定 NetEventQueryRemoveDevice 的事件代码,注意 NDIS 仅对播发 FilterNetPnPEvent 函数入口点的Filter驱动程序执行此步骤。 Filter驱动程序在调用 NdisFRegisterFilterDriver 函数时播发此入口点;

3. 在调用 FilterNetPnPEvent 函数的上下文中,Filter驱动程序必须调用 NdisFNetPnPEvent ,将 NetEventQueryRemoveDevice 事件转发到驱动程序堆栈中的下一个Filter驱动程序。 这会导致 NDIS 使用 NetEventQueryRemoveDevice 的事件代码调用该Filter驱动程序的 FilterNetPnPEvent 函数,注意 NDIS 仅对驱动程序堆栈中播发 FilterNetPnPEvent 函数入口点的下一个Filter驱动程序执行此步骤;

4. 驱动程序堆栈中的每个Filter驱动程序重复上一步,直到堆栈中最高的Filter驱动程序转发 NetEventQueryRemoveDevice 事件。发生这种情况时,NDIS 会调用绑定到 NIC 的所有协议驱动程序的 ProtocolNetPnPEvent 函数。 在此调用中,NDIS 指定 NetEventQueryRemoveDevice 的事件代码;

5. NDIS 使用事件代码 NdisDevicePnPEventSurpriseRemoved 调用 MiniportDevicePnPEventNotify 函数。 微型端口驱动程序应注意该设备已被物理删除。 如果微型端口驱动程序是 NDIS-WDM 驱动程序,它应取消发送到基础总线驱动程序的任何挂起的 IRP;

6. NDIS 执行以下步骤:

  • 它会暂停绑定到 NIC 的所有协议驱动程序;
  • 它会暂停附加到 NIC 的所有Filter驱动程序;
  • 它将暂停 NIC 的微型端口驱动程序;
  • 它调用绑定到 NIC 的所有协议驱动程序的 ProtocolUnbindAdapterEx 函数;
  • 它调用附加到 NIC 的所有Filter模块的 FilterDetach 函数;

7. 在所有协议和Filter驱动程序未绑定并从 NIC 分离后,NDIS 调用微型端口驱动程序的 MiniportHaltEx 函数。 NDIS 将 MiniportHaltEx 的 HaltAction 参数设置为 NdisHaltDeviceSurpriseRemoved;

8. NDIS 将IRP_MN_SURPRISE_REMOVAL请求发送到堆栈中的下一个较低设备对象。 收到来自堆栈中下一个较低设备对象的返回IRP_MN_SURPRISE_REMOVAL请求后,NDIS 将完成IRP_MN_SURPRISE_REMOVAL请求;

9. PnP 管理器发出 IRP_MN_REMOVE_DEVICE 请求,要求删除 设备对象的 NIC;

10. NDIS 将IRP_MN_REMOVE_DEVICE请求发送到堆栈中的下一个较低设备对象。

11. 当 NDIS 收到来自堆栈中下一个较低设备对象的已完成IRP_MN_REMOVE_DEVICE请求时,NDIS 会销毁它为 NIC 创建的 FDO (FDO) 的功能设备对象;

  • 21
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值