GetScatterGatherList seems not worked

Hello,
I want to use Direct I/O to implement DMA on my own driver, but it seems doesn’t work. Here’s my steps(For some reasons, I can not choose the way of WDF’s Dmatransaction):
1, allocate DMA adaptor during the driver init. DEVICE_DESCRIPTION dd; RtlZeroMemory(&dd, sizeof(dd)); dd.Version = DEVICE_DESCRIPTION_VERSION2; dd.Master = TRUE; dd.ScatterGather = TRUE; dd.InterfaceType = PCIBus; dd.MaximumLength = MAXIMUM_TRANSFER_LENGTH; dd.Dma64BitAddresses = TRUE;
ULONG NumberOfMapRegisters = 100;
adapter = IoGetDmaAdapter(WdfDeviceWdmGetPhysicalDevice(DevExt->Device), &dd, &NumberOfMapRegisters);
KdPrint((“DMA Adapter can afford %d Map Registers”, NumberOfMapRegisters));
if (!adapter) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, “WdfDmaEnablerCreate failed: %!STATUS!”, status); return STATUS_NDIS_ADAPTER_NOT_FOUND; }
DevExt->DmaChannel[i].DmaAdaptor = adapter;
2, Make a DeviceIOContorl with Direct I/O #define PCIe_IOCTL_CREATE_DMA_CHANNEL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_DIRECT_FROM_HARDWARE, FILE_ANY_ACCESS)
3, In EvtIoDeviceControl routine PDEVICE_OBJECT pDevice = WdfDeviceWdmGetPhysicalDevice(DevExt->Device); status = WdfRequestRetrieveInputWdmMdl(Request, &mdl); virtualAddress = MmGetMdlVirtualAddress(mdl); length = MmGetMdlByteCount(mdl); status = adapter->DmaOperations->GetScatterGatherList( adapter, pDevice, mdl, virtualAddress, length, SGListExcution, DevExt, TRUE );4, In SGListExcution, get the SGList to my device’s DMA engine dteVA = (PDMA_TRANSFER_ELEMENT)devExt->ReadCommonBufferBase; dteLA = (devExt->ReadCommonBufferBaseLA.QuadPart + sizeof(DMA_TRANSFER_ELEMENT)); for (i = 0; i < SgList->NumberOfElements; i++) {
dteVA->LogicalAddr = SgList->Elements[i].Address.QuadPart; dteVA->Length = SgList->Elements[i].Length;
KdPrint((“[Element %d]LogicalAddr: %llx, Length:%llu”, i, dteVA->LogicalAddr, dteVA->Length));
// Reserved dteVA->Status = 0xFFFF; dteVA->VirturalAddr = 0;
offset += SgList->Elements[i].Length;
// // If at end of SgList, then set LastElement bit in final NTE. // if (i == SgList->NumberOfElements - 1) { dteVA->NextDescAddr = 0; break; } else { dteVA->NextDescAddr = dteLA; }

//Adjust the next DMA_TRANSFER_ELEMEMT
dteVA++; dteLA += sizeof(DMA_TRANSFER_ELEMENT);
KdPrint((“dteVA is %llx, dteLA is %llx”, dteVA, dteLA)); } After doing this, I enable my device to write data to the physical address. But there’s no data found after the divice finish writing. my user space buffer is still nothing.
I don’t know in which part the problem occurs?
Thank you

Have you tried WdfDmaEnablerCreate and
then using WdfDmaEnablerWdmGetDmaAdapter? What is preventing you from
using the WDF DMA? I had a complex DMA setup that I was able to port to
KMDF from WDM. Check out the PLX9x5x sample for insight.

  • Phil

On Sat, Oct 22, 2016 at 7:29 AM, lizzoe wrote:

>
> Hello,
>
> I want to use Direct I/O to implement DMA on my own driver, but it seems
> doesn’t work. Here’s my steps(For some reasons, I can not choose the way
> of WDF’s Dmatransaction):
>
> 1, allocate DMA adaptor during the driver init.
> DEVICE_DESCRIPTION dd;
> RtlZeroMemory(&dd, sizeof(dd));
> dd.Version = DEVICE_DESCRIPTION_VERSION2;
> dd.Master = TRUE;
> dd.ScatterGather = TRUE;
> dd.InterfaceType = PCIBus;
> dd.MaximumLength = MAXIMUM_TRANSFER_LENGTH;
> dd.Dma64BitAddresses = TRUE;
>
> ULONG NumberOfMapRegisters = 100;
>
> adapter = IoGetDmaAdapter(WdfDeviceWdmGetPhysicalDevice(DevExt->Device),
> &dd, &NumberOfMapRegisters);
>
> KdPrint((“DMA Adapter can afford %d Map Registers”,
> NumberOfMapRegisters));
>
> if (!adapter)
> {
> TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
> “WdfDmaEnablerCreate failed: %!STATUS!”, status);
> return STATUS_NDIS_ADAPTER_NOT_FOUND;
> }
>
> DevExt->DmaChannel[i].DmaAdaptor = adapter;
>
> 2, Make a DeviceIOContorl with Direct I/O
> #define PCIe_IOCTL_CREATE_DMA_CHANNEL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804,
> METHOD_DIRECT_FROM_HARDWARE, FILE_ANY_ACCESS)
>
> 3, In EvtIoDeviceControl routine
> PDEVICE_OBJECT pDevice = WdfDeviceWdmGetPhysicalDevice(DevExt->Device);
> status = WdfRequestRetrieveInputWdmMdl(Request, &mdl);
> virtualAddress = MmGetMdlVirtualAddress(mdl);
> length = MmGetMdlByteCount(mdl);
>
> status = adapter->DmaOperations->GetScatterGatherList(
> adapter,
> pDevice,
> mdl,
> virtualAddress,
> length,
> SGListExcution,
> DevExt,
> TRUE
> );
> 4, In SGListExcution, get the SGList to my device’s DMA engine
> dteVA = (PDMA_TRANSFER_ELEMENT)devExt->ReadCommonBufferBase;
> dteLA = (devExt->ReadCommonBufferBaseLA.QuadPart +
> sizeof(DMA_TRANSFER_ELEMENT));
> for (i = 0; i < SgList->NumberOfElements; i++) {
>
> dteVA->LogicalAddr = SgList->Elements[i].Address.QuadPart;
> dteVA->Length = SgList->Elements[i].Length;
>
> KdPrint((“[Element %d]LogicalAddr: %llx, Length:%llu”, i,
> dteVA->LogicalAddr, dteVA->Length));
>
> // Reserved
> dteVA->Status = 0xFFFF;
> dteVA->VirturalAddr = 0;
>
> offset += SgList->Elements[i].Length;
>
> //
> // If at end of SgList, then set LastElement bit in final NTE.
> //
> if (i == SgList->NumberOfElements - 1)
> {
> dteVA->NextDescAddr = 0;
> break;
> }
> else
> {
> dteVA->NextDescAddr = dteLA;
> }
>
>
> //Adjust the next DMA_TRANSFER_ELEMEMT
>
> dteVA++;
> dteLA += sizeof(DMA_TRANSFER_ELEMENT);
>
> KdPrint((“dteVA is %llx, dteLA is %llx”, dteVA, dteLA));
> }
>
> After doing this, I enable my device to write data to the physical
> address. But there’s no data found after the divice finish writing.
> my user space buffer is still nothing.
>
> I don’t know in which part the problem occurs?
>
> Thank you
>
> — NTDEV is sponsored by OSR Visit the list online at: MONTHLY seminars
> on crash dump analysis, WDF, Windows internals and software drivers!
> Details at To unsubscribe, visit the List Server section of OSR Online at

On Oct 22, 2016, at 4:29 AM, lizzoe wrote:
>
> I want to use Direct I/O to implement DMA on my own driver, but it seems doesn’t work. Here’s my steps(For some reasons, I can not choose the way of WDF’s Dmatransaction):
> …
> 4, In SGListExcution, get the SGList to my device’s DMA engine

Where do you do that? You haven’t shown that code. Somewhere, you have to send the physical address of the common buffer to a hardware register, and then write another hardware register to trigger the DMA. You should then get an interrupt when the DMA is complete. Are all of those things happening?

It you do get the DMA complete interrupt, then there are two possibilities: either you are setting up the DMA descriptors improperly, or your hardware is broken. Have you dumped the whole descriptor to the debugger output so you can confirm the contents exactly?

Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

I mean that the Scatter/Gather list I get from GetScatterGatherList Routine is wrong. SgList->Elements[i].Length has even 2Mb size.

After receive device’s Write complete interrupt, user space buffer is still no data valid.

Now I use DMA Enabler and DMA transaction rewrite the driver , and then get the correct SGList on my own EvtProgramReadDma callback routine. User application can also get the correct data.

I just wondered what has gone wrong while I user GetScatterGatherList.

xxxxx@sina.com

From: Tim Roberts
Date: 2016-10-24 05:54
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] GetScatterGatherList seems not worked
On Oct 22, 2016, at 4:29 AM, lizzoe wrote:
>
> I want to use Direct I/O to implement DMA on my own driver, but it seems doesn’t work. Here’s my steps(For some reasons, I can not choose the way of WDF’s Dmatransaction):
> …
> 4, In SGListExcution, get the SGList to my device’s DMA engine

Where do you do that? You haven’t shown that code. Somewhere, you have to send the physical address of the common buffer to a hardware register, and then write another hardware register to trigger the DMA. You should then get an interrupt when the DMA is complete. Are all of those things happening?

It you do get the DMA complete interrupt, then there are two possibilities: either you are setting up the DMA descriptors improperly, or your hardware is broken. Have you dumped the whole descriptor to the debugger output so you can confirm the contents exactly?

Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


NTDEV is sponsored by OSR

Visit the list online at: http:

MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers!
Details at http:

To unsubscribe, visit the List Server section of OSR Online at http:</http:></http:></http:>