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