1 1.31 riastrad /* $NetBSD: drm_cdevsw.c,v 1.31 2024/04/21 03:02:39 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad /*- 4 1.1 riastrad * Copyright (c) 2013 The NetBSD Foundation, Inc. 5 1.1 riastrad * All rights reserved. 6 1.1 riastrad * 7 1.1 riastrad * This code is derived from software contributed to The NetBSD Foundation 8 1.1 riastrad * by Taylor R. Campbell. 9 1.1 riastrad * 10 1.1 riastrad * Redistribution and use in source and binary forms, with or without 11 1.1 riastrad * modification, are permitted provided that the following conditions 12 1.1 riastrad * are met: 13 1.1 riastrad * 1. Redistributions of source code must retain the above copyright 14 1.1 riastrad * notice, this list of conditions and the following disclaimer. 15 1.1 riastrad * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 riastrad * notice, this list of conditions and the following disclaimer in the 17 1.1 riastrad * documentation and/or other materials provided with the distribution. 18 1.1 riastrad * 19 1.1 riastrad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 riastrad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 riastrad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 riastrad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 riastrad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 riastrad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 riastrad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 riastrad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 riastrad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 riastrad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 riastrad * POSSIBILITY OF SUCH DAMAGE. 30 1.1 riastrad */ 31 1.1 riastrad 32 1.1 riastrad #include <sys/cdefs.h> 33 1.31 riastrad __KERNEL_RCSID(0, "$NetBSD: drm_cdevsw.c,v 1.31 2024/04/21 03:02:39 riastradh Exp $"); 34 1.1 riastrad 35 1.1 riastrad #include <sys/param.h> 36 1.1 riastrad #include <sys/types.h> 37 1.1 riastrad #include <sys/conf.h> 38 1.1 riastrad #include <sys/device.h> 39 1.1 riastrad #include <sys/file.h> 40 1.1 riastrad #include <sys/filedesc.h> 41 1.1 riastrad #include <sys/ioccom.h> 42 1.1 riastrad #include <sys/kauth.h> 43 1.1 riastrad #ifndef _MODULE 44 1.1 riastrad /* XXX Mega-kludge because modules are broken. */ 45 1.1 riastrad #include <sys/once.h> 46 1.1 riastrad #endif 47 1.1 riastrad #include <sys/pmf.h> 48 1.1 riastrad #include <sys/poll.h> 49 1.1 riastrad #ifndef _MODULE 50 1.1 riastrad #include <sys/reboot.h> /* XXX drm_init kludge */ 51 1.1 riastrad #endif 52 1.1 riastrad #include <sys/select.h> 53 1.1 riastrad 54 1.1 riastrad #include <uvm/uvm_extern.h> 55 1.1 riastrad 56 1.1 riastrad #include <linux/err.h> 57 1.1 riastrad 58 1.1 riastrad #include <linux/pm.h> 59 1.1 riastrad 60 1.25 riastrad #include <drm/drm_agpsupport.h> 61 1.24 riastrad #include <drm/drm_device.h> 62 1.21 riastrad #include <drm/drm_drv.h> 63 1.21 riastrad #include <drm/drm_file.h> 64 1.23 riastrad #include <drm/drm_irq.h> 65 1.21 riastrad #include <drm/drm_legacy.h> 66 1.17 riastrad 67 1.17 riastrad #include "../dist/drm/drm_internal.h" 68 1.1 riastrad #include "../dist/drm/drm_legacy.h" 69 1.1 riastrad 70 1.1 riastrad static dev_type_open(drm_open); 71 1.1 riastrad 72 1.1 riastrad static int drm_close(struct file *); 73 1.1 riastrad static int drm_read(struct file *, off_t *, struct uio *, kauth_cred_t, 74 1.1 riastrad int); 75 1.1 riastrad static int drm_dequeue_event(struct drm_file *, size_t, 76 1.1 riastrad struct drm_pending_event **, int); 77 1.13 maya static int drm_ioctl_shim(struct file *, unsigned long, void *); 78 1.1 riastrad static int drm_poll(struct file *, int); 79 1.1 riastrad static int drm_kqfilter(struct file *, struct knote *); 80 1.1 riastrad static int drm_stat(struct file *, struct stat *); 81 1.1 riastrad static int drm_fop_mmap(struct file *, off_t *, size_t, int, int *, int *, 82 1.1 riastrad struct uvm_object **, int *); 83 1.22 riastrad static void drm_requeue_event(struct drm_file *, struct drm_pending_event *); 84 1.22 riastrad 85 1.8 riastrad static paddr_t drm_legacy_mmap(dev_t, off_t, int); 86 1.1 riastrad 87 1.1 riastrad const struct cdevsw drm_cdevsw = { 88 1.1 riastrad .d_open = drm_open, 89 1.1 riastrad .d_close = noclose, 90 1.1 riastrad .d_read = noread, 91 1.1 riastrad .d_write = nowrite, 92 1.1 riastrad .d_ioctl = noioctl, 93 1.1 riastrad .d_stop = nostop, 94 1.1 riastrad .d_tty = notty, 95 1.1 riastrad .d_poll = nopoll, 96 1.8 riastrad .d_mmap = drm_legacy_mmap, 97 1.1 riastrad .d_kqfilter = nokqfilter, 98 1.1 riastrad .d_discard = nodiscard, 99 1.1 riastrad /* XXX was D_TTY | D_NEGOFFSAFE */ 100 1.1 riastrad /* XXX Add D_MPSAFE some day... */ 101 1.1 riastrad .d_flag = D_NEGOFFSAFE, 102 1.1 riastrad }; 103 1.1 riastrad 104 1.29 riastrad const struct fileops drm_fileops = { 105 1.1 riastrad .fo_name = "drm", 106 1.1 riastrad .fo_read = drm_read, 107 1.1 riastrad .fo_write = fbadop_write, 108 1.13 maya .fo_ioctl = drm_ioctl_shim, 109 1.1 riastrad .fo_fcntl = fnullop_fcntl, 110 1.1 riastrad .fo_poll = drm_poll, 111 1.1 riastrad .fo_stat = drm_stat, 112 1.1 riastrad .fo_close = drm_close, 113 1.1 riastrad .fo_kqfilter = drm_kqfilter, 114 1.1 riastrad .fo_restart = fnullop_restart, 115 1.1 riastrad .fo_mmap = drm_fop_mmap, 116 1.1 riastrad }; 117 1.1 riastrad 118 1.1 riastrad static int 119 1.1 riastrad drm_open(dev_t d, int flags, int fmt, struct lwp *l) 120 1.1 riastrad { 121 1.1 riastrad struct drm_minor *dminor; 122 1.1 riastrad struct drm_device *dev; 123 1.26 riastrad bool lastclose; 124 1.1 riastrad int fd; 125 1.1 riastrad struct file *fp; 126 1.26 riastrad struct drm_file *priv; 127 1.26 riastrad int need_setup = 0; 128 1.1 riastrad int error; 129 1.1 riastrad 130 1.1 riastrad error = drm_guarantee_initialized(); 131 1.1 riastrad if (error) 132 1.1 riastrad goto fail0; 133 1.1 riastrad 134 1.26 riastrad /* Synchronize with drm_file.c, drm_open and drm_open_helper. */ 135 1.26 riastrad 136 1.1 riastrad if (flags & O_EXCL) { 137 1.1 riastrad error = EBUSY; 138 1.1 riastrad goto fail0; 139 1.1 riastrad } 140 1.1 riastrad 141 1.1 riastrad dminor = drm_minor_acquire(minor(d)); 142 1.1 riastrad if (IS_ERR(dminor)) { 143 1.1 riastrad /* XXX errno Linux->NetBSD */ 144 1.1 riastrad error = -PTR_ERR(dminor); 145 1.1 riastrad goto fail0; 146 1.1 riastrad } 147 1.1 riastrad dev = dminor->dev; 148 1.1 riastrad if (dev->switch_power_state != DRM_SWITCH_POWER_ON) { 149 1.1 riastrad error = EINVAL; 150 1.1 riastrad goto fail1; 151 1.1 riastrad } 152 1.1 riastrad 153 1.6 riastrad mutex_lock(&drm_global_mutex); 154 1.1 riastrad if (dev->open_count == INT_MAX) { 155 1.6 riastrad mutex_unlock(&drm_global_mutex); 156 1.1 riastrad error = EBUSY; 157 1.1 riastrad goto fail1; 158 1.1 riastrad } 159 1.26 riastrad if (dev->open_count++ == 0) 160 1.26 riastrad need_setup = 1; 161 1.10 riastrad mutex_unlock(&drm_global_mutex); 162 1.1 riastrad 163 1.26 riastrad error = fd_allocfile(&fp, &fd); 164 1.26 riastrad if (error) 165 1.26 riastrad goto fail2; 166 1.26 riastrad 167 1.26 riastrad priv = drm_file_alloc(dminor); 168 1.26 riastrad if (IS_ERR(priv)) { 169 1.1 riastrad /* XXX errno Linux->NetBSD */ 170 1.26 riastrad error = -PTR_ERR(priv); 171 1.26 riastrad goto fail3; 172 1.26 riastrad } 173 1.26 riastrad 174 1.26 riastrad if (drm_is_primary_client(priv)) { 175 1.26 riastrad /* XXX errno Linux->NetBSD */ 176 1.26 riastrad error = -drm_master_open(priv); 177 1.1 riastrad if (error) 178 1.26 riastrad goto fail4; 179 1.1 riastrad } 180 1.27 riastrad priv->filp = fp; 181 1.1 riastrad 182 1.26 riastrad mutex_lock(&dev->filelist_mutex); 183 1.26 riastrad list_add(&priv->lhead, &dev->filelist); 184 1.26 riastrad mutex_unlock(&dev->filelist_mutex); 185 1.26 riastrad /* XXX Alpha hose? */ 186 1.1 riastrad 187 1.26 riastrad if (need_setup) { 188 1.26 riastrad /* XXX errno Linux->NetBSD */ 189 1.26 riastrad error = -drm_legacy_setup(dev); 190 1.26 riastrad if (error) 191 1.26 riastrad goto fail5; 192 1.26 riastrad } 193 1.1 riastrad 194 1.26 riastrad error = fd_clone(fp, fd, flags, &drm_fileops, priv); 195 1.1 riastrad KASSERT(error == EMOVEFD); /* XXX */ 196 1.1 riastrad 197 1.1 riastrad /* Success! (But error has to be EMOVEFD, not 0.) */ 198 1.1 riastrad return error; 199 1.1 riastrad 200 1.26 riastrad fail5: mutex_lock(&dev->filelist_mutex); 201 1.26 riastrad list_del(&priv->lhead); 202 1.26 riastrad mutex_unlock(&dev->filelist_mutex); 203 1.26 riastrad fail4: drm_file_free(priv); 204 1.26 riastrad fail3: fd_abort(curproc, fp, fd); 205 1.6 riastrad fail2: mutex_lock(&drm_global_mutex); 206 1.1 riastrad KASSERT(0 < dev->open_count); 207 1.1 riastrad --dev->open_count; 208 1.1 riastrad lastclose = (dev->open_count == 0); 209 1.6 riastrad mutex_unlock(&drm_global_mutex); 210 1.1 riastrad if (lastclose) 211 1.18 riastrad drm_lastclose(dev); 212 1.1 riastrad fail1: drm_minor_release(dminor); 213 1.1 riastrad fail0: KASSERT(error); 214 1.14 mrg if (error == ERESTARTSYS) 215 1.14 mrg error = ERESTART; 216 1.1 riastrad return error; 217 1.1 riastrad } 218 1.1 riastrad 219 1.1 riastrad static int 220 1.1 riastrad drm_close(struct file *fp) 221 1.1 riastrad { 222 1.26 riastrad struct drm_file *const priv = fp->f_data; 223 1.26 riastrad struct drm_minor *const dminor = priv->minor; 224 1.1 riastrad struct drm_device *const dev = dminor->dev; 225 1.1 riastrad bool lastclose; 226 1.1 riastrad 227 1.26 riastrad /* Synchronize with drm_file.c, drm_release. */ 228 1.26 riastrad 229 1.26 riastrad mutex_lock(&dev->filelist_mutex); 230 1.26 riastrad list_del(&priv->lhead); 231 1.26 riastrad mutex_unlock(&dev->filelist_mutex); 232 1.26 riastrad 233 1.26 riastrad drm_file_free(priv); 234 1.1 riastrad 235 1.6 riastrad mutex_lock(&drm_global_mutex); 236 1.1 riastrad KASSERT(0 < dev->open_count); 237 1.1 riastrad --dev->open_count; 238 1.1 riastrad lastclose = (dev->open_count == 0); 239 1.6 riastrad mutex_unlock(&drm_global_mutex); 240 1.1 riastrad 241 1.1 riastrad if (lastclose) 242 1.18 riastrad drm_lastclose(dev); 243 1.1 riastrad 244 1.1 riastrad drm_minor_release(dminor); 245 1.1 riastrad 246 1.1 riastrad return 0; 247 1.1 riastrad } 248 1.1 riastrad 249 1.1 riastrad static int 250 1.1 riastrad drm_read(struct file *fp, off_t *off, struct uio *uio, kauth_cred_t cred, 251 1.1 riastrad int flags) 252 1.1 riastrad { 253 1.1 riastrad struct drm_file *const file = fp->f_data; 254 1.20 riastrad struct drm_device *const dev = file->minor->dev; 255 1.1 riastrad struct drm_pending_event *event; 256 1.1 riastrad bool first; 257 1.20 riastrad int ret = 0; 258 1.20 riastrad 259 1.20 riastrad /* 260 1.20 riastrad * Only one event reader at a time, so that if copyout faults 261 1.20 riastrad * after dequeueing one event and we have to put the event 262 1.20 riastrad * back, another reader won't see out-of-order events. 263 1.20 riastrad */ 264 1.20 riastrad spin_lock(&dev->event_lock); 265 1.20 riastrad DRM_SPIN_WAIT_NOINTR_UNTIL(ret, &file->event_read_wq, &dev->event_lock, 266 1.20 riastrad file->event_read_lock == NULL); 267 1.20 riastrad if (ret) { 268 1.20 riastrad spin_unlock(&dev->event_lock); 269 1.20 riastrad /* XXX errno Linux->NetBSD */ 270 1.20 riastrad return -ret; 271 1.20 riastrad } 272 1.20 riastrad file->event_read_lock = curlwp; 273 1.20 riastrad spin_unlock(&dev->event_lock); 274 1.1 riastrad 275 1.1 riastrad for (first = true; ; first = false) { 276 1.1 riastrad int f = 0; 277 1.20 riastrad off_t offset; 278 1.20 riastrad size_t resid; 279 1.1 riastrad 280 1.1 riastrad if (!first || ISSET(fp->f_flag, FNONBLOCK)) 281 1.1 riastrad f |= FNONBLOCK; 282 1.1 riastrad 283 1.20 riastrad ret = drm_dequeue_event(file, uio->uio_resid, &event, f); 284 1.20 riastrad if (ret) { 285 1.20 riastrad if ((ret == -EWOULDBLOCK) && !first) 286 1.20 riastrad ret = 0; 287 1.1 riastrad break; 288 1.1 riastrad } 289 1.1 riastrad if (event == NULL) 290 1.1 riastrad break; 291 1.20 riastrad 292 1.20 riastrad offset = uio->uio_offset; 293 1.20 riastrad resid = uio->uio_resid; 294 1.20 riastrad /* XXX errno NetBSD->Linux */ 295 1.20 riastrad ret = -uiomove(event->event, event->event->length, uio); 296 1.20 riastrad if (ret) { 297 1.20 riastrad /* 298 1.20 riastrad * Faulted on copyout. Put the event back and 299 1.20 riastrad * stop here. 300 1.20 riastrad */ 301 1.20 riastrad if (!first) { 302 1.20 riastrad /* 303 1.20 riastrad * Already transferred some events. 304 1.20 riastrad * Rather than back them all out, just 305 1.20 riastrad * say we succeeded at returning those. 306 1.20 riastrad */ 307 1.20 riastrad ret = 0; 308 1.20 riastrad } 309 1.20 riastrad uio->uio_offset = offset; 310 1.20 riastrad uio->uio_resid = resid; 311 1.20 riastrad drm_requeue_event(file, event); 312 1.1 riastrad break; 313 1.20 riastrad } 314 1.20 riastrad kfree(event); 315 1.1 riastrad } 316 1.1 riastrad 317 1.20 riastrad /* Release the event read lock. */ 318 1.20 riastrad spin_lock(&dev->event_lock); 319 1.20 riastrad KASSERT(file->event_read_lock == curlwp); 320 1.20 riastrad file->event_read_lock = NULL; 321 1.20 riastrad DRM_SPIN_WAKEUP_ONE(&file->event_read_wq, &dev->event_lock); 322 1.20 riastrad spin_unlock(&dev->event_lock); 323 1.20 riastrad 324 1.20 riastrad /* XXX errno Linux->NetBSD */ 325 1.20 riastrad 326 1.1 riastrad /* Success! */ 327 1.20 riastrad if (ret == ERESTARTSYS) 328 1.20 riastrad ret = ERESTART; 329 1.20 riastrad return -ret; 330 1.1 riastrad } 331 1.1 riastrad 332 1.1 riastrad static int 333 1.1 riastrad drm_dequeue_event(struct drm_file *file, size_t max_length, 334 1.1 riastrad struct drm_pending_event **eventp, int flags) 335 1.1 riastrad { 336 1.1 riastrad struct drm_device *const dev = file->minor->dev; 337 1.1 riastrad struct drm_pending_event *event = NULL; 338 1.1 riastrad unsigned long irqflags; 339 1.1 riastrad int ret = 0; 340 1.1 riastrad 341 1.1 riastrad spin_lock_irqsave(&dev->event_lock, irqflags); 342 1.1 riastrad 343 1.1 riastrad if (ISSET(flags, FNONBLOCK)) { 344 1.1 riastrad if (list_empty(&file->event_list)) 345 1.1 riastrad ret = -EWOULDBLOCK; 346 1.1 riastrad } else { 347 1.1 riastrad DRM_SPIN_WAIT_UNTIL(ret, &file->event_wait, &dev->event_lock, 348 1.1 riastrad !list_empty(&file->event_list)); 349 1.1 riastrad } 350 1.1 riastrad if (ret) 351 1.1 riastrad goto out; 352 1.1 riastrad 353 1.1 riastrad event = list_first_entry(&file->event_list, struct drm_pending_event, 354 1.1 riastrad link); 355 1.1 riastrad if (event->event->length > max_length) { 356 1.1 riastrad /* Event is too large, can't return it. */ 357 1.1 riastrad event = NULL; 358 1.1 riastrad ret = 0; 359 1.1 riastrad goto out; 360 1.1 riastrad } 361 1.1 riastrad 362 1.1 riastrad file->event_space += event->event->length; 363 1.1 riastrad list_del(&event->link); 364 1.1 riastrad 365 1.1 riastrad out: spin_unlock_irqrestore(&dev->event_lock, irqflags); 366 1.1 riastrad *eventp = event; 367 1.1 riastrad return ret; 368 1.1 riastrad } 369 1.1 riastrad 370 1.20 riastrad static void 371 1.20 riastrad drm_requeue_event(struct drm_file *file, struct drm_pending_event *event) 372 1.20 riastrad { 373 1.20 riastrad struct drm_device *const dev = file->minor->dev; 374 1.20 riastrad unsigned long irqflags; 375 1.20 riastrad 376 1.20 riastrad spin_lock_irqsave(&dev->event_lock, irqflags); 377 1.20 riastrad list_add(&event->link, &file->event_list); 378 1.20 riastrad KASSERT(file->event_space >= event->event->length); 379 1.20 riastrad file->event_space -= event->event->length; 380 1.20 riastrad spin_unlock_irqrestore(&dev->event_lock, irqflags); 381 1.20 riastrad } 382 1.20 riastrad 383 1.1 riastrad static int 384 1.13 maya drm_ioctl_shim(struct file *fp, unsigned long cmd, void *data) 385 1.13 maya { 386 1.13 maya struct drm_file *file = fp->f_data; 387 1.13 maya struct drm_driver *driver = file->minor->dev->driver; 388 1.14 mrg int error; 389 1.13 maya 390 1.13 maya if (driver->ioctl_override) 391 1.14 mrg error = driver->ioctl_override(fp, cmd, data); 392 1.13 maya else 393 1.14 mrg error = drm_ioctl(fp, cmd, data); 394 1.14 mrg if (error == ERESTARTSYS) 395 1.14 mrg error = ERESTART; 396 1.14 mrg 397 1.14 mrg return error; 398 1.13 maya } 399 1.13 maya 400 1.13 maya static int 401 1.28 riastrad drm_poll(struct file *fp, int events) 402 1.1 riastrad { 403 1.1 riastrad struct drm_file *const file = fp->f_data; 404 1.1 riastrad struct drm_device *const dev = file->minor->dev; 405 1.1 riastrad int revents = 0; 406 1.1 riastrad unsigned long irqflags; 407 1.1 riastrad 408 1.1 riastrad if (!ISSET(events, (POLLIN | POLLRDNORM))) 409 1.1 riastrad return 0; 410 1.1 riastrad 411 1.1 riastrad spin_lock_irqsave(&dev->event_lock, irqflags); 412 1.1 riastrad if (list_empty(&file->event_list)) 413 1.1 riastrad selrecord(curlwp, &file->event_selq); 414 1.1 riastrad else 415 1.1 riastrad revents |= (events & (POLLIN | POLLRDNORM)); 416 1.1 riastrad spin_unlock_irqrestore(&dev->event_lock, irqflags); 417 1.1 riastrad 418 1.1 riastrad return revents; 419 1.1 riastrad } 420 1.1 riastrad 421 1.1 riastrad static void filt_drm_detach(struct knote *); 422 1.1 riastrad static int filt_drm_event(struct knote *, long); 423 1.1 riastrad 424 1.1 riastrad static const struct filterops drm_filtops = { 425 1.16 thorpej .f_flags = FILTEROP_ISFD, 426 1.1 riastrad .f_attach = NULL, 427 1.1 riastrad .f_detach = filt_drm_detach, 428 1.1 riastrad .f_event = filt_drm_event, 429 1.1 riastrad }; 430 1.1 riastrad 431 1.1 riastrad static int 432 1.1 riastrad drm_kqfilter(struct file *fp, struct knote *kn) 433 1.1 riastrad { 434 1.1 riastrad struct drm_file *const file = fp->f_data; 435 1.1 riastrad struct drm_device *const dev = file->minor->dev; 436 1.1 riastrad unsigned long irqflags; 437 1.1 riastrad 438 1.1 riastrad switch (kn->kn_filter) { 439 1.1 riastrad case EVFILT_READ: 440 1.1 riastrad kn->kn_fop = &drm_filtops; 441 1.1 riastrad kn->kn_hook = file; 442 1.1 riastrad spin_lock_irqsave(&dev->event_lock, irqflags); 443 1.15 thorpej selrecord_knote(&file->event_selq, kn); 444 1.1 riastrad spin_unlock_irqrestore(&dev->event_lock, irqflags); 445 1.1 riastrad return 0; 446 1.1 riastrad case EVFILT_WRITE: 447 1.1 riastrad default: 448 1.1 riastrad return EINVAL; 449 1.1 riastrad } 450 1.1 riastrad } 451 1.1 riastrad 452 1.1 riastrad static void 453 1.1 riastrad filt_drm_detach(struct knote *kn) 454 1.1 riastrad { 455 1.1 riastrad struct drm_file *const file = kn->kn_hook; 456 1.1 riastrad struct drm_device *const dev = file->minor->dev; 457 1.1 riastrad unsigned long irqflags; 458 1.1 riastrad 459 1.1 riastrad spin_lock_irqsave(&dev->event_lock, irqflags); 460 1.15 thorpej selremove_knote(&file->event_selq, kn); 461 1.1 riastrad spin_unlock_irqrestore(&dev->event_lock, irqflags); 462 1.1 riastrad } 463 1.1 riastrad 464 1.1 riastrad static int 465 1.1 riastrad filt_drm_event(struct knote *kn, long hint) 466 1.1 riastrad { 467 1.1 riastrad struct drm_file *const file = kn->kn_hook; 468 1.1 riastrad struct drm_device *const dev = file->minor->dev; 469 1.1 riastrad unsigned long irqflags; 470 1.1 riastrad int ret; 471 1.1 riastrad 472 1.1 riastrad if (hint == NOTE_SUBMIT) 473 1.1 riastrad KASSERT(spin_is_locked(&dev->event_lock)); 474 1.1 riastrad else 475 1.1 riastrad spin_lock_irqsave(&dev->event_lock, irqflags); 476 1.1 riastrad if (list_empty(&file->event_list)) { 477 1.1 riastrad ret = 0; 478 1.1 riastrad } else { 479 1.1 riastrad struct drm_pending_event *const event = 480 1.1 riastrad list_first_entry(&file->event_list, 481 1.1 riastrad struct drm_pending_event, link); 482 1.1 riastrad kn->kn_data = event->event->length; 483 1.1 riastrad ret = 1; 484 1.1 riastrad } 485 1.1 riastrad if (hint == NOTE_SUBMIT) 486 1.1 riastrad KASSERT(spin_is_locked(&dev->event_lock)); 487 1.1 riastrad else 488 1.1 riastrad spin_unlock_irqrestore(&dev->event_lock, irqflags); 489 1.1 riastrad 490 1.1 riastrad return ret; 491 1.1 riastrad } 492 1.1 riastrad 493 1.1 riastrad static int 494 1.1 riastrad drm_stat(struct file *fp, struct stat *st) 495 1.1 riastrad { 496 1.1 riastrad struct drm_file *const file = fp->f_data; 497 1.1 riastrad struct drm_minor *const dminor = file->minor; 498 1.1 riastrad const dev_t devno = makedev(cdevsw_lookup_major(&drm_cdevsw), 499 1.31 riastrad dminor->index); 500 1.1 riastrad 501 1.1 riastrad (void)memset(st, 0, sizeof(*st)); 502 1.1 riastrad 503 1.1 riastrad st->st_dev = devno; 504 1.1 riastrad st->st_ino = 0; /* XXX (dev,ino) uniqueness bleh */ 505 1.1 riastrad st->st_uid = kauth_cred_geteuid(fp->f_cred); 506 1.1 riastrad st->st_gid = kauth_cred_getegid(fp->f_cred); 507 1.1 riastrad st->st_mode = S_IFCHR; /* XXX what? */ 508 1.1 riastrad st->st_rdev = devno; 509 1.1 riastrad /* XXX what else? */ 510 1.1 riastrad 511 1.1 riastrad return 0; 512 1.1 riastrad } 513 1.1 riastrad 514 1.1 riastrad static int 515 1.1 riastrad drm_fop_mmap(struct file *fp, off_t *offp, size_t len, int prot, int *flagsp, 516 1.1 riastrad int *advicep, struct uvm_object **uobjp, int *maxprotp) 517 1.1 riastrad { 518 1.1 riastrad struct drm_file *const file = fp->f_data; 519 1.1 riastrad struct drm_device *const dev = file->minor->dev; 520 1.1 riastrad int error; 521 1.1 riastrad 522 1.1 riastrad KASSERT(fp == file->filp); 523 1.30 riastrad KASSERT(len > 0); 524 1.30 riastrad 525 1.14 mrg /* XXX errno Linux->NetBSD */ 526 1.14 mrg error = -(*dev->driver->mmap_object)(dev, *offp, len, prot, uobjp, 527 1.1 riastrad offp, file->filp); 528 1.1 riastrad *maxprotp = prot; 529 1.1 riastrad *advicep = UVM_ADV_RANDOM; 530 1.14 mrg if (error == ERESTARTSYS) 531 1.14 mrg error = ERESTART; 532 1.14 mrg return error; 533 1.1 riastrad } 534 1.1 riastrad 535 1.1 riastrad static paddr_t 536 1.8 riastrad drm_legacy_mmap(dev_t d, off_t offset, int prot) 537 1.1 riastrad { 538 1.1 riastrad struct drm_minor *dminor; 539 1.1 riastrad paddr_t paddr; 540 1.1 riastrad 541 1.1 riastrad dminor = drm_minor_acquire(minor(d)); 542 1.1 riastrad if (IS_ERR(dminor)) 543 1.1 riastrad return (paddr_t)-1; 544 1.1 riastrad 545 1.8 riastrad paddr = drm_legacy_mmap_paddr(dminor->dev, offset, prot); 546 1.1 riastrad 547 1.1 riastrad drm_minor_release(dminor); 548 1.1 riastrad return paddr; 549 1.1 riastrad } 550