lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Fri, 30 May 2008 17:33:54 -0700
From:	Greg KH <gregkh@...e.de>
To:	linux-kernel@...r.kernel.org
Subject: Re: via agp patches

This looks like the meatiest patch, with lots of support for new
hardware.  Gotta love the StudlyCaps...

---
 drivers/char/drm/Kconfig              |    7 
 drivers/char/drm/Makefile             |    2 
 drivers/char/drm/drm_pciids.h         |    9 
 drivers/char/drm/via_chrome9_3d_reg.h |  395 +++++++++++
 drivers/char/drm/via_chrome9_dma.c    | 1147 ++++++++++++++++++++++++++++++++++
 drivers/char/drm/via_chrome9_dma.h    |   68 ++
 drivers/char/drm/via_chrome9_drm.c    |  993 +++++++++++++++++++++++++++++
 drivers/char/drm/via_chrome9_drm.h    |  423 ++++++++++++
 drivers/char/drm/via_chrome9_drv.c    |  153 ++++
 drivers/char/drm/via_chrome9_drv.h    |  145 ++++
 drivers/char/drm/via_chrome9_mm.c     |  388 +++++++++++
 drivers/char/drm/via_chrome9_mm.h     |   67 +
 12 files changed, 3796 insertions(+), 1 deletion(-)

--- a/drivers/char/drm/drm_pciids.h
+++ b/drivers/char/drm/drm_pciids.h
@@ -339,10 +339,17 @@
 	{0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
 	{0x1106, 0x3344, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
 	{0x1106, 0x3343, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-	{0x1106, 0x3230, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_DX9_0}, \
 	{0x1106, 0x3157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_PRO_GROUP_A}, \
 	{0, 0, 0}
 
+
+#define via_chrome9DRV_PCI_IDS \
+	{0x1106, 0x3225, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+	{0x1106, 0x3230, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_CHROME9_DX9_0}, \
+	{0x1106, 0x3371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+	{0x1106, 0x1122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_CHROME9_PCIE_GROUP},\
+	{0, 0, 0}
+
 #define i810_PCI_IDS \
 	{0x8086, 0x7121, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
 	{0x8086, 0x7123, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
--- a/drivers/char/drm/Kconfig
+++ b/drivers/char/drm/Kconfig
@@ -99,6 +99,13 @@ config DRM_VIA
 	  Choose this option if you have a Via unichrome or compatible video
 	  chipset. If M is selected the module will be called via.
 
+config DRM_VIA_CHROME9
+	tristate "Via unichrome9 video cards"
+	depends on DRM
+	help
+	  Choose this option if you have a Via unichrome9 or compatible video
+	  chipset. If M is selected the module will be called via_chrome9.
+
 config DRM_SAVAGE
 	tristate "Savage video cards"
 	depends on DRM
--- a/drivers/char/drm/Makefile
+++ b/drivers/char/drm/Makefile
@@ -18,6 +18,7 @@ radeon-objs := radeon_drv.o radeon_cp.o 
 sis-objs    := sis_drv.o sis_mm.o
 savage-objs := savage_drv.o savage_bci.o savage_state.o
 via-objs    := via_irq.o via_drv.o via_map.o via_mm.o via_dma.o via_verifier.o via_video.o via_dmablit.o
+via_chrome9-objs := via_chrome9_drv.o via_chrome9_drm.o via_chrome9_mm.o via_chrome9_dma.o
 
 ifeq ($(CONFIG_COMPAT),y)
 drm-objs    += drm_ioc32.o
@@ -38,3 +39,4 @@ obj-$(CONFIG_DRM_I915)  += i915.o
 obj-$(CONFIG_DRM_SIS)   += sis.o
 obj-$(CONFIG_DRM_SAVAGE)+= savage.o
 obj-$(CONFIG_DRM_VIA)	+=via.o
+obj-$(CONFIG_DRM_VIA_CHROME9) += via_chrome9.o
--- /dev/null
+++ b/drivers/char/drm/via_chrome9_3d_reg.h
@@ -0,0 +1,395 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license,
+ * 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL VIA, S3 GRAPHICS, 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.
+ */
+
+#ifndef VIA_CHROME9_3D_REG_H
+#define VIA_CHROME9_3D_REG_H
+#define GetMMIORegister(base, offset)      \
+	(*(volatile unsigned int *)(void *)(((unsigned char *)(base)) + \
+	(offset)))
+#define SetMMIORegister(base, offset, val) \
+	(*(volatile unsigned int *)(void *)(((unsigned char *)(base)) + \
+	(offset)) = (val))
+
+#define GetMMIORegisterU8(base, offset)      \
+	(*(volatile unsigned char *)(void *)(((unsigned char *)(base)) + \
+	(offset)))
+#define SetMMIORegisterU8(base, offset, val) \
+	(*(volatile unsigned char *)(void *)(((unsigned char *)(base)) + \
+	(offset)) = (val))
+
+#define BCI_SEND(bci, value)   (*(bci)++ = (unsigned long)(value))
+#define BCI_SET_STREAM_REGISTER(bci_base, bci_index, reg_value)         \
+do {                                                                    \
+	unsigned long cmd;                                              \
+									\
+	cmd = (0x90000000                                               \
+		| (1<<16) /* stream processor register */               \
+		| (bci_index & 0x3FFC)); /* MMIO register address */    \
+	BCI_SEND(bci_base, cmd);                                        \
+	BCI_SEND(bci_base, reg_value);                                  \
+	} while (0)
+
+/* Command Header Type */
+
+#define INV_AGPHeader0              0xFE000000
+#define INV_AGPHeader1              0xFE010000
+#define INV_AGPHeader2              0xFE020000
+#define INV_AGPHeader3              0xFE030000
+#define INV_AGPHeader4              0xFE040000
+#define INV_AGPHeader5              0xFE050000
+#define INV_AGPHeader6              0xFE060000
+#define INV_AGPHeader7              0xFE070000
+#define INV_AGPHeader82             0xFE820000
+#define INV_AGPHeader_MASK          0xFFFF0000
+
+/*send pause address of AGP ring command buffer via_chrome9 this IO port*/
+#define INV_REG_PCIPAUSE            0x294
+#define INV_REG_PCIPAUSE_ENABLE     0x4
+
+#define INV_CMDBUF_THRESHOLD     (8)
+#define INV_QW_PAUSE_ALIGN       0x40
+
+/* Transmission IO Space*/
+#define INV_REG_CR_TRANS            0x041C
+#define INV_REG_CR_BEGIN            0x0420
+#define INV_REG_CR_END              0x0438
+
+#define INV_REG_3D_TRANS            0x043C
+#define INV_REG_3D_BEGIN            0x0440
+#define INV_REG_3D_END              0x06FC
+#define INV_REG_23D_WAIT            0x326C
+/*3D / 2D ID Control (Only For Group A)*/
+#define INV_REG_2D3D_ID_CTRL     0x060
+
+
+/* Engine Status */
+
+#define INV_RB_ENG_STATUS           0x0400
+#define INV_ENG_BUSY_HQV0           0x00040000
+#define INV_ENG_BUSY_HQV1           0x00020000
+#define INV_ENG_BUSY_CR             0x00000010
+#define INV_ENG_BUSY_MPEG           0x00000008
+#define INV_ENG_BUSY_VQ             0x00000004
+#define INV_ENG_BUSY_2D             0x00000002
+#define INV_ENG_BUSY_3D             0x00001FE1
+#define INV_ENG_BUSY_ALL            		\
+	(INV_ENG_BUSY_2D | INV_ENG_BUSY_3D | INV_ENG_BUSY_CR)
+
+/* Command Queue Status*/
+#define INV_RB_VQ_STATUS            0x0448
+#define INV_VQ_FULL                 0x40000000
+
+/* AGP command buffer pointer current position*/
+#define INV_RB_AGPCMD_CURRADDR      0x043C
+
+/* AGP command buffer status*/
+#define INV_RB_AGPCMD_STATUS        0x0444
+#define INV_AGPCMD_InPause          0x80000000
+
+/*AGP command buffer pause address*/
+#define INV_RB_AGPCMD_PAUSEADDR     0x045C
+
+/*AGP command buffer jump address*/
+#define INV_RB_AGPCMD_JUMPADDR      0x0460
+
+/*AGP command buffer start address*/
+#define INV_RB_AGPCMD_STARTADDR      0x0464
+
+
+/* Constants */
+#define NUMBER_OF_EVENT_TAGS        1024
+#define NUMBER_OF_APERTURES_CLB     16
+
+/* Register definition */
+#define HW_SHADOW_ADDR              0x8520
+#define HW_GARTTABLE_ADDR           0x8540
+
+#define INV_HSWFlag_DBGMASK          0x00000FFF
+#define INV_HSWFlag_ENCODEMASK       0x007FFFF0
+#define INV_HSWFlag_ADDRSHFT         8
+#define INV_HSWFlag_DECODEMASK       			\
+	(INV_HSWFlag_ENCODEMASK << INV_HSWFlag_ADDRSHFT)
+#define INV_HSWFlag_ADDR_ENCODE(x)   0xCC000000
+#define INV_HSWFlag_ADDR_DECODE(x)    			\
+	(((unsigned int)x & INV_HSWFlag_DECODEMASK) >> INV_HSWFlag_ADDRSHFT)
+
+
+#define INV_SubA_HAGPBstL        0x60000000
+#define INV_SubA_HAGPBstH        0x61000000
+#define INV_SubA_HAGPBendL       0x62000000
+#define INV_SubA_HAGPBendH       0x63000000
+#define INV_SubA_HAGPBpL         0x64000000
+#define INV_SubA_HAGPBpID        0x65000000
+#define INV_HAGPBpID_PAUSE               0x00000000
+#define INV_HAGPBpID_JUMP                0x00000100
+#define INV_HAGPBpID_STOP                0x00000200
+
+#define INV_HAGPBpH_MASK                 0x000000FF
+#define INV_HAGPBpH_SHFT                 0
+
+#define INV_SubA_HAGPBjumpL      0x66000000
+#define INV_SubA_HAGPBjumpH      0x67000000
+#define INV_HAGPBjumpH_MASK              0x000000FF
+#define INV_HAGPBjumpH_SHFT              0
+
+#define INV_SubA_HFthRCM         0x68000000
+#define INV_HFthRCM_MASK                 0x003F0000
+#define INV_HFthRCM_SHFT                 16
+#define INV_HFthRCM_8                    0x00080000
+#define INV_HFthRCM_10                   0x000A0000
+#define INV_HFthRCM_18                   0x00120000
+#define INV_HFthRCM_24                   0x00180000
+#define INV_HFthRCM_32                   0x00200000
+
+#define INV_HAGPBClear                   0x00000008
+
+#define INV_HRSTTrig_RestoreAGP          0x00000004
+#define INV_HRSTTrig_RestoreAll          0x00000002
+#define INV_HAGPBTrig                    0x00000001
+
+#define INV_ParaSubType_MASK     0xff000000
+#define INV_ParaType_MASK        0x00ff0000
+#define INV_ParaOS_MASK          0x0000ff00
+#define INV_ParaAdr_MASK         0x000000ff
+#define INV_ParaSubType_SHIFT    24
+#define INV_ParaType_SHIFT       16
+#define INV_ParaOS_SHIFT         8
+#define INV_ParaAdr_SHIFT        0
+
+#define INV_ParaType_Vdata       0x00000000
+#define INV_ParaType_Attr        0x00010000
+#define INV_ParaType_Tex         0x00020000
+#define INV_ParaType_Pal         0x00030000
+#define INV_ParaType_FVF         0x00040000
+#define INV_ParaType_PreCR       0x00100000
+#define INV_ParaType_CR          0x00110000
+#define INV_ParaType_Cfg         0x00fe0000
+#define INV_ParaType_Dummy       0x00300000
+
+#define INV_HWBasL_MASK          0x00FFFFFF
+#define INV_HWBasH_MASK          0xFF000000
+#define INV_HWBasH_SHFT          24
+#define INV_HWBasL(x)            ((unsigned int)(x) & INV_HWBasL_MASK)
+#define INV_HWBasH(x)            ((unsigned int)(x) >> INV_HWBasH_SHFT)
+#define INV_HWBas256(x)          ((unsigned int)(x) >> 8)
+#define INV_HWPit32(x)           ((unsigned int)(x) >> 5)
+
+/* Read Back Register Setting */
+#define INV_SubA_HSetRBGID       	 0x02000000
+#define INV_HSetRBGID_CR                 0x00000000
+#define INV_HSetRBGID_FE                 0x00000001
+#define INV_HSetRBGID_PE                 0x00000002
+#define INV_HSetRBGID_RC                 0x00000003
+#define INV_HSetRBGID_PS                 0x00000004
+#define INV_HSetRBGID_XE                 0x00000005
+#define INV_HSetRBGID_BE                 0x00000006
+
+
+struct drm_clb_event_tag_info {
+	unsigned int *linear_address;
+	unsigned int *event_tag_linear_address;
+	int   usage[NUMBER_OF_EVENT_TAGS];
+	unsigned int   pid[NUMBER_OF_EVENT_TAGS];
+};
+
+static inline int IS_AGPHEADER_INV(unsigned int data)
+{
+	switch (data & INV_AGPHeader_MASK) {
+	case INV_AGPHeader0:
+	case INV_AGPHeader1:
+	case INV_AGPHeader2:
+	case INV_AGPHeader3:
+	case INV_AGPHeader4:
+	case INV_AGPHeader5:
+	case INV_AGPHeader6:
+	case INV_AGPHeader7:
+		return TRUE;
+	default:
+		return FALSE;
+	}
+}
+
+/*  Header0: 2D */
+#define ADDCmdHeader0_INVI(pCmd, dwCount)                       \
+{                                                               \
+	/* 4 unsigned int align, insert NULL Command for padding */    \
+	while (((unsigned long *)(pCmd)) & 0xF) {                    \
+		*(pCmd)++ = 0xCC000000;                         \
+	}                                                       \
+	*(pCmd)++ = INV_AGPHeader0;                             \
+	*(pCmd)++ = (dwCount);                                  \
+	*(pCmd)++ = 0;                                          \
+	*(pCmd)++ = (unsigned int)INV_HSWFlag_ADDR_ENCODE(pCmd);       \
+}
+
+/* Header1: 2D */
+#define ADDCmdHeader1_INVI(pCmd, dwAddr, dwCount)               \
+{                                                               \
+	/* 4 unsigned int align, insert NULL Command for padding */    \
+	while (((unsigned long *)(pCmd)) & 0xF) {                    \
+		*(pCmd)++ = 0xCC000000;                         \
+	}                                                       \
+	*(pCmd)++ = INV_AGPHeader1 | (dwAddr);                  \
+	*(pCmd)++ = (dwCount);                                  \
+	*(pCmd)++ = 0;                                          \
+	*(pCmd)++ = (unsigned int)INV_HSWFlag_ADDR_ENCODE(pCmd);       \
+}
+
+/* Header2: CR/3D */
+#define ADDCmdHeader2_INVI(pCmd, dwAddr, dwType)                \
+{                                                               \
+	/* 4 unsigned int align, insert NULL Command for padding */    \
+	while (((unsigned int)(pCmd)) & 0xF) {                        \
+		*(pCmd)++ = 0xCC000000;                         \
+	}                                                       \
+	*(pCmd)++ = INV_AGPHeader2 | ((dwAddr)+4);              \
+	*(pCmd)++ = (dwAddr);                                   \
+	*(pCmd)++ = (dwType);                                   \
+	*(pCmd)++ = (unsigned int)INV_HSWFlag_ADDR_ENCODE(pCmd);       \
+}
+
+/* Header2: CR/3D with SW Flag */
+#define ADDCmdHeader2_SWFlag_INVI(pCmd, dwAddr, dwType, dwSWFlag)  \
+{                                                                  \
+	/* 4 unsigned int align, insert NULL Command for padding */       \
+	while (((unsigned long *)(pCmd)) & 0xF) {			   \
+		*(pCmd)++ = 0xCC000000;                            \
+	}                                                          \
+	*(pCmd)++ = INV_AGPHeader2 | ((dwAddr)+4);                 \
+	*(pCmd)++ = (dwAddr);                                      \
+	*(pCmd)++ = (dwType);                                      \
+	*(pCmd)++ = (dwSWFlag);                                    \
+}
+
+
+/* Header3: 3D */
+#define ADDCmdHeader3_INVI(pCmd, dwType, dwStart, dwCount)      \
+{                                                               \
+	/* 4 unsigned int align, insert NULL Command for padding */    \
+	while (((unsigned long *)(pCmd)) & 0xF) {			\
+		*(pCmd)++ = 0xCC000000;                         \
+	}                                                       \
+	*(pCmd)++ = INV_AGPHeader3 | INV_REG_3D_TRANS;          \
+	*(pCmd)++ = (dwCount);                                  \
+	*(pCmd)++ = (dwType) | ((dwStart) & 0xFFFF);            \
+	*(pCmd)++ = (unsigned int)INV_HSWFlag_ADDR_ENCODE(pCmd);       \
+}
+
+/* Header3: 3D with SW Flag */
+#define ADDCmdHeader3_SWFlag_INVI(pCmd, dwType, dwStart, dwSWFlag, dwCount)  \
+{                                                                            \
+	/* 4 unsigned int align, insert NULL Command for padding */          \
+	while (((unsigned long *)(pCmd)) & 0xF) {                           \
+		*(pCmd)++ = 0xCC000000;                                      \
+	}                                                                    \
+	*(pCmd)++ = INV_AGPHeader3 | INV_REG_3D_TRANS;                       \
+	*(pCmd)++ = (dwCount);                                               \
+	*(pCmd)++ = (dwType) | ((dwStart) & 0xFFFF);                         \
+	*(pCmd)++ = (dwSWFlag);                                              \
+}
+
+/* Header4: DVD */
+#define ADDCmdHeader4_INVI(pCmd, dwAddr, dwCount, id)           \
+{                                                               \
+    /* 4 unsigned int align, insert NULL Command for padding */ \
+	while (((unsigned long *)(pCmd)) & 0xF) {              \
+		*(pCmd)++ = 0xCC000000;                         \
+	}                                                       \
+	*(pCmd)++ = INV_AGPHeader4 | (dwAddr);                  \
+	*(pCmd)++ = (dwCount);                                  \
+	*(pCmd)++ = (id);                                       \
+	*(pCmd)++ = 0;                                          \
+}
+
+/* Header5: DVD */
+#define ADDCmdHeader5_INVI(pCmd, dwQWcount, id)                 \
+{                                                               \
+	/* 4 unsigned int align, insert NULL Command for padding */    \
+	while (((unsigned long *)(pCmd)) & 0xF) {                    \
+	*(pCmd)++ = 0xCC000000;                                 \
+	}                                                       \
+	*(pCmd)++ = INV_AGPHeader5;                             \
+	*(pCmd)++ = (dwQWcount);                                \
+	*(pCmd)++ = (id);                                       \
+	*(pCmd)++ = 0;                                          \
+}
+
+/* Header6: DEBUG */
+#define ADDCmdHeader6_INVI(pCmd)                                \
+{                                                               \
+	/* 4 unsigned int align, insert NULL Command for padding */    \
+	while (((unsigned long *)(pCmd)) & 0xF) {                    \
+		*(pCmd)++ = 0xCC000000;                         \
+	}                                                       \
+	*(pCmd)++ = INV_AGPHeader6;                             \
+	*(pCmd)++ = 0;                                          \
+	*(pCmd)++ = 0;                                          \
+	*(pCmd)++ = 0;                                          \
+}
+
+/* Header7: DMA */
+#define ADDCmdHeader7_INVI(pCmd, dwQWcount, id)                 \
+{                                                               \
+	/* 4 unsigned int align, insert NULL Command for padding */    \
+	while (((unsigned long *)(pCmd)) & 0xF) {                    \
+		*(pCmd)++ = 0xCC000000;                         \
+	}                                                       \
+	*(pCmd)++ = INV_AGPHeader7;                             \
+	*(pCmd)++ = (dwQWcount);                                \
+	*(pCmd)++ = (id);                                       \
+	*(pCmd)++ = 0;                                          \
+}
+
+/* Header82: Branch buffer */
+#define ADDCmdHeader82_INVI(pCmd, dwAddr, dwType);              \
+{                                                               \
+	/* 4 unsigned int align, insert NULL Command for padding */    \
+	while (((unsigned long *)(pCmd)) & 0xF) {                    \
+		*(pCmd)++ = 0xCC000000;                         \
+	}                                                       \
+	*(pCmd)++ = INV_AGPHeader82 | ((dwAddr)+4);             \
+	*(pCmd)++ = (dwAddr);                                   \
+	*(pCmd)++ = (dwType);                                   \
+	*(pCmd)++ = 0xCC000000;                                 \
+}
+
+
+#define ADD2DCmd_INVI(pCmd, dwAddr, dwCmd)                  \
+{                                                           \
+	*(pCmd)++ = (dwAddr);                               \
+	*(pCmd)++ = (dwCmd);                                \
+}
+
+#define ADDCmdData_INVI(pCmd, dwCmd)             *(pCmd)++ = (dwCmd)
+
+#define ADDCmdDataStream_INVI(pCmdBuf, pCmd, dwCount)       \
+{                                                           \
+	memcpy((pCmdBuf), (pCmd), ((dwCount)<<2));        \
+	(pCmdBuf) += (dwCount);                             \
+}
+
+#endif
--- /dev/null
+++ b/drivers/char/drm/via_chrome9_dma.c
@@ -0,0 +1,1147 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license,
+ * 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL VIA, S3 GRAPHICS, 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.
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "via_chrome9_drm.h"
+#include "via_chrome9_drv.h"
+#include "via_chrome9_3d_reg.h"
+#include "via_chrome9_dma.h"
+
+#define NULLCOMMANDNUMBER 256
+unsigned int NULL_COMMAND_INV[4] =
+	{ 0xCC000000, 0xCD000000, 0xCE000000, 0xCF000000 };
+
+void
+via_chrome9ke_assert(int a)
+{
+}
+
+unsigned int
+ProtectSizeValue(unsigned int size)
+{
+	unsigned int i;
+	for (i = 0; i < 8; i++)
+		if ((size > (1 << (i + 12)))
+		    && (size <= (1 << (i + 13))))
+			return (i + 1);
+	return 0;
+}
+
+static unsigned int
+InitPCIEGART(struct drm_via_chrome9_private *dev_priv)
+{
+	unsigned int *pGARTTable;
+	unsigned int i, entries, GARTOffset;
+	unsigned char sr6a, sr6b, sr6c, sr6f, sr7b;
+
+	if (!dev_priv->pagetable_map.pagetable_size)
+		return 0;
+
+	entries = dev_priv->pagetable_map.pagetable_size / sizeof(unsigned int);
+
+	pGARTTable =
+		ioremap_nocache(dev_priv->fb_base_address +
+				dev_priv->pagetable_map.pagetable_offset,
+				dev_priv->pagetable_map.pagetable_size);
+	if (pGARTTable)
+		dev_priv->pagetable_map.pagetable_handle = pGARTTable;
+	else
+		return 0;
+
+	/*set gart table base */
+	GARTOffset = dev_priv->pagetable_map.pagetable_offset;
+
+	SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6c);
+	sr6c = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5);
+	sr6c &= (~0x80);
+	SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6c);
+
+	sr6a = (unsigned char) ((GARTOffset & 0xff000) >> 12);
+	SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6a);
+	SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6a);
+
+	sr6b = (unsigned char) ((GARTOffset & 0xff00000) >> 20);
+	SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6b);
+	SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6b);
+
+	SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6c);
+	sr6c = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5);
+	sr6c |= ((unsigned char) ((GARTOffset >> 28) & 0x01));
+	SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6c);
+
+	SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x7b);
+	sr7b = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5);
+	sr7b &= (~0x0f);
+	sr7b |= ProtectSizeValue(dev_priv->pagetable_map.pagetable_size);
+	SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr7b);
+
+	for (i = 0; i < entries; i++)
+		writel(0x80000000, pGARTTable + i);
+	/*flush */
+	SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6f);
+	do {
+		sr6f = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5);
+	}
+	while (sr6f & 0x80)
+		;
+
+	sr6f |= 0x80;
+	SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6f);
+
+	SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6c);
+	sr6c = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5);
+	sr6c |= 0x80;
+	SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6c);
+
+	return 1;
+}
+
+
+static unsigned int *
+AllocAndBindPCIEMemory(struct drm_via_chrome9_private *dev_priv,
+	unsigned int size, unsigned int offset)
+{
+	unsigned int *addrlinear;
+	unsigned int *pGARTTable;
+	unsigned int entries, alignedoffset, i;
+	unsigned char sr6c, sr6f;
+
+	if (!size)
+		return NULL;
+
+	entries = (size + PAGE_SIZE - 1) / PAGE_SIZE;
+	alignedoffset = (offset + PAGE_SIZE - 1) / PAGE_SIZE;
+
+	if ((entries + alignedoffset) >
+	    (dev_priv->pagetable_map.pagetable_size / sizeof(unsigned int)))
+		return NULL;
+
+	addrlinear =
+		__vmalloc(entries * PAGE_SIZE, GFP_KERNEL | __GFP_HIGHMEM,
+			  PAGE_KERNEL_NOCACHE);
+
+	if (!addrlinear)
+		return NULL;
+
+	pGARTTable = dev_priv->pagetable_map.pagetable_handle;
+
+	SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6c);
+	sr6c = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5);
+	sr6c &= (~0x80);
+	SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6c);
+
+	SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6f);
+	do {
+		sr6f = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5);
+	}
+	while (sr6f & 0x80)
+		;
+
+	for (i = 0; i < entries; i++)
+		writel(page_to_pfn
+		       (vmalloc_to_page((void *) addrlinear + PAGE_SIZE * i)) &
+		       0x3fffffff, pGARTTable + i + alignedoffset);
+
+	sr6f |= 0x80;
+	SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6f);
+
+	SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6c);
+	sr6c = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5);
+	sr6c |= 0x80;
+	SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6c);
+
+	return addrlinear;
+
+}
+
+void
+SetAGPDoubleCmd_inv(struct drm_device *dev)
+{
+	/* we now don't use double buffer */
+	return;
+}
+
+void
+SetAGPRingCmdRegs_inv(struct drm_device *dev)
+{
+	struct drm_via_chrome9_private *dev_priv =
+		(struct drm_via_chrome9_private *) dev->dev_private;
+	struct drm_via_chrome9_DMA_manager *lpcmDMAManager =
+		(struct drm_via_chrome9_DMA_manager *) dev_priv->dma_manager;
+	unsigned int AGPBufLinearBase = 0, AGPBufPhysicalBase = 0;
+	unsigned long *pFree;
+	unsigned int dwStart, dwEnd, dwPause, AGPCurrAddr, AGPCurStat, CurrAGP;
+	unsigned int dwReg60, dwReg61, dwReg62, dwReg63,
+		dwReg64, dwReg65, dwJump;
+
+	lpcmDMAManager->pFree = lpcmDMAManager->pBeg;
+
+	AGPBufLinearBase = (unsigned int) lpcmDMAManager->addr_linear;
+	AGPBufPhysicalBase =
+		(dev_priv->chip_agp ==
+		 CHIP_PCIE) ? 0 : (unsigned int) dev->agp->base +
+		lpcmDMAManager->pPhysical;
+	/*add shadow offset */
+
+	CurrAGP =
+		GetMMIORegister(dev_priv->mmio->handle, INV_RB_AGPCMD_CURRADDR);
+	AGPCurStat =
+		GetMMIORegister(dev_priv->mmio->handle, INV_RB_AGPCMD_STATUS);
+
+	if (AGPCurStat & INV_AGPCMD_InPause) {
+		AGPCurrAddr =
+			GetMMIORegister(dev_priv->mmio->handle,
+					INV_RB_AGPCMD_CURRADDR);
+		pFree = (unsigned long *) (AGPBufLinearBase + AGPCurrAddr -
+					   AGPBufPhysicalBase);
+		ADDCmdHeader2_INVI(pFree, INV_REG_CR_TRANS, INV_ParaType_Dummy);
+		if (dev_priv->chip_sub_index == CHIP_H6S2)
+			do {
+				ADDCmdData_INVI(pFree, 0xCCCCCCC0);
+				ADDCmdData_INVI(pFree, 0xDDD00000);
+			}
+			while ((u32)((unsigned int) pFree) & 0x7f)
+				;
+			/*for 8*128bit aligned */
+		else
+			do {
+				ADDCmdData_INVI(pFree, 0xCCCCCCC0);
+				ADDCmdData_INVI(pFree, 0xDDD00000);
+			}
+			while ((u32) ((unsigned int) pFree) & 0x1f)
+				;
+			/*for 256bit aligned */
+		dwPause =
+			(u32) (((unsigned int) pFree) - AGPBufLinearBase +
+			       AGPBufPhysicalBase - 16);
+
+		dwReg64 = INV_SubA_HAGPBpL | INV_HWBasL(dwPause);
+		dwReg65 =
+			INV_SubA_HAGPBpID | INV_HWBasH(dwPause) |
+			INV_HAGPBpID_STOP;
+
+		SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_TRANS,
+				INV_ParaType_PreCR);
+		SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN,
+				dwReg64);
+		SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN,
+				dwReg65);
+
+		while ((GetMMIORegister
+			(dev_priv->mmio->handle,
+			 INV_RB_ENG_STATUS) & INV_ENG_BUSY_ALL));
+	}
+	dwStart =
+		(u32) ((unsigned int) lpcmDMAManager->pBeg - AGPBufLinearBase +
+		       AGPBufPhysicalBase);
+	dwEnd = (u32) ((unsigned int) lpcmDMAManager->pEnd - AGPBufLinearBase +
+		       AGPBufPhysicalBase);
+
+	lpcmDMAManager->pFree = lpcmDMAManager->pBeg;
+	if (dev_priv->chip_sub_index == CHIP_H6S2) {
+		ADDCmdHeader2_INVI(lpcmDMAManager->pFree, INV_REG_CR_TRANS,
+				   INV_ParaType_Dummy);
+		do {
+			ADDCmdData_INVI(lpcmDMAManager->pFree, 0xCCCCCCC0);
+			ADDCmdData_INVI(lpcmDMAManager->pFree, 0xDDD00000);
+		}
+		while ((u32)((unsigned long *) lpcmDMAManager->pFree) & 0x7f)
+			;
+	}
+	dwJump = 0xFFFFFFF0;
+	dwPause =
+		(u32)(((unsigned int) lpcmDMAManager->pFree) -
+		16 - AGPBufLinearBase + AGPBufPhysicalBase);
+
+	DRM_DEBUG("dwStart = %08x, dwEnd = %08x, dwPause = %08x\n", dwStart,
+		  dwEnd, dwPause);
+
+	dwReg60 = INV_SubA_HAGPBstL | INV_HWBasL(dwStart);
+	dwReg61 = INV_SubA_HAGPBstH | INV_HWBasH(dwStart);
+	dwReg62 = INV_SubA_HAGPBendL | INV_HWBasL(dwEnd);
+	dwReg63 = INV_SubA_HAGPBendH | INV_HWBasH(dwEnd);
+	dwReg64 = INV_SubA_HAGPBpL | INV_HWBasL(dwPause);
+	dwReg65 = INV_SubA_HAGPBpID | INV_HWBasH(dwPause) | INV_HAGPBpID_PAUSE;
+
+	if (dev_priv->chip_sub_index == CHIP_H6S2)
+		dwReg60 |= 0x01;
+
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_TRANS,
+			INV_ParaType_PreCR);
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg60);
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg61);
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg62);
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg63);
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg64);
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg65);
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN,
+			INV_SubA_HAGPBjumpL | INV_HWBasL(dwJump));
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN,
+			INV_SubA_HAGPBjumpH | INV_HWBasH(dwJump));
+
+	/* Trigger AGP cycle */
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN,
+			INV_SubA_HFthRCM | INV_HFthRCM_10 | INV_HAGPBTrig);
+
+	/*for debug */
+	CurrAGP =
+		GetMMIORegister(dev_priv->mmio->handle, INV_RB_AGPCMD_CURRADDR);
+
+	lpcmDMAManager->pInUseBySW = lpcmDMAManager->pFree;
+}
+
+/* Do hw intialization and determine whether to use dma or mmio to
+talk with hw */
+int
+via_chrome9_hw_init(struct drm_device *dev,
+	struct drm_via_chrome9_init *init)
+{
+	struct drm_via_chrome9_private *dev_priv =
+		(struct drm_via_chrome9_private *) dev->dev_private;
+	unsigned retval = 0;
+	unsigned int *pGARTTable, *addrlinear = NULL;
+	int pages;
+	struct drm_clb_event_tag_info *event_tag_info;
+	struct drm_via_chrome9_DMA_manager *lpcmDMAManager = NULL;
+
+	if (init->chip_agp == CHIP_PCIE) {
+		dev_priv->pagetable_map.pagetable_offset =
+			init->garttable_offset;
+		dev_priv->pagetable_map.pagetable_size = init->garttable_size;
+		dev_priv->agp_size = init->agp_tex_size;
+		/*Henry :prepare for PCIE texture buffer */
+	} else {
+		dev_priv->pagetable_map.pagetable_offset = 0;
+		dev_priv->pagetable_map.pagetable_size = 0;
+	}
+
+	dev_priv->dma_manager =
+		kmalloc(sizeof(struct drm_via_chrome9_DMA_manager), GFP_KERNEL);
+	if (!dev_priv->dma_manager) {
+		DRM_ERROR("could not allocate system for dma_manager!\n");
+		return -ENOMEM;
+	}
+
+	lpcmDMAManager =
+		(struct drm_via_chrome9_DMA_manager *) dev_priv->dma_manager;
+	((struct drm_via_chrome9_DMA_manager *)
+		dev_priv->dma_manager)->DMASize = init->DMA_size;
+	((struct drm_via_chrome9_DMA_manager *)
+		dev_priv->dma_manager)->pPhysical = init->DMA_phys_address;
+
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_TRANS, 0x00110000);
+	if (dev_priv->chip_sub_index == CHIP_H6S2) {
+		SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN,
+				0x06000000);
+		SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN,
+				0x07100000);
+	} else {
+		SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN,
+				0x02000000);
+		SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN,
+				0x03100000);
+	}
+
+	/* Specify fence command read back ID */
+	/* Default the read back ID is CR */
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_TRANS,
+			INV_ParaType_PreCR);
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN,
+			INV_SubA_HSetRBGID | INV_HSetRBGID_CR);
+
+	DRM_DEBUG("begin to init\n");
+
+	if (dev_priv->chip_sub_index == CHIP_H6S2) {
+		dev_priv->pcie_vmalloc_nocache = 0;
+		if (dev_priv->pagetable_map.pagetable_size)
+			retval = InitPCIEGART(dev_priv);
+
+		if (retval && dev_priv->drm_agp_type != DRM_AGP_DISABLED) {
+			addrlinear =
+				AllocAndBindPCIEMemory(dev_priv,
+						       lpcmDMAManager->DMASize +
+						       dev_priv->agp_size, 0);
+			if (addrlinear) {
+				dev_priv->pcie_vmalloc_nocache = (unsigned long)
+					addrlinear;
+			} else {
+				dev_priv->bci_buffer =
+					vmalloc(MAX_BCI_BUFFER_SIZE);
+				dev_priv->drm_agp_type = DRM_AGP_DISABLED;
+			}
+		} else {
+			dev_priv->bci_buffer = vmalloc(MAX_BCI_BUFFER_SIZE);
+			dev_priv->drm_agp_type = DRM_AGP_DISABLED;
+		}
+	} else {
+		if (dev_priv->drm_agp_type != DRM_AGP_DISABLED) {
+			pGARTTable = NULL;
+			addrlinear = (unsigned int *)
+				ioremap(dev->agp->base +
+					lpcmDMAManager->pPhysical,
+					lpcmDMAManager->DMASize);
+			dev_priv->bci_buffer = NULL;
+		} else {
+			dev_priv->bci_buffer = vmalloc(MAX_BCI_BUFFER_SIZE);
+			/*Homer, BCI path always use this block of memory8 */
+		}
+	}
+
+	/*till here we have known whether support dma or not */
+	pages = dev->sg->pages;
+	event_tag_info = vmalloc(sizeof(struct drm_clb_event_tag_info));
+	memset(event_tag_info, 0, sizeof(struct drm_clb_event_tag_info));
+	if (!event_tag_info)
+		return DRM_ERROR(" event_tag_info allocate error!");
+
+	/* aligned to 16k alignment */
+	event_tag_info->linear_address =
+		(int
+		 *) (((unsigned int) dev_priv->shadow_map.shadow_handle +
+		      0x3fff) & 0xffffc000);
+	event_tag_info->event_tag_linear_address =
+		event_tag_info->linear_address + 3;
+	dev_priv->event_tag_info = (void *) event_tag_info;
+	dev_priv->max_apertures = NUMBER_OF_APERTURES_CLB;
+
+	/* Initialize DMA data structure */
+	lpcmDMAManager->DMASize /= sizeof(unsigned int);
+	lpcmDMAManager->pBeg = addrlinear;
+	lpcmDMAManager->pFree = lpcmDMAManager->pBeg;
+	lpcmDMAManager->pInUseBySW = lpcmDMAManager->pBeg;
+	lpcmDMAManager->pInUseByHW = lpcmDMAManager->pBeg;
+	lpcmDMAManager->LastIssuedEventTag = (unsigned int) (unsigned long *)
+		lpcmDMAManager->pBeg;
+	lpcmDMAManager->ppInUseByHW =
+		(unsigned int **) ((char *) (dev_priv->mmio->handle) +
+				   INV_RB_AGPCMD_CURRADDR);
+	lpcmDMAManager->bDMAAgp = dev_priv->chip_agp;
+	lpcmDMAManager->addr_linear = (unsigned int *) addrlinear;
+
+	if (dev_priv->drm_agp_type == DRM_AGP_DOUBLE_BUFFER) {
+		lpcmDMAManager->MaxKickoffSize = lpcmDMAManager->DMASize >> 1;
+		lpcmDMAManager->pEnd =
+			lpcmDMAManager->addr_linear +
+			(lpcmDMAManager->DMASize >> 1) - 1;
+		SetAGPDoubleCmd_inv(dev);
+		if (dev_priv->chip_sub_index == CHIP_H6S2) {
+			DRM_INFO("DMA buffer initialized finished. ");
+			DRM_INFO("Use PCIE Double Buffer type!\n");
+			DRM_INFO("Total PCIE DMA buffer size = %8d bytes. \n",
+				 lpcmDMAManager->DMASize << 2);
+		} else {
+			DRM_INFO("DMA buffer initialized finished. ");
+			DRM_INFO("Use AGP Double Buffer type!\n");
+			DRM_INFO("Total AGP DMA buffer size = %8d bytes. \n",
+				 lpcmDMAManager->DMASize << 2);
+		}
+	} else if (dev_priv->drm_agp_type == DRM_AGP_RING_BUFFER) {
+		lpcmDMAManager->MaxKickoffSize = lpcmDMAManager->DMASize;
+		lpcmDMAManager->pEnd =
+			lpcmDMAManager->addr_linear + lpcmDMAManager->DMASize;
+		SetAGPRingCmdRegs_inv(dev);
+		if (dev_priv->chip_sub_index == CHIP_H6S2) {
+			DRM_INFO("DMA buffer initialized finished. \n");
+			DRM_INFO("Use PCIE Ring Buffer type!");
+			DRM_INFO("Total PCIE DMA buffer size = %8d bytes. \n",
+				 lpcmDMAManager->DMASize << 2);
+		} else {
+			DRM_INFO("DMA buffer initialized finished. ");
+			DRM_INFO("Use AGP Ring Buffer type!\n");
+			DRM_INFO("Total AGP DMA buffer size = %8d bytes. \n",
+				 lpcmDMAManager->DMASize << 2);
+		}
+	} else if (dev_priv->drm_agp_type == DRM_AGP_DISABLED) {
+		lpcmDMAManager->MaxKickoffSize = 0x0;
+		if (dev_priv->chip_sub_index == CHIP_H6S2)
+			DRM_INFO("PCIE init failed! Use PCI\n");
+		else
+			DRM_INFO("AGP init failed! Use PCI\n");
+	}
+	return 0;
+}
+
+static void
+kickoff_bci_inv(struct drm_via_chrome9_private *dev_priv,
+		struct drm_via_chrome9_flush *dma_info)
+{
+	u32 HdType, dwQWCount, i, dwCount, Addr1, Addr2, SWPointer,
+		SWPointerEnd;
+	unsigned long *pCmdData;
+	int result;
+
+	/*pCmdData = __s3gke_vmalloc(dma_info->cmd_size<<2); */
+	pCmdData = dev_priv->bci_buffer;
+
+	if (!pCmdData)
+		return;
+
+	result = copy_from_user((int *) pCmdData, dma_info->usermode_dma_buf,
+				dma_info->cmd_size << 2);
+
+	SWPointer = 0;
+	SWPointerEnd = (u32) dma_info->cmd_size;
+	while (SWPointer < SWPointerEnd) {
+		HdType = pCmdData[SWPointer] & INV_AGPHeader_MASK;
+		switch (HdType) {
+		case INV_AGPHeader0:
+		case INV_AGPHeader5:
+			dwQWCount = pCmdData[SWPointer + 1];
+			SWPointer += 4;
+
+			for (i = 0; i < dwQWCount; i++) {
+				SetMMIORegister(dev_priv->mmio->handle,
+						pCmdData[SWPointer],
+						pCmdData[SWPointer + 1]);
+				SWPointer += 2;
+			}
+			break;
+
+		case INV_AGPHeader1:
+			dwCount = pCmdData[SWPointer + 1];
+			Addr1 = 0x0;
+			SWPointer += 4;	/* skip 128-bit. */
+
+			for (; dwCount > 0; dwCount--, SWPointer++,
+				Addr1 += 4) {
+				SetMMIORegister(dev_priv->hostBlt->handle,
+						Addr1, pCmdData[SWPointer]);
+			}
+			break;
+
+		case INV_AGPHeader4:
+			dwCount = pCmdData[SWPointer + 1];
+			Addr1 = pCmdData[SWPointer] & 0x0000FFFF;
+			SWPointer += 4;	/* skip 128-bit. */
+
+			for (; dwCount > 0; dwCount--, SWPointer++)
+				SetMMIORegister(dev_priv->mmio->handle, Addr1,
+						pCmdData[SWPointer]);
+			break;
+
+		case INV_AGPHeader2:
+			Addr1 = pCmdData[SWPointer + 1] & 0xFFFF;
+			Addr2 = pCmdData[SWPointer] & 0xFFFF;
+
+			/* Write first data (either ParaType or whatever) to
+			Addr1 */
+			SetMMIORegister(dev_priv->mmio->handle, Addr1,
+					pCmdData[SWPointer + 2]);
+			SWPointer += 4;
+
+			/* The following data are all written to Addr2,
+			   until another header is met */
+			while (!IS_AGPHEADER_INV(pCmdData[SWPointer])
+			       && (SWPointer < SWPointerEnd)) {
+				SetMMIORegister(dev_priv->mmio->handle, Addr2,
+						pCmdData[SWPointer]);
+				SWPointer++;
+			}
+			break;
+
+		case INV_AGPHeader3:
+			Addr1 = pCmdData[SWPointer] & 0xFFFF;
+			Addr2 = Addr1 + 4;
+			dwCount = pCmdData[SWPointer + 1];
+
+			/* Write first data (either ParaType or whatever) to
+			Addr1 */
+			SetMMIORegister(dev_priv->mmio->handle, Addr1,
+					pCmdData[SWPointer + 2]);
+			SWPointer += 4;
+
+			for (i = 0; i < dwCount; i++) {
+				SetMMIORegister(dev_priv->mmio->handle, Addr2,
+						pCmdData[SWPointer]);
+				SWPointer++;
+			}
+			break;
+
+		case INV_AGPHeader6:
+			break;
+
+		case INV_AGPHeader7:
+			break;
+
+		default:
+			SWPointer += 4;	/* Advance to next header */
+		}
+
+		SWPointer = (SWPointer + 3) & ~3;
+	}
+}
+
+void
+kickoff_dma_db_inv(struct drm_device *dev)
+{
+	struct drm_via_chrome9_private *dev_priv =
+		(struct drm_via_chrome9_private *) dev->dev_private;
+	struct drm_via_chrome9_DMA_manager *lpcmDMAManager =
+		dev_priv->dma_manager;
+
+	u32 BufferSize = (u32) (lpcmDMAManager->pFree - lpcmDMAManager->pBeg);
+
+	unsigned int AGPBufLinearBase =
+		(unsigned int) lpcmDMAManager->addr_linear;
+	unsigned int AGPBufPhysicalBase =
+		(unsigned int) dev->agp->base + lpcmDMAManager->pPhysical;
+	/*add shadow offset */
+
+	unsigned int dwStart, dwEnd, dwPause;
+	unsigned int dwReg60, dwReg61, dwReg62, dwReg63, dwReg64, dwReg65;
+	unsigned int CR_Status;
+
+	if (BufferSize == 0)
+		return;
+
+	/* 256-bit alignment of AGP pause address */
+	if ((u32) ((unsigned long *) lpcmDMAManager->pFree) & 0x1f) {
+		ADDCmdHeader2_INVI(lpcmDMAManager->pFree, INV_REG_CR_TRANS,
+				   INV_ParaType_Dummy);
+		do {
+			ADDCmdData_INVI(lpcmDMAManager->pFree, 0xCCCCCCC0);
+			ADDCmdData_INVI(lpcmDMAManager->pFree, 0xDDD00000);
+		}
+		while (((unsigned int) lpcmDMAManager->pFree) & 0x1f)
+			;
+	}
+
+	dwStart =
+		(u32) (unsigned long *)lpcmDMAManager->pBeg -
+		AGPBufLinearBase + AGPBufPhysicalBase;
+	dwEnd = (u32) (unsigned long *)lpcmDMAManager->pEnd -
+		AGPBufLinearBase + AGPBufPhysicalBase;
+	dwPause =
+		(u32)(unsigned long *)lpcmDMAManager->pFree -
+		AGPBufLinearBase + AGPBufPhysicalBase - 4;
+
+	dwReg60 = INV_SubA_HAGPBstL | INV_HWBasL(dwStart);
+	dwReg61 = INV_SubA_HAGPBstH | INV_HWBasH(dwStart);
+	dwReg62 = INV_SubA_HAGPBendL | INV_HWBasL(dwEnd);
+	dwReg63 = INV_SubA_HAGPBendH | INV_HWBasH(dwEnd);
+	dwReg64 = INV_SubA_HAGPBpL | INV_HWBasL(dwPause);
+	dwReg65 = INV_SubA_HAGPBpID | INV_HWBasH(dwPause) | INV_HAGPBpID_STOP;
+
+	/* wait CR idle */
+	CR_Status = GetMMIORegister(dev_priv->mmio->handle, INV_RB_ENG_STATUS);
+	while (CR_Status & INV_ENG_BUSY_CR)
+		CR_Status =
+			GetMMIORegister(dev_priv->mmio->handle,
+					INV_RB_ENG_STATUS);
+
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_TRANS,
+			INV_ParaType_PreCR);
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg60);
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg61);
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg62);
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg63);
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg64);
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg65);
+
+	/* Trigger AGP cycle */
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN,
+			INV_SubA_HFthRCM | INV_HFthRCM_10 | INV_HAGPBTrig);
+
+	if (lpcmDMAManager->pBeg == lpcmDMAManager->addr_linear) {
+		/* The second AGP command buffer */
+		lpcmDMAManager->pBeg =
+			lpcmDMAManager->addr_linear +
+			(lpcmDMAManager->DMASize >> 2);
+		lpcmDMAManager->pEnd =
+			lpcmDMAManager->addr_linear + lpcmDMAManager->DMASize;
+		lpcmDMAManager->pFree = lpcmDMAManager->pBeg;
+	} else {
+		/* The first AGP command buffer */
+		lpcmDMAManager->pBeg = lpcmDMAManager->addr_linear;
+		lpcmDMAManager->pEnd =
+			lpcmDMAManager->addr_linear +
+			(lpcmDMAManager->DMASize / 2) - 1;
+		lpcmDMAManager->pFree = lpcmDMAManager->pBeg;
+	}
+	CR_Status = GetMMIORegister(dev_priv->mmio->handle, INV_RB_ENG_STATUS);
+}
+
+
+void
+kickoff_dma_ring_inv(struct drm_device *dev)
+{
+	unsigned int dwPause, dwReg64, dwReg65;
+
+	struct drm_via_chrome9_private *dev_priv =
+		(struct drm_via_chrome9_private *) dev->dev_private;
+	struct drm_via_chrome9_DMA_manager *lpcmDMAManager =
+		dev_priv->dma_manager;
+
+	unsigned int AGPBufLinearBase =
+		(unsigned int) lpcmDMAManager->addr_linear;
+	unsigned int AGPBufPhysicalBase =
+		(dev_priv->chip_agp ==
+		 CHIP_PCIE) ? 0 : (unsigned int) dev->agp->base +
+		lpcmDMAManager->pPhysical;
+	/*add shadow offset */
+
+	/* 256-bit alignment of AGP pause address */
+	if (dev_priv->chip_sub_index == CHIP_H6S2) {
+		if ((u32)
+		    ((unsigned long *) lpcmDMAManager->pFree) & 0x7f) {
+			ADDCmdHeader2_INVI(lpcmDMAManager->pFree,
+					   INV_REG_CR_TRANS,
+					   INV_ParaType_Dummy);
+			do {
+				ADDCmdData_INVI(lpcmDMAManager->pFree,
+						0xCCCCCCC0);
+				ADDCmdData_INVI(lpcmDMAManager->pFree,
+						0xDDD00000);
+			}
+			while ((u32)((unsigned long *) lpcmDMAManager->pFree) &
+				0x7f)
+				;
+		}
+	} else {
+		if ((u32)
+		    ((unsigned long *) lpcmDMAManager->pFree) & 0x1f) {
+			ADDCmdHeader2_INVI(lpcmDMAManager->pFree,
+					   INV_REG_CR_TRANS,
+					   INV_ParaType_Dummy);
+			do {
+				ADDCmdData_INVI(lpcmDMAManager->pFree,
+						0xCCCCCCC0);
+				ADDCmdData_INVI(lpcmDMAManager->pFree,
+						0xDDD00000);
+			}
+			while ((u32)((unsigned long *) lpcmDMAManager->pFree) &
+				0x1f)
+				;
+		}
+	}
+
+
+	dwPause = (u32) ((unsigned long *) lpcmDMAManager->pFree)
+		- AGPBufLinearBase + AGPBufPhysicalBase - 16;
+
+	dwReg64 = INV_SubA_HAGPBpL | INV_HWBasL(dwPause);
+	dwReg65 = INV_SubA_HAGPBpID | INV_HWBasH(dwPause) | INV_HAGPBpID_PAUSE;
+
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_TRANS,
+			INV_ParaType_PreCR);
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg64);
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg65);
+
+	lpcmDMAManager->pInUseBySW = lpcmDMAManager->pFree;
+}
+
+static int
+waitchipidle_inv(struct drm_via_chrome9_private *dev_priv)
+{
+	unsigned int count = 50000;
+	unsigned int eng_status;
+	unsigned int engine_busy;
+
+	do {
+		eng_status =
+			GetMMIORegister(dev_priv->mmio->handle,
+					INV_RB_ENG_STATUS);
+		engine_busy = eng_status & INV_ENG_BUSY_ALL;
+		count--;
+	}
+	while (engine_busy && count)
+		;
+	if (count && engine_busy == 0)
+		return 0;
+	return -1;
+}
+
+void
+get_space_db_inv(struct drm_device *dev,
+	struct cmd_get_space *lpcmGetSpaceData)
+{
+	struct drm_via_chrome9_private *dev_priv =
+		(struct drm_via_chrome9_private *) dev->dev_private;
+	struct drm_via_chrome9_DMA_manager *lpcmDMAManager =
+		dev_priv->dma_manager;
+
+	unsigned int dwRequestSize = lpcmGetSpaceData->dwRequestSize;
+	if (dwRequestSize > lpcmDMAManager->MaxKickoffSize) {
+		DRM_INFO("too big DMA buffer request!!!\n");
+		via_chrome9ke_assert(0);
+		*lpcmGetSpaceData->pCmdData = (unsigned int) NULL;
+		return;
+	}
+
+	if ((lpcmDMAManager->pFree + dwRequestSize) >
+	    (lpcmDMAManager->pEnd - INV_CMDBUF_THRESHOLD * 2))
+		kickoff_dma_db_inv(dev);
+
+	*lpcmGetSpaceData->pCmdData = (unsigned int) lpcmDMAManager->pFree;
+}
+
+void
+RewindRingAGP_inv(struct drm_device *dev)
+{
+	struct drm_via_chrome9_private *dev_priv =
+		(struct drm_via_chrome9_private *) dev->dev_private;
+	struct drm_via_chrome9_DMA_manager *lpcmDMAManager =
+		dev_priv->dma_manager;
+
+	unsigned int AGPBufLinearBase =
+		(unsigned int) lpcmDMAManager->addr_linear;
+	unsigned int AGPBufPhysicalBase =
+		(dev_priv->chip_agp ==
+		 CHIP_PCIE) ? 0 : (unsigned int) dev->agp->base +
+		lpcmDMAManager->pPhysical;
+	/*add shadow offset */
+
+	unsigned int dwPause, dwJump;
+	unsigned int dwReg66, dwReg67;
+	unsigned int dwReg64, dwReg65;
+
+	ADDCmdHeader2_INVI(lpcmDMAManager->pFree, INV_REG_CR_TRANS,
+			   INV_ParaType_Dummy);
+	ADDCmdData_INVI(lpcmDMAManager->pFree, 0xCCCCCCC7);
+	if (dev_priv->chip_sub_index == CHIP_H6S2)
+		while ((unsigned int) lpcmDMAManager->pFree & 0x7F)
+			ADDCmdData_INVI(lpcmDMAManager->pFree, 0xCCCCCCC7);
+	else
+		while ((unsigned int) lpcmDMAManager->pFree & 0x1F)
+			ADDCmdData_INVI(lpcmDMAManager->pFree, 0xCCCCCCC7);
+	dwJump = ((u32) ((unsigned long *) lpcmDMAManager->pFree))
+		- AGPBufLinearBase + AGPBufPhysicalBase - 16;
+
+	lpcmDMAManager->pFree = lpcmDMAManager->pBeg;
+
+	dwPause = ((u32) ((unsigned long *) lpcmDMAManager->pFree))
+		- AGPBufLinearBase + AGPBufPhysicalBase - 16;
+
+	dwReg64 = INV_SubA_HAGPBpL | INV_HWBasL(dwPause);
+	dwReg65 = INV_SubA_HAGPBpID | INV_HWBasH(dwPause) | INV_HAGPBpID_PAUSE;
+
+	dwReg66 = INV_SubA_HAGPBjumpL | INV_HWBasL(dwJump);
+	dwReg67 = INV_SubA_HAGPBjumpH | INV_HWBasH(dwJump);
+
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_TRANS,
+			INV_ParaType_PreCR);
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg66);
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg67);
+
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg64);
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN, dwReg65);
+	lpcmDMAManager->pInUseBySW = lpcmDMAManager->pFree;
+}
+
+
+void
+get_space_ring_inv(struct drm_device *dev,
+		   struct cmd_get_space *lpcmGetSpaceData)
+{
+	struct drm_via_chrome9_private *dev_priv =
+		(struct drm_via_chrome9_private *) dev->dev_private;
+	struct drm_via_chrome9_DMA_manager *lpcmDMAManager =
+		dev_priv->dma_manager;
+	unsigned int dwUnFlushed;
+	unsigned int dwRequestSize = lpcmGetSpaceData->dwRequestSize;
+
+	unsigned int AGPBufLinearBase =
+		(unsigned int) lpcmDMAManager->addr_linear;
+	unsigned int AGPBufPhysicalBase =
+		(dev_priv->chip_agp ==
+		 CHIP_PCIE) ? 0 : (unsigned int) dev->agp->base +
+		lpcmDMAManager->pPhysical;
+	/*add shadow offset */
+	u32 BufStart, BufEnd, CurSW, CurHW, NextSW, BoundaryCheck;
+
+	dwUnFlushed =
+		(unsigned int) (lpcmDMAManager->pFree - lpcmDMAManager->pBeg);
+	/*default bEnableModuleSwitch is on for metro,is off for rest */
+	/*cmHW_Module_Switch is context-wide variable which is enough for 2d/3d
+	   switch in a context. */
+	/*But we must keep the dma buffer being wrapped head and tail by 3d cmds
+	   when it is kicked off to kernel mode. */
+	/*Get DMA Space (If requested, or no BCI space and BCI not forced. */
+
+	if (dwRequestSize > lpcmDMAManager->MaxKickoffSize) {
+		DRM_INFO("too big DMA buffer request!!!\n");
+		via_chrome9ke_assert(0);
+		*lpcmGetSpaceData->pCmdData = 0;
+		return;
+	}
+
+	if (dwUnFlushed + dwRequestSize > lpcmDMAManager->MaxKickoffSize)
+		kickoff_dma_ring_inv(dev);
+
+	BufStart =
+		(u32)((unsigned int) lpcmDMAManager->pBeg) - AGPBufLinearBase +
+		AGPBufPhysicalBase;
+	BufEnd = (u32)((unsigned int) lpcmDMAManager->pEnd) - AGPBufLinearBase +
+		AGPBufPhysicalBase;
+	dwRequestSize = lpcmGetSpaceData->dwRequestSize << 2;
+	NextSW = (u32) ((unsigned int) lpcmDMAManager->pFree) + dwRequestSize +
+		INV_CMDBUF_THRESHOLD * 8 - AGPBufLinearBase +
+		AGPBufPhysicalBase;
+
+	CurSW = (u32)((unsigned int) lpcmDMAManager->pFree) - AGPBufLinearBase +
+		AGPBufPhysicalBase;
+	CurHW = GetMMIORegister(dev_priv->mmio->handle, INV_RB_AGPCMD_CURRADDR);
+
+	if (NextSW >= BufEnd) {
+		kickoff_dma_ring_inv(dev);
+		CurSW = (u32) ((unsigned int) lpcmDMAManager->pFree) -
+			AGPBufLinearBase + AGPBufPhysicalBase;
+		/* make sure the last rewind is completed */
+		CurHW = GetMMIORegister(dev_priv->mmio->handle,
+					INV_RB_AGPCMD_CURRADDR);
+		while (CurHW > CurSW)
+			CurHW = GetMMIORegister(dev_priv->mmio->handle,
+						INV_RB_AGPCMD_CURRADDR);
+		/* Sometime the value read from HW is unreliable,
+		so need double confirm. */
+		CurHW = GetMMIORegister(dev_priv->mmio->handle,
+					INV_RB_AGPCMD_CURRADDR);
+		while (CurHW > CurSW)
+			CurHW = GetMMIORegister(dev_priv->mmio->handle,
+						INV_RB_AGPCMD_CURRADDR);
+		BoundaryCheck =
+			BufStart + dwRequestSize + INV_QW_PAUSE_ALIGN * 16;
+		if (BoundaryCheck >= BufEnd)
+			/* If an empty command buffer can't hold
+			the request data. */
+			via_chrome9ke_assert(0);
+		else {
+			/* We need to guarntee the new commands have no chance
+			to override the unexected commands or wait until there
+			is no unexecuted commands in agp buffer */
+			if (CurSW <= BoundaryCheck) {
+				CurHW = GetMMIORegister(dev_priv->mmio->handle,
+							INV_RB_AGPCMD_CURRADDR);
+				while (CurHW < CurSW)
+					CurHW = GetMMIORegister(
+					dev_priv->mmio->handle,
+					INV_RB_AGPCMD_CURRADDR);
+				/*Sometime the value read from HW is unreliable,
+				   so need double confirm. */
+				CurHW = GetMMIORegister(dev_priv->mmio->handle,
+							INV_RB_AGPCMD_CURRADDR);
+				while (CurHW < CurSW) {
+					CurHW = GetMMIORegister(
+						dev_priv->mmio->handle,
+						INV_RB_AGPCMD_CURRADDR);
+				}
+				RewindRingAGP_inv(dev);
+				CurSW = (u32) ((unsigned long *)
+					       lpcmDMAManager->pFree) -
+					AGPBufLinearBase + AGPBufPhysicalBase;
+				CurHW = GetMMIORegister(dev_priv->mmio->handle,
+							INV_RB_AGPCMD_CURRADDR);
+				/* Waiting until hw pointer jump to start
+				and hw pointer will */
+				/* equal to sw pointer */
+				while (CurHW != CurSW) {
+					CurHW = GetMMIORegister(
+						dev_priv->mmio->handle,
+						INV_RB_AGPCMD_CURRADDR);
+				}
+			} else {
+				CurHW = GetMMIORegister(dev_priv->mmio->handle,
+							INV_RB_AGPCMD_CURRADDR);
+
+				while (CurHW <= BoundaryCheck) {
+					CurHW = GetMMIORegister(
+						dev_priv->mmio->handle,
+						INV_RB_AGPCMD_CURRADDR);
+				}
+				CurHW = GetMMIORegister(dev_priv->mmio->handle,
+							INV_RB_AGPCMD_CURRADDR);
+				/* Sometime the value read from HW is
+				unreliable, so need double confirm. */
+				while (CurHW <= BoundaryCheck) {
+					CurHW = GetMMIORegister(
+						dev_priv->mmio->handle,
+						INV_RB_AGPCMD_CURRADDR);
+				}
+				RewindRingAGP_inv(dev);
+			}
+		}
+	} else {
+		/* no need to rewind Ensure unexecuted agp commands will
+		not be override by new
+		agp commands */
+		CurSW = (u32) ((unsigned int) lpcmDMAManager->pFree) -
+			AGPBufLinearBase + AGPBufPhysicalBase;
+		CurHW = GetMMIORegister(dev_priv->mmio->handle,
+					INV_RB_AGPCMD_CURRADDR);
+
+		while ((CurHW > CurSW) && (CurHW <= NextSW))
+			CurHW = GetMMIORegister(dev_priv->mmio->handle,
+						INV_RB_AGPCMD_CURRADDR);
+
+		/* Sometime the value read from HW is unreliable,
+		so need double confirm. */
+		CurHW = GetMMIORegister(dev_priv->mmio->handle,
+					INV_RB_AGPCMD_CURRADDR);
+		while ((CurHW > CurSW) && (CurHW <= NextSW))
+			CurHW = GetMMIORegister(dev_priv->mmio->handle,
+						INV_RB_AGPCMD_CURRADDR);
+	}
+	/*return the space handle */
+	*lpcmGetSpaceData->pCmdData = (unsigned int) lpcmDMAManager->pFree;
+}
+
+void
+release_space_inv(struct drm_device *dev,
+		  struct cmd_release_space *lpcmReleaseSpaceData)
+{
+	struct drm_via_chrome9_private *dev_priv =
+		(struct drm_via_chrome9_private *) dev->dev_private;
+	struct drm_via_chrome9_DMA_manager *lpcmDMAManager =
+		dev_priv->dma_manager;
+	unsigned int dwReleaseSize = lpcmReleaseSpaceData->dwReleaseSize;
+	int i = 0;
+
+	lpcmDMAManager->pFree += dwReleaseSize;
+
+	/* aligned address */
+	while (((unsigned int) lpcmDMAManager->pFree) & 0xF) {
+		/* not in 4 unsigned ints (16 Bytes) align address,
+		insert NULL Commands */
+		*lpcmDMAManager->pFree++ = NULL_COMMAND_INV[i & 0x3];
+		i++;
+	}
+
+	if ((dev_priv->chip_sub_index == CHIP_H5)
+	    && (dev_priv->drm_agp_type == DRM_AGP_RING_BUFFER)) {
+		ADDCmdHeader2_INVI(lpcmDMAManager->pFree, INV_REG_CR_TRANS,
+				   INV_ParaType_Dummy);
+		for (i = 0; i < NULLCOMMANDNUMBER; i++)
+			ADDCmdData_INVI(lpcmDMAManager->pFree, 0xCC000000);
+	}
+}
+
+int
+via_chrome9_ioctl_flush(struct drm_device *dev, void *data,
+	struct drm_file *file_priv)
+{
+	struct drm_via_chrome9_flush *dma_info = data;
+	struct drm_via_chrome9_private *dev_priv =
+		(struct drm_via_chrome9_private *) dev->dev_private;
+	int ret = 0;
+	int result = 0;
+	struct cmd_get_space getspace;
+	struct cmd_release_space releasespace;
+	volatile unsigned long *pCmdData = NULL;
+
+	switch (dma_info->dma_cmd_type) {
+		/* Copy DMA buffer to BCI command buffer */
+	case flush_bci:
+	case flush_bci_and_wait:
+		if (dma_info->cmd_size <= 0)
+			return 0;
+		if (dma_info->cmd_size > MAX_BCI_BUFFER_SIZE) {
+			DRM_INFO("too big BCI space request!!!\n");
+			return 0;
+		}
+
+		kickoff_bci_inv(dev_priv, dma_info);
+		waitchipidle_inv(dev_priv);
+		break;
+		/* Use DRM DMA buffer manager to kick off DMA directly */
+	case dma_kickoff:
+		break;
+
+		/* Copy user mode DMA buffer to kernel DMA buffer,
+		then kick off DMA */
+	case flush_dma_buffer:
+	case flush_dma_and_wait:
+		if (dma_info->cmd_size <= 0)
+			return 0;
+
+		getspace.dwRequestSize = dma_info->cmd_size;
+		if ((dev_priv->chip_sub_index == CHIP_H5)
+		    && (dev_priv->drm_agp_type == DRM_AGP_RING_BUFFER))
+			getspace.dwRequestSize += (NULLCOMMANDNUMBER + 4);
+		/*henry:Patch for VT3293 agp ring buffer stability */
+		getspace.pCmdData = (unsigned int *) &pCmdData;
+
+		if (dev_priv->drm_agp_type == DRM_AGP_DOUBLE_BUFFER)
+			get_space_db_inv(dev, &getspace);
+		else if (dev_priv->drm_agp_type == DRM_AGP_RING_BUFFER)
+			get_space_ring_inv(dev, &getspace);
+
+		if (pCmdData) {
+			/*copy data from userspace to kernel-dma-agp buffer */
+			result = copy_from_user((int *)
+						pCmdData,
+						dma_info->usermode_dma_buf,
+						dma_info->cmd_size << 2);
+			releasespace.dwReleaseSize = dma_info->cmd_size;
+			release_space_inv(dev, &releasespace);
+
+			if (dev_priv->drm_agp_type == DRM_AGP_DOUBLE_BUFFER)
+				kickoff_dma_db_inv(dev);
+			else if (dev_priv->drm_agp_type == DRM_AGP_RING_BUFFER)
+				kickoff_dma_ring_inv(dev);
+
+			if (dma_info->dma_cmd_type == flush_dma_and_wait)
+				waitchipidle_inv(dev_priv);
+		} else {
+			DRM_INFO("No enough DMA space");
+			ret = -ENOMEM;
+		}
+		break;
+
+	default:
+		DRM_INFO("Invalid DMA buffer type");
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+int
+via_chrome9_ioctl_free(struct drm_device *dev, void *data,
+	struct drm_file *file_priv)
+{
+	return 0;
+}
+
+int
+via_chrome9_ioctl_wait_chip_idle(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv)
+{
+	struct drm_via_chrome9_private *dev_priv =
+		(struct drm_via_chrome9_private *) dev->dev_private;
+
+	waitchipidle_inv(dev_priv);
+	/* maybe_bug here, do we always return 0 */
+	return 0;
+}
+
+int
+via_chrome9_ioctl_flush_cache(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv)
+{
+	return 0;
+}
--- /dev/null
+++ b/drivers/char/drm/via_chrome9_dma.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license,
+ * 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL VIA, S3 GRAPHICS, 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.
+ */
+#ifndef _VIA_CHROME9_DMA_H_
+#define _VIA_CHROME9_DMA_H_
+
+#define MAX_BCI_BUFFER_SIZE 16*1024*1024
+
+enum cmd_request_type {
+	CM_REQUEST_BCI,
+	CM_REQUEST_DMA,
+	CM_REQUEST_RB,
+	CM_REQUEST_RB_FORCED_DMA,
+	CM_REQUEST_NOTAVAILABLE
+};
+
+struct cmd_get_space {
+	unsigned int            dwRequestSize;
+	enum cmd_request_type      hint;
+	volatile unsigned int   *pCmdData;
+};
+
+struct cmd_release_space {
+	unsigned int  dwReleaseSize;
+};
+
+extern int via_chrome9_hw_init(struct drm_device *dev,
+	struct drm_via_chrome9_init *init);
+extern int via_chrome9_ioctl_flush(struct drm_device *dev, void *data,
+	struct drm_file *file_priv);
+extern int via_chrome9_ioctl_free(struct drm_device *dev, void *data,
+	struct drm_file *file_prev);
+extern int via_chrome9_ioctl_wait_chip_idle(struct drm_device *dev,
+	void *data, struct drm_file *file_priv);
+extern int via_chrome9_ioctl_flush_cache(struct drm_device *dev,
+	void *data, struct drm_file *file_priv);
+extern int via_chrome9_ioctl_flush(struct drm_device *dev, void *data,
+	struct drm_file *file_priv);
+extern int via_chrome9_ioctl_free(struct drm_device *dev, void *data,
+	struct drm_file *file_priv);
+extern unsigned int ProtectSizeValue(unsigned int size);
+extern void SetAGPDoubleCmd_inv(struct drm_device *dev);
+extern void SetAGPRingCmdRegs_inv(struct drm_device *dev);
+
+#endif
--- /dev/null
+++ b/drivers/char/drm/via_chrome9_drm.c
@@ -0,0 +1,993 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license,
+ * 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL VIA, S3 GRAPHICS, 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.
+ */
+#include "drmP.h"
+#include "via_chrome9_drm.h"
+#include "via_chrome9_drv.h"
+#include "via_chrome9_mm.h"
+#include "via_chrome9_dma.h"
+#include "via_chrome9_3d_reg.h"
+
+#define VIA_CHROME9DRM_VIDEO_STARTADDRESS_ALIGNMENT 10
+
+
+void __via_chrome9ke_udelay(unsigned long usecs)
+{
+	unsigned long start;
+	unsigned long stop;
+	unsigned long period;
+	unsigned long wait_period;
+	struct timespec tval;
+
+#ifdef NDELAY_LIMIT
+#define UDELAY_LIMIT    (NDELAY_LIMIT/1000) /* supposed to be 10 msec */
+#else
+#define UDELAY_LIMIT    (10000)             /* 10 msec */
+#endif
+
+	if (usecs > UDELAY_LIMIT) {
+		start = jiffies;
+		tval.tv_sec = usecs / 1000000;
+		tval.tv_nsec = (usecs - tval.tv_sec * 1000000) * 1000;
+		wait_period = timespec_to_jiffies(&tval);
+		do {
+			stop = jiffies;
+
+			if (stop < start)
+				period = ((unsigned long)-1 - start) + stop + 1;
+			else
+				period = stop - start;
+
+		} while (period < wait_period);
+	} else
+		udelay(usecs);  /* delay value might get checked once again */
+}
+
+int via_chrome9_ioctl_process_exit(struct drm_device *dev, void *data,
+	struct drm_file *file_priv)
+{
+	return 0;
+}
+
+int via_chrome9_ioctl_restore_primary(struct drm_device *dev,
+	void *data, struct drm_file *file_priv)
+{
+	return 0;
+}
+
+void Initialize3DEngine(struct drm_via_chrome9_private *dev_priv)
+{
+	int i;
+	unsigned int StageOfTexture;
+
+	if (dev_priv->chip_sub_index == CHIP_H5 ||
+		dev_priv->chip_sub_index == CHIP_H5S1) {
+		SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+			0x00010000);
+
+		for (i = 0; i <= 0x8A; i++) {
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(unsigned int) i << 24);
+		}
+
+		/* Initial Texture Stage Setting*/
+		for (StageOfTexture = 0; StageOfTexture < 0xf;
+		StageOfTexture++) {
+			SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+				(0x00020000 | 0x00000000 |
+				(StageOfTexture & 0xf)<<24));
+		/*  *((unsigned int volatile*)(pMapIOPort+HC_REG_TRANS_SET)) =
+		(0x00020000 | HC_ParaSubType_Tex0 | (StageOfTexture &
+		0xf)<<24);*/
+			for (i = 0 ; i <= 0x30 ; i++) {
+			/* *((unsigned int volatile*)(pMapIOPort+
+			HC_REG_Hpara0)) = ((unsigned int) i << 24);*/
+				SetMMIORegister(dev_priv->mmio->handle,
+				0x440, (unsigned int) i << 24);
+			}
+		}
+
+		/* Initial Texture Sampler Setting*/
+		for (StageOfTexture = 0; StageOfTexture < 0xf;
+		StageOfTexture++) {
+			SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+				(0x00020000 | 0x00020000 |
+				(StageOfTexture & 0xf)<<24));
+			/* *((unsigned int volatile*)(pMapIOPort+
+			HC_REG_TRANS_SET)) = (0x00020000 | 0x00020000 |
+			( StageOfTexture & 0xf)<<24);*/
+			for (i = 0 ; i <= 0x30 ; i++) {
+			/* *((unsigned int volatile*)(pMapIOPort+
+			HC_REG_Hpara0)) = ((unsigned int) i << 24);*/
+				SetMMIORegister(dev_priv->mmio->handle,
+				0x440, (unsigned int) i << 24);
+			}
+		}
+
+		SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+			(0x00020000 | 0xfe000000));
+		/* *((unsigned int volatile*)(pMapIOPort+HC_REG_TRANS_SET)) =
+			(0x00020000 | HC_ParaSubType_TexGen);*/
+		for (i = 0 ; i <= 0x13 ; i++) {
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(unsigned int) i << 24);
+			/* *((unsigned int volatile*)(pMapIOPort+
+			HC_REG_Hpara0)) = ((unsigned int) i << 24);*/
+		}
+
+		/* Initial Gamma Table Setting*/
+		/* Initial Gamma Table Setting*/
+		/* 5 + 4 = 9 (12) dwords*/
+		/* sRGB texture is not directly support by H3 hardware.
+		We have to set the deGamma table for texture sampling.*/
+
+		/* degamma table*/
+		SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+			(0x00030000 | 0x15000000));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(0x40000000 | (30 << 20) | (15 << 10) | (5)));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			((119 << 20) | (81 << 10) | (52)));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			((283 << 20) | (219 << 10) | (165)));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			((535 << 20) | (441 << 10) | (357)));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			((119 << 20) | (884 << 20) | (757 << 10) |
+			(640)));
+
+		/* gamma table*/
+		SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+			(0x00030000 | 0x17000000));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(0x40000000 | (13 << 20) | (13 << 10) | (13)));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(0x40000000 | (26 << 20) | (26 << 10) | (26)));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(0x40000000 | (39 << 20) | (39 << 10) | (39)));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			((51 << 20) | (51 << 10) | (51)));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			((71 << 20) | (71 << 10) | (71)));
+		SetMMIORegister(dev_priv->mmio->handle,
+			0x440, (87 << 20) | (87 << 10) | (87));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(113 << 20) | (113 << 10) | (113));
+		SetMMIORegister(dev_priv->mmio->handle,
+			0x440, (135 << 20) | (135 << 10) | (135));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(170 << 20) | (170 << 10) | (170));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(199 << 20) | (199 << 10) | (199));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(246 << 20) | (246 << 10) | (246));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(284 << 20) | (284 << 10) | (284));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(317 << 20) | (317 << 10) | (317));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(347 << 20) | (347 << 10) | (347));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(373 << 20) | (373 << 10) | (373));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(398 << 20) | (398 << 10) | (398));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(442 << 20) | (442 << 10) | (442));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(481 << 20) | (481 << 10) | (481));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(517 << 20) | (517 << 10) | (517));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(550 << 20) | (550 << 10) | (550));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(609 << 20) | (609 << 10) | (609));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(662 << 20) | (662 << 10) | (662));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(709 << 20) | (709 << 10) | (709));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(753 << 20) | (753 << 10) | (753));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(794 << 20) | (794 << 10) | (794));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(832 << 20) | (832 << 10) | (832));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(868 << 20) | (868 << 10) | (868));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(902 << 20) | (902 << 10) | (902));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(934 << 20) | (934 << 10) | (934));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(966 << 20) | (966 << 10) | (966));
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			(996 << 20) | (996 << 10) | (996));
+
+
+		/*
+		For Interrupt Restore only All types of write through
+		regsiters should be write header data to hardware at
+		least before it can restore. H/W will automatically
+		record the header to write through state buffer for
+		resture usage.
+		By Jaren:
+		HParaType = 8'h03, HParaSubType = 8'h00
+						8'h11
+						8'h12
+						8'h14
+						8'h15
+						8'h17
+		HParaSubType 8'h12, 8'h15 is initialized.
+		[HWLimit]
+		1. All these write through registers can't be partial
+		update.
+		2. All these write through must be AGP command
+		16 entries : 4 128-bit data */
+
+		 /* Initialize INV_ParaSubType_TexPal  	 */
+		SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+			(0x00030000 | 0x00000000));
+		for (i = 0; i < 16; i++) {
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				0x00000000);
+		}
+
+		/* Initialize INV_ParaSubType_4X4Cof */
+		/* 32 entries : 8 128-bit data */
+		SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+			(0x00030000 | 0x11000000));
+		for (i = 0; i < 32; i++) {
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				0x00000000);
+		}
+
+		/* Initialize INV_ParaSubType_StipPal */
+		/* 5 entries : 2 128-bit data */
+		SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+			(0x00030000 | 0x14000000));
+		for (i = 0; i < (5+3); i++) {
+			SetMMIORegister(dev_priv->mmio->handle,
+				0x440, 0x00000000);
+		}
+
+		/* primitive setting & vertex format*/
+		SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+			(0x00040000 | 0x14000000));
+		for (i = 0; i < 52; i++) {
+			SetMMIORegister(dev_priv->mmio->handle,
+			0x440, ((unsigned int) i << 24));
+		}
+		SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+			0x00fe0000);
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			0x4000840f);
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			0x47000400);
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			0x44000000);
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			0x46000000);
+
+		/* setting Misconfig*/
+		SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+			0x00fe0000);
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			0x00001004);
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			0x0800004b);
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			0x0a000049);
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			0x0b0000fb);
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			0x0c000001);
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			0x0d0000cb);
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			0x0e000009);
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			0x10000000);
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			0x110000ff);
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			0x12000000);
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			0x130000db);
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			0x14000000);
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			0x15000000);
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			0x16000000);
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			0x17000000);
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			0x18000000);
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			0x19000000);
+		SetMMIORegister(dev_priv->mmio->handle, 0x440,
+			0x20000000);
+		} else if (dev_priv->chip_sub_index == CHIP_H6S2) {
+			SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+				0x00010000);
+			for (i = 0; i <= 0x9A; i++) {
+				SetMMIORegister(dev_priv->mmio->handle, 0x440,
+					(unsigned int) i << 24);
+			}
+
+			/* Initial Texture Stage Setting*/
+			for (StageOfTexture = 0; StageOfTexture <= 0xf;
+			StageOfTexture++) {
+				SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+					(0x00020000 | 0x00000000 |
+					(StageOfTexture & 0xf)<<24));
+				/*  *((unsigned int volatile*)(pMapIOPort+
+				HC_REG_TRANS_SET)) =
+				(0x00020000 | HC_ParaSubType_Tex0 |
+				(StageOfTexture & 0xf)<<24);*/
+				for (i = 0 ; i <= 0x30 ; i++) {
+				/* *((unsigned int volatile*)(pMapIOPort+
+				HC_REG_Hpara0)) =((unsigned int) i << 24);*/
+					SetMMIORegister(dev_priv->mmio->handle,
+					0x440, (unsigned int) i << 24);
+				}
+			}
+
+			/* Initial Texture Sampler Setting*/
+			for (StageOfTexture = 0; StageOfTexture <= 0xf;
+			StageOfTexture++) {
+				SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+					(0x00020000 | 0x20000000 |
+					(StageOfTexture & 0xf)<<24));
+				/* *((unsigned int volatile*)(pMapIOPort+
+				HC_REG_TRANS_SET)) =(0x00020000 | 0x00020000 |
+				( StageOfTexture & 0xf)<<24);*/
+				for (i = 0 ; i <= 0x36 ; i++) {
+				/* *((unsigned int volatile*)(pMapIOPort+
+				HC_REG_Hpara0)) =((unsigned int) i << 24);*/
+					SetMMIORegister(dev_priv->mmio->handle,
+						0x440, (unsigned int) i << 24);
+				}
+			}
+
+			SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+				(0x00020000 | 0xfe000000));
+			for (i = 0 ; i <= 0x13 ; i++) {
+				SetMMIORegister(dev_priv->mmio->handle, 0x440,
+					(unsigned int) i << 24);
+				/* *((unsigned int volatile*)(pMapIOPort+
+				HC_REG_Hpara0)) =((unsigned int) i << 24);*/
+			}
+
+			/* Initial Gamma Table Setting*/
+			/* Initial Gamma Table Setting*/
+			/* 5 + 4 = 9 (12) dwords*/
+			/* sRGB texture is not directly support by
+			H3 hardware.*/
+			/* We have to set the deGamma table for texture
+			sampling.*/
+
+			/* degamma table*/
+			SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+				(0x00030000 | 0x15000000));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(0x40000000 | (30 << 20) | (15 << 10) | (5)));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				((119 << 20) | (81 << 10) | (52)));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				((283 << 20) | (219 << 10) | (165)));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				((535 << 20) | (441 << 10) | (357)));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				((119 << 20) | (884 << 20) | (757 << 10)
+				| (640)));
+
+			/* gamma table*/
+			SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+				(0x00030000 | 0x17000000));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(0x40000000 | (13 << 20) | (13 << 10) | (13)));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(0x40000000 | (26 << 20) | (26 << 10) | (26)));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(0x40000000 | (39 << 20) | (39 << 10) | (39)));
+			SetMMIORegister(dev_priv->mmio->handle,
+				0x440, ((51 << 20) | (51 << 10) | (51)));
+			SetMMIORegister(dev_priv->mmio->handle,
+				0x440, ((71 << 20) | (71 << 10) | (71)));
+			SetMMIORegister(dev_priv->mmio->handle,
+				0x440, (87 << 20) | (87 << 10) | (87));
+			SetMMIORegister(dev_priv->mmio->handle,
+				0x440, (113 << 20) | (113 << 10) | (113));
+			SetMMIORegister(dev_priv->mmio->handle,
+				0x440, (135 << 20) | (135 << 10) | (135));
+			SetMMIORegister(dev_priv->mmio->handle,
+				0x440, (170 << 20) | (170 << 10) | (170));
+			SetMMIORegister(dev_priv->mmio->handle,
+				0x440, (199 << 20) | (199 << 10) | (199));
+			SetMMIORegister(dev_priv->mmio->handle,
+				0x440, (246 << 20) | (246 << 10) | (246));
+			SetMMIORegister(dev_priv->mmio->handle,
+				0x440, (284 << 20) | (284 << 10) | (284));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(317 << 20) | (317 << 10) | (317));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(347 << 20) | (347 << 10) | (347));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(373 << 20) | (373 << 10) | (373));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(398 << 20) | (398 << 10) | (398));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(442 << 20) | (442 << 10) | (442));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(481 << 20) | (481 << 10) | (481));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(517 << 20) | (517 << 10) | (517));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(550 << 20) | (550 << 10) | (550));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(609 << 20) | (609 << 10) | (609));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(662 << 20) | (662 << 10) | (662));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(709 << 20) | (709 << 10) | (709));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(753 << 20) | (753 << 10) | (753));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(794 << 20) | (794 << 10) | (794));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(832 << 20) | (832 << 10) | (832));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(868 << 20) | (868 << 10) | (868));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(902 << 20) | (902 << 10) | (902));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(934 << 20) | (934 << 10) | (934));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(966 << 20) | (966 << 10) | (966));
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				(996 << 20) | (996 << 10) | (996));
+
+
+			/* For Interrupt Restore only
+			All types of write through regsiters should be write
+			header data to hardware at least before it can restore.
+			H/W will automatically record the header to write
+			through state buffer for restureusage.
+			By Jaren:
+			HParaType = 8'h03, HParaSubType = 8'h00
+			     8'h11
+			     8'h12
+			     8'h14
+			     8'h15
+			     8'h17
+			HParaSubType 8'h12, 8'h15 is initialized.
+			[HWLimit]
+			1. All these write through registers can't be partial
+			update.
+			2. All these write through must be AGP command
+			16 entries : 4 128-bit data */
+
+			/* Initialize INV_ParaSubType_TexPal  	 */
+			SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+				(0x00030000 | 0x00000000));
+			for (i = 0; i < 16; i++) {
+				SetMMIORegister(dev_priv->mmio->handle, 0x440,
+					0x00000000);
+			}
+
+			/* Initialize INV_ParaSubType_4X4Cof */
+			/* 32 entries : 8 128-bit data */
+			SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+				(0x00030000 | 0x11000000));
+			for (i = 0; i < 32; i++) {
+				SetMMIORegister(dev_priv->mmio->handle, 0x440,
+					0x00000000);
+			}
+
+			/* Initialize INV_ParaSubType_StipPal */
+			/* 5 entries : 2 128-bit data */
+			SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+				(0x00030000 | 0x14000000));
+			for (i = 0; i < (5+3); i++) {
+				SetMMIORegister(dev_priv->mmio->handle, 0x440,
+					0x00000000);
+			}
+
+			/* primitive setting & vertex format*/
+			SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+			(0x00040000));
+			for (i = 0; i <= 0x62; i++) {
+				SetMMIORegister(dev_priv->mmio->handle, 0x440,
+					((unsigned int) i << 24));
+			}
+
+			/*ParaType 0xFE - Configure and Misc Setting*/
+			SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+			(0x00fe0000));
+			for (i = 0; i <= 0x47; i++) {
+				SetMMIORegister(dev_priv->mmio->handle, 0x440,
+					((unsigned int) i << 24));
+			}
+			/*ParaType 0x11 - Frame Buffer Auto-Swapping and
+			Command Regulator Misc*/
+			SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+			(0x00110000));
+			for (i = 0; i <= 0x20; i++) {
+				SetMMIORegister(dev_priv->mmio->handle, 0x440,
+					((unsigned int) i << 24));
+			}
+			SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+				0x00fe0000);
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				0x4000840f);
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				0x47000404);
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				0x44000000);
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				0x46000005);
+
+			/* setting Misconfig*/
+			SetMMIORegister(dev_priv->mmio->handle, 0x43C,
+			0x00fe0000);
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				0x00001004);
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				0x08000249);
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				0x0a0002c9);
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				0x0b0002fb);
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				0x0c000000);
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				0x0d0002cb);
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				0x0e000009);
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				0x10000049);
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				0x110002ff);
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				0x12000008);
+			SetMMIORegister(dev_priv->mmio->handle, 0x440,
+				0x130002db);
+		}
+}
+
+int  via_chrome9_drm_resume(struct pci_dev *pci)
+{
+	struct drm_device *dev = (struct drm_device *)pci_get_drvdata(pci);
+	struct drm_via_chrome9_private *dev_priv =
+		(struct drm_via_chrome9_private *)dev->dev_private;
+	struct drm_via_chrome9_DMA_manager *lpcmDMAManager =
+		dev_priv->dma_manager;
+
+	Initialize3DEngine(dev_priv);
+
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_TRANS, 0x00110000);
+	if (dev_priv->chip_sub_index == CHIP_H6S2) {
+		SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN,
+			0x06000000);
+		SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN,
+			0x07100000);
+	} else{
+		SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN,
+			0x02000000);
+		SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN,
+			0x03100000);
+	}
+
+
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_TRANS,
+	INV_ParaType_PreCR);
+	SetMMIORegister(dev_priv->mmio->handle, INV_REG_CR_BEGIN,
+	INV_SubA_HSetRBGID | INV_HSetRBGID_CR);
+
+	if (dev_priv->chip_sub_index == CHIP_H6S2) {
+		unsigned int *pGARTTable;
+		unsigned int i, entries, GARTOffset;
+		unsigned char sr6a, sr6b, sr6c, sr6f, sr7b;
+		unsigned int *addrlinear;
+		unsigned int size, alignedoffset;
+
+		entries = dev_priv->pagetable_map.pagetable_size /
+			sizeof(unsigned int);
+		pGARTTable = dev_priv->pagetable_map.pagetable_handle;
+
+		GARTOffset = dev_priv->pagetable_map.pagetable_offset;
+
+		SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6c);
+		sr6c = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5);
+		sr6c &= (~0x80);
+		SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6c);
+
+		sr6a = (unsigned char)((GARTOffset & 0xff000) >> 12);
+		SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6a);
+		SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6a);
+
+		sr6b = (unsigned char)((GARTOffset & 0xff00000) >> 20);
+		SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6b);
+		SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6b);
+
+		SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6c);
+		sr6c = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5);
+		sr6c |= ((unsigned char)((GARTOffset >> 28) & 0x01));
+		SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6c);
+
+		SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x7b);
+		sr7b = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5);
+		sr7b &= (~0x0f);
+		sr7b |= ProtectSizeValue(dev_priv->
+			pagetable_map.pagetable_size);
+		SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr7b);
+
+		for (i = 0; i < entries; i++)
+			writel(0x80000000, pGARTTable+i);
+
+		/*flush*/
+		SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6f);
+		do {
+			sr6f = GetMMIORegisterU8(dev_priv->mmio->handle,
+				0x83c5);
+		} while (sr6f & 0x80);
+
+		sr6f |= 0x80;
+		SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6f);
+
+		SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6c);
+		sr6c = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5);
+		sr6c |= 0x80;
+		SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6c);
+
+		size = lpcmDMAManager->DMASize * sizeof(unsigned int) +
+		dev_priv->agp_size;
+		alignedoffset = 0;
+		entries = (size + PAGE_SIZE - 1) / PAGE_SIZE;
+		addrlinear = (unsigned int *)dev_priv->pcie_vmalloc_nocache;
+
+		SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6c);
+		sr6c = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5);
+		sr6c &= (~0x80);
+		SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6c);
+
+		SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6f);
+		do {
+			sr6f = GetMMIORegisterU8(dev_priv->mmio->handle,
+				0x83c5);
+		} while (sr6f & 0x80);
+
+		for (i = 0; i < entries; i++)
+			writel(page_to_pfn(vmalloc_to_page((void *)addrlinear +
+				PAGE_SIZE * i)) & 0x3fffffff, pGARTTable+
+				i+alignedoffset);
+
+		sr6f |= 0x80;
+		SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6f);
+
+		SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c4, 0x6c);
+		sr6c = GetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5);
+		sr6c |= 0x80;
+		SetMMIORegisterU8(dev_priv->mmio->handle, 0x83c5, sr6c);
+
+	}
+
+	if (dev_priv->drm_agp_type == DRM_AGP_DOUBLE_BUFFER)
+		SetAGPDoubleCmd_inv(dev);
+	else if (dev_priv->drm_agp_type == DRM_AGP_RING_BUFFER)
+		SetAGPRingCmdRegs_inv(dev);
+	return 0;
+}
+
+int  via_chrome9_drm_suspend(struct pci_dev *dev,
+	pm_message_t state)
+{
+	return 0;
+}
+
+int via_chrome9_driver_load(struct drm_device *dev,
+	unsigned long chipset)
+{
+	struct drm_via_chrome9_private *dev_priv;
+	int ret = 0;
+	static int associate;
+
+	if (!associate) {
+		pci_set_drvdata(dev->pdev, dev);
+		dev->pdev->driver = &dev->driver->pci_driver;
+		associate = 1;
+	}
+
+	dev->counters += 4;
+	dev->types[6] = _DRM_STAT_IRQ;
+	dev->types[7] = _DRM_STAT_PRIMARY;
+	dev->types[8] = _DRM_STAT_SECONDARY;
+	dev->types[9] = _DRM_STAT_DMA;
+
+	dev_priv = drm_calloc(1, sizeof(struct drm_via_chrome9_private),
+		DRM_MEM_DRIVER);
+	if (dev_priv == NULL)
+		return -ENOMEM;
+
+	/* Clear */
+	memset(dev_priv, 0, sizeof(struct drm_via_chrome9_private));
+
+	dev_priv->dev = dev;
+	dev->dev_private = (void *)dev_priv;
+
+	dev_priv->chip_index = chipset;
+
+	ret = drm_sman_init(&dev_priv->sman, 2, 12, 8);
+	if (ret)
+		drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+	return ret;
+}
+
+int via_chrome9_driver_unload(struct drm_device *dev)
+{
+	struct drm_via_chrome9_private *dev_priv = dev->dev_private;
+
+	drm_sman_takedown(&dev_priv->sman);
+
+	drm_free(dev_priv, sizeof(struct drm_via_chrome9_private),
+		DRM_MEM_DRIVER);
+
+	return 0;
+}
+
+static int via_chrome9_initialize(struct drm_device *dev,
+	struct drm_via_chrome9_init *init)
+{
+	struct drm_via_chrome9_private *dev_priv =
+		(struct drm_via_chrome9_private *)dev->dev_private;
+
+	dev_priv->chip_agp = init->chip_agp;
+	dev_priv->chip_index = init->chip_index;
+	dev_priv->chip_sub_index = init->chip_sub_index;
+
+	dev_priv->usec_timeout = init->usec_timeout;
+	dev_priv->front_offset = init->front_offset;
+	dev_priv->back_offset = init->back_offset >>
+		VIA_CHROME9DRM_VIDEO_STARTADDRESS_ALIGNMENT <<
+		VIA_CHROME9DRM_VIDEO_STARTADDRESS_ALIGNMENT;
+	dev_priv->available_fb_size = init->available_fb_size -
+		(init->available_fb_size %
+		(1 << VIA_CHROME9DRM_VIDEO_STARTADDRESS_ALIGNMENT));
+	dev_priv->depth_offset = init->depth_offset;
+
+	/* Find all the map added first, doing this is necessary to
+	intialize hw */
+	if (via_chrome9_map_init(dev, init)) {
+		DRM_ERROR("function via_chrome9_map_init ERROR !\n");
+		goto error;
+	}
+
+	/* Necessary information has been gathered for initialize hw */
+	if (via_chrome9_hw_init(dev, init)) {
+		DRM_ERROR("function via_chrome9_hw_init ERROR !\n");
+		goto error;
+	}
+
+	/* After hw intialization, we have kown whether to use agp
+	or to use pcie for texture */
+	if (via_chrome9_heap_management_init(dev, init)) {
+		DRM_ERROR("function \
+			via_chrome9_heap_management_init ERROR !\n");
+		goto error;
+	}
+
+	return 0;
+
+error:
+	/* all the error recover has been processed in relevant function,
+	so here just return error */
+	return -EINVAL;
+}
+
+static void via_chrome9_cleanup(struct drm_device *dev,
+	struct drm_via_chrome9_init *init)
+{
+	struct drm_via_chrome9_DMA_manager *lpcmDMAManager = NULL;
+	struct drm_via_chrome9_private *dev_priv =
+		(struct drm_via_chrome9_private *)dev->dev_private;
+	DRM_DEBUG("function via_chrome9_cleanup run!\n");
+
+	if (!dev_priv)
+		return ;
+
+	lpcmDMAManager =
+		(struct drm_via_chrome9_DMA_manager *)dev_priv->dma_manager;
+	if (dev_priv->pcie_vmalloc_nocache) {
+		vfree((void *)dev_priv->pcie_vmalloc_nocache);
+		dev_priv->pcie_vmalloc_nocache = 0;
+		if (lpcmDMAManager)
+		lpcmDMAManager->addr_linear = NULL;
+	}
+
+	if (dev_priv->pagetable_map.pagetable_handle) {
+		iounmap(dev_priv->pagetable_map.pagetable_handle);
+		dev_priv->pagetable_map.pagetable_handle = NULL;
+	}
+
+	if (lpcmDMAManager && lpcmDMAManager->addr_linear) {
+		iounmap(lpcmDMAManager->addr_linear);
+		lpcmDMAManager->addr_linear = NULL;
+	}
+
+	kfree(lpcmDMAManager);
+	dev_priv->dma_manager = NULL;
+
+	if (dev_priv->event_tag_info) {
+		vfree(dev_priv->event_tag_info);
+		dev_priv->event_tag_info = NULL;
+	}
+
+	if (dev_priv->bci_buffer) {
+		vfree(dev_priv->bci_buffer);
+		dev_priv->bci_buffer = NULL;
+	}
+
+	via_chrome9_memory_destroy_heap(dev, dev_priv);
+}
+
+/*
+Do almost everything intialize here,include:
+1.intialize all addmaps in private data structure
+2.intialize memory heap management for video agp/pcie
+3.intialize hw for dma(pcie/agp) function
+
+Note:all this function will dispatch into relevant function
+*/
+int via_chrome9_ioctl_init(struct drm_device *dev, void *data,
+	struct drm_file *file_priv)
+{
+	struct drm_via_chrome9_init *init = (struct drm_via_chrome9_init *)data;
+
+	switch (init->func) {
+	case VIA_CHROME9_INIT:
+		if (via_chrome9_initialize(dev, init)) {
+			DRM_ERROR("function via_chrome9_initialize error\n");
+			return -1;
+		}
+		break;
+
+	case VIA_CHROME9_CLEANUP:
+		via_chrome9_cleanup(dev, init);
+		break;
+
+	default:
+		return -1;
+	}
+
+	return 0;
+}
+
+int via_chrome9_ioctl_allocate_event_tag(struct drm_device *dev,
+	void *data, struct drm_file *file_priv)
+{
+	struct drm_via_chrome9_event_tag *event_tag = data;
+	struct drm_via_chrome9_private *dev_priv =
+		(struct drm_via_chrome9_private *)dev->dev_private;
+	struct drm_clb_event_tag_info *event_tag_info =
+		dev_priv->event_tag_info;
+	unsigned int *event_addr = 0, i = 0;
+
+	for (i = 0; i < NUMBER_OF_EVENT_TAGS; i++) {
+		if (!event_tag_info->usage[i])
+			break;
+	}
+
+	if (i < NUMBER_OF_EVENT_TAGS) {
+		event_tag_info->usage[i] = 1;
+		event_tag->event_offset = i;
+		event_tag->last_sent_event_value.event_low = 0;
+		event_tag->current_event_value.event_low = 0;
+		event_addr = event_tag_info->linear_address +
+		event_tag->event_offset * 4;
+		*event_addr = 0;
+		return 0;
+	} else {
+		return -7;
+	}
+
+	return 0;
+}
+
+int via_chrome9_ioctl_free_event_tag(struct drm_device *dev,
+	void *data, struct drm_file *file_priv)
+{
+	struct drm_via_chrome9_private *dev_priv =
+		(struct drm_via_chrome9_private *)dev->dev_private;
+	struct drm_clb_event_tag_info *event_tag_info =
+		dev_priv->event_tag_info;
+	struct drm_via_chrome9_event_tag *event_tag = data;
+
+	event_tag_info->usage[event_tag->event_offset] = 0;
+	return 0;
+}
+
+void via_chrome9_lastclose(struct drm_device *dev)
+{
+	via_chrome9_cleanup(dev, 0);
+	return ;
+}
+
+static int via_chrome9_do_wait_vblank(struct drm_via_chrome9_private
+		*dev_priv)
+{
+	int i;
+
+	for (i = 0; i < dev_priv->usec_timeout; i++) {
+		VIA_CHROME9_WRITE8(0x83d4, 0x34);
+		if ((VIA_CHROME9_READ8(0x83d5)) & 0x8)
+			return 0;
+		__via_chrome9ke_udelay(1);
+	}
+
+	return (-1);
+}
+
+void via_chrome9_preclose(struct drm_device *dev, struct drm_file *file_priv)
+{
+	struct drm_via_chrome9_private *dev_priv =
+		(struct drm_via_chrome9_private *) dev->dev_private;
+	struct drm_via_chrome9_sarea *sarea_priv = NULL;
+
+	if (!dev_priv)
+		return ;
+
+	sarea_priv = dev_priv->sarea_priv;
+	if (!sarea_priv)
+		return ;
+
+	if ((sarea_priv->page_flip == 1) &&
+		(sarea_priv->current_page != VIA_CHROME9_FRONT)) {
+		volatile unsigned long *bci_base;
+		if (via_chrome9_do_wait_vblank(dev_priv))
+			return;
+
+		bci_base = (volatile unsigned long *)(dev_priv->bci);
+
+		BCI_SET_STREAM_REGISTER(bci_base, 0x81c4, 0xc0000000);
+		BCI_SET_STREAM_REGISTER(bci_base, 0x81c0,
+			dev_priv->front_offset);
+		BCI_SEND(bci_base, 0x64000000);/* wait vsync */
+
+		sarea_priv->current_page = VIA_CHROME9_FRONT;
+	}
+}
+
+int via_chrome9_is_agp(struct drm_device *dev)
+{
+	/* filter out pcie group which has no AGP device */
+	if (dev->pci_device == 0x1122) {
+		dev->driver->driver_features &=
+		~(DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_REQUIRE_AGP);
+		return 0;
+	}
+	return 1;
+}
+
--- /dev/null
+++ b/drivers/char/drm/via_chrome9_drm.h
@@ -0,0 +1,423 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license,
+ * 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL VIA, S3 GRAPHICS, 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.
+ */
+#ifndef _VIA_CHROME9_DRM_H_
+#define _VIA_CHROME9_DRM_H_
+
+/* WARNING: These defines must be the same as what the Xserver uses.
+ * if you change them, you must change the defines in the Xserver.
+ */
+
+#ifndef _VIA_CHROME9_DEFINES_
+#define _VIA_CHROME9_DEFINES_
+
+#ifndef __KERNEL__
+#include "via_drmclient.h"
+#endif
+
+#define VIA_CHROME9_NR_SAREA_CLIPRECTS 		8
+#define VIA_CHROME9_NR_XVMC_PORTS               10
+#define VIA_CHROME9_NR_XVMC_LOCKS               5
+#define VIA_CHROME9_MAX_CACHELINE_SIZE          64
+#define XVMCLOCKPTR(saPriv,lockNo)					\
+	((volatile struct drm_hw_lock *)				\
+	(((((unsigned long) (saPriv)->XvMCLockArea) + 			\
+				      (VIA_CHROME9_MAX_CACHELINE_SIZE - 1)) & \
+				     ~(VIA_CHROME9_MAX_CACHELINE_SIZE - 1)) + \
+				    VIA_CHROME9_MAX_CACHELINE_SIZE*(lockNo)))
+
+/* Each region is a minimum of 64k, and there are at most 64 of them.
+ */
+#define VIA_CHROME9_NR_TEX_REGIONS 64
+#define VIA_CHROME9_LOG_MIN_TEX_REGION_SIZE 16
+#endif
+
+#define VIA_CHROME9_UPLOAD_TEX0IMAGE  0x1	/* handled clientside */
+#define VIA_CHROME9_UPLOAD_TEX1IMAGE  0x2	/* handled clientside */
+#define VIA_CHROME9_UPLOAD_CTX        0x4
+#define VIA_CHROME9_UPLOAD_BUFFERS    0x8
+#define VIA_CHROME9_UPLOAD_TEX0       0x10
+#define VIA_CHROME9_UPLOAD_TEX1       0x20
+#define VIA_CHROME9_UPLOAD_CLIPRECTS  0x40
+#define VIA_CHROME9_UPLOAD_ALL        0xff
+
+/* VIA_CHROME9 specific ioctls */
+#define DRM_VIA_CHROME9_ALLOCMEM                    0x00
+#define DRM_VIA_CHROME9_FREEMEM                     0x01
+#define DRM_VIA_CHROME9_FREE                        0x02
+#define DRM_VIA_CHROME9_ALLOCATE_EVENT_TAG          0x03
+#define DRM_VIA_CHROME9_FREE_EVENT_TAG              0x04
+#define DRM_VIA_CHROME9_ALLOCATE_APERTURE           0x05
+#define DRM_VIA_CHROME9_FREE_APERTURE               0x06
+#define DRM_VIA_CHROME9_ALLOCATE_VIDEO_MEM          0x07
+#define DRM_VIA_CHROME9_FREE_VIDEO_MEM              0x08
+#define DRM_VIA_CHROME9_WAIT_CHIP_IDLE              0x09
+#define DRM_VIA_CHROME9_PROCESS_EXIT                0x0A
+#define DRM_VIA_CHROME9_RESTORE_PRIMARY             0x0B
+#define DRM_VIA_CHROME9_FLUSH_CACHE                 0x0C
+#define DRM_VIA_CHROME9_INIT                        0x0D
+#define DRM_VIA_CHROME9_FLUSH                       0x0E
+#define DRM_VIA_CHROME9_CHECKVIDMEMSIZE             0x0F
+#define DRM_VIA_CHROME9_PCIEMEMCTRL                 0x10
+#define DRM_VIA_CHROME9_AUTH_MAGIC	            0x11
+
+#define DRM_IOCTL_VIA_CHROME9_INIT                  	 \
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_INIT, \
+	struct drm_via_chrome9_init)
+#define DRM_IOCTL_VIA_CHROME9_FLUSH                 \
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_FLUSH, \
+	struct drm_via_chrome9_flush)
+#define DRM_IOCTL_VIA_CHROME9_FREE                  \
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_FREE, int)
+#define DRM_IOCTL_VIA_CHROME9_ALLOCATE_EVENT_TAG    \
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_ALLOCATE_EVENT_TAG, \
+	struct drm_event_via_chrome9_tag)
+#define DRM_IOCTL_VIA_CHROME9_FREE_EVENT_TAG        \
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_FREE_EVENT_TAG, \
+	struct drm_event_via_chrome9_tag)
+#define DRM_IOCTL_VIA_CHROME9_ALLOCATE_APERTURE     \
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_ALLOCATE_APERTURE, \
+	struct drm_via_chrome9_aperture)
+#define DRM_IOCTL_VIA_CHROME9_FREE_APERTURE         \
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_FREE_APERTURE, \
+	struct drm_via_chrome9_aperture)
+#define DRM_IOCTL_VIA_CHROME9_ALLOCATE_VIDEO_MEM    \
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_ALLOCATE_VIDEO_MEM, \
+	struct drm_via_chrome9_memory_alloc)
+#define DRM_IOCTL_VIA_CHROME9_FREE_VIDEO_MEM        \
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_FREE_VIDEO_MEM, \
+	struct drm_via_chrome9_memory_alloc)
+#define DRM_IOCTL_VIA_CHROME9_WAIT_CHIP_IDLE        \
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_WAIT_CHIP_IDLE, int)
+#define DRM_IOCTL_VIA_CHROME9_PROCESS_EXIT          \
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_PROCESS_EXIT, int)
+#define DRM_IOCTL_VIA_CHROME9_RESTORE_PRIMARY       \
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_RESTORE_PRIMARY, int)
+#define DRM_IOCTL_VIA_CHROME9_FLUSH_CACHE           \
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_FLUSH_CACHE, int)
+#define DRM_IOCTL_VIA_CHROME9_ALLOCMEM       	    \
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_ALLOCMEM, int)
+#define DRM_IOCTL_VIA_CHROME9_FREEMEM               \
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_FREEMEM, int)
+#define DRM_IOCTL_VIA_CHROME9_CHECK_VIDMEM_SIZE     \
+	DRM_IOW(DRM_COMMAND_BASE +  DRM_VIA_CHROME9_CHECKVIDMEMSIZE, \
+	struct drm_via_chrome9_memory_alloc)
+#define DRM_IOCTL_VIA_CHROME9_PCIEMEMCTRL           \
+	DRM_IOW(DRM_COMMAND_BASE +  DRM_VIA_CHROME9_PCIEMEMCTRL,\
+	drm_via_chrome9_pciemem_ctrl_t)
+#define DRM_IOCTL_VIA_CHROME9_AUTH_MAGIC            \
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_CHROME9_AUTH_MAGIC, drm_auth_t)
+
+enum S3GCHIPIDS {
+	CHIP_UNKNOWN = -1,
+	CHIP_CMODEL,    /*Model for any chip. */
+	CHIP_CLB,       /*Columbia */
+	CHIP_DST,       /*Destination */
+	CHIP_CSR,       /*Castlerock */
+	CHIP_INV,       /*Innovation (H3) */
+	CHIP_H5,        /*Innovation (H5) */
+	CHIP_H5S1,      /*Innovation (H5S1) */
+	CHIP_H6S2,      /*Innovation (H6S2) */
+	CHIP_CMS,       /*Columbia MS */
+	CHIP_METRO,     /*Metropolis */
+	CHIP_MANHATTAN, /*manhattan */
+	CHIP_MATRIX,    /*matrix */
+	CHIP_EVO,	    /*change for GCC 4.1 -add- 07.02.12*/
+	CHIP_H6S1,      /*Innovation (H6S1)*/
+	CHIP_DST2,      /*Destination-2 */
+	CHIP_LAST       /*Maximum number of chips supported. */
+};
+
+enum VIA_CHROME9CHIPBUS {
+	CHIP_PCI,
+	CHIP_AGP,
+	CHIP_PCIE
+};
+
+struct drm_via_chrome9_init {
+	enum {
+		VIA_CHROME9_INIT    = 0x01,
+		VIA_CHROME9_CLEANUP = 0x02
+	} func;
+	int chip_agp;
+	int chip_index;
+	int chip_sub_index;
+	int usec_timeout;
+	unsigned int   sarea_priv_offset;
+	unsigned int   fb_cpp;
+	unsigned int   front_offset;
+	unsigned int   back_offset;
+	unsigned int   depth_offset;
+	unsigned int   mmio_handle;
+	unsigned int   dma_handle;
+	unsigned int   fb_handle;
+	unsigned int   front_handle;
+	unsigned int   back_handle;
+	unsigned int   depth_handle;
+
+	unsigned int   fb_tex_offset;
+	unsigned int   fb_tex_size;
+
+	unsigned int   agp_tex_size;
+	unsigned int   agp_tex_handle;
+	unsigned int   shadow_size;
+	unsigned int   shadow_handle;
+	unsigned int   garttable_size;
+	unsigned int   garttable_offset;
+	unsigned long  available_fb_size;
+	unsigned long  fb_base_address;
+	unsigned int   DMA_size;
+	unsigned long  DMA_phys_address;
+	enum {
+		AGP_RING_BUFFER,
+		AGP_DOUBLE_BUFFER,
+		AGP_DISABLED
+	} agp_type;
+	unsigned int hostBlt_handle;
+};
+
+enum dma_cmd_type {
+	flush_bci = 0,
+	flush_bci_and_wait,
+	dma_kickoff,
+	flush_dma_buffer,
+	flush_dma_and_wait
+};
+
+struct drm_via_chrome9_flush {
+	enum dma_cmd_type    dma_cmd_type;
+	/* command buffer index */
+	int    cmd_idx;
+	/* command buffer offset */
+	int    cmd_offset;
+	/* command dword size,command always from beginning */
+	int    cmd_size;
+	/* if use dma kick off,it is dma kick off command */
+	unsigned long  dma_kickoff[2];
+	/* user mode DMA buffer pointer */
+	unsigned int *usermode_dma_buf;
+};
+
+struct event_value {
+	int event_low;
+	int event_high;
+};
+
+struct drm_via_chrome9_event_tag {
+	unsigned int  event_size;         /* event tag size */
+	int	 event_offset;                /* event tag id */
+	struct event_value last_sent_event_value;
+	struct event_value current_event_value;
+	int         query_mask0;
+	int         query_mask1;
+	int         query_Id1;
+};
+
+/* Indices into buf.Setup where various bits of state are mirrored per
+ * context and per buffer.  These can be fired at the card as a unit,
+ * or in a piecewise fashion as required.
+ */
+
+#define VIA_CHROME9_TEX_SETUP_SIZE 8
+
+/* Flags for clear ioctl
+ */
+#define VIA_CHROME9_FRONT   0x1
+#define VIA_CHROME9_BACK    0x2
+#define VIA_CHROME9_DEPTH   0x4
+#define VIA_CHROME9_STENCIL 0x8
+#define VIA_CHROME9_MEM_VIDEO   0	/* matches drm constant */
+#define VIA_CHROME9_MEM_AGP     1	/* matches drm constant */
+#define VIA_CHROME9_MEM_SYSTEM  2
+#define VIA_CHROME9_MEM_MIXED   3
+#define VIA_CHROME9_MEM_UNKNOWN 4
+
+struct drm_via_chrome9_agp {
+	uint32_t offset;
+	uint32_t size;
+};
+
+struct drm_via_chrome9_fb {
+	uint32_t offset;
+	uint32_t size;
+};
+
+struct drm_via_chrome9_mem {
+	uint32_t context;
+	uint32_t type;
+	uint32_t size;
+	unsigned long index;
+	unsigned long offset;
+};
+
+struct drm_via_chrome9_aperture {
+	/*IN: The frame buffer offset of the surface. */
+	int surface_offset;
+	/*IN: Surface pitch in byte, */
+	int pitch;
+	/*IN: Surface width in pixel */
+	int width;
+	/*IN: Surface height in pixel */
+	int height;
+	/*IN: Surface color format, Columbia has more color formats */
+	int color_format;
+	/*IN: Rotation degrees, only for Columbia */
+	int rotation_degree;
+	/*IN Is the PCIE Video, for MATRIX support NONLOCAL Aperture */
+	int isPCIEVIDEO;
+	/*IN: Is the surface tilled, only for Columbia */
+	int is_tiled;
+	/*IN:  Only allocate apertur, not hardware setup. */
+	int allocate_only;
+	/* OUT: linear address for aperture */
+	unsigned int *aperture_linear_address;
+	/*OUT:  The pitch of the aperture,for CPU write not for GE */
+	int aperture_pitch;
+	/*OUT: The index of the aperture */
+	int aperture_handle;
+	int apertureID;
+	/* always =0xAAAAAAAA */
+	/* Aligned surface's width(in pixel) */
+	int width_aligned;
+	/* Aligned surface's height(in pixel) */
+	int height_aligned;
+};
+
+/*
+    Some fileds of this data structure has no meaning now since
+    we have managed heap based on mechanism provided by DRM
+    Remain what it was to keep consistent with 3D driver interface.
+*/
+struct drm_via_chrome9_memory_alloc {
+	enum {
+		memory_heap_video = 0,
+		memory_heap_agp,
+		memory_heap_pcie_video,
+		memory_heap_pcie,
+		max_memory_heaps
+	} heap_type;
+	struct {
+		void *lpL1Node;
+		unsigned int       alcL1Tag;
+		unsigned int       usageCount;
+		unsigned int       dwVersion;
+		unsigned int       dwResHandle;
+		unsigned int       dwProcessID;
+	} heap_info;
+	unsigned int flags;
+	unsigned int size;
+	unsigned int physaddress;
+	unsigned int offset;
+	unsigned int align;
+	void *linearaddress;
+};
+
+struct drm_via_chrome9_dma_init {
+	enum {
+		VIA_CHROME9_INIT_DMA = 0x01,
+		VIA_CHROME9_CLEANUP_DMA = 0x02,
+		VIA_CHROME9_DMA_INITIALIZED = 0x03
+	} func;
+
+	unsigned long offset;
+	unsigned long size;
+	unsigned long reg_pause_addr;
+};
+
+struct drm_via_chrome9_cmdbuffer {
+	char __user *buf;
+	unsigned long size;
+};
+
+/* Warning: If you change the SAREA structure you must change the Xserver
+ * structure as well */
+
+struct drm_via_chrome9_tex_region {
+	unsigned char next, prev;	/* indices to form a circular LRU  */
+	unsigned char inUse;	/* owned by a client, or free? */
+	int age;		/* tracked by clients to update local LRU's */
+};
+
+struct drm_via_chrome9_sarea {
+	int page_flip;
+	int current_page;
+	unsigned int req_drawable;/* the X drawable id */
+	unsigned int req_draw_buffer;/* VIA_CHROME9_FRONT or VIA_CHROME9_BACK */
+	/* Last context that uploaded state */
+	int ctx_owner;
+};
+
+struct drm_via_chrome9_cmdbuf_size {
+	enum {
+		VIA_CHROME9_CMDBUF_SPACE = 0x01,
+		VIA_CHROME9_CMDBUF_LAG = 0x02
+	} func;
+	int wait;
+	uint32_t size;
+};
+
+struct drm_via_chrome9_DMA_manager {
+	unsigned int     *addr_linear;
+	unsigned int     DMASize;
+	unsigned int     bDMAAgp;
+	unsigned int     LastIssuedEventTag;
+	unsigned int     *pBeg;
+	unsigned int     *pInUseByHW;
+	unsigned int     **ppInUseByHW;
+	unsigned int     *pInUseBySW;
+	unsigned int     *pFree;
+	unsigned int     *pEnd;
+
+	unsigned long    pPhysical;
+	unsigned int     MaxKickoffSize;
+};
+
+extern int via_chrome9_ioctl_wait_chip_idle(struct drm_device *dev,
+	void *data, struct drm_file *file_priv);
+extern int via_chrome9_ioctl_init(struct drm_device *dev,
+	void *data, struct drm_file *file_priv);
+extern int via_chrome9_ioctl_allocate_event_tag(struct drm_device
+	*dev, void *data, struct drm_file *file_priv);
+extern int via_chrome9_ioctl_free_event_tag(struct drm_device *dev,
+	void *data, struct drm_file *file_priv);
+extern int via_chrome9_driver_load(struct drm_device *dev,
+	unsigned long chipset);
+extern int via_chrome9_driver_unload(struct drm_device *dev);
+extern int via_chrome9_ioctl_process_exit(struct drm_device *dev,
+	void *data, struct drm_file *file_priv);
+extern int via_chrome9_ioctl_restore_primary(struct drm_device *dev,
+	void *data, struct drm_file *file_priv);
+extern int  via_chrome9_drm_resume(struct pci_dev *dev);
+extern int  via_chrome9_drm_suspend(struct pci_dev *dev,
+	pm_message_t state);
+extern void __via_chrome9ke_udelay(unsigned long usecs);
+extern void via_chrome9_lastclose(struct drm_device *dev);
+extern void via_chrome9_preclose(struct drm_device *dev,
+	struct drm_file *file_priv);
+extern int via_chrome9_is_agp(struct drm_device *dev);
+
+
+#endif				/* _VIA_CHROME9_DRM_H_ */
--- /dev/null
+++ b/drivers/char/drm/via_chrome9_drv.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license,
+ * 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL VIA, S3 GRAPHICS, 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.
+ */
+
+#include "drmP.h"
+#include "via_chrome9_drm.h"
+#include "via_chrome9_drv.h"
+#include "via_chrome9_dma.h"
+#include "via_chrome9_mm.h"
+
+#include "drm_pciids.h"
+
+static int dri_library_name(struct drm_device *dev, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "via_chrome9");
+}
+
+int via_chrome9_drm_authmagic(struct drm_device *dev, void *data,
+	struct drm_file *file_priv)
+{
+	return 0;
+}
+
+struct drm_ioctl_desc via_chrome9_ioctls[] = {
+	DRM_IOCTL_DEF(DRM_VIA_CHROME9_INIT, via_chrome9_ioctl_init,
+		DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),/* via_chrome9_map.c*/
+	DRM_IOCTL_DEF(DRM_VIA_CHROME9_FLUSH, via_chrome9_ioctl_flush, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_VIA_CHROME9_FREE, via_chrome9_ioctl_free, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_VIA_CHROME9_ALLOCATE_EVENT_TAG,
+		via_chrome9_ioctl_allocate_event_tag, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_VIA_CHROME9_FREE_EVENT_TAG,
+		via_chrome9_ioctl_free_event_tag, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_VIA_CHROME9_ALLOCATE_APERTURE,
+		via_chrome9_ioctl_allocate_aperture, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_VIA_CHROME9_FREE_APERTURE,
+		via_chrome9_ioctl_free_aperture, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_VIA_CHROME9_ALLOCATE_VIDEO_MEM,
+	via_chrome9_ioctl_allocate_mem_wrapper,	DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_VIA_CHROME9_FREE_VIDEO_MEM,
+		via_chrome9_ioctl_free_mem_wrapper, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_VIA_CHROME9_WAIT_CHIP_IDLE,
+		via_chrome9_ioctl_wait_chip_idle, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_VIA_CHROME9_PROCESS_EXIT,
+		via_chrome9_ioctl_process_exit, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_VIA_CHROME9_RESTORE_PRIMARY,
+		via_chrome9_ioctl_restore_primary, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_VIA_CHROME9_FLUSH_CACHE,
+		via_chrome9_ioctl_flush_cache, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_VIA_CHROME9_ALLOCMEM,
+		via_chrome9_ioctl_allocate_mem_base, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_VIA_CHROME9_FREEMEM,
+		via_chrome9_ioctl_freemem_base, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_VIA_CHROME9_CHECKVIDMEMSIZE,
+		via_chrome9_ioctl_check_vidmem_size, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_VIA_CHROME9_PCIEMEMCTRL,
+		via_chrome9_ioctl_pciemem_ctrl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_VIA_CHROME9_AUTH_MAGIC, via_chrome9_drm_authmagic, 0)
+};
+
+int via_chrome9_max_ioctl = DRM_ARRAY_SIZE(via_chrome9_ioctls);
+
+static struct pci_device_id pciidlist[] = {
+	via_chrome9DRV_PCI_IDS
+};
+
+int  via_chrome9_driver_open(struct drm_device *dev,
+	struct drm_file *priv)
+{
+	priv->authenticated = 1;
+	return 0;
+}
+
+static struct drm_driver driver = {
+	.driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP |
+		DRIVER_HAVE_DMA | DRIVER_FB_DMA | DRIVER_USE_MTRR,
+	.open = via_chrome9_driver_open,
+	.load = via_chrome9_driver_load,
+	.unload = via_chrome9_driver_unload,
+	.device_is_agp = via_chrome9_is_agp,
+	.dri_library_name = dri_library_name,
+	.reclaim_buffers = drm_core_reclaim_buffers,
+	.reclaim_buffers_locked = NULL,
+	.reclaim_buffers_idlelocked = via_chrome9_reclaim_buffers_locked,
+	.lastclose = via_chrome9_lastclose,
+	.preclose = via_chrome9_preclose,
+	.get_map_ofs = drm_core_get_map_ofs,
+	.get_reg_ofs = drm_core_get_reg_ofs,
+	.ioctls = via_chrome9_ioctls,
+	.fops = {
+		 .owner = THIS_MODULE,
+		 .open = drm_open,
+		 .release = drm_release,
+		 .ioctl = drm_ioctl,
+		 .mmap = drm_mmap,
+		 .poll = drm_poll,
+		 .fasync = drm_fasync,
+	},
+	.pci_driver = {
+		 .name = DRIVER_NAME,
+		 .id_table = pciidlist,
+		 .resume = via_chrome9_drm_resume,
+		 .suspend = via_chrome9_drm_suspend,
+	},
+
+	.name = DRIVER_NAME,
+	.desc = DRIVER_DESC,
+	.date = DRIVER_DATE,
+	.major = DRIVER_MAJOR,
+	.minor = DRIVER_MINOR,
+	.patchlevel = DRIVER_PATCHLEVEL,
+};
+
+static int __init via_chrome9_init(void)
+{
+    driver.num_ioctls = via_chrome9_max_ioctl;
+    driver.dev_priv_size = sizeof(struct drm_via_chrome9_private);
+    return drm_init(&driver);
+}
+
+static void __exit via_chrome9_exit(void)
+{
+	drm_exit(&driver);
+}
+
+module_init(via_chrome9_init);
+module_exit(via_chrome9_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
--- /dev/null
+++ b/drivers/char/drm/via_chrome9_drv.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license,
+ * 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL VIA, S3 GRAPHICS, 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.
+ */
+#ifndef _VIA_CHROME9_DRV_H_
+#define _VIA_CHROME9_DRV_H_
+
+#include "drm_sman.h"
+#define DRIVER_AUTHOR	"Various"
+
+#define DRIVER_NAME		"via_chrome9_chrome9"
+#define DRIVER_DESC		"VIA_CHROME9 Unichrome / Pro"
+#define DRIVER_DATE		"20080415"
+
+#define DRIVER_MAJOR		2
+#define DRIVER_MINOR		11
+#define DRIVER_PATCHLEVEL	1
+
+#define via_chrome9_PCI_BUF_SIZE 60000
+#define via_chrome9_FIRE_BUF_SIZE  1024
+#define via_chrome9_NUM_IRQS 4
+
+#define MAX_MEMORY_HEAPS     4
+#define NUMBER_OF_APERTURES     32
+
+/*typedef struct drm_via_chrome9_shadow_map drm_via_chrome9_shadow_map_t;*/
+struct drm_via_chrome9_shadow_map {
+	struct drm_map  *shadow;
+	unsigned int   shadow_size;
+	unsigned int   *shadow_handle;
+};
+
+/*typedef struct drm_via_chrome9_pagetable_map
+ *drm_via_chrome9_pagetable_map_t;
+ */
+struct drm_via_chrome9_pagetable_map {
+	unsigned int pagetable_offset;
+	unsigned int pagetable_size;
+	unsigned int *pagetable_handle;
+	unsigned int mmt_register;
+};
+
+/*typedef struct drm_via_chrome9_private drm_via_chrome9_private_t;*/
+struct drm_via_chrome9_private {
+	int chip_agp;
+	int chip_index;
+	int chip_sub_index;
+
+	unsigned long front_offset;
+	unsigned long back_offset;
+	unsigned long depth_offset;
+	unsigned long fb_base_address;
+	unsigned long available_fb_size;
+	int usec_timeout;
+	int max_apertures;
+	struct drm_sman sman;
+	unsigned int alignment;
+	/* bit[31]:0:indicate no alignment needed,1:indicate
+	alignment needed and size is bit[0:30]*/
+
+	struct drm_map *sarea;
+	struct drm_via_chrome9_sarea *sarea_priv;
+
+	struct drm_map  *mmio;
+	struct drm_map  *hostBlt;
+	struct drm_map  *fb;
+	struct drm_map  *front;
+	struct drm_map  *back;
+	struct drm_map  *depth;
+	struct drm_map  *agp_tex;
+	unsigned int agp_size;
+	unsigned int agp_offset;
+
+	struct semaphore *drm_s3g_sem;
+
+	struct drm_via_chrome9_shadow_map  shadow_map;
+	struct drm_via_chrome9_pagetable_map pagetable_map;
+
+	char *bci;
+
+	int aperture_usage[NUMBER_OF_APERTURES];
+	void *event_tag_info;
+
+	/* DMA buffer manager */
+	void *dma_manager;
+	/* Indicate agp/pcie heap initialization flag */
+	int agp_initialized;
+	/* Indicate video heap initialization flag */
+	int vram_initialized;
+
+	unsigned long pcie_vmalloc_addr;
+
+	/* pointer to device information */
+	void *dev;
+	/* if agp init fail, go ahead and force dri use PCI*/
+	enum {
+		DRM_AGP_RING_BUFFER,
+		DRM_AGP_DOUBLE_BUFFER,
+		DRM_AGP_DISABLED
+	} drm_agp_type;
+	/*end*/
+
+	unsigned long *bci_buffer;
+	unsigned long pcie_vmalloc_nocache;
+};
+
+
+enum via_chrome9_family {
+	VIA_CHROME9_OTHER = 0,	/* Baseline */
+	VIA_CHROME9_PRO_GROUP_A,/* Another video engine and DMA commands */
+	VIA_CHROME9_DX9_0,
+	VIA_CHROME9_PCIE_GROUP
+};
+
+/* VIA_CHROME9 MMIO register access */
+#define VIA_CHROME9_BASE ((dev_priv->mmio))
+
+#define VIA_CHROME9_READ(reg)		DRM_READ32(VIA_CHROME9_BASE, reg)
+#define VIA_CHROME9_WRITE(reg, val)	DRM_WRITE32(VIA_CHROME9_BASE, reg, val)
+#define VIA_CHROME9_READ8(reg)		DRM_READ8(VIA_CHROME9_BASE, reg)
+#define VIA_CHROME9_WRITE8(reg, val)	DRM_WRITE8(VIA_CHROME9_BASE, reg, val)
+
+#endif
--- /dev/null
+++ b/drivers/char/drm/via_chrome9_mm.c
@@ -0,0 +1,388 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license,
+ * 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL VIA, S3 GRAPHICS, 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.
+ */
+
+#include "drmP.h"
+#include "via_chrome9_drm.h"
+#include "via_chrome9_drv.h"
+#include "drm_sman.h"
+#include "via_chrome9_mm.h"
+
+#define VIA_CHROME9_MM_GRANULARITY 4
+#define VIA_CHROME9_MM_GRANULARITY_MASK ((1 << VIA_CHROME9_MM_GRANULARITY) - 1)
+
+
+int via_chrome9_map_init(struct drm_device *dev,
+	struct drm_via_chrome9_init *init)
+{
+	struct drm_via_chrome9_private *dev_priv =
+		(struct drm_via_chrome9_private *)dev->dev_private;
+
+	dev_priv->sarea = drm_getsarea(dev);
+	if (!dev_priv->sarea) {
+		DRM_ERROR("could not find sarea!\n");
+		goto error;
+	}
+	dev_priv->sarea_priv =
+		(struct drm_via_chrome9_sarea *)((unsigned char *)dev_priv->
+		sarea->handle + init->sarea_priv_offset);
+
+	dev_priv->fb = drm_core_findmap(dev, init->fb_handle);
+	if (!dev_priv->fb) {
+		DRM_ERROR("could not find framebuffer!\n");
+		goto error;
+	}
+	/* Frame buffer physical base address */
+	dev_priv->fb_base_address = init->fb_base_address;
+
+	if (init->shadow_size) {
+		/* find apg shadow region mappings */
+	dev_priv->shadow_map.shadow = drm_core_findmap(dev, init->
+	shadow_handle);
+		if (!dev_priv->shadow_map.shadow) {
+			DRM_ERROR("could not shadow map!\n");
+			goto error;
+			}
+		dev_priv->shadow_map.shadow_size = init->shadow_size;
+		dev_priv->shadow_map.shadow_handle = (unsigned int *)dev_priv->
+			shadow_map.shadow->handle;
+		init->shadow_handle = dev_priv->shadow_map.shadow->offset;
+		}
+	if (init->agp_tex_size && init->chip_agp != CHIP_PCIE) {
+	/* find apg texture buffer mappings */
+	dev_priv->agp_tex = drm_core_findmap(dev, init->agp_tex_handle);
+	dev_priv->agp_size = init->agp_tex_size;
+	dev_priv->agp_offset = init->agp_tex_handle;
+	if (!dev_priv->agp_tex) {
+		DRM_ERROR("could not find agp texture map !\n");
+		goto error;
+		}
+	}
+	/* find mmio/dma mappings */
+	dev_priv->mmio = drm_core_findmap(dev, init->mmio_handle);
+	if (!dev_priv->mmio) {
+		DRM_ERROR("failed to find mmio region!\n");
+		goto error;
+		}
+
+	dev_priv->hostBlt = drm_core_findmap(dev, init->hostBlt_handle);
+	if (!dev_priv->hostBlt) {
+		DRM_ERROR("failed to find host bitblt region!\n");
+		goto error;
+		}
+
+	dev_priv->drm_agp_type = init->agp_type;
+	if (init->agp_type != AGP_DISABLED && init->chip_agp != CHIP_PCIE) {
+		dev->agp_buffer_map = drm_core_findmap(dev, init->dma_handle);
+		if (!dev->agp_buffer_map) {
+			DRM_ERROR("failed to find dma buffer region!\n");
+			goto error;
+			}
+		}
+
+	dev_priv->bci  = (char *)dev_priv->mmio->handle + 0x10000;
+
+	return 0;
+
+error:
+	/* do cleanup here, refine_later */
+	return (-EINVAL);
+}
+
+int via_chrome9_heap_management_init(struct drm_device *dev,
+	struct drm_via_chrome9_init *init)
+{
+	struct drm_via_chrome9_private *dev_priv =
+		(struct drm_via_chrome9_private *) dev->dev_private;
+	int ret = 0;
+
+	/* video memory management. range: 0 ---- video_whole_size */
+	mutex_lock(&dev->struct_mutex);
+	ret = drm_sman_set_range(&dev_priv->sman, VIA_CHROME9_MEM_VIDEO,
+		0, dev_priv->available_fb_size >> VIA_CHROME9_MM_GRANULARITY);
+	if (ret) {
+		DRM_ERROR("VRAM memory manager initialization ******ERROR\
+			!******\n");
+		mutex_unlock(&dev->struct_mutex);
+		goto error;
+	}
+	dev_priv->vram_initialized = 1;
+	/* agp/pcie heap management.
+	note:because agp is contradict with pcie, so only one is enough
+	for managing both of them.*/
+	init->agp_type = dev_priv->drm_agp_type;
+	if (init->agp_type != AGP_DISABLED && dev_priv->agp_size) {
+	ret = drm_sman_set_range(&dev_priv->sman, VIA_CHROME9_MEM_AGP,
+		0, dev_priv->agp_size >> VIA_CHROME9_MM_GRANULARITY);
+	if (ret) {
+		DRM_ERROR("AGP/PCIE memory manager initialization ******ERROR\
+			!******\n");
+		mutex_unlock(&dev->struct_mutex);
+		goto error;
+		}
+	dev_priv->agp_initialized = 1;
+	}
+	mutex_unlock(&dev->struct_mutex);
+	return 0;
+
+error:
+	/* Do error recover here, refine_later */
+	return -EINVAL;
+}
+
+
+void via_chrome9_memory_destroy_heap(struct drm_device *dev,
+	struct drm_via_chrome9_private *dev_priv)
+{
+	mutex_lock(&dev->struct_mutex);
+	drm_sman_cleanup(&dev_priv->sman);
+	dev_priv->vram_initialized = 0;
+	dev_priv->agp_initialized = 0;
+	mutex_unlock(&dev->struct_mutex);
+}
+
+void via_chrome9_reclaim_buffers_locked(struct drm_device *dev,
+				struct drm_file *file_priv)
+{
+	return;
+}
+
+int via_chrome9_ioctl_allocate_aperture(struct drm_device *dev,
+	void *data, struct drm_file *file_priv)
+{
+	return 0;
+}
+
+int via_chrome9_ioctl_free_aperture(struct drm_device *dev,
+	void *data, struct drm_file *file_priv)
+{
+	return 0;
+}
+
+
+/* Allocate memory from DRM module for video playing */
+int via_chrome9_ioctl_allocate_mem_base(struct drm_device *dev,
+void *data, struct drm_file *file_priv)
+{
+	struct drm_via_chrome9_mem *mem = data;
+	struct drm_memblock_item *item;
+	struct drm_via_chrome9_private *dev_priv =
+		(struct drm_via_chrome9_private *) dev->dev_private;
+	unsigned long tmpSize = 0, offset = 0, alignment = 0;
+	/* modify heap_type to agp for pcie, since we treat pcie/agp heap
+	no difference in heap management */
+	if (mem->type == memory_heap_pcie) {
+		if (dev_priv->chip_agp != CHIP_PCIE) {
+		DRM_ERROR(
+		"User want to alloc memory from pcie heap but via_chrome9.ko\
+			has no this heap exist.******ERROR******\n");
+		return -EINVAL;
+		}
+	mem->type = memory_heap_agp;
+	}
+
+	if (mem->type > VIA_CHROME9_MEM_AGP) {
+		DRM_ERROR("Unknown memory type allocation\n");
+		return -EINVAL;
+	}
+	mutex_lock(&dev->struct_mutex);
+	if (0 == ((mem->type == VIA_CHROME9_MEM_VIDEO) ?
+		dev_priv->vram_initialized : dev_priv->agp_initialized)) {
+		DRM_ERROR("Attempt to allocate from uninitialized\
+			memory manager.\n");
+		mutex_unlock(&dev->struct_mutex);
+		return -EINVAL;
+		}
+	tmpSize = (mem->size + VIA_CHROME9_MM_GRANULARITY_MASK) >>
+		VIA_CHROME9_MM_GRANULARITY;
+	mem->size = tmpSize << VIA_CHROME9_MM_GRANULARITY;
+	alignment = (dev_priv->alignment & 0x80000000) ? dev_priv->
+	alignment & 0x7FFFFFFF:0;
+	alignment /= (1 << VIA_CHROME9_MM_GRANULARITY);
+	item = drm_sman_alloc(&dev_priv->sman, mem->type, tmpSize, alignment,
+	(unsigned long)file_priv);
+	mutex_unlock(&dev->struct_mutex);
+	/* alloc failed */
+	if (!item) {
+		DRM_ERROR("Allocate memory failed ******ERROR******.\n");
+		return -ENOMEM;
+	}
+	/* Till here every thing is ok, we check the memory type allocated
+	and return appropriate value to user mode  Here the value return to
+	user is very difficult to operate. BE CAREFULLY!!! */
+	/* offset is used by user mode ap to calculate the virtual address
+	which is used to access the memory allocated */
+	mem->index = item->user_hash.key;
+	offset = item->mm->offset(item->mm, item->mm_info) <<
+	VIA_CHROME9_MM_GRANULARITY;
+	switch (mem->type) {
+	case VIA_CHROME9_MEM_VIDEO:
+		mem->offset = offset + dev_priv->back_offset;
+		break;
+	case VIA_CHROME9_MEM_AGP:
+	/* return different value to user according to the chip type */
+		if (dev_priv->chip_agp == CHIP_PCIE) {
+			mem->offset = offset +
+			((struct drm_via_chrome9_DMA_manager *)dev_priv->
+				dma_manager)->DMASize * sizeof(unsigned long);
+		} else {
+		mem->offset = offset;
+		}
+		break;
+	default:
+	/* Strange thing happen! Faint. Code bug! */
+		DRM_ERROR("Enter here is impossible ******\
+		ERROR******.\n");
+		return -EINVAL;
+	}
+	/*DONE. Need we call function copy_to_user ?NO. We can't even
+	touch user's space.But we are lucky, since kernel drm:drm_ioctl
+	will to the job for us.  */
+	return 0;
+}
+
+/* Allocate video/AGP/PCIE memory from heap management */
+int via_chrome9_ioctl_allocate_mem_wrapper(struct drm_device
+	*dev, void *data, struct drm_file *file_priv)
+{
+	struct drm_via_chrome9_memory_alloc *memory_alloc =
+		(struct drm_via_chrome9_memory_alloc *)data;
+	struct drm_via_chrome9_private *dev_priv =
+		(struct drm_via_chrome9_private *) dev->dev_private;
+	struct drm_via_chrome9_mem mem;
+
+	mem.size = memory_alloc->size;
+	mem.type = memory_alloc->heap_type;
+	dev_priv->alignment = memory_alloc->align | 0x80000000;
+	if (via_chrome9_ioctl_allocate_mem_base(dev, &mem, file_priv)) {
+		DRM_ERROR("Allocate memory error!.\n");
+		return -ENOMEM;
+		}
+	dev_priv->alignment = 0;
+	/* Till here every thing is ok, we check the memory type allocated and
+	return appropriate value to user mode Here the value return to user is
+	very difficult to operate. BE CAREFULLY!!!*/
+	/* offset is used by user mode ap to calculate the virtual address
+	which is used to access the memory allocated */
+	memory_alloc->offset = mem.offset;
+	memory_alloc->heap_info.lpL1Node = (void *)mem.index;
+	memory_alloc->size = mem.size;
+	switch (memory_alloc->heap_type) {
+	case VIA_CHROME9_MEM_VIDEO:
+		memory_alloc->physaddress = memory_alloc->offset +
+		dev_priv->fb_base_address;
+		memory_alloc->linearaddress = (void *)memory_alloc->physaddress;
+		break;
+	case VIA_CHROME9_MEM_AGP:
+		/* return different value to user according to the chip type */
+		if (dev_priv->chip_agp == CHIP_PCIE) {
+			memory_alloc->physaddress = memory_alloc->offset;
+			memory_alloc->linearaddress = (void *)memory_alloc->
+			physaddress;
+		} else {
+			memory_alloc->physaddress = dev->agp->base +
+			memory_alloc->offset +
+			((struct drm_via_chrome9_DMA_manager *)
+			dev_priv->dma_manager)->DMASize * sizeof(unsigned long);
+			memory_alloc->linearaddress =
+			(void *)memory_alloc->physaddress;
+		}
+		break;
+	default:
+		/* Strange thing happen! Faint. Code bug! */
+		DRM_ERROR("Enter here is impossible ******ERROR******.\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+int via_chrome9_ioctl_free_mem_wrapper(struct drm_device *dev,
+	void *data, struct drm_file *file_priv)
+{
+	struct drm_via_chrome9_memory_alloc *memory_alloc = data;
+	struct drm_via_chrome9_mem mem;
+
+	mem.index = (unsigned long)memory_alloc->heap_info.lpL1Node;
+	if (via_chrome9_ioctl_freemem_base(dev, &mem, file_priv)) {
+		DRM_ERROR("function free_mem_wrapper error.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int via_chrome9_ioctl_freemem_base(struct drm_device *dev,
+	void *data, struct drm_file *file_priv)
+{
+	struct drm_via_chrome9_private *dev_priv = dev->dev_private;
+	struct drm_via_chrome9_mem *mem = data;
+	int ret;
+
+	mutex_lock(&dev->struct_mutex);
+	ret = drm_sman_free_key(&dev_priv->sman, mem->index);
+	mutex_unlock(&dev->struct_mutex);
+	DRM_DEBUG("free = 0x%lx\n", mem->index);
+
+	return ret;
+}
+
+int via_chrome9_ioctl_check_vidmem_size(struct drm_device *dev,
+	void *data, struct drm_file *file_priv)
+{
+	return 0;
+}
+
+int via_chrome9_ioctl_pciemem_ctrl(struct drm_device *dev,
+	void *data, struct drm_file *file_priv)
+{
+	int result = 0;
+	struct drm_via_chrome9_private *dev_priv = dev->dev_private;
+	struct drm_via_chrome9_pciemem_ctrl *pcie_memory_ctrl = data;
+	switch (pcie_memory_ctrl->ctrl_type) {
+	case pciemem_copy_from_user:
+		result = copy_from_user((void *)(
+		dev_priv->pcie_vmalloc_nocache+
+		pcie_memory_ctrl->pcieoffset),
+		pcie_memory_ctrl->usermode_data,
+		pcie_memory_ctrl->size);
+		break;
+	case pciemem_copy_to_user:
+		result = copy_to_user(pcie_memory_ctrl->usermode_data,
+		(void *)(dev_priv->pcie_vmalloc_nocache+
+		pcie_memory_ctrl->pcieoffset),
+		pcie_memory_ctrl->size);
+		break;
+	case pciemem_memset:
+		memset((void *)(dev_priv->pcie_vmalloc_nocache +
+		pcie_memory_ctrl->pcieoffset),
+		pcie_memory_ctrl->memsetdata,
+		pcie_memory_ctrl->size);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
--- /dev/null
+++ b/drivers/char/drm/via_chrome9_mm.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license,
+ * 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL VIA, S3 GRAPHICS, 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.
+ */
+#ifndef _VIA_CHROME9_MM_H_
+#define _VIA_CHROME9_MM_H_
+struct drm_via_chrome9_pciemem_ctrl {
+	enum {
+		pciemem_copy_from_user = 0,
+		pciemem_copy_to_user,
+		pciemem_memset,
+		} ctrl_type;
+	unsigned int pcieoffset;
+	unsigned int size;/*in Byte*/
+	unsigned char memsetdata;/*for memset*/
+	void *usermode_data;/*user mode data pointer*/
+};
+
+extern int via_chrome9_map_init(struct drm_device *dev,
+	struct drm_via_chrome9_init *init);
+extern int via_chrome9_heap_management_init(struct drm_device
+	*dev, struct drm_via_chrome9_init *init);
+extern void via_chrome9_memory_destroy_heap(struct drm_device
+	*dev, struct drm_via_chrome9_private *dev_priv);
+extern int via_chrome9_ioctl_check_vidmem_size(struct drm_device
+	*dev, void *data, struct drm_file *file_priv);
+extern int via_chrome9_ioctl_pciemem_ctrl(struct drm_device *dev,
+	void *data, struct drm_file *file_priv);
+extern int via_chrome9_ioctl_allocate_aperture(struct drm_device
+	*dev, void *data, struct drm_file *file_priv);
+extern int via_chrome9_ioctl_free_aperture(struct drm_device *dev,
+	void *data, struct drm_file *file_priv);
+extern int via_chrome9_ioctl_allocate_mem_base(struct drm_device
+	*dev, void *data, struct drm_file *file_priv);
+extern int via_chrome9_ioctl_allocate_mem_wrapper(
+	struct drm_device *dev,	void *data, struct drm_file *file_priv);
+extern int via_chrome9_ioctl_freemem_base(struct drm_device
+	*dev, void *data, struct drm_file *file_priv);
+extern int via_chrome9_ioctl_free_mem_wrapper(struct drm_device
+	*dev, void *data, struct drm_file *file_priv);
+extern void via_chrome9_reclaim_buffers_locked(struct drm_device
+	*dev, struct drm_file *file_priv);
+
+#endif
+
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ