/**
* A structure describing an ID for a PCI driver. Each driver provides a
* table of these IDs for each device that it supports.
*/
struct rte_pci_id {
uint16_t vendor_id; /< Vendor ID or PCI_ANY_ID. */
uint16_t device_id; /< Device ID or PCI_ANY_ID. */
uint16_t subsystem_vendor_id; /< Subsystem vendor ID or PCI_ANY_ID. */
uint16_t subsystem_device_id; /< Subsystem device ID or PCI_ANY_ID. */
};
已ixgbe类型的网卡为例,注册的信息为rte\_ixgbe\_pmd:
static struct eth_driver rte_ixgbe_pmd = {
.pci_drv = {
.name = “rte_ixgbe_pmd”,
.id_table = pci_id_ixgbe_map,
.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
RTE_PCI_DRV_DETACHABLE,
},
.eth_dev_init = eth_ixgbe_dev_init,
.eth_dev_uninit = eth_ixgbe_dev_uninit,
.dev_private_size = sizeof(struct ixgbe_adapter),
};
至此,注册的每款驱动的设备初始化,支持的设备等信息以及系统中所有的pci设备信息就已经都有了,分别记录在”pci\_driver\_list”和”pci\_device\_list”这两个全局的链表中,接下来就可以完成设备匹配驱动,别初始化设备了。
#### 4、网卡设备初始化
rte\_eal\_init()函数接下来调用rte\_eal\_pci\_probe()函数完成具体的设备的初始化
/*
* Scan the content of the PCI bus, and call the devinit() function for
* all registered drivers that have a matching entry in its id_table
* for discovered devices.
*/
int rte_eal_pci_probe(void)
{
struct rte_pci_device *dev = NULL;
struct rte_devargs *devargs;
int probe_all = 0;
int ret = 0;
/* 如果配置了白名单,只初始化白名单中的设备,否则所有支持的设备都初始化 */
if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)
probe_all = 1;
TAILQ_FOREACH(dev, &pci_device_list, next) {
/* set devargs in PCI structure */
devargs = pci_devargs_lookup(dev);
if (devargs != NULL)
dev->devargs = devargs;
/* probe all or only whitelisted devices */
if (probe_all)
ret = pci_probe_all_drivers(dev);
else if (devargs != NULL &&
devargs->type == RTE_DEVTYPE_WHITELISTED_PCI)
ret = pci_probe_all_drivers(dev);
if (ret < 0)
rte_exit(EXIT_FAILURE, “Requested device " PCI_PRI_FMT
" cannot be used\n”, dev->addr.domain, dev->addr.bus,
dev->addr.devid, dev->addr.function);
}
return 0;
}
rte\_eal\_pci\_probe\_one\_driver()函数中,在probe一个具体的设备时,比较vendor id、device id,然后映射设备资源、调用驱动的设备初始化函数:
/*
* If vendor/device ID match, call the devinit() function of the
* driver.
*/
static int
rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev)
{
int ret;
const struct rte_pci_id *id_table;
for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
/* check if device’s identifiers match the driver’s ones */
… …
if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
/* map resources for devices that use igb_uio /
ret = rte_eal_pci_map_device(dev);
if (ret != 0)
return ret;
} else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND &&
rte_eal_process_type() == RTE_PROC_PRIMARY) {
/ unbind current driver /
if (pci_unbind_kernel_driver(dev) < 0)
return -1;
}
/ call the driver devinit() function /
return dr->devinit(dr, dev);
}
/ return positive value if driver doesn’t support this device