1 /*
2  * Copyright 1992-2003 by Alan Hourihane, North Wales, UK.
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of Alan Hourihane not be used in
9  * advertising or publicity pertaining to distribution of the software without
10  * specific, written prior permission.  Alan Hourihane makes no representations
11  * about the suitability of this software for any purpose.  It is provided
12  * "as is" without express or implied warranty.
13  *
14  * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20  * PERFORMANCE OF THIS SOFTWARE.
21  *
22  * Authors:  Alan Hourihane, <alanh@fairlite.demon.co.uk>
23  *
24  * CyberBladeXP4 accelerated options.
25  */
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29 
30 #include "xf86.h"
31 #include "xf86_OSproc.h"
32 
33 #include "xf86Pci.h"
34 
35 #include "miline.h"
36 
37 #include "trident.h"
38 #include "trident_regs.h"
39 
40 #ifdef HAVE_XAA_H
41 #include "xaarop.h"
42 
43 static void XP4Sync(ScrnInfoPtr pScrn);
44 #if 0
45 static void XP4SetupForDashedLine(ScrnInfoPtr pScrn, int fg, int bg,
46 				int rop, unsigned int planemask, int length,
47     				unsigned char *pattern);
48 static void XP4SubsequentDashedBresenhamLine(ScrnInfoPtr pScrn,
49         			int x, int y, int dmaj, int dmin, int e,
50 				int len, int octant, int phase);
51 static void XP4SetupForSolidLine(ScrnInfoPtr pScrn, int color,
52 				int rop, unsigned int planemask);
53 static void XP4SubsequentSolidBresenhamLine(ScrnInfoPtr pScrn,
54         			int x, int y, int dmaj, int dmin, int e,
55 				int len, int octant);
56 #endif
57 static void XP4SubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y,
58     				int len, int dir);
59 static void XP4SetupForFillRectSolid(ScrnInfoPtr pScrn, int color,
60 				int rop, unsigned int planemask);
61 static void XP4SubsequentFillRectSolid(ScrnInfoPtr pScrn, int x,
62 				int y, int w, int h);
63 static void XP4SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn,
64 				int x1, int y1, int x2,
65 				int y2, int w, int h);
66 static void XP4SetupForScreenToScreenCopy(ScrnInfoPtr pScrn,
67 				int xdir, int ydir, int rop,
68                                 unsigned int planemask,
69 				int transparency_color);
70 static void XP4SetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
71 				int patternx, int patterny, int fg, int bg,
72 				int rop, unsigned int planemask);
73 static void XP4SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn,
74 				int patternx, int patterny, int x, int y,
75 				int w, int h);
76 static void XP4SetupForCPUToScreenColorExpandFill(
77 				ScrnInfoPtr pScrn,
78 				int fg, int bg, int rop,
79 				unsigned int planemask);
80 static void XP4SubsequentCPUToScreenColorExpandFill(
81 				ScrnInfoPtr pScrn, int x,
82 				int y, int w, int h, int skipleft);
83 
84 static int bpp;
85 static int ropcode;
86 
87 static void
XP4InitializeAccelerator(ScrnInfoPtr pScrn)88 XP4InitializeAccelerator(ScrnInfoPtr pScrn)
89 {
90     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
91     int shift;
92 
93     /* This forces updating the clipper */
94     pTrident->Clipping = TRUE;
95 
96     CHECKCLIPPING;
97 
98     switch (pScrn->bitsPerPixel) {
99 	case 8:
100 	default:		/* Muffle compiler */
101 		shift = 18;
102 		break;
103 	case 16:
104 		shift = 19;
105 		break;
106 	case 32:
107 		shift = 20;
108 		break;
109     }
110 
111     switch (pScrn->bitsPerPixel) {
112 	case 8:
113 	    bpp = 0x40;
114 	    break;
115 	case 16:
116 	    bpp = 0x41;
117 	    break;
118 	case 32:
119 	    bpp = 0x42;
120 	    break;
121     }
122     MMIO_OUT32(pTrident->IOBase, 0x2154, (pScrn->displayWidth) << shift);
123     MMIO_OUT32(pTrident->IOBase, 0x2150, (pScrn->displayWidth) << shift);
124 }
125 #endif
126 
127 Bool
XP4XaaInit(ScreenPtr pScreen)128 XP4XaaInit(ScreenPtr pScreen)
129 {
130 #ifdef HAVE_XAA_H
131     XAAInfoRecPtr infoPtr;
132     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
133     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
134 
135     if (pTrident->NoAccel)
136 	return FALSE;
137 
138     pTrident->AccelInfoRec = infoPtr = XAACreateInfoRec();
139     if (!infoPtr) return FALSE;
140 
141     infoPtr->Flags = PIXMAP_CACHE |
142 		     OFFSCREEN_PIXMAPS |
143 		     LINEAR_FRAMEBUFFER;
144 
145     pTrident->InitializeAccelerator = XP4InitializeAccelerator;
146     XP4InitializeAccelerator(pScrn);
147 
148     infoPtr->Sync = XP4Sync;
149 
150 #if 0 /* TO DO for the XP */
151     infoPtr->SolidLineFlags = NO_PLANEMASK;
152     infoPtr->SetupForSolidLine = XP4SetupForSolidLine;
153     infoPtr->SolidBresenhamLineErrorTermBits = 12;
154     infoPtr->SubsequentSolidBresenhamLine = XP4SubsequentSolidBresenhamLine;
155 
156     infoPtr->DashedLineFlags = LINE_PATTERN_MSBFIRST_LSBJUSTIFIED |
157 			       NO_PLANEMASK |
158 			       LINE_PATTERN_POWER_OF_2_ONLY;
159     infoPtr->SetupForDashedLine = XP4SetupForDashedLine;
160     infoPtr->DashedBresenhamLineErrorTermBits = 12;
161     infoPtr->SubsequentDashedBresenhamLine =
162 					XP4SubsequentDashedBresenhamLine;
163     infoPtr->DashPatternMaxLength = 16;
164 #endif
165 
166 
167     infoPtr->SolidFillFlags = NO_PLANEMASK;
168     infoPtr->SetupForSolidFill = XP4SetupForFillRectSolid;
169     infoPtr->SubsequentSolidFillRect = XP4SubsequentFillRectSolid;
170 #if 0
171     infoPtr->SubsequentSolidHorVertLine = XP4SubsequentSolidHorVertLine;
172 #endif
173 
174     infoPtr->ScreenToScreenCopyFlags = NO_PLANEMASK | NO_TRANSPARENCY;
175 
176     infoPtr->SetupForScreenToScreenCopy =
177 				XP4SetupForScreenToScreenCopy;
178     infoPtr->SubsequentScreenToScreenCopy =
179 				XP4SubsequentScreenToScreenCopy;
180 
181     infoPtr->Mono8x8PatternFillFlags =  NO_PLANEMASK |
182 					HARDWARE_PATTERN_PROGRAMMED_BITS |
183 					HARDWARE_PATTERN_SCREEN_ORIGIN |
184 					BIT_ORDER_IN_BYTE_MSBFIRST;
185 
186     infoPtr->SetupForMono8x8PatternFill =
187 				XP4SetupForMono8x8PatternFill;
188     infoPtr->SubsequentMono8x8PatternFillRect =
189 				XP4SubsequentMono8x8PatternFillRect;
190 
191 #if 0
192     infoPtr->CPUToScreenColorExpandFillFlags = NO_PLANEMASK |
193 					BIT_ORDER_IN_BYTE_MSBFIRST;
194     infoPtr->ColorExpandBase = pTrident->D3Base;
195     infoPtr->ColorExpandRange = pScrn->displayWidth;
196 
197     infoPtr->SetupForCPUToScreenColorExpandFill =
198 			XP4SetupForCPUToScreenColorExpandFill;
199     infoPtr->SubsequentCPUToScreenColorExpandFill =
200 			XP4SubsequentCPUToScreenColorExpandFill;
201 #endif
202 
203     return(XAAInit(pScreen, infoPtr));
204 #else
205     return FALSE;
206 #endif
207 }
208 
209 #ifdef HAVE_XAA_H
210 static void
XP4Sync(ScrnInfoPtr pScrn)211 XP4Sync(ScrnInfoPtr pScrn)
212 {
213     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
214     int count = 0, timeout = 0;
215     int busy;
216 
217     for (;;) {
218 	BLTBUSY(busy);
219 	if (busy != GE_BUSY) {
220 	    return;
221 	}
222 	count++;
223 	if (count == 10000000) {
224 	    ErrorF("XP: BitBLT engine time-out.\n");
225 	    count = 9990000;
226 	    timeout++;
227 	    if (timeout == 4) {
228 		/* Reset BitBLT Engine */
229 		TGUI_STATUS(0x00);
230 		return;
231 	    }
232 	}
233     }
234 }
235 
236 static void
XP4SetupForScreenToScreenCopy(ScrnInfoPtr pScrn,int xdir,int ydir,int rop,unsigned int planemask,int transparency_color)237 XP4SetupForScreenToScreenCopy(ScrnInfoPtr pScrn,
238 				int xdir, int ydir, int rop,
239 				unsigned int planemask, int transparency_color)
240 {
241     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
242     int dst = 0;
243 
244     pTrident->BltScanDirection = 0;
245     if (xdir < 0) pTrident->BltScanDirection |= XNEG;
246     if (ydir < 0) pTrident->BltScanDirection |= YNEG;
247 
248     REPLICATE(transparency_color);
249     if (transparency_color != -1) {
250 	dst |= 3<<16;
251     	MMIO_OUT32(pTrident->IOBase, 0x2134, transparency_color);
252     }
253 
254     ropcode = rop;
255 
256     MMIO_OUT32(pTrident->IOBase, 0x2128, pTrident->BltScanDirection | SCR2SCR);
257 }
258 
259 static void
XP4SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn,int x1,int y1,int x2,int y2,int w,int h)260 XP4SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
261 					int x2, int y2, int w, int h)
262 {
263     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
264 
265     if (pTrident->BltScanDirection & YNEG) {
266         y1 = y1 + h - 1;
267 	y2 = y2 + h - 1;
268     }
269     if (pTrident->BltScanDirection & XNEG) {
270 	x1 = x1 + w - 1;
271 	x2 = x2 + w - 1;
272     }
273     MMIO_OUT32(pTrident->IOBase, 0x2138, x2<<16 | y2);
274     MMIO_OUT32(pTrident->IOBase, 0x213C, x1<<16 | y1);
275     MMIO_OUT32(pTrident->IOBase, 0x2140, w<<16 | h);
276     XP4Sync(pScrn);
277     MMIO_OUT32(pTrident->IOBase, 0x2124, XAAGetCopyROP(ropcode) << 24 | bpp << 8 | 1);
278 }
279 
280 #if 0
281 static void
282 XP4SetupForSolidLine(ScrnInfoPtr pScrn, int color,
283 					 int rop, unsigned int planemask)
284 {
285     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
286 
287     pTrident->BltScanDirection = 0;
288     REPLICATE(color);
289     TGUI_FMIX(XAAPatternROP[rop]);
290     if (pTrident->Chipset >= PROVIDIA9685) {
291     	TGUI_FPATCOL(color);
292     } else {
293     	TGUI_FCOLOUR(color);
294     }
295 }
296 
297 static void
298 XP4SubsequentSolidBresenhamLine( ScrnInfoPtr pScrn,
299         int x, int y, int dmaj, int dmin, int e, int len, int octant)
300 {
301     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
302     int tmp = pTrident->BltScanDirection;
303 
304     if (octant & YMAJOR) tmp |= YMAJ;
305     if (octant & XDECREASING) tmp |= XNEG;
306     if (octant & YDECREASING) tmp |= YNEG;
307     TGUI_DRAWFLAG(SOLIDFILL | STENCIL | tmp);
308     XP_SRC_XY(dmin-dmaj,dmin);
309     XP_DEST_XY(x,y);
310     XP_DIM_XY(dmin+e,len);
311     TGUI_COMMAND(GE_BRESLINE);
312     XP4Sync(pScrn);
313 }
314 #endif
315 
316 static void
XP4SubsequentSolidHorVertLine(ScrnInfoPtr pScrn,int x,int y,int len,int dir)317 XP4SubsequentSolidHorVertLine(
318     ScrnInfoPtr pScrn,
319     int x, int y,
320     int len, int dir
321 ){
322     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
323 
324     TGUI_DRAWFLAG(SOLIDFILL);
325     if (dir == DEGREES_0) {
326     	XP_DIM_XY(len,1);
327     	XP_DEST_XY(x,y);
328     } else {
329     	XP_DIM_XY(1,len);
330     	XP_DEST_XY(x,y);
331     }
332     TGUI_COMMAND(GE_BLT);
333     XP4Sync(pScrn);
334 }
335 
336 #if 0
337 void
338 XP4SetupForDashedLine(
339     ScrnInfoPtr pScrn,
340     int fg, int bg, int rop,
341     unsigned int planemask,
342     int length,
343     unsigned char *pattern
344 ){
345     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
346     CARD32 *DashPattern = (CARD32*)pattern;
347     CARD32 NiceDashPattern = DashPattern[0];
348 
349     NiceDashPattern = *((CARD16 *)pattern) & ((1<<length) - 1);
350     switch(length) {
351 	case 2:	NiceDashPattern |= NiceDashPattern << 2;
352 	case 4:	NiceDashPattern |= NiceDashPattern << 4;
353 	case 8:	NiceDashPattern |= NiceDashPattern << 8;
354     }
355     pTrident->BltScanDirection = 0;
356     REPLICATE(fg);
357     if (pTrident->Chipset >= PROVIDIA9685) {
358 	TGUI_FPATCOL(fg);
359     	if (bg == -1) {
360 	    pTrident->BltScanDirection |= 1<<12;
361     	    TGUI_BPATCOL(~fg);
362     	} else {
363     	    REPLICATE(bg);
364     	    TGUI_BPATCOL(bg);
365     	}
366     } else {
367     	TGUI_FCOLOUR(fg);
368     	if (bg == -1) {
369 	    pTrident->BltScanDirection |= 1<<12;
370     	    TGUI_BCOLOUR(~fg);
371     	} else {
372     	    REPLICATE(bg);
373     	    TGUI_BCOLOUR(bg);
374     	}
375     }
376     TGUI_FMIX(XAAPatternROP[rop]);
377     pTrident->LinePattern = NiceDashPattern;
378 }
379 
380 void
381 XP4SubsequentDashedBresenhamLine(ScrnInfoPtr pScrn,
382         int x, int y, int dmaj, int dmin, int e, int len, int octant, int phase)
383 {
384     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
385     int tmp = pTrident->BltScanDirection;
386 
387     if (octant & YMAJOR) tmp |= YMAJ;
388     if (octant & XDECREASING) tmp |= XNEG;
389     if (octant & YDECREASING) tmp |= YNEG;
390 
391     TGUI_STYLE(((pTrident->LinePattern >> phase) |
392 		(pTrident->LinePattern << (16-phase))) & 0x0000FFFF);
393     TGUI_DRAWFLAG(STENCIL | tmp);
394     XP_SRC_XY(dmin-dmaj,dmin);
395     XP_DEST_XY(x,y);
396     XP_DIM_XY(e+dmin,len);
397     TGUI_COMMAND(GE_BRESLINE);
398     XP4Sync(pScrn);
399 }
400 #endif
401 
402 static void
XP4SetupForFillRectSolid(ScrnInfoPtr pScrn,int color,int rop,unsigned int planemask)403 XP4SetupForFillRectSolid(ScrnInfoPtr pScrn, int color,
404 				    int rop, unsigned int planemask)
405 {
406     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
407 
408     ropcode = rop;
409 
410     REPLICATE(color);
411     MMIO_OUT32(pTrident->IOBase, 0x2158, color);
412     MMIO_OUT32(pTrident->IOBase, 0x2128, 1<<14);
413 }
414 
415 static void
XP4SubsequentFillRectSolid(ScrnInfoPtr pScrn,int x,int y,int w,int h)416 XP4SubsequentFillRectSolid(ScrnInfoPtr pScrn, int x, int y, int w, int h)
417 {
418     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
419 
420     MMIO_OUT32(pTrident->IOBase, 0x2138, x<<16 | y);
421     MMIO_OUT32(pTrident->IOBase, 0x2140, w<<16 | h);
422     XP4Sync(pScrn);
423     MMIO_OUT32(pTrident->IOBase, 0x2124, XAAGetPatternROP(ropcode) << 24 | bpp << 8 | 2);
424 }
425 
426 #if 1
MoveDWORDS(register CARD32 * dest,register CARD32 * src,register int dwords)427 static void MoveDWORDS(
428    register CARD32* dest,
429    register CARD32* src,
430    register int dwords )
431 {
432      while(dwords & ~0x03) {
433 	*dest = *src;
434 	*(dest + 1) = *(src + 1);
435 	*(dest + 2) = *(src + 2);
436 	*(dest + 3) = *(src + 3);
437 	src += 4;
438 	dest += 4;
439 	dwords -= 4;
440      }
441      if (!dwords) return;
442      *dest = *src;
443      dest += 1;
444      src += 1;
445      if (dwords == 1) return;
446      *dest = *src;
447      dest += 1;
448      src += 1;
449      if (dwords == 2) return;
450      *dest = *src;
451      dest += 1;
452      src += 1;
453 }
454 #endif
455 
456 #if 1
MoveDWORDS_FixedBase(register CARD32 * dest,register CARD32 * src,register int dwords)457 static void MoveDWORDS_FixedBase(
458    register CARD32* dest,
459    register CARD32* src,
460    register int dwords )
461 {
462      while(dwords & ~0x03) {
463 	 *dest = *src;
464 	 *dest = *(src + 1);
465 	 *dest = *(src + 2);
466 	 *dest = *(src + 3);
467 	 dwords -= 4;
468 	 src += 4;
469      }
470 
471      if(!dwords) return;
472      *dest = *src;
473      if(dwords == 1) return;
474      *dest = *(src + 1);
475      if(dwords == 2) return;
476      *dest = *(src + 2);
477 }
478 #endif
479 
480 
481 static void
XP4SetupForMono8x8PatternFill(ScrnInfoPtr pScrn,int patternx,int patterny,int fg,int bg,int rop,unsigned int planemask)482 XP4SetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
483 					   int patternx, int patterny,
484 					   int fg, int bg, int rop,
485 					   unsigned int planemask)
486 {
487     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
488     int drawflag = 0;
489 
490     REPLICATE(fg);
491     MMIO_OUT32(pTrident->IOBase, 0x2158, fg);
492 
493     if (bg == -1) {
494 	drawflag |= 1<<12;
495    	MMIO_OUT32(pTrident->IOBase, 0x215C, ~fg);
496     } else {
497     	REPLICATE(bg);
498    	MMIO_OUT32(pTrident->IOBase, 0x215C, bg);
499     }
500 
501     ropcode = rop;
502 
503     drawflag |= 7<<18;
504     TGUI_DRAWFLAG(PATMONO | drawflag);
505 }
506 
507 static void
XP4SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn,int patternx,int patterny,int x,int y,int w,int h)508 XP4SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn,
509 				   int patternx, int patterny,
510 				   int x, int y,
511 				   int w, int h)
512 {
513     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
514 
515     MMIO_OUT32(pTrident->IOBase, 0x2180, patternx);
516     MMIO_OUT32(pTrident->IOBase, 0x2184, patterny);
517     MMIO_OUT32(pTrident->IOBase, 0x2138, x<<16 | y);
518     MMIO_OUT32(pTrident->IOBase, 0x2140, w<<16 | h);
519     XP4Sync(pScrn);
520     MMIO_OUT32(pTrident->IOBase, 0x2124, XAAGetPatternROP(ropcode) << 24 | bpp << 8 | 2);
521 }
522 
523 #if 1
524 static void
XP4SetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,int fg,int bg,int rop,unsigned int planemask)525 XP4SetupForCPUToScreenColorExpandFill(
526 	ScrnInfoPtr pScrn,
527 	int fg, int bg,
528 	int rop,
529 	unsigned int planemask
530 ){
531     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
532 
533     ropcode = XAAGetCopyROP(rop);
534 #if 0
535     TGUI_FMIX(XAACopyROP[rop]);
536 #endif
537     if (bg == -1) {
538     TGUI_DRAWFLAG(SRCMONO | 1<<12);
539     	REPLICATE(fg);
540 	TGUI_FCOLOUR(fg);
541     } else {
542     TGUI_DRAWFLAG(SRCMONO);
543     	REPLICATE(fg);
544     	REPLICATE(bg);
545 	TGUI_FCOLOUR(fg);
546 	TGUI_BCOLOUR(bg);
547     }
548 }
549 
550 static void
XP4SubsequentCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,int x,int y,int w,int h,int skipleft)551 XP4SubsequentCPUToScreenColorExpandFill(
552 	ScrnInfoPtr pScrn,
553 	int x, int y, int w, int h,
554 	int skipleft
555 ){
556     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
557 
558     MMIO_OUT32(pTrident->IOBase, 0x2138, x<<16 | y);
559     MMIO_OUT32(pTrident->IOBase, 0x2140, w<<16 | h);
560     XP4Sync(pScrn);
561     MMIO_OUT32(pTrident->IOBase, 0x2124, ropcode << 24 | bpp << 8 | 2);
562 }
563 #endif
564 #endif
565