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;
}