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