@@ -139,6 +139,7 @@ __LIB__libodp_la_SOURCES = \
odp_packet.c \
odp_packet_flags.c \
odp_packet_io.c \
+ odp_pci.c \
odp_pci_vfio.c \
pktio/io_ops.c \
pktio/pktio_common.c \
new file mode 100644
@@ -0,0 +1,190 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdio.h>
+#include <linux/limits.h>
+#include <stdlib.h>
+#include <odp/dma.h>
+#include <odp/pci.h>
+#include <odp_debug_internal.h>
+#include <odp_pci_internal.h>
+#include <odp_pci_vfio_internal.h>
+
+#define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
+
+/* operations on PCI devices: */
+
+uint16_t odp_pci_get_vendor(odp_pci_dev_t dev_hdl)
+{
+ return ((pci_dev_t *)dev_hdl)->pci_id.vendor_id;
+}
+
+uint16_t odp_pci_get_device(odp_pci_dev_t dev_hdl)
+{
+ return ((pci_dev_t *)dev_hdl)->pci_id.device_id;
+}
+
+uint16_t odp_pci_get_subsystem_vendor(odp_pci_dev_t dev_hdl)
+{
+ return ((pci_dev_t *)dev_hdl)->pci_id.subsystem_vendor_id;
+}
+
+uint16_t odp_pci_get_subsystem_device(odp_pci_dev_t dev_hdl)
+{
+ return ((pci_dev_t *)dev_hdl)->pci_id.subsystem_device_id;
+}
+
+void *odp_pci_get_resource_addr(odp_pci_dev_t dev_hdl, int bar)
+{
+ return ((pci_dev_t *)dev_hdl)->bar_maps[bar].addr;
+}
+
+char *odp_pci_get_addr_str(odp_pci_dev_t dev_hdl)
+{
+ return ((pci_dev_t *)dev_hdl)->pci_address;
+}
+
+/*
+ * parse a sysfs (or other) file containing one integer value
+ */
+static int parse_sysfs_value(const char *filename, unsigned long *val)
+{
+ FILE *f;
+ char buf[BUFSIZ];
+ char *end = NULL;
+
+ f = fopen(filename, "r");
+ if (!f) {
+ ODP_ERR("%s(): cannot open sysfs value %s\n",
+ __func__, filename);
+ return -1;
+ }
+
+ if (fgets(buf, sizeof(buf), f) == NULL) {
+ ODP_ERR("%s(): cannot read sysfs value %s\n",
+ __func__, filename);
+ fclose(f);
+ return -1;
+ }
+ *val = strtoul(buf, &end, 0);
+ if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) {
+ ODP_ERR("%s(): cannot parse sysfs value %s\n",
+ __func__, filename);
+ fclose(f);
+ return -1;
+ }
+ fclose(f);
+ return 0;
+}
+
+odp_pci_dev_t _odp_pci_init(const char *pci_addr)
+{
+ char filename[PATH_MAX];
+ unsigned long tmp;
+ pci_dev_t *dev;
+
+ dev = malloc(sizeof(pci_dev_t));
+ if (!dev)
+ return NULL;
+
+ /* currentely only vfio is supported */
+ if (_odp_pci_vfio_init(pci_addr, dev) < 0)
+ goto pci_init_err;
+
+ /* get vendor id */
+ snprintf(filename, sizeof(filename), SYSFS_PCI_DEVICES "/%s/vendor",
+ pci_addr);
+ if (parse_sysfs_value(filename, &tmp) < 0)
+ goto pci_init_err;
+
+ dev->pci_id.vendor_id = (uint16_t)tmp;
+
+ /* get device id */
+ snprintf(filename, sizeof(filename), SYSFS_PCI_DEVICES "/%s/device",
+ pci_addr);
+ if (parse_sysfs_value(filename, &tmp) < 0)
+ goto pci_init_err;
+
+ dev->pci_id.device_id = (uint16_t)tmp;
+
+ /* get subsystem_vendor id */
+ snprintf(filename, sizeof(filename),
+ SYSFS_PCI_DEVICES "/%s/subsystem_vendor",
+ pci_addr);
+ if (parse_sysfs_value(filename, &tmp) < 0)
+ goto pci_init_err;
+
+ dev->pci_id.subsystem_vendor_id = (uint16_t)tmp;
+
+ /* get subsystem_device id */
+ snprintf(filename, sizeof(filename),
+ SYSFS_PCI_DEVICES "/%s/subsystem_device",
+ pci_addr);
+ if (parse_sysfs_value(filename, &tmp) < 0)
+ goto pci_init_err;
+
+ dev->pci_id.subsystem_device_id = (uint16_t)tmp;
+
+ return (odp_pci_dev_t)dev;
+
+pci_init_err:
+ free(dev);
+ return NULL;
+}
+
+void _odp_pci_release(odp_pci_dev_t pci_dev)
+{
+ /* currentely only vfio is supported */
+ _odp_pci_vfio_release((pci_dev_t *)pci_dev);
+ free(pci_dev);
+}
+
+int odp_pci_map_dma_region(odp_pci_dev_t dev_hdl,
+ odp_dma_map_t region)
+{
+ pci_dev_t *dev = (pci_dev_t *)dev_hdl;
+ dma_map_t *map_s = dma_map_handle_to_map(region);
+
+ /* map fragments one by one */
+ /* currentely only vfio is supported */
+ do {
+ if (_odp_pci_vfio_map_dma_region_f(dev, map_s)) {
+ /* remove partially mapped region: */
+ odp_pci_unmap_dma_region(dev_hdl, region);
+ return -1;
+ }
+ map_s = map_s->next;
+ } while (map_s);
+
+ return 0;
+}
+
+int odp_pci_unmap_dma_region(odp_pci_dev_t dev_hdl,
+ odp_dma_map_t region)
+{
+ pci_dev_t *dev = (pci_dev_t *)dev_hdl;
+ dma_map_t *map_s = dma_map_handle_to_map(region);
+
+ /* unmap fragments one by one */
+ /* currentely only vfio is supported */
+ do {
+ _odp_pci_vfio_unmap_dma_region_f(dev, map_s);
+ map_s = map_s->next;
+ } while (map_s);
+
+ return 0;
+}
+
+int odp_pci_read_config(odp_pci_dev_t dev, void *buf, size_t len, int offs)
+{
+ return _odp_pci_vfio_read_config((pci_dev_t *)dev, buf, len, offs);
+}
+
+int odp_pci_write_config(odp_pci_dev_t dev, const void *buf,
+ size_t len, int offs)
+{
+ return _odp_pci_vfio_write_config((pci_dev_t *)dev, buf, len, offs);
+}
This implementation just acts as a simple wrapper around pci-vfio. This could grow if other pci access (such as user-io) get involved. Signed-off-by: Christophe Milard <christophe.milard@linaro.org> --- platform/linux-generic/Makefile.am | 1 + platform/linux-generic/odp_pci.c | 190 +++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 platform/linux-generic/odp_pci.c