+ return (vlib_pci_map_region_int (vm, h, resource, addr, result));
+}
+
+clib_error_t *
+vlib_pci_io_region (vlib_main_t * vm, vlib_pci_dev_handle_t h, u32 resource)
+{
+ linux_pci_device_t *p = linux_pci_get_device (h);
+ clib_error_t *error = 0;
+ int fd = -1;
+ u64 size = 0, offset = 0;
+
+ if ((error = vlib_pci_region (vm, h, resource, &fd, &size, &offset)))
+ return error;
+
+ p->io_fd = fd;
+ p->io_offset = offset;
+ return error;
+}
+
+clib_error_t *
+vlib_pci_read_write_io (vlib_main_t * vm, vlib_pci_dev_handle_t h,
+ vlib_read_or_write_t read_or_write,
+ uword offset, void *data, u32 length)
+{
+ linux_pci_device_t *p = linux_pci_get_device (h);
+ int n = 0;
+
+ if (read_or_write == VLIB_READ)
+ n = pread (p->io_fd, data, length, p->io_offset + offset);
+ else
+ n = pwrite (p->io_fd, data, length, p->io_offset + offset);
+
+ if (n != length)
+ return clib_error_return_unix (0, "%s",
+ read_or_write == VLIB_READ
+ ? "read" : "write");
+ return 0;
+}
+
+clib_error_t *
+vlib_pci_map_dma (vlib_main_t * vm, vlib_pci_dev_handle_t h, void *ptr)
+{
+ linux_pci_device_t *p = linux_pci_get_device (h);
+
+ if (!p->supports_va_dma)
+ return 0;
+
+ return vfio_map_physmem_page (vm, ptr);
+}
+
+int
+vlib_pci_supports_virtual_addr_dma (vlib_main_t * vm, vlib_pci_dev_handle_t h)
+{
+ linux_pci_device_t *p = linux_pci_get_device (h);
+
+ return p->supports_va_dma != 0;
+}
+
+clib_error_t *
+vlib_pci_device_open (vlib_main_t * vm, vlib_pci_addr_t * addr,
+ pci_device_id_t ids[], vlib_pci_dev_handle_t * handle)
+{
+ linux_pci_main_t *lpm = &linux_pci_main;
+ vlib_pci_device_info_t *di;
+ linux_pci_device_t *p;
+ clib_error_t *err = 0;
+ pci_device_id_t *i;
+
+ di = vlib_pci_get_device_info (vm, addr, &err);
+
+ if (err)
+ return err;
+ for (i = ids; i->vendor_id != 0; i++)
+ if (i->vendor_id == di->vendor_id && i->device_id == di->device_id)
+ break;
+
+ if (i->vendor_id == 0)
+ return clib_error_return (0, "Wrong vendor or device id");
+
+ pool_get (lpm->linux_pci_devices, p);
+ p->handle = p - lpm->linux_pci_devices;
+ p->addr.as_u32 = di->addr.as_u32;
+ p->intx_irq.fd = -1;
+ p->numa_node = di->numa_node;
+ /*
+ * pci io bar read/write fd
+ */
+ p->io_fd = -1;
+
+ pci_log_debug (vm, p, "open vid:0x%04x did:0x%04x driver:%s iommu_group:%d",
+ di->vendor_id, di->device_id, di->driver_name,
+ di->iommu_group);
+
+ if (strncmp ("vfio-pci", (char *) di->driver_name, 8) == 0)
+ err = add_device_vfio (vm, p, di, 0);
+ else if (strncmp ("uio_pci_generic", (char *) di->driver_name, 8) == 0)
+ err = add_device_uio (vm, p, di, 0);
+ else
+ err = clib_error_create ("device not bound to 'vfio-pci' or "
+ "'uio_pci_generic' kernel module");
+ if (err)
+ goto error;
+
+ *handle = p->handle;
+
+error:
+ vlib_pci_free_device_info (di);
+ if (err)
+ {
+ pci_log_err (vm, p, "%U", format_clib_error, err);
+ clib_memset (p, 0, sizeof (linux_pci_device_t));
+ pool_put (lpm->linux_pci_devices, p);
+ }
+
+ return err;