/*++ Copyright (c) 1990-1995 Microsoft Corporation Module Name: s3.h Abstract: This module contains the definitions for the S3 miniport driver. Environment: Kernel mode Revision History: --*/ #include "dderror.h" #include "devioctl.h" #include "miniport.h" #include "ntddvdeo.h" #include "video.h" // // We don't use the CRT 'min' function because that would drag in // unwanted CRT baggage. // #define MIN(a, b) ((a) < (b) ? (a) : (b)) // // Size of the ROM we map in // #define MAX_ROM_SCAN 512 // // Number of access ranges used by an S3. // #define NUM_S3_ACCESS_RANGES 36 #define NUM_S3_ACCESS_RANGES_USED 22 #define NUM_S3_PCI_ACCESS_RANGES 2 #define S3_EXTENDED_RANGE_START 4 // // Index of Frame buffer in access range array // #define A000_FRAME_BUF 1 #define LINEAR_FRAME_BUF 36 // // Constants defining 'New Memory-mapped I/O' window: // #define NEW_MMIO_WINDOW_SIZE 0x4000000 // Total window size -- 64 MB #define NEW_MMIO_IO_OFFSET 0x1000000 // Offset to start of little endian // control registers -- 16 MB #define NEW_MMIO_IO_LENGTH 0x0020000 // Length of control registers // -- 128 KB //////////////////////////////////////////////////////////////////////// // Capabilities flags // // These are private flags passed to the S3 display driver. They're // put in the high word of the 'AttributeFlags' field of the // 'VIDEO_MODE_INFORMATION' structure (found in 'ntddvdeo.h') passed // to the display driver via an 'VIDEO_QUERY_AVAIL_MODES' or // 'VIDEO_QUERY_CURRENT_MODE' IOCTL. // // NOTE: These definitions must match those in the S3 display driver's // 'driver.h'! typedef enum { CAPS_STREAMS_CAPABLE = 0x00000040, // Has overlay streams processor CAPS_FORCE_DWORD_REREADS= 0x00000080, // Dword reads occasionally return // an incorrect result, so always // retry the reads CAPS_NEW_MMIO = 0x00000100, // Can use 'new memory-mapped // I/O' scheme introduced with // 868/968 CAPS_POLYGON = 0x00000200, // Can do polygons in hardware CAPS_24BPP = 0x00000400, // Has 24bpp capability CAPS_BAD_24BPP = 0x00000800, // Has 868/968 early rev chip bugs // when at 24bpp CAPS_PACKED_EXPANDS = 0x00001000, // Can do 'new 32-bit transfers' CAPS_PIXEL_FORMATTER = 0x00002000, // Can do colour space conversions, // and one-dimensional hardware // stretches CAPS_BAD_DWORD_READS = 0x00004000, // Dword or word reads from the // frame buffer will occasionally // return an incorrect result, // so always do byte reads CAPS_NO_DIRECT_ACCESS = 0x00008000, // Frame buffer can't be directly // accessed by GDI or DCI -- // because dword or word reads // would crash system, or Alpha // is running in sparse space CAPS_HW_PATTERNS = 0x00010000, // 8x8 hardware pattern support CAPS_MM_TRANSFER = 0x00020000, // Memory-mapped image transfers CAPS_MM_IO = 0x00040000, // Memory-mapped I/O CAPS_MM_32BIT_TRANSFER = 0x00080000, // Can do 32bit bus size transfers CAPS_16_ENTRY_FIFO = 0x00100000, // At least 16 entries in FIFO CAPS_SW_POINTER = 0x00200000, // No hardware pointer; use software // simulation CAPS_BT485_POINTER = 0x00400000, // Use Brooktree 485 pointer CAPS_TI025_POINTER = 0x00800000, // Use TI TVP3020/3025 pointer CAPS_SCALE_POINTER = 0x01000000, // Set if the S3 hardware pointer // x position has to be scaled by // two CAPS_SPARSE_SPACE = 0x02000000, // Frame buffer is mapped in sparse // space on the Alpha CAPS_NEW_BANK_CONTROL = 0x04000000, // Set if 801/805/928 style banking CAPS_NEWER_BANK_CONTROL = 0x08000000, // Set if 864/964 style banking CAPS_RE_REALIZE_PATTERN = 0x10000000, // Set if we have to work around the // 864/964 hardware pattern bug CAPS_SLOW_MONO_EXPANDS = 0x20000000, // Set if we have to slow down // monochrome expansions CAPS_MM_GLYPH_EXPAND = 0x40000000, // Use memory-mapped I/O glyph- // expand method of drawing text CAPS_WAIT_ON_PALETTE = 0x80000000, // Wait for vertical retrace before // setting the palette registers } CAPS; #define CAPS_DAC_POINTER (CAPS_BT485_POINTER | CAPS_TI025_POINTER) // // Supported board definitions. // typedef enum _S3_BOARDS { S3_GENERIC = 0, S3_ORCHID, S3_NUMBER_NINE, S3_DELL, S3_METHEUS, S3_DIAMOND, S3_HP, S3_IBM_PS2, MAX_S3_BOARD } S3_BOARDS; // // Chip type definitions -- for families of chips // // if you change this typedef it will change the size of the second element // (named Fixed) of the union in the typedef for S3_VIDEO_FREQUENCIES and // PS3_VIDEO_FREQUENCIES, look at that typedef for a caution about the effect // this will have on autoinitialization // typedef enum _S3_CHIPSETS { S3_911 = 0, // 911 and 924 boards S3_801, // 801 and 805 boards S3_928, // 928 boards S3_864, // 864, 964, 732, 764, and 765 boards S3_866, // 866, 868, and 968 boards MAX_S3_CHIPSET } S3_CHIPSETS; // // Chip subtypes -- for more differentiation within families // // Note that ordering is important. // typedef enum _S3_SUBTYPE { SUBTYPE_911 = 0, // 911 and 924 SUBTYPE_80x, // 801 and 805 SUBTYPE_928, // 928 and 928PCI SUBTYPE_805i, // 805i SUBTYPE_864, // 864 SUBTYPE_964, // 964 SUBTYPE_764, // Trio64 SUBTYPE_732, // Trio32 SUBTYPE_866, // 866 SUBTYPE_868, // 868 SUBTYPE_765, // Trio64 V+ SUBTYPE_968, // 968 MAX_S3_SUBTYPE } S3_SUBTYPE; // // DAC type definitions // typedef enum _S3_DACS { UNKNOWN_DAC = 0, // unknown DAC type BT_485, // Brooktree's Bt 485 TI_3020, // TI's 3020 or 3025 S3_SDAC, // S3's SDAC MAX_S3_DACS } S3_DACS; // // Hardware pointer capabilities flags // typedef enum _POINTER_CAPABILITY { POINTER_BUILT_IN = 0x01, // A pointer is built in to the hardware POINTER_WORKS_ONLY_AT_8BPP = 0x02, // If set, the hardware pointer works // only at 8bpp, and only for modes // 1024x768 or less POINTER_NEEDS_SCALING = 0x04, // x-coordinate must be scaled by 2 at // 32bpp } POINTER_CAPABILITY; // // Characteristics of each mode // typedef struct _S3_VIDEO_MODES { USHORT Int10ModeNumberContiguous; USHORT Int10ModeNumberNoncontiguous; ULONG ScreenStrideContiguous; VIDEO_MODE_INFORMATION ModeInformation; } S3_VIDEO_MODES, *PS3_VIDEO_MODES; // // Mode-set specific information. // typedef struct _S3_VIDEO_FREQUENCIES { ULONG BitsPerPel; ULONG ScreenWidth; ULONG ScreenFrequency; union { // // The compiler uses the first element of a union to determine where // it places the values given when the union is autoinitialized. // // If size of the Fixed element of this union is changed by adding // chips to the enum typedef for S3_CHIPSET then the Int10 element // needs to be padded with dummy fields to make autoinitialization // of the Fixed element work correctly. // // If values are removed from the S3_CHIPSET typedef then either the // Int10 element should shrunk by removing pads or the Fixed element // should be padded. // struct { ULONG_PTR FrequencyPrimarySet; ULONG_PTR FrequencyPrimaryMask; ULONG_PTR FrequencySecondarySet; ULONG_PTR FrequencySecondaryMask; ULONG_PTR SizePad0; // make struct sizes match } Int10; struct { union { // // This is done so that Clock overlays FrequencyPrimarySet // and CRTCTable[1] overlays FrequencyPrimaryMask, whether // we are compiling for 32 or 64 bits. // ULONG Clock; ULONG_PTR Pad; }; PUSHORT CRTCTable[MAX_S3_CHIPSET]; } Fixed; }; PS3_VIDEO_MODES ModeEntry; ULONG ModeIndex; UCHAR ModeValid; } S3_VIDEO_FREQUENCIES, *PS3_VIDEO_FREQUENCIES; // // Streams parameter information. // typedef struct _K2TABLE { USHORT ScreenWidth; UCHAR BitsPerPel; UCHAR RefreshRate; UCHAR MemoryFlags; UCHAR MemorySpeed; ULONG Value; } K2TABLE; #define MEM_1EDO 0x0 #define MEM_2EDO 0x2 #define MEM_FAST 0x3 #define MEM_TYPE_MASK 0x3 #define MEM_1MB 0x0 #define MEM_2MB 0x10 #define MEM_SIZE_MASK 0x10 // // Private IOCTL for communicating S3 streams parameters. These definitions // must match those in the display driver! // #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; // // Register definitions used with VideoPortRead/Write functions // // It's a good idea to write your miniport to allow for easy register // re-mapping, but I wouldn't recommend that anyone use this particular // implementation because it's pretty dumb. // #define DAC_PIXEL_MASK_REG (PVOID)((PUCHAR)((PHW_DEVICE_EXTENSION)HwDeviceExtension)->MappedAddress[2] + (0x03C6 - 0x03C0)) #define BT485_ADDR_CMD_REG0 (PVOID)((PUCHAR)((PHW_DEVICE_EXTENSION)HwDeviceExtension)->MappedAddress[2] + (0x03C6 - 0x03C0)) #define TI025_INDEX_REG (PVOID)((PUCHAR)((PHW_DEVICE_EXTENSION)HwDeviceExtension)->MappedAddress[2] + (0x03C6 - 0x03C0)) #define TI025_DATA_REG (PVOID)((PUCHAR)((PHW_DEVICE_EXTENSION)HwDeviceExtension)->MappedAddress[2] + (0x03C7 - 0x03C0)) #define CRT_DATA_REG (PVOID)((PUCHAR)((PHW_DEVICE_EXTENSION)HwDeviceExtension)->MappedAddress[3] + (0x03D5 - 0x03D4)) #define SYSTEM_CONTROL_REG (PVOID)((PUCHAR)((PHW_DEVICE_EXTENSION)HwDeviceExtension)->MappedAddress[3] + (0x03DA - 0x03D4)) #define CRT_ADDRESS_REG ((PHW_DEVICE_EXTENSION)HwDeviceExtension)->MappedAddress[3] #define GP_STAT ((PHW_DEVICE_EXTENSION)HwDeviceExtension)->MappedAddress[12] // 0x9AE8 #define DAC_ADDRESS_WRITE_PORT (PVOID)((PUCHAR)HwDeviceExtension->MappedAddress[2] + (0x03C8 - 0x03C0)) #define DAC_DATA_REG_PORT (PVOID)((PUCHAR)HwDeviceExtension->MappedAddress[2] + (0x03C9 - 0x03C0)) #define MISC_OUTPUT_REG_WRITE (PVOID)((PUCHAR)HwDeviceExtension->MappedAddress[2] + (0x03C2 - 0x03C0)) #define MISC_OUTPUT_REG_READ (PVOID)((PUCHAR)HwDeviceExtension->MappedAddress[2] + (0x03CC - 0x03C0)) #define SEQ_ADDRESS_REG (PVOID)((PUCHAR)HwDeviceExtension->MappedAddress[2] + (0x03C4 - 0x03C0)) #define SEQ_DATA_REG (PVOID)((PUCHAR)HwDeviceExtension->MappedAddress[2] + (0x03C5 - 0x03C0)) #define IOCTL_PRIVATE_GET_FUNCTIONAL_UNIT \ CTL_CODE(FILE_DEVICE_VIDEO, 0x180, METHOD_BUFFERED, FILE_ANY_ACCESS) typedef struct _FUNCTIONAL_UNIT_INFO { ULONG FunctionalUnitID; ULONG Reserved; } FUNCTIONAL_UNIT_INFO, *PFUNCTIONAL_UNIT_INFO; // // Define device extension structure. This is device dependent/private // information. // typedef struct _HW_DEVICE_EXTENSION { PHYSICAL_ADDRESS PhysicalFrameAddress; ULONG PhysicalFrameIoSpace; ULONG FrameLength; PHYSICAL_ADDRESS PhysicalRegisterAddress; ULONG RegisterLength; UCHAR RegisterSpace; PHYSICAL_ADDRESS PhysicalMmIoAddress; ULONG MmIoLength; ULONG ChildCount; UCHAR MmIoSpace; UCHAR FrequencySecondaryIndex; UCHAR BiosPresent; UCHAR CR5C; BOOLEAN bNeedReset; PUCHAR MmIoBase; PS3_VIDEO_MODES ActiveModeEntry; PS3_VIDEO_FREQUENCIES ActiveFrequencyEntry; PS3_VIDEO_FREQUENCIES Int10FrequencyTable; PS3_VIDEO_FREQUENCIES FixedFrequencyTable; USHORT PCIDeviceID; ULONG FunctionalUnitID; ULONG BoardID; S3_CHIPSETS ChipID; S3_SUBTYPE SubTypeID; ULONG DacID; ULONG Capabilities; ULONG NumAvailableModes; ULONG NumTotalModes; ULONG AdapterMemorySize; PVOID MappedAddress[NUM_S3_ACCESS_RANGES]; } HW_DEVICE_EXTENSION, *PHW_DEVICE_EXTENSION; // // SDAC M and N paramaters // typedef struct { UCHAR m; UCHAR n; } SDAC_PLL_PARMS; #define SDAC_TABLE_SIZE 16 // // Highest valid DAC color register index. // #define VIDEO_MAX_COLOR_REGISTER 0xFF // // Data // // // Global Physical Access Ranges. // Logical access ranges must be stored in the HwDeviceExtension so different // addresses can be used for different boards. // extern VIDEO_ACCESS_RANGE S3AccessRanges[]; // // Memory Size array // extern ULONG gacjMemorySize[]; // // nnlck.c clock generator table // extern long vclk_range[]; // // Hard-coded modeset tables // extern USHORT s3_set_vga_mode[]; extern USHORT s3_set_vga_mode_no_bios[]; extern USHORT S3_911_Enhanced_Mode[]; extern USHORT S3_801_Enhanced_Mode[]; extern USHORT S3_928_Enhanced_Mode[]; extern USHORT S3_928_1280_Enhanced_Mode[]; // // Externs for 864 PPC board // extern USHORT S3_864_Enhanced_Mode[]; extern USHORT S3_864_1280_Enhanced_Mode[]; extern SDAC_PLL_PARMS SdacTable[]; extern UCHAR MParameterTable[]; // // Hard-coded modeset frequency tables // extern S3_VIDEO_FREQUENCIES GenericFixedFrequencyTable[]; extern S3_VIDEO_FREQUENCIES OrchidFixedFrequencyTable[]; extern S3_VIDEO_FREQUENCIES NumberNine928NewFixedFrequencyTable[]; // // Int 10 frequency tables // extern S3_VIDEO_FREQUENCIES GenericFrequencyTable[]; extern S3_VIDEO_FREQUENCIES Dell805FrequencyTable[]; extern S3_VIDEO_FREQUENCIES NumberNine928NewFrequencyTable[]; extern S3_VIDEO_FREQUENCIES NumberNine928OldFrequencyTable[]; extern S3_VIDEO_FREQUENCIES Metheus928FrequencyTable[]; extern S3_VIDEO_FREQUENCIES Generic64NewFrequencyTable[]; extern S3_VIDEO_FREQUENCIES Generic64OldFrequencyTable[]; extern S3_VIDEO_FREQUENCIES NumberNine64FrequencyTable[]; extern S3_VIDEO_FREQUENCIES Diamond64FrequencyTable[]; extern S3_VIDEO_FREQUENCIES HerculesFrequencyTable[]; extern S3_VIDEO_FREQUENCIES Hercules64FrequencyTable[]; extern S3_VIDEO_FREQUENCIES Hercules68FrequencyTable[]; // // Mode Tables // extern S3_VIDEO_MODES S3Modes[]; extern ULONG NumS3VideoModes; // // Streams Tables // extern K2TABLE K2WidthRatio[]; extern K2TABLE K2FifoValue[]; // // Function prototypes // // // sdac.c // BOOLEAN InitializeSDAC( PHW_DEVICE_EXTENSION ); BOOLEAN FindSDAC( PHW_DEVICE_EXTENSION ); // // nnclk.c // long calc_clock(long, int); long gcd(long, long); VOID set_clock( PHW_DEVICE_EXTENSION HwDeviceExtension, LONG clock_value); // // S3.c // ULONG S3GetChildDescriptor( PVOID HwDeviceExtension, PVIDEO_CHILD_ENUM_INFO ChildEnumInfo, PVIDEO_CHILD_TYPE pChildType, PVOID pvChildDescriptor, PULONG pHwId, PULONG pUnused ); VP_STATUS GetDeviceDataCallback( PVOID HwDeviceExtension, PVOID Context, VIDEO_DEVICE_DATA_TYPE DeviceDataType, PVOID Identifier, ULONG IdentifierLength, PVOID ConfigurationData, ULONG ConfigurationDataLength, PVOID ComponentInformation, ULONG ComponentInformationLength ); VP_STATUS S3FindAdapter( PVOID HwDeviceExtension, PVOID HwContext, PWSTR ArgumentString, PVIDEO_PORT_CONFIG_INFO ConfigInfo, PUCHAR Again ); BOOLEAN S3Initialize( PVOID HwDeviceExtension ); BOOLEAN S3ResetHw( PVOID HwDeviceExtension, ULONG Columns, ULONG Rows ); BOOLEAN S3StartIO( PVOID HwDeviceExtension, PVIDEO_REQUEST_PACKET RequestPacket ); VP_STATUS S3SetColorLookup( PHW_DEVICE_EXTENSION HwDeviceExtension, PVIDEO_CLUT ClutBuffer, ULONG ClutBufferSize ); VOID SetHWMode( PHW_DEVICE_EXTENSION HwDeviceExtension, PUSHORT pusCmdStream ); VP_STATUS S3RegistryCallback( PVOID HwDeviceExtension, PVOID Context, PWSTR ValueName, PVOID ValueData, ULONG ValueLength ); LONG CompareRom( PUCHAR Rom, PUCHAR String ); VOID MapLinearControlSpace( PHW_DEVICE_EXTENSION HwDeviceExtension ); BOOLEAN S3IsaDetection( PHW_DEVICE_EXTENSION HwDeviceExtension, PULONG key ); VOID S3GetInfo( PHW_DEVICE_EXTENSION HwDeviceExtension, POINTER_CAPABILITY *PointerCapability, VIDEO_ACCESS_RANGE accessRange[] ); VOID S3DetermineFrequencyTable( PVOID HwDeviceExtension, VIDEO_ACCESS_RANGE accessRange[], INTERFACE_TYPE AdapterInterfaceType ); VOID S3DetermineDACType( PVOID HwDeviceExtension, POINTER_CAPABILITY *PointerCapability ); VOID S3ValidateModes( PVOID HwDeviceExtension, POINTER_CAPABILITY *PointerCapability ); VOID S3DetermineMemorySize( PVOID HwDeviceExtension ); VOID S3RecordChipType( PHW_DEVICE_EXTENSION HwDeviceExtension, PULONG key ); VOID AlphaDetermineMemoryUsage( PHW_DEVICE_EXTENSION HwDeviceExtension, VIDEO_ACCESS_RANGE accessRange[] ); ULONG UnlockExtendedRegs( PHW_DEVICE_EXTENSION HwDeviceExtension ); VOID LockExtendedRegs( PHW_DEVICE_EXTENSION HwDeviceExtension, ULONG key ); // // Non-int 10 platform support // VOID ZeroMemAndDac( PHW_DEVICE_EXTENSION HwDeviceExtension ); VP_STATUS Set_Oem_Clock( PHW_DEVICE_EXTENSION HwDeviceExtension ); VP_STATUS Wait_VSync( PHW_DEVICE_EXTENSION HwDeviceExtension ); BOOLEAN Bus_Test( PHW_DEVICE_EXTENSION HwDeviceExtension ); BOOLEAN Set864MemoryTiming( PHW_DEVICE_EXTENSION HwDeviceExtension ); BOOLEAN S3ConfigurePCI( PHW_DEVICE_EXTENSION HwDeviceExtension, PULONG NumPCIAccessRanges, PVIDEO_ACCESS_RANGE PCIAccessRanges ); VP_STATUS QueryStreamsParameters( PHW_DEVICE_EXTENSION HwDeviceExtension, VIDEO_QUERY_STREAMS_MODE *pStreamsMode, VIDEO_QUERY_STREAMS_PARAMETERS *pStreamsParameters ); VOID WorkAroundForMach( PHW_DEVICE_EXTENSION HwDeviceExtension ); // // ddc.c // BOOLEAN GetDdcInformation ( PHW_DEVICE_EXTENSION phwDeviceExtension, PUCHAR QueryBuffer, ULONG BufferSize ); // // power management // VP_STATUS S3GetPowerState( PHW_DEVICE_EXTENSION HwDeviceExtension, ULONG HwDeviceId, PVIDEO_POWER_MANAGEMENT VideoPowerManagement ); VP_STATUS S3SetPowerState( PHW_DEVICE_EXTENSION HwDeviceExtension, ULONG HwDeviceId, PVIDEO_POWER_MANAGEMENT VideoPowerManagement ); #define VESA_POWER_FUNCTION 0x4f10 #define VESA_POWER_ON 0x0000 #define VESA_POWER_STANDBY 0x0100 #define VESA_POWER_SUSPEND 0x0200 #define VESA_POWER_OFF 0x0400 #define VESA_GET_POWER_FUNC 0x0000 #define VESA_SET_POWER_FUNC 0x0001 #define VESA_STATUS_SUCCESS 0x004f