summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/drm/drm.h463
-rw-r--r--sys/dev/drm/drmP.h20
-rw-r--r--sys/dev/drm/drm_bufs.h10
-rw-r--r--sys/dev/drm/drm_drv.h30
-rw-r--r--sys/dev/drm/drm_fops.h8
-rw-r--r--sys/dev/drm/drm_ioctl.h91
-rw-r--r--sys/dev/drm/drm_irq.h119
-rw-r--r--sys/dev/drm/drm_os_freebsd.h6
-rw-r--r--sys/dev/drm/mga_dma.c2
-rw-r--r--sys/dev/drm/r128_cce.c2
-rw-r--r--sys/dev/drm/radeon.h21
-rw-r--r--sys/dev/drm/radeon_cp.c31
-rw-r--r--sys/dev/drm/radeon_drm.h16
-rw-r--r--sys/dev/drm/radeon_drv.h5
-rw-r--r--sys/dev/drm/radeon_state.c323
15 files changed, 833 insertions, 314 deletions
diff --git a/sys/dev/drm/drm.h b/sys/dev/drm/drm.h
index 6026580..9ef223d 100644
--- a/sys/dev/drm/drm.h
+++ b/sys/dev/drm/drm.h
@@ -1,6 +1,14 @@
-/* drm.h -- Header for Direct Rendering Manager -*- linux-c -*-
- * Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com
+/**
+ * \file drm.h
+ * Header for the Direct Rendering Manager
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
*
+ * \par Acknowledgments:
+ * Dec 1999, Richard Henderson <rth@twiddle.net>, move to generic \c cmpxchg.
+ */
+
+/*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All rights reserved.
@@ -24,15 +32,10 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
- * Authors:
- * Rickard E. (Rik) Faith <faith@valinux.com>
- *
- * Acknowledgements:
- * Dec 1999, Richard Henderson <rth@twiddle.net>, move to generic cmpxchg.
- *
* $FreeBSD$
*/
+
#ifndef _DRM_H_
#define _DRM_H_
@@ -79,29 +82,42 @@
#define DRM_DEV_GID 0
#endif
-#define DRM_NAME "drm" /* Name in kernel, /dev, and /proc */
-#define DRM_MIN_ORDER 5 /* At least 2^5 bytes = 32 bytes */
-#define DRM_MAX_ORDER 22 /* Up to 2^22 bytes = 4MB */
-#define DRM_RAM_PERCENT 10 /* How much system ram can we lock? */
+#if CONFIG_XFREE86_VERSION >= XFREE86_VERSION(4,1,0,0)
+#ifdef __OpenBSD__
+#define DRM_MAJOR 81
+#endif
+#if defined(__linux__) || defined(__NetBSD__)
+#define DRM_MAJOR 226
+#endif
+#define DRM_MAX_MINOR 15
+#endif
+#define DRM_NAME "drm" /**< Name in kernel, /dev, and /proc */
+#define DRM_MIN_ORDER 5 /**< At least 2^5 bytes = 32 bytes */
+#define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */
+#define DRM_RAM_PERCENT 10 /**< How much system ram can we lock? */
-#define _DRM_LOCK_HELD 0x80000000 /* Hardware lock is held */
-#define _DRM_LOCK_CONT 0x40000000 /* Hardware lock is contended */
+#define _DRM_LOCK_HELD 0x80000000 /**< Hardware lock is held */
+#define _DRM_LOCK_CONT 0x40000000 /**< Hardware lock is contended */
#define _DRM_LOCK_IS_HELD(lock) ((lock) & _DRM_LOCK_HELD)
#define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT)
#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
+
typedef unsigned long drm_handle_t;
typedef unsigned int drm_context_t;
typedef unsigned int drm_drawable_t;
typedef unsigned int drm_magic_t;
-/* Warning: If you change this structure, make sure you change
- * XF86DRIClipRectRec in the server as well */
-/* KW: Actually it's illegal to change either for
+/**
+ * Cliprect.
+ *
+ * \warning: If you change this structure, make sure you change
+ * XF86DRIClipRectRec in the server as well
+ *
+ * \note KW: Actually it's illegal to change either for
* backwards-compatibility reasons.
*/
-
typedef struct drm_clip_rect {
unsigned short x1;
unsigned short y1;
@@ -109,6 +125,10 @@ typedef struct drm_clip_rect {
unsigned short y2;
} drm_clip_rect_t;
+
+/**
+ * Texture region,
+ */
typedef struct drm_tex_region {
unsigned char next;
unsigned char prev;
@@ -117,32 +137,52 @@ typedef struct drm_tex_region {
unsigned int age;
} drm_tex_region_t;
+
+/**
+ * DRM_IOCTL_VERSION ioctl argument type.
+ *
+ * \sa drmGetVersion().
+ */
typedef struct drm_version {
- int version_major; /* Major version */
- int version_minor; /* Minor version */
- int version_patchlevel;/* Patch level */
- size_t name_len; /* Length of name buffer */
- char *name; /* Name of driver */
- size_t date_len; /* Length of date buffer */
- char *date; /* User-space buffer to hold date */
- size_t desc_len; /* Length of desc buffer */
- char *desc; /* User-space buffer to hold desc */
+ int version_major; /**< Major version */
+ int version_minor; /**< Minor version */
+ int version_patchlevel;/**< Patch level */
+ size_t name_len; /**< Length of name buffer */
+ char *name; /**< Name of driver */
+ size_t date_len; /**< Length of date buffer */
+ char *date; /**< User-space buffer to hold date */
+ size_t desc_len; /**< Length of desc buffer */
+ char *desc; /**< User-space buffer to hold desc */
} drm_version_t;
+
+/**
+ * DRM_IOCTL_GET_UNIQUE ioctl argument type.
+ *
+ * \sa drmGetBusid() and drmSetBusId().
+ */
typedef struct drm_unique {
- size_t unique_len; /* Length of unique */
- char *unique; /* Unique name for driver instantiation */
+ size_t unique_len; /**< Length of unique */
+ char *unique; /**< Unique name for driver instantiation */
} drm_unique_t;
+
typedef struct drm_list {
- int count; /* Length of user-space structures */
+ int count; /**< Length of user-space structures */
drm_version_t *version;
} drm_list_t;
+
typedef struct drm_block {
int unused;
} drm_block_t;
+
+/**
+ * DRM_IOCTL_CONTROL ioctl argument type.
+ *
+ * \sa drmCtlInstHandler() and drmCtlUninstHandler().
+ */
typedef struct drm_control {
enum {
DRM_ADD_COMMAND,
@@ -153,49 +193,70 @@ typedef struct drm_control {
int irq;
} drm_control_t;
+
+/**
+ * Type of memory to map.
+ */
typedef enum drm_map_type {
- _DRM_FRAME_BUFFER = 0, /* WC (no caching), no core dump */
- _DRM_REGISTERS = 1, /* no caching, no core dump */
- _DRM_SHM = 2, /* shared, cached */
- _DRM_AGP = 3, /* AGP/GART */
- _DRM_SCATTER_GATHER = 4 /* Scatter/gather memory for PCI DMA */
+ _DRM_FRAME_BUFFER = 0, /**< WC (no caching), no core dump */
+ _DRM_REGISTERS = 1, /**< no caching, no core dump */
+ _DRM_SHM = 2, /**< shared, cached */
+ _DRM_AGP = 3, /**< AGP/GART */
+ _DRM_SCATTER_GATHER = 4 /**< Scatter/gather memory for PCI DMA */
} drm_map_type_t;
+
+/**
+ * Memory mapping flags.
+ */
typedef enum drm_map_flags {
- _DRM_RESTRICTED = 0x01, /* Cannot be mapped to user-virtual */
+ _DRM_RESTRICTED = 0x01, /**< Cannot be mapped to user-virtual */
_DRM_READ_ONLY = 0x02,
- _DRM_LOCKED = 0x04, /* shared, cached, locked */
- _DRM_KERNEL = 0x08, /* kernel requires access */
- _DRM_WRITE_COMBINING = 0x10, /* use write-combining if available */
- _DRM_CONTAINS_LOCK = 0x20, /* SHM page that contains lock */
- _DRM_REMOVABLE = 0x40 /* Removable mapping */
+ _DRM_LOCKED = 0x04, /**< shared, cached, locked */
+ _DRM_KERNEL = 0x08, /**< kernel requires access */
+ _DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */
+ _DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */
+ _DRM_REMOVABLE = 0x40 /**< Removable mapping */
} drm_map_flags_t;
+
typedef struct drm_ctx_priv_map {
- unsigned int ctx_id; /* Context requesting private mapping */
- void *handle; /* Handle of map */
+ unsigned int ctx_id; /**< Context requesting private mapping */
+ void *handle; /**< Handle of map */
} drm_ctx_priv_map_t;
+
+/**
+ * DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls
+ * argument type.
+ *
+ * \sa drmAddMap().
+ */
typedef struct drm_map {
- unsigned long offset; /* Requested physical address (0 for SAREA)*/
- unsigned long size; /* Requested physical size (bytes) */
- drm_map_type_t type; /* Type of memory to map */
- drm_map_flags_t flags; /* Flags */
- void *handle; /* User-space: "Handle" to pass to mmap */
- /* Kernel-space: kernel-virtual address */
- int mtrr; /* MTRR slot used */
- /* Private data */
+ unsigned long offset; /**< Requested physical address (0 for SAREA)*/
+ unsigned long size; /**< Requested physical size (bytes) */
+ drm_map_type_t type; /**< Type of memory to map */
+ drm_map_flags_t flags; /**< Flags */
+ void *handle; /**< User-space: "Handle" to pass to mmap() */
+ /**< Kernel-space: kernel-virtual address */
+ int mtrr; /**< MTRR slot used */
+ /* Private data */
} drm_map_t;
+
+/**
+ * DRM_IOCTL_GET_CLIENT ioctl argument type.
+ */
typedef struct drm_client {
- int idx; /* Which client desired? */
- int auth; /* Is client authenticated? */
- unsigned long pid; /* Process id */
- unsigned long uid; /* User id */
- unsigned long magic; /* Magic */
- unsigned long iocs; /* Ioctl count */
+ int idx; /**< Which client desired? */
+ int auth; /**< Is client authenticated? */
+ unsigned long pid; /**< Process ID */
+ unsigned long uid; /**< User ID */
+ unsigned long magic; /**< Magic */
+ unsigned long iocs; /**< Ioctl count */
} drm_client_t;
+
typedef enum {
_DRM_STAT_LOCK,
_DRM_STAT_OPENS,
@@ -203,20 +264,24 @@ typedef enum {
_DRM_STAT_IOCTLS,
_DRM_STAT_LOCKS,
_DRM_STAT_UNLOCKS,
- _DRM_STAT_VALUE, /* Generic value */
- _DRM_STAT_BYTE, /* Generic byte counter (1024bytes/K) */
- _DRM_STAT_COUNT, /* Generic non-byte counter (1000/k) */
+ _DRM_STAT_VALUE, /**< Generic value */
+ _DRM_STAT_BYTE, /**< Generic byte counter (1024bytes/K) */
+ _DRM_STAT_COUNT, /**< Generic non-byte counter (1000/k) */
- _DRM_STAT_IRQ, /* IRQ */
- _DRM_STAT_PRIMARY, /* Primary DMA bytes */
- _DRM_STAT_SECONDARY, /* Secondary DMA bytes */
- _DRM_STAT_DMA, /* DMA */
- _DRM_STAT_SPECIAL, /* Special DMA (e.g., priority or polled) */
- _DRM_STAT_MISSED /* Missed DMA opportunity */
+ _DRM_STAT_IRQ, /**< IRQ */
+ _DRM_STAT_PRIMARY, /**< Primary DMA bytes */
+ _DRM_STAT_SECONDARY, /**< Secondary DMA bytes */
+ _DRM_STAT_DMA, /**< DMA */
+ _DRM_STAT_SPECIAL, /**< Special DMA (e.g., priority or polled) */
+ _DRM_STAT_MISSED /**< Missed DMA opportunity */
/* Add to the *END* of the list */
} drm_stat_type_t;
+
+/**
+ * DRM_IOCTL_GET_STATS ioctl argument type.
+ */
typedef struct drm_stats {
unsigned long count;
struct {
@@ -225,137 +290,220 @@ typedef struct drm_stats {
} data[15];
} drm_stats_t;
+
+/**
+ * Hardware locking flags.
+ */
typedef enum drm_lock_flags {
- _DRM_LOCK_READY = 0x01, /* Wait until hardware is ready for DMA */
- _DRM_LOCK_QUIESCENT = 0x02, /* Wait until hardware quiescent */
- _DRM_LOCK_FLUSH = 0x04, /* Flush this context's DMA queue first */
- _DRM_LOCK_FLUSH_ALL = 0x08, /* Flush all DMA queues first */
+ _DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */
+ _DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */
+ _DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */
+ _DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */
/* These *HALT* flags aren't supported yet
-- they will be used to support the
full-screen DGA-like mode. */
- _DRM_HALT_ALL_QUEUES = 0x10, /* Halt all current and future queues */
- _DRM_HALT_CUR_QUEUES = 0x20 /* Halt all current queues */
+ _DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */
+ _DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */
} drm_lock_flags_t;
+
+/**
+ * DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type.
+ *
+ * \sa drmGetLock() and drmUnlock().
+ */
typedef struct drm_lock {
int context;
drm_lock_flags_t flags;
} drm_lock_t;
-typedef enum drm_dma_flags { /* These values *MUST* match xf86drm.h */
- /* Flags for DMA buffer dispatch */
- _DRM_DMA_BLOCK = 0x01, /* Block until buffer dispatched.
- Note, the buffer may not yet have
- been processed by the hardware --
- getting a hardware lock with the
- hardware quiescent will ensure
- that the buffer has been
- processed. */
- _DRM_DMA_WHILE_LOCKED = 0x02, /* Dispatch while lock held */
- _DRM_DMA_PRIORITY = 0x04, /* High priority dispatch */
-
- /* Flags for DMA buffer request */
- _DRM_DMA_WAIT = 0x10, /* Wait for free buffers */
- _DRM_DMA_SMALLER_OK = 0x20, /* Smaller-than-requested buffers ok */
- _DRM_DMA_LARGER_OK = 0x40 /* Larger-than-requested buffers ok */
+
+/**
+ * DMA flags
+ *
+ * \warning
+ * These values \e must match xf86drm.h.
+ *
+ * \sa drm_dma.
+ */
+typedef enum drm_dma_flags {
+ /* Flags for DMA buffer dispatch */
+ _DRM_DMA_BLOCK = 0x01, /**<
+ * Block until buffer dispatched.
+ *
+ * \note The buffer may not yet have
+ * been processed by the hardware --
+ * getting a hardware lock with the
+ * hardware quiescent will ensure
+ * that the buffer has been
+ * processed.
+ */
+ _DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */
+ _DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */
+
+ /* Flags for DMA buffer request */
+ _DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */
+ _DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */
+ _DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */
} drm_dma_flags_t;
+
+/**
+ * DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type.
+ *
+ * \sa drmAddBufs().
+ */
typedef struct drm_buf_desc {
- int count; /* Number of buffers of this size */
- int size; /* Size in bytes */
- int low_mark; /* Low water mark */
- int high_mark; /* High water mark */
+ int count; /**< Number of buffers of this size */
+ int size; /**< Size in bytes */
+ int low_mark; /**< Low water mark */
+ int high_mark; /**< High water mark */
enum {
- _DRM_PAGE_ALIGN = 0x01, /* Align on page boundaries for DMA */
- _DRM_AGP_BUFFER = 0x02, /* Buffer is in agp space */
- _DRM_SG_BUFFER = 0x04 /* Scatter/gather memory buffer */
+ _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
+ _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
+ _DRM_SG_BUFFER = 0x04 /**< Scatter/gather memory buffer */
} flags;
- unsigned long agp_start; /* Start address of where the agp buffers
- * are in the agp aperture */
+ unsigned long agp_start; /**<
+ * Start address of where the AGP buffers are
+ * in the AGP aperture
+ */
} drm_buf_desc_t;
+
+/**
+ * DRM_IOCTL_INFO_BUFS ioctl argument type.
+ */
typedef struct drm_buf_info {
- int count; /* Entries in list */
+ int count; /**< Entries in list */
drm_buf_desc_t *list;
} drm_buf_info_t;
+
+/**
+ * DRM_IOCTL_FREE_BUFS ioctl argument type.
+ */
typedef struct drm_buf_free {
int count;
int *list;
} drm_buf_free_t;
+
+/**
+ * Buffer information
+ *
+ * \sa drm_buf_map.
+ */
typedef struct drm_buf_pub {
- int idx; /* Index into master buflist */
- int total; /* Buffer size */
- int used; /* Amount of buffer in use (for DMA) */
- void *address; /* Address of buffer */
+ int idx; /**< Index into the master buffer list */
+ int total; /**< Buffer size */
+ int used; /**< Amount of buffer in use (for DMA) */
+ void *address; /**< Address of buffer */
} drm_buf_pub_t;
+
+/**
+ * DRM_IOCTL_MAP_BUFS ioctl argument type.
+ */
typedef struct drm_buf_map {
- int count; /* Length of buflist */
- void *virtual; /* Mmaped area in user-virtual */
- drm_buf_pub_t *list; /* Buffer information */
+ int count; /**< Length of the buffer list */
+ void *virtual; /**< Mmap'd area in user-virtual */
+ drm_buf_pub_t *list; /**< Buffer information */
} drm_buf_map_t;
+
+/**
+ * DRM_IOCTL_DMA ioctl argument type.
+ *
+ * Indices here refer to the offset into the buffer list in drm_buf_get.
+ *
+ * \sa drmDMA().
+ */
typedef struct drm_dma {
- /* Indices here refer to the offset into
- buflist in drm_buf_get_t. */
- int context; /* Context handle */
- int send_count; /* Number of buffers to send */
- int *send_indices; /* List of handles to buffers */
- int *send_sizes; /* Lengths of data to send */
- drm_dma_flags_t flags; /* Flags */
- int request_count; /* Number of buffers requested */
- int request_size; /* Desired size for buffers */
- int *request_indices; /* Buffer information */
+ int context; /**< Context handle */
+ int send_count; /**< Number of buffers to send */
+ int *send_indices; /**< List of handles to buffers */
+ int *send_sizes; /**< Lengths of data to send */
+ drm_dma_flags_t flags; /**< Flags */
+ int request_count; /**< Number of buffers requested */
+ int request_size; /**< Desired size for buffers */
+ int *request_indices; /**< Buffer information */
int *request_sizes;
- int granted_count; /* Number of buffers granted */
+ int granted_count; /**< Number of buffers granted */
} drm_dma_t;
+
typedef enum {
_DRM_CONTEXT_PRESERVED = 0x01,
_DRM_CONTEXT_2DONLY = 0x02
} drm_ctx_flags_t;
+
+/**
+ * DRM_IOCTL_ADD_CTX ioctl argument type.
+ *
+ * \sa drmCreateContext() and drmDestroyContext().
+ */
typedef struct drm_ctx {
drm_context_t handle;
drm_ctx_flags_t flags;
} drm_ctx_t;
+
+/**
+ * DRM_IOCTL_RES_CTX ioctl argument type.
+ */
typedef struct drm_ctx_res {
int count;
drm_ctx_t *contexts;
} drm_ctx_res_t;
+
+/**
+ * DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type.
+ */
typedef struct drm_draw {
drm_drawable_t handle;
} drm_draw_t;
+
+/**
+ * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type.
+ */
typedef struct drm_auth {
drm_magic_t magic;
} drm_auth_t;
+
+/**
+ * DRM_IOCTL_IRQ_BUSID ioctl argument type.
+ *
+ * \sa drmGetInterruptFromBusID().
+ */
typedef struct drm_irq_busid {
- int irq;
- int busnum;
- int devnum;
- int funcnum;
+ int irq; /**< IRQ number */
+ int busnum; /**< bus number */
+ int devnum; /**< device number */
+ int funcnum; /**< function number */
} drm_irq_busid_t;
+
typedef enum {
- _DRM_VBLANK_ABSOLUTE = 0x0, /* Wait for specific vblank sequence number */
- _DRM_VBLANK_RELATIVE = 0x1, /* Wait for given number of vblanks */
- _DRM_VBLANK_SIGNAL = 0x40000000 /* Send signal instead of blocking */
+ _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
+ _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
+ _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
} drm_vblank_seq_type_t;
+
#define _DRM_VBLANK_FLAGS_MASK _DRM_VBLANK_SIGNAL
+
struct drm_wait_vblank_request {
drm_vblank_seq_type_t type;
unsigned int sequence;
unsigned long signal;
};
+
struct drm_wait_vblank_reply {
drm_vblank_seq_type_t type;
unsigned int sequence;
@@ -363,29 +511,59 @@ struct drm_wait_vblank_reply {
long tval_usec;
};
+
+/**
+ * DRM_IOCTL_WAIT_VBLANK ioctl argument type.
+ *
+ * \sa drmWaitVBlank().
+ */
typedef union drm_wait_vblank {
struct drm_wait_vblank_request request;
struct drm_wait_vblank_reply reply;
} drm_wait_vblank_t;
+
+/**
+ * DRM_IOCTL_AGP_ENABLE ioctl argument type.
+ *
+ * \sa drmAgpEnable().
+ */
typedef struct drm_agp_mode {
- unsigned long mode;
+ unsigned long mode; /**< AGP mode */
} drm_agp_mode_t;
- /* For drm_agp_alloc -- allocated a buffer */
+
+/**
+ * DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type.
+ *
+ * \sa drmAgpAlloc() and drmAgpFree().
+ */
typedef struct drm_agp_buffer {
- unsigned long size; /* In bytes -- will round to page boundary */
- unsigned long handle; /* Used for BIND/UNBIND ioctls */
- unsigned long type; /* Type of memory to allocate */
- unsigned long physical; /* Physical used by i810 */
+ unsigned long size; /**< In bytes -- will round to page boundary */
+ unsigned long handle; /**< Used for binding / unbinding */
+ unsigned long type; /**< Type of memory to allocate */
+ unsigned long physical; /**< Physical used by i810 */
} drm_agp_buffer_t;
- /* For drm_agp_bind */
+
+/**
+ * DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type.
+ *
+ * \sa drmAgpBind() and drmAgpUnbind().
+ */
typedef struct drm_agp_binding {
- unsigned long handle; /* From drm_agp_buffer */
- unsigned long offset; /* In bytes -- will round to page boundary */
+ unsigned long handle; /**< From drm_agp_buffer */
+ unsigned long offset; /**< In bytes -- will round to page boundary */
} drm_agp_binding_t;
+
+/**
+ * DRM_IOCTL_AGP_INFO ioctl argument type.
+ *
+ * \sa drmAgpVersionMajor(), drmAgpVersionMinor(), drmAgpGetMode(),
+ * drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(),
+ * drmAgpVendorId() and drmAgpDeviceId().
+ */
typedef struct drm_agp_info {
int agp_version_major;
int agp_version_minor;
@@ -400,11 +578,18 @@ typedef struct drm_agp_info {
unsigned short id_device;
} drm_agp_info_t;
+
+/**
+ * DRM_IOCTL_SG_ALLOC ioctl argument type.
+ */
typedef struct drm_scatter_gather {
- unsigned long size; /* In bytes -- will round to page boundary */
- unsigned long handle; /* Used for mapping / unmapping */
+ unsigned long size; /**< In bytes -- will round to page boundary */
+ unsigned long handle; /**< Used for mapping / unmapping */
} drm_scatter_gather_t;
+/**
+ * DRM_IOCTL_SET_VERSION ioctl argument type.
+ */
typedef struct drm_set_version {
int drm_di_major;
int drm_di_minor;
@@ -412,6 +597,7 @@ typedef struct drm_set_version {
int drm_dd_minor;
} drm_set_version_t;
+
#define DRM_IOCTL_BASE 'd'
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
#define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type)
@@ -472,8 +658,13 @@ typedef struct drm_set_version {
#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, drm_wait_vblank_t)
-/* Device specfic ioctls should only be in their respective headers
- * The device specific ioctl range is 0x40 to 0x79. */
+/**
+ * Device specific ioctls should only be in their respective headers
+ * The device specific ioctl range is from 0x40 to 0x79.
+ *
+ * \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and
+ * drmCommandReadWrite().
+ */
#define DRM_COMMAND_BASE 0x40
#endif
diff --git a/sys/dev/drm/drmP.h b/sys/dev/drm/drmP.h
index adf9953..dc1ab7e 100644
--- a/sys/dev/drm/drmP.h
+++ b/sys/dev/drm/drmP.h
@@ -119,6 +119,8 @@ typedef struct drm_file drm_file_t;
#define DRM_MIN(a,b) ((a)<(b)?(a):(b))
#define DRM_MAX(a,b) ((a)>(b)?(a):(b))
+#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
+
#define DRM_GET_PRIV_SAREA(_dev, _ctx, _map) do { \
(_map) = (_dev)->context_sareas[_ctx]; \
} while(0)
@@ -211,6 +213,9 @@ struct drm_file {
drm_magic_t magic;
unsigned long ioctl_count;
struct drm_device *devXX;
+#ifdef DRIVER_FILE_FIELDS
+ DRIVER_FILE_FIELDS;
+#endif
};
typedef struct drm_lock_data {
@@ -314,6 +319,7 @@ struct drm_device {
device_t device; /* Device instance from newbus */
#endif
dev_t devnode; /* Device number for mknod */
+ int if_version; /* Highest interface version set */
int flags; /* Flags to open(2) */
@@ -330,7 +336,6 @@ struct drm_device {
/* Usage Counters */
int open_count; /* Outstanding files open */
int buf_use; /* Buffers in use -- cannot alloc */
- int buf_alloc; /* Buffer allocation in progress */
/* Performance counters */
unsigned long counters;
@@ -354,14 +359,21 @@ struct drm_device {
/* Context support */
int irq; /* Interrupt used by board */
- int irqrid; /* Interrupt used by board */
+ int irq_enabled; /* True if the irq handler is enabled */
#ifdef __FreeBSD__
+ int irqrid; /* Interrupt used by board */
struct resource *irqr; /* Resource for interrupt used by board */
#elif defined(__NetBSD__)
struct pci_attach_args pa;
pci_intr_handle_t ih;
#endif
void *irqh; /* Handle from bus_setup_intr */
+
+ int pci_domain;
+ int pci_bus;
+ int pci_slot;
+ int pci_func;
+
atomic_t context_flag; /* Context swapping flag */
int last_context; /* Last current context */
#if __FreeBSD_version >= 400005
@@ -444,7 +456,7 @@ extern void DRM(reclaim_buffers)(drm_device_t *dev, DRMFILE filp);
#if __HAVE_IRQ
/* IRQ support (drm_irq.h) */
-extern int DRM(irq_install)( drm_device_t *dev, int irq );
+extern int DRM(irq_install)(drm_device_t *dev);
extern int DRM(irq_uninstall)( drm_device_t *dev );
extern irqreturn_t DRM(irq_handler)( DRM_IRQ_ARGS );
extern void DRM(driver_irq_preinstall)( drm_device_t *dev );
@@ -493,7 +505,7 @@ extern int DRM(version)( DRM_IOCTL_ARGS );
extern int DRM(setversion)( DRM_IOCTL_ARGS );
/* Misc. IOCTL support (drm_ioctl.h) */
-extern int DRM(irq_busid)(DRM_IOCTL_ARGS);
+extern int DRM(irq_by_busid)(DRM_IOCTL_ARGS);
extern int DRM(getunique)(DRM_IOCTL_ARGS);
extern int DRM(setunique)(DRM_IOCTL_ARGS);
extern int DRM(getmap)(DRM_IOCTL_ARGS);
diff --git a/sys/dev/drm/drm_bufs.h b/sys/dev/drm/drm_bufs.h
index efb8ce7..5053d36 100644
--- a/sys/dev/drm/drm_bufs.h
+++ b/sys/dev/drm/drm_bufs.h
@@ -137,7 +137,17 @@ int DRM(addmap)( DRM_IOCTL_ARGS )
}
map->offset = (unsigned long)map->handle;
if ( map->flags & _DRM_CONTAINS_LOCK ) {
+ /* Prevent a 2nd X Server from creating a 2nd lock */
+ DRM_LOCK();
+ if (dev->lock.hw_lock != NULL) {
+ DRM_UNLOCK();
+ DRM(free)(map->handle, map->size,
+ DRM_MEM_SAREA);
+ DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
+ return DRM_ERR(EBUSY);
+ }
dev->lock.hw_lock = map->handle; /* Pointer to lock */
+ DRM_UNLOCK();
}
break;
#if __REALLY_HAVE_AGP
diff --git a/sys/dev/drm/drm_drv.h b/sys/dev/drm/drm_drv.h
index 191dc9f..395ba0b 100644
--- a/sys/dev/drm/drm_drv.h
+++ b/sys/dev/drm/drm_drv.h
@@ -102,6 +102,9 @@
#ifndef DRIVER_IOCTLS
#define DRIVER_IOCTLS
#endif
+#ifndef DRIVER_OPEN_HELPER
+#define DRIVER_OPEN_HELPER( priv, dev )
+#endif
#ifndef DRIVER_FOPS
#endif
@@ -132,7 +135,9 @@ static drm_ioctl_desc_t DRM(ioctls)[] = {
[DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { DRM(version), 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { DRM(getunique), 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { DRM(getmagic), 0, 0 },
- [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { DRM(irq_busid), 0, 1 },
+#if __HAVE_IRQ
+ [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { DRM(irq_by_busid), 0, 1 },
+#endif
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { DRM(getmap), 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { DRM(getclient), 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = { DRM(getstats), 0, 0 },
@@ -413,14 +418,15 @@ const char *DRM(find_description)(int vendor, int device) {
return NULL;
}
-/* Initialize the DRM on first open. Called with device's lock held */
+/* Initialize the DRM on first open. */
static int DRM(setup)( drm_device_t *dev )
{
int i;
+ DRM_SPINLOCK_ASSERT(&dev->dev_lock);
+
DRIVER_PRESETUP();
dev->buf_use = 0;
- dev->buf_alloc = 0;
#if __HAVE_DMA
i = DRM(dma_setup)( dev );
@@ -476,9 +482,10 @@ static int DRM(setup)( drm_device_t *dev )
dev->lock.hw_lock = NULL;
dev->lock.lock_queue = 0;
- dev->irq = 0;
+ dev->irq_enabled = 0;
dev->context_flag = 0;
dev->last_context = 0;
+ dev->if_version = 0;
#ifdef __FreeBSD__
dev->buf_sigio = NULL;
@@ -492,9 +499,7 @@ static int DRM(setup)( drm_device_t *dev )
return 0;
}
-/* Free resources associated with the DRM on the last close.
- * Called with the device's lock held.
- */
+/* Free resources associated with the DRM on the last close. */
static int DRM(takedown)( drm_device_t *dev )
{
drm_magic_entry_t *pt, *next;
@@ -502,11 +507,13 @@ static int DRM(takedown)( drm_device_t *dev )
drm_map_list_entry_t *list;
int i;
+ DRM_SPINLOCK_ASSERT(&dev->dev_lock);
+
DRM_DEBUG( "\n" );
DRIVER_PRETAKEDOWN();
#if __HAVE_IRQ
- if (dev->irq != 0)
+ if (dev->irq_enabled)
DRM(irq_uninstall)( dev );
#endif
@@ -643,6 +650,13 @@ static int DRM(init)( device_t nbdev )
unit = minor(dev->device.dv_unit);
#endif
+ dev->irq = pci_get_irq(dev->device);
+ /* XXX Fix domain number (alpha hoses) */
+ dev->pci_domain = 0;
+ dev->pci_bus = pci_get_bus(dev->device);
+ dev->pci_slot = pci_get_slot(dev->device);
+ dev->pci_func = pci_get_function(dev->device);
+
dev->maplist = DRM(calloc)(1, sizeof(*dev->maplist), DRM_MEM_MAPS);
if (dev->maplist == NULL) {
retcode = ENOMEM;
diff --git a/sys/dev/drm/drm_fops.h b/sys/dev/drm/drm_fops.h
index eb44970..190b708 100644
--- a/sys/dev/drm/drm_fops.h
+++ b/sys/dev/drm/drm_fops.h
@@ -34,7 +34,6 @@
#include "dev/drm/drmP.h"
-/* Requires device lock held */
drm_file_t *DRM(find_file_by_proc)(drm_device_t *dev, DRM_STRUCTPROC *p)
{
#if __FreeBSD_version >= 500021
@@ -46,6 +45,8 @@ drm_file_t *DRM(find_file_by_proc)(drm_device_t *dev, DRM_STRUCTPROC *p)
#endif
drm_file_t *priv;
+ DRM_SPINLOCK_ASSERT(&dev->dev_lock);
+
TAILQ_FOREACH(priv, &dev->files, link)
if (priv->pid == pid && priv->uid == uid)
return priv;
@@ -66,7 +67,7 @@ int DRM(open_helper)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p,
DRM_DEBUG("pid = %d, minor = %d\n", DRM_CURRENTPID, m);
DRM_LOCK();
- priv = (drm_file_t *) DRM(find_file_by_proc)(dev, p);
+ priv = DRM(find_file_by_proc)(dev, p);
if (priv) {
priv->refs++;
} else {
@@ -89,6 +90,9 @@ int DRM(open_helper)(dev_t kdev, int flags, int fmt, DRM_STRUCTPROC *p,
priv->devXX = dev;
priv->ioctl_count = 0;
priv->authenticated = !DRM_SUSER(p);
+
+ DRIVER_OPEN_HELPER( priv, dev );
+
TAILQ_INSERT_TAIL(&dev->files, priv, link);
}
DRM_UNLOCK();
diff --git a/sys/dev/drm/drm_ioctl.h b/sys/dev/drm/drm_ioctl.h
index 83953c7..d348519 100644
--- a/sys/dev/drm/drm_ioctl.h
+++ b/sys/dev/drm/drm_ioctl.h
@@ -33,53 +33,6 @@
#include "dev/drm/drmP.h"
-int DRM(irq_busid)( DRM_IOCTL_ARGS )
-{
-#ifdef __FreeBSD__
- drm_irq_busid_t id;
- devclass_t pci;
- device_t bus, dev;
- device_t *kids;
- int error, i, num_kids;
-
- DRM_COPY_FROM_USER_IOCTL( id, (drm_irq_busid_t *)data, sizeof(id) );
-
- pci = devclass_find("pci");
- if (!pci)
- return ENOENT;
- bus = devclass_get_device(pci, id.busnum);
- if (!bus)
- return ENOENT;
- error = device_get_children(bus, &kids, &num_kids);
- if (error)
- return error;
-
- dev = 0;
- for (i = 0; i < num_kids; i++) {
- dev = kids[i];
- if (pci_get_slot(dev) == id.devnum
- && pci_get_function(dev) == id.funcnum)
- break;
- }
-
- free(kids, M_TEMP);
-
- if (i != num_kids)
- id.irq = pci_get_irq(dev);
- else
- id.irq = 0;
- DRM_DEBUG("%d:%d:%d => IRQ %d\n",
- id.busnum, id.devnum, id.funcnum, id.irq);
-
- DRM_COPY_TO_USER_IOCTL( (drm_irq_busid_t *)data, id, sizeof(id) );
-
- return 0;
-#else
- /* don't support interrupt-driven drivers on Net yet */
- return ENOENT;
-#endif
-}
-
/*
* Beginning in revision 1.1 of the DRM interface, getunique will return
* a unique in the form pci:oooo:bb:dd.f (o=domain, b=bus, d=device, f=function)
@@ -110,7 +63,8 @@ int DRM(getunique)( DRM_IOCTL_ARGS )
int DRM(setunique)( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
- drm_unique_t u;
+ drm_unique_t u;
+ int domain, bus, slot, func, ret;
if (dev->unique_len || dev->unique)
return DRM_ERR(EBUSY);
@@ -131,6 +85,21 @@ int DRM(setunique)( DRM_IOCTL_ARGS )
dev->unique[dev->unique_len] = '\0';
+ /* Return error if the busid submitted doesn't match the device's actual
+ * busid.
+ */
+ ret = sscanf(dev->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
+ if (ret != 3)
+ return DRM_ERR(EINVAL);
+ domain = bus >> 8;
+ bus &= 0xff;
+
+ if ((domain != dev->pci_domain) ||
+ (bus != dev->pci_bus) ||
+ (slot != dev->pci_slot) ||
+ (func != dev->pci_func))
+ return DRM_ERR(EINVAL);
+
return 0;
}
@@ -147,10 +116,8 @@ DRM(set_busid)(drm_device_t *dev)
if (dev->unique == NULL)
return ENOMEM;
- /* XXX Fix domain number (alpha hoses) */
snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%1x",
- 0, pci_get_bus(dev->device), pci_get_slot(dev->device),
- pci_get_function(dev->device));
+ dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
return 0;
}
@@ -261,26 +228,31 @@ int DRM(getstats)( DRM_IOCTL_ARGS )
return 0;
}
+#define DRM_IF_MAJOR 1
+#define DRM_IF_MINOR 2
+
int DRM(setversion)(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_set_version_t sv;
drm_set_version_t retv;
+ int if_version;
DRM_COPY_FROM_USER_IOCTL(sv, (drm_set_version_t *)data, sizeof(sv));
- retv.drm_di_major = 1;
- retv.drm_di_minor = 1;
+ retv.drm_di_major = DRM_IF_MAJOR;
+ retv.drm_di_minor = DRM_IF_MINOR;
retv.drm_dd_major = DRIVER_MAJOR;
retv.drm_dd_minor = DRIVER_MINOR;
DRM_COPY_TO_USER_IOCTL((drm_set_version_t *)data, retv, sizeof(sv));
if (sv.drm_di_major != -1) {
- if (sv.drm_di_major != 1 || sv.drm_di_minor < 0)
- return EINVAL;
- if (sv.drm_di_minor > 1)
+ if (sv.drm_di_major != DRM_IF_MAJOR ||
+ sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR)
return EINVAL;
+ if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_dd_minor);
+ dev->if_version = DRM_MAX(if_version, dev->if_version);
if (sv.drm_di_minor >= 1) {
/*
* Version 1.1 includes tying of DRM to specific device
@@ -290,12 +262,11 @@ int DRM(setversion)(DRM_IOCTL_ARGS)
}
if (sv.drm_dd_major != -1) {
- if (sv.drm_dd_major != DRIVER_MAJOR || sv.drm_dd_minor < 0)
- return EINVAL;
- if (sv.drm_dd_minor > DRIVER_MINOR)
+ if (sv.drm_dd_major != DRIVER_MAJOR ||
+ sv.drm_dd_minor < 0 || sv.drm_dd_minor > DRIVER_MINOR)
return EINVAL;
#ifdef DRIVER_SETVERSION
- DRIVER_SETVERSION(dev, sv);
+ DRIVER_SETVERSION(dev, &sv);
#endif
}
return 0;
diff --git a/sys/dev/drm/drm_irq.h b/sys/dev/drm/drm_irq.h
index e062f6c..7275269 100644
--- a/sys/dev/drm/drm_irq.h
+++ b/sys/dev/drm/drm_irq.h
@@ -29,6 +29,29 @@
* $FreeBSD$
*/
+int DRM(irq_by_busid)( DRM_IOCTL_ARGS )
+{
+ DRM_DEVICE;
+ drm_irq_busid_t irq;
+
+ DRM_COPY_FROM_USER_IOCTL(irq, (drm_irq_busid_t *)data, sizeof(irq));
+
+ if ((irq.busnum >> 8) != dev->pci_domain ||
+ (irq.busnum & 0xff) != dev->pci_bus ||
+ irq.devnum != dev->pci_slot ||
+ irq.funcnum != dev->pci_func)
+ return EINVAL;
+
+ irq.irq = dev->irq;
+
+ DRM_DEBUG("%d:%d:%d => IRQ %d\n",
+ irq.busnum, irq.devnum, irq.funcnum, irq.irq);
+
+ DRM_COPY_TO_USER_IOCTL( (drm_irq_busid_t *)data, irq, sizeof(irq) );
+
+ return 0;
+}
+
#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
static irqreturn_t
DRM(irq_handler_wrap)(DRM_IRQ_ARGS)
@@ -41,22 +64,22 @@ DRM(irq_handler_wrap)(DRM_IRQ_ARGS)
}
#endif
-int DRM(irq_install)( drm_device_t *dev, int irq )
+int DRM(irq_install)(drm_device_t *dev)
{
int retcode;
- if ( irq == 0 || dev->dev_private == NULL)
+ if (dev->irq == 0 || dev->dev_private == NULL)
return DRM_ERR(EINVAL);
DRM_LOCK();
- if ( dev->irq ) {
+ if (dev->irq_enabled) {
DRM_UNLOCK();
return DRM_ERR(EBUSY);
}
- dev->irq = irq;
+ dev->irq_enabled = 1;
DRM_UNLOCK();
- DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
+ DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
dev->context_flag = 0;
@@ -69,31 +92,18 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
DRM_SPININIT(dev->irq_lock, "DRM IRQ lock");
-#if __HAVE_VBL_IRQ && 0 /* disabled */
- TAILQ_INIT( &dev->vbl_sig_list );
-#endif
-
/* Before installing handler */
DRM(driver_irq_preinstall)( dev );
/* Install handler */
- dev->irqrid = 0;
#ifdef __FreeBSD__
+ dev->irqrid = 0;
dev->irqr = bus_alloc_resource(dev->device, SYS_RES_IRQ, &dev->irqrid,
0, ~0, 1, RF_SHAREABLE);
if (!dev->irqr) {
-#elif defined(__NetBSD__)
- if (pci_intr_map(&dev->pa, &dev->ih) != 0) {
-#endif
- DRM_LOCK();
- DRM_SPINUNINIT(dev->irq_lock);
- dev->irq = 0;
- dev->irqrid = 0;
- DRM_UNLOCK();
- return ENOENT;
+ retcode = ENOENT;
+ goto err;
}
-
-#ifdef __FreeBSD__
#if __FreeBSD_version < 500000
retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY,
DRM(irq_handler), dev, &dev->irqh);
@@ -101,45 +111,55 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY | INTR_MPSAFE,
DRM(irq_handler_wrap), dev, &dev->irqh);
#endif
- if ( retcode ) {
+ if (retcode != 0)
+ goto err;
#elif defined(__NetBSD__)
+ if (pci_intr_map(&dev->pa, &dev->ih) != 0) {
+ retcode = ENOENT;
+ goto err;
+ }
dev->irqh = pci_intr_establish(&dev->pa.pa_pc, dev->ih, IPL_TTY,
(irqreturn_t (*)(DRM_IRQ_ARGS))DRM(irq_handler), dev);
- if ( !dev->irqh ) {
-#endif
- DRM_LOCK();
-#ifdef __FreeBSD__
- bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid, dev->irqr);
-#endif
- DRM_SPINUNINIT(dev->irq_lock);
- dev->irq = 0;
- dev->irqrid = 0;
- DRM_UNLOCK();
- return retcode;
+ if (!dev->irqh) {
+ retcode = ENOENT;
+ goto err;
}
+#endif
/* After installing handler */
DRM(driver_irq_postinstall)( dev );
return 0;
+err:
+ DRM_LOCK();
+ dev->irq_enabled = 0;
+#ifdef ___FreeBSD__
+ if (dev->irqrid != 0) {
+ bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid,
+ dev->irqr);
+ dev->irqrid = 0;
+ }
+#endif
+ DRM_SPINUNINIT(dev->irq_lock);
+ DRM_UNLOCK();
+ return retcode;
}
+/* XXX: This function needs to be called with the device lock held. In some
+ * cases it isn't, so far.
+ */
int DRM(irq_uninstall)( drm_device_t *dev )
{
- int irq;
int irqrid;
-
- DRM_LOCK();
- irq = dev->irq;
- irqrid = dev->irqrid;
- dev->irq = 0;
- dev->irqrid = 0;
- DRM_UNLOCK();
- if ( !irq )
+ if (!dev->irq_enabled)
return DRM_ERR(EINVAL);
- DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
+ dev->irq_enabled = 0;
+ irqrid = dev->irqrid;
+ dev->irqrid = 0;
+
+ DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
DRM(driver_irq_uninstall)( dev );
@@ -158,14 +178,21 @@ int DRM(control)( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_control_t ctl;
+ int err;
DRM_COPY_FROM_USER_IOCTL( ctl, (drm_control_t *) data, sizeof(ctl) );
switch ( ctl.func ) {
case DRM_INST_HANDLER:
- return DRM(irq_install)( dev, ctl.irq );
+ if (dev->if_version < DRM_IF_VERSION(1, 2) &&
+ ctl.irq != dev->irq)
+ return DRM_ERR(EINVAL);
+ return DRM(irq_install)(dev);
case DRM_UNINST_HANDLER:
- return DRM(irq_uninstall)( dev );
+ DRM_LOCK();
+ err = DRM(irq_uninstall)( dev );
+ DRM_UNLOCK();
+ return err;
default:
return DRM_ERR(EINVAL);
}
@@ -179,7 +206,7 @@ int DRM(wait_vblank)( DRM_IOCTL_ARGS )
struct timeval now;
int ret;
- if (!dev->irq)
+ if (!dev->irq_enabled)
return DRM_ERR(EINVAL);
DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data,
diff --git a/sys/dev/drm/drm_os_freebsd.h b/sys/dev/drm/drm_os_freebsd.h
index de03771..43b6524 100644
--- a/sys/dev/drm/drm_os_freebsd.h
+++ b/sys/dev/drm/drm_os_freebsd.h
@@ -124,6 +124,7 @@
#define DRM_SPINUNINIT(l) mtx_destroy(&l)
#define DRM_SPINLOCK(l) mtx_lock(l)
#define DRM_SPINUNLOCK(u) mtx_unlock(u);
+#define DRM_SPINLOCK_ASSERT(l) mtx_assert(l, MA_OWNED)
#define DRM_CURRENTPID curthread->td_proc->p_pid
#define DRM_LOCK() mtx_lock(&dev->dev_lock)
#define DRM_UNLOCK() mtx_unlock(&dev->dev_lock)
@@ -139,6 +140,7 @@
#define DRM_SPINUNINIT(l)
#define DRM_SPINLOCK(l)
#define DRM_SPINUNLOCK(u)
+#define DRM_SPINLOCK_ASSERT(l)
#define DRM_CURRENTPID curproc->p_pid
#define DRM_LOCK()
#define DRM_UNLOCK()
@@ -269,8 +271,12 @@ for ( ret = 0 ; !ret && !(condition) ; ) { \
(!useracc((caddr_t)uaddr, size, VM_PROT_READ))
#define DRM_COPY_FROM_USER_UNCHECKED(arg1, arg2, arg3) \
copyin(arg2, arg1, arg3)
+#define DRM_COPY_TO_USER_UNCHECKED(arg1, arg2, arg3) \
+ copyout(arg2, arg1, arg3)
#define DRM_GET_USER_UNCHECKED(val, uaddr) \
((val) = fuword(uaddr), 0)
+#define DRM_PUT_USER_UNCHECKED(uaddr, val) \
+ suword(uaddr, val)
/* DRM_READMEMORYBARRIER() prevents reordering of reads.
* DRM_WRITEMEMORYBARRIER() prevents reordering of writes.
diff --git a/sys/dev/drm/mga_dma.c b/sys/dev/drm/mga_dma.c
index 6745d65..01406b5 100644
--- a/sys/dev/drm/mga_dma.c
+++ b/sys/dev/drm/mga_dma.c
@@ -646,7 +646,7 @@ int mga_do_cleanup_dma( drm_device_t *dev )
* may not have been called from userspace and after dev_private
* is freed, it's too late.
*/
- if ( dev->irq ) DRM(irq_uninstall)(dev);
+ if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
#endif
if ( dev->dev_private ) {
diff --git a/sys/dev/drm/r128_cce.c b/sys/dev/drm/r128_cce.c
index 87c4d81..39b37a8 100644
--- a/sys/dev/drm/r128_cce.c
+++ b/sys/dev/drm/r128_cce.c
@@ -601,7 +601,7 @@ int r128_do_cleanup_cce( drm_device_t *dev )
* may not have been called from userspace and after dev_private
* is freed, it's too late.
*/
- if ( dev->irq ) DRM(irq_uninstall)(dev);
+ if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
#endif
if ( dev->dev_private ) {
diff --git a/sys/dev/drm/radeon.h b/sys/dev/drm/radeon.h
index 3dbf9a1..3cdf7fb 100644
--- a/sys/dev/drm/radeon.h
+++ b/sys/dev/drm/radeon.h
@@ -53,7 +53,7 @@
#define DRIVER_DATE "20020828"
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 9
+#define DRIVER_MINOR 10
#define DRIVER_PATCHLEVEL 0
/* Interface history:
@@ -83,6 +83,9 @@
* Add 'GET' queries for starting additional clients on different VT's.
* 1.9 - Add DRM_IOCTL_RADEON_CP_RESUME ioctl.
* Add texture rectangle support for r100.
+ * 1.10- Add SETPARAM ioctl; first parameter to set is FB_LOCATION, which
+ * clients use to tell the DRM where they think the framebuffer is
+ * located in the card's address space
*/
#define DRIVER_IOCTLS \
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 }, \
@@ -108,8 +111,9 @@
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_ALLOC)] = { radeon_mem_alloc, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_FREE)] = { radeon_mem_free, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_INIT_HEAP)] = { radeon_mem_init_heap, 1, 1 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_EMIT)] = { radeon_irq_emit, 1, 0 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_WAIT)] = { radeon_irq_wait, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_EMIT)] = { radeon_irq_emit, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_WAIT)] = { radeon_irq_wait, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_SETPARAM)] = { radeon_cp_setparam, 1, 0 }, \
#define DRIVER_PCI_IDS \
{0x1002, 0x4242, 0, "ATI Radeon BB R200 AIW 8500DV"}, \
@@ -149,6 +153,17 @@
{0x1002, 0x5961, 0, "ATI Radeon RV280 9200"}, \
{0, 0, 0, NULL}
+#define DRIVER_FILE_FIELDS \
+ int64_t radeon_fb_delta; \
+
+#define DRIVER_OPEN_HELPER( filp_priv, dev ) \
+do { \
+ drm_radeon_private_t *dev_priv = dev->dev_private; \
+ if ( dev_priv ) \
+ filp_priv->radeon_fb_delta = dev_priv->fb_location; \
+ else \
+ filp_priv->radeon_fb_delta = 0; \
+} while( 0 )
/* When a client dies:
* - Check for and clean up flipped page state
diff --git a/sys/dev/drm/radeon_cp.c b/sys/dev/drm/radeon_cp.c
index b134f95..6ec65b7 100644
--- a/sys/dev/drm/radeon_cp.c
+++ b/sys/dev/drm/radeon_cp.c
@@ -857,7 +857,8 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev,
/* Initialize the memory controller */
RADEON_WRITE( RADEON_MC_FB_LOCATION,
- (dev_priv->gart_vm_start - 1) & 0xffff0000 );
+ ( ( dev_priv->gart_vm_start - 1 ) & 0xffff0000 )
+ | ( dev_priv->fb_location >> 16 ) );
#if __REALLY_HAVE_AGP
if ( !dev_priv->is_pci ) {
@@ -1073,13 +1074,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
dev_priv->depth_offset = init->depth_offset;
dev_priv->depth_pitch = init->depth_pitch;
- dev_priv->front_pitch_offset = (((dev_priv->front_pitch/64) << 22) |
- (dev_priv->front_offset >> 10));
- dev_priv->back_pitch_offset = (((dev_priv->back_pitch/64) << 22) |
- (dev_priv->back_offset >> 10));
- dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch/64) << 22) |
- (dev_priv->depth_offset >> 10));
-
/* Hardware state for depth clears. Remove this if/when we no
* longer clear the depth buffer with a 3D rectangle. Hard-code
* all values to prevent unwanted 3D state from slipping through
@@ -1206,9 +1200,26 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
dev_priv->buffers->handle );
}
+ dev_priv->fb_location = ( RADEON_READ( RADEON_MC_FB_LOCATION )
+ & 0xffff ) << 16;
+
+ dev_priv->front_pitch_offset = (((dev_priv->front_pitch/64) << 22) |
+ ( ( dev_priv->front_offset
+ + dev_priv->fb_location ) >> 10 ) );
+
+ dev_priv->back_pitch_offset = (((dev_priv->back_pitch/64) << 22) |
+ ( ( dev_priv->back_offset
+ + dev_priv->fb_location ) >> 10 ) );
+
+ dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch/64) << 22) |
+ ( ( dev_priv->depth_offset
+ + dev_priv->fb_location ) >> 10 ) );
+
dev_priv->gart_size = init->gart_size;
- dev_priv->gart_vm_start = RADEON_READ( RADEON_CONFIG_APER_SIZE );
+ dev_priv->gart_vm_start = dev_priv->fb_location
+ + RADEON_READ( RADEON_CONFIG_APER_SIZE );
+
#if __REALLY_HAVE_AGP
if ( !dev_priv->is_pci )
dev_priv->gart_buffers_offset = (dev_priv->buffers->offset
@@ -1278,7 +1289,7 @@ int radeon_do_cleanup_cp( drm_device_t *dev )
* may not have been called from userspace and after dev_private
* is freed, it's too late.
*/
- if ( dev->irq ) DRM(irq_uninstall)(dev);
+ if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
#endif
if ( dev->dev_private ) {
diff --git a/sys/dev/drm/radeon_drm.h b/sys/dev/drm/radeon_drm.h
index 3bf4877..bd4dde3 100644
--- a/sys/dev/drm/radeon_drm.h
+++ b/sys/dev/drm/radeon_drm.h
@@ -392,6 +392,7 @@ typedef struct {
#define DRM_IOCTL_RADEON_IRQ_WAIT DRM_IOW( 0x57, drm_radeon_irq_wait_t)
/* added by Charl P. Botha - see radeon_cp.c for details */
#define DRM_IOCTL_RADEON_CP_RESUME DRM_IO(0x58)
+#define DRM_IOCTL_RADEON_SETPARAM DRM_IOW(0x59, drm_radeon_setparam_t)
typedef struct drm_radeon_init {
enum {
@@ -504,7 +505,7 @@ typedef struct drm_radeon_tex_image {
} drm_radeon_tex_image_t;
typedef struct drm_radeon_texture {
- int offset;
+ unsigned int offset;
int pitch;
int format;
int width; /* Texture image coordinates */
@@ -539,6 +540,7 @@ typedef struct drm_radeon_indirect {
#define RADEON_PARAM_STATUS_HANDLE 8
#define RADEON_PARAM_SAREA_HANDLE 9
#define RADEON_PARAM_GART_TEX_HANDLE 10
+#define RADEON_PARAM_SCRATCH_OFFSET 11
typedef struct drm_radeon_getparam {
int param;
@@ -580,4 +582,16 @@ typedef struct drm_radeon_irq_wait {
} drm_radeon_irq_wait_t;
+/* 1.10: Clients tell the DRM where they think the framebuffer is located in
+ * the card's address space, via a new generic ioctl to set parameters
+ */
+
+typedef struct drm_radeon_setparam {
+ unsigned int param;
+ int64_t value;
+} drm_radeon_setparam_t;
+
+#define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */
+
+
#endif
diff --git a/sys/dev/drm/radeon_drv.h b/sys/dev/drm/radeon_drv.h
index 1e9d2af..6a04349 100644
--- a/sys/dev/drm/radeon_drv.h
+++ b/sys/dev/drm/radeon_drv.h
@@ -75,6 +75,8 @@ typedef struct drm_radeon_private {
drm_radeon_ring_buffer_t ring;
drm_radeon_sarea_t *sarea_priv;
+ u32 fb_location;
+
int gart_size;
u32 gart_vm_start;
unsigned long gart_buffers_offset;
@@ -186,6 +188,7 @@ extern int radeon_cp_indirect( DRM_IOCTL_ARGS );
extern int radeon_cp_vertex2( DRM_IOCTL_ARGS );
extern int radeon_cp_cmdbuf( DRM_IOCTL_ARGS );
extern int radeon_cp_getparam( DRM_IOCTL_ARGS );
+extern int radeon_cp_setparam( DRM_IOCTL_ARGS );
extern int radeon_cp_flip( DRM_IOCTL_ARGS );
extern int radeon_mem_alloc( DRM_IOCTL_ARGS );
@@ -241,6 +244,7 @@ extern void radeon_do_release(drm_device_t *dev);
#define RADEON_CRTC2_OFFSET 0x0324
#define RADEON_CRTC2_OFFSET_CNTL 0x0328
+#define RADEON_RB3D_COLOROFFSET 0x1c40
#define RADEON_RB3D_COLORPITCH 0x1c48
#define RADEON_DP_GUI_MASTER_CNTL 0x146c
@@ -334,6 +338,7 @@ extern void radeon_do_release(drm_device_t *dev);
#define RADEON_PP_MISC 0x1c14
#define RADEON_PP_ROT_MATRIX_0 0x1d58
#define RADEON_PP_TXFILTER_0 0x1c54
+#define RADEON_PP_TXOFFSET_0 0x1c5c
#define RADEON_PP_TXFILTER_1 0x1c6c
#define RADEON_PP_TXFILTER_2 0x1c84
diff --git a/sys/dev/drm/radeon_state.c b/sys/dev/drm/radeon_state.c
index cbeeedd..eb3cf20 100644
--- a/sys/dev/drm/radeon_state.c
+++ b/sys/dev/drm/radeon_state.c
@@ -38,6 +38,151 @@
/* ================================================================
+ * Helper functions for client state checking and fixup
+ */
+
+static __inline__ int radeon_check_and_fixup_offset( drm_radeon_private_t *dev_priv,
+ drm_file_t *filp_priv,
+ u32 *offset ) {
+ u32 off = *offset;
+
+ if ( off >= dev_priv->fb_location &&
+ off < ( dev_priv->gart_vm_start + dev_priv->gart_size ) )
+ return 0;
+
+ off += filp_priv->radeon_fb_delta;
+
+ DRM_DEBUG( "offset fixed up to 0x%x\n", off );
+
+ if ( off < dev_priv->fb_location ||
+ off >= ( dev_priv->gart_vm_start + dev_priv->gart_size ) )
+ return DRM_ERR( EINVAL );
+
+ *offset = off;
+
+ return 0;
+}
+
+static __inline__ int radeon_check_and_fixup_offset_user( drm_radeon_private_t *dev_priv,
+ drm_file_t *filp_priv,
+ u32 *offset ) {
+ u32 off;
+
+ DRM_GET_USER_UNCHECKED( off, offset );
+
+ if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &off ) )
+ return DRM_ERR( EINVAL );
+
+ DRM_PUT_USER_UNCHECKED( offset, off );
+
+ return 0;
+}
+
+static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_priv,
+ drm_file_t *filp_priv,
+ int id,
+ u32 *data ) {
+ if ( id == RADEON_EMIT_PP_MISC &&
+ radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
+ &data[( RADEON_RB3D_DEPTHOFFSET
+ - RADEON_PP_MISC ) / 4] ) ) {
+ DRM_ERROR( "Invalid depth buffer offset\n" );
+ return DRM_ERR( EINVAL );
+ } else if ( id == RADEON_EMIT_PP_CNTL &&
+ radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
+ &data[( RADEON_RB3D_COLOROFFSET
+ - RADEON_PP_CNTL ) / 4] ) ) {
+ DRM_ERROR( "Invalid colour buffer offset\n" );
+ return DRM_ERR( EINVAL );
+ } else if ( id >= R200_EMIT_PP_TXOFFSET_0 &&
+ id <= R200_EMIT_PP_TXOFFSET_5 &&
+ radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
+ &data[0] ) ) {
+ DRM_ERROR( "Invalid R200 texture offset\n" );
+ return DRM_ERR( EINVAL );
+ } else if ( ( id == RADEON_EMIT_PP_TXFILTER_0 || id == RADEON_EMIT_PP_TXFILTER_1 ||
+ id == RADEON_EMIT_PP_TXFILTER_2 /*|| id == RADEON_EMIT_PP_TXFILTER_3 ||
+ id == RADEON_EMIT_PP_TXFILTER_4 || id == RADEON_EMIT_PP_TXFILTER_5*/ ) &&
+ radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
+ &data[( RADEON_PP_TXOFFSET_0
+ - RADEON_PP_TXFILTER_0 ) / 4] ) ) {
+ DRM_ERROR( "Invalid R100 texture offset\n" );
+ return DRM_ERR( EINVAL );
+ } else if ( id == R200_PP_CUBIC_OFFSET_F1_0 || id == R200_PP_CUBIC_OFFSET_F1_1 ||
+ id == R200_PP_CUBIC_OFFSET_F1_2 || id == R200_PP_CUBIC_OFFSET_F1_3 ||
+ id == R200_PP_CUBIC_OFFSET_F1_4 || id == R200_PP_CUBIC_OFFSET_F1_5 ) {
+ int i;
+ for ( i = 0; i < 6; i++ ) {
+ if ( radeon_check_and_fixup_offset_user( dev_priv,
+ filp_priv,
+ &data[i] ) ) {
+ DRM_ERROR( "Invalid R200 cubic texture offset\n" );
+ return DRM_ERR( EINVAL );
+ }
+ }
+ }
+
+ return 0;
+}
+
+static __inline__ int radeon_check_and_fixup_packet3( drm_radeon_private_t *dev_priv,
+ drm_file_t *filp_priv,
+ drm_radeon_cmd_buffer_t *cmdbuf,
+ unsigned int *cmdsz ) {
+ u32 tmp[4], *cmd = ( u32* )cmdbuf->buf;
+
+ if ( DRM_COPY_FROM_USER_UNCHECKED( tmp, cmd, sizeof( tmp ) ) ) {
+ DRM_ERROR( "Failed to copy data from user space\n" );
+ return DRM_ERR( EFAULT );
+ }
+
+ *cmdsz = 2 + ( ( tmp[0] & RADEON_CP_PACKET_COUNT_MASK ) >> 16 );
+
+ if ( ( tmp[0] & 0xc0000000 ) != RADEON_CP_PACKET3 ) {
+ DRM_ERROR( "Not a type 3 packet\n" );
+ return DRM_ERR( EINVAL );
+ }
+
+ if ( 4 * *cmdsz > cmdbuf->bufsz ) {
+ DRM_ERROR( "Packet size larger than size of data provided\n" );
+ return DRM_ERR( EINVAL );
+ }
+
+ /* Check client state and fix it up if necessary */
+ if ( tmp[0] & 0x8000 ) { /* MSB of opcode: next DWORD GUI_CNTL */
+ u32 offset;
+
+ if ( tmp[1] & ( RADEON_GMC_SRC_PITCH_OFFSET_CNTL
+ | RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) {
+ offset = tmp[2] << 10;
+ if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &offset ) ) {
+ DRM_ERROR( "Invalid first packet offset\n" );
+ return DRM_ERR( EINVAL );
+ }
+ tmp[2] = ( tmp[2] & 0xffc00000 ) | offset >> 10;
+ }
+
+ if ( ( tmp[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL ) &&
+ ( tmp[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) {
+ offset = tmp[3] << 10;
+ if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &offset ) ) {
+ DRM_ERROR( "Invalid second packet offset\n" );
+ return DRM_ERR( EINVAL );
+ }
+ tmp[3] = ( tmp[3] & 0xffc00000 ) | offset >> 10;
+ }
+
+ if ( DRM_COPY_TO_USER_UNCHECKED( cmd, tmp, sizeof( tmp ) ) ) {
+ DRM_ERROR( "Failed to copy data to user space\n" );
+ return DRM_ERR( EFAULT );
+ }
+ }
+
+ return 0;
+}
+
+
+/* ================================================================
* CP hardware state programming functions
*/
@@ -59,15 +204,28 @@ static __inline__ void radeon_emit_clip_rect( drm_radeon_private_t *dev_priv,
/* Emit 1.1 state
*/
-static void radeon_emit_state( drm_radeon_private_t *dev_priv,
- drm_radeon_context_regs_t *ctx,
- drm_radeon_texture_regs_t *tex,
- unsigned int dirty )
+static int radeon_emit_state( drm_radeon_private_t *dev_priv,
+ drm_file_t *filp_priv,
+ drm_radeon_context_regs_t *ctx,
+ drm_radeon_texture_regs_t *tex,
+ unsigned int dirty )
{
RING_LOCALS;
DRM_DEBUG( "dirty=0x%08x\n", dirty );
if ( dirty & RADEON_UPLOAD_CONTEXT ) {
+ if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+ &ctx->rb3d_depthoffset ) ) {
+ DRM_ERROR( "Invalid depth buffer offset\n" );
+ return DRM_ERR( EINVAL );
+ }
+
+ if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+ &ctx->rb3d_coloroffset ) ) {
+ DRM_ERROR( "Invalid depth buffer offset\n" );
+ return DRM_ERR( EINVAL );
+ }
+
BEGIN_RING( 14 );
OUT_RING( CP_PACKET0( RADEON_PP_MISC, 6 ) );
OUT_RING( ctx->pp_misc );
@@ -151,6 +309,12 @@ static void radeon_emit_state( drm_radeon_private_t *dev_priv,
}
if ( dirty & RADEON_UPLOAD_TEX0 ) {
+ if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+ &tex[0].pp_txoffset ) ) {
+ DRM_ERROR( "Invalid texture offset for unit 0\n" );
+ return DRM_ERR( EINVAL );
+ }
+
BEGIN_RING( 9 );
OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_0, 5 ) );
OUT_RING( tex[0].pp_txfilter );
@@ -165,6 +329,12 @@ static void radeon_emit_state( drm_radeon_private_t *dev_priv,
}
if ( dirty & RADEON_UPLOAD_TEX1 ) {
+ if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+ &tex[1].pp_txoffset ) ) {
+ DRM_ERROR( "Invalid texture offset for unit 1\n" );
+ return DRM_ERR( EINVAL );
+ }
+
BEGIN_RING( 9 );
OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_1, 5 ) );
OUT_RING( tex[1].pp_txfilter );
@@ -179,6 +349,12 @@ static void radeon_emit_state( drm_radeon_private_t *dev_priv,
}
if ( dirty & RADEON_UPLOAD_TEX2 ) {
+ if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+ &tex[2].pp_txoffset ) ) {
+ DRM_ERROR( "Invalid texture offset for unit 2\n" );
+ return DRM_ERR( EINVAL );
+ }
+
BEGIN_RING( 9 );
OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_2, 5 ) );
OUT_RING( tex[2].pp_txfilter );
@@ -191,12 +367,15 @@ static void radeon_emit_state( drm_radeon_private_t *dev_priv,
OUT_RING( tex[2].pp_border_color );
ADVANCE_RING();
}
+
+ return 0;
}
/* Emit 1.2 state
*/
-static void radeon_emit_state2( drm_radeon_private_t *dev_priv,
- drm_radeon_state_t *state )
+static int radeon_emit_state2( drm_radeon_private_t *dev_priv,
+ drm_file_t *filp_priv,
+ drm_radeon_state_t *state )
{
RING_LOCALS;
@@ -208,7 +387,7 @@ static void radeon_emit_state2( drm_radeon_private_t *dev_priv,
ADVANCE_RING();
}
- radeon_emit_state( dev_priv, &state->context,
+ return radeon_emit_state( dev_priv, filp_priv, &state->context,
state->tex, state->dirty );
}
@@ -1067,6 +1246,7 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
drm_radeon_tex_image_t *image )
{
drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_file_t *filp_priv;
drm_buf_t *buf;
u32 format;
u32 *buffer;
@@ -1076,6 +1256,13 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
int i;
RING_LOCALS;
+ DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
+ if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &tex->offset ) ) {
+ DRM_ERROR( "Invalid destination offset\n" );
+ return DRM_ERR( EINVAL );
+ }
+
dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD;
/* Flush the pixel cache. This ensures no pixel data gets mixed
@@ -1379,6 +1566,7 @@ int radeon_cp_vertex( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_file_t *filp_priv;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_device_dma_t *dma = dev->dma;
drm_buf_t *buf;
@@ -1392,6 +1580,8 @@ int radeon_cp_vertex( DRM_IOCTL_ARGS )
return DRM_ERR(EINVAL);
}
+ DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex_t *)data,
sizeof(vertex) );
@@ -1431,11 +1621,14 @@ int radeon_cp_vertex( DRM_IOCTL_ARGS )
buf->used = vertex.count; /* not used? */
if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
- radeon_emit_state( dev_priv,
- &sarea_priv->context_state,
- sarea_priv->tex_state,
- sarea_priv->dirty );
-
+ if ( radeon_emit_state( dev_priv, filp_priv,
+ &sarea_priv->context_state,
+ sarea_priv->tex_state,
+ sarea_priv->dirty ) ) {
+ DRM_ERROR( "radeon_emit_state failed\n" );
+ return DRM_ERR( EINVAL );
+ }
+
sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
RADEON_UPLOAD_TEX1IMAGES |
RADEON_UPLOAD_TEX2IMAGES |
@@ -1463,6 +1656,7 @@ int radeon_cp_indices( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_file_t *filp_priv;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_device_dma_t *dma = dev->dma;
drm_buf_t *buf;
@@ -1477,6 +1671,8 @@ int radeon_cp_indices( DRM_IOCTL_ARGS )
return DRM_ERR(EINVAL);
}
+ DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
DRM_COPY_FROM_USER_IOCTL( elts, (drm_radeon_indices_t *)data,
sizeof(elts) );
@@ -1525,10 +1721,13 @@ int radeon_cp_indices( DRM_IOCTL_ARGS )
buf->used = elts.end;
if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
- radeon_emit_state( dev_priv,
- &sarea_priv->context_state,
- sarea_priv->tex_state,
- sarea_priv->dirty );
+ if ( radeon_emit_state( dev_priv, filp_priv,
+ &sarea_priv->context_state,
+ sarea_priv->tex_state,
+ sarea_priv->dirty ) ) {
+ DRM_ERROR( "radeon_emit_state failed\n" );
+ return DRM_ERR( EINVAL );
+ }
sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
RADEON_UPLOAD_TEX1IMAGES |
@@ -1688,6 +1887,7 @@ int radeon_cp_vertex2( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_file_t *filp_priv;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_device_dma_t *dma = dev->dma;
drm_buf_t *buf;
@@ -1702,6 +1902,8 @@ int radeon_cp_vertex2( DRM_IOCTL_ARGS )
return DRM_ERR(EINVAL);
}
+ DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex2_t *)data,
sizeof(vertex) );
@@ -1749,7 +1951,10 @@ int radeon_cp_vertex2( DRM_IOCTL_ARGS )
sizeof(state) ) )
return DRM_ERR(EFAULT);
- radeon_emit_state2( dev_priv, &state );
+ if ( radeon_emit_state2( dev_priv, filp_priv, &state ) ) {
+ DRM_ERROR( "radeon_emit_state2 failed\n" );
+ return DRM_ERR( EINVAL );
+ }
laststate = prim.stateidx;
}
@@ -1786,6 +1991,7 @@ int radeon_cp_vertex2( DRM_IOCTL_ARGS )
static int radeon_emit_packets(
drm_radeon_private_t *dev_priv,
+ drm_file_t *filp_priv,
drm_radeon_cmd_header_t header,
drm_radeon_cmd_buffer_t *cmdbuf )
{
@@ -1800,8 +2006,15 @@ static int radeon_emit_packets(
sz = packet[id].len;
reg = packet[id].start;
- if (sz * sizeof(int) > cmdbuf->bufsz)
+ if (sz * sizeof(int) > cmdbuf->bufsz) {
+ DRM_ERROR( "Packet size provided larger than data provided\n" );
return DRM_ERR(EINVAL);
+ }
+
+ if ( radeon_check_and_fixup_packets( dev_priv, filp_priv, id, data ) ) {
+ DRM_ERROR( "Packet verification failed\n" );
+ return DRM_ERR( EINVAL );
+ }
BEGIN_RING(sz+1);
OUT_RING( CP_PACKET0( reg, (sz-1) ) );
@@ -1884,24 +2097,21 @@ static __inline__ int radeon_emit_vectors(
static int radeon_emit_packet3( drm_device_t *dev,
+ drm_file_t *filp_priv,
drm_radeon_cmd_buffer_t *cmdbuf )
{
drm_radeon_private_t *dev_priv = dev->dev_private;
- int cmdsz, tmp;
- int *cmd = (int *)cmdbuf->buf;
+ unsigned int cmdsz;
+ int *cmd = (int *)cmdbuf->buf, ret;
RING_LOCALS;
-
DRM_DEBUG("\n");
- if (DRM_GET_USER_UNCHECKED( tmp, &cmd[0]))
- return DRM_ERR(EFAULT);
-
- cmdsz = 2 + ((tmp & RADEON_CP_PACKET_COUNT_MASK) >> 16);
-
- if ((tmp & 0xc0000000) != RADEON_CP_PACKET3 ||
- cmdsz * 4 > cmdbuf->bufsz)
- return DRM_ERR(EINVAL);
+ if ( ( ret = radeon_check_and_fixup_packet3( dev_priv, filp_priv,
+ cmdbuf, &cmdsz ) ) ) {
+ DRM_ERROR( "Packet verification failed\n" );
+ return ret;
+ }
BEGIN_RING( cmdsz );
OUT_RING_USER_TABLE( cmd, cmdsz );
@@ -1914,27 +2124,25 @@ static int radeon_emit_packet3( drm_device_t *dev,
static int radeon_emit_packet3_cliprect( drm_device_t *dev,
+ drm_file_t *filp_priv,
drm_radeon_cmd_buffer_t *cmdbuf,
int orig_nbox )
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_clip_rect_t box;
- int cmdsz, tmp;
- int *cmd = (int *)cmdbuf->buf;
+ unsigned int cmdsz;
+ int *cmd = (int *)cmdbuf->buf, ret;
drm_clip_rect_t *boxes = cmdbuf->boxes;
int i = 0;
RING_LOCALS;
DRM_DEBUG("\n");
- if (DRM_GET_USER_UNCHECKED( tmp, &cmd[0]))
- return DRM_ERR(EFAULT);
-
- cmdsz = 2 + ((tmp & RADEON_CP_PACKET_COUNT_MASK) >> 16);
-
- if ((tmp & 0xc0000000) != RADEON_CP_PACKET3 ||
- cmdsz * 4 > cmdbuf->bufsz)
- return DRM_ERR(EINVAL);
+ if ( ( ret = radeon_check_and_fixup_packet3( dev_priv, filp_priv,
+ cmdbuf, &cmdsz ) ) ) {
+ DRM_ERROR( "Packet verification failed\n" );
+ return ret;
+ }
if (!orig_nbox)
goto out;
@@ -2011,6 +2219,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_file_t *filp_priv;
drm_device_dma_t *dma = dev->dma;
drm_buf_t *buf = 0;
int idx;
@@ -2025,6 +2234,8 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
return DRM_ERR(EINVAL);
}
+ DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
DRM_COPY_FROM_USER_IOCTL( cmdbuf, (drm_radeon_cmd_buffer_t *)data,
sizeof(cmdbuf) );
@@ -2055,7 +2266,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
switch (header.header.cmd_type) {
case RADEON_CMD_PACKET:
DRM_DEBUG("RADEON_CMD_PACKET\n");
- if (radeon_emit_packets( dev_priv, header, &cmdbuf )) {
+ if (radeon_emit_packets( dev_priv, filp_priv, header, &cmdbuf )) {
DRM_ERROR("radeon_emit_packets failed\n");
return DRM_ERR(EINVAL);
}
@@ -2098,7 +2309,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
case RADEON_CMD_PACKET3:
DRM_DEBUG("RADEON_CMD_PACKET3\n");
- if (radeon_emit_packet3( dev, &cmdbuf )) {
+ if (radeon_emit_packet3( dev, filp_priv, &cmdbuf )) {
DRM_ERROR("radeon_emit_packet3 failed\n");
return DRM_ERR(EINVAL);
}
@@ -2106,7 +2317,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
case RADEON_CMD_PACKET3_CLIP:
DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n");
- if (radeon_emit_packet3_cliprect( dev, &cmdbuf, orig_nbox )) {
+ if (radeon_emit_packet3_cliprect( dev, filp_priv, &cmdbuf, orig_nbox )) {
DRM_ERROR("radeon_emit_packet3_clip failed\n");
return DRM_ERR(EINVAL);
}
@@ -2205,3 +2416,31 @@ int radeon_cp_getparam( DRM_IOCTL_ARGS )
return 0;
}
+
+int radeon_cp_setparam( DRM_IOCTL_ARGS ) {
+ DRM_DEVICE;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ drm_file_t *filp_priv;
+ drm_radeon_setparam_t sp;
+
+ if ( !dev_priv ) {
+ DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+ return DRM_ERR( EINVAL );
+ }
+
+ DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
+
+ DRM_COPY_FROM_USER_IOCTL( sp, ( drm_radeon_setparam_t* )data,
+ sizeof( sp ) );
+
+ switch( sp.param ) {
+ case RADEON_SETPARAM_FB_LOCATION:
+ filp_priv->radeon_fb_delta = dev_priv->fb_location - sp.value;
+ break;
+ default:
+ DRM_DEBUG( "Invalid parameter %d\n", sp.param );
+ return DRM_ERR( EINVAL );
+ }
+
+ return 0;
+}
OpenPOWER on IntegriCloud