OSDN Git Service

libdrm: Implement drmParsePciDeviceInfo for FreeBSD
authorEmmanuel Vadot <manu@FreeBSD.Org>
Tue, 21 Jan 2020 17:49:47 +0000 (18:49 +0100)
committerEmmanuel Vadot <manu@FreeBSD.org>
Tue, 21 Apr 2020 17:26:54 +0000 (19:26 +0200)
The FreeBSD kernel expose a pseudo-device /dev/pci to obtain information
about present PCI device.
Uee the PCIOCGETCONF ioctl on this device to look up the desired device
information.

Signed-off-by: Emmanuel Vadot <manu@FreeBSD.org>
Reviewed-by: Eric Engestrom <eric@engestrom.ch>
Reviewed-by: Emil Velikov <emil.velikov@collabora.com>
xf86drm.c

index 53eb832..db9823d 100644 (file)
--- a/xf86drm.c
+++ b/xf86drm.c
@@ -64,6 +64,7 @@
 
 #if defined(__FreeBSD__)
 #include <sys/param.h>
+#include <sys/pciio.h>
 #endif
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
@@ -3416,6 +3417,48 @@ static int drmParsePciDeviceInfo(int maj, int min,
     device->subdevice_id = pinfo.subdevice_id;
 
     return 0;
+#elif __FreeBSD__
+    drmPciBusInfo info;
+    struct pci_conf_io pc;
+    struct pci_match_conf patterns[1];
+    struct pci_conf results[1];
+    int fd, error;
+
+    if (get_sysctl_pci_bus_info(maj, min, &info) != 0)
+        return -EINVAL;
+
+    fd = open("/dev/pci", O_RDONLY, 0);
+    if (fd < 0)
+        return -errno;
+
+    bzero(&patterns, sizeof(patterns));
+    patterns[0].pc_sel.pc_domain = info.domain;
+    patterns[0].pc_sel.pc_bus = info.bus;
+    patterns[0].pc_sel.pc_dev = info.dev;
+    patterns[0].pc_sel.pc_func = info.func;
+    patterns[0].flags = PCI_GETCONF_MATCH_DOMAIN | PCI_GETCONF_MATCH_BUS
+                      | PCI_GETCONF_MATCH_DEV | PCI_GETCONF_MATCH_FUNC;
+    bzero(&pc, sizeof(struct pci_conf_io));
+    pc.num_patterns = 1;
+    pc.pat_buf_len = sizeof(patterns);
+    pc.patterns = patterns;
+    pc.match_buf_len = sizeof(results);
+    pc.matches = results;
+
+    if (ioctl(fd, PCIOCGETCONF, &pc) || pc.status == PCI_GETCONF_ERROR) {
+        error = errno;
+        close(fd);
+        return -error;
+    }
+    close(fd);
+
+    device->vendor_id = results[0].pc_vendor;
+    device->device_id = results[0].pc_device;
+    device->subvendor_id = results[0].pc_subvendor;
+    device->subdevice_id = results[0].pc_subdevice;
+    device->revision_id = results[0].pc_revid;
+
+    return 0;
 #else
 #warning "Missing implementation of drmParsePciDeviceInfo"
     return -EINVAL;