在需要的时候,我们也许需要NDIS微型端口程序信息,下面会从多个方面来讨论如何查询NDIS微型端口驱动。
查询无连接微型端口驱动程序
若要查询无连接微型端口驱动程序维护的 OID,绑定协议调用 NdisOidRequest 并传递 一个NDIS_OID_REQUEST 结构,该结构指定对象 (OID) 正在查询,该对象指向 NDIS 最终写入所请求信息的缓冲区。
如果 NDIS 不响应微型端口驱动程序,则对 NdisOidRequest 的 调用会导致 NDIS 调用微型端口驱动程序的 MiniportOidRequest 函数,该函数将请求的信息返回到 NDIS。 MiniportOidRequest 可以通过调用 NdisMOidRequestComplete 以同步或异步方式完成。
NDIS 还可以自行调用微型端口驱动程序的 MiniportOidRequest 函数(例如,在微型端口驱动程序的 MiniportInitializeEx 函数返回NDIS_STATUS_SUCCESS)以查询微型端口驱动程序的功能、状态或统计信息之后。 下图演示了查询无连接微型端口驱动程序。
NDIS 代表微型端口驱动程序响应许多 OID 请求。 微型端口驱动程序在初始化期间和状态指示中报告其许多 OID 值。
使用 OID_GEN_MAC_OPTIONS 调用 MiniportOidRequest 时,它必须返回一个位掩码,该位掩码指定微型端口驱动程序执行的可选操作。 标志集包括:
- NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA。 此标志向协议驱动程序指示它可以通过任何方式访问指示的数据。 如果微型端口驱动程序指示数据来自板载共享内存,则它不得设置此标志;
- NDIS_MAC_OPTION_NO_LOOPBACK。 如果设置了此标志,微型端口驱动程序不会环回传递给 MiniportSendNetBufferLists 的数据包 (数据包) 定向到同一计算机上的接收器,并且微型端口驱动程序预期 NDIS 执行环回。 如果 NDIS 执行数据包的环回,则数据包不会向下传递到微型端口驱动程序。 微型端口驱动程序始终设置此标志,除非 NIC 执行硬件环回;
- NDIS_MAC_OPTION_RECEIVE_SERIALIZED。 如果设置了此标志,微型端口驱动程序不会指示任何新接收的数据包,直到之前收到的数据包已完全处理,包括传输数据。 大多数微型端口驱动程序(通过调用 NdisMIndicateReceiveNetBufferLists 指示数据包的驱动程序除外)都设置此标志;
微型端口驱动程序不得使用标志NDIS_MAC_OPTION_RESERVED,该标志保留供 NDIS 内部使用。
MiniportOidRequest 还会使用特定于媒体的 OID 进行查询,以确定 NIC 的当前地址。 例如,将使用 OID_802_3_CURRENT_ADDRESS 查询类型为 802.3 的 NIC 的微型端口驱动程序。
某些媒体类型的微型端口驱动程序将收到特定于媒体的其他 OID。 例如,使用 OID_802.3_MAXIMUM_LIST_SIZE 查询 NIC 类型为 802.3 的微型端口驱动程序。
查询面向连接的微型端口驱动程序
若要查询面向连接的微型端口驱动程序维护的信息对象,绑定协议调用 NdisCoOidRequest 并传递 NDIS_OID_REQUEST 结构,该结构指定正在查询的 OID对象,并提供 NDIS 最终将请求的信息写入其中的缓冲区。 调用 NdisCoOidRequest 会导致 NDIS 调用微型端口驱动程序的 MiniportCoOidRequest 函数,该函数将请求的信息返回给 NDIS。 MiniportCoOidRequest 可以通过调用 NdisCoOidRequestComplete 以同步或异步方式完成。
NDIS 还可以自行调用微型端口驱动程序的 MiniportCoOidRequest 函数(例如,在微型端口驱动程序的 MiniportInitializeEx 函数返回NDIS_STATUS_SUCCESS之后)来查询微型端口驱动程序的功能、状态或统计信息。 下图说明了如何查询面向连接的微型端口驱动程序。
面向连接的微型端口驱动程序必须能够提供有关特定 NIC 的所有虚拟连接( (VC) )以及每个 VC 的全局基础信息。 例如,如果将非 NULLNdisVcHandle 提供给 MiniportCoOidRequest 进行 OID_GEN_CO_RCV_CRC_ERROR查询,则微型端口驱动程序将返回指定 VC 上所有接收中遇到的 CRC 错误数。 对于具有 NULLNdisVcHandle 的同一请求,微型端口驱动程序返回通过 NIC 接收的所有传入接收时遇到的 CRC 错误总数。
以下列表包含面向连接的微型端口驱动程序的一组必需的常规操作 OID:
- OID_GEN_CO_SUPPORTED_LIST
- OID_GEN_CO_HARDWARE_STATUS
- OID_GEN_CO_MEDIA_SUPPORTED
- OID_GEN_CO_MEDIA_IN_USE
- OID_GEN_CO_LINK_SPEED
- OID_GEN_CO_VENDOR_ID
- OID_GEN_CO_VENDOR_DESCRIPTION
- OID_GEN_CO_VENDOR_DRIVER_VERSION
- OID_GEN_CO_DRIVER_VERSION
- OID_GEN_CO_MAC_OPTIONS
- OID_GEN_CO_MEDIA_CONNECT_STATUS
- OID_GEN_CO_MINIMUM_LINK_SPEED
微型端口驱动程序的 MiniportCoOidRequest 函数必须准备好对查询或设置做出相应的响应,以响应上述任何 OID。
使用 OID_GEN_CO_MAC_OPTIONS 调用 MiniportCoOidRequest 时,它必须返回指定微型端口驱动程序执行的可选操作的位掩码。 标志集包括:
- NDIS_MAC_OPTION_NO_LOOPBACK。 如果设置了此标志,微型端口驱动程序不会环回传递给 MiniportCoSendNetBufferLists 的 数据包,该数据包定向到同一计算机上的接收器,并且微型端口驱动程序希望 NDIS 执行环回。 如果 NDIS 执行数据包的环回,则数据包不会向下传递到微型端口驱动程序。 微型端口驱动程序始终设置此标志,除非 NIC 执行硬件环回;
- NDIS_MAC_ETOX_INDICATION。 如果设置了此标志,微型端口驱动程序会指示仅在 NIC 传输数据包后完成发送;
微型端口驱动程序不得使用保留供 NDIS 内部使用的 NDIS_MAC_OPTION_RESERVED 标志。
MiniportCoOidRequest 还将使用特定于媒体的 OID 进行查询,以确定 NIC 的当前地址。
直接从用户模式查询微型端口驱动程序
应用程序可以使用 IOCTL_NDIS_QUERY_GLOBAL_STATS 直接从微型端口驱动程序的 NIC 查询信息。 在此操作中,应用程序可以使用微型端口驱动程序支持的任何查询 OID。
查询 64 位统计信息 OID
对于某些统计信息 OID,每秒 1 GB (Gbps) 且速度较快的所有微型端口驱动程序都必须支持 64 位计数器。 所有每秒 100 兆字节 (Mbps) 和更快的微型端口驱动程序应支持此类 OID 的 64 位计数器。
查询统计信息 OID 的请求者NDIS_OID_REQUEST InformationBufferLength 设置为 4 字节,)表示 32 位统计信息请求,或设置为 8 字节以指示 64 位统计信息请求。 在其响应中,微型端口驱动程序将 NDIS_OID_REQUEST BytesNeeded 设置为微型端口驱动程序支持的统计信息值的大小, 4对于 32 位或 8对于 64 位。 微型端口驱动程序将 NDIS_OID_REQUEST BytesWritten 设置为 InformationBufferLength 值的较小值和微型端口驱动程序支持的统计信息大小。
以下部分介绍了支持 64 位统计信息 OID 的微型端口驱动程序如何响应此类 OID 查询。
1. 64 位值的 64 位查询: NDIS_OID_REQUEST InformationBufferLength 大于或等于 8。
微型端口驱动程序:
- 返回信息缓冲区中的 64 位值;
- 将 NDIS_OID_REQUEST BytesWritten 设置为 8;
- 从其 MiniportOidRequest 或 MiniportCoOidRequest 函数返回NDIS_STATUS_SUCCESS;
2. 64 位值的 32 位查询: NDIS_OID_REQUEST InformationBufferLength 大于或等于 4 且小于 8。
微型端口驱动程序:
- 在信息缓冲区中,返回 64 位值的较低 32 位;
- 将 NDIS_OID_REQUEST BytesWritten 设置为 4;
- 将 NDIS_OID_REQUEST BytesNeeded 设置为 8;
- 从其 MiniportOidRequest 或 MiniportCoOidRequest 函数返回NDIS_STATUS_SUCCESS;
3. 64 位值的长度无效查询: NDIS_OID_REQUEST InformationBufferLength 小于 4。
微型端口驱动程序:
- 不返回信息缓冲区中的任何值;
- 将 NDIS_OID_REQUEST BytesWritten 设置为 0;
- 将 NDIS_OID_REQUEST BytesNeeded 设置为 8;
- 从其 MiniportOidRequest 或 MiniportCoOidRequest 函数返回NDIS_STATUS_INVALID_LENGTH;
设置无连接微型端口驱动程序的信息
若要设置无连接微型端口驱动程序维护的 OID,绑定协议调用 NdisOidRequest 并传递一个 NDIS_OID_REQUEST 结构,该结构指定正在查询 的 OID ,该对象指向包含应设置对象的值的缓冲区。 调用 NdisOidRequest 会导致 NDIS 调用微型端口驱动程序的 MiniportOidRequest 函数,该函数使用提供的值设置对象。
对 MiniportOidRequest 的 调用可以同步或异步完成。 若要异步完成调用,微型端口驱动程序调用 NdisMOidRequestComplete。 下图演示了无连接微型端口驱动程序 (每个绑定) 的设置信息。
设置面向连接的微型端口驱动程序的信息
若要设置面向连接的微型端口驱动程序维护的 OID,绑定协议调用 NdisCoOidRequest 并传递一个 NDIS_OID_REQUEST 结构,该结构指定正在查询的 OID) (对象,该对象指向包含应设置对象的值的缓冲区。 调用 NdisCoOidRequest 会导致 NDIS 调用微型端口驱动程序的 MiniportCoOidRequest 函数,该函数使用提供的值设置 对象。
对 NdisCoOidRequest 的 调用可以同步或异步完成。 若要异步完成调用,微型端口驱动程序调用 NdisCoOidRequestComplete。 下图演示了面向连接的微型端口驱动程序中的设置信息。
设置微型端口驱动程序信息的场合
在初始化期间,将调用无连接微型端口驱动程序中的 MiniportOidRequest 函数和面向连接的微型端口驱动程序中的 MiniportCoOidRequest 函数。 还可以以下情况下调用函数:
- 在硬件重置期间;
- 如果协议调用 NdisCloseAdapterEx;
在硬件重置操作期间调用 MiniportOidRequest 或 MiniportCoOidRequest。 在这种情况下,将调用 MiniportOidRequest 或 MiniportCoOidRequest ,以将微型端口驱动程序重置为其地址的初始状态。
当微型端口驱动程序的 NIC 被协议的 NdisCloseAdapterEx 调用关闭时,NDIS 调用 MiniportOidRequest 或 MiniportCoOidRequest。 将请求此类微型端口驱动程序更新其寻址信息。
报告硬件状态
无连接微型端口驱动程序通过调用 NdisMIndicateStatusEx 指示硬件状态到上层的更改。 面向连接的微型端口驱动程序通过调用 NdisMCoIndicateStatusEx 来指示更改。
NdisM (Co) IndicateStatusEx 采用常规状态代码和缓冲区,其中包含媒体特定信息,进一步定义状态更改原因。 NDIS 将此状态更改报告给绑定协议驱动程序。 NDIS 不会解释或以其他方式截获状态代码。
微型端口驱动程序可以发出一个或多个此类调用。 但是,与早期版本的 NDIS 不同,微型端口驱动程序并不指示它已完成发送状态。 协议驱动程序或配置管理器可以记录状态或根据需要采取纠正措施。
NdisMCoIndicateStatusEx 采用任何有效的 NDIS_STATUS_Xxx 值。
微型端口驱动程序负责指示对协议或更高级别驱动程序有意义的状态代码。 协议驱动程序会忽略其不感兴趣或在其操作上下文中没有意义的任何状态值。
微型端口驱动程序不能在其 MiniportInitializeEx、 MiniportInterrupt、 MiniportHaltEx 或 MiniportShutdownEx 函数的上下文中指示状态。
上层驱动程序或 NDIS 还可以询问微型端口驱动程序的硬件状态。 当无 连接微型端口驱动程序的 MiniportOidRequest 函数或面向连接的微型端口驱动程序的 MiniportCoOidRequest 函数收到OID_GEN_HARDWARE_STATUS时,它将使用 NDIS_HARDWARE_STATUS 中定义的任何适用状态值进行响应。 这些状态值包括:
- NdisHardwareStatusReady
- NdisHardwareStatusInitializing
- NdisHardwareStatusReset
- NdisHardwareStatusClosing
- NdisHardwareStatusNotReady
可以查询微型端口驱动程序,以便 NDIS 可以在 NDIS 驱动程序层之间同步操作,例如,通过确定 NIC 是否已准备好接受数据包。
指示连接状态
微型端口驱动程序调用 NdisMIndicateStatusEx 或 NdisMCoIndicateStatusEx 以指示媒体连接状态的更改。 微型端口驱动程序将以下状态指示之一传递给 NdisM (Co) IndicateStatus:
- NDIS_STATUS_MEDIA_CONNECT:指示媒体连接状态从“已断开连接”更改为“已连接”。 当断开连接的适配器建立网络连接时,将发生媒体连接状态更改。 例如,适配器在无线适配器) (范围内或用户连接网络电缆时连接;
- NDIS_STATUS_MEDIA_DISCONNECT:指示媒体连接状态从“已连接”更改为“已断开连接”。 当连接的适配器失去网络连接时,将发生媒体断开连接状态更改。 例如,适配器因无线适配器) (范围或用户拔下网线而失去连接;
除非另行指定,否则微型端口驱动程序应在检测到状态更改后两秒内指示媒体连接状态更改。
微型端口驱动程序可以在执行某些操作时检查媒体连接状态, 查看以下列表。 如果操作完成后的状态与操作开始前的状态相同,微型端口驱动程序不必报告操作期间可能发生的任何状态更改。
以下列表介绍了指示微型端口驱动程序的媒体连接状态更改的其他要求:
重 置: NDIS 调用 MiniportResetEx 来重置微型端口驱动程序。 微型端口驱动程序可以同步或异步完成重置。如果重置后的媒体连接状态不同,驱动程序应在完成重置后的两秒内指示状态。微型端口驱动程序在确定媒体连接状态之前不应完成重置操作;
停止: 当 NDIS 调用 MiniportHaltEx 时,微型端口驱动程序不得指示任何媒体连接状态更改;
正在初始化:NDIS 调用微型端口驱动程序的 MiniportInitializeEx 函数来初始化适配器。 在适配器初始化期间,微型端口驱动程序必须遵循以下准则:
- 如果微型端口驱动程序在从 MiniportInitializeEx 返回后未指示媒体连接状态,则 NDIS 使用 NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES 结构的 MediaConnectState 成员的值来确定媒体连接状态。 当驱动程序从其 MiniportInitializeEx 函数调用 NdisMSetMiniportAttributes 时,微型端口驱动程序为 NDIS 提供此结构。注意 如果 MediaConnectState 成员设置为 MediaConnectStateUnknown,则 NDIS 将继续,就像适配器断开连接一样;
- 如果在 NDIS 调用 MiniportInitializeEx 后连接了适配器,微型端口驱动程序可以在从 MiniportInitializeEx 返回后 5 秒内指示NDIS_STATUS_MEDIA_CONNECT;
- 如果在 NDIS 调用 MiniportInitializeEx 后适配器断开连接,微型端口驱动程序应在从 MiniportInitializeEx 返回后 2 秒内指示NDIS_STATUS_MEDIA_DISCONNECT;
- 初始化时,微型端口驱动程序应异步处理 OID_GEN_MEDIA_CONNECT_STATUS 或 OID_GEN_CO_MEDIA_CONNECT_STATUS 请求。 微型端口驱动程序在确定连接状态之前不应完成此类请求;
- 媒体连接状态的确定不应延迟初始化。 如有必要,微型端口驱动程序应启动该过程以确定 MiniportInitializeEx 中的连接状态,并在以后完成该过程。 例如,微型端口驱动程序可以设置一个计时器来轮询适配器的连接状态;
- 反序列化的微型端口驱动程序可以指示在初始化期间媒体断开连接,但序列化的微型端口驱动程序不应;
睡眠:微型端口驱动程序在收到将设备电源状态设置为 D1、D2 或 D3 的OID_PNP_SET_POWER 请求时进入网络睡眠状态。微型端口驱动程序不得在进入睡眠状态或处于睡眠状态时指示任何媒体连接状态发生更改;
醒来:微型端口驱动程序在收到将设备电源状态设置为 D0 的OID_PNP_SET_POWER请求时从睡眠状态唤醒。如果适配器在唤醒后的媒体连接状态与睡眠前的状态相同,微型端口驱动程序不应指示媒体连接状态更改。 如果连接状态发生更改,微型端口驱动程序应在唤醒后的两秒内指示新的连接状态。唤醒时,微型端口驱动程序应异步处理OID_GEN_MEDIA_CONNECT_STATUS或OID_GEN_CO_MEDIA_CONNECT_STATUS请求。 微型端口驱动程序在确定连接状态之前不应完成此类请求;