处理 NDIS 选择性挂起空闲通知

如果发生下列事件之一,NDIS 将启动选择性挂起操作:

  • 网络适配器已处于非活动状态,时间超过空闲超时时间。 此超时期限的持续时间由 *SSIdleTimeout 标准化 INF 关键字的值指定。 有关此关键字的详细信息,请参阅 NDIS 选择性挂起的标准化 INF 关键字

    有关 NDIS 如何确定网络适配器处于空闲状态的详细信息,请参阅 NDIS 如何检测空闲网络适配器

  • 符合 Always On Always Connected (AOAC) 技术的系统正在转换为连接的待机状态。

通过选择性挂起操作,网络适配器将转换为低功率状态。 NDIS 通过调用 MiniportIdleNotification 处理程序函数向微型端口驱动程序发出空闲通知来开始此操作。

处理空闲通知时,微型端口驱动程序可能需要执行依赖于总线的操作。 下图显示了用于处理 USB 网络适配器的微型端口驱动程序的空闲通知所涉及的步骤。

diagram showing the idle notification operation.

本主题包括有关如何处理 NDIS 选择性挂起空闲通知的以下信息:

处理对 MiniportIdleNotification 调用的指南

调用 NdisMIdleNotificationConfirm 指南

取消和完成 NDIS 选择性挂起空闲通知

处理对 MiniportIdleNotification 调用的指南

NDIS 和微型端口驱动程序在 NDIS 调用 MiniportIdleNotification 时执行以下步骤:

  1. NDIS 调用 MiniportIdleNotification 处理程序函数,以通知驱动程序基础网络适配器似乎处于空闲状态。 NDIS 将 MiniportIdleNotification 处理程序函数的 ForceIdle 参数设置为以下值之一:

    • NDIS 将当网络适配器处于非活动状态的时间超过空闲超时时段时 ,将 ForceIdle 参数设置为 FALSE

    • 当符合 Always On Always Connected (AOAC) 技术的系统正在转换为连接待机状态时,NDIS 会将 ForceIdle 参数设置为 TRUE

  2. 调用 MiniportIdleNotification 时,微型端口驱动程序可以通过返回NDIS_STATUS_BUSY来否决空闲通知和选择性暂停操作。 例如,如果驱动程序检测到网络适配器上的活动,驱动程序可能会否决空闲通知。

    如果微型端口驱动程序否决空闲通知,NDIS 会重启网络适配器上的活动监视器。 如果适配器在空闲超时期间再次处于非活动状态,NDIS 会调用 MiniportIdleNotification

    注意 如果 ForceIdle 参数设置为 TRUE,微型端口驱动程序不得否决空闲通知。 在这种情况下,驱动程序必须继续执行选择性挂起操作。

  3. 如果微型端口驱动程序未否决空闲通知,则必须执行任何特定于总线的操作,以便为选择性挂起操作准备网络适配器。 例如,USB 网络适配器的微型端口驱动程序执行以下步骤,以确定网络适配器是否可以转换为低功率状态:

    1. 微型端口驱动程序调用 IoCallDriver , (IRP) 发出 I/O 请求数据包,以便将 USB 空闲请求 (IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION) 到基础 USB 总线驱动程序。 在此 IRP 中,微型端口驱动程序必须指定回调和完成例程。

      USB 总线驱动程序不会立即完成 IRP。 IRP 通过低功率转换处于挂起状态。 如果发生以下任何事件,则总线驱动程序稍后将完成 IRP:

      • 微型端口驱动程序取消 IRP。

      • 需要系统电源状态更改。

      • 设备已从 USB 中心中删除。

    2. USB 总线驱动程序确定它可以将网络适配器置于低功率状态后,它会调用微型端口驱动程序的 IRP 回调例程。 此调用确认网络适配器可以转换为低功率状态。

      有关如何为 USB 空闲请求 IRP 编写回调例程的指南,请参阅 实现 USB 空闲请求 IRP 回调例程

  4. 微型端口驱动程序完成为选择性挂起操作准备网络适配器后,它会调用 NdisMIdleNotificationConfirm。 在此调用中,微型端口驱动程序指定网络适配器可以转换为的最低电源状态。

    根据选择性挂起操作的总线要求,微型端口驱动程序在调用 MiniportIdleNotification 的上下文中同步调用 NdisMIdleNotificationConfirm,或在 MiniportIdleNotification 返回后异步调用。 例如,USB 网络适配器的微型端口驱动程序在 USB 空闲请求的回调例程的上下文中调用 NdisMIdleNotificationConfirm 。 USB 总线驱动程序在调用 IoCallDriver 的上下文中同步调用回调例程,或在 MiniportIdleNotification 返回后异步调用回调例程。

  5. 如果网络适配器可以转换为低功率状态,微型端口驱动程序将从调用 到 MiniportIdleNotification 返回NDIS_STATUS_PENDING。

    注意 微型端口驱动程序返回NDIS_STATUS_PENDING,因为在驱动程序调用 NdisMIdleNotificationComplete 之前,空闲通知不会完成。 微型端口驱动程序不得从 MiniportIdleNotification 返回NDIS_STATUS_SUCCESS。

微型端口驱动程序应执行以下操作,直到网络适配器暂停并转换为低功率状态:

调用 NdisMIdleNotificationConfirm 指南

当微型端口驱动程序调用 NdisMIdleNotificationConfirm 时,NDIS 和微型端口驱动程序遵循以下步骤:

  1. 基础总线驱动程序 IRP_MN_WAIT_WAKE NDIS 问题。 此 IRP 使总线驱动程序能够唤醒网络适配器,以响应外部唤醒信号。

  2. NDIS 向微型端口驱动程序发出对象标识符 (OID) 设置 OID_PM_PARAMETERS 请求。 此 OID 请求与 一个NDIS_PM_PARAMETERS 结构相关联,该结构指定网络适配器生成唤醒事件的设置。

    微型端口驱动程序在处理 NDIS_PM_PARAMETERS 结构的成员时必须遵循以下准则:

    • 如果 MiniportIdleNotification 处理程序函数的 ForceIdle 参数设置为 FALSE,NDIS 仅在NDIS_PM_PARAMETERS结构的 WakeUpFlags 成员中设置NDIS_PM_SELECTIVE_SUSPEND_ENABLED标志。 在这种情况下,当发生以下事件之一时,网络适配器可以发出唤醒事件信号:

      • 网络适配器接收与接收数据包筛选器匹配的数据包。 适配器配置为通过 OID_GEN_CURRENT_PACKET_FILTER的 OID 集请求使用这些筛选器。

      • 网络适配器检测到需要网络驱动程序堆栈处理的其他外部事件,例如,当链接状态更改为媒体断开连接或已连接媒体时。

    • 如果 MiniportIdleNotification 处理程序函数的 ForceIdle 参数设置为 TRUE,NDIS 不会在 NDIS_PM_PARAMETERS 结构的 WakeUpFlags 成员中设置NDIS_PM_SELECTIVE_SUSPEND_ENABLED标志。 在这种情况下,NDIS 为与 NDIS 选择性挂起无关的唤醒事件 设置NDIS_PM_PARAMETERS 结构中的其他成员。

      注意仅当符合 Always On Always Connected (AOAC) 技术转换为连接待机状态的系统时,NDIS 才会将 ForceIdle 参数设置为 TRUE

      驱动程序使用NDIS_STATUS_SUCCESS完成 OID 请求。

      注意 如果 NDIS 在 NDIS_PM_PARAMETERS 结构的 WakeUpFlags 成员中设置 NDIS_PM_SELECTIVE_SUSPEND_ENABLED 标志,则会直接向微型端口驱动程序发出 OID_PM_PARAMETERS 的 OID 集请求。 这样,NDIS 就可以通过网络驱动程序堆栈中的筛选器驱动程序绕过处理。

  3. 成功完成 OID_PM_PARAMETERS 的 OID 集请求后,NDIS 会向微型端口驱动程序发出 OID 集请求 OID_PNP_SET_POWER

    当它处理此 OID 集请求时,驱动程序准备网络适配器以转换为 OID 请求中指定的低功率状态。 驱动程序必须通过以下方式完成所有挂起的操作:

    • 微型端口驱动程序等待以前指示的所有接收数据包通过对 MiniportReturnNetBufferLists 的调用返回。

    • 微型端口驱动程序等待硬件处理的发送请求完成。 请求完成后,微型端口驱动程序必须调用 NdisMSendNetBufferListsComplete

    • 微型端口驱动程序通过调用 NdisMSendNetBufferListsComplete 完成所有挂起的发送请求。

    • 微型端口驱动程序必须取消所有挂起的 NDIS 计时器和工作项。 取消这些计时器和工作项后,驱动程序必须等待这些计时器和工作项的完成。

    • 微型端口驱动程序必须将网络适配器置于静止状态。 例如,驱动程序必须取消所有硬件计时器。

    微型端口驱动程序配置基础网络适配器,以启用以前在 OID 集请求中指定 OID_PM_PARAMETERS的指定唤醒事件。 为低功率转换准备网络适配器后,微型端口驱动程序使用 NDIS_STATUS_SUCCESS 完成 OID_PNP_SET_POWER 的 OID 集请求。

  4. NDIS 向基础总线驱动程序发出 IRP_MN_SET_POWER 。 此 IRP 请求将网络适配器转换为低功率状态。

    注意 在选择性挂起操作期间,网络适配器将转换为在调用 NdisMIdleNotificationConfirm 中指定的设备电源状态。 微型端口驱动程序在此函数的 IdlePowerState 参数中指定此设备电源状态。

IRP 完成后,NDIS 将从调用 NdisMIdleNotificationConfirm 返回。

取消和完成 NDIS 选择性挂起空闲通知

发出空闲通知后,可以通过以下方式取消和完成该通知:

  • 如果满足以下条件,NDIS 可以取消未完成的空闲通知:

    • 过度分配的协议或筛选器驱动程序会向微型端口驱动程序发出发送数据包请求或 OID 请求。

    • 基础适配器发出唤醒事件信号,例如接收与 LAN 唤醒 (WOL) 模式匹配的数据包,或检测其媒体连接状态的变化。

    NDIS 通过调用 MiniportCancelIdleNotification 取消空闲通知。 调用此处理程序函数时,微型端口驱动程序会取消以前为空闲通知发出的任何特定于总线的 IRP。 最后,微型端口驱动程序调用 NdisMIdleNotificationComplete 以完成空闲通知。

    有关 NDIS 如何取消空闲通知的详细信息,请参阅 取消 NDIS 选择性挂起空闲通知

  • 网络适配器处于低功率状态后,微型端口驱动程序可以完成空闲通知本身,以将适配器恢复为全电源状态。 执行此操作的原因特定于驱动程序和适配器的设计和要求。 微型端口驱动程序通过调用 NdisMIdleNotificationComplete 完成空闲通知。

    有关微型端口驱动程序如何完成空闲通知的详细信息,请参阅 完成 NDIS 选择性挂起空闲通知