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