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

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

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

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

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

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

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

« Ответ #3 : 08-02-2010 12:54 » 

http://www.osronline.com/showThread.cfm?link=13272

IRP_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 уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
MikePol
Постоялец

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

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

« Ответ #5 : 09-02-2010 07:32 » 

С одной стороный, вроде бы плата гонять может. С другой почему тогда в XP всё подругому? Неясно
Записан
Ochkarik
Модератор

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

« Ответ #6 : 09-02-2010 07:55 » 

IoForwardIrpSynchronously - ух ты! а я все по старинке сам вызываю...)

да насчет ресурсов правильно)
Записан

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

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

« Ответ #7 : 09-02-2010 08:02 » 

Мистика. Но если нет вообще никаких вариантов что и где не так, то остается вручную выставить CMD при помощи, например IRP_MN_WRITE_CONFIG
Записан
Ochkarik
Модератор

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

« Ответ #8 : 09-02-2010 08:08 » 

PS а попробуйте еще DriverStudio 3.2 генерилку на чистом Си.... WinDriver мне раньше не нравился) правда давно его смотрел..
в DS рыбу генерить тоже 5 минут)

PPS а если картина будет той же... тогда действительно либо железо смотреть либо....вручную.
« Последнее редактирование: 09-02-2010 08:10 от Ochkarik » Записан

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

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

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

« Ответ #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 Кб - загружено 1926 раз.)
« Последнее редактирование: 09-02-2010 23:23 от Ochkarik » Записан

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

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

« Ответ #11 : 10-02-2010 00:06 » 

Цитата: Ochkarik
PPS и непонятно почему писать надо "2"... второй бит за память отвечает....

Я, если честно, так плотно с PCI не работал как вы, а когда что-то надо было, "выдергивал" куски из спецификации наскоро. Поэтому многих ньюансов не знаю. Но вот когда у меня был вопрос по поводу значения CMD, я для себя обнаружил такую таблицу

* pci_1.JPG (42.87 Кб - загружено 1882 раз.)
« Последнее редактирование: 10-02-2010 00:09 от resource » Записан
Ochkarik
Модератор

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

« Ответ #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 уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
resource
Молодой специалист

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

« Ответ #13 : 10-02-2010 07:23 » 

Цитата: MikePol
Написан простой WDM драйвер для чтения регистров памяти
Цитата: MikePol
Единственное что меня смущает, что я получаю вместо одного ресурса - 2. Один из них диапазон памяти
Цитата: Ochkarik
... второй бит за память отвечает....
Тут не поспоришь даже
Записан
resource
Молодой специалист

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

« Ответ #14 : 10-02-2010 07:56 » 

Кстати по поводу CmResourceTypeDevicePrivate тоже интересный момент. Я никакого описания к этой вещи не видел кроме как "драйвер шины знает что с ним делать". Ну допустим я пишу драйвер шины. И чего мне с ним делать?
Записан
Ochkarik
Модератор

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

« Ответ #15 : 10-02-2010 18:25 » 

кстати... джентельмены, а вы думаете про эту функцию RtlCmDecodeMemIoResource?

и почему она прописана в http://msdn.microsoft.com/en-us/library/dd852012.aspx
Цитата
Drivers 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 уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Ochkarik
Модератор

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

« Ответ #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 уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
resource
Молодой специалист

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

« Ответ #17 : 11-02-2010 01:27 » 

Цитата: Ochkarik
или это макрос?

В хедерах написано
Код:
#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)
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines