summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/cmd/drm-tests/misc2/Makefile.com6
-rw-r--r--usr/src/cmd/drm-tests/misc2/common/drmtest_sun.c100
-rw-r--r--usr/src/cmd/drm-tests/misc2/common/getsundev.c131
-rw-r--r--usr/src/common/libdrm/patches/xf86drm-c.patch170
-rw-r--r--usr/src/common/libdrm/patches/xf86drm-h.patch18
-rw-r--r--usr/src/lib/libdrm/Makefile.com12
-rw-r--r--usr/src/lib/libdrm/common/sun_devinfo.c291
-rw-r--r--usr/src/lib/libdrm/common/sun_xf86drm.c176
-rw-r--r--usr/src/pkg/manifests/system-test-libdrm.mf2
9 files changed, 856 insertions, 50 deletions
diff --git a/usr/src/cmd/drm-tests/misc2/Makefile.com b/usr/src/cmd/drm-tests/misc2/Makefile.com
index dd2862b..a6a24dd 100644
--- a/usr/src/cmd/drm-tests/misc2/Makefile.com
+++ b/usr/src/cmd/drm-tests/misc2/Makefile.com
@@ -20,7 +20,8 @@ PROG= \
getstats \
setversion \
updatedraw \
- name_from_fd
+ name_from_fd \
+ getsundev
# All programs here require this devinfo object.
DEVOBJ=drmtest_sun.o
@@ -53,6 +54,9 @@ clean:
%.o : ../common/%.c
$(COMPILE.c) -o $@ -c $<
+getsundev : getsundev.o
+ $(LINK.c) -o $@ $@.o $(DEVOBJ) $(LDLIBS)
+
.KEEP_STATE:
include ../../../Makefile.targ
diff --git a/usr/src/cmd/drm-tests/misc2/common/drmtest_sun.c b/usr/src/cmd/drm-tests/misc2/common/drmtest_sun.c
index 6328803..caf5d31 100644
--- a/usr/src/cmd/drm-tests/misc2/common/drmtest_sun.c
+++ b/usr/src/cmd/drm-tests/misc2/common/drmtest_sun.c
@@ -25,6 +25,29 @@
*
*/
+/*
+ * Copyright 2016 Gordon W. Ross
+ */
+
+/*
+ * Helper functions for libdrm/tests. See:
+ * drm_open_any()
+ * getclient.c
+ * getstats.c
+ * getversion.c
+ * openclose.c
+ * drm_open_any_master()
+ * setversion.c
+ * updatedraw.c
+ *
+ * This module replaces libdrm/tests/drmtest.c
+ * which needs the linux "udev" interfaces.
+ * Here we use libdevinfo.h instead via these
+ * private interfaces in libdrm:
+ * _sun_drm_find_device()
+ * _sun_drm_get_pci_info()
+ */
+
#include <string.h>
#include <fcntl.h>
#include <fnmatch.h>
@@ -53,48 +76,45 @@ static int is_master(int fd)
return 1;
}
-/** Open the first DRM device matching the criteria */
+/*
+ * Open the first DRM device matching the criteria
+ */
int drm_open_matching(const char *pci_glob, int flags)
{
- di_node_t udev;
-// struct udev_enumerate *e;
-// struct udev_device *device, *parent;
-// struct udev_list_entry *entry;
- const char *pci_id, *path;
- const char *usub, *dnode;
- uint_t di_flags;
- int fd;
-
- /* Get everything? */
- di_flags = DINFOSUBTREE | DINFOPROP | DINFOMINOR | DINFOPATH | DINFOLYR;
- udev = di_init("/", di_flags);
- if (udev == DI_NODE_NIL) {
- fprintf(stderr, "failed to initialize devinfo context\n");
- exit (1);
- }
-
- fd = -1;
-#if 0 // Todo
- e = udev_enumerate_new(udev);
- udev_enumerate_add_match_subsystem(e, "drm");
- udev_enumerate_scan_devices(e);
- udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
- path = udev_list_entry_get_name(entry);
- device = udev_device_new_from_syspath(udev, path);
- parent = udev_device_get_parent(device);
- usub = udev_device_get_subsystem(parent);
- /* Filter out KMS output devices. */
- if (!usub || (strcmp(usub, "pci") != 0))
- continue;
- pci_id = udev_device_get_property_value(parent, "PCI_ID");
- if (fnmatch(pci_glob, pci_id, 0) != 0)
- continue;
- dnode = udev_device_get_devnode(device);
- if (strstr(dnode, "control"))
+ char *path = NULL;
+ int i, ret;
+ int fd = -1;
+
+ /*
+ * If our glob patter matches all, let's skip
+ * getting the PCI info etc.
+ */
+ if (strcmp(pci_glob, "*:*") == 0)
+ pci_glob = NULL;
+
+ /* Could also start at the offset for some device type. */
+ for (i = 0; i < DRM_MAX_MINOR; i++) {
+ free(path);
+ ret = _sun_drm_find_device(i, &path);
+ if (ret != 0)
continue;
- fd = open(dnode, O_RDWR);
+
+ if (pci_glob != NULL) {
+ drmPciDeviceInfo pcii;
+ char pci_str[32];
+ ret = _sun_drm_get_pci_info(path, &pcii);
+ if (ret != 0)
+ continue;
+ snprintf(pci_str, sizeof (pci_str),
+ "%x:%x", pcii.vendor_id, pcii.device_id);
+ if (fnmatch(pci_glob, pci_str, 0) != 0)
+ continue;
+ }
+
+ fd = open(path, O_RDWR);
if (fd < 0)
continue;
+
if ((flags & DRM_TEST_MASTER) && !is_master(fd)) {
close(fd);
fd = -1;
@@ -103,12 +123,8 @@ int drm_open_matching(const char *pci_glob, int flags)
break;
}
- udev_enumerate_unref(e);
-#else
- exit (1);
-#endif
- di_fini(udev);
+ free(path);
return fd;
}
diff --git a/usr/src/cmd/drm-tests/misc2/common/getsundev.c b/usr/src/cmd/drm-tests/misc2/common/getsundev.c
new file mode 100644
index 0000000..12be92f
--- /dev/null
+++ b/usr/src/cmd/drm-tests/misc2/common/getsundev.c
@@ -0,0 +1,131 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * Copyright 2016 Gordon W. Ross
+ */
+
+/*
+ * Tests for the OS-dependent functions over in:
+ * libdevinfo/common/sun_devinfo.c
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <fnmatch.h>
+#include <libdevinfo.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mkdev.h>
+
+#include "xf86drm.h"
+
+int main(int argc, char **argv)
+{
+ drmPciBusInfo pci_bus;
+ drmPciDeviceInfo pci_dev;
+ char *path;
+ char *path2;
+ int failures = 0;
+ int min = 0;
+ int maj;
+ int fd, ret;
+
+ if (argc > 1)
+ min = atoi(argv[1]);
+
+ maj = _sun_drm_get_major();
+ printf("drm major: %d\n", maj);
+
+ ret = _sun_drm_find_device(min, &path);
+ if (ret) {
+ printf("FAIL: _sun_drm_find_device(%d, &) -> %d\n", min, ret);
+ failures++;
+ } else {
+ printf("Found device: %s\n", path);
+ }
+
+ ret = _sun_drmParseSubsystemType(maj, min);
+ if (ret != DRM_BUS_PCI) {
+ printf("FAIL: _sun_drmParseSubsystemType(%d, %d) -> %d\n",
+ maj, min, ret);
+ failures++;
+ }
+
+ ret = _sun_drmParsePciBusInfo(maj, min, &pci_bus);
+ if (ret) {
+ printf("FAIL: _sun_drmParsePciBusInfo(%d, %d, &) -> %d\n",
+ maj, min, ret);
+ failures++;
+ } else {
+ printf("PCI bus info: dom=%d bus=%d dev=%d func=%d\n",
+ pci_bus.domain,
+ pci_bus.bus,
+ pci_bus.dev,
+ pci_bus.func);
+ }
+
+ ret = _sun_drmParsePciDeviceInfo(path, &pci_dev);
+ if (ret) {
+ printf("FAIL: _sun_drmParsePciDeviceInfo(\"%s\", &) -> %d\n",
+ path, ret);
+ failures++;
+ } else {
+ printf("PCI device info: ven=%x dev=%x "
+ "subven=%x subdev=%x rev=%x\n",
+ pci_dev.vendor_id,
+ pci_dev.device_id,
+ pci_dev.subvendor_id,
+ pci_dev.subdevice_id,
+ pci_dev.revision_id);
+ }
+
+ fd = open(path, O_RDWR);
+ if (fd < 0) {
+ ret = errno;
+ printf("FAIL: open(%s) -> %d\n", path, ret);
+ return (1);
+ }
+
+ path2 = _sun_drmGetMinorNameForFD(fd, 0);
+ if (path2 == NULL) {
+ ret = errno;
+ printf("FAIL: open(%s) -> %d\n", path, ret);
+ failures++;
+ } else {
+ printf("Path from fd: %s\n", path2);
+ if (strcmp(path2, path) != 0) {
+ printf("FAIL\n");
+ failures++;
+ }
+ }
+
+ close(fd);
+ free(path2);
+ free(path);
+
+ return (failures ? 1 : 0);
+}
diff --git a/usr/src/common/libdrm/patches/xf86drm-c.patch b/usr/src/common/libdrm/patches/xf86drm-c.patch
index 7c6064b..19a6b25 100644
--- a/usr/src/common/libdrm/patches/xf86drm-c.patch
+++ b/usr/src/common/libdrm/patches/xf86drm-c.patch
@@ -1,7 +1,83 @@
-diff ... b/xf86drm.c
---- a/xf86drm.c Fri Mar 20 07:05:48 2015
-+++ b/xf86drm.c Fri Mar 20 07:06:10 2015
-@@ -1108,7 +1108,7 @@
+diff ... libdrm-2.4.71/xf86drm.c
+--- libdrm-2.4.71-ref/xf86drm.c Wed Jul 20 19:42:21 2016
++++ libdrm-2.4.71/xf86drm.c Sun Nov 20 11:16:08 2016
+@@ -98,6 +98,11 @@
+ #endif
+ #endif /* __OpenBSD__ */
+
++#if defined(__sun)
++/* Device majors are dynamic. */
++#define DRM_MAJOR (_sun_drm_get_major())
++#endif /* __sun */
++
+ #ifndef DRM_MAJOR
+ #define DRM_MAJOR 226 /* Linux */
+ #endif
+@@ -349,9 +354,14 @@
+ if (stat(DRM_DIR_NAME, &st)) {
+ if (!isroot)
+ return DRM_ERR_NOT_ROOT;
++#if defined(__sun)
++ /* Let the system do this. */
++ return DRM_ERR_NO_DEVICE;
++#else
+ mkdir(DRM_DIR_NAME, DRM_DEV_DIRMODE);
+ chown_check_return(DRM_DIR_NAME, 0, 0); /* root:root */
+ chmod(DRM_DIR_NAME, DRM_DEV_DIRMODE);
++#endif
+ }
+
+ /* Check if the device node exists and create it if necessary. */
+@@ -358,8 +368,13 @@
+ if (stat(buf, &st)) {
+ if (!isroot)
+ return DRM_ERR_NOT_ROOT;
++#if defined(__sun)
++ /* Let the system do this. */
++ return DRM_ERR_NO_DEVICE;
++#else
+ remove(buf);
+ mknod(buf, S_IFCHR | devmode, dev);
++#endif
+ }
+
+ if (drm_server_info && drm_server_info->get_perms) {
+@@ -405,6 +420,10 @@
+ if (st.st_rdev != dev) {
+ if (!isroot)
+ return DRM_ERR_NOT_ROOT;
++#if defined(__sun)
++ /* Let the system do this. */
++ return DRM_ERR_NO_DEVICE;
++#else
+ remove(buf);
+ mknod(buf, S_IFCHR | devmode, dev);
+ if (drm_server_info && drm_server_info->get_perms) {
+@@ -411,6 +430,7 @@
+ chown_check_return(buf, user, group);
+ chmod(buf, devmode);
+ }
++#endif
+ }
+ fd = open(buf, O_RDWR, 0);
+ drmMsg("drmOpenDevice: open result is %d, (%s)\n",
+@@ -532,6 +552,7 @@
+ }
+ }
+
++#ifndef __sun /* Avoid "static unused" warning */
+ static const char *drmGetMinorName(int type)
+ {
+ switch (type) {
+@@ -545,6 +566,7 @@
+ return NULL;
+ }
+ }
++#endif /* __sun */
+
+ /**
+ * Open the device by bus ID.
+@@ -1108,7 +1130,7 @@
drm_map_t map;
memclear(map);
@@ -10,3 +86,89 @@ diff ... b/xf86drm.c
if(drmIoctl(fd, DRM_IOCTL_RM_MAP, &map))
return -errno;
+@@ -2696,6 +2718,15 @@
+ fstat(fd, &sbuf);
+ d = sbuf.st_rdev;
+
++#if defined(__sun)
++ /*
++ * Get rid of clone-open bits in the minor number.
++ * See: the drm driver drm_sun_open()
++ * Don't have DRM_CLONEID_NBITS here.
++ */
++ d &= ~0x3fe00;
++#endif
++
+ for (i = 0; i < DRM_MAX_MINOR; i++) {
+ snprintf(name, sizeof name, DRM_DEV_NAME, DRM_DIR_NAME, i);
+ if (stat(name, &sbuf) == 0 && sbuf.st_rdev == d)
+@@ -2761,6 +2792,10 @@
+ return 0;
+ }
+
++#ifdef __sun /* OS-dependent */
++#define drmGetMinorNameForFD(fd, t) \
++ _sun_drmGetMinorNameForFD(fd, t)
++#else /* __sun */
+ static char *drmGetMinorNameForFD(int fd, int type)
+ {
+ #ifdef __linux__
+@@ -2822,6 +2857,7 @@
+ #endif
+ return NULL;
+ }
++#endif /* __sun */
+
+ char *drmGetPrimaryDeviceNameFromFd(int fd)
+ {
+@@ -2833,6 +2869,10 @@
+ return drmGetMinorNameForFD(fd, DRM_NODE_RENDER);
+ }
+
++#ifdef __sun /* OS-dependent */
++#define drmParseSubsystemType(ma, mi) \
++ _sun_drmParseSubsystemType(ma, mi)
++#else /* __sun */
+ static int drmParseSubsystemType(int maj, int min)
+ {
+ #ifdef __linux__
+@@ -2859,7 +2899,12 @@
+ return -EINVAL;
+ #endif
+ }
++#endif /* __sun */
+
++#ifdef __sun /* OS-dependent */
++#define drmParsePciBusInfo(ma, mi, inf) \
++ _sun_drmParsePciBusInfo(ma, mi, inf)
++#else /* __sun */
+ static int drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info)
+ {
+ #ifdef __linux__
+@@ -2901,6 +2946,7 @@
+ return -EINVAL;
+ #endif
+ }
++#endif /* __sun */
+
+ static int drmCompareBusInfo(drmDevicePtr a, drmDevicePtr b)
+ {
+@@ -2946,6 +2992,10 @@
+ 3 /* length of the node number */;
+ }
+
++#ifdef __sun /* OS-dependent */
++#define drmParsePciDeviceInfo(name, dip) \
++ _sun_drmParsePciDeviceInfo(name, dip)
++#else /* __sun */
+ static int drmParsePciDeviceInfo(const char *d_name,
+ drmPciDeviceInfoPtr device)
+ {
+@@ -2976,6 +3026,7 @@
+ return -EINVAL;
+ #endif
+ }
++#endif /* __sun */
+
+ void drmFreeDevice(drmDevicePtr *device)
+ {
diff --git a/usr/src/common/libdrm/patches/xf86drm-h.patch b/usr/src/common/libdrm/patches/xf86drm-h.patch
index 6b00073..1dd0f7e 100644
--- a/usr/src/common/libdrm/patches/xf86drm-h.patch
+++ b/usr/src/common/libdrm/patches/xf86drm-h.patch
@@ -47,3 +47,21 @@ index 76eb94e..6a14120 100644
#ifndef DRM_CAS
#define DRM_CAS(lock,old,new,ret) do { ret=1; } while (0) /* FAST LOCK FAILS */
#endif
+@@ -796,6 +807,17 @@
+ extern int drmGetDevices(drmDevicePtr devices[], int max_devices);
+ extern void drmFreeDevices(drmDevicePtr devices[], int count);
+
++#ifdef __sun
++extern int _sun_drm_get_major(void);
++extern char * _sun_drmGetMinorNameForFD(int fd, int type);
++extern int _sun_drmParseSubsystemType(int maj, int min);
++extern int _sun_drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info);
++extern int _sun_drmParsePciDeviceInfo(const char *d_name,
++ drmPciDeviceInfoPtr device);
++extern int _sun_drm_find_device(int min, char **pathp);
++extern int _sun_drm_get_pci_info(char *path, drmPciDeviceInfo *pcii);
++#endif /* __sun */
++
+ #if defined(__cplusplus)
+ }
+ #endif
diff --git a/usr/src/lib/libdrm/Makefile.com b/usr/src/lib/libdrm/Makefile.com
index 8dd6a3d..c8aa409 100644
--- a/usr/src/lib/libdrm/Makefile.com
+++ b/usr/src/lib/libdrm/Makefile.com
@@ -30,8 +30,8 @@ VERS= .2
# See common/libdrm/libdrm-*/Makefile.in am__objects
OBJECTS= xf86drm.o xf86drmHash.o \
- xf86drmRandom.o xf86drmSL.o \
- xf86drmMode.o
+ xf86drmRandom.o xf86drmSL.o xf86drmMode.o \
+ sun_xf86drm.o sun_devinfo.o
include ../../Makefile.lib
include $(SRC)/common/libdrm/Makefile.drm
@@ -43,8 +43,10 @@ MAPFILES=
SRCDIR = $(LIBDRM_CMN_DIR)
SRCS = $(OBJECTS:%.o=$(SRCDIR)/%.c)
+CPPFLAGS += -I$(LIBDRM_CMN_DIR)
+
# CFLAGS += $(CCVERBOSE)
-LDLIBS += -lm -lc
+LDLIBS += -lm -ldevinfo -lc
all : $(LIBS) $(PCS)
@@ -53,4 +55,8 @@ lint :
include ../Makefile.pc
include ../../Makefile.targ
+objs/%.o pics/%.o: ../common/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
.KEEP_STATE:
diff --git a/usr/src/lib/libdrm/common/sun_devinfo.c b/usr/src/lib/libdrm/common/sun_devinfo.c
new file mode 100644
index 0000000..d7d5669
--- /dev/null
+++ b/usr/src/lib/libdrm/common/sun_devinfo.c
@@ -0,0 +1,291 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * Copyright 2016 Gordon W. Ross
+ */
+
+/*
+ * Helper functions for sun_xf86drm.c to find DRM device nodes
+ * given a pair of device major/minor numbers.
+ *
+ * Some of this code was cribbed from the "prtconf" command.
+ */
+
+/*
+ * Device major numbers on illumos and Solaris are dynamic.
+ *
+ * Device node naming is also different. See:
+ * uts/common/io/drm/drm_stub.c drm_get_minor()
+ * uts/common/io/drm/drm_sysfs.c drm_sysfs_device_add()
+ *
+ * Device "types" (encoded in some of the minor bits)
+ * Typical device setup with intel graphics:
+ *
+ * DRM_MINOR_LEGACY /devices/pci@0,0/display@2:drm0
+ * DRM_MINOR_CONTROL /devices/pci@0,0/display@2:controlD0
+ * DRM_MINOR_RENDER /devices/pci@0,0/display@2:renderD0
+ * DRM_MINOR_VGATEXT /devices/pci@0,0/display@2:gfx0
+ * DRM_MINOR_AGPMASTER /devices/pci@0,0/display@2:agpmaster0
+ *
+ * The "devlinks" system also makes links under /dev
+ * which normally look something like this:
+ *
+ * /dev/fbs/gfx0 -> .../display@2:gfx0
+ * /dev/fb -> .../display@2:gfx0
+ * /dev/fb0 -> fbs/text-0
+ * /dev/fb1 -> fbs/gfx0
+ * /dev/agp/agpmaster0 -> .../display@2:agpmaster0
+ * /dev/dri/card1 -> .../display@2:controlD0
+ *
+ * (i916 driver) /devices/pci@0,0/pci1179,1@0:agptarget
+ * /dev/agp/agptarget0 -> /devices/pci@0,0/pci1179,1@0:agptarget
+ *
+ * (agpgart driver) /devices/agpgart:agpgart
+ * /dev/agpgart -> /devices/agpgart:agpgart
+ */
+
+#include <string.h>
+#include <fcntl.h>
+#include <fnmatch.h>
+#include <libdevinfo.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mkdev.h>
+
+#include "xf86drm.h"
+
+struct search_args {
+ char *s_path;
+ int s_minor;
+};
+
+static int find_dev(di_node_t, void *);
+static int find_minor(di_node_t, di_minor_t, struct search_args *);
+
+static int _sun_drm_major; /* cache */
+
+int _sun_drm_get_major(void)
+{
+ struct stat sbuf;
+ dev_t dev = 0;
+ char *path;
+ int i, ret;
+
+ if (_sun_drm_major != 0)
+ return (_sun_drm_major);
+
+ for (i = 0; i < DRM_MAX_MINOR; i++) {
+ ret = _sun_drm_find_device(i, &path);
+ if (ret != 0)
+ continue;
+ ret = stat(path, &sbuf);
+ free(path);
+ if (ret != 0)
+ continue;
+ if (!S_ISCHR(sbuf.st_mode))
+ continue;
+ dev = major(sbuf.st_rdev);
+ if (dev != 0) {
+ _sun_drm_major = dev;
+ return (dev);
+ }
+ }
+
+ /*
+ * No devices found? No way to return errors here,
+ * so just return an impossible value, and let
+ * later calls like open fail.
+ */
+ return (MAXMAJ32);
+}
+
+int
+_sun_drm_find_device(int min, char **pathp)
+{
+ struct search_args sargs;
+ di_node_t root_node;
+
+ root_node = di_init("/", DINFOCPYALL);
+ if (root_node == DI_NODE_NIL)
+ return (-errno);
+
+ memset(&sargs, 0, sizeof (sargs));
+
+ di_walk_node(root_node, DI_WALK_CLDFIRST, &sargs, find_dev);
+ di_fini(root_node);
+
+ if (sargs.s_path == NULL)
+ return (-ENOENT);
+
+ if (pathp != NULL)
+ *pathp = sargs.s_path;
+ else
+ free(sargs.s_path);
+
+ return (0);
+}
+
+/*
+ * Call back function for di_walk_node, called for every device node.
+ */
+static int
+find_dev(di_node_t node, void *vargs)
+{
+ struct search_args *sargs = vargs;
+ const char *node_name;
+ di_minor_t minor_node;
+
+ node_name = di_node_name(node);
+
+ if (strcmp(node_name, "pseudo") == 0)
+ return (DI_WALK_PRUNECHILD);
+
+ /*
+ * Had: udev_enumerate_add_match_subsystem(e, "drm");
+ * so skip anything outside "drm".
+ * For illumos or Solaris, I think we want to skip
+ * anything that's not named "display".
+ */
+ if (strcmp(node_name, "display") != 0)
+ return (DI_WALK_CONTINUE);
+
+ /*
+ * Walk the minor node paths searching...
+ */
+ minor_node = DI_MINOR_NIL;
+ while ((minor_node = di_minor_next(node, minor_node)) != DI_MINOR_NIL) {
+ if (find_minor(node, minor_node, sargs)) {
+ /* Found it! */
+ return (DI_WALK_TERMINATE);
+ }
+ }
+
+ return (DI_WALK_CONTINUE);
+}
+
+/*
+ * Search function called for each minor node under some device
+ * that was found to be of likely interest above.
+ * Return non-zero if match found.
+ */
+static int
+find_minor(di_node_t node, di_minor_t minor, struct search_args *sargs)
+{
+ char *path;
+ dev_t devt;
+ int ret;
+
+ devt = di_minor_devt(minor);
+
+ /* Does the caller want a specific minor number? */
+ if (sargs->s_minor >= 0 &&
+ sargs->s_minor != minor(devt))
+ return (0);
+
+ /*
+ * get device minor node path
+ * Note: allocates path
+ */
+ if ((path = di_devfs_minor_path(minor)) == NULL)
+ return (0);
+ ret = asprintf(&sargs->s_path, "/devices%s", path);
+ di_devfs_path_free(path);
+
+ if (ret < 0) {
+ free(sargs->s_path);
+ return (0);
+ }
+
+ return (1);
+}
+
+/*
+ * Get PCI data for the give device path.
+ *
+ * Note path given is a full minor under /devices i.e.
+ * /devices/pci@0,0/display@2:drm
+ * and libdevinfo wants just:
+ * /pci@0,0/display@2
+ */
+int
+_sun_drm_get_pci_info(char *path, drmPciDeviceInfo *pcii)
+{
+ char pathbuf[MAXPATHLEN];
+ di_node_t node;
+ char *s;
+ char *propstr = NULL;
+ int *propval = NULL;
+ int ret = -EINVAL;
+
+ /* Skip the /devices prefix, if present. */
+ if (strncmp(path, "/devices/", 9) == 0)
+ path += 8; /* the next slash */
+ strlcpy(pathbuf, path, sizeof (pathbuf));
+
+ /* Strip :drm0 or whatever */
+ if ((s = strrchr(pathbuf, ':')) != NULL)
+ *s = '\0';
+
+ /*
+ * Ask libdevinfo about this device
+ */
+ node = di_init(pathbuf, DINFOCPYALL);
+ if (node == DI_NODE_NIL)
+ return -EINVAL;
+
+ /*
+ * Get the various PCI properties.
+ * Only the first two are required.
+ */
+ memset(pcii, 0, sizeof(*pcii));
+ if (di_prop_lookup_ints(DDI_DEV_T_ANY, node,
+ "vendor-id", &propval) > 0)
+ pcii->vendor_id = (uint16_t)*propval;
+ else
+ goto out;
+
+ if (di_prop_lookup_ints(DDI_DEV_T_ANY, node,
+ "device-id", &propval) > 0)
+ pcii->device_id = (uint16_t)*propval;
+ else
+ goto out;
+
+ if (di_prop_lookup_ints(DDI_DEV_T_ANY, node,
+ "subsystem-vendor-id", &propval) > 0)
+ pcii->subvendor_id = (uint16_t)*propval;
+
+ if (di_prop_lookup_ints(DDI_DEV_T_ANY, node,
+ "subsystem-id", &propval) > 0)
+ pcii->subdevice_id = (uint16_t)*propval;
+
+ if (di_prop_lookup_ints(DDI_DEV_T_ANY, node,
+ "revision-id", &propval) > 0)
+ pcii->revision_id = (uint16_t)*propval;
+
+ ret = 0;
+out:
+ di_fini(node);
+ return (ret);
+}
diff --git a/usr/src/lib/libdrm/common/sun_xf86drm.c b/usr/src/lib/libdrm/common/sun_xf86drm.c
new file mode 100644
index 0000000..5387bce
--- /dev/null
+++ b/usr/src/lib/libdrm/common/sun_xf86drm.c
@@ -0,0 +1,176 @@
+/**
+ * \file xf86drm.c
+ * User-level interface to DRM device
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Kevin E. Martin <martin@valinux.com>
+ */
+
+/*
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * OS-dependent versions of several functions found in:
+ * libdrm/xf86drm.c (mostly where those need "udev")
+ * Here we use libdevinfo.h instead via these
+ * private interfaces in libdrm:
+ * _sun_drm_find_device()
+ * _sun_drm_get_pci_info()
+ *
+ * See sun_devinfo.c
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stddef.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mkdev.h>
+
+#include "xf86drm.h"
+
+/* Device majors are dynamic. */
+#define DRM_MAJOR (_sun_drm_get_major())
+
+char *_sun_drmGetMinorNameForFD(int fd, int type)
+{
+ char *path = NULL;
+ struct stat sbuf;
+ int err, maj, min;
+
+ 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;
+
+ /* Walk devices looking for this minor */
+ err = _sun_drm_find_device(min, &path);
+ if (err != 0)
+ return (NULL);
+
+ return (path);
+}
+
+int _sun_drmParseSubsystemType(int maj, int min)
+{
+ char *path = NULL;
+ char *p;
+ int ret;
+
+ if (maj != DRM_MAJOR)
+ return -EINVAL;
+
+ ret = _sun_drm_find_device(min, &path);
+ if (ret != 0)
+ return (ret);
+
+ p = path;
+ if (strncmp(p, "/devices", 8) == 0)
+ p += 8;
+
+ if (strncmp(p, "/pci@", 5) == 0)
+ ret = DRM_BUS_PCI;
+ else
+ ret = -EINVAL;
+ free(path);
+
+ return (ret);
+}
+
+int _sun_drmParsePciBusInfo(int maj, int min, drmPciBusInfoPtr info)
+{
+ char *path = NULL;
+ int bus, slot, unit;
+ int n, ret;
+
+ if (maj != DRM_MAJOR)
+ return -EINVAL;
+
+ ret = _sun_drm_find_device(min, &path);
+ if (ret != 0)
+ return (ret);
+
+ n = sscanf(path, "/devices/pci@%d,%d/display@%d:",
+ &bus, &slot, &unit);
+ free(path);
+ if (n != 3)
+ return -EINVAL;
+
+ info->domain = 0;
+ info->bus = bus;
+ info->dev = slot;
+ info->func = unit;
+
+ return 0;
+}
+
+/*
+ * Given d_name as some name under /dev,
+ * find the /devices path and then get the
+ * PCI properties for that device.
+ */
+int _sun_drmParsePciDeviceInfo(const char *d_name,
+ drmPciDeviceInfo *pcii)
+{
+ struct stat sbuf;
+ int err, maj, min;
+ char dev_path[256];
+ char *path = NULL;
+
+ if (d_name[0] == '/')
+ strlcpy(dev_path, d_name, sizeof (dev_path));
+ else
+ snprintf(dev_path, sizeof (dev_path),
+ DRM_DIR_NAME "/%s", d_name);
+ if (stat(dev_path, &sbuf))
+ return -errno;
+
+ maj = major(sbuf.st_rdev);
+ min = minor(sbuf.st_rdev);
+ if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode))
+ return -EINVAL;
+
+ /* Get the /devices path */
+ err = _sun_drm_find_device(min, &path);
+ if (err != 0)
+ return err;
+
+ err = _sun_drm_get_pci_info(path, pcii);
+ free(path);
+
+ return err;
+}
+
+/*
+ * XXX: todo - int drmCheckModesettingSupported()
+ */
diff --git a/usr/src/pkg/manifests/system-test-libdrm.mf b/usr/src/pkg/manifests/system-test-libdrm.mf
index 4c3558f..b8df185 100644
--- a/usr/src/pkg/manifests/system-test-libdrm.mf
+++ b/usr/src/pkg/manifests/system-test-libdrm.mf
@@ -30,6 +30,7 @@ file path=opt/drm-tests/$(ARCH64)/exynos_fimg2d_perf
file path=opt/drm-tests/$(ARCH64)/exynos_fimg2d_test
file path=opt/drm-tests/$(ARCH64)/getclient
file path=opt/drm-tests/$(ARCH64)/getstats
+file path=opt/drm-tests/$(ARCH64)/getsundev
file path=opt/drm-tests/$(ARCH64)/getversion
file path=opt/drm-tests/$(ARCH64)/hash
file path=opt/drm-tests/$(ARCH64)/kms-steal-crtc
@@ -55,6 +56,7 @@ file path=opt/drm-tests/exynos_fimg2d_perf
file path=opt/drm-tests/exynos_fimg2d_test
file path=opt/drm-tests/getclient
file path=opt/drm-tests/getstats
+file path=opt/drm-tests/getsundev
file path=opt/drm-tests/getversion
file path=opt/drm-tests/hash
file path=opt/drm-tests/kms-steal-crtc