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

980 lines
34 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
*
\**************************************************************************/
#define CP_TRACK DISPDBG((100,"CP access - File(%s) line(%d)", __FILE__, __LINE__))
typedef struct _PDEV PDEV; // Handy forward declaration
//////////////////////////////////////////////////////////////////////
// private IOCTL info - if you touch this, do the same to the miniport
#define IOCTL_VIDEO_GET_VIDEO_CARD_INFO \
CTL_CODE (FILE_DEVICE_VIDEO, 2048, METHOD_BUFFERED, FILE_ANY_ACCESS)
typedef struct _VIDEO_COPROCESSOR_INFORMATION {
ULONG ulChipID; // ET3000, ET4000, W32, W32I, or W32P
ULONG ulRevLevel; // REV_A, REV_B, REV_C, REV_D, REV_UNDEF
ULONG ulVideoMemory; // in bytes
} VIDEO_COPROCESSOR_INFORMATION, *PVIDEO_COPROCESSOR_INFORMATION;
//////////////////////////////////////////////////////////////////////
// The following are reflected in hw.inc. Don't change these
// without changing that file.
typedef enum _CHIP_TYPE {
ET3000 = 1,
ET4000,
W32,
W32I,
W32P,
ET6000
} CHIP_TYPE;
typedef enum _REV_TYPE {
REV_UNDEF = 1,
REV_A,
REV_B,
REV_C,
REV_D,
} REV_TYPE;
//////////////////////////////////////////////////////////////////////
// Ports
#define SEG_SELECT_LO 0x03CD
#define SEG_SELECT_HI 0x03CB
#define CRTC_INDEX 0x03D4
#define CRTC_DATA 0x03D5
#define CRTCB_SPRITE_INDEX 0x217A
#define CRTCB_SPRITE_DATA 0x217B
//////////////////////////////////////////////////////////////////////
// Memory Map
// When we are banked
#define BANKED_MMU_BUFFER_MEMORY_ADDR 0xB8000
#define BANKED_MMU_BUFFER_MEMORY_LEN (0xBE000 - 0xB8000)
#define BANKED_MMU_MEMORY_MAPPED_REGS_ADDR 0xBFF00
#define BANKED_MMU_MEMORY_MAPPED_REGS_LEN (0xC0000 - 0xBFF00)
#define BANKED_MMU_EXTERNAL_MAPPED_REGS_ADDR 0xBE000
#define BANKED_MMU_EXTERNAL_MAPPED_REGS_LEN (0xBF000 - 0xBE000)
#define BANKED_APERTURE_0_OFFSET 0x0000
#define BANKED_APERTURE_1_OFFSET 0x2000
#define BANKED_APERTURE_2_OFFSET 0x4000
// When we are linear
#define MMU_BUFFER_MEMORY_ADDR 0x200000
#define MMU_BUFFER_MEMORY_LEN 0x17FFFF
#define MMU_MEMORY_MAPPED_REGS_ADDR 0x3FFF00
#define MMU_MEMORY_MAPPED_REGS_LEN 0x000100
#define MMU_EXTERNAL_MAPPED_REGS_ADDR 0x3FE000
#define MMU_EXTERNAL_MAPPED_REGS_LEN 0x001000
#define APERTURE_0_OFFSET 0x000000
#define APERTURE_1_OFFSET 0x080000
#define APERTURE_2_OFFSET 0x100000
// Always
#define VGA_MEMORY_ADDR 0xA0000
#define MMU_APERTURE_2_ACL_BIT 0x04
#define MMU_PORT_IO_ADDR 0
#define MMU_PORT_IO_LEN 0x10000
//////////////////////////////////////////////////////////////////////
// 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
//////////////////////////////////////////////////////////////////
// Port access macros
#define CP_OUT_DWORD(pjBase, cjOffset, ul)\
{\
CP_TRACK;\
WRITE_PORT_ULONG((BYTE*) pjBase + (cjOffset), (DWORD) (ul));\
CP_EIEIO();\
}
#define CP_OUT_WORD(pjBase, cjOffset, w)\
{\
CP_TRACK;\
WRITE_PORT_USHORT((BYTE*) pjBase + (cjOffset), (WORD) (w));\
CP_EIEIO();\
}
#define CP_OUT_BYTE(pjBase, cjOffset, j)\
{\
CP_TRACK;\
WRITE_PORT_UCHAR((BYTE*) pjBase + (cjOffset), (BYTE) (j));\
CP_EIEIO();\
}
#define CP_IN_DWORD(pjBase, cjOffset)\
(\
CP_TRACK,\
READ_PORT_ULONG((BYTE*) pjBase + (cjOffset))\
)
#define CP_IN_WORD(pjBase, cjOffset)\
(\
CP_TRACK,\
READ_PORT_USHORT((BYTE*) pjBase + (cjOffset))\
)
#define CP_IN_BYTE(pjBase, cjOffset)\
(\
CP_TRACK,\
READ_PORT_UCHAR((BYTE*) pjBase + (cjOffset))\
)
//////////////////////////////////////////////////////////////////
// Memory mapped register access macros
#define CP_WRITE_DWORD(pjBase, cjOffset, ul)\
CP_TRACK,\
WRITE_REGISTER_ULONG((BYTE*) pjBase + (cjOffset), (DWORD) (ul))
#define CP_WRITE_WORD(pjBase, cjOffset, w)\
CP_TRACK,\
WRITE_REGISTER_USHORT((BYTE*) pjBase + (cjOffset), (WORD) (w))
#define CP_WRITE_BYTE(pjBase, cjOffset, j)\
CP_TRACK,\
WRITE_REGISTER_UCHAR((BYTE*) pjBase + (cjOffset), (BYTE) (j))
#define CP_READ_DWORD(pjBase, cjOffset)\
(\
CP_TRACK,\
READ_REGISTER_ULONG((BYTE*) pjBase + (cjOffset))\
)
#define CP_READ_WORD(pjBase, cjOffset)\
(\
CP_TRACK,\
READ_REGISTER_USHORT((BYTE*) pjBase + (cjOffset))\
)
#define CP_READ_BYTE(pjBase, cjOffset)\
(\
CP_TRACK,\
READ_REGISTER_UCHAR((BYTE*) pjBase + (cjOffset))\
)
//////////////////////////////////////////////////////////
// W32 ACL register access macros
//////////////////////////////////////////////////////////
// Reads
#define CP_ACL_STAT(ppdev, pjBase)\
CP_READ_BYTE(pjBase, OFFSET_jAclStatus)
//////////////////////////////////////////////////////////
// Writes
#define CP_WRITE_MMU_DWORD(ppdev, mmu, offset, x)\
{\
CP_WRITE_DWORD((ppdev->pjMmu##mmu), offset, (x));\
CP_EIEIO();\
}
#define CP_WRITE_MMU_WORD(ppdev, mmu, offset, x)\
{\
CP_WRITE_WORD((ppdev->pjMmu##mmu), offset, (x));\
CP_EIEIO();\
}
#define CP_WRITE_MMU_BYTE(ppdev, mmu, offset, x)\
{\
CP_WRITE_BYTE((ppdev->pjMmu##mmu), offset, (x));\
CP_EIEIO();\
}
#define CP_MMU_BP0(ppdev, pjBase, x)\
{\
CP_WRITE_DWORD(pjBase, OFFSET_ulMmuBasePtr0, (x));\
CP_EIEIO();\
}
#define CP_MMU_BP1(ppdev, pjBase, x)\
{\
CP_WRITE_DWORD(pjBase, OFFSET_ulMmuBasePtr1, (x));\
CP_EIEIO();\
}
#define CP_MMU_BP2(ppdev, pjBase, x)\
{\
CP_WRITE_DWORD(pjBase, OFFSET_ulMmuBasePtr2, (x));\
CP_EIEIO();\
}
#define CP_MMU_CTRL(ppdev, pjBase, x)\
{\
CP_WRITE_BYTE(pjBase, OFFSET_jMmuCtrl, (x));\
CP_EIEIO();\
}
#define CP_STATE(ppdev, pjBase, x)\
{\
CP_WRITE_BYTE(pjBase, OFFSET_jOperationState, (x));\
CP_EIEIO();\
}
#define CP_SYNC_ENABLE(ppdev, pjBase, x)\
{\
CP_WRITE_BYTE(pjBase, OFFSET_jSyncEnable, (x));\
CP_EIEIO();\
}
#define CP_PAT_ADDR(ppdev, pjBase, x)\
{\
CP_WRITE_DWORD(pjBase, OFFSET_ulPatAddr, (x));\
CP_EIEIO();\
}
#define CP_SRC_ADDR(ppdev, pjBase, x)\
{\
CP_WRITE_DWORD(pjBase, OFFSET_ulSrcAddr, (x));\
CP_EIEIO();\
}
#define CP_DST_ADDR(ppdev, pjBase, x)\
{\
CP_WRITE_DWORD(pjBase, OFFSET_ulDstAddr, (x));\
CP_EIEIO();\
}
#define CP_MIX_ADDR(ppdev, pjBase, x)\
{\
CP_WRITE_DWORD(pjBase, OFFSET_ulMixAddr, (x));\
CP_EIEIO();\
}
#define CP_PAT_Y_OFFSET(ppdev, pjBase, x)\
{\
CP_WRITE_WORD(pjBase, OFFSET_wPatYOffset, (x));\
CP_EIEIO();\
}
#define CP_SRC_Y_OFFSET(ppdev, pjBase, x)\
{\
CP_WRITE_WORD(pjBase, OFFSET_wSrcYOffset, (x));\
CP_EIEIO();\
}
#define CP_DST_Y_OFFSET(ppdev, pjBase, x)\
{\
CP_WRITE_WORD(pjBase, OFFSET_wDstYOffset, (x));\
CP_EIEIO();\
}
#define CP_MIX_Y_OFFSET(ppdev, pjBase, x)\
{\
CP_WRITE_WORD(pjBase, OFFSET_wMixYOffset, (x));\
CP_EIEIO();\
}
#define CP_PEL_DEPTH(ppdev, pjBase, x)\
{\
CP_WRITE_BYTE(pjBase, OFFSET_jPixelDepthW32P, (x));\
CP_EIEIO();\
}
#define CP_BUS_SIZE(ppdev, pjBase, x)\
{\
CP_WRITE_BYTE(pjBase, OFFSET_jBusSizeW32, (x));\
CP_EIEIO();\
}
#define CP_XY_DIR(ppdev, pjBase, x)\
{\
CP_WRITE_BYTE(pjBase, OFFSET_jXYDir, (x));\
CP_EIEIO();\
}
#define CP_PAT_WRAP(ppdev, pjBase, x)\
{\
CP_WRITE_BYTE(pjBase, OFFSET_jPatWrap, (x));\
CP_EIEIO();\
}
#define CP_XFER_DISABLE(ppdev, pjBase, x)\
{\
CP_WRITE_BYTE(pjBase, OFFSET_jXferDisable, (x));\
CP_EIEIO();\
}
#define CP_SRC_WRAP(ppdev, pjBase, x)\
{\
CP_WRITE_BYTE(pjBase, OFFSET_jSrcWrap, (x));\
CP_EIEIO();\
}
#define CP_XCNT(ppdev, pjBase, x)\
{\
CP_WRITE_WORD(pjBase, OFFSET_wXCnt, (x));\
CP_EIEIO();\
}
#define CP_YCNT(ppdev, pjBase, x)\
{\
CP_WRITE_WORD(pjBase, OFFSET_wYCnt, (x));\
CP_EIEIO();\
}
#define CP_ROUTING_CTRL(ppdev, pjBase, x)\
{\
CP_WRITE_BYTE(pjBase, OFFSET_jRoutCtrl, (x));\
CP_EIEIO();\
}
#define CP_RELOAD_CTRL(ppdev, pjBase, x)\
{\
CP_WRITE_BYTE(pjBase, OFFSET_jReloadCtrlW32, (x));\
CP_EIEIO();\
}
#define CP_BK_ROP(ppdev, pjBase, x)\
{\
CP_WRITE_BYTE(pjBase, OFFSET_jBkRop, (x));\
CP_EIEIO();\
}
#define CP_FG_ROP(ppdev, pjBase, x)\
{\
CP_WRITE_BYTE(pjBase, OFFSET_jFgRop, (x));\
CP_EIEIO();\
}
#define CP_ERR_TERM(ppdev, pjBase, x)\
{\
CP_WRITE_WORD(pjBase, OFFSET_wErrTerm, (x));\
CP_EIEIO();\
}
#define CP_DELTA_MINOR(ppdev, pjBase, x)\
{\
CP_WRITE_WORD(pjBase, OFFSET_wDeltaMinor, (x));\
CP_EIEIO();\
}
#define CP_DELTA_MAJOR(ppdev, pjBase, x)\
{\
CP_WRITE_WORD(pjBase, OFFSET_wDeltaMajor, (x));\
CP_EIEIO();\
}
#define CP_X_POS_W32P(ppdev, pjBase, x)\
{\
CP_WRITE_WORD(pjBase, OFFSET_wXPosW32P, (x));\
CP_EIEIO();\
}
#define CP_Y_POS_W32P(ppdev, pjBase, x)\
{\
CP_WRITE_WORD(pjBase, OFFSET_wYPosW32P, (x));\
CP_EIEIO();\
}
#define CP_X_POS_W32(ppdev, pjBase, x)\
{\
CP_WRITE_WORD(pjBase, OFFSET_wXPosW32, (x));\
CP_EIEIO();\
}
#define CP_Y_POS_W32(ppdev, pjBase, x)\
{\
CP_WRITE_WORD(pjBase, OFFSET_wYPosW32, (x));\
CP_EIEIO();\
}
#define CP_ACL_CONFIG(ppdev, pjBase, x)\
{\
CP_WRITE_WORD(pjBase, OFFSET_jConfig, (x));\
CP_EIEIO();\
}
#define CP_ACL_POWER(ppdev, pjBase, x)\
{\
CP_WRITE_WORD(pjBase, OFFSET_jPowerCtrl, (x));\
CP_EIEIO();\
}
#define CP_ACL_STEP(ppdev, pjBase, x)\
{\
CP_WRITE_WORD(pjBase, OFFSET_jSteppingCtrl, (x));\
CP_EIEIO();\
}
//////////////////////////////////////////////////////////
// W32 video coprocessor control register offsets
#define OFFSET_ulMmuBasePtr0 0x00
#define OFFSET_ulMmuBasePtr1 0x04
#define OFFSET_ulMmuBasePtr2 0x08
#define OFFSET_jMmuCtrl 0x13
#define OFFSET_jSuspendTerminate 0x30
#define OFFSET_jOperationState 0x31
#define OFFSET_jSyncEnable 0x32
#define OFFSET_jConfig 0x32 // ET6000
#define OFFSET_jIntrMask 0x34
#define OFFSET_jIntrStatus 0x35
#define OFFSET_jAclStatus 0x36
#define OFFSET_jPowerCtrl 0x37 // ET6000
#define OFFSET_wXPosW32P 0x38 // W32p+ only
#define OFFSET_wYPosW32P 0x3A // W32p+ only
#define OFFSET_ulPatAddr 0x80
#define OFFSET_ulSrcAddr 0x84
#define OFFSET_wPatYOffset 0x88
#define OFFSET_wSrcYOffset 0x8A
#define OFFSET_wDstYOffset 0x8C
#define OFFSET_jBusSizeW32 0x8E // W32 and W32i only
#define OFFSET_jPixelDepthW32P 0x8E // W32p+ only
#define OFFSET_jXYDir 0x8F
#define OFFSET_jPatWrap 0x90
#define OFFSET_jXferDisable 0x91 // ET6000
#define OFFSET_jSrcWrap 0x92
#define OFFSET_jSecondaryEdge 0x93 // ET6000
#define OFFSET_wXPosW32 0x94 // W32 and W32i only
#define OFFSET_wYPosW32 0x96 // W32 and W32i only
#define OFFSET_wXCnt 0x98
#define OFFSET_wYCnt 0x9A
#define OFFSET_jRoutCtrl 0x9C
#define OFFSET_jMixCtrl 0x9C // ET6000
#define OFFSET_jReloadCtrlW32 0x9D // W32 and W32i only
#define OFFSET_jSteppingCtrl 0x9D // ET6000
#define OFFSET_jBkRop 0x9E
#define OFFSET_jFgRop 0x9F
#define OFFSET_ulDstAddr 0xA0
#define OFFSET_ulMixAddr 0xA4
#define OFFSET_wMixYOffset 0xA8
#define OFFSET_wErrTerm 0xAA
#define OFFSET_wDeltaMinor 0xAC
#define OFFSET_wDeltaMajor 0xAE
#define OFFSET_wSecErrTerm 0xB2 // ET6000
#define OFFSET_wSecDeltaMinor 0xB4 // ET6000
#define OFFSET_wSecDeltaMajor 0xB6 // ET6000
typedef struct {
ULONG ulVgaMemAddr;
ULONG ulPhysMemAddr;
ULONG ulPhysMemLen;
ULONG ulPhysRegsAddr;
ULONG ulPhysRegsLen;
ULONG ulPhysPortsAddr;
ULONG ulPhysPortsLen;
ULONG ulPhysExtrnMapRegAddr;
ULONG ulPhysExtrnMapRegLen;
PVOID pvMemoryBufferVirtualAddr;
PVOID pvMemoryMappedRegisterVirtualAddr;
PVOID pvPortsVirtualAddr;
PVOID pvExternalRegistersVirtualAddr;
} W32MMUINFO, *PW32MMUINFO;
//////////////////////////////////////////////////////////
// Virtual bus size
#define VIRTUAL_BUS_8_BIT 0x00
#define VIRTUAL_BUS_16_BIT 0x01
#define VIRTUAL_BUS_32_BIT 0x02
#define HW_PEL_DEPTH_8BPP 0x00
#define HW_PEL_DEPTH_16BPP 0x10
#define HW_PEL_DEPTH_24BPP 0x20
#define HW_PEL_DEPTH_32BPP 0x30
//////////////////////////////////////////////////////////
// Routing control
#define CPU_SOURCE_DATA 0x01
#define CPU_MIX_DATA 0x02
#define CPU_X_COUNT 0x04
#define CPU_Y_COUNT 0x05
//////////////////////////////////////////////////////////
// X/Y direction
#define BOTTOM_TO_TOP 0x02
#define RIGHT_TO_LEFT 0x01
#define TBLR 0x00
#define TBRL 0x01
#define BTLR 0x02
#define BTRL 0x03
//////////////////////////////////////////////////////////
// Pattern/Source wrap
#define NO_PATTERN_WRAP 0x77
#define SOLID_COLOR_PATTERN_WRAP 0x02
#define SOLID_COLOR_PATTERN_OFFSET 0x04
#define SOLID_COLOR_PATTERN_WRAP_24BPP 0x0A
#define SOLID_COLOR_PATTERN_OFFSET_24BPP 0x03
#define PATTERN_WRAP_8x8 0x33
#define PATTERN_WRAP_16x8 0x34
#define PATTERN_WRAP_32x8 0x35
#define PATTERN_WIDTH 0x08
#define PATTERN_HEIGHT 0x08
#define PATTERN_SIZE (PATTERN_WIDTH*PATTERN_HEIGHT)
#define PATTERN_OFFSET PATTERN_WIDTH
//////////////////////////////////////////////////////////
// W32 H/W pointer (sprite) data.
typedef struct {
POINTL ptlHot,
ptlLast;
SIZEL szlPointer;
FLONG fl;
} W32SPRITEDATA, *PW32SPRITEDATA;
#define POINTER_DISABLED 0X01
//////////////////////////////////////////////////////////
// Some handy clipping control structures.
typedef struct {
ULONG c;
RECTL arcl[8];
} ENUMRECTS8, *PENUMRECTS8;
////////////////////////////////////////////////////////////////////////////
// The following will spin until there is room in the ACL command queue for
// another blt command.
#define WAIT_FOR_EMPTY_ACL_QUEUE(ppdev, pjBase) \
{ \
while (CP_ACL_STAT(ppdev, pjBase) & 0x01); \
}
////////////////////////////////////////////////////////////////////////////
// The following will spin until the ACL has processed all queued commands.
#define WAIT_FOR_IDLE_ACL(ppdev, pjBase) \
{ \
while (CP_ACL_STAT(ppdev, pjBase) & 0x02); \
}
////////////////////////////////////////////////////////////////////////////
// The following will return TRUE if the FIFO is full.
#define FIFO_BUSY(ppdev, pjBase) \
(CP_ACL_STAT(ppdev, pjBase) & 0x01) \
////////////////////////////////////////////////////////////////////////////
// The following will return TRUE if the ACL is busy at the moment.
#define IS_BUSY(ppdev, pjBase) \
(CP_ACL_STAT(ppdev, pjBase) & 0x02) \
////////////////////////////////////////////////////////////////////////////
// The following will spin until the ACL starts processing a command.
#define WAIT_FOR_BUSY_ACL(ppdev, pjBase) \
{ \
while (!(CP_ACL_STAT(ppdev, pjBase) & 0x02)); \
}
////////////////////////////////////////////////////////////////////////////
// The following will spin until the vertical retrace occurs.
#define WAIT_FOR_VERTICAL_RETRACE \
{ \
while ( (INP(0x3DA) & 0x08)); \
while (!(INP(0x3DA) & 0x08)); \
} \
////////////////////////////////////////////////////////////////////////////
// The following synchronize framebuffer access with the accelerator
#define START_DIRECT_ACCESS(ppdev, pjBase)\
{\
WAIT_FOR_IDLE_ACL(ppdev, pjBase);\
}
#define END_DIRECT_ACCESS(ppdev, pjBase)\
{\
CP_EIEIO();\
}
//////////////////////////////////////////////////////////
// Made a change to check for >= W32P so that the ET6000 could be handled
// correctly by this macro. It is more efficient than checking for both
// chip types. Keep in mind that this macro may have to be modified to
// properly handle future chips.
#define SET_DEST_ADDR(ppdev, addr) \
{ \
BYTE* pjBase = ppdev->pjBase; \
\
if (ppdev->ulChipID >= W32P) \
{ \
CP_DST_ADDR(ppdev, pjBase, (addr)+ppdev->xyOffset); \
} \
else \
{ \
CP_MMU_BP2(ppdev, pjBase, ((addr)+ppdev->xyOffset)); \
} \
}
#define SET_DEST_ADDR_ABS(ppdev, addr) \
{ \
BYTE* pjBase = ppdev->pjBase; \
\
if (ppdev->ulChipID >= W32P) \
{ \
CP_DST_ADDR(ppdev, pjBase, (addr)); \
} \
else \
{ \
CP_MMU_BP2(ppdev, pjBase, (addr)); \
} \
}
#define START_ACL(ppdev) \
{ \
if (ppdev->ulChipID < W32P) \
{ \
CP_WRITE_MMU_BYTE(ppdev, 2, 0, 0); \
} \
}
#define SET_FG_COLOR(ppdev,color) \
{ \
BYTE* pjBase = ppdev->pjBase; \
LONG cBpp = ppdev->cBpp; \
\
WAIT_FOR_EMPTY_ACL_QUEUE(ppdev, pjBase); \
CP_PAT_WRAP(ppdev, pjBase, SOLID_COLOR_PATTERN_WRAP); \
CP_PAT_Y_OFFSET(ppdev, pjBase, (SOLID_COLOR_PATTERN_OFFSET - 1)); \
CP_PAT_ADDR(ppdev, pjBase, ppdev->ulSolidColorOffset); \
\
{ \
ULONG ulSolidColor; \
\
WAIT_FOR_IDLE_ACL(ppdev, pjBase); \
CP_MMU_BP0(ppdev, pjBase, ppdev->ulSolidColorOffset); \
\
ulSolidColor = color; \
\
if (cBpp == 1) \
{ \
ulSolidColor |= ulSolidColor << 8; \
} \
if (cBpp <= 2) \
{ \
ulSolidColor |= ulSolidColor << 16; \
} \
\
CP_WRITE_MMU_DWORD(ppdev, 0, 0, ulSolidColor); \
} \
}
//////////////////////////////////////////////////////////
// CRTCB/Sprite defines port definitions.
#define CRTCB_SPRITE_HORZ_POSITION_LOW 0xE0
#define CRTCB_SPRITE_HORZ_POSITION_HIGH 0xE1
#define CRTCB_WIDTH_LOW_SPRITE_HORZ_PRESET 0xE2
#define CRTCB_WIDTH_HIGH 0xE3
#define CRTCB_SPRITE_VERT_POSITION_LOW 0xE4
#define CRTCB_SPRITE_VERT_POSITION_HIGH 0xE5
#define CRTCB_HEIGHT_LOW_SPRITE_VERT_PRESET 0xE6
#define CRTCB_HEIGHT_HIGH 0xE7
#define CRTCB_SPRITE_START_ADDR_LOW 0xE8
#define CRTCB_SPRITE_START_ADDR_MEDIUM 0xE9
#define CRTCB_SPRITE_START_ADDR_HIGH 0xEA
#define CRTCB_SPRITE_ROW_OFFSET_LOW 0xEB
#define CRTCB_SPRITE_ROW_OFFSET_HIGH 0xEC
#define CRTCB_PIXEL_PANNING 0xED
#define CRTCB_COLOR_DEPTH 0xEE
#define CRTCB_SPRITE_CONTROL 0xEF
// ET6000 specific sprite equates. These are offsets into the
// PCI configuration space.
//
#define ET6K_SPRITE_HORZ_PRESET 0x82
#define ET6K_SPRITE_VERT_PRESET 0x83
#define ET6K_SPRITE_HORZ_POS_LOW 0x84
#define ET6K_SPRITE_HORZ_POS_HIGH 0x85
#define ET6K_SPRITE_VERT_POS_LOW 0x86
#define ET6K_SPRITE_VERT_POS_HIGH 0x87
#define ET6K_SPRITE_ADDR_LOW 0x0F
#define ET6K_SPRITE_ADDR_HIGH 0x0E
#define ET6K_SPRITE_ENABLE_PORT 0x46
#define ET6K_SPRITE_ENABLE_BIT 0x01
//////////////////////////////////////////////////////////
// The following enable is documented as part of the IMA port.
// It's true, the facts are stranger than fiction.
#define CRTCB_SPRITE_ENABLE_PORT 0xF7
#define CRTCB_SPRITE_ENABLE_BIT 0x80
//////////////////////////////////////////////////////////
// Some handy macros for sprite manipulation
#define SPRITE_BUFFER_SIZE 0x4400
//////////////////////////////////////////////////////////
// There are bugs in the W32 that require enabling or
// disabling the cursor during vertical retrace.
#define ENABLE_SPRITE(ppdev) \
{ \
BYTE byte; \
ppdev->W32SpriteData.fl &= ~POINTER_DISABLED; \
if (ppdev->ulChipID != ET6000) \
{ \
if (ppdev->ulChipID == W32) \
{ \
WAIT_FOR_VERTICAL_RETRACE; \
} \
OUTP(CRTCB_SPRITE_INDEX, CRTCB_SPRITE_ENABLE_PORT); \
byte = INP(CRTCB_SPRITE_DATA); \
byte |= CRTCB_SPRITE_ENABLE_BIT; \
OUTP(CRTCB_SPRITE_DATA, byte); \
}\
else \
{ \
byte = INP(ppdev->PCIConfigSpaceAddr + ET6K_SPRITE_ENABLE_PORT);\
byte |= ET6K_SPRITE_ENABLE_BIT; \
OUTP(ppdev->PCIConfigSpaceAddr + ET6K_SPRITE_ENABLE_PORT, byte);\
} \
}
#define DISABLE_SPRITE(ppdev) \
{ \
BYTE byte; \
ppdev->W32SpriteData.fl |= POINTER_DISABLED; \
if (ppdev->ulChipID != ET6000) \
{ \
if (ppdev->ulChipID == W32) \
{ \
WAIT_FOR_VERTICAL_RETRACE; \
} \
OUTP(CRTCB_SPRITE_INDEX, CRTCB_SPRITE_ENABLE_PORT); \
byte = INP(CRTCB_SPRITE_DATA); \
byte &= ~CRTCB_SPRITE_ENABLE_BIT; \
OUTP(CRTCB_SPRITE_DATA, byte); \
}\
else \
{ \
byte = INP(ppdev->PCIConfigSpaceAddr + ET6K_SPRITE_ENABLE_PORT);\
byte &= ~ET6K_SPRITE_ENABLE_BIT; \
OUTP(ppdev->PCIConfigSpaceAddr + ET6K_SPRITE_ENABLE_PORT, byte);\
} \
}
#define SET_HORZ_POSITION(val) \
{ \
OUTP(CRTCB_SPRITE_INDEX, CRTCB_SPRITE_HORZ_POSITION_LOW); \
OUTP(CRTCB_SPRITE_DATA, LOBYTE(val)); \
OUTP(CRTCB_SPRITE_INDEX, CRTCB_SPRITE_HORZ_POSITION_HIGH); \
OUTP(CRTCB_SPRITE_DATA, HIBYTE(val)); \
}
#define SET_VERT_POSITION(val) \
{ \
OUTP(CRTCB_SPRITE_INDEX, CRTCB_SPRITE_VERT_POSITION_LOW); \
OUTP(CRTCB_SPRITE_DATA, LOBYTE(val)); \
OUTP(CRTCB_SPRITE_INDEX, CRTCB_SPRITE_VERT_POSITION_HIGH); \
OUTP(CRTCB_SPRITE_DATA, HIBYTE(val)); \
}
#define SET_HORZ_PRESET(val) \
{ \
OUTP(CRTCB_SPRITE_INDEX, CRTCB_WIDTH_LOW_SPRITE_HORZ_PRESET); \
OUTP(CRTCB_SPRITE_DATA, LOBYTE(val)); \
OUTP(CRTCB_SPRITE_INDEX, CRTCB_WIDTH_HIGH); \
OUTP(CRTCB_SPRITE_DATA, 0); \
}
#define SET_VERT_PRESET(val) \
{ \
OUTP(CRTCB_SPRITE_INDEX, CRTCB_HEIGHT_LOW_SPRITE_VERT_PRESET); \
OUTP(CRTCB_SPRITE_DATA, LOBYTE(val)); \
OUTP(CRTCB_SPRITE_INDEX, CRTCB_HEIGHT_HIGH); \
OUTP(CRTCB_SPRITE_DATA, 0); \
}
#define SET_SPRITE_START_ADDR(val) \
{ \
ULONG ulAddr; \
ulAddr = val >> 2; \
OUTP(CRTCB_SPRITE_INDEX, CRTCB_SPRITE_START_ADDR_LOW); \
OUTP(CRTCB_SPRITE_DATA, LOWORD(LOBYTE(ulAddr))); \
OUTP(CRTCB_SPRITE_INDEX, CRTCB_SPRITE_START_ADDR_MEDIUM); \
OUTP(CRTCB_SPRITE_DATA, LOWORD(HIBYTE(ulAddr))); \
OUTP(CRTCB_SPRITE_INDEX, CRTCB_SPRITE_START_ADDR_HIGH); \
OUTP(CRTCB_SPRITE_DATA, LOBYTE(HIWORD(ulAddr))); \
}
#define SET_SPRITE_ROW_OFFSET \
{ \
OUTP(CRTCB_SPRITE_INDEX, CRTCB_SPRITE_ROW_OFFSET_LOW); \
OUTP(CRTCB_SPRITE_DATA, 2); \
OUTP(CRTCB_SPRITE_INDEX, CRTCB_SPRITE_ROW_OFFSET_HIGH); \
OUTP(CRTCB_SPRITE_DATA, 0); \
}
#define ET6K_SPRITE_HORZ_POSITION(ppdev, x) \
{ \
OUTP(ppdev->PCIConfigSpaceAddr + ET6K_SPRITE_HORZ_POS_LOW, (x & 0x00FF));\
OUTP(ppdev->PCIConfigSpaceAddr + ET6K_SPRITE_HORZ_POS_HIGH, (x >> 8));\
}
#define ET6K_SPRITE_VERT_POSITION(ppdev, y) \
{ \
OUTP(ppdev->PCIConfigSpaceAddr + ET6K_SPRITE_VERT_POS_LOW, (y & 0x00FF));\
OUTP(ppdev->PCIConfigSpaceAddr + ET6K_SPRITE_VERT_POS_HIGH, (y >> 8));\
}
#define ET6K_HORZ_PRESET(ppdev, x); \
{ \
OUTP(ppdev->PCIConfigSpaceAddr + ET6K_SPRITE_HORZ_PRESET, (x));\
}
#define ET6K_VERT_PRESET(ppdev, y) \
{ \
OUTP(ppdev->PCIConfigSpaceAddr + ET6K_SPRITE_VERT_PRESET, (y));\
}
//
// The ET6000 sprite start address is specified in DWORDS. We have a buffer
// of 256 dwords at the end of video memory which contains the sprite data.
// Since this aligns us to a 1K boundary, we can be sure that by simply
// discarding the lower 10 bits of the address that we won't be losing
// anything.
//
#define ET6K_SPRITE_START_ADDR(ppdev, addr) \
{ \
OUTP(CRTC_INDEX, ET6K_SPRITE_ADDR_HIGH); \
OUTP(CRTC_DATA, ((addr >> 18) & 0x0FF)); \
OUTP(CRTC_INDEX, ET6K_SPRITE_ADDR_LOW); \
OUTP(CRTC_DATA, ((addr >> 10) & 0x0FF)); \
}
#define ET6K_SPRITE_COLOR(ppdev, color) \
{ \
OUTP(ppdev->PCIConfigSpaceAddr + 0x67, 9); \
OUTP(ppdev->PCIConfigSpaceAddr + 0x69, color & 0x00FF); \
OUTP(ppdev->PCIConfigSpaceAddr + 0x69, color >> 8); \
}
////////////////////////////////////////////////////////////////////////
// Chip equates
#define STATUS_1 0x03DA
#define VSY_NOT 0x0008
#define ENABLE_KEY(ppdev) \
{ \
CP_OUT_BYTE(ppdev->pjPorts,(0x03D8),(0x00)); \
CP_OUT_BYTE(ppdev->pjPorts,(0x03BF),(0x01)); \
}
#define DISABLE_KEY(ppdev) \
{ \
CP_OUT_BYTE(ppdev->pjPorts,(0x03BF),(0x03)); \
CP_OUT_BYTE(ppdev->pjPorts,(0x03D8),(0xa0)); \
}
#define OUTPW(p, v) CP_OUT_WORD(ppdev->pjPorts,(p),(v))
#define OUTP(p, v) CP_OUT_BYTE(ppdev->pjPorts,(p),(v))
#define INPW(p) CP_IN_WORD(ppdev->pjPorts,(p))
#define INP(p) CP_IN_BYTE(ppdev->pjPorts,(p))
//////////////////////////////////////////////////////////
// Rop definitions for the hardware
#define R3_SRCCOPY 0xCC /* dest = source */
#define R3_SRCPAINT 0xEE /* dest = source OR dest */
#define R3_SRCAND 0x88 /* dest = source AND dest */
#define R3_SRCINVERT 0x66 /* dest = source XOR dest */
#define R3_SRCERASE 0x44 /* dest = source AND (NOT dest ) */
#define R3_NOTSRCCOPY 0x33 /* dest = (NOT source) */
#define R3_NOTSRCERASE 0x11 /* dest = (NOT src) AND (NOT dest) */
#define R3_MERGECOPY 0xC0 /* dest = (source AND pattern) */
#define R3_MERGEPAINT 0xBB /* dest = (NOT source) OR dest */
#define R3_PATCOPY 0xF0 /* dest = pattern */
#define R3_PATPAINT 0xFB /* dest = DPSnoo */
#define R3_PATINVERT 0x5A /* dest = pattern XOR dest */
#define R3_DSTINVERT 0x55 /* dest = (NOT dest) */
#define R3_BLACKNESS 0x00 /* dest = BLACK */
#define R3_WHITENESS 0xFF /* dest = WHITE */
#define R4_SRCCOPY 0xCCCC /* dest = source */
#define R4_SRCPAINT 0xEEEE /* dest = source OR dest */
#define R4_SRCAND 0x8888 /* dest = source AND dest */
#define R4_SRCINVERT 0x6666 /* dest = source XOR dest */
#define R4_SRCERASE 0x4444 /* dest = source AND (NOT dest ) */
#define R4_NOTSRCCOPY 0x3333 /* dest = (NOT source) */
#define R4_NOTSRCERASE 0x1111 /* dest = (NOT src) AND (NOT dest) */
#define R4_MERGECOPY 0xC0C0 /* dest = (source AND pattern) */
#define R4_MERGEPAINT 0xBBBB /* dest = (NOT source) OR dest */
#define R4_PATCOPY 0xF0F0 /* dest = pattern */
#define R4_PATPAINT 0xFBFB /* dest = DPSnoo */
#define R4_PATINVERT 0x5A5A /* dest = pattern XOR dest */
#define R4_DSTINVERT 0x5555 /* dest = (NOT dest) */
#define R4_BLACKNESS 0x0000 /* dest = BLACK */
#define R4_WHITENESS 0xFFFF /* dest = WHITE */
#define R3_NOP 0xAA /* dest = dest */
#define R4_XPAR_EXPAND 0xCCAA /* dest = source (where src is 1) */