|
|
/******************************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) */
|