diff options
Diffstat (limited to 'linux')
-rw-r--r-- | linux/drm.h | 11 | ||||
-rw-r--r-- | linux/drmP.h | 2 | ||||
-rw-r--r-- | linux/drm_drv.h | 1 | ||||
-rw-r--r-- | linux/drm_ioctl.h | 75 |
4 files changed, 88 insertions, 1 deletions
diff --git a/linux/drm.h b/linux/drm.h index e7443e12..62baccaf 100644 --- a/linux/drm.h +++ b/linux/drm.h @@ -584,6 +584,16 @@ typedef struct drm_scatter_gather { unsigned long handle; /**< Used for mapping / unmapping */ } drm_scatter_gather_t; +/** + * DRM_IOCTL_SET_VERSION ioctl argument type. + */ +typedef struct drm_set_version { + int drm_di_major; + int drm_di_minor; + int drm_dd_major; + int drm_dd_minor; +} drm_set_version_t; + #define DRM_IOCTL_BASE 'd' #define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr) @@ -598,6 +608,7 @@ typedef struct drm_scatter_gather { #define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, drm_map_t) #define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, drm_client_t) #define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, drm_stats_t) +#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, drm_set_version_t) #define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm_unique_t) #define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, drm_auth_t) diff --git a/linux/drmP.h b/linux/drmP.h index ae499cae..3d379664 100644 --- a/linux/drmP.h +++ b/linux/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/drm_drv.h b/linux/drm_drv.h index 4ea81e8c..ae299928 100644 --- a/linux/drm_drv.h +++ b/linux/drm_drv.h @@ -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/drm_ioctl.h b/linux/drm_ioctl.h index 8d98000f..ac54cae9 100644 --- a/linux/drm_ioctl.h +++ b/linux/drm_ioctl.h @@ -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; +} |