diff options
Diffstat (limited to 'drivers/char/drm')
-rw-r--r-- | drivers/char/drm/Kconfig | 2 | ||||
-rw-r--r-- | drivers/char/drm/mga_dma.c | 601 | ||||
-rw-r--r-- | drivers/char/drm/mga_drm.h | 95 | ||||
-rw-r--r-- | drivers/char/drm/mga_drv.h | 96 | ||||
-rw-r--r-- | drivers/char/drm/mga_irq.c | 72 | ||||
-rw-r--r-- | drivers/char/drm/mga_state.c | 158 | ||||
-rw-r--r-- | drivers/char/drm/mga_warp.c | 141 |
7 files changed, 888 insertions, 277 deletions
diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig index 123417e43040..d6c50312aec6 100644 --- a/drivers/char/drm/Kconfig +++ b/drivers/char/drm/Kconfig | |||
@@ -82,7 +82,7 @@ endchoice | |||
82 | 82 | ||
83 | config DRM_MGA | 83 | config DRM_MGA |
84 | tristate "Matrox g200/g400" | 84 | tristate "Matrox g200/g400" |
85 | depends on DRM && AGP | 85 | depends on DRM |
86 | help | 86 | help |
87 | Choose this option if you have a Matrox G200, G400 or G450 graphics | 87 | Choose this option if you have a Matrox G200, G400 or G450 graphics |
88 | card. If M is selected, the module will be called mga. AGP | 88 | card. If M is selected, the module will be called mga. AGP |
diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c index 832eaf8a5068..7899e281d062 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,383 @@ 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 | |||
403 | int 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 | /** | ||
421 | * Bootstrap the driver for AGP DMA. | ||
422 | * | ||
423 | * \todo | ||
424 | * Investigate whether there is any benifit to storing the WARP microcode in | ||
425 | * AGP memory. If not, the microcode may as well always be put in PCI | ||
426 | * memory. | ||
427 | * | ||
428 | * \todo | ||
429 | * This routine needs to set dma_bs->agp_mode to the mode actually configured | ||
430 | * in the hardware. Looking just at the Linux AGP driver code, I don't see | ||
431 | * an easy way to determine this. | ||
432 | * | ||
433 | * \sa mga_do_dma_bootstrap, mga_do_pci_dma_bootstrap | ||
434 | */ | ||
435 | static int mga_do_agp_dma_bootstrap(drm_device_t * dev, | ||
436 | drm_mga_dma_bootstrap_t * dma_bs) | ||
437 | { | ||
438 | drm_mga_private_t * const dev_priv = (drm_mga_private_t *) dev->dev_private; | ||
439 | const unsigned int warp_size = mga_warp_microcode_size(dev_priv); | ||
440 | int err; | ||
441 | unsigned offset; | ||
442 | const unsigned secondary_size = dma_bs->secondary_bin_count | ||
443 | * dma_bs->secondary_bin_size; | ||
444 | const unsigned agp_size = (dma_bs->agp_size << 20); | ||
445 | drm_buf_desc_t req; | ||
446 | drm_agp_mode_t mode; | ||
447 | drm_agp_info_t info; | ||
448 | |||
449 | |||
450 | /* Acquire AGP. */ | ||
451 | err = drm_agp_acquire(dev); | ||
452 | if (err) { | ||
453 | DRM_ERROR("Unable to acquire AGP\n"); | ||
454 | return err; | ||
455 | } | ||
456 | |||
457 | err = drm_agp_info(dev, &info); | ||
458 | if (err) { | ||
459 | DRM_ERROR("Unable to get AGP info\n"); | ||
460 | return err; | ||
461 | } | ||
462 | |||
463 | mode.mode = (info.mode & ~0x07) | dma_bs->agp_mode; | ||
464 | err = drm_agp_enable(dev, mode); | ||
465 | if (err) { | ||
466 | DRM_ERROR("Unable to enable AGP (mode = 0x%lx)\n", mode.mode); | ||
467 | return err; | ||
468 | } | ||
469 | |||
470 | |||
471 | /* In addition to the usual AGP mode configuration, the G200 AGP cards | ||
472 | * need to have the AGP mode "manually" set. | ||
473 | */ | ||
474 | |||
475 | if (dev_priv->chipset == MGA_CARD_TYPE_G200) { | ||
476 | if (mode.mode & 0x02) { | ||
477 | MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_ENABLE); | ||
478 | } | ||
479 | else { | ||
480 | MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_DISABLE); | ||
481 | } | ||
482 | } | ||
483 | |||
484 | |||
485 | /* Allocate and bind AGP memory. */ | ||
486 | dev_priv->agp_pages = agp_size / PAGE_SIZE; | ||
487 | dev_priv->agp_mem = drm_alloc_agp( dev, dev_priv->agp_pages, 0 ); | ||
488 | if (dev_priv->agp_mem == NULL) { | ||
489 | dev_priv->agp_pages = 0; | ||
490 | DRM_ERROR("Unable to allocate %uMB AGP memory\n", | ||
491 | dma_bs->agp_size); | ||
492 | return DRM_ERR(ENOMEM); | ||
493 | } | ||
494 | |||
495 | err = drm_bind_agp( dev_priv->agp_mem, 0 ); | ||
496 | if (err) { | ||
497 | DRM_ERROR("Unable to bind AGP memory\n"); | ||
498 | return err; | ||
499 | } | ||
500 | |||
501 | offset = 0; | ||
502 | err = drm_addmap( dev, offset, warp_size, | ||
503 | _DRM_AGP, _DRM_READ_ONLY, & dev_priv->warp ); | ||
504 | if (err) { | ||
505 | DRM_ERROR("Unable to map WARP microcode\n"); | ||
506 | return err; | ||
507 | } | ||
508 | |||
509 | offset += warp_size; | ||
510 | err = drm_addmap( dev, offset, dma_bs->primary_size, | ||
511 | _DRM_AGP, _DRM_READ_ONLY, & dev_priv->primary ); | ||
512 | if (err) { | ||
513 | DRM_ERROR("Unable to map primary DMA region\n"); | ||
514 | return err; | ||
515 | } | ||
516 | |||
517 | offset += dma_bs->primary_size; | ||
518 | err = drm_addmap( dev, offset, secondary_size, | ||
519 | _DRM_AGP, 0, & dev->agp_buffer_map ); | ||
520 | if (err) { | ||
521 | DRM_ERROR("Unable to map secondary DMA region\n"); | ||
522 | return err; | ||
523 | } | ||
524 | |||
525 | (void) memset( &req, 0, sizeof(req) ); | ||
526 | req.count = dma_bs->secondary_bin_count; | ||
527 | req.size = dma_bs->secondary_bin_size; | ||
528 | req.flags = _DRM_AGP_BUFFER; | ||
529 | req.agp_start = offset; | ||
530 | |||
531 | err = drm_addbufs_agp( dev, & req ); | ||
532 | if (err) { | ||
533 | DRM_ERROR("Unable to add secondary DMA buffers\n"); | ||
534 | return err; | ||
535 | } | ||
536 | |||
537 | offset += secondary_size; | ||
538 | err = drm_addmap( dev, offset, agp_size - offset, | ||
539 | _DRM_AGP, 0, & dev_priv->agp_textures ); | ||
540 | if (err) { | ||
541 | DRM_ERROR("Unable to map AGP texture region\n"); | ||
542 | return err; | ||
543 | } | ||
544 | |||
545 | drm_core_ioremap(dev_priv->warp, dev); | ||
546 | drm_core_ioremap(dev_priv->primary, dev); | ||
547 | drm_core_ioremap(dev->agp_buffer_map, dev); | ||
548 | |||
549 | if (!dev_priv->warp->handle || | ||
550 | !dev_priv->primary->handle || !dev->agp_buffer_map->handle) { | ||
551 | DRM_ERROR("failed to ioremap agp regions! (%p, %p, %p)\n", | ||
552 | dev_priv->warp->handle, dev_priv->primary->handle, | ||
553 | dev->agp_buffer_map->handle); | ||
554 | return DRM_ERR(ENOMEM); | ||
555 | } | ||
556 | |||
557 | dev_priv->dma_access = MGA_PAGPXFER; | ||
558 | dev_priv->wagp_enable = MGA_WAGP_ENABLE; | ||
559 | |||
560 | DRM_INFO("Initialized card for AGP DMA.\n"); | ||
561 | return 0; | ||
562 | } | ||
563 | |||
564 | /** | ||
565 | * Bootstrap the driver for PCI DMA. | ||
566 | * | ||
567 | * \todo | ||
568 | * The algorithm for decreasing the size of the primary DMA buffer could be | ||
569 | * better. The size should be rounded up to the nearest page size, then | ||
570 | * decrease the request size by a single page each pass through the loop. | ||
571 | * | ||
572 | * \todo | ||
573 | * Determine whether the maximum address passed to drm_pci_alloc is correct. | ||
574 | * The same goes for drm_addbufs_pci. | ||
575 | * | ||
576 | * \sa mga_do_dma_bootstrap, mga_do_agp_dma_bootstrap | ||
577 | */ | ||
578 | static int mga_do_pci_dma_bootstrap(drm_device_t * dev, | ||
579 | drm_mga_dma_bootstrap_t * dma_bs) | ||
580 | { | ||
581 | drm_mga_private_t * const dev_priv = (drm_mga_private_t *) dev->dev_private; | ||
582 | const unsigned int warp_size = mga_warp_microcode_size(dev_priv); | ||
583 | unsigned int primary_size; | ||
584 | unsigned int bin_count; | ||
585 | int err; | ||
586 | drm_buf_desc_t req; | ||
587 | |||
588 | |||
589 | if (dev->dma == NULL) { | ||
590 | DRM_ERROR("dev->dma is NULL\n"); | ||
591 | return DRM_ERR(EFAULT); | ||
592 | } | ||
593 | |||
594 | /* The proper alignment is 0x100 for this mapping */ | ||
595 | err = drm_addmap(dev, 0, warp_size, _DRM_CONSISTENT, | ||
596 | _DRM_READ_ONLY, &dev_priv->warp); | ||
597 | if (err != 0) { | ||
598 | DRM_ERROR("Unable to create mapping for WARP microcode\n"); | ||
599 | return err; | ||
600 | } | ||
601 | |||
602 | /* Other than the bottom two bits being used to encode other | ||
603 | * information, there don't appear to be any restrictions on the | ||
604 | * alignment of the primary or secondary DMA buffers. | ||
605 | */ | ||
606 | |||
607 | for ( primary_size = dma_bs->primary_size | ||
608 | ; primary_size != 0 | ||
609 | ; primary_size >>= 1 ) { | ||
610 | /* The proper alignment for this mapping is 0x04 */ | ||
611 | err = drm_addmap(dev, 0, primary_size, _DRM_CONSISTENT, | ||
612 | _DRM_READ_ONLY, &dev_priv->primary); | ||
613 | if (!err) | ||
614 | break; | ||
615 | } | ||
616 | |||
617 | if (err != 0) { | ||
618 | DRM_ERROR("Unable to allocate primary DMA region\n"); | ||
619 | return DRM_ERR(ENOMEM); | ||
620 | } | ||
621 | |||
622 | if (dev_priv->primary->size != dma_bs->primary_size) { | ||
623 | DRM_INFO("Primary DMA buffer size reduced from %u to %u.\n", | ||
624 | dma_bs->primary_size, | ||
625 | (unsigned) dev_priv->primary->size); | ||
626 | dma_bs->primary_size = dev_priv->primary->size; | ||
627 | } | ||
628 | |||
629 | for ( bin_count = dma_bs->secondary_bin_count | ||
630 | ; bin_count > 0 | ||
631 | ; bin_count-- ) { | ||
632 | (void) memset( &req, 0, sizeof(req) ); | ||
633 | req.count = bin_count; | ||
634 | req.size = dma_bs->secondary_bin_size; | ||
635 | |||
636 | err = drm_addbufs_pci( dev, & req ); | ||
637 | if (!err) { | ||
638 | break; | ||
639 | } | ||
640 | } | ||
641 | |||
642 | if (bin_count == 0) { | ||
643 | DRM_ERROR("Unable to add secondary DMA buffers\n"); | ||
644 | return err; | ||
645 | } | ||
646 | |||
647 | if (bin_count != dma_bs->secondary_bin_count) { | ||
648 | DRM_INFO("Secondary PCI DMA buffer bin count reduced from %u " | ||
649 | "to %u.\n", dma_bs->secondary_bin_count, bin_count); | ||
650 | |||
651 | dma_bs->secondary_bin_count = bin_count; | ||
652 | } | ||
653 | |||
654 | dev_priv->dma_access = 0; | ||
655 | dev_priv->wagp_enable = 0; | ||
656 | |||
657 | dma_bs->agp_mode = 0; | ||
658 | |||
659 | DRM_INFO("Initialized card for PCI DMA.\n"); | ||
660 | return 0; | ||
661 | } | ||
662 | |||
663 | |||
664 | static int mga_do_dma_bootstrap(drm_device_t * dev, | ||
665 | drm_mga_dma_bootstrap_t * dma_bs) | ||
666 | { | ||
667 | const int is_agp = (dma_bs->agp_mode != 0) && drm_device_is_agp(dev); | ||
668 | int err; | ||
669 | drm_mga_private_t * const dev_priv = | ||
670 | (drm_mga_private_t *) dev->dev_private; | ||
671 | |||
672 | |||
673 | dev_priv->used_new_dma_init = 1; | ||
674 | |||
675 | /* The first steps are the same for both PCI and AGP based DMA. Map | ||
676 | * the cards MMIO registers and map a status page. | ||
677 | */ | ||
678 | err = drm_addmap( dev, dev_priv->mmio_base, dev_priv->mmio_size, | ||
679 | _DRM_REGISTERS, _DRM_READ_ONLY, & dev_priv->mmio ); | ||
680 | if (err) { | ||
681 | DRM_ERROR("Unable to map MMIO region\n"); | ||
682 | return err; | ||
683 | } | ||
684 | |||
685 | |||
686 | err = drm_addmap( dev, 0, SAREA_MAX, _DRM_SHM, | ||
687 | _DRM_READ_ONLY | _DRM_LOCKED | _DRM_KERNEL, | ||
688 | & dev_priv->status ); | ||
689 | if (err) { | ||
690 | DRM_ERROR("Unable to map status region\n"); | ||
691 | return err; | ||
692 | } | ||
693 | |||
694 | |||
695 | /* The DMA initialization procedure is slightly different for PCI and | ||
696 | * AGP cards. AGP cards just allocate a large block of AGP memory and | ||
697 | * carve off portions of it for internal uses. The remaining memory | ||
698 | * is returned to user-mode to be used for AGP textures. | ||
699 | */ | ||
700 | |||
701 | if (is_agp) { | ||
702 | err = mga_do_agp_dma_bootstrap(dev, dma_bs); | ||
703 | } | ||
704 | |||
705 | /* If we attempted to initialize the card for AGP DMA but failed, | ||
706 | * clean-up any mess that may have been created. | ||
707 | */ | ||
708 | |||
709 | if (err) { | ||
710 | mga_do_cleanup_dma(dev); | ||
711 | } | ||
712 | |||
713 | |||
714 | /* Not only do we want to try and initialized PCI cards for PCI DMA, | ||
715 | * but we also try to initialized AGP cards that could not be | ||
716 | * initialized for AGP DMA. This covers the case where we have an AGP | ||
717 | * card in a system with an unsupported AGP chipset. In that case the | ||
718 | * card will be detected as AGP, but we won't be able to allocate any | ||
719 | * AGP memory, etc. | ||
720 | */ | ||
721 | |||
722 | if (!is_agp || err) { | ||
723 | err = mga_do_pci_dma_bootstrap(dev, dma_bs); | ||
724 | } | ||
725 | |||
726 | |||
727 | return err; | ||
728 | } | ||
729 | |||
730 | int mga_dma_bootstrap(DRM_IOCTL_ARGS) | ||
731 | { | ||
732 | DRM_DEVICE; | ||
733 | drm_mga_dma_bootstrap_t bootstrap; | ||
734 | int err; | ||
735 | |||
736 | |||
737 | DRM_COPY_FROM_USER_IOCTL(bootstrap, | ||
738 | (drm_mga_dma_bootstrap_t __user *) data, | ||
739 | sizeof(bootstrap)); | ||
740 | |||
741 | err = mga_do_dma_bootstrap(dev, & bootstrap); | ||
742 | if (! err) { | ||
743 | static const int modes[] = { 0, 1, 2, 2, 4, 4, 4, 4 }; | ||
744 | const drm_mga_private_t * const dev_priv = | ||
745 | (drm_mga_private_t *) dev->dev_private; | ||
746 | |||
747 | if (dev_priv->agp_textures != NULL) { | ||
748 | bootstrap.texture_handle = dev_priv->agp_textures->offset; | ||
749 | bootstrap.texture_size = dev_priv->agp_textures->size; | ||
750 | } | ||
751 | else { | ||
752 | bootstrap.texture_handle = 0; | ||
753 | bootstrap.texture_size = 0; | ||
754 | } | ||
755 | |||
756 | bootstrap.agp_mode = modes[ bootstrap.agp_mode & 0x07 ]; | ||
757 | if (DRM_COPY_TO_USER( (void __user *) data, & bootstrap, | ||
758 | sizeof(bootstrap))) { | ||
759 | err = DRM_ERR(EFAULT); | ||
760 | } | ||
761 | } | ||
762 | else { | ||
763 | mga_do_cleanup_dma(dev); | ||
764 | } | ||
765 | |||
766 | return err; | ||
767 | } | ||
768 | |||
399 | static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) | 769 | static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) |
400 | { | 770 | { |
401 | drm_mga_private_t *dev_priv; | 771 | drm_mga_private_t *dev_priv; |
402 | int ret; | 772 | int ret; |
403 | DRM_DEBUG( "\n" ); | 773 | DRM_DEBUG( "\n" ); |
404 | 774 | ||
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 | 775 | ||
411 | dev_priv->chipset = init->chipset; | 776 | dev_priv = dev->dev_private; |
412 | 777 | ||
413 | dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT; | 778 | if (init->sgram) { |
414 | |||
415 | if ( init->sgram ) { | ||
416 | dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK; | 779 | dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK; |
417 | } else { | 780 | } else { |
418 | dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR; | 781 | dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR; |
@@ -436,88 +799,65 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) | |||
436 | 799 | ||
437 | DRM_GETSAREA(); | 800 | DRM_GETSAREA(); |
438 | 801 | ||
439 | if(!dev_priv->sarea) { | 802 | if (!dev_priv->sarea) { |
440 | DRM_ERROR( "failed to find sarea!\n" ); | 803 | 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); | 804 | return DRM_ERR(EINVAL); |
445 | } | 805 | } |
446 | 806 | ||
447 | dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset); | 807 | if (! dev_priv->used_new_dma_init) { |
448 | if(!dev_priv->mmio) { | 808 | dev_priv->status = drm_core_findmap(dev, init->status_offset); |
449 | DRM_ERROR( "failed to find mmio region!\n" ); | 809 | if (!dev_priv->status) { |
450 | /* Assign dev_private so we can do cleanup. */ | 810 | DRM_ERROR("failed to find status page!\n"); |
451 | dev->dev_private = (void *)dev_priv; | 811 | return DRM_ERR(EINVAL); |
452 | mga_do_cleanup_dma( dev ); | 812 | } |
453 | return DRM_ERR(EINVAL); | 813 | dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset); |
454 | } | 814 | if (!dev_priv->mmio) { |
455 | dev_priv->status = drm_core_findmap(dev, init->status_offset); | 815 | DRM_ERROR("failed to find mmio region!\n"); |
456 | if(!dev_priv->status) { | 816 | return DRM_ERR(EINVAL); |
457 | DRM_ERROR( "failed to find status page!\n" ); | 817 | } |
458 | /* Assign dev_private so we can do cleanup. */ | 818 | dev_priv->warp = drm_core_findmap(dev, init->warp_offset); |
459 | dev->dev_private = (void *)dev_priv; | 819 | if (!dev_priv->warp) { |
460 | mga_do_cleanup_dma( dev ); | 820 | DRM_ERROR("failed to find warp microcode region!\n"); |
461 | return DRM_ERR(EINVAL); | 821 | return DRM_ERR(EINVAL); |
462 | } | 822 | } |
463 | dev_priv->warp = drm_core_findmap(dev, init->warp_offset); | 823 | dev_priv->primary = drm_core_findmap(dev, init->primary_offset); |
464 | if(!dev_priv->warp) { | 824 | if (!dev_priv->primary) { |
465 | DRM_ERROR( "failed to find warp microcode region!\n" ); | 825 | DRM_ERROR("failed to find primary dma region!\n"); |
466 | /* Assign dev_private so we can do cleanup. */ | 826 | return DRM_ERR(EINVAL); |
467 | dev->dev_private = (void *)dev_priv; | 827 | } |
468 | mga_do_cleanup_dma( dev ); | 828 | dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); |
469 | return DRM_ERR(EINVAL); | 829 | if (!dev->agp_buffer_map) { |
470 | } | 830 | DRM_ERROR("failed to find dma buffer region!\n"); |
471 | dev_priv->primary = drm_core_findmap(dev, init->primary_offset); | 831 | return DRM_ERR(EINVAL); |
472 | if(!dev_priv->primary) { | 832 | } |
473 | DRM_ERROR( "failed to find primary dma region!\n" ); | 833 | |
474 | /* Assign dev_private so we can do cleanup. */ | 834 | drm_core_ioremap(dev_priv->warp, dev); |
475 | dev->dev_private = (void *)dev_priv; | 835 | drm_core_ioremap(dev_priv->primary, dev); |
476 | mga_do_cleanup_dma( dev ); | 836 | drm_core_ioremap(dev->agp_buffer_map, dev); |
477 | return DRM_ERR(EINVAL); | ||
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 | } | 837 | } |
487 | 838 | ||
488 | dev_priv->sarea_priv = | 839 | dev_priv->sarea_priv = |
489 | (drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle + | 840 | (drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle + |
490 | init->sarea_priv_offset); | 841 | init->sarea_priv_offset); |
491 | 842 | ||
492 | drm_core_ioremap( dev_priv->warp, dev ); | 843 | if (!dev_priv->warp->handle || |
493 | drm_core_ioremap( dev_priv->primary, dev ); | 844 | !dev_priv->primary->handle || |
494 | drm_core_ioremap( dev->agp_buffer_map, dev ); | 845 | ((dev_priv->dma_access != 0) && |
495 | 846 | ((dev->agp_buffer_map == NULL) || | |
496 | if(!dev_priv->warp->handle || | 847 | (dev->agp_buffer_map->handle == NULL)))) { |
497 | !dev_priv->primary->handle || | 848 | 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); | 849 | return DRM_ERR(ENOMEM); |
504 | } | 850 | } |
505 | 851 | ||
506 | ret = mga_warp_install_microcode( dev_priv ); | 852 | ret = mga_warp_install_microcode(dev_priv); |
507 | if ( ret < 0 ) { | 853 | if (ret < 0) { |
508 | DRM_ERROR( "failed to install WARP ucode!\n" ); | 854 | 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; | 855 | return ret; |
513 | } | 856 | } |
514 | 857 | ||
515 | ret = mga_warp_init( dev_priv ); | 858 | ret = mga_warp_init(dev_priv); |
516 | if ( ret < 0 ) { | 859 | if (ret < 0) { |
517 | DRM_ERROR( "failed to init WARP engine!\n" ); | 860 | 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; | 861 | return ret; |
522 | } | 862 | } |
523 | 863 | ||
@@ -557,22 +897,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; | 897 | dev_priv->sarea_priv->last_frame.head = 0; |
558 | dev_priv->sarea_priv->last_frame.wrap = 0; | 898 | dev_priv->sarea_priv->last_frame.wrap = 0; |
559 | 899 | ||
560 | if ( mga_freelist_init( dev, dev_priv ) < 0 ) { | 900 | if (mga_freelist_init(dev, dev_priv) < 0) { |
561 | DRM_ERROR( "could not initialize freelist\n" ); | 901 | 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); | 902 | return DRM_ERR(ENOMEM); |
566 | } | 903 | } |
567 | 904 | ||
568 | /* Make dev_private visable to others. */ | ||
569 | dev->dev_private = (void *)dev_priv; | ||
570 | return 0; | 905 | return 0; |
571 | } | 906 | } |
572 | 907 | ||
573 | static int mga_do_cleanup_dma( drm_device_t *dev ) | 908 | static int mga_do_cleanup_dma( drm_device_t *dev ) |
574 | { | 909 | { |
575 | DRM_DEBUG( "\n" ); | 910 | int err = 0; |
911 | DRM_DEBUG("\n"); | ||
576 | 912 | ||
577 | /* Make sure interrupts are disabled here because the uninstall ioctl | 913 | /* Make sure interrupts are disabled here because the uninstall ioctl |
578 | * may not have been called from userspace and after dev_private | 914 | * may not have been called from userspace and after dev_private |
@@ -583,20 +919,49 @@ static int mga_do_cleanup_dma( drm_device_t *dev ) | |||
583 | if ( dev->dev_private ) { | 919 | if ( dev->dev_private ) { |
584 | drm_mga_private_t *dev_priv = dev->dev_private; | 920 | drm_mga_private_t *dev_priv = dev->dev_private; |
585 | 921 | ||
586 | if ( dev_priv->warp != NULL ) | 922 | if ((dev_priv->warp != NULL) |
587 | drm_core_ioremapfree( dev_priv->warp, dev ); | 923 | && (dev_priv->mmio->type != _DRM_CONSISTENT)) |
588 | if ( dev_priv->primary != NULL ) | 924 | drm_core_ioremapfree(dev_priv->warp, dev); |
589 | drm_core_ioremapfree( dev_priv->primary, dev ); | 925 | |
590 | if ( dev->agp_buffer_map != NULL ) | 926 | if ((dev_priv->primary != NULL) |
591 | drm_core_ioremapfree( dev->agp_buffer_map, dev ); | 927 | && (dev_priv->primary->type != _DRM_CONSISTENT)) |
928 | drm_core_ioremapfree(dev_priv->primary, dev); | ||
592 | 929 | ||
593 | if ( dev_priv->head != NULL ) { | 930 | if (dev->agp_buffer_map != NULL) |
594 | mga_freelist_cleanup( dev ); | 931 | drm_core_ioremapfree(dev->agp_buffer_map, dev); |
932 | |||
933 | if (dev_priv->used_new_dma_init) { | ||
934 | if (dev_priv->agp_mem != NULL) { | ||
935 | dev_priv->agp_textures = NULL; | ||
936 | drm_unbind_agp(dev_priv->agp_mem); | ||
937 | |||
938 | drm_free_agp(dev_priv->agp_mem, dev_priv->agp_pages); | ||
939 | dev_priv->agp_pages = 0; | ||
940 | dev_priv->agp_mem = NULL; | ||
941 | } | ||
942 | |||
943 | if ((dev->agp != NULL) && dev->agp->acquired) { | ||
944 | err = drm_agp_release(dev); | ||
945 | } | ||
946 | |||
947 | dev_priv->used_new_dma_init = 0; | ||
595 | } | 948 | } |
596 | 949 | ||
597 | drm_free( dev->dev_private, sizeof(drm_mga_private_t), | 950 | dev_priv->warp = NULL; |
598 | DRM_MEM_DRIVER ); | 951 | dev_priv->primary = NULL; |
599 | dev->dev_private = NULL; | 952 | dev_priv->mmio = NULL; |
953 | dev_priv->status = NULL; | ||
954 | dev_priv->sarea = NULL; | ||
955 | dev_priv->sarea_priv = NULL; | ||
956 | dev->agp_buffer_map = NULL; | ||
957 | |||
958 | memset(&dev_priv->prim, 0, sizeof(dev_priv->prim)); | ||
959 | dev_priv->warp_pipe = 0; | ||
960 | memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys)); | ||
961 | |||
962 | if (dev_priv->head != NULL) { | ||
963 | mga_freelist_cleanup(dev); | ||
964 | } | ||
600 | } | 965 | } |
601 | 966 | ||
602 | return 0; | 967 | return 0; |
@@ -606,14 +971,20 @@ int mga_dma_init( DRM_IOCTL_ARGS ) | |||
606 | { | 971 | { |
607 | DRM_DEVICE; | 972 | DRM_DEVICE; |
608 | drm_mga_init_t init; | 973 | drm_mga_init_t init; |
974 | int err; | ||
609 | 975 | ||
610 | LOCK_TEST_WITH_RETURN( dev, filp ); | 976 | LOCK_TEST_WITH_RETURN( dev, filp ); |
611 | 977 | ||
612 | DRM_COPY_FROM_USER_IOCTL( init, (drm_mga_init_t __user *)data, sizeof(init) ); | 978 | DRM_COPY_FROM_USER_IOCTL(init, (drm_mga_init_t __user *) data, |
979 | sizeof(init)); | ||
613 | 980 | ||
614 | switch ( init.func ) { | 981 | switch ( init.func ) { |
615 | case MGA_INIT_DMA: | 982 | case MGA_INIT_DMA: |
616 | return mga_do_init_dma( dev, &init ); | 983 | err = mga_do_init_dma(dev, &init); |
984 | if (err) { | ||
985 | (void) mga_do_cleanup_dma(dev); | ||
986 | } | ||
987 | return err; | ||
617 | case MGA_CLEANUP_DMA: | 988 | case MGA_CLEANUP_DMA: |
618 | return mga_do_cleanup_dma( dev ); | 989 | return mga_do_cleanup_dma( dev ); |
619 | } | 990 | } |
@@ -742,7 +1113,21 @@ int mga_dma_buffers( DRM_IOCTL_ARGS ) | |||
742 | return ret; | 1113 | return ret; |
743 | } | 1114 | } |
744 | 1115 | ||
745 | void mga_driver_pretakedown(drm_device_t *dev) | 1116 | /** |
1117 | * Called just before the module is unloaded. | ||
1118 | */ | ||
1119 | int mga_driver_postcleanup(drm_device_t * dev) | ||
1120 | { | ||
1121 | drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER); | ||
1122 | dev->dev_private = NULL; | ||
1123 | |||
1124 | return 0; | ||
1125 | } | ||
1126 | |||
1127 | /** | ||
1128 | * Called when the last opener of the device is closed. | ||
1129 | */ | ||
1130 | void mga_driver_pretakedown(drm_device_t * dev) | ||
746 | { | 1131 | { |
747 | mga_do_cleanup_dma( dev ); | 1132 | mga_do_cleanup_dma( dev ); |
748 | } | 1133 | } |
diff --git a/drivers/char/drm/mga_drm.h b/drivers/char/drm/mga_drm.h index 4500e6e4920a..2d8aa790379e 100644 --- a/drivers/char/drm/mga_drm.h +++ b/drivers/char/drm/mga_drm.h | |||
@@ -226,10 +226,6 @@ typedef struct _drm_mga_sarea { | |||
226 | } drm_mga_sarea_t; | 226 | } drm_mga_sarea_t; |
227 | 227 | ||
228 | 228 | ||
229 | /* WARNING: If you change any of these defines, make sure to change the | ||
230 | * defines in the Xserver file (xf86drmMga.h) | ||
231 | */ | ||
232 | |||
233 | /* MGA specific ioctls | 229 | /* MGA specific ioctls |
234 | * The device specific ioctl range is 0x40 to 0x79. | 230 | * The device specific ioctl range is 0x40 to 0x79. |
235 | */ | 231 | */ |
@@ -244,6 +240,14 @@ typedef struct _drm_mga_sarea { | |||
244 | #define DRM_MGA_BLIT 0x08 | 240 | #define DRM_MGA_BLIT 0x08 |
245 | #define DRM_MGA_GETPARAM 0x09 | 241 | #define DRM_MGA_GETPARAM 0x09 |
246 | 242 | ||
243 | /* 3.2: | ||
244 | * ioctls for operating on fences. | ||
245 | */ | ||
246 | #define DRM_MGA_SET_FENCE 0x0a | ||
247 | #define DRM_MGA_WAIT_FENCE 0x0b | ||
248 | #define DRM_MGA_DMA_BOOTSTRAP 0x0c | ||
249 | |||
250 | |||
247 | #define DRM_IOCTL_MGA_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t) | 251 | #define DRM_IOCTL_MGA_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t) |
248 | #define DRM_IOCTL_MGA_FLUSH DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, drm_lock_t) | 252 | #define DRM_IOCTL_MGA_FLUSH DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, drm_lock_t) |
249 | #define DRM_IOCTL_MGA_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MGA_RESET) | 253 | #define DRM_IOCTL_MGA_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MGA_RESET) |
@@ -254,6 +258,9 @@ typedef struct _drm_mga_sarea { | |||
254 | #define DRM_IOCTL_MGA_ILOAD DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_ILOAD, drm_mga_iload_t) | 258 | #define DRM_IOCTL_MGA_ILOAD DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_ILOAD, drm_mga_iload_t) |
255 | #define DRM_IOCTL_MGA_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_BLIT, drm_mga_blit_t) | 259 | #define DRM_IOCTL_MGA_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_BLIT, drm_mga_blit_t) |
256 | #define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_GETPARAM, drm_mga_getparam_t) | 260 | #define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_GETPARAM, drm_mga_getparam_t) |
261 | #define DRM_IOCTL_MGA_SET_FENCE DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_SET_FENCE, uint32_t) | ||
262 | #define DRM_IOCTL_MGA_WAIT_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_WAIT_FENCE, uint32_t) | ||
263 | #define DRM_IOCTL_MGA_DMA_BOOTSTRAP DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_DMA_BOOTSTRAP, drm_mga_dma_bootstrap_t) | ||
257 | 264 | ||
258 | typedef struct _drm_mga_warp_index { | 265 | typedef struct _drm_mga_warp_index { |
259 | int installed; | 266 | int installed; |
@@ -292,12 +299,72 @@ typedef struct drm_mga_init { | |||
292 | unsigned long buffers_offset; | 299 | unsigned long buffers_offset; |
293 | } drm_mga_init_t; | 300 | } drm_mga_init_t; |
294 | 301 | ||
295 | typedef struct drm_mga_fullscreen { | 302 | typedef struct drm_mga_dma_bootstrap { |
296 | enum { | 303 | /** |
297 | MGA_INIT_FULLSCREEN = 0x01, | 304 | * \name AGP texture region |
298 | MGA_CLEANUP_FULLSCREEN = 0x02 | 305 | * |
299 | } func; | 306 | * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, these fields will |
300 | } drm_mga_fullscreen_t; | 307 | * be filled in with the actual AGP texture settings. |
308 | * | ||
309 | * \warning | ||
310 | * If these fields are non-zero, but dma_mga_dma_bootstrap::agp_mode | ||
311 | * is zero, it means that PCI memory (most likely through the use of | ||
312 | * an IOMMU) is being used for "AGP" textures. | ||
313 | */ | ||
314 | /*@{*/ | ||
315 | drm_handle_t texture_handle; /**< Handle used to map AGP textures. */ | ||
316 | uint32_t texture_size; /**< Size of the AGP texture region. */ | ||
317 | /*@}*/ | ||
318 | |||
319 | |||
320 | /** | ||
321 | * Requested size of the primary DMA region. | ||
322 | * | ||
323 | * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be | ||
324 | * filled in with the actual AGP mode. If AGP was not available | ||
325 | */ | ||
326 | uint32_t primary_size; | ||
327 | |||
328 | |||
329 | /** | ||
330 | * Requested number of secondary DMA buffers. | ||
331 | * | ||
332 | * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be | ||
333 | * filled in with the actual number of secondary DMA buffers | ||
334 | * allocated. Particularly when PCI DMA is used, this may be | ||
335 | * (subtantially) less than the number requested. | ||
336 | */ | ||
337 | uint32_t secondary_bin_count; | ||
338 | |||
339 | |||
340 | /** | ||
341 | * Requested size of each secondary DMA buffer. | ||
342 | * | ||
343 | * While the kernel \b is free to reduce | ||
344 | * dma_mga_dma_bootstrap::secondary_bin_count, it is \b not allowed | ||
345 | * to reduce dma_mga_dma_bootstrap::secondary_bin_size. | ||
346 | */ | ||
347 | uint32_t secondary_bin_size; | ||
348 | |||
349 | |||
350 | /** | ||
351 | * Bit-wise mask of AGPSTAT2_* values. Currently only \c AGPSTAT2_1X, | ||
352 | * \c AGPSTAT2_2X, and \c AGPSTAT2_4X are supported. If this value is | ||
353 | * zero, it means that PCI DMA should be used, even if AGP is | ||
354 | * possible. | ||
355 | * | ||
356 | * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be | ||
357 | * filled in with the actual AGP mode. If AGP was not available | ||
358 | * (i.e., PCI DMA was used), this value will be zero. | ||
359 | */ | ||
360 | uint32_t agp_mode; | ||
361 | |||
362 | |||
363 | /** | ||
364 | * Desired AGP GART size, measured in megabytes. | ||
365 | */ | ||
366 | uint8_t agp_size; | ||
367 | } drm_mga_dma_bootstrap_t; | ||
301 | 368 | ||
302 | typedef struct drm_mga_clear { | 369 | typedef struct drm_mga_clear { |
303 | unsigned int flags; | 370 | unsigned int flags; |
@@ -342,6 +409,14 @@ typedef struct _drm_mga_blit { | |||
342 | */ | 409 | */ |
343 | #define MGA_PARAM_IRQ_NR 1 | 410 | #define MGA_PARAM_IRQ_NR 1 |
344 | 411 | ||
412 | /* 3.2: Query the actual card type. The DDX only distinguishes between | ||
413 | * G200 chips and non-G200 chips, which it calls G400. It turns out that | ||
414 | * there are some very sublte differences between the G4x0 chips and the G550 | ||
415 | * chips. Using this parameter query, a client-side driver can detect the | ||
416 | * difference between a G4x0 and a G550. | ||
417 | */ | ||
418 | #define MGA_PARAM_CARD_TYPE 2 | ||
419 | |||
345 | typedef struct drm_mga_getparam { | 420 | typedef struct drm_mga_getparam { |
346 | int param; | 421 | int param; |
347 | void __user *value; | 422 | void __user *value; |
diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h index 38f913905e04..b22fdbd4f830 100644 --- a/drivers/char/drm/mga_drv.h +++ b/drivers/char/drm/mga_drv.h | |||
@@ -38,11 +38,11 @@ | |||
38 | 38 | ||
39 | #define DRIVER_NAME "mga" | 39 | #define DRIVER_NAME "mga" |
40 | #define DRIVER_DESC "Matrox G200/G400" | 40 | #define DRIVER_DESC "Matrox G200/G400" |
41 | #define DRIVER_DATE "20051013" | 41 | #define DRIVER_DATE "20050607" |
42 | 42 | ||
43 | #define DRIVER_MAJOR 3 | 43 | #define DRIVER_MAJOR 3 |
44 | #define DRIVER_MINOR 1 | 44 | #define DRIVER_MINOR 2 |
45 | #define DRIVER_PATCHLEVEL 1 | 45 | #define DRIVER_PATCHLEVEL 0 |
46 | 46 | ||
47 | typedef struct drm_mga_primary_buffer { | 47 | typedef struct drm_mga_primary_buffer { |
48 | u8 *start; | 48 | u8 *start; |
@@ -87,9 +87,43 @@ typedef struct drm_mga_private { | |||
87 | int chipset; | 87 | int chipset; |
88 | int usec_timeout; | 88 | int usec_timeout; |
89 | 89 | ||
90 | /** | ||
91 | * If set, the new DMA initialization sequence was used. This is | ||
92 | * primarilly used to select how the driver should uninitialized its | ||
93 | * internal DMA structures. | ||
94 | */ | ||
95 | int used_new_dma_init; | ||
96 | |||
97 | /** | ||
98 | * If AGP memory is used for DMA buffers, this will be the value | ||
99 | * \c MGA_PAGPXFER. Otherwise, it will be zero (for a PCI transfer). | ||
100 | */ | ||
101 | u32 dma_access; | ||
102 | |||
103 | /** | ||
104 | * If AGP memory is used for DMA buffers, this will be the value | ||
105 | * \c MGA_WAGP_ENABLE. Otherwise, it will be zero (for a PCI | ||
106 | * transfer). | ||
107 | */ | ||
108 | u32 wagp_enable; | ||
109 | |||
110 | /** | ||
111 | * \name MMIO region parameters. | ||
112 | * | ||
113 | * \sa drm_mga_private_t::mmio | ||
114 | */ | ||
115 | /*@{*/ | ||
116 | u32 mmio_base; /**< Bus address of base of MMIO. */ | ||
117 | u32 mmio_size; /**< Size of the MMIO region. */ | ||
118 | /*@}*/ | ||
119 | |||
90 | u32 clear_cmd; | 120 | u32 clear_cmd; |
91 | u32 maccess; | 121 | u32 maccess; |
92 | 122 | ||
123 | wait_queue_head_t fence_queue; | ||
124 | atomic_t last_fence_retired; | ||
125 | u32 next_fence_to_post; | ||
126 | |||
93 | unsigned int fb_cpp; | 127 | unsigned int fb_cpp; |
94 | unsigned int front_offset; | 128 | unsigned int front_offset; |
95 | unsigned int front_pitch; | 129 | unsigned int front_pitch; |
@@ -108,35 +142,43 @@ typedef struct drm_mga_private { | |||
108 | drm_local_map_t *status; | 142 | drm_local_map_t *status; |
109 | drm_local_map_t *warp; | 143 | drm_local_map_t *warp; |
110 | drm_local_map_t *primary; | 144 | drm_local_map_t *primary; |
111 | drm_local_map_t *buffers; | ||
112 | drm_local_map_t *agp_textures; | 145 | drm_local_map_t *agp_textures; |
146 | |||
147 | DRM_AGP_MEM *agp_mem; | ||
148 | unsigned int agp_pages; | ||
113 | } drm_mga_private_t; | 149 | } drm_mga_private_t; |
114 | 150 | ||
115 | /* mga_dma.c */ | 151 | /* mga_dma.c */ |
116 | extern int mga_dma_init( DRM_IOCTL_ARGS ); | 152 | extern int mga_driver_preinit(drm_device_t * dev, unsigned long flags); |
117 | extern int mga_dma_flush( DRM_IOCTL_ARGS ); | 153 | extern int mga_dma_bootstrap(DRM_IOCTL_ARGS); |
118 | extern int mga_dma_reset( DRM_IOCTL_ARGS ); | 154 | extern int mga_dma_init(DRM_IOCTL_ARGS); |
119 | extern int mga_dma_buffers( DRM_IOCTL_ARGS ); | 155 | extern int mga_dma_flush(DRM_IOCTL_ARGS); |
120 | extern void mga_driver_pretakedown(drm_device_t *dev); | 156 | extern int mga_dma_reset(DRM_IOCTL_ARGS); |
121 | extern int mga_driver_dma_quiescent(drm_device_t *dev); | 157 | extern int mga_dma_buffers(DRM_IOCTL_ARGS); |
122 | 158 | extern int mga_driver_postcleanup(drm_device_t * dev); | |
123 | extern int mga_do_wait_for_idle( drm_mga_private_t *dev_priv ); | 159 | extern void mga_driver_pretakedown(drm_device_t * dev); |
124 | 160 | extern int mga_driver_dma_quiescent(drm_device_t * dev); | |
125 | extern void mga_do_dma_flush( drm_mga_private_t *dev_priv ); | 161 | |
126 | extern void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv ); | 162 | extern int mga_do_wait_for_idle(drm_mga_private_t * dev_priv); |
127 | extern void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv ); | 163 | |
164 | extern void mga_do_dma_flush(drm_mga_private_t * dev_priv); | ||
165 | extern void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv); | ||
166 | extern void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv); | ||
128 | 167 | ||
129 | extern int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf ); | 168 | extern int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf ); |
130 | 169 | ||
131 | /* mga_warp.c */ | 170 | /* mga_warp.c */ |
132 | extern int mga_warp_install_microcode( drm_mga_private_t *dev_priv ); | 171 | extern unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv); |
133 | extern int mga_warp_init( drm_mga_private_t *dev_priv ); | 172 | extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv); |
134 | 173 | extern int mga_warp_init(drm_mga_private_t * dev_priv); | |
135 | extern int mga_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence); | 174 | |
136 | extern irqreturn_t mga_driver_irq_handler( DRM_IRQ_ARGS ); | 175 | /* mga_irq.c */ |
137 | extern void mga_driver_irq_preinstall( drm_device_t *dev ); | 176 | extern int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence); |
138 | extern void mga_driver_irq_postinstall( drm_device_t *dev ); | 177 | extern int mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence); |
139 | extern void mga_driver_irq_uninstall( drm_device_t *dev ); | 178 | extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS); |
179 | extern void mga_driver_irq_preinstall(drm_device_t * dev); | ||
180 | extern void mga_driver_irq_postinstall(drm_device_t * dev); | ||
181 | extern void mga_driver_irq_uninstall(drm_device_t * dev); | ||
140 | extern long mga_compat_ioctl(struct file *filp, unsigned int cmd, | 182 | extern long mga_compat_ioctl(struct file *filp, unsigned int cmd, |
141 | unsigned long arg); | 183 | unsigned long arg); |
142 | 184 | ||
@@ -527,6 +569,12 @@ do { \ | |||
527 | */ | 569 | */ |
528 | #define MGA_EXEC 0x0100 | 570 | #define MGA_EXEC 0x0100 |
529 | 571 | ||
572 | /* AGP PLL encoding (for G200 only). | ||
573 | */ | ||
574 | #define MGA_AGP_PLL 0x1e4c | ||
575 | # define MGA_AGP2XPLL_DISABLE (0 << 0) | ||
576 | # define MGA_AGP2XPLL_ENABLE (1 << 0) | ||
577 | |||
530 | /* Warp registers | 578 | /* Warp registers |
531 | */ | 579 | */ |
532 | #define MGA_WR0 0x2d00 | 580 | #define MGA_WR0 0x2d00 |
diff --git a/drivers/char/drm/mga_irq.c b/drivers/char/drm/mga_irq.c index bc0b6b5d43a6..52eaa4e788f9 100644 --- a/drivers/char/drm/mga_irq.c +++ b/drivers/char/drm/mga_irq.c | |||
@@ -41,15 +41,40 @@ irqreturn_t mga_driver_irq_handler( DRM_IRQ_ARGS ) | |||
41 | drm_mga_private_t *dev_priv = | 41 | drm_mga_private_t *dev_priv = |
42 | (drm_mga_private_t *)dev->dev_private; | 42 | (drm_mga_private_t *)dev->dev_private; |
43 | int status; | 43 | int status; |
44 | int handled = 0; | ||
45 | |||
46 | status = MGA_READ(MGA_STATUS); | ||
44 | 47 | ||
45 | status = MGA_READ( MGA_STATUS ); | ||
46 | |||
47 | /* VBLANK interrupt */ | 48 | /* VBLANK interrupt */ |
48 | if ( status & MGA_VLINEPEN ) { | 49 | if ( status & MGA_VLINEPEN ) { |
49 | MGA_WRITE( MGA_ICLEAR, MGA_VLINEICLR ); | 50 | MGA_WRITE( MGA_ICLEAR, MGA_VLINEICLR ); |
50 | atomic_inc(&dev->vbl_received); | 51 | atomic_inc(&dev->vbl_received); |
51 | DRM_WAKEUP(&dev->vbl_queue); | 52 | DRM_WAKEUP(&dev->vbl_queue); |
52 | drm_vbl_send_signals( dev ); | 53 | drm_vbl_send_signals(dev); |
54 | handled = 1; | ||
55 | } | ||
56 | |||
57 | /* SOFTRAP interrupt */ | ||
58 | if (status & MGA_SOFTRAPEN) { | ||
59 | const u32 prim_start = MGA_READ(MGA_PRIMADDRESS); | ||
60 | const u32 prim_end = MGA_READ(MGA_PRIMEND); | ||
61 | |||
62 | |||
63 | MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR); | ||
64 | |||
65 | /* In addition to clearing the interrupt-pending bit, we | ||
66 | * have to write to MGA_PRIMEND to re-start the DMA operation. | ||
67 | */ | ||
68 | if ( (prim_start & ~0x03) != (prim_end & ~0x03) ) { | ||
69 | MGA_WRITE(MGA_PRIMEND, prim_end); | ||
70 | } | ||
71 | |||
72 | atomic_inc(&dev_priv->last_fence_retired); | ||
73 | DRM_WAKEUP(&dev_priv->fence_queue); | ||
74 | handled = 1; | ||
75 | } | ||
76 | |||
77 | if ( handled ) { | ||
53 | return IRQ_HANDLED; | 78 | return IRQ_HANDLED; |
54 | } | 79 | } |
55 | return IRQ_NONE; | 80 | return IRQ_NONE; |
@@ -73,9 +98,28 @@ int mga_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence) | |||
73 | return ret; | 98 | return ret; |
74 | } | 99 | } |
75 | 100 | ||
76 | void mga_driver_irq_preinstall( drm_device_t *dev ) { | 101 | int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence) |
77 | drm_mga_private_t *dev_priv = | 102 | { |
78 | (drm_mga_private_t *)dev->dev_private; | 103 | drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; |
104 | unsigned int cur_fence; | ||
105 | int ret = 0; | ||
106 | |||
107 | /* Assume that the user has missed the current sequence number | ||
108 | * by about a day rather than she wants to wait for years | ||
109 | * using fences. | ||
110 | */ | ||
111 | DRM_WAIT_ON(ret, dev_priv->fence_queue, 3 * DRM_HZ, | ||
112 | (((cur_fence = atomic_read(&dev_priv->last_fence_retired)) | ||
113 | - *sequence) <= (1 << 23))); | ||
114 | |||
115 | *sequence = cur_fence; | ||
116 | |||
117 | return ret; | ||
118 | } | ||
119 | |||
120 | void mga_driver_irq_preinstall(drm_device_t * dev) | ||
121 | { | ||
122 | drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; | ||
79 | 123 | ||
80 | /* Disable *all* interrupts */ | 124 | /* Disable *all* interrupts */ |
81 | MGA_WRITE( MGA_IEN, 0 ); | 125 | MGA_WRITE( MGA_IEN, 0 ); |
@@ -83,12 +127,14 @@ void mga_driver_irq_preinstall( drm_device_t *dev ) { | |||
83 | MGA_WRITE( MGA_ICLEAR, ~0 ); | 127 | MGA_WRITE( MGA_ICLEAR, ~0 ); |
84 | } | 128 | } |
85 | 129 | ||
86 | void mga_driver_irq_postinstall( drm_device_t *dev ) { | 130 | void mga_driver_irq_postinstall(drm_device_t * dev) |
87 | drm_mga_private_t *dev_priv = | 131 | { |
88 | (drm_mga_private_t *)dev->dev_private; | 132 | drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; |
133 | |||
134 | DRM_INIT_WAITQUEUE( &dev_priv->fence_queue ); | ||
89 | 135 | ||
90 | /* Turn on VBL interrupt */ | 136 | /* Turn on vertical blank interrupt and soft trap interrupt. */ |
91 | MGA_WRITE( MGA_IEN, MGA_VLINEIEN ); | 137 | MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); |
92 | } | 138 | } |
93 | 139 | ||
94 | void mga_driver_irq_uninstall( drm_device_t *dev ) { | 140 | void mga_driver_irq_uninstall( drm_device_t *dev ) { |
@@ -98,5 +144,7 @@ void mga_driver_irq_uninstall( drm_device_t *dev ) { | |||
98 | return; | 144 | return; |
99 | 145 | ||
100 | /* Disable *all* interrupts */ | 146 | /* Disable *all* interrupts */ |
101 | MGA_WRITE( MGA_IEN, 0 ); | 147 | MGA_WRITE(MGA_IEN, 0); |
148 | |||
149 | dev->irq_enabled = 0; | ||
102 | } | 150 | } |
diff --git a/drivers/char/drm/mga_state.c b/drivers/char/drm/mga_state.c index 3c7a8f5ba501..05bbb4719376 100644 --- a/drivers/char/drm/mga_state.c +++ b/drivers/char/drm/mga_state.c | |||
@@ -53,16 +53,16 @@ static void mga_emit_clip_rect( drm_mga_private_t *dev_priv, | |||
53 | 53 | ||
54 | /* Force reset of DWGCTL on G400 (eliminates clip disable bit). | 54 | /* Force reset of DWGCTL on G400 (eliminates clip disable bit). |
55 | */ | 55 | */ |
56 | if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) { | 56 | if (dev_priv->chipset == MGA_CARD_TYPE_G400) { |
57 | DMA_BLOCK( MGA_DWGCTL, ctx->dwgctl, | 57 | DMA_BLOCK(MGA_DWGCTL, ctx->dwgctl, |
58 | MGA_LEN + MGA_EXEC, 0x80000000, | 58 | MGA_LEN + MGA_EXEC, 0x80000000, |
59 | MGA_DWGCTL, ctx->dwgctl, | 59 | MGA_DWGCTL, ctx->dwgctl, |
60 | MGA_LEN + MGA_EXEC, 0x80000000 ); | 60 | MGA_LEN + MGA_EXEC, 0x80000000); |
61 | } | 61 | } |
62 | DMA_BLOCK( MGA_DMAPAD, 0x00000000, | 62 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
63 | MGA_CXBNDRY, (box->x2 << 16) | box->x1, | 63 | MGA_CXBNDRY, ((box->x2 - 1) << 16) | box->x1, |
64 | MGA_YTOP, box->y1 * pitch, | 64 | MGA_YTOP, box->y1 * pitch, |
65 | MGA_YBOT, box->y2 * pitch ); | 65 | MGA_YBOT, (box->y2 - 1) * pitch); |
66 | 66 | ||
67 | ADVANCE_DMA(); | 67 | ADVANCE_DMA(); |
68 | } | 68 | } |
@@ -260,12 +260,11 @@ static __inline__ void mga_g200_emit_pipe( drm_mga_private_t *dev_priv ) | |||
260 | 260 | ||
261 | /* Padding required to to hardware bug. | 261 | /* Padding required to to hardware bug. |
262 | */ | 262 | */ |
263 | DMA_BLOCK( MGA_DMAPAD, 0xffffffff, | 263 | DMA_BLOCK(MGA_DMAPAD, 0xffffffff, |
264 | MGA_DMAPAD, 0xffffffff, | 264 | MGA_DMAPAD, 0xffffffff, |
265 | MGA_DMAPAD, 0xffffffff, | 265 | MGA_DMAPAD, 0xffffffff, |
266 | MGA_WIADDR, (dev_priv->warp_pipe_phys[pipe] | | 266 | MGA_WIADDR, (dev_priv->warp_pipe_phys[pipe] | |
267 | MGA_WMODE_START | | 267 | MGA_WMODE_START | dev_priv->wagp_enable)); |
268 | MGA_WAGP_ENABLE) ); | ||
269 | 268 | ||
270 | ADVANCE_DMA(); | 269 | ADVANCE_DMA(); |
271 | } | 270 | } |
@@ -342,12 +341,11 @@ static __inline__ void mga_g400_emit_pipe( drm_mga_private_t *dev_priv ) | |||
342 | MGA_WR60, MGA_G400_WR_MAGIC ); /* tex1 height */ | 341 | MGA_WR60, MGA_G400_WR_MAGIC ); /* tex1 height */ |
343 | 342 | ||
344 | /* Padding required to to hardware bug */ | 343 | /* Padding required to to hardware bug */ |
345 | DMA_BLOCK( MGA_DMAPAD, 0xffffffff, | 344 | DMA_BLOCK(MGA_DMAPAD, 0xffffffff, |
346 | MGA_DMAPAD, 0xffffffff, | 345 | MGA_DMAPAD, 0xffffffff, |
347 | MGA_DMAPAD, 0xffffffff, | 346 | MGA_DMAPAD, 0xffffffff, |
348 | MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] | | 347 | MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] | |
349 | MGA_WMODE_START | | 348 | MGA_WMODE_START | dev_priv->wagp_enable)); |
350 | MGA_WAGP_ENABLE) ); | ||
351 | 349 | ||
352 | ADVANCE_DMA(); | 350 | ADVANCE_DMA(); |
353 | } | 351 | } |
@@ -459,9 +457,9 @@ static int mga_verify_state( drm_mga_private_t *dev_priv ) | |||
459 | if ( dirty & MGA_UPLOAD_TEX0 ) | 457 | if ( dirty & MGA_UPLOAD_TEX0 ) |
460 | ret |= mga_verify_tex( dev_priv, 0 ); | 458 | ret |= mga_verify_tex( dev_priv, 0 ); |
461 | 459 | ||
462 | if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) { | 460 | if (dev_priv->chipset >= MGA_CARD_TYPE_G400) { |
463 | if ( dirty & MGA_UPLOAD_TEX1 ) | 461 | if (dirty & MGA_UPLOAD_TEX1) |
464 | ret |= mga_verify_tex( dev_priv, 1 ); | 462 | ret |= mga_verify_tex(dev_priv, 1); |
465 | 463 | ||
466 | if ( dirty & MGA_UPLOAD_PIPE ) | 464 | if ( dirty & MGA_UPLOAD_PIPE ) |
467 | ret |= ( sarea_priv->warp_pipe > MGA_MAX_G400_PIPES ); | 465 | ret |= ( sarea_priv->warp_pipe > MGA_MAX_G400_PIPES ); |
@@ -686,12 +684,12 @@ static void mga_dma_dispatch_vertex( drm_device_t *dev, drm_buf_t *buf ) | |||
686 | 684 | ||
687 | BEGIN_DMA( 1 ); | 685 | BEGIN_DMA( 1 ); |
688 | 686 | ||
689 | DMA_BLOCK( MGA_DMAPAD, 0x00000000, | 687 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
690 | MGA_DMAPAD, 0x00000000, | 688 | MGA_DMAPAD, 0x00000000, |
691 | MGA_SECADDRESS, (address | | 689 | MGA_SECADDRESS, (address | |
692 | MGA_DMA_VERTEX), | 690 | MGA_DMA_VERTEX), |
693 | MGA_SECEND, ((address + length) | | 691 | MGA_SECEND, ((address + length) | |
694 | MGA_PAGPXFER) ); | 692 | dev_priv->dma_access)); |
695 | 693 | ||
696 | ADVANCE_DMA(); | 694 | ADVANCE_DMA(); |
697 | } while ( ++i < sarea_priv->nbox ); | 695 | } while ( ++i < sarea_priv->nbox ); |
@@ -733,11 +731,11 @@ static void mga_dma_dispatch_indices( drm_device_t *dev, drm_buf_t *buf, | |||
733 | 731 | ||
734 | BEGIN_DMA( 1 ); | 732 | BEGIN_DMA( 1 ); |
735 | 733 | ||
736 | DMA_BLOCK( MGA_DMAPAD, 0x00000000, | 734 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, |
737 | MGA_DMAPAD, 0x00000000, | 735 | MGA_DMAPAD, 0x00000000, |
738 | MGA_SETUPADDRESS, address + start, | 736 | MGA_SETUPADDRESS, address + start, |
739 | MGA_SETUPEND, ((address + end) | | 737 | MGA_SETUPEND, ((address + end) | |
740 | MGA_PAGPXFER) ); | 738 | dev_priv->dma_access)); |
741 | 739 | ||
742 | ADVANCE_DMA(); | 740 | ADVANCE_DMA(); |
743 | } while ( ++i < sarea_priv->nbox ); | 741 | } while ( ++i < sarea_priv->nbox ); |
@@ -764,7 +762,7 @@ static void mga_dma_dispatch_iload( drm_device_t *dev, drm_buf_t *buf, | |||
764 | drm_mga_private_t *dev_priv = dev->dev_private; | 762 | drm_mga_private_t *dev_priv = dev->dev_private; |
765 | drm_mga_buf_priv_t *buf_priv = buf->dev_private; | 763 | drm_mga_buf_priv_t *buf_priv = buf->dev_private; |
766 | drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state; | 764 | drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state; |
767 | u32 srcorg = buf->bus_address | MGA_SRCACC_AGP | MGA_SRCMAP_SYSMEM; | 765 | u32 srcorg = buf->bus_address | dev_priv->dma_access | MGA_SRCMAP_SYSMEM; |
768 | u32 y2; | 766 | u32 y2; |
769 | DMA_LOCALS; | 767 | DMA_LOCALS; |
770 | DRM_DEBUG( "buf=%d used=%d\n", buf->idx, buf->used ); | 768 | DRM_DEBUG( "buf=%d used=%d\n", buf->idx, buf->used ); |
@@ -1095,6 +1093,9 @@ static int mga_getparam( DRM_IOCTL_ARGS ) | |||
1095 | case MGA_PARAM_IRQ_NR: | 1093 | case MGA_PARAM_IRQ_NR: |
1096 | value = dev->irq; | 1094 | value = dev->irq; |
1097 | break; | 1095 | break; |
1096 | case MGA_PARAM_CARD_TYPE: | ||
1097 | value = dev_priv->chipset; | ||
1098 | break; | ||
1098 | default: | 1099 | default: |
1099 | return DRM_ERR(EINVAL); | 1100 | return DRM_ERR(EINVAL); |
1100 | } | 1101 | } |
@@ -1107,17 +1108,82 @@ static int mga_getparam( DRM_IOCTL_ARGS ) | |||
1107 | return 0; | 1108 | return 0; |
1108 | } | 1109 | } |
1109 | 1110 | ||
1111 | static int mga_set_fence(DRM_IOCTL_ARGS) | ||
1112 | { | ||
1113 | DRM_DEVICE; | ||
1114 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
1115 | u32 temp; | ||
1116 | DMA_LOCALS; | ||
1117 | |||
1118 | if (!dev_priv) { | ||
1119 | DRM_ERROR("%s called with no initialization\n", __FUNCTION__); | ||
1120 | return DRM_ERR(EINVAL); | ||
1121 | } | ||
1122 | |||
1123 | DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); | ||
1124 | |||
1125 | /* I would normal do this assignment in the declaration of temp, | ||
1126 | * but dev_priv may be NULL. | ||
1127 | */ | ||
1128 | |||
1129 | temp = dev_priv->next_fence_to_post; | ||
1130 | dev_priv->next_fence_to_post++; | ||
1131 | |||
1132 | BEGIN_DMA(1); | ||
1133 | DMA_BLOCK(MGA_DMAPAD, 0x00000000, | ||
1134 | MGA_DMAPAD, 0x00000000, | ||
1135 | MGA_DMAPAD, 0x00000000, | ||
1136 | MGA_SOFTRAP, 0x00000000); | ||
1137 | ADVANCE_DMA(); | ||
1138 | |||
1139 | if (DRM_COPY_TO_USER( (u32 __user *) data, & temp, sizeof(u32))) { | ||
1140 | DRM_ERROR("copy_to_user\n"); | ||
1141 | return DRM_ERR(EFAULT); | ||
1142 | } | ||
1143 | |||
1144 | return 0; | ||
1145 | } | ||
1146 | |||
1147 | static int mga_wait_fence(DRM_IOCTL_ARGS) | ||
1148 | { | ||
1149 | DRM_DEVICE; | ||
1150 | drm_mga_private_t *dev_priv = dev->dev_private; | ||
1151 | u32 fence; | ||
1152 | |||
1153 | if (!dev_priv) { | ||
1154 | DRM_ERROR("%s called with no initialization\n", __FUNCTION__); | ||
1155 | return DRM_ERR(EINVAL); | ||
1156 | } | ||
1157 | |||
1158 | DRM_COPY_FROM_USER_IOCTL(fence, (u32 __user *) data, sizeof(u32)); | ||
1159 | |||
1160 | DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); | ||
1161 | |||
1162 | mga_driver_fence_wait(dev, & fence); | ||
1163 | |||
1164 | if (DRM_COPY_TO_USER( (u32 __user *) data, & fence, sizeof(u32))) { | ||
1165 | DRM_ERROR("copy_to_user\n"); | ||
1166 | return DRM_ERR(EFAULT); | ||
1167 | } | ||
1168 | |||
1169 | return 0; | ||
1170 | } | ||
1171 | |||
1110 | drm_ioctl_desc_t mga_ioctls[] = { | 1172 | drm_ioctl_desc_t mga_ioctls[] = { |
1111 | [DRM_IOCTL_NR(DRM_MGA_INIT)] = { mga_dma_init, 1, 1 }, | 1173 | [DRM_IOCTL_NR(DRM_MGA_INIT)] = {mga_dma_init, 1, 1}, |
1112 | [DRM_IOCTL_NR(DRM_MGA_FLUSH)] = { mga_dma_flush, 1, 0 }, | 1174 | [DRM_IOCTL_NR(DRM_MGA_FLUSH)] = {mga_dma_flush, 1, 0}, |
1113 | [DRM_IOCTL_NR(DRM_MGA_RESET)] = { mga_dma_reset, 1, 0 }, | 1175 | [DRM_IOCTL_NR(DRM_MGA_RESET)] = {mga_dma_reset, 1, 0}, |
1114 | [DRM_IOCTL_NR(DRM_MGA_SWAP)] = { mga_dma_swap, 1, 0 }, | 1176 | [DRM_IOCTL_NR(DRM_MGA_SWAP)] = {mga_dma_swap, 1, 0}, |
1115 | [DRM_IOCTL_NR(DRM_MGA_CLEAR)] = { mga_dma_clear, 1, 0 }, | 1177 | [DRM_IOCTL_NR(DRM_MGA_CLEAR)] = {mga_dma_clear, 1, 0}, |
1116 | [DRM_IOCTL_NR(DRM_MGA_VERTEX)] = { mga_dma_vertex, 1, 0 }, | 1178 | [DRM_IOCTL_NR(DRM_MGA_VERTEX)] = {mga_dma_vertex, 1, 0}, |
1117 | [DRM_IOCTL_NR(DRM_MGA_INDICES)] = { mga_dma_indices, 1, 0 }, | 1179 | [DRM_IOCTL_NR(DRM_MGA_INDICES)] = {mga_dma_indices, 1, 0}, |
1118 | [DRM_IOCTL_NR(DRM_MGA_ILOAD)] = { mga_dma_iload, 1, 0 }, | 1180 | [DRM_IOCTL_NR(DRM_MGA_ILOAD)] = {mga_dma_iload, 1, 0}, |
1119 | [DRM_IOCTL_NR(DRM_MGA_BLIT)] = { mga_dma_blit, 1, 0 }, | 1181 | [DRM_IOCTL_NR(DRM_MGA_BLIT)] = {mga_dma_blit, 1, 0}, |
1120 | [DRM_IOCTL_NR(DRM_MGA_GETPARAM)]= { mga_getparam, 1, 0 }, | 1182 | [DRM_IOCTL_NR(DRM_MGA_GETPARAM)] = {mga_getparam, 1, 0}, |
1183 | [DRM_IOCTL_NR(DRM_MGA_SET_FENCE)] = {mga_set_fence, 1, 0}, | ||
1184 | [DRM_IOCTL_NR(DRM_MGA_WAIT_FENCE)] = {mga_wait_fence, 1, 0}, | ||
1185 | [DRM_IOCTL_NR(DRM_MGA_DMA_BOOTSTRAP)] = {mga_dma_bootstrap, 1, 1}, | ||
1186 | |||
1121 | }; | 1187 | }; |
1122 | 1188 | ||
1123 | int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls); | 1189 | int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls); |
diff --git a/drivers/char/drm/mga_warp.c b/drivers/char/drm/mga_warp.c index 0a3a0cc700dc..55ccc8a0ac29 100644 --- a/drivers/char/drm/mga_warp.c +++ b/drivers/char/drm/mga_warp.c | |||
@@ -48,65 +48,52 @@ do { \ | |||
48 | vcbase += WARP_UCODE_SIZE( which ); \ | 48 | vcbase += WARP_UCODE_SIZE( which ); \ |
49 | } while (0) | 49 | } while (0) |
50 | 50 | ||
51 | 51 | static const unsigned int mga_warp_g400_microcode_size = | |
52 | static unsigned int mga_warp_g400_microcode_size( drm_mga_private_t *dev_priv ) | 52 | (WARP_UCODE_SIZE(warp_g400_tgz) + |
53 | { | 53 | WARP_UCODE_SIZE(warp_g400_tgza) + |
54 | unsigned int size; | 54 | WARP_UCODE_SIZE(warp_g400_tgzaf) + |
55 | 55 | WARP_UCODE_SIZE(warp_g400_tgzf) + | |
56 | size = ( WARP_UCODE_SIZE( warp_g400_tgz ) + | 56 | WARP_UCODE_SIZE(warp_g400_tgzs) + |
57 | WARP_UCODE_SIZE( warp_g400_tgza ) + | 57 | WARP_UCODE_SIZE(warp_g400_tgzsa) + |
58 | WARP_UCODE_SIZE( warp_g400_tgzaf ) + | 58 | WARP_UCODE_SIZE(warp_g400_tgzsaf) + |
59 | WARP_UCODE_SIZE( warp_g400_tgzf ) + | 59 | WARP_UCODE_SIZE(warp_g400_tgzsf) + |
60 | WARP_UCODE_SIZE( warp_g400_tgzs ) + | 60 | WARP_UCODE_SIZE(warp_g400_t2gz) + |
61 | WARP_UCODE_SIZE( warp_g400_tgzsa ) + | 61 | WARP_UCODE_SIZE(warp_g400_t2gza) + |
62 | WARP_UCODE_SIZE( warp_g400_tgzsaf ) + | 62 | WARP_UCODE_SIZE(warp_g400_t2gzaf) + |
63 | WARP_UCODE_SIZE( warp_g400_tgzsf ) + | 63 | WARP_UCODE_SIZE(warp_g400_t2gzf) + |
64 | WARP_UCODE_SIZE( warp_g400_t2gz ) + | 64 | WARP_UCODE_SIZE(warp_g400_t2gzs) + |
65 | WARP_UCODE_SIZE( warp_g400_t2gza ) + | 65 | WARP_UCODE_SIZE(warp_g400_t2gzsa) + |
66 | WARP_UCODE_SIZE( warp_g400_t2gzaf ) + | 66 | WARP_UCODE_SIZE(warp_g400_t2gzsaf) + |
67 | WARP_UCODE_SIZE( warp_g400_t2gzf ) + | 67 | WARP_UCODE_SIZE(warp_g400_t2gzsf)); |
68 | WARP_UCODE_SIZE( warp_g400_t2gzs ) + | 68 | |
69 | WARP_UCODE_SIZE( warp_g400_t2gzsa ) + | 69 | static const unsigned int mga_warp_g200_microcode_size = |
70 | WARP_UCODE_SIZE( warp_g400_t2gzsaf ) + | 70 | (WARP_UCODE_SIZE(warp_g200_tgz) + |
71 | WARP_UCODE_SIZE( warp_g400_t2gzsf ) ); | 71 | WARP_UCODE_SIZE(warp_g200_tgza) + |
72 | 72 | WARP_UCODE_SIZE(warp_g200_tgzaf) + | |
73 | size = PAGE_ALIGN( size ); | 73 | WARP_UCODE_SIZE(warp_g200_tgzf) + |
74 | 74 | WARP_UCODE_SIZE(warp_g200_tgzs) + | |
75 | DRM_DEBUG( "G400 ucode size = %d bytes\n", size ); | 75 | WARP_UCODE_SIZE(warp_g200_tgzsa) + |
76 | return size; | 76 | WARP_UCODE_SIZE(warp_g200_tgzsaf) + |
77 | } | 77 | WARP_UCODE_SIZE(warp_g200_tgzsf)); |
78 | 78 | ||
79 | static unsigned int mga_warp_g200_microcode_size( drm_mga_private_t *dev_priv ) | 79 | |
80 | unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv) | ||
80 | { | 81 | { |
81 | unsigned int size; | 82 | switch (dev_priv->chipset) { |
82 | 83 | case MGA_CARD_TYPE_G400: | |
83 | size = ( WARP_UCODE_SIZE( warp_g200_tgz ) + | 84 | case MGA_CARD_TYPE_G550: |
84 | WARP_UCODE_SIZE( warp_g200_tgza ) + | 85 | return PAGE_ALIGN(mga_warp_g400_microcode_size); |
85 | WARP_UCODE_SIZE( warp_g200_tgzaf ) + | 86 | case MGA_CARD_TYPE_G200: |
86 | WARP_UCODE_SIZE( warp_g200_tgzf ) + | 87 | return PAGE_ALIGN(mga_warp_g200_microcode_size); |
87 | WARP_UCODE_SIZE( warp_g200_tgzs ) + | 88 | default: |
88 | WARP_UCODE_SIZE( warp_g200_tgzsa ) + | 89 | return 0; |
89 | WARP_UCODE_SIZE( warp_g200_tgzsaf ) + | 90 | } |
90 | WARP_UCODE_SIZE( warp_g200_tgzsf ) ); | ||
91 | |||
92 | size = PAGE_ALIGN( size ); | ||
93 | |||
94 | DRM_DEBUG( "G200 ucode size = %d bytes\n", size ); | ||
95 | return size; | ||
96 | } | 91 | } |
97 | 92 | ||
98 | static int mga_warp_install_g400_microcode( drm_mga_private_t *dev_priv ) | 93 | static int mga_warp_install_g400_microcode( drm_mga_private_t *dev_priv ) |
99 | { | 94 | { |
100 | unsigned char *vcbase = dev_priv->warp->handle; | 95 | unsigned char *vcbase = dev_priv->warp->handle; |
101 | unsigned long pcbase = dev_priv->warp->offset; | 96 | unsigned long pcbase = dev_priv->warp->offset; |
102 | unsigned int size; | ||
103 | |||
104 | size = mga_warp_g400_microcode_size( dev_priv ); | ||
105 | if ( size > dev_priv->warp->size ) { | ||
106 | DRM_ERROR( "microcode too large! (%u > %lu)\n", | ||
107 | size, dev_priv->warp->size ); | ||
108 | return DRM_ERR(ENOMEM); | ||
109 | } | ||
110 | 97 | ||
111 | memset( dev_priv->warp_pipe_phys, 0, | 98 | memset( dev_priv->warp_pipe_phys, 0, |
112 | sizeof(dev_priv->warp_pipe_phys) ); | 99 | sizeof(dev_priv->warp_pipe_phys) ); |
@@ -136,35 +123,36 @@ static int mga_warp_install_g200_microcode( drm_mga_private_t *dev_priv ) | |||
136 | { | 123 | { |
137 | unsigned char *vcbase = dev_priv->warp->handle; | 124 | unsigned char *vcbase = dev_priv->warp->handle; |
138 | unsigned long pcbase = dev_priv->warp->offset; | 125 | unsigned long pcbase = dev_priv->warp->offset; |
139 | unsigned int size; | ||
140 | |||
141 | size = mga_warp_g200_microcode_size( dev_priv ); | ||
142 | if ( size > dev_priv->warp->size ) { | ||
143 | DRM_ERROR( "microcode too large! (%u > %lu)\n", | ||
144 | size, dev_priv->warp->size ); | ||
145 | return DRM_ERR(ENOMEM); | ||
146 | } | ||
147 | 126 | ||
148 | memset( dev_priv->warp_pipe_phys, 0, | 127 | memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys)); |
149 | sizeof(dev_priv->warp_pipe_phys) ); | ||
150 | 128 | ||
151 | WARP_UCODE_INSTALL( warp_g200_tgz, MGA_WARP_TGZ ); | 129 | WARP_UCODE_INSTALL(warp_g200_tgz, MGA_WARP_TGZ); |
152 | WARP_UCODE_INSTALL( warp_g200_tgzf, MGA_WARP_TGZF ); | 130 | WARP_UCODE_INSTALL(warp_g200_tgzf, MGA_WARP_TGZF); |
153 | WARP_UCODE_INSTALL( warp_g200_tgza, MGA_WARP_TGZA ); | 131 | WARP_UCODE_INSTALL(warp_g200_tgza, MGA_WARP_TGZA); |
154 | WARP_UCODE_INSTALL( warp_g200_tgzaf, MGA_WARP_TGZAF ); | 132 | WARP_UCODE_INSTALL(warp_g200_tgzaf, MGA_WARP_TGZAF); |
155 | WARP_UCODE_INSTALL( warp_g200_tgzs, MGA_WARP_TGZS ); | 133 | WARP_UCODE_INSTALL(warp_g200_tgzs, MGA_WARP_TGZS); |
156 | WARP_UCODE_INSTALL( warp_g200_tgzsf, MGA_WARP_TGZSF ); | 134 | WARP_UCODE_INSTALL(warp_g200_tgzsf, MGA_WARP_TGZSF); |
157 | WARP_UCODE_INSTALL( warp_g200_tgzsa, MGA_WARP_TGZSA ); | 135 | WARP_UCODE_INSTALL(warp_g200_tgzsa, MGA_WARP_TGZSA); |
158 | WARP_UCODE_INSTALL( warp_g200_tgzsaf, MGA_WARP_TGZSAF ); | 136 | WARP_UCODE_INSTALL(warp_g200_tgzsaf, MGA_WARP_TGZSAF); |
159 | 137 | ||
160 | return 0; | 138 | return 0; |
161 | } | 139 | } |
162 | 140 | ||
163 | int mga_warp_install_microcode( drm_mga_private_t *dev_priv ) | 141 | int mga_warp_install_microcode( drm_mga_private_t *dev_priv ) |
164 | { | 142 | { |
165 | switch ( dev_priv->chipset ) { | 143 | const unsigned int size = mga_warp_microcode_size(dev_priv); |
144 | |||
145 | DRM_DEBUG("MGA ucode size = %d bytes\n", size); | ||
146 | if (size > dev_priv->warp->size) { | ||
147 | DRM_ERROR("microcode too large! (%u > %lu)\n", | ||
148 | size, dev_priv->warp->size); | ||
149 | return DRM_ERR(ENOMEM); | ||
150 | } | ||
151 | |||
152 | switch (dev_priv->chipset) { | ||
166 | case MGA_CARD_TYPE_G400: | 153 | case MGA_CARD_TYPE_G400: |
167 | return mga_warp_install_g400_microcode( dev_priv ); | 154 | case MGA_CARD_TYPE_G550: |
155 | return mga_warp_install_g400_microcode(dev_priv); | ||
168 | case MGA_CARD_TYPE_G200: | 156 | case MGA_CARD_TYPE_G200: |
169 | return mga_warp_install_g200_microcode( dev_priv ); | 157 | return mga_warp_install_g200_microcode( dev_priv ); |
170 | default: | 158 | default: |
@@ -182,10 +170,11 @@ int mga_warp_init( drm_mga_private_t *dev_priv ) | |||
182 | */ | 170 | */ |
183 | switch ( dev_priv->chipset ) { | 171 | switch ( dev_priv->chipset ) { |
184 | case MGA_CARD_TYPE_G400: | 172 | case MGA_CARD_TYPE_G400: |
185 | MGA_WRITE( MGA_WIADDR2, MGA_WMODE_SUSPEND ); | 173 | case MGA_CARD_TYPE_G550: |
186 | MGA_WRITE( MGA_WGETMSB, 0x00000E00 ); | 174 | MGA_WRITE(MGA_WIADDR2, MGA_WMODE_SUSPEND); |
187 | MGA_WRITE( MGA_WVRTXSZ, 0x00001807 ); | 175 | MGA_WRITE(MGA_WGETMSB, 0x00000E00); |
188 | MGA_WRITE( MGA_WACCEPTSEQ, 0x18000000 ); | 176 | MGA_WRITE(MGA_WVRTXSZ, 0x00001807); |
177 | MGA_WRITE(MGA_WACCEPTSEQ, 0x18000000); | ||
189 | break; | 178 | break; |
190 | case MGA_CARD_TYPE_G200: | 179 | case MGA_CARD_TYPE_G200: |
191 | MGA_WRITE( MGA_WIADDR, MGA_WMODE_SUSPEND ); | 180 | MGA_WRITE( MGA_WIADDR, MGA_WMODE_SUSPEND ); |