PCI 总线学习笔记(五)

PCI 总线学习系列,参考自
技术大牛博客: PCIe 扫盲系列博文连载目录篇
书籍:王齐老师的《PCI Express 体系结构导读》


下面的文章中加入了自己的一些理解和实际使用中遇到的一些场景,供日后查询和回忆使用

PCI 总线定义了两类配置请求, 一类是 Type 00h 配置请求, 另一类是 Type 01h 配置请求。 PCI 总线使用这些配置请求访问 PCI 总线树上的设备配置空间, 包括 PCI 桥和 PCI Agent 设备的配置空间。

  • Type 00h 配置请求:用于访问与 HOST 主桥或者 PCI 桥直接相连的 PCI Agent 设备或者 PCI 桥(仅能传递给目标设备,而不会被进一步转发)
  • Type 01h 配置请求: HOST 主桥或者 PCI 桥使用 Type 01h 配置请求, 需要至少穿越一个 PCI 桥, 访问没有与其直接相连的 PCI Agent 设备或者 PCI 桥(配置请求可以被进一步转发)

1、Type 01h 和Type 00h 配置请求

  在 PCI 总线中, 只有 PCI 桥能够接收 Type 01h 配置请求。Type 01h 配置请求不能直接发向最终的 PCI Agent 设备, 而只能由 PCI 桥将其转换为 Type 01h 继续发向其他 PCI 桥, 或者转换为 Type 00h 配置请求发向 PCI Agent 设备。

  以 x86 系统为例,在地址周期中, HOST 主桥使用配置读写总线事务, 将 CONFIG_ADDRESS 寄存器的内容复制到 PCI 总线的 AD [31∶0] 信号线中。 CONFIG_ADDRESS 寄存器与 Type 01h 配置请求的对应关系如下图所示
在这里插入图片描述

  从上图中可以发现, CONFIG_ADDRESS 寄存器的内容基本上是原封不动地复制到 PCI 总线的AD [31∶0] 信号线上的。 其中 CONFIG_ADDRESS 的 Enable 位不被复制, 而 AD 总线的第 0 位必须为 1, 表示当前配置请求是 Type 01h。

  当 PCI 总线接收到 Type01 配置请求时, 将寻找合适的 PCI 桥接收这个配置信息。 如果这个配置请求是直接发向 PCI 桥下的与之直接相连的 PCI 设备时, PCI 桥将接收这个 Type 01 配置请求,并将其转换为 Type 00h 配置请求; 否则 PCI 桥将当前 Type 01h 配置请求原封不动地传递给下一级 PCI 总线。

  如果 HOST 主桥或者 PCI 桥发起的是 Type 00h 配置请求, CONFIG_ADDRESS 寄存器与 AD [31∶0] 的转换如下图所示:
在这里插入图片描述

  此时处理器对 CONFIG_DATA 寄存器进行读写时, 处理器将 CONFIG_ADDRESS 寄存器中的 Function Number 和 Register Number 字段复制到 PCI 的 AD 总线的第10 ~2 位; 将 AD 总线的第 1~0 位赋值为 0b00。 PCI 总线在配置请求总线事务的地址周期根据 AD [1∶0] 判断当前配置请求是 Type 00h 还是 Type 01h。

如果 AD [1∶0] 等于 0b 00 表示是 Type 00h 配置请求, 如果 AD [1∶0] 等于 0b 01 表示是 Type 01h 配置请求

  而 AD [31∶11] 与 CONFIG_ADDRESS 的 Device Number 字段有关, 在 Type 00h 配置请求的地址周期中, AD [31∶11] 位有且只有一位为 1, 其中 AD [31∶11] 的每一位选通一个 PCI 设备的配置空间。 PCI 设备配置空间的片选信号是 IDSEL, 因此 AD[31∶ 11] 将与 PCI 设备的 IDSEL 信号对应相连

从这里可以知道, PCI 协议中的设备号,是由 PCI 设备的 IDSEL 信号线,与 PCI 总线上的地址线 AD[0 : 31] 的硬件连接关系确定的

1.1、总结

  上面讲解的东西,更多的是为了理解 PCI 协议,真正在 PCI 总线驱动开发上用到的不多。比较常用的就是配置 HOST 主桥发出的到底是 Type 00h 还是 Type 01h 配置请求。

  有些板卡,硬件上已经配置好 HOST 发出的到底是 Type 00h 还是 Type 01h 配置请求,我们无需关心。有些板卡更灵活,需要我们手动在软件上去配置,例如:当访问的 bus 号为当前 PCI 控制器起始 bus 号 + 1 时,使用 Type 00h 配置请求;否则就是 Type 01h 配置请求。了解了底层的原理,这里我们具体场景具体分析就行,不必拘泥。

1.2 代码实例

以 rk3568 为例:

static void __iomem *rk_pcie_ecam_map_bus(struct pci_bus *bus, unsigned int devfn, int where)
{
....../*  如果访问的是 root bus,使用 Type 00h,不需要转发;否则使用  Type 01h*/if (pci_is_root_bus(bus->parent))atu_type = PCIE_ATU_TYPE_CFG0;elseatu_type = PCIE_ATU_TYPE_CFG1;
......
}

以 Linux 源码中,dw IP 核代码为例:

static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,u32 devfn, int where, int size, u32 *val)
{
......if (bus->parent->number == pp->root_bus_nr) {type = PCIE_ATU_TYPE_CFG0;cpu_addr = pp->cfg0_base;cfg_size = pp->cfg0_size;va_cfg_base = pp->va_cfg0_base;} else {type = PCIE_ATU_TYPE_CFG1;cpu_addr = pp->cfg1_base;cfg_size = pp->cfg1_size;va_cfg_base = pp->va_cfg1_base;}
......
}

2、PCI 总线配置请求的转换原则

  当 CONFIG_ADDRESS 寄存器的 Enable 位为 1, 系统软件访问 CONFIG_DATA 寄存器时,HOST 主桥可以产生两类 PCI 总线配置读写总线事务, 分别为 Type 00h 和 Type 01h 配置读写总线事务。 在配置读写总线事务的地址周期和数据周期中,CONFIG_ADDRESS 和 CONFIG_DATA 寄存器中的数据将被放置到 PCI 总线的 AD 总线上。 其中 Type 00h 和 Type 01h 配置读写总线事务映射到 AD 总线的数据并不相同。

  其中 Type 00h 配置请求可以直接读取 PCI Agent 设备的配置空间, 而 Type 01h 配置请求在通过 PCI 桥时, 最终将被转换为 Type 00h 配置请求, 并读取 PCI Agent 设备的配置寄存器。 本节重点讲述 PCI 桥如何将 Type 01h 配置请求转换为 Type 00h 配置请求。

  首先 Type 00h 配置请求不会被转换成 Type 01h 配置请求, 因为 Type 00h 配置请求是发向最终 PCI Agent 设备, 这些 PCI Agent 设备不会转发这些配置请求。当 CONFIG_ADDRESS 寄存器的 Bus Number 字段为 0 时, 处理器对 CONFIG_DATA 寄存器操作时, HOST 主桥将直接产生 Type 00h 配置请求, 挂接在 PCI 总线 0 上的某个设备将通过 ID 译码接收这个 Type 00h 配置请求, 并对配置寄存器进行读写操作。 如果 PCI 总线上没有设备接收这个 Type 00h 配置请求, 将引发 Master Abort, 详情见 PCI 总线规范, 本节对此不做进一步说明。

  如果 CONFIG_ADDRESS 寄存器的 Bus Number 字段为 n ( n≠ 0), 即访问的 PCI 设备不是直接挂接在 PCI 总线 0 上的, 此时 HOST 主桥对 CONFIG_DATA 寄存器操作时, 将产生Type 01h 配置请求, PCI 总线 0 将遍历所有在这条总线上的 PCI 桥, 确定由哪个 PCI 桥接收这个 Type 01h 配置请求。如果 n 大于或等于某个 PCI 桥的 Secondary Bus Number 寄存器, 而且小于或等于 Subordinate Bus number 寄存器, 那么这个 PCI 桥将接收在当前 PCI 总线上的 Type 01 配置请求,并采用以下规则进行递归处理:

  1. 开始。
  2. 遍历当前 PCI 总线的所有 PCI 桥。
  3. 如果 n 等于某个 PCI 桥的 Secondary Bus Number 寄存器, 说明这个 Type 01 配置请求的目标设备直接连接在该 PCI 桥的 Secondary bus 上。 此时 PCI 桥将 Type 01 配置请求转换为 Type 00h 配置请求, 并将这个配置请求发送到 PCI 桥的 Secondary Bus 上, Secondary Bus 上的某个设备将响应这个 Type 00h 配置请求, 并与 HOST 主桥进行配置信息的交换,转 (5) 。
  4. 如果 n 大于 PCI 桥的 Secondary Bus Number 寄存器, 而且小于或等于 PCI 桥的 Subordinate Bus number 寄存器, 说明这个 Type 01 配置请求的目标设备不与该 PCI 桥的 Secondary Bus 直接相连, 但是由这个 PCI 桥下游总线上的某个 PCI 桥管理。 此时 PCI 桥将首先认领这个 Type 01 配置请求, 并将其转发到 Secondary Bus, 转 (2)。
  5. 结束。

3、PCI 总线树 Bus 号的初始化

参考 PCI 总线学习笔记(三)

4、PCI 总线 Device 号的分配

  一条 PCI 总线会挂接各种各样的 PCI 设备, 而每一个 PCI 设备在 PCI 总线下具有唯一的设备号。 系统软件通过总线号和设备号定位一个 PCI 设备之后, 才能访问这个 PCI 设备的配置寄存器。

  PCI 设备的 IDSEL 信号与 PCI 总线的 AD [31∶ 0] 信号的连接关系决定了该设备在这条 PCI 总线的设备号。 如上文所述, 每一个 PCI 设备都使用独立的 IDSEL 信号, 该信号将与 PCI 总线的 AD [31∶ 0] 信号连接, IDSEL 信号的含义见第 PCI 总线学习笔记(一)。

  在此我们简要回顾 PCI 的配置读写事务使用的时序。 如下图所示, PCI 总线事务由一个地址周期加若干个数据周期组成。 在进行配置读写请求总线事务时, C / BE# 信号线的值在地址周期中为 0x1010 或者为 0x1011, 表示当前总线事务为配置读或者配置写请求。 此时出现在 AD [31∶ 0] 总线上的值并不是目标设备的 PCI 总线地址, 而是目标设备的 ID 号, 这与 PCI 总线进行 I / O 或者存储器请求时不同, 因为 PCI 总线使用 ID 号而不是 PCI 总线地址对配置空间进行访问。
在这里插入图片描述
  如图 2-12 所示, 在配置读写总线事务的地址周期中, AD [10∶ 0] 信号已经被 Function Number 和 Register Number 使用, 因此 PCI 设备的 IDSEL 只能与 AD [31∶ 11] 信号连接。认真的读者一定可以发现在 CONFIG_ADDRESS 寄存器中 Device Number 字段一共有 5 位可以表示 32 个设备, 而 AD [31∶ 11] 只有 21 位, 显然在这两者之间无法建立一一对应的映射关系。 因此在一条 PCI 总线上如果有 21 个以上的 PCI 设备, 那么总是有几个设备无法与 AD [31∶ 11] 信号线连接, 从而 PCI 总线无法访问这些设备。 因为 PCI 总线在配置请求的地址周期中, 只能使用第 31 ~ 11 这些 AD 信号, 所以在一条总线上最多也只能挂接 21 个 PCI 设备。 这 21 个设备可能是从 0 到 20, 也可能是从 11 到 31 排列。 从而系统软件在遍历 PCI 总线时, 还是需要从 0 到 31 遍历整条 PCI 总线。

在这里插入图片描述

  在实际的应用中, 一条 PCI 总线能够挂接 21 个设备已经足够了, 实际上由于 PCI 总线的负载能力有限, 即便在总线频率为 33 MHz 的情况下, 在一条 PCI 总线中最多也只能挂接 10 个负载, 一条 PCI 总线所能挂接的负载详见表 1-1。 AD 信号线与 PCI 设备 IDSEL 线的连接关系如图 2-14 所示
在这里插入图片描述

  PCI 总线推荐了一种 Device Number 字段与 AD [31∶ 16] 之间的映射关系。 其中 PCI 设备 0 与 Device Number 字段的 0b00000 对应; PCI 设备 1 与 Device Number 字段的 0b00001 对应, 并以此类推, PCI 设备 15 与 Device Number 字段的 0b01111 对应。

  在这种映射关系之下, 一条 PCI 总线中, 与信号线 AD16 相连的 PCI 设备的设备号为 0;与信号线 AD17 相连的 PCI 设备的设备号为 1; 以此类推, 与信号线 AD31 相连的 PCI 设备的设备号为 15。 在 Type 00h 配置请求中, 设备号并没有像 Function Number 和 Register Number 那样以编码的形式出现在 AD 总线上, 而是与 AD 信号一一对应, 如图 2-12 所示。

  这里有一个原则需要读者注意, 就是对 PCI 设备的配置寄存器进行访问时, 一定要有确定的 Bus Number、 Device Number、 Function Number 和 Register Number, 这 “四元组” 缺一不可。 在 Type 00h 配置请求中, Device Number 由 AD [31∶ 11] 信号线与 PCI 设备 IDSEL 信号的连接关系确定; Function Number 保存在 AD [10∶ 8] 字段中; 而 Register Number 保存在 AD [7∶ 2] 字段中; 在 Type 01h 配置请求中, 也有完整的四元组信息。

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

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

相关文章

Spring Cloud Alibaba VS Spring Cloud

​​Spring Cloud Alibaba 与 Spring Cloud 组件对比​ ​​服务发现与注册中心​ 功能​​​Spring Cloud​​​Spring Cloud Alibaba​对比说明​​核心组件​EurekaNacosNacos 支持动态配置管理、健康检查更灵活,且提供 DNS 服务发现能力。​​​​健康检查​​…

Java—— 常见API介绍 第五期

JDK8以后新增的时间相关类 Date类ZoneId:时区Instant:时间戳ZoneDateTime:带时区的时间 日期格式化类 SimpleDateFormat DateTimeFormatter:用于时间的格式化和解析 日历类 Calendar LocalDate:年、月、日LocalTime…

Java与Kotlin在Android开发中的全面对比分析

趋势很重要 语言发展背景与现状 Android操作系统自2008年正式发布以来,Java长期作为其主要的开发语言。这种选择源于Java语言的跨平台特性、成熟的生态系统以及广泛开发者基础。然而,随着移动开发需求的快速演变,Java在Android开发中逐渐暴…

第一部分:git基本操作

目录 1、git初识 1.1、存在的问题 1.2、版本控制器 1.3、git安装 1.3.1、CentOS平台 1.3.2、ubuntu平台 2、git基本操作 2.1、创建仓库 2.2、配置git 3、工作区、暂存区、版本库 4、基本操作 4.1、场景一 4.2、场景二 4.3、修改文件 5、版本回退 6、撤销修改 …

正则表达式与python使用

一、Python正则表达式基础 1. 导入模块 Python通过 re 模块实现正则表达式功能,需先导入模块: import re2. 核心语法 普通字符:直接匹配字面值(如 a 匹配字符 a)。元字符: \d:匹配数字&…

从FP32到BF16,再到混合精度的全景解析

笔者做过目标检测模型、超分模型以及扩散生成模型。其中最常使用的是单精度FP32、半精度FP16、BF16。 双精度"FP64"就不说了,不太会用到。 #1. 单精度、半精度和混合精度 单精度(FP32)、半精度(FP16)和混合…

Hot100方法及易错点总结2

本文旨在记录做hot100时遇到的问题及易错点 五、234.回文链表141.环形链表 六、142. 环形链表II21.合并两个有序链表2.两数相加19.删除链表的倒数第n个节点 七、24.两两交换链表中的节点25.K个一组翻转链表(坑点很多,必须多做几遍)138.随机链表的复制148.排序链表 N…

不在同一个局域网的远程桌面连接怎么设置?本地内网计算机让其他网络远程访问6种常用方法

远程桌面是一种重要的技术,它允许用户通过网络远程访问和控制另一台计算机的桌面界面。但是,当被控制端和控制端不在同一个局域网内时,就需要进行一些额外的配置。本文将详细介绍在不同局域网下设置远程桌面的步骤,以帮助读者顺利…

天机学堂day10作业,完善兑换优惠券功能

UserCouponServiceImpl /*** 兑换码兑换优惠券* param code*/TransactionalOverridepublic void exchangeCoupon(String code) {//1、校验code是否为空if (StringUtils.isBlank(code)) {throw new BadRequestException("非法参数!");}//2、解析兑换码&…

JAVA工程师面试题(七)

1、递归实现1,1,2,3,5,8,….第30个数是多少&#xff1f; public static int Foo(int i) { if (i < 0) return 0; else if(i > 0 && i < 2) return 1; else return Foo(i -1) Foo(i - 2); }…

Qt基础009(HTTP编程和QJSON)

文章目录 软件开发网络架构BS架构/CS架构 HTTP基本概念QT的HTTP编程JSON数据概述QT生成JSON数据QT解析JSON数据 软件开发网络架构 BS架构/CS架构 ​ 在计算机网络和软件开发中&#xff0c;CS架构&#xff08;Client-Server Architecture&#xff0c;客户端-服务器架构&#x…

高精度电流检测革命:同轴分流器的创新应用与技术演进

一、精密测量原理与结构创新 基于电磁场分布重构技术的新型同轴分流器&#xff0c;突破了传统电流测量的物理限制。该器件采用三维环形电阻矩阵结构&#xff0c;通过多层级导电环的精密排列&#xff0c;实现了电流路径的涡流自补偿。区别于常规分流器的平板式设计&#xff0c;其…

【使用层次序列构建二叉树(数据结构C)】

使用层次序列构建二叉树&#xff08;C语言实现&#xff09; 在数据结构学习过程中&#xff0c;二叉树的构建方式通常有递归建树&#xff08;前序/中序&#xff09;和层次建树&#xff08;广度优先&#xff09;两种。本文将介绍一种基于辅助队列实现的层次建树方法&#xff0c;并…

设置Rocky Linux盒盖不休眠的3个简单步骤

在 Rocky linux&#xff08;和其他基于 RHEL 的发行版&#xff09;中&#xff0c;当你关闭笔记本电脑的盖子时&#xff0c;默认行为通常是使系统休眠。如果你想更改这一行为&#xff0c;例如&#xff0c;使系统在关闭盖子时只是锁定&#xff0c;你可以按照以下步骤操作&#xf…

WPF的发展历程

文章目录 WPF的发展历程引言起源与背景&#xff08;2001-2006&#xff09;从Avalon到WPF设计目标与创新理念 WPF核心技术特点与架构基础架构与渲染模型关键技术特点MVVM架构模式 WPF在现代Windows开发中的地位与前景当前市场定位与其他微软UI技术的关系未来发展前景 社区贡献与…

【器件专题1——IGBT第1讲】IGBT:电力电子领域的 “万能开关”,如何撑起新能源时代?

一、IGBT 是什么&#xff1f;重新认识这个 “低调的电力心脏” 你可能没听过 IGBT&#xff0c;但一定用过它驱动的设备&#xff1a;家里的变频空调、路上的电动汽车、屋顶的光伏逆变器&#xff0c;甚至高铁和电网的核心部件里&#xff0c;都藏着这个 “电力电子开关的瑞士军刀”…

新闻速递丨Altair 与 Databricks 达成合作,加速数据驱动型创新

NEWS Altair 近日宣布与数据和人工智能公司 Databricks 达成战略合作&#xff0c;通过新一代数据统一化、图谱驱动智能和企业级人工智能&#xff08;AI&#xff09;技术赋能双方客户。 此次合作整合了两大平台的核心优势&#xff0c;将 Altair RapidMiner 平台的强大功能&…

c++11 :智能指针

目录 一 为什么需要智能指针&#xff1f; 二 智能指针的使用及原理 1. RAII 2. auto_ptr 3. unique_ptr 4. shared_ptr 5. weak_ptr 三 内存泄漏 1.什么是内存泄漏&#xff0c;内存泄漏的危害 2. 如何避免内存泄漏&#xff1f; 一 为什么需要智能指针&#xff1f; …

大模型在直肠癌预测及治疗方案制定中的应用研究

目录 一、引言 1.1 研究背景与意义 1.2 研究目的 1.3 研究方法与创新点 二、大模型技术概述 2.1 大模型的基本原理 2.2 常见大模型类型及特点 2.3 在医疗领域的应用进展 三、直肠癌预测相关数据收集与处理 3.1 数据来源 3.2 数据清洗与预处理 3.3 特征工程 四、大…

VRRP与防火墙双机热备实验

目录 实验一&#xff1a;VRRP负载均衡与故障切换 实验拓扑​编辑一、实验配置步骤 1. 基础网络配置 2. VRRP双组配置 二、关键验证命令 1. 查看VRRP状态 2. 路由表验证 三、流量分析 正常负载均衡场景&#xff1a; 故障切换验证&#xff1a; 实验二&#xff1a;防火…