patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / drivers / char / drm / drm_ioctl.h
index a78ee56..cbf2dbf 100644 (file)
 
 #include "drmP.h"
 
-
-/**
- * Get interrupt from bus id.
- * 
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_irq_busid structure.
- * \return zero on success or a negative number on failure.
- * 
- * Finds the PCI device with the specified bus id and gets its IRQ number.
- */
-int DRM(irq_busid)(struct inode *inode, struct file *filp,
-                  unsigned int cmd, unsigned long arg)
-{
-       drm_irq_busid_t p;
-       struct pci_dev  *dev;
-
-       if (copy_from_user(&p, (drm_irq_busid_t *)arg, sizeof(p)))
-               return -EFAULT;
-#ifdef __alpha__
-       {
-               int domain = p.busnum >> 8;
-               p.busnum &= 0xff;
-
-               /*
-                * Find the hose the device is on (the domain number is the
-                * hose index) and offset the bus by the root bus of that
-                * hose.
-                */
-                for(dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,NULL);
-                    dev;
-                    dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,dev)) {
-                       struct pci_controller *hose = dev->sysdata;
-                       
-                       if (hose->index == domain) {
-                               p.busnum += hose->bus->number;
-                               break;
-                       }
-               }
-       }
-#endif
-       dev = pci_find_slot(p.busnum, PCI_DEVFN(p.devnum, p.funcnum));
-       if (!dev) {
-               DRM_ERROR("pci_find_slot failed for %d:%d:%d\n",
-                         p.busnum, p.devnum, p.funcnum);
-               p.irq = 0;
-               goto out;
-       }                       
-       if (pci_enable_device(dev) != 0) {
-               DRM_ERROR("pci_enable_device failed for %d:%d:%d\n",
-                         p.busnum, p.devnum, p.funcnum);
-               p.irq = 0;
-               goto out;
-       }               
-       p.irq = dev->irq;
- out:
-       DRM_DEBUG("%d:%d:%d => IRQ %d\n",
-                 p.busnum, p.devnum, p.funcnum, p.irq);
-       if (copy_to_user((drm_irq_busid_t *)arg, &p, sizeof(p)))
-               return -EFAULT;
-       return 0;
-}
+#include "linux/pci.h"
 
 /**
  * Get the bus id.
@@ -138,8 +76,10 @@ int DRM(getunique)(struct inode *inode, struct file *filp,
  * \param arg user argument, pointing to a drm_unique structure.
  * \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.
+ * Copies the bus id from userspace into drm_device::unique, and verifies that
+ * it matches the device this DRM is attached to (EINVAL otherwise).  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)
@@ -147,6 +87,7 @@ int DRM(setunique)(struct inode *inode, struct file *filp,
        drm_file_t       *priv   = filp->private_data;
        drm_device_t     *dev    = priv->dev;
        drm_unique_t     u;
+       int              domain, bus, slot, func, ret;
 
        if (dev->unique_len || dev->unique) return -EBUSY;
 
@@ -164,55 +105,49 @@ int DRM(setunique)(struct inode *inode, struct file *filp,
 
        dev->devname = DRM(alloc)(strlen(dev->name) + strlen(dev->unique) + 2,
                                  DRM_MEM_DRIVER);
-       if(!dev->devname) {
-               DRM(free)(dev->devname, sizeof(*dev->devname), DRM_MEM_DRIVER);
+       if (!dev->devname)
                return -ENOMEM;
-       }
+
        sprintf(dev->devname, "%s@%s", dev->name, dev->unique);
 
-       do {
-               struct pci_dev *pci_dev;
-                int domain, b, d, f;
-                char *p;
-                for(p = dev->unique; p && *p && *p != ':'; p++);
-                if (!p || !*p) break;
-                b = (int)simple_strtoul(p+1, &p, 10);
-                if (*p != ':') break;
-                d = (int)simple_strtoul(p+1, &p, 10);
-                if (*p != ':') break;
-                f = (int)simple_strtoul(p+1, &p, 10);
-                if (*p) break;
-               domain = b >> 8;
-               b &= 0xff;
-
-#ifdef __alpha__
-               /*
-                * Find the hose the device is on (the domain number is the
-                * hose index) and offset the bus by the root bus of that
-                * hose.
-                */
-                for(pci_dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,NULL);
-                    pci_dev;
-                    pci_dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,pci_dev)) {
-                       struct pci_controller *hose = pci_dev->sysdata;
-                       
-                       if (hose->index == domain) {
-                               b += hose->bus->number;
-                               break;
-                       }
-               }
-#endif
+       /* Return error if the busid submitted doesn't match the device's actual
+        * busid.
+        */
+       ret = sscanf(dev->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
+       if (ret != 3)
+               return DRM_ERR(EINVAL);
+       domain = bus >> 8;
+       bus &= 0xff;
+       
+       if ((domain != dev->pci_domain) ||
+           (bus != dev->pci_bus) ||
+           (slot != dev->pci_slot) ||
+           (func != dev->pci_func))
+               return -EINVAL;
 
-                pci_dev = pci_find_slot(b, PCI_DEVFN(d,f));
-                if (pci_dev) {
-                       dev->pdev = pci_dev;
-#ifdef __alpha__
-                       dev->hose = pci_dev->sysdata;
-#endif
-               }
-        } while(0);
+       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;
+
+       snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d",
+               dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
+
+       dev->devname = DRM(alloc)(strlen(dev->name) + dev->unique_len + 2,
+                               DRM_MEM_DRIVER);
+       if (dev->devname == NULL)
+               return ENOMEM;
+
+       sprintf(dev->devname, "%s@%s", dev->name, dev->unique);
 
        return 0;
 }
@@ -363,3 +298,47 @@ int DRM(getstats)( struct inode *inode, struct file *filp,
                return -EFAULT;
        return 0;
 }
+
+#define DRM_IF_MAJOR   1
+#define DRM_IF_MINOR   2
+
+int DRM(setversion)(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       drm_set_version_t sv;
+       drm_set_version_t retv;
+       int if_version;
+
+       DRM_COPY_FROM_USER_IOCTL(sv, (drm_set_version_t *)data, sizeof(sv));
+
+       retv.drm_di_major = DRM_IF_MAJOR;
+       retv.drm_di_minor = DRM_IF_MINOR;
+       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 != DRM_IF_MAJOR ||
+                   sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR)
+                       return EINVAL;
+               if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_dd_minor);
+               dev->if_version = DRM_MAX(if_version, dev->if_version);
+               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 || sv.drm_dd_minor > DRIVER_MINOR)
+                       return EINVAL;
+#ifdef DRIVER_SETVERSION
+               DRIVER_SETVERSION(dev, &sv);
+#endif
+       }
+       return 0;
+}