diff options
-rw-r--r-- | usr/src/cmd/drm-tests/misc2/Makefile.com | 6 | ||||
-rw-r--r-- | usr/src/cmd/drm-tests/misc2/common/drmtest_sun.c | 100 | ||||
-rw-r--r-- | usr/src/cmd/drm-tests/misc2/common/getsundev.c | 131 | ||||
-rw-r--r-- | usr/src/common/libdrm/patches/xf86drm-c.patch | 170 | ||||
-rw-r--r-- | usr/src/common/libdrm/patches/xf86drm-h.patch | 18 | ||||
-rw-r--r-- | usr/src/lib/libdrm/Makefile.com | 12 | ||||
-rw-r--r-- | usr/src/lib/libdrm/common/sun_devinfo.c | 291 | ||||
-rw-r--r-- | usr/src/lib/libdrm/common/sun_xf86drm.c | 176 | ||||
-rw-r--r-- | usr/src/pkg/manifests/system-test-libdrm.mf | 2 |
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 |