这一篇主要讲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,

本文深入解析queue.c中关于消息请求队列的处理,包括应用程序通信、DMA传输及MSI中断处理。重点讲解PCIe_EvtIoDeviceControl如何实现用户态与内核态的数据交换,DMA传输过程的详细步骤,以及中断回调PCIe_InterruptMessageService和PCIe_InterruptDpc的执行逻辑。此外,阐述EvtProgramDMA函数中针对特定板卡的DMA寄存器配置,并强调不同板卡可能需要调整的寄存器设置。
最低0.47元/天 解锁文章
1792

被折叠的 条评论
为什么被折叠?



