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