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

1535 lines
58 KiB
C

/******************************Module*Header*******************************\
*
* *******************
* * GDI SAMPLE CODE *
* *******************
*
* Module Name: hw.h
*
* All the hardware specific driver file stuff. Parts are mirrored in
* 'hw.inc'.
*
* Copyright (c) 1992-1998 Microsoft Corporation
*
\**************************************************************************/
////////////////////////////////////////////////////////////////////////
// Chip equates:
#define STATUS_1 0x03DA
#define DISPLAY_MODE_INACTIVE 0x001
#define VBLANK_ACTIVE 0x008
#define CRTC_INDEX 0x03D4
#define CRTC_DATA 0x03D5
#define S3R8 0x038
#define S3R9 0x039
#define S3R1 0x031
#define S3R5 0x035
#define CR39 0x039
#define CR4C 0x04C
#define CR4D 0x04D
#define HGC_MODE 0x045
#define HGC_ENABLE 0x001
#define HGC_DISABLE 0x000
#define HGC_ORGX_LSB 0x047
#define HGC_ORGX_MSB 0x046
#define HGC_ORGY_LSB 0x049
#define HGC_ORGY_MSB 0x048
#define HGC_DX 0x04E
#define HGC_DY 0x04F
#define REG_UNLOCK_1 0x048
#define CPUA_BASE 0x001
#define SYSCTL_UNLOCK 0x0A0
#define SYSCTL_LOCK 0x000
#define SYS_CNFG 0x040
#define LAW_CTL 0x058
#define EX_SCTL_2 0x051
#define EX_DAC_CT 0x055
#define MISC_1 0x03A
///////////////////////////////////////////////////////////////////////
// Brooktree 485 stuff:
#define BT485_ADDR_CMD_REG0 0x03c6
#define BT485_ADDR_CMD_REG1 0x03c8
#define BT485_ADDR_CMD_REG2 0x03c9
#define BT485_ADDR_CMD_REG3 0x03c6
#define BT485_CMD_REG_3_ACCESS 0x080
#define BT485_ADDR_CUR_COLOR_WRITE 0x03c8
#define BT485_CUR_COLOR_DATA 0x03c9
#define BT485_ADDR_CUR_RAM_WRITE 0x03c8
#define BT485_CUR_RAM_ARRAY_DATA 0x03c7
#define BT485_CURSOR_COLOR_1 0x01
#define BT485_CURSOR_COLOR_2 0x02
#define BT485_CURSOR_X_LOW 0x03c8
#define BT485_CURSOR_X_HIGH 0x03c9
#define BT485_CURSOR_Y_LOW 0x03c6
#define BT485_CURSOR_Y_HIGH 0x03c7
#define BT485_CURSOR_DISABLE (~0x03)
#define BT485_CURSOR_MODE2 0x02
#define BT485_64X64_CURSOR 0x04
// Command types:
#define DRAW_LINE 0x02000
#define RECTANGLE_FILL 0x04000
#define POLYGON_SOLID 0x06000
#define FOUR_POINT_TRAPEZOID_SOLID 0x08000
#define BRESENHAM_TRAPEZOID_SOLID 0x0A000
#define BITBLT 0x0C000
#define PATTERN_FILL 0x0E000
#define POLYLINE 0x02800
#define POLYGON_PATTERN 0x06800
#define FOUR_POINT_TRAPEZOID_PATTERN 0x08800
#define BRESENHAM_TRAPEZOID_PATTERN 0x0A800
#define ROPBLT 0x0C800
#define BYTE_SWAP 0x01000
#define BUS_SIZE_NEW_32 0x00600
#define BUS_SIZE_32 0x00400
#define BUS_SIZE_16 0x00200
#define BUS_SIZE_8 0x00000
#define WAIT 0x00100
// Drawing directions (radial):
#define DRAWING_DIRECTION_0 0x0000
#define DRAWING_DIRECTION_45 0x0020
#define DRAWING_DIRECTION_90 0x0040
#define DRAWING_DIRECTION_135 0x0060
#define DRAWING_DIRECTION_180 0x0080
#define DRAWING_DIRECTION_225 0x00A0
#define DRAWING_DIRECTION_270 0x00C0
#define DRAWING_DIRECTION_315 0x00E0
// Drawing directions (x/y):
#define DRAWING_DIR_BTRLXM 0x0000
#define DRAWING_DIR_BTLRXM 0x0020
#define DRAWING_DIR_BTRLYM 0x0040
#define DRAWING_DIR_BTLRYM 0x0060
#define DRAWING_DIR_TBRLXM 0x0080
#define DRAWING_DIR_TBLRXM 0x00A0
#define DRAWING_DIR_TBRLYM 0x00C0
#define DRAWING_DIR_TBLRYM 0x00E0
// Drawing direction bits:
#define PLUS_X 0x0020
#define PLUS_Y 0x0080
#define MAJOR_Y 0x0040
// Draw:
#define DRAW 0x0010
// Direction type:
#define DIR_TYPE_RADIAL 0x0008
#define DIR_TYPE_XY 0x0000
// Last pixel:
#define LAST_PIXEL_OFF 0x0004
#define LAST_PIXEL_ON 0x0000
// Pixel mode:
#define MULTIPLE_PIXELS 0x0002
#define SINGLE_PIXEL 0x0000
// Read/write:
#define READ 0x0000
#define WRITE 0x0001
// Graphics processor status:
#define HARDWARE_BUSY 0x0200
#define READ_DATA_AVAILABLE 0x0100
#define GP_ALL_EMPTY 0x0400
// S3 chips that support MM I/O and ALL_EMPTY have 16 FIFO slots:
#define MM_ALL_EMPTY_FIFO_COUNT 16
#define IO_ALL_EMPTY_FIFO_COUNT 8
#define MULT_MISC_COLOR_COMPARE 0x0100
// Fifo status in terms of empty entries:
#define FIFO_1_EMPTY 0x080
#define FIFO_2_EMPTY 0x040
#define FIFO_3_EMPTY 0x020
#define FIFO_4_EMPTY 0x010
#define FIFO_5_EMPTY 0x008
#define FIFO_6_EMPTY 0x004
#define FIFO_7_EMPTY 0x002
#define FIFO_8_EMPTY 0x001
// These are the defines for the multifunction control register.
// The 4 MSBs define the function of the register.
#define RECT_HEIGHT 0x00000
#define CLIP_TOP 0x01000
#define CLIP_LEFT 0x02000
#define CLIP_BOTTOM 0x03000
#define CLIP_RIGHT 0x04000
#define DATA_EXTENSION 0x0A000
#define MULT_MISC_INDEX 0x0E000
#define READ_SEL_INDEX 0x0F000
#define ALL_ONES 0x00000
#define CPU_DATA 0x00080
#define DISPLAY_MEMORY 0x000C0
// Colour source:
#define BACKGROUND_COLOR 0x000
#define FOREGROUND_COLOR 0x020
#define SRC_CPU_DATA 0x040
#define SRC_DISPLAY_MEMORY 0x060
// Mix modes:
#define NOT_SCREEN 0x00
#define LOGICAL_0 0x01
#define LOGICAL_1 0x02
#define LEAVE_ALONE 0x03
#define NOT_NEW 0x04
#define SCREEN_XOR_NEW 0x05
#define NOT_SCREEN_XOR_NEW 0x06
#define OVERPAINT 0x07
#define NOT_SCREEN_OR_NOT_NEW 0x08
#define SCREEN_OR_NOT_NEW 0x09
#define NOT_SCREEN_OR_NEW 0x0A
#define SCREEN_OR_NEW 0x0B
#define SCREEN_AND_NEW 0x0C
#define NOT_SCREEN_AND_NEW 0x0D
#define SCREEN_AND_NOT_NEW 0x0E
#define NOT_SCREEN_AND_NOT_NEW 0x0F
////////////////////////////////////////////////////////////////////
// S3 port control
////////////////////////////////////////////////////////////////////
// Accelerator port addresses:
#define CUR_Y 0x082E8
#define CUR_X 0x086E8
#define DEST_Y 0x08AE8
#define DEST_X 0x08EE8
#define AXSTP 0x08AE8
#define DIASTP 0x08EE8
#define ERR_TERM 0x092E8
#define MAJ_AXIS_PCNT 0x096E8
#define CMD 0x09AE8
#define SHORT_STROKE 0x09EE8
#define BKGD_COLOR 0x0A2E8
#define FRGD_COLOR 0x0A6E8
#define WRT_MASK 0x0AAE8
#define RD_MASK 0x0AEE8
#define COLOR_CMP 0x0B2E8
#define BKGD_MIX 0x0B6E8
#define FRGD_MIX 0x0BAE8
#define MULTIFUNC_CNTL 0x0BEE8
#define MIN_AXIS_PCNT 0x0BEE8
#define SCISSORS 0x0BEE8
#define PIX_CNTL 0x0BEE8
#define PIX_TRANS 0x0E2E8
// Packed addresses, for Trio64 or newer:
#define ALT_CURXY 0x08100
#define ALT_CURXY2 0x08104
#define ALT_STEP 0x08108
#define ALT_STEP2 0x0810C
#define ALT_ERR 0x08110
#define ALT_CMD 0x08118
#define ALT_MIX 0x08134
#define ALT_PCNT 0x08148
#define ALT_PAT 0x08168
#define SCISSORS_T 0x08138
#define SCISSORS_L 0x0813A
#define SCISSORS_B 0x0813C
#define SCISSORS_R 0x0813E
#define MULT_MISC_READ_SEL 0x08144
////////////////////////////////////////////////////////////////////
// S3 streams processor
////////////////////////////////////////////////////////////////////
// Stream processor register definitions
#define P_CONTROL 0x8180 // Primary Stream Control register
#define CKEY_LOW 0x8184 // Color/Chroma Key Control
#define S_CONTROL 0x8190 // Secondary Stream Control
#define CKEY_HI 0x8194 // Chroma Key Upper Bound
#define S_HK1K2 0x8198 // Secondary Stream Stretch/Filter const
#define BLEND_CONTROL 0x81a0 // Blend Control
#define P_0 0x81c0 // Primary Stream Frame Buffer Address 0
#define P_1 0x81c4 // Primary Stream Frame Buffer Address 1
#define P_STRIDE 0x81c8 // Primary Stream Stride
#define LPB_DB 0x81cc // Double buffer and LPB Support
#define S_0 0x81d0 // Secondary Stream Frame Buffer Addr 0
#define S_1 0x81d4 // Secondary Stream Frame Buffer Addr 1
#define S_STRIDE 0x81d8 // Secondary Stream Stride
#define OPAQUE_CONTROL 0x81dc // Opaque Overlay Control
#define S_VK1 0x81e0 // K1 Vertical Scale Factor
#define S_VK2 0x81e4 // K2 Vertical Scale Factor
#define S_VDDA 0x81e8 // DDA Vertical Accumulator Init Value
#define FIFO_CONTROL 0x81ec // Stream FIFO and RAS Controls
#define P_XY 0x81f0 // Primary Stream Window Start Coord
#define P_WH 0x81f4 // Primary Stream Window Size
#define S_XY 0x81f8 // Secondary Stream Window Start Coord
#define S_WH 0x81fc // Secondary Stream Window Size
#define P_Format_Shift 24
#define P_Format_Mask (7L << P_Format_Shift)
#define P_RGB8 (0L << P_Format_Shift)
#define P_RGB15 (3L << P_Format_Shift)
#define P_RGB16 (5L << P_Format_Shift)
#define P_RGB24 (6L << P_Format_Shift)
#define P_RGB32 (7L << P_Format_Shift)
#define P_Filter_Shift 28
#define P_Filter_Mask (7L << P_Filter_Shift)
#define P_1x (0L << P_Filter_Shift)
#define P_2x (1L << P_Filter_Shift)
#define P_2xBiLinear (2L << P_Filter_Shift)
#define BVCr_Shift 0
#define BVCr_Mask (255L << BVCr_Shift)
#define GUCb_Shift 8
#define GUCb_Mask (255L << GUCb_Shift)
#define RY_Shift 16
#define RY_Mask (255L << RY_Shift)
#define Compare_Shift 24
#define Compare_Mask (255L << Compare_Shift)
#define CompareBits7 (0L << Compare_Shift)
#define CompareBits6t7 (1L << Compare_Shift)
#define CompareBits5t7 (2L << Compare_Shift)
#define CompareBits4t7 (3L << Compare_Shift)
#define CompareBits3t7 (4L << Compare_Shift)
#define CompareBits2t7 (5L << Compare_Shift)
#define CompareBits1t7 (6L << Compare_Shift)
#define CompareBits0t7 (7L << Compare_Shift)
#define KeyFrom_Shift 28
#define KeyFrom_Mask (1L << KeyFrom_Shift)
#define KeyFromStream (0L << KeyFrom_Shift)
#define KeyFromCompare (1L << KeyFrom_Shift)
#define HDDA_Shift 0
#define HDDA_Mask (((1L << 12)-1) << HDDA_Shift)
#define S_Format_Shift 24
#define S_Format_Mask (7L << S_Format_Shift)
#define S_YCrCb422 (1L << S_Format_Shift)
#define S_YUV422 (2L << S_Format_Shift)
#define S_RGB15 (3L << S_Format_Shift)
#define S_YUV211 (4L << S_Format_Shift)
#define S_RGB16 (5L << S_Format_Shift)
#define S_RGB24 (6L << S_Format_Shift)
#define S_RGB32 (7L << S_Format_Shift)
#define S_Filter_Shift 28
#define S_Filter_Mask (7L << S_Filter_Shift)
#define S_1x (0L << S_Filter_Shift)
#define S_Upto2x (1L << S_Filter_Shift)
#define S_2xTo4x (2L << S_Filter_Shift)
#define S_Beyond4x (3L << S_Filter_Shift)
#define HighVCr_Shift 0
#define HighVCr_Mask (255L << HighVCr_Shift)
#define HighUCb_Shift 8
#define HighUCb_Mask (255L << HighUCb_Shift)
#define HighY_Shift 16
#define HighY_Mask (255L << HighY_Shift)
#define HK1_Shift 0
#define HK1_Mask (((1L << 11) - 1) << HK1_Shift)
#define HK2_Shift 16
#define HK2_Mask (((1L << 11) - 1) << HK2_Shift)
#define VK1_Shift 0
#define VK1_Mask (((1L << 11) - 1) << VK1_Shift)
#define VK2_Shift 0
#define VK2_Mask (((1L << 11) - 1) << VK2_Shift)
#define VDDA_Shift 0
#define VDDA_Mask (((1L << 12) - 1) << VDDA_Shift)
#define Ks_Shift 2
#define Ks_Mask (7L << Ks_Shift)
#define Kp_Shift 10
#define Kp_Mask (7L << Kp_Shift)
#define Compose_Shift 24
#define Compose_Mask (7L << Compose_Shift)
#define SOnP (0L << Compose_Shift)
#define POnS (1L << Compose_Shift)
#define Dissolve (2L << Compose_Shift)
#define Fade (3L << Compose_Shift)
#define KeyOnP (5L << Compose_Shift)
#define KeyOnS (6L << Compose_Shift)
#define FifoAlloc_Shift 0
#define FifoAlloc_Mask (31L << StrFifoAlloc_Shift)
#define FifoAlloc24_0 (0L << StrFifoAlloc_Shift)
#define FifoAlloc16_8 (8L << StrFifoAlloc_Shift)
#define FifoAlloc12_12 (12L << StrFifoAlloc_Shift)
#define FifoAlloc8_16 (16L << StrFifoAlloc_Shift)
#define FifoAlloc0_24 (24L << StrFifoAlloc_Shift)
#define S_FifoThresh_Shift 5
#define S_FifoThresh_Mask (31L << S_FifoThresh_Shift)
#define P_FifoThresh_Shift 10
#define P_FifoThresh_Mask (31L << P_FifoThresh_Shift)
#define RASLowTime_Shift 15
#define RASLowTime_Mask (1L << RASLowTime_Shift)
#define RASLowTimeFromCR68 (0L << RASLowTime_Shift)
#define RASLowTime2_5 (1L << RASLowTime_Shift)
#define RASPreCharge_Shift 16
#define RASPreCharge_Mask (1L << RASPreCharge_Shift)
#define RASPreChargeFromCR68 (0L << RASPreCharge_Shift)
#define RASPreCharge1_5 (1L << RASPreCharge_Shift)
#define RASInactive_Shift 17
#define RASInactive_Mask (1L << RASInactive_Shift)
#define RASInactiveLow (0L << RASInactive_Shift)
#define RASInactiveHigh (1L << RASInactive_Shift)
#define MemoryCycle_Shift 18
#define MemoryCycle_Mask (1L << MemoryCycle_Shift)
#define MemoryCycle2 (0L << MemoryCycle_Shift)
#define MemoryCycle1 (1L << MemoryCycle_Shift)
#define H_Shift 0
#define H_Mask (0x07ffL << H_Shift)
#define W_Shift 16
#define W_Mask (0x07ffL << W_Shift)
#define Y_Shift 0
#define Y_Mask (0x07ffL << Y_Shift)
#define X_Shift 16
#define X_Mask (0x07ffL << X_Shift)
#define P_Select_Shift 0
#define P_Select_Mask (1L << P_Select_Shift)
#define P_Select0 (0L << P_Select_Shift)
#define P_Select1 (1L << P_Select_Shift)
#define S_Select_Shift 1
#define S_Select_Mask (3L << S_Select_Shift)
#define S_Select0 (0L << S_Select_Shift)
#define S_Select1 (1L << S_Select_Shift)
#define S_Select00Or11 (2L << S_Select_Shift)
#define S_Select01Or10 (3L << S_Select_Shift)
#define L_Select_Shift 4
#define L_Select_Mask (1L << L_Select_Shift)
#define L_Select0 (0L << L_Select_Shift)
#define L_Select1 (1L << L_Select_Shift)
#define L_SelWait_Shift 5
#define L_SelWait_Mask (1L << L_SelWait_Shift)
#define L_SelWaitNo (0L << L_SelWait_Shift)
#define L_SelWaitYes (1L << L_SelWait_Shift)
#define L_SelAutoToggle_Shift 6
#define L_SelAutoToggle_Mask (1L << L_SelAutoToggle_Shift)
#define L_SelAutoToggleNo (0L << L_SelAutoToggle_Shift)
#define L_SelAutoToggleYes (1L << L_SelAutoToggle_Shift)
#define L_FramesToDrop_Shift 8
#define L_FramesToDrop_Mask (3L << L_FramesToDrop_Shift)
#define OpqStart_Shift 3
#define OpqStart_Mask (((1L << 10) - 1) << OpqStart_Shift)
#define OpqEnd_Shift 19
#define OpqEnd_Mask (((1L << 10) - 1) << OpqEnd_Shift)
#define OpqTopSel_Shift 30
#define OpqTopSel_Mask (1L << OpqTopSel_Shift)
#define OpqTopSelS_ (0L << OpqTopSel_Shift)
#define OpqTopSelP_ (1L << OpqTopSel_Shift)
#define OpqCtrl_Shift 31
#define OpqCtrl_Mask (1L << OpqCtrl_Shift)
#define OpqDisabled (0L << OpqCtrl_Shift)
#define OpqEnabled (1L << OpqCtrl_Shift)
// The following defines are for VL and PCI system configuration
#define K2V_SRD_LPB_MASK 0x03
#define K2V_SRD_LPB 0x00
#define K2V_SRD_FC K2V_SRD_LPB_MASK
#define K2V_SRD_COMP 0x02
#define K2V_CR5C_SRC_MASK 0x03
#define K2V_CR5C_SRC_DIGITIZER 0x02
#define K2V_CR5C_SRC_MPEG 0x01
#define K2V_SR1C_MASK 0x03
#define K2V_SR1C_VL 0x01
#define K2V_SR1C_PCI 0x02
// Useful macros
#define HDDA(w0,w1) (((2*(w0-1)-(w1-1)) << HDDA_Shift) & HDDA_Mask )
#define VDDA(h1) (((1-h1) << VDDA_Shift) & VDDA_Mask )
#define HK1(w0) (((w0 - 1) << HK1_Shift) & HK1_Mask )
#define HK2(w0,w1) (((w0 - w1) << HK2_Shift) & HK2_Mask )
#define HK1K2(w0,w1) (HK1(w0) | HK2(w0, w1))
#define VK1(h0) (((h0 - 1) << VK1_Shift) & VK1_Mask )
#define VK2(h0,h1) (((h0 - h1) << VK2_Shift) & VK2_Mask )
#define XY(x,y) ((((x+1)<<X_Shift)&X_Mask) | (((y+1)<<Y_Shift)&Y_Mask))
#define WH(w,h) ((((w-1)<<W_Shift)&W_Mask) | (((h)<<H_Shift)&H_Mask))
#define HWCODEC 0
#define SWCODEC 1
#define DIGITIZER 2
#define MAX_DEVICE 3
#define DSTWIN_SIZES 5
////////////////////////////////////////////////////////////////////
// S3 pixel formatter
////////////////////////////////////////////////////////////////////
// Equates for Pixel Formatter (Video Engine) 868/968
#define INPUT_RGB8 0x00000000
#define INPUT_RGB15 0x00600000
#define INPUT_RGB16 0x00700000
#define INPUT_RGB32 0x00300000
#define INPUT_YUV422 0x00480000
#define INPUT_YCrCb422 0x00400000
#define INPUT_RAW 0x00500000
#define OUTPUT_RGB8 0x00000000
#define OUTPUT_RGB15 0x00060000
#define OUTPUT_RGB16 0x00070000
#define OUTPUT_RGB32 0x00030000
#define OUTPUT_YUY2 0x000C0000
#define OUTPUT_RAW 0x00050000
#define CSCENABLE 0x40000000
#define STRETCH 0x00000000
#define SHRINK 0x80000000
#define SCREEN 0x00000000
#define HOST 0x40000000
#define FILTERENABLE 0x80000000
#define BILINEAR 0x00000000
#define LINEAR02420 0x00004000
#define LINEAR12221 0x00008000
#define PF_BUSY 0x80000000
#define PF_NOP 0x00018080
#define PF_CONTROL 0x00018088
#define PF_DDA 0x0001808C
#define PF_STEP 0x00018090
#define PF_CROP 0x00018094
#define PF_SRCADDR 0x00018098
#define PF_DSTADDR 0x0001809C
//////////////////////////////////////////////////////////////////////
// RISC considerations
//
// 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. We used to have to do this separately for
// the Alpha because unlike the PowerPC it did not guarantee that
// output to the same address will be exectued in order. However,
// with the move to kernel-mode, on Alpha we are now calling HAL
// routines for every port I/O which ensure that this is not a
// problem.
#if defined(_ALPHA_)
// On Alpha, since we must do all non-frame-buffer I/O through HAL
// routines, which automatically do memory-barriers, we don't have
// to do memory barriers ourselves (and should not, because it's a
// performance hit).
#define CP_EIEIO()
#define CP_MEMORY_BARRIER()
#else
// 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
////////////////////////////////////////////////////////////////////
// Macros for accessing accelerator registers:
/////////////////////////////////////////////////////////////////////////
// 32bpp Support
//
// The S3 has only 16 bit register operations. When running at 32bpp,
// depth-related registers are written twice in succession in order to
// convey 32 bit values.
#define OUT_PSEUDO_DWORD(p, x) \
{ \
WRITE_PORT_USHORT((p), (USHORT)(x)); \
CP_MEMORY_BARRIER(); \
WRITE_PORT_USHORT((p), (USHORT)((x) >> 16)); \
}
#define WRITE_PSEUDO_DWORD(p, x) \
{ \
WRITE_REGISTER_USHORT((p), (USHORT) (x)); \
CP_MEMORY_BARRIER(); \
WRITE_REGISTER_USHORT((p), (USHORT) ((x) >> 16)); \
}
// DEPTH32(ppdev) returns TRUE if running at 32bpp, meaning that DEPTH32
// macros must be used, and returns FALSE if running at 8 or 16bpp,
// meaning that DEPTH macros must be used:
#define DEPTH32(ppdev) (ppdev->iBitmapFormat == BMF_32BPP)
#define IO_GP_BUSY(ppdev) (IO_GP_STAT(ppdev) & HARDWARE_BUSY)
#define IO_FIFO_BUSY(ppdev, level) \
(IO_GP_STAT(ppdev) & ((FIFO_1_EMPTY << 1) >> (level)))
#if DBG
/////////////////////////////////////////////////////////////////////////
// Checked Build
//
// We hook some of the accelerator macros on checked (debug) builds
// for sanity checking.
VOID vOutFifoW(VOID*, ULONG);
VOID vOutDepth(PDEV*, VOID*, ULONG);
VOID vOutFifoPseudoD(PDEV*, VOID*, ULONG);
VOID vWriteFifoW(VOID*, ULONG);
VOID vWriteFifoD(VOID*, ULONG);
VOID vWriteFifoPseudoD(PDEV*, VOID*, ULONG);
VOID vIoFifoWait(PDEV*, LONG);
VOID vIoGpWait(PDEV*);
VOID vIoAllEmpty(PDEV*);
VOID vCheckDataReady(PDEV*);
VOID vCheckDataComplete(PDEV*);
UCHAR jInp(BYTE*, ULONG);
USHORT wInpW(BYTE*, ULONG);
VOID vOutp(BYTE*, ULONG, ULONG);
VOID vOutpW(BYTE*, ULONG, ULONG);
VOID vAcquireCrtc(PDEV*);
VOID vReleaseCrtc(PDEV*);
#define OUT_FIFO_W(p, v) vOutFifoW((p), (ULONG) (v))
#define OUT_FIFO_PSEUDO_D(ppdev, p, v) vOutFifoPseudoD((ppdev), (p), (ULONG) (v))
#define WRITE_FIFO_W(p, v) vWriteFifoW((p), (ULONG) (v))
#define WRITE_FIFO_D(p, v) vWriteFifoD((p), (ULONG) (v))
#define IO_FIFO_WAIT(ppdev, level) vIoFifoWait((ppdev), (level))
#define IO_GP_WAIT(ppdev) vIoGpWait(ppdev)
#define IO_ALL_EMPTY(ppdev) vIoAllEmpty(ppdev)
#define CHECK_DATA_READY(ppdev) vCheckDataReady(ppdev)
#define CHECK_DATA_COMPLETE(ppdev) vCheckDataComplete(ppdev)
#define OUTPW(pjIoBase, p, v) vOutpW((pjIoBase), (p), (ULONG) (v))
#define OUTP(pjIoBase, p, v) vOutp((pjIoBase), (p), (ULONG) (v))
#define INPW(pjIoBase, p) wInpW((pjIoBase), (p))
#define INP(pjIoBase, p) jInp((pjIoBase), (p))
// The CRTC register critical section must be acquired before
// touching the CRTC register (because of async pointers):
#define ACQUIRE_CRTC_CRITICAL_SECTION(ppdev) vAcquireCrtc(ppdev)
#define RELEASE_CRTC_CRITICAL_SECTION(ppdev) vReleaseCrtc(ppdev)
#else
/////////////////////////////////////////////////////////////////////////
// Free Build
//
// For a free (non-debug build), we make everything in-line.
// Safe port access macros -- these macros automatically do memory
// ----------------------- barriers, so you don't have to worry
// about them:
#if defined(_X86_)
// x86 doesn't need 'pjIoBase' added in, so save some code space:
#define OUTPW(pjIoBase, p, v) WRITE_PORT_USHORT((p), (v))
#define OUTP(pjIoBase, p, v) WRITE_PORT_UCHAR((p), (v))
#define INPW(pjIoBase, p) ((USHORT)READ_PORT_USHORT((p)))
#define INP(pjIoBase, p) ((UCHAR)READ_PORT_UCHAR((p)))
#else
// Non-x86 platforms have the I/O range starting at 'pjIoBase':
#define OUTPW(pjIoBase, p, v) \
{ \
CP_EIEIO(); \
WRITE_PORT_USHORT((pjIoBase) + (p), (USHORT)(v)); \
CP_EIEIO(); \
}
#define OUTP(pjIoBase, p, v) \
{ \
CP_EIEIO(); \
WRITE_PORT_UCHAR((pjIoBase) + (p), (UCHAR)(v)); \
CP_EIEIO(); \
}
__inline USHORT INPW(BYTE* pjIoBase, ULONG p)
{
CP_EIEIO();
return(READ_PORT_USHORT(pjIoBase + p));
}
__inline UCHAR INP(BYTE* pjIoBase, ULONG p)
{
CP_EIEIO();
return(READ_PORT_UCHAR(pjIoBase + p));
}
#endif
// Not-so-safe port access macros -- for performance, the following macros
// ------------------------------ do not automatically do memory
// barriers, so you must do them yourself:
#define OUT_FIFO_W(p, v) WRITE_PORT_USHORT((p), (USHORT) (v))
#define OUT_FIFO_PSEUDO_D(ppdev, p, x) OUT_PSEUDO_DWORD((p), (ULONG) (x))
#define WRITE_FIFO_W(p, v) \
{ \
VPBYTE foo = (p); \
WRITE_REGISTER_USHORT(foo, (USHORT) (v)); \
}
#define WRITE_FIFO_D(p, v) \
{ \
VPBYTE foo = (p); \
WRITE_REGISTER_ULONG((p), (ULONG) (v)); \
}
#define IO_FIFO_WAIT(ppdev, level) \
do {;} while (IO_FIFO_BUSY(ppdev, (level)))
#define IO_GP_WAIT(ppdev) \
do {;} while (IO_GP_BUSY(ppdev))
#define IO_ALL_EMPTY(ppdev) \
do {;} while (!(IO_GP_STAT(ppdev) & GP_ALL_EMPTY))
#define CHECK_DATA_READY(ppdev) // Expands to nothing
#define CHECK_DATA_COMPLETE(ppdev) // Expands to nothing
// The CRTC register critical section must be acquired before
// touching the CRTC register (because of async pointers):
#define ACQUIRE_CRTC_CRITICAL_SECTION(ppdev) \
EngAcquireSemaphore(ppdev->csCrtc);
// 80x/805i/928 and 928PCI chips have a bug where if I/O registers
// are left unlocked after accessing them, writes to memory with
// similar addresses can cause writes to I/O registers. The problem
// registers are 0x40, 0x58, 0x59 and 0x5c. We will simply always
// leave the index set to an innocuous register (namely, the text
// mode cursor start scan line):
#define RELEASE_CRTC_CRITICAL_SECTION(ppdev) \
{ \
OUTP(ppdev->pjIoBase, CRTC_INDEX, 0xa); \
EngReleaseSemaphore(ppdev->csCrtc); \
}
#endif
////////////////////////////////////////////////////////////////////
// Port access using I/O
// The following are ABSOLUTE positioning macros. They do NOT take
// the surface's offset into account (for off-screen device-format
// bitmaps):
#define IO_ABS_CUR_Y(ppdev, y) \
OUT_FIFO_W(ppdev->ioCur_y, (y))
#define IO_ABS_CUR_X(ppdev, x) \
OUT_FIFO_W(ppdev->ioCur_x, (x))
#define IO_ABS_DEST_Y(ppdev, y) \
OUT_FIFO_W(ppdev->ioDesty_axstp, (y))
#define IO_ABS_DEST_X(ppdev, x) \
OUT_FIFO_W(ppdev->ioDestx_diastp, (x))
#define IO_ABS_SCISSORS_T(ppdev, y) \
{ \
CP_MEMORY_BARRIER(); \
OUT_FIFO_W(ppdev->ioMulti_function, (y) | CLIP_TOP); \
}
#define IO_ABS_SCISSORS_L(ppdev, x) \
{ \
CP_MEMORY_BARRIER(); \
OUT_FIFO_W(ppdev->ioMulti_function, (x) | CLIP_LEFT); \
}
#define IO_ABS_SCISSORS_B(ppdev, y) \
{ \
CP_MEMORY_BARRIER(); \
OUT_FIFO_W(ppdev->ioMulti_function, (y) | CLIP_BOTTOM); \
}
#define IO_ABS_SCISSORS_R(ppdev, x) \
{ \
CP_MEMORY_BARRIER(); \
OUT_FIFO_W(ppdev->ioMulti_function, (x) | CLIP_RIGHT); \
}
// The following are RELATIVE positioning macros. They DO take
// the surface's offset into account:
#define IO_CUR_Y(ppdev, y) \
IO_ABS_CUR_Y(ppdev, (y) + ppdev->yOffset)
#define IO_CUR_X(ppdev, x) \
IO_ABS_CUR_X(ppdev, (x) + ppdev->xOffset)
#define IO_DEST_Y(ppdev, y) \
IO_ABS_DEST_Y(ppdev, (y) + ppdev->yOffset)
#define IO_DEST_X(ppdev, x) \
IO_ABS_DEST_X(ppdev, (x) + ppdev->xOffset)
#define IO_SCISSORS_T(ppdev, y) \
IO_ABS_SCISSORS_T(ppdev, (y) + ppdev->yOffset)
#define IO_SCISSORS_L(ppdev, x) \
IO_ABS_SCISSORS_L(ppdev, (x) + ppdev->xOffset)
#define IO_SCISSORS_B(ppdev, y) \
IO_ABS_SCISSORS_B(ppdev, (y) + ppdev->yOffset)
#define IO_SCISSORS_R(ppdev, x) \
IO_ABS_SCISSORS_R(ppdev, (x) + ppdev->xOffset)
// The following are the rest of the S3 registers we use:
#define IO_AXSTP(ppdev, x) \
OUT_FIFO_W(ppdev->ioDesty_axstp, (x))
#define IO_DIASTP(ppdev, x) \
OUT_FIFO_W(ppdev->ioDestx_diastp, (x))
#define IO_ERR_TERM(ppdev, x) \
OUT_FIFO_W(ppdev->ioErr_term, (x))
#define IO_MAJ_AXIS_PCNT(ppdev, x) \
OUT_FIFO_W(ppdev->ioMaj_axis_pcnt, (x))
__inline USHORT IO_GP_STAT(PDEV* ppdev)
{
CP_EIEIO();
return(READ_PORT_USHORT(ppdev->ioGp_stat_cmd));
}
// Note that we have to put memory barriers before and after the
// command output. The first memory barrier ensures that all the
// settings registers have been set before the command is executed,
// and the second ensures that no subsequent changes to the settings
// registers will mess up the current command:
#define IO_CMD(ppdev, x) \
{ \
CP_EIEIO(); \
OUT_FIFO_W(ppdev->ioGp_stat_cmd, (x)); \
CP_EIEIO(); \
}
#define IO_SHORT_STROKE(ppdev, x) \
{ \
CP_EIEIO(); \
OUT_FIFO_W(ppdev->ioShort_stroke, (x)); \
CP_EIEIO(); \
}
#define IO_BKGD_MIX(ppdev, x) \
OUT_FIFO_W(ppdev->ioBkgd_mix, (x))
#define IO_FRGD_MIX(ppdev, x) \
OUT_FIFO_W(ppdev->ioFrgd_mix, (x))
#define IO_MIN_AXIS_PCNT(ppdev, x) \
{ \
CP_MEMORY_BARRIER(); \
OUT_FIFO_W(ppdev->ioMulti_function, (x) | RECT_HEIGHT); \
}
#define IO_MULTIFUNC_CNTL(ppdev, x) \
{ \
CP_MEMORY_BARRIER(); \
OUT_FIFO_W(ppdev->ioMulti_function, (x) | MULT_MISC_INDEX); \
}
#define IO_PIX_CNTL(ppdev, x) \
{ \
CP_MEMORY_BARRIER(); \
OUT_FIFO_W(ppdev->ioMulti_function, (x) | DATA_EXTENSION); \
}
#define IO_READ_SEL(ppdev, x) \
{ \
CP_MEMORY_BARRIER(); \
OUT_FIFO_W(ppdev->ioMulti_function, (x) | READ_SEL_INDEX); \
}
#define IO_MULT_MISC(ppdev, x) \
{ \
CP_MEMORY_BARRIER(); \
OUT_FIFO_W(ppdev->ioMulti_function, (x) | MULT_MISC_INDEX); \
}
#define IO_RD_REG_DT(ppdev, x) \
{ \
CP_EIEIO(); \
x = READ_PORT_USHORT(ppdev->ioMulti_function); \
CP_EIEIO(); \
}
#define IO_PIX_TRANS(ppdev, x) \
{ \
CP_MEMORY_BARRIER(); \
/* Can't use OUT_FIFO_W: */ \
WRITE_PORT_USHORT(ppdev->ioPix_trans, (x)); \
}
// Macros for outputing colour-depth dependent values at 8bpp and 16bpp:
#define IO_BKGD_COLOR(ppdev, x) \
OUT_FIFO_W(ppdev->ioBkgd_color, (x))
#define IO_FRGD_COLOR(ppdev, x) \
OUT_FIFO_W(ppdev->ioFrgd_color, (x))
#define IO_WRT_MASK(ppdev, x) \
OUT_FIFO_W(ppdev->ioWrt_mask, (x))
#define IO_RD_MASK(ppdev, x) \
OUT_FIFO_W(ppdev->ioRd_mask, (x))
#define IO_COLOR_CMP(ppdev, x) \
OUT_FIFO_W(ppdev->ioColor_cmp, (x))
// Macros for outputing colour-depth dependent values at 32bpp:
#define IO_BKGD_COLOR32(ppdev, x) \
OUT_FIFO_PSEUDO_D(ppdev, ppdev->ioBkgd_color, (x))
#define IO_FRGD_COLOR32(ppdev, x) \
OUT_FIFO_PSEUDO_D(ppdev, ppdev->ioFrgd_color, (x))
#define IO_WRT_MASK32(ppdev, x) \
OUT_FIFO_PSEUDO_D(ppdev, ppdev->ioWrt_mask, (x))
#define IO_RD_MASK32(ppdev, x) \
OUT_FIFO_PSEUDO_D(ppdev, ppdev->ioRd_mask, (x))
#define IO_COLOR_CMP32(ppdev, x) \
OUT_FIFO_PSEUDO_D(ppdev, ppdev->ioColor_cmp, (x))
////////////////////////////////////////////////////////////////////
// Port access using memory-mapped I/O:
// The following are ABSOLUTE positioning macros. They do NOT take
// the surface's offset into account:
#define MM_ABS_CUR_Y(ppdev, pjMmBase, y) \
WRITE_FIFO_W((BYTE*) (pjMmBase) + CUR_Y, (y))
#define MM_ABS_CUR_X(ppdev, pjMmBase, x) \
WRITE_FIFO_W((BYTE*) (pjMmBase) + CUR_X, (x))
#define MM_ABS_DEST_Y(ppdev, pjMmBase, y) \
WRITE_FIFO_W((BYTE*) (pjMmBase) + DEST_Y, (y))
#define MM_ABS_DEST_X(ppdev, pjMmBase, x) \
WRITE_FIFO_W((BYTE*) (pjMmBase) + DEST_X, (x))
#define MM_ABS_SCISSORS_T(ppdev, pjMmBase, y) \
{ \
CP_MEMORY_BARRIER(); \
WRITE_FIFO_W((BYTE*) (pjMmBase) + SCISSORS, (y) | CLIP_TOP); \
}
#define MM_ABS_SCISSORS_L(ppdev, pjMmBase, x) \
{ \
CP_MEMORY_BARRIER(); \
WRITE_FIFO_W((BYTE*) (pjMmBase) + SCISSORS, (x) | CLIP_LEFT); \
}
#define MM_ABS_SCISSORS_B(ppdev, pjMmBase, y) \
{ \
CP_MEMORY_BARRIER(); \
WRITE_FIFO_W((BYTE*) (pjMmBase) + SCISSORS, (y) | CLIP_BOTTOM); \
}
#define MM_ABS_SCISSORS_R(ppdev, pjMmBase, x) \
{ \
CP_MEMORY_BARRIER(); \
WRITE_FIFO_W((BYTE*) (pjMmBase) + SCISSORS, (x) | CLIP_RIGHT); \
}
// The following are RELATIVE positioning macros. They DO take
// the surface's offset into account:
#define MM_CUR_Y(ppdev, pjMmBase, y) \
MM_ABS_CUR_Y(ppdev, pjMmBase, (y) + ppdev->yOffset)
#define MM_CUR_X(ppdev, pjMmBase, x) \
MM_ABS_CUR_X(ppdev, pjMmBase, (x) + ppdev->xOffset)
#define MM_DEST_Y(ppdev, pjMmBase, y) \
MM_ABS_DEST_Y(ppdev, pjMmBase, (y) + ppdev->yOffset)
#define MM_DEST_X(ppdev, pjMmBase, x) \
MM_ABS_DEST_X(ppdev, pjMmBase, (x) + ppdev->xOffset)
#define MM_SCISSORS_T(ppdev, pjMmBase, y) \
MM_ABS_SCISSORS_T(ppdev, pjMmBase, (y) + ppdev->yOffset)
#define MM_SCISSORS_L(ppdev, pjMmBase, x) \
MM_ABS_SCISSORS_L(ppdev, pjMmBase, (x) + ppdev->xOffset)
#define MM_SCISSORS_B(ppdev, pjMmBase, y) \
MM_ABS_SCISSORS_B(ppdev, pjMmBase, (y) + ppdev->yOffset)
#define MM_SCISSORS_R(ppdev, pjMmBase, x) \
MM_ABS_SCISSORS_R(ppdev, pjMmBase, (x) + ppdev->xOffset)
// The following are the rest of the S3 registers we use:
#define MM_AXSTP(ppdev, pjMmBase, x) \
WRITE_FIFO_W((BYTE*) (pjMmBase) + AXSTP, (x))
#define MM_DIASTP(ppdev, pjMmBase, x) \
WRITE_FIFO_W((BYTE*) (pjMmBase) + DIASTP, (x))
#define MM_ERR_TERM(ppdev, pjMmBase, x) \
WRITE_FIFO_W((BYTE*) (pjMmBase) + ERR_TERM, (x))
#define MM_MAJ_AXIS_PCNT(ppdev, pjMmBase, x) \
WRITE_FIFO_W((BYTE*) (pjMmBase) + MAJ_AXIS_PCNT, (x))
#define MM_CMD(ppdev, pjMmBase, x) \
{ \
CP_EIEIO(); \
WRITE_FIFO_W((BYTE*) (pjMmBase) + CMD, (x)); \
CP_EIEIO(); \
}
#define MM_SHORT_STROKE(ppdev, pjMmBase, x) \
{ \
CP_EIEIO(); \
WRITE_FIFO_W((BYTE*) (pjMmBase) + SHORT_STROKE, (x)); \
CP_EIEIO(); \
}
#define MM_BKGD_MIX(ppdev, pjMmBase, x) \
WRITE_FIFO_W((BYTE*) (pjMmBase) + BKGD_MIX, (x))
#define MM_FRGD_MIX(ppdev, pjMmBase, x) \
WRITE_FIFO_W((BYTE*) (pjMmBase) + FRGD_MIX, (x))
#define MM_MIN_AXIS_PCNT(ppdev, pjMmBase, x) \
{ \
CP_MEMORY_BARRIER(); \
WRITE_FIFO_W((BYTE*) (pjMmBase) + MIN_AXIS_PCNT, (x) | RECT_HEIGHT); \
}
#define MM_MULTIFUNC_CNTL(ppdev, pjMmBase, x) \
{ \
CP_MEMORY_BARRIER(); \
WRITE_FIFO_W((BYTE*) (pjMmBase) + MULTIFUNC_CNTL, (x) | MULT_MISC_INDEX); \
}
#define MM_PIX_CNTL(ppdev, pjMmBase, x) \
{ \
CP_MEMORY_BARRIER(); \
WRITE_FIFO_W((BYTE*) (pjMmBase) + PIX_CNTL, (x) | DATA_EXTENSION); \
}
#define MM_PIX_TRANS(ppdev, pjMmBase, x) \
{ \
CP_MEMORY_BARRIER(); \
/* Can't use WRITE_FIFO_W: */ \
WRITE_REGISTER_USHORT((BYTE*) (pjMmBase) + PIX_TRANS, (x)); \
}
// Macros for outputing colour-depth dependent values at any colour depth:
#define MM_BKGD_COLOR(ppdev, pjMmBase, x) \
WRITE_FIFO_D((BYTE*) (pjMmBase) + BKGD_COLOR, (x))
#define MM_FRGD_COLOR(ppdev, pjMmBase, x) \
WRITE_FIFO_D((BYTE*) (pjMmBase) + FRGD_COLOR, (x))
#define MM_WRT_MASK(ppdev, pjMmBase, x) \
WRITE_FIFO_D((BYTE*) (pjMmBase) + WRT_MASK, (x))
#define MM_RD_MASK(ppdev, pjMmBase, x) \
WRITE_FIFO_D((BYTE*) (pjMmBase) + RD_MASK, (x))
#define MM_COLOR_CMP(ppdev, pjMmBase, x) \
WRITE_FIFO_D((BYTE*) (pjMmBase) + COLOR_CMP, (x))
#define MM_FIFO_BUSY(ppdev, pjMmBase, level) \
(((level) <= 8) ? IO_GP_STAT(ppdev) & (0x0080 >> ((level) - 1)) \
: IO_GP_STAT(ppdev) & (0x8000 >> ((level) - 9)))
#if DBG
VOID vMmFifoWait(PDEV*, BYTE*, LONG);
#define MM_FIFO_WAIT(ppdev, pjMmBase, level) \
vMmFifoWait((ppdev), (pjMmBase), (level))
#else
#define MM_FIFO_WAIT(ppdev, pjMmBase, level) \
do {;} while (MM_FIFO_BUSY(ppdev, pjMmBase, (level)))
#endif
//////////////////////////////////////////////////////////////////////
// Note: The PACKXY_FAST macro is unsafe with negative coordinates
#define PACKXY(x, y) (((x) << 16) | ((y) & 0xffff))
#define PACKXY_FAST(x, y) (((x) << 16) | (y))
#define NW_ABS_CURXY(ppdev, pjMmBase, x, y) \
WRITE_FIFO_D((BYTE*) (pjMmBase) + ALT_CURXY, PACKXY((x), (y)))
#define NW_ABS_CURXY_FAST(ppdev, pjMmBase, x, y) \
WRITE_FIFO_D((BYTE*) (pjMmBase) + ALT_CURXY, PACKXY_FAST((x), (y)))
#define NW_ABS_CURXY2(ppdev, pjMmBase, x, y) \
WRITE_FIFO_D((BYTE*) (pjMmBase) + ALT_CURXY2, PACKXY((x), (y)))
#define NW_ABS_STEPXY(ppdev, pjMmBase, x, y) \
WRITE_FIFO_D((BYTE*) (pjMmBase) + ALT_STEP, PACKXY((x), (y)))
#define NW_ALT_STEP(ppdev, pjMmBase, diastp, axstp) \
WRITE_FIFO_D((BYTE*) (pjMmBase) + ALT_STEP, PACKXY((diastp), (axstp)))
#define NW_ABS_DESTXY_FAST(ppdev, pjMmBase, x, y) \
WRITE_FIFO_D((BYTE*) (pjMmBase) + ALT_STEP, PACKXY((x), (y)))
#define NW_ALT_PCNT(ppdev, pjMmBase, cx, cy) \
WRITE_FIFO_D((BYTE*) (pjMmBase) + ALT_PCNT, PACKXY_FAST((cx), (cy)))
#define NW_ALT_PCNT_PACKED(ppdev, pjMmBase, cxcy) \
WRITE_FIFO_D((BYTE*) (pjMmBase) + ALT_PCNT, cxcy)
#define NW_ALT_CMD(ppdev, pjMmBase, x) \
WRITE_FIFO_D((BYTE*) (pjMmBase) + ALT_CMD, (x))
#define NW_ALT_MIX(ppdev, pjMmBase, fore, back) \
WRITE_FIFO_D((BYTE*) (pjMmBase) + ALT_MIX, PACKXY((fore), (back)))
#define NW_ALT_ERR(ppdev, pjMmBase, err2, err) \
WRITE_FIFO_D((BYTE*) (pjMmBase) + ALT_ERR, PACKXY((err2), (err)))
#define NW_FRGD_COLOR(ppdev, pjMmBase, x) \
WRITE_FIFO_D((BYTE*) (pjMmBase) + FRGD_COLOR, (x))
#define NW_BKGD_COLOR(ppdev, pjMmBase, x) \
WRITE_FIFO_D((BYTE*) (pjMmBase) + BKGD_COLOR, (x))
#define NW_ABS_SCISSORS_LT(ppdev, pjMmBase, x, y) \
WRITE_FIFO_D((BYTE*) (pjMmBase) + SCISSORS_T, PACKXY((x), (y)))
#define NW_ABS_SCISSORS_RB(ppdev, pjMmBase, x, y) \
WRITE_FIFO_D((BYTE*) (pjMmBase) + SCISSORS_B, PACKXY((x), (y)))
#define NW_MULT_MISC_READ_SEL(ppdev, pjMmBase, mult, read) \
WRITE_FIFO_D((BYTE*) (pjMmBase) + MULT_MISC_READ_SEL, PACKXY((read), (mult)))
__inline BOOL NW_FIFO_BUSY(PDEV* ppdev, BYTE* pjMmBase, ULONG level)
{
CP_EIEIO();
return(((level) <= 8) ? (READ_REGISTER_USHORT((BYTE*) (pjMmBase) + CMD)
& (0x0080 >> ((level) - 1)))
: (READ_REGISTER_USHORT((BYTE*) (pjMmBase) + CMD)
& (0x8000 >> ((level) - 9))));
}
__inline BOOL NW_GP_BUSY(PDEV* ppdev, BYTE* pjMmBase)
{
CP_EIEIO();
return(READ_REGISTER_USHORT((BYTE*) (pjMmBase) + CMD) & HARDWARE_BUSY);
}
#define NW_PIX_CNTL MM_PIX_CNTL
#define NW_COLOR_CMP MM_COLOR_CMP
#if DBG
VOID vNwGpWait(PDEV*, BYTE*);
VOID vNwFifoWait(PDEV*, BYTE*, LONG);
VOID vDbgFakeWait(PDEV*, BYTE*, LONG);
#define NW_GP_WAIT(ppdev, pjMmBase) \
vNwGpWait((ppdev), (pjMmBase))
#define NW_FIFO_WAIT(ppdev, pjMmBase, level) \
vNwFifoWait((ppdev), (pjMmBase), (level))
// DBG_FAKE_WAIT is only relevant on checked builds, and updates the
// current debug-only fifo-empty count to allow us to do FIFO writes
// without waiting for FIFO empty, when we (hopefully) know what we're
// doing:
#define DBG_FAKE_WAIT(ppdev, pjMmBase, level) \
vDbgFakeWait((ppdev), (pjMmBase), (level))
#else
#define NW_GP_WAIT(ppdev, pjMmBase) \
do {;} while (NW_GP_BUSY(ppdev, pjMmBase))
#define NW_FIFO_WAIT(ppdev, pjMmBase, level) \
do {;} while (NW_FIFO_BUSY(ppdev, pjMmBase, (level)))
#define DBG_FAKE_WAIT(ppdev, pjMmBase, level)
#endif
/////////////////////////////////////////////////////////////////////////////
// MM_TRANSFER routines
#define MM(pjMmBase, pjMmAlpha) (pjMmBase)
#if defined(_X86_)
#define VPBYTE BYTE volatile * volatile
#else
#define VPBYTE BYTE *
#endif
//////////////////////////
// MM_TRANSFER_BYTE - Byte transfers using memory-mapped I/O transfers.
//
// NOTE: The first versions of the 868/968 have a bug where they can't do
// byte-sized memory-mapped transfers. Consequently, we always do
// word transfers.
#define MM_TRANSFER_BYTE(ppdev, pjMmBase, p, c) \
{ \
ULONG mcw = (c) >> 1; \
BYTE* mpjSrc = (BYTE*) (p); \
USHORT** mapwMmXfer = ppdev->apwMmXfer; \
VPBYTE foo = pjMmBase; \
\
ASSERTDD((c) > 0, "Can't have a zero transfer count"); \
CP_MEMORY_BARRIER(); \
while (mcw-- != 0) \
{ \
WRITE_REGISTER_USHORT(MM(foo, mapwMmXfer[mcw & XFER_MASK]), \
*((USHORT UNALIGNED *) mpjSrc)); \
mpjSrc += 2; \
} \
if ((c) & 1) \
{ \
WRITE_REGISTER_USHORT(MM(foo, mapwMmXfer[XFER_MASK]), \
(USHORT) (*mpjSrc)); \
} \
}
//////////////////////////
// MM_TRANSFER_BYTE_THIN - Glyph transfers using memory-mapped I/O transfers.
//
// NOTE: The first versions of the 868/968 have a bug where they can't do
// byte-sized memory-mapped transfers. Consequently, we always do
// word transfers.
#define MM_TRANSFER_BYTE_THIN(ppdev, pjMmBase, p, c) \
{ \
ULONG mcj = (c); \
BYTE* mpjSrc = (BYTE*) (p); \
USHORT** mapwMmXfer = ppdev->apwMmXfer; \
VPBYTE foo = pjMmBase; \
\
ASSERTDD((c) > 0, "Can't have a zero transfer count"); \
CP_MEMORY_BARRIER(); \
do { \
WRITE_REGISTER_USHORT(MM(foo, mapwMmXfer[mcj & XFER_MASK]), \
(USHORT) (*mpjSrc)); \
mpjSrc++; \
} while (--mcj); \
}
//////////////////////////
// MM_TRANSFER_WORD_ALIGNED - Word transfers using memory-mapped transfers.
//
// Source must be dword aligned!
#define MM_TRANSFER_WORD_ALIGNED(ppdev, pjMmBase, p, c) \
{ \
ULONG mcd = (c) >> 1; \
ULONG* mpdSrc = (ULONG*) (p); \
ULONG** mapdMmXfer = ppdev->apdMmXfer; \
VPBYTE foo = pjMmBase; \
ASSERTDD((((ULONG_PTR) p) & 3) == 0, "Transfer not dword aligned"); \
ASSERTDD((c) > 0, "Can't have a zero transfer count"); \
CP_MEMORY_BARRIER(); \
while (mcd-- != 0) \
{ \
WRITE_REGISTER_ULONG(MM(foo, mapdMmXfer[mcd & XFER_MASK]), *mpdSrc++); \
} \
if ((c) & 1) \
{ \
WRITE_REGISTER_USHORT(ppdev->apwMmXfer[XFER_MASK], \
*((USHORT*) mpdSrc)); \
} \
}
//////////////////////////
// MM_TRANSFER_WORD - Word transfers using memory-mapped transfers.
//
// Source does not have to be dword aligned.
#define MM_TRANSFER_WORD(ppdev, pjMmBase, p, c) \
{ \
ULONG UNALIGNED * mpdSrc = (ULONG*) (p); \
ULONG mcd = (c) >> 1; \
VPBYTE foo = pjMmBase; \
ULONG** mapdMmXfer = ppdev->apdMmXfer; \
ASSERTDD((c) > 0, "Can't have a zero transfer count"); \
CP_MEMORY_BARRIER(); \
while (mcd-- != 0) \
{ \
WRITE_REGISTER_ULONG(MM(foo, mapdMmXfer[mcd & XFER_MASK]), \
*mpdSrc++); \
} \
if ((c) & 1) \
{ \
WRITE_REGISTER_USHORT(ppdev->apwMmXfer[XFER_MASK], \
*((USHORT UNALIGNED *) mpdSrc)); \
} \
}
//////////////////////////
// MM_TRANSFER_DWORD_ALIGNED - Dword transfers using memory-mapped transfers.
//
// Source must be dword aligned!
#define MM_TRANSFER_DWORD_ALIGNED(ppdev, pjMmBase, p, c) \
{ \
ULONG mcd = (c); \
ULONG* mpdSrc = (ULONG*) (p); \
VPBYTE foo = pjMmBase; \
ULONG** mapdMmXfer = ppdev->apdMmXfer; \
ASSERTDD((((ULONG_PTR) p) & 3) == 0, "Transfer not dword aligned"); \
ASSERTDD(ppdev->flCaps & CAPS_MM_TRANSFER, "Must be MM I/O"); \
ASSERTDD((c) > 0, "Can't have a zero transfer count"); \
\
CP_MEMORY_BARRIER(); \
do { \
WRITE_REGISTER_ULONG(MM(foo, mapdMmXfer[mcd & XFER_MASK]), \
*mpdSrc++); \
} while (--mcd); \
}
//////////////////////////
// MM_TRANSFER_DWORD - Dword transfers using memory-mapped transfers.
//
// Source does not have to be dword aligned.
#define MM_TRANSFER_DWORD(ppdev, pjMmBase, p, c) \
{ \
ULONG mcd = (c); \
ULONG UNALIGNED* mpdSrc = (ULONG*) (p); \
VPBYTE foo = pjMmBase; \
ULONG** mapdMmXfer = ppdev->apdMmXfer; \
ASSERTDD((c) > 0, "Can't have a zero transfer count"); \
\
CP_MEMORY_BARRIER(); \
do { \
WRITE_REGISTER_ULONG(MM(foo, mapdMmXfer[mcd & XFER_MASK]), \
*mpdSrc++); \
} while (--mcd); \
}
//////////////////////////
// MM_TRANSFER_WORD_ODD - Word transfers for glyphs of odd byte length
// and more than one byte wide.
//
// Source must be word aligned.
#define MM_TRANSFER_WORD_ODD(ppdev, pjMmBase, p, cjWidth, cy) \
{ \
BYTE* mpjSrc = (BYTE*) (p); \
USHORT** mapwMmXfer = ppdev->apwMmXfer; \
LONG mi = 0; \
LONG mcy = (cy); \
LONG mcw = ((cjWidth) >> 1); \
LONG mc; \
VPBYTE foo = pjMmBase; \
\
ASSERTDD(((cjWidth) > 0) && ((cy) > 0), "Can't have a zero transfer count");\
ASSERTDD((cjWidth) & 1, "Must be odd byte width"); \
ASSERTDD((cjWidth) > 2, "Must be more than 2 bytes wide"); \
\
CP_MEMORY_BARRIER(); \
do { \
mc = mcw; \
do { \
WRITE_REGISTER_USHORT(MM(foo, mapwMmXfer[(mi++) & XFER_MASK]), \
*((USHORT UNALIGNED *) mpjSrc)); \
mpjSrc += 2; \
} while (--mc != 0); \
\
WRITE_REGISTER_USHORT(MM(foo, mapwMmXfer[(mi++) & XFER_MASK]), \
(USHORT) (*(mpjSrc))); \
mpjSrc++; \
} while (--mcy != 0); \
}
//////////////////////////
// IO_TRANSFER_WORD_ALIGNED - Word transfers using normal I/O.
#define IO_TRANSFER_WORD_ALIGNED(ppdev, p, c) \
{ \
ULONG mcw = (c); \
USHORT* mpwSrc = (USHORT*) (p); \
ASSERTDD((((ULONG_PTR) p) & 3) == 0, "Transfer not dword aligned"); \
ASSERTDD((c) > 0, "Can't have a zero transfer count"); \
do { \
IO_PIX_TRANS(ppdev, *mpwSrc++); \
} while (--mcw); \
}
//////////////////////////
// IO_TRANSFER_WORD - Word transfers using normal I/O.
//
// Source does not have to be dword aligned.
#define IO_TRANSFER_WORD(ppdev, p, c) \
{ \
ULONG mcw = (c); \
USHORT UNALIGNED * mpwSrc = (USHORT*) (p); \
ASSERTDD((c) > 0, "Can't have a zero transfer count"); \
do { \
IO_PIX_TRANS(ppdev, *mpwSrc++); \
} while (--mcw); \
}
/////////////////////////////////////////////////////////////////////////////
// DirectDraw stuff
#define IS_RGB15_R(flRed) \
(flRed == 0x7c00)
#define IS_RGB15(this) \
(((this)->dwRBitMask == 0x7c00) && \
((this)->dwGBitMask == 0x03e0) && \
((this)->dwBBitMask == 0x001f))
#define IS_RGB16(this) \
(((this)->dwRBitMask == 0xf800) && \
((this)->dwGBitMask == 0x07e0) && \
((this)->dwBBitMask == 0x001f))
#define IS_RGB24(this) \
(((this)->dwRBitMask == 0x00ff0000) && \
((this)->dwGBitMask == 0x0000ff00) && \
((this)->dwBBitMask == 0x000000ff))
#define IS_RGB32(this) \
(((this)->dwRBitMask == 0x00ff0000) && \
((this)->dwGBitMask == 0x0000ff00) && \
((this)->dwBBitMask == 0x000000ff))
#define RGB15to32(c) \
(((c & 0x7c00) << 9) | \
((c & 0x03e0) << 6) | \
((c & 0x001f) << 3))
#define RGB16to32(c) \
(((c & 0xf800) << 8) | \
((c & 0x07e0) << 5) | \
((c & 0x001f) << 3))
#define VBLANK_IS_ACTIVE(pjIoBase) \
(INP(pjIoBase, STATUS_1) & VBLANK_ACTIVE)
#define DISPLAY_IS_ACTIVE(pjIoBase) \
(!(INP(pjIoBase, STATUS_1) & DISPLAY_MODE_INACTIVE))
#define WAIT_FOR_VBLANK(pjIoBase) \
do {} while (!(VBLANK_IS_ACTIVE(pjIoBase)));
extern VOID vStreamsDelay(); // Work around 765 timing bug
#define WRITE_STREAM_D(pjMmBase, Register, x) \
{ \
WRITE_REGISTER_ULONG((BYTE*) (pjMmBase) + Register, (x)); \
CP_EIEIO(); \
vStreamsDelay(); \
}
#define WRITE_FORMATTER_D(pjMmBase, Register, x) \
{ \
if (Register == PF_NOP) \
CP_EIEIO(); \
WRITE_FIFO_D((BYTE*) (pjMmBase) + Register, (x)); \
}
#define NW_FORMATTER_WAIT(ppdev, pjMmBase) \
{ \
CP_EIEIO(); \
do {} while (READ_REGISTER_ULONG((BYTE*) (pjMmBase) + PF_DSTADDR) & PF_BUSY); \
}
/////////////////////////////////////////////////////////////////////////////
// Private IOCTL for communicating S3 streams parameters. These definitions
// must match those in the miniport!
#define IOCTL_VIDEO_S3_QUERY_STREAMS_PARAMETERS \
CTL_CODE(FILE_DEVICE_VIDEO, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
typedef struct _VIDEO_QUERY_STREAMS_MODE {
ULONG ScreenWidth;
ULONG BitsPerPel;
ULONG RefreshRate;
} VIDEO_QUERY_STREAMS_MODE;
typedef struct _VIDEO_QUERY_STREAMS_PARAMETERS {
ULONG MinOverlayStretch;
ULONG FifoValue;
} VIDEO_QUERY_STREAMS_PARAMETERS;