文章目录
- CPU 地址空间与PCI 地址空间
- PCI 地址空间
- CPU 地址空间
- Host Bridge
- PCI 设备连接框图
- PCI 硬件信号
- Configuration Commands
CPU 地址空间与PCI 地址空间
PCI 地址空间
PCI总线具有32位数据/地址复用总线,所以其存储地址空间为2的32次方=4GB。也就是PCI上的所有设备共同映射到这4GB上,每个PCI设备占用唯一的一段PCI地址,以便于PCI总线统一寻址。每个PCI设备通过PCI寄存器中的基地址寄存器来指定映射的首地址。PCI地址空间对应于计算机系统结构中的PCI总线。
CPU 地址空间
如果处理器具有32位的地址总线,其理论可寻址空间为2的32次方=4GB。在不同的物理位置上存在着不同设备,不同的设备又各自具有存储器,那么CPU如何访问这些存储器呢?CPU把系统中各个设备的存储空间映射到一个统一的存储空间上,称为系统存储空间共4GB,这样CPU就可以访问到所有的存储器。比如PCI存储器映射到从0xFFF80000开始的地址空间,显卡映射到0XFFF00000。
Host Bridge
PCI 地址空间和CPU地址空间的范围都是0x00000000—0xFFFFFFFF
。主机端只能发起/响应CPU地址空间的地址访问操作,PCI设备也只能发起/响应对于PCI地址空间的访问请求,因此,在PCI地址空间和CPU地址空间之间就存在一层映射关系,如下图所示。
当CPU需要访问PCI地址空间 0xF0000000—0xFFFFFFFF这段地址时,根据图2中的映射关系,CPU需要发出对0x90000000—0x9FFFFFFF这段地址空间中相应地址的访问请求。当CPU发出对0xF0000008地址的访问请求时,实际访问的则是CPU地址空间的0xF0000008地址,并不能访问到PCI地址空间的0xF0000008地址。只有当CPU发出对0x90000008地址的访问请求时,才能真正访问到PCI地址空间的0xF0000008地址。反之亦然,当PCI设备需要访问CPU地址空间0x00000000—0x7FFFFFFF这段地址时,PCI设备实际发出的是对PCI地址空间0x30000000—0xAFFFFFFF这段地址空间的访问操作。
由于在CPU地址空间和PCI地址空间需要进行地址映射,因此就需要一个具有地址转换功能的角色,该角色就是PCI的HOST主桥。以CPU访问PCI设备为例,当CPU需要发起对某一个PCI设备的访问时,会发出对相应CPU地址空间的访问请求,然后由HOST主桥将该CPU地址空间转换为对应的PCI地址空间,然后再由对应的PCI设备对该访问请求进行响应。因此,任何一个PCI设备只有在CPU地址空间具有相应的映像地址时,才能被CPU所访问。
由以上分析可知,HOST主桥负责隔离CPU地址空间和PCI地址空间,并完成CPU与PCI设备之间的地址映射和数据交换。
PCI 设备连接框图
CPU 发出的地址位于CPU的地址空间,CPU 发出的某个地址有可能是访问内存的或者是访问某个其它模块的,也有可能是访问某个PCI 设备的,CPU 发出的地址范围不一样,它访问到的外设就不一样。假设CPU 发出一个访问PCI 设备的地址 Address0, 那么 CPU 下面连接着的 Bridge 会把 CPU 发出来的地址转换为 PCI_Address, PCI_Address 地址通过 PCI 总线会到达各个设备,那么,那么多设备,谁来相应PCI_Address 这个地址呢?
- 首先,驱动程序初始化的时候会去扫描 PCI 设备,获取PCI设备需要的地址空间大小,比如 设备 LAN 需要 1K的空间, SCSI 需要1M的空间,所以需要首先确认每个设备需要多大范围的空间。具体就是读PCI设备配置空间的寄存器,就可以知道该设备属于哪类设备、该设备要申请的资源(要申请多大的空间)。
- 然后,驱动程序要把 PCI 地址空间中的某一块地址分配给这些设备,所谓分配地址空间给某个设备,就是从从PCI 地址空间中划出一段,表示以后如果要访问这块地址空间时,就是访问这个设备。具体操作就是分配地址范围,然后将地址范围写回到配置空间中的寄存器中。
PCI 硬件信号
从图中可以看到有 AD 信号,也即地址和数据复用信号,一共是32条线,上面传输的时地址或者是数据,那么如何区分AD上传输的时地址信号还是数据信号呢? 答案就是通过 FRAM信号,在FRAM信号为低的时候,在第一个时钟时,AD 总线上传输的就是地址信号,在后续的时钟里传输就是Data。
那么就有个问题:一开始的时候,PCI 总线上的各个设备还没有地址空间,它们也不知道在PCI 总线传输的信号时访问谁的,那么如何去选中某个PCI 设备呢?
从上图中可以看到有个 IDSEL 引脚,它的作用就是配置设备时用来选中某个PCI 设备的,我们顺便看下PCI其他引脚的作用。
我们继续看下如何选中某个PCI 设备的,如下图所示:
在 PCI bus0 上挂有3个设备,第2个设备也是个PCI 桥,它的线面就是BUS1, 在BUS1 下面有第4个设备和第5个设备,刚开始的这个5个设备都没有配置,那么如何去选中某个设备,就是通过图中的 IDSEL信号来选中。比如对于设备1 它的 IDSEL 肯定是某一个信号,同样对于设备2,它的IDSEL肯定是另外一个信号,到底是通过哪个引脚来选中这个设备,不同的 Root Bridge 有不同的设计,比如可以设计成功过 AD31 信号来选中 PCI 设备1,通过 AD30 来选中设备2,当然也可以通过其他引脚来单独选中PCI设备1。再比如可以通过 BUS1中的AD31来选中PCI 设备4,使用总线BUS1中的AD30来选中PCI 设备5.
下图是type0 配置空间的头部信息。
通过 IDSEL 来选中某个 PCI设备,然后去读取它的配置寄存器,去设置它的配置寄存器,每个设备都有245字节的配置寄存器。此外每个设备可能有多种功能,每个PCI设备最多可以有八种功能,对于每种功能它都有256字节的配置寄存器,那么前面提到了通过 IDSEL 可以选择某个设备,那么怎选择设备中的某个功能呢? 怎么选择配置空间中某一个寄存器?
Configuration Commands
如上图所示 Type0 就是用来访问一般的PCI设备,Type1 用来访问桥后面的设备,紧着这再看时序图:
通过上面图 3-1 和图 3-4 我们就可以知道如何访问配置空间:
- 首先通过 IDSEL 来选中某个 PCI 设备;
- 如果想选中设备中的某个功能某个寄存器,就通过 ADDRESS,在 AD[31-0] 这32条信号线上指定功能function,指定寄存器 REG,如第一个图中的 Type0 的
bit[10:8]
可以用来指定function,bit[7:2]
可以用来选中 寄存器。 在FRAM 信号为底的时候,在第一个时钟 FRAM有效(低电平),这个时候 AD上传输的就是 address, 后续的时钟传输就是data; - 通过 C/BE(Command/Byte Enable) 信号来判断是读还是写:
如果是读写配置空间,那么 C/BE 的4个信号传输的值应该是
0b1010
或者0b1011
。当设备配置好之后,可以通过 I/O Read 或者 IO Write 来访问它,也可以通过memory read 或者 memory write 来访问它。
推荐阅读:
https://myfj.ijournals.cn/myfjsjyyj/article/html/20240105?st=article_issue
https://blog.csdn.net/zjy900507/article/details/81740345