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

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

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

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

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

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

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

显示空闲通知操作的关系图。

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

处理对 MiniportIdleNotification 的调用的指南

调用 NdisMIdleNotificationConfirm 指南

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

处理对 MiniportIdleNotification 的调用的指南

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

  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 为 USB 空闲请求发出 I/O 请求数据包 (IRP) , (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. NDIS 向基础总线驱动程序 发出IRP_MN_WAIT_WAKE 问题。 此 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_PM_PARAMETERS 结构中为与 NDIS 选择性挂起无关的唤醒事件设置其他成员。

      注意仅当符合 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_PM_PARAMETERS 的 OID 集请求中指定的指定唤醒事件。 为低功耗转换准备网络适配器后,微型端口驱动程序使用 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 选择性挂起空闲通知