s3_cursor.c revision 340e3fbd
1/*
2 *      Copyright 2001  Ani Joshi <ajoshi@unixbox.com>
3 *
4 *      XFree86 4.x driver for S3 chipsets
5 *
6 *
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that copyright
10 * notice and this permission notice appear in supporting documentation and
11 * that the name of Ani Joshi not be used in advertising or
12 * publicity pertaining to distribution of the software without specific,
13 * written prior permission.  Ani Joshi makes no representations
14 * about the suitability of this software for any purpose.  It is provided
15 * "as-is" without express or implied warranty.
16 *
17 * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19 * EVENT SHALL ANI JOSHI BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23 * PERFORMANCE OF THIS SOFTWARE.
24 *
25 *
26 */
27/* $XFree86: $ */
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include "xf86.h"
34#include "xf86_OSproc.h"
35
36#include "compiler.h"
37
38#include "s3.h"
39#include "s3_reg.h"
40
41
42static void S3SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
43{
44	S3Ptr pS3 = S3PTR(pScrn);
45	int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
46	unsigned short packfg, packbg;
47
48	switch (pS3->s3Bpp) {
49	case 1:
50		/* XXX Trio series only */
51		outb(vgaCRIndex, 0x45);
52		inb(vgaCRReg);
53		outb(vgaCRIndex, 0x4a);
54		outb(vgaCRReg, fg);
55		outb(vgaCRReg, fg);
56
57		outb(vgaCRIndex, 0x45);
58		inb(vgaCRReg);
59		outb(vgaCRIndex, 0x4b);
60		outb(vgaCRReg, bg);
61		outb(vgaCRReg, bg);
62
63		break;
64	case 2:
65		/* XXX depth 16 */
66		packfg = ((fg & 0x00f80000) >> 19) | ((fg & 0x0000fc00) >> 5) |
67			 ((fg & 0x000000f8) << 8);
68		packbg = ((bg & 0x00f80000) >> 19) | ((bg & 0x0000fc00) >> 5) |
69			 ((bg & 0x000000f8) << 8);
70
71		outb(vgaCRIndex, 0x45);
72		inb(vgaCRReg);
73		outb(vgaCRIndex, 0x4a);
74		outb(vgaCRReg, packfg);
75		outb(vgaCRReg, packfg >> 8);
76
77		outb(vgaCRIndex, 0x45);
78		inb(vgaCRReg);
79		outb(vgaCRIndex, 0x4b);
80		outb(vgaCRReg, packbg);
81		outb(vgaCRReg, packbg >> 8);
82
83		break;
84	default:
85		outb(vgaCRIndex, 0x45);
86		inb(vgaCRReg);
87		outb(vgaCRIndex, 0x4a);
88		outb(vgaCRReg, (fg & 0x00ff0000) >> 16);
89		outb(vgaCRReg, (fg & 0x0000ff00) >> 8);
90		outb(vgaCRReg, (fg & 0x000000ff));
91
92		outb(vgaCRIndex, 0x45);
93		inb(vgaCRReg);
94		outb(vgaCRIndex, 0x4b);
95		outb(vgaCRReg, (bg & 0x00ff0000) >> 16);
96		outb(vgaCRReg, (bg & 0x0000ff00) >> 8);
97		outb(vgaCRReg, (bg & 0x000000ff));
98
99		break;
100	}
101}
102
103
104static void S3SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
105{
106	S3Ptr pS3 = S3PTR(pScrn);
107	int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
108
109	outb(vgaCRIndex, 0x39);
110	outb(vgaCRReg, 0xa5);
111
112	outb(vgaCRIndex, 0x46);
113	outb(vgaCRReg, x >> 8);
114	outb(vgaCRIndex, 0x47);
115	outb(vgaCRReg, x);
116
117	outb(vgaCRIndex, 0x49);
118	outb(vgaCRReg, y);
119	outb(vgaCRIndex, 0x48);
120	outb(vgaCRReg, y >> 8);
121}
122
123
124static void S3HideCursor(ScrnInfoPtr pScrn)
125{
126	S3Ptr pS3 = S3PTR(pScrn);
127	int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
128	unsigned char tmp;
129
130	outb(vgaCRIndex, 0x45);
131	tmp = inb(vgaCRReg);
132	outb(vgaCRReg, tmp & ~0x01);
133}
134
135
136static void S3ShowCursor(ScrnInfoPtr pScrn)
137{
138	S3Ptr pS3 = S3PTR(pScrn);
139	int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
140	unsigned char tmp;
141
142	outb(vgaCRIndex, 0x39);
143	outb(vgaCRReg, 0xa5);
144
145	outb(vgaCRIndex, 0x55);
146	tmp = inb(vgaCRReg);
147	outb(vgaCRReg, tmp | 0x10);
148
149	outb(vgaCRIndex, 0x4c);
150	outb(vgaCRReg, pS3->FBCursorOffset >> 8);
151	outb(vgaCRIndex, 0x4d);
152	outb(vgaCRReg, pS3->FBCursorOffset);
153
154	outb(vgaCRIndex, 0x45);
155	tmp = inb(vgaCRReg);
156	outb(vgaCRReg, tmp | 0x01);
157}
158
159
160static void S3LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image)
161{
162	S3Ptr pS3 = S3PTR(pScrn);
163	int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
164	unsigned char cr45;
165
166	outb(vgaCRIndex, 0x39);
167	outb(vgaCRReg, 0xa5);
168
169	WaitIdle();
170
171	VerticalRetraceWait();
172
173	outb(vgaCRIndex, 0x45);
174	cr45 = inb(vgaCRReg);
175	outb(vgaCRReg, cr45 & 0xfe);
176
177	outb(vgaCRIndex, 0x46);
178	outb(vgaCRReg, 0xff);
179	outb(vgaCRIndex, 0x47);
180	outb(vgaCRReg, 0x7f);
181	outb(vgaCRIndex, 0x49);
182	outb(vgaCRReg, 0xff);
183	outb(vgaCRIndex, 0x4e);
184	outb(vgaCRReg, 0x3f);
185	outb(vgaCRIndex, 0x4f);
186	outb(vgaCRReg, 0x3f);
187	outb(vgaCRIndex, 0x48);
188	outb(vgaCRReg, 0x7f);
189
190	memcpy(pS3->FBBase + (pS3->FBCursorOffset * 1024), image, 1024);
191
192	VerticalRetraceWait();
193
194	outb(vgaCRIndex, 0x45);
195	outb(vgaCRReg, cr45);
196}
197
198
199static Bool S3UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
200{
201	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
202	S3Ptr pS3 = S3PTR(pScrn);
203	return (pS3->hwCursor);
204}
205
206
207Bool S3_CursorInit(ScreenPtr pScreen)
208{
209	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
210	S3Ptr pS3 = S3PTR(pScrn);
211	xf86CursorInfoPtr pCurs;
212
213	if (!(pCurs = pS3->pCurs = xf86CreateCursorInfoRec()))
214		return FALSE;
215
216	pCurs->MaxWidth = 64;
217	pCurs->MaxHeight = 64;
218	pCurs->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
219		       HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
220		       HARDWARE_CURSOR_BIT_ORDER_MSBFIRST;
221
222	pCurs->SetCursorColors = S3SetCursorColors;
223	pCurs->SetCursorPosition = S3SetCursorPosition;
224	pCurs->LoadCursorImage = S3LoadCursorImage;
225	pCurs->HideCursor = S3HideCursor;
226	pCurs->ShowCursor = S3ShowCursor;
227	pCurs->UseHWCursor = S3UseHWCursor;
228
229	return xf86InitCursor(pScreen, pCurs);
230}
231
232