1
2/*
3Copyright (C) 1994-1999 The XFree86 Project, Inc.  All Rights Reserved.
4
5Permission is hereby granted, free of charge, to any person obtaining a copy of
6this software and associated documentation files (the "Software"), to deal in
7the Software without restriction, including without limitation the rights to
8use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9of the Software, and to permit persons to whom the Software is furnished to do
10so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in all
13copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
17NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of the XFree86 Project shall not
23be used in advertising or otherwise to promote the sale, use or other dealings
24in this Software without prior written authorization from the XFree86 Project.
25*/
26
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#endif
30
31#include <unistd.h>
32#include "s3v.h"
33#include "s3v_pciids.h"
34
35#include "miline.h"
36	/* fb includes are in s3v.h */
37#include "xaarop.h"
38
39#include "servermd.h" /* LOG2_BYTES_PER_SCANLINE_PAD */
40
41#ifdef HAVE_XAA_H
42static void S3VWriteMask(CARD32*, int);
43
44static void S3VEngineReset(ScrnInfoPtr pScrn);
45/* s3v.h - static void S3VAccelSync(ScrnInfoPtr); */
46static void S3VSetupForSolidFill(ScrnInfoPtr, int, int, unsigned);
47static void S3VSubsequentSolidFillRect(ScrnInfoPtr, int, int, int, int);
48static void S3VSubsequentSolidFillRectPlaneMask(ScrnInfoPtr, int, int,
49				int, int);
50static void S3VSetupForMono8x8PatternFill(ScrnInfoPtr,int, int, int, int,
51                                int, unsigned int);
52static void S3VSubsequentMono8x8PatternFillRect(ScrnInfoPtr,int, int,
53                                int, int, int, int);
54static void S3VSubsequentMono8x8PatternFillRectPlaneMask(ScrnInfoPtr,int, int,
55                                int, int, int, int);
56static void S3VSetupForScreenToScreenCopy(ScrnInfoPtr, int, int, int,
57				unsigned int, int);
58static void S3VSubsequentScreenToScreenCopy(ScrnInfoPtr, int, int, int, int,
59				int, int);
60static void S3VSetupForCPUToScreenColorExpand(ScrnInfoPtr, int, int, int,
61				unsigned int);
62static void S3VSubsequentCPUToScreenColorExpand(ScrnInfoPtr, int, int, int,
63				int, int);
64static void S3VSetupForImageWrite(ScrnInfoPtr, int, unsigned int, int,
65				int, int);
66static void S3VSubsequentImageWriteRect(ScrnInfoPtr, int, int, int, int, int);
67static void S3VSubsequentSolidHorVertLine(ScrnInfoPtr, int, int, int, int);
68static void S3VSubsequentSolidHorVertLinePlaneMask(ScrnInfoPtr, int, int,
69				int, int);
70#if 0
71static void S3VSubsequentSolidBresenhamLine(ScrnInfoPtr, int, int, int,
72				int, int, int, int);
73static void S3VPolylinesThinSolidWrapper(DrawablePtr, GCPtr, int, int,
74				DDXPointPtr);
75static void S3VPolySegmentThinSolidWrapper(DrawablePtr, GCPtr, int, xSegment*);
76#endif
77static void S3VNopAllCmdSets(ScrnInfoPtr pScrn);
78#endif
79
80Bool
81S3VAccelInit(ScreenPtr pScreen)
82{
83#ifdef HAVE_XAA_H
84    XAAInfoRecPtr infoPtr;
85    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
86    S3VPtr ps3v = S3VPTR(pScrn);
87    BoxRec AvailFBArea;
88
89    ps3v->AccelInfoRec = infoPtr = XAACreateInfoRec();
90    if(!infoPtr) return FALSE;
91
92    switch(ps3v->Chipset)
93      {
94      case S3_ViRGE:
95      case S3_ViRGE_VX:
96	ps3v->AccelFlags = BLT_BUG;
97	break;
98      default:
99	ps3v->AccelFlags = 0;
100	break;
101      }
102
103    ps3v->AccelFlags |= MONO_TRANS_BUG; /* which aren't broken ? */
104
105
106    infoPtr->Flags = PIXMAP_CACHE |
107		     LINEAR_FRAMEBUFFER |
108		     OFFSCREEN_PIXMAPS;
109
110    infoPtr->Sync = S3VAccelSync;
111
112    /* Problem reports with solid fill on trio3d */
113    if(!S3_TRIO_3D_SERIES(ps3v->Chipset))
114      {
115	/* Solid filled rects */
116	infoPtr->SetupForSolidFill =
117	  S3VSetupForSolidFill;
118	infoPtr->SubsequentSolidFillRect =
119	  S3VSubsequentSolidFillRect;
120      }
121
122    /* Screen to screen copies */
123    infoPtr->SetupForScreenToScreenCopy =
124        S3VSetupForScreenToScreenCopy;
125    infoPtr->SubsequentScreenToScreenCopy =
126        S3VSubsequentScreenToScreenCopy;
127    infoPtr->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
128
129    /* Mono 8x8 patterns */
130    infoPtr->SetupForMono8x8PatternFill =
131        S3VSetupForMono8x8PatternFill;
132    infoPtr->SubsequentMono8x8PatternFillRect =
133        S3VSubsequentMono8x8PatternFillRect;
134    infoPtr->Mono8x8PatternFillFlags = NO_TRANSPARENCY |
135				HARDWARE_PATTERN_PROGRAMMED_BITS |
136				HARDWARE_PATTERN_SCREEN_ORIGIN |
137				BIT_ORDER_IN_BYTE_MSBFIRST;
138
139
140#ifndef __alpha__
141
142    /* disable color expand on GX2 until we trace down */
143    /* lockups.  locate 'html'  in an xterm is a good  */
144    /* test case for an AGP GX2. */
145    if (!S3_ViRGE_GX2_SERIES(ps3v->Chipset))
146      {
147
148
149	/* CPU to screen color expansion */
150	infoPtr->CPUToScreenColorExpandFillFlags =  ROP_NEEDS_SOURCE |
151					CPU_TRANSFER_PAD_DWORD |
152                                        SCANLINE_PAD_DWORD |
153                                        BIT_ORDER_IN_BYTE_MSBFIRST |
154                                  	LEFT_EDGE_CLIPPING;
155
156	if(ps3v->AccelFlags & MONO_TRANS_BUG)
157	  infoPtr->CPUToScreenColorExpandFillFlags |=  NO_TRANSPARENCY;
158
159	infoPtr->ColorExpandRange = 0x8000;
160	infoPtr->ColorExpandBase = ps3v->MapBaseDense;
161	infoPtr->SetupForCPUToScreenColorExpandFill =
162                S3VSetupForCPUToScreenColorExpand;
163	infoPtr->SubsequentCPUToScreenColorExpandFill =
164                S3VSubsequentCPUToScreenColorExpand;
165
166      } /* if(!GX2...) */
167
168
169    /* Image Writes */
170    infoPtr->ImageWriteFlags =  	ROP_NEEDS_SOURCE |
171					NO_TRANSPARENCY |
172					CPU_TRANSFER_PAD_DWORD |
173					SCANLINE_PAD_DWORD |
174					NO_GXCOPY |  /* added - kjb */
175					LEFT_EDGE_CLIPPING;
176
177    infoPtr->ImageWriteRange = 0x8000;
178    infoPtr->ImageWriteBase = ps3v->MapBaseDense;
179    infoPtr->SetupForImageWrite = S3VSetupForImageWrite;
180    infoPtr->SubsequentImageWriteRect = S3VSubsequentImageWriteRect;
181
182    /* on alpha, I see corruption in the xscreensaver program "hypercube"
183       as the line acceleration is just stubs, it loses us nothing to
184       disable it on alphas */
185
186    /* Lines */
187#if 0
188    /* Bresenham lines are broken when passed through fb to xaa
189       so I pulled all the line functions.  This shouldn't hurt us
190       a whole lot, since the Subsequent..Bresen stuff doesn't have
191       any hardware accel yet anyway...  And xaa will do horiz/vert
192       lines with the rect fill (like we are doing here) anyway.
193       KJB 9/11/00
194    */
195    infoPtr->SetupForSolidLine = S3VSetupForSolidFill;
196    infoPtr->SubsequentSolidHorVertLine = S3VSubsequentSolidHorVertLine;
197    infoPtr->SubsequentSolidBresenhamLine = S3VSubsequentSolidBresenhamLine;
198    infoPtr->PolySegmentThinSolid = S3VPolySegmentThinSolidWrapper;
199    infoPtr->PolylinesThinSolid = S3VPolylinesThinSolidWrapper;
200#endif
201
202#endif /* !__alpha__ */
203
204    /* And these are screen parameters used to setup the GE */
205
206     ps3v->Width = pScrn->displayWidth;
207     					/* Bytes per pixel */
208     ps3v->Bpp = pScrn->bitsPerPixel / 8;
209     					/* Bytes per line */
210     ps3v->Bpl = ps3v->Width * ps3v->Bpp;
211     					/* ScissB is max height, minus 1k */
212					/* for hwcursor?, then limited by */
213					/* ViRGE max height register of   */
214					/* 2047 */
215     ps3v->ScissB = (pScrn->videoRam * 1024 - 1024) / ps3v->Bpl;
216     if (ps3v->ScissB > 2047)
217         ps3v->ScissB = 2047;
218
219
220    S3VEngineReset(pScrn);
221
222
223    AvailFBArea.x1 = 0;
224    AvailFBArea.y1 = 0;
225    AvailFBArea.x2 = pScrn->displayWidth;
226    AvailFBArea.y2 = (pScrn->videoRam * 1024 - 1024) /
227		     (pScrn->displayWidth * pScrn->bitsPerPixel / 8);
228
229    xf86InitFBManager(pScreen, &AvailFBArea);
230
231    /* make sure offscreen pixmaps aren't bigger than our address space */
232    infoPtr->maxOffPixWidth  = 2048;
233    infoPtr->maxOffPixHeight = 2048;
234
235    return (XAAInit(pScreen, infoPtr));
236#else
237    return FALSE;
238#endif
239}
240
241Bool
242S3VAccelInit32(ScreenPtr pScreen)
243{
244   return FALSE;
245}
246
247void
248S3VNopAllCmdSets(ScrnInfoPtr pScrn)
249{
250  int i;
251  int max_it=1000;
252  S3VPtr ps3v = S3VPTR(pScrn);
253
254  if (xf86GetVerbosity() > 1) {
255     ErrorF("\tTrio3D -- S3VNopAllCmdSets: SubsysStats#1 = 0x%08lx\n",
256        (unsigned long)IN_SUBSYS_STAT());
257  }
258
259  mem_barrier();
260  for(i=0;i<max_it;i++) {
261    if( (IN_SUBSYS_STAT() & 0x3f802000 & 0x20002000) == 0x20002000) {
262      break;
263    }
264  }
265
266  if(i!=max_it) {
267    if (xf86GetVerbosity() > 1) ErrorF("\tTrio3D -- S3VNopAllCmdSets: state changed after %d iterations\n",i);
268  } else {
269    if (xf86GetVerbosity() > 1) ErrorF("\tTrio3D -- S3VNopAllCmdSets: state DIDN'T changed after %d iterations\n",max_it);
270  }
271
272  WaitQueue(5);
273
274  OUTREG(CMD_SET, CMD_NOP);
275
276  if (xf86GetVerbosity() > 1) {
277     ErrorF("\tTrio3D -- S3VNopAllCmdSets: SubsysStats#2 = 0x%08lx\n",
278        (unsigned long)IN_SUBSYS_STAT());
279  }
280}
281
282void
283S3VGEReset(ScrnInfoPtr pScrn, int from_timeout, int line, const char *file)
284{
285    unsigned long gs1, gs2;   /* -- debug info for graphics state -- */
286    unsigned char tmp, sr1, resetidx=0x66;  /* FIXME */
287    int r;
288    int ge_was_on = 0;
289    CARD32 fifo_control = 0, miu_control = 0;
290    CARD32 streams_timeout = 0, misc_timeout = 0;
291    vgaHWPtr hwp = VGAHWPTR(pScrn);
292	S3VPtr ps3v = S3VPTR(pScrn);
293  	int vgaCRIndex, vgaCRReg, vgaIOBase;
294  	vgaIOBase = hwp->IOBase;
295  	vgaCRIndex = vgaIOBase + 4;
296  	vgaCRReg = vgaIOBase + 5;
297
298
299    if (S3_TRIO_3D_SERIES(ps3v->Chipset)) {
300      VGAOUT8(0x3c4,0x01);
301      sr1 = VGAIN8(0x3c5);
302
303      if (sr1 & 0x20) {
304        if (xf86GetVerbosity() > 1)
305          ErrorF("\tTrio3D -- Display is on...turning off\n");
306        VGAOUT8(0x3c5,sr1 & ~0x20);
307        VerticalRetraceWait();
308      }
309    }
310
311    if (from_timeout) {
312      if (ps3v->GEResetCnt++ < 10 || xf86GetVerbosity() > 1)
313	ErrorF("\tS3VGEReset called from %s line %d\n",file,line);
314    }
315    else {
316      if (S3_TRIO_3D_SERIES(ps3v->Chipset))
317        S3VNopAllCmdSets(pScrn);
318      WaitIdleEmpty();
319    }
320
321
322    if (from_timeout && (ps3v->Chipset == S3_ViRGE || ps3v->Chipset == S3_ViRGE_VX || ps3v->Chipset == S3_ViRGE_DXGX)) {
323      /* reset will trash these registers, so save them */
324      fifo_control    = INREG(FIFO_CONTROL_REG);
325      miu_control     = INREG(MIU_CONTROL_REG);
326      streams_timeout = INREG(STREAMS_TIMEOUT_REG);
327      misc_timeout    = INREG(MISC_TIMEOUT_REG);
328    }
329
330    if(ps3v->Chipset == S3_ViRGE_VX){
331        VGAOUT8(vgaCRIndex, 0x63);
332        }
333    else {
334        VGAOUT8(vgaCRIndex, 0x66);
335        }
336  if (!S3_TRIO_3D_SERIES(ps3v->Chipset)) {
337    tmp = VGAIN8(vgaCRReg);
338
339    usleep(10000);
340    for (r=1; r<10; r++) {  /* try multiple times to avoid lockup of ViRGE/MX */
341      VGAOUT8(vgaCRReg, tmp | 0x02);
342      usleep(10000);
343      VGAOUT8(vgaCRReg, tmp & ~0x02);
344      usleep(10000);
345
346      xf86ErrorFVerb(VERBLEV, "	S3VGEReset sub_stat=%lx \n",
347   	(unsigned long)IN_SUBSYS_STAT()
348	);
349
350      if (!from_timeout)
351        WaitIdleEmpty();
352
353      OUTREG(DEST_SRC_STR, ps3v->Bpl << 16 | ps3v->Bpl);
354
355      usleep(10000);
356      if (((IN_SUBSYS_STAT() & 0x3f00) != 0x3000))
357	xf86ErrorFVerb(VERBLEV, "restarting S3 graphics engine reset %2d ...\n",r);
358      else
359	break;
360    }
361    } else {
362    usleep(10000);
363
364    for (r=1; r<10; r++) {
365      VerticalRetraceWait();
366      VGAOUT8(vgaCRIndex,resetidx);
367      tmp = VGAIN8(vgaCRReg);
368
369      VGAOUT8(0x3c4,0x01);
370      sr1 = VGAIN8(0x3c5);
371
372      if(sr1 & 0x20) {
373        if(xf86GetVerbosity() > 1) {
374          ErrorF("\tTrio3D -- Upps Display is on again ...turning off\n");
375        }
376        VGAOUT8(0x3c4,0x01);
377        VerticalRetraceWait();
378        VGAOUT8(0x3c5,sr1 & ~0x20);
379      }
380
381      VerticalRetraceWait();
382      gs1   = (long) IN_SUBSYS_STAT();
383
384      /* turn off the GE */
385
386      VGAOUT8(vgaCRIndex,resetidx);
387      if(tmp & 0x01) {
388	/*        tmp &= ~0x01; */
389        VGAOUT8(vgaCRReg, tmp);
390        ge_was_on = 1;
391        usleep(10000);
392      }
393
394      gs2   = (long) IN_SUBSYS_STAT();
395      VGAOUT8(vgaCRReg, (tmp | 0x02));
396      usleep(10000);
397
398      VerticalRetraceWait();
399      VGAOUT8(vgaCRIndex,resetidx);
400      VGAOUT8(vgaCRReg, (tmp & ~0x02));
401      usleep(10000);
402
403      if(ge_was_on) {
404        tmp |= 0x01;
405        VGAOUT8(vgaCRReg, tmp);
406        usleep(10000);
407      }
408
409      if (xf86GetVerbosity() > 2) {
410          ErrorF("\tTrio3D -- GE was %s ST#1: 0x%08lx ST#2: 0x%08lx\n",
411		 (ge_was_on) ? "on" : "off", gs1, gs2);
412      }
413
414      VerticalRetraceWait();
415
416      if (!from_timeout) {
417	S3VNopAllCmdSets(pScrn);
418        WaitIdleEmpty();
419      }
420
421      OUTREG(DEST_SRC_STR, ps3v->Bpl << 16 | ps3v->Bpl);
422      usleep(10000);
423
424      if((IN_SUBSYS_STAT() & 0x3f802000 & 0x20002000) != 0x20002000) {
425        if(xf86GetVerbosity() > 1)
426          ErrorF("restarting S3 graphics engine reset %2d ...%lx\n",
427		 r, (unsigned long)IN_SUBSYS_STAT());
428      }
429        else
430          break;
431    }
432    }
433
434    if (from_timeout && (ps3v->Chipset == S3_ViRGE || ps3v->Chipset == S3_ViRGE_VX
435			 || ps3v->Chipset == S3_ViRGE_DXGX)) {
436      /* restore trashed registers */
437      OUTREG(FIFO_CONTROL_REG, fifo_control);
438      OUTREG(MIU_CONTROL_REG, miu_control);
439      OUTREG(STREAMS_TIMEOUT_REG, streams_timeout);
440      OUTREG(MISC_TIMEOUT_REG, misc_timeout);
441    }
442
443    WAITFIFO(2);
444/*      SETB_SRC_BASE(0); */
445/*      SETB_DEST_BASE(0);    */
446    OUTREG(SRC_BASE, 0);
447    OUTREG(DEST_BASE, 0);
448
449  	WAITFIFO(4);
450    OUTREG(CLIP_L_R, ((0) << 16) | ps3v->Width);
451    OUTREG(CLIP_T_B, ((0) << 16) | ps3v->ScissB);
452    OUTREG(MONO_PAT_0, ~0);
453    OUTREG(MONO_PAT_1, ~0);
454
455    if (!from_timeout && S3_TRIO_3D_SERIES(ps3v->Chipset))
456      S3VNopAllCmdSets(pScrn);
457}
458
459/* The sync function for the GE */
460void
461S3VAccelSync(ScrnInfoPtr pScrn)
462{
463    S3VPtr ps3v = S3VPTR(pScrn);
464
465    WAITIDLE();
466}
467
468#ifdef HAVE_XAA_H
469static void
470S3VEngineReset(ScrnInfoPtr pScrn)
471{
472    S3VPtr ps3v = S3VPTR(pScrn);
473
474    ps3v->SrcBaseY = 0;
475    ps3v->DestBaseY = 0;
476    ps3v->Stride = pScrn->displayWidth * pScrn->bitsPerPixel >> 3;
477
478    switch(pScrn->bitsPerPixel) {
479    case 8: 	ps3v->CommonCmd = DRAW | DST_8BPP;
480		ps3v->FullPlaneMask = 0x000000ff;
481		ps3v->bltbug_width1 = 51;
482		ps3v->bltbug_width2 = 64;
483		break;
484    case 16: 	ps3v->CommonCmd = DRAW | DST_16BPP;
485		ps3v->FullPlaneMask = 0x0000ffff;
486		ps3v->bltbug_width1 = 26;
487		ps3v->bltbug_width2 = 32;
488		break;
489    case 24: 	ps3v->CommonCmd = DRAW | DST_24BPP;
490		ps3v->FullPlaneMask = 0x00ffffff;
491		ps3v->bltbug_width1 = 16;
492		ps3v->bltbug_width2 = 22;
493		break;
494    }
495
496
497    WAITFIFO(5);
498    OUTREG(SRC_BASE, 0);
499    OUTREG(DEST_BASE, 0);
500    OUTREG(DEST_SRC_STR, ps3v->Stride | (ps3v->Stride << 16));
501
502    OUTREG(CLIP_L_R, ((0) << 16) | ps3v->Width);
503    OUTREG(CLIP_T_B, ((0) << 16) | ps3v->ScissB);
504}
505
506
507static void
508S3VWriteMask(
509   CARD32 *dstBase,
510   int dwords
511){
512  /* on alphas, be sure to call this with MapBaseDense, not MapBase! */
513   int numLeft;
514   CARD32 *dst = dstBase;
515
516   while(dwords >= 8192) {
517	numLeft = 8192;
518	while(numLeft) {
519	  dst[0] = ~0; dst[1] = ~0;
520	  dst[2] = ~0; dst[3] = ~0;
521	  dst += 4;
522	  numLeft -= 4;
523	}
524	dwords -= 8192;
525	dst = dstBase;
526   }
527   while(dwords >= 4) {
528	dst[0] = ~0; dst[1] = ~0;
529	dst[2] = ~0; dst[3] = ~0;
530	dst += 4;
531	dwords -= 4;
532   }
533   if(!dwords) return;
534   dst[0] = ~0;
535   if(dwords == 1) return;
536   dst[1] = ~0;
537   if(dwords == 2) return;
538   dst[2] = ~0;
539
540   return;
541}
542
543
544	/************************\
545	|  Solid Filled Rects    |
546	\************************/
547
548static void
549S3VSetupForSolidFill(
550   ScrnInfoPtr pScrn,
551   int color, int rop,
552   unsigned int planemask
553){
554    S3VPtr ps3v = S3VPTR(pScrn);
555    int mix;
556
557    mix = XAAHelpSolidROP(pScrn, &color, planemask, &rop);
558
559    ps3v->AccelCmd = ps3v->CommonCmd | (rop << 17) |
560			CMD_XP | CMD_YP | CMD_AUTOEXEC | CMD_BITBLT;
561
562    if(mix & ROP_SRC) {
563	ps3v->AccelCmd |= MIX_CPUDATA | CMD_ITA_DWORD | MIX_MONO_SRC;
564	ps3v->AccelInfoRec->SubsequentSolidFillRect =
565		S3VSubsequentSolidFillRectPlaneMask;
566	ps3v->AccelInfoRec->SubsequentSolidHorVertLine =
567		S3VSubsequentSolidHorVertLinePlaneMask;
568	WAITFIFO(5);
569	OUTREG(SRC_FG_CLR, planemask);
570    } else {
571	ps3v->AccelInfoRec->SubsequentSolidFillRect =
572		S3VSubsequentSolidFillRect;
573	ps3v->AccelInfoRec->SubsequentSolidHorVertLine =
574		S3VSubsequentSolidHorVertLine;
575	WAITFIFO(4);
576    }
577
578    if(mix & ROP_PAT) {
579	ps3v->AccelCmd |= MIX_MONO_PATT;
580	OUTREG(PAT_FG_CLR, color);
581	OUTREG(MONO_PAT_0, ~0);
582	OUTREG(MONO_PAT_1, ~0);
583    }
584
585    OUTREG(CMD_SET, ps3v->AccelCmd);
586}
587
588
589void
590S3VSubsequentSolidFillRect(
591   ScrnInfoPtr pScrn,
592   int x, int y,
593   int w, int h
594){
595    S3VPtr ps3v = S3VPTR(pScrn);
596
597    CHECK_DEST_BASE(y,h);
598
599    WAITFIFO(2);
600    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
601    WAITCMD();
602    OUTREG(RDEST_XY, (x << 16) | y);
603}
604
605
606void
607S3VSubsequentSolidFillRectPlaneMask(
608   ScrnInfoPtr pScrn,
609   int x, int y,
610   int w, int h
611){
612    S3VPtr ps3v = S3VPTR(pScrn);
613    int dwords;
614
615    CHECK_DEST_BASE(y,h);
616
617    dwords = ((w + 31) >> 5) * h;
618
619    WAITFIFO(2);
620    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
621    WAITCMD();
622    OUTREG(RDEST_XY, (x << 16) | y);
623    S3VWriteMask((CARD32*)ps3v->MapBaseDense, dwords);
624}
625
626
627	/**************************\
628	|  Screen to Screen Copies |
629	\**************************/
630
631static void
632S3VSetupForScreenToScreenCopy(
633   ScrnInfoPtr pScrn,
634   int xdir, int ydir,
635   int rop,
636   unsigned int planemask,
637   int trans
638){
639    S3VPtr ps3v = S3VPTR(pScrn);
640
641    planemask &= ps3v->FullPlaneMask;
642    ps3v->AccelCmd = ps3v->CommonCmd | CMD_AUTOEXEC | CMD_BITBLT;
643
644    if(planemask != ps3v->FullPlaneMask) {
645        ps3v->AccelCmd |= (XAAGetCopyROP_PM(rop) << 17) | MIX_MONO_PATT;
646	WAITFIFO(4);
647	OUTREG(PAT_FG_CLR, planemask);
648	OUTREG(MONO_PAT_0, ~0);
649	OUTREG(MONO_PAT_1, ~0);
650        }
651    else {
652        ps3v->AccelCmd |= XAAGetCopyROP(rop) << 17;
653	WAITFIFO(1);
654        }
655    if(xdir == 1) ps3v->AccelCmd |= CMD_XP;
656    if(ydir == 1) ps3v->AccelCmd |= CMD_YP;
657
658    OUTREG(CMD_SET, ps3v->AccelCmd);
659}
660
661
662static void
663S3VSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
664        int x2, int y2, int w, int h)
665{
666    S3VPtr ps3v = S3VPTR(pScrn);
667
668    CHECK_SRC_BASE(y1,h);
669    CHECK_DEST_BASE(y2,h);
670
671    w--;
672
673    if(!(ps3v->AccelCmd & CMD_YP)) {
674	y1 += h - 1; y2 += h - 1;
675    }
676
677    if(!(ps3v->AccelCmd & CMD_XP)) {
678	x1 += w; x2 += w;
679    }
680
681    WAITFIFO(3);
682    OUTREG(RWIDTH_HEIGHT, (w << 16) | h);
683    OUTREG(RSRC_XY, (x1 << 16) | y1);
684    WAITCMD();
685    OUTREG(RDEST_XY, (x2 << 16) | y2);
686}
687
688
689	/*********************\
690	|  8x8 Pattern fills  |
691	\*********************/
692
693
694static void
695S3VSetupForMono8x8PatternFill(
696    ScrnInfoPtr pScrn,
697    int patx, int paty,
698    int fg, int bg,
699    int rop, unsigned int planemask
700){
701    S3VPtr ps3v = S3VPTR(pScrn);
702    int mix;
703
704    mix = XAAHelpPatternROP(pScrn, &fg, &bg, planemask, &rop);
705
706    ps3v->AccelCmd = ps3v->CommonCmd | (rop << 17) |
707			CMD_XP | CMD_YP | CMD_AUTOEXEC | CMD_BITBLT;
708
709    if(mix & ROP_SRC) {
710 	ps3v->AccelCmd |= MIX_CPUDATA | CMD_ITA_DWORD | MIX_MONO_SRC;
711	ps3v->AccelInfoRec->SubsequentMono8x8PatternFillRect =
712		S3VSubsequentMono8x8PatternFillRectPlaneMask;
713	WAITFIFO(6);
714	OUTREG(SRC_FG_CLR, planemask);
715    } else {
716	ps3v->AccelInfoRec->SubsequentMono8x8PatternFillRect =
717		S3VSubsequentMono8x8PatternFillRect;
718	WAITFIFO(5);
719    }
720
721    if(mix & ROP_PAT) {
722	ps3v->AccelCmd |= MIX_MONO_PATT;
723	OUTREG(PAT_FG_CLR, fg);
724	OUTREG(PAT_BG_CLR, bg);
725	OUTREG(MONO_PAT_0, patx);
726	OUTREG(MONO_PAT_1, paty);
727    }
728
729    OUTREG(CMD_SET, ps3v->AccelCmd);
730}
731
732
733static void
734S3VSubsequentMono8x8PatternFillRect(
735    ScrnInfoPtr pScrn,
736    int patx, int paty,
737    int x, int y, int w, int h
738){
739    S3VPtr ps3v = S3VPTR(pScrn);
740
741    CHECK_DEST_BASE(y,h);
742
743    WAITFIFO(2);
744    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
745    WAITCMD();
746    OUTREG(RDEST_XY, (x << 16) | y);
747}
748
749
750static void
751S3VSubsequentMono8x8PatternFillRectPlaneMask(
752    ScrnInfoPtr pScrn,
753    int patx, int paty,
754    int x, int y, int w, int h
755){
756    S3VPtr ps3v = S3VPTR(pScrn);
757    int dwords;
758
759    CHECK_DEST_BASE(y,h);
760
761    dwords = ((w + 31) >> 5) * h;
762
763    WAITFIFO(2);
764    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
765    WAITCMD();
766    OUTREG(RDEST_XY, (x << 16) | y);
767
768    S3VWriteMask((CARD32*)ps3v->MapBaseDense, dwords);
769}
770
771	/*********************************\
772	|  CPU to Screen Color Expansion  |
773	\*********************************/
774
775
776static void
777S3VSetupForCPUToScreenColorExpand(
778    ScrnInfoPtr pScrn,
779    int fg, int bg,
780    int rop,
781    unsigned int planemask
782){
783    S3VPtr ps3v = S3VPTR(pScrn);
784
785    planemask &= ps3v->FullPlaneMask;
786    ps3v->AccelCmd = ps3v->CommonCmd | CMD_AUTOEXEC | CMD_BITBLT |
787		CMD_XP | CMD_YP | CMD_ITA_DWORD | CMD_HWCLIP |
788		MIX_CPUDATA | MIX_MONO_SRC;
789
790
791    if(planemask == ps3v->FullPlaneMask) {
792        ps3v->AccelCmd |= XAAGetCopyROP(rop) << 17;
793	WAITFIFO(3);
794    } else {
795        ps3v->AccelCmd |= (XAAGetCopyROP_PM(rop) << 17) | MIX_MONO_PATT;
796	WAITFIFO(6);
797	OUTREG(MONO_PAT_0, ~0);
798	OUTREG(MONO_PAT_1, ~0);
799        OUTREG(PAT_FG_CLR, planemask);
800    }
801
802    if(bg == -1)
803	ps3v->AccelCmd |= MIX_MONO_TRANSP;
804    else
805	OUTREG(SRC_BG_CLR, bg);
806
807    OUTREG(SRC_FG_CLR, fg);
808    OUTREG(CMD_SET, ps3v->AccelCmd);
809}
810
811
812void
813S3VSubsequentCPUToScreenColorExpand(
814    ScrnInfoPtr pScrn,
815    int x, int y,
816    int w, int h,
817    int skipleft
818){
819    S3VPtr ps3v = S3VPTR(pScrn);
820
821    CHECK_DEST_BASE(y,h);
822    WAITFIFO(3);
823    OUTREG(CLIP_L_R, ((x + skipleft) << 16) | 0xffff);
824    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
825    WAITCMD();
826    OUTREG(RDEST_XY, (x << 16) | y);
827}
828
829
830    /****************\
831    |  Image Writes  |
832    \****************/
833
834
835static void
836S3VSetupForImageWrite(
837   ScrnInfoPtr pScrn,
838   int rop, unsigned int planemask,
839   int trans_color, int bpp, int depth
840){
841    S3VPtr ps3v = S3VPTR(pScrn);
842
843    planemask &= ps3v->FullPlaneMask;
844    ps3v->AccelCmd = ps3v->CommonCmd | CMD_AUTOEXEC | CMD_BITBLT |
845		MIX_CPUDATA | CMD_ITA_DWORD | CMD_HWCLIP | CMD_XP | CMD_YP;
846
847    if(planemask != ps3v->FullPlaneMask) {
848        ps3v->AccelCmd |= (XAAGetCopyROP_PM(rop) << 17) | MIX_MONO_PATT;
849	WAITFIFO(4);
850	OUTREG(PAT_FG_CLR, planemask);
851	OUTREG(MONO_PAT_0, ~0);
852	OUTREG(MONO_PAT_1, ~0);
853    } else {
854        ps3v->AccelCmd |= XAAGetCopyROP(rop) << 17;
855	WAITFIFO(1);
856    }
857
858    OUTREG(CMD_SET, ps3v->AccelCmd);
859}
860
861
862static void
863S3VSubsequentImageWriteRect(
864    ScrnInfoPtr pScrn,
865    int x, int y,
866    int w, int h,
867    int skipleft
868){
869    S3VPtr ps3v = S3VPTR(pScrn);
870
871    CHECK_DEST_BASE(y,h);
872
873    WAITFIFO(3);
874    OUTREG(CLIP_L_R, ((x + skipleft) << 16) | 0xffff);
875    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
876    WAITCMD();
877    OUTREG(RDEST_XY, (x << 16) | y);
878}
879
880
881	/***********\
882	|   Lines   |
883	\***********/
884
885
886#if 0   /* Some line funcs are disabled at the moment */
887
888static void
889S3VPolylinesThinSolidWrapper(
890   DrawablePtr     pDraw,
891   GCPtr           pGC,
892   int             mode,
893   int             npt,
894   DDXPointPtr     pPts
895){
896    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
897    S3VPtr ps3v = S3VPTR(infoRec->pScrn);
898    ps3v->CurrentGC = pGC;
899    /* fb support */
900    ps3v->CurrentDrawable = pDraw;
901    if(infoRec->NeedToSync)
902	S3VAccelSync(infoRec->pScrn);
903    XAAPolyLines(pDraw, pGC, mode, npt, pPts);
904}
905
906static void
907S3VPolySegmentThinSolidWrapper(
908   DrawablePtr     pDraw,
909   GCPtr           pGC,
910   int             nseg,
911   xSegment        *pSeg
912){
913    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
914    S3VPtr ps3v = S3VPTR(infoRec->pScrn);
915    ps3v->CurrentGC = pGC;
916    /* fb support */
917    ps3v->CurrentDrawable = pDraw;
918    if(infoRec->NeedToSync)
919	S3VAccelSync(infoRec->pScrn);
920    XAAPolySegment(pDraw, pGC, nseg, pSeg);
921}
922
923#endif
924
925static void
926S3VSubsequentSolidHorVertLine(
927    ScrnInfoPtr pScrn,
928    int x, int y,
929    int len, int dir
930){
931    S3VPtr ps3v = S3VPTR(pScrn);
932    int w, h;
933
934    if(dir == DEGREES_0) {
935	w = len; h = 1;
936    } else {
937	w = 1; h = len;
938    }
939
940    CHECK_DEST_BASE(y,h);
941
942    WAITFIFO(2);
943    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
944    WAITCMD();
945    OUTREG(RDEST_XY, (x << 16) | y);
946}
947
948static void
949S3VSubsequentSolidHorVertLinePlaneMask(
950    ScrnInfoPtr pScrn,
951    int x, int y,
952    int len, int dir
953){
954    S3VPtr ps3v = S3VPTR(pScrn);
955    int w, h, dwords;
956
957    if(dir == DEGREES_0) {
958	w = len; h = 1; dwords = (len + 31) >> 5;
959    } else {
960	w = 1; h = len; dwords = len;
961    }
962
963    CHECK_DEST_BASE(y,h);
964
965    WAITFIFO(2);
966    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
967    WAITCMD();
968    OUTREG(RDEST_XY, (x << 16) | y);
969
970    S3VWriteMask((CARD32*)ps3v->MapBaseDense, dwords);
971}
972
973#endif
974
975void
976S3VWaitFifoGX2(S3VPtr ps3v, int slots )
977{
978  if(ps3v->NoPCIRetry)
979    while(((INREG(SUBSYS_STAT_REG) >> 9) & 0x60) < slots){}
980}
981
982
983
984void
985S3VWaitFifoMain(S3VPtr ps3v, int slots )
986{
987  if(ps3v->NoPCIRetry)
988    while(((INREG(SUBSYS_STAT_REG) >> 8) & 0x1f) < slots){}
989}
990
991
992void
993S3VWaitCmdGX2(S3VPtr ps3v)
994{
995  while(((INREG(ADV_FUNC_CNTR) >> 6) & 0x1f) != 16){}
996}
997
998
999void
1000S3VWaitDummy(S3VPtr ps3v)
1001{
1002  /* do nothing */
1003}
1004
1005/*EOF*/
1006
1007