xf86drm.c revision e1dba5c3a73078dec24f07a6d685435677db94a4
1/* xf86drm.c -- User-level interface to DRM device 2 * Created: Tue Jan 5 08:16:21 1999 by faith@precisioninsight.com 3 * Revised: Mon Dec 6 11:34:13 1999 by faith@precisioninsight.com 4 * 5 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 6 * All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the next 16 * paragraph) shall be included in all copies or substantial portions of the 17 * Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 * DEALINGS IN THE SOFTWARE. 26 * 27 * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c,v 1.43 1999/08/04 18:14:43 faith Exp $ 28 * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c,v 1.5 1999/10/13 22:33:07 dawes Exp $ 29 * 30 */ 31 32#ifdef XFree86Server 33# include "xf86.h" 34# include "xf86_OSproc.h" 35# include "xf86_ansic.h" 36# include "xf86Priv.h" 37# define _DRM_MALLOC xalloc 38# define _DRM_FREE xfree 39# ifndef XFree86LOADER 40# include <sys/stat.h> 41# include <sys/mman.h> 42# endif 43#else 44# include <stdio.h> 45# include <stdlib.h> 46# include <unistd.h> 47# include <string.h> 48# include <ctype.h> 49# include <fcntl.h> 50# include <errno.h> 51# include <signal.h> 52# include <sys/types.h> 53# include <sys/stat.h> 54# include <sys/ioctl.h> 55# include <sys/mman.h> 56# include <sys/time.h> 57# ifdef DRM_USE_MALLOC 58# define _DRM_MALLOC malloc 59# define _DRM_FREE free 60extern int xf86InstallSIGIOHandler(int fd, void (*f)(int, void *), void *); 61extern int xf86RemoveSIGIOHandler(int fd); 62# else 63# include <Xlibint.h> 64# define _DRM_MALLOC Xmalloc 65# define _DRM_FREE Xfree 66# endif 67#endif 68 69/* Not all systems have MAP_FAILED defined */ 70#ifndef MAP_FAILED 71#define MAP_FAILED ((void *)-1) 72#endif 73 74#include <sys/sysmacros.h> /* for makedev() */ 75#include "xf86drm.h" 76#include "drm.h" 77 78static void *drmHashTable = NULL; /* Context switch callbacks */ 79 80typedef struct drmHashEntry { 81 int fd; 82 void (*f)(int, void *, void *); 83 void *tagTable; 84} drmHashEntry; 85 86void *drmMalloc(int size) 87{ 88 void *pt; 89 if ((pt = _DRM_MALLOC(size))) memset(pt, 0, size); 90 return pt; 91} 92 93void drmFree(void *pt) 94{ 95 if (pt) _DRM_FREE(pt); 96} 97 98static char *drmStrdup(const char *s) 99{ 100 return s ? strdup(s) : NULL; 101} 102 103 104static unsigned long drmGetKeyFromFd(int fd) 105{ 106#ifdef XFree86LOADER 107 struct xf86stat st; 108#else 109 struct stat st; 110#endif 111 112 st.st_rdev = 0; 113 fstat(fd, &st); 114 return st.st_rdev; 115} 116 117static drmHashEntry *drmGetEntry(int fd) 118{ 119 unsigned long key = drmGetKeyFromFd(fd); 120 void *value; 121 drmHashEntry *entry; 122 123 if (!drmHashTable) drmHashTable = drmHashCreate(); 124 125 if (drmHashLookup(drmHashTable, key, &value)) { 126 entry = drmMalloc(sizeof(*entry)); 127 entry->fd = fd; 128 entry->f = NULL; 129 entry->tagTable = drmHashCreate(); 130 drmHashInsert(drmHashTable, key, entry); 131 } else { 132 entry = value; 133 } 134 return entry; 135} 136 137/* drm_open is used to open the /dev/drm device */ 138 139static int drm_open(const char *file) 140{ 141 int fd = open(file, O_RDWR, 0); 142 143 if (fd >= 0) return fd; 144 return -errno; 145} 146 147/* drmAvailable looks for /proc/drm, and returns 1 if it is present. */ 148 149int drmAvailable(void) 150{ 151 if (!access("/proc/graphics/0", R_OK)) return 1; 152 return 0; 153} 154 155static int drmOpenDevice(const char *path, long dev, 156 mode_t mode, uid_t user, gid_t group) 157{ 158#ifdef XFree86LOADER 159 struct xf86stat st; 160#else 161 struct stat st; 162#endif 163 164 if (!stat(path, &st) && st.st_rdev == dev) return drm_open(path); 165 166 if (geteuid()) return DRM_ERR_NOT_ROOT; 167 remove(path); 168 if (mknod(path, S_IFCHR, dev)) { 169 remove(path); 170 return DRM_ERR_NOT_ROOT; 171 } 172 chown(path, user, group); 173 chmod(path, mode); 174 return drm_open(path); 175} 176 177static int drmOpenByBusid(const char *busid) 178{ 179 int i; 180 char dev_name[64]; 181 char *buf; 182 int fd; 183 184 for (i = 0; i < 8; i++) { 185 sprintf(dev_name, "/dev/graphics/card%d", i); 186 if ((fd = drm_open(dev_name)) >= 0) { 187 buf = drmGetBusid(fd); 188 if (buf && !strcmp(buf, busid)) { 189 drmFreeBusid(buf); 190 return fd; 191 } 192 if (buf) drmFreeBusid(buf); 193 close(fd); 194 } 195 } 196 return -1; 197} 198 199static int drmOpenByName(const char *name) 200{ 201 int i; 202 char proc_name[64]; 203 char dev_name[64]; 204 char buf[512]; 205 mode_t mode = DRM_DEV_MODE; 206 mode_t dirmode; 207 gid_t group = DRM_DEV_GID; 208 uid_t user = DRM_DEV_UID; 209 int fd; 210 char *pt; 211 char *driver = NULL; 212 char *devstring; 213 long dev = 0; 214 int retcode; 215 216#if defined(XFree86Server) 217 mode = xf86ConfigDRI.mode ? xf86ConfigDRI.mode : DRM_DEV_MODE; 218 group = xf86ConfigDRI.group ? xf86ConfigDRI.group : DRM_DEV_GID; 219#endif 220 221 if (!geteuid()) { 222 dirmode = mode; 223 if (dirmode & S_IRUSR) dirmode |= S_IXUSR; 224 if (dirmode & S_IRGRP) dirmode |= S_IXGRP; 225 if (dirmode & S_IROTH) dirmode |= S_IXOTH; 226 dirmode &= ~(S_IWGRP | S_IWOTH); 227 mkdir("/dev/graphics", 0); 228 chown("/dev/graphics", user, group); 229 chmod("/dev/graphics", dirmode); 230 } 231 232 for (i = 0; i < 8; i++) { 233 sprintf(proc_name, "/proc/graphics/%d/name", i); 234 sprintf(dev_name, "/dev/graphics/card%d", i); 235 if ((fd = open(proc_name, 0, 0)) >= 0) { 236 retcode = read(fd, buf, sizeof(buf)-1); 237 close(fd); 238 if (retcode) { 239 buf[retcode-1] = '\0'; 240 for (driver = pt = buf; *pt && *pt != ' '; ++pt) 241 ; 242 if (*pt) { /* Device is next */ 243 *pt = '\0'; 244 if (!strcmp(driver, name)) { /* Match */ 245 for (devstring = ++pt; *pt && *pt != ' '; ++pt) 246 ; 247 if (*pt) { /* Found busid */ 248 return drmOpenByBusid(++pt); 249 } else { /* No busid */ 250 dev = strtol(devstring, NULL, 0); 251 return drmOpenDevice(dev_name, dev, 252 mode, user, group); 253 } 254 } 255 } 256 } 257 } else remove(dev_name); 258 } 259 return -1; 260} 261 262/* drmOpen looks up the specified name and busid, and opens the device 263 found. The entry in /dev/graphics is created if necessary (and if root). 264 A file descriptor is returned. On error, the return value is 265 negative. */ 266 267int drmOpen(const char *name, const char *busid) 268{ 269 270 if (busid) return drmOpenByBusid(busid); 271 return drmOpenByName(name); 272} 273 274void drmFreeVersion(drmVersionPtr v) 275{ 276 if (!v) return; 277 if (v->name) drmFree(v->name); 278 if (v->date) drmFree(v->date); 279 if (v->desc) drmFree(v->desc); 280 drmFree(v); 281} 282 283static void drmFreeKernelVersion(drm_version_t *v) 284{ 285 if (!v) return; 286 if (v->name) drmFree(v->name); 287 if (v->date) drmFree(v->date); 288 if (v->desc) drmFree(v->desc); 289 drmFree(v); 290} 291 292static void drmCopyVersion(drmVersionPtr d, drm_version_t *s) 293{ 294 d->version_major = s->version_major; 295 d->version_minor = s->version_minor; 296 d->version_patchlevel = s->version_patchlevel; 297 d->name_len = s->name_len; 298 d->name = drmStrdup(s->name); 299 d->date_len = s->date_len; 300 d->date = drmStrdup(s->date); 301 d->desc_len = s->desc_len; 302 d->desc = drmStrdup(s->desc); 303} 304 305/* drmVersion obtains the version information via an ioctl. Similar 306 * information is available via /proc/drm. */ 307 308drmVersionPtr drmGetVersion(int fd) 309{ 310 drmVersionPtr retval; 311 drm_version_t *version = drmMalloc(sizeof(*version)); 312 313 /* First, get the lengths */ 314 version->name_len = 0; 315 version->name = NULL; 316 version->date_len = 0; 317 version->date = NULL; 318 version->desc_len = 0; 319 version->desc = NULL; 320 321 if (ioctl(fd, DRM_IOCTL_VERSION, version)) { 322 drmFreeKernelVersion(version); 323 return NULL; 324 } 325 326 /* Now, allocate space and get the data */ 327 if (version->name_len) 328 version->name = drmMalloc(version->name_len + 1); 329 if (version->date_len) 330 version->date = drmMalloc(version->date_len + 1); 331 if (version->desc_len) 332 version->desc = drmMalloc(version->desc_len + 1); 333 334 if (ioctl(fd, DRM_IOCTL_VERSION, version)) { 335 drmFreeKernelVersion(version); 336 return NULL; 337 } 338 339 /* The results might not be null-terminated 340 strings, so terminate them. */ 341 342 if (version->name_len) version->name[version->name_len] = '\0'; 343 if (version->date_len) version->date[version->date_len] = '\0'; 344 if (version->desc_len) version->desc[version->desc_len] = '\0'; 345 346 /* Now, copy it all back into the 347 client-visible data structure... */ 348 retval = drmMalloc(sizeof(*retval)); 349 drmCopyVersion(retval, version); 350 drmFreeKernelVersion(version); 351 return retval; 352} 353 354void drmFreeBusid(const char *busid) 355{ 356 drmFree((void *)busid); 357} 358 359char *drmGetBusid(int fd) 360{ 361 drm_unique_t u; 362 363 u.unique_len = 0; 364 u.unique = NULL; 365 366 if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL; 367 u.unique = drmMalloc(u.unique_len + 1); 368 if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL; 369 u.unique[u.unique_len] = '\0'; 370 return u.unique; 371} 372 373int drmSetBusid(int fd, const char *busid) 374{ 375 drm_unique_t u; 376 377 u.unique = (char *)busid; 378 u.unique_len = strlen(busid); 379 380 if (ioctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) return -errno; 381 return 0; 382} 383 384int drmGetMagic(int fd, drmMagicPtr magic) 385{ 386 drm_auth_t auth; 387 388 *magic = 0; 389 if (ioctl(fd, DRM_IOCTL_GET_MAGIC, &auth)) return -errno; 390 *magic = auth.magic; 391 return 0; 392} 393 394int drmAuthMagic(int fd, drmMagic magic) 395{ 396 drm_auth_t auth; 397 398 auth.magic = magic; 399 if (ioctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth)) return -errno; 400 return 0; 401} 402 403int drmAddMap(int fd, 404 drmHandle offset, 405 drmSize size, 406 drmMapType type, 407 drmMapFlags flags, 408 drmHandlePtr handle) 409{ 410 drm_map_t map; 411 412 map.offset = offset; 413 map.size = size; 414 map.handle = 0; 415 map.type = type; 416 map.flags = flags; 417 if (ioctl(fd, DRM_IOCTL_ADD_MAP, &map)) return -errno; 418 if (handle) *handle = (drmHandle)map.handle; 419 return 0; 420} 421 422int drmAddBufs(int fd, int count, int size, int flags) 423{ 424 drm_buf_desc_t request; 425 426 request.count = count; 427 request.size = size; 428 request.low_mark = 0; 429 request.high_mark = 0; 430 request.flags = flags; 431 if (ioctl(fd, DRM_IOCTL_ADD_BUFS, &request)) return -errno; 432 return request.count; 433} 434 435int drmMarkBufs(int fd, double low, double high) 436{ 437 drm_buf_info_t info; 438 int i; 439 440 info.count = 0; 441 info.list = NULL; 442 443 if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) return -EINVAL; 444 445 if (!info.count) return -EINVAL; 446 447 if (!(info.list = drmMalloc(info.count * sizeof(*info.list)))) 448 return -ENOMEM; 449 450 if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) { 451 int retval = -errno; 452 drmFree(info.list); 453 return retval; 454 } 455 456 for (i = 0; i < info.count; i++) { 457 info.list[i].low_mark = low * info.list[i].count; 458 info.list[i].high_mark = high * info.list[i].count; 459 if (ioctl(fd, DRM_IOCTL_MARK_BUFS, &info.list[i])) { 460 int retval = -errno; 461 drmFree(info.list); 462 return retval; 463 } 464 } 465 drmFree(info.list); 466 467 return 0; 468} 469 470int drmFreeBufs(int fd, int count, int *list) 471{ 472 drm_buf_free_t request; 473 474 request.count = count; 475 request.list = list; 476 if (ioctl(fd, DRM_IOCTL_FREE_BUFS, &request)) return -errno; 477 return 0; 478} 479 480int drmClose(int fd) 481{ 482 unsigned long key = drmGetKeyFromFd(fd); 483 drmHashEntry *entry = drmGetEntry(fd); 484 485 drmHashDestroy(entry->tagTable); 486 entry->fd = 0; 487 entry->f = NULL; 488 entry->tagTable = NULL; 489 490 drmHashDelete(drmHashTable, key); 491 drmFree(entry); 492 493 return close(fd); 494} 495 496int drmMap(int fd, 497 drmHandle handle, 498 drmSize size, 499 drmAddressPtr address) 500{ 501 if (fd < 0) return -EINVAL; 502 *address = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, handle); 503 if (*address == MAP_FAILED) return -errno; 504 return 0; 505} 506 507int drmUnmap(drmAddress address, drmSize size) 508{ 509 return munmap(address, size); 510} 511 512drmBufInfoPtr drmGetBufInfo(int fd) 513{ 514 drm_buf_info_t info; 515 drmBufInfoPtr retval; 516 int i; 517 518 info.count = 0; 519 info.list = NULL; 520 521 if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) return NULL; 522 523 if (info.count) { 524 if (!(info.list = drmMalloc(info.count * sizeof(*info.list)))) 525 return NULL; 526 527 if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) { 528 drmFree(info.list); 529 return NULL; 530 } 531 /* Now, copy it all back into the 532 client-visible data structure... */ 533 retval = drmMalloc(sizeof(*retval)); 534 retval->count = info.count; 535 retval->list = drmMalloc(info.count * sizeof(*retval->list)); 536 for (i = 0; i < info.count; i++) { 537 retval->list[i].count = info.list[i].count; 538 retval->list[i].size = info.list[i].size; 539 retval->list[i].low_mark = info.list[i].low_mark; 540 retval->list[i].high_mark = info.list[i].high_mark; 541 } 542 drmFree(info.list); 543 return retval; 544 } 545 return NULL; 546} 547 548drmBufMapPtr drmMapBufs(int fd) 549{ 550 drm_buf_map_t bufs; 551 drmBufMapPtr retval; 552 int i; 553 554 bufs.count = 0; 555 bufs.list = NULL; 556 if (ioctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) return NULL; 557 558 if (bufs.count) { 559 if (!(bufs.list = drmMalloc(bufs.count * sizeof(*bufs.list)))) 560 return NULL; 561 562 if (ioctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) { 563 drmFree(bufs.list); 564 return NULL; 565 } 566 /* Now, copy it all back into the 567 client-visible data structure... */ 568 retval = drmMalloc(sizeof(*retval)); 569 retval->count = bufs.count; 570 retval->list = drmMalloc(bufs.count * sizeof(*retval->list)); 571 for (i = 0; i < bufs.count; i++) { 572 retval->list[i].idx = bufs.list[i].idx; 573 retval->list[i].total = bufs.list[i].total; 574 retval->list[i].used = 0; 575 retval->list[i].address = bufs.list[i].address; 576 } 577 return retval; 578 } 579 return NULL; 580} 581 582int drmUnmapBufs(drmBufMapPtr bufs) 583{ 584 int i; 585 586 for (i = 0; i < bufs->count; i++) { 587 munmap(bufs->list[i].address, bufs->list[i].total); 588 } 589 return 0; 590} 591 592int drmDMA(int fd, drmDMAReqPtr request) 593{ 594 drm_dma_t dma; 595 596 /* Copy to hidden structure */ 597 dma.context = request->context; 598 dma.send_count = request->send_count; 599 dma.send_indices = request->send_list; 600 dma.send_sizes = request->send_sizes; 601 dma.flags = request->flags; 602 dma.request_count = request->request_count; 603 dma.request_size = request->request_size; 604 dma.request_indices = request->request_list; 605 dma.request_sizes = request->request_sizes; 606 if (ioctl(fd, DRM_IOCTL_DMA, &dma)) return -errno; 607 request->granted_count = dma.granted_count; 608 609 return 0; 610} 611 612int drmGetLock(int fd, drmContext context, drmLockFlags flags) 613{ 614 drm_lock_t lock; 615 616 lock.context = context; 617 lock.flags = 0; 618 if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY; 619 if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT; 620 if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH; 621 if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL; 622 if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES; 623 if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES; 624 625 while (ioctl(fd, DRM_IOCTL_LOCK, &lock)) 626 ; 627 return 0; 628} 629 630int drmUnlock(int fd, drmContext context) 631{ 632 drm_lock_t lock; 633 634 lock.context = context; 635 lock.flags = 0; 636 return ioctl(fd, DRM_IOCTL_UNLOCK, &lock); 637} 638 639drmContextPtr drmGetReservedContextList(int fd, int *count) 640{ 641 drm_ctx_res_t res; 642 drm_ctx_t *list; 643 drmContextPtr retval; 644 int i; 645 646 res.count = 0; 647 res.contexts = NULL; 648 if (ioctl(fd, DRM_IOCTL_RES_CTX, &res)) return NULL; 649 650 if (!res.count) return NULL; 651 652 if (!(list = drmMalloc(res.count * sizeof(*list)))) return NULL; 653 if (!(retval = drmMalloc(res.count * sizeof(*retval)))) { 654 drmFree(list); 655 return NULL; 656 } 657 658 res.contexts = list; 659 if (ioctl(fd, DRM_IOCTL_RES_CTX, &res)) return NULL; 660 661 for (i = 0; i < res.count; i++) retval[i] = list[i].handle; 662 drmFree(list); 663 664 *count = res.count; 665 return retval; 666} 667 668void drmFreeReservedContextList(drmContextPtr pt) 669{ 670 drmFree(pt); 671} 672 673int drmCreateContext(int fd, drmContextPtr handle) 674{ 675 drm_ctx_t ctx; 676 677 ctx.flags = 0; /* Modified with functions below */ 678 if (ioctl(fd, DRM_IOCTL_ADD_CTX, &ctx)) return -errno; 679 *handle = ctx.handle; 680 return 0; 681} 682 683int drmSwitchToContext(int fd, drmContext context) 684{ 685 drm_ctx_t ctx; 686 687 ctx.handle = context; 688 if (ioctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx)) return -errno; 689 return 0; 690} 691 692int drmSetContextFlags(int fd, drmContext context, drmContextFlags flags) 693{ 694 drm_ctx_t ctx; 695 696 /* Context preserving means that no context 697 switched are done between DMA buffers 698 from one context and the next. This is 699 suitable for use in the X server (which 700 promises to maintain hardware context, 701 or in the client-side library when 702 buffers are swapped on behalf of two 703 threads. */ 704 ctx.handle = context; 705 ctx.flags = 0; 706 if (flags & DRM_CONTEXT_PRESERVED) ctx.flags |= _DRM_CONTEXT_PRESERVED; 707 if (flags & DRM_CONTEXT_2DONLY) ctx.flags |= _DRM_CONTEXT_2DONLY; 708 if (ioctl(fd, DRM_IOCTL_MOD_CTX, &ctx)) return -errno; 709 return 0; 710} 711 712int drmGetContextFlags(int fd, drmContext context, drmContextFlagsPtr flags) 713{ 714 drm_ctx_t ctx; 715 716 ctx.handle = context; 717 if (ioctl(fd, DRM_IOCTL_GET_CTX, &ctx)) return -errno; 718 *flags = 0; 719 if (ctx.flags & _DRM_CONTEXT_PRESERVED) *flags |= DRM_CONTEXT_PRESERVED; 720 if (ctx.flags & _DRM_CONTEXT_2DONLY) *flags |= DRM_CONTEXT_2DONLY; 721 return 0; 722} 723 724int drmDestroyContext(int fd, drmContext handle) 725{ 726 drm_ctx_t ctx; 727 ctx.handle = handle; 728 if (ioctl(fd, DRM_IOCTL_RM_CTX, &ctx)) return -errno; 729 return 0; 730} 731 732int drmCreateDrawable(int fd, drmDrawablePtr handle) 733{ 734 drm_draw_t draw; 735 if (ioctl(fd, DRM_IOCTL_ADD_DRAW, &draw)) return -errno; 736 *handle = draw.handle; 737 return 0; 738} 739 740int drmDestroyDrawable(int fd, drmDrawable handle) 741{ 742 drm_draw_t draw; 743 draw.handle = handle; 744 if (ioctl(fd, DRM_IOCTL_RM_DRAW, &draw)) return -errno; 745 return 0; 746} 747 748int drmError(int err, const char *label) 749{ 750 switch (err) { 751 case DRM_ERR_NO_DEVICE: fprintf(stderr, "%s: no device\n", label); break; 752 case DRM_ERR_NO_ACCESS: fprintf(stderr, "%s: no access\n", label); break; 753 case DRM_ERR_NOT_ROOT: fprintf(stderr, "%s: not root\n", label); break; 754 case DRM_ERR_INVALID: fprintf(stderr, "%s: invalid args\n", label);break; 755 default: 756 if (err < 0) err = -err; 757 fprintf( stderr, "%s: error %d (%s)\n", label, err, strerror(err) ); 758 break; 759 } 760 761 return 1; 762} 763 764int drmCtlInstHandler(int fd, int irq) 765{ 766 drm_control_t ctl; 767 768 ctl.func = DRM_INST_HANDLER; 769 ctl.irq = irq; 770 if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl)) return -errno; 771 return 0; 772} 773 774int drmCtlUninstHandler(int fd) 775{ 776 drm_control_t ctl; 777 778 ctl.func = DRM_UNINST_HANDLER; 779 ctl.irq = 0; 780 if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl)) return -errno; 781 return 0; 782} 783 784int drmFinish(int fd, int context, drmLockFlags flags) 785{ 786 drm_lock_t lock; 787 788 lock.context = context; 789 lock.flags = 0; 790 if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY; 791 if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT; 792 if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH; 793 if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL; 794 if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES; 795 if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES; 796 if (ioctl(fd, DRM_IOCTL_FINISH, &lock)) return -errno; 797 return 0; 798} 799 800int drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum) 801{ 802 drm_irq_busid_t p; 803 804 p.busnum = busnum; 805 p.devnum = devnum; 806 p.funcnum = funcnum; 807 if (ioctl(fd, DRM_IOCTL_IRQ_BUSID, &p)) return -errno; 808 return p.irq; 809} 810 811int drmAddContextTag(int fd, drmContext context, void *tag) 812{ 813 drmHashEntry *entry = drmGetEntry(fd); 814 815 if (drmHashInsert(entry->tagTable, context, tag)) { 816 drmHashDelete(entry->tagTable, context); 817 drmHashInsert(entry->tagTable, context, tag); 818 } 819 return 0; 820} 821 822int drmDelContextTag(int fd, drmContext context) 823{ 824 drmHashEntry *entry = drmGetEntry(fd); 825 826 return drmHashDelete(entry->tagTable, context); 827} 828 829void *drmGetContextTag(int fd, drmContext context) 830{ 831 drmHashEntry *entry = drmGetEntry(fd); 832 void *value; 833 834 if (drmHashLookup(entry->tagTable, context, &value)) return NULL; 835 836 return value; 837} 838 839#if defined(XFree86Server) || defined(DRM_USE_MALLOC) 840static void drmSIGIOHandler(int interrupt, void *closure) 841{ 842 unsigned long key; 843 void *value; 844 ssize_t count; 845 drm_ctx_t ctx; 846 typedef void (*_drmCallback)(int, void *, void *); 847 char buf[256]; 848 drmContext old; 849 drmContext new; 850 void *oldctx; 851 void *newctx; 852 char *pt; 853 drmHashEntry *entry; 854 855 if (!drmHashTable) return; 856 if (drmHashFirst(drmHashTable, &key, &value)) { 857 entry = value; 858 do { 859#if 0 860 fprintf(stderr, "Trying %d\n", entry->fd); 861#endif 862 if ((count = read(entry->fd, buf, sizeof(buf)))) { 863 buf[count] = '\0'; 864#if 0 865 fprintf(stderr, "Got %s\n", buf); 866#endif 867 868 for (pt = buf; *pt != ' '; ++pt); /* Find first space */ 869 ++pt; 870 old = strtol(pt, &pt, 0); 871 new = strtol(pt, NULL, 0); 872 oldctx = drmGetContextTag(entry->fd, old); 873 newctx = drmGetContextTag(entry->fd, new); 874#if 0 875 fprintf(stderr, "%d %d %p %p\n", old, new, oldctx, newctx); 876#endif 877 ((_drmCallback)entry->f)(entry->fd, oldctx, newctx); 878 ctx.handle = new; 879 ioctl(entry->fd, DRM_IOCTL_NEW_CTX, &ctx); 880 } 881 } while (drmHashNext(drmHashTable, &key, &value)); 882 } 883} 884 885int drmInstallSIGIOHandler(int fd, void (*f)(int, void *, void *)) 886{ 887 drmHashEntry *entry; 888 889 entry = drmGetEntry(fd); 890 entry->f = f; 891 892 return xf86InstallSIGIOHandler(fd, drmSIGIOHandler, 0); 893} 894 895int drmRemoveSIGIOHandler(int fd) 896{ 897 drmHashEntry *entry = drmGetEntry(fd); 898 899 entry->f = NULL; 900 901 return xf86RemoveSIGIOHandler(fd); 902} 903#endif 904