PCI bar 解析

news/2024/11/25 5:07:27/

只要是接入系统的 pci 设备就需要和系统软件进行交互,设备和系统之间的交流主要包含以下两部分:

1,系统要能访问到设备的寄存器

用于控制设备行为,包括DMA,数据收发等;设备通过寄存器报告自身的状态,如是否工作正常,有没有什么错误;

2,设备和系统之间互相传输数据

系统定位设备寄存器的位置以及数据收发的位置。换句话说,设备内部的这些资源应该是可寻址的,能够被系统访问到进而完成一些读写操作。一种思路是设备出厂的时候,就固化自己片上存储空间对应在系统中的地址空间,比如对应到0xFE000000h ~ 0xFE000FFF(4KB),这段地址被该设备独占,对这段地址进行ioremap映射后进行访问就可以和该设备交互。可想而知这种方式可扩展性差,毕竟设备有很多,照这样分配地址,那估计系统有多少地址宽度都不够造的。

另外每个设备对于其所需要的地址空间类型(无论是IO映射还是MMIO映射)和大小有多种多样的需求,但是又不能自己配置,所以必须以一定方式提供信息(包括请求的地址空间类型和大小)给系统,从而让BIOS或操作系统内核来为其分配。PCIe设备可能会有一些自己的内部资源,Host通过BAR(Base Address Register)空间访问这些资源,BAR指的是设备配置空间中的4个字节,针对一个设备来说,其有6个BAR地址(实际中所有的BAR并不会都使用,不使用的BAR必须由厂商硬编码为0),设备的每个BAR对应设备上的一段存储空间(或者寄存器空间),系统通过将系统地址写入BAR就建立了存储空间的卡上地址和系统地址空间的映射。BAR空间实际上是Host将这段空间映射到自己的物理地址空间中,因此主机驱动需要先知道这段空间的大小和属性,然后找一段可用的物理地址,再把这个物理地址配置到PCIe地址空间中去。从系统的物理地址空间中分配一段地址空间,并把相应的基地址写回到BAR寄存器。(写入BAR寄存器的地址其实是PCI地址空间的地址,只是x86架构中两种地址空间重合,有的架构比如PowerPC就需要将CPU的物理地址转换为PCI地址空间的地址)。BAR空间在Host上只是分配了一段地址空间,实际对应设备的资源。当Host读写BAR空间时,都会通过PCIe接口(PCI TLP消息)进行实际的数据传输。

BAR 空间实际上是主机将这段空间映射到自己的物理地址空间中,因此主机驱动需要先知道这段空间的大小和属性,然后找一段可用的物理地址,再把这个物理地址配置到PCIe地址空间中去。

在硬件加电初始化时,BIOS固件统一检查了所有的PCI设备, 并统一为他们分配了一个和其他互不冲突的地址,让他们的驱动程序可以向这些地址映射他们的寄存器,这些地址被BIOS写进了各个设备的配置空间的BAR寄存器中,因为这个活动是一个PCI的标准的活动,所以自然写到各个设备的配置空间里而不是他们风格各异的控制寄存器空间里。当然只有BIOS可以访问配置空间。当操作系统 初始化时,他为每个PCI设备分配了pci_dev结构,并且把BIOS获得的并写到了配置空间中的地址读出来写到了pci_dev中的resource 字段中。这样以后我们在读这些地址就不需要在访问配置空间了,直接跟pci_dev要就可以了,我们这里的四个函数就是直接从pci_dev读出了相关数 据,代码在include/linux/pci.h中。定义如下:

        #define pci_resource_start(dev,bar) ((dev)->resource[(bar)].start)

        #define pci_resource_end(dev,bar) ((dev)->resource[(bar)].end)

在内核中pci_setup_device()函数完成了对单个pci 设备的设备和检测,并将获取的信息存取设备结构体中,用于后期具体设备的使用,在pci_setup_device->pci_read_bases-> __pci_read_base中会decode bar读取bios 中配好的系统地址,并写到创建的 resource中去,这里的地址都是物理的(即写到bar中的地址值),必须要在pci设备驱动的probe函数中调用ioremap 或者 pci_iomap 来将这些地址map成虚拟地址才可以使用,访问这个虚拟地址就可以直接操作pcie 设备上的寄存器(片上物理地址)了:

        base_addr = pci_resource_start(pci_dev, bar_idx); 

        size = pci_resource_len(pci_dev, bar_idx); 

        virt_addr = pci_iomap(vpri_dev->pci_dev, bar_idx, 0); 

pci_read_bases 作用:

1,pci_read_bases首先会依次遍历howmany PCI/PCIe设备的BAR配置;

2,struct resource *res = &dev->resource[pos]获取对应的PCI/PCIe设备对应的BAR的resource结构体,为后面的获取到资源信息做填充使用;

3,__pci_read_base用于具体的PCI/PCIe设备资源获取和解析;

4,如果rom是有效的,则会进一步去解析PCI_ROM_RESOURCE的扩展配置空间的资源信息( #6: expansion ROM resource );

__pci_read_base 的作用:

1,读取PCI/PCIe设备的BAR寄存器,解析PCI/PCIe设备的属性以及资源需求信息;

2,读取BAR寄存器的过程

 ·读BAR,保留原值;

 ·写0xFFFFFFFF到BAR;

 ·再读出来,解析出所需要的地址空间大小,记录在pci_dev->resource[ ]里;

       pci_dev->resource[ ].start = 0;

       pci_dev->resource[ ].end = size - 1;

 ·将原值写会BAR寄存器中;

 ·根据上一步读取出的l和sz去计算设备当前BAR所需要资源的基址和大小,通过pcibios_bus_to_resource配置到对应设备BAR的resource里面(设置resource.start);

涉及的代码如下:

    /* 读取BAR寄存器的过程 */

    pci_read_config_dword(dev, pos, &l); /* BARl(起始地址) */

    pci_write_config_dword(dev, pos, mask); /* BAR1 */

    pci_read_config_dword(dev, pos, &sz); /* BARsz(长度) */

    pci_write_config_dword(dev, pos, l); /* BAR l(恢复) */


http://www.ppmy.cn/news/507180.html

相关文章

PCI、PCIE配置空间的访问

一. 使用PCI兼容性配置访问机制 根据协议,x86上使用了两个I/O端口寄存器(OUT 和 IN 在汇编中是端口读写操作指令。端口是主机与外设进行数据交换使用的,分为数据端口,状态端口和控制端口三种。PC机给每一个端口分配了一个地址&am…

PCI设备与PCI桥的配置空间

PCI配置空间 HOST主桥通过配置读写事务报文访问设备的配置空间,PCI总线规定了三种类型的PCI配置空间。配置空间中出现的地址都是PCI总线域的地址。 (1)Agent设备配置空间(HeaderType.HeaderLayout0) (2)Bridge桥配置空间(HeaderType.HeaderLayout1) (3)Cardbus桥…

PCI-PCIE中断机制之一

PCI总线使用INTA#、INTB#、INTC#和INTD#信号向处理器发出中断请求。这些中断请求信号为低电平有效,并与处理器的中断控制器连接。在PCI体系结构中,这些中断信号属于边带信号(Sideband Signals),PCI总线规范并没有明确规…

PCI总线原理

PCI即 Peripheral Component Interconnect,中文意思是“ 外围器件互联”,是由PCISIG (PCI Special Interest Group)推出的一种局部并行总线标准。在现在电子设备中应用非常广泛,下面我详细介绍下PCI总线的工作原理,希望对大家有…

pcie应用记录 - pcie中断

项目场景: (1)fpga与国产龙芯3A3000 cpu主板通过pcie总线进行通信; (2)主板采用rework国产实时嵌入式操作系统,fpga部分为xlinx a7系列及 xilinx 7x pcie ip核; (3&…

PCI小结

几个基本的问题: 1) 注册函数的问题:因为编写的PCI设备驱动,是为某一具体设备服务,而这一具体设备,虽为PCI设备,但其本质仍可划分为,字符设备,网络设备等。因此在驱动程…

接口--PCI/PCIE

关于PCIE的参考,见:王齐的博客 ---------------------------------------------- 分界线 ----------------------------------------------------------- PCI总线原理 PCI即Peripheral Component Interconnect,中文意思是“外围器件互联”&a…

RK3399平台开发系列讲解(PCI/PCI-E)5.54、PCIE INTx中断机制

文章目录 一、PCIe中断过程二、PCIE 控制器支持的中断三、PCIE 控制器注册中断四、PCIe设备中断号分配沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇章将介绍RK3399平台PCIE总线中断INTx相关内容。 一、PCIe中断过程 层级结构为:PCIe设备 => PCIe控制器 =&g…