接前一篇文章:《PCI Express体系结构导读》随记 —— 第I篇 第2章 PCI总线的桥与配置(6)
MPC8548处理器的拓扑结构如图2-2所示:
OCeaN部件的拓扑结构如图2-3所示:
为了便于理解,再次贴出图1-1。
PCI总线规定访问配置空间的总线事务,即配置读写总线事务,使用ID号进行寻址。PCI设备的ID号由总线号(Bus Number)、设备号(Device Number)和功能号(Function Number)组成。
其中,总线号在HOST主桥遍历PCI总线树时确定。PCI总线可以使用PCI桥扩展PCI总线,并形成一棵PCI总线树。在一棵PCI总线树上,有几个PCI桥(包括HOST主桥),就有几条PCI总线。在一棵PCI总线树中,总线号由系统软件决定。通常,与HOST主桥直接相连的PCI总线编号为0,系统软件使用DFS(Depth-First Search,深度优先)算法扫描PCI总线树上的所有PCI总线,并依次进行编号。
一条PCI总线的设备号由PCI设备的IDSEL信号与PCI总线地址线的连接关系确定。
功能号与PCI设备的具体设计相关。在一个PCI设备中,最多有8个功能设备,而且每一个设备都有各自的PCI配置空间。而在绝大多数PCI设备中,只有一个功能设备。
HOST主桥使用寄存器号访问PCI设备配置空间的某个寄存器。
在MPC8548处理器的HOST主桥中,与PCI设备配置空间相关的寄存器由CFG_ADDR、CFG_DATA和INT_ACK寄存器组成。系统软件使用CFG_ADDR和CFG_DATA寄存器访问PCI设备的配置空间,而使用INT_ACK寄存器访问挂接在PCI总线上的中断控制器的中断向量。HOST主桥这3个寄存器的地址偏移和属性表如表2-1所示:
表2-1 PCI总线配置寄存器
偏移 | 寄存器 | 属性 | 复位值 |
---|---|---|---|
0x0000_8000 | CFG_ADDR | 可读写 | 0x00000000 |
0x0000_8004 | CFG_DATA | 可读写 | 0x00000000 |
0x0000_8008 | INT_ACK | 只读 | 0x00000000 |
在MPC8548处理器中,所有内部寄存器都使用存储器映射方式进行寻址,并存放在BASE_ADDR变量为起始地址的“1MB连续的物理地址空间”中。PowerPC处理器可以通过BASE_ADDR+Offset的方式访问表2-1中的寄存器。
MPC8548处理器使用CFG_ADDR寄存器和CFG_DATA寄存器访问PCI设备的配置空间(上边一已提到)。其中用CFG_ADDR寄存器保存PCI设备的ID号和寄存器号,CFG_ADDR寄存器的各个字段的详细说明如下所示:
当该位为1时,HOST主桥使能对PCI设备配置空间的访问。当HOST处理器对CFG_DATA寄存器进行访问时,HOST主桥将对这个寄存器的访问转换为PCI配置读写总线事务并发送到PCI总线上。
Bus Number字段记录PCI设备所在的总线号。
Device Number字段记录PCI设备的设备号。
Function Number字段记录PCI设备的功能号。
Register Number字段记录PCI设备的配置寄存器号。
MPC8548处理器访问PCI设备的配置空间时,首先需要在CFG_ADDR寄存器中设置这个PCI设备对应的总线号、设备号、功能号和寄存器号;然后使能Enable位;之后当MPC8548处理器对CFG_DATA寄存器进行读写访问时, HOST主桥将这个存储器读写访问转换为PCI配置读写请求,并发送到PCI总线上。如果Enable位没有使能,处理器对CFG_DATA的访问不过是一个普通的I/O访问,HOST主桥并不能将其转换为PCI读写配置请求。
HOST主桥根据CFG_ADDR寄存器中的ID号,生成PCI配置读写总线事务,并将该事务通过ID译码方式发送到指定的PCI设备。PCI设备将接收来自配置写总线事务的数据,或者为配置读总线事务提供数据。
值得注意的是,在PowerPC处理器中,在CFG_DATA寄存器中保存的数据采用大端模式进行编址,而PCI设备的配置寄存器采用小端模式编址,因此,HOST主桥需要进行模式转换。下面以源代码2?1为例说明PowerPC处理器如何访问PCI配置空间。
源代码2-1?PowerPC处理器访问PCI配置空间
stw r0, 0(r1)
ld r3,0(r2)
首先假设寄存器r1的初始值为BASE_ADDR+0x0_8000(即CFG_ADDR寄存器的地址),寄存器r0的初始值为0x80000008,寄存器r2的初始值为BASE_ADDR+0x0_8004 (即CFG_DATA寄存器的地址),而指定PCI设备(总线号、设备号、功能号都为0)的配置寄存器的0x0B~0x08中的值为0x99887766。
这段源代码的执行步骤如下:
(1)将r0寄存器的值赋值到r1寄存器所指向的地址空间中,即初始化CFG_ADDR寄存器为0x80000008;
(2)从r2寄存器所指向的地址空间中读取数据到r3寄存器中,即从CFG_DATA寄存器中读取数据到r3寄存器。
在MPC8548处理器中,源代码2?1执行完毕后,寄存器r3保存的值为0x66778899,而不是0x9988-6677。系统程序员在使用这个返回值时,一定要注意大小端模式的转换。
值得注意的是,源代码2?1可以使用lwbrx指令进行优化,该指令可以在读取数据的同时,进行大小端模式的转换。
处理器读取INT_ACK寄存器时,HOST主桥将这个读操作转换为PCI总线中断响应事务。PCI总线中断响应事务的作用是通过PCI总线读取中断控制器的中断向量号,这样做的前提是中断控制器需要连接在PCI总线上。
PowerPC处理器使用的MPIC中断控制器不是挂接在PCI总线上,而是挂接在SoC平台总线上。因此,PCI总线提供的中断应答事务在这个处理器系统中并没有太大用途。但是并不排除某些PowerPC处理器系统使用了挂接在PCI总线上的中断控制器,比如PCI南桥芯片,此时PowerPC处理器系统需要使用中断应答事务读取PCI南桥中的中断控制器,以获取中断向量号。
更多内容请看下回。