https://blog.csdn.net/Jmilk/article/details/106007926
打開 dpdk-18.08/drivers/bus/pci/linux/pci.c 可以看到以下內容:
#define PCI_MAX_RESOURCE 6 /* * PCI 掃描文件系統下的 resource 文件 * @param filename: 通常為 /sys/bus/pci/devices/{pci_addr}/resource 文件 * @param dev[out]: dpdk 中對一個 PCI 設備的抽象 */ static int pci_parse_sysfs_resource(const char *filename, struct rte_pci_device *dev) { FILE *f; char buf[BUFSIZ]; int i; uint64_t phys_addr, end_addr, flags; f = fopen(filename, "r"); // 先打開 resource 文件,只讀 if (f == NULL) { RTE_LOG(ERR, EAL, "Cannot open sysfs resource\n"); return -1; } // 掃描 6 次,因為 PCI 最多有 6 個 BAR for (i = 0; i<PCI_MAX_RESOURCE; i++) { if (fgets(buf, sizeof(buf), f) == NULL) { RTE_LOG(ERR, EAL, "%s(): cannot read resource\n", __func__); goto error; } // 掃描 resource 文件拿到 BAR if (pci_parse_one_sysfs_resource(buf, sizeof(buf), &phys_addr, &end_addr, &flags) < 0) goto error; // 如果是 Memory BAR,則進行記錄 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; } } fclose(f); return 0; error: fclose(f); return -1; } /* * 掃描 PCI resource 文件中的某一行 * @param line: 某一行 * @param len: 長度,為第一個參數字符串的長度 * @param phys_addr[out]: PCI BAR 的起始地址,這個地址要 mmap() 才能用 * @param end_addr[out]: PCI BAR 的結束地址 * @param flags[out]: PCI BAR 的標志 */ int pci_parse_one_sysfs_resource(char *line, size_t len, uint64_t *phys_addr, uint64_t *end_addr, uint64_t *flags) { union pci_resource_info { struct { char *phys_addr; char *end_addr; char *flags; }; char *ptrs[PCI_RESOURCE_FMT_NVAL]; } res_info; // 字符串處理 if (rte_strsplit(line, len, res_info.ptrs, 3, ' ') != 3) { RTE_LOG(ERR, EAL, "%s(): bad resource format\n", __func__); return -1; } errno = 0; // 字符串處理,拿到 PCI BAR 起始地址、PCI BAR 結束地址、PCI BAR 標志 *phys_addr = strtoull(res_info.phys_addr, NULL, 16); *end_addr = strtoull(res_info.end_addr,