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