PCIe 访问 EP 配置空间,空间映射详解,BDF 计算偏移

访问 EP 的配置空间方法

  1. 内存映射
  2. IO 访问

内存访问配置空间

  1. 前置知识
    PCIe 设备的寻址是按照 BDF 即 Bus-Device-Function 来组织的。访问某个设备则需要根据BDF计算偏移地址。

  2. 两种不同的内存访问配置空间方法

    • 类 xilinx,基地址 + 偏移地址访问
// linux-5.10\drivers\pci\controller\pcie-xilinx.c
/* ECAM definitions */
#define ECAM_BUS_NUM_SHIFT		20
#define ECAM_DEV_NUM_SHIFT		12
/*** xilinx_pcie_map_bus - Get configuration base* @bus: PCI Bus structure* @devfn: Device/function* @where: Offset from base** Return: Base address of the configuration space needed to be*	   accessed.*/
static void __iomem *xilinx_pcie_map_bus(struct pci_bus *bus,unsigned int devfn, int where)
{struct xilinx_pcie_port *port = bus->sysdata;int relbus;if (!xilinx_pcie_valid_device(bus, devfn))return NULL;relbus = (bus->number << ECAM_BUS_NUM_SHIFT) |(devfn << ECAM_DEV_NUM_SHIFT);return port->reg_base + relbus + where;
}

这个函数是转换配置空间的地址,port->reg_base = devm_pci_remap_cfg_resource(dev, &regs); 从设备树获取的基地址,然后加上 bus->number 与 devfn 计算得到的偏移地址。这个地址可以直接通过 readl 与 writel 直接访问。

  • 类 designware,变基地址 + 偏移地址访问
static void __iomem *dw_pcie_other_conf_map_bus(struct pci_bus *bus,unsigned int devfn, int where)
{int type;u32 busdev;struct pcie_port *pp = bus->sysdata;struct dw_pcie *pci = to_dw_pcie_from_pp(pp);/** Checking whether the link is up here is a last line of defense* against platforms that forward errors on the system bus as* SError upon PCI configuration transactions issued when the link* is down. This check is racy by definition and does not stop* the system from triggering an SError if the link goes down* after this check is performed.*/if (!dw_pcie_link_up(pci))return NULL;busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |PCIE_ATU_FUNC(PCI_FUNC(devfn));if (pci_is_root_bus(bus->parent))type = PCIE_ATU_TYPE_CFG0;elsetype = PCIE_ATU_TYPE_CFG1;dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1,type, pp->cfg0_base,busdev, pp->cfg0_size);return pp->va_cfg0_base + where;
}static int dw_pcie_rd_other_conf(struct pci_bus *bus, unsigned int devfn,int where, int size, u32 *val)
{int ret;struct pcie_port *pp = bus->sysdata;struct dw_pcie *pci = to_dw_pcie_from_pp(pp);ret = pci_generic_config_read(bus, devfn, where, size, val);if (!ret && pci->num_viewport <= 2)dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1,PCIE_ATU_TYPE_IO, pp->io_base,pp->io_bus_addr, pp->io_size);return ret;
}static int dw_pcie_wr_other_conf(struct pci_bus *bus, unsigned int devfn,int where, int size, u32 val)
{int ret;struct pcie_port *pp = bus->sysdata;struct dw_pcie *pci = to_dw_pcie_from_pp(pp);ret = pci_generic_config_write(bus, devfn, where, size, val);if (!ret && pci->num_viewport <= 2)dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1,PCIE_ATU_TYPE_IO, pp->io_base,pp->io_bus_addr, pp->io_size);return ret;
}static struct pci_ops dw_child_pcie_ops = {.map_bus = dw_pcie_other_conf_map_bus,.read = dw_pcie_rd_other_conf,.write = dw_pcie_wr_other_conf,
};

分析 dw_pcie_other_conf_map_bus() 函数,这个是用来计算访问 EP 配置空间地址。同样也是通过 BDF 计算出 busdev 的偏移,但是它调用了 dw_pcie_prog_outbound_atu(busdev) 做了地址转换,所以它每次返回的转换后的地址都是 pp->va_cfg0_base + where,而 pp->va_cfg0_base 是固定的值,它是由 pp->va_cfg0_base = devm_pci_remap_cfgspace(dev, pp->cfg0_base, pp->cfg0_size); 从设备树里读出来的固定地址空间。

总结

两种 MEM 访问 EP 配置空间的方式都是通过基地址 + 偏移地址访问的。类 xilinx 的方式是全映射,需要 256M 的空间,将所有的 PCIe 设备的配置空间都映射到 CPU 的地址空间来。类 designware 则取巧,使用少量的 CPU 地址空间,但是每次访问之前需要重新映射 EP 的地址,使得相同的 CPU 地址空间可以放到的不同的 EP 设备的配置空间。
两种访问区别

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/175848.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

http1,https,http2,http3总结

1.HTTP 当我们浏览网页时&#xff0c;地址栏中使用最多的多是https://开头的url&#xff0c;它与我们所学的http协议有什么区别&#xff1f; http协议又叫超文本传输协议&#xff0c;它是应用层中使用最多的协议&#xff0c; http与我们常说的socket有什么区别吗&#xff1f; …

【ARM 嵌入式 C 入门及渐进 10 -- 冒泡排序 选择排序 插入排序 快速排序 归并排序 堆排序 比较介绍】

文章目录 排序算法小结排序算法C实现排序方法的稳定性 排序算法小结 C语言中常用的排序算法包括冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序。下面我们来一一介绍&#xff1a; 冒泡排序&#xff08;Bubble Sort&#xff09;&#xff1a;冒泡排序是通过比较相邻…

android 8.1 disable unsupported sensor

如果device不支持某种sensor,可以在android/frameworks/base/core/java/android/hardware/SystemSensorManager.java里将其disabled掉。以disable proximity sensor为例。 public SystemSensorManager(Context context, Looper mainLooper) {synchronized(sLock) {if (!sNativ…

MWeb Pro for Mac:博客生成编辑器,助力你的创作之旅

在当今数字化时代&#xff0c;博客已经成为了许多人记录生活、分享知识和表达观点的重要渠道。而要打造一个专业、美观且易于管理的博客&#xff0c;选择一款强大的博客生成编辑器至关重要。今天&#xff0c;我向大家推荐一款备受好评的Mac软件——MWeb Pro。 MWeb Pro是一款专…

flutter深研

https://www.douyin.com/video/7020336319058627853 关闭系统风扇 在 Windows 操作系统上安装和配置 Flutter 开发环境 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 下载Git - Downloading Package 推荐使用迅雷下载 系统配置要求 要想安装和运行 Flutter&#xf…

使用FastAPI部署Ultralytics YOLOv5模型

YOLO是You Only Look Once(你只看一次)的缩写&#xff0c;它具有识别图像中的物体的非凡能力&#xff0c;在日常应用中会经常被使用。所以在本文中&#xff0c;我们将介绍如何使用FastAPI的集成YOLOv5&#xff0c;这样我们可以将YOLOv5做为API对外提供服务。 Python有几个web框…

如何将 ruby 打包类似于jdk在另一台相同架构的机器上面开箱即用

需求 目前工作中使用到了ruby作为java 项目的中转语言&#xff0c;但是部署ruby的时候由于环境的不同会出现安装依赖包失败的问题&#xff0c;如何找到一种开箱即用的方式类似于java 中的jdk内置jvm这种方式 解决 TruffleRuby 完美解决问题&#xff0c;TruffleRuby 是使用 T…

基于STC系列单片机实现外部中断0控制按键调节定时器0产生PWM(脉宽调制)的功能

#define uchar unsigned char//自定义无符号字符型为uchar #define uint unsigned int//自定义无符号整数型为uint sbit PwmOut P1^0;//位定义脉宽调制输出为单片机P1.0脚 uchar PwmTimeCount;//声明脉宽调制时间计数变量 uchar PwmDutyCycle;//声明脉宽调制占空比变量 void Ti…

Apache服务的搭建与配置(超详细版)

前言 Apache是一种常见的Web服务器软件&#xff0c;广泛用于Linux和其他UNIX操作系统上。它是自由软件&#xff0c;可以通过开放源代码的方式进行自由分发和修改。Apache提供了处理静态和动态内容的能力&#xff0c;而且还支持多种编程语言和脚本&#xff0c;如PHP、Python和P…

python数据可视化

内容主要介绍了python模块matplotlib即seaborn数据可视化 matplotlib模块通过import matplotlib.pyplot as plt生成图形&#xff0c;如生成图形没展示&#xff0c;可调用plt.show()方法展示图形&#xff1b; 对于颜色属性设置&#xff0c;既可以使用十六进制颜色表达(#7777aa…

cdrx8和2020哪个版本更好用?有什么区别

经过多年的发展&#xff0c;cdr推出了很多优秀的版本&#xff0c;并顺应时代的发展更新了多项功能。随着cdr推出的软件版本增多&#xff0c;小伙伴们可选择的产品也在增多&#xff0c;那么该怎么选择呢&#xff1f;本文会给大家介绍cdrx8和2020的区别&#xff0c;CDRX8和2020哪…

Pytorch 猫狗识别案例

猫狗识别数据集https://download.csdn.net/download/Victor_Li_/88483483?spm1001.2014.3001.5501 训练集图片路径 测试集图片路径 训练代码如下 import torch import torchvision import matplotlib.pyplot as plt import torchvision.models as models import torch.nn as…

基于静电放电算法的无人机航迹规划-附代码

基于静电放电算法的无人机航迹规划 文章目录 基于静电放电算法的无人机航迹规划1.静电放电搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用静电放电算法来优化无人机航迹规划。 …

0基础学习PyFlink——用户自定义函数之UDF

大纲 标量函数入参并非表中一行&#xff08;Row&#xff09;入参是表中一行&#xff08;Row&#xff09;alias PyFlink中关于用户定义方法有&#xff1a; UDF&#xff1a;用户自定义函数。UDTF&#xff1a;用户自定义表值函数。UDAF&#xff1a;用户自定义聚合函数。UDTAF&…

1400*C. Team(模拟构造)

Problem - 401C - Codeforces 解析&#xff1a; 因为0不能相邻&#xff0c;所以0之间最少 n-1 个位置&#xff0c;最多 n1 个位置&#xff0c;如果 m<n-1显然不符题意。 并且1最多连续两个&#xff0c;所以 m>2*n2 同样不符题意。 其余情况构造即可 #include<bits/st…

【嵌入式】【GIT】如何迁移老的GIF到新的仓库时使用LFS功能并保持LOG不变

一、正常迁移流程 假设有仓库 ssh://old/buildroot-201902 需要迁移到新的仓库 ssh://old/buildroot-201902时,我们可以使用以下命令来完成: # 下载老的仓库 git clone ssh://old/buildroot-201902 # 向新的仓库上传所有的tags git push ssh://new/buildroot-201902 --tag…

【网络安全】Seeker内网穿透追踪定位

Seeker追踪定位对方精确位置 前言一、kali安装二、seeker定位1、ngrok平台注册2、获取一次性邮箱地址3、ngrok平台登录4、ngrok下载5、ngrok令牌授权6、seeker下载7、运行seeker定位8、运行隧道开启监听9、伪装链接10、用户点击&#xff08;获取定位成功&#xff09;11、利用经…

Rust-虽然9天过去了,结果是没有结果(Docker容器的端口映射问题)

​ 这篇文章收录于Rust 实战专栏。这个专栏中的相关代码来自于我开发的笔记系统。它启动于是2023年的9月14日。相关技术栈目前包括&#xff1a;Rust&#xff0c;Javascript。关注我&#xff0c;我会通过这个项目的开发给大家带来相关实战技术的分享。 前言 上上周了吧&#xf…

机器学习(六)构建机器学习模型

1.9构建机器学习模型 我们使用机器学习预测模型的工作流程讲解机器学习系统整套处理过程。 整个过程包括了数据预处理、模型学习、模型验证及模型预测。其中数据预处理包含了对数据的基本处理&#xff0c;包括特征抽取及缩放、特征选择、特征降维和特征抽样&#xff1b;我们将…

Linux的简介和环境搭建

简介 Linux是一套免费使用和自由传播的类Unix操作系统&#xff0c;是一个基于POSIX和Unix的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的Unix工具软件、应用程序和网络协议。它支持32位和64位硬件。Linux继承了Unix以网络为核心的设计思想&#xff0c;是一个…