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