diff options
author | Jose Fonseca <jrfonseca@users.sourceforge.net> | 2003-06-21 13:09:08 +0000 |
---|---|---|
committer | Jose Fonseca <jrfonseca@users.sourceforge.net> | 2003-06-21 13:09:08 +0000 |
commit | a3e0b635ea1df32c54298c3d4ff23aab0528c04d (patch) | |
tree | 22700bc4ad6b0cb48fa5f525656b947dca43c3f0 | |
parent | c83761e041c5d91394f5590bb8c79d66b2d6cc7a (diff) |
Janitorial of the drm_vm.h. Move some definition of some DMA related data
structures into drm_dma.h.
-rw-r--r-- | linux-core/drmP.h | 76 | ||||
-rw-r--r-- | linux-core/drm_dma.c | 45 | ||||
-rw-r--r-- | linux-core/drm_vm.c | 590 | ||||
-rw-r--r-- | linux-core/i810_drv.c | 2 | ||||
-rw-r--r-- | linux-core/i830_drv.c | 2 | ||||
-rw-r--r-- | linux-core/mga_drv.c | 2 | ||||
-rw-r--r-- | linux-core/r128_drv.c | 2 | ||||
-rw-r--r-- | linux-core/radeon_drv.c | 2 | ||||
-rw-r--r-- | linux-core/sis_drv.c | 2 | ||||
-rw-r--r-- | linux-core/tdfx_drv.c | 2 | ||||
-rw-r--r-- | linux/drmP.h | 76 | ||||
-rw-r--r-- | linux/drm_dma.h | 45 | ||||
-rw-r--r-- | linux/drm_vm.h | 590 | ||||
-rw-r--r-- | linux/drm_vm_tmp.h | 608 | ||||
-rw-r--r-- | linux/gamma_drv.c | 2 | ||||
-rw-r--r-- | linux/i810_drv.c | 2 | ||||
-rw-r--r-- | linux/i830_drv.c | 2 | ||||
-rw-r--r-- | linux/mga_drv.c | 2 | ||||
-rw-r--r-- | linux/r128_drv.c | 2 | ||||
-rw-r--r-- | linux/radeon_drv.c | 2 | ||||
-rw-r--r-- | linux/sis_drv.c | 2 | ||||
-rw-r--r-- | linux/tdfx_drv.c | 2 |
22 files changed, 759 insertions, 1301 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 1f5f83e61..d393bc8fa 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -118,6 +118,7 @@ typedef struct drm_device drm_device_t; #include "drm_bufs.h" #include "drm_lock.h" #include "drm_dma.h" +#include "drm_vm.h" /***********************************************************************/ @@ -438,64 +439,11 @@ typedef struct drm_file { unsigned long lock_count; } drm_file_t; -/** Wait queue */ -typedef struct drm_queue { - atomic_t use_count; /**< Outstanding uses (+1) */ - atomic_t finalization; /**< Finalization in progress */ - atomic_t block_count; /**< Count of processes waiting */ - atomic_t block_read; /**< Queue blocked for reads */ - wait_queue_head_t read_queue; /**< Processes waiting on block_read */ - atomic_t block_write; /**< Queue blocked for writes */ - wait_queue_head_t write_queue; /**< Processes waiting on block_write */ -#if 1 - atomic_t total_queued; /**< Total queued statistic */ - atomic_t total_flushed;/**< Total flushes statistic */ - atomic_t total_locks; /**< Total locks statistics */ -#endif - drm_ctx_flags_t flags; /**< Context preserving and 2D-only */ - drm_waitlist_t waitlist; /**< Pending buffers */ - wait_queue_head_t flush_queue; /**< Processes waiting until flush */ -} drm_queue_t; - -/** - * DMA data. - */ -typedef struct drm_device_dma { - - drm_buf_entry_t bufs[DRM_MAX_ORDER+1]; /**< buffers, grouped by their size order */ - int buf_count; /**< total number of buffers */ - drm_buf_t **buflist; /**< Vector of pointers into drm_device_dma::bufs */ - int seg_count; - int page_count; /**< number of pages */ - unsigned long *pagelist; /**< page list */ - unsigned long byte_count; - enum { - _DRM_DMA_USE_AGP = 0x01, - _DRM_DMA_USE_SG = 0x02 - } flags; - - /** \name DMA support */ - /*@{*/ - drm_buf_t *this_buffer; /**< Buffer being sent */ - drm_buf_t *next_buffer; /**< Selected buffer to send */ - drm_queue_t *next_queue; /**< Queue from which buffer selected*/ - wait_queue_head_t waiting; /**< Processes waiting on free bufs */ - /*@}*/ -} drm_device_dma_t; - typedef struct drm_sigdata { int context; drm_hw_lock_t *lock; } drm_sigdata_t; -/** - * Mappings list - */ -typedef struct drm_map_list { - struct list_head head; /**< list head */ - drm_map_t *map; /**< mapping */ -} drm_map_list_t; - typedef drm_map_t drm_local_map_t; /** @@ -638,28 +586,6 @@ extern int DRM(open_helper)(struct inode *inode, struct file *filp, extern int DRM(flush)(struct file *filp); extern int DRM(fasync)(int fd, struct file *filp, int on); - /* Mapping support (drm_vm.h) */ -extern struct page *DRM(vm_nopage)(struct vm_area_struct *vma, - unsigned long address, - int write_access); -extern struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma, - unsigned long address, - int write_access); -extern struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma, - unsigned long address, - int write_access); -extern struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma, - unsigned long address, - int write_access); -extern void DRM(vm_open)(struct vm_area_struct *vma); -extern void DRM(vm_close)(struct vm_area_struct *vma); -extern void DRM(vm_shm_close)(struct vm_area_struct *vma); -extern int DRM(mmap_dma)(struct file *filp, - struct vm_area_struct *vma); -extern int DRM(mmap)(struct file *filp, struct vm_area_struct *vma); -extern unsigned int DRM(poll)(struct file *filp, struct poll_table_struct *wait); -extern ssize_t DRM(read)(struct file *filp, char *buf, size_t count, loff_t *off); - /* Memory management support (drm_memory.h) */ extern void DRM(mem_init)(void); extern int DRM(mem_info)(char *buf, char **start, off_t offset, diff --git a/linux-core/drm_dma.c b/linux-core/drm_dma.c index 8daa2ba25..14d5043dc 100644 --- a/linux-core/drm_dma.c +++ b/linux-core/drm_dma.c @@ -34,6 +34,51 @@ #ifndef _DRM_DMA_H_ #define _DRM_DMA_H_ +/** Wait queue */ +typedef struct drm_queue { + atomic_t use_count; /**< Outstanding uses (+1) */ + atomic_t finalization; /**< Finalization in progress */ + atomic_t block_count; /**< Count of processes waiting */ + atomic_t block_read; /**< Queue blocked for reads */ + wait_queue_head_t read_queue; /**< Processes waiting on block_read */ + atomic_t block_write; /**< Queue blocked for writes */ + wait_queue_head_t write_queue; /**< Processes waiting on block_write */ +#if 1 + atomic_t total_queued; /**< Total queued statistic */ + atomic_t total_flushed;/**< Total flushes statistic */ + atomic_t total_locks; /**< Total locks statistics */ +#endif + drm_ctx_flags_t flags; /**< Context preserving and 2D-only */ + drm_waitlist_t waitlist; /**< Pending buffers */ + wait_queue_head_t flush_queue; /**< Processes waiting until flush */ +} drm_queue_t; + +/** + * DMA data. + */ +typedef struct drm_device_dma { + + drm_buf_entry_t bufs[DRM_MAX_ORDER+1]; /**< buffers, grouped by their size order */ + int buf_count; /**< total number of buffers */ + drm_buf_t **buflist; /**< Vector of pointers into drm_device_dma::bufs */ + int seg_count; + int page_count; /**< number of pages */ + unsigned long *pagelist; /**< page list */ + unsigned long byte_count; + enum { + _DRM_DMA_USE_AGP = 0x01, + _DRM_DMA_USE_SG = 0x02 + } flags; + + /** \name DMA support */ + /*@{*/ + drm_buf_t *this_buffer; /**< Buffer being sent */ + drm_buf_t *next_buffer; /**< Selected buffer to send */ + drm_queue_t *next_queue; /**< Queue from which buffer selected*/ + wait_queue_head_t waiting; /**< Processes waiting on free bufs */ + /*@}*/ +} drm_device_dma_t; + #if __HAVE_VBL_IRQ diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index c1dfb3779..2df6461d1 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -7,8 +7,6 @@ */ /* - * Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com - * * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. @@ -33,578 +31,34 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#define __NO_VERSION__ -#include "drmP.h" - -/** AGP virtual memory operations */ -struct vm_operations_struct DRM(vm_ops) = { - .nopage = DRM(vm_nopage), - .open = DRM(vm_open), - .close = DRM(vm_close), -}; - -/** Shared virtual memory operations */ -struct vm_operations_struct DRM(vm_shm_ops) = { - .nopage = DRM(vm_shm_nopage), - .open = DRM(vm_open), - .close = DRM(vm_shm_close), -}; - -/** DMA virtual memory operations */ -struct vm_operations_struct DRM(vm_dma_ops) = { - .nopage = DRM(vm_dma_nopage), - .open = DRM(vm_open), - .close = DRM(vm_close), -}; - -/** Scatter-gather virtual memory operations */ -struct vm_operations_struct DRM(vm_sg_ops) = { - .nopage = DRM(vm_sg_nopage), - .open = DRM(vm_open), - .close = DRM(vm_close), -}; +#ifndef _DRM_VM_H_ +#define _DRM_VM_H_ /** - * \c nopage method for AGP virtual memory. - * - * \param vma virtual memory area. - * \param address access address. - * \param write_access sharing. - * \return pointer to the page structure. - * - * Find the right map and if it's AGP memory find the real physical page to - * map, get the page, increment the use count and return it. - */ -struct page *DRM(vm_nopage)(struct vm_area_struct *vma, - unsigned long address, - int write_access) -{ -#if __REALLY_HAVE_AGP - drm_file_t *priv = vma->vm_file->private_data; - drm_device_t *dev = priv->dev; - drm_map_t *map = NULL; - drm_map_list_t *r_list; - struct list_head *list; - - /* - * Find the right map - */ - - if(!dev->agp || !dev->agp->cant_use_aperture) goto vm_nopage_error; - - list_for_each(list, &dev->maplist->head) { - r_list = list_entry(list, drm_map_list_t, head); - map = r_list->map; - if (!map) continue; - if (map->offset == VM_OFFSET(vma)) break; - } - - if (map && map->type == _DRM_AGP) { - unsigned long offset = address - vma->vm_start; - unsigned long baddr = VM_OFFSET(vma) + offset; - struct drm_agp_mem *agpmem; - struct page *page; - -#if __alpha__ - /* - * Adjust to a bus-relative address - */ - baddr -= dev->hose->mem_space->start; -#endif - - /* - * It's AGP memory - find the real physical page to map - */ - for(agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) { - if (agpmem->bound <= baddr && - agpmem->bound + agpmem->pages * PAGE_SIZE > baddr) - break; - } - - if (!agpmem) goto vm_nopage_error; - - /* - * Get the page, inc the use count, and return it - */ - offset = (baddr - agpmem->bound) >> PAGE_SHIFT; - page = virt_to_page(__va(agpmem->memory->memory[offset])); - get_page(page); - - DRM_DEBUG("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n", - baddr, __va(agpmem->memory->memory[offset]), offset, - atomic_read(&page->count)); - - return page; - } -vm_nopage_error: -#endif /* __REALLY_HAVE_AGP */ - - return NOPAGE_SIGBUS; /* Disallow mremap */ -} - -/** - * \c nopage method for shared virtual memory. - * - * \param vma virtual memory area. - * \param address access address. - * \param write_access sharing. - * \return pointer to the page structure. - * - * Get the the mapping, find the real physical page to map, get the page, and - * return it. + * Mappings list */ -struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma, - unsigned long address, - int write_access) -{ - drm_map_t *map = (drm_map_t *)vma->vm_private_data; - unsigned long offset; - unsigned long i; - struct page *page; - - if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */ - if (!map) return NOPAGE_OOM; /* Nothing allocated */ - - offset = address - vma->vm_start; - i = (unsigned long)map->handle + offset; - page = vmalloc_to_page((void *)i); - if (!page) - return NOPAGE_OOM; - get_page(page); - - DRM_DEBUG("shm_nopage 0x%lx\n", address); - return page; -} - - -/** - * \c close method for shared virtual memory. - * - * \param vma virtual memory area. - * - * Deletes map information if we are the last - * person to close a mapping and it's not in the global maplist. - */ -void DRM(vm_shm_close)(struct vm_area_struct *vma) -{ - drm_file_t *priv = vma->vm_file->private_data; - drm_device_t *dev = priv->dev; - drm_vma_entry_t *pt, *prev, *next; - drm_map_t *map; - drm_map_list_t *r_list; - struct list_head *list; - int found_maps = 0; - - DRM_DEBUG("0x%08lx,0x%08lx\n", - vma->vm_start, vma->vm_end - vma->vm_start); - atomic_dec(&dev->vma_count); - - map = vma->vm_private_data; - - down(&dev->struct_sem); - for (pt = dev->vmalist, prev = NULL; pt; pt = next) { - next = pt->next; - if (pt->vma->vm_private_data == map) found_maps++; - if (pt->vma == vma) { - if (prev) { - prev->next = pt->next; - } else { - dev->vmalist = pt->next; - } - DRM(free)(pt, sizeof(*pt), DRM_MEM_VMAS); - } else { - prev = pt; - } - } - /* We were the only map that was found */ - if(found_maps == 1 && - map->flags & _DRM_REMOVABLE) { - /* Check to see if we are in the maplist, if we are not, then - * we delete this mappings information. - */ - found_maps = 0; - list = &dev->maplist->head; - list_for_each(list, &dev->maplist->head) { - r_list = list_entry(list, drm_map_list_t, head); - if (r_list->map == map) found_maps++; - } - - if(!found_maps) { - switch (map->type) { - case _DRM_REGISTERS: - case _DRM_FRAME_BUFFER: -#if __REALLY_HAVE_MTRR - if (map->mtrr >= 0) { - int retcode; - retcode = mtrr_del(map->mtrr, - map->offset, - map->size); - DRM_DEBUG("mtrr_del = %d\n", retcode); - } -#endif - DRM(ioremapfree)(map->handle, map->size, dev); - break; - case _DRM_SHM: - vfree(map->handle); - break; - case _DRM_AGP: - case _DRM_SCATTER_GATHER: - break; - } - DRM(free)(map, sizeof(*map), DRM_MEM_MAPS); - } - } - up(&dev->struct_sem); -} - -/** - * \c nopage method for DMA virtual memory. - * - * \param vma virtual memory area. - * \param address access address. - * \param write_access sharing. - * \return pointer to the page structure. - * - * Determine the page number from the page offset and get it from drm_device_dma::pagelist. - */ -struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma, - unsigned long address, - int write_access) -{ - drm_file_t *priv = vma->vm_file->private_data; - drm_device_t *dev = priv->dev; - drm_device_dma_t *dma = dev->dma; - unsigned long offset; - unsigned long page_nr; - struct page *page; - - if (!dma) return NOPAGE_SIGBUS; /* Error */ - if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */ - if (!dma->pagelist) return NOPAGE_OOM ; /* Nothing allocated */ - - offset = address - vma->vm_start; /* vm_[pg]off[set] should be 0 */ - page_nr = offset >> PAGE_SHIFT; - page = virt_to_page((dma->pagelist[page_nr] + - (offset & (~PAGE_MASK)))); - - get_page(page); - - DRM_DEBUG("dma_nopage 0x%lx (page %lu)\n", address, page_nr); - return page; -} - -/** - * \c nopage method for scatter-gather virtual memory. - * - * \param vma virtual memory area. - * \param address access address. - * \param write_access sharing. - * \return pointer to the page structure. - * - * Determine the map offset from the page offset and get it from drm_sg_mem::pagelist. - */ -struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma, - unsigned long address, - int write_access) -{ - drm_map_t *map = (drm_map_t *)vma->vm_private_data; - drm_file_t *priv = vma->vm_file->private_data; - drm_device_t *dev = priv->dev; - drm_sg_mem_t *entry = dev->sg; - unsigned long offset; - unsigned long map_offset; - unsigned long page_offset; - struct page *page; - - if (!entry) return NOPAGE_SIGBUS; /* Error */ - if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */ - if (!entry->pagelist) return NOPAGE_OOM ; /* Nothing allocated */ - - - offset = address - vma->vm_start; - map_offset = map->offset - dev->sg->handle; - page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT); - page = entry->pagelist[page_offset]; - get_page(page); - - return page; -} - -/** - * \c open method for shared virtual memory. - * - * \param vma virtual memory area. - * - * Create a new drm_vma_entry structure as the \p vma private data entry and - * add it to drm_device::vmalist. - */ -void DRM(vm_open)(struct vm_area_struct *vma) -{ - drm_file_t *priv = vma->vm_file->private_data; - drm_device_t *dev = priv->dev; - drm_vma_entry_t *vma_entry; - - DRM_DEBUG("0x%08lx,0x%08lx\n", - vma->vm_start, vma->vm_end - vma->vm_start); - atomic_inc(&dev->vma_count); - - vma_entry = DRM(alloc)(sizeof(*vma_entry), DRM_MEM_VMAS); - if (vma_entry) { - down(&dev->struct_sem); - vma_entry->vma = vma; - vma_entry->next = dev->vmalist; - vma_entry->pid = current->pid; - dev->vmalist = vma_entry; - up(&dev->struct_sem); - } -} - -/** - * \c close method for all virtual memory types. - * - * \param vma virtual memory area. - * - * Search the \p vma private data entry in drm_device::vmalist, unlink it, and - * free it. - */ -void DRM(vm_close)(struct vm_area_struct *vma) -{ - drm_file_t *priv = vma->vm_file->private_data; - drm_device_t *dev = priv->dev; - drm_vma_entry_t *pt, *prev; - - DRM_DEBUG("0x%08lx,0x%08lx\n", - vma->vm_start, vma->vm_end - vma->vm_start); - atomic_dec(&dev->vma_count); - - down(&dev->struct_sem); - for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) { - if (pt->vma == vma) { - if (prev) { - prev->next = pt->next; - } else { - dev->vmalist = pt->next; - } - DRM(free)(pt, sizeof(*pt), DRM_MEM_VMAS); - break; - } - } - up(&dev->struct_sem); -} - -/** - * mmap DMA memory. - * - * \param filp file pointer. - * \param vma virtual memory area. - * \return zero on success or a negative number on failure. - * - * Sets the virtual memory area operations structure to vm_dma_ops, the file - * pointer, and calls vm_open(). - */ -int DRM(mmap_dma)(struct file *filp, struct vm_area_struct *vma) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev; - drm_device_dma_t *dma; - unsigned long length = vma->vm_end - vma->vm_start; - - lock_kernel(); - dev = priv->dev; - dma = dev->dma; - DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", - vma->vm_start, vma->vm_end, VM_OFFSET(vma)); - - /* Length must match exact page count */ - if (!dma || (length >> PAGE_SHIFT) != dma->page_count) { - unlock_kernel(); - return -EINVAL; - } - unlock_kernel(); - - vma->vm_ops = &DRM(vm_dma_ops); - -#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */ - vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */ -#else - vma->vm_flags |= VM_RESERVED; /* Don't swap */ -#endif - - vma->vm_file = filp; /* Needed for drm_vm_open() */ - DRM(vm_open)(vma); - return 0; -} - -#ifndef DRIVER_GET_MAP_OFS -#define DRIVER_GET_MAP_OFS() (map->offset) -#endif - -#ifndef DRIVER_GET_REG_OFS -#ifdef __alpha__ -#define DRIVER_GET_REG_OFS() (dev->hose->dense_mem_base - \ - dev->hose->mem_space->start) -#else -#define DRIVER_GET_REG_OFS() 0 -#endif -#endif - -/** - * mmap DMA memory. - * - * \param filp file pointer. - * \param vma virtual memory area. - * \return zero on success or a negative number on failure. - * - * If the virtual memory area has no offset associated with it then it's a DMA - * area, so calls mmap_dma(). Otherwise searches the map in drm_device::maplist, - * checks that the restricted flag is not set, sets the virtual memory operations - * according to the mapping type and remaps the pages. Finally sets the file - * pointer and calls vm_open(). - */ -int DRM(mmap)(struct file *filp, struct vm_area_struct *vma) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_map_t *map = NULL; - drm_map_list_t *r_list; - unsigned long offset = 0; - struct list_head *list; - - DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", - vma->vm_start, vma->vm_end, VM_OFFSET(vma)); - - if ( !priv->authenticated ) return -EACCES; - - /* We check for "dma". On Apple's UniNorth, it's valid to have - * the AGP mapped at physical address 0 - * --BenH. - */ - if (!VM_OFFSET(vma) -#if __REALLY_HAVE_AGP - && (!dev->agp || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE) -#endif - ) - return DRM(mmap_dma)(filp, vma); - - /* A sequential search of a linked list is - fine here because: 1) there will only be - about 5-10 entries in the list and, 2) a - DRI client only has to do this mapping - once, so it doesn't have to be optimized - for performance, even if the list was a - bit longer. */ - list_for_each(list, &dev->maplist->head) { - unsigned long off; +typedef struct drm_map_list { + struct list_head head; /**< list head */ + drm_map_t *map; /**< mapping */ +} drm_map_list_t; - r_list = list_entry(list, drm_map_list_t, head); - map = r_list->map; - if (!map) continue; - off = DRIVER_GET_MAP_OFS(); - if (off == VM_OFFSET(vma)) break; - } - if (!map || ((map->flags&_DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) - return -EPERM; +/** \name Prototypes */ +/*@{*/ - /* Check for valid size. */ - if (map->size != vma->vm_end - vma->vm_start) return -EINVAL; +extern struct page *DRM(vm_nopage)(struct vm_area_struct *vma, unsigned long address, int write_access); +extern struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma, unsigned long address, int write_access); +extern struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma, unsigned long address, int write_access); +extern struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma, unsigned long address, int write_access); +extern void DRM(vm_open)(struct vm_area_struct *vma); +extern void DRM(vm_close)(struct vm_area_struct *vma); +extern void DRM(vm_shm_close)(struct vm_area_struct *vma); +extern int DRM(mmap_dma)(struct file *filp, struct vm_area_struct *vma); +extern int DRM(mmap)(struct file *filp, struct vm_area_struct *vma); +extern unsigned int DRM(poll)(struct file *filp, struct poll_table_struct *wait); +extern ssize_t DRM(read)(struct file *filp, char *buf, size_t count, loff_t *off); - if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) { - vma->vm_flags &= (VM_READ | VM_MAYREAD); -#if defined(__i386__) || defined(__x86_64__) - pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW; -#else - /* Ye gads this is ugly. With more thought - we could move this up higher and use - `protection_map' instead. */ - vma->vm_page_prot = __pgprot(pte_val(pte_wrprotect( - __pte(pgprot_val(vma->vm_page_prot))))); -#endif - } +/*@}*/ - switch (map->type) { - case _DRM_AGP: -#if __REALLY_HAVE_AGP - if (dev->agp->cant_use_aperture) { - /* - * On some platforms we can't talk to bus dma address from the CPU, so for - * memory of type DRM_AGP, we'll deal with sorting out the real physical - * pages and mappings in nopage() - */ -#if defined(__powerpc__) - pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; -#endif - vma->vm_ops = &DRM(vm_ops); - break; - } -#endif - /* fall through to _DRM_FRAME_BUFFER... */ - case _DRM_FRAME_BUFFER: - case _DRM_REGISTERS: - if (VM_OFFSET(vma) >= __pa(high_memory)) { -#if defined(__i386__) || defined(__x86_64__) - if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) { - pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; - pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT; - } -#elif defined(__powerpc__) - pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE | _PAGE_GUARDED; -#endif - vma->vm_flags |= VM_IO; /* not in core dump */ - } -#if defined(__ia64__) - if (map->type != _DRM_AGP) - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); -#endif - offset = DRIVER_GET_REG_OFS(); -#ifdef __sparc__ - if (io_remap_page_range(DRM_RPR_ARG(vma) vma->vm_start, - VM_OFFSET(vma) + offset, - vma->vm_end - vma->vm_start, - vma->vm_page_prot, 0)) -#else - if (remap_page_range(DRM_RPR_ARG(vma) vma->vm_start, - VM_OFFSET(vma) + offset, - vma->vm_end - vma->vm_start, - vma->vm_page_prot)) -#endif - return -EAGAIN; - DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx," - " offset = 0x%lx\n", - map->type, - vma->vm_start, vma->vm_end, VM_OFFSET(vma) + offset); - vma->vm_ops = &DRM(vm_ops); - break; - case _DRM_SHM: - vma->vm_ops = &DRM(vm_shm_ops); - vma->vm_private_data = (void *)map; - /* Don't let this area swap. Change when - DRM_KERNEL advisory is supported. */ -#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */ - vma->vm_flags |= VM_LOCKED; -#else - vma->vm_flags |= VM_RESERVED; -#endif - break; - case _DRM_SCATTER_GATHER: - vma->vm_ops = &DRM(vm_sg_ops); - vma->vm_private_data = (void *)map; -#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */ - vma->vm_flags |= VM_LOCKED; -#else - vma->vm_flags |= VM_RESERVED; -#endif - break; - default: - return -EINVAL; /* This should never happen. */ - } -#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */ - vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */ -#else - vma->vm_flags |= VM_RESERVED; /* Don't swap */ -#endif - vma->vm_file = filp; /* Needed for drm_vm_open() */ - DRM(vm_open)(vma); - return 0; -} +#endif /* !_DRM_VM_H_ */ diff --git a/linux-core/i810_drv.c b/linux-core/i810_drv.c index e7160eb96..09210198b 100644 --- a/linux-core/i810_drv.c +++ b/linux-core/i810_drv.c @@ -51,5 +51,5 @@ #include "drm_lock_tmp.h" #include "drm_memory.h" #include "drm_proc.h" -#include "drm_vm.h" +#include "drm_vm_tmp.h" #include "drm_stub.h" diff --git a/linux-core/i830_drv.c b/linux-core/i830_drv.c index dd2af6985..ccb51397d 100644 --- a/linux-core/i830_drv.c +++ b/linux-core/i830_drv.c @@ -53,5 +53,5 @@ #include "drm_lock_tmp.h" #include "drm_memory.h" #include "drm_proc.h" -#include "drm_vm.h" +#include "drm_vm_tmp.h" #include "drm_stub.h" diff --git a/linux-core/mga_drv.c b/linux-core/mga_drv.c index 9f7abab3b..2f118582f 100644 --- a/linux-core/mga_drv.c +++ b/linux-core/mga_drv.c @@ -48,5 +48,5 @@ #include "drm_lock_tmp.h" #include "drm_memory.h" #include "drm_proc.h" -#include "drm_vm.h" +#include "drm_vm_tmp.h" #include "drm_stub.h" diff --git a/linux-core/r128_drv.c b/linux-core/r128_drv.c index d2e37231d..28ad94bb7 100644 --- a/linux-core/r128_drv.c +++ b/linux-core/r128_drv.c @@ -50,6 +50,6 @@ #include "drm_lock_tmp.h" #include "drm_memory.h" #include "drm_proc.h" -#include "drm_vm.h" +#include "drm_vm_tmp.h" #include "drm_stub.h" #include "drm_sg_tmp.h" diff --git a/linux-core/radeon_drv.c b/linux-core/radeon_drv.c index 716f0ee40..e963ffb9f 100644 --- a/linux-core/radeon_drv.c +++ b/linux-core/radeon_drv.c @@ -51,6 +51,6 @@ #include "drm_lock_tmp.h" #include "drm_memory.h" #include "drm_proc.h" -#include "drm_vm.h" +#include "drm_vm_tmp.h" #include "drm_stub.h" #include "drm_sg_tmp.h" diff --git a/linux-core/sis_drv.c b/linux-core/sis_drv.c index 5aece8f96..32d632b2c 100644 --- a/linux-core/sis_drv.c +++ b/linux-core/sis_drv.c @@ -44,5 +44,5 @@ #include "drm_lock_tmp.h" #include "drm_memory.h" #include "drm_proc.h" -#include "drm_vm.h" +#include "drm_vm_tmp.h" #include "drm_stub.h" diff --git a/linux-core/tdfx_drv.c b/linux-core/tdfx_drv.c index 36fdb35e1..404ed6d59 100644 --- a/linux-core/tdfx_drv.c +++ b/linux-core/tdfx_drv.c @@ -88,5 +88,5 @@ static drm_pci_list_t DRM(idlist)[] = { #include "drm_lock_tmp.h" #include "drm_memory.h" #include "drm_proc.h" -#include "drm_vm.h" +#include "drm_vm_tmp.h" #include "drm_stub.h" diff --git a/linux/drmP.h b/linux/drmP.h index 1f5f83e61..d393bc8fa 100644 --- a/linux/drmP.h +++ b/linux/drmP.h @@ -118,6 +118,7 @@ typedef struct drm_device drm_device_t; #include "drm_bufs.h" #include "drm_lock.h" #include "drm_dma.h" +#include "drm_vm.h" /***********************************************************************/ @@ -438,64 +439,11 @@ typedef struct drm_file { unsigned long lock_count; } drm_file_t; -/** Wait queue */ -typedef struct drm_queue { - atomic_t use_count; /**< Outstanding uses (+1) */ - atomic_t finalization; /**< Finalization in progress */ - atomic_t block_count; /**< Count of processes waiting */ - atomic_t block_read; /**< Queue blocked for reads */ - wait_queue_head_t read_queue; /**< Processes waiting on block_read */ - atomic_t block_write; /**< Queue blocked for writes */ - wait_queue_head_t write_queue; /**< Processes waiting on block_write */ -#if 1 - atomic_t total_queued; /**< Total queued statistic */ - atomic_t total_flushed;/**< Total flushes statistic */ - atomic_t total_locks; /**< Total locks statistics */ -#endif - drm_ctx_flags_t flags; /**< Context preserving and 2D-only */ - drm_waitlist_t waitlist; /**< Pending buffers */ - wait_queue_head_t flush_queue; /**< Processes waiting until flush */ -} drm_queue_t; - -/** - * DMA data. - */ -typedef struct drm_device_dma { - - drm_buf_entry_t bufs[DRM_MAX_ORDER+1]; /**< buffers, grouped by their size order */ - int buf_count; /**< total number of buffers */ - drm_buf_t **buflist; /**< Vector of pointers into drm_device_dma::bufs */ - int seg_count; - int page_count; /**< number of pages */ - unsigned long *pagelist; /**< page list */ - unsigned long byte_count; - enum { - _DRM_DMA_USE_AGP = 0x01, - _DRM_DMA_USE_SG = 0x02 - } flags; - - /** \name DMA support */ - /*@{*/ - drm_buf_t *this_buffer; /**< Buffer being sent */ - drm_buf_t *next_buffer; /**< Selected buffer to send */ - drm_queue_t *next_queue; /**< Queue from which buffer selected*/ - wait_queue_head_t waiting; /**< Processes waiting on free bufs */ - /*@}*/ -} drm_device_dma_t; - typedef struct drm_sigdata { int context; drm_hw_lock_t *lock; } drm_sigdata_t; -/** - * Mappings list - */ -typedef struct drm_map_list { - struct list_head head; /**< list head */ - drm_map_t *map; /**< mapping */ -} drm_map_list_t; - typedef drm_map_t drm_local_map_t; /** @@ -638,28 +586,6 @@ extern int DRM(open_helper)(struct inode *inode, struct file *filp, extern int DRM(flush)(struct file *filp); extern int DRM(fasync)(int fd, struct file *filp, int on); - /* Mapping support (drm_vm.h) */ -extern struct page *DRM(vm_nopage)(struct vm_area_struct *vma, - unsigned long address, - int write_access); -extern struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma, - unsigned long address, - int write_access); -extern struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma, - unsigned long address, - int write_access); -extern struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma, - unsigned long address, - int write_access); -extern void DRM(vm_open)(struct vm_area_struct *vma); -extern void DRM(vm_close)(struct vm_area_struct *vma); -extern void DRM(vm_shm_close)(struct vm_area_struct *vma); -extern int DRM(mmap_dma)(struct file *filp, - struct vm_area_struct *vma); -extern int DRM(mmap)(struct file *filp, struct vm_area_struct *vma); -extern unsigned int DRM(poll)(struct file *filp, struct poll_table_struct *wait); -extern ssize_t DRM(read)(struct file *filp, char *buf, size_t count, loff_t *off); - /* Memory management support (drm_memory.h) */ extern void DRM(mem_init)(void); extern int DRM(mem_info)(char *buf, char **start, off_t offset, diff --git a/linux/drm_dma.h b/linux/drm_dma.h index 8daa2ba25..14d5043dc 100644 --- a/linux/drm_dma.h +++ b/linux/drm_dma.h @@ -34,6 +34,51 @@ #ifndef _DRM_DMA_H_ #define _DRM_DMA_H_ +/** Wait queue */ +typedef struct drm_queue { + atomic_t use_count; /**< Outstanding uses (+1) */ + atomic_t finalization; /**< Finalization in progress */ + atomic_t block_count; /**< Count of processes waiting */ + atomic_t block_read; /**< Queue blocked for reads */ + wait_queue_head_t read_queue; /**< Processes waiting on block_read */ + atomic_t block_write; /**< Queue blocked for writes */ + wait_queue_head_t write_queue; /**< Processes waiting on block_write */ +#if 1 + atomic_t total_queued; /**< Total queued statistic */ + atomic_t total_flushed;/**< Total flushes statistic */ + atomic_t total_locks; /**< Total locks statistics */ +#endif + drm_ctx_flags_t flags; /**< Context preserving and 2D-only */ + drm_waitlist_t waitlist; /**< Pending buffers */ + wait_queue_head_t flush_queue; /**< Processes waiting until flush */ +} drm_queue_t; + +/** + * DMA data. + */ +typedef struct drm_device_dma { + + drm_buf_entry_t bufs[DRM_MAX_ORDER+1]; /**< buffers, grouped by their size order */ + int buf_count; /**< total number of buffers */ + drm_buf_t **buflist; /**< Vector of pointers into drm_device_dma::bufs */ + int seg_count; + int page_count; /**< number of pages */ + unsigned long *pagelist; /**< page list */ + unsigned long byte_count; + enum { + _DRM_DMA_USE_AGP = 0x01, + _DRM_DMA_USE_SG = 0x02 + } flags; + + /** \name DMA support */ + /*@{*/ + drm_buf_t *this_buffer; /**< Buffer being sent */ + drm_buf_t *next_buffer; /**< Selected buffer to send */ + drm_queue_t *next_queue; /**< Queue from which buffer selected*/ + wait_queue_head_t waiting; /**< Processes waiting on free bufs */ + /*@}*/ +} drm_device_dma_t; + #if __HAVE_VBL_IRQ diff --git a/linux/drm_vm.h b/linux/drm_vm.h index c1dfb3779..2df6461d1 100644 --- a/linux/drm_vm.h +++ b/linux/drm_vm.h @@ -7,8 +7,6 @@ */ /* - * Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com - * * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All Rights Reserved. @@ -33,578 +31,34 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#define __NO_VERSION__ -#include "drmP.h" - -/** AGP virtual memory operations */ -struct vm_operations_struct DRM(vm_ops) = { - .nopage = DRM(vm_nopage), - .open = DRM(vm_open), - .close = DRM(vm_close), -}; - -/** Shared virtual memory operations */ -struct vm_operations_struct DRM(vm_shm_ops) = { - .nopage = DRM(vm_shm_nopage), - .open = DRM(vm_open), - .close = DRM(vm_shm_close), -}; - -/** DMA virtual memory operations */ -struct vm_operations_struct DRM(vm_dma_ops) = { - .nopage = DRM(vm_dma_nopage), - .open = DRM(vm_open), - .close = DRM(vm_close), -}; - -/** Scatter-gather virtual memory operations */ -struct vm_operations_struct DRM(vm_sg_ops) = { - .nopage = DRM(vm_sg_nopage), - .open = DRM(vm_open), - .close = DRM(vm_close), -}; +#ifndef _DRM_VM_H_ +#define _DRM_VM_H_ /** - * \c nopage method for AGP virtual memory. - * - * \param vma virtual memory area. - * \param address access address. - * \param write_access sharing. - * \return pointer to the page structure. - * - * Find the right map and if it's AGP memory find the real physical page to - * map, get the page, increment the use count and return it. - */ -struct page *DRM(vm_nopage)(struct vm_area_struct *vma, - unsigned long address, - int write_access) -{ -#if __REALLY_HAVE_AGP - drm_file_t *priv = vma->vm_file->private_data; - drm_device_t *dev = priv->dev; - drm_map_t *map = NULL; - drm_map_list_t *r_list; - struct list_head *list; - - /* - * Find the right map - */ - - if(!dev->agp || !dev->agp->cant_use_aperture) goto vm_nopage_error; - - list_for_each(list, &dev->maplist->head) { - r_list = list_entry(list, drm_map_list_t, head); - map = r_list->map; - if (!map) continue; - if (map->offset == VM_OFFSET(vma)) break; - } - - if (map && map->type == _DRM_AGP) { - unsigned long offset = address - vma->vm_start; - unsigned long baddr = VM_OFFSET(vma) + offset; - struct drm_agp_mem *agpmem; - struct page *page; - -#if __alpha__ - /* - * Adjust to a bus-relative address - */ - baddr -= dev->hose->mem_space->start; -#endif - - /* - * It's AGP memory - find the real physical page to map - */ - for(agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) { - if (agpmem->bound <= baddr && - agpmem->bound + agpmem->pages * PAGE_SIZE > baddr) - break; - } - - if (!agpmem) goto vm_nopage_error; - - /* - * Get the page, inc the use count, and return it - */ - offset = (baddr - agpmem->bound) >> PAGE_SHIFT; - page = virt_to_page(__va(agpmem->memory->memory[offset])); - get_page(page); - - DRM_DEBUG("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n", - baddr, __va(agpmem->memory->memory[offset]), offset, - atomic_read(&page->count)); - - return page; - } -vm_nopage_error: -#endif /* __REALLY_HAVE_AGP */ - - return NOPAGE_SIGBUS; /* Disallow mremap */ -} - -/** - * \c nopage method for shared virtual memory. - * - * \param vma virtual memory area. - * \param address access address. - * \param write_access sharing. - * \return pointer to the page structure. - * - * Get the the mapping, find the real physical page to map, get the page, and - * return it. + * Mappings list */ -struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma, - unsigned long address, - int write_access) -{ - drm_map_t *map = (drm_map_t *)vma->vm_private_data; - unsigned long offset; - unsigned long i; - struct page *page; - - if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */ - if (!map) return NOPAGE_OOM; /* Nothing allocated */ - - offset = address - vma->vm_start; - i = (unsigned long)map->handle + offset; - page = vmalloc_to_page((void *)i); - if (!page) - return NOPAGE_OOM; - get_page(page); - - DRM_DEBUG("shm_nopage 0x%lx\n", address); - return page; -} - - -/** - * \c close method for shared virtual memory. - * - * \param vma virtual memory area. - * - * Deletes map information if we are the last - * person to close a mapping and it's not in the global maplist. - */ -void DRM(vm_shm_close)(struct vm_area_struct *vma) -{ - drm_file_t *priv = vma->vm_file->private_data; - drm_device_t *dev = priv->dev; - drm_vma_entry_t *pt, *prev, *next; - drm_map_t *map; - drm_map_list_t *r_list; - struct list_head *list; - int found_maps = 0; - - DRM_DEBUG("0x%08lx,0x%08lx\n", - vma->vm_start, vma->vm_end - vma->vm_start); - atomic_dec(&dev->vma_count); - - map = vma->vm_private_data; - - down(&dev->struct_sem); - for (pt = dev->vmalist, prev = NULL; pt; pt = next) { - next = pt->next; - if (pt->vma->vm_private_data == map) found_maps++; - if (pt->vma == vma) { - if (prev) { - prev->next = pt->next; - } else { - dev->vmalist = pt->next; - } - DRM(free)(pt, sizeof(*pt), DRM_MEM_VMAS); - } else { - prev = pt; - } - } - /* We were the only map that was found */ - if(found_maps == 1 && - map->flags & _DRM_REMOVABLE) { - /* Check to see if we are in the maplist, if we are not, then - * we delete this mappings information. - */ - found_maps = 0; - list = &dev->maplist->head; - list_for_each(list, &dev->maplist->head) { - r_list = list_entry(list, drm_map_list_t, head); - if (r_list->map == map) found_maps++; - } - - if(!found_maps) { - switch (map->type) { - case _DRM_REGISTERS: - case _DRM_FRAME_BUFFER: -#if __REALLY_HAVE_MTRR - if (map->mtrr >= 0) { - int retcode; - retcode = mtrr_del(map->mtrr, - map->offset, - map->size); - DRM_DEBUG("mtrr_del = %d\n", retcode); - } -#endif - DRM(ioremapfree)(map->handle, map->size, dev); - break; - case _DRM_SHM: - vfree(map->handle); - break; - case _DRM_AGP: - case _DRM_SCATTER_GATHER: - break; - } - DRM(free)(map, sizeof(*map), DRM_MEM_MAPS); - } - } - up(&dev->struct_sem); -} - -/** - * \c nopage method for DMA virtual memory. - * - * \param vma virtual memory area. - * \param address access address. - * \param write_access sharing. - * \return pointer to the page structure. - * - * Determine the page number from the page offset and get it from drm_device_dma::pagelist. - */ -struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma, - unsigned long address, - int write_access) -{ - drm_file_t *priv = vma->vm_file->private_data; - drm_device_t *dev = priv->dev; - drm_device_dma_t *dma = dev->dma; - unsigned long offset; - unsigned long page_nr; - struct page *page; - - if (!dma) return NOPAGE_SIGBUS; /* Error */ - if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */ - if (!dma->pagelist) return NOPAGE_OOM ; /* Nothing allocated */ - - offset = address - vma->vm_start; /* vm_[pg]off[set] should be 0 */ - page_nr = offset >> PAGE_SHIFT; - page = virt_to_page((dma->pagelist[page_nr] + - (offset & (~PAGE_MASK)))); - - get_page(page); - - DRM_DEBUG("dma_nopage 0x%lx (page %lu)\n", address, page_nr); - return page; -} - -/** - * \c nopage method for scatter-gather virtual memory. - * - * \param vma virtual memory area. - * \param address access address. - * \param write_access sharing. - * \return pointer to the page structure. - * - * Determine the map offset from the page offset and get it from drm_sg_mem::pagelist. - */ -struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma, - unsigned long address, - int write_access) -{ - drm_map_t *map = (drm_map_t *)vma->vm_private_data; - drm_file_t *priv = vma->vm_file->private_data; - drm_device_t *dev = priv->dev; - drm_sg_mem_t *entry = dev->sg; - unsigned long offset; - unsigned long map_offset; - unsigned long page_offset; - struct page *page; - - if (!entry) return NOPAGE_SIGBUS; /* Error */ - if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */ - if (!entry->pagelist) return NOPAGE_OOM ; /* Nothing allocated */ - - - offset = address - vma->vm_start; - map_offset = map->offset - dev->sg->handle; - page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT); - page = entry->pagelist[page_offset]; - get_page(page); - - return page; -} - -/** - * \c open method for shared virtual memory. - * - * \param vma virtual memory area. - * - * Create a new drm_vma_entry structure as the \p vma private data entry and - * add it to drm_device::vmalist. - */ -void DRM(vm_open)(struct vm_area_struct *vma) -{ - drm_file_t *priv = vma->vm_file->private_data; - drm_device_t *dev = priv->dev; - drm_vma_entry_t *vma_entry; - - DRM_DEBUG("0x%08lx,0x%08lx\n", - vma->vm_start, vma->vm_end - vma->vm_start); - atomic_inc(&dev->vma_count); - - vma_entry = DRM(alloc)(sizeof(*vma_entry), DRM_MEM_VMAS); - if (vma_entry) { - down(&dev->struct_sem); - vma_entry->vma = vma; - vma_entry->next = dev->vmalist; - vma_entry->pid = current->pid; - dev->vmalist = vma_entry; - up(&dev->struct_sem); - } -} - -/** - * \c close method for all virtual memory types. - * - * \param vma virtual memory area. - * - * Search the \p vma private data entry in drm_device::vmalist, unlink it, and - * free it. - */ -void DRM(vm_close)(struct vm_area_struct *vma) -{ - drm_file_t *priv = vma->vm_file->private_data; - drm_device_t *dev = priv->dev; - drm_vma_entry_t *pt, *prev; - - DRM_DEBUG("0x%08lx,0x%08lx\n", - vma->vm_start, vma->vm_end - vma->vm_start); - atomic_dec(&dev->vma_count); - - down(&dev->struct_sem); - for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) { - if (pt->vma == vma) { - if (prev) { - prev->next = pt->next; - } else { - dev->vmalist = pt->next; - } - DRM(free)(pt, sizeof(*pt), DRM_MEM_VMAS); - break; - } - } - up(&dev->struct_sem); -} - -/** - * mmap DMA memory. - * - * \param filp file pointer. - * \param vma virtual memory area. - * \return zero on success or a negative number on failure. - * - * Sets the virtual memory area operations structure to vm_dma_ops, the file - * pointer, and calls vm_open(). - */ -int DRM(mmap_dma)(struct file *filp, struct vm_area_struct *vma) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev; - drm_device_dma_t *dma; - unsigned long length = vma->vm_end - vma->vm_start; - - lock_kernel(); - dev = priv->dev; - dma = dev->dma; - DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", - vma->vm_start, vma->vm_end, VM_OFFSET(vma)); - - /* Length must match exact page count */ - if (!dma || (length >> PAGE_SHIFT) != dma->page_count) { - unlock_kernel(); - return -EINVAL; - } - unlock_kernel(); - - vma->vm_ops = &DRM(vm_dma_ops); - -#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */ - vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */ -#else - vma->vm_flags |= VM_RESERVED; /* Don't swap */ -#endif - - vma->vm_file = filp; /* Needed for drm_vm_open() */ - DRM(vm_open)(vma); - return 0; -} - -#ifndef DRIVER_GET_MAP_OFS -#define DRIVER_GET_MAP_OFS() (map->offset) -#endif - -#ifndef DRIVER_GET_REG_OFS -#ifdef __alpha__ -#define DRIVER_GET_REG_OFS() (dev->hose->dense_mem_base - \ - dev->hose->mem_space->start) -#else -#define DRIVER_GET_REG_OFS() 0 -#endif -#endif - -/** - * mmap DMA memory. - * - * \param filp file pointer. - * \param vma virtual memory area. - * \return zero on success or a negative number on failure. - * - * If the virtual memory area has no offset associated with it then it's a DMA - * area, so calls mmap_dma(). Otherwise searches the map in drm_device::maplist, - * checks that the restricted flag is not set, sets the virtual memory operations - * according to the mapping type and remaps the pages. Finally sets the file - * pointer and calls vm_open(). - */ -int DRM(mmap)(struct file *filp, struct vm_area_struct *vma) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_map_t *map = NULL; - drm_map_list_t *r_list; - unsigned long offset = 0; - struct list_head *list; - - DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", - vma->vm_start, vma->vm_end, VM_OFFSET(vma)); - - if ( !priv->authenticated ) return -EACCES; - - /* We check for "dma". On Apple's UniNorth, it's valid to have - * the AGP mapped at physical address 0 - * --BenH. - */ - if (!VM_OFFSET(vma) -#if __REALLY_HAVE_AGP - && (!dev->agp || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE) -#endif - ) - return DRM(mmap_dma)(filp, vma); - - /* A sequential search of a linked list is - fine here because: 1) there will only be - about 5-10 entries in the list and, 2) a - DRI client only has to do this mapping - once, so it doesn't have to be optimized - for performance, even if the list was a - bit longer. */ - list_for_each(list, &dev->maplist->head) { - unsigned long off; +typedef struct drm_map_list { + struct list_head head; /**< list head */ + drm_map_t *map; /**< mapping */ +} drm_map_list_t; - r_list = list_entry(list, drm_map_list_t, head); - map = r_list->map; - if (!map) continue; - off = DRIVER_GET_MAP_OFS(); - if (off == VM_OFFSET(vma)) break; - } - if (!map || ((map->flags&_DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) - return -EPERM; +/** \name Prototypes */ +/*@{*/ - /* Check for valid size. */ - if (map->size != vma->vm_end - vma->vm_start) return -EINVAL; +extern struct page *DRM(vm_nopage)(struct vm_area_struct *vma, unsigned long address, int write_access); +extern struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma, unsigned long address, int write_access); +extern struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma, unsigned long address, int write_access); +extern struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma, unsigned long address, int write_access); +extern void DRM(vm_open)(struct vm_area_struct *vma); +extern void DRM(vm_close)(struct vm_area_struct *vma); +extern void DRM(vm_shm_close)(struct vm_area_struct *vma); +extern int DRM(mmap_dma)(struct file *filp, struct vm_area_struct *vma); +extern int DRM(mmap)(struct file *filp, struct vm_area_struct *vma); +extern unsigned int DRM(poll)(struct file *filp, struct poll_table_struct *wait); +extern ssize_t DRM(read)(struct file *filp, char *buf, size_t count, loff_t *off); - if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) { - vma->vm_flags &= (VM_READ | VM_MAYREAD); -#if defined(__i386__) || defined(__x86_64__) - pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW; -#else - /* Ye gads this is ugly. With more thought - we could move this up higher and use - `protection_map' instead. */ - vma->vm_page_prot = __pgprot(pte_val(pte_wrprotect( - __pte(pgprot_val(vma->vm_page_prot))))); -#endif - } +/*@}*/ - switch (map->type) { - case _DRM_AGP: -#if __REALLY_HAVE_AGP - if (dev->agp->cant_use_aperture) { - /* - * On some platforms we can't talk to bus dma address from the CPU, so for - * memory of type DRM_AGP, we'll deal with sorting out the real physical - * pages and mappings in nopage() - */ -#if defined(__powerpc__) - pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; -#endif - vma->vm_ops = &DRM(vm_ops); - break; - } -#endif - /* fall through to _DRM_FRAME_BUFFER... */ - case _DRM_FRAME_BUFFER: - case _DRM_REGISTERS: - if (VM_OFFSET(vma) >= __pa(high_memory)) { -#if defined(__i386__) || defined(__x86_64__) - if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) { - pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; - pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT; - } -#elif defined(__powerpc__) - pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE | _PAGE_GUARDED; -#endif - vma->vm_flags |= VM_IO; /* not in core dump */ - } -#if defined(__ia64__) - if (map->type != _DRM_AGP) - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); -#endif - offset = DRIVER_GET_REG_OFS(); -#ifdef __sparc__ - if (io_remap_page_range(DRM_RPR_ARG(vma) vma->vm_start, - VM_OFFSET(vma) + offset, - vma->vm_end - vma->vm_start, - vma->vm_page_prot, 0)) -#else - if (remap_page_range(DRM_RPR_ARG(vma) vma->vm_start, - VM_OFFSET(vma) + offset, - vma->vm_end - vma->vm_start, - vma->vm_page_prot)) -#endif - return -EAGAIN; - DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx," - " offset = 0x%lx\n", - map->type, - vma->vm_start, vma->vm_end, VM_OFFSET(vma) + offset); - vma->vm_ops = &DRM(vm_ops); - break; - case _DRM_SHM: - vma->vm_ops = &DRM(vm_shm_ops); - vma->vm_private_data = (void *)map; - /* Don't let this area swap. Change when - DRM_KERNEL advisory is supported. */ -#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */ - vma->vm_flags |= VM_LOCKED; -#else - vma->vm_flags |= VM_RESERVED; -#endif - break; - case _DRM_SCATTER_GATHER: - vma->vm_ops = &DRM(vm_sg_ops); - vma->vm_private_data = (void *)map; -#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */ - vma->vm_flags |= VM_LOCKED; -#else - vma->vm_flags |= VM_RESERVED; -#endif - break; - default: - return -EINVAL; /* This should never happen. */ - } -#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */ - vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */ -#else - vma->vm_flags |= VM_RESERVED; /* Don't swap */ -#endif - vma->vm_file = filp; /* Needed for drm_vm_open() */ - DRM(vm_open)(vma); - return 0; -} +#endif /* !_DRM_VM_H_ */ diff --git a/linux/drm_vm_tmp.h b/linux/drm_vm_tmp.h new file mode 100644 index 000000000..34bb8531e --- /dev/null +++ b/linux/drm_vm_tmp.h @@ -0,0 +1,608 @@ +/** + * \file drm_vm_tmp.h + * Memory mapping for DRM + * + * \author Rickard E. (Rik) Faith <faith@valinux.com> + * \author Gareth Hughes <gareth@valinux.com> + */ + +/* + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#define __NO_VERSION__ +#include "drmP.h" + +/** AGP virtual memory operations */ +struct vm_operations_struct DRM(vm_ops) = { + .nopage = DRM(vm_nopage), + .open = DRM(vm_open), + .close = DRM(vm_close), +}; + +/** Shared virtual memory operations */ +struct vm_operations_struct DRM(vm_shm_ops) = { + .nopage = DRM(vm_shm_nopage), + .open = DRM(vm_open), + .close = DRM(vm_shm_close), +}; + +/** DMA virtual memory operations */ +struct vm_operations_struct DRM(vm_dma_ops) = { + .nopage = DRM(vm_dma_nopage), + .open = DRM(vm_open), + .close = DRM(vm_close), +}; + +/** Scatter-gather virtual memory operations */ +struct vm_operations_struct DRM(vm_sg_ops) = { + .nopage = DRM(vm_sg_nopage), + .open = DRM(vm_open), + .close = DRM(vm_close), +}; + +/** + * \c nopage method for AGP virtual memory. + * + * \param vma virtual memory area. + * \param address access address. + * \param write_access sharing. + * \return pointer to the page structure. + * + * Find the right map and if it's AGP memory find the real physical page to + * map, get the page, increment the use count and return it. + */ +struct page *DRM(vm_nopage)(struct vm_area_struct *vma, + unsigned long address, + int write_access) +{ +#if __REALLY_HAVE_AGP + drm_file_t *priv = vma->vm_file->private_data; + drm_device_t *dev = priv->dev; + drm_map_t *map = NULL; + drm_map_list_t *r_list; + struct list_head *list; + + /* + * Find the right map + */ + + if(!dev->agp || !dev->agp->cant_use_aperture) goto vm_nopage_error; + + list_for_each(list, &dev->maplist->head) { + r_list = list_entry(list, drm_map_list_t, head); + map = r_list->map; + if (!map) continue; + if (map->offset == VM_OFFSET(vma)) break; + } + + if (map && map->type == _DRM_AGP) { + unsigned long offset = address - vma->vm_start; + unsigned long baddr = VM_OFFSET(vma) + offset; + struct drm_agp_mem *agpmem; + struct page *page; + +#if __alpha__ + /* + * Adjust to a bus-relative address + */ + baddr -= dev->hose->mem_space->start; +#endif + + /* + * It's AGP memory - find the real physical page to map + */ + for(agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) { + if (agpmem->bound <= baddr && + agpmem->bound + agpmem->pages * PAGE_SIZE > baddr) + break; + } + + if (!agpmem) goto vm_nopage_error; + + /* + * Get the page, inc the use count, and return it + */ + offset = (baddr - agpmem->bound) >> PAGE_SHIFT; + page = virt_to_page(__va(agpmem->memory->memory[offset])); + get_page(page); + + DRM_DEBUG("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n", + baddr, __va(agpmem->memory->memory[offset]), offset, + atomic_read(&page->count)); + + return page; + } +vm_nopage_error: +#endif /* __REALLY_HAVE_AGP */ + + return NOPAGE_SIGBUS; /* Disallow mremap */ +} + +/** + * \c nopage method for shared virtual memory. + * + * \param vma virtual memory area. + * \param address access address. + * \param write_access sharing. + * \return pointer to the page structure. + * + * Get the the mapping, find the real physical page to map, get the page, and + * return it. + */ +struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma, + unsigned long address, + int write_access) +{ + drm_map_t *map = (drm_map_t *)vma->vm_private_data; + unsigned long offset; + unsigned long i; + struct page *page; + + if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */ + if (!map) return NOPAGE_OOM; /* Nothing allocated */ + + offset = address - vma->vm_start; + i = (unsigned long)map->handle + offset; + page = vmalloc_to_page((void *)i); + if (!page) + return NOPAGE_OOM; + get_page(page); + + DRM_DEBUG("shm_nopage 0x%lx\n", address); + return page; +} + + +/** + * \c close method for shared virtual memory. + * + * \param vma virtual memory area. + * + * Deletes map information if we are the last + * person to close a mapping and it's not in the global maplist. + */ +void DRM(vm_shm_close)(struct vm_area_struct *vma) +{ + drm_file_t *priv = vma->vm_file->private_data; + drm_device_t *dev = priv->dev; + drm_vma_entry_t *pt, *prev, *next; + drm_map_t *map; + drm_map_list_t *r_list; + struct list_head *list; + int found_maps = 0; + + DRM_DEBUG("0x%08lx,0x%08lx\n", + vma->vm_start, vma->vm_end - vma->vm_start); + atomic_dec(&dev->vma_count); + + map = vma->vm_private_data; + + down(&dev->struct_sem); + for (pt = dev->vmalist, prev = NULL; pt; pt = next) { + next = pt->next; + if (pt->vma->vm_private_data == map) found_maps++; + if (pt->vma == vma) { + if (prev) { + prev->next = pt->next; + } else { + dev->vmalist = pt->next; + } + DRM(free)(pt, sizeof(*pt), DRM_MEM_VMAS); + } else { + prev = pt; + } + } + /* We were the only map that was found */ + if(found_maps == 1 && + map->flags & _DRM_REMOVABLE) { + /* Check to see if we are in the maplist, if we are not, then + * we delete this mappings information. + */ + found_maps = 0; + list = &dev->maplist->head; + list_for_each(list, &dev->maplist->head) { + r_list = list_entry(list, drm_map_list_t, head); + if (r_list->map == map) found_maps++; + } + + if(!found_maps) { + switch (map->type) { + case _DRM_REGISTERS: + case _DRM_FRAME_BUFFER: +#if __REALLY_HAVE_MTRR + if (map->mtrr >= 0) { + int retcode; + retcode = mtrr_del(map->mtrr, + map->offset, + map->size); + DRM_DEBUG("mtrr_del = %d\n", retcode); + } +#endif + DRM(ioremapfree)(map->handle, map->size, dev); + break; + case _DRM_SHM: + vfree(map->handle); + break; + case _DRM_AGP: + case _DRM_SCATTER_GATHER: + break; + } + DRM(free)(map, sizeof(*map), DRM_MEM_MAPS); + } + } + up(&dev->struct_sem); +} + +/** + * \c nopage method for DMA virtual memory. + * + * \param vma virtual memory area. + * \param address access address. + * \param write_access sharing. + * \return pointer to the page structure. + * + * Determine the page number from the page offset and get it from drm_device_dma::pagelist. + */ +struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma, + unsigned long address, + int write_access) +{ + drm_file_t *priv = vma->vm_file->private_data; + drm_device_t *dev = priv->dev; + drm_device_dma_t *dma = dev->dma; + unsigned long offset; + unsigned long page_nr; + struct page *page; + + if (!dma) return NOPAGE_SIGBUS; /* Error */ + if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */ + if (!dma->pagelist) return NOPAGE_OOM ; /* Nothing allocated */ + + offset = address - vma->vm_start; /* vm_[pg]off[set] should be 0 */ + page_nr = offset >> PAGE_SHIFT; + page = virt_to_page((dma->pagelist[page_nr] + + (offset & (~PAGE_MASK)))); + + get_page(page); + + DRM_DEBUG("dma_nopage 0x%lx (page %lu)\n", address, page_nr); + return page; +} + +/** + * \c nopage method for scatter-gather virtual memory. + * + * \param vma virtual memory area. + * \param address access address. + * \param write_access sharing. + * \return pointer to the page structure. + * + * Determine the map offset from the page offset and get it from drm_sg_mem::pagelist. + */ +struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma, + unsigned long address, + int write_access) +{ + drm_map_t *map = (drm_map_t *)vma->vm_private_data; + drm_file_t *priv = vma->vm_file->private_data; + drm_device_t *dev = priv->dev; + drm_sg_mem_t *entry = dev->sg; + unsigned long offset; + unsigned long map_offset; + unsigned long page_offset; + struct page *page; + + if (!entry) return NOPAGE_SIGBUS; /* Error */ + if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */ + if (!entry->pagelist) return NOPAGE_OOM ; /* Nothing allocated */ + + + offset = address - vma->vm_start; + map_offset = map->offset - dev->sg->handle; + page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT); + page = entry->pagelist[page_offset]; + get_page(page); + + return page; +} + +/** + * \c open method for shared virtual memory. + * + * \param vma virtual memory area. + * + * Create a new drm_vma_entry structure as the \p vma private data entry and + * add it to drm_device::vmalist. + */ +void DRM(vm_open)(struct vm_area_struct *vma) +{ + drm_file_t *priv = vma->vm_file->private_data; + drm_device_t *dev = priv->dev; + drm_vma_entry_t *vma_entry; + + DRM_DEBUG("0x%08lx,0x%08lx\n", + vma->vm_start, vma->vm_end - vma->vm_start); + atomic_inc(&dev->vma_count); + + vma_entry = DRM(alloc)(sizeof(*vma_entry), DRM_MEM_VMAS); + if (vma_entry) { + down(&dev->struct_sem); + vma_entry->vma = vma; + vma_entry->next = dev->vmalist; + vma_entry->pid = current->pid; + dev->vmalist = vma_entry; + up(&dev->struct_sem); + } +} + +/** + * \c close method for all virtual memory types. + * + * \param vma virtual memory area. + * + * Search the \p vma private data entry in drm_device::vmalist, unlink it, and + * free it. + */ +void DRM(vm_close)(struct vm_area_struct *vma) +{ + drm_file_t *priv = vma->vm_file->private_data; + drm_device_t *dev = priv->dev; + drm_vma_entry_t *pt, *prev; + + DRM_DEBUG("0x%08lx,0x%08lx\n", + vma->vm_start, vma->vm_end - vma->vm_start); + atomic_dec(&dev->vma_count); + + down(&dev->struct_sem); + for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) { + if (pt->vma == vma) { + if (prev) { + prev->next = pt->next; + } else { + dev->vmalist = pt->next; + } + DRM(free)(pt, sizeof(*pt), DRM_MEM_VMAS); + break; + } + } + up(&dev->struct_sem); +} + +/** + * mmap DMA memory. + * + * \param filp file pointer. + * \param vma virtual memory area. + * \return zero on success or a negative number on failure. + * + * Sets the virtual memory area operations structure to vm_dma_ops, the file + * pointer, and calls vm_open(). + */ +int DRM(mmap_dma)(struct file *filp, struct vm_area_struct *vma) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev; + drm_device_dma_t *dma; + unsigned long length = vma->vm_end - vma->vm_start; + + lock_kernel(); + dev = priv->dev; + dma = dev->dma; + DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", + vma->vm_start, vma->vm_end, VM_OFFSET(vma)); + + /* Length must match exact page count */ + if (!dma || (length >> PAGE_SHIFT) != dma->page_count) { + unlock_kernel(); + return -EINVAL; + } + unlock_kernel(); + + vma->vm_ops = &DRM(vm_dma_ops); + +#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */ + vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */ +#else + vma->vm_flags |= VM_RESERVED; /* Don't swap */ +#endif + + vma->vm_file = filp; /* Needed for drm_vm_open() */ + DRM(vm_open)(vma); + return 0; +} + +#ifndef DRIVER_GET_MAP_OFS +#define DRIVER_GET_MAP_OFS() (map->offset) +#endif + +#ifndef DRIVER_GET_REG_OFS +#ifdef __alpha__ +#define DRIVER_GET_REG_OFS() (dev->hose->dense_mem_base - \ + dev->hose->mem_space->start) +#else +#define DRIVER_GET_REG_OFS() 0 +#endif +#endif + +/** + * mmap DMA memory. + * + * \param filp file pointer. + * \param vma virtual memory area. + * \return zero on success or a negative number on failure. + * + * If the virtual memory area has no offset associated with it then it's a DMA + * area, so calls mmap_dma(). Otherwise searches the map in drm_device::maplist, + * checks that the restricted flag is not set, sets the virtual memory operations + * according to the mapping type and remaps the pages. Finally sets the file + * pointer and calls vm_open(). + */ +int DRM(mmap)(struct file *filp, struct vm_area_struct *vma) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_map_t *map = NULL; + drm_map_list_t *r_list; + unsigned long offset = 0; + struct list_head *list; + + DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", + vma->vm_start, vma->vm_end, VM_OFFSET(vma)); + + if ( !priv->authenticated ) return -EACCES; + + /* We check for "dma". On Apple's UniNorth, it's valid to have + * the AGP mapped at physical address 0 + * --BenH. + */ + if (!VM_OFFSET(vma) +#if __REALLY_HAVE_AGP + && (!dev->agp || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE) +#endif + ) + return DRM(mmap_dma)(filp, vma); + + /* A sequential search of a linked list is + fine here because: 1) there will only be + about 5-10 entries in the list and, 2) a + DRI client only has to do this mapping + once, so it doesn't have to be optimized + for performance, even if the list was a + bit longer. */ + list_for_each(list, &dev->maplist->head) { + unsigned long off; + + r_list = list_entry(list, drm_map_list_t, head); + map = r_list->map; + if (!map) continue; + off = DRIVER_GET_MAP_OFS(); + if (off == VM_OFFSET(vma)) break; + } + + if (!map || ((map->flags&_DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) + return -EPERM; + + /* Check for valid size. */ + if (map->size != vma->vm_end - vma->vm_start) return -EINVAL; + + if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) { + vma->vm_flags &= (VM_READ | VM_MAYREAD); +#if defined(__i386__) || defined(__x86_64__) + pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW; +#else + /* Ye gads this is ugly. With more thought + we could move this up higher and use + `protection_map' instead. */ + vma->vm_page_prot = __pgprot(pte_val(pte_wrprotect( + __pte(pgprot_val(vma->vm_page_prot))))); +#endif + } + + switch (map->type) { + case _DRM_AGP: +#if __REALLY_HAVE_AGP + if (dev->agp->cant_use_aperture) { + /* + * On some platforms we can't talk to bus dma address from the CPU, so for + * memory of type DRM_AGP, we'll deal with sorting out the real physical + * pages and mappings in nopage() + */ +#if defined(__powerpc__) + pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; +#endif + vma->vm_ops = &DRM(vm_ops); + break; + } +#endif + /* fall through to _DRM_FRAME_BUFFER... */ + case _DRM_FRAME_BUFFER: + case _DRM_REGISTERS: + if (VM_OFFSET(vma) >= __pa(high_memory)) { +#if defined(__i386__) || defined(__x86_64__) + if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) { + pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; + pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT; + } +#elif defined(__powerpc__) + pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE | _PAGE_GUARDED; +#endif + vma->vm_flags |= VM_IO; /* not in core dump */ + } +#if defined(__ia64__) + if (map->type != _DRM_AGP) + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); +#endif + offset = DRIVER_GET_REG_OFS(); +#ifdef __sparc__ + if (io_remap_page_range(DRM_RPR_ARG(vma) vma->vm_start, + VM_OFFSET(vma) + offset, + vma->vm_end - vma->vm_start, + vma->vm_page_prot, 0)) +#else + if (remap_page_range(DRM_RPR_ARG(vma) vma->vm_start, + VM_OFFSET(vma) + offset, + vma->vm_end - vma->vm_start, + vma->vm_page_prot)) +#endif + return -EAGAIN; + DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx," + " offset = 0x%lx\n", + map->type, + vma->vm_start, vma->vm_end, VM_OFFSET(vma) + offset); + vma->vm_ops = &DRM(vm_ops); + break; + case _DRM_SHM: + vma->vm_ops = &DRM(vm_shm_ops); + vma->vm_private_data = (void *)map; + /* Don't let this area swap. Change when + DRM_KERNEL advisory is supported. */ +#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */ + vma->vm_flags |= VM_LOCKED; +#else + vma->vm_flags |= VM_RESERVED; +#endif + break; + case _DRM_SCATTER_GATHER: + vma->vm_ops = &DRM(vm_sg_ops); + vma->vm_private_data = (void *)map; +#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */ + vma->vm_flags |= VM_LOCKED; +#else + vma->vm_flags |= VM_RESERVED; +#endif + break; + default: + return -EINVAL; /* This should never happen. */ + } +#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */ + vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */ +#else + vma->vm_flags |= VM_RESERVED; /* Don't swap */ +#endif + + vma->vm_file = filp; /* Needed for drm_vm_open() */ + DRM(vm_open)(vma); + return 0; +} diff --git a/linux/gamma_drv.c b/linux/gamma_drv.c index 7b10ed95c..0f82a252d 100644 --- a/linux/gamma_drv.c +++ b/linux/gamma_drv.c @@ -53,5 +53,5 @@ #include "gamma_lock.h" /* NOTE */ #include "drm_memory.h" #include "drm_proc.h" -#include "drm_vm.h" +#include "drm_vm_tmp.h" #include "drm_stub.h" diff --git a/linux/i810_drv.c b/linux/i810_drv.c index e7160eb96..09210198b 100644 --- a/linux/i810_drv.c +++ b/linux/i810_drv.c @@ -51,5 +51,5 @@ #include "drm_lock_tmp.h" #include "drm_memory.h" #include "drm_proc.h" -#include "drm_vm.h" +#include "drm_vm_tmp.h" #include "drm_stub.h" diff --git a/linux/i830_drv.c b/linux/i830_drv.c index dd2af6985..ccb51397d 100644 --- a/linux/i830_drv.c +++ b/linux/i830_drv.c @@ -53,5 +53,5 @@ #include "drm_lock_tmp.h" #include "drm_memory.h" #include "drm_proc.h" -#include "drm_vm.h" +#include "drm_vm_tmp.h" #include "drm_stub.h" diff --git a/linux/mga_drv.c b/linux/mga_drv.c index 9f7abab3b..2f118582f 100644 --- a/linux/mga_drv.c +++ b/linux/mga_drv.c @@ -48,5 +48,5 @@ #include "drm_lock_tmp.h" #include "drm_memory.h" #include "drm_proc.h" -#include "drm_vm.h" +#include "drm_vm_tmp.h" #include "drm_stub.h" diff --git a/linux/r128_drv.c b/linux/r128_drv.c index d2e37231d..28ad94bb7 100644 --- a/linux/r128_drv.c +++ b/linux/r128_drv.c @@ -50,6 +50,6 @@ #include "drm_lock_tmp.h" #include "drm_memory.h" #include "drm_proc.h" -#include "drm_vm.h" +#include "drm_vm_tmp.h" #include "drm_stub.h" #include "drm_sg_tmp.h" diff --git a/linux/radeon_drv.c b/linux/radeon_drv.c index 716f0ee40..e963ffb9f 100644 --- a/linux/radeon_drv.c +++ b/linux/radeon_drv.c @@ -51,6 +51,6 @@ #include "drm_lock_tmp.h" #include "drm_memory.h" #include "drm_proc.h" -#include "drm_vm.h" +#include "drm_vm_tmp.h" #include "drm_stub.h" #include "drm_sg_tmp.h" diff --git a/linux/sis_drv.c b/linux/sis_drv.c index 5aece8f96..32d632b2c 100644 --- a/linux/sis_drv.c +++ b/linux/sis_drv.c @@ -44,5 +44,5 @@ #include "drm_lock_tmp.h" #include "drm_memory.h" #include "drm_proc.h" -#include "drm_vm.h" +#include "drm_vm_tmp.h" #include "drm_stub.h" diff --git a/linux/tdfx_drv.c b/linux/tdfx_drv.c index 36fdb35e1..404ed6d59 100644 --- a/linux/tdfx_drv.c +++ b/linux/tdfx_drv.c @@ -88,5 +88,5 @@ static drm_pci_list_t DRM(idlist)[] = { #include "drm_lock_tmp.h" #include "drm_memory.h" #include "drm_proc.h" -#include "drm_vm.h" +#include "drm_vm_tmp.h" #include "drm_stub.h" |