예제 #1
0
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 {
예제 #2
0
파일: drm_gem.c 프로젝트: ornarium/freebsd
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);
}
예제 #3
0
파일: drm_fops.c 프로젝트: Alkzndr/freebsd
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);
}
예제 #4
0
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 {
예제 #5
0
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);
}
예제 #7
0
파일: drm_fops.c 프로젝트: Alkzndr/freebsd
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);
}
예제 #8
0
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 {
예제 #9
0
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);
}