OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [drm/] [i810_dma.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* i810_dma.c -- DMA support for the i810 -*- 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 <keith@tungstengraphics.com>
30
 *
31
 */
32
 
33
#include <linux/config.h>
34
#include "i810.h"
35
#include "drmP.h"
36
#include "drm.h"
37
#include "i810_drm.h"
38
#include "i810_drv.h"
39
#include <linux/interrupt.h>    /* For task queue support */
40
#include <linux/delay.h>
41
 
42
#define DO_MUNMAP(m, a, l)      do_munmap(m, a, l)
43
 
44
#define I810_BUF_FREE           2
45
#define I810_BUF_CLIENT         1
46
#define I810_BUF_HARDWARE       0
47
 
48
#define I810_BUF_UNMAPPED 0
49
#define I810_BUF_MAPPED   1
50
 
51
#define RING_LOCALS     unsigned int outring, ringmask; volatile char *virt;
52
 
53
#define BEGIN_LP_RING(n) do {                                           \
54
        if (0) DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", n, __FUNCTION__);  \
55
        if (dev_priv->ring.space < n*4)                                 \
56
                i810_wait_ring(dev, n*4);                               \
57
        dev_priv->ring.space -= n*4;                                    \
58
        outring = dev_priv->ring.tail;                                  \
59
        ringmask = dev_priv->ring.tail_mask;                            \
60
        virt = dev_priv->ring.virtual_start;                            \
61
} while (0)
62
 
63
#define ADVANCE_LP_RING() do {                          \
64
        if (0) DRM_DEBUG("ADVANCE_LP_RING\n");                   \
65
        dev_priv->ring.tail = outring;                  \
66
        I810_WRITE(LP_RING + RING_TAIL, outring);       \
67
} while(0)
68
 
69
#define OUT_RING(n) do {                                \
70
        if (0) DRM_DEBUG("   OUT_RING %x\n", (int)(n));  \
71
        *(volatile unsigned int *)(virt + outring) = n; \
72
        outring += 4;                                   \
73
        outring &= ringmask;                            \
74
} while (0)
75
 
76
static inline void i810_print_status_page(drm_device_t *dev)
77
{
78
        drm_device_dma_t *dma = dev->dma;
79
        drm_i810_private_t *dev_priv = dev->dev_private;
80
        u32 *temp = (u32 *)dev_priv->hw_status_page;
81
        int i;
82
 
83
        DRM_DEBUG(  "hw_status: Interrupt Status : %x\n", temp[0]);
84
        DRM_DEBUG(  "hw_status: LpRing Head ptr : %x\n", temp[1]);
85
        DRM_DEBUG(  "hw_status: IRing Head ptr : %x\n", temp[2]);
86
        DRM_DEBUG(  "hw_status: Reserved : %x\n", temp[3]);
87
        DRM_DEBUG(  "hw_status: Last Render: %x\n", temp[4]);
88
        DRM_DEBUG(  "hw_status: Driver Counter : %d\n", temp[5]);
89
        for(i = 6; i < dma->buf_count + 6; i++) {
90
                DRM_DEBUG( "buffer status idx : %d used: %d\n", i - 6, temp[i]);
91
        }
92
}
93
 
94
static drm_buf_t *i810_freelist_get(drm_device_t *dev)
95
{
96
        drm_device_dma_t *dma = dev->dma;
97
        int              i;
98
        int              used;
99
 
100
        /* Linear search might not be the best solution */
101
 
102
        for (i = 0; i < dma->buf_count; i++) {
103
                drm_buf_t *buf = dma->buflist[ i ];
104
                drm_i810_buf_priv_t *buf_priv = buf->dev_private;
105
                /* In use is already a pointer */
106
                used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
107
                               I810_BUF_CLIENT);
108
                if(used == I810_BUF_FREE) {
109
                        return buf;
110
                }
111
        }
112
        return NULL;
113
}
114
 
115
/* This should only be called if the buffer is not sent to the hardware
116
 * yet, the hardware updates in use for us once its on the ring buffer.
117
 */
118
 
119
static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf)
120
{
121
        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
122
        int used;
123
 
124
        /* In use is already a pointer */
125
        used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_FREE);
126
        if(used != I810_BUF_CLIENT) {
127
                DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
128
                return -EINVAL;
129
        }
130
 
131
        return 0;
132
}
133
 
134
static struct file_operations i810_buffer_fops = {
135
        .open    = DRM(open),
136
        .flush   = DRM(flush),
137
        .release = DRM(release),
138
        .ioctl   = DRM(ioctl),
139
        .mmap    = i810_mmap_buffers,
140
        .read    = DRM(read),
141
        .fasync  = DRM(fasync),
142
        .poll    = DRM(poll),
143
};
144
 
145
int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
146
{
147
        drm_file_t          *priv         = filp->private_data;
148
        drm_device_t        *dev;
149
        drm_i810_private_t  *dev_priv;
150
        drm_buf_t           *buf;
151
        drm_i810_buf_priv_t *buf_priv;
152
 
153
        lock_kernel();
154
        dev      = priv->dev;
155
        dev_priv = dev->dev_private;
156
        buf      = dev_priv->mmap_buffer;
157
        buf_priv = buf->dev_private;
158
 
159
        vma->vm_flags |= (VM_IO | VM_DONTCOPY);
160
        vma->vm_file = filp;
161
 
162
        buf_priv->currently_mapped = I810_BUF_MAPPED;
163
        unlock_kernel();
164
 
165
        if (remap_page_range(DRM_RPR_ARG(vma) vma->vm_start,
166
                             VM_OFFSET(vma),
167
                             vma->vm_end - vma->vm_start,
168
                             vma->vm_page_prot)) return -EAGAIN;
169
        return 0;
170
}
171
 
172
static int i810_map_buffer(drm_buf_t *buf, struct file *filp)
173
{
174
        drm_file_t        *priv   = filp->private_data;
175
        drm_device_t      *dev    = priv->dev;
176
        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
177
        drm_i810_private_t *dev_priv = dev->dev_private;
178
        struct file_operations *old_fops;
179
        int retcode = 0;
180
 
181
        if(buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL;
182
 
183
 
184
 
185
 
186
        down_write( &current->mm->mmap_sem );
187
 
188
        old_fops = filp->f_op;
189
        filp->f_op = &i810_buffer_fops;
190
        dev_priv->mmap_buffer = buf;
191
        buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total,
192
                                            PROT_READ|PROT_WRITE,
193
                                            MAP_SHARED,
194
                                            buf->bus_address);
195
        dev_priv->mmap_buffer = NULL;
196
        filp->f_op = old_fops;
197
        if ((unsigned long)buf_priv->virtual > -1024UL) {
198
                /* Real error */
199
                DRM_DEBUG("mmap error\n");
200
                retcode = (signed int)buf_priv->virtual;
201
                buf_priv->virtual = 0;
202
        }
203
 
204
 
205
 
206
        up_write( &current->mm->mmap_sem );
207
 
208
        return retcode;
209
}
210
 
211
static int i810_unmap_buffer(drm_buf_t *buf)
212
{
213
        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
214
        int retcode = 0;
215
 
216
        if(buf_priv->currently_mapped != I810_BUF_MAPPED)
217
                return -EINVAL;
218
 
219
 
220
 
221
        down_write( &current->mm->mmap_sem );
222
 
223
        retcode = DO_MUNMAP(current->mm,
224
                            (unsigned long)buf_priv->virtual,
225
                            (size_t) buf->total);
226
 
227
 
228
 
229
        up_write( &current->mm->mmap_sem );
230
 
231
        buf_priv->currently_mapped = I810_BUF_UNMAPPED;
232
        buf_priv->virtual = 0;
233
 
234
        return retcode;
235
}
236
 
237
static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d,
238
                               struct file *filp)
239
{
240
        drm_file_t        *priv   = filp->private_data;
241
        drm_buf_t         *buf;
242
        drm_i810_buf_priv_t *buf_priv;
243
        int retcode = 0;
244
 
245
        buf = i810_freelist_get(dev);
246
        if (!buf) {
247
                retcode = -ENOMEM;
248
                DRM_DEBUG("retcode=%d\n", retcode);
249
                return retcode;
250
        }
251
 
252
        retcode = i810_map_buffer(buf, filp);
253
        if(retcode) {
254
                i810_freelist_put(dev, buf);
255
                DRM_DEBUG("mapbuf failed, retcode %d\n", retcode);
256
                return retcode;
257
        }
258
        buf->pid     = priv->pid;
259
        buf_priv = buf->dev_private;
260
        d->granted = 1;
261
        d->request_idx = buf->idx;
262
        d->request_size = buf->total;
263
        d->virtual = buf_priv->virtual;
264
 
265
        return retcode;
266
}
267
 
268
static int i810_dma_cleanup(drm_device_t *dev)
269
{
270
        drm_device_dma_t *dma = dev->dma;
271
 
272
        if(dev->dev_private) {
273
                int i;
274
                drm_i810_private_t *dev_priv =
275
                        (drm_i810_private_t *) dev->dev_private;
276
 
277
                if(dev_priv->ring.virtual_start) {
278
                        DRM(ioremapfree)((void *) dev_priv->ring.virtual_start,
279
                                         dev_priv->ring.Size, dev);
280
                }
281
                if(dev_priv->hw_status_page != 0UL) {
282
                        pci_free_consistent(dev->pdev, PAGE_SIZE,
283
                                            (void *)dev_priv->hw_status_page,
284
                                            dev_priv->dma_status_page);
285
                        /* Need to rewrite hardware status page */
286
                        I810_WRITE(0x02080, 0x1ffff000);
287
                }
288
                DRM(free)(dev->dev_private, sizeof(drm_i810_private_t),
289
                         DRM_MEM_DRIVER);
290
                dev->dev_private = NULL;
291
 
292
                for (i = 0; i < dma->buf_count; i++) {
293
                        drm_buf_t *buf = dma->buflist[ i ];
294
                        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
295
                        DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total, dev);
296
                }
297
        }
298
        return 0;
299
}
300
 
301
static int i810_wait_ring(drm_device_t *dev, int n)
302
{
303
        drm_i810_private_t *dev_priv = dev->dev_private;
304
        drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
305
        int iters = 0;
306
        unsigned long end;
307
        unsigned int last_head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
308
 
309
        end = jiffies + (HZ*3);
310
        while (ring->space < n) {
311
                ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
312
                ring->space = ring->head - (ring->tail+8);
313
                if (ring->space < 0) ring->space += ring->Size;
314
 
315
                if (ring->head != last_head)
316
                   end = jiffies + (HZ*3);
317
 
318
                iters++;
319
                if(time_before(end, jiffies)) {
320
                        DRM_ERROR("space: %d wanted %d\n", ring->space, n);
321
                        DRM_ERROR("lockup\n");
322
                        goto out_wait_ring;
323
                }
324
                udelay(1);
325
        }
326
 
327
out_wait_ring:
328
        return iters;
329
}
330
 
331
static void i810_kernel_lost_context(drm_device_t *dev)
332
{
333
        drm_i810_private_t *dev_priv = dev->dev_private;
334
        drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
335
 
336
        ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
337
        ring->tail = I810_READ(LP_RING + RING_TAIL);
338
        ring->space = ring->head - (ring->tail+8);
339
        if (ring->space < 0) ring->space += ring->Size;
340
}
341
 
342
static int i810_freelist_init(drm_device_t *dev, drm_i810_private_t *dev_priv)
343
{
344
        drm_device_dma_t *dma = dev->dma;
345
        int my_idx = 24;
346
        u32 *hw_status = (u32 *)(dev_priv->hw_status_page + my_idx);
347
        int i;
348
 
349
        if(dma->buf_count > 1019) {
350
                /* Not enough space in the status page for the freelist */
351
                return -EINVAL;
352
        }
353
 
354
        for (i = 0; i < dma->buf_count; i++) {
355
                drm_buf_t *buf = dma->buflist[ i ];
356
                drm_i810_buf_priv_t *buf_priv = buf->dev_private;
357
 
358
                buf_priv->in_use = hw_status++;
359
                buf_priv->my_use_idx = my_idx;
360
                my_idx += 4;
361
 
362
                *buf_priv->in_use = I810_BUF_FREE;
363
 
364
                buf_priv->kernel_virtual = DRM(ioremap)(buf->bus_address,
365
                                                        buf->total, dev);
366
        }
367
        return 0;
368
}
369
 
370
static int i810_dma_initialize(drm_device_t *dev,
371
                               drm_i810_private_t *dev_priv,
372
                               drm_i810_init_t *init)
373
{
374
        struct list_head *list;
375
 
376
        memset(dev_priv, 0, sizeof(drm_i810_private_t));
377
 
378
        list_for_each(list, &dev->maplist->head) {
379
                drm_map_list_t *r_list = (drm_map_list_t *)list;
380
                if( r_list->map &&
381
                    r_list->map->type == _DRM_SHM &&
382
                    r_list->map->flags & _DRM_CONTAINS_LOCK ) {
383
                        dev_priv->sarea_map = r_list->map;
384
                        break;
385
                }
386
        }
387
        if(!dev_priv->sarea_map) {
388
                dev->dev_private = (void *)dev_priv;
389
                i810_dma_cleanup(dev);
390
                DRM_ERROR("can not find sarea!\n");
391
                return -EINVAL;
392
        }
393
        DRM_FIND_MAP( dev_priv->mmio_map, init->mmio_offset );
394
        if(!dev_priv->mmio_map) {
395
                dev->dev_private = (void *)dev_priv;
396
                i810_dma_cleanup(dev);
397
                DRM_ERROR("can not find mmio map!\n");
398
                return -EINVAL;
399
        }
400
        DRM_FIND_MAP( dev_priv->buffer_map, init->buffers_offset );
401
        if(!dev_priv->buffer_map) {
402
                dev->dev_private = (void *)dev_priv;
403
                i810_dma_cleanup(dev);
404
                DRM_ERROR("can not find dma buffer map!\n");
405
                return -EINVAL;
406
        }
407
 
408
        dev_priv->sarea_priv = (drm_i810_sarea_t *)
409
                ((u8 *)dev_priv->sarea_map->handle +
410
                 init->sarea_priv_offset);
411
 
412
        dev_priv->ring.Start = init->ring_start;
413
        dev_priv->ring.End = init->ring_end;
414
        dev_priv->ring.Size = init->ring_size;
415
 
416
        dev_priv->ring.virtual_start = DRM(ioremap)(dev->agp->base +
417
                                                    init->ring_start,
418
                                                    init->ring_size, dev);
419
 
420
        if (dev_priv->ring.virtual_start == NULL) {
421
                dev->dev_private = (void *) dev_priv;
422
                i810_dma_cleanup(dev);
423
                DRM_ERROR("can not ioremap virtual address for"
424
                          " ring buffer\n");
425
                return -ENOMEM;
426
        }
427
 
428
        dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
429
 
430
        dev_priv->w = init->w;
431
        dev_priv->h = init->h;
432
        dev_priv->pitch = init->pitch;
433
        dev_priv->back_offset = init->back_offset;
434
        dev_priv->depth_offset = init->depth_offset;
435
 
436
        dev_priv->overlay_offset = init->overlay_offset;
437
        dev_priv->overlay_physical = init->overlay_physical;
438
 
439
        dev_priv->front_di1 = init->front_offset | init->pitch_bits;
440
        dev_priv->back_di1 = init->back_offset | init->pitch_bits;
441
        dev_priv->zi1 = init->depth_offset | init->pitch_bits;
442
 
443
        /* Program Hardware Status Page */
444
        dev_priv->hw_status_page =
445
                (unsigned long) pci_alloc_consistent(dev->pdev, PAGE_SIZE,
446
                                                &dev_priv->dma_status_page);
447
        if(dev_priv->hw_status_page == 0UL) {
448
                dev->dev_private = (void *)dev_priv;
449
                i810_dma_cleanup(dev);
450
                DRM_ERROR("Can not allocate hardware status page\n");
451
                return -ENOMEM;
452
        }
453
        memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE);
454
        DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page);
455
 
456
        I810_WRITE(0x02080, dev_priv->dma_status_page);
457
        DRM_DEBUG("Enabled hardware status page\n");
458
 
459
        /* Now we need to init our freelist */
460
        if(i810_freelist_init(dev, dev_priv) != 0) {
461
                dev->dev_private = (void *)dev_priv;
462
                i810_dma_cleanup(dev);
463
                DRM_ERROR("Not enough space in the status page for"
464
                          " the freelist\n");
465
                return -ENOMEM;
466
        }
467
        dev->dev_private = (void *)dev_priv;
468
 
469
        return 0;
470
}
471
 
472
#ifdef CONFIG_DRM_I810_XFREE_41
473
int xfreeversion = 41;
474
#else
475
int xfreeversion = -1;
476
#endif
477
 
478
MODULE_PARM(xfreeversion, "i");
479
MODULE_PARM_DESC(xfreeversion, "The version of XFree86 that needs to be supported");
480
 
481
int i810_dma_init(struct inode *inode, struct file *filp,
482
                  unsigned int cmd, unsigned long arg)
483
{
484
        drm_file_t *priv = filp->private_data;
485
        drm_device_t *dev = priv->dev;
486
        drm_i810_private_t *dev_priv;
487
        drm_i810_init_t init;
488
        int retcode = 0;
489
 
490
        if (copy_from_user(&init, (drm_i810_init_t *)arg, sizeof(init)))
491
                return -EFAULT;
492
 
493
        if ((xfreeversion == 41) ||
494
            ((xfreeversion == -1) && (init.pitch == 0))) {
495
                /*
496
                 * Ok we have a problem here.  Someone decided it was
497
                 * funny to add two fields in the middle of the
498
                 * drm_i810_init_it structure in the transition between
499
                 * XFree86 4.1.0 and 4.2.0.
500
                 *
501
                 * The code below tries to fix this ABI breakage up as
502
                 * good as possible, unfortionatly it's impossible to
503
                 * autodetect which interface the user wants, hence the
504
                 * module parameter -- Arjan
505
                 */
506
 
507
                init.pitch_bits = init.h;
508
                init.pitch = init.w;
509
                init.h = init.overlay_physical;
510
                init.w = init.overlay_offset;
511
                init.overlay_physical = 0;
512
                init.overlay_offset = 0;
513
        }
514
 
515
        switch(init.func) {
516
                case I810_INIT_DMA:
517
                        dev_priv = DRM(alloc)(sizeof(drm_i810_private_t),
518
                                             DRM_MEM_DRIVER);
519
                        if(dev_priv == NULL) return -ENOMEM;
520
                        retcode = i810_dma_initialize(dev, dev_priv, &init);
521
                break;
522
                case I810_CLEANUP_DMA:
523
                        retcode = i810_dma_cleanup(dev);
524
                break;
525
                default:
526
                        retcode = -EINVAL;
527
                break;
528
        }
529
 
530
        return retcode;
531
}
532
 
533
 
534
 
535
/* Most efficient way to verify state for the i810 is as it is
536
 * emitted.  Non-conformant state is silently dropped.
537
 */
538
static void i810EmitContextVerified( drm_device_t *dev,
539
                                     unsigned int *code )
540
{
541
        drm_i810_private_t *dev_priv = dev->dev_private;
542
        int i, j = 0;
543
        RING_LOCALS;
544
 
545
        BEGIN_LP_RING( I810_CTX_SETUP_SIZE );
546
 
547
        OUT_RING( GFX_OP_COLOR_FACTOR );
548
        OUT_RING( code[I810_CTXREG_CF1] );
549
 
550
        OUT_RING( GFX_OP_STIPPLE );
551
        OUT_RING( code[I810_CTXREG_ST1] );
552
 
553
        for ( i = 4 ; i < I810_CTX_SETUP_SIZE ; i++ ) {
554
                if ((code[i] & (7<<29)) == (3<<29) &&
555
                    (code[i] & (0x1f<<24)) < (0x1d<<24))
556
                {
557
                        OUT_RING( code[i] );
558
                        j++;
559
                }
560
                else printk("constext state dropped!!!\n");
561
        }
562
 
563
        if (j & 1)
564
                OUT_RING( 0 );
565
 
566
        ADVANCE_LP_RING();
567
}
568
 
569
static void i810EmitTexVerified( drm_device_t *dev,
570
                                 volatile unsigned int *code )
571
{
572
        drm_i810_private_t *dev_priv = dev->dev_private;
573
        int i, j = 0;
574
        RING_LOCALS;
575
 
576
        BEGIN_LP_RING( I810_TEX_SETUP_SIZE );
577
 
578
        OUT_RING( GFX_OP_MAP_INFO );
579
        OUT_RING( code[I810_TEXREG_MI1] );
580
        OUT_RING( code[I810_TEXREG_MI2] );
581
        OUT_RING( code[I810_TEXREG_MI3] );
582
 
583
        for ( i = 4 ; i < I810_TEX_SETUP_SIZE ; i++ ) {
584
 
585
                if ((code[i] & (7<<29)) == (3<<29) &&
586
                    (code[i] & (0x1f<<24)) < (0x1d<<24))
587
                {
588
                        OUT_RING( code[i] );
589
                        j++;
590
                }
591
                else printk("texture state dropped!!!\n");
592
        }
593
 
594
        if (j & 1)
595
                OUT_RING( 0 );
596
 
597
        ADVANCE_LP_RING();
598
}
599
 
600
 
601
/* Need to do some additional checking when setting the dest buffer.
602
 */
603
static void i810EmitDestVerified( drm_device_t *dev,
604
                                  volatile unsigned int *code )
605
{
606
        drm_i810_private_t *dev_priv = dev->dev_private;
607
        unsigned int tmp;
608
        RING_LOCALS;
609
 
610
        BEGIN_LP_RING( I810_DEST_SETUP_SIZE + 2 );
611
 
612
        tmp = code[I810_DESTREG_DI1];
613
        if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
614
                OUT_RING( CMD_OP_DESTBUFFER_INFO );
615
                OUT_RING( tmp );
616
        }
617
        else
618
           printk("buffer state dropped\n");
619
 
620
        /* invarient:
621
         */
622
        OUT_RING( CMD_OP_Z_BUFFER_INFO );
623
        OUT_RING( dev_priv->zi1 );
624
 
625
        OUT_RING( GFX_OP_DESTBUFFER_VARS );
626
        OUT_RING( code[I810_DESTREG_DV1] );
627
 
628
        OUT_RING( GFX_OP_DRAWRECT_INFO );
629
        OUT_RING( code[I810_DESTREG_DR1] );
630
        OUT_RING( code[I810_DESTREG_DR2] );
631
        OUT_RING( code[I810_DESTREG_DR3] );
632
        OUT_RING( code[I810_DESTREG_DR4] );
633
        OUT_RING( 0 );
634
 
635
        ADVANCE_LP_RING();
636
}
637
 
638
 
639
 
640
static void i810EmitState( drm_device_t *dev )
641
{
642
        drm_i810_private_t *dev_priv = dev->dev_private;
643
        drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
644
        unsigned int dirty = sarea_priv->dirty;
645
 
646
        if (dirty & I810_UPLOAD_BUFFERS) {
647
                i810EmitDestVerified( dev, sarea_priv->BufferState );
648
                sarea_priv->dirty &= ~I810_UPLOAD_BUFFERS;
649
        }
650
 
651
        if (dirty & I810_UPLOAD_CTX) {
652
                i810EmitContextVerified( dev, sarea_priv->ContextState );
653
                sarea_priv->dirty &= ~I810_UPLOAD_CTX;
654
        }
655
 
656
        if (dirty & I810_UPLOAD_TEX0) {
657
                i810EmitTexVerified( dev, sarea_priv->TexState[0] );
658
                sarea_priv->dirty &= ~I810_UPLOAD_TEX0;
659
        }
660
 
661
        if (dirty & I810_UPLOAD_TEX1) {
662
                i810EmitTexVerified( dev, sarea_priv->TexState[1] );
663
                sarea_priv->dirty &= ~I810_UPLOAD_TEX1;
664
        }
665
}
666
 
667
 
668
 
669
/* need to verify
670
 */
671
static void i810_dma_dispatch_clear( drm_device_t *dev, int flags,
672
                                     unsigned int clear_color,
673
                                     unsigned int clear_zval )
674
{
675
        drm_i810_private_t *dev_priv = dev->dev_private;
676
        drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
677
        int nbox = sarea_priv->nbox;
678
        drm_clip_rect_t *pbox = sarea_priv->boxes;
679
        int pitch = dev_priv->pitch;
680
        int cpp = 2;
681
        int i;
682
        RING_LOCALS;
683
 
684
        i810_kernel_lost_context(dev);
685
 
686
        if (nbox > I810_NR_SAREA_CLIPRECTS)
687
                nbox = I810_NR_SAREA_CLIPRECTS;
688
 
689
        for (i = 0 ; i < nbox ; i++, pbox++) {
690
                unsigned int x = pbox->x1;
691
                unsigned int y = pbox->y1;
692
                unsigned int width = (pbox->x2 - x) * cpp;
693
                unsigned int height = pbox->y2 - y;
694
                unsigned int start = y * pitch + x * cpp;
695
 
696
                if (pbox->x1 > pbox->x2 ||
697
                    pbox->y1 > pbox->y2 ||
698
                    pbox->x2 > dev_priv->w ||
699
                    pbox->y2 > dev_priv->h)
700
                        continue;
701
 
702
                if ( flags & I810_FRONT ) {
703
                        BEGIN_LP_RING( 6 );
704
                        OUT_RING( BR00_BITBLT_CLIENT |
705
                                  BR00_OP_COLOR_BLT | 0x3 );
706
                        OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
707
                        OUT_RING( (height << 16) | width );
708
                        OUT_RING( start );
709
                        OUT_RING( clear_color );
710
                        OUT_RING( 0 );
711
                        ADVANCE_LP_RING();
712
                }
713
 
714
                if ( flags & I810_BACK ) {
715
                        BEGIN_LP_RING( 6 );
716
                        OUT_RING( BR00_BITBLT_CLIENT |
717
                                  BR00_OP_COLOR_BLT | 0x3 );
718
                        OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
719
                        OUT_RING( (height << 16) | width );
720
                        OUT_RING( dev_priv->back_offset + start );
721
                        OUT_RING( clear_color );
722
                        OUT_RING( 0 );
723
                        ADVANCE_LP_RING();
724
                }
725
 
726
                if ( flags & I810_DEPTH ) {
727
                        BEGIN_LP_RING( 6 );
728
                        OUT_RING( BR00_BITBLT_CLIENT |
729
                                  BR00_OP_COLOR_BLT | 0x3 );
730
                        OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
731
                        OUT_RING( (height << 16) | width );
732
                        OUT_RING( dev_priv->depth_offset + start );
733
                        OUT_RING( clear_zval );
734
                        OUT_RING( 0 );
735
                        ADVANCE_LP_RING();
736
                }
737
        }
738
}
739
 
740
static void i810_dma_dispatch_swap( drm_device_t *dev )
741
{
742
        drm_i810_private_t *dev_priv = dev->dev_private;
743
        drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
744
        int nbox = sarea_priv->nbox;
745
        drm_clip_rect_t *pbox = sarea_priv->boxes;
746
        int pitch = dev_priv->pitch;
747
        int cpp = 2;
748
        int ofs = dev_priv->back_offset;
749
        int i;
750
        RING_LOCALS;
751
 
752
        i810_kernel_lost_context(dev);
753
 
754
        if (nbox > I810_NR_SAREA_CLIPRECTS)
755
                nbox = I810_NR_SAREA_CLIPRECTS;
756
 
757
        for (i = 0 ; i < nbox; i++, pbox++)
758
        {
759
                unsigned int w = pbox->x2 - pbox->x1;
760
                unsigned int h = pbox->y2 - pbox->y1;
761
                unsigned int dst = pbox->x1*cpp + pbox->y1*pitch;
762
                unsigned int start = ofs + dst;
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
                BEGIN_LP_RING( 6 );
771
                OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 );
772
                OUT_RING( pitch | (0xCC << 16));
773
                OUT_RING( (h << 16) | (w * cpp));
774
                OUT_RING( dst );
775
                OUT_RING( pitch );
776
                OUT_RING( start );
777
                ADVANCE_LP_RING();
778
        }
779
}
780
 
781
 
782
static void i810_dma_dispatch_vertex(drm_device_t *dev,
783
                                     drm_buf_t *buf,
784
                                     int discard,
785
                                     int used)
786
{
787
        drm_i810_private_t *dev_priv = dev->dev_private;
788
        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
789
        drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
790
        drm_clip_rect_t *box = sarea_priv->boxes;
791
        int nbox = sarea_priv->nbox;
792
        unsigned long address = (unsigned long)buf->bus_address;
793
        unsigned long start = address - dev->agp->base;
794
        int i = 0;
795
        RING_LOCALS;
796
 
797
        i810_kernel_lost_context(dev);
798
 
799
        if (nbox > I810_NR_SAREA_CLIPRECTS)
800
                nbox = I810_NR_SAREA_CLIPRECTS;
801
 
802
        if (used > 4*1024)
803
                used = 0;
804
 
805
        if (sarea_priv->dirty)
806
           i810EmitState( dev );
807
 
808
        if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
809
                unsigned int prim = (sarea_priv->vertex_prim & PR_MASK);
810
 
811
                *(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE | prim |
812
                                             ((used/4)-2));
813
 
814
                if (used & 4) {
815
                        *(u32 *)((u32)buf_priv->virtual + used) = 0;
816
                        used += 4;
817
                }
818
 
819
                i810_unmap_buffer(buf);
820
        }
821
 
822
        if (used) {
823
                do {
824
                        if (i < nbox) {
825
                                BEGIN_LP_RING(4);
826
                                OUT_RING( GFX_OP_SCISSOR | SC_UPDATE_SCISSOR |
827
                                          SC_ENABLE );
828
                                OUT_RING( GFX_OP_SCISSOR_INFO );
829
                                OUT_RING( box[i].x1 | (box[i].y1<<16) );
830
                                OUT_RING( (box[i].x2-1) | ((box[i].y2-1)<<16) );
831
                                ADVANCE_LP_RING();
832
                        }
833
 
834
                        BEGIN_LP_RING(4);
835
                        OUT_RING( CMD_OP_BATCH_BUFFER );
836
                        OUT_RING( start | BB1_PROTECTED );
837
                        OUT_RING( start + used - 4 );
838
                        OUT_RING( 0 );
839
                        ADVANCE_LP_RING();
840
 
841
                } while (++i < nbox);
842
        }
843
 
844
        if (discard) {
845
                dev_priv->counter++;
846
 
847
                (void) cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
848
                               I810_BUF_HARDWARE);
849
 
850
                BEGIN_LP_RING(8);
851
                OUT_RING( CMD_STORE_DWORD_IDX );
852
                OUT_RING( 20 );
853
                OUT_RING( dev_priv->counter );
854
                OUT_RING( CMD_STORE_DWORD_IDX );
855
                OUT_RING( buf_priv->my_use_idx );
856
                OUT_RING( I810_BUF_FREE );
857
                OUT_RING( CMD_REPORT_HEAD );
858
                OUT_RING( 0 );
859
                ADVANCE_LP_RING();
860
        }
861
}
862
 
863
 
864
void i810_dma_quiescent(drm_device_t *dev)
865
{
866
        drm_i810_private_t *dev_priv = dev->dev_private;
867
        RING_LOCALS;
868
 
869
/*      printk("%s\n", __FUNCTION__); */
870
 
871
        i810_kernel_lost_context(dev);
872
 
873
        BEGIN_LP_RING(4);
874
        OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
875
        OUT_RING( CMD_REPORT_HEAD );
876
        OUT_RING( 0 );
877
        OUT_RING( 0 );
878
        ADVANCE_LP_RING();
879
 
880
        i810_wait_ring( dev, dev_priv->ring.Size - 8 );
881
}
882
 
883
static int i810_flush_queue(drm_device_t *dev)
884
{
885
        drm_i810_private_t *dev_priv = dev->dev_private;
886
        drm_device_dma_t *dma = dev->dma;
887
        int i, ret = 0;
888
        RING_LOCALS;
889
 
890
/*      printk("%s\n", __FUNCTION__); */
891
 
892
        i810_kernel_lost_context(dev);
893
 
894
        BEGIN_LP_RING(2);
895
        OUT_RING( CMD_REPORT_HEAD );
896
        OUT_RING( 0 );
897
        ADVANCE_LP_RING();
898
 
899
        i810_wait_ring( dev, dev_priv->ring.Size - 8 );
900
 
901
        for (i = 0; i < dma->buf_count; i++) {
902
                drm_buf_t *buf = dma->buflist[ i ];
903
                drm_i810_buf_priv_t *buf_priv = buf->dev_private;
904
 
905
                int used = cmpxchg(buf_priv->in_use, I810_BUF_HARDWARE,
906
                                   I810_BUF_FREE);
907
 
908
                if (used == I810_BUF_HARDWARE)
909
                        DRM_DEBUG("reclaimed from HARDWARE\n");
910
                if (used == I810_BUF_CLIENT)
911
                        DRM_DEBUG("still on client\n");
912
        }
913
 
914
        return ret;
915
}
916
 
917
/* Must be called with the lock held */
918
void i810_reclaim_buffers(drm_device_t *dev, pid_t pid)
919
{
920
        drm_device_dma_t *dma = dev->dma;
921
        int              i;
922
 
923
        if (!dma) return;
924
        if (!dev->dev_private) return;
925
        if (!dma->buflist) return;
926
 
927
        i810_flush_queue(dev);
928
 
929
        for (i = 0; i < dma->buf_count; i++) {
930
                drm_buf_t *buf = dma->buflist[ i ];
931
                drm_i810_buf_priv_t *buf_priv = buf->dev_private;
932
 
933
                if (buf->pid == pid && buf_priv) {
934
                        int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
935
                                           I810_BUF_FREE);
936
 
937
                        if (used == I810_BUF_CLIENT)
938
                                DRM_DEBUG("reclaimed from client\n");
939
                        if(buf_priv->currently_mapped == I810_BUF_MAPPED)
940
                                buf_priv->currently_mapped = I810_BUF_UNMAPPED;
941
                }
942
        }
943
}
944
 
945
int i810_flush_ioctl(struct inode *inode, struct file *filp,
946
                     unsigned int cmd, unsigned long arg)
947
{
948
        drm_file_t        *priv   = filp->private_data;
949
        drm_device_t      *dev    = priv->dev;
950
 
951
        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
952
                DRM_ERROR("i810_flush_ioctl called without lock held\n");
953
                return -EINVAL;
954
        }
955
 
956
        i810_flush_queue(dev);
957
        return 0;
958
}
959
 
960
 
961
int i810_dma_vertex(struct inode *inode, struct file *filp,
962
               unsigned int cmd, unsigned long arg)
963
{
964
        drm_file_t *priv = filp->private_data;
965
        drm_device_t *dev = priv->dev;
966
        drm_device_dma_t *dma = dev->dma;
967
        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
968
        u32 *hw_status = (u32 *)dev_priv->hw_status_page;
969
        drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
970
                                        dev_priv->sarea_priv;
971
        drm_i810_vertex_t vertex;
972
 
973
        if (copy_from_user(&vertex, (drm_i810_vertex_t *)arg, sizeof(vertex)))
974
                return -EFAULT;
975
 
976
        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
977
                DRM_ERROR("i810_dma_vertex called without lock held\n");
978
                return -EINVAL;
979
        }
980
 
981
        if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL;
982
 
983
        i810_dma_dispatch_vertex( dev,
984
                                  dma->buflist[ vertex.idx ],
985
                                  vertex.discard, vertex.used );
986
 
987
        atomic_add(vertex.used, &dev->counts[_DRM_STAT_SECONDARY]);
988
        atomic_inc(&dev->counts[_DRM_STAT_DMA]);
989
        sarea_priv->last_enqueue = dev_priv->counter-1;
990
        sarea_priv->last_dispatch = (int) hw_status[5];
991
 
992
        return 0;
993
}
994
 
995
 
996
 
997
int i810_clear_bufs(struct inode *inode, struct file *filp,
998
                   unsigned int cmd, unsigned long arg)
999
{
1000
        drm_file_t *priv = filp->private_data;
1001
        drm_device_t *dev = priv->dev;
1002
        drm_i810_clear_t clear;
1003
 
1004
        if (copy_from_user(&clear, (drm_i810_clear_t *)arg, sizeof(clear)))
1005
                return -EFAULT;
1006
 
1007
        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1008
                DRM_ERROR("i810_clear_bufs called without lock held\n");
1009
                return -EINVAL;
1010
        }
1011
 
1012
        /* GH: Someone's doing nasty things... */
1013
        if (!dev->dev_private) {
1014
                return -EINVAL;
1015
        }
1016
 
1017
        i810_dma_dispatch_clear( dev, clear.flags,
1018
                                 clear.clear_color,
1019
                                 clear.clear_depth );
1020
        return 0;
1021
}
1022
 
1023
int i810_swap_bufs(struct inode *inode, struct file *filp,
1024
                  unsigned int cmd, unsigned long arg)
1025
{
1026
        drm_file_t *priv = filp->private_data;
1027
        drm_device_t *dev = priv->dev;
1028
 
1029
        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1030
                DRM_ERROR("i810_swap_buf called without lock held\n");
1031
                return -EINVAL;
1032
        }
1033
 
1034
        i810_dma_dispatch_swap( dev );
1035
        return 0;
1036
}
1037
 
1038
int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
1039
                unsigned long arg)
1040
{
1041
        drm_file_t        *priv     = filp->private_data;
1042
        drm_device_t      *dev      = priv->dev;
1043
        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1044
        u32 *hw_status = (u32 *)dev_priv->hw_status_page;
1045
        drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
1046
                                        dev_priv->sarea_priv;
1047
 
1048
        sarea_priv->last_dispatch = (int) hw_status[5];
1049
        return 0;
1050
}
1051
 
1052
int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
1053
                unsigned long arg)
1054
{
1055
        drm_file_t        *priv     = filp->private_data;
1056
        drm_device_t      *dev      = priv->dev;
1057
        int               retcode   = 0;
1058
        drm_i810_dma_t    d;
1059
        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1060
        u32 *hw_status = (u32 *)dev_priv->hw_status_page;
1061
        drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
1062
                                        dev_priv->sarea_priv;
1063
 
1064
        if (copy_from_user(&d, (drm_i810_dma_t *)arg, sizeof(d)))
1065
                return -EFAULT;
1066
 
1067
        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1068
                DRM_ERROR("i810_dma called without lock held\n");
1069
                return -EINVAL;
1070
        }
1071
 
1072
        d.granted = 0;
1073
 
1074
        retcode = i810_dma_get_buffer(dev, &d, filp);
1075
 
1076
        if (copy_to_user((drm_dma_t *)arg, &d, sizeof(d)))
1077
                return -EFAULT;
1078
        sarea_priv->last_dispatch = (int) hw_status[5];
1079
 
1080
        return retcode;
1081
}
1082
 
1083
int i810_copybuf(struct inode *inode,
1084
                 struct file *filp,
1085
                 unsigned int cmd,
1086
                 unsigned long arg)
1087
{
1088
        /* Never copy - 2.4.x doesn't need it */
1089
        return 0;
1090
}
1091
 
1092
int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
1093
                unsigned long arg)
1094
{
1095
        /* Never copy - 2.4.x doesn't need it */
1096
        return 0;
1097
}
1098
 
1099
static void i810_dma_dispatch_mc(drm_device_t *dev, drm_buf_t *buf, int used,
1100
                unsigned int last_render)
1101
{
1102
        drm_i810_private_t *dev_priv = dev->dev_private;
1103
        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
1104
        drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
1105
        unsigned long address = (unsigned long)buf->bus_address;
1106
        unsigned long start = address - dev->agp->base;
1107
        int u;
1108
        RING_LOCALS;
1109
 
1110
        i810_kernel_lost_context(dev);
1111
 
1112
        u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
1113
                I810_BUF_HARDWARE);
1114
        if(u != I810_BUF_CLIENT) {
1115
                DRM_DEBUG("MC found buffer that isn't mine!\n");
1116
        }
1117
 
1118
        if (used > 4*1024)
1119
                used = 0;
1120
 
1121
        sarea_priv->dirty = 0x7f;
1122
 
1123
        DRM_DEBUG("dispatch mc addr 0x%lx, used 0x%x\n",
1124
                address, used);
1125
 
1126
        dev_priv->counter++;
1127
        DRM_DEBUG("dispatch counter : %ld\n", dev_priv->counter);
1128
        DRM_DEBUG("i810_dma_dispatch_mc\n");
1129
        DRM_DEBUG("start : %lx\n", start);
1130
        DRM_DEBUG("used : %d\n", used);
1131
        DRM_DEBUG("start + used - 4 : %ld\n", start + used - 4);
1132
 
1133
        if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
1134
                if (used & 4) {
1135
                        *(u32 *)((u32)buf_priv->virtual + used) = 0;
1136
                        used += 4;
1137
                }
1138
 
1139
                i810_unmap_buffer(buf);
1140
        }
1141
        BEGIN_LP_RING(4);
1142
        OUT_RING( CMD_OP_BATCH_BUFFER );
1143
        OUT_RING( start | BB1_PROTECTED );
1144
        OUT_RING( start + used - 4 );
1145
        OUT_RING( 0 );
1146
        ADVANCE_LP_RING();
1147
 
1148
 
1149
        BEGIN_LP_RING(8);
1150
        OUT_RING( CMD_STORE_DWORD_IDX );
1151
        OUT_RING( buf_priv->my_use_idx );
1152
        OUT_RING( I810_BUF_FREE );
1153
        OUT_RING( 0 );
1154
 
1155
        OUT_RING( CMD_STORE_DWORD_IDX );
1156
        OUT_RING( 16 );
1157
        OUT_RING( last_render );
1158
        OUT_RING( 0 );
1159
        ADVANCE_LP_RING();
1160
}
1161
 
1162
int i810_dma_mc(struct inode *inode, struct file *filp,
1163
        unsigned int cmd, unsigned long arg)
1164
{
1165
        drm_file_t *priv = filp->private_data;
1166
        drm_device_t *dev = priv->dev;
1167
        drm_device_dma_t *dma = dev->dma;
1168
        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1169
        u32 *hw_status = (u32 *)dev_priv->hw_status_page;
1170
        drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
1171
                dev_priv->sarea_priv;
1172
        drm_i810_mc_t mc;
1173
 
1174
        if (copy_from_user(&mc, (drm_i810_mc_t *)arg, sizeof(mc)))
1175
                return -EFAULT;
1176
 
1177
 
1178
        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1179
                DRM_ERROR("i810_dma_mc called without lock held\n");
1180
                return -EINVAL;
1181
        }
1182
 
1183
        i810_dma_dispatch_mc(dev, dma->buflist[mc.idx], mc.used,
1184
                mc.last_render );
1185
 
1186
        atomic_add(mc.used, &dev->counts[_DRM_STAT_SECONDARY]);
1187
        atomic_inc(&dev->counts[_DRM_STAT_DMA]);
1188
        sarea_priv->last_enqueue = dev_priv->counter-1;
1189
        sarea_priv->last_dispatch = (int) hw_status[5];
1190
 
1191
        return 0;
1192
}
1193
 
1194
int i810_rstatus(struct inode *inode, struct file *filp,
1195
                unsigned int cmd, unsigned long arg)
1196
{
1197
        drm_file_t *priv = filp->private_data;
1198
        drm_device_t *dev = priv->dev;
1199
        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1200
 
1201
        return (int)(((u32 *)(dev_priv->hw_status_page))[4]);
1202
}
1203
 
1204
int i810_ov0_info(struct inode *inode, struct file *filp,
1205
                unsigned int cmd, unsigned long arg)
1206
{
1207
        drm_file_t *priv = filp->private_data;
1208
        drm_device_t *dev = priv->dev;
1209
        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1210
        drm_i810_overlay_t data;
1211
 
1212
        data.offset = dev_priv->overlay_offset;
1213
        data.physical = dev_priv->overlay_physical;
1214
        if (copy_to_user((drm_i810_overlay_t *)arg,&data,sizeof(data)))
1215
                return -EFAULT;
1216
        return 0;
1217
}
1218
 
1219
int i810_fstatus(struct inode *inode, struct file *filp,
1220
                unsigned int cmd, unsigned long arg)
1221
{
1222
        drm_file_t *priv = filp->private_data;
1223
        drm_device_t *dev = priv->dev;
1224
        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1225
 
1226
        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1227
                DRM_ERROR("i810_fstatus called without lock held\n");
1228
                return -EINVAL;
1229
        }
1230
        return I810_READ(0x30008);
1231
}
1232
 
1233
int i810_ov0_flip(struct inode *inode, struct file *filp,
1234
                unsigned int cmd, unsigned long arg)
1235
{
1236
        drm_file_t *priv = filp->private_data;
1237
        drm_device_t *dev = priv->dev;
1238
        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1239
 
1240
        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1241
                DRM_ERROR("i810_ov0_flip called without lock held\n");
1242
                return -EINVAL;
1243
        }
1244
 
1245
        //Tell the overlay to update
1246
        I810_WRITE(0x30000,dev_priv->overlay_physical | 0x80000000);
1247
 
1248
        return 0;
1249
}
1250
 
1251
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.