#include "tseng.h"
static void TsengShowCursor(ScrnInfoPtr pScrn);
static void TsengHideCursor(ScrnInfoPtr pScrn);
static void TsengSetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
static Bool TsengUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs);
static void TsengSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg);
static void TsengLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *bits);
Bool
TsengHWCursorInit(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
TsengPtr pTseng = TsengPTR(pScrn);
xf86CursorInfoPtr infoPtr;
PDEBUG(" TsengHWCursorInit\n");
if (!pTseng->HWCursor)
return FALSE;
infoPtr = xf86CreateCursorInfoRec();
if (!infoPtr)
return FALSE;
pTseng->CursorInfoRec = infoPtr;
pTseng->HWCursorBuffer =
pTseng->FbBase + pTseng->HWCursorBufferOffset;
if (!pTseng->UseLinMem) {
#ifdef TODO
pTseng->HWCursorBuffer =
pTseng->something
- pTseng->what
+ 0x18000;
#else
ErrorF("banked HW cursor not implemented yet!\n");
#endif
}
infoPtr->MaxWidth = 64;
infoPtr->MaxHeight = 64;
infoPtr->Flags =
HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
HARDWARE_CURSOR_INVERT_MASK;
infoPtr->SetCursorColors = TsengSetCursorColors;
infoPtr->SetCursorPosition = TsengSetCursorPosition;
infoPtr->LoadCursorImage = TsengLoadCursorImage;
infoPtr->HideCursor = TsengHideCursor;
infoPtr->ShowCursor = TsengShowCursor;
infoPtr->UseHWCursor = TsengUseHWCursor;
return (xf86InitCursor(pScreen, infoPtr));
}
static Bool
TsengUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
{
return TRUE;
}
static void
TsengShowCursor(ScrnInfoPtr pScrn)
{
unsigned char tmp;
TsengPtr pTseng = TsengPTR(pScrn);
if (Is_ET6K) {
tmp = inb(pTseng->IOAddress + 0x46);
outb(pTseng->IOAddress + 0x46, (tmp | 0x01));
} else {
outb(0x217A, 0xF7);
tmp = inb(0x217B);
outb(0x217B, tmp | 0x80);
}
}
static void
TsengHideCursor(ScrnInfoPtr pScrn)
{
unsigned char tmp;
TsengPtr pTseng = TsengPTR(pScrn);
if (Is_ET6K) {
tmp = inb(pTseng->IOAddress + 0x46);
outb(pTseng->IOAddress + 0x46, (tmp & 0xfe));;
} else {
outb(0x217A, 0xF7);
tmp = inb(0x217B);
outb(0x217B, tmp & ~0x80);
}
}
static void
TsengSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
{
int xorigin, yorigin;
TsengPtr pTseng = TsengPTR(pScrn);
xorigin = 0;
yorigin = 0;
if (x < 0) {
xorigin = -x;
x = 0;
}
if (y < 0) {
yorigin = -y;
y = 0;
}
#ifdef TODO
if (XF86SCRNINFO(pScr)->modes->Flags & V_DBLSCAN)
y *= 2;
#endif
if (Is_ET6K) {
outb(pTseng->IOAddress + 0x82, xorigin);
outb(pTseng->IOAddress + 0x83, yorigin);
outb(pTseng->IOAddress + 0x84, (x & 0xff));
outb(pTseng->IOAddress + 0x85, ((x >> 8) & 0x0f));
outb(pTseng->IOAddress + 0x86, (y & 0xff));
outb(pTseng->IOAddress + 0x87, ((y >> 8) & 0x0f));
} else {
outb(0x217A, 0xE2);
outb(0x217B, xorigin);
outb(0x217A, 0xE6);
outb(0x217B, yorigin);
outb(0x217A, 0xE0);
outb(0x217B, (x & 0xff));
outb(0x217A, 0xE1);
outb(0x217B, ((x >> 8) & 0x0f));
outb(0x217A, 0xE4);
outb(0x217B, (y & 0xff));
outb(0x217A, 0xE5);
outb(0x217B, ((y >> 8) & 0x0f));
}
}
static void
TsengSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
{
TsengPtr pTseng = TsengPTR(pScrn);
unsigned char et6k_fg, et6k_bg;
if (Is_ET6K) {
et6k_fg = (fg & 0x00000003)
| ((fg & 0x00000300) >> 6)
| ((fg & 0x00030000) >> 12);
et6k_bg = (bg & 0x00000003)
| ((bg & 0x00000300) >> 6)
| ((bg & 0x00030000) >> 12);
outb(pTseng->IOAddress + 0x67, 0x09);
outb(pTseng->IOAddress + 0x69, et6k_bg);
outb(pTseng->IOAddress + 0x69, et6k_fg);
} else {
xf86Msg(X_ERROR, "Internal error: ET4000 hardware cursor color changes not implemented\n");
}
}
void
TsengLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *bits)
{
TsengPtr pTseng = TsengPTR(pScrn);
int iobase = VGAHW_GET_IOBASE();
unsigned char tmp;
#ifdef DEBUG_HWC
int i;
int d;
for (i = 0; i < 1024; i++) {
d = *(bits + i);
ErrorF("%d%d%d%d", d & 0x03, (d >> 2) & 0x03, (d >> 4) & 0x03, (d >> 6) & 0x03);
if ((i & 15) == 15)
ErrorF("\n");
}
#endif
if (Is_ET6K) {
outb(iobase + 0x04, 0x0E);
tmp = inb(iobase + 0x05) & 0xF0;
outb(iobase + 0x05, tmp | (((pTseng->HWCursorBufferOffset / 4) >> 16) & 0x0F));
outb(iobase + 0x04, 0x0F);
outb(iobase + 0x05, ((pTseng->HWCursorBufferOffset / 4) >> 8) & 0xFF);
} else {
outb(0x217A, 0xEA);
tmp = inb(0x217B) & 0xF0;
outb(0x217B, tmp | (((pTseng->HWCursorBufferOffset / 4) >> 16) & 0x0F));
outb(0x217A, 0xE9);
outb(0x217B, ((pTseng->HWCursorBufferOffset / 4) >> 8) & 0xFF);
outb(0x217A, 0xE8);
outb(0x217B, (pTseng->HWCursorBufferOffset / 4) & 0xFF);
outb(0x217A, 0xEB);
outb(0x217B, 2);
outb(0x217A, 0xEC);
tmp = inb(0x217B);
outb(0x217B, tmp & 0xFE);
outb(0x217A, 0xEF);
tmp = inb(0x217B);
outb(0x217B, (tmp & 0xF8) | 0x02);
outb(0x217A, 0xEE);
outb(0x217B, 1);
}
memcpy(pTseng->HWCursorBuffer, bits, 1024);
}