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

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

ua
Offline Offline

« Ответ #30 : 19-04-2012 08:21 » 

Ochkarik, Вы как всегда на высоте! Спасибо! )))
вместа MmMapLockedPages() использую MmMapLockedPagesSpecifyCache() с параметром UserMode...
Цитата
передать физ адрес - через порты m_IoPortRange0 у вас вроде было написано.
да, это понятно, научился делать, маленькая загвоздка в регистр физический адрес передается как ULONG, а у меня физический адрес PHYSICAL_ADDRESS  - структура иммет LowPart и HighPart, какие из этих параметров передавать?

Вы наверное не знаете чем заменить m_MemoryRange0.ind(pArgs->ByteOffset, pOutBuffer, pArgs->DwordCount), я подозреваю, что READ_REGISTER_BUFFER_ULONG()?
« Последнее редактирование: 19-04-2012 08:33 от sabbatazh » Записан
Ochkarik
Модератор

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

« Ответ #31 : 19-04-2012 08:55 » 

можно и так.
физический адрес: если у вас плата не поддерживает x64, то отдаете ей только LowPart.
подозреваю что да, чтение из платы в pOutBuffer, который из IRP, который они сначала мапируют в системное адресное пространство (не понял только зачем) .
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
sabbatazh
Помогающий

ua
Offline Offline

« Ответ #32 : 19-04-2012 11:52 » 

Спасибо! Воспользовавшись Вашими советами переписал процедуру numega:
Код: (C)
NTSTATUS MDMAIDevice::MDMAI_MEM_READ_Handler(KIrp I)
{
        NTSTATUS status = STATUS_SUCCESS;
        KMemory* Mem;
        Mem = new (NonPagedPool) KMemory(I.Mdl());
        ULONG* pOutBuffer = (ULONG*)Mem->MapToSystemSpace();
        XDSP_READ_WRITE_MEMORY_ARGS* pArgs = (XDSP_READ_WRITE_MEMORY_ARGS*)I.IoctlBuffer();

        m_MemoryRange0.ind(pArgs->ByteOffset, pOutBuffer, pArgs->DwordCount);

        I.Information() = 0;

        return status;
}
под WDM, использую для выделения буфера ExAllocatePool():
Код: (C++)
case  MDMAI_MEM_READ://IOCTL_READ_IMAGE:
                {
                        if (cbin < sizeof(XDSP_READ_WRITE_MEMORY_ARGS*))
                                         {
                                                status = STATUS_INVALID_PARAMETER;
                                                break;
                                         }

                                        XDSP_READ_WRITE_MEMORY_ARGS* p = (XDSP_READ_WRITE_MEMORY_ARGS*)Irp->AssociatedIrp.SystemBuffer;
                                                        KdPrint((DRIVERNAME " — Size of XDSP_READ_WRITE_MEMORY_ARGS = %d \n", sizeof(XDSP_READ_WRITE_MEMORY_ARGS)));

                                if (p!=NULL)
                                {
                                        PULONG buff = (PULONG)ExAllocatePool(NonPagedPool,cbout);

                                        ULONG offset = p->ByteOffset;                                          
                                                        KdPrint((DRIVERNAME " — Device on real addrr %I32x, offset = %I32x \n",pdx->portaddr, offset));

                                        READ_PORT_BUFFER_ULONG((PULONG)(pdx->portaddr+offset), buff, p->DwordCount);

                                        info = sizeof(buff);
                                                        KdPrint((DRIVERNAME " — Size of DATA = %d \n", info));

                                                PVOID pInputBuffer  = Irp->AssociatedIrp.SystemBuffer;
                                                PVOID pOutputBuffer = NULL;
                                               
                                                        if(Irp->MdlAddress)
                                                                {
                                                                        pOutputBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
                                                                }
                                               
                                                        if(pInputBuffer && pOutputBuffer)
                                                                {                                                                      
                                                                                KdPrint((DRIVERNAME " - %i >= %i", cbout, info));
                                                                        if(cbout >= info)
                                                                        {
                                                                                RtlCopyMemory(pOutputBuffer, buff, info);

                                                                                  status = STATUS_SUCCESS;
                                                                        }else status = STATUS_BUFFER_TOO_SMALL;
                                                                }
                                                  //status = STATUS_SUCCESS;
                                        ExFreePool(buff);
                                }else status = STATUS_INVALID_PARAMETER;
                        break;
                }
и получилось очень много строк!)))
« Последнее редактирование: 19-04-2012 12:01 от sabbatazh » Записан
Ochkarik
Модератор

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

« Ответ #33 : 19-04-2012 13:08 » 

1. проверка. в драйвер по  IOCTL передается структура а вы проверяете на размер указателя на нее. это не верно)
2. буфер выделяется в приложении, по-моему, а не создается новый. зачем вам второй буфер и второе копирование?
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
sabbatazh
Помогающий

ua
Offline Offline

« Ответ #34 : 19-04-2012 14:46 » 

1. проверка. в драйвер по  IOCTL передается структура а вы проверяете на размер указателя на нее. это не верно)
2. буфер выделяется в приложении, по-моему, а не создается новый. зачем вам второй буфер и второе копирование?
я не понял!((( Вас не затруднит подробнее объяснить! Спасибо!
Записан
Ochkarik
Модератор

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

« Ответ #35 : 19-04-2012 16:24 » 

if (cbin < sizeof(XDSP_READ_WRITE_MEMORY_ARGS*))
sizeof(XDSP_READ_WRITE_MEMORY_ARGS*) - размер указателя а не структуры.

2.
        Mem = new (NonPagedPool) KMemory(I.Mdl());
        ULONG* pOutBuffer = (ULONG*)Mem->MapToSystemSpace();
видимо (скорее всего!) не выделяет собственно память, а только получает указатель на уже выделенную память, из входного IRP, описанную через дескриптор MDL.
просто мапирует в системное адресное драйверу.




Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
sabbatazh
Помогающий

ua
Offline Offline

« Ответ #36 : 19-04-2012 16:31 » 

Ochkarik, Спасибо!!!
Столкнулся с проблемой синего экрана, при попытке прочитать LowPart ( PHYSICAL_ADDRESS) ДМА :
Код: (C++)
PHYSICAL_ADDRESS DmaPhysAddr1;

...
 m_DmaBuffer1 = pdx->DMAAdapter->DmaOperations->AllocateCommonBuffer(
                                           pdx->DMAAdapter, ROUND_TO_PAGES(MAX_DMA_LENGTH), &DmaPhysAddr1, FALSE);

if ((!m_DmaBuffer1))
                        {  
                                        KdPrint(("Failed to allocate DMA buffer\n"));
                                return STATUS_INSUFFICIENT_RESOURCES;
                        }
...//проходит проверку!

ULONG DMABufferPhysPtr1 = DmaPhysAddr1.LowPart; <- синий экран!!!
точно эта строка ULONG DMABufferPhysPtr1 = DmaPhysAddr1.LowPart; приводит к критической ошибке (проверил несколько раз)!
что за чудеса??? (((
« Последнее редактирование: 19-04-2012 16:39 от sabbatazh » Записан
Ochkarik
Модератор

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

« Ответ #37 : 19-04-2012 18:35 » 

 Не может быть...
быть не может... это физически невозможно)
но ошибка точно не в ней. ищите в другом месте...
иногда ошибки проявляются в BSOD позже того места где они возникают)
« Последнее редактирование: 19-04-2012 18:45 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
sabbatazh
Помогающий

ua
Offline Offline

« Ответ #38 : 21-04-2012 14:09 » 

Ochkarik,  нашел в чем ошибка!
я не правильно объявлял структуру XDSP_DMA_BUFFER_PTRS, а именно переменную pBuffer, у меня в WDM :
Код: (C++)
XDSP_DMA_BUFFER_PTRS* pBuffer = (XDSP_DMA_BUFFER_PTRS*)Irp->AssociatedIrp.SystemBuffer;
if (pBuffer!=NULL) pBuffer->DMABufferPhysPtr1 = DmaPhysAddr1.LowPart; <- синий экран!!!
а в nuMega драйвере через память:
Код: (C)
NTSTATUS status = STATUS_SUCCESS;
        HANDLE hEvent = *(HANDLE*)I.IoctlBuffer();                      // Get user event handle from inStream
        KMemory Mem(I.Mdl());                                                           // Create KMemory based on outStream(addr ptr of user buf)
//      PVOID* pBuffer = (PVOID*)Mem.MapToSystemSpace();        // Map to system pBuffer
        XDSP_DMA_BUFFER_PTRS* pBuffer = (XDSP_DMA_BUFFER_PTRS*)Mem.MapToSystemSpace();
pBuffer->DMABufferPhysPtr1 = DmaPhysAddr1;
и соответственно у nuMega все работает, а у меня даже  pBuffer->DMABufferPhysPtr1 = 0; на синий экран уводит...
Вы мне писали, но я сделал не так!
Цитата
Mem = new (NonPagedPool) KMemory(I.Mdl());
        ULONG* pOutBuffer = (ULONG*)Mem->MapToSystemSpace();
видимо (скорее всего!) не выделяет собственно память, а только получает указатель на уже выделенную память, из входного IRP, описанную через дескриптор MDL.
просто мапирует в системное адресное драйверу.
сдела через ExAllocatePool()
Код: (C++)
XDSP_DMA_BUFFER_PTRS* pBuffer = (XDSP_DMA_BUFFER_PTRS*)ExAllocatePool(NonPagedPool,cbout);
if (pBuffer!=NULL) pBuffer->DMABufferPhysPtr1 = DmaPhysAddr1.LowPart;
//...
ExFreePool(pBuffer);
без синего экрана!)))  так правильно объявить pBuffer Не понял ))) я доволен!)))
Спасибо Вам!!!

Добавлено через 2 часа и 48 секунд:
Отказывается выделять память больше чем 1м!((((
« Последнее редактирование: 21-04-2012 16:55 от sabbatazh » Записан
Ochkarik
Модератор

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

« Ответ #39 : 21-04-2012 22:18 » 

NonPagedPool - это не тот ресурс которым можно так в легкую разбрасываться. в системе на него ограничения)

Добавлено через 11 минут и 55 секунд:
а кроме того... ну это ересь - выделять буфер чтобы его тут же убить. копируйте напрямую.
PS да, выделили память - проверили что выделилось. это у вас есть.
а вот ExFreePool судя по куску кода - вызовется и обоих случаях. это не очень правильно) привыкайте писать аккуратнее - будет меньше BSODов)
« Последнее редактирование: 21-04-2012 22:30 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
sabbatazh
Помогающий

ua
Offline Offline

« Ответ #40 : 22-04-2012 13:07 » 

Ochkarik, Спасибо!!! Очень помогли!
Обнаружил, что 64М память выделяется после установки драйвера и перезагрузки системы, и драйвер переставляю скока угодно, память выделяется... с чем это может быть связано??


Добавлено через 32 минуты и 17 секунд:
ДУмаю уже последний мой вопрос по этой теме!)  Здесь была моя ладья...
ВЫлетает синий экран после закрытия приложения работающего с драйвером (ну тут думаю разберусь), вызывается функция:
1)!!!
Код: (C++)
DriverObject->MajorFunction[IRP_MJ_CLOSE]                       = MDMAICreateClose;
//..
NTSTATUS MDMAICreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
                DbgPrint("Enter from MDMAICreateClose!\n");    
       
        PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
        PMDMAI_DEVICE_EXTENSION deviceExtension  = (PMDMAI_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
               
    Irp->IoStatus.Status = STATUS_SUCCESS;
   
    if(irpStack->MajorFunction == IRP_MJ_CREATE){

       // status = STATUS_UNSUCCESSFUL;
    }

        if(irpStack->MajorFunction == IRP_MJ_CLOSE){

                ResetDevice(deviceExtension);
    }
   
         Irp->IoStatus.Information = 0;
         IoCompleteRequest(Irp, IO_NO_INCREMENT);

        return (STATUS_SUCCESS);
}
может необходимо что-то подчистить еще...?? но вроде все хоршо... на ум приходит, дополнить удаление прерывания if (pExt->InterruptObject) IoDisconnectInterrupt( pExt->InterruptObject ); , я объект его создаю в MDMAI_DMA_SETUP : status = IoConnectInterrupt( &pdx->InterruptObject, (PKSERVICE_ROUTINE)OnInterrupt, (PVOID)pdx, NULL, pdx->InterruptVector, pdx->InterruptIrql, pdx->InterruptIrql, pdx->InterruptMode, TRUE, pdx->InterruptAffinity, FALSE ); ... попробывал получил синий экран...
 
2)!!!
и когда удаляю драйвер:
Код: (C++)
case IRP_MN_REMOVE_DEVICE:              //запрос на удаление драйвера возвращает ТОЛЬКО! STATUS_SUCCESS
                 KdPrint(("Enter in IRP_MN_REMOVE_DEVICE\n"));
                       
                    MDMAIDmaAdapterFree(pExt);

                        if (pExt->state == TRUE) {
                                // Woah!  we still have an interrupt object out there!
                                // Delete our Interrupt object
                                //if (pExt->InterruptObject) IoDisconnectInterrupt( pExt->InterruptObject );
                                        pExt->state = FALSE;}

                        //status = MDMAIForwardIrpSynchronous(DeviceObject, Irp);              
                        IoDeleteSymbolicLink(&(UNICODE_STRING)pExt->ustrSymLinkName);
                        Irp->IoStatus.Status = STATUS_SUCCESS;
                        IoCompleteRequest(Irp, IO_NO_INCREMENT);
                        IoDetachDevice(pExt->TargetDeviceObject);
                        IoDeleteDevice(pExt->DeviceObject);
                 KdPrint(("Leave RemoveDevice\n"));
                 return STATUS_SUCCESS;
думаю, что все дело в MDMAIDmaAdapterFree(pExt) :
Код: (C++)
NTSTATUS MDMAIDmaAdapterFree(PMDMAI_DEVICE_EXTENSION pdx)
{      
                        KdPrint((DRIVERNAME " - Releasing DMA Adapter object...\n"));  
 
                if ((DmaVirtualAddr1!=NULL) && (DmaVirtualAddr2!=NULL) && (DmaVirtualAddr3!=NULL) && (DmaVirtualAddr3!=NULL))
                        {      
                                //MmUnmapLockedPages(DmaVirtualAddr0, pMdlBuffData);                   
                                        DmaVirtualAddr1 = NULL;
                                        DmaVirtualAddr2 = NULL;
                                        DmaVirtualAddr3 = NULL;
                                        DmaVirtualAddr4 = NULL;

                                if (DmaBufferMemory1 != NULL) IoFreeMdl(DmaBufferMemory1);
                                if (DmaBufferMemory2 != NULL) IoFreeMdl(DmaBufferMemory2);
                                if (DmaBufferMemory3 != NULL) IoFreeMdl(DmaBufferMemory3);
                                if (DmaBufferMemory4 != NULL) IoFreeMdl(DmaBufferMemory4);
                        }                              
               
                // Verify DMA Adapter was created
                if (pdx->DMAAdapter == NULL)
                        {
                                KdPrint(("ERROR - DMA Adapter object doesn't exist, unable to free object\n"));
                                return STATUS_RESOURCE_TYPE_NOT_FOUND;
                        }

                if ((!m_DmaBuffer1)&&(!m_DmaBuffer2)&&(!m_DmaBuffer3)&&(!m_DmaBuffer4))
                        {  
                                        KdPrint(("Failed to allocate DMA buffer\n"));
                                return STATUS_INSUFFICIENT_RESOURCES;
                        }

                // Release the buffer  
                pdx->DMAAdapter->DmaOperations->FreeCommonBuffer(pdx->DMAAdapter, ROUND_TO_PAGES(MAX_DMA_LENGTH), DmaPhysAddr1, m_DmaBuffer1, FALSE);//ROUND_TO_PAGES(MAX_DMA_LENGTH)
                pdx->DMAAdapter->DmaOperations->FreeCommonBuffer(pdx->DMAAdapter, ROUND_TO_PAGES(MAX_DMA_LENGTH), DmaPhysAddr2, m_DmaBuffer2, FALSE);
                pdx->DMAAdapter->DmaOperations->FreeCommonBuffer(pdx->DMAAdapter, ROUND_TO_PAGES(MAX_DMA_LENGTH), DmaPhysAddr3, m_DmaBuffer3, FALSE);
                pdx->DMAAdapter->DmaOperations->FreeCommonBuffer(pdx->DMAAdapter, ROUND_TO_PAGES(MAX_DMA_LENGTH), DmaPhysAddr4, m_DmaBuffer4, FALSE);
       
                // Clear memory object properties  
                if (m_DmaBuffer1 != NULL) m_DmaBuffer1 = NULL; //RtlZeroMemory(h0_BuffData, sizeof(h0_BuffData));
                if (m_DmaBuffer2 != NULL) m_DmaBuffer2 = NULL;
                if (m_DmaBuffer3 != NULL) m_DmaBuffer3 = NULL;
                if (m_DmaBuffer4 != NULL) m_DmaBuffer4 = NULL;         

                // Delete the DMA Adapter
                (*pdx->DMAAdapter->DmaOperations->PutDmaAdapter)(pdx->DMAAdapter);

                // DMA adapter object deleted, no longer available
                pdx->DMAAdapter = NULL;
                       
                                KdPrint((DRIVERNAME " - Releasing DMA Adapter object... OK!!!\n"));
       
    return STATUS_SUCCESS;
}
от теперь и не приложу ума где ошибка !!! в одном месте устраняю, а в другом появляется! С ума сойти...
« Последнее редактирование: 22-04-2012 13:39 от sabbatazh » Записан
Ochkarik
Модератор

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

« Ответ #41 : 22-04-2012 14:45 » 

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

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

PPS не забывать что IRP могут обрабатываться параллельно. то бишь надо думать о синхронизации потоков и использовать атомарные или потокобезопасные методы.

Добавлено через 1 минуту и 53 секунды:
PPPS по поводу 64м - это DMA? или nonpagedpool?
фрагментация наверное... а вообще 64м... вам действительно такой объем нужен? или вы перестраховываетесь?
« Последнее редактирование: 22-04-2012 14:50 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
sabbatazh
Помогающий

ua
Offline Offline

« Ответ #42 : 23-04-2012 11:18 » 

Спасибо!!! Буду пробовать!
Цитата
не забывать что IRP могут обрабатываться параллельно. то бишь надо думать о синхронизации потоков и использовать атомарные или потокобезопасные методы.
- это как? типа ткаго:
Код: (C++)
NTSTATUS MDMAIForwardIrpSynchronous(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
        PMDMAI_DEVICE_EXTENSION   deviceExtension;
        KEVENT event;
        NTSTATUS status;

        KeInitializeEvent(&event, NotificationEvent, FALSE);
        deviceExtension = (PMDMAI_DEVICE_EXTENSION) DeviceObject->DeviceExtension;

        IoCopyCurrentIrpStackLocationToNext(Irp);

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

        status = IoCallDriver(deviceExtension->TargetDeviceObject, Irp);

        if (status == STATUS_PENDING) {
                KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
                status = Irp->IoStatus.Status;
        }
        return status;
}
Цитата
по поводу 64м - это DMA? или nonpagedpool?
ДМА ... 64М перестраховываюсь ... потому что в приложении тоже выделяется или 64М, или 32М памяти под данные... плата гонит большой поток данных... (она у меня старенькая и на ней прикручено 4 планки памяти по 16М (или больше - 32М история умалчивает, штам затерт) на канал, т.е. 4 канал (2 АЦП и 2 ЦАП)... и имеется исходный код nuMega... приложение только исполнительным файлом... Вот и мучаюсь!))) ну ни че с Вашей помощи есть прогресс!)
« Последнее редактирование: 23-04-2012 11:21 от sabbatazh » Записан
Ochkarik
Модератор

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

« Ответ #43 : 23-04-2012 16:12 » 

не. ну я имел в виду, что система может зайти в функцию обработки IRP два раза для разных IRP. то бишь пользовательский код внутри желательно потокобесопасным делать по возможности.
особенно PnP всякие запросы...
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
sabbatazh
Помогающий

ua
Offline Offline

« Ответ #44 : 24-04-2012 07:51 » 

не. ну я имел в виду, что система может зайти в функцию обработки IRP два раза для разных IRP. то бишь пользовательский код внутри желательно потокобесопасным делать по возможности.
особенно PnP всякие запросы...
а кокай подход или метод применить для потокобезопасности (желательно пример... ыыы... ваще обнаглел?!, а то чет до меня туго доходит... )?!)))
Записан
Ochkarik
Модератор

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

« Ответ #45 : 24-04-2012 08:25 » 

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

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
sabbatazh
Помогающий

ua
Offline Offline

« Ответ #46 : 30-04-2012 11:31 » 

Ochkarik,  Спасибо!! Разобрался...
И осталось решить маленький вопрос... с передачей обьекта прерывания ДМА по хенделу...
в nuMega драйвере есть такие строки:
Код: (C++)
NTSTATUS MDMAIDevice::MDMAI_DMA_SETUP_Handler(KIrp I)
{//...
HANDLE hEvent = *(HANDLE*)I.IoctlBuffer();                      // Get user event handle from inStream
m_pEventSignal = new (NonPagedPool)KEvent(hEvent);      // Create KEvent base on user event handle
//...}
как их правильно представить в WDM???
а вызывается функция в пользовательском приложении:
Код: (C++)
// Создаем event object for interrupt
  InterruptEventHandle[bDeviceNumber]=CreateEvent(NULL,FALSE,FALSE,NULL);
  // Если invalid handle
  if(InterruptEventHandle[bDeviceNumber]==INVALID_HANDLE_VALUE)
  {
    return XDSP_INVALID_DEVICE_HANDLE;
  }

  // Конфигурируем DMA - передаем event object handle, получаем DmaMemoryBufferPtr
  status=DeviceIoControl(DeviceHandle[bDeviceNumber],
                                                 MDMAI_DMA_SETUP,
                                                 &InterruptEventHandle[bDeviceNumber],
                                                 sizeof(InterruptEventHandle[bDeviceNumber]),
                                                 &DMABufferPtrs[bDeviceNumber],
                                                 sizeof(DMABufferPtrs[bDeviceNumber]),
                                                 &nRet,
                                                 NULL);
Я так думаю, что необходимо воспользоваться ObReferenceObjectByHandle()Не понял

Добавлено через 1 час, 17 минут и 50 секунд:
ознакимившись с литературой, наварганил следующий код:
Код: (C++)
case MDMAI_DMA_SETUP:
{
//...
HANDLE hEvent =  (HANDLE) stack->Parameters.DeviceIoControl.Type3InputBuffer;
status = ObReferenceObjectByHandle(        //Create reference to Event Object with Application
                           hEvent,              //Handle as Event Object
                           GENERIC_ALL,//EVENT_MODIFY_STATE,   //Can Modify Event Object state
                           NULL,    //Type of event object. if File object - *IofileObjectType
                           KernelMode,   //UserMode or KernelMode. If KernelMode - Set Previuos parameter to NULL
                           (PVOID *)&_kEvent,              //Global pointer to Event object
                           NULL);

                                                if (_kEvent) KeSetEvent(_kEvent, 0, FALSE);
                                                else {
                                                        KdPrint((DRIVERNAME " — ERROR KEvent \n"));
                                                }
//...
}
и в итоге выпригиваю на "ERROR KEvent "... Где я ошибся?!
« Последнее редактирование: 30-04-2012 12:53 от sabbatazh » Записан
Ochkarik
Модератор

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

« Ответ #47 : 30-04-2012 13:12 » 

stack->Parameters.DeviceIoControl.Type3InputBuffer
это указатель на буфер где лежит Event, а не сам Event)

PS где проверка status?! что  за безобразие)
« Последнее редактирование: 30-04-2012 13:14 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
sabbatazh
Помогающий

ua
Offline Offline

« Ответ #48 : 30-04-2012 14:08 » 

stack->Parameters.DeviceIoControl.Type3InputBuffer
это указатель на буфер где лежит Event, а не сам Event)
Это чуток не понял?! я что-то пропустил?
PS где проверка status?! что  за безобразие)
конечно имеется!)))
Код: (C++)
 if(status!=STATUS_SUCCESS)
            {
                status = STATUS_INVALID_PARAMETER;
                return status; // <-
            }
« Последнее редактирование: 30-04-2012 14:10 от sabbatazh » Записан
Ochkarik
Модератор

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

« Ответ #49 : 30-04-2012 14:11 » 

HANDLE* phEvent =  (HANDLE*) stack->Parameters.DeviceIoControl.Type3InputBuffer;
при использовании - соответственно)
« Последнее редактирование: 30-04-2012 15:03 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
sabbatazh
Помогающий

ua
Offline Offline

« Ответ #50 : 30-04-2012 14:32 » 

HANDLE* phEvent =  (HANDLE*) stack->Parameters.DeviceIoControl.Type3InputBuffer;
при использовании - соответственно)
не проходит привязка к приложению... status = STATUS_SUCCESS... (((
переделал инициализацию и все прошло:
Код: (C++)
 HANDLE hEvent =  *(HANDLE*)Irp->AssociatedIrp.SystemBuffer;
PKEVENT _kEvent;
status = ObReferenceObjectByHandle(        //Create reference to Event Object with Application
                           hEvent,              //Handle as Event Object
                           GENERIC_ALL,//EVENT_MODIFY_STATE,   //Can Modify Event Object state
                           NULL,    //Type of event object. if File object - *IofileObjectType
                           KernelMode,   //UserMode or KernelMode. If KernelMode - Set Previuos parameter to NULL
                           (PVOID *)&_kEvent,              //Global pointer to Event object
                           NULL);

                                                 if(status != STATUS_SUCCESS)
                                                        {
                                                                KdPrint((DRIVERNAME " — ERROR Event Object \n"));
                                                                status = STATUS_INVALID_PARAMETER;
                                                                break;
                                                        }

                                                if (_kEvent) KeSetEvent(_kEvent, 0, FALSE);
                                                else
                                                        {
                                                                KdPrint((DRIVERNAME " — ERROR SetKEvent \n"));
                                                                status = STATUS_INVALID_PARAMETER;
                                                                break;
                                                        }

                                                                KdPrint((DRIVERNAME " — Init Event Object... \n"));

но данные все равно из ДМА не читаются юзерской программой (картинки нет  Быть такого не может Не может быть...)...
у меня подозрение на передаваемое адресное пространство ДМА в пользовательскую программу...
Что можит быть по Вашему???
« Последнее редактирование: 30-04-2012 14:51 от sabbatazh » Записан
Ochkarik
Модератор

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

« Ответ #51 : 30-04-2012 14:59 » 

это я и имел в виду, можно и так.
о.. там же раньше Type3InputBuffer был))) а это только для METHOD_NEITHER а не METHOD_BUFFERED.
метод доступа определяется при формировании значения CTL_CODE() и соответственно доступ по разному делается


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

Добавлено через 3 минуты и 13 секунд:
память DMA выделяется в системном адресном пространстве. у приложения к нему доступа нет.
необходимо выполнить маппинг в пользовательское пространство адресов во время работы драйвера в контексте приложения. удобнее это сделать внутри IOCTL какого нить.
« Последнее редактирование: 30-04-2012 15:10 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
sabbatazh
Помогающий

ua
Offline Offline

« Ответ #52 : 01-05-2012 08:28 » 

Цитата
а как передаете в пользовательское? мапируете? в драйвер данные видит? Event до приложения доходит?
Для этих целий используется структура и функция в ДЛЛ:
Код: (C++)
struct XDSP_DMA_BUFFER_PTRS
{      
        ULONG* DMABufferUserPtr1;
        ULONG* DMABufferUserPtr2;
        ULONG* DMABufferUserPtr3;
        ULONG* DMABufferUserPtr4;

        ULONG  DMABufferPhysPtr1;
        ULONG  DMABufferPhysPtr2;
        ULONG  DMABufferPhysPtr3;
        ULONG  DMABufferPhysPtr4;
};
функция в пользовательском (ДЛЛ) приложении читающая параметры буферов ДМА
Код: (C++)
//...

XDSP_DMA_BUFFER_PTRS DMABufferPtrs;

 // Создаем event object for interrupt
  InterruptEventHandle = CreateEvent(NULL,FALSE,FALSE,NULL);
  // Если invalid handle
  if(InterruptEventHandle == INVALID_HANDLE_VALUE)
  {
    return XDSP_INVALID_DEVICE_HANDLE;
  }

  // Конфигурируем DMA - передаем event object handle, получаем DmaMemoryBufferPtr
                            status=DeviceIoControl(DeviceHandle,
                                                 MDMAI_DMA_SETUP,
                                                 &InterruptEventHandle,
                                                 sizeof(InterruptEventHandle),
                                                 &DMABufferPtrs,
                                                 sizeof(DMABufferPtrs),
                                                 &nRet,
                                                 NULL);
  // Если invalid handle
  if(status==FALSE)
  {
    return XDSP_INVALID_DEVICE_HANDLE;
  }
 
  *phInterruptEventHandle=InterruptEventHandle;
 
  *ppDmaBuffer1=DMABufferPtrs.DMABufferUserPtr1;
  *ppDmaBuffer2=DMABufferPtrs.DMABufferUserPtr2;
  *ppDmaBuffer3=DMABufferPtrs.DMABufferUserPtr3;
  *ppDmaBuffer4=DMABufferPtrs.DMABufferUserPtr4;

  *pDmaBufferAddr1=&DMABufferPtrs.DMABufferPhysPtr1;
  *pDmaBufferAddr2=&DMABufferPtrs.DMABufferPhysPtr2;
  *pDmaBufferAddr3=&DMABufferPtrs.DMABufferPhysPtr3;
  *pDmaBufferAddr4=&DMABufferPtrs.DMABufferPhysPtr4;
в драйвере эту же структуру заполняю следующим образом:
Код: (C++)
m_DmaBuffer1  = pdx->DMAAdapter->DmaOperations->AllocateCommonBuffer(
                                           pdx->DMAAdapter, ROUND_TO_PAGES(MAX_DMA_LENGTH), &DmaPhysAddr1, FALSE);
               
                m_DmaBuffer2  = pdx->DMAAdapter->DmaOperations->AllocateCommonBuffer(
                                            pdx->DMAAdapter, ROUND_TO_PAGES(MAX_DMA_LENGTH), &DmaPhysAddr2, FALSE);
               
                m_DmaBuffer3  = pdx->DMAAdapter->DmaOperations->AllocateCommonBuffer(
                                            pdx->DMAAdapter, ROUND_TO_PAGES(MAX_DMA_LENGTH), &DmaPhysAddr3, FALSE);
               
                m_DmaBuffer4  = pdx->DMAAdapter->DmaOperations->AllocateCommonBuffer(
                                            pdx->DMAAdapter, ROUND_TO_PAGES(MAX_DMA_LENGTH), &DmaPhysAddr4, FALSE);
//...
                  DmaVirtualAddr1 = MmMapLockedPagesSpecifyCache(DmaBufferMemory1, UserMode, MmCached, NULL, FALSE, NormalPagePriority);
                        DmaVirtualAddr2 = MmMapLockedPagesSpecifyCache(DmaBufferMemory2, UserMode, MmCached, NULL, FALSE, NormalPagePriority);
                        DmaVirtualAddr3 = MmMapLockedPagesSpecifyCache(DmaBufferMemory3, UserMode, MmCached, NULL, FALSE, NormalPagePriority);
                        DmaVirtualAddr4 = MmMapLockedPagesSpecifyCache(DmaBufferMemory4, UserMode, MmCached, NULL, FALSE, NormalPagePriority);
//...
XDSP_DMA_BUFFER_PTRS* pBuffer = (XDSP_DMA_BUFFER_PTRS*)ExAllocatePool(NonPagedPool,cbout);
pBuffer->DMABufferPhysPtr1 = DmaPhysAddr1.LowPart;
pBuffer->DMABufferPhysPtr2 = DmaPhysAddr2.LowPart;
pBuffer->DMABufferPhysPtr3 = DmaPhysAddr3.LowPart;
pBuffer->DMABufferPhysPtr4 = DmaPhysAddr4.LowPart;

pBuffer->DMABufferUserPtr1 = (ULONG*)DmaVirtualAddr1;                                      
pBuffer->DMABufferUserPtr2 = (ULONG*)DmaVirtualAddr2;
pBuffer->DMABufferUserPtr3 = (ULONG*)DmaVirtualAddr3;
pBuffer->DMABufferUserPtr4 = (ULONG*)DmaVirtualAddr4;
//...
RtlCopyMemory(pOutputBuffer, pBuffer, info); // отправили пользователю...
и при сравнеии заполнения структур как в драйвере так и в пользовательской программе получились разные значения DMABufferUserPtr1, DMABufferUserPtr2, DMABufferUserPtr3, DMABufferUserPtr4, а значения физических адресов правильны... не могу понять в чем дело?! ...
и дальше значения данной структры из ДЛЛ передаются в приложение, - кода которого у меня нет!((((
В чем можит быть ошибка?!
Спасибо!
« Последнее редактирование: 01-05-2012 13:45 от Ochkarik » Записан
Ochkarik
Модератор

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

« Ответ #53 : 01-05-2012 14:04 » 

DMABufferPhysPtr1 - приложению передавать не стоит - приложению физику знать не надо, и делать с этим адресом - нечего. (или у вас структуры менять нельзя?)
не вижу - как вы получаете MDL DmaBufferMemory1?
и ГЛАВНОЕ: в каком контексте вы вызываете MmMapLockedPagesSpecifyCache()? надо делать обязательно в контексте приложения: то есть в IRP вызванном процессом приложения. в случае промежуточной библиотеки - подумайте где лучше)

RtlCopyMemory(pOutputBuffer, pBuffer, info);
- ересь! и лишнее копирование. пишите код рационально)

PS лучше не форматируйте код табуляцией. оно потом криво выглядит) в настройках студии где то галку надо снять "use tab" или что то типа этого.

Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
sabbatazh
Помогающий

ua
Offline Offline

« Ответ #54 : 01-05-2012 17:39 » new

Цитата
DMABufferPhysPtr1 - приложению передавать не стоит - приложению физику знать не надо, и делать с этим адресом - нечего. (или у вас структуры менять нельзя?)
менять нельзя... дальше передаются в приложение эти данные... с какой целью не пойму!
Цитата
не вижу - как вы получаете MDL DmaBufferMemory1?
Код: (C++)
DmaBufferMemory1 = IoAllocateMdl(m_DmaBuffer1, ROUND_TO_PAGES(MAX_DMA_LENGTH), FALSE, FALSE, NULL);//ROUND_TO_PAGES(MAX_DMA_LENGTH)
                DmaBufferMemory2 = IoAllocateMdl(m_DmaBuffer2, ROUND_TO_PAGES(MAX_DMA_LENGTH), FALSE, FALSE, NULL);
                DmaBufferMemory3 = IoAllocateMdl(m_DmaBuffer3, ROUND_TO_PAGES(MAX_DMA_LENGTH), FALSE, FALSE, NULL);
                DmaBufferMemory4 = IoAllocateMdl(m_DmaBuffer4, ROUND_TO_PAGES(MAX_DMA_LENGTH), FALSE, FALSE, NULL);
Цитата
и ГЛАВНОЕ: в каком контексте вы вызываете MmMapLockedPagesSpecifyCache()? надо делать обязательно в контексте приложения: то есть в IRP вызванном процессом приложения. в случае промежуточной библиотеки - подумайте где лучше)
проанализировав драйвер nuMega в нем есть такие строки
Код: (C++)
pBuffer->DMABufferPhysPtr1 = DmaPhysAddr1;
        pBuffer->DMABufferPhysPtr2 = DmaPhysAddr2;
        pBuffer->DMABufferPhysPtr3 = DmaPhysAddr3;
        pBuffer->DMABufferPhysPtr4 = DmaPhysAddr4;
        pBuffer->DMABufferUserPtr1 = (DWORD*)DmaBufferMemory1->MapToUserSpace();
        pBuffer->DMABufferUserPtr2 = (DWORD*)DmaBufferMemory2->MapToUserSpace();
        pBuffer->DMABufferUserPtr3 = (DWORD*)DmaBufferMemory3->MapToUserSpace();
        pBuffer->DMABufferUserPtr4 = (DWORD*)DmaBufferMemory4->MapToUserSpace();
соответственно вызов осуществляется в драйвере... потому что в ДЛЛ нет ни чего подобного, а в приложение не могу заглянуть (кода нет)!
Цитата
RtlCopyMemory(pOutputBuffer, pBuffer, info);
- ересь! и лишнее копирование. пишите код рационально)
делал все по примерам и как написано в книгах, другога подхода не знаю... (((
Цитата
PS лучше не форматируйте код табуляцией. оно потом криво выглядит) в настройках студии где то галку надо снять "use tab" или что то типа этого.
постараюсь!)))) но ведь каряво выглядит!))
Спасибо!
Записан
Ochkarik
Модератор

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

« Ответ #55 : 01-05-2012 20:35 » 

вот конкретно операцию MmMapLockedPagesSpecifyCache() вы в каком месте драйвера делаете?
и в какой момент работы приложения(библиотеки) - это место драйвера выполняется?
- должно выполнятся в IRP который посылает конкретно это приложение.
То есть, может быть, не стоит этого делать по загрузке библиотеки в ее main... по крайней мере ProcessAttach дождаться...

Добавлено через 2 минуты и 31 секунду:
PS
насчет  RtlCopyMemory(pOutputBuffer, pBuffer, info);
я к тому, что вам же промежуточный буфер потом все равно не нужен... так и пишите сразу в выходной буфер!
или вы все таки MmMapLockedPagesSpecifyCache() вызываете в одной функции, а приложению отдаете в другой.
тогда это не правильно с MmMapLockedPagesSpecifyCache() так низя.
« Последнее редактирование: 01-05-2012 20:38 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
sabbatazh
Помогающий

ua
Offline Offline

« Ответ #56 : 01-05-2012 21:00 » 

Спасибо!!! Учту!!
MmMapLockedPagesSpecifyCache(), у меня вызывается при инициализации драйвера и ДМА, а в приложение передается уже переменная от инициализации... исправлю...

Добавлено через 2 дня, 7 часов, 18 минут и 50 секунд:
Ochkarik, Исправил все недочеты... теперь передается все нормально... но данные пользовательская программа не читает... (((
Думал в прерывании дело... нет, прерывание верно выстовляется... нашел ошибку в:
Код: (C++)
VOID DpcForIsr(IN PKDPC UnusedDpc, IN PVOID Context, IN PVOID SystemArgument1, IN PVOID SystemArgument2) // NTAPI
{
        //PKEVENT Event = (PKEVENT) Context;
        //_kEvent = (PKEVENT) Context;
        KeSetEvent(_kEvent, IO_NO_INCREMENT, FALSE);

        UNREFERENCED_PARAMETER(UnusedDpc);
        UNREFERENCED_PARAMETER(SystemArgument1);
        UNREFERENCED_PARAMETER(SystemArgument2);
       
        //KeResetEvent(_kEvent);

        DbgPrint("enter DPS:\n");
}
_kEvent сделал, пока, глобальной...
и не какого эфекта!
почитал информацию с поста https://forum.shelek.ru/index.php?debug;action=printpage;topic=11514.0 тоже не помогло...
« Последнее редактирование: 04-05-2012 04:19 от sabbatazh » Записан
Ochkarik
Модератор

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

« Ответ #57 : 04-05-2012 04:31 » 

событие в приложении выделяете? с автосбросом?
само DpcForIsr вызывается?

проверяйте по шагам) корректность передачи хендла, вызов ObReferenceObjectByHandle, попробуйте просто событие передать - дойдет ли?
должно все работать)
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
sabbatazh
Помогающий

ua
Offline Offline

« Ответ #58 : 20-05-2012 16:10 » 

Здравствуйте уважаемые знатоки! Давненько я не выходил на связь…
Наконец, добрался до драйвера! (неделю борюсь, все перепробывал)
Значит… получается следующая петрушка…
Цитата
событие в приложении выделяете? с автосбросом?
в ДЛЛ делается следующая штука:
Код: (C++)
// Создаем event object for interrupt
  InterruptEventHandle=CreateEvent(NULL,FALSE,FALSE,NULL);
// и дальше передается в приложение
//...
if(WaitForSingleObject(InterruptEventHandle,TimeOut)==WAIT_OBJECT_0)
  {
        XdspResetAll(hDeviceHandle);
        // Selecting RAM 1 (second) and Do Transaction
        return XdspDMATransactionStart(hDeviceHandle,1,1,TimeOut); // XDSP_STATUS_SUCCESS - if all is OK
  }
Цитата
само DpcForIsr вызывается?
Да, когда происходит прерывание от платы, при записи Данных в память...
Проверил Все доходит ... handle передается верно! ObReferenceObjectByHandle - вызывается без ошибки! объект kEvent - создается в драйвере...

Может выложить nuMega исходники, я что-то упустил?!(((
Уже не знаю какой бубен взять!)
« Последнее редактирование: 20-05-2012 16:41 от sabbatazh » Записан
Ochkarik
Модератор

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

« Ответ #59 : 21-05-2012 09:46 » 

"объект kEvent - создается в драйвере... " - вот тут не понял?)
WaitForSingleObject - что возвращает? TimeOut  - как задан?
Записан

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

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines