PCI设备内存操作函数总结
1. ExAllocatePool()
函数说明:
ExAllocatePool allocates pool memory of the specified type and returns a pointer to the allocated
block.
函数定义:
PVOID ExAllocatePool(
__in POOL_TYPE PoolType,
__in SIZE_T NumberOfBytes
);
代码中用来分配设备描述DMA adepter设备的特性(DEVICE_DESCRIPTION),作为参数传递给IoGetDmaAdapter()函数。在调用IoGetDmaAdapter()函数之前就要对PDEVICE_DESCRIPTION结构进行指定各种特性。
实际中这样使用:
PDEVICE_DESCRIPTION DeviceDescription = (PDEVICE_DESCRIPTION) ExAllocatePool
(PagedPool, sizeof(DEVICE_DESCRIPTION));
2. RtlZeroMemory()
函数说明:
The RtlZeroMemory routine fills a block of memory with zeros, given a pointer to the block and the length, in bytes, to be filled.
函数定义:
VOID RtlZeroMemory(
__in VOID UNALIGNED *Destination,
__in SIZE_T Length
);
3. IoGetDmaAdapter()
函数说明:
The IoGetDmaAdapter routine returns a pointer to the DMA adapter structure for a physical device object.
函数定义:
struct _DMA_ADAPTER* IoGetDmaAdapter(
__in_opt PDEVICE_OBJECT PhysicalDeviceObject,
__in struct _DEVICE_DESCRIPTION *DeviceDescription,
__out PULONG NumberOfMapRegisters
);
实际代码中这样使用:
ULONG NumberOfMapRegisters=100;
pdx->DmaAdapter=IoGetDmaAdapter(pdx->NextStackDevice,DeviceDescription,&NumberOfMapRegisters);// NextStackDevice在AddDevice函数中已经attach了。
4. AllocateCommonBuffer()
函数说明:
The AllocateCommonBuffer routine allocates memory and maps it so that it is simultaneously accessible from both the processor and a device for DMA operations。
函数定义:
PVOID AllocateCommonBuffer(
__in PDMA_ADAPTER DmaAdapter,
__in ULONG Length,
__out PPHYSICAL_ADDRESS LogicalAddress,
__in BOOLEAN CacheEnabled
);
注:第一个参数是IoGetDmaAdapter()返回的,第三个参数是自己顶一顶一个物理地址类型,用来接收分配得到的物理地址首址。
返回值:返回值为虚拟地址,供上层使用
实际代码中这样使用:
pdx->descAddress=pdx->allocateCommonBuffer(pdx->DmaAdapter,(ULONG)DESC_ADDRESS*PORT_NUM,&pdx->DescLogicalAddress,FALSE);
附:使用该函数必不可少的会使用下面的函数
pdx->DmaAdapter=IoGetDmaAdapter(pdx->NextStackDevice,DeviceDescription,&NumberOfMapRegisters);
//创建一个DMA适配器
pdx->allocateCommonBuffer=*pdx->DmaAdapter->DmaOperations->AllocateCommonBuffer;
//分配连续的物理内存DMA函数
pdx->freeCommonBuffer = *pdx->DmaAdapter->DmaOperations->FreeCommonBuffer;
//释放连续的物理内存DMA函数
pdx->putDmaAdapter=*pdx->DmaAdapter->DmaOperations->PutDmaAdapter;
//释放DMA Adapter对象
当通过AllocateCommonBuffer()分配得到地址之后需要把这个地址分成两部分来处理,与硬件打交道的需要用LogicAddress 与 应用程序打交道需用 Virtual Address.
最好将AllocateCommonBuffer()函数取得的这两个地址保存到设备扩展中特定的变量中(根据内存块的用处),便于以后操作。可以这样做:
pdx->RxDescVirBase=(PCHAR)pdx->descAddress;
pdx->RxDescPhyBase=(ULONG)(pdx->DescLogicalAddress.LowPart); //物理地址
WRITE_REGISTER_ULONG( (PULONG)&pdx->pHBARegs->RxAddr_des_0,pdx->rx_fc_des
c_buf_phy[0]+16);
WRITE_REGISTER_ULONG( (PULONG)&pdx->pHBARegs->RxAddr_des_addr0_ptr,pdx->r
x_fc_desc_buf_phy[0]+4);
注意前面的 +16 和 +4 实际分别代表美一块内存的的偏移位置,由于我们定义了这块内存的结构,并在里面布局,+16 其实代表了struct rx_fc_ctl_tab 结构中的 struct rx_fc_desc_entity entity[RX_FC_DESC_NUM] 域,这里又是一个结构,也就是我们最终会用到的“描述符”。注意:我们这里的操作是将一个地址写到一个寄存器,这个地址必须是物理地址,也就是前面说的LogicAddress。这里pHBARegs是通过pdx->pHBARegs=(PHBA_REGS)pdx->RegsBase;
获得的,也就是在CmResourceTypeMemory传过来时解析,代表硬件提供的DMA寄存器首址。
对于硬件的初始化就是通过WRITE_REGISTER_ULONG()函数来完成,针对设备的起始地址来进行偏移,自己定义结构来匹配各个寄存器的内容,注意这个自己定义的结构一定要严格跟硬件寄存器相同,一bit都不能差。
PCI设备内存操作函数总结的更多相关文章
- c++ void,内存操作函数
void的含义 void的字面意思是“无类型”, void * 则为“无类型指针”, void * 可以指向任何类型的数据 void几乎只有“注释”和限制程序的作用,因为从来没有人会定义一个void变 ...
- c#读写共享内存操作函数封装
原文 c#读写共享内存操作函数封装 c#共享内存操作相对c++共享内存操作来说原理是一样,但是c#会显得有点复杂. 现把昨天封装的读写共享内存封装的函数记录下来,一方面希望给需要这块的有点帮助,另一方 ...
- Delphi中复制带有String的记录结构时不能使用Move之类的内存操作函数
请看下面的代码: program TestRecord; {$APPTYPE CONSOLE} uses SysUtils, Math; type TRecordA = record Na ...
- 内存操作函数memmove,memcpy,memset
通过字符串的学习,我们知道字符串操作函数的操作对象是字符串,并且它的结束标志是结束符\0,当然这个说的是不 受限制的字符串函数.然而当我们想要将一段内存的数据复制到另一块内存时,我们不能使用字符串操作 ...
- C语言中内存操作函数
一.malloc/calloc 名称: Malloc/calloc 功能: 动态内存分配函数 头文件: #include <stdlib.h> 函数原形: void *malloc(s ...
- 自己实现内存操作函数memset(),memcmp(),memcpy(),memmove()
1.memset()内存设置函数(初始化) void *my_memset(void* dest, int c, size_t count) { assert(dest != NULL); char ...
- 【转】C内存操作函数
一.malloc/calloc 名称: Malloc/calloc 功能: 动态内存分配函数 头文件: #include <stdlib.h> 函数原形: void *malloc(si ...
- c语言学习之基础知识点介绍(十九):内存操作函数
一.malloc函数 /* 首先需要导入头文件 #include <stdlib.h> malloc void* malloc(n); n是字节大小 开辟堆空间,开辟的字节数以n为准 返回 ...
- Delphi 的内存操作函数(1): 给字符指针分配内存
马上能想到的函数有: GetMem AllocMem ReallocMem FreeMem GetMemory ReallocMemory FreeMemory New Dispose NewStr ...
随机推荐
- java类加载时执行顺序
源代码 class HelloA { public HelloA() { System.out.print("A"); } { System.out.print("B&q ...
- for in 在数组和json中
数组中也有for--in,相较于对象中的用法是有区别的:数组中 var arr = ['曹操','曹植','曹丕'] for(i in arr){ console.log(i) //0 1 2 con ...
- flask入门与发送邮件与QQ邮箱
前言: 快两个月没写博客了, 原因是懒了, 没有最初写博客那种看到阅读量上涨, 别人给自己文章点赞后的开心. 心态也发生了不少变化. 有机会再来写写. 前两个月我去厦门某公司实习, 本着去厦门玩一玩还 ...
- Matlab中图论工具箱的应用
Matlab图论工具箱的命令见表1 表1 matlab图论工具箱的相关命令 命令名 功能 graphallshortestpaths 求图中所有顶点对之间的最短距离 graphconncomp 找无 ...
- 编译预处理命令define
#include 包含指令 将一个源文件嵌入到当前源文件中该点处. #include<文件名> 按标准方式搜索,文件位于C++系统目录的include子目录下 #include" ...
- 正负样本比率失衡SMOTE
正负样本比率失衡SMOTE [TOC] 背景 这几天测试天池的优惠券预测数据在dnn上面会不会比集成树有较好的效果,但是正负样本差距太大,而处理这种情况的一般有欠抽样和过抽样,这里主要讲过抽样,过抽样 ...
- Spring Boot让开发如此简单
从html到asp后一直专注.net开发,从.net诞生到如今,从winform到webform,从asp.net到.net mcv,从.net mvc到.net core,从ado.net到linq ...
- Html5本地存储和本地数据库
一个网站如何能在客户的浏览器存储更多的数据呢? 在Html4的时代在浏览器端存储点网站个性化的数据,尤其是用户浏览器的痕迹,用户的相关数据等一般只能存储在Cookie中,但是大多是浏览器对于Cooki ...
- mac攻略(4) -- 使用brew配置php7开发环境(mac+php+apache+mysql+redis)
[http://www.cnblogs.com/redirect/p/6131751.html] 网上有很多文章都是错误的,因为是copy别人的,作者没有自己亲测,不仅不能给新手提供帮助,还会产生严重 ...
- apache服务器主域名跳转www域名
为集中网站权重,有时候我们需要把www域名跳转到主域名,或者主域名跳转到www域名. apache服务器如何实现主域名跳转www域名: 打开网站根目录下.htaccess文件,没有的话新建一个上传至网 ...