i830_dma.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:36k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* i830_dma.c -- DMA support for the I830 -*- linux-c -*-
  2.  * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
  3.  *
  4.  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  5.  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  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.  * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
  28.  *     Jeff Hartmann <jhartmann@valinux.com>
  29.  *      Keith Whitwell <keithw@valinux.com>
  30.  *      Abraham vd Merwe <abraham@2d3d.co.za>
  31.  *
  32.  */
  33. #include "i830.h"
  34. #include "drmP.h"
  35. #include "i830_drv.h"
  36. #include <linux/interrupt.h> /* For task queue support */
  37. #include <linux/delay.h>
  38. /* in case we don't have a 2.3.99-pre6 kernel or later: */
  39. #ifndef VM_DONTCOPY
  40. #define VM_DONTCOPY 0
  41. #endif
  42. #define I830_BUF_FREE 2
  43. #define I830_BUF_CLIENT 1
  44. #define I830_BUF_HARDWARE       0
  45. #define I830_BUF_UNMAPPED 0
  46. #define I830_BUF_MAPPED   1
  47. #define RING_LOCALS unsigned int outring, ringmask; volatile char *virt;
  48. #define DO_IDLE_WORKAROUND()
  49. do {
  50.    int _head;
  51.    int _tail;
  52.    do { 
  53.       _head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
  54.       _tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
  55.       udelay(1);
  56.    } while(_head != _tail);
  57. } while(0)
  58. #define I830_SYNC_WORKAROUND 0
  59. #define BEGIN_LP_RING(n) do {
  60. if (I830_VERBOSE)
  61. DRM_DEBUG("BEGIN_LP_RING(%d) in %sn",
  62.   n, __FUNCTION__);
  63. if (I830_SYNC_WORKAROUND)
  64. DO_IDLE_WORKAROUND();
  65. if (dev_priv->ring.space < n*4) 
  66. i830_wait_ring(dev, n*4);
  67. dev_priv->ring.space -= n*4;
  68. outring = dev_priv->ring.tail;
  69. ringmask = dev_priv->ring.tail_mask;
  70. virt = dev_priv->ring.virtual_start;
  71. } while (0)
  72. #define ADVANCE_LP_RING() do {
  73. if (I830_VERBOSE) DRM_DEBUG("ADVANCE_LP_RINGn");
  74. dev_priv->ring.tail = outring;
  75. I830_WRITE(LP_RING + RING_TAIL, outring);
  76. } while(0)
  77. #define OUT_RING(n) do {
  78. if (I830_VERBOSE) DRM_DEBUG("   OUT_RING %xn", (int)(n));
  79. *(volatile unsigned int *)(virt + outring) = n;
  80. outring += 4;
  81. outring &= ringmask;
  82. } while (0);
  83. static inline void i830_print_status_page(drm_device_t *dev)
  84. {
  85.     drm_device_dma_t *dma = dev->dma;
  86.        drm_i830_private_t *dev_priv = dev->dev_private;
  87. u8 *temp = dev_priv->hw_status_page;
  88.     int i;
  89.     DRM_DEBUG(  "hw_status: Interrupt Status : %xn", temp[0]);
  90.     DRM_DEBUG(  "hw_status: LpRing Head ptr : %xn", temp[1]);
  91.     DRM_DEBUG(  "hw_status: IRing Head ptr : %xn", temp[2]);
  92.        DRM_DEBUG(  "hw_status: Reserved : %xn", temp[3]);
  93.     DRM_DEBUG(  "hw_status: Driver Counter : %dn", temp[5]);
  94.     for(i = 9; i < dma->buf_count + 9; i++) {
  95.     DRM_DEBUG( "buffer status idx : %d used: %dn", i - 9, temp[i]);
  96. }
  97. }
  98. static drm_buf_t *i830_freelist_get(drm_device_t *dev)
  99. {
  100.     drm_device_dma_t *dma = dev->dma;
  101. int  i;
  102.     int   used;
  103.    
  104. /* Linear search might not be the best solution */
  105.     for (i = 0; i < dma->buf_count; i++) {
  106.     drm_buf_t *buf = dma->buflist[ i ];
  107.     drm_i830_buf_priv_t *buf_priv = buf->dev_private;
  108. /* In use is already a pointer */
  109.     used = cmpxchg(buf_priv->in_use, I830_BUF_FREE, 
  110.        I830_BUF_CLIENT);
  111.     if(used == I830_BUF_FREE) {
  112. return buf;
  113. }
  114. }
  115.     return NULL;
  116. }
  117. /* This should only be called if the buffer is not sent to the hardware
  118.  * yet, the hardware updates in use for us once its on the ring buffer.
  119.  */
  120. static int i830_freelist_put(drm_device_t *dev, drm_buf_t *buf)
  121. {
  122.     drm_i830_buf_priv_t *buf_priv = buf->dev_private;
  123.     int used;
  124.    
  125.     /* In use is already a pointer */
  126.     used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, I830_BUF_FREE);
  127.     if(used != I830_BUF_CLIENT) {
  128.     DRM_ERROR("Freeing buffer thats not in use : %dn", buf->idx);
  129.     return -EINVAL;
  130. }
  131.    
  132.     return 0;
  133. }
  134. static struct file_operations i830_buffer_fops = {
  135. open:  DRM(open),
  136. flush:  DRM(flush),
  137. release: DRM(release),
  138. ioctl:  DRM(ioctl),
  139. mmap:  i830_mmap_buffers,
  140. read:  DRM(read),
  141. fasync:  DRM(fasync),
  142.        poll:  DRM(poll),
  143. };
  144. int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
  145. {
  146. drm_file_t     *priv   = filp->private_data;
  147. drm_device_t     *dev;
  148. drm_i830_private_t  *dev_priv;
  149. drm_buf_t           *buf;
  150. drm_i830_buf_priv_t *buf_priv;
  151. lock_kernel();
  152. dev  = priv->dev;
  153. dev_priv = dev->dev_private;
  154. buf      = dev_priv->mmap_buffer;
  155. buf_priv = buf->dev_private;
  156.    
  157. vma->vm_flags |= (VM_IO | VM_DONTCOPY);
  158. vma->vm_file = filp;
  159.    
  160.     buf_priv->currently_mapped = I830_BUF_MAPPED;
  161. unlock_kernel();
  162. if (remap_page_range(vma->vm_start,
  163.      VM_OFFSET(vma),
  164.      vma->vm_end - vma->vm_start,
  165.      vma->vm_page_prot)) return -EAGAIN;
  166. return 0;
  167. }
  168. static int i830_map_buffer(drm_buf_t *buf, struct file *filp)
  169. {
  170. drm_file_t   *priv   = filp->private_data;
  171. drm_device_t   *dev   = priv->dev;
  172. drm_i830_buf_priv_t *buf_priv = buf->dev_private;
  173.        drm_i830_private_t *dev_priv = dev->dev_private;
  174.     struct file_operations *old_fops;
  175. int retcode = 0;
  176. if(buf_priv->currently_mapped == I830_BUF_MAPPED) return -EINVAL;
  177. if(VM_DONTCOPY != 0) {
  178. down_write( &current->mm->mmap_sem );
  179. old_fops = filp->f_op;
  180. filp->f_op = &i830_buffer_fops;
  181. dev_priv->mmap_buffer = buf;
  182. buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, 
  183.     PROT_READ|PROT_WRITE,
  184.     MAP_SHARED, 
  185.     buf->bus_address);
  186. dev_priv->mmap_buffer = NULL;
  187.     filp->f_op = old_fops;
  188. if ((unsigned long)buf_priv->virtual > -1024UL) {
  189. /* Real error */
  190. DRM_DEBUG("mmap errorn");
  191. retcode = (signed int)buf_priv->virtual;
  192. buf_priv->virtual = 0;
  193. }
  194. up_write( &current->mm->mmap_sem );
  195. } else {
  196. buf_priv->virtual = buf_priv->kernel_virtual;
  197.     buf_priv->currently_mapped = I830_BUF_MAPPED;
  198. }
  199. return retcode;
  200. }
  201. static int i830_unmap_buffer(drm_buf_t *buf)
  202. {
  203. drm_i830_buf_priv_t *buf_priv = buf->dev_private;
  204. int retcode = 0;
  205. if(VM_DONTCOPY != 0) {
  206. if(buf_priv->currently_mapped != I830_BUF_MAPPED) 
  207. return -EINVAL;
  208. down_write( &current->mm->mmap_sem );
  209.          retcode = do_munmap(current->mm, 
  210.     (unsigned long)buf_priv->virtual, 
  211.     (size_t) buf->total);
  212.     up_write( &current->mm->mmap_sem );
  213. }
  214.     buf_priv->currently_mapped = I830_BUF_UNMAPPED;
  215.     buf_priv->virtual = 0;
  216. return retcode;
  217. }
  218. static int i830_dma_get_buffer(drm_device_t *dev, drm_i830_dma_t *d, 
  219.        struct file *filp)
  220. {
  221. drm_file_t   *priv   = filp->private_data;
  222. drm_buf_t   *buf;
  223. drm_i830_buf_priv_t *buf_priv;
  224. int retcode = 0;
  225. buf = i830_freelist_get(dev);
  226. if (!buf) {
  227. retcode = -ENOMEM;
  228.     DRM_DEBUG("retcode=%dn", retcode);
  229. return retcode;
  230. }
  231.    
  232. retcode = i830_map_buffer(buf, filp);
  233. if(retcode) {
  234. i830_freelist_put(dev, buf);
  235.     DRM_DEBUG("mapbuf failed, retcode %dn", retcode);
  236. return retcode;
  237. }
  238. buf->pid     = priv->pid;
  239. buf_priv = buf->dev_private;
  240. d->granted = 1;
  241.     d->request_idx = buf->idx;
  242.     d->request_size = buf->total;
  243.     d->virtual = buf_priv->virtual;
  244. return retcode;
  245. }
  246. static int i830_dma_cleanup(drm_device_t *dev)
  247. {
  248. drm_device_dma_t *dma = dev->dma;
  249. if(dev->dev_private) {
  250. int i;
  251.     drm_i830_private_t *dev_priv = 
  252.       (drm_i830_private_t *) dev->dev_private;
  253.    
  254.     if(dev_priv->ring.virtual_start) {
  255.     DRM(ioremapfree)((void *) dev_priv->ring.virtual_start,
  256.  dev_priv->ring.Size);
  257. }
  258.     if(dev_priv->hw_status_page != NULL) {
  259.     pci_free_consistent(dev->pdev, PAGE_SIZE, 
  260.         dev_priv->hw_status_page, dev_priv->dma_status_page);
  261.     /* Need to rewrite hardware status page */
  262.     I830_WRITE(0x02080, 0x1ffff000);
  263. }
  264.     DRM(free)(dev->dev_private, sizeof(drm_i830_private_t), 
  265.  DRM_MEM_DRIVER);
  266.     dev->dev_private = NULL;
  267. for (i = 0; i < dma->buf_count; i++) {
  268. drm_buf_t *buf = dma->buflist[ i ];
  269. drm_i830_buf_priv_t *buf_priv = buf->dev_private;
  270. DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total);
  271. }
  272. }
  273.     return 0;
  274. }
  275. static int i830_wait_ring(drm_device_t *dev, int n)
  276. {
  277.     drm_i830_private_t *dev_priv = dev->dev_private;
  278.     drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
  279.     int iters = 0;
  280.     unsigned long end;
  281. unsigned int last_head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
  282. end = jiffies + (HZ*3);
  283.     while (ring->space < n) {
  284.     ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
  285.     ring->space = ring->head - (ring->tail+8);
  286. if (ring->space < 0) ring->space += ring->Size;
  287.    
  288. if (ring->head != last_head) {
  289. end = jiffies + (HZ*3);
  290. last_head = ring->head;
  291. }
  292.   
  293.     iters++;
  294. if(time_before(end,jiffies)) {
  295.     DRM_ERROR("space: %d wanted %dn", ring->space, n);
  296.     DRM_ERROR("lockupn");
  297.     goto out_wait_ring;
  298. }
  299.     udelay(1);
  300. }
  301. out_wait_ring:   
  302.     return iters;
  303. }
  304. static void i830_kernel_lost_context(drm_device_t *dev)
  305. {
  306.        drm_i830_private_t *dev_priv = dev->dev_private;
  307.     drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
  308.       
  309.     ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
  310.       ring->tail = I830_READ(LP_RING + RING_TAIL);
  311.       ring->space = ring->head - (ring->tail+8);
  312.       if (ring->space < 0) ring->space += ring->Size;
  313. }
  314. static int i830_freelist_init(drm_device_t *dev, drm_i830_private_t *dev_priv)
  315. {
  316.        drm_device_dma_t *dma = dev->dma;
  317.     int my_idx = 36;
  318.     u32 *hw_status = (u32 *)(dev_priv->hw_status_page + my_idx);
  319.     int i;
  320.     if(dma->buf_count > 1019) {
  321.     /* Not enough space in the status page for the freelist */
  322.     return -EINVAL;
  323. }
  324.     for (i = 0; i < dma->buf_count; i++) {
  325.     drm_buf_t *buf = dma->buflist[ i ];
  326.     drm_i830_buf_priv_t *buf_priv = buf->dev_private;
  327.     buf_priv->in_use = hw_status++;
  328.     buf_priv->my_use_idx = my_idx;
  329.     my_idx += 4;
  330.     *buf_priv->in_use = I830_BUF_FREE;
  331. buf_priv->kernel_virtual = DRM(ioremap)(buf->bus_address, 
  332. buf->total);
  333. }
  334. return 0;
  335. }
  336. static int i830_dma_initialize(drm_device_t *dev, 
  337.        drm_i830_private_t *dev_priv,
  338.        drm_i830_init_t *init)
  339. {
  340. struct list_head *list;
  341.     memset(dev_priv, 0, sizeof(drm_i830_private_t));
  342. list_for_each(list, &dev->maplist->head) {
  343. drm_map_list_t *r_list = (drm_map_list_t *)list;
  344. if( r_list->map &&
  345.     r_list->map->type == _DRM_SHM &&
  346.     r_list->map->flags & _DRM_CONTAINS_LOCK ) {
  347. dev_priv->sarea_map = r_list->map;
  348.   break;
  349.   }
  350.   }
  351. if(!dev_priv->sarea_map) {
  352. dev->dev_private = (void *)dev_priv;
  353. i830_dma_cleanup(dev);
  354. DRM_ERROR("can not find sarea!n");
  355. return -EINVAL;
  356. }
  357. DRM_FIND_MAP( dev_priv->mmio_map, init->mmio_offset );
  358. if(!dev_priv->mmio_map) {
  359. dev->dev_private = (void *)dev_priv;
  360. i830_dma_cleanup(dev);
  361. DRM_ERROR("can not find mmio map!n");
  362. return -EINVAL;
  363. }
  364. DRM_FIND_MAP( dev_priv->buffer_map, init->buffers_offset );
  365. if(!dev_priv->buffer_map) {
  366. dev->dev_private = (void *)dev_priv;
  367. i830_dma_cleanup(dev);
  368. DRM_ERROR("can not find dma buffer map!n");
  369. return -EINVAL;
  370. }
  371. dev_priv->sarea_priv = (drm_i830_sarea_t *)
  372. ((u8 *)dev_priv->sarea_map->handle +
  373.  init->sarea_priv_offset);
  374.     atomic_set(&dev_priv->flush_done, 0);
  375. init_waitqueue_head(&dev_priv->flush_queue);
  376.     dev_priv->ring.Start = init->ring_start;
  377.     dev_priv->ring.End = init->ring_end;
  378.     dev_priv->ring.Size = init->ring_size;
  379.     dev_priv->ring.virtual_start = DRM(ioremap)(dev->agp->base + 
  380.     init->ring_start, 
  381.     init->ring_size);
  382.     if (dev_priv->ring.virtual_start == NULL) {
  383. dev->dev_private = (void *) dev_priv;
  384.     i830_dma_cleanup(dev);
  385.     DRM_ERROR("can not ioremap virtual address for"
  386.   " ring buffern");
  387.     return -ENOMEM;
  388. }
  389.     dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
  390.    
  391. dev_priv->w = init->w;
  392. dev_priv->h = init->h;
  393. dev_priv->pitch = init->pitch;
  394. dev_priv->back_offset = init->back_offset;
  395. dev_priv->depth_offset = init->depth_offset;
  396. dev_priv->front_di1 = init->front_offset | init->pitch_bits;
  397. dev_priv->back_di1 = init->back_offset | init->pitch_bits;
  398. dev_priv->zi1 = init->depth_offset | init->pitch_bits;
  399. dev_priv->cpp = init->cpp;
  400. /* We are using seperate values as placeholders for mechanisms for
  401.  * private backbuffer/depthbuffer usage.
  402.  */
  403. dev_priv->back_pitch = init->back_pitch;
  404. dev_priv->depth_pitch = init->depth_pitch;
  405.     /* Program Hardware Status Page */
  406.     dev_priv->hw_status_page = pci_alloc_consistent(dev->pdev, PAGE_SIZE, 
  407. &dev_priv->dma_status_page);
  408.     if(dev_priv->hw_status_page == NULL) {
  409. dev->dev_private = (void *)dev_priv;
  410. i830_dma_cleanup(dev);
  411. DRM_ERROR("Can not allocate hardware status pagen");
  412. return -ENOMEM;
  413. }
  414.     memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
  415. DRM_DEBUG("hw status page @ %pn", dev_priv->hw_status_page);
  416.    
  417.     I830_WRITE(0x02080, dev_priv->dma_status_page);
  418. DRM_DEBUG("Enabled hardware status pagen");
  419.    
  420.     /* Now we need to init our freelist */
  421.     if(i830_freelist_init(dev, dev_priv) != 0) {
  422. dev->dev_private = (void *)dev_priv;
  423.     i830_dma_cleanup(dev);
  424.     DRM_ERROR("Not enough space in the status page for"
  425.   " the freelistn");
  426.     return -ENOMEM;
  427. }
  428. dev->dev_private = (void *)dev_priv;
  429.     return 0;
  430. }
  431. int i830_dma_init(struct inode *inode, struct file *filp,
  432.   unsigned int cmd, unsigned long arg)
  433. {
  434.     drm_file_t *priv = filp->private_data;
  435.     drm_device_t *dev = priv->dev;
  436.     drm_i830_private_t *dev_priv;
  437.     drm_i830_init_t init;
  438.     int retcode = 0;
  439.    if (copy_from_user(&init, (drm_i830_init_t *)arg, sizeof(init)))
  440. return -EFAULT;
  441.     switch(init.func) {
  442.   case I830_INIT_DMA:
  443. dev_priv = DRM(alloc)(sizeof(drm_i830_private_t), 
  444.       DRM_MEM_DRIVER);
  445.     if(dev_priv == NULL) return -ENOMEM;
  446.     retcode = i830_dma_initialize(dev, dev_priv, &init);
  447.     break;
  448.   case I830_CLEANUP_DMA:
  449.     retcode = i830_dma_cleanup(dev);
  450.     break;
  451.   default:
  452.     retcode = -EINVAL;
  453.     break;
  454. }
  455.    
  456.     return retcode;
  457. }
  458. /* Most efficient way to verify state for the i830 is as it is
  459.  * emitted.  Non-conformant state is silently dropped.
  460.  *
  461.  * Use 'volatile' & local var tmp to force the emitted values to be
  462.  * identical to the verified ones.
  463.  */
  464. static void i830EmitContextVerified( drm_device_t *dev, 
  465.      volatile unsigned int *code )
  466. {
  467.     drm_i830_private_t *dev_priv = dev->dev_private;
  468. int i, j = 0;
  469. unsigned int tmp;
  470. RING_LOCALS;
  471. BEGIN_LP_RING( I830_CTX_SETUP_SIZE );
  472. for ( i = 0 ; i < I830_CTX_SETUP_SIZE ; i++ ) {
  473. tmp = code[i];
  474. #if 0
  475. if ((tmp & (7<<29)) == (3<<29) &&
  476.     (tmp & (0x1f<<24)) < (0x1d<<24)) {
  477. OUT_RING( tmp ); 
  478. j++;
  479. } else {
  480. printk("Skipping %dn", i);
  481. }
  482. #else
  483. OUT_RING( tmp ); 
  484. j++;
  485. #endif
  486. }
  487. if (j & 1) 
  488. OUT_RING( 0 ); 
  489. ADVANCE_LP_RING();
  490. }
  491. static void i830EmitTexVerified( drm_device_t *dev, 
  492.  volatile unsigned int *code ) 
  493. {
  494.     drm_i830_private_t *dev_priv = dev->dev_private;
  495. int i, j = 0;
  496. unsigned int tmp;
  497. RING_LOCALS;
  498. BEGIN_LP_RING( I830_TEX_SETUP_SIZE );
  499. OUT_RING( GFX_OP_MAP_INFO );
  500. OUT_RING( code[I830_TEXREG_MI1] );
  501. OUT_RING( code[I830_TEXREG_MI2] );
  502. OUT_RING( code[I830_TEXREG_MI3] );
  503. OUT_RING( code[I830_TEXREG_MI4] );
  504. OUT_RING( code[I830_TEXREG_MI5] );
  505. for ( i = 6 ; i < I830_TEX_SETUP_SIZE ; i++ ) {
  506. tmp = code[i];
  507. OUT_RING( tmp ); 
  508. j++;
  509. if (j & 1) 
  510. OUT_RING( 0 ); 
  511. ADVANCE_LP_RING();
  512. }
  513. static void i830EmitTexBlendVerified( drm_device_t *dev, 
  514.      volatile unsigned int *code,
  515.      volatile unsigned int num)
  516. {
  517.     drm_i830_private_t *dev_priv = dev->dev_private;
  518. int i, j = 0;
  519. unsigned int tmp;
  520. RING_LOCALS;
  521. BEGIN_LP_RING( num );
  522. for ( i = 0 ; i < num ; i++ ) {
  523. tmp = code[i];
  524. OUT_RING( tmp );
  525. j++;
  526. }
  527. if (j & 1) 
  528. OUT_RING( 0 ); 
  529. ADVANCE_LP_RING();
  530. }
  531. static void i830EmitTexPalette( drm_device_t *dev,
  532.         unsigned int *palette,
  533.         int number,
  534.         int is_shared )
  535. {
  536.     drm_i830_private_t *dev_priv = dev->dev_private;
  537. int i;
  538. RING_LOCALS;
  539. BEGIN_LP_RING( 258 );
  540. if(is_shared == 1) {
  541. OUT_RING(CMD_OP_MAP_PALETTE_LOAD |
  542.  MAP_PALETTE_NUM(0) |
  543.  MAP_PALETTE_BOTH);
  544. } else {
  545. OUT_RING(CMD_OP_MAP_PALETTE_LOAD | MAP_PALETTE_NUM(number));
  546. }
  547. for(i = 0; i < 256; i++) {
  548. OUT_RING(palette[i]);
  549. }
  550. OUT_RING(0);
  551. }
  552. /* Need to do some additional checking when setting the dest buffer.
  553.  */
  554. static void i830EmitDestVerified( drm_device_t *dev, 
  555.   volatile unsigned int *code ) 
  556. {
  557.     drm_i830_private_t *dev_priv = dev->dev_private;
  558. unsigned int tmp;
  559. RING_LOCALS;
  560. BEGIN_LP_RING( I830_DEST_SETUP_SIZE + 6 );
  561. tmp = code[I830_DESTREG_CBUFADDR];
  562. if (tmp == dev_priv->front_di1) {
  563. /* Don't use fence when front buffer rendering */
  564. OUT_RING( CMD_OP_DESTBUFFER_INFO );
  565. OUT_RING( BUF_3D_ID_COLOR_BACK | 
  566.   BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) );
  567. OUT_RING( tmp );
  568. OUT_RING( CMD_OP_DESTBUFFER_INFO );
  569. OUT_RING( BUF_3D_ID_DEPTH |
  570.   BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp));
  571. OUT_RING( dev_priv->zi1 );
  572. } else if(tmp == dev_priv->back_di1) {
  573. OUT_RING( CMD_OP_DESTBUFFER_INFO );
  574. OUT_RING( BUF_3D_ID_COLOR_BACK | 
  575.   BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) |
  576.   BUF_3D_USE_FENCE);
  577. OUT_RING( tmp );
  578. OUT_RING( CMD_OP_DESTBUFFER_INFO );
  579. OUT_RING( BUF_3D_ID_DEPTH | BUF_3D_USE_FENCE | 
  580.   BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp));
  581. OUT_RING( dev_priv->zi1 );
  582. } else {
  583. DRM_DEBUG("bad di1 %x (allow %x or %x)n",
  584.   tmp, dev_priv->front_di1, dev_priv->back_di1);
  585. }
  586. /* invarient:
  587.  */
  588. OUT_RING( GFX_OP_DESTBUFFER_VARS );
  589. OUT_RING( code[I830_DESTREG_DV1] );
  590. OUT_RING( GFX_OP_DRAWRECT_INFO );
  591. OUT_RING( code[I830_DESTREG_DR1] );
  592. OUT_RING( code[I830_DESTREG_DR2] );
  593. OUT_RING( code[I830_DESTREG_DR3] );
  594. OUT_RING( code[I830_DESTREG_DR4] );
  595. /* Need to verify this */
  596. tmp = code[I830_DESTREG_SENABLE];
  597. if((tmp & ~0x3) == GFX_OP_SCISSOR_ENABLE) {
  598. OUT_RING( tmp );
  599. } else {
  600. DRM_DEBUG("bad scissor enablen");
  601. OUT_RING( 0 );
  602. }
  603. OUT_RING( code[I830_DESTREG_SENABLE] );
  604. OUT_RING( GFX_OP_SCISSOR_RECT );
  605. OUT_RING( code[I830_DESTREG_SR1] );
  606. OUT_RING( code[I830_DESTREG_SR2] );
  607. ADVANCE_LP_RING();
  608. }
  609. static void i830EmitState( drm_device_t *dev )
  610. {
  611.     drm_i830_private_t *dev_priv = dev->dev_private;
  612.        drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
  613. unsigned int dirty = sarea_priv->dirty;
  614. if (dirty & I830_UPLOAD_BUFFERS) {
  615. i830EmitDestVerified( dev, sarea_priv->BufferState );
  616. sarea_priv->dirty &= ~I830_UPLOAD_BUFFERS;
  617. }
  618. if (dirty & I830_UPLOAD_CTX) {
  619. i830EmitContextVerified( dev, sarea_priv->ContextState );
  620. sarea_priv->dirty &= ~I830_UPLOAD_CTX;
  621. }
  622. if (dirty & I830_UPLOAD_TEX0) {
  623. i830EmitTexVerified( dev, sarea_priv->TexState[0] );
  624. sarea_priv->dirty &= ~I830_UPLOAD_TEX0;
  625. }
  626. if (dirty & I830_UPLOAD_TEX1) {
  627. i830EmitTexVerified( dev, sarea_priv->TexState[1] );
  628. sarea_priv->dirty &= ~I830_UPLOAD_TEX1;
  629. }
  630. if (dirty & I830_UPLOAD_TEXBLEND0) {
  631. i830EmitTexBlendVerified( dev, sarea_priv->TexBlendState[0],
  632. sarea_priv->TexBlendStateWordsUsed[0]);
  633. sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND0;
  634. }
  635. if (dirty & I830_UPLOAD_TEXBLEND1) {
  636. i830EmitTexBlendVerified( dev, sarea_priv->TexBlendState[1],
  637. sarea_priv->TexBlendStateWordsUsed[1]);
  638. sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND1;
  639. }
  640. if (dirty & I830_UPLOAD_TEX_PALETTE_SHARED) {
  641.    i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 1);
  642. } else {
  643.    if (dirty & I830_UPLOAD_TEX_PALETTE_N(0)) {
  644.       i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 0);
  645.       sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(0);
  646.    }
  647.    if (dirty & I830_UPLOAD_TEX_PALETTE_N(1)) {
  648.       i830EmitTexPalette(dev, sarea_priv->Palette[1], 1, 0);
  649.       sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(1);
  650.    }
  651. }
  652. }
  653. static void i830_dma_dispatch_clear( drm_device_t *dev, int flags, 
  654.     unsigned int clear_color,
  655.     unsigned int clear_zval,
  656.     unsigned int clear_depthmask)
  657. {
  658.     drm_i830_private_t *dev_priv = dev->dev_private;
  659.        drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
  660. int nbox = sarea_priv->nbox;
  661. drm_clip_rect_t *pbox = sarea_priv->boxes;
  662. int pitch = dev_priv->pitch;
  663. int cpp = dev_priv->cpp;
  664. int i;
  665. unsigned int BR13, CMD, D_CMD;
  666. RING_LOCALS;
  667.    i830_kernel_lost_context(dev);
  668. switch(cpp) {
  669. case 2: 
  670. BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
  671. D_CMD = CMD = XY_COLOR_BLT_CMD;
  672. break;
  673. case 4:
  674. BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24) | (1<<25);
  675. CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA | 
  676.        XY_COLOR_BLT_WRITE_RGB);
  677. D_CMD = XY_COLOR_BLT_CMD;
  678. if(clear_depthmask & 0x00ffffff)
  679. D_CMD |= XY_COLOR_BLT_WRITE_RGB;
  680. if(clear_depthmask & 0xff000000)
  681. D_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
  682. break;
  683. default:
  684. BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
  685. D_CMD = CMD = XY_COLOR_BLT_CMD;
  686. break;
  687. }
  688.        if (nbox > I830_NR_SAREA_CLIPRECTS)
  689.       nbox = I830_NR_SAREA_CLIPRECTS;
  690. for (i = 0 ; i < nbox ; i++, pbox++) {
  691. if (pbox->x1 > pbox->x2 ||
  692.     pbox->y1 > pbox->y2 ||
  693.     pbox->x2 > dev_priv->w ||
  694.     pbox->y2 > dev_priv->h)
  695. continue;
  696.     if ( flags & I830_FRONT ) {     
  697.     DRM_DEBUG("clear frontn");
  698. BEGIN_LP_RING( 6 );     
  699. OUT_RING( CMD );
  700. OUT_RING( BR13 );
  701. OUT_RING( (pbox->y1 << 16) | pbox->x1 );
  702. OUT_RING( (pbox->y2 << 16) | pbox->x2 );
  703. OUT_RING( 0 );
  704. OUT_RING( clear_color );
  705. ADVANCE_LP_RING();
  706. }
  707. if ( flags & I830_BACK ) {
  708. DRM_DEBUG("clear backn");
  709. BEGIN_LP_RING( 6 );     
  710. OUT_RING( CMD );
  711. OUT_RING( BR13 );
  712. OUT_RING( (pbox->y1 << 16) | pbox->x1 );
  713. OUT_RING( (pbox->y2 << 16) | pbox->x2 );
  714. OUT_RING( dev_priv->back_offset );
  715. OUT_RING( clear_color );
  716. ADVANCE_LP_RING();
  717. }
  718. if ( flags & I830_DEPTH ) {
  719. DRM_DEBUG("clear depthn");
  720. BEGIN_LP_RING( 6 );
  721. OUT_RING( D_CMD );
  722. OUT_RING( BR13 );
  723. OUT_RING( (pbox->y1 << 16) | pbox->x1 );
  724. OUT_RING( (pbox->y2 << 16) | pbox->x2 );
  725. OUT_RING( dev_priv->depth_offset );
  726. OUT_RING( clear_zval );
  727. ADVANCE_LP_RING();
  728. }
  729. }
  730. }
  731. static void i830_dma_dispatch_swap( drm_device_t *dev )
  732. {
  733.     drm_i830_private_t *dev_priv = dev->dev_private;
  734.        drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
  735. int nbox = sarea_priv->nbox;
  736. drm_clip_rect_t *pbox = sarea_priv->boxes;
  737. int pitch = dev_priv->pitch;
  738. int cpp = dev_priv->cpp;
  739. int ofs = dev_priv->back_offset;
  740. int i;
  741. unsigned int CMD, BR13;
  742. RING_LOCALS;
  743. DRM_DEBUG("swapbuffersn");
  744. switch(cpp) {
  745. case 2: 
  746. BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
  747. CMD = XY_SRC_COPY_BLT_CMD;
  748. break;
  749. case 4:
  750. BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24) | (1<<25);
  751. CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
  752.        XY_SRC_COPY_BLT_WRITE_RGB);
  753. break;
  754. default:
  755. BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
  756. CMD = XY_SRC_COPY_BLT_CMD;
  757. break;
  758. }
  759.    i830_kernel_lost_context(dev);
  760.        if (nbox > I830_NR_SAREA_CLIPRECTS)
  761.       nbox = I830_NR_SAREA_CLIPRECTS;
  762. for (i = 0 ; i < nbox; i++, pbox++) 
  763. {
  764. if (pbox->x1 > pbox->x2 ||
  765.     pbox->y1 > pbox->y2 ||
  766.     pbox->x2 > dev_priv->w ||
  767.     pbox->y2 > dev_priv->h)
  768. continue;
  769.  
  770. DRM_DEBUG("dispatch swap %d,%d-%d,%d!n",
  771.   pbox->x1, pbox->y1,
  772.   pbox->x2, pbox->y2);
  773. BEGIN_LP_RING( 8 );
  774. OUT_RING( CMD );
  775. OUT_RING( BR13 );
  776. OUT_RING( (pbox->y1 << 16) |
  777.   pbox->x1 );
  778. OUT_RING( (pbox->y2 << 16) |
  779.   pbox->x2 );
  780. OUT_RING( 0 /* front ofs always zero */ );
  781. OUT_RING( (pbox->y1 << 16) |
  782.   pbox->x1 );
  783. OUT_RING( BR13 & 0xffff );
  784. OUT_RING( ofs );
  785. ADVANCE_LP_RING();
  786. }
  787. }
  788. static void i830_dma_dispatch_vertex(drm_device_t *dev, 
  789.      drm_buf_t *buf,
  790.      int discard,
  791.      int used)
  792. {
  793.     drm_i830_private_t *dev_priv = dev->dev_private;
  794. drm_i830_buf_priv_t *buf_priv = buf->dev_private;
  795.     drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
  796.     drm_clip_rect_t *box = sarea_priv->boxes;
  797.     int nbox = sarea_priv->nbox;
  798. unsigned long address = (unsigned long)buf->bus_address;
  799. unsigned long start = address - dev->agp->base;     
  800. int i = 0, u;
  801.     RING_LOCALS;
  802.     i830_kernel_lost_context(dev);
  803.     if (nbox > I830_NR_SAREA_CLIPRECTS) 
  804. nbox = I830_NR_SAREA_CLIPRECTS;
  805. if (discard) {
  806. u = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, 
  807.     I830_BUF_HARDWARE);
  808. if(u != I830_BUF_CLIENT) {
  809. DRM_DEBUG("xxxx 2n");
  810. }
  811. }
  812. if (used > 4*1024) 
  813. used = 0;
  814. if (sarea_priv->dirty)
  815.    i830EmitState( dev );
  816.    DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %dn", 
  817.   address, used, nbox);
  818.     dev_priv->counter++;
  819.     DRM_DEBUG(  "dispatch counter : %ldn", dev_priv->counter);
  820.     DRM_DEBUG(  "i830_dma_dispatchn");
  821.     DRM_DEBUG(  "start : %lxn", start);
  822. DRM_DEBUG(  "used : %dn", used);
  823.     DRM_DEBUG(  "start + used - 4 : %ldn", start + used - 4);
  824. if (buf_priv->currently_mapped == I830_BUF_MAPPED) {
  825. *(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE |
  826.      sarea_priv->vertex_prim |
  827.      ((used/4)-2));
  828. if (used & 4) {
  829. *(u32 *)((u32)buf_priv->virtual + used) = 0;
  830. used += 4;
  831. }
  832. i830_unmap_buffer(buf);
  833. }
  834.    
  835. if (used) {
  836. do {
  837. if (i < nbox) {
  838. BEGIN_LP_RING(6);
  839. OUT_RING( GFX_OP_DRAWRECT_INFO );
  840. OUT_RING( sarea_priv->BufferState[I830_DESTREG_DR1] );
  841. OUT_RING( box[i].x1 | (box[i].y1<<16) );
  842. OUT_RING( box[i].x2 | (box[i].y2<<16) );
  843. OUT_RING( sarea_priv->BufferState[I830_DESTREG_DR4] );
  844. OUT_RING( 0 );
  845. ADVANCE_LP_RING();
  846. }
  847. BEGIN_LP_RING(4);
  848. OUT_RING( MI_BATCH_BUFFER );
  849. OUT_RING( start | MI_BATCH_NON_SECURE );
  850. OUT_RING( start + used - 4 );
  851. OUT_RING( 0 );
  852. ADVANCE_LP_RING();
  853. } while (++i < nbox);
  854. }
  855. BEGIN_LP_RING(10);
  856. OUT_RING( CMD_STORE_DWORD_IDX );
  857. OUT_RING( 20 );
  858. OUT_RING( dev_priv->counter );
  859. OUT_RING( 0 );
  860. if (discard) {
  861. OUT_RING( CMD_STORE_DWORD_IDX );
  862. OUT_RING( buf_priv->my_use_idx );
  863. OUT_RING( I830_BUF_FREE );
  864. OUT_RING( 0 );
  865. }
  866.        OUT_RING( CMD_REPORT_HEAD );
  867. OUT_RING( 0 );
  868.     ADVANCE_LP_RING();
  869. }
  870. /* Interrupts are only for flushing */
  871. void i830_dma_service(int irq, void *device, struct pt_regs *regs)
  872. {
  873. drm_device_t  *dev = (drm_device_t *)device;
  874.        drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
  875.     u16 temp;
  876.    
  877.        temp = I830_READ16(I830REG_INT_IDENTITY_R);
  878.     temp = temp & ~(0x6000);
  879.     if(temp != 0) I830_WRITE16(I830REG_INT_IDENTITY_R, 
  880.    temp); /* Clear all interrupts */
  881. else
  882.    return;
  883.  
  884.     queue_task(&dev->tq, &tq_immediate);
  885.     mark_bh(IMMEDIATE_BH);
  886. }
  887. void DRM(dma_immediate_bh)(void *device)
  888. {
  889. drm_device_t *dev = (drm_device_t *) device;
  890.        drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
  891.     atomic_set(&dev_priv->flush_done, 1);
  892.     wake_up_interruptible(&dev_priv->flush_queue);
  893. }
  894. static inline void i830_dma_emit_flush(drm_device_t *dev)
  895. {
  896.     drm_i830_private_t *dev_priv = dev->dev_private;
  897.     RING_LOCALS;
  898.     i830_kernel_lost_context(dev);
  899.     BEGIN_LP_RING(2);
  900.        OUT_RING( CMD_REPORT_HEAD );
  901.        OUT_RING( GFX_OP_USER_INTERRUPT );
  902.        ADVANCE_LP_RING();
  903. i830_wait_ring( dev, dev_priv->ring.Size - 8 );
  904. atomic_set(&dev_priv->flush_done, 1);
  905. wake_up_interruptible(&dev_priv->flush_queue);
  906. }
  907. static inline void i830_dma_quiescent_emit(drm_device_t *dev)
  908. {
  909.        drm_i830_private_t *dev_priv = dev->dev_private;
  910.     RING_LOCALS;
  911.    i830_kernel_lost_context(dev);
  912.     BEGIN_LP_RING(4);
  913.     OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
  914.     OUT_RING( CMD_REPORT_HEAD );
  915.        OUT_RING( 0 );
  916.        OUT_RING( GFX_OP_USER_INTERRUPT );
  917.     ADVANCE_LP_RING();
  918. i830_wait_ring( dev, dev_priv->ring.Size - 8 );
  919. atomic_set(&dev_priv->flush_done, 1);
  920. wake_up_interruptible(&dev_priv->flush_queue);
  921. }
  922. void i830_dma_quiescent(drm_device_t *dev)
  923. {
  924.        DECLARE_WAITQUEUE(entry, current);
  925.    drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
  926. unsigned long end;      
  927.     if(dev_priv == NULL) {
  928.     return;
  929. }
  930.        atomic_set(&dev_priv->flush_done, 0);
  931.     add_wait_queue(&dev_priv->flush_queue, &entry);
  932.     end = jiffies + (HZ*3);
  933.    
  934.     for (;;) {
  935. current->state = TASK_INTERRUPTIBLE;
  936.        i830_dma_quiescent_emit(dev);
  937.     if (atomic_read(&dev_priv->flush_done) == 1) break;
  938. if(time_before(end, jiffies)) {
  939.     DRM_ERROR("lockupn");
  940.     break;
  941. }    
  942.        schedule_timeout(HZ*3);
  943.        if (signal_pending(current)) {
  944.     break;
  945. }
  946. }
  947.    
  948.     current->state = TASK_RUNNING;
  949.     remove_wait_queue(&dev_priv->flush_queue, &entry);
  950.    
  951.     return;
  952. }
  953. static int i830_flush_queue(drm_device_t *dev)
  954. {
  955.     DECLARE_WAITQUEUE(entry, current);
  956.    drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
  957. drm_device_dma_t *dma = dev->dma;
  958. unsigned long end;
  959.     int i, ret = 0;      
  960.     if(dev_priv == NULL) {
  961.     return 0;
  962. }
  963.        atomic_set(&dev_priv->flush_done, 0);
  964.     add_wait_queue(&dev_priv->flush_queue, &entry);
  965.     end = jiffies + (HZ*3);
  966.     for (;;) {
  967. current->state = TASK_INTERRUPTIBLE;
  968.        i830_dma_emit_flush(dev);
  969.     if (atomic_read(&dev_priv->flush_done) == 1) break;
  970. if(time_before(end, jiffies)) {
  971.     DRM_ERROR("lockupn");
  972.     break;
  973. }    
  974.        schedule_timeout(HZ*3);
  975.        if (signal_pending(current)) {
  976.     ret = -EINTR; /* Can't restart */
  977.     break;
  978. }
  979. }
  980.    
  981.     current->state = TASK_RUNNING;
  982.     remove_wait_queue(&dev_priv->flush_queue, &entry);
  983.     for (i = 0; i < dma->buf_count; i++) {
  984.     drm_buf_t *buf = dma->buflist[ i ];
  985.     drm_i830_buf_priv_t *buf_priv = buf->dev_private;
  986.    
  987. int used = cmpxchg(buf_priv->in_use, I830_BUF_HARDWARE, 
  988.    I830_BUF_FREE);
  989. if (used == I830_BUF_HARDWARE)
  990. DRM_DEBUG("reclaimed from HARDWAREn");
  991. if (used == I830_BUF_CLIENT)
  992. DRM_DEBUG("still on client HARDWAREn");
  993. }
  994.     return ret;
  995. }
  996. /* Must be called with the lock held */
  997. void i830_reclaim_buffers(drm_device_t *dev, pid_t pid)
  998. {
  999. drm_device_dma_t *dma = dev->dma;
  1000. int  i;
  1001. if (!dma) return;
  1002.        if (!dev->dev_private) return;
  1003. if (!dma->buflist) return;
  1004.         i830_flush_queue(dev);
  1005. for (i = 0; i < dma->buf_count; i++) {
  1006.     drm_buf_t *buf = dma->buflist[ i ];
  1007.     drm_i830_buf_priv_t *buf_priv = buf->dev_private;
  1008.    
  1009. if (buf->pid == pid && buf_priv) {
  1010. int used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, 
  1011.    I830_BUF_FREE);
  1012. if (used == I830_BUF_CLIENT)
  1013. DRM_DEBUG("reclaimed from clientn");
  1014.     if(buf_priv->currently_mapped == I830_BUF_MAPPED)
  1015.       buf_priv->currently_mapped = I830_BUF_UNMAPPED;
  1016. }
  1017. }
  1018. }
  1019. int i830_flush_ioctl(struct inode *inode, struct file *filp, 
  1020.      unsigned int cmd, unsigned long arg)
  1021. {
  1022.     drm_file_t   *priv   = filp->private_data;
  1023.     drm_device_t   *dev   = priv->dev;
  1024.    
  1025.     DRM_DEBUG("i830_flush_ioctln");
  1026.     if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
  1027. DRM_ERROR("i830_flush_ioctl called without lock heldn");
  1028. return -EINVAL;
  1029. }
  1030.     i830_flush_queue(dev);
  1031.     return 0;
  1032. }
  1033. int i830_dma_vertex(struct inode *inode, struct file *filp,
  1034.        unsigned int cmd, unsigned long arg)
  1035. {
  1036. drm_file_t *priv = filp->private_data;
  1037. drm_device_t *dev = priv->dev;
  1038. drm_device_dma_t *dma = dev->dma;
  1039.     drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
  1040.        u32 *hw_status = (u32 *)dev_priv->hw_status_page;
  1041.     drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) 
  1042.       dev_priv->sarea_priv; 
  1043. drm_i830_vertex_t vertex;
  1044. if (copy_from_user(&vertex, (drm_i830_vertex_t *)arg, sizeof(vertex)))
  1045. return -EFAULT;
  1046.     if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
  1047. DRM_ERROR("i830_dma_vertex called without lock heldn");
  1048. return -EINVAL;
  1049. }
  1050. DRM_DEBUG("i830 dma vertex, idx %d used %d discard %dn",
  1051.   vertex.idx, vertex.used, vertex.discard);
  1052. if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL;
  1053. i830_dma_dispatch_vertex( dev, 
  1054.   dma->buflist[ vertex.idx ], 
  1055.   vertex.discard, vertex.used );
  1056. sarea_priv->last_enqueue = dev_priv->counter-1;
  1057.     sarea_priv->last_dispatch = (int) hw_status[5];
  1058.    
  1059. return 0;
  1060. }
  1061. int i830_clear_bufs(struct inode *inode, struct file *filp,
  1062.    unsigned int cmd, unsigned long arg)
  1063. {
  1064. drm_file_t *priv = filp->private_data;
  1065. drm_device_t *dev = priv->dev;
  1066. drm_i830_clear_t clear;
  1067.     if (copy_from_user(&clear, (drm_i830_clear_t *)arg, sizeof(clear)))
  1068. return -EFAULT;
  1069.    
  1070.     if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
  1071. DRM_ERROR("i830_clear_bufs called without lock heldn");
  1072. return -EINVAL;
  1073. }
  1074. /* GH: Someone's doing nasty things... */
  1075. if (!dev->dev_private) {
  1076. return -EINVAL;
  1077. }
  1078. i830_dma_dispatch_clear( dev, clear.flags, 
  1079.  clear.clear_color, 
  1080.  clear.clear_depth,
  1081.          clear.clear_depthmask);
  1082.     return 0;
  1083. }
  1084. int i830_swap_bufs(struct inode *inode, struct file *filp,
  1085.   unsigned int cmd, unsigned long arg)
  1086. {
  1087. drm_file_t *priv = filp->private_data;
  1088. drm_device_t *dev = priv->dev;
  1089.    
  1090. DRM_DEBUG("i830_swap_bufsn");
  1091.     if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
  1092. DRM_ERROR("i830_swap_buf called without lock heldn");
  1093. return -EINVAL;
  1094. }
  1095. i830_dma_dispatch_swap( dev );
  1096.     return 0;
  1097. }
  1098. int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd,
  1099. unsigned long arg)
  1100. {
  1101.     drm_file_t   *priv     = filp->private_data;
  1102. drm_device_t   *dev     = priv->dev;
  1103.     drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
  1104.        u32 *hw_status = (u32 *)dev_priv->hw_status_page;
  1105.     drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) 
  1106.       dev_priv->sarea_priv; 
  1107.        sarea_priv->last_dispatch = (int) hw_status[5];
  1108. return 0;
  1109. }
  1110. int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
  1111. unsigned long arg)
  1112. {
  1113. drm_file_t   *priv     = filp->private_data;
  1114. drm_device_t   *dev     = priv->dev;
  1115. int   retcode   = 0;
  1116. drm_i830_dma_t   d;
  1117.     drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
  1118.     u32 *hw_status = (u32 *)dev_priv->hw_status_page;
  1119.     drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) 
  1120.       dev_priv->sarea_priv; 
  1121. DRM_DEBUG("getbufn");
  1122.     if (copy_from_user(&d, (drm_i830_dma_t *)arg, sizeof(d)))
  1123. return -EFAULT;
  1124.    
  1125. if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
  1126. DRM_ERROR("i830_dma called without lock heldn");
  1127. return -EINVAL;
  1128. }
  1129. d.granted = 0;
  1130. retcode = i830_dma_get_buffer(dev, &d, filp);
  1131. DRM_DEBUG("i830_dma: %d returning %d, granted = %dn",
  1132.   current->pid, retcode, d.granted);
  1133. if (copy_to_user((drm_dma_t *)arg, &d, sizeof(d)))
  1134. return -EFAULT;
  1135.     sarea_priv->last_dispatch = (int) hw_status[5];
  1136. return retcode;
  1137. }
  1138. int i830_copybuf(struct inode *inode, struct file *filp, unsigned int cmd,
  1139. unsigned long arg)
  1140. {
  1141. drm_file_t   *priv     = filp->private_data;
  1142. drm_device_t   *dev     = priv->dev;
  1143. drm_i830_copy_t   d;
  1144.     drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
  1145.     u32 *hw_status = (u32 *)dev_priv->hw_status_page;
  1146.     drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) 
  1147.       dev_priv->sarea_priv; 
  1148. drm_buf_t *buf;
  1149. drm_i830_buf_priv_t *buf_priv;
  1150. drm_device_dma_t *dma = dev->dma;
  1151. if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
  1152. DRM_ERROR("i830_dma called without lock heldn");
  1153. return -EINVAL;
  1154. }
  1155.    
  1156.     if (copy_from_user(&d, (drm_i830_copy_t *)arg, sizeof(d)))
  1157. return -EFAULT;
  1158. if(d.idx < 0 || d.idx > dma->buf_count) return -EINVAL;
  1159. buf = dma->buflist[ d.idx ];
  1160.     buf_priv = buf->dev_private;
  1161. if (buf_priv->currently_mapped != I830_BUF_MAPPED) return -EPERM;
  1162. if(d.used < 0 || d.used > buf->total) return -EINVAL;
  1163.     if (copy_from_user(buf_priv->virtual, d.address, d.used))
  1164. return -EFAULT;
  1165.     sarea_priv->last_dispatch = (int) hw_status[5];
  1166. return 0;
  1167. }
  1168. int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
  1169. unsigned long arg)
  1170. {
  1171. if(VM_DONTCOPY == 0) return 1;
  1172. return 0;
  1173. }