WdfDmaTransactionInitializeUsingRequest & WDFREQUEST

How a WdfRequest should be formatted for WdfDmaTransactionInitializeUsingRequest? I’m using WdfRequestCreate, WdfMemoryCreatePreallocated (with content of a buffer I want to DMA) and WdfIoTargetFormatRequestForWrite.

WdfDmaTransactionInitializeUsingRequest fails with c0000010 (invalid device request).

verifier log shows " Couldn’t retrieve mdl from WDFREQUEST…" Am I missing any steps above?

In your first post you referred to WdfRequestCreate, are you trying to do
this on a Create? There is no MDL on a create call, you really have to be
doing this operation on one of the calls referred to in the documentation
https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdfdma
transaction/nf-wdfdmatransaction-wdfdmatransactioninitializeusingrequest

Don Burn
Windows Driver Consulting
Website: http://www.windrvr.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Sunday, March 04, 2018 3:45 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] WdfDmaTransactionInitializeUsingRequest & WDFREQUEST

verifier log shows " Couldn’t retrieve mdl from WDFREQUEST…" Am I missing
any steps above?


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

If you are going to use a request in this context it is needs to have a valid current stack location. This means a request presented to you by a queue. A self created request that is formatted has valid NEXT stack location. Since you have the mdl, just call WdfDmaTransactionInitialize

d

Bent from my phone


From: xxxxx@lists.osr.com on behalf of xxxxx@gmail.com
Sent: Sunday, March 4, 2018 12:45:09 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] WdfDmaTransactionInitializeUsingRequest & WDFREQUEST

verifier log shows " Couldn’t retrieve mdl from WDFREQUEST…" Am I missing any steps above?


NTDEV is sponsored by OSR

Visit the list online at: https:

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

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

Hi Doron, the situation is I’ve to send a large buffer to the device. This buffer has a content read from a file. So, I’ve to create a request from scratch. Should I rather create a MDL and use WdfDmaTransactionInitialize?

>the situation is I’ve to send a large buffer to the device

So… you don’t REALLY need a WdfRequest? You just need a buffer and a DMA Transaction?

In that case, don’t build the Request. Just allocate the buffer and/or the MDL that describes the buffer, and WdfDmaTransactionInitialize… No Request required.

Peter
OSR
@OSRDrivers

Thanks Peter. Basic question. Do I need WdfCommonBuffer if MDL is used?

xxxxx@gmail.com wrote:

Thanks Peter. Basic question. Do I need WdfCommonBuffer if MDL is used?

It’s not an either/or.  You always need an MDL with
WdfDmaTransactionInitialize.  The question is, where did the buffer come
from?  What does the MDL point to?

If you have been handed a buffer, or you already allocated a buffer,
then you can create an MDL for it and pass it to WDTI, assuming you can
do scatter/gather.

If you can’t do scatter/gather, then you’ll need a common buffer.


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

Tim,

The buffer is allocated using ExAllocatePoolWithTag and filled with content read from a file.

mdl is created using IoAllocateMdl call with the above buffer

mdl is then passed to WDTI

A commonbuffer for write was allocated earlier in EvtDeviceAdd

I can’t do scatter/gather.

Now, my confusion, how is commonbuffer is used or connected with WdfDmaTransaction object? In EvtProgramDma, WdfDmaTransactionGetBytesTransferred returns 0 and the commonbuffer is empty.

xxxxx@gmail.com wrote:

The buffer is allocated using ExAllocatePoolWithTag and filled with content read from a file.

mdl is created using IoAllocateMdl call with the above buffer

mdl is then passed to WDTI

A commonbuffer for write was allocated earlier in EvtDeviceAdd

I can’t do scatter/gather.

Then you should fire your hardware engineers.   No PCIe design in the
21st Century should ever be built without scatter/gather.

Now, my confusion, how is commonbuffer is used or connected with WdfDmaTransaction object? In EvtProgramDma, WdfDmaTransactionGetBytesTransferred returns 0 and the commonbuffer is empty.

There’s no connection between them.  The common buffer is just another
way of allocating memory.  It only gets used if you use it, and right
now you aren’t using it.

Here’s what happens now.  You have your ExAllocatePoolWithTag (which, I
hope, is non-paged pool?) buffer, which is not physically contiguous. 
When you pass that to WdfDmaTransactionInitialize, it’s going to call
your callback multiple times, once for each page in the transfer.  Your
callback will set up and trigger the DMAs, one page at a time.  As you
get the DMA completion interrupts, you call
WdfDmaTransactionDmaCompleted, and KMDF will call your callback again
for the next page.  The common buffer is not involved.

As long as you have the common buffer, why don’t you just read the file
into the common buffer?  Then you can do the entire thing as one
transfer.  With a common buffer, there is really no need to use a
WdfDmaTransaction at all.


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

>> Then you should fire your hardware engineers
I wish I could :slight_smile:

>As long as you have the common buffer, why don’t you just read the file
>into the common buffer?? Then you can do the entire thing as one
>transfer.? With a common buffer, there is really no need to use a

Understood. To be clear, in this case, I don’t need WDTI and WDTE calls

Thanks Tim for the clarification

Well… no, that’s not true.

Even if your hardware doesn’t support scatter/gather, you can do packet-based DMA.

I’m now thoroughly lost with what the OP needs to do.

OP… instead of asking us one-line questions, can you please explain the overall goal you want to accomplish? Maybe then we can steer you in the right direction.

Sorry for being confused. But I am. And I want to help…

Peter
OSR
@OSRDrivers

Hi Peter, Trying to DMA 8K buffer of data read from a file. Needed clarification around on my attempt to use WdfDmaTransactionInitializeUsingRequest by creating WDFREQUEST from scratch. Needed further clarifications on using mdl & common buffer & WdfDmaTransaction and related APIs. Per Tim, I guess I can just read the content into a common buffer and DMA it without doing the WDF framework way at least for this scenario.

Thank you for that.

Who’s doing the reading? Does an application send you the data to be DMA’ed? That’s the normal workflow for a driver. App reads the file, app calls WriteFile on a handle that’s been opened to the device, the driver for that device does the DMA operation.

Peter
OSR
@OSRDrivers

In this case, the driver has to do read (fw config data) and DMA in D0Entry context.

No. Sorry. That’s not the right design. We don’t do DMA operations from within the EvtDeviceD0Entry Event Processing Callback. It just won’t work the way you expect.

Do you need interrupts to process your DMA (and know it’s done)? If so, you’ll need to start a worker thread from within your EvtDeviceD0EntryPostInterruptsEnabled Event Processing Callback.

But, there’s a bigger question. Longer term, how does your device handle I/O Requests? How does it deal with read and write requests? How does it setup its general DMA processing?

Peter
OSR
@OSRDrivers

Hi Peter, Yes, it is being done in EvtDeviceD0EntryPostInterruptsEnabled. Sorry, I replied quickly. The reads/writes will be handled very similar to how its done in the wdk sample (PLX9x5x)

xxxxx@gmail.com wrote:

Trying to DMA 8K buffer of data read from a file
In this case, the driver has to do read (fw config data) and DMA in D0Entry context.

If you’re only doing two pages, then this is trivially easy.   Get
yourself an 8k common buffer.  Read the file data directly into the
buffer.  Set up your DMA hardware and trigger the DMA.  All the
interrupt has to do is set a flag saying “DMA engine is now free”.

Does your hardware have a register-based interface to transfer this
data?  For a one-time transfer that small, you might as well just do
register pounding.  DMA isn’t buying you anything.


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

This. Absolutely.

In fact, do you *really* want to do this each time your hardware enters D0 state? Because, that’s what you’re effectively doing by targeting EvtDeviceD0EntryPostInterruptsEnabled.

If you don’t need the interrupts OR the DMA, you can do the one time only register pounding directly in EvtDevicePrepareHardware. *I* know it says not to fool with your hardware in this routine, but that guidance is somewhat out of style. You know that you’re in D0 on entry to EvtDevicePrepareHardware, and this happens to be a darn convenient place to do your one-time hardware initialization.

Alternatively, if you really need to do this with DMA and interrupts, I was going to suggest firing-off a worker thread, and just having it work the setup I/O into your “ordinary” DMA I/O path.

I, personally, would try to avoid using a unique DMA scheme for the configuration phase of your driver’s work. If your ordinary I/O path does packet-based DMA, and (again) if I absolutely needed to DMA the config data, I would try to do packet-based DMA in my config path. I would try to avoid allocating a Common Buffer and writing a bunch of DMA code strictly to handle the initialization. I don’t like debugging separate code paths when I can help it. And having two unique ways you handle DMA makes maintenance more confusing, as well.

Peter
OSR
@OSRDrivers