驱动程序(6) WDF下DMA传输的驱动程序代码详细说明之queue.c

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

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这一篇主要讲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, 
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值