urock
Участник
Offline
|
|
« : 15-03-2010 16:38 » |
|
Добрый день! Моему PCI драйверу позарез нужно знать Код Экземпляра Устройства (как в Device Manager) или по-английски: Device Instance ID. ( http://msdn.microsoft.com/en-us/library/dd567984.aspx). Следую MSDN, я узнаю сначала Device ID (или Hardware ID) через вызов IoGetDeviceProperty. Получаю что-то типа "PCI\VENDOR_XXXX_and_so_on" - прямо то что мне надо. Затем к этому надо добавить Instance ID. Опять же следуя MSDN создаю IRP_MJ_PNP (IRP_MN_QUERY_ID) и посылаю его драйверу шины асинхронным способом (то есть, создаю запрос с помощью IoAllocateIrp, и устанавливаю свою CompletionRoutine). В этой функции завершения я и получаю заветный указатель на нужную мне строчку. Проблема только в том, что я получаю какую-то урезанную строку! Конкретнее: в Device Manager вижу, что мой Device Instance ID = "PCI\VENDOR_XXXX_and_so_on\5&12D884F0&0&2020F0", т.е. сам Instance ID = "5&12D884F0&0&2020F0". А драйвер шины возвращает моему драйверу указатель на такую строку: "2020F0" - т.е. состоящую только из 6ти последних символов. Что за черт? Может кто сталкивался с подобным? Спасибо!
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #1 : 15-03-2010 17:00 » |
|
по моему, там часть кода - физический номер шины, куда девайс воткнут. возможно именно его обрубила винда? вы посмотрите сколько вобще Instance ID в спецификации PCI занимает) это в конфиг-спейсе PCI должно быть.
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #2 : 15-03-2010 17:01 » |
|
Во-первых, есть подозрение, что когда сам создаешь IRP, то CompletionRoutine можно не устанавливать.
Что касается остального, то неплохо бы код привести, по формированию IRP (IRP_MN_QUERY_ID). Посмотреть как поля заданы. Вчастности, я бы поэксперементировал (от недостатка опыта) с полем Parameters.QueryId.IdType
|
|
« Последнее редактирование: 15-03-2010 17:03 от resource »
|
Записан
|
|
|
|
urock
Участник
Offline
|
|
« Ответ #3 : 15-03-2010 18:49 » |
|
Ochkarik, в MSDN значение Instance ID, к сожалению, конкретно не определено. Вот цитата: The following is an example of an instance ID ("1&08") concatenated to a device ID for a PCI device:
PCI\VEN_1000&DEV_0001&SUBSYS_00000000&REV_02\1&08 как я понимаю, ничего общего с идентификатором устройства PCI на шине (DDDD:BB:DD:F, где DDDD - домен, BB - номер шины, DD - номер устройства, F - номер функции) это не имеет. resource, CompletionRoutine можно не устанавливать, когда посылаешь синхронный IRP, т.е. завершение которого ты хочешь дождаться. Например с помощью функции IoBuildSynchroniuosFsdRequest. Я так кстати тоже пробовал, но че-то не заработало - в поле Information не было указателя на строку.. Сам код остался на работе, но заверю, что поля заполнены так как сказано тут http://msdn.microsoft.com/en-us/library/ms806519.aspx. В частности поле Parameters.QueryId.IdType было равно BusQueryInstanceID.
|
|
|
Записан
|
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #4 : 15-03-2010 19:31 » |
|
Ну не обязательно IoBuildSynchroniuosFsdRequest. IoAllocateIrp'ом можно создать любой IRP.
Скажу честно, не обладаю достаточным опытом, чтобы сразу понять в чем может быть причина. А потому, я бы на твоем месте попробовал бы IRP_MN_QUERY_ID с разными значениями Parameters.QueryId.IdType и сравнил бы каждый результат с данными Device Manager'а. Подход с одной стороны дилетантский, но с другой - практика это лучший путь познания.
|
|
|
Записан
|
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #5 : 15-03-2010 19:47 » |
|
Походу насчет IoAllocateIrp я действительно не прав
|
|
|
Записан
|
|
|
|
urock
Участник
Offline
|
|
« Ответ #6 : 16-03-2010 06:44 » |
|
вот привожу код создания IRP (делаю я это в самом конце функции AddDevice) status1 = IoAcquireRemoveLock(&pdx->RemoveLock, (PVOID) 42); KdPrint((DRIVERNAME " - IoAcquireRemoveLock returned\n")); if (!NT_SUCCESS(status1)) { KdPrint((DRIVERNAME " - IoAcquireRemoveLock error!\n")); break; } Irp = IoAllocateIrp(pdx->LowerDeviceObject->StackSize, FALSE); KdPrint((DRIVERNAME " - IoAllocateIrp returned \n")); if (!Irp) { KdPrint((DRIVERNAME " - Irp = NULL!\n")); IoReleaseRemoveLock(&pdx->RemoveLock,(PVOID) 42); break; }
PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(Irp); KdPrint((DRIVERNAME " - IoGetNextIrpStackLocation returned \n")); if (!stack) { KdPrint((DRIVERNAME " - IoGetNextIrpStackLocation error!\n")); IoFreeIrp(Irp); IoReleaseRemoveLock(&pdx->RemoveLock,(PVOID) 42); break; }
stack->MajorFunction = IRP_MJ_PNP; stack->MinorFunction = IRP_MN_QUERY_ID; stack->Parameters.QueryId.IdType = BusQueryInstanceID; Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
IoSetCompletionRoutine(Irp,(PIO_COMPLETION_ROUTINE)QueryCompletionRoutine,pdx,TRUE,TRUE,TRUE); KdPrint((DRIVERNAME " - IoSetCompletionRoutine returned\n")); status1 = IoCallDriver(pdx->LowerDeviceObject, Irp); KdPrint((DRIVERNAME " - IoCallDriver returned with status %x\n",status1)); Вот функция завершения: NTSTATUS QueryCompletionRoutine(PDEVICE_OBJECT junk,PIRP Irp,PDEVICE_EXTENSION pdx) { PTSTR instanceId; ULONG instLen; NTSTATUS status; KdPrint((DRIVERNAME " - Entering QueryCompletionRoutine! \n")); instanceId = (PTSTR) Irp->IoStatus.Information; KdPrint((DRIVERNAME " - Got Instance Id = %ws\n",instanceId)); // AAAA // status = RtlStringCbCopyW(pdx->instanceId,100,(const wchar_t*)instanceId); wcscpy(pdx->instanceId,(const wchar_t*)instanceId); KdPrint((DRIVERNAME " - Saved Instance Id = %ws\n",pdx->instanceId)); IoFreeIrp(Irp); IoReleaseRemoveLock(&pdx->RemoveLock,(PVOID) 42); swprintf(pdx->devInstId,L"%ws\\%ws",pdx->hardwareId,pdx->instanceId); KdPrint((DRIVERNAME " - DevInstId = %ws\n",pdx->devInstId));
return STATUS_MORE_PROCESSING_REQUIRED; } На метке //AAAA я уже получаю неправильную (обрезанную) строку. Я тут подумал, что может я рано посылаю свой Query IRP? Может к концу функции AddDevice система еще не до конца сформировала Instance ID, и я получаю просто недоделанный вариант? Попробую сейчас посылать этот запрос из функции StartDevice или вообще в ответ на пользовательский IOCTL запрос.
|
|
|
Записан
|
|
|
|
urock
Участник
Offline
|
|
« Ответ #7 : 16-03-2010 07:12 » |
|
идея с переносом запроса в функцию StartDevice не прошла - возвращается точно то же.
|
|
|
Записан
|
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #8 : 16-03-2010 07:44 » |
|
В QueryCompletionRoutine не мешало бы смотреть поле IoStatus.Status.
Вот ты не хочешь попробовать посмотреть разные Parameters.QueryId.IdType. Ну за неимением вариантов, все же рекомендую. Мне самому интересно, что тебе придет для: BusQueryDeviceID, BusQueryHardwareIDs, BusQueryCompatibleIDs и BusQueryContainerID.
|
|
|
Записан
|
|
|
|
urock
Участник
Offline
|
|
« Ответ #9 : 16-03-2010 07:56 » |
|
да ща гляну - отпишусь.
|
|
|
Записан
|
|
|
|
urock
Участник
Offline
|
|
« Ответ #10 : 16-03-2010 08:28 » |
|
ну BusQueryDeviceID выдает DeviceID, BusQueryHardwareIDs - HardwareIDs, выдает BusQueryCompatibleIDs - CompatibleIDs. Значение ContainerID у меня не определено (WIN XP DDK2600). Зато в wdm.h определено значение BusQueryDeviceSerialNumber. Но когда его используешь - комп перезагружается.
имеет смысл обновить версию DDK может?
|
|
|
Записан
|
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #11 : 16-03-2010 08:34 » |
|
Имеет смысл WDK поставить. Но что касается BusQueryDeviceSerialNumber, то в WDK/DDK написано The following ID type is reserved: BusQueryDeviceSerialNumber Так, что не надо так делать. Жаль что ты конкретные значения не написал (выданные для BusQueryDeviceID и остальные). Интересно (для себя) посмотреть.
|
|
|
Записан
|
|
|
|
urock
Участник
Offline
|
|
« Ответ #12 : 16-03-2010 08:44 » |
|
Слушай, они такие же как и в DeviceManagere. Свойства устройства, вкладка Сведения. Если есть еще необходимость выложить мои - сделаю
|
|
|
Записан
|
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #13 : 16-03-2010 08:51 » |
|
Да ладно. Если ты сам их видел, и видел что они приходят в нормальном виде, то можно не приводить
Просто я всё это к тому, что возможно в твоём запросе ничего не обрубается, а та строка для InstanceID, которую ты видишь в device manager'е на самом деле составная. Вот только из чего она составлена. Может быть посмотреть в сторону DEVICE_CAPABILITIES->UniqueID
|
|
« Последнее редактирование: 16-03-2010 09:20 от resource »
|
Записан
|
|
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #15 : 18-03-2010 21:09 » |
|
Может он формируется самой системой? Всмысле драйвером шины
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #16 : 18-03-2010 21:21 » |
|
ага. проглядел сразу...Device Instance ID формируется системой и не прописан в железе. ну нечему там, кроме географии расположения быть. больше признаков же никаких нет?
|
|
« Последнее редактирование: 18-03-2010 21:36 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
Ochkarik
|
|
« Ответ #17 : 18-03-2010 21:47 » |
|
кстати попробуйте в реестре посмотреть. в каком нибудь HKEY_CURRENT_CONFIG\System\CurrentControlSet\Enum\PCI это может быть вообще адресом памяти, где какая нибудь структура лежит.
|
|
« Последнее редактирование: 18-03-2010 21:50 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #18 : 18-03-2010 21:57 » |
|
Мне всё-таки кажется что ничего не обрубается, а именно device manager показывает уже в каком-то собранном виде. Может быть так приплетены Device Instance ID родительских PDO или типа того. Надо попробовать послать такой запрос к PDO и посмотреть что там придет, и сравнить с тем что показывает Device Manager.
Дело в том, что Device Manager полюбому получает инфу из реестра. А в реестр она известно как попадает. Устройства перечисляются "деревом", от корневого и там дальше уже.
|
|
« Последнее редактирование: 18-03-2010 22:05 от resource »
|
Записан
|
|
|
|
urock
Участник
Offline
|
|
« Ответ #19 : 24-03-2010 06:44 » |
|
Ochkarik, да Device Instance ID должен где-то лежать в реестре, тока где это я не нашел) Но я просто плохо искал.
Решил проблему по-другому. Этого обрезанного кода мне хватает для идентификации устройства. Задача стояла следующая. Пользовательское приложение управляет несколькими одинаковыми платами. На платах ПЛИСы с PCI Express интерфейсом. Глобальная задача была обеспечить реконфигурацию ПЛИС без перезагрузки ОС. Сводилась она к тому, что надо перед реконфигурацией отключить устройство (disable), чтоб к нему никто не обращался, а после реконфигурации сделать рескан шины и включить устройство. Хотелось сделать это автоматически, т.е. чтоб пользовательское приложение управляло всем, оператор бы нажал кнопку и программа сама отключила бы устройство, перезалила прошивку, и включила его. Для этого мне и нужен был этот идентификатор - чтоб знать какое устройство отключать. А дальше я разбирал код программы devcon из DDK и совмещал его с моим кодом. Если интересно - позже могу рассказать как это делать подробнее.
|
|
|
Записан
|
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #20 : 24-03-2010 09:33 » |
|
Конечно интересно. Расскажешь
зы Мне кажется что для твоей задачи вполне достаточно было номера устройства относительно шины
|
|
|
Записан
|
|
|
|
PredatorAlpha
Помогающий
Offline
|
|
« Ответ #21 : 24-03-2010 18:12 » |
|
На платах ПЛИСы с PCI Express интерфейсом. Если не секрет, какие именно FPGA? PCI Express интерфейс сами разрабатывали или встроен в чип стандартный контроллер? Скольки линейный PCI Express? Хотя судя по тому что надо отключить, залить и включить то сами его разрабатывали....
|
|
|
Записан
|
|
|
|
urock
Участник
Offline
|
|
« Ответ #22 : 26-03-2010 07:21 » |
|
FPGA Xilinx Virtex 6. PCI Express ядро сами не разрабатывали. Там уже есть железное ядро + готовая обертка. Мы добавляли только user logic в проект. Сам модуль поддерживает 8 лэйнов.
|
|
|
Записан
|
|
|
|
PredatorAlpha
Помогающий
Offline
|
|
« Ответ #23 : 27-03-2010 07:42 » |
|
У нас на пятом виртексе четырёхлинейка. Не вполне понятно, зачем там нужна реконфигурация. Полной перепрошивки FPGA не может быть, иначе поплывёт логика PCIE (или вы пишете прошивку через драйвер куда-то на плату, запускаете и ждёте??).
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #24 : 27-03-2010 21:09 » |
|
PredatorAlpha, urock, кстати если не ошибаюсь была возможность грузить виртекс частями... или спартан. не разбирался, но ребята говорили что похожая возможность вроде была. кроме того - я подозреваю что можно по горячему платы менять(пусть не механически но на уровне логики шины). по крайней мере - существует же ExpressCard который включает PCI-E и USB. так что - почему бы и нет?
PS кстати а чем прошиваете? мы через PCI свой контроллер JTAG сваяли... по ieee1532. вот только xilinx bsdl-файлы описания не всегда с первого раза правильные выпускает)))
|
|
« Последнее редактирование: 27-03-2010 21:13 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
PredatorAlpha
Помогающий
Offline
|
|
« Ответ #25 : 28-03-2010 20:44 » |
|
PS кстати а чем прошиваете? мы через PCI свой контроллер JTAG сваяли... по ieee1532. вот только xilinx bsdl-файлы описания не всегда с первого раза правильные выпускает)))
Через стандарный внешний JTAG зашиваем бутовую флешку, из которой Xilinx сам грузит конфигурацию FPGA вместе с микропрограммой к встроенному PowerPC440. Переконфигурирование нам не требуется ... пока что, как минимум.
|
|
« Последнее редактирование: 28-03-2010 20:45 от PredatorAlpha »
|
Записан
|
|
|
|
urock
Участник
Offline
|
|
« Ответ #26 : 29-03-2010 07:04 » |
|
PredatorAlpha, да у нас разные схемы загрузки прошивки в ПЛИС. По одному варианту мы загружаем прошивку сначала в SPI Flash, затем я даю команду на перезагрузку, которая по таймеру откладывается на пару секунд, за которые программа как раз выключает устройство. Потом прошивка перезагружается, я делаю рескан шины и включаю устройство. Необходимость в этом может возникнуть у пользователя, когда тому надо будет другой алгоритм прокрутить на ПЛИС. По другому варианту прошивку можно грузить не из Flash, а из другого ПЛИС, установленного на модуле. Ochkarik, да эта частичная реконфигурация давно уже заявлена и Xilinx и Altera но никто пока не сделал нормальную возможность это использовать. По крайней мере я не пока не сталкивался с реально работающими системами, использующими частичную реконфигурацию. Вот тут Altera в очередной раз заявляет что в ее 28nm кристаллах будет user friendly partial reconfiguration http://fpgablog.com/posts/embedded-hardcopy-fpga/?utm_source=feedburner&utm_medium=email&utm_campaign=Feed:+fpgablog+(FPGA+Blog)
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #27 : 29-03-2010 12:16 » |
|
user friendly - это обнадеживает))) правда мы на Xilinx исторически сидим)
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
WWX
Участник
Offline
|
|
« Ответ #28 : 17-12-2019 09:57 » |
|
Практически аналогичная ситуация - тоже в драйвере хотелось бы получить "Instance ID". В принципе как получить в общем-то понятно (хотя пока не пробовал). Но меня смущает последнее предложение из документации Microsoft по запросу IRP_MN_QUERY_ID: After the IRP completes and the driver is finished with the ID, the driver must free the ID structure returned by the driver(s) that handled the query IRP. ( https://docs.microsoft.com/ru-ru/windows-hardware/drivers/kernel/irp-mn-query-id) Не совсем понятно чем освобождать возвращённую строку? ExFreePool здесь наверное не уместен?
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #29 : 17-12-2019 10:07 » |
|
добрый день! я так понимаю как раз ExFreePool - уместен, потому что: 1. If a driver returns ID(s) in response to this IRP, it allocates a WCHAR structure from paged pool to contain the ID(s). 2. The PnP manager frees the structure when it is no longer needed. а поскольку запрос посылает не PnP manager а вы то и освобождать - тоже вам.
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
|