全新Linux教程-驱动大全-PCI和PCIe子系统-P5-PCIe设备的配置过程

1 PCIe系统硬件结构

注意:在pci设备中,可以通过引脚选中设备,但是在PCIe设备中,由于是端对端的配置过程(endpoint to endpoint)。PCIe桥中有很多端口,端口可以直接连接PCIe设备。在设备之间只有差分信号,并无其他引脚。无需选中,每个端口只有一个设备。但是,RC发出的信号在switch中需要选择端口

        配置时如何选中哪个p2p?配置后如何选中p2p?配置后用pci_addr地址范围选中端口就行了。首先,CPU 发出的地址经过RC, 会转换成add_pci。P2P也是一个设备,可以看作是一个桥,也有自己的BDF。RC传过来的地址,会经过每个P2P的判断,判断该地址在不在P2P处理的范围之内(图中,假设了每个P2P的地址范围分别是A-B,C-D,E-F)。

  • 那么是谁对P2P设备的地址访问做决定的呢?(谁写进去他的配置空间里),这里也是回答配置时如何选择哪个p2p?

接下来就回答第一个问题,在配置时应该给各个p2p如何配置地址访问,如何选中?

        在一开始的时候,host发出的地址肯定知道是自己要去配置还是去读取,他们的信息写在发出fmt和type字段里面(接下来就是要确定访问哪个目标设备,根据下面的TLP header的格式可以知道,确定哪个设备是需要知道Bus, Deveice, Function的)。但是我们一开始,并不知道每个设备的总线号,设备号,功能号,因此后面的字段都是未知的。

        但是,由于设备号是在硬件上就写死了的,例如RC后pcie桥的所有p2p桥,会从做到右一次进行编号0,1,2(因此在RC这一层也就是bus0这层,可以根据设备号来选择哪个设备)。

那么我们在最开始时,是如何确定BDF号的呢?首先,RC在制作的时候,在硬件上就对3个P2P写死了设备号,从小到大编号。0,1,2....等(所以这里的设备号又是能确定的?)。这几个设备会监测总线0上的信号,发现传过来的包属于cfgread0或者configread1时,此时就是要进行配置读写。

host桥发出事务层的包TLP时,通过TLP头部格式。如果是读取当前bridge,在事务层中的head有一个head字段,直接配置cfgrd0即可。如果需要经过bridge,则配置cfgrd1。意味着总线上传输的信号包括:Bus Dev Fun和Reg。--没太看懂

 

2 PCIe系统软件层次

从软件的角度,我们只关心事务层。在事务层传输中,我们需要关心

  • 要做什么:内存读、内存写、IO读、IO写、配置读、配置写以及消息总线事务和原子操作等总事务。这相当于事务层的分类。
  • 内存读写/io读写:哪个地址?
  • 配置读写:哪个“Bus/device/function/register”
  • 数据

3 事务层TLP格式

前面我们大概知道一个TLP主要由三部分组成:头+data+digest。头部包含了最重要的信息。不同的TLP事务层(前面提到的内存读写 IO读写 配置读写等),其头部完成不同。它包括了TLB事务类型,路由信息等等。data的长度为:0-1024DW。在PCIe 2.1规范中引入了Local TLP Prefix和EP-EP Prefex。他们的作用处理在设备之间处理消息传递。

3.1Posted和Non-posted && Split总线事务

Post的意思是"邮寄"、"投递"。PCIe是一种高速数据传输接口,它有两种数据传送方式:posted和non-posted。

posted传送方式是指发送端发送数据后,不需要等待接收端的确认信号,就可以继续发送下一个数据包。这种传送方式的速度非常快,但可能会出现数据丢失或错误,因为发送端没有等待接收端的确认信号。non-posted传送方式是指发送端需要等待接收端的确认信号,才能继续发送下一个数据包。这种传送方式的速度比posted传送方式稍慢,但可以保证数据的完整性和准确性。在实际应用中,当数据的可靠性比速度更加重要时,通常会选择non-posted传送方式;而当速度比可靠性更加重要时,则会选择posted传送方式。

PCIe有两类事务:

  • Posted:主设备访问目标设备时,主设备发出信号后就不再理会后续过程,也就是"发射后不管"。使用这种方式,在数据未到达目标设备前,主设备就可以结束当前操作,效率更高。适用于"内存写"等场合。
  • Non-Posted:主设备访问目标设备时,主设备发出信号后必须等待后续结果。比如"内存读",必须得到返回的数据,才能结束当前操作。PCIe总线使用split传送方式处理所有Non-post总线事务。

在PCIe系统中:

  • Posted:内存写
  • Non-Posted:内存读、IO读、IO写、配置读、配置写
  • 对于Non-Posted,使用Split传送方式
    • Split含有:分离
    • 被拆分为两部分,发出请求报文、得到完成报文

Split总线事务:

Split总线事务是指将一个PCIe总线事务拆分成多个步骤进行处理的过程。通俗来说,就是将一个大的数据传输任务分成多个小的任务来分别完成。在PCIe系统中,当一个设备需要进行数据传输时,它会向总线控制器发出一个请求,请求占用总线进行数据传输。如果总线控制器发现总线正在被其他设备使用,那么它就会将这个请求拆分成多个步骤,分别进行处理,直到完成整个数据传输任务。Split总线事务的过程中,每一步都会占用总线一定的时间,所以整个数据传输过程的时间会比较长。但是,由于Split总线事务可以避免总线的占用时间过长而导致其他设备无法使用总线的情况,从而提高了PCIe总线的效率。总之,Split总线事务是PCIe系统中为了提高总线效率而采用的一种拆分数据传输任务的技术。

3.2TLP通用格式

Fmt和Type字段确认当前TLP使用的总线事务。TLP头是大小由3个双字或者4个双字组成。

  • Fmt[2:0]的具体表格如下:0位代表是3个双字还是4格 双字,1位代表是否带有数据,第三位1代表保留。
  • Type[4:0]的具体格式如下:表示了存储读写,IO读写,配置读写等。

下图来自《PCI Express_ Base Specification Revision 4.0 Version 0.3 ( PDFDrive )》。

3.3TLP头部

TLP的完整格式如下:根据fmt和type来确定是读配置还是写配置。通过BDF来确定目标。

4 配置和RC直连的设备

4.1怎么访问直连的设备

RC本身就是一个桥,要去访问跟桥直接相连的设备,用CfgRd0类型的TLP:

* Fmt和Type取值为0b00, 0b00100,表示:Configuration Read Type 0

* TLP中设置有"Bus/Device/Funciton/Register"

* 提问:上图红圈中是设备,怎么知道它自己的Bus号是0,Device分别是0、1、2?

* 红圈中的设备都是在RC内部,它们的Device号是硬件里写死的(hard-coded)

* 当这些设备监测到Bus0上的TLP是CfgRd0后,忽略TLP中的Bus,比对TLP中的Device

* 如果Device吻合,就回应TLP

4.2配置end-point

配置endpoint的完整格式。

5 配置示例

5.1必备知识

5.1.1PCIe设备的配置寄存器

PCI/PCIe设备、桥,它们的配置寄存器前面若干字节格式是一样的,可以从里面的"Header Type"分辨:(1)它是普通设备,还是桥;(2)它是单功能设备,还是多功能设备:所谓功能,就是Function,一个物理设备可以有多个功能(例如可以转IIC或者串口,可以通过功能号指定当前设备的功能),也就有多个逻辑设备;如下图第7位所示。

一般的PCI/PCIe设备,它的配置寄存器格式如上上图的"Type 0 Header",在PCIe系统中这类设备被称为Endpoint。

PCI/PCIe桥,它的配置寄存器格式如上上图的"Type 1 Header",对于PCI/PCIe桥,里面的由三项重要的总线号:

  • Pirmary Bus Number:上游总线号
  • Secondary Bus Number:自己的总线号
  • Subordinate Bus Number:下游总线号的最大数值

5.1.2 type 0configure request

如果要配置的设备,就在当前总线上,即目标设备的Bus号等于当前桥的Secondary Bus Number,那么在当前总线(即Secondary Bus Number)上传输的就是"Type 0 Configuration Request":

  • TLP格式如下图所示
  • 不会穿过桥

5.1.3 Type 1 Configuration Request

如果要配置的设备,不在当前总线上,但是在它下面的总线上,即:

  • 目标设备的Bus号大于当前桥的Secondary Bus Number,
  • 目标设备的Bus号小于或等于当前桥的Subordinate Bus Number,

那么在当前总线(即Secondary Bus Number)上传输的就是"Type 1 Configuration Request":

  • TLP格式如下图所示
  • 会穿过桥
  • 到达设备时,跟设备直接连接的桥会把它转换为"Type 0 Configuration Request"

5.2配置过程示例

5.2.1硬件拓扑结构

以下图中的设备的配置过程为例,给大家做示范。深度优先扫描。

5.2.2配置过程演示(Bus3的dev0设备)

下文中BDF表示Bus,Device,Function,用这三个数值来表示设备。

1. 软件设置Host/PCI Bridge的Secondary Bus Number为0,Subordinate Bus Number为255(先设置为最大,后面再改)。primary无所谓。

2. 从Bus 0开始扫描(发出配置0的读,读到A的配置寄存器):先尝试读到BDF(0,0,0)设备的Vendor ID,如果不成功表示没有这个设备,就尝试下一个设备BDF(0,1,0)。一个桥下最多可以直接连接32个设备,所以会尝试32次:Device号从0到31。**注意**:在Host/PCI Bridge中,这些设备的Device号是硬件写死的。所有device的硬件号会在代码中通过一个宏写死,然后依次遍历这些devices。先扫描到A设备号,然后读它的配置寄存器。

3. 步骤2读取BDF(0,0,0)设备(即使图中的A)时,发现它的Header Type是01h,表示它是一个桥、单功能设备

4. 发现了设备A是一个桥,配置它:

* Primary Bus Number Register = 0:它的上游总线是Bus 0

* Secondary Bus Number Register = 1:从它发出的总线是Bus 1

* Subordinate Bus Number Register = 255:先设置为最大,后面再改

5. 因为发现了桥A,执行"深度优先"的配置过程:先去枚举A下面的设备,再回来枚举跟A同级的B

6. 软件读取BDF(1,0,0)设备(就是设备C)的Vendor ID,成功得到Vendor ID,表示这个设备存在。

7. 它的Header Type是01h,表示这是一个桥、单功能设备。

8. 配置桥C:

* Primary Bus Number Register = 1:它的上游总线是Bus 1

* Secondary Bus Number Register = 2:从它发出的总线是Bus 2

* Subordinate Bus Number Register = 255:先设置为最大,后面再改

9. 继续从桥C执行"深度优先"的配置过程,枚举Bus 2下的设备,从BDF(2,0,0)开始

10. 读取BDF(2,0,0)设备(就是设备D)的Vendor ID,成功得到Vendor ID,表示这个设备存在。

11. 它的Header Type是01h,表示这是一个桥、单功能设备。

12. 配置桥D:

* Primary Bus Number Register = 2:它的上游总线是Bus 2

* Secondary Bus Number Register = 3:从它发出的总线是Bus 3

* Subordinate Bus Number Register = 255:先设置为最大,后面再改

13. 继续从桥D执行"深度优先"的配置过程,枚举Bus 2下的设备,从BDF(3,0,0)开始

14. 读取BDF(3,0,0)设备的Vendor ID,成功得到Vendor ID,表示这个设备存在。

15. 它的Header Type是80h,表示这是一个Endpoing、多功能设备。

16. 软件枚举这个设备的所有8个功能,发现它有Function0、1

17. 软件继续枚举Bus 3上其他设备(Device号1~31),没发现更多设备

18. 现在已经扫描完桥D即Bus 3下的所有设备,它下面没有桥,所以桥D的Subordinate Bus Number等于3。扫描完Bus 3后,回退到上一级Bus 2,继续扫描其他设备,从BDF(2,1,0)开始,就是开始扫描设备E。

19. 读取BDF(2,1,0)设备(就是设备E)的Vendor ID,成功得到Vendor ID,表示这个设备存在。

20. 它的Header Type是01h,表示这是一个桥、单功能设备。

21. 配置桥E:

* Primary Bus Number Register = 2:它的上游总线是Bus 2

* Secondary Bus Number Register = 4:从它发出的总线是Bus 4

* Subordinate Bus Number Register = 255:先设置为最大,后面再改

22. 继续从桥D执行"深度优先"的配置过程,枚举Bus 4下的设备,从BDF(4,0,0)开始

23. 读取BDF(4,0,0)设备的Vendor ID,成功得到Vendor ID,表示这个设备存在。

24. 它的Header Type是00h,表示这是一个Endpoing、单功能设备。

25. 软件继续枚举Bus 4上其他设备(Device号1~31),没发现更多设备

26. 已经枚举完设备E即Bus 4下的所有设备了,更新设备E的Subordinate Bus Number为4。然后继续扫描设备E的同级设备:Bus=2,Device从2到31,发现Bus 2上没有这些设备。

27. 软件更新设备C即Bus 2的桥,把它的Subordinate Bus Number设置为4。然后继续扫描设备C的同级设备:Bus=1,Device从1到31,发现Bus 1上没有这些设备。

28. 软件更新设备A即Bus 1的桥,把它的Subordinate Bus Number设置为4。然后继续扫描设备A的同级设备:Bus=0,Device从1到31,发现Bus 0上的设备B。

29. 配置桥B:

* Primary Bus Number Register = 0:它的上游总线是Bus 0

* Secondary Bus Number Register = 5:从它发出的总线是Bus 5

* Subordinate Bus Number Register = 255:先设置为最大,后面再改

30. 再从桥B开始,执行"深度优先"的配置过程。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python连接数据库1

1、建立简单的数据库连接(前提是有数据库) from pymysql import Connection connConnection(host localhost, #主机名 /ip地址 127.0.0.1port3306, #端口,默认为这个userroot, #账户名password123456 #密码,自己的密码 ) #打印相…

施耐德 M340 PWM1 功能块使用方法

功能块帮助文档:《EcoStruxure™ Control Expert - 控制 , 功能块库》https://www.schneider-electric.cn/zh/download/document/33003687K01000/输出处理 --> PWM1:脉宽调制 功能块样式、引脚 EN BOOL 输入。1使能功能块,0不使能功能块…

14.基础乐理-音级、基本音级、变化音级

音级: 乐音体系中的每一个音,都叫 音级。 基本音级: 基本音级是 CDEFGAB 它们七个,在钢琴上使用白键展示的,没有任何升降号、没有任何重升重降号的。 变化音级: 除了 CDEFGAB 这七个音,都叫变化…

利用Python进行大规模数据处理

👽发现宝藏 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 利用Python进行大规模数据处理:Hadoop与Spark的对比 随着数据量的不断增长&…

web网站搭建实验

综合练习:请给openlab搭建web网站 网站需求: 1.基于域名www.openlab.com可以访问网站内容为 welcome to openlab!!! 2.给该公司创建三个子界面分别显示学生信息,教学资料 和缴费网站,基于,www.openlab.com/data网站…

Android RecyclerView的LayoutManager配置

RecyclerView的item布局方式依赖于其配置的布局管理器。不同的布局管理器可以实现不同的界面效果。 LayoutManager介绍 RecyclerView可以通过setLayoutManager设置布局管理器,该方法的源码如下: /*** Set the {link LayoutManager} that this RecyclerV…

JAVA 项目<果园之窗>_1

这几天有空看能不能把水果店管理系统整出来,目标是整个网页版本的,以我的电脑做服务器,数据存在mysql中 以我目前的理解整个项目大致可分为前端部分、后端部分、数据库部分,也就这三个部分 目前打开并运行了一个别人的项目&#…

Linux下SPI设备驱动实验:验证读写SPI设备中数据的函数功能

一. 简介 前面文章实现了 SPI设备驱动框架,并在此基础上添加了字符设备驱动框架,实现了读 / 写SPI设备中数据的函数,文章如下: Linux下SPI设备驱动实验:向SPI驱动框架中加入字符设备驱动框架代码-CSDN博客 Linux下…

2024年学浪的缓存怎么导出来

在自我成长的道路上,越来越多的朋友选择通过精选课程来提升自己。然而,面对那些服务期限有限的课程,怎样才能把握住知识的光芒,让它照亮未来的每一个角落?本文就教大家如何利用工具下载学浪app平台的课程 工具我已经打…

【ARM 裸机】I.MX 启动方式之启动头文件 2

接上一节:【ARM 裸机】I.MX 启动方式之启动头文件 1; 2.3、DCD DCD,Device Configuration Data ,就是配置 6ULL 寄存器的,DCD 数据最大限制 1768 字节; CCGR0 是不是很熟悉?对,在…

C++奇迹之旅:深入理解赋值运算符重载

文章目录 📝赋值运算符重载🌠 运算符重载🌉特性 🌠 赋值运算符重载🌠传值返回:🌠传引用赋值:🌉两种返回选择🌉赋值运算符只能重载成类的成员函数不能重载成全…

用Gold-yolo模块改进yolov8模型

gold-yolo论文: https://arxiv.org/pdf/2309.11331.pdf gold-yolo代码: https://github.com/huawei-noah/Efficient-Computing/tree/master/Detection/Gold-YOLO 一 gold模块简介 Gold-Yolo是华为诺亚方舟实验室2023年发布的工作,主要优化检…

Linux程序的地址空间,进程终止

个人主页:点我进入主页 专栏分类:C语言初阶 C语言进阶 数据结构初阶 Linux C初阶 算法 欢迎大家点赞,评论,收藏。 一起努力,一起奔赴大厂 一.程序的地址空间 1.1程序的地址空间的引入 我们知道frok可以创建…

重塑我们对随机性在计算中的作用的理解

2023年图灵奖,最近刚刚颁给普林斯顿数学教授 Avi Wigderson!作为理论计算机科学领域的领军人物,他对于理解计算中的随机性和伪随机性的作用,作出了开创性贡献。 Avi Wigderson 的履历 自 1999 年以来,Wigderson 一直担…

Python五子棋VS人机对战

上一次编写了一个python五子棋游戏,但是属于玩家之间的对战。今天介绍五子棋和人机对战。本博文目的是教学和一些毕业设计。 目前电脑下棋逻辑算法还是比较简单的,不能和市面上五子棋相提并论,请大家理想对待! 代码: import pygame import sys import tkinter as tk fro…

再拓信创版图-Smartbi Insight V11与东方国信CirroData数据库完成兼容适配认证

近日,思迈特商业智能与数据分析软件 [简称:Smartbi Insight] V11与北京东方国信科技股份有限公司 (以下简称东方国信)CirroData-OLAP分布式数据库V2.14.1完成兼容性测试。经双方严格测试,两款产品能够达到通用兼容性要…

python语言零基础入门——注释、print()函数、input()函数

目录 一、注释 1.块注释 2.行内注释 3.多行注释 二、打印变量 1.print()函数:输出/打印指定内容 2.input()函数:输入指定内容 三、编程题:个人名片 一、注释 1.块注释 以#开始,直到本行结束都是注释为了保证代码的可读性…

初步学习node.js文件模块

环境已安装好; 写一个read1.js如下; var fs require("fs"); var data ;// 创建一个流 var stream1 fs.createReadStream(test1.jsp); stream1.setEncoding(UTF8);// 绑定data事件 stream1.on(data, function(mydata) {data mydata; });/…

Unity ECS

一:前言 ECS与OOP不同,ECS是组合编程,而OOP的理念是继承 E表示Entity,每个Entity都是一个有唯一id的实体。C表示Component,内部只有属性,例如位置、速度、生命值等。S表示System,驱动实体的行为…

Leetcode. 12 整数转罗马数字

罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例…