Index: graphics/libdrm/Makefile =================================================================== --- graphics/libdrm/Makefile +++ graphics/libdrm/Makefile @@ -2,9 +2,8 @@ # $FreeBSD$ PORTNAME= libdrm -PORTVERSION= 2.4.75 +PORTVERSION= 2.4.76 PORTEPOCH= 1 -PORTREVISION= 3 CATEGORIES= graphics x11 MASTER_SITES= http://dri.freedesktop.org/libdrm/ @@ -14,8 +13,7 @@ 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 @@ # 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 Index: graphics/libdrm/distinfo =================================================================== --- graphics/libdrm/distinfo +++ graphics/libdrm/distinfo @@ -1,3 +1,3 @@ -TIMESTAMP = 1485779860 -SHA256 (libdrm-2.4.75.tar.bz2) = 2d5a500eef412cc287d12268eed79d571e262d4957a2ec9258073f305985054f -SIZE (libdrm-2.4.75.tar.bz2) = 774589 +TIMESTAMP = 1490822962 +SHA256 (libdrm-2.4.76.tar.bz2) = 7cdfb83ea77def453299dd95332aa9257c9f3534ff5844f5c0ce87265c275f3a +SIZE (libdrm-2.4.76.tar.bz2) = 783155 Index: graphics/libdrm/files/Makefile.am =================================================================== --- graphics/libdrm/files/Makefile.am +++ /dev/null @@ -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) Index: graphics/libdrm/files/configure.ac =================================================================== --- graphics/libdrm/files/configure.ac +++ /dev/null @@ -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@:>@]), Index: graphics/libdrm/files/extra-xf86drm.c =================================================================== --- graphics/libdrm/files/extra-xf86drm.c +++ graphics/libdrm/files/extra-xf86drm.c @@ -4,7 +4,7 @@ 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 Index: graphics/libdrm/files/patch-Makefile.in =================================================================== --- graphics/libdrm/files/patch-Makefile.in +++ /dev/null @@ -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) Index: graphics/libdrm/files/patch-config.h.in =================================================================== --- graphics/libdrm/files/patch-config.h.in +++ /dev/null @@ -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 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 - Index: graphics/libdrm/files/patch-configure =================================================================== --- graphics/libdrm/files/patch-configure +++ /dev/null @@ -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 Index: graphics/libdrm/files/patch-xf86drm.h =================================================================== --- /dev/null +++ graphics/libdrm/files/patch-xf86drm.h @@ -0,0 +1,37 @@ +--- xf86drm.h.orig 2017-03-21 18:18:28 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) Index: graphics/libdrm/files/patch-xf86drm.c =================================================================== --- graphics/libdrm/files/patch-xf86drm.c +++ graphics/libdrm/files/patch-xf86drm.c @@ -1,73 +1,414 @@ ---- xf86drm.c.orig 2017-01-30 19:04:05 UTC +--- xf86drm.c.orig 2017-03-21 19:07:25 UTC +++ xf86drm.c -@@ -62,6 +62,10 @@ +@@ -49,6 +49,9 @@ + #include + #include + #include ++#ifdef HAVE_SYS_SYSCTL_H ++#include ++#endif + #include + #define stat_t struct stat + #include +@@ -62,6 +65,10 @@ #endif #include -+#ifdef HAVE_LIBDEVQ -+#include "libdevq.h" ++#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) ++#include +#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" +@@ -72,18 +79,12 @@ + + #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" ++#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) ++#define DRM_MAJOR 0 #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 */ #endif #ifdef __NetBSD__ -@@ -548,6 +556,7 @@ static int drmGetMinorType(int minor) - } +@@ -180,7 +181,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; - } + /** +- * 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 +224,89 @@ drmHashEntry *drmGetEntry(int fd) + return entry; } + ++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 +374,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 +411,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 +422,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 +533,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 +587,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. -@@ -2734,7 +2744,7 @@ int drmGetNodeTypeFromFd(int fd) - maj = major(sbuf.st_rdev); - min = minor(sbuf.st_rdev); + * +@@ -2699,33 +2724,40 @@ int drmDropMaster(int fd) -- if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) { -+ if (DRM_MAJOR && maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) { - errno = EINVAL; - return -1; + 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)) +@@ -2743,6 +2775,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) +@@ -2782,7 +2815,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]; +@@ -2833,13 +2866,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]; -+ -+ fstat(fd, &buf); -+ snprintf(name, sizeof(name), "/dev/%s", -+ devname(buf.st_rdev, S_IFCHR)); ++ const char *dev_name = drmGetDeviceName(type); ++ if (!dev_name) ++ return NULL; ++ ++ char *name = drmGetDeviceNameFromFd2(fd); ++ if (!name) ++ return NULL; ++ ++ int oldnum = drmGetNodeNumber(name); ++ int oldtype = drmGetMinorType(oldnum); ++ if (oldtype < 0) { ++ free(name); ++ return NULL; ++ } + -+ return strdup(name); ++ 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; + +@@ -2849,20 +2904,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; +@@ -2960,7 +3001,7 @@ static int drmParseSubsystemType(int maj return DRM_BUS_HOST1X; return -EINVAL; @@ -76,163 +417,379 @@ return DRM_BUS_PCI; #else #warning "Missing implementation of drmParseSubsystemType" -@@ -3023,6 +3042,61 @@ static int drmParsePciBusInfo(int maj, i +@@ -2968,7 +3009,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; -+ -+ 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); -+ -+ 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]; +-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; +@@ -3017,6 +3059,50 @@ 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)); ++ ++ stat_t sbuf; ++ if (stat(name, &sbuf)) ++ return -errno; + -+ drmBSDDeviceNameHack(path, hacked_path, PATH_MAX); -+ fd = open(hacked_path, O_RDONLY); ++ 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 ++ */ ++ const char *name_fmt = "%*s %x pci:%u:%u:%u.%u"; ++ 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; ++ ++ unsigned int rdev = 0, domain = 0, bus = 0, slot = 0, func = 0; ++ value[length] = '\0'; ++ if (sscanf(value, name_fmt, &rdev, &domain, &bus, &slot, &func) != 5) ++ continue; ++ ++ if (rdev == makedev(maj, min)) { ++ info->domain = domain; ++ info->bus = bus; ++ info->dev = slot; ++ info->func = func; ++ return 0; ++ } ++ } ++ return -ENODEV; + #else + #warning "Missing implementation of drmParsePciBusInfo" + return -EINVAL; +@@ -3051,32 +3137,6 @@ static int drmCompareBusInfo(drmDevicePt + return -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, +@@ -3146,6 +3206,7 @@ static int parse_config_sysfs_file(int m + #endif + + static int drmParsePciDeviceInfo(int maj, int min, ++ drmPciBusInfoPtr info, + drmPciDeviceInfoPtr device, + uint32_t flags) + { +@@ -3182,6 +3243,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]; + ++ int fd = open("/dev/pci", O_RDONLY, 0); + if (fd < 0) + return -errno; + -+ ret = devq_device_get_pcibusaddr(fd, &domain, &bus, &slot, &function); ++ 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 (ret < 0) { ++ if (ioctl(fd, PCIOCGETCONF, &pc) || pc.status == PCI_GETCONF_ERROR) { ++ int error = errno; + close(fd); -+ return -1; ++ return -error; + } -+ -+ info->domain = (uint16_t) domain; -+ info->bus = (uint8_t) bus; -+ info->dev = (uint8_t) slot; -+ info->func = (uint8_t) function; -+ + 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 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]; ++ 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; + -+ drmBSDDeviceNameHack(path, hacked_path, PATH_MAX); -+ -+ fd = open(hacked_path, O_RDONLY); -+ -+ 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; -+ -+ close(fd); + return 0; -+} -+#endif -+ - static void drmFreePlatformDevice(drmDevicePtr device) - { - if (device->deviceinfo.platform) { -@@ -3308,7 +3412,11 @@ static int drmProcessPciDevice(drmDevice + #else + #warning "Missing implementation of drmParsePciDeviceInfo" + return -EINVAL; +@@ -3262,7 +3360,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; +@@ -3308,7 +3406,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) { +@@ -3317,7 +3415,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 +@@ -3667,7 +3765,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]); + } + } +@@ -3685,7 +3783,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 + * +@@ -3703,8 +3801,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; +@@ -3725,26 +3823,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; +@@ -3765,8 +3853,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; +@@ -3786,7 +3874,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 +@@ -3807,14 +3895,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 +@@ -3912,7 +4000,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 +@@ -3931,8 +4019,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; +@@ -3957,14 +4045,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); +@@ -4072,7 +4160,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)) +@@ -4095,9 +4183,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; +@@ -4115,26 +4220,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);