1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36#include "mga.h"
37#include "drmP.h"
38#include "mga_drv.h"
39
40#include <linux/interrupt.h>
41#include <linux/delay.h>
42
43#define MGA_DEFAULT_USEC_TIMEOUT 10000
44#define MGA_FREELIST_DEBUG 0
45
46
47
48
49
50
51int mga_do_wait_for_idle( drm_mga_private_t *dev_priv )
52{
53 u32 status = 0;
54 int i;
55 DRM_DEBUG( "%s\n", __FUNCTION__ );
56
57 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
58 status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK;
59 if ( status == MGA_ENDPRDMASTS ) {
60 MGA_WRITE8( MGA_CRTC_INDEX, 0 );
61 return 0;
62 }
63 udelay( 1 );
64 }
65
66#if MGA_DMA_DEBUG
67 DRM_ERROR( "failed!\n" );
68 DRM_INFO( " status=0x%08x\n", status );
69#endif
70 return -EBUSY;
71}
72
73int mga_do_dma_idle( drm_mga_private_t *dev_priv )
74{
75 u32 status = 0;
76 int i;
77 DRM_DEBUG( "%s\n", __FUNCTION__ );
78
79 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
80 status = MGA_READ( MGA_STATUS ) & MGA_DMA_IDLE_MASK;
81 if ( status == MGA_ENDPRDMASTS ) return 0;
82 udelay( 1 );
83 }
84
85#if MGA_DMA_DEBUG
86 DRM_ERROR( "failed! status=0x%08x\n", status );
87#endif
88 return -EBUSY;
89}
90
91int mga_do_dma_reset( drm_mga_private_t *dev_priv )
92{
93 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
94 drm_mga_primary_buffer_t *primary = &dev_priv->prim;
95
96 DRM_DEBUG( "%s\n", __FUNCTION__ );
97
98
99
100 primary->tail = 0;
101 primary->space = primary->size;
102 primary->last_flush = 0;
103
104 sarea_priv->last_wrap = 0;
105
106
107
108
109
110
111
112 return 0;
113}
114
115int mga_do_engine_reset( drm_mga_private_t *dev_priv )
116{
117 DRM_DEBUG( "%s\n", __FUNCTION__ );
118
119
120
121
122 MGA_WRITE( MGA_RST, MGA_SOFTRESET );
123 udelay( 15 );
124 MGA_WRITE( MGA_RST, 0 );
125
126
127
128
129
130
131
132
133#if 0
134 MGA_WRITE( MGA_PRIMPTR,
135 virt_to_bus((void *)dev_priv->prim.status_page) |
136 MGA_PRIMPTREN0 |
137 MGA_PRIMPTREN1 );
138#endif
139
140 MGA_WRITE( MGA_ICLEAR, MGA_SOFTRAPICLR );
141 MGA_WRITE( MGA_IEN, MGA_SOFTRAPIEN );
142
143
144
145 mga_do_dma_reset( dev_priv );
146
147
148
149 return 0;
150}
151
152
153
154
155
156
157void mga_do_dma_flush( drm_mga_private_t *dev_priv )
158{
159 drm_mga_primary_buffer_t *primary = &dev_priv->prim;
160 u32 head, tail;
161 u32 status = 0;
162 int i;
163 DMA_LOCALS;
164 DRM_DEBUG( "%s:\n", __FUNCTION__ );
165
166
167 for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
168 status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK;
169 if ( status == MGA_ENDPRDMASTS ) break;
170 udelay( 1 );
171 }
172
173 if ( primary->tail == primary->last_flush ) {
174 DRM_DEBUG( " bailing out...\n" );
175 return;
176 }
177
178 tail = primary->tail + dev_priv->primary->offset;
179
180
181
182
183
184 BEGIN_DMA( 1 );
185
186 DMA_BLOCK( MGA_DMAPAD, 0x00000000,
187 MGA_DMAPAD, 0x00000000,
188 MGA_DMAPAD, 0x00000000,
189 MGA_DMAPAD, 0x00000000 );
190
191 ADVANCE_DMA();
192
193 primary->last_flush = primary->tail;
194
195 head = MGA_READ( MGA_PRIMADDRESS );
196
197 if ( head <= tail ) {
198 primary->space = primary->size - primary->tail;
199 } else {
200 primary->space = head - tail;
201 }
202
203 DRM_DEBUG( " head = 0x%06lx\n", head - dev_priv->primary->offset );
204 DRM_DEBUG( " tail = 0x%06lx\n", tail - dev_priv->primary->offset );
205 DRM_DEBUG( " space = 0x%06x\n", primary->space );
206
207 mga_flush_write_combine();
208 MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER );
209
210 DRM_DEBUG( "%s: done.\n", __FUNCTION__ );
211}
212
213void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv )
214{
215 drm_mga_primary_buffer_t *primary = &dev_priv->prim;
216 u32 head, tail;
217 DMA_LOCALS;
218 DRM_DEBUG( "%s:\n", __FUNCTION__ );
219
220 BEGIN_DMA_WRAP();
221
222 DMA_BLOCK( MGA_DMAPAD, 0x00000000,
223 MGA_DMAPAD, 0x00000000,
224 MGA_DMAPAD, 0x00000000,
225 MGA_DMAPAD, 0x00000000 );
226
227 ADVANCE_DMA();
228
229 tail = primary->tail + dev_priv->primary->offset;
230
231 primary->tail = 0;
232 primary->last_flush = 0;
233 primary->last_wrap++;
234
235 head = MGA_READ( MGA_PRIMADDRESS );
236
237 if ( head == dev_priv->primary->offset ) {
238 primary->space = primary->size;
239 } else {
240 primary->space = head - dev_priv->primary->offset;
241 }
242
243 DRM_DEBUG( " head = 0x%06lx\n",
244 head - dev_priv->primary->offset );
245 DRM_DEBUG( " tail = 0x%06x\n", primary->tail );
246 DRM_DEBUG( " wrap = %d\n", primary->last_wrap );
247 DRM_DEBUG( " space = 0x%06x\n", primary->space );
248
249 mga_flush_write_combine();
250 MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER );
251
252 set_bit( 0, &primary->wrapped );
253 DRM_DEBUG( "%s: done.\n", __FUNCTION__ );
254}
255
256void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv )
257{
258 drm_mga_primary_buffer_t *primary = &dev_priv->prim;
259 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
260 u32 head = dev_priv->primary->offset;
261 DRM_DEBUG( "%s:\n", __FUNCTION__ );
262
263 sarea_priv->last_wrap++;
264 DRM_DEBUG( " wrap = %d\n", sarea_priv->last_wrap );
265
266 mga_flush_write_combine();
267 MGA_WRITE( MGA_PRIMADDRESS, head | MGA_DMA_GENERAL );
268
269 clear_bit( 0, &primary->wrapped );
270 DRM_DEBUG( "%s: done.\n", __FUNCTION__ );
271}
272
273
274
275
276
277
278#define MGA_BUFFER_USED ~0
279#define MGA_BUFFER_FREE 0
280
281#if MGA_FREELIST_DEBUG
282static void mga_freelist_print( drm_device_t *dev )
283{
284 drm_mga_private_t *dev_priv = dev->dev_private;
285 drm_mga_freelist_t *entry;
286
287 DRM_INFO( "\n" );
288 DRM_INFO( "current dispatch: last=0x%x done=0x%x\n",
289 dev_priv->sarea_priv->last_dispatch,
290 (unsigned int)(MGA_READ( MGA_PRIMADDRESS ) -
291 dev_priv->primary->offset) );
292 DRM_INFO( "current freelist:\n" );
293
294 for ( entry = dev_priv->head->next ; entry ; entry = entry->next ) {
295 DRM_INFO( " %p idx=%2d age=0x%x 0x%06lx\n",
296 entry, entry->buf->idx, entry->age.head,
297 entry->age.head - dev_priv->primary->offset );
298 }
299 DRM_INFO( "\n" );
300}
301#endif
302
303static int mga_freelist_init( drm_device_t *dev, drm_mga_private_t *dev_priv )
304{
305 drm_device_dma_t *dma = dev->dma;
306 drm_buf_t *buf;
307 drm_mga_buf_priv_t *buf_priv;
308 drm_mga_freelist_t *entry;
309 int i;
310 DRM_DEBUG( "%s: count=%d\n",
311 __FUNCTION__, 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
352static 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( "%s\n", __FUNCTION__ );
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
371
372static 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
388static 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( "%s:\n", __FUNCTION__ );
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
421int 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( "%s: age=0x%06lx wrap=%d\n",
428 __FUNCTION__,
429 buf_priv->list_entry->age.head -
430 dev_priv->primary->offset,
431 buf_priv->list_entry->age.wrap );
432
433 entry = buf_priv->list_entry;
434 head = dev_priv->head;
435
436 if ( buf_priv->list_entry->age.head == MGA_BUFFER_USED ) {
437 SET_AGE( &entry->age, MGA_BUFFER_FREE, 0 );
438 prev = dev_priv->tail;
439 prev->next = entry;
440 entry->prev = prev;
441 entry->next = NULL;
442 } else {
443 prev = head->next;
444 head->next = entry;
445 prev->prev = entry;
446 entry->prev = head;
447 entry->next = prev;
448 }
449
450 return 0;
451}
452
453
454
455
456
457
458static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
459{
460 drm_mga_private_t *dev_priv;
461 struct list_head *list;
462 int ret;
463 DRM_DEBUG( "%s\n", __FUNCTION__ );
464
465 dev_priv = DRM(alloc)( sizeof(drm_mga_private_t), DRM_MEM_DRIVER );
466 if ( !dev_priv )
467 return -ENOMEM;
468
469 memset( dev_priv, 0, sizeof(drm_mga_private_t) );
470
471 dev_priv->chipset = init->chipset;
472
473 dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
474
475 if ( init->sgram ) {
476 dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK;
477 } else {
478 dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR;
479 }
480 dev_priv->maccess = init->maccess;
481
482 dev_priv->fb_cpp = init->fb_cpp;
483 dev_priv->front_offset = init->front_offset;
484 dev_priv->front_pitch = init->front_pitch;
485 dev_priv->back_offset = init->back_offset;
486 dev_priv->back_pitch = init->back_pitch;
487
488 dev_priv->depth_cpp = init->depth_cpp;
489 dev_priv->depth_offset = init->depth_offset;
490 dev_priv->depth_pitch = init->depth_pitch;
491
492
493
494 dev_priv->texture_offset = init->texture_offset[0];
495 dev_priv->texture_size = init->texture_size[0];
496
497 list_for_each( list, &dev->maplist->head ) {
498 drm_map_list_t *entry = (drm_map_list_t *)list;
499 if ( entry->map &&
500 entry->map->type == _DRM_SHM &&
501 (entry->map->flags & _DRM_CONTAINS_LOCK) ) {
502 dev_priv->sarea = entry->map;
503 break;
504 }
505 }
506 if(!dev_priv->sarea) {
507 DRM_ERROR( "failed to find sarea!\n" );
508
509 dev->dev_private = (void *)dev_priv;
510 mga_do_cleanup_dma( dev );
511 return -EINVAL;
512 }
513
514 DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
515 if(!dev_priv->fb) {
516 DRM_ERROR( "failed to find framebuffer!\n" );
517
518 dev->dev_private = (void *)dev_priv;
519 mga_do_cleanup_dma( dev );
520 return -EINVAL;
521 }
522 DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
523 if(!dev_priv->mmio) {
524 DRM_ERROR( "failed to find mmio region!\n" );
525
526 dev->dev_private = (void *)dev_priv;
527 mga_do_cleanup_dma( dev );
528 return -EINVAL;
529 }
530 DRM_FIND_MAP( dev_priv->status, init->status_offset );
531 if(!dev_priv->status) {
532 DRM_ERROR( "failed to find status page!\n" );
533
534 dev->dev_private = (void *)dev_priv;
535 mga_do_cleanup_dma( dev );
536 return -EINVAL;
537 }
538
539 DRM_FIND_MAP( dev_priv->warp, init->warp_offset );
540 if(!dev_priv->warp) {
541 DRM_ERROR( "failed to find warp microcode region!\n" );
542
543 dev->dev_private = (void *)dev_priv;
544 mga_do_cleanup_dma( dev );
545 return -EINVAL;
546 }
547 DRM_FIND_MAP( dev_priv->primary, init->primary_offset );
548 if(!dev_priv->primary) {
549 DRM_ERROR( "failed to find primary dma region!\n" );
550
551 dev->dev_private = (void *)dev_priv;
552 mga_do_cleanup_dma( dev );
553 return -EINVAL;
554 }
555 DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
556 if(!dev_priv->buffers) {
557 DRM_ERROR( "failed to find dma buffer region!\n" );
558
559 dev->dev_private = (void *)dev_priv;
560 mga_do_cleanup_dma( dev );
561 return -EINVAL;
562 }
563
564 dev_priv->sarea_priv =
565 (drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle +
566 init->sarea_priv_offset);
567
568 DRM_IOREMAP( dev_priv->warp );
569 DRM_IOREMAP( dev_priv->primary );
570 DRM_IOREMAP( dev_priv->buffers );
571
572 if(!dev_priv->warp->handle ||
573 !dev_priv->primary->handle ||
574 !dev_priv->buffers->handle ) {
575 DRM_ERROR( "failed to ioremap agp regions!\n" );
576
577 dev->dev_private = (void *)dev_priv;
578 mga_do_cleanup_dma( dev );
579 return -ENOMEM;
580 }
581
582 ret = mga_warp_install_microcode( dev_priv );
583 if ( ret < 0 ) {
584 DRM_ERROR( "failed to install WARP ucode!\n" );
585
586 dev->dev_private = (void *)dev_priv;
587 mga_do_cleanup_dma( dev );
588 return ret;
589 }
590
591 ret = mga_warp_init( dev_priv );
592 if ( ret < 0 ) {
593 DRM_ERROR( "failed to init WARP engine!\n" );
594
595 dev->dev_private = (void *)dev_priv;
596 mga_do_cleanup_dma( dev );
597 return ret;
598 }
599
600 dev_priv->prim.status = (u32 *)dev_priv->status->handle;
601
602 mga_do_wait_for_idle( dev_priv );
603
604
605
606 MGA_WRITE( MGA_PRIMADDRESS,
607 dev_priv->primary->offset | MGA_DMA_GENERAL );
608#if 0
609 MGA_WRITE( MGA_PRIMPTR,
610 virt_to_bus((void *)dev_priv->prim.status) |
611 MGA_PRIMPTREN0 |
612 MGA_PRIMPTREN1 );
613#endif
614
615 dev_priv->prim.start = (u8 *)dev_priv->primary->handle;
616 dev_priv->prim.end = ((u8 *)dev_priv->primary->handle
617 + dev_priv->primary->size);
618 dev_priv->prim.size = dev_priv->primary->size;
619
620 dev_priv->prim.tail = 0;
621 dev_priv->prim.space = dev_priv->prim.size;
622 dev_priv->prim.wrapped = 0;
623
624 dev_priv->prim.last_flush = 0;
625 dev_priv->prim.last_wrap = 0;
626
627 dev_priv->prim.high_mark = 256 * DMA_BLOCK_SIZE;
628
629 spin_lock_init( &dev_priv->prim.list_lock );
630
631 dev_priv->prim.status[0] = dev_priv->primary->offset;
632 dev_priv->prim.status[1] = 0;
633
634 dev_priv->sarea_priv->last_wrap = 0;
635 dev_priv->sarea_priv->last_frame.head = 0;
636 dev_priv->sarea_priv->last_frame.wrap = 0;
637
638 if ( mga_freelist_init( dev, dev_priv ) < 0 ) {
639 DRM_ERROR( "could not initialize freelist\n" );
640
641 dev->dev_private = (void *)dev_priv;
642 mga_do_cleanup_dma( dev );
643 return -ENOMEM;
644 }
645
646
647 dev->dev_private = (void *)dev_priv;
648 return 0;
649}
650
651int mga_do_cleanup_dma( drm_device_t *dev )
652{
653 DRM_DEBUG( "%s\n", __FUNCTION__ );
654
655 if ( dev->dev_private ) {
656 drm_mga_private_t *dev_priv = dev->dev_private;
657
658 DRM_IOREMAPFREE( dev_priv->warp );
659 DRM_IOREMAPFREE( dev_priv->primary );
660 DRM_IOREMAPFREE( dev_priv->buffers );
661
662 if ( dev_priv->head != NULL ) {
663 mga_freelist_cleanup( dev );
664 }
665
666 DRM(free)( dev->dev_private, sizeof(drm_mga_private_t),
667 DRM_MEM_DRIVER );
668 dev->dev_private = NULL;
669 }
670
671 return 0;
672}
673
674int mga_dma_init( struct inode *inode, struct file *filp,
675 unsigned int cmd, unsigned long arg )
676{
677 drm_file_t *priv = filp->private_data;
678 drm_device_t *dev = priv->dev;
679 drm_mga_init_t init;
680
681 if ( copy_from_user( &init, (drm_mga_init_t *)arg, sizeof(init) ) )
682 return -EFAULT;
683
684 switch ( init.func ) {
685 case MGA_INIT_DMA:
686 return mga_do_init_dma( dev, &init );
687 case MGA_CLEANUP_DMA:
688 return mga_do_cleanup_dma( dev );
689 }
690
691 return -EINVAL;
692}
693
694
695
696
697
698
699int mga_dma_flush( struct inode *inode, struct file *filp,
700 unsigned int cmd, unsigned long arg )
701{
702 drm_file_t *priv = filp->private_data;
703 drm_device_t *dev = priv->dev;
704 drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
705 drm_lock_t lock;
706
707 LOCK_TEST_WITH_RETURN( dev );
708
709 if ( copy_from_user( &lock, (drm_lock_t *)arg, sizeof(lock) ) )
710 return -EFAULT;
711
712 DRM_DEBUG( "%s: %s%s%s\n",
713 __FUNCTION__,
714 (lock.flags & _DRM_LOCK_FLUSH) ? "flush, " : "",
715 (lock.flags & _DRM_LOCK_FLUSH_ALL) ? "flush all, " : "",
716 (lock.flags & _DRM_LOCK_QUIESCENT) ? "idle, " : "" );
717
718 WRAP_WAIT_WITH_RETURN( dev_priv );
719
720 if ( lock.flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL) ) {
721 mga_do_dma_flush( dev_priv );
722 }
723
724 if ( lock.flags & _DRM_LOCK_QUIESCENT ) {
725#if MGA_DMA_DEBUG
726 int ret = mga_do_wait_for_idle( dev_priv );
727 if ( ret < 0 )
728 DRM_INFO( __FUNCTION__": -EBUSY\n" );
729 return ret;
730#else
731 return mga_do_wait_for_idle( dev_priv );
732#endif
733 } else {
734 return 0;
735 }
736}
737
738int mga_dma_reset( struct inode *inode, struct file *filp,
739 unsigned int cmd, unsigned long arg )
740{
741 drm_file_t *priv = filp->private_data;
742 drm_device_t *dev = priv->dev;
743 drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
744
745 LOCK_TEST_WITH_RETURN( dev );
746
747 return mga_do_dma_reset( dev_priv );
748}
749
750
751
752
753
754
755static int mga_dma_get_buffers( drm_device_t *dev, drm_dma_t *d )
756{
757 drm_buf_t *buf;
758 int i;
759
760 for ( i = d->granted_count ; i < d->request_count ; i++ ) {
761 buf = mga_freelist_get( dev );
762 if ( !buf ) return -EAGAIN;
763
764 buf->pid = current->pid;
765
766 if ( copy_to_user( &d->request_indices[i],
767 &buf->idx, sizeof(buf->idx) ) )
768 return -EFAULT;
769 if ( copy_to_user( &d->request_sizes[i],
770 &buf->total, sizeof(buf->total) ) )
771 return -EFAULT;
772
773 d->granted_count++;
774 }
775 return 0;
776}
777
778int mga_dma_buffers( struct inode *inode, struct file *filp,
779 unsigned int cmd, unsigned long arg )
780{
781 drm_file_t *priv = filp->private_data;
782 drm_device_t *dev = priv->dev;
783 drm_device_dma_t *dma = dev->dma;
784 drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
785 drm_dma_t d;
786 int ret = 0;
787
788 LOCK_TEST_WITH_RETURN( dev );
789
790 if ( copy_from_user( &d, (drm_dma_t *)arg, sizeof(d) ) )
791 return -EFAULT;
792
793
794
795 if ( d.send_count != 0 ) {
796 DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",
797 current->pid, d.send_count );
798 return -EINVAL;
799 }
800
801
802
803 if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
804 DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n",
805 current->pid, d.request_count, dma->buf_count );
806 return -EINVAL;
807 }
808
809 WRAP_TEST_WITH_RETURN( dev_priv );
810
811 d.granted_count = 0;
812
813 if ( d.request_count ) {
814 ret = mga_dma_get_buffers( dev, &d );
815 }
816
817 if ( copy_to_user( (drm_dma_t *)arg, &d, sizeof(d) ) )
818 return -EFAULT;
819
820 return ret;
821}
822