1340e3fbdSmrg/*
2340e3fbdSmrg *      Copyright 2001  Ani Joshi <ajoshi@unixbox.com>
3340e3fbdSmrg *
4340e3fbdSmrg *      XFree86 4.x driver for S3 chipsets
5340e3fbdSmrg *
6340e3fbdSmrg *
7340e3fbdSmrg * Permission to use, copy, modify, distribute, and sell this software and its
8340e3fbdSmrg * documentation for any purpose is hereby granted without fee, provided that
9340e3fbdSmrg * the above copyright notice appear in all copies and that both that copyright
10340e3fbdSmrg * notice and this permission notice appear in supporting documentation and
11340e3fbdSmrg * that the name of Ani Joshi not be used in advertising or
12340e3fbdSmrg * publicity pertaining to distribution of the software without specific,
13340e3fbdSmrg * written prior permission.  Ani Joshi makes no representations
14340e3fbdSmrg * about the suitability of this software for any purpose.  It is provided
15340e3fbdSmrg * "as-is" without express or implied warranty.
16340e3fbdSmrg *
17340e3fbdSmrg * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18340e3fbdSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19340e3fbdSmrg * EVENT SHALL ANI JOSHI BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20340e3fbdSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21340e3fbdSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22340e3fbdSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23340e3fbdSmrg * PERFORMANCE OF THIS SOFTWARE.
24340e3fbdSmrg *
25340e3fbdSmrg *
26340e3fbdSmrg */
27340e3fbdSmrg
28340e3fbdSmrg#ifdef HAVE_CONFIG_H
29340e3fbdSmrg#include "config.h"
30340e3fbdSmrg#endif
31340e3fbdSmrg
32340e3fbdSmrg#include "xf86.h"
33340e3fbdSmrg
34340e3fbdSmrg#include "miline.h"
35340e3fbdSmrg
36340e3fbdSmrg#include "s3.h"
37340e3fbdSmrg#include "s3_reg.h"
38340e3fbdSmrg
39b27e1915Smrg#ifdef HAVE_XAA_H
40340e3fbdSmrg
41340e3fbdSmrg#if 0
42340e3fbdSmrgstatic Bool NicePattern;
43340e3fbdSmrgstatic int DashPatternSize;
44340e3fbdSmrg#define MAX_LINE_PATTERN_LENGTH	512
45340e3fbdSmrg#define LINE_PATTERN_START	((MAX_LINE_PATTERN_LENGTH >> 5) - 1)
46340e3fbdSmrgstatic CARD32 DashPattern[MAX_LINE_PATTERN_LENGTH >> 5];
47340e3fbdSmrg#endif
48340e3fbdSmrg
49340e3fbdSmrg
50340e3fbdSmrgstatic void S3Sync(ScrnInfoPtr pScrn)
51340e3fbdSmrg{
52340e3fbdSmrg	WaitIdle();
53340e3fbdSmrg}
54340e3fbdSmrg
55340e3fbdSmrgstatic void S3SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
56340e3fbdSmrg				unsigned int planemask)
57340e3fbdSmrg{
58340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
59340e3fbdSmrg
60340e3fbdSmrg	WaitQueue16_32(4,6);
61340e3fbdSmrg	SET_PIX_CNTL(0);
62340e3fbdSmrg	SET_FRGD_COLOR(color);
63340e3fbdSmrg	SET_FRGD_MIX(FSS_FRGDCOL | s3alu[rop]);
64340e3fbdSmrg	SET_WRT_MASK(planemask);
65340e3fbdSmrg}
66340e3fbdSmrg
67340e3fbdSmrgstatic void S3SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y,
68340e3fbdSmrg				      int w, int h)
69340e3fbdSmrg{
70340e3fbdSmrg#ifdef S3_NEWMMIO
71340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
72340e3fbdSmrg#endif
73340e3fbdSmrg
74340e3fbdSmrg	WaitQueue(5);
75340e3fbdSmrg	SET_CURPT((short)x, (short)y);
76340e3fbdSmrg	SET_AXIS_PCNT(w - 1, h - 1);
77340e3fbdSmrg	SET_CMD(CMD_RECT | DRAW | INC_X | INC_Y | WRTDATA);
78340e3fbdSmrg}
79340e3fbdSmrg
80340e3fbdSmrg
81340e3fbdSmrgstatic void S3SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir,
82340e3fbdSmrg					 int ydir, int rop,
83340e3fbdSmrg					 unsigned int planemask,
84340e3fbdSmrg					 int trans_color)
85340e3fbdSmrg{
86340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
87340e3fbdSmrg
88340e3fbdSmrg	pS3->BltDir = CMD_BITBLT | DRAW | WRTDATA;
89340e3fbdSmrg
90340e3fbdSmrg	if (xdir == 1)
91340e3fbdSmrg		pS3->BltDir |= INC_X;
92340e3fbdSmrg	if (ydir == 1)
93340e3fbdSmrg		pS3->BltDir |= INC_Y;
94340e3fbdSmrg
95340e3fbdSmrg	pS3->trans_color = trans_color;
96340e3fbdSmrg
97340e3fbdSmrg	WaitQueue16_32(3,4);
98340e3fbdSmrg	SET_PIX_CNTL(0);
99340e3fbdSmrg	SET_FRGD_MIX(FSS_BITBLT | s3alu[rop]);
100340e3fbdSmrg	SET_WRT_MASK(planemask);
101340e3fbdSmrg}
102340e3fbdSmrg
103340e3fbdSmrg
104340e3fbdSmrgstatic void S3SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn,
105340e3fbdSmrg					   int srcx, int srcy,
106340e3fbdSmrg					   int dstx, int dsty,
107340e3fbdSmrg					   int w, int h)
108340e3fbdSmrg{
109340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
110340e3fbdSmrg
111340e3fbdSmrg	w--;
112340e3fbdSmrg	h--;
113340e3fbdSmrg
114340e3fbdSmrg	if (!(pS3->BltDir & INC_Y)) {
115340e3fbdSmrg		srcy += h;
116340e3fbdSmrg		dsty += h;
117340e3fbdSmrg	}
118340e3fbdSmrg
119340e3fbdSmrg	if (!(pS3->BltDir & INC_X)) {
120340e3fbdSmrg		srcx += w;
121340e3fbdSmrg		dstx += w;
122340e3fbdSmrg	}
123340e3fbdSmrg
124340e3fbdSmrg	if (pS3->trans_color == -1) {
125340e3fbdSmrg		WaitQueue(7);
126340e3fbdSmrg		SET_CURPT((short)srcx, (short)srcy);
127340e3fbdSmrg		SET_DESTSTP((short)dstx, (short)dsty);
128340e3fbdSmrg		SET_AXIS_PCNT((short)w, (short)h);
129340e3fbdSmrg		SET_CMD(pS3->BltDir);
130340e3fbdSmrg	} else {
131340e3fbdSmrg		WaitQueue16_32(2,3);
132340e3fbdSmrg		SET_MULT_MISC(CMD_REG_WIDTH | 0x0100);
133340e3fbdSmrg		SET_COLOR_CMP(pS3->trans_color);
134340e3fbdSmrg
135340e3fbdSmrg		WaitQueue(8);
136340e3fbdSmrg		SET_CURPT((short)srcx, (short)srcy);
137340e3fbdSmrg		SET_DESTSTP((short)dstx, (short)dsty);
138340e3fbdSmrg		SET_AXIS_PCNT((short)w, (short)h);
139340e3fbdSmrg		SET_CMD(pS3->BltDir);
140340e3fbdSmrg		SET_MULT_MISC(CMD_REG_WIDTH);
141340e3fbdSmrg	}
142340e3fbdSmrg}
143340e3fbdSmrg
144bd35f0dbSahoka#if 0
145340e3fbdSmrgstatic void S3SetupForColor8x8PatternFill(ScrnInfoPtr pScrn,
146340e3fbdSmrg					  int patx, int paty,
147340e3fbdSmrg					  int rop, unsigned int planemask,
148340e3fbdSmrg					  int trans_color)
149340e3fbdSmrg{
150340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
151340e3fbdSmrg
152340e3fbdSmrg	pS3->trans_color = trans_color;
153340e3fbdSmrg
154340e3fbdSmrg	WaitQueue16_32(3,4);
155340e3fbdSmrg	SET_PIX_CNTL(0);
156340e3fbdSmrg	SET_FRGD_MIX(FSS_BITBLT | s3alu[rop]);
157340e3fbdSmrg	SET_WRT_MASK(planemask);
158340e3fbdSmrg}
159340e3fbdSmrg
160340e3fbdSmrgstatic void S3SubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrn,
161340e3fbdSmrg					    	int patx, int paty,
162340e3fbdSmrg					    	int x, int y,
163340e3fbdSmrg					    	int w, int h)
164340e3fbdSmrg{
165340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
166340e3fbdSmrg
167340e3fbdSmrg	if (pS3->trans_color == -1) {
168340e3fbdSmrg		WaitQueue(7);
169340e3fbdSmrg		SET_CURPT((short)patx, (short)paty);
170340e3fbdSmrg		SET_DESTSTP((short)x, (short)y);
171340e3fbdSmrg		SET_AXIS_PCNT(w - 1, h - 1);
172340e3fbdSmrg		SET_CMD(CMD_PFILL | DRAW | INC_Y | INC_X | WRTDATA);
173340e3fbdSmrg	} else {
174340e3fbdSmrg		WaitQueue16_32(2,3);
175340e3fbdSmrg		SET_MULT_MISC(CMD_REG_WIDTH | 0x0100);
176340e3fbdSmrg		SET_COLOR_CMP(pS3->trans_color);
177340e3fbdSmrg
178340e3fbdSmrg		WaitQueue(8);
179340e3fbdSmrg		SET_CURPT((short)patx, (short)paty);
180340e3fbdSmrg		SET_DESTSTP((short)x, (short)y);
181340e3fbdSmrg		SET_AXIS_PCNT(w - 1, h - 1);
182340e3fbdSmrg		SET_CMD(CMD_PFILL | DRAW | INC_Y | INC_X | WRTDATA);
183340e3fbdSmrg		SET_MULT_MISC(CMD_REG_WIDTH);
184340e3fbdSmrg	}
185340e3fbdSmrg}
186bd35f0dbSahoka#endif
187340e3fbdSmrg
188340e3fbdSmrg#ifdef S3_NEWMMIO
189340e3fbdSmrgstatic void S3SetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
190340e3fbdSmrg						 int fg, int bg,
191340e3fbdSmrg						 int rop,
192340e3fbdSmrg						 unsigned int planemask)
193340e3fbdSmrg{
194340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
195340e3fbdSmrg
196340e3fbdSmrg	WaitQueue16_32(3,4);
197340e3fbdSmrg	if (bg == -1) {
198340e3fbdSmrg		if (pS3->ColorExpandBug) {
199340e3fbdSmrg			SET_MIX(FSS_FRGDCOL | s3alu[rop], BSS_BKGDCOL | MIX_XOR);
200340e3fbdSmrg			SET_BKGD_COLOR(0);
201340e3fbdSmrg		} else
202340e3fbdSmrg			SET_MIX(FSS_FRGDCOL | s3alu[rop], BSS_BKGDCOL | MIX_DST);
203340e3fbdSmrg	} else {
204340e3fbdSmrg		SET_MIX(FSS_FRGDCOL | s3alu[rop], BSS_BKGDCOL | s3alu[rop]);
205340e3fbdSmrg		SET_BKGD_COLOR(bg);
206340e3fbdSmrg	}
207340e3fbdSmrg
208340e3fbdSmrg	WaitQueue16_32(3,5);
209340e3fbdSmrg	SET_FRGD_COLOR(fg);
210340e3fbdSmrg	SET_WRT_MASK(planemask);
211340e3fbdSmrg	SET_PIX_CNTL(MIXSEL_EXPPC);
212340e3fbdSmrg}
213340e3fbdSmrg
214340e3fbdSmrg
215340e3fbdSmrgstatic void S3SubsequentCPUToScreenColorExpandFill32(ScrnInfoPtr pScrn,
216340e3fbdSmrg						     int x, int y,
217340e3fbdSmrg						     int w, int h,
218340e3fbdSmrg						     int skipleft)
219340e3fbdSmrg{
220340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
221340e3fbdSmrg
222340e3fbdSmrg	WaitQueue(4);
223340e3fbdSmrg	SET_CURPT((short)x, (short)y);
224340e3fbdSmrg	SET_AXIS_PCNT((short)w-1, (short)h-1);
225340e3fbdSmrg
226340e3fbdSmrg	WaitIdle();
227340e3fbdSmrg	SET_CMD(CMD_RECT | BYTSEQ | _32BIT | PCDATA | DRAW |
228340e3fbdSmrg		PLANAR | INC_Y | INC_X | WRTDATA);
229340e3fbdSmrg}
230340e3fbdSmrg#endif
231340e3fbdSmrg
232340e3fbdSmrg#if 0
233340e3fbdSmrg#ifndef S3_NEWMMIO
234340e3fbdSmrg
235340e3fbdSmrgstatic void S3SetupForScanlineImageWriteNoMMIO(ScrnInfoPtr pScrn, int rop,
236340e3fbdSmrg					       unsigned int planemask,
237340e3fbdSmrg					       int trans_color,
238340e3fbdSmrg					       int bpp, int depth)
239340e3fbdSmrg{
240340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
241340e3fbdSmrg
242340e3fbdSmrg	WaitQueue16_32(3,4)
243340e3fbdSmrg	SET_FRGD_MIX(FSS_PCDATA | s3alu[rop]);
244340e3fbdSmrg	SET_WRT_MASK(planemask);
245340e3fbdSmrg	SET_PIX_CNTL(0);
246340e3fbdSmrg}
247340e3fbdSmrg
248340e3fbdSmrgstatic void S3SubsequentScanlineImageWriteRectNoMMIO(ScrnInfoPtr pScrn,
249340e3fbdSmrg						     int x, int y,
250340e3fbdSmrg						     int w, int h,
251340e3fbdSmrg						     int skipleft)
252340e3fbdSmrg{
253340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
254340e3fbdSmrg
255340e3fbdSmrg	pS3->imageWidth = w;
256340e3fbdSmrg	pS3->imageHeight = h;
257340e3fbdSmrg
258340e3fbdSmrg	WaitQueue(5);
259340e3fbdSmrg	SET_CURPT((short)x, (short)y);
260340e3fbdSmrg	SET_AXIS_PCNT((short)w-1, (short)h-1);
261340e3fbdSmrg	WaitIdle();
262340e3fbdSmrg	SET_CMD(CMD_RECT | BYTSEQ | _16BIT | INC_Y | INC_X | DRAW |
263340e3fbdSmrg		PCDATA | WRTDATA);
264340e3fbdSmrg}
265340e3fbdSmrg
266340e3fbdSmrg
267340e3fbdSmrgstatic void S3SubsequentImageWriteScanlineNoMMIO(ScrnInfoPtr pScrn,
268340e3fbdSmrg						 int bufno)
269340e3fbdSmrg{
270340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
271340e3fbdSmrg	int i, j;
272340e3fbdSmrg	int w, h;
273340e3fbdSmrg	CARD16 *src = (CARD16 *)&pS3->imageBuffer;
274340e3fbdSmrg
275340e3fbdSmrg	w = pS3->imageWidth * pS3->s3Bpp;
276340e3fbdSmrg	h = pS3->imageHeight;
277340e3fbdSmrg
278340e3fbdSmrg	for(j=0; j<h; j++) {
279340e3fbdSmrg		for(i=0; i<(w & ~1); ) {
280340e3fbdSmrg			/* XXX not for 32bpp */
281340e3fbdSmrg			SET_PIX_TRANS_W(ldw_u(src));
282340e3fbdSmrg			src++;
283340e3fbdSmrg			i += 2;
284340e3fbdSmrg		}
285340e3fbdSmrg	}
286340e3fbdSmrg}
287340e3fbdSmrg
288340e3fbdSmrg#endif
289340e3fbdSmrg#endif
290340e3fbdSmrg
291340e3fbdSmrg
292340e3fbdSmrgstatic void S3SetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop,
293340e3fbdSmrg				unsigned int planemask)
294340e3fbdSmrg{
295340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
296340e3fbdSmrg
297340e3fbdSmrg	WaitQueue16_32(4,6);
298340e3fbdSmrg	SET_PIX_CNTL(0);
299340e3fbdSmrg	SET_FRGD_COLOR(color);
300340e3fbdSmrg	SET_FRGD_MIX(FSS_FRGDCOL | s3alu[rop]);
301340e3fbdSmrg	SET_WRT_MASK(planemask);
302340e3fbdSmrg}
303340e3fbdSmrg
304340e3fbdSmrg
305340e3fbdSmrgstatic void S3SubsequentSolidBresenhamLine(ScrnInfoPtr pScrn,
306340e3fbdSmrg					   int x, int y,
307340e3fbdSmrg					   int major, int minor,
308340e3fbdSmrg					   int err, int len, int octant)
309340e3fbdSmrg{
310340e3fbdSmrg#ifdef S3_NEWMMIO
311340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
312340e3fbdSmrg#endif
313340e3fbdSmrg	unsigned short cmd;
314340e3fbdSmrg	int error, e1, e2;
315340e3fbdSmrg
316340e3fbdSmrg	error = minor + err;
317340e3fbdSmrg	e1 = minor;   /* was: major, wrong (twini@xfree86.org) */
318340e3fbdSmrg	e2 = minor - major;
319340e3fbdSmrg
320340e3fbdSmrg	if (major) {
321340e3fbdSmrg		cmd = CMD_LINE | DRAW | WRTDATA | LASTPIX;
322340e3fbdSmrg
323340e3fbdSmrg		if (octant & YMAJOR)
324340e3fbdSmrg			cmd |= YMAJAXIS;
325340e3fbdSmrg		if (!(octant & XDECREASING))
326340e3fbdSmrg			cmd |= INC_X;
327340e3fbdSmrg		if (!(octant & YDECREASING))
328340e3fbdSmrg			cmd |= INC_Y;
329340e3fbdSmrg
330340e3fbdSmrg		WaitQueue(7);
331340e3fbdSmrg		SET_CURPT((short)x, (short)y);
332340e3fbdSmrg		SET_ERR_TERM((short)error);
333340e3fbdSmrg		SET_DESTSTP((short)e2, (short)e1);
334340e3fbdSmrg		SET_MAJ_AXIS_PCNT((short)len);
335340e3fbdSmrg		SET_CMD(cmd);
336340e3fbdSmrg	} else {
337340e3fbdSmrg		WaitQueue(4);
338340e3fbdSmrg		SET_CURPT((short)x, (short)y);
339340e3fbdSmrg		SET_MAJ_AXIS_PCNT((short)len-1);
340340e3fbdSmrg		SET_CMD(CMD_LINE | DRAW | LINETYPE | WRTDATA | VECDIR_270);
341340e3fbdSmrg	}
342340e3fbdSmrg}
343340e3fbdSmrg
344340e3fbdSmrg
345340e3fbdSmrg
346340e3fbdSmrgstatic void S3SubsequentSolidHorVertLine(ScrnInfoPtr pScrn,
347340e3fbdSmrg					 int x, int y, int len, int dir)
348340e3fbdSmrg{
349340e3fbdSmrg	if (dir == DEGREES_0)
350340e3fbdSmrg		S3SubsequentSolidFillRect(pScrn, x, y, len, 1);
351340e3fbdSmrg	else
352340e3fbdSmrg		S3SubsequentSolidFillRect(pScrn, x, y, 1, len);
353340e3fbdSmrg}
354340e3fbdSmrg
355340e3fbdSmrg
356340e3fbdSmrg#if 0
357340e3fbdSmrg
358340e3fbdSmrgstatic void S3SetupForDashedLine(ScrnInfoPtr pScrn,
359340e3fbdSmrg                                 int fg, int bg,
360340e3fbdSmrg                                 int rop, unsigned int planemask,
361340e3fbdSmrg                                 int len, unsigned char *pattern)
362340e3fbdSmrg{
363340e3fbdSmrg#ifdef S3_NEWMMIO
364340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
365340e3fbdSmrg
366340e3fbdSmrg	S3SetupForCPUToScreenColorExpandFill(pScrn, bg, fg, rop, planemask);
367340e3fbdSmrg#endif
368340e3fbdSmrg
369340e3fbdSmrg	WaitQueue(4);
370340e3fbdSmrg
371340e3fbdSmrg	NicePattern = FALSE;
372340e3fbdSmrg
373340e3fbdSmrg	if (len <= 32) {
374340e3fbdSmrg		register CARD32 scratch = DashPattern[LINE_PATTERN_START];
375340e3fbdSmrg
376340e3fbdSmrg		if (len & (len - 1)) {
377340e3fbdSmrg			while (len < 16) {
378340e3fbdSmrg				scratch |= (scratch >> len);
379340e3fbdSmrg				len <<= 1;
380340e3fbdSmrg			}
381340e3fbdSmrg			scratch |= (scratch >> len);
382340e3fbdSmrg			DashPattern[LINE_PATTERN_START] = scratch;
383340e3fbdSmrg		} else {
384340e3fbdSmrg			switch (len) {
385340e3fbdSmrg				case 2:
386340e3fbdSmrg					scratch |= scratch >> 2;
387340e3fbdSmrg				case 4:
388340e3fbdSmrg					scratch |= scratch >> 4;
389340e3fbdSmrg				case 8:
390340e3fbdSmrg					scratch |= scratch >> 8;
391340e3fbdSmrg				case 16:
392340e3fbdSmrg					scratch |= scratch >> 16;
393340e3fbdSmrg					DashPattern[LINE_PATTERN_START] = scratch;
394340e3fbdSmrg				case 32:
395340e3fbdSmrg					NicePattern = TRUE;
396340e3fbdSmrg				default:
397340e3fbdSmrg					break;
398340e3fbdSmrg			}
399340e3fbdSmrg		}
400340e3fbdSmrg	}
401340e3fbdSmrg
402340e3fbdSmrg	DashPatternSize = len;
403340e3fbdSmrg}
404340e3fbdSmrg
405340e3fbdSmrg
406340e3fbdSmrgstatic void S3SubsequentDashedBresenhamLine32(ScrnInfoPtr pScrn,
407340e3fbdSmrg					      int x, int y,
408340e3fbdSmrg					      int absmaj, int absmin,
409340e3fbdSmrg					      int err, int len,
410340e3fbdSmrg					      int octant, int phase)
411340e3fbdSmrg{
412340e3fbdSmrg#ifdef S3_NEWMMIO
413340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
414340e3fbdSmrg#endif
415340e3fbdSmrg	register int count = (len + 31) >> 5;
416340e3fbdSmrg	register CARD32 pattern;
417340e3fbdSmrg	int error, e1, e2;
418340e3fbdSmrg
419340e3fbdSmrg	error = absmin + err;
420340e3fbdSmrg	e1 = absmaj;
421340e3fbdSmrg	e2 = absmin - absmaj;
422340e3fbdSmrg
423340e3fbdSmrg	if (err) {
424340e3fbdSmrg		unsigned short cmd = _32BIT | PLANAR | WRTDATA | DRAW |
425340e3fbdSmrg				     PCDATA | LASTPIX | CMD_LINE;
426340e3fbdSmrg
427340e3fbdSmrg		if (octant & YMAJOR)
428340e3fbdSmrg			cmd |= YMAJAXIS;
429340e3fbdSmrg		if (!(octant & XDECREASING))
430340e3fbdSmrg			cmd |= INC_X;
431340e3fbdSmrg		if (!(octant & YDECREASING))
432340e3fbdSmrg			cmd |= INC_Y;
433340e3fbdSmrg
434340e3fbdSmrg		WaitQueue(7);
435340e3fbdSmrg		SET_CURPT((short)x, (short)y);
436340e3fbdSmrg		SET_ERR_TERM((short)error);
437340e3fbdSmrg		SET_DESTSTP((short)e2, (short)e1);
438340e3fbdSmrg		SET_MAJ_AXIS_PCNT((short)len);
439340e3fbdSmrg		SET_CMD(cmd);
440340e3fbdSmrg	} else {
441340e3fbdSmrg		if (octant & YMAJOR) {
442340e3fbdSmrg			WaitQueue(4);
443340e3fbdSmrg			SET_CURPT((short)x, (short)y);
444340e3fbdSmrg			SET_MAJ_AXIS_PCNT((short)len - 1);
445340e3fbdSmrg
446340e3fbdSmrg			if (octant & YDECREASING) {
447340e3fbdSmrg				SET_CMD(_32BIT | PLANAR | WRTDATA | DRAW |
448340e3fbdSmrg					CMD_LINE | LINETYPE | VECDIR_090);
449340e3fbdSmrg			} else {
450340e3fbdSmrg				SET_CMD(_32BIT | PLANAR | WRTDATA | DRAW |
451340e3fbdSmrg					CMD_LINE | LINETYPE | VECDIR_270);
452340e3fbdSmrg			}
453340e3fbdSmrg		} else {
454340e3fbdSmrg			if (octant & XDECREASING) {
455340e3fbdSmrg				WaitQueue(4);
456340e3fbdSmrg				SET_CURPT((short)x, (short)y);
457340e3fbdSmrg				SET_MAJ_AXIS_PCNT((short)len - 1);
458340e3fbdSmrg				SET_CMD(_32BIT | PLANAR | WRTDATA | DRAW |
459340e3fbdSmrg					PCDATA | CMD_LINE | LINETYPE | VECDIR_180);
460340e3fbdSmrg			} else {
461340e3fbdSmrg				WaitQueue(4);
462340e3fbdSmrg				SET_CURPT((short)x, (short)y);
463340e3fbdSmrg				SET_MAJ_AXIS_PCNT((short)len - 1);
464340e3fbdSmrg				SET_CMD(_32BIT | PLANAR | WRTDATA | DRAW |
465340e3fbdSmrg					PCDATA | CMD_RECT | INC_Y | INC_X);
466340e3fbdSmrg			}
467340e3fbdSmrg		}
468340e3fbdSmrg	}
469340e3fbdSmrg
470340e3fbdSmrg	if (NicePattern) {
471340e3fbdSmrg#ifdef S3_NEWMMIO
472340e3fbdSmrg		register CARD32 *dest = (CARD32*)&IMG_TRANS;
473340e3fbdSmrg#endif
474340e3fbdSmrg
475340e3fbdSmrg		pattern = (phase) ? (DashPattern[LINE_PATTERN_START] << phase) |
476340e3fbdSmrg			(DashPattern[LINE_PATTERN_START] >> (32 - phase)) :
477340e3fbdSmrg			 DashPattern[LINE_PATTERN_START];
478340e3fbdSmrg
479340e3fbdSmrg#ifdef S3_NEWMMIO
480340e3fbdSmrg		while (count & ~0x03) {
481340e3fbdSmrg			dest[0] = dest[1] = dest[2] = dest[3] = pattern;
482340e3fbdSmrg			dest += 4;
483340e3fbdSmrg			count -= 4;
484340e3fbdSmrg		}
485340e3fbdSmrg		switch (count) {
486340e3fbdSmrg		case 1:
487340e3fbdSmrg			dest[0] = pattern;
488340e3fbdSmrg			break;
489340e3fbdSmrg		case 2:
490340e3fbdSmrg			dest[0] = dest[1] = pattern;
491340e3fbdSmrg			break;
492340e3fbdSmrg		case 3:
493340e3fbdSmrg			dest[0] = dest[1] = dest[2] = pattern;
494340e3fbdSmrg			break;
495340e3fbdSmrg		}
496340e3fbdSmrg#else
497340e3fbdSmrg
498340e3fbdSmrg		while (count--)
499340e3fbdSmrg			SET_PIX_TRANS_L(pattern);
500340e3fbdSmrg#endif
501340e3fbdSmrg	} else if (DashPatternSize < 32) {
502340e3fbdSmrg		register int offset = phase;
503340e3fbdSmrg
504340e3fbdSmrg		while (count--) {
505340e3fbdSmrg			SET_PIX_TRANS_L((DashPattern[LINE_PATTERN_START] << offset) |
506340e3fbdSmrg				(DashPattern[LINE_PATTERN_START] >>
507340e3fbdSmrg				(DashPatternSize - offset)));
508340e3fbdSmrg			offset += 32;
509340e3fbdSmrg			while (offset > DashPatternSize)
510340e3fbdSmrg				offset -= DashPatternSize;
511340e3fbdSmrg		}
512340e3fbdSmrg	} else {
513340e3fbdSmrg		int offset = phase;
514340e3fbdSmrg		register unsigned char *srcp = (unsigned char *)(DashPattern) +
515340e3fbdSmrg			(MAX_LINE_PATTERN_LENGTH >> 3) - 1;
516340e3fbdSmrg		register CARD32 *scratch;
517340e3fbdSmrg		int scratch2, shift;
518340e3fbdSmrg
519340e3fbdSmrg		while (count--) {
520340e3fbdSmrg			shift = DashPatternSize - offset;
521340e3fbdSmrg			scratch = (CARD32*)(srcp - (offset >> 3) - 3);
522340e3fbdSmrg			scratch2 = offset & 0x07;
523340e3fbdSmrg
524340e3fbdSmrg			if (shift & ~31) {
525340e3fbdSmrg				if (scratch2) {
526340e3fbdSmrg					pattern = (*scratch << scratch2) |
527340e3fbdSmrg						  (*(scratch - 1) >> (32 - scratch2));
528340e3fbdSmrg				} else
529340e3fbdSmrg					pattern = *scratch;
530340e3fbdSmrg			} else {
531340e3fbdSmrg				pattern = (*((CARD32*)(srcp - 3)) >> shift) |
532340e3fbdSmrg					  (*scratch << scratch2);
533340e3fbdSmrg			}
534340e3fbdSmrg			SET_PIX_TRANS_L(pattern);
535340e3fbdSmrg			offset += 32;
536340e3fbdSmrg			while (offset >= DashPatternSize)
537340e3fbdSmrg				offset -= DashPatternSize;
538340e3fbdSmrg		}
539340e3fbdSmrg	}
540340e3fbdSmrg}
541340e3fbdSmrg
542b27e1915Smrg#endif
543340e3fbdSmrg#endif
544340e3fbdSmrg
545340e3fbdSmrg#ifdef S3_NEWMMIO
546340e3fbdSmrgBool S3AccelInitNewMMIO(ScreenPtr pScreen)
547340e3fbdSmrg#else
548340e3fbdSmrgBool S3AccelInitPIO(ScreenPtr pScreen)
549340e3fbdSmrg#endif
550340e3fbdSmrg{
551b27e1915Smrg#ifdef HAVE_XAA_H
552b27e1915Smrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
553340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
554340e3fbdSmrg	XAAInfoRecPtr pXAA;
555340e3fbdSmrg
556340e3fbdSmrg	if (pS3->Chipset == PCI_CHIP_968)
557340e3fbdSmrg		pS3->ColorExpandBug = TRUE;
558340e3fbdSmrg	else
559340e3fbdSmrg		pS3->ColorExpandBug = FALSE;
560340e3fbdSmrg
561340e3fbdSmrg	if (!(pXAA = XAACreateInfoRec()))
562340e3fbdSmrg		return FALSE;
563340e3fbdSmrg
564340e3fbdSmrg	pS3->pXAA = pXAA;
565340e3fbdSmrg
566340e3fbdSmrg	pXAA->Flags = (PIXMAP_CACHE | OFFSCREEN_PIXMAPS |
567340e3fbdSmrg		       LINEAR_FRAMEBUFFER);
568340e3fbdSmrg
569340e3fbdSmrg	pXAA->Sync = S3Sync;
570340e3fbdSmrg
571340e3fbdSmrg	pXAA->SetupForSolidFill = S3SetupForSolidFill;
572340e3fbdSmrg	pXAA->SubsequentSolidFillRect = S3SubsequentSolidFillRect;
573340e3fbdSmrg
574340e3fbdSmrg	pXAA->SetupForScreenToScreenCopy = S3SetupForScreenToScreenCopy;
575340e3fbdSmrg	pXAA->SubsequentScreenToScreenCopy = S3SubsequentScreenToScreenCopy;
576bd35f0dbSahoka	pXAA->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
577340e3fbdSmrg
578bd35f0dbSahoka#if 0
579bd35f0dbSahoka/*
580bd35f0dbSahoka  8x8 color pattern filling doesn't work properly after introducing
581bd35f0dbSahoka  framebuffer manager initialization before XAA initialization. There
582bd35f0dbSahoka  are problems with addressing a colour patterns from offscreen area.
583bd35f0dbSahoka*/
584340e3fbdSmrg	pXAA->SetupForColor8x8PatternFill = S3SetupForColor8x8PatternFill;
585340e3fbdSmrg	pXAA->SubsequentColor8x8PatternFillRect = S3SubsequentColor8x8PatternFillRect;
586bd35f0dbSahoka	pXAA->Color8x8PatternFillFlags = NO_TRANSPARENCY |
587bd35f0dbSahoka		HARDWARE_PATTERN_SCREEN_ORIGIN |
588bd35f0dbSahoka		BIT_ORDER_IN_BYTE_MSBFIRST;
589bd35f0dbSahoka
590bd35f0dbSahoka	pXAA->CachePixelGranularity = 0;
591bd35f0dbSahoka#endif
592340e3fbdSmrg
593340e3fbdSmrg#ifdef S3_NEWMMIO
594340e3fbdSmrg	pXAA->SetupForCPUToScreenColorExpandFill =
595340e3fbdSmrg		S3SetupForCPUToScreenColorExpandFill;
596340e3fbdSmrg	pXAA->SubsequentCPUToScreenColorExpandFill =
597340e3fbdSmrg		S3SubsequentCPUToScreenColorExpandFill32;
598340e3fbdSmrg	pXAA->ColorExpandBase = (void *) &IMG_TRANS;
599340e3fbdSmrg	pXAA->ColorExpandRange = 0x8000;
600340e3fbdSmrg	pXAA->CPUToScreenColorExpandFillFlags = CPU_TRANSFER_PAD_DWORD |
601340e3fbdSmrg						BIT_ORDER_IN_BYTE_MSBFIRST |
602340e3fbdSmrg						SCANLINE_PAD_DWORD;
603340e3fbdSmrg#endif
604340e3fbdSmrg
605340e3fbdSmrg#if 0
606340e3fbdSmrg#ifndef S3_NEWMMIO
607340e3fbdSmrg	pXAA->ScanlineImageWriteFlags = NO_TRANSPARENCY;
608340e3fbdSmrg	pXAA->SetupForScanlineImageWrite =
609340e3fbdSmrg		S3SetupForScanlineImageWriteNoMMIO;
610340e3fbdSmrg	pXAA->SubsequentScanlineImageWriteRect =
611340e3fbdSmrg		S3SubsequentScanlineImageWriteRectNoMMIO;
612340e3fbdSmrg	pXAA->SubsequentImageWriteScanline =
613340e3fbdSmrg		S3SubsequentImageWriteScanlineNoMMIO;
614340e3fbdSmrg	pXAA->NumScanlineImageWriteBuffers = 1;
615340e3fbdSmrg	pXAA->ScanlineImageWriteBuffers = &pS3->imageBuffer;
616340e3fbdSmrg#endif
617340e3fbdSmrg#endif
618340e3fbdSmrg
619340e3fbdSmrg	pXAA->SetupForSolidLine = S3SetupForSolidLine;
620340e3fbdSmrg	pXAA->SubsequentSolidBresenhamLine = S3SubsequentSolidBresenhamLine;
621340e3fbdSmrg	pXAA->SubsequentSolidHorVertLine = S3SubsequentSolidHorVertLine;
622340e3fbdSmrg	pXAA->SolidBresenhamLineErrorTermBits = 12;
623340e3fbdSmrg#if 0
624340e3fbdSmrg	/* kinda buggy...  and its faster without it */
625340e3fbdSmrg	pXAA->SetupForDashedLine = S3SetupForDashedLine;
626340e3fbdSmrg	pXAA->SubsequentDashedBresenhamLine = S3SubsequentDashedBresenhamLine32;
627340e3fbdSmrg	pXAA->DashPatternMaxLength = MAX_LINE_PATTERN_LENGTH;
628340e3fbdSmrg#endif
629340e3fbdSmrg
630340e3fbdSmrg	return XAAInit(pScreen, pXAA);
631b27e1915Smrg#else
632b27e1915Smrg	return FALSE;
633b27e1915Smrg#endif
634340e3fbdSmrg}
635