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