summaryrefslogtreecommitdiff
path: root/linux-core
diff options
context:
space:
mode:
Diffstat (limited to 'linux-core')
-rw-r--r--linux-core/drmP.h2
-rw-r--r--linux-core/drm_drv.c1
-rw-r--r--linux-core/drm_ioctl.c75
3 files changed, 77 insertions, 1 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index ae499cae..3d379664 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -853,6 +853,8 @@ extern int DRM(getclient)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int DRM(getstats)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
+extern int DRM(setversion)(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
/* Context IOCTL support (drm_context.h) */
extern int DRM(resctx)( struct inode *inode, struct file *filp,
diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c
index 4ea81e8c..ae299928 100644
--- a/linux-core/drm_drv.c
+++ b/linux-core/drm_drv.c
@@ -174,6 +174,7 @@ static drm_ioctl_desc_t DRM(ioctls)[] = {
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { DRM(getmap), 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { DRM(getclient), 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = { DRM(getstats), 0, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = { DRM(setversion), 0, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { DRM(setunique), 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { DRM(noop), 1, 1 },
diff --git a/linux-core/drm_ioctl.c b/linux-core/drm_ioctl.c
index 8d98000f..ac54cae9 100644
--- a/linux-core/drm_ioctl.c
+++ b/linux-core/drm_ioctl.c
@@ -36,6 +36,7 @@
#define __NO_VERSION__
#include "drmP.h"
+#include "linux/pci.h"
/**
* Get interrupt from bus id.
@@ -140,7 +141,9 @@ int DRM(getunique)(struct inode *inode, struct file *filp,
* \return zero on success or a negative number on failure.
*
* Copies the bus id from userspace into drm_device::unique, and searches for
- * the respective PCI device, updating drm_device::pdev.
+ * the respective PCI device, updating drm_device::pdev. Deprecated in
+ * interface version 1.1 and will return EBUSY when setversion has requested
+ * version 1.1 or greater.
*/
int DRM(setunique)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
@@ -218,6 +221,36 @@ int DRM(setunique)(struct inode *inode, struct file *filp,
return 0;
}
+static int
+DRM(set_busid)(drm_device_t *dev)
+{
+ if (dev->unique != NULL)
+ return EBUSY;
+
+ dev->unique_len = 20;
+ dev->unique = DRM(alloc)(dev->unique_len + 1, DRM_MEM_DRIVER);
+ if (dev->unique == NULL)
+ return ENOMEM;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74)
+ snprintf(dev->unique, dev->unique_len, "pci:%s", pci_name(dev->pdev));
+#else
+ {
+ int domain = 0;
+#ifdef __alpha__
+ struct pci_controller *hose = pci_dev->sysdata;
+
+ domain = hose->bus->number;
+#endif
+ snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d",
+ domain, dev->pdev->bus->number,
+ PCI_SLOT(dev->pdev->devfn), PCI_FUNC(dev->pdev->devfn));
+ }
+#endif
+
+ return 0;
+}
+
/**
* Get a mapping information.
@@ -364,3 +397,43 @@ int DRM(getstats)( struct inode *inode, struct file *filp,
return -EFAULT;
return 0;
}
+
+int DRM(setversion)(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_set_version_t sv;
+ drm_set_version_t retv;
+
+ DRM_COPY_FROM_USER_IOCTL(sv, (drm_set_version_t *)data, sizeof(sv));
+
+ retv.drm_di_major = 1;
+ retv.drm_di_minor = 1;
+ retv.drm_dd_major = DRIVER_MAJOR;
+ retv.drm_dd_minor = DRIVER_MINOR;
+
+ DRM_COPY_TO_USER_IOCTL((drm_set_version_t *)data, retv, sizeof(sv));
+
+ if (sv.drm_di_major != -1) {
+ if (sv.drm_di_major != 1 || sv.drm_di_minor < 0)
+ return EINVAL;
+ if (sv.drm_di_minor > 1)
+ return EINVAL;
+ if (sv.drm_di_minor >= 1) {
+ /*
+ * Version 1.1 includes tying of DRM to specific device
+ */
+ DRM(set_busid)(dev);
+ }
+ }
+
+ if (sv.drm_dd_major != -1) {
+ if (sv.drm_dd_major != DRIVER_MAJOR || sv.drm_dd_minor < 0)
+ return EINVAL;
+ if (sv.drm_dd_minor > DRIVER_MINOR)
+ return EINVAL;
+#ifdef DRIVER_SETVERSION
+ DRIVER_SETVERSION(dev, sv);
+#endif
+ }
+ return 0;
+}