diff mbox

[1/5] drm: allow opening the drm device by type (control, render or render_only)

Message ID 1355709775-15674-1-git-send-email-martin.peres@free.fr (mailing list archive)
State New, archived
Headers show

Commit Message

Martin Peres Dec. 17, 2012, 2:02 a.m. UTC
From: Martin Peres <martin.peres@labri.fr>

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

Patch

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, ...);