#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86_ansic.h"
#include "compiler.h"
#include "xf86PciInfo.h"
#include "xf86Pci.h"
#include "xf86Cursor.h"
#include "ct_driver.h"
#define CURSOR_SYNC(pScrn) \
if (IS_HiQV(cPtr)) { \
CHIPSHiQVSync(pScrn); \
} else { \
if(!cPtr->UseMMIO) { \
CHIPSSync(pScrn); \
} else { \
CHIPSMMIOSync(pScrn); \
} \
}
#if X_BYTE_ORDER == X_BIG_ENDIAN
#define P_SWAP32( a , b ) \
((char *)a)[0] = ((char *)b)[3]; \
((char *)a)[1] = ((char *)b)[2]; \
((char *)a)[2] = ((char *)b)[1]; \
((char *)a)[3] = ((char *)b)[0]
#define P_SWAP16( a , b ) \
((char *)a)[0] = ((char *)b)[1]; \
((char *)a)[1] = ((char *)b)[0]; \
((char *)a)[2] = ((char *)b)[3]; \
((char *)a)[3] = ((char *)b)[2]
#endif
static void
CHIPSShowCursor(ScrnInfoPtr pScrn)
{
CHIPSPtr cPtr = CHIPSPTR(pScrn);
unsigned char tmp;
CURSOR_SYNC(pScrn);
if (IS_HiQV(cPtr)) {
tmp = cPtr->readXR(cPtr, 0xA0);
cPtr->writeXR(cPtr, 0xA0, (tmp & 0xF8) | 5);
if (cPtr->UseDualChannel &&
(! xf86IsEntityShared(pScrn->entityList[0]))) {
unsigned int IOSS, MSS;
IOSS = cPtr->readIOSS(cPtr);
MSS = cPtr->readMSS(cPtr);
cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) |
IOSS_PIPE_B));
cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS &
MSS_MASK) | MSS_PIPE_B));
tmp = cPtr->readXR(cPtr, 0xA0);
cPtr->writeXR(cPtr, 0xA0, (tmp & 0xF8) | 5);
cPtr->writeIOSS(cPtr, IOSS);
cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), MSS);
}
} else {
if(!cPtr->UseMMIO) {
HW_DEBUG(0x8);
outw(cPtr->PIOBase+DR(0x8), 0x21);
} else {
HW_DEBUG(DR(8));
MMIOmeml(MR(8)) = 0x21;
}
}
cPtr->HWCursorShown = TRUE;
}
static void
CHIPSHideCursor(ScrnInfoPtr pScrn)
{
CHIPSPtr cPtr = CHIPSPTR(pScrn);
unsigned char tmp;
CURSOR_SYNC(pScrn);
if (IS_HiQV(cPtr)) {
tmp = cPtr->readXR(cPtr, 0xA0);
cPtr->writeXR(cPtr, 0xA0, tmp & 0xF8);
if (cPtr->UseDualChannel &&
(! xf86IsEntityShared(pScrn->entityList[0]))) {
unsigned int IOSS, MSS;
IOSS = cPtr->readIOSS(cPtr);
MSS = cPtr->readMSS(cPtr);
cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) |
IOSS_PIPE_B));
cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS &
MSS_MASK) | MSS_PIPE_B));
tmp = cPtr->readXR(cPtr, 0xA0);
cPtr->writeXR(cPtr, 0xA0, tmp & 0xF8);
cPtr->writeIOSS(cPtr, IOSS);
cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), MSS);
}
} else {
if(!cPtr->UseMMIO) {
HW_DEBUG(0x8);
outw(cPtr->PIOBase+DR(0x8), 0x20);
} else {
HW_DEBUG(DR(0x8));
MMIOmeml(DR(0x8)) = 0x20;
}
}
cPtr->HWCursorShown = FALSE;
}
static void
CHIPSSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
{
CHIPSPtr cPtr = CHIPSPTR(pScrn);
CURSOR_SYNC(pScrn);
if (x < 0)
x = ~(x-1) | 0x8000;
if (y < 0)
y = ~(y-1) | 0x8000;
if (IS_HiQV(cPtr)) {
cPtr->writeXR(cPtr, 0xA4, x & 0xFF);
cPtr->writeXR(cPtr, 0xA5, (x >> 8) & 0x87);
cPtr->writeXR(cPtr, 0xA6, y & 0xFF);
cPtr->writeXR(cPtr, 0xA7, (y >> 8) & 0x87);
if (cPtr->UseDualChannel &&
(! xf86IsEntityShared(pScrn->entityList[0]))) {
unsigned int IOSS, MSS;
IOSS = cPtr->readIOSS(cPtr);
MSS = cPtr->readMSS(cPtr);
cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) |
IOSS_PIPE_B));
cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS &
MSS_MASK) | MSS_PIPE_B));
cPtr->writeXR(cPtr, 0xA4, x & 0xFF);
cPtr->writeXR(cPtr, 0xA5, (x >> 8) & 0x87);
cPtr->writeXR(cPtr, 0xA6, y & 0xFF);
cPtr->writeXR(cPtr, 0xA7, (y >> 8) & 0x87);
cPtr->writeIOSS(cPtr, IOSS);
cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), MSS);
}
} else {
CARD32 xy;
xy = y;
xy = (xy << 16) | x;
if(!cPtr->UseMMIO) {
HW_DEBUG(0xB);
outl(cPtr->PIOBase+DR(0xB), xy);
} else {
HW_DEBUG(MR(0xB));
MMIOmeml(MR(0xB)) = xy;
}
}
}
static void
CHIPSSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
{
CHIPSPtr cPtr = CHIPSPTR(pScrn);
vgaHWPtr hwp = VGAHWPTR(pScrn);
CARD32 packedcolfg, packedcolbg;
CURSOR_SYNC(pScrn);
if (IS_HiQV(cPtr)) {
unsigned char xr80;
xr80 = cPtr->readXR(cPtr, 0x80);
cPtr->writeXR(cPtr, 0x80, xr80 | 0x1);
hwp->writeDacWriteAddr(hwp, 0x04);
if (xr80 & 0x80) {
hwp->writeDacData(hwp, (bg >> 16) & 0xFF);
hwp->writeDacData(hwp, (bg >> 8) & 0xFF);
hwp->writeDacData(hwp, bg & 0xFF);
hwp->writeDacData(hwp, (fg >> 16) & 0xFF);
hwp->writeDacData(hwp, (fg >> 8) & 0xFF);
hwp->writeDacData(hwp, fg & 0xFF);
} else {
hwp->writeDacData(hwp, (bg >> 18) & 0xFF);
hwp->writeDacData(hwp, (bg >> 10) & 0xFF);
hwp->writeDacData(hwp, (bg >> 2) & 0xFF);
hwp->writeDacData(hwp, (fg >> 18) & 0xFF);
hwp->writeDacData(hwp, (fg >> 10) & 0xFF);
hwp->writeDacData(hwp, (fg >> 2) & 0xFF);
}
cPtr->writeXR(cPtr, 0x80, xr80);
if (cPtr->UseDualChannel &&
(! xf86IsEntityShared(pScrn->entityList[0]))) {
unsigned int IOSS, MSS;
IOSS = cPtr->readIOSS(cPtr);
MSS = cPtr->readMSS(cPtr);
cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) |
IOSS_PIPE_B));
cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) |
MSS_PIPE_B));
xr80 = cPtr->readXR(cPtr, 0x80);
cPtr->writeXR(cPtr, 0x80, xr80 | 0x1);
hwp->writeDacWriteAddr(hwp, 0x04);
if (xr80 & 0x80) {
hwp->writeDacData(hwp, (bg >> 16) & 0xFF);
hwp->writeDacData(hwp, (bg >> 8) & 0xFF);
hwp->writeDacData(hwp, bg & 0xFF);
hwp->writeDacData(hwp, (fg >> 16) & 0xFF);
hwp->writeDacData(hwp, (fg >> 8) & 0xFF);
hwp->writeDacData(hwp, fg & 0xFF);
} else {
hwp->writeDacData(hwp, (bg >> 18) & 0xFF);
hwp->writeDacData(hwp, (bg >> 10) & 0xFF);
hwp->writeDacData(hwp, (bg >> 2) & 0xFF);
hwp->writeDacData(hwp, (fg >> 18) & 0xFF);
hwp->writeDacData(hwp, (fg >> 10) & 0xFF);
hwp->writeDacData(hwp, (fg >> 2) & 0xFF);
}
cPtr->writeXR(cPtr, 0x80, xr80);
cPtr->writeIOSS(cPtr, IOSS);
cPtr->writeMSS(cPtr, hwp, MSS);
}
} else if (IS_Wingine(cPtr)) {
outl(cPtr->PIOBase+DR(0xA), (bg & 0xFFFFFF));
outl(cPtr->PIOBase+DR(0x9), (fg & 0xFFFFFF));
} else {
packedcolfg = ((fg & 0xF80000) >> 8) | ((fg & 0xFC00) >> 5)
| ((fg & 0xF8) >> 3);
packedcolbg = ((bg & 0xF80000) >> 8) | ((bg & 0xFC00) >> 5)
| ((bg & 0xF8) >> 3);
packedcolfg = (packedcolfg << 16) | packedcolbg;
if(!cPtr->UseMMIO) {
HW_DEBUG(0x9);
outl(cPtr->PIOBase+DR(0x9), packedcolfg);
} else {
MMIOmeml(MR(0x9)) = packedcolfg;
HW_DEBUG(MR(0x9));
}
}
}
static void
CHIPSLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
{
CHIPSPtr cPtr = CHIPSPTR(pScrn);
CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn);
#if X_BYTE_ORDER == X_BIG_ENDIAN
CARD32 *s = (pointer)src;
CARD32 *d = (pointer)(cPtr->FbBase + cAcl->CursorAddress);
int y;
#endif
CURSOR_SYNC(pScrn);
if (cPtr->cursorDelay) {
usleep(200000);
cPtr->cursorDelay = FALSE;
}
if (IS_Wingine(cPtr)) {
int i;
CARD32 *tmp = (CARD32 *)src;
outl(cPtr->PIOBase+DR(0x8),0x20);
for (i=0; i<64; i++) {
outl(cPtr->PIOBase+DR(0xC),*(CARD32 *)tmp);
tmp++;
}
} else {
if (cPtr->Flags & ChipsLinearSupport) {
#if X_BYTE_ORDER == X_BIG_ENDIAN
switch(cAcl->BytesPerPixel) {
case 4:
case 3:
for (y = 0; y < 64; y++) {
P_SWAP32(d,s);
d++; s++;
P_SWAP32(d,s);
d++; s++;
P_SWAP32(d,s);
d++; s++;
P_SWAP32(d,s);
d++; s++;
}
break;
case 2:
for (y = 0; y < 64; y++) {
P_SWAP16(d,s);
d++; s++;
P_SWAP16(d,s);
d++; s++;
P_SWAP16(d,s);
d++; s++;
P_SWAP16(d,s);
d++; s++;
P_SWAP16(d,s);
d++; s++;
}
break;
default:
for (y = 0; y < 64; y++) {
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
}
}
#else
memcpy((unsigned char *)cPtr->FbBase + cAcl->CursorAddress,
src, cPtr->CursorInfoRec->MaxWidth *
cPtr->CursorInfoRec->MaxHeight / 4);
#endif
} else {
if (IS_HiQV(cPtr))
if (pScrn->bitsPerPixel < 8)
CHIPSHiQVSetReadWritePlanar(pScrn->pScreen,
(int)(cAcl->CursorAddress >> 16));
else
CHIPSHiQVSetReadWrite(pScrn->pScreen,
(int)(cAcl->CursorAddress >> 16));
else
if (pScrn->bitsPerPixel < 8)
CHIPSSetWritePlanar(pScrn->pScreen,
(int)(cAcl->CursorAddress >> 16));
else
CHIPSSetWrite(pScrn->pScreen,
(int)(cAcl->CursorAddress >> 16));
memcpy((unsigned char *)cPtr->FbBase + (cAcl->CursorAddress &
0xFFFF), src, cPtr->CursorInfoRec->MaxWidth *
cPtr->CursorInfoRec->MaxHeight / 4);
}
}
if (IS_HiQV(cPtr)) {
cPtr->writeXR(cPtr, 0xA2, (cAcl->CursorAddress >> 8) & 0xFF);
cPtr->writeXR(cPtr, 0xA3, (cAcl->CursorAddress >> 16) & 0x3F);
if (cPtr->UseDualChannel &&
(! xf86IsEntityShared(pScrn->entityList[0]))) {
unsigned int IOSS, MSS;
IOSS = cPtr->readIOSS(cPtr);
MSS = cPtr->readMSS(cPtr);
cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) |
IOSS_PIPE_B));
cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS &
MSS_MASK) | MSS_PIPE_B));
cPtr->writeXR(cPtr, 0xA2, (cAcl->CursorAddress >> 8) & 0xFF);
cPtr->writeXR(cPtr, 0xA3, (cAcl->CursorAddress >> 16) & 0x3F);
cPtr->writeIOSS(cPtr, IOSS);
cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), MSS);
}
} else if (!IS_Wingine(cPtr)) {
if (!cPtr->UseMMIO) {
HW_DEBUG(0xC);
outl(cPtr->PIOBase+DR(0xC), cAcl->CursorAddress);
} else {
HW_DEBUG(MR(0xC));
MMIOmeml(MR(0xC)) = cAcl->CursorAddress;
}
}
}
static Bool
CHIPSUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
CHIPSPtr cPtr = CHIPSPTR(pScrn);
return (((cPtr->Flags & ChipsHWCursor) != 0)
&& !(pScrn->currentMode->Flags & V_DBLSCAN));
}
Bool
CHIPSCursorInit(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
CHIPSPtr cPtr = CHIPSPTR(pScrn);
xf86CursorInfoPtr infoPtr;
infoPtr = xf86CreateCursorInfoRec();
if(!infoPtr) return FALSE;
cPtr->CursorInfoRec = infoPtr;
infoPtr->Flags =
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
#endif
HARDWARE_CURSOR_INVERT_MASK |
HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
HARDWARE_CURSOR_TRUECOLOR_AT_8BPP;
if (IS_HiQV(cPtr)) {
infoPtr->Flags |= HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64;
infoPtr->MaxHeight = 64;
infoPtr->MaxWidth = 64;
} else if (IS_Wingine(cPtr)) {
infoPtr->Flags |= HARDWARE_CURSOR_SOURCE_MASK_NOT_INTERLEAVED;
infoPtr->MaxHeight = 32;
infoPtr->MaxWidth = 32;
} else {
infoPtr->Flags |= HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8;
infoPtr->MaxHeight = 32;
infoPtr->MaxWidth = 32;
}
infoPtr->SetCursorColors = CHIPSSetCursorColors;
infoPtr->SetCursorPosition = CHIPSSetCursorPosition;
infoPtr->LoadCursorImage = CHIPSLoadCursorImage;
infoPtr->HideCursor = CHIPSHideCursor;
infoPtr->ShowCursor = CHIPSShowCursor;
infoPtr->UseHWCursor = CHIPSUseHWCursor;
return(xf86InitCursor(pScreen, infoPtr));
}