diff -Naur ./drivers/char/drm/drm_pciids.h ./drivers/char/drm/drm_pciids.h --- ./drivers/char/drm/drm_pciids.h 2008-04-17 10:49:44.000000000 +0800 +++ ./drivers/char/drm/drm_pciids.h 2008-06-05 04:46:09.000000000 +0800 @@ -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}, \ diff -Naur ./char/drm/Kconfig ./drivers/char/drm/Kconfig --- ./drivers/char/drm/Kconfig 2008-04-17 10:49:44.000000000 +0800 +++ ./drivers/char/drm/Kconfig 2008-06-05 04:38:05.000000000 +0800 @@ -98,6 +98,13 @@ help 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" diff -Naur ./drivers/char/drm/Makefile ./drivers/char/drm/Makefile --- ./drivers/char/drm/Makefile 2008-04-17 10:49:44.000000000 +0800 +++ ./drivers/char/drm/Makefile 2008-06-05 04:38:02.000000000 +0800 @@ -18,6 +18,7 @@ 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_SIS) += sis.o obj-$(CONFIG_DRM_SAVAGE)+= savage.o obj-$(CONFIG_DRM_VIA) +=via.o +obj-$(CONFIG_DRM_VIA_CHROME9) += via_chrome9.o diff -Naur ./drivers/char/drm/via_chrome9_3d_reg.h ./drivers/char/drm/via_chrome9_3d_reg.h --- ./drivers/char/drm/via_chrome9_3d_reg.h 1970-01-01 08:00:00.000000000 +0800 +++ ./drivers/char/drm/via_chrome9_3d_reg.h 2008-06-05 04:38:00.000000000 +0800 @@ -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 diff -Naur ./drivers/char/drm/via_chrome9_dma.c ./drivers/char/drm/via_chrome9_dma.c --- ./drivers/char/drm/via_chrome9_dma.c 1970-01-01 08:00:00.000000000 +0800 +++ ./drivers/char/drm/via_chrome9_dma.c 2008-06-05 04:38:00.000000000 +0800 @@ -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; +} diff -Naur ./drivers/char/drm/via_chrome9_dma.h ./drivers/char/drm/via_chrome9_dma.h --- ./drivers/char/drm/via_chrome9_dma.h 1970-01-01 08:00:00.000000000 +0800 +++ ./drivers/char/drm/via_chrome9_dma.h 2008-06-05 04:38:00.000000000 +0800 @@ -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 diff -Naur ./drivers/char/drm/via_chrome9_drm.c ./drivers/char/drm/via_chrome9_drm.c --- ./drivers/char/drm/via_chrome9_drm.c 1970-01-01 08:00:00.000000000 +0800 +++ ./drivers/char/drm/via_chrome9_drm.c 2008-06-05 04:38:00.000000000 +0800 @@ -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; +} + diff -Naur ./drivers/char/drm/via_chrome9_drm.h ./drivers/char/drm/via_chrome9_drm.h --- ./drivers/char/drm/via_chrome9_drm.h 1970-01-01 08:00:00.000000000 +0800 +++ ./drivers/char/drm/via_chrome9_drm.h 2008-06-05 04:38:00.000000000 +0800 @@ -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_ */ diff -Naur ./drivers/char/drm/via_chrome9_drv.c ./drivers/char/drm/via_chrome9_drv.c --- ./drivers/char/drm/via_chrome9_drv.c 1970-01-01 08:00:00.000000000 +0800 +++ ./drivers/char/drm/via_chrome9_drv.c 2008-06-05 04:38:00.000000000 +0800 @@ -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"); diff -Naur ./drivers/char/drm/via_chrome9_drv.h ./drivers/char/drm/via_chrome9_drv.h --- ./drivers/char/drm/via_chrome9_drv.h 1970-01-01 08:00:00.000000000 +0800 +++ ./drivers/char/drm/via_chrome9_drv.h 2008-06-05 04:38:00.000000000 +0800 @@ -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 diff -Naur ./drivers/char/drm/via_chrome9_mm.c ./drivers/char/drm/via_chrome9_mm.c --- ./drivers/char/drm/via_chrome9_mm.c 1970-01-01 08:00:00.000000000 +0800 +++ ./drivers/char/drm/via_chrome9_mm.c 2008-06-05 04:38:00.000000000 +0800 @@ -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; +} diff -Naur ./drivers/char/drm/via_chrome9_mm.h ./drivers/char/drm/via_chrome9_mm.h --- ./drivers/char/drm/via_chrome9_mm.h 1970-01-01 08:00:00.000000000 +0800 +++ ./drivers/char/drm/via_chrome9_mm.h 2008-06-05 04:38:00.000000000 +0800 @@ -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 +