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...
|
|
|
|