IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> pcie设备bar地址空间映射到用户空间的方式 -> 正文阅读

[游戏开发]pcie设备bar地址空间映射到用户空间的方式

该程序通过指定pcie设备的vendor id和device id能够将设备的bar空间映射到用户空间,用户空间可以通过映射后的地址对bar进行读写操作,方便驱动调试。

代码如下:

#include <errno.h>
#include <getopt.h>
#include <fcntl.h>
#include <inttypes.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include <dirent.h>
#include <libgen.h>
#include <linux/fs.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <signal.h>
#include <ctype.h>
#include <termios.h>


typedef unsigned long long __u64;

#define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \
  __LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0)

#define MAP_SIZE 4096UL
#define MAP_MASK (MAP_SIZE - 1)


#define SEARCH_ROOT_DIR     "/sys/devices"///pci0000:00/0000:00:03.0/0000:04:00.0/0000:05:01.0/0000:06:00.0"
#define MAIN_DEV_ID_FILE    "vendor" 
#define SUB_DEV_ID_FILE     "device"
#define VIRADDR_FILE        "resource"
#define MAX_FILE_NAME_LONG 255
#define MAX_DIR_PATH_LONG  255


int pci_get_attrvalue_by_file(__u64 *pValue, char *fileName, __u64 region)
{
    FILE * fp = NULL;
    char buf[1024] = {0};
    if(0 != access(fileName,F_OK))
        return -1;
    fp = fopen(fileName, "rb");
    if(fp)
    {
        while(fgets(buf,1024,fp))
        {
        	if (region == 0)
            {
        		fclose(fp);
				__u64 tmpVal = (__u64)strtoll(buf, NULL, 16);
				*pValue = tmpVal;
				return 0;
            }
			region--;
        }
		fclose(fp);
    }
    return -1;
}

int pci_get_bar_phyaddr_by_id(__u64 *pValue, __u64 mainDevId, __u64 subDevId, __u64 region, char *pDirPath)
{
    __u64 value = 0;
    char fileName[MAX_FILE_NAME_LONG+1] = {0};
    
    memset(fileName, 0, MAX_FILE_NAME_LONG);
    snprintf(fileName,MAX_FILE_NAME_LONG,"%s/%s", pDirPath ,MAIN_DEV_ID_FILE);
    if(pci_get_attrvalue_by_file(&value, fileName, 0) || value != mainDevId)
        return -1;
        
    memset(fileName, 0, MAX_FILE_NAME_LONG);
    snprintf(fileName,MAX_FILE_NAME_LONG,"%s/%s", pDirPath ,SUB_DEV_ID_FILE);
    if(pci_get_attrvalue_by_file(&value, fileName, 0) || value != subDevId)
        return -1;
        
    memset(fileName, 0, MAX_FILE_NAME_LONG);
    snprintf(fileName,MAX_FILE_NAME_LONG,"%s/%s", pDirPath ,VIRADDR_FILE);
    if(0 == pci_get_attrvalue_by_file(&value, fileName, region))
    {
        *pValue = value;
        return 0;
    }
    return -1;
}



int pci_get_bar_by_traversal_dir( __u64 *pOutValue, char *dirName, __u64 mainDevId, __u64 subDevId, __u64 region)
{
    DIR   *pDir = NULL;
    struct dirent *pDirent = NULL;
    __u64 addr = 0;
    int ret = -1;
    if( 0 == pci_get_bar_phyaddr_by_id(&addr, mainDevId, subDevId, region, dirName ))
    {
        *pOutValue = addr;
        return 0;
    }
    else
    {
        if( (pDir =opendir(dirName))==NULL )
            return -1;
        while( NULL != (pDirent = readdir(pDir)) )
        {
            if(4 == pDirent->d_type)//dir
            {
                char subDirName[MAX_FILE_NAME_LONG+1] = {0};
                if(0 == strcmp(pDirent->d_name,".") || 0 == strcmp(pDirent->d_name,".."))
                    continue;
                snprintf(subDirName,MAX_FILE_NAME_LONG,"%s/%s", dirName,  pDirent->d_name);
                if(0 == pci_get_bar_by_traversal_dir( pOutValue, subDirName,  mainDevId,  subDevId, region))
                {
                    ret = 0;
                    break;
                }
            }
        }
        closedir(pDir);
    }
    return ret;
    
}


int pci_get_bar_phyaddr( __u64 *pOutValue, __u64 mainDevId, __u64 subDevId, __u64 region)
{
    return pci_get_bar_by_traversal_dir(pOutValue, SEARCH_ROOT_DIR, mainDevId, subDevId, region);
}

int main(int argc, char **argv)
{
	void *membase=NULL;
    __u64 target=0;
	int mmap_fd;
	void *map_base; 
	__u64 mainDevId;
	__u64 subDevId;

	
	if(argc != 3)
	{
		printf("param error\n");
		return -1;
	}
	
	mainDevId = strtoll(argv[1],NULL,16);
	subDevId = strtoll(argv[2],NULL,16);

	
	if(pci_get_bar_phyaddr(&target, mainDevId,subDevId, 0))
	{
		fprintf(stderr, "pci_get_attrvalue_by_file mainDevId:0x%llx  subDevId:0x%llx err\n", mainDevId,subDevId);
		return -1;
	}
	printf("bar phyaddr:0x%llx\n",target);

	

    if((mmap_fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL;
    fflush(stdout);

    /* Map one page */ //将内核空间映射到用户空间
    map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, mmap_fd, target & ~MAP_MASK);
    if(map_base == (void *) -1) FATAL;
    printf("Memory mapped at address %p.\n", map_base); 
    fflush(stdout);

	
    membase = map_base + (target & MAP_MASK);
	printf("bar map virtual address %p.\n", map_base); 

	close(mmap_fd);
	return 0;
}

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-03-24 00:54:10  更:2022-03-24 00:56:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:33:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码