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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* mga_dma.c -- DMA support for mga g200/g400 -*- 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:
28
 *    Rickard E. (Rik) Faith <faith@valinux.com>
29
 *    Jeff Hartmann <jhartmann@valinux.com>
30
 *    Keith Whitwell <keith@tungstengraphics.com>
31
 *
32
 * Rewritten by:
33
 *    Gareth Hughes <gareth@valinux.com>
34
 */
35
 
36
#include "mga.h"
37
#include "drmP.h"
38
#include "drm.h"
39
#include "mga_drm.h"
40
#include "mga_drv.h"
41
#include <asm/delay.h>
42
#include "drm_os_linux.h"
43
 
44
#define MGA_DEFAULT_USEC_TIMEOUT        10000
45
#define MGA_FREELIST_DEBUG              0
46
 
47
 
48
/* ================================================================
49
 * Engine control
50
 */
51
 
52
int mga_do_wait_for_idle( drm_mga_private_t *dev_priv )
53
{
54
        u32 status = 0;
55
        int i;
56
        DRM_DEBUG( "\n" );
57
 
58
        for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
59
                status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK;
60
                if ( status == MGA_ENDPRDMASTS ) {
61
                        MGA_WRITE8( MGA_CRTC_INDEX, 0 );
62
                        return 0;
63
                }
64
                udelay( 1 );
65
        }
66
 
67
#if MGA_DMA_DEBUG
68
        DRM_ERROR( "failed!\n" );
69
        DRM_INFO( "   status=0x%08x\n", status );
70
#endif
71
        return -EBUSY;
72
}
73
 
74
int mga_do_dma_idle( drm_mga_private_t *dev_priv )
75
{
76
        u32 status = 0;
77
        int i;
78
        DRM_DEBUG( "\n" );
79
 
80
        for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
81
                status = MGA_READ( MGA_STATUS ) & MGA_DMA_IDLE_MASK;
82
                if ( status == MGA_ENDPRDMASTS ) return 0;
83
                udelay( 1 );
84
        }
85
 
86
#if MGA_DMA_DEBUG
87
        DRM_ERROR( "failed! status=0x%08x\n", status );
88
#endif
89
        return -EBUSY;
90
}
91
 
92
int mga_do_dma_reset( drm_mga_private_t *dev_priv )
93
{
94
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
95
        drm_mga_primary_buffer_t *primary = &dev_priv->prim;
96
 
97
        DRM_DEBUG( "\n" );
98
 
99
        /* The primary DMA stream should look like new right about now.
100
         */
101
        primary->tail = 0;
102
        primary->space = primary->size;
103
        primary->last_flush = 0;
104
 
105
        sarea_priv->last_wrap = 0;
106
 
107
        /* FIXME: Reset counters, buffer ages etc...
108
         */
109
 
110
        /* FIXME: What else do we need to reinitialize?  WARP stuff?
111
         */
112
 
113
        return 0;
114
}
115
 
116
int mga_do_engine_reset( drm_mga_private_t *dev_priv )
117
{
118
        DRM_DEBUG( "\n" );
119
 
120
        /* Okay, so we've completely screwed up and locked the engine.
121
         * How about we clean up after ourselves?
122
         */
123
        MGA_WRITE( MGA_RST, MGA_SOFTRESET );
124
        udelay( 15 );                           /* Wait at least 10 usecs */
125
        MGA_WRITE( MGA_RST, 0 );
126
 
127
        /* Initialize the registers that get clobbered by the soft
128
         * reset.  Many of the core register values survive a reset,
129
         * but the drawing registers are basically all gone.
130
         *
131
         * 3D clients should probably die after calling this.  The X
132
         * server should reset the engine state to known values.
133
         */
134
#if 0
135
        MGA_WRITE( MGA_PRIMPTR,
136
                   virt_to_bus((void *)dev_priv->prim.status_page) |
137
                   MGA_PRIMPTREN0 |
138
                   MGA_PRIMPTREN1 );
139
#endif
140
 
141
        MGA_WRITE( MGA_ICLEAR, MGA_SOFTRAPICLR );
142
        MGA_WRITE( MGA_IEN,    MGA_SOFTRAPIEN );
143
 
144
        /* The primary DMA stream should look like new right about now.
145
         */
146
        mga_do_dma_reset( dev_priv );
147
 
148
        /* This bad boy will never fail.
149
         */
150
        return 0;
151
}
152
 
153
 
154
/* ================================================================
155
 * Primary DMA stream
156
 */
157
 
158
void mga_do_dma_flush( drm_mga_private_t *dev_priv )
159
{
160
        drm_mga_primary_buffer_t *primary = &dev_priv->prim;
161
        u32 head, tail;
162
        u32 status = 0;
163
        int i;
164
        DMA_LOCALS;
165
        DRM_DEBUG( "\n" );
166
 
167
        /* We need to wait so that we can do an safe flush */
168
        for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
169
                status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK;
170
                if ( status == MGA_ENDPRDMASTS ) break;
171
                udelay( 1 );
172
        }
173
 
174
        if ( primary->tail == primary->last_flush ) {
175
                DRM_DEBUG( "   bailing out...\n" );
176
                return;
177
        }
178
 
179
        tail = primary->tail + dev_priv->primary->offset;
180
 
181
        /* We need to pad the stream between flushes, as the card
182
         * actually (partially?) reads the first of these commands.
183
         * See page 4-16 in the G400 manual, middle of the page or so.
184
         */
185
        BEGIN_DMA( 1 );
186
 
187
        DMA_BLOCK( MGA_DMAPAD,  0x00000000,
188
                   MGA_DMAPAD,  0x00000000,
189
                   MGA_DMAPAD,  0x00000000,
190
                   MGA_DMAPAD,  0x00000000 );
191
 
192
        ADVANCE_DMA();
193
 
194
        primary->last_flush = primary->tail;
195
 
196
        head = MGA_READ( MGA_PRIMADDRESS );
197
 
198
        if ( head <= tail ) {
199
                primary->space = primary->size - primary->tail;
200
        } else {
201
                primary->space = head - tail;
202
        }
203
 
204
        DRM_DEBUG( "   head = 0x%06lx\n", head - dev_priv->primary->offset );
205
        DRM_DEBUG( "   tail = 0x%06lx\n", tail - dev_priv->primary->offset );
206
        DRM_DEBUG( "  space = 0x%06x\n", primary->space );
207
 
208
        mga_flush_write_combine();
209
        MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER );
210
 
211
        DRM_DEBUG( "done.\n" );
212
}
213
 
214
void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv )
215
{
216
        drm_mga_primary_buffer_t *primary = &dev_priv->prim;
217
        u32 head, tail;
218
        DMA_LOCALS;
219
        DRM_DEBUG( "\n" );
220
 
221
        BEGIN_DMA_WRAP();
222
 
223
        DMA_BLOCK( MGA_DMAPAD,  0x00000000,
224
                   MGA_DMAPAD,  0x00000000,
225
                   MGA_DMAPAD,  0x00000000,
226
                   MGA_DMAPAD,  0x00000000 );
227
 
228
        ADVANCE_DMA();
229
 
230
        tail = primary->tail + dev_priv->primary->offset;
231
 
232
        primary->tail = 0;
233
        primary->last_flush = 0;
234
        primary->last_wrap++;
235
 
236
        head = MGA_READ( MGA_PRIMADDRESS );
237
 
238
        if ( head == dev_priv->primary->offset ) {
239
                primary->space = primary->size;
240
        } else {
241
                primary->space = head - dev_priv->primary->offset;
242
        }
243
 
244
        DRM_DEBUG( "   head = 0x%06lx\n",
245
                  head - dev_priv->primary->offset );
246
        DRM_DEBUG( "   tail = 0x%06x\n", primary->tail );
247
        DRM_DEBUG( "   wrap = %d\n", primary->last_wrap );
248
        DRM_DEBUG( "  space = 0x%06x\n", primary->space );
249
 
250
        mga_flush_write_combine();
251
        MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER );
252
 
253
        set_bit( 0, &primary->wrapped );
254
        DRM_DEBUG( "done.\n" );
255
}
256
 
257
void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv )
258
{
259
        drm_mga_primary_buffer_t *primary = &dev_priv->prim;
260
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
261
        u32 head = dev_priv->primary->offset;
262
        DRM_DEBUG( "\n" );
263
 
264
        sarea_priv->last_wrap++;
265
        DRM_DEBUG( "   wrap = %d\n", sarea_priv->last_wrap );
266
 
267
        mga_flush_write_combine();
268
        MGA_WRITE( MGA_PRIMADDRESS, head | MGA_DMA_GENERAL );
269
 
270
        clear_bit( 0, &primary->wrapped );
271
        DRM_DEBUG( "done.\n" );
272
}
273
 
274
 
275
/* ================================================================
276
 * Freelist management
277
 */
278
 
279
#define MGA_BUFFER_USED         ~0
280
#define MGA_BUFFER_FREE         0
281
 
282
#if MGA_FREELIST_DEBUG
283
static void mga_freelist_print( drm_device_t *dev )
284
{
285
        drm_mga_private_t *dev_priv = dev->dev_private;
286
        drm_mga_freelist_t *entry;
287
 
288
        DRM_INFO( "\n" );
289
        DRM_INFO( "current dispatch: last=0x%x done=0x%x\n",
290
                  dev_priv->sarea_priv->last_dispatch,
291
                  (unsigned int)(MGA_READ( MGA_PRIMADDRESS ) -
292
                                 dev_priv->primary->offset) );
293
        DRM_INFO( "current freelist:\n" );
294
 
295
        for ( entry = dev_priv->head->next ; entry ; entry = entry->next ) {
296
                DRM_INFO( "   %p   idx=%2d  age=0x%x 0x%06lx\n",
297
                          entry, entry->buf->idx, entry->age.head,
298
                          entry->age.head - dev_priv->primary->offset );
299
        }
300
        DRM_INFO( "\n" );
301
}
302
#endif
303
 
304
static int mga_freelist_init( drm_device_t *dev, drm_mga_private_t *dev_priv )
305
{
306
        drm_device_dma_t *dma = dev->dma;
307
        drm_buf_t *buf;
308
        drm_mga_buf_priv_t *buf_priv;
309
        drm_mga_freelist_t *entry;
310
        int i;
311
        DRM_DEBUG( "count=%d\n", dma->buf_count );
312
 
313
        dev_priv->head = DRM(alloc)( sizeof(drm_mga_freelist_t),
314
                                     DRM_MEM_DRIVER );
315
        if ( dev_priv->head == NULL )
316
                return -ENOMEM;
317
 
318
        memset( dev_priv->head, 0, sizeof(drm_mga_freelist_t) );
319
        SET_AGE( &dev_priv->head->age, MGA_BUFFER_USED, 0 );
320
 
321
        for ( i = 0 ; i < dma->buf_count ; i++ ) {
322
                buf = dma->buflist[i];
323
                buf_priv = buf->dev_private;
324
 
325
                entry = DRM(alloc)( sizeof(drm_mga_freelist_t),
326
                                    DRM_MEM_DRIVER );
327
                if ( entry == NULL )
328
                        return -ENOMEM;
329
 
330
                memset( entry, 0, sizeof(drm_mga_freelist_t) );
331
 
332
                entry->next = dev_priv->head->next;
333
                entry->prev = dev_priv->head;
334
                SET_AGE( &entry->age, MGA_BUFFER_FREE, 0 );
335
                entry->buf = buf;
336
 
337
                if ( dev_priv->head->next != NULL )
338
                        dev_priv->head->next->prev = entry;
339
                if ( entry->next == NULL )
340
                        dev_priv->tail = entry;
341
 
342
                buf_priv->list_entry = entry;
343
                buf_priv->discard = 0;
344
                buf_priv->dispatched = 0;
345
 
346
                dev_priv->head->next = entry;
347
        }
348
 
349
        return 0;
350
}
351
 
352
static void mga_freelist_cleanup( drm_device_t *dev )
353
{
354
        drm_mga_private_t *dev_priv = dev->dev_private;
355
        drm_mga_freelist_t *entry;
356
        drm_mga_freelist_t *next;
357
        DRM_DEBUG( "\n" );
358
 
359
        entry = dev_priv->head;
360
        while ( entry ) {
361
                next = entry->next;
362
                DRM(free)( entry, sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER );
363
                entry = next;
364
        }
365
 
366
        dev_priv->head = dev_priv->tail = NULL;
367
}
368
 
369
#if 0
370
/* FIXME: Still needed?
371
 */
372
static void mga_freelist_reset( drm_device_t *dev )
373
{
374
        drm_device_dma_t *dma = dev->dma;
375
        drm_buf_t *buf;
376
        drm_mga_buf_priv_t *buf_priv;
377
        int i;
378
 
379
        for ( i = 0 ; i < dma->buf_count ; i++ ) {
380
                buf = dma->buflist[i];
381
                buf_priv = buf->dev_private;
382
                SET_AGE( &buf_priv->list_entry->age,
383
                         MGA_BUFFER_FREE, 0 );
384
        }
385
}
386
#endif
387
 
388
static drm_buf_t *mga_freelist_get( drm_device_t *dev )
389
{
390
        drm_mga_private_t *dev_priv = dev->dev_private;
391
        drm_mga_freelist_t *next;
392
        drm_mga_freelist_t *prev;
393
        drm_mga_freelist_t *tail = dev_priv->tail;
394
        u32 head, wrap;
395
        DRM_DEBUG( "\n" );
396
 
397
        head = MGA_READ( MGA_PRIMADDRESS );
398
        wrap = dev_priv->sarea_priv->last_wrap;
399
 
400
        DRM_DEBUG( "   tail=0x%06lx %d\n",
401
                   tail->age.head ?
402
                   tail->age.head - dev_priv->primary->offset : 0,
403
                   tail->age.wrap );
404
        DRM_DEBUG( "   head=0x%06lx %d\n",
405
                   head - dev_priv->primary->offset, wrap );
406
 
407
        if ( TEST_AGE( &tail->age, head, wrap ) ) {
408
                prev = dev_priv->tail->prev;
409
                next = dev_priv->tail;
410
                prev->next = NULL;
411
                next->prev = next->next = NULL;
412
                dev_priv->tail = prev;
413
                SET_AGE( &next->age, MGA_BUFFER_USED, 0 );
414
                return next->buf;
415
        }
416
 
417
        DRM_DEBUG( "returning NULL!\n" );
418
        return NULL;
419
}
420
 
421
int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf )
422
{
423
        drm_mga_private_t *dev_priv = dev->dev_private;
424
        drm_mga_buf_priv_t *buf_priv = buf->dev_private;
425
        drm_mga_freelist_t *head, *entry, *prev;
426
 
427
        DRM_DEBUG( "age=0x%06lx wrap=%d\n",
428
                   buf_priv->list_entry->age.head -
429
                   dev_priv->primary->offset,
430
                   buf_priv->list_entry->age.wrap );
431
 
432
        entry = buf_priv->list_entry;
433
        head = dev_priv->head;
434
 
435
        if ( buf_priv->list_entry->age.head == MGA_BUFFER_USED ) {
436
                SET_AGE( &entry->age, MGA_BUFFER_FREE, 0 );
437
                prev = dev_priv->tail;
438
                prev->next = entry;
439
                entry->prev = prev;
440
                entry->next = NULL;
441
        } else {
442
                prev = head->next;
443
                head->next = entry;
444
                prev->prev = entry;
445
                entry->prev = head;
446
                entry->next = prev;
447
        }
448
 
449
        return 0;
450
}
451
 
452
 
453
/* ================================================================
454
 * DMA initialization, cleanup
455
 */
456
 
457
static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
458
{
459
        drm_mga_private_t *dev_priv;
460
        int ret;
461
        DRM_DEBUG( "\n" );
462
 
463
        dev_priv = DRM(alloc)( sizeof(drm_mga_private_t), DRM_MEM_DRIVER );
464
        if ( !dev_priv )
465
                return -ENOMEM;
466
 
467
        memset( dev_priv, 0, sizeof(drm_mga_private_t) );
468
 
469
        dev_priv->chipset = init->chipset;
470
 
471
        dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
472
 
473
        if ( init->sgram ) {
474
                dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK;
475
        } else {
476
                dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR;
477
        }
478
        dev_priv->maccess       = init->maccess;
479
 
480
        dev_priv->fb_cpp        = init->fb_cpp;
481
        dev_priv->front_offset  = init->front_offset;
482
        dev_priv->front_pitch   = init->front_pitch;
483
        dev_priv->back_offset   = init->back_offset;
484
        dev_priv->back_pitch    = init->back_pitch;
485
 
486
        dev_priv->depth_cpp     = init->depth_cpp;
487
        dev_priv->depth_offset  = init->depth_offset;
488
        dev_priv->depth_pitch   = init->depth_pitch;
489
 
490
        /* FIXME: Need to support AGP textures...
491
         */
492
        dev_priv->texture_offset = init->texture_offset[0];
493
        dev_priv->texture_size = init->texture_size[0];
494
 
495
        DRM_GETSAREA();
496
 
497
        if(!dev_priv->sarea) {
498
                DRM_ERROR( "failed to find sarea!\n" );
499
                /* Assign dev_private so we can do cleanup. */
500
                dev->dev_private = (void *)dev_priv;
501
                mga_do_cleanup_dma( dev );
502
                return -EINVAL;
503
        }
504
 
505
        DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
506
        if(!dev_priv->fb) {
507
                DRM_ERROR( "failed to find framebuffer!\n" );
508
                /* Assign dev_private so we can do cleanup. */
509
                dev->dev_private = (void *)dev_priv;
510
                mga_do_cleanup_dma( dev );
511
                return -EINVAL;
512
        }
513
        DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
514
        if(!dev_priv->mmio) {
515
                DRM_ERROR( "failed to find mmio region!\n" );
516
                /* Assign dev_private so we can do cleanup. */
517
                dev->dev_private = (void *)dev_priv;
518
                mga_do_cleanup_dma( dev );
519
                return -EINVAL;
520
        }
521
        DRM_FIND_MAP( dev_priv->status, init->status_offset );
522
        if(!dev_priv->status) {
523
                DRM_ERROR( "failed to find status page!\n" );
524
                /* Assign dev_private so we can do cleanup. */
525
                dev->dev_private = (void *)dev_priv;
526
                mga_do_cleanup_dma( dev );
527
                return -EINVAL;
528
        }
529
 
530
        DRM_FIND_MAP( dev_priv->warp, init->warp_offset );
531
        if(!dev_priv->warp) {
532
                DRM_ERROR( "failed to find warp microcode region!\n" );
533
                /* Assign dev_private so we can do cleanup. */
534
                dev->dev_private = (void *)dev_priv;
535
                mga_do_cleanup_dma( dev );
536
                return -EINVAL;
537
        }
538
        DRM_FIND_MAP( dev_priv->primary, init->primary_offset );
539
        if(!dev_priv->primary) {
540
                DRM_ERROR( "failed to find primary dma region!\n" );
541
                /* Assign dev_private so we can do cleanup. */
542
                dev->dev_private = (void *)dev_priv;
543
                mga_do_cleanup_dma( dev );
544
                return -EINVAL;
545
        }
546
        DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
547
        if(!dev_priv->buffers) {
548
                DRM_ERROR( "failed to find dma buffer region!\n" );
549
                /* Assign dev_private so we can do cleanup. */
550
                dev->dev_private = (void *)dev_priv;
551
                mga_do_cleanup_dma( dev );
552
                return -EINVAL;
553
        }
554
 
555
        dev_priv->sarea_priv =
556
                (drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle +
557
                                    init->sarea_priv_offset);
558
 
559
        DRM_IOREMAP( dev_priv->warp, dev );
560
        DRM_IOREMAP( dev_priv->primary, dev );
561
        DRM_IOREMAP( dev_priv->buffers, dev );
562
 
563
        if(!dev_priv->warp->handle ||
564
           !dev_priv->primary->handle ||
565
           !dev_priv->buffers->handle ) {
566
                DRM_ERROR( "failed to ioremap agp regions!\n" );
567
                /* Assign dev_private so we can do cleanup. */
568
                dev->dev_private = (void *)dev_priv;
569
                mga_do_cleanup_dma( dev );
570
                return -ENOMEM;
571
        }
572
 
573
        ret = mga_warp_install_microcode( dev_priv );
574
        if ( ret < 0 ) {
575
                DRM_ERROR( "failed to install WARP ucode!\n" );
576
                /* Assign dev_private so we can do cleanup. */
577
                dev->dev_private = (void *)dev_priv;
578
                mga_do_cleanup_dma( dev );
579
                return ret;
580
        }
581
 
582
        ret = mga_warp_init( dev_priv );
583
        if ( ret < 0 ) {
584
                DRM_ERROR( "failed to init WARP engine!\n" );
585
                /* Assign dev_private so we can do cleanup. */
586
                dev->dev_private = (void *)dev_priv;
587
                mga_do_cleanup_dma( dev );
588
                return ret;
589
        }
590
 
591
        dev_priv->prim.status = (u32 *)dev_priv->status->handle;
592
 
593
        mga_do_wait_for_idle( dev_priv );
594
 
595
        /* Init the primary DMA registers.
596
         */
597
        MGA_WRITE( MGA_PRIMADDRESS,
598
                   dev_priv->primary->offset | MGA_DMA_GENERAL );
599
#if 0
600
        MGA_WRITE( MGA_PRIMPTR,
601
                   virt_to_bus((void *)dev_priv->prim.status) |
602
                   MGA_PRIMPTREN0 |     /* Soft trap, SECEND, SETUPEND */
603
                   MGA_PRIMPTREN1 );    /* DWGSYNC */
604
#endif
605
 
606
        dev_priv->prim.start = (u8 *)dev_priv->primary->handle;
607
        dev_priv->prim.end = ((u8 *)dev_priv->primary->handle
608
                              + dev_priv->primary->size);
609
        dev_priv->prim.size = dev_priv->primary->size;
610
 
611
        dev_priv->prim.tail = 0;
612
        dev_priv->prim.space = dev_priv->prim.size;
613
        dev_priv->prim.wrapped = 0;
614
 
615
        dev_priv->prim.last_flush = 0;
616
        dev_priv->prim.last_wrap = 0;
617
 
618
        dev_priv->prim.high_mark = 256 * DMA_BLOCK_SIZE;
619
 
620
        dev_priv->prim.status[0] = dev_priv->primary->offset;
621
        dev_priv->prim.status[1] = 0;
622
 
623
        dev_priv->sarea_priv->last_wrap = 0;
624
        dev_priv->sarea_priv->last_frame.head = 0;
625
        dev_priv->sarea_priv->last_frame.wrap = 0;
626
 
627
        if ( mga_freelist_init( dev, dev_priv ) < 0 ) {
628
                DRM_ERROR( "could not initialize freelist\n" );
629
                /* Assign dev_private so we can do cleanup. */
630
                dev->dev_private = (void *)dev_priv;
631
                mga_do_cleanup_dma( dev );
632
                return -ENOMEM;
633
        }
634
 
635
        /* Make dev_private visable to others. */
636
        dev->dev_private = (void *)dev_priv;
637
        return 0;
638
}
639
 
640
int mga_do_cleanup_dma( drm_device_t *dev )
641
{
642
        DRM_DEBUG( "\n" );
643
 
644
        if ( dev->dev_private ) {
645
                drm_mga_private_t *dev_priv = dev->dev_private;
646
 
647
                DRM_IOREMAPFREE( dev_priv->warp, dev );
648
                DRM_IOREMAPFREE( dev_priv->primary, dev );
649
                DRM_IOREMAPFREE( dev_priv->buffers, dev );
650
 
651
                if ( dev_priv->head != NULL ) {
652
                        mga_freelist_cleanup( dev );
653
                }
654
 
655
                DRM(free)( dev->dev_private, sizeof(drm_mga_private_t),
656
                           DRM_MEM_DRIVER );
657
                dev->dev_private = NULL;
658
        }
659
 
660
        return 0;
661
}
662
 
663
int mga_dma_init( struct inode *inode, struct file *filp,
664
                  unsigned int cmd, unsigned long arg )
665
{
666
        drm_file_t *priv = filp->private_data;
667
        drm_device_t *dev = priv->dev;
668
        drm_mga_init_t init;
669
 
670
        if ( copy_from_user( &init, (drm_mga_init_t *)arg, sizeof(init) ) )
671
                return -EFAULT;
672
 
673
        switch ( init.func ) {
674
        case MGA_INIT_DMA:
675
                return mga_do_init_dma( dev, &init );
676
        case MGA_CLEANUP_DMA:
677
                return mga_do_cleanup_dma( dev );
678
        }
679
 
680
        return -EINVAL;
681
}
682
 
683
 
684
/* ================================================================
685
 * Primary DMA stream management
686
 */
687
 
688
int mga_dma_flush( struct inode *inode, struct file *filp,
689
                   unsigned int cmd, unsigned long arg )
690
{
691
        drm_file_t *priv = filp->private_data;
692
        drm_device_t *dev = priv->dev;
693
        drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
694
        drm_lock_t lock;
695
 
696
        LOCK_TEST_WITH_RETURN( dev );
697
 
698
        if ( copy_from_user( &lock, (drm_lock_t *)arg, sizeof(lock) ) )
699
                return -EFAULT;
700
 
701
        DRM_DEBUG( "%s: %s%s%s\n",
702
                   __FUNCTION__,
703
                   (lock.flags & _DRM_LOCK_FLUSH) ?     "flush, " : "",
704
                   (lock.flags & _DRM_LOCK_FLUSH_ALL) ? "flush all, " : "",
705
                   (lock.flags & _DRM_LOCK_QUIESCENT) ? "idle, " : "" );
706
 
707
        WRAP_WAIT_WITH_RETURN( dev_priv );
708
 
709
        if ( lock.flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL) ) {
710
                mga_do_dma_flush( dev_priv );
711
        }
712
 
713
        if ( lock.flags & _DRM_LOCK_QUIESCENT ) {
714
#if MGA_DMA_DEBUG
715
                int ret = mga_do_wait_for_idle( dev_priv );
716
                if ( ret < 0 )
717
                        DRM_INFO( "%s: -EBUSY\n", __FUNCTION__ );
718
                return ret;
719
#else
720
                return mga_do_wait_for_idle( dev_priv );
721
#endif
722
        } else {
723
                return 0;
724
        }
725
}
726
 
727
int mga_dma_reset( struct inode *inode, struct file *filp,
728
                   unsigned int cmd, unsigned long arg )
729
{
730
        drm_file_t *priv = filp->private_data;
731
        drm_device_t *dev = priv->dev;
732
        drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
733
 
734
        LOCK_TEST_WITH_RETURN( dev );
735
 
736
        return mga_do_dma_reset( dev_priv );
737
}
738
 
739
 
740
/* ================================================================
741
 * DMA buffer management
742
 */
743
 
744
static int mga_dma_get_buffers( drm_device_t *dev, drm_dma_t *d )
745
{
746
        drm_buf_t *buf;
747
        int i;
748
 
749
        for ( i = d->granted_count ; i < d->request_count ; i++ ) {
750
                buf = mga_freelist_get( dev );
751
                if ( !buf ) return -EAGAIN;
752
 
753
                buf->pid = current->pid;
754
 
755
                if ( copy_to_user( &d->request_indices[i],
756
                                   &buf->idx, sizeof(buf->idx) ) )
757
                        return -EFAULT;
758
                if ( copy_to_user( &d->request_sizes[i],
759
                                   &buf->total, sizeof(buf->total) ) )
760
                        return -EFAULT;
761
 
762
                d->granted_count++;
763
        }
764
        return 0;
765
}
766
 
767
int mga_dma_buffers( struct inode *inode, struct file *filp,
768
                     unsigned int cmd, unsigned long arg )
769
{
770
        drm_file_t *priv = filp->private_data;
771
        drm_device_t *dev = priv->dev;
772
        drm_device_dma_t *dma = dev->dma;
773
        drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
774
        drm_dma_t d;
775
        int ret = 0;
776
 
777
        LOCK_TEST_WITH_RETURN( dev );
778
 
779
        if ( copy_from_user( &d, (drm_dma_t *)arg, sizeof(d) ) )
780
                return -EFAULT;
781
 
782
        /* Please don't send us buffers.
783
         */
784
        if ( d.send_count != 0 ) {
785
                DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",
786
                           current->pid, d.send_count );
787
                return -EINVAL;
788
        }
789
 
790
        /* We'll send you buffers.
791
         */
792
        if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
793
                DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n",
794
                           current->pid, d.request_count, dma->buf_count );
795
                return -EINVAL;
796
        }
797
 
798
        WRAP_TEST_WITH_RETURN( dev_priv );
799
 
800
        d.granted_count = 0;
801
 
802
        if ( d.request_count ) {
803
                ret = mga_dma_get_buffers( dev, &d );
804
        }
805
 
806
        if ( copy_to_user( (drm_dma_t *)arg, &d, sizeof(d) ) )
807
                return -EFAULT;
808
 
809
        return ret;
810
}

powered by: WebSVN 2.1.0

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