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