summaryrefslogtreecommitdiff
path: root/bsd/drm_ioctl.h
blob: 63562fef9ab33a49f36c0b52e9f9a82c73b00ae5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/* drm_ioctl.h -- IOCTL processing for DRM -*- linux-c -*-
 * Created: Fri Jan  8 09:01:26 1999 by faith@valinux.com
 *
 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors:
 *    Rickard E. (Rik) Faith <faith@valinux.com>
 *    Gareth Hughes <gareth@valinux.com>
 */

#include "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
}

int DRM(getunique)( DRM_IOCTL_ARGS )
{
	DRM_DEVICE;
	drm_unique_t	 u;

	DRM_COPY_FROM_USER_IOCTL( u, (drm_unique_t *)data, sizeof(u) );

	if (u.unique_len >= dev->unique_len) {
		if (DRM_COPY_TO_USER(u.unique, dev->unique, dev->unique_len))
			return DRM_ERR(EFAULT);
	}
	u.unique_len = dev->unique_len;

	DRM_COPY_TO_USER_IOCTL( (drm_unique_t *)data, u, sizeof(u) );

	return 0;
}

int DRM(setunique)( DRM_IOCTL_ARGS )
{
	DRM_DEVICE;
	drm_unique_t	 u;

	if (dev->unique_len || dev->unique)
		return DRM_ERR(EBUSY);

	DRM_COPY_FROM_USER_IOCTL( u, (drm_unique_t *)data, sizeof(u) );

	if (!u.unique_len || u.unique_len > 1024)
		return DRM_ERR(EINVAL);

	dev->unique_len = u.unique_len;
	dev->unique	= DRM(alloc)(u.unique_len + 1, DRM_MEM_DRIVER);

	if(!dev->unique) return DRM_ERR(ENOMEM);

	if (DRM_COPY_FROM_USER(dev->unique, u.unique, dev->unique_len))
		return DRM_ERR(EFAULT);

	dev->unique[dev->unique_len] = '\0';

	dev->devname = DRM(alloc)(strlen(dev->name) + strlen(dev->unique) + 2,
				  DRM_MEM_DRIVER);
	if(!dev->devname) {
		DRM(free)(dev->devname, sizeof(*dev->devname), DRM_MEM_DRIVER);
		return DRM_ERR(ENOMEM);
	}
	sprintf(dev->devname, "%s@%s", dev->name, dev->unique);


	return 0;
}


int DRM(getmap)( DRM_IOCTL_ARGS )
{
	DRM_DEVICE;
	drm_map_t    map;
	drm_map_t    *mapinlist;
	drm_map_list_entry_t *list;
	int          idx;
	int	     i = 0;

	DRM_COPY_FROM_USER_IOCTL( map, (drm_map_t *)data, sizeof(map) );

	idx = map.offset;

	DRM_LOCK;
	if (idx < 0 || idx >= dev->map_count) {
		DRM_UNLOCK;
		return DRM_ERR(EINVAL);
	}

	TAILQ_FOREACH(list, dev->maplist, link) {
		mapinlist = list->map;
		if (i==idx) {
			map.offset = mapinlist->offset;
			map.size   = mapinlist->size;
			map.type   = mapinlist->type;
			map.flags  = mapinlist->flags;
			map.handle = mapinlist->handle;
			map.mtrr   = mapinlist->mtrr;
			break;
		}
		i++;
	}

	DRM_UNLOCK;

 	if (!list)
		return EINVAL;

	DRM_COPY_TO_USER_IOCTL( (drm_map_t *)data, map, sizeof(map) );

	return 0;
}

int DRM(getclient)( DRM_IOCTL_ARGS )
{
	DRM_DEVICE;
	drm_client_t client;
	drm_file_t   *pt;
	int          idx;
	int          i = 0;

	DRM_COPY_FROM_USER_IOCTL( client, (drm_client_t *)data, sizeof(client) );

	idx = client.idx;
	DRM_LOCK;
	TAILQ_FOREACH(pt, &dev->files, link) {
		if (i==idx)
		{
			client.auth  = pt->authenticated;
			client.pid   = pt->pid;
			client.uid   = pt->uid;
			client.magic = pt->magic;
			client.iocs  = pt->ioctl_count;
			DRM_UNLOCK;

			*(drm_client_t *)data = client;
			return 0;
		}
		i++;
	}
	DRM_UNLOCK;

	DRM_COPY_TO_USER_IOCTL( (drm_client_t *)data, client, sizeof(client) );

	return 0;
}

int DRM(getstats)( DRM_IOCTL_ARGS )
{
	DRM_DEVICE;
	drm_stats_t  stats;
	int          i;

	memset(&stats, 0, sizeof(stats));
	
	DRM_LOCK;

	for (i = 0; i < dev->counters; i++) {
		if (dev->types[i] == _DRM_STAT_LOCK)
			stats.data[i].value
				= (dev->lock.hw_lock
				   ? dev->lock.hw_lock->lock : 0);
		else 
			stats.data[i].value = atomic_read(&dev->counts[i]);
		stats.data[i].type  = dev->types[i];
	}
	
	stats.count = dev->counters;

	DRM_UNLOCK;

	DRM_COPY_TO_USER_IOCTL( (drm_stats_t *)data, stats, sizeof(stats) );

	return 0;
}
sion(). */ 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 */ } 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 */ } drm_unique_t; typedef struct drm_list { 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, DRM_RM_COMMAND, DRM_INST_HANDLER, DRM_UNINST_HANDLER } func; 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_map_type_t; /** * Memory mapping flags. */ typedef enum drm_map_flags { _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_map_flags_t; typedef struct drm_ctx_priv_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 */ } 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 */ } drm_client_t; typedef enum { _DRM_STAT_LOCK, _DRM_STAT_OPENS, _DRM_STAT_CLOSES, _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_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 { unsigned long value; drm_stat_type_t type; } 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 */ /* 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_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; /** * 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 */ 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 */ } flags; 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 */ 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 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 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 { 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 */ } 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; /**< 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_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; long tval_sec; 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; /**< AGP mode */ } drm_agp_mode_t; /** * 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 binding / unbinding */ unsigned long type; /**< Type of memory to allocate */ unsigned long physical; /**< Physical used by i810 */ } drm_agp_buffer_t; /** * 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 */ } 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; unsigned long mode;