1
2
3
4
5#include <dirent.h>
6#include <fcntl.h>
7#include <stdio.h>
8#include <string.h>
9#include <unistd.h>
10
11#include <rte_string_fns.h>
12
13#include "ccp_pci.h"
14
15static const char * const uio_module_names[] = {
16 "igb_uio",
17 "uio_pci_generic",
18};
19
20int
21ccp_check_pci_uio_module(void)
22{
23 FILE *fp;
24 int i;
25 char buf[BUFSIZ];
26
27 fp = fopen(PROC_MODULES, "r");
28 if (fp == NULL)
29 return -1;
30 i = 0;
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]))) {
35 fclose(fp);
36 return i;
37 }
38 }
39 i++;
40 rewind(fp);
41 }
42 fclose(fp);
43 printf("Insert igb_uio or uio_pci_generic kernel module(s)");
44 return -1;
45}
46
47
48
49
50int
51ccp_parse_pci_addr_format(const char *buf, int bufsize, uint16_t *domain,
52 uint8_t *bus, uint8_t *devid, uint8_t *function)
53{
54
55 union splitaddr {
56 struct {
57 char *domain;
58 char *bus;
59 char *devid;
60 char *function;
61 };
62 char *str[PCI_FMT_NVAL];
63
64 } splitaddr;
65
66 char *buf_copy = strndup(buf, bufsize);
67
68 if (buf_copy == NULL)
69 return -1;
70
71 if (rte_strsplit(buf_copy, bufsize, splitaddr.str, PCI_FMT_NVAL, ':')
72 != PCI_FMT_NVAL - 1)
73 goto error;
74
75 splitaddr.function = strchr(splitaddr.devid, '.');
76 if (splitaddr.function == NULL)
77 goto error;
78 *splitaddr.function++ = '\0';
79
80
81 errno = 0;
82 *domain = (uint8_t)strtoul(splitaddr.domain, NULL, 16);
83 *bus = (uint8_t)strtoul(splitaddr.bus, NULL, 16);
84 *devid = (uint8_t)strtoul(splitaddr.devid, NULL, 16);
85 *function = (uint8_t)strtoul(splitaddr.function, NULL, 10);
86 if (errno != 0)
87 goto error;
88
89 free(buf_copy);
90 return 0;
91error:
92 free(buf_copy);
93 return -1;
94}
95
96int
97ccp_pci_parse_sysfs_value(const char *filename, unsigned long *val)
98{
99 FILE *f;
100 char buf[BUFSIZ];
101 char *end = NULL;
102
103 f = fopen(filename, "r");
104 if (f == NULL)
105 return -1;
106 if (fgets(buf, sizeof(buf), f) == NULL) {
107 fclose(f);
108 return -1;
109 }
110 *val = strtoul(buf, &end, 0);
111 if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) {
112 fclose(f);
113 return -1;
114 }
115 fclose(f);
116 return 0;
117}
118
119
120#define IORESOURCE_IO 0x00000100
121#define IORESOURCE_MEM 0x00000200
122
123
124
125
126static int
127ccp_pci_parse_one_sysfs_resource(char *line, size_t len, uint64_t *phys_addr,
128 uint64_t *end_addr, uint64_t *flags)
129{
130 union pci_resource_info {
131 struct {
132 char *phys_addr;
133 char *end_addr;
134 char *flags;
135 };
136 char *ptrs[PCI_RESOURCE_FMT_NVAL];
137 } res_info;
138
139 if (rte_strsplit(line, len, res_info.ptrs, 3, ' ') != 3)
140 return -1;
141 errno = 0;
142 *phys_addr = strtoull(res_info.phys_addr, NULL, 16);
143 *end_addr = strtoull(res_info.end_addr, NULL, 16);
144 *flags = strtoull(res_info.flags, NULL, 16);
145 if (errno != 0)
146 return -1;
147
148 return 0;
149}
150
151
152int
153ccp_pci_parse_sysfs_resource(const char *filename, struct rte_pci_device *dev)
154{
155 FILE *fp;
156 char buf[BUFSIZ];
157 int i;
158 uint64_t phys_addr, end_addr, flags;
159
160 fp = fopen(filename, "r");
161 if (fp == NULL)
162 return -1;
163
164 for (i = 0; i < PCI_MAX_RESOURCE; i++) {
165 if (fgets(buf, sizeof(buf), fp) == NULL)
166 goto error;
167 if (ccp_pci_parse_one_sysfs_resource(buf, sizeof(buf),
168 &phys_addr, &end_addr, &flags) < 0)
169 goto error;
170
171 if (flags & IORESOURCE_MEM) {
172 dev->mem_resource[i].phys_addr = phys_addr;
173 dev->mem_resource[i].len = end_addr - phys_addr + 1;
174
175 dev->mem_resource[i].addr = NULL;
176 }
177 }
178 fclose(fp);
179 return 0;
180
181error:
182 fclose(fp);
183 return -1;
184}
185
186int
187ccp_find_uio_devname(const char *dirname)
188{
189
190 DIR *dir;
191 struct dirent *e;
192 char dirname_uio[PATH_MAX];
193 unsigned int uio_num;
194 int ret = -1;
195
196
197
198
199 snprintf(dirname_uio, sizeof(dirname_uio), "%s/uio", dirname);
200 dir = opendir(dirname_uio);
201 if (dir == NULL) {
202
203 dir = opendir(dirname);
204 if (dir == NULL)
205 return -1;
206 }
207
208
209 while ((e = readdir(dir)) != NULL) {
210
211 int shortprefix_len = sizeof("uio") - 1;
212
213 int longprefix_len = sizeof("uio:uio") - 1;
214 char *endptr;
215
216 if (strncmp(e->d_name, "uio", 3) != 0)
217 continue;
218
219
220 errno = 0;
221 uio_num = strtoull(e->d_name + shortprefix_len, &endptr, 10);
222 if (errno == 0 && endptr != (e->d_name + shortprefix_len)) {
223 ret = uio_num;
224 break;
225 }
226
227
228 errno = 0;
229 uio_num = strtoull(e->d_name + longprefix_len, &endptr, 10);
230 if (errno == 0 && endptr != (e->d_name + longprefix_len)) {
231 ret = uio_num;
232 break;
233 }
234 }
235 closedir(dir);
236 return ret;
237
238
239}
240