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