/****************************************************************************** * * ****************************************** * * Copyright (c) 1995, Cirrus Logic, Inc. * * * All Rights Reserved * * ****************************************** * * PROJECT: Laguna I (CL-GD546x) - * * FILE: cirrus.c * * AUTHOR: Benny Ng * * DESCRIPTION: * This is the Cirrus Logic Laguna NT miniport driver. * (kernel mode only) * Based on the S3 miniport from NT DDK. * * Copyright (c) 1995, 1996 Cirrus Logic, Inc. * * MODULES: * DriverEntry() * CLFindAdapter() * CLInitialize() * CLStartIO() * VS_Control_Hack() * Output_To_VS_CLK_CONTROL() * PMNT_Init() * PMNT_SetACPIState() * PMNT_GetACPIState() * PMNT_SetHwModuleState() * PMNT_GetHwModuleState() * PMNT_Close() * CLSetColorLookup() * CLFindVmemSize() * CLWriteRegistryInfo() * CLValidateModes() * CLCopyModeInfo() * CLSetMode() * CLSetMonitorType() * CLPowerManagement() * * REVISION HISTORY: * 5/30/95 Benny Ng Initial version * * $Log: //uinac/log/log/laguna/nt35/miniport/cl546x/CIRRUS.C $ * * Rev 1.131 Jun 16 1998 09:51:24 frido * PDR#????? - Make CLResetHw and all dependent functions * non-pageable. * * Rev 1.130 May 04 1998 11:54:58 frido * Oops. wrong check. * * Rev 1.129 May 04 1998 11:31:16 frido * Changed the FIFO override code to include clocks 16h and 17h and * changed the values in the override table. * * Rev 1.128 Apr 30 1998 15:30:18 frido * PDR#11398. CLRegistryCallback has been added to patch the * InstalledDisplayDrivers registry entry in case a remote control program * like LapLink or Timbuktu has been loaded. * * Rev 1.127 Apr 23 1998 16:18:34 frido * PDR#11377. Test PCI command register when looking for a Laguna * borda. It might be disabled. * * Rev 1.126 Apr 23 1998 14:54:46 frido * PDR#11290. Before changing to a text mode from a graphics mode, we * need to enable the PCI configuration registers. * * Rev 1.125 Apr 20 1998 11:33:54 frido * PDR#11350. Added CLResetHw routine which resets the hardware to * the default text mode. * * Rev 1.124 Apr 17 1998 13:54:00 frido * Keep sync polarity as is, but only make them negative when the monitor * requires it. * * Rev 1.123 Apr 15 1998 10:07:38 frido * PDR#11317: The SyncPolarity registry key has changed a bit. Now it * is a string value which will hold EDID manufacturer and monitor codes * for monitors that need negative polarity. * * Rev 1.122 Apr 02 1998 15:50:06 frido * Changed the SyncPolarity code. It is now dynamic using the EDID * manufacturer and product code to compare with a list in the registry. * * Rev 1.121 Mar 30 1998 15:02:48 frido * PDR#11284. I changed the delay before writing the palette data in the * CLSetColorLookup routine. Now when the vertical retrace is being * activated, all remaining palette entries are send to the chip. * * Rev 1.120 Mar 25 1998 18:28:56 frido * Why don't I compile before checking in? That would catch the errors... * * Rev 1.119 Mar 25 1998 18:20:28 frido * Fixed the CLGetMonitorSyncPolarity function. * * Rev 1.118 Mar 25 1998 17:57:56 frido * Added IOCTL_STALL. * * Rev 1.117 Mar 25 1998 10:22:50 frido * Removed the multi-string registry hack for NT 5.0. * * Rev 1.116 Mar 25 1998 10:19:04 frido * Added new code for monitor sync polarity. * * Rev 1.115 Feb 25 1998 15:39:04 frido * Added NT 5.0 PnP & Power Saving support. * * Rev 1.114 Jan 22 1998 16:25:24 frido * Added a call to enable Write Combined Caching for Intel CPU's. * * Rev 1.113 Jan 21 1998 17:49:22 frido * Redfined the validation of the chipset for frame buffer bursting. * * Rev 1.112 Jan 21 1998 17:43:16 frido * Enabled frame buffer bursting on 5465AF and higher. * * Rev 1.111 Jan 06 1998 16:47:22 frido * I have added a LowRes registry flag. If it is not available or 0, low-res * modes are disabled. If the value is 1, low-res modes are enabled. * * Rev 1.110 Dec 10 1997 13:17:50 frido * Merged from 1.62 branch. * * Rev 1.109.1.3 Nov 20 1997 14:57:02 frido * Re-enabled 640x350 and 640x400 as normal modes. * * Rev 1.109.1.2 Nov 19 1997 10:04:10 phyang * Added FIFO Threshold override table for clock speed 0x14h. * * Rev 1.109.1.1 Nov 17 1997 11:06:10 frido * Added MULTI_CLOCK support. This new feature (as per customer * request) overrides the FIFO Threshold value for certain modes at * different clock speeds. * * Rev 1.109.1.0 Nov 10 1997 11:41:04 phyang * Added 5 device I/O control codes for utilities to update registry values. * * Rev 1.109 Nov 04 1997 09:22:56 frido * Added code to disable LOWRES modes if defined in SWAT.h. * * Rev 1.108 Nov 03 1997 16:58:08 phyang * Added USB Fix flag query support and better mode filter function. * * Rev 1.107 Oct 23 1997 15:46:20 phyang * Move usMaxVtFrequency and usMaxXResolution to HW_DEVICE_EXTENSION. * * Rev 1.106 23 Oct 1997 11:17:04 noelv * Added new DDC filter function. * RE-enabled DD modes. * * Rev 1.104 07 Oct 1997 16:45:42 frido * I have removed all low-res modes again, WHQL fails at 320x400 and 340x400. * * Rev 1.103 27 Sep 1997 10:58:44 frido * Removed the displaying of the version number. It would generate STOP * messages during unattended setup. * * Rev 1.102 16 Sep 1997 13:46:16 frido * Added patch to counteract NT's memory leak when using multiple display * driver DLL's. * * Rev 1.101 16 Sep 1997 13:30:12 bennyn * * Display the version message after Laguna chip family is detected. * * Rev 1.100 12 Sep 1997 09:09:22 FRIDO * Enabled 256-byte prefetch. * * Rev 1.99 04 Sep 1997 16:37:16 bennyn * * Added restore and set video window regs before and after the mode change. * * Rev 1.98 29 Aug 1997 12:26:02 noelv * restore file after roll-back * * Rev 1.96 27 Aug 1997 10:29:18 noelv * Apply CONTROL[4] fix to AF chip, too. * * Rev 1.95 26 Aug 1997 11:46:46 noelv * Enable lo-res DDRAW modes. * * Rev 1.94 20 Aug 1997 16:59:58 noelv * Typo in version string (again :) * * Rev 1.93 20 Aug 1997 09:33:18 bennyn * * Added automatically detects PnP monitor support * * Rev 1.92 19 Aug 1997 17:40:16 noelv * * Added newline to driver version string * * Rev 1.91 14 Aug 1997 14:44:56 noelv * * Changed the way the version is reported. * * Rev 1.90 13 Aug 1997 11:22:10 noelv * Added [5465AD] setcion to MODE.INI * * Rev 1.89 07 Aug 1997 15:30:18 noelv * Made AGP_VGA_HACK and FAVOR_MODE_INI a permanent part of the driver. * Removed their #defines * * Rev 1.88 04 Aug 1997 16:26:12 BENNYN * Commented out the EDID mode filter function * * Rev 1.87 29 Jul 1997 15:10:04 noelv * 0x0484 to perfomance reg to get rid of snow in foxbear. * * Rev 1.86 23 Jul 1997 09:26:44 bennyn * * Added code to handle IOCTL_GET_BIOS_VERSION command * * Rev 1.85 22 Jul 1997 12:39:40 bennyn * * Trunicate the mode table of EDID data is available * * Rev 1.84 21 Jul 1997 13:51:52 bennyn * * Added call to ReadVesaTiming() * * Rev 1.83 15 Jul 1997 09:20:18 noelv * Added AGP card support for NT 3.51 * * Rev 1.82 14 Jul 1997 16:51:50 bennyn * Removed setting the mclk to 13h for cl5465 * * Rev 1.81 02 Jul 1997 15:08:52 noelv * Fixes the clock-set code for 5465. Set the clock to 13h * * Rev 1.80 01 Jul 1997 14:48:02 bennyn * Change MCLK to 14 for 5465 * * Rev 1.79 20 Jun 1997 13:45:36 bennyn * * Added power manager functions to Miniport * * Rev 1.78 19 Jun 1997 11:32:52 BENNYN * Disabled the 256-bytes fetch * * Rev 1.77 16 Jun 1997 16:25:20 noelv * * 5465AD HW workarounds from Frido * SWAT: * SWAT: Rev 1.4 07 Jun 1997 12:45:08 frido * SWAT: Added setting of CONTROL[4] bit for 5465AD chip. * * Rev 1.76 15 May 1997 15:57:02 noelv * Moved SWAT4 stuff to the miniport * * Rev 1.75 14 May 1997 16:56:04 bennyn * Fixed PDR 9630 * * Rev 1.74 05 May 1997 16:38:52 noelv * Wait for blank before writing to the palette * * Rev 1.73 30 Apr 1997 16:41:24 noelv * Moved global SystemIoBusNumber into the device extension, where it belongs. * * Rev 1.72 24 Apr 1997 11:00:52 SueS * Enable MMIO access to PCI space on a reset device IOCTL. Added * function CLEnablePCIConfigMMIO. * * Rev 1.71 23 Apr 1997 07:20:10 SueS * Added new IOCTL for enabling memory-mapped I/O access to PCI * configuration registers. Save PCI slot number for use in later * kernel function call. * * Rev 1.70 22 Apr 1997 11:01:44 noelv * * Added forward compatible chip ids. * * Rev 1.69 17 Apr 1997 14:34:00 noelv * Changed interleave for 8 meg boards. * Expanded frame buffer memory space to 16 meg. * Don't patch MODE.INI modes. * * Rev 1.68 04 Apr 1997 14:45:56 noelv * Removed VL access ranges. Rearranged VGA access ranges. * Changed call to SetMode() to include the new parameter. * * Rev 1.67 28 Mar 1997 16:59:38 noelv * Added 5464 and 5465 specific code to CLEnableTiling. * * Rev 1.66 28 Mar 1997 13:29:30 noelv * Fixed tiling on NT 3.51 * * Rev 1.65 27 Mar 1997 11:33:36 noelv * Favor MODE.INI modes over BIOS modes. * Fix ClEnableTiling for 5464. * * Rev 1.64 24 Mar 1997 16:07:58 noelv * Changed memory detect to use memory mapped registers (instead of VGA). * * Rev 1.63 03 Mar 1997 14:42:14 SueS * Subtract 1 from tiles per line (Win95 bandwidth improvement). * Set address translation delay to 3 clocks. * * Rev 1.62 28 Feb 1997 11:19:16 SueS * For bus mastering (which isn't currently enabled), get an adapter object * for the call to HalAllocateCommonBuffer. Otherwise, we bomb when we boot * in VGA mode with bus mastering turned on. * * Rev 1.61 26 Feb 1997 16:14:38 noelv * CLPatchModeTable now correctly locates a planar BIOS. * * Rev 1.60 21 Feb 1997 16:16:44 noelv * Fixed typo in AGP code. * * Rev 1.59 21 Feb 1997 15:20:50 noelv * Sped up CLPatchModeTable * * Rev 1.58 21 Feb 1997 14:42:10 noelv * Oops. I swapped the frame buffer and register address spaces by accident. * * Rev 1.57 21 Feb 1997 12:53:42 noelv * AGP and 5465 4meg support * * Rev 1.56 19 Feb 1997 13:16:44 noelv * Added partial AGP support * * Rev 1.55 04 Feb 1997 15:35:58 bennyn * Interleave off for VGA modes, on for extended modes * * Rev 1.54 03 Feb 1997 13:24:46 noelv * Remove 1280x960 * * Rev 1.53 31 Jan 1997 10:00:26 noelv * Allowed +/- 1 hz when matching refresh reates between MODE.INI and BIOS * * Rev 1.52 28 Jan 1997 11:32:32 noelv * write the correct chip type to the registry. * * Rev 1.51 14 Jan 1997 17:23:08 bennyn * Modified to support 5465 * * Rev 1.50 14 Jan 1997 12:32:02 noelv * Split MODE.INI by chip type * * Rev 1.49 09 Dec 1996 15:50:44 bennyn * Supported the 5465 MMIO & FB base addr PCI offset change * * Rev 1.48 03 Dec 1996 10:51:42 noelv * Always use 2-way interleave * * Rev 1.47 26 Nov 1996 08:42:50 SueS * Added case for closing the log file. * * Rev 1.46 13 Nov 1996 16:19:46 noelv * Disabled WC memory for the 5462 * * Rev 1.45 13 Nov 1996 15:28:36 SueS * Added support for two new IOCTL codes used for the file logging option. * There is an IOCTL request to open the file and another to write to it. * * Rev 1.44 13 Nov 1996 08:18:12 noelv * * Cleaned up support for 5464 register set. * * Rev 1.43 11 Nov 1996 10:42:08 noelv * Turn off bus mastering abilities for release builds. * * Rev 1.42 07 Nov 1996 10:48:04 BENNYN * Turn-on P6WC bit and added support for BD and 5465 parts * * Rev 1.41 30 Oct 1996 14:06:50 bennyn * * Modified for pageable miniport * * Rev 1.40 23 Oct 1996 16:03:14 noelv * * Added BUS MASTERING support. * * Rev 1.39 07 Oct 1996 14:28:20 noelv * Removed WC memory. * * Rev 1.38 03 Oct 1996 17:12:10 noelv * removed LNCTRL init. * * Rev 1.37 01 Oct 1996 17:39:08 noelv * Don't read LnCntl reg. * * Rev 1.36 30 Sep 1996 10:01:42 noelv * Used 16 bit writes to do clear-screen BLT, 'cause 5464 was hanging. * * Rev 1.35 24 Sep 1996 10:02:00 noelv * Added venus chipset to known bad. * * Rev 1.34 18 Sep 1996 15:49:12 noelv * P^ cache enabled on NT 4.0 only * * Rev 1.33 13 Sep 1996 15:35:36 bennyn * Turn-on the P6 cache * * Rev 1.32 30 Aug 1996 13:00:18 noelv * * Set interleave before calling SetMode(). * * Rev 1.31 23 Aug 1996 14:18:28 noelv * * Fixed syntax error. * * Rev 1.30 23 Aug 1996 14:14:48 noelv * Accidently timmed VGA modes from NT 3.51 driver. * * Rev 1.29 23 Aug 1996 09:43:34 noelv * Frido bug release 8-23. * * Rev 1.28 22 Aug 1996 18:47:12 noelv * fixed typo in ttrimming DD modes from nt3.51 * * Rev 1.27 22 Aug 1996 17:39:06 noelv * Trim DD modes from NT3.51 * * Rev 1.26 22 Aug 1996 16:35:06 noelv * Changed for new mode.ini * * Rev 1.25 21 Aug 1996 16:42:58 noelv * Turned down the clock on the '64 * * Rev 1.24 20 Aug 1996 11:57:50 noelv * * Added correct chip ID to registry. * * Rev 1.23 20 Aug 1996 11:26:56 noelv * Bugfix release from Frido 8-19-96 * * Rev 1.4 18 Aug 1996 23:24:36 frido * #1334? - Changed hardware registers to 'volatile'. * * Rev 1.3 17 Aug 1996 17:31:18 frido * Cleanup up #1242 patch by blanking screen before clearing video memory. * * Rev 1.2 16 Aug 1996 14:34:42 frido * #1242 - Added clearing of video memory. * * Rev 1.1 15 Aug 1996 12:45:10 frido * Fixed warning messages. * * Rev 1.0 14 Aug 1996 17:12:18 frido * Initial revision. * * Rev 1.21 15 Jul 1996 17:18:00 noelv * Added wait for idle before mode switch * * Rev 1.20 11 Jul 1996 15:30:38 bennyn * Modified to support DirectDraw * * Rev 1.19 25 Jun 1996 10:48:58 bennyn * Bring-up the 5464 * * Rev 1.18 19 Jun 1996 11:04:48 noelv * New mode switch code. * * Rev 1.17 05 Jun 1996 09:01:38 noelv * Reserve 8 meg of address space for the frame buffer. * * Rev 1.16 13 May 1996 14:52:34 bennyn * Added 5464 support * * Rev 1.15 10 Apr 1996 17:58:42 bennyn * * Conditional turn on HD_BRST_EN * * Rev 1.14 26 Mar 1996 16:46:14 noelv * * Test pointer in CLPatchModeTable befor using it. * * Rev 1.13 12 Mar 1996 16:11:46 noelv * * Removed support for AC chip. * * Rev 1.12 02 Mar 1996 12:30:02 noelv * Miniport now patches the ModeTable with information read from the BIOS * * Rev 1.11 23 Jan 1996 14:08:38 bennyn * Modified for COMPAQ * * Rev 1.10 20 Nov 1995 13:43:54 noelv * Updated registry with adapter string and DAC type. * * Rev 1.9 16 Nov 1995 13:27:04 bennyn * * Fixed not recognize AC parts & Added handling of IOCTL_CL_BIOS. * * Rev 1.8 26 Oct 1995 10:14:06 NOELV * Added version information. * * Rev 1.7 27 Sep 1995 11:03:00 bennyn * Fixed setting TRUE color modes * * Rev 1.6 22 Sep 1995 10:25:00 bennyn * * Rev 1.5 19 Sep 1995 08:27:44 bennyn * Fixed register space addr mask problem * * Rev 1.4 24 Aug 1995 08:13:22 bennyn * Set the CONTROL, LNCNTL & TILE_CTRL registers, this is corresponding to the * * Rev 1.3 22 Aug 1995 10:16:58 bennyn * Inital version for real HW * * Rev 1.2 21 Aug 1995 15:30:04 bennyn * * Rev 1.1 17 Aug 1995 08:17:56 BENNYN * * Rev 1.0 24 Jul 1995 13:22:38 NOELV * Initial revision. * **************************************************************************** ****************************************************************************/ /*----------------------------- INCLUDES ----------------------------------*/ #include "cirrus.h" #include "modemon.h" #include "version.h" #include "SWAT.h" /*----------------------------- DEFINES -----------------------------------*/ //#define DBGBRK #define PCIACCESS1 #define NO_BUS_MASTER 1 #define DISPLVL 2 #ifdef DBGBRK #define NTAPI __stdcall VOID NTAPI DbgBreakPoint(VOID); #endif #define VOLATILE volatile #define QUERY_MONITOR_ID 0x22446688 #define QUERY_NONDDC_MONITOR_ID 0x11223344 #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 // The 5465 (to at least AC) has a problem when PCI configuration space // is accessible in memory space. On 16-bit writes, a 32-bit write is // actually performed, so the next register has garbage written to it. // We get around this problem by clearing bit 0 of the Vendor Specific // Control register in PCI configuration space. When this bit is set // to 0, PCI configuration registers are not available through memory // mapped I/O. Since some functions require access to PCI registers, // and only the miniport can access the kernel function to reenable it, // the display driver must post a message to the miniport to enable this // bit when needed. // #define VS_CONTROL_HACK 1 /*--------------------- STATIC FUNCTION PROTOTYPES ------------------------*/ /*--------------------------- ENUMERATIONS --------------------------------*/ /*----------------------------- TYPEDEFS ----------------------------------*/ typedef struct { USHORT VendorId; // Vender Id USHORT DeviceId; // Device Id USHORT HwRev; // HW rev } BADCHIPSET; /*-------------------------- STATIC VARIABLES -----------------------------*/ // // VGA Access Ranges definitions // VIDEO_ACCESS_RANGE CLAccessRanges[NUM_VGA_ACCESS_RANGES] = { // RangeStart RangeLength // | | RangeInIoSpace // | | | RangeVisible // +-----+-----+ | | | RangeShareable // v v v v v v {0x000003B0, 0x00000000, 0x0000000c, 1, 1, 1}, // First chunk of vga ports {0x000003C0, 0x00000000, 0x00000020, 1, 1, 1}, // Remainder of vga ports {0x000A0000, 0x00000000, 0x00020000, 0, 1, 1}, // VGA memory }; #define NUMBADCHIPSET 3 BADCHIPSET BadChipSet[NUMBADCHIPSET] = { {0x0E11, 0x0001, 0x0003}, {0x0E11, 0x1000, 0x0001}, {0x8086, 0x1237, 0x0000}, }; unsigned long resetmode = 0xFFFFFFFF; // // Device ID supported by this miniport // USHORT DeviceId[] = { // Supported chips. CL_GD5462, CL_GD5464, CL_GD5464_BD, CL_GD5465, // For forward compatiblty... CL_GD546x_D7, CL_GD546x_D8, CL_GD546x_D9, CL_GD546x_DA, CL_GD546x_DB, CL_GD546x_DC, CL_GD546x_DD, CL_GD546x_DE, CL_GD546x_DF, // Terminator 0 }; #define ALWAYS_ON_VS_CLK_CTL 0x0000C0A0 // VW_CLK, RAMDAC_CLK static DWORD LgPM_vs_clk_table[] = { 0x00000001, // MOD_2D 0x00000002, // MOD_STRETCH 0x00000004, // MOD_3D 0x00000008, // MOD_EXTMODE 0x00000010, // MOD_VGA 0x00000000, // MOD_RAMDAC 0x00000040, // MOD_VPORT 0x00000000, // MOD_VW 0x00000100, // MOD_TVOUT 0x00000000, // Reserved9 0x00000000, // Reserved10 0x00000000, // Reserved11 0x00000000, // Reserved12 0x00000000, // Reserved13 0x00004000, // SYBCLK_OTHER_EN 0x00008000, // DISP_OTHER_EN 0x00000000, // Reserved16 0x00000000, // Reserved17 0x00000000, // Reserved18 0x00000000, // Reserved19 0x00000000, // Reserved20 0x00000000, // Reserved21 0x00000000, // Reserved22 0x00000000, // Reserved23 0x00000000, // Reserved24 0x00000000, // Reserved25 0x00000000, // Reserved26 0x00000000, // Reserved27 0x00000000, // Reserved28 0x00000000, // Reserved29 0x00000000, // Reserved30 0x00000000 // Reserved31 }; // // Memory interleave is based on how much memory we have. // For BIOS modes we don't muck with memory interleave. // But if MODE.INI is used to set the mode, we need to set the // memory interleave ourselves. // #define ONE_WAY (0x00 << 6) #define TWO_WAY (0x01 << 6) #define FOUR_WAY (0x02 << 6) unsigned char bLeave[] = { TWO_WAY, TWO_WAY, TWO_WAY, FOUR_WAY, TWO_WAY, TWO_WAY, TWO_WAY, FOUR_WAY, }; #if LOG_FILE extern HANDLE LogFileHandle; // Handle for log file #endif /*-------------------------- EXTERNAL FUNCTIONS --------------------------*/ extern ULONG RtlWriteRegistryValue(ULONG RelativeTo, PWSTR Path, PWSTR ValueName, ULONG ValueType, PVOID ValueData, ULONG ValueLength); extern DWORD ConfigureLagunaMemory(DWORD dwPhysFB, DWORD dwFBSize); extern void ReleaseMTRRs(DWORD dwFBMTRRReg); /*-------------------------- GLOBAL FUNCTIONS -----------------------------*/ VOID HalDisplayString(PUCHAR); #if 0 VP_STATUS CLGetLowResValue(PHW_DEVICE_EXTENSION HwDeviceExtension, PVOID Context, PWSTR ValueName, PVOID ValueData, ULONG ValueLength); #endif #if defined(ALLOC_PRAGMA) #pragma alloc_text(PAGE,DriverEntry) #pragma alloc_text(PAGE,CLFindAdapter) #pragma alloc_text(PAGE,CLInitialize) #pragma alloc_text(PAGE,CLStartIO) #pragma alloc_text(PAGE,ReadClockLine) #pragma alloc_text(PAGE,WriteClockLine) #pragma alloc_text(PAGE,WriteDataLine) #pragma alloc_text(PAGE,ReadDataLine) #pragma alloc_text(PAGE,WaitVSync) #pragma alloc_text(PAGE,VS_Control_Hack) #pragma alloc_text(PAGE,Output_To_VS_CLK_CONTROL) #pragma alloc_text(PAGE,PMNT_Init) #pragma alloc_text(PAGE,PMNT_SetACPIState) #pragma alloc_text(PAGE,PMNT_GetACPIState) #pragma alloc_text(PAGE,PMNT_SetHwModuleState) #pragma alloc_text(PAGE,PMNT_GetHwModuleState) #pragma alloc_text(PAGE,PMNT_Close) #pragma alloc_text(PAGE,CLSetColorLookup) #pragma alloc_text(PAGE,CLFindVmemSize) #pragma alloc_text(PAGE,CLWriteRegistryInfo) #pragma alloc_text(PAGE,CLValidateModes) #pragma alloc_text(PAGE,CLCopyModeInfo) #if 0 // Stress test #pragma alloc_text(PAGE,CLSetMode) #pragma alloc_text(PAGE,CLSetMonitorType) #pragma alloc_text(PAGE,CLEnableTiling) #endif #pragma alloc_text(PAGE,CLPowerManagement) #pragma alloc_text(PAGE,CLPatchModeTable) #pragma alloc_text(PAGE,CLEnablePciBurst) #pragma alloc_text(PAGE,CLFindLagunaOnPciBus) #pragma alloc_text(PAGE,ClAllocateCommonBuffer) #if 0 #pragma alloc_text(PAGE,CLGetLowResValue) #endif #if _WIN32_WINNT >= 0x0500 #pragma alloc_text(PAGE,CLGetChildDescriptor) #pragma alloc_text(PAGE,CLGetPowerState) #pragma alloc_text(PAGE,CLSetPowerState) #pragma alloc_text(PAGE,GetDDCInformation) #endif #endif /**************************************************************************** * FUNCTION NAME: DriverEntry() * * DESCRIPTION: * Installable driver initialization entry point. * This entry point is called directly by the I/O system. * * REVISION HISTORY: * 5/30/95 Benny Ng Initial version ****************************************************************************/ ULONG DriverEntry (PVOID Context1, PVOID Context2) { VIDEO_HW_INITIALIZATION_DATA hwInitData; ULONG status; ULONG status1; PAGED_CODE(); VideoDebugPrint((DISPLVL, "Miniport - CL546x DriverEntry\n")); // // Zero out structure. // VideoPortZeroMemory(&hwInitData, sizeof(VIDEO_HW_INITIALIZATION_DATA)); // // Specify sizes of structure and extension. // hwInitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA); // // Set entry points. // hwInitData.HwFindAdapter = CLFindAdapter; hwInitData.HwInitialize = CLInitialize; hwInitData.HwInterrupt = NULL; hwInitData.HwStartIO = CLStartIO; #if 1 // PDR#11350 hwInitData.HwResetHw = CLResetHw; #endif #if _WIN32_WINNT >= 0x0500 hwInitData.HwGetVideoChildDescriptor = CLGetChildDescriptor; hwInitData.HwGetPowerState = CLGetPowerState; hwInitData.HwSetPowerState = CLSetPowerState; #endif // // Determine the size we require for the device extension. // hwInitData.HwDeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION); // // Always start with parameters for device0 in this case. // // This device only supports PCI bus types. // hwInitData.AdapterInterfaceType = PCIBus; status = VideoPortInitialize(Context1, Context2, &hwInitData, NULL); return status; } // end DriverEntry() #if _WIN32_WINNT >= 0x0500 #define QUERY_ACPI_MONITOR_ID 0x0100 #define QUERY_ACPI_PANEL_ID 0x0110 #define QUERY_ACPI_TV_ID 0x0200 /******************************************************************************* * Enumerate all devices controlled by the Laguna graphics chip. This includes * DDC monitors attached to the board, as well as other devices which may be * connected to the I2C bus. */ ULONG CLGetChildDescriptor( PVOID HwDeviceExtension, // Pointer to our hardware device context // structure. PVIDEO_CHILD_ENUM_INFO ChildEnumInfo, // Information about the device that // should be enumerated PVIDEO_CHILD_TYPE pChildType, // Type of child we are enumerating - monitor, // I2C, ... PVOID pChildDescriptor, // Identification structure of the device // (EDID, string). ULONG* pUId, // Private unique 32 bit ID to be passed back to // the miniport. PVOID pUnused // unused ) /* * The return value is TRUE if the child device existed, FALSE if it did not. *******************************************************************************/ { PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension; switch (ChildEnumInfo->ChildIndex) { case 0: // // Case 0 is used to enumerate devices found by the ACPI firmware. // // For monitor devices enumerated by ACPI, the video port will get // the EDID directly from ACPI. // switch (ChildEnumInfo->ACPIHwId) { case QUERY_ACPI_MONITOR_ID: *pChildType = Monitor; *pUId = ChildEnumInfo->ACPIHwId; return ERROR_MORE_DATA; case QUERY_ACPI_PANEL_ID: *pChildType = Monitor; *pUId = ChildEnumInfo->ACPIHwId; return ERROR_MORE_DATA; case QUERY_ACPI_TV_ID: *pChildType = Monitor; *pUId = ChildEnumInfo->ACPIHwId; return ERROR_MORE_DATA; default: ASSERT(FALSE); return ERROR_NO_MORE_DEVICES; } case 1: // Obtain the EDID structure via DDC. if (GetDDCInformation(HwDeviceExtension, pChildDescriptor, ChildEnumInfo->ChildDescriptorSize)) { *pChildType = Monitor; *pUId = 0x22446688; VideoDebugPrint((1, "CLGetChildDescriptor - " "successfully read EDID structure\n")); } else { // Always return at least a monitor. *pChildType = Monitor; *pUId = 0x11223344; VideoDebugPrint((1, "CLGetChildDescriptor - " "DDC not supported\n")); } return ERROR_MORE_DATA; default: return ERROR_NO_MORE_DEVICES; } } /******************************************************************************* * Returns the power state information. */ VP_STATUS CLGetPowerState( PHW_DEVICE_EXTENSION HwDeviceExtension, // Pointer to our hardware // device extension structure. ULONG HwDeviceId, // Private unique 32 bit ID // identifying the device. PVIDEO_POWER_MANAGEMENT VideoPowerManagement // Power state information. ) /* * The return value is TRUE if the power state can be set, FALSE otherwise. *******************************************************************************/ { VP_STATUS status; // // We only support power setting for the monitor. Make sure the // HwDeviceId matches one the the monitors we could report. // if ((HwDeviceId == QUERY_NONDDC_MONITOR_ID) || (HwDeviceId == QUERY_MONITOR_ID)) { VIDEO_X86_BIOS_ARGUMENTS biosArguments; // // We are querying the power support for the monitor. // if ((VideoPowerManagement->PowerState == VideoPowerOn) || (VideoPowerManagement->PowerState == VideoPowerHibernate)) { return NO_ERROR; } VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS)); biosArguments.Eax = VESA_POWER_FUNCTION; biosArguments.Ebx = VESA_GET_POWER_FUNC; status = VideoPortInt10(HwDeviceExtension, &biosArguments); if ( (status == NO_ERROR ) && ( (biosArguments.Eax & 0xffff) == VESA_STATUS_SUCCESS)) { switch (VideoPowerManagement->PowerState) { case VideoPowerStandBy: return (biosArguments.Ebx & VESA_POWER_STANDBY) ? NO_ERROR : ERROR_INVALID_FUNCTION; case VideoPowerSuspend: return (biosArguments.Ebx & VESA_POWER_SUSPEND) ? NO_ERROR : ERROR_INVALID_FUNCTION; case VideoPowerOff: return (biosArguments.Ebx & VESA_POWER_OFF) ? NO_ERROR : ERROR_INVALID_FUNCTION; default: break; } } VideoDebugPrint((1, "This device does not support Power Management.\n")); return ERROR_INVALID_FUNCTION; } else if (HwDeviceId == DISPLAY_ADAPTER_HW_ID) { // // We are querying power support for the graphics card. // switch (VideoPowerManagement->PowerState) { case VideoPowerOn: case VideoPowerHibernate: case VideoPowerStandBy: return NO_ERROR; case VideoPowerOff: case VideoPowerSuspend: // // Indicate that we can't do VideoPowerOff, because // we have no way of coming back when power is re-applied // to the card. // return ERROR_INVALID_FUNCTION; default: ASSERT(FALSE); return ERROR_INVALID_FUNCTION; } } else { VideoDebugPrint((1, "Unknown HwDeviceId")); ASSERT(FALSE); return ERROR_INVALID_PARAMETER; } } /******************************************************************************* * Set the power state for a given device. */ VP_STATUS CLSetPowerState( PHW_DEVICE_EXTENSION HwDeviceExtension, // Pointer to our hardware // device extension structure. ULONG HwDeviceId, // Private unique 32 bit ID // identifying the device. PVIDEO_POWER_MANAGEMENT VideoPowerManagement // Power state information. ) /* * The return value is TRUE if the power state can be set, FALSE otherwise. *******************************************************************************/ { VP_STATUS status; // // Make sure we recognize the device. // if ((HwDeviceId == QUERY_NONDDC_MONITOR_ID) || (HwDeviceId == QUERY_MONITOR_ID)) { VIDEO_X86_BIOS_ARGUMENTS biosArguments; VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS)); biosArguments.Eax = VESA_POWER_FUNCTION; biosArguments.Ebx = VESA_SET_POWER_FUNC; switch (VideoPowerManagement->PowerState) { case VideoPowerOn: case VideoPowerHibernate: biosArguments.Ebx |= VESA_POWER_ON; break; case VideoPowerStandBy: biosArguments.Ebx |= VESA_POWER_STANDBY; break; case VideoPowerSuspend: biosArguments.Ebx |= VESA_POWER_SUSPEND; break; case VideoPowerOff: biosArguments.Ebx |= VESA_POWER_OFF; break; default: VideoDebugPrint((1, "Unknown power state.\n")); ASSERT(FALSE); return ERROR_INVALID_PARAMETER; } status = VideoPortInt10(HwDeviceExtension, &biosArguments); if ( (status == NO_ERROR ) && ((biosArguments.Eax & 0xffff) == VESA_STATUS_SUCCESS)) { HwDeviceExtension->MonitorEnabled = ((VideoPowerManagement->PowerState == VideoPowerOn) || (VideoPowerManagement->PowerState == VideoPowerHibernate)); return NO_ERROR; } else { VideoDebugPrint((1, "CLSetPowerState: Int10 failed \n")); return ERROR_INVALID_PARAMETER; } } else if (HwDeviceId == DISPLAY_ADAPTER_HW_ID) { switch (VideoPowerManagement->PowerState) { case VideoPowerOn: case VideoPowerStandBy: case VideoPowerSuspend: case VideoPowerOff: case VideoPowerHibernate: return NO_ERROR; default: ASSERT(FALSE); return ERROR_INVALID_PARAMETER; } } else { VideoDebugPrint((1, "Unknown HwDeviceId")); ASSERT(FALSE); return ERROR_INVALID_PARAMETER; } } #endif /**************************************************************************** * FUNCTION NAME: CLFindAdapter() * * DESCRIPTION: * This routine is called to determine if the adapter for this driver * is present in the system. * If it is present, the function fills out some information describing * the adapter. * * REVISION HISTORY: * 5/30/95 Benny Ng Initial version ****************************************************************************/ VP_STATUS CLFindAdapter ( PVOID HwDeviceExtension, // Our global data PVOID HwContext, // Not used. PWSTR ArgumentString, // Not used. PVIDEO_PORT_CONFIG_INFO ConfigInfo, // Pass info about card back to NT PUCHAR Again) // We always say 'no' { PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension; PVIDEO_ACCESS_RANGE pAccessRanges; VIDEO_ACCESS_RANGE AccessRanges[TOTAL_ACCESS_RANGES]; PVOID MappedAddress[TOTAL_ACCESS_RANGES]; ULONG ReleaseCnt=0, start_range, skip_ranges; VP_STATUS status = ERROR_DEV_NOT_EXIST; ULONG i; ULONG ulFirstAccessRange; unsigned long SystemIoBusNumber; PAGED_CODE(); VideoDebugPrint((DISPLVL, "Miniport - CLFindAdapter. AdapterInterfaceType is %d.\n", ConfigInfo->AdapterInterfaceType)); VideoDebugPrint((DISPLVL, "Miniport - CLFindAdapter. SystemIoBusNumber is %d.\n", ConfigInfo->SystemIoBusNumber)); SystemIoBusNumber = ConfigInfo->SystemIoBusNumber; #ifdef DBGBRK DbgBreakPoint(); #endif // // Make sure the size of the structure is at least as large as what we // are expecting (check version of the config info structure). // if (ConfigInfo->Length < sizeof(VIDEO_PORT_CONFIG_INFO)) { VideoDebugPrint((DISPLVL, "Miniport - CLFindAdapter parameter wrong size.\n")); return (ERROR_INVALID_PARAMETER); } // // Detect a PCI card. We don't do ISA bus. We don't do VL bus. // // After detecting the chip, we fill in the register and frame buffer // access ranges with data from PCI registers. // The location and size of the VGA access ranges is constant, // but the location of our registers and frame buffer depend on where // the PCI BIOS decided to put them. // pAccessRanges = &AccessRanges[FIRST_MM_ACCESS_RANGE]; if (ConfigInfo->AdapterInterfaceType == PCIBus) status = CLFindLagunaOnPciBus(hwDeviceExtension, pAccessRanges); // // If we didn't find our chip, then return failure. // if (status != NO_ERROR) { VideoDebugPrint((DISPLVL, "Miniport - CLFindLagunaOnPciBus did not find a Laguna chip.\n")); *Again = 0; return status; } // // The maximum possible frame buffer size is 1/4 of frame buffer // address space decoded by the chip. This is because the chip // replicates the frame buffer address space 4 times. // AccessRanges[MM_FRAME_BUFFER_ACCESS_RANGE].RangeLength /= 4; // // Hey, hey, hey. We found a chip. // VideoDebugPrint((DISPLVL, "Miniport - CLFindLagunaOnPciBus found a CL546x.\n")); // // We will start by see if if we can get the VGA resources. // // assume we can get the VGA resources hwDeviceExtension->Dont_Do_VGA = 0; ulFirstAccessRange = FIRST_VGA_ACCESS_RANGE; // Copy the VGA access ranges into our AccessRanges structure. VideoPortMoveMemory(AccessRanges, CLAccessRanges, sizeof(VIDEO_ACCESS_RANGE) * NUM_VGA_ACCESS_RANGES); // Check to see if there is a VGA I/O hardware resource conflict. VideoDebugPrint((DISPLVL, "Miniport - Verifying the VGA access ranges.\n")); status = VideoPortVerifyAccessRanges(hwDeviceExtension, NUM_VGA_ACCESS_RANGES, AccessRanges); VideoDebugPrint ((DISPLVL, "Miniport - VGA access ranges verification was %s. Status was %d.\n", ((status == NO_ERROR) ? "successful" : "not successful"), status)); if (status != NO_ERROR) { // We didn't get the VGA space. We may be a secondary adapter so // continue but hands off VGA resources. hwDeviceExtension->Dont_Do_VGA = 1; MappedAddress[0] = MappedAddress[1] = MappedAddress[2] = NULL; ulFirstAccessRange = FIRST_MM_ACCESS_RANGE; // skip VGA resources } // // Now verify the Laguna register and frame buffer ranges. // (include VGA ranges if the are available to us) // status = VideoPortVerifyAccessRanges(hwDeviceExtension, (TOTAL_ACCESS_RANGES-ulFirstAccessRange), &AccessRanges[ulFirstAccessRange]); if (status != NO_ERROR) return status; // !!!!!!! CONFLICT !!!!!!! // Now map the access ranges. VideoDebugPrint ((DISPLVL, "Miniport - Mapping access ranges.\n")); for (i = ulFirstAccessRange; i < TOTAL_ACCESS_RANGES; i++) { pAccessRanges = &AccessRanges[i]; VideoDebugPrint((DISPLVL, "Miniport - Mapping range. Start=0x%08X:0x%08X Length=%d.\n", pAccessRanges->RangeStart.HighPart, pAccessRanges->RangeStart.LowPart, pAccessRanges->RangeLength )); if ((MappedAddress[i] = VideoPortGetDeviceBase(hwDeviceExtension, pAccessRanges->RangeStart, pAccessRanges->RangeLength, pAccessRanges->RangeInIoSpace)) == NULL) { VideoDebugPrint((DISPLVL, "Miniport - Mapping failed\n")); VideoDebugPrint ((DISPLVL, "Miniport - Unmapping access ranges.\n")); // Unmap the previously mapped addresses while (i-- > ulFirstAccessRange) { VideoPortFreeDeviceBase(hwDeviceExtension, &MappedAddress[i]); } return ERROR_DEV_NOT_EXIST; } else VideoDebugPrint((DISPLVL,"Miniport - Mapping successful.\n")); } // end for // Save the location of the VGA registers. hwDeviceExtension->IOAddress = MappedAddress[0]; // // Initialize variables in hardware extension // hwDeviceExtension->CurrentModeNum = (ULONG) -1; hwDeviceExtension->CurrentMode = NULL; hwDeviceExtension->PowerState = VideoPowerOn; hwDeviceExtension->SystemIoBusNumber=SystemIoBusNumber; // // Save the VGA mapped address. // // hwDeviceExtension->VLIOAddress = MappedAddress[1]; // // Save the physical register address information // pAccessRanges = &AccessRanges[MM_REGISTER_ACCESS_RANGE]; hwDeviceExtension->PhysicalRegisterAddress = pAccessRanges->RangeStart; hwDeviceExtension->PhysicalRegisterLength = pAccessRanges->RangeLength; hwDeviceExtension->PhysicalFrameInIoSpace = pAccessRanges->RangeInIoSpace; // // Save the virtual register address information // hwDeviceExtension->RegisterAddress = MappedAddress[MM_REGISTER_ACCESS_RANGE]; hwDeviceExtension->RegisterLength = pAccessRanges->RangeLength; // // Get the size of the video memory. // if ((hwDeviceExtension->AdapterMemorySize = CLFindVmemSize(hwDeviceExtension)) == 0) { VideoDebugPrint((DISPLVL, "Miniport - No VMEM installed\n")); // Unmap our access ranges. for (i=0; i < ReleaseCnt; i++) VideoPortFreeDeviceBase(hwDeviceExtension, &MappedAddress[i]); // Erase the claim on the hardware resource VideoPortVerifyAccessRanges(hwDeviceExtension, 0, AccessRanges); return ERROR_DEV_NOT_EXIST; } // // Save the physical frame buffer address information // pAccessRanges = &AccessRanges[MM_FRAME_BUFFER_ACCESS_RANGE]; hwDeviceExtension->PhysicalFrameAddress = pAccessRanges->RangeStart; hwDeviceExtension->PhysicalFrameLength = pAccessRanges->RangeLength; hwDeviceExtension->PhysicalRegisterInIoSpace = pAccessRanges->RangeInIoSpace; // // Save the virtual frame buffer address information. // hwDeviceExtension->FrameAddress = MappedAddress[MM_FRAME_BUFFER_ACCESS_RANGE]; hwDeviceExtension->FrameLength = hwDeviceExtension->AdapterMemorySize; VideoDebugPrint ((DISPLVL, "Miniport - Physical Reg location= 0x%08X, Physical FB location=0x%08X \n" " Physical Reg size= %08d, Physical FB size= %08d \n", hwDeviceExtension->PhysicalRegisterAddress.LowPart, hwDeviceExtension->PhysicalFrameAddress.LowPart, hwDeviceExtension->PhysicalRegisterLength, hwDeviceExtension->PhysicalFrameLength )); VideoDebugPrint ((DISPLVL, "Miniport - Logical Reg address=0x%08X, Logical FB address=0x%08X \n" " Logical Reg size= %08d, Logical FB size= %08d \n", hwDeviceExtension->RegisterAddress, hwDeviceExtension->FrameAddress, hwDeviceExtension->RegisterLength, hwDeviceExtension->FrameLength )); // // We have this so that the int10 will also work on the VGA also if we // use it in this driver. // if( ! hwDeviceExtension->Dont_Do_VGA ) { ConfigInfo->VdmPhysicalVideoMemoryAddress.LowPart = 0x000A0000; ConfigInfo->VdmPhysicalVideoMemoryAddress.HighPart = 0x00000000; ConfigInfo->VdmPhysicalVideoMemoryLength = 0x00020000; } // // Clear out the Emulator entries and the state size since this driver // does not support them. // ConfigInfo->NumEmulatorAccessEntries = 0; ConfigInfo->EmulatorAccessEntries = NULL; ConfigInfo->EmulatorAccessEntriesContext = 0; // // This driver does not do SAVE/RESTORE of hardware state. // ConfigInfo->HardwareStateSize = 0; { BOOLEAN HDBrstEN = TRUE; // // Enable burst mode // HDBrstEN = CLEnablePciBurst(HwDeviceExtension); // // We now have a complete hardware description of the hardware. // Save the information to the registry so it can be used by // configuration programs - such as the display applet // CLWriteRegistryInfo(HwDeviceExtension, HDBrstEN); } // Always set AGPDataStreaming flag hwDeviceExtension->dwAGPDataStreamingFlag = 1; // // Here we prune valid modes, based on memory requirements. // It would be better if we could make the VESA call to determine // the modes that the BIOS supports; however, that requires a buffer // and it don't work with NT Int 10 support. // // We prune modes so that we will not annoy the user by presenting // modes in the 'Video Applet' which we know the user can't use. // CLValidateModes(HwDeviceExtension); CLPatchModeTable(HwDeviceExtension); // // If we're doing DMA, we need a page locked buffer. // ClAllocateCommonBuffer(HwDeviceExtension); // // Initial the power manager data // PMNT_Init(hwDeviceExtension); // // Get the monitor sync polarity. (now just use default) // hwDeviceExtension->dwPolarity = 0; // // Initialize the monitor state to "On". // hwDeviceExtension->MonitorEnabled = TRUE; // // Indicate we do not wish to be called over // *Again = 0; // // Indicate a successful completion status. // return NO_ERROR; } // end CLFindAdapter() /**************************************************************************** * FUNCTION NAME: CLInitialize() * * DESCRIPTION: * This routine does one time initialization of the device. * * REVISION HISTORY: * 5/30/95 Benny Ng Initial version ****************************************************************************/ BOOLEAN CLInitialize (PVOID HwDeviceExtension) { PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension; PAGED_CODE(); VideoDebugPrint((DISPLVL, "Miniport - CLInitialize\n")); return TRUE; } // end CLInitialize() #if 1 // PDR#11350 /**************************************************************************** * FUNCTION NAME: CLResetHw() * * DESCRIPTION: * This routine resets the hardware to mode 3. ****************************************************************************/ BOOLEAN CLResetHw( PHW_DEVICE_EXTENSION HwDeviceExtension, ULONG Columns, ULONG Rows ) { #undef LAGUNA_REGS #define LAGUNA_REGS HwDeviceExtension->RegisterAddress ULONG i; VOLATILE USHORT* pCursorControl = (USHORT*)(LAGUNA_REGS + 0x00E6); VideoDebugPrint((DISPLVL, "Miniport - CLResetHw\n")); // Disable the hardware cursor. *pCursorControl &= ~0x01; #if VS_CONTROL_HACK // Enable PCI configuration registers. CLEnablePCIConfigMMIO(HwDeviceExtension); #endif // Set the default text mode. if (resetmode != 0xFFFFFFFF) { VIDEO_MODE VideoMode; VideoMode.RequestedMode = resetmode; CLSetMode(HwDeviceExtension, &VideoMode); } return FALSE; // Let the HAL handle the VGA registers. } #endif //************************************************************************** // Enable or Disable the MMIO access // void VS_Control_Hack(PHW_DEVICE_EXTENSION HwDeviceExtension, BOOL Enable) { #if VS_CONTROL_HACK #undef LAGUNA_REGS #define LAGUNA_REGS HwDeviceExtension->RegisterAddress VOLATILE DWORD* pVS_CONTROL_reg = (DWORD*)(LAGUNA_REGS + 0x3FC); if (Enable) { CLEnablePCIConfigMMIO(HwDeviceExtension); } else { // Clear bit 0 to disable PCI register MMIO access *pVS_CONTROL_reg = *pVS_CONTROL_reg & 0xFFFFFFFE; } #endif // if VS_CONTROL_HACK } //************************************************************************** // Write value to VS_CLOCK_CONTROL register // void Output_To_VS_CLK_CONTROL(PHW_DEVICE_EXTENSION HwDeviceExtension, DWORD val) { #undef LAGUNA_REGS #define LAGUNA_REGS HwDeviceExtension->RegisterAddress VOLATILE DWORD* pVSCLK_CONTROL_reg = (DWORD*)(LAGUNA_REGS + 0x3F4); VOLATILE DWORD* pVS_CONTROL_reg = (DWORD*)(LAGUNA_REGS + 0x3FC); VS_Control_Hack(HwDeviceExtension, TRUE); // Enable VS_CLK_CONTROL write *pVS_CONTROL_reg = *pVS_CONTROL_reg | 0x800; *pVSCLK_CONTROL_reg = val; // Disable VS_CLK_CONTROL write *pVS_CONTROL_reg = *pVS_CONTROL_reg & 0xFFFFF7FF; VS_Control_Hack(HwDeviceExtension, FALSE); } /**************************************************************************** * FUNCTION NAME: PMNT_Init() * * DESCRIPTION: The routine initializes the PM internal variables. * * Return: None ****************************************************************************/ void PMNT_Init(PHW_DEVICE_EXTENSION hwDeviceExtension) { LGPWRMGR_DATA* pdata; DWORD clkdata; DWORD mask; int i; #undef LAGUNA_REGS #define LAGUNA_REGS hwDeviceExtension->RegisterAddress VOLATILE DWORD* pVSCLK_CONTROL_reg = (DWORD*)(LAGUNA_REGS + 0x3F4); // Points to the internal structure pdata = &(hwDeviceExtension->PMdata); pdata->wInitSignature = 0xA55A; pdata->VS_clk_ctl_state = 0; // Initial VS_CLK_CTL image clkdata = *pVSCLK_CONTROL_reg; pdata->VS_clk_ctl_state = clkdata & 0xFFFF; mask = 1; for (i=0; i < TOTAL_MOD; i++) { if ((clkdata & mask) != 0) pdata->Mod_refcnt[i] = 1; else pdata->Mod_refcnt[i] = 0; mask = mask << 1; }; // Set internal ACPI state to D0 state pdata->ACPI_state = ACPI_D0; return; }; // PMNT_Init /**************************************************************************** * FUNCTION NAME: PMNT_SetACPIState() * * DESCRIPTION: This routine sets to the specified ACPI state. * * Input: * state - ACPI states (ACPI_D0, ACPI_D1, ACPI_D2, ACPI_D3). * ****************************************************************************/ VP_STATUS PMNT_SetACPIState (PHW_DEVICE_EXTENSION hwDeviceExtension, ULONG state) { P_LGPWRMGR_DATA pdata; DWORD VS_clk_ctl_val; pdata = &(hwDeviceExtension->PMdata); // Returns FALSE if signature is invalid or invalid state number if ((pdata->wInitSignature != 0xA55A) || (state >= TOTAL_ACPI)) return ERROR_INVALID_PARAMETER; switch (state) { case ACPI_D0: { VS_clk_ctl_val = pdata->VS_clk_ctl_state; break; }; // case ACPI_D0 case ACPI_D1: case ACPI_D2: { VS_clk_ctl_val = ALWAYS_ON_VS_CLK_CTL; break; }; // case ACPI_D1 & ACPI_D2 case ACPI_D3: { VS_clk_ctl_val = 0; break; }; // case ACPI_D3 }; // end switch // Output the VS_CLK_CONTROL Output_To_VS_CLK_CONTROL(hwDeviceExtension, VS_clk_ctl_val); // Update internal ACPI state pdata->ACPI_state = state; return NO_ERROR; }; // PMNT_SetACPIState /**************************************************************************** * FUNCTION NAME: PMNT_GetACPIState() * * DESCRIPTION: This API returns the current ACPI state in use * * Input: * state - Pointer to ULONG variable for returning ACPI state * (ACPI_D0, ACPI_D1, ACPI_D2, ACPI_D3). * ****************************************************************************/ VP_STATUS PMNT_GetACPIState (PHW_DEVICE_EXTENSION hwDeviceExtension, ULONG* state) { P_LGPWRMGR_DATA pdata; pdata = &(hwDeviceExtension->PMdata); // Returns FALSE if signature is invalid if (pdata->wInitSignature != 0xA55A) return ERROR_INVALID_PARAMETER; *state = pdata->ACPI_state; return NO_ERROR; }; // PMNT_GetACPIState /**************************************************************************** * FUNCTION NAME: PMNT_SetHwModuleState() * * DESCRIPTION: This routine validates the request for any conflict between * the request and the current chip operation. If it is valid, * it will enable or disable the specified HW module by turning * on or off appropriate HW clocks and returns NO_ERROR. If it is * invalid or there is a conflict to the current chip operation, * it ignores the request and return FAIL. * * Input: * hwmod - can be one of the following HW modules * MOD_2D * MOD_3D * MOD_TVOUT * MOD_VPORT * MOD_VGA * MOD_EXTMODE * MOD_STRETCH * * state - Ether ENABLE or DISABLE. * *****************************************************************************/ VP_STATUS PMNT_SetHwModuleState (PHW_DEVICE_EXTENSION hwDeviceExtension, ULONG hwmod, ULONG state) { P_LGPWRMGR_DATA pdata; pdata = &(hwDeviceExtension->PMdata); // Returns FALSE if signature is invalid || invalid module number if ((pdata->wInitSignature != 0xA55A) || (hwmod >= TOTAL_MOD)) return ERROR_INVALID_PARAMETER; // Returns FALSE if ACPI state is not in D0 state if (pdata->ACPI_state != ACPI_D0) return ERROR_INVALID_FUNCTION; // Perform the operation on VS_CLK_CONTROL if (state == ENABLE) { // Enable the module pdata->VS_clk_ctl_state |= LgPM_vs_clk_table[hwmod]; if (pdata->Mod_refcnt[hwmod] != 0xFFFFFFFF) pdata->Mod_refcnt[hwmod]++; } else { // Disable the module if (pdata->Mod_refcnt[hwmod] != 0) { pdata->Mod_refcnt[hwmod]--; if (pdata->Mod_refcnt[hwmod] == 0) pdata->VS_clk_ctl_state &= (~LgPM_vs_clk_table[hwmod]); }; // endif (Mod_refcnt[hwmod] != 0) }; // endif (state == ENABLE) // Output the VS_CLK_CONTROL Output_To_VS_CLK_CONTROL(hwDeviceExtension, pdata->VS_clk_ctl_state); return NO_ERROR; }; // PMNT_SetHwModuleState /**************************************************************************** * FUNCTION NAME: PMNT_GetHwModuleState() * * DESCRIPTION: This routine returns the current state of a particular * hardware module. * * Input: * hwmod - can be one of the following HW modules * MOD_2D * MOD_3D * MOD_TVOUT * MOD_VPORT * MOD_VGA * MOD_EXTMODE * MOD_STRETCH * * state - Pointer to ULONG variable for returning the HW module state * (ENABLE or DISABLE). * ****************************************************************************/ VP_STATUS PMNT_GetHwModuleState (PHW_DEVICE_EXTENSION hwDeviceExtension, ULONG hwmod, ULONG* state) { P_LGPWRMGR_DATA pdata; pdata = &(hwDeviceExtension->PMdata); *state = DISABLE; // Returns FALSE if signature is invalid || invalid module number if ((pdata->wInitSignature != 0xA55A) || (hwmod >= TOTAL_MOD)) return ERROR_INVALID_PARAMETER; // Returns FALSE if ACPI state is not in D0 state if (pdata->ACPI_state != ACPI_D0) return ERROR_INVALID_FUNCTION; if (pdata->Mod_refcnt[hwmod] != 0) *state = ENABLE; return NO_ERROR; }; // PMNT_GetHwModuleState /**************************************************************************** * FUNCTION NAME: PMNT_Close() * * DESCRIPTION: This routine closes down the power management module. * ****************************************************************************/ void PMNT_Close (PHW_DEVICE_EXTENSION hwDeviceExtension) { P_LGPWRMGR_DATA pdata; pdata = &(hwDeviceExtension->PMdata); // Returns FALSE if signature is invalid if (pdata->wInitSignature != 0xA55A) return; pdata->wInitSignature = 0x0; }; // PMNT_Close /**************************************************************************** * FUNCTION NAME: CLStartIO() * * DESCRIPTION: * This routine is the main execution routine for the miniport driver. It * accepts a Video Request Packet, performs the request, and then returns * with the appropriate status. * * REVISION HISTORY: * 5/30/95 Benny Ng Initial version ****************************************************************************/ BOOLEAN CLStartIO (PVOID HwDeviceExtension, PVIDEO_REQUEST_PACKET RequestPacket) { VP_STATUS status; PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension; PVIDEO_POWER_MANAGEMENT PMInformation; PVIDEO_MODE_INFORMATION modeInformation; PVIDEO_MEMORY_INFORMATION memoryInformation; VIDEO_MODE videoMode; PVIDEO_PUBLIC_ACCESS_RANGES portAccess; PVIDEO_MEMORY mappedMemory; PMODETABLE pVideoMode; ULONG inIoSpace; ULONG i; PHYSICAL_ADDRESS AdjFBAddr; ULONG AdjFBLength; ULONG ReservedFBLength; VOLATILE PUCHAR pOffset2D_reg; ULONG FBOffset; ULONG Temp; PVIDEO_SHARE_MEMORY pShareMemory; PVIDEO_SHARE_MEMORY_INFORMATION pShareMemoryInformation; PHYSICAL_ADDRESS shareAddress; PVOID virtualAddress; ULONG sharedViewSize; PAGED_CODE(); // // If the current power state is VideoPowerOff, fails all // IOCTL_VIDEO_XXX requests until the IOCTL_VIDEO_SET_POWER_MANAGEMENT // request that resets to a power-on condition // if ((hwDeviceExtension->PowerState == VideoPowerOff)) { VideoDebugPrint((DISPLVL, "Miniport - PowerOff\n")); return FALSE; }; // // Switch on the IoContolCode in the RequestPacket. It indicates which // function must be performed by the driver. // switch (RequestPacket->IoControlCode) { //----------------------------------------------------- #if 0 // not supported anymore //----------------------------------------------------- case IOCTL_GET_BIOS_VERSION: { WORD *pOut = (WORD *) RequestPacket->OutputBuffer; if ((RequestPacket->OutputBufferLength < (RequestPacket->StatusBlock->Information = sizeof(WORD)))) { status = ERROR_INSUFFICIENT_BUFFER; break; }; *pOut = hwDeviceExtension->BIOSVersion; status = NO_ERROR; break; }; // end case IOCTL_GET_BIOS_VERSION //----------------------------------------------------- case IOCTL_SET_HW_MODULE_POWER_STATE: { PLGPM_IN_STRUCT pInLGPM; PLGPM_OUT_STRUCT pOutLGPM; if ((RequestPacket->OutputBufferLength < (RequestPacket->StatusBlock->Information = sizeof(PLGPM_OUT_STRUCT))) || (RequestPacket->InputBufferLength < sizeof(LGPM_IN_STRUCT))) { status = ERROR_INSUFFICIENT_BUFFER; break; }; pInLGPM = (PLGPM_IN_STRUCT) RequestPacket->InputBuffer; pOutLGPM = (PLGPM_OUT_STRUCT) RequestPacket->OutputBuffer; status = PMNT_SetHwModuleState (hwDeviceExtension, pInLGPM->arg1, pInLGPM->arg2); break; }; // end case IOCTL_SET_HW_MODULE_POWER_STATE //----------------------------------------------------- case IOCTL_GET_HW_MODULE_POWER_STATE: { PLGPM_IN_STRUCT pInLGPM; PLGPM_OUT_STRUCT pOutLGPM; if ((RequestPacket->OutputBufferLength < (RequestPacket->StatusBlock->Information = sizeof(PLGPM_OUT_STRUCT))) || (RequestPacket->InputBufferLength < sizeof(LGPM_IN_STRUCT))) { status = ERROR_INSUFFICIENT_BUFFER; break; }; pInLGPM = (PLGPM_IN_STRUCT) RequestPacket->InputBuffer; pOutLGPM = (PLGPM_OUT_STRUCT) RequestPacket->OutputBuffer; status = PMNT_GetHwModuleState (hwDeviceExtension, pInLGPM->arg1, (ULONG*) pInLGPM->arg2); break; }; // end case IOCTL_GET_HW_MODULE_POWER_STATE #endif// 0 // not supported anymore //----------------------------------------------------- case IOCTL_GET_AGPDATASTREAMING: { DWORD *pOut = (DWORD *) RequestPacket->OutputBuffer; if ((RequestPacket->OutputBufferLength < (RequestPacket->StatusBlock->Information = sizeof(DWORD)))) { status = ERROR_INSUFFICIENT_BUFFER; break; }; *pOut = hwDeviceExtension->dwAGPDataStreamingFlag; status = NO_ERROR; break; }; // end case IOCTL_GET_AGPDATASTREAMING //----------------------------------------------------- case IOCTL_VIDEO_SHARE_VIDEO_MEMORY: VideoDebugPrint((DISPLVL, "Miniport - ShareVideoMemory\n")); #ifdef DBGBRK DbgBreakPoint(); #endif if ( (RequestPacket->OutputBufferLength < sizeof(VIDEO_SHARE_MEMORY_INFORMATION)) || (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))) { VideoDebugPrint((1, "Miniport - SHARE_VIDEO_MEM-INSUFFICIENT_BUF\n")); status = ERROR_INSUFFICIENT_BUFFER; break; }; pShareMemory = RequestPacket->InputBuffer; #if 0 // extra rectangle at bottom makes this more complex, I'm taking the // easy way out and assume that the display driver is asking for // a reasonable ammount of space if ((pShareMemory->ViewOffset > hwDeviceExtension->AdapterMemorySize) || ((pShareMemory->ViewOffset + pShareMemory->ViewSize) > hwDeviceExtension->AdapterMemorySize)) { VideoDebugPrint((1, "Miniport - SHARE_VIDEO_MEM-INVALID_PARAM\n")); status = ERROR_INVALID_PARAMETER; break; }; #endif RequestPacket->StatusBlock->Information = sizeof(VIDEO_SHARE_MEMORY_INFORMATION); // Beware: the input buffer and the output buffer are the same // buffer, and therefore data should not be copied from one to the // other // virtualAddress = pShareMemory->ProcessHandle; sharedViewSize = pShareMemory->ViewSize; inIoSpace = 0; // Enable the USWC on the P6 processor #ifdef VIDEO_MEMORY_SPACE_P6CACHE if (hwDeviceExtension->ChipID != CL_GD5462) inIoSpace |= VIDEO_MEMORY_SPACE_P6CACHE; #endif // NOTE: we are ignoring ViewOffset // shareAddress.QuadPart = hwDeviceExtension->PhysicalFrameAddress.QuadPart; status = VideoPortMapMemory(hwDeviceExtension, shareAddress, &sharedViewSize, &inIoSpace, &virtualAddress); pShareMemoryInformation = RequestPacket->OutputBuffer; pShareMemoryInformation->SharedViewOffset = pShareMemory->ViewOffset; pShareMemoryInformation->VirtualAddress = virtualAddress; pShareMemoryInformation->SharedViewSize = sharedViewSize; break; //----------------------------------------------------- case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY: VideoDebugPrint((DISPLVL, "Miniport - UnshareVideoMemory\n")); #ifdef DBGBRK DbgBreakPoint(); #endif if (RequestPacket->InputBufferLength < sizeof(VIDEO_SHARE_MEMORY)) { status = ERROR_INSUFFICIENT_BUFFER; break; }; pShareMemory = RequestPacket->InputBuffer; status = VideoPortUnmapMemory(hwDeviceExtension, pShareMemory->RequestedVirtualAddress, pShareMemory->ProcessHandle); break; //----------------------------------------------------- case IOCTL_VIDEO_MAP_VIDEO_MEMORY: VideoDebugPrint((DISPLVL, "Miniport - MapVideoMemory\n")); #ifdef DBGBRK DbgBreakPoint(); #endif if ((RequestPacket->OutputBufferLength < (RequestPacket->StatusBlock->Information = sizeof(VIDEO_MEMORY_INFORMATION))) || (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))) { status = ERROR_INSUFFICIENT_BUFFER; break; }; memoryInformation = RequestPacket->OutputBuffer; memoryInformation->VideoRamBase = ((PVIDEO_MEMORY) (RequestPacket->InputBuffer))->RequestedVirtualAddress; // // Adjust the FB starting address and size based on OFFSET_2D // pOffset2D_reg = hwDeviceExtension->RegisterAddress + OFFSET_2D_REG; FBOffset = ((ULONG) *pOffset2D_reg) & 0xFF; VideoDebugPrint((DISPLVL, "Miniport - OFFSET_2D=%xH\n", FBOffset)); Temp = hwDeviceExtension->CurrentMode->BytesPerScanLine; FBOffset = (FBOffset * 64) * Temp; AdjFBAddr = hwDeviceExtension->PhysicalFrameAddress; AdjFBAddr.LowPart += FBOffset; ReservedFBLength = hwDeviceExtension->PhysicalFrameLength; // v-normmi added room for extra rectangle at bottom left if (ReservedFBLength < 0x800000) { ReservedFBLength += (Temp*4*32); // pitch * 4 max height tiles } // // Do memory mapping // inIoSpace = 0; // Enable the USWC on the P6 processor #ifdef VIDEO_MEMORY_SPACE_P6CACHE if (hwDeviceExtension->ChipID != CL_GD5462) inIoSpace |= VIDEO_MEMORY_SPACE_P6CACHE; #endif status = VideoPortMapMemory(hwDeviceExtension, AdjFBAddr, &ReservedFBLength, &inIoSpace, &(memoryInformation->VideoRamBase)); // // The frame buffer and virtual memory are equivalent in this // case. // memoryInformation->FrameBufferBase = memoryInformation->VideoRamBase; // // This is the *real* amount of memory on the board. // This gets reported back to the display driver. // AdjFBLength = hwDeviceExtension->FrameLength - FBOffset; memoryInformation->VideoRamLength = AdjFBLength; memoryInformation->FrameBufferLength = AdjFBLength; VideoDebugPrint((DISPLVL, "Miniport - DD FB virtual spac=%xH\n", memoryInformation->FrameBufferBase)); break; //----------------------------------------------------- case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY: VideoDebugPrint((DISPLVL, "Miniport - UnMapVideoMemory\n")); #ifdef DBGBRK DbgBreakPoint(); #endif if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) { status = ERROR_INSUFFICIENT_BUFFER; break; }; status = VideoPortUnmapMemory(hwDeviceExtension, ((PVIDEO_MEMORY) (RequestPacket->InputBuffer))->RequestedVirtualAddress, 0); break; //----------------------------------------------------- case IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES: VideoDebugPrint((DISPLVL, "Miniport - QueryPublicAccessRanges\n")); #ifdef DBGBRK DbgBreakPoint(); #endif if (RequestPacket->OutputBufferLength < (RequestPacket->StatusBlock->Information = sizeof(VIDEO_PUBLIC_ACCESS_RANGES))) { status = ERROR_INSUFFICIENT_BUFFER; break; }; portAccess = RequestPacket->OutputBuffer; portAccess->VirtualAddress = (PVOID) NULL; // Requested VA portAccess->InIoSpace = FALSE; portAccess->MappedInIoSpace = portAccess->InIoSpace; status = VideoPortMapMemory(hwDeviceExtension, hwDeviceExtension->PhysicalRegisterAddress, &hwDeviceExtension->RegisterLength, &portAccess->MappedInIoSpace, &portAccess->VirtualAddress); VideoDebugPrint((DISPLVL, "Miniport - DD Reg virtual spac=%xH\n", portAccess->VirtualAddress)); break; //----------------------------------------------------- case IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES: VideoDebugPrint((DISPLVL, "Miniport - FreePublicAccessRanges\n")); #ifdef DBGBRK DbgBreakPoint(); #endif if (RequestPacket->InputBufferLength < 2 * sizeof(VIDEO_MEMORY)) { status = ERROR_INSUFFICIENT_BUFFER; break; }; status = NO_ERROR; mappedMemory = RequestPacket->InputBuffer; for (i = 0; i < 2; i++) { if (mappedMemory->RequestedVirtualAddress != NULL) { status = VideoPortUnmapMemory(hwDeviceExtension, mappedMemory->RequestedVirtualAddress, 0); }; mappedMemory++; } // end for break; //----------------------------------------------------- case IOCTL_VIDEO_QUERY_AVAIL_MODES: VideoDebugPrint((DISPLVL, "Miniport - QueryAvailableModes\n")); #ifdef DBGBRK DbgBreakPoint(); #endif if (RequestPacket->OutputBufferLength < (RequestPacket->StatusBlock->Information = hwDeviceExtension->NumAvailableModes * sizeof(VIDEO_MODE_INFORMATION))) { status = ERROR_INSUFFICIENT_BUFFER; break; }; modeInformation = (PVIDEO_MODE_INFORMATION) RequestPacket->OutputBuffer; // // For each mode supported by the card, store the mode characteristics // in the output buffer. // for (i = 0; i < TotalVideoModes; i++) { // Points to the selected mode table slot // pVideoMode = &ModeTable[i]; // Check whether the mode is valid // if (pVideoMode->ValidMode) { // // Copy the selected mode information into the // VIDEO_MODE_INFORMATION structure buffer. // CLCopyModeInfo(HwDeviceExtension, modeInformation, i, pVideoMode); // // Points to next VIDEO_MODE_INFORMATION structure slot // modeInformation++; }; } /* end for */ status = NO_ERROR; break; //----------------------------------------------------- case IOCTL_VIDEO_QUERY_CURRENT_MODE: VideoDebugPrint((DISPLVL, "Miniport - QueryCurrentModes\n")); #ifdef DBGBRK DbgBreakPoint(); #endif // // Find out the size of the data to be put in the the buffer and return // that in the status information (whether or not the information is // there). If the buffer passed in is not large enough return an // appropriate error code. // if (RequestPacket->OutputBufferLength < (RequestPacket->StatusBlock->Information = sizeof(VIDEO_MODE_INFORMATION))) { status = ERROR_INSUFFICIENT_BUFFER; break; }; // // check if a mode has been set // if (hwDeviceExtension->CurrentMode == NULL) { status = ERROR_INVALID_FUNCTION; break; }; modeInformation = (PVIDEO_MODE_INFORMATION) RequestPacket->OutputBuffer; // Copy the selected mode information into the // VIDEO_MODE_INFORMATION structure provided by NT. // CLCopyModeInfo(hwDeviceExtension, modeInformation, hwDeviceExtension->CurrentModeNum, hwDeviceExtension->CurrentMode); status = NO_ERROR; break; //----------------------------------------------------- case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES: VideoDebugPrint((DISPLVL, "Miniport - QueryNumAvailableModes\n")); #ifdef DBGBRK DbgBreakPoint(); #endif // // Find out the size of the data to be put in the the buffer and // return that in the status information (whether or not the // information is there). If the buffer passed in is not large // enough return an appropriate error code. // if (RequestPacket->OutputBufferLength < (RequestPacket->StatusBlock->Information = sizeof(VIDEO_NUM_MODES))) { status = ERROR_INSUFFICIENT_BUFFER; break; }; ((PVIDEO_NUM_MODES)RequestPacket->OutputBuffer)->NumModes = hwDeviceExtension->NumAvailableModes; ((PVIDEO_NUM_MODES)RequestPacket->OutputBuffer)->ModeInformationLength = sizeof(VIDEO_MODE_INFORMATION); status = NO_ERROR; break; //----------------------------------------------------- case IOCTL_VIDEO_SET_COLOR_REGISTERS: VideoDebugPrint((DISPLVL, "Miniport - SetColorRegs\n")); #ifdef DBGBRK DbgBreakPoint(); #endif status = CLSetColorLookup(HwDeviceExtension, (PVIDEO_CLUT) RequestPacket->InputBuffer, RequestPacket->InputBufferLength); break; //----------------------------------------------------- case IOCTL_VIDEO_SET_CURRENT_MODE: VideoDebugPrint((DISPLVL, "Miniport - SetCurrentMode\n")); #ifdef DBGBRK DbgBreakPoint(); #endif // // Check if the size of the data in the input buffer is large enough. // if (RequestPacket->InputBufferLength < sizeof(VIDEO_MODE)) { status = ERROR_INSUFFICIENT_BUFFER; break; }; status = CLSetMode(HwDeviceExtension, (PVIDEO_MODE) RequestPacket->InputBuffer); break; //----------------------------------------------------- case IOCTL_VIDEO_RESET_DEVICE: VideoDebugPrint((DISPLVL, "Miniport - ResetDevice\n")); #if VS_CONTROL_HACK CLEnablePCIConfigMMIO(HwDeviceExtension); #endif #ifdef DBGBRK DbgBreakPoint(); #endif if ( ! hwDeviceExtension->Dont_Do_VGA ) // Only if VGA regs are available. { // Initialize the DAC to 0 (black). // // Turn off the screen at the DAC. // VideoPortWritePortUchar((PUCHAR) 0x3c6, (UCHAR) 0x0); for (i = 0; i < 256; i++) { VideoPortWritePortUchar((PUCHAR) 0x3c8, (UCHAR) i); VideoPortWritePortUchar((PUCHAR) 0x3c9, (UCHAR) 0); VideoPortWritePortUchar((PUCHAR) 0x3c9, (UCHAR) 0); VideoPortWritePortUchar((PUCHAR) 0x3c9, (UCHAR) 0); } // end for // // Turn on the screen at the DAC // VideoPortWritePortUchar((PUCHAR) 0x3c6, (UCHAR) 0xFF); } videoMode.RequestedMode = resetmode; // mode.ini //videoMode.RequestedMode = DEFAULT_MODE; // BIOS status = CLSetMode(HwDeviceExtension, (PVIDEO_MODE) &videoMode); break; #if 0 // not supported anymore //----------------------------------------------------- case IOCTL_VIDEO_GET_POWER_MANAGEMENT: VideoDebugPrint((DISPLVL, "Miniport - GetPowerManagement\n")); #ifdef DBGBRK DbgBreakPoint(); #endif // // Find out the size of the data to be put in the the buffer and return // that in the status information (whether or not the information is // there). If the buffer passed in is not large enough return an // appropriate error code. // if (RequestPacket->OutputBufferLength < (RequestPacket->StatusBlock->Information = sizeof(VIDEO_POWER_MANAGEMENT))) { status = ERROR_INSUFFICIENT_BUFFER; break; }; PMInformation = (PVIDEO_POWER_MANAGEMENT) RequestPacket->OutputBuffer; status = CLPowerManagement(HwDeviceExtension, PMInformation, FALSE); break; //----------------------------------------------------- case IOCTL_CL_STRING_DISPLAY: VideoDebugPrint((DISPLVL, "Miniport - StringDisplay\n")); #ifdef DBGBRK DbgBreakPoint(); #endif HalDisplayString((PUCHAR) RequestPacket->InputBuffer); status = NO_ERROR; break; #endif// 0 // not supported anymore // ---------------------------------------------------------------- case IOCTL_CL_GET_COMMON_BUFFER: { // // Communicate to the display driver the location and size of the // common DMA buffer. // // The display driver gives us a pointer to this structure. // We fill in the values here. // // struct { // PUCHAR PhysAddress; // PUCHAR VirtAddress; // ULONG Length; // } *pCommonBufferInfo; COMMON_BUFFER_INFO *pCommonBufferInfo; VideoDebugPrint((DISPLVL, "Miniport - Get Common Buffer.\n")); RequestPacket->StatusBlock->Information = sizeof(COMMON_BUFFER_INFO); if (RequestPacket->OutputBufferLength < sizeof(COMMON_BUFFER_INFO)) { VideoDebugPrint((DISPLVL, "Miniport - Buffer size mismatch.\n")); status = ERROR_INSUFFICIENT_BUFFER; break; } // // Retrieve pointer to CommonBufferInfo struct. // pCommonBufferInfo = (COMMON_BUFFER_INFO *)(RequestPacket->OutputBuffer); // // Fill it in. // pCommonBufferInfo->PhysAddress = hwDeviceExtension->PhysicalCommonBufferAddr; pCommonBufferInfo->VirtAddress = hwDeviceExtension->VirtualCommonBufferAddr; pCommonBufferInfo->Length = hwDeviceExtension->CommonBufferSize; status = NO_ERROR; } break; #if VS_CONTROL_HACK // ---------------------------------------------------------------- case IOCTL_VIDEO_ENABLE_PCI_MMIO: { status = CLEnablePCIConfigMMIO(HwDeviceExtension); break; } #endif // VS_CONTROL_HACK #if LOG_FILE // ---------------------------------------------------------------- case IOCTL_CL_CREATE_LOG_FILE: { LogFileHandle = CreateLogFile(); status = NO_ERROR; } break; // ---------------------------------------------------------------- case IOCTL_CL_WRITE_LOG_FILE: { WriteLogFile(LogFileHandle, RequestPacket->InputBuffer, RequestPacket->InputBufferLength); status = NO_ERROR; } break; // ---------------------------------------------------------------- case IOCTL_CL_CLOSE_LOG_FILE: { CloseLogFile(LogFileHandle); status = NO_ERROR; } break; #endif #if 1 // ---------------------------------------------------------------- case IOCTL_STALL: { VideoPortStallExecution(*(PULONG) RequestPacket->InputBuffer); status = NO_ERROR; } break; #endif //----------------------------------------------------- // if we get here, an invalid IoControlCode was specified. // default: VideoDebugPrint((DISPLVL, "Miniport - invalid command= %xH\n", RequestPacket->IoControlCode)); #ifdef DBGBRK DbgBreakPoint(); #endif status = ERROR_INVALID_FUNCTION; break; } // end switch RequestPacket->StatusBlock->Status = status; return TRUE; } // end CLStartIO() /**************************************************************************** * FUNCTION NAME: CLSetColorLookup() * * DESCRIPTION: * This routine sets a specified portion of the color lookup table settings. * * REVISION HISTORY: * 5/30/95 Benny Ng Initial version ****************************************************************************/ VP_STATUS CLSetColorLookup (PHW_DEVICE_EXTENSION HwDeviceExtension, PVIDEO_CLUT ClutBuffer, ULONG ClutBufferSize) { USHORT i; USHORT FirstEntry; #undef LAGUNA_REGS #define LAGUNA_REGS HwDeviceExtension->RegisterAddress VOLATILE BYTE* pPal_Addr_Reg = (BYTE*)(LAGUNA_REGS + 0xA8); VOLATILE BYTE* pPal_Data_Reg = (BYTE*)(LAGUNA_REGS + 0xAC); ULONG cCounter = 0; PAGED_CODE(); // // Check if the size of the data in the input buffer is large enough. // if ((ClutBufferSize < sizeof(VIDEO_CLUT) - sizeof(ULONG)) || (ClutBufferSize < sizeof(VIDEO_CLUT) + (sizeof(ULONG) * (ClutBuffer->NumEntries - 1)))) { return ERROR_INSUFFICIENT_BUFFER; }; // // Check to see if the parameters are valid. // if ((ClutBuffer->NumEntries == 0) || (ClutBuffer->FirstEntry > VIDEO_MAX_COLOR_REGISTER) || (ClutBuffer->FirstEntry + ClutBuffer->NumEntries > VIDEO_MAX_COLOR_REGISTER + 1)) { return ERROR_INVALID_PARAMETER; }; // // Set CLUT registers directly on the hardware // FirstEntry = ClutBuffer->FirstEntry; for (i = 0; i < ClutBuffer->NumEntries; i++) { // Wait for blanking if ((HwDeviceExtension->Dont_Do_VGA == FALSE) && (HwDeviceExtension->MonitorEnabled == TRUE)) // Only wait for blanking if VGA regs are available. { #if 1 // PDR#11284 if (cCounter-- == 0) { // Wait for end of vertical retrace. while (VideoPortReadPortUchar((PUCHAR) 0x3DA) & 0x08) ; // Wait for beginning of display disable. while( (VideoPortReadPortUchar((PUCHAR) 0x3DA) & 0x01)) ; while(! (VideoPortReadPortUchar((PUCHAR) 0x3DA) & 0x01)) ; // Load the counter. cCounter = (VideoPortReadPortUchar((PUCHAR) 0x3DA) & 0x08) ? 256 : 0; } #else // Wait for bit-0 becomes 0 while(1) { unsigned char stat; stat = VideoPortReadPortUchar( (PUCHAR)0x3DA ); if (!(stat & 1)) // Test bit 0. If it's a 0 break; // then continue. } // Wait for bit-0 becomes 1 while(1) { unsigned char stat; stat = VideoPortReadPortUchar( (PUCHAR)0x3DA ); if (stat & 1) // Test bit 0. If it's a 1 break; // then continue. } #endif } // Write the entry. *pPal_Addr_Reg = (UCHAR) (FirstEntry + i); *pPal_Data_Reg = (UCHAR) (ClutBuffer->LookupTable[i].RgbArray.Red); *pPal_Data_Reg = (UCHAR) (ClutBuffer->LookupTable[i].RgbArray.Green); *pPal_Data_Reg = (UCHAR) (ClutBuffer->LookupTable[i].RgbArray.Blue); } // end for return NO_ERROR; } // end CLSetColorLookup() /**************************************************************************** * FUNCTION NAME: CLFindVmemSize() * * DESCRIPTION: * This routine returns the amount of RAM installed on the card. * * REVISION HISTORY: * 5/30/95 Benny Ng Initial version ****************************************************************************/ ULONG CLFindVmemSize (PHW_DEVICE_EXTENSION HwDeviceExtension) { UCHAR OrigSRindex; ULONG memsize; #define LAGUNA_REGS HwDeviceExtension->RegisterAddress VOLATILE USHORT* pRIF_reg = (USHORT*)(LAGUNA_REGS + 0x200); PAGED_CODE(); /* 1.) If 62 or 64 or 65 AC or below Lower 3 bits of RIF is the number of banks -1. Add one and multiply by 1MB 2.) If 65 AD then some bits in the RIF have changed Then bits 15:14 have been overloaded MEM_TYPE == 00b --- use step 1 MEM_TYPE == 01b --- use step 1 MEM_TYPE == 10b or MEM_TYPE == 11b then Lower 3 bits of RIF is the number of banks -1. Add one and multiply by 2MB. */ memsize = *pRIF_reg; // get RIF register. memsize = memsize & 7; // keep lowest 3 bits. memsize = memsize + 1; // Add 1 to get number of banks. memsize = memsize * 1024 * 1024; // multiply by 1 meg per bank. // // If the chip is 5465AD or later, adjust the memory size. // if ((HwDeviceExtension->ChipID > CL_GD5465) || ((HwDeviceExtension->ChipID==CL_GD5465)&&(HwDeviceExtension->ChipRev>1))) { unsigned long mem_type = *pRIF_reg; mem_type = mem_type >> 14; if (mem_type >= 2) memsize *= 2; // 2 megabytes per bank. } VideoDebugPrint((DISPLVL, "Miniport - AdapterMemorySize= 0x%X (%d meg)\n", memsize, memsize/(1024*1024))); // // Return the Number of bytes of RAM installed. // return (memsize); } // CirrusFindVmemSize() /**************************************************************************** * FUNCTION NAME: CLWriteRegistryInfo() * * DESCRIPTION: * Write hardware information to registry. * * REVISION HISTORY: * 5/30/95 Benny Ng Initial version ****************************************************************************/ VOID CLWriteRegistryInfo (PHW_DEVICE_EXTENSION hwDeviceExtension, BOOLEAN hdbrsten) { PWSTR pszString; ULONG cbString; PAGED_CODE(); VideoDebugPrint((DISPLVL, "Miniport - CLWriteRegestryInfo.\n")); // Store Memory Size VideoPortSetRegistryParameters(hwDeviceExtension, L"HardwareInformation.MemorySize", &hwDeviceExtension->AdapterMemorySize, sizeof(ULONG)); // Store chip Type if (hwDeviceExtension->ChipID == CL_GD5462) { pszString = L"Cirrus Logic 5462"; cbString = sizeof(L"Cirrus Logic 5462"); } else if (hwDeviceExtension->ChipID == CL_GD5464) { pszString = L"Cirrus Logic 5464"; cbString = sizeof(L"Cirrus Logic 5464"); } else if (hwDeviceExtension->ChipID == CL_GD5465) { pszString = L"Cirrus Logic 5465"; cbString = sizeof(L"Cirrus Logic 5465"); } else { pszString = L"Cirrus Logic 546x"; cbString = sizeof(L"Cirrus Logic 546x"); } VideoPortSetRegistryParameters(hwDeviceExtension, L"HardwareInformation.ChipType", pszString, cbString); // Store DAC Type pszString = L"Internal"; cbString = sizeof(L"Internal"); VideoPortSetRegistryParameters(hwDeviceExtension, L"HardwareInformation.DacType", pszString, cbString); // Store Adapter String pszString = L"Cirrus Logic VisualMedia(TM) Accelerator"; cbString = sizeof(L"Cirrus Logic VisualMedia(TM) Accelerator"); VideoPortSetRegistryParameters(hwDeviceExtension, L"HardwareInformation.AdapterString", pszString, cbString); // HD BRST EN if (hdbrsten) { pszString = L"1"; cbString = sizeof(L"1"); } else { pszString = L"0"; cbString = sizeof(L"0"); }; VideoPortSetRegistryParameters(hwDeviceExtension, L"HardwareInformation.HdBrstEn", pszString, cbString); VideoDebugPrint((DISPLVL, "Miniport - CLWriteRegestryInfo - Exit.\n")); } // end CLWriteRegistryInfo() // Verify the BIOS ID. // At offset 001e these is a string that says "IBM VGA Compatible". // #define CheckBiosID(BiosAddress) \ ( ( *(BiosAddress+0x1E) == 'I') \ && ( *(BiosAddress+0x1F) == 'B') \ && ( *(BiosAddress+0x20) == 'M') \ && ( *(BiosAddress+0x21) == ' ') \ && ( *(BiosAddress+0x22) == 'V') \ && ( *(BiosAddress+0x23) == 'G') \ && ( *(BiosAddress+0x24) == 'A') \ && ( *(BiosAddress+0x25) == ' ') \ && ( *(BiosAddress+0x26) == 'C') \ && ( *(BiosAddress+0x27) == 'o') \ && ( *(BiosAddress+0x28) == 'm') \ && ( *(BiosAddress+0x29) == 'p') \ && ( *(BiosAddress+0x2A) == 'a') \ && ( *(BiosAddress+0x2B) == 't') \ && ( *(BiosAddress+0x2C) == 'i') \ && ( *(BiosAddress+0x2D) == 'b') \ && ( *(BiosAddress+0x2E) == 'l') \ && ( *(BiosAddress+0x2F) == 'e') \ ) \ /**************************************************************************** * FUNCTION NAME: CLPatchModeTable() * * DESCRIPTION: * This routine patches the ModeTable with info from the BIOS * * MUST be called AFTER ClValidateModes! * ****************************************************************************/ VOID CLPatchModeTable (PHW_DEVICE_EXTENSION HwDeviceExtension) { unsigned long index; unsigned char *BiosAddress; // Pointer to start of BIOS. ULONG SupParms; // Offset of SUpplimental parameter table. unsigned char s_TPL; // Tiles per line. unsigned char s_TFIFO; // Tiled display and threshold fifo. USHORT TileWidth; // Tile width. 128 or 256. USHORT FB_Pitch; // Frame buffer pitch. VIDEO_X86_BIOS_ARGUMENTS biosregs; PHYSICAL_ADDRESS PhysAddr; // Our Video Bios PAGED_CODE(); VideoDebugPrint((DISPLVL, "Miniport - PatchModeTable.\n")); if (HwDeviceExtension->Dont_Do_VGA) { VideoDebugPrint((DISPLVL, "Miniport - PatchModeTable - No VGA! - Exit.\n")); return; } // // NVH // We're going to do something weird here. // The scan line lengths in the mode table entries in MTBL.C // may not be right. So before we copy the mode info into NT, we are // going to query the BIOS and patch the mode table entry if necessary. // When we query the BIOS, it will hand us a 16 bit pointer // in ES:DI that points to the supplimental parameter table // for the mode we are interested in. From there we will get the // information we need to patch the ModeTable in MTBL.C // The tricky part is that VideoPortInt10 does not provide a way // for the BIOS to pass back DS. // A chat with the BIOS author revealed that DS will always be // either 0xC000 or 0xE000. So we convert physical address 0x000C0000 // into a 32 bit pointer with VideoPortGetDeviceBase(), and then look // at it to see if it points to the BIOS. If not, we try again with // 0x000E0000 // Once we locate our BIOS we make BIOS call, and add the returned // value of DI to our BIOS pointer, and viola! we have a usable pointer // to the supplimental parameter table in the BIOS. // // Someday I will have to atone for my sins. // // // Here we get a pointer to the Video BIOS so we can examine the // mode tables. The BIOS may be at C0000, or maybe E0000. We'll try both. // At offset 001e these is a string that says "IBM VGA Compatible". // PhysAddr.HighPart = 0; PhysAddr.LowPart = 0xC0000; BiosAddress = VideoPortGetDeviceBase( HwDeviceExtension, PhysAddr, // RangeStart 0x10000, // RangeLength, FALSE); // In memory space. if (BiosAddress==NULL || !CheckBiosID(BiosAddress)) { if (BiosAddress!=NULL) VideoPortFreeDeviceBase(HwDeviceExtension,BiosAddress); // It's at E0000. PhysAddr.HighPart = 0; PhysAddr.LowPart = 0xE0000; BiosAddress = VideoPortGetDeviceBase( HwDeviceExtension, PhysAddr, // RangeStart 0x10000, // RangeLength, FALSE); // In memory space. } if (BiosAddress!=NULL && CheckBiosID(BiosAddress)) { // Found it VideoDebugPrint((DISPLVL, "PatchModeTable - Found BIOS at 0x%08X.\n", BiosAddress)); } else { // Didn't find it if (BiosAddress!=NULL) VideoPortFreeDeviceBase(HwDeviceExtension,BiosAddress); VideoDebugPrint((DISPLVL,"PatchModeTable - Couldn't find the BIOS.\n")); return; } // // Get the BIOS version informaton { WORD ver; UCHAR val; unsigned char *pBiosAddrTmp; ver = 0; pBiosAddrTmp = BiosAddress + 0x5f; ver = (*pBiosAddrTmp) - 0x30; pBiosAddrTmp++; pBiosAddrTmp++; val = (*pBiosAddrTmp) - 0x30; pBiosAddrTmp++; val = (val << 4) + ((*pBiosAddrTmp) - 0x30); ver = (ver << 8) | val; HwDeviceExtension->BIOSVersion = ver; } // // Now read the frame buffer pitch from the BIOS // and patch the ModeTable. // for (index=0; index < TotalVideoModes; ++index) { // If we don't use the BIOS for this mode, don't patch it if (ModeTable[index].SetModeString) continue; // If it's not a valid mode, don't patch it. // All BIOS hires modes // *should* be marked invalid by now, meaning the rest of this // function does nothing. if (ModeTable[index].ValidMode == FALSE) continue; // If it's not a hires mode, don't patch it. if (ModeTable[index].BitsPerPixel < 8) continue; VideoDebugPrint((DISPLVL, " Patching Mode %d - %dx%dx%d@%d.\n", index, ModeTable[index].XResol , ModeTable[index].YResol , ModeTable[index].BitsPerPixel , ModeTable[index].Frequency )); // Ask the BIOS where the supplimental parameter // table for this mode is. biosregs.Eax = 0x1200 | ModeTable[index].BIOSModeNum; biosregs.Ebx = 0xA0; biosregs.Ecx = biosregs.Edx = biosregs.Esi = biosregs.Edi = 0; VideoPortInt10(HwDeviceExtension, &biosregs); SupParms = biosregs.Edi & 0x0000FFFF; if (SupParms == 0x0000FFFF) // BIOS call failed. continue; // Tiles per line is at offset 14 from start of table. if (HwDeviceExtension->ChipID <= CL_GD5464_BD) s_TPL = *(BiosAddress + SupParms + 14); else s_TPL = *(BiosAddress + SupParms + 15); // If this is a tiled mode, patch the table. if (s_TPL != 0) { // Tiled display register is at offset 15 if (HwDeviceExtension->ChipID <= CL_GD5464_BD) s_TFIFO = *(BiosAddress + SupParms + 15); else s_TFIFO = *(BiosAddress + SupParms + 16); // Bit 6 of s_TFIFO is 0 for 128 byte wide tiles and // 1 for 256 byte wide tiles. TileWidth = (s_TFIFO & 0x40) ? 256 : 128; if (HwDeviceExtension->ChipID > CL_GD5464_BD) s_TPL = (s_TFIFO & 0x40) ? s_TPL>> 1 : s_TPL; // Calculate pitch of the frame buffer. FB_Pitch = TileWidth * s_TPL; // Patch the ModeTable entry. ModeTable[index].BytesPerScanLine = FB_Pitch; } } VideoPortFreeDeviceBase(HwDeviceExtension,BiosAddress); VideoDebugPrint((DISPLVL, "Miniport - CLPatchModeTable - Exit.\n")); } // end CLPatchModeTable() /**************************************************************************** * FUNCTION NAME: CLValidateModes() * * DESCRIPTION: * Determines which modes are valid and which are not. * * REVISION HISTORY: * 5/30/95 Benny Ng Initial version ****************************************************************************/ VOID CLValidateModes (PHW_DEVICE_EXTENSION HwDeviceExtension) { ULONG i,j; ULONG ReqireMem; PMODETABLE pVMode; PAGED_CODE(); VideoDebugPrint((DISPLVL, "Miniport - CLValidateModes.\n")); HwDeviceExtension->NumAvailableModes = 0; HwDeviceExtension->NumTotalModes = TotalVideoModes; // // All the modes in the table start out marked invalid. // We will step through the table one mode at a time, examining // each mode to see if we will support it. // If we decide to support the mode, we will mark it as valid. // for (i = 0; i < TotalVideoModes; i++) { pVMode = &ModeTable[i]; // // Is the mode supported by this chip? // if (pVMode->ChipType & LG_ALL) { // // This mode is valid for all laguna chips. // Fall through. // ; } else if ((pVMode->ChipType & LG_5465) && (HwDeviceExtension->ChipID == CL_GD5465)) { // // We are a 5465 and this mode is valid for 5465 chips. // Fall through. // ; } else if ((pVMode->ChipType & LG_5465AD) && ((HwDeviceExtension->ChipID == CL_GD5465) && (HwDeviceExtension->ChipRev>1))) { // // We are a 5465AD and this mode is valid for 5465AD chips. // Fall through. // ; } else if ((pVMode->ChipType & LG_5464) && (HwDeviceExtension->ChipID == CL_GD5464)) { // // We are a 5464 and this mode is valid for 5464 chips. // Fall through. // ; } else if ((pVMode->ChipType & LG_5462) && (HwDeviceExtension->ChipID == CL_GD5462)) { // // We are a 5462 and this mode is valid for 5462 chips. // Fall through. // ; } else { // // This chip doesn't do this mode. // Leave this mode marked invalid and get the next mode. // continue; } // // Is this the RESET mode? // We have once special mode in the mode table that resets the chip. // We don't want to mark it as VALID, since it's not a real mode. // But we do want to remember what it is, since we we need it for // IOCTL_VIDEO_RESET_DEVICE // if (pVMode->XResol == 0) { resetmode = i; continue; } // // Does the video board have enough memory to do this mode? // ReqireMem = pVMode->NumOfPlanes * pVMode->BytesPerScanLine * pVMode->YResol; if (HwDeviceExtension->AdapterMemorySize < ReqireMem) { // // We don't have enough memory to support this mode. // Leave this mode marked invalid and get the next mode. // continue; }; // // Disable BIOS modes if we don't do VGA // if (HwDeviceExtension->Dont_Do_VGA) { if (pVMode->BIOSModeNum != 0) continue; // Skip this mode. } // // The NT 4.0 Display Applet automatically trims Direct Draw modes // from the mode list that it shows to the user. // It bases it's decision on the number of scan lines in the mode. // Modes with less then 480 scan lines don't even show up in the // list of available modes. // // Unfortunatly we have some Direct Draw modes with 480 scan lines // but fewer than 640 columns (like 320x480). The display applet // thinks that these are desktop modes, since they have 480 scan lines, // but we disagree. To prevent the user from selecting them, we // will remove them entirely. // if ( (pVMode->YResol == 480) && (pVMode->XResol < 640)) { if ((pVMode->BIOSModeNum == 0) || (pVMode->BIOSModeNum > 0x12)) { // This mode has less than 640 columns. // This mode is not a VGA mode. continue; // Skip it. } } #if 0 // Get the LowRes registry value. if ((VideoPortGetRegistryParameters(HwDeviceExtension, L"LowRes", FALSE, CLGetLowResValue, NULL) != NO_ERROR) || (HwDeviceExtension->fLowRes == FALSE) ) { // // Disable support for all low resolution modes (less than 640x350). // if ( (pVMode->XResol < 640) || (pVMode->YResol < 350) ) { if ((pVMode->BIOSModeNum == 0) || (pVMode->BIOSModeNum > 0x12)) { // This mode is a non-VGA low resolution mode, skip it. continue; } } } #endif // // Mark the mode as available. pVMode->ValidMode = TRUE; HwDeviceExtension->NumAvailableModes++; } // end for // // There may be duplicate modes in the BIOS and MODE.INI. // for (i = 0; i < TotalVideoModes; i++) { pVMode = &ModeTable[i]; if (pVMode->ValidMode != TRUE) continue; // // We will favor the MODE.INI modes over the BIOS modes. // We want the last instance of each mode in the table. // So, for each mode M, we scan the rest of the table and // if we find a mode that is equivilant to mode M, we // disable this mode. // for (j=(i+1); jXResol && ModeTable[j].YResol == pVMode->YResol && ModeTable[j].BitsPerPixel == pVMode->BitsPerPixel && /* Match refresh within +/- 1 Hz */ ModeTable[j].Frequency >= pVMode->Frequency-1 && ModeTable[j].Frequency <= pVMode->Frequency+1 ) { // Yep, it's the same mode. Disable pVMode. pVMode->ValidMode = FALSE; } } // end inner for loop } // end outer for loop VideoDebugPrint((DISPLVL, "Miniport - CLValidateModes - Exit.\n")); } // end CLValidateModes() #if 0 VP_STATUS CLGetLowResValue(PHW_DEVICE_EXTENSION HwDeviceExtension, PVOID Context, PWSTR ValueName, PVOID ValueData, ULONG ValueLength) { PAGED_CODE(); if (ValueLength > 0 && ValueLength <= sizeof(DWORD)) { HwDeviceExtension->fLowRes = (*(BYTE*) ValueData != 0); return(NO_ERROR); } HwDeviceExtension->fLowRes = FALSE; return(ERROR_INVALID_PARAMETER); } #endif /**************************************************************************** * FUNCTION NAME: CopyModeInfo() * * DESCRIPTION: * This routine copy the selected mode informations from mode table * into the VIDEO_MODE_INFORMATION structure provided by NT. * * REVISION HISTORY: * 5/30/95 Benny Ng Initial version ****************************************************************************/ VOID CLCopyModeInfo (PHW_DEVICE_EXTENSION HwDeviceExtension, PVIDEO_MODE_INFORMATION videoModes, ULONG ModeIndex, PMODETABLE ModeInfo) { PAGED_CODE(); // // Copy the mode informations to window supplied buffer // videoModes->Length = sizeof(VIDEO_MODE_INFORMATION); videoModes->ModeIndex = ModeIndex; videoModes->VisScreenWidth = ModeInfo->XResol; videoModes->VisScreenHeight = ModeInfo->YResol; videoModes->ScreenStride = ModeInfo->BytesPerScanLine; videoModes->NumberOfPlanes = ModeInfo->NumOfPlanes; videoModes->BitsPerPlane = ModeInfo->BitsPerPixel; videoModes->Frequency = ModeInfo->Frequency; videoModes->XMillimeter = 320; // temp hardcoded constant videoModes->YMillimeter = 240; // temp hardcoded constant if (videoModes->BitsPerPlane >= 8) { // // Calculate the bitmap width (note the '+ 1' on BitsPerPlane is // so that '15bpp' works out right): // videoModes->VideoMemoryBitmapWidth = videoModes->ScreenStride / ((videoModes->BitsPerPlane + 1) >> 3); // // Calculate the bitmap height. // videoModes->VideoMemoryBitmapHeight = HwDeviceExtension->AdapterMemorySize / videoModes->ScreenStride; } else { videoModes->VideoMemoryBitmapWidth = 0; videoModes->VideoMemoryBitmapHeight = 0; }; // // Set Mono/Color & Text/Graphic modes, interlace/non-interlace // videoModes->AttributeFlags = ModeInfo->fbType; if ((ModeInfo->BitsPerPixel == 24) || (ModeInfo->BitsPerPixel == 32)) { videoModes->NumberRedBits = 8; videoModes->NumberGreenBits = 8; videoModes->NumberBlueBits = 8; videoModes->RedMask = 0xff0000; videoModes->GreenMask = 0x00ff00; videoModes->BlueMask = 0x0000ff; } else if (ModeInfo->BitsPerPixel == 16) { videoModes->NumberRedBits = 5; videoModes->NumberGreenBits = 6; videoModes->NumberBlueBits = 5; videoModes->RedMask = 0x1F << 11; videoModes->GreenMask = 0x3F << 5; videoModes->BlueMask = 0x1F; } else { videoModes->NumberRedBits = 6; videoModes->NumberGreenBits = 6; videoModes->NumberBlueBits = 6; videoModes->RedMask = 0; videoModes->GreenMask = 0; videoModes->BlueMask = 0; videoModes->AttributeFlags |= (VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE); }; } // end CLCopyModeInfo() //***************************************************************************** // // CLEnableTiling() // // Enable Tiled mode for Laguna chip. // // //***************************************************************************** VOID CLEnableTiling( PHW_DEVICE_EXTENSION HwDeviceExtension, PMODETABLE pReqModeTable ) { #undef LAGUNA_REGS #define LAGUNA_REGS HwDeviceExtension->RegisterAddress VOLATILE PUSHORT pControl_reg = (PUSHORT)(LAGUNA_REGS + 0x402); VOLATILE PUCHAR pTileCtrl_reg = (PUCHAR) (LAGUNA_REGS + 0x407); VOLATILE UCHAR* pPixelMask_reg = (UCHAR*) (LAGUNA_REGS + 0xA0); VOLATILE USHORT* pDTTR_reg = (USHORT*)(LAGUNA_REGS + 0xEA); VOLATILE USHORT* pTilingCtrl_reg = (USHORT*)(LAGUNA_REGS + 0x2C4); PVIDEO_X86_BIOS_ARGUMENTS pInbiosargs; PVIDEO_X86_BIOS_ARGUMENTS pOutbiosargs; VIDEO_X86_BIOS_ARGUMENTS biosargs; unsigned long VidMem; unsigned long ulInterleave; unsigned long TilesPerLine; unsigned long WideTiles; unsigned long BitsPerPixel; VideoDebugPrint((DISPLVL, "Miniport - Setting tiling.\n")); // // If it's not a Hi Res mode, turn off tiling. // if (pReqModeTable->BitsPerPixel < 8) { VideoDebugPrint((DISPLVL, "Miniport - Not hi-res mode. No tiling.\n")); *pControl_reg |= 0x1000; // Set bit 12 of CONTROL if (HwDeviceExtension->ChipID >= CL_GD5465) *pTilingCtrl_reg &= 0xFF7F; //Clear bit 7 of TILING_CONTROL HwDeviceExtension->TileSize = 0; HwDeviceExtension->TiledMode = 0; HwDeviceExtension->TiledTPL = 0; HwDeviceExtension->TiledInterleave = 0; return; } // // It is a hi res mode. Turn on tiling. // // // If we used the BIOS to set the mode, use the BIOS to enable tiling. // Also set TILE_CTRL, TILING_CTRL, CONTROL and DTTR. // if (!(pReqModeTable->SetModeString)) { // Call BIOS to set tiling. VideoDebugPrint((DISPLVL, "Miniport - Using BIOS. Setting tiled mode.\n")); VideoPortZeroMemory(&biosargs, sizeof(VIDEO_X86_BIOS_ARGUMENTS)); biosargs.Eax = 0x1200; biosargs.Ebx = 0x00B3; VideoPortInt10(HwDeviceExtension, &biosargs); // Get tile size WideTiles = (biosargs.Eax & 0xFF) - 1; // AL=1 for narrow, 2 for wide // Get tiles per line TilesPerLine = biosargs.Ebx & 0xFF; //BL is tiles per line if ((HwDeviceExtension->ChipID >= CL_GD5465) && WideTiles) TilesPerLine /= 2; // Get color depth BitsPerPixel = pReqModeTable->BitsPerPixel; BitsPerPixel = (BitsPerPixel/ 8) - 1; // Convert 8,16,24,32 to 0,1,2,3 // Get memory interleave ulInterleave = (BYTE)(biosargs.Ebx >> 8); // BH is memory interleave. ulInterleave = ulInterleave << 6; // shift to bits 6-7 // Set DTTR bits 14-15 *pDTTR_reg &= 0x3FFF; // Clear bits 14-15 *pDTTR_reg |= (WORD) (ulInterleave << 8); // Set bits 14-15 // Set tile control reg. *pTileCtrl_reg = (BYTE)( ulInterleave // set bits 6-7 | TilesPerLine); // Set bits 0-5 // Set tiling control reg if (HwDeviceExtension->ChipID >= CL_GD5465) { *pTilingCtrl_reg &= 0x003F; // Clear bits 6-15 *pTilingCtrl_reg |= ( (ulInterleave << 8) // Set bits 14-15 | (TilesPerLine << 8) // Set bits 8-13 | (1 << 7) // set bit 7 | (WideTiles<<6) ); // Set bits 6 } // Set control reg *pControl_reg =(WORD) ( (BitsPerPixel << 13) | (WideTiles << 11) ); } // // If we used MODE.INI to set the mode. // else { // // Set memory interleave // VidMem = HwDeviceExtension->AdapterMemorySize >> 20; ulInterleave = bLeave[VidMem - 1]; // TILE_CTRL bits 6-7 *pTileCtrl_reg &= 0x3F; // Clear bits 6-7 *pTileCtrl_reg |= (USHORT)ulInterleave; // Set bits 6-7 // DTTR bits 14-15 ulInterleave = ulInterleave << 8; // Shift interleave to bit 14-15 *pDTTR_reg &= 0x3FFF; // Clear bits 14-15 *pDTTR_reg |= (USHORT)ulInterleave; // Set bits 14-15 // TILING_CTRL bits 14-15 if (HwDeviceExtension->ChipID >= CL_GD5465) { *pTilingCtrl_reg &= 0x3FFF; // Clear bits 14-15 *pTilingCtrl_reg |= (USHORT)ulInterleave; // Set bits 14-15 } else { WORD tpl = *pTileCtrl_reg; WORD dttr = *pDTTR_reg; // DTTR tiles per line - bits 8-13. tpl = tpl & 0x003F; // tiles per line is in bits 0-5. tpl = tpl << 8; // shift to bits 8-12. dttr &= 0xC0FF; // Clear bits 8-13 in DTTR dttr |= tpl; // Set bits 8-13 in DTTR *pDTTR_reg = dttr; // CONTROL enable tiling - bit 12. *pControl_reg &= 0xEFFF; // clear bit 12 } } #if 0 // // If the fetch tiles per line is greater than the display tiles per line // we can reduce the fetch tiles per line by 1. This speeds things // up a bit. // if (HwDeviceExtension->ChipID >= CL_GD5465) { unsigned long fetch_tpl = (*pDTTR_reg >> 8) & 0x3F; unsigned long display_tpl = (*pTileCtrl_reg) & 0x3F; if (fetch_tpl > display_tpl) *pDTTR_reg -= 0x0100; // One less tile per line } #endif // // Now put some mode information into the HwDeviceExtension. // HwDeviceExtension->TileSize = ((*pControl_reg >> 11) & 3) + 1; HwDeviceExtension->TiledMode = (UCHAR) pReqModeTable->BIOSModeNum; HwDeviceExtension->TiledTPL = *pTileCtrl_reg & 0x3F; HwDeviceExtension->TiledInterleave = *pTileCtrl_reg >> 6; // // Report some debug information. // VideoDebugPrint((DISPLVL, "\n" " CONTROL(402): 0x%04X BPP=%2d Tiling=%s Size=%s \n", *pControl_reg, ((((*pControl_reg & 0x6000) >>13) +1) *8), // bpp (*pControl_reg & 0x1000) ? "disabled" : "enabled ", // tile disable (*pControl_reg & 0x0800) ? "wide " : "narrow" // tile size )); VideoDebugPrint((DISPLVL, " TILE_CTRL(407): 0x%04X Interleave=%d TPL=%2d\n", *pTileCtrl_reg, (1<<((*pTileCtrl_reg & 0xC0) >> 6)), // Interleave (*pTileCtrl_reg & 0x3F) // Tiles per line. )); VideoDebugPrint((DISPLVL, " DTTR(EA): 0x%04X Interleave=%d FetchTPL=%2d Size=%s\n", *pDTTR_reg, (1<<((*pDTTR_reg & 0xC000) >> 14)), // Interleave ((*pDTTR_reg & 0x3F00) >> 8), // Tiles per line. ((*pDTTR_reg & 0x0040) ? "wide " : "narrow") // tile size )); if (HwDeviceExtension->ChipID >= CL_GD5465) VideoDebugPrint((DISPLVL, " TILING_CTRL(2C4): 0x%04X Interleave=%d TPL=%2d Tiling=%s Size=%s\n", *pTilingCtrl_reg, (1<<((*pTilingCtrl_reg & 0xC000) >> 14)), // Interleave ((*pTilingCtrl_reg & 0x3F00) >> 8), // Tile per line ((*pTilingCtrl_reg & 0x0080) ? "enabled " : "disabled"), // tile enable ((*pTilingCtrl_reg & 0x0040) ? "wide " : "narrow") // tile size )); VideoDebugPrint((DISPLVL,"\n")); } #if MULTI_CLOCK /******************************************************************************\ * * CLOverrideFIFOThreshold() * * Description: Override the FIFO Threshold value for CL-GD5465 chips running * at different clock speeds. * * Arguments: PHW_DEVICE_EXTENSION HwDeviceExtension * Pointer to hardware device extension. * PMODETABLE pReqModeTable * Pointer to MODETABLE structure containing the video mode * just set. * * Return value: Nothing. * \******************************************************************************/ void CLOverrideFIFOThreshold(PHW_DEVICE_EXTENSION HwDeviceExtension, PMODETABLE pReqModeTable) { #undef LAGUNA_REGS #define LAGUNA_REGS HwDeviceExtension->RegisterAddress VOLATILE USHORT* pDisplayThreshold_reg = (USHORT*) (LAGUNA_REGS + 0x00EA); VOLATILE BYTE* pBCLKMultiplier_reg = (BYTE*) (LAGUNA_REGS + 0x02C0); int i; BYTE BCLKMultiplier; static struct _FIFOTABLE { USHORT xRes; USHORT yRes; UCHAR BitsPerPixel; USHORT RefreshRate; BYTE BCLKMin; BYTE BCLKMax; USHORT FIFOThreshold; } FIFOTable[] = // Here we define the FIFO Threshold override values for certain modes. { // xres, yres, bpp, refresh, clockmin, clockmax, FIFOThreshold { 1600, 1200, 16, 70, 0x14, 0x17, 0x31}, { 1152, 864, 24, 85, 0x14, 0x17, 0x31}, { 1280, 960, 24, 75, 0x14, 0x17, 0x31}, { 1024, 768, 32, 85, 0x14, 0x17, 0x31}, }; // Get the current clock speed. BCLKMultiplier = *pBCLKMultiplier_reg; // Browse the table to find a match for the requested video mode. for (i = 0; i < sizeof(FIFOTable) / sizeof(FIFOTable[0]); i++) { if ( (FIFOTable[i].xRes == pReqModeTable->XResol) && (FIFOTable[i].yRes == pReqModeTable->YResol) && (FIFOTable[i].BitsPerPixel == pReqModeTable->BitsPerPixel) && (FIFOTable[i].RefreshRate == pReqModeTable->Frequency) && (FIFOTable[i].BCLKMin <= BCLKMultiplier) && (FIFOTable[i].BCLKMax >= BCLKMultiplier) ) { // The requested video mode has been found, so override the FIFO // Threshold value. VideoDebugPrint((DISPLVL, "\nMiniport - FIFO Threshold was %04X.\n", *pDisplayThreshold_reg)); *pDisplayThreshold_reg = (*pDisplayThreshold_reg & ~0x003F) | FIFOTable[i].FIFOThreshold; VideoDebugPrint((DISPLVL, "\nMiniport - FIFO Threshold changed to %04X.\n", *pDisplayThreshold_reg)); break; } } } #endif /**************************************************************************** * FUNCTION NAME: CLSetMode() * * DESCRIPTION: * This routine sets the Laguna into the requested mode. * * REVISION HISTORY: * 5/30/95 Benny Ng Initial version ****************************************************************************/ static __inline void SetVW0_TEST0 (PHW_DEVICE_EXTENSION HwDeviceExtension) { #undef LAGUNA_REGS #define LAGUNA_REGS HwDeviceExtension->RegisterAddress VOLATILE ULONG* pVW0_TEST0 = (ULONG*) (LAGUNA_REGS + 0x80F0); // Set VW0_TEST0 to 0x42 after mode change if (HwDeviceExtension->ChipID >= CL_GD5465) *pVW0_TEST0 = 0x42; }; VP_STATUS CLSetMode (PHW_DEVICE_EXTENSION HwDeviceExtension, PVIDEO_MODE Mode) { VP_STATUS status; PMODETABLE pReqModeTable; VIDEO_X86_BIOS_ARGUMENTS biosargs; ULONG ReqMode; USHORT ClrMemMask = 0x0000; #undef LAGUNA_REGS #define LAGUNA_REGS HwDeviceExtension->RegisterAddress VOLATILE PUSHORT pStatus_reg = (PUSHORT)(LAGUNA_REGS + STATUS_REG); VOLATILE PUSHORT pControl_reg = (PUSHORT)(LAGUNA_REGS + CONTROL_REG); VOLATILE PUCHAR pTileCtrl_reg = (PUCHAR) (LAGUNA_REGS + TILE_CTRL_REG); VOLATILE ULONG* pOP0_opRDRAM_reg = (ULONG*) (LAGUNA_REGS + 0x520); VOLATILE WORD* pOP0_opRDRAM_X_reg = (WORD*) (LAGUNA_REGS + 0x520); VOLATILE WORD* pOP0_opRDRAM_Y_reg = (WORD*) (LAGUNA_REGS + 0x522); VOLATILE ULONG* pDRAWBLTDEF_reg = (ULONG*) (LAGUNA_REGS + 0x584); VOLATILE ULONG* pOP0_opBGCOLOR_reg = (ULONG*) (LAGUNA_REGS + 0x5E4); VOLATILE ULONG* pBITMASK_reg = (ULONG*) (LAGUNA_REGS + 0x5E8); VOLATILE ULONG* pBLTEXT_EX_reg = (ULONG*) (LAGUNA_REGS + 0x700); VOLATILE WORD* pBLTEXT_EX_X_reg = (WORD*) (LAGUNA_REGS + 0x700); VOLATILE WORD* pBLTEXT_EX_Y_reg = (WORD*) (LAGUNA_REGS + 0x702); VOLATILE BYTE* pMCLK_reg = (BYTE*) (LAGUNA_REGS + 0x08C); VOLATILE USHORT* pDTTR_reg = (USHORT*)(LAGUNA_REGS + 0xEA); VOLATILE ULONG* pVW0_HSTRT = (ULONG*) (LAGUNA_REGS + 0x8000); VOLATILE ULONG* pVW0_CONTROL0 = (ULONG*) (LAGUNA_REGS + 0x80E4); VOLATILE ULONG* pVW0_TEST0 = (ULONG*) (LAGUNA_REGS + 0x80F0); VOLATILE BYTE* pMISC_OUTPUT_reg = (BYTE*) (LAGUNA_REGS + 0x0080); #if 0 // Stress test PAGED_CODE(); #endif // Reset the video window registers to their boot state if (HwDeviceExtension->ChipID >= CL_GD5465) { VOLATILE ULONG* pVW0_REGS; *pVW0_CONTROL0 = 1; // Disable and arm VW0 // Fill VW0 regs between HSTRT and CONTROL0 with 0 for (pVW0_REGS = pVW0_HSTRT; pVW0_REGS < pVW0_CONTROL0; pVW0_REGS++) *pVW0_REGS = 0; *pVW0_CONTROL0 = 1; // arm VW0 *pVW0_TEST0 = 0xA; // Reset TEST0 reg to boot state }; // // AGP HACK!!! // If we don't have access to VGA modes, then lie. // if (HwDeviceExtension->Dont_Do_VGA) { if ((Mode->RequestedMode) == DEFAULT_MODE) { VideoDebugPrint((DISPLVL, "\nMiniport - Impliment DEFAULT_MODE for Dont_Do_VGA.\n")); // Wait for chip to go idle. while (*pStatus_reg & 0x07); // disable tiling. ReqMode = Mode->RequestedMode & ~VIDEO_MODE_NO_ZERO_MEMORY; pReqModeTable = &ModeTable[ReqMode]; CLEnableTiling(HwDeviceExtension, pReqModeTable); HwDeviceExtension->CurrentModeNum =Mode->RequestedMode; SetVW0_TEST0(HwDeviceExtension); return NO_ERROR; } } // // Check to see if we are requesting a valid mode // ReqMode = Mode->RequestedMode & ~VIDEO_MODE_NO_ZERO_MEMORY; if (Mode->RequestedMode & VIDEO_MODE_NO_ZERO_MEMORY) { ClrMemMask = 0x8000; } if (ReqMode >= TotalVideoModes) { SetVW0_TEST0(HwDeviceExtension); return ERROR_INVALID_PARAMETER; } // // If selected mode = current mode then return. // if (HwDeviceExtension->CurrentModeNum == ReqMode) { SetVW0_TEST0(HwDeviceExtension); return NO_ERROR; } // // Points to the selected mode table slot // pReqModeTable = &ModeTable[ReqMode]; // // Don't try to set the mode it it is not supported by the chip/card. // if (pReqModeTable->ValidMode != TRUE) { // The reset mode is marked invalid, but we still need to // "set" it for IOCTL_VIDEO_RESET_DEVICE. if (Mode->RequestedMode != resetmode) { SetVW0_TEST0(HwDeviceExtension); return ERROR_INVALID_PARAMETER; } } // // Wait for chip to go idle. // while (*pStatus_reg & 0x07); #if VS_CONTROL_HACK // Enable PCI configuration registers. CLEnablePCIConfigMMIO(HwDeviceExtension); #endif // // If a SetModeString is available, then call SetMode(). // if (pReqModeTable->SetModeString) { UCHAR reg_SR15; // Set the mode. VideoDebugPrint((DISPLVL, "Miniport - Calling SetMode\n")); SetMode(pReqModeTable->SetModeString, HwDeviceExtension->RegisterAddress, NULL, HwDeviceExtension->Dont_Do_VGA); if (Mode->RequestedMode == resetmode) { // After doing HwReset, NT can call the BIOS to set a mode. // There is one 'gotcha' here. If we previously set a mode without // using the BIOS, then the BIOS doesn't know what the current mode // is, and may not set the new mode correctly. // If we clear bit 5 in SR15 prior to setting the mode, then the // BIOS will 'set everything' when it sets the mode. VideoPortWritePortUchar((PUCHAR) 0x3C4, 0x15); // Select SR15 reg_SR15 = VideoPortReadPortUchar((PUCHAR) 0x3C5); // Read SR15 reg_SR15 = reg_SR15 & 0xDF ; // 1101 1111 // Clear bit 5 VideoPortWritePortUchar((PUCHAR) 0x3C4, 0x15); // Select SR15 VideoPortWritePortUchar((PUCHAR) 0x3C5, reg_SR15); // Write SR15 } } // // Otherwise, use BIOS to set the mode. // else { UCHAR reg_SR15; VideoDebugPrint((DISPLVL, "Miniport - Using BIOS to set the mode\n")); // // Set the Vertical Monitor type. // if (!CLSetMonitorType(HwDeviceExtension, pReqModeTable->YResol, pReqModeTable->MonitorTypeVal)) { SetVW0_TEST0(HwDeviceExtension); return ERROR_INVALID_PARAMETER; }; // // We are using the BIOS to set the mode. // There is one 'gotcha' here. If we previously set a mode without // using the BIOS, then the BIOS doesn't know what the current mode // is, and may not set the new mode correctly. // If we clear bit 5 in SR15 prior to setting the mode, then the // BIOS will 'set everything' when it sets the mode. // VideoPortWritePortUchar((PUCHAR) 0x3C4, 0x15); // Select SR15 reg_SR15 = VideoPortReadPortUchar((PUCHAR) 0x3C5); // Read SR15 reg_SR15 = reg_SR15 & 0xDF ; // 1101 1111 // Clear bit 5 VideoPortWritePortUchar((PUCHAR) 0x3C4, 0x15); // Select SR15 VideoPortWritePortUchar((PUCHAR) 0x3C5, reg_SR15); // Write SR15 // // Set the selected mode. // VideoPortZeroMemory(&biosargs, sizeof(VIDEO_X86_BIOS_ARGUMENTS)); biosargs.Eax = 0x4F02; biosargs.Ebx = pReqModeTable->BIOSModeNum | ClrMemMask; VideoDebugPrint((DISPLVL, "Miniport - Mode=%xH\n", biosargs.Ebx)); if ((status = VideoPortInt10(HwDeviceExtension, &biosargs)) != NO_ERROR) { SetVW0_TEST0(HwDeviceExtension); return status; }; if ((biosargs.Eax & 0xffff) != VESA_STATUS_SUCCESS) { SetVW0_TEST0(HwDeviceExtension); VideoDebugPrint((1, "CLSetMode: Int10 call failed. Mode=%xH\n", biosargs.Ebx)); return ERROR_INVALID_PARAMETER; } } // End use BIOS to set mode. // Set monitor sync polarity for hi-res modes. if (pReqModeTable->XResol >= 320 || pReqModeTable->YResol >= 200) { *pMISC_OUTPUT_reg |= (BYTE) HwDeviceExtension->dwPolarity; } // // Enable Tiling. // CLEnableTiling(HwDeviceExtension, pReqModeTable); // // SWAT, 7 Jun 97 // 5465AD: Set bit 4 in the CONTROL register to disable bugfix 201 which is // causing hang ups in HostToScreen bitblts. // if ( (HwDeviceExtension->ChipID == CL_GD5465) && (HwDeviceExtension->ChipRev >= 2) ) { *pControl_reg |= 0x0010; } // // Turn down the clock a bit on the 5464 and 65. // VideoDebugPrint((DISPLVL, "Miniport - MCLK was %xH.\n", *pMCLK_reg)); if (HwDeviceExtension->ChipID == CL_GD5464) { *pMCLK_reg = 0x10; VideoDebugPrint((DISPLVL, "Miniport - MCLK set to %xH.\n", *pMCLK_reg)); } // else if (HwDeviceExtension->ChipID >= CL_GD5465) // { // pMCLK_reg = (BYTE*) (LAGUNA_REGS + 0x2C0); // *pMCLK_reg = 0x13; // VideoDebugPrint((DISPLVL, "Miniport - MCLK set to %xH.\n", *pMCLK_reg)); // } #if MULTI_CLOCK { // The current mode table files have no single value for the FIFO Threshold // register for all clock speeds. So we need to override the FIFO Threshold // registers in case we are running at a clock speed that otherwise would // produce a lot of noise on the screen. Notice we only implement this // routine for the CL-GD5465 chip. if (HwDeviceExtension->ChipID == CL_GD5465) { CLOverrideFIFOThreshold(HwDeviceExtension, pReqModeTable); } } #endif // Clear the video memory if we have a graphics mode. if ((pReqModeTable->BitsPerPixel >= 8) && !ClrMemMask) { *pBITMASK_reg = 0xFFFFFFFF; // enable all bits *pDRAWBLTDEF_reg = 0x100700F0; // solid color fill, ROP_PATCOPY *pOP0_opBGCOLOR_reg = 0; // fill with black // // Chip bug. // On the 5464 we must do 16 bit writes for the first BLT, // or the chip might hang. // *pOP0_opRDRAM_X_reg = 0; // fill at 0,0 *pOP0_opRDRAM_Y_reg = 0; // fill at 0,0 *pBLTEXT_EX_X_reg = pReqModeTable->XResol; *pBLTEXT_EX_Y_reg = pReqModeTable->YResol; // Wait for the blit to complete. while (*pStatus_reg & 0x07); } // // Report some debug information. // VideoDebugPrint((DISPLVL, "Miniport - CONTROL=%Xh, TILE_CTRL=%Xh, DTTR=%Xh\n", *pControl_reg, *pTileCtrl_reg, *pDTTR_reg)); VideoDebugPrint((DISPLVL, "Miniport - TileSize=%d, TiledTPL=%d, Interleave=%d\n", HwDeviceExtension->TileSize, HwDeviceExtension->TiledTPL, HwDeviceExtension->TiledInterleave)); // // Store the new mode values. // HwDeviceExtension->CurrentMode = pReqModeTable; HwDeviceExtension->CurrentModeNum = ReqMode; SetVW0_TEST0(HwDeviceExtension); return NO_ERROR; } //end CLSetMode() /**************************************************************************** * FUNCTION NAME: CLSetMonitorType() * * DESCRIPTION: * Setup the monitor type. * * REVISION HISTORY: * 5/30/95 Benny Ng Initial version ****************************************************************************/ BOOLEAN CLSetMonitorType (PHW_DEVICE_EXTENSION HwDeviceExtension, USHORT VertScanlines, UCHAR MonitorTypeVal) { VIDEO_X86_BIOS_ARGUMENTS biosArguments; ULONG tempEAX, tempEBX, tempECX; BOOLEAN err = FALSE; #if 0 // Stress test PAGED_CODE(); #endif VideoDebugPrint((DISPLVL, "Miniport - SetMonitorType\n")); if (HwDeviceExtension->Dont_Do_VGA) { VideoDebugPrint((DISPLVL, "\nMiniport - Impliment CLSetMonitorType for Dont_Do_VGA\n\n")); return TRUE; } // // Decode the selected frequency and selected vertical scanlines, // tempEAX = 0; tempEBX = 0; tempECX = 0; if (VertScanlines <= 480) { // Set the Max vertical resolution & frequency tempEAX = MonitorTypeVal & 0xF0; } else if (VertScanlines <= 600) { // Set the Max vertical resolution & frequency tempEAX = 0x1; tempEBX = MonitorTypeVal << 8; } else if (VertScanlines <= 768) { // Set the Max vertical resolution & frequency tempEAX = 0x2; tempEBX = MonitorTypeVal << 8; } else if (VertScanlines <= 1024) { // Set the Max vertical resolution & frequency tempEAX = 0x3; tempECX = MonitorTypeVal << 8; } else if (VertScanlines <= 1200) { // Set the Max vertical resolution & frequency tempEAX = 0x4; tempECX = MonitorTypeVal << 8; } else { err = TRUE; }; // // If invalid Vertical scanlines, return FALSE // if (err) { return FALSE; }; // // Set the selected monitor type // VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS)); biosArguments.Eax = 0x00001200 | tempEAX; biosArguments.Ebx = 0x000000A4 | tempEBX; biosArguments.Ecx = tempECX; if (VideoPortInt10(HwDeviceExtension, &biosArguments) == NO_ERROR) { return TRUE; } else { VideoDebugPrint((DISPLVL, "Miniport - Set Monitor Type failed\n")); return FALSE; }; } // end CLSetMonitorType() /**************************************************************************** * FUNCTION NAME: CLPowerManagement() * * DESCRIPTION: * This routine get or set the power state. If it is GET operation, it * saves current power state in the VIDEO_POWER_MANAGEMENT structure * provided by NT. * * REVISION HISTORY: * 5/30/95 Benny Ng Initial version ****************************************************************************/ VP_STATUS CLPowerManagement (PHW_DEVICE_EXTENSION HwDeviceExtension, PVIDEO_POWER_MANAGEMENT pPMinfo, BOOLEAN SetPowerState) { VP_STATUS status; VIDEO_X86_BIOS_ARGUMENTS biosargs; PAGED_CODE(); // // Setup VIDEO_X86_BIOS_ARGUMENTS structure to do an INT 10 to // set or get power state // VideoPortZeroMemory(&biosargs, sizeof(VIDEO_X86_BIOS_ARGUMENTS)); biosargs.Eax = 0x4F10; if (SetPowerState) { switch (pPMinfo->PowerState) { case VideoPowerOn: biosargs.Ebx = 0x0001; break; case VideoPowerStandBy: biosargs.Ebx = 0x0101; break; case VideoPowerSuspend: biosargs.Ebx = 0x0201; break; case VideoPowerOff: biosargs.Ebx = 0x0401; break; default: break; }; } else { biosargs.Ebx = 0x0002; }; if (biosargs.Ebx == 0) { return ERROR_INVALID_PARAMETER; }; // // Do the BIOS call // if ((status = VideoPortInt10(HwDeviceExtension, &biosargs)) != NO_ERROR) { return status; }; // // If it is GET operation, saves the power state in the output buffer // if (!SetPowerState) { pPMinfo->Length = sizeof(VIDEO_POWER_MANAGEMENT); pPMinfo->DPMSVersion = 0x1; switch (biosargs.Ebx & 0x00000F00) { case 0x000: pPMinfo->PowerState = VideoPowerOn; break; case 0x100: pPMinfo->PowerState = VideoPowerStandBy; break; case 0x200: pPMinfo->PowerState = VideoPowerSuspend; break; case 0x400: pPMinfo->PowerState = VideoPowerOff; break; default: pPMinfo->PowerState = (ULONG) -1; break; }; }; // // Update the local copy of the power state // if (pPMinfo->PowerState != (ULONG) -1) { HwDeviceExtension->PowerState = pPMinfo->PowerState; }; return NO_ERROR; }; // CLGetPowerManagement() //***************************************************************************** // // CLEnablePciBurst() // // Detect bad motherboard chip sets and don't turn on the HD_BRST_EN bit. // // Return TRUE if bursting was enabled. // Return FALSE if it was disabled. // //***************************************************************************** BOOLEAN CLEnablePciBurst( PHW_DEVICE_EXTENSION hwDeviceExtension ) { PCI_COMMON_CONFIG PciCommonConfig; BOOLEAN HDBrstEN; USHORT VendorId, DevId, HWRev; ULONG Slot, Bus, ulTmp, i; #undef LAGUNA_REGS #define LAGUNA_REGS (hwDeviceExtension->RegisterAddress) VOLATILE ULONG *pHostMasterControl = (PULONG) (LAGUNA_REGS + 0x4440); VOLATILE ULONG *pVSControl_reg = (PULONG) (LAGUNA_REGS + VSCONTROL_REG); VOLATILE WORD *pFB_Cache_Ctrl = (WORD *) (LAGUNA_REGS + 0x2C8); VOLATILE USHORT *pTilingCtrl_reg = (USHORT*)(LAGUNA_REGS + 0x2C4); VOLATILE USHORT *pPerformance_reg = (USHORT*)(LAGUNA_REGS + 0x58C); VOLATILE ULONG *pControl2_reg = (PULONG) (LAGUNA_REGS + 0x418); PAGED_CODE(); VideoDebugPrint((DISPLVL, "Miniport - CLEnablePciBurst.\n")); // // There are three burst settings we need to concern ourselves with. // // FRAME BUFFER - Bursting to the frame buffer is broken on the // 5462, 5464 and 5465. We always turn this off. // // HOSTDATA - Bursting to HOSTDATA works for some motherboard chipsets // but not for others. We have a table listing the bad chipsets. // // HOST_X_Y - Bursting to the Host XY unit is broken on the 5464, but // works on the 5465. // if ( (hwDeviceExtension->ChipID > CL_GD5465) || ( (hwDeviceExtension->ChipID == CL_GD5465) && (hwDeviceExtension->ChipRev >= 3) ) ) { // Enable frame buffer bursting on 5465AF and higher. *pVSControl_reg |= (1 << 13); VideoDebugPrint((DISPLVL, "-> Enabled frame buffer bursting.\n")); } else { // Disable frame buffer bursting on all other chips. *pVSControl_reg &= ~(1 << 13); VideoDebugPrint((DISPLVL, "-> Disabled frame buffer bursting.\n")); } // // HostXY. Disable on 5464. // if (hwDeviceExtension->ChipID == CL_GD5464) { ulTmp = *pHostMasterControl; ulTmp |= 0x3; // Set bit 0-1 to disable burst. *pHostMasterControl = ulTmp; VideoDebugPrint((DISPLVL, " Disabled HOST_XY bursting.\n")); } else if (hwDeviceExtension->ChipID > CL_GD5464) { ulTmp = *pHostMasterControl; ulTmp &= 0xFFFFFFFC; // Clear bit 0-1 to enable burst. *pHostMasterControl = ulTmp; VideoDebugPrint((DISPLVL, " Enabled HOST_XY bursting.\n")); } // // HOSTDATA bursting. // #if 1 HDBrstEN = FALSE; // force 'disabled' till the following code is validated #else HDBrstEN = TRUE; // default is 'enabled'. // For each ID in our list of bad motherboards. for (i = 0; i < NUMBADCHIPSET && HDBrstEN; i++) { VendorId = BadChipSet[i].VendorId; DevId = BadChipSet[i].DeviceId; HWRev = BadChipSet[i].HwRev; // // search PCI space and see if the bad ID is there. // Bus = 0; Slot = 0; while ( ulTmp = HalGetBusData(PCIConfiguration, Bus, Slot, &PciCommonConfig, PCI_COMMON_HDR_LENGTH) ) { if ((ulTmp > 4) && (PciCommonConfig.VendorID == VendorId) && (PciCommonConfig.DeviceID == DevId)) { // This motherboard is a bad one. HDBrstEN = FALSE; break; // quit looking. } if ( ++Slot == MAX_SLOTS ) { Slot = 0; Bus++; } } // end while } // end for each id in our list of bad ones. #endif if (HDBrstEN) { ulTmp = *pVSControl_reg; ulTmp |= 0x00001000; // Set bit 12 to enable. *pVSControl_reg = ulTmp; VideoDebugPrint((DISPLVL, " Enabled HOSTDATA bursting.\n")); } else { ulTmp = *pVSControl_reg; ulTmp &= 0xFFFFEFFF; // Clear bit 12 to disable. *pVSControl_reg = ulTmp; VideoDebugPrint((DISPLVL, " Disabled HOSTDATA bursting.\n")); } // // Frame buffer caching is broken on the 65 // if (hwDeviceExtension->ChipID >= CL_GD5465) { // // Frame buffer caching is broken on the 65 // WORD temp = *pFB_Cache_Ctrl; temp = temp & 0xFFFE; // turn off bit 0. *pFB_Cache_Ctrl = temp; } // // Enable 5465AD optimizations. // if ( ((hwDeviceExtension->ChipID==CL_GD5465) // 5465 && (hwDeviceExtension->ChipRev>1)) // rev AD || (hwDeviceExtension->ChipID > CL_GD5465)) // and later. { // Reduce Address Translate Delay to 3 clocks. *pTilingCtrl_reg = (*pTilingCtrl_reg| 0x0001); // Enable 256-byte fetch. *pPerformance_reg = (*pPerformance_reg & ~0x4000); *pControl2_reg = (*pControl2_reg | 0x0010); } *pPerformance_reg = (*pPerformance_reg | 0x0484); VideoDebugPrint((DISPLVL, "Miniport - CLEnablePciBurst - Exit.\n")); return HDBrstEN; } //***************************************************************************** // // CLFindLagunaOnPciBus // // Scan all the slots on the PCI bus and look for a Laguna chip. // // If we find one, store it's PCI ID in the hwDeviceExtension, and // and store it's PCI mappings in the AccessRanges structure. // // Return NO_ERROR if we find a Laguna // Return ERROR_DEV_NOT_EXIST if we don't // //***************************************************************************** VP_STATUS CLFindLagunaOnPciBus( PHW_DEVICE_EXTENSION hwDeviceExtension, PVIDEO_ACCESS_RANGE pAccessRanges // Points to the first of the two Laguna // access ranges. We will fill these // two ranges with data from PCI space. ) { UCHAR Command; PCI_COMMON_CONFIG PciCommonConfig; BOOLEAN DeviceFound = FALSE; USHORT VendorId = VENDOR_ID; // Vender Id ULONG Slot = 0; ULONG ulTmp,i; VP_STATUS status = ERROR_DEV_NOT_EXIST; PAGED_CODE(); VideoDebugPrint((DISPLVL, "Miniport - Searching PCI bus for Laguna card.\n")); #if _WIN32_WINNT >= 0x0500 status = VideoPortGetAccessRanges(hwDeviceExtension, 0, NULL, NUM_MM_ACCESS_RANGES, pAccessRanges, NULL, NULL, NULL); if (status == NO_ERROR) { ulTmp = VideoPortGetBusData(hwDeviceExtension, PCIConfiguration, 0, &PciCommonConfig, 0, PCI_COMMON_HDR_LENGTH); // Rev AC of the Laguna chip (5462) is not supported. if ( (PciCommonConfig.DeviceID == CL_GD5462) // CL-GD5462 && (PciCommonConfig.RevisionID == 0) // Rev AC ) { status = ERROR_DEV_NOT_EXIST; } } #else // // Loop through the PCI slots, looking our chip. // for (Slot = 0; Slot < MAX_SLOTS; Slot++) { // Get data from a PCI slot. ulTmp = VideoPortGetBusData(hwDeviceExtension, PCIConfiguration, Slot, &PciCommonConfig, 0, PCI_COMMON_HDR_LENGTH); // Is the card in this slot a Cirrus card? if ((ulTmp > 4) && (PciCommonConfig.VendorID != VendorId)) continue; // Nope. Next slot. // // It's a Cirrus card. But is it a Laguna? // Loop through our list of Laguna devices and see if // the card in this slot is on the list. // i = 0; DeviceFound = FALSE; while ((DeviceId[i] != 0) && (DeviceFound == FALSE)) { if ( (PciCommonConfig.DeviceID == DeviceId[i]) #if 1 // PDR#11377 && (PciCommonConfig.Command & (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE)) #endif ) { DeviceFound = TRUE; // It's a Laguna. break; // Exit FOR loop. } i++; } if (! DeviceFound) continue; // Nope, not a supported Laguna. Next slot. // Rev AC of the Laguna chip (5462) is not supported. if ((PciCommonConfig.DeviceID == CL_GD5462) && (PciCommonConfig.RevisionID == 0)) // Rev AC continue; // move on to next PCI slot. // We found a card we can use. Quit looking. status = NO_ERROR; break; // Exit FOR loop. } // end for slot #endif // // Did we find our chip? // if (status != NO_ERROR) return status; // Nope. Return the error. // // Store the chip ID and revision in the DeviceExtention so // the display driver can find out what chip it's using. // hwDeviceExtension->ChipID = PciCommonConfig.DeviceID; hwDeviceExtension->ChipRev = PciCommonConfig.RevisionID; // Save the slot number for future use. hwDeviceExtension->SlotNumber = Slot; // // Tell PCI to enable the IO and memory addresses. // // Get PCI COMMAND reg. ulTmp = VideoPortGetBusData( hwDeviceExtension, PCIConfiguration, Slot, &Command, FIELD_OFFSET(PCI_COMMON_CONFIG, Command), 1); if (ulTmp != 1) // Error talking to PCI space. return ERROR_DEV_NOT_EXIST; // The 5464 and later can Bus Master. if (hwDeviceExtension->ChipID >= CL_GD5464) Command |= PCI_ENABLE_BUS_MASTER; // Set PCI COMMAND reg. VideoPortSetBusData(hwDeviceExtension, PCIConfiguration, Slot, &Command, FIELD_OFFSET(PCI_COMMON_CONFIG, Command), 1); // // Get the PCI configuration data // ulTmp = VideoPortGetBusData(hwDeviceExtension, PCIConfiguration, Slot, &PciCommonConfig, 0, PCI_COMMON_HDR_LENGTH); // // Setup Access Range for Register space // if (hwDeviceExtension->ChipID == CL_GD5462) { // 5462 decodes 16 k of register address space. pAccessRanges->RangeStart.LowPart = PciCommonConfig.u.type0.BaseAddresses[0] & 0xFFFFC000; pAccessRanges->RangeStart.HighPart = 0x00000000; pAccessRanges->RangeLength = (16 * 1024); } else if (hwDeviceExtension->ChipID <= CL_GD5464_BD) { // 5464 and BD decode 32 k of register address space. pAccessRanges->RangeStart.LowPart = PciCommonConfig.u.type0.BaseAddresses[0] & 0xFFFF8000; pAccessRanges->RangeStart.HighPart = 0x00000000; pAccessRanges->RangeLength = (32 * 1024); } else // For the 5465 and later we swapped the the PCI regs around. { // Use the defaults pAccessRanges->RangeStart.LowPart = PciCommonConfig.u.type0.BaseAddresses[1] & DEFAULT_RESERVED_REGISTER_MASK; pAccessRanges->RangeStart.HighPart = 0x00000000; pAccessRanges->RangeLength = DEFAULT_RESERVED_REGISTER_SPACE; } pAccessRanges->RangeInIoSpace = FALSE; pAccessRanges->RangeVisible = TRUE; pAccessRanges->RangeShareable = FALSE; // // Setup Access Range for Frame buffer // the 62 and the 64 both use the default frame buffer size. // ++pAccessRanges; // move to next access range to be filled in. // The 65 and later have PCI BASE ADDR regs 0 and 1 reversed. if (hwDeviceExtension->ChipID <= CL_GD5464_BD) pAccessRanges->RangeStart.LowPart = PciCommonConfig.u.type0.BaseAddresses[1] & DEFAULT_RESERVED_FB_MASK; else pAccessRanges->RangeStart.LowPart = PciCommonConfig.u.type0.BaseAddresses[0] & DEFAULT_RESERVED_FB_MASK; pAccessRanges->RangeStart.HighPart = 0x00000000; pAccessRanges->RangeLength = DEFAULT_RESERVED_FB_SPACE; pAccessRanges->RangeInIoSpace = FALSE; pAccessRanges->RangeVisible = TRUE; pAccessRanges->RangeShareable = FALSE; status = NO_ERROR; return status; } // **************************************************************************** // // ClAllocateCommonBuffer() // // Allocates a locked down common buffer for bus mastered data transfers. // // If the Alloc fails, it isn't fatal; we just don't do bus mastering. // The driver can test the size of the common buffer to see if it exists. // // **************************************************************************** VOID ClAllocateCommonBuffer( PHW_DEVICE_EXTENSION HwDeviceExtension ) { PHYSICAL_ADDRESS logicalAddress; PVOID VirtualAddr; PADAPTER_OBJECT AdapterObject; DEVICE_DESCRIPTION DeviceDescription; ULONG NumberOfMapRegisters; PAGED_CODE(); // // No common buffer exists at this time. // HwDeviceExtension->CommonBufferSize = 0; HwDeviceExtension->PhysicalCommonBufferAddr = 0; HwDeviceExtension->VirtualCommonBufferAddr = 0; #if NO_BUS_MASTER return; #else // // CL5462 doesn't do bus masters. // if (HwDeviceExtension->ChipID == CL_GD5462) { VideoDebugPrint((DISPLVL, "Miniport - AllocCommonBuffer Failed: CL5462 doesn't bus master.\n")); return; } // Set up the device attributes description RtlZeroMemory(&DeviceDescription, sizeof(DeviceDescription)); DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION; DeviceDescription.Master = TRUE; DeviceDescription.ScatterGather = TRUE; DeviceDescription.DemandMode = TRUE; DeviceDescription.AutoInitialize = TRUE; DeviceDescription.Dma32BitAddresses = TRUE; DeviceDescription.IgnoreCount = FALSE; DeviceDescription.Reserved1 = FALSE; DeviceDescription.Reserved2 = FALSE; DeviceDescription.BusNumber = HwDeviceExtension->SystemIoBusNumber; DeviceDescription.DmaChannel = 0; DeviceDescription.InterfaceType = PCIBus; DeviceDescription.DmaWidth = Width32Bits; DeviceDescription.DmaSpeed = 0; DeviceDescription.MaximumLength = SIZE_BUS_MASTER_BUFFER; DeviceDescription.DmaPort = 0; NumberOfMapRegisters = SIZE_BUS_MASTER_BUFFER/PAGE_SIZE + 1; // Get a pointer to the adapter object. This is required for allocating // a buffer for bus mastering. AdapterObject = (PADAPTER_OBJECT)HalGetAdapter(&DeviceDescription, &NumberOfMapRegisters); if (AdapterObject == NULL) VideoDebugPrint((DISPLVL, "Miniport - HalGetAdapter failed.\n")); // // Request a common buffer. // The physical address of the common buffer will come back in // logicalAddress // VirtualAddr = (void *)HalAllocateCommonBuffer( AdapterObject, // (IN) Adapter object SIZE_BUS_MASTER_BUFFER, // (IN) Length. &logicalAddress, // (OUT) Phys address. FALSE); // (IN) Not cachable. // // Warn if we got back a NULL // if (VirtualAddr == NULL) { VideoDebugPrint((DISPLVL, "Miniport - AllocCommonBuffer Virtual Addr Failed.\n")); return; } if ((logicalAddress.HighPart==0) && (logicalAddress.LowPart==0)) { VideoDebugPrint((DISPLVL, "Miniport - AllocCommonBuffer Physical Addr Failed.\n")); return; } // // CL5464 chip bug. If bit 27 of the address is 0, it will // hose the chip. // if ( logicalAddress.LowPart & (1>>27) ) { VideoDebugPrint((DISPLVL, "Miniport - AllocCommonBuffer failed: Physical Addr bit 27 set.\n")); return; } // // Store the size and address of the common buffer. // Size != 0 will indicate success to the rest of the driver. // HwDeviceExtension->CommonBufferSize = SIZE_BUS_MASTER_BUFFER; HwDeviceExtension->VirtualCommonBufferAddr = (UCHAR*) VirtualAddr; HwDeviceExtension->PhysicalCommonBufferAddr = (UCHAR*) logicalAddress.LowPart; VideoDebugPrint((DISPLVL, "Miniport - Buffer is at HIGH: 0x%08X LOW: 0x%08X Virtual: 0x%08X\n", logicalAddress.HighPart, logicalAddress.LowPart, VirtualAddr)); #endif // NO_BUS_MASTER } #if VS_CONTROL_HACK // **************************************************************************** // // CLEnablePCIConfigMMIO() // // Enables memory-mapped access to PCI configuration registers. // // **************************************************************************** VP_STATUS CLEnablePCIConfigMMIO( PHW_DEVICE_EXTENSION HwDeviceExtension ) { ULONG VSCValue; ULONG ulTmp; // Get the current value of the VSC register ulTmp = VideoPortGetBusData( HwDeviceExtension, PCIConfiguration, // bus data type HwDeviceExtension->SlotNumber, // slot number &VSCValue, // buffer for returned data 0xfc, // VS Control offset 4); // 4 bytes if (ulTmp != 4) // we only want 4 bytes back { return(ERROR_DEV_NOT_EXIST); } else { // Set bit to enable memory-mapped access to PCI configuration regs VSCValue |= 1; VideoPortSetBusData( HwDeviceExtension, PCIConfiguration, // bus data type HwDeviceExtension->SlotNumber, // slot number &VSCValue, // value to set 0xfc, // VS Control offset 4); // 4 bytes return(NO_ERROR); } } #endif