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

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Проблема с чтением и записью в драйвере IEEE1394  (Прочитано 6153 раз)
0 Пользователей и 4 Гостей смотрят эту тему.
Treww
Гость
« : 16-01-2006 08:40 » 

Добрый день.

Вопрос по общению с драйвером IEEE1394.
Есть тепловизор NEC, для которого необходимо написать драйвер.
Буду рад всем, кто сталкивался с такой штукой и вообще работал с FireWire.

С драйверами я общаюсь второй раз, но потихоньку разобрался из чего они сотоят: Загрузка, выгрузка, PNP....
Общую структуру драйвера написал: он загружается, выгружается, взаимодействие с программками тоже работает. Даже получаю из шины разные параметры, количество сбросов и тд.
А загвоздка получилась, как только стал записывать в прибор.

Передаю драйверу шины запрос REQUEST_ASYNC_WRITE,
а он выдает статус STATUS_DEVICE_DATA_ERROR (0xC000009C) на любые данные из программы.

Я выделил два пространства для чтения и записи. Хотя одно используется для записи, а второе для чтения. Поставил на них функции оповещения.
Поставил оповещение на сброс шины. И перед работой с прибором получаю количество сбросов шины.
После попытки записи вызов функции оповещения не происходит.

Если кто может помочь, посмотрите пожалуйста код. Если увидите ошибку, подскажите где.

Заранее спасибо.

NTSTATUS DeviceIoControl( IN PDEVICE_OBJECT  DeviceObject, IN PIRP  Irp)
{
  PIO_STACK_LOCATION pio;
  PDEVICE_OBJECT dev;
  PDEVICE_EXTENTION pdx;
  NTSTATUS status=STATUS_SUCCESS;
  KEVENT event;
  ULONG Control;

  status=STATUS_SUCCESS;
  pdx=(PDEVICE_EXTENTION)DeviceObject->DeviceExtension;
  pio=IoGetCurrentIrpStackLocation(Irp);

  switch(pio->Parameters.DeviceIoControl.IoControlCode)
  {
  // выполнить команду
  case IOCTL_COMMAND:
    {
      status=GetGenerationCount(pdx);
      if(NT_SUCCESS(status))
        status=Command  (pdx,Irp);
      Irp->IoStatus.Status=status;
      IoCompleteRequest(Irp,IO_NO_INCREMENT);
      break;
    }
  default:
    {
      status=STATUS_INVALID_PARAMETER;
      break;
    }
  }
  return status;
}


NTSTATUS Command(PDEVICE_EXTENTION pdx,PIRP irp)
{
  IRB irb;
  NTSTATUS status;

  PNODE_DEVICE_EXTENSION node;
  KEVENT event;
  PIO_STACK_LOCATION pio;
  IO_STATUS_BLOCK ioStatus;
  PIRP irpNew=NULL;
  PMDL mdl=NULL;
  char* buf=NULL;
  int size=0;
  do
  {
   KdBreakPoint();

    pio=IoGetCurrentIrpStackLocation(irp);
    size=pio->Parameters.DeviceIoControl.InputBufferLength;
   
    // буфер для текста команд
    buf=ExAllocatePool(NonPagedPool,PAGE_SIZE);
    if(!buf)
    {
      status=STATUS_INSUFFICIENT_RESOURCES;
      break;
    }
   
    RtlZeroMemory(buf,PAGE_SIZE);
    RtlCopyMemory(buf,irp->AssociatedIrp.SystemBuffer,size);

    mdl=IoAllocateMdl(buf,size,FALSE,FALSE,NULL);
    MmBuildMdlForNonPagedPool(mdl);

    irb.FunctionNumber=REQUEST_ASYNC_WRITE;
    irb.u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_High=INITIAL_REGISTER_SPACE_HI;
    irb.u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low=INITIAL_REGISTER_SPACE_LO&0x800;
    irb.u.AsyncWrite.Mdl=mdl;
    irb.u.AsyncWrite.ulGeneration=pdx->gen_count;
    irb.u.AsyncWrite.nNumberOfBytesToWrite=size;
    irb.u.AsyncWrite.nBlockSize=0;
    irb.u.AsyncWrite.fulFlags=0;

    irpNew=IoBuildDeviceIoControlRequest(IOCTL_1394_CLASS,pdx->LowerDevice,NULL,NULL,NULL,0,TRUE,&event,&ioStatus);

    pio=IoGetNextIrpStackLocation(irpNew);
    pio->Parameters.Others.Argument1=&irb;
   
    KeInitializeEvent(&event,SynchronizationEvent,FALSE);
    status=IoCallDriver(pdx->LowerDevice,irpNew);
    if(status==STATUS_PENDING)
      KeWaitForSingleObject(&event,Executive,KernelMode,FALSE,NULL);

    status=ioStatus.Status;
    size=ioStatus.Information;
  }
  while(FALSE);

  if(mdl) ExFreeMdl(mdl);
  if(buf) ExFreePool(buf);

return status;
}
Записан
Ochkarik
Модератор

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

« Ответ #1 : 01-02-2006 10:13 » new

у меня так... в конечном драйвере вышло.
в целом похоже но...
Код:
NTSTATUS 
AsyncWriteCompletionRoutine( IN PDEVICE_OBJECT   DeviceObject,
IN PIRP             Irp,
IN PVOID            Context)
{
PKEVENT             event;
   
SOFT_ICE_DEBUG1;
    //KdPrint( ("Sh01d: AsyncWriteCompletionRoutine\n"));

    event = (PKEVENT) Context;
    if (Irp->PendingReturned)
    {
        KeSetEvent(event, IO_NO_INCREMENT, FALSE);//по примеру XP оно здесь
    }
    return STATUS_MORE_PROCESSING_REQUIRED;
    UNREFERENCED_PARAMETER(DeviceObject);
}

NTSTATUS
SH1394REC_AsyncWrite_TT(
    IN  PDEVICE_EXTENSION_MY    devExt, //!< device extension
    IN  DWORD                   Data,
    IN  ULONG                   NumberOfBytes,          //!< длинна запроса чтения/записи
    IN  ULONG                   OffsetLow              //!< адрес (младшая часть)
    )
{
PIRB        irb = 0;
PIRP        irp = 0;
PIO_STACK_LOCATION  irpStack;
DWORD   *lpBuffer = 0;
PMDL    mdlBuffer = 0;
DWORD   i;
NTSTATUS    status = STATUS_INSUFFICIENT_RESOURCES;
KEVENT event;

SOFT_ICE_DEBUG1;

    // Allocate an IRB
    do{
        irp = IoAllocateIrp(devExt->LowerDeviceObject->StackSize,FALSE);
        if (irp == NULL)
        {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }
       
        irb = (PIRB)ExAllocateFromNPagedLookasideList(&devExt->IrbList);
        if (irb == NULL)
        {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }


        lpBuffer = ExAllocatePool(NonPagedPool,NumberOfBytes);
        if (lpBuffer == NULL)
        {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }
        lpBuffer[0] = Data;
        mdlBuffer =
            IoAllocateMdl(  lpBuffer,
                            NumberOfBytes,
                            FALSE,
                            FALSE,
                            NULL);
        if (mdlBuffer == NULL)
        {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        MmBuildMdlForNonPagedPool(mdlBuffer);
        // Setup the IRB


        //RtlZeroMemory(irb, sizeof(IRB)); - только на < DISPATCH_LEVEL
        for(i=0;i<sizeof(IRB)>>2;i+=4)
            ((DWORD*)irb)[i]=0;

        irb->FunctionNumber = REQUEST_ASYNC_WRITE;
        irb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_High = CMD_1394OFFSET_HI;
        irb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low = OffsetLow;
        irb->u.AsyncWrite.nNumberOfBytesToWrite = NumberOfBytes;
        irb->u.AsyncWrite.Mdl = mdlBuffer;
        irb->u.AsyncWrite.ulGeneration = devExt->GenerationCount;
        //irb->u.AsyncWrite.fulFlags = ASYNC_FLAGS_NO_STATUS;//???
        //irb->u.AsyncWrite.DestinationAddress.IA_Destination_ID.NA_Bus_Number = LOCAL_BUS;
        //irb->u.AsyncWrite.DestinationAddress.IA_Destination_ID.NA_Node_Number = 0;

        //irpStack = IoGetCurrentIrpStackLocation(irp);
        irpStack = IoGetNextIrpStackLocation(irp);
        irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
        irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
        irpStack->Parameters.Others.Argument1 = irb;

        //запись в драйвер шины 1394
// status = SendIrpSynchronously(irp,devExt->LowerDeviceObject);       
        KeInitializeEvent(  &event,
    NotificationEvent,
    FALSE);

        IoSetCompletionRoutine(irp,AsyncWriteCompletionRoutine,&event,TRUE,TRUE,TRUE);

        //KdPrint( ("Sh01d: Send command!\n"));


        status = IoCallDriver(devExt->LowerDeviceObject, irp);
        if (STATUS_PENDING == status)
        {
            //KdPrint( ("Sh01d: IoCallDriver - STATUS_PENDING...\n"));
        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
            //KdPrint( ("Sh01d: KeWaitForSingleObject - ok...\n"));
        status = irp->IoStatus.Status;
        };
        status = irp->IoStatus.Status;



       
    } while (FALSE);

    //в случае ошибок освобождаем все что нахватали из ресурсов:
    if (irp != NULL)
        IoFreeIrp(irp);

    if (irb != NULL)
        ExFreeToNPagedLookasideList(&devExt->IrbList,irb);
   
    if (mdlBuffer != NULL)
        IoFreeMdl(mdlBuffer);
   
    if (lpBuffer != NULL)
        ExFreePool(lpBuffer);

    return status;
}
Записан

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

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

« Ответ #2 : 01-02-2006 10:17 » 

и второй вариант из первых попыток, практически нумеговский код.
извините, в вашем коде на первый взгляд ничего плохого не нашел а разбираться увы - со временем напряженка...
возможно STATUS_DEVICE_DATA_ERROR (0xC000009C) может выдаваться если устройство не подтверждает запись в этот регион... адреса правильно указаны? к сожалению более точно уже не помю... забыл уже) попробуйте по ДДК посмотреть что где может возвращатся... на "асинк-врайт".

///////////////////////////////////////////////////////////////////////////////////////////////////
//  Test1394PC1SubmitIrb
//      method to asynchronously submit an IRB to the bus driver.
//!Функция отправляет текущий IRP, нижнему драйверу через его IRP_MJ_INTERNAL_DEVICE_CONTROL.
//!по окончании обработки IRP вызывается:
//!     CompletionRoutine(IN  PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN  PVOID Context)
NTSTATUS
Test1394PC1SubmitIrb(
    IN  PDEVICE_OBJECT              DeviceObject,       //!>device object
    IN  PIRB                        Irb,                //!>IRB для запроса
    IN  PIRP                        Irp,                //!>текущий IRP
    IN  PIO_COMPLETION_ROUTINE      CompletionRoutine,  //!>функция завершения запроса IRP (completion routine)
    IN  PVOID                       Context)            //!>конеткст вызова функции завершения (completion routine)
{
    NTSTATUS            status;
    IO_STATUS_BLOCK     ioStatus;
    KEVENT              event;
    PIO_STACK_LOCATION  irpStack;

    Test1394PC1DebugPrint(DBG_IO, DBG_INFO, __FUNCTION__"++");

    // Get the next IRP stack location
    irpStack = IoGetNextIrpStackLocation(Irp);

    // Use internal device control even though
    // some DDK documentation may state otherwise
    irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;

    // Set the control code
    irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;

    // Set up the parameters for the IRP
    irpStack->Parameters.Others.Argument1 = Irb;

    // Set our completion routine in the IRP
    IoSetCompletionRoutine(Irp,CompletionRoutine,Context,TRUE,TRUE,TRUE);

    // Send it down
    status = IoCallDriver(DeviceObject, Irp);

    Test1394PC1DebugPrint(DBG_IO, DBG_INFO, __FUNCTION__"--. STATUS %x", status);

    return status;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//  Test1394PC1_DeviceAccess
//      Sends or receives data on the 1394 bus using asynchronous read or
//      write transfers, using a completion routine
//  Arguments:
//      IN  DeviceExtension
//              Our device extension
//      IN  OriginalRequest
//              IRP to send to completion routine
//      IN  OffsetHigh
//              Destination address high part
//      IN  OffsetLow
//              Destination address low part
//      IN  Mdl
//              Transfer data buffer
//      IN  NumberOfBytes
//              Number of data bytes to transfer
//      IN  bWrite
//              Flag to indicate transfer direction
//      IN  bRawMode
//              Flag to indicate whether to send the request to the bus driver or the port driver.
//      IN  Node
//              Node number to read/write from/to, set to MAX_LOCAL_NODES to let the bus route the transfer.
//  Return Value:
//      If a failure status is returned, then the completion routine
//      will not be called.  STATUS_PENDING is a successful return.
//
//! Функция четния/записи адресного пространства устройства 1394.
//! Функция размещает IRP для драйвера шины 1394, размещает ioContext,
//! и посылает запрос с CompletionRoutine, которая будет вызвана по завершению операции.
//! возвращает STATUS_PENDING при успешном вызове (или STATUS_INSUFFICIENT_RESOURCES)
//! Если возвращен не STATUS_PENDING - функция завершения не будет вызвана.
//! текущий запрос помечается IoMarkIrpPending(OriginalRequest)
NTSTATUS
Test1394PC1_DeviceAccess(
    IN  PTEST1394PC1_DEVICE_EXTENSION  DeviceExtension, //!< device extension
    IN  PIRP                    OriginalRequest,        //!< инициирующий IRP
    IN  ULONG                   NumberOfBytes,          //!< длинна запроса чтения/записи
    IN  USHORT                  OffsetHigh,             //!< адрес (старшая часть)
    IN  ULONG                   OffsetLow,              //!< адрес (младшая часть)   
    IN  PMDL                    Mdl,                    //!< MDL куда писать при чтении(откуда читать при записи)
    IN  BOOLEAN                 bWrite,                 //!< Запись(чтение)
    IN  BOOLEAN                 bRawMode,               //!< запись в порт (минуя драйвер шины 1394)
    IN  USHORT                  Node                    //!< номер устройства 1394 на локальной шине, если запись в порт  или MAX_LOCAL_NODES - если запсись в драйвер шины
    )
{
PTEST1394PC1_IO_CONTEXT ioContext;
ULONG                       length;
PIRP                        irp;
PIRB                        irb;
NTSTATUS                    status;

    do{
        ASSERT(Mdl != NULL);

        // allocate io context to pass to completion routine
        ioContext = (PTEST1394PC1_IO_CONTEXT)ExAllocatePool(NonPagedPool, sizeof(TEST1394PC1_IO_CONTEXT));

        if (ioContext == NULL)
        {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        irp = IoAllocateIrp(DeviceExtension->LowerDeviceObject->StackSize,FALSE);

        if (irp == NULL)
        {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        // Allocate an IRB
        irb = (PIRB)ExAllocateFromNPagedLookasideList(&DeviceExtension->IrbList);
        if (irb == NULL)
        {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        // Mark the original IRP pending
        IoMarkIrpPending(OriginalRequest);

        // Setup the IRB
        RtlZeroMemory(irb, sizeof(IRB));

        if (bWrite)
        {
            irb->FunctionNumber = REQUEST_ASYNC_WRITE;

            irb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_High = OffsetHigh;
            irb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low = OffsetLow;
            irb->u.AsyncWrite.nNumberOfBytesToWrite = NumberOfBytes;
            irb->u.AsyncWrite.Mdl = Mdl;
            irb->u.AsyncWrite.ulGeneration = DeviceExtension->GenerationCount;
            if (Node < MAX_LOCAL_NODES)
            {
                irb->u.AsyncWrite.DestinationAddress.IA_Destination_ID.NA_Bus_Number = LOCAL_BUS;
                irb->u.AsyncWrite.DestinationAddress.IA_Destination_ID.NA_Node_Number = Node;
            }
        }
        else
        {
            irb->FunctionNumber = REQUEST_ASYNC_READ;

            irb->u.AsyncRead.DestinationAddress.IA_Destination_Offset.Off_High = OffsetHigh;
            irb->u.AsyncRead.DestinationAddress.IA_Destination_Offset.Off_Low = OffsetLow;
            irb->u.AsyncRead.nNumberOfBytesToRead = NumberOfBytes;
            irb->u.AsyncRead.Mdl = Mdl;
            irb->u.AsyncRead.ulGeneration = DeviceExtension->GenerationCount;
            if (Node < MAX_LOCAL_NODES)
            {
                irb->u.AsyncRead.DestinationAddress.IA_Destination_ID.NA_Bus_Number = LOCAL_BUS;
                irb->u.AsyncRead.DestinationAddress.IA_Destination_ID.NA_Node_Number = Node;
            }
        }

        // Setup the context
        ioContext->DeviceExtension = DeviceExtension;
        ioContext->Irp = irp;
        ioContext->Irb = irb;
        ioContext->Mdl = Mdl;
        ioContext->NumberOfBytes = NumberOfBytes;
        ioContext->OriginalRequest = OriginalRequest;

        // Send it down
        if (bRawMode)
            Test1394PC1SubmitIrb(
                DeviceExtension->PortDeviceObject,
                ioContext->Irb,
                ioContext->Irp,
                Test1394PC1_AccessCompletionRoutine,
                ioContext);
        else
            Test1394PC1SubmitIrb(
                DeviceExtension->LowerDeviceObject,
                ioContext->Irb,
                ioContext->Irp,
                Test1394PC1_AccessCompletionRoutine,
                ioContext);

        status = STATUS_PENDING;
    } while (FALSE);

    if (!NT_SUCCESS(status))
    {
        //в случае ошибок освобождаем все что нахватали из ресурсов:
        // Free our allocated IRP
        if (irp != NULL)
            IoFreeIrp(irp);

        // Free our allocated IRB memory
        if (irb != NULL)
            ExFreeToNPagedLookasideList(&DeviceExtension->IrbList,irb);

        // Free our allocated context
        if (ioContext != NULL)
            ExFreePool(ioContext);
    }

    return status;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
//  Test1394PC1_AccessCompletionRoutine
//      Completion routine for asynchronous transfer.
//! Функция вызывается по завершению запроса Test1394PC1Access0RDeviceAccess
//! Устанавливает статус выполнения операции запроса IRP,
//! указывает число скопированных данных, освобождает ресурсы запроса и завершает исходный IRP.
NTSTATUS
Test1394PC1_AccessCompletionRoutine(
    IN  PDEVICE_OBJECT  DeviceObject,
    IN  PIRP            Irp,
    IN  PVOID           Context
    )
{
PTEST1394PC1_IO_CONTEXT     ioContext;
NTSTATUS                    status;
PIRP                        originalIrp;
PTEST1394PC1_DEVICE_EXTENSION deviceExtension;

    // Get our completion context
    ioContext = (PTEST1394PC1_IO_CONTEXT)Context;

    // Get the status of the async request
    status = Irp->IoStatus.Status;

    Test1394PC1DebugPrint(DBG_IO, DBG_TRACE, __FUNCTION__"++. IRP %p STATUS %x", Irp, status);

    // Get the IRP from the async request
    originalIrp = ioContext->OriginalRequest;

    // Get our device extension
    deviceExtension = ioContext->DeviceExtension;

    if (originalIrp)
    {
        originalIrp->IoStatus.Status = Irp->IoStatus.Status;
        if (NT_SUCCESS(Irp->IoStatus.Status))
        {
            originalIrp->IoStatus.Information = ioContext->NumberOfBytes;
        }
    }

    // Free our allocated IRB memory
    ExFreeToNPagedLookasideList(&deviceExtension->IrbList,ioContext->Irb);

    // Free our allocate IRP
    IoFreeIrp(ioContext->Irp);

    // Free our allocated context
    ExFreePool(ioContext);

    if (originalIrp)
    {
        // Complete the original request
        IoCompleteRequest(originalIrp, IO_NO_INCREMENT);
        Test1394PC1DecrementIoCount(&deviceExtension->IoLock);
    }

    Test1394PC1DebugPrint(DBG_IO, DBG_TRACE, __FUNCTION__"--");

    return STATUS_MORE_PROCESSING_REQUIRED;
}
« Последнее редактирование: 01-02-2006 10:25 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Treww
Гость
« Ответ #3 : 02-02-2006 06:18 » 

Добрый день.

Ошибка оказалась глупой. Еще раз взглянул на свой код и сразу все увидел и понял.

Не верная бинарная функция вместо or использовал and. В результате чего адрес сбрасывался в ноль.

Исправлен всего один сивол & -> |:

irb.u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low=INITIAL_REGISTER_SPACE_LO|0x800;

После этого приборчик стал приятно урчать. Улыбаюсь

Спасибо всем.
Улыбаюсь

Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines