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