s3_cursor.c revision 340e3fbd
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/* $XFree86: $ */
28340e3fbdSmrg
29340e3fbdSmrg#ifdef HAVE_CONFIG_H
30340e3fbdSmrg#include "config.h"
31340e3fbdSmrg#endif
32340e3fbdSmrg
33340e3fbdSmrg#include "xf86.h"
34340e3fbdSmrg#include "xf86_OSproc.h"
35340e3fbdSmrg
36340e3fbdSmrg#include "compiler.h"
37340e3fbdSmrg
38340e3fbdSmrg#include "s3.h"
39340e3fbdSmrg#include "s3_reg.h"
40340e3fbdSmrg
41340e3fbdSmrg
42340e3fbdSmrgstatic void S3SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
43340e3fbdSmrg{
44340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
45340e3fbdSmrg	int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
46340e3fbdSmrg	unsigned short packfg, packbg;
47340e3fbdSmrg
48340e3fbdSmrg	switch (pS3->s3Bpp) {
49340e3fbdSmrg	case 1:
50340e3fbdSmrg		/* XXX Trio series only */
51340e3fbdSmrg		outb(vgaCRIndex, 0x45);
52340e3fbdSmrg		inb(vgaCRReg);
53340e3fbdSmrg		outb(vgaCRIndex, 0x4a);
54340e3fbdSmrg		outb(vgaCRReg, fg);
55340e3fbdSmrg		outb(vgaCRReg, fg);
56340e3fbdSmrg
57340e3fbdSmrg		outb(vgaCRIndex, 0x45);
58340e3fbdSmrg		inb(vgaCRReg);
59340e3fbdSmrg		outb(vgaCRIndex, 0x4b);
60340e3fbdSmrg		outb(vgaCRReg, bg);
61340e3fbdSmrg		outb(vgaCRReg, bg);
62340e3fbdSmrg
63340e3fbdSmrg		break;
64340e3fbdSmrg	case 2:
65340e3fbdSmrg		/* XXX depth 16 */
66340e3fbdSmrg		packfg = ((fg & 0x00f80000) >> 19) | ((fg & 0x0000fc00) >> 5) |
67340e3fbdSmrg			 ((fg & 0x000000f8) << 8);
68340e3fbdSmrg		packbg = ((bg & 0x00f80000) >> 19) | ((bg & 0x0000fc00) >> 5) |
69340e3fbdSmrg			 ((bg & 0x000000f8) << 8);
70340e3fbdSmrg
71340e3fbdSmrg		outb(vgaCRIndex, 0x45);
72340e3fbdSmrg		inb(vgaCRReg);
73340e3fbdSmrg		outb(vgaCRIndex, 0x4a);
74340e3fbdSmrg		outb(vgaCRReg, packfg);
75340e3fbdSmrg		outb(vgaCRReg, packfg >> 8);
76340e3fbdSmrg
77340e3fbdSmrg		outb(vgaCRIndex, 0x45);
78340e3fbdSmrg		inb(vgaCRReg);
79340e3fbdSmrg		outb(vgaCRIndex, 0x4b);
80340e3fbdSmrg		outb(vgaCRReg, packbg);
81340e3fbdSmrg		outb(vgaCRReg, packbg >> 8);
82340e3fbdSmrg
83340e3fbdSmrg		break;
84340e3fbdSmrg	default:
85340e3fbdSmrg		outb(vgaCRIndex, 0x45);
86340e3fbdSmrg		inb(vgaCRReg);
87340e3fbdSmrg		outb(vgaCRIndex, 0x4a);
88340e3fbdSmrg		outb(vgaCRReg, (fg & 0x00ff0000) >> 16);
89340e3fbdSmrg		outb(vgaCRReg, (fg & 0x0000ff00) >> 8);
90340e3fbdSmrg		outb(vgaCRReg, (fg & 0x000000ff));
91340e3fbdSmrg
92340e3fbdSmrg		outb(vgaCRIndex, 0x45);
93340e3fbdSmrg		inb(vgaCRReg);
94340e3fbdSmrg		outb(vgaCRIndex, 0x4b);
95340e3fbdSmrg		outb(vgaCRReg, (bg & 0x00ff0000) >> 16);
96340e3fbdSmrg		outb(vgaCRReg, (bg & 0x0000ff00) >> 8);
97340e3fbdSmrg		outb(vgaCRReg, (bg & 0x000000ff));
98340e3fbdSmrg
99340e3fbdSmrg		break;
100340e3fbdSmrg	}
101340e3fbdSmrg}
102340e3fbdSmrg
103340e3fbdSmrg
104340e3fbdSmrgstatic void S3SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
105340e3fbdSmrg{
106340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
107340e3fbdSmrg	int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
108340e3fbdSmrg
109340e3fbdSmrg	outb(vgaCRIndex, 0x39);
110340e3fbdSmrg	outb(vgaCRReg, 0xa5);
111340e3fbdSmrg
112340e3fbdSmrg	outb(vgaCRIndex, 0x46);
113340e3fbdSmrg	outb(vgaCRReg, x >> 8);
114340e3fbdSmrg	outb(vgaCRIndex, 0x47);
115340e3fbdSmrg	outb(vgaCRReg, x);
116340e3fbdSmrg
117340e3fbdSmrg	outb(vgaCRIndex, 0x49);
118340e3fbdSmrg	outb(vgaCRReg, y);
119340e3fbdSmrg	outb(vgaCRIndex, 0x48);
120340e3fbdSmrg	outb(vgaCRReg, y >> 8);
121340e3fbdSmrg}
122340e3fbdSmrg
123340e3fbdSmrg
124340e3fbdSmrgstatic void S3HideCursor(ScrnInfoPtr pScrn)
125340e3fbdSmrg{
126340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
127340e3fbdSmrg	int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
128340e3fbdSmrg	unsigned char tmp;
129340e3fbdSmrg
130340e3fbdSmrg	outb(vgaCRIndex, 0x45);
131340e3fbdSmrg	tmp = inb(vgaCRReg);
132340e3fbdSmrg	outb(vgaCRReg, tmp & ~0x01);
133340e3fbdSmrg}
134340e3fbdSmrg
135340e3fbdSmrg
136340e3fbdSmrgstatic void S3ShowCursor(ScrnInfoPtr pScrn)
137340e3fbdSmrg{
138340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
139340e3fbdSmrg	int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
140340e3fbdSmrg	unsigned char tmp;
141340e3fbdSmrg
142340e3fbdSmrg	outb(vgaCRIndex, 0x39);
143340e3fbdSmrg	outb(vgaCRReg, 0xa5);
144340e3fbdSmrg
145340e3fbdSmrg	outb(vgaCRIndex, 0x55);
146340e3fbdSmrg	tmp = inb(vgaCRReg);
147340e3fbdSmrg	outb(vgaCRReg, tmp | 0x10);
148340e3fbdSmrg
149340e3fbdSmrg	outb(vgaCRIndex, 0x4c);
150340e3fbdSmrg	outb(vgaCRReg, pS3->FBCursorOffset >> 8);
151340e3fbdSmrg	outb(vgaCRIndex, 0x4d);
152340e3fbdSmrg	outb(vgaCRReg, pS3->FBCursorOffset);
153340e3fbdSmrg
154340e3fbdSmrg	outb(vgaCRIndex, 0x45);
155340e3fbdSmrg	tmp = inb(vgaCRReg);
156340e3fbdSmrg	outb(vgaCRReg, tmp | 0x01);
157340e3fbdSmrg}
158340e3fbdSmrg
159340e3fbdSmrg
160340e3fbdSmrgstatic void S3LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image)
161340e3fbdSmrg{
162340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
163340e3fbdSmrg	int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
164340e3fbdSmrg	unsigned char cr45;
165340e3fbdSmrg
166340e3fbdSmrg	outb(vgaCRIndex, 0x39);
167340e3fbdSmrg	outb(vgaCRReg, 0xa5);
168340e3fbdSmrg
169340e3fbdSmrg	WaitIdle();
170340e3fbdSmrg
171340e3fbdSmrg	VerticalRetraceWait();
172340e3fbdSmrg
173340e3fbdSmrg	outb(vgaCRIndex, 0x45);
174340e3fbdSmrg	cr45 = inb(vgaCRReg);
175340e3fbdSmrg	outb(vgaCRReg, cr45 & 0xfe);
176340e3fbdSmrg
177340e3fbdSmrg	outb(vgaCRIndex, 0x46);
178340e3fbdSmrg	outb(vgaCRReg, 0xff);
179340e3fbdSmrg	outb(vgaCRIndex, 0x47);
180340e3fbdSmrg	outb(vgaCRReg, 0x7f);
181340e3fbdSmrg	outb(vgaCRIndex, 0x49);
182340e3fbdSmrg	outb(vgaCRReg, 0xff);
183340e3fbdSmrg	outb(vgaCRIndex, 0x4e);
184340e3fbdSmrg	outb(vgaCRReg, 0x3f);
185340e3fbdSmrg	outb(vgaCRIndex, 0x4f);
186340e3fbdSmrg	outb(vgaCRReg, 0x3f);
187340e3fbdSmrg	outb(vgaCRIndex, 0x48);
188340e3fbdSmrg	outb(vgaCRReg, 0x7f);
189340e3fbdSmrg
190340e3fbdSmrg	memcpy(pS3->FBBase + (pS3->FBCursorOffset * 1024), image, 1024);
191340e3fbdSmrg
192340e3fbdSmrg	VerticalRetraceWait();
193340e3fbdSmrg
194340e3fbdSmrg	outb(vgaCRIndex, 0x45);
195340e3fbdSmrg	outb(vgaCRReg, cr45);
196340e3fbdSmrg}
197340e3fbdSmrg
198340e3fbdSmrg
199340e3fbdSmrgstatic Bool S3UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
200340e3fbdSmrg{
201340e3fbdSmrg	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
202340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
203340e3fbdSmrg	return (pS3->hwCursor);
204340e3fbdSmrg}
205340e3fbdSmrg
206340e3fbdSmrg
207340e3fbdSmrgBool S3_CursorInit(ScreenPtr pScreen)
208340e3fbdSmrg{
209340e3fbdSmrg	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
210340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
211340e3fbdSmrg	xf86CursorInfoPtr pCurs;
212340e3fbdSmrg
213340e3fbdSmrg	if (!(pCurs = pS3->pCurs = xf86CreateCursorInfoRec()))
214340e3fbdSmrg		return FALSE;
215340e3fbdSmrg
216340e3fbdSmrg	pCurs->MaxWidth = 64;
217340e3fbdSmrg	pCurs->MaxHeight = 64;
218340e3fbdSmrg	pCurs->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
219340e3fbdSmrg		       HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
220340e3fbdSmrg		       HARDWARE_CURSOR_BIT_ORDER_MSBFIRST;
221340e3fbdSmrg
222340e3fbdSmrg	pCurs->SetCursorColors = S3SetCursorColors;
223340e3fbdSmrg	pCurs->SetCursorPosition = S3SetCursorPosition;
224340e3fbdSmrg	pCurs->LoadCursorImage = S3LoadCursorImage;
225340e3fbdSmrg	pCurs->HideCursor = S3HideCursor;
226340e3fbdSmrg	pCurs->ShowCursor = S3ShowCursor;
227340e3fbdSmrg	pCurs->UseHWCursor = S3UseHWCursor;
228340e3fbdSmrg
229340e3fbdSmrg	return xf86InitCursor(pScreen, pCurs);
230340e3fbdSmrg}
231340e3fbdSmrg
232