Часть кода тут пропущена, вот полностью функция
[code]
BOOLEAN
EvtProgramReadDma(
IN WDFDMATRANSACTION Transaction,
IN WDFDEVICE Device,
IN WDFCONTEXT Context,
IN WDF_DMA_DIRECTION Direction,
IN PSCATTER_GATHER_LIST SgList
)
{
PDEVICE_EXTENSION devExt;
size_t offset;
ULONG i;
UNREFERENCED_PARAMETER( Context );
UNREFERENCED_PARAMETER( Direction );
devExt = PLxGetDeviceContext(Device);
WdfInterruptAcquireLock( devExt->Interrupt );
//временно останавляваю диспетчер
{
union {
DISP_CONTROL bits;
ULONG ulong;
} DispCtrl;
DispCtrl.ulong =
READ_REGISTER_ULONG( (PULONG) &devExt->Regs->ControlDisp );
DispCtrl.bits.DispStop = TRUE;
WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->ControlDisp,
DispCtrl.ulong );
}
//заполняем таблицу дескпипторов
for (i=0; i < SgList->NumberOfElements; i++) {
WRITE_REGISTER_ULONG ((PULONG) &devExt->Regs->ReadAddr, 0х7000000);
WRITE_REGISTER_ULONG ((PULONG) &devExt->Regs->WriteAddr, SgList->Elements[i].Address.LowPart);
WRITE_REGISTER_ULONG ((PULONG) &devExt->Regs->Length, SgList->Elements[i].Length);
{
union {
DESC_CONTROL bits;
ULONG ulong;
} DescCtrl;
DescCtrl.ulong =
READ_REGISTER_ULONG( (PULONG) &devExt->Regs->ControlDesc );
//последний пакет
if (i==SgList->NumberOfElements-1)
{
DescCtrl.bits.TransferCOMP_IRQ = TRUE;
}
else
{
DescCtrl.bits.DoneEarly = TRUE;
}
//при выставлении бита Go данные скидываются в дескрипторное FIFO
DescCtrl.bits.Go = TRUE;
WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->ControlDesc,
DescCtrl.ulong );
}
}
//запускаю диспетчер
{
union {
DISP_CONTROL bits;
ULONG ulong;
} DispCtrl;
DispCtrl.ulong =
READ_REGISTER_ULONG( (PULONG) &devExt->Regs->ControlDisp );
DispCtrl.bits.DispStop = FALSE;
WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->ControlDisp,
DispCtrl.ulong );
}
WdfInterruptReleaseLock( devExt->Interrupt );
return TRUE;
}
[/code]
Насколько я понимаю, что как только что-то появляется в фифо (бит Descriptor Buffer Empty обнуляется), то и передача запускается. Но на всякий случай останавливаю диспетчер, заполняю дескрипторы и обратно запускаю.
В offset заносится количество уже переданных битов. Извините, я немного изменил уже тот кусочек кода, теперь там смещение внутри BAR0. (так же и должно быть, будто система понимает, что начальные адреса относятся именно к устройству? т.е. задавая адрес 0х7000000, читаются или записываются данные расположенные по смещению 0х7000000 внутри платы.).
У меня тоже есть подозрения, что контроллеру не доступны данные физические адреса, но есть одна особенность. Сегодня с помощью MmAllocateContiguousMemory выделял буфер, устраивал обмен данными между BAR0 устройства и этим буфером - работает. И самое интересное, что физические адреса из построенного системой scatter\gather списка и физические адреса выделенного с помощью MmAllocateContiguousMemory буфера примерно равны, т.е. не скажешь, что между ними такая большая разница, что по одним (буфер выделенный с помощью MmAllocateContiguousMemory) запись и чтение идет нормально, а по другим (сформированный инфраструктурой из запроса scatter\gather список ) пустота и не пишет. Будто страницы не те). И вот то ли реально физические адреса не те, либо контроллер не может с ними работать (но это в этом сомневаюсь).
Стоит попробовать поставить ограничение на адрес, но как это сделать? MmAllocateContiguousMemory выделяет буфер с заданными ограничениями, но как связать его с запросом?
Если делать так, то все работает, но к DMA это не имеет никакого отношения.
[code]
//получает буфер вывода запроса ввода-вывода.
status = WdfRequestRetrieveOutputBuffer( Request,
(size_t)Length,
&configurationDescriptor,
NULL );
//копируем данные из BAR0 в буфер вывода
status = WdfMemoryCopyToBuffer( outputBuff,
0,
AddrBAR0,
Length, );
[/code]
Попробовать выделить так буфер, а потом с помощью IoAllocateMdl и MmBuildMdlForNonPagedPool получить его MDL, а потом с полученным MDL, соответствующим этому буферу вызывать BuildScatterGatherList или GetScatterGatherList? Но это вроде бред какой-то)) (вопрос не в тему: почему написано, что вы ответили в 16:18, а я увидел это только в 20:18? у нас 4 часа разницы? )