PCI设备初始化(一)

访问PCI设备

我们知道CPU和网卡是通过PCI总线相连的,CPU可以直接访问系统内存(虚拟地址),也可以通过映射间接访问总线地址,那CPU怎么访问网卡的存储空间呢?

每个网卡都有自己的存储空间,这些空间的卡上地址(在网卡上的地址)本质上是局部的,所以都从0开始,它们不与总线直接相连,在把网卡插上总线并加电之初,从总线上还访问不到这些空间

系统初始化时扫描PCI总线上的各个PCI设备(包括网卡),为这些设备分配总线地址,并建立起其卡上地址和总线地址的映射,那映射是怎么建立起来的?

每个PCI设备上都有用来建立映射的配置寄存器组配置空间),系统初始化时通过这组寄存器来为设备"配置"总线地址,那CPU怎么访问这组寄存器呢?这就又回到原点了

PCI标准规定配置寄存器组最大256 byte,其中开头64 byte是标准的(对每个PCI设备都一样),所有PCI设备的配置寄存器组都使用相同的地址(卡上地址或偏移量)

这里写图片描述

系统在IO地址空间预留了八个字节(0xCF8~0xCFF),其中前四个字节做地址寄存器,后四个字节做数据寄存器,当CPU访问某个设备的某个配置寄存器时,首先通过I/O命令向地址寄存器写入目标地址(包括总线号、设备号、功能号、寄存器地址的综合地址),然后通过I/O命令读写数据寄存器

综合地址的结构如下图所示,其中寄存器地址的高6位用于寻址最大64 word(256 byte)的配置寄存器组

这里写图片描述

如下图所示,一个256B代表一个配置寄存器组,最多有2^16个配置寄存器组(最大有16MB)

这里写图片描述

写入综合地址后,从0号总线开始,每个PCI桥将综合地址中的总线号和自己的总线号相比,若符合,根据设备号+功能号寻找设备;若不符合,将综合地址传递给下一级总线的PCI桥继续寻找,直到找到设备,最后根据8位寄存器地址找到配置寄存器,此时通过I/O命令读写数据寄存器就可以读写配置寄存器了

系统初始化时扫描PCI总线上的各个PCI设备(包括网卡),为这些设备分配总线地址,设备的每个BAR对应设备的一段存储空间,系统通过将总线地址写入BAR就建立了存储空间的卡上地址和总线地址的映射

设备驱动程序调用pci_ioremap_bar()将写入BAR的总线地址(保存在resource数组中)映射到系统内存的虚拟地址,之后CPU就可以通过虚拟地址访问PCI设备的存储空间,而不用再通过IO命令了

探测PCI设备

配置寄存器组中的Header Type为0表示普通PCI设备、为1表示PCI桥,PCI桥根据功能又分为Host-PCI桥、PCI-PCI桥、PCI-ISA桥、PCI-CardBus桥等

每个PCI总线都挂在一个PCI桥下,其中0号总线挂在Host-PCI桥下(CPU通过Host-PCI桥连到0号总线),所有总线组成一颗总线树

这里写图片描述

直接探测

探测PCI设备有BIOS探测直接探测两种方式,两者都是从Host-PCI桥开始深度优先搜索总线树上的所有设备,我们以直接探测为例讨论

  • 申请IO地址空间0xCF8~0xCFF,探测Host-PCI桥
12345
arch_initcallpci_arch_initpci_direct_probepci_check_type1pci_sanity_check
  • 深度优先搜索总线树,读取BAR,写入resource
123456
subsys_initcallpci_legacy_initpcibios_scan_rootpci_scan_bus_parentedpci_scan_child_buspci_scan_slot
pcibios_fixup_bus
pci_scan_bridge
67891011
pci_scan_slotpci_scan_single_devicepci_scan_devicepci_setup_devicepci_read_bases__pci_read_base
pcibios_fixup_buspci_read_bridge_bases
pci_scan_bridgepci_scan_child_bus
  • 深度优先搜索总线树,分配总线地址,写入BAR建立映射
1234
subsys_initcallpcibios_initpcibios_resource_surveypcibios_allocate_bus_resources
为每个总线分配地址
pcibios_allocate_resources
为每个PCI设备分配地址
fs_initcallpcibios_assign_resources
为起始地址已改成0的区间分配地址
pci_assign_unassigned_resourcespci_bus_assign_resources
4567
pcibios_allocate_bus_resourcespci_find_parent_resource
request_resource__request_resource
pcibios_allocate_resourcesalloc_resourcepci_find_parent_resource
request_resource__request_resource
pci_bus_assign_resourcespbus_assign_resources_sortedpci_assign_resource__pci_assign_resource
78910
__pci_assign_resourcepci_bus_alloc_resourceallocate_resourcefind_resource
__request_resource
pci_update_resource

深度优先搜索

这里写图片描述

这里写图片描述

参考资料

《Linux内核源代码情景分析》
《PCI Express 体系结构导读》
http://blog.sina.com.cn/s/articlelist_1685243084_3_1.html
http://blog.chinaaet.com/justlxy/p/5100057779

  • 12
    点赞
  • 108
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值