Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2014 Intel Corporation
3 : : */
4 : :
5 : : #include <string.h>
6 : : #include <unistd.h>
7 : : #include <fcntl.h>
8 : : #include <dirent.h>
9 : : #include <inttypes.h>
10 : : #include <sys/stat.h>
11 : : #include <sys/mman.h>
12 : : #include <sys/sysmacros.h>
13 : :
14 : : #if defined(RTE_ARCH_X86)
15 : : #include <sys/io.h>
16 : : #endif
17 : :
18 : : #include <rte_string_fns.h>
19 : : #include <rte_log.h>
20 : : #include <rte_pci.h>
21 : : #include <rte_bus_pci.h>
22 : : #include <rte_common.h>
23 : : #include <rte_malloc.h>
24 : :
25 : : #include "eal_filesystem.h"
26 : : #include "pci_init.h"
27 : : #include "private.h"
28 : :
29 : : void *pci_map_addr = NULL;
30 : :
31 : : #define OFF_MAX ((uint64_t)(off_t)-1)
32 : :
33 : : int
34 : 0 : pci_uio_read_config(const struct rte_intr_handle *intr_handle,
35 : : void *buf, size_t len, off_t offset)
36 : : {
37 : 0 : int uio_cfg_fd = rte_intr_dev_fd_get(intr_handle);
38 : :
39 [ # # ]: 0 : if (uio_cfg_fd < 0)
40 : : return -1;
41 : :
42 : 0 : return pread(uio_cfg_fd, buf, len, offset);
43 : : }
44 : :
45 : : int
46 : 0 : pci_uio_write_config(const struct rte_intr_handle *intr_handle,
47 : : const void *buf, size_t len, off_t offset)
48 : : {
49 : 0 : int uio_cfg_fd = rte_intr_dev_fd_get(intr_handle);
50 : :
51 [ # # ]: 0 : if (uio_cfg_fd < 0)
52 : : return -1;
53 : :
54 : 0 : return pwrite(uio_cfg_fd, buf, len, offset);
55 : : }
56 : :
57 : : int
58 : 0 : pci_uio_mmio_read(const struct rte_pci_device *dev, int bar,
59 : : void *buf, size_t len, off_t offset)
60 : : {
61 [ # # # # ]: 0 : if (bar >= PCI_MAX_RESOURCE || dev->mem_resource[bar].addr == NULL ||
62 [ # # ]: 0 : (uint64_t)offset + len > dev->mem_resource[bar].len)
63 : : return -1;
64 : 0 : memcpy(buf, (uint8_t *)dev->mem_resource[bar].addr + offset, len);
65 : 0 : return len;
66 : : }
67 : :
68 : : int
69 : 0 : pci_uio_mmio_write(const struct rte_pci_device *dev, int bar,
70 : : const void *buf, size_t len, off_t offset)
71 : : {
72 [ # # # # ]: 0 : if (bar >= PCI_MAX_RESOURCE || dev->mem_resource[bar].addr == NULL ||
73 [ # # ]: 0 : (uint64_t)offset + len > dev->mem_resource[bar].len)
74 : : return -1;
75 : 0 : memcpy((uint8_t *)dev->mem_resource[bar].addr + offset, buf, len);
76 : 0 : return len;
77 : : }
78 : :
79 : : static int
80 : 0 : pci_mknod_uio_dev(const char *sysfs_uio_path, unsigned uio_num)
81 : : {
82 : : FILE *f;
83 : : char filename[PATH_MAX];
84 : : int ret;
85 : : unsigned major, minor;
86 : : dev_t dev;
87 : :
88 : : /* get the name of the sysfs file that contains the major and minor
89 : : * of the uio device and read its content */
90 : : snprintf(filename, sizeof(filename), "%s/dev", sysfs_uio_path);
91 : :
92 : 0 : f = fopen(filename, "r");
93 [ # # ]: 0 : if (f == NULL) {
94 : 0 : RTE_LOG(ERR, EAL, "%s(): cannot open sysfs to get major:minor\n",
95 : : __func__);
96 : 0 : return -1;
97 : : }
98 : :
99 : 0 : ret = fscanf(f, "%u:%u", &major, &minor);
100 [ # # ]: 0 : if (ret != 2) {
101 : 0 : RTE_LOG(ERR, EAL, "%s(): cannot parse sysfs to get major:minor\n",
102 : : __func__);
103 : 0 : fclose(f);
104 : 0 : return -1;
105 : : }
106 : 0 : fclose(f);
107 : :
108 : : /* create the char device "mknod /dev/uioX c major minor" */
109 : : snprintf(filename, sizeof(filename), "/dev/uio%u", uio_num);
110 : 0 : dev = makedev(major, minor);
111 : 0 : ret = mknod(filename, S_IFCHR | S_IRUSR | S_IWUSR, dev);
112 [ # # ]: 0 : if (ret != 0) {
113 : 0 : RTE_LOG(ERR, EAL, "%s(): mknod() failed %s\n",
114 : : __func__, strerror(errno));
115 : 0 : return -1;
116 : : }
117 : :
118 : : return ret;
119 : : }
120 : :
121 : : /*
122 : : * Return the uioX char device used for a pci device. On success, return
123 : : * the UIO number and fill dstbuf string with the path of the device in
124 : : * sysfs. On error, return a negative value. In this case dstbuf is
125 : : * invalid.
126 : : */
127 : : static int
128 : 0 : pci_get_uio_dev(struct rte_pci_device *dev, char *dstbuf,
129 : : unsigned int buflen, int create)
130 : : {
131 : : struct rte_pci_addr *loc = &dev->addr;
132 : : int uio_num = -1;
133 : : struct dirent *e;
134 : : DIR *dir;
135 : : char dirname[PATH_MAX];
136 : :
137 : : /* depending on kernel version, uio can be located in uio/uioX
138 : : * or uio:uioX */
139 : :
140 : 0 : snprintf(dirname, sizeof(dirname),
141 : : "%s/" PCI_PRI_FMT "/uio", rte_pci_get_sysfs_path(),
142 : 0 : loc->domain, loc->bus, loc->devid, loc->function);
143 : :
144 : 0 : dir = opendir(dirname);
145 [ # # ]: 0 : if (dir == NULL) {
146 : : /* retry with the parent directory */
147 : 0 : snprintf(dirname, sizeof(dirname),
148 : : "%s/" PCI_PRI_FMT, rte_pci_get_sysfs_path(),
149 : 0 : loc->domain, loc->bus, loc->devid, loc->function);
150 : 0 : dir = opendir(dirname);
151 : :
152 [ # # ]: 0 : if (dir == NULL) {
153 : 0 : RTE_LOG(ERR, EAL, "Cannot opendir %s\n", dirname);
154 : 0 : return -1;
155 : : }
156 : : }
157 : :
158 : : /* take the first file starting with "uio" */
159 [ # # ]: 0 : while ((e = readdir(dir)) != NULL) {
160 : : /* format could be uio%d ...*/
161 : : int shortprefix_len = sizeof("uio") - 1;
162 : : /* ... or uio:uio%d */
163 : : int longprefix_len = sizeof("uio:uio") - 1;
164 : : char *endptr;
165 : :
166 [ # # ]: 0 : if (strncmp(e->d_name, "uio", 3) != 0)
167 : 0 : continue;
168 : :
169 : : /* first try uio%d */
170 : 0 : errno = 0;
171 : 0 : uio_num = strtoull(e->d_name + shortprefix_len, &endptr, 10);
172 [ # # # # ]: 0 : if (errno == 0 && endptr != (e->d_name + shortprefix_len)) {
173 : 0 : snprintf(dstbuf, buflen, "%s/uio%u", dirname, uio_num);
174 : 0 : break;
175 : : }
176 : :
177 : : /* then try uio:uio%d */
178 : 0 : errno = 0;
179 : 0 : uio_num = strtoull(e->d_name + longprefix_len, &endptr, 10);
180 [ # # # # ]: 0 : if (errno == 0 && endptr != (e->d_name + longprefix_len)) {
181 : 0 : snprintf(dstbuf, buflen, "%s/uio:uio%u", dirname, uio_num);
182 : : break;
183 : : }
184 : : }
185 : 0 : closedir(dir);
186 : :
187 : : /* No uio resource found */
188 [ # # ]: 0 : if (e == NULL)
189 : : return -1;
190 : :
191 : : /* create uio device if we've been asked to */
192 [ # # # # : 0 : if (rte_eal_create_uio_dev() && create &&
# # ]
193 : 0 : pci_mknod_uio_dev(dstbuf, uio_num) < 0)
194 : 0 : RTE_LOG(WARNING, EAL, "Cannot create /dev/uio%u\n", uio_num);
195 : :
196 : : return uio_num;
197 : : }
198 : :
199 : : void
200 : 0 : pci_uio_free_resource(struct rte_pci_device *dev,
201 : : struct mapped_pci_resource *uio_res)
202 : : {
203 : 0 : int uio_cfg_fd = rte_intr_dev_fd_get(dev->intr_handle);
204 : :
205 : 0 : rte_free(uio_res);
206 : :
207 [ # # ]: 0 : if (uio_cfg_fd >= 0) {
208 : 0 : close(uio_cfg_fd);
209 : 0 : rte_intr_dev_fd_set(dev->intr_handle, -1);
210 : : }
211 : :
212 [ # # ]: 0 : if (rte_intr_fd_get(dev->intr_handle) >= 0) {
213 : 0 : close(rte_intr_fd_get(dev->intr_handle));
214 : 0 : rte_intr_fd_set(dev->intr_handle, -1);
215 : 0 : rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UNKNOWN);
216 : : }
217 : 0 : }
218 : :
219 : : int
220 : 0 : pci_uio_alloc_resource(struct rte_pci_device *dev,
221 : : struct mapped_pci_resource **uio_res)
222 : : {
223 : : char dirname[PATH_MAX];
224 : : char cfgname[PATH_MAX];
225 : : char devname[PATH_MAX]; /* contains the /dev/uioX */
226 : : int uio_num, fd, uio_cfg_fd;
227 : : struct rte_pci_addr *loc;
228 : :
229 : : loc = &dev->addr;
230 : :
231 : : /* find uio resource */
232 : 0 : uio_num = pci_get_uio_dev(dev, dirname, sizeof(dirname), 1);
233 [ # # ]: 0 : if (uio_num < 0) {
234 : 0 : RTE_LOG(WARNING, EAL, " "PCI_PRI_FMT" not managed by UIO driver, "
235 : : "skipping\n", loc->domain, loc->bus, loc->devid, loc->function);
236 : 0 : return 1;
237 : : }
238 : : snprintf(devname, sizeof(devname), "/dev/uio%u", uio_num);
239 : :
240 : : /* save fd if in primary process */
241 : : fd = open(devname, O_RDWR);
242 [ # # ]: 0 : if (fd < 0) {
243 : 0 : RTE_LOG(ERR, EAL, "Cannot open %s: %s\n",
244 : : devname, strerror(errno));
245 : 0 : goto error;
246 : : }
247 : :
248 [ # # ]: 0 : if (rte_intr_fd_set(dev->intr_handle, fd))
249 : 0 : goto error;
250 : :
251 : : snprintf(cfgname, sizeof(cfgname),
252 : : "/sys/class/uio/uio%u/device/config", uio_num);
253 : :
254 : : uio_cfg_fd = open(cfgname, O_RDWR);
255 [ # # ]: 0 : if (uio_cfg_fd < 0) {
256 : 0 : RTE_LOG(ERR, EAL, "Cannot open %s: %s\n",
257 : : cfgname, strerror(errno));
258 : 0 : goto error;
259 : : }
260 : :
261 [ # # ]: 0 : if (rte_intr_dev_fd_set(dev->intr_handle, uio_cfg_fd))
262 : 0 : goto error;
263 : :
264 [ # # ]: 0 : if (dev->kdrv == RTE_PCI_KDRV_IGB_UIO) {
265 [ # # ]: 0 : if (rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UIO))
266 : 0 : goto error;
267 : : } else {
268 [ # # ]: 0 : if (rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UIO_INTX))
269 : 0 : goto error;
270 : :
271 : : /* set bus master that is not done by uio_pci_generic */
272 [ # # ]: 0 : if (rte_pci_set_bus_master(dev, true)) {
273 : 0 : RTE_LOG(ERR, EAL, "Cannot set up bus mastering!\n");
274 : 0 : goto error;
275 : : }
276 : : }
277 : :
278 : : /* allocate the mapping details for secondary processes*/
279 : 0 : *uio_res = rte_zmalloc("UIO_RES", sizeof(**uio_res), 0);
280 [ # # ]: 0 : if (*uio_res == NULL) {
281 : 0 : RTE_LOG(ERR, EAL,
282 : : "%s(): cannot store uio mmap details\n", __func__);
283 : 0 : goto error;
284 : : }
285 : :
286 : 0 : strlcpy((*uio_res)->path, devname, sizeof((*uio_res)->path));
287 : 0 : memcpy(&(*uio_res)->pci_addr, &dev->addr, sizeof((*uio_res)->pci_addr));
288 : :
289 : 0 : return 0;
290 : :
291 : 0 : error:
292 : 0 : pci_uio_free_resource(dev, *uio_res);
293 : 0 : return -1;
294 : : }
295 : :
296 : : int
297 : 0 : pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx,
298 : : struct mapped_pci_resource *uio_res, int map_idx)
299 : : {
300 : : int fd = -1;
301 : : char devname[PATH_MAX];
302 : : void *mapaddr;
303 : : struct rte_pci_addr *loc;
304 : : struct pci_map *maps;
305 : : int wc_activate = 0;
306 : :
307 [ # # ]: 0 : if (dev->driver != NULL)
308 : 0 : wc_activate = dev->driver->drv_flags & RTE_PCI_DRV_WC_ACTIVATE;
309 : :
310 : : loc = &dev->addr;
311 : 0 : maps = uio_res->maps;
312 : :
313 : : /* allocate memory to keep path */
314 : 0 : maps[map_idx].path = rte_malloc(NULL, sizeof(devname), 0);
315 [ # # ]: 0 : if (maps[map_idx].path == NULL) {
316 : 0 : RTE_LOG(ERR, EAL, "Cannot allocate memory for path: %s\n",
317 : : strerror(errno));
318 : 0 : return -1;
319 : : }
320 : :
321 : : /*
322 : : * open resource file, to mmap it
323 : : */
324 [ # # ]: 0 : if (wc_activate) {
325 : : /* update devname for mmap */
326 : 0 : snprintf(devname, sizeof(devname),
327 : : "%s/" PCI_PRI_FMT "/resource%d_wc",
328 : : rte_pci_get_sysfs_path(),
329 : 0 : loc->domain, loc->bus, loc->devid,
330 : 0 : loc->function, res_idx);
331 : :
332 : : fd = open(devname, O_RDWR);
333 [ # # # # ]: 0 : if (fd < 0 && errno != ENOENT) {
334 : 0 : RTE_LOG(INFO, EAL, "%s cannot be mapped. "
335 : : "Fall-back to non prefetchable mode.\n",
336 : : devname);
337 : : }
338 : : }
339 : :
340 [ # # ]: 0 : if (!wc_activate || fd < 0) {
341 : 0 : snprintf(devname, sizeof(devname),
342 : : "%s/" PCI_PRI_FMT "/resource%d",
343 : : rte_pci_get_sysfs_path(),
344 : 0 : loc->domain, loc->bus, loc->devid,
345 : 0 : loc->function, res_idx);
346 : :
347 : : /* then try to map resource file */
348 : : fd = open(devname, O_RDWR);
349 [ # # ]: 0 : if (fd < 0) {
350 : 0 : RTE_LOG(ERR, EAL, "Cannot open %s: %s\n",
351 : : devname, strerror(errno));
352 : 0 : goto error;
353 : : }
354 : : }
355 : :
356 : : /* try mapping somewhere close to the end of hugepages */
357 [ # # ]: 0 : if (pci_map_addr == NULL)
358 : 0 : pci_map_addr = pci_find_max_end_va();
359 : :
360 : 0 : mapaddr = pci_map_resource(pci_map_addr, fd, 0,
361 : 0 : (size_t)dev->mem_resource[res_idx].len, 0);
362 : 0 : close(fd);
363 [ # # ]: 0 : if (mapaddr == NULL)
364 : 0 : goto error;
365 : :
366 : 0 : pci_map_addr = RTE_PTR_ADD(mapaddr,
367 : : (size_t)dev->mem_resource[res_idx].len);
368 : :
369 : 0 : pci_map_addr = RTE_PTR_ALIGN(pci_map_addr, sysconf(_SC_PAGE_SIZE));
370 : :
371 : 0 : maps[map_idx].phaddr = dev->mem_resource[res_idx].phys_addr;
372 : 0 : maps[map_idx].size = dev->mem_resource[res_idx].len;
373 : 0 : maps[map_idx].addr = mapaddr;
374 : 0 : maps[map_idx].offset = 0;
375 : 0 : strcpy(maps[map_idx].path, devname);
376 : 0 : dev->mem_resource[res_idx].addr = mapaddr;
377 : :
378 : 0 : return 0;
379 : :
380 : 0 : error:
381 : 0 : rte_free(maps[map_idx].path);
382 : 0 : return -1;
383 : : }
384 : :
385 : : #define PIO_MAX 0x10000
386 : :
387 : : #if defined(RTE_ARCH_X86)
388 : : int
389 : 0 : pci_uio_ioport_map(struct rte_pci_device *dev, int bar,
390 : : struct rte_pci_ioport *p)
391 : : {
392 : : FILE *f = NULL;
393 : : char dirname[PATH_MAX];
394 : : char filename[PATH_MAX];
395 : : char buf[BUFSIZ];
396 : : uint64_t phys_addr, end_addr, flags;
397 : : unsigned long base;
398 : : int i, fd;
399 : :
400 : : /* open and read addresses of the corresponding resource in sysfs */
401 : 0 : snprintf(filename, sizeof(filename), "%s/" PCI_PRI_FMT "/resource",
402 : 0 : rte_pci_get_sysfs_path(), dev->addr.domain, dev->addr.bus,
403 : 0 : dev->addr.devid, dev->addr.function);
404 : 0 : f = fopen(filename, "r");
405 [ # # ]: 0 : if (f == NULL) {
406 : 0 : RTE_LOG(ERR, EAL, "%s(): Cannot open sysfs resource: %s\n",
407 : : __func__, strerror(errno));
408 : 0 : return -1;
409 : : }
410 : :
411 [ # # ]: 0 : for (i = 0; i < bar + 1; i++) {
412 [ # # ]: 0 : if (fgets(buf, sizeof(buf), f) == NULL) {
413 : 0 : RTE_LOG(ERR, EAL, "%s(): Cannot read sysfs resource\n", __func__);
414 : 0 : goto error;
415 : : }
416 : : }
417 [ # # ]: 0 : if (pci_parse_one_sysfs_resource(buf, sizeof(buf), &phys_addr,
418 : : &end_addr, &flags) < 0)
419 : 0 : goto error;
420 : :
421 [ # # ]: 0 : if (flags & IORESOURCE_IO) {
422 [ # # ]: 0 : if (rte_eal_iopl_init()) {
423 : 0 : RTE_LOG(ERR, EAL, "%s(): insufficient ioport permissions for PCI device %s\n",
424 : : __func__, dev->name);
425 : 0 : goto error;
426 : : }
427 : :
428 : 0 : base = (unsigned long)phys_addr;
429 [ # # ]: 0 : if (base > PIO_MAX) {
430 : 0 : RTE_LOG(ERR, EAL, "%s(): %08lx too large PIO resource\n", __func__, base);
431 : 0 : goto error;
432 : : }
433 : :
434 : 0 : RTE_LOG(DEBUG, EAL, "%s(): PIO BAR %08lx detected\n", __func__, base);
435 [ # # ]: 0 : } else if (flags & IORESOURCE_MEM) {
436 : 0 : base = (unsigned long)dev->mem_resource[bar].addr;
437 : 0 : RTE_LOG(DEBUG, EAL, "%s(): MMIO BAR %08lx detected\n", __func__, base);
438 : : } else {
439 : 0 : RTE_LOG(ERR, EAL, "%s(): unknown BAR type\n", __func__);
440 : 0 : goto error;
441 : : }
442 : :
443 : : /* FIXME only for primary process ? */
444 [ # # ]: 0 : if (rte_intr_type_get(dev->intr_handle) ==
445 : : RTE_INTR_HANDLE_UNKNOWN) {
446 : 0 : int uio_num = pci_get_uio_dev(dev, dirname, sizeof(dirname), 0);
447 [ # # ]: 0 : if (uio_num < 0) {
448 : 0 : RTE_LOG(ERR, EAL, "cannot open %s: %s\n",
449 : : dirname, strerror(errno));
450 : 0 : goto error;
451 : : }
452 : :
453 : : snprintf(filename, sizeof(filename), "/dev/uio%u", uio_num);
454 : : fd = open(filename, O_RDWR);
455 [ # # ]: 0 : if (fd < 0) {
456 : 0 : RTE_LOG(ERR, EAL, "Cannot open %s: %s\n",
457 : : filename, strerror(errno));
458 : 0 : goto error;
459 : : }
460 [ # # ]: 0 : if (rte_intr_fd_set(dev->intr_handle, fd))
461 : 0 : goto error;
462 : :
463 [ # # ]: 0 : if (rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UIO))
464 : 0 : goto error;
465 : : }
466 : :
467 : 0 : RTE_LOG(DEBUG, EAL, "PCI Port IO found start=0x%lx\n", base);
468 : :
469 : 0 : p->base = base;
470 : 0 : p->len = 0;
471 : 0 : fclose(f);
472 : 0 : return 0;
473 : 0 : error:
474 : : if (f)
475 : 0 : fclose(f);
476 : 0 : return -1;
477 : : }
478 : : #else
479 : : int
480 : : pci_uio_ioport_map(struct rte_pci_device *dev, int bar,
481 : : struct rte_pci_ioport *p)
482 : : {
483 : : FILE *f;
484 : : char buf[BUFSIZ];
485 : : char filename[PATH_MAX];
486 : : uint64_t phys_addr, end_addr, flags;
487 : : int fd, i;
488 : : void *addr;
489 : :
490 : : /* open and read addresses of the corresponding resource in sysfs */
491 : : snprintf(filename, sizeof(filename), "%s/" PCI_PRI_FMT "/resource",
492 : : rte_pci_get_sysfs_path(), dev->addr.domain, dev->addr.bus,
493 : : dev->addr.devid, dev->addr.function);
494 : : f = fopen(filename, "r");
495 : : if (f == NULL) {
496 : : RTE_LOG(ERR, EAL, "Cannot open sysfs resource: %s\n",
497 : : strerror(errno));
498 : : return -1;
499 : : }
500 : : for (i = 0; i < bar + 1; i++) {
501 : : if (fgets(buf, sizeof(buf), f) == NULL) {
502 : : RTE_LOG(ERR, EAL, "Cannot read sysfs resource\n");
503 : : goto error;
504 : : }
505 : : }
506 : : if (pci_parse_one_sysfs_resource(buf, sizeof(buf), &phys_addr,
507 : : &end_addr, &flags) < 0)
508 : : goto error;
509 : : if ((flags & IORESOURCE_IO) == 0) {
510 : : RTE_LOG(ERR, EAL, "BAR %d is not an IO resource\n", bar);
511 : : goto error;
512 : : }
513 : : snprintf(filename, sizeof(filename), "%s/" PCI_PRI_FMT "/resource%d",
514 : : rte_pci_get_sysfs_path(), dev->addr.domain, dev->addr.bus,
515 : : dev->addr.devid, dev->addr.function, bar);
516 : :
517 : : /* mmap the pci resource */
518 : : fd = open(filename, O_RDWR);
519 : : if (fd < 0) {
520 : : RTE_LOG(ERR, EAL, "Cannot open %s: %s\n", filename,
521 : : strerror(errno));
522 : : goto error;
523 : : }
524 : : addr = mmap(NULL, end_addr + 1, PROT_READ | PROT_WRITE,
525 : : MAP_SHARED, fd, 0);
526 : : close(fd);
527 : : if (addr == MAP_FAILED) {
528 : : RTE_LOG(ERR, EAL, "Cannot mmap IO port resource: %s\n",
529 : : strerror(errno));
530 : : goto error;
531 : : }
532 : :
533 : : /* strangely, the base address is mmap addr + phys_addr */
534 : : p->base = (uintptr_t)addr + phys_addr;
535 : : p->len = end_addr + 1;
536 : : RTE_LOG(DEBUG, EAL, "PCI Port IO found start=0x%"PRIx64"\n", p->base);
537 : : fclose(f);
538 : :
539 : : return 0;
540 : :
541 : : error:
542 : : fclose(f);
543 : : return -1;
544 : : }
545 : : #endif
546 : :
547 : : #if defined(RTE_ARCH_X86)
548 : :
549 : : static inline uint8_t ioread8(void *addr)
550 : : {
551 : : uint8_t val;
552 : :
553 : 0 : val = (uint64_t)(uintptr_t)addr >= PIO_MAX ?
554 : : *(volatile uint8_t *)addr :
555 : : #ifdef __GLIBC__
556 : 0 : inb_p((unsigned long)addr);
557 : : #else
558 : : inb((unsigned long)addr);
559 : : #endif
560 : :
561 : : return val;
562 : : }
563 : :
564 : : static inline uint16_t ioread16(void *addr)
565 : : {
566 : : uint16_t val;
567 : :
568 : 0 : val = (uint64_t)(uintptr_t)addr >= PIO_MAX ?
569 : : *(volatile uint16_t *)addr :
570 : : #ifdef __GLIBC__
571 : 0 : inw_p((unsigned long)addr);
572 : : #else
573 : : inw((unsigned long)addr);
574 : : #endif
575 : :
576 : : return val;
577 : : }
578 : :
579 : : static inline uint32_t ioread32(void *addr)
580 : : {
581 : : uint32_t val;
582 : :
583 : : val = (uint64_t)(uintptr_t)addr >= PIO_MAX ?
584 : 0 : *(volatile uint32_t *)addr :
585 : : #ifdef __GLIBC__
586 : 0 : inl_p((unsigned long)addr);
587 : : #else
588 : : inl((unsigned long)addr);
589 : : #endif
590 : :
591 : : return val;
592 : : }
593 : :
594 : : static inline void iowrite8(uint8_t val, void *addr)
595 : : {
596 : : (uint64_t)(uintptr_t)addr >= PIO_MAX ?
597 : 0 : *(volatile uint8_t *)addr = val :
598 : : #ifdef __GLIBC__
599 : 0 : outb_p(val, (unsigned long)addr);
600 : : #else
601 : : outb(val, (unsigned long)addr);
602 : : #endif
603 : : }
604 : :
605 : : static inline void iowrite16(uint16_t val, void *addr)
606 : : {
607 : : (uint64_t)(uintptr_t)addr >= PIO_MAX ?
608 : 0 : *(volatile uint16_t *)addr = val :
609 : : #ifdef __GLIBC__
610 : 0 : outw_p(val, (unsigned long)addr);
611 : : #else
612 : : outw(val, (unsigned long)addr);
613 : : #endif
614 : : }
615 : :
616 : : static inline void iowrite32(uint32_t val, void *addr)
617 : : {
618 : : (uint64_t)(uintptr_t)addr >= PIO_MAX ?
619 : 0 : *(volatile uint32_t *)addr = val :
620 : : #ifdef __GLIBC__
621 : 0 : outl_p(val, (unsigned long)addr);
622 : : #else
623 : : outl(val, (unsigned long)addr);
624 : : #endif
625 : : }
626 : :
627 : : #else /* !RTE_ARCH_X86 */
628 : :
629 : : static inline uint8_t ioread8(void *addr)
630 : : {
631 : : return *(volatile uint8_t *)addr;
632 : : }
633 : :
634 : : static inline uint16_t ioread16(void *addr)
635 : : {
636 : : return *(volatile uint16_t *)addr;
637 : : }
638 : :
639 : : static inline uint32_t ioread32(void *addr)
640 : : {
641 : : return *(volatile uint32_t *)addr;
642 : : }
643 : :
644 : : static inline void iowrite8(uint8_t val, void *addr)
645 : : {
646 : : *(volatile uint8_t *)addr = val;
647 : : }
648 : :
649 : : static inline void iowrite16(uint16_t val, void *addr)
650 : : {
651 : : *(volatile uint16_t *)addr = val;
652 : : }
653 : :
654 : : static inline void iowrite32(uint32_t val, void *addr)
655 : : {
656 : : *(volatile uint32_t *)addr = val;
657 : : }
658 : :
659 : : #endif /* !RTE_ARCH_X86 */
660 : :
661 : : void
662 : 0 : pci_uio_ioport_read(struct rte_pci_ioport *p,
663 : : void *data, size_t len, off_t offset)
664 : : {
665 : : uint8_t *d;
666 : : int size;
667 : 0 : uintptr_t reg = p->base + offset;
668 : :
669 [ # # ]: 0 : for (d = data; len > 0; d += size, reg += size, len -= size) {
670 [ # # ]: 0 : if (len >= 4) {
671 : : size = 4;
672 [ # # ]: 0 : *(uint32_t *)d = ioread32((void *)reg);
673 [ # # ]: 0 : } else if (len >= 2) {
674 : : size = 2;
675 [ # # ]: 0 : *(uint16_t *)d = ioread16((void *)reg);
676 : : } else {
677 : : size = 1;
678 [ # # ]: 0 : *d = ioread8((void *)reg);
679 : : }
680 : : }
681 : 0 : }
682 : :
683 : : void
684 : 0 : pci_uio_ioport_write(struct rte_pci_ioport *p,
685 : : const void *data, size_t len, off_t offset)
686 : : {
687 : : const uint8_t *s;
688 : : int size;
689 : 0 : uintptr_t reg = p->base + offset;
690 : :
691 [ # # ]: 0 : for (s = data; len > 0; s += size, reg += size, len -= size) {
692 [ # # ]: 0 : if (len >= 4) {
693 : : size = 4;
694 [ # # ]: 0 : iowrite32(*(const uint32_t *)s, (void *)reg);
695 [ # # ]: 0 : } else if (len >= 2) {
696 : : size = 2;
697 [ # # ]: 0 : iowrite16(*(const uint16_t *)s, (void *)reg);
698 : : } else {
699 : : size = 1;
700 [ # # ]: 0 : iowrite8(*s, (void *)reg);
701 : : }
702 : : }
703 : 0 : }
704 : :
705 : : int
706 : 0 : pci_uio_ioport_unmap(struct rte_pci_ioport *p)
707 : : {
708 : : #if defined(RTE_ARCH_X86)
709 : : RTE_SET_USED(p);
710 : : /* FIXME close intr fd ? */
711 : 0 : return 0;
712 : : #else
713 : : return munmap((void *)(uintptr_t)p->base, p->len);
714 : : #endif
715 : : }
|