diff options
Diffstat (limited to 'src/ct_cursor.c')
-rw-r--r-- | src/ct_cursor.c | 481 |
1 files changed, 481 insertions, 0 deletions
diff --git a/src/ct_cursor.c b/src/ct_cursor.c new file mode 100644 index 0000000..44a7e8a --- /dev/null +++ b/src/ct_cursor.c @@ -0,0 +1,481 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/chips/ct_cursor.c,v 1.27 2002/11/25 14:04:58 eich Exp $ */ + +/* + * Copyright 1994 The XFree86 Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * DAVID WEXELBLAT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Hardware Cursor for Trident utilizing XAA Cursor code. + * Written by Alan Hourihane <alanh@fairlite.demon.co.uk> + * Modified for Chips and Technologies by David Bateman <dbateman@eng.uts.edu.au> + */ + +/* All drivers should typically include these */ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" + +/* Everything using inb/outb, etc needs "compiler.h" */ +#include "compiler.h" + +/* Drivers for PCI hardware need this */ +#include "xf86PciInfo.h" + +/* Drivers that need to access the PCI config space directly need this */ +#include "xf86Pci.h" + +#include "xf86Cursor.h" + +/* Driver specific headers */ +#include "ct_driver.h" + +/* Sync function, maybe this should check infoRec->NeedToSync before syncing */ +#define CURSOR_SYNC(pScrn) \ + if (IS_HiQV(cPtr)) { \ + CHIPSHiQVSync(pScrn); \ + } else { \ + if(!cPtr->UseMMIO) { \ + CHIPSSync(pScrn); \ + } else { \ + CHIPSMMIOSync(pScrn); \ + } \ + } + +/* Swing your cursor bytes round and round... yeehaw! */ +#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); + + /* turn the cursor on */ + 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)); + /* Used to be: MMIOmemw(MR(8)) = 0x21; */ + MMIOmeml(MR(8)) = 0x21; + } + } + cPtr->HWCursorShown = TRUE; +} + +static void +CHIPSHideCursor(ScrnInfoPtr pScrn) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + unsigned char tmp; + + CURSOR_SYNC(pScrn); + + /* turn the cursor off */ + 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)); + /* Used to be: MMIOmemw(DR(0x8)) = 0x20; */ + MMIOmeml(DR(0x8)) = 0x20; + } + } + cPtr->HWCursorShown = FALSE; +} + +static void +CHIPSSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + + CURSOR_SYNC(pScrn); + + if (pScrn->currentMode->Flags & V_DBLSCAN) + y *= 2; + + if (x < 0) + x = ~(x-1) | 0x8000; + if (y < 0) + y = ~(y-1) | 0x8000; + + /* Program the cursor origin (offset into the cursor bitmap). */ + 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; + + /* Enable extended palette addressing */ + xr80 = cPtr->readXR(cPtr, 0x80); + cPtr->writeXR(cPtr, 0x80, xr80 | 0x1); + + /* Write the new colours to the extended VGA palette. Palette + * index is incremented after each write, so only write index + * once + */ + hwp->writeDacWriteAddr(hwp, 0x04); + if (xr80 & 0x80) { + /* 8bit DAC */ + 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 { + /* 6bit DAC */ + 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); + } + /* Enable normal palette addressing */ + 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)); + /* Enable extended palette addressing */ + xr80 = cPtr->readXR(cPtr, 0x80); + cPtr->writeXR(cPtr, 0x80, xr80 | 0x1); + + /* Write the new colours to the extended VGA palette. Palette + * index is incremented after each write, so only write index + * once + */ + hwp->writeDacWriteAddr(hwp, 0x04); + if (xr80 & 0x80) { + /* 8bit DAC */ + 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 { + /* 6bit DAC */ + 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); + } + /* Enable normal palette addressing */ + 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 + /* On big endian machines we must flip our cursor image around. */ + 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 { + /* + * The cursor can only be in the last 16K of video memory, + * which fits in the last banking window. + */ + 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); + } + } + + /* set cursor address here or we loose the cursor on video mode change */ + 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 pScr, CursorPtr pCurs) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScr->myNum]); + return ((cPtr->Flags & ChipsHWCursor) != 0); +} + +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)); +} + |