这一篇主要讲queue.c里对于消息请求队列的处理,涉及到了和应用程序的通信,同时为了以后的项目需求,也加入了DMA传输和传输完成后的MSI中断处理。
queue.c
/*++
Module Name: queue.c
Abstract:This file contains the queue entry points and callbacks.And it includes DeviceIoControl function.
Environment: Kernel-mode Driver Framework
Time: 20181015
--*/
#include "driver.h"
BOOLEAN DMATransaction(IN WDFQUEUE Queue, IN WDFREQUEST Request);
//BOOLEAN EvtProgramDMA(IN WDFDMATRANSACTION Transaction, IN WDFDEVICE Device, IN WDFCONTEXT Context, IN WDF_DMA_DIRECTION Direction, IN PSCATTER_GATHER_LIST SgList);
#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, PCIe_EvtIoDeviceControl)
#pragma alloc_text (PAGE, PCIe_EvtIoStop)
#endif
VOID
PCIe_EvtIoDeviceControl(
_In_ WDFQUEUE Queue,
_In_ WDFREQUEST Request,
_In_ size_t OutputBufferLength,
_In_ size_t InputBufferLength,
_In_ ULONG IoControlCode
)
/*++
Routine Description:
This event is invoked when the framework receives IRP_MJ_DEVICE_CONTROL request.
Arguments:
Queue - Handle to the framework queue object that is associated with the
I/O request.
Request - Handle to a framework request object.
OutputBufferLength - Size of the output buffer in bytes
InputBufferLength - Size of the input buffer in bytes
IoControlCode - I/O control code.
Return Value:
VOID
--*/
{
//PIRP pIrp;
//PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
//ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
PAGED_CODE();
KdPrintEx((DPFLTR_IHVAUDIO_ID, DPFLTR_ERROR_LEVEL, "Function 'EvtIoDeviceControl' begins\n"));
WDFDEVICE hDevice;
PDEVICE_CONTEXT pDeviceContext;
NTSTATUS status;
PVOID inBuffer;
PVOID outBuffer;
ULONG DmaStatus, DmaControl;
ULONG state;
ULONG i, j;
hDevice = WdfIoQueueGetDevice(Queue);
pDeviceContext = GetDeviceContext(hDevice); //获取设备上下文句柄
switch (IoControlCode)
{
//基于WDF框架下的DMA传输操作
case WDF_DMA:
KdPrintEx((DPFLTR_IHVAUDIO_ID, DPFLTR_ERROR_LEVEL, "Begin to execute WDF_DMA!\n"));
//获取从应用程序传递过来的数据,并打印出来
status = WdfRequestRetrieveInputBuffer(Request, sizeof(ULONG), &inBuffer, NULL);
if (!NT_SUCCESS(status))
{
WdfRequestComplete(Request, STATUS_UNSUCCESSFUL);
break;
}
state = *(ULONG*)inBuffer;
KdPrintEx((DPFLTR_IHVAUDIO_ID, DPFLTR_ERROR_LEVEL, "received data is %d\n\n", state));
ULONG length;
WDFDMATRANSACTION dmaTransaction;
dmaTransaction = pDeviceContext->DmaTransaction;
//测试DMA传输,先给BAR0一段空间赋值,然后将该段数据搬移
//循环给BAR0赋值,4个Byte编址为一个数,4096字节只能存1024个数
for (i = 0; i < 1024; i++)
{
WRITE_REGISTER_ULONG(WDF_PTR_ADD_OFFSET(pDeviceContext->MemBaseAddress0, i* 4), i );
//KdPrintEx((DPFLTR_IHVAUDIO_ID, DPFLTR_ERROR_LEVEL, "%d,", READ_REGISTER_ULONG(WDF_PTR_ADD_OFFSET(pDeviceContext->MemBaseAddress0, i* 4))));
}
//初始化MDL
PMDL BufferMdl;
//PVOID UserModeVirtualAddress, KernelModeVirtualAddress;
BufferMdl = IoAllocateMdl(pDeviceContext->CommonBufferBase, 4096, FALSE, FALSE, NULL);
MmBuildMdlForNonPagedPool(BufferMdl);
MmProbeAndLockPages(BufferMdl, KernelMode,