1280183Sdumbbell/** 2280183Sdumbbell * \file drm_vm.c 3280183Sdumbbell * Memory mapping for DRM 4280183Sdumbbell * 5280183Sdumbbell * \author Rickard E. (Rik) Faith <faith@valinux.com> 6280183Sdumbbell * \author Gareth Hughes <gareth@valinux.com> 7280183Sdumbbell */ 8280183Sdumbbell 9280183Sdumbbell/* 10280183Sdumbbell * Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com 11280183Sdumbbell * 12280183Sdumbbell * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 13280183Sdumbbell * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 14235783Skib * All Rights Reserved. 15235783Skib * 16235783Skib * Permission is hereby granted, free of charge, to any person obtaining a 17235783Skib * copy of this software and associated documentation files (the "Software"), 18235783Skib * to deal in the Software without restriction, including without limitation 19235783Skib * the rights to use, copy, modify, merge, publish, distribute, sublicense, 20235783Skib * and/or sell copies of the Software, and to permit persons to whom the 21235783Skib * Software is furnished to do so, subject to the following conditions: 22280183Sdumbbell * 23235783Skib * The above copyright notice and this permission notice (including the next 24235783Skib * paragraph) shall be included in all copies or substantial portions of the 25235783Skib * Software. 26280183Sdumbbell * 27235783Skib * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28235783Skib * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29235783Skib * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 30280183Sdumbbell * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 31280183Sdumbbell * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 32280183Sdumbbell * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 33280183Sdumbbell * OTHER DEALINGS IN THE SOFTWARE. 34235783Skib */ 35235783Skib 36235783Skib#include <sys/cdefs.h> 37235783Skib__FBSDID("$FreeBSD$"); 38235783Skib 39235783Skib/** @file drm_vm.c 40235783Skib * Support code for mmaping of DRM maps. 41235783Skib */ 42235783Skib 43235783Skib#include <dev/drm2/drmP.h> 44235783Skib#include <dev/drm2/drm.h> 45235783Skib 46280183Sdumbbell#ifdef FREEBSD_NOTYET 47235783Skibint 48235783Skibdrm_mmap(struct cdev *kdev, vm_ooffset_t offset, vm_paddr_t *paddr, 49235783Skib int prot, vm_memattr_t *memattr) 50235783Skib{ 51235783Skib struct drm_device *dev = drm_get_device_from_kdev(kdev); 52235783Skib struct drm_file *file_priv = NULL; 53235783Skib drm_local_map_t *map; 54235783Skib enum drm_map_type type; 55235783Skib vm_paddr_t phys; 56235783Skib int error; 57235783Skib 58235783Skib /* d_mmap gets called twice, we can only reference file_priv during 59235783Skib * the first call. We need to assume that if error is EBADF the 60298955Spfg * call was successful and the client is authenticated. 61235783Skib */ 62235783Skib error = devfs_get_cdevpriv((void **)&file_priv); 63235783Skib if (error == ENOENT) { 64235783Skib DRM_ERROR("Could not find authenticator!\n"); 65235783Skib return EINVAL; 66235783Skib } 67235783Skib 68235783Skib if (file_priv && !file_priv->authenticated) 69235783Skib return EACCES; 70235783Skib 71235783Skib DRM_DEBUG("called with offset %016jx\n", offset); 72235783Skib if (dev->dma && offset < ptoa(dev->dma->page_count)) { 73235783Skib drm_device_dma_t *dma = dev->dma; 74235783Skib 75235783Skib DRM_SPINLOCK(&dev->dma_lock); 76235783Skib 77235783Skib if (dma->pagelist != NULL) { 78235783Skib unsigned long page = offset >> PAGE_SHIFT; 79235783Skib unsigned long phys = dma->pagelist[page]; 80235783Skib 81235783Skib DRM_SPINUNLOCK(&dev->dma_lock); 82235783Skib *paddr = phys; 83235783Skib return 0; 84235783Skib } else { 85235783Skib DRM_SPINUNLOCK(&dev->dma_lock); 86235783Skib return -1; 87235783Skib } 88235783Skib } 89235783Skib 90235783Skib /* A sequential search of a linked list is 91235783Skib fine here because: 1) there will only be 92235783Skib about 5-10 entries in the list and, 2) a 93235783Skib DRI client only has to do this mapping 94235783Skib once, so it doesn't have to be optimized 95235783Skib for performance, even if the list was a 96235783Skib bit longer. 97235783Skib */ 98235783Skib DRM_LOCK(dev); 99235783Skib TAILQ_FOREACH(map, &dev->maplist, link) { 100235783Skib if (offset >> DRM_MAP_HANDLE_SHIFT == 101235783Skib (unsigned long)map->handle >> DRM_MAP_HANDLE_SHIFT) 102235783Skib break; 103235783Skib } 104235783Skib 105235783Skib if (map == NULL) { 106235783Skib DRM_DEBUG("Can't find map, request offset = %016jx\n", offset); 107235783Skib TAILQ_FOREACH(map, &dev->maplist, link) { 108235783Skib DRM_DEBUG("map offset = %016lx, handle = %016lx\n", 109235783Skib map->offset, (unsigned long)map->handle); 110235783Skib } 111235783Skib DRM_UNLOCK(dev); 112235783Skib return -1; 113235783Skib } 114235783Skib if (((map->flags & _DRM_RESTRICTED) && !DRM_SUSER(DRM_CURPROC))) { 115235783Skib DRM_UNLOCK(dev); 116235783Skib DRM_DEBUG("restricted map\n"); 117235783Skib return -1; 118235783Skib } 119235783Skib type = map->type; 120235783Skib DRM_UNLOCK(dev); 121235783Skib 122235783Skib offset = offset & ((1ULL << DRM_MAP_HANDLE_SHIFT) - 1); 123235783Skib 124235783Skib switch (type) { 125235783Skib case _DRM_FRAME_BUFFER: 126235783Skib case _DRM_AGP: 127235783Skib *memattr = VM_MEMATTR_WRITE_COMBINING; 128235783Skib /* FALLTHROUGH */ 129235783Skib case _DRM_REGISTERS: 130235783Skib phys = map->offset + offset; 131235783Skib break; 132235783Skib case _DRM_SCATTER_GATHER: 133235783Skib *memattr = VM_MEMATTR_WRITE_COMBINING; 134235783Skib /* FALLTHROUGH */ 135235783Skib case _DRM_CONSISTENT: 136235783Skib case _DRM_SHM: 137235783Skib phys = vtophys((char *)map->virtual + offset); 138235783Skib break; 139235783Skib default: 140235783Skib DRM_ERROR("bad map type %d\n", type); 141235783Skib return -1; /* This should never happen. */ 142235783Skib } 143235783Skib 144235783Skib *paddr = phys; 145235783Skib return 0; 146235783Skib} 147280183Sdumbbell#endif /* FREEBSD_NOTYET */ 148