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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* drm_dma.c -- DMA IOCTL and function support -*- linux-c -*-
2
 * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
3
 *
4
 * Copyright 1999, 2000 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
 * VA LINUX SYSTEMS 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
25
 * OTHER DEALINGS IN THE SOFTWARE.
26
 *
27
 * Authors:
28
 *    Rickard E. (Rik) Faith <faith@valinux.com>
29
 *    Gareth Hughes <gareth@valinux.com>
30
 */
31
 
32
#include "drmP.h"
33
#include "drm_os_linux.h"
34
#include <linux/interrupt.h>    /* For task queue support */
35
 
36
#ifndef __HAVE_DMA_WAITQUEUE
37
#define __HAVE_DMA_WAITQUEUE    0
38
#endif
39
#ifndef __HAVE_DMA_RECLAIM
40
#define __HAVE_DMA_RECLAIM      0
41
#endif
42
#ifndef __HAVE_SHARED_IRQ
43
#define __HAVE_SHARED_IRQ       0
44
#endif
45
 
46
#if __HAVE_SHARED_IRQ
47
#define DRM_IRQ_TYPE            SA_SHIRQ
48
#else
49
#define DRM_IRQ_TYPE            0
50
#endif
51
 
52
#if __HAVE_DMA
53
 
54
int DRM(dma_setup)( drm_device_t *dev )
55
{
56
        int i;
57
 
58
        dev->dma = DRM(alloc)( sizeof(*dev->dma), DRM_MEM_DRIVER );
59
        if ( !dev->dma )
60
                return -ENOMEM;
61
 
62
        memset( dev->dma, 0, sizeof(*dev->dma) );
63
 
64
        for ( i = 0 ; i <= DRM_MAX_ORDER ; i++ )
65
                memset(&dev->dma->bufs[i], 0, sizeof(dev->dma->bufs[0]));
66
 
67
        return 0;
68
}
69
 
70
void DRM(dma_takedown)(drm_device_t *dev)
71
{
72
        drm_device_dma_t  *dma = dev->dma;
73
        int               i, j;
74
 
75
        if (!dma) return;
76
 
77
                                /* Clear dma buffers */
78
        for (i = 0; i <= DRM_MAX_ORDER; i++) {
79
                if (dma->bufs[i].seg_count) {
80
                        DRM_DEBUG("order %d: buf_count = %d,"
81
                                  " seg_count = %d\n",
82
                                  i,
83
                                  dma->bufs[i].buf_count,
84
                                  dma->bufs[i].seg_count);
85
                        for (j = 0; j < dma->bufs[i].seg_count; j++) {
86
                                DRM(free_pages)(dma->bufs[i].seglist[j],
87
                                                dma->bufs[i].page_order,
88
                                                DRM_MEM_DMA);
89
                        }
90
                        DRM(free)(dma->bufs[i].seglist,
91
                                  dma->bufs[i].seg_count
92
                                  * sizeof(*dma->bufs[0].seglist),
93
                                  DRM_MEM_SEGS);
94
                }
95
                if(dma->bufs[i].buf_count) {
96
                        for(j = 0; j < dma->bufs[i].buf_count; j++) {
97
                           if(dma->bufs[i].buflist[j].dev_private) {
98
                              DRM(free)(dma->bufs[i].buflist[j].dev_private,
99
                                        dma->bufs[i].buflist[j].dev_priv_size,
100
                                        DRM_MEM_BUFS);
101
                           }
102
                        }
103
                        DRM(free)(dma->bufs[i].buflist,
104
                                  dma->bufs[i].buf_count *
105
                                  sizeof(*dma->bufs[0].buflist),
106
                                  DRM_MEM_BUFS);
107
#if __HAVE_DMA_FREELIST
108
                        DRM(freelist_destroy)(&dma->bufs[i].freelist);
109
#endif
110
                }
111
        }
112
 
113
        if (dma->buflist) {
114
                DRM(free)(dma->buflist,
115
                          dma->buf_count * sizeof(*dma->buflist),
116
                          DRM_MEM_BUFS);
117
        }
118
 
119
        if (dma->pagelist) {
120
                DRM(free)(dma->pagelist,
121
                          dma->page_count * sizeof(*dma->pagelist),
122
                          DRM_MEM_PAGES);
123
        }
124
        DRM(free)(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER);
125
        dev->dma = NULL;
126
}
127
 
128
 
129
#if __HAVE_DMA_HISTOGRAM
130
/* This is slow, but is useful for debugging. */
131
int DRM(histogram_slot)(unsigned long count)
132
{
133
        int value = DRM_DMA_HISTOGRAM_INITIAL;
134
        int slot;
135
 
136
        for (slot = 0;
137
             slot < DRM_DMA_HISTOGRAM_SLOTS;
138
             ++slot, value = DRM_DMA_HISTOGRAM_NEXT(value)) {
139
                if (count < value) return slot;
140
        }
141
        return DRM_DMA_HISTOGRAM_SLOTS - 1;
142
}
143
 
144
void DRM(histogram_compute)(drm_device_t *dev, drm_buf_t *buf)
145
{
146
        cycles_t queued_to_dispatched;
147
        cycles_t dispatched_to_completed;
148
        cycles_t completed_to_freed;
149
        int      q2d, d2c, c2f, q2c, q2f;
150
 
151
        if (buf->time_queued) {
152
                queued_to_dispatched    = (buf->time_dispatched
153
                                           - buf->time_queued);
154
                dispatched_to_completed = (buf->time_completed
155
                                           - buf->time_dispatched);
156
                completed_to_freed      = (buf->time_freed
157
                                           - buf->time_completed);
158
 
159
                q2d = DRM(histogram_slot)(queued_to_dispatched);
160
                d2c = DRM(histogram_slot)(dispatched_to_completed);
161
                c2f = DRM(histogram_slot)(completed_to_freed);
162
 
163
                q2c = DRM(histogram_slot)(queued_to_dispatched
164
                                          + dispatched_to_completed);
165
                q2f = DRM(histogram_slot)(queued_to_dispatched
166
                                          + dispatched_to_completed
167
                                          + completed_to_freed);
168
 
169
                atomic_inc(&dev->histo.total);
170
                atomic_inc(&dev->histo.queued_to_dispatched[q2d]);
171
                atomic_inc(&dev->histo.dispatched_to_completed[d2c]);
172
                atomic_inc(&dev->histo.completed_to_freed[c2f]);
173
 
174
                atomic_inc(&dev->histo.queued_to_completed[q2c]);
175
                atomic_inc(&dev->histo.queued_to_freed[q2f]);
176
 
177
        }
178
        buf->time_queued     = 0;
179
        buf->time_dispatched = 0;
180
        buf->time_completed  = 0;
181
        buf->time_freed      = 0;
182
}
183
#endif
184
 
185
void DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf)
186
{
187
        if (!buf) return;
188
 
189
        buf->waiting  = 0;
190
        buf->pending  = 0;
191
        buf->pid      = 0;
192
        buf->used     = 0;
193
#if __HAVE_DMA_HISTOGRAM
194
        buf->time_completed = get_cycles();
195
#endif
196
 
197
        if ( __HAVE_DMA_WAITQUEUE && waitqueue_active(&buf->dma_wait)) {
198
                wake_up_interruptible(&buf->dma_wait);
199
        }
200
#if __HAVE_DMA_FREELIST
201
        else {
202
                drm_device_dma_t *dma = dev->dma;
203
                                /* If processes are waiting, the last one
204
                                   to wake will put the buffer on the free
205
                                   list.  If no processes are waiting, we
206
                                   put the buffer on the freelist here. */
207
                DRM(freelist_put)(dev, &dma->bufs[buf->order].freelist, buf);
208
        }
209
#endif
210
}
211
 
212
#if !__HAVE_DMA_RECLAIM
213
void DRM(reclaim_buffers)(drm_device_t *dev, pid_t pid)
214
{
215
        drm_device_dma_t *dma = dev->dma;
216
        int              i;
217
 
218
        if (!dma) return;
219
        for (i = 0; i < dma->buf_count; i++) {
220
                if (dma->buflist[i]->pid == pid) {
221
                        switch (dma->buflist[i]->list) {
222
                        case DRM_LIST_NONE:
223
                                DRM(free_buffer)(dev, dma->buflist[i]);
224
                                break;
225
                        case DRM_LIST_WAIT:
226
                                dma->buflist[i]->list = DRM_LIST_RECLAIM;
227
                                break;
228
                        default:
229
                                /* Buffer already on hardware. */
230
                                break;
231
                        }
232
                }
233
        }
234
}
235
#endif
236
 
237
 
238
/* GH: This is a big hack for now...
239
 */
240
#if __HAVE_OLD_DMA
241
 
242
void DRM(clear_next_buffer)(drm_device_t *dev)
243
{
244
        drm_device_dma_t *dma = dev->dma;
245
 
246
        dma->next_buffer = NULL;
247
        if (dma->next_queue && !DRM_BUFCOUNT(&dma->next_queue->waitlist)) {
248
                wake_up_interruptible(&dma->next_queue->flush_queue);
249
        }
250
        dma->next_queue  = NULL;
251
}
252
 
253
int DRM(select_queue)(drm_device_t *dev, void (*wrapper)(unsigned long))
254
{
255
        int        i;
256
        int        candidate = -1;
257
        int        j         = jiffies;
258
 
259
        if (!dev) {
260
                DRM_ERROR("No device\n");
261
                return -1;
262
        }
263
        if (!dev->queuelist || !dev->queuelist[DRM_KERNEL_CONTEXT]) {
264
                                /* This only happens between the time the
265
                                   interrupt is initialized and the time
266
                                   the queues are initialized. */
267
                return -1;
268
        }
269
 
270
                                /* Doing "while locked" DMA? */
271
        if (DRM_WAITCOUNT(dev, DRM_KERNEL_CONTEXT)) {
272
                return DRM_KERNEL_CONTEXT;
273
        }
274
 
275
                                /* If there are buffers on the last_context
276
                                   queue, and we have not been executing
277
                                   this context very long, continue to
278
                                   execute this context. */
279
        if (dev->last_switch <= j
280
            && dev->last_switch + DRM_TIME_SLICE > j
281
            && DRM_WAITCOUNT(dev, dev->last_context)) {
282
                return dev->last_context;
283
        }
284
 
285
                                /* Otherwise, find a candidate */
286
        for (i = dev->last_checked + 1; i < dev->queue_count; i++) {
287
                if (DRM_WAITCOUNT(dev, i)) {
288
                        candidate = dev->last_checked = i;
289
                        break;
290
                }
291
        }
292
 
293
        if (candidate < 0) {
294
                for (i = 0; i < dev->queue_count; i++) {
295
                        if (DRM_WAITCOUNT(dev, i)) {
296
                                candidate = dev->last_checked = i;
297
                                break;
298
                        }
299
                }
300
        }
301
 
302
        if (wrapper
303
            && candidate >= 0
304
            && candidate != dev->last_context
305
            && dev->last_switch <= j
306
            && dev->last_switch + DRM_TIME_SLICE > j) {
307
                if (dev->timer.expires != dev->last_switch + DRM_TIME_SLICE) {
308
                        del_timer(&dev->timer);
309
                        dev->timer.function = wrapper;
310
                        dev->timer.data     = (unsigned long)dev;
311
                        dev->timer.expires  = dev->last_switch+DRM_TIME_SLICE;
312
                        add_timer(&dev->timer);
313
                }
314
                return -1;
315
        }
316
 
317
        return candidate;
318
}
319
 
320
 
321
int DRM(dma_enqueue)(drm_device_t *dev, drm_dma_t *d)
322
{
323
        int               i;
324
        drm_queue_t       *q;
325
        drm_buf_t         *buf;
326
        int               idx;
327
        int               while_locked = 0;
328
        drm_device_dma_t  *dma = dev->dma;
329
        DECLARE_WAITQUEUE(entry, current);
330
 
331
        DRM_DEBUG("%d\n", d->send_count);
332
 
333
        if (d->flags & _DRM_DMA_WHILE_LOCKED) {
334
                int context = dev->lock.hw_lock->lock;
335
 
336
                if (!_DRM_LOCK_IS_HELD(context)) {
337
                        DRM_ERROR("No lock held during \"while locked\""
338
                                  " request\n");
339
                        return -EINVAL;
340
                }
341
                if (d->context != _DRM_LOCKING_CONTEXT(context)
342
                    && _DRM_LOCKING_CONTEXT(context) != DRM_KERNEL_CONTEXT) {
343
                        DRM_ERROR("Lock held by %d while %d makes"
344
                                  " \"while locked\" request\n",
345
                                  _DRM_LOCKING_CONTEXT(context),
346
                                  d->context);
347
                        return -EINVAL;
348
                }
349
                q = dev->queuelist[DRM_KERNEL_CONTEXT];
350
                while_locked = 1;
351
        } else {
352
                q = dev->queuelist[d->context];
353
        }
354
 
355
 
356
        atomic_inc(&q->use_count);
357
        if (atomic_read(&q->block_write)) {
358
                add_wait_queue(&q->write_queue, &entry);
359
                atomic_inc(&q->block_count);
360
                for (;;) {
361
                        current->state = TASK_INTERRUPTIBLE;
362
                        if (!atomic_read(&q->block_write)) break;
363
                        schedule();
364
                        if (signal_pending(current)) {
365
                                atomic_dec(&q->use_count);
366
                                remove_wait_queue(&q->write_queue, &entry);
367
                                return -EINTR;
368
                        }
369
                }
370
                atomic_dec(&q->block_count);
371
                current->state = TASK_RUNNING;
372
                remove_wait_queue(&q->write_queue, &entry);
373
        }
374
 
375
        for (i = 0; i < d->send_count; i++) {
376
                idx = d->send_indices[i];
377
                if (idx < 0 || idx >= dma->buf_count) {
378
                        atomic_dec(&q->use_count);
379
                        DRM_ERROR("Index %d (of %d max)\n",
380
                                  d->send_indices[i], dma->buf_count - 1);
381
                        return -EINVAL;
382
                }
383
                buf = dma->buflist[ idx ];
384
                if (buf->pid != current->pid) {
385
                        atomic_dec(&q->use_count);
386
                        DRM_ERROR("Process %d using buffer owned by %d\n",
387
                                  current->pid, buf->pid);
388
                        return -EINVAL;
389
                }
390
                if (buf->list != DRM_LIST_NONE) {
391
                        atomic_dec(&q->use_count);
392
                        DRM_ERROR("Process %d using buffer %d on list %d\n",
393
                                  current->pid, buf->idx, buf->list);
394
                }
395
                buf->used         = d->send_sizes[i];
396
                buf->while_locked = while_locked;
397
                buf->context      = d->context;
398
                if (!buf->used) {
399
                        DRM_ERROR("Queueing 0 length buffer\n");
400
                }
401
                if (buf->pending) {
402
                        atomic_dec(&q->use_count);
403
                        DRM_ERROR("Queueing pending buffer:"
404
                                  " buffer %d, offset %d\n",
405
                                  d->send_indices[i], i);
406
                        return -EINVAL;
407
                }
408
                if (buf->waiting) {
409
                        atomic_dec(&q->use_count);
410
                        DRM_ERROR("Queueing waiting buffer:"
411
                                  " buffer %d, offset %d\n",
412
                                  d->send_indices[i], i);
413
                        return -EINVAL;
414
                }
415
                buf->waiting = 1;
416
                if (atomic_read(&q->use_count) == 1
417
                    || atomic_read(&q->finalization)) {
418
                        DRM(free_buffer)(dev, buf);
419
                } else {
420
                        DRM(waitlist_put)(&q->waitlist, buf);
421
                        atomic_inc(&q->total_queued);
422
                }
423
        }
424
        atomic_dec(&q->use_count);
425
 
426
        return 0;
427
}
428
 
429
static int DRM(dma_get_buffers_of_order)(drm_device_t *dev, drm_dma_t *d,
430
                                         int order)
431
{
432
        int               i;
433
        drm_buf_t         *buf;
434
        drm_device_dma_t  *dma = dev->dma;
435
 
436
        for (i = d->granted_count; i < d->request_count; i++) {
437
                buf = DRM(freelist_get)(&dma->bufs[order].freelist,
438
                                        d->flags & _DRM_DMA_WAIT);
439
                if (!buf) break;
440
                if (buf->pending || buf->waiting) {
441
                        DRM_ERROR("Free buffer %d in use by %d (w%d, p%d)\n",
442
                                  buf->idx,
443
                                  buf->pid,
444
                                  buf->waiting,
445
                                  buf->pending);
446
                }
447
                buf->pid     = current->pid;
448
                if (copy_to_user(&d->request_indices[i],
449
                                 &buf->idx,
450
                                 sizeof(buf->idx)))
451
                        return -EFAULT;
452
 
453
                if (copy_to_user(&d->request_sizes[i],
454
                                 &buf->total,
455
                                 sizeof(buf->total)))
456
                        return -EFAULT;
457
 
458
                ++d->granted_count;
459
        }
460
        return 0;
461
}
462
 
463
 
464
int DRM(dma_get_buffers)(drm_device_t *dev, drm_dma_t *dma)
465
{
466
        int               order;
467
        int               retcode = 0;
468
        int               tmp_order;
469
 
470
        order = DRM(order)(dma->request_size);
471
 
472
        dma->granted_count = 0;
473
        retcode            = DRM(dma_get_buffers_of_order)(dev, dma, order);
474
 
475
        if (dma->granted_count < dma->request_count
476
            && (dma->flags & _DRM_DMA_SMALLER_OK)) {
477
                for (tmp_order = order - 1;
478
                     !retcode
479
                             && dma->granted_count < dma->request_count
480
                             && tmp_order >= DRM_MIN_ORDER;
481
                     --tmp_order) {
482
 
483
                        retcode = DRM(dma_get_buffers_of_order)(dev, dma,
484
                                                                tmp_order);
485
                }
486
        }
487
 
488
        if (dma->granted_count < dma->request_count
489
            && (dma->flags & _DRM_DMA_LARGER_OK)) {
490
                for (tmp_order = order + 1;
491
                     !retcode
492
                             && dma->granted_count < dma->request_count
493
                             && tmp_order <= DRM_MAX_ORDER;
494
                     ++tmp_order) {
495
 
496
                        retcode = DRM(dma_get_buffers_of_order)(dev, dma,
497
                                                                tmp_order);
498
                }
499
        }
500
        return 0;
501
}
502
 
503
#endif /* __HAVE_OLD_DMA */
504
 
505
 
506
#if __HAVE_DMA_IRQ
507
 
508
int DRM(irq_install)( drm_device_t *dev, int irq )
509
{
510
        int ret;
511
 
512
        if ( !irq )
513
                return -EINVAL;
514
 
515
        down( &dev->struct_sem );
516
        if ( dev->irq ) {
517
                up( &dev->struct_sem );
518
                return -EBUSY;
519
        }
520
        dev->irq = irq;
521
        up( &dev->struct_sem );
522
 
523
        DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
524
 
525
        dev->context_flag = 0;
526
        dev->interrupt_flag = 0;
527
        dev->dma_flag = 0;
528
 
529
        dev->dma->next_buffer = NULL;
530
        dev->dma->next_queue = NULL;
531
        dev->dma->this_buffer = NULL;
532
 
533
#if __HAVE_DMA_IRQ_BH
534
        INIT_LIST_HEAD( &dev->tq.list );
535
        dev->tq.sync = 0;
536
        dev->tq.routine = DRM(dma_immediate_bh);
537
        dev->tq.data = dev;
538
#endif
539
 
540
#if __HAVE_VBL_IRQ
541
        init_waitqueue_head(&dev->vbl_queue);
542
 
543
        spin_lock_init( &dev->vbl_lock );
544
 
545
        INIT_LIST_HEAD( &dev->vbl_sigs.head );
546
 
547
        dev->vbl_pending = 0;
548
#endif
549
 
550
                                /* Before installing handler */
551
        DRM(driver_irq_preinstall)(dev);
552
 
553
                                /* Install handler */
554
        ret = request_irq( dev->irq, DRM(dma_service),
555
                           DRM_IRQ_TYPE, dev->devname, dev );
556
        if ( ret < 0 ) {
557
                down( &dev->struct_sem );
558
                dev->irq = 0;
559
                up( &dev->struct_sem );
560
                return ret;
561
        }
562
 
563
                                /* After installing handler */
564
        DRM(driver_irq_postinstall)(dev);
565
 
566
        return 0;
567
}
568
 
569
int DRM(irq_uninstall)( drm_device_t *dev )
570
{
571
        int irq;
572
 
573
        down( &dev->struct_sem );
574
        irq = dev->irq;
575
        dev->irq = 0;
576
        up( &dev->struct_sem );
577
 
578
        if ( !irq )
579
                return -EINVAL;
580
 
581
        DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
582
 
583
        DRM(driver_irq_uninstall)( dev );
584
 
585
        free_irq( irq, dev );
586
 
587
        return 0;
588
}
589
 
590
int DRM(control)( struct inode *inode, struct file *filp,
591
                  unsigned int cmd, unsigned long arg )
592
{
593
        drm_file_t *priv = filp->private_data;
594
        drm_device_t *dev = priv->dev;
595
        drm_control_t ctl;
596
 
597
        if ( copy_from_user( &ctl, (drm_control_t *)arg, sizeof(ctl) ) )
598
                return -EFAULT;
599
 
600
        switch ( ctl.func ) {
601
        case DRM_INST_HANDLER:
602
                return DRM(irq_install)( dev, ctl.irq );
603
        case DRM_UNINST_HANDLER:
604
                return DRM(irq_uninstall)( dev );
605
        default:
606
                return -EINVAL;
607
        }
608
}
609
 
610
#if __HAVE_VBL_IRQ
611
 
612
int DRM(wait_vblank)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data )
613
{
614
        drm_file_t *priv = filp->private_data;
615
        drm_device_t *dev = priv->dev;
616
        drm_wait_vblank_t vblwait;
617
        struct timeval now;
618
        int ret = 0;
619
        unsigned int flags;
620
 
621
        if (!dev->irq)
622
                return -EINVAL;
623
 
624
        DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data,
625
                                  sizeof(vblwait) );
626
 
627
        switch ( vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK ) {
628
        case _DRM_VBLANK_RELATIVE:
629
                vblwait.request.sequence += atomic_read( &dev->vbl_received );
630
                vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
631
        case _DRM_VBLANK_ABSOLUTE:
632
                break;
633
        default:
634
                return -EINVAL;
635
        }
636
 
637
        flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
638
 
639
        if ( flags & _DRM_VBLANK_SIGNAL ) {
640
                unsigned long irqflags;
641
                drm_vbl_sig_t *vbl_sig;
642
 
643
                vblwait.reply.sequence = atomic_read( &dev->vbl_received );
644
 
645
                spin_lock_irqsave( &dev->vbl_lock, irqflags );
646
 
647
                /* Check if this task has already scheduled the same signal
648
                 * for the same vblank sequence number; nothing to be done in
649
                 * that case
650
                 */
651
                list_for_each( ( (struct list_head *) vbl_sig ), &dev->vbl_sigs.head ) {
652
                        if (vbl_sig->sequence == vblwait.request.sequence
653
                            && vbl_sig->info.si_signo == vblwait.request.signal
654
                            && vbl_sig->task == current)
655
                        {
656
                                spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
657
                                goto done;
658
                        }
659
                }
660
 
661
                if ( dev->vbl_pending >= 100 ) {
662
                        spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
663
                        return -EBUSY;
664
                }
665
 
666
                dev->vbl_pending++;
667
 
668
                spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
669
 
670
                if ( !( vbl_sig = kmalloc(sizeof(drm_vbl_sig_t), GFP_KERNEL) ) )
671
                        return -ENOMEM;
672
 
673
 
674
                memset( (void *)vbl_sig, 0, sizeof(*vbl_sig) );
675
 
676
                vbl_sig->sequence = vblwait.request.sequence;
677
                vbl_sig->info.si_signo = vblwait.request.signal;
678
                vbl_sig->task = current;
679
 
680
                spin_lock_irqsave( &dev->vbl_lock, irqflags );
681
 
682
                list_add_tail( (struct list_head *) vbl_sig, &dev->vbl_sigs.head );
683
 
684
                spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
685
        } else {
686
                ret = DRM(vblank_wait)( dev, &vblwait.request.sequence );
687
 
688
                do_gettimeofday( &now );
689
                vblwait.reply.tval_sec = now.tv_sec;
690
                vblwait.reply.tval_usec = now.tv_usec;
691
        }
692
 
693
done:
694
        DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait,
695
                                sizeof(vblwait) );
696
 
697
        return ret;
698
}
699
 
700
void DRM(vbl_send_signals)( drm_device_t *dev )
701
{
702
        struct list_head *tmp;
703
        drm_vbl_sig_t *vbl_sig;
704
        unsigned int vbl_seq = atomic_read( &dev->vbl_received );
705
        unsigned long flags;
706
 
707
        spin_lock_irqsave( &dev->vbl_lock, flags );
708
 
709
        list_for_each_safe( ( (struct list_head *) vbl_sig ), tmp, &dev->vbl_sigs.head ) {
710
                if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) {
711
                        vbl_sig->info.si_code = vbl_seq;
712
                        send_sig_info( vbl_sig->info.si_signo, &vbl_sig->info, vbl_sig->task );
713
 
714
                        list_del( (struct list_head *) vbl_sig );
715
 
716
 
717
                        kfree( vbl_sig );
718
                        dev->vbl_pending--;
719
                }
720
        }
721
 
722
        spin_unlock_irqrestore( &dev->vbl_lock, flags );
723
}
724
 
725
#endif  /* __HAVE_VBL_IRQ */
726
 
727
#else
728
 
729
int DRM(control)( struct inode *inode, struct file *filp,
730
                  unsigned int cmd, unsigned long arg )
731
{
732
        drm_control_t ctl;
733
 
734
        if ( copy_from_user( &ctl, (drm_control_t *)arg, sizeof(ctl) ) )
735
                return -EFAULT;
736
 
737
        switch ( ctl.func ) {
738
        case DRM_INST_HANDLER:
739
        case DRM_UNINST_HANDLER:
740
                return 0;
741
        default:
742
                return -EINVAL;
743
        }
744
}
745
 
746
#endif /* __HAVE_DMA_IRQ */
747
 
748
#endif /* __HAVE_DMA */

powered by: WebSVN 2.1.0

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