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
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
|