一、概述
pci_scan和pci_probe相互关联,
1.pci_scan扫描所有可用的设备,提取出来各种信息,其中最重要的是得到了BAR0的地址,给到了dev->mem_resource[i].phys_addr。
2.pci_probe会轮询pci_scan扫到的设备,然后再轮询注册的驱动,比较驱动的device_id和vender_id,如果对,就会先把/sys/bus/pci/devices/0000:01:00.0/resource0文件映射到用户态,得到虚拟地址,给到dev->mem_resource[res_idx].addr = mapaddr。
这样dev->mem_resource[i].phys_addr和dev->mem_resource[res_idx].addr = mapaddr,设备的物理地址和映射的虚拟地址全部得到。
3.下面就会调用驱动的probe函数,调用驱动里面的dev_init函数,得到hw->hw_addr的地址,PCI的配置空间进行初始化,后面所有设备的配置基地址都是在hw->hw_addr基础上进行。
二、pci_scan
1.函数功能
1)扫描设备
通过rte_pci_scan扫描"/sys/bus/pci/devices"文件夹下面的设备ID,在readdir函数里面会把下面的文件夹全部轮询一遍
$ ls /sys/bus/pci/devices/
0000:00:00.0 0000:00:01.1 0000:00:02.1 0000:00:08.1 0000:00:14.3 0000:00:18.2 0000:00:18.5 0000:01:00.0 0000:03:00.0 0000:05:00.2 0000:05:00.5 0000:06:00.1
0000:00:00.2 0000:00:01.2 0000:00:02.2 0000:00:08.2 0000:00:18.0 0000:00:18.3 0000:00:18.6 0000:01:00.1 0000:04:00.0 0000:05:00.3 0000:05:00.6
0000:00:01.0 0000:00:02.0 0000:00:08.0 0000:00:14.0 0000:00:18.1 0000:00:18.4 0000:00:18.7 0000:02:00.0 0000:05:00.0 0000:05:00.4 0000:06:00.0
2)解析数据
进入pci-id文件夹后,解析数据,包括各类ID
其中 pci_parse_sysfs_resource (/sys/bus/pci/devices/0000:01:00.0/resource)是BAR的物理地址,赋值给mem_resource
if (flags & IORESOURCE_MEM) {
dev->mem_resource[i].phys_addr = phys_addr;
dev->mem_resource[i].len = end_addr - phys_addr + 1;
/* not mapped for now */
dev->mem_resource[i].addr = NULL;
}
3)添加节点
通过函数rte_pci_add_device,把dev添加到rte_pci_bus.device_list里面。
三、pci_probe
1.函数功能
1)轮询device和driver
轮询所有的设备和驱动PMD,比较二者的device_id和vender_id,
2)pci_uio_alloc_resource
如果能打开/dev/uio%u和/sys/class/uio/uio%u/device/config文件,申请空间。
3)映射配置空间
将/sys/bus/pci/devices/0000:01:00.0/resource0文件映射到用户态空间,最后得到了dev->mem_resource[res_idx].addr = mapaddr虚拟地址,这个就是后面驱动常用的hw->hw_addr的地址。
4)调用驱动的probe函数
mmap成功后,就会调用驱动的probe函数,然后dev_init,调用驱动对应的初始化函数,会赋值hw->hw_addr = dev->mem_resource[0].addr ,
最后对配置空间进行初始化。