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