MikePol
Постоялец
Offline
|
|
« : 08-02-2010 08:39 » |
|
Есть самодельная плата PCI. Написан простой WDM драйвер для чтения регистров памяти (больше в ней нет ничего). Под Windows ХР все работало отлично. А вот в Windows 7 начались непонятные проблемы. Плата определяется, ресурсы выдаются. Но чтения из регистров не происходит (возвращает FFFFFFFF). Поставил Windriver. С помощью его визарда обнаружил, что CMD PCI Configuration Space равен 0, а должен быть 2 (В ХР он всегда равен 2). Если в визарде записать туда 2 - все работает. Теперь хочу сделать такую же запись программно при инициализации устройства. Попробовал в IRP_MN_START_DEVICE записывать 2 в CMD - не помогает. Возможно нужно делать запись в другом месте ? Вопросов 2 : 1. Почему в Win7 CMD =0. (Есть один способ получить CMD=2 в Win7 - после загрузки компьютера заставить его "уснуть" (завершение работы - сон). Тогда при пробуждении CMD становится =2)/ 2. В какое время нужно записывать 2 в CMD ?
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #1 : 08-02-2010 09:41 » |
|
Знаете, это что-то с платой не так. Потому что наша самопальная плата работает от XP/Vista до Windows-7 без проблем. При этом я точно ни в какой config PCI не лезу и ничего туда сверх того что пишет операционка - не пишу. честно говоря я даже конфигурационные регистры PCI ни разу не смотрел. может быть вы IRP_MN_START_DEVICE некорректно обрабатываете? по портам у меня единственная экзотика стоит: case CmResourceTypePort: devExt->Port.MappedPort = (pPartialDescriptors->Flags & CM_RESOURCE_PORT_IO) == 0; //надо ли мапировать порты(для RISC) if (devExt->Port.MappedPort) { //RISC архитектура (порты отображаются в оперативную память) devExt->PortBaseAddr = (DWORD) MmMapIoSpace (devExt->Port.Start, devExt->Port.Length, //==4*4 MmNonCached); KdPrint(( "MmMapIoSpace \n")); };
но скорее всего это кросплатформенная ересь, после отравления парами DDK Windows98)
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
MikePol
Постоялец
Offline
|
|
« Ответ #2 : 08-02-2010 11:34 » |
|
Да, вроде бы, стандартно все обрабатываю. case IRP_MN_START_DEVICE: {
KdPrint((DRIVERNAME "Enter in IRP_MN_START_DEVICE\n")); Irp->IoStatus.Status = STATUS_SUCCESS; // status = ForwardAndWait((PDEVICE_EXTENSION)fdo->DeviceExtension, Irp); //
KdPrint((DRIVERNAME "STATUS = %d\n",status));
if (!NT_SUCCESS(status)) return CompleteRequest(Irp, status, Irp->IoStatus.Information);
PCM_PARTIAL_RESOURCE_LIST raw, translated; raw = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList; translated = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
status = StartDevice(fdo,raw,translated); KdPrint((DRIVERNAME "STATUS = %d\n",status)); return CompleteRequest(Irp, status, Irp->IoStatus.Information); break; } NTSTATUS StartDevice(PDEVICE_OBJECT fdo, PCM_PARTIAL_RESOURCE_LIST raw, PCM_PARTIAL_RESOURCE_LIST translated) { // StartDevice NTSTATUS status=STATUS_SUCCESS; PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
PHYSICAL_ADDRESS portbase; BOOLEAN gotport = FALSE; if (!translated) { KdPrint(("Resourse not translated !!! ")); return STATUS_DEVICE_CONFIGURATION_ERROR; // no resources assigned?? } KdPrint(("TRNSLATED OK !!! "));
PCM_PARTIAL_RESOURCE_DESCRIPTOR resource = translated->PartialDescriptors; ULONG nres = translated->Count; KdPrint((" N resourse %d \n", nres));
PHYSICAL_ADDRESS membase;
bool isport = TRUE;
for (ULONG i = 0; i < nres; ++i, ++resource) { // for each resource switch (resource->Type) { // switch on resource type
case CmResourceTypePort: portbase = resource->u.Port.Start; pdx->nports = resource->u.Port.Length; KdPrint((DRIVERNAME " - I/O resource PORT %d\n", portbase)); pdx->mappedport = (resource->Flags & CM_RESOURCE_PORT_IO) == 0; gotport = TRUE;
break; case CmResourceTypeMemory: { membase = resource->u.Memory.Start;
pdx->mem_length = resource->u.Memory.Length; KdPrint((DRIVERNAME " - I/O resource MEMORY start = %X length =%d \n", membase,pdx->mem_length )); gotport = TRUE; isport = FALSE; break; } default: KdPrint((DRIVERNAME " - Unexpected I/O resource type %d\n", resource->Type)); break; } // switch on resource type } // for each resource
if (!(TRUE && gotport )) { KdPrint((DRIVERNAME " - Didn't get expected I/O resources\n")); return STATUS_DEVICE_CONFIGURATION_ERROR; }
pdx->portaddr = portbase.LowPart; KdPrint((DRIVERNAME " Mike - PortADDR %0x My ", pdx->portaddr ));
KdPrint((DRIVERNAME "STATUS = %X\n",status));
pdx->ismem_plata = !isport;
KdPrint((DRIVERNAME "Isport = %d\n",isport));
if (!isport) { pdx->mem_start = (PUCHAR) MmMapIoSpace(membase, pdx->mem_length, MmNonCached);
KdPrint((DRIVERNAME "membase = %x memstart =%x memlength = %d", membase.LowPart, *(pdx->mem_start), pdx->mem_length ));
if (!pdx->mem_start) return STATUS_NO_MEMORY; } Единственное что меня смущает, что я получаю вместо одного ресурса - 2. Один из них диапазон памяти, а второй неизвестный CmResourceTypeDevicePrivate.
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #3 : 08-02-2010 12:54 » |
|
http://www.osronline.com/showThread.cfm?link=13272IRP_MN_START_DEVICE должен начинаться status = SendIrpSynchronously(Irp, devExt->LowerDevice); if (NT_SUCCESS(status) && NT_SUCCESS(Irp->IoStatus.Status)) { ...ваша инициализация ресурсов.
и заканчиваться так: Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status;
функция return CompleteRequest(Irp, status, Irp->IoStatus.Information) это включает? PS SendIrpSynchronously() понятно что) CallDriver() + WFSO
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
MikePol
Постоялец
Offline
|
|
« Ответ #4 : 09-02-2010 06:52 » |
|
IRP_MN_START_DEVICE должен начинаться status = SendIrpSynchronously(Irp, devExt->LowerDevice); if (NT_SUCCESS(status) && NT_SUCCESS(Irp->IoStatus.Status)) { ...ваша инициализация ресурсов.
Да, ForwardAndWait выглядит вот так : return IoForwardIrpSynchronously(pdx->LowerDeviceObject, Irp);
CompleteRequest: NTSTATUS CompleteRequest(IN PIRP Irp, IN NTSTATUS status, IN UINT_PTR info) { // CompleteRequest Irp->IoStatus.Status = status; Irp->IoStatus.Information = info; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } // CompleteRequest За ссылку спасибо, я правильно понял, что CmResourceTypeDevicePrivate - это нормально и обрабатывать его должен только драйвер шины ?
|
|
|
Записан
|
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #5 : 09-02-2010 07:32 » |
|
С одной стороный, вроде бы плата гонять может. С другой почему тогда в XP всё подругому? Неясно
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #6 : 09-02-2010 07:55 » |
|
IoForwardIrpSynchronously - ух ты! а я все по старинке сам вызываю...)
да насчет ресурсов правильно)
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #7 : 09-02-2010 08:02 » |
|
Мистика. Но если нет вообще никаких вариантов что и где не так, то остается вручную выставить CMD при помощи, например IRP_MN_WRITE_CONFIG
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #8 : 09-02-2010 08:08 » |
|
PS а попробуйте еще DriverStudio 3.2 генерилку на чистом Си.... WinDriver мне раньше не нравился) правда давно его смотрел.. в DS рыбу генерить тоже 5 минут)
PPS а если картина будет той же... тогда действительно либо железо смотреть либо....вручную.
|
|
« Последнее редактирование: 09-02-2010 08:10 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
MikePol
Постоялец
Offline
|
|
« Ответ #9 : 09-02-2010 11:00 » |
|
Всем спасибо. В итоге получилось записать в CMD программным путем в IRP_MN_START_DEVICE при помощи IRP_MN_WRITE_CONFIG. Другого варианта пока не вижу. WinDriver -ом для разработки я не пользовался. Пользовался только его инструментами для диагностики железки. В итоге плата нормально работает под Linux, 2000, XP. В win7, Win Vista - нормально работает после записи IRP_MN_WRITE_CONFIG. Почему не работает так и не понял.
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #10 : 09-02-2010 23:05 » |
|
кстати если имеется в виду тот 16 битный регистр по адресу 0x4 в конфигурационном пространстве... он отвечает за включение устройства - генерацию и ответ на соответствующие запросы по PCI шине) то в спецификации PCI 2.3 стр.197 таблица 6-1 PS непонятно почему он не взводится... жаль времени нет) на нашей железке бы исследовал вопрос... в спецификации сказано что он должен быть 0 при инициализации. судя по тому что в winXP вы читаете из него что то отличное от 0 - значит именно windows включает устройство. значит либо у нас на этот регистр наплевали при разработке контроллера( а в microsoft изменили управление этим регистром), и поэтому наша железка под Vista/Win7 работает без плясок с конфигом, либо вы что то в драйвере неправильно сделали... что там еще повлиять может. может быть IRP_MJ_POWER... что то еще было среди IRP_MJ_PNP по поводу конфигурирования ресурсов. PPS и непонятно почему писать надо "2"... второй бит за память отвечает....
|
6-1.JPG (108.61 Кб - загружено 1927 раз.)
|
« Последнее редактирование: 09-02-2010 23:23 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #11 : 10-02-2010 00:06 » |
|
PPS и непонятно почему писать надо "2"... второй бит за память отвечает.... Я, если честно, так плотно с PCI не работал как вы, а когда что-то надо было, "выдергивал" куски из спецификации наскоро. Поэтому многих ньюансов не знаю. Но вот когда у меня был вопрос по поводу значения CMD, я для себя обнаружил такую таблицу
|
|
« Последнее редактирование: 10-02-2010 00:09 от resource »
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #12 : 10-02-2010 05:57 » |
|
да я сам PCI - не писал))) а последняя таблица - это по-моему физические сигналы - то что по самой шине идет. "The Command lines (C/BE3 to C/BE0) indicate the type of bus transfer during the address phase." но это не команды программного конфигурирования...
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #13 : 10-02-2010 07:23 » |
|
Написан простой WDM драйвер для чтения регистров памяти Единственное что меня смущает, что я получаю вместо одного ресурса - 2. Один из них диапазон памяти ... второй бит за память отвечает.... Тут не поспоришь даже
|
|
|
Записан
|
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #14 : 10-02-2010 07:56 » |
|
Кстати по поводу CmResourceTypeDevicePrivate тоже интересный момент. Я никакого описания к этой вещи не видел кроме как "драйвер шины знает что с ним делать". Ну допустим я пишу драйвер шины. И чего мне с ним делать?
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #15 : 10-02-2010 18:25 » |
|
кстати... джентельмены, а вы думаете про эту функцию RtlCmDecodeMemIoResource? и почему она прописана в http://msdn.microsoft.com/en-us/library/dd852012.aspxDrivers for Windows Vista and later versions of the Windows operating system can use RtlCmDecodeMemIoResource and RtlCmEncodeMemIoResource to read and update the u.Port member, rather than updating it directly. или это макрос?
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
Ochkarik
|
|
« Ответ #16 : 10-02-2010 18:30 » |
|
https://www.osronline.com/ShowThread.cfm?link=149346еще ветка про CmResourceTypeDevicePrivate... I have two specific responses to your issue, and then a long treatise on the history of I/O space that explains why you're having to deal with this in gory detail.
First the specific responses: 1) if you use "!devnode <address> e" to look at the format of the resource requirements list that gets created for your device, you will notice that each BAR requirement is followed by one of CmResourceTypeDevicePrivate. This contains data associated with the requirement preceding it. They have to be removed as a pair. 2) re: your suggestion to modify the I/O enable bit manually - this is also bad. The PCI driver believes it owns this bit, and will set and clear it at the appropriate times. Your code would have to keep up with all of these times, and avoid synchronization issues that come from two drivers trying to manage the same bit in different ways. This is the kind of thing that would work until it doesn't. It would be much, much, much better if there were an un-decoding address that the BAR could be set to.
|
|
« Последнее редактирование: 10-02-2010 18:32 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #17 : 11-02-2010 01:27 » |
|
или это макрос? В хедерах написано #if (NTDDI_VERSION >= NTDDI_VISTA) NTSYSAPI ULONGLONG NTAPI RtlCmDecodeMemIoResource ( __in PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor, __out_opt PULONGLONG Start ); #endif Как видно - не макрос Насколько я понял, RtlCmDecodeMemIoResource автоматизирует действие типа portbase = resource->u.Port.Start; numports = resource->u.Port.Length Как утверждает DDK, она может так делать для CmResourceTypeMemory, CmResourceTypeMemoryLarge и CmResourceTypePort. Видимо я не всё понимаю про эту функцию, и поэтому она мне кажется совершенно бесполезной. Ведь все равно придется пролистывать структуры CM_PARTIAL_RESOURCE_DESCRIPTOR и смотреть какого они типа, а те две строчки я и сам могу написать. Неясно. Судя по тому, что RtlCmDecodeMemIoResource может быть вызвана на любом IRQL, ничего особого она больше не делает (не факт конечно), т.е. если что, надо не забыть вручную вызвать MmMapIoSpace (если вы к примеру счастливый обладатель Alpha)
|
|
|
Записан
|
|
|
|
|