1
2 /*
3 * Copyright 1997-2000 by Robin Cutshaw <robin@XFree86.Org>
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of Robin Cutshaw not be used in
10 * advertising or publicity pertaining to distribution of the software without
11 * specific, written prior permission. Robin Cutshaw makes no representations
12 * about the suitability of this software for any purpose. It is provided
13 * "as is" without express or implied warranty.
14 *
15 * ROBIN CUTSHAW DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL ROBIN CUTSHAW BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21 * PERFORMANCE OF THIS SOFTWARE.
22 *
23 */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29
30 #include "xf86fbman.h"
31 #include "miline.h"
32 #include "servermd.h"
33
34 #include "xf86.h"
35 #include "xf86_OSproc.h"
36 #include "xf86Pci.h"
37
38 #include "i128.h"
39 #include "i128reg.h"
40
41 #ifdef HAVE_XAA_H
42 #include "xaalocal.h"
43
44 static void I128BitBlit(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2,
45 int w, int h);
46 static void I128SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir,
47 int ydir, int rop, unsigned planemask, int transparency_color);
48 static void I128SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
49 int x2, int y2, int w, int h);
50 static void I128SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
51 unsigned planemask);
52 static void I128SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w,
53 int h);
54 static void I128SubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1,
55 int x2, int y2, int flags);
56 static void I128SetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1,
57 int x2, int y2);
58 static void I128FillSolidRects(ScrnInfoPtr pScrn, int fg, int rop,
59 unsigned int planemask, int nBox, register BoxPtr pBoxI);
60 #if 0
61 static void I128ScreenToScreenBitBlt(ScrnInfoPtr pScrn, int nbox,
62 DDXPointPtr pptSrc, BoxPtr pbox, int xdir, int ydir, int alu,
63 unsigned planemask);
64 #endif
65
66 #endif
67 #define ENG_PIPELINE_READY() { while (pI128->mem.rbase_a[BUSY] & BUSY_BUSY) ; }
68 #define ENG_DONE() { while (pI128->mem.rbase_a[FLOW] & (FLOW_DEB | FLOW_MCB | FLOW_PRV)) ;}
69
70
71 /* pre-shift rops and just or in as needed */
72
73 static const CARD32 i128alu[16] =
74 {
75 CR_CLEAR<<8,
76 CR_AND<<8,
77 CR_AND_REV<<8,
78 CR_COPY<<8,
79 CR_AND_INV<<8,
80 CR_NOOP<<8,
81 CR_XOR<<8,
82 CR_OR<<8,
83 CR_NOR<<8,
84 CR_EQUIV<<8,
85 CR_INVERT<<8,
86 CR_OR_REV<<8,
87 CR_COPY_INV<<8,
88 CR_OR_INV<<8,
89 CR_NAND<<8,
90 CR_SET<<8
91 };
92 /* 8bpp 16bpp 32bpp unused */
93 static const int min_size[] = { 0x62, 0x32, 0x1A, 0x00 };
94 static const int max_size[] = { 0x80, 0x40, 0x20, 0x00 };
95 static const int split_size[] = { 0x20, 0x10, 0x08, 0x00 };
96
97
98 void
I128EngineDone(ScrnInfoPtr pScrn)99 I128EngineDone(ScrnInfoPtr pScrn)
100 {
101 I128Ptr pI128 = I128PTR(pScrn);
102 ENG_DONE();
103 }
104
105 #ifdef HAVE_XAA_H
106 static void
I128BitBlit(ScrnInfoPtr pScrn,int x1,int y1,int x2,int y2,int w,int h)107 I128BitBlit(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2, int w, int h)
108 {
109 I128Ptr pI128 = I128PTR(pScrn);
110
111 #if 0
112 if (pI128->Debug)
113 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BB %d,%d %d,%d %d,%d 0x%x/0x%x\n", x1, y1, x2, y2, w, h, pI128->cmd);
114 #endif
115
116 ENG_PIPELINE_READY();
117
118 pI128->mem.rbase_a[CMD] = pI128->cmd;
119 /*pI128->mem.rbase_a[XY3_DIR] = pI128->blitdir;*/
120
121 if (pI128->blitdir & DIR_RL_TB) {
122 x1 += w; x1--;
123 x2 += w; x2--;
124 }
125 if (pI128->blitdir & DIR_LR_BT) {
126 y1 += h; y1--;
127 y2 += h; y2--;
128 }
129
130
131
132 if (pI128->Chipset == PCI_CHIP_I128) {
133 int bppi;
134
135 static int first_time_through = 1;
136
137 /* The I128-1 has a nasty bitblit bug
138 * that occurs when dest is exactly 8 pages wide
139 */
140
141 bppi = (pI128->mem.rbase_a[BUF_CTRL] & BC_PSIZ_MSK) >> 24;
142
143 if ((w >= min_size[bppi]) && (w <= max_size[bppi])) {
144 if (first_time_through) {
145 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
146 "Using I128-1 workarounds.\n");
147 first_time_through = 0;
148 }
149
150 bppi = split_size[bppi];
151 #if 1
152 /* split method */
153
154 pI128->mem.rbase_a[XY2_WH] = (bppi<<16) | h;
155 pI128->mem.rbase_a[XY0_SRC] = (x1<<16) | y1; MB;
156 pI128->mem.rbase_a[XY1_DST] = (x2<<16) | y2; MB;
157
158 ENG_PIPELINE_READY();
159
160 w -= bppi;
161
162 if (pI128->blitdir & DIR_RL_TB) {
163 /* right to left blit */
164 x1 -= bppi;
165 x2 -= bppi;
166 } else {
167 /* left to right blit */
168 x1 += bppi;
169 x2 += bppi;
170 }
171 #else
172 /* clip method */
173 pI128->mem.rbase_a[CLPTL] = (x2<<16) | y2;
174 pI128->mem.rbase_a[CLPBR] = ((x2+w)<<16) | (y2+h);
175 w += bppi;
176 #endif
177 }
178 }
179
180 pI128->mem.rbase_a[XY2_WH] = (w<<16) | h;
181 pI128->mem.rbase_a[XY0_SRC] = (x1<<16) | y1; MB;
182 pI128->mem.rbase_a[XY1_DST] = (x2<<16) | y2; MB;
183 }
184
185 static void
I128SetupForScreenToScreenCopy(ScrnInfoPtr pScrn,int xdir,int ydir,int rop,unsigned planemask,int transparency_color)186 I128SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir,
187 int rop, unsigned planemask, int transparency_color)
188 {
189 I128Ptr pI128 = I128PTR(pScrn);
190
191 #if 0
192 if (pI128->Debug)
193 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SFSSC %d,%d %d 0x%x %d\n", xdir, ydir, rop, planemask, transparency_color);
194 #endif
195
196 ENG_PIPELINE_READY();
197
198 if (planemask == -1)
199 pI128->mem.rbase_a[MASK] = -1;
200 else switch (pI128->bitsPerPixel) {
201 case 8:
202 pI128->mem.rbase_a[MASK] = planemask |
203 (planemask<<8) |
204 (planemask<<16) |
205 (planemask<<24);
206 break;
207 case 16:
208 pI128->mem.rbase_a[MASK] = planemask | (planemask<<16);
209 break;
210 case 24:
211 case 32:
212 default:
213 pI128->mem.rbase_a[MASK] = planemask;
214 break;
215 }
216
217
218 pI128->mem.rbase_a[CLPTL] = 0x00000000;
219 pI128->mem.rbase_a[CLPBR] = (4095<<16) | 2047;
220
221 if (transparency_color != -1)
222 pI128->mem.rbase_a[BACK] = transparency_color;
223
224
225 if (xdir == -1) {
226 if (ydir == -1) pI128->blitdir = DIR_RL_BT;
227 else pI128->blitdir = DIR_RL_TB;
228 } else {
229 if (ydir == -1) pI128->blitdir = DIR_LR_BT;
230 else pI128->blitdir = DIR_LR_TB;
231 }
232 pI128->mem.rbase_a[XY3_DIR] = pI128->blitdir;
233
234 pI128->rop = i128alu[rop];
235 pI128->cmd = (transparency_color != -1 ? (CS_TRNSP<<16) : 0) |
236 pI128->rop | CO_BITBLT;
237 pI128->mem.rbase_a[CMD] = pI128->cmd;
238 }
239
240 static void
I128SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn,int x1,int y1,int x2,int y2,int w,int h)241 I128SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
242 int x2, int y2, int w, int h)
243 {
244 I128BitBlit(pScrn, x1, y1, x2, y2, w, h);
245 }
246
247 static void
I128SetupForSolidFill(ScrnInfoPtr pScrn,int color,int rop,unsigned planemask)248 I128SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, unsigned planemask)
249 {
250 I128Ptr pI128 = I128PTR(pScrn);
251
252 #if 0
253 if (pI128->Debug)
254 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SFSF color 0x%x rop 0x%x (I128rop 0x%x) pmask 0x%x\n", color, rop, i128alu[rop]>>8, planemask);
255 #endif
256
257 ENG_PIPELINE_READY();
258
259 if (planemask == -1)
260 pI128->mem.rbase_a[MASK] = -1;
261 else switch (pI128->bitsPerPixel) {
262 case 8:
263 pI128->mem.rbase_a[MASK] = planemask |
264 (planemask<<8) |
265 (planemask<<16) |
266 (planemask<<24);
267 break;
268 case 16:
269 pI128->mem.rbase_a[MASK] = planemask | (planemask<<16);
270 break;
271 case 24:
272 case 32:
273 default:
274 pI128->mem.rbase_a[MASK] = planemask;
275 break;
276 }
277
278 pI128->mem.rbase_a[FORE] = color;
279
280 pI128->clptl = pI128->mem.rbase_a[CLPTL] = 0x00000000;
281 pI128->clpbr = pI128->mem.rbase_a[CLPBR] = (4095<<16) | 2047 ;
282
283 pI128->mem.rbase_a[XY3_DIR] = pI128->blitdir = DIR_LR_TB;
284
285 pI128->rop = i128alu[rop];
286 pI128->cmd = (CS_SOLID<<16) | pI128->rop | CO_BITBLT;
287 pI128->mem.rbase_a[CMD] = pI128->cmd;
288 }
289
290 static void
I128SubsequentSolidFillRect(ScrnInfoPtr pScrn,int x,int y,int w,int h)291 I128SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
292 {
293 #if 0
294 I128Ptr pI128 = I128PTR(pScrn);
295
296 if (pI128->Debug)
297 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SSFR %d,%d %d,%d\n", x, y, w, h);
298 #endif
299 I128BitBlit(pScrn, 0, 0, x, y, w, h);
300 }
301
302 static void
I128SubsequentSolidTwoPointLine(ScrnInfoPtr pScrn,int x1,int y1,int x2,int y2,int flags)303 I128SubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1, int x2,
304 int y2, int flags)
305 {
306 I128Ptr pI128 = I128PTR(pScrn);
307
308 #if 0
309 if (pI128->Debug)
310 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "STPL I128rop 0x%x %d,%d %d,%d clip %d,%d %d,%d\n", pI128->rop, x1, y1, x2, y2, pI128->clptl>>16, pI128->clptl&0xffff, (pI128->clpbr>>16)&0xffff, pI128->clpbr&0xffff);
311 #endif
312
313 ENG_PIPELINE_READY();
314
315 pI128->mem.rbase_a[CMD] =
316 ((flags&0x0100) ? (CP_NLST<<24) : 0) |
317 (CC_CLPRECI<<21) |
318 (CS_SOLID<<16) |
319 pI128->rop |
320 CO_LINE;
321
322 pI128->mem.rbase_a[CLPTL] = pI128->clptl;
323 pI128->mem.rbase_a[CLPBR] = pI128->clpbr;
324
325 pI128->mem.rbase_a[XY0_SRC] = (x1<<16) | y1; MB;
326 pI128->mem.rbase_a[XY1_DST] = (x2<<16) | y2; MB;
327 }
328
329 static void
I128SetClippingRectangle(ScrnInfoPtr pScrn,int x1,int y1,int x2,int y2)330 I128SetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2)
331 {
332 I128Ptr pI128 = I128PTR(pScrn);
333 int tmp;
334
335 #if 0
336 if (pI128->Debug)
337 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SCR %d,%d %d,%d\n", x1, y1, x2, y2);
338 #endif
339
340 if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; }
341 if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; }
342
343 pI128->clptl = (x1<<16) | y1;
344 pI128->clpbr = (x2<<16) | y2;
345 }
346
347
348 static void
I128FillSolidRects(ScrnInfoPtr pScrn,int fg,int rop,unsigned int planemask,int nBox,register BoxPtr pBoxI)349 I128FillSolidRects(ScrnInfoPtr pScrn, int fg, int rop, unsigned int planemask,
350 int nBox, register BoxPtr pBoxI)
351 {
352 I128Ptr pI128 = I128PTR(pScrn);
353 register int w, h;
354
355 #if 0
356 if (pI128->Debug)
357 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "FSR color 0x%x rop 0x%x (I128rop 0x%x) pmask 0x%x\n", fg, rop, i128alu[rop]>>8, planemask);
358 #endif
359
360 ENG_PIPELINE_READY();
361
362 if (planemask != -1) {
363 if (pI128->bitsPerPixel == 8) {
364 planemask |= (planemask<<8) |
365 (planemask<<16) |
366 (planemask<<24);
367 } else if (pI128->bitsPerPixel == 16)
368 planemask |= planemask<<16;
369 }
370
371 pI128->mem.rbase_a[MASK] = planemask;
372 pI128->mem.rbase_a[FORE] = fg;
373 pI128->mem.rbase_a[CMD] = (CS_SOLID<<16) | i128alu[rop] | CO_BITBLT;
374 pI128->mem.rbase_a[CLPTL] = 0x00000000;
375 pI128->mem.rbase_a[CLPBR] = (4095<<16) | 2047;
376
377 pI128->mem.rbase_a[XY3_DIR] = DIR_LR_TB;
378 pI128->mem.rbase_a[XY0_SRC] = 0x00000000;
379
380 while (nBox > 0) {
381 w = pBoxI->x2 - pBoxI->x1;
382 h = pBoxI->y2 - pBoxI->y1;
383 if (w > 0 && h > 0) {
384 pI128->mem.rbase_a[XY2_WH] = (w<<16) | h; MB;
385 pI128->mem.rbase_a[XY1_DST] =
386 (pBoxI->x1<<16) | pBoxI->y1; MB;
387
388 ENG_PIPELINE_READY();
389 #if 0
390 if (pI128->Debug)
391 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "FSR x,y %d,%d w,h %d,%d\n", pBoxI->x1, pBoxI->y1, w, h);
392 #endif
393
394 }
395 pBoxI++;
396 nBox--;
397 }
398
399 ENG_DONE();
400
401 }
402
403 #if 0
404 static void
405 I128ScreenToScreenBitBlt(ScrnInfoPtr pScrn, int nbox, DDXPointPtr pptSrc,
406 BoxPtr pbox, int xdir, int ydir, int alu, unsigned planemask)
407 {
408 I128Ptr pI128 = I128PTR(pScrn);
409 I128SetupForScreenToScreenCopy(pScrn, xdir, ydir, alu, planemask, -1);
410 for (; nbox; pbox++, pptSrc++, nbox--)
411 I128SubsequentScreenToScreenCopy(pScrn, pptSrc->x, pptSrc->y,
412 pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
413 ENG_DONE();
414 }
415 #endif
416
417 #endif
418
419 Bool
I128XaaInit(ScreenPtr pScreen)420 I128XaaInit(ScreenPtr pScreen)
421 {
422 #ifdef HAVE_XAA_H
423 XAAInfoRecPtr infoPtr;
424 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
425 I128Ptr pI128 = I128PTR(pScrn);
426 BoxRec AvailFBArea;
427 CARD32 buf_ctrl;
428 int maxlines;
429
430 pI128->XaaInfoRec = infoPtr = XAACreateInfoRec();
431 if (!infoPtr) return FALSE;
432
433 infoPtr->Flags = PIXMAP_CACHE |
434 OFFSCREEN_PIXMAPS |
435 LINEAR_FRAMEBUFFER ;
436
437 infoPtr->Sync = I128EngineDone;
438
439 /* screen to screen copy */
440 infoPtr->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
441 if (pI128->Chipset == PCI_CHIP_I128_T2R)
442 infoPtr->ScreenToScreenCopyFlags |= ONLY_LEFT_TO_RIGHT_BITBLT;
443
444 infoPtr->SetupForScreenToScreenCopy = I128SetupForScreenToScreenCopy;
445 infoPtr->SubsequentScreenToScreenCopy =
446 I128SubsequentScreenToScreenCopy;
447
448 #if 0
449 /* screen to screen color expansion */
450 if (pI128->Chipset == PCI_CHIP_I128_T2R)
451 infoPtr->ScreenToScreenColorExpandFillFlags |=
452 ONLY_LEFT_TO_RIGHT_BITBLT;
453
454 infoPtr->SetupForScreenToScreenColorExpandFill =
455 I128SetupForScreenToScreenColorExpandFill;
456 infoPtr->SubsequentScreenToScreenColorExpandFill =
457 I128SubsequentScreenToScreenColorExpandFill;
458 #endif
459
460 /* solid fills */
461 infoPtr->SetupForSolidFill = I128SetupForSolidFill;
462 infoPtr->SubsequentSolidFillRect = I128SubsequentSolidFillRect;
463
464 infoPtr->FillSolidRects = I128FillSolidRects;
465
466 /* solid lines */
467 infoPtr->SubsequentSolidTwoPointLine = I128SubsequentSolidTwoPointLine;
468
469 /* clipping */
470 infoPtr->ClippingFlags = HARDWARE_CLIP_LINE;
471 infoPtr->SetClippingRectangle = I128SetClippingRectangle;
472
473 infoPtr->PolyFillRectSolidFlags = 0;
474
475 maxlines = ((pI128->MemorySize * 1024) - 1024) /
476 (pScrn->displayWidth * pI128->bitsPerPixel / 8);
477 AvailFBArea.x1 = 0;
478 AvailFBArea.x2 = pI128->displayWidth;
479 AvailFBArea.y1 = 0;
480 AvailFBArea.y2 = maxlines;
481 xf86InitFBManager(pScreen, &AvailFBArea);
482 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
483 "Using %d lines for offscreen memory\n",
484 maxlines - pScrn->virtualY);
485
486 switch (pI128->bitsPerPixel) {
487 case 8: buf_ctrl = BC_PSIZ_8B; break;
488 case 16: buf_ctrl = BC_PSIZ_16B; break;
489 case 24:
490 case 32: buf_ctrl = BC_PSIZ_32B; break;
491 default: buf_ctrl = 0; break; /* error */
492 }
493 if (pI128->Chipset == PCI_CHIP_I128_T2R) {
494 if (pI128->MemoryType == I128_MEMORY_SGRAM)
495 buf_ctrl |= BC_MDM_PLN;
496 else
497 buf_ctrl |= BC_BLK_ENA;
498 }
499 pI128->mem.rbase_a[BUF_CTRL] = buf_ctrl;
500
501 pI128->mem.rbase_a[DE_PGE] = 0x00;
502 pI128->mem.rbase_a[DE_SORG] = pI128->displayOffset;
503 pI128->mem.rbase_a[DE_DORG] = pI128->displayOffset;
504 pI128->mem.rbase_a[DE_MSRC] = 0x00;
505 pI128->mem.rbase_a[DE_WKEY] = 0x00;
506 pI128->mem.rbase_a[DE_SPTCH] = pI128->mem.rbase_g[DB_PTCH];
507 pI128->mem.rbase_a[DE_DPTCH] = pI128->mem.rbase_g[DB_PTCH];
508 if (pI128->Chipset == PCI_CHIP_I128_T2R4)
509 pI128->mem.rbase_a[DE_ZPTCH] = pI128->mem.rbase_g[DB_PTCH];
510 pI128->mem.rbase_a[RMSK] = 0x00000000;
511 pI128->mem.rbase_a[XY4_ZM] = ZOOM_NONE;
512 pI128->mem.rbase_a[LPAT] = 0xffffffff; /* for lines */
513 pI128->mem.rbase_a[PCTRL] = 0x00000000; /* for lines */
514 pI128->mem.rbase_a[CLPTL] = 0x00000000;
515 pI128->mem.rbase_a[CLPBR] = (4095<<16) | 2047 ;
516 if (pI128->Chipset == PCI_CHIP_I128_T2R ||
517 pI128->Chipset == PCI_CHIP_I128_T2R4)
518 pI128->mem.rbase_a[ACNTRL] = 0x00000000;
519 pI128->mem.rbase_a[INTM] = 0x03;
520
521 if (pI128->Debug) {
522 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I128XaaInit done\n");
523 I128DumpActiveRegisters(pScrn);
524 }
525
526 return(XAAInit(pScreen, infoPtr));
527 #else
528 return FALSE;
529 #endif
530 }
531