Support libdrm functions required for Mesa versions >= 13.
On linux this information is pulled out of a psuedo filesystem, here the
new DRM_IOCTL_GET_PCIINFO ioctl is used for the same.
Only primary drm nodes are handled, render and control nodes which we
don't have aren't. This also only handles devices with PCI ids.
drmGetMinorNameForFD() based on code the Mesa loader used to have.
diff --git xf86drm.c xf86drm.c
index 3c2c5d4..03fe257 100644
--- xf86drm.c
+++ xf86drm.c
@@ -62,6 +62,10 @@
#endif
#include <math.h>
+#ifdef __OpenBSD__
+#include <sys/pciio.h>
+#endif
+
/* Not all systems have MAP_FAILED defined */
#ifndef MAP_FAILED
#define MAP_FAILED ((void *)-1)
@@ -2851,7 +2855,25 @@ static char *drmGetMinorNameForFD(int fd, int type)
out_close_dir:
closedir(sysdir);
#else
-#warning "Missing implementation of drmGetMinorNameForFD"
+ struct stat sbuf;
+ unsigned int maj, min;
+ char buf[0x40];
+ int n;
+
+ if (fstat(fd, &sbuf))
+ return NULL;
+
+ maj = major(sbuf.st_rdev);
+ min = minor(sbuf.st_rdev);
+
+ if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
+ return NULL;
+
+ n = snprintf(buf, sizeof(buf), DRM_DEV_NAME, DRM_DIR_NAME, min);
+ if (n == -1 || n >= sizeof(buf))
+ return NULL;
+
+ return strdup(buf);
#endif
return NULL;
}
@@ -2887,6 +2909,8 @@ static int drmParseSubsystemType(int maj, int min)
return DRM_BUS_PCI;
return -EINVAL;
+#elif defined(__OpenBSD__)
+ return DRM_BUS_PCI;
#else
#warning "Missing implementation of drmParseSubsystemType"
return -EINVAL;
@@ -2929,6 +2953,26 @@ static int drmParsePciBusInfo(int maj, int min,
drmPciBusInfoPtr info)
info->func = func;
return 0;
+#elif defined(__OpenBSD__)
+ struct drm_pciinfo pinfo;
+ int fd;
+
+ fd = drmOpenMinor(min, 0, DRM_NODE_PRIMARY);
+ if (fd < 0)
+ return -errno;
+
+ if (drmIoctl(fd, DRM_IOCTL_GET_PCIINFO, &pinfo)) {
+ close(fd);
+ return -errno;
+ }
+ close(fd);
+
+ info->domain = pinfo.domain;
+ info->bus = pinfo.bus;
+ info->dev = pinfo.dev;
+ info->func = pinfo.func;
+
+ return 0;
#else
#warning "Missing implementation of drmParsePciBusInfo"
return -EINVAL;
@@ -3004,6 +3048,37 @@ static int drmParsePciDeviceInfo(const char *d_name,
device->subdevice_id = config[46] | (config[47] << 8);
return 0;
+#elif defined(__OpenBSD__)
+ struct drm_pciinfo pinfo;
+ char buf[0x40];
+ int fd, n;
+
+ n = snprintf(buf, sizeof(buf), "%s/%s", DRM_DIR_NAME, d_name);
+ if (n == -1 || n >= sizeof(buf))
+ return -errno;
+
+#ifndef X_PRIVSEP
+ fd = open(buf, O_RDWR, 0);
+#else
+ fd = priv_open_device(buf);
+#endif
+
+ if (fd < 0)
+ return -errno;
+
+ if (drmIoctl(fd, DRM_IOCTL_GET_PCIINFO, &pinfo)) {
+ close(fd);
+ return -errno;
+ }
+ close(fd);
+
+ device->vendor_id = pinfo.vendor_id;
+ device->device_id = pinfo.device_id;
+ device->revision_id = pinfo.revision_id;
+ device->subvendor_id = pinfo.subvendor_id;
+ device->subdevice_id = pinfo.subdevice_id;
+
+ return 0;
#else
#warning "Missing implementation of drmParsePciDeviceInfo"
return -EINVAL;
@@ -3117,6 +3192,46 @@ static void drmFoldDuplicatedDevices(drmDevicePtr
local_devices[], int count)
*/
int drmGetDevice(int fd, drmDevicePtr *device)
{
+#ifdef __OpenBSD__
+ drmDevicePtr d;
+ struct stat sbuf;
+ char node[PATH_MAX + 1];
+ char d_name[PATH_MAX + 1];
+ int maj, min, n;
+ int ret;
+ int max_count = 1;
+
+ if (fd == -1 || device == NULL)
+ return -EINVAL;
+
+ if (fstat(fd, &sbuf))
+ return -errno;
+
+ maj = major(sbuf.st_rdev);
+ min = minor(sbuf.st_rdev);
+
+ if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
+ return -EINVAL;
+
+ n = snprintf(d_name, PATH_MAX, "drm%d", min);
+ if (n == -1 || n >= PATH_MAX)
+ return -errno;
+
+ n = snprintf(node, PATH_MAX, DRM_DEV_NAME, DRM_DIR_NAME, min);
+ if (n == -1 || n >= PATH_MAX)
+ return -errno;
+ if (stat(node, &sbuf))
+ return -EINVAL;
+
+ ret = drmProcessPciDevice(&d, d_name, node, DRM_NODE_PRIMARY,
+ maj, min, true);
+ if (ret)
+ return ret;
+
+ *device = d;
+
+ return 0;
+#else
drmDevicePtr *local_devices;
drmDevicePtr d;
DIR *sysdir;
@@ -3224,6 +3339,7 @@ free_devices:
free_locals:
free(local_devices);
return ret;
+#endif
}
/**