Драйвер перечислил два дочерних PDO, которые вернули идентичные идентификаторы устройств

У меня есть драйвер шины kmdf PCI\VEN_XXXX&DEV_XXXX, который создает два статически перечисляемых PDO с серийными номерами: 217 и 218; один для каждого порта Ethernet. Идентификатор оборудования PDO - ROOT\MY_NIC_PORT, поэтому я могу установить на них драйвер NDIS Miniport.

Водитель автобуса проходит SDV и Verifier; но при перезагрузке перечисляются еще два PDO. При следующей перезагрузке я получаю дубликат сбоя pdo.

В примере тостера используется идентификатор класса устройства как часть идентификатора оборудования. Когда я попытался, мои порты 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.
************************************************************

1 ответ

Решение

Существует несколько версий образца шины тостера. Предположим, вы начали с этого, а затем обратите внимание, что он сохраняет свой список дочерних PDO в реестре. Я предполагаю, что ваш драйвер одновременно загружает PDO из реестра и тоже пытается их динамически создавать.

Установите точку останова в версии вашего драйвера Bus_PlugInDevice и посмотрите, как часто она вызывается. Убедитесь, что он никогда не будет вызываться дважды с одним и тем же ID экземпляра.

Чтобы прояснить ситуацию с именами: класс настройки устройства - это GUID, который полностью не связан с его идентификатором оборудования. Для сетевых карт, которые хотят взаимодействовать с сетевым стеком операционной системы, вы должны использовать класс настройки NET {4d36e972-e325-11ce-bfc1-08002be10318}. Вы можете поместить все, что вы хотите в свой аппаратный идентификатор. На самом деле я не советую вам вводить "ROOT\", поскольку это может быть перепутано с устройством с корневым перечислением (которым не являются ваши устройства). Вместо этого вы можете использовать "yourcompany_yourdevice\port1" в качестве идентификатора оборудования.

Пока вы думаете о присвоении имен, есть несколько моментов, которые следует отметить в отношении идентификаторов оборудования:

  • После того, как вы назначите HWID, его довольно трудно изменить в будущем обновлении драйвера, не нарушая клиентов, которые уже установили ваше устройство. Так что поймите правильно с первого раза.
  • После назначения идентификатора экземпляра не изменяйте и не используйте его повторно в течение всего срока службы устройства. В противном случае вы будете вызывать эту проверку или заставлять IP-адреса перемещаться / сбрасываться. В конечном итоге ОС использует идентификатор экземпляра, чтобы определить, к какому порту NIC привязать IP-адрес.
  • Подумайте, что произойдет, если кто-то подключит 2 устройства к системе. Убедитесь, что ваш идентификатор экземпляра уникален для всех портов. Это можно сделать путем кодирования в Instance ID серийного номера устройства PCI (если оно есть) или возврата к шине PCI:device:function.
  • Не объединяйте разные типы оборудования под одним и тем же идентификатором оборудования. Например, если версия вашего устройства класса "люкс" поддерживает разгрузку контрольной суммы, а обычная версия - нет, вы должны использовать 2 разных идентификатора оборудования для этих двух разных устройств. В противном случае сложно написать один INF, содержащий ключевые слова для обоих.
Другие вопросы по тегам