Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2  Все   Вниз
  Печать  
Автор Тема: Device Instance ID  (Прочитано 40539 раз)
0 Пользователей и 8 Гостей смотрят эту тему.
urock
Участник

ru
Offline 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
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 15-03-2010 17:00 » 

по моему, там часть кода - физический номер шины, куда девайс воткнут. возможно именно его обрубила винда?
вы посмотрите сколько вобще Instance ID в спецификации PCI занимает) это в конфиг-спейсе PCI должно быть.
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 15-03-2010 17:01 » 

Во-первых, есть подозрение, что когда сам создаешь IRP, то CompletionRoutine можно не устанавливать.

Что касается остального, то неплохо бы код привести, по формированию IRP (IRP_MN_QUERY_ID). Посмотреть как поля заданы. Вчастности, я бы поэксперементировал (от недостатка опыта) с полем Parameters.QueryId.IdType
« Последнее редактирование: 15-03-2010 17:03 от resource » Записан
urock
Участник

ru
Offline 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
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 15-03-2010 19:31 » 

Ну не обязательно IoBuildSynchroniuosFsdRequest. IoAllocateIrp'ом можно создать любой IRP.

Скажу честно, не обладаю достаточным опытом, чтобы сразу понять в чем может быть причина. А потому, я бы на твоем месте попробовал бы IRP_MN_QUERY_ID с разными значениями Parameters.QueryId.IdType и сравнил бы каждый результат с данными Device Manager'а. Подход с одной стороны дилетантский, но с другой - практика это лучший путь познания.
Записан
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 15-03-2010 19:47 » 

Походу насчет IoAllocateIrp я действительно не прав
Записан
urock
Участник

ru
Offline 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
Участник

ru
Offline Offline

« Ответ #7 : 16-03-2010 07:12 » 

идея с переносом запроса в функцию StartDevice  не прошла - возвращается точно то же.
Записан
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 16-03-2010 07:44 » 

В QueryCompletionRoutine не мешало бы смотреть поле IoStatus.Status.

Вот ты не хочешь попробовать посмотреть разные Parameters.QueryId.IdType. Ну за неимением вариантов, все же рекомендую. Мне самому интересно, что тебе придет для: BusQueryDeviceID, BusQueryHardwareIDs, BusQueryCompatibleIDs и BusQueryContainerID.
Записан
urock
Участник

ru
Offline Offline

« Ответ #9 : 16-03-2010 07:56 » 

да ща гляну - отпишусь.
Записан
urock
Участник

ru
Offline Offline

« Ответ #10 : 16-03-2010 08:28 » 

ну BusQueryDeviceID выдает DeviceID, BusQueryHardwareIDs - HardwareIDs,  выдает BusQueryCompatibleIDs - CompatibleIDs. Значение  ContainerID у меня не определено (WIN XP DDK2600). Зато в wdm.h определено значение BusQueryDeviceSerialNumber. Но когда его используешь - комп перезагружается.

имеет смысл обновить версию DDK может?
Записан
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 16-03-2010 08:34 » 

Имеет смысл WDK поставить. Но что касается BusQueryDeviceSerialNumber, то в WDK/DDK написано
Цитата
The following ID type is reserved: BusQueryDeviceSerialNumber

Так, что не надо так делать.
Жаль что ты конкретные значения не написал (выданные для BusQueryDeviceID и остальные). Интересно (для себя) посмотреть.
Записан
urock
Участник

ru
Offline Offline

« Ответ #12 : 16-03-2010 08:44 » 

Слушай, они такие же как и в DeviceManagere. Свойства устройства, вкладка Сведения. Если есть еще необходимость выложить мои - сделаю
Записан
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #13 : 16-03-2010 08:51 » 

Да ладно. Если ты сам их видел, и видел что они приходят в нормальном виде, то можно не приводить

Просто я всё это к тому, что возможно в твоём запросе ничего не обрубается, а та строка для InstanceID, которую ты видишь в device manager'е на самом деле составная. Вот только из чего она составлена. Может быть посмотреть в сторону DEVICE_CAPABILITIES->UniqueID
« Последнее редактирование: 16-03-2010 09:20 от resource » Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #14 : 18-03-2010 21:07 » 

а кто такое этот Device Instance ID?
все что я вижу это
http://ru.wikipedia.org/wiki/PCI_configuration_space
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #15 : 18-03-2010 21:09 » 

Может он формируется самой системой? Всмысле драйвером шины
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #16 : 18-03-2010 21:21 » 

ага. проглядел сразу...Device Instance ID формируется системой и не прописан в железе.
ну нечему там, кроме географии расположения быть. больше признаков же никаких нет?
« Последнее редактирование: 18-03-2010 21:36 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #17 : 18-03-2010 21:47 » new

кстати попробуйте в реестре посмотреть. в каком нибудь HKEY_CURRENT_CONFIG\System\CurrentControlSet\Enum\PCI
это может быть вообще адресом памяти, где какая нибудь структура лежит.
« Последнее редактирование: 18-03-2010 21:50 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
resource
Молодой специалист

ru
Offline 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
Участник

ru
Offline Offline

« Ответ #19 : 24-03-2010 06:44 » 

Ochkarik,  да Device Instance ID должен где-то лежать в реестре, тока где это я не нашел) Но я просто плохо искал.

Решил проблему по-другому.  Этого обрезанного кода мне хватает для идентификации устройства. Задача стояла следующая. Пользовательское приложение управляет несколькими одинаковыми платами.  На платах ПЛИСы с PCI Express интерфейсом. Глобальная задача была обеспечить реконфигурацию ПЛИС без перезагрузки ОС. Сводилась она к тому, что надо перед реконфигурацией отключить устройство (disable), чтоб к нему никто не обращался, а после реконфигурации сделать рескан шины и  включить устройство. Хотелось сделать это автоматически, т.е. чтоб пользовательское приложение управляло всем, оператор бы нажал кнопку и программа сама отключила бы устройство, перезалила прошивку, и включила его. Для этого мне и нужен был этот идентификатор - чтоб знать какое устройство отключать. А дальше я разбирал код программы devcon из DDK и совмещал его с моим кодом. Если интересно - позже могу рассказать как это делать подробнее.
Записан
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #20 : 24-03-2010 09:33 » 

Конечно интересно. Расскажешь

зы Мне кажется что для твоей задачи вполне достаточно было номера устройства относительно шины
Записан
PredatorAlpha
Помогающий

us
Offline Offline

« Ответ #21 : 24-03-2010 18:12 » 

  На платах ПЛИСы с PCI Express интерфейсом.
Если не секрет, какие именно FPGA? PCI Express интерфейс сами разрабатывали или встроен в чип стандартный контроллер? Скольки линейный PCI Express?
Хотя судя по тому что надо отключить, залить и включить то сами его разрабатывали....
Записан
urock
Участник

ru
Offline Offline

« Ответ #22 : 26-03-2010 07:21 » 

FPGA Xilinx Virtex 6. PCI Express ядро сами не разрабатывали. Там уже есть железное ядро + готовая обертка.  Мы добавляли только user logic в проект. Сам модуль поддерживает 8 лэйнов.
Записан
PredatorAlpha
Помогающий

us
Offline Offline

« Ответ #23 : 27-03-2010 07:42 » 

У нас на пятом виртексе четырёхлинейка.
Не вполне понятно, зачем там нужна реконфигурация.
Полной перепрошивки FPGA не может быть, иначе поплывёт логика PCIE (или вы пишете прошивку через драйвер куда-то на плату, запускаете и ждёте??).
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #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 уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
PredatorAlpha
Помогающий

us
Offline Offline

« Ответ #25 : 28-03-2010 20:44 » 

Цитата
PS
кстати а чем прошиваете? мы через PCI свой контроллер JTAG сваяли... по ieee1532. вот только xilinx bsdl-файлы описания не всегда с первого раза правильные выпускает)))
Через стандарный внешний JTAG зашиваем бутовую флешку, из которой Xilinx сам грузит конфигурацию FPGA вместе с микропрограммой к встроенному PowerPC440. Переконфигурирование нам не требуется ... пока что, как минимум.
« Последнее редактирование: 28-03-2010 20:45 от PredatorAlpha » Записан
urock
Участник

ru
Offline 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
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #27 : 29-03-2010 12:16 » 

user friendly - это обнадеживает)))
правда мы на Xilinx исторически сидим)
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
WWX
Участник

ru
Offline 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
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #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 уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Страниц: [1] 2  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines