DMA upon IOCTL request

Hello,

I’m working with WDK 7600.16385.1

My IOCTL request contains 2 fields:
UINT64 DestAddress; (Allocated by application)
UINT32 SourceAddress; (PCI offset from BAR0)
UINT32 DmaSize; (bytes)

Upon getting this request, the device driver has to initialite a DMA read from hardware into DestAddress.

In the IOCTL handler I have to call:
WdfDmaTransactionInitialize (devExt->ReadDmaTransaction,
EvtProgramReadDma, WdfDmaDirectionReadFromDevice, mdl, virtualAddress,
Size);

The 5th parameter is virtualAddress.
Can it be the virtual address sent from application ?

How can I get mdl ?
Should I use:
MmInitializeMdl (mdl, virtualAddress, DmaSize) ?

Thank you,
Zvika

Hello,

Application side

DeviceIoControl (hDevice, Code, pInBuf, InBufSize, pOutBuf, DmaSize, &ByteCounter, &Overlapped)
pOutBuf : Pointer to DMA destination. This is a virtual buffer allocated in the application
pInBuf: Pointer to struct that contains 2 UINT32:

  1. Offset inside PCI BAR. This is the data source
  2. DMA size
    InBufSize: sizeof (UINT32)*2

Device Driver side - IOCTL request handler

WdfRequestRetrieveOutputBuffer (Request, DataSize, &pOutBuffer, &Length);

mdl = IoAllocateMdl(pOutBuffer, DmaSize, FALSE, FALSE, NULL);

WdfDmaTransactionInitialize( devExt->ReadDmaTransaction,
PLxEvtProgramReadDma,
WdfDmaDirectionReadFromDevice,
mdl,
pOutBuffer,
Length);

WdfDmaTransactionExecute( devExt->ReadDmaTransaction,
WDF_NO_CONTEXT);

Can you please tell if the sequence is correct ?

Thank you,
Zvika

On Mon, May 29, 2017 at 10:33 AM, wrote:

> I’m working with WDK 7600.16385.1
>

Well I didn’t get any further than that. Why? It’s obsolete unless you for
some horrible reason need to build for XP.

Mark Roddy

On May 29, 2017, at 10:54 AM, xxxxx@gmail.com wrote:

Hello,

Device Driver side - IOCTL request handler

WdfRequestRetrieveOutputBuffer (Request, DataSize, &pOutBuffer, &Length);

How did you skip over WdfDmaTransactionInitializeUsingRequest? It will handle all of the buffer configuration for you.

mdl = IoAllocateMdl(pOutBuffer, DmaSize, FALSE, FALSE, NULL);

Again, how did you skip over WdfRequestRetrieveOutputWdmMdl? The WdfDmaTransactionInitialize example code even uses this to perform the exact same function. If you use WDTIUsingRequest, you won’t need this.

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

Hi Tim,

In the Plx9x5x sample, PLxEvtIoRead calls to: WdfDmaTransactionInitializeUsingRequest
I used this code.
It works great.
PLxEvtIoRead is called upon ReadFile in the application.

But in my case, this is an IOCTL handler.

How can WdfDmaTransactionInitializeUsingRequest “knows” what is the destination DMA virtual address ?

In my case, can I call WdfDmaTransactionExecute right after WdfDmaTransactionInitializeUsingRequest, like in Plx9x5x sample ?

Thank you,
Zvika

On May 29, 2017, at 8:05 PM, xxxxx@gmail.com wrote:

In the Plx9x5x sample, PLxEvtIoRead calls to: WdfDmaTransactionInitializeUsingRequest
I used this code.
It works great.
PLxEvtIoRead is called upon ReadFile in the application.

But in my case, this is an IOCTL handler.

How can WdfDmaTransactionInitializeUsingRequest “knows” what is the destination DMA virtual address ?

Exactly the same way it does in a "read’ request – from the output buffer address in the IRP.

In my case, can I call WdfDmaTransactionExecute right after WdfDmaTransactionInitializeUsingRequest, like in Plx9x5x sample ?

Yes.

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

Hi Tim,

I called to:
status = WdfDmaTransactionInitializeUsingRequest (devExt->ReadDmaTransaction, Request, PLxEvtProgramReadDma, WdfDmaDirectionReadFromDevice).

right after:
status = WdfRequestRetrieveInputBuffer (…)

This causes a blue screen.

For some reason, no dmp file is created. I’m running this under Windows Embedded 7 (64).

devExt->ReadDmaTransaction is calculated in PLxInitializeDMA taken from the sample code.

Thank you,
Zvika

I really, really, dislike that KMDF sample. Really dislike it. A lot.

Anyhow… Enable WDF Verifier, turn on verbose logging, examine the IFR.

In short Zvi, debug the problem. You’ve been around here long enough to know these steps.

Peter
PSR
@OSRDrivers

>How can WdfDmaTransactionInitializeUsingRequest “knows” what is the destination DMA virtual address ?

WdfRequestWdmGetIrp returns an IRP pointer. The MdlAddress member of the IRP is the address of the MDL that describes the buffer. MmGetMdlVirtualAddress returns the virtual address. This address may not be valid in the current thread’s context.

The DMA transaction type is determined by the IOCTL code’s method (METHOD_IN_DIRECT or METHOD_OUT_DIRECT).

Read these pages:

https://msdn.microsoft.com/en-us/library/windows/hardware/ff540663(v=vs.85).aspx

https://msdn.microsoft.com/en-us/library/windows/hardware/ff547107(v=vs.85).aspx

status = WdfRequestRetrieveInputBuffer (…)

This causes a blue screen.

Based on the code you posted, it looks like you are trying to perform a read operation while this thread is about IOCTL and DMA. Note that WdfRequestRetrieveInputBuffer cannot be used for a read operation. But are you using this API for a read or IOCTL request ?

Hello N.D,

Thank you for your reply.

I’m using IOCTL (and not ReadFile) because I have to “tell” the device driver from what HW address to do the DMA.

Currently, the IOCTL code is:
#define MODULE_READ_DATA_CODE CTL_CODE (FILE_DEVICE_UNKNOWN, 0x806, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

The output buffer is passed to the device driver by the 5th parameter in:
DeviceIoControl (hDevice, Code, pInBuf, InBufSize, pOutBuf, DmaSize,
&ByteCounter, &Overlapped)

An alternative: I can send an IOCTL request to set the DMA source before ReadFile.
But I think this way is not the cleanest one.

Best regards,
Zvika

On May 30, 2017, at 9:57 PM, xxxxx@gmail.com wrote:

Thank you for your reply.

I’m using IOCTL (and not ReadFile) because I have to “tell” the device driver from what HW address to do the DMA.

Currently, the IOCTL code is:
#define MODULE_READ_DATA_CODE CTL_CODE (FILE_DEVICE_UNKNOWN, 0x806, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

The output buffer is passed to the device driver by the 5th parameter in:
DeviceIoControl (hDevice, Code, pInBuf, InBufSize, pOutBuf, DmaSize,
&ByteCounter, &Overlapped)

Have you done any reading about ioctl codes? With METHOD_BUFFERED, there is only ONE buffer address passed to the driver. The app’s input data is copied in to that buffer before the request, and copied back out after the request. It’s the same memory.

For DMA, you obviously want METHOD_IN_DIRECT.

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

Hi Tim, N.D, All,

I changed to:
#define MODULE_READ_DATA_CODE CTL_CODE
(FILE_DEVICE_UNKNOWN, 0x806, METHOD_IN_DIRECT, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

But now, calling to:
WdfDmaTransactionInitializeUsingRequest (devExt->ReadDmaTransaction, Request, PlxEvtProgramReadDma, WdfDmaDirectionReadFromDevice);

returns: 0xC0000010 - STATUS_INVALID_DEVICE_REQUEST

Can you tell why ?

The goal of this IOCTL is to read data from HW.
So I think WdfDmaDirectionReadFromDevice is the right choise.

Thank you,
Zvika

Try METHOD_OUT_DIRECT.


The DmaDirection value must be WdfDmaDirectionReadFromDevice if:

• The request type is WdfRequestTypeRead
• The request type is WdfRequestTypeDeviceControl or WdfRequestTypeDeviceControlInternal and the I/O control code specifies a transfer type of METHOD_OUT_DIRECT

Hello,

I changed to METHOD_OUT_DIRECT.
And got a blue dump.

Here is the output of analyze:

********************************************************************************
********************************************************************************
Loading Dump File [C:\Users\990598\Downloads\010114-8283-01.dmp]
Mini Kernel Dump File: Only registers and stack trace are available

Symbol search path is: SRV*C:\MySymbols*http://msdl.microsoft.com/download/symbols
Executable search path is: C:\Windows\System32
Windows 7 Kernel Version 7601 (Service Pack 1) MP (8 procs) Free x64
Product: WinNt, suite: TerminalServer EmbeddedNT SingleUserTS
Built by: 7601.18741.amd64fre.win7sp1_gdr.150202-1526
Machine Name:
Kernel base = 0xfffff80002a06000 PsLoadedModuleList = 0xfffff80002c4a890
Debug session time: Wed Jan 1 11:24:33.266 2014 (UTC + 3:00)
System Uptime: 0 days 0:00:40.140
Loading Kernel Symbols



Loading User Symbols
Loading unloaded module list

*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************

Use !analyze -v to get detailed debugging information.

BugCheck 10D, {3, 57ff0f83e78, 1, fffffa800e6ce550}

Probably caused by : Wdf01000.sys ( Wdf01000!FxRequest::CompleteInternal+515 )

Followup: MachineOwner

0: kd> !analyze -v
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************

WDF_VIOLATION (10d)
The Kernel-Mode Driver Framework was notified that Windows detected an error
in a framework-based driver. In general, the dump file will yield additional
information about the driver that caused this bug check.
Arguments:
Arg1: 0000000000000003, Windows Driver Framework Verifier has encountered a fatal error.
In particular, an I/O request has been completed, but a framework
request object cannot be deleted because there are outstanding
references to the input buffer or the output buffer, or both. The
driver’s IFR will include details on the outstanding references.
Arg2: 0000057ff0f83e78, WDFREQUEST handle
Arg3: 0000000000000001, The number of outstanding references remaining on both buffers.
Arg4: fffffa800e6ce550, Reserved.

Debugging Details:

BUGCHECK_STR: 0x10D_3

CUSTOMER_CRASH_COUNT: 1

DEFAULT_BUCKET_ID: VERIFIER_ENABLED_VISTA_MINIDUMP

PROCESS_NAME: Consolex8.exe

CURRENT_IRQL: 0

LAST_CONTROL_TRANSFER: from fffff88000e68d55 to fffff80002a7aec0

STACK_TEXT:
fffff880064da348 fffff88000e68d55 : 000000000000010d 0000000000000003 0000057ff0f83e78 0000000000000001 : nt!KeBugCheckEx
fffff880064da350 0000000000000000 : 0000000000000000 0000000000000000 0000000000000000 0000000000000000 : Wdf01000!FxRequest::CompleteInternal+0x515

STACK_COMMAND: kb

FOLLOWUP_IP:
Wdf01000!FxRequest::CompleteInternal+515
fffff880`00e68d55 cc int 3

SYMBOL_STACK_INDEX: 1

SYMBOL_NAME: Wdf01000!FxRequest::CompleteInternal+515

FOLLOWUP_NAME: MachineOwner

MODULE_NAME: Wdf01000

IMAGE_NAME: Wdf01000.sys

DEBUG_FLR_IMAGE_TIMESTAMP: 5010aa89

FAILURE_BUCKET_ID: X64_0x10D_3_VRF_Wdf01000!FxRequest::CompleteInternal+515

BUCKET_ID: X64_0x10D_3_VRF_Wdf01000!FxRequest::CompleteInternal+515

Followup: MachineOwner

********************************************************************************
********************************************************************************

In WinDbg I put:
SRV*C:\MySymbols*http://msdl.microsoft.com/download/symbols

In the symbols path.

Can you please help ?

Thank you,
Zvika

xxxxx@gmail.com wrote:

I changed to METHOD_OUT_DIRECT.
And got a blue dump.

Here is the output of analyze:

Did you read the analysis? The WDF verifier practically wrote you an
essay telling you what you did wrong.


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