summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Peres <martin.peres@labri.fr>2012-12-15 18:49:06 +0100
committerMartin Peres <martin.peres@labri.fr>2012-12-16 00:47:07 +0100
commit4a86cbbed0c6d74a8b68ec72b8de8e48905d4015 (patch)
treee987da5e79b471714df1a7ee847996f955085a79
parent0980633afd9c7eecc0c75ef3bea4d3c6b7aa1898 (diff)
drm: allow opening the drm device by type (control, render or render_only)
Signed-off-by: Martin Peres <martin.peres@labri.fr>
-rw-r--r--tests/name_from_fd.c19
-rw-r--r--xf86drm.c105
-rw-r--r--xf86drm.h7
3 files changed, 100 insertions, 31 deletions
diff --git a/tests/name_from_fd.c b/tests/name_from_fd.c
index 330c8ff0..8e1a1978 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 2a74c807..eb0549d6 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 5ecb2846..d727ce1b 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, ...);