paddr_t drmmmap(dev_t kdev, off_t offset, int prot) { struct drm_device *dev = drm_get_device_from_kdev(kdev); drm_local_map_t *map; struct drm_file *priv; drm_map_type_t type; paddr_t phys; DRM_LOCK(); priv = drm_find_file_by_minor(dev, minor(kdev)); DRM_UNLOCK(); if (priv == NULL) { DRM_ERROR("can't find authenticator\n"); return (EINVAL); } if (!priv->authenticated) return (EACCES); if (dev->dma && offset >= 0 && offset < ptoa(dev->dma->page_count)) { drm_device_dma_t *dma = dev->dma; DRM_SPINLOCK(&dev->dma_lock); if (dma->pagelist != NULL) { unsigned long page = offset >> PAGE_SHIFT; unsigned long phys = dma->pagelist[page]; DRM_SPINUNLOCK(&dev->dma_lock); return (atop(phys)); } else {
int drm_gem_mmap_single(struct cdev *kdev, vm_ooffset_t *offset, vm_size_t size, struct vm_object **obj_res, int nprot) { struct drm_device *dev; struct drm_gem_object *gem_obj; struct vm_object *vm_obj; dev = drm_get_device_from_kdev(kdev); if ((dev->driver->driver_features & DRIVER_GEM) == 0) return (ENODEV); DRM_LOCK(dev); gem_obj = drm_gem_object_from_offset(dev, *offset); if (gem_obj == NULL) { DRM_UNLOCK(dev); return (ENODEV); } drm_gem_object_reference(gem_obj); DRM_UNLOCK(dev); vm_obj = cdev_pager_allocate(gem_obj, OBJT_MGTDEVICE, dev->driver->gem_pager_ops, size, nprot, DRM_GEM_MAPPING_MAPOFF(*offset), curthread->td_ucred); if (vm_obj == NULL) { drm_gem_object_unreference_unlocked(gem_obj); return (EINVAL); } *offset = DRM_GEM_MAPPING_MAPOFF(*offset); *obj_res = vm_obj; return (0); }
int drm_poll(struct cdev *kdev, int events, struct thread *td) { struct drm_file *file_priv; struct drm_device *dev; int error, revents; error = devfs_get_cdevpriv((void **)&file_priv); if (error != 0) { DRM_ERROR("can't find authenticator\n"); return (EINVAL); } dev = drm_get_device_from_kdev(kdev); revents = 0; mtx_lock(&dev->event_lock); if ((events & (POLLIN | POLLRDNORM)) != 0) { if (list_empty(&file_priv->event_list)) { CTR0(KTR_DRM, "drm_poll empty list"); selrecord(td, &file_priv->event_poll); } else { revents |= events & (POLLIN | POLLRDNORM); CTR1(KTR_DRM, "drm_poll revents %x", revents); } } mtx_unlock(&dev->event_lock); return (revents); }
int drm_mmap(struct dev_mmap_args *ap) { struct cdev *kdev = ap->a_head.a_dev; vm_offset_t offset = ap->a_offset; struct drm_device *dev = drm_get_device_from_kdev(kdev); struct drm_file *file_priv = NULL; drm_local_map_t *map; enum drm_map_type type; vm_paddr_t phys; DRM_LOCK(); file_priv = drm_find_file_by_proc(dev, DRM_CURPROC); DRM_UNLOCK(); if (file_priv == NULL) { DRM_ERROR("can't find authenticator\n"); return EINVAL; } if (!file_priv->authenticated) return EACCES; if (dev->dma && offset < ptoa(dev->dma->page_count)) { drm_device_dma_t *dma = dev->dma; DRM_SPINLOCK(&dev->dma_lock); if (dma->pagelist != NULL) { unsigned long page = offset >> PAGE_SHIFT; unsigned long phys = dma->pagelist[page]; ap->a_result = atop(phys); DRM_SPINUNLOCK(&dev->dma_lock); return 0; } else {
int drm_mmap(struct dev_mmap_args *ap) { struct cdev *kdev = ap->a_head.a_dev; vm_offset_t offset = ap->a_offset; struct drm_device *dev = drm_get_device_from_kdev(kdev); struct drm_file *file_priv = NULL; struct drm_local_map *map = NULL; struct drm_map_list *r_list; enum drm_map_type type; vm_paddr_t phys; /* d_mmap gets called twice, we can only reference file_priv during * the first call. We need to assume that if error is EBADF the * call was succesful and the client is authenticated. */ DRM_LOCK(dev); file_priv = drm_find_file_by_proc(dev, curthread); DRM_UNLOCK(dev); if (!file_priv) { DRM_ERROR("Could not find authenticator!\n"); return EINVAL; } if (!file_priv->authenticated) return EACCES; DRM_DEBUG("called with offset %016jx\n", (uintmax_t)offset); if (dev->dma && offset < ptoa(dev->dma->page_count)) { drm_device_dma_t *dma = dev->dma; spin_lock(&dev->dma_lock); if (dma->pagelist != NULL) { unsigned long page = offset >> PAGE_SHIFT; unsigned long phys = dma->pagelist[page]; spin_unlock(&dev->dma_lock); // XXX *paddr = phys; ap->a_result = phys; return 0; } else {
int drm_read(struct dev_read_args *ap) { struct cdev *kdev = ap->a_head.a_dev; struct uio *uio = ap->a_uio; int ioflag = ap->a_ioflag; struct drm_file *file_priv; struct drm_device *dev; struct drm_pending_event *e; int error; error = devfs_get_cdevpriv(ap->a_fp, (void **)&file_priv); if (error != 0) { DRM_ERROR("can't find authenticator\n"); return (EINVAL); } dev = drm_get_device_from_kdev(kdev); lockmgr(&dev->event_lock, LK_EXCLUSIVE); while (list_empty(&file_priv->event_list)) { if ((ioflag & O_NONBLOCK) != 0) { error = EAGAIN; goto out; } error = lksleep(&file_priv->event_space, &dev->event_lock, PCATCH, "drmrea", 0); if (error != 0) goto out; } while (drm_dequeue_event(dev, file_priv, uio, &e)) { lockmgr(&dev->event_lock, LK_RELEASE); error = uiomove((caddr_t)e->event, e->event->length, uio); e->destroy(e); if (error != 0) return (error); lockmgr(&dev->event_lock, LK_EXCLUSIVE); } out: lockmgr(&dev->event_lock, LK_RELEASE); return (error); }
int drm_read(struct cdev *kdev, struct uio *uio, int ioflag) { struct drm_file *file_priv; struct drm_device *dev; struct drm_pending_event *e; int error; error = devfs_get_cdevpriv((void **)&file_priv); if (error != 0) { DRM_ERROR("can't find authenticator\n"); return (EINVAL); } dev = drm_get_device_from_kdev(kdev); mtx_lock(&dev->event_lock); while (list_empty(&file_priv->event_list)) { if ((ioflag & O_NONBLOCK) != 0) { error = EAGAIN; goto out; } error = msleep(&file_priv->event_space, &dev->event_lock, PCATCH, "drmrea", 0); if (error != 0) goto out; } while (drm_dequeue_event(dev, file_priv, uio, &e)) { mtx_unlock(&dev->event_lock); error = uiomove(e->event, e->event->length, uio); CTR3(KTR_DRM, "drm_event_dequeued %d %d %d", curproc->p_pid, e->event->type, e->event->length); e->destroy(e); if (error != 0) return (error); mtx_lock(&dev->event_lock); } out: mtx_unlock(&dev->event_lock); return (error); }
int drm_mmap(struct cdev *kdev, vm_ooffset_t offset, vm_paddr_t *paddr, int prot, vm_memattr_t *memattr) { struct drm_device *dev = drm_get_device_from_kdev(kdev); struct drm_file *file_priv = NULL; drm_local_map_t *map; enum drm_map_type type; vm_paddr_t phys; int error; /* d_mmap gets called twice, we can only reference file_priv during * the first call. We need to assume that if error is EBADF the * call was succesful and the client is authenticated. */ error = devfs_get_cdevpriv((void **)&file_priv); if (error == ENOENT) { DRM_ERROR("Could not find authenticator!\n"); return EINVAL; } if (file_priv && !file_priv->authenticated) return EACCES; DRM_DEBUG("called with offset %016jx\n", offset); if (dev->dma && offset < ptoa(dev->dma->page_count)) { drm_device_dma_t *dma = dev->dma; DRM_SPINLOCK(&dev->dma_lock); if (dma->pagelist != NULL) { unsigned long page = offset >> PAGE_SHIFT; unsigned long phys = dma->pagelist[page]; DRM_SPINUNLOCK(&dev->dma_lock); *paddr = phys; return 0; } else {
int drm_kqfilter(struct dev_kqfilter_args *ap) { struct cdev *kdev = ap->a_head.a_dev; struct drm_file *file_priv; struct drm_device *dev; struct knote *kn = ap->a_kn; struct klist *klist; int error; error = devfs_get_cdevpriv(ap->a_fp, (void **)&file_priv); if (error != 0) { DRM_ERROR("can't find authenticator\n"); return (EINVAL); } dev = drm_get_device_from_kdev(kdev); ap->a_result = 0; switch (kn->kn_filter) { case EVFILT_READ: case EVFILT_WRITE: kn->kn_fop = &drmfiltops; kn->kn_hook = (caddr_t)file_priv; break; default: ap->a_result = EOPNOTSUPP; return (0); } lockmgr(&dev->event_lock, LK_EXCLUSIVE); klist = &file_priv->dkq.ki_note; knote_insert(klist, kn); lockmgr(&dev->event_lock, LK_RELEASE); return (0); }