summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@linux.ie>2004-09-03 14:54:53 +0000
committerDave Airlie <airlied@linux.ie>2004-09-03 14:54:53 +0000
commit4b1acac672f93bed056ae5563a82826e7ab634b1 (patch)
treeae3cc0a2d1a9c6680b620f3d7918831343667f24
parent838bb7af71b5730de55549a74c8198215c1f1475 (diff)
initial hack of library splitdrmlib-0-0-1-branch
-rw-r--r--linux-core/Makefile4
-rw-r--r--linux-core/Makefile.kernel7
-rw-r--r--linux-core/drmP.h729
-rw-r--r--linux-core/drm_auth.c4
-rw-r--r--linux-core/drm_context.c14
-rw-r--r--linux-core/drm_core.h699
-rw-r--r--linux-core/drm_drv.c129
-rw-r--r--linux-core/drm_fops.c4
-rw-r--r--linux-core/drm_ioctl.c8
-rw-r--r--linux-core/drm_irq.c4
-rw-r--r--linux-core/drm_scatter.c24
-rw-r--r--linux-core/drm_stub.c8
-rw-r--r--linux-core/drm_vm.c10
-rw-r--r--linux-core/radeon_drv.c8
-rw-r--r--linux/Makefile4
-rw-r--r--linux/Makefile.kernel7
-rw-r--r--linux/ati_pcigart.c206
-rw-r--r--linux/drmP.h729
-rw-r--r--linux/drm_agpsupport.c473
-rw-r--r--linux/drm_auth.h4
-rw-r--r--linux/drm_bufs.c1346
-rw-r--r--linux/drm_context.h14
-rw-r--r--linux/drm_core.h699
-rw-r--r--linux/drm_core_memory.h147
-rw-r--r--linux/drm_dma.c183
-rw-r--r--linux/drm_drv.h129
-rw-r--r--linux/drm_fops.h4
-rw-r--r--linux/drm_headers.h52
-rw-r--r--linux/drm_ioctl.h8
-rw-r--r--linux/drm_irq.h4
-rw-r--r--linux/drm_memory.c203
-rw-r--r--linux/drm_memory_debug.c463
-rw-r--r--linux/drm_proc.c541
-rw-r--r--linux/drm_scatter.h24
-rw-r--r--linux/drm_stub.h8
-rw-r--r--linux/drm_vm.h10
-rw-r--r--linux/drmcore_exports.c32
-rw-r--r--linux/radeon_drv.c8
38 files changed, 5282 insertions, 1668 deletions
diff --git a/linux-core/Makefile b/linux-core/Makefile
index 9cfe7d5c..1bff058f 100644
--- a/linux-core/Makefile
+++ b/linux-core/Makefile
@@ -50,12 +50,12 @@ endif
MACHINE := $(shell uname -m)
# Modules for all architectures
-MODULE_LIST := tdfx.o r128.o radeon.o mga.o sis.o savage.o via.o mach64.o
+MODULE_LIST := #tdfx.o r128.o radeon.o mga.o sis.o savage.o via.o mach64.o
# Modules only for ix86 architectures
ifneq (,$(findstring 86,$(MACHINE)))
ARCHX86 := 1
-MODULE_LIST += i830.o i810.o i915.o
+MODULE_LIST += #i830.o i810.o i915.o
endif
ifneq (,$(findstring sparc64,$(MACHINE)))
diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel
index 92e3f73e..8e68d40a 100644
--- a/linux-core/Makefile.kernel
+++ b/linux-core/Makefile.kernel
@@ -7,6 +7,7 @@
# $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.kernel,v 1.18 2003/08/16 17:59:17 dawes Exp $
#
+drmcore-objs :=
tdfx-objs := tdfx_drv.o
r128-objs := r128_drv.o r128_cce.o r128_state.o r128_irq.o
mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o
@@ -41,9 +42,11 @@ obj- :=
export-objs := via_mm.o
endif
+drmcore-y := drm_bufs.o drm_memory.o drm_memory_debug.o drm_agpsupport.o drm_dma.o ati_pcigart.o drm_proc.o drmcore_exports.o
+obj-m += drmcore.o radeon.o
obj-$(CONFIG_DRM_TDFX) += tdfx.o
-obj-$(CONFIG_DRM_R128) += r128.o
-obj-$(CONFIG_DRM_RADEON)+= radeon.o
+obj-$(CONFIG_DRM_R128) += r128.o
+obj-$(CONFIG_DRM_RADEON)+= radeon.o drmcore.o
obj-$(CONFIG_DRM_MGA) += mga.o
obj-$(CONFIG_DRM_I810) += i810.o
obj-$(CONFIG_DRM_I830) += i830.o
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 495277f6..b26f6189 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -36,179 +36,27 @@
#ifdef __KERNEL__
-#ifdef __alpha__
-/* add include of current.h so that "current" is defined
- * before static inline funcs in wait.h. Doing this so we
- * can build the DRM (part of PI DRI). 4/21/2000 S + B */
-#include <asm/current.h>
-#endif /* __alpha__ */
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/miscdevice.h>
-#include <linux/fs.h>
-#include <linux/proc_fs.h>
-#include <linux/init.h>
-#include <linux/file.h>
-#include <linux/pci.h>
-#include <linux/version.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h> /* For (un)lock_kernel */
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-#if defined(__alpha__) || defined(__powerpc__)
-#include <asm/pgtable.h> /* For pte_wrprotect */
-#endif
-#include <asm/io.h>
-#include <asm/mman.h>
-#include <asm/uaccess.h>
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-#include <linux/types.h>
-#include <linux/agp_backend.h>
-#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,41)
-#define HAS_WORKQUEUE 0
-#else
-#define HAS_WORKQUEUE 1
-#endif
-#if !HAS_WORKQUEUE
-#include <linux/tqueue.h>
-#else
-#include <linux/workqueue.h>
-#endif
-#include <linux/poll.h>
-#include <asm/pgalloc.h>
-#include "drm.h"
-
-#include "drm_os_linux.h"
/* If you want the memory alloc debug functionality, change define below */
/* #define DEBUG_MEMORY */
/***********************************************************************/
-/** \name DRM template customization defaults */
-/*@{*/
-
-/* driver capabilities and requirements mask */
-#define DRIVER_USE_AGP 0x1
-#define DRIVER_REQUIRE_AGP 0x2
-#define DRIVER_USE_MTRR 0x4
-#define DRIVER_HAVE_DMA 0x10
-#define DRIVER_HAVE_IRQ 0x20
-#define DRIVER_SG 0x40
-#define DRIVER_PCI_DMA 0x80
-#define DRIVER_IRQ_SHARED 0x100
-#define DRIVER_IRQ_VBL 0x200
-#define DRIVER_DMA_QUEUE 0x800
-
-#define __OS_HAS_AGP (defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE))
-#define __OS_HAS_MTRR (defined(CONFIG_MTRR))
-/*@}*/
-
-
-/***********************************************************************/
/** \name Begin the DRM... */
/*@{*/
-#define DRM_DEBUG_CODE 2 /**< Include debugging code if > 1, then
- also include looping detection. */
-
-#define DRM_HASH_SIZE 16 /**< Size of key hash table. Must be power of 2. */
-#define DRM_KERNEL_CONTEXT 0 /**< Change drm_resctx if changed */
-#define DRM_RESERVED_CONTEXTS 1 /**< Change drm_resctx if changed */
-#define DRM_LOOPING_LIMIT 5000000
-#define DRM_BSZ 1024 /**< Buffer size for /dev/drm? output */
-#define DRM_TIME_SLICE (HZ/20) /**< Time slice for GLXContexts */
-#define DRM_LOCK_SLICE 1 /**< Time slice for lock, in jiffies */
-
-#define DRM_FLAG_DEBUG 0x01
-
-#define DRM_MEM_DMA 0
-#define DRM_MEM_SAREA 1
-#define DRM_MEM_DRIVER 2
-#define DRM_MEM_MAGIC 3
-#define DRM_MEM_IOCTLS 4
-#define DRM_MEM_MAPS 5
-#define DRM_MEM_VMAS 6
-#define DRM_MEM_BUFS 7
-#define DRM_MEM_SEGS 8
-#define DRM_MEM_PAGES 9
-#define DRM_MEM_FILES 10
-#define DRM_MEM_QUEUES 11
-#define DRM_MEM_CMDS 12
-#define DRM_MEM_MAPPINGS 13
-#define DRM_MEM_BUFLISTS 14
-#define DRM_MEM_AGPLISTS 15
-#define DRM_MEM_TOTALAGP 16
-#define DRM_MEM_BOUNDAGP 17
-#define DRM_MEM_CTXBITMAP 18
-#define DRM_MEM_STUB 19
-#define DRM_MEM_SGLISTS 20
-#define DRM_MEM_CTXLIST 21
#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
/*@}*/
-#include "drm_compat.h"
+#include "drm_core.h"
/***********************************************************************/
/** \name Macros to make printk easier */
/*@{*/
-/**
- * Error output.
- *
- * \param fmt printf() like format string.
- * \param arg arguments
- */
-#define DRM_ERROR(fmt, arg...) \
- printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* " fmt , __FUNCTION__ , ##arg)
-
-/**
- * Memory error output.
- *
- * \param area memory area where the error occurred.
- * \param fmt printf() like format string.
- * \param arg arguments
- */
-#define DRM_MEM_ERROR(area, fmt, arg...) \
- printk(KERN_ERR "[" DRM_NAME ":%s:%s] *ERROR* " fmt , __FUNCTION__, \
- DRM(mem_stats)[area].name , ##arg)
-#define DRM_INFO(fmt, arg...) printk(KERN_INFO "[" DRM_NAME "] " fmt , ##arg)
-
-/**
- * Debug output.
- *
- * \param fmt printf() like format string.
- * \param arg arguments
- */
-#if DRM_DEBUG_CODE
-#define DRM_DEBUG(fmt, arg...) \
- do { \
- if ( DRM(flags) & DRM_FLAG_DEBUG ) \
- printk(KERN_DEBUG \
- "[" DRM_NAME ":%s] " fmt , \
- __FUNCTION__ , ##arg); \
- } while (0)
-#else
-#define DRM_DEBUG(fmt, arg...) do { } while (0)
-#endif
-
-#define DRM_PROC_LIMIT (PAGE_SIZE-80)
-
-#define DRM_PROC_PRINT(fmt, arg...) \
- len += sprintf(&buf[len], fmt , ##arg); \
- if (len > DRM_PROC_LIMIT) { *eof = 1; return len - offset; }
-
-#define DRM_PROC_PRINT_RET(ret, fmt, arg...) \
- len += sprintf(&buf[len], fmt , ##arg); \
- if (len > DRM_PROC_LIMIT) { ret; *eof = 1; return len - offset; }
/*@}*/
@@ -221,9 +69,6 @@
#define DRM_MIN(a,b) ((a)<(b)?(a):(b))
#define DRM_MAX(a,b) ((a)>(b)?(a):(b))
-#define DRM_LEFTCOUNT(x) (((x)->rp + (x)->count - (x)->wp) % ((x)->count + 1))
-#define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x))
-#define DRM_WAITCOUNT(dev,idx) DRM_BUFCOUNT(&dev->queuelist[idx]->waitlist)
#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
/**
@@ -253,440 +98,6 @@ do { \
} \
} while (0)
-/**
- * Ioctl function type.
- *
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param arg argument.
- */
-typedef int drm_ioctl_t( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-
-typedef struct drm_ioctl_desc {
- drm_ioctl_t *func;
- int auth_needed;
- int root_only;
-} drm_ioctl_desc_t;
-
-typedef struct drm_devstate {
- pid_t owner; /**< X server pid holding x_lock */
-} drm_devstate_t;
-
-typedef struct drm_magic_entry {
- drm_magic_t magic;
- struct drm_file *priv;
- struct drm_magic_entry *next;
-} drm_magic_entry_t;
-
-typedef struct drm_magic_head {
- struct drm_magic_entry *head;
- struct drm_magic_entry *tail;
-} drm_magic_head_t;
-
-typedef struct drm_vma_entry {
- struct vm_area_struct *vma;
- struct drm_vma_entry *next;
- pid_t pid;
-} drm_vma_entry_t;
-
-/**
- * DMA buffer.
- */
-typedef struct drm_buf {
- int idx; /**< Index into master buflist */
- int total; /**< Buffer size */
- int order; /**< log-base-2(total) */
- int used; /**< Amount of buffer in use (for DMA) */
- unsigned long offset; /**< Byte offset (used internally) */
- void *address; /**< Address of buffer */
- unsigned long bus_address; /**< Bus address of buffer */
- struct drm_buf *next; /**< Kernel-only: used for free list */
- __volatile__ int waiting; /**< On kernel DMA queue */
- __volatile__ int pending; /**< On hardware DMA queue */
- wait_queue_head_t dma_wait; /**< Processes waiting */
- struct file *filp; /**< Pointer to holding file descr */
- int context; /**< Kernel queue for this buffer */
- int while_locked;/**< Dispatch this buffer while locked */
- enum {
- DRM_LIST_NONE = 0,
- DRM_LIST_FREE = 1,
- DRM_LIST_WAIT = 2,
- DRM_LIST_PEND = 3,
- DRM_LIST_PRIO = 4,
- DRM_LIST_RECLAIM = 5
- } list; /**< Which list we're on */
-
- int dev_priv_size; /**< Size of buffer private storage */
- void *dev_private; /**< Per-buffer private storage */
-} drm_buf_t;
-
-
-/** bufs is one longer than it has to be */
-typedef struct drm_waitlist {
- int count; /**< Number of possible buffers */
- drm_buf_t **bufs; /**< List of pointers to buffers */
- drm_buf_t **rp; /**< Read pointer */
- drm_buf_t **wp; /**< Write pointer */
- drm_buf_t **end; /**< End pointer */
- spinlock_t read_lock;
- spinlock_t write_lock;
-} drm_waitlist_t;
-
-typedef struct drm_freelist {
- int initialized; /**< Freelist in use */
- atomic_t count; /**< Number of free buffers */
- drm_buf_t *next; /**< End pointer */
-
- wait_queue_head_t waiting; /**< Processes waiting on free bufs */
- int low_mark; /**< Low water mark */
- int high_mark; /**< High water mark */
- atomic_t wfh; /**< If waiting for high mark */
- spinlock_t lock;
-} drm_freelist_t;
-
-/**
- * Buffer entry. There is one of this for each buffer size order.
- */
-typedef struct drm_buf_entry {
- int buf_size; /**< size */
- int buf_count; /**< number of buffers */
- drm_buf_t *buflist; /**< buffer list */
- int seg_count;
- int page_order;
- unsigned long *seglist;
-
- drm_freelist_t freelist;
-} drm_buf_entry_t;
-
-/** File private data */
-typedef struct drm_file {
- int authenticated;
- int minor;
- pid_t pid;
- uid_t uid;
- drm_magic_t magic;
- unsigned long ioctl_count;
- struct drm_file *next;
- struct drm_file *prev;
- struct drm_device *dev;
- int remove_auth_on_close;
- unsigned long lock_count;
- void *driver_priv;
-} drm_file_t;
-
-/** Wait queue */
-typedef struct drm_queue {
- atomic_t use_count; /**< Outstanding uses (+1) */
- atomic_t finalization; /**< Finalization in progress */
- atomic_t block_count; /**< Count of processes waiting */
- atomic_t block_read; /**< Queue blocked for reads */
- wait_queue_head_t read_queue; /**< Processes waiting on block_read */
- atomic_t block_write; /**< Queue blocked for writes */
- wait_queue_head_t write_queue; /**< Processes waiting on block_write */
-#if 1
- atomic_t total_queued; /**< Total queued statistic */
- atomic_t total_flushed;/**< Total flushes statistic */
- atomic_t total_locks; /**< Total locks statistics */
-#endif
- drm_ctx_flags_t flags; /**< Context preserving and 2D-only */
- drm_waitlist_t waitlist; /**< Pending buffers */
- wait_queue_head_t flush_queue; /**< Processes waiting until flush */
-} drm_queue_t;
-
-/**
- * Lock data.
- */
-typedef struct drm_lock_data {
- drm_hw_lock_t *hw_lock; /**< Hardware lock */
- struct file *filp; /**< File descr of lock holder (0=kernel) */
- wait_queue_head_t lock_queue; /**< Queue of blocked processes */
- unsigned long lock_time; /**< Time of last lock in jiffies */
-} drm_lock_data_t;
-
-/**
- * DMA data.
- */
-typedef struct drm_device_dma {
-
- drm_buf_entry_t bufs[DRM_MAX_ORDER+1]; /**< buffers, grouped by their size order */
- int buf_count; /**< total number of buffers */
- drm_buf_t **buflist; /**< Vector of pointers into drm_device_dma::bufs */
- int seg_count;
- int page_count; /**< number of pages */
- unsigned long *pagelist; /**< page list */
- unsigned long byte_count;
- enum {
- _DRM_DMA_USE_AGP = 0x01,
- _DRM_DMA_USE_SG = 0x02
- } flags;
-
- /** \name DMA support */
- /*@{*/
- drm_buf_t *this_buffer; /**< Buffer being sent */
- drm_buf_t *next_buffer; /**< Selected buffer to send */
- drm_queue_t *next_queue; /**< Queue from which buffer selected*/
- wait_queue_head_t waiting; /**< Processes waiting on free bufs */
- /*@}*/
-} drm_device_dma_t;
-
-#if __OS_HAS_AGP
-/**
- * AGP memory entry. Stored as a doubly linked list.
- */
-typedef struct drm_agp_mem {
- unsigned long handle; /**< handle */
- DRM_AGP_MEM *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 {
- DRM_AGP_KERN 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;
-} drm_sigdata_t;
-
-/**
- * Mappings list
- */
-typedef struct drm_map_list {
- struct list_head head; /**< list head */
- drm_map_t *map; /**< mapping */
-} drm_map_list_t;
-
-typedef drm_map_t drm_local_map_t;
-
-/**
- * Context handle list
- */
-typedef struct drm_ctx_list {
- struct list_head head; /**< list head */
- drm_context_t handle; /**< context handle */
- drm_file_t *tag; /**< associated fd private data */
-} drm_ctx_list_t;
-
-
-typedef struct drm_vbl_sig {
- struct list_head head;
- unsigned int sequence;
- struct siginfo info;
- struct task_struct *task;
-} drm_vbl_sig_t;
-
-
-/**
- * DRM device functions structure
- */
-struct drm_device;
-
-struct drm_driver_fn {
- int (*preinit)(struct drm_device *, unsigned long flags);
- int (*postinit)(struct drm_device *, unsigned long flags);
- void (*prerelease)(struct drm_device *, struct file *filp);
- void (*pretakedown)(struct drm_device *);
- int (*postcleanup)(struct drm_device *);
- int (*presetup)(struct drm_device *);
- int (*postsetup)(struct drm_device *);
-
- /* these are opposites at the moment */
- int (*open_helper)(struct drm_device *, drm_file_t *);
- void (*free_filp_private)(struct drm_device *, drm_file_t *);
-
- void (*release)(struct drm_device *, struct file *filp);
- void (*dma_ready)(struct drm_device *);
- int (*dma_quiescent)(struct drm_device *);
- int (*context_ctor)(struct drm_device *dev, int context);
- int (*context_dtor)(struct drm_device *dev, int context);
- int (*kernel_context_switch)(struct drm_device *dev, int old, int new);
- int (*kernel_context_switch_unlock)(struct drm_device *dev);
- int (*vblank_wait)(struct drm_device *dev, unsigned int *sequence);
-/* these have to be filled in */
- irqreturn_t (*irq_handler)( DRM_IRQ_ARGS );
- void (*irq_preinstall)(struct drm_device *dev);
- void (*irq_postinstall)(struct drm_device *dev);
- void (*irq_uninstall)(struct drm_device *dev);
- void (*reclaim_buffers)(struct file *filp);
- unsigned long (*get_map_ofs)(drm_map_t *map);
- unsigned long (*get_reg_ofs)(struct drm_device *dev);
- void (*set_version)(struct drm_device *dev, drm_set_version_t *sv);
-};
-
-/**
- * DRM device structure.
- */
-typedef struct drm_device {
- const char *name; /**< Simple driver name */
- char *unique; /**< Unique identifier: e.g., busid */
- int unique_len; /**< Length of unique field */
- dev_t device; /**< Device number for mknod */
- char *devname; /**< For /proc/interrupts */
- int minor; /**< Minor device number */
- int if_version; /**< Highest interface version set */
-
- int blocked; /**< Blocked due to VC switch? */
- struct proc_dir_entry *root; /**< Root for this device's entries */
-
- /** \name Locks */
- /*@{*/
- spinlock_t count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */
- struct semaphore struct_sem; /**< For others */
- /*@}*/
-
- /** \name Usage Counters */
- /*@{*/
- int open_count; /**< Outstanding files open */
- atomic_t ioctl_count; /**< Outstanding IOCTLs pending */
- atomic_t vma_count; /**< Outstanding vma areas open */
- int buf_use; /**< Buffers in use -- cannot alloc */
- atomic_t buf_alloc; /**< Buffer allocation in progress */
- /*@}*/
-
- /** \name Performance counters */
- /*@{*/
- unsigned long counters;
- drm_stat_type_t types[15];
- atomic_t counts[15];
- /*@}*/
-
- /** \name Authentication */
- /*@{*/
- drm_file_t *file_first; /**< file list head */
- drm_file_t *file_last; /**< file list tail */
- drm_magic_head_t magiclist[DRM_HASH_SIZE]; /**< magic hash table */
- /*@}*/
-
- /** \name Memory management */
- /*@{*/
- drm_map_list_t *maplist; /**< Linked list of regions */
- int map_count; /**< Number of mappable regions */
-
- /** \name Context handle management */
- /*@{*/
- drm_ctx_list_t *ctxlist; /**< Linked list of context handles */
- int ctx_count; /**< Number of context handles */
- struct semaphore ctxlist_sem; /**< For ctxlist */
-
- drm_map_t **context_sareas; /**< per-context SAREA's */
- int max_context;
-
- drm_vma_entry_t *vmalist; /**< List of vmas (for debugging) */
- drm_lock_data_t lock; /**< Information on hardware lock */
- /*@}*/
-
- /** \name DMA queues (contexts) */
- /*@{*/
- int queue_count; /**< Number of active DMA queues */
- int queue_reserved; /**< Number of reserved DMA queues */
- int queue_slots; /**< Actual length of queuelist */
- drm_queue_t **queuelist; /**< Vector of pointers to DMA queues */
- drm_device_dma_t *dma; /**< Optional pointer for DMA support */
- /*@}*/
-
- /** \name Context support */
- /*@{*/
- int irq; /**< Interrupt used by board */
- int irq_enabled; /**< True if irq handler is enabled */
- __volatile__ long context_flag; /**< Context swapping flag */
- __volatile__ long interrupt_flag; /**< Interruption handler flag */
- __volatile__ long dma_flag; /**< DMA dispatch flag */
- struct timer_list timer; /**< Timer for delaying ctx switch */
- wait_queue_head_t context_wait; /**< Processes waiting on ctx switch */
- int last_checked; /**< Last context checked for DMA */
- int last_context; /**< Last current context */
- unsigned long last_switch; /**< jiffies at last context switch */
- /*@}*/
-
-#if !HAS_WORKQUEUE
- struct tq_struct tq;
-#else
- struct work_struct work;
-#endif
- /** \name VBLANK IRQ support */
- /*@{*/
-
- wait_queue_head_t vbl_queue; /**< VBLANK wait queue */
- atomic_t vbl_received;
- spinlock_t vbl_lock;
- drm_vbl_sig_t vbl_sigs; /**< signal list to send on VBLANK */
- unsigned int vbl_pending;
-
- /*@}*/
- cycles_t ctx_start;
- cycles_t lck_start;
-
- char buf[DRM_BSZ]; /**< Output buffer */
- char *buf_rp; /**< Read pointer */
- char *buf_wp; /**< Write pointer */
- char *buf_end; /**< End pointer */
- struct fasync_struct *buf_async;/**< Processes waiting for SIGIO */
- wait_queue_head_t buf_readers; /**< Processes waiting to read */
- wait_queue_head_t buf_writers; /**< Processes waiting to ctx switch */
-
-#if __OS_HAS_AGP
- drm_agp_head_t *agp; /**< AGP data */
-#endif
-
- struct pci_dev *pdev; /**< PCI device structure */
- int pci_domain; /**< PCI bus domain number */
- int pci_bus; /**< PCI bus number */
- int pci_slot; /**< PCI slot number */
- int pci_func; /**< PCI function number */
-#ifdef __alpha__
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3)
- struct pci_controler *hose;
-#else
- struct pci_controller *hose;
-#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;
-
- int need_reset; /**< secondary device needing reset */
- struct drm_driver_fn fn_tbl;
- drm_local_map_t *agp_buffer_map;
- int dev_priv_size;
- u32 driver_features;
-} drm_device_t;
-
-static __inline__ int drm_core_check_feature(struct drm_device *dev, int feature)
-{
- return ((dev->driver_features & feature) ? 1 : 0);
-}
extern void DRM(driver_register_fns)(struct drm_device *dev);
@@ -729,27 +140,6 @@ extern int DRM(mmap)(struct file *filp, struct vm_area_struct *vma);
extern unsigned int DRM(poll)(struct file *filp, struct poll_table_struct *wait);
extern ssize_t DRM(read)(struct file *filp, char __user *buf, size_t count, loff_t *off);
- /* Memory management support (drm_memory.h) */
-extern void DRM(mem_init)(void);
-extern int DRM(mem_info)(char *buf, char **start, off_t offset,
- int request, int *eof, void *data);
-extern void *DRM(calloc)(size_t nmemb, size_t size, int area);
-extern void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size,
- int area);
-extern unsigned long DRM(alloc_pages)(int order, int area);
-extern void DRM(free_pages)(unsigned long address, int order,
- int area);
-extern void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev);
-extern void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size,
- drm_device_t *dev);
-extern void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev);
-
-#if __OS_HAS_AGP
-extern DRM_AGP_MEM *DRM(alloc_agp)(int pages, u32 type);
-extern int DRM(free_agp)(DRM_AGP_MEM *handle, int pages);
-extern int DRM(bind_agp)(DRM_AGP_MEM *handle, unsigned int start);
-extern int DRM(unbind_agp)(DRM_AGP_MEM *handle);
-#endif
/* Misc. IOCTL support (drm_ioctl.h) */
extern int DRM(irq_by_busid)(struct inode *inode, struct file *filp,
@@ -825,31 +215,6 @@ extern int DRM(lock_free)(drm_device_t *dev,
unsigned int context);
extern int DRM(notifier)(void *priv);
- /* Buffer management support (drm_bufs.h) */
-extern int DRM(order)( unsigned long size );
-extern int DRM(addmap)( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int DRM(rmmap)( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int DRM(initmap)( drm_device_t *dev, unsigned int offset,
- unsigned int size, int type, int flags );
-extern int DRM(addbufs)( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int DRM(infobufs)( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int DRM(markbufs)( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int DRM(freebufs)( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int DRM(mapbufs)( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-
- /* DMA support (drm_dma.h) */
-extern int DRM(dma_setup)(drm_device_t *dev);
-extern void DRM(dma_takedown)(drm_device_t *dev);
-extern void DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf);
-extern void DRM(reclaim_buffers)( struct file *filp );
-
/* IRQ support (drm_irq.h) */
extern int DRM(control)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg );
@@ -866,32 +231,7 @@ extern int DRM(vblank_wait)(drm_device_t *dev, unsigned int *vbl_seq);
extern void DRM(vbl_send_signals)( drm_device_t *dev );
-#if __OS_HAS_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 DRM_AGP_MEM *DRM(agp_allocate_memory)(size_t pages, u32 type);
-extern int DRM(agp_free_memory)(DRM_AGP_MEM *handle);
-extern int DRM(agp_bind_memory)(DRM_AGP_MEM *handle, off_t start);
-extern int DRM(agp_unbind_memory)(DRM_AGP_MEM *handle);
-#endif
+
/* Stub support (drm_stub.h) */
int DRM(stub_register)(const char *name,
@@ -900,11 +240,11 @@ int DRM(stub_register)(const char *name,
int DRM(stub_unregister)(int minor);
/* Proc support (drm_proc.h) */
-extern int DRM(proc_init)(drm_device_t *dev,
+extern int drm_proc_init(drm_device_t *dev,
int minor,
struct proc_dir_entry *root,
struct proc_dir_entry **dev_root);
-extern int DRM(proc_cleanup)(int minor,
+extern int drm_proc_cleanup(int minor,
struct proc_dir_entry *root,
struct proc_dir_entry *dev_root);
@@ -915,13 +255,7 @@ extern int DRM(sg_alloc)(struct inode *inode, struct file *filp,
extern int DRM(sg_free)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
- /* ATI PCIGART support (ati_pcigart.h) */
-extern int DRM(ati_pcigart_init)(drm_device_t *dev,
- unsigned long *addr,
- dma_addr_t *bus_addr);
-extern int DRM(ati_pcigart_cleanup)(drm_device_t *dev,
- unsigned long addr,
- dma_addr_t bus_addr);
+
extern void *DRM(pci_alloc)(drm_device_t *dev, size_t size,
size_t align, dma_addr_t maxaddr,
@@ -930,56 +264,9 @@ extern void DRM(pci_free)(drm_device_t *dev, size_t size,
void *vaddr, dma_addr_t busaddr);
-/* Inline replacements for DRM_IOREMAP macros */
-static __inline__ void drm_core_ioremap(struct drm_map *map, struct drm_device *dev)
-{
- map->handle = DRM(ioremap)( map->offset, map->size, dev );
-}
-
-static __inline__ void drm_core_ioremap_nocache(struct drm_map *map, struct drm_device *dev)
-{
- map->handle = DRM(ioremap_nocache)(map->offset, map->size, dev);
-}
-
-static __inline__ void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev)
-{
- if ( map->handle && map->size )
- DRM(ioremapfree)( map->handle, map->size, dev );
-}
-
-static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, unsigned long offset)
-{
- struct list_head *_list;
- list_for_each( _list, &dev->maplist->head ) {
- drm_map_list_t *_entry = list_entry( _list, drm_map_list_t, head );
- if ( _entry->map &&
- _entry->map->offset == offset ) {
- return _entry->map;
- }
- }
- return NULL;
-}
-
-static __inline__ void drm_core_dropmap(struct drm_map *map)
-{
-}
-
-#ifndef DEBUG_MEMORY
-/** Wrapper around kmalloc() */
-static __inline__ void *DRM(alloc)(size_t size, int area)
-{
- return kmalloc(size, GFP_KERNEL);
-}
-
-/** Wrapper around kfree() */
-static __inline__ void DRM(free)(void *pt, size_t size, int area)
-{
- kfree(pt);
-}
-#else
-extern void *DRM(alloc)(size_t size, int area);
-extern void DRM(free)(void *pt, size_t size, int area);
-#endif
+
+
+
/*@}*/
diff --git a/linux-core/drm_auth.c b/linux-core/drm_auth.c
index fe099871..2931ac22 100644
--- a/linux-core/drm_auth.c
+++ b/linux-core/drm_auth.c
@@ -95,7 +95,7 @@ int DRM(add_magic)(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
DRM_DEBUG("%d\n", magic);
hash = DRM(hash_magic)(magic);
- entry = DRM(alloc)(sizeof(*entry), DRM_MEM_MAGIC);
+ entry = drm_core_alloc(sizeof(*entry), DRM_MEM_MAGIC);
if (!entry) return -ENOMEM;
memset(entry, 0, sizeof(*entry));
entry->magic = magic;
@@ -152,7 +152,7 @@ int DRM(remove_magic)(drm_device_t *dev, drm_magic_t magic)
}
up(&dev->struct_sem);
- DRM(free)(pt, sizeof(*pt), DRM_MEM_MAGIC);
+ drm_core_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
return -EINVAL;
}
diff --git a/linux-core/drm_context.c b/linux-core/drm_context.c
index e1cb95c6..8bad6b39 100644
--- a/linux-core/drm_context.c
+++ b/linux-core/drm_context.c
@@ -100,7 +100,7 @@ int DRM(ctxbitmap_next)( drm_device_t *dev )
if(dev->context_sareas) {
drm_map_t **ctx_sareas;
- ctx_sareas = DRM(realloc)(dev->context_sareas,
+ ctx_sareas = drm_core_realloc(dev->context_sareas,
(dev->max_context - 1) *
sizeof(*dev->context_sareas),
dev->max_context *
@@ -115,7 +115,7 @@ int DRM(ctxbitmap_next)( drm_device_t *dev )
dev->context_sareas[bit] = NULL;
} else {
/* max_context == 1 at this point */
- dev->context_sareas = DRM(alloc)(
+ dev->context_sareas = drm_core_alloc(
dev->max_context *
sizeof(*dev->context_sareas),
DRM_MEM_MAPS);
@@ -148,7 +148,7 @@ int DRM(ctxbitmap_init)( drm_device_t *dev )
int temp;
down(&dev->struct_sem);
- dev->ctx_bitmap = (unsigned long *) DRM(alloc)( PAGE_SIZE,
+ dev->ctx_bitmap = (unsigned long *) drm_core_alloc( PAGE_SIZE,
DRM_MEM_CTXBITMAP );
if ( dev->ctx_bitmap == NULL ) {
up(&dev->struct_sem);
@@ -178,11 +178,11 @@ int DRM(ctxbitmap_init)( drm_device_t *dev )
void DRM(ctxbitmap_cleanup)( drm_device_t *dev )
{
down(&dev->struct_sem);
- if( dev->context_sareas ) DRM(free)( dev->context_sareas,
+ if( dev->context_sareas ) drm_core_free( dev->context_sareas,
sizeof(*dev->context_sareas) *
dev->max_context,
DRM_MEM_MAPS );
- DRM(free)( (void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP );
+ drm_core_free( (void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP );
up(&dev->struct_sem);
}
@@ -421,7 +421,7 @@ int DRM(addctx)( struct inode *inode, struct file *filp,
dev->fn_tbl.context_ctor(dev, ctx.handle);
}
- ctx_entry = DRM(alloc)( sizeof(*ctx_entry), DRM_MEM_CTXLIST );
+ ctx_entry = drm_core_alloc( sizeof(*ctx_entry), DRM_MEM_CTXLIST );
if ( !ctx_entry ) {
DRM_DEBUG("out of memory\n");
return -ENOMEM;
@@ -564,7 +564,7 @@ int DRM(rmctx)( struct inode *inode, struct file *filp,
list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) {
if ( pos->handle == ctx.handle ) {
list_del( &pos->head );
- DRM(free)( pos, sizeof(*pos), DRM_MEM_CTXLIST );
+ drm_core_free( pos, sizeof(*pos), DRM_MEM_CTXLIST );
--dev->ctx_count;
}
}
diff --git a/linux-core/drm_core.h b/linux-core/drm_core.h
new file mode 100644
index 00000000..435d5cbf
--- /dev/null
+++ b/linux-core/drm_core.h
@@ -0,0 +1,699 @@
+#ifndef DRM_CORE_H
+#define DRM_CORE_H
+
+#include "drm_compat.h"
+#define DRM_PROC_LIMIT (PAGE_SIZE-80)
+
+#define DRM_PROC_PRINT(fmt, arg...) \
+ len += sprintf(&buf[len], fmt , ##arg); \
+ if (len > DRM_PROC_LIMIT) { *eof = 1; return len - offset; }
+
+#define DRM_PROC_PRINT_RET(ret, fmt, arg...) \
+ len += sprintf(&buf[len], fmt , ##arg); \
+ if (len > DRM_PROC_LIMIT) { ret; *eof = 1; return len - offset; }
+
+/**
+ * Memory error output.
+ *
+ * \param area memory area where the error occurred.
+ * \param fmt printf() like format string.
+ * \param arg arguments
+ */
+#define DRM_INFO(fmt, arg...) printk(KERN_INFO "[" DRM_NAME "] " fmt , ##arg)
+
+/**
+ * Error output.
+ *
+ * \param fmt printf() like format string.
+ * \param arg arguments
+ */
+#define DRM_ERROR(fmt, arg...) \
+ printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* " fmt , __FUNCTION__ , ##arg)
+
+#if DRM_DEBUG_CODE
+#define DRM_DEBUG(fmt, arg...) \
+ do { \
+ if (1) \
+ printk(KERN_DEBUG \
+ "[" DRM_NAME ":%s] " fmt , \
+ __FUNCTION__ , ##arg); \
+ } while (0)
+#else
+#define DRM_DEBUG(fmt, arg...) do { } while (0)
+#endif
+
+#define DRM_LEFTCOUNT(x) (((x)->rp + (x)->count - (x)->wp) % ((x)->count + 1))
+#define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x))
+#define DRM_WAITCOUNT(dev,idx) DRM_BUFCOUNT(&dev->queuelist[idx]->waitlist)
+
+
+/* driver capabilities and requirements mask */
+#define DRIVER_USE_AGP 0x1
+#define DRIVER_REQUIRE_AGP 0x2
+#define DRIVER_USE_MTRR 0x4
+#define DRIVER_HAVE_DMA 0x10
+#define DRIVER_HAVE_IRQ 0x20
+#define DRIVER_SG 0x40
+#define DRIVER_PCI_DMA 0x80
+#define DRIVER_IRQ_SHARED 0x100
+#define DRIVER_IRQ_VBL 0x200
+#define DRIVER_DMA_QUEUE 0x800
+
+#define __OS_HAS_AGP (defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE))
+#define __OS_HAS_MTRR (defined(CONFIG_MTRR))
+/*@}*/
+#define DRM_DEBUG_CODE 2 /**< Include debugging code if > 1, then
+ also include looping detection. */
+
+#define DRM_HASH_SIZE 16 /**< Size of key hash table. Must be power of 2. */
+#define DRM_KERNEL_CONTEXT 0 /**< Change drm_resctx if changed */
+#define DRM_RESERVED_CONTEXTS 1 /**< Change drm_resctx if changed */
+#define DRM_LOOPING_LIMIT 5000000
+#define DRM_BSZ 1024 /**< Buffer size for /dev/drm? output */
+#define DRM_TIME_SLICE (HZ/20) /**< Time slice for GLXContexts */
+#define DRM_LOCK_SLICE 1 /**< Time slice for lock, in jiffies */
+
+#define DRM_FLAG_DEBUG 0x01
+
+#define DRM_MEM_DMA 0
+#define DRM_MEM_SAREA 1
+#define DRM_MEM_DRIVER 2
+#define DRM_MEM_MAGIC 3
+#define DRM_MEM_IOCTLS 4
+#define DRM_MEM_MAPS 5
+#define DRM_MEM_VMAS 6
+#define DRM_MEM_BUFS 7
+#define DRM_MEM_SEGS 8
+#define DRM_MEM_PAGES 9
+#define DRM_MEM_FILES 10
+#define DRM_MEM_QUEUES 11
+#define DRM_MEM_CMDS 12
+#define DRM_MEM_MAPPINGS 13
+#define DRM_MEM_BUFLISTS 14
+#define DRM_MEM_AGPLISTS 15
+#define DRM_MEM_TOTALAGP 16
+#define DRM_MEM_BOUNDAGP 17
+#define DRM_MEM_CTXBITMAP 18
+#define DRM_MEM_STUB 19
+#define DRM_MEM_SGLISTS 20
+#define DRM_MEM_CTXLIST 21
+
+/**
+ * Ioctl function type.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg argument.
+ */
+typedef int drm_ioctl_t( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+
+typedef struct drm_ioctl_desc {
+ drm_ioctl_t *func;
+ int auth_needed;
+ int root_only;
+} drm_ioctl_desc_t;
+
+typedef struct drm_devstate {
+ pid_t owner; /**< X server pid holding x_lock */
+} drm_devstate_t;
+
+typedef struct drm_magic_entry {
+ drm_magic_t magic;
+ struct drm_file *priv;
+ struct drm_magic_entry *next;
+} drm_magic_entry_t;
+
+typedef struct drm_magic_head {
+ struct drm_magic_entry *head;
+ struct drm_magic_entry *tail;
+} drm_magic_head_t;
+
+typedef struct drm_vma_entry {
+ struct vm_area_struct *vma;
+ struct drm_vma_entry *next;
+ pid_t pid;
+} drm_vma_entry_t;
+
+/**
+ * DMA buffer.
+ */
+typedef struct drm_buf {
+ int idx; /**< Index into master buflist */
+ int total; /**< Buffer size */
+ int order; /**< log-base-2(total) */
+ int used; /**< Amount of buffer in use (for DMA) */
+ unsigned long offset; /**< Byte offset (used internally) */
+ void *address; /**< Address of buffer */
+ unsigned long bus_address; /**< Bus address of buffer */
+ struct drm_buf *next; /**< Kernel-only: used for free list */
+ __volatile__ int waiting; /**< On kernel DMA queue */
+ __volatile__ int pending; /**< On hardware DMA queue */
+ wait_queue_head_t dma_wait; /**< Processes waiting */
+ struct file *filp; /**< Pointer to holding file descr */
+ int context; /**< Kernel queue for this buffer */
+ int while_locked;/**< Dispatch this buffer while locked */
+ enum {
+ DRM_LIST_NONE = 0,
+ DRM_LIST_FREE = 1,
+ DRM_LIST_WAIT = 2,
+ DRM_LIST_PEND = 3,
+ DRM_LIST_PRIO = 4,
+ DRM_LIST_RECLAIM = 5
+ } list; /**< Which list we're on */
+
+ int dev_priv_size; /**< Size of buffer private storage */
+ void *dev_private; /**< Per-buffer private storage */
+} drm_buf_t;
+
+
+/** bufs is one longer than it has to be */
+typedef struct drm_waitlist {
+ int count; /**< Number of possible buffers */
+ drm_buf_t **bufs; /**< List of pointers to buffers */
+ drm_buf_t **rp; /**< Read pointer */
+ drm_buf_t **wp; /**< Write pointer */
+ drm_buf_t **end; /**< End pointer */
+ spinlock_t read_lock;
+ spinlock_t write_lock;
+} drm_waitlist_t;
+
+typedef struct drm_freelist {
+ int initialized; /**< Freelist in use */
+ atomic_t count; /**< Number of free buffers */
+ drm_buf_t *next; /**< End pointer */
+
+ wait_queue_head_t waiting; /**< Processes waiting on free bufs */
+ int low_mark; /**< Low water mark */
+ int high_mark; /**< High water mark */
+ atomic_t wfh; /**< If waiting for high mark */
+ spinlock_t lock;
+} drm_freelist_t;
+
+/**
+ * Buffer entry. There is one of this for each buffer size order.
+ */
+typedef struct drm_buf_entry {
+ int buf_size; /**< size */
+ int buf_count; /**< number of buffers */
+ drm_buf_t *buflist; /**< buffer list */
+ int seg_count;
+ int page_order;
+ unsigned long *seglist;
+
+ drm_freelist_t freelist;
+} drm_buf_entry_t;
+
+/** File private data */
+typedef struct drm_file {
+ int authenticated;
+ int minor;
+ pid_t pid;
+ uid_t uid;
+ drm_magic_t magic;
+ unsigned long ioctl_count;
+ struct drm_file *next;
+ struct drm_file *prev;
+ struct drm_device *dev;
+ int remove_auth_on_close;
+ unsigned long lock_count;
+ void *driver_priv;
+} drm_file_t;
+
+/** Wait queue */
+typedef struct drm_queue {
+ atomic_t use_count; /**< Outstanding uses (+1) */
+ atomic_t finalization; /**< Finalization in progress */
+ atomic_t block_count; /**< Count of processes waiting */
+ atomic_t block_read; /**< Queue blocked for reads */
+ wait_queue_head_t read_queue; /**< Processes waiting on block_read */
+ atomic_t block_write; /**< Queue blocked for writes */
+ wait_queue_head_t write_queue; /**< Processes waiting on block_write */
+#if 1
+ atomic_t total_queued; /**< Total queued statistic */
+ atomic_t total_flushed;/**< Total flushes statistic */
+ atomic_t total_locks; /**< Total locks statistics */
+#endif
+ drm_ctx_flags_t flags; /**< Context preserving and 2D-only */
+ drm_waitlist_t waitlist; /**< Pending buffers */
+ wait_queue_head_t flush_queue; /**< Processes waiting until flush */
+} drm_queue_t;
+
+/**
+ * Lock data.
+ */
+typedef struct drm_lock_data {
+ drm_hw_lock_t *hw_lock; /**< Hardware lock */
+ struct file *filp; /**< File descr of lock holder (0=kernel) */
+ wait_queue_head_t lock_queue; /**< Queue of blocked processes */
+ unsigned long lock_time; /**< Time of last lock in jiffies */
+} drm_lock_data_t;
+
+/**
+ * DMA data.
+ */
+typedef struct drm_device_dma {
+
+ drm_buf_entry_t bufs[DRM_MAX_ORDER+1]; /**< buffers, grouped by their size order */
+ int buf_count; /**< total number of buffers */
+ drm_buf_t **buflist; /**< Vector of pointers into drm_device_dma::bufs */
+ int seg_count;
+ int page_count; /**< number of pages */
+ unsigned long *pagelist; /**< page list */
+ unsigned long byte_count;
+ enum {
+ _DRM_DMA_USE_AGP = 0x01,
+ _DRM_DMA_USE_SG = 0x02
+ } flags;
+
+ /** \name DMA support */
+ /*@{*/
+ drm_buf_t *this_buffer; /**< Buffer being sent */
+ drm_buf_t *next_buffer; /**< Selected buffer to send */
+ drm_queue_t *next_queue; /**< Queue from which buffer selected*/
+ wait_queue_head_t waiting; /**< Processes waiting on free bufs */
+ /*@}*/
+} drm_device_dma_t;
+
+#if __OS_HAS_AGP
+/**
+ * AGP memory entry. Stored as a doubly linked list.
+ */
+typedef struct drm_agp_mem {
+ unsigned long handle; /**< handle */
+ DRM_AGP_MEM *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 {
+ DRM_AGP_KERN 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;
+} drm_sigdata_t;
+
+/**
+ * Mappings list
+ */
+typedef struct drm_map_list {
+ struct list_head head; /**< list head */
+ drm_map_t *map; /**< mapping */
+} drm_map_list_t;
+
+typedef drm_map_t drm_local_map_t;
+
+/**
+ * Context handle list
+ */
+typedef struct drm_ctx_list {
+ struct list_head head; /**< list head */
+ drm_context_t handle; /**< context handle */
+ drm_file_t *tag; /**< associated fd private data */
+} drm_ctx_list_t;
+
+
+typedef struct drm_vbl_sig {
+ struct list_head head;
+ unsigned int sequence;
+ struct siginfo info;
+ struct task_struct *task;
+} drm_vbl_sig_t;
+
+
+/**
+ * DRM device functions structure
+ */
+struct drm_device;
+
+struct drm_driver_fn {
+ int (*preinit)(struct drm_device *, unsigned long flags);
+ int (*postinit)(struct drm_device *, unsigned long flags);
+ void (*prerelease)(struct drm_device *, struct file *filp);
+ void (*pretakedown)(struct drm_device *);
+ int (*postcleanup)(struct drm_device *);
+ int (*presetup)(struct drm_device *);
+ int (*postsetup)(struct drm_device *);
+
+ /* these are opposites at the moment */
+ int (*open_helper)(struct drm_device *, drm_file_t *);
+ void (*free_filp_private)(struct drm_device *, drm_file_t *);
+
+ void (*release)(struct drm_device *, struct file *filp);
+ void (*dma_ready)(struct drm_device *);
+ int (*dma_quiescent)(struct drm_device *);
+ int (*context_ctor)(struct drm_device *dev, int context);
+ int (*context_dtor)(struct drm_device *dev, int context);
+ int (*kernel_context_switch)(struct drm_device *dev, int old, int new);
+ int (*kernel_context_switch_unlock)(struct drm_device *dev);
+ int (*vblank_wait)(struct drm_device *dev, unsigned int *sequence);
+/* these have to be filled in */
+ irqreturn_t (*irq_handler)( DRM_IRQ_ARGS );
+ void (*irq_preinstall)(struct drm_device *dev);
+ void (*irq_postinstall)(struct drm_device *dev);
+ void (*irq_uninstall)(struct drm_device *dev);
+ void (*reclaim_buffers)(struct file *filp);
+ unsigned long (*get_map_ofs)(drm_map_t *map);
+ unsigned long (*get_reg_ofs)(struct drm_device *dev);
+ void (*set_version)(struct drm_device *dev, drm_set_version_t *sv);
+};
+
+/**
+ * DRM device structure.
+ */
+typedef struct drm_device {
+ const char *name; /**< Simple driver name */
+ char *unique; /**< Unique identifier: e.g., busid */
+ int unique_len; /**< Length of unique field */
+ dev_t device; /**< Device number for mknod */
+ char *devname; /**< For /proc/interrupts */
+ int minor; /**< Minor device number */
+ int if_version; /**< Highest interface version set */
+
+ int blocked; /**< Blocked due to VC switch? */
+ struct proc_dir_entry *root; /**< Root for this device's entries */
+
+ /** \name Locks */
+ /*@{*/
+ spinlock_t count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */
+ struct semaphore struct_sem; /**< For others */
+ /*@}*/
+
+ /** \name Usage Counters */
+ /*@{*/
+ int open_count; /**< Outstanding files open */
+ atomic_t ioctl_count; /**< Outstanding IOCTLs pending */
+ atomic_t vma_count; /**< Outstanding vma areas open */
+ int buf_use; /**< Buffers in use -- cannot alloc */
+ atomic_t buf_alloc; /**< Buffer allocation in progress */
+ /*@}*/
+
+ /** \name Performance counters */
+ /*@{*/
+ unsigned long counters;
+ drm_stat_type_t types[15];
+ atomic_t counts[15];
+ /*@}*/
+
+ /** \name Authentication */
+ /*@{*/
+ drm_file_t *file_first; /**< file list head */
+ drm_file_t *file_last; /**< file list tail */
+ drm_magic_head_t magiclist[DRM_HASH_SIZE]; /**< magic hash table */
+ /*@}*/
+
+ /** \name Memory management */
+ /*@{*/
+ drm_map_list_t *maplist; /**< Linked list of regions */
+ int map_count; /**< Number of mappable regions */
+
+ /** \name Context handle management */
+ /*@{*/
+ drm_ctx_list_t *ctxlist; /**< Linked list of context handles */
+ int ctx_count; /**< Number of context handles */
+ struct semaphore ctxlist_sem; /**< For ctxlist */
+
+ drm_map_t **context_sareas; /**< per-context SAREA's */
+ int max_context;
+
+ drm_vma_entry_t *vmalist; /**< List of vmas (for debugging) */
+ drm_lock_data_t lock; /**< Information on hardware lock */
+ /*@}*/
+
+ /** \name DMA queues (contexts) */
+ /*@{*/
+ int queue_count; /**< Number of active DMA queues */
+ int queue_reserved; /**< Number of reserved DMA queues */
+ int queue_slots; /**< Actual length of queuelist */
+ drm_queue_t **queuelist; /**< Vector of pointers to DMA queues */
+ drm_device_dma_t *dma; /**< Optional pointer for DMA support */
+ /*@}*/
+
+ /** \name Context support */
+ /*@{*/
+ int irq; /**< Interrupt used by board */
+ int irq_enabled; /**< True if irq handler is enabled */
+ __volatile__ long context_flag; /**< Context swapping flag */
+ __volatile__ long interrupt_flag; /**< Interruption handler flag */
+ __volatile__ long dma_flag; /**< DMA dispatch flag */
+ struct timer_list timer; /**< Timer for delaying ctx switch */
+ wait_queue_head_t context_wait; /**< Processes waiting on ctx switch */
+ int last_checked; /**< Last context checked for DMA */
+ int last_context; /**< Last current context */
+ unsigned long last_switch; /**< jiffies at last context switch */
+ /*@}*/
+
+#if !HAS_WORKQUEUE
+ struct tq_struct tq;
+#else
+ struct work_struct work;
+#endif
+ /** \name VBLANK IRQ support */
+ /*@{*/
+
+ wait_queue_head_t vbl_queue; /**< VBLANK wait queue */
+ atomic_t vbl_received;
+ spinlock_t vbl_lock;
+ drm_vbl_sig_t vbl_sigs; /**< signal list to send on VBLANK */
+ unsigned int vbl_pending;
+
+ /*@}*/
+ cycles_t ctx_start;
+ cycles_t lck_start;
+
+ char buf[DRM_BSZ]; /**< Output buffer */
+ char *buf_rp; /**< Read pointer */
+ char *buf_wp; /**< Write pointer */
+ char *buf_end; /**< End pointer */
+ struct fasync_struct *buf_async;/**< Processes waiting for SIGIO */
+ wait_queue_head_t buf_readers; /**< Processes waiting to read */
+ wait_queue_head_t buf_writers; /**< Processes waiting to ctx switch */
+
+#if __OS_HAS_AGP
+ drm_agp_head_t *agp; /**< AGP data */
+#endif
+
+ struct pci_dev *pdev; /**< PCI device structure */
+ int pci_domain; /**< PCI bus domain number */
+ int pci_bus; /**< PCI bus number */
+ int pci_slot; /**< PCI slot number */
+ int pci_func; /**< PCI function number */
+#ifdef __alpha__
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3)
+ struct pci_controler *hose;
+#else
+ struct pci_controller *hose;
+#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;
+
+ int need_reset; /**< secondary device needing reset */
+ struct drm_driver_fn fn_tbl;
+ drm_local_map_t *agp_buffer_map;
+ int dev_priv_size;
+ u32 driver_features;
+} drm_device_t;
+
+#if __OS_HAS_AGP
+extern DRM_AGP_MEM *drm_memory_alloc_agp(int pages, u32 type);
+extern int drm_memory_free_agp(DRM_AGP_MEM *handle, int pages);
+extern int drm_memory_bind_agp(DRM_AGP_MEM *handle, unsigned int start);
+extern int drm_memory_unbind_agp(DRM_AGP_MEM *handle);
+#endif
+ /* Buffer management support (drm_bufs.h) */
+extern int drm_core_order( unsigned long size );
+extern int drm_core_addmap( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int drm_core_rmmap( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int drm_core_initmap( drm_device_t *dev, unsigned int offset,
+ unsigned int size, int type, int flags );
+extern int drm_core_addbufs( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int drm_core_infobufs( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int drm_core_markbufs( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int drm_core_freebufs( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int drm_core_mapbufs( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+
+ /* DMA support (drm_dma.h) */
+extern int drm_core_dma_setup(drm_device_t *dev);
+extern void drm_core_dma_takedown(drm_device_t *dev);
+extern void drm_core_free_buffer(drm_device_t *dev, drm_buf_t *buf);
+extern void drm_core_reclaim_buffers( struct file *filp );
+
+#if __OS_HAS_AGP
+ /* AGP/GART support (drm_agpsupport.h) */
+extern drm_agp_head_t *drm_memory_agp_init(void);
+extern void drm_memory_agp_uninit(void);
+extern int drm_memory_agp_acquire(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern void drm_memory_agp_do_release(void);
+extern int drm_memory_agp_release(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_memory_agp_enable(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_memory_agp_info(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_memory_agp_alloc(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_memory_agp_free(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_memory_agp_unbind(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_memory_agp_bind(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern DRM_AGP_MEM *drm_memory_agp_allocate_memory(size_t pages, u32 type);
+extern int drm_memory_agp_free_memory(DRM_AGP_MEM *handle);
+extern int drm_memory_agp_bind_memory(DRM_AGP_MEM *handle, off_t start);
+extern int drm_memory_agp_unbind_memory(DRM_AGP_MEM *handle);
+#endif
+
+ /* ATI PCIGART support (ati_pcigart.h) */
+extern int drm_ati_pcigart_init(drm_device_t *dev,
+ unsigned long *addr,
+ dma_addr_t *bus_addr);
+extern int drm_ati_pcigart_cleanup(drm_device_t *dev,
+ unsigned long addr,
+ dma_addr_t bus_addr);
+
+ /* Proc support (drm_proc.h) */
+extern int drm_proc_init(drm_device_t *dev,
+ int minor,
+ struct proc_dir_entry *root,
+ struct proc_dir_entry **dev_root);
+extern int drm_proc_cleanup(int minor,
+ struct proc_dir_entry *root,
+ struct proc_dir_entry *dev_root);
+
+
+static __inline__ int drm_core_check_feature(struct drm_device *dev, int feature)
+{
+ return ((dev->driver_features & feature) ? 1 : 0);
+}
+
+#include "drm_core_memory.h"
+
+#ifndef DEBUG_MEMORY
+/** Wrapper around kmalloc() */
+static __inline__ void *drm_core_alloc(size_t size, int area)
+{
+ return kmalloc(size, GFP_KERNEL);
+}
+
+/** Wrapper around kfree() */
+static __inline__ void drm_core_free(void *pt, size_t size, int area)
+{
+ kfree(pt);
+}
+
+static __inline__ void drm_core_ioremap(struct drm_map *map, struct drm_device *dev)
+{
+ map->handle = drm_ioremap( map->offset, map->size, dev );
+}
+
+static __inline__ void drm_core_ioremap_nocache(struct drm_map *map, struct drm_device *dev)
+{
+ map->handle = drm_ioremap_nocache(map->offset, map->size, dev);
+}
+
+static __inline__ void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev)
+{
+ if ( map->handle && map->size )
+ drm_ioremapfree( map->handle, map->size, dev );
+}
+
+static __inline__ void drm_core_free_pages(unsigned long address, int order, int area)
+{
+ drm_memory_free_pages(address, order, area);
+}
+
+static __inline__ void *drm_core_realloc(void *oldpt, size_t oldsize, size_t size, int area)
+{
+ return drm_memory_realloc(oldpt, oldsize, size, area);
+}
+
+static __inline__ unsigned long drm_core_alloc_pages(int order, int area)
+{
+ return drm_memory_alloc_pages(order, area);
+}
+
+static __inline__ void drm_core_mem_init(void)
+{
+ drm_memory_mem_init();
+}
+
+#else
+static __inline__ void *drm_core_alloc(size_t size, int area)
+{
+ return drm_memory_debug_alloc(size, area);
+}
+static __inline__ void drm_core_free(void *pt, size_t size, int area)
+{
+ drm_memory_debug_free(pt, size, area);
+}
+#endif
+
+
+static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, unsigned long offset)
+{
+ struct list_head *_list;
+ list_for_each( _list, &dev->maplist->head ) {
+ drm_map_list_t *_entry = list_entry( _list, drm_map_list_t, head );
+ if ( _entry->map &&
+ _entry->map->offset == offset ) {
+ return _entry->map;
+ }
+ }
+ return NULL;
+}
+
+static __inline__ void drm_core_dropmap(struct drm_map *map)
+{
+}
+
+extern int drm_core_dma_setup( drm_device_t *dev );
+extern void drm_core_dma_takedown(drm_device_t *dev);
+extern void drm_core_free_buffer(drm_device_t *dev, drm_buf_t *buf);
+extern void drm_core_reclaim_buffers( struct file *filp );
+
+
+
+#endif
diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c
index 8f42e357..e8cf159b 100644
--- a/linux-core/drm_drv.c
+++ b/linux-core/drm_drv.c
@@ -126,8 +126,8 @@ drm_ioctl_desc_t DRM(ioctls)[] = {
[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { DRM(noop), 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { DRM(authmagic), 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { DRM(addmap), 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = { DRM(rmmap), 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_core_addmap, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = { drm_core_rmmap, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { DRM(setsareactx), 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { DRM(getsareactx), 1, 0 },
@@ -148,24 +148,24 @@ drm_ioctl_desc_t DRM(ioctls)[] = {
[DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { DRM(noop), 1, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { DRM(addbufs), 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { DRM(markbufs), 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { DRM(infobufs), 1, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { DRM(mapbufs), 1, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { DRM(freebufs), 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { drm_core_addbufs, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_core_markbufs, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_core_infobufs, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { drm_core_mapbufs, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_core_freebufs, 1, 0 },
/* The DRM_IOCTL_DMA ioctl should be defined by the driver. */
[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { DRM(control), 1, 1 },
#if __OS_HAS_AGP
- [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 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_memory_agp_acquire, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_memory_agp_release, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_memory_agp_enable, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_memory_agp_info, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_memory_agp_alloc, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_memory_agp_free, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_memory_agp_bind, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_memory_agp_unbind, 1, 1 },
#endif
[DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = { DRM(sg_alloc), 1, 1 },
@@ -201,7 +201,7 @@ static int DRM(setup)( drm_device_t *dev )
if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
{
- i = DRM(dma_setup)( dev );
+ i = drm_core_dma_setup( dev );
if ( i < 0 )
return i;
}
@@ -249,7 +249,7 @@ static int DRM(setup)( drm_device_t *dev )
dev->magiclist[i].tail = NULL;
}
- dev->ctxlist = DRM(alloc)(sizeof(*dev->ctxlist),
+ dev->ctxlist = drm_core_alloc(sizeof(*dev->ctxlist),
DRM_MEM_CTXLIST);
if(dev->ctxlist == NULL) return -ENOMEM;
memset(dev->ctxlist, 0, sizeof(*dev->ctxlist));
@@ -327,13 +327,13 @@ static int DRM(takedown)( drm_device_t *dev )
del_timer( &dev->timer );
if ( dev->devname ) {
- DRM(free)( dev->devname, strlen( dev->devname ) + 1,
+ drm_core_free( dev->devname, strlen( dev->devname ) + 1,
DRM_MEM_DRIVER );
dev->devname = NULL;
}
if ( dev->unique ) {
- DRM(free)( dev->unique, strlen( dev->unique ) + 1,
+ drm_core_free( dev->unique, strlen( dev->unique ) + 1,
DRM_MEM_DRIVER );
dev->unique = NULL;
dev->unique_len = 0;
@@ -342,7 +342,7 @@ static int DRM(takedown)( drm_device_t *dev )
for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
for ( pt = dev->magiclist[i].head ; pt ; pt = next ) {
next = pt->next;
- DRM(free)( pt, sizeof(*pt), DRM_MEM_MAGIC );
+ drm_core_free( pt, sizeof(*pt), DRM_MEM_MAGIC );
}
dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
}
@@ -357,13 +357,13 @@ static int DRM(takedown)( drm_device_t *dev )
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 );
+ if ( entry->bound ) drm_memory_unbind_agp( entry->memory );
+ drm_memory_free_agp( entry->memory, entry->pages );
+ drm_core_free( entry, sizeof(*entry), DRM_MEM_AGPLISTS );
}
dev->agp->memory = NULL;
- if ( dev->agp->acquired ) DRM(agp_do_release)();
+ if ( dev->agp->acquired ) drm_memory_agp_do_release();
dev->agp->acquired = 0;
dev->agp->enabled = 0;
@@ -374,7 +374,7 @@ static int DRM(takedown)( drm_device_t *dev )
if ( dev->vmalist ) {
for ( vma = dev->vmalist ; vma ; vma = vma_next ) {
vma_next = vma->next;
- DRM(free)( vma, sizeof(*vma), DRM_MEM_VMAS );
+ drm_core_free( vma, sizeof(*vma), DRM_MEM_VMAS );
}
dev->vmalist = NULL;
}
@@ -406,10 +406,10 @@ static int DRM(takedown)( drm_device_t *dev )
}
break;
}
- DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
+ drm_core_free(map, sizeof(*map), DRM_MEM_MAPS);
}
list_del( list );
- DRM(free)(r_list, sizeof(*r_list), DRM_MEM_MAPS);
+ drm_core_free(r_list, sizeof(*r_list), DRM_MEM_MAPS);
}
}
@@ -418,13 +418,13 @@ static int DRM(takedown)( drm_device_t *dev )
for ( i = 0 ; i < dev->queue_count ; i++ ) {
if ( dev->queuelist[i] ) {
- DRM(free)( dev->queuelist[i],
+ drm_core_free( dev->queuelist[i],
sizeof(*dev->queuelist[0]),
DRM_MEM_QUEUES );
dev->queuelist[i] = NULL;
}
}
- DRM(free)( dev->queuelist,
+ drm_core_free( dev->queuelist,
dev->queue_slots * sizeof(*dev->queuelist),
DRM_MEM_QUEUES );
dev->queuelist = NULL;
@@ -432,7 +432,7 @@ static int DRM(takedown)( drm_device_t *dev )
dev->queue_count = 0;
if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
- DRM(dma_takedown)( dev );
+ drm_core_dma_takedown( dev );
if ( dev->lock.hw_lock ) {
dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */
@@ -447,7 +447,7 @@ static int DRM(takedown)( drm_device_t *dev )
static void DRM(init_fn_table)(struct drm_device *dev)
{
- dev->fn_tbl.reclaim_buffers = DRM(core_reclaim_buffers);
+ dev->fn_tbl.reclaim_buffers = drm_core_reclaim_buffers;
dev->fn_tbl.get_map_ofs = DRM(core_get_map_ofs);
dev->fn_tbl.get_reg_ofs = DRM(core_get_reg_ofs);
}
@@ -493,7 +493,7 @@ static int drm_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->pci_func = PCI_FUNC(pdev->devfn);
dev->irq = pdev->irq;
- dev->maplist = DRM(alloc)(sizeof(*dev->maplist), DRM_MEM_MAPS);
+ dev->maplist = drm_core_alloc(sizeof(*dev->maplist), DRM_MEM_MAPS);
if(dev->maplist == NULL) return -ENOMEM;
memset(dev->maplist, 0, sizeof(*dev->maplist));
INIT_LIST_HEAD(&dev->maplist->head);
@@ -511,7 +511,7 @@ static int drm_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
#if __OS_HAS_AGP
if (drm_core_check_feature(dev, DRIVER_USE_AGP)) {
- dev->agp = DRM(agp_init)();
+ dev->agp = drm_memory_agp_init();
if ( drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && dev->agp == NULL ) {
DRM_ERROR( "Cannot initialize the agpgart module.\n" );
retcode = -EINVAL;
@@ -609,7 +609,7 @@ static int __init drm_init( void )
DRM(parse_options)( drm_opts );
#endif
- DRM(mem_init)();
+ drm_core_mem_init();
for (i=0; (DRM(pciidlist)[i].vendor != 0) && !DRM(fb_loaded); i++) {
pid = &DRM(pciidlist[i]);
@@ -676,7 +676,7 @@ static void __exit drm_cleanup( drm_device_t *dev )
if ( ( map = r_list->map ) ) {
switch ( map->type ) {
case _DRM_REGISTERS:
- DRM(ioremapfree)( map->handle, map->size, dev );
+ drm_core_ioremapfree( map, dev );
break;
case _DRM_FRAME_BUFFER:
@@ -699,12 +699,12 @@ static void __exit drm_cleanup( drm_device_t *dev )
DRM_DEBUG("Extra maplist item\n");
break;
}
- DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
+ drm_core_free(map, sizeof(*map), DRM_MEM_MAPS);
}
list_del( list );
- DRM(free)(r_list, sizeof(*r_list), DRM_MEM_MAPS);
+ drm_core_free(r_list, sizeof(*r_list), DRM_MEM_MAPS);
}
- DRM(free)(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
+ drm_core_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
dev->maplist = NULL;
}
if (DRM(fb_loaded)==0)
@@ -730,8 +730,8 @@ static void __exit drm_cleanup( drm_device_t *dev )
}
#endif
if ( drm_core_check_feature(dev, DRIVER_USE_AGP) && dev->agp ) {
- DRM(agp_uninit)();
- DRM(free)( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS );
+ drm_memory_agp_uninit();
+ drm_core_free( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS );
dev->agp = NULL;
}
#endif
@@ -956,7 +956,7 @@ int DRM(release)( struct inode *inode, struct file *filp )
DRM(ctxbitmap_free)( dev, pos->handle );
list_del( &pos->head );
- DRM(free)( pos, sizeof(*pos), DRM_MEM_CTXLIST );
+ drm_core_free( pos, sizeof(*pos), DRM_MEM_CTXLIST );
--dev->ctx_count;
}
}
@@ -985,7 +985,7 @@ int DRM(release)( struct inode *inode, struct file *filp )
if (dev->fn_tbl.free_filp_private)
dev->fn_tbl.free_filp_private( dev, priv );
- DRM(free)( priv, sizeof(*priv), DRM_MEM_FILES );
+ drm_core_free( priv, sizeof(*priv), DRM_MEM_FILES );
/* ========================================================
* End inline drm_release
@@ -1129,29 +1129,28 @@ int DRM(lock)( struct inode *inode, struct file *filp,
current->state = TASK_RUNNING;
remove_wait_queue( &dev->lock.lock_queue, &entry );
- if ( !ret ) {
- sigemptyset( &dev->sigmask );
- sigaddset( &dev->sigmask, SIGSTOP );
- sigaddset( &dev->sigmask, SIGTSTP );
- sigaddset( &dev->sigmask, SIGTTIN );
- sigaddset( &dev->sigmask, SIGTTOU );
- dev->sigdata.context = lock.context;
- dev->sigdata.lock = dev->lock.hw_lock;
- block_all_signals( DRM(notifier),
- &dev->sigdata, &dev->sigmask );
-
- if (dev->fn_tbl.dma_ready && (lock.flags & _DRM_LOCK_READY))
- dev->fn_tbl.dma_ready(dev);
-
- if ( dev->fn_tbl.dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT ))
- return dev->fn_tbl.dma_quiescent(dev);
-
-
- if ( dev->fn_tbl.kernel_context_switch && dev->last_context != lock.context ) {
- dev->fn_tbl.kernel_context_switch(dev, dev->last_context,
- lock.context);
- }
- }
+ sigemptyset( &dev->sigmask );
+ sigaddset( &dev->sigmask, SIGSTOP );
+ sigaddset( &dev->sigmask, SIGTSTP );
+ sigaddset( &dev->sigmask, SIGTTIN );
+ sigaddset( &dev->sigmask, SIGTTOU );
+ dev->sigdata.context = lock.context;
+ dev->sigdata.lock = dev->lock.hw_lock;
+ block_all_signals( DRM(notifier),
+ &dev->sigdata, &dev->sigmask );
+
+ if (dev->fn_tbl.dma_ready && (lock.flags & _DRM_LOCK_READY))
+ dev->fn_tbl.dma_ready(dev);
+
+ if ( dev->fn_tbl.dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT ))
+ return dev->fn_tbl.dma_quiescent(dev);
+
+
+ if ( dev->fn_tbl.kernel_context_switch && dev->last_context != lock.context ) {
+ dev->fn_tbl.kernel_context_switch(dev, dev->last_context,
+ lock.context);
+ }
+
DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" );
diff --git a/linux-core/drm_fops.c b/linux-core/drm_fops.c
index 21935b7a..32c6177c 100644
--- a/linux-core/drm_fops.c
+++ b/linux-core/drm_fops.c
@@ -60,7 +60,7 @@ int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
- priv = DRM(alloc)(sizeof(*priv), DRM_MEM_FILES);
+ priv = drm_core_alloc(sizeof(*priv), DRM_MEM_FILES);
if(!priv) return -ENOMEM;
memset(priv, 0, sizeof(*priv));
@@ -111,7 +111,7 @@ int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
return 0;
out_free:
- DRM(free)(priv, sizeof(*priv), DRM_MEM_FILES);
+ drm_core_free(priv, sizeof(*priv), DRM_MEM_FILES);
return ret;
}
diff --git a/linux-core/drm_ioctl.c b/linux-core/drm_ioctl.c
index c3725668..4e5055ef 100644
--- a/linux-core/drm_ioctl.c
+++ b/linux-core/drm_ioctl.c
@@ -98,14 +98,14 @@ int DRM(setunique)(struct inode *inode, struct file *filp,
if (!u.unique_len || u.unique_len > 1024) return -EINVAL;
dev->unique_len = u.unique_len;
- dev->unique = DRM(alloc)(u.unique_len + 1, DRM_MEM_DRIVER);
+ dev->unique = drm_core_alloc(u.unique_len + 1, DRM_MEM_DRIVER);
if(!dev->unique) return -ENOMEM;
if (copy_from_user(dev->unique, u.unique, dev->unique_len))
return -EFAULT;
dev->unique[dev->unique_len] = '\0';
- dev->devname = DRM(alloc)(strlen(dev->name) + strlen(dev->unique) + 2,
+ dev->devname = drm_core_alloc(strlen(dev->name) + strlen(dev->unique) + 2,
DRM_MEM_DRIVER);
if (!dev->devname)
return -ENOMEM;
@@ -137,14 +137,14 @@ DRM(set_busid)(drm_device_t *dev)
return EBUSY;
dev->unique_len = 20;
- dev->unique = DRM(alloc)(dev->unique_len + 1, DRM_MEM_DRIVER);
+ dev->unique = drm_core_alloc(dev->unique_len + 1, DRM_MEM_DRIVER);
if (dev->unique == NULL)
return ENOMEM;
snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d",
dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
- dev->devname = DRM(alloc)(strlen(dev->name) + dev->unique_len + 2,
+ dev->devname = drm_core_alloc(strlen(dev->name) + dev->unique_len + 2,
DRM_MEM_DRIVER);
if (dev->devname == NULL)
return ENOMEM;
diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c
index a1622c0e..a88edf98 100644
--- a/linux-core/drm_irq.c
+++ b/linux-core/drm_irq.c
@@ -304,7 +304,7 @@ int DRM(wait_vblank)( DRM_IOCTL_ARGS )
spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
- if ( !( vbl_sig = DRM(alloc)( sizeof( drm_vbl_sig_t ), DRM_MEM_DRIVER ) ) ) {
+ if ( !( vbl_sig = drm_core_alloc( sizeof( drm_vbl_sig_t ), DRM_MEM_DRIVER ) ) ) {
return -ENOMEM;
}
@@ -360,7 +360,7 @@ void DRM(vbl_send_signals)( drm_device_t *dev )
list_del( list );
- DRM(free)( vbl_sig, sizeof(*vbl_sig), DRM_MEM_DRIVER );
+ drm_core_free( vbl_sig, sizeof(*vbl_sig), DRM_MEM_DRIVER );
dev->vbl_pending--;
}
diff --git a/linux-core/drm_scatter.c b/linux-core/drm_scatter.c
index 888e6296..02e82781 100644
--- a/linux-core/drm_scatter.c
+++ b/linux-core/drm_scatter.c
@@ -50,13 +50,13 @@ void DRM(sg_cleanup)( drm_sg_mem_t *entry )
vfree( entry->virtual );
- DRM(free)( entry->busaddr,
+ drm_core_free( entry->busaddr,
entry->pages * sizeof(*entry->busaddr),
DRM_MEM_PAGES );
- DRM(free)( entry->pagelist,
+ drm_core_free( entry->pagelist,
entry->pages * sizeof(*entry->pagelist),
DRM_MEM_PAGES );
- DRM(free)( entry,
+ drm_core_free( entry,
sizeof(*entry),
DRM_MEM_SGLISTS );
}
@@ -82,7 +82,7 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp,
if ( copy_from_user( &request, argp, sizeof(request) ) )
return -EFAULT;
- entry = DRM(alloc)( sizeof(*entry), DRM_MEM_SGLISTS );
+ entry = drm_core_alloc( sizeof(*entry), DRM_MEM_SGLISTS );
if ( !entry )
return -ENOMEM;
@@ -92,22 +92,22 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp,
DRM_DEBUG( "sg size=%ld pages=%ld\n", request.size, pages );
entry->pages = pages;
- entry->pagelist = DRM(alloc)( pages * sizeof(*entry->pagelist),
+ entry->pagelist = drm_core_alloc( pages * sizeof(*entry->pagelist),
DRM_MEM_PAGES );
if ( !entry->pagelist ) {
- DRM(free)( entry, sizeof(*entry), DRM_MEM_SGLISTS );
+ drm_core_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),
+ entry->busaddr = drm_core_alloc( pages * sizeof(*entry->busaddr),
DRM_MEM_PAGES );
if ( !entry->busaddr ) {
- DRM(free)( entry->pagelist,
+ drm_core_free( entry->pagelist,
entry->pages * sizeof(*entry->pagelist),
DRM_MEM_PAGES );
- DRM(free)( entry,
+ drm_core_free( entry,
sizeof(*entry),
DRM_MEM_SGLISTS );
return -ENOMEM;
@@ -116,13 +116,13 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp,
entry->virtual = vmalloc_32( pages << PAGE_SHIFT );
if ( !entry->virtual ) {
- DRM(free)( entry->busaddr,
+ drm_core_free( entry->busaddr,
entry->pages * sizeof(*entry->busaddr),
DRM_MEM_PAGES );
- DRM(free)( entry->pagelist,
+ drm_core_free( entry->pagelist,
entry->pages * sizeof(*entry->pagelist),
DRM_MEM_PAGES );
- DRM(free)( entry,
+ drm_core_free( entry,
sizeof(*entry),
DRM_MEM_SGLISTS );
return -ENOMEM;
diff --git a/linux-core/drm_stub.c b/linux-core/drm_stub.c
index 3d9ade35..53f75f4c 100644
--- a/linux-core/drm_stub.c
+++ b/linux-core/drm_stub.c
@@ -162,7 +162,7 @@ static int DRM(stub_getminor)(const char *name, struct file_operations *fops,
int i;
if (!DRM(stub_list)) {
- DRM(stub_list) = DRM(alloc)(sizeof(*DRM(stub_list))
+ DRM(stub_list) = drm_core_alloc(sizeof(*DRM(stub_list))
* DRM_STUB_MAXCARDS, DRM_MEM_STUB);
if(!DRM(stub_list)) return -1;
for (i = 0; i < DRM_STUB_MAXCARDS; i++) {
@@ -174,7 +174,7 @@ static int DRM(stub_getminor)(const char *name, struct file_operations *fops,
if (!DRM(stub_list)[i].fops) {
DRM(stub_list)[i].name = name;
DRM(stub_list)[i].fops = fops;
- DRM(proc_init)(dev, i, DRM(stub_info).proc_root,
+ drm_proc_init(dev, i, DRM(stub_info).proc_root,
&DRM(stub_list)[i].dev_root);
(*DRM(stub_info).info_count)++;
DRM_DEBUG("info count increased %d\n", *DRM(stub_info).info_count);
@@ -200,7 +200,7 @@ static int DRM(stub_putminor)(int minor)
if (minor < 0 || minor >= DRM_STUB_MAXCARDS) return -1;
DRM(stub_list)[minor].name = NULL;
DRM(stub_list)[minor].fops = NULL;
- DRM(proc_cleanup)(minor, DRM(stub_info).proc_root,
+ drm_proc_cleanup(minor, DRM(stub_info).proc_root,
DRM(stub_list)[minor].dev_root);
(*DRM(stub_info).info_count)--;
@@ -213,7 +213,7 @@ static int DRM(stub_putminor)(int minor)
} else {
DRM_DEBUG("unregistering inter_module \n");
inter_module_unregister("drm");
- DRM(free)(DRM(stub_list),
+ drm_core_free(DRM(stub_list),
sizeof(*DRM(stub_list)) * DRM_STUB_MAXCARDS,
DRM_MEM_STUB);
remove_proc_entry("dri", NULL);
diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c
index f13db00b..86fe9426 100644
--- a/linux-core/drm_vm.c
+++ b/linux-core/drm_vm.c
@@ -183,7 +183,7 @@ void DRM(vm_shm_close)(struct vm_area_struct *vma)
} else {
dev->vmalist = pt->next;
}
- DRM(free)(pt, sizeof(*pt), DRM_MEM_VMAS);
+ drm_core_free(pt, sizeof(*pt), DRM_MEM_VMAS);
} else {
prev = pt;
}
@@ -214,7 +214,7 @@ void DRM(vm_shm_close)(struct vm_area_struct *vma)
DRM_DEBUG("mtrr_del = %d\n", retcode);
}
#endif
- DRM(ioremapfree)(map->handle, map->size, dev);
+ drm_core_ioremapfree(map, dev);
break;
case _DRM_SHM:
vfree(map->handle);
@@ -223,7 +223,7 @@ void DRM(vm_shm_close)(struct vm_area_struct *vma)
case _DRM_SCATTER_GATHER:
break;
}
- DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
+ drm_core_free(map, sizeof(*map), DRM_MEM_MAPS);
}
}
up(&dev->struct_sem);
@@ -405,7 +405,7 @@ void DRM(vm_open)(struct vm_area_struct *vma)
vma->vm_start, vma->vm_end - vma->vm_start);
atomic_inc(&dev->vma_count);
- vma_entry = DRM(alloc)(sizeof(*vma_entry), DRM_MEM_VMAS);
+ vma_entry = drm_core_alloc(sizeof(*vma_entry), DRM_MEM_VMAS);
if (vma_entry) {
down(&dev->struct_sem);
vma_entry->vma = vma;
@@ -442,7 +442,7 @@ void DRM(vm_close)(struct vm_area_struct *vma)
} else {
dev->vmalist = pt->next;
}
- DRM(free)(pt, sizeof(*pt), DRM_MEM_VMAS);
+ drm_core_free(pt, sizeof(*pt), DRM_MEM_VMAS);
break;
}
}
diff --git a/linux-core/radeon_drv.c b/linux-core/radeon_drv.c
index 74e32df0..582d172c 100644
--- a/linux-core/radeon_drv.c
+++ b/linux-core/radeon_drv.c
@@ -31,18 +31,16 @@
#include <linux/config.h>
+#include "drm_headers.h"
+
#include "radeon.h"
#include "drmP.h"
#include "drm.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
-#include "ati_pcigart.h"
-#include "drm_agpsupport.h"
#include "drm_auth.h"
-#include "drm_bufs.h"
#include "drm_context.h"
-#include "drm_dma.h"
#include "drm_drawable.h"
#include "drm_drv.h"
#include "drm_fops.h"
@@ -50,8 +48,6 @@
#include "drm_ioctl.h"
#include "drm_irq.h"
#include "drm_lock.h"
-#include "drm_memory.h"
-#include "drm_proc.h"
#include "drm_vm.h"
#include "drm_stub.h"
#include "drm_scatter.h"
diff --git a/linux/Makefile b/linux/Makefile
index 9cfe7d5c..1bff058f 100644
--- a/linux/Makefile
+++ b/linux/Makefile
@@ -50,12 +50,12 @@ endif
MACHINE := $(shell uname -m)
# Modules for all architectures
-MODULE_LIST := tdfx.o r128.o radeon.o mga.o sis.o savage.o via.o mach64.o
+MODULE_LIST := #tdfx.o r128.o radeon.o mga.o sis.o savage.o via.o mach64.o
# Modules only for ix86 architectures
ifneq (,$(findstring 86,$(MACHINE)))
ARCHX86 := 1
-MODULE_LIST += i830.o i810.o i915.o
+MODULE_LIST += #i830.o i810.o i915.o
endif
ifneq (,$(findstring sparc64,$(MACHINE)))
diff --git a/linux/Makefile.kernel b/linux/Makefile.kernel
index 92e3f73e..8e68d40a 100644
--- a/linux/Makefile.kernel
+++ b/linux/Makefile.kernel
@@ -7,6 +7,7 @@
# $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/Makefile.kernel,v 1.18 2003/08/16 17:59:17 dawes Exp $
#
+drmcore-objs :=
tdfx-objs := tdfx_drv.o
r128-objs := r128_drv.o r128_cce.o r128_state.o r128_irq.o
mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o
@@ -41,9 +42,11 @@ obj- :=
export-objs := via_mm.o
endif
+drmcore-y := drm_bufs.o drm_memory.o drm_memory_debug.o drm_agpsupport.o drm_dma.o ati_pcigart.o drm_proc.o drmcore_exports.o
+obj-m += drmcore.o radeon.o
obj-$(CONFIG_DRM_TDFX) += tdfx.o
-obj-$(CONFIG_DRM_R128) += r128.o
-obj-$(CONFIG_DRM_RADEON)+= radeon.o
+obj-$(CONFIG_DRM_R128) += r128.o
+obj-$(CONFIG_DRM_RADEON)+= radeon.o drmcore.o
obj-$(CONFIG_DRM_MGA) += mga.o
obj-$(CONFIG_DRM_I810) += i810.o
obj-$(CONFIG_DRM_I830) += i830.o
diff --git a/linux/ati_pcigart.c b/linux/ati_pcigart.c
new file mode 100644
index 00000000..54e3e242
--- /dev/null
+++ b/linux/ati_pcigart.c
@@ -0,0 +1,206 @@
+/**
+ * \file ati_pcigart.h
+ * ATI PCI GART support
+ *
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Wed Dec 13 21:52:19 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.
+ */
+
+#include "drm_headers.h"
+
+#if PAGE_SIZE == 65536
+# define ATI_PCIGART_TABLE_ORDER 0
+# define ATI_PCIGART_TABLE_PAGES (1 << 0)
+#elif PAGE_SIZE == 16384
+# define ATI_PCIGART_TABLE_ORDER 1
+# define ATI_PCIGART_TABLE_PAGES (1 << 1)
+#elif PAGE_SIZE == 8192
+# define ATI_PCIGART_TABLE_ORDER 2
+# define ATI_PCIGART_TABLE_PAGES (1 << 2)
+#elif PAGE_SIZE == 4096
+# define ATI_PCIGART_TABLE_ORDER 3
+# define ATI_PCIGART_TABLE_PAGES (1 << 3)
+#else
+# error - PAGE_SIZE not 64K, 16K, 8K or 4K
+#endif
+
+# define ATI_MAX_PCIGART_PAGES 8192 /**< 32 MB aperture, 4K pages */
+# define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */
+
+static unsigned long drm_ati_alloc_pcigart_table( void )
+{
+ unsigned long address;
+ struct page *page;
+ int i;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ address = __get_free_pages( GFP_KERNEL, ATI_PCIGART_TABLE_ORDER );
+ if ( address == 0UL ) {
+ return 0;
+ }
+
+ page = virt_to_page( address );
+
+ for ( i = 0 ; i < ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
+ get_page(page);
+ SetPageReserved( page );
+ }
+
+ DRM_DEBUG( "%s: returning 0x%08lx\n", __FUNCTION__, address );
+ return address;
+}
+
+static void drm_ati_free_pcigart_table( unsigned long address )
+{
+ struct page *page;
+ int i;
+ DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+ page = virt_to_page( address );
+
+ for ( i = 0 ; i < ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
+ __put_page(page);
+ ClearPageReserved( page );
+ }
+
+ free_pages( address, ATI_PCIGART_TABLE_ORDER );
+}
+
+int drm_ati_pcigart_init( drm_device_t *dev,
+ unsigned long *addr,
+ dma_addr_t *bus_addr)
+{
+ drm_sg_mem_t *entry = dev->sg;
+ unsigned long address = 0;
+ unsigned long pages;
+ u32 *pci_gart, page_base, bus_address = 0;
+ int i, j, ret = 0;
+
+ if ( !entry ) {
+ DRM_ERROR( "no scatter/gather memory!\n" );
+ goto done;
+ }
+
+ address = drm_ati_alloc_pcigart_table();
+ if ( !address ) {
+ DRM_ERROR( "cannot allocate PCI GART page!\n" );
+ goto done;
+ }
+
+ if ( !dev->pdev ) {
+ DRM_ERROR( "PCI device unknown!\n" );
+ goto done;
+ }
+
+ bus_address = pci_map_single(dev->pdev, (void *)address,
+ ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
+ PCI_DMA_TODEVICE);
+ if (bus_address == 0) {
+ DRM_ERROR( "unable to map PCIGART pages!\n" );
+ drm_ati_free_pcigart_table( address );
+ address = 0;
+ goto done;
+ }
+
+ pci_gart = (u32 *)address;
+
+ pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES )
+ ? entry->pages : ATI_MAX_PCIGART_PAGES;
+
+ memset( pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32) );
+
+ for ( i = 0 ; i < pages ; i++ ) {
+ /* we need to support large memory configurations */
+ entry->busaddr[i] = pci_map_single(dev->pdev,
+ page_address( entry->pagelist[i] ),
+ PAGE_SIZE,
+ PCI_DMA_TODEVICE);
+ if (entry->busaddr[i] == 0) {
+ DRM_ERROR( "unable to map PCIGART pages!\n" );
+ drm_ati_pcigart_cleanup( dev, address, bus_address );
+ address = 0;
+ bus_address = 0;
+ goto done;
+ }
+ page_base = (u32) entry->busaddr[i];
+
+ for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
+ *pci_gart++ = cpu_to_le32( page_base );
+ page_base += ATI_PCIGART_PAGE_SIZE;
+ }
+ }
+
+ ret = 1;
+
+#if defined(__i386__) || defined(__AMD64__) || defined(__x86_64__)
+ asm volatile ( "wbinvd" ::: "memory" );
+#else
+ mb();
+#endif
+
+done:
+ *addr = address;
+ *bus_addr = bus_address;
+ return ret;
+}
+
+int drm_ati_pcigart_cleanup( drm_device_t *dev,
+ unsigned long addr,
+ dma_addr_t bus_addr)
+{
+ drm_sg_mem_t *entry = dev->sg;
+ unsigned long pages;
+ int i;
+
+ /* we need to support large memory configurations */
+ if ( !entry ) {
+ DRM_ERROR( "no scatter/gather memory!\n" );
+ return 0;
+ }
+
+ if ( bus_addr ) {
+ pci_unmap_single(dev->pdev, bus_addr,
+ ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
+ PCI_DMA_TODEVICE);
+
+ pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES )
+ ? entry->pages : ATI_MAX_PCIGART_PAGES;
+
+ for ( i = 0 ; i < pages ; i++ ) {
+ if ( !entry->busaddr[i] ) break;
+ pci_unmap_single(dev->pdev, entry->busaddr[i],
+ PAGE_SIZE, PCI_DMA_TODEVICE);
+ }
+ }
+
+ if ( addr ) {
+ drm_ati_free_pcigart_table( addr );
+ }
+
+ return 1;
+}
diff --git a/linux/drmP.h b/linux/drmP.h
index 495277f6..b26f6189 100644
--- a/linux/drmP.h
+++ b/linux/drmP.h
@@ -36,179 +36,27 @@
#ifdef __KERNEL__
-#ifdef __alpha__
-/* add include of current.h so that "current" is defined
- * before static inline funcs in wait.h. Doing this so we
- * can build the DRM (part of PI DRI). 4/21/2000 S + B */
-#include <asm/current.h>
-#endif /* __alpha__ */
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/miscdevice.h>
-#include <linux/fs.h>
-#include <linux/proc_fs.h>
-#include <linux/init.h>
-#include <linux/file.h>
-#include <linux/pci.h>
-#include <linux/version.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h> /* For (un)lock_kernel */
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-#if defined(__alpha__) || defined(__powerpc__)
-#include <asm/pgtable.h> /* For pte_wrprotect */
-#endif
-#include <asm/io.h>
-#include <asm/mman.h>
-#include <asm/uaccess.h>
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-#include <linux/types.h>
-#include <linux/agp_backend.h>
-#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,41)
-#define HAS_WORKQUEUE 0
-#else
-#define HAS_WORKQUEUE 1
-#endif
-#if !HAS_WORKQUEUE
-#include <linux/tqueue.h>
-#else
-#include <linux/workqueue.h>
-#endif
-#include <linux/poll.h>
-#include <asm/pgalloc.h>
-#include "drm.h"
-
-#include "drm_os_linux.h"
/* If you want the memory alloc debug functionality, change define below */
/* #define DEBUG_MEMORY */
/***********************************************************************/
-/** \name DRM template customization defaults */
-/*@{*/
-
-/* driver capabilities and requirements mask */
-#define DRIVER_USE_AGP 0x1
-#define DRIVER_REQUIRE_AGP 0x2
-#define DRIVER_USE_MTRR 0x4
-#define DRIVER_HAVE_DMA 0x10
-#define DRIVER_HAVE_IRQ 0x20
-#define DRIVER_SG 0x40
-#define DRIVER_PCI_DMA 0x80
-#define DRIVER_IRQ_SHARED 0x100
-#define DRIVER_IRQ_VBL 0x200
-#define DRIVER_DMA_QUEUE 0x800
-
-#define __OS_HAS_AGP (defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE))
-#define __OS_HAS_MTRR (defined(CONFIG_MTRR))
-/*@}*/
-
-
-/***********************************************************************/
/** \name Begin the DRM... */
/*@{*/
-#define DRM_DEBUG_CODE 2 /**< Include debugging code if > 1, then
- also include looping detection. */
-
-#define DRM_HASH_SIZE 16 /**< Size of key hash table. Must be power of 2. */
-#define DRM_KERNEL_CONTEXT 0 /**< Change drm_resctx if changed */
-#define DRM_RESERVED_CONTEXTS 1 /**< Change drm_resctx if changed */
-#define DRM_LOOPING_LIMIT 5000000
-#define DRM_BSZ 1024 /**< Buffer size for /dev/drm? output */
-#define DRM_TIME_SLICE (HZ/20) /**< Time slice for GLXContexts */
-#define DRM_LOCK_SLICE 1 /**< Time slice for lock, in jiffies */
-
-#define DRM_FLAG_DEBUG 0x01
-
-#define DRM_MEM_DMA 0
-#define DRM_MEM_SAREA 1
-#define DRM_MEM_DRIVER 2
-#define DRM_MEM_MAGIC 3
-#define DRM_MEM_IOCTLS 4
-#define DRM_MEM_MAPS 5
-#define DRM_MEM_VMAS 6
-#define DRM_MEM_BUFS 7
-#define DRM_MEM_SEGS 8
-#define DRM_MEM_PAGES 9
-#define DRM_MEM_FILES 10
-#define DRM_MEM_QUEUES 11
-#define DRM_MEM_CMDS 12
-#define DRM_MEM_MAPPINGS 13
-#define DRM_MEM_BUFLISTS 14
-#define DRM_MEM_AGPLISTS 15
-#define DRM_MEM_TOTALAGP 16
-#define DRM_MEM_BOUNDAGP 17
-#define DRM_MEM_CTXBITMAP 18
-#define DRM_MEM_STUB 19
-#define DRM_MEM_SGLISTS 20
-#define DRM_MEM_CTXLIST 21
#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
/*@}*/
-#include "drm_compat.h"
+#include "drm_core.h"
/***********************************************************************/
/** \name Macros to make printk easier */
/*@{*/
-/**
- * Error output.
- *
- * \param fmt printf() like format string.
- * \param arg arguments
- */
-#define DRM_ERROR(fmt, arg...) \
- printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* " fmt , __FUNCTION__ , ##arg)
-
-/**
- * Memory error output.
- *
- * \param area memory area where the error occurred.
- * \param fmt printf() like format string.
- * \param arg arguments
- */
-#define DRM_MEM_ERROR(area, fmt, arg...) \
- printk(KERN_ERR "[" DRM_NAME ":%s:%s] *ERROR* " fmt , __FUNCTION__, \
- DRM(mem_stats)[area].name , ##arg)
-#define DRM_INFO(fmt, arg...) printk(KERN_INFO "[" DRM_NAME "] " fmt , ##arg)
-
-/**
- * Debug output.
- *
- * \param fmt printf() like format string.
- * \param arg arguments
- */
-#if DRM_DEBUG_CODE
-#define DRM_DEBUG(fmt, arg...) \
- do { \
- if ( DRM(flags) & DRM_FLAG_DEBUG ) \
- printk(KERN_DEBUG \
- "[" DRM_NAME ":%s] " fmt , \
- __FUNCTION__ , ##arg); \
- } while (0)
-#else
-#define DRM_DEBUG(fmt, arg...) do { } while (0)
-#endif
-
-#define DRM_PROC_LIMIT (PAGE_SIZE-80)
-
-#define DRM_PROC_PRINT(fmt, arg...) \
- len += sprintf(&buf[len], fmt , ##arg); \
- if (len > DRM_PROC_LIMIT) { *eof = 1; return len - offset; }
-
-#define DRM_PROC_PRINT_RET(ret, fmt, arg...) \
- len += sprintf(&buf[len], fmt , ##arg); \
- if (len > DRM_PROC_LIMIT) { ret; *eof = 1; return len - offset; }
/*@}*/
@@ -221,9 +69,6 @@
#define DRM_MIN(a,b) ((a)<(b)?(a):(b))
#define DRM_MAX(a,b) ((a)>(b)?(a):(b))
-#define DRM_LEFTCOUNT(x) (((x)->rp + (x)->count - (x)->wp) % ((x)->count + 1))
-#define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x))
-#define DRM_WAITCOUNT(dev,idx) DRM_BUFCOUNT(&dev->queuelist[idx]->waitlist)
#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
/**
@@ -253,440 +98,6 @@ do { \
} \
} while (0)
-/**
- * Ioctl function type.
- *
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param arg argument.
- */
-typedef int drm_ioctl_t( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-
-typedef struct drm_ioctl_desc {
- drm_ioctl_t *func;
- int auth_needed;
- int root_only;
-} drm_ioctl_desc_t;
-
-typedef struct drm_devstate {
- pid_t owner; /**< X server pid holding x_lock */
-} drm_devstate_t;
-
-typedef struct drm_magic_entry {
- drm_magic_t magic;
- struct drm_file *priv;
- struct drm_magic_entry *next;
-} drm_magic_entry_t;
-
-typedef struct drm_magic_head {
- struct drm_magic_entry *head;
- struct drm_magic_entry *tail;
-} drm_magic_head_t;
-
-typedef struct drm_vma_entry {
- struct vm_area_struct *vma;
- struct drm_vma_entry *next;
- pid_t pid;
-} drm_vma_entry_t;
-
-/**
- * DMA buffer.
- */
-typedef struct drm_buf {
- int idx; /**< Index into master buflist */
- int total; /**< Buffer size */
- int order; /**< log-base-2(total) */
- int used; /**< Amount of buffer in use (for DMA) */
- unsigned long offset; /**< Byte offset (used internally) */
- void *address; /**< Address of buffer */
- unsigned long bus_address; /**< Bus address of buffer */
- struct drm_buf *next; /**< Kernel-only: used for free list */
- __volatile__ int waiting; /**< On kernel DMA queue */
- __volatile__ int pending; /**< On hardware DMA queue */
- wait_queue_head_t dma_wait; /**< Processes waiting */
- struct file *filp; /**< Pointer to holding file descr */
- int context; /**< Kernel queue for this buffer */
- int while_locked;/**< Dispatch this buffer while locked */
- enum {
- DRM_LIST_NONE = 0,
- DRM_LIST_FREE = 1,
- DRM_LIST_WAIT = 2,
- DRM_LIST_PEND = 3,
- DRM_LIST_PRIO = 4,
- DRM_LIST_RECLAIM = 5
- } list; /**< Which list we're on */
-
- int dev_priv_size; /**< Size of buffer private storage */
- void *dev_private; /**< Per-buffer private storage */
-} drm_buf_t;
-
-
-/** bufs is one longer than it has to be */
-typedef struct drm_waitlist {
- int count; /**< Number of possible buffers */
- drm_buf_t **bufs; /**< List of pointers to buffers */
- drm_buf_t **rp; /**< Read pointer */
- drm_buf_t **wp; /**< Write pointer */
- drm_buf_t **end; /**< End pointer */
- spinlock_t read_lock;
- spinlock_t write_lock;
-} drm_waitlist_t;
-
-typedef struct drm_freelist {
- int initialized; /**< Freelist in use */
- atomic_t count; /**< Number of free buffers */
- drm_buf_t *next; /**< End pointer */
-
- wait_queue_head_t waiting; /**< Processes waiting on free bufs */
- int low_mark; /**< Low water mark */
- int high_mark; /**< High water mark */
- atomic_t wfh; /**< If waiting for high mark */
- spinlock_t lock;
-} drm_freelist_t;
-
-/**
- * Buffer entry. There is one of this for each buffer size order.
- */
-typedef struct drm_buf_entry {
- int buf_size; /**< size */
- int buf_count; /**< number of buffers */
- drm_buf_t *buflist; /**< buffer list */
- int seg_count;
- int page_order;
- unsigned long *seglist;
-
- drm_freelist_t freelist;
-} drm_buf_entry_t;
-
-/** File private data */
-typedef struct drm_file {
- int authenticated;
- int minor;
- pid_t pid;
- uid_t uid;
- drm_magic_t magic;
- unsigned long ioctl_count;
- struct drm_file *next;
- struct drm_file *prev;
- struct drm_device *dev;
- int remove_auth_on_close;
- unsigned long lock_count;
- void *driver_priv;
-} drm_file_t;
-
-/** Wait queue */
-typedef struct drm_queue {
- atomic_t use_count; /**< Outstanding uses (+1) */
- atomic_t finalization; /**< Finalization in progress */
- atomic_t block_count; /**< Count of processes waiting */
- atomic_t block_read; /**< Queue blocked for reads */
- wait_queue_head_t read_queue; /**< Processes waiting on block_read */
- atomic_t block_write; /**< Queue blocked for writes */
- wait_queue_head_t write_queue; /**< Processes waiting on block_write */
-#if 1
- atomic_t total_queued; /**< Total queued statistic */
- atomic_t total_flushed;/**< Total flushes statistic */
- atomic_t total_locks; /**< Total locks statistics */
-#endif
- drm_ctx_flags_t flags; /**< Context preserving and 2D-only */
- drm_waitlist_t waitlist; /**< Pending buffers */
- wait_queue_head_t flush_queue; /**< Processes waiting until flush */
-} drm_queue_t;
-
-/**
- * Lock data.
- */
-typedef struct drm_lock_data {
- drm_hw_lock_t *hw_lock; /**< Hardware lock */
- struct file *filp; /**< File descr of lock holder (0=kernel) */
- wait_queue_head_t lock_queue; /**< Queue of blocked processes */
- unsigned long lock_time; /**< Time of last lock in jiffies */
-} drm_lock_data_t;
-
-/**
- * DMA data.
- */
-typedef struct drm_device_dma {
-
- drm_buf_entry_t bufs[DRM_MAX_ORDER+1]; /**< buffers, grouped by their size order */
- int buf_count; /**< total number of buffers */
- drm_buf_t **buflist; /**< Vector of pointers into drm_device_dma::bufs */
- int seg_count;
- int page_count; /**< number of pages */
- unsigned long *pagelist; /**< page list */
- unsigned long byte_count;
- enum {
- _DRM_DMA_USE_AGP = 0x01,
- _DRM_DMA_USE_SG = 0x02
- } flags;
-
- /** \name DMA support */
- /*@{*/
- drm_buf_t *this_buffer; /**< Buffer being sent */
- drm_buf_t *next_buffer; /**< Selected buffer to send */
- drm_queue_t *next_queue; /**< Queue from which buffer selected*/
- wait_queue_head_t waiting; /**< Processes waiting on free bufs */
- /*@}*/
-} drm_device_dma_t;
-
-#if __OS_HAS_AGP
-/**
- * AGP memory entry. Stored as a doubly linked list.
- */
-typedef struct drm_agp_mem {
- unsigned long handle; /**< handle */
- DRM_AGP_MEM *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 {
- DRM_AGP_KERN 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;
-} drm_sigdata_t;
-
-/**
- * Mappings list
- */
-typedef struct drm_map_list {
- struct list_head head; /**< list head */
- drm_map_t *map; /**< mapping */
-} drm_map_list_t;
-
-typedef drm_map_t drm_local_map_t;
-
-/**
- * Context handle list
- */
-typedef struct drm_ctx_list {
- struct list_head head; /**< list head */
- drm_context_t handle; /**< context handle */
- drm_file_t *tag; /**< associated fd private data */
-} drm_ctx_list_t;
-
-
-typedef struct drm_vbl_sig {
- struct list_head head;
- unsigned int sequence;
- struct siginfo info;
- struct task_struct *task;
-} drm_vbl_sig_t;
-
-
-/**
- * DRM device functions structure
- */
-struct drm_device;
-
-struct drm_driver_fn {
- int (*preinit)(struct drm_device *, unsigned long flags);
- int (*postinit)(struct drm_device *, unsigned long flags);
- void (*prerelease)(struct drm_device *, struct file *filp);
- void (*pretakedown)(struct drm_device *);
- int (*postcleanup)(struct drm_device *);
- int (*presetup)(struct drm_device *);
- int (*postsetup)(struct drm_device *);
-
- /* these are opposites at the moment */
- int (*open_helper)(struct drm_device *, drm_file_t *);
- void (*free_filp_private)(struct drm_device *, drm_file_t *);
-
- void (*release)(struct drm_device *, struct file *filp);
- void (*dma_ready)(struct drm_device *);
- int (*dma_quiescent)(struct drm_device *);
- int (*context_ctor)(struct drm_device *dev, int context);
- int (*context_dtor)(struct drm_device *dev, int context);
- int (*kernel_context_switch)(struct drm_device *dev, int old, int new);
- int (*kernel_context_switch_unlock)(struct drm_device *dev);
- int (*vblank_wait)(struct drm_device *dev, unsigned int *sequence);
-/* these have to be filled in */
- irqreturn_t (*irq_handler)( DRM_IRQ_ARGS );
- void (*irq_preinstall)(struct drm_device *dev);
- void (*irq_postinstall)(struct drm_device *dev);
- void (*irq_uninstall)(struct drm_device *dev);
- void (*reclaim_buffers)(struct file *filp);
- unsigned long (*get_map_ofs)(drm_map_t *map);
- unsigned long (*get_reg_ofs)(struct drm_device *dev);
- void (*set_version)(struct drm_device *dev, drm_set_version_t *sv);
-};
-
-/**
- * DRM device structure.
- */
-typedef struct drm_device {
- const char *name; /**< Simple driver name */
- char *unique; /**< Unique identifier: e.g., busid */
- int unique_len; /**< Length of unique field */
- dev_t device; /**< Device number for mknod */
- char *devname; /**< For /proc/interrupts */
- int minor; /**< Minor device number */
- int if_version; /**< Highest interface version set */
-
- int blocked; /**< Blocked due to VC switch? */
- struct proc_dir_entry *root; /**< Root for this device's entries */
-
- /** \name Locks */
- /*@{*/
- spinlock_t count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */
- struct semaphore struct_sem; /**< For others */
- /*@}*/
-
- /** \name Usage Counters */
- /*@{*/
- int open_count; /**< Outstanding files open */
- atomic_t ioctl_count; /**< Outstanding IOCTLs pending */
- atomic_t vma_count; /**< Outstanding vma areas open */
- int buf_use; /**< Buffers in use -- cannot alloc */
- atomic_t buf_alloc; /**< Buffer allocation in progress */
- /*@}*/
-
- /** \name Performance counters */
- /*@{*/
- unsigned long counters;
- drm_stat_type_t types[15];
- atomic_t counts[15];
- /*@}*/
-
- /** \name Authentication */
- /*@{*/
- drm_file_t *file_first; /**< file list head */
- drm_file_t *file_last; /**< file list tail */
- drm_magic_head_t magiclist[DRM_HASH_SIZE]; /**< magic hash table */
- /*@}*/
-
- /** \name Memory management */
- /*@{*/
- drm_map_list_t *maplist; /**< Linked list of regions */
- int map_count; /**< Number of mappable regions */
-
- /** \name Context handle management */
- /*@{*/
- drm_ctx_list_t *ctxlist; /**< Linked list of context handles */
- int ctx_count; /**< Number of context handles */
- struct semaphore ctxlist_sem; /**< For ctxlist */
-
- drm_map_t **context_sareas; /**< per-context SAREA's */
- int max_context;
-
- drm_vma_entry_t *vmalist; /**< List of vmas (for debugging) */
- drm_lock_data_t lock; /**< Information on hardware lock */
- /*@}*/
-
- /** \name DMA queues (contexts) */
- /*@{*/
- int queue_count; /**< Number of active DMA queues */
- int queue_reserved; /**< Number of reserved DMA queues */
- int queue_slots; /**< Actual length of queuelist */
- drm_queue_t **queuelist; /**< Vector of pointers to DMA queues */
- drm_device_dma_t *dma; /**< Optional pointer for DMA support */
- /*@}*/
-
- /** \name Context support */
- /*@{*/
- int irq; /**< Interrupt used by board */
- int irq_enabled; /**< True if irq handler is enabled */
- __volatile__ long context_flag; /**< Context swapping flag */
- __volatile__ long interrupt_flag; /**< Interruption handler flag */
- __volatile__ long dma_flag; /**< DMA dispatch flag */
- struct timer_list timer; /**< Timer for delaying ctx switch */
- wait_queue_head_t context_wait; /**< Processes waiting on ctx switch */
- int last_checked; /**< Last context checked for DMA */
- int last_context; /**< Last current context */
- unsigned long last_switch; /**< jiffies at last context switch */
- /*@}*/
-
-#if !HAS_WORKQUEUE
- struct tq_struct tq;
-#else
- struct work_struct work;
-#endif
- /** \name VBLANK IRQ support */
- /*@{*/
-
- wait_queue_head_t vbl_queue; /**< VBLANK wait queue */
- atomic_t vbl_received;
- spinlock_t vbl_lock;
- drm_vbl_sig_t vbl_sigs; /**< signal list to send on VBLANK */
- unsigned int vbl_pending;
-
- /*@}*/
- cycles_t ctx_start;
- cycles_t lck_start;
-
- char buf[DRM_BSZ]; /**< Output buffer */
- char *buf_rp; /**< Read pointer */
- char *buf_wp; /**< Write pointer */
- char *buf_end; /**< End pointer */
- struct fasync_struct *buf_async;/**< Processes waiting for SIGIO */
- wait_queue_head_t buf_readers; /**< Processes waiting to read */
- wait_queue_head_t buf_writers; /**< Processes waiting to ctx switch */
-
-#if __OS_HAS_AGP
- drm_agp_head_t *agp; /**< AGP data */
-#endif
-
- struct pci_dev *pdev; /**< PCI device structure */
- int pci_domain; /**< PCI bus domain number */
- int pci_bus; /**< PCI bus number */
- int pci_slot; /**< PCI slot number */
- int pci_func; /**< PCI function number */
-#ifdef __alpha__
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3)
- struct pci_controler *hose;
-#else
- struct pci_controller *hose;
-#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;
-
- int need_reset; /**< secondary device needing reset */
- struct drm_driver_fn fn_tbl;
- drm_local_map_t *agp_buffer_map;
- int dev_priv_size;
- u32 driver_features;
-} drm_device_t;
-
-static __inline__ int drm_core_check_feature(struct drm_device *dev, int feature)
-{
- return ((dev->driver_features & feature) ? 1 : 0);
-}
extern void DRM(driver_register_fns)(struct drm_device *dev);
@@ -729,27 +140,6 @@ extern int DRM(mmap)(struct file *filp, struct vm_area_struct *vma);
extern unsigned int DRM(poll)(struct file *filp, struct poll_table_struct *wait);
extern ssize_t DRM(read)(struct file *filp, char __user *buf, size_t count, loff_t *off);
- /* Memory management support (drm_memory.h) */
-extern void DRM(mem_init)(void);
-extern int DRM(mem_info)(char *buf, char **start, off_t offset,
- int request, int *eof, void *data);
-extern void *DRM(calloc)(size_t nmemb, size_t size, int area);
-extern void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size,
- int area);
-extern unsigned long DRM(alloc_pages)(int order, int area);
-extern void DRM(free_pages)(unsigned long address, int order,
- int area);
-extern void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev);
-extern void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size,
- drm_device_t *dev);
-extern void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev);
-
-#if __OS_HAS_AGP
-extern DRM_AGP_MEM *DRM(alloc_agp)(int pages, u32 type);
-extern int DRM(free_agp)(DRM_AGP_MEM *handle, int pages);
-extern int DRM(bind_agp)(DRM_AGP_MEM *handle, unsigned int start);
-extern int DRM(unbind_agp)(DRM_AGP_MEM *handle);
-#endif
/* Misc. IOCTL support (drm_ioctl.h) */
extern int DRM(irq_by_busid)(struct inode *inode, struct file *filp,
@@ -825,31 +215,6 @@ extern int DRM(lock_free)(drm_device_t *dev,
unsigned int context);
extern int DRM(notifier)(void *priv);
- /* Buffer management support (drm_bufs.h) */
-extern int DRM(order)( unsigned long size );
-extern int DRM(addmap)( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int DRM(rmmap)( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int DRM(initmap)( drm_device_t *dev, unsigned int offset,
- unsigned int size, int type, int flags );
-extern int DRM(addbufs)( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int DRM(infobufs)( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int DRM(markbufs)( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int DRM(freebufs)( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-extern int DRM(mapbufs)( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-
- /* DMA support (drm_dma.h) */
-extern int DRM(dma_setup)(drm_device_t *dev);
-extern void DRM(dma_takedown)(drm_device_t *dev);
-extern void DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf);
-extern void DRM(reclaim_buffers)( struct file *filp );
-
/* IRQ support (drm_irq.h) */
extern int DRM(control)( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg );
@@ -866,32 +231,7 @@ extern int DRM(vblank_wait)(drm_device_t *dev, unsigned int *vbl_seq);
extern void DRM(vbl_send_signals)( drm_device_t *dev );
-#if __OS_HAS_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 DRM_AGP_MEM *DRM(agp_allocate_memory)(size_t pages, u32 type);
-extern int DRM(agp_free_memory)(DRM_AGP_MEM *handle);
-extern int DRM(agp_bind_memory)(DRM_AGP_MEM *handle, off_t start);
-extern int DRM(agp_unbind_memory)(DRM_AGP_MEM *handle);
-#endif
+
/* Stub support (drm_stub.h) */
int DRM(stub_register)(const char *name,
@@ -900,11 +240,11 @@ int DRM(stub_register)(const char *name,
int DRM(stub_unregister)(int minor);
/* Proc support (drm_proc.h) */
-extern int DRM(proc_init)(drm_device_t *dev,
+extern int drm_proc_init(drm_device_t *dev,
int minor,
struct proc_dir_entry *root,
struct proc_dir_entry **dev_root);
-extern int DRM(proc_cleanup)(int minor,
+extern int drm_proc_cleanup(int minor,
struct proc_dir_entry *root,
struct proc_dir_entry *dev_root);
@@ -915,13 +255,7 @@ extern int DRM(sg_alloc)(struct inode *inode, struct file *filp,
extern int DRM(sg_free)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
- /* ATI PCIGART support (ati_pcigart.h) */
-extern int DRM(ati_pcigart_init)(drm_device_t *dev,
- unsigned long *addr,
- dma_addr_t *bus_addr);
-extern int DRM(ati_pcigart_cleanup)(drm_device_t *dev,
- unsigned long addr,
- dma_addr_t bus_addr);
+
extern void *DRM(pci_alloc)(drm_device_t *dev, size_t size,
size_t align, dma_addr_t maxaddr,
@@ -930,56 +264,9 @@ extern void DRM(pci_free)(drm_device_t *dev, size_t size,
void *vaddr, dma_addr_t busaddr);
-/* Inline replacements for DRM_IOREMAP macros */
-static __inline__ void drm_core_ioremap(struct drm_map *map, struct drm_device *dev)
-{
- map->handle = DRM(ioremap)( map->offset, map->size, dev );
-}
-
-static __inline__ void drm_core_ioremap_nocache(struct drm_map *map, struct drm_device *dev)
-{
- map->handle = DRM(ioremap_nocache)(map->offset, map->size, dev);
-}
-
-static __inline__ void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev)
-{
- if ( map->handle && map->size )
- DRM(ioremapfree)( map->handle, map->size, dev );
-}
-
-static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, unsigned long offset)
-{
- struct list_head *_list;
- list_for_each( _list, &dev->maplist->head ) {
- drm_map_list_t *_entry = list_entry( _list, drm_map_list_t, head );
- if ( _entry->map &&
- _entry->map->offset == offset ) {
- return _entry->map;
- }
- }
- return NULL;
-}
-
-static __inline__ void drm_core_dropmap(struct drm_map *map)
-{
-}
-
-#ifndef DEBUG_MEMORY
-/** Wrapper around kmalloc() */
-static __inline__ void *DRM(alloc)(size_t size, int area)
-{
- return kmalloc(size, GFP_KERNEL);
-}
-
-/** Wrapper around kfree() */
-static __inline__ void DRM(free)(void *pt, size_t size, int area)
-{
- kfree(pt);
-}
-#else
-extern void *DRM(alloc)(size_t size, int area);
-extern void DRM(free)(void *pt, size_t size, int area);
-#endif
+
+
+
/*@}*/
diff --git a/linux/drm_agpsupport.c b/linux/drm_agpsupport.c
new file mode 100644
index 00000000..2e2e4ebe
--- /dev/null
+++ b/linux/drm_agpsupport.c
@@ -0,0 +1,473 @@
+/**
+ * \file drm_agpsupport.h
+ * DRM support for AGP/GART backend
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drm_headers.h"
+
+#define DRM(x) drm_memory_##x
+
+#if __OS_HAS_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;
+ DRM_AGP_KERN *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 __user *)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)
+ return -ENODEV;
+ if (dev->agp->acquired)
+ return -EBUSY;
+ if (!drm_agp->acquire)
+ return -EINVAL;
+#ifndef VMAP_4_ARGS
+ if ( dev->agp->cant_use_aperture )
+ return -EINVAL;
+#endif
+ 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 __user *)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;
+ DRM_AGP_MEM *memory;
+ unsigned long pages;
+ u32 type;
+ drm_agp_buffer_t __user *argp = (void __user *)arg;
+
+ if (!dev->agp || !dev->agp->acquired)
+ return -EINVAL;
+ if (copy_from_user(&request, argp, sizeof(request)))
+ return -EFAULT;
+ if (!(entry = drm_core_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_core_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
+ return -ENOMEM;
+ }
+
+ entry->handle = (unsigned long)memory->key + 1;
+ 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(argp, &request, sizeof(request))) {
+ dev->agp->memory = entry->next;
+ dev->agp->memory->prev = NULL;
+ DRM(free_agp)(memory, pages);
+ drm_core_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 __user *)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 __user *)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 __user *)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_core_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_core_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_core_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
+ }
+ 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() */
+DRM_AGP_MEM *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)(DRM_AGP_MEM *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)(DRM_AGP_MEM *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)(DRM_AGP_MEM *handle)
+{
+ if (!handle || !drm_agp->unbind_memory)
+ return -EINVAL;
+ return drm_agp->unbind_memory(handle);
+}
+
+#endif /* __OS_HAS_AGP */
diff --git a/linux/drm_auth.h b/linux/drm_auth.h
index fe099871..2931ac22 100644
--- a/linux/drm_auth.h
+++ b/linux/drm_auth.h
@@ -95,7 +95,7 @@ int DRM(add_magic)(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
DRM_DEBUG("%d\n", magic);
hash = DRM(hash_magic)(magic);
- entry = DRM(alloc)(sizeof(*entry), DRM_MEM_MAGIC);
+ entry = drm_core_alloc(sizeof(*entry), DRM_MEM_MAGIC);
if (!entry) return -ENOMEM;
memset(entry, 0, sizeof(*entry));
entry->magic = magic;
@@ -152,7 +152,7 @@ int DRM(remove_magic)(drm_device_t *dev, drm_magic_t magic)
}
up(&dev->struct_sem);
- DRM(free)(pt, sizeof(*pt), DRM_MEM_MAGIC);
+ drm_core_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
return -EINVAL;
}
diff --git a/linux/drm_bufs.c b/linux/drm_bufs.c
new file mode 100644
index 00000000..f53dd523
--- /dev/null
+++ b/linux/drm_bufs.c
@@ -0,0 +1,1346 @@
+/**
+ * \file drm_bufs.c
+ * Generic buffer Library File
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
+ *
+ * Copyright 1999, 2000 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.
+ */
+
+#include "drm_headers.h"
+/**
+ * Compute size order. Returns the exponent of the smaller power of two which
+ * is greater or equal to given number.
+ *
+ * \param size size.
+ * \return order.
+ *
+ * \todo Can be made faster.
+ */
+int drm_core_order( unsigned long size )
+{
+ int order;
+ unsigned long tmp;
+
+ for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++)
+ ;
+
+ if (size & (size - 1))
+ ++order;
+
+ return order;
+}
+
+ /**
+ * Adjusts the memory offset to its absolute value according to the mapping
+ * type. Adds the map to the map list drm_device::maplist. Adds MTRR's where
+ * applicable and if supported by the kernel.
+ */
+int drm_core_initmap( drm_device_t *dev, unsigned int offset, unsigned int size, int type, int flags )
+{
+ drm_map_t *map;
+ drm_map_list_t *list;
+
+ DRM_DEBUG("\n");
+
+ if ( (offset & (~PAGE_MASK)) || (size & (~PAGE_MASK)) )
+ return -EINVAL;
+#if !defined(__sparc__) && !defined(__alpha__)
+ if ( offset + size < offset || offset < virt_to_phys(high_memory) )
+ return -EINVAL;
+#endif
+ if ( !(list = drm_core_alloc( sizeof(*list), DRM_MEM_MAPS )))
+ return -ENOMEM;
+ memset(list, 0, sizeof(*list));
+
+ if ( !(map = drm_core_alloc( sizeof(*map), DRM_MEM_MAPS ))) {
+ drm_core_free(list, sizeof(*list), DRM_MEM_MAPS);
+ return -ENOMEM;
+ }
+
+ *map = (drm_map_t){
+ .offset = offset,
+ .size = size,
+ .type = type,
+ .flags = flags,
+ .mtrr = -1,
+ .handle = 0,
+ };
+ list->map = map;
+
+ DRM_DEBUG( "initmap offset = 0x%08lx, size = 0x%08lx, type = %d\n",
+ map->offset, map->size, map->type );
+
+#ifdef __alpha__
+ map->offset += dev->hose->mem_space->start;
+#endif
+#if __OS_HAS_MTRR
+ if ( drm_core_check_feature(dev, DRIVER_USE_MTRR) ) {
+ if ( map->type == _DRM_FRAME_BUFFER ||
+ (map->flags & _DRM_WRITE_COMBINING) ) {
+ map->mtrr = mtrr_add( map->offset, map->size,
+ MTRR_TYPE_WRCOMB, 1 );
+ }
+ }
+#endif
+ if (map->type == _DRM_REGISTERS)
+ drm_core_ioremap( map, dev );
+
+ down(&dev->struct_sem);
+ list_add(&list->head, &dev->maplist->head);
+ up(&dev->struct_sem);
+
+ DRM_DEBUG("finished\n");
+
+ return 0;
+}
+
+/**
+ * Ioctl to specify a range of memory that is available for mapping by a non-root process.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_map structure.
+ * \return zero on success or a negative value on error.
+ *
+ * Adjusts the memory offset to its absolute value according to the mapping
+ * type. Adds the map to the map list drm_device::maplist. Adds MTRR's where
+ * applicable and if supported by the kernel.
+ */
+int drm_core_addmap( 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_map_t *map;
+ drm_map_t __user *argp = (void __user *)arg;
+ drm_map_list_t *list;
+
+ if ( !(filp->f_mode & 3) ) return -EACCES; /* Require read/write */
+
+ map = drm_core_alloc( sizeof(*map), DRM_MEM_MAPS );
+ if ( !map )
+ return -ENOMEM;
+
+ if ( copy_from_user( map, argp, sizeof(*map) ) ) {
+ drm_core_free( map, sizeof(*map), DRM_MEM_MAPS );
+ return -EFAULT;
+ }
+
+ /* Only allow shared memory to be removable since we only keep enough
+ * book keeping information about shared memory to allow for removal
+ * when processes fork.
+ */
+ if ( (map->flags & _DRM_REMOVABLE) && map->type != _DRM_SHM ) {
+ drm_core_free( map, sizeof(*map), DRM_MEM_MAPS );
+ return -EINVAL;
+ }
+ DRM_DEBUG( "offset = 0x%08lx, size = 0x%08lx, type = %d\n",
+ map->offset, map->size, map->type );
+ if ( (map->offset & (~PAGE_MASK)) || (map->size & (~PAGE_MASK)) ) {
+ drm_core_free( map, sizeof(*map), DRM_MEM_MAPS );
+ return -EINVAL;
+ }
+ map->mtrr = -1;
+ map->handle = NULL;
+
+ switch ( map->type ) {
+ case _DRM_REGISTERS:
+ case _DRM_FRAME_BUFFER: {
+ /* after all the drivers switch to permanent mapping this should just return an error */
+ struct list_head *_list;
+
+ /* if map already exists, return the existing one instead of creating a new one */
+ list_for_each( _list, &dev->maplist->head ) {
+ drm_map_list_t *_entry = list_entry( _list, drm_map_list_t, head );
+ if ( _entry->map && _entry->map->type == map->type ) {
+ drm_core_free( map, sizeof(*map), DRM_MEM_MAPS );
+ map = _entry->map;
+ DRM_DEBUG( "Found existing: offset = 0x%08lx, size = 0x%08lx, type = %d\n",
+ map->offset, map->size, map->type );
+ goto found_it;
+ }
+ }
+#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__)
+ if ( map->offset + map->size < map->offset ||
+ map->offset < virt_to_phys(high_memory) ) {
+ drm_core_free( map, sizeof(*map), DRM_MEM_MAPS );
+ return -EINVAL;
+ }
+#endif
+#ifdef __alpha__
+ map->offset += dev->hose->mem_space->start;
+#endif
+#if __OS_HAS_MTRR
+ if (drm_core_check_feature(dev, DRIVER_USE_MTRR)) {
+ if ( map->type == _DRM_FRAME_BUFFER ||
+ (map->flags & _DRM_WRITE_COMBINING) ) {
+ map->mtrr = mtrr_add( map->offset, map->size,
+ MTRR_TYPE_WRCOMB, 1 );
+ }
+ }
+#endif
+ if (map->type == _DRM_REGISTERS)
+ drm_core_ioremap( map, dev );
+ break;
+ }
+ case _DRM_SHM:
+ map->handle = vmalloc_32(map->size);
+ DRM_DEBUG( "%lu %d %p\n",
+ map->size, drm_core_order( map->size ), map->handle );
+ if ( !map->handle ) {
+ drm_core_free( map, sizeof(*map), DRM_MEM_MAPS );
+ return -ENOMEM;
+ }
+ map->offset = (unsigned long)map->handle;
+ if ( map->flags & _DRM_CONTAINS_LOCK ) {
+ /* Prevent a 2nd X Server from creating a 2nd lock */
+ if (dev->lock.hw_lock != NULL) {
+ vfree( map->handle );
+ drm_core_free( map, sizeof(*map), DRM_MEM_MAPS );
+ return -EBUSY;
+ }
+ dev->sigdata.lock =
+ dev->lock.hw_lock = map->handle; /* Pointer to lock */
+ }
+ break;
+#if __OS_HAS_AGP
+ case _DRM_AGP:
+ if (drm_core_check_feature(dev, DRIVER_USE_AGP)) {
+#ifdef __alpha__
+ map->offset += dev->hose->mem_space->start;
+#endif
+ map->offset += dev->agp->base;
+ map->mtrr = dev->agp->agp_mtrr; /* for getmap */
+ }
+ break;
+#endif
+ case _DRM_SCATTER_GATHER:
+ if (!dev->sg) {
+ drm_core_free(map, sizeof(*map), DRM_MEM_MAPS);
+ return -EINVAL;
+ }
+ map->offset += dev->sg->handle;
+ break;
+
+ default:
+ drm_core_free( map, sizeof(*map), DRM_MEM_MAPS );
+ return -EINVAL;
+ }
+
+ list = drm_core_alloc(sizeof(*list), DRM_MEM_MAPS);
+ if(!list) {
+ drm_core_free(map, sizeof(*map), DRM_MEM_MAPS);
+ return -EINVAL;
+ }
+ memset(list, 0, sizeof(*list));
+ list->map = map;
+
+ down(&dev->struct_sem);
+ list_add(&list->head, &dev->maplist->head);
+ up(&dev->struct_sem);
+found_it:
+ if ( copy_to_user( argp, map, sizeof(*map) ) )
+ return -EFAULT;
+ if ( map->type != _DRM_SHM ) {
+ if ( copy_to_user( &argp->handle,
+ &map->offset,
+ sizeof(map->offset) ) )
+ return -EFAULT;
+ }
+ return 0;
+}
+
+
+/**
+ * Remove a map private from list and deallocate resources if the mapping
+ * isn't in use.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_map_t structure.
+ * \return zero on success or a negative value on error.
+ *
+ * Searches the map on drm_device::maplist, removes it from the list, see if
+ * its being used, and free any associate resource (such as MTRR's) if it's not
+ * being on use.
+ *
+ * \sa addmap().
+ */
+int drm_core_rmmap(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;
+ struct list_head *list;
+ drm_map_list_t *r_list = NULL;
+ drm_vma_entry_t *pt, *prev;
+ drm_map_t *map;
+ drm_map_t request;
+ int found_maps = 0;
+
+ if (copy_from_user(&request, (drm_map_t __user *)arg,
+ sizeof(request))) {
+ return -EFAULT;
+ }
+
+ down(&dev->struct_sem);
+ list = &dev->maplist->head;
+ list_for_each(list, &dev->maplist->head) {
+ r_list = list_entry(list, drm_map_list_t, head);
+
+ if(r_list->map &&
+ r_list->map->handle == request.handle &&
+ r_list->map->flags & _DRM_REMOVABLE) break;
+ }
+
+ /* List has wrapped around to the head pointer, or its empty we didn't
+ * find anything.
+ */
+ if(list == (&dev->maplist->head)) {
+ up(&dev->struct_sem);
+ return -EINVAL;
+ }
+ map = r_list->map;
+
+ /* Register and framebuffer maps are permanent */
+ if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) {
+ up(&dev->struct_sem);
+ return 0;
+ }
+ list_del(list);
+ drm_core_free(list, sizeof(*list), DRM_MEM_MAPS);
+
+ for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) {
+ if (pt->vma->vm_private_data == map) found_maps++;
+ }
+
+ if(!found_maps) {
+ switch (map->type) {
+ case _DRM_REGISTERS:
+ case _DRM_FRAME_BUFFER:
+ break; /* Can't get here, make compiler happy */
+ case _DRM_SHM:
+ vfree(map->handle);
+ break;
+ case _DRM_AGP:
+ case _DRM_SCATTER_GATHER:
+ break;
+ }
+ drm_core_free(map, sizeof(*map), DRM_MEM_MAPS);
+ }
+ up(&dev->struct_sem);
+ return 0;
+}
+
+/**
+ * Cleanup after an error on one of the addbufs() functions.
+ *
+ * \param entry buffer entry where the error occurred.
+ *
+ * Frees any pages and buffers associated with the given entry.
+ */
+static void drm_cleanup_buf_error(drm_device_t *dev, drm_buf_entry_t *entry)
+{
+ int i;
+
+ if (entry->seg_count) {
+ for (i = 0; i < entry->seg_count; i++) {
+ if (entry->seglist[i]) {
+ drm_core_free_pages(entry->seglist[i],
+ entry->page_order,
+ DRM_MEM_DMA);
+ }
+ }
+ drm_core_free(entry->seglist,
+ entry->seg_count *
+ sizeof(*entry->seglist),
+ DRM_MEM_SEGS);
+
+ entry->seg_count = 0;
+ }
+
+ if (entry->buf_count) {
+ for (i = 0; i < entry->buf_count; i++) {
+ if (entry->buflist[i].dev_private) {
+ drm_core_free(entry->buflist[i].dev_private,
+ entry->buflist[i].dev_priv_size,
+ DRM_MEM_BUFS);
+ }
+ }
+ drm_core_free(entry->buflist,
+ entry->buf_count *
+ sizeof(*entry->buflist),
+ DRM_MEM_BUFS);
+
+ entry->buf_count = 0;
+ }
+}
+
+#if __OS_HAS_AGP
+/**
+ * Add AGP buffers for DMA transfers (ioctl).
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_buf_desc_t request.
+ * \return zero on success or a negative number on failure.
+ *
+ * After some sanity checks creates a drm_buf structure for each buffer and
+ * reallocates the buffer list of the same size order to accommodate the new
+ * buffers.
+ */
+int drm_core_addbufs_agp( 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_device_dma_t *dma = dev->dma;
+ drm_buf_desc_t request;
+ drm_buf_entry_t *entry;
+ drm_buf_t *buf;
+ unsigned long offset;
+ unsigned long agp_offset;
+ int count;
+ int order;
+ int size;
+ int alignment;
+ int page_order;
+ int total;
+ int byte_count;
+ int i;
+ drm_buf_t **temp_buflist;
+ drm_buf_desc_t __user *argp = (void __user *)arg;
+
+ if ( !dma ) return -EINVAL;
+
+ if ( copy_from_user( &request, argp,
+ sizeof(request) ) )
+ return -EFAULT;
+
+ count = request.count;
+ order = drm_core_order( request.size );
+ size = 1 << order;
+
+ alignment = (request.flags & _DRM_PAGE_ALIGN)
+ ? PAGE_ALIGN(size) : size;
+ page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+ total = PAGE_SIZE << page_order;
+
+ byte_count = 0;
+ agp_offset = dev->agp->base + request.agp_start;
+
+ DRM_DEBUG( "count: %d\n", count );
+ DRM_DEBUG( "order: %d\n", order );
+ DRM_DEBUG( "size: %d\n", size );
+ DRM_DEBUG( "agp_offset: %lu\n", agp_offset );
+ DRM_DEBUG( "alignment: %d\n", alignment );
+ DRM_DEBUG( "page_order: %d\n", page_order );
+ DRM_DEBUG( "total: %d\n", total );
+
+ if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
+ if ( dev->queue_count ) return -EBUSY; /* Not while in use */
+
+ spin_lock( &dev->count_lock );
+ if ( dev->buf_use ) {
+ spin_unlock( &dev->count_lock );
+ return -EBUSY;
+ }
+ atomic_inc( &dev->buf_alloc );
+ spin_unlock( &dev->count_lock );
+
+ down( &dev->struct_sem );
+ entry = &dma->bufs[order];
+ if ( entry->buf_count ) {
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM; /* May only call once for each order */
+ }
+
+ if (count < 0 || count > 4096) {
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -EINVAL;
+ }
+
+ entry->buflist = drm_core_alloc( count * sizeof(*entry->buflist),
+ DRM_MEM_BUFS );
+ if ( !entry->buflist ) {
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM;
+ }
+ memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
+
+ entry->buf_size = size;
+ entry->page_order = page_order;
+
+ offset = 0;
+
+ while ( entry->buf_count < count ) {
+ buf = &entry->buflist[entry->buf_count];
+ buf->idx = dma->buf_count + entry->buf_count;
+ buf->total = alignment;
+ buf->order = order;
+ buf->used = 0;
+
+ buf->offset = (dma->byte_count + offset);
+ buf->bus_address = agp_offset + offset;
+ buf->address = (void *)(agp_offset + offset);
+ buf->next = NULL;
+ buf->waiting = 0;
+ buf->pending = 0;
+ init_waitqueue_head( &buf->dma_wait );
+ buf->filp = NULL;
+
+ buf->dev_priv_size = dev->dev_priv_size;
+ buf->dev_private = drm_core_alloc( buf->dev_priv_size,
+ DRM_MEM_BUFS );
+ if(!buf->dev_private) {
+ /* Set count correctly so we free the proper amount. */
+ entry->buf_count = count;
+ drm_cleanup_buf_error(dev,entry);
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM;
+ }
+ memset( buf->dev_private, 0, buf->dev_priv_size );
+
+ DRM_DEBUG( "buffer %d @ %p\n",
+ entry->buf_count, buf->address );
+
+ offset += alignment;
+ entry->buf_count++;
+ byte_count += PAGE_SIZE << page_order;
+ }
+
+ DRM_DEBUG( "byte_count: %d\n", byte_count );
+
+ temp_buflist = drm_core_realloc( dma->buflist,
+ dma->buf_count * sizeof(*dma->buflist),
+ (dma->buf_count + entry->buf_count)
+ * sizeof(*dma->buflist),
+ DRM_MEM_BUFS );
+ if(!temp_buflist) {
+ /* Free the entry because it isn't valid */
+ drm_cleanup_buf_error(dev,entry);
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM;
+ }
+ dma->buflist = temp_buflist;
+
+ for ( i = 0 ; i < entry->buf_count ; i++ ) {
+ dma->buflist[i + dma->buf_count] = &entry->buflist[i];
+ }
+
+ dma->buf_count += entry->buf_count;
+ dma->byte_count += byte_count;
+
+ DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
+ DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
+
+ up( &dev->struct_sem );
+
+ request.count = entry->buf_count;
+ request.size = size;
+
+ if ( copy_to_user( argp, &request, sizeof(request) ) )
+ return -EFAULT;
+
+ dma->flags = _DRM_DMA_USE_AGP;
+
+ atomic_dec( &dev->buf_alloc );
+ return 0;
+}
+#endif /* __OS_HAS_AGP */
+
+int drm_core_addbufs_pci( 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_device_dma_t *dma = dev->dma;
+ drm_buf_desc_t request;
+ int count;
+ int order;
+ int size;
+ int total;
+ int page_order;
+ drm_buf_entry_t *entry;
+ unsigned long page;
+ drm_buf_t *buf;
+ int alignment;
+ unsigned long offset;
+ int i;
+ int byte_count;
+ int page_count;
+ unsigned long *temp_pagelist;
+ drm_buf_t **temp_buflist;
+ drm_buf_desc_t __user *argp = (void __user *)arg;
+
+ if (!drm_core_check_feature(dev, DRIVER_PCI_DMA)) return -EINVAL;
+
+ if ( !dma ) return -EINVAL;
+
+ if ( copy_from_user( &request, argp, sizeof(request) ) )
+ return -EFAULT;
+
+ count = request.count;
+ order = drm_core_order( request.size );
+ size = 1 << order;
+
+ DRM_DEBUG( "count=%d, size=%d (%d), order=%d, queue_count=%d\n",
+ request.count, request.size, size,
+ order, dev->queue_count );
+
+ if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
+ if ( dev->queue_count ) return -EBUSY; /* Not while in use */
+
+ alignment = (request.flags & _DRM_PAGE_ALIGN)
+ ? PAGE_ALIGN(size) : size;
+ page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+ total = PAGE_SIZE << page_order;
+
+ spin_lock( &dev->count_lock );
+ if ( dev->buf_use ) {
+ spin_unlock( &dev->count_lock );
+ return -EBUSY;
+ }
+ atomic_inc( &dev->buf_alloc );
+ spin_unlock( &dev->count_lock );
+
+ down( &dev->struct_sem );
+ entry = &dma->bufs[order];
+ if ( entry->buf_count ) {
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM; /* May only call once for each order */
+ }
+
+ if (count < 0 || count > 4096) {
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -EINVAL;
+ }
+
+ entry->buflist = drm_core_alloc( count * sizeof(*entry->buflist),
+ DRM_MEM_BUFS );
+ if ( !entry->buflist ) {
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM;
+ }
+ memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
+
+ entry->seglist = drm_core_alloc( count * sizeof(*entry->seglist),
+ DRM_MEM_SEGS );
+ if ( !entry->seglist ) {
+ drm_core_free( entry->buflist,
+ count * sizeof(*entry->buflist),
+ DRM_MEM_BUFS );
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM;
+ }
+ memset( entry->seglist, 0, count * sizeof(*entry->seglist) );
+
+ /* Keep the original pagelist until we know all the allocations
+ * have succeeded
+ */
+ temp_pagelist = drm_core_alloc( (dma->page_count + (count << page_order))
+ * sizeof(*dma->pagelist),
+ DRM_MEM_PAGES );
+ if (!temp_pagelist) {
+ drm_core_free( entry->buflist,
+ count * sizeof(*entry->buflist),
+ DRM_MEM_BUFS );
+ drm_core_free( entry->seglist,
+ count * sizeof(*entry->seglist),
+ DRM_MEM_SEGS );
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM;
+ }
+ memcpy(temp_pagelist,
+ dma->pagelist,
+ dma->page_count * sizeof(*dma->pagelist));
+ DRM_DEBUG( "pagelist: %d entries\n",
+ dma->page_count + (count << page_order) );
+
+ entry->buf_size = size;
+ entry->page_order = page_order;
+ byte_count = 0;
+ page_count = 0;
+
+ while ( entry->buf_count < count ) {
+ page = drm_core_alloc_pages( page_order, DRM_MEM_DMA );
+ if ( !page ) {
+ /* Set count correctly so we free the proper amount. */
+ entry->buf_count = count;
+ entry->seg_count = count;
+ drm_cleanup_buf_error(dev,entry);
+ drm_core_free( temp_pagelist,
+ (dma->page_count + (count << page_order))
+ * sizeof(*dma->pagelist),
+ DRM_MEM_PAGES );
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM;
+ }
+ entry->seglist[entry->seg_count++] = page;
+ for ( i = 0 ; i < (1 << page_order) ; i++ ) {
+ DRM_DEBUG( "page %d @ 0x%08lx\n",
+ dma->page_count + page_count,
+ page + PAGE_SIZE * i );
+ temp_pagelist[dma->page_count + page_count++]
+ = page + PAGE_SIZE * i;
+ }
+ for ( offset = 0 ;
+ offset + size <= total && entry->buf_count < count ;
+ offset += alignment, ++entry->buf_count ) {
+ buf = &entry->buflist[entry->buf_count];
+ buf->idx = dma->buf_count + entry->buf_count;
+ buf->total = alignment;
+ buf->order = order;
+ buf->used = 0;
+ buf->offset = (dma->byte_count + byte_count + offset);
+ buf->address = (void *)(page + offset);
+ buf->bus_address = virt_to_bus(buf->address);
+ buf->next = NULL;
+ buf->waiting = 0;
+ buf->pending = 0;
+ init_waitqueue_head( &buf->dma_wait );
+ buf->filp = NULL;
+
+ buf->dev_priv_size = dev->dev_priv_size;
+ buf->dev_private = drm_core_alloc( dev->dev_priv_size,
+ DRM_MEM_BUFS );
+ if(!buf->dev_private) {
+ /* Set count correctly so we free the proper amount. */
+ entry->buf_count = count;
+ entry->seg_count = count;
+ drm_cleanup_buf_error(dev,entry);
+ drm_core_free( temp_pagelist,
+ (dma->page_count + (count << page_order))
+ * sizeof(*dma->pagelist),
+ DRM_MEM_PAGES );
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM;
+ }
+ memset( buf->dev_private, 0, buf->dev_priv_size );
+
+ DRM_DEBUG( "buffer %d @ %p\n",
+ entry->buf_count, buf->address );
+ }
+ byte_count += PAGE_SIZE << page_order;
+ }
+
+ temp_buflist = drm_core_realloc( dma->buflist,
+ dma->buf_count * sizeof(*dma->buflist),
+ (dma->buf_count + entry->buf_count)
+ * sizeof(*dma->buflist),
+ DRM_MEM_BUFS );
+ if (!temp_buflist) {
+ /* Free the entry because it isn't valid */
+ drm_cleanup_buf_error(dev,entry);
+ drm_core_free( temp_pagelist,
+ (dma->page_count + (count << page_order))
+ * sizeof(*dma->pagelist),
+ DRM_MEM_PAGES );
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM;
+ }
+ dma->buflist = temp_buflist;
+
+ for ( i = 0 ; i < entry->buf_count ; i++ ) {
+ dma->buflist[i + dma->buf_count] = &entry->buflist[i];
+ }
+
+ /* No allocations failed, so now we can replace the orginal pagelist
+ * with the new one.
+ */
+ if (dma->page_count) {
+ drm_core_free(dma->pagelist,
+ dma->page_count * sizeof(*dma->pagelist),
+ DRM_MEM_PAGES);
+ }
+ dma->pagelist = temp_pagelist;
+
+ dma->buf_count += entry->buf_count;
+ dma->seg_count += entry->seg_count;
+ dma->page_count += entry->seg_count << page_order;
+ dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
+
+ up( &dev->struct_sem );
+
+ request.count = entry->buf_count;
+ request.size = size;
+
+ if ( copy_to_user( argp, &request, sizeof(request) ) )
+ return -EFAULT;
+
+ atomic_dec( &dev->buf_alloc );
+ return 0;
+
+}
+
+int drm_core_addbufs_sg( 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_device_dma_t *dma = dev->dma;
+ drm_buf_desc_t __user *argp = (void __user *)arg;
+ drm_buf_desc_t request;
+ drm_buf_entry_t *entry;
+ drm_buf_t *buf;
+ unsigned long offset;
+ unsigned long agp_offset;
+ int count;
+ int order;
+ int size;
+ int alignment;
+ int page_order;
+ int total;
+ int byte_count;
+ int i;
+ drm_buf_t **temp_buflist;
+
+ if (!drm_core_check_feature(dev, DRIVER_SG)) return -EINVAL;
+
+ if ( !dma ) return -EINVAL;
+
+ if ( copy_from_user( &request, argp, sizeof(request) ) )
+ return -EFAULT;
+
+ count = request.count;
+ order = drm_core_order( request.size );
+ size = 1 << order;
+
+ alignment = (request.flags & _DRM_PAGE_ALIGN)
+ ? PAGE_ALIGN(size) : size;
+ page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+ total = PAGE_SIZE << page_order;
+
+ byte_count = 0;
+ agp_offset = request.agp_start;
+
+ DRM_DEBUG( "count: %d\n", count );
+ DRM_DEBUG( "order: %d\n", order );
+ DRM_DEBUG( "size: %d\n", size );
+ DRM_DEBUG( "agp_offset: %lu\n", agp_offset );
+ DRM_DEBUG( "alignment: %d\n", alignment );
+ DRM_DEBUG( "page_order: %d\n", page_order );
+ DRM_DEBUG( "total: %d\n", total );
+
+ if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
+ if ( dev->queue_count ) return -EBUSY; /* Not while in use */
+
+ spin_lock( &dev->count_lock );
+ if ( dev->buf_use ) {
+ spin_unlock( &dev->count_lock );
+ return -EBUSY;
+ }
+ atomic_inc( &dev->buf_alloc );
+ spin_unlock( &dev->count_lock );
+
+ down( &dev->struct_sem );
+ entry = &dma->bufs[order];
+ if ( entry->buf_count ) {
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM; /* May only call once for each order */
+ }
+
+ if (count < 0 || count > 4096) {
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -EINVAL;
+ }
+
+ entry->buflist = drm_core_alloc( count * sizeof(*entry->buflist),
+ DRM_MEM_BUFS );
+ if ( !entry->buflist ) {
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM;
+ }
+ memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
+
+ entry->buf_size = size;
+ entry->page_order = page_order;
+
+ offset = 0;
+
+ while ( entry->buf_count < count ) {
+ buf = &entry->buflist[entry->buf_count];
+ buf->idx = dma->buf_count + entry->buf_count;
+ buf->total = alignment;
+ buf->order = order;
+ buf->used = 0;
+
+ buf->offset = (dma->byte_count + offset);
+ buf->bus_address = agp_offset + offset;
+ buf->address = (void *)(agp_offset + offset + dev->sg->handle);
+ buf->next = NULL;
+ buf->waiting = 0;
+ buf->pending = 0;
+ init_waitqueue_head( &buf->dma_wait );
+ buf->filp = NULL;
+
+ buf->dev_priv_size = dev->dev_priv_size;
+ buf->dev_private = drm_core_alloc( dev->dev_priv_size,
+ DRM_MEM_BUFS );
+ if(!buf->dev_private) {
+ /* Set count correctly so we free the proper amount. */
+ entry->buf_count = count;
+ drm_cleanup_buf_error(dev,entry);
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM;
+ }
+
+ memset( buf->dev_private, 0, buf->dev_priv_size );
+
+ DRM_DEBUG( "buffer %d @ %p\n",
+ entry->buf_count, buf->address );
+
+ offset += alignment;
+ entry->buf_count++;
+ byte_count += PAGE_SIZE << page_order;
+ }
+
+ DRM_DEBUG( "byte_count: %d\n", byte_count );
+
+ temp_buflist = drm_core_realloc( dma->buflist,
+ dma->buf_count * sizeof(*dma->buflist),
+ (dma->buf_count + entry->buf_count)
+ * sizeof(*dma->buflist),
+ DRM_MEM_BUFS );
+ if(!temp_buflist) {
+ /* Free the entry because it isn't valid */
+ drm_cleanup_buf_error(dev,entry);
+ up( &dev->struct_sem );
+ atomic_dec( &dev->buf_alloc );
+ return -ENOMEM;
+ }
+ dma->buflist = temp_buflist;
+
+ for ( i = 0 ; i < entry->buf_count ; i++ ) {
+ dma->buflist[i + dma->buf_count] = &entry->buflist[i];
+ }
+
+ dma->buf_count += entry->buf_count;
+ dma->byte_count += byte_count;
+
+ DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
+ DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
+
+ up( &dev->struct_sem );
+
+ request.count = entry->buf_count;
+ request.size = size;
+
+ if ( copy_to_user( argp, &request, sizeof(request) ) )
+ return -EFAULT;
+
+ dma->flags = _DRM_DMA_USE_SG;
+
+ atomic_dec( &dev->buf_alloc );
+ return 0;
+}
+
+/**
+ * Add buffers for DMA transfers (ioctl).
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_buf_desc_t request.
+ * \return zero on success or a negative number on failure.
+ *
+ * According with the memory type specified in drm_buf_desc::flags and the
+ * build options, it dispatches the call either to addbufs_agp(),
+ * addbufs_sg() or addbufs_pci() for AGP, scatter-gather or consistent
+ * PCI memory respectively.
+ */
+int drm_core_addbufs( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
+{
+ drm_buf_desc_t request;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+ return -EINVAL;
+
+ if ( copy_from_user( &request, (drm_buf_desc_t __user *)arg,
+ sizeof(request) ) )
+ return -EFAULT;
+
+#if __OS_HAS_AGP
+ if ( request.flags & _DRM_AGP_BUFFER )
+ return drm_core_addbufs_agp( inode, filp, cmd, arg );
+ else
+#endif
+ if ( request.flags & _DRM_SG_BUFFER )
+ return drm_core_addbufs_sg( inode, filp, cmd, arg );
+ else
+ return drm_core_addbufs_pci( inode, filp, cmd, arg );
+}
+
+
+/**
+ * Get information about the buffer mappings.
+ *
+ * This was originally mean for debugging purposes, or by a sophisticated
+ * client library to determine how best to use the available buffers (e.g.,
+ * large buffers can be used for image transfer).
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_buf_info structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Increments drm_device::buf_use while holding the drm_device::count_lock
+ * lock, preventing of allocating more buffers after this call. Information
+ * about each requested buffer is then copied into user space.
+ */
+int drm_core_infobufs( 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_device_dma_t *dma = dev->dma;
+ drm_buf_info_t request;
+ drm_buf_info_t __user *argp = (void __user *)arg;
+ int i;
+ int count;
+
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+ return -EINVAL;
+
+ if ( !dma ) return -EINVAL;
+
+ spin_lock( &dev->count_lock );
+ if ( atomic_read( &dev->buf_alloc ) ) {
+ spin_unlock( &dev->count_lock );
+ return -EBUSY;
+ }
+ ++dev->buf_use; /* Can't allocate more after this call */
+ spin_unlock( &dev->count_lock );
+
+ if ( copy_from_user( &request, argp, sizeof(request) ) )
+ return -EFAULT;
+
+ for ( i = 0, count = 0 ; i < DRM_MAX_ORDER + 1 ; i++ ) {
+ if ( dma->bufs[i].buf_count ) ++count;
+ }
+
+ DRM_DEBUG( "count = %d\n", count );
+
+ if ( request.count >= count ) {
+ for ( i = 0, count = 0 ; i < DRM_MAX_ORDER + 1 ; i++ ) {
+ if ( dma->bufs[i].buf_count ) {
+ drm_buf_desc_t __user *to = &request.list[count];
+ drm_buf_entry_t *from = &dma->bufs[i];
+ drm_freelist_t *list = &dma->bufs[i].freelist;
+ if ( copy_to_user( &to->count,
+ &from->buf_count,
+ sizeof(from->buf_count) ) ||
+ copy_to_user( &to->size,
+ &from->buf_size,
+ sizeof(from->buf_size) ) ||
+ copy_to_user( &to->low_mark,
+ &list->low_mark,
+ sizeof(list->low_mark) ) ||
+ copy_to_user( &to->high_mark,
+ &list->high_mark,
+ sizeof(list->high_mark) ) )
+ return -EFAULT;
+
+ DRM_DEBUG( "%d %d %d %d %d\n",
+ i,
+ dma->bufs[i].buf_count,
+ dma->bufs[i].buf_size,
+ dma->bufs[i].freelist.low_mark,
+ dma->bufs[i].freelist.high_mark );
+ ++count;
+ }
+ }
+ }
+ request.count = count;
+
+ if ( copy_to_user( argp, &request, sizeof(request) ) )
+ return -EFAULT;
+
+ return 0;
+}
+
+/**
+ * Specifies a low and high water mark for buffer allocation
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg a pointer to a drm_buf_desc structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies that the size order is bounded between the admissible orders and
+ * updates the respective drm_device_dma::bufs entry low and high water mark.
+ *
+ * \note This ioctl is deprecated and mostly never used.
+ */
+int drm_core_markbufs( 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_device_dma_t *dma = dev->dma;
+ drm_buf_desc_t request;
+ int order;
+ drm_buf_entry_t *entry;
+
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+ return -EINVAL;
+
+ if ( !dma ) return -EINVAL;
+
+ if ( copy_from_user( &request,
+ (drm_buf_desc_t __user *)arg,
+ sizeof(request) ) )
+ return -EFAULT;
+
+ DRM_DEBUG( "%d, %d, %d\n",
+ request.size, request.low_mark, request.high_mark );
+ order = drm_core_order( request.size );
+ if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
+ entry = &dma->bufs[order];
+
+ if ( request.low_mark < 0 || request.low_mark > entry->buf_count )
+ return -EINVAL;
+ if ( request.high_mark < 0 || request.high_mark > entry->buf_count )
+ return -EINVAL;
+
+ entry->freelist.low_mark = request.low_mark;
+ entry->freelist.high_mark = request.high_mark;
+
+ return 0;
+}
+
+/**
+ * Unreserve the buffers in list, previously reserved using drmDMA.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_buf_free structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Calls free_buffer() for each used buffer.
+ * This function is primarily used for debugging.
+ */
+int drm_core_freebufs( 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_device_dma_t *dma = dev->dma;
+ drm_buf_free_t request;
+ int i;
+ int idx;
+ drm_buf_t *buf;
+
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+ return -EINVAL;
+
+ if ( !dma ) return -EINVAL;
+
+ if ( copy_from_user( &request,
+ (drm_buf_free_t __user *)arg,
+ sizeof(request) ) )
+ return -EFAULT;
+
+ DRM_DEBUG( "%d\n", request.count );
+ for ( i = 0 ; i < request.count ; i++ ) {
+ if ( copy_from_user( &idx,
+ &request.list[i],
+ sizeof(idx) ) )
+ return -EFAULT;
+ if ( idx < 0 || idx >= dma->buf_count ) {
+ DRM_ERROR( "Index %d (of %d max)\n",
+ idx, dma->buf_count - 1 );
+ return -EINVAL;
+ }
+ buf = dma->buflist[idx];
+ if ( buf->filp != filp ) {
+ DRM_ERROR( "Process %d freeing buffer not owned\n",
+ current->pid );
+ return -EINVAL;
+ }
+ drm_core_free_buffer( dev, buf );
+ }
+
+ return 0;
+}
+
+/**
+ * Maps all of the DMA buffers into client-virtual space (ioctl).
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_buf_map structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Maps the AGP or SG buffer region with do_mmap(), and copies information
+ * about each buffer into user space. The PCI buffers are already mapped on the
+ * addbufs_pci() call.
+ */
+int drm_core_mapbufs( 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_device_dma_t *dma = dev->dma;
+ drm_buf_map_t __user *argp = (void __user *)arg;
+ int retcode = 0;
+ const int zero = 0;
+ unsigned long virtual;
+ unsigned long address;
+ drm_buf_map_t request;
+ int i;
+
+ if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+ return -EINVAL;
+
+ if ( !dma ) return -EINVAL;
+
+ spin_lock( &dev->count_lock );
+ if ( atomic_read( &dev->buf_alloc ) ) {
+ spin_unlock( &dev->count_lock );
+ return -EBUSY;
+ }
+ dev->buf_use++; /* Can't allocate more after this call */
+ spin_unlock( &dev->count_lock );
+
+ if ( copy_from_user( &request, argp, sizeof(request) ) )
+ return -EFAULT;
+
+ if ( request.count >= dma->buf_count ) {
+ if (( drm_core_check_feature(dev, DRIVER_USE_AGP) && (dma->flags & _DRM_DMA_USE_AGP)) ||
+ ( drm_core_check_feature(dev, DRIVER_SG) && (dma->flags & _DRM_DMA_USE_SG)) ) {
+ drm_map_t *map = dev->agp_buffer_map;
+
+ if ( !map ) {
+ retcode = -EINVAL;
+ goto done;
+ }
+
+#if LINUX_VERSION_CODE <= 0x020402
+ down( &current->mm->mmap_sem );
+#else
+ down_write( &current->mm->mmap_sem );
+#endif
+ virtual = do_mmap( filp, 0, map->size,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ (unsigned long)map->offset );
+#if LINUX_VERSION_CODE <= 0x020402
+ up( &current->mm->mmap_sem );
+#else
+ up_write( &current->mm->mmap_sem );
+#endif
+ } else {
+#if LINUX_VERSION_CODE <= 0x020402
+ down( &current->mm->mmap_sem );
+#else
+ down_write( &current->mm->mmap_sem );
+#endif
+ virtual = do_mmap( filp, 0, dma->byte_count,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED, 0 );
+#if LINUX_VERSION_CODE <= 0x020402
+ up( &current->mm->mmap_sem );
+#else
+ up_write( &current->mm->mmap_sem );
+#endif
+ }
+ if ( virtual > -1024UL ) {
+ /* Real error */
+ retcode = (signed long)virtual;
+ goto done;
+ }
+ request.virtual = (void __user *)virtual;
+
+ for ( i = 0 ; i < dma->buf_count ; i++ ) {
+ if ( copy_to_user( &request.list[i].idx,
+ &dma->buflist[i]->idx,
+ sizeof(request.list[0].idx) ) ) {
+ retcode = -EFAULT;
+ goto done;
+ }
+ if ( copy_to_user( &request.list[i].total,
+ &dma->buflist[i]->total,
+ sizeof(request.list[0].total) ) ) {
+ retcode = -EFAULT;
+ goto done;
+ }
+ if ( copy_to_user( &request.list[i].used,
+ &zero,
+ sizeof(zero) ) ) {
+ retcode = -EFAULT;
+ goto done;
+ }
+ address = virtual + dma->buflist[i]->offset; /* *** */
+ if ( copy_to_user( &request.list[i].address,
+ &address,
+ sizeof(address) ) ) {
+ retcode = -EFAULT;
+ goto done;
+ }
+ }
+ }
+ done:
+ request.count = dma->buf_count;
+ DRM_DEBUG( "%d buffers, retcode = %d\n", request.count, retcode );
+
+ if ( copy_to_user( argp, &request, sizeof(request) ) )
+ return -EFAULT;
+
+ return retcode;
+}
+
diff --git a/linux/drm_context.h b/linux/drm_context.h
index e1cb95c6..8bad6b39 100644
--- a/linux/drm_context.h
+++ b/linux/drm_context.h
@@ -100,7 +100,7 @@ int DRM(ctxbitmap_next)( drm_device_t *dev )
if(dev->context_sareas) {
drm_map_t **ctx_sareas;
- ctx_sareas = DRM(realloc)(dev->context_sareas,
+ ctx_sareas = drm_core_realloc(dev->context_sareas,
(dev->max_context - 1) *
sizeof(*dev->context_sareas),
dev->max_context *
@@ -115,7 +115,7 @@ int DRM(ctxbitmap_next)( drm_device_t *dev )
dev->context_sareas[bit] = NULL;
} else {
/* max_context == 1 at this point */
- dev->context_sareas = DRM(alloc)(
+ dev->context_sareas = drm_core_alloc(
dev->max_context *
sizeof(*dev->context_sareas),
DRM_MEM_MAPS);
@@ -148,7 +148,7 @@ int DRM(ctxbitmap_init)( drm_device_t *dev )
int temp;
down(&dev->struct_sem);
- dev->ctx_bitmap = (unsigned long *) DRM(alloc)( PAGE_SIZE,
+ dev->ctx_bitmap = (unsigned long *) drm_core_alloc( PAGE_SIZE,
DRM_MEM_CTXBITMAP );
if ( dev->ctx_bitmap == NULL ) {
up(&dev->struct_sem);
@@ -178,11 +178,11 @@ int DRM(ctxbitmap_init)( drm_device_t *dev )
void DRM(ctxbitmap_cleanup)( drm_device_t *dev )
{
down(&dev->struct_sem);
- if( dev->context_sareas ) DRM(free)( dev->context_sareas,
+ if( dev->context_sareas ) drm_core_free( dev->context_sareas,
sizeof(*dev->context_sareas) *
dev->max_context,
DRM_MEM_MAPS );
- DRM(free)( (void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP );
+ drm_core_free( (void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP );
up(&dev->struct_sem);
}
@@ -421,7 +421,7 @@ int DRM(addctx)( struct inode *inode, struct file *filp,
dev->fn_tbl.context_ctor(dev, ctx.handle);
}
- ctx_entry = DRM(alloc)( sizeof(*ctx_entry), DRM_MEM_CTXLIST );
+ ctx_entry = drm_core_alloc( sizeof(*ctx_entry), DRM_MEM_CTXLIST );
if ( !ctx_entry ) {
DRM_DEBUG("out of memory\n");
return -ENOMEM;
@@ -564,7 +564,7 @@ int DRM(rmctx)( struct inode *inode, struct file *filp,
list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) {
if ( pos->handle == ctx.handle ) {
list_del( &pos->head );
- DRM(free)( pos, sizeof(*pos), DRM_MEM_CTXLIST );
+ drm_core_free( pos, sizeof(*pos), DRM_MEM_CTXLIST );
--dev->ctx_count;
}
}
diff --git a/linux/drm_core.h b/linux/drm_core.h
new file mode 100644
index 00000000..435d5cbf
--- /dev/null
+++ b/linux/drm_core.h
@@ -0,0 +1,699 @@
+#ifndef DRM_CORE_H
+#define DRM_CORE_H
+
+#include "drm_compat.h"
+#define DRM_PROC_LIMIT (PAGE_SIZE-80)
+
+#define DRM_PROC_PRINT(fmt, arg...) \
+ len += sprintf(&buf[len], fmt , ##arg); \
+ if (len > DRM_PROC_LIMIT) { *eof = 1; return len - offset; }
+
+#define DRM_PROC_PRINT_RET(ret, fmt, arg...) \
+ len += sprintf(&buf[len], fmt , ##arg); \
+ if (len > DRM_PROC_LIMIT) { ret; *eof = 1; return len - offset; }
+
+/**
+ * Memory error output.
+ *
+ * \param area memory area where the error occurred.
+ * \param fmt printf() like format string.
+ * \param arg arguments
+ */
+#define DRM_INFO(fmt, arg...) printk(KERN_INFO "[" DRM_NAME "] " fmt , ##arg)
+
+/**
+ * Error output.
+ *
+ * \param fmt printf() like format string.
+ * \param arg arguments
+ */
+#define DRM_ERROR(fmt, arg...) \
+ printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* " fmt , __FUNCTION__ , ##arg)
+
+#if DRM_DEBUG_CODE
+#define DRM_DEBUG(fmt, arg...) \
+ do { \
+ if (1) \
+ printk(KERN_DEBUG \
+ "[" DRM_NAME ":%s] " fmt , \
+ __FUNCTION__ , ##arg); \
+ } while (0)
+#else
+#define DRM_DEBUG(fmt, arg...) do { } while (0)
+#endif
+
+#define DRM_LEFTCOUNT(x) (((x)->rp + (x)->count - (x)->wp) % ((x)->count + 1))
+#define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x))
+#define DRM_WAITCOUNT(dev,idx) DRM_BUFCOUNT(&dev->queuelist[idx]->waitlist)
+
+
+/* driver capabilities and requirements mask */
+#define DRIVER_USE_AGP 0x1
+#define DRIVER_REQUIRE_AGP 0x2
+#define DRIVER_USE_MTRR 0x4
+#define DRIVER_HAVE_DMA 0x10
+#define DRIVER_HAVE_IRQ 0x20
+#define DRIVER_SG 0x40
+#define DRIVER_PCI_DMA 0x80
+#define DRIVER_IRQ_SHARED 0x100
+#define DRIVER_IRQ_VBL 0x200
+#define DRIVER_DMA_QUEUE 0x800
+
+#define __OS_HAS_AGP (defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE))
+#define __OS_HAS_MTRR (defined(CONFIG_MTRR))
+/*@}*/
+#define DRM_DEBUG_CODE 2 /**< Include debugging code if > 1, then
+ also include looping detection. */
+
+#define DRM_HASH_SIZE 16 /**< Size of key hash table. Must be power of 2. */
+#define DRM_KERNEL_CONTEXT 0 /**< Change drm_resctx if changed */
+#define DRM_RESERVED_CONTEXTS 1 /**< Change drm_resctx if changed */
+#define DRM_LOOPING_LIMIT 5000000
+#define DRM_BSZ 1024 /**< Buffer size for /dev/drm? output */
+#define DRM_TIME_SLICE (HZ/20) /**< Time slice for GLXContexts */
+#define DRM_LOCK_SLICE 1 /**< Time slice for lock, in jiffies */
+
+#define DRM_FLAG_DEBUG 0x01
+
+#define DRM_MEM_DMA 0
+#define DRM_MEM_SAREA 1
+#define DRM_MEM_DRIVER 2
+#define DRM_MEM_MAGIC 3
+#define DRM_MEM_IOCTLS 4
+#define DRM_MEM_MAPS 5
+#define DRM_MEM_VMAS 6
+#define DRM_MEM_BUFS 7
+#define DRM_MEM_SEGS 8
+#define DRM_MEM_PAGES 9
+#define DRM_MEM_FILES 10
+#define DRM_MEM_QUEUES 11
+#define DRM_MEM_CMDS 12
+#define DRM_MEM_MAPPINGS 13
+#define DRM_MEM_BUFLISTS 14
+#define DRM_MEM_AGPLISTS 15
+#define DRM_MEM_TOTALAGP 16
+#define DRM_MEM_BOUNDAGP 17
+#define DRM_MEM_CTXBITMAP 18
+#define DRM_MEM_STUB 19
+#define DRM_MEM_SGLISTS 20
+#define DRM_MEM_CTXLIST 21
+
+/**
+ * Ioctl function type.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg argument.
+ */
+typedef int drm_ioctl_t( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+
+typedef struct drm_ioctl_desc {
+ drm_ioctl_t *func;
+ int auth_needed;
+ int root_only;
+} drm_ioctl_desc_t;
+
+typedef struct drm_devstate {
+ pid_t owner; /**< X server pid holding x_lock */
+} drm_devstate_t;
+
+typedef struct drm_magic_entry {
+ drm_magic_t magic;
+ struct drm_file *priv;
+ struct drm_magic_entry *next;
+} drm_magic_entry_t;
+
+typedef struct drm_magic_head {
+ struct drm_magic_entry *head;
+ struct drm_magic_entry *tail;
+} drm_magic_head_t;
+
+typedef struct drm_vma_entry {
+ struct vm_area_struct *vma;
+ struct drm_vma_entry *next;
+ pid_t pid;
+} drm_vma_entry_t;
+
+/**
+ * DMA buffer.
+ */
+typedef struct drm_buf {
+ int idx; /**< Index into master buflist */
+ int total; /**< Buffer size */
+ int order; /**< log-base-2(total) */
+ int used; /**< Amount of buffer in use (for DMA) */
+ unsigned long offset; /**< Byte offset (used internally) */
+ void *address; /**< Address of buffer */
+ unsigned long bus_address; /**< Bus address of buffer */
+ struct drm_buf *next; /**< Kernel-only: used for free list */
+ __volatile__ int waiting; /**< On kernel DMA queue */
+ __volatile__ int pending; /**< On hardware DMA queue */
+ wait_queue_head_t dma_wait; /**< Processes waiting */
+ struct file *filp; /**< Pointer to holding file descr */
+ int context; /**< Kernel queue for this buffer */
+ int while_locked;/**< Dispatch this buffer while locked */
+ enum {
+ DRM_LIST_NONE = 0,
+ DRM_LIST_FREE = 1,
+ DRM_LIST_WAIT = 2,
+ DRM_LIST_PEND = 3,
+ DRM_LIST_PRIO = 4,
+ DRM_LIST_RECLAIM = 5
+ } list; /**< Which list we're on */
+
+ int dev_priv_size; /**< Size of buffer private storage */
+ void *dev_private; /**< Per-buffer private storage */
+} drm_buf_t;
+
+
+/** bufs is one longer than it has to be */
+typedef struct drm_waitlist {
+ int count; /**< Number of possible buffers */
+ drm_buf_t **bufs; /**< List of pointers to buffers */
+ drm_buf_t **rp; /**< Read pointer */
+ drm_buf_t **wp; /**< Write pointer */
+ drm_buf_t **end; /**< End pointer */
+ spinlock_t read_lock;
+ spinlock_t write_lock;
+} drm_waitlist_t;
+
+typedef struct drm_freelist {
+ int initialized; /**< Freelist in use */
+ atomic_t count; /**< Number of free buffers */
+ drm_buf_t *next; /**< End pointer */
+
+ wait_queue_head_t waiting; /**< Processes waiting on free bufs */
+ int low_mark; /**< Low water mark */
+ int high_mark; /**< High water mark */
+ atomic_t wfh; /**< If waiting for high mark */
+ spinlock_t lock;
+} drm_freelist_t;
+
+/**
+ * Buffer entry. There is one of this for each buffer size order.
+ */
+typedef struct drm_buf_entry {
+ int buf_size; /**< size */
+ int buf_count; /**< number of buffers */
+ drm_buf_t *buflist; /**< buffer list */
+ int seg_count;
+ int page_order;
+ unsigned long *seglist;
+
+ drm_freelist_t freelist;
+} drm_buf_entry_t;
+
+/** File private data */
+typedef struct drm_file {
+ int authenticated;
+ int minor;
+ pid_t pid;
+ uid_t uid;
+ drm_magic_t magic;
+ unsigned long ioctl_count;
+ struct drm_file *next;
+ struct drm_file *prev;
+ struct drm_device *dev;
+ int remove_auth_on_close;
+ unsigned long lock_count;
+ void *driver_priv;
+} drm_file_t;
+
+/** Wait queue */
+typedef struct drm_queue {
+ atomic_t use_count; /**< Outstanding uses (+1) */
+ atomic_t finalization; /**< Finalization in progress */
+ atomic_t block_count; /**< Count of processes waiting */
+ atomic_t block_read; /**< Queue blocked for reads */
+ wait_queue_head_t read_queue; /**< Processes waiting on block_read */
+ atomic_t block_write; /**< Queue blocked for writes */
+ wait_queue_head_t write_queue; /**< Processes waiting on block_write */
+#if 1
+ atomic_t total_queued; /**< Total queued statistic */
+ atomic_t total_flushed;/**< Total flushes statistic */
+ atomic_t total_locks; /**< Total locks statistics */
+#endif
+ drm_ctx_flags_t flags; /**< Context preserving and 2D-only */
+ drm_waitlist_t waitlist; /**< Pending buffers */
+ wait_queue_head_t flush_queue; /**< Processes waiting until flush */
+} drm_queue_t;
+
+/**
+ * Lock data.
+ */
+typedef struct drm_lock_data {
+ drm_hw_lock_t *hw_lock; /**< Hardware lock */
+ struct file *filp; /**< File descr of lock holder (0=kernel) */
+ wait_queue_head_t lock_queue; /**< Queue of blocked processes */
+ unsigned long lock_time; /**< Time of last lock in jiffies */
+} drm_lock_data_t;
+
+/**
+ * DMA data.
+ */
+typedef struct drm_device_dma {
+
+ drm_buf_entry_t bufs[DRM_MAX_ORDER+1]; /**< buffers, grouped by their size order */
+ int buf_count; /**< total number of buffers */
+ drm_buf_t **buflist; /**< Vector of pointers into drm_device_dma::bufs */
+ int seg_count;
+ int page_count; /**< number of pages */
+ unsigned long *pagelist; /**< page list */
+ unsigned long byte_count;
+ enum {
+ _DRM_DMA_USE_AGP = 0x01,
+ _DRM_DMA_USE_SG = 0x02
+ } flags;
+
+ /** \name DMA support */
+ /*@{*/
+ drm_buf_t *this_buffer; /**< Buffer being sent */
+ drm_buf_t *next_buffer; /**< Selected buffer to send */
+ drm_queue_t *next_queue; /**< Queue from which buffer selected*/
+ wait_queue_head_t waiting; /**< Processes waiting on free bufs */
+ /*@}*/
+} drm_device_dma_t;
+
+#if __OS_HAS_AGP
+/**
+ * AGP memory entry. Stored as a doubly linked list.
+ */
+typedef struct drm_agp_mem {
+ unsigned long handle; /**< handle */
+ DRM_AGP_MEM *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 {
+ DRM_AGP_KERN 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;
+} drm_sigdata_t;
+
+/**
+ * Mappings list
+ */
+typedef struct drm_map_list {
+ struct list_head head; /**< list head */
+ drm_map_t *map; /**< mapping */
+} drm_map_list_t;
+
+typedef drm_map_t drm_local_map_t;
+
+/**
+ * Context handle list
+ */
+typedef struct drm_ctx_list {
+ struct list_head head; /**< list head */
+ drm_context_t handle; /**< context handle */
+ drm_file_t *tag; /**< associated fd private data */
+} drm_ctx_list_t;
+
+
+typedef struct drm_vbl_sig {
+ struct list_head head;
+ unsigned int sequence;
+ struct siginfo info;
+ struct task_struct *task;
+} drm_vbl_sig_t;
+
+
+/**
+ * DRM device functions structure
+ */
+struct drm_device;
+
+struct drm_driver_fn {
+ int (*preinit)(struct drm_device *, unsigned long flags);
+ int (*postinit)(struct drm_device *, unsigned long flags);
+ void (*prerelease)(struct drm_device *, struct file *filp);
+ void (*pretakedown)(struct drm_device *);
+ int (*postcleanup)(struct drm_device *);
+ int (*presetup)(struct drm_device *);
+ int (*postsetup)(struct drm_device *);
+
+ /* these are opposites at the moment */
+ int (*open_helper)(struct drm_device *, drm_file_t *);
+ void (*free_filp_private)(struct drm_device *, drm_file_t *);
+
+ void (*release)(struct drm_device *, struct file *filp);
+ void (*dma_ready)(struct drm_device *);
+ int (*dma_quiescent)(struct drm_device *);
+ int (*context_ctor)(struct drm_device *dev, int context);
+ int (*context_dtor)(struct drm_device *dev, int context);
+ int (*kernel_context_switch)(struct drm_device *dev, int old, int new);
+ int (*kernel_context_switch_unlock)(struct drm_device *dev);
+ int (*vblank_wait)(struct drm_device *dev, unsigned int *sequence);
+/* these have to be filled in */
+ irqreturn_t (*irq_handler)( DRM_IRQ_ARGS );
+ void (*irq_preinstall)(struct drm_device *dev);
+ void (*irq_postinstall)(struct drm_device *dev);
+ void (*irq_uninstall)(struct drm_device *dev);
+ void (*reclaim_buffers)(struct file *filp);
+ unsigned long (*get_map_ofs)(drm_map_t *map);
+ unsigned long (*get_reg_ofs)(struct drm_device *dev);
+ void (*set_version)(struct drm_device *dev, drm_set_version_t *sv);
+};
+
+/**
+ * DRM device structure.
+ */
+typedef struct drm_device {
+ const char *name; /**< Simple driver name */
+ char *unique; /**< Unique identifier: e.g., busid */
+ int unique_len; /**< Length of unique field */
+ dev_t device; /**< Device number for mknod */
+ char *devname; /**< For /proc/interrupts */
+ int minor; /**< Minor device number */
+ int if_version; /**< Highest interface version set */
+
+ int blocked; /**< Blocked due to VC switch? */
+ struct proc_dir_entry *root; /**< Root for this device's entries */
+
+ /** \name Locks */
+ /*@{*/
+ spinlock_t count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */
+ struct semaphore struct_sem; /**< For others */
+ /*@}*/
+
+ /** \name Usage Counters */
+ /*@{*/
+ int open_count; /**< Outstanding files open */
+ atomic_t ioctl_count; /**< Outstanding IOCTLs pending */
+ atomic_t vma_count; /**< Outstanding vma areas open */
+ int buf_use; /**< Buffers in use -- cannot alloc */
+ atomic_t buf_alloc; /**< Buffer allocation in progress */
+ /*@}*/
+
+ /** \name Performance counters */
+ /*@{*/
+ unsigned long counters;
+ drm_stat_type_t types[15];
+ atomic_t counts[15];
+ /*@}*/
+
+ /** \name Authentication */
+ /*@{*/
+ drm_file_t *file_first; /**< file list head */
+ drm_file_t *file_last; /**< file list tail */
+ drm_magic_head_t magiclist[DRM_HASH_SIZE]; /**< magic hash table */
+ /*@}*/
+
+ /** \name Memory management */
+ /*@{*/
+ drm_map_list_t *maplist; /**< Linked list of regions */
+ int map_count; /**< Number of mappable regions */
+
+ /** \name Context handle management */
+ /*@{*/
+ drm_ctx_list_t *ctxlist; /**< Linked list of context handles */
+ int ctx_count; /**< Number of context handles */
+ struct semaphore ctxlist_sem; /**< For ctxlist */
+
+ drm_map_t **context_sareas; /**< per-context SAREA's */
+ int max_context;
+
+ drm_vma_entry_t *vmalist; /**< List of vmas (for debugging) */
+ drm_lock_data_t lock; /**< Information on hardware lock */
+ /*@}*/
+
+ /** \name DMA queues (contexts) */
+ /*@{*/
+ int queue_count; /**< Number of active DMA queues */
+ int queue_reserved; /**< Number of reserved DMA queues */
+ int queue_slots; /**< Actual length of queuelist */
+ drm_queue_t **queuelist; /**< Vector of pointers to DMA queues */
+ drm_device_dma_t *dma; /**< Optional pointer for DMA support */
+ /*@}*/
+
+ /** \name Context support */
+ /*@{*/
+ int irq; /**< Interrupt used by board */
+ int irq_enabled; /**< True if irq handler is enabled */
+ __volatile__ long context_flag; /**< Context swapping flag */
+ __volatile__ long interrupt_flag; /**< Interruption handler flag */
+ __volatile__ long dma_flag; /**< DMA dispatch flag */
+ struct timer_list timer; /**< Timer for delaying ctx switch */
+ wait_queue_head_t context_wait; /**< Processes waiting on ctx switch */
+ int last_checked; /**< Last context checked for DMA */
+ int last_context; /**< Last current context */
+ unsigned long last_switch; /**< jiffies at last context switch */
+ /*@}*/
+
+#if !HAS_WORKQUEUE
+ struct tq_struct tq;
+#else
+ struct work_struct work;
+#endif
+ /** \name VBLANK IRQ support */
+ /*@{*/
+
+ wait_queue_head_t vbl_queue; /**< VBLANK wait queue */
+ atomic_t vbl_received;
+ spinlock_t vbl_lock;
+ drm_vbl_sig_t vbl_sigs; /**< signal list to send on VBLANK */
+ unsigned int vbl_pending;
+
+ /*@}*/
+ cycles_t ctx_start;
+ cycles_t lck_start;
+
+ char buf[DRM_BSZ]; /**< Output buffer */
+ char *buf_rp; /**< Read pointer */
+ char *buf_wp; /**< Write pointer */
+ char *buf_end; /**< End pointer */
+ struct fasync_struct *buf_async;/**< Processes waiting for SIGIO */
+ wait_queue_head_t buf_readers; /**< Processes waiting to read */
+ wait_queue_head_t buf_writers; /**< Processes waiting to ctx switch */
+
+#if __OS_HAS_AGP
+ drm_agp_head_t *agp; /**< AGP data */
+#endif
+
+ struct pci_dev *pdev; /**< PCI device structure */
+ int pci_domain; /**< PCI bus domain number */
+ int pci_bus; /**< PCI bus number */
+ int pci_slot; /**< PCI slot number */
+ int pci_func; /**< PCI function number */
+#ifdef __alpha__
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3)
+ struct pci_controler *hose;
+#else
+ struct pci_controller *hose;
+#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;
+
+ int need_reset; /**< secondary device needing reset */
+ struct drm_driver_fn fn_tbl;
+ drm_local_map_t *agp_buffer_map;
+ int dev_priv_size;
+ u32 driver_features;
+} drm_device_t;
+
+#if __OS_HAS_AGP
+extern DRM_AGP_MEM *drm_memory_alloc_agp(int pages, u32 type);
+extern int drm_memory_free_agp(DRM_AGP_MEM *handle, int pages);
+extern int drm_memory_bind_agp(DRM_AGP_MEM *handle, unsigned int start);
+extern int drm_memory_unbind_agp(DRM_AGP_MEM *handle);
+#endif
+ /* Buffer management support (drm_bufs.h) */
+extern int drm_core_order( unsigned long size );
+extern int drm_core_addmap( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int drm_core_rmmap( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int drm_core_initmap( drm_device_t *dev, unsigned int offset,
+ unsigned int size, int type, int flags );
+extern int drm_core_addbufs( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int drm_core_infobufs( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int drm_core_markbufs( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int drm_core_freebufs( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+extern int drm_core_mapbufs( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg );
+
+ /* DMA support (drm_dma.h) */
+extern int drm_core_dma_setup(drm_device_t *dev);
+extern void drm_core_dma_takedown(drm_device_t *dev);
+extern void drm_core_free_buffer(drm_device_t *dev, drm_buf_t *buf);
+extern void drm_core_reclaim_buffers( struct file *filp );
+
+#if __OS_HAS_AGP
+ /* AGP/GART support (drm_agpsupport.h) */
+extern drm_agp_head_t *drm_memory_agp_init(void);
+extern void drm_memory_agp_uninit(void);
+extern int drm_memory_agp_acquire(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern void drm_memory_agp_do_release(void);
+extern int drm_memory_agp_release(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_memory_agp_enable(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_memory_agp_info(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_memory_agp_alloc(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_memory_agp_free(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_memory_agp_unbind(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern int drm_memory_agp_bind(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
+extern DRM_AGP_MEM *drm_memory_agp_allocate_memory(size_t pages, u32 type);
+extern int drm_memory_agp_free_memory(DRM_AGP_MEM *handle);
+extern int drm_memory_agp_bind_memory(DRM_AGP_MEM *handle, off_t start);
+extern int drm_memory_agp_unbind_memory(DRM_AGP_MEM *handle);
+#endif
+
+ /* ATI PCIGART support (ati_pcigart.h) */
+extern int drm_ati_pcigart_init(drm_device_t *dev,
+ unsigned long *addr,
+ dma_addr_t *bus_addr);
+extern int drm_ati_pcigart_cleanup(drm_device_t *dev,
+ unsigned long addr,
+ dma_addr_t bus_addr);
+
+ /* Proc support (drm_proc.h) */
+extern int drm_proc_init(drm_device_t *dev,
+ int minor,
+ struct proc_dir_entry *root,
+ struct proc_dir_entry **dev_root);
+extern int drm_proc_cleanup(int minor,
+ struct proc_dir_entry *root,
+ struct proc_dir_entry *dev_root);
+
+
+static __inline__ int drm_core_check_feature(struct drm_device *dev, int feature)
+{
+ return ((dev->driver_features & feature) ? 1 : 0);
+}
+
+#include "drm_core_memory.h"
+
+#ifndef DEBUG_MEMORY
+/** Wrapper around kmalloc() */
+static __inline__ void *drm_core_alloc(size_t size, int area)
+{
+ return kmalloc(size, GFP_KERNEL);
+}
+
+/** Wrapper around kfree() */
+static __inline__ void drm_core_free(void *pt, size_t size, int area)
+{
+ kfree(pt);
+}
+
+static __inline__ void drm_core_ioremap(struct drm_map *map, struct drm_device *dev)
+{
+ map->handle = drm_ioremap( map->offset, map->size, dev );
+}
+
+static __inline__ void drm_core_ioremap_nocache(struct drm_map *map, struct drm_device *dev)
+{
+ map->handle = drm_ioremap_nocache(map->offset, map->size, dev);
+}
+
+static __inline__ void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev)
+{
+ if ( map->handle && map->size )
+ drm_ioremapfree( map->handle, map->size, dev );
+}
+
+static __inline__ void drm_core_free_pages(unsigned long address, int order, int area)
+{
+ drm_memory_free_pages(address, order, area);
+}
+
+static __inline__ void *drm_core_realloc(void *oldpt, size_t oldsize, size_t size, int area)
+{
+ return drm_memory_realloc(oldpt, oldsize, size, area);
+}
+
+static __inline__ unsigned long drm_core_alloc_pages(int order, int area)
+{
+ return drm_memory_alloc_pages(order, area);
+}
+
+static __inline__ void drm_core_mem_init(void)
+{
+ drm_memory_mem_init();
+}
+
+#else
+static __inline__ void *drm_core_alloc(size_t size, int area)
+{
+ return drm_memory_debug_alloc(size, area);
+}
+static __inline__ void drm_core_free(void *pt, size_t size, int area)
+{
+ drm_memory_debug_free(pt, size, area);
+}
+#endif
+
+
+static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, unsigned long offset)
+{
+ struct list_head *_list;
+ list_for_each( _list, &dev->maplist->head ) {
+ drm_map_list_t *_entry = list_entry( _list, drm_map_list_t, head );
+ if ( _entry->map &&
+ _entry->map->offset == offset ) {
+ return _entry->map;
+ }
+ }
+ return NULL;
+}
+
+static __inline__ void drm_core_dropmap(struct drm_map *map)
+{
+}
+
+extern int drm_core_dma_setup( drm_device_t *dev );
+extern void drm_core_dma_takedown(drm_device_t *dev);
+extern void drm_core_free_buffer(drm_device_t *dev, drm_buf_t *buf);
+extern void drm_core_reclaim_buffers( struct file *filp );
+
+
+
+#endif
diff --git a/linux/drm_core_memory.h b/linux/drm_core_memory.h
new file mode 100644
index 00000000..640de3d8
--- /dev/null
+++ b/linux/drm_core_memory.h
@@ -0,0 +1,147 @@
+#ifndef DRM_CORE_MEMORY_H
+#define DRM_CORE_MEMORY_H
+
+#if __OS_HAS_AGP && defined(VMAP_4_ARGS)
+
+#ifdef HAVE_PAGE_AGP
+#include <asm/agp.h>
+#else
+#ifdef __powerpc__
+# define PAGE_AGP __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE)
+#else
+# define PAGE_AGP PAGE_KERNEL
+#endif
+#endif
+
+void drm_memory_free_pages(unsigned long address, int order, int area);
+void *drm_memory_realloc(void *oldpt, size_t oldsize, size_t size, int area);
+unsigned long drm_memory_alloc_pages(int order, int area);
+void drm_memory_mem_init(void);
+/*
+ * Find the drm_map that covers the range [offset, offset+size).
+ */
+static inline drm_map_t *
+drm_lookup_map (unsigned long offset, unsigned long size, drm_device_t *dev)
+{
+ struct list_head *list;
+ drm_map_list_t *r_list;
+ drm_map_t *map;
+
+ list_for_each(list, &dev->maplist->head) {
+ r_list = (drm_map_list_t *) list;
+ map = r_list->map;
+ if (!map)
+ continue;
+ if (map->offset <= offset && (offset + size) <= (map->offset + map->size))
+ return map;
+ }
+ return NULL;
+}
+
+static inline void *
+agp_remap (unsigned long offset, unsigned long size, drm_device_t *dev)
+{
+ unsigned long *phys_addr_map, i, num_pages = PAGE_ALIGN(size) / PAGE_SIZE;
+ struct drm_agp_mem *agpmem;
+ struct page **page_map;
+ void *addr;
+
+ size = PAGE_ALIGN(size);
+
+#ifdef __alpha__
+ offset -= dev->hose->mem_space->start;
+#endif
+
+ for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next)
+ if (agpmem->bound <= offset
+ && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >= (offset + size))
+ break;
+ if (!agpmem)
+ return NULL;
+
+ /*
+ * OK, we're mapping AGP space on a chipset/platform on which memory accesses by
+ * the CPU do not get remapped by the GART. We fix this by using the kernel's
+ * page-table instead (that's probably faster anyhow...).
+ */
+ /* note: use vmalloc() because num_pages could be large... */
+ page_map = vmalloc(num_pages * sizeof(struct page *));
+ if (!page_map)
+ return NULL;
+
+ phys_addr_map = agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE;
+ for (i = 0; i < num_pages; ++i)
+ page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT);
+ addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP);
+ vfree(page_map);
+
+ return addr;
+}
+
+static inline unsigned long
+drm_follow_page (void *vaddr)
+{
+ pgd_t *pgd = pgd_offset_k((unsigned long) vaddr);
+ pmd_t *pmd = pmd_offset(pgd, (unsigned long) vaddr);
+ pte_t *ptep = pte_offset_kernel(pmd, (unsigned long) vaddr);
+ return pte_pfn(*ptep) << PAGE_SHIFT;
+}
+
+#endif /* __OS_HAS_AGP && defined(VMAP_4_ARGS) */
+
+static inline void *drm_ioremap(unsigned long offset, unsigned long size, drm_device_t *dev)
+{
+#if __OS_HAS_AGP && defined(VMAP_4_ARGS)
+ if ( drm_core_check_feature(dev, DRIVER_USE_AGP) && dev->agp && dev->agp->cant_use_aperture) {
+ drm_map_t *map = drm_lookup_map(offset, size, dev);
+
+ if (map && map->type == _DRM_AGP)
+ return agp_remap(offset, size, dev);
+ }
+#endif
+
+ return ioremap(offset, size);
+}
+
+static inline void *drm_ioremap_nocache(unsigned long offset, unsigned long size,
+ drm_device_t *dev)
+{
+#if __OS_HAS_AGP&& defined(VMAP_4_ARGS)
+ if ( drm_core_check_feature(dev, DRIVER_USE_AGP) && dev->agp && dev->agp->cant_use_aperture) {
+ drm_map_t *map = drm_lookup_map(offset, size, dev);
+
+ if (map && map->type == _DRM_AGP)
+ return agp_remap(offset, size, dev);
+ }
+#endif
+
+ return ioremap_nocache(offset, size);
+}
+
+static inline void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev)
+{
+#if __OS_HAS_AGP && defined(VMAP_4_ARGS)
+ /*
+ * This is a bit ugly. It would be much cleaner if the DRM API would use separate
+ * routines for handling mappings in the AGP space. Hopefully this can be done in
+ * a future revision of the interface...
+ */
+ if (drm_core_check_feature(dev, DRIVER_USE_AGP) && dev->agp && dev->agp->cant_use_aperture
+ && ((unsigned long) pt >= VMALLOC_START && (unsigned long) pt < VMALLOC_END))
+ {
+ unsigned long offset;
+ drm_map_t *map;
+
+ offset = drm_follow_page(pt) | ((unsigned long) pt & ~PAGE_MASK);
+ map = drm_lookup_map(offset, size, dev);
+ if (map && map->type == _DRM_AGP) {
+ vunmap(pt);
+ return;
+ }
+ }
+#endif
+
+ iounmap(pt);
+}
+
+#endif
diff --git a/linux/drm_dma.c b/linux/drm_dma.c
new file mode 100644
index 00000000..59a9b281
--- /dev/null
+++ b/linux/drm_dma.c
@@ -0,0 +1,183 @@
+/**
+ * \file drm_dma.h
+ * DMA IOCTL and function support
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
+ *
+ * Copyright 1999, 2000 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.
+ */
+
+#include "drm_headers.h"
+
+
+/**
+ * Initialize the DMA data.
+ *
+ * \param dev DRM device.
+ * \return zero on success or a negative value on failure.
+ *
+ * Allocate and initialize a drm_device_dma structure.
+ */
+int drm_core_dma_setup( drm_device_t *dev )
+{
+ int i;
+
+ dev->dma = drm_core_alloc( sizeof(*dev->dma), DRM_MEM_DRIVER );
+ if ( !dev->dma )
+ return -ENOMEM;
+
+ memset( dev->dma, 0, sizeof(*dev->dma) );
+
+ for ( i = 0 ; i <= DRM_MAX_ORDER ; i++ )
+ memset(&dev->dma->bufs[i], 0, sizeof(dev->dma->bufs[0]));
+
+ return 0;
+}
+
+/**
+ * Cleanup the DMA resources.
+ *
+ * \param dev DRM device.
+ *
+ * Free all pages associated with DMA buffers, the buffers and pages lists, and
+ * finally the the drm_device::dma structure itself.
+ */
+void drm_core_dma_takedown(drm_device_t *dev)
+{
+ drm_device_dma_t *dma = dev->dma;
+ int i, j;
+
+ if (!dma) return;
+
+ /* Clear dma buffers */
+ for (i = 0; i <= DRM_MAX_ORDER; i++) {
+ if (dma->bufs[i].seg_count) {
+ DRM_DEBUG("order %d: buf_count = %d,"
+ " seg_count = %d\n",
+ i,
+ dma->bufs[i].buf_count,
+ dma->bufs[i].seg_count);
+ for (j = 0; j < dma->bufs[i].seg_count; j++) {
+ if (dma->bufs[i].seglist[j]) {
+ drm_core_free_pages(dma->bufs[i].seglist[j],
+ dma->bufs[i].page_order,
+ DRM_MEM_DMA);
+ }
+ }
+ drm_core_free(dma->bufs[i].seglist,
+ dma->bufs[i].seg_count
+ * sizeof(*dma->bufs[0].seglist),
+ DRM_MEM_SEGS);
+ }
+ if (dma->bufs[i].buf_count) {
+ for (j = 0; j < dma->bufs[i].buf_count; j++) {
+ if (dma->bufs[i].buflist[j].dev_private) {
+ drm_core_free(dma->bufs[i].buflist[j].dev_private,
+ dma->bufs[i].buflist[j].dev_priv_size,
+ DRM_MEM_BUFS);
+ }
+ }
+ drm_core_free(dma->bufs[i].buflist,
+ dma->bufs[i].buf_count *
+ sizeof(*dma->bufs[0].buflist),
+ DRM_MEM_BUFS);
+
+ }
+ }
+
+ if (dma->buflist) {
+ drm_core_free(dma->buflist,
+ dma->buf_count * sizeof(*dma->buflist),
+ DRM_MEM_BUFS);
+ }
+
+ if (dma->pagelist) {
+ drm_core_free(dma->pagelist,
+ dma->page_count * sizeof(*dma->pagelist),
+ DRM_MEM_PAGES);
+ }
+ drm_core_free(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER);
+ dev->dma = NULL;
+}
+
+
+/**
+ * Free a buffer.
+ *
+ * \param dev DRM device.
+ * \param buf buffer to free.
+ *
+ * Resets the fields of \p buf.
+ */
+void drm_core_free_buffer(drm_device_t *dev, drm_buf_t *buf)
+{
+ if (!buf) return;
+
+ buf->waiting = 0;
+ buf->pending = 0;
+ buf->filp = NULL;
+ buf->used = 0;
+
+ if ( drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && waitqueue_active(&buf->dma_wait)) {
+ wake_up_interruptible(&buf->dma_wait);
+ }
+}
+
+/**
+ * Reclaim the buffers.
+ *
+ * \param filp file pointer.
+ *
+ * Frees each buffer associated with \p filp not already on the hardware.
+ */
+void drm_core_reclaim_buffers( struct file *filp )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_device_dma_t *dma = dev->dma;
+ int i;
+
+ if (!dma) return;
+ for (i = 0; i < dma->buf_count; i++) {
+ if (dma->buflist[i]->filp == filp) {
+ switch (dma->buflist[i]->list) {
+ case DRM_LIST_NONE:
+ drm_core_free_buffer(dev, dma->buflist[i]);
+ break;
+ case DRM_LIST_WAIT:
+ dma->buflist[i]->list = DRM_LIST_RECLAIM;
+ break;
+ default:
+ /* Buffer already on hardware. */
+ break;
+ }
+ }
+ }
+}
+
diff --git a/linux/drm_drv.h b/linux/drm_drv.h
index 8f42e357..e8cf159b 100644
--- a/linux/drm_drv.h
+++ b/linux/drm_drv.h
@@ -126,8 +126,8 @@ drm_ioctl_desc_t DRM(ioctls)[] = {
[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { DRM(noop), 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { DRM(authmagic), 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { DRM(addmap), 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = { DRM(rmmap), 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_core_addmap, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = { drm_core_rmmap, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { DRM(setsareactx), 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { DRM(getsareactx), 1, 0 },
@@ -148,24 +148,24 @@ drm_ioctl_desc_t DRM(ioctls)[] = {
[DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { DRM(noop), 1, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { DRM(addbufs), 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { DRM(markbufs), 1, 1 },
- [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { DRM(infobufs), 1, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { DRM(mapbufs), 1, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { DRM(freebufs), 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { drm_core_addbufs, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_core_markbufs, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_core_infobufs, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { drm_core_mapbufs, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_core_freebufs, 1, 0 },
/* The DRM_IOCTL_DMA ioctl should be defined by the driver. */
[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { DRM(control), 1, 1 },
#if __OS_HAS_AGP
- [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 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_memory_agp_acquire, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_memory_agp_release, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_memory_agp_enable, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_memory_agp_info, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_memory_agp_alloc, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_memory_agp_free, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_memory_agp_bind, 1, 1 },
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_memory_agp_unbind, 1, 1 },
#endif
[DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = { DRM(sg_alloc), 1, 1 },
@@ -201,7 +201,7 @@ static int DRM(setup)( drm_device_t *dev )
if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
{
- i = DRM(dma_setup)( dev );
+ i = drm_core_dma_setup( dev );
if ( i < 0 )
return i;
}
@@ -249,7 +249,7 @@ static int DRM(setup)( drm_device_t *dev )
dev->magiclist[i].tail = NULL;
}
- dev->ctxlist = DRM(alloc)(sizeof(*dev->ctxlist),
+ dev->ctxlist = drm_core_alloc(sizeof(*dev->ctxlist),
DRM_MEM_CTXLIST);
if(dev->ctxlist == NULL) return -ENOMEM;
memset(dev->ctxlist, 0, sizeof(*dev->ctxlist));
@@ -327,13 +327,13 @@ static int DRM(takedown)( drm_device_t *dev )
del_timer( &dev->timer );
if ( dev->devname ) {
- DRM(free)( dev->devname, strlen( dev->devname ) + 1,
+ drm_core_free( dev->devname, strlen( dev->devname ) + 1,
DRM_MEM_DRIVER );
dev->devname = NULL;
}
if ( dev->unique ) {
- DRM(free)( dev->unique, strlen( dev->unique ) + 1,
+ drm_core_free( dev->unique, strlen( dev->unique ) + 1,
DRM_MEM_DRIVER );
dev->unique = NULL;
dev->unique_len = 0;
@@ -342,7 +342,7 @@ static int DRM(takedown)( drm_device_t *dev )
for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
for ( pt = dev->magiclist[i].head ; pt ; pt = next ) {
next = pt->next;
- DRM(free)( pt, sizeof(*pt), DRM_MEM_MAGIC );
+ drm_core_free( pt, sizeof(*pt), DRM_MEM_MAGIC );
}
dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
}
@@ -357,13 +357,13 @@ static int DRM(takedown)( drm_device_t *dev )
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 );
+ if ( entry->bound ) drm_memory_unbind_agp( entry->memory );
+ drm_memory_free_agp( entry->memory, entry->pages );
+ drm_core_free( entry, sizeof(*entry), DRM_MEM_AGPLISTS );
}
dev->agp->memory = NULL;
- if ( dev->agp->acquired ) DRM(agp_do_release)();
+ if ( dev->agp->acquired ) drm_memory_agp_do_release();
dev->agp->acquired = 0;
dev->agp->enabled = 0;
@@ -374,7 +374,7 @@ static int DRM(takedown)( drm_device_t *dev )
if ( dev->vmalist ) {
for ( vma = dev->vmalist ; vma ; vma = vma_next ) {
vma_next = vma->next;
- DRM(free)( vma, sizeof(*vma), DRM_MEM_VMAS );
+ drm_core_free( vma, sizeof(*vma), DRM_MEM_VMAS );
}
dev->vmalist = NULL;
}
@@ -406,10 +406,10 @@ static int DRM(takedown)( drm_device_t *dev )
}
break;
}
- DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
+ drm_core_free(map, sizeof(*map), DRM_MEM_MAPS);
}
list_del( list );
- DRM(free)(r_list, sizeof(*r_list), DRM_MEM_MAPS);
+ drm_core_free(r_list, sizeof(*r_list), DRM_MEM_MAPS);
}
}
@@ -418,13 +418,13 @@ static int DRM(takedown)( drm_device_t *dev )
for ( i = 0 ; i < dev->queue_count ; i++ ) {
if ( dev->queuelist[i] ) {
- DRM(free)( dev->queuelist[i],
+ drm_core_free( dev->queuelist[i],
sizeof(*dev->queuelist[0]),
DRM_MEM_QUEUES );
dev->queuelist[i] = NULL;
}
}
- DRM(free)( dev->queuelist,
+ drm_core_free( dev->queuelist,
dev->queue_slots * sizeof(*dev->queuelist),
DRM_MEM_QUEUES );
dev->queuelist = NULL;
@@ -432,7 +432,7 @@ static int DRM(takedown)( drm_device_t *dev )
dev->queue_count = 0;
if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
- DRM(dma_takedown)( dev );
+ drm_core_dma_takedown( dev );
if ( dev->lock.hw_lock ) {
dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */
@@ -447,7 +447,7 @@ static int DRM(takedown)( drm_device_t *dev )
static void DRM(init_fn_table)(struct drm_device *dev)
{
- dev->fn_tbl.reclaim_buffers = DRM(core_reclaim_buffers);
+ dev->fn_tbl.reclaim_buffers = drm_core_reclaim_buffers;
dev->fn_tbl.get_map_ofs = DRM(core_get_map_ofs);
dev->fn_tbl.get_reg_ofs = DRM(core_get_reg_ofs);
}
@@ -493,7 +493,7 @@ static int drm_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->pci_func = PCI_FUNC(pdev->devfn);
dev->irq = pdev->irq;
- dev->maplist = DRM(alloc)(sizeof(*dev->maplist), DRM_MEM_MAPS);
+ dev->maplist = drm_core_alloc(sizeof(*dev->maplist), DRM_MEM_MAPS);
if(dev->maplist == NULL) return -ENOMEM;
memset(dev->maplist, 0, sizeof(*dev->maplist));
INIT_LIST_HEAD(&dev->maplist->head);
@@ -511,7 +511,7 @@ static int drm_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
#if __OS_HAS_AGP
if (drm_core_check_feature(dev, DRIVER_USE_AGP)) {
- dev->agp = DRM(agp_init)();
+ dev->agp = drm_memory_agp_init();
if ( drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && dev->agp == NULL ) {
DRM_ERROR( "Cannot initialize the agpgart module.\n" );
retcode = -EINVAL;
@@ -609,7 +609,7 @@ static int __init drm_init( void )
DRM(parse_options)( drm_opts );
#endif
- DRM(mem_init)();
+ drm_core_mem_init();
for (i=0; (DRM(pciidlist)[i].vendor != 0) && !DRM(fb_loaded); i++) {
pid = &DRM(pciidlist[i]);
@@ -676,7 +676,7 @@ static void __exit drm_cleanup( drm_device_t *dev )
if ( ( map = r_list->map ) ) {
switch ( map->type ) {
case _DRM_REGISTERS:
- DRM(ioremapfree)( map->handle, map->size, dev );
+ drm_core_ioremapfree( map, dev );
break;
case _DRM_FRAME_BUFFER:
@@ -699,12 +699,12 @@ static void __exit drm_cleanup( drm_device_t *dev )
DRM_DEBUG("Extra maplist item\n");
break;
}
- DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
+ drm_core_free(map, sizeof(*map), DRM_MEM_MAPS);
}
list_del( list );
- DRM(free)(r_list, sizeof(*r_list), DRM_MEM_MAPS);
+ drm_core_free(r_list, sizeof(*r_list), DRM_MEM_MAPS);
}
- DRM(free)(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
+ drm_core_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
dev->maplist = NULL;
}
if (DRM(fb_loaded)==0)
@@ -730,8 +730,8 @@ static void __exit drm_cleanup( drm_device_t *dev )
}
#endif
if ( drm_core_check_feature(dev, DRIVER_USE_AGP) && dev->agp ) {
- DRM(agp_uninit)();
- DRM(free)( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS );
+ drm_memory_agp_uninit();
+ drm_core_free( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS );
dev->agp = NULL;
}
#endif
@@ -956,7 +956,7 @@ int DRM(release)( struct inode *inode, struct file *filp )
DRM(ctxbitmap_free)( dev, pos->handle );
list_del( &pos->head );
- DRM(free)( pos, sizeof(*pos), DRM_MEM_CTXLIST );
+ drm_core_free( pos, sizeof(*pos), DRM_MEM_CTXLIST );
--dev->ctx_count;
}
}
@@ -985,7 +985,7 @@ int DRM(release)( struct inode *inode, struct file *filp )
if (dev->fn_tbl.free_filp_private)
dev->fn_tbl.free_filp_private( dev, priv );
- DRM(free)( priv, sizeof(*priv), DRM_MEM_FILES );
+ drm_core_free( priv, sizeof(*priv), DRM_MEM_FILES );
/* ========================================================
* End inline drm_release
@@ -1129,29 +1129,28 @@ int DRM(lock)( struct inode *inode, struct file *filp,
current->state = TASK_RUNNING;
remove_wait_queue( &dev->lock.lock_queue, &entry );
- if ( !ret ) {
- sigemptyset( &dev->sigmask );
- sigaddset( &dev->sigmask, SIGSTOP );
- sigaddset( &dev->sigmask, SIGTSTP );
- sigaddset( &dev->sigmask, SIGTTIN );
- sigaddset( &dev->sigmask, SIGTTOU );
- dev->sigdata.context = lock.context;
- dev->sigdata.lock = dev->lock.hw_lock;
- block_all_signals( DRM(notifier),
- &dev->sigdata, &dev->sigmask );
-
- if (dev->fn_tbl.dma_ready && (lock.flags & _DRM_LOCK_READY))
- dev->fn_tbl.dma_ready(dev);
-
- if ( dev->fn_tbl.dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT ))
- return dev->fn_tbl.dma_quiescent(dev);
-
-
- if ( dev->fn_tbl.kernel_context_switch && dev->last_context != lock.context ) {
- dev->fn_tbl.kernel_context_switch(dev, dev->last_context,
- lock.context);
- }
- }
+ sigemptyset( &dev->sigmask );
+ sigaddset( &dev->sigmask, SIGSTOP );
+ sigaddset( &dev->sigmask, SIGTSTP );
+ sigaddset( &dev->sigmask, SIGTTIN );
+ sigaddset( &dev->sigmask, SIGTTOU );
+ dev->sigdata.context = lock.context;
+ dev->sigdata.lock = dev->lock.hw_lock;
+ block_all_signals( DRM(notifier),
+ &dev->sigdata, &dev->sigmask );
+
+ if (dev->fn_tbl.dma_ready && (lock.flags & _DRM_LOCK_READY))
+ dev->fn_tbl.dma_ready(dev);
+
+ if ( dev->fn_tbl.dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT ))
+ return dev->fn_tbl.dma_quiescent(dev);
+
+
+ if ( dev->fn_tbl.kernel_context_switch && dev->last_context != lock.context ) {
+ dev->fn_tbl.kernel_context_switch(dev, dev->last_context,
+ lock.context);
+ }
+
DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" );
diff --git a/linux/drm_fops.h b/linux/drm_fops.h
index 21935b7a..32c6177c 100644
--- a/linux/drm_fops.h
+++ b/linux/drm_fops.h
@@ -60,7 +60,7 @@ int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
- priv = DRM(alloc)(sizeof(*priv), DRM_MEM_FILES);
+ priv = drm_core_alloc(sizeof(*priv), DRM_MEM_FILES);
if(!priv) return -ENOMEM;
memset(priv, 0, sizeof(*priv));
@@ -111,7 +111,7 @@ int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
return 0;
out_free:
- DRM(free)(priv, sizeof(*priv), DRM_MEM_FILES);
+ drm_core_free(priv, sizeof(*priv), DRM_MEM_FILES);
return ret;
}
diff --git a/linux/drm_headers.h b/linux/drm_headers.h
new file mode 100644
index 00000000..13d2b41e
--- /dev/null
+++ b/linux/drm_headers.h
@@ -0,0 +1,52 @@
+
+#ifdef __alpha__
+/* add include of current.h so that "current" is defined
+ * before static inline funcs in wait.h. Doing this so we
+ * can build the DRM (part of PI DRI). 4/21/2000 S + B */
+#include <asm/current.h>
+#endif /* __alpha__ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/file.h>
+#include <linux/pci.h>
+#include <linux/version.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h> /* For (un)lock_kernel */
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#if defined(__alpha__) || defined(__powerpc__)
+#include <asm/pgtable.h> /* For pte_wrprotect */
+#endif
+#include <asm/io.h>
+#include <asm/mman.h>
+#include <asm/uaccess.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
+#include <linux/types.h>
+#include <linux/agp_backend.h>
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,41)
+#define HAS_WORKQUEUE 0
+#else
+#define HAS_WORKQUEUE 1
+#endif
+#if !HAS_WORKQUEUE
+#include <linux/tqueue.h>
+#else
+#include <linux/workqueue.h>
+#endif
+#include <linux/poll.h>
+#include <asm/pgalloc.h>
+#include "drm.h"
+
+#include "drm_os_linux.h"
+
+#include "drm_core.h"
+#include "drm_core_memory.h"
diff --git a/linux/drm_ioctl.h b/linux/drm_ioctl.h
index c3725668..4e5055ef 100644
--- a/linux/drm_ioctl.h
+++ b/linux/drm_ioctl.h
@@ -98,14 +98,14 @@ int DRM(setunique)(struct inode *inode, struct file *filp,
if (!u.unique_len || u.unique_len > 1024) return -EINVAL;
dev->unique_len = u.unique_len;
- dev->unique = DRM(alloc)(u.unique_len + 1, DRM_MEM_DRIVER);
+ dev->unique = drm_core_alloc(u.unique_len + 1, DRM_MEM_DRIVER);
if(!dev->unique) return -ENOMEM;
if (copy_from_user(dev->unique, u.unique, dev->unique_len))
return -EFAULT;
dev->unique[dev->unique_len] = '\0';
- dev->devname = DRM(alloc)(strlen(dev->name) + strlen(dev->unique) + 2,
+ dev->devname = drm_core_alloc(strlen(dev->name) + strlen(dev->unique) + 2,
DRM_MEM_DRIVER);
if (!dev->devname)
return -ENOMEM;
@@ -137,14 +137,14 @@ DRM(set_busid)(drm_device_t *dev)
return EBUSY;
dev->unique_len = 20;
- dev->unique = DRM(alloc)(dev->unique_len + 1, DRM_MEM_DRIVER);
+ dev->unique = drm_core_alloc(dev->unique_len + 1, DRM_MEM_DRIVER);
if (dev->unique == NULL)
return ENOMEM;
snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d",
dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
- dev->devname = DRM(alloc)(strlen(dev->name) + dev->unique_len + 2,
+ dev->devname = drm_core_alloc(strlen(dev->name) + dev->unique_len + 2,
DRM_MEM_DRIVER);
if (dev->devname == NULL)
return ENOMEM;
diff --git a/linux/drm_irq.h b/linux/drm_irq.h
index a1622c0e..a88edf98 100644
--- a/linux/drm_irq.h
+++ b/linux/drm_irq.h
@@ -304,7 +304,7 @@ int DRM(wait_vblank)( DRM_IOCTL_ARGS )
spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
- if ( !( vbl_sig = DRM(alloc)( sizeof( drm_vbl_sig_t ), DRM_MEM_DRIVER ) ) ) {
+ if ( !( vbl_sig = drm_core_alloc( sizeof( drm_vbl_sig_t ), DRM_MEM_DRIVER ) ) ) {
return -ENOMEM;
}
@@ -360,7 +360,7 @@ void DRM(vbl_send_signals)( drm_device_t *dev )
list_del( list );
- DRM(free)( vbl_sig, sizeof(*vbl_sig), DRM_MEM_DRIVER );
+ drm_core_free( vbl_sig, sizeof(*vbl_sig), DRM_MEM_DRIVER );
dev->vbl_pending--;
}
diff --git a/linux/drm_memory.c b/linux/drm_memory.c
new file mode 100644
index 00000000..76c14865
--- /dev/null
+++ b/linux/drm_memory.c
@@ -0,0 +1,203 @@
+/**
+ * \file drm_memory.h
+ * Memory management wrappers for DRM
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Thu Feb 4 14:00:34 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drm_headers.h"
+
+/**
+ * Cut down version of drm_memory_debug.h, which used to be called
+ * drm_memory.h.
+ */
+
+/* Need the 4-argument version of vmap(). */
+#if __OS_HAS_AGP && defined(VMAP_4_ARGS)
+
+#include <linux/vmalloc.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#ifndef pte_offset_kernel
+# define pte_offset_kernel(dir, address) pte_offset(dir, address)
+#endif
+#ifndef pte_pfn
+# define pte_pfn(pte) (pte_page(pte) - mem_map)
+#endif
+#ifndef pfn_to_page
+# define pfn_to_page(pfn) (mem_map + (pfn))
+#endif
+#endif
+
+
+
+
+#ifdef DEBUG_MEMORY
+#include "drm_memory_debug.h"
+#else
+
+/** No-op. */
+void drm_memory_mem_init(void)
+{
+}
+
+/**
+ * Called when "/proc/dri/%dev%/mem" is read.
+ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param len requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ *
+ * No-op.
+ */
+int drm_memory_mem_info(char *buf, char **start, off_t offset,
+ int len, int *eof, void *data)
+{
+ return 0;
+}
+
+/** Wrapper around kmalloc() */
+void *drm_memory_calloc(size_t nmemb, size_t size, int area)
+{
+ void *addr;
+
+ addr = kmalloc(size * nmemb, GFP_KERNEL);
+ if (addr != NULL)
+ memset((void *)addr, 0, size * nmemb);
+
+ return addr;
+}
+
+/** Wrapper around kmalloc() and kfree() */
+void *drm_memory_realloc(void *oldpt, size_t oldsize, size_t size, int area)
+{
+ void *pt;
+
+ if (!(pt = kmalloc(size, GFP_KERNEL))) return NULL;
+ if (oldpt && oldsize) {
+ memcpy(pt, oldpt, oldsize);
+ kfree(oldpt);
+ }
+ return pt;
+}
+
+/**
+ * Allocate pages.
+ *
+ * \param order size order.
+ * \param area memory area. (Not used.)
+ * \return page address on success, or zero on failure.
+ *
+ * Allocate and reserve free pages.
+ */
+unsigned long drm_memory_alloc_pages(int order, int area)
+{
+ unsigned long address;
+ unsigned long bytes = PAGE_SIZE << order;
+ unsigned long addr;
+ unsigned int sz;
+
+ address = __get_free_pages(GFP_KERNEL, order);
+ if (!address)
+ return 0;
+
+ /* Zero */
+ memset((void *)address, 0, bytes);
+
+ /* Reserve */
+ for (addr = address, sz = bytes;
+ sz > 0;
+ addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+ SetPageReserved(virt_to_page(addr));
+ }
+
+ return address;
+}
+
+/**
+ * Free pages.
+ *
+ * \param address address of the pages to free.
+ * \param order size order.
+ * \param area memory area. (Not used.)
+ *
+ * Unreserve and free pages allocated by alloc_pages().
+ */
+void drm_memory_free_pages(unsigned long address, int order, int area)
+{
+ unsigned long bytes = PAGE_SIZE << order;
+ unsigned long addr;
+ unsigned int sz;
+
+ if (!address)
+ return;
+
+ /* Unreserve */
+ for (addr = address, sz = bytes;
+ sz > 0;
+ addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+ ClearPageReserved(virt_to_page(addr));
+ }
+
+ free_pages(address, order);
+}
+
+#if __OS_HAS_AGP
+/** Wrapper around agp_allocate_memory() */
+DRM_AGP_MEM *drm_memory_alloc_agp(int pages, u32 type)
+{
+ return drm_memory_agp_allocate_memory (pages, type);
+}
+
+/** Wrapper around agp_free_memory() */
+int drm_memory_free_agp(DRM_AGP_MEM *handle, int pages)
+{
+ return drm_memory_agp_free_memory(handle) ? 0 : -EINVAL;
+}
+
+/** Wrapper around agp_bind_memory() */
+int drm_memory_bind_agp(DRM_AGP_MEM *handle, unsigned int start)
+{
+ return drm_memory_agp_bind_memory(handle, start);
+}
+
+/** Wrapper around agp_unbind_memory() */
+int drm_memory_unbind_agp(DRM_AGP_MEM *handle)
+{
+ return drm_memory_agp_unbind_memory(handle);
+}
+#endif /* agp */
+#endif /* debug_memory */
+#endif
diff --git a/linux/drm_memory_debug.c b/linux/drm_memory_debug.c
new file mode 100644
index 00000000..a15a304d
--- /dev/null
+++ b/linux/drm_memory_debug.c
@@ -0,0 +1,463 @@
+/**
+ * \file drm_memory.h
+ * Memory management wrappers for DRM.
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drm_headers.h"
+
+#define DRM_MEM_ERROR(area, fmt, arg...) \
+ printk(KERN_ERR "[" DRM_NAME ":%s:%s] *ERROR* " fmt , __FUNCTION__, \
+ drm_memory_debug_mem_stats[area].name , ##arg)
+
+
+typedef struct drm_mem_stats {
+ const char *name;
+ int succeed_count;
+ int free_count;
+ int fail_count;
+ unsigned long bytes_allocated;
+ unsigned long bytes_freed;
+} drm_mem_stats_t;
+
+static spinlock_t drm_memory_debug_mem_lock = SPIN_LOCK_UNLOCKED;
+static unsigned long drm_memory_debug_ram_available = 0; /* In pages */
+static unsigned long drm_memory_debug_ram_used = 0;
+static drm_mem_stats_t drm_memory_debug_mem_stats[] = {
+ [DRM_MEM_DMA] = { "dmabufs" },
+ [DRM_MEM_SAREA] = { "sareas" },
+ [DRM_MEM_DRIVER] = { "driver" },
+ [DRM_MEM_MAGIC] = { "magic" },
+ [DRM_MEM_IOCTLS] = { "ioctltab" },
+ [DRM_MEM_MAPS] = { "maplist" },
+ [DRM_MEM_VMAS] = { "vmalist" },
+ [DRM_MEM_BUFS] = { "buflist" },
+ [DRM_MEM_SEGS] = { "seglist" },
+ [DRM_MEM_PAGES] = { "pagelist" },
+ [DRM_MEM_FILES] = { "files" },
+ [DRM_MEM_QUEUES] = { "queues" },
+ [DRM_MEM_CMDS] = { "commands" },
+ [DRM_MEM_MAPPINGS] = { "mappings" },
+ [DRM_MEM_BUFLISTS] = { "buflists" },
+ [DRM_MEM_AGPLISTS] = { "agplist" },
+ [DRM_MEM_SGLISTS] = { "sglist" },
+ [DRM_MEM_TOTALAGP] = { "totalagp" },
+ [DRM_MEM_BOUNDAGP] = { "boundagp" },
+ [DRM_MEM_CTXBITMAP] = { "ctxbitmap"},
+ [DRM_MEM_CTXLIST] = { "ctxlist" },
+ [DRM_MEM_STUB] = { "stub" },
+ { NULL, 0, } /* Last entry must be null */
+};
+
+void drm_memory_debug_mem_init(void)
+{
+ drm_mem_stats_t *mem;
+ struct sysinfo si;
+
+ for (mem = drm_memory_debug_mem_stats; mem->name; ++mem) {
+ mem->succeed_count = 0;
+ mem->free_count = 0;
+ mem->fail_count = 0;
+ mem->bytes_allocated = 0;
+ mem->bytes_freed = 0;
+ }
+
+ si_meminfo(&si);
+ drm_memory_debug_ram_available = si.totalram;
+ drm_memory_debug_ram_used = 0;
+}
+
+/* drm_mem_info is called whenever a process reads /dev/drm/mem. */
+
+static int drm_memory_debug__mem_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data)
+{
+ drm_mem_stats_t *pt;
+ int len = 0;
+
+ if (offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ *eof = 0;
+ *start = &buf[offset];
+
+ DRM_PROC_PRINT(" total counts "
+ " | outstanding \n");
+ DRM_PROC_PRINT("type alloc freed fail bytes freed"
+ " | allocs bytes\n\n");
+ DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB |\n",
+ "system", 0, 0, 0,
+ drm_memory_debug_ram_available << (PAGE_SHIFT - 10));
+ DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB |\n",
+ "locked", 0, 0, 0, drm_memory_debug_ram_used >> 10);
+ DRM_PROC_PRINT("\n");
+ for (pt = drm_memory_debug_mem_stats; pt->name; pt++) {
+ DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ld\n",
+ pt->name,
+ pt->succeed_count,
+ pt->free_count,
+ pt->fail_count,
+ pt->bytes_allocated,
+ pt->bytes_freed,
+ pt->succeed_count - pt->free_count,
+ (long)pt->bytes_allocated
+ - (long)pt->bytes_freed);
+ }
+
+ if (len > request + offset) return request;
+ *eof = 1;
+ return len - offset;
+}
+
+int drm_memory_debug_mem_info(char *buf, char **start, off_t offset,
+ int len, int *eof, void *data)
+{
+ int ret;
+
+ spin_lock(&drm_memory_debug_mem_lock);
+ ret = drm_memory_debug__mem_info(buf, start, offset, len, eof, data);
+ spin_unlock(&drm_memory_debug_mem_lock);
+ return ret;
+}
+
+void *drm_memory_debug_alloc(size_t size, int area)
+{
+ void *pt;
+
+ if (!size) {
+ DRM_MEM_ERROR(area, "Allocating 0 bytes\n");
+ return NULL;
+ }
+
+ if (!(pt = kmalloc(size, GFP_KERNEL))) {
+ spin_lock(&drm_memory_debug_mem_lock);
+ ++drm_memory_debug_mem_stats[area].fail_count;
+ spin_unlock(&drm_memory_debug_mem_lock);
+ return NULL;
+ }
+ spin_lock(&drm_memory_debug_mem_lock);
+ ++drm_memory_debug_mem_stats[area].succeed_count;
+ drm_memory_debug_mem_stats[area].bytes_allocated += size;
+ spin_unlock(&drm_memory_debug_mem_lock);
+ return pt;
+}
+
+void *drm_memory_debug_calloc(size_t nmemb, size_t size, int area)
+{
+ void *addr;
+
+ addr = drm_memory_debug_alloc(nmemb * size, area);
+ if (addr != NULL)
+ memset((void *)addr, 0, size * nmemb);
+
+ return addr;
+}
+
+void *drm_memory_debug_realloc(void *oldpt, size_t oldsize, size_t size, int area)
+{
+ void *pt;
+
+ if (!(pt = drm_memory_debug_alloc(size, area))) return NULL;
+ if (oldpt && oldsize) {
+ memcpy(pt, oldpt, oldsize);
+ drm_memory_debug_free(oldpt, oldsize, area);
+ }
+ return pt;
+}
+
+void drm_memory_debug_free(void *pt, size_t size, int area)
+{
+ int alloc_count;
+ int free_count;
+
+ if (!pt) DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n");
+ else kfree(pt);
+ spin_lock(&drm_memory_debug_mem_lock);
+ drm_memory_debug_mem_stats[area].bytes_freed += size;
+ free_count = ++drm_memory_debug_mem_stats[area].free_count;
+ alloc_count = drm_memory_debug_mem_stats[area].succeed_count;
+ spin_unlock(&drm_memory_debug_mem_lock);
+ if (free_count > alloc_count) {
+ DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocs\n",
+ free_count, alloc_count);
+ }
+}
+
+unsigned long drm_debug_alloc_pages(int order, int area)
+{
+ unsigned long address;
+ unsigned long bytes = PAGE_SIZE << order;
+ unsigned long addr;
+ unsigned int sz;
+
+ spin_lock(&drm_memory_debug_mem_lock);
+ if ((drm_memory_debug_ram_used >> PAGE_SHIFT)
+ > (DRM_RAM_PERCENT * drm_memory_debug_ram_available) / 100) {
+ spin_unlock(&drm_memory_debug_mem_lock);
+ return 0;
+ }
+ spin_unlock(&drm_memory_debug_mem_lock);
+
+ address = __get_free_pages(GFP_KERNEL, order);
+ if (!address) {
+ spin_lock(&drm_memory_debug_mem_lock);
+ ++drm_memory_debug_mem_stats[area].fail_count;
+ spin_unlock(&drm_memory_debug_mem_lock);
+ return 0;
+ }
+ spin_lock(&drm_memory_debug_mem_lock);
+ ++drm_memory_debug_mem_stats[area].succeed_count;
+ drm_memory_debug_mem_stats[area].bytes_allocated += bytes;
+ drm_memory_debug_ram_used += bytes;
+ spin_unlock(&drm_memory_debug_mem_lock);
+
+
+ /* Zero outside the lock */
+ memset((void *)address, 0, bytes);
+
+ /* Reserve */
+ for (addr = address, sz = bytes;
+ sz > 0;
+ addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+ SetPageReserved(virt_to_page(addr));
+ }
+
+ return address;
+}
+
+void drm_memory_debug_free_pages(unsigned long address, int order, int area)
+{
+ unsigned long bytes = PAGE_SIZE << order;
+ int alloc_count;
+ int free_count;
+ unsigned long addr;
+ unsigned int sz;
+
+ if (!address) {
+ DRM_MEM_ERROR(area, "Attempt to free address 0\n");
+ } else {
+ /* Unreserve */
+ for (addr = address, sz = bytes;
+ sz > 0;
+ addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+ ClearPageReserved(virt_to_page(addr));
+ }
+ free_pages(address, order);
+ }
+
+ spin_lock(&drm_memory_debug_mem_lock);
+ free_count = ++drm_memory_debug_mem_stats[area].free_count;
+ alloc_count = drm_memory_debug_mem_stats[area].succeed_count;
+ drm_memory_debug_mem_stats[area].bytes_freed += bytes;
+ drm_memory_debug_ram_used -= bytes;
+ spin_unlock(&drm_memory_debug_mem_lock);
+ if (free_count > alloc_count) {
+ DRM_MEM_ERROR(area,
+ "Excess frees: %d frees, %d allocs\n",
+ free_count, alloc_count);
+ }
+}
+
+void *drm_memory_debug_ioremap(unsigned long offset, unsigned long size, drm_device_t *dev)
+{
+ void *pt;
+
+ if (!size) {
+ DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
+ "Mapping 0 bytes at 0x%08lx\n", offset);
+ return NULL;
+ }
+
+ if (!(pt = drm_ioremap(offset, size, dev))) {
+ spin_lock(&drm_memory_debug_mem_lock);
+ ++drm_memory_debug_mem_stats[DRM_MEM_MAPPINGS].fail_count;
+ spin_unlock(&drm_memory_debug_mem_lock);
+ return NULL;
+ }
+ spin_lock(&drm_memory_debug_mem_lock);
+ ++drm_memory_debug_mem_stats[DRM_MEM_MAPPINGS].succeed_count;
+ drm_memory_debug_mem_stats[DRM_MEM_MAPPINGS].bytes_allocated += size;
+ spin_unlock(&drm_memory_debug_mem_lock);
+ return pt;
+}
+
+void *drm_memory_ioremap_nocache(unsigned long offset, unsigned long size, drm_device_t *dev)
+{
+ void *pt;
+
+ if (!size) {
+ DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
+ "Mapping 0 bytes at 0x%08lx\n", offset);
+ return NULL;
+ }
+
+ if (!(pt = drm_ioremap_nocache(offset, size, dev))) {
+ spin_lock(&drm_memory_debug_mem_lock);
+ ++drm_memory_debug_mem_stats[DRM_MEM_MAPPINGS].fail_count;
+ spin_unlock(&drm_memory_debug_mem_lock);
+ return NULL;
+ }
+ spin_lock(&drm_memory_debug_mem_lock);
+ ++drm_memory_debug_mem_stats[DRM_MEM_MAPPINGS].succeed_count;
+ drm_memory_debug_mem_stats[DRM_MEM_MAPPINGS].bytes_allocated += size;
+ spin_unlock(&drm_memory_debug_mem_lock);
+ return pt;
+}
+
+void drm_memory_debug_ioremapfree(void *pt, unsigned long size, drm_device_t *dev)
+{
+ int alloc_count;
+ int free_count;
+
+ if (!pt)
+ DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
+ "Attempt to free NULL pointer\n");
+ else
+ drm_ioremapfree(pt, size, dev);
+
+ spin_lock(&drm_memory_debug_mem_lock);
+ drm_memory_debug_mem_stats[DRM_MEM_MAPPINGS].bytes_freed += size;
+ free_count = ++drm_memory_debug_mem_stats[DRM_MEM_MAPPINGS].free_count;
+ alloc_count = drm_memory_debug_mem_stats[DRM_MEM_MAPPINGS].succeed_count;
+ spin_unlock(&drm_memory_debug_mem_lock);
+ if (free_count > alloc_count) {
+ DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
+ "Excess frees: %d frees, %d allocs\n",
+ free_count, alloc_count);
+ }
+}
+
+#if __OS_HAS_AGP
+
+DRM_AGP_MEM *drm_memory_debug_alloc_agp(int pages, u32 type)
+{
+ DRM_AGP_MEM *handle;
+
+ if (!pages) {
+ DRM_MEM_ERROR(DRM_MEM_TOTALAGP, "Allocating 0 pages\n");
+ return NULL;
+ }
+
+ if ((handle = drm_memory_agp_allocate_memory(pages, type))) {
+ spin_lock(&drm_memory_debug_mem_lock);
+ ++drm_memory_debug_mem_stats[DRM_MEM_TOTALAGP].succeed_count;
+ drm_memory_debug_mem_stats[DRM_MEM_TOTALAGP].bytes_allocated
+ += pages << PAGE_SHIFT;
+ spin_unlock(&drm_memory_debug_mem_lock);
+ return handle;
+ }
+ spin_lock(&drm_memory_debug_mem_lock);
+ ++drm_memory_debug_mem_stats[DRM_MEM_TOTALAGP].fail_count;
+ spin_unlock(&drm_memory_debug_mem_lock);
+ return NULL;
+}
+
+int drm_memory_debug_free_agp(DRM_AGP_MEM *handle, int pages)
+{
+ int alloc_count;
+ int free_count;
+ int retval = -EINVAL;
+
+ if (!handle) {
+ DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
+ "Attempt to free NULL AGP handle\n");
+ return retval;
+ }
+
+ if (drm_memory_agp_free_memory(handle)) {
+ spin_lock(&drm_memory_debug_mem_lock);
+ free_count = ++drm_memory_debug_mem_stats[DRM_MEM_TOTALAGP].free_count;
+ alloc_count = drm_memory_debug_mem_stats[DRM_MEM_TOTALAGP].succeed_count;
+ drm_memory_debug_mem_stats[DRM_MEM_TOTALAGP].bytes_freed
+ += pages << PAGE_SHIFT;
+ spin_unlock(&drm_memory_debug_mem_lock);
+ if (free_count > alloc_count) {
+ DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
+ "Excess frees: %d frees, %d allocs\n",
+ free_count, alloc_count);
+ }
+ return 0;
+ }
+ return retval;
+}
+
+int drm_memory_debug_bind_agp(DRM_AGP_MEM *handle, unsigned int start)
+{
+ int retcode = -EINVAL;
+
+ if (!handle) {
+ DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
+ "Attempt to bind NULL AGP handle\n");
+ return retcode;
+ }
+
+ if (!(retcode = drm_memory_agp_bind_memory(handle, start))) {
+ spin_lock(&drm_memory_debug_mem_lock);
+ ++drm_memory_debug_mem_stats[DRM_MEM_BOUNDAGP].succeed_count;
+ drm_memory_debug_mem_stats[DRM_MEM_BOUNDAGP].bytes_allocated
+ += handle->page_count << PAGE_SHIFT;
+ spin_unlock(&drm_memory_debug_mem_lock);
+ return retcode;
+ }
+ spin_lock(&drm_memory_debug_mem_lock);
+ ++drm_memory_debug_mem_stats[DRM_MEM_BOUNDAGP].fail_count;
+ spin_unlock(&drm_memory_debug_mem_lock);
+ return retcode;
+}
+
+int drm_memory_debug_unbind_agp(DRM_AGP_MEM *handle)
+{
+ int alloc_count;
+ int free_count;
+ int retcode = -EINVAL;
+
+ if (!handle) {
+ DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
+ "Attempt to unbind NULL AGP handle\n");
+ return retcode;
+ }
+
+ if ((retcode = drm_memory_agp_unbind_memory(handle))) return retcode;
+ spin_lock(&drm_memory_debug_mem_lock);
+ free_count = ++drm_memory_debug_mem_stats[DRM_MEM_BOUNDAGP].free_count;
+ alloc_count = drm_memory_debug_mem_stats[DRM_MEM_BOUNDAGP].succeed_count;
+ drm_memory_debug_mem_stats[DRM_MEM_BOUNDAGP].bytes_freed
+ += handle->page_count << PAGE_SHIFT;
+ spin_unlock(&drm_memory_debug_mem_lock);
+ if (free_count > alloc_count) {
+ DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
+ "Excess frees: %d frees, %d allocs\n",
+ free_count, alloc_count);
+ }
+ return retcode;
+}
+#endif
diff --git a/linux/drm_proc.c b/linux/drm_proc.c
new file mode 100644
index 00000000..9390f079
--- /dev/null
+++ b/linux/drm_proc.c
@@ -0,0 +1,541 @@
+/**
+ * \file drm_proc.h
+ * /proc support for DRM
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ *
+ * \par Acknowledgements:
+ * Matthew J Sottek <matthew.j.sottek@intel.com> sent in a patch to fix
+ * the problem with the proc files not outputting all their information.
+ */
+
+/*
+ * Created: Mon Jan 11 09:48:47 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drm_headers.h"
+
+extern int drm_memory_mem_info(char *buf, char **start, off_t offset,
+ int len, int *eof, void *data);
+
+static int drm_proc_name_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data);
+static int drm_proc_vm_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data);
+static int drm_proc_clients_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data);
+static int drm_proc_queues_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data);
+static int drm_proc_bufs_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data);
+#if DRM_DEBUG_CODE
+static int drm_proc_vma_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data);
+#endif
+
+/**
+ * Proc file list.
+ */
+struct drm_proc_list {
+ const char *name; /**< file name */
+ int (*f)(char *, char **, off_t, int, int *, void *); /**< proc callback*/
+} drm_proc_list[] = {
+ { "name", drm_proc_name_info },
+ { "mem", drm_memory_mem_info },
+ { "vm", drm_proc_vm_info },
+ { "clients", drm_proc_clients_info },
+ { "queues", drm_proc_queues_info },
+ { "bufs", drm_proc_bufs_info },
+#if DRM_DEBUG_CODE
+ { "vma", drm_proc_vma_info },
+#endif
+};
+#define DRM_PROC_ENTRIES (sizeof(drm_proc_list)/sizeof(drm_proc_list[0]))
+
+/**
+ * Initialize the DRI proc filesystem for a device.
+ *
+ * \param dev DRM device.
+ * \param minor device minor number.
+ * \param root DRI proc dir entry.
+ * \param dev_root resulting DRI device proc dir entry.
+ * \return root entry pointer on success, or NULL on failure.
+ *
+ * Create the DRI proc root entry "/proc/dri", the device proc root entry
+ * "/proc/dri/%minor%/", and each entry in proc_list as
+ * "/proc/dri/%minor%/%name%".
+ */
+int drm_proc_init(drm_device_t *dev, int minor,
+ struct proc_dir_entry *root,
+ struct proc_dir_entry **dev_root)
+{
+ struct proc_dir_entry *ent;
+ int i, j;
+ char name[64];
+
+ sprintf(name, "%d", minor);
+ *dev_root = create_proc_entry(name, S_IFDIR, root);
+ if (!*dev_root) {
+ DRM_ERROR("Cannot create /proc/dri/%s\n", name);
+ return -1;
+ }
+
+ for (i = 0; i < DRM_PROC_ENTRIES; i++) {
+ ent = create_proc_entry(drm_proc_list[i].name,
+ S_IFREG|S_IRUGO, *dev_root);
+ if (!ent) {
+ DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
+ name, drm_proc_list[i].name);
+ for (j = 0; j < i; j++)
+ remove_proc_entry(drm_proc_list[i].name,
+ *dev_root);
+ remove_proc_entry(name, root);
+ return -1;
+ }
+ ent->read_proc = drm_proc_list[i].f;
+ ent->data = dev;
+ }
+ return 0;
+}
+
+
+/**
+ * Cleanup the proc filesystem resources.
+ *
+ * \param minor device minor number.
+ * \param root DRI proc dir entry.
+ * \param dev_root DRI device proc dir entry.
+ * \return always zero.
+ *
+ * Remove all proc entries created by proc_init().
+ */
+int drm_proc_cleanup(int minor, struct proc_dir_entry *root,
+ struct proc_dir_entry *dev_root)
+{
+ int i;
+ char name[64];
+
+ if (!root || !dev_root) return 0;
+
+ for (i = 0; i < DRM_PROC_ENTRIES; i++)
+ remove_proc_entry(drm_proc_list[i].name, dev_root);
+ sprintf(name, "%d", minor);
+ remove_proc_entry(name, root);
+
+ return 0;
+}
+
+/**
+ * Called when "/proc/dri/.../name" is read.
+ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param request requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ *
+ * Prints the device name together with the bus id if available.
+ */
+static int drm_proc_name_info(char *buf, char **start, off_t offset, int request,
+ int *eof, void *data)
+{
+ drm_device_t *dev = (drm_device_t *)data;
+ int len = 0;
+
+ if (offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ *start = &buf[offset];
+ *eof = 0;
+
+ if (dev->unique) {
+ DRM_PROC_PRINT("%s 0x%lx %s\n",
+ dev->name, (long)old_encode_dev(dev->device), dev->unique);
+ } else {
+ DRM_PROC_PRINT("%s 0x%lx\n", dev->name, (long)old_encode_dev(dev->device));
+ }
+
+ if (len > request + offset) return request;
+ *eof = 1;
+ return len - offset;
+}
+
+/**
+ * Called when "/proc/dri/.../vm" is read.
+ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param request requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ *
+ * Prints information about all mappings in drm_device::maplist.
+ */
+static int drm_proc__vm_info(char *buf, char **start, off_t offset, int request,
+ int *eof, void *data)
+{
+ drm_device_t *dev = (drm_device_t *)data;
+ int len = 0;
+ drm_map_t *map;
+ drm_map_list_t *r_list;
+ struct list_head *list;
+
+ /* Hardcoded from _DRM_FRAME_BUFFER,
+ _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
+ _DRM_SCATTER_GATHER. */
+ const char *types[] = { "FB", "REG", "SHM", "AGP", "SG" };
+ const char *type;
+ int i;
+
+ if (offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ *start = &buf[offset];
+ *eof = 0;
+
+ DRM_PROC_PRINT("slot offset size type flags "
+ "address mtrr\n\n");
+ i = 0;
+ if (dev->maplist != NULL) list_for_each(list, &dev->maplist->head) {
+ r_list = list_entry(list, drm_map_list_t, head);
+ map = r_list->map;
+ if(!map) continue;
+ if (map->type < 0 || map->type > 4) type = "??";
+ else type = types[map->type];
+ DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ",
+ i,
+ map->offset,
+ map->size,
+ type,
+ map->flags,
+ (unsigned long)map->handle);
+ if (map->mtrr < 0) {
+ DRM_PROC_PRINT("none\n");
+ } else {
+ DRM_PROC_PRINT("%4d\n", map->mtrr);
+ }
+ i++;
+ }
+
+ if (len > request + offset) return request;
+ *eof = 1;
+ return len - offset;
+}
+
+/**
+ * Simply calls _vm_info() while holding the drm_device::struct_sem lock.
+ */
+static int drm_proc_vm_info(char *buf, char **start, off_t offset, int request,
+ int *eof, void *data)
+{
+ drm_device_t *dev = (drm_device_t *)data;
+ int ret;
+
+ down(&dev->struct_sem);
+ ret = drm_proc__vm_info(buf, start, offset, request, eof, data);
+ up(&dev->struct_sem);
+ return ret;
+}
+
+/**
+ * Called when "/proc/dri/.../queues" is read.
+ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param request requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ */
+static int drm_proc__queues_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data)
+{
+ drm_device_t *dev = (drm_device_t *)data;
+ int len = 0;
+ int i;
+ drm_queue_t *q;
+
+ if (offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ *start = &buf[offset];
+ *eof = 0;
+
+ DRM_PROC_PRINT(" ctx/flags use fin"
+ " blk/rw/rwf wait flushed queued"
+ " locks\n\n");
+ for (i = 0; i < dev->queue_count; i++) {
+ q = dev->queuelist[i];
+ atomic_inc(&q->use_count);
+ DRM_PROC_PRINT_RET(atomic_dec(&q->use_count),
+ "%5d/0x%03x %5d %5d"
+ " %5d/%c%c/%c%c%c %5Zd\n",
+ i,
+ q->flags,
+ atomic_read(&q->use_count),
+ atomic_read(&q->finalization),
+ atomic_read(&q->block_count),
+ atomic_read(&q->block_read) ? 'r' : '-',
+ atomic_read(&q->block_write) ? 'w' : '-',
+ waitqueue_active(&q->read_queue) ? 'r':'-',
+ waitqueue_active(&q->write_queue) ? 'w':'-',
+ waitqueue_active(&q->flush_queue) ? 'f':'-',
+ DRM_BUFCOUNT(&q->waitlist));
+ atomic_dec(&q->use_count);
+ }
+
+ if (len > request + offset) return request;
+ *eof = 1;
+ return len - offset;
+}
+
+/**
+ * Simply calls _queues_info() while holding the drm_device::struct_sem lock.
+ */
+static int drm_proc_queues_info(char *buf, char **start, off_t offset, int request,
+ int *eof, void *data)
+{
+ drm_device_t *dev = (drm_device_t *)data;
+ int ret;
+
+ down(&dev->struct_sem);
+ ret = drm_proc__queues_info(buf, start, offset, request, eof, data);
+ up(&dev->struct_sem);
+ return ret;
+}
+
+/**
+ * Called when "/proc/dri/.../bufs" is read.
+ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param request requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ */
+static int drm_proc__bufs_info(char *buf, char **start, off_t offset, int request,
+ int *eof, void *data)
+{
+ drm_device_t *dev = (drm_device_t *)data;
+ int len = 0;
+ drm_device_dma_t *dma = dev->dma;
+ int i;
+
+ if (!dma || offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ *start = &buf[offset];
+ *eof = 0;
+
+ DRM_PROC_PRINT(" o size count free segs pages kB\n\n");
+ for (i = 0; i <= DRM_MAX_ORDER; i++) {
+ if (dma->bufs[i].buf_count)
+ DRM_PROC_PRINT("%2d %8d %5d %5d %5d %5d %5ld\n",
+ i,
+ dma->bufs[i].buf_size,
+ dma->bufs[i].buf_count,
+ atomic_read(&dma->bufs[i]
+ .freelist.count),
+ dma->bufs[i].seg_count,
+ dma->bufs[i].seg_count
+ *(1 << dma->bufs[i].page_order),
+ (dma->bufs[i].seg_count
+ * (1 << dma->bufs[i].page_order))
+ * PAGE_SIZE / 1024);
+ }
+ DRM_PROC_PRINT("\n");
+ for (i = 0; i < dma->buf_count; i++) {
+ if (i && !(i%32)) DRM_PROC_PRINT("\n");
+ DRM_PROC_PRINT(" %d", dma->buflist[i]->list);
+ }
+ DRM_PROC_PRINT("\n");
+
+ if (len > request + offset) return request;
+ *eof = 1;
+ return len - offset;
+}
+
+/**
+ * Simply calls _bufs_info() while holding the drm_device::struct_sem lock.
+ */
+static int drm_proc_bufs_info(char *buf, char **start, off_t offset, int request,
+ int *eof, void *data)
+{
+ drm_device_t *dev = (drm_device_t *)data;
+ int ret;
+
+ down(&dev->struct_sem);
+ ret = drm_proc__bufs_info(buf, start, offset, request, eof, data);
+ up(&dev->struct_sem);
+ return ret;
+}
+
+/**
+ * Called when "/proc/dri/.../clients" is read.
+ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param request requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ */
+static int drm_proc__clients_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data)
+{
+ drm_device_t *dev = (drm_device_t *)data;
+ int len = 0;
+ drm_file_t *priv;
+
+ if (offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ *start = &buf[offset];
+ *eof = 0;
+
+ DRM_PROC_PRINT("a dev pid uid magic ioctls\n\n");
+ for (priv = dev->file_first; priv; priv = priv->next) {
+ DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n",
+ priv->authenticated ? 'y' : 'n',
+ priv->minor,
+ priv->pid,
+ priv->uid,
+ priv->magic,
+ priv->ioctl_count);
+ }
+
+ if (len > request + offset) return request;
+ *eof = 1;
+ return len - offset;
+}
+
+/**
+ * Simply calls _clients_info() while holding the drm_device::struct_sem lock.
+ */
+static int drm_proc_clients_info(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data)
+{
+ drm_device_t *dev = (drm_device_t *)data;
+ int ret;
+
+ down(&dev->struct_sem);
+ ret = drm_proc__clients_info(buf, start, offset, request, eof, data);
+ up(&dev->struct_sem);
+ return ret;
+}
+
+#if DRM_DEBUG_CODE
+
+static int drm_proc__vma_info(char *buf, char **start, off_t offset, int request,
+ int *eof, void *data)
+{
+ drm_device_t *dev = (drm_device_t *)data;
+ int len = 0;
+ drm_vma_entry_t *pt;
+ struct vm_area_struct *vma;
+#if defined(__i386__)
+ unsigned int pgprot;
+#endif
+
+ if (offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ *start = &buf[offset];
+ *eof = 0;
+
+ DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n",
+ atomic_read(&dev->vma_count),
+ high_memory, virt_to_phys(high_memory));
+ for (pt = dev->vmalist; pt; pt = pt->next) {
+ if (!(vma = pt->vma)) continue;
+ DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx",
+ pt->pid,
+ vma->vm_start,
+ vma->vm_end,
+ vma->vm_flags & VM_READ ? 'r' : '-',
+ vma->vm_flags & VM_WRITE ? 'w' : '-',
+ vma->vm_flags & VM_EXEC ? 'x' : '-',
+ vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
+ vma->vm_flags & VM_LOCKED ? 'l' : '-',
+ vma->vm_flags & VM_IO ? 'i' : '-',
+ VM_OFFSET(vma));
+
+#if defined(__i386__)
+ pgprot = pgprot_val(vma->vm_page_prot);
+ DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c",
+ pgprot & _PAGE_PRESENT ? 'p' : '-',
+ pgprot & _PAGE_RW ? 'w' : 'r',
+ pgprot & _PAGE_USER ? 'u' : 's',
+ pgprot & _PAGE_PWT ? 't' : 'b',
+ pgprot & _PAGE_PCD ? 'u' : 'c',
+ pgprot & _PAGE_ACCESSED ? 'a' : '-',
+ pgprot & _PAGE_DIRTY ? 'd' : '-',
+ pgprot & _PAGE_PSE ? 'm' : 'k',
+ pgprot & _PAGE_GLOBAL ? 'g' : 'l' );
+#endif
+ DRM_PROC_PRINT("\n");
+ }
+
+ if (len > request + offset) return request;
+ *eof = 1;
+ return len - offset;
+}
+
+static int drm_proc_vma_info(char *buf, char **start, off_t offset, int request,
+ int *eof, void *data)
+{
+ drm_device_t *dev = (drm_device_t *)data;
+ int ret;
+
+ down(&dev->struct_sem);
+ ret = drm_proc__vma_info(buf, start, offset, request, eof, data);
+ up(&dev->struct_sem);
+ return ret;
+}
+#endif
+
+
diff --git a/linux/drm_scatter.h b/linux/drm_scatter.h
index 888e6296..02e82781 100644
--- a/linux/drm_scatter.h
+++ b/linux/drm_scatter.h
@@ -50,13 +50,13 @@ void DRM(sg_cleanup)( drm_sg_mem_t *entry )
vfree( entry->virtual );
- DRM(free)( entry->busaddr,
+ drm_core_free( entry->busaddr,
entry->pages * sizeof(*entry->busaddr),
DRM_MEM_PAGES );
- DRM(free)( entry->pagelist,
+ drm_core_free( entry->pagelist,
entry->pages * sizeof(*entry->pagelist),
DRM_MEM_PAGES );
- DRM(free)( entry,
+ drm_core_free( entry,
sizeof(*entry),
DRM_MEM_SGLISTS );
}
@@ -82,7 +82,7 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp,
if ( copy_from_user( &request, argp, sizeof(request) ) )
return -EFAULT;
- entry = DRM(alloc)( sizeof(*entry), DRM_MEM_SGLISTS );
+ entry = drm_core_alloc( sizeof(*entry), DRM_MEM_SGLISTS );
if ( !entry )
return -ENOMEM;
@@ -92,22 +92,22 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp,
DRM_DEBUG( "sg size=%ld pages=%ld\n", request.size, pages );
entry->pages = pages;
- entry->pagelist = DRM(alloc)( pages * sizeof(*entry->pagelist),
+ entry->pagelist = drm_core_alloc( pages * sizeof(*entry->pagelist),
DRM_MEM_PAGES );
if ( !entry->pagelist ) {
- DRM(free)( entry, sizeof(*entry), DRM_MEM_SGLISTS );
+ drm_core_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),
+ entry->busaddr = drm_core_alloc( pages * sizeof(*entry->busaddr),
DRM_MEM_PAGES );
if ( !entry->busaddr ) {
- DRM(free)( entry->pagelist,
+ drm_core_free( entry->pagelist,
entry->pages * sizeof(*entry->pagelist),
DRM_MEM_PAGES );
- DRM(free)( entry,
+ drm_core_free( entry,
sizeof(*entry),
DRM_MEM_SGLISTS );
return -ENOMEM;
@@ -116,13 +116,13 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp,
entry->virtual = vmalloc_32( pages << PAGE_SHIFT );
if ( !entry->virtual ) {
- DRM(free)( entry->busaddr,
+ drm_core_free( entry->busaddr,
entry->pages * sizeof(*entry->busaddr),
DRM_MEM_PAGES );
- DRM(free)( entry->pagelist,
+ drm_core_free( entry->pagelist,
entry->pages * sizeof(*entry->pagelist),
DRM_MEM_PAGES );
- DRM(free)( entry,
+ drm_core_free( entry,
sizeof(*entry),
DRM_MEM_SGLISTS );
return -ENOMEM;
diff --git a/linux/drm_stub.h b/linux/drm_stub.h
index 3d9ade35..53f75f4c 100644
--- a/linux/drm_stub.h
+++ b/linux/drm_stub.h
@@ -162,7 +162,7 @@ static int DRM(stub_getminor)(const char *name, struct file_operations *fops,
int i;
if (!DRM(stub_list)) {
- DRM(stub_list) = DRM(alloc)(sizeof(*DRM(stub_list))
+ DRM(stub_list) = drm_core_alloc(sizeof(*DRM(stub_list))
* DRM_STUB_MAXCARDS, DRM_MEM_STUB);
if(!DRM(stub_list)) return -1;
for (i = 0; i < DRM_STUB_MAXCARDS; i++) {
@@ -174,7 +174,7 @@ static int DRM(stub_getminor)(const char *name, struct file_operations *fops,
if (!DRM(stub_list)[i].fops) {
DRM(stub_list)[i].name = name;
DRM(stub_list)[i].fops = fops;
- DRM(proc_init)(dev, i, DRM(stub_info).proc_root,
+ drm_proc_init(dev, i, DRM(stub_info).proc_root,
&DRM(stub_list)[i].dev_root);
(*DRM(stub_info).info_count)++;
DRM_DEBUG("info count increased %d\n", *DRM(stub_info).info_count);
@@ -200,7 +200,7 @@ static int DRM(stub_putminor)(int minor)
if (minor < 0 || minor >= DRM_STUB_MAXCARDS) return -1;
DRM(stub_list)[minor].name = NULL;
DRM(stub_list)[minor].fops = NULL;
- DRM(proc_cleanup)(minor, DRM(stub_info).proc_root,
+ drm_proc_cleanup(minor, DRM(stub_info).proc_root,
DRM(stub_list)[minor].dev_root);
(*DRM(stub_info).info_count)--;
@@ -213,7 +213,7 @@ static int DRM(stub_putminor)(int minor)
} else {
DRM_DEBUG("unregistering inter_module \n");
inter_module_unregister("drm");
- DRM(free)(DRM(stub_list),
+ drm_core_free(DRM(stub_list),
sizeof(*DRM(stub_list)) * DRM_STUB_MAXCARDS,
DRM_MEM_STUB);
remove_proc_entry("dri", NULL);
diff --git a/linux/drm_vm.h b/linux/drm_vm.h
index f13db00b..86fe9426 100644
--- a/linux/drm_vm.h
+++ b/linux/drm_vm.h
@@ -183,7 +183,7 @@ void DRM(vm_shm_close)(struct vm_area_struct *vma)
} else {
dev->vmalist = pt->next;
}
- DRM(free)(pt, sizeof(*pt), DRM_MEM_VMAS);
+ drm_core_free(pt, sizeof(*pt), DRM_MEM_VMAS);
} else {
prev = pt;
}
@@ -214,7 +214,7 @@ void DRM(vm_shm_close)(struct vm_area_struct *vma)
DRM_DEBUG("mtrr_del = %d\n", retcode);
}
#endif
- DRM(ioremapfree)(map->handle, map->size, dev);
+ drm_core_ioremapfree(map, dev);
break;
case _DRM_SHM:
vfree(map->handle);
@@ -223,7 +223,7 @@ void DRM(vm_shm_close)(struct vm_area_struct *vma)
case _DRM_SCATTER_GATHER:
break;
}
- DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
+ drm_core_free(map, sizeof(*map), DRM_MEM_MAPS);
}
}
up(&dev->struct_sem);
@@ -405,7 +405,7 @@ void DRM(vm_open)(struct vm_area_struct *vma)
vma->vm_start, vma->vm_end - vma->vm_start);
atomic_inc(&dev->vma_count);
- vma_entry = DRM(alloc)(sizeof(*vma_entry), DRM_MEM_VMAS);
+ vma_entry = drm_core_alloc(sizeof(*vma_entry), DRM_MEM_VMAS);
if (vma_entry) {
down(&dev->struct_sem);
vma_entry->vma = vma;
@@ -442,7 +442,7 @@ void DRM(vm_close)(struct vm_area_struct *vma)
} else {
dev->vmalist = pt->next;
}
- DRM(free)(pt, sizeof(*pt), DRM_MEM_VMAS);
+ drm_core_free(pt, sizeof(*pt), DRM_MEM_VMAS);
break;
}
}
diff --git a/linux/drmcore_exports.c b/linux/drmcore_exports.c
new file mode 100644
index 00000000..69a32dfe
--- /dev/null
+++ b/linux/drmcore_exports.c
@@ -0,0 +1,32 @@
+#include "drm_headers.h"
+
+EXPORT_SYMBOL(drm_core_reclaim_buffers);
+EXPORT_SYMBOL(drm_memory_agp_uninit);
+EXPORT_SYMBOL(drm_core_rmmap);
+EXPORT_SYMBOL(drm_ati_pcigart_cleanup);
+EXPORT_SYMBOL(drm_core_infobufs);
+EXPORT_SYMBOL(drm_proc_init);
+EXPORT_SYMBOL(drm_core_dma_takedown);
+EXPORT_SYMBOL(drm_proc_cleanup);
+EXPORT_SYMBOL(drm_core_dma_setup);
+EXPORT_SYMBOL(drm_memory_agp_bind);
+EXPORT_SYMBOL(drm_core_freebufs);
+EXPORT_SYMBOL(drm_ati_pcigart_init);
+EXPORT_SYMBOL(drm_memory_unbind_agp);
+EXPORT_SYMBOL(drm_core_markbufs);
+EXPORT_SYMBOL(drm_memory_agp_init);
+EXPORT_SYMBOL(drm_memory_agp_info);
+EXPORT_SYMBOL(drm_memory_agp_alloc);
+EXPORT_SYMBOL(drm_memory_agp_do_release);
+EXPORT_SYMBOL(drm_memory_agp_release);
+EXPORT_SYMBOL(drm_memory_realloc);
+EXPORT_SYMBOL(drm_memory_agp_enable);
+EXPORT_SYMBOL(drm_memory_agp_acquire);
+EXPORT_SYMBOL(drm_memory_agp_free);
+EXPORT_SYMBOL(drm_core_addbufs);
+EXPORT_SYMBOL(drm_core_order);
+EXPORT_SYMBOL(drm_memory_mem_init);
+EXPORT_SYMBOL(drm_core_mapbufs);
+EXPORT_SYMBOL(drm_core_addmap);
+EXPORT_SYMBOL(drm_memory_agp_unbind);
+EXPORT_SYMBOL(drm_memory_free_agp);
diff --git a/linux/radeon_drv.c b/linux/radeon_drv.c
index 74e32df0..582d172c 100644
--- a/linux/radeon_drv.c
+++ b/linux/radeon_drv.c
@@ -31,18 +31,16 @@
#include <linux/config.h>
+#include "drm_headers.h"
+
#include "radeon.h"
#include "drmP.h"
#include "drm.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
-#include "ati_pcigart.h"
-#include "drm_agpsupport.h"
#include "drm_auth.h"
-#include "drm_bufs.h"
#include "drm_context.h"
-#include "drm_dma.h"
#include "drm_drawable.h"
#include "drm_drv.h"
#include "drm_fops.h"
@@ -50,8 +48,6 @@
#include "drm_ioctl.h"
#include "drm_irq.h"
#include "drm_lock.h"
-#include "drm_memory.h"
-#include "drm_proc.h"
#include "drm_vm.h"
#include "drm_stub.h"
#include "drm_scatter.h"