处理设置电源请求

中间驱动程序必须处理将电源设置为工作状态(网络设备电源状态为 D0)和睡眠状态(D1、D2 或 D3 的网络设备电源状态)的请求。 中间驱动程序还应维护电源状态变量和 StandBy 标志。 本主题将进一步讨论这些问题。

有关中间驱动程序电源管理的示例,请参阅 GitHub 上的 Windows 驱动程序示例存储库中的 NDIS MUX MUX 中间驱动程序和通知对象驱动程序示例示例。

处理对睡眠状态的“设置电源请求”

有两种情况:中间驱动程序必须处理睡眠状态的一组电源请求:

  • NDIS 请求中间驱动程序的虚拟微型端口上边缘进入睡眠状态。

  • 中间驱动程序协议下边缘处理基础微型端口驱动程序在收到即插即用(PnP)事件通知时转换为睡眠状态。

这些事件可以按任意顺序发生,一个事件不一定伴随另一个事件。

当中间驱动程序的虚拟微型端口上边缘收到将电源设置为睡眠状态的请求时,用于处理请求的事件序列如下所示:

  1. NDIS 调用 绑定到虚拟微型端口的每个协议驱动程序的 ProtocolNetPnPEvent 函数。 对 ProtocolNetPnPEvent 的调用指定 睡眠状态的 NetEventSetPower 事件。 绑定到中间驱动程序的协议驱动程序停止发送网络数据,并向中间驱动程序虚拟端口发出 OID 请求。 中间驱动程序的协议下边缘可以继续发送网络数据和请求,直到 NDIS 指示基础微型端口驱动程序正在转换为睡眠状态。

  2. NDIS 暂停过度的驱动程序,然后在发出 NetEventSetPower 事件后虚拟微型端口。 暂停的指定原因是转换为低功率状态。 有关暂停虚拟微型端口的详细信息,请参阅 暂停适配器

    请注意,在虚拟微型端口处于低功率状态时,无法将 OID 请求发送到虚拟微型端口,但OID_PNP_标准版T_POWER除外

  3. NDIS 向中间驱动程序的虚拟微型端口发出OID_PNP_标准版T_POWER请求。 中间驱动程序通过返回NDIS_STATUS_SUCCESS来接受请求。 中间驱动程序不得将OID_PNP_标准版T_POWER请求传播到基础微型端口驱动程序。 中间驱动程序完成此请求后,它不应指示更多收到的网络数据或指示状态,即使它继续从基础微型端口驱动程序接收网络数据和状态指示。

当中间驱动程序的协议下边缘将基础微型端口驱动程序转换为睡眠状态时,处理转换的事件序列如下所示:

  1. NDIS 调用 中间驱动程序协议下边缘的 ProtocolNetPnPEvent 函数。 对 ProtocolNetPnPEvent 的调用指定 睡眠状态的 NetEventSetPower 事件。 中间驱动程序必须停止发送网络数据并向基础微型端口驱动程序发出 OID 请求。 如果存在未完成的请求或发送,中间驱动程序应从对 ProtocolNetPnPEvent 的调用中返回NDIS_STATUS_PENDING。 中间驱动程序调用 NdisCompleteNetPnPEvent 以完成对 ProtocolNetPnPEvent 的调用。 中间驱动程序的协议边缘仍可以从基础微型端口驱动程序获取收到的数据包和状态指示。 可以忽略收到的网络数据。 如果中间驱动程序的实现取决于监视基础微型端口驱动程序的状态,则仍应监视状态指示。

  2. NDIS 暂停中间驱动程序的协议边缘,然后在发出 NetEventSetPower 事件后暂停基础微型端口适配器。 暂停的指定原因是转换为低功率状态。 有关暂停协议绑定的详细信息,请参阅 暂停绑定

    请注意,在处于低功率状态时,无法将 OID 请求发送到基础微型端口适配器,但OID_PNP_标准版T_POWER除外

  3. NDIS 向基础微型端口驱动程序发出OID_PNP_标准版T_POWER请求。 但是,如果基础微型端口驱动程序不支持电源管理,它将停止。 在这种情况下,即使 NDIS 停止基础微型端口驱动程序,也不会请求中间驱动程序协议从基础微型端口驱动程序和 NIC 取消绑定。 在基础微型端口驱动程序成功完成处理 OID(或微型端口驱动程序已停止)后,它不会指示任何其他网络数据或状态。

处理对工作状态的“设置电源请求”

有两种情况:中间驱动程序处理对工作状态的一组电源请求:

  • NDIS 请求中间驱动程序的虚拟微型端口上边缘进入工作状态。

  • 在收到即插即用(PnP)事件通知时,中间驱动程序协议的下边缘处理基础微型端口驱动程序转换为工作状态。

这些事件可以按任意顺序发生,一个事件不一定伴随另一个事件。

当中间驱动程序的虚拟微型端口上边缘收到将电源设置为工作状态的请求时,处理请求的事件序列如下所示:

  1. NDIS 向中间驱动程序的虚拟微型端口发出OID_PNP_标准版T_POWER。 中间驱动程序将NDIS_STATUS_SUCCESS返回到集电源请求。 中间驱动程序不得将OID_PNP_标准版T_POWER请求传播到基础微型端口驱动程序。

  2. NDIS 重新启动虚拟微型端口,然后在发出集电源 OID 后重启过度的驱动程序。 有关重启虚拟微型端口的详细信息,请参阅 “启动适配器”。

  3. NDIS 调用 过度覆盖协议驱动程序的 ProtocolNetPnPEvent 函数。 对 ProtocolNetPnPEvent 的调用指定要 设置工作状态的 NetEventSetPower 事件(D0)。 绑定协议驱动程序可以开始将网络数据发送到中间驱动程序的虚拟微型端口。

当中间驱动程序的协议下边缘将基础微型端口驱动程序转换为工作状态时,用于处理转换的事件序列如下所示:

  1. NDIS 向基础微型端口驱动程序发出OID_PNP_标准版T_POWER,或者在基础微型端口驱动程序停止时调用其 MiniportInitializeEx 处理程序。

  2. NDIS 重新启动基础微型端口驱动程序,然后在发出 OID 后重启中间 NDIS 和基础微型端口适配器的协议边缘。 有关暂停协议绑定的详细信息,请参阅 重启绑定

  3. NDIS 调用 中间驱动程序的 ProtocolNetPnPEvent 函数。 对 ProtocolNetPnPEvent 的调用指定要 设置工作状态的 NetEventSetPower 事件(D0)。 中间驱动程序可以开始将网络数据发送到基础微型端口驱动程序。

电源状态和备用标志

中间驱动程序应为每个虚拟微型端口实例以及驱动程序绑定到的每个基础微型端口驱动程序维护单独的电源状态变量。 中间驱动程序还应为每个虚拟微型端口维护一个 StandingBy 标志,即:

  • 当虚拟微型端口或基础微型端口驱动程序的电源状态离开 D0 时,设置为 TRUE

  • 当虚拟微型端口或基础微型端口驱动程序的电源状态返回到 D0 时,设置为 FAL标准版

注意 对于 MUX 中间驱动程序,可以有多个虚拟微型端口与基础微型端口驱动程序相关联,或者有多个与每个虚拟微型端口关联的基础微型端口。 当任何微型端口适配器的电源状态发生更改时,所有关联的微型端口的行为也会受到影响。 行为受到的影响是特定于实现的。 例如,实现负载均衡故障转移(LBFO)解决方案的驱动程序在停用单个基础微型端口驱动程序时可能不会停用虚拟微型端口。 但是,依赖于所有基础微型端口驱动程序的驱动程序实现需要在停用任何基础微型端口驱动程序时停用虚拟微型端口。

中间驱动程序在处理请求时应使用 StandingBy 标志和电源状态变量,如下所示:

  • 驱动程序的 MiniportSendNetBufferLists 函数应失败,除非虚拟微型端口及其基础微型端口适配器都位于 D0 中。

  • 驱动程序的 MiniportOidRequest 函数应始终成功OID_PNP_QUERY_POWER以确保驱动程序接收后续OID_PNP_标准版T_POWER请求。

  • 如果虚拟微型端口不在 D0 或 StandingBy 为 TRUE,驱动程序的 MiniportOidRequest 函数应失败。 否则,如果基础微型端口驱动程序不在 D0 中,则应将单个请求排入队列。 当基础微型端口驱动程序状态变为 D0 时,应处理排队请求。

  • 仅当基础微型端口和虚拟微型端口都位于 D0 中时,中间驱动程序虚拟微型端口才应报告状态。