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 (at) valinux.com> 27 * Daryll Strauss <daryll (at) valinux.com> 28 * Gareth Hughes <gareth (at) 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 = malloc(sizeof(*priv), DRM_MEM_FILES, M_NOWAIT | M_ZERO); 75 if (priv == NULL) { 76 DRM_UNLOCK(); 77 return ENOMEM; 78 } 79 priv->uid = kauth_cred_getsvuid(p->p_cred); 80 priv->pid = p->p_pid; 81 82 priv->minor = m; 83 priv->ioctl_count = 0; 84 85 /* for compatibility root is always authenticated */ 86 priv->authenticated = DRM_SUSER(p); 87 88 if (dev->driver->open) { 89 /* shared code returns -errno */ 90 retcode = -dev->driver->open(dev, priv); 91 if (retcode != 0) { 92 free(priv, DRM_MEM_FILES); 93 DRM_UNLOCK(); 94 return retcode; 95 } 96 } 97 98 /* first opener automatically becomes master */ 99 priv->master = TAILQ_EMPTY(&dev->files); 100 101 TAILQ_INSERT_TAIL(&dev->files, priv, link); 102 } 103 DRM_UNLOCK(); 104 105 return 0; 106 } 107 108 #elif defined(__FreeBSD__) 109 110 /* drm_open_helper is called whenever a process opens /dev/drm. */ 111 int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p, 112 struct drm_device *dev) 113 { 114 struct drm_file *priv; 115 int m = minor(kdev); 116 int retcode; 117 118 if (flags & O_EXCL) 119 return EBUSY; /* No exclusive opens */ 120 dev->flags = flags; 121 122 DRM_DEBUG("pid = %d, minor = %d\n", DRM_CURRENTPID, m); 123 124 priv = malloc(sizeof(*priv), DRM_MEM_FILES, M_NOWAIT | M_ZERO); 125 if (priv == NULL) { 126 return ENOMEM; 127 } 128 129 retcode = devfs_set_cdevpriv(priv, drm_close); 130 if (retcode != 0) { 131 free(priv, DRM_MEM_FILES); 132 return retcode; 133 } 134 135 DRM_LOCK(); 136 priv->dev = dev; 137 priv->uid = p->td_ucred->cr_svuid; 138 priv->pid = p->td_proc->p_pid; 139 priv->minor = m; 140 priv->ioctl_count = 0; 141 142 /* for compatibility root is always authenticated */ 143 priv->authenticated = DRM_SUSER(p); 144 145 if (dev->driver->open) { 146 /* shared code returns -errno */ 147 retcode = -dev->driver->open(dev, priv); 148 if (retcode != 0) { 149 devfs_clear_cdevpriv(); 150 free(priv, DRM_MEM_FILES); 151 DRM_UNLOCK(); 152 return retcode; 153 } 154 } 155 156 /* first opener automatically becomes master */ 157 priv->master = TAILQ_EMPTY(&dev->files); 158 159 TAILQ_INSERT_TAIL(&dev->files, priv, link); 160 DRM_UNLOCK(); 161 kdev->si_drv1 = dev; 162 return 0; 163 } 164 #endif 165 166 /* The drm_read and drm_poll are stubs to prevent spurious errors 167 * on older X Servers (4.3.0 and earlier) */ 168 169 int drm_read(DRM_CDEV kdev, struct uio *uio, int ioflag) 170 { 171 return 0; 172 } 173 174 int drm_poll(DRM_CDEV kdev, int events, DRM_STRUCTCDEVPROC *p) 175 { 176 return 0; 177 } 178