s3v_accel.c revision 84fd5825
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, 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
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#ifdef HAVE_XAA_H
544
545	/************************\
546	|  Solid Filled Rects    |
547	\************************/
548
549static void
550S3VSetupForSolidFill(
551   ScrnInfoPtr pScrn,
552   int color, int rop,
553   unsigned int planemask
554){
555    S3VPtr ps3v = S3VPTR(pScrn);
556    int mix;
557
558    mix = XAAHelpSolidROP(pScrn, &color, planemask, &rop);
559
560    ps3v->AccelCmd = ps3v->CommonCmd | (rop << 17) |
561			CMD_XP | CMD_YP | CMD_AUTOEXEC | CMD_BITBLT;
562
563    if(mix & ROP_SRC) {
564	ps3v->AccelCmd |= MIX_CPUDATA | CMD_ITA_DWORD | MIX_MONO_SRC;
565	ps3v->AccelInfoRec->SubsequentSolidFillRect =
566		S3VSubsequentSolidFillRectPlaneMask;
567	ps3v->AccelInfoRec->SubsequentSolidHorVertLine =
568		S3VSubsequentSolidHorVertLinePlaneMask;
569	WAITFIFO(5);
570	OUTREG(SRC_FG_CLR, planemask);
571    } else {
572	ps3v->AccelInfoRec->SubsequentSolidFillRect =
573		S3VSubsequentSolidFillRect;
574	ps3v->AccelInfoRec->SubsequentSolidHorVertLine =
575		S3VSubsequentSolidHorVertLine;
576	WAITFIFO(4);
577    }
578
579    if(mix & ROP_PAT) {
580	ps3v->AccelCmd |= MIX_MONO_PATT;
581	OUTREG(PAT_FG_CLR, color);
582	OUTREG(MONO_PAT_0, ~0);
583	OUTREG(MONO_PAT_1, ~0);
584    }
585
586    OUTREG(CMD_SET, ps3v->AccelCmd);
587}
588
589
590void
591S3VSubsequentSolidFillRect(
592   ScrnInfoPtr pScrn,
593   int x, int y,
594   int w, int h
595){
596    S3VPtr ps3v = S3VPTR(pScrn);
597
598    CHECK_DEST_BASE(y,h);
599
600    WAITFIFO(2);
601    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
602    WAITCMD();
603    OUTREG(RDEST_XY, (x << 16) | y);
604}
605
606
607void
608S3VSubsequentSolidFillRectPlaneMask(
609   ScrnInfoPtr pScrn,
610   int x, int y,
611   int w, int h
612){
613    S3VPtr ps3v = S3VPTR(pScrn);
614    int dwords;
615
616    CHECK_DEST_BASE(y,h);
617
618    dwords = ((w + 31) >> 5) * h;
619
620    WAITFIFO(2);
621    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
622    WAITCMD();
623    OUTREG(RDEST_XY, (x << 16) | y);
624    S3VWriteMask((CARD32*)ps3v->MapBaseDense, dwords);
625}
626
627
628	/**************************\
629	|  Screen to Screen Copies |
630	\**************************/
631
632static void
633S3VSetupForScreenToScreenCopy(
634   ScrnInfoPtr pScrn,
635   int xdir, int ydir,
636   int rop,
637   unsigned int planemask,
638   int trans
639){
640    S3VPtr ps3v = S3VPTR(pScrn);
641
642    planemask &= ps3v->FullPlaneMask;
643    ps3v->AccelCmd = ps3v->CommonCmd | CMD_AUTOEXEC | CMD_BITBLT;
644
645    if(planemask != ps3v->FullPlaneMask) {
646        ps3v->AccelCmd |= (XAAGetCopyROP_PM(rop) << 17) | MIX_MONO_PATT;
647	WAITFIFO(4);
648	OUTREG(PAT_FG_CLR, planemask);
649	OUTREG(MONO_PAT_0, ~0);
650	OUTREG(MONO_PAT_1, ~0);
651        }
652    else {
653        ps3v->AccelCmd |= XAAGetCopyROP(rop) << 17;
654	WAITFIFO(1);
655        }
656    if(xdir == 1) ps3v->AccelCmd |= CMD_XP;
657    if(ydir == 1) ps3v->AccelCmd |= CMD_YP;
658
659    OUTREG(CMD_SET, ps3v->AccelCmd);
660}
661
662
663static void
664S3VSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
665        int x2, int y2, int w, int h)
666{
667    S3VPtr ps3v = S3VPTR(pScrn);
668
669    CHECK_SRC_BASE(y1,h);
670    CHECK_DEST_BASE(y2,h);
671
672    w--;
673
674    if(!(ps3v->AccelCmd & CMD_YP)) {
675	y1 += h - 1; y2 += h - 1;
676    }
677
678    if(!(ps3v->AccelCmd & CMD_XP)) {
679	x1 += w; x2 += w;
680    }
681
682    WAITFIFO(3);
683    OUTREG(RWIDTH_HEIGHT, (w << 16) | h);
684    OUTREG(RSRC_XY, (x1 << 16) | y1);
685    WAITCMD();
686    OUTREG(RDEST_XY, (x2 << 16) | y2);
687}
688
689
690	/*********************\
691	|  8x8 Pattern fills  |
692	\*********************/
693
694
695static void
696S3VSetupForMono8x8PatternFill(
697    ScrnInfoPtr pScrn,
698    int patx, int paty,
699    int fg, int bg,
700    int rop, unsigned int planemask
701){
702    S3VPtr ps3v = S3VPTR(pScrn);
703    int mix;
704
705    mix = XAAHelpPatternROP(pScrn, &fg, &bg, planemask, &rop);
706
707    ps3v->AccelCmd = ps3v->CommonCmd | (rop << 17) |
708			CMD_XP | CMD_YP | CMD_AUTOEXEC | CMD_BITBLT;
709
710    if(mix & ROP_SRC) {
711 	ps3v->AccelCmd |= MIX_CPUDATA | CMD_ITA_DWORD | MIX_MONO_SRC;
712	ps3v->AccelInfoRec->SubsequentMono8x8PatternFillRect =
713		S3VSubsequentMono8x8PatternFillRectPlaneMask;
714	WAITFIFO(6);
715	OUTREG(SRC_FG_CLR, planemask);
716    } else {
717	ps3v->AccelInfoRec->SubsequentMono8x8PatternFillRect =
718		S3VSubsequentMono8x8PatternFillRect;
719	WAITFIFO(5);
720    }
721
722    if(mix & ROP_PAT) {
723	ps3v->AccelCmd |= MIX_MONO_PATT;
724	OUTREG(PAT_FG_CLR, fg);
725	OUTREG(PAT_BG_CLR, bg);
726	OUTREG(MONO_PAT_0, patx);
727	OUTREG(MONO_PAT_1, paty);
728    }
729
730    OUTREG(CMD_SET, ps3v->AccelCmd);
731}
732
733
734static void
735S3VSubsequentMono8x8PatternFillRect(
736    ScrnInfoPtr pScrn,
737    int patx, int paty,
738    int x, int y, int w, int h
739){
740    S3VPtr ps3v = S3VPTR(pScrn);
741
742    CHECK_DEST_BASE(y,h);
743
744    WAITFIFO(2);
745    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
746    WAITCMD();
747    OUTREG(RDEST_XY, (x << 16) | y);
748}
749
750
751static void
752S3VSubsequentMono8x8PatternFillRectPlaneMask(
753    ScrnInfoPtr pScrn,
754    int patx, int paty,
755    int x, int y, int w, int h
756){
757    S3VPtr ps3v = S3VPTR(pScrn);
758    int dwords;
759
760    CHECK_DEST_BASE(y,h);
761
762    dwords = ((w + 31) >> 5) * h;
763
764    WAITFIFO(2);
765    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
766    WAITCMD();
767    OUTREG(RDEST_XY, (x << 16) | y);
768
769    S3VWriteMask((CARD32*)ps3v->MapBaseDense, dwords);
770}
771
772	/*********************************\
773	|  CPU to Screen Color Expansion  |
774	\*********************************/
775
776
777static void
778S3VSetupForCPUToScreenColorExpand(
779    ScrnInfoPtr pScrn,
780    int fg, int bg,
781    int rop,
782    unsigned int planemask
783){
784    S3VPtr ps3v = S3VPTR(pScrn);
785
786    planemask &= ps3v->FullPlaneMask;
787    ps3v->AccelCmd = ps3v->CommonCmd | CMD_AUTOEXEC | CMD_BITBLT |
788		CMD_XP | CMD_YP | CMD_ITA_DWORD | CMD_HWCLIP |
789		MIX_CPUDATA | MIX_MONO_SRC;
790
791
792    if(planemask == ps3v->FullPlaneMask) {
793        ps3v->AccelCmd |= XAAGetCopyROP(rop) << 17;
794	WAITFIFO(3);
795    } else {
796        ps3v->AccelCmd |= (XAAGetCopyROP_PM(rop) << 17) | MIX_MONO_PATT;
797	WAITFIFO(6);
798	OUTREG(MONO_PAT_0, ~0);
799	OUTREG(MONO_PAT_1, ~0);
800        OUTREG(PAT_FG_CLR, planemask);
801    }
802
803    if(bg == -1)
804	ps3v->AccelCmd |= MIX_MONO_TRANSP;
805    else
806	OUTREG(SRC_BG_CLR, bg);
807
808    OUTREG(SRC_FG_CLR, fg);
809    OUTREG(CMD_SET, ps3v->AccelCmd);
810}
811
812
813void
814S3VSubsequentCPUToScreenColorExpand(
815    ScrnInfoPtr pScrn,
816    int x, int y,
817    int w, int h,
818    int skipleft
819){
820    S3VPtr ps3v = S3VPTR(pScrn);
821
822    CHECK_DEST_BASE(y,h);
823    WAITFIFO(3);
824    OUTREG(CLIP_L_R, ((x + skipleft) << 16) | 0xffff);
825    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
826    WAITCMD();
827    OUTREG(RDEST_XY, (x << 16) | y);
828}
829
830
831    /****************\
832    |  Image Writes  |
833    \****************/
834
835
836static void
837S3VSetupForImageWrite(
838   ScrnInfoPtr pScrn,
839   int rop, unsigned int planemask,
840   int trans_color, int bpp, int depth
841){
842    S3VPtr ps3v = S3VPTR(pScrn);
843
844    planemask &= ps3v->FullPlaneMask;
845    ps3v->AccelCmd = ps3v->CommonCmd | CMD_AUTOEXEC | CMD_BITBLT |
846		MIX_CPUDATA | CMD_ITA_DWORD | CMD_HWCLIP | CMD_XP | CMD_YP;
847
848    if(planemask != ps3v->FullPlaneMask) {
849        ps3v->AccelCmd |= (XAAGetCopyROP_PM(rop) << 17) | MIX_MONO_PATT;
850	WAITFIFO(4);
851	OUTREG(PAT_FG_CLR, planemask);
852	OUTREG(MONO_PAT_0, ~0);
853	OUTREG(MONO_PAT_1, ~0);
854    } else {
855        ps3v->AccelCmd |= XAAGetCopyROP(rop) << 17;
856	WAITFIFO(1);
857    }
858
859    OUTREG(CMD_SET, ps3v->AccelCmd);
860}
861
862
863static void
864S3VSubsequentImageWriteRect(
865    ScrnInfoPtr pScrn,
866    int x, int y,
867    int w, int h,
868    int skipleft
869){
870    S3VPtr ps3v = S3VPTR(pScrn);
871
872    CHECK_DEST_BASE(y,h);
873
874    WAITFIFO(3);
875    OUTREG(CLIP_L_R, ((x + skipleft) << 16) | 0xffff);
876    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
877    WAITCMD();
878    OUTREG(RDEST_XY, (x << 16) | y);
879}
880
881
882	/***********\
883	|   Lines   |
884	\***********/
885
886
887#if 0   /* Some line funcs are disabled at the moment */
888
889static void
890S3VPolylinesThinSolidWrapper(
891   DrawablePtr     pDraw,
892   GCPtr           pGC,
893   int             mode,
894   int             npt,
895   DDXPointPtr     pPts
896){
897    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
898    S3VPtr ps3v = S3VPTR(infoRec->pScrn);
899    ps3v->CurrentGC = pGC;
900    /* fb support */
901    ps3v->CurrentDrawable = pDraw;
902    if(infoRec->NeedToSync)
903	S3VAccelSync(infoRec->pScrn);
904    XAAPolyLines(pDraw, pGC, mode, npt, pPts);
905}
906
907static void
908S3VPolySegmentThinSolidWrapper(
909   DrawablePtr     pDraw,
910   GCPtr           pGC,
911   int             nseg,
912   xSegment        *pSeg
913){
914    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
915    S3VPtr ps3v = S3VPTR(infoRec->pScrn);
916    ps3v->CurrentGC = pGC;
917    /* fb support */
918    ps3v->CurrentDrawable = pDraw;
919    if(infoRec->NeedToSync)
920	S3VAccelSync(infoRec->pScrn);
921    XAAPolySegment(pDraw, pGC, nseg, pSeg);
922}
923
924#endif
925
926static void
927S3VSubsequentSolidHorVertLine(
928    ScrnInfoPtr pScrn,
929    int x, int y,
930    int len, int dir
931){
932    S3VPtr ps3v = S3VPTR(pScrn);
933    int w, h;
934
935    if(dir == DEGREES_0) {
936	w = len; h = 1;
937    } else {
938	w = 1; h = len;
939    }
940
941    CHECK_DEST_BASE(y,h);
942
943    WAITFIFO(2);
944    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
945    WAITCMD();
946    OUTREG(RDEST_XY, (x << 16) | y);
947}
948
949static void
950S3VSubsequentSolidHorVertLinePlaneMask(
951    ScrnInfoPtr pScrn,
952    int x, int y,
953    int len, int dir
954){
955    S3VPtr ps3v = S3VPTR(pScrn);
956    int w, h, dwords;
957
958    if(dir == DEGREES_0) {
959	w = len; h = 1; dwords = (len + 31) >> 5;
960    } else {
961	w = 1; h = len; dwords = len;
962    }
963
964    CHECK_DEST_BASE(y,h);
965
966    WAITFIFO(2);
967    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
968    WAITCMD();
969    OUTREG(RDEST_XY, (x << 16) | y);
970
971    S3VWriteMask((CARD32*)ps3v->MapBaseDense, dwords);
972}
973
974#endif
975
976void
977S3VWaitFifoGX2(S3VPtr ps3v, int slots )
978{
979  if(ps3v->NoPCIRetry)
980    while(((INREG(SUBSYS_STAT_REG) >> 9) & 0x60) < slots){}
981}
982
983
984
985void
986S3VWaitFifoMain(S3VPtr ps3v, int slots )
987{
988  if(ps3v->NoPCIRetry)
989    while(((INREG(SUBSYS_STAT_REG) >> 8) & 0x1f) < slots){}
990}
991
992
993void
994S3VWaitCmdGX2(S3VPtr ps3v)
995{
996  while(((INREG(ADV_FUNC_CNTR) >> 6) & 0x1f) != 16){}
997}
998
999
1000void
1001S3VWaitDummy(S3VPtr ps3v)
1002{
1003  /* do nothing */
1004}
1005
1006/*EOF*/
1007
1008