fix up radeon span functions using latest r200 code from Brian,
[mesa.git] / src / mesa / drivers / dri / dri_client / xf86drm.c
1 /**
2 * \file xf86drm.c
3 * User-level interface to DRM device
4 *
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Kevin E. Martin <martin@valinux.com>
7 */
8
9 /*
10 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
11 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
12 * All Rights Reserved.
13 *
14 * Permission is hereby granted, free of charge, to any person obtaining a
15 * copy of this software and associated documentation files (the "Software"),
16 * to deal in the Software without restriction, including without limitation
17 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 * and/or sell copies of the Software, and to permit persons to whom the
19 * Software is furnished to do so, subject to the following conditions:
20 *
21 * The above copyright notice and this permission notice (including the next
22 * paragraph) shall be included in all copies or substantial portions of the
23 * Software.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
29 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
30 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
31 * DEALINGS IN THE SOFTWARE.
32 */
33
34 /* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c,v 1.36 2003/08/24 17:35:35 tsi Exp $ */
35
36 #ifdef XFree86Server
37 # include "xf86.h"
38 # include "xf86_OSproc.h"
39 # include "drm.h"
40 # include "xf86_ansic.h"
41 # define _DRM_MALLOC xalloc
42 # define _DRM_FREE xfree
43 # ifndef XFree86LOADER
44 # include <sys/mman.h>
45 # endif
46 #else
47 # include <stdio.h>
48 # include <stdlib.h>
49 # include <unistd.h>
50 # include <string.h>
51 # include <ctype.h>
52 # include <fcntl.h>
53 # include <errno.h>
54 # include <signal.h>
55 # include <sys/types.h>
56 # include <sys/stat.h>
57 # define stat_t struct stat
58 # include <sys/ioctl.h>
59 # include <sys/mman.h>
60 # include <sys/time.h>
61 # include <stdarg.h>
62 # ifdef DRM_USE_MALLOC
63 # define _DRM_MALLOC malloc
64 # define _DRM_FREE free
65 # else
66 # include <X11/Xlibint.h>
67 # define _DRM_MALLOC Xmalloc
68 # define _DRM_FREE Xfree
69 # endif
70 # include "drm.h"
71 #endif
72
73 /* No longer needed with CVS kernel modules on alpha
74 #if defined(__alpha__) && defined(__linux__)
75 extern unsigned long _bus_base(void);
76 #define BUS_BASE _bus_base()
77 #endif
78 */
79
80 /* Not all systems have MAP_FAILED defined */
81 #ifndef MAP_FAILED
82 #define MAP_FAILED ((void *)-1)
83 #endif
84
85 #include "xf86drm.h"
86
87 #ifdef __FreeBSD__
88 #define DRM_MAJOR 145
89 #endif
90
91 #ifdef __NetBSD__
92 #define DRM_MAJOR 34
93 #endif
94
95 # ifdef __OpenBSD__
96 # define DRM_MAJOR 81
97 # endif
98
99 #ifndef DRM_MAJOR
100 #define DRM_MAJOR 226 /* Linux */
101 #endif
102
103 #ifndef DRM_MAX_MINOR
104 #define DRM_MAX_MINOR 16
105 #endif
106
107 #ifdef __linux__
108 #include <sys/sysmacros.h> /* for makedev() */
109 #endif
110
111 #ifndef makedev
112 /* This definition needs to be changed on
113 some systems if dev_t is a structure.
114 If there is a header file we can get it
115 from, there would be best. */
116 #define makedev(x,y) ((dev_t)(((x) << 8) | (y)))
117 #endif
118
119 #define DRM_MSG_VERBOSITY 3
120
121 /**
122 * Output a message to stderr.
123 *
124 * \param format printf() like format string.
125 *
126 * \internal
127 * This function is a wrapper around vfprintf().
128 */
129 static void
130 drmMsg(const char *format, ...)
131 {
132 va_list ap;
133
134 #ifndef XFree86Server
135 const char *env;
136 if ((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose"))
137 #endif
138 {
139 va_start(ap, format);
140 #ifdef XFree86Server
141 xf86VDrvMsgVerb(-1, X_NONE, DRM_MSG_VERBOSITY, format, ap);
142 #else
143 vfprintf(stderr, format, ap);
144 #endif
145 va_end(ap);
146 }
147 }
148
149 static void *drmHashTable = NULL; /* Context switch callbacks */
150
151 typedef struct drmHashEntry {
152 int fd;
153 void (*f)(int, void *, void *);
154 void *tagTable;
155 } drmHashEntry;
156
157 void *drmMalloc(int size)
158 {
159 void *pt;
160 if ((pt = _DRM_MALLOC(size))) memset(pt, 0, size);
161 return pt;
162 }
163
164 void drmFree(void *pt)
165 {
166 if (pt) _DRM_FREE(pt);
167 }
168
169 /* drmStrdup can't use strdup(3), since it doesn't call _DRM_MALLOC... */
170 static char *drmStrdup(const char *s)
171 {
172 char *retval = NULL;
173
174 if (s) {
175 retval = _DRM_MALLOC(strlen(s)+1);
176 strcpy(retval, s);
177 }
178 return retval;
179 }
180
181
182 static unsigned long drmGetKeyFromFd(int fd)
183 {
184 stat_t st;
185
186 st.st_rdev = 0;
187 fstat(fd, &st);
188 return st.st_rdev;
189 }
190
191 static drmHashEntry *drmGetEntry(int fd)
192 {
193 unsigned long key = drmGetKeyFromFd(fd);
194 void *value;
195 drmHashEntry *entry;
196
197 if (!drmHashTable) drmHashTable = drmHashCreate();
198
199 if (drmHashLookup(drmHashTable, key, &value)) {
200 entry = drmMalloc(sizeof(*entry));
201 entry->fd = fd;
202 entry->f = NULL;
203 entry->tagTable = drmHashCreate();
204 drmHashInsert(drmHashTable, key, entry);
205 } else {
206 entry = value;
207 }
208 return entry;
209 }
210
211 /**
212 * Compare two busid strings
213 *
214 * \param first
215 * \param second
216 *
217 * \return 1 if matched.
218 *
219 * \internal
220 * This function compares two bus ID strings. It understands the older
221 * PCI:b:d:f format and the newer pci:oooo:bb:dd.f format. In the format, o is
222 * domain, b is bus, d is device, f is function.
223 */
224 static int drmMatchBusID(const char *id1, const char *id2)
225 {
226 /* First, check if the IDs are exactly the same */
227 if (strcasecmp(id1, id2) == 0)
228 return 1;
229
230 /* Try to match old/new-style PCI bus IDs. */
231 if (strncasecmp(id1, "pci", 3) == 0) {
232 int o1, b1, d1, f1;
233 int o2, b2, d2, f2;
234 int ret;
235
236 ret = sscanf(id1, "pci:%04x:%02x:%02x.%d", &o1, &b1, &d1, &f1);
237 if (ret != 4) {
238 o1 = 0;
239 ret = sscanf(id1, "PCI:%d:%d:%d", &b1, &d1, &f1);
240 if (ret != 3)
241 return 0;
242 }
243
244 ret = sscanf(id2, "pci:%04x:%02x:%02x.%d", &o2, &b2, &d2, &f2);
245 if (ret != 4) {
246 o2 = 0;
247 ret = sscanf(id2, "PCI:%d:%d:%d", &b2, &d2, &f2);
248 if (ret != 3)
249 return 0;
250 }
251
252 if ((o1 != o2) || (b1 != b2) || (d1 != d2) || (f1 != f2))
253 return 0;
254 else
255 return 1;
256 }
257 return 0;
258 }
259
260 /**
261 * Open the DRM device, creating it if necessary.
262 *
263 * \param dev major and minor numbers of the device.
264 * \param minor minor number of the device.
265 *
266 * \return a file descriptor on success, or a negative value on error.
267 *
268 * \internal
269 * Assembles the device name from \p minor and opens it, creating the device
270 * special file node with the major and minor numbers specified by \p dev and
271 * parent directory if necessary and was called by root.
272 */
273 static int drmOpenDevice(long dev, int minor)
274 {
275 stat_t st;
276 char buf[64];
277 int fd;
278 mode_t devmode = DRM_DEV_MODE;
279 int isroot = !geteuid();
280 #if defined(XFree86Server)
281 uid_t user = DRM_DEV_UID;
282 gid_t group = DRM_DEV_GID;
283 #endif
284
285 sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
286 drmMsg("drmOpenDevice: node name is %s\n", buf);
287
288 #if defined(XFree86Server)
289 devmode = xf86ConfigDRI.mode ? xf86ConfigDRI.mode : DRM_DEV_MODE;
290 devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH);
291 group = (xf86ConfigDRI.group >= 0) ? xf86ConfigDRI.group : DRM_DEV_GID;
292 #endif
293
294 if (stat(DRM_DIR_NAME, &st)) {
295 if (!isroot) return DRM_ERR_NOT_ROOT;
296 mkdir(DRM_DIR_NAME, DRM_DEV_DIRMODE);
297 chown(DRM_DIR_NAME, 0, 0); /* root:root */
298 chmod(DRM_DIR_NAME, DRM_DEV_DIRMODE);
299 }
300
301 /* Check if the device node exists and create it if necessary. */
302 if (stat(buf, &st)) {
303 if (!isroot) return DRM_ERR_NOT_ROOT;
304 remove(buf);
305 mknod(buf, S_IFCHR | devmode, dev);
306 }
307 #if defined(XFree86Server)
308 chown(buf, user, group);
309 chmod(buf, devmode);
310 #endif
311
312 fd = open(buf, O_RDWR, 0);
313 drmMsg("drmOpenDevice: open result is %d, (%s)\n",
314 fd, fd < 0 ? strerror(errno) : "OK");
315 if (fd >= 0) return fd;
316
317 /* Check if the device node is not what we expect it to be, and recreate it
318 * and try again if so.
319 */
320 if (st.st_rdev != dev) {
321 if (!isroot) return DRM_ERR_NOT_ROOT;
322 remove(buf);
323 mknod(buf, S_IFCHR | devmode, dev);
324 #if defined(XFree86Server)
325 chown(buf, user, group);
326 chmod(buf, devmode);
327 #endif
328 }
329 fd = open(buf, O_RDWR, 0);
330 drmMsg("drmOpenDevice: open result is %d, (%s)\n",
331 fd, fd < 0 ? strerror(errno) : "OK");
332 if (fd >= 0) return fd;
333
334 drmMsg("drmOpenDevice: Open failed\n");
335 remove(buf);
336 return -errno;
337 }
338
339
340 /**
341 * Open the DRM device
342 *
343 * \param minor device minor number.
344 * \param create allow to create the device if set.
345 *
346 * \return a file descriptor on success, or a negative value on error.
347 *
348 * \internal
349 * Calls drmOpenDevice() if \p create is set, otherwise assembles the device
350 * name from \p minor and opens it.
351 */
352 static int drmOpenMinor(int minor, int create)
353 {
354 int fd;
355 char buf[64];
356
357 if (create) return drmOpenDevice(makedev(DRM_MAJOR, minor), minor);
358
359 sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
360 if ((fd = open(buf, O_RDWR, 0)) >= 0) return fd;
361 return -errno;
362 }
363
364
365 /**
366 * Determine whether the DRM kernel driver has been loaded.
367 *
368 * \return 1 if the DRM driver is loaded, 0 otherwise.
369 *
370 * \internal
371 * Determine the presence of the kernel driver by attempting to open the 0
372 * minor and get version information. For backward compatibility with older
373 * Linux implementations, /proc/dri is also checked.
374 */
375 int drmAvailable(void)
376 {
377 drmVersionPtr version;
378 int retval = 0;
379 int fd;
380
381 if ((fd = drmOpenMinor(0, 1)) < 0) {
382 #ifdef __linux__
383 /* Try proc for backward Linux compatibility */
384 if (!access("/proc/dri/0", R_OK)) return 1;
385 #endif
386 return 0;
387 }
388
389 if ((version = drmGetVersion(fd))) {
390 retval = 1;
391 drmFreeVersion(version);
392 }
393 close(fd);
394
395 return retval;
396 }
397
398
399 /**
400 * Open the device by bus ID.
401 *
402 * \param busid bus ID.
403 *
404 * \return a file descriptor on success, or a negative value on error.
405 *
406 * \internal
407 * This function attempts to open every possible minor (up to DRM_MAX_MINOR),
408 * comparing the device bus ID with the one supplied.
409 *
410 * \sa drmOpenMinor() and drmGetBusid().
411 */
412 static int drmOpenByBusid(const char *busid)
413 {
414 int i;
415 int fd;
416 const char *buf;
417 drmSetVersion sv;
418
419 drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid);
420 for (i = 0; i < DRM_MAX_MINOR; i++) {
421 fd = drmOpenMinor(i, 1);
422 drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd);
423 if (fd >= 0) {
424 sv.drm_di_major = 1;
425 sv.drm_di_minor = 1;
426 sv.drm_dd_major = -1; /* Don't care */
427 drmSetInterfaceVersion(fd, &sv);
428 buf = drmGetBusid(fd);
429 drmMsg("drmOpenByBusid: drmGetBusid reports %s\n", buf);
430 if (buf && drmMatchBusID(buf, busid)) {
431 drmFreeBusid(buf);
432 return fd;
433 }
434 if (buf) drmFreeBusid(buf);
435 close(fd);
436 }
437 }
438 return -1;
439 }
440
441
442 /**
443 * Open the device by name.
444 *
445 * \param name driver name.
446 *
447 * \return a file descriptor on success, or a negative value on error.
448 *
449 * \internal
450 * This function opens the first minor number that matches the driver name and
451 * isn't already in use. If it's in use it then it will already have a bus ID
452 * assigned.
453 *
454 * \sa drmOpenMinor(), drmGetVersion() and drmGetBusid().
455 */
456 static int drmOpenByName(const char *name)
457 {
458 int i;
459 int fd;
460 drmVersionPtr version;
461 char * id;
462
463 if (!drmAvailable()) {
464 #if !defined(XFree86Server)
465 return -1;
466 #else
467 /* try to load the kernel module now */
468 if (!xf86LoadKernelModule(name)) {
469 ErrorF("[drm] failed to load kernel module \"%s\"\n",
470 name);
471 return -1;
472 }
473 #endif
474 }
475
476 /*
477 * Open the first minor number that matches the driver name and isn't
478 * already in use. If it's in use it will have a busid assigned already.
479 */
480 for (i = 0; i < DRM_MAX_MINOR; i++) {
481 if ((fd = drmOpenMinor(i, 1)) >= 0) {
482 if ((version = drmGetVersion(fd))) {
483 if (!strcmp(version->name, name)) {
484 drmFreeVersion(version);
485 id = drmGetBusid(fd);
486 drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL");
487 if (!id || !*id) {
488 if (id) {
489 drmFreeBusid(id);
490 }
491 return fd;
492 } else {
493 drmFreeBusid(id);
494 }
495 } else {
496 drmFreeVersion(version);
497 }
498 }
499 close(fd);
500 }
501 }
502
503 #ifdef __linux__
504 /* Backward-compatibility /proc support */
505 for (i = 0; i < 8; i++) {
506 char proc_name[64], buf[512];
507 char *driver, *pt, *devstring;
508 int retcode;
509
510 sprintf(proc_name, "/proc/dri/%d/name", i);
511 if ((fd = open(proc_name, 0, 0)) >= 0) {
512 retcode = read(fd, buf, sizeof(buf)-1);
513 close(fd);
514 if (retcode) {
515 buf[retcode-1] = '\0';
516 for (driver = pt = buf; *pt && *pt != ' '; ++pt)
517 ;
518 if (*pt) { /* Device is next */
519 *pt = '\0';
520 if (!strcmp(driver, name)) { /* Match */
521 for (devstring = ++pt; *pt && *pt != ' '; ++pt)
522 ;
523 if (*pt) { /* Found busid */
524 return drmOpenByBusid(++pt);
525 } else { /* No busid */
526 return drmOpenDevice(strtol(devstring, NULL, 0),i);
527 }
528 }
529 }
530 }
531 }
532 }
533 #endif
534
535 return -1;
536 }
537
538
539 /**
540 * Open the DRM device.
541 *
542 * Looks up the specified name and bus ID, and opens the device found. The
543 * entry in /dev/dri is created if necessary and if called by root.
544 *
545 * \param name driver name. Not referenced if bus ID is supplied.
546 * \param busid bus ID. Zero if not known.
547 *
548 * \return a file descriptor on success, or a negative value on error.
549 *
550 * \internal
551 * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName()
552 * otherwise.
553 */
554 int drmOpen(const char *name, const char *busid)
555 {
556 #ifdef XFree86Server
557 if (!drmAvailable() && name != NULL) {
558 /* try to load the kernel */
559 if (!xf86LoadKernelModule(name)) {
560 ErrorF("[drm] failed to load kernel module \"%s\"\n",
561 name);
562 return -1;
563 }
564 }
565 #endif
566
567 if (busid) {
568 int fd;
569
570 fd = drmOpenByBusid(busid);
571 if (fd >= 0)
572 return fd;
573 }
574 if (name)
575 return drmOpenByName(name);
576 return -1;
577 }
578
579
580 /**
581 * Free the version information returned by drmGetVersion().
582 *
583 * \param v pointer to the version information.
584 *
585 * \internal
586 * It frees the memory pointed by \p %v as well as all the non-null strings
587 * pointers in it.
588 */
589 void drmFreeVersion(drmVersionPtr v)
590 {
591 if (!v) return;
592 if (v->name) drmFree(v->name);
593 if (v->date) drmFree(v->date);
594 if (v->desc) drmFree(v->desc);
595 drmFree(v);
596 }
597
598
599 /**
600 * Free the non-public version information returned by the kernel.
601 *
602 * \param v pointer to the version information.
603 *
604 * \internal
605 * Used by drmGetVersion() to free the memory pointed by \p %v as well as all
606 * the non-null strings pointers in it.
607 */
608 static void drmFreeKernelVersion(drm_version_t *v)
609 {
610 if (!v) return;
611 if (v->name) drmFree(v->name);
612 if (v->date) drmFree(v->date);
613 if (v->desc) drmFree(v->desc);
614 drmFree(v);
615 }
616
617
618 /**
619 * Copy version information.
620 *
621 * \param d destination pointer.
622 * \param s source pointer.
623 *
624 * \internal
625 * Used by drmGetVersion() to translate the information returned by the ioctl
626 * interface in a private structure into the public structure counterpart.
627 */
628 static void drmCopyVersion(drmVersionPtr d, const drm_version_t *s)
629 {
630 d->version_major = s->version_major;
631 d->version_minor = s->version_minor;
632 d->version_patchlevel = s->version_patchlevel;
633 d->name_len = s->name_len;
634 d->name = drmStrdup(s->name);
635 d->date_len = s->date_len;
636 d->date = drmStrdup(s->date);
637 d->desc_len = s->desc_len;
638 d->desc = drmStrdup(s->desc);
639 }
640
641
642 /**
643 * Query the driver version information.
644 *
645 * \param fd file descriptor.
646 *
647 * \return pointer to a drmVersion structure which should be freed with
648 * drmFreeVersion().
649 *
650 * \note Similar information is available via /proc/dri.
651 *
652 * \internal
653 * It gets the version information via successive DRM_IOCTL_VERSION ioctls,
654 * first with zeros to get the string lengths, and then the actually strings.
655 * It also null-terminates them since they might not be already.
656 */
657 drmVersionPtr drmGetVersion(int fd)
658 {
659 drmVersionPtr retval;
660 drm_version_t *version = drmMalloc(sizeof(*version));
661
662 /* First, get the lengths */
663 version->name_len = 0;
664 version->name = NULL;
665 version->date_len = 0;
666 version->date = NULL;
667 version->desc_len = 0;
668 version->desc = NULL;
669
670 if (ioctl(fd, DRM_IOCTL_VERSION, version)) {
671 drmFreeKernelVersion(version);
672 return NULL;
673 }
674
675 /* Now, allocate space and get the data */
676 if (version->name_len)
677 version->name = drmMalloc(version->name_len + 1);
678 if (version->date_len)
679 version->date = drmMalloc(version->date_len + 1);
680 if (version->desc_len)
681 version->desc = drmMalloc(version->desc_len + 1);
682
683 if (ioctl(fd, DRM_IOCTL_VERSION, version)) {
684 drmMsg("DRM_IOCTL_VERSION: %s\n", strerror(errno));
685 drmFreeKernelVersion(version);
686 return NULL;
687 }
688
689 /* The results might not be null-terminated
690 strings, so terminate them. */
691
692 if (version->name_len) version->name[version->name_len] = '\0';
693 if (version->date_len) version->date[version->date_len] = '\0';
694 if (version->desc_len) version->desc[version->desc_len] = '\0';
695
696 /* Now, copy it all back into the
697 client-visible data structure... */
698 retval = drmMalloc(sizeof(*retval));
699 drmCopyVersion(retval, version);
700 drmFreeKernelVersion(version);
701 return retval;
702 }
703
704
705 /**
706 * Get version information for the DRM user space library.
707 *
708 * This version number is driver independent.
709 *
710 * \param fd file descriptor.
711 *
712 * \return version information.
713 *
714 * \internal
715 * This function allocates and fills a drm_version structure with a hard coded
716 * version number.
717 */
718 drmVersionPtr drmGetLibVersion(int fd)
719 {
720 drm_version_t *version = drmMalloc(sizeof(*version));
721
722 /* Version history:
723 * revision 1.0.x = original DRM interface with no drmGetLibVersion
724 * entry point and many drm<Device> extensions
725 * revision 1.1.x = added drmCommand entry points for device extensions
726 * added drmGetLibVersion to identify libdrm.a version
727 * revision 1.2.x = added drmSetInterfaceVersion
728 * modified drmOpen to handle both busid and name
729 */
730 version->version_major = 1;
731 version->version_minor = 2;
732 version->version_patchlevel = 0;
733
734 return (drmVersionPtr)version;
735 }
736
737
738 /**
739 * Free the bus ID information.
740 *
741 * \param busid bus ID information string as given by drmGetBusid().
742 *
743 * \internal
744 * This function is just frees the memory pointed by \p busid.
745 */
746 void drmFreeBusid(const char *busid)
747 {
748 drmFree((void *)busid);
749 }
750
751
752 /**
753 * Get the bus ID of the device.
754 *
755 * \param fd file descriptor.
756 *
757 * \return bus ID string.
758 *
759 * \internal
760 * This function gets the bus ID via successive DRM_IOCTL_GET_UNIQUE ioctls to
761 * get the string length and data, passing the arguments in a drm_unique
762 * structure.
763 */
764 char *drmGetBusid(int fd)
765 {
766 drm_unique_t u;
767
768 u.unique_len = 0;
769 u.unique = NULL;
770
771 if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL;
772 u.unique = drmMalloc(u.unique_len + 1);
773 if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL;
774 u.unique[u.unique_len] = '\0';
775
776 return u.unique;
777 }
778
779
780 /**
781 * Set the bus ID of the device.
782 *
783 * \param fd file descriptor.
784 * \param busid bus ID string.
785 *
786 * \return zero on success, negative on failure.
787 *
788 * \internal
789 * This function is a wrapper around the DRM_IOCTL_SET_UNIQUE ioctl, passing
790 * the arguments in a drm_unique structure.
791 */
792 int drmSetBusid(int fd, const char *busid)
793 {
794 drm_unique_t u;
795
796 u.unique = (char *)busid;
797 u.unique_len = strlen(busid);
798
799 if (ioctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) {
800 return -errno;
801 }
802 return 0;
803 }
804
805 int drmGetMagic(int fd, drm_magic_t * magic)
806 {
807 drm_auth_t auth;
808
809 *magic = 0;
810 if (ioctl(fd, DRM_IOCTL_GET_MAGIC, &auth)) return -errno;
811 *magic = auth.magic;
812 return 0;
813 }
814
815 int drmAuthMagic(int fd, drm_magic_t magic)
816 {
817 drm_auth_t auth;
818
819 auth.magic = magic;
820 if (ioctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth)) return -errno;
821 return 0;
822 }
823
824 /**
825 * Specifies a range of memory that is available for mapping by a
826 * non-root process.
827 *
828 * \param fd file descriptor.
829 * \param offset usually the physical address. The actual meaning depends of
830 * the \p type parameter. See below.
831 * \param size of the memory in bytes.
832 * \param type type of the memory to be mapped.
833 * \param flags combination of several flags to modify the function actions.
834 * \param handle will be set to a value that may be used as the offset
835 * parameter for mmap().
836 *
837 * \return zero on success or a negative value on error.
838 *
839 * \par Mapping the frame buffer
840 * For the frame buffer
841 * - \p offset will be the physical address of the start of the frame buffer,
842 * - \p size will be the size of the frame buffer in bytes, and
843 * - \p type will be DRM_FRAME_BUFFER.
844 *
845 * \par
846 * The area mapped will be uncached. If MTRR support is available in the
847 * kernel, the frame buffer area will be set to write combining.
848 *
849 * \par Mapping the MMIO register area
850 * For the MMIO register area,
851 * - \p offset will be the physical address of the start of the register area,
852 * - \p size will be the size of the register area bytes, and
853 * - \p type will be DRM_REGISTERS.
854 * \par
855 * The area mapped will be uncached.
856 *
857 * \par Mapping the SAREA
858 * For the SAREA,
859 * - \p offset will be ignored and should be set to zero,
860 * - \p size will be the desired size of the SAREA in bytes,
861 * - \p type will be DRM_SHM.
862 *
863 * \par
864 * A shared memory area of the requested size will be created and locked in
865 * kernel memory. This area may be mapped into client-space by using the handle
866 * returned.
867 *
868 * \note May only be called by root.
869 *
870 * \internal
871 * This function is a wrapper around the DRM_IOCTL_ADD_MAP ioctl, passing
872 * the arguments in a drm_map structure.
873 */
874 int drmAddMap(int fd,
875 drm_handle_t offset,
876 drmSize size,
877 drmMapType type,
878 drmMapFlags flags,
879 drm_handle_t * handle)
880 {
881 drm_map_t map;
882
883 map.offset = offset;
884 /* No longer needed with CVS kernel modules on alpha
885 #ifdef __alpha__
886 if (type != DRM_SHM)
887 map.offset += BUS_BASE;
888 #endif
889 */
890 map.size = size;
891 map.handle = 0;
892 map.type = type;
893 map.flags = flags;
894 if (ioctl(fd, DRM_IOCTL_ADD_MAP, &map)) return -errno;
895 if (handle) *handle = (drm_handle_t)map.handle;
896 return 0;
897 }
898
899 int drmRmMap(int fd, drm_handle_t handle)
900 {
901 drm_map_t map;
902
903 map.handle = (void *)handle;
904
905 if(ioctl(fd, DRM_IOCTL_RM_MAP, &map)) return -errno;
906 return 0;
907 }
908
909 /**
910 * Make buffers available for DMA transfers.
911 *
912 * \param fd file descriptor.
913 * \param count number of buffers.
914 * \param size size of each buffer.
915 * \param flags buffer allocation flags.
916 * \param agp_offset offset in the AGP aperture
917 *
918 * \return number of buffers allocated, negative on error.
919 *
920 * \internal
921 * This function is a wrapper around DRM_IOCTL_ADD_BUFS ioctl.
922 *
923 * \sa drm_buf_desc.
924 */
925 int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags,
926 int agp_offset)
927 {
928 drm_buf_desc_t request;
929
930 request.count = count;
931 request.size = size;
932 request.low_mark = 0;
933 request.high_mark = 0;
934 request.flags = flags;
935 request.agp_start = agp_offset;
936
937 if (ioctl(fd, DRM_IOCTL_ADD_BUFS, &request)) return -errno;
938 return request.count;
939 }
940
941 int drmMarkBufs(int fd, double low, double high)
942 {
943 drm_buf_info_t info;
944 int i;
945
946 info.count = 0;
947 info.list = NULL;
948
949 if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) return -EINVAL;
950
951 if (!info.count) return -EINVAL;
952
953 if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
954 return -ENOMEM;
955
956 if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
957 int retval = -errno;
958 drmFree(info.list);
959 return retval;
960 }
961
962 for (i = 0; i < info.count; i++) {
963 info.list[i].low_mark = low * info.list[i].count;
964 info.list[i].high_mark = high * info.list[i].count;
965 if (ioctl(fd, DRM_IOCTL_MARK_BUFS, &info.list[i])) {
966 int retval = -errno;
967 drmFree(info.list);
968 return retval;
969 }
970 }
971 drmFree(info.list);
972
973 return 0;
974 }
975
976 /**
977 * Free buffers.
978 *
979 * \param fd file descriptor.
980 * \param count number of buffers to free.
981 * \param list list of buffers to be freed.
982 *
983 * \return zero on success, or a negative value on failure.
984 *
985 * \note This function is primarily used for debugging.
986 *
987 * \internal
988 * This function is a wrapper around the DRM_IOCTL_FREE_BUFS ioctl, passing
989 * the arguments in a drm_buf_free structure.
990 */
991 int drmFreeBufs(int fd, int count, int *list)
992 {
993 drm_buf_free_t request;
994
995 request.count = count;
996 request.list = list;
997 if (ioctl(fd, DRM_IOCTL_FREE_BUFS, &request)) return -errno;
998 return 0;
999 }
1000
1001
1002 /**
1003 * Close the device.
1004 *
1005 * \param fd file descriptor.
1006 *
1007 * \internal
1008 * This function closes the file descriptor.
1009 */
1010 int drmClose(int fd)
1011 {
1012 unsigned long key = drmGetKeyFromFd(fd);
1013 drmHashEntry *entry = drmGetEntry(fd);
1014
1015 drmHashDestroy(entry->tagTable);
1016 entry->fd = 0;
1017 entry->f = NULL;
1018 entry->tagTable = NULL;
1019
1020 drmHashDelete(drmHashTable, key);
1021 drmFree(entry);
1022
1023 return close(fd);
1024 }
1025
1026
1027 /**
1028 * Map a region of memory.
1029 *
1030 * \param fd file descriptor.
1031 * \param handle handle returned by drmAddMap().
1032 * \param size size in bytes. Must match the size used by drmAddMap().
1033 * \param address will contain the user-space virtual address where the mapping
1034 * begins.
1035 *
1036 * \return zero on success, or a negative value on failure.
1037 *
1038 * \internal
1039 * This function is a wrapper for mmap().
1040 */
1041 int drmMap(int fd,
1042 drm_handle_t handle,
1043 drmSize size,
1044 drmAddressPtr address)
1045 {
1046 static unsigned long pagesize_mask = 0;
1047
1048 if (fd < 0) return -EINVAL;
1049
1050 if (!pagesize_mask)
1051 pagesize_mask = getpagesize() - 1;
1052
1053 size = (size + pagesize_mask) & ~pagesize_mask;
1054
1055 *address = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, handle);
1056 if (*address == MAP_FAILED) return -errno;
1057 return 0;
1058 }
1059
1060
1061 /**
1062 * Unmap mappings obtained with drmMap().
1063 *
1064 * \param address address as given by drmMap().
1065 * \param size size in bytes. Must match the size used by drmMap().
1066 *
1067 * \return zero on success, or a negative value on failure.
1068 *
1069 * \internal
1070 * This function is a wrapper for unmap().
1071 */
1072 int drmUnmap(drmAddress address, drmSize size)
1073 {
1074 return munmap(address, size);
1075 }
1076
1077 drmBufInfoPtr drmGetBufInfo(int fd)
1078 {
1079 drm_buf_info_t info;
1080 drmBufInfoPtr retval;
1081 int i;
1082
1083 info.count = 0;
1084 info.list = NULL;
1085
1086 if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) return NULL;
1087
1088 if (info.count) {
1089 if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
1090 return NULL;
1091
1092 if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
1093 drmFree(info.list);
1094 return NULL;
1095 }
1096 /* Now, copy it all back into the
1097 client-visible data structure... */
1098 retval = drmMalloc(sizeof(*retval));
1099 retval->count = info.count;
1100 retval->list = drmMalloc(info.count * sizeof(*retval->list));
1101 for (i = 0; i < info.count; i++) {
1102 retval->list[i].count = info.list[i].count;
1103 retval->list[i].size = info.list[i].size;
1104 retval->list[i].low_mark = info.list[i].low_mark;
1105 retval->list[i].high_mark = info.list[i].high_mark;
1106 }
1107 drmFree(info.list);
1108 return retval;
1109 }
1110 return NULL;
1111 }
1112
1113 /**
1114 * Map all DMA buffers into client-virtual space.
1115 *
1116 * \param fd file descriptor.
1117 *
1118 * \return a pointer to a ::drmBufMap structure.
1119 *
1120 * \note The client may not use these buffers until obtaining buffer indices
1121 * with drmDMA().
1122 *
1123 * \internal
1124 * This function calls the DRM_IOCTL_MAP_BUFS ioctl and copies the returned
1125 * information about the buffers in a drm_buf_map structure into the
1126 * client-visible data structures.
1127 */
1128 drmBufMapPtr drmMapBufs(int fd)
1129 {
1130 drm_buf_map_t bufs;
1131 drmBufMapPtr retval;
1132 int i;
1133
1134 bufs.count = 0;
1135 bufs.list = NULL;
1136 bufs.virtual = NULL;
1137 if (ioctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) return NULL;
1138
1139 if (!bufs.count) return NULL;
1140
1141 if (!(bufs.list = drmMalloc(bufs.count * sizeof(*bufs.list))))
1142 return NULL;
1143
1144 if (ioctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) {
1145 drmFree(bufs.list);
1146 return NULL;
1147 }
1148 /* Now, copy it all back into the
1149 client-visible data structure... */
1150 retval = drmMalloc(sizeof(*retval));
1151 retval->count = bufs.count;
1152 retval->list = drmMalloc(bufs.count * sizeof(*retval->list));
1153 for (i = 0; i < bufs.count; i++) {
1154 retval->list[i].idx = bufs.list[i].idx;
1155 retval->list[i].total = bufs.list[i].total;
1156 retval->list[i].used = 0;
1157 retval->list[i].address = bufs.list[i].address;
1158 }
1159
1160 drmFree(bufs.list);
1161
1162 return retval;
1163 }
1164
1165
1166 /**
1167 * Unmap buffers allocated with drmMapBufs().
1168 *
1169 * \return zero on success, or negative value on failure.
1170 *
1171 * \internal
1172 * Calls munmap() for every buffer stored in \p bufs and frees the
1173 * memory allocated by drmMapBufs().
1174 */
1175 int drmUnmapBufs(drmBufMapPtr bufs)
1176 {
1177 int i;
1178
1179 for (i = 0; i < bufs->count; i++) {
1180 munmap(bufs->list[i].address, bufs->list[i].total);
1181 }
1182
1183 drmFree(bufs->list);
1184 drmFree(bufs);
1185
1186 return 0;
1187 }
1188
1189
1190 #define DRM_DMA_RETRY 16
1191
1192 /**
1193 * Reserve DMA buffers.
1194 *
1195 * \param fd file descriptor.
1196 * \param request
1197 *
1198 * \return zero on success, or a negative value on failure.
1199 *
1200 * \internal
1201 * Assemble the arguments into a drm_dma structure and keeps issuing the
1202 * DRM_IOCTL_DMA ioctl until success or until maximum number of retries.
1203 */
1204 int drmDMA(int fd, drmDMAReqPtr request)
1205 {
1206 drm_dma_t dma;
1207 int ret, i = 0;
1208
1209 /* Copy to hidden structure */
1210 dma.context = request->context;
1211 dma.send_count = request->send_count;
1212 dma.send_indices = request->send_list;
1213 dma.send_sizes = request->send_sizes;
1214 dma.flags = request->flags;
1215 dma.request_count = request->request_count;
1216 dma.request_size = request->request_size;
1217 dma.request_indices = request->request_list;
1218 dma.request_sizes = request->request_sizes;
1219 dma.granted_count = 0;
1220
1221 do {
1222 ret = ioctl( fd, DRM_IOCTL_DMA, &dma );
1223 } while ( ret && errno == EAGAIN && i++ < DRM_DMA_RETRY );
1224
1225 if ( ret == 0 ) {
1226 request->granted_count = dma.granted_count;
1227 return 0;
1228 } else {
1229 return -errno;
1230 }
1231 }
1232
1233
1234 /**
1235 * Obtain heavyweight hardware lock.
1236 *
1237 * \param fd file descriptor.
1238 * \param context context.
1239 * \param flags flags that determine the sate of the hardware when the function
1240 * returns.
1241 *
1242 * \return always zero.
1243 *
1244 * \internal
1245 * This function translates the arguments into a drm_lock structure and issue
1246 * the DRM_IOCTL_LOCK ioctl until the lock is successfully acquired.
1247 */
1248 int drmGetLock(int fd, drm_context_t context, drmLockFlags flags)
1249 {
1250 drm_lock_t lock;
1251
1252 lock.context = context;
1253 lock.flags = 0;
1254 if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY;
1255 if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT;
1256 if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH;
1257 if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL;
1258 if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
1259 if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
1260
1261 while (ioctl(fd, DRM_IOCTL_LOCK, &lock))
1262 ;
1263 return 0;
1264 }
1265
1266 /**
1267 * Release the hardware lock.
1268 *
1269 * \param fd file descriptor.
1270 * \param context context.
1271 *
1272 * \return zero on success, or a negative value on failure.
1273 *
1274 * \internal
1275 * This function is a wrapper around the DRM_IOCTL_UNLOCK ioctl, passing the
1276 * argument in a drm_lock structure.
1277 */
1278 int drmUnlock(int fd, drm_context_t context)
1279 {
1280 drm_lock_t lock;
1281
1282 lock.context = context;
1283 lock.flags = 0;
1284 return ioctl(fd, DRM_IOCTL_UNLOCK, &lock);
1285 }
1286
1287 drm_context_t * drmGetReservedContextList(int fd, int *count)
1288 {
1289 drm_ctx_res_t res;
1290 drm_ctx_t *list;
1291 drm_context_t * retval;
1292 int i;
1293
1294 res.count = 0;
1295 res.contexts = NULL;
1296 if (ioctl(fd, DRM_IOCTL_RES_CTX, &res)) return NULL;
1297
1298 if (!res.count) return NULL;
1299
1300 if (!(list = drmMalloc(res.count * sizeof(*list)))) return NULL;
1301 if (!(retval = drmMalloc(res.count * sizeof(*retval)))) {
1302 drmFree(list);
1303 return NULL;
1304 }
1305
1306 res.contexts = list;
1307 if (ioctl(fd, DRM_IOCTL_RES_CTX, &res)) return NULL;
1308
1309 for (i = 0; i < res.count; i++) retval[i] = list[i].handle;
1310 drmFree(list);
1311
1312 *count = res.count;
1313 return retval;
1314 }
1315
1316 void drmFreeReservedContextList(drm_context_t * pt)
1317 {
1318 drmFree(pt);
1319 }
1320
1321 /**
1322 * Create context.
1323 *
1324 * Used by the X server during GLXContext initialization. This causes
1325 * per-context kernel-level resources to be allocated.
1326 *
1327 * \param fd file descriptor.
1328 * \param handle is set on success. To be used by the client when requesting DMA
1329 * dispatch with drmDMA().
1330 *
1331 * \return zero on success, or a negative value on failure.
1332 *
1333 * \note May only be called by root.
1334 *
1335 * \internal
1336 * This function is a wrapper around the DRM_IOCTL_ADD_CTX ioctl, passing the
1337 * argument in a drm_ctx structure.
1338 */
1339 int drmCreateContext(int fd, drm_context_t * handle)
1340 {
1341 drm_ctx_t ctx;
1342
1343 ctx.flags = 0; /* Modified with functions below */
1344 if (ioctl(fd, DRM_IOCTL_ADD_CTX, &ctx)) return -errno;
1345 *handle = ctx.handle;
1346 return 0;
1347 }
1348
1349 int drmSwitchToContext(int fd, drm_context_t context)
1350 {
1351 drm_ctx_t ctx;
1352
1353 ctx.handle = context;
1354 if (ioctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx)) return -errno;
1355 return 0;
1356 }
1357
1358 int drmSetContextFlags(int fd, drm_context_t context, drm_context_tFlags flags)
1359 {
1360 drm_ctx_t ctx;
1361
1362 /* Context preserving means that no context
1363 switched are done between DMA buffers
1364 from one context and the next. This is
1365 suitable for use in the X server (which
1366 promises to maintain hardware context,
1367 or in the client-side library when
1368 buffers are swapped on behalf of two
1369 threads. */
1370 ctx.handle = context;
1371 ctx.flags = 0;
1372 if (flags & DRM_CONTEXT_PRESERVED) ctx.flags |= _DRM_CONTEXT_PRESERVED;
1373 if (flags & DRM_CONTEXT_2DONLY) ctx.flags |= _DRM_CONTEXT_2DONLY;
1374 if (ioctl(fd, DRM_IOCTL_MOD_CTX, &ctx)) return -errno;
1375 return 0;
1376 }
1377
1378 int drmGetContextFlags(int fd, drm_context_t context, drm_context_tFlagsPtr flags)
1379 {
1380 drm_ctx_t ctx;
1381
1382 ctx.handle = context;
1383 if (ioctl(fd, DRM_IOCTL_GET_CTX, &ctx)) return -errno;
1384 *flags = 0;
1385 if (ctx.flags & _DRM_CONTEXT_PRESERVED) *flags |= DRM_CONTEXT_PRESERVED;
1386 if (ctx.flags & _DRM_CONTEXT_2DONLY) *flags |= DRM_CONTEXT_2DONLY;
1387 return 0;
1388 }
1389
1390 /**
1391 * Destroy context.
1392 *
1393 * Free any kernel-level resources allocated with drmCreateContext() associated
1394 * with the context.
1395 *
1396 * \param fd file descriptor.
1397 * \param handle handle given by drmCreateContext().
1398 *
1399 * \return zero on success, or a negative value on failure.
1400 *
1401 * \note May only be called by root.
1402 *
1403 * \internal
1404 * This function is a wrapper around the DRM_IOCTL_RM_CTX ioctl, passing the
1405 * argument in a drm_ctx structure.
1406 */
1407 int drmDestroyContext(int fd, drm_context_t handle)
1408 {
1409 drm_ctx_t ctx;
1410 ctx.handle = handle;
1411 if (ioctl(fd, DRM_IOCTL_RM_CTX, &ctx)) return -errno;
1412 return 0;
1413 }
1414
1415 int drmCreateDrawable(int fd, drm_drawable_t * handle)
1416 {
1417 drm_draw_t draw;
1418 if (ioctl(fd, DRM_IOCTL_ADD_DRAW, &draw)) return -errno;
1419 *handle = draw.handle;
1420 return 0;
1421 }
1422
1423 int drmDestroyDrawable(int fd, drm_drawable_t handle)
1424 {
1425 drm_draw_t draw;
1426 draw.handle = handle;
1427 if (ioctl(fd, DRM_IOCTL_RM_DRAW, &draw)) return -errno;
1428 return 0;
1429 }
1430
1431 /**
1432 * Acquire the AGP device.
1433 *
1434 * Must be called before any of the other AGP related calls.
1435 *
1436 * \param fd file descriptor.
1437 *
1438 * \return zero on success, or a negative value on failure.
1439 *
1440 * \internal
1441 * This function is a wrapper around the DRM_IOCTL_AGP_ACQUIRE ioctl.
1442 */
1443 int drmAgpAcquire(int fd)
1444 {
1445 if (ioctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL)) return -errno;
1446 return 0;
1447 }
1448
1449
1450 /**
1451 * Release the AGP device.
1452 *
1453 * \param fd file descriptor.
1454 *
1455 * \return zero on success, or a negative value on failure.
1456 *
1457 * \internal
1458 * This function is a wrapper around the DRM_IOCTL_AGP_RELEASE ioctl.
1459 */
1460 int drmAgpRelease(int fd)
1461 {
1462 if (ioctl(fd, DRM_IOCTL_AGP_RELEASE, NULL)) return -errno;
1463 return 0;
1464 }
1465
1466
1467 /**
1468 * Set the AGP mode.
1469 *
1470 * \param fd file descriptor.
1471 * \param mode AGP mode.
1472 *
1473 * \return zero on success, or a negative value on failure.
1474 *
1475 * \internal
1476 * This function is a wrapper around the DRM_IOCTL_AGP_ENABLE ioctl, passing the
1477 * argument in a drm_agp_mode structure.
1478 */
1479 int drmAgpEnable(int fd, unsigned long mode)
1480 {
1481 drm_agp_mode_t m;
1482
1483 m.mode = mode;
1484 if (ioctl(fd, DRM_IOCTL_AGP_ENABLE, &m)) return -errno;
1485 return 0;
1486 }
1487
1488
1489 /**
1490 * Allocate a chunk of AGP memory.
1491 *
1492 * \param fd file descriptor.
1493 * \param size requested memory size in bytes. Will be rounded to page boundary.
1494 * \param type type of memory to allocate.
1495 * \param address if not zero, will be set to the physical address of the
1496 * allocated memory.
1497 * \param handle on success will be set to a handle of the allocated memory.
1498 *
1499 * \return zero on success, or a negative value on failure.
1500 *
1501 * \internal
1502 * This function is a wrapper around the DRM_IOCTL_AGP_ALLOC ioctl, passing the
1503 * arguments in a drm_agp_buffer structure.
1504 */
1505 int drmAgpAlloc(int fd, unsigned long size, unsigned long type,
1506 unsigned long *address, unsigned long *handle)
1507 {
1508 drm_agp_buffer_t b;
1509
1510 *handle = DRM_AGP_NO_HANDLE;
1511 b.size = size;
1512 b.handle = 0;
1513 b.type = type;
1514 if (ioctl(fd, DRM_IOCTL_AGP_ALLOC, &b)) return -errno;
1515 if (address != 0UL) *address = b.physical;
1516 *handle = b.handle;
1517 return 0;
1518 }
1519
1520
1521 /**
1522 * Free a chunk of AGP memory.
1523 *
1524 * \param fd file descriptor.
1525 * \param handle handle to the allocated memory, as given by drmAgpAllocate().
1526 *
1527 * \return zero on success, or a negative value on failure.
1528 *
1529 * \internal
1530 * This function is a wrapper around the DRM_IOCTL_AGP_FREE ioctl, passing the
1531 * argument in a drm_agp_buffer structure.
1532 */
1533 int drmAgpFree(int fd, unsigned long handle)
1534 {
1535 drm_agp_buffer_t b;
1536
1537 b.size = 0;
1538 b.handle = handle;
1539 if (ioctl(fd, DRM_IOCTL_AGP_FREE, &b)) return -errno;
1540 return 0;
1541 }
1542
1543
1544 /**
1545 * Bind a chunk of AGP memory.
1546 *
1547 * \param fd file descriptor.
1548 * \param handle handle to the allocated memory, as given by drmAgpAllocate().
1549 * \param offset offset in bytes. It will round to page boundary.
1550 *
1551 * \return zero on success, or a negative value on failure.
1552 *
1553 * \internal
1554 * This function is a wrapper around the DRM_IOCTL_AGP_BIND ioctl, passing the
1555 * argument in a drm_agp_binding structure.
1556 */
1557 int drmAgpBind(int fd, unsigned long handle, unsigned long offset)
1558 {
1559 drm_agp_binding_t b;
1560
1561 b.handle = handle;
1562 b.offset = offset;
1563 if (ioctl(fd, DRM_IOCTL_AGP_BIND, &b)) return -errno;
1564 return 0;
1565 }
1566
1567
1568 /**
1569 * Unbind a chunk of AGP memory.
1570 *
1571 * \param fd file descriptor.
1572 * \param handle handle to the allocated memory, as given by drmAgpAllocate().
1573 *
1574 * \return zero on success, or a negative value on failure.
1575 *
1576 * \internal
1577 * This function is a wrapper around the DRM_IOCTL_AGP_UNBIND ioctl, passing
1578 * the argument in a drm_agp_binding structure.
1579 */
1580 int drmAgpUnbind(int fd, unsigned long handle)
1581 {
1582 drm_agp_binding_t b;
1583
1584 b.handle = handle;
1585 b.offset = 0;
1586 if (ioctl(fd, DRM_IOCTL_AGP_UNBIND, &b)) return -errno;
1587 return 0;
1588 }
1589
1590
1591 /**
1592 * Get AGP driver major version number.
1593 *
1594 * \param fd file descriptor.
1595 *
1596 * \return major version number on success, or a negative value on failure..
1597 *
1598 * \internal
1599 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1600 * necessary information in a drm_agp_info structure.
1601 */
1602 int drmAgpVersionMajor(int fd)
1603 {
1604 drm_agp_info_t i;
1605
1606 if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno;
1607 return i.agp_version_major;
1608 }
1609
1610
1611 /**
1612 * Get AGP driver minor version number.
1613 *
1614 * \param fd file descriptor.
1615 *
1616 * \return minor version number on success, or a negative value on failure.
1617 *
1618 * \internal
1619 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1620 * necessary information in a drm_agp_info structure.
1621 */
1622 int drmAgpVersionMinor(int fd)
1623 {
1624 drm_agp_info_t i;
1625
1626 if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno;
1627 return i.agp_version_minor;
1628 }
1629
1630
1631 /**
1632 * Get AGP mode.
1633 *
1634 * \param fd file descriptor.
1635 *
1636 * \return mode on success, or zero on failure.
1637 *
1638 * \internal
1639 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1640 * necessary information in a drm_agp_info structure.
1641 */
1642 unsigned long drmAgpGetMode(int fd)
1643 {
1644 drm_agp_info_t i;
1645
1646 if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
1647 return i.mode;
1648 }
1649
1650
1651 /**
1652 * Get AGP aperture base.
1653 *
1654 * \param fd file descriptor.
1655 *
1656 * \return aperture base on success, zero on failure.
1657 *
1658 * \internal
1659 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1660 * necessary information in a drm_agp_info structure.
1661 */
1662 unsigned long drmAgpBase(int fd)
1663 {
1664 drm_agp_info_t i;
1665
1666 if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
1667 return i.aperture_base;
1668 }
1669
1670
1671 /**
1672 * Get AGP aperture size.
1673 *
1674 * \param fd file descriptor.
1675 *
1676 * \return aperture size on success, zero on failure.
1677 *
1678 * \internal
1679 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1680 * necessary information in a drm_agp_info structure.
1681 */
1682 unsigned long drmAgpSize(int fd)
1683 {
1684 drm_agp_info_t i;
1685
1686 if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
1687 return i.aperture_size;
1688 }
1689
1690
1691 /**
1692 * Get used AGP memory.
1693 *
1694 * \param fd file descriptor.
1695 *
1696 * \return memory used on success, or zero on failure.
1697 *
1698 * \internal
1699 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1700 * necessary information in a drm_agp_info structure.
1701 */
1702 unsigned long drmAgpMemoryUsed(int fd)
1703 {
1704 drm_agp_info_t i;
1705
1706 if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
1707 return i.memory_used;
1708 }
1709
1710
1711 /**
1712 * Get available AGP memory.
1713 *
1714 * \param fd file descriptor.
1715 *
1716 * \return memory available on success, or zero on failure.
1717 *
1718 * \internal
1719 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1720 * necessary information in a drm_agp_info structure.
1721 */
1722 unsigned long drmAgpMemoryAvail(int fd)
1723 {
1724 drm_agp_info_t i;
1725
1726 if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
1727 return i.memory_allowed;
1728 }
1729
1730
1731 /**
1732 * Get hardware vendor ID.
1733 *
1734 * \param fd file descriptor.
1735 *
1736 * \return vendor ID on success, or zero on failure.
1737 *
1738 * \internal
1739 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1740 * necessary information in a drm_agp_info structure.
1741 */
1742 unsigned int drmAgpVendorId(int fd)
1743 {
1744 drm_agp_info_t i;
1745
1746 if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
1747 return i.id_vendor;
1748 }
1749
1750
1751 /**
1752 * Get hardware device ID.
1753 *
1754 * \param fd file descriptor.
1755 *
1756 * \return zero on success, or zero on failure.
1757 *
1758 * \internal
1759 * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
1760 * necessary information in a drm_agp_info structure.
1761 */
1762 unsigned int drmAgpDeviceId(int fd)
1763 {
1764 drm_agp_info_t i;
1765
1766 if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
1767 return i.id_device;
1768 }
1769
1770 int drmScatterGatherAlloc(int fd, unsigned long size, unsigned long *handle)
1771 {
1772 drm_scatter_gather_t sg;
1773
1774 *handle = 0;
1775 sg.size = size;
1776 sg.handle = 0;
1777 if (ioctl(fd, DRM_IOCTL_SG_ALLOC, &sg)) return -errno;
1778 *handle = sg.handle;
1779 return 0;
1780 }
1781
1782 int drmScatterGatherFree(int fd, unsigned long handle)
1783 {
1784 drm_scatter_gather_t sg;
1785
1786 sg.size = 0;
1787 sg.handle = handle;
1788 if (ioctl(fd, DRM_IOCTL_SG_FREE, &sg)) return -errno;
1789 return 0;
1790 }
1791
1792 /**
1793 * Wait for VBLANK.
1794 *
1795 * \param fd file descriptor.
1796 * \param vbl pointer to a drmVBlank structure.
1797 *
1798 * \return zero on success, or a negative value on failure.
1799 *
1800 * \internal
1801 * This function is a wrapper around the DRM_IOCTL_WAIT_VBLANK ioctl.
1802 */
1803 int drmWaitVBlank(int fd, drmVBlankPtr vbl)
1804 {
1805 int ret;
1806
1807 do {
1808 ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl);
1809 vbl->request.type &= ~DRM_VBLANK_RELATIVE;
1810 } while (ret && errno == EINTR);
1811
1812 return ret;
1813 }
1814
1815 int drmError(int err, const char *label)
1816 {
1817 switch (err) {
1818 case DRM_ERR_NO_DEVICE: fprintf(stderr, "%s: no device\n", label); break;
1819 case DRM_ERR_NO_ACCESS: fprintf(stderr, "%s: no access\n", label); break;
1820 case DRM_ERR_NOT_ROOT: fprintf(stderr, "%s: not root\n", label); break;
1821 case DRM_ERR_INVALID: fprintf(stderr, "%s: invalid args\n", label);break;
1822 default:
1823 if (err < 0) err = -err;
1824 fprintf( stderr, "%s: error %d (%s)\n", label, err, strerror(err) );
1825 break;
1826 }
1827
1828 return 1;
1829 }
1830
1831 /**
1832 * Install IRQ handler.
1833 *
1834 * \param fd file descriptor.
1835 * \param irq IRQ number.
1836 *
1837 * \return zero on success, or a negative value on failure.
1838 *
1839 * \internal
1840 * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
1841 * argument in a drm_control structure.
1842 */
1843 int drmCtlInstHandler(int fd, int irq)
1844 {
1845 drm_control_t ctl;
1846
1847 ctl.func = DRM_INST_HANDLER;
1848 ctl.irq = irq;
1849 if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl)) return -errno;
1850 return 0;
1851 }
1852
1853
1854 /**
1855 * Uninstall IRQ handler.
1856 *
1857 * \param fd file descriptor.
1858 *
1859 * \return zero on success, or a negative value on failure.
1860 *
1861 * \internal
1862 * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
1863 * argument in a drm_control structure.
1864 */
1865 int drmCtlUninstHandler(int fd)
1866 {
1867 drm_control_t ctl;
1868
1869 ctl.func = DRM_UNINST_HANDLER;
1870 ctl.irq = 0;
1871 if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl)) return -errno;
1872 return 0;
1873 }
1874
1875 int drmFinish(int fd, int context, drmLockFlags flags)
1876 {
1877 drm_lock_t lock;
1878
1879 lock.context = context;
1880 lock.flags = 0;
1881 if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY;
1882 if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT;
1883 if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH;
1884 if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL;
1885 if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
1886 if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
1887 if (ioctl(fd, DRM_IOCTL_FINISH, &lock)) return -errno;
1888 return 0;
1889 }
1890
1891 /**
1892 * Get IRQ from bus ID.
1893 *
1894 * \param fd file descriptor.
1895 * \param busnum bus number.
1896 * \param devnum device number.
1897 * \param funcnum function number.
1898 *
1899 * \return IRQ number on success, or a negative value on failure.
1900 *
1901 * \internal
1902 * This function is a wrapper around the DRM_IOCTL_IRQ_BUSID ioctl, passing the
1903 * arguments in a drm_irq_busid structure.
1904 */
1905 int drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum)
1906 {
1907 drm_irq_busid_t p;
1908
1909 p.busnum = busnum;
1910 p.devnum = devnum;
1911 p.funcnum = funcnum;
1912 if (ioctl(fd, DRM_IOCTL_IRQ_BUSID, &p)) return -errno;
1913 return p.irq;
1914 }
1915
1916 int drmAddContextTag(int fd, drm_context_t context, void *tag)
1917 {
1918 drmHashEntry *entry = drmGetEntry(fd);
1919
1920 if (drmHashInsert(entry->tagTable, context, tag)) {
1921 drmHashDelete(entry->tagTable, context);
1922 drmHashInsert(entry->tagTable, context, tag);
1923 }
1924 return 0;
1925 }
1926
1927 int drmDelContextTag(int fd, drm_context_t context)
1928 {
1929 drmHashEntry *entry = drmGetEntry(fd);
1930
1931 return drmHashDelete(entry->tagTable, context);
1932 }
1933
1934 void *drmGetContextTag(int fd, drm_context_t context)
1935 {
1936 drmHashEntry *entry = drmGetEntry(fd);
1937 void *value;
1938
1939 if (drmHashLookup(entry->tagTable, context, &value)) return NULL;
1940
1941 return value;
1942 }
1943
1944 int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id, drm_handle_t handle)
1945 {
1946 drm_ctx_priv_map_t map;
1947
1948 map.ctx_id = ctx_id;
1949 map.handle = (void *)handle;
1950
1951 if (ioctl(fd, DRM_IOCTL_SET_SAREA_CTX, &map)) return -errno;
1952 return 0;
1953 }
1954
1955 int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id, drm_handle_t * handle)
1956 {
1957 drm_ctx_priv_map_t map;
1958
1959 map.ctx_id = ctx_id;
1960
1961 if (ioctl(fd, DRM_IOCTL_GET_SAREA_CTX, &map)) return -errno;
1962 if (handle) *handle = (drm_handle_t)map.handle;
1963
1964 return 0;
1965 }
1966
1967 int drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size,
1968 drmMapType *type, drmMapFlags *flags, drm_handle_t *handle,
1969 int *mtrr)
1970 {
1971 drm_map_t map;
1972
1973 map.offset = idx;
1974 if (ioctl(fd, DRM_IOCTL_GET_MAP, &map)) return -errno;
1975 *offset = map.offset;
1976 *size = map.size;
1977 *type = map.type;
1978 *flags = map.flags;
1979 *handle = (unsigned long)map.handle;
1980 *mtrr = map.mtrr;
1981 return 0;
1982 }
1983
1984 int drmGetClient(int fd, int idx, int *auth, int *pid, int *uid,
1985 unsigned long *magic, unsigned long *iocs)
1986 {
1987 drm_client_t client;
1988
1989 client.idx = idx;
1990 if (ioctl(fd, DRM_IOCTL_GET_CLIENT, &client)) return -errno;
1991 *auth = client.auth;
1992 *pid = client.pid;
1993 *uid = client.uid;
1994 *magic = client.magic;
1995 *iocs = client.iocs;
1996 return 0;
1997 }
1998
1999 int drmGetStats(int fd, drmStatsT *stats)
2000 {
2001 drm_stats_t s;
2002 int i;
2003
2004 if (ioctl(fd, DRM_IOCTL_GET_STATS, &s)) return -errno;
2005
2006 stats->count = 0;
2007 memset(stats, 0, sizeof(*stats));
2008 if (s.count > sizeof(stats->data)/sizeof(stats->data[0]))
2009 return -1;
2010
2011 #define SET_VALUE \
2012 stats->data[i].long_format = "%-20.20s"; \
2013 stats->data[i].rate_format = "%8.8s"; \
2014 stats->data[i].isvalue = 1; \
2015 stats->data[i].verbose = 0
2016
2017 #define SET_COUNT \
2018 stats->data[i].long_format = "%-20.20s"; \
2019 stats->data[i].rate_format = "%5.5s"; \
2020 stats->data[i].isvalue = 0; \
2021 stats->data[i].mult_names = "kgm"; \
2022 stats->data[i].mult = 1000; \
2023 stats->data[i].verbose = 0
2024
2025 #define SET_BYTE \
2026 stats->data[i].long_format = "%-20.20s"; \
2027 stats->data[i].rate_format = "%5.5s"; \
2028 stats->data[i].isvalue = 0; \
2029 stats->data[i].mult_names = "KGM"; \
2030 stats->data[i].mult = 1024; \
2031 stats->data[i].verbose = 0
2032
2033
2034 stats->count = s.count;
2035 for (i = 0; i < s.count; i++) {
2036 stats->data[i].value = s.data[i].value;
2037 switch (s.data[i].type) {
2038 case _DRM_STAT_LOCK:
2039 stats->data[i].long_name = "Lock";
2040 stats->data[i].rate_name = "Lock";
2041 SET_VALUE;
2042 break;
2043 case _DRM_STAT_OPENS:
2044 stats->data[i].long_name = "Opens";
2045 stats->data[i].rate_name = "O";
2046 SET_COUNT;
2047 stats->data[i].verbose = 1;
2048 break;
2049 case _DRM_STAT_CLOSES:
2050 stats->data[i].long_name = "Closes";
2051 stats->data[i].rate_name = "Lock";
2052 SET_COUNT;
2053 stats->data[i].verbose = 1;
2054 break;
2055 case _DRM_STAT_IOCTLS:
2056 stats->data[i].long_name = "Ioctls";
2057 stats->data[i].rate_name = "Ioc/s";
2058 SET_COUNT;
2059 break;
2060 case _DRM_STAT_LOCKS:
2061 stats->data[i].long_name = "Locks";
2062 stats->data[i].rate_name = "Lck/s";
2063 SET_COUNT;
2064 break;
2065 case _DRM_STAT_UNLOCKS:
2066 stats->data[i].long_name = "Unlocks";
2067 stats->data[i].rate_name = "Unl/s";
2068 SET_COUNT;
2069 break;
2070 case _DRM_STAT_IRQ:
2071 stats->data[i].long_name = "IRQs";
2072 stats->data[i].rate_name = "IRQ/s";
2073 SET_COUNT;
2074 break;
2075 case _DRM_STAT_PRIMARY:
2076 stats->data[i].long_name = "Primary Bytes";
2077 stats->data[i].rate_name = "PB/s";
2078 SET_BYTE;
2079 break;
2080 case _DRM_STAT_SECONDARY:
2081 stats->data[i].long_name = "Secondary Bytes";
2082 stats->data[i].rate_name = "SB/s";
2083 SET_BYTE;
2084 break;
2085 case _DRM_STAT_DMA:
2086 stats->data[i].long_name = "DMA";
2087 stats->data[i].rate_name = "DMA/s";
2088 SET_COUNT;
2089 break;
2090 case _DRM_STAT_SPECIAL:
2091 stats->data[i].long_name = "Special DMA";
2092 stats->data[i].rate_name = "dma/s";
2093 SET_COUNT;
2094 break;
2095 case _DRM_STAT_MISSED:
2096 stats->data[i].long_name = "Miss";
2097 stats->data[i].rate_name = "Ms/s";
2098 SET_COUNT;
2099 break;
2100 case _DRM_STAT_VALUE:
2101 stats->data[i].long_name = "Value";
2102 stats->data[i].rate_name = "Value";
2103 SET_VALUE;
2104 break;
2105 case _DRM_STAT_BYTE:
2106 stats->data[i].long_name = "Bytes";
2107 stats->data[i].rate_name = "B/s";
2108 SET_BYTE;
2109 break;
2110 case _DRM_STAT_COUNT:
2111 default:
2112 stats->data[i].long_name = "Count";
2113 stats->data[i].rate_name = "Cnt/s";
2114 SET_COUNT;
2115 break;
2116 }
2117 }
2118 return 0;
2119 }
2120
2121 /**
2122 * Issue a set-version ioctl.
2123 *
2124 * \param fd file descriptor.
2125 * \param drmCommandIndex command index
2126 * \param data source pointer of the data to be read and written.
2127 * \param size size of the data to be read and written.
2128 *
2129 * \return zero on success, or a negative value on failure.
2130 *
2131 * \internal
2132 * It issues a read-write ioctl given by
2133 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2134 */
2135 int drmSetInterfaceVersion(int fd, drmSetVersion *version )
2136 {
2137 int retcode = 0;
2138 drm_set_version_t sv;
2139
2140 sv.drm_di_major = version->drm_di_major;
2141 sv.drm_di_minor = version->drm_di_minor;
2142 sv.drm_dd_major = version->drm_dd_major;
2143 sv.drm_dd_minor = version->drm_dd_minor;
2144
2145 if (ioctl(fd, DRM_IOCTL_SET_VERSION, &sv)) {
2146 retcode = -errno;
2147 }
2148
2149 version->drm_di_major = sv.drm_di_major;
2150 version->drm_di_minor = sv.drm_di_minor;
2151 version->drm_dd_major = sv.drm_dd_major;
2152 version->drm_dd_minor = sv.drm_dd_minor;
2153
2154 return retcode;
2155 }
2156
2157 /**
2158 * Send a device-specific command.
2159 *
2160 * \param fd file descriptor.
2161 * \param drmCommandIndex command index
2162 *
2163 * \return zero on success, or a negative value on failure.
2164 *
2165 * \internal
2166 * It issues a ioctl given by
2167 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2168 */
2169 int drmCommandNone(int fd, unsigned long drmCommandIndex)
2170 {
2171 void *data = NULL; /* dummy */
2172 unsigned long request;
2173
2174 request = DRM_IO( DRM_COMMAND_BASE + drmCommandIndex);
2175
2176 if (ioctl(fd, request, data)) {
2177 return -errno;
2178 }
2179 return 0;
2180 }
2181
2182
2183 /**
2184 * Send a device-specific read command.
2185 *
2186 * \param fd file descriptor.
2187 * \param drmCommandIndex command index
2188 * \param data destination pointer of the data to be read.
2189 * \param size size of the data to be read.
2190 *
2191 * \return zero on success, or a negative value on failure.
2192 *
2193 * \internal
2194 * It issues a read ioctl given by
2195 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2196 */
2197 int drmCommandRead(int fd, unsigned long drmCommandIndex,
2198 void *data, unsigned long size )
2199 {
2200 unsigned long request;
2201
2202 request = DRM_IOC( DRM_IOC_READ, DRM_IOCTL_BASE,
2203 DRM_COMMAND_BASE + drmCommandIndex, size);
2204
2205 if (ioctl(fd, request, data)) {
2206 return -errno;
2207 }
2208 return 0;
2209 }
2210
2211
2212 /**
2213 * Send a device-specific write command.
2214 *
2215 * \param fd file descriptor.
2216 * \param drmCommandIndex command index
2217 * \param data source pointer of the data to be written.
2218 * \param size size of the data to be written.
2219 *
2220 * \return zero on success, or a negative value on failure.
2221 *
2222 * \internal
2223 * It issues a write ioctl given by
2224 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2225 */
2226 int drmCommandWrite(int fd, unsigned long drmCommandIndex,
2227 void *data, unsigned long size )
2228 {
2229 unsigned long request;
2230
2231 request = DRM_IOC( DRM_IOC_WRITE, DRM_IOCTL_BASE,
2232 DRM_COMMAND_BASE + drmCommandIndex, size);
2233
2234 if (ioctl(fd, request, data)) {
2235 return -errno;
2236 }
2237 return 0;
2238 }
2239
2240
2241 /**
2242 * Send a device-specific read-write command.
2243 *
2244 * \param fd file descriptor.
2245 * \param drmCommandIndex command index
2246 * \param data source pointer of the data to be read and written.
2247 * \param size size of the data to be read and written.
2248 *
2249 * \return zero on success, or a negative value on failure.
2250 *
2251 * \internal
2252 * It issues a read-write ioctl given by
2253 * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
2254 */
2255 int drmCommandWriteRead(int fd, unsigned long drmCommandIndex,
2256 void *data, unsigned long size )
2257 {
2258 unsigned long request;
2259
2260 request = DRM_IOC( DRM_IOC_READ|DRM_IOC_WRITE, DRM_IOCTL_BASE,
2261 DRM_COMMAND_BASE + drmCommandIndex, size);
2262
2263 if (ioctl(fd, request, data)) {
2264 return -errno;
2265 }
2266 return 0;
2267 }
2268
2269 #if defined(XFree86Server)
2270 static void drmSIGIOHandler(int interrupt, void *closure)
2271 {
2272 unsigned long key;
2273 void *value;
2274 ssize_t count;
2275 drm_ctx_t ctx;
2276 typedef void (*_drmCallback)(int, void *, void *);
2277 char buf[256];
2278 drm_context_t old;
2279 drm_context_t new;
2280 void *oldctx;
2281 void *newctx;
2282 char *pt;
2283 drmHashEntry *entry;
2284
2285 if (!drmHashTable) return;
2286 if (drmHashFirst(drmHashTable, &key, &value)) {
2287 entry = value;
2288 do {
2289 #if 0
2290 fprintf(stderr, "Trying %d\n", entry->fd);
2291 #endif
2292 if ((count = read(entry->fd, buf, sizeof(buf))) > 0) {
2293 buf[count] = '\0';
2294 #if 0
2295 fprintf(stderr, "Got %s\n", buf);
2296 #endif
2297
2298 for (pt = buf; *pt != ' '; ++pt); /* Find first space */
2299 ++pt;
2300 old = strtol(pt, &pt, 0);
2301 new = strtol(pt, NULL, 0);
2302 oldctx = drmGetContextTag(entry->fd, old);
2303 newctx = drmGetContextTag(entry->fd, new);
2304 #if 0
2305 fprintf(stderr, "%d %d %p %p\n", old, new, oldctx, newctx);
2306 #endif
2307 ((_drmCallback)entry->f)(entry->fd, oldctx, newctx);
2308 ctx.handle = new;
2309 ioctl(entry->fd, DRM_IOCTL_NEW_CTX, &ctx);
2310 }
2311 } while (drmHashNext(drmHashTable, &key, &value));
2312 }
2313 }
2314
2315 int drmInstallSIGIOHandler(int fd, void (*f)(int, void *, void *))
2316 {
2317 drmHashEntry *entry;
2318
2319 entry = drmGetEntry(fd);
2320 entry->f = f;
2321
2322 return xf86InstallSIGIOHandler(fd, drmSIGIOHandler, 0);
2323 }
2324
2325 int drmRemoveSIGIOHandler(int fd)
2326 {
2327 drmHashEntry *entry = drmGetEntry(fd);
2328
2329 entry->f = NULL;
2330
2331 return xf86RemoveSIGIOHandler(fd);
2332 }
2333 #endif