Commit 7962e010 authored by Dave Airlie's avatar Dave Airlie

From Eric Anholt:

 Introduce a new ioctl, DRM_IOCTL_SET_VERSION. This ioctl allows the server
or client to notify the DRM that it expects a certain version of the device
dependent or device independent interface. If the major doesn't match or minor
is too large, EINVAL is returned. A major of -1 means that the requestor
doesn't care about that portion of the interface. The ioctl returns the actual
versions in the same struct. 
parent d31fc344
......@@ -580,6 +580,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)
......@@ -594,6 +604,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)
......
......@@ -819,6 +819,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,
......
......@@ -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 },
......
......@@ -35,6 +35,7 @@
#include "drmP.h"
#include "linux/pci.h"
/**
* Get interrupt from bus id.
......@@ -139,7 +140,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)
......@@ -217,6 +220,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.
......@@ -363,3 +396,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;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment