aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bsd-core/drmP.h5
-rw-r--r--bsd-core/drm_drv.c1
-rw-r--r--bsd-core/drm_ioctl.c70
-rw-r--r--bsd/drm.h8
-rw-r--r--bsd/drmP.h5
-rw-r--r--bsd/drm_drv.h1
-rw-r--r--bsd/drm_ioctl.h70
-rw-r--r--libdrm/xf86drm.c136
-rw-r--r--linux-core/drmP.h2
-rw-r--r--linux-core/drm_drv.c1
-rw-r--r--linux-core/drm_ioctl.c75
-rw-r--r--linux/drm.h11
-rw-r--r--linux/drmP.h2
-rw-r--r--linux/drm_drv.h1
-rw-r--r--linux/drm_ioctl.h75
-rw-r--r--shared-core/drm.h11
-rw-r--r--shared/drm.h11
17 files changed, 468 insertions, 17 deletions
diff --git a/bsd-core/drmP.h b/bsd-core/drmP.h
index b2e045e6..eec3faed 100644
--- a/bsd-core/drmP.h
+++ b/bsd-core/drmP.h
@@ -390,9 +390,6 @@ struct drm_device {
extern int DRM(flags);
- /* Driver support (drm_drv.h) */
-extern int DRM(version)( DRM_IOCTL_ARGS );
-
/* Memory management support (drm_memory.h) */
extern void DRM(mem_init)(void);
extern void DRM(mem_uninit)(void);
@@ -491,6 +488,8 @@ extern int DRM(ati_pcigart_cleanup)(drm_device_t *dev,
/* Locking IOCTL support (drm_drv.h) */
extern int DRM(lock)(DRM_IOCTL_ARGS);
extern int DRM(unlock)(DRM_IOCTL_ARGS);
+extern int DRM(version)( DRM_IOCTL_ARGS );
+extern int DRM(setversion)( DRM_IOCTL_ARGS );
/* Misc. IOCTL support (drm_ioctl.h) */
extern int DRM(irq_busid)(DRM_IOCTL_ARGS);
diff --git a/bsd-core/drm_drv.c b/bsd-core/drm_drv.c
index 582a4112..3f494694 100644
--- a/bsd-core/drm_drv.c
+++ b/bsd-core/drm_drv.c
@@ -135,6 +135,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/bsd-core/drm_ioctl.c b/bsd-core/drm_ioctl.c
index a195d0c4..50cf937d 100644
--- a/bsd-core/drm_ioctl.c
+++ b/bsd-core/drm_ioctl.c
@@ -79,6 +79,12 @@ int DRM(irq_busid)( DRM_IOCTL_ARGS )
#endif
}
+/*
+ * Beginning in revision 1.1 of the DRM interface, getunique will return
+ * a unique in the form pci:oooo:bb:dd.f (o=domain, b=bus, d=device, f=function)
+ * before setunique has been called. The format for the bus-specific part of
+ * the unique is not defined for any other bus.
+ */
int DRM(getunique)( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
@@ -97,6 +103,9 @@ int DRM(getunique)( DRM_IOCTL_ARGS )
return 0;
}
+/* Deprecated in DRM version 1.1, and will return EBUSY when setversion has
+ * requested version 1.1 or greater.
+ */
int DRM(setunique)( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
@@ -125,6 +134,26 @@ int DRM(setunique)( DRM_IOCTL_ARGS )
}
+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;
+
+ /* XXX Fix domain number (alpha hoses) */
+ snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%1x",
+ 0, pci_get_bus(dev->device), pci_get_slot(dev->device),
+ pci_get_function(dev->device));
+
+ return 0;
+}
+
int DRM(getmap)( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
@@ -231,6 +260,47 @@ int DRM(getstats)( DRM_IOCTL_ARGS )
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;
+}
+
+
int DRM(noop)(DRM_IOCTL_ARGS)
{
DRM_DEBUG("\n");
diff --git a/bsd/drm.h b/bsd/drm.h
index 73c83869..8c67be4d 100644
--- a/bsd/drm.h
+++ b/bsd/drm.h
@@ -405,6 +405,13 @@ typedef struct drm_scatter_gather {
unsigned long handle; /* Used for mapping / unmapping */
} drm_scatter_gather_t;
+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)
#define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type)
@@ -418,6 +425,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/bsd/drmP.h b/bsd/drmP.h
index b2e045e6..eec3faed 100644
--- a/bsd/drmP.h
+++ b/bsd/drmP.h
@@ -390,9 +390,6 @@ struct drm_device {
extern int DRM(flags);
- /* Driver support (drm_drv.h) */
-extern int DRM(version)( DRM_IOCTL_ARGS );
-
/* Memory management support (drm_memory.h) */
extern void DRM(mem_init)(void);
extern void DRM(mem_uninit)(void);
@@ -491,6 +488,8 @@ extern int DRM(ati_pcigart_cleanup)(drm_device_t *dev,
/* Locking IOCTL support (drm_drv.h) */
extern int DRM(lock)(DRM_IOCTL_ARGS);
extern int DRM(unlock)(DRM_IOCTL_ARGS);
+extern int DRM(version)( DRM_IOCTL_ARGS );
+extern int DRM(setversion)( DRM_IOCTL_ARGS );
/* Misc. IOCTL support (drm_ioctl.h) */
extern int DRM(irq_busid)(DRM_IOCTL_ARGS);
diff --git a/bsd/drm_drv.h b/bsd/drm_drv.h
index 582a4112..3f494694 100644
--- a/bsd/drm_drv.h
+++ b/bsd/drm_drv.h
@@ -135,6 +135,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/bsd/drm_ioctl.h b/bsd/drm_ioctl.h
index a195d0c4..50cf937d 100644
--- a/bsd/drm_ioctl.h
+++ b/bsd/drm_ioctl.h
@@ -79,6 +79,12 @@ int DRM(irq_busid)( DRM_IOCTL_ARGS )
#endif
}
+/*
+ * Beginning in revision 1.1 of the DRM interface, getunique will return
+ * a unique in the form pci:oooo:bb:dd.f (o=domain, b=bus, d=device, f=function)
+ * before setunique has been called. The format for the bus-specific part of
+ * the unique is not defined for any other bus.
+ */
int DRM(getunique)( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
@@ -97,6 +103,9 @@ int DRM(getunique)( DRM_IOCTL_ARGS )
return 0;
}
+/* Deprecated in DRM version 1.1, and will return EBUSY when setversion has
+ * requested version 1.1 or greater.
+ */
int DRM(setunique)( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
@@ -125,6 +134,26 @@ int DRM(setunique)( DRM_IOCTL_ARGS )
}
+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;
+
+ /* XXX Fix domain number (alpha hoses) */
+ snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%1x",
+ 0, pci_get_bus(dev->device), pci_get_slot(dev->device),
+ pci_get_function(dev->device));
+
+ return 0;
+}
+
int DRM(getmap)( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
@@ -231,6 +260,47 @@ int DRM(getstats)( DRM_IOCTL_ARGS )
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;
+}
+
+
int DRM(noop)(DRM_IOCTL_ARGS)
{
DRM_DEBUG("\n");
diff --git a/libdrm/xf86drm.c b/libdrm/xf86drm.c
index 773c6d24..23750b9c 100644
--- a/libdrm/xf86drm.c
+++ b/libdrm/xf86drm.c
@@ -211,6 +211,55 @@ static drmHashEntry *drmGetEntry(int fd)
}
/**
+ * Compare two busid strings
+ *
+ * \param first
+ * \param second
+ *
+ * \return 1 if matched.
+ *
+ * \internal
+ * This function compares two bus ID strings. It understands the older
+ * PCI:b:d:f format and the newer pci:oooo:bb:dd.f format. In the format, o is
+ * domain, b is bus, d is device, f is function.
+ */
+static int drmMatchBusID(const char *id1, const char *id2)
+{
+ /* First, check if the IDs are exactly the same */
+ if (strcasecmp(id1, id2) == 0)
+ return 1;
+
+ /* Try to match old/new-style PCI bus IDs. */
+ if (strncasecmp(id1, "pci", 3) == 0) {
+ int o1, b1, d1, f1;
+ int o2, b2, d2, f2;
+ int ret;
+
+ ret = sscanf(id1, "pci:%04x:%02x:%02x.%d", &o1, &b1, &d1, &f1);
+ if (ret != 4) {
+ o1 = 0;
+ ret = sscanf(id1, "PCI:%d:%d:%d", &b1, &d1, &f1);
+ if (ret != 3)
+ return 0;
+ }
+
+ ret = sscanf(id2, "pci:%04x:%02x:%02x.%d", &o2, &b2, &d2, &f2);
+ if (ret != 4) {
+ o2 = 0;
+ ret = sscanf(id2, "PCI:%d:%d:%d", &b2, &d2, &f2);
+ if (ret != 3)
+ return 0;
+ }
+
+ if ((o1 != o2) || (b1 != b2) || (d1 != d2) || (f1 != f2))
+ return 0;
+ else
+ return 1;
+ }
+ return 0;
+}
+
+/**
* Open the DRM device, creating it if necessary.
*
* \param dev major and minor numbers of the device.
@@ -235,7 +284,8 @@ static int drmOpenDevice(long dev, int minor)
gid_t group = DRM_DEV_GID;
#endif
- drmMsg("drmOpenDevice: minor is %d\n", minor);
+ sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
+ drmMsg("drmOpenDevice: node name is %s\n", buf);
#if defined(XFree86Server)
devmode = xf86ConfigDRI.mode ? xf86ConfigDRI.mode : DRM_DEV_MODE;
@@ -250,8 +300,7 @@ static int drmOpenDevice(long dev, int minor)
chmod(DRM_DIR_NAME, DRM_DEV_DIRMODE);
}
- sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
- drmMsg("drmOpenDevice: node name is %s\n", buf);
+ /* Check if the device node exists and create it if necessary. */
if (stat(buf, &st)) {
if (!isroot) return DRM_ERR_NOT_ROOT;
remove(buf);
@@ -267,10 +316,17 @@ static int drmOpenDevice(long dev, int minor)
fd, fd < 0 ? strerror(errno) : "OK");
if (fd >= 0) return fd;
+ /* Check if the device node is not what we expect it to be, and recreate it
+ * and try again if so.
+ */
if (st.st_rdev != dev) {
if (!isroot) return DRM_ERR_NOT_ROOT;
remove(buf);
mknod(buf, S_IFCHR | devmode, dev);
+#if defined(XFree86Server)
+ chown(buf, user, group);
+ chmod(buf, devmode);
+#endif
}
fd = open(buf, O_RDWR, 0);
drmMsg("drmOpenDevice: open result is %d, (%s)\n",
@@ -360,15 +416,20 @@ static int drmOpenByBusid(const char *busid)
int i;
int fd;
const char *buf;
-
- drmMsg("drmOpenByBusid: busid is %s\n", busid);
+ drmSetVersion sv;
+
+ drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid);
for (i = 0; i < DRM_MAX_MINOR; i++) {
fd = drmOpenMinor(i, 1);
drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd);
if (fd >= 0) {
+ sv.drm_di_major = 1;
+ sv.drm_di_minor = 1;
+ sv.drm_dd_major = -1; /* Don't care */
+ drmSetInterfaceVersion(fd, &sv);
buf = drmGetBusid(fd);
drmMsg("drmOpenByBusid: drmGetBusid reports %s\n", buf);
- if (buf && !strcmp(buf, busid)) {
+ if (buf && drmMatchBusID(buf, busid)) {
drmFreeBusid(buf);
return fd;
}
@@ -494,9 +555,27 @@ static int drmOpenByName(const char *name)
*/
int drmOpen(const char *name, const char *busid)
{
+#ifdef XFree86Server
+ if (!drmAvailable() && name != NULL) {
+ /* try to load the kernel */
+ if (!xf86LoadKernelModule(name)) {
+ ErrorF("[drm] failed to load kernel module \"%s\"\n",
+ name);
+ return -1;
+ }
+ }
+#endif
+
+ if (busid) {
+ int fd;
- if (busid) return drmOpenByBusid(busid);
- return drmOpenByName(name);
+ fd = drmOpenByBusid(busid);
+ if (fd >= 0)
+ return fd;
+ }
+ if (name)
+ return drmOpenByName(name);
+ return -1;
}
@@ -647,9 +726,11 @@ drmVersionPtr drmGetLibVersion(int fd)
* entry point and many drm<Device> extensions
* revision 1.1.x = added drmCommand entry points for device extensions
* added drmGetLibVersion to identify libdrm.a version
+ * revision 1.2.x = added drmSetInterfaceVersion
+ * modified drmOpen to handle both busid and name
*/
version->version_major = 1;
- version->version_minor = 1;
+ version->version_minor = 2;
version->version_patchlevel = 0;
return (drmVersionPtr)version;
@@ -693,6 +774,7 @@ char *drmGetBusid(int fd)
u.unique = drmMalloc(u.unique_len + 1);
if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL;
u.unique[u.unique_len] = '\0';
+
return u.unique;
}
@@ -2030,6 +2112,42 @@ int drmGetStats(int fd, drmStatsT *stats)
}
/**
+ * Issue a set-version ioctl.
+ *
+ * \param fd file descriptor.
+ * \param drmCommandIndex command index
+ * \param data source pointer of the data to be read and written.
+ * \param size size of the data to be read and written.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * It issues a read-write ioctl given by
+ * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
+ */
+int drmSetInterfaceVersion(int fd, drmSetVersion *version )
+{
+ int retcode = 0;
+ drm_set_version_t sv;
+
+ sv.drm_di_major = version->drm_di_major;
+ sv.drm_di_minor = version->drm_di_minor;
+ sv.drm_dd_major = version->drm_dd_major;
+ sv.drm_dd_minor = version->drm_dd_minor;
+
+ if (ioctl(fd, DRM_IOCTL_SET_VERSION, &sv)) {
+ retcode = -errno;
+ }
+
+ version->drm_di_major = sv.drm_di_major;
+ version->drm_di_minor = sv.drm_di_minor;
+ version->drm_dd_major = sv.drm_dd_major;
+ version->drm_dd_minor = sv.drm_dd_minor;
+
+ return retcode;
+}
+
+/**
* Send a device-specific command.
*
* \param fd file descriptor.
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;
+}
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;
+}
diff --git a/shared-core/drm.h b/shared-core/drm.h
index e7443e12..62baccaf 100644
--- a/shared-core/drm.h
+++ b/shared-core/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/shared/drm.h b/shared/drm.h
index e7443e12..62baccaf 100644
--- a/shared/drm.h
+++ b/shared/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)