From 93522f6d3ad6924cbf413915491e4f8228502d98 Mon Sep 17 00:00:00 2001 From: Jose Fonseca Date: Thu, 19 Jun 2003 00:09:52 +0000 Subject: Revert the janitorial - that works is now on the new branch newdrm-0-0-1-branch. --- linux-core/drmP.h | 106 +++++++- linux-core/drm_agpsupport.c | 451 +++++++++++++++++++++++++++++++++ linux-core/drm_bufs.c | 3 - linux-core/drm_drv.c | 68 +++-- linux-core/drm_memory.h | 12 +- linux-core/drm_memory_debug.h | 10 +- linux-core/drm_scatter.c | 229 +++++++++++++++++ linux-core/i810_drv.c | 2 +- linux-core/i830_drv.c | 2 +- linux-core/mga_drv.c | 2 +- linux-core/r128_drv.c | 4 +- linux-core/radeon_drv.c | 4 +- linux-core/sis_drv.c | 2 +- linux/drmP.h | 106 +++++++- linux/drm_agp.h | 111 --------- linux/drm_agp_tmp.h | 564 ------------------------------------------ linux/drm_agpsupport.h | 451 +++++++++++++++++++++++++++++++++ linux/drm_bufs.h | 3 - linux/drm_drv.h | 68 +++-- linux/drm_memory.h | 12 +- linux/drm_memory_debug.h | 10 +- linux/drm_scatter.h | 229 +++++++++++++++++ linux/drm_sg.h | 65 ----- linux/drm_sg_tmp.h | 309 ----------------------- linux/gamma_drv.c | 2 +- linux/i810_drv.c | 2 +- linux/i830_drv.c | 2 +- linux/mga_drv.c | 2 +- linux/r128_drv.c | 4 +- linux/radeon_drv.c | 4 +- linux/sis_drv.c | 2 +- 31 files changed, 1673 insertions(+), 1168 deletions(-) create mode 100644 linux-core/drm_agpsupport.c create mode 100644 linux-core/drm_scatter.c delete mode 100644 linux/drm_agp.h delete mode 100644 linux/drm_agp_tmp.h create mode 100644 linux/drm_agpsupport.h create mode 100644 linux/drm_scatter.h delete mode 100644 linux/drm_sg.h delete mode 100644 linux/drm_sg_tmp.h diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 3d352a6d..5626e4ff 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -66,6 +66,10 @@ #ifdef CONFIG_MTRR #include #endif +#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE) +#include +#include +#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,41) #define HAS_WORKQUEUE 0 #else @@ -82,10 +86,14 @@ #include "drm_os_linux.h" + /***********************************************************************/ /** \name DRM template customization defaults */ /*@{*/ +#ifndef __HAVE_AGP +#define __HAVE_AGP 0 +#endif #ifndef __HAVE_MTRR #define __HAVE_MTRR 0 #endif @@ -105,18 +113,14 @@ #define __HAVE_DMA_FREELIST 0 #endif +#define __REALLY_HAVE_AGP (__HAVE_AGP && (defined(CONFIG_AGP) || \ + defined(CONFIG_AGP_MODULE))) #define __REALLY_HAVE_MTRR (__HAVE_MTRR && defined(CONFIG_MTRR)) #define __REALLY_HAVE_SG (__HAVE_SG) /*@}*/ -typedef struct drm_device drm_device_t; - -#include "drm_agp.h" -#include "drm_sg.h" - - /***********************************************************************/ /** \name Begin the DRM... */ /*@{*/ @@ -571,6 +575,48 @@ typedef struct drm_device_dma { /*@}*/ } drm_device_dma_t; +#if __REALLY_HAVE_AGP +/** + * AGP memory entry. Stored as a doubly linked list. + */ +typedef struct drm_agp_mem { + unsigned long handle; /**< handle */ + agp_memory *memory; + unsigned long bound; /**< address */ + int pages; + struct drm_agp_mem *prev; /**< previous entry */ + struct drm_agp_mem *next; /**< next entry */ +} drm_agp_mem_t; + +/** + * AGP data. + * + * \sa DRM(agp_init)() and drm_device::agp. + */ +typedef struct drm_agp_head { + agp_kern_info agp_info; /**< AGP device information */ + drm_agp_mem_t *memory; /**< memory entries */ + unsigned long mode; /**< AGP mode */ + int enabled; /**< whether the AGP bus as been enabled */ + int acquired; /**< whether the AGP device has been acquired */ + unsigned long base; + int agp_mtrr; + int cant_use_aperture; + unsigned long page_mask; +} drm_agp_head_t; +#endif + +/** + * Scatter-gather memory. + */ +typedef struct drm_sg_mem { + unsigned long handle; + void *virtual; + int pages; + struct page **pagelist; + dma_addr_t *busaddr; +} drm_sg_mem_t; + typedef struct drm_sigdata { int context; drm_hw_lock_t *lock; @@ -600,7 +646,7 @@ typedef struct drm_vbl_sig { /** * DRM device structure. */ -struct drm_device { +typedef struct drm_device { const char *name; /**< Simple driver name */ char *unique; /**< Unique identifier: e.g., busid */ int unique_len; /**< Length of unique field */ @@ -711,12 +757,11 @@ struct drm_device { #endif #endif drm_sg_mem_t *sg; /**< Scatter gather memory */ - unsigned long *ctx_bitmap; /**< context bitmap */ void *dev_private; /**< device private data */ drm_sigdata_t sigdata; /**< For block_all_signals */ sigset_t sigmask; -}; +} drm_device_t; /******************************************************************/ @@ -785,10 +830,10 @@ extern void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, extern void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev); #if __REALLY_HAVE_AGP -extern agp_memory *DRM(agp_alloc)(int pages, u32 type); -extern int DRM(agp_free)(agp_memory *handle, int pages); -extern int DRM(agp_bind)(agp_memory *handle, unsigned int start); -extern int DRM(agp_unbind)(agp_memory *handle); +extern agp_memory *DRM(alloc_agp)(int pages, u32 type); +extern int DRM(free_agp)(agp_memory *handle, int pages); +extern int DRM(bind_agp)(agp_memory *handle, unsigned int start); +extern int DRM(unbind_agp)(agp_memory *handle); #endif /* Misc. IOCTL support (drm_ioctl.h) */ @@ -911,6 +956,32 @@ extern void DRM(dma_immediate_bh)( void *dev ); #endif /* __HAVE_DMA */ +#if __REALLY_HAVE_AGP + /* AGP/GART support (drm_agpsupport.h) */ +extern drm_agp_head_t *DRM(agp_init)(void); +extern void DRM(agp_uninit)(void); +extern int DRM(agp_acquire)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern void DRM(agp_do_release)(void); +extern int DRM(agp_release)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int DRM(agp_enable)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int DRM(agp_info)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int DRM(agp_alloc)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int DRM(agp_free)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int DRM(agp_unbind)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int DRM(agp_bind)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern agp_memory *DRM(agp_allocate_memory)(size_t pages, u32 type); +extern int DRM(agp_free_memory)(agp_memory *handle); +extern int DRM(agp_bind_memory)(agp_memory *handle, off_t start); +extern int DRM(agp_unbind_memory)(agp_memory *handle); +#endif /* Stub support (drm_stub.h) */ int DRM(stub_register)(const char *name, @@ -927,6 +998,15 @@ extern int DRM(proc_cleanup)(int minor, struct proc_dir_entry *root, struct proc_dir_entry *dev_root); +#if __HAVE_SG + /* Scatter Gather Support (drm_scatter.h) */ +extern void DRM(sg_cleanup)(drm_sg_mem_t *entry); +extern int DRM(sg_alloc)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int DRM(sg_free)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +#endif + /* ATI PCIGART support (ati_pcigart.h) */ extern int DRM(ati_pcigart_init)(drm_device_t *dev, unsigned long *addr, diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c new file mode 100644 index 00000000..81850593 --- /dev/null +++ b/linux-core/drm_agpsupport.c @@ -0,0 +1,451 @@ +/** + * \file drm_agpsupport.h + * DRM support for AGP/GART backend + * + * \author Rickard E. (Rik) Faith + * \author Gareth Hughes + */ + +/* + * 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" +#include + +#if __REALLY_HAVE_AGP + + +#define DRM_AGP_GET (drm_agp_t *)inter_module_get("drm_agp") +#define DRM_AGP_PUT inter_module_put("drm_agp") + +/** + * Pointer to the drm_agp_t structure made available by the agpgart module. + */ +static const drm_agp_t *drm_agp = NULL; + +/** + * AGP information ioctl. + * + * \param inode device inode. + * \param filp file pointer. + * \param cmd command. + * \param arg pointer to a (output) drm_agp_info structure. + * \return zero on success or a negative number on failure. + * + * Verifies the AGP device has been initialized and acquired and fills in the + * drm_agp_info structure with the information in drm_agp_head::agp_info. + */ +int DRM(agp_info)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + agp_kern_info *kern; + drm_agp_info_t info; + + if (!dev->agp || !dev->agp->acquired || !drm_agp->copy_info) + return -EINVAL; + + kern = &dev->agp->agp_info; + info.agp_version_major = kern->version.major; + info.agp_version_minor = kern->version.minor; + info.mode = kern->mode; + info.aperture_base = kern->aper_base; + info.aperture_size = kern->aper_size * 1024 * 1024; + info.memory_allowed = kern->max_memory << PAGE_SHIFT; + info.memory_used = kern->current_memory << PAGE_SHIFT; + info.id_vendor = kern->device->vendor; + info.id_device = kern->device->device; + + if (copy_to_user((drm_agp_info_t *)arg, &info, sizeof(info))) + return -EFAULT; + return 0; +} + +/** + * Acquire the AGP device (ioctl). + * + * \param inode device inode. + * \param filp file pointer. + * \param cmd command. + * \param arg user argument. + * \return zero on success or a negative number on failure. + * + * Verifies the AGP device hasn't been acquired before and calls + * drm_agp->acquire(). + */ +int DRM(agp_acquire)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + int retcode; + + if (!dev->agp || dev->agp->acquired || !drm_agp->acquire) + return -EINVAL; + if ((retcode = drm_agp->acquire())) return retcode; + dev->agp->acquired = 1; + return 0; +} + +/** + * Release the AGP device (ioctl). + * + * \param inode device inode. + * \param filp file pointer. + * \param cmd command. + * \param arg user argument. + * \return zero on success or a negative number on failure. + * + * Verifies the AGP device has been acquired and calls drm_agp->release(). + */ +int DRM(agp_release)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + + if (!dev->agp || !dev->agp->acquired || !drm_agp->release) + return -EINVAL; + drm_agp->release(); + dev->agp->acquired = 0; + return 0; + +} + +/** + * Release the AGP device. + * + * Calls drm_agp->release(). + */ +void DRM(agp_do_release)(void) +{ + if (drm_agp->release) drm_agp->release(); +} + +/** + * Enable the AGP bus. + * + * \param inode device inode. + * \param filp file pointer. + * \param cmd command. + * \param arg pointer to a drm_agp_mode structure. + * \return zero on success or a negative number on failure. + * + * Verifies the AGP device has been acquired but not enabled, and calls + * drm_agp->enable(). + */ +int DRM(agp_enable)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_agp_mode_t mode; + + if (!dev->agp || !dev->agp->acquired || !drm_agp->enable) + return -EINVAL; + + if (copy_from_user(&mode, (drm_agp_mode_t *)arg, sizeof(mode))) + return -EFAULT; + + dev->agp->mode = mode.mode; + drm_agp->enable(mode.mode); + dev->agp->base = dev->agp->agp_info.aper_base; + dev->agp->enabled = 1; + return 0; +} + +/** + * Allocate AGP memory. + * + * \param inode device inode. + * \param filp file pointer. + * \param cmd command. + * \param arg pointer to a drm_agp_buffer structure. + * \return zero on success or a negative number on failure. + * + * Verifies the AGP device is present and has been acquired, allocates the + * memory via alloc_agp() and creates a drm_agp_mem entry for it. + */ +int DRM(agp_alloc)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_agp_buffer_t request; + drm_agp_mem_t *entry; + agp_memory *memory; + unsigned long pages; + u32 type; + + if (!dev->agp || !dev->agp->acquired) return -EINVAL; + if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request))) + return -EFAULT; + if (!(entry = DRM(alloc)(sizeof(*entry), DRM_MEM_AGPLISTS))) + return -ENOMEM; + + memset(entry, 0, sizeof(*entry)); + + pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE; + type = (u32) request.type; + + if (!(memory = DRM(alloc_agp)(pages, type))) { + DRM(free)(entry, sizeof(*entry), DRM_MEM_AGPLISTS); + return -ENOMEM; + } + + entry->handle = (unsigned long)memory->key; + entry->memory = memory; + entry->bound = 0; + entry->pages = pages; + entry->prev = NULL; + entry->next = dev->agp->memory; + if (dev->agp->memory) dev->agp->memory->prev = entry; + dev->agp->memory = entry; + + request.handle = entry->handle; + request.physical = memory->physical; + + if (copy_to_user((drm_agp_buffer_t *)arg, &request, sizeof(request))) { + dev->agp->memory = entry->next; + dev->agp->memory->prev = NULL; + DRM(free_agp)(memory, pages); + DRM(free)(entry, sizeof(*entry), DRM_MEM_AGPLISTS); + return -EFAULT; + } + return 0; +} + +/** + * Search for the AGP memory entry associated with a handle. + * + * \param dev DRM device structure. + * \param handle AGP memory handle. + * \return pointer to the drm_agp_mem structure associated with \p handle. + * + * Walks through drm_agp_head::memory until finding a matching handle. + */ +static drm_agp_mem_t *DRM(agp_lookup_entry)(drm_device_t *dev, + unsigned long handle) +{ + drm_agp_mem_t *entry; + + for (entry = dev->agp->memory; entry; entry = entry->next) { + if (entry->handle == handle) return entry; + } + return NULL; +} + +/** + * Unbind AGP memory from the GATT (ioctl). + * + * \param inode device inode. + * \param filp file pointer. + * \param cmd command. + * \param arg pointer to a drm_agp_binding structure. + * \return zero on success or a negative number on failure. + * + * Verifies the AGP device is present and acquired, looks-up the AGP memory + * entry and passes it to the unbind_agp() function. + */ +int DRM(agp_unbind)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_agp_binding_t request; + drm_agp_mem_t *entry; + int ret; + + if (!dev->agp || !dev->agp->acquired) return -EINVAL; + if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request))) + return -EFAULT; + if (!(entry = DRM(agp_lookup_entry)(dev, request.handle))) + return -EINVAL; + if (!entry->bound) return -EINVAL; + ret = DRM(unbind_agp)(entry->memory); + if (ret == 0) + entry->bound = 0; + return ret; +} + +/** + * Bind AGP memory into the GATT (ioctl) + * + * \param inode device inode. + * \param filp file pointer. + * \param cmd command. + * \param arg pointer to a drm_agp_binding structure. + * \return zero on success or a negative number on failure. + * + * Verifies the AGP device is present and has been acquired and that no memory + * is currently bound into the GATT. Looks-up the AGP memory entry and passes + * it to bind_agp() function. + */ +int DRM(agp_bind)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_agp_binding_t request; + drm_agp_mem_t *entry; + int retcode; + int page; + + if (!dev->agp || !dev->agp->acquired || !drm_agp->bind_memory) + return -EINVAL; + if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request))) + return -EFAULT; + if (!(entry = DRM(agp_lookup_entry)(dev, request.handle))) + return -EINVAL; + if (entry->bound) return -EINVAL; + page = (request.offset + PAGE_SIZE - 1) / PAGE_SIZE; + if ((retcode = DRM(bind_agp)(entry->memory, page))) return retcode; + entry->bound = dev->agp->base + (page << PAGE_SHIFT); + DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n", + dev->agp->base, entry->bound); + return 0; +} + +/** + * Free AGP memory (ioctl). + * + * \param inode device inode. + * \param filp file pointer. + * \param cmd command. + * \param arg pointer to a drm_agp_buffer structure. + * \return zero on success or a negative number on failure. + * + * Verifies the AGP device is present and has been acquired and looks up the + * AGP memory entry. If the memory it's currently bound, unbind it via + * unbind_agp(). Frees it via free_agp() as well as the entry itself + * and unlinks from the doubly linked list it's inserted in. + */ +int DRM(agp_free)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_agp_buffer_t request; + drm_agp_mem_t *entry; + + if (!dev->agp || !dev->agp->acquired) return -EINVAL; + if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request))) + return -EFAULT; + if (!(entry = DRM(agp_lookup_entry)(dev, request.handle))) + return -EINVAL; + if (entry->bound) DRM(unbind_agp)(entry->memory); + + if (entry->prev) entry->prev->next = entry->next; + else dev->agp->memory = entry->next; + if (entry->next) entry->next->prev = entry->prev; + DRM(free_agp)(entry->memory, entry->pages); + DRM(free)(entry, sizeof(*entry), DRM_MEM_AGPLISTS); + return 0; +} + +/** + * Initialize the AGP resources. + * + * \return pointer to a drm_agp_head structure. + * + * Gets the drm_agp_t structure which is made available by the agpgart module + * via the inter_module_* functions. Creates and initializes a drm_agp_head + * structure. + */ +drm_agp_head_t *DRM(agp_init)(void) +{ + drm_agp_head_t *head = NULL; + + drm_agp = DRM_AGP_GET; + if (drm_agp) { + if (!(head = DRM(alloc)(sizeof(*head), DRM_MEM_AGPLISTS))) + return NULL; + memset((void *)head, 0, sizeof(*head)); + drm_agp->copy_info(&head->agp_info); + if (head->agp_info.chipset == NOT_SUPPORTED) { + DRM(free)(head, sizeof(*head), DRM_MEM_AGPLISTS); + return NULL; + } + head->memory = NULL; +#if LINUX_VERSION_CODE <= 0x020408 + head->cant_use_aperture = 0; + head->page_mask = ~(0xfff); +#else + head->cant_use_aperture = head->agp_info.cant_use_aperture; + head->page_mask = head->agp_info.page_mask; +#endif + + DRM_INFO("AGP %d.%d aperture @ 0x%08lx %ZuMB\n", + head->agp_info.version.major, + head->agp_info.version.minor, + head->agp_info.aper_base, + head->agp_info.aper_size); + } + return head; +} + +/** + * Free the AGP resources. + * + * Releases the pointer in ::drm_agp. + */ +void DRM(agp_uninit)(void) +{ + DRM_AGP_PUT; + drm_agp = NULL; +} + +/** Calls drm_agp->allocate_memory() */ +agp_memory *DRM(agp_allocate_memory)(size_t pages, u32 type) +{ + if (!drm_agp->allocate_memory) return NULL; + return drm_agp->allocate_memory(pages, type); +} + +/** Calls drm_agp->free_memory() */ +int DRM(agp_free_memory)(agp_memory *handle) +{ + if (!handle || !drm_agp->free_memory) return 0; + drm_agp->free_memory(handle); + return 1; +} + +/** Calls drm_agp->bind_memory() */ +int DRM(agp_bind_memory)(agp_memory *handle, off_t start) +{ + if (!handle || !drm_agp->bind_memory) return -EINVAL; + return drm_agp->bind_memory(handle, start); +} + +/** Calls drm_agp->unbind_memory() */ +int DRM(agp_unbind_memory)(agp_memory *handle) +{ + if (!handle || !drm_agp->unbind_memory) return -EINVAL; + return drm_agp->unbind_memory(handle); +} + +#endif /* __REALLY_HAVE_AGP */ diff --git a/linux-core/drm_bufs.c b/linux-core/drm_bufs.c index f42fabef..77573709 100644 --- a/linux-core/drm_bufs.c +++ b/linux-core/drm_bufs.c @@ -174,8 +174,6 @@ int DRM(addmap)( struct inode *inode, struct file *filp, map->mtrr = dev->agp->agp_mtrr; /* for getmap */ break; #endif - -#if __HAVE_SG case _DRM_SCATTER_GATHER: if (!dev->sg) { DRM(free)(map, sizeof(*map), DRM_MEM_MAPS); @@ -183,7 +181,6 @@ int DRM(addmap)( struct inode *inode, struct file *filp, } map->offset += dev->sg->handle; break; -#endif default: DRM(free)( map, sizeof(*map), DRM_MEM_MAPS ); diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index 5a4ab36e..90c2d18b 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -225,19 +225,19 @@ static drm_ioctl_desc_t DRM(ioctls)[] = { #endif #if __REALLY_HAVE_AGP - [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { DRM(agp_acquire_ioctl), 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { DRM(agp_release_ioctl), 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { DRM(agp_enable_ioctl), 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { DRM(agp_info_ioctl), 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { DRM(agp_alloc_ioctl), 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { DRM(agp_free_ioctl), 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { DRM(agp_bind_ioctl), 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { DRM(agp_unbind_ioctl), 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { DRM(agp_acquire), 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { DRM(agp_release), 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { DRM(agp_enable), 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { DRM(agp_info), 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { DRM(agp_alloc), 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { DRM(agp_free), 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { DRM(agp_bind), 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { DRM(agp_unbind), 1, 1 }, #endif #if __HAVE_SG - [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = { DRM(sg_alloc_ioctl), 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { DRM(sg_free_ioctl), 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = { DRM(sg_alloc), 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { DRM(sg_free), 1, 1 }, #endif #if __HAVE_VBL_IRQ @@ -416,6 +416,29 @@ static int DRM(takedown)( drm_device_t *dev ) dev->magiclist[i].head = dev->magiclist[i].tail = NULL; } +#if __REALLY_HAVE_AGP + /* Clear AGP information */ + if ( dev->agp ) { + drm_agp_mem_t *entry; + drm_agp_mem_t *nexte; + + /* Remove AGP resources, but leave dev->agp + intact until drv_cleanup is called. */ + for ( entry = dev->agp->memory ; entry ; entry = nexte ) { + nexte = entry->next; + if ( entry->bound ) DRM(unbind_agp)( entry->memory ); + DRM(free_agp)( entry->memory, entry->pages ); + DRM(free)( entry, sizeof(*entry), DRM_MEM_AGPLISTS ); + } + dev->agp->memory = NULL; + + if ( dev->agp->acquired ) DRM(agp_do_release)(); + + dev->agp->acquired = 0; + dev->agp->enabled = 0; + } +#endif + /* Clear vma list (only built for debugging) */ if ( dev->vmalist ) { for ( vma = dev->vmalist ; vma ; vma = vma_next ) { @@ -463,7 +486,10 @@ static int DRM(takedown)( drm_device_t *dev ) * isn't defined. */ #if __HAVE_SG - DRM(sg_cleanup)(dev); + if(dev->sg) { + DRM(sg_cleanup)(dev->sg); + dev->sg = NULL; + } #endif break; } @@ -592,10 +618,6 @@ static int __init drm_init( void ) DRM(mem_init)(); -#if __REALLY_HAVE_AGP - DRM(agp_init)(); -#endif - for (i = 0; i < DRM(numdevs); i++) { dev = &(DRM(device)[i]); memset( (void *)dev, 0, sizeof(*dev) ); @@ -608,9 +630,8 @@ static int __init drm_init( void ) dev->name = DRIVER_NAME; #if __REALLY_HAVE_AGP - DRM(agp_init_dev)( dev ); + dev->agp = DRM(agp_init)(); #if __MUST_HAVE_AGP - if ( dev->agp == NULL ) { DRM_ERROR( "Cannot initialize the agpgart module.\n" ); DRM(stub_unregister)(DRM(minor)[i]); @@ -618,12 +639,14 @@ static int __init drm_init( void ) return -ENOMEM; } #endif +#if __REALLY_HAVE_MTRR if (dev->agp) dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base, dev->agp->agp_info.aper_size*1024*1024, MTRR_TYPE_WRCOMB, 1 ); #endif +#endif #if __HAVE_CTX_BITMAP retcode = DRM(ctxbitmap_init)( dev ); @@ -689,14 +712,13 @@ static void __exit drm_cleanup( void ) DRM(takedown)( dev ); #if __REALLY_HAVE_AGP - DRM(agp_cleanup_dev)( dev ); + if ( dev->agp ) { + DRM(agp_uninit)(); + DRM(free)( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS ); + dev->agp = NULL; + } #endif } - -#if __REALLY_HAVE_AGP - DRM(agp_cleanup)(); -#endif - DRIVER_POSTCLEANUP(); kfree(DRM(minor)); kfree(DRM(device)); diff --git a/linux-core/drm_memory.h b/linux-core/drm_memory.h index 9999c213..2a969fcd 100644 --- a/linux-core/drm_memory.h +++ b/linux-core/drm_memory.h @@ -332,29 +332,27 @@ void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev) #if __REALLY_HAVE_AGP /** Wrapper around agp_allocate_memory() */ -agp_memory *DRM(agp_alloc)(int pages, u32 type) +agp_memory *DRM(alloc_agp)(int pages, u32 type) { return DRM(agp_allocate_memory)(pages, type); } /** Wrapper around agp_free_memory() */ -int DRM(agp_free)(agp_memory *handle, int pages) +int DRM(free_agp)(agp_memory *handle, int pages) { return DRM(agp_free_memory)(handle) ? 0 : -EINVAL; } /** Wrapper around agp_bind_memory() */ -int DRM(agp_bind)(agp_memory *handle, unsigned int start) +int DRM(bind_agp)(agp_memory *handle, unsigned int start) { return DRM(agp_bind_memory)(handle, start); } /** Wrapper around agp_unbind_memory() */ -int DRM(agp_unbind)(agp_memory *handle) +int DRM(unbind_agp)(agp_memory *handle) { return DRM(agp_unbind_memory)(handle); } -#endif /* __REALLY_HAVE_AGP */ - - +#endif /* agp */ #endif /* debug_memory */ diff --git a/linux-core/drm_memory_debug.h b/linux-core/drm_memory_debug.h index 91b42126..5cfff83a 100644 --- a/linux-core/drm_memory_debug.h +++ b/linux-core/drm_memory_debug.h @@ -1,5 +1,5 @@ /** - * \file drm_memory_debug.h + * \file drm_memory.h * Memory management wrappers for DRM. * * \author Rickard E. (Rik) Faith @@ -343,7 +343,7 @@ void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev) #if __REALLY_HAVE_AGP -agp_memory *DRM(agp_alloc)(int pages, u32 type) +agp_memory *DRM(alloc_agp)(int pages, u32 type) { agp_memory *handle; @@ -366,7 +366,7 @@ agp_memory *DRM(agp_alloc)(int pages, u32 type) return NULL; } -int DRM(agp_free)(agp_memory *handle, int pages) +int DRM(free_agp)(agp_memory *handle, int pages) { int alloc_count; int free_count; @@ -395,7 +395,7 @@ int DRM(agp_free)(agp_memory *handle, int pages) return retval; } -int DRM(agp_bind)(agp_memory *handle, unsigned int start) +int DRM(bind_agp)(agp_memory *handle, unsigned int start) { int retcode = -EINVAL; @@ -419,7 +419,7 @@ int DRM(agp_bind)(agp_memory *handle, unsigned int start) return retcode; } -int DRM(agp_unbind)(agp_memory *handle) +int DRM(unbind_agp)(agp_memory *handle) { int alloc_count; int free_count; diff --git a/linux-core/drm_scatter.c b/linux-core/drm_scatter.c new file mode 100644 index 00000000..45a30fc3 --- /dev/null +++ b/linux-core/drm_scatter.c @@ -0,0 +1,229 @@ +/** + * \file drm_scatter.h + * IOCTLs to manage scatter/gather memory + * + * \author Gareth Hughes + */ + +/* + * Created: Mon Dec 18 23:20:54 2000 by gareth@valinux.com + * + * 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 + * PRECISION INSIGHT 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 +#include +#include "drmP.h" + +#define DEBUG_SCATTER 0 + +void DRM(sg_cleanup)( drm_sg_mem_t *entry ) +{ + struct page *page; + int i; + + for ( i = 0 ; i < entry->pages ; i++ ) { + page = entry->pagelist[i]; + if ( page ) + ClearPageReserved( page ); + } + + vfree( entry->virtual ); + + DRM(free)( entry->busaddr, + entry->pages * sizeof(*entry->busaddr), + DRM_MEM_PAGES ); + DRM(free)( entry->pagelist, + entry->pages * sizeof(*entry->pagelist), + DRM_MEM_PAGES ); + DRM(free)( entry, + sizeof(*entry), + DRM_MEM_SGLISTS ); +} + +int DRM(sg_alloc)( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_scatter_gather_t request; + drm_sg_mem_t *entry; + unsigned long pages, i, j; + + DRM_DEBUG( "%s\n", __FUNCTION__ ); + + if ( dev->sg ) + return -EINVAL; + + if ( copy_from_user( &request, + (drm_scatter_gather_t *)arg, + sizeof(request) ) ) + return -EFAULT; + + entry = DRM(alloc)( sizeof(*entry), DRM_MEM_SGLISTS ); + if ( !entry ) + return -ENOMEM; + + memset( entry, 0, sizeof(*entry) ); + + pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE; + DRM_DEBUG( "sg size=%ld pages=%ld\n", request.size, pages ); + + entry->pages = pages; + entry->pagelist = DRM(alloc)( pages * sizeof(*entry->pagelist), + DRM_MEM_PAGES ); + if ( !entry->pagelist ) { + DRM(free)( entry, sizeof(*entry), DRM_MEM_SGLISTS ); + return -ENOMEM; + } + + memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist)); + + entry->busaddr = DRM(alloc)( pages * sizeof(*entry->busaddr), + DRM_MEM_PAGES ); + if ( !entry->busaddr ) { + DRM(free)( entry->pagelist, + entry->pages * sizeof(*entry->pagelist), + DRM_MEM_PAGES ); + DRM(free)( entry, + sizeof(*entry), + DRM_MEM_SGLISTS ); + return -ENOMEM; + } + memset( (void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr) ); + + entry->virtual = vmalloc_32( pages << PAGE_SHIFT ); + if ( !entry->virtual ) { + DRM(free)( entry->busaddr, + entry->pages * sizeof(*entry->busaddr), + DRM_MEM_PAGES ); + DRM(free)( entry->pagelist, + entry->pages * sizeof(*entry->pagelist), + DRM_MEM_PAGES ); + DRM(free)( entry, + sizeof(*entry), + DRM_MEM_SGLISTS ); + return -ENOMEM; + } + + /* This also forces the mapping of COW pages, so our page list + * will be valid. Please don't remove it... + */ + memset( entry->virtual, 0, pages << PAGE_SHIFT ); + + entry->handle = (unsigned long)entry->virtual; + + DRM_DEBUG( "sg alloc handle = %08lx\n", entry->handle ); + DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual ); + + for ( i = entry->handle, j = 0 ; j < pages ; i += PAGE_SIZE, j++ ) { + entry->pagelist[j] = vmalloc_to_page((void *)i); + if (!entry->pagelist[j]) + goto failed; + SetPageReserved(entry->pagelist[j]); + } + + request.handle = entry->handle; + + if ( copy_to_user( (drm_scatter_gather_t *)arg, + &request, + sizeof(request) ) ) { + DRM(sg_cleanup)( entry ); + return -EFAULT; + } + + dev->sg = entry; + +#if DEBUG_SCATTER + /* Verify that each page points to its virtual address, and vice + * versa. + */ + { + int error = 0; + + for ( i = 0 ; i < pages ; i++ ) { + unsigned long *tmp; + + tmp = page_address( entry->pagelist[i] ); + for ( j = 0 ; + j < PAGE_SIZE / sizeof(unsigned long) ; + j++, tmp++ ) { + *tmp = 0xcafebabe; + } + tmp = (unsigned long *)((u8 *)entry->virtual + + (PAGE_SIZE * i)); + for( j = 0 ; + j < PAGE_SIZE / sizeof(unsigned long) ; + j++, tmp++ ) { + if ( *tmp != 0xcafebabe && error == 0 ) { + error = 1; + DRM_ERROR( "Scatter allocation error, " + "pagelist does not match " + "virtual mapping\n" ); + } + } + tmp = page_address( entry->pagelist[i] ); + for(j = 0 ; + j < PAGE_SIZE / sizeof(unsigned long) ; + j++, tmp++) { + *tmp = 0; + } + } + if (error == 0) + DRM_ERROR( "Scatter allocation matches pagelist\n" ); + } +#endif + + return 0; + + failed: + DRM(sg_cleanup)( entry ); + return -ENOMEM; +} + +int DRM(sg_free)( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_scatter_gather_t request; + drm_sg_mem_t *entry; + + if ( copy_from_user( &request, + (drm_scatter_gather_t *)arg, + sizeof(request) ) ) + return -EFAULT; + + entry = dev->sg; + dev->sg = NULL; + + if ( !entry || entry->handle != request.handle ) + return -EINVAL; + + DRM_DEBUG( "sg free virtual = %p\n", entry->virtual ); + + DRM(sg_cleanup)( entry ); + + return 0; +} diff --git a/linux-core/i810_drv.c b/linux-core/i810_drv.c index 2b816fbf..0bc79386 100644 --- a/linux-core/i810_drv.c +++ b/linux-core/i810_drv.c @@ -37,7 +37,7 @@ #include "i810_drm.h" #include "i810_drv.h" -#include "drm_agp_tmp.h" +#include "drm_agpsupport.h" #include "drm_auth.h" #include "drm_bufs.h" #include "drm_context.h" diff --git a/linux-core/i830_drv.c b/linux-core/i830_drv.c index 496c41ee..0735c94d 100644 --- a/linux-core/i830_drv.c +++ b/linux-core/i830_drv.c @@ -39,7 +39,7 @@ #include "i830_drm.h" #include "i830_drv.h" -#include "drm_agp_tmp.h" +#include "drm_agpsupport.h" #include "drm_auth.h" #include "drm_bufs.h" #include "drm_context.h" diff --git a/linux-core/mga_drv.c b/linux-core/mga_drv.c index f438660c..f0d4935d 100644 --- a/linux-core/mga_drv.c +++ b/linux-core/mga_drv.c @@ -35,7 +35,7 @@ #include "drm.h" #include "mga_drm.h" #include "mga_drv.h" -#include "drm_agp_tmp.h" +#include "drm_agpsupport.h" #include "drm_auth.h" #include "drm_bufs.h" #include "drm_context.h" diff --git a/linux-core/r128_drv.c b/linux-core/r128_drv.c index 474c1418..e2e42690 100644 --- a/linux-core/r128_drv.c +++ b/linux-core/r128_drv.c @@ -37,7 +37,7 @@ #include "r128_drv.h" #include "ati_pcigart.h" -#include "drm_agp_tmp.h" +#include "drm_agpsupport.h" #include "drm_auth.h" #include "drm_bufs.h" #include "drm_context.h" @@ -52,4 +52,4 @@ #include "drm_proc.h" #include "drm_vm.h" #include "drm_stub.h" -#include "drm_sg_tmp.h" +#include "drm_scatter.h" diff --git a/linux-core/radeon_drv.c b/linux-core/radeon_drv.c index 1473e2ee..6152b8a5 100644 --- a/linux-core/radeon_drv.c +++ b/linux-core/radeon_drv.c @@ -38,7 +38,7 @@ #include "radeon_drv.h" #include "ati_pcigart.h" -#include "drm_agp_tmp.h" +#include "drm_agpsupport.h" #include "drm_auth.h" #include "drm_bufs.h" #include "drm_context.h" @@ -53,4 +53,4 @@ #include "drm_proc.h" #include "drm_vm.h" #include "drm_stub.h" -#include "drm_sg_tmp.h" +#include "drm_scatter.h" diff --git a/linux-core/sis_drv.c b/linux-core/sis_drv.c index 64d0754f..3dd075d3 100644 --- a/linux-core/sis_drv.c +++ b/linux-core/sis_drv.c @@ -32,7 +32,7 @@ #include "sis_drv.h" #include "drm_auth.h" -#include "drm_agp_tmp.h" +#include "drm_agpsupport.h" #include "drm_bufs.h" #include "drm_context.h" #include "drm_dma.h" diff --git a/linux/drmP.h b/linux/drmP.h index 3d352a6d..5626e4ff 100644 --- a/linux/drmP.h +++ b/linux/drmP.h @@ -66,6 +66,10 @@ #ifdef CONFIG_MTRR #include #endif +#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE) +#include +#include +#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,41) #define HAS_WORKQUEUE 0 #else @@ -82,10 +86,14 @@ #include "drm_os_linux.h" + /***********************************************************************/ /** \name DRM template customization defaults */ /*@{*/ +#ifndef __HAVE_AGP +#define __HAVE_AGP 0 +#endif #ifndef __HAVE_MTRR #define __HAVE_MTRR 0 #endif @@ -105,18 +113,14 @@ #define __HAVE_DMA_FREELIST 0 #endif +#define __REALLY_HAVE_AGP (__HAVE_AGP && (defined(CONFIG_AGP) || \ + defined(CONFIG_AGP_MODULE))) #define __REALLY_HAVE_MTRR (__HAVE_MTRR && defined(CONFIG_MTRR)) #define __REALLY_HAVE_SG (__HAVE_SG) /*@}*/ -typedef struct drm_device drm_device_t; - -#include "drm_agp.h" -#include "drm_sg.h" - - /***********************************************************************/ /** \name Begin the DRM... */ /*@{*/ @@ -571,6 +575,48 @@ typedef struct drm_device_dma { /*@}*/ } drm_device_dma_t; +#if __REALLY_HAVE_AGP +/** + * AGP memory entry. Stored as a doubly linked list. + */ +typedef struct drm_agp_mem { + unsigned long handle; /**< handle */ + agp_memory *memory; + unsigned long bound; /**< address */ + int pages; + struct drm_agp_mem *prev; /**< previous entry */ + struct drm_agp_mem *next; /**< next entry */ +} drm_agp_mem_t; + +/** + * AGP data. + * + * \sa DRM(agp_init)() and drm_device::agp. + */ +typedef struct drm_agp_head { + agp_kern_info agp_info; /**< AGP device information */ + drm_agp_mem_t *memory; /**< memory entries */ + unsigned long mode; /**< AGP mode */ + int enabled; /**< whether the AGP bus as been enabled */ + int acquired; /**< whether the AGP device has been acquired */ + unsigned long base; + int agp_mtrr; + int cant_use_aperture; + unsigned long page_mask; +} drm_agp_head_t; +#endif + +/** + * Scatter-gather memory. + */ +typedef struct drm_sg_mem { + unsigned long handle; + void *virtual; + int pages; + struct page **pagelist; + dma_addr_t *busaddr; +} drm_sg_mem_t; + typedef struct drm_sigdata { int context; drm_hw_lock_t *lock; @@ -600,7 +646,7 @@ typedef struct drm_vbl_sig { /** * DRM device structure. */ -struct drm_device { +typedef struct drm_device { const char *name; /**< Simple driver name */ char *unique; /**< Unique identifier: e.g., busid */ int unique_len; /**< Length of unique field */ @@ -711,12 +757,11 @@ struct drm_device { #endif #endif drm_sg_mem_t *sg; /**< Scatter gather memory */ - unsigned long *ctx_bitmap; /**< context bitmap */ void *dev_private; /**< device private data */ drm_sigdata_t sigdata; /**< For block_all_signals */ sigset_t sigmask; -}; +} drm_device_t; /******************************************************************/ @@ -785,10 +830,10 @@ extern void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, extern void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev); #if __REALLY_HAVE_AGP -extern agp_memory *DRM(agp_alloc)(int pages, u32 type); -extern int DRM(agp_free)(agp_memory *handle, int pages); -extern int DRM(agp_bind)(agp_memory *handle, unsigned int start); -extern int DRM(agp_unbind)(agp_memory *handle); +extern agp_memory *DRM(alloc_agp)(int pages, u32 type); +extern int DRM(free_agp)(agp_memory *handle, int pages); +extern int DRM(bind_agp)(agp_memory *handle, unsigned int start); +extern int DRM(unbind_agp)(agp_memory *handle); #endif /* Misc. IOCTL support (drm_ioctl.h) */ @@ -911,6 +956,32 @@ extern void DRM(dma_immediate_bh)( void *dev ); #endif /* __HAVE_DMA */ +#if __REALLY_HAVE_AGP + /* AGP/GART support (drm_agpsupport.h) */ +extern drm_agp_head_t *DRM(agp_init)(void); +extern void DRM(agp_uninit)(void); +extern int DRM(agp_acquire)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern void DRM(agp_do_release)(void); +extern int DRM(agp_release)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int DRM(agp_enable)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int DRM(agp_info)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int DRM(agp_alloc)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int DRM(agp_free)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int DRM(agp_unbind)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int DRM(agp_bind)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern agp_memory *DRM(agp_allocate_memory)(size_t pages, u32 type); +extern int DRM(agp_free_memory)(agp_memory *handle); +extern int DRM(agp_bind_memory)(agp_memory *handle, off_t start); +extern int DRM(agp_unbind_memory)(agp_memory *handle); +#endif /* Stub support (drm_stub.h) */ int DRM(stub_register)(const char *name, @@ -927,6 +998,15 @@ extern int DRM(proc_cleanup)(int minor, struct proc_dir_entry *root, struct proc_dir_entry *dev_root); +#if __HAVE_SG + /* Scatter Gather Support (drm_scatter.h) */ +extern void DRM(sg_cleanup)(drm_sg_mem_t *entry); +extern int DRM(sg_alloc)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int DRM(sg_free)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +#endif + /* ATI PCIGART support (ati_pcigart.h) */ extern int DRM(ati_pcigart_init)(drm_device_t *dev, unsigned long *addr, diff --git a/linux/drm_agp.h b/linux/drm_agp.h deleted file mode 100644 index 1bd932e1..00000000 --- a/linux/drm_agp.h +++ /dev/null @@ -1,111 +0,0 @@ -/** - * \file drm_agp.h - * DRM support for AGP/GART backend - * - * \author Rickard E. (Rik) Faith - * \author Gareth Hughes - */ - -/* - * 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. - */ - -#ifndef _DRM_AGP_H_ -#define _DRM_AGP_H_ - -#ifndef __HAVE_AGP -#define __HAVE_AGP 0 -#endif - -#define __REALLY_HAVE_AGP (__HAVE_AGP && \ - (defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE))) - -#if __REALLY_HAVE_AGP - - -#include -#include - - -/** - * AGP memory entry. Stored as a doubly linked list. - */ -typedef struct drm_agp_mem { - unsigned long handle; /**< handle */ - agp_memory *memory; - unsigned long bound; /**< address */ - int pages; - struct drm_agp_mem *prev; /**< previous entry */ - struct drm_agp_mem *next; /**< next entry */ -} drm_agp_mem_t; - -/** - * AGP data. - * - * \sa DRM(agp_init)() and drm_device::agp. - */ -typedef struct drm_agp_head { - agp_kern_info agp_info; /**< AGP device information */ - drm_agp_mem_t *memory; /**< memory entries */ - unsigned long mode; /**< AGP mode */ - int enabled; /**< whether the AGP bus as been enabled */ - int acquired; /**< whether the AGP device has been acquired */ - unsigned long base; - int agp_mtrr; - int cant_use_aperture; - unsigned long page_mask; -} drm_agp_head_t; - - -/** \name Prototypes */ -/*@{*/ - -extern int DRM(agp_acquire)(void); -extern void DRM(agp_release)(void); -extern void DRM(agp_enable)(unsigned long mode); -extern agp_memory *DRM(agp_allocate_memory)(size_t pages, u32 type); -extern int DRM(agp_free_memory)(agp_memory *handle); -extern int DRM(agp_bind_memory)(agp_memory *handle, off_t start); -extern int DRM(agp_unbind_memory)(agp_memory *handle); - -extern int DRM(agp_acquire_ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern int DRM(agp_release_ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern int DRM(agp_enable_ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern int DRM(agp_info_ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern int DRM(agp_alloc_ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern int DRM(agp_free_ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern int DRM(agp_bind_ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern int DRM(agp_unbind_ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); - -extern void DRM(agp_init)(void); -extern void DRM(agp_cleanup)(void); -extern void DRM(agp_init_dev)(drm_device_t *dev); -extern void DRM(agp_cleanup_dev)(drm_device_t *dev); - -/*@}*/ - - -#endif /* __REALLY_HAVE_AGP */ - -#endif /* !_DRM_AGP_H_ */ diff --git a/linux/drm_agp_tmp.h b/linux/drm_agp_tmp.h deleted file mode 100644 index 8ae64b1d..00000000 --- a/linux/drm_agp_tmp.h +++ /dev/null @@ -1,564 +0,0 @@ -/** - * \file drm_agp_tmp.h - * DRM support for AGP/GART backend - * - * \author Rickard E. (Rik) Faith - * \author Gareth Hughes - */ - -/* - * 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. - */ - - - -#if __REALLY_HAVE_AGP - -#define __NO_VERSION__ -#include "drmP.h" -#include - - -/** - * Pointer to the drm_agp_t structure made available by the AGPGART module. - */ -static const drm_agp_t *drm_agp = NULL; - - -/**********************************************************************/ -/** - * \name drm_agp wrappers - * - * These functions are thin wrappers around the respective methods in drm_agp - * which are exposed by the AGPGART module. - * - */ -/* TODO: Put these in a header inline. */ -/*@{*/ - -/** - * Acquire the AGP device. - */ -int DRM(agp_acquire)(void) -{ - if (!drm_agp || !drm_agp->acquire) - return -EINVAL; - return drm_agp->acquire(); -} - -/** - * Release the AGP device. - */ -void DRM(agp_release)(void) -{ - if (!drm_agp || !drm_agp->release) - return; - drm_agp->release(); -} - -/** - * Enable the AGP bus. - */ -void DRM(agp_enable)(unsigned long mode) -{ - if (!drm_agp || !drm_agp->enable) - return; - drm_agp->enable(mode); -} - -/** - * Allocate AGP memory. - * - * Not meant to be called directly. Use agp_alloc() instead, which can provide - * some debugging features. - */ -agp_memory *DRM(agp_allocate_memory)(size_t pages, u32 type) -{ - if (!drm_agp || !drm_agp->allocate_memory) - return NULL; - return drm_agp->allocate_memory(pages, type); -} - -/** - * Free AGP memory. - * - * Not meant to be called directly. Use agp_free() instead, which can provide - * some debugging features. - */ -int DRM(agp_free_memory)(agp_memory *handle) -{ - if (!handle || !drm_agp || !drm_agp->free_memory) - return 0; - drm_agp->free_memory(handle); - return 1; -} - -/** - * Bind AGP memory. - * - * Not meant to be called directly. Use agp_bind() instead, which can provide - * some debugging features. - */ -int DRM(agp_bind_memory)(agp_memory *handle, off_t start) -{ - if (!handle || !drm_agp || !drm_agp->bind_memory) - return -EINVAL; - return drm_agp->bind_memory(handle, start); -} - -/** - * Bind AGP memory. - * - * Not meant to be called directly. Use agp_unbind() instead, which can provide - * some debugging features. - */ -int DRM(agp_unbind_memory)(agp_memory *handle) -{ - if (!handle || !drm_agp || !drm_agp->unbind_memory) - return -EINVAL; - return drm_agp->unbind_memory(handle); -} - -/**@}*/ - - -/**********************************************************************/ -/** \name Ioctl's */ -/*@{*/ - -/** - * Acquire the AGP device. - * - * \param inode device inode. - * \param filp file pointer. - * \param cmd command. - * \param arg user argument. - * \return zero on success or a negative number on failure. - * - * Verifies the AGP device hasn't been acquired before and calls - * drm_acquire(). - */ -int DRM(agp_acquire_ioctl)(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - int retcode; - - if (!dev->agp || dev->agp->acquired || !drm_agp->acquire) - return -EINVAL; - if ((retcode = DRM(agp_acquire)())) return retcode; - dev->agp->acquired = 1; - return 0; -} - -/** - * Release the AGP device. - * - * \param inode device inode. - * \param filp file pointer. - * \param cmd command. - * \param arg user argument. - * \return zero on success or a negative number on failure. - * - * Verifies the AGP device has been acquired and calls drm_agp->release(). - */ -int DRM(agp_release_ioctl)(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - - if (!dev->agp || !dev->agp->acquired || !drm_agp->release) - return -EINVAL; - drm_agp->release(); - dev->agp->acquired = 0; - return 0; - -} - -/** - * Get AGP information. - * - * \param inode device inode. - * \param filp file pointer. - * \param cmd command. - * \param arg pointer to an (output) drm_agp_info structure. - * \return zero on success or a negative number on failure. - * - * Verifies the AGP device has been initialized and acquired and fills in the - * drm_agp_info structure with the information in drm_agp_head::agp_info. - */ -int DRM(agp_info_ioctl)(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - agp_kern_info *kern; - drm_agp_info_t info; - - if (!dev->agp || !dev->agp->acquired || !drm_agp->copy_info) - return -EINVAL; - - kern = &dev->agp->agp_info; - info.agp_version_major = kern->version.major; - info.agp_version_minor = kern->version.minor; - info.mode = kern->mode; - info.aperture_base = kern->aper_base; - info.aperture_size = kern->aper_size * 1024 * 1024; - info.memory_allowed = kern->max_memory << PAGE_SHIFT; - info.memory_used = kern->current_memory << PAGE_SHIFT; - info.id_vendor = kern->device->vendor; - info.id_device = kern->device->device; - - if (copy_to_user((drm_agp_info_t *)arg, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -/** - * Enable the AGP bus. - * - * \param inode device inode. - * \param filp file pointer. - * \param cmd command. - * \param arg pointer to a drm_agp_mode structure. - * \return zero on success or a negative number on failure. - * - * Verifies the AGP device has been acquired, and calls - * agp_enable(). - */ -int DRM(agp_enable_ioctl)(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_agp_mode_t mode; - - if (!dev->agp || !dev->agp->acquired || !drm_agp->enable) - return -EINVAL; - - if (copy_from_user(&mode, (drm_agp_mode_t *)arg, sizeof(mode))) - return -EFAULT; - - dev->agp->mode = mode.mode; - DRM(agp_enable)(mode.mode); - dev->agp->base = dev->agp->agp_info.aper_base; - dev->agp->enabled = 1; - return 0; -} - -/** - * Allocate AGP memory. - * - * \param inode device inode. - * \param filp file pointer. - * \param cmd command. - * \param arg pointer to a drm_agp_buffer structure. - * \return zero on success or a negative number on failure. - * - * Verifies the AGP device is present and has been acquired, allocates the - * memory via agp_alloc() and creates a drm_agp_mem entry for it. - */ -int DRM(agp_alloc_ioctl)(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_agp_buffer_t request; - drm_agp_mem_t *entry; - agp_memory *memory; - unsigned long pages; - u32 type; - - if (!dev->agp || !dev->agp->acquired) return -EINVAL; - if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request))) - return -EFAULT; - if (!(entry = DRM(alloc)(sizeof(*entry), DRM_MEM_AGPLISTS))) - return -ENOMEM; - - memset(entry, 0, sizeof(*entry)); - - pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE; - type = (u32) request.type; - - if (!(memory = DRM(agp_alloc)(pages, type))) { - DRM(free)(entry, sizeof(*entry), DRM_MEM_AGPLISTS); - return -ENOMEM; - } - - entry->handle = (unsigned long)memory->key; - entry->memory = memory; - entry->bound = 0; - entry->pages = pages; - entry->prev = NULL; - entry->next = dev->agp->memory; - if (dev->agp->memory) dev->agp->memory->prev = entry; - dev->agp->memory = entry; - - request.handle = entry->handle; - request.physical = memory->physical; - - if (copy_to_user((drm_agp_buffer_t *)arg, &request, sizeof(request))) { - dev->agp->memory = entry->next; - dev->agp->memory->prev = NULL; - DRM(agp_free)(memory, pages); - DRM(free)(entry, sizeof(*entry), DRM_MEM_AGPLISTS); - return -EFAULT; - } - return 0; -} - -/** - * Search for the AGP memory entry associated with a handle. - * - * \param dev DRM device structure. - * \param handle AGP memory handle. - * \return pointer to the drm_agp_mem structure associated with \p handle. - * - * Walks through drm_agp_head::memory until finding a matching handle. - */ -static drm_agp_mem_t *DRM(agp_lookup_entry)(drm_device_t *dev, - unsigned long handle) -{ - drm_agp_mem_t *entry; - - for (entry = dev->agp->memory; entry; entry = entry->next) { - if (entry->handle == handle) return entry; - } - return NULL; -} - -/** - * Unbind AGP memory from the GATT. - * - * \param inode device inode. - * \param filp file pointer. - * \param cmd command. - * \param arg pointer to a drm_agp_binding structure. - * \return zero on success or a negative number on failure. - * - * Verifies the AGP device is present and acquired, looks-up the AGP memory - * entry and passes it to the agp_unbind() function. - */ -int DRM(agp_unbind_ioctl)(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_agp_binding_t request; - drm_agp_mem_t *entry; - int ret; - - if (!dev->agp || !dev->agp->acquired) return -EINVAL; - if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request))) - return -EFAULT; - if (!(entry = DRM(agp_lookup_entry)(dev, request.handle))) - return -EINVAL; - if (!entry->bound) return -EINVAL; - ret = DRM(agp_unbind)(entry->memory); - if (ret == 0) - entry->bound = 0; - return ret; -} - -/** - * Bind AGP memory into the GATT - * - * \param inode device inode. - * \param filp file pointer. - * \param cmd command. - * \param arg pointer to a drm_agp_binding structure. - * \return zero on success or a negative number on failure. - * - * Verifies the AGP device is present and has been acquired and that no memory - * is currently bound into the GATT. Looks-up the AGP memory entry and passes - * it to agp_bind() function. - */ -int DRM(agp_bind_ioctl)(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_agp_binding_t request; - drm_agp_mem_t *entry; - int retcode; - int page; - - if (!dev->agp || !dev->agp->acquired || !drm_agp->bind_memory) - return -EINVAL; - if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request))) - return -EFAULT; - if (!(entry = DRM(agp_lookup_entry)(dev, request.handle))) - return -EINVAL; - if (entry->bound) return -EINVAL; - page = (request.offset + PAGE_SIZE - 1) / PAGE_SIZE; - if ((retcode = DRM(agp_bind)(entry->memory, page))) return retcode; - entry->bound = dev->agp->base + (page << PAGE_SHIFT); - DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n", - dev->agp->base, entry->bound); - return 0; -} - -/** - * Free AGP memory. - * - * \param inode device inode. - * \param filp file pointer. - * \param cmd command. - * \param arg pointer to a drm_agp_buffer structure. - * \return zero on success or a negative number on failure. - * - * Verifies the AGP device is present and has been acquired and looks up the - * AGP memory entry. If the memory it's currently bound, unbind it via - * agp_unbind(). Frees it via agp_free() as well as the entry itself - * and unlinks from the doubly linked list it's inserted in. - */ -int DRM(agp_free_ioctl)(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_agp_buffer_t request; - drm_agp_mem_t *entry; - - if (!dev->agp || !dev->agp->acquired) return -EINVAL; - if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request))) - return -EFAULT; - if (!(entry = DRM(agp_lookup_entry)(dev, request.handle))) - return -EINVAL; - if (entry->bound) DRM(agp_unbind)(entry->memory); - - if (entry->prev) entry->prev->next = entry->next; - else dev->agp->memory = entry->next; - if (entry->next) entry->next->prev = entry->prev; - DRM(agp_free)(entry->memory, entry->pages); - DRM(free)(entry, sizeof(*entry), DRM_MEM_AGPLISTS); - return 0; -} - -/*@}*/ - - -/**********************************************************************/ -/** \name Initialization and cleanup */ -/*@{*/ - -/** - * Initialize the global AGP resources. - * - * Gets the drm_agp_t structure which is made available by the agpgart module - * via the inter_module_* functions. - */ -void DRM(agp_init)(void) -{ - drm_agp = (drm_agp_t *)inter_module_get("drm_agp"); -} - -/** - * Free the global AGP resources. - * - * Releases the pointer in ::drm_agp. - */ -void DRM(agp_cleanup)(void) -{ - if (drm_agp) { - inter_module_put("drm_agp"); - drm_agp = NULL; - } -} - -/** - * Initialize the device AGP resources. - * - * Creates and initializes a drm_agp_head structure in drm_device_t::agp. - */ -void DRM(agp_init_dev)(drm_device_t *dev) -{ - drm_agp_head_t *head = NULL; - - if (!drm_agp) - return; - - if (!(head = DRM(alloc)(sizeof(*head), DRM_MEM_AGPLISTS))) - return; - - memset((void *)head, 0, sizeof(*head)); - drm_agp->copy_info(&head->agp_info); - if (head->agp_info.chipset == NOT_SUPPORTED) { - DRM(free)(head, sizeof(*head), DRM_MEM_AGPLISTS); - return; - } - head->memory = NULL; -#if LINUX_VERSION_CODE <= 0x020408 - head->cant_use_aperture = 0; - head->page_mask = ~(0xfff); -#else - head->cant_use_aperture = head->agp_info.cant_use_aperture; - head->page_mask = head->agp_info.page_mask; -#endif - - DRM_INFO("AGP %d.%d aperture @ 0x%08lx %ZuMB\n", - head->agp_info.version.major, - head->agp_info.version.minor, - head->agp_info.aper_base, - head->agp_info.aper_size); - - dev->agp = head; -} - -/** - * Free the device AGP resources. - */ -void DRM(agp_cleanup_dev)(drm_device_t *dev) -{ - if ( dev->agp ) { - drm_agp_mem_t *entry; - drm_agp_mem_t *nexte; - - /* Remove AGP resources, but leave dev->agp - intact until drv_cleanup is called. */ - for ( entry = dev->agp->memory ; entry ; entry = nexte ) { - nexte = entry->next; - if ( entry->bound ) DRM(agp_unbind)( entry->memory ); - DRM(agp_free)( entry->memory, entry->pages ); - DRM(free)( entry, sizeof(*entry), DRM_MEM_AGPLISTS ); - } - dev->agp->memory = NULL; - - if ( dev->agp->acquired ) - DRM(agp_release)(); - - dev->agp->acquired = 0; - dev->agp->enabled = 0; - - DRM(free)( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS ); - dev->agp = NULL; - } -} - -/*@}*/ - - -#endif /* __REALLY_HAVE_AGP */ diff --git a/linux/drm_agpsupport.h b/linux/drm_agpsupport.h new file mode 100644 index 00000000..81850593 --- /dev/null +++ b/linux/drm_agpsupport.h @@ -0,0 +1,451 @@ +/** + * \file drm_agpsupport.h + * DRM support for AGP/GART backend + * + * \author Rickard E. (Rik) Faith + * \author Gareth Hughes + */ + +/* + * 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" +#include + +#if __REALLY_HAVE_AGP + + +#define DRM_AGP_GET (drm_agp_t *)inter_module_get("drm_agp") +#define DRM_AGP_PUT inter_module_put("drm_agp") + +/** + * Pointer to the drm_agp_t structure made available by the agpgart module. + */ +static const drm_agp_t *drm_agp = NULL; + +/** + * AGP information ioctl. + * + * \param inode device inode. + * \param filp file pointer. + * \param cmd command. + * \param arg pointer to a (output) drm_agp_info structure. + * \return zero on success or a negative number on failure. + * + * Verifies the AGP device has been initialized and acquired and fills in the + * drm_agp_info structure with the information in drm_agp_head::agp_info. + */ +int DRM(agp_info)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + agp_kern_info *kern; + drm_agp_info_t info; + + if (!dev->agp || !dev->agp->acquired || !drm_agp->copy_info) + return -EINVAL; + + kern = &dev->agp->agp_info; + info.agp_version_major = kern->version.major; + info.agp_version_minor = kern->version.minor; + info.mode = kern->mode; + info.aperture_base = kern->aper_base; + info.aperture_size = kern->aper_size * 1024 * 1024; + info.memory_allowed = kern->max_memory << PAGE_SHIFT; + info.memory_used = kern->current_memory << PAGE_SHIFT; + info.id_vendor = kern->device->vendor; + info.id_device = kern->device->device; + + if (copy_to_user((drm_agp_info_t *)arg, &info, sizeof(info))) + return -EFAULT; + return 0; +} + +/** + * Acquire the AGP device (ioctl). + * + * \param inode device inode. + * \param filp file pointer. + * \param cmd command. + * \param arg user argument. + * \return zero on success or a negative number on failure. + * + * Verifies the AGP device hasn't been acquired before and calls + * drm_agp->acquire(). + */ +int DRM(agp_acquire)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + int retcode; + + if (!dev->agp || dev->agp->acquired || !drm_agp->acquire) + return -EINVAL; + if ((retcode = drm_agp->acquire())) return retcode; + dev->agp->acquired = 1; + return 0; +} + +/** + * Release the AGP device (ioctl). + * + * \param inode device inode. + * \param filp file pointer. + * \param cmd command. + * \param arg user argument. + * \return zero on success or a negative number on failure. + * + * Verifies the AGP device has been acquired and calls drm_agp->release(). + */ +int DRM(agp_release)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + + if (!dev->agp || !dev->agp->acquired || !drm_agp->release) + return -EINVAL; + drm_agp->release(); + dev->agp->acquired = 0; + return 0; + +} + +/** + * Release the AGP device. + * + * Calls drm_agp->release(). + */ +void DRM(agp_do_release)(void) +{ + if (drm_agp->release) drm_agp->release(); +} + +/** + * Enable the AGP bus. + * + * \param inode device inode. + * \param filp file pointer. + * \param cmd command. + * \param arg pointer to a drm_agp_mode structure. + * \return zero on success or a negative number on failure. + * + * Verifies the AGP device has been acquired but not enabled, and calls + * drm_agp->enable(). + */ +int DRM(agp_enable)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_agp_mode_t mode; + + if (!dev->agp || !dev->agp->acquired || !drm_agp->enable) + return -EINVAL; + + if (copy_from_user(&mode, (drm_agp_mode_t *)arg, sizeof(mode))) + return -EFAULT; + + dev->agp->mode = mode.mode; + drm_agp->enable(mode.mode); + dev->agp->base = dev->agp->agp_info.aper_base; + dev->agp->enabled = 1; + return 0; +} + +/** + * Allocate AGP memory. + * + * \param inode device inode. + * \param filp file pointer. + * \param cmd command. + * \param arg pointer to a drm_agp_buffer structure. + * \return zero on success or a negative number on failure. + * + * Verifies the AGP device is present and has been acquired, allocates the + * memory via alloc_agp() and creates a drm_agp_mem entry for it. + */ +int DRM(agp_alloc)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_agp_buffer_t request; + drm_agp_mem_t *entry; + agp_memory *memory; + unsigned long pages; + u32 type; + + if (!dev->agp || !dev->agp->acquired) return -EINVAL; + if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request))) + return -EFAULT; + if (!(entry = DRM(alloc)(sizeof(*entry), DRM_MEM_AGPLISTS))) + return -ENOMEM; + + memset(entry, 0, sizeof(*entry)); + + pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE; + type = (u32) request.type; + + if (!(memory = DRM(alloc_agp)(pages, type))) { + DRM(free)(entry, sizeof(*entry), DRM_MEM_AGPLISTS); + return -ENOMEM; + } + + entry->handle = (unsigned long)memory->key; + entry->memory = memory; + entry->bound = 0; + entry->pages = pages; + entry->prev = NULL; + entry->next = dev->agp->memory; + if (dev->agp->memory) dev->agp->memory->prev = entry; + dev->agp->memory = entry; + + request.handle = entry->handle; + request.physical = memory->physical; + + if (copy_to_user((drm_agp_buffer_t *)arg, &request, sizeof(request))) { + dev->agp->memory = entry->next; + dev->agp->memory->prev = NULL; + DRM(free_agp)(memory, pages); + DRM(free)(entry, sizeof(*entry), DRM_MEM_AGPLISTS); + return -EFAULT; + } + return 0; +} + +/** + * Search for the AGP memory entry associated with a handle. + * + * \param dev DRM device structure. + * \param handle AGP memory handle. + * \return pointer to the drm_agp_mem structure associated with \p handle. + * + * Walks through drm_agp_head::memory until finding a matching handle. + */ +static drm_agp_mem_t *DRM(agp_lookup_entry)(drm_device_t *dev, + unsigned long handle) +{ + drm_agp_mem_t *entry; + + for (entry = dev->agp->memory; entry; entry = entry->next) { + if (entry->handle == handle) return entry; + } + return NULL; +} + +/** + * Unbind AGP memory from the GATT (ioctl). + * + * \param inode device inode. + * \param filp file pointer. + * \param cmd command. + * \param arg pointer to a drm_agp_binding structure. + * \return zero on success or a negative number on failure. + * + * Verifies the AGP device is present and acquired, looks-up the AGP memory + * entry and passes it to the unbind_agp() function. + */ +int DRM(agp_unbind)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_agp_binding_t request; + drm_agp_mem_t *entry; + int ret; + + if (!dev->agp || !dev->agp->acquired) return -EINVAL; + if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request))) + return -EFAULT; + if (!(entry = DRM(agp_lookup_entry)(dev, request.handle))) + return -EINVAL; + if (!entry->bound) return -EINVAL; + ret = DRM(unbind_agp)(entry->memory); + if (ret == 0) + entry->bound = 0; + return ret; +} + +/** + * Bind AGP memory into the GATT (ioctl) + * + * \param inode device inode. + * \param filp file pointer. + * \param cmd command. + * \param arg pointer to a drm_agp_binding structure. + * \return zero on success or a negative number on failure. + * + * Verifies the AGP device is present and has been acquired and that no memory + * is currently bound into the GATT. Looks-up the AGP memory entry and passes + * it to bind_agp() function. + */ +int DRM(agp_bind)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_agp_binding_t request; + drm_agp_mem_t *entry; + int retcode; + int page; + + if (!dev->agp || !dev->agp->acquired || !drm_agp->bind_memory) + return -EINVAL; + if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request))) + return -EFAULT; + if (!(entry = DRM(agp_lookup_entry)(dev, request.handle))) + return -EINVAL; + if (entry->bound) return -EINVAL; + page = (request.offset + PAGE_SIZE - 1) / PAGE_SIZE; + if ((retcode = DRM(bind_agp)(entry->memory, page))) return retcode; + entry->bound = dev->agp->base + (page << PAGE_SHIFT); + DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n", + dev->agp->base, entry->bound); + return 0; +} + +/** + * Free AGP memory (ioctl). + * + * \param inode device inode. + * \param filp file pointer. + * \param cmd command. + * \param arg pointer to a drm_agp_buffer structure. + * \return zero on success or a negative number on failure. + * + * Verifies the AGP device is present and has been acquired and looks up the + * AGP memory entry. If the memory it's currently bound, unbind it via + * unbind_agp(). Frees it via free_agp() as well as the entry itself + * and unlinks from the doubly linked list it's inserted in. + */ +int DRM(agp_free)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_agp_buffer_t request; + drm_agp_mem_t *entry; + + if (!dev->agp || !dev->agp->acquired) return -EINVAL; + if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request))) + return -EFAULT; + if (!(entry = DRM(agp_lookup_entry)(dev, request.handle))) + return -EINVAL; + if (entry->bound) DRM(unbind_agp)(entry->memory); + + if (entry->prev) entry->prev->next = entry->next; + else dev->agp->memory = entry->next; + if (entry->next) entry->next->prev = entry->prev; + DRM(free_agp)(entry->memory, entry->pages); + DRM(free)(entry, sizeof(*entry), DRM_MEM_AGPLISTS); + return 0; +} + +/** + * Initialize the AGP resources. + * + * \return pointer to a drm_agp_head structure. + * + * Gets the drm_agp_t structure which is made available by the agpgart module + * via the inter_module_* functions. Creates and initializes a drm_agp_head + * structure. + */ +drm_agp_head_t *DRM(agp_init)(void) +{ + drm_agp_head_t *head = NULL; + + drm_agp = DRM_AGP_GET; + if (drm_agp) { + if (!(head = DRM(alloc)(sizeof(*head), DRM_MEM_AGPLISTS))) + return NULL; + memset((void *)head, 0, sizeof(*head)); + drm_agp->copy_info(&head->agp_info); + if (head->agp_info.chipset == NOT_SUPPORTED) { + DRM(free)(head, sizeof(*head), DRM_MEM_AGPLISTS); + return NULL; + } + head->memory = NULL; +#if LINUX_VERSION_CODE <= 0x020408 + head->cant_use_aperture = 0; + head->page_mask = ~(0xfff); +#else + head->cant_use_aperture = head->agp_info.cant_use_aperture; + head->page_mask = head->agp_info.page_mask; +#endif + + DRM_INFO("AGP %d.%d aperture @ 0x%08lx %ZuMB\n", + head->agp_info.version.major, + head->agp_info.version.minor, + head->agp_info.aper_base, + head->agp_info.aper_size); + } + return head; +} + +/** + * Free the AGP resources. + * + * Releases the pointer in ::drm_agp. + */ +void DRM(agp_uninit)(void) +{ + DRM_AGP_PUT; + drm_agp = NULL; +} + +/** Calls drm_agp->allocate_memory() */ +agp_memory *DRM(agp_allocate_memory)(size_t pages, u32 type) +{ + if (!drm_agp->allocate_memory) return NULL; + return drm_agp->allocate_memory(pages, type); +} + +/** Calls drm_agp->free_memory() */ +int DRM(agp_free_memory)(agp_memory *handle) +{ + if (!handle || !drm_agp->free_memory) return 0; + drm_agp->free_memory(handle); + return 1; +} + +/** Calls drm_agp->bind_memory() */ +int DRM(agp_bind_memory)(agp_memory *handle, off_t start) +{ + if (!handle || !drm_agp->bind_memory) return -EINVAL; + return drm_agp->bind_memory(handle, start); +} + +/** Calls drm_agp->unbind_memory() */ +int DRM(agp_unbind_memory)(agp_memory *handle) +{ + if (!handle || !drm_agp->unbind_memory) return -EINVAL; + return drm_agp->unbind_memory(handle); +} + +#endif /* __REALLY_HAVE_AGP */ diff --git a/linux/drm_bufs.h b/linux/drm_bufs.h index f42fabef..77573709 100644 --- a/linux/drm_bufs.h +++ b/linux/drm_bufs.h @@ -174,8 +174,6 @@ int DRM(addmap)( struct inode *inode, struct file *filp, map->mtrr = dev->agp->agp_mtrr; /* for getmap */ break; #endif - -#if __HAVE_SG case _DRM_SCATTER_GATHER: if (!dev->sg) { DRM(free)(map, sizeof(*map), DRM_MEM_MAPS); @@ -183,7 +181,6 @@ int DRM(addmap)( struct inode *inode, struct file *filp, } map->offset += dev->sg->handle; break; -#endif default: DRM(free)( map, sizeof(*map), DRM_MEM_MAPS ); diff --git a/linux/drm_drv.h b/linux/drm_drv.h index 5a4ab36e..90c2d18b 100644 --- a/linux/drm_drv.h +++ b/linux/drm_drv.h @@ -225,19 +225,19 @@ static drm_ioctl_desc_t DRM(ioctls)[] = { #endif #if __REALLY_HAVE_AGP - [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { DRM(agp_acquire_ioctl), 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { DRM(agp_release_ioctl), 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { DRM(agp_enable_ioctl), 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { DRM(agp_info_ioctl), 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { DRM(agp_alloc_ioctl), 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { DRM(agp_free_ioctl), 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { DRM(agp_bind_ioctl), 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { DRM(agp_unbind_ioctl), 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { DRM(agp_acquire), 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { DRM(agp_release), 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { DRM(agp_enable), 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { DRM(agp_info), 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { DRM(agp_alloc), 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { DRM(agp_free), 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { DRM(agp_bind), 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { DRM(agp_unbind), 1, 1 }, #endif #if __HAVE_SG - [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = { DRM(sg_alloc_ioctl), 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { DRM(sg_free_ioctl), 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = { DRM(sg_alloc), 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { DRM(sg_free), 1, 1 }, #endif #if __HAVE_VBL_IRQ @@ -416,6 +416,29 @@ static int DRM(takedown)( drm_device_t *dev ) dev->magiclist[i].head = dev->magiclist[i].tail = NULL; } +#if __REALLY_HAVE_AGP + /* Clear AGP information */ + if ( dev->agp ) { + drm_agp_mem_t *entry; + drm_agp_mem_t *nexte; + + /* Remove AGP resources, but leave dev->agp + intact until drv_cleanup is called. */ + for ( entry = dev->agp->memory ; entry ; entry = nexte ) { + nexte = entry->next; + if ( entry->bound ) DRM(unbind_agp)( entry->memory ); + DRM(free_agp)( entry->memory, entry->pages ); + DRM(free)( entry, sizeof(*entry), DRM_MEM_AGPLISTS ); + } + dev->agp->memory = NULL; + + if ( dev->agp->acquired ) DRM(agp_do_release)(); + + dev->agp->acquired = 0; + dev->agp->enabled = 0; + } +#endif + /* Clear vma list (only built for debugging) */ if ( dev->vmalist ) { for ( vma = dev->vmalist ; vma ; vma = vma_next ) { @@ -463,7 +486,10 @@ static int DRM(takedown)( drm_device_t *dev ) * isn't defined. */ #if __HAVE_SG - DRM(sg_cleanup)(dev); + if(dev->sg) { + DRM(sg_cleanup)(dev->sg); + dev->sg = NULL; + } #endif break; } @@ -592,10 +618,6 @@ static int __init drm_init( void ) DRM(mem_init)(); -#if __REALLY_HAVE_AGP - DRM(agp_init)(); -#endif - for (i = 0; i < DRM(numdevs); i++) { dev = &(DRM(device)[i]); memset( (void *)dev, 0, sizeof(*dev) ); @@ -608,9 +630,8 @@ static int __init drm_init( void ) dev->name = DRIVER_NAME; #if __REALLY_HAVE_AGP - DRM(agp_init_dev)( dev ); + dev->agp = DRM(agp_init)(); #if __MUST_HAVE_AGP - if ( dev->agp == NULL ) { DRM_ERROR( "Cannot initialize the agpgart module.\n" ); DRM(stub_unregister)(DRM(minor)[i]); @@ -618,12 +639,14 @@ static int __init drm_init( void ) return -ENOMEM; } #endif +#if __REALLY_HAVE_MTRR if (dev->agp) dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base, dev->agp->agp_info.aper_size*1024*1024, MTRR_TYPE_WRCOMB, 1 ); #endif +#endif #if __HAVE_CTX_BITMAP retcode = DRM(ctxbitmap_init)( dev ); @@ -689,14 +712,13 @@ static void __exit drm_cleanup( void ) DRM(takedown)( dev ); #if __REALLY_HAVE_AGP - DRM(agp_cleanup_dev)( dev ); + if ( dev->agp ) { + DRM(agp_uninit)(); + DRM(free)( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS ); + dev->agp = NULL; + } #endif } - -#if __REALLY_HAVE_AGP - DRM(agp_cleanup)(); -#endif - DRIVER_POSTCLEANUP(); kfree(DRM(minor)); kfree(DRM(device)); diff --git a/linux/drm_memory.h b/linux/drm_memory.h index 9999c213..2a969fcd 100644 --- a/linux/drm_memory.h +++ b/linux/drm_memory.h @@ -332,29 +332,27 @@ void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev) #if __REALLY_HAVE_AGP /** Wrapper around agp_allocate_memory() */ -agp_memory *DRM(agp_alloc)(int pages, u32 type) +agp_memory *DRM(alloc_agp)(int pages, u32 type) { return DRM(agp_allocate_memory)(pages, type); } /** Wrapper around agp_free_memory() */ -int DRM(agp_free)(agp_memory *handle, int pages) +int DRM(free_agp)(agp_memory *handle, int pages) { return DRM(agp_free_memory)(handle) ? 0 : -EINVAL; } /** Wrapper around agp_bind_memory() */ -int DRM(agp_bind)(agp_memory *handle, unsigned int start) +int DRM(bind_agp)(agp_memory *handle, unsigned int start) { return DRM(agp_bind_memory)(handle, start); } /** Wrapper around agp_unbind_memory() */ -int DRM(agp_unbind)(agp_memory *handle) +int DRM(unbind_agp)(agp_memory *handle) { return DRM(agp_unbind_memory)(handle); } -#endif /* __REALLY_HAVE_AGP */ - - +#endif /* agp */ #endif /* debug_memory */ diff --git a/linux/drm_memory_debug.h b/linux/drm_memory_debug.h index 91b42126..5cfff83a 100644 --- a/linux/drm_memory_debug.h +++ b/linux/drm_memory_debug.h @@ -1,5 +1,5 @@ /** - * \file drm_memory_debug.h + * \file drm_memory.h * Memory management wrappers for DRM. * * \author Rickard E. (Rik) Faith @@ -343,7 +343,7 @@ void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev) #if __REALLY_HAVE_AGP -agp_memory *DRM(agp_alloc)(int pages, u32 type) +agp_memory *DRM(alloc_agp)(int pages, u32 type) { agp_memory *handle; @@ -366,7 +366,7 @@ agp_memory *DRM(agp_alloc)(int pages, u32 type) return NULL; } -int DRM(agp_free)(agp_memory *handle, int pages) +int DRM(free_agp)(agp_memory *handle, int pages) { int alloc_count; int free_count; @@ -395,7 +395,7 @@ int DRM(agp_free)(agp_memory *handle, int pages) return retval; } -int DRM(agp_bind)(agp_memory *handle, unsigned int start) +int DRM(bind_agp)(agp_memory *handle, unsigned int start) { int retcode = -EINVAL; @@ -419,7 +419,7 @@ int DRM(agp_bind)(agp_memory *handle, unsigned int start) return retcode; } -int DRM(agp_unbind)(agp_memory *handle) +int DRM(unbind_agp)(agp_memory *handle) { int alloc_count; int free_count; diff --git a/linux/drm_scatter.h b/linux/drm_scatter.h new file mode 100644 index 00000000..45a30fc3 --- /dev/null +++ b/linux/drm_scatter.h @@ -0,0 +1,229 @@ +/** + * \file drm_scatter.h + * IOCTLs to manage scatter/gather memory + * + * \author Gareth Hughes + */ + +/* + * Created: Mon Dec 18 23:20:54 2000 by gareth@valinux.com + * + * 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 + * PRECISION INSIGHT 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 +#include +#include "drmP.h" + +#define DEBUG_SCATTER 0 + +void DRM(sg_cleanup)( drm_sg_mem_t *entry ) +{ + struct page *page; + int i; + + for ( i = 0 ; i < entry->pages ; i++ ) { + page = entry->pagelist[i]; + if ( page ) + ClearPageReserved( page ); + } + + vfree( entry->virtual ); + + DRM(free)( entry->busaddr, + entry->pages * sizeof(*entry->busaddr), + DRM_MEM_PAGES ); + DRM(free)( entry->pagelist, + entry->pages * sizeof(*entry->pagelist), + DRM_MEM_PAGES ); + DRM(free)( entry, + sizeof(*entry), + DRM_MEM_SGLISTS ); +} + +int DRM(sg_alloc)( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_scatter_gather_t request; + drm_sg_mem_t *entry; + unsigned long pages, i, j; + + DRM_DEBUG( "%s\n", __FUNCTION__ ); + + if ( dev->sg ) + return -EINVAL; + + if ( copy_from_user( &request, + (drm_scatter_gather_t *)arg, + sizeof(request) ) ) + return -EFAULT; + + entry = DRM(alloc)( sizeof(*entry), DRM_MEM_SGLISTS ); + if ( !entry ) + return -ENOMEM; + + memset( entry, 0, sizeof(*entry) ); + + pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE; + DRM_DEBUG( "sg size=%ld pages=%ld\n", request.size, pages ); + + entry->pages = pages; + entry->pagelist = DRM(alloc)( pages * sizeof(*entry->pagelist), + DRM_MEM_PAGES ); + if ( !entry->pagelist ) { + DRM(free)( entry, sizeof(*entry), DRM_MEM_SGLISTS ); + return -ENOMEM; + } + + memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist)); + + entry->busaddr = DRM(alloc)( pages * sizeof(*entry->busaddr), + DRM_MEM_PAGES ); + if ( !entry->busaddr ) { + DRM(free)( entry->pagelist, + entry->pages * sizeof(*entry->pagelist), + DRM_MEM_PAGES ); + DRM(free)( entry, + sizeof(*entry), + DRM_MEM_SGLISTS ); + return -ENOMEM; + } + memset( (void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr) ); + + entry->virtual = vmalloc_32( pages << PAGE_SHIFT ); + if ( !entry->virtual ) { + DRM(free)( entry->busaddr, + entry->pages * sizeof(*entry->busaddr), + DRM_MEM_PAGES ); + DRM(free)( entry->pagelist, + entry->pages * sizeof(*entry->pagelist), + DRM_MEM_PAGES ); + DRM(free)( entry, + sizeof(*entry), + DRM_MEM_SGLISTS ); + return -ENOMEM; + } + + /* This also forces the mapping of COW pages, so our page list + * will be valid. Please don't remove it... + */ + memset( entry->virtual, 0, pages << PAGE_SHIFT ); + + entry->handle = (unsigned long)entry->virtual; + + DRM_DEBUG( "sg alloc handle = %08lx\n", entry->handle ); + DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual ); + + for ( i = entry->handle, j = 0 ; j < pages ; i += PAGE_SIZE, j++ ) { + entry->pagelist[j] = vmalloc_to_page((void *)i); + if (!entry->pagelist[j]) + goto failed; + SetPageReserved(entry->pagelist[j]); + } + + request.handle = entry->handle; + + if ( copy_to_user( (drm_scatter_gather_t *)arg, + &request, + sizeof(request) ) ) { + DRM(sg_cleanup)( entry ); + return -EFAULT; + } + + dev->sg = entry; + +#if DEBUG_SCATTER + /* Verify that each page points to its virtual address, and vice + * versa. + */ + { + int error = 0; + + for ( i = 0 ; i < pages ; i++ ) { + unsigned long *tmp; + + tmp = page_address( entry->pagelist[i] ); + for ( j = 0 ; + j < PAGE_SIZE / sizeof(unsigned long) ; + j++, tmp++ ) { + *tmp = 0xcafebabe; + } + tmp = (unsigned long *)((u8 *)entry->virtual + + (PAGE_SIZE * i)); + for( j = 0 ; + j < PAGE_SIZE / sizeof(unsigned long) ; + j++, tmp++ ) { + if ( *tmp != 0xcafebabe && error == 0 ) { + error = 1; + DRM_ERROR( "Scatter allocation error, " + "pagelist does not match " + "virtual mapping\n" ); + } + } + tmp = page_address( entry->pagelist[i] ); + for(j = 0 ; + j < PAGE_SIZE / sizeof(unsigned long) ; + j++, tmp++) { + *tmp = 0; + } + } + if (error == 0) + DRM_ERROR( "Scatter allocation matches pagelist\n" ); + } +#endif + + return 0; + + failed: + DRM(sg_cleanup)( entry ); + return -ENOMEM; +} + +int DRM(sg_free)( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_scatter_gather_t request; + drm_sg_mem_t *entry; + + if ( copy_from_user( &request, + (drm_scatter_gather_t *)arg, + sizeof(request) ) ) + return -EFAULT; + + entry = dev->sg; + dev->sg = NULL; + + if ( !entry || entry->handle != request.handle ) + return -EINVAL; + + DRM_DEBUG( "sg free virtual = %p\n", entry->virtual ); + + DRM(sg_cleanup)( entry ); + + return 0; +} diff --git a/linux/drm_sg.h b/linux/drm_sg.h deleted file mode 100644 index afd80ef0..00000000 --- a/linux/drm_sg.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * \file drm_sg.h - * IOCTLs to manage scatter/gather memory - * - * \author Gareth Hughes - */ - -/* - * 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 - * PRECISION INSIGHT 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. - */ - - -#ifndef _DRM_SCATTER_H_ -#define _DRM_SCATTER_H_ - - -/** - * Scatter/gather memory entry. - * - * This structure is used by sg_alloc() sg_free() to store all the necessary - * information about a scatter/gather memory block. - * - * Also one instance of this structure is used to hold the user-space - * allocation done via the sg_alloc_ioctl() and sg_free_ioctl() ioctl's. - */ -typedef struct drm_sg_mem { - unsigned long handle; - void *virtual; /**< virtual address */ - int pages; - struct page **pagelist; - dma_addr_t *busaddr; /**< bus address */ -} drm_sg_mem_t; - - -/** \name Prototypes */ -/*@{*/ -extern void DRM(sg_free)( drm_sg_mem_t *entry ); -extern drm_sg_mem_t * DRM(sg_alloc)( unsigned long size ); -extern int DRM(sg_alloc_ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern int DRM(sg_free_ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -extern void DRM(sg_cleanup)(drm_device_t *dev); -/*@}*/ - - -#endif diff --git a/linux/drm_sg_tmp.h b/linux/drm_sg_tmp.h deleted file mode 100644 index 95cb1fc7..00000000 --- a/linux/drm_sg_tmp.h +++ /dev/null @@ -1,309 +0,0 @@ -/** - * \file drm_sg_tmp.h - * IOCTLs to manage scatter/gather memory - * - * \author Gareth Hughes - */ - -/* - * 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 - * PRECISION INSIGHT 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. - */ - - -#if __HAVE_SG - - -#define __NO_VERSION__ -#include -#include -#include "drmP.h" - - -/** - * Define to non-zero to verify that each page points to its virtual address, - * and vice versa, in sg_alloc(). - */ -#define DEBUG_SCATTER 0 - - -/** - * Free scatter/gather memory. - * - * \param entry scatter/gather memory entry to free, as returned by sg_alloc(). - */ -void DRM(sg_free)( drm_sg_mem_t *entry ) -{ - struct page *page; - int i; - - for ( i = 0 ; i < entry->pages ; i++ ) { - page = entry->pagelist[i]; - if ( page ) - ClearPageReserved( page ); - } - - vfree( entry->virtual ); - - DRM(free)( entry->busaddr, - entry->pages * sizeof(*entry->busaddr), - DRM_MEM_PAGES ); - DRM(free)( entry->pagelist, - entry->pages * sizeof(*entry->pagelist), - DRM_MEM_PAGES ); - DRM(free)( entry, - sizeof(*entry), - DRM_MEM_SGLISTS ); -} - -/** - * Allocate scatter/gather memory. - * - * \param size size of memory to allocate. - * \return pointer to a drm_sg_mem structure on success or NULL on failure. - */ -drm_sg_mem_t * DRM(sg_alloc)( unsigned long size ) -{ - drm_sg_mem_t *entry; - unsigned long pages, i, j; - - DRM_DEBUG( "%s\n", __FUNCTION__ ); - - entry = DRM(alloc)( sizeof(*entry), DRM_MEM_SGLISTS ); - if ( !entry ) - return NULL; - - memset( entry, 0, sizeof(*entry) ); - - pages = (size + PAGE_SIZE - 1) / PAGE_SIZE; - DRM_DEBUG( "sg size=%ld pages=%ld\n", size, pages ); - - entry->pages = pages; - entry->pagelist = DRM(alloc)( pages * sizeof(*entry->pagelist), - DRM_MEM_PAGES ); - if ( !entry->pagelist ) { - DRM(free)( entry, sizeof(*entry), DRM_MEM_SGLISTS ); - return NULL; - } - - memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist)); - - entry->busaddr = DRM(alloc)( pages * sizeof(*entry->busaddr), - DRM_MEM_PAGES ); - if ( !entry->busaddr ) { - DRM(free)( entry->pagelist, - entry->pages * sizeof(*entry->pagelist), - DRM_MEM_PAGES ); - DRM(free)( entry, - sizeof(*entry), - DRM_MEM_SGLISTS ); - return NULL; - } - memset( (void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr) ); - - entry->virtual = vmalloc_32( pages << PAGE_SHIFT ); - if ( !entry->virtual ) { - DRM(free)( entry->busaddr, - entry->pages * sizeof(*entry->busaddr), - DRM_MEM_PAGES ); - DRM(free)( entry->pagelist, - entry->pages * sizeof(*entry->pagelist), - DRM_MEM_PAGES ); - DRM(free)( entry, - sizeof(*entry), - DRM_MEM_SGLISTS ); - return NULL; - } - - /* This also forces the mapping of COW pages, so our page list - * will be valid. Please don't remove it... - */ - memset( entry->virtual, 0, pages << PAGE_SHIFT ); - - entry->handle = (unsigned long)entry->virtual; - - DRM_DEBUG( "sg alloc handle = %08lx\n", entry->handle ); - DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual ); - - for ( i = entry->handle, j = 0 ; j < pages ; i += PAGE_SIZE, j++ ) { - entry->pagelist[j] = vmalloc_to_page((void *)i); - if (!entry->pagelist[j]) - goto failed; - SetPageReserved(entry->pagelist[j]); - } - -#if DEBUG_SCATTER - { - int error = 0; - - for ( i = 0 ; i < pages ; i++ ) { - unsigned long *tmp; - - tmp = page_address( entry->pagelist[i] ); - for ( j = 0 ; - j < PAGE_SIZE / sizeof(unsigned long) ; - j++, tmp++ ) { - *tmp = 0xcafebabe; - } - tmp = (unsigned long *)((u8 *)entry->virtual + - (PAGE_SIZE * i)); - for( j = 0 ; - j < PAGE_SIZE / sizeof(unsigned long) ; - j++, tmp++ ) { - if ( *tmp != 0xcafebabe && error == 0 ) { - error = 1; - DRM_ERROR( "Scatter allocation error, " - "pagelist does not match " - "virtual mapping\n" ); - } - } - tmp = page_address( entry->pagelist[i] ); - for(j = 0 ; - j < PAGE_SIZE / sizeof(unsigned long) ; - j++, tmp++) { - *tmp = 0; - } - } - if (error == 0) - DRM_ERROR( "Scatter allocation matches pagelist\n" ); - } -#endif - - return entry; - - failed: - DRM(sg_free)( entry ); - return NULL; -} - - -/**********************************************************************/ -/** \name Ioctl's - * - * These expose the scatter/gather memory functions to user-space, - * doing the necessary parameter verification and book-keeping to avoid memory - * leaks. - * - * In the current implementation only one scatter/gather memory block can be - * allocated per device at a given instance. - * - * The information about the currently allocated scatter/gather memory block is - * stored in drm_device_t::sg. - */ -/*@{*/ - -/** - * Wrapper ioctl around sg_alloc(). - * - * \param inode device inode. - * \param filp file pointer. - * \param cmd command. - * \param arg user argument, pointing to a drm_scatter_gather structure. - * \return zero on success or a negative number on failure. - */ -int DRM(sg_alloc_ioctl)( struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg ) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_scatter_gather_t request; - drm_sg_mem_t *entry; - - DRM_DEBUG( "%s\n", __FUNCTION__ ); - - if ( dev->sg ) - return -EINVAL; - - if ( copy_from_user( &request, - (drm_scatter_gather_t *)arg, - sizeof(request) ) ) - return -EFAULT; - - entry = DRM(sg_alloc)( request.size ); - if ( !entry ) - return -ENOMEM; - - request.handle = entry->handle; - - if ( copy_to_user( (drm_scatter_gather_t *)arg, - &request, - sizeof(request) ) ) { - DRM(sg_free)( entry ); - return -EFAULT; - } - - dev->sg = entry; - - return 0; -} - -/** Wrapper around sg_free(). - * - * \param inode device inode. - * \param filp file pointer. - * \param cmd command. - * \param arg user argument, pointing to a drm_scatter_gather structure. - * \return zero on success or a negative number on failure. - */ -int DRM(sg_free_ioctl)( struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg ) -{ - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->dev; - drm_scatter_gather_t request; - drm_sg_mem_t *entry; - - if ( copy_from_user( &request, - (drm_scatter_gather_t *)arg, - sizeof(request) ) ) - return -EFAULT; - - entry = dev->sg; - dev->sg = NULL; - - if ( !entry || entry->handle != request.handle ) - return -EINVAL; - - DRM_DEBUG( "sg free virtual = %p\n", entry->virtual ); - - DRM(sg_free)( entry ); - - return 0; -} - -/*@}*/ - - -/** - * Called by takedown() to free the scatter/gather memory resources associated - * with a given device, i.e., to free drm_device_t::sg. - */ -void DRM(sg_cleanup)(drm_device_t *dev) -{ - if ( dev->sg ) { - DRM(sg_free)( dev->sg ); - dev->sg = NULL; - } -} - - -#endif diff --git a/linux/gamma_drv.c b/linux/gamma_drv.c index 1313418e..f1b8b205 100644 --- a/linux/gamma_drv.c +++ b/linux/gamma_drv.c @@ -37,7 +37,7 @@ #include "gamma_drv.h" #include "drm_auth.h" -#include "drm_agp_tmp.h" +#include "drm_agpsupport.h" #include "drm_bufs.h" #include "gamma_context.h" /* NOTE! */ #include "drm_dma.h" diff --git a/linux/i810_drv.c b/linux/i810_drv.c index 2b816fbf..0bc79386 100644 --- a/linux/i810_drv.c +++ b/linux/i810_drv.c @@ -37,7 +37,7 @@ #include "i810_drm.h" #include "i810_drv.h" -#include "drm_agp_tmp.h" +#include "drm_agpsupport.h" #include "drm_auth.h" #include "drm_bufs.h" #include "drm_context.h" diff --git a/linux/i830_drv.c b/linux/i830_drv.c index 496c41ee..0735c94d 100644 --- a/linux/i830_drv.c +++ b/linux/i830_drv.c @@ -39,7 +39,7 @@ #include "i830_drm.h" #include "i830_drv.h" -#include "drm_agp_tmp.h" +#include "drm_agpsupport.h" #include "drm_auth.h" #include "drm_bufs.h" #include "drm_context.h" diff --git a/linux/mga_drv.c b/linux/mga_drv.c index f438660c..f0d4935d 100644 --- a/linux/mga_drv.c +++ b/linux/mga_drv.c @@ -35,7 +35,7 @@ #include "drm.h" #include "mga_drm.h" #include "mga_drv.h" -#include "drm_agp_tmp.h" +#include "drm_agpsupport.h" #include "drm_auth.h" #include "drm_bufs.h" #include "drm_context.h" diff --git a/linux/r128_drv.c b/linux/r128_drv.c index 474c1418..e2e42690 100644 --- a/linux/r128_drv.c +++ b/linux/r128_drv.c @@ -37,7 +37,7 @@ #include "r128_drv.h" #include "ati_pcigart.h" -#include "drm_agp_tmp.h" +#include "drm_agpsupport.h" #include "drm_auth.h" #include "drm_bufs.h" #include "drm_context.h" @@ -52,4 +52,4 @@ #include "drm_proc.h" #include "drm_vm.h" #include "drm_stub.h" -#include "drm_sg_tmp.h" +#include "drm_scatter.h" diff --git a/linux/radeon_drv.c b/linux/radeon_drv.c index 1473e2ee..6152b8a5 100644 --- a/linux/radeon_drv.c +++ b/linux/radeon_drv.c @@ -38,7 +38,7 @@ #include "radeon_drv.h" #include "ati_pcigart.h" -#include "drm_agp_tmp.h" +#include "drm_agpsupport.h" #include "drm_auth.h" #include "drm_bufs.h" #include "drm_context.h" @@ -53,4 +53,4 @@ #include "drm_proc.h" #include "drm_vm.h" #include "drm_stub.h" -#include "drm_sg_tmp.h" +#include "drm_scatter.h" diff --git a/linux/sis_drv.c b/linux/sis_drv.c index 64d0754f..3dd075d3 100644 --- a/linux/sis_drv.c +++ b/linux/sis_drv.c @@ -32,7 +32,7 @@ #include "sis_drv.h" #include "drm_auth.h" -#include "drm_agp_tmp.h" +#include "drm_agpsupport.h" #include "drm_bufs.h" #include "drm_context.h" #include "drm_dma.h" -- cgit v1.2.3