windows-nt/Source/XPSP1/NT/drivers/video/matrox/mga/disp/pointer.c
2020-09-26 16:20:57 +08:00

1485 lines
48 KiB
C

/******************************Module*Header*******************************\
* Module Name: pointer.c
*
* This module contains the hardware pointer support for the display
* driver.
*
* Copyright (c) 1993-1996 Microsoft Corporation
* Copyright (c) 1993-1996 Matrox Electronic Systems, Ltd.
\**************************************************************************/
#include "precomp.h"
#define BT485_CURSOR_SIZE 64
#define BT482_CURSOR_SIZE 32
#define VIEWPOINT_CURSOR_SIZE 64
#define VIEWPOINT_OUT (VIEWPOINT_CURSOR_SIZE/2-1-VIEWPOINT_CURSOR_SIZE)
#define TVP3026_CURSOR_SIZE 64
#define TVP3026_OUT (TVP3026_CURSOR_SIZE-TVP3026_CURSOR_SIZE)
#define OLD_TVP_SHIFT 2
#define NEW_TVP_SHIFT 0
BYTE Plane0LUT[] = { 0x00, 0x01, 0x04, 0x05,
0x10, 0x11, 0x14, 0x15,
0x40, 0x41, 0x44, 0x45,
0x50, 0x51, 0x54, 0x55 };
BYTE Plane1LUT[] = { 0x00, 0x02, 0x08, 0x0a,
0x20, 0x22, 0x28, 0x2a,
0x80, 0x82, 0x88, 0x8a,
0xa0, 0xa2, 0xa8, 0xaa };
/****************************************************************************\
* SetBt48xPointerShape
\****************************************************************************/
ULONG SetBt48xPointerShape(
SURFOBJ* pso,
SURFOBJ* psoMsk,
SURFOBJ* psoColor,
XLATEOBJ* pxlo,
LONG xHot,
LONG yHot,
LONG x,
LONG y,
RECTL* prcl,
FLONG fl)
{
ULONG i;
ULONG j;
ULONG cxMask;
ULONG cyMask;
ULONG cMaskDimension;
LONG lDelta;
PDEV* ppdev;
BYTE* pjBase;
UCHAR ucTemp;
UCHAR ucByteWidth;
UCHAR ucOldCR;
UCHAR ucOldCmdRegA;
BYTE* pjAND;
BYTE* pjXOR;
LONG cjWidth;
LONG cjSkip;
LONG cjWidthRemainder;
LONG cyHeightRemainder;
LONG cjHeightRemainder;
ppdev = (PDEV*) pso->dhpdev;
pjBase = ppdev->pjBase;
// Figure out the dimensions of the masks:
cMaskDimension = (ppdev->RamDacFlags == RAMDAC_BT482) ? 32 : 64;
// Get the bitmap dimensions.
cxMask = psoMsk->sizlBitmap.cx;
cyMask = psoMsk->sizlBitmap.cy >> 1; // Height includes AND and XOR masks
// Set up pointers to the AND and XOR masks.
lDelta = psoMsk->lDelta;
pjAND = psoMsk->pvScan0;
pjXOR = pjAND + (cyMask * lDelta);
// Do some other download setup:
cjWidth = cxMask >> 3;
cjSkip = lDelta - cjWidth;
cjWidthRemainder = (cMaskDimension / 8) - cjWidth;
// Don't bother blanking the bottom part of the cursor if it is
// already blank:
cyHeightRemainder = min(ppdev->cyPointerHeight, (LONG) cMaskDimension)
- cyMask;
cyHeightRemainder = max(cyHeightRemainder, 0);
cjHeightRemainder = cyHeightRemainder * (cMaskDimension / 8);
ppdev->cyPointerHeight = cyMask;
DrvMovePointer(pso, -1, -1, NULL); // Disable the H/W cursor
if ((ppdev->RamDacFlags == RAMDAC_BT485) ||
(ppdev->RamDacFlags == RAMDAC_PX2085))
{
// Set the cursor for 64 X 64, and set the 2 MSB's for the cursor
// RAM addr to 0.
// First get access to Command Register 3
// Prepare to download AND mask to Bt485
// Clear bit 7 of CR0 so we can access CR3
ucTemp = CP_READ_REGISTER_BYTE(pjBase + BT485_COMMAND_REG0);
ucTemp |= 0x80;
CP_WRITE_REGISTER_BYTE(pjBase + BT485_COMMAND_REG0, ucTemp);
// Turn on bit 0 to address register
CP_WRITE_REGISTER_BYTE(pjBase + BT485_CURSOR_RAM_WRITE, 1);
ucTemp = CP_READ_REGISTER_BYTE(pjBase + BT485_COMMAND_REG3);
ucTemp &= 0xF8; // CR3 bit2=1 (64x64 cursor)
ucTemp |= 0x06; // CR3 bit1-bit0=10 (AND mask)
CP_WRITE_REGISTER_BYTE(pjBase + BT485_COMMAND_REG3, ucTemp);
// Start at address 0x200 (AND mask)
CP_WRITE_REGISTER_BYTE(pjBase + BT485_CURSOR_RAM_WRITE, 0);
// Down load the AND mask:
for (j = cyMask; j != 0; j--)
{
for (i = cjWidth; i != 0; i--)
{
CP_WRITE_REGISTER_BYTE(pjBase + BT485_CURSOR_RAM_DATA, *pjAND++);
}
pjAND += cjSkip;
for (i = cjWidthRemainder; i != 0; i--)
{
pjBase = ppdev->pjBase; // Compiler work-around
CP_WRITE_REGISTER_BYTE(pjBase + BT485_CURSOR_RAM_DATA, 0xff);
}
}
for (j = cjHeightRemainder; j != 0; j--)
{
pjBase = ppdev->pjBase; // Compiler work-around
CP_WRITE_REGISTER_BYTE(pjBase + BT485_CURSOR_RAM_DATA, 0xff);
}
// Prepare to download XOR mask to Bt485
// Clear bit 7 of CR0 so we can access CR3
ucTemp = CP_READ_REGISTER_BYTE(pjBase + BT485_COMMAND_REG0);
ucTemp |= 0x80;
CP_WRITE_REGISTER_BYTE(pjBase + BT485_COMMAND_REG0, ucTemp);
// Turn on bit 0 to address register
CP_WRITE_REGISTER_BYTE(pjBase + BT485_CURSOR_RAM_WRITE, 1);
ucTemp = CP_READ_REGISTER_BYTE(pjBase + BT485_COMMAND_REG3);
ucTemp &= 0xF8; // CR3 bit2=1 (64x64 cursor)
ucTemp |= 0x04; // CR3 bit1-bit0=00 (XOR mask)
CP_WRITE_REGISTER_BYTE(pjBase + BT485_COMMAND_REG3, ucTemp);
// Start at address 0x200 (AND mask)
CP_WRITE_REGISTER_BYTE(pjBase + BT485_CURSOR_RAM_WRITE, 0);
// Down load the XOR mask
for (j = cyMask; j != 0; j--)
{
for (i = cjWidth; i != 0; i--)
{
CP_WRITE_REGISTER_BYTE(pjBase + BT485_CURSOR_RAM_DATA, *pjXOR++);
}
pjXOR += cjSkip;
for (i = cjWidthRemainder; i != 0; i--)
{
pjBase = ppdev->pjBase; // Compiler work-around
CP_WRITE_REGISTER_BYTE(pjBase + BT485_CURSOR_RAM_DATA, 0);
}
}
for (j = cjHeightRemainder; j != 0; j--)
{
pjBase = ppdev->pjBase; // Compiler work-around
CP_WRITE_REGISTER_BYTE(pjBase + BT485_CURSOR_RAM_DATA, 0);
}
}
else // Download to Bt482
{
// Prepare to download AND mask to Bt482
// Store current REGA value, select extended registers
ucOldCmdRegA = CP_READ_REGISTER_BYTE(pjBase + BT482_COMMAND_REGA);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_COMMAND_REGA,
ucOldCmdRegA | BT482_EXTENDED_REG_SELECT);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PALETTE_RAM_WRITE, CURS_REG);
ucOldCR = CP_READ_REGISTER_BYTE(pjBase + BT482_PEL_MASK);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PEL_MASK, ucOldCR | BT482_CURSOR_RAM_SELECT);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PALETTE_RAM_WRITE, 0x80);
for (j = cyMask; j != 0; j--)
{
for (i = cjWidth; i != 0; i--)
{
CP_WRITE_REGISTER_BYTE(pjBase + BT482_OVRLAY_REGS, *pjAND++);
CP_READ_REGISTER_BYTE(pjBase + HST_REV); // Need 600us delay
CP_READ_REGISTER_BYTE(pjBase + HST_REV);
}
pjAND += cjSkip;
for (i = cjWidthRemainder; i != 0; i--)
{
pjBase = ppdev->pjBase; // Compiler work-around
CP_WRITE_REGISTER_BYTE(pjBase + BT482_OVRLAY_REGS, 0xff);
CP_READ_REGISTER_BYTE(pjBase + HST_REV); // Need 600us delay
CP_READ_REGISTER_BYTE(pjBase + HST_REV);
}
}
for (j = cjHeightRemainder; j != 0; j--)
{
pjBase = ppdev->pjBase; // Compiler work-around
CP_WRITE_REGISTER_BYTE(pjBase + BT482_OVRLAY_REGS, 0xff);
CP_READ_REGISTER_BYTE(pjBase + HST_REV); // Need 600us delay
CP_READ_REGISTER_BYTE(pjBase + HST_REV);
}
// Prepare to download XOR mask to Bt482
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PALETTE_RAM_WRITE, 0x00);
for (j = cyMask; j != 0; j--)
{
for (i = cjWidth; i != 0; i--)
{
CP_WRITE_REGISTER_BYTE(pjBase + BT482_OVRLAY_REGS, *pjXOR++);
CP_READ_REGISTER_BYTE(pjBase + HST_REV); // Need 600us delay
CP_READ_REGISTER_BYTE(pjBase + HST_REV);
}
pjXOR += cjSkip;
for (i = cjWidthRemainder; i != 0; i--)
{
pjBase = ppdev->pjBase; // Compiler work-around
CP_WRITE_REGISTER_BYTE(pjBase + BT482_OVRLAY_REGS, 0);
CP_READ_REGISTER_BYTE(pjBase + HST_REV); // Need 600us delay
CP_READ_REGISTER_BYTE(pjBase + HST_REV);
}
}
for (j = cjHeightRemainder; j != 0; j--)
{
pjBase = ppdev->pjBase; // Compiler work-around
CP_WRITE_REGISTER_BYTE(pjBase + BT482_OVRLAY_REGS, 0);
CP_READ_REGISTER_BYTE(pjBase + HST_REV); // Need 600us delay
CP_READ_REGISTER_BYTE(pjBase + HST_REV);
}
// Restore old Cursor Regsister and Command Register A values
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PALETTE_RAM_WRITE, CURS_REG);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PEL_MASK, ucOldCR);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_COMMAND_REGA, ucOldCmdRegA);
}
// Set the position of the cursor (and enable it)
DrvMovePointer(pso, x, y, NULL);
return(SPS_ACCEPT_NOEXCLUDE);
}
/****************************************************************************\
* SetViewPointPointerShape -
\****************************************************************************/
ULONG SetViewPointPointerShape(
SURFOBJ* pso,
SURFOBJ* psoMsk,
SURFOBJ* psoColor,
XLATEOBJ* pxlo,
LONG xHot,
LONG yHot,
LONG x,
LONG y,
RECTL* prcl,
FLONG fl)
{
ULONG i;
ULONG j;
ULONG cxAND;
ULONG cyAND;
ULONG cxRemaining;
ULONG cyRemaining;
BYTE* pjAND;
BYTE* pjXOR;
LONG lDelta;
PDEV* ppdev;
BYTE* pjBase;
BYTE ViewPointTranspMask;
ppdev = (PDEV*) pso->dhpdev;
pjBase = ppdev->pjBase;
// The ViewPoint requires that the AND mask (plane 1) and the XOR mask
// (plane 0) be interleaved on a bit-by-bit basis:
//
// Plane1/AND: F E D C B A 9 8
// Plane0/XOR: 7 6 5 4 3 2 1 0
//
// will be downloaded as: "B 3 A 2 9 1 8 0" and "F 7 E 6 D 5 C 4".
// The fastest way to do that is probably to use a lookup table:
//
// Plane1: "B A 9 8" --> "B - A - 9 - 8 -"
// Plane0: "3 2 1 0" --> "- 3 - 2 - 1 - 0"
// OR --> "B 3 A 2 9 1 8 0"
// Get the bitmap dimensions.
// This assumes that the cursor width is an integer number of bytes!
cxAND = psoMsk->sizlBitmap.cx / 8;
cxRemaining = 2 * ((VIEWPOINT_CURSOR_SIZE/8) - cxAND);
cyAND = psoMsk->sizlBitmap.cy / 2;
cyRemaining = VIEWPOINT_CURSOR_SIZE - cyAND;
// Set up pointers to the AND and XOR masks.
pjAND = psoMsk->pvScan0;
lDelta = psoMsk->lDelta;
pjXOR = pjAND + (cyAND * lDelta);
if (ppdev->bHwPointerActive)
{
// The hardware cursor is currently enabled.
// Disable it.
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_INDEX, VPOINT_CUR_CTL);
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_DATA, VIEWPOINT_CURSOR_OFF);
// Signal that the cursor is disabled.
ppdev->bHwPointerActive = FALSE;
}
// The effect of this is to make the pointer pixels transparent.
ViewPointTranspMask = 0xaa;
// Setup for downloading the pointer masks.
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_INDEX, VPOINT_CUR_RAM_LSB);
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_DATA, 0);
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_INDEX, VPOINT_CUR_RAM_MSB);
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_DATA, 0);
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_INDEX, VPOINT_CUR_RAM_DATA);
// Build and copy the interleaved mask.
for (i = 0; i < cyAND; i++)
{
// Copy over a line of the interleaved mask.
for (j = 0; j < cxAND; j++)
{
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_DATA,
(Plane1LUT[pjAND[j] >> 4] | Plane0LUT[pjXOR[j] >> 4]));
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_DATA,
(Plane1LUT[pjAND[j] & 0x0f] | Plane0LUT[pjXOR[j] & 0x0f]));
}
// Copy over transparent bytes for the remaining of the line.
for (j = (VIEWPOINT_CURSOR_SIZE/8) - (psoMsk->sizlBitmap.cx >> 3);
j != 0;
j--)
{
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_DATA, ViewPointTranspMask);
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_DATA, ViewPointTranspMask);
}
// Point to the next line of the source masks.
pjAND += lDelta;
pjXOR += lDelta;
}
// Copy over transparent bytes for the remaining of the mask.
for (i = 0; i < cyRemaining; i++)
{
for (j = (VIEWPOINT_CURSOR_SIZE/8);
j != 0;
j--)
{
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_DATA, ViewPointTranspMask);
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_DATA, ViewPointTranspMask);
}
}
// Set the position of the cursor (and enable it).
DrvMovePointer(pso, x, y, NULL);
return(SPS_ACCEPT_NOEXCLUDE);
}
/****************************************************************************\
* MilSetTVP3026PointerShape -
\****************************************************************************/
ULONG MilSetTVP3026PointerShape(
SURFOBJ* pso,
SURFOBJ* psoMsk,
SURFOBJ* psoColor,
XLATEOBJ* pxlo,
LONG xHot,
LONG yHot,
LONG x,
LONG y,
RECTL* prcl,
FLONG fl)
{
ULONG i;
ULONG j;
ULONG cxMask;
ULONG cyMask;
ULONG cMaskDimension;
LONG lDelta;
PDEV* ppdev;
BYTE* pjBase;
UCHAR ucTemp;
UCHAR ucByteWidth;
UCHAR ucOldCR;
UCHAR ucOldCmdRegA;
BYTE* pjAND;
BYTE* pjXOR;
LONG cjWidth;
LONG cjSkip;
LONG cjWidthRemainder;
LONG cyHeightRemainder;
LONG cyNextBank;
BYTE jData;
ULONG UlTvpIndirectIndex;
ULONG UlTvpIndexedData;
ULONG UlTvpCurAddrWr;
ULONG UlTvpCurData;
// The old MGA chips had direct register offsets that were multiples of
// four, while the new Millenium uses increments of one. So, we define the
// offsets as increments of one and shift for the older boards.
// No scaling (shifting) of offsets
// Note that the compiler is kind enough to recognize that these are
// constant declarations:
UlTvpIndirectIndex = TVP3026_INDIRECT_INDEX(NEW_TVP_SHIFT);
UlTvpIndexedData = TVP3026_INDEXED_DATA(NEW_TVP_SHIFT);
UlTvpCurAddrWr = TVP3026_CUR_ADDR_WR(NEW_TVP_SHIFT);
UlTvpCurData = TVP3026_CUR_DATA(NEW_TVP_SHIFT);
ppdev = (PDEV*) pso->dhpdev;
pjBase = ppdev->pjBase;
// Get the bitmap dimensions.
cxMask = psoMsk->sizlBitmap.cx;
cyMask = psoMsk->sizlBitmap.cy >> 1; // Height includes AND and XOR masks
// Set up pointers to the AND and XOR masks.
lDelta = psoMsk->lDelta;
pjAND = psoMsk->pvScan0;
pjXOR = pjAND + (cyMask * lDelta);
// Do some other download setup:
cjWidth = cxMask >> 3;
cjSkip = lDelta - cjWidth;
cjWidthRemainder = (64 / 8) - cjWidth;
// Don't bother blanking the bottom part of the cursor if it is
// already blank:
cyHeightRemainder = min(ppdev->cyPointerHeight, (LONG) 64)
- cyMask;
cyHeightRemainder = max(cyHeightRemainder, 0);
ppdev->cyPointerHeight = cyMask;
// Disable the cursor, access bytes 200-2FF of cursor RAM.
ppdev->bHwPointerActive = FALSE;
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndirectIndex, TVP3026_I_CUR_CTL);
jData = CP_READ_REGISTER_BYTE(pjBase + UlTvpIndexedData)
& ~(TVP3026_D_CURSOR_RAM_MASK | TVP3026_D_CURSOR_MASK);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndexedData,
jData | TVP3026_D_CURSOR_RAM_10);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurAddrWr, 0);
// Down load the AND mask:
cyNextBank = 32;
for (j = cyMask; j != 0; j--)
{
for (i = cjWidth; i != 0; i--)
{
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurData, *pjAND++);
}
pjAND += cjSkip;
for (i = cjWidthRemainder; i != 0; i--)
{
pjBase = ppdev->pjBase; // Compiler work-around
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurData, 0xff);
}
if (--cyNextBank == 0)
{
// Access bytes 300-3FF of cursor RAM.
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndirectIndex,
TVP3026_I_CUR_CTL);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndexedData,
jData | TVP3026_D_CURSOR_RAM_11);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurAddrWr, 0);
}
}
for (j = cyHeightRemainder; j != 0; j--)
{
for (i = 8; i != 0; i--)
{
pjBase = ppdev->pjBase; // Compiler work-around
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurData, 0xff);
}
if (--cyNextBank == 0)
{
// Access bytes 300-3FF of cursor RAM.
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndirectIndex,
TVP3026_I_CUR_CTL);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndexedData,
jData | TVP3026_D_CURSOR_RAM_11);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurAddrWr, 0);
}
}
// Access bytes 00-FF of cursor RAM.
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndirectIndex,
TVP3026_I_CUR_CTL);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndexedData,
jData | TVP3026_D_CURSOR_RAM_00);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurAddrWr, 0);
// Down load the XOR mask
cyNextBank = 32;
for (j = cyMask; j != 0; j--)
{
for (i = cjWidth; i != 0; i--)
{
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurData, *pjXOR++);
}
pjXOR += cjSkip;
for (i = cjWidthRemainder; i != 0; i--)
{
pjBase = ppdev->pjBase; // Compiler work-around
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurData, 0);
}
if (--cyNextBank == 0)
{
// Access bytes 100-1FF of cursor RAM.
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndirectIndex,
TVP3026_I_CUR_CTL);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndexedData,
jData | TVP3026_D_CURSOR_RAM_01);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurAddrWr, 0);
}
}
for (j = cyHeightRemainder; j != 0; j--)
{
for (i = 8; i != 0; i--)
{
pjBase = ppdev->pjBase; // Compiler work-around
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurData, 0);
}
if (--cyNextBank == 0)
{
// Access bytes 100-1FF of cursor RAM.
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndirectIndex,
TVP3026_I_CUR_CTL);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndexedData,
jData | TVP3026_D_CURSOR_RAM_01);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurAddrWr, 0);
}
}
// Set the position of the cursor (and enable it)
DrvMovePointer(pso, x, y, NULL);
return(SPS_ACCEPT_NOEXCLUDE);
}
/****************************************************************************\
* MgaSetTVP3026PointerShape -
\****************************************************************************/
ULONG MgaSetTVP3026PointerShape(
SURFOBJ* pso,
SURFOBJ* psoMsk,
SURFOBJ* psoColor,
XLATEOBJ* pxlo,
LONG xHot,
LONG yHot,
LONG x,
LONG y,
RECTL* prcl,
FLONG fl)
{
ULONG i;
ULONG j;
ULONG cxMask;
ULONG cyMask;
ULONG cMaskDimension;
LONG lDelta;
PDEV* ppdev;
BYTE* pjBase;
UCHAR ucTemp;
UCHAR ucByteWidth;
UCHAR ucOldCR;
UCHAR ucOldCmdRegA;
BYTE* pjAND;
BYTE* pjXOR;
LONG cjWidth;
LONG cjSkip;
LONG cjWidthRemainder;
LONG cyHeightRemainder;
LONG cyNextBank;
BYTE jData;
ULONG UlTvpIndirectIndex;
ULONG UlTvpIndexedData;
ULONG UlTvpCurAddrWr;
ULONG UlTvpCurData;
// The old MGA chips had direct register offsets that were multiples of
// four, while the new Millenium uses increments of one. So, we define the
// offsets as increments of one and shift for the older boards.
// No scaling (shifting) of offsets
// Note that the compiler is kind enough to recognize that these are
// constant declarations:
UlTvpIndirectIndex = TVP3026_INDIRECT_INDEX(OLD_TVP_SHIFT);
UlTvpIndexedData = TVP3026_INDEXED_DATA(OLD_TVP_SHIFT);
UlTvpCurAddrWr = TVP3026_CUR_ADDR_WR(OLD_TVP_SHIFT);
UlTvpCurData = TVP3026_CUR_DATA(OLD_TVP_SHIFT);
ppdev = (PDEV*) pso->dhpdev;
pjBase = ppdev->pjBase;
// Get the bitmap dimensions.
cxMask = psoMsk->sizlBitmap.cx;
cyMask = psoMsk->sizlBitmap.cy >> 1; // Height includes AND and XOR masks
// Set up pointers to the AND and XOR masks.
lDelta = psoMsk->lDelta;
pjAND = psoMsk->pvScan0;
pjXOR = pjAND + (cyMask * lDelta);
// Do some other download setup:
cjWidth = cxMask >> 3;
cjSkip = lDelta - cjWidth;
cjWidthRemainder = (64 / 8) - cjWidth;
// Don't bother blanking the bottom part of the cursor if it is
// already blank:
cyHeightRemainder = min(ppdev->cyPointerHeight, (LONG) 64)
- cyMask;
cyHeightRemainder = max(cyHeightRemainder, 0);
ppdev->cyPointerHeight = cyMask;
// Disable the cursor, access bytes 200-2FF of cursor RAM.
ppdev->bHwPointerActive = FALSE;
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndirectIndex, TVP3026_I_CUR_CTL);
jData = CP_READ_REGISTER_BYTE(pjBase + UlTvpIndexedData)
& ~(TVP3026_D_CURSOR_RAM_MASK | TVP3026_D_CURSOR_MASK);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndexedData,
jData | TVP3026_D_CURSOR_RAM_10);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurAddrWr, 0);
// Down load the AND mask:
cyNextBank = 32;
for (j = cyMask; j != 0; j--)
{
for (i = cjWidth; i != 0; i--)
{
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurData, *pjAND++);
}
pjAND += cjSkip;
for (i = cjWidthRemainder; i != 0; i--)
{
pjBase = ppdev->pjBase; // Compiler work-around
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurData, 0xff);
}
if (--cyNextBank == 0)
{
// Access bytes 300-3FF of cursor RAM.
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndirectIndex,
TVP3026_I_CUR_CTL);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndexedData,
jData | TVP3026_D_CURSOR_RAM_11);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurAddrWr, 0);
}
}
for (j = cyHeightRemainder; j != 0; j--)
{
for (i = 8; i != 0; i--)
{
pjBase = ppdev->pjBase; // Compiler work-around
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurData, 0xff);
}
if (--cyNextBank == 0)
{
// Access bytes 300-3FF of cursor RAM.
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndirectIndex,
TVP3026_I_CUR_CTL);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndexedData,
jData | TVP3026_D_CURSOR_RAM_11);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurAddrWr, 0);
}
}
// Access bytes 00-FF of cursor RAM.
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndirectIndex,
TVP3026_I_CUR_CTL);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndexedData,
jData | TVP3026_D_CURSOR_RAM_00);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurAddrWr, 0);
// Down load the XOR mask
cyNextBank = 32;
for (j = cyMask; j != 0; j--)
{
for (i = cjWidth; i != 0; i--)
{
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurData, *pjXOR++);
}
pjXOR += cjSkip;
for (i = cjWidthRemainder; i != 0; i--)
{
pjBase = ppdev->pjBase; // Compiler work-around
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurData, 0);
}
if (--cyNextBank == 0)
{
// Access bytes 100-1FF of cursor RAM.
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndirectIndex,
TVP3026_I_CUR_CTL);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndexedData,
jData | TVP3026_D_CURSOR_RAM_01);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurAddrWr, 0);
}
}
for (j = cyHeightRemainder; j != 0; j--)
{
for (i = 8; i != 0; i--)
{
pjBase = ppdev->pjBase; // Compiler work-around
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurData, 0);
}
if (--cyNextBank == 0)
{
// Access bytes 100-1FF of cursor RAM.
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndirectIndex,
TVP3026_I_CUR_CTL);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpIndexedData,
jData | TVP3026_D_CURSOR_RAM_01);
CP_WRITE_REGISTER_BYTE(pjBase + UlTvpCurAddrWr, 0);
}
}
// Set the position of the cursor (and enable it)
DrvMovePointer(pso, x, y, NULL);
return(SPS_ACCEPT_NOEXCLUDE);
}
/****************************************************************************\
* DrvSetPointerShape
\****************************************************************************/
ULONG DrvSetPointerShape(
SURFOBJ* pso,
SURFOBJ* psoMsk,
SURFOBJ* psoColor,
XLATEOBJ* pxlo,
LONG xHot,
LONG yHot,
LONG x,
LONG y,
RECTL* prcl,
FLONG fl)
{
PDEV* ppdev;
LONG cx;
LONG cy;
LONG cMax;
ULONG ulRet;
ppdev = (PDEV*) pso->dhpdev;
// Because our DAC pointers usually flash when we set them, we'll
// always decline animated pointers:
if (fl & (SPS_ANIMATESTART | SPS_ANIMATEUPDATE))
{
goto HideAndDecline;
}
//
// Bug: 412974. we have HW cursor corruption. Disable it by declining.
//
goto HideAndDecline;
// We're not going to handle any colour pointers, pointers that
// are larger than our hardware allows, or flags that we don't
// understand.
//
// (Note that the spec says we should decline any flags we don't
// understand, but we'll actually be declining if we don't see
// the only flag we *do* understand...)
//
// Our old documentation says that 'psoMsk' may be NULL, which means
// that the pointer is transparent. Well, trust me, that's wrong.
// I've checked GDI's code, and it will never pass us a NULL psoMsk:
cx = psoMsk->sizlBitmap.cx; // Note that 'sizlBitmap.cy' accounts
cy = psoMsk->sizlBitmap.cy >> 1; // for the double height due to the
// inclusion of both the AND masks
// and the XOR masks. For now, we're
// only interested in the true
// pointer dimensions, so we divide
// by 2.
cMax = (ppdev->RamDacFlags == RAMDAC_BT482) ? BT482_CURSOR_SIZE : 64;
if ((psoColor != NULL) ||
(cx > cMax) || // Hardware pointer is cMax by cMax
(cy > cMax) || // pixels
(cx & 7) || // To simplify download routines, handle
// only byte-aligned widths
!(fl & SPS_CHANGE)) // Must have this flag set
{
goto HideAndDecline;
}
// Save the hot spot in the pdev.
ppdev->ptlHotSpot.x = xHot;
ppdev->ptlHotSpot.y = yHot;
// Program the monochrome hardware pointer.
switch (ppdev->RamDacFlags)
{
case RAMDAC_BT485:
case RAMDAC_BT482:
case RAMDAC_PX2085:
ulRet = SetBt48xPointerShape(pso, psoMsk, psoColor,
pxlo, xHot, yHot, x, y, prcl, fl);
break;
case RAMDAC_VIEWPOINT:
ulRet = SetViewPointPointerShape(pso, psoMsk, psoColor,
pxlo, xHot, yHot, x, y, prcl, fl);
break;
case RAMDAC_TVP3026:
case RAMDAC_TVP3030:
if (ppdev->ulBoardId == MGA_STORM)
{
ulRet = MilSetTVP3026PointerShape(pso, psoMsk, psoColor,
pxlo, xHot, yHot, x, y, prcl, fl);
}
else
{
ulRet = MgaSetTVP3026PointerShape(pso, psoMsk, psoColor,
pxlo, xHot, yHot, x, y, prcl, fl);
}
break;
default:
ulRet = SPS_DECLINE;
break;
}
return(ulRet);
HideAndDecline:
// Since we're declining the new pointer, GDI will simulate it via
// DrvCopyBits calls. So we should really hide the old hardware
// pointer if it's visible. We can get DrvMovePointer to do this
// for us:
DrvMovePointer(pso, -1, -1, NULL);
return(SPS_DECLINE);
}
/****************************************************************************\
* DrvMovePointer
*
\****************************************************************************/
VOID DrvMovePointer(
SURFOBJ* pso,
LONG x,
LONG y,
RECTL* prcl)
{
PDEV* ppdev;
OH* poh;
BYTE* pjBase;
UCHAR ucTemp;
UCHAR ucOldCmdRegA;
ULONG ulDacScale;
ppdev = (PDEV*) pso->dhpdev;
poh = ((DSURF*) pso->dhsurf)->poh;
pjBase = ppdev->pjBase;
// Convert the pointer's position from relative to absolute
// coordinates (this is only significant for multiple board
// support).
x += poh->x;
y += poh->y;
// If x is -1 after the offset then take down the cursor.
if (x == -1)
{
if (!(ppdev->bHwPointerActive))
{
// The hardware cursor is disabled already.
return;
}
// Disable the cursor.
// We will set the cursor position outside the display to prevent
// flickering when switching from software to hardware cursor.
switch (ppdev->RamDacFlags)
{
case RAMDAC_BT485:
// Disable the cursor, then fall through.
ucTemp = CP_READ_REGISTER_BYTE(pjBase + BT485_COMMAND_REG2);
CP_WRITE_REGISTER_BYTE(pjBase + BT485_COMMAND_REG2, ucTemp & 0xfc);
case RAMDAC_PX2085:
// Set the cursor position outside the display.
CP_WRITE_REGISTER_BYTE(pjBase + BT485_CURSOR_X_LOW, 0);
CP_WRITE_REGISTER_BYTE(pjBase + BT485_CURSOR_X_HIGH, 0);
CP_WRITE_REGISTER_BYTE(pjBase + BT485_CURSOR_Y_LOW, 0);
CP_WRITE_REGISTER_BYTE(pjBase + BT485_CURSOR_Y_HIGH, 0);
break;
case RAMDAC_BT482:
ucOldCmdRegA = CP_READ_REGISTER_BYTE(pjBase + BT482_COMMAND_REGA);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_COMMAND_REGA, BT482_EXTENDED_REG_SELECT);
// Set the cursor position outside the display.
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PALETTE_RAM_WRITE, CURS_X_LOW_REG);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PEL_MASK, 0);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PALETTE_RAM_WRITE, CURS_X_HIGH_REG);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PEL_MASK, 0);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PALETTE_RAM_WRITE, CURS_Y_LOW_REG);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PEL_MASK, 0);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PALETTE_RAM_WRITE, CURS_Y_HIGH_REG);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PEL_MASK, 0);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_CURSOR_RAM_WRITE, CURS_REG);
ucTemp = CP_READ_REGISTER_BYTE(pjBase + BT482_PEL_MASK);
ucTemp &= ~(BT482_CURSOR_OP_DISABLED | BT482_CURSOR_FIELDS);
ucTemp |= BT482_CURSOR_DISABLED;
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PEL_MASK, ucTemp);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_COMMAND_REGA, ucOldCmdRegA);
break;
case RAMDAC_VIEWPOINT:
// Set the cursor position outside the display.
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_INDEX, VPOINT_CUR_X_LSB);
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_DATA, VIEWPOINT_OUT & 0xff);
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_INDEX, VPOINT_CUR_X_MSB);
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_DATA, (VIEWPOINT_OUT >> 8));
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_INDEX, VPOINT_CUR_Y_LSB);
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_DATA, VIEWPOINT_OUT & 0xff);
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_INDEX, VPOINT_CUR_Y_MSB);
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_DATA, (VIEWPOINT_OUT >> 8));
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_INDEX, VPOINT_CUR_CTL);
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_DATA, VIEWPOINT_CURSOR_OFF);
break;
case RAMDAC_TVP3026:
case RAMDAC_TVP3030:
// Set the cursor position outside the display.
if (ppdev->ulBoardId == MGA_STORM)
{
ulDacScale = 0;
}
else
{
ulDacScale = 2;
}
CP_WRITE_REGISTER_BYTE(pjBase + TVP3026_CUR_X_LSB(ulDacScale),TVP3026_OUT & 0xff);
CP_WRITE_REGISTER_BYTE(pjBase + TVP3026_CUR_X_MSB(ulDacScale),(TVP3026_OUT >> 8));
CP_WRITE_REGISTER_BYTE(pjBase + TVP3026_CUR_Y_LSB(ulDacScale),TVP3026_OUT & 0xff);
CP_WRITE_REGISTER_BYTE(pjBase + TVP3026_CUR_Y_MSB(ulDacScale),(TVP3026_OUT >> 8));
// Disable the cursor.
CP_WRITE_REGISTER_BYTE(pjBase + TVP3026_INDIRECT_INDEX(ulDacScale),TVP3026_I_CUR_CTL);
ucTemp = CP_READ_REGISTER_BYTE(pjBase + TVP3026_INDEXED_DATA(ulDacScale));
ucTemp &= ~TVP3026_D_CURSOR_MASK;
ucTemp |= TVP3026_D_CURSOR_OFF;
CP_WRITE_REGISTER_BYTE(pjBase + TVP3026_INDEXED_DATA(ulDacScale),ucTemp);
break;
default:
break;
}
// Signal that the hardware cursor is not currently enabled.
ppdev->bHwPointerActive = FALSE;
return;
}
else
{
// Calculate the actual (x,y) coordinate to send to Bt48x RamDac
x -= ppdev->ptlHotSpot.x; // Adjust the (x,y) coordinate
y -= ppdev->ptlHotSpot.y; // considering the hot-spot
x += ppdev->szlPointerOverscan.cx;
y += ppdev->szlPointerOverscan.cy;
switch(ppdev->RamDacFlags)
{
case RAMDAC_BT485:
case RAMDAC_PX2085:
x += BT485_CURSOR_SIZE; // Bt48x origin is at the bottom
y += BT485_CURSOR_SIZE;
CP_WRITE_REGISTER_BYTE(pjBase + BT485_CURSOR_X_LOW, x & 0xff);
CP_WRITE_REGISTER_BYTE(pjBase + BT485_CURSOR_X_HIGH, x >> 8);
CP_WRITE_REGISTER_BYTE(pjBase + BT485_CURSOR_Y_LOW, y & 0xff);
CP_WRITE_REGISTER_BYTE(pjBase + BT485_CURSOR_Y_HIGH, y >> 8);
// Enable the cursor... We have a flag in the pdev
// to indicate whether the cursor is already enabled.
// We cannot read vsyncsts anymore, so we do it differently.
// The code for disabling the hardware cursor set its
// position to (0, 0), so any flickering should be less
// obvious.
if (!(ppdev->bHwPointerActive))
{
// The hardware cursor is disabled.
ucTemp = CP_READ_REGISTER_BYTE(pjBase + BT485_COMMAND_REG2);
ucTemp|=0x02;
CP_WRITE_REGISTER_BYTE(pjBase + BT485_COMMAND_REG2, ucTemp);
}
break;
case RAMDAC_VIEWPOINT:
x += VIEWPOINT_CURSOR_SIZE/2-1; // Viewpoint origin is at the center
y += VIEWPOINT_CURSOR_SIZE/2-1;
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_INDEX, VPOINT_CUR_X_LSB);
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_DATA, x & 0xff);
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_INDEX, VPOINT_CUR_X_MSB);
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_DATA, x >> 8);
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_INDEX, VPOINT_CUR_Y_LSB);
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_DATA, y & 0xff);
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_INDEX, VPOINT_CUR_Y_MSB);
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_DATA, y >> 8);
// Enable the cursor... We have a flag in the pdev
// to indicate whether the cursor is already enabled.
// We cannot read vsyncsts anymore, so we do it differently.
// The code for disabling the hardware cursor set its
// position to (0, 0), so any flickering should be less
// obvious.
if (!(ppdev->bHwPointerActive))
{
// The hardware cursor is disabled.
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_INDEX, VPOINT_CUR_CTL);
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_DATA, VIEWPOINT_CURSOR_ON);
}
break;
case RAMDAC_BT482:
x += BT482_CURSOR_SIZE; // Bt48x origin is at the bottom
y += BT482_CURSOR_SIZE;
ucOldCmdRegA = CP_READ_REGISTER_BYTE(pjBase + BT482_COMMAND_REGA);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_COMMAND_REGA,
ucOldCmdRegA | BT482_EXTENDED_REG_SELECT);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PALETTE_RAM_WRITE, CURS_X_LOW_REG);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PEL_MASK, x & 0xff);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PALETTE_RAM_WRITE, CURS_X_HIGH_REG);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PEL_MASK, x >> 8);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PALETTE_RAM_WRITE, CURS_Y_LOW_REG);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PEL_MASK, y & 0xff);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PALETTE_RAM_WRITE, CURS_Y_HIGH_REG);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PEL_MASK, y >> 8);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_COMMAND_REGA, ucOldCmdRegA);
// Enable the Bt482 Cursor.
// We cannot read vsyncsts anymore, so we do it differently.
// The code for disabling the hardware cursor set its
// position to (0, 0), so any flickering should be less
// obvious.
if (!(ppdev->bHwPointerActive))
{
// The hardware cursor is disabled.
ucOldCmdRegA = CP_READ_REGISTER_BYTE(pjBase + BT482_COMMAND_REGA);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_COMMAND_REGA, BT482_EXTENDED_REG_SELECT);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_CURSOR_RAM_WRITE, CURS_REG);
ucTemp = CP_READ_REGISTER_BYTE(pjBase + BT482_PEL_MASK);
ucTemp &= ~(BT482_CURSOR_OP_DISABLED | BT482_CURSOR_FIELDS);
ucTemp |= BT482_CURSOR_WINDOWS;
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PEL_MASK, ucTemp);
CP_WRITE_REGISTER_BYTE(pjBase + BT482_COMMAND_REGA, ucOldCmdRegA);
}
break;
case RAMDAC_TVP3026:
case RAMDAC_TVP3030:
if (ppdev->ulBoardId == MGA_STORM)
{
ulDacScale = 0;
}
else
{
ulDacScale = 2;
}
x += TVP3026_CURSOR_SIZE;
y += TVP3026_CURSOR_SIZE;
CP_WRITE_REGISTER_BYTE(pjBase + TVP3026_CUR_X_LSB(ulDacScale), x & 0xff);
CP_WRITE_REGISTER_BYTE(pjBase + TVP3026_CUR_X_MSB(ulDacScale), x >> 8);
CP_WRITE_REGISTER_BYTE(pjBase + TVP3026_CUR_Y_LSB(ulDacScale), y & 0xff);
CP_WRITE_REGISTER_BYTE(pjBase + TVP3026_CUR_Y_MSB(ulDacScale), y >> 8);
// Enable the cursor... We have a flag in the pdev
// to indicate whether the cursor is already enabled.
// We cannot read vsyncsts anymore, so we do it differently.
// The code for disabling the hardware cursor set its
// position to (0, 0), so any flickering should be less
// obvious.
if (!(ppdev->bHwPointerActive))
{
// The hardware cursor is disabled.
CP_WRITE_REGISTER_BYTE(pjBase + TVP3026_INDIRECT_INDEX(ulDacScale),TVP3026_I_CUR_CTL);
ucTemp = CP_READ_REGISTER_BYTE(pjBase + TVP3026_INDEXED_DATA(ulDacScale));
ucTemp &= ~TVP3026_D_CURSOR_MASK;
ucTemp |= TVP3026_D_CURSOR_ON;
CP_WRITE_REGISTER_BYTE(pjBase + TVP3026_INDEXED_DATA(ulDacScale),ucTemp);
}
break;
default:
break;
}
// Signal that the hardware cursor is enabled.
ppdev->bHwPointerActive = TRUE;
}
}
/******************************Public*Routine******************************\
* VOID vDisablePointer
*
\**************************************************************************/
VOID vDisablePointer(
PDEV* ppdev)
{
// Nothing to do, really
}
/******************************Public*Routine******************************\
* VOID vAssertModePointer
*
\**************************************************************************/
VOID vAssertModePointer(
PDEV* ppdev,
BOOL bEnable)
{
BYTE* pjBase;
BYTE byte;
BYTE Bt48xCmdReg0;
BYTE Bt48xCmdReg1;
BYTE Bt48xCmdReg2;
BYTE Bt48xCmdReg3;
if (bEnable)
{
pjBase = ppdev->pjBase;
ppdev->bHwPointerActive = FALSE;
ppdev->cyPointerHeight = 1024; // A large number to ensure that the
// entire pointer is downloaded
// the first time
switch (ppdev->RamDacFlags)
{
case RAMDAC_BT482:
// Make sure our copy of RegA doesn't allow access to extended
// registers.
byte = CP_READ_REGISTER_BYTE(pjBase + BT482_COMMAND_REGA);
Bt48xCmdReg0 = byte & ~BT482_EXTENDED_REG_SELECT;
// Get access to extended registers.
CP_WRITE_REGISTER_BYTE(pjBase + BT482_COMMAND_REGA,
Bt48xCmdReg0 | BT482_EXTENDED_REG_SELECT);
// Record contents of RegB.
CP_WRITE_REGISTER_BYTE(pjBase + BT482_CURSOR_RAM_WRITE, COMMAND_B_REG);
Bt48xCmdReg1 = CP_READ_REGISTER_BYTE(pjBase + BT482_PEL_MASK);
// Make sure our copy of Cursor Reg has the cursor disabled
// and the cursor color palette selected.
CP_WRITE_REGISTER_BYTE(pjBase + BT482_CURSOR_RAM_WRITE, CURS_REG);
byte = CP_READ_REGISTER_BYTE(pjBase + BT482_PEL_MASK);
Bt48xCmdReg2 = (byte & ~(BT482_CURSOR_FIELDS |
BT482_CURSOR_RAM_SELECT)) |
(BT482_CURSOR_DISABLED |
BT482_CURSOR_COLOR_PALETTE_SELECT);
// Disable the cursor, and prepare to access the cursor palette.
CP_WRITE_REGISTER_BYTE(pjBase + BT482_PEL_MASK, Bt48xCmdReg2);
// Cursor colors have been set by IOCTL_VIDEO_SET_CURRENT_MODE.
// We don't need access to extended registers any more, for now.
CP_WRITE_REGISTER_BYTE(pjBase + BT482_COMMAND_REGA, Bt48xCmdReg0);
// Our color palette will be set later, by the miniport.
break;
case RAMDAC_BT485:
case RAMDAC_PX2085:
// Make sure our copy of Reg0 doesn't allow access to Reg3.
byte = CP_READ_REGISTER_BYTE(pjBase + BT485_COMMAND_REG0);
// There seems to be a problem with unselecting Command 3
// Bt48xCmdReg0 = byte & ~BT485_REG3_SELECT;
Bt48xCmdReg0 = byte;
Bt48xCmdReg1 = CP_READ_REGISTER_BYTE(pjBase + BT485_COMMAND_REG1);
// Make sure our copy of Reg2 has the cursor disabled.
byte = CP_READ_REGISTER_BYTE(pjBase + BT485_COMMAND_REG2);
Bt48xCmdReg2 = (byte & ~BT485_CURSOR_FIELDS) |
BT485_CURSOR_DISABLED;
// Disable the cursor.
CP_WRITE_REGISTER_BYTE(pjBase + BT485_COMMAND_REG2, Bt48xCmdReg2);
// Access and record contents of Reg3.
CP_WRITE_REGISTER_BYTE(pjBase + BT485_COMMAND_REG0, Bt48xCmdReg0 |
BT485_REG3_SELECT);
CP_WRITE_REGISTER_BYTE(pjBase + BT485_CURSOR_RAM_WRITE, 1);
byte = CP_READ_REGISTER_BYTE(pjBase + BT485_COMMAND_REG3);
// Make sure our copy of Reg3 has the 64x64 cursor selected
// and the 2MSBs for the 64x64 cursor set to zero.
Bt48xCmdReg3 = byte | BT485_CURSOR_64X64 &
~BT485_CURSOR_64X64_FIELDS;
// Make sure we start out using the 64x64 cursor, and record
// the pointer size so that we know which one we're using.
CP_WRITE_REGISTER_BYTE(pjBase + BT485_COMMAND_REG3, Bt48xCmdReg3);
// There seems to be a problem with unselecting Command 3
// We don't need to access Reg3 any more, for now.
CP_WRITE_REGISTER_BYTE(pjBase + BT485_COMMAND_REG0, Bt48xCmdReg0);
// Cursor colors have been set by IOCTL_VIDEO_SET_CURRENT_MODE.
// Our color palette will be set later, by the miniport.
break;
case RAMDAC_VIEWPOINT:
// Disable the cursor.
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_INDEX, VPOINT_CUR_CTL);
CP_WRITE_REGISTER_BYTE(pjBase + VIEWPOINT_DATA, VIEWPOINT_CURSOR_OFF);
// Cursor colors have been set by IOCTL_VIDEO_SET_CURRENT_MODE.
// Our color palette will be set later, by the miniport.
break;
case RAMDAC_TVP3026:
case RAMDAC_TVP3030:
// Disable the cursor.
if (ppdev->ulBoardId == MGA_STORM)
{
CP_WRITE_REGISTER_BYTE(pjBase + TVP3026_INDIRECT_INDEX(NEW_TVP_SHIFT), TVP3026_I_CUR_CTL);
byte = CP_READ_REGISTER_BYTE(pjBase + TVP3026_INDEXED_DATA(NEW_TVP_SHIFT));
byte &= ~TVP3026_D_CURSOR_MASK;
byte |= TVP3026_D_CURSOR_OFF;
CP_WRITE_REGISTER_BYTE(pjBase + TVP3026_INDEXED_DATA(NEW_TVP_SHIFT), byte);
}
else
{
CP_WRITE_REGISTER_BYTE(pjBase + TVP3026_INDIRECT_INDEX(OLD_TVP_SHIFT), TVP3026_I_CUR_CTL);
byte = CP_READ_REGISTER_BYTE(pjBase + TVP3026_INDEXED_DATA(OLD_TVP_SHIFT));
byte &= ~TVP3026_D_CURSOR_MASK;
byte |= TVP3026_D_CURSOR_OFF;
CP_WRITE_REGISTER_BYTE(pjBase + TVP3026_INDEXED_DATA(OLD_TVP_SHIFT), byte);
}
// Cursor colors have been set by IOCTL_VIDEO_SET_CURRENT_MODE.
// Our color palette will be set later, by the miniport.
break;
}
}
}
/******************************Public*Routine******************************\
* BOOL bEnablePointer
*
\**************************************************************************/
BOOL bEnablePointer(
PDEV* ppdev)
{
RAMDAC_INFO VideoPointerAttr;
ULONG ReturnedDataLength;
// Query the MGA miniport about the hardware pointer, using a private
// IOCTL:
if (EngDeviceIoControl(ppdev->hDriver,
IOCTL_VIDEO_MTX_QUERY_RAMDAC_INFO,
NULL, // Input
0,
&VideoPointerAttr,
sizeof(RAMDAC_INFO),
&ReturnedDataLength))
{
DISPDBG((0, "bEnablePointer -- failed MTX_QUERY_RAMDAC_INFO"));
return(FALSE);
}
ppdev->RamDacFlags = VideoPointerAttr.Flags & RAMDAC_FIELDS;
ppdev->szlPointerOverscan.cx = VideoPointerAttr.OverScanX;
ppdev->szlPointerOverscan.cy = VideoPointerAttr.OverScanY;
// Initialize the pointer:
vAssertModePointer(ppdev, TRUE);
return(TRUE);
}