Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

4929 lines
150 KiB

/******************************************************************************
*
* ******************************************
* * 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 <fetch-1> 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 <they are now called memory
type>
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); j<TotalVideoModes; j++)
{
// Does this mode match pVMode?
if( ModeTable[j].ValidMode == TRUE &&
ModeTable[j].XResol == pVMode->XResol &&
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