1 /*- 2 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 3 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the next 14 * paragraph) shall be included in all copies or substantial portions of the 15 * Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 * OTHER DEALINGS IN THE SOFTWARE. 24 * 25 * Authors: 26 * Rickard E. (Rik) Faith <faith@valinux.com> 27 * Daryll Strauss <daryll@valinux.com> 28 * Gareth Hughes <gareth@valinux.com> 29 * 30 */ 31 32 /** @file drm_fops.c 33 * Support code for dealing with the file privates associated with each 34 * open of the DRM device. 35 */ 36 37 #include "drmP.h" 38 39 #if defined(__NetBSD__) 40 struct drm_file * 41 drm_find_file_by_proc(struct drm_device *dev, struct proc *p) 42 { 43 uid_t uid = kauth_cred_getsvuid(p->p_cred); 44 pid_t pid = p->p_pid; 45 struct drm_file *priv; 46 47 DRM_SPINLOCK_ASSERT(&dev->dev_lock); 48 49 TAILQ_FOREACH(priv, &dev->files, link) { 50 if (priv->pid == pid && priv->uid == uid) 51 return priv; 52 } 53 54 return NULL; 55 } 56 57 /* drm_open_helper is called whenever a process opens /dev/drm. */ 58 int drm_open_helper(dev_t kdev, int flags, int fmt, struct proc *p, 59 struct drm_device *dev) 60 { 61 int m = minor(kdev); 62 struct drm_file *priv; 63 int retcode; 64 65 if (flags & O_EXCL) 66 return EBUSY; /* No exclusive opens */ 67 dev->flags = flags; 68 69 DRM_DEBUG("pid = %d, minor = %d\n", DRM_CURRENTPID, m); 70 71 DRM_LOCK(); 72 priv = drm_find_file_by_proc(dev, p); 73 if (priv) { 74 priv->refs++; 75 } else { 76 priv = malloc(sizeof(*priv), DRM_MEM_FILES, M_NOWAIT | M_ZERO); 77 if (priv == NULL) { 78 DRM_UNLOCK(); 79 return ENOMEM; 80 } 81 priv->uid = kauth_cred_getsvuid(p->p_cred); 82 priv->pid = p->p_pid; 83 84 priv->refs = 1; 85 priv->minor = m; 86 priv->ioctl_count = 0; 87 88 /* for compatibility root is always authenticated */ 89 priv->authenticated = DRM_SUSER(p); 90 91 if (dev->driver->open) { 92 /* shared code returns -errno */ 93 retcode = -dev->driver->open(dev, priv); 94 if (retcode != 0) { 95 free(priv, DRM_MEM_FILES); 96 DRM_UNLOCK(); 97 return retcode; 98 } 99 } 100 101 /* first opener automatically becomes master */ 102 priv->master = TAILQ_EMPTY(&dev->files); 103 104 TAILQ_INSERT_TAIL(&dev->files, priv, link); 105 } 106 DRM_UNLOCK(); 107 108 return 0; 109 } 110 111 #elif defined(__FreeBSD__) 112 113 /* drm_open_helper is called whenever a process opens /dev/drm. */ 114 int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p, 115 struct drm_device *dev) 116 { 117 struct drm_file *priv; 118 int m = minor(kdev); 119 int retcode; 120 121 if (flags & O_EXCL) 122 return EBUSY; /* No exclusive opens */ 123 dev->flags = flags; 124 125 DRM_DEBUG("pid = %d, minor = %d\n", DRM_CURRENTPID, m); 126 127 priv = malloc(sizeof(*priv), DRM_MEM_FILES, M_NOWAIT | M_ZERO); 128 if (priv == NULL) { 129 return ENOMEM; 130 } 131 132 retcode = devfs_set_cdevpriv(priv, drm_close); 133 if (retcode != 0) { 134 free(priv, DRM_MEM_FILES); 135 return retcode; 136 } 137 138 DRM_LOCK(); 139 priv->dev = dev; 140 priv->uid = p->td_ucred->cr_svuid; 141 priv->pid = p->td_proc->p_pid; 142 priv->minor = m; 143 priv->ioctl_count = 0; 144 145 /* for compatibility root is always authenticated */ 146 priv->authenticated = DRM_SUSER(p); 147 148 if (dev->driver->open) { 149 /* shared code returns -errno */ 150 retcode = -dev->driver->open(dev, priv); 151 if (retcode != 0) { 152 devfs_clear_cdevpriv(); 153 free(priv, DRM_MEM_FILES); 154 DRM_UNLOCK(); 155 return retcode; 156 } 157 } 158 159 /* first opener automatically becomes master */ 160 priv->master = TAILQ_EMPTY(&dev->files); 161 162 TAILQ_INSERT_TAIL(&dev->files, priv, link); 163 DRM_UNLOCK(); 164 kdev->si_drv1 = dev; 165 return 0; 166 } 167 #endif 168 169 /* The drm_read and drm_poll are stubs to prevent spurious errors 170 * on older X Servers (4.3.0 and earlier) */ 171 172 int drm_read(DRM_CDEV kdev, struct uio *uio, int ioflag) 173 { 174 return 0; 175 } 176 177 int drm_poll(DRM_CDEV kdev, int events, DRM_STRUCTCDEVPROC *p) 178 { 179 return 0; 180 } 181