aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm/mga_dma.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/drm/mga_dma.c')
-rw-r--r--drivers/char/drm/mga_dma.c612
1 files changed, 503 insertions, 109 deletions
diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c
index 832eaf8a5068..fc7d4a594bca 100644
--- a/drivers/char/drm/mga_dma.c
+++ b/drivers/char/drm/mga_dma.c
@@ -23,18 +23,21 @@
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 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 24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE. 25 * DEALINGS IN THE SOFTWARE.
26 * 26 */
27 * Authors: 27
28 * Rickard E. (Rik) Faith <faith@valinux.com> 28/**
29 * Jeff Hartmann <jhartmann@valinux.com> 29 * \file mga_dma.c
30 * Keith Whitwell <keith@tungstengraphics.com> 30 * DMA support for MGA G200 / G400.
31 * 31 *
32 * Rewritten by: 32 * \author Rickard E. (Rik) Faith <faith@valinux.com>
33 * Gareth Hughes <gareth@valinux.com> 33 * \author Jeff Hartmann <jhartmann@valinux.com>
34 * \author Keith Whitwell <keith@tungstengraphics.com>
35 * \author Gareth Hughes <gareth@valinux.com>
34 */ 36 */
35 37
36#include "drmP.h" 38#include "drmP.h"
37#include "drm.h" 39#include "drm.h"
40#include "drm_sarea.h"
38#include "mga_drm.h" 41#include "mga_drm.h"
39#include "mga_drv.h" 42#include "mga_drv.h"
40 43
@@ -148,7 +151,7 @@ void mga_do_dma_flush( drm_mga_private_t *dev_priv )
148 DRM_DEBUG( " space = 0x%06x\n", primary->space ); 151 DRM_DEBUG( " space = 0x%06x\n", primary->space );
149 152
150 mga_flush_write_combine(); 153 mga_flush_write_combine();
151 MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER ); 154 MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access);
152 155
153 DRM_DEBUG( "done.\n" ); 156 DRM_DEBUG( "done.\n" );
154} 157}
@@ -190,7 +193,7 @@ void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv )
190 DRM_DEBUG( " space = 0x%06x\n", primary->space ); 193 DRM_DEBUG( " space = 0x%06x\n", primary->space );
191 194
192 mga_flush_write_combine(); 195 mga_flush_write_combine();
193 MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER ); 196 MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access);
194 197
195 set_bit( 0, &primary->wrapped ); 198 set_bit( 0, &primary->wrapped );
196 DRM_DEBUG( "done.\n" ); 199 DRM_DEBUG( "done.\n" );
@@ -396,23 +399,390 @@ int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf )
396 * DMA initialization, cleanup 399 * DMA initialization, cleanup
397 */ 400 */
398 401
402
403int mga_driver_preinit(drm_device_t *dev, unsigned long flags)
404{
405 drm_mga_private_t * dev_priv;
406
407 dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
408 if (!dev_priv)
409 return DRM_ERR(ENOMEM);
410
411 dev->dev_private = (void *)dev_priv;
412 memset(dev_priv, 0, sizeof(drm_mga_private_t));
413
414 dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
415 dev_priv->chipset = flags;
416
417 return 0;
418}
419
420#if __OS_HAS_AGP
421/**
422 * Bootstrap the driver for AGP DMA.
423 *
424 * \todo
425 * Investigate whether there is any benifit to storing the WARP microcode in
426 * AGP memory. If not, the microcode may as well always be put in PCI
427 * memory.
428 *
429 * \todo
430 * This routine needs to set dma_bs->agp_mode to the mode actually configured
431 * in the hardware. Looking just at the Linux AGP driver code, I don't see
432 * an easy way to determine this.
433 *
434 * \sa mga_do_dma_bootstrap, mga_do_pci_dma_bootstrap
435 */
436static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
437 drm_mga_dma_bootstrap_t * dma_bs)
438{
439 drm_mga_private_t * const dev_priv = (drm_mga_private_t *) dev->dev_private;
440 const unsigned int warp_size = mga_warp_microcode_size(dev_priv);
441 int err;
442 unsigned offset;
443 const unsigned secondary_size = dma_bs->secondary_bin_count
444 * dma_bs->secondary_bin_size;
445 const unsigned agp_size = (dma_bs->agp_size << 20);
446 drm_buf_desc_t req;
447 drm_agp_mode_t mode;
448 drm_agp_info_t info;
449
450
451 /* Acquire AGP. */
452 err = drm_agp_acquire(dev);
453 if (err) {
454 DRM_ERROR("Unable to acquire AGP\n");
455 return err;
456 }
457
458 err = drm_agp_info(dev, &info);
459 if (err) {
460 DRM_ERROR("Unable to get AGP info\n");
461 return err;
462 }
463
464 mode.mode = (info.mode & ~0x07) | dma_bs->agp_mode;
465 err = drm_agp_enable(dev, mode);
466 if (err) {
467 DRM_ERROR("Unable to enable AGP (mode = 0x%lx)\n", mode.mode);
468 return err;
469 }
470
471
472 /* In addition to the usual AGP mode configuration, the G200 AGP cards
473 * need to have the AGP mode "manually" set.
474 */
475
476 if (dev_priv->chipset == MGA_CARD_TYPE_G200) {
477 if (mode.mode & 0x02) {
478 MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_ENABLE);
479 }
480 else {
481 MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_DISABLE);
482 }
483 }
484
485
486 /* Allocate and bind AGP memory. */
487 dev_priv->agp_pages = agp_size / PAGE_SIZE;
488 dev_priv->agp_mem = drm_alloc_agp( dev, dev_priv->agp_pages, 0 );
489 if (dev_priv->agp_mem == NULL) {
490 dev_priv->agp_pages = 0;
491 DRM_ERROR("Unable to allocate %uMB AGP memory\n",
492 dma_bs->agp_size);
493 return DRM_ERR(ENOMEM);
494 }
495
496 err = drm_bind_agp( dev_priv->agp_mem, 0 );
497 if (err) {
498 DRM_ERROR("Unable to bind AGP memory\n");
499 return err;
500 }
501
502 offset = 0;
503 err = drm_addmap( dev, offset, warp_size,
504 _DRM_AGP, _DRM_READ_ONLY, & dev_priv->warp );
505 if (err) {
506 DRM_ERROR("Unable to map WARP microcode\n");
507 return err;
508 }
509
510 offset += warp_size;
511 err = drm_addmap( dev, offset, dma_bs->primary_size,
512 _DRM_AGP, _DRM_READ_ONLY, & dev_priv->primary );
513 if (err) {
514 DRM_ERROR("Unable to map primary DMA region\n");
515 return err;
516 }
517
518 offset += dma_bs->primary_size;
519 err = drm_addmap( dev, offset, secondary_size,
520 _DRM_AGP, 0, & dev->agp_buffer_map );
521 if (err) {
522 DRM_ERROR("Unable to map secondary DMA region\n");
523 return err;
524 }
525
526 (void) memset( &req, 0, sizeof(req) );
527 req.count = dma_bs->secondary_bin_count;
528 req.size = dma_bs->secondary_bin_size;
529 req.flags = _DRM_AGP_BUFFER;
530 req.agp_start = offset;
531
532 err = drm_addbufs_agp( dev, & req );
533 if (err) {
534 DRM_ERROR("Unable to add secondary DMA buffers\n");
535 return err;
536 }
537
538 offset += secondary_size;
539 err = drm_addmap( dev, offset, agp_size - offset,
540 _DRM_AGP, 0, & dev_priv->agp_textures );
541 if (err) {
542 DRM_ERROR("Unable to map AGP texture region\n");
543 return err;
544 }
545
546 drm_core_ioremap(dev_priv->warp, dev);
547 drm_core_ioremap(dev_priv->primary, dev);
548 drm_core_ioremap(dev->agp_buffer_map, dev);
549
550 if (!dev_priv->warp->handle ||
551 !dev_priv->primary->handle || !dev->agp_buffer_map->handle) {
552 DRM_ERROR("failed to ioremap agp regions! (%p, %p, %p)\n",
553 dev_priv->warp->handle, dev_priv->primary->handle,
554 dev->agp_buffer_map->handle);
555 return DRM_ERR(ENOMEM);
556 }
557
558 dev_priv->dma_access = MGA_PAGPXFER;
559 dev_priv->wagp_enable = MGA_WAGP_ENABLE;
560
561 DRM_INFO("Initialized card for AGP DMA.\n");
562 return 0;
563}
564#else
565static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
566 drm_mga_dma_bootstrap_t * dma_bs)
567{
568 return -EINVAL;
569}
570#endif
571
572/**
573 * Bootstrap the driver for PCI DMA.
574 *
575 * \todo
576 * The algorithm for decreasing the size of the primary DMA buffer could be
577 * better. The size should be rounded up to the nearest page size, then
578 * decrease the request size by a single page each pass through the loop.
579 *
580 * \todo
581 * Determine whether the maximum address passed to drm_pci_alloc is correct.
582 * The same goes for drm_addbufs_pci.
583 *
584 * \sa mga_do_dma_bootstrap, mga_do_agp_dma_bootstrap
585 */
586static int mga_do_pci_dma_bootstrap(drm_device_t * dev,
587 drm_mga_dma_bootstrap_t * dma_bs)
588{
589 drm_mga_private_t * const dev_priv = (drm_mga_private_t *) dev->dev_private;
590 const unsigned int warp_size = mga_warp_microcode_size(dev_priv);
591 unsigned int primary_size;
592 unsigned int bin_count;
593 int err;
594 drm_buf_desc_t req;
595
596
597 if (dev->dma == NULL) {
598 DRM_ERROR("dev->dma is NULL\n");
599 return DRM_ERR(EFAULT);
600 }
601
602 /* The proper alignment is 0x100 for this mapping */
603 err = drm_addmap(dev, 0, warp_size, _DRM_CONSISTENT,
604 _DRM_READ_ONLY, &dev_priv->warp);
605 if (err != 0) {
606 DRM_ERROR("Unable to create mapping for WARP microcode\n");
607 return err;
608 }
609
610 /* Other than the bottom two bits being used to encode other
611 * information, there don't appear to be any restrictions on the
612 * alignment of the primary or secondary DMA buffers.
613 */
614
615 for ( primary_size = dma_bs->primary_size
616 ; primary_size != 0
617 ; primary_size >>= 1 ) {
618 /* The proper alignment for this mapping is 0x04 */
619 err = drm_addmap(dev, 0, primary_size, _DRM_CONSISTENT,
620 _DRM_READ_ONLY, &dev_priv->primary);
621 if (!err)
622 break;
623 }
624
625 if (err != 0) {
626 DRM_ERROR("Unable to allocate primary DMA region\n");
627 return DRM_ERR(ENOMEM);
628 }
629
630 if (dev_priv->primary->size != dma_bs->primary_size) {
631 DRM_INFO("Primary DMA buffer size reduced from %u to %u.\n",
632 dma_bs->primary_size,
633 (unsigned) dev_priv->primary->size);
634 dma_bs->primary_size = dev_priv->primary->size;
635 }
636
637 for ( bin_count = dma_bs->secondary_bin_count
638 ; bin_count > 0
639 ; bin_count-- ) {
640 (void) memset( &req, 0, sizeof(req) );
641 req.count = bin_count;
642 req.size = dma_bs->secondary_bin_size;
643
644 err = drm_addbufs_pci( dev, & req );
645 if (!err) {
646 break;
647 }
648 }
649
650 if (bin_count == 0) {
651 DRM_ERROR("Unable to add secondary DMA buffers\n");
652 return err;
653 }
654
655 if (bin_count != dma_bs->secondary_bin_count) {
656 DRM_INFO("Secondary PCI DMA buffer bin count reduced from %u "
657 "to %u.\n", dma_bs->secondary_bin_count, bin_count);
658
659 dma_bs->secondary_bin_count = bin_count;
660 }
661
662 dev_priv->dma_access = 0;
663 dev_priv->wagp_enable = 0;
664
665 dma_bs->agp_mode = 0;
666
667 DRM_INFO("Initialized card for PCI DMA.\n");
668 return 0;
669}
670
671
672static int mga_do_dma_bootstrap(drm_device_t * dev,
673 drm_mga_dma_bootstrap_t * dma_bs)
674{
675 const int is_agp = (dma_bs->agp_mode != 0) && drm_device_is_agp(dev);
676 int err;
677 drm_mga_private_t * const dev_priv =
678 (drm_mga_private_t *) dev->dev_private;
679
680
681 dev_priv->used_new_dma_init = 1;
682
683 /* The first steps are the same for both PCI and AGP based DMA. Map
684 * the cards MMIO registers and map a status page.
685 */
686 err = drm_addmap( dev, dev_priv->mmio_base, dev_priv->mmio_size,
687 _DRM_REGISTERS, _DRM_READ_ONLY, & dev_priv->mmio );
688 if (err) {
689 DRM_ERROR("Unable to map MMIO region\n");
690 return err;
691 }
692
693
694 err = drm_addmap( dev, 0, SAREA_MAX, _DRM_SHM,
695 _DRM_READ_ONLY | _DRM_LOCKED | _DRM_KERNEL,
696 & dev_priv->status );
697 if (err) {
698 DRM_ERROR("Unable to map status region\n");
699 return err;
700 }
701
702
703 /* The DMA initialization procedure is slightly different for PCI and
704 * AGP cards. AGP cards just allocate a large block of AGP memory and
705 * carve off portions of it for internal uses. The remaining memory
706 * is returned to user-mode to be used for AGP textures.
707 */
708 if (is_agp) {
709 err = mga_do_agp_dma_bootstrap(dev, dma_bs);
710 }
711
712 /* If we attempted to initialize the card for AGP DMA but failed,
713 * clean-up any mess that may have been created.
714 */
715
716 if (err) {
717 mga_do_cleanup_dma(dev);
718 }
719
720
721 /* Not only do we want to try and initialized PCI cards for PCI DMA,
722 * but we also try to initialized AGP cards that could not be
723 * initialized for AGP DMA. This covers the case where we have an AGP
724 * card in a system with an unsupported AGP chipset. In that case the
725 * card will be detected as AGP, but we won't be able to allocate any
726 * AGP memory, etc.
727 */
728
729 if (!is_agp || err) {
730 err = mga_do_pci_dma_bootstrap(dev, dma_bs);
731 }
732
733
734 return err;
735}
736
737int mga_dma_bootstrap(DRM_IOCTL_ARGS)
738{
739 DRM_DEVICE;
740 drm_mga_dma_bootstrap_t bootstrap;
741 int err;
742
743
744 DRM_COPY_FROM_USER_IOCTL(bootstrap,
745 (drm_mga_dma_bootstrap_t __user *) data,
746 sizeof(bootstrap));
747
748 err = mga_do_dma_bootstrap(dev, & bootstrap);
749 if (! err) {
750 static const int modes[] = { 0, 1, 2, 2, 4, 4, 4, 4 };
751 const drm_mga_private_t * const dev_priv =
752 (drm_mga_private_t *) dev->dev_private;
753
754 if (dev_priv->agp_textures != NULL) {
755 bootstrap.texture_handle = dev_priv->agp_textures->offset;
756 bootstrap.texture_size = dev_priv->agp_textures->size;
757 }
758 else {
759 bootstrap.texture_handle = 0;
760 bootstrap.texture_size = 0;
761 }
762
763 bootstrap.agp_mode = modes[ bootstrap.agp_mode & 0x07 ];
764 if (DRM_COPY_TO_USER( (void __user *) data, & bootstrap,
765 sizeof(bootstrap))) {
766 err = DRM_ERR(EFAULT);
767 }
768 }
769 else {
770 mga_do_cleanup_dma(dev);
771 }
772
773 return err;
774}
775
399static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) 776static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
400{ 777{
401 drm_mga_private_t *dev_priv; 778 drm_mga_private_t *dev_priv;
402 int ret; 779 int ret;
403 DRM_DEBUG( "\n" ); 780 DRM_DEBUG( "\n" );
404 781
405 dev_priv = drm_alloc( sizeof(drm_mga_private_t), DRM_MEM_DRIVER );
406 if ( !dev_priv )
407 return DRM_ERR(ENOMEM);
408
409 memset( dev_priv, 0, sizeof(drm_mga_private_t) );
410 782
411 dev_priv->chipset = init->chipset; 783 dev_priv = dev->dev_private;
412 784
413 dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT; 785 if (init->sgram) {
414
415 if ( init->sgram ) {
416 dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK; 786 dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK;
417 } else { 787 } else {
418 dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR; 788 dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR;
@@ -436,88 +806,66 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
436 806
437 DRM_GETSAREA(); 807 DRM_GETSAREA();
438 808
439 if(!dev_priv->sarea) { 809 if (!dev_priv->sarea) {
440 DRM_ERROR( "failed to find sarea!\n" ); 810 DRM_ERROR("failed to find sarea!\n");
441 /* Assign dev_private so we can do cleanup. */
442 dev->dev_private = (void *)dev_priv;
443 mga_do_cleanup_dma( dev );
444 return DRM_ERR(EINVAL); 811 return DRM_ERR(EINVAL);
445 } 812 }
446 813
447 dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset); 814 if (! dev_priv->used_new_dma_init) {
448 if(!dev_priv->mmio) { 815 dev_priv->status = drm_core_findmap(dev, init->status_offset);
449 DRM_ERROR( "failed to find mmio region!\n" ); 816 if (!dev_priv->status) {
450 /* Assign dev_private so we can do cleanup. */ 817 DRM_ERROR("failed to find status page!\n");
451 dev->dev_private = (void *)dev_priv; 818 return DRM_ERR(EINVAL);
452 mga_do_cleanup_dma( dev ); 819 }
453 return DRM_ERR(EINVAL); 820 dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
454 } 821 if (!dev_priv->mmio) {
455 dev_priv->status = drm_core_findmap(dev, init->status_offset); 822 DRM_ERROR("failed to find mmio region!\n");
456 if(!dev_priv->status) { 823 return DRM_ERR(EINVAL);
457 DRM_ERROR( "failed to find status page!\n" ); 824 }
458 /* Assign dev_private so we can do cleanup. */ 825 dev_priv->warp = drm_core_findmap(dev, init->warp_offset);
459 dev->dev_private = (void *)dev_priv; 826 if (!dev_priv->warp) {
460 mga_do_cleanup_dma( dev ); 827 DRM_ERROR("failed to find warp microcode region!\n");
461 return DRM_ERR(EINVAL); 828 return DRM_ERR(EINVAL);
462 } 829 }
463 dev_priv->warp = drm_core_findmap(dev, init->warp_offset); 830 dev_priv->primary = drm_core_findmap(dev, init->primary_offset);
464 if(!dev_priv->warp) { 831 if (!dev_priv->primary) {
465 DRM_ERROR( "failed to find warp microcode region!\n" ); 832 DRM_ERROR("failed to find primary dma region!\n");
466 /* Assign dev_private so we can do cleanup. */ 833 return DRM_ERR(EINVAL);
467 dev->dev_private = (void *)dev_priv; 834 }
468 mga_do_cleanup_dma( dev ); 835 dev->agp_buffer_token = init->buffers_offset;
469 return DRM_ERR(EINVAL); 836 dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
470 } 837 if (!dev->agp_buffer_map) {
471 dev_priv->primary = drm_core_findmap(dev, init->primary_offset); 838 DRM_ERROR("failed to find dma buffer region!\n");
472 if(!dev_priv->primary) { 839 return DRM_ERR(EINVAL);
473 DRM_ERROR( "failed to find primary dma region!\n" ); 840 }
474 /* Assign dev_private so we can do cleanup. */ 841
475 dev->dev_private = (void *)dev_priv; 842 drm_core_ioremap(dev_priv->warp, dev);
476 mga_do_cleanup_dma( dev ); 843 drm_core_ioremap(dev_priv->primary, dev);
477 return DRM_ERR(EINVAL); 844 drm_core_ioremap(dev->agp_buffer_map, dev);
478 }
479 dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
480 if(!dev->agp_buffer_map) {
481 DRM_ERROR( "failed to find dma buffer region!\n" );
482 /* Assign dev_private so we can do cleanup. */
483 dev->dev_private = (void *)dev_priv;
484 mga_do_cleanup_dma( dev );
485 return DRM_ERR(EINVAL);
486 } 845 }
487 846
488 dev_priv->sarea_priv = 847 dev_priv->sarea_priv =
489 (drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle + 848 (drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle +
490 init->sarea_priv_offset); 849 init->sarea_priv_offset);
491 850
492 drm_core_ioremap( dev_priv->warp, dev ); 851 if (!dev_priv->warp->handle ||
493 drm_core_ioremap( dev_priv->primary, dev ); 852 !dev_priv->primary->handle ||
494 drm_core_ioremap( dev->agp_buffer_map, dev ); 853 ((dev_priv->dma_access != 0) &&
495 854 ((dev->agp_buffer_map == NULL) ||
496 if(!dev_priv->warp->handle || 855 (dev->agp_buffer_map->handle == NULL)))) {
497 !dev_priv->primary->handle || 856 DRM_ERROR("failed to ioremap agp regions!\n");
498 !dev->agp_buffer_map->handle ) {
499 DRM_ERROR( "failed to ioremap agp regions!\n" );
500 /* Assign dev_private so we can do cleanup. */
501 dev->dev_private = (void *)dev_priv;
502 mga_do_cleanup_dma( dev );
503 return DRM_ERR(ENOMEM); 857 return DRM_ERR(ENOMEM);
504 } 858 }
505 859
506 ret = mga_warp_install_microcode( dev_priv ); 860 ret = mga_warp_install_microcode(dev_priv);
507 if ( ret < 0 ) { 861 if (ret < 0) {
508 DRM_ERROR( "failed to install WARP ucode!\n" ); 862 DRM_ERROR("failed to install WARP ucode!\n");
509 /* Assign dev_private so we can do cleanup. */
510 dev->dev_private = (void *)dev_priv;
511 mga_do_cleanup_dma( dev );
512 return ret; 863 return ret;
513 } 864 }
514 865
515 ret = mga_warp_init( dev_priv ); 866 ret = mga_warp_init(dev_priv);
516 if ( ret < 0 ) { 867 if (ret < 0) {
517 DRM_ERROR( "failed to init WARP engine!\n" ); 868 DRM_ERROR("failed to init WARP engine!\n");
518 /* Assign dev_private so we can do cleanup. */
519 dev->dev_private = (void *)dev_priv;
520 mga_do_cleanup_dma( dev );
521 return ret; 869 return ret;
522 } 870 }
523 871
@@ -557,22 +905,18 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
557 dev_priv->sarea_priv->last_frame.head = 0; 905 dev_priv->sarea_priv->last_frame.head = 0;
558 dev_priv->sarea_priv->last_frame.wrap = 0; 906 dev_priv->sarea_priv->last_frame.wrap = 0;
559 907
560 if ( mga_freelist_init( dev, dev_priv ) < 0 ) { 908 if (mga_freelist_init(dev, dev_priv) < 0) {
561 DRM_ERROR( "could not initialize freelist\n" ); 909 DRM_ERROR("could not initialize freelist\n");
562 /* Assign dev_private so we can do cleanup. */
563 dev->dev_private = (void *)dev_priv;
564 mga_do_cleanup_dma( dev );
565 return DRM_ERR(ENOMEM); 910 return DRM_ERR(ENOMEM);
566 } 911 }
567 912
568 /* Make dev_private visable to others. */
569 dev->dev_private = (void *)dev_priv;
570 return 0; 913 return 0;
571} 914}
572 915
573static int mga_do_cleanup_dma( drm_device_t *dev ) 916static int mga_do_cleanup_dma( drm_device_t *dev )
574{ 917{
575 DRM_DEBUG( "\n" ); 918 int err = 0;
919 DRM_DEBUG("\n");
576 920
577 /* Make sure interrupts are disabled here because the uninstall ioctl 921 /* Make sure interrupts are disabled here because the uninstall ioctl
578 * may not have been called from userspace and after dev_private 922 * may not have been called from userspace and after dev_private
@@ -583,37 +927,73 @@ static int mga_do_cleanup_dma( drm_device_t *dev )
583 if ( dev->dev_private ) { 927 if ( dev->dev_private ) {
584 drm_mga_private_t *dev_priv = dev->dev_private; 928 drm_mga_private_t *dev_priv = dev->dev_private;
585 929
586 if ( dev_priv->warp != NULL ) 930 if ((dev_priv->warp != NULL)
587 drm_core_ioremapfree( dev_priv->warp, dev ); 931 && (dev_priv->mmio->type != _DRM_CONSISTENT))
588 if ( dev_priv->primary != NULL ) 932 drm_core_ioremapfree(dev_priv->warp, dev);
589 drm_core_ioremapfree( dev_priv->primary, dev ); 933
590 if ( dev->agp_buffer_map != NULL ) 934 if ((dev_priv->primary != NULL)
591 drm_core_ioremapfree( dev->agp_buffer_map, dev ); 935 && (dev_priv->primary->type != _DRM_CONSISTENT))
936 drm_core_ioremapfree(dev_priv->primary, dev);
937
938 if (dev->agp_buffer_map != NULL)
939 drm_core_ioremapfree(dev->agp_buffer_map, dev);
592 940
593 if ( dev_priv->head != NULL ) { 941 if (dev_priv->used_new_dma_init) {
594 mga_freelist_cleanup( dev ); 942#if __OS_HAS_AGP
943 if (dev_priv->agp_mem != NULL) {
944 dev_priv->agp_textures = NULL;
945 drm_unbind_agp(dev_priv->agp_mem);
946
947 drm_free_agp(dev_priv->agp_mem, dev_priv->agp_pages);
948 dev_priv->agp_pages = 0;
949 dev_priv->agp_mem = NULL;
950 }
951
952 if ((dev->agp != NULL) && dev->agp->acquired) {
953 err = drm_agp_release(dev);
954 }
955#endif
956 dev_priv->used_new_dma_init = 0;
595 } 957 }
596 958
597 drm_free( dev->dev_private, sizeof(drm_mga_private_t), 959 dev_priv->warp = NULL;
598 DRM_MEM_DRIVER ); 960 dev_priv->primary = NULL;
599 dev->dev_private = NULL; 961 dev_priv->mmio = NULL;
962 dev_priv->status = NULL;
963 dev_priv->sarea = NULL;
964 dev_priv->sarea_priv = NULL;
965 dev->agp_buffer_map = NULL;
966
967 memset(&dev_priv->prim, 0, sizeof(dev_priv->prim));
968 dev_priv->warp_pipe = 0;
969 memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
970
971 if (dev_priv->head != NULL) {
972 mga_freelist_cleanup(dev);
973 }
600 } 974 }
601 975
602 return 0; 976 return err;
603} 977}
604 978
605int mga_dma_init( DRM_IOCTL_ARGS ) 979int mga_dma_init( DRM_IOCTL_ARGS )
606{ 980{
607 DRM_DEVICE; 981 DRM_DEVICE;
608 drm_mga_init_t init; 982 drm_mga_init_t init;
983 int err;
609 984
610 LOCK_TEST_WITH_RETURN( dev, filp ); 985 LOCK_TEST_WITH_RETURN( dev, filp );
611 986
612 DRM_COPY_FROM_USER_IOCTL( init, (drm_mga_init_t __user *)data, sizeof(init) ); 987 DRM_COPY_FROM_USER_IOCTL(init, (drm_mga_init_t __user *) data,
988 sizeof(init));
613 989
614 switch ( init.func ) { 990 switch ( init.func ) {
615 case MGA_INIT_DMA: 991 case MGA_INIT_DMA:
616 return mga_do_init_dma( dev, &init ); 992 err = mga_do_init_dma(dev, &init);
993 if (err) {
994 (void) mga_do_cleanup_dma(dev);
995 }
996 return err;
617 case MGA_CLEANUP_DMA: 997 case MGA_CLEANUP_DMA:
618 return mga_do_cleanup_dma( dev ); 998 return mga_do_cleanup_dma( dev );
619 } 999 }
@@ -742,7 +1122,21 @@ int mga_dma_buffers( DRM_IOCTL_ARGS )
742 return ret; 1122 return ret;
743} 1123}
744 1124
745void mga_driver_pretakedown(drm_device_t *dev) 1125/**
1126 * Called just before the module is unloaded.
1127 */
1128int mga_driver_postcleanup(drm_device_t * dev)
1129{
1130 drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
1131 dev->dev_private = NULL;
1132
1133 return 0;
1134}
1135
1136/**
1137 * Called when the last opener of the device is closed.
1138 */
1139void mga_driver_pretakedown(drm_device_t * dev)
746{ 1140{
747 mga_do_cleanup_dma( dev ); 1141 mga_do_cleanup_dma( dev );
748} 1142}