Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Home NTDEV
Before Posting...
Please check out the Community Guidelines in the Announcements and Administration Category.

More Info on Driver Writing and Debugging


The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.


Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/


KMDF Can't Create DMA Enabler Object with WdfDmaEnablerCreate

ret0ret0 Member Posts: 4

Hi folks,
I want to create a DMA driver in KMDF and the driver is not based on any physical device, that is to say it wouldn't configure any registers of a real DMA controller. However, I cannot create the DMA enabler object with WdfDmaEnablerCreate. WdfDmaEnablerCreate function always returns 0xC0000001 when configuring non-system profile in WDF_DMA_PROFILE. And using system DMA profiles(i.e. WdfDmaProfileSystem) leads to BSOD when doing WdfCommonBufferCreate.

I also want to ask, if a KMDF DMA driver can run without binding any physical device?

Thanks a lot.

Here is the code:

#include "driver.h"
#include "device.tmh"

#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, DmaTestCreateDevice)
#endif

NTSTATUS
DmaTestCreateDevice(
    _Inout_ PWDFDEVICE_INIT DeviceInit
    )
{
    WDF_OBJECT_ATTRIBUTES deviceAttributes;
    PDEVICE_CONTEXT deviceContext;
    WDFDEVICE device;
    WDF_DMA_ENABLER_CONFIG  dmaConfig;
    WDFDMAENABLER       DmaEnabler;

    WDFCOMMONBUFFER     CommonBuffer;
    PVOID               CommonBufferBase;
    PHYSICAL_ADDRESS    CommonBufferBaseLA;
    WDFDMATRANSACTION   DmaTransaction;

    NTSTATUS status;

    PAGED_CODE();

    WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT);

    deviceAttributes.SynchronizationScope = WdfSynchronizationScopeDevice;

    status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);

    if (NT_SUCCESS(status)) {

        deviceContext = DeviceGetContext(device);

        //
        // Initialize the context.
        //
        deviceContext->PrivateDeviceData = 0;

        //
        // Create DMAEnabler
        //
        WdfDeviceSetAlignmentRequirement(device, FILE_OCTA_ALIGNMENT);

        WDF_DMA_ENABLER_CONFIG_INIT(&dmaConfig, WdfDmaProfilePacket, MAXNLEN);

        status = WdfDmaEnablerCreate(device,
            &dmaConfig,
            WDF_NO_OBJECT_ATTRIBUTES,
            &DmaEnabler);

        if (!NT_SUCCESS(status)) {
            DbgPrint("WdfDmaEnablerCreate failed: status=0x%x\n", status);
            return status;
        }
        DbgPrint("WdfDmaEnablerCreate succeeded\n");

        status = WdfCommonBufferCreate(DmaEnabler,
            MAXNLEN,
            WDF_NO_OBJECT_ATTRIBUTES,
            &CommonBuffer);

        if (!NT_SUCCESS(status)) {
            DbgPrint("WdfCommonBufferCreate failed: status=0x%x\n", status);
            return status;
        }
        DbgPrint("WdfCommonBufferCreate succeeded\n");
        CommonBufferBase =
            WdfCommonBufferGetAlignedVirtualAddress(CommonBuffer);

        CommonBufferBaseLA =
            WdfCommonBufferGetAlignedLogicalAddress(CommonBuffer);

        RtlZeroMemory(CommonBufferBase, MAXNLEN);

        DbgPrint("CommonBuffer VA 0x%x ,LA 0x%x, Len 0x%x\n",
            CommonBufferBase,
            CommonBufferBaseLA.LowPart,
            WdfCommonBufferGetLength(CommonBuffer));


        status = WdfDmaTransactionCreate(DmaEnabler,
            WDF_NO_OBJECT_ATTRIBUTES,
            &DmaTransaction);

        if (!NT_SUCCESS(status)) {
            DbgPrint("WdfDmaTransactionCreate failed: status=0x%x\n", status);
        }
        DbgPrint("WdfDmaTransactionCreate status=%x\n", status);

        //
        // Create a device interface so that applications can find and talk
        // to us.
        //
        status = WdfDeviceCreateDeviceInterface(
            device,
            &GUID_DEVINTERFACE_DmaTest,
            NULL // ReferenceString
            );

        if (NT_SUCCESS(status)) {
            //
            // Initialize the I/O Package and any Queues
            //
            status = DmaTestQueueInitialize(device);
        }
    }

    return status;
}

Comments

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 13,498

    Of course it can't. How could it? If there's no hardware, then there's no bus, there are no physical addresses, and of course there's no hardware to perform the DMA. The DMA enabler requires strong interaction with the PCI bus driver.

    What do you think you would be achieving with "virtual" DMA?

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • ret0ret0 Member Posts: 4

    Tim,

    Of course it can't. How could it? If there's no hardware, then there's no bus, there are no physical addresses, and of course there's no hardware to perform the DMA. The DMA enabler requires strong interaction with the PCI bus driver.

    It's a great help to me, since I don't know about the internals of DMA enabler.

    What do you think you would be achieving with "virtual" DMA?

    I want to use this "virtual" DMA to configure the Intel CBDMA transferring data from memory to device. The target device has its own driver. I woulder if I can run the driver as a service(like NT driver) or non-pnp driver, which doesn't rely on any physical device.

    By the way, the docs of Microsoft say "The framework does not support system-mode DMA transfers on PC-based platforms", is this the cause of BSOD?

    Thanks.

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 13,498

    How are you going to get access to the device's memory, if you are not the driver? The resources for a piece of hardware are owned by the driver. You could possibly make a filter driver to get into the same stack, I suppose. You'd need to do that in order to get the physical addresses you need.

    However, if the driver isn't expecting anyone else to do transfers, it's not going to like you going behind its back. You'll be messing up its internal state.

    I thought Windows had added support for the system DMA controllers that Intel unwisely reintroduced in the mid-2010s, but it looks like that support does not extend to KMDF. Relying on a system DMA controller in a PC system is always going to be a problem, because it's a shared resources, and shared resources are not always available.

    https://docs.microsoft.com/en-us/windows-hardware/drivers/wdf/supporting-system-mode-dma

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • ret0ret0 Member Posts: 4

    Tim,
    you did me a big favor, thank you very much.

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 7,915

    (moving to the right topic... this isn't an Admin issue or an Annoucement)

    Peter Viscarola
    OSR
    @OSRDrivers

  • MBond2MBond2 Member Posts: 145

    Unwisely reintroduced? I’m not sure.

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 13,498

    I suppose I'm being snarky. System DMA will always be a scarce resource. That means you have to plan for it to be unavailable, and that means you might as well just skip it. If your device really needs DMA, make it a bus master.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 7,915
    edited July 24

    System DMA was reintroduced primarily to support SoC systems.

    It’s a scarce resource like Map Registers. The system DMA controller is shared. If it’s unavailable you queue for it, you don’t skip it.

    Peter

    Peter Viscarola
    OSR
    @OSRDrivers

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Kernel Debugging 30 Mar 2020 OSR Seminar Space
Developing Minifilters 15 Jun 2020 LIVE ONLINE
Writing WDF Drivers 22 June 2020 LIVE ONLINE
Internals & Software Drivers 28 Sept 2020 Dulles, VA