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

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2 3  Все   Вниз
  Печать  
Автор Тема: PCI + DMA в WDM драйвере  (Прочитано 53616 раз)
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 » new

тэээкс... у вас 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...
Страниц: [1] 2 3  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines