eal: introduce PCI ioport API
[dpdk.git] / lib / librte_eal / linuxapp / eal / eal_pci.c
index db947da..4346973 100644 (file)
@@ -621,6 +621,176 @@ int rte_eal_pci_write_config(const struct rte_pci_device *device,
        }
 }
 
+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)
+static int
+pci_ioport_map(struct rte_pci_device *dev, int bar __rte_unused,
+              struct rte_pci_ioport *p)
+{
+       uint16_t start, end;
+       FILE *fp;
+       char *line = NULL;
+       char pci_id[16];
+       int found = 0;
+       size_t linesz;
+
+       snprintf(pci_id, sizeof(pci_id), PCI_PRI_FMT,
+                dev->addr.domain, dev->addr.bus,
+                dev->addr.devid, dev->addr.function);
+
+       fp = fopen("/proc/ioports", "r");
+       if (fp == NULL) {
+               RTE_LOG(ERR, EAL, "%s(): can't open ioports\n", __func__);
+               return -1;
+       }
+
+       while (getdelim(&line, &linesz, '\n', fp) > 0) {
+               char *ptr = line;
+               char *left;
+               int n;
+
+               n = strcspn(ptr, ":");
+               ptr[n] = 0;
+               left = &ptr[n + 1];
+
+               while (*left && isspace(*left))
+                       left++;
+
+               if (!strncmp(left, pci_id, strlen(pci_id))) {
+                       found = 1;
+
+                       while (*ptr && isspace(*ptr))
+                               ptr++;
+
+                       sscanf(ptr, "%04hx-%04hx", &start, &end);
+
+                       break;
+               }
+       }
+
+       free(line);
+       fclose(fp);
+
+       if (!found)
+               return -1;
+
+       dev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;
+       p->base = start;
+       RTE_LOG(DEBUG, EAL, "PCI Port IO found start=0x%x\n", start);
+
+       return 0;
+}
+#endif
+
+int
+rte_eal_pci_ioport_map(struct rte_pci_device *dev, int bar,
+                      struct rte_pci_ioport *p)
+{
+       int ret;
+
+       switch (dev->kdrv) {
+#ifdef VFIO_PRESENT
+       case RTE_KDRV_VFIO:
+               ret = -1;
+               if (pci_vfio_is_enabled())
+                       ret = pci_vfio_ioport_map(dev, bar, p);
+               break;
+#endif
+       case RTE_KDRV_IGB_UIO:
+       case RTE_KDRV_UIO_GENERIC:
+               ret = pci_uio_ioport_map(dev, bar, p);
+               break;
+       default:
+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)
+               /* special case for x86 ... */
+               ret = pci_ioport_map(dev, bar, p);
+#else
+               ret = -1;
+#endif
+               break;
+       }
+
+       if (!ret)
+               p->dev = dev;
+
+       return ret;
+}
+
+void
+rte_eal_pci_ioport_read(struct rte_pci_ioport *p,
+                       void *data, size_t len, off_t offset)
+{
+       switch (p->dev->kdrv) {
+#ifdef VFIO_PRESENT
+       case RTE_KDRV_VFIO:
+               pci_vfio_ioport_read(p, data, len, offset);
+               break;
+#endif
+       case RTE_KDRV_IGB_UIO:
+       case RTE_KDRV_UIO_GENERIC:
+               pci_uio_ioport_read(p, data, len, offset);
+               break;
+       default:
+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)
+               /* special case for x86 ... */
+               pci_uio_ioport_read(p, data, len, offset);
+#endif
+               break;
+       }
+}
+
+void
+rte_eal_pci_ioport_write(struct rte_pci_ioport *p,
+                        const void *data, size_t len, off_t offset)
+{
+       switch (p->dev->kdrv) {
+#ifdef VFIO_PRESENT
+       case RTE_KDRV_VFIO:
+               pci_vfio_ioport_write(p, data, len, offset);
+               break;
+#endif
+       case RTE_KDRV_IGB_UIO:
+       case RTE_KDRV_UIO_GENERIC:
+               pci_uio_ioport_write(p, data, len, offset);
+               break;
+       default:
+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)
+               /* special case for x86 ... */
+               pci_uio_ioport_write(p, data, len, offset);
+#endif
+               break;
+       }
+}
+
+int
+rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p)
+{
+       int ret;
+
+       switch (p->dev->kdrv) {
+#ifdef VFIO_PRESENT
+       case RTE_KDRV_VFIO:
+               ret = -1;
+               if (pci_vfio_is_enabled())
+                       ret = pci_vfio_ioport_unmap(p);
+               break;
+#endif
+       case RTE_KDRV_IGB_UIO:
+       case RTE_KDRV_UIO_GENERIC:
+               ret = pci_uio_ioport_unmap(p);
+               break;
+       default:
+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)
+               /* special case for x86 ... nothing to do */
+               ret = 0;
+#else
+               ret = -1;
+#endif
+               break;
+       }
+
+       return ret;
+}
+
 /* Init the PCI EAL subsystem */
 int
 rte_eal_pci_init(void)