sabbatazh
Помогающий
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
|
|
« Ответ #1 : 10-04-2012 17:01 » |
|
доброго! а чем не устраивает код этих IOCTL? и чем вообще не устраивает драйвер. надеюсь не на классах нумеги написанный?)
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #2 : 10-04-2012 20:12 » |
|
Ochkarik, вот как раз на них!!!! (((( и это полный бред!! и теперь хочу свое сделать и знать, что сделал! подскажите в каком направлении работать, или хоть пример... а то совсем туго!) Спасибо!
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #3 : 11-04-2012 13:10 » |
|
если плата пишет в память ПК, то вот эти функции: выделение памяти: DMAAdapter = IoGetDmaAdapter(...) hBuff0 = DMAAdapter->DmaOperations->AllocateCommonBuffer(...) потом передаете в плату физические адреса выделенного региона и вуаля.
про отображаемую память с платы в пространство ПК: это при PnP - будет запрос IRP_MN_START_DEVICE/CmResourceTypeMemory на выделение ресурсов (если не путаю, давно с ней занимался)
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #4 : 12-04-2012 09:05 » |
|
Ochkarik, Спасибо!!! и вот что в драйвере от нумеги: 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
|
|
« Ответ #5 : 12-04-2012 10:05 » |
|
тэээкс... у вас DMA с платы в память ПК. еще, видимо используется прерывание чтобы сигнализировать о заполнении буфера. переписать... 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 уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
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
|
|
« Ответ #7 : 12-04-2012 13:46 » |
|
из 4го порта читается значение и обратно записывается в тот же порт. а потом, видимо, возвращается пользователю в IRP.
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
|
Ochkarik
|
|
« Ответ #9 : 12-04-2012 13:56 » |
|
пожалуй похоже что так. (эт я вначале невнимательно посмотрел). смотрите откуда у вас DmaPhysAddr1-4 получаются.
Добавлено через 3 минуты и 33 секунды: и смотрите что у вас в Isr_Irq() и в DpcFor_Irq()
|
|
« Последнее редактирование: 12-04-2012 14:01 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #10 : 16-04-2012 09:57 » |
|
и смотрите что у вас в Isr_Irq() и в DpcFor_Irq() обьясните пожалуйста зачем и как правильно построить данные функции! Спасибо!
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #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 уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #12 : 16-04-2012 15:28 » |
|
подскажите, пожалуйсто, в функции DMAAdapter->DmaOperations->AllocateCommonBuffer() какой логический адрес указывать? или он тут автоматом присваивается или адрес устройства?
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #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 уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #14 : 16-04-2012 16:34 » |
|
Ochkarik, Так точно!!! не правильно перевел... ((( от с чем столкнулся: сделал все как Вы советовали! но память не Выделяется! сделал четыре буфера все идентичны ну и вот на нулевом застрял! #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
|
|
« Ответ #15 : 16-04-2012 16:42 » |
|
очень вероятно что да. 64М - это жестоко. функция выделяет физически непрерывную память - с этим в системе напряженка) более того. после запуска OC вероятность выделить бОльший кусок физически непрерывной памяти - падает: фрагментация однако. при старте ОС я выделял до 16-32Мбайт, позже - можно обломаться. сейчас выделяю 2 или 4. уже не помню точно. PS да, и кроме того это nonpaged pool. то бишь не кэшируемая... с этим тоже напряженка. где то на форуме была инфа о предельном размере этого пула для разных версий ОС.
|
|
« Последнее редактирование: 16-04-2012 16:45 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
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 : 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??? а то я сделал процедуру, а она синий экран выкинула! 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
|
|
« Ответ #17 : 16-04-2012 21:06 » |
|
не надо жадничать) попробуйте начать с выделения 4/8кб)
PutDmaAdapter - выглядит правильно, уверены что на этом вызове падает? DeviceDescription - как у меня?
Добавлено через 5 минут: PS ExFreePool(h0_BuffData); - не надо так делать)
|
|
« Последнее редактирование: 16-04-2012 21:11 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #18 : 16-04-2012 22:14 » |
|
PS ExFreePool(h0_BuffData); - не надо так делать) а как PutDmaAdapter - выглядит правильно, уверены что на этом вызове падает? именно так, больше не чему! я 16 пост подправил, Вас не затруднит взглянуть? DeviceDescription - как у меня? перетянул с nuMega: 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
|
|
« Ответ #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 уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
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
|
|
« Ответ #21 : 17-04-2012 09:56 » |
|
ну раз больше 1мб не выделяется то значит больше и не получится. может быть получится если драйвер будет запускаться при старте системы. какая ОС, сколько памяти на борту? и... сколько вам вообще нужно этой памяти на самом деле? нафиг выделять больше чем надо?)
Добавлено через 14 минут и 28 секунд: да MmMapLockedPages(pMdlBuffData0...) будет нужен если вы хотите отмапировать буфер в приложение. вызывать соответственно только в контексте того приложения которому вы хотите отмапировать.
Добавлено через 53 секунды: PS вообще буфер лучше размещать при PnP. а потом только маппинг в приложение делать.
|
|
« Последнее редактирование: 17-04-2012 10:11 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #22 : 17-04-2012 11:14 » |
|
Ochkarik, использую винду семерку 32, 3гига памяти, и нужно до 64 метров выделять памяти под буфер (так сделано в nuMega драйвере)... с платы большой поток данных идет... !!! нашел почему был синий экран, в фуннкции 16 сообщения, исправил: 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
|
|
« Ответ #23 : 17-04-2012 11:59 » |
|
теперь работает как часы, китайские!))
- после сборки обработать рашпилем и будут тикать как советские)
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #24 : 17-04-2012 15:19 » |
|
пожалуй похоже что так. (эт я вначале невнимательно посмотрел). смотрите откуда у вас DmaPhysAddr1-4 получаются.
Добавлено через 3 минуты и 33 секунды: и смотрите что у вас в Isr_Irq() и в DpcFor_Irq()
Подскажите пожалуйста, как правильно работать с Isr_Irq() и в DpcFor_Irq() в WDM? искал в сети пример с пояснением ... - толкого ни чего не нашел!
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #25 : 17-04-2012 16:30 » |
|
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #26 : 18-04-2012 18:32 » |
|
прочитал, Вами указанные сылки и сразу возник вопрос : как представить функции nuMega 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); } и 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 секунд:функции представил в следующем виде: 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; } } ну и соответственно 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
|
|
« Ответ #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 уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #28 : 18-04-2012 20:31 » |
|
PPS DpcForIsr должна возвращать VOID. и входных параметра 4. понял 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); } Спасибо!!! и еще... объясните пожалуйсто функцию: 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
|
|
« Ответ #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 уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
|