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

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

ua
Offline Offline

« : 10-04-2012 14:31 » 

Здравствуйте Уважаемые знатоки!
У меня возникла такая проблема! Переписываю драйвер написанный в nuMega и много чего не понятно…
Есть PCI плата с четырьмя каналами 2 АЦП и 2 ЦАП, для каждого канала есть своя память… доступ к регистрам осуществляется через READ_PORT_ULONG… а данные проецируются в память…
получаю физические адреса портов и памяти, физический адрес преобразцовую в виртуальный и на этом ступор…
Читаю регистры
Код:
#define MDMAI_IO_READ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define MDMAI_IO_WRITE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
научился ... И в старом драйвере были еще такие строки:
Код:
#define MDMAI_MEM_READ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)//работа с памятью 
#define MDMAI_MEM_WRITE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_IN_DIRECT, FILE_ANY_ACCESS)//работа с памятью
#define MDMAI_DMA_SETUP CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)//???
#define MDMAI_INOUT_SET CTL_CODE(FILE_DEVICE_UNKNOWN, 0x805, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)//???
собственно вопрос:
как правильно создать четыре буфера ДМА и передавать через них данные???
Подскажите как быть?!
Спасибо!!!
Записан
Ochkarik
Модератор

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

« Ответ #1 : 10-04-2012 17:01 » 

доброго!
а чем не устраивает код этих IOCTL? и чем вообще не устраивает драйвер. надеюсь не на классах нумеги написанный?)
Записан

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

ua
Offline Offline

« Ответ #2 : 10-04-2012 20:12 » 

Ochkarik,  вот как раз на них!!!! (((( и это полный бред!! и теперь хочу свое сделать и знать, что сделал!
подскажите в каком направлении работать, или хоть пример... а то совсем туго!)
Спасибо!
Записан
Ochkarik
Модератор

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

« Ответ #3 : 11-04-2012 13:10 » 

если плата пишет в память ПК, то вот эти функции:
выделение памяти:
   DMAAdapter = IoGetDmaAdapter(...)
   hBuff0 = DMAAdapter->DmaOperations->AllocateCommonBuffer(...)
потом передаете в плату физические адреса выделенного региона и вуаля.

про отображаемую память с платы в пространство ПК: это при PnP - будет запрос IRP_MN_START_DEVICE/CmResourceTypeMemory на выделение ресурсов (если не путаю, давно с ней занимался)
Записан

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

ua
Offline Offline

« Ответ #4 : 12-04-2012 09:05 » 

Ochkarik, Спасибо!!!
и вот что в драйвере от нумеги:
Код: (C)
NTSTATUS MDMAIDevice::MDMAI_DMA_SETUP_Handler(KIrp I)
{
        //t << "MDMAI_DMA_SETUP_Handler" << EOL;
        //t << "m_FindMaxDmaBufferSize=" << m_FindMaxDmaBufferSize << EOL;
        //t << "m_MaxDmaBufferSize=" << m_MaxDmaBufferSize << EOL;
        //t << "m_DmaBufferSize=" << m_DmaBufferSize << EOL;
        //t << "MAX_DMA_LENGTH=" << MAX_DMA_LENGTH << " ( " << MAX_DMA_LENGTH/1048576 << " MB )" << EOL;

        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();
    //PVOID DmaBufferMemoryAddr;

        m_pEventSignal = new (NonPagedPool)KEvent(hEvent);      // Create KEvent base on user event handle

//      DmaBufferMemoryAddr = DmaBufferMemory1->MapToUserSpace();       // Map m_DmaBuffer to user space
//      *pBuffer = DmaBufferMemoryAddr;                                                         // Fill outStream addr of buf with UserDmaBuffer mapped to user space
//      DmaBufferMemoryAddr = DmaBufferMemory2->MapToUserSpace();       // Map m_DmaBuffer to user space
//      *(pBuffer+1) = DmaBufferMemoryAddr;                                                     // Fill outStream addr of buf with UserDmaBuffer mapped to user space
        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();

        // Connect interrupt to ISR
        status = m_Irq.Connect(LinkTo(Isr_Irq), this);
        // Setup the DPC to be used for interrupt processing
        m_DpcFor_Irq.Setup(LinkTo(DpcFor_Irq), this);

        m_IoPortRange0.outd(1*4,0x00000000);  // RESET_ALL
        m_IoPortRange0.outd(1*4,0x00000001);
        m_IoPortRange0.outd(1*4,0x00000000);
        m_IoPortRange0.outd(7*4,DmaPhysAddr1); // Write Physical Address Of Memory Buffer
//      m_IoPortRange0.outd(8*4,DmaPhysAddr2); // Write Physical Address Of Memory Buffer

/*      // Clear DMA Buffer
        RtlZeroMemory(Buf,MAX_DMA_LENGTH);
*/
     
        I.Information() = 0;
 
        DeviceWasSetuped = 1;
       
        return status;
}
что Вы можете посоветовать и как лучше переписать данную функцию???
« Последнее редактирование: 12-04-2012 10:07 от Ochkarik » Записан
Ochkarik
Модератор

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

« Ответ #5 : 12-04-2012 10:05 » 

тэээкс... у вас DMA с платы в память ПК.
еще, видимо используется прерывание чтобы сигнализировать о заполнении буфера.

переписать...
Код: (C)
DEVICE_DESCRIPTION          devDescr;    //для инициализации объекта DMA Adapter.
    RtlZeroMemory(&devDescr,sizeof(DEVICE_DESCRIPTION)); //обнуляем лишнее (по рекомендации)
    devDescr.Version = DEVICE_DESCRIPTION_VERSION;      //перавя версия, нулевая исползуется только при IgnoreCounter = FALSE
    devDescr.Master = TRUE;
    devDescr.ScatterGather = FALSE;
    //devDescr.DemandMode = Not Used
    //devDescr.AutoInitialize = Not Used
    devDescr.Dma32BitAddresses = TRUE;
    devDescr.IgnoreCount = TRUE;
    //devDescr.Reserved1 = 0;
    devDescr.Dma64BitAddresses = FALSE;
    //devDescr.DoNotUse2 = 0; //=devDescr.BusNumber - NotUsed in WDM
    //devDescr.DmaChannel = 0; //только для Slave устройств
    devDescr.InterfaceType = PCIBus;
    //devDescr.DmaWidth -
    //devDescr.DmaSpeed - не для мастера? (только если value only if the machine's ACPI BIOS supports it)... ничего не понял
    //devDescr.MaximumLength = ROUND_TO_PAGES(XXXXX/2);    
    devDescr.MaximumLength = PAGE_SIZE;    //в любом случае они просили округлить до PAGE_SIZE, да на здоровье!
    //devDescr.DmaPort = 0;   //говорят, что это устаревший параметр. но нужен для совместимости... для Legacy...
    devExt->NumberOfMapRegisters = 2; //мои изыски - вряд ли нужно

     DWORD              NumberOfMapRegisters;   //это надо или нет для расположения DMA adapter
     PDMA_ADAPTER       DMAAdapter;                    //для использования DMA BusMaster необходимо сотворить DMA адаптер
     DMAAdapter =
        IoGetDmaAdapter(    DevExt->PhysicalDeviceObject,
                            &devDescr,
                            &NumberOfMapRegisters);

    if (!DMAAdapter)
    {
        //не удалось получить DMA Adapter.
        ошибка
    }
    PVOID h0_BuffData;
    PHYSICAL_ADDRESS    lpPhisAddrBuffData;
    h0_BuffData =
        DMAAdapter->DmaOperations->
            AllocateCommonBuffer(   DMAAdapter,
                                    ROUND_TO_PAGES(__ваш_размер_),
                                    &lpPhisAddrBuffData,
                                    FALSE);//не совсем понял... в DDK сказано, что этот кеширование должно быть включено..?


    if (!devExt->h0_BuffData)
    {
        //не удалось выделить буфер.
        ошибка
    }

     PMDL               pMdlBuffData;
     pMdlBuffData = IoAllocateMdl(h0_BuffData, ROUND_TO_PAGES(__ваш_размер_), FALSE, FALSE, NULL);
    if (devExt->pMdlBuffData != 0)
    {
        MmBuildMdlForNonPagedPool(pMdlBuffData);
    }
    else
    {
        ошибка
    }

    WRITE_PORT_ULONG((DWORD*)(0xXXXX), (DWORD)lpPhisAddrBuffData.LowPart);

это что касается выделения буфера для DMA. код примерный, поэтому тупо не надо копировать)
насчет остального, повторяться не буду - сгенерите рыбу нумегой без классов под ВАШУ плату(должна быть вставлена) - там есть такая возможность, нумега автоматом ресурсы увидит.

Добавлено через 6 минут и 20 секунд:
PS ээээ... я немного другой пример привел чем у вас было... у вас - память видимо выделялась в приложении... потом мапируется и лочится.
я привел  выделение в драйвере...
разница: приложение выделяет память расположенную в физической памяти -  кусками по 4к.
если плата ScatterGather не поддерживает - это ограничивает одной транзакции по PCI не более 4к.
при выделении памяти как у меня - можно выделять больший размер физически непрерывной памяти.



Добавлено через 5 минут и 4 секунды:
но суть видимо была такая:
выделяем память в приложении.
вызываем драйвер: мапируем буфер в системную память. делаем ее NonPageble. получаем физические адреса на нее, и сообщаем их плате.
инициализируем начало транзакции на плате.
подвешиваем пришедший IRP на pending.
после этого ждем ISR прерывание от платы, по его приходу - запускаем DPC прерывания, в нем завершаем IRP.
так?
« Последнее редактирование: 12-04-2012 10:19 от Ochkarik » Записан

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

ua
Offline Offline

« Ответ #6 : 12-04-2012 13:39 » 

нумега не могу поставить, стоит 7...
наплате для DMA стоит счетчик данных, который при достижении определеного значения выставляет прерывания DMA (это мне так обьяснили)...
вот и на слепую воюю...
в драйвере есть: #define MAX_DMA_LENGTH   0x4000000       // 0x400000 - 64 MB
которое используется в выше приведенной функции...
ну и если что-то подскажет данная функция:
Код:
NTSTATUS MDMAIDevice::MDMAI_INOUT_SET_Handler(KIrp I)
{
NTSTATUS status = STATUS_SUCCESS;
ULONG port4;

    port4 = m_IoPortRange0.ind(4*4); // Read port 4 ControlRegister
    m_IoPortRange0.outd(4*4,port4);  // Enable transaction

KMemory Mem(I.Mdl()); // Create KMemory based on outStream(addr ptr of user buf)
ULONG* pBuffer = (ULONG*)Mem.MapToSystemSpace(); // Map to system pBuffer

*pBuffer = port4;//MAX_DMA_LENGTH;

I.Information() = 0;

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

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

« Ответ #7 : 12-04-2012 13:46 » 

из 4го порта читается значение и обратно записывается в тот же порт. а потом, видимо, возвращается пользователю в IRP.
Записан

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

ua
Offline Offline

« Ответ #8 : 12-04-2012 13:52 » 

Ochkarik, спасибо!!!
И получается, что все таки драйвер, выделяет память, а пользовательская программа подключается к выделенному пространству... ??
читал топ https://forum.shelek.ru/index.php?debug;action=printpage;topic=8409.0
« Последнее редактирование: 12-04-2012 13:54 от sabbatazh » Записан
Ochkarik
Модератор

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

« Ответ #9 : 12-04-2012 13:56 » 

пожалуй похоже что так. (эт я вначале невнимательно посмотрел).
смотрите откуда у вас DmaPhysAddr1-4 получаются.

Добавлено через 3 минуты и 33 секунды:
и смотрите что у вас в Isr_Irq() и в DpcFor_Irq()
« Последнее редактирование: 12-04-2012 14:01 от Ochkarik » Записан

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

ua
Offline Offline

« Ответ #10 : 16-04-2012 09:57 » 

Цитата
и смотрите что у вас в Isr_Irq() и в DpcFor_Irq()
обьясните пожалуйста зачем и как правильно построить данные функции! Спасибо!
Записан
Ochkarik
Модератор

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

« Ответ #11 : 16-04-2012 11:07 » 

isr - обработка аппаратного прерывания. выполняется на DIRQL.
DPC - отложенное прерывание, вызывается после связанного с ним ISR. выполняется помоему на Dispatch_Level. в него переносят то что нельзя выполнить в ISR на DIRQL (например функции которые не могут быть выполнены на DIRQL. или в случае если обработка прерывания занимает слишком большое время (более 10-50мкс помоему).

как и зачем:
обычно (ОБЫЧНО!) плата, после передачи данных по DMA Должны сигнализировать ПК о том что они передали новую порцию данных(сам механизм DMA - такой информации не может предоставить). это делается при помощи прерываний.
что конкретно там делать - зависит от вашей платы.
« Последнее редактирование: 16-04-2012 11:10 от Ochkarik » Записан

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

ua
Offline Offline

« Ответ #12 : 16-04-2012 15:28 » 

подскажите, пожалуйсто, в функции DMAAdapter->DmaOperations->AllocateCommonBuffer() какой логический адрес указывать? или он тут автоматом присваивается или адрес устройства?
Записан
Ochkarik
Модератор

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

« Ответ #13 : 16-04-2012 15:44 » 

внимательнее)
PVOID AllocateCommonBuffer(
  __in   PDMA_ADAPTER DmaAdapter,
  __in   ULONG Length,
  __out  PPHYSICAL_ADDRESS LogicalAddress,
  __in   BOOLEAN CacheEnabled
);

Добавлено через 1 минуту и 3 секунды:
PS это физический адрес, который вы потом своей железке скажете. программно вы по нему обращаться не имеете права - он только для аппаратуры имеет физический смысл)

Цитата
LogicalAddress [out]
Pointer to a variable that receives the logical address the device can use to access the allocated buffer. Use this address rather than calling MmGetPhysicalAddress because the system can take into account any platform-specific memory restrictions.
« Последнее редактирование: 16-04-2012 15:48 от Ochkarik » Записан

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

ua
Offline Offline

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

Ochkarik, Так точно!!! не правильно перевел... (((
от с чем столкнулся: сделал все как Вы советовали! но память не Выделяется!
сделал четыре буфера все идентичны ну и вот на нулевом застрял!

Код: (C++)
#define MAX_DMA_LENGTH  0x4000000           // 0x400000 - 64 MB
//...
// Allocate a DMA adapter object
        pdx->DMAAdapter = IoGetDmaAdapter(pdx->PhysicalDeviceObject, &DeviceDescription, &NumMapRegisters);

        if (pdx->DMAAdapter == NULL)
                {
                        KdPrint(("ERROR - DMA Adapter allocation failed\n"));
                        return STATUS_INSUFFICIENT_RESOURCES;
                }
       
                h0_BuffData = pdx->DMAAdapter->DmaOperations->AllocateCommonBuffer(
                                          pdx->DMAAdapter, ROUND_TO_PAGES(MAX_DMA_LENGTH), &lpPhisAddrBuffData0, FALSE);

                if (!h0_BuffData)
                        {  
                                        KdPrint(("Failed to allocate DMA buffer\n")); //<- Запрыгиваем сюда, -  не есть хорошо!
                                return STATUS_INSUFFICIENT_RESOURCES;
                        }
               
                pMdlBuffData0 = IoAllocateMdl(h0_BuffData, ROUND_TO_PAGES(MAX_DMA_LENGTH), FALSE, FALSE, NULL);

                        if (pMdlBuffData0 != NULL)
                                {
                                        MmBuildMdlForNonPagedPool(pMdlBuffData0);
                                }
                                else
                                {
                                        ExFreePool(h0_BuffData);
                                                KdPrint(("Failed to allocate MDL buffer\n"));
                                               
                                        return STATUS_INSUFFICIENT_RESOURCES;
                                }
и DebugView: "Failed to allocate DMA buffer". наверное много требую MAX_DMA_LENGTH... Не понял
« Последнее редактирование: 16-04-2012 16:36 от sabbatazh » Записан
Ochkarik
Модератор

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

« Ответ #15 : 16-04-2012 16:42 » 

очень вероятно что да. 64М - это жестоко.
функция выделяет физически непрерывную память - с этим в системе напряженка)
более того. после запуска OC вероятность выделить бОльший кусок физически непрерывной памяти - падает: фрагментация однако.
при старте ОС я выделял до 16-32Мбайт,  позже - можно обломаться. сейчас выделяю 2 или 4. уже не помню точно.
PS да, и кроме того это nonpaged pool. то бишь не кэшируемая... с этим тоже напряженка. где то на форуме была инфа о предельном размере этого пула для разных версий ОС.
« Последнее редактирование: 16-04-2012 16:45 от Ochkarik » Записан

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

ua
Offline Offline

« Ответ #16 : 16-04-2012 20:26 » 

Ochkarik, все перепробывал... капец не выделяется... менял 16 и 2 и 32 и 8 М... запрыгивает в "Failed to allocate DMA buffer" ... что делать Не понял винда 7... 1М выделяет думаю, что дело в  DeviceDescription.MaximumLength = ROUND_TO_PAGES(MAX_DMA_LENGTH);//PAGE_SIZE; - проверю...
дополнил, как и в nuMega DmaVirtualAddr0 :
Код: (C++)
DmaVirtualAddr0 = MmMapLockedPagesSpecifyCache(pMdlBuffData, UserMode, MmCached, NULL, FALSE, NormalPagePriority);
                        if (!DmaVirtualAddr0)
                                {
                                                KdPrint(("Failed to allocate VirtualAddr\n"));
                                                IoFreeMdl(pMdlBuffData);
                                                ExFreePool(h0_BuffData);
                                        return STATUS_INSUFFICIENT_RESOURCES;
                                }

и еще вопрос: как правильно освободить DMA??? а то я сделал процедуру, а она синий экран выкинула!
Код: (C++)
NTSTATUS MDMAIDmaAdapterFree(PMDMAI_DEVICE_EXTENSION pdx)
{
    KdPrint(("Releasing DMA Adapter object...\n"));

           if (DmaVirtualAddr0 != NULL)
                {                      
                        MmUnmapLockedPages(DmaVirtualAddr0, pMdlBuffData);
                        IoFreeMdl(pMdlBuffData);
                        ExFreePool(DmaVirtualAddr0);
                        ExFreePool(h0_BuffData);
                }

    // 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;
    }

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

    // DMA adapter object deleted, no longer available
        pdx->DMAAdapter = NULL;

    return STATUS_SUCCESS;
}
« Последнее редактирование: 16-04-2012 22:12 от sabbatazh » Записан
Ochkarik
Модератор

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

« Ответ #17 : 16-04-2012 21:06 » 

не надо жадничать) попробуйте начать с выделения 4/8кб)

PutDmaAdapter - выглядит правильно, уверены что на этом вызове падает?
DeviceDescription - как у меня?

Добавлено через 5 минут:
PS ExFreePool(h0_BuffData); - не надо так делать)
« Последнее редактирование: 16-04-2012 21:11 от Ochkarik » Записан

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

ua
Offline Offline

« Ответ #18 : 16-04-2012 22:14 » 

Цитата
PS ExFreePool(h0_BuffData); - не надо так делать)
а как Не понял
Цитата
PutDmaAdapter - выглядит правильно, уверены что на этом вызове падает?
именно так,  больше не чему!

я 16 пост подправил, Вас не затруднит взглянуть?

Цитата
DeviceDescription - как у меня?
перетянул с nuMega:
Код: (C++)
DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;      //перавя версия, нулевая исползуется только при IgnoreCounter = FALSE
    DeviceDescription.Master = TRUE;
    DeviceDescription.ScatterGather = FALSE;
    DeviceDescription.DemandMode = TRUE;
    DeviceDescription.AutoInitialize = FALSE;
    DeviceDescription.Dma32BitAddresses = TRUE;
    DeviceDescription.IgnoreCount = FALSE;//TRUE;
    //devDescr.Reserved1 = 0;
    DeviceDescription.Dma64BitAddresses = FALSE;
    //devDescr.DoNotUse2 = 0; //=devDescr.BusNumber - NotUsed in WDM
    DeviceDescription.DmaChannel = 0; //только для Slave устройств
    DeviceDescription.InterfaceType = PCIBus;
    DeviceDescription.DmaWidth = Width32Bits;   // PCI default width
    DeviceDescription.DmaSpeed = Compatible;//не для мастера? (только если value only if the machine's ACPI BIOS supports it)... ничего не понял
    //devDescr.MaximumLength = ROUND_TO_PAGES(XXXXX/2);    
    DeviceDescription.MaximumLength = ROUND_TO_PAGES(MAX_DMA_LENGTH);//PAGE_SIZE;
или оставить как у Вас?
« Последнее редактирование: 16-04-2012 22:19 от sabbatazh » Записан
Ochkarik
Модератор

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

« Ответ #19 : 17-04-2012 06:55 » 

h0_BuffData - вы выделяете одним классом функций а убиваете - другим.
ищите слева: http://msdn.microsoft.com/en-us/library/windows/hardware/ff540575(v=vs.85).aspx
если вы выделяете память AllocateCommonBuffer то уж удаляйте ее при помощи FreeCommonBuffer!
если выделяете ExAllocatePool - тогда удаляйте  ExFreePool. не надо смешивать.

DeviceDescription.MaximumLength оставьте 1 страницу... не помню уже что за параметр))) читать надо.

MmMapLockedPagesSpecifyCache  -не уверен что нужно лочить) оно и так уже...
на работу приду гляну.

Добавлено через 5 минут и 39 секунд:
так 1мб выделился? не понял.
« Последнее редактирование: 17-04-2012 07:01 от Ochkarik » Записан

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

ua
Offline Offline

« Ответ #20 : 17-04-2012 08:51 » 

Цитата
h0_BuffData - вы выделяете одним классом функций а убиваете - другим.
ищите слева: http://msdn.microsoft.com/en-us/library/windows/hardware/ff540575(v=vs.85).aspx
если вы выделяете память AllocateCommonBuffer то уж удаляйте ее при помощи FreeCommonBuffer!
если выделяете ExAllocatePool - тогда удаляйте  ExFreePool. не надо смешивать.

DeviceDescription.MaximumLength оставьте 1 страницу... не помню уже что за параметр))) читать надо.

MmMapLockedPagesSpecifyCache  -не уверен что нужно лочить) оно и так уже...
на работу приду гляну.
Спасибо!!!
Цитата
так 1мб выделился? не понял.
Выделяется! больше нет!
Записан
Ochkarik
Модератор

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

« Ответ #21 : 17-04-2012 09:56 » 

ну раз больше 1мб не выделяется то значит больше и не получится. может быть получится если драйвер будет запускаться при старте системы.
какая ОС, сколько памяти на борту? и... сколько вам вообще нужно этой памяти на самом деле? нафиг выделять больше чем надо?)

Добавлено через 14 минут и 28 секунд:
да MmMapLockedPages(pMdlBuffData0...) будет нужен если вы хотите отмапировать буфер в приложение.
вызывать соответственно только в контексте того приложения которому вы хотите отмапировать.

Добавлено через 53 секунды:
PS вообще буфер лучше размещать при PnP.
а потом только маппинг в приложение делать.
« Последнее редактирование: 17-04-2012 10:11 от Ochkarik » Записан

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

ua
Offline Offline

« Ответ #22 : 17-04-2012 11:14 » 

Ochkarik, использую винду семерку 32, 3гига памяти, и нужно до 64 метров выделять памяти под буфер (так сделано в nuMega драйвере)... с платы большой поток данных идет... !!!
нашел почему был синий экран, в фуннкции 16 сообщения, исправил:
Код: (C++)
NTSTATUS MDMAIDmaAdapterFree(PMDMAI_DEVICE_EXTENSION pdx)
{      
                        KdPrint((DRIVERNAME " - Releasing DMA Adapter object...\n"));

        if (DmaVirtualAddr0 != NULL)
                {      
                        //MmUnmapLockedPages(DmaVirtualAddr0, pMdlBuffData);
                        if (pMdlBuffData != NULL) IoFreeMdl(pMdlBuffData);
                          DmaVirtualAddr0 = NULL;                        
                }

    // 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;
                }

        // Release the buffer  
    pdx->DMAAdapter->DmaOperations->FreeCommonBuffer(  
        pdx->DMAAdapter,  
        ROUND_TO_PAGES(MAX_DMA_LENGTH),  
        lpPhisAddrBuffData,  
        h0_BuffData,  
        FALSE      // Enable Caching for buffer?  
        );      
       
        // Clear memory object properties  
    if (h0_BuffData != NULL) h0_BuffData = NULL; //RtlZeroMemory(h0_BuffData, sizeof(h0_BuffData));  

    // 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;
}
теперь работает как часы, китайские!))
« Последнее редактирование: 17-04-2012 11:19 от sabbatazh » Записан
Ochkarik
Модератор

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

« Ответ #23 : 17-04-2012 11:59 » 

Цитата
теперь работает как часы, китайские!))
- после сборки обработать рашпилем и будут тикать как советские)
Записан

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

ua
Offline Offline

« Ответ #24 : 17-04-2012 15:19 » 

пожалуй похоже что так. (эт я вначале невнимательно посмотрел).
смотрите откуда у вас DmaPhysAddr1-4 получаются.

Добавлено через 3 минуты и 33 секунды:
и смотрите что у вас в Isr_Irq() и в DpcFor_Irq()
Подскажите пожалуйста, как правильно работать с Isr_Irq() и в DpcFor_Irq() в WDM? искал в сети пример с пояснением ... - толкого ни чего не нашел!
Записан
Ochkarik
Модератор

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

« Ответ #25 : 17-04-2012 16:30 » 

ключевые слова для поиска)
CmResourceTypeInterrupt http://msdn.microsoft.com/en-us/library/windows/hardware/ff565394(v=vs.85).aspx
IoConnectInterrupt http://technet.microsoft.com/en-us/library/ff548371(VS.85).aspx
DpcForIsr routine http://technet.microsoft.com/en-us/library/ff544079(VS.85).aspx

InterruptService routine http://technet.microsoft.com/en-us/library/ff547958(VS.85).aspx
IoRequestDpc routine http://technet.microsoft.com/en-us/library/ff549657(VS.85).aspx
Записан

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

ua
Offline Offline

« Ответ #26 : 18-04-2012 18:32 » 

прочитал, Вами указанные сылки и сразу возник вопрос :  как представить функции nuMega
Код: (C++)
VOID MDMAIDevice::DpcFor_Irq(PVOID Arg1, PVOID Arg2)
{
        m_pEventSignal->Set();

        // The following macros simply allows compilation at Warning Level 4
        // If you reference these parameters in the function simply remove the macro.
        UNREFERENCED_PARAMETER(Arg1);
        UNREFERENCED_PARAMETER(Arg2);
}
и
Код: (C++)
BOOLEAN MDMAIDevice::Isr_Irq(void)
{
        ULONG port1,port3;

    if(DeviceWasSetuped==1)
        {
          port3 = m_IoPortRange0.ind(3*4);   // Read port 3
          if((port3 & 0x1) | (port3 & 0x2))
          {
        port1 = m_IoPortRange0.ind(1*4); // Read port 1
        port1 = port1 & ~0x00000002;
            m_IoPortRange0.outd(1*4,port1);  // Reset interrupt Clear
        port1 = port1 |  0x00000002;
            m_IoPortRange0.outd(1*4,port1);  // Reset interrupt Set
        port1 = port1 & ~0x00000002;
            m_IoPortRange0.outd(1*4,port1);  // Reset interrupt Clear

            // Request deferred procedure call
            // The arguments to Request may be any values that you choose
            m_DpcFor_Irq.Request(NULL, NULL);

            // Return TRUE to indicate that our device caused the interrupt
            return TRUE;
          }
          return FALSE;
        } else {
      port1 = m_IoPortRange0.ind(1*4); // Read port 1
      port1 = port1 & ~0x00000002;
          m_IoPortRange0.outd(1*4,port1);  // Reset interrupt Clear
      port1 = port1 |  0x00000002;
          m_IoPortRange0.outd(1*4,port1);  // Reset interrupt Set
      port1 = port1 & ~0x00000002;
          m_IoPortRange0.outd(1*4,port1);  // Reset interrupt Clear

          // Request deferred procedure call
          // The arguments to Request may be any values that you choose
          m_DpcFor_Irq.Request(NULL, NULL);

          // Return TRUE to indicate that our device caused the interrupt
          return TRUE;
        }
}
а именно, что такое m_DpcFor_Irq.Request(NULL, NULL); и функция DpcFor_Irq(PVOID Arg1, PVOID Arg2)
как это все представить или будит выгледеть в WDM?? ?
я запутался! Спасибо! (и думаю уже Вас достал!)

Добавлено через 35 минут и 40 секунд:
функции представил в следующем виде:
Код: (C++)
BOOLEAN OnInterrupt( PKINTERRUPT InterruptObject, PMDMAI_DEVICE_EXTENSION pdx )
{                                                       // OnInterrupt
                        DbgPrint(("==============interrupt!!!\n"));    

        ULONG port1,port3;

        if(DeviceWasSetuped==1)
                {
                                port3 = READ_PORT_UCHAR((PULONG)(pdx->portaddr+3*4));
                        if((port3 & 0x1) | (port3 & 0x2))
                                {
                                        port1 = READ_PORT_UCHAR( (PULONG)(pdx->portaddr + 1*4)); // Read port 1
                                        port1 = port1 & ~0x00000002;                                                                           
                                                        WRITE_PORT_ULONG((PULONG)(pdx->portaddr + 1*4), port1); // Reset interrupt Clear
                                        port1 = port1 |  0x00000002;
                                                        WRITE_PORT_ULONG((PULONG)(pdx->portaddr + 1*4), port1); // Reset interrupt Set
                                        port1 = port1 & ~0x00000002;
                                                        WRITE_PORT_ULONG((PULONG)(pdx->portaddr + 1*4), port1);  // Reset interrupt Clear

                                        IoRequestDpc(pdx->DeviceObject, NULL, pdx);

                                        return TRUE;
                                }
                        return FALSE;
                }else{
                                        port1 = READ_PORT_UCHAR( (PULONG)(pdx->portaddr + 1*4)); // Read port 1
                                        port1 = port1 & ~0x00000002;                                                                           
                                                        WRITE_PORT_ULONG((PULONG)(pdx->portaddr + 1*4), port1); // Reset interrupt Clear
                                        port1 = port1 |  0x00000002;
                                                        WRITE_PORT_ULONG((PULONG)(pdx->portaddr + 1*4), port1); // Reset interrupt Set
                                        port1 = port1 & ~0x00000002;
                                                        WRITE_PORT_ULONG((PULONG)(pdx->portaddr + 1*4), port1);  // Reset interrupt Clear

                                        IoRequestDpc(pdx->DeviceObject, NULL, pdx);

                                        return TRUE;
                }              
}
ну и соответственно
Код: (C++)
NTSTATUS MDMAIDpcFor_Irq(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
{
        PKEVENT Event = (PKEVENT) Context;

        UNREFERENCED_PARAMETER(DeviceObject);
        UNREFERENCED_PARAMETER(Irp);

        KeSetEvent(Event, IO_NO_INCREMENT, FALSE);

        return(STATUS_MORE_PROCESSING_REQUIRED);
}
Просмотрите, Верно?!
« Последнее редактирование: 18-04-2012 19:08 от sabbatazh » Записан
Ochkarik
Модератор

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

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

m_DpcFor_Irq - экземпляр класса DPC. m_DpcFor_Irq.Request() - соответственно запрос DPC.
WDM - соответственно функция IoRequestDpc()  - см ссылки.

выше у вас были строки
        // Connect interrupt to ISR
        status = m_Irq.Connect(LinkTo(Isr_Irq), this);

        // Setup the DPC to be used for interrupt processing
        m_DpcFor_Irq.Setup(LinkTo(DpcFor_Irq), this);
сильно не вчитываясь - инициализируется этот самый экземпляр класса прерывания и класса DPC, своими... назовем это "калбэками" - пользовательские функции обработки: Isr_Irq и  DpcFor_Irq.
их аналоги для WDM IoConnectInterrupt  и IoInitializeDpcRequest.

на самом деле если вы внутрь реализации класса нумеги посмотрите - вы там все это увидите.
по-моему они там в исходниках были.

PS не, не достали))
PPS DpcForIsr должна возвращать VOID. и входных параметра 4.
и вы туда передаете IoRequestDpc(pdx->DeviceObject, NULL, pdx); - последний параметр "__in  PVOID Context"
а в самой DPC  кладете его в PKEVENT Event = (PKEVENT) Context;
а в целом что то похожее)
Записан

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

ua
Offline Offline

« Ответ #28 : 18-04-2012 20:31 » 

Цитата
PPS DpcForIsr должна возвращать VOID. и входных параметра 4.
понял
Код: (C++)
VOID DpcForIsr(IN PKDPC UnusedDpc, IN PVOID Context, IN PVOID SystemArgument1, IN PVOID SystemArgument2) // NTAPI
{
        PKEVENT Event = (PKEVENT) Context;
       
        UNREFERENCED_PARAMETER(UnusedDpc);
        UNREFERENCED_PARAMETER(SystemArgument1);
        UNREFERENCED_PARAMETER(SystemArgument2);

        KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
}
Спасибо!!!

и еще... объясните пожалуйсто функцию:
Код: (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;
}
... я так понял m_MemoryRange0.ind(pArgs->ByteOffset, pOutBuffer, pArgs->DwordCount) - не что иное как READ_REGISTER_BUFFER_ULONG()
и зачем еще такая штука m_pEventSignal = new (NonPagedPool)KEvent(hEvent) (строка из функции ответа 4)))
и чем заменить DmaBufferMemory1->MapToUserSpace();
а передавать пользователю и плате DmaPhysAddr1.LowPart или DmaPhysAddr1.HighPart физический адрес выделенной памяти ДМА?
Спасибо!!!!
« Последнее редактирование: 18-04-2012 21:32 от sabbatazh » Записан
Ochkarik
Модератор

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

« Ответ #29 : 19-04-2012 06:16 » 

почти. но поскольку предполагается пользовать IoRequestDpc - для нее второй аргумент DpcForIsr  другой. и про передачу Event-а вместо pdx не забудьте. посмотрите внимательно как DpcForIsr  определен. ссылку я давал

m_pEventSignal -  пользователь передает в драйвер хендл события. но в драйвере напрямую его нельзя использовать. сначала делают ссылку на это событие и используют ее. ObReferenceObjectByHandle()
читать Sharing Is Caring - Sharing Events Between Kernel-User Mode  

передать физ адрес - через порты m_IoPortRange0 у вас вроде было написано.

MapToUserSpace  - видимо мапирование памяти к пользователю. MmMapLockedPages() вызванная в контексте пользователя.
« Последнее редактирование: 19-04-2012 06:18 от Ochkarik » Записан

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

Цитата
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...
sabbatazh
Помогающий

ua
Offline Offline

« Ответ #60 : 21-05-2012 14:55 » 

Ochkarik, я в ДЛЛ ни чего не изменял... она ведь со старым драйвером прекрасно работала, и єти все функции тоже работали....
Цитата
"объект kEvent - создается в драйвере... " - вот тут не понял?)
обьявлен и создается в драйвере... или не так?
Код: (C++)
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
                           UserMode,   //UserMode or KernelMode. If KernelMode - Set Previuos parameter to NULL
                           (PVOID *)&_kEvent,              //Global pointer to Event object
                           NULL);
Цитата
TimeOut  - как задан?
задается из приложения... посмотрю значение из ДЛЛ ...
Цитата
WaitForSingleObject - что возвращает?
посмотрю значение из ДЛЛ ...
« Последнее редактирование: 21-05-2012 15:01 от sabbatazh » Записан
Ochkarik
Модератор

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

« Ответ #61 : 21-05-2012 15:14 » 

формулировка:
создание - это если б вы IoCreateSynchronizationEvent/IoCreateNotificationEvent в драйвере делали...
а ObReferenceObjectByHandle - ссылку на уже существующий объект созданный в приложении получает.


Добавлено через 5 минут и 25 секунд:
и кстати получает не....
читайте описание функции ObReferenceObjectByHandle Ага

Добавлено через 5 минут и 31 секунду:
PS третий и четвертый параметр. да и второй тоже... не факт.

Добавлено через 29 секунд:
Код: (C)
                status =
                        ObReferenceObjectByHandle(  hEvent,
                                                    EVENT_MODIFY_STATE,
                                                    *ExEventObjectType,
                                                    KernelMode,
                                                    (PVOID*)&kEvent,
                                                    NULL);
« Последнее редактирование: 21-05-2012 15:28 от Ochkarik » Записан

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

ua
Offline Offline

« Ответ #62 : 22-05-2012 15:43 » 

Ochkarik, спасибо за помощь! Почитал... просветился!)
Цитата
WaitForSingleObject - что возвращает?
возвращает значение отличное от WAIT_OBJECT_0... не пойму с чем это связано!
Цитата
TimeOut  - как задан?
задано 1000 ...
Записан
Ochkarik
Модератор

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

« Ответ #63 : 22-05-2012 15:49 » 

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

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

ua
Offline Offline

« Ответ #64 : 22-05-2012 17:26 » 

Ochkarik, Вы как всегда правы!!!!
изменил ДЛЛ прописал вместо TimeOut... INFINITE
Код: (C++)
if(WaitForSingleObject(InterruptEventHandle, INFINITE)==WAIT_OBJECT_0) // TimeOut
и все заработало!!! )))
Огромное Вам Спасибо!!!
Записан
Ochkarik
Модератор

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

« Ответ #65 : 22-05-2012 18:30 » 

ну что-ж... но все таки старайтесь избегать бесконечных ожиданий)
всегда пожалуйста)
Записан

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

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines