1c06b6b69Smrg
2c06b6b69Smrg/*
3c06b6b69Smrg * Copyright 1994  The XFree86 Project
4c06b6b69Smrg *
5c06b6b69Smrg * Permission is hereby granted, free of charge, to any person obtaining a
6c06b6b69Smrg * copy of this software and associated documentation files (the "Software"),
7c06b6b69Smrg * to deal in the Software without restriction, including without limitation
8c06b6b69Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9c06b6b69Smrg * and/or sell copies of the Software, and to permit persons to whom the
10c06b6b69Smrg * Software is furnished to do so, subject to the following conditions:
11c06b6b69Smrg *
12c06b6b69Smrg * The above copyright notice and this permission notice shall be included in
13c06b6b69Smrg * all copies or substantial portions of the Software.
14c06b6b69Smrg *
15c06b6b69Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16c06b6b69Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17c06b6b69Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18c06b6b69Smrg * DAVID WEXELBLAT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19c06b6b69Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20c06b6b69Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21c06b6b69Smrg * SOFTWARE.
22c06b6b69Smrg *
23c06b6b69Smrg * Hardware Cursor for Trident utilizing XAA Cursor code.
24c06b6b69Smrg * Written by Alan Hourihane <alanh@fairlite.demon.co.uk>
25c06b6b69Smrg * Modified for Chips and Technologies by David Bateman <dbateman@eng.uts.edu.au>
26c06b6b69Smrg */
27c06b6b69Smrg
28c06b6b69Smrg#ifdef HAVE_CONFIG_H
29c06b6b69Smrg#include "config.h"
30c06b6b69Smrg#endif
31c06b6b69Smrg
32c06b6b69Smrg/* All drivers should typically include these */
33c06b6b69Smrg#include "xf86.h"
34c06b6b69Smrg#include "xf86_OSproc.h"
35c06b6b69Smrg
36c06b6b69Smrg/* Everything using inb/outb, etc needs "compiler.h" */
37c06b6b69Smrg#include "compiler.h"
38c06b6b69Smrg
39c06b6b69Smrg/* Drivers that need to access the PCI config space directly need this */
40c06b6b69Smrg#include "xf86Pci.h"
41c06b6b69Smrg
42c06b6b69Smrg#include "xf86Cursor.h"
43c06b6b69Smrg
44c06b6b69Smrg/* Driver specific headers */
45c06b6b69Smrg#include "ct_driver.h"
46c06b6b69Smrg
47c06b6b69Smrg/* Sync function, maybe this should check infoRec->NeedToSync before syncing */
4804109a1cSmacallan#ifdef HAVE_XAA_H
49c06b6b69Smrg#define CURSOR_SYNC(pScrn) \
50c06b6b69Smrg    if (IS_HiQV(cPtr)) { \
51c06b6b69Smrg	CHIPSHiQVSync(pScrn); \
52c06b6b69Smrg    } else { \
53c06b6b69Smrg	if(!cPtr->UseMMIO) { \
54c06b6b69Smrg	    CHIPSSync(pScrn); \
55c06b6b69Smrg	} else { \
56c06b6b69Smrg	    CHIPSMMIOSync(pScrn); \
57c06b6b69Smrg	} \
58c06b6b69Smrg    }
5904109a1cSmacallan#else
6004109a1cSmacallan#define CURSOR_SYNC(pScrn)
6104109a1cSmacallan#endif
62c06b6b69Smrg
63c06b6b69Smrg/* Swing your cursor bytes round and round... yeehaw! */
64c06b6b69Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN
65c06b6b69Smrg#define P_SWAP32( a , b )                \
66c06b6b69Smrg       ((char *)a)[0] = ((char *)b)[3];  \
67c06b6b69Smrg       ((char *)a)[1] = ((char *)b)[2];  \
68c06b6b69Smrg       ((char *)a)[2] = ((char *)b)[1];  \
69c06b6b69Smrg       ((char *)a)[3] = ((char *)b)[0]
70c06b6b69Smrg
71c06b6b69Smrg#define P_SWAP16( a , b )                \
72c06b6b69Smrg       ((char *)a)[0] = ((char *)b)[1];  \
73c06b6b69Smrg       ((char *)a)[1] = ((char *)b)[0];  \
74c06b6b69Smrg       ((char *)a)[2] = ((char *)b)[3];  \
75c06b6b69Smrg       ((char *)a)[3] = ((char *)b)[2]
76c06b6b69Smrg#endif
77c06b6b69Smrg
78c06b6b69Smrgstatic void
79c06b6b69SmrgCHIPSShowCursor(ScrnInfoPtr pScrn)
80c06b6b69Smrg{
81c06b6b69Smrg    CHIPSPtr cPtr = CHIPSPTR(pScrn);
82c06b6b69Smrg    unsigned char tmp;
83c06b6b69Smrg
84c06b6b69Smrg    CURSOR_SYNC(pScrn);
85c06b6b69Smrg
86c06b6b69Smrg    /* turn the cursor on */
87c06b6b69Smrg    if (IS_HiQV(cPtr)) {
88c06b6b69Smrg	tmp = cPtr->readXR(cPtr, 0xA0);
89c06b6b69Smrg	cPtr->writeXR(cPtr, 0xA0, (tmp & 0xF8) | 5);
90c06b6b69Smrg	if (cPtr->UseDualChannel &&
91c06b6b69Smrg	    (! xf86IsEntityShared(pScrn->entityList[0]))) {
92c06b6b69Smrg	    unsigned int IOSS, MSS;
93c06b6b69Smrg	    IOSS = cPtr->readIOSS(cPtr);
94c06b6b69Smrg	    MSS = cPtr->readMSS(cPtr);
95c06b6b69Smrg	    cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) |
96c06b6b69Smrg				   IOSS_PIPE_B));
97c06b6b69Smrg	    cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS &
98c06b6b69Smrg				  MSS_MASK) | MSS_PIPE_B));
99c06b6b69Smrg	    tmp = cPtr->readXR(cPtr, 0xA0);
100c06b6b69Smrg	    cPtr->writeXR(cPtr, 0xA0, (tmp & 0xF8) | 5);
101c06b6b69Smrg	    cPtr->writeIOSS(cPtr, IOSS);
102c06b6b69Smrg	    cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), MSS);
103c06b6b69Smrg	}
104c06b6b69Smrg    } else {
105c06b6b69Smrg	if(!cPtr->UseMMIO) {
106c06b6b69Smrg	    HW_DEBUG(0x8);
107c06b6b69Smrg	    outw(cPtr->PIOBase+DR(0x8), 0x21);
108c06b6b69Smrg	} else {
109c06b6b69Smrg	    HW_DEBUG(DR(8));
110c06b6b69Smrg	    /*  Used to be: MMIOmemw(MR(8)) = 0x21; */
111c06b6b69Smrg	    MMIOmeml(MR(8)) = 0x21;
112c06b6b69Smrg	}
113c06b6b69Smrg    }
114c06b6b69Smrg    cPtr->HWCursorShown = TRUE;
115c06b6b69Smrg}
116c06b6b69Smrg
117c06b6b69Smrgstatic void
118c06b6b69SmrgCHIPSHideCursor(ScrnInfoPtr pScrn)
119c06b6b69Smrg{
120c06b6b69Smrg    CHIPSPtr cPtr = CHIPSPTR(pScrn);
121c06b6b69Smrg    unsigned char tmp;
122c06b6b69Smrg
123c06b6b69Smrg    CURSOR_SYNC(pScrn);
124c06b6b69Smrg
125c06b6b69Smrg    /* turn the cursor off */
126c06b6b69Smrg    if (IS_HiQV(cPtr)) {
127c06b6b69Smrg	tmp = cPtr->readXR(cPtr, 0xA0);
128c06b6b69Smrg	cPtr->writeXR(cPtr, 0xA0, tmp & 0xF8);
129c06b6b69Smrg	if (cPtr->UseDualChannel &&
130c06b6b69Smrg	    (! xf86IsEntityShared(pScrn->entityList[0]))) {
131c06b6b69Smrg	    unsigned int IOSS, MSS;
132c06b6b69Smrg	    IOSS = cPtr->readIOSS(cPtr);
133c06b6b69Smrg	    MSS = cPtr->readMSS(cPtr);
134c06b6b69Smrg	    cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) |
135c06b6b69Smrg				   IOSS_PIPE_B));
136c06b6b69Smrg	    cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS &
137c06b6b69Smrg				  MSS_MASK) | MSS_PIPE_B));
138c06b6b69Smrg	    tmp = cPtr->readXR(cPtr, 0xA0);
139c06b6b69Smrg	    cPtr->writeXR(cPtr, 0xA0, tmp & 0xF8);
140c06b6b69Smrg	    cPtr->writeIOSS(cPtr, IOSS);
141c06b6b69Smrg	    cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), MSS);
142c06b6b69Smrg	}
143c06b6b69Smrg    } else {
144c06b6b69Smrg	if(!cPtr->UseMMIO) {
145c06b6b69Smrg	    HW_DEBUG(0x8);
146c06b6b69Smrg	    outw(cPtr->PIOBase+DR(0x8), 0x20);
147c06b6b69Smrg	} else {
148c06b6b69Smrg	    HW_DEBUG(DR(0x8));
149c06b6b69Smrg	    /* Used to be: MMIOmemw(DR(0x8)) = 0x20; */
150c06b6b69Smrg	    MMIOmeml(DR(0x8)) = 0x20;
151c06b6b69Smrg	}
152c06b6b69Smrg    }
153c06b6b69Smrg    cPtr->HWCursorShown = FALSE;
154c06b6b69Smrg}
155c06b6b69Smrg
156c06b6b69Smrgstatic void
157c06b6b69SmrgCHIPSSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
158c06b6b69Smrg{
159c06b6b69Smrg    CHIPSPtr cPtr = CHIPSPTR(pScrn);
160c06b6b69Smrg
161c06b6b69Smrg    CURSOR_SYNC(pScrn);
162c06b6b69Smrg
163c06b6b69Smrg    if (x < 0)
164c06b6b69Smrg	x = ~(x-1) | 0x8000;
165c06b6b69Smrg    if (y < 0)
166c06b6b69Smrg	y = ~(y-1) | 0x8000;
167c06b6b69Smrg
168c06b6b69Smrg    /* Program the cursor origin (offset into the cursor bitmap). */
169c06b6b69Smrg    if (IS_HiQV(cPtr)) {
170c06b6b69Smrg	cPtr->writeXR(cPtr, 0xA4, x & 0xFF);
171c06b6b69Smrg	cPtr->writeXR(cPtr, 0xA5, (x >> 8) & 0x87);
172c06b6b69Smrg	cPtr->writeXR(cPtr, 0xA6, y & 0xFF);
173c06b6b69Smrg	cPtr->writeXR(cPtr, 0xA7, (y >> 8) & 0x87);
174c06b6b69Smrg	if (cPtr->UseDualChannel &&
175c06b6b69Smrg	    (! xf86IsEntityShared(pScrn->entityList[0]))) {
176c06b6b69Smrg	    unsigned int IOSS, MSS;
177c06b6b69Smrg	    IOSS = cPtr->readIOSS(cPtr);
178c06b6b69Smrg	    MSS = cPtr->readMSS(cPtr);
179c06b6b69Smrg	    cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) |
180c06b6b69Smrg				   IOSS_PIPE_B));
181c06b6b69Smrg	    cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS &
182c06b6b69Smrg				  MSS_MASK) | MSS_PIPE_B));
183c06b6b69Smrg	    cPtr->writeXR(cPtr, 0xA4, x & 0xFF);
184c06b6b69Smrg	    cPtr->writeXR(cPtr, 0xA5, (x >> 8) & 0x87);
185c06b6b69Smrg	    cPtr->writeXR(cPtr, 0xA6, y & 0xFF);
186c06b6b69Smrg	    cPtr->writeXR(cPtr, 0xA7, (y >> 8) & 0x87);
187c06b6b69Smrg	    cPtr->writeIOSS(cPtr, IOSS);
188c06b6b69Smrg	    cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), MSS);
189c06b6b69Smrg	}
190c06b6b69Smrg    } else {
191c06b6b69Smrg	CARD32 xy;
192c06b6b69Smrg
193c06b6b69Smrg	xy = y;
194c06b6b69Smrg	xy = (xy << 16) | x;
195c06b6b69Smrg	if(!cPtr->UseMMIO) {
196c06b6b69Smrg	    HW_DEBUG(0xB);
197c06b6b69Smrg	    outl(cPtr->PIOBase+DR(0xB), xy);
198c06b6b69Smrg	} else {
199c06b6b69Smrg	    HW_DEBUG(MR(0xB));
200c06b6b69Smrg	    MMIOmeml(MR(0xB)) = xy;
201c06b6b69Smrg	}
202c06b6b69Smrg    }
203c06b6b69Smrg}
204c06b6b69Smrg
205c06b6b69Smrgstatic void
206c06b6b69SmrgCHIPSSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
207c06b6b69Smrg{
208c06b6b69Smrg    CHIPSPtr cPtr = CHIPSPTR(pScrn);
209c06b6b69Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
210c06b6b69Smrg    CARD32 packedcolfg, packedcolbg;
211c06b6b69Smrg
212c06b6b69Smrg    CURSOR_SYNC(pScrn);
213c06b6b69Smrg
214c06b6b69Smrg    if (IS_HiQV(cPtr)) {
215c06b6b69Smrg	unsigned char xr80;
216c06b6b69Smrg
217c06b6b69Smrg	/* Enable extended palette addressing */
218c06b6b69Smrg	xr80 = cPtr->readXR(cPtr, 0x80);
219c06b6b69Smrg	cPtr->writeXR(cPtr, 0x80, xr80 | 0x1);
220c06b6b69Smrg
221c06b6b69Smrg	/* Write the new colours to the extended VGA palette. Palette
222c06b6b69Smrg	 * index is incremented after each write, so only write index
223c06b6b69Smrg	 * once
224c06b6b69Smrg	 */
225c06b6b69Smrg	hwp->writeDacWriteAddr(hwp, 0x04);
226c06b6b69Smrg	if (xr80 & 0x80) {
227c06b6b69Smrg	    /* 8bit DAC */
228c06b6b69Smrg	    hwp->writeDacData(hwp, (bg >> 16) & 0xFF);
229c06b6b69Smrg	    hwp->writeDacData(hwp, (bg >> 8) & 0xFF);
230c06b6b69Smrg	    hwp->writeDacData(hwp, bg & 0xFF);
231c06b6b69Smrg	    hwp->writeDacData(hwp, (fg >> 16) & 0xFF);
232c06b6b69Smrg	    hwp->writeDacData(hwp, (fg >> 8) & 0xFF);
233c06b6b69Smrg	    hwp->writeDacData(hwp, fg & 0xFF);
234c06b6b69Smrg	} else {
235c06b6b69Smrg	    /* 6bit DAC */
236c06b6b69Smrg	    hwp->writeDacData(hwp, (bg >> 18) & 0xFF);
237c06b6b69Smrg	    hwp->writeDacData(hwp, (bg >> 10) & 0xFF);
238c06b6b69Smrg	    hwp->writeDacData(hwp, (bg >> 2) & 0xFF);
239c06b6b69Smrg	    hwp->writeDacData(hwp, (fg >> 18) & 0xFF);
240c06b6b69Smrg	    hwp->writeDacData(hwp, (fg >> 10) & 0xFF);
241c06b6b69Smrg	    hwp->writeDacData(hwp, (fg >> 2) & 0xFF);
242c06b6b69Smrg	}
243c06b6b69Smrg	/* Enable normal palette addressing */
244c06b6b69Smrg	cPtr->writeXR(cPtr, 0x80, xr80);
245c06b6b69Smrg
246c06b6b69Smrg	if (cPtr->UseDualChannel &&
247c06b6b69Smrg	    (! xf86IsEntityShared(pScrn->entityList[0]))) {
248c06b6b69Smrg	    unsigned int IOSS, MSS;
249c06b6b69Smrg	    IOSS = cPtr->readIOSS(cPtr);
250c06b6b69Smrg	    MSS = cPtr->readMSS(cPtr);
251c06b6b69Smrg	    cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) |
252c06b6b69Smrg				   IOSS_PIPE_B));
253c06b6b69Smrg	    cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) |
254c06b6b69Smrg				   MSS_PIPE_B));
255c06b6b69Smrg	    /* Enable extended palette addressing */
256c06b6b69Smrg	    xr80 = cPtr->readXR(cPtr, 0x80);
257c06b6b69Smrg	    cPtr->writeXR(cPtr, 0x80, xr80 | 0x1);
258c06b6b69Smrg
259c06b6b69Smrg	    /* Write the new colours to the extended VGA palette. Palette
260c06b6b69Smrg	     * index is incremented after each write, so only write index
261c06b6b69Smrg	     * once
262c06b6b69Smrg	     */
263c06b6b69Smrg	    hwp->writeDacWriteAddr(hwp, 0x04);
264c06b6b69Smrg	    if (xr80 & 0x80) {
265c06b6b69Smrg		/* 8bit DAC */
266c06b6b69Smrg		hwp->writeDacData(hwp, (bg >> 16) & 0xFF);
267c06b6b69Smrg		hwp->writeDacData(hwp, (bg >> 8) & 0xFF);
268c06b6b69Smrg		hwp->writeDacData(hwp, bg & 0xFF);
269c06b6b69Smrg		hwp->writeDacData(hwp, (fg >> 16) & 0xFF);
270c06b6b69Smrg		hwp->writeDacData(hwp, (fg >> 8) & 0xFF);
271c06b6b69Smrg		hwp->writeDacData(hwp, fg & 0xFF);
272c06b6b69Smrg	    } else {
273c06b6b69Smrg		/* 6bit DAC */
274c06b6b69Smrg		hwp->writeDacData(hwp, (bg >> 18) & 0xFF);
275c06b6b69Smrg		hwp->writeDacData(hwp, (bg >> 10) & 0xFF);
276c06b6b69Smrg		hwp->writeDacData(hwp, (bg >> 2) & 0xFF);
277c06b6b69Smrg		hwp->writeDacData(hwp, (fg >> 18) & 0xFF);
278c06b6b69Smrg		hwp->writeDacData(hwp, (fg >> 10) & 0xFF);
279c06b6b69Smrg		hwp->writeDacData(hwp, (fg >> 2) & 0xFF);
280c06b6b69Smrg	    }
281c06b6b69Smrg	    /* Enable normal palette addressing */
282c06b6b69Smrg	    cPtr->writeXR(cPtr, 0x80, xr80);
283c06b6b69Smrg	    cPtr->writeIOSS(cPtr, IOSS);
284c06b6b69Smrg	    cPtr->writeMSS(cPtr, hwp, MSS);
285c06b6b69Smrg	}
286c06b6b69Smrg    } else if (IS_Wingine(cPtr)) {
287c06b6b69Smrg	outl(cPtr->PIOBase+DR(0xA), (bg & 0xFFFFFF));
288c06b6b69Smrg	outl(cPtr->PIOBase+DR(0x9), (fg & 0xFFFFFF));
289c06b6b69Smrg    } else {
290c06b6b69Smrg	packedcolfg =  ((fg & 0xF80000) >> 8) | ((fg & 0xFC00) >> 5)
291c06b6b69Smrg	    | ((fg & 0xF8) >> 3);
292c06b6b69Smrg	packedcolbg =  ((bg & 0xF80000) >> 8) | ((bg & 0xFC00) >> 5)
293c06b6b69Smrg	    | ((bg & 0xF8) >> 3);
294c06b6b69Smrg	packedcolfg = (packedcolfg << 16) | packedcolbg;
295c06b6b69Smrg	if(!cPtr->UseMMIO) {
296c06b6b69Smrg	    HW_DEBUG(0x9);
297c06b6b69Smrg	    outl(cPtr->PIOBase+DR(0x9), packedcolfg);
298c06b6b69Smrg	} else {
299c06b6b69Smrg	    MMIOmeml(MR(0x9)) = packedcolfg;
300c06b6b69Smrg	    HW_DEBUG(MR(0x9));
301c06b6b69Smrg	}
302c06b6b69Smrg    }
303c06b6b69Smrg}
304c06b6b69Smrg
305c06b6b69Smrgstatic void
306c06b6b69SmrgCHIPSLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
307c06b6b69Smrg{
308c06b6b69Smrg    CHIPSPtr cPtr = CHIPSPTR(pScrn);
309c06b6b69Smrg    CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn);
310c06b6b69Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN
311c06b6b69Smrg    CARD32 *s = (pointer)src;
312c06b6b69Smrg    CARD32 *d = (pointer)(cPtr->FbBase + cAcl->CursorAddress);
313c06b6b69Smrg    int y;
314c06b6b69Smrg#endif
315c06b6b69Smrg
316c06b6b69Smrg    CURSOR_SYNC(pScrn);
317c06b6b69Smrg
318c06b6b69Smrg    if (cPtr->cursorDelay) {
319c06b6b69Smrg	usleep(200000);
320c06b6b69Smrg	cPtr->cursorDelay = FALSE;
321c06b6b69Smrg    }
322c06b6b69Smrg
323c06b6b69Smrg    if (IS_Wingine(cPtr)) {
324c06b6b69Smrg	int i;
325c06b6b69Smrg	CARD32 *tmp = (CARD32 *)src;
326c06b6b69Smrg
327c06b6b69Smrg	outl(cPtr->PIOBase+DR(0x8),0x20);
328c06b6b69Smrg	for (i=0; i<64; i++) {
329c06b6b69Smrg	    outl(cPtr->PIOBase+DR(0xC),*(CARD32 *)tmp);
330c06b6b69Smrg	    tmp++;
331c06b6b69Smrg	}
332c06b6b69Smrg    } else {
333c06b6b69Smrg	if (cPtr->Flags & ChipsLinearSupport) {
334c06b6b69Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN
335c06b6b69Smrg	    /* On big endian machines we must flip our cursor image around. */
336c06b6b69Smrg    	    switch(pScrn->bitsPerPixel >> 3) {
337c06b6b69Smrg    	        case 4:
338c06b6b69Smrg    	        case 3:
339c06b6b69Smrg#if 1
340c06b6b69Smrg		    memcpy((unsigned char *)cPtr->FbBase + cAcl->CursorAddress,
341c06b6b69Smrg			   src, cPtr->CursorInfoRec->MaxWidth *
342c06b6b69Smrg			   cPtr->CursorInfoRec->MaxHeight / 4);
343c06b6b69Smrg#else
344c06b6b69Smrg        	    for (y = 0; y < 64; y++) {
345c06b6b69Smrg            	        P_SWAP32(d,s);
346c06b6b69Smrg            	        d++; s++;
347c06b6b69Smrg            	        P_SWAP32(d,s);
348c06b6b69Smrg            	        d++; s++;
349c06b6b69Smrg            	        P_SWAP32(d,s);
350c06b6b69Smrg            	        d++; s++;
351c06b6b69Smrg            	        P_SWAP32(d,s);
352c06b6b69Smrg            	        d++; s++;
353c06b6b69Smrg        	    }
354c06b6b69Smrg#endif
355c06b6b69Smrg        	    break;
356c06b6b69Smrg    	        case 2:
357c06b6b69Smrg           	    for (y = 0; y < 64; y++) {
358c06b6b69Smrg            	        P_SWAP16(d,s);
359c06b6b69Smrg            	        d++; s++;
360c06b6b69Smrg                        P_SWAP16(d,s);
361c06b6b69Smrg                        d++; s++;
362c06b6b69Smrg                        P_SWAP16(d,s);
363c06b6b69Smrg                        d++; s++;
364c06b6b69Smrg                        P_SWAP16(d,s);
365c06b6b69Smrg                        d++; s++;
366c06b6b69Smrg                    }
367c06b6b69Smrg                    break;
368c06b6b69Smrg                default:
369c06b6b69Smrg                    for (y = 0; y < 64; y++) {
370c06b6b69Smrg                        *d++ = *s++;
371c06b6b69Smrg                        *d++ = *s++;
372c06b6b69Smrg                        *d++ = *s++;
373c06b6b69Smrg                        *d++ = *s++;
374c06b6b69Smrg                    }
375c06b6b69Smrg            }
376c06b6b69Smrg#else
377c06b6b69Smrg	    memcpy((unsigned char *)cPtr->FbBase + cAcl->CursorAddress,
378c06b6b69Smrg			src, cPtr->CursorInfoRec->MaxWidth *
379c06b6b69Smrg			cPtr->CursorInfoRec->MaxHeight / 4);
380c06b6b69Smrg#endif
381c06b6b69Smrg	} else {
382c06b6b69Smrg	    /*
383c06b6b69Smrg	     * The cursor can only be in the last 16K of video memory,
384c06b6b69Smrg	     * which fits in the last banking window.
385c06b6b69Smrg	     */
386c06b6b69Smrg	    if (IS_HiQV(cPtr))
387c06b6b69Smrg		if (pScrn->bitsPerPixel < 8)
388c06b6b69Smrg		    CHIPSHiQVSetReadWritePlanar(pScrn->pScreen,
389c06b6b69Smrg					    (int)(cAcl->CursorAddress >> 16));
390c06b6b69Smrg		else
391c06b6b69Smrg		    CHIPSHiQVSetReadWrite(pScrn->pScreen,
392c06b6b69Smrg					    (int)(cAcl->CursorAddress >> 16));
393c06b6b69Smrg	    else
394c06b6b69Smrg		if (pScrn->bitsPerPixel < 8)
395c06b6b69Smrg		    CHIPSSetWritePlanar(pScrn->pScreen,
396c06b6b69Smrg					    (int)(cAcl->CursorAddress >> 16));
397c06b6b69Smrg		else
398c06b6b69Smrg		    CHIPSSetWrite(pScrn->pScreen,
399c06b6b69Smrg					    (int)(cAcl->CursorAddress >> 16));
400c06b6b69Smrg	    memcpy((unsigned char *)cPtr->FbBase + (cAcl->CursorAddress &
401c06b6b69Smrg			0xFFFF), src,  cPtr->CursorInfoRec->MaxWidth *
402c06b6b69Smrg			cPtr->CursorInfoRec->MaxHeight / 4);
403c06b6b69Smrg	}
404c06b6b69Smrg    }
405c06b6b69Smrg
406c06b6b69Smrg    /* set cursor address here or we loose the cursor on video mode change */
407c06b6b69Smrg    if (IS_HiQV(cPtr)) {
408c06b6b69Smrg	cPtr->writeXR(cPtr, 0xA2, (cAcl->CursorAddress >> 8) & 0xFF);
409c06b6b69Smrg	cPtr->writeXR(cPtr, 0xA3, (cAcl->CursorAddress >> 16) & 0x3F);
410c06b6b69Smrg	if (cPtr->UseDualChannel &&
411c06b6b69Smrg	    (! xf86IsEntityShared(pScrn->entityList[0]))) {
412c06b6b69Smrg	    unsigned int IOSS, MSS;
413c06b6b69Smrg	    IOSS = cPtr->readIOSS(cPtr);
414c06b6b69Smrg	    MSS = cPtr->readMSS(cPtr);
415c06b6b69Smrg	    cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) |
416c06b6b69Smrg				   IOSS_PIPE_B));
417c06b6b69Smrg	    cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS &
418c06b6b69Smrg				  MSS_MASK) | MSS_PIPE_B));
419c06b6b69Smrg	    cPtr->writeXR(cPtr, 0xA2, (cAcl->CursorAddress >> 8) & 0xFF);
420c06b6b69Smrg	    cPtr->writeXR(cPtr, 0xA3, (cAcl->CursorAddress >> 16) & 0x3F);
421c06b6b69Smrg	    cPtr->writeIOSS(cPtr, IOSS);
422c06b6b69Smrg	    cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), MSS);
423c06b6b69Smrg	}
424c06b6b69Smrg    } else if (!IS_Wingine(cPtr)) {
425c06b6b69Smrg	if (!cPtr->UseMMIO) {
426c06b6b69Smrg	    HW_DEBUG(0xC);
427c06b6b69Smrg	    outl(cPtr->PIOBase+DR(0xC), cAcl->CursorAddress);
428c06b6b69Smrg	} else {
429c06b6b69Smrg	    HW_DEBUG(MR(0xC));
430c06b6b69Smrg	    MMIOmeml(MR(0xC)) = cAcl->CursorAddress;
431c06b6b69Smrg	}
432c06b6b69Smrg    }
433c06b6b69Smrg}
434c06b6b69Smrg
435c06b6b69Smrgstatic Bool
436c06b6b69SmrgCHIPSUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
437c06b6b69Smrg{
438a1d73b4bSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
439c06b6b69Smrg    CHIPSPtr cPtr = CHIPSPTR(pScrn);
440c06b6b69Smrg
441c06b6b69Smrg    return (((cPtr->Flags & ChipsHWCursor) != 0)
442c06b6b69Smrg	    && !(pScrn->currentMode->Flags & V_DBLSCAN));
443c06b6b69Smrg}
444c06b6b69Smrg
445c06b6b69SmrgBool
446c06b6b69SmrgCHIPSCursorInit(ScreenPtr pScreen)
447c06b6b69Smrg{
448a1d73b4bSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
449c06b6b69Smrg    CHIPSPtr cPtr = CHIPSPTR(pScrn);
450c06b6b69Smrg    xf86CursorInfoPtr infoPtr;
451c06b6b69Smrg
452c06b6b69Smrg    infoPtr = xf86CreateCursorInfoRec();
453c06b6b69Smrg    if(!infoPtr) return FALSE;
454c06b6b69Smrg
455c06b6b69Smrg    cPtr->CursorInfoRec = infoPtr;
456c06b6b69Smrg
457c06b6b69Smrg    infoPtr->Flags =
458c06b6b69Smrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN
459c06b6b69Smrg	HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
460c06b6b69Smrg#endif
461c06b6b69Smrg	HARDWARE_CURSOR_INVERT_MASK |
462c06b6b69Smrg	HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
463c06b6b69Smrg	HARDWARE_CURSOR_TRUECOLOR_AT_8BPP;
464c06b6b69Smrg
465c06b6b69Smrg    if (IS_HiQV(cPtr)) {
466c06b6b69Smrg	infoPtr->Flags |= HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64;
467c06b6b69Smrg	infoPtr->MaxHeight = 64;
468c06b6b69Smrg	infoPtr->MaxWidth = 64;
469c06b6b69Smrg    } else if (IS_Wingine(cPtr)) {
470c06b6b69Smrg	infoPtr->Flags |= HARDWARE_CURSOR_SOURCE_MASK_NOT_INTERLEAVED;
471c06b6b69Smrg	infoPtr->MaxHeight = 32;
472c06b6b69Smrg	infoPtr->MaxWidth = 32;
473c06b6b69Smrg    } else {
474c06b6b69Smrg	infoPtr->Flags |= HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8;
475c06b6b69Smrg	infoPtr->MaxHeight = 32;
476c06b6b69Smrg	infoPtr->MaxWidth = 32;
477c06b6b69Smrg    }
478c06b6b69Smrg
479c06b6b69Smrg    infoPtr->SetCursorColors = CHIPSSetCursorColors;
480c06b6b69Smrg    infoPtr->SetCursorPosition = CHIPSSetCursorPosition;
481c06b6b69Smrg    infoPtr->LoadCursorImage = CHIPSLoadCursorImage;
482c06b6b69Smrg    infoPtr->HideCursor = CHIPSHideCursor;
483c06b6b69Smrg    infoPtr->ShowCursor = CHIPSShowCursor;
484c06b6b69Smrg    infoPtr->UseHWCursor = CHIPSUseHWCursor;
485c06b6b69Smrg
486c06b6b69Smrg    return(xf86InitCursor(pScreen, infoPtr));
487c06b6b69Smrg}
488c06b6b69Smrg
489