summaryrefslogtreecommitdiff
path: root/linux-core/drm_drv.c
AgeCommit message (Collapse)Author
2007-05-26drm: cleanup use of Linux list handling macrosDave Airlie
This makes the drms use of the list handling macros a lot cleaner and more along the lines of how they should be used.
2007-04-28drm: add new drm_wait_on function to replace macroDave Airlie
2007-04-28remove DRM_GETSAREA and replace with drm_getsarea functionDave Airlie
2007-03-20rename badly named defineDave Airlie
2007-03-19cleanup ioctl expansion codeDave Airlie
2007-03-19make drm fops const from kernelDave Airlie
2007-01-25Remove a scary error printed when we were leaking memory caches.Thomas Hellstrom
We don't use memory caches anymore... Fix memory accounting initialization to only use low or DMA32 memory.
2006-12-15Remove the memory caches for fence objects and memory manager nodes,Thomas Hellstrom
since the support for memory caches has gone from 2.6.20.
2006-10-20Bug #8707, 2.6.19-rc compatibility for memory manager code.Thomas Hellstrom
2006-10-17Add vma list memory usage to memory accounting.Thomas Hellstrom
Use byte unit for /proc printout of memory usage for small sizes to be able to detect memory allocation bugs more easily.
2006-10-17Add memory usage accounting to avoid DOS problems.Thomas Hellstrom
2006-10-17Extend generality for more memory types.Thomas Hellstrom
Fix up init and destruction code.
2006-10-11Big update:Thomas Hellstrom
Adapt for new functions in the 2.6.19 kernel. Remove the ability to have multiple regions in one TTM. This simplifies a lot of code. Remove the ability to access TTMs from user space. We don't need it anymore without ttm regions. Don't change caching policy for evicted buffers. Instead change it only when the buffer is accessed by the CPU (on the first page fault). This tremendously speeds up eviction rates. Current code is safe for kernels <= 2.6.14. Should also be OK with 2.6.19 and above.
2006-10-10Use a nopage-based approach to fault in pfns.Thomas Hellstrom
2006-10-03Get rid of all ugly PTE hacks.Thomas Hellstrom
2006-10-02Add a buffer object manager for TTM maps.Thomas Hellstrom
2006-09-29Change first valid DRM drawable ID to be 1 instead of 0.Michel Dänzer
This makes it easier for userspace to know when it needs to allocate an ID. Also free drawable information memory when it's no longer needed. (cherry picked from df7551ef7334d728ec0371423661bb403d3e270a commit)
2006-09-29Hook up DRM_IOCTL_UPDATE_DRAW ioctl.Michel Dänzer
(cherry picked from 98a89504589427a76c3f5cfa2266962a1a212672 commit)
2006-09-05Fix memory cache initialization.Thomas Hellstrom
2006-09-04Make memory caches global so that they can be used withThomas Hellstrom
multiple heads.
2006-09-01Bugfixes,Thomas Hellstrom
Memory allocation optimizations. Buffer manager takedown.
2006-08-30Remove the buffer object hint field and use it onlyThomas Hellstrom
as an argument. Validate stub.
2006-08-30Memory manager init and takedown.Thomas Hellstrom
2006-08-28Merge branch 'master' of git+ssh://git.freedesktop.org/git/mesa/drm into ↵Thomas Hellstrom
drm-ttm-0-2-branch Conflicts: linux-core/drmP.h
2006-08-28add static function, and remove bad attributionsDave Airlie
2006-08-28remove some DRM_ARRAY_SIZE from linux core codeDave Airlie
2006-08-27Remove the ioctl multiplexing, and instead allow for genericThomas Hellstrom
drm ioctls 0x80 - 0xFF.
2006-08-21User / Kernel space fence objects (device-independent part).Thomas Hellstrom
2006-08-21Generic DRM support base-class support for user-space objects, likeThomas Hellstrom
fence objects and buffer objects: Refcounting, Inter-process sharing, Synchronization Destruction.
2006-08-16Remove hash tables on DRM exit.Thomas Hellstrom
2006-08-14Avoid kernel oops in some error paths calling drm_lastclose().Thomas Hellstrom
2006-07-24remove incorrect exit marking on cleanup pci as this is called from other pathsDave Airlie
2006-07-24switch drm to use Linux mutexes instead of semaphore.Dave Airlie
I hope the fallback compat code works if not shout at me.
2006-06-06Fix drm_remove_magic potential memory leak / corruption. Move drmThomas Hellstrom
authentication token hashing to new generic hash table implementation.
2006-04-03make add context non master...Dave Airlie
2006-02-18major realigment of DRM CVS with kernel code, makes integration much easierDave Airlie
2006-02-18fix card unloadDave Airlie
2006-01-02use drm_cards_limit instead of cards_limitDave Airlie
2005-11-11A bunch of create_proc_dir_entry() calls creating directories had crept inDave Airlie
since the last sweep; converted to proc_mkdir(). From: Al Viro (via kernel)
2005-11-03Converts the remaining drm_agp_foo functions to be a drm_agp_foo andIan Romanick
drm_agp_foo_ioctl pair. Modifies the MGA DRM to use the drm_agp_foo functions instead of the drm_foo_agp functions. The drm_foo_agp functions are no longer exported by drm.ko. Ensures that dma->seg_count and dma->page_count are properly set in drm_addbufs_{agp,sg,fb}. drm_addbufs_pci was already correct. Ensures that mga_do_agp_dma_bootstrap correctly sets agp_buffer_token. At this point PCI DMA is still broken. Xorg bug: #4797 Reviewed by: Dave Airlie, Eric Anholt Signed-off-by: Ian Romanick <idr@us.ibm.com>
2005-09-03convert ioctl flags to use flags instead of separate intsDave Airlie
2005-08-05Rename the driver hooks in the DRM to something a little moreEric Anholt
understandable: preinit -> load postinit -> (removed) presetup -> firstopen postsetup -> (removed) open_helper -> open prerelease -> preclose free_filp_priv -> postclose pretakedown -> lastclose postcleanup -> unload release -> reclaim_buffers_locked version -> (removed) postinit and version were replaced with generic code in the Linux DRM (drivers now set their version numbers and description in the driver structure, like on BSD). postsetup wasn't used at all. Fixes the savage hooks for initializing and tearing down mappings at the right times. Testing involved at least starting X, running glxgears, killing glxgears, exiting X, and repeating. Tested on: FreeBSD (g200, g400, r200, r128) Linux (r200, savage4)
2005-08-04Split the control of master vs root priv. Everything is still marked asJon Smirl
needing root.
2005-06-28- Remove drm_initmap and replace its usage with drm_addmap. This reducesEric Anholt
code duplication, and it also hands you the map pointer so you don't need to re-find it. - Remove the permanent maps flag. Instead, for register and framebuffer maps, we always check whether there's already a map of that type and offset around. Move the Radeon map initialization into presetup (first open) so it happens again after every takedown. - Remove the split cleanup of maps between driver takedown (last close) and cleanup (module unload). Instead, always tear down maps on takedown, and drivers can recreate them on first open. - Make MGA always use addmap, instead of allocating consistent memory in the PCI case and then faking up a map for it, which accomplished nearly the same thing, in a different order. Note that the maps are exposed to the user again: we may want to expose a flag to avoid this, but it's not a security concern, and saves us a lot of code. - Remove rmmaps in the MGA driver. Since the function is only called during takedown anyway, we can let them die a natural death. - Make removal of maps happen in one function, which is called by both drm_takedown and drm_rmmap_ioctl. Reviewed by: idr (previous revision) Tested on: mga (old/new/pci dma), radeon, savage
2005-06-28Given that BenH says using the sysdev approach for DRM is bogus, I'll yankAlan Hourihane
the code for it, rather than introducing something that isn't going to work 100% of the time.
2005-06-24Make sysdev class only register when fbdev detectedJon Smirl
2005-06-24More err path clean up for drm_pm Add mandatory sysdev shutdown functionJon Smirl
2005-06-22Get the power management hooks into the right place so that everything getsJon Smirl
freed correctly.
2005-06-14Adds support for PCI cards to MGA DRMIan Romanick
This patch adds serveral new ioctls and a new query to get_param query to support PCI MGA cards. Two ioctls were added to implement interrupt based waiting. With this change, the client-side driver no longer needs to map the primary DMA region or the MMIO region. Previously, end-of-frame waiting was done by busy waiting in the client-side driver until one of the MMIO registers (the current DMA pointer) matched a pointer to the end of primary DMA space. By using interrupts, the busy waiting and the extra mappings are removed. A third ioctl was added to bootstrap DMA. This ioctl, which is used by the X-server, moves a *LOT* of code from the X-server into the kernel. This allows the kernel to do whatever needs to be done to setup DMA buffers. The entire process and the locations of the buffers are hidden from user-mode. Additionally, a get_param query was added to differentiate between G4x0 cards and G550 cards. A gap was left in the numbering sequence so that, if needed, G450 cards could be distinguished from G400 cards. According to Ville Syrjälä, the G4x0 cards and the G550 cards handle anisotropic filtering differently. This seems the most compatible way to let the client-side driver know which card it's own. Doing this very small change now eliminates the need to bump the DRM minor version twice. http://marc.theaimsgroup.com/?l=dri-devel&m=106625815319773&w=2 A number of ioctl handlers in linux-core were also modified so that they could be called in-kernel. In these cases, the in-kernel callable version kept the existing name (e.g., drm_agp_acquire) and the ioctl handler added _ioctl to the name (e.g., drm_agp_acquire_ioctl). This patch also replaces the drm_agp_do_release function with drm_agp_release. drm_agp_release (drm_core_agp_release in the previous patch) is very similar to drm_agp_do_release, and I saw no reason to have both. This commit *breaks the build* on BSD. Eric said that he would make the required updates to the BSD side soon. Xorg bug: 3259 Reviewed by: Eric Anholt
2005-06-09drm_mem_init should be done at core load, not driver initJon Smirl
6' href='#n766'>766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109
/* mga_state.c -- State support for mga g200/g400
 * Created: Thu Jan 27 02:53:43 2000 by jhartmann@precisioninsight.com
 *
 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 * Authors: Jeff Hartmann <jhartmann@precisioninsight.com>
 * 	    Keith Whitwell <keithw@precisioninsight.com>
 *
 */

#define __NO_VERSION__
#include "drmP.h"
#include "mga_drv.h"
#include "drm.h"

typedef u_int16_t u16;
typedef u_int32_t u32;

#define MGAEMITCLIP_SIZE        10
#define MGAEMITCTX_SIZE         20
#define MGAG200EMITTEX_SIZE     20
#define MGAG400EMITTEX0_SIZE    30
#define MGAG400EMITTEX1_SIZE    25
#define MGAG400EMITPIPE_SIZE    50
#define MGAG200EMITPIPE_SIZE    15

#define MAX_STATE_SIZE ((MGAEMITCLIP_SIZE * MGA_NR_SAREA_CLIPRECTS) + \
                        MGAEMITCTX_SIZE + MGAG400EMITTEX0_SIZE + \
                        MGAG400EMITTEX1_SIZE + MGAG400EMITPIPE_SIZE)



static void mgaEmitClipRect(drm_mga_private_t * dev_priv,
			    drm_clip_rect_t * box)
{
	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
	unsigned int *regs = sarea_priv->ContextState;
	PRIMLOCALS;
	DRM_DEBUG("%s\n", __FUNCTION__);

	/* This takes 10 dwords */
	PRIMGETPTR(dev_priv);

	/* Force reset of dwgctl (eliminates clip disable) */
	if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
#if 0
	PRIMOUTREG(MGAREG_DMAPAD, 0);
	PRIMOUTREG(MGAREG_DWGSYNC, 0);
	PRIMOUTREG(MGAREG_DWGSYNC, 0);
	PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
#else
	PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
	PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0x80000000);
	PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
	PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0x80000000);
#endif
	}
	PRIMOUTREG(MGAREG_DMAPAD, 0);
	PRIMOUTREG(MGAREG_CXBNDRY, ((box->x2) << 16) | (box->x1));
	PRIMOUTREG(MGAREG_YTOP, box->y1 * dev_priv->stride / dev_priv->cpp);
	PRIMOUTREG(MGAREG_YBOT, box->y2 * dev_priv->stride / dev_priv->cpp);

	PRIMADVANCE(dev_priv);
}

static void mgaEmitContext(drm_mga_private_t * dev_priv)
{
	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
	unsigned int *regs = sarea_priv->ContextState;
	PRIMLOCALS;
	DRM_DEBUG("%s\n", __FUNCTION__);

	/* This takes a max of 20 dwords */
	PRIMGETPTR(dev_priv);

	PRIMOUTREG(MGAREG_DSTORG, regs[MGA_CTXREG_DSTORG]);
	PRIMOUTREG(MGAREG_MACCESS, regs[MGA_CTXREG_MACCESS]);
	PRIMOUTREG(MGAREG_PLNWT, regs[MGA_CTXREG_PLNWT]);
	PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);

	PRIMOUTREG(MGAREG_ALPHACTRL, regs[MGA_CTXREG_ALPHACTRL]);
	PRIMOUTREG(MGAREG_FOGCOL, regs[MGA_CTXREG_FOGCOLOR]);
	PRIMOUTREG(MGAREG_WFLAG, regs[MGA_CTXREG_WFLAG]);
	PRIMOUTREG(MGAREG_ZORG, dev_priv->depthOffset);	/* invarient */

	if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
		PRIMOUTREG(MGAREG_WFLAG1, regs[MGA_CTXREG_WFLAG]);
		PRIMOUTREG(MGAREG_TDUALSTAGE0, regs[MGA_CTXREG_TDUAL0]);
		PRIMOUTREG(MGAREG_TDUALSTAGE1, regs[MGA_CTXREG_TDUAL1]);
		PRIMOUTREG(MGAREG_FCOL, regs[MGA_CTXREG_FCOL]);

                PRIMOUTREG(MGAREG_STENCIL, regs[MGA_CTXREG_STENCIL]);
                PRIMOUTREG(MGAREG_STENCILCTL, regs[MGA_CTXREG_STENCILCTL]);
                PRIMOUTREG(MGAREG_DMAPAD, 0);
                PRIMOUTREG(MGAREG_DMAPAD, 0);

	} else {
		PRIMOUTREG(MGAREG_FCOL, regs[MGA_CTXREG_FCOL]);
		PRIMOUTREG(MGAREG_DMAPAD, 0);
		PRIMOUTREG(MGAREG_DMAPAD, 0);
		PRIMOUTREG(MGAREG_DMAPAD, 0);
	}

	PRIMADVANCE(dev_priv);
}

static void mgaG200EmitTex(drm_mga_private_t * dev_priv)
{
	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
	unsigned int *regs = sarea_priv->TexState[0];
	PRIMLOCALS;
	DRM_DEBUG("%s\n", __FUNCTION__);

	PRIMGETPTR(dev_priv);

	/* This takes 20 dwords */

	PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2]);
	PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL]);
	PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER]);
	PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL]);

	PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG]);
	PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1]);
	PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2]);
	PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3]);

	PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4]);
	PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH]);
	PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT]);
	PRIMOUTREG(MGAREG_WR24, regs[MGA_TEXREG_WIDTH]);

	PRIMOUTREG(MGAREG_WR34, regs[MGA_TEXREG_HEIGHT]);
	PRIMOUTREG(MGAREG_TEXTRANS, 0xffff);
	PRIMOUTREG(MGAREG_TEXTRANSHIGH, 0xffff);
	PRIMOUTREG(MGAREG_DMAPAD, 0);

	PRIMADVANCE(dev_priv);
}

#define TMC_dualtex_enable              0x80

static void mgaG400EmitTex0(drm_mga_private_t * dev_priv)
{
	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
	unsigned int *regs = sarea_priv->TexState[0];
	PRIMLOCALS;
	DRM_DEBUG("%s\n", __FUNCTION__);

	PRIMGETPTR(dev_priv);

	/* This takes a max of 30 dwords */

	PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] | 0x00008000);
	PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL]);
	PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER]);
	PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL]);

	PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG]);
	PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1]);
	PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2]);
	PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3]);

	PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4]);
	PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH]);
	PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT]);
        PRIMOUTREG(MGAREG_WR49, 0);

        PRIMOUTREG(MGAREG_WR57, 0);
        PRIMOUTREG(MGAREG_WR53, 0);
        PRIMOUTREG(MGAREG_WR61, 0);
        PRIMOUTREG(MGAREG_WR52, 0x40);

        PRIMOUTREG(MGAREG_WR60, 0x40);
        PRIMOUTREG(MGAREG_WR54, regs[MGA_TEXREG_WIDTH] | 0x40);
        PRIMOUTREG(MGAREG_WR62, regs[MGA_TEXREG_HEIGHT] | 0x40);
	PRIMOUTREG(MGAREG_DMAPAD, 0);

		PRIMOUTREG(MGAREG_DMAPAD, 0);
		PRIMOUTREG(MGAREG_DMAPAD, 0);

	PRIMOUTREG(MGAREG_TEXTRANS, 0xffff);
	PRIMOUTREG(MGAREG_TEXTRANSHIGH, 0xffff);

	PRIMADVANCE(dev_priv);
}

#define TMC_map1_enable 		0x80000000

static void mgaG400EmitTex1(drm_mga_private_t * dev_priv)
{
	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
	unsigned int *regs = sarea_priv->TexState[1];
	PRIMLOCALS;
	DRM_DEBUG("%s\n", __FUNCTION__);

	PRIMGETPTR(dev_priv);

	/* This takes 25 dwords */

	PRIMOUTREG(MGAREG_TEXCTL2,
		   regs[MGA_TEXREG_CTL2] | TMC_map1_enable | 0x00008000);
	PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL]);
	PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER]);
	PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL]);

	PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG]);
	PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1]);
	PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2]);
	PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3]);

	PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4]);
	PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH]);
	PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT]);
        PRIMOUTREG(MGAREG_WR49, 0);

        PRIMOUTREG(MGAREG_WR57, 0);
        PRIMOUTREG(MGAREG_WR53, 0);
        PRIMOUTREG(MGAREG_WR61, 0);
        PRIMOUTREG(MGAREG_WR52, regs[MGA_TEXREG_WIDTH] | 0x40);

        PRIMOUTREG(MGAREG_WR60, regs[MGA_TEXREG_HEIGHT] | 0x40);

	PRIMOUTREG(MGAREG_TEXTRANS, 0xffff);
	PRIMOUTREG(MGAREG_TEXTRANSHIGH, 0xffff);
	PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] | 0x00008000);

	PRIMADVANCE(dev_priv);
}

#define MAGIC_FPARAM_HEX_VALUE 0x46480000
/* This is the hex value of 12800.0f which is a magic value we must
 * set in wr56.
 */


#define EMIT_PIPE 50
static void mgaG400EmitPipe(drm_mga_private_t * dev_priv)
{
	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
	unsigned int pipe = sarea_priv->WarpPipe;
	PRIMLOCALS;
	DRM_DEBUG("%s\n", __FUNCTION__);

	PRIMGETPTR(dev_priv);

	/* This takes 50 dwords */

	/* Establish vertex size.  
	 */
	PRIMOUTREG(MGAREG_WIADDR2, WIA_wmode_suspend);
	PRIMOUTREG(MGAREG_DMAPAD, 0);
	PRIMOUTREG(MGAREG_DMAPAD, 0);
	PRIMOUTREG(MGAREG_DMAPAD, 0);

	if (pipe & MGA_T2) {
		PRIMOUTREG(MGAREG_WVRTXSZ, 0x00001e09);
		PRIMOUTREG(MGAREG_DMAPAD, 0);
		PRIMOUTREG(MGAREG_DMAPAD, 0);
		PRIMOUTREG(MGAREG_DMAPAD, 0);

		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0x1e000000);
	} else {
		if (dev_priv->WarpPipe & MGA_T2) {
			/* Flush the WARP pipe */
			PRIMOUTREG(MGAREG_YDST, 0);
			PRIMOUTREG(MGAREG_FXLEFT, 0);
			PRIMOUTREG(MGAREG_FXRIGHT, 1);
			PRIMOUTREG(MGAREG_DWGCTL, MGA_FLUSH_CMD);

			PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 1);
			PRIMOUTREG(MGAREG_DWGSYNC, 0x7000);
			PRIMOUTREG(MGAREG_TEXCTL2, 0x00008000);
			PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0);

			PRIMOUTREG(MGAREG_TEXCTL2, 0x80 | 0x00008000);
			PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0);
			PRIMOUTREG(MGAREG_TEXCTL2, 0x00008000);
			PRIMOUTREG(MGAREG_DMAPAD, 0);
		}

		PRIMOUTREG(MGAREG_WVRTXSZ, 0x00001807);
		PRIMOUTREG(MGAREG_DMAPAD, 0);
		PRIMOUTREG(MGAREG_DMAPAD, 0);
		PRIMOUTREG(MGAREG_DMAPAD, 0);

		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0x18000000);
	}

	PRIMOUTREG(MGAREG_WFLAG, 0);
	PRIMOUTREG(MGAREG_WFLAG1, 0);
	PRIMOUTREG(MGAREG_WR56, MAGIC_FPARAM_HEX_VALUE);
	PRIMOUTREG(MGAREG_DMAPAD, 0);

        PRIMOUTREG(MGAREG_WR49, 0);     /* Tex stage 0 */
        PRIMOUTREG(MGAREG_WR57, 0);     /* Tex stage 0 */
        PRIMOUTREG(MGAREG_WR53, 0);     /* Tex stage 1 */
        PRIMOUTREG(MGAREG_WR61, 0);     /* Tex stage 1 */


        PRIMOUTREG(MGAREG_WR54, 0x40);  /* Tex stage 0 : w */
        PRIMOUTREG(MGAREG_WR62, 0x40);  /* Tex stage 0 : h */
        PRIMOUTREG(MGAREG_WR52, 0x40);  /* Tex stage 1 : w */
        PRIMOUTREG(MGAREG_WR60, 0x40);  /* Tex stage 1 : h */


	/* Dma pading required due to hw bug */
	PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
	PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
	PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
	PRIMOUTREG(MGAREG_WIADDR2,
		   (u32) (dev_priv->WarpIndex[pipe].
			  phys_addr | WIA_wmode_start | WIA_wagp_agp));
	PRIMADVANCE(dev_priv);
}

static void mgaG200EmitPipe(drm_mga_private_t * dev_priv)
{
	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
	unsigned int pipe = sarea_priv->WarpPipe;
	PRIMLOCALS;
	DRM_DEBUG("%s\n", __FUNCTION__);

	PRIMGETPTR(dev_priv);

	/* This takes 15 dwords */

	PRIMOUTREG(MGAREG_WIADDR, WIA_wmode_suspend);
	PRIMOUTREG(MGAREG_WVRTXSZ, 7);
	PRIMOUTREG(MGAREG_WFLAG, 0);
	PRIMOUTREG(MGAREG_WR24, 0);     /* tex w/h */

        PRIMOUTREG(MGAREG_WR25, 0x100);
        PRIMOUTREG(MGAREG_WR34, 0);     /* tex w/h */
        PRIMOUTREG(MGAREG_WR42, 0xFFFF);
        PRIMOUTREG(MGAREG_WR60, 0xFFFF);

	/* Dma pading required due to hw bug */
	PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
	PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
	PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
	PRIMOUTREG(MGAREG_WIADDR,
		   (u32) (dev_priv->WarpIndex[pipe].
			  phys_addr | WIA_wmode_start | WIA_wagp_agp));

	PRIMADVANCE(dev_priv);
}

static void mgaEmitState(drm_mga_private_t * dev_priv)
{
	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
	unsigned int dirty = sarea_priv->dirty;
	DRM_DEBUG("%s\n", __FUNCTION__);

	if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
		int multitex = sarea_priv->WarpPipe & MGA_T2;

		if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
			mgaG400EmitPipe(dev_priv);
			dev_priv->WarpPipe = sarea_priv->WarpPipe;
		}

		if (dirty & MGA_UPLOAD_CTX) {
			mgaEmitContext(dev_priv);
			sarea_priv->dirty &= ~MGA_UPLOAD_CTX;
		}

		if (dirty & MGA_UPLOAD_TEX0) {
			mgaG400EmitTex0(dev_priv);
			sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
		}

		if ((dirty & MGA_UPLOAD_TEX1) && multitex) {
			mgaG400EmitTex1(dev_priv);
			sarea_priv->dirty &= ~MGA_UPLOAD_TEX1;
		}
	} else {
		if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
			mgaG200EmitPipe(dev_priv);
			dev_priv->WarpPipe = sarea_priv->WarpPipe;
		}

		if (dirty & MGA_UPLOAD_CTX) {
			mgaEmitContext(dev_priv);
			sarea_priv->dirty &= ~MGA_UPLOAD_CTX;
		}

		if (dirty & MGA_UPLOAD_TEX0) {
			mgaG200EmitTex(dev_priv);
			sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
		}
	}
}


/* Disallow all write destinations except the front and backbuffer.
 */
static int mgaVerifyContext(drm_mga_private_t * dev_priv)
{
	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
	unsigned int *regs = sarea_priv->ContextState;

	DRM_DEBUG("%s\n", __FUNCTION__);

	if (regs[MGA_CTXREG_DSTORG] != dev_priv->frontOffset &&
	    regs[MGA_CTXREG_DSTORG] != dev_priv->backOffset) {
		DRM_DEBUG("BAD DSTORG: %x (front %x, back %x)\n\n",
			  regs[MGA_CTXREG_DSTORG], dev_priv->frontOffset,
			  dev_priv->backOffset);
		regs[MGA_CTXREG_DSTORG] = 0;
		return -1;
	}

	return 0;
}

/* Disallow texture reads from PCI space.
 */
static int mgaVerifyTex(drm_mga_private_t * dev_priv, int unit)
{
	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;

	DRM_DEBUG("%s\n", __FUNCTION__);

	if ((sarea_priv->TexState[unit][MGA_TEXREG_ORG] & 0x3) == 0x1) {
		DRM_DEBUG("BAD TEXREG_ORG: %x, unit %d\n",
			  sarea_priv->TexState[unit][MGA_TEXREG_ORG],
			  unit);
		sarea_priv->TexState[unit][MGA_TEXREG_ORG] = 0;
		return -1;
	}

	return 0;
}

static int mgaVerifyState(drm_mga_private_t * dev_priv)
{
	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
	unsigned int dirty = sarea_priv->dirty;
	int rv = 0;

	DRM_DEBUG("%s\n", __FUNCTION__);

	if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
		sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;

	if (dirty & MGA_UPLOAD_CTX)
		rv |= mgaVerifyContext(dev_priv);

	if (dirty & MGA_UPLOAD_TEX0)
		rv |= mgaVerifyTex(dev_priv, 0);

	if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
		if (dirty & MGA_UPLOAD_TEX1)
			rv |= mgaVerifyTex(dev_priv, 1);

		if (dirty & MGA_UPLOAD_PIPE)
			rv |= (sarea_priv->WarpPipe > MGA_MAX_G400_PIPES);
	} else {
		if (dirty & MGA_UPLOAD_PIPE)
			rv |= (sarea_priv->WarpPipe > MGA_MAX_G200_PIPES);
	}

	return rv == 0;
}

static int mgaVerifyIload(drm_mga_private_t * dev_priv,
			  unsigned long bus_address,
			  unsigned int dstOrg, int length)
{
	DRM_DEBUG("%s\n", __FUNCTION__);

	if (dstOrg < dev_priv->textureOffset ||
	    dstOrg + length >
	    (dev_priv->textureOffset + dev_priv->textureSize)) {
		return EINVAL;
	}
	if (length % 64) {
		return EINVAL;
	}
	return 0;
}

/* This copies a 64 byte aligned agp region to the frambuffer
 * with a standard blit, the ioctl needs to do checking */

static void mga_dma_dispatch_tex_blit(drm_device_t * dev,
				      unsigned long bus_address,
				      int length, unsigned int destOrg)
{
	drm_mga_private_t *dev_priv = dev->dev_private;
	int use_agp = PDEA_pagpxfer_enable | 0x00000001;
	u16 y2;
	PRIMLOCALS;
	DRM_DEBUG("%s\n", __FUNCTION__);

	y2 = length / 64;

	PRIM_OVERFLOW(dev, dev_priv, 30);

	PRIMOUTREG(MGAREG_DSTORG, destOrg);
	PRIMOUTREG(MGAREG_MACCESS, 0x00000000);
	DRM_DEBUG("srcorg : %lx\n", bus_address | use_agp);
	PRIMOUTREG(MGAREG_SRCORG, (u32) bus_address | use_agp);
	PRIMOUTREG(MGAREG_AR5, 64);

	PRIMOUTREG(MGAREG_PITCH, 64);
	PRIMOUTREG(MGAREG_DMAPAD, 0);
	PRIMOUTREG(MGAREG_DMAPAD, 0);
	PRIMOUTREG(MGAREG_DWGCTL, MGA_COPY_CMD);

	PRIMOUTREG(MGAREG_AR0, 63);
	PRIMOUTREG(MGAREG_AR3, 0);