Update to 2.4.78 and remove the dependency on libdevq

The functionality previously provided by libdevq is now implemented directly
in libdrm. This direct implementation should be more robust than the prior
integration. Initial testing has shown improvements in some scenarios while
remaining on-par elsewhere. The ultimate goal of this effort is to have our
platform support integrated upstream, which will be easier without the extra
dependency. With that in mind, please quickly report any regressions found.

Reviewed by:	dumbbell (x11), bapt (x11)
Approved by:	swills (mentor), dumbbell (x11)
Differential Revision:	https://reviews.freebsd.org/D10184
This commit is contained in:
Matthew Rezny 2017-04-08 15:49:25 +00:00
parent 6deaa26f4f
commit b29ddf3ae3
Notes: svn2git 2021-03-31 03:12:20 +00:00
svn path=/head/; revision=438051
11 changed files with 855 additions and 433 deletions

View File

@ -2,9 +2,8 @@
# $FreeBSD$
PORTNAME= libdrm
PORTVERSION= 2.4.75
PORTVERSION= 2.4.78
PORTEPOCH= 1
PORTREVISION= 3
CATEGORIES= graphics x11
MASTER_SITES= http://dri.freedesktop.org/libdrm/
@ -14,8 +13,7 @@ COMMENT= Userspace interface to kernel Direct Rendering Module services
LICENSE= MIT
BUILD_DEPENDS= ${LOCALBASE}/libdata/pkgconfig/pthread-stubs.pc:devel/libpthread-stubs
LIB_DEPENDS= libpciaccess.so:devel/libpciaccess \
libdevq.so:devel/libdevq
LIB_DEPENDS= libpciaccess.so:devel/libpciaccess
USES= libtool pkgconfig tar:bzip2
GNU_CONFIGURE= yes
@ -74,7 +72,7 @@ PLIST_SUB+= RADEON_DRIVERS="@comment "
# This variable is not for users. So use a non-default name, intended for
# people working on DRM kernel module development.
.if !defined(LIBDRM_SKIP_RETURN_PATCH)
.if ${OPSYS} == FreeBSD && !defined(LIBDRM_SKIP_RETURN_PATCH)
EXTRA_PATCHES+= ${FILESDIR}/extra-xf86drm.c
.endif

View File

@ -1,3 +1,3 @@
TIMESTAMP = 1485779860
SHA256 (libdrm-2.4.75.tar.bz2) = 2d5a500eef412cc287d12268eed79d571e262d4957a2ec9258073f305985054f
SIZE (libdrm-2.4.75.tar.bz2) = 774589
TIMESTAMP = 1491604820
SHA256 (libdrm-2.4.78.tar.bz2) = 3dbe2ed3e2ee6ebe8a848195286ef362f66675a7102958e42906d734aa6925d8
SIZE (libdrm-2.4.78.tar.bz2) = 772306

View File

@ -1,14 +0,0 @@
--- Makefile.am.orig 2016-12-13 03:45:20.000000000 +0100
+++ Makefile.am 2017-01-30 14:02:04.821902000 +0100
@@ -115,9 +115,9 @@
libdrm_la_LTLIBRARIES = libdrm.la
libdrm_ladir = $(libdir)
libdrm_la_LDFLAGS = -version-number 2:4:0 -no-undefined
-libdrm_la_LIBADD = @CLOCK_LIB@ -lm
+libdrm_la_LIBADD = @CLOCK_LIB@ -lm @LIBDEVQ_LIBS@
-libdrm_la_CPPFLAGS = -I$(top_srcdir)/include/drm
+libdrm_la_CPPFLAGS = -I$(top_srcdir)/include/drm @LIBDEVQ_CFLAGS@
AM_CFLAGS = \
$(WARN_CFLAGS) \
$(VALGRIND_CFLAGS)

View File

@ -1,39 +0,0 @@
--- configure.ac.orig 2017-01-28 02:15:16.000000000 +0100
+++ configure.ac 2017-01-30 14:00:14.452530000 +0100
@@ -72,6 +72,11 @@
[Enable support for using udev instead of mknod (default: disabled)])],
[UDEV=$enableval], [UDEV=no])
+AC_ARG_ENABLE([devq],
+ [AS_HELP_STRING([--enable-devq],
+ [Enable support for using devq for device detection (default: disabled)])],
+ [DEVQ=$enableval], [DEVQ=no])
+
AC_ARG_ENABLE(libkms,
AS_HELP_STRING([--disable-libkms],
[Disable KMS mm abstraction library (default: auto, enabled on supported platforms)]),
@@ -322,6 +327,10 @@
AC_DEFINE(UDEV, 1, [Have UDEV support])
fi
+if test "x$DEVQ" = xyes; then
+ AC_DEFINE(DEVQ, 1, [Have DEVQ support])
+fi
+
AC_CANONICAL_HOST
if test "x$LIBKMS" = xauto ; then
case $host_os in
@@ -451,6 +460,13 @@
AC_MSG_RESULT([$CAIRO])
AM_CONDITIONAL(HAVE_CAIRO, [test "x$CAIRO" = xyes])
+# For FreeBSD support
+PKG_CHECK_MODULES([LIBDEVQ], [libdevq-1.0 >= 0.0.4], [HAVE_LIBDEVQ=yes], [HAVE_LIBDEVQ=no])
+if test "x$HAVE_LIBDEVQ" = xyes; then
+ AC_DEFINE(HAVE_LIBDEVQ, 1, [Have libdevq support])
+fi
+AM_CONDITIONAL(HAVE_LIBDEVQ, [test "x$HAVE_LIBDEVQ" = xyes])
+
# xsltproc for docbook manpages
AC_ARG_ENABLE([manpages],
AS_HELP_STRING([--enable-manpages], [enable manpages @<:@default=auto@:>@]),

View File

@ -4,7 +4,7 @@ for now. Newer kernel modules will have this fixed included.
dragonfly fixed this issue in,
http://gitweb.dragonflybsd.org/dragonfly.git/commit/b922632f623ee2cc2c1346bb3a6894a7756676aa
which will be included in the 4.4 release when it is released.
which has been included since the 4.4 release.
--- xf86drm.c.orig 2017-01-30 13:59:15.919081000 +0100
+++ xf86drm.c

View File

@ -1,13 +0,0 @@
--- Makefile.in.orig 2017-01-28 02:00:33 UTC
+++ Makefile.in
@@ -562,8 +562,8 @@ SUBDIRS = \
libdrm_la_LTLIBRARIES = libdrm.la
libdrm_ladir = $(libdir)
libdrm_la_LDFLAGS = -version-number 2:4:0 -no-undefined
-libdrm_la_LIBADD = @CLOCK_LIB@ -lm
-libdrm_la_CPPFLAGS = -I$(top_srcdir)/include/drm
+libdrm_la_LIBADD = @CLOCK_LIB@ -lm @LIBDEVQ_LIBS@
+libdrm_la_CPPFLAGS = -I$(top_srcdir)/include/drm @LIBDEVQ_CFLAGS@
AM_CFLAGS = \
$(WARN_CFLAGS) \
$(VALGRIND_CFLAGS)

View File

@ -1,22 +0,0 @@
--- config.h.in.orig 2017-01-28 02:00:33 UTC
+++ config.h.in
@@ -8,6 +8,9 @@
/* Define to 1 if using `alloca.c'. */
#undef C_ALLOCA
+/* Have DEVQ support */
+#undef DEVQ
+
/* Define to 1 if you have `alloca', as a function or macro. */
#undef HAVE_ALLOCA
@@ -51,6 +54,9 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
+/* Have libdevq support */
+#undef HAVE_LIBDEVQ
+
/* Enable if your compiler supports the Intel __sync_* atomic primitives */
#undef HAVE_LIBDRM_ATOMIC_PRIMITIVES

View File

@ -1,182 +0,0 @@
--- configure.orig 2017-01-30 19:04:05 UTC
+++ configure
@@ -646,6 +646,10 @@ HAVE_MANPAGES_STYLESHEET_TRUE
MANPAGES_STYLESHEET
BUILD_MANPAGES_FALSE
BUILD_MANPAGES_TRUE
+HAVE_LIBDEVQ_FALSE
+HAVE_LIBDEVQ_TRUE
+LIBDEVQ_LIBS
+LIBDEVQ_CFLAGS
HAVE_CAIRO_FALSE
HAVE_CAIRO_TRUE
CAIRO_LIBS
@@ -838,6 +842,7 @@ with_gnu_ld
with_sysroot
enable_libtool_lock
enable_udev
+enable_devq
enable_libkms
enable_intel
enable_radeon
@@ -877,6 +882,8 @@ CUNIT_CFLAGS
CUNIT_LIBS
CAIRO_CFLAGS
CAIRO_LIBS
+LIBDEVQ_CFLAGS
+LIBDEVQ_LIBS
VALGRIND_CFLAGS
VALGRIND_LIBS'
@@ -1511,6 +1518,8 @@ Optional Features:
--disable-libtool-lock avoid locking (might break parallel builds)
--enable-udev Enable support for using udev instead of mknod
(default: disabled)
+ --enable-devq Enable support for using devq for device detection
+ (default: disabled)
--disable-libkms Disable KMS mm abstraction library (default: auto,
enabled on supported platforms)
--disable-intel Enable support for intel's KMS API (default: auto,
@@ -1586,6 +1595,10 @@ Some influential environment variables:
CAIRO_CFLAGS
C compiler flags for CAIRO, overriding pkg-config
CAIRO_LIBS linker flags for CAIRO, overriding pkg-config
+ LIBDEVQ_CFLAGS
+ C compiler flags for LIBDEVQ, overriding pkg-config
+ LIBDEVQ_LIBS
+ linker flags for LIBDEVQ, overriding pkg-config
VALGRIND_CFLAGS
C compiler flags for VALGRIND, overriding pkg-config
VALGRIND_LIBS
@@ -13217,6 +13230,14 @@ else
fi
+# Check whether --enable-devq was given.
+if test "${enable_devq+set}" = set; then :
+ enableval=$enable_devq; DEVQ=$enableval
+else
+ DEVQ=no
+fi
+
+
# Check whether --enable-libkms was given.
if test "${enable_libkms+set}" = set; then :
enableval=$enable_libkms; LIBKMS=$enableval
@@ -13873,6 +13894,12 @@ $as_echo "#define UDEV 1" >>confdefs.h
fi
+if test "x$DEVQ" = xyes; then
+
+$as_echo "#define DEVQ 1" >>confdefs.h
+
+fi
+
if test "x$LIBKMS" = xauto ; then
case $host_os in
@@ -14331,6 +14358,92 @@ else
fi
+# For FreeBSD support
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBDEVQ" >&5
+$as_echo_n "checking for LIBDEVQ... " >&6; }
+
+if test -n "$LIBDEVQ_CFLAGS"; then
+ pkg_cv_LIBDEVQ_CFLAGS="$LIBDEVQ_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libdevq-1.0 >= 0.0.4\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libdevq-1.0 >= 0.0.4") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBDEVQ_CFLAGS=`$PKG_CONFIG --cflags "libdevq-1.0 >= 0.0.4" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBDEVQ_LIBS"; then
+ pkg_cv_LIBDEVQ_LIBS="$LIBDEVQ_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libdevq-1.0 >= 0.0.4\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libdevq-1.0 >= 0.0.4") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBDEVQ_LIBS=`$PKG_CONFIG --libs "libdevq-1.0 >= 0.0.4" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ LIBDEVQ_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libdevq-1.0 >= 0.0.4" 2>&1`
+ else
+ LIBDEVQ_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libdevq-1.0 >= 0.0.4" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBDEVQ_PKG_ERRORS" >&5
+
+ HAVE_LIBDEVQ=no
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ HAVE_LIBDEVQ=no
+else
+ LIBDEVQ_CFLAGS=$pkg_cv_LIBDEVQ_CFLAGS
+ LIBDEVQ_LIBS=$pkg_cv_LIBDEVQ_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ HAVE_LIBDEVQ=yes
+fi
+if test "x$HAVE_LIBDEVQ" = xyes; then
+
+$as_echo "#define HAVE_LIBDEVQ 1" >>confdefs.h
+
+fi
+ if test "x$HAVE_LIBDEVQ" = xyes; then
+ HAVE_LIBDEVQ_TRUE=
+ HAVE_LIBDEVQ_FALSE='#'
+else
+ HAVE_LIBDEVQ_TRUE='#'
+ HAVE_LIBDEVQ_FALSE=
+fi
+
+
# xsltproc for docbook manpages
# Check whether --enable-manpages was given.
if test "${enable_manpages+set}" = set; then :
@@ -14737,6 +14850,10 @@ if test -z "${HAVE_CAIRO_TRUE}" && test
as_fn_error $? "conditional \"HAVE_CAIRO\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
+if test -z "${HAVE_LIBDEVQ_TRUE}" && test -z "${HAVE_LIBDEVQ_FALSE}"; then
+ as_fn_error $? "conditional \"HAVE_LIBDEVQ\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
if test -z "${BUILD_MANPAGES_TRUE}" && test -z "${BUILD_MANPAGES_FALSE}"; then
as_fn_error $? "conditional \"BUILD_MANPAGES\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5

View File

@ -1,73 +1,411 @@
--- xf86drm.c.orig 2017-01-30 19:04:05 UTC
--- xf86drm.c.orig 2017-04-07 08:49:13 UTC
+++ xf86drm.c
@@ -62,6 +62,10 @@
@@ -49,6 +49,9 @@
#include <signal.h>
#include <time.h>
#include <sys/types.h>
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
#include <sys/stat.h>
#define stat_t struct stat
#include <sys/ioctl.h>
@@ -62,6 +65,10 @@
#endif
#include <math.h>
+#ifdef HAVE_LIBDEVQ
+#include "libdevq.h"
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+#include <sys/pciio.h>
+#endif
+
/* Not all systems have MAP_FAILED defined */
#ifndef MAP_FAILED
#define MAP_FAILED ((void *)-1)
@@ -82,8 +86,12 @@
#define DRM_RENDER_MINOR_NAME "renderD"
#endif
@@ -72,18 +79,8 @@
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
#include "util_math.h"
-#ifdef __OpenBSD__
-#define DRM_PRIMARY_MINOR_NAME "drm"
-#define DRM_CONTROL_MINOR_NAME "drmC"
-#define DRM_RENDER_MINOR_NAME "drmR"
-#else
-#define DRM_PRIMARY_MINOR_NAME "card"
-#define DRM_CONTROL_MINOR_NAME "controlD"
-#define DRM_RENDER_MINOR_NAME "renderD"
-#endif
-
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
-#define DRM_MAJOR 145
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#define DRM_MAJOR 0
+#endif
+
+#if defined(__DragonFly__)
+#define DRM_MAJOR 65 /* was 145 XXX needs checking */
+#define DRM_MAJOR 0 /* Major ID unused on systems with devfs */
#endif
#ifdef __NetBSD__
@@ -548,6 +556,7 @@ static int drmGetMinorType(int minor)
}
@@ -180,7 +177,7 @@ void drmFree(void *pt)
}
+#if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) && !defined(__DragonFly__)
static const char *drmGetMinorName(int type)
{
switch (type) {
@@ -561,6 +570,7 @@ static const char *drmGetMinorName(int t
return NULL;
}
}
+#endif
/**
* Open the device by bus ID.
@@ -2734,7 +2744,7 @@ int drmGetNodeTypeFromFd(int fd)
maj = major(sbuf.st_rdev);
min = minor(sbuf.st_rdev);
- * Call ioctl, restarting if it is interupted
+ * Call ioctl, restarting if it is interrupted
*/
int
drmIoctl(int fd, unsigned long request, void *arg)
@@ -223,6 +220,89 @@ drmHashEntry *drmGetEntry(int fd)
return entry;
}
- if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) {
+ if (DRM_MAJOR && maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) {
errno = EINVAL;
return -1;
+static int drmGetMinorBase(int type)
+{
+ switch (type) {
+ case DRM_NODE_PRIMARY:
+ case DRM_NODE_CONTROL:
+ case DRM_NODE_RENDER:
+ return type << 6;
+ default:
+ return -1;
+ };
+}
+
+static int drmGetMinorType(int minor)
+{
+ if (minor < 0)
+ return -1;
+
+ int type = minor >> 6;
+ switch (type) {
+ case DRM_NODE_PRIMARY:
+ case DRM_NODE_CONTROL:
+ case DRM_NODE_RENDER:
+ return type;
+ default:
+ return -1;
+ }
+}
+
+#ifdef __linux__
+static const char *drmGetMinorName(int type)
+{
+ switch (type) {
+ case DRM_NODE_PRIMARY:
+ return DRM_PRIMARY_MINOR_NAME;
+ case DRM_NODE_CONTROL:
+ return DRM_CONTROL_MINOR_NAME;
+ case DRM_NODE_RENDER:
+ return DRM_RENDER_MINOR_NAME;
+ default:
+ return NULL;
+ }
+}
+#endif
+
+static const char *drmGetDeviceName(int type)
+{
+ switch (type) {
+ case DRM_NODE_PRIMARY:
+ return DRM_DEV_NAME;
+ case DRM_NODE_CONTROL:
+ return DRM_CONTROL_DEV_NAME;
+ case DRM_NODE_RENDER:
+ return DRM_RENDER_DEV_NAME;
+ default:
+ return NULL;
+ }
+}
+
+static int drmGetNodeNumber(const char *name)
+{
+ size_t name_len = strnlen(name, DRM_NODE_NAME_MAX);
+ while (name_len && isdigit(name[name_len - 1]))
+ --name_len;
+ return strtol(name + name_len, NULL, 10);
+}
+
+static int drmGetNodeType(const char *name)
+{
+ if (strncmp(name, DRM_PRIMARY_MINOR_NAME,
+ sizeof(DRM_PRIMARY_MINOR_NAME) - 1) == 0)
+ return DRM_NODE_PRIMARY;
+
+ if (strncmp(name, DRM_CONTROL_MINOR_NAME,
+ sizeof(DRM_CONTROL_MINOR_NAME ) - 1) == 0)
+ return DRM_NODE_CONTROL;
+
+ if (strncmp(name, DRM_RENDER_MINOR_NAME,
+ sizeof(DRM_RENDER_MINOR_NAME) - 1) == 0)
+ return DRM_NODE_RENDER;
+
+ return -1;
+}
+
/**
* Compare two busid strings
*
@@ -290,7 +370,7 @@ static int drmMatchBusID(const char *id1
*
* \internal
* Checks for failure. If failure was caused by signal call chown again.
- * If any other failure happened then it will output error mesage using
+ * If any other failure happened then it will output error message using
* drmMsg() call.
*/
#if !defined(UDEV)
@@ -327,8 +407,8 @@ static int chown_check_return(const char
static int drmOpenDevice(dev_t dev, int minor, int type)
{
stat_t st;
- const char *dev_name;
- char buf[64];
+ const char *dev_name = drmGetDeviceName(type);
+ char buf[DRM_NODE_NAME_MAX];
int fd;
mode_t devmode = DRM_DEV_MODE, serv_mode;
gid_t serv_group;
@@ -338,21 +418,14 @@ static int drmOpenDevice(dev_t dev, int
gid_t group = DRM_DEV_GID;
#endif
- switch (type) {
- case DRM_NODE_PRIMARY:
- dev_name = DRM_DEV_NAME;
- break;
- case DRM_NODE_CONTROL:
- dev_name = DRM_CONTROL_DEV_NAME;
- break;
- case DRM_NODE_RENDER:
- dev_name = DRM_RENDER_DEV_NAME;
- break;
- default:
+ if (!dev_name)
return -EINVAL;
- };
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+ sprintf(buf, dev_name, DRM_DIR_NAME, minor + drmGetMinorBase(type));
+#else
sprintf(buf, dev_name, DRM_DIR_NAME, minor);
+#endif
drmMsg("drmOpenDevice: node name is %s\n", buf);
if (drm_server_info && drm_server_info->get_perms) {
@@ -456,27 +529,20 @@ wait_for_udev:
static int drmOpenMinor(int minor, int create, int type)
{
int fd;
- char buf[64];
- const char *dev_name;
+ char buf[DRM_NODE_NAME_MAX];
+ const char *dev_name = drmGetDeviceName(type);
if (create)
return drmOpenDevice(makedev(DRM_MAJOR, minor), minor, type);
- switch (type) {
- case DRM_NODE_PRIMARY:
- dev_name = DRM_DEV_NAME;
- break;
- case DRM_NODE_CONTROL:
- dev_name = DRM_CONTROL_DEV_NAME;
- break;
- case DRM_NODE_RENDER:
- dev_name = DRM_RENDER_DEV_NAME;
- break;
- default:
+ if (!dev_name)
return -EINVAL;
- };
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+ sprintf(buf, dev_name, DRM_DIR_NAME, minor + drmGetMinorBase(type));
+#else
sprintf(buf, dev_name, DRM_DIR_NAME, minor);
+#endif
if ((fd = open(buf, O_RDWR, 0)) >= 0)
return fd;
return -errno;
@@ -517,51 +583,6 @@ int drmAvailable(void)
return retval;
}
-static int drmGetMinorBase(int type)
-{
- switch (type) {
- case DRM_NODE_PRIMARY:
- return 0;
- case DRM_NODE_CONTROL:
- return 64;
- case DRM_NODE_RENDER:
- return 128;
- default:
- return -1;
- };
-}
-
-static int drmGetMinorType(int minor)
-{
- int type = minor >> 6;
-
- if (minor < 0)
- return -1;
-
- switch (type) {
- case DRM_NODE_PRIMARY:
- case DRM_NODE_CONTROL:
- case DRM_NODE_RENDER:
- return type;
- default:
- return -1;
- }
-}
-
-static const char *drmGetMinorName(int type)
-{
- switch (type) {
- case DRM_NODE_PRIMARY:
- return DRM_PRIMARY_MINOR_NAME;
- case DRM_NODE_CONTROL:
- return DRM_CONTROL_MINOR_NAME;
- case DRM_NODE_RENDER:
- return DRM_RENDER_MINOR_NAME;
- default:
- return NULL;
- }
-}
-
/**
* Open the device by bus ID.
*
@@ -2705,33 +2726,40 @@ int drmDropMaster(int fd)
char *drmGetDeviceNameFromFd(int fd)
{
- char name[128];
- struct stat sbuf;
- dev_t d;
- int i;
-
/* The whole drmOpen thing is a fiasco and we need to find a way
* back to just using open(2). For now, however, lets just make
* things worse with even more ad hoc directory walking code to
* discover the device file name. */
+ stat_t sbuf;
fstat(fd, &sbuf);
- d = sbuf.st_rdev;
+ dev_t d = sbuf.st_rdev;
- for (i = 0; i < DRM_MAX_MINOR; i++) {
+ for (int i = 0; i < DRM_MAX_MINOR; i++) {
+ char name[DRM_NODE_NAME_MAX];
snprintf(name, sizeof name, DRM_DEV_NAME, DRM_DIR_NAME, i);
if (stat(name, &sbuf) == 0 && sbuf.st_rdev == d)
- break;
+ return strdup(name);
}
@@ -2833,6 +2843,15 @@ static char *drmGetMinorNameForFD(int fd
- if (i == DRM_MAX_MINOR)
- return NULL;
-
- return strdup(name);
+ return NULL;
}
int drmGetNodeTypeFromFd(int fd)
{
- struct stat sbuf;
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+ char *name = drmGetDeviceNameFromFd2(fd);
+ if (!name) {
+ errno = ENODEV;
+ return -1;
+ }
+
+ int type = drmGetNodeType(name);
+ free(name);
+ if (type < 0)
+ errno = ENODEV;
+ return type;
+#else
+ stat_t sbuf;
int maj, min, type;
if (fstat(fd, &sbuf))
@@ -2749,6 +2777,7 @@ int drmGetNodeTypeFromFd(int fd)
if (type == -1)
errno = ENODEV;
return type;
+#endif
}
int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd)
@@ -2788,7 +2817,7 @@ static char *drmGetMinorNameForFD(int fd
#ifdef __linux__
DIR *sysdir;
struct dirent *pent, *ent;
- struct stat sbuf;
+ stat_t sbuf;
const char *name = drmGetMinorName(type);
int len;
char dev_name[64], buf[64];
@@ -2839,13 +2868,35 @@ static char *drmGetMinorNameForFD(int fd
out_close_dir:
closedir(sysdir);
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+ struct stat buf;
+ char name[64];
+ const char *dev_name = drmGetDeviceName(type);
+ if (!dev_name)
+ return NULL;
+
+ fstat(fd, &buf);
+ snprintf(name, sizeof(name), "/dev/%s",
+ devname(buf.st_rdev, S_IFCHR));
+ char *name = drmGetDeviceNameFromFd2(fd);
+ if (!name)
+ return NULL;
+
+ return strdup(name);
+ int oldnum = drmGetNodeNumber(name);
+ int oldtype = drmGetMinorType(oldnum);
+ if (oldtype < 0) {
+ free(name);
+ return NULL;
+ }
+
+ int newnum = oldnum - drmGetMinorBase(oldtype) + drmGetMinorBase(type);
+ snprintf(name, DRM_NODE_NAME_MAX, dev_name, DRM_DIR_NAME, newnum);
+ return name;
#else
struct stat sbuf;
char buf[PATH_MAX + 1];
@@ -2960,7 +2979,7 @@ static int drmParseSubsystemType(int maj
- struct stat sbuf;
- char buf[PATH_MAX + 1];
- const char *dev_name;
+ stat_t sbuf;
+ char buf[DRM_NODE_NAME_MAX];
+ const char *dev_name = drmGetDeviceName(type);
unsigned int maj, min;
int n, base;
+ if (!dev_name)
+ return NULL;
+
if (fstat(fd, &sbuf))
return NULL;
@@ -2855,20 +2906,6 @@ out_close_dir:
if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
return NULL;
- switch (type) {
- case DRM_NODE_PRIMARY:
- dev_name = DRM_DEV_NAME;
- break;
- case DRM_NODE_CONTROL:
- dev_name = DRM_CONTROL_DEV_NAME;
- break;
- case DRM_NODE_RENDER:
- dev_name = DRM_RENDER_DEV_NAME;
- break;
- default:
- return NULL;
- };
-
base = drmGetMinorBase(type);
if (base < 0)
return NULL;
@@ -2966,7 +3003,7 @@ static int drmParseSubsystemType(int maj
return DRM_BUS_HOST1X;
return -EINVAL;
@ -76,163 +414,389 @@
return DRM_BUS_PCI;
#else
#warning "Missing implementation of drmParseSubsystemType"
@@ -3023,6 +3042,61 @@ static int drmParsePciBusInfo(int maj, i
@@ -2974,7 +3011,8 @@ static int drmParseSubsystemType(int maj
#endif
}
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+/*
+ * XXX temporary workaround, because FreeBSD doesn't provide
+ * pcibus device sysctl trees for renderD and controlD nodes (yet)
+ */
+static void
+drmBSDDeviceNameHack(const char *path, char *hacked_path, int length)
+{
+ int start, number;
+ const char *errstr;
-static int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info)
+static int drmParsePciBusInfo(const char *node, int node_type,
+ int maj, int min, drmPciBusInfoPtr info)
{
#ifdef __linux__
unsigned int domain, bus, dev, func;
@@ -3023,6 +3061,60 @@ static int drmParsePciBusInfo(int maj, i
info->func = pinfo.func;
return 0;
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+ /*
+ * Only the primary nodes can be mapped to hw.dri.%i via major/minor
+ * Determine the primary node by offset and use its major/minor pair
+ */
+ if (node_type != DRM_NODE_PRIMARY) {
+ char name[DRM_NODE_NAME_MAX];
+ snprintf(name, sizeof(name), DRM_DEV_NAME, DRM_DIR_NAME,
+ drmGetNodeNumber(node) - drmGetMinorBase(node_type));
+
+ if (strcmp(path, DRM_DIR_NAME "/controlD") > 0) {
+ start = 17;
+ number = strtonum(&path[start], 0, 256, &errstr) - 64;
+ snprintf(hacked_path, length, "%s/card%i", DRM_DIR_NAME, number);
+ } else if (strcmp(path, DRM_DIR_NAME "/renderD") > 0) {
+ start = 16;
+ number = strtonum(&path[start], 0, 256, &errstr) - 128;
+ snprintf(hacked_path, length, "%s/card%i", DRM_DIR_NAME, number);
+ } else
+ snprintf(hacked_path, length, "%s", path);
+ stat_t sbuf;
+ if (stat(name, &sbuf))
+ return -errno;
+
+ return;
+}
+
+static int
+drmParsePciBusInfoBSD(const char *path, drmPciBusInfoPtr info)
+{
+ int fd, ret;
+ int domain = 0, bus = 0, slot = 0, function = 0;
+ char hacked_path[PATH_MAX + 1];
+
+ drmBSDDeviceNameHack(path, hacked_path, PATH_MAX);
+ fd = open(hacked_path, O_RDONLY);
+
+ if (fd < 0)
+ return -errno;
+
+ ret = devq_device_get_pcibusaddr(fd, &domain, &bus, &slot, &function);
+
+ if (ret < 0) {
+ close(fd);
+ return -1;
+ maj = major(sbuf.st_rdev);
+ min = minor(sbuf.st_rdev);
+ }
+ /*
+ * Major/minor appear after the driver name in the hw.dri.%i.name node
+ * Find the node with matching major/minor pair and parse the bus ID,
+ * which may be after the name or may be alone in hw.dri.%i.busid
+ */
+ #define bus_fmt "pci:%04x:%02x:%02x.%u"
+ #define name_fmt "%*s %x " bus_fmt
+ for (int i = 0; i < DRM_MAX_MINOR; ++i) {
+ char name[16], value[256];
+ size_t length = sizeof(value);
+ snprintf(name, sizeof(name), "hw.dri.%i.name", i);
+ if (sysctlbyname(name, value, &length, NULL, 0))
+ continue;
+
+ info->domain = (uint16_t) domain;
+ info->bus = (uint8_t) bus;
+ info->dev = (uint8_t) slot;
+ info->func = (uint8_t) function;
+ value[length] = '\0';
+ unsigned int rdev = 0, domain = 0, bus = 0, slot = 0, func = 0;
+ int vals = sscanf(value, name_fmt, &rdev, &domain, &bus, &slot, &func);
+
+ close(fd);
+ return 0;
+}
+#endif
+
static int drmCompareBusInfo(drmDevicePtr a, drmDevicePtr b)
{
if (a == NULL || b == NULL)
@@ -3188,6 +3262,36 @@ static int drmParsePciDeviceInfo(int maj
#endif
+ if (vals >= 1 && rdev == makedev(maj,min)) {
+ if (vals < 5) {
+ /* busid not in the name, try busid */
+ length = sizeof(value);
+ snprintf(name, sizeof(name), "hw.dri.%i.busid", i);
+ if (sysctlbyname(name, value, &length, NULL, 0))
+ break;
+ value[length] = '\0';
+ if (sscanf(value, bus_fmt, &domain, &bus, &slot, &func) != 4)
+ break;
+ }
+ info->domain = domain;
+ info->bus = bus;
+ info->dev = slot;
+ info->func = func;
+ return 0;
+ }
+ }
+ return -ENODEV;
#else
#warning "Missing implementation of drmParsePciBusInfo"
return -EINVAL;
@@ -3057,32 +3149,6 @@ static int drmCompareBusInfo(drmDevicePt
return -1;
}
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+static int drmParsePciDeviceInfoBSD(const char *path,
+ drmPciDeviceInfoPtr device,
+ uint32_t flags)
+{
+ int fd, vendor_id = 0, device_id = 0, subvendor_id = 0,
+ subdevice_id = 0, revision_id = 0;
+ char hacked_path[PATH_MAX + 1];
-static int drmGetNodeType(const char *name)
-{
- if (strncmp(name, DRM_PRIMARY_MINOR_NAME,
- sizeof(DRM_PRIMARY_MINOR_NAME) - 1) == 0)
- return DRM_NODE_PRIMARY;
-
- if (strncmp(name, DRM_CONTROL_MINOR_NAME,
- sizeof(DRM_CONTROL_MINOR_NAME ) - 1) == 0)
- return DRM_NODE_CONTROL;
-
- if (strncmp(name, DRM_RENDER_MINOR_NAME,
- sizeof(DRM_RENDER_MINOR_NAME) - 1) == 0)
- return DRM_NODE_RENDER;
-
- return -EINVAL;
-}
-
-static int drmGetMaxNodeName(void)
-{
- return sizeof(DRM_DIR_NAME) +
- MAX3(sizeof(DRM_PRIMARY_MINOR_NAME),
- sizeof(DRM_CONTROL_MINOR_NAME),
- sizeof(DRM_RENDER_MINOR_NAME)) +
- 3 /* length of the node number */;
-}
-
#ifdef __linux__
static int parse_separate_sysfs_files(int maj, int min,
drmPciDeviceInfoPtr device,
@@ -3152,6 +3218,7 @@ static int parse_config_sysfs_file(int m
#endif
static int drmParsePciDeviceInfo(int maj, int min,
+ drmPciBusInfoPtr info,
drmPciDeviceInfoPtr device,
uint32_t flags)
{
@@ -3188,6 +3255,43 @@ static int drmParsePciDeviceInfo(int maj
device->subdevice_id = pinfo.subdevice_id;
return 0;
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+ struct pci_conf_io pc;
+ struct pci_match_conf patterns[1];
+ struct pci_conf results[1];
+
+ drmBSDDeviceNameHack(path, hacked_path, PATH_MAX);
+
+ fd = open(hacked_path, O_RDONLY);
+
+ int fd = open("/dev/pci", O_RDONLY, 0);
+ if (fd < 0)
+ return -errno;
+
+ devq_device_get_pciid_full_from_fd(fd, &vendor_id, &device_id,
+ &subvendor_id, &subdevice_id, &revision_id);
+
+ device->vendor_id = (uint16_t) vendor_id;
+ device->device_id = (uint16_t) device_id;
+ device->subvendor_id = (uint16_t) subvendor_id;
+ device->subdevice_id = (uint16_t) subdevice_id;
+ device->revision_id = (uint8_t) revision_id;
+
+ 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) {
+ int error = errno;
+ close(fd);
+ return -error;
+ }
+ close(fd);
+ return 0;
+}
+#endif
+
static void drmFreePlatformDevice(drmDevicePtr device)
{
if (device->deviceinfo.platform) {
@@ -3308,7 +3412,11 @@ static int drmProcessPciDevice(drmDevice
+ 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;
@@ -3268,7 +3372,7 @@ static drmDevicePtr drmDeviceAlloc(unsig
unsigned int i;
char *ptr;
- max_node_length = ALIGN(drmGetMaxNodeName(), sizeof(void *));
+ max_node_length = ALIGN(DRM_NODE_NAME_MAX, sizeof(void *));
extra = DRM_NODE_MAX * (sizeof(void *) + max_node_length);
size = sizeof(*device) + extra + bus_size + device_size;
@@ -3314,7 +3418,7 @@ static int drmProcessPciDevice(drmDevice
dev->businfo.pci = (drmPciBusInfoPtr)addr;
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+ ret = drmParsePciBusInfoBSD(node, dev->businfo.pci);
+#else
ret = drmParsePciBusInfo(maj, min, dev->businfo.pci);
+#endif
- ret = drmParsePciBusInfo(maj, min, dev->businfo.pci);
+ ret = drmParsePciBusInfo(node, node_type, maj, min, dev->businfo.pci);
if (ret)
goto free_device;
@@ -3316,8 +3424,11 @@ static int drmProcessPciDevice(drmDevice
if (fetch_deviceinfo) {
@@ -3323,7 +3427,7 @@ static int drmProcessPciDevice(drmDevice
addr += sizeof(drmPciBusInfo);
dev->deviceinfo.pci = (drmPciDeviceInfoPtr)addr;
-
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+ ret = drmParsePciDeviceInfoBSD(node, dev->deviceinfo.pci, flags);
+#else
ret = drmParsePciDeviceInfo(maj, min, dev->deviceinfo.pci, flags);
+#endif
- ret = drmParsePciDeviceInfo(maj, min, dev->deviceinfo.pci, flags);
+ ret = drmParsePciDeviceInfo(maj, min, dev->businfo.pci, dev->deviceinfo.pci, flags);
if (ret)
goto free_device;
}
@@ -3786,7 +3897,7 @@ int drmGetDevice2(int fd, uint32_t flags
@@ -3673,7 +3777,7 @@ static void drmFoldDuplicatedDevices(drm
local_devices[i]->available_nodes |= local_devices[j]->available_nodes;
node_type = log2(local_devices[j]->available_nodes);
memcpy(local_devices[i]->nodes[node_type],
- local_devices[j]->nodes[node_type], drmGetMaxNodeName());
+ local_devices[j]->nodes[node_type], DRM_NODE_NAME_MAX);
drmFreeDevice(&local_devices[j]);
}
}
@@ -3691,7 +3795,7 @@ drm_device_validate_flags(uint32_t flags
* Get information about the opened drm device
*
* \param fd file descriptor of the drm device
- * \param flags feature/behaviour bitmask
+ * \param flags feature/behavior bitmask
* \param device the address of a drmDevicePtr where the information
* will be allocated in stored
*
@@ -3709,8 +3813,8 @@ int drmGetDevice2(int fd, uint32_t flags
* Avoid stat'ing all of /dev needlessly by implementing this custom path.
*/
drmDevicePtr d;
- struct stat sbuf;
- char node[PATH_MAX + 1];
+ stat_t sbuf;
+ char node[DRM_NODE_NAME_MAX];
const char *dev_name;
int node_type, subsystem_type;
int maj, min, n, ret, base;
@@ -3731,26 +3835,16 @@ int drmGetDevice2(int fd, uint32_t flags
if (node_type == -1)
return -ENODEV;
- switch (node_type) {
- case DRM_NODE_PRIMARY:
- dev_name = DRM_DEV_NAME;
- break;
- case DRM_NODE_CONTROL:
- dev_name = DRM_CONTROL_DEV_NAME;
- break;
- case DRM_NODE_RENDER:
- dev_name = DRM_RENDER_DEV_NAME;
- break;
- default:
+ dev_name = drmGetDeviceName(node_type);
+ if (!dev_name)
return -EINVAL;
- };
base = drmGetMinorBase(node_type);
if (base < 0)
return -EINVAL;
- n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min - base);
- if (n == -1 || n >= PATH_MAX)
+ n = snprintf(node, sizeof(node), dev_name, DRM_DIR_NAME, min - base);
+ if (n == -1 || n >= sizeof(node))
return -errno;
if (stat(node, &sbuf))
return -EINVAL;
@@ -3771,8 +3865,8 @@ int drmGetDevice2(int fd, uint32_t flags
drmDevicePtr d;
DIR *sysdir;
struct dirent *dent;
- struct stat sbuf;
- char node[PATH_MAX + 1];
+ stat_t sbuf;
+ char node[DRM_NODE_NAME_MAX];
int node_type, subsystem_type;
int maj, min;
int ret, i, node_count;
@@ -3792,7 +3886,7 @@ int drmGetDevice2(int fd, uint32_t flags
maj = major(sbuf.st_rdev);
min = minor(sbuf.st_rdev);
- if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
+ if (DRM_MAJOR && maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
+ if ((DRM_MAJOR && maj != DRM_MAJOR) || !S_ISCHR(sbuf.st_mode))
return -EINVAL;
subsystem_type = drmParseSubsystemType(maj, min);
@@ -3814,7 +3925,7 @@ int drmGetDevice2(int fd, uint32_t flags
@@ -3813,14 +3907,14 @@ int drmGetDevice2(int fd, uint32_t flags
if (node_type < 0)
continue;
- snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, dent->d_name);
+ snprintf(node, sizeof(node), "%s/%s", DRM_DIR_NAME, dent->d_name);
if (stat(node, &sbuf))
continue;
maj = major(sbuf.st_rdev);
min = minor(sbuf.st_rdev);
- if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
+ if (DRM_MAJOR && maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
+ if ((DRM_MAJOR && maj != DRM_MAJOR) || !S_ISCHR(sbuf.st_mode))
continue;
if (drmParseSubsystemType(maj, min) != subsystem_type)
@@ -3964,7 +4075,7 @@ int drmGetDevices2(uint32_t flags, drmDe
@@ -3918,7 +4012,7 @@ int drmGetDevice(int fd, drmDevicePtr *d
/**
* Get drm devices on the system
*
- * \param flags feature/behaviour bitmask
+ * \param flags feature/behavior bitmask
* \param devices the array of devices with drmDevicePtr elements
* can be NULL to get the device number first
* \param max_devices the maximum number of devices for the array
@@ -3937,8 +4031,8 @@ int drmGetDevices2(uint32_t flags, drmDe
drmDevicePtr device;
DIR *sysdir;
struct dirent *dent;
- struct stat sbuf;
- char node[PATH_MAX + 1];
+ stat_t sbuf;
+ char node[DRM_NODE_NAME_MAX];
int node_type, subsystem_type;
int maj, min;
int ret, i, node_count, device_count;
@@ -3963,14 +4057,14 @@ int drmGetDevices2(uint32_t flags, drmDe
if (node_type < 0)
continue;
- snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, dent->d_name);
+ snprintf(node, sizeof(node), "%s/%s", DRM_DIR_NAME, dent->d_name);
if (stat(node, &sbuf))
continue;
maj = major(sbuf.st_rdev);
min = minor(sbuf.st_rdev);
- if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
+ if (DRM_MAJOR && maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
+ if ((DRM_MAJOR && maj != DRM_MAJOR) || !S_ISCHR(sbuf.st_mode))
continue;
subsystem_type = drmParseSubsystemType(maj, min);
@@ -4108,7 +4219,7 @@ char *drmGetDeviceNameFromFd2(int fd)
maj = major(sbuf.st_rdev);
min = minor(sbuf.st_rdev);
@@ -4078,7 +4172,7 @@ int drmGetDevices(drmDevicePtr devices[]
char *drmGetDeviceNameFromFd2(int fd)
{
#ifdef __linux__
- struct stat sbuf;
+ stat_t sbuf;
char path[PATH_MAX + 1], *value;
unsigned int maj, min;
- if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
+ if (DRM_MAJOR && maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
@@ -4101,9 +4195,26 @@ char *drmGetDeviceNameFromFd2(int fd)
free(value);
return strdup(path);
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+ stat_t sbuf;
+ if (fstat(fd, &sbuf))
+ return NULL;
+
+ dev_t rdev = sbuf.st_rdev;
+ /* minor numbers don't depend on node name suffix, search for a match */
+ for (int i = 0; i < DRM_MAX_MINOR; ++i) {
+ char node[DRM_NODE_NAME_MAX];
+ for (int j = 0; j < DRM_NODE_MAX; ++j) {
+ snprintf(node, sizeof(node), drmGetDeviceName(j),
+ DRM_DIR_NAME, drmGetMinorBase(j) + i);
+ if (stat(node, &sbuf) == 0 && sbuf.st_rdev == rdev)
+ return strdup(node);
+ }
+ }
+ return NULL;
#else
- struct stat sbuf;
- char node[PATH_MAX + 1];
+ stat_t sbuf;
+ char node[DRM_NODE_NAME_MAX];
const char *dev_name;
int node_type;
int maj, min, n, base;
@@ -4121,26 +4232,16 @@ char *drmGetDeviceNameFromFd2(int fd)
if (node_type == -1)
return NULL;
node_type = drmGetMinorType(min);
- switch (node_type) {
- case DRM_NODE_PRIMARY:
- dev_name = DRM_DEV_NAME;
- break;
- case DRM_NODE_CONTROL:
- dev_name = DRM_CONTROL_DEV_NAME;
- break;
- case DRM_NODE_RENDER:
- dev_name = DRM_RENDER_DEV_NAME;
- break;
- default:
+ dev_name = drmGetDeviceName(node_type);
+ if (!dev_name)
return NULL;
- };
base = drmGetMinorBase(node_type);
if (base < 0)
return NULL;
- n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min - base);
- if (n == -1 || n >= PATH_MAX)
+ n = snprintf(node, sizeof(node), dev_name, DRM_DIR_NAME, min - base);
+ if (n == -1 || n >= sizeof(node))
return NULL;
return strdup(node);

View File

@ -0,0 +1,37 @@
--- xf86drm.h.orig 2017-04-07 08:49:13 UTC
+++ xf86drm.h
@@ -78,17 +78,27 @@ extern "C" {
#ifdef __OpenBSD__
#define DRM_DIR_NAME "/dev"
-#define DRM_DEV_NAME "%s/drm%d"
-#define DRM_CONTROL_DEV_NAME "%s/drmC%d"
-#define DRM_RENDER_DEV_NAME "%s/drmR%d"
+#define DRM_PRIMARY_MINOR_NAME "drm"
+#define DRM_CONTROL_MINOR_NAME "drmC"
+#define DRM_RENDER_MINOR_NAME "drmR"
#else
#define DRM_DIR_NAME "/dev/dri"
-#define DRM_DEV_NAME "%s/card%d"
-#define DRM_CONTROL_DEV_NAME "%s/controlD%d"
-#define DRM_RENDER_DEV_NAME "%s/renderD%d"
-#define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */
+#define DRM_PRIMARY_MINOR_NAME "card"
+#define DRM_CONTROL_MINOR_NAME "controlD"
+#define DRM_RENDER_MINOR_NAME "renderD"
#endif
+#define DRM_DEV_NAME "%s/" DRM_PRIMARY_MINOR_NAME "%d"
+#define DRM_CONTROL_DEV_NAME "%s/" DRM_CONTROL_MINOR_NAME "%d"
+#define DRM_RENDER_DEV_NAME "%s/" DRM_RENDER_MINOR_NAME "%d"
+
+#define DRM_NODE_NAME_MAX \
+ (sizeof(DRM_DIR_NAME) + \
+ MAX3(sizeof(DRM_PRIMARY_MINOR_NAME), \
+ sizeof(DRM_CONTROL_MINOR_NAME), \
+ sizeof(DRM_RENDER_MINOR_NAME)) \
+ + 3) /* length of the node number */
+
#define DRM_ERR_NO_DEVICE (-1001)
#define DRM_ERR_NO_ACCESS (-1002)
#define DRM_ERR_NOT_ROOT (-1003)

View File

@ -1,4 +1,4 @@
--- xf86drmMode.c.orig 2017-01-28 01:15:16 UTC
--- xf86drmMode.c.orig 2017-04-07 08:49:13 UTC
+++ xf86drmMode.c
@@ -47,6 +47,7 @@
#include <stdlib.h>
@ -8,3 +8,96 @@
#include <sys/sysctl.h>
#endif
#include <stdio.h>
@@ -796,43 +797,60 @@ int drmCheckModesettingSupported(const c
closedir(sysdir);
if (found)
return 0;
-#elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
- char kbusid[1024], sbusid[1024];
- char oid[128];
- int domain, bus, dev, func;
- int i, modesetting, ret;
- size_t len;
+#elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__DragonFly__)
+ #define bus_fmt "pci:%04x:%02x:%02x.%u"
+ #define name_fmt "%*s %*s " bus_fmt
+ unsigned int d1 = 0, b1 = 0, s1 = 0, f1 = 0;
+ if (sscanf(busid, bus_fmt, &d1, &b1, &s1, &f1) != 4)
+ return -EINVAL;
+ /*
+ * hw.dri.%i.bus is not always present and hw.dri.%i.name does not
+ * always contain the busid, so try both for best chance of success
+ */
+ for (int i = 0; i < DRM_MAX_MINOR; ++i) {
+ char name[22], value[256];
+ size_t length = sizeof(value);
+ snprintf(name, sizeof(name), "hw.dri.%i.name", i);
+ if (sysctlbyname(name, value, &length, NULL, 0))
+ continue;
- ret = sscanf(busid, "pci:%04x:%02x:%02x.%d", &domain, &bus, &dev,
- &func);
- if (ret != 4)
- return -EINVAL;
- snprintf(kbusid, sizeof(kbusid), "pci:%04x:%02x:%02x.%d", domain, bus,
- dev, func);
+ value[length] = '\0';
+ unsigned int d2 = 0, b2 = 0, s2 = 0, f2 = 0;
+ switch (sscanf(value, name_fmt, &d2, &b2, &s2, &f2)) {
+ case 0: /* busid not in the name, try busid */
+ length = sizeof(value);
+ snprintf(name, sizeof(name), "hw.dri.%i.busid", i);
+ if (sysctlbyname(name, value, &length, NULL, 0))
+ continue;
- /* How many GPUs do we expect in the machine ? */
- for (i = 0; i < 16; i++) {
- snprintf(oid, sizeof(oid), "hw.dri.%d.busid", i);
- len = sizeof(sbusid);
- ret = sysctlbyname(oid, sbusid, &len, NULL, 0);
- if (ret == -1) {
- if (errno == ENOENT)
+ value[length] = '\0';
+ if (sscanf(value, bus_fmt, &d2, &b2, &s2, &f2) != 4)
continue;
- return -EINVAL;
+ /* fall through after parsing busid */
+
+ case 4: /* if we jumped here then busid was in the name */
+ if (d1 == d2 && b1 == b2 && s1 == s2 && f1 == f2) {
+ /*
+ * Confirm the drm driver for this device supports KMS,
+ * except on DragonFly where all the drm drivers do so
+ * but only hw.dri.0.modesetting is present
+ */
+ #ifndef __DragonFly__
+ int modesetting = 0;
+ length = sizeof(modesetting);
+ snprintf(name, sizeof(name), "hw.dri.%i.modesetting", i);
+ if (sysctlbyname(name, &modesetting, &length, NULL, 0)
+ || length != sizeof(modesetting) || !modesetting)
+ return -ENOSYS;
+ else
+ #endif
+ return 0;
+ }
+ default:
+ break;
}
- if (strcmp(sbusid, kbusid) != 0)
- continue;
- snprintf(oid, sizeof(oid), "hw.dri.%d.modesetting", i);
- len = sizeof(modesetting);
- ret = sysctlbyname(oid, &modesetting, &len, NULL, 0);
- if (ret == -1 || len != sizeof(modesetting))
- return -EINVAL;
- return (modesetting ? 0 : -ENOSYS);
}
-#elif defined(__DragonFly__)
- return 0;
-#endif
-#ifdef __OpenBSD__
+#elif defined(__OpenBSD__)
int fd;
struct drm_mode_card_res res;
drmModeResPtr r = 0;