summaryrefslogtreecommitdiffstats
path: root/src/s3v_accel.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/s3v_accel.c')
-rw-r--r--src/s3v_accel.c400
1 files changed, 400 insertions, 0 deletions
diff --git a/src/s3v_accel.c b/src/s3v_accel.c
new file mode 100644
index 0000000..ce5643e
--- /dev/null
+++ b/src/s3v_accel.c
@@ -0,0 +1,400 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/s3v_accel.c,v 1.25 2003/11/06 18:38:05 tsi Exp $ */
+
+/*
+Copyright (C) 1994-1999 The XFree86 Project, 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, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice 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, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT 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.
+
+Except as contained in this notice, the name of the XFree86 Project shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the XFree86 Project.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* fb includes are in s3v.h */
+#include "s3v.h"
+#include "miline.h"
+
+#include "servermd.h" /* LOG2_BYTES_PER_SCANLINE_PAD */
+
+static void S3VWriteMask(CARD32*, int);
+
+static void S3VNopAllCmdSets(ScrnInfoPtr pScrn);
+
+void VWaitFifoGX2(S3VPtr ps3v, int slots);
+void S3VWaitFifoMain(S3VPtr ps3v, int slots);
+void S3VWaitDummy(S3VPtr ps3v);
+void S3VEngineReset(ScrnInfoPtr pScrn);
+
+Bool S3VAccelInit(ScreenPtr pScreen);
+Bool S3VAccelInit32(ScreenPtr pScreen);
+
+Bool
+S3VAccelInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ switch(ps3v->Chipset)
+ {
+ case S3_ViRGE:
+ case S3_ViRGE_VX:
+ ps3v->AccelFlags = BLT_BUG;
+ break;
+ default:
+ ps3v->AccelFlags = 0;
+ break;
+ }
+
+ ps3v->AccelFlags |= MONO_TRANS_BUG; /* which aren't broken ? */
+
+ ps3v->EXAendfb = ps3v->videoRambytes -
+ 1024 - /* hw cursor */
+ 0x200000;
+
+ if (ps3v->useEXA)
+ return S3VEXAInit(pScreen);
+ else
+ return S3VXAAInit(pScreen);
+}
+
+Bool
+S3VAccelInit32(ScreenPtr pScreen)
+{
+ return FALSE;
+}
+
+void
+S3VNopAllCmdSets(ScrnInfoPtr pScrn)
+{
+ int i;
+ int max_it=1000;
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ if (xf86GetVerbosity() > 1) {
+ ErrorF("\tTrio3D -- S3VNopAllCmdSets: SubsysStats#1 = 0x%08lx\n",
+ (unsigned long)IN_SUBSYS_STAT());
+ }
+
+ mem_barrier();
+ for(i=0;i<max_it;i++) {
+ if( (IN_SUBSYS_STAT() & 0x3f802000 & 0x20002000) == 0x20002000) {
+ break;
+ }
+ }
+
+ if(i!=max_it) {
+ if (xf86GetVerbosity() > 1) ErrorF("\tTrio3D -- S3VNopAllCmdSets: state changed after %d iterations\n",i);
+ } else {
+ if (xf86GetVerbosity() > 1) ErrorF("\tTrio3D -- S3VNopAllCmdSets: state DIDN'T changed after %d iterations\n",max_it);
+ }
+
+ WaitQueue(5);
+
+ OUTREG(CMD_SET, CMD_NOP);
+
+ if (xf86GetVerbosity() > 1) {
+ ErrorF("\tTrio3D -- S3VNopAllCmdSets: SubsysStats#2 = 0x%08lx\n",
+ (unsigned long)IN_SUBSYS_STAT());
+ }
+}
+
+void
+S3VGEReset(ScrnInfoPtr pScrn, int from_timeout, int line, char *file)
+{
+ unsigned long gs1, gs2; /* -- debug info for graphics state -- */
+ unsigned char tmp, sr1, resetidx=0x66; /* FIXME */
+ int r;
+ int ge_was_on = 0;
+ CARD32 fifo_control = 0, miu_control = 0;
+ CARD32 streams_timeout = 0, misc_timeout = 0;
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ S3VPtr ps3v = S3VPTR(pScrn);
+ int vgaCRIndex, vgaCRReg, vgaIOBase;
+ vgaIOBase = hwp->IOBase;
+ vgaCRIndex = vgaIOBase + 4;
+ vgaCRReg = vgaIOBase + 5;
+
+
+ if (S3_TRIO_3D_SERIES(ps3v->Chipset)) {
+ VGAOUT8(0x3c4,0x01);
+ sr1 = VGAIN8(0x3c5);
+
+ if (sr1 & 0x20) {
+ if (xf86GetVerbosity() > 1)
+ ErrorF("\tTrio3D -- Display is on...turning off\n");
+ VGAOUT8(0x3c5,sr1 & ~0x20);
+ VerticalRetraceWait();
+ }
+ }
+
+ if (from_timeout) {
+ if (ps3v->GEResetCnt++ < 10 || xf86GetVerbosity() > 1)
+ ErrorF("\tS3VGEReset called from %s line %d\n",file,line);
+ }
+ else {
+ if (S3_TRIO_3D_SERIES(ps3v->Chipset))
+ S3VNopAllCmdSets(pScrn);
+ WaitIdleEmpty();
+ }
+
+
+ if (from_timeout && (ps3v->Chipset == S3_ViRGE || ps3v->Chipset == S3_ViRGE_VX || ps3v->Chipset == S3_ViRGE_DXGX)) {
+ /* reset will trash these registers, so save them */
+ fifo_control = INREG(FIFO_CONTROL_REG);
+ miu_control = INREG(MIU_CONTROL_REG);
+ streams_timeout = INREG(STREAMS_TIMEOUT_REG);
+ misc_timeout = INREG(MISC_TIMEOUT_REG);
+ }
+
+ if(ps3v->Chipset == S3_ViRGE_VX){
+ VGAOUT8(vgaCRIndex, 0x63);
+ }
+ else {
+ VGAOUT8(vgaCRIndex, 0x66);
+ }
+ if (!S3_TRIO_3D_SERIES(ps3v->Chipset)) {
+ tmp = VGAIN8(vgaCRReg);
+
+ usleep(10000);
+ for (r=1; r<10; r++) { /* try multiple times to avoid lockup of ViRGE/MX */
+ VGAOUT8(vgaCRReg, tmp | 0x02);
+ usleep(10000);
+ VGAOUT8(vgaCRReg, tmp & ~0x02);
+ usleep(10000);
+
+ xf86ErrorFVerb(VERBLEV, " S3VGEReset sub_stat=%lx \n",
+ (unsigned long)IN_SUBSYS_STAT()
+ );
+
+ if (!from_timeout)
+ WaitIdleEmpty();
+
+ OUTREG(DEST_SRC_STR, ps3v->Bpl << 16 | ps3v->Bpl);
+
+ usleep(10000);
+ if (((IN_SUBSYS_STAT() & 0x3f00) != 0x3000))
+ xf86ErrorFVerb(VERBLEV, "restarting S3 graphics engine reset %2d ...\n",r);
+ else
+ break;
+ }
+ } else {
+ usleep(10000);
+
+ for (r=1; r<10; r++) {
+ VerticalRetraceWait();
+ VGAOUT8(vgaCRIndex,resetidx);
+ tmp = VGAIN8(vgaCRReg);
+
+ VGAOUT8(0x3c4,0x01);
+ sr1 = VGAIN8(0x3c5);
+
+ if(sr1 & 0x20) {
+ if(xf86GetVerbosity() > 1) {
+ ErrorF("\tTrio3D -- Upps Display is on again ...turning off\n");
+ }
+ VGAOUT8(0x3c4,0x01);
+ VerticalRetraceWait();
+ VGAOUT8(0x3c5,sr1 & ~0x20);
+ }
+
+ VerticalRetraceWait();
+ gs1 = (long) IN_SUBSYS_STAT();
+
+ /* turn off the GE */
+
+ VGAOUT8(vgaCRIndex,resetidx);
+ if(tmp & 0x01) {
+ /* tmp &= ~0x01; */
+ VGAOUT8(vgaCRReg, tmp);
+ ge_was_on = 1;
+ usleep(10000);
+ }
+
+ gs2 = (long) IN_SUBSYS_STAT();
+ VGAOUT8(vgaCRReg, (tmp | 0x02));
+ usleep(10000);
+
+ VerticalRetraceWait();
+ VGAOUT8(vgaCRIndex,resetidx);
+ VGAOUT8(vgaCRReg, (tmp & ~0x02));
+ usleep(10000);
+
+ if(ge_was_on) {
+ tmp |= 0x01;
+ VGAOUT8(vgaCRReg, tmp);
+ usleep(10000);
+ }
+
+ if (xf86GetVerbosity() > 2) {
+ ErrorF("\tTrio3D -- GE was %s ST#1: 0x%08lx ST#2: 0x%08lx\n",
+ (ge_was_on) ? "on" : "off", gs1, gs2);
+ }
+
+ VerticalRetraceWait();
+
+ if (!from_timeout) {
+ S3VNopAllCmdSets(pScrn);
+ WaitIdleEmpty();
+ }
+
+ OUTREG(DEST_SRC_STR, ps3v->Bpl << 16 | ps3v->Bpl);
+ usleep(10000);
+
+ if((IN_SUBSYS_STAT() & 0x3f802000 & 0x20002000) != 0x20002000) {
+ if(xf86GetVerbosity() > 1)
+ ErrorF("restarting S3 graphics engine reset %2d ...%lx\n",
+ r, (unsigned long)IN_SUBSYS_STAT());
+ }
+ else
+ break;
+ }
+ }
+
+ if (from_timeout && (ps3v->Chipset == S3_ViRGE || ps3v->Chipset == S3_ViRGE_VX
+ || ps3v->Chipset == S3_ViRGE_DXGX)) {
+ /* restore trashed registers */
+ OUTREG(FIFO_CONTROL_REG, fifo_control);
+ OUTREG(MIU_CONTROL_REG, miu_control);
+ OUTREG(STREAMS_TIMEOUT_REG, streams_timeout);
+ OUTREG(MISC_TIMEOUT_REG, misc_timeout);
+ }
+
+ WAITFIFO(2);
+/* SETB_SRC_BASE(0); */
+/* SETB_DEST_BASE(0); */
+ OUTREG(SRC_BASE, 0);
+ OUTREG(DEST_BASE, 0);
+
+ WAITFIFO(4);
+ OUTREG(CLIP_L_R, ((0) << 16) | ps3v->Width);
+ OUTREG(CLIP_T_B, ((0) << 16) | ps3v->ScissB);
+ OUTREG(MONO_PAT_0, ~0);
+ OUTREG(MONO_PAT_1, ~0);
+
+ if (!from_timeout && S3_TRIO_3D_SERIES(ps3v->Chipset))
+ S3VNopAllCmdSets(pScrn);
+}
+
+void
+S3VEngineReset(ScrnInfoPtr pScrn)
+{
+ S3VPtr ps3v = S3VPTR(pScrn);
+
+ ps3v->SrcBaseY = 0;
+ ps3v->DestBaseY = 0;
+ ps3v->Stride = pScrn->displayWidth * pScrn->bitsPerPixel >> 3;
+
+ switch(pScrn->bitsPerPixel) {
+ case 8: ps3v->CommonCmd = DRAW | DST_8BPP;
+ ps3v->FullPlaneMask = 0x000000ff;
+ ps3v->bltbug_width1 = 51;
+ ps3v->bltbug_width2 = 64;
+ break;
+ case 16: ps3v->CommonCmd = DRAW | DST_16BPP;
+ ps3v->FullPlaneMask = 0x0000ffff;
+ ps3v->bltbug_width1 = 26;
+ ps3v->bltbug_width2 = 32;
+ break;
+ case 24: ps3v->CommonCmd = DRAW | DST_24BPP;
+ ps3v->FullPlaneMask = 0x00ffffff;
+ ps3v->bltbug_width1 = 16;
+ ps3v->bltbug_width2 = 22;
+ break;
+ }
+
+
+ WAITFIFO(5);
+ OUTREG(SRC_BASE, 0);
+ OUTREG(DEST_BASE, 0);
+ OUTREG(DEST_SRC_STR, ps3v->Stride | (ps3v->Stride << 16));
+
+ OUTREG(CLIP_L_R, ((0) << 16) | ps3v->Width);
+ OUTREG(CLIP_T_B, ((0) << 16) | ps3v->ScissB);
+}
+
+
+static void
+S3VWriteMask(
+ CARD32 *dstBase,
+ int dwords
+){
+ /* on alphas, be sure to call this with MapBaseDense, not MapBase! */
+ int numLeft;
+ CARD32 *dst = dstBase;
+
+ while(dwords >= 8192) {
+ numLeft = 8192;
+ while(numLeft) {
+ dst[0] = ~0; dst[1] = ~0;
+ dst[2] = ~0; dst[3] = ~0;
+ dst += 4;
+ numLeft -= 4;
+ }
+ dwords -= 8192;
+ dst = dstBase;
+ }
+ while(dwords >= 4) {
+ dst[0] = ~0; dst[1] = ~0;
+ dst[2] = ~0; dst[3] = ~0;
+ dst += 4;
+ dwords -= 4;
+ }
+ if(!dwords) return;
+ dst[0] = ~0;
+ if(dwords == 1) return;
+ dst[1] = ~0;
+ if(dwords == 2) return;
+ dst[2] = ~0;
+
+ return;
+}
+
+void
+S3VWaitFifoGX2(S3VPtr ps3v, int slots )
+{
+ if(ps3v->NoPCIRetry)
+ while(((INREG(SUBSYS_STAT_REG) >> 9) & 0x60) < slots){}
+}
+
+void
+S3VWaitFifoMain(S3VPtr ps3v, int slots )
+{
+ if(ps3v->NoPCIRetry)
+ while(((INREG(SUBSYS_STAT_REG) >> 8) & 0x1f) < slots){}
+}
+
+
+void
+S3VWaitCmdGX2(S3VPtr ps3v)
+{
+ while(((INREG(ADV_FUNC_CNTR) >> 6) & 0x1f) != 16){}
+}
+
+
+void
+S3VWaitDummy(S3VPtr ps3v)
+{
+ /* do nothing */
+}
+
+/*EOF*/
+