读书笔记之PCI Express体系结构导读

第一章 PCI总线的基本知识

PCI总线概念

PCI(Peripheral Componnent Interconnect)在处理器体系结构中属于局部总线,局部总线作为系统总线的延伸,其主要的功能就是连接外部设备。随着处理器主频的不断提升,就要求速度更快带宽更高的局部总线。起初PC采用8位的XT总线作为局部总线,后来很快升级到16位的ISA(Industry Stadnard Architecture)总线,并逐步发展到32位的EISA(Extended Industry Stadnard Architecture )总线,VESA(Video Electronics Standards Association)总线和MCA(MIcro Channel Architecture)总线。
PCI总线属于并行总线,PCIE是属于串行总线,但是软件架构完全兼容PCI总线的架构。主要是因为并行总线的频率提升更加困难,因此后期PCI总线的硬件设计采用了高速的串行总线来实现。

PCI总线特点

  • PCI总线空间与处理器空间隔离
    PCI设备具有独立的地址空间,即PCI总线地址空间和存储器的地址空间通过HOST主桥(PCI控制器)隔离。处理器需要通过HOST主桥才能访问PCI设备,而PCI设备需要通过HOST主桥采用访问存储器。在HOST主桥中含有很多缓冲区,这些缓冲使得处理器总线与PCI总线工作的各自的时钟频率上互不干扰。HOST主桥的存在使得PCI设备和处理器可以方便的共享主存储器的资源。处理器访问PCI设备时,需要通过HOST主桥进行地址空间的额转换,同样PCI设备访问主存储器的时候也需要HOST主桥来进行地址空间的转换。PCI设备使用的地址是属于PCI总线域的地址,与主存储器的地址分别属于不同的域。

  • 可扩展性
    在PCI总线中HOST主桥直接可以推出一条PCI总线,这条总线就是该HOST主桥管理的第一条PCI总线,该总线还可以通过PCI桥扩展出一系列PCI总线,并以HOST主桥为根节点。形成一棵PCI总线树。这些PCI总线都可以连接PCI设备,但是在一个PCI总线树上,最多可以连接256个PCI设备,其中包括PCI桥。在同一个PCI总线上的设备之间可以直接通信,而并不影响其他PCI总线上设备间的数据通信。隶属于同一棵PCI总线树上的设备可以直接通信,但是需要PCI桥进行数据转发。PCI桥是PCI总线中的一个重要部件,他的存起使能PCI总线具有很强的扩展性,在以HOST为根节点的PCI总线树上,每一个PCI桥下也可以连接一个PCI总线子树,PCI桥下的总线仍然可以使用PCI桥进行总线扩展。PCI桥管理这个总线子树,PCI桥的配置空间含有一系列总线子树的配置寄存器。在PCI桥的两端,分别连接了两条PCI总线,靠近处理器的被成为上游总线,另一条被称为下游总线。这两条总线间的通信需要桥来进行,PCI桥的概念同样被PCIE总线所采纳。在PCIE中同样使用。

  • 动态配置机制
    PCI设备所使用的地址空间可以根据需要由系统软件动态的进行配置。PCI总线使用这种方式合理的解决了PCI设备地址冲突的问题,从而实现了即插即用。每一个PCI设备都有独立的PCI配置空间,在配置空间中含有该设备在PCI总线中使用的基地址,系统软件可以动态配置这个基地址。从而保证每一个设备的地址空间并不相同。PCI桥的配置空间中含有其下PCI子树所能使用的地址范围。

  • 总线带宽
    PCI总线与之前的总线相比极大的提高了总线的带宽,32位33MHz的PCI总线可以提供132MB/s的峰值带宽,而64位66MHz的PCI总线可以提供的峰值带宽为532MB/s。虽然PCI总线的带宽还是不能和PCIE总线的带宽相比,但是相比之前的局部总线的带宽,已经提高很多。

  • 共享总线机制
    PCI设备通过仲裁机制或者PCI总线的使用权后,才能进行数据传送,在PCI总线上进行数据的传送并不需要处理器的参与。PCI总线的仲裁器是不在PCI规范内的,虽然大多数HOST主桥和PCI桥中都含有仲裁器,但是可以关闭,但是使用独立的PCI总线仲裁器。PCI总线使用共享总线的方式进行数据的传递,在同一条总线上,所有PCI设备共享同一总线的带宽,这将极大的影响PCI总线的效率。

  • 中断机制
    PCI总线上的设备可以通过四根中断请求信号INT A-D向处理器提交中断请求。PCI总线上的设备是共享这些中断请求信号的,不同的PCI设备可以将这些中断请求信号“线与”后,与中断控制器的中断请求引脚连接。PCI设备的配置空间记录了该设备使用这四根中断请求信号的信息。PCI总线还进一步提出了MSI(Message Signal Interrupt)机制。该机制使用存储器写总线事物传递中断请求,并使用处理器的FSB(Front Side Bus)总线提供的Interrupt Message 总线事物。从而提高PCI设备的中断请求效率。

HOST主桥

HOST主桥是一个特别的桥片,主要的功能就算是隔离处理器系统的存储器域和系统的PCI总线域,并管理PCI总线域,同时完成处理器和PCI 设备间的数据交换。处理器与PCI设备间的数据交换主要由处理器访问PCI设备的地址空间和PCI设备使用DMA机制访问主存储器这两种方式来完成。在一个处理器系统中,有几个HOST主桥就有几个PCI总线域。PCI总线设备通过HOST主桥访问主存储器的时候,需要处理器的cache进行一致性的操作,因此在设计HOST主桥的时候需要考虑到各种架构上cache一致性的操作。在HOST主桥中含有许多数据缓冲,以支持PCI总线的预读取机制。

PCI总线

在处理器系统中,含有PCI总线和PCI总线树两个概念。这两个概念并不相同,在一棵PCI总线树上可能含有多条PCI总线,而具有血缘关系的PCI总线组成一棵PCI总线树。

PCI设备

在PCI总线中有三类设备:PCI主设备,PCI从设备和桥设备。其中PCI从设备只能被动的接受来自HOST主桥或者其他PCI设备的读写请求,而PCI主设备可以通过总线仲裁得到PCI总线的使用权,可以主动的向其他PCI设备或者主存储器发出读写请求。而桥设备的主要作用就是管理下游总线并转发上游总线的事物。一个PCI设备既可以是主设备也可以是从设备,但是在同一时刻这个设备只能是主设备或者从设备。PCI主设备被成为PCI Agent设备。在处理器系统中常见的如PCI网卡、显卡、声卡等都属于PCI Agent。

PCI总线的负载

PCI总线所能挂接的负载和总线的频率相关,其中总线频率越高,所能挂接的负载就越少,但是总线的峰值带宽越大。
当频率为33MHz所能挂接的负载为4-5个插槽,当频率为66MHz的时候,所能挂接的负载为1-2个插槽。

PCI总线的存储器读写总线事务

PCI总线使用单端并行数据线,采用地址译码方式进行数据传输,而采用ID译码的方式进行配置信息的传输。地址译码使用的是地址信号,而ID译码使用PCI设备的ID,包括BUS号,Device号,Function号,和寄存器号。PCI设备只有在软件初始化配置空间之后,才能够被其他主设备访问。当PCI设备的配置空间被初始化之后,该设备在当前的PCI总线树上将拥有一个独立的PCI总线的地址空间即BAR空间(Base address Register)。处理器与PCI设备进行数据交换,或者PCI设备之间进行存储器数据交换的时候,将通过PCI总线完成。而PCI设备和主存储器进行DMA操作时,使用的是PCI总线域的地址,而不是存储器域的地址,此时将由HOST主桥完成PCI总线地址到存储器域地址的转换。
PCI总线支持一下几类存储器读写总线事务:

  • HOST处理器对PCI设备的BAR空间进行数据读写,BAR空间可以使用存储器或者IO译码的方式来访问。
  • PCI设备间的数据传送
  • PCI设备对主存储器进行读写即DMA操作。

Posted和Non-Posted传送方式

PCI总线规定了两类数据传送方式,分别为Posteed和non-Posted方式,其中Posted数据传送方式也叫Posted总线事务,Non-Posted数据传送方式也叫Non-Posted总线事务。Posted总线事务指PCI主设备向PCI目标设备进行数据传送时,当数据到达PCI桥后,即由PCI桥接管来自上游总线的事务,并将其转发到下游总线,在数据还没有到大目标设备之前,PCI总线就可以释放总线事务,从而在一定程度上解决了总线事务的阻塞的问题。而Nonposted是指在数据没有到达目标设备之前是不会释放总线事务的传送方式。只要数据到达目标设备之后才会释放。PCI总线规定只有存储器写请求可以采用Posted总线事务,而存储器读请求和IO读请求、配置读请求只能采用Non-Posted总线事务。

HOST处理器访问PCI设备

HOST处理器对PCI设备的访问主要包含两方面的内容,一是处理器向PCI设备发起存储器和IO读写请求,另一方面是出处理器对设备进行配置读写。在PCI设备的配置空间中,共有6个BAR寄存器每一个BAR寄存器与PCI设备使用的PCI总线地址空间对应,BAR空间记录这组地址空间的基地址。在PCI总线中存储器读写事物与IO读写事物比较类似,首先HOST处理器在初始化时需要将PCI设备使用的BAR空间映射到存储器域的地址空间中,之后处理器通过读写映射之后的存储器域的地址空间来初始化PCI设备。

PCI 总线树BUS号的初始化

在一个处理器系统中,每一个HOST主桥都推出一棵PCI总线树,在这个PCI总线树中有多少个PCI桥(包含HOST主桥)就包含有多少条PCI总线。系统软件在便利当前的PCI总线树的时候,需要先对这些PCI总线进行编号,即初始化PCI桥的Primary/Secondary和Subordinate Bus Number寄存器。一般与HOST主桥直接相连的PCI总线命名为PCI总线0,然后系统软件使用DFS(Depth First Search)算法依次对其他的PCI总线进行编号,需要注意的是与HOST主桥相连的PCI总线其编号都为0,因为当系统中有多个HOST主桥的时候,将有多个PCI总线0,但是这些却分属不同的PCI总线域,其含义也并不相同。
DFS算法是搜索算法的一种,其实现机制是沿着一棵树的深度进行遍历各个节点,并尽可能的搜索树的分支,DFS的算法为线性时间复杂度,适合对拓扑结构未知的树进行遍历。
在初始化总线树的BUS号的时候,只扫描桥设备,忽略agent设备。与主桥相连的那个总线为总线0,下面的第一个桥下面所连接的总线为总线1,并初始化这个桥的primary Bus number 为0,secondary bus number为1,并初始化桥1的配置空间,继续扫描桥1下面的桥设备,如果还有桥,那么这个桥就是桥2,初始化桥二的primary Bus number 为1,secondary bus number为2,依次类推。当桥n为最后一个桥,其下面没有桥设备了。那么初始化桥n的primary Bus number 为n-1,secondary bus number n,并初始化这个桥的suboridinate bus number为n,并初始化这个桥的配置空间,然后一次向上一级退,初始化上一级桥的suboridinate bus number n,直到将桥一的suboridinate bus number 为n。如果PCI 总线0上除了挂接了桥一外,那么另一个桥的级为桥n+1,并按照上面的过程一次再初始化桥N+1下面的桥设备的配置空间,primary Bus number寄存器和secondary bus number寄存器和suboridinate bus number 寄存器。注意primary Bus number寄存器和secondary bus number寄存器在遍历PCI总线过程中是从上而下分配的,而suboridinate bus number 寄存器是从下而上分配的每一个桥的这个值都是一个值。只有确定了一个PCI桥下有多少条PCI总线后才能初始化该PCI桥的suboridinate bus number 寄存器。

PCI总线DEVICE号的分配

众所周知一条PCI总线上会挂接各种PCI设备,而每一个PCI设备在PCI总线上具有唯一的设备号。系统软件通过总线号和DEVICE号来确定一个PCI设备之后,才能访问这个PCI设备的配置寄存器。那么需要注意:PCI使用ID寻址的方式来访问PCI设备的配置寄存器,而使用地址寻址的方式来访问PCI设备的mem空间和io空间。
PCI设备的ISSEL信息与PCI总线的AD[31:0]信号的连接关系决定了该设备在这条PCI总线上的设备号,每一个PCI设备都使用独立的IDSEL信号,该信号与PCI总线的AD[31:0]信号连接。在CONFIG_ADDRESS寄存器中DEVICE number字段共有5位可以表示32个设备,而AD[31:11]只有11位,显然这两者之间不会建立一对一的映射关系,因此在一条PCI总线上要有21个以上的PCI设备,那么总是有几个设备是无法与AD[31:11]建立信号连接的,所以起始在一条PCI总线挂载的最大的PCI设备的个数并不是32个,这不是这里的21个,而是和PCI总线的频率有关系的,频率越低挂载的设备也就越多,相反频率越高,挂载的设备就越少。在33Mhz的情况下最多也只能挂载10个负载。PCI总线推荐了一种Device number 字段与AD[31:16]之间的映射关系,其中PCI设备0与device number 字段的0b00000对应,PCI设备1与device number 字段的0b00001对应,一次类推PCI设备15与device number 字段的0b01111对应。注意:对PCI设备的配置寄存器进行访问的时候,一定要明确bus number /device number/function number/和register number这四元组。缺一不可。

非透明PCI桥

非透明的PCI桥主要应用就是通过这种桥来连接两个处理器的情况,可以实现双路服务器。非透明桥的作用是对不同PCI总线域的地址进行隔离,而不是隔离PCI总线域和存储器域的地址。HOST主桥的作用才是将存储器域的地址和PCI总线域的地址进行隔离。

PCI 设备的Base address reg

该组寄存器简称为BAR寄存器,BAR寄存器保存PCI设备使用的地址空间的基地址,注意这个地址是属于PCI总线域的地址,并不是存储器域的地址。(x86,Arm/MIPS架构上这两个总线域的地址是直接相等的,但是在Powpc上却不是)。每一个设备最多有6个BAR寄存器,但是具体设备上使用几个视情况而定。在PCI设备复位后,该寄存器存放PCI设备需要使用的地址空间的大小,空间类型(IO/MEM),系统软件对PCI总线进行配置的时候,首先获得这个寄存器的初始化信息,之后将根据系统的配置将合理的地址写入到这个寄存器中,系统软件可以对这个寄存器写入0xffffffff之后再读获取BAR空间的长度。当处理器访问BAR空间时,需要使用BAR寄存器提供的基地址,需要注意,给处理器的地址都是属于存储器域的虚拟地址,而BAR空间存放的是PCI总线域中的物理地址,需要将这个地址转化为存储器域的物理地址之后,再转化为存储器域的虚拟地址才能给CPU使用,这样访问的地址才是真正的PCI设备的地址空间。在linux内核中使用pci_dev->resource[bar].start参数获取BAR寄存器在存储器域的物理地址。在编写设备驱动程序的时候,必须使用pci_resource_start函数获取BAR空间对应的存储器域的物理地址,然后使用ioremap函数将这个物理地址转换为虚拟地址。注意ioremap函数的作用就是将存储器域的物理地址转换为存储器域的虚拟地址,但是在x86架构或者ARM以及MIPS架构这个函数的实现是不同的。

你可能感兴趣的:(PCIE)