驱动程序枚举了两个返回相同设备 ID 的子 PDO

A driver has enumerated two child PDO's that returned identical Device ID's

我有一个 kmdf 总线驱动程序 PCI\VEN_XXXX&DEV_XXXX,它创建两个序列号为 217 和 218 的静态枚举 PDO;每个以太网端口一个。 PDO 硬件 ID 为 ROOT\MY_NIC_PORT,因此我可以在其上安装 NDIS 微型端口驱动程序。

总线驱动通过SDV和Verifier;但是,在重新启动时会枚举另外两个 PDO。在下次重新启动时,我遇到重复的 pdo 崩溃。

烤面包机示例使用设备 class guid 作为硬件 ID 的一部分。当我尝试在设备管理器中不再显示我的 NIC 端口时。

如有任何调试建议或解决方法,我们将不胜感激?

pnpCaps.LockSupported = WdfFalse;
pnpCaps.EjectSupported = WdfTrue;
pnpCaps.Removable = WdfTrue;
pnpCaps.DockDevice = WdfFalse;
pnpCaps.UniqueID = WdfTrue;
pnpCaps.SilentInstall = WdfTrue;
pnpCaps.SurpriseRemovalOK = WdfTrue;
pnpCaps.HardwareDisabled = WdfFalse;
pnpCaps.NoDisplayInUI = WdfFalse;
pnpCaps.Address = SerialNo;
pnpCaps.UINumber = SerialNo;

************************************************************
Driver Verifier detected violation:

A driver has enumerated two child PDO's that returned identical Device
ID's.

CulpritAddress = FFFFF8025ED309C4, DeviceObject1 = FFFFE3882FB2F300, 
DeviceObject2 = FFFFE3882EBF88D0.
************************************************************

烤面包机总线示例有几个版本——假设您从 this one 开始,然后请注意它在注册表中保存了其子 PDO 列表。我的猜测是您的驱动程序既从注册表加载 PDO,又试图动态创建一些 PDO。

在您的 Bus_PlugInDevice 驱动程序版本上设置一个断点,然后查看它被调用的频率。确保永远不会使用相同的实例 ID 调用 2x。

澄清一点命名问题:设备设置class是一个与其硬件ID完全无关的GUID。对于想要与 OS 的网络堆栈互操作的 NIC,您必须使用 NET 设置 class,{4d36e972-e325-11ce-bfc1-08002be10318}。您可以将任何您想要的内容放入您的硬件 ID。我真的不鼓励你把 "ROOT\" 放在那里,因为这可能会与根枚举设备(你的设备不是)混淆。相反,您可以使用 "yourcompany_yourdevice\port1" 作为硬件 ID。

当您在考虑命名时,有一些关于硬件 ID 的注意事项:

  • 一旦您分配了 HWID,就很难在未来的驱动程序更新中更改它,而不会破坏已经安装了您设备的客户。所以第一次做对。
  • 分配实例 ID 后,请勿在设备的整个生命周期内更改或重复使用它。否则,您将导致此错误检查,或导致 IP 地址跳转/重置。 OS 最终使用实例 ID 来确定将 IP 地址绑定到哪个 NIC 端口。
  • 想一想如果有人将您的 2 个设备插入系统会发生什么。确保您的实例 ID 在所有端口中都是唯一的。您可以通过将 PCI 设备序列号(如果有的话)编码到实例 ID 中或回退到 PCI bus:device:function.
  • 来完成此操作
  • 不要将不同类型 的硬件归为同一硬件 ID。例如,如果您的设备的豪华版支持校验和卸载,但普通版不支持——您应该为这两种不同的设备使用 2 个不同的硬件 ID。否则很难编写一个包含两者关键字的 INF。