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

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

ru
Offline Offline

« : 22-05-2008 06:59 » 

На примере Oney собрал драйвера для PCI устройства. Устройство работает только с портами ввода/вывода.
Драйвер работает в 2000/XP, в 98-м пишет "ошибка код 10", но все равно работает.
Скачал Windows Driver Kits для того, чтобы собрать под висту. Драйвер отлично собирается - никаких ошибок.
Но при установке, после указания системе .sys файла появляется окно установки и оно зависает. В конце концов система выдает ошибку (истекло время ожидания).
Для отладки под 2000/ХР я использовал DebugView ( в коде использую KdPrint). Под вистой эта утилита не работает (не может сделать Kernel Capture). Посмотреть в каком месте зависает не могу Жаль
В чем может быть проблема ? Как под вистой можно смотреть отладочные сообщения драйвера ?
И вообще какие отладчики существуют под Висту ?
Записан
Ochkarik
Модератор

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

« Ответ #1 : 22-05-2008 10:34 » 

по поводу отладки - глянь пару постов назад, флаг в реестре надо взвести. где то я кидал ссылку.
кстати, посмотри, у меня под вистой была ерунда, что в inf-е админские права на доступ по R/W стояли, а апликуха в висте по умолчанию от пользователя запускается, даже если ты админ.
PS
http://blogs.msdn.com/doronh/archive/2006/11/14/where-did-my-debug-output-go-in-vista.aspx
"If you are using DbgPrint for your debug output in Vista you may have noticed that you cannot see anything in the debugger.  That is because DbgPrint now defaults to the DEFAULT debug component (you can read about the change here) and the default settings for this component is to hide all output.  To remedy this you can do either of the following

Change the value of Kd_DEFAULT_MASK to 0xFFFFFFFF ('ed nt!Kd_DEFAULT_MASK  0xFFFFFFFF') at runtime or right after boot
Open up the registry and go to this path, HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Debug Print Filter and add the following value "DEFAULT" : REG_DWORD : 0xFFFFFFFF and then reboot
This will allow you to see your debug output, but you might see a lot of other components' output as well.  One way to mitigate this is to use DbgPrintEx instead and pick the component ID which most closely matches your driver's functionality.  Note that DbgPrintEx is only available on Windows XP and later so if you need to support Windows 2000 you might want want to stick with DbgPrint since choosing which function to use at runtime can be difficult (since passing var args can be difficult unless you have variadic parameter support for macros (which the latest WDK has))."
« Последнее редактирование: 22-05-2008 10:36 от Ochkarik » Записан

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

ru
Offline Offline

« Ответ #2 : 28-05-2008 06:05 » 

А Вы не могли бы объяснить где надо менять "Kd_DEFAULT_MASK to 0xFFFFFFFF " ?
У меня раздела реестра "Debug Print Filter " не существует. Его надо создать , а потом добавить в него параметр "Default" со значением 0xFFFFFFFF  ?
Записан
MikePol
Постоялец

ru
Offline Offline

« Ответ #3 : 28-05-2008 06:38 » 

Все, разобрался, спасибо !
Записан
MikePol
Постоялец

ru
Offline Offline

« Ответ #4 : 29-05-2008 07:23 » 

Проблема с DbgView решилась. Но запустить драйвер под вистой мне так и не удалось.
Нормально отрабатывает DriverEntry, AddDivice, StartDevice (IRP_MN_START_DEVICE).
Но установщик ОС пытается установить несколько минут ( полоска бегает) но потом выдает сообщение : "Возврат из операции произошел из-за превышения времени ожидания". DbgView показывает, что после этого приходят еще несколько пакетов (PNP), которые я отбрасываю.

   
Код:
     IoSkipCurrentIrpStackLocation(Irp);
             return IoCallDriver(pdx->LowerDeviceObject, Irp);

В диспетчере устройств, устройство отображается, как будто все драйвера нормально установились, однако , если зайти на вкладку ресуры - окно зависает. Устройство должно использовать диапазон портов ввода вывода (8 байт)
Ниже код трех функций  DriverEntry, AddDivice, StartDevice (IRP_MN_START_DEVICE).
В чем может быть проблема ?


Код:
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{ // DriverEntry
KdPrint((DRIVERNAME " - Entering DriverEntry: DriverObject %8.8lX\n", DriverObject));

// Insist that OS support at least the WDM level of the DDK we use

if (!IoIsWdmVersionAvailable(1, 0))
{
KdPrint((DRIVERNAME " - Expected version of WDM (%d.%2.2d) not available\n", 1, 0));
return STATUS_UNSUCCESSFUL;
}

// See if we're running under Win98 or NT:

KdPrint(("\n NOW TEST RIGISTRY \n N"));
       
win98 = FALSE;

#if DBG
if (win98)
KdPrint((DRIVERNAME " - Running under Windows 98\n"));
else
KdPrint((DRIVERNAME " - Running under NT\n"));
#endif

DriverObject->DriverUnload = DriverUnload;
DriverObject->DriverExtension->AddDevice = AddDevice;

DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
//DriverObject->MajorFunction[IRP_MJ_READ] = DispatchReadWrite;
// DriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchCleanup;
// DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
//DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = DispatchWmi;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=DispatchControl;

cardnumber = 0;
   



   
KdPrint(("Mike : Entry Completed \n "));
   
//char tempstr = masind[cardnumber] ;

//KdPrint((tempstr));

return STATUS_SUCCESS;
} // DriverEntry

Код:
NTSTATUS AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT pdo)
{ // AddDevice
PAGED_CODE();
KdPrint((DRIVERNAME " - Entering AddDevice: DriverObject %8.8lX, pdo %8.8lX\n", DriverObject, pdo));
       
 
NTSTATUS status=STATUS_SUCCESS;

// Create a function device object to represent the hardware we're managing.

PDEVICE_OBJECT fdo;

/*ULONG dxsize = (sizeof(DEVICE_EXTENSION) + 7) & ~7;
ULONG xsize = dxsize ; */

/*UNICODE_STRING numberstr;
RtlInitUnicodeString(&numberstr, L"XX");

RtlIntegerToUnicodeString(cardnumber, 0, &numberstr);  */

UNICODE_STRING devname;

switch (cardnumber) {
case 0: RtlInitUnicodeString(&devname, L"\\DosDevices\\lir940pci0");break;
case 1: RtlInitUnicodeString(&devname, L"\\DosDevices\\lir940pci1");break;
case 2: RtlInitUnicodeString(&devname, L"\\DosDevices\\lir940pci2");break;
case 3: RtlInitUnicodeString(&devname, L"\\DosDevices\\lir940pci3");
}
   
/*if (cardnumber)  RtlInitUnicodeString(&devname, L"\\DosDevices\\lir940pci1");
else RtlInitUnicodeString(&devname, L"\\DosDevices\\lir940pci0"); */

//RtlAppendUnicodeStringToString(&devname , &numberstr);
     

cardnumber++;
   

status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), &devname,
FILE_DEVICE_UNKNOWN, /*для 98*FILE_DEVICE_SECURE_OPEN*/ 0x00000100, FALSE, &fdo);
if (!NT_SUCCESS(status))
{ // can't create device object
KdPrint((DRIVERNAME " - IoCreateDevice failed - %X\n", status));
return status;
} // can't create device object

PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

// From this point forward, any error will have side effects that need to
// be cleaned up.

do
{ // finish initialization
pdx->DeviceObject = fdo;
pdx->Pdo = pdo;


fdo->Flags |= DO_BUFFERED_IO;



pdx->LowerDeviceObject = IoAttachDeviceToDeviceStack(fdo, pdo);
if (!pdx->LowerDeviceObject)
{ // can't attach
KdPrint((DRIVERNAME " - IoAttachDeviceToDeviceStack failed\n"));
status = 0xC00002B6L; // для 98 STATUS_DEVICE_REMOVED;
break;
} // can't attach



// Clear the "initializing" flag so that we can get IRPs

fdo->Flags &= ~DO_DEVICE_INITIALIZING;
} // finish initialization
while (FALSE);

if (!NT_SUCCESS(status))
{ // need to cleanup

KdPrint(("Mike ^  Error on Init "));
if (pdx->devname.Buffer)
RtlFreeUnicodeString(&pdx->devname);
if (pdx->LowerDeviceObject)
IoDetachDevice(pdx->LowerDeviceObject);
IoDeleteDevice(fdo);
} // need to cleanup
// if (NT_SUCCESS(status)) KdPrint(("MIke :  AddDevice  is OK "));

    KdPrint((DRIVERNAME " - ADD DEVICE before status  %X\n", status));
   
return status;
} // AddDevice



Код:
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;

// Identify the I/O resources we're supposed to use.

KdPrint(("Mike : Entry  Start Device "));




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", pdx->mem_start,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->portbase = (PUCHAR) portbase.QuadPart;
pdx->portaddr = portbase.LowPart;
KdPrint((DRIVERNAME " Mike   -  PortADDR  %0x  My  ", pdx->portaddr ));
KdPrint((DRIVERNAME " Mike   -  PortBASE  %0x  My  ", pdx->portbase ));






// ResetDevice(pdx); // reset the device

KdPrint((DRIVERNAME "STATUS = %X\n",status));


if (!NT_SUCCESS(status))
{
KdPrint((DRIVERNAME " - IoConnectInterrupt failed - %X\n", status));
if (pdx->portbase && pdx->mappedport)
MmUnmapIoSpace(pdx->portbase, pdx->nports);
pdx->portbase = NULL;
return status;
}

pdx->ismem_plata = !isport;


KdPrint((DRIVERNAME "Isport = %d\n",isport));


if (!isport)
{
pdx->mem_start = (PUCHAR) MmMapIoSpace(membase, pdx->mem_length, MmNonCached);
if (!pdx->mem_start) return STATUS_NO_MEMORY;
}


KdPrint((DRIVERNAME "The End Of StartDevice\n"));

// Initialize the device

// KeSynchronizeExecution(pdx->InterruptObject, (PKSYNCHRONIZE_ROUTINE) SetupDevice, pdx);

return status;
} // StartDevice


« Последнее редактирование: 29-05-2008 07:41 от MikePol » Записан
Ochkarik
Модератор

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

« Ответ #5 : 29-05-2008 09:17 » 

строка:
   for (ULONG i = 0; i < nres; ++i, ++resource)
- не с того индекса. или с того? ++i и ++resource как-то непривычно выглядели)))
обычно я i++ ...

   if (!(TRUE && gotport ))
- вообще не понял
про мапирование портов.. надо так:
    if (devExt->Port.MappedPort)
    {
   //RISC архитектура (порты отображаются в оперативную память)
   devExt->PortBaseAddr = (DWORD)
       MmMapIoSpace (devExt->Port.Start,
           devExt->Port.Length, //==4*4
           MmNonCached);
}

и что то с последовательностью напутано...
//   ResetDevice(pdx);         // reset the device
после чего MmMapIoSpace...

да, еще. что в отладочных сообщениях то в итоге? до куда все дошло то?
« Последнее редактирование: 29-05-2008 09:30 от Ochkarik » Записан

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

ru
Offline Offline

« Ответ #6 : 29-05-2008 09:49 » 

строка:
   for (ULONG i = 0; i < nres; ++i, ++resource)
- не с того индекса. или с того? ++i и ++resource как-то непривычно выглядели)))
обычно я i++ ...

Там только один ресурс - 8 байт порта ввода вывода. Но, почему то цикл выполняется 2 раза, то есть nres = 2.  Я сейчас всместо nres  единицу поставил в условии цикла .

Мапирование портов я не делаю. isport = 1 ВСЕГДА для этого устройства.

ResetDevice закоментирован, я просто не стал вырезать.
Вообще это "переработка" pci42 Oney. Была задача сделать быстро работоспособный драйвер. Поэтому редактировал пример, пока хоть как-то не заработало. Там много лишнего осталось, но убирать не стал - боялся что перестанет работать.

В отладочных сообщениях доходит до KdPrint((DRIVERNAME "The End Of StartDevice\n"));
Потом ничего не происходит несколько минут, потом система выдает сообщение о превышении времени ожидания и после этого приходит 15 пакетов в висте  и 4 в XP, которые я "скипаю" .
Проблема в том, что в XP все отлично работает, а в висте  - сообщение о превышении времени ожидания. 
Записан
Ochkarik
Модератор

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

« Ответ #7 : 29-05-2008 10:15 » 

pdx->portbase = (PUCHAR) portbase.QuadPart;
это вы к чему? что за указатель?

про мапирование - пардон ошибся... я думал это код для мапироавния портов IO для RISC. хотя вообще говоря мало ли...)


перед обработкой и звхватом ресурсов я делаю    
status = SendIrpSynchronously(Irp, devExt->LowerDevice);
и только после него проверяю ресурсы.

про
nres = 2
- проверьте что за тип второго ресурса там возвращается.

PS SendIrpSynchronously - это мой СallDevice(lover) и ожидание завершения нижележащим драйвером. вроде как вначале надо делать.
Записан

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

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

« Ответ #8 : 29-05-2008 10:21 » 

да,  IRP_MN_START_DEVICE:

This IRP must be handled first by the parent bus driver for a device and then by each higher driver in the device stack.
Записан

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

ru
Offline Offline

« Ответ #9 : 29-05-2008 12:06 » 

pdx->portbase = (PUCHAR) portbase.QuadPart;
это вы к чему? что за указатель?

Он не используется нигде , я удалил его вообще.


про
nres = 2
- проверьте что за тип второго ресурса там возвращается.

Тип ресурса - CmResourceTypeDevicePrivate

Если сначала вызывать IoCallDriver, то драйвер перезагружает XP, а в висте ничего не меняется. Опять через несколько минут ошибка времени ожидания .

Записан
Ochkarik
Модератор

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

« Ответ #10 : 29-05-2008 14:32 » 

CmResourceTypeDevicePrivate
 - его не надо обрабатывать.

Если сначала вызывать IoCallDriver, то драйвер перезагружает XP, а в висте ничего не меняется. Опять через несколько минут ошибка времени ожидания .
- значит что то еще не правильно. перезагружать не должно. посмотрите поиском по DDK\src\kernel\ любой пример - ВЕЗДЕ первым делом IRP_MN_START_DEVICE пересылается ниже и ТОЛЬКО ПОТОМ обрабатывается. это ТРЕБОВАНИЕ DDK.

покажите весь код обработки IRP_MN_START_DEVICE.

« Последнее редактирование: 29-05-2008 14:35 от Ochkarik » Записан

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

ru
Offline Offline

« Ответ #11 : 30-05-2008 03:45 » 

Странно, если бы это неправильно работало, то в и в XP и 98-м не работало. А тут только в Висте зависает.
Вообще я пример Oney переделывал, вряд ли я изменил порядок вызова IoCallDriver.

Код:
#pragma PAGEDCODE /// for Vista

NTSTATUS DispatchPnp(PDEVICE_OBJECT fdo, PIRP Irp)
{ // DispatchPnp
PAGED_CODE();
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

 
    PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
    ULONG fcn = stack->MinorFunction;
   

NTSTATUS status = STATUS_SUCCESS;

    KdPrint(("In PnP Dispatch IRP - %X",Irp));
switch (fcn) {
case  IRP_MN_START_DEVICE:

// IoCallDriver(pdx->LowerDeviceObject, Irp); /// XP перезагружается

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);
return CompleteRequest(Irp, status, Irp->Size);
break;
}
case  IRP_MN_REMOVE_DEVICE:
{
  KdPrint((" MIke : IRP_MN_STOP_DEVICE"));
          StopDevice(fdo,FALSE);
  RemoveDevice(fdo);
  return STATUS_SUCCESS;
  break;
}

default:
{
KdPrint(("IRP PNP BY DEFAULT "));
IoSkipCurrentIrpStackLocation(Irp);
             return IoCallDriver(pdx->LowerDeviceObject, Irp);
}
}
 
     
  }   
Записан
Ochkarik
Модератор

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

« Ответ #12 : 30-05-2008 10:38 » 

жесть... не ожидал такого от Ony...
то есть вы вообще нижележащий драйвер(драйвер шины) не вызываете?Не понял?
это не правильно. вообще не правильно.
что не появляется BSOD - вам повезло)

значит так.
когда к вам приходят IRP, вы должны не только обработать их сами, но и передать их дальше по стеку. (если в кратце)
в какой последовательности их обрабатывать - указано в DDK.
не передают IRP нижележащим драйверам только в двух случаях: либо драйвер шины(у него нет нижележащего), либо если вы завершаете его со статусом отличным от SUCCESS. да и то не всегда.

заначится так. перед проверкой ресурсов, неплохо бы пропустить IRP дальше. причем дождаться полной его обработки драйвером шины.
для этого необходимо вызвать такую функцию:
Код:
NTSTATUS 
SendIrpSynchronously( IN PIRP     Irp,
IN PDEVICE_OBJECT    LowerDevice)
{
DWORD status;
KEVENT event;
    KdPrint( (": SendIrpSynchronously\n"));
    KeInitializeEvent(  &event,
NotificationEvent,
FALSE);

    IoCopyCurrentIrpStackLocationToNext(Irp);

    IoSetCompletionRoutine( Irp,
    Sh01CompletionRoutine,
    &event,
    TRUE,TRUE,TRUE);

    status = IoCallDriver(LowerDevice, Irp);

    if (STATUS_PENDING == status)
    {
KeWaitForSingleObject(  &event,
Executive, // Waiting for reason of a driver
KernelMode, // Must be kernelmode if event memory is in stack
FALSE, // No allert
NULL); // No timeout
status = Irp->IoStatus.Status;
    };
    KdPrint( ("SendIrpSynchronously-exit\n"));
    return status;
}
NTSTATUS
Sh01CompletionRoutine( IN PDEVICE_OBJECT   DeviceObject,
IN PIRP             Irp,
IN PVOID            Context)
{
PKEVENT             event;
    KdPrint( (": CompletionRoutine\n"));

    event = (PKEVENT) Context;
    if (Irp->PendingReturned)
    {
        //по примеру XP - это не надо IoMarkIrpPending(Irp);
//по DDK2000 - 'это просто необходимо;)
       
        KeSetEvent(event, 0, FALSE);//по примеру XP оно здесь
    }
    //
    // We could switch on the major and minor functions of the IRP to perform
    // different functions, but we know that Context is an event that needs
    // to be set.
    //
    //KeSetEvent(event, 0, FALSE);//так было в 2000
    //
    // Allows the caller to reuse the IRP
    //
    KdPrint( (": CompletionRoutine-exit\n"));
    return STATUS_MORE_PROCESSING_REQUIRED;
}

в PNP делать так:
Код:
NTSTATUS		status;
PIO_STACK_LOCATION IOStack;
PDEVICE_EXTENSION_MY devExt;

    IOStack = IoGetCurrentIrpStackLocation(Irp);
    devExt = (PDEVICE_EXTENSION_MY)DeviceObject->DeviceExtension;
    switch (IOStack->MinorFunction)
    {
    case IRP_MN_START_DEVICE:
//-------------------------------------
status = SendIrpSynchronously(Irp, devExt->LowerDevice);
//->начало обработки IRP...............

if (NT_SUCCESS(status) && NT_SUCCESS(Irp->IoStatus.Status))
{
             ...............
             ВАША ОБРАБОТКА
}
else
{
    //в противном случае не стартовало...
            KdPrint( (": Call Lower Driver - faled?\n"));
            status = STATUS_UNSUCCESSFUL;
};
       break;
    case IRP_MN_REMOVE_DEVICE: //запрос на удаление драйвера возвращает ТОЛЬКО! STATUS_SUCCESS

        ...................
        ТУТ удаляем все ресурсы!!!!!!!!!!!!!!!!!!

        Irp->IoStatus.Status = STATUS_SUCCESS; //обязательно! остальные значения недопустимы!!!***
        status = SkipCurrIrpStack_CallLowerDriver(devExt->LowerDevice,Irp);

        IoDetachDevice( devExt->LowerDevice);
        IoDeleteDevice( DeviceObject ); //удаляем само устройство (!!! в том числе удаляется devExt!!!)

        status = STATUS_SUCCESS; //обязательно! остальные значения недопустимы!!!
        return status;//<<<<<<<<<<<<<------------------
    default: //данные запросы не определены, но я думаю,
//что в целях на всякий сучай необходимо предусмотреть их обработку*********
//впринципе такое возможно для более высокой версии WDM... может быть XP?
        // Pass down all the unhandled Irps.
        //
        status = SkipCurrIrpStack_CallLowerDriver(devExt->LowerDevice,Irp);
        IoReleaseRemoveLock(&devExt->RemoveLock, Irp);
        return status;
    };

    Irp->IoStatus.Status = status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);//вернул по примеру XP
    return status;
};


//пропуск IRP вниз по стеку и вызов нижележащего объекта устройства
Код:
// ***********************************************************************
DWORD __forceinline SkipCurrIrpStack_CallLowerDriver(PDEVICE_OBJECT LowerDevice, PIRP Irp)
{
        IoSkipCurrentIrpStackLocation (Irp);
        return IoCallDriver(LowerDevice, Irp);
};


PS вообще это не все что надо обрабатывать.... это какой то неправильный пример был. совсем не правильный...
во вложении - пример драйвера PCI устройства с поддержкой портов IO (одно окно) и прерыванием.
поддержаны READ|WRITE и IOCTL
впрочем там много чего напихано, а нужно лишь обработка PNP.
пример сделан на DriverStudio 3.2
примерно такой я брал за основу когда писал свои драйвера.


PPS на самом деле у меня еще больше запросов обрабатывается. и QweryRemove - все запросы и QweryStop и т.д.

* DevicePCI.zip (55.23 Кб - загружено 979 раз.)
« Последнее редактирование: 30-05-2008 11:00 от Ochkarik » Записан

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

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

« Ответ #13 : 30-05-2008 10:56 » 

да, а откуда пример брали? глянуть бы...
у ony был пример Generic с книжкой - там все правильно.
короче вы меня не пугайте))) у Oney - все правильно в примере PCI42!
там вызов ForwardAndWait функции в самом начале START_DEVICE.
раз уж лень изучать подробно - берите пример из DS который я вам кинул. думаю он должен заработать.
« Последнее редактирование: 30-05-2008 11:09 от Ochkarik » Записан

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

ru
Offline Offline

« Ответ #14 : 02-06-2008 12:21 » 

Ochkarik, большое спасибо за ваши советы.
На самом деле, мне хочется изучить это подробно.
Сейчас я добавил функцию ForwardAndWait  в DispatchPNP

Код:
 case  IRP_MN_START_DEVICE:


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);
return CompleteRequest(Irp, status, Irp->IoStatus.Information);
break;
Тестирую в ХР, система требует перезагрузки , то есть status, возвращаемый ForwardAndWait  - не STATUS_SUCCESS.
После перезагрузки драйвер нормально запускается. Правда, если его остановить, а потом запустить опять - требует перезагрузку.
В чем может быть причина "неправильного" статуса ?

ForwardAndWait

Код:
NTSTATUS OnRequestComplete(PDEVICE_OBJECT junk, PIRP Irp, PKEVENT pev)
{ // OnRequestComplete
KeSetEvent(pev, 0, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
} // OnRequestComplete


NTSTATUS ForwardAndWait(PDEVICE_EXTENSION pdx, PIRP Irp)
{ // ForwardAndWait
PAGED_CODE();

KEVENT event;
KeInitializeEvent(&event, NotificationEvent, FALSE);

IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) OnRequestComplete,
(PVOID) &event, TRUE, TRUE, TRUE);

IoCallDriver(pdx->LowerDeviceObject, Irp);
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
return Irp->IoStatus.Status;
} // ForwardAndWait

Записан
Ochkarik
Модератор

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

« Ответ #15 : 02-06-2008 13:16 » 

ForwardAndWait  - не при чем.

причина в том, что вы его не выгружаете целиком.
или в том, что забыли при остановке и выгрузке все заянтые ресурсы освободить.
скорее всего - первое.

при выгрузке вам помимо всего прочего придут
IRP_MN_QUERY_STOP_DEVICE потом IRP_MN_STOP_DEVICE (или IRP_MN_CANCEL_STOP_DEVICE).
по ним вы должны остановить и освободить ресурсы. - помоему это для перераспределения ресурсов.
PS (сорри эт я облажался - при выгрузке они помоему не приходят. но такие IRP тоже есть)

перед выгрузкой помоему эти:
так же бывают IRP_MN_QUERY_REMOVE_DEVICE потом IRP_MN_REMOVE_DEVICE (или IRP_MN_CANCEL_REMOVE_DEVICE)
они посылаются перед удалением драйвера для освобождения ресурсов.

есть еще IRP_MN_SURPRISE_REMOVAL - это обычно для шин с горячей заменой(USB/ExpressCard/PCMCIA и т.д.).
по  IRP_MN_REMOVE_DEVICE, кстати - еще и
IoDetachDevice(   devExt->LowerDevice);
IoDeleteDevice( DeviceObject ); //удаляем само устройство (!!! в том числе удаляется devExt!!!)
сделать надо.

ForwardAndWait  должна быть не только в START_DEVICE, но и остальных. но там надо смотреть по месту...
обычно в случае начала процесса (обработки чего либо, старта и т.д.) сначала IRP шлется ниже по стеку(ForwardAndWait), потом обрабатывается самим драйвером. идея в том, что любой челен стека может "провалить" IRP.
в случае "удаления" устройства(или отмены) - обычно наоборот(return IoCallDriver()), чтобы освободить все занятые ресурсы до того как начнет зачищать свои ресурсы нижележащий.


в общем посмотри еше раз пример Ony повнимательнее либо мой пример DevicePCI.zip.
в DDK опять же пишут - что и в какой последовательности делать.

« Последнее редактирование: 02-06-2008 13:18 от Ochkarik » Записан

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

ru
Offline Offline

« Ответ #16 : 04-06-2008 06:12 » 

Все сделал , как в примере pci42 у Они (по крайней мере мне так кажется).
В итоге в XP драйвер отлично запускается, останавливается, перезапускается. А в Висте зависает, причем не выводит некоторые отладочные сообщения.
Я обрабатываю только 2 Irp c IRP_MN_PNP:
1. IRP_MN_START_DEVICE
2. IRP_MN_REMOVE_DEVICE
Ну и в остальных случаях - спускаю по стеку вниз.

вот DispatchPnp:
Код:
NTSTATUS DispatchPnp(PDEVICE_OBJECT fdo, PIRP Irp)
{ // DispatchPnp
PAGED_CODE();
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

 
    PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
    ULONG fcn = stack->MinorFunction;
   

NTSTATUS status = STATUS_SUCCESS;

    KdPrint(("In PnP Dispatch IRP - %X\n",Irp));
switch (fcn) {
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);
return CompleteRequest(Irp, status, Irp->IoStatus.Information);
break;
}
case  IRP_MN_REMOVE_DEVICE:
{
  KdPrint((" MIke : IRP_MN_STOP_DEVICE"));
          StopDevice(fdo,FALSE);
  RemoveDevice(fdo);
  IoSkipCurrentIrpStackLocation(Irp);
          return IoCallDriver(pdx->LowerDeviceObject, Irp);
  break;
}

default:
{
KdPrint(("IRP PNP BY DEFAULT "));
IoSkipCurrentIrpStackLocation(Irp);
             return IoCallDriver(pdx->LowerDeviceObject, Irp);
}
}
   
     
  }

Вот ForwardAndWait:

Код:
NTSTATUS ForwardAndWait(PDEVICE_EXTENSION pdx, PIRP Irp)
{

// ForwardAndWait

KdPrint(("Before PAGED_CODE();\n"));
PAGED_CODE();

KdPrint(("BeforeKeInitializeEvent\n"));
KEVENT event;
KeInitializeEvent(&event, NotificationEvent, FALSE);

IoCopyCurrentIrpStackLocationToNext(Irp);

KdPrint(("Before IoSetCompletionRoutine\n"));
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) OnRequestComplete,
(PVOID) &event, TRUE, TRUE, TRUE);

KdPrint(("Before IoCallDriver\n"));
IoCallDriver(pdx->LowerDeviceObject, Irp);
KdPrint(("Before KeWaitForSingleObject\n"));
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);

KdPrint(("Forward and Wait Complete STATUS = %d\n", Irp->IoStatus.Status));


return Irp->IoStatus.Status;
} // ForwardAndWait


В ХР все отладочные сообщения выводятся.
В Висте - в DispatchPnp выводится только
 KdPrint(("In PnP Dispatch IRP - %X\n",Irp));
Дальше выводятся сообщения из StartDevice. То есть в Висте ни  KdPrint((DRIVERNAME "Enter in IRP_MN_START_DEVICE\n"));, ни одного сообщения из ForwardAndWait не выводятся, однако отображаются сообщения из StartDevice.

Читаю Они, пока не нашел ничего в чем может быть проблема. Собираю с помощью Windows Vista and Windows Server Longhorn x86 Checked Build Environment. В XP этот драйвер работает, а в самой Висте не хочет Жаль

Записан
Ochkarik
Модератор

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

« Ответ #17 : 04-06-2008 07:43 » new

поводу отладочных сообщений:
в XP был баг (в висте наверняка остался):
  при отладке, когда подряд следует много длинных отладочных сообщений, переполнялся системный буфер этих сообщений. в следствии чего, некоторые сообщения пропадали.
уменьшите длинну сообщений. и уберите не нужные.


CompleteRequest(Irp, status, Irp->IoStatus.Information);
- вот это, что за ерунда? вместо IoCompleteRequest(Irp, IO_NO_INCREMENT);?


далее, по IRP_MN_REMOVE_DEVICE, -  что за RemoveDevice()?
return IoCallDriver(pdx->LowerDeviceObject, Irp); - ересь!

я же привел пример кода. там указано то надо сделать и в какой последовательности.

в DDK глава есть:
найдите описание IRP_MN_REMOVE_DEVICE,
там ссылка "Handling an IRP_MN_REMOVE_DEVICE Request" а в ней, по ссылке "Removing a Device in a Function Driver ".
Записан

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

ru
Offline Offline

« Ответ #18 : 04-06-2008 10:14 » 

CompleteRequest это практически то же самое, что и IoCompleteRequest
Код:
#pragma LOCKEDCODE
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


RemoveDevice
Код:
#pragma PAGEDCODE

VOID RemoveDevice(IN PDEVICE_OBJECT fdo)
{ // RemoveDevice
PAGED_CODE();
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
NTSTATUS status;
   
RtlFreeUnicodeString(&pdx->devname);

if (pdx->LowerDeviceObject)
IoDetachDevice(pdx->LowerDeviceObject);

IoDeleteDevice(fdo);
} // RemoveDevice

Там вроде тоже самое выполняется, что и в Вашем примере.

Изменил порядок в IRP_MN_REMOVE:

Код:
	 case  IRP_MN_REMOVE_DEVICE:
{
  KdPrint((" MIke : IRP_MN_STOP_DEVICE"));
        //  StopDevice(fdo,FALSE);


  Irp->IoStatus.Status = STATUS_SUCCESS;

  IoSkipCurrentIrpStackLocation(Irp);
          IoCallDriver(pdx->LowerDeviceObject, Irp);

  RemoveDevice(fdo);

  return STATUS_SUCCESS;
  break;
}

Результат тот же. Виста подвисает и выдает сообщение о том , что истекло время ожидания. ХР работает отлично.
По поводу сообщений: сообщения не выводятся из "середины". То есть до определенного сообщения выводятся все и после все. А только те, которые в  case  IRP_MN_START_DEVICE: не выводятся.
Записан
Ochkarik
Модератор

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

« Ответ #19 : 04-06-2008 13:01 » 

вместо
        IoSkipCurrentIrpStackLocation(Irp);
          IoCallDriver(pdx->LowerDeviceObject, Irp);
надо:
ForwardAndWait()
впрочем не думаю что поможет...
буду думать.

да.
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines