1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Advanced Micro Devices, Inc. All rights reserved.
11 #include <rte_string_fns.h>
15 static const char * const uio_module_names[] = {
21 ccp_check_pci_uio_module(void)
27 fp = fopen(PROC_MODULES, "r");
31 while (uio_module_names[i] != NULL) {
32 while (fgets(buf, sizeof(buf), fp) != NULL) {
33 if (!strncmp(buf, uio_module_names[i],
34 strlen(uio_module_names[i])))
40 printf("Insert igb_uio or uio_pci_generic kernel module(s)");
41 return -1;/* uio not inserted */
45 * split up a pci address into its constituent parts.
48 ccp_parse_pci_addr_format(const char *buf, int bufsize, uint16_t *domain,
49 uint8_t *bus, uint8_t *devid, uint8_t *function)
51 /* first split on ':' */
59 char *str[PCI_FMT_NVAL];
60 /* last element-separator is "." not ":" */
63 char *buf_copy = strndup(buf, bufsize);
68 if (rte_strsplit(buf_copy, bufsize, splitaddr.str, PCI_FMT_NVAL, ':')
71 /* final split is on '.' between devid and function */
72 splitaddr.function = strchr(splitaddr.devid, '.');
73 if (splitaddr.function == NULL)
75 *splitaddr.function++ = '\0';
77 /* now convert to int values */
79 *domain = (uint8_t)strtoul(splitaddr.domain, NULL, 16);
80 *bus = (uint8_t)strtoul(splitaddr.bus, NULL, 16);
81 *devid = (uint8_t)strtoul(splitaddr.devid, NULL, 16);
82 *function = (uint8_t)strtoul(splitaddr.function, NULL, 10);
86 free(buf_copy); /* free the copy made with strdup */
94 ccp_pci_parse_sysfs_value(const char *filename, unsigned long *val)
100 f = fopen(filename, "r");
103 if (fgets(buf, sizeof(buf), f) == NULL) {
107 *val = strtoul(buf, &end, 0);
108 if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) {
116 /** IO resource type: */
117 #define IORESOURCE_IO 0x00000100
118 #define IORESOURCE_MEM 0x00000200
120 /* parse one line of the "resource" sysfs file (note that the 'line'
121 * string is modified)
124 ccp_pci_parse_one_sysfs_resource(char *line, size_t len, uint64_t *phys_addr,
125 uint64_t *end_addr, uint64_t *flags)
127 union pci_resource_info {
133 char *ptrs[PCI_RESOURCE_FMT_NVAL];
136 if (rte_strsplit(line, len, res_info.ptrs, 3, ' ') != 3)
139 *phys_addr = strtoull(res_info.phys_addr, NULL, 16);
140 *end_addr = strtoull(res_info.end_addr, NULL, 16);
141 *flags = strtoull(res_info.flags, NULL, 16);
148 /* parse the "resource" sysfs file */
150 ccp_pci_parse_sysfs_resource(const char *filename, struct rte_pci_device *dev)
155 uint64_t phys_addr, end_addr, flags;
157 fp = fopen(filename, "r");
161 for (i = 0; i < PCI_MAX_RESOURCE; i++) {
162 if (fgets(buf, sizeof(buf), fp) == NULL)
164 if (ccp_pci_parse_one_sysfs_resource(buf, sizeof(buf),
165 &phys_addr, &end_addr, &flags) < 0)
168 if (flags & IORESOURCE_MEM) {
169 dev->mem_resource[i].phys_addr = phys_addr;
170 dev->mem_resource[i].len = end_addr - phys_addr + 1;
171 /* not mapped for now */
172 dev->mem_resource[i].addr = NULL;
184 ccp_find_uio_devname(const char *dirname)
189 char dirname_uio[PATH_MAX];
190 unsigned int uio_num;
193 /* depending on kernel version, uio can be located in uio/uioX
196 snprintf(dirname_uio, sizeof(dirname_uio), "%s/uio", dirname);
197 dir = opendir(dirname_uio);
199 /* retry with the parent directory might be different kernel version*/
200 dir = opendir(dirname);
205 /* take the first file starting with "uio" */
206 while ((e = readdir(dir)) != NULL) {
207 /* format could be uio%d ...*/
208 int shortprefix_len = sizeof("uio") - 1;
209 /* ... or uio:uio%d */
210 int longprefix_len = sizeof("uio:uio") - 1;
213 if (strncmp(e->d_name, "uio", 3) != 0)
216 /* first try uio%d */
218 uio_num = strtoull(e->d_name + shortprefix_len, &endptr, 10);
219 if (errno == 0 && endptr != (e->d_name + shortprefix_len)) {
224 /* then try uio:uio%d */
226 uio_num = strtoull(e->d_name + longprefix_len, &endptr, 10);
227 if (errno == 0 && endptr != (e->d_name + longprefix_len)) {