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...
|
|
|
sabbatazh
Помогающий
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
|
|
« Ответ #31 : 19-04-2012 08:55 » |
|
можно и так. физический адрес: если у вас плата не поддерживает x64, то отдаете ей только LowPart. подозреваю что да, чтение из платы в pOutBuffer, который из IRP, который они сначала мапируют в системное адресное пространство (не понял только зачем) .
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #32 : 19-04-2012 11:52 » |
|
Спасибо! Воспользовавшись Вашими советами переписал процедуру numega: 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(): 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
|
|
« Ответ #33 : 19-04-2012 13:08 » |
|
1. проверка. в драйвер по IOCTL передается структура а вы проверяете на размер указателя на нее. это не верно) 2. буфер выделяется в приложении, по-моему, а не создается новый. зачем вам второй буфер и второе копирование?
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #34 : 19-04-2012 14:46 » |
|
1. проверка. в драйвер по IOCTL передается структура а вы проверяете на размер указателя на нее. это не верно) 2. буфер выделяется в приложении, по-моему, а не создается новый. зачем вам второй буфер и второе копирование?
я не понял!((( Вас не затруднит подробнее объяснить! Спасибо!
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #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 уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #36 : 19-04-2012 16:31 » |
|
Ochkarik, Спасибо!!! Столкнулся с проблемой синего экрана, при попытке прочитать LowPart ( PHYSICAL_ADDRESS) ДМА : 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
|
|
« Ответ #37 : 19-04-2012 18:35 » |
|
быть не может... это физически невозможно) но ошибка точно не в ней. ищите в другом месте... иногда ошибки проявляются в BSOD позже того места где они возникают)
|
|
« Последнее редактирование: 19-04-2012 18:45 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #38 : 21-04-2012 14:09 » |
|
Ochkarik, нашел в чем ошибка! я не правильно объявлял структуру XDSP_DMA_BUFFER_PTRS, а именно переменную pBuffer, у меня в WDM : XDSP_DMA_BUFFER_PTRS* pBuffer = (XDSP_DMA_BUFFER_PTRS*)Irp->AssociatedIrp.SystemBuffer; if (pBuffer!=NULL) pBuffer->DMABufferPhysPtr1 = DmaPhysAddr1.LowPart; <- синий экран!!! а в nuMega драйвере через память: 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() 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
|
|
« Ответ #39 : 21-04-2012 22:18 » |
|
NonPagedPool - это не тот ресурс которым можно так в легкую разбрасываться. в системе на него ограничения)
Добавлено через 11 минут и 55 секунд: а кроме того... ну это ересь - выделять буфер чтобы его тут же убить. копируйте напрямую. PS да, выделили память - проверили что выделилось. это у вас есть. а вот ExFreePool судя по куску кода - вызовется и обоих случаях. это не очень правильно) привыкайте писать аккуратнее - будет меньше BSODов)
|
|
« Последнее редактирование: 21-04-2012 22:30 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #40 : 22-04-2012 13:07 » |
|
Ochkarik, Спасибо!!! Очень помогли! Обнаружил, что 64М память выделяется после установки драйвера и перезагрузки системы, и драйвер переставляю скока угодно, память выделяется... с чем это может быть связано?? Добавлено через 32 минуты и 17 секунд:ДУмаю уже последний мой вопрос по этой теме!) ВЫлетает синий экран после закрытия приложения работающего с драйвером (ну тут думаю разберусь), вызывается функция: 1)!!! 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)!!! и когда удаляю драйвер: 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) : 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
|
|
« Ответ #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 уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #42 : 23-04-2012 11:18 » |
|
Спасибо!!! Буду пробовать! не забывать что IRP могут обрабатываться параллельно. то бишь надо думать о синхронизации потоков и использовать атомарные или потокобезопасные методы. - это как? типа ткаго: 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
|
|
« Ответ #43 : 23-04-2012 16:12 » |
|
не. ну я имел в виду, что система может зайти в функцию обработки IRP два раза для разных IRP. то бишь пользовательский код внутри желательно потокобесопасным делать по возможности. особенно PnP всякие запросы...
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #44 : 24-04-2012 07:51 » |
|
не. ну я имел в виду, что система может зайти в функцию обработки IRP два раза для разных IRP. то бишь пользовательский код внутри желательно потокобесопасным делать по возможности. особенно PnP всякие запросы...
а кокай подход или метод применить для потокобезопасности (желательно пример... ыыы... ваще обнаглел?!, а то чет до меня туго доходит... )?!)))
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #45 : 24-04-2012 08:25 » |
|
не, пример вам не надо)) вы должны сами подумать в каком месте оно у вас нужно или не нужно) а вообще лучше полистайте Руссиновича, это в любом случае полезно будет) полистаете и сразу поймете что это такое и с чем его едят)
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #46 : 30-04-2012 11:31 » |
|
Ochkarik, Спасибо!! Разобрался... И осталось решить маленький вопрос... с передачей обьекта прерывания ДМА по хенделу... в nuMega драйвере есть такие строки: 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??? а вызывается функция в пользовательском приложении: // Создаем 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 секунд:ознакимившись с литературой, наварганил следующий код: 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
|
|
« Ответ #47 : 30-04-2012 13:12 » |
|
stack->Parameters.DeviceIoControl.Type3InputBuffer это указатель на буфер где лежит Event, а не сам Event)
PS где проверка status?! что за безобразие)
|
|
« Последнее редактирование: 30-04-2012 13:14 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #48 : 30-04-2012 14:08 » |
|
stack->Parameters.DeviceIoControl.Type3InputBuffer это указатель на буфер где лежит Event, а не сам Event) Это чуток не понял?! я что-то пропустил? PS где проверка status?! что за безобразие)
конечно имеется!))) if(status!=STATUS_SUCCESS) { status = STATUS_INVALID_PARAMETER; return status; // <- }
|
|
« Последнее редактирование: 30-04-2012 14:10 от sabbatazh »
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #49 : 30-04-2012 14:11 » |
|
HANDLE* phEvent = (HANDLE*) stack->Parameters.DeviceIoControl.Type3InputBuffer; при использовании - соответственно)
|
|
« Последнее редактирование: 30-04-2012 15:03 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #50 : 30-04-2012 14:32 » |
|
HANDLE* phEvent = (HANDLE*) stack->Parameters.DeviceIoControl.Type3InputBuffer; при использовании - соответственно)
не проходит привязка к приложению... status = STATUS_SUCCESS... ((( переделал инициализацию и все прошло: 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
|
|
« Ответ #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 уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #52 : 01-05-2012 08:28 » |
|
а как передаете в пользовательское? мапируете? в драйвер данные видит? Event до приложения доходит? Для этих целий используется структура и функция в ДЛЛ: struct XDSP_DMA_BUFFER_PTRS { ULONG* DMABufferUserPtr1; ULONG* DMABufferUserPtr2; ULONG* DMABufferUserPtr3; ULONG* DMABufferUserPtr4;
ULONG DMABufferPhysPtr1; ULONG DMABufferPhysPtr2; ULONG DMABufferPhysPtr3; ULONG DMABufferPhysPtr4; }; функция в пользовательском (ДЛЛ) приложении читающая параметры буферов ДМА //...
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; в драйвере эту же структуру заполняю следующим образом: 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
|
|
« Ответ #53 : 01-05-2012 14:04 » |
|
DMABufferPhysPtr1 - приложению передавать не стоит - приложению физику знать не надо, и делать с этим адресом - нечего. (или у вас структуры менять нельзя?) не вижу - как вы получаете MDL DmaBufferMemory1? и ГЛАВНОЕ: в каком контексте вы вызываете MmMapLockedPagesSpecifyCache()? надо делать обязательно в контексте приложения: то есть в IRP вызванном процессом приложения. в случае промежуточной библиотеки - подумайте где лучше)
RtlCopyMemory(pOutputBuffer, pBuffer, info); - ересь! и лишнее копирование. пишите код рационально)
PS лучше не форматируйте код табуляцией. оно потом криво выглядит) в настройках студии где то галку надо снять "use tab" или что то типа этого.
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #54 : 01-05-2012 17:39 » |
|
DMABufferPhysPtr1 - приложению передавать не стоит - приложению физику знать не надо, и делать с этим адресом - нечего. (или у вас структуры менять нельзя?) менять нельзя... дальше передаются в приложение эти данные... с какой целью не пойму! не вижу - как вы получаете MDL DmaBufferMemory1? 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 в нем есть такие строки 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
|
|
« Ответ #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 уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #56 : 01-05-2012 21:00 » |
|
Спасибо!!! Учту!! MmMapLockedPagesSpecifyCache(), у меня вызывается при инициализации драйвера и ДМА, а в приложение передается уже переменная от инициализации... исправлю... Добавлено через 2 дня, 7 часов, 18 минут и 50 секунд:Ochkarik, Исправил все недочеты... теперь передается все нормально... но данные пользовательская программа не читает... ((( Думал в прерывании дело... нет, прерывание верно выстовляется... нашел ошибку в: 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
|
|
« Ответ #57 : 04-05-2012 04:31 » |
|
событие в приложении выделяете? с автосбросом? само DpcForIsr вызывается?
проверяйте по шагам) корректность передачи хендла, вызов ObReferenceObjectByHandle, попробуйте просто событие передать - дойдет ли? должно все работать)
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #58 : 20-05-2012 16:10 » |
|
Здравствуйте уважаемые знатоки! Давненько я не выходил на связь… Наконец, добрался до драйвера! (неделю борюсь, все перепробывал) Значит… получается следующая петрушка… событие в приложении выделяете? с автосбросом? в ДЛЛ делается следующая штука: // Создаем 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
|
|
« Ответ #59 : 21-05-2012 09:46 » |
|
"объект kEvent - создается в драйвере... " - вот тут не понял?) WaitForSingleObject - что возвращает? TimeOut - как задан?
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #60 : 21-05-2012 14:55 » |
|
Ochkarik, я в ДЛЛ ни чего не изменял... она ведь со старым драйвером прекрасно работала, и єти все функции тоже работали.... "объект kEvent - создается в драйвере... " - вот тут не понял?) обьявлен и создается в драйвере... или не так? 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
|
|
« Ответ #61 : 21-05-2012 15:14 » |
|
формулировка: создание - это если б вы IoCreateSynchronizationEvent/IoCreateNotificationEvent в драйвере делали... а ObReferenceObjectByHandle - ссылку на уже существующий объект созданный в приложении получает. Добавлено через 5 минут и 25 секунд:и кстати получает не.... читайте описание функции ObReferenceObjectByHandle Добавлено через 5 минут и 31 секунду:PS третий и четвертый параметр. да и второй тоже... не факт. Добавлено через 29 секунд: status = ObReferenceObjectByHandle( hEvent, EVENT_MODIFY_STATE, *ExEventObjectType, KernelMode, (PVOID*)&kEvent, NULL);
|
|
« Последнее редактирование: 21-05-2012 15:28 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #62 : 22-05-2012 15:43 » |
|
Ochkarik, спасибо за помощь! Почитал... просветился!) WaitForSingleObject - что возвращает? возвращает значение отличное от WAIT_OBJECT_0... не пойму с чем это связано! TimeOut - как задан? задано 1000 ...
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #63 : 22-05-2012 15:49 » |
|
отличное - это наверное таймаут. не знаю как вы проверяете - ничего сказать не могу... попробуйте собрать минимальный тестовый пример и вызвать событие напрямую.
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
sabbatazh
Помогающий
Offline
|
|
« Ответ #64 : 22-05-2012 17:26 » |
|
Ochkarik, Вы как всегда правы!!!! изменил ДЛЛ прописал вместо TimeOut... INFINITE if(WaitForSingleObject(InterruptEventHandle, INFINITE)==WAIT_OBJECT_0) // TimeOut и все заработало!!! ))) Огромное Вам Спасибо!!!
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #65 : 22-05-2012 18:30 » |
|
ну что-ж... но все таки старайтесь избегать бесконечных ожиданий) всегда пожалуйста)
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
|