s3v_accel.c revision 1d54945d
11d54945dSmrg/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/s3v_accel.c,v 1.25 2003/11/06 18:38:05 tsi Exp $ */
21d54945dSmrg
31d54945dSmrg/*
41d54945dSmrgCopyright (C) 1994-1999 The XFree86 Project, Inc.  All Rights Reserved.
51d54945dSmrg
61d54945dSmrgPermission is hereby granted, free of charge, to any person obtaining a copy of
71d54945dSmrgthis software and associated documentation files (the "Software"), to deal in
81d54945dSmrgthe Software without restriction, including without limitation the rights to
91d54945dSmrguse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
101d54945dSmrgof the Software, and to permit persons to whom the Software is furnished to do
111d54945dSmrgso, subject to the following conditions:
121d54945dSmrg
131d54945dSmrgThe above copyright notice and this permission notice shall be included in all
141d54945dSmrgcopies or substantial portions of the Software.
151d54945dSmrg
161d54945dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
171d54945dSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
181d54945dSmrgNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
191d54945dSmrgXFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
201d54945dSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
211d54945dSmrgWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
221d54945dSmrg
231d54945dSmrgExcept as contained in this notice, the name of the XFree86 Project shall not
241d54945dSmrgbe used in advertising or otherwise to promote the sale, use or other dealings
251d54945dSmrgin this Software without prior written authorization from the XFree86 Project.
261d54945dSmrg*/
271d54945dSmrg
281d54945dSmrg#ifdef HAVE_CONFIG_H
291d54945dSmrg#include "config.h"
301d54945dSmrg#endif
311d54945dSmrg
321d54945dSmrg#include "s3v.h"
331d54945dSmrg
341d54945dSmrg#include "miline.h"
351d54945dSmrg	/* fb includes are in s3v.h */
361d54945dSmrg#include "xaalocal.h"
371d54945dSmrg#include "xaarop.h"
381d54945dSmrg
391d54945dSmrg#include "servermd.h" /* LOG2_BYTES_PER_SCANLINE_PAD */
401d54945dSmrg
411d54945dSmrgstatic void S3VWriteMask(CARD32*, int);
421d54945dSmrg
431d54945dSmrgstatic void S3VEngineReset(ScrnInfoPtr pScrn);
441d54945dSmrg/* s3v.h - static void S3VAccelSync(ScrnInfoPtr); */
451d54945dSmrgstatic void S3VSetupForSolidFill(ScrnInfoPtr, int, int, unsigned);
461d54945dSmrgstatic void S3VSubsequentSolidFillRect(ScrnInfoPtr, int, int, int, int);
471d54945dSmrgstatic void S3VSubsequentSolidFillRectPlaneMask(ScrnInfoPtr, int, int,
481d54945dSmrg				int, int);
491d54945dSmrgstatic void S3VSetupForMono8x8PatternFill(ScrnInfoPtr,int, int, int, int,
501d54945dSmrg                                int, unsigned int);
511d54945dSmrgstatic void S3VSubsequentMono8x8PatternFillRect(ScrnInfoPtr,int, int,
521d54945dSmrg                                int, int, int, int);
531d54945dSmrgstatic void S3VSubsequentMono8x8PatternFillRectPlaneMask(ScrnInfoPtr,int, int,
541d54945dSmrg                                int, int, int, int);
551d54945dSmrgstatic void S3VSetupForScreenToScreenCopy(ScrnInfoPtr, int, int, int,
561d54945dSmrg				unsigned int, int);
571d54945dSmrgstatic void S3VSubsequentScreenToScreenCopy(ScrnInfoPtr, int, int, int, int,
581d54945dSmrg				int, int);
591d54945dSmrgstatic void S3VSetupForCPUToScreenColorExpand(ScrnInfoPtr, int, int, int,
601d54945dSmrg				unsigned int);
611d54945dSmrgstatic void S3VSubsequentCPUToScreenColorExpand(ScrnInfoPtr, int, int, int,
621d54945dSmrg				int, int);
631d54945dSmrgstatic void S3VSetupForImageWrite(ScrnInfoPtr, int, unsigned int, int,
641d54945dSmrg				int, int);
651d54945dSmrgstatic void S3VSubsequentImageWriteRect(ScrnInfoPtr, int, int, int, int, int);
661d54945dSmrgstatic void S3VSubsequentSolidHorVertLine(ScrnInfoPtr, int, int, int, int);
671d54945dSmrgstatic void S3VSubsequentSolidHorVertLinePlaneMask(ScrnInfoPtr, int, int,
681d54945dSmrg				int, int);
691d54945dSmrg#if 0
701d54945dSmrgstatic void S3VSubsequentSolidBresenhamLine(ScrnInfoPtr, int, int, int,
711d54945dSmrg				int, int, int, int);
721d54945dSmrgstatic void S3VPolylinesThinSolidWrapper(DrawablePtr, GCPtr, int, int,
731d54945dSmrg				DDXPointPtr);
741d54945dSmrgstatic void S3VPolySegmentThinSolidWrapper(DrawablePtr, GCPtr, int, xSegment*);
751d54945dSmrg#endif
761d54945dSmrgstatic void S3VNopAllCmdSets(ScrnInfoPtr pScrn);
771d54945dSmrg
781d54945dSmrg
791d54945dSmrgBool
801d54945dSmrgS3VAccelInit(ScreenPtr pScreen)
811d54945dSmrg{
821d54945dSmrg    XAAInfoRecPtr infoPtr;
831d54945dSmrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
841d54945dSmrg    S3VPtr ps3v = S3VPTR(pScrn);
851d54945dSmrg    BoxRec AvailFBArea;
861d54945dSmrg
871d54945dSmrg    ps3v->AccelInfoRec = infoPtr = XAACreateInfoRec();
881d54945dSmrg    if(!infoPtr) return FALSE;
891d54945dSmrg
901d54945dSmrg    switch(ps3v->Chipset)
911d54945dSmrg      {
921d54945dSmrg      case S3_ViRGE:
931d54945dSmrg      case S3_ViRGE_VX:
941d54945dSmrg	ps3v->AccelFlags = BLT_BUG;
951d54945dSmrg	break;
961d54945dSmrg      default:
971d54945dSmrg	ps3v->AccelFlags = 0;
981d54945dSmrg	break;
991d54945dSmrg      }
1001d54945dSmrg
1011d54945dSmrg    ps3v->AccelFlags |= MONO_TRANS_BUG; /* which aren't broken ? */
1021d54945dSmrg
1031d54945dSmrg
1041d54945dSmrg    infoPtr->Flags = PIXMAP_CACHE |
1051d54945dSmrg		     LINEAR_FRAMEBUFFER |
1061d54945dSmrg		     OFFSCREEN_PIXMAPS;
1071d54945dSmrg
1081d54945dSmrg    infoPtr->Sync = S3VAccelSync;
1091d54945dSmrg
1101d54945dSmrg    /* Problem reports with solid fill on trio3d */
1111d54945dSmrg    if(!S3_TRIO_3D_SERIES(ps3v->Chipset))
1121d54945dSmrg      {
1131d54945dSmrg	/* Solid filled rects */
1141d54945dSmrg	infoPtr->SetupForSolidFill =
1151d54945dSmrg	  S3VSetupForSolidFill;
1161d54945dSmrg	infoPtr->SubsequentSolidFillRect =
1171d54945dSmrg	  S3VSubsequentSolidFillRect;
1181d54945dSmrg      }
1191d54945dSmrg
1201d54945dSmrg    /* Screen to screen copies */
1211d54945dSmrg    infoPtr->SetupForScreenToScreenCopy =
1221d54945dSmrg        S3VSetupForScreenToScreenCopy;
1231d54945dSmrg    infoPtr->SubsequentScreenToScreenCopy =
1241d54945dSmrg        S3VSubsequentScreenToScreenCopy;
1251d54945dSmrg    infoPtr->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
1261d54945dSmrg
1271d54945dSmrg    /* Mono 8x8 patterns */
1281d54945dSmrg    infoPtr->SetupForMono8x8PatternFill =
1291d54945dSmrg        S3VSetupForMono8x8PatternFill;
1301d54945dSmrg    infoPtr->SubsequentMono8x8PatternFillRect =
1311d54945dSmrg        S3VSubsequentMono8x8PatternFillRect;
1321d54945dSmrg    infoPtr->Mono8x8PatternFillFlags = NO_TRANSPARENCY |
1331d54945dSmrg				HARDWARE_PATTERN_PROGRAMMED_BITS |
1341d54945dSmrg				HARDWARE_PATTERN_SCREEN_ORIGIN |
1351d54945dSmrg				BIT_ORDER_IN_BYTE_MSBFIRST;
1361d54945dSmrg
1371d54945dSmrg
1381d54945dSmrg#ifndef __alpha__
1391d54945dSmrg
1401d54945dSmrg    /* disable color expand on GX2 until we trace down */
1411d54945dSmrg    /* lockups.  locate 'html'  in an xterm is a good  */
1421d54945dSmrg    /* test case for an AGP GX2. */
1431d54945dSmrg    if (!S3_ViRGE_GX2_SERIES(ps3v->Chipset))
1441d54945dSmrg      {
1451d54945dSmrg
1461d54945dSmrg
1471d54945dSmrg	/* CPU to screen color expansion */
1481d54945dSmrg	infoPtr->CPUToScreenColorExpandFillFlags =  ROP_NEEDS_SOURCE |
1491d54945dSmrg					CPU_TRANSFER_PAD_DWORD |
1501d54945dSmrg                                        SCANLINE_PAD_DWORD |
1511d54945dSmrg                                        BIT_ORDER_IN_BYTE_MSBFIRST |
1521d54945dSmrg                                  	LEFT_EDGE_CLIPPING;
1531d54945dSmrg
1541d54945dSmrg	if(ps3v->AccelFlags & MONO_TRANS_BUG)
1551d54945dSmrg	  infoPtr->CPUToScreenColorExpandFillFlags |=  NO_TRANSPARENCY;
1561d54945dSmrg
1571d54945dSmrg	infoPtr->ColorExpandRange = 0x8000;
1581d54945dSmrg	infoPtr->ColorExpandBase = ps3v->MapBaseDense;
1591d54945dSmrg	infoPtr->SetupForCPUToScreenColorExpandFill =
1601d54945dSmrg                S3VSetupForCPUToScreenColorExpand;
1611d54945dSmrg	infoPtr->SubsequentCPUToScreenColorExpandFill =
1621d54945dSmrg                S3VSubsequentCPUToScreenColorExpand;
1631d54945dSmrg
1641d54945dSmrg      } /* if(!GX2...) */
1651d54945dSmrg
1661d54945dSmrg
1671d54945dSmrg    /* Image Writes */
1681d54945dSmrg    infoPtr->ImageWriteFlags =  	ROP_NEEDS_SOURCE |
1691d54945dSmrg					NO_TRANSPARENCY |
1701d54945dSmrg					CPU_TRANSFER_PAD_DWORD |
1711d54945dSmrg					SCANLINE_PAD_DWORD |
1721d54945dSmrg					NO_GXCOPY |  /* added - kjb */
1731d54945dSmrg					LEFT_EDGE_CLIPPING;
1741d54945dSmrg
1751d54945dSmrg    infoPtr->ImageWriteRange = 0x8000;
1761d54945dSmrg    infoPtr->ImageWriteBase = ps3v->MapBaseDense;
1771d54945dSmrg    infoPtr->SetupForImageWrite = S3VSetupForImageWrite;
1781d54945dSmrg    infoPtr->SubsequentImageWriteRect = S3VSubsequentImageWriteRect;
1791d54945dSmrg
1801d54945dSmrg    /* on alpha, I see corruption in the xscreensaver program "hypercube"
1811d54945dSmrg       as the line acceleration is just stubs, it loses us nothing to
1821d54945dSmrg       disable it on alphas */
1831d54945dSmrg
1841d54945dSmrg    /* Lines */
1851d54945dSmrg#if 0
1861d54945dSmrg    /* Bresenham lines are broken when passed through fb to xaa
1871d54945dSmrg       so I pulled all the line functions.  This shouldn't hurt us
1881d54945dSmrg       a whole lot, since the Subsequent..Bresen stuff doesn't have
1891d54945dSmrg       any hardware accel yet anyway...  And xaa will do horiz/vert
1901d54945dSmrg       lines with the rect fill (like we are doing here) anyway.
1911d54945dSmrg       KJB 9/11/00
1921d54945dSmrg    */
1931d54945dSmrg    infoPtr->SetupForSolidLine = S3VSetupForSolidFill;
1941d54945dSmrg    infoPtr->SubsequentSolidHorVertLine = S3VSubsequentSolidHorVertLine;
1951d54945dSmrg    infoPtr->SubsequentSolidBresenhamLine = S3VSubsequentSolidBresenhamLine;
1961d54945dSmrg    infoPtr->PolySegmentThinSolid = S3VPolySegmentThinSolidWrapper;
1971d54945dSmrg    infoPtr->PolylinesThinSolid = S3VPolylinesThinSolidWrapper;
1981d54945dSmrg#endif
1991d54945dSmrg
2001d54945dSmrg#endif /* !__alpha__ */
2011d54945dSmrg
2021d54945dSmrg    /* And these are screen parameters used to setup the GE */
2031d54945dSmrg
2041d54945dSmrg     ps3v->Width = pScrn->displayWidth;
2051d54945dSmrg     					/* Bytes per pixel */
2061d54945dSmrg     ps3v->Bpp = pScrn->bitsPerPixel / 8;
2071d54945dSmrg     					/* Bytes per line */
2081d54945dSmrg     ps3v->Bpl = ps3v->Width * ps3v->Bpp;
2091d54945dSmrg     					/* ScissB is max height, minus 1k */
2101d54945dSmrg					/* for hwcursor?, then limited by */
2111d54945dSmrg					/* ViRGE max height register of   */
2121d54945dSmrg					/* 2047 */
2131d54945dSmrg     ps3v->ScissB = (pScrn->videoRam * 1024 - 1024) / ps3v->Bpl;
2141d54945dSmrg     if (ps3v->ScissB > 2047)
2151d54945dSmrg         ps3v->ScissB = 2047;
2161d54945dSmrg
2171d54945dSmrg
2181d54945dSmrg    S3VEngineReset(pScrn);
2191d54945dSmrg
2201d54945dSmrg
2211d54945dSmrg    AvailFBArea.x1 = 0;
2221d54945dSmrg    AvailFBArea.y1 = 0;
2231d54945dSmrg    AvailFBArea.x2 = pScrn->displayWidth;
2241d54945dSmrg    AvailFBArea.y2 = (pScrn->videoRam * 1024 - 1024) /
2251d54945dSmrg		     (pScrn->displayWidth * pScrn->bitsPerPixel / 8);
2261d54945dSmrg
2271d54945dSmrg    xf86InitFBManager(pScreen, &AvailFBArea);
2281d54945dSmrg
2291d54945dSmrg    /* make sure offscreen pixmaps aren't bigger than our address space */
2301d54945dSmrg    infoPtr->maxOffPixWidth  = 2048;
2311d54945dSmrg    infoPtr->maxOffPixHeight = 2048;
2321d54945dSmrg
2331d54945dSmrg    return (XAAInit(pScreen, infoPtr));
2341d54945dSmrg}
2351d54945dSmrg
2361d54945dSmrg
2371d54945dSmrgBool
2381d54945dSmrgS3VAccelInit32(ScreenPtr pScreen)
2391d54945dSmrg{
2401d54945dSmrg   return FALSE;
2411d54945dSmrg}
2421d54945dSmrg
2431d54945dSmrgvoid
2441d54945dSmrgS3VNopAllCmdSets(ScrnInfoPtr pScrn)
2451d54945dSmrg{
2461d54945dSmrg  int i;
2471d54945dSmrg  int max_it=1000;
2481d54945dSmrg  S3VPtr ps3v = S3VPTR(pScrn);
2491d54945dSmrg
2501d54945dSmrg  if (xf86GetVerbosity() > 1) {
2511d54945dSmrg     ErrorF("\tTrio3D -- S3VNopAllCmdSets: SubsysStats#1 = 0x%08lx\n",
2521d54945dSmrg        (unsigned long)IN_SUBSYS_STAT());
2531d54945dSmrg  }
2541d54945dSmrg
2551d54945dSmrg  mem_barrier();
2561d54945dSmrg  for(i=0;i<max_it;i++) {
2571d54945dSmrg    if( (IN_SUBSYS_STAT() & 0x3f802000 & 0x20002000) == 0x20002000) {
2581d54945dSmrg      break;
2591d54945dSmrg    }
2601d54945dSmrg  }
2611d54945dSmrg
2621d54945dSmrg  if(i!=max_it) {
2631d54945dSmrg    if (xf86GetVerbosity() > 1) ErrorF("\tTrio3D -- S3VNopAllCmdSets: state changed after %d iterations\n",i);
2641d54945dSmrg  } else {
2651d54945dSmrg    if (xf86GetVerbosity() > 1) ErrorF("\tTrio3D -- S3VNopAllCmdSets: state DIDN'T changed after %d iterations\n",max_it);
2661d54945dSmrg  }
2671d54945dSmrg
2681d54945dSmrg  WaitQueue(5);
2691d54945dSmrg
2701d54945dSmrg  OUTREG(CMD_SET, CMD_NOP);
2711d54945dSmrg
2721d54945dSmrg  if (xf86GetVerbosity() > 1) {
2731d54945dSmrg     ErrorF("\tTrio3D -- S3VNopAllCmdSets: SubsysStats#2 = 0x%08lx\n",
2741d54945dSmrg        (unsigned long)IN_SUBSYS_STAT());
2751d54945dSmrg  }
2761d54945dSmrg}
2771d54945dSmrg
2781d54945dSmrgvoid
2791d54945dSmrgS3VGEReset(ScrnInfoPtr pScrn, int from_timeout, int line, char *file)
2801d54945dSmrg{
2811d54945dSmrg    unsigned long gs1, gs2;   /* -- debug info for graphics state -- */
2821d54945dSmrg    unsigned char tmp, sr1, resetidx=0x66;  /* FIXME */
2831d54945dSmrg    int r;
2841d54945dSmrg    int ge_was_on = 0;
2851d54945dSmrg    CARD32 fifo_control = 0, miu_control = 0;
2861d54945dSmrg    CARD32 streams_timeout = 0, misc_timeout = 0;
2871d54945dSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
2881d54945dSmrg	S3VPtr ps3v = S3VPTR(pScrn);
2891d54945dSmrg  	int vgaCRIndex, vgaCRReg, vgaIOBase;
2901d54945dSmrg  	vgaIOBase = hwp->IOBase;
2911d54945dSmrg  	vgaCRIndex = vgaIOBase + 4;
2921d54945dSmrg  	vgaCRReg = vgaIOBase + 5;
2931d54945dSmrg
2941d54945dSmrg
2951d54945dSmrg    if (S3_TRIO_3D_SERIES(ps3v->Chipset)) {
2961d54945dSmrg      VGAOUT8(0x3c4,0x01);
2971d54945dSmrg      sr1 = VGAIN8(0x3c5);
2981d54945dSmrg
2991d54945dSmrg      if (sr1 & 0x20) {
3001d54945dSmrg        if (xf86GetVerbosity() > 1)
3011d54945dSmrg          ErrorF("\tTrio3D -- Display is on...turning off\n");
3021d54945dSmrg        VGAOUT8(0x3c5,sr1 & ~0x20);
3031d54945dSmrg        VerticalRetraceWait();
3041d54945dSmrg      }
3051d54945dSmrg    }
3061d54945dSmrg
3071d54945dSmrg    if (from_timeout) {
3081d54945dSmrg      if (ps3v->GEResetCnt++ < 10 || xf86GetVerbosity() > 1)
3091d54945dSmrg	ErrorF("\tS3VGEReset called from %s line %d\n",file,line);
3101d54945dSmrg    }
3111d54945dSmrg    else {
3121d54945dSmrg      if (S3_TRIO_3D_SERIES(ps3v->Chipset))
3131d54945dSmrg        S3VNopAllCmdSets(pScrn);
3141d54945dSmrg      WaitIdleEmpty();
3151d54945dSmrg    }
3161d54945dSmrg
3171d54945dSmrg
3181d54945dSmrg    if (from_timeout && (ps3v->Chipset == S3_ViRGE || ps3v->Chipset == S3_ViRGE_VX || ps3v->Chipset == S3_ViRGE_DXGX)) {
3191d54945dSmrg      /* reset will trash these registers, so save them */
3201d54945dSmrg      fifo_control    = INREG(FIFO_CONTROL_REG);
3211d54945dSmrg      miu_control     = INREG(MIU_CONTROL_REG);
3221d54945dSmrg      streams_timeout = INREG(STREAMS_TIMEOUT_REG);
3231d54945dSmrg      misc_timeout    = INREG(MISC_TIMEOUT_REG);
3241d54945dSmrg    }
3251d54945dSmrg
3261d54945dSmrg    if(ps3v->Chipset == S3_ViRGE_VX){
3271d54945dSmrg        VGAOUT8(vgaCRIndex, 0x63);
3281d54945dSmrg        }
3291d54945dSmrg    else {
3301d54945dSmrg        VGAOUT8(vgaCRIndex, 0x66);
3311d54945dSmrg        }
3321d54945dSmrg  if (!S3_TRIO_3D_SERIES(ps3v->Chipset)) {
3331d54945dSmrg    tmp = VGAIN8(vgaCRReg);
3341d54945dSmrg
3351d54945dSmrg    usleep(10000);
3361d54945dSmrg    for (r=1; r<10; r++) {  /* try multiple times to avoid lockup of ViRGE/MX */
3371d54945dSmrg      VGAOUT8(vgaCRReg, tmp | 0x02);
3381d54945dSmrg      usleep(10000);
3391d54945dSmrg      VGAOUT8(vgaCRReg, tmp & ~0x02);
3401d54945dSmrg      usleep(10000);
3411d54945dSmrg
3421d54945dSmrg      xf86ErrorFVerb(VERBLEV, "	S3VGEReset sub_stat=%lx \n",
3431d54945dSmrg   	(unsigned long)IN_SUBSYS_STAT()
3441d54945dSmrg	);
3451d54945dSmrg
3461d54945dSmrg      if (!from_timeout)
3471d54945dSmrg        WaitIdleEmpty();
3481d54945dSmrg
3491d54945dSmrg      OUTREG(DEST_SRC_STR, ps3v->Bpl << 16 | ps3v->Bpl);
3501d54945dSmrg
3511d54945dSmrg      usleep(10000);
3521d54945dSmrg      if (((IN_SUBSYS_STAT() & 0x3f00) != 0x3000))
3531d54945dSmrg	xf86ErrorFVerb(VERBLEV, "restarting S3 graphics engine reset %2d ...\n",r);
3541d54945dSmrg      else
3551d54945dSmrg	break;
3561d54945dSmrg    }
3571d54945dSmrg    } else {
3581d54945dSmrg    usleep(10000);
3591d54945dSmrg
3601d54945dSmrg    for (r=1; r<10; r++) {
3611d54945dSmrg      VerticalRetraceWait();
3621d54945dSmrg      VGAOUT8(vgaCRIndex,resetidx);
3631d54945dSmrg      tmp = VGAIN8(vgaCRReg);
3641d54945dSmrg
3651d54945dSmrg      VGAOUT8(0x3c4,0x01);
3661d54945dSmrg      sr1 = VGAIN8(0x3c5);
3671d54945dSmrg
3681d54945dSmrg      if(sr1 & 0x20) {
3691d54945dSmrg        if(xf86GetVerbosity() > 1) {
3701d54945dSmrg          ErrorF("\tTrio3D -- Upps Display is on again ...turning off\n");
3711d54945dSmrg        }
3721d54945dSmrg        VGAOUT8(0x3c4,0x01);
3731d54945dSmrg        VerticalRetraceWait();
3741d54945dSmrg        VGAOUT8(0x3c5,sr1 & ~0x20);
3751d54945dSmrg      }
3761d54945dSmrg
3771d54945dSmrg      VerticalRetraceWait();
3781d54945dSmrg      gs1   = (long) IN_SUBSYS_STAT();
3791d54945dSmrg
3801d54945dSmrg      /* turn off the GE */
3811d54945dSmrg
3821d54945dSmrg      VGAOUT8(vgaCRIndex,resetidx);
3831d54945dSmrg      if(tmp & 0x01) {
3841d54945dSmrg	/*        tmp &= ~0x01; */
3851d54945dSmrg        VGAOUT8(vgaCRReg, tmp);
3861d54945dSmrg        ge_was_on = 1;
3871d54945dSmrg        usleep(10000);
3881d54945dSmrg      }
3891d54945dSmrg
3901d54945dSmrg      gs2   = (long) IN_SUBSYS_STAT();
3911d54945dSmrg      VGAOUT8(vgaCRReg, (tmp | 0x02));
3921d54945dSmrg      usleep(10000);
3931d54945dSmrg
3941d54945dSmrg      VerticalRetraceWait();
3951d54945dSmrg      VGAOUT8(vgaCRIndex,resetidx);
3961d54945dSmrg      VGAOUT8(vgaCRReg, (tmp & ~0x02));
3971d54945dSmrg      usleep(10000);
3981d54945dSmrg
3991d54945dSmrg      if(ge_was_on) {
4001d54945dSmrg        tmp |= 0x01;
4011d54945dSmrg        VGAOUT8(vgaCRReg, tmp);
4021d54945dSmrg        usleep(10000);
4031d54945dSmrg      }
4041d54945dSmrg
4051d54945dSmrg      if (xf86GetVerbosity() > 2) {
4061d54945dSmrg          ErrorF("\tTrio3D -- GE was %s ST#1: 0x%08lx ST#2: 0x%08lx\n",
4071d54945dSmrg		 (ge_was_on) ? "on" : "off", gs1, gs2);
4081d54945dSmrg      }
4091d54945dSmrg
4101d54945dSmrg      VerticalRetraceWait();
4111d54945dSmrg
4121d54945dSmrg      if (!from_timeout) {
4131d54945dSmrg	S3VNopAllCmdSets(pScrn);
4141d54945dSmrg        WaitIdleEmpty();
4151d54945dSmrg      }
4161d54945dSmrg
4171d54945dSmrg      OUTREG(DEST_SRC_STR, ps3v->Bpl << 16 | ps3v->Bpl);
4181d54945dSmrg      usleep(10000);
4191d54945dSmrg
4201d54945dSmrg      if((IN_SUBSYS_STAT() & 0x3f802000 & 0x20002000) != 0x20002000) {
4211d54945dSmrg        if(xf86GetVerbosity() > 1)
4221d54945dSmrg          ErrorF("restarting S3 graphics engine reset %2d ...%lx\n",
4231d54945dSmrg		 r, (unsigned long)IN_SUBSYS_STAT());
4241d54945dSmrg      }
4251d54945dSmrg        else
4261d54945dSmrg          break;
4271d54945dSmrg    }
4281d54945dSmrg    }
4291d54945dSmrg
4301d54945dSmrg    if (from_timeout && (ps3v->Chipset == S3_ViRGE || ps3v->Chipset == S3_ViRGE_VX
4311d54945dSmrg			 || ps3v->Chipset == S3_ViRGE_DXGX)) {
4321d54945dSmrg      /* restore trashed registers */
4331d54945dSmrg      OUTREG(FIFO_CONTROL_REG, fifo_control);
4341d54945dSmrg      OUTREG(MIU_CONTROL_REG, miu_control);
4351d54945dSmrg      OUTREG(STREAMS_TIMEOUT_REG, streams_timeout);
4361d54945dSmrg      OUTREG(MISC_TIMEOUT_REG, misc_timeout);
4371d54945dSmrg    }
4381d54945dSmrg
4391d54945dSmrg    WAITFIFO(2);
4401d54945dSmrg/*      SETB_SRC_BASE(0); */
4411d54945dSmrg/*      SETB_DEST_BASE(0);    */
4421d54945dSmrg    OUTREG(SRC_BASE, 0);
4431d54945dSmrg    OUTREG(DEST_BASE, 0);
4441d54945dSmrg
4451d54945dSmrg  	WAITFIFO(4);
4461d54945dSmrg    OUTREG(CLIP_L_R, ((0) << 16) | ps3v->Width);
4471d54945dSmrg    OUTREG(CLIP_T_B, ((0) << 16) | ps3v->ScissB);
4481d54945dSmrg    OUTREG(MONO_PAT_0, ~0);
4491d54945dSmrg    OUTREG(MONO_PAT_1, ~0);
4501d54945dSmrg
4511d54945dSmrg    if (!from_timeout && S3_TRIO_3D_SERIES(ps3v->Chipset))
4521d54945dSmrg      S3VNopAllCmdSets(pScrn);
4531d54945dSmrg}
4541d54945dSmrg
4551d54945dSmrg/* The sync function for the GE */
4561d54945dSmrgvoid
4571d54945dSmrgS3VAccelSync(ScrnInfoPtr pScrn)
4581d54945dSmrg{
4591d54945dSmrg    S3VPtr ps3v = S3VPTR(pScrn);
4601d54945dSmrg
4611d54945dSmrg    WAITIDLE();
4621d54945dSmrg}
4631d54945dSmrg
4641d54945dSmrg
4651d54945dSmrgstatic void
4661d54945dSmrgS3VEngineReset(ScrnInfoPtr pScrn)
4671d54945dSmrg{
4681d54945dSmrg    S3VPtr ps3v = S3VPTR(pScrn);
4691d54945dSmrg
4701d54945dSmrg    ps3v->SrcBaseY = 0;
4711d54945dSmrg    ps3v->DestBaseY = 0;
4721d54945dSmrg    ps3v->Stride = pScrn->displayWidth * pScrn->bitsPerPixel >> 3;
4731d54945dSmrg
4741d54945dSmrg    switch(pScrn->bitsPerPixel) {
4751d54945dSmrg    case 8: 	ps3v->CommonCmd = DRAW | DST_8BPP;
4761d54945dSmrg		ps3v->FullPlaneMask = 0x000000ff;
4771d54945dSmrg		ps3v->bltbug_width1 = 51;
4781d54945dSmrg		ps3v->bltbug_width2 = 64;
4791d54945dSmrg		break;
4801d54945dSmrg    case 16: 	ps3v->CommonCmd = DRAW | DST_16BPP;
4811d54945dSmrg		ps3v->FullPlaneMask = 0x0000ffff;
4821d54945dSmrg		ps3v->bltbug_width1 = 26;
4831d54945dSmrg		ps3v->bltbug_width2 = 32;
4841d54945dSmrg		break;
4851d54945dSmrg    case 24: 	ps3v->CommonCmd = DRAW | DST_24BPP;
4861d54945dSmrg		ps3v->FullPlaneMask = 0x00ffffff;
4871d54945dSmrg		ps3v->bltbug_width1 = 16;
4881d54945dSmrg		ps3v->bltbug_width2 = 22;
4891d54945dSmrg		break;
4901d54945dSmrg    }
4911d54945dSmrg
4921d54945dSmrg
4931d54945dSmrg    WAITFIFO(5);
4941d54945dSmrg    OUTREG(SRC_BASE, 0);
4951d54945dSmrg    OUTREG(DEST_BASE, 0);
4961d54945dSmrg    OUTREG(DEST_SRC_STR, ps3v->Stride | (ps3v->Stride << 16));
4971d54945dSmrg
4981d54945dSmrg    OUTREG(CLIP_L_R, ((0) << 16) | ps3v->Width);
4991d54945dSmrg    OUTREG(CLIP_T_B, ((0) << 16) | ps3v->ScissB);
5001d54945dSmrg}
5011d54945dSmrg
5021d54945dSmrg
5031d54945dSmrgstatic void
5041d54945dSmrgS3VWriteMask(
5051d54945dSmrg   CARD32 *dstBase,
5061d54945dSmrg   int dwords
5071d54945dSmrg){
5081d54945dSmrg  /* on alphas, be sure to call this with MapBaseDense, not MapBase! */
5091d54945dSmrg   int numLeft;
5101d54945dSmrg   CARD32 *dst = dstBase;
5111d54945dSmrg
5121d54945dSmrg   while(dwords >= 8192) {
5131d54945dSmrg	numLeft = 8192;
5141d54945dSmrg	while(numLeft) {
5151d54945dSmrg	  dst[0] = ~0; dst[1] = ~0;
5161d54945dSmrg	  dst[2] = ~0; dst[3] = ~0;
5171d54945dSmrg	  dst += 4;
5181d54945dSmrg	  numLeft -= 4;
5191d54945dSmrg	}
5201d54945dSmrg	dwords -= 8192;
5211d54945dSmrg	dst = dstBase;
5221d54945dSmrg   }
5231d54945dSmrg   while(dwords >= 4) {
5241d54945dSmrg	dst[0] = ~0; dst[1] = ~0;
5251d54945dSmrg	dst[2] = ~0; dst[3] = ~0;
5261d54945dSmrg	dst += 4;
5271d54945dSmrg	dwords -= 4;
5281d54945dSmrg   }
5291d54945dSmrg   if(!dwords) return;
5301d54945dSmrg   dst[0] = ~0;
5311d54945dSmrg   if(dwords == 1) return;
5321d54945dSmrg   dst[1] = ~0;
5331d54945dSmrg   if(dwords == 2) return;
5341d54945dSmrg   dst[2] = ~0;
5351d54945dSmrg
5361d54945dSmrg   return;
5371d54945dSmrg}
5381d54945dSmrg
5391d54945dSmrg
5401d54945dSmrg	/************************\
5411d54945dSmrg	|  Solid Filled Rects    |
5421d54945dSmrg	\************************/
5431d54945dSmrg
5441d54945dSmrgstatic void
5451d54945dSmrgS3VSetupForSolidFill(
5461d54945dSmrg   ScrnInfoPtr pScrn,
5471d54945dSmrg   int color, int rop,
5481d54945dSmrg   unsigned int planemask
5491d54945dSmrg){
5501d54945dSmrg    S3VPtr ps3v = S3VPTR(pScrn);
5511d54945dSmrg    int mix;
5521d54945dSmrg
5531d54945dSmrg    mix = XAAHelpSolidROP(pScrn, &color, planemask, &rop);
5541d54945dSmrg
5551d54945dSmrg    ps3v->AccelCmd = ps3v->CommonCmd | (rop << 17) |
5561d54945dSmrg			CMD_XP | CMD_YP | CMD_AUTOEXEC | CMD_BITBLT;
5571d54945dSmrg
5581d54945dSmrg    if(mix & ROP_SRC) {
5591d54945dSmrg	ps3v->AccelCmd |= MIX_CPUDATA | CMD_ITA_DWORD | MIX_MONO_SRC;
5601d54945dSmrg	ps3v->AccelInfoRec->SubsequentSolidFillRect =
5611d54945dSmrg		S3VSubsequentSolidFillRectPlaneMask;
5621d54945dSmrg	ps3v->AccelInfoRec->SubsequentSolidHorVertLine =
5631d54945dSmrg		S3VSubsequentSolidHorVertLinePlaneMask;
5641d54945dSmrg	WAITFIFO(5);
5651d54945dSmrg	OUTREG(SRC_FG_CLR, planemask);
5661d54945dSmrg    } else {
5671d54945dSmrg	ps3v->AccelInfoRec->SubsequentSolidFillRect =
5681d54945dSmrg		S3VSubsequentSolidFillRect;
5691d54945dSmrg	ps3v->AccelInfoRec->SubsequentSolidHorVertLine =
5701d54945dSmrg		S3VSubsequentSolidHorVertLine;
5711d54945dSmrg	WAITFIFO(4);
5721d54945dSmrg    }
5731d54945dSmrg
5741d54945dSmrg    if(mix & ROP_PAT) {
5751d54945dSmrg	ps3v->AccelCmd |= MIX_MONO_PATT;
5761d54945dSmrg	OUTREG(PAT_FG_CLR, color);
5771d54945dSmrg	OUTREG(MONO_PAT_0, ~0);
5781d54945dSmrg	OUTREG(MONO_PAT_1, ~0);
5791d54945dSmrg    }
5801d54945dSmrg
5811d54945dSmrg    OUTREG(CMD_SET, ps3v->AccelCmd);
5821d54945dSmrg}
5831d54945dSmrg
5841d54945dSmrg
5851d54945dSmrgvoid
5861d54945dSmrgS3VSubsequentSolidFillRect(
5871d54945dSmrg   ScrnInfoPtr pScrn,
5881d54945dSmrg   int x, int y,
5891d54945dSmrg   int w, int h
5901d54945dSmrg){
5911d54945dSmrg    S3VPtr ps3v = S3VPTR(pScrn);
5921d54945dSmrg
5931d54945dSmrg    CHECK_DEST_BASE(y,h);
5941d54945dSmrg
5951d54945dSmrg    WAITFIFO(2);
5961d54945dSmrg    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
5971d54945dSmrg    WAITCMD();
5981d54945dSmrg    OUTREG(RDEST_XY, (x << 16) | y);
5991d54945dSmrg}
6001d54945dSmrg
6011d54945dSmrg
6021d54945dSmrgvoid
6031d54945dSmrgS3VSubsequentSolidFillRectPlaneMask(
6041d54945dSmrg   ScrnInfoPtr pScrn,
6051d54945dSmrg   int x, int y,
6061d54945dSmrg   int w, int h
6071d54945dSmrg){
6081d54945dSmrg    S3VPtr ps3v = S3VPTR(pScrn);
6091d54945dSmrg    int dwords;
6101d54945dSmrg
6111d54945dSmrg    CHECK_DEST_BASE(y,h);
6121d54945dSmrg
6131d54945dSmrg    dwords = ((w + 31) >> 5) * h;
6141d54945dSmrg
6151d54945dSmrg    WAITFIFO(2);
6161d54945dSmrg    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
6171d54945dSmrg    WAITCMD();
6181d54945dSmrg    OUTREG(RDEST_XY, (x << 16) | y);
6191d54945dSmrg    S3VWriteMask((CARD32*)ps3v->MapBaseDense, dwords);
6201d54945dSmrg}
6211d54945dSmrg
6221d54945dSmrg
6231d54945dSmrg	/**************************\
6241d54945dSmrg	|  Screen to Screen Copies |
6251d54945dSmrg	\**************************/
6261d54945dSmrg
6271d54945dSmrgstatic void
6281d54945dSmrgS3VSetupForScreenToScreenCopy(
6291d54945dSmrg   ScrnInfoPtr pScrn,
6301d54945dSmrg   int xdir, int ydir,
6311d54945dSmrg   int rop,
6321d54945dSmrg   unsigned int planemask,
6331d54945dSmrg   int trans
6341d54945dSmrg){
6351d54945dSmrg    S3VPtr ps3v = S3VPTR(pScrn);
6361d54945dSmrg
6371d54945dSmrg    planemask &= ps3v->FullPlaneMask;
6381d54945dSmrg    ps3v->AccelCmd = ps3v->CommonCmd | CMD_AUTOEXEC | CMD_BITBLT;
6391d54945dSmrg
6401d54945dSmrg    if(planemask != ps3v->FullPlaneMask) {
6411d54945dSmrg        ps3v->AccelCmd |= (XAAGetCopyROP_PM(rop) << 17) | MIX_MONO_PATT;
6421d54945dSmrg	WAITFIFO(4);
6431d54945dSmrg	OUTREG(PAT_FG_CLR, planemask);
6441d54945dSmrg	OUTREG(MONO_PAT_0, ~0);
6451d54945dSmrg	OUTREG(MONO_PAT_1, ~0);
6461d54945dSmrg        }
6471d54945dSmrg    else {
6481d54945dSmrg        ps3v->AccelCmd |= XAAGetCopyROP(rop) << 17;
6491d54945dSmrg	WAITFIFO(1);
6501d54945dSmrg        }
6511d54945dSmrg    if(xdir == 1) ps3v->AccelCmd |= CMD_XP;
6521d54945dSmrg    if(ydir == 1) ps3v->AccelCmd |= CMD_YP;
6531d54945dSmrg
6541d54945dSmrg    OUTREG(CMD_SET, ps3v->AccelCmd);
6551d54945dSmrg}
6561d54945dSmrg
6571d54945dSmrg
6581d54945dSmrgstatic void
6591d54945dSmrgS3VSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
6601d54945dSmrg        int x2, int y2, int w, int h)
6611d54945dSmrg{
6621d54945dSmrg    S3VPtr ps3v = S3VPTR(pScrn);
6631d54945dSmrg
6641d54945dSmrg    CHECK_SRC_BASE(y1,h);
6651d54945dSmrg    CHECK_DEST_BASE(y2,h);
6661d54945dSmrg
6671d54945dSmrg    w--;
6681d54945dSmrg
6691d54945dSmrg    if(!(ps3v->AccelCmd & CMD_YP)) {
6701d54945dSmrg	y1 += h - 1; y2 += h - 1;
6711d54945dSmrg    }
6721d54945dSmrg
6731d54945dSmrg    if(!(ps3v->AccelCmd & CMD_XP)) {
6741d54945dSmrg	x1 += w; x2 += w;
6751d54945dSmrg    }
6761d54945dSmrg
6771d54945dSmrg    WAITFIFO(3);
6781d54945dSmrg    OUTREG(RWIDTH_HEIGHT, (w << 16) | h);
6791d54945dSmrg    OUTREG(RSRC_XY, (x1 << 16) | y1);
6801d54945dSmrg    WAITCMD();
6811d54945dSmrg    OUTREG(RDEST_XY, (x2 << 16) | y2);
6821d54945dSmrg}
6831d54945dSmrg
6841d54945dSmrg
6851d54945dSmrg	/*********************\
6861d54945dSmrg	|  8x8 Pattern fills  |
6871d54945dSmrg	\*********************/
6881d54945dSmrg
6891d54945dSmrg
6901d54945dSmrgstatic void
6911d54945dSmrgS3VSetupForMono8x8PatternFill(
6921d54945dSmrg    ScrnInfoPtr pScrn,
6931d54945dSmrg    int patx, int paty,
6941d54945dSmrg    int fg, int bg,
6951d54945dSmrg    int rop, unsigned int planemask
6961d54945dSmrg){
6971d54945dSmrg    S3VPtr ps3v = S3VPTR(pScrn);
6981d54945dSmrg    int mix;
6991d54945dSmrg
7001d54945dSmrg    mix = XAAHelpPatternROP(pScrn, &fg, &bg, planemask, &rop);
7011d54945dSmrg
7021d54945dSmrg    ps3v->AccelCmd = ps3v->CommonCmd | (rop << 17) |
7031d54945dSmrg			CMD_XP | CMD_YP | CMD_AUTOEXEC | CMD_BITBLT;
7041d54945dSmrg
7051d54945dSmrg    if(mix & ROP_SRC) {
7061d54945dSmrg 	ps3v->AccelCmd |= MIX_CPUDATA | CMD_ITA_DWORD | MIX_MONO_SRC;
7071d54945dSmrg	ps3v->AccelInfoRec->SubsequentMono8x8PatternFillRect =
7081d54945dSmrg		S3VSubsequentMono8x8PatternFillRectPlaneMask;
7091d54945dSmrg	WAITFIFO(6);
7101d54945dSmrg	OUTREG(SRC_FG_CLR, planemask);
7111d54945dSmrg    } else {
7121d54945dSmrg	ps3v->AccelInfoRec->SubsequentMono8x8PatternFillRect =
7131d54945dSmrg		S3VSubsequentMono8x8PatternFillRect;
7141d54945dSmrg	WAITFIFO(5);
7151d54945dSmrg    }
7161d54945dSmrg
7171d54945dSmrg    if(mix & ROP_PAT) {
7181d54945dSmrg	ps3v->AccelCmd |= MIX_MONO_PATT;
7191d54945dSmrg	OUTREG(PAT_FG_CLR, fg);
7201d54945dSmrg	OUTREG(PAT_BG_CLR, bg);
7211d54945dSmrg	OUTREG(MONO_PAT_0, patx);
7221d54945dSmrg	OUTREG(MONO_PAT_1, paty);
7231d54945dSmrg    }
7241d54945dSmrg
7251d54945dSmrg    OUTREG(CMD_SET, ps3v->AccelCmd);
7261d54945dSmrg}
7271d54945dSmrg
7281d54945dSmrg
7291d54945dSmrgstatic void
7301d54945dSmrgS3VSubsequentMono8x8PatternFillRect(
7311d54945dSmrg    ScrnInfoPtr pScrn,
7321d54945dSmrg    int patx, int paty,
7331d54945dSmrg    int x, int y, int w, int h
7341d54945dSmrg){
7351d54945dSmrg    S3VPtr ps3v = S3VPTR(pScrn);
7361d54945dSmrg
7371d54945dSmrg    CHECK_DEST_BASE(y,h);
7381d54945dSmrg
7391d54945dSmrg    WAITFIFO(2);
7401d54945dSmrg    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
7411d54945dSmrg    WAITCMD();
7421d54945dSmrg    OUTREG(RDEST_XY, (x << 16) | y);
7431d54945dSmrg}
7441d54945dSmrg
7451d54945dSmrg
7461d54945dSmrgstatic void
7471d54945dSmrgS3VSubsequentMono8x8PatternFillRectPlaneMask(
7481d54945dSmrg    ScrnInfoPtr pScrn,
7491d54945dSmrg    int patx, int paty,
7501d54945dSmrg    int x, int y, int w, int h
7511d54945dSmrg){
7521d54945dSmrg    S3VPtr ps3v = S3VPTR(pScrn);
7531d54945dSmrg    int dwords;
7541d54945dSmrg
7551d54945dSmrg    CHECK_DEST_BASE(y,h);
7561d54945dSmrg
7571d54945dSmrg    dwords = ((w + 31) >> 5) * h;
7581d54945dSmrg
7591d54945dSmrg    WAITFIFO(2);
7601d54945dSmrg    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
7611d54945dSmrg    WAITCMD();
7621d54945dSmrg    OUTREG(RDEST_XY, (x << 16) | y);
7631d54945dSmrg
7641d54945dSmrg    S3VWriteMask((CARD32*)ps3v->MapBaseDense, dwords);
7651d54945dSmrg}
7661d54945dSmrg
7671d54945dSmrg	/*********************************\
7681d54945dSmrg	|  CPU to Screen Color Expansion  |
7691d54945dSmrg	\*********************************/
7701d54945dSmrg
7711d54945dSmrg
7721d54945dSmrgstatic void
7731d54945dSmrgS3VSetupForCPUToScreenColorExpand(
7741d54945dSmrg    ScrnInfoPtr pScrn,
7751d54945dSmrg    int fg, int bg,
7761d54945dSmrg    int rop,
7771d54945dSmrg    unsigned int planemask
7781d54945dSmrg){
7791d54945dSmrg    S3VPtr ps3v = S3VPTR(pScrn);
7801d54945dSmrg
7811d54945dSmrg    planemask &= ps3v->FullPlaneMask;
7821d54945dSmrg    ps3v->AccelCmd = ps3v->CommonCmd | CMD_AUTOEXEC | CMD_BITBLT |
7831d54945dSmrg		CMD_XP | CMD_YP | CMD_ITA_DWORD | CMD_HWCLIP |
7841d54945dSmrg		MIX_CPUDATA | MIX_MONO_SRC;
7851d54945dSmrg
7861d54945dSmrg
7871d54945dSmrg    if(planemask == ps3v->FullPlaneMask) {
7881d54945dSmrg        ps3v->AccelCmd |= XAAGetCopyROP(rop) << 17;
7891d54945dSmrg	WAITFIFO(3);
7901d54945dSmrg    } else {
7911d54945dSmrg        ps3v->AccelCmd |= (XAAGetCopyROP_PM(rop) << 17) | MIX_MONO_PATT;
7921d54945dSmrg	WAITFIFO(6);
7931d54945dSmrg	OUTREG(MONO_PAT_0, ~0);
7941d54945dSmrg	OUTREG(MONO_PAT_1, ~0);
7951d54945dSmrg        OUTREG(PAT_FG_CLR, planemask);
7961d54945dSmrg    }
7971d54945dSmrg
7981d54945dSmrg    if(bg == -1)
7991d54945dSmrg	ps3v->AccelCmd |= MIX_MONO_TRANSP;
8001d54945dSmrg    else
8011d54945dSmrg	OUTREG(SRC_BG_CLR, bg);
8021d54945dSmrg
8031d54945dSmrg    OUTREG(SRC_FG_CLR, fg);
8041d54945dSmrg    OUTREG(CMD_SET, ps3v->AccelCmd);
8051d54945dSmrg}
8061d54945dSmrg
8071d54945dSmrg
8081d54945dSmrgvoid
8091d54945dSmrgS3VSubsequentCPUToScreenColorExpand(
8101d54945dSmrg    ScrnInfoPtr pScrn,
8111d54945dSmrg    int x, int y,
8121d54945dSmrg    int w, int h,
8131d54945dSmrg    int skipleft
8141d54945dSmrg){
8151d54945dSmrg    S3VPtr ps3v = S3VPTR(pScrn);
8161d54945dSmrg
8171d54945dSmrg    CHECK_DEST_BASE(y,h);
8181d54945dSmrg    WAITFIFO(3);
8191d54945dSmrg    OUTREG(CLIP_L_R, ((x + skipleft) << 16) | 0xffff);
8201d54945dSmrg    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
8211d54945dSmrg    WAITCMD();
8221d54945dSmrg    OUTREG(RDEST_XY, (x << 16) | y);
8231d54945dSmrg}
8241d54945dSmrg
8251d54945dSmrg
8261d54945dSmrg    /****************\
8271d54945dSmrg    |  Image Writes  |
8281d54945dSmrg    \****************/
8291d54945dSmrg
8301d54945dSmrg
8311d54945dSmrgstatic void
8321d54945dSmrgS3VSetupForImageWrite(
8331d54945dSmrg   ScrnInfoPtr pScrn,
8341d54945dSmrg   int rop, unsigned int planemask,
8351d54945dSmrg   int trans_color, int bpp, int depth
8361d54945dSmrg){
8371d54945dSmrg    S3VPtr ps3v = S3VPTR(pScrn);
8381d54945dSmrg
8391d54945dSmrg    planemask &= ps3v->FullPlaneMask;
8401d54945dSmrg    ps3v->AccelCmd = ps3v->CommonCmd | CMD_AUTOEXEC | CMD_BITBLT |
8411d54945dSmrg		MIX_CPUDATA | CMD_ITA_DWORD | CMD_HWCLIP | CMD_XP | CMD_YP;
8421d54945dSmrg
8431d54945dSmrg    if(planemask != ps3v->FullPlaneMask) {
8441d54945dSmrg        ps3v->AccelCmd |= (XAAGetCopyROP_PM(rop) << 17) | MIX_MONO_PATT;
8451d54945dSmrg	WAITFIFO(4);
8461d54945dSmrg	OUTREG(PAT_FG_CLR, planemask);
8471d54945dSmrg	OUTREG(MONO_PAT_0, ~0);
8481d54945dSmrg	OUTREG(MONO_PAT_1, ~0);
8491d54945dSmrg    } else {
8501d54945dSmrg        ps3v->AccelCmd |= XAAGetCopyROP(rop) << 17;
8511d54945dSmrg	WAITFIFO(1);
8521d54945dSmrg    }
8531d54945dSmrg
8541d54945dSmrg    OUTREG(CMD_SET, ps3v->AccelCmd);
8551d54945dSmrg}
8561d54945dSmrg
8571d54945dSmrg
8581d54945dSmrgstatic void
8591d54945dSmrgS3VSubsequentImageWriteRect(
8601d54945dSmrg    ScrnInfoPtr pScrn,
8611d54945dSmrg    int x, int y,
8621d54945dSmrg    int w, int h,
8631d54945dSmrg    int skipleft
8641d54945dSmrg){
8651d54945dSmrg    S3VPtr ps3v = S3VPTR(pScrn);
8661d54945dSmrg
8671d54945dSmrg    CHECK_DEST_BASE(y,h);
8681d54945dSmrg
8691d54945dSmrg    WAITFIFO(3);
8701d54945dSmrg    OUTREG(CLIP_L_R, ((x + skipleft) << 16) | 0xffff);
8711d54945dSmrg    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
8721d54945dSmrg    WAITCMD();
8731d54945dSmrg    OUTREG(RDEST_XY, (x << 16) | y);
8741d54945dSmrg}
8751d54945dSmrg
8761d54945dSmrg
8771d54945dSmrg	/***********\
8781d54945dSmrg	|   Lines   |
8791d54945dSmrg	\***********/
8801d54945dSmrg
8811d54945dSmrg
8821d54945dSmrg#if 0   /* Some line funcs are disabled at the moment */
8831d54945dSmrg
8841d54945dSmrgstatic void
8851d54945dSmrgS3VPolylinesThinSolidWrapper(
8861d54945dSmrg   DrawablePtr     pDraw,
8871d54945dSmrg   GCPtr           pGC,
8881d54945dSmrg   int             mode,
8891d54945dSmrg   int             npt,
8901d54945dSmrg   DDXPointPtr     pPts
8911d54945dSmrg){
8921d54945dSmrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
8931d54945dSmrg    S3VPtr ps3v = S3VPTR(infoRec->pScrn);
8941d54945dSmrg    ps3v->CurrentGC = pGC;
8951d54945dSmrg    /* fb support */
8961d54945dSmrg    ps3v->CurrentDrawable = pDraw;
8971d54945dSmrg    if(infoRec->NeedToSync)
8981d54945dSmrg	S3VAccelSync(infoRec->pScrn);
8991d54945dSmrg    XAAPolyLines(pDraw, pGC, mode, npt, pPts);
9001d54945dSmrg}
9011d54945dSmrg
9021d54945dSmrgstatic void
9031d54945dSmrgS3VPolySegmentThinSolidWrapper(
9041d54945dSmrg   DrawablePtr     pDraw,
9051d54945dSmrg   GCPtr           pGC,
9061d54945dSmrg   int             nseg,
9071d54945dSmrg   xSegment        *pSeg
9081d54945dSmrg){
9091d54945dSmrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
9101d54945dSmrg    S3VPtr ps3v = S3VPTR(infoRec->pScrn);
9111d54945dSmrg    ps3v->CurrentGC = pGC;
9121d54945dSmrg    /* fb support */
9131d54945dSmrg    ps3v->CurrentDrawable = pDraw;
9141d54945dSmrg    if(infoRec->NeedToSync)
9151d54945dSmrg	S3VAccelSync(infoRec->pScrn);
9161d54945dSmrg    XAAPolySegment(pDraw, pGC, nseg, pSeg);
9171d54945dSmrg}
9181d54945dSmrg
9191d54945dSmrg#endif
9201d54945dSmrg
9211d54945dSmrgstatic void
9221d54945dSmrgS3VSubsequentSolidHorVertLine(
9231d54945dSmrg    ScrnInfoPtr pScrn,
9241d54945dSmrg    int x, int y,
9251d54945dSmrg    int len, int dir
9261d54945dSmrg){
9271d54945dSmrg    S3VPtr ps3v = S3VPTR(pScrn);
9281d54945dSmrg    int w, h;
9291d54945dSmrg
9301d54945dSmrg    if(dir == DEGREES_0) {
9311d54945dSmrg	w = len; h = 1;
9321d54945dSmrg    } else {
9331d54945dSmrg	w = 1; h = len;
9341d54945dSmrg    }
9351d54945dSmrg
9361d54945dSmrg    CHECK_DEST_BASE(y,h);
9371d54945dSmrg
9381d54945dSmrg    WAITFIFO(2);
9391d54945dSmrg    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
9401d54945dSmrg    WAITCMD();
9411d54945dSmrg    OUTREG(RDEST_XY, (x << 16) | y);
9421d54945dSmrg}
9431d54945dSmrg
9441d54945dSmrgstatic void
9451d54945dSmrgS3VSubsequentSolidHorVertLinePlaneMask(
9461d54945dSmrg    ScrnInfoPtr pScrn,
9471d54945dSmrg    int x, int y,
9481d54945dSmrg    int len, int dir
9491d54945dSmrg){
9501d54945dSmrg    S3VPtr ps3v = S3VPTR(pScrn);
9511d54945dSmrg    int w, h, dwords;
9521d54945dSmrg
9531d54945dSmrg    if(dir == DEGREES_0) {
9541d54945dSmrg	w = len; h = 1; dwords = (len + 31) >> 5;
9551d54945dSmrg    } else {
9561d54945dSmrg	w = 1; h = len; dwords = len;
9571d54945dSmrg    }
9581d54945dSmrg
9591d54945dSmrg    CHECK_DEST_BASE(y,h);
9601d54945dSmrg
9611d54945dSmrg    WAITFIFO(2);
9621d54945dSmrg    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
9631d54945dSmrg    WAITCMD();
9641d54945dSmrg    OUTREG(RDEST_XY, (x << 16) | y);
9651d54945dSmrg
9661d54945dSmrg    S3VWriteMask((CARD32*)ps3v->MapBaseDense, dwords);
9671d54945dSmrg}
9681d54945dSmrg
9691d54945dSmrg
9701d54945dSmrgvoid
9711d54945dSmrgS3VWaitFifoGX2(S3VPtr ps3v, int slots )
9721d54945dSmrg{
9731d54945dSmrg  if(ps3v->NoPCIRetry)
9741d54945dSmrg    while(((INREG(SUBSYS_STAT_REG) >> 9) & 0x60) < slots){}
9751d54945dSmrg}
9761d54945dSmrg
9771d54945dSmrg
9781d54945dSmrg
9791d54945dSmrgvoid
9801d54945dSmrgS3VWaitFifoMain(S3VPtr ps3v, int slots )
9811d54945dSmrg{
9821d54945dSmrg  if(ps3v->NoPCIRetry)
9831d54945dSmrg    while(((INREG(SUBSYS_STAT_REG) >> 8) & 0x1f) < slots){}
9841d54945dSmrg}
9851d54945dSmrg
9861d54945dSmrg
9871d54945dSmrgvoid
9881d54945dSmrgS3VWaitCmdGX2(S3VPtr ps3v)
9891d54945dSmrg{
9901d54945dSmrg  while(((INREG(ADV_FUNC_CNTR) >> 6) & 0x1f) != 16){}
9911d54945dSmrg}
9921d54945dSmrg
9931d54945dSmrg
9941d54945dSmrgvoid
9951d54945dSmrgS3VWaitDummy(S3VPtr ps3v)
9961d54945dSmrg{
9971d54945dSmrg  /* do nothing */
9981d54945dSmrg}
9991d54945dSmrg
10001d54945dSmrg/*EOF*/
10011d54945dSmrg
1002