From: Martin Peres <martin.pe...@labri.fr>

Signed-off-by: Martin Peres <martin.peres at labri.fr>
---
 tests/name_from_fd.c |  19 ++++++----
 xf86drm.c            | 105 ++++++++++++++++++++++++++++++++++++++++-----------
 xf86drm.h            |   7 ++++
 3 files changed, 100 insertions(+), 31 deletions(-)

diff --git a/tests/name_from_fd.c b/tests/name_from_fd.c
index 330c8ff..8e1a197 100644
--- a/tests/name_from_fd.c
+++ b/tests/name_from_fd.c
@@ -41,17 +41,20 @@ int main(int argc, char **argv)
 {
        int fd, ret;
        drm_set_version_t sv, version;
-       const char *name = "/dev/dri/card0";
+       const char *name[2] = { "/dev/dri/card0", "/dev/dri/renderD128" };
        char *v;
+       int i;

-       fd = open("/dev/dri/card0", O_RDWR);
-       if (fd == -1)
-               return 0;
+       for (i = 0; i < 2; i++) {
+               fd = open(name[i], O_RDWR);
+               if (fd > 0) {
+                       v = drmGetDeviceNameFromFd(fd);
+                       close(fd);
+                       assert(v != NULL);
+                       assert(strcmp(name[i], v) == 0);
+               }
+       }

-       v = drmGetDeviceNameFromFd(fd);
-       close(fd);
-
-       assert(strcmp(name, v) == 0);
        drmFree(v);

        return 0;
diff --git a/xf86drm.c b/xf86drm.c
index 2a74c80..eb0549d 100644
--- a/xf86drm.c
+++ b/xf86drm.c
@@ -85,9 +85,6 @@

 #define DRM_MSG_VERBOSITY 3

-#define DRM_NODE_CONTROL 0
-#define DRM_NODE_RENDER 1
-
 static drmServerInfoPtr drm_server_info;

 void drmSetServerInfo(drmServerInfoPtr info)
@@ -286,10 +283,51 @@ static int chown_check_return(const char *path, uid_t 
owner, gid_t group)
 }

 /**
+ * Generate the device name according to its type.
+ *
+ * \param buf buffer that will hold the device path after the call.
+ * \param len length of the buffer.
+ * \param base_dir base directory used to generate the path. If NULL, it
+ *        defaults to DRM_DIR_NAME ("/dev/dri").
+ * \param type the type of device (control, render or render_only).
+ * \param minor number of the device.
+ */
+static void drmDevicePath(char *buf, size_t len, const char *base_dir, int 
type, 
+                         int minor)
+{
+       const char *dev_name = NULL;
+       
+       switch (type)
+       {
+       case DRM_NODE_CONTROL:
+               dev_name = DRM_CONTROL_DEV_NAME;
+               /* we do not increase minor by 64 not to change the current 
+                * behaviour even though I couldn't find who uses this type!
+                */
+               break;
+       case DRM_NODE_RENDER_ONLY:
+               dev_name = DRM_RENDER_ONLY_DEV_NAME;
+               minor += 128;
+               break;
+       default:
+               drmMsg("drmDevicePath: unknown type %d, default to render.\n", 
type);
+       case DRM_NODE_RENDER:
+               dev_name = DRM_DEV_NAME;
+               break;
+       }
+       
+       if (!base_dir)
+               base_dir = DRM_DIR_NAME;
+
+       snprintf(buf, len, dev_name, base_dir, minor);
+}
+
+/**
  * Open the DRM device, creating it if necessary.
  *
  * \param dev major and minor numbers of the device.
  * \param minor minor number of the device.
+ * \param type the type of device we want to open (control, render or 
render_only).
  * 
  * \return a file descriptor on success, or a negative value on error.
  *
@@ -308,7 +346,7 @@ static int drmOpenDevice(long dev, int minor, int type)
     uid_t           user    = DRM_DEV_UID;
     gid_t           group   = DRM_DEV_GID, serv_group;

-    sprintf(buf, type ? DRM_DEV_NAME : DRM_CONTROL_DEV_NAME, DRM_DIR_NAME, 
minor);
+    drmDevicePath(buf, sizeof(buf), NULL, type, minor);
     drmMsg("drmOpenDevice: node name is %s\n", buf);

     if (drm_server_info) {
@@ -417,7 +455,7 @@ static int drmOpenMinor(int minor, int create, int type)
     if (create)
        return drmOpenDevice(makedev(DRM_MAJOR, minor), minor, type);

-    sprintf(buf, type ? DRM_DEV_NAME : DRM_CONTROL_DEV_NAME, DRM_DIR_NAME, 
minor);
+    drmDevicePath(buf, sizeof(buf), NULL, type, minor);
     if ((fd = open(buf, O_RDWR, 0)) >= 0)
        return fd;
     return -errno;
@@ -472,7 +510,7 @@ int drmAvailable(void)
  *
  * \sa drmOpenMinor() and drmGetBusid().
  */
-static int drmOpenByBusid(const char *busid)
+static int drmOpenByBusid(const char *busid, int type)
 {
     int        i, pci_domain_ok = 1;
     int        fd;
@@ -481,7 +519,7 @@ static int drmOpenByBusid(const char *busid)

     drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid);
     for (i = 0; i < DRM_MAX_MINOR; i++) {
-       fd = drmOpenMinor(i, 1, DRM_NODE_RENDER);
+       fd = drmOpenMinor(i, 1, type);
        drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd);
        if (fd >= 0) {
            /* We need to try for 1.4 first for proper PCI domain support
@@ -531,7 +569,7 @@ static int drmOpenByBusid(const char *busid)
  * 
  * \sa drmOpenMinor(), drmGetVersion() and drmGetBusid().
  */
-static int drmOpenByName(const char *name)
+static int drmOpenByName(const char *name, int type)
 {
     int           i;
     int           fd;
@@ -556,7 +594,7 @@ static int drmOpenByName(const char *name)
      * already in use.  If it's in use it will have a busid assigned already.
      */
     for (i = 0; i < DRM_MAX_MINOR; i++) {
-       if ((fd = drmOpenMinor(i, 1, DRM_NODE_RENDER)) >= 0) {
+       if ((fd = drmOpenMinor(i, 1, type)) >= 0) {
            if ((version = drmGetVersion(fd))) {
                if (!strcmp(version->name, name)) {
                    drmFreeVersion(version);
@@ -598,9 +636,9 @@ static int drmOpenByName(const char *name)
                        for (devstring = ++pt; *pt && *pt != ' '; ++pt)
                            ;
                        if (*pt) { /* Found busid */
-                           return drmOpenByBusid(++pt);
+                           return drmOpenByBusid(++pt, type);
                        } else { /* No busid */
-                           return drmOpenDevice(strtol(devstring, NULL, 0),i, 
DRM_NODE_RENDER);
+                           return drmOpenDevice(strtol(devstring, NULL, 0),i, 
type);
                        }
                    }
                }
@@ -621,6 +659,7 @@ static int drmOpenByName(const char *name)
  *
  * \param name driver name. Not referenced if bus ID is supplied.
  * \param busid bus ID. Zero if not known.
+ * \param type type of node wanted (control, render or render_only).
  * 
  * \return a file descriptor on success, or a negative value on error.
  * 
@@ -628,7 +667,7 @@ static int drmOpenByName(const char *name)
  * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName()
  * otherwise.
  */
-int drmOpen(const char *name, const char *busid)
+int drmOpenType(const char *name, const char *busid, int type)
 {
     if (!drmAvailable() && name != NULL && drm_server_info) {
        /* try to load the kernel */
@@ -639,17 +678,37 @@ int drmOpen(const char *name, const char *busid)
     }

     if (busid) {
-       int fd = drmOpenByBusid(busid);
+       int fd = drmOpenByBusid(busid, type);
        if (fd >= 0)
            return fd;
     }

     if (name)
-       return drmOpenByName(name);
+       return drmOpenByName(name, type);

     return -1;
 }

+/**
+ * Open the DRM device.
+ *
+ * Looks up the specified name and bus ID, and opens the device found.  The
+ * entry in /dev/dri is created if necessary and if called by root.
+ *
+ * \param name driver name. Not referenced if bus ID is supplied.
+ * \param busid bus ID. Zero if not known.
+ * 
+ * \return a file descriptor on success, or a negative value on error.
+ * 
+ * \internal
+ * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName()
+ * otherwise.
+ */
+int drmOpen(const char *name, const char *busid)
+{
+   return drmOpenType(name, busid, DRM_NODE_RENDER);
+}
+
 int drmOpenControl(int minor)
 {
     return drmOpenMinor(minor, 0, DRM_NODE_CONTROL);
@@ -2522,7 +2581,7 @@ char *drmGetDeviceNameFromFd(int fd)
        char name[128];
        struct stat sbuf;
        dev_t d;
-       int i;
+       int type, 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
@@ -2532,15 +2591,15 @@ char *drmGetDeviceNameFromFd(int fd)
        fstat(fd, &sbuf);
        d = sbuf.st_rdev;

-       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)
-                       break;
+       for (type = DRM_NODE_RENDER; type <= DRM_NODE_RENDER_ONLY; type++) {
+               for (i = 0; i < DRM_MAX_MINOR; i++) {
+                       drmDevicePath(name, sizeof(name), NULL, type, i);
+                       if (stat(name, &sbuf) == 0 && sbuf.st_rdev == d)
+                               return strdup(name);
+               }
        }
-       if (i == DRM_MAX_MINOR)
-               return NULL;
-
-       return strdup(name);
+       
+       return NULL;
 }

 int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd)
diff --git a/xf86drm.h b/xf86drm.h
index 5ecb284..d727ce1 100644
--- a/xf86drm.h
+++ b/xf86drm.h
@@ -47,6 +47,10 @@ extern "C" {
 #define DRM_MAX_MINOR   16
 #endif

+#define DRM_NODE_CONTROL 0
+#define DRM_NODE_RENDER 1
+#define DRM_NODE_RENDER_ONLY 2
+
 #if defined(__linux__)

 #define DRM_IOCTL_NR(n)                _IOC_NR(n)
@@ -78,6 +82,7 @@ extern "C" {

 #define DRM_DIR_NAME  "/dev/dri"
 #define DRM_DEV_NAME  "%s/card%d"
+#define DRM_RENDER_ONLY_DEV_NAME  "%s/renderD%d"
 #define DRM_CONTROL_DEV_NAME  "%s/controlD%d"
 #define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */

@@ -544,6 +549,7 @@ do {        register unsigned int __old __asm("o0");        
        \

 /* General user-level programmer's API: unprivileged */
 extern int           drmAvailable(void);
+extern int           drmOpenType(const char *name, const char *busid, int 
type);
 extern int           drmOpen(const char *name, const char *busid);
 extern int drmOpenControl(int minor);
 extern int           drmClose(int fd);
@@ -694,6 +700,7 @@ extern int  drmSLLookupNeighbors(void *l, unsigned long key,
                                 unsigned long *prev_key, void **prev_value,
                                 unsigned long *next_key, void **next_value);

+extern int drmOpenTypeOnce(void *unused, const char *BusID, int *newlyopened, 
int type);
 extern int drmOpenOnce(void *unused, const char *BusID, int *newlyopened);
 extern void drmCloseOnce(int fd);
 extern void drmMsg(const char *format, ...);
-- 
1.8.0.1

Reply via email to