PCI总线定义了两类配置请求,一类是Type 00h配置请求,另一类是Type 01h配置请求。PCI总线使用这些配置请求访问PCI总线树上的设备配置空间,包括PCI桥和PCI Agent设备的配置空间。当x86处理器对CONFIG_DATA寄存器进行读写操作时,HOST主桥将决定向PCI总线发送Type 00h配置请求还是Type 01h配置请求。在PCI总线事务的地址周期中,这两种配置请求总线事务的不同反映在PCI总线的AD[31∶0]信号线上。......
2023-10-20
Linux PowerPC初始化PCI总线树的步骤与Linux x86类似,也调用了一些Linux系统中与PCI总线相关的通用函数。但是PowerPC处理器使用的HOST主桥与x86处理器并不相同,因此Linux PowerPC初始化PCI总线树的过程与Linux x86有些差别。本节以MPC8572处理器为例,说明Linux PowerPC初始化PCI总线树的过程。
MPC8572处理器共有三个PCIe总线控制器,其中每一个总线控制器都可以管理一个独立的PCI总线树。在每一个总线控制器中都包含一组独立的寄存器,MPC8572处理器可以通过设置Inbound和Outbound寄存器,访问对应PCI总线树上所有PCI设备的配置空间。这组寄存器与MPC8548处理器提供的对应寄存器较为类似,详见第2.2节。
Linux PowerPC在引入了Open Firmware机制[22]后,使用dts文件管理PCI总线控制器。MPC8572处理器系统使用的dts文件为./arch/powerpc/boot/dts/mpc8572ds.dts文件,其中与PCI总线控制器相关的部分如源代码14-43所示。
源代码14-43 MPC8572处理器系统使用的dts文件
以上代码分别描述了MPC8572处理器系统的3个PCIe控制器,其使用的寄存器空间为0xFFE08000~0xFFE08FFFF、0xFFE09000~0xFFE09FFFF和0xFFE0A000~0xFFE0AFFFF。这三个PCIe控制器分别管理3棵PCI总线树,其PCI总线的编号都为0~255,在这个dts文件中还包含了PCIe控制器的其他信息,本节并不关心这些内容。
Linux PowerPC在调用setup_arch→mpc85xx_cds_setup_arch函数时,分别初始化这三个PCIe控制器,该函数的实现如源代码14-44所示。
源代码14-44 mpc85xx_cds_setup_arch函数
mpc85xx_cds_setup_arch函数分析mpc8572ds.dts文件,并将“pci0”作为主PCI总线控制器,并调用fsl_add_bridge(np,1)函数进行初始化操作,“pci1”和“pci2”作为从PCI总线控制器调用fsl_add_bridge(np,0)函数进行初始化操作。在MPC8572处理器中,主PCI总线控制器需要处理ISA总线使用的存储器和I/O地址空间。
fsl_add_bridge函数在./arch/powerpc/sysdev/fsl_pci.c文件中,该函数的实现如源代码14-45~26所示。Linux PowerPC使用pci_controller结构描述HOST主桥,包括这个主桥管理的PCI总线域地址范围、PCI总线号和访问配置寄存器的方法等一系列信息,pci_controller结构在./arch/powerpc/include/asm/pci-bridge.h文件中。
源代码14-45 fsl_add_bridge函数片段1
这段代码首先分析mpc8572ds.dts文件,然后获得PCIe主桥管理的PCI总线范围,对于pci0控制器,bus_range[0]为0,而bus_range[1]为255。之后为当前PCIe主桥使用的hose结构分配空间,并初始化其first_busno和last_busno参数。
setup_indirect_pci函数设置在Linux PowerPC中间接访问PCI设备配置空间的函数,如第2.2节所示,在PowerPC处理器中,访问PCI设备配置空间有两种方式,一种是使用间接访问方式,一种是使用ECAM方式。与x86处理器略有不同,PowerPC处理器使用间接访问方式也可以访问PCIe设备的扩展配置空间,因此ECAM方式对于PowerPC处理器而言,并不是必须的。
源代码14-46 fsl_add_bridge函数片段2
pci_process_bridge_OF_ranges函数分析mpc8572ds.dts文件的“ranges”字段,在dts文件中,ranges字段的解释如下。
ranges字段共由14个双字组成,每7个双字为1组,每一组描述一段PCI总线域地址空间与存储器域地址空间的对应关系。
●每一组的第一个双字代表pci_space,为0x200-0000表示这段PCI总线地址空间为存储器地址空间,为0x100-0000表示这段PCI总线地址空间为I/O地址空间。
●每一组的第2~3个双字存放pci_address,即PCI域地址空间。(www.chuimin.cn)
●每一组的第4~5个双字存放cpu_address,即存储器域地址空间。
●每一组的第6~7个双字存放size,即这段地址空间的大小。
pci_process_bridge_OF_ranges函数的主要作用就是根据dts文件中的ranges字段,初始化hose结构的对应参数,本节对该函数不做进一步介绍。
setup_pci_atmu函数首先设置MPC8572处理器中的Outbound和Inbound寄存器组,这两组寄存器的描述见第2.2节。然后设置PEXCSRBAR寄存器。
如果MPC8572处理器作为RC[23],而且支持MSI中断机制时,需要设置PCIe主桥的BAR0寄存器,即PEXCSRBAR(PCI Express Base Address Register)寄存器。在PCI规范中,MSI中断机制以存储器写的方式实现,当这个MSI存储器写最终到达RC时,需要能够被RC接收。在PowerPC处理器中,MSI存储器写的目的地址为MSIIR寄存器在PCI总线域的物理地址。此时PowerPC处理器可以采用两种方式接收这个MSI存储器写,一种是设置Inbound寄存器,映射MSIIR寄存器所在的PCI总线空间,另一种是设置RC的BAR0寄存器。Linux PowerPC使用了后一种方式。
Linux PowerPC执行完毕setup_arch函数后,还会执行一些和PCI总线初始化相关的函数,如下所示。
c053e04c t__initcall_pcibus_class_init2
c053e050 t__initcall_pci_driver_init2
c053e088 t__initcall_pcibios_init4
c053e0ac t__initcall_pci_slot_init4
c053e28c t__initcall_pci_init6
c053e290 t__initcall_pci_proc_init6
c053e3ec t__initcall_pci_resource_alignment_sysfs_init7
c053e3f0 t__initcall_pci_sysfs_init7
这些函数在第14.3节中都有介绍,虽然Linux PowerPC执行这些函数的过程与Linux x86略有不同,但大体类似,本章对此不做进一步说明。
有关PCI Express体系结构导读的文章
PCI总线定义了两类配置请求,一类是Type 00h配置请求,另一类是Type 01h配置请求。PCI总线使用这些配置请求访问PCI总线树上的设备配置空间,包括PCI桥和PCI Agent设备的配置空间。当x86处理器对CONFIG_DATA寄存器进行读写操作时,HOST主桥将决定向PCI总线发送Type 00h配置请求还是Type 01h配置请求。在PCI总线事务的地址周期中,这两种配置请求总线事务的不同反映在PCI总线的AD[31∶0]信号线上。......
2023-10-20
Linux系统在初始化时,将在do_initcalls函数中执行__initcall_xyz_initx函数,从而执行xyz_init函数。Linux系统使用这种方法规范初始化模块的执行,并保证这些模块可以按照指定的顺序依次执行。在Linux内核的System.map[4]文件中,可以找到在__early_initcall_end和__initcall_end之间所有的函数指针,其中与PCI总线初始化相关的函数如源代码14-4所示,这些函数将按照在以下源代码中出现的顺序依次执行。......
2023-10-20
在PCIe总线中,存储器读写和I/O读写TLP使用基于地址的路由方式。TLP使用基于地址的路由时,一定要通过查询这组寄存器之后,再决定传送路径。下文以TLP1~TLP3的发送过程对地址路由过程进行说明。本小节中的例子将使用P-P2桥片接收TLP1,并将TLP1推至PCI Bus2,而PCI Bus2上的EP1将接收TLP1,完成整个地址路由。由以上叙述可以发现,PCIe总线中基于地址的路由方式与PCI总线上的基于地址的数据传递流程十分相近。......
2023-10-20
对于Linux x86而言,BIOS已经将PCI设备使用的存储器和I/O资源设置完毕,而其他Linux系统,如Linux PowerPC,需要使用该函数设置PCI设备使用的存储器和I/O资源。pci_init函数的主要作用是对已经完成枚举的PCI设备进行修复工作,用于修补一些BI-OS中对PCI设备有影响的Bugs。CompactPCI总线在通信系统中较为常见。而pci_sysfs_init函数与sysfs文件系统相关,主要功能是将每一个PCI设备加入到sysfs文件系统的相应目录中,本节对此不做进一步介绍。Linux x86对PCI总线进行初始化时,使用了许多不完美的源代码。......
2023-10-20
系统软件在遍历当前PCI总线树时,需要首先对这些PCI总线进行编号,即初始化PCI桥的Primary、Secondary和Sub-ordinate Bus Number寄存器。扫描PCI总线2,发现PCI桥3,并将PCI桥3的Secondary Bus命名为PCI总线3。继续回退到PCI总线1。从以上算法可以看出,PCI桥的Primary Bus和Secondary Bus号的分配在遍历PCI总线树的过程中从上向下分配,而Subordinate Bus号是从下向上分配的,因为只有确定了一个PCI桥之下究竟有多少条PCI总线后,才能初始化该PCI桥的Subordinate Bus号。......
2023-10-20
系统软件使用DFS算法对PCI总线进行遍历时,完成这些寄存器的初始化,即分配这些设备在PCI总线域的地址空间。值得注意的是,PCI Agent设备的BAR0~5寄存器和PCI桥的Base寄存器保存的地址都是PCI总线地址。而这些地址在处理器系统的存储器域中具有映像,如果一个PCI设备的BAR空间在存储器域中没有映像,处理器将不能访问该PCI设备的BAR空间。......
2023-10-20
PCIe总线规范将这种“对PCIe设备配置空间”的读写访问方式称为ECAM机制。CPU可以直接对这段特殊的存储器域地址空间进行访问,从而访问PCIe设备的配置空间。使用ECAM机制与使用CONFIG_ADDRESS和CONFIG_DATA这对寄存器,间接访问PCIe设备的配置空间有较大的不同。其中raw_pci_ops函数指针使用0xCF8和0xCFC两个I/O端口寄存器访问PCI总线配置空间,而raw_pci_ext_ops函数使用ECAM方式访问PCI总线配置空间。虽然Montevina平台提供了256MB的PCIe设备使用的配置空间,但是这些空间的实际利用率较低。......
2023-10-20
PCI设备进行上电初始化时,将E2PROM中的信息读到PCI设备的配置空间中作为初始值。这个过程由硬件逻辑完成,绝大多数PCI设备使用这种方式初始化其配置空间。在PCI Agent设备的配置空间中包含了许多寄存器,这些寄存器决定了该设备在PCI总线中的使用方法,本节不会全部介绍这些寄存器,因为系统软件只对部分配置寄存器感兴趣。PCI Agent设备使用的配置空间如图2-9所示。图2-9 PCI Agent设备的配置空间Revision ID和Class Code寄存器这两个寄存器只读。......
2023-10-20
相关推荐