Home | History | Annotate | Line # | Download | only in dist
      1 /**
      2  * \file xf86drm.h
      3  * OS-independent header for DRM user-level library interface.
      4  *
      5  * \author Rickard E. (Rik) Faith <faith (at) valinux.com>
      6  */
      7 
      8 /*
      9  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
     10  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
     11  * All Rights Reserved.
     12  *
     13  * Permission is hereby granted, free of charge, to any person obtaining a
     14  * copy of this software and associated documentation files (the "Software"),
     15  * to deal in the Software without restriction, including without limitation
     16  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     17  * and/or sell copies of the Software, and to permit persons to whom the
     18  * Software is furnished to do so, subject to the following conditions:
     19  *
     20  * The above copyright notice and this permission notice (including the next
     21  * paragraph) shall be included in all copies or substantial portions of the
     22  * Software.
     23  *
     24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     25  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     26  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     27  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     28  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     29  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     30  * DEALINGS IN THE SOFTWARE.
     31  *
     32  */
     33 
     34 #ifndef _XF86DRM_H_
     35 #define _XF86DRM_H_
     36 
     37 #include <stdarg.h>
     38 #if 1
     39 #include <sys/atomic.h>
     40 #else
     41 #include <sys/types.h>
     42 #endif
     43 #include <stdint.h>
     44 #include <drm.h>
     45 
     46 #if defined(__cplusplus)
     47 extern "C" {
     48 #endif
     49 
     50 #ifndef DRM_MAX_MINOR
     51 #define DRM_MAX_MINOR   64 /* deprecated */
     52 #endif
     53 
     54 #if defined(__linux__)
     55 
     56 #define DRM_IOCTL_NR(n)		_IOC_NR(n)
     57 #define DRM_IOC_VOID		_IOC_NONE
     58 #define DRM_IOC_READ		_IOC_READ
     59 #define DRM_IOC_WRITE		_IOC_WRITE
     60 #define DRM_IOC_READWRITE	_IOC_READ|_IOC_WRITE
     61 #define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
     62 
     63 #else /* One of the *BSDs */
     64 
     65 #include <sys/ioccom.h>
     66 #define DRM_IOCTL_NR(n)         ((n) & 0xff)
     67 #define DRM_IOC_VOID            IOC_VOID
     68 #define DRM_IOC_READ            IOC_OUT
     69 #define DRM_IOC_WRITE           IOC_IN
     70 #define DRM_IOC_READWRITE       IOC_INOUT
     71 #define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
     72 
     73 #endif
     74 
     75 				/* Defaults, if nothing set in xf86config */
     76 #define DRM_DEV_UID	 0
     77 #define DRM_DEV_GID	 0
     78 /* Default /dev/dri directory permissions 0755 */
     79 #define DRM_DEV_DIRMODE	 	\
     80 	(S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
     81 #define DRM_DEV_MODE	 (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
     82 
     83 #ifdef __OpenBSD__
     84 #define DRM_DIR_NAME  "/dev"
     85 #define DRM_PRIMARY_MINOR_NAME  "drm"
     86 #define DRM_CONTROL_MINOR_NAME  "drmC" /* deprecated */
     87 #define DRM_RENDER_MINOR_NAME   "drmR"
     88 #else
     89 #define DRM_DIR_NAME  "/dev/dri"
     90 #define DRM_PRIMARY_MINOR_NAME  "card"
     91 #define DRM_CONTROL_MINOR_NAME  "controlD" /* deprecated */
     92 #define DRM_RENDER_MINOR_NAME   "renderD"
     93 #define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */
     94 #endif
     95 
     96 #define DRM_DEV_NAME          "%s/" DRM_PRIMARY_MINOR_NAME "%d"
     97 #define DRM_CONTROL_DEV_NAME  "%s/" DRM_CONTROL_MINOR_NAME "%d" /* deprecated */
     98 #define DRM_RENDER_DEV_NAME   "%s/" DRM_RENDER_MINOR_NAME  "%d"
     99 
    100 #define DRM_NODE_NAME_MAX \
    101     (sizeof(DRM_DIR_NAME) + 1 /* slash */ \
    102      + MAX3(sizeof(DRM_PRIMARY_MINOR_NAME), \
    103             sizeof(DRM_CONTROL_MINOR_NAME), \
    104             sizeof(DRM_RENDER_MINOR_NAME)) \
    105      + sizeof("1048575") /* highest possible node number 2^MINORBITS - 1 */ \
    106      + 1) /* NULL-terminator */
    107 
    108 #define DRM_ERR_NO_DEVICE  (-1001)
    109 #define DRM_ERR_NO_ACCESS  (-1002)
    110 #define DRM_ERR_NOT_ROOT   (-1003)
    111 #define DRM_ERR_INVALID    (-1004)
    112 #define DRM_ERR_NO_FD      (-1005)
    113 
    114 #define DRM_AGP_NO_HANDLE 0
    115 
    116 typedef unsigned int  drmSize,     *drmSizePtr;	    /**< For mapped regions */
    117 typedef void          *drmAddress, **drmAddressPtr; /**< For mapped regions */
    118 
    119 #if (__GNUC__ >= 3)
    120 #define DRM_PRINTFLIKE(f, a) __attribute__ ((format(__printf__, f, a)))
    121 #else
    122 #define DRM_PRINTFLIKE(f, a)
    123 #endif
    124 
    125 typedef struct _drmServerInfo {
    126   int (*debug_print)(const char *format, va_list ap) DRM_PRINTFLIKE(1,0);
    127   int (*load_module)(const char *name);
    128   void (*get_perms)(gid_t *, mode_t *);
    129 } drmServerInfo, *drmServerInfoPtr;
    130 
    131 typedef struct drmHashEntry {
    132     int      fd;
    133     void     (*f)(int, void *, void *);
    134     void     *tagTable;
    135 } drmHashEntry;
    136 
    137 extern int drmIoctl(int fd, unsigned long request, void *arg);
    138 extern void *drmGetHashTable(void);
    139 extern drmHashEntry *drmGetEntry(int fd);
    140 
    141 /**
    142  * Driver version information.
    143  *
    144  * \sa drmGetVersion() and drmSetVersion().
    145  */
    146 typedef struct _drmVersion {
    147     int     version_major;        /**< Major version */
    148     int     version_minor;        /**< Minor version */
    149     int     version_patchlevel;   /**< Patch level */
    150     int     name_len; 	          /**< Length of name buffer */
    151     char    *name;	          /**< Name of driver */
    152     int     date_len;             /**< Length of date buffer */
    153     char    *date;                /**< User-space buffer to hold date */
    154     int     desc_len;	          /**< Length of desc buffer */
    155     char    *desc;                /**< User-space buffer to hold desc */
    156 } drmVersion, *drmVersionPtr;
    157 
    158 typedef struct _drmStats {
    159     unsigned long count;	     /**< Number of data */
    160     struct {
    161 	unsigned long value;	     /**< Value from kernel */
    162 	const char    *long_format;  /**< Suggested format for long_name */
    163 	const char    *long_name;    /**< Long name for value */
    164 	const char    *rate_format;  /**< Suggested format for rate_name */
    165 	const char    *rate_name;    /**< Short name for value per second */
    166 	int           isvalue;       /**< True if value (vs. counter) */
    167 	const char    *mult_names;   /**< Multiplier names (e.g., "KGM") */
    168 	int           mult;          /**< Multiplier value (e.g., 1024) */
    169 	int           verbose;       /**< Suggest only in verbose output */
    170     } data[15];
    171 } drmStatsT;
    172 
    173 
    174 				/* All of these enums *MUST* match with the
    175                                    kernel implementation -- so do *NOT*
    176                                    change them!  (The drmlib implementation
    177                                    will just copy the flags instead of
    178                                    translating them.) */
    179 typedef enum {
    180     DRM_FRAME_BUFFER    = 0,      /**< WC, no caching, no core dump */
    181     DRM_REGISTERS       = 1,      /**< no caching, no core dump */
    182     DRM_SHM             = 2,      /**< shared, cached */
    183     DRM_AGP             = 3,	  /**< AGP/GART */
    184     DRM_SCATTER_GATHER  = 4,	  /**< PCI scatter/gather */
    185     DRM_CONSISTENT      = 5	  /**< PCI consistent */
    186 } drmMapType;
    187 
    188 typedef enum {
    189     DRM_RESTRICTED      = 0x0001, /**< Cannot be mapped to client-virtual */
    190     DRM_READ_ONLY       = 0x0002, /**< Read-only in client-virtual */
    191     DRM_LOCKED          = 0x0004, /**< Physical pages locked */
    192     DRM_KERNEL          = 0x0008, /**< Kernel requires access */
    193     DRM_WRITE_COMBINING = 0x0010, /**< Use write-combining, if available */
    194     DRM_CONTAINS_LOCK   = 0x0020, /**< SHM page that contains lock */
    195     DRM_REMOVABLE	= 0x0040  /**< Removable mapping */
    196 } drmMapFlags;
    197 
    198 /**
    199  * \warning These values *MUST* match drm.h
    200  */
    201 typedef enum {
    202     /** \name Flags for DMA buffer dispatch */
    203     /*@{*/
    204     DRM_DMA_BLOCK        = 0x01, /**<
    205 				  * Block until buffer dispatched.
    206 				  *
    207 				  * \note the buffer may not yet have been
    208 				  * processed by the hardware -- getting a
    209 				  * hardware lock with the hardware quiescent
    210 				  * will ensure that the buffer has been
    211 				  * processed.
    212 				  */
    213     DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */
    214     DRM_DMA_PRIORITY     = 0x04, /**< High priority dispatch */
    215     /*@}*/
    216 
    217     /** \name Flags for DMA buffer request */
    218     /*@{*/
    219     DRM_DMA_WAIT         = 0x10, /**< Wait for free buffers */
    220     DRM_DMA_SMALLER_OK   = 0x20, /**< Smaller-than-requested buffers OK */
    221     DRM_DMA_LARGER_OK    = 0x40  /**< Larger-than-requested buffers OK */
    222     /*@}*/
    223 } drmDMAFlags;
    224 
    225 typedef enum {
    226     DRM_PAGE_ALIGN       = 0x01,
    227     DRM_AGP_BUFFER       = 0x02,
    228     DRM_SG_BUFFER        = 0x04,
    229     DRM_FB_BUFFER        = 0x08,
    230     DRM_PCI_BUFFER_RO    = 0x10
    231 } drmBufDescFlags;
    232 
    233 typedef enum {
    234     DRM_LOCK_READY      = 0x01, /**< Wait until hardware is ready for DMA */
    235     DRM_LOCK_QUIESCENT  = 0x02, /**< Wait until hardware quiescent */
    236     DRM_LOCK_FLUSH      = 0x04, /**< Flush this context's DMA queue first */
    237     DRM_LOCK_FLUSH_ALL  = 0x08, /**< Flush all DMA queues first */
    238 				/* These *HALT* flags aren't supported yet
    239                                    -- they will be used to support the
    240                                    full-screen DGA-like mode. */
    241     DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */
    242     DRM_HALT_CUR_QUEUES = 0x20  /**< Halt all current queues */
    243 } drmLockFlags;
    244 
    245 typedef enum {
    246     DRM_CONTEXT_PRESERVED = 0x01, /**< This context is preserved and
    247 				     never swapped. */
    248     DRM_CONTEXT_2DONLY    = 0x02  /**< This context is for 2D rendering only. */
    249 } drm_context_tFlags, *drm_context_tFlagsPtr;
    250 
    251 typedef struct _drmBufDesc {
    252     int              count;	  /**< Number of buffers of this size */
    253     int              size;	  /**< Size in bytes */
    254     int              low_mark;	  /**< Low water mark */
    255     int              high_mark;	  /**< High water mark */
    256 } drmBufDesc, *drmBufDescPtr;
    257 
    258 typedef struct _drmBufInfo {
    259     int              count;	  /**< Number of buffers described in list */
    260     drmBufDescPtr    list;	  /**< List of buffer descriptions */
    261 } drmBufInfo, *drmBufInfoPtr;
    262 
    263 typedef struct _drmBuf {
    264     int              idx;	  /**< Index into the master buffer list */
    265     int              total;	  /**< Buffer size */
    266     int              used;	  /**< Amount of buffer in use (for DMA) */
    267     drmAddress       address;	  /**< Address */
    268 } drmBuf, *drmBufPtr;
    269 
    270 /**
    271  * Buffer mapping information.
    272  *
    273  * Used by drmMapBufs() and drmUnmapBufs() to store information about the
    274  * mapped buffers.
    275  */
    276 typedef struct _drmBufMap {
    277     int              count;	  /**< Number of buffers mapped */
    278     drmBufPtr        list;	  /**< Buffers */
    279 } drmBufMap, *drmBufMapPtr;
    280 
    281 typedef struct _drmLock {
    282     volatile unsigned int lock;
    283     char                      padding[60];
    284     /* This is big enough for most current (and future?) architectures:
    285        DEC Alpha:              32 bytes
    286        Intel Merced:           ?
    287        Intel P5/PPro/PII/PIII: 32 bytes
    288        Intel StrongARM:        32 bytes
    289        Intel i386/i486:        16 bytes
    290        MIPS:                   32 bytes (?)
    291        Motorola 68k:           16 bytes
    292        Motorola PowerPC:       32 bytes
    293        Sun SPARC:              32 bytes
    294     */
    295 } drmLock, *drmLockPtr;
    296 
    297 /**
    298  * Indices here refer to the offset into
    299  * list in drmBufInfo
    300  */
    301 typedef struct _drmDMAReq {
    302     drm_context_t    context;  	  /**< Context handle */
    303     int           send_count;     /**< Number of buffers to send */
    304     int           *send_list;     /**< List of handles to buffers */
    305     int           *send_sizes;    /**< Lengths of data to send, in bytes */
    306     drmDMAFlags   flags;          /**< Flags */
    307     int           request_count;  /**< Number of buffers requested */
    308     int           request_size;	  /**< Desired size of buffers requested */
    309     int           *request_list;  /**< Buffer information */
    310     int           *request_sizes; /**< Minimum acceptable sizes */
    311     int           granted_count;  /**< Number of buffers granted at this size */
    312 } drmDMAReq, *drmDMAReqPtr;
    313 
    314 typedef struct _drmRegion {
    315     drm_handle_t     handle;
    316     unsigned int  offset;
    317     drmSize       size;
    318     drmAddress    map;
    319 } drmRegion, *drmRegionPtr;
    320 
    321 typedef struct _drmTextureRegion {
    322     unsigned char next;
    323     unsigned char prev;
    324     unsigned char in_use;
    325     unsigned char padding;	/**< Explicitly pad this out */
    326     unsigned int  age;
    327 } drmTextureRegion, *drmTextureRegionPtr;
    328 
    329 
    330 typedef enum {
    331     DRM_VBLANK_ABSOLUTE = 0x0,	/**< Wait for specific vblank sequence number */
    332     DRM_VBLANK_RELATIVE = 0x1,	/**< Wait for given number of vblanks */
    333     /* bits 1-6 are reserved for high crtcs */
    334     DRM_VBLANK_HIGH_CRTC_MASK = 0x0000003e,
    335     DRM_VBLANK_EVENT = 0x4000000,	/**< Send event instead of blocking */
    336     DRM_VBLANK_FLIP = 0x8000000,	/**< Scheduled buffer swap should flip */
    337     DRM_VBLANK_NEXTONMISS = 0x10000000,	/**< If missed, wait for next vblank */
    338     DRM_VBLANK_SECONDARY = 0x20000000,	/**< Secondary display controller */
    339     DRM_VBLANK_SIGNAL   = 0x40000000	/* Send signal instead of blocking */
    340 } drmVBlankSeqType;
    341 #define DRM_VBLANK_HIGH_CRTC_SHIFT 1
    342 
    343 typedef struct _drmVBlankReq {
    344 	drmVBlankSeqType type;
    345 	unsigned int sequence;
    346 	unsigned long signal;
    347 } drmVBlankReq, *drmVBlankReqPtr;
    348 
    349 typedef struct _drmVBlankReply {
    350 	drmVBlankSeqType type;
    351 	unsigned int sequence;
    352 	long tval_sec;
    353 	long tval_usec;
    354 } drmVBlankReply, *drmVBlankReplyPtr;
    355 
    356 typedef union _drmVBlank {
    357 	drmVBlankReq request;
    358 	drmVBlankReply reply;
    359 } drmVBlank, *drmVBlankPtr;
    360 
    361 typedef struct _drmSetVersion {
    362 	int drm_di_major;
    363 	int drm_di_minor;
    364 	int drm_dd_major;
    365 	int drm_dd_minor;
    366 } drmSetVersion, *drmSetVersionPtr;
    367 
    368 #define __drm_dummy_lock(lock) (*(__volatile__ unsigned int *)lock)
    369 
    370 #define DRM_LOCK_HELD  0x80000000U /**< Hardware lock is held */
    371 #define DRM_LOCK_CONT  0x40000000U /**< Hardware lock is contended */
    372 
    373 #if 1
    374 
    375 #define DRM_CAS(lock, old, new, __ret)	\
    376  (__ret = atomic_cas_uint(&__drm_dummy_lock(lock), (old), (new)) != (old));
    377 
    378 #elif defined(__GNUC__) && (__GNUC__ >= 2)
    379 # if defined(__i386) || defined(__AMD64__) || defined(__x86_64__) || defined(__amd64__)
    380 				/* Reflect changes here to drmP.h */
    381 #define DRM_CAS(lock,old,new,__ret)                                    \
    382 	do {                                                           \
    383                 int __dummy;	/* Can't mark eax as clobbered */      \
    384 		__asm__ __volatile__(                                  \
    385 			"lock ; cmpxchg %4,%1\n\t"                     \
    386                         "setnz %0"                                     \
    387 			: "=d" (__ret),                                \
    388    			  "=m" (__drm_dummy_lock(lock)),               \
    389                           "=a" (__dummy)                               \
    390 			: "2" (old),                                   \
    391 			  "r" (new));                                  \
    392 	} while (0)
    393 
    394 #elif defined(__alpha__)
    395 
    396 #define	DRM_CAS(lock, old, new, ret)		\
    397 	do {					\
    398 		int tmp, old32;			\
    399 		__asm__ __volatile__(		\
    400 		"	addl	$31, %5, %3\n"	\
    401 		"1:	ldl_l	%0, %2\n"	\
    402 		"	cmpeq	%0, %3, %1\n"	\
    403 		"	beq	%1, 2f\n"	\
    404 		"	mov	%4, %0\n"	\
    405 		"	stl_c	%0, %2\n"	\
    406 		"	beq	%0, 3f\n"	\
    407 		"	mb\n"			\
    408 		"2:	cmpeq	%1, 0, %1\n"	\
    409 		".subsection 2\n"		\
    410 		"3:	br	1b\n"		\
    411 		".previous"			\
    412 		: "=&r"(tmp), "=&r"(ret),	\
    413 		  "=m"(__drm_dummy_lock(lock)),	\
    414 		  "=&r"(old32)			\
    415 		: "r"(new), "r"(old)		\
    416 		: "memory");			\
    417 	} while (0)
    418 
    419 #elif defined(__sparc__)
    420 
    421 #define DRM_CAS(lock,old,new,__ret)				\
    422 do {	register unsigned int __old __asm("o0");		\
    423 	register unsigned int __new __asm("o1");		\
    424 	register volatile unsigned int *__lock __asm("o2");	\
    425 	__old = old;						\
    426 	__new = new;						\
    427 	__lock = (volatile unsigned int *)lock;			\
    428 	__asm__ __volatile__(					\
    429 		/*"cas [%2], %3, %0"*/				\
    430 		".word 0xd3e29008\n\t"				\
    431 		/*"membar #StoreStore | #StoreLoad"*/		\
    432 		".word 0x8143e00a"				\
    433 		: "=&r" (__new)					\
    434 		: "0" (__new),					\
    435 		  "r" (__lock),					\
    436 		  "r" (__old)					\
    437 		: "memory");					\
    438 	__ret = (__new != __old);				\
    439 } while(0)
    440 
    441 #elif defined(__ia64__)
    442 
    443 #ifdef __INTEL_COMPILER
    444 /* this currently generates bad code (missing stop bits)... */
    445 #include <ia64intrin.h>
    446 
    447 #define DRM_CAS(lock,old,new,__ret)					      \
    448 	do {								      \
    449 		unsigned long __result, __old = (old) & 0xffffffff;		\
    450 		__mf();							      	\
    451 		__result = _InterlockedCompareExchange_acq(&__drm_dummy_lock(lock), (new), __old);\
    452 		__ret = (__result) != (__old);					\
    453 /*		__ret = (__sync_val_compare_and_swap(&__drm_dummy_lock(lock), \
    454 						     (old), (new))	      \
    455 			 != (old));					      */\
    456 	} while (0)
    457 
    458 #else
    459 #define DRM_CAS(lock,old,new,__ret)					  \
    460 	do {								  \
    461 		unsigned int __result, __old = (old);			  \
    462 		__asm__ __volatile__(					  \
    463 			"mf\n"						  \
    464 			"mov ar.ccv=%2\n"				  \
    465 			";;\n"						  \
    466 			"cmpxchg4.acq %0=%1,%3,ar.ccv"			  \
    467 			: "=r" (__result), "=m" (__drm_dummy_lock(lock))  \
    468 			: "r" ((unsigned long)__old), "r" (new)			  \
    469 			: "memory");					  \
    470 		__ret = (__result) != (__old);				  \
    471 	} while (0)
    472 
    473 #endif
    474 
    475 #elif defined(__powerpc__)
    476 
    477 #define DRM_CAS(lock,old,new,__ret)			\
    478 	do {						\
    479 		__asm__ __volatile__(			\
    480 			"sync;"				\
    481 			"0:    lwarx %0,0,%1;"		\
    482 			"      xor. %0,%3,%0;"		\
    483 			"      bne 1f;"			\
    484 			"      stwcx. %2,0,%1;"		\
    485 			"      bne- 0b;"		\
    486 			"1:    "			\
    487 			"sync;"				\
    488 		: "=&r"(__ret)				\
    489 		: "r"(lock), "r"(new), "r"(old)		\
    490 		: "cr0", "memory");			\
    491 	} while (0)
    492 
    493 # elif defined (__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
    494 	|| defined (__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \
    495 	|| defined (__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) \
    496 	|| defined (__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
    497 	|| defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
    498 	|| defined(__ARM_ARCH_7EM__)
    499        /* excluding ARMv4/ARMv5 and lower (lacking ldrex/strex support) */
    500        #undef DRM_DEV_MODE
    501        #define DRM_DEV_MODE     (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
    502 
    503        #define DRM_CAS(lock,old,new,__ret)             \
    504        do {                                            \
    505                __asm__ __volatile__ (                  \
    506                        "1: ldrex %0, [%1]\n"           \
    507                        "   teq %0, %2\n"               \
    508                        "   ite eq\n"                   \
    509                        "   strexeq %0, %3, [%1]\n"     \
    510                        "   movne   %0, #1\n"           \
    511                : "=&r" (__ret)                         \
    512                : "r" (lock), "r" (old), "r" (new)      \
    513                : "cc","memory");                       \
    514        } while (0)
    515 
    516 #endif /* architecture */
    517 #endif /* __GNUC__ >= 2 */
    518 
    519 #ifndef DRM_CAS
    520 #define DRM_CAS(lock,old,new,ret) do { ret=1; } while (0) /* FAST LOCK FAILS */
    521 #endif
    522 
    523 #if defined(__alpha__)
    524 #define DRM_CAS_RESULT(_result)		long _result
    525 #elif defined(__powerpc__)
    526 #define DRM_CAS_RESULT(_result)		int _result
    527 #else
    528 #define DRM_CAS_RESULT(_result)		char _result
    529 #endif
    530 
    531 #define DRM_LIGHT_LOCK(fd,lock,context)                                \
    532 	do {                                                           \
    533                 DRM_CAS_RESULT(__ret);                                 \
    534 		DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret);     \
    535                 if (__ret) drmGetLock(fd,context,0);                   \
    536         } while(0)
    537 
    538 				/* This one counts fast locks -- for
    539                                    benchmarking only. */
    540 #define DRM_LIGHT_LOCK_COUNT(fd,lock,context,count)                    \
    541 	do {                                                           \
    542                 DRM_CAS_RESULT(__ret);                                 \
    543 		DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret);     \
    544                 if (__ret) drmGetLock(fd,context,0);                   \
    545                 else       ++count;                                    \
    546         } while(0)
    547 
    548 #define DRM_LOCK(fd,lock,context,flags)                                \
    549 	do {                                                           \
    550 		if (flags) drmGetLock(fd,context,flags);               \
    551 		else       DRM_LIGHT_LOCK(fd,lock,context);            \
    552 	} while(0)
    553 
    554 #define DRM_UNLOCK(fd,lock,context)                                    \
    555 	do {                                                           \
    556                 DRM_CAS_RESULT(__ret);                                 \
    557 		DRM_CAS(lock,DRM_LOCK_HELD|context,context,__ret);     \
    558                 if (__ret) drmUnlock(fd,context);                      \
    559         } while(0)
    560 
    561 				/* Simple spin locks */
    562 #define DRM_SPINLOCK(spin,val)                                         \
    563 	do {                                                           \
    564             DRM_CAS_RESULT(__ret);                                     \
    565 	    do {                                                       \
    566 		DRM_CAS(spin,0,val,__ret);                             \
    567 		if (__ret) while ((spin)->lock);                       \
    568 	    } while (__ret);                                           \
    569 	} while(0)
    570 
    571 #define DRM_SPINLOCK_TAKE(spin,val)                                    \
    572 	do {                                                           \
    573             DRM_CAS_RESULT(__ret);                                     \
    574             int  cur;                                                  \
    575 	    do {                                                       \
    576                 cur = (*spin).lock;                                    \
    577 		DRM_CAS(spin,cur,val,__ret);                           \
    578 	    } while (__ret);                                           \
    579 	} while(0)
    580 
    581 #define DRM_SPINLOCK_COUNT(spin,val,count,__ret)                       \
    582 	do {                                                           \
    583             int  __i;                                                  \
    584             __ret = 1;                                                 \
    585             for (__i = 0; __ret && __i < count; __i++) {               \
    586 		DRM_CAS(spin,0,val,__ret);                             \
    587 		if (__ret) for (;__i < count && (spin)->lock; __i++);  \
    588 	    }                                                          \
    589 	} while(0)
    590 
    591 #define DRM_SPINUNLOCK(spin,val)                                       \
    592 	do {                                                           \
    593             DRM_CAS_RESULT(__ret);                                     \
    594             if ((*spin).lock == val) { /* else server stole lock */    \
    595 	        do {                                                   \
    596 		    DRM_CAS(spin,val,0,__ret);                         \
    597 	        } while (__ret);                                       \
    598             }                                                          \
    599 	} while(0)
    600 
    601 
    602 
    603 /* General user-level programmer's API: unprivileged */
    604 extern int           drmAvailable(void);
    605 extern int           drmOpen(const char *name, const char *busid);
    606 
    607 #define DRM_NODE_PRIMARY 0
    608 #define DRM_NODE_CONTROL 1 /* deprecated: never returned */
    609 #define DRM_NODE_RENDER  2
    610 #define DRM_NODE_MAX     3
    611 
    612 extern int           drmOpenWithType(const char *name, const char *busid,
    613                                      int type);
    614 
    615 extern int           drmOpenControl(int minor); /* deprecated: always fails */
    616 extern int           drmOpenRender(int minor);
    617 extern int           drmClose(int fd);
    618 extern drmVersionPtr drmGetVersion(int fd);
    619 extern drmVersionPtr drmGetLibVersion(int fd);
    620 extern int           drmGetCap(int fd, uint64_t capability, uint64_t *value);
    621 extern void          drmFreeVersion(drmVersionPtr);
    622 extern int           drmGetMagic(int fd, drm_magic_t * magic);
    623 extern char          *drmGetBusid(int fd);
    624 extern int           drmGetInterruptFromBusID(int fd, int busnum, int devnum,
    625 					      int funcnum);
    626 extern int           drmGetMap(int fd, int idx, drm_handle_t *offset,
    627 			       drmSize *size, drmMapType *type,
    628 			       drmMapFlags *flags, drm_handle_t *handle,
    629 			       int *mtrr);
    630 extern int           drmGetClient(int fd, int idx, int *auth, int *pid,
    631 				  int *uid, unsigned long *magic,
    632 				  unsigned long *iocs);
    633 extern int           drmGetStats(int fd, drmStatsT *stats);
    634 extern int           drmSetInterfaceVersion(int fd, drmSetVersion *version);
    635 extern int           drmCommandNone(int fd, unsigned long drmCommandIndex);
    636 extern int           drmCommandRead(int fd, unsigned long drmCommandIndex,
    637                                     void *data, unsigned long size);
    638 extern int           drmCommandWrite(int fd, unsigned long drmCommandIndex,
    639                                      void *data, unsigned long size);
    640 extern int           drmCommandWriteRead(int fd, unsigned long drmCommandIndex,
    641                                          void *data, unsigned long size);
    642 
    643 /* General user-level programmer's API: X server (root) only  */
    644 extern void          drmFreeBusid(const char *busid);
    645 extern int           drmSetBusid(int fd, const char *busid);
    646 extern int           drmAuthMagic(int fd, drm_magic_t magic);
    647 extern int           drmAddMap(int fd,
    648 			       drm_handle_t offset,
    649 			       drmSize size,
    650 			       drmMapType type,
    651 			       drmMapFlags flags,
    652 			       drm_handle_t * handle);
    653 extern int	     drmRmMap(int fd, drm_handle_t handle);
    654 extern int	     drmAddContextPrivateMapping(int fd, drm_context_t ctx_id,
    655 						 drm_handle_t handle);
    656 
    657 extern int           drmAddBufs(int fd, int count, int size,
    658 				drmBufDescFlags flags,
    659 				int agp_offset);
    660 extern int           drmMarkBufs(int fd, double low, double high);
    661 extern int           drmCreateContext(int fd, drm_context_t * handle);
    662 extern int           drmSetContextFlags(int fd, drm_context_t context,
    663 					drm_context_tFlags flags);
    664 extern int           drmGetContextFlags(int fd, drm_context_t context,
    665 					drm_context_tFlagsPtr flags);
    666 extern int           drmAddContextTag(int fd, drm_context_t context, void *tag);
    667 extern int           drmDelContextTag(int fd, drm_context_t context);
    668 extern void          *drmGetContextTag(int fd, drm_context_t context);
    669 extern drm_context_t * drmGetReservedContextList(int fd, int *count);
    670 extern void          drmFreeReservedContextList(drm_context_t *);
    671 extern int           drmSwitchToContext(int fd, drm_context_t context);
    672 extern int           drmDestroyContext(int fd, drm_context_t handle);
    673 extern int           drmCreateDrawable(int fd, drm_drawable_t * handle);
    674 extern int           drmDestroyDrawable(int fd, drm_drawable_t handle);
    675 extern int           drmUpdateDrawableInfo(int fd, drm_drawable_t handle,
    676 					   drm_drawable_info_type_t type,
    677 					   unsigned int num, void *data);
    678 extern int           drmCtlInstHandler(int fd, int irq);
    679 extern int           drmCtlUninstHandler(int fd);
    680 extern int           drmSetClientCap(int fd, uint64_t capability,
    681 				     uint64_t value);
    682 
    683 extern int           drmCrtcGetSequence(int fd, uint32_t crtcId,
    684 					uint64_t *sequence, uint64_t *ns);
    685 extern int           drmCrtcQueueSequence(int fd, uint32_t crtcId,
    686 					  uint32_t flags, uint64_t sequence,
    687 					  uint64_t *sequence_queued,
    688 					  uint64_t user_data);
    689 /* General user-level programmer's API: authenticated client and/or X */
    690 extern int           drmMap(int fd,
    691 			    drm_handle_t handle,
    692 			    drmSize size,
    693 			    drmAddressPtr address);
    694 extern int           drmUnmap(drmAddress address, drmSize size);
    695 extern drmBufInfoPtr drmGetBufInfo(int fd);
    696 extern drmBufMapPtr  drmMapBufs(int fd);
    697 extern int           drmUnmapBufs(drmBufMapPtr bufs);
    698 extern int           drmDMA(int fd, drmDMAReqPtr request);
    699 extern int           drmFreeBufs(int fd, int count, int *list);
    700 extern int           drmGetLock(int fd,
    701 			        drm_context_t context,
    702 			        drmLockFlags flags);
    703 extern int           drmUnlock(int fd, drm_context_t context);
    704 extern int           drmFinish(int fd, int context, drmLockFlags flags);
    705 extern int	     drmGetContextPrivateMapping(int fd, drm_context_t ctx_id,
    706 						 drm_handle_t * handle);
    707 
    708 /* AGP/GART support: X server (root) only */
    709 extern int           drmAgpAcquire(int fd);
    710 extern int           drmAgpRelease(int fd);
    711 extern int           drmAgpEnable(int fd, unsigned long mode);
    712 extern int           drmAgpAlloc(int fd, unsigned long size,
    713 				 unsigned long type, unsigned long *address,
    714 				 drm_handle_t *handle);
    715 extern int           drmAgpFree(int fd, drm_handle_t handle);
    716 extern int 	     drmAgpBind(int fd, drm_handle_t handle,
    717 				unsigned long offset);
    718 extern int           drmAgpUnbind(int fd, drm_handle_t handle);
    719 
    720 /* AGP/GART info: authenticated client and/or X */
    721 extern int           drmAgpVersionMajor(int fd);
    722 extern int           drmAgpVersionMinor(int fd);
    723 extern unsigned long drmAgpGetMode(int fd);
    724 extern unsigned long drmAgpBase(int fd); /* Physical location */
    725 extern unsigned long drmAgpSize(int fd); /* Bytes */
    726 extern unsigned long drmAgpMemoryUsed(int fd);
    727 extern unsigned long drmAgpMemoryAvail(int fd);
    728 extern unsigned int  drmAgpVendorId(int fd);
    729 extern unsigned int  drmAgpDeviceId(int fd);
    730 
    731 /* PCI scatter/gather support: X server (root) only */
    732 extern int           drmScatterGatherAlloc(int fd, unsigned long size,
    733 					   drm_handle_t *handle);
    734 extern int           drmScatterGatherFree(int fd, drm_handle_t handle);
    735 
    736 extern int           drmWaitVBlank(int fd, drmVBlankPtr vbl);
    737 
    738 /* Support routines */
    739 extern void          drmSetServerInfo(drmServerInfoPtr info);
    740 extern int           drmError(int err, const char *label);
    741 extern void          *drmMalloc(int size);
    742 extern void          drmFree(void *pt);
    743 
    744 /* Hash table routines */
    745 extern void *drmHashCreate(void);
    746 extern int  drmHashDestroy(void *t);
    747 extern int  drmHashLookup(void *t, unsigned long key, void **value);
    748 extern int  drmHashInsert(void *t, unsigned long key, void *value);
    749 extern int  drmHashDelete(void *t, unsigned long key);
    750 extern int  drmHashFirst(void *t, unsigned long *key, void **value);
    751 extern int  drmHashNext(void *t, unsigned long *key, void **value);
    752 
    753 /* PRNG routines */
    754 extern void          *drmRandomCreate(unsigned long seed);
    755 extern int           drmRandomDestroy(void *state);
    756 extern unsigned long drmRandom(void *state);
    757 extern double        drmRandomDouble(void *state);
    758 
    759 /* Skip list routines */
    760 
    761 extern void *drmSLCreate(void);
    762 extern int  drmSLDestroy(void *l);
    763 extern int  drmSLLookup(void *l, unsigned long key, void **value);
    764 extern int  drmSLInsert(void *l, unsigned long key, void *value);
    765 extern int  drmSLDelete(void *l, unsigned long key);
    766 extern int  drmSLNext(void *l, unsigned long *key, void **value);
    767 extern int  drmSLFirst(void *l, unsigned long *key, void **value);
    768 extern void drmSLDump(void *l);
    769 extern int  drmSLLookupNeighbors(void *l, unsigned long key,
    770 				 unsigned long *prev_key, void **prev_value,
    771 				 unsigned long *next_key, void **next_value);
    772 
    773 extern int drmOpenOnce(void *unused, const char *BusID, int *newlyopened);
    774 extern int drmOpenOnceWithType(const char *BusID, int *newlyopened, int type);
    775 extern void drmCloseOnce(int fd);
    776 extern void drmMsg(const char *format, ...) DRM_PRINTFLIKE(1, 2);
    777 
    778 extern int drmSetMaster(int fd);
    779 extern int drmDropMaster(int fd);
    780 extern int drmIsMaster(int fd);
    781 
    782 #define DRM_EVENT_CONTEXT_VERSION 4
    783 
    784 typedef struct _drmEventContext {
    785 
    786 	/* This struct is versioned so we can add more pointers if we
    787 	 * add more events. */
    788 	int version;
    789 
    790 	void (*vblank_handler)(int fd,
    791 			       unsigned int sequence,
    792 			       unsigned int tv_sec,
    793 			       unsigned int tv_usec,
    794 			       void *user_data);
    795 
    796 	void (*page_flip_handler)(int fd,
    797 				  unsigned int sequence,
    798 				  unsigned int tv_sec,
    799 				  unsigned int tv_usec,
    800 				  void *user_data);
    801 
    802 	void (*page_flip_handler2)(int fd,
    803 				   unsigned int sequence,
    804 				   unsigned int tv_sec,
    805 				   unsigned int tv_usec,
    806 				   unsigned int crtc_id,
    807 				   void *user_data);
    808 
    809 	void (*sequence_handler)(int fd,
    810 				 uint64_t sequence,
    811 				 uint64_t ns,
    812 				 uint64_t user_data);
    813 } drmEventContext, *drmEventContextPtr;
    814 
    815 extern int drmHandleEvent(int fd, drmEventContextPtr evctx);
    816 
    817 extern char *drmGetDeviceNameFromFd(int fd);
    818 
    819 /* Improved version of drmGetDeviceNameFromFd which attributes for any type of
    820  * device/node - card or renderD.
    821  */
    822 extern char *drmGetDeviceNameFromFd2(int fd);
    823 extern int drmGetNodeTypeFromFd(int fd);
    824 
    825 /* Convert between GEM handles and DMA-BUF file descriptors.
    826  *
    827  * Warning: since GEM handles are not reference-counted and are unique per
    828  * DRM file description, the caller is expected to perform its own reference
    829  * counting. drmPrimeFDToHandle is guaranteed to return the same handle for
    830  * different FDs if they reference the same underlying buffer object. This
    831  * could even be a buffer object originally created on the same DRM FD.
    832  *
    833  * When sharing a DRM FD with an API such as EGL or GBM, the caller must not
    834  * use drmPrimeHandleToFD nor drmPrimeFDToHandle. A single user-space
    835  * reference-counting implementation is necessary to avoid double-closing GEM
    836  * handles.
    837  *
    838  * Two processes can't share the same DRM FD and both use it to create or
    839  * import GEM handles, even when using a single user-space reference-counting
    840  * implementation like GBM, because GBM doesn't share its state between
    841  * processes.
    842  */
    843 extern int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd);
    844 extern int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle);
    845 
    846 extern int drmCloseBufferHandle(int fd, uint32_t handle);
    847 
    848 extern char *drmGetPrimaryDeviceNameFromFd(int fd);
    849 extern char *drmGetRenderDeviceNameFromFd(int fd);
    850 
    851 #define DRM_BUS_PCI       0
    852 #define DRM_BUS_USB       1
    853 #define DRM_BUS_PLATFORM  2
    854 #define DRM_BUS_HOST1X    3
    855 #define DRM_BUS_FAUX      4
    856 
    857 typedef struct _drmPciBusInfo {
    858     uint16_t domain;
    859     uint8_t bus;
    860     uint8_t dev;
    861     uint8_t func;
    862 } drmPciBusInfo, *drmPciBusInfoPtr;
    863 
    864 typedef struct _drmPciDeviceInfo {
    865     uint16_t vendor_id;
    866     uint16_t device_id;
    867     uint16_t subvendor_id;
    868     uint16_t subdevice_id;
    869     uint8_t revision_id;
    870 } drmPciDeviceInfo, *drmPciDeviceInfoPtr;
    871 
    872 typedef struct _drmUsbBusInfo {
    873     uint8_t bus;
    874     uint8_t dev;
    875 } drmUsbBusInfo, *drmUsbBusInfoPtr;
    876 
    877 typedef struct _drmUsbDeviceInfo {
    878     uint16_t vendor;
    879     uint16_t product;
    880 } drmUsbDeviceInfo, *drmUsbDeviceInfoPtr;
    881 
    882 #define DRM_PLATFORM_DEVICE_NAME_LEN 512
    883 
    884 typedef struct _drmPlatformBusInfo {
    885     char fullname[DRM_PLATFORM_DEVICE_NAME_LEN];
    886 } drmPlatformBusInfo, *drmPlatformBusInfoPtr;
    887 
    888 typedef struct _drmPlatformDeviceInfo {
    889     char **compatible; /* NULL terminated list of compatible strings */
    890 } drmPlatformDeviceInfo, *drmPlatformDeviceInfoPtr;
    891 
    892 #define DRM_HOST1X_DEVICE_NAME_LEN 512
    893 
    894 typedef struct _drmHost1xBusInfo {
    895     char fullname[DRM_HOST1X_DEVICE_NAME_LEN];
    896 } drmHost1xBusInfo, *drmHost1xBusInfoPtr;
    897 
    898 typedef struct _drmHost1xDeviceInfo {
    899     char **compatible; /* NULL terminated list of compatible strings */
    900 } drmHost1xDeviceInfo, *drmHost1xDeviceInfoPtr;
    901 
    902 #define DRM_FAUX_DEVICE_NAME_LEN 512
    903 
    904 typedef struct _drmFauxBusInfo {
    905     char name[DRM_FAUX_DEVICE_NAME_LEN];
    906 } drmFauxBusInfo, *drmFauxBusInfoPtr;
    907 
    908 typedef struct _drmDevice {
    909     char **nodes; /* DRM_NODE_MAX sized array */
    910     int available_nodes; /* DRM_NODE_* bitmask */
    911     int bustype;
    912     union {
    913         drmPciBusInfoPtr pci;
    914         drmUsbBusInfoPtr usb;
    915         drmPlatformBusInfoPtr platform;
    916         drmHost1xBusInfoPtr host1x;
    917         drmFauxBusInfoPtr faux;
    918     } businfo;
    919     union {
    920         drmPciDeviceInfoPtr pci;
    921         drmUsbDeviceInfoPtr usb;
    922         drmPlatformDeviceInfoPtr platform;
    923         drmHost1xDeviceInfoPtr host1x;
    924     } deviceinfo;
    925 } drmDevice, *drmDevicePtr;
    926 
    927 extern int drmGetDevice(int fd, drmDevicePtr *device);
    928 extern void drmFreeDevice(drmDevicePtr *device);
    929 
    930 extern int drmGetDevices(drmDevicePtr devices[], int max_devices);
    931 extern void drmFreeDevices(drmDevicePtr devices[], int count);
    932 
    933 #define DRM_DEVICE_GET_PCI_REVISION (1 << 0)
    934 extern int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device);
    935 extern int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_devices);
    936 
    937 extern int drmGetDeviceFromDevId(dev_t dev_id, uint32_t flags, drmDevicePtr *device);
    938 
    939 /**
    940  * Get the node type (DRM_NODE_PRIMARY or DRM_NODE_RENDER) from a device ID.
    941  *
    942  * Returns negative errno on error.
    943  */
    944 extern int drmGetNodeTypeFromDevId(dev_t devid);
    945 
    946 /**
    947  * Check if two drmDevice pointers represent the same DRM device.
    948  *
    949  * Returns 1 if the devices are equal, 0 otherwise.
    950  */
    951 extern int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b);
    952 
    953 extern int drmSyncobjCreate(int fd, uint32_t flags, uint32_t *handle);
    954 extern int drmSyncobjDestroy(int fd, uint32_t handle);
    955 extern int drmSyncobjHandleToFD(int fd, uint32_t handle, int *obj_fd);
    956 extern int drmSyncobjFDToHandle(int fd, int obj_fd, uint32_t *handle);
    957 
    958 extern int drmSyncobjImportSyncFile(int fd, uint32_t handle, int sync_file_fd);
    959 extern int drmSyncobjExportSyncFile(int fd, uint32_t handle, int *sync_file_fd);
    960 extern int drmSyncobjWait(int fd, uint32_t *handles, unsigned num_handles,
    961 			  int64_t timeout_nsec, unsigned flags,
    962 			  uint32_t *first_signaled);
    963 extern int drmSyncobjReset(int fd, const uint32_t *handles, uint32_t handle_count);
    964 extern int drmSyncobjSignal(int fd, const uint32_t *handles, uint32_t handle_count);
    965 extern int drmSyncobjTimelineSignal(int fd, const uint32_t *handles,
    966 				    uint64_t *points, uint32_t handle_count);
    967 extern int drmSyncobjTimelineWait(int fd, uint32_t *handles, uint64_t *points,
    968 				  unsigned num_handles,
    969 				  int64_t timeout_nsec, unsigned flags,
    970 				  uint32_t *first_signaled);
    971 extern int drmSyncobjQuery(int fd, uint32_t *handles, uint64_t *points,
    972 			   uint32_t handle_count);
    973 extern int drmSyncobjQuery2(int fd, uint32_t *handles, uint64_t *points,
    974 			    uint32_t handle_count, uint32_t flags);
    975 extern int drmSyncobjTransfer(int fd,
    976 			      uint32_t dst_handle, uint64_t dst_point,
    977 			      uint32_t src_handle, uint64_t src_point,
    978 			      uint32_t flags);
    979 extern int drmSyncobjEventfd(int fd, uint32_t handle, uint64_t point, int ev_fd,
    980                              uint32_t flags);
    981 
    982 extern char *
    983 drmGetFormatModifierVendor(uint64_t modifier);
    984 
    985 extern char *
    986 drmGetFormatModifierName(uint64_t modifier);
    987 
    988 extern char *
    989 drmGetFormatName(uint32_t format);
    990 
    991 #ifndef fourcc_mod_get_vendor
    992 #define fourcc_mod_get_vendor(modifier) \
    993        (((modifier) >> 56) & 0xff)
    994 #endif
    995 
    996 #if defined(__cplusplus)
    997 }
    998 #endif
    999 
   1000 #endif
   1001