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