Logo Search packages:      
Sourcecode: linux version File versions  Download package

int drm_ioctl ( struct inode *  inode,
struct file *  filp,
unsigned int  cmd,
unsigned long  arg 
)

Called whenever a process performs an ioctl on /dev/drm.

Parameters:
inode device inode.
file_priv DRM file private.
cmd command.
arg user argument.
Returns:
zero on success or negative number on failure.
Looks up the ioctl function in the ioctls table, checking for root previleges if so required, and dispatches to the respective function.

Definition at line 450 of file drm_drv.c.

References DRM_COMMAND_BASE, and drm_ioctls.

Referenced by drm_compat_ioctl(), i915_compat_ioctl(), mga_compat_ioctl(), r128_compat_ioctl(), and radeon_compat_ioctl().

{
      struct drm_file *file_priv = filp->private_data;
      struct drm_device *dev = file_priv->head->dev;
      struct drm_ioctl_desc *ioctl;
      drm_ioctl_t *func;
      unsigned int nr = DRM_IOCTL_NR(cmd);
      int retcode = -EINVAL;
      char *kdata = NULL;

      atomic_inc(&dev->ioctl_count);
      atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
      ++file_priv->ioctl_count;

      DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
              task_pid_nr(current), cmd, nr,
              (long)old_encode_dev(file_priv->head->device),
              file_priv->authenticated);

      if ((nr >= DRM_CORE_IOCTL_COUNT) &&
          ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
            goto err_i1;
      if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
          (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
            ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
      else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE))
            ioctl = &drm_ioctls[nr];
      else
            goto err_i1;

      func = ioctl->func;
      /* is there a local override? */
      if ((nr == DRM_IOCTL_NR(DRM_IOCTL_DMA)) && dev->driver->dma_ioctl)
            func = dev->driver->dma_ioctl;


      if (!func) {
            DRM_DEBUG("no function\n");
            retcode = -EINVAL;
      } else if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) ||
               ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) ||
               ((ioctl->flags & DRM_MASTER) && !file_priv->master)) {
            retcode = -EACCES;
      } else {
            if (cmd & (IOC_IN | IOC_OUT)) {
                  kdata = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
                  if (!kdata)
                        return -ENOMEM;
            }

            if (cmd & IOC_IN) {
                  if (copy_from_user(kdata, (void __user *)arg,
                                 _IOC_SIZE(cmd)) != 0) {
                        retcode = -EACCES;
                        goto err_i1;
                  }
            }
            retcode = func(dev, kdata, file_priv);

            if (cmd & IOC_OUT) {
                  if (copy_to_user((void __user *)arg, kdata,
                               _IOC_SIZE(cmd)) != 0)
                        retcode = -EACCES;
            }
      }

      err_i1:
      if (kdata)
            kfree(kdata);
      atomic_dec(&dev->ioctl_count);
      if (retcode)
            DRM_DEBUG("ret = %x\n", retcode);
      return retcode;
}


Generated by  Doxygen 1.6.0   Back to index