1 /*
   2  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
   3  * Use is subject to license terms.
   4  */
   5 
   6 /* BEGIN CSTYLED */
   7 
   8 /* drm_fops.h -- File operations for DRM -*- linux-c -*-
   9  * Created: Mon Jan  4 08:58:31 1999 by faith@valinux.com
  10  */
  11 /*-
  12  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  13  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  14  * Copyright (c) 2009, Intel Corporation.
  15  * All Rights Reserved.
  16  *
  17  * Permission is hereby granted, free of charge, to any person obtaining a
  18  * copy of this software and associated documentation files (the "Software"),
  19  * to deal in the Software without restriction, including without limitation
  20  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  21  * and/or sell copies of the Software, and to permit persons to whom the
  22  * Software is furnished to do so, subject to the following conditions:
  23  *
  24  * The above copyright notice and this permission notice (including the next
  25  * paragraph) shall be included in all copies or substantial portions of the
  26  * Software.
  27  *
  28  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  29  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  30  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  31  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  32  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  33  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  34  * OTHER DEALINGS IN THE SOFTWARE.
  35  *
  36  * Authors:
  37  *    Rickard E. (Rik) Faith <faith@valinux.com>
  38  *    Daryll Strauss <daryll@valinux.com>
  39  *    Gareth Hughes <gareth@valinux.com>
  40  *
  41  */
  42 
  43 /* END CSTYLED */
  44 
  45 #include "drmP.h"
  46 
  47 /*ARGSUSED*/
  48 drm_file_t *
  49 drm_find_file_by_proc(drm_device_t *dev, cred_t *credp)
  50 {
  51         pid_t pid = ddi_get_pid();
  52         drm_file_t *priv;
  53 
  54         TAILQ_FOREACH(priv, &dev->files, link)
  55         if (priv->pid == pid)
  56                 return (priv);
  57         return (NULL);
  58 }
  59 
  60 
  61 drm_cminor_t *
  62 drm_find_file_by_minor(drm_device_t *dev, int minor)
  63 {
  64         drm_cminor_t    *mp;
  65 
  66         TAILQ_FOREACH(mp, &dev->minordevs, link) {
  67                 if (mp->minor == minor)
  68                         return (mp);
  69         }
  70         return (NULL);
  71 }
  72 
  73 /* drm_open_helper is called whenever a process opens /dev/drm. */
  74 /*ARGSUSED*/
  75 int
  76 drm_open_helper(drm_device_t *dev, drm_cminor_t *mp, int flags,
  77     int otyp, cred_t *credp)
  78 {
  79         drm_file_t   *priv;
  80         pid_t pid;
  81         int retcode;
  82 
  83         if (flags & FEXCL)
  84                 return (EBUSY); /* No exclusive opens */
  85         dev->flags = flags;
  86 
  87         pid = ddi_get_pid();
  88         DRM_DEBUG("drm_open_helper :pid = %d", pid);
  89 
  90         DRM_LOCK();
  91         priv = drm_find_file_by_proc(dev, credp);
  92         if (priv) {
  93                 priv->refs++;
  94         } else {
  95                 priv = drm_alloc(sizeof (*priv), DRM_MEM_FILES);
  96                 if (priv == NULL) {
  97                         DRM_UNLOCK();
  98                         return (ENOMEM);
  99                 }
 100                 bzero(priv, sizeof (*priv));
 101 
 102                 priv->uid            = crgetsuid(credp);
 103                 priv->pid            = pid;
 104 
 105                 priv->refs           = 1;
 106                 priv->minor          = 5;    /* just for hack */
 107                 priv->ioctl_count    = 0;
 108 
 109                 /* for compatibility root is always authenticated */
 110                 priv->authenticated  = DRM_SUSER(credp);
 111 
 112                 if (dev->driver->use_gem == 1)
 113                         drm_gem_open(priv);
 114 
 115                 if (dev->driver->open) {
 116                         retcode = dev->driver->open(dev, priv);
 117                         if (retcode != 0) {
 118                                 drm_free(priv, sizeof (*priv), DRM_MEM_FILES);
 119                                 DRM_UNLOCK();
 120                                 return (retcode);
 121                         }
 122                 }
 123 
 124                 /* first opener automatically becomes master */
 125                 priv->master = TAILQ_EMPTY(&dev->files);
 126                 TAILQ_INSERT_TAIL(&dev->files, priv, link);
 127         }
 128         mp->fpriv = priv;
 129         DRM_UNLOCK();
 130         return (0);
 131 }