980 lines
34 KiB
C
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) */
|