1/* mach64_state.c -- State support for mach64 (Rage Pro) driver -*- linux-c -*- 2 * Created: Sun Dec 03 19:20:26 2000 by gareth@valinux.com 3 */ 4/*- 5 * Copyright 2000 Gareth Hughes 6 * Copyright 2002-2003 Leif Delgass 7 * All Rights Reserved. 8 * --- 13 unchanged lines hidden (view full) --- 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 * THE COPYRIGHT OWNER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 24 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 * Authors: 28 * Gareth Hughes <gareth@valinux.com> 29 * Leif Delgass <ldelgass@retinalburn.net> |
30 * Jos�� Fonseca <j_r_fonseca@yahoo.co.uk> |
31 */ 32 33#include <sys/cdefs.h> |
34__FBSDID("$FreeBSD: head/sys/dev/drm/mach64_state.c 182080 2008-08-23 20:59:12Z rnoland $"); |
35 36#include "dev/drm/drmP.h" 37#include "dev/drm/drm.h" 38#include "dev/drm/mach64_drm.h" 39#include "dev/drm/mach64_drv.h" 40 41/* Interface history: 42 * 43 * 1.0 - Initial mach64 DRM 44 * 45 */ |
46struct drm_ioctl_desc mach64_ioctls[] = { 47 DRM_IOCTL_DEF(DRM_MACH64_INIT, mach64_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 48 DRM_IOCTL_DEF(DRM_MACH64_CLEAR, mach64_dma_clear, DRM_AUTH), 49 DRM_IOCTL_DEF(DRM_MACH64_SWAP, mach64_dma_swap, DRM_AUTH), 50 DRM_IOCTL_DEF(DRM_MACH64_IDLE, mach64_dma_idle, DRM_AUTH), 51 DRM_IOCTL_DEF(DRM_MACH64_RESET, mach64_engine_reset, DRM_AUTH), 52 DRM_IOCTL_DEF(DRM_MACH64_VERTEX, mach64_dma_vertex, DRM_AUTH), 53 DRM_IOCTL_DEF(DRM_MACH64_BLIT, mach64_dma_blit, DRM_AUTH), 54 DRM_IOCTL_DEF(DRM_MACH64_FLUSH, mach64_dma_flush, DRM_AUTH), 55 DRM_IOCTL_DEF(DRM_MACH64_GETPARAM, mach64_get_param, DRM_AUTH), |
56}; 57 58int mach64_max_ioctl = DRM_ARRAY_SIZE(mach64_ioctls); 59 60/* ================================================================ 61 * DMA hardware state programming functions 62 */ 63 --- 19 unchanged lines hidden (view full) --- 83} 84 85/* Mach64 doesn't have hardware cliprects, just one hardware scissor, 86 * so the GL scissor is intersected with each cliprect here 87 */ 88/* This function returns 0 on success, 1 for no intersection, and 89 * negative for an error 90 */ |
91static int mach64_emit_cliprect(struct drm_file *file_priv, 92 drm_mach64_private_t * dev_priv, 93 struct drm_clip_rect * box) |
94{ 95 u32 sc_left_right, sc_top_bottom; |
96 struct drm_clip_rect scissor; |
97 drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 98 drm_mach64_context_regs_t *regs = &sarea_priv->context_state; 99 DMALOCALS; 100 |
101 DRM_DEBUG("box=%p\n", box); |
102 103 /* Get GL scissor */ 104 /* FIXME: store scissor in SAREA as a cliprect instead of in 105 * hardware format, or do intersection client-side 106 */ 107 scissor.x1 = regs->sc_left_right & 0xffff; 108 scissor.x2 = (regs->sc_left_right & 0xffff0000) >> 16; 109 scissor.y1 = regs->sc_top_bottom & 0xffff; --- 9 unchanged lines hidden (view full) --- 119 if (box->y2 < scissor.y2) 120 scissor.y2 = box->y2; 121 /* positive return means skip */ 122 if (scissor.x1 >= scissor.x2) 123 return 1; 124 if (scissor.y1 >= scissor.y2) 125 return 1; 126 |
127 DMAGETPTR(file_priv, dev_priv, 2); /* returns on failure to get buffer */ |
128 129 sc_left_right = ((scissor.x1 << 0) | (scissor.x2 << 16)); 130 sc_top_bottom = ((scissor.y1 << 0) | (scissor.y2 << 16)); 131 132 DMAOUTREG(MACH64_SC_LEFT_RIGHT, sc_left_right); 133 DMAOUTREG(MACH64_SC_TOP_BOTTOM, sc_top_bottom); 134 135 DMAADVANCE(dev_priv, 1); 136 137 return 0; 138} 139 |
140static __inline__ int mach64_emit_state(struct drm_file *file_priv, |
141 drm_mach64_private_t * dev_priv) 142{ 143 drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 144 drm_mach64_context_regs_t *regs = &sarea_priv->context_state; 145 unsigned int dirty = sarea_priv->dirty; 146 u32 offset = ((regs->tex_size_pitch & 0xf0) >> 2); 147 DMALOCALS; 148 149 if (MACH64_VERBOSE) { 150 mach64_print_dirty(__FUNCTION__, dirty); 151 } else { |
152 DRM_DEBUG("dirty=0x%08x\n", dirty); |
153 } 154 |
155 DMAGETPTR(file_priv, dev_priv, 17); /* returns on failure to get buffer */ |
156 157 if (dirty & MACH64_UPLOAD_MISC) { 158 DMAOUTREG(MACH64_DP_MIX, regs->dp_mix); 159 DMAOUTREG(MACH64_DP_SRC, regs->dp_src); 160 DMAOUTREG(MACH64_CLR_CMP_CNTL, regs->clr_cmp_cntl); 161 DMAOUTREG(MACH64_GUI_TRAJ_CNTL, regs->gui_traj_cntl); 162 sarea_priv->dirty &= ~MACH64_UPLOAD_MISC; 163 } --- 47 unchanged lines hidden (view full) --- 211 return 0; 212 213} 214 215/* ================================================================ 216 * DMA command dispatch functions 217 */ 218 |
219static int mach64_dma_dispatch_clear(struct drm_device * dev, 220 struct drm_file *file_priv, |
221 unsigned int flags, 222 int cx, int cy, int cw, int ch, 223 unsigned int clear_color, 224 unsigned int clear_depth) 225{ 226 drm_mach64_private_t *dev_priv = dev->dev_private; 227 drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 228 drm_mach64_context_regs_t *ctx = &sarea_priv->context_state; 229 int nbox = sarea_priv->nbox; |
230 struct drm_clip_rect *pbox = sarea_priv->boxes; |
231 u32 fb_bpp, depth_bpp; 232 int i; 233 DMALOCALS; 234 |
235 DRM_DEBUG("\n"); |
236 237 switch (dev_priv->fb_bpp) { 238 case 16: 239 fb_bpp = MACH64_DATATYPE_RGB565; 240 break; 241 case 32: 242 fb_bpp = MACH64_DATATYPE_ARGB8888; 243 break; 244 default: |
245 return -EINVAL; |
246 } 247 switch (dev_priv->depth_bpp) { 248 case 16: 249 depth_bpp = MACH64_DATATYPE_RGB565; 250 break; 251 case 24: 252 case 32: 253 depth_bpp = MACH64_DATATYPE_ARGB8888; 254 break; 255 default: |
256 return -EINVAL; |
257 } 258 259 if (!nbox) 260 return 0; 261 |
262 DMAGETPTR(file_priv, dev_priv, nbox * 31); /* returns on failure to get buffer */ |
263 264 for (i = 0; i < nbox; i++) { 265 int x = pbox[i].x1; 266 int y = pbox[i].y1; 267 int w = pbox[i].x2 - x; 268 int h = pbox[i].y2 - y; 269 270 DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n", --- 84 unchanged lines hidden (view full) --- 355 } 356 } 357 358 DMAADVANCE(dev_priv, 1); 359 360 return 0; 361} 362 |
363static int mach64_dma_dispatch_swap(struct drm_device * dev, 364 struct drm_file *file_priv) |
365{ 366 drm_mach64_private_t *dev_priv = dev->dev_private; 367 drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 368 int nbox = sarea_priv->nbox; |
369 struct drm_clip_rect *pbox = sarea_priv->boxes; |
370 u32 fb_bpp; 371 int i; 372 DMALOCALS; 373 |
374 DRM_DEBUG("\n"); |
375 376 switch (dev_priv->fb_bpp) { 377 case 16: 378 fb_bpp = MACH64_DATATYPE_RGB565; 379 break; 380 case 32: 381 default: 382 fb_bpp = MACH64_DATATYPE_ARGB8888; 383 break; 384 } 385 386 if (!nbox) 387 return 0; 388 |
389 DMAGETPTR(file_priv, dev_priv, 13 + nbox * 4); /* returns on failure to get buffer */ |
390 391 DMAOUTREG(MACH64_Z_CNTL, 0); 392 DMAOUTREG(MACH64_SCALE_3D_CNTL, 0); 393 394 DMAOUTREG(MACH64_SC_LEFT_RIGHT, 0 | (8191 << 16)); /* no scissor */ 395 DMAOUTREG(MACH64_SC_TOP_BOTTOM, 0 | (16383 << 16)); 396 397 DMAOUTREG(MACH64_CLR_CMP_CNTL, 0); --- 45 unchanged lines hidden (view full) --- 443 444static int mach64_do_get_frames_queued(drm_mach64_private_t * dev_priv) 445{ 446 drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; 447 drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 448 int i, start; 449 u32 head, tail, ofs; 450 |
451 DRM_DEBUG("\n"); |
452 453 if (sarea_priv->frames_queued == 0) 454 return 0; 455 456 tail = ring->tail; 457 mach64_ring_tick(dev_priv, ring); 458 head = ring->head; 459 --- 21 unchanged lines hidden (view full) --- 481 } 482 483 return sarea_priv->frames_queued; 484} 485 486/* Copy and verify a client submited buffer. 487 * FIXME: Make an assembly optimized version 488 */ |
489static __inline__ int copy_from_user_vertex(u32 *to, 490 const u32 __user *ufrom, 491 unsigned long bytes) |
492{ 493 unsigned long n = bytes; /* dwords remaining in buffer */ 494 u32 *from, *orig_from; 495 496 from = drm_alloc(bytes, DRM_MEM_DRIVER); 497 if (from == NULL) |
498 return -ENOMEM; |
499 500 if (DRM_COPY_FROM_USER(from, ufrom, bytes)) { 501 drm_free(from, bytes, DRM_MEM_DRIVER); |
502 return -EFAULT; |
503 } 504 orig_from = from; /* we'll be modifying the "from" ptr, so save it */ 505 506 n >>= 2; 507 508 while (n > 1) { 509 u32 data, reg, count; 510 --- 12 unchanged lines hidden (view full) --- 523 */ 524 if ((reg >= 0x0190 && reg < 0x01c1) || 525 (reg >= 0x01ca && reg <= 0x01cf)) { 526 *to++ = data; 527 memcpy(to, from, count << 2); 528 from += count; 529 to += count; 530 } else { |
531 DRM_ERROR("Got bad command: 0x%04x\n", reg); |
532 drm_free(orig_from, bytes, DRM_MEM_DRIVER); |
533 return -EACCES; |
534 } 535 } else { 536 DRM_ERROR |
537 ("Got bad command count(=%u) dwords remaining=%lu\n", 538 count, n); |
539 drm_free(orig_from, bytes, DRM_MEM_DRIVER); |
540 return -EINVAL; |
541 } 542 } 543 544 drm_free(orig_from, bytes, DRM_MEM_DRIVER); 545 if (n == 0) 546 return 0; 547 else { |
548 DRM_ERROR("Bad buf->used(=%lu)\n", bytes); 549 return -EINVAL; |
550 } 551} 552 |
553static int mach64_dma_dispatch_vertex(struct drm_device * dev, 554 struct drm_file *file_priv, 555 drm_mach64_vertex_t * vertex) |
556{ 557 drm_mach64_private_t *dev_priv = dev->dev_private; 558 drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; |
559 struct drm_buf *copy_buf; 560 void *buf = vertex->buf; 561 unsigned long used = vertex->used; 562 int ret = 0; 563 int i = 0; |
564 int done = 0; 565 int verify_ret = 0; 566 DMALOCALS; 567 |
568 DRM_DEBUG("buf=%p used=%lu nbox=%d\n", 569 buf, used, sarea_priv->nbox); |
570 |
571 if (!used) 572 goto _vertex_done; |
573 |
574 copy_buf = mach64_freelist_get(dev_priv); 575 if (copy_buf == NULL) { 576 DRM_ERROR("couldn't get buffer\n"); 577 return -EAGAIN; 578 } |
579 |
580 /* Mach64's vertex data is actually register writes. To avoid security 581 * compromises these register writes have to be verified and copied from 582 * user space into a private DMA buffer. 583 */ 584 verify_ret = copy_from_user_vertex(GETBUFPTR(copy_buf), buf, used); |
585 |
586 if (verify_ret != 0) { 587 mach64_freelist_put(dev_priv, copy_buf); 588 goto _vertex_done; 589 } |
590 |
591 copy_buf->used = used; |
592 |
593 DMASETPTR(copy_buf); |
594 |
595 if (sarea_priv->dirty & ~MACH64_UPLOAD_CLIPRECTS) { 596 ret = mach64_emit_state(file_priv, dev_priv); 597 if (ret < 0) 598 return ret; 599 } |
600 |
601 do { 602 /* Emit the next cliprect */ 603 if (i < sarea_priv->nbox) { 604 ret = mach64_emit_cliprect(file_priv, dev_priv, 605 &sarea_priv->boxes[i]); 606 if (ret < 0) { 607 /* failed to get buffer */ 608 return ret; 609 } else if (ret != 0) { 610 /* null intersection with scissor */ 611 continue; 612 } |
613 } |
614 if ((i >= sarea_priv->nbox - 1)) 615 done = 1; |
616 |
617 /* Add the buffer to the DMA queue */ 618 DMAADVANCE(dev_priv, done); 619 620 } while (++i < sarea_priv->nbox); 621 622 if (!done) { 623 if (copy_buf->pending) { |
624 DMADISCARDBUF(); |
625 } else { 626 /* This buffer wasn't used (no cliprects), so place it 627 * back on the free list |
628 */ |
629 mach64_freelist_put(dev_priv, copy_buf); |
630 } 631 } 632 |
633_vertex_done: |
634 sarea_priv->dirty &= ~MACH64_UPLOAD_CLIPRECTS; 635 sarea_priv->nbox = 0; 636 637 return verify_ret; 638} 639 |
640static __inline__ int copy_from_user_blit(u32 *to, 641 const u32 __user *ufrom, 642 unsigned long bytes) 643{ 644 to = (u32 *)((char *)to + MACH64_HOSTDATA_BLIT_OFFSET); 645 646 if (DRM_COPY_FROM_USER(to, ufrom, bytes)) { 647 return -EFAULT; 648 } 649 650 return 0; 651} 652 653static int mach64_dma_dispatch_blit(struct drm_device * dev, 654 struct drm_file *file_priv, |
655 drm_mach64_blit_t * blit) 656{ 657 drm_mach64_private_t *dev_priv = dev->dev_private; |
658 int dword_shift, dwords; |
659 unsigned long used; 660 struct drm_buf *copy_buf; 661 int verify_ret = 0; |
662 DMALOCALS; 663 664 /* The compiler won't optimize away a division by a variable, 665 * even if the only legal values are powers of two. Thus, we'll 666 * use a shift instead. 667 */ 668 switch (blit->format) { 669 case MACH64_DATATYPE_ARGB8888: --- 7 unchanged lines hidden (view full) --- 677 dword_shift = 1; 678 break; 679 case MACH64_DATATYPE_CI8: 680 case MACH64_DATATYPE_RGB8: 681 dword_shift = 2; 682 break; 683 default: 684 DRM_ERROR("invalid blit format %d\n", blit->format); |
685 return -EINVAL; |
686 } 687 |
688 /* Set buf->used to the bytes of blit data based on the blit dimensions 689 * and verify the size. When the setup is emitted to the buffer with 690 * the DMA* macros below, buf->used is incremented to include the bytes 691 * used for setup as well as the blit data. 692 */ 693 dwords = (blit->width * blit->height) >> dword_shift; |
694 used = dwords << 2; 695 if (used <= 0 || 696 used > MACH64_BUFFER_SIZE - MACH64_HOSTDATA_BLIT_OFFSET) { 697 DRM_ERROR("Invalid blit size: %lu bytes\n", used); 698 return -EINVAL; |
699 } 700 |
701 copy_buf = mach64_freelist_get(dev_priv); 702 if (copy_buf == NULL) { 703 DRM_ERROR("couldn't get buffer\n"); 704 return -EAGAIN; 705 } 706 707 /* Copy the blit data from userspace. 708 * 709 * XXX: This is overkill. The most efficient solution would be having 710 * two sets of buffers (one set private for vertex data, the other set 711 * client-writable for blits). However that would bring more complexity 712 * and would break backward compatability. The solution currently 713 * implemented is keeping all buffers private, allowing to secure the 714 * driver, without increasing complexity at the expense of some speed 715 * transfering data. 716 */ 717 verify_ret = copy_from_user_blit(GETBUFPTR(copy_buf), blit->buf, used); 718 719 if (verify_ret != 0) { 720 mach64_freelist_put(dev_priv, copy_buf); 721 goto _blit_done; 722 } 723 724 copy_buf->used = used; 725 |
726 /* FIXME: Use a last buffer flag and reduce the state emitted for subsequent, 727 * continuation buffers? 728 */ 729 730 /* Blit via BM_HOSTDATA (gui-master) - like HOST_DATA[0-15], but doesn't require 731 * a register command every 16 dwords. State setup is added at the start of the 732 * buffer -- the client leaves space for this based on MACH64_HOSTDATA_BLIT_OFFSET 733 */ |
734 DMASETPTR(copy_buf); |
735 736 DMAOUTREG(MACH64_Z_CNTL, 0); 737 DMAOUTREG(MACH64_SCALE_3D_CNTL, 0); 738 739 DMAOUTREG(MACH64_SC_LEFT_RIGHT, 0 | (8191 << 16)); /* no scissor */ 740 DMAOUTREG(MACH64_SC_TOP_BOTTOM, 0 | (16383 << 16)); 741 742 DMAOUTREG(MACH64_CLR_CMP_CNTL, 0); /* disable */ --- 13 unchanged lines hidden (view full) --- 756 MACH64_BKGD_SRC_BKGD_CLR 757 | MACH64_FRGD_SRC_HOST | MACH64_MONO_SRC_ONE); 758 759 DMAOUTREG(MACH64_DST_OFF_PITCH, 760 (blit->pitch << 22) | (blit->offset >> 3)); 761 DMAOUTREG(MACH64_DST_X_Y, (blit->y << 16) | blit->x); 762 DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (blit->height << 16) | blit->width); 763 |
764 DRM_DEBUG("%lu bytes\n", used); |
765 766 /* Add the buffer to the queue */ 767 DMAADVANCEHOSTDATA(dev_priv); 768 |
769_blit_done: 770 return verify_ret; |
771} 772 773/* ================================================================ 774 * IOCTL functions 775 */ 776 |
777int mach64_dma_clear(struct drm_device *dev, void *data, 778 struct drm_file *file_priv) |
779{ |
780 drm_mach64_private_t *dev_priv = dev->dev_private; 781 drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; |
782 drm_mach64_clear_t *clear = data; |
783 int ret; 784 |
785 DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); |
786 |
787 LOCK_TEST_WITH_RETURN(dev, file_priv); |
788 |
789 if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS) 790 sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS; 791 |
792 ret = mach64_dma_dispatch_clear(dev, file_priv, clear->flags, 793 clear->x, clear->y, clear->w, clear->h, 794 clear->clear_color, 795 clear->clear_depth); |
796 797 /* Make sure we restore the 3D state next time. 798 */ 799 sarea_priv->dirty |= (MACH64_UPLOAD_CONTEXT | MACH64_UPLOAD_MISC); 800 return ret; 801} 802 |
803int mach64_dma_swap(struct drm_device *dev, void *data, 804 struct drm_file *file_priv) |
805{ |
806 drm_mach64_private_t *dev_priv = dev->dev_private; 807 drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; 808 int ret; 809 |
810 DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); |
811 |
812 LOCK_TEST_WITH_RETURN(dev, file_priv); |
813 814 if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS) 815 sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS; 816 |
817 ret = mach64_dma_dispatch_swap(dev, file_priv); |
818 819 /* Make sure we restore the 3D state next time. 820 */ 821 sarea_priv->dirty |= (MACH64_UPLOAD_CONTEXT | MACH64_UPLOAD_MISC); 822 return ret; 823} 824 |
825int mach64_dma_vertex(struct drm_device *dev, void *data, 826 struct drm_file *file_priv) |
827{ |
828 drm_mach64_private_t *dev_priv = dev->dev_private; 829 drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; |
830 drm_mach64_vertex_t *vertex = data; |
831 |
832 LOCK_TEST_WITH_RETURN(dev, file_priv); |
833 834 if (!dev_priv) { |
835 DRM_ERROR("called with no initialization\n"); 836 return -EINVAL; |
837 } 838 |
839 DRM_DEBUG("pid=%d buf=%p used=%lu discard=%d\n", 840 DRM_CURRENTPID, 841 vertex->buf, vertex->used, vertex->discard); |
842 |
843 if (vertex->prim < 0 || vertex->prim > MACH64_PRIM_POLYGON) { 844 DRM_ERROR("buffer prim %d\n", vertex->prim); 845 return -EINVAL; |
846 } 847 |
848 if (vertex->used > MACH64_BUFFER_SIZE || (vertex->used & 3) != 0) { |
849 DRM_ERROR("Invalid vertex buffer size: %lu bytes\n", |
850 vertex->used); 851 return -EINVAL; |
852 } 853 854 if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS) 855 sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS; 856 |
857 return mach64_dma_dispatch_vertex(dev, file_priv, vertex); |
858} 859 |
860int mach64_dma_blit(struct drm_device *dev, void *data, 861 struct drm_file *file_priv) |
862{ |
863 drm_mach64_private_t *dev_priv = dev->dev_private; 864 drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; |
865 drm_mach64_blit_t *blit = data; |
866 int ret; 867 |
868 LOCK_TEST_WITH_RETURN(dev, file_priv); |
869 |
870 ret = mach64_dma_dispatch_blit(dev, file_priv, blit); |
871 |
872 /* Make sure we restore the 3D state next time. 873 */ 874 sarea_priv->dirty |= (MACH64_UPLOAD_CONTEXT | 875 MACH64_UPLOAD_MISC | MACH64_UPLOAD_CLIPRECTS); 876 877 return ret; 878} 879 |
880int mach64_get_param(struct drm_device *dev, void *data, 881 struct drm_file *file_priv) |
882{ |
883 drm_mach64_private_t *dev_priv = dev->dev_private; |
884 drm_mach64_getparam_t *param = data; |
885 int value; 886 |
887 DRM_DEBUG("\n"); |
888 889 if (!dev_priv) { |
890 DRM_ERROR("called with no initialization\n"); 891 return -EINVAL; |
892 } 893 |
894 switch (param->param) { |
895 case MACH64_PARAM_FRAMES_QUEUED: 896 /* Needs lock since it calls mach64_ring_tick() */ |
897 LOCK_TEST_WITH_RETURN(dev, file_priv); |
898 value = mach64_do_get_frames_queued(dev_priv); 899 break; 900 case MACH64_PARAM_IRQ_NR: 901 value = dev->irq; 902 break; 903 default: |
904 return -EINVAL; |
905 } 906 |
907 if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) { |
908 DRM_ERROR("copy_to_user\n"); |
909 return -EFAULT; |
910 } 911 912 return 0; 913} |