windows-nt/Source/XPSP1/NT/drivers/video/ms/weitek/disp/hw.h
2020-09-26 16:20:57 +08:00

571 lines
21 KiB
C

/******************************Module*Header*******************************\
* Module Name: hw.h
*
* All the hardware specific driver file stuff. Parts are mirrored in
* 'hw.inc'.
*
* Copyright (c) 1992-1995 Microsoft Corporation
*
\**************************************************************************/
//
// Private IOCTL definitions for communicating with the Weitek miniport.
//
// NOTE: These must match the Weitek miniport definitions!
//
#define IOCTL_VIDEO_GET_BASE_ADDR \
CTL_CODE (FILE_DEVICE_VIDEO, 2048, METHOD_BUFFERED, FILE_ANY_ACCESS)
typedef struct _VIDEO_COPROCESSOR_INFORMATION {
ULONG CoprocessorID; // 0 == p9000, 1 = p9100
ULONG FrameBufferBase;
ULONG CoprocessorBase;
} VIDEO_COPROCESSOR_INFORMATION, *PVIDEO_COPROCESSOR_INFORMATION;
//////////////////////////////////////////////////////////////////////
// Shared p9000 and p9100 Coproc Registers Address Constant definitions
//
#define Status 0x80000 //status register
#define Wmin 0x80220 //pixel clipping window minimum register
#define Wmax 0x80224 //and maximum register
#define Woffset 0x80190 //window offset register
#define Quad 0x80008 //draw a quadrilateral
#define Bitblt 0x80004 //screen to screen blit
#define Pixel8 0xE000C //host to screen color pixel transfer
#define Pixel1 0xE0080 //host to screen mono pixel transfer w/ expansion
#define Pixel1Full 0xE00FC //same as above w/ 32bit wide pixels
#define Nextpixel 0x80014 //next pixel
#define PatternOrgX 0x80210 //pattern orgin x
#define PatternOrgY 0x80214 //pattern orgin y
#define PatternRAM 0xE0280 //pattern ram
#define Raster 0x80218 //raster register to write
#define Metacord 0x81218 //meta-coordinate register
#define Xy0 0x81018 //abs screen addr
#define Xy1 0x81058 //r/w 16-bit x (hi)
#define Xy2 0x81098 // and
#define Xy3 0x810D8 // 16-bit y (lo)
#define X0 0x81008 //abs screen addr
#define X1 0x81048
#define X2 0x81088
#define X3 0x810C8
#define Y0 0x81010 //abs screen addr
#define Y1 0x81050
#define Y2 0x81090
#define Y3 0x810D0
#define WoffsetBit 0x00020 //bit to set for coordinates relative
//to window offset
//
// p9000 Coproc Registers Address Constant definitions
//
#define Foreground 0x80200 //P9000 foreground color register
#define Background 0x80204 //P9000 background color register
//
// p9100 Coproc Registers Address Constant definitions
//
#define Wmin_b 0x802A0 //byte clipping window minimum register
#define Wmax_b 0x802A4 //and maximum register
#define Color0 0xE0200 //P9100 color[0] register
#define Color1 0xE0204 //P9100 color[1] register
#define Color2 0xE0238 //P9100 color[2] register
#define Color3 0xE023C //P9100 color[3] register
// We try to share as many register constants as we can between the
// P9000 and the P9100, so that we don't have to duplicate code.
// But the base offset for the registers we used changed somewhat;
// we apply this corrector to the I/O base pointer to compensate:
#define P9100_BASE_CORRECTION (0x2000L - 0x80000L)
//////////////////////////////////////////////////////////////////////
// Shared p9000 and p9100 Coproc Registers bit template definitions
//
#define BUSY 0x40000000L //busy, but can start quad or bitblit
#define QBUSY 0x80000000L //busy, cannot start quad or bitblt
#define QUADFAIL 0x10 //QUAD failed, use software to draw this
#define MetaRect 0x100 //or with METACORD when entering rectangles
#define MetaLine 0x040 //or with METACORD when entering line
#define MetaQuad 0x0C0 //or with METACORD when entering quad
#define MetaTri 0x080 //or with METACORD when entering triangle
//
// p9000 Coproc Registers bit template definitions
//
// For the raster register:
#define P9000_ENABLE_PATTERN 0x20000 //enable pattern
#define P9000_OVERSIZED 0x10000 //enable oversized mode
#define P9000_F 0xff00L
#define P9000_B 0xf0f0L
#define P9000_S 0xccccL
#define P9000_D 0xaaaaL
#define P9000_OPAQUE_EXPAND 0xfc30L
#define P9000_TRANSPARENT_EXPAND 0xee22L
//
// p9100 Coproc Registers bit template definitions
//
// For the raster register:
#define P9100_TRANSPARENT_PATTERN 0x20000 //enable transparent pattern
#define P9100_OVERSIZED 0x10000 //enable oversized mode
#define P9100_PIXEL1_TRANSPARENT 0x08000 //enable pixel1 transparent mode
#define P9100_FOUR_COLOR_PATTERN 0x04000 //4 colour pattern (8bpp only)
#define P9100_ENABLE_PATTERN 0x02000 //enable pattern
#define P9100_P 0x00f0L
#define P9100_S 0x00ccL
#define P9100_D 0x00aaL
#define P9100_OPAQUE_EXPAND P9100_S
#define P9100_TRANSPARENT_EXPAND (P9100_S | P9100_PIXEL1_TRANSPARENT)
//////////////////////////////////////////////////////////////////////
// Alpha and PowerPC considerations
//
// Both the Alpha and the PowerPC do not guarantee that I/O to
// separate addresses will be executed in order. The Alpha and
// PowerPC differ, however, in that the PowerPC guarantees that
// output to the same address will be executed in order, while the
// Alpha may cache and 'collapse' consecutive output to become only
// one output.
//
// Consequently, we use the following synchronization macros. They
// are relatively expensive in terms of performance, so we try to avoid
// them whereever possible.
//
// CP_EIEIO() 'Ensure In-order Execution of I/O'
// - Used to flush any pending I/O in situations where we wish to
// avoid out-of-order execution of I/O to separate addresses.
//
// CP_MEMORY_BARRIER()
// - Used to flush any pending I/O in situations where we wish to
// avoid out-of-order execution or 'collapsing' of I/O to
// the same address. On the PowerPC, this will be defined as
// a null operation.
#if defined(_PPC_)
// On PowerPC, CP_MEMORY_BARRIER doesn't do anything.
#define CP_EIEIO() MEMORY_BARRIER()
#define CP_MEMORY_BARRIER()
#else
// On Alpha, CP_EIEIO is the same thing as a CP_MEMORY_BARRIER.
// On other systems, both CP_EIEIO and CP_MEMORY_BARRIER don't do anything.
#define CP_EIEIO() MEMORY_BARRIER()
#define CP_MEMORY_BARRIER() MEMORY_BARRIER()
#endif
//////////////////////////////////////////////////////////////////////
// Access macros:
//
#define MAX_COORD 0x3fff
#define CP_OUT(pjBase, cjOffset, ul) \
WRITE_REGISTER_ULONG((BYTE*) pjBase + (cjOffset), (ULONG) (ul))
#define CP_IN(pjBase, cjOffset) \
READ_REGISTER_ULONG((BYTE*) pjBase + (cjOffset))
// Note that we have to be careful if 'y' is negative that its signed
// bits don't get ORed into the 'x' component:
#define PACKXY(x, y) (((x) << 16) | ((y) & 0xffff))
#define CP_WAIT(ppdev, pjBase) \
{ \
do {CP_EIEIO();} while (CP_IN(pjBase, Status) & BUSY); \
CP_EIEIO(); \
}
#define CP_RASTER(ppdev, pjBase, x) \
{ \
ASSERTDD(P9000(ppdev) || ((x) & 0x01f00) == 0, \
"Illegal P9100 raster value"); \
CP_OUT(pjBase, Raster, (x)); \
}
#define CP_NEXT_PIXELS(ppdev, pjBase, x) \
CP_OUT(pjBase, Nextpixel, (x));
#define CP_START_QUAD(ppdev, pjBase) \
{ \
CP_EIEIO(); \
CP_IN(pjBase, Quad); \
CP_EIEIO(); \
}
#define CP_START_QUAD_STAT(ppdev, pjBase, stat) \
{ \
CP_EIEIO(); \
stat = CP_IN(pjBase, Quad); \
CP_EIEIO(); \
}
#define CP_START_QUAD_WAIT(ppdev, pjBase) \
{ \
do { \
CP_EIEIO(); \
} while (CP_IN(pjBase, Quad) & QBUSY); \
CP_EIEIO(); \
}
#define CP_START_BLT(ppdev, pjBase) \
{ \
CP_EIEIO(); \
CP_IN(pjBase, Bitblt); \
CP_EIEIO(); \
}
#define CP_START_BLT_WAIT(ppdev, pjBase) \
{ \
do { \
CP_EIEIO(); \
} while (CP_IN(pjBase, Bitblt) & QBUSY); \
CP_EIEIO(); \
}
#define CP_START_QUAD(ppdev, pjBase) \
{ \
CP_EIEIO(); \
CP_IN(pjBase, Quad); \
CP_EIEIO(); \
}
#define CP_START_PIXEL8(ppdev, pjBase) \
CP_EIEIO();
#define CP_END_PIXEL8(ppdev, pjBase) \
CP_EIEIO();
#define CP_PIXEL8(ppdev, pjBase, x) \
{ \
CP_OUT(pjBase, Pixel8, (x)); \
CP_MEMORY_BARRIER(); \
}
#define CP_START_PIXEL1(ppdev, pjBase) \
CP_EIEIO();
#define CP_END_PIXEL1(ppdev, pjBase) \
CP_EIEIO();
#define CP_PIXEL1(ppdev, pjBase, x) \
{ \
CP_OUT(pjBase, Pixel1Full, (x)); \
CP_MEMORY_BARRIER(); \
}
// Note: 'count' must be pre-decremented by 1
#define CP_PIXEL1_REM(ppdev, pjBase, count, x) \
{ \
/* This EIEIO is to ensure we don't get out of */ \
/* order with normal full CP_PIXEL1 writes */ \
CP_EIEIO(); \
CP_OUT(pjBase, Pixel1 + ((count) << 2), (x)); \
}
#define CP_PIXEL1_REM_REGISTER(ppdev, pjBase, count)\
((BYTE*) (pjBase) + Pixel1 + ((count) << 2))
#define CP_PIXEL1_VIA_REGISTER(ppdev, pReg, x) \
{ \
/* This EIEIO is to ensure we don't get out of */ \
/* order with normal full CP_PIXEL1 writes */ \
CP_EIEIO(); \
WRITE_REGISTER_ULONG(pReg, (x)); \
}
#define CP_PATTERN(ppdev, pjBase, index, x) \
CP_OUT(pjBase, PatternRAM + ((index) << 2), (x))
#define CP_PATTERN_ORGX(ppdev, pjBase, x) \
CP_OUT(pjBase, PatternOrgX, (x))
#define CP_PATTERN_ORGY(ppdev, pjBase, x) \
CP_OUT(pjBase, PatternOrgY, (x))
//
#define CP_METALINE(ppdev, pjBase, x, y) \
{ \
CP_OUT(pjBase, Metacord | MetaLine, \
PACKXY((x) + ppdev->xOffset, (y) + ppdev->yOffset));\
CP_MEMORY_BARRIER(); \
}
#define CP_METARECT(ppdev, pjBase, x, y) \
{ \
CP_OUT(pjBase, Metacord | MetaRect, \
PACKXY((x) + ppdev->xOffset, (y) + ppdev->yOffset));\
CP_MEMORY_BARRIER(); \
}
#define CP_METAQUAD(ppdev, pjBase, x, y) \
{ \
CP_OUT(pjBase, Metacord | MetaQuad, \
PACKXY((x) + ppdev->xOffset, (y) + ppdev->yOffset));\
CP_MEMORY_BARRIER(); \
}
#define CP_METATRI(ppdev, pjBase, x, y) \
{ \
CP_OUT(pjBase, Metacord | MetaTri, \
PACKXY((x) + ppdev->xOffset, (y) + ppdev->yOffset));\
CP_MEMORY_BARRIER(); \
}
#define CP_WOFFSET(ppdev, pjBase, x, y) \
CP_OUT(pjBase, Woffset, PACKXY((x), (y)))
#define CP_WMIN(ppdev, pjBase, x, y) \
CP_OUT(pjBase, P9000(ppdev) ? Wmin : Wmin_b, \
PACKXY(((x) + ppdev->xOffset) * ppdev->cjPel, (y) + ppdev->yOffset))
#define CP_WMAX(ppdev, pjBase, x, y) \
CP_OUT(pjBase, P9000(ppdev) ? Wmax : Wmax_b, \
PACKXY(((x) + ppdev->xOffset + 1) * ppdev->cjPel - 1, (y) + ppdev->yOffset))
#define CP_WLEFT(ppdev, pjBase, x) \
CP_OUT(pjBase, P9000(ppdev) ? Wmin : Wmin_b, \
PACKXY(((x) + ppdev->xOffset) * ppdev->cjPel, 0))
#define CP_WRIGHT(ppdev, pjBase, x) \
CP_OUT(pjBase, P9000(ppdev) ? Wmax : Wmax_b, \
PACKXY(((x) + ppdev->xOffset + 1) * ppdev->cjPel - 1, MAX_COORD))
#define CP_XY0(ppdev, pjBase, x, y) \
CP_OUT(pjBase, Xy0, PACKXY((x) + ppdev->xOffset, (y) + ppdev->yOffset))
#define CP_XY1(ppdev, pjBase, x, y) \
CP_OUT(pjBase, Xy1, PACKXY((x) + ppdev->xOffset, (y) + ppdev->yOffset))
#define CP_XY2(ppdev, pjBase, x, y) \
CP_OUT(pjBase, Xy2, PACKXY((x) + ppdev->xOffset, (y) + ppdev->yOffset))
#define CP_XY3(ppdev, pjBase, x, y) \
CP_OUT(pjBase, Xy3, PACKXY((x) + ppdev->xOffset, (y) + ppdev->yOffset))
#define CP_X0(ppdev, pjBase, x) \
CP_OUT(pjBase, X0, (x) + ppdev->xOffset)
#define CP_X1(ppdev, pjBase, x) \
CP_OUT(pjBase, X1, (x) + ppdev->xOffset)
#define CP_X2(ppdev, pjBase, x) \
CP_OUT(pjBase, X2, (x) + ppdev->xOffset)
#define CP_X3(ppdev, pjBase, x) \
CP_OUT(pjBase, X3, (x) + ppdev->xOffset)
#define CP_Y0(ppdev, pjBase, y) \
CP_OUT(pjBase, Y0, (y) + ppdev->yOffset)
#define CP_Y1(ppdev, pjBase, y) \
CP_OUT(pjBase, Y1, (y) + ppdev->yOffset)
#define CP_Y2(ppdev, pjBase, y) \
CP_OUT(pjBase, Y2, (y) + ppdev->yOffset)
#define CP_Y3(ppdev, pjBase, y) \
CP_OUT(pjBase, Y3, (y) + ppdev->yOffset)
//
#define CP_WOFF_PACKED_XY0(ppdev, pjBase, xy) \
CP_OUT(pjBase, Xy0 | WoffsetBit, (xy))
#define CP_WOFF_PACKED_XY1(ppdev, pjBase, xy) \
CP_OUT(pjBase, Xy1 | WoffsetBit, (xy))
#define CP_WOFF_PACKED_XY2(ppdev, pjBase, xy) \
CP_OUT(pjBase, Xy2 | WoffsetBit, (xy))
#define CP_WOFF_PACKED_XY3(ppdev, pjBase, xy) \
CP_OUT(pjBase, Xy3 | WoffsetBit, (xy))
#define CP_ABS_PACKED_XY0(ppdev, pjBase, xy) \
CP_OUT(pjBase, Xy0, (xy))
#define CP_ABS_PACKED_XY1(ppdev, pjBase, xy) \
CP_OUT(pjBase, Xy1, (xy))
#define CP_ABS_PACKED_XY2(ppdev, pjBase, xy) \
CP_OUT(pjBase, Xy2, (xy))
#define CP_ABS_PACKED_XY3(ppdev, pjBase, xy) \
CP_OUT(pjBase, Xy3, (xy))
//
#define CP_ABS_WMIN(ppdev, pjBase, x, y) \
CP_OUT(pjBase, P9000(ppdev) ? Wmin : Wmin_b, \
PACKXY((x) * ppdev->cjPel, (y)))
#define CP_ABS_WMAX(ppdev, pjBase, x, y) \
CP_OUT(pjBase, P9000(ppdev) ? Wmax : Wmax_b, \
PACKXY(((x) + 1) * ppdev->cjPel - 1, (y)))
#define CP_ABS_WLEFT(ppdev, pjBase, x) \
CP_OUT(pjBase, P9000(ppdev) ? Wmin : Wmin_b, \
PACKXY((x) * ppdev->cjPel, 0))
#define CP_ABS_WRIGHT(ppdev, pjBase, x) \
CP_OUT(pjBase, P9000(ppdev) ? Wmax : Wmax_b, \
PACKXY(((x) + 1) * ppdev->cjPel - 1, MAX_COORD))
#define CP_ABS_METARECT(ppdev, pjBase, x, y) \
{ \
CP_OUT(pjBase, Metacord | MetaRect, PACKXY((x), (y)));\
CP_MEMORY_BARRIER(); \
}
#define CP_ABS_XY0(ppdev, pjBase, x, y) \
CP_OUT(pjBase, Xy0, PACKXY((x), (y)))
#define CP_ABS_XY1(ppdev, pjBase, x, y) \
CP_OUT(pjBase, Xy1, PACKXY((x), (y)))
#define CP_ABS_XY2(ppdev, pjBase, x, y) \
CP_OUT(pjBase, Xy2, PACKXY((x), (y)))
#define CP_ABS_XY3(ppdev, pjBase, x, y) \
CP_OUT(pjBase, Xy3, PACKXY((x), (y)))
#define CP_ABS_PACKED_XY0(ppdev, pjBase, x) \
CP_OUT(pjBase, Xy0, (x))
#define CP_ABS_PACKED_XY1(ppdev, pjBase, x) \
CP_OUT(pjBase, Xy1, (x))
#define CP_ABS_PACKED_XY2(ppdev, pjBase, x) \
CP_OUT(pjBase, Xy2, (x))
#define CP_ABS_PACKED_XY3(ppdev, pjBase, x) \
CP_OUT(pjBase, Xy3, (x))
#define CP_ABS_X0(ppdev, pjBase, y) \
CP_OUT(pjBase, X0, (y))
#define CP_ABS_X1(ppdev, pjBase, y) \
CP_OUT(pjBase, X1, (y))
#define CP_ABS_X2(ppdev, pjBase, y) \
CP_OUT(pjBase, X2, (y))
#define CP_ABS_X3(ppdev, pjBase, y) \
CP_OUT(pjBase, X3, (y))
#define CP_ABS_Y0(ppdev, pjBase, y) \
CP_OUT(pjBase, Y0, (y))
#define CP_ABS_Y1(ppdev, pjBase, y) \
CP_OUT(pjBase, Y1, (y))
#define CP_ABS_Y2(ppdev, pjBase, y) \
CP_OUT(pjBase, Y2, (y))
#define CP_ABS_Y3(ppdev, pjBase, y) \
CP_OUT(pjBase, Y3, (y))
///////////////////////////////////////////////////////////////////
// P9000 only macros
//
#define CP_FOREGROUND(ppdev, pjBase, x) \
{ \
ASSERTDD(ppdev->flStat & STAT_P9000, "Foreground"); \
CP_OUT(pjBase, Foreground, (x)); \
}
#define CP_BACKGROUND(ppdev, pjBase, x) \
{ \
ASSERTDD(ppdev->flStat & STAT_P9000, "Background"); \
CP_OUT(pjBase, Background, (x)); \
}
///////////////////////////////////////////////////////////////////
// P9100 only macros
//
#define PACK_COLOR(ppdev, x, ulResult) \
{ \
ulResult = (x); \
if (ppdev->flStat & STAT_8BPP) \
{ \
ulResult |= (ulResult << 8); \
ulResult |= (ulResult << 16); \
} \
else if (ppdev->flStat & STAT_16BPP) \
ulResult |= (ulResult << 16); \
else if (ppdev->flStat & STAT_24BPP) \
ulResult |= (ulResult << 24); \
}
#define CP_COLOR0(ppdev, pjBase, x) \
{ \
ULONG ul; \
ASSERTDD(!(ppdev->flStat & STAT_P9000), "Color0"); \
PACK_COLOR(ppdev, (x), ul); \
CP_OUT(pjBase, Color0, ul); \
}
#define CP_COLOR1(ppdev, pjBase, x) \
{ \
ULONG ul; \
ASSERTDD(!(ppdev->flStat & STAT_P9000), "Color1"); \
PACK_COLOR(ppdev, (x), ul); \
CP_OUT(pjBase, Color1, ul); \
}
// The _FAST colour macros take colours that are pre-packed for
// the P9100:
#define CP_COLOR0_FAST(ppdev, pjBase, x) \
{ \
ASSERTDD(!(ppdev->flStat & STAT_P9000), "Color0"); \
CP_OUT(pjBase, Color0, (x)); \
}
#define CP_COLOR1_FAST(ppdev, pjBase, x) \
{ \
ASSERTDD(!(ppdev->flStat & STAT_P9000), "Color1"); \
CP_OUT(pjBase, Color1, (x)); \
}
#define CP_COLOR2_FAST(ppdev, pjBase, x) \
{ \
ASSERTDD(!(ppdev->flStat & STAT_P9000), "Color2"); \
ASSERTDD(ppdev->flStat & STAT_8BPP, "Color2"); \
CP_OUT(pjBase, Color2, (x)); \
}
#define CP_COLOR3_FAST(ppdev, pjBase, x) \
{ \
ASSERTDD(!(ppdev->flStat & STAT_P9000), "Color3"); \
ASSERTDD(ppdev->flStat & STAT_8BPP, "Color3"); \
CP_OUT(pjBase, Color3, (x)); \
}