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

4929 lines
150 KiB

  1. /******************************************************************************
  2. *
  3. * ******************************************
  4. * * Copyright (c) 1995, Cirrus Logic, Inc. *
  5. * * All Rights Reserved *
  6. * ******************************************
  7. *
  8. * PROJECT: Laguna I (CL-GD546x) -
  9. *
  10. * FILE: cirrus.c
  11. *
  12. * AUTHOR: Benny Ng
  13. *
  14. * DESCRIPTION:
  15. * This is the Cirrus Logic Laguna NT miniport driver.
  16. * (kernel mode only)
  17. * Based on the S3 miniport from NT DDK.
  18. *
  19. * Copyright (c) 1995, 1996 Cirrus Logic, Inc.
  20. *
  21. * MODULES:
  22. * DriverEntry()
  23. * CLFindAdapter()
  24. * CLInitialize()
  25. * CLStartIO()
  26. * VS_Control_Hack()
  27. * Output_To_VS_CLK_CONTROL()
  28. * PMNT_Init()
  29. * PMNT_SetACPIState()
  30. * PMNT_GetACPIState()
  31. * PMNT_SetHwModuleState()
  32. * PMNT_GetHwModuleState()
  33. * PMNT_Close()
  34. * CLSetColorLookup()
  35. * CLFindVmemSize()
  36. * CLWriteRegistryInfo()
  37. * CLValidateModes()
  38. * CLCopyModeInfo()
  39. * CLSetMode()
  40. * CLSetMonitorType()
  41. * CLPowerManagement()
  42. *
  43. * REVISION HISTORY:
  44. * 5/30/95 Benny Ng Initial version
  45. *
  46. * $Log: //uinac/log/log/laguna/nt35/miniport/cl546x/CIRRUS.C $
  47. *
  48. * Rev 1.131 Jun 16 1998 09:51:24 frido
  49. * PDR#????? - Make CLResetHw and all dependent functions
  50. * non-pageable.
  51. *
  52. * Rev 1.130 May 04 1998 11:54:58 frido
  53. * Oops. wrong check.
  54. *
  55. * Rev 1.129 May 04 1998 11:31:16 frido
  56. * Changed the FIFO override code to include clocks 16h and 17h and
  57. * changed the values in the override table.
  58. *
  59. * Rev 1.128 Apr 30 1998 15:30:18 frido
  60. * PDR#11398. CLRegistryCallback has been added to patch the
  61. * InstalledDisplayDrivers registry entry in case a remote control program
  62. * like LapLink or Timbuktu has been loaded.
  63. *
  64. * Rev 1.127 Apr 23 1998 16:18:34 frido
  65. * PDR#11377. Test PCI command register when looking for a Laguna
  66. * borda. It might be disabled.
  67. *
  68. * Rev 1.126 Apr 23 1998 14:54:46 frido
  69. * PDR#11290. Before changing to a text mode from a graphics mode, we
  70. * need to enable the PCI configuration registers.
  71. *
  72. * Rev 1.125 Apr 20 1998 11:33:54 frido
  73. * PDR#11350. Added CLResetHw routine which resets the hardware to
  74. * the default text mode.
  75. *
  76. * Rev 1.124 Apr 17 1998 13:54:00 frido
  77. * Keep sync polarity as is, but only make them negative when the monitor
  78. * requires it.
  79. *
  80. * Rev 1.123 Apr 15 1998 10:07:38 frido
  81. * PDR#11317: The SyncPolarity registry key has changed a bit. Now it
  82. * is a string value which will hold EDID manufacturer and monitor codes
  83. * for monitors that need negative polarity.
  84. *
  85. * Rev 1.122 Apr 02 1998 15:50:06 frido
  86. * Changed the SyncPolarity code. It is now dynamic using the EDID
  87. * manufacturer and product code to compare with a list in the registry.
  88. *
  89. * Rev 1.121 Mar 30 1998 15:02:48 frido
  90. * PDR#11284. I changed the delay before writing the palette data in the
  91. * CLSetColorLookup routine. Now when the vertical retrace is being
  92. * activated, all remaining palette entries are send to the chip.
  93. *
  94. * Rev 1.120 Mar 25 1998 18:28:56 frido
  95. * Why don't I compile before checking in? That would catch the errors...
  96. *
  97. * Rev 1.119 Mar 25 1998 18:20:28 frido
  98. * Fixed the CLGetMonitorSyncPolarity function.
  99. *
  100. * Rev 1.118 Mar 25 1998 17:57:56 frido
  101. * Added IOCTL_STALL.
  102. *
  103. * Rev 1.117 Mar 25 1998 10:22:50 frido
  104. * Removed the multi-string registry hack for NT 5.0.
  105. *
  106. * Rev 1.116 Mar 25 1998 10:19:04 frido
  107. * Added new code for monitor sync polarity.
  108. *
  109. * Rev 1.115 Feb 25 1998 15:39:04 frido
  110. * Added NT 5.0 PnP & Power Saving support.
  111. *
  112. * Rev 1.114 Jan 22 1998 16:25:24 frido
  113. * Added a call to enable Write Combined Caching for Intel CPU's.
  114. *
  115. * Rev 1.113 Jan 21 1998 17:49:22 frido
  116. * Redfined the validation of the chipset for frame buffer bursting.
  117. *
  118. * Rev 1.112 Jan 21 1998 17:43:16 frido
  119. * Enabled frame buffer bursting on 5465AF and higher.
  120. *
  121. * Rev 1.111 Jan 06 1998 16:47:22 frido
  122. * I have added a LowRes registry flag. If it is not available or 0, low-res
  123. * modes are disabled. If the value is 1, low-res modes are enabled.
  124. *
  125. * Rev 1.110 Dec 10 1997 13:17:50 frido
  126. * Merged from 1.62 branch.
  127. *
  128. * Rev 1.109.1.3 Nov 20 1997 14:57:02 frido
  129. * Re-enabled 640x350 and 640x400 as normal modes.
  130. *
  131. * Rev 1.109.1.2 Nov 19 1997 10:04:10 phyang
  132. * Added FIFO Threshold override table for clock speed 0x14h.
  133. *
  134. * Rev 1.109.1.1 Nov 17 1997 11:06:10 frido
  135. * Added MULTI_CLOCK support. This new feature (as per customer
  136. * request) overrides the FIFO Threshold value for certain modes at
  137. * different clock speeds.
  138. *
  139. * Rev 1.109.1.0 Nov 10 1997 11:41:04 phyang
  140. * Added 5 device I/O control codes for utilities to update registry values.
  141. *
  142. * Rev 1.109 Nov 04 1997 09:22:56 frido
  143. * Added code to disable LOWRES modes if defined in SWAT.h.
  144. *
  145. * Rev 1.108 Nov 03 1997 16:58:08 phyang
  146. * Added USB Fix flag query support and better mode filter function.
  147. *
  148. * Rev 1.107 Oct 23 1997 15:46:20 phyang
  149. * Move usMaxVtFrequency and usMaxXResolution to HW_DEVICE_EXTENSION.
  150. *
  151. * Rev 1.106 23 Oct 1997 11:17:04 noelv
  152. * Added new DDC filter function.
  153. * RE-enabled DD modes.
  154. *
  155. * Rev 1.104 07 Oct 1997 16:45:42 frido
  156. * I have removed all low-res modes again, WHQL fails at 320x400 and 340x400.
  157. *
  158. * Rev 1.103 27 Sep 1997 10:58:44 frido
  159. * Removed the displaying of the version number. It would generate STOP
  160. * messages during unattended setup.
  161. *
  162. * Rev 1.102 16 Sep 1997 13:46:16 frido
  163. * Added patch to counteract NT's memory leak when using multiple display
  164. * driver DLL's.
  165. *
  166. * Rev 1.101 16 Sep 1997 13:30:12 bennyn
  167. *
  168. * Display the version message after Laguna chip family is detected.
  169. *
  170. * Rev 1.100 12 Sep 1997 09:09:22 FRIDO
  171. * Enabled 256-byte prefetch.
  172. *
  173. * Rev 1.99 04 Sep 1997 16:37:16 bennyn
  174. *
  175. * Added restore and set video window regs before and after the mode change.
  176. *
  177. * Rev 1.98 29 Aug 1997 12:26:02 noelv
  178. * restore file after roll-back
  179. *
  180. * Rev 1.96 27 Aug 1997 10:29:18 noelv
  181. * Apply CONTROL[4] fix to AF chip, too.
  182. *
  183. * Rev 1.95 26 Aug 1997 11:46:46 noelv
  184. * Enable lo-res DDRAW modes.
  185. *
  186. * Rev 1.94 20 Aug 1997 16:59:58 noelv
  187. * Typo in version string (again :)
  188. *
  189. * Rev 1.93 20 Aug 1997 09:33:18 bennyn
  190. *
  191. * Added automatically detects PnP monitor support
  192. *
  193. * Rev 1.92 19 Aug 1997 17:40:16 noelv
  194. *
  195. * Added newline to driver version string
  196. *
  197. * Rev 1.91 14 Aug 1997 14:44:56 noelv
  198. *
  199. * Changed the way the version is reported.
  200. *
  201. * Rev 1.90 13 Aug 1997 11:22:10 noelv
  202. * Added [5465AD] setcion to MODE.INI
  203. *
  204. * Rev 1.89 07 Aug 1997 15:30:18 noelv
  205. * Made AGP_VGA_HACK and FAVOR_MODE_INI a permanent part of the driver.
  206. * Removed their #defines
  207. *
  208. * Rev 1.88 04 Aug 1997 16:26:12 BENNYN
  209. * Commented out the EDID mode filter function
  210. *
  211. * Rev 1.87 29 Jul 1997 15:10:04 noelv
  212. * 0x0484 to perfomance reg to get rid of snow in foxbear.
  213. *
  214. * Rev 1.86 23 Jul 1997 09:26:44 bennyn
  215. *
  216. * Added code to handle IOCTL_GET_BIOS_VERSION command
  217. *
  218. * Rev 1.85 22 Jul 1997 12:39:40 bennyn
  219. *
  220. * Trunicate the mode table of EDID data is available
  221. *
  222. * Rev 1.84 21 Jul 1997 13:51:52 bennyn
  223. *
  224. * Added call to ReadVesaTiming()
  225. *
  226. * Rev 1.83 15 Jul 1997 09:20:18 noelv
  227. * Added AGP card support for NT 3.51
  228. *
  229. * Rev 1.82 14 Jul 1997 16:51:50 bennyn
  230. * Removed setting the mclk to 13h for cl5465
  231. *
  232. * Rev 1.81 02 Jul 1997 15:08:52 noelv
  233. * Fixes the clock-set code for 5465. Set the clock to 13h
  234. *
  235. * Rev 1.80 01 Jul 1997 14:48:02 bennyn
  236. * Change MCLK to 14 for 5465
  237. *
  238. * Rev 1.79 20 Jun 1997 13:45:36 bennyn
  239. *
  240. * Added power manager functions to Miniport
  241. *
  242. * Rev 1.78 19 Jun 1997 11:32:52 BENNYN
  243. * Disabled the 256-bytes fetch
  244. *
  245. * Rev 1.77 16 Jun 1997 16:25:20 noelv
  246. *
  247. * 5465AD HW workarounds from Frido
  248. * SWAT:
  249. * SWAT: Rev 1.4 07 Jun 1997 12:45:08 frido
  250. * SWAT: Added setting of CONTROL[4] bit for 5465AD chip.
  251. *
  252. * Rev 1.76 15 May 1997 15:57:02 noelv
  253. * Moved SWAT4 stuff to the miniport
  254. *
  255. * Rev 1.75 14 May 1997 16:56:04 bennyn
  256. * Fixed PDR 9630
  257. *
  258. * Rev 1.74 05 May 1997 16:38:52 noelv
  259. * Wait for blank before writing to the palette
  260. *
  261. * Rev 1.73 30 Apr 1997 16:41:24 noelv
  262. * Moved global SystemIoBusNumber into the device extension, where it belongs.
  263. *
  264. * Rev 1.72 24 Apr 1997 11:00:52 SueS
  265. * Enable MMIO access to PCI space on a reset device IOCTL. Added
  266. * function CLEnablePCIConfigMMIO.
  267. *
  268. * Rev 1.71 23 Apr 1997 07:20:10 SueS
  269. * Added new IOCTL for enabling memory-mapped I/O access to PCI
  270. * configuration registers. Save PCI slot number for use in later
  271. * kernel function call.
  272. *
  273. * Rev 1.70 22 Apr 1997 11:01:44 noelv
  274. *
  275. * Added forward compatible chip ids.
  276. *
  277. * Rev 1.69 17 Apr 1997 14:34:00 noelv
  278. * Changed interleave for 8 meg boards.
  279. * Expanded frame buffer memory space to 16 meg.
  280. * Don't patch MODE.INI modes.
  281. *
  282. * Rev 1.68 04 Apr 1997 14:45:56 noelv
  283. * Removed VL access ranges. Rearranged VGA access ranges.
  284. * Changed call to SetMode() to include the new parameter.
  285. *
  286. * Rev 1.67 28 Mar 1997 16:59:38 noelv
  287. * Added 5464 and 5465 specific code to CLEnableTiling.
  288. *
  289. * Rev 1.66 28 Mar 1997 13:29:30 noelv
  290. * Fixed tiling on NT 3.51
  291. *
  292. * Rev 1.65 27 Mar 1997 11:33:36 noelv
  293. * Favor MODE.INI modes over BIOS modes.
  294. * Fix ClEnableTiling for 5464.
  295. *
  296. * Rev 1.64 24 Mar 1997 16:07:58 noelv
  297. * Changed memory detect to use memory mapped registers (instead of VGA).
  298. *
  299. * Rev 1.63 03 Mar 1997 14:42:14 SueS
  300. * Subtract 1 from tiles per line (Win95 <fetch-1> bandwidth improvement).
  301. * Set address translation delay to 3 clocks.
  302. *
  303. * Rev 1.62 28 Feb 1997 11:19:16 SueS
  304. * For bus mastering (which isn't currently enabled), get an adapter object
  305. * for the call to HalAllocateCommonBuffer. Otherwise, we bomb when we boot
  306. * in VGA mode with bus mastering turned on.
  307. *
  308. * Rev 1.61 26 Feb 1997 16:14:38 noelv
  309. * CLPatchModeTable now correctly locates a planar BIOS.
  310. *
  311. * Rev 1.60 21 Feb 1997 16:16:44 noelv
  312. * Fixed typo in AGP code.
  313. *
  314. * Rev 1.59 21 Feb 1997 15:20:50 noelv
  315. * Sped up CLPatchModeTable
  316. *
  317. * Rev 1.58 21 Feb 1997 14:42:10 noelv
  318. * Oops. I swapped the frame buffer and register address spaces by accident.
  319. *
  320. * Rev 1.57 21 Feb 1997 12:53:42 noelv
  321. * AGP and 5465 4meg support
  322. *
  323. * Rev 1.56 19 Feb 1997 13:16:44 noelv
  324. * Added partial AGP support
  325. *
  326. * Rev 1.55 04 Feb 1997 15:35:58 bennyn
  327. * Interleave off for VGA modes, on for extended modes
  328. *
  329. * Rev 1.54 03 Feb 1997 13:24:46 noelv
  330. * Remove 1280x960
  331. *
  332. * Rev 1.53 31 Jan 1997 10:00:26 noelv
  333. * Allowed +/- 1 hz when matching refresh reates between MODE.INI and BIOS
  334. *
  335. * Rev 1.52 28 Jan 1997 11:32:32 noelv
  336. * write the correct chip type to the registry.
  337. *
  338. * Rev 1.51 14 Jan 1997 17:23:08 bennyn
  339. * Modified to support 5465
  340. *
  341. * Rev 1.50 14 Jan 1997 12:32:02 noelv
  342. * Split MODE.INI by chip type
  343. *
  344. * Rev 1.49 09 Dec 1996 15:50:44 bennyn
  345. * Supported the 5465 MMIO & FB base addr PCI offset change
  346. *
  347. * Rev 1.48 03 Dec 1996 10:51:42 noelv
  348. * Always use 2-way interleave
  349. *
  350. * Rev 1.47 26 Nov 1996 08:42:50 SueS
  351. * Added case for closing the log file.
  352. *
  353. * Rev 1.46 13 Nov 1996 16:19:46 noelv
  354. * Disabled WC memory for the 5462
  355. *
  356. * Rev 1.45 13 Nov 1996 15:28:36 SueS
  357. * Added support for two new IOCTL codes used for the file logging option.
  358. * There is an IOCTL request to open the file and another to write to it.
  359. *
  360. * Rev 1.44 13 Nov 1996 08:18:12 noelv
  361. *
  362. * Cleaned up support for 5464 register set.
  363. *
  364. * Rev 1.43 11 Nov 1996 10:42:08 noelv
  365. * Turn off bus mastering abilities for release builds.
  366. *
  367. * Rev 1.42 07 Nov 1996 10:48:04 BENNYN
  368. * Turn-on P6WC bit and added support for BD and 5465 parts
  369. *
  370. * Rev 1.41 30 Oct 1996 14:06:50 bennyn
  371. *
  372. * Modified for pageable miniport
  373. *
  374. * Rev 1.40 23 Oct 1996 16:03:14 noelv
  375. *
  376. * Added BUS MASTERING support.
  377. *
  378. * Rev 1.39 07 Oct 1996 14:28:20 noelv
  379. * Removed WC memory.
  380. *
  381. * Rev 1.38 03 Oct 1996 17:12:10 noelv
  382. * removed LNCTRL init.
  383. *
  384. * Rev 1.37 01 Oct 1996 17:39:08 noelv
  385. * Don't read LnCntl reg.
  386. *
  387. * Rev 1.36 30 Sep 1996 10:01:42 noelv
  388. * Used 16 bit writes to do clear-screen BLT, 'cause 5464 was hanging.
  389. *
  390. * Rev 1.35 24 Sep 1996 10:02:00 noelv
  391. * Added venus chipset to known bad.
  392. *
  393. * Rev 1.34 18 Sep 1996 15:49:12 noelv
  394. * P^ cache enabled on NT 4.0 only
  395. *
  396. * Rev 1.33 13 Sep 1996 15:35:36 bennyn
  397. * Turn-on the P6 cache
  398. *
  399. * Rev 1.32 30 Aug 1996 13:00:18 noelv
  400. *
  401. * Set interleave before calling SetMode().
  402. *
  403. * Rev 1.31 23 Aug 1996 14:18:28 noelv
  404. *
  405. * Fixed syntax error.
  406. *
  407. * Rev 1.30 23 Aug 1996 14:14:48 noelv
  408. * Accidently timmed VGA modes from NT 3.51 driver.
  409. *
  410. * Rev 1.29 23 Aug 1996 09:43:34 noelv
  411. * Frido bug release 8-23.
  412. *
  413. * Rev 1.28 22 Aug 1996 18:47:12 noelv
  414. * fixed typo in ttrimming DD modes from nt3.51
  415. *
  416. * Rev 1.27 22 Aug 1996 17:39:06 noelv
  417. * Trim DD modes from NT3.51
  418. *
  419. * Rev 1.26 22 Aug 1996 16:35:06 noelv
  420. * Changed for new mode.ini
  421. *
  422. * Rev 1.25 21 Aug 1996 16:42:58 noelv
  423. * Turned down the clock on the '64
  424. *
  425. * Rev 1.24 20 Aug 1996 11:57:50 noelv
  426. *
  427. * Added correct chip ID to registry.
  428. *
  429. * Rev 1.23 20 Aug 1996 11:26:56 noelv
  430. * Bugfix release from Frido 8-19-96
  431. *
  432. * Rev 1.4 18 Aug 1996 23:24:36 frido
  433. * #1334? - Changed hardware registers to 'volatile'.
  434. *
  435. * Rev 1.3 17 Aug 1996 17:31:18 frido
  436. * Cleanup up #1242 patch by blanking screen before clearing video memory.
  437. *
  438. * Rev 1.2 16 Aug 1996 14:34:42 frido
  439. * #1242 - Added clearing of video memory.
  440. *
  441. * Rev 1.1 15 Aug 1996 12:45:10 frido
  442. * Fixed warning messages.
  443. *
  444. * Rev 1.0 14 Aug 1996 17:12:18 frido
  445. * Initial revision.
  446. *
  447. * Rev 1.21 15 Jul 1996 17:18:00 noelv
  448. * Added wait for idle before mode switch
  449. *
  450. * Rev 1.20 11 Jul 1996 15:30:38 bennyn
  451. * Modified to support DirectDraw
  452. *
  453. * Rev 1.19 25 Jun 1996 10:48:58 bennyn
  454. * Bring-up the 5464
  455. *
  456. * Rev 1.18 19 Jun 1996 11:04:48 noelv
  457. * New mode switch code.
  458. *
  459. * Rev 1.17 05 Jun 1996 09:01:38 noelv
  460. * Reserve 8 meg of address space for the frame buffer.
  461. *
  462. * Rev 1.16 13 May 1996 14:52:34 bennyn
  463. * Added 5464 support
  464. *
  465. * Rev 1.15 10 Apr 1996 17:58:42 bennyn
  466. *
  467. * Conditional turn on HD_BRST_EN
  468. *
  469. * Rev 1.14 26 Mar 1996 16:46:14 noelv
  470. *
  471. * Test pointer in CLPatchModeTable befor using it.
  472. *
  473. * Rev 1.13 12 Mar 1996 16:11:46 noelv
  474. *
  475. * Removed support for AC chip.
  476. *
  477. * Rev 1.12 02 Mar 1996 12:30:02 noelv
  478. * Miniport now patches the ModeTable with information read from the BIOS
  479. *
  480. * Rev 1.11 23 Jan 1996 14:08:38 bennyn
  481. * Modified for COMPAQ
  482. *
  483. * Rev 1.10 20 Nov 1995 13:43:54 noelv
  484. * Updated registry with adapter string and DAC type.
  485. *
  486. * Rev 1.9 16 Nov 1995 13:27:04 bennyn
  487. *
  488. * Fixed not recognize AC parts & Added handling of IOCTL_CL_BIOS.
  489. *
  490. * Rev 1.8 26 Oct 1995 10:14:06 NOELV
  491. * Added version information.
  492. *
  493. * Rev 1.7 27 Sep 1995 11:03:00 bennyn
  494. * Fixed setting TRUE color modes
  495. *
  496. * Rev 1.6 22 Sep 1995 10:25:00 bennyn
  497. *
  498. * Rev 1.5 19 Sep 1995 08:27:44 bennyn
  499. * Fixed register space addr mask problem
  500. *
  501. * Rev 1.4 24 Aug 1995 08:13:22 bennyn
  502. * Set the CONTROL, LNCNTL & TILE_CTRL registers, this is corresponding to the
  503. *
  504. * Rev 1.3 22 Aug 1995 10:16:58 bennyn
  505. * Inital version for real HW
  506. *
  507. * Rev 1.2 21 Aug 1995 15:30:04 bennyn
  508. *
  509. * Rev 1.1 17 Aug 1995 08:17:56 BENNYN
  510. *
  511. * Rev 1.0 24 Jul 1995 13:22:38 NOELV
  512. * Initial revision.
  513. *
  514. ****************************************************************************
  515. ****************************************************************************/
  516. /*----------------------------- INCLUDES ----------------------------------*/
  517. #include "cirrus.h"
  518. #include "modemon.h"
  519. #include "version.h"
  520. #include "SWAT.h"
  521. /*----------------------------- DEFINES -----------------------------------*/
  522. //#define DBGBRK
  523. #define PCIACCESS1
  524. #define NO_BUS_MASTER 1
  525. #define DISPLVL 2
  526. #ifdef DBGBRK
  527. #define NTAPI __stdcall
  528. VOID NTAPI DbgBreakPoint(VOID);
  529. #endif
  530. #define VOLATILE volatile
  531. #define QUERY_MONITOR_ID 0x22446688
  532. #define QUERY_NONDDC_MONITOR_ID 0x11223344
  533. #define VESA_POWER_FUNCTION 0x4f10
  534. #define VESA_POWER_ON 0x0000
  535. #define VESA_POWER_STANDBY 0x0100
  536. #define VESA_POWER_SUSPEND 0x0200
  537. #define VESA_POWER_OFF 0x0400
  538. #define VESA_GET_POWER_FUNC 0x0000
  539. #define VESA_SET_POWER_FUNC 0x0001
  540. #define VESA_STATUS_SUCCESS 0x004f
  541. // The 5465 (to at least AC) has a problem when PCI configuration space
  542. // is accessible in memory space. On 16-bit writes, a 32-bit write is
  543. // actually performed, so the next register has garbage written to it.
  544. // We get around this problem by clearing bit 0 of the Vendor Specific
  545. // Control register in PCI configuration space. When this bit is set
  546. // to 0, PCI configuration registers are not available through memory
  547. // mapped I/O. Since some functions require access to PCI registers,
  548. // and only the miniport can access the kernel function to reenable it,
  549. // the display driver must post a message to the miniport to enable this
  550. // bit when needed.
  551. //
  552. #define VS_CONTROL_HACK 1
  553. /*--------------------- STATIC FUNCTION PROTOTYPES ------------------------*/
  554. /*--------------------------- ENUMERATIONS --------------------------------*/
  555. /*----------------------------- TYPEDEFS ----------------------------------*/
  556. typedef struct {
  557. USHORT VendorId; // Vender Id
  558. USHORT DeviceId; // Device Id
  559. USHORT HwRev; // HW rev
  560. } BADCHIPSET;
  561. /*-------------------------- STATIC VARIABLES -----------------------------*/
  562. //
  563. // VGA Access Ranges definitions
  564. //
  565. VIDEO_ACCESS_RANGE CLAccessRanges[NUM_VGA_ACCESS_RANGES] = {
  566. // RangeStart RangeLength
  567. // | | RangeInIoSpace
  568. // | | | RangeVisible
  569. // +-----+-----+ | | | RangeShareable
  570. // v v v v v v
  571. {0x000003B0, 0x00000000, 0x0000000c, 1, 1, 1}, // First chunk of vga ports
  572. {0x000003C0, 0x00000000, 0x00000020, 1, 1, 1}, // Remainder of vga ports
  573. {0x000A0000, 0x00000000, 0x00020000, 0, 1, 1}, // VGA memory
  574. };
  575. #define NUMBADCHIPSET 3
  576. BADCHIPSET BadChipSet[NUMBADCHIPSET] =
  577. {
  578. {0x0E11, 0x0001, 0x0003},
  579. {0x0E11, 0x1000, 0x0001},
  580. {0x8086, 0x1237, 0x0000},
  581. };
  582. unsigned long resetmode = 0xFFFFFFFF;
  583. //
  584. // Device ID supported by this miniport
  585. //
  586. USHORT DeviceId[] =
  587. {
  588. // Supported chips.
  589. CL_GD5462,
  590. CL_GD5464,
  591. CL_GD5464_BD,
  592. CL_GD5465,
  593. // For forward compatiblty...
  594. CL_GD546x_D7,
  595. CL_GD546x_D8,
  596. CL_GD546x_D9,
  597. CL_GD546x_DA,
  598. CL_GD546x_DB,
  599. CL_GD546x_DC,
  600. CL_GD546x_DD,
  601. CL_GD546x_DE,
  602. CL_GD546x_DF,
  603. // Terminator
  604. 0
  605. };
  606. #define ALWAYS_ON_VS_CLK_CTL 0x0000C0A0 // VW_CLK, RAMDAC_CLK
  607. static DWORD LgPM_vs_clk_table[] =
  608. {
  609. 0x00000001, // MOD_2D
  610. 0x00000002, // MOD_STRETCH
  611. 0x00000004, // MOD_3D
  612. 0x00000008, // MOD_EXTMODE
  613. 0x00000010, // MOD_VGA
  614. 0x00000000, // MOD_RAMDAC
  615. 0x00000040, // MOD_VPORT
  616. 0x00000000, // MOD_VW
  617. 0x00000100, // MOD_TVOUT
  618. 0x00000000, // Reserved9
  619. 0x00000000, // Reserved10
  620. 0x00000000, // Reserved11
  621. 0x00000000, // Reserved12
  622. 0x00000000, // Reserved13
  623. 0x00004000, // SYBCLK_OTHER_EN
  624. 0x00008000, // DISP_OTHER_EN
  625. 0x00000000, // Reserved16
  626. 0x00000000, // Reserved17
  627. 0x00000000, // Reserved18
  628. 0x00000000, // Reserved19
  629. 0x00000000, // Reserved20
  630. 0x00000000, // Reserved21
  631. 0x00000000, // Reserved22
  632. 0x00000000, // Reserved23
  633. 0x00000000, // Reserved24
  634. 0x00000000, // Reserved25
  635. 0x00000000, // Reserved26
  636. 0x00000000, // Reserved27
  637. 0x00000000, // Reserved28
  638. 0x00000000, // Reserved29
  639. 0x00000000, // Reserved30
  640. 0x00000000 // Reserved31
  641. };
  642. //
  643. // Memory interleave is based on how much memory we have.
  644. // For BIOS modes we don't muck with memory interleave.
  645. // But if MODE.INI is used to set the mode, we need to set the
  646. // memory interleave ourselves.
  647. //
  648. #define ONE_WAY (0x00 << 6)
  649. #define TWO_WAY (0x01 << 6)
  650. #define FOUR_WAY (0x02 << 6)
  651. unsigned char bLeave[] = {
  652. TWO_WAY,
  653. TWO_WAY,
  654. TWO_WAY,
  655. FOUR_WAY,
  656. TWO_WAY,
  657. TWO_WAY,
  658. TWO_WAY,
  659. FOUR_WAY,
  660. };
  661. #if LOG_FILE
  662. extern HANDLE LogFileHandle; // Handle for log file
  663. #endif
  664. /*-------------------------- EXTERNAL FUNCTIONS --------------------------*/
  665. extern ULONG RtlWriteRegistryValue(ULONG RelativeTo, PWSTR Path,
  666. PWSTR ValueName, ULONG ValueType,
  667. PVOID ValueData, ULONG ValueLength);
  668. extern DWORD ConfigureLagunaMemory(DWORD dwPhysFB, DWORD dwFBSize);
  669. extern void ReleaseMTRRs(DWORD dwFBMTRRReg);
  670. /*-------------------------- GLOBAL FUNCTIONS -----------------------------*/
  671. VOID HalDisplayString(PUCHAR);
  672. #if 0
  673. VP_STATUS CLGetLowResValue(PHW_DEVICE_EXTENSION HwDeviceExtension,
  674. PVOID Context, PWSTR ValueName, PVOID ValueData, ULONG ValueLength);
  675. #endif
  676. #if defined(ALLOC_PRAGMA)
  677. #pragma alloc_text(PAGE,DriverEntry)
  678. #pragma alloc_text(PAGE,CLFindAdapter)
  679. #pragma alloc_text(PAGE,CLInitialize)
  680. #pragma alloc_text(PAGE,CLStartIO)
  681. #pragma alloc_text(PAGE,ReadClockLine)
  682. #pragma alloc_text(PAGE,WriteClockLine)
  683. #pragma alloc_text(PAGE,WriteDataLine)
  684. #pragma alloc_text(PAGE,ReadDataLine)
  685. #pragma alloc_text(PAGE,WaitVSync)
  686. #pragma alloc_text(PAGE,VS_Control_Hack)
  687. #pragma alloc_text(PAGE,Output_To_VS_CLK_CONTROL)
  688. #pragma alloc_text(PAGE,PMNT_Init)
  689. #pragma alloc_text(PAGE,PMNT_SetACPIState)
  690. #pragma alloc_text(PAGE,PMNT_GetACPIState)
  691. #pragma alloc_text(PAGE,PMNT_SetHwModuleState)
  692. #pragma alloc_text(PAGE,PMNT_GetHwModuleState)
  693. #pragma alloc_text(PAGE,PMNT_Close)
  694. #pragma alloc_text(PAGE,CLSetColorLookup)
  695. #pragma alloc_text(PAGE,CLFindVmemSize)
  696. #pragma alloc_text(PAGE,CLWriteRegistryInfo)
  697. #pragma alloc_text(PAGE,CLValidateModes)
  698. #pragma alloc_text(PAGE,CLCopyModeInfo)
  699. #if 0 // Stress test
  700. #pragma alloc_text(PAGE,CLSetMode)
  701. #pragma alloc_text(PAGE,CLSetMonitorType)
  702. #pragma alloc_text(PAGE,CLEnableTiling)
  703. #endif
  704. #pragma alloc_text(PAGE,CLPowerManagement)
  705. #pragma alloc_text(PAGE,CLPatchModeTable)
  706. #pragma alloc_text(PAGE,CLEnablePciBurst)
  707. #pragma alloc_text(PAGE,CLFindLagunaOnPciBus)
  708. #pragma alloc_text(PAGE,ClAllocateCommonBuffer)
  709. #if 0
  710. #pragma alloc_text(PAGE,CLGetLowResValue)
  711. #endif
  712. #if _WIN32_WINNT >= 0x0500
  713. #pragma alloc_text(PAGE,CLGetChildDescriptor)
  714. #pragma alloc_text(PAGE,CLGetPowerState)
  715. #pragma alloc_text(PAGE,CLSetPowerState)
  716. #pragma alloc_text(PAGE,GetDDCInformation)
  717. #endif
  718. #endif
  719. /****************************************************************************
  720. * FUNCTION NAME: DriverEntry()
  721. *
  722. * DESCRIPTION:
  723. * Installable driver initialization entry point.
  724. * This entry point is called directly by the I/O system.
  725. *
  726. * REVISION HISTORY:
  727. * 5/30/95 Benny Ng Initial version
  728. ****************************************************************************/
  729. ULONG DriverEntry (PVOID Context1,
  730. PVOID Context2)
  731. {
  732. VIDEO_HW_INITIALIZATION_DATA hwInitData;
  733. ULONG status;
  734. ULONG status1;
  735. PAGED_CODE();
  736. VideoDebugPrint((DISPLVL, "Miniport - CL546x DriverEntry\n"));
  737. //
  738. // Zero out structure.
  739. //
  740. VideoPortZeroMemory(&hwInitData, sizeof(VIDEO_HW_INITIALIZATION_DATA));
  741. //
  742. // Specify sizes of structure and extension.
  743. //
  744. hwInitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA);
  745. //
  746. // Set entry points.
  747. //
  748. hwInitData.HwFindAdapter = CLFindAdapter;
  749. hwInitData.HwInitialize = CLInitialize;
  750. hwInitData.HwInterrupt = NULL;
  751. hwInitData.HwStartIO = CLStartIO;
  752. #if 1 // PDR#11350
  753. hwInitData.HwResetHw = CLResetHw;
  754. #endif
  755. #if _WIN32_WINNT >= 0x0500
  756. hwInitData.HwGetVideoChildDescriptor = CLGetChildDescriptor;
  757. hwInitData.HwGetPowerState = CLGetPowerState;
  758. hwInitData.HwSetPowerState = CLSetPowerState;
  759. #endif
  760. //
  761. // Determine the size we require for the device extension.
  762. //
  763. hwInitData.HwDeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
  764. //
  765. // Always start with parameters for device0 in this case.
  766. //
  767. // This device only supports PCI bus types.
  768. //
  769. hwInitData.AdapterInterfaceType = PCIBus;
  770. status = VideoPortInitialize(Context1,
  771. Context2,
  772. &hwInitData,
  773. NULL);
  774. return status;
  775. } // end DriverEntry()
  776. #if _WIN32_WINNT >= 0x0500
  777. #define QUERY_ACPI_MONITOR_ID 0x0100
  778. #define QUERY_ACPI_PANEL_ID 0x0110
  779. #define QUERY_ACPI_TV_ID 0x0200
  780. /*******************************************************************************
  781. * Enumerate all devices controlled by the Laguna graphics chip. This includes
  782. * DDC monitors attached to the board, as well as other devices which may be
  783. * connected to the I2C bus.
  784. */
  785. ULONG CLGetChildDescriptor(
  786. PVOID HwDeviceExtension, // Pointer to our hardware device context
  787. // structure.
  788. PVIDEO_CHILD_ENUM_INFO ChildEnumInfo, // Information about the device that
  789. // should be enumerated
  790. PVIDEO_CHILD_TYPE pChildType, // Type of child we are enumerating - monitor,
  791. // I2C, ...
  792. PVOID pChildDescriptor, // Identification structure of the device
  793. // (EDID, string).
  794. ULONG* pUId, // Private unique 32 bit ID to be passed back to
  795. // the miniport.
  796. PVOID pUnused // unused
  797. )
  798. /*
  799. * The return value is TRUE if the child device existed, FALSE if it did not.
  800. *******************************************************************************/
  801. {
  802. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  803. switch (ChildEnumInfo->ChildIndex)
  804. {
  805. case 0:
  806. //
  807. // Case 0 is used to enumerate devices found by the ACPI firmware.
  808. //
  809. // For monitor devices enumerated by ACPI, the video port will get
  810. // the EDID directly from ACPI.
  811. //
  812. switch (ChildEnumInfo->ACPIHwId)
  813. {
  814. case QUERY_ACPI_MONITOR_ID:
  815. *pChildType = Monitor;
  816. *pUId = ChildEnumInfo->ACPIHwId;
  817. return ERROR_MORE_DATA;
  818. case QUERY_ACPI_PANEL_ID:
  819. *pChildType = Monitor;
  820. *pUId = ChildEnumInfo->ACPIHwId;
  821. return ERROR_MORE_DATA;
  822. case QUERY_ACPI_TV_ID:
  823. *pChildType = Monitor;
  824. *pUId = ChildEnumInfo->ACPIHwId;
  825. return ERROR_MORE_DATA;
  826. default:
  827. ASSERT(FALSE);
  828. return ERROR_NO_MORE_DEVICES;
  829. }
  830. case 1:
  831. // Obtain the EDID structure via DDC.
  832. if (GetDDCInformation(HwDeviceExtension, pChildDescriptor, ChildEnumInfo->ChildDescriptorSize))
  833. {
  834. *pChildType = Monitor;
  835. *pUId = 0x22446688;
  836. VideoDebugPrint((1, "CLGetChildDescriptor - "
  837. "successfully read EDID structure\n"));
  838. }
  839. else
  840. {
  841. // Always return at least a monitor.
  842. *pChildType = Monitor;
  843. *pUId = 0x11223344;
  844. VideoDebugPrint((1, "CLGetChildDescriptor - "
  845. "DDC not supported\n"));
  846. }
  847. return ERROR_MORE_DATA;
  848. default:
  849. return ERROR_NO_MORE_DEVICES;
  850. }
  851. }
  852. /*******************************************************************************
  853. * Returns the power state information.
  854. */
  855. VP_STATUS CLGetPowerState(
  856. PHW_DEVICE_EXTENSION HwDeviceExtension, // Pointer to our hardware
  857. // device extension structure.
  858. ULONG HwDeviceId, // Private unique 32 bit ID
  859. // identifying the device.
  860. PVIDEO_POWER_MANAGEMENT VideoPowerManagement // Power state information.
  861. )
  862. /*
  863. * The return value is TRUE if the power state can be set, FALSE otherwise.
  864. *******************************************************************************/
  865. {
  866. VP_STATUS status;
  867. //
  868. // We only support power setting for the monitor. Make sure the
  869. // HwDeviceId matches one the the monitors we could report.
  870. //
  871. if ((HwDeviceId == QUERY_NONDDC_MONITOR_ID) ||
  872. (HwDeviceId == QUERY_MONITOR_ID)) {
  873. VIDEO_X86_BIOS_ARGUMENTS biosArguments;
  874. //
  875. // We are querying the power support for the monitor.
  876. //
  877. if ((VideoPowerManagement->PowerState == VideoPowerOn) ||
  878. (VideoPowerManagement->PowerState == VideoPowerHibernate)) {
  879. return NO_ERROR;
  880. }
  881. VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  882. biosArguments.Eax = VESA_POWER_FUNCTION;
  883. biosArguments.Ebx = VESA_GET_POWER_FUNC;
  884. status = VideoPortInt10(HwDeviceExtension, &biosArguments);
  885. if ( (status == NO_ERROR ) &&
  886. ( (biosArguments.Eax & 0xffff) == VESA_STATUS_SUCCESS)) {
  887. switch (VideoPowerManagement->PowerState) {
  888. case VideoPowerStandBy:
  889. return (biosArguments.Ebx & VESA_POWER_STANDBY) ?
  890. NO_ERROR : ERROR_INVALID_FUNCTION;
  891. case VideoPowerSuspend:
  892. return (biosArguments.Ebx & VESA_POWER_SUSPEND) ?
  893. NO_ERROR : ERROR_INVALID_FUNCTION;
  894. case VideoPowerOff:
  895. return (biosArguments.Ebx & VESA_POWER_OFF) ?
  896. NO_ERROR : ERROR_INVALID_FUNCTION;
  897. default:
  898. break;
  899. }
  900. }
  901. VideoDebugPrint((1, "This device does not support Power Management.\n"));
  902. return ERROR_INVALID_FUNCTION;
  903. } else if (HwDeviceId == DISPLAY_ADAPTER_HW_ID) {
  904. //
  905. // We are querying power support for the graphics card.
  906. //
  907. switch (VideoPowerManagement->PowerState) {
  908. case VideoPowerOn:
  909. case VideoPowerHibernate:
  910. case VideoPowerStandBy:
  911. return NO_ERROR;
  912. case VideoPowerOff:
  913. case VideoPowerSuspend:
  914. //
  915. // Indicate that we can't do VideoPowerOff, because
  916. // we have no way of coming back when power is re-applied
  917. // to the card.
  918. //
  919. return ERROR_INVALID_FUNCTION;
  920. default:
  921. ASSERT(FALSE);
  922. return ERROR_INVALID_FUNCTION;
  923. }
  924. } else {
  925. VideoDebugPrint((1, "Unknown HwDeviceId"));
  926. ASSERT(FALSE);
  927. return ERROR_INVALID_PARAMETER;
  928. }
  929. }
  930. /*******************************************************************************
  931. * Set the power state for a given device.
  932. */
  933. VP_STATUS CLSetPowerState(
  934. PHW_DEVICE_EXTENSION HwDeviceExtension, // Pointer to our hardware
  935. // device extension structure.
  936. ULONG HwDeviceId, // Private unique 32 bit ID
  937. // identifying the device.
  938. PVIDEO_POWER_MANAGEMENT VideoPowerManagement // Power state information.
  939. )
  940. /*
  941. * The return value is TRUE if the power state can be set, FALSE otherwise.
  942. *******************************************************************************/
  943. {
  944. VP_STATUS status;
  945. //
  946. // Make sure we recognize the device.
  947. //
  948. if ((HwDeviceId == QUERY_NONDDC_MONITOR_ID) ||
  949. (HwDeviceId == QUERY_MONITOR_ID)) {
  950. VIDEO_X86_BIOS_ARGUMENTS biosArguments;
  951. VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  952. biosArguments.Eax = VESA_POWER_FUNCTION;
  953. biosArguments.Ebx = VESA_SET_POWER_FUNC;
  954. switch (VideoPowerManagement->PowerState) {
  955. case VideoPowerOn:
  956. case VideoPowerHibernate:
  957. biosArguments.Ebx |= VESA_POWER_ON;
  958. break;
  959. case VideoPowerStandBy:
  960. biosArguments.Ebx |= VESA_POWER_STANDBY;
  961. break;
  962. case VideoPowerSuspend:
  963. biosArguments.Ebx |= VESA_POWER_SUSPEND;
  964. break;
  965. case VideoPowerOff:
  966. biosArguments.Ebx |= VESA_POWER_OFF;
  967. break;
  968. default:
  969. VideoDebugPrint((1, "Unknown power state.\n"));
  970. ASSERT(FALSE);
  971. return ERROR_INVALID_PARAMETER;
  972. }
  973. status = VideoPortInt10(HwDeviceExtension, &biosArguments);
  974. if ( (status == NO_ERROR ) &&
  975. ((biosArguments.Eax & 0xffff) == VESA_STATUS_SUCCESS)) {
  976. HwDeviceExtension->MonitorEnabled =
  977. ((VideoPowerManagement->PowerState == VideoPowerOn) ||
  978. (VideoPowerManagement->PowerState == VideoPowerHibernate));
  979. return NO_ERROR;
  980. }
  981. else {
  982. VideoDebugPrint((1, "CLSetPowerState: Int10 failed \n"));
  983. return ERROR_INVALID_PARAMETER;
  984. }
  985. } else if (HwDeviceId == DISPLAY_ADAPTER_HW_ID) {
  986. switch (VideoPowerManagement->PowerState) {
  987. case VideoPowerOn:
  988. case VideoPowerStandBy:
  989. case VideoPowerSuspend:
  990. case VideoPowerOff:
  991. case VideoPowerHibernate:
  992. return NO_ERROR;
  993. default:
  994. ASSERT(FALSE);
  995. return ERROR_INVALID_PARAMETER;
  996. }
  997. } else {
  998. VideoDebugPrint((1, "Unknown HwDeviceId"));
  999. ASSERT(FALSE);
  1000. return ERROR_INVALID_PARAMETER;
  1001. }
  1002. }
  1003. #endif
  1004. /****************************************************************************
  1005. * FUNCTION NAME: CLFindAdapter()
  1006. *
  1007. * DESCRIPTION:
  1008. * This routine is called to determine if the adapter for this driver
  1009. * is present in the system.
  1010. * If it is present, the function fills out some information describing
  1011. * the adapter.
  1012. *
  1013. * REVISION HISTORY:
  1014. * 5/30/95 Benny Ng Initial version
  1015. ****************************************************************************/
  1016. VP_STATUS CLFindAdapter (
  1017. PVOID HwDeviceExtension, // Our global data
  1018. PVOID HwContext, // Not used.
  1019. PWSTR ArgumentString, // Not used.
  1020. PVIDEO_PORT_CONFIG_INFO ConfigInfo, // Pass info about card back to NT
  1021. PUCHAR Again) // We always say 'no'
  1022. {
  1023. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  1024. PVIDEO_ACCESS_RANGE pAccessRanges;
  1025. VIDEO_ACCESS_RANGE AccessRanges[TOTAL_ACCESS_RANGES];
  1026. PVOID MappedAddress[TOTAL_ACCESS_RANGES];
  1027. ULONG ReleaseCnt=0, start_range, skip_ranges;
  1028. VP_STATUS status = ERROR_DEV_NOT_EXIST;
  1029. ULONG i;
  1030. ULONG ulFirstAccessRange;
  1031. unsigned long SystemIoBusNumber;
  1032. PAGED_CODE();
  1033. VideoDebugPrint((DISPLVL,
  1034. "Miniport - CLFindAdapter. AdapterInterfaceType is %d.\n",
  1035. ConfigInfo->AdapterInterfaceType));
  1036. VideoDebugPrint((DISPLVL,
  1037. "Miniport - CLFindAdapter. SystemIoBusNumber is %d.\n",
  1038. ConfigInfo->SystemIoBusNumber));
  1039. SystemIoBusNumber = ConfigInfo->SystemIoBusNumber;
  1040. #ifdef DBGBRK
  1041. DbgBreakPoint();
  1042. #endif
  1043. //
  1044. // Make sure the size of the structure is at least as large as what we
  1045. // are expecting (check version of the config info structure).
  1046. //
  1047. if (ConfigInfo->Length < sizeof(VIDEO_PORT_CONFIG_INFO))
  1048. {
  1049. VideoDebugPrint((DISPLVL, "Miniport - CLFindAdapter parameter wrong size.\n"));
  1050. return (ERROR_INVALID_PARAMETER);
  1051. }
  1052. //
  1053. // Detect a PCI card. We don't do ISA bus. We don't do VL bus.
  1054. //
  1055. // After detecting the chip, we fill in the register and frame buffer
  1056. // access ranges with data from PCI registers.
  1057. // The location and size of the VGA access ranges is constant,
  1058. // but the location of our registers and frame buffer depend on where
  1059. // the PCI BIOS decided to put them.
  1060. //
  1061. pAccessRanges = &AccessRanges[FIRST_MM_ACCESS_RANGE];
  1062. if (ConfigInfo->AdapterInterfaceType == PCIBus)
  1063. status = CLFindLagunaOnPciBus(hwDeviceExtension, pAccessRanges);
  1064. //
  1065. // If we didn't find our chip, then return failure.
  1066. //
  1067. if (status != NO_ERROR)
  1068. {
  1069. VideoDebugPrint((DISPLVL,
  1070. "Miniport - CLFindLagunaOnPciBus did not find a Laguna chip.\n"));
  1071. *Again = 0;
  1072. return status;
  1073. }
  1074. //
  1075. // The maximum possible frame buffer size is 1/4 of frame buffer
  1076. // address space decoded by the chip. This is because the chip
  1077. // replicates the frame buffer address space 4 times.
  1078. //
  1079. AccessRanges[MM_FRAME_BUFFER_ACCESS_RANGE].RangeLength /= 4;
  1080. //
  1081. // Hey, hey, hey. We found a chip.
  1082. //
  1083. VideoDebugPrint((DISPLVL, "Miniport - CLFindLagunaOnPciBus found a CL546x.\n"));
  1084. //
  1085. // We will start by see if if we can get the VGA resources.
  1086. //
  1087. // assume we can get the VGA resources
  1088. hwDeviceExtension->Dont_Do_VGA = 0;
  1089. ulFirstAccessRange = FIRST_VGA_ACCESS_RANGE;
  1090. // Copy the VGA access ranges into our AccessRanges structure.
  1091. VideoPortMoveMemory(AccessRanges,
  1092. CLAccessRanges,
  1093. sizeof(VIDEO_ACCESS_RANGE) * NUM_VGA_ACCESS_RANGES);
  1094. // Check to see if there is a VGA I/O hardware resource conflict.
  1095. VideoDebugPrint((DISPLVL, "Miniport - Verifying the VGA access ranges.\n"));
  1096. status = VideoPortVerifyAccessRanges(hwDeviceExtension,
  1097. NUM_VGA_ACCESS_RANGES,
  1098. AccessRanges);
  1099. VideoDebugPrint ((DISPLVL,
  1100. "Miniport - VGA access ranges verification was %s. Status was %d.\n",
  1101. ((status == NO_ERROR) ? "successful" : "not successful"), status));
  1102. if (status != NO_ERROR)
  1103. {
  1104. // We didn't get the VGA space. We may be a secondary adapter so
  1105. // continue but hands off VGA resources.
  1106. hwDeviceExtension->Dont_Do_VGA = 1;
  1107. MappedAddress[0] =
  1108. MappedAddress[1] =
  1109. MappedAddress[2] = NULL;
  1110. ulFirstAccessRange = FIRST_MM_ACCESS_RANGE; // skip VGA resources
  1111. }
  1112. //
  1113. // Now verify the Laguna register and frame buffer ranges.
  1114. // (include VGA ranges if the are available to us)
  1115. //
  1116. status = VideoPortVerifyAccessRanges(hwDeviceExtension,
  1117. (TOTAL_ACCESS_RANGES-ulFirstAccessRange),
  1118. &AccessRanges[ulFirstAccessRange]);
  1119. if (status != NO_ERROR)
  1120. return status; // !!!!!!! CONFLICT !!!!!!!
  1121. // Now map the access ranges.
  1122. VideoDebugPrint ((DISPLVL, "Miniport - Mapping access ranges.\n"));
  1123. for (i = ulFirstAccessRange; i < TOTAL_ACCESS_RANGES; i++)
  1124. {
  1125. pAccessRanges = &AccessRanges[i];
  1126. VideoDebugPrint((DISPLVL,
  1127. "Miniport - Mapping range. Start=0x%08X:0x%08X Length=%d.\n",
  1128. pAccessRanges->RangeStart.HighPart,
  1129. pAccessRanges->RangeStart.LowPart,
  1130. pAccessRanges->RangeLength ));
  1131. if ((MappedAddress[i] = VideoPortGetDeviceBase(hwDeviceExtension,
  1132. pAccessRanges->RangeStart,
  1133. pAccessRanges->RangeLength,
  1134. pAccessRanges->RangeInIoSpace)) == NULL)
  1135. {
  1136. VideoDebugPrint((DISPLVL, "Miniport - Mapping failed\n"));
  1137. VideoDebugPrint ((DISPLVL,
  1138. "Miniport - Unmapping access ranges.\n"));
  1139. // Unmap the previously mapped addresses
  1140. while (i-- > ulFirstAccessRange)
  1141. {
  1142. VideoPortFreeDeviceBase(hwDeviceExtension, &MappedAddress[i]);
  1143. }
  1144. return ERROR_DEV_NOT_EXIST;
  1145. }
  1146. else
  1147. VideoDebugPrint((DISPLVL,"Miniport - Mapping successful.\n"));
  1148. } // end for
  1149. // Save the location of the VGA registers.
  1150. hwDeviceExtension->IOAddress = MappedAddress[0];
  1151. //
  1152. // Initialize variables in hardware extension
  1153. //
  1154. hwDeviceExtension->CurrentModeNum = (ULONG) -1;
  1155. hwDeviceExtension->CurrentMode = NULL;
  1156. hwDeviceExtension->PowerState = VideoPowerOn;
  1157. hwDeviceExtension->SystemIoBusNumber=SystemIoBusNumber;
  1158. //
  1159. // Save the VGA mapped address.
  1160. //
  1161. // hwDeviceExtension->VLIOAddress = MappedAddress[1];
  1162. //
  1163. // Save the physical register address information
  1164. //
  1165. pAccessRanges = &AccessRanges[MM_REGISTER_ACCESS_RANGE];
  1166. hwDeviceExtension->PhysicalRegisterAddress = pAccessRanges->RangeStart;
  1167. hwDeviceExtension->PhysicalRegisterLength = pAccessRanges->RangeLength;
  1168. hwDeviceExtension->PhysicalFrameInIoSpace = pAccessRanges->RangeInIoSpace;
  1169. //
  1170. // Save the virtual register address information
  1171. //
  1172. hwDeviceExtension->RegisterAddress = MappedAddress[MM_REGISTER_ACCESS_RANGE];
  1173. hwDeviceExtension->RegisterLength = pAccessRanges->RangeLength;
  1174. //
  1175. // Get the size of the video memory.
  1176. //
  1177. if ((hwDeviceExtension->AdapterMemorySize =
  1178. CLFindVmemSize(hwDeviceExtension)) == 0)
  1179. {
  1180. VideoDebugPrint((DISPLVL, "Miniport - No VMEM installed\n"));
  1181. // Unmap our access ranges.
  1182. for (i=0; i < ReleaseCnt; i++)
  1183. VideoPortFreeDeviceBase(hwDeviceExtension, &MappedAddress[i]);
  1184. // Erase the claim on the hardware resource
  1185. VideoPortVerifyAccessRanges(hwDeviceExtension,
  1186. 0,
  1187. AccessRanges);
  1188. return ERROR_DEV_NOT_EXIST;
  1189. }
  1190. //
  1191. // Save the physical frame buffer address information
  1192. //
  1193. pAccessRanges = &AccessRanges[MM_FRAME_BUFFER_ACCESS_RANGE];
  1194. hwDeviceExtension->PhysicalFrameAddress = pAccessRanges->RangeStart;
  1195. hwDeviceExtension->PhysicalFrameLength = pAccessRanges->RangeLength;
  1196. hwDeviceExtension->PhysicalRegisterInIoSpace =
  1197. pAccessRanges->RangeInIoSpace;
  1198. //
  1199. // Save the virtual frame buffer address information.
  1200. //
  1201. hwDeviceExtension->FrameAddress = MappedAddress[MM_FRAME_BUFFER_ACCESS_RANGE];
  1202. hwDeviceExtension->FrameLength = hwDeviceExtension->AdapterMemorySize;
  1203. VideoDebugPrint
  1204. ((DISPLVL,
  1205. "Miniport - Physical Reg location= 0x%08X, Physical FB location=0x%08X \n"
  1206. " Physical Reg size= %08d, Physical FB size= %08d \n",
  1207. hwDeviceExtension->PhysicalRegisterAddress.LowPart,
  1208. hwDeviceExtension->PhysicalFrameAddress.LowPart,
  1209. hwDeviceExtension->PhysicalRegisterLength,
  1210. hwDeviceExtension->PhysicalFrameLength
  1211. ));
  1212. VideoDebugPrint
  1213. ((DISPLVL,
  1214. "Miniport - Logical Reg address=0x%08X, Logical FB address=0x%08X \n"
  1215. " Logical Reg size= %08d, Logical FB size= %08d \n",
  1216. hwDeviceExtension->RegisterAddress,
  1217. hwDeviceExtension->FrameAddress,
  1218. hwDeviceExtension->RegisterLength,
  1219. hwDeviceExtension->FrameLength
  1220. ));
  1221. //
  1222. // We have this so that the int10 will also work on the VGA also if we
  1223. // use it in this driver.
  1224. //
  1225. if( ! hwDeviceExtension->Dont_Do_VGA )
  1226. {
  1227. ConfigInfo->VdmPhysicalVideoMemoryAddress.LowPart = 0x000A0000;
  1228. ConfigInfo->VdmPhysicalVideoMemoryAddress.HighPart = 0x00000000;
  1229. ConfigInfo->VdmPhysicalVideoMemoryLength = 0x00020000;
  1230. }
  1231. //
  1232. // Clear out the Emulator entries and the state size since this driver
  1233. // does not support them.
  1234. //
  1235. ConfigInfo->NumEmulatorAccessEntries = 0;
  1236. ConfigInfo->EmulatorAccessEntries = NULL;
  1237. ConfigInfo->EmulatorAccessEntriesContext = 0;
  1238. //
  1239. // This driver does not do SAVE/RESTORE of hardware state.
  1240. //
  1241. ConfigInfo->HardwareStateSize = 0;
  1242. {
  1243. BOOLEAN HDBrstEN = TRUE;
  1244. //
  1245. // Enable burst mode
  1246. //
  1247. HDBrstEN = CLEnablePciBurst(HwDeviceExtension);
  1248. //
  1249. // We now have a complete hardware description of the hardware.
  1250. // Save the information to the registry so it can be used by
  1251. // configuration programs - such as the display applet
  1252. //
  1253. CLWriteRegistryInfo(HwDeviceExtension, HDBrstEN);
  1254. }
  1255. // Always set AGPDataStreaming flag
  1256. hwDeviceExtension->dwAGPDataStreamingFlag = 1;
  1257. //
  1258. // Here we prune valid modes, based on memory requirements.
  1259. // It would be better if we could make the VESA call to determine
  1260. // the modes that the BIOS supports; however, that requires a buffer
  1261. // and it don't work with NT Int 10 support.
  1262. //
  1263. // We prune modes so that we will not annoy the user by presenting
  1264. // modes in the 'Video Applet' which we know the user can't use.
  1265. //
  1266. CLValidateModes(HwDeviceExtension);
  1267. CLPatchModeTable(HwDeviceExtension);
  1268. //
  1269. // If we're doing DMA, we need a page locked buffer.
  1270. //
  1271. ClAllocateCommonBuffer(HwDeviceExtension);
  1272. //
  1273. // Initial the power manager data
  1274. //
  1275. PMNT_Init(hwDeviceExtension);
  1276. //
  1277. // Get the monitor sync polarity. (now just use default)
  1278. //
  1279. hwDeviceExtension->dwPolarity = 0;
  1280. //
  1281. // Initialize the monitor state to "On".
  1282. //
  1283. hwDeviceExtension->MonitorEnabled = TRUE;
  1284. //
  1285. // Indicate we do not wish to be called over
  1286. //
  1287. *Again = 0;
  1288. //
  1289. // Indicate a successful completion status.
  1290. //
  1291. return NO_ERROR;
  1292. } // end CLFindAdapter()
  1293. /****************************************************************************
  1294. * FUNCTION NAME: CLInitialize()
  1295. *
  1296. * DESCRIPTION:
  1297. * This routine does one time initialization of the device.
  1298. *
  1299. * REVISION HISTORY:
  1300. * 5/30/95 Benny Ng Initial version
  1301. ****************************************************************************/
  1302. BOOLEAN CLInitialize (PVOID HwDeviceExtension)
  1303. {
  1304. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  1305. PAGED_CODE();
  1306. VideoDebugPrint((DISPLVL, "Miniport - CLInitialize\n"));
  1307. return TRUE;
  1308. } // end CLInitialize()
  1309. #if 1 // PDR#11350
  1310. /****************************************************************************
  1311. * FUNCTION NAME: CLResetHw()
  1312. *
  1313. * DESCRIPTION:
  1314. * This routine resets the hardware to mode 3.
  1315. ****************************************************************************/
  1316. BOOLEAN CLResetHw(
  1317. PHW_DEVICE_EXTENSION HwDeviceExtension,
  1318. ULONG Columns,
  1319. ULONG Rows
  1320. )
  1321. {
  1322. #undef LAGUNA_REGS
  1323. #define LAGUNA_REGS HwDeviceExtension->RegisterAddress
  1324. ULONG i;
  1325. VOLATILE USHORT* pCursorControl = (USHORT*)(LAGUNA_REGS + 0x00E6);
  1326. VideoDebugPrint((DISPLVL, "Miniport - CLResetHw\n"));
  1327. // Disable the hardware cursor.
  1328. *pCursorControl &= ~0x01;
  1329. #if VS_CONTROL_HACK
  1330. // Enable PCI configuration registers.
  1331. CLEnablePCIConfigMMIO(HwDeviceExtension);
  1332. #endif
  1333. // Set the default text mode.
  1334. if (resetmode != 0xFFFFFFFF)
  1335. {
  1336. VIDEO_MODE VideoMode;
  1337. VideoMode.RequestedMode = resetmode;
  1338. CLSetMode(HwDeviceExtension, &VideoMode);
  1339. }
  1340. return FALSE; // Let the HAL handle the VGA registers.
  1341. }
  1342. #endif
  1343. //**************************************************************************
  1344. // Enable or Disable the MMIO access
  1345. //
  1346. void VS_Control_Hack(PHW_DEVICE_EXTENSION HwDeviceExtension, BOOL Enable)
  1347. {
  1348. #if VS_CONTROL_HACK
  1349. #undef LAGUNA_REGS
  1350. #define LAGUNA_REGS HwDeviceExtension->RegisterAddress
  1351. VOLATILE DWORD* pVS_CONTROL_reg = (DWORD*)(LAGUNA_REGS + 0x3FC);
  1352. if (Enable)
  1353. {
  1354. CLEnablePCIConfigMMIO(HwDeviceExtension);
  1355. }
  1356. else
  1357. {
  1358. // Clear bit 0 to disable PCI register MMIO access
  1359. *pVS_CONTROL_reg = *pVS_CONTROL_reg & 0xFFFFFFFE;
  1360. }
  1361. #endif // if VS_CONTROL_HACK
  1362. }
  1363. //**************************************************************************
  1364. // Write value to VS_CLOCK_CONTROL register
  1365. //
  1366. void Output_To_VS_CLK_CONTROL(PHW_DEVICE_EXTENSION HwDeviceExtension, DWORD val)
  1367. {
  1368. #undef LAGUNA_REGS
  1369. #define LAGUNA_REGS HwDeviceExtension->RegisterAddress
  1370. VOLATILE DWORD* pVSCLK_CONTROL_reg = (DWORD*)(LAGUNA_REGS + 0x3F4);
  1371. VOLATILE DWORD* pVS_CONTROL_reg = (DWORD*)(LAGUNA_REGS + 0x3FC);
  1372. VS_Control_Hack(HwDeviceExtension, TRUE);
  1373. // Enable VS_CLK_CONTROL write
  1374. *pVS_CONTROL_reg = *pVS_CONTROL_reg | 0x800;
  1375. *pVSCLK_CONTROL_reg = val;
  1376. // Disable VS_CLK_CONTROL write
  1377. *pVS_CONTROL_reg = *pVS_CONTROL_reg & 0xFFFFF7FF;
  1378. VS_Control_Hack(HwDeviceExtension, FALSE);
  1379. }
  1380. /****************************************************************************
  1381. * FUNCTION NAME: PMNT_Init()
  1382. *
  1383. * DESCRIPTION: The routine initializes the PM internal variables.
  1384. *
  1385. * Return: None
  1386. ****************************************************************************/
  1387. void PMNT_Init(PHW_DEVICE_EXTENSION hwDeviceExtension)
  1388. {
  1389. LGPWRMGR_DATA* pdata;
  1390. DWORD clkdata;
  1391. DWORD mask;
  1392. int i;
  1393. #undef LAGUNA_REGS
  1394. #define LAGUNA_REGS hwDeviceExtension->RegisterAddress
  1395. VOLATILE DWORD* pVSCLK_CONTROL_reg = (DWORD*)(LAGUNA_REGS + 0x3F4);
  1396. // Points to the internal structure
  1397. pdata = &(hwDeviceExtension->PMdata);
  1398. pdata->wInitSignature = 0xA55A;
  1399. pdata->VS_clk_ctl_state = 0;
  1400. // Initial VS_CLK_CTL image
  1401. clkdata = *pVSCLK_CONTROL_reg;
  1402. pdata->VS_clk_ctl_state = clkdata & 0xFFFF;
  1403. mask = 1;
  1404. for (i=0; i < TOTAL_MOD; i++)
  1405. {
  1406. if ((clkdata & mask) != 0)
  1407. pdata->Mod_refcnt[i] = 1;
  1408. else
  1409. pdata->Mod_refcnt[i] = 0;
  1410. mask = mask << 1;
  1411. };
  1412. // Set internal ACPI state to D0 state
  1413. pdata->ACPI_state = ACPI_D0;
  1414. return;
  1415. }; // PMNT_Init
  1416. /****************************************************************************
  1417. * FUNCTION NAME: PMNT_SetACPIState()
  1418. *
  1419. * DESCRIPTION: This routine sets to the specified ACPI state.
  1420. *
  1421. * Input:
  1422. * state - ACPI states (ACPI_D0, ACPI_D1, ACPI_D2, ACPI_D3).
  1423. *
  1424. ****************************************************************************/
  1425. VP_STATUS PMNT_SetACPIState (PHW_DEVICE_EXTENSION hwDeviceExtension, ULONG state)
  1426. {
  1427. P_LGPWRMGR_DATA pdata;
  1428. DWORD VS_clk_ctl_val;
  1429. pdata = &(hwDeviceExtension->PMdata);
  1430. // Returns FALSE if signature is invalid or invalid state number
  1431. if ((pdata->wInitSignature != 0xA55A) || (state >= TOTAL_ACPI))
  1432. return ERROR_INVALID_PARAMETER;
  1433. switch (state)
  1434. {
  1435. case ACPI_D0:
  1436. {
  1437. VS_clk_ctl_val = pdata->VS_clk_ctl_state;
  1438. break;
  1439. }; // case ACPI_D0
  1440. case ACPI_D1:
  1441. case ACPI_D2:
  1442. {
  1443. VS_clk_ctl_val = ALWAYS_ON_VS_CLK_CTL;
  1444. break;
  1445. }; // case ACPI_D1 & ACPI_D2
  1446. case ACPI_D3:
  1447. {
  1448. VS_clk_ctl_val = 0;
  1449. break;
  1450. }; // case ACPI_D3
  1451. }; // end switch
  1452. // Output the VS_CLK_CONTROL
  1453. Output_To_VS_CLK_CONTROL(hwDeviceExtension, VS_clk_ctl_val);
  1454. // Update internal ACPI state
  1455. pdata->ACPI_state = state;
  1456. return NO_ERROR;
  1457. }; // PMNT_SetACPIState
  1458. /****************************************************************************
  1459. * FUNCTION NAME: PMNT_GetACPIState()
  1460. *
  1461. * DESCRIPTION: This API returns the current ACPI state in use
  1462. *
  1463. * Input:
  1464. * state - Pointer to ULONG variable for returning ACPI state
  1465. * (ACPI_D0, ACPI_D1, ACPI_D2, ACPI_D3).
  1466. *
  1467. ****************************************************************************/
  1468. VP_STATUS PMNT_GetACPIState (PHW_DEVICE_EXTENSION hwDeviceExtension, ULONG* state)
  1469. {
  1470. P_LGPWRMGR_DATA pdata;
  1471. pdata = &(hwDeviceExtension->PMdata);
  1472. // Returns FALSE if signature is invalid
  1473. if (pdata->wInitSignature != 0xA55A)
  1474. return ERROR_INVALID_PARAMETER;
  1475. *state = pdata->ACPI_state;
  1476. return NO_ERROR;
  1477. }; // PMNT_GetACPIState
  1478. /****************************************************************************
  1479. * FUNCTION NAME: PMNT_SetHwModuleState()
  1480. *
  1481. * DESCRIPTION: This routine validates the request for any conflict between
  1482. * the request and the current chip operation. If it is valid,
  1483. * it will enable or disable the specified HW module by turning
  1484. * on or off appropriate HW clocks and returns NO_ERROR. If it is
  1485. * invalid or there is a conflict to the current chip operation,
  1486. * it ignores the request and return FAIL.
  1487. *
  1488. * Input:
  1489. * hwmod - can be one of the following HW modules
  1490. * MOD_2D
  1491. * MOD_3D
  1492. * MOD_TVOUT
  1493. * MOD_VPORT
  1494. * MOD_VGA
  1495. * MOD_EXTMODE
  1496. * MOD_STRETCH
  1497. *
  1498. * state - Ether ENABLE or DISABLE.
  1499. *
  1500. *****************************************************************************/
  1501. VP_STATUS PMNT_SetHwModuleState (PHW_DEVICE_EXTENSION hwDeviceExtension,
  1502. ULONG hwmod,
  1503. ULONG state)
  1504. {
  1505. P_LGPWRMGR_DATA pdata;
  1506. pdata = &(hwDeviceExtension->PMdata);
  1507. // Returns FALSE if signature is invalid || invalid module number
  1508. if ((pdata->wInitSignature != 0xA55A) || (hwmod >= TOTAL_MOD))
  1509. return ERROR_INVALID_PARAMETER;
  1510. // Returns FALSE if ACPI state is not in D0 state
  1511. if (pdata->ACPI_state != ACPI_D0)
  1512. return ERROR_INVALID_FUNCTION;
  1513. // Perform the operation on VS_CLK_CONTROL
  1514. if (state == ENABLE)
  1515. {
  1516. // Enable the module
  1517. pdata->VS_clk_ctl_state |= LgPM_vs_clk_table[hwmod];
  1518. if (pdata->Mod_refcnt[hwmod] != 0xFFFFFFFF)
  1519. pdata->Mod_refcnt[hwmod]++;
  1520. }
  1521. else
  1522. {
  1523. // Disable the module
  1524. if (pdata->Mod_refcnt[hwmod] != 0)
  1525. {
  1526. pdata->Mod_refcnt[hwmod]--;
  1527. if (pdata->Mod_refcnt[hwmod] == 0)
  1528. pdata->VS_clk_ctl_state &= (~LgPM_vs_clk_table[hwmod]);
  1529. }; // endif (Mod_refcnt[hwmod] != 0)
  1530. }; // endif (state == ENABLE)
  1531. // Output the VS_CLK_CONTROL
  1532. Output_To_VS_CLK_CONTROL(hwDeviceExtension, pdata->VS_clk_ctl_state);
  1533. return NO_ERROR;
  1534. }; // PMNT_SetHwModuleState
  1535. /****************************************************************************
  1536. * FUNCTION NAME: PMNT_GetHwModuleState()
  1537. *
  1538. * DESCRIPTION: This routine returns the current state of a particular
  1539. * hardware module.
  1540. *
  1541. * Input:
  1542. * hwmod - can be one of the following HW modules
  1543. * MOD_2D
  1544. * MOD_3D
  1545. * MOD_TVOUT
  1546. * MOD_VPORT
  1547. * MOD_VGA
  1548. * MOD_EXTMODE
  1549. * MOD_STRETCH
  1550. *
  1551. * state - Pointer to ULONG variable for returning the HW module state
  1552. * (ENABLE or DISABLE).
  1553. *
  1554. ****************************************************************************/
  1555. VP_STATUS PMNT_GetHwModuleState (PHW_DEVICE_EXTENSION hwDeviceExtension,
  1556. ULONG hwmod,
  1557. ULONG* state)
  1558. {
  1559. P_LGPWRMGR_DATA pdata;
  1560. pdata = &(hwDeviceExtension->PMdata);
  1561. *state = DISABLE;
  1562. // Returns FALSE if signature is invalid || invalid module number
  1563. if ((pdata->wInitSignature != 0xA55A) || (hwmod >= TOTAL_MOD))
  1564. return ERROR_INVALID_PARAMETER;
  1565. // Returns FALSE if ACPI state is not in D0 state
  1566. if (pdata->ACPI_state != ACPI_D0)
  1567. return ERROR_INVALID_FUNCTION;
  1568. if (pdata->Mod_refcnt[hwmod] != 0)
  1569. *state = ENABLE;
  1570. return NO_ERROR;
  1571. }; // PMNT_GetHwModuleState
  1572. /****************************************************************************
  1573. * FUNCTION NAME: PMNT_Close()
  1574. *
  1575. * DESCRIPTION: This routine closes down the power management module.
  1576. *
  1577. ****************************************************************************/
  1578. void PMNT_Close (PHW_DEVICE_EXTENSION hwDeviceExtension)
  1579. {
  1580. P_LGPWRMGR_DATA pdata;
  1581. pdata = &(hwDeviceExtension->PMdata);
  1582. // Returns FALSE if signature is invalid
  1583. if (pdata->wInitSignature != 0xA55A)
  1584. return;
  1585. pdata->wInitSignature = 0x0;
  1586. }; // PMNT_Close
  1587. /****************************************************************************
  1588. * FUNCTION NAME: CLStartIO()
  1589. *
  1590. * DESCRIPTION:
  1591. * This routine is the main execution routine for the miniport driver. It
  1592. * accepts a Video Request Packet, performs the request, and then returns
  1593. * with the appropriate status.
  1594. *
  1595. * REVISION HISTORY:
  1596. * 5/30/95 Benny Ng Initial version
  1597. ****************************************************************************/
  1598. BOOLEAN CLStartIO (PVOID HwDeviceExtension,
  1599. PVIDEO_REQUEST_PACKET RequestPacket)
  1600. {
  1601. VP_STATUS status;
  1602. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  1603. PVIDEO_POWER_MANAGEMENT PMInformation;
  1604. PVIDEO_MODE_INFORMATION modeInformation;
  1605. PVIDEO_MEMORY_INFORMATION memoryInformation;
  1606. VIDEO_MODE videoMode;
  1607. PVIDEO_PUBLIC_ACCESS_RANGES portAccess;
  1608. PVIDEO_MEMORY mappedMemory;
  1609. PMODETABLE pVideoMode;
  1610. ULONG inIoSpace;
  1611. ULONG i;
  1612. PHYSICAL_ADDRESS AdjFBAddr;
  1613. ULONG AdjFBLength;
  1614. ULONG ReservedFBLength;
  1615. VOLATILE PUCHAR pOffset2D_reg;
  1616. ULONG FBOffset;
  1617. ULONG Temp;
  1618. PVIDEO_SHARE_MEMORY pShareMemory;
  1619. PVIDEO_SHARE_MEMORY_INFORMATION pShareMemoryInformation;
  1620. PHYSICAL_ADDRESS shareAddress;
  1621. PVOID virtualAddress;
  1622. ULONG sharedViewSize;
  1623. PAGED_CODE();
  1624. //
  1625. // If the current power state is VideoPowerOff, fails all
  1626. // IOCTL_VIDEO_XXX requests until the IOCTL_VIDEO_SET_POWER_MANAGEMENT
  1627. // request that resets to a power-on condition
  1628. //
  1629. if ((hwDeviceExtension->PowerState == VideoPowerOff))
  1630. {
  1631. VideoDebugPrint((DISPLVL, "Miniport - PowerOff\n"));
  1632. return FALSE;
  1633. };
  1634. //
  1635. // Switch on the IoContolCode in the RequestPacket. It indicates which
  1636. // function must be performed by the driver.
  1637. //
  1638. switch (RequestPacket->IoControlCode)
  1639. {
  1640. //-----------------------------------------------------
  1641. #if 0 // not supported anymore
  1642. //-----------------------------------------------------
  1643. case IOCTL_GET_BIOS_VERSION:
  1644. {
  1645. WORD *pOut = (WORD *) RequestPacket->OutputBuffer;
  1646. if ((RequestPacket->OutputBufferLength <
  1647. (RequestPacket->StatusBlock->Information = sizeof(WORD))))
  1648. {
  1649. status = ERROR_INSUFFICIENT_BUFFER;
  1650. break;
  1651. };
  1652. *pOut = hwDeviceExtension->BIOSVersion;
  1653. status = NO_ERROR;
  1654. break;
  1655. }; // end case IOCTL_GET_BIOS_VERSION
  1656. //-----------------------------------------------------
  1657. case IOCTL_SET_HW_MODULE_POWER_STATE:
  1658. {
  1659. PLGPM_IN_STRUCT pInLGPM;
  1660. PLGPM_OUT_STRUCT pOutLGPM;
  1661. if ((RequestPacket->OutputBufferLength <
  1662. (RequestPacket->StatusBlock->Information =
  1663. sizeof(PLGPM_OUT_STRUCT))) ||
  1664. (RequestPacket->InputBufferLength < sizeof(LGPM_IN_STRUCT)))
  1665. {
  1666. status = ERROR_INSUFFICIENT_BUFFER;
  1667. break;
  1668. };
  1669. pInLGPM = (PLGPM_IN_STRUCT) RequestPacket->InputBuffer;
  1670. pOutLGPM = (PLGPM_OUT_STRUCT) RequestPacket->OutputBuffer;
  1671. status = PMNT_SetHwModuleState (hwDeviceExtension,
  1672. pInLGPM->arg1,
  1673. pInLGPM->arg2);
  1674. break;
  1675. }; // end case IOCTL_SET_HW_MODULE_POWER_STATE
  1676. //-----------------------------------------------------
  1677. case IOCTL_GET_HW_MODULE_POWER_STATE:
  1678. {
  1679. PLGPM_IN_STRUCT pInLGPM;
  1680. PLGPM_OUT_STRUCT pOutLGPM;
  1681. if ((RequestPacket->OutputBufferLength <
  1682. (RequestPacket->StatusBlock->Information =
  1683. sizeof(PLGPM_OUT_STRUCT))) ||
  1684. (RequestPacket->InputBufferLength < sizeof(LGPM_IN_STRUCT)))
  1685. {
  1686. status = ERROR_INSUFFICIENT_BUFFER;
  1687. break;
  1688. };
  1689. pInLGPM = (PLGPM_IN_STRUCT) RequestPacket->InputBuffer;
  1690. pOutLGPM = (PLGPM_OUT_STRUCT) RequestPacket->OutputBuffer;
  1691. status = PMNT_GetHwModuleState (hwDeviceExtension,
  1692. pInLGPM->arg1,
  1693. (ULONG*) pInLGPM->arg2);
  1694. break;
  1695. }; // end case IOCTL_GET_HW_MODULE_POWER_STATE
  1696. #endif// 0 // not supported anymore
  1697. //-----------------------------------------------------
  1698. case IOCTL_GET_AGPDATASTREAMING:
  1699. {
  1700. DWORD *pOut = (DWORD *) RequestPacket->OutputBuffer;
  1701. if ((RequestPacket->OutputBufferLength <
  1702. (RequestPacket->StatusBlock->Information = sizeof(DWORD))))
  1703. {
  1704. status = ERROR_INSUFFICIENT_BUFFER;
  1705. break;
  1706. };
  1707. *pOut = hwDeviceExtension->dwAGPDataStreamingFlag;
  1708. status = NO_ERROR;
  1709. break;
  1710. }; // end case IOCTL_GET_AGPDATASTREAMING
  1711. //-----------------------------------------------------
  1712. case IOCTL_VIDEO_SHARE_VIDEO_MEMORY:
  1713. VideoDebugPrint((DISPLVL, "Miniport - ShareVideoMemory\n"));
  1714. #ifdef DBGBRK
  1715. DbgBreakPoint();
  1716. #endif
  1717. if (
  1718. (RequestPacket->OutputBufferLength
  1719. < sizeof(VIDEO_SHARE_MEMORY_INFORMATION))
  1720. || (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)))
  1721. {
  1722. VideoDebugPrint((1,
  1723. "Miniport - SHARE_VIDEO_MEM-INSUFFICIENT_BUF\n"));
  1724. status = ERROR_INSUFFICIENT_BUFFER;
  1725. break;
  1726. };
  1727. pShareMemory = RequestPacket->InputBuffer;
  1728. #if 0 // extra rectangle at bottom makes this more complex, I'm taking the
  1729. // easy way out and assume that the display driver is asking for
  1730. // a reasonable ammount of space
  1731. if ((pShareMemory->ViewOffset > hwDeviceExtension->AdapterMemorySize) ||
  1732. ((pShareMemory->ViewOffset + pShareMemory->ViewSize) >
  1733. hwDeviceExtension->AdapterMemorySize))
  1734. {
  1735. VideoDebugPrint((1, "Miniport - SHARE_VIDEO_MEM-INVALID_PARAM\n"));
  1736. status = ERROR_INVALID_PARAMETER;
  1737. break;
  1738. };
  1739. #endif
  1740. RequestPacket->StatusBlock->Information =
  1741. sizeof(VIDEO_SHARE_MEMORY_INFORMATION);
  1742. // Beware: the input buffer and the output buffer are the same
  1743. // buffer, and therefore data should not be copied from one to the
  1744. // other
  1745. //
  1746. virtualAddress = pShareMemory->ProcessHandle;
  1747. sharedViewSize = pShareMemory->ViewSize;
  1748. inIoSpace = 0;
  1749. // Enable the USWC on the P6 processor
  1750. #ifdef VIDEO_MEMORY_SPACE_P6CACHE
  1751. if (hwDeviceExtension->ChipID != CL_GD5462)
  1752. inIoSpace |= VIDEO_MEMORY_SPACE_P6CACHE;
  1753. #endif
  1754. // NOTE: we are ignoring ViewOffset
  1755. //
  1756. shareAddress.QuadPart = hwDeviceExtension->PhysicalFrameAddress.QuadPart;
  1757. status = VideoPortMapMemory(hwDeviceExtension,
  1758. shareAddress,
  1759. &sharedViewSize,
  1760. &inIoSpace,
  1761. &virtualAddress);
  1762. pShareMemoryInformation = RequestPacket->OutputBuffer;
  1763. pShareMemoryInformation->SharedViewOffset = pShareMemory->ViewOffset;
  1764. pShareMemoryInformation->VirtualAddress = virtualAddress;
  1765. pShareMemoryInformation->SharedViewSize = sharedViewSize;
  1766. break;
  1767. //-----------------------------------------------------
  1768. case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY:
  1769. VideoDebugPrint((DISPLVL, "Miniport - UnshareVideoMemory\n"));
  1770. #ifdef DBGBRK
  1771. DbgBreakPoint();
  1772. #endif
  1773. if (RequestPacket->InputBufferLength < sizeof(VIDEO_SHARE_MEMORY))
  1774. {
  1775. status = ERROR_INSUFFICIENT_BUFFER;
  1776. break;
  1777. };
  1778. pShareMemory = RequestPacket->InputBuffer;
  1779. status = VideoPortUnmapMemory(hwDeviceExtension,
  1780. pShareMemory->RequestedVirtualAddress,
  1781. pShareMemory->ProcessHandle);
  1782. break;
  1783. //-----------------------------------------------------
  1784. case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
  1785. VideoDebugPrint((DISPLVL, "Miniport - MapVideoMemory\n"));
  1786. #ifdef DBGBRK
  1787. DbgBreakPoint();
  1788. #endif
  1789. if ((RequestPacket->OutputBufferLength <
  1790. (RequestPacket->StatusBlock->Information =
  1791. sizeof(VIDEO_MEMORY_INFORMATION))) ||
  1792. (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)))
  1793. {
  1794. status = ERROR_INSUFFICIENT_BUFFER;
  1795. break;
  1796. };
  1797. memoryInformation = RequestPacket->OutputBuffer;
  1798. memoryInformation->VideoRamBase = ((PVIDEO_MEMORY)
  1799. (RequestPacket->InputBuffer))->RequestedVirtualAddress;
  1800. //
  1801. // Adjust the FB starting address and size based on OFFSET_2D
  1802. //
  1803. pOffset2D_reg = hwDeviceExtension->RegisterAddress + OFFSET_2D_REG;
  1804. FBOffset = ((ULONG) *pOffset2D_reg) & 0xFF;
  1805. VideoDebugPrint((DISPLVL, "Miniport - OFFSET_2D=%xH\n", FBOffset));
  1806. Temp = hwDeviceExtension->CurrentMode->BytesPerScanLine;
  1807. FBOffset = (FBOffset * 64) * Temp;
  1808. AdjFBAddr = hwDeviceExtension->PhysicalFrameAddress;
  1809. AdjFBAddr.LowPart += FBOffset;
  1810. ReservedFBLength = hwDeviceExtension->PhysicalFrameLength;
  1811. // v-normmi added room for extra rectangle at bottom left
  1812. if (ReservedFBLength < 0x800000)
  1813. {
  1814. ReservedFBLength += (Temp*4*32); // pitch * 4 max height tiles
  1815. }
  1816. //
  1817. // Do memory mapping
  1818. //
  1819. inIoSpace = 0;
  1820. // Enable the USWC on the P6 processor
  1821. #ifdef VIDEO_MEMORY_SPACE_P6CACHE
  1822. if (hwDeviceExtension->ChipID != CL_GD5462)
  1823. inIoSpace |= VIDEO_MEMORY_SPACE_P6CACHE;
  1824. #endif
  1825. status = VideoPortMapMemory(hwDeviceExtension,
  1826. AdjFBAddr,
  1827. &ReservedFBLength,
  1828. &inIoSpace,
  1829. &(memoryInformation->VideoRamBase));
  1830. //
  1831. // The frame buffer and virtual memory are equivalent in this
  1832. // case.
  1833. //
  1834. memoryInformation->FrameBufferBase = memoryInformation->VideoRamBase;
  1835. //
  1836. // This is the *real* amount of memory on the board.
  1837. // This gets reported back to the display driver.
  1838. //
  1839. AdjFBLength = hwDeviceExtension->FrameLength - FBOffset;
  1840. memoryInformation->VideoRamLength = AdjFBLength;
  1841. memoryInformation->FrameBufferLength = AdjFBLength;
  1842. VideoDebugPrint((DISPLVL, "Miniport - DD FB virtual spac=%xH\n",
  1843. memoryInformation->FrameBufferBase));
  1844. break;
  1845. //-----------------------------------------------------
  1846. case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
  1847. VideoDebugPrint((DISPLVL, "Miniport - UnMapVideoMemory\n"));
  1848. #ifdef DBGBRK
  1849. DbgBreakPoint();
  1850. #endif
  1851. if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))
  1852. {
  1853. status = ERROR_INSUFFICIENT_BUFFER;
  1854. break;
  1855. };
  1856. status = VideoPortUnmapMemory(hwDeviceExtension,
  1857. ((PVIDEO_MEMORY) (RequestPacket->InputBuffer))->RequestedVirtualAddress,
  1858. 0);
  1859. break;
  1860. //-----------------------------------------------------
  1861. case IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES:
  1862. VideoDebugPrint((DISPLVL, "Miniport - QueryPublicAccessRanges\n"));
  1863. #ifdef DBGBRK
  1864. DbgBreakPoint();
  1865. #endif
  1866. if (RequestPacket->OutputBufferLength <
  1867. (RequestPacket->StatusBlock->Information = sizeof(VIDEO_PUBLIC_ACCESS_RANGES)))
  1868. {
  1869. status = ERROR_INSUFFICIENT_BUFFER;
  1870. break;
  1871. };
  1872. portAccess = RequestPacket->OutputBuffer;
  1873. portAccess->VirtualAddress = (PVOID) NULL; // Requested VA
  1874. portAccess->InIoSpace = FALSE;
  1875. portAccess->MappedInIoSpace = portAccess->InIoSpace;
  1876. status = VideoPortMapMemory(hwDeviceExtension,
  1877. hwDeviceExtension->PhysicalRegisterAddress,
  1878. &hwDeviceExtension->RegisterLength,
  1879. &portAccess->MappedInIoSpace,
  1880. &portAccess->VirtualAddress);
  1881. VideoDebugPrint((DISPLVL, "Miniport - DD Reg virtual spac=%xH\n",
  1882. portAccess->VirtualAddress));
  1883. break;
  1884. //-----------------------------------------------------
  1885. case IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES:
  1886. VideoDebugPrint((DISPLVL, "Miniport - FreePublicAccessRanges\n"));
  1887. #ifdef DBGBRK
  1888. DbgBreakPoint();
  1889. #endif
  1890. if (RequestPacket->InputBufferLength < 2 * sizeof(VIDEO_MEMORY))
  1891. {
  1892. status = ERROR_INSUFFICIENT_BUFFER;
  1893. break;
  1894. };
  1895. status = NO_ERROR;
  1896. mappedMemory = RequestPacket->InputBuffer;
  1897. for (i = 0; i < 2; i++)
  1898. {
  1899. if (mappedMemory->RequestedVirtualAddress != NULL)
  1900. {
  1901. status = VideoPortUnmapMemory(hwDeviceExtension,
  1902. mappedMemory->RequestedVirtualAddress,
  1903. 0);
  1904. };
  1905. mappedMemory++;
  1906. } // end for
  1907. break;
  1908. //-----------------------------------------------------
  1909. case IOCTL_VIDEO_QUERY_AVAIL_MODES:
  1910. VideoDebugPrint((DISPLVL, "Miniport - QueryAvailableModes\n"));
  1911. #ifdef DBGBRK
  1912. DbgBreakPoint();
  1913. #endif
  1914. if (RequestPacket->OutputBufferLength <
  1915. (RequestPacket->StatusBlock->Information =
  1916. hwDeviceExtension->NumAvailableModes * sizeof(VIDEO_MODE_INFORMATION)))
  1917. {
  1918. status = ERROR_INSUFFICIENT_BUFFER;
  1919. break;
  1920. };
  1921. modeInformation = (PVIDEO_MODE_INFORMATION) RequestPacket->OutputBuffer;
  1922. //
  1923. // For each mode supported by the card, store the mode characteristics
  1924. // in the output buffer.
  1925. //
  1926. for (i = 0; i < TotalVideoModes; i++)
  1927. {
  1928. // Points to the selected mode table slot
  1929. //
  1930. pVideoMode = &ModeTable[i];
  1931. // Check whether the mode is valid
  1932. //
  1933. if (pVideoMode->ValidMode)
  1934. {
  1935. //
  1936. // Copy the selected mode information into the
  1937. // VIDEO_MODE_INFORMATION structure buffer.
  1938. //
  1939. CLCopyModeInfo(HwDeviceExtension, modeInformation, i, pVideoMode);
  1940. //
  1941. // Points to next VIDEO_MODE_INFORMATION structure slot
  1942. //
  1943. modeInformation++;
  1944. };
  1945. } /* end for */
  1946. status = NO_ERROR;
  1947. break;
  1948. //-----------------------------------------------------
  1949. case IOCTL_VIDEO_QUERY_CURRENT_MODE:
  1950. VideoDebugPrint((DISPLVL, "Miniport - QueryCurrentModes\n"));
  1951. #ifdef DBGBRK
  1952. DbgBreakPoint();
  1953. #endif
  1954. //
  1955. // Find out the size of the data to be put in the the buffer and return
  1956. // that in the status information (whether or not the information is
  1957. // there). If the buffer passed in is not large enough return an
  1958. // appropriate error code.
  1959. //
  1960. if (RequestPacket->OutputBufferLength <
  1961. (RequestPacket->StatusBlock->Information =
  1962. sizeof(VIDEO_MODE_INFORMATION)))
  1963. {
  1964. status = ERROR_INSUFFICIENT_BUFFER;
  1965. break;
  1966. };
  1967. //
  1968. // check if a mode has been set
  1969. //
  1970. if (hwDeviceExtension->CurrentMode == NULL)
  1971. {
  1972. status = ERROR_INVALID_FUNCTION;
  1973. break;
  1974. };
  1975. modeInformation = (PVIDEO_MODE_INFORMATION) RequestPacket->OutputBuffer;
  1976. // Copy the selected mode information into the
  1977. // VIDEO_MODE_INFORMATION structure provided by NT.
  1978. //
  1979. CLCopyModeInfo(hwDeviceExtension,
  1980. modeInformation,
  1981. hwDeviceExtension->CurrentModeNum,
  1982. hwDeviceExtension->CurrentMode);
  1983. status = NO_ERROR;
  1984. break;
  1985. //-----------------------------------------------------
  1986. case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
  1987. VideoDebugPrint((DISPLVL, "Miniport - QueryNumAvailableModes\n"));
  1988. #ifdef DBGBRK
  1989. DbgBreakPoint();
  1990. #endif
  1991. //
  1992. // Find out the size of the data to be put in the the buffer and
  1993. // return that in the status information (whether or not the
  1994. // information is there). If the buffer passed in is not large
  1995. // enough return an appropriate error code.
  1996. //
  1997. if (RequestPacket->OutputBufferLength <
  1998. (RequestPacket->StatusBlock->Information = sizeof(VIDEO_NUM_MODES)))
  1999. {
  2000. status = ERROR_INSUFFICIENT_BUFFER;
  2001. break;
  2002. };
  2003. ((PVIDEO_NUM_MODES)RequestPacket->OutputBuffer)->NumModes =
  2004. hwDeviceExtension->NumAvailableModes;
  2005. ((PVIDEO_NUM_MODES)RequestPacket->OutputBuffer)->ModeInformationLength =
  2006. sizeof(VIDEO_MODE_INFORMATION);
  2007. status = NO_ERROR;
  2008. break;
  2009. //-----------------------------------------------------
  2010. case IOCTL_VIDEO_SET_COLOR_REGISTERS:
  2011. VideoDebugPrint((DISPLVL, "Miniport - SetColorRegs\n"));
  2012. #ifdef DBGBRK
  2013. DbgBreakPoint();
  2014. #endif
  2015. status = CLSetColorLookup(HwDeviceExtension,
  2016. (PVIDEO_CLUT) RequestPacket->InputBuffer,
  2017. RequestPacket->InputBufferLength);
  2018. break;
  2019. //-----------------------------------------------------
  2020. case IOCTL_VIDEO_SET_CURRENT_MODE:
  2021. VideoDebugPrint((DISPLVL, "Miniport - SetCurrentMode\n"));
  2022. #ifdef DBGBRK
  2023. DbgBreakPoint();
  2024. #endif
  2025. //
  2026. // Check if the size of the data in the input buffer is large enough.
  2027. //
  2028. if (RequestPacket->InputBufferLength < sizeof(VIDEO_MODE))
  2029. {
  2030. status = ERROR_INSUFFICIENT_BUFFER;
  2031. break;
  2032. };
  2033. status = CLSetMode(HwDeviceExtension,
  2034. (PVIDEO_MODE) RequestPacket->InputBuffer);
  2035. break;
  2036. //-----------------------------------------------------
  2037. case IOCTL_VIDEO_RESET_DEVICE:
  2038. VideoDebugPrint((DISPLVL, "Miniport - ResetDevice\n"));
  2039. #if VS_CONTROL_HACK
  2040. CLEnablePCIConfigMMIO(HwDeviceExtension);
  2041. #endif
  2042. #ifdef DBGBRK
  2043. DbgBreakPoint();
  2044. #endif
  2045. if ( ! hwDeviceExtension->Dont_Do_VGA ) // Only if VGA regs are available.
  2046. {
  2047. // Initialize the DAC to 0 (black).
  2048. //
  2049. // Turn off the screen at the DAC.
  2050. //
  2051. VideoPortWritePortUchar((PUCHAR) 0x3c6, (UCHAR) 0x0);
  2052. for (i = 0; i < 256; i++)
  2053. {
  2054. VideoPortWritePortUchar((PUCHAR) 0x3c8, (UCHAR) i);
  2055. VideoPortWritePortUchar((PUCHAR) 0x3c9, (UCHAR) 0);
  2056. VideoPortWritePortUchar((PUCHAR) 0x3c9, (UCHAR) 0);
  2057. VideoPortWritePortUchar((PUCHAR) 0x3c9, (UCHAR) 0);
  2058. } // end for
  2059. //
  2060. // Turn on the screen at the DAC
  2061. //
  2062. VideoPortWritePortUchar((PUCHAR) 0x3c6, (UCHAR) 0xFF);
  2063. }
  2064. videoMode.RequestedMode = resetmode; // mode.ini
  2065. //videoMode.RequestedMode = DEFAULT_MODE; // BIOS
  2066. status = CLSetMode(HwDeviceExtension, (PVIDEO_MODE) &videoMode);
  2067. break;
  2068. #if 0 // not supported anymore
  2069. //-----------------------------------------------------
  2070. case IOCTL_VIDEO_GET_POWER_MANAGEMENT:
  2071. VideoDebugPrint((DISPLVL, "Miniport - GetPowerManagement\n"));
  2072. #ifdef DBGBRK
  2073. DbgBreakPoint();
  2074. #endif
  2075. //
  2076. // Find out the size of the data to be put in the the buffer and return
  2077. // that in the status information (whether or not the information is
  2078. // there). If the buffer passed in is not large enough return an
  2079. // appropriate error code.
  2080. //
  2081. if (RequestPacket->OutputBufferLength <
  2082. (RequestPacket->StatusBlock->Information =
  2083. sizeof(VIDEO_POWER_MANAGEMENT)))
  2084. {
  2085. status = ERROR_INSUFFICIENT_BUFFER;
  2086. break;
  2087. };
  2088. PMInformation = (PVIDEO_POWER_MANAGEMENT) RequestPacket->OutputBuffer;
  2089. status = CLPowerManagement(HwDeviceExtension, PMInformation, FALSE);
  2090. break;
  2091. //-----------------------------------------------------
  2092. case IOCTL_CL_STRING_DISPLAY:
  2093. VideoDebugPrint((DISPLVL, "Miniport - StringDisplay\n"));
  2094. #ifdef DBGBRK
  2095. DbgBreakPoint();
  2096. #endif
  2097. HalDisplayString((PUCHAR) RequestPacket->InputBuffer);
  2098. status = NO_ERROR;
  2099. break;
  2100. #endif// 0 // not supported anymore
  2101. // ----------------------------------------------------------------
  2102. case IOCTL_CL_GET_COMMON_BUFFER:
  2103. {
  2104. //
  2105. // Communicate to the display driver the location and size of the
  2106. // common DMA buffer.
  2107. //
  2108. // The display driver gives us a pointer to this structure.
  2109. // We fill in the values here.
  2110. //
  2111. // struct {
  2112. // PUCHAR PhysAddress;
  2113. // PUCHAR VirtAddress;
  2114. // ULONG Length;
  2115. // } *pCommonBufferInfo;
  2116. COMMON_BUFFER_INFO *pCommonBufferInfo;
  2117. VideoDebugPrint((DISPLVL, "Miniport - Get Common Buffer.\n"));
  2118. RequestPacket->StatusBlock->Information = sizeof(COMMON_BUFFER_INFO);
  2119. if (RequestPacket->OutputBufferLength < sizeof(COMMON_BUFFER_INFO))
  2120. {
  2121. VideoDebugPrint((DISPLVL, "Miniport - Buffer size mismatch.\n"));
  2122. status = ERROR_INSUFFICIENT_BUFFER;
  2123. break;
  2124. }
  2125. //
  2126. // Retrieve pointer to CommonBufferInfo struct.
  2127. //
  2128. pCommonBufferInfo = (COMMON_BUFFER_INFO *)(RequestPacket->OutputBuffer);
  2129. //
  2130. // Fill it in.
  2131. //
  2132. pCommonBufferInfo->PhysAddress =
  2133. hwDeviceExtension->PhysicalCommonBufferAddr;
  2134. pCommonBufferInfo->VirtAddress =
  2135. hwDeviceExtension->VirtualCommonBufferAddr;
  2136. pCommonBufferInfo->Length = hwDeviceExtension->CommonBufferSize;
  2137. status = NO_ERROR;
  2138. }
  2139. break;
  2140. #if VS_CONTROL_HACK
  2141. // ----------------------------------------------------------------
  2142. case IOCTL_VIDEO_ENABLE_PCI_MMIO:
  2143. {
  2144. status = CLEnablePCIConfigMMIO(HwDeviceExtension);
  2145. break;
  2146. }
  2147. #endif // VS_CONTROL_HACK
  2148. #if LOG_FILE
  2149. // ----------------------------------------------------------------
  2150. case IOCTL_CL_CREATE_LOG_FILE:
  2151. {
  2152. LogFileHandle = CreateLogFile();
  2153. status = NO_ERROR;
  2154. }
  2155. break;
  2156. // ----------------------------------------------------------------
  2157. case IOCTL_CL_WRITE_LOG_FILE:
  2158. {
  2159. WriteLogFile(LogFileHandle,
  2160. RequestPacket->InputBuffer,
  2161. RequestPacket->InputBufferLength);
  2162. status = NO_ERROR;
  2163. }
  2164. break;
  2165. // ----------------------------------------------------------------
  2166. case IOCTL_CL_CLOSE_LOG_FILE:
  2167. {
  2168. CloseLogFile(LogFileHandle);
  2169. status = NO_ERROR;
  2170. }
  2171. break;
  2172. #endif
  2173. #if 1
  2174. // ----------------------------------------------------------------
  2175. case IOCTL_STALL:
  2176. {
  2177. VideoPortStallExecution(*(PULONG) RequestPacket->InputBuffer);
  2178. status = NO_ERROR;
  2179. }
  2180. break;
  2181. #endif
  2182. //-----------------------------------------------------
  2183. // if we get here, an invalid IoControlCode was specified.
  2184. //
  2185. default:
  2186. VideoDebugPrint((DISPLVL, "Miniport - invalid command= %xH\n",
  2187. RequestPacket->IoControlCode));
  2188. #ifdef DBGBRK
  2189. DbgBreakPoint();
  2190. #endif
  2191. status = ERROR_INVALID_FUNCTION;
  2192. break;
  2193. } // end switch
  2194. RequestPacket->StatusBlock->Status = status;
  2195. return TRUE;
  2196. } // end CLStartIO()
  2197. /****************************************************************************
  2198. * FUNCTION NAME: CLSetColorLookup()
  2199. *
  2200. * DESCRIPTION:
  2201. * This routine sets a specified portion of the color lookup table settings.
  2202. *
  2203. * REVISION HISTORY:
  2204. * 5/30/95 Benny Ng Initial version
  2205. ****************************************************************************/
  2206. VP_STATUS CLSetColorLookup (PHW_DEVICE_EXTENSION HwDeviceExtension,
  2207. PVIDEO_CLUT ClutBuffer,
  2208. ULONG ClutBufferSize)
  2209. {
  2210. USHORT i;
  2211. USHORT FirstEntry;
  2212. #undef LAGUNA_REGS
  2213. #define LAGUNA_REGS HwDeviceExtension->RegisterAddress
  2214. VOLATILE BYTE* pPal_Addr_Reg = (BYTE*)(LAGUNA_REGS + 0xA8);
  2215. VOLATILE BYTE* pPal_Data_Reg = (BYTE*)(LAGUNA_REGS + 0xAC);
  2216. ULONG cCounter = 0;
  2217. PAGED_CODE();
  2218. //
  2219. // Check if the size of the data in the input buffer is large enough.
  2220. //
  2221. if ((ClutBufferSize < sizeof(VIDEO_CLUT) - sizeof(ULONG)) ||
  2222. (ClutBufferSize < sizeof(VIDEO_CLUT) +
  2223. (sizeof(ULONG) * (ClutBuffer->NumEntries - 1))))
  2224. {
  2225. return ERROR_INSUFFICIENT_BUFFER;
  2226. };
  2227. //
  2228. // Check to see if the parameters are valid.
  2229. //
  2230. if ((ClutBuffer->NumEntries == 0) ||
  2231. (ClutBuffer->FirstEntry > VIDEO_MAX_COLOR_REGISTER) ||
  2232. (ClutBuffer->FirstEntry + ClutBuffer->NumEntries >
  2233. VIDEO_MAX_COLOR_REGISTER + 1))
  2234. {
  2235. return ERROR_INVALID_PARAMETER;
  2236. };
  2237. //
  2238. // Set CLUT registers directly on the hardware
  2239. //
  2240. FirstEntry = ClutBuffer->FirstEntry;
  2241. for (i = 0; i < ClutBuffer->NumEntries; i++)
  2242. {
  2243. // Wait for blanking
  2244. if ((HwDeviceExtension->Dont_Do_VGA == FALSE) &&
  2245. (HwDeviceExtension->MonitorEnabled == TRUE)) // Only wait for blanking if VGA regs are available.
  2246. {
  2247. #if 1 // PDR#11284
  2248. if (cCounter-- == 0)
  2249. {
  2250. // Wait for end of vertical retrace.
  2251. while (VideoPortReadPortUchar((PUCHAR) 0x3DA) & 0x08) ;
  2252. // Wait for beginning of display disable.
  2253. while( (VideoPortReadPortUchar((PUCHAR) 0x3DA) & 0x01)) ;
  2254. while(! (VideoPortReadPortUchar((PUCHAR) 0x3DA) & 0x01)) ;
  2255. // Load the counter.
  2256. cCounter = (VideoPortReadPortUchar((PUCHAR) 0x3DA) & 0x08)
  2257. ? 256 : 0;
  2258. }
  2259. #else
  2260. // Wait for bit-0 becomes 0
  2261. while(1)
  2262. {
  2263. unsigned char stat;
  2264. stat = VideoPortReadPortUchar( (PUCHAR)0x3DA );
  2265. if (!(stat & 1)) // Test bit 0. If it's a 0
  2266. break; // then continue.
  2267. }
  2268. // Wait for bit-0 becomes 1
  2269. while(1)
  2270. {
  2271. unsigned char stat;
  2272. stat = VideoPortReadPortUchar( (PUCHAR)0x3DA );
  2273. if (stat & 1) // Test bit 0. If it's a 1
  2274. break; // then continue.
  2275. }
  2276. #endif
  2277. }
  2278. // Write the entry.
  2279. *pPal_Addr_Reg = (UCHAR) (FirstEntry + i);
  2280. *pPal_Data_Reg = (UCHAR) (ClutBuffer->LookupTable[i].RgbArray.Red);
  2281. *pPal_Data_Reg = (UCHAR) (ClutBuffer->LookupTable[i].RgbArray.Green);
  2282. *pPal_Data_Reg = (UCHAR) (ClutBuffer->LookupTable[i].RgbArray.Blue);
  2283. } // end for
  2284. return NO_ERROR;
  2285. } // end CLSetColorLookup()
  2286. /****************************************************************************
  2287. * FUNCTION NAME: CLFindVmemSize()
  2288. *
  2289. * DESCRIPTION:
  2290. * This routine returns the amount of RAM installed on the card.
  2291. *
  2292. * REVISION HISTORY:
  2293. * 5/30/95 Benny Ng Initial version
  2294. ****************************************************************************/
  2295. ULONG CLFindVmemSize (PHW_DEVICE_EXTENSION HwDeviceExtension)
  2296. {
  2297. UCHAR OrigSRindex;
  2298. ULONG memsize;
  2299. #define LAGUNA_REGS HwDeviceExtension->RegisterAddress
  2300. VOLATILE USHORT* pRIF_reg = (USHORT*)(LAGUNA_REGS + 0x200);
  2301. PAGED_CODE();
  2302. /*
  2303. 1.) If 62 or 64 or 65 AC or below
  2304. Lower 3 bits of RIF is the number of banks -1. Add one and multiply
  2305. by 1MB
  2306. 2.) If 65 AD then some bits in the RIF have changed
  2307. Then bits 15:14 have been overloaded <they are now called memory
  2308. type>
  2309. MEM_TYPE == 00b --- use step 1
  2310. MEM_TYPE == 01b --- use step 1
  2311. MEM_TYPE == 10b or MEM_TYPE == 11b then
  2312. Lower 3 bits of RIF is the number of banks -1. Add one and
  2313. multiply by 2MB.
  2314. */
  2315. memsize = *pRIF_reg; // get RIF register.
  2316. memsize = memsize & 7; // keep lowest 3 bits.
  2317. memsize = memsize + 1; // Add 1 to get number of banks.
  2318. memsize = memsize * 1024 * 1024; // multiply by 1 meg per bank.
  2319. //
  2320. // If the chip is 5465AD or later, adjust the memory size.
  2321. //
  2322. if ((HwDeviceExtension->ChipID > CL_GD5465) ||
  2323. ((HwDeviceExtension->ChipID==CL_GD5465)&&(HwDeviceExtension->ChipRev>1)))
  2324. {
  2325. unsigned long mem_type = *pRIF_reg;
  2326. mem_type = mem_type >> 14;
  2327. if (mem_type >= 2)
  2328. memsize *= 2; // 2 megabytes per bank.
  2329. }
  2330. VideoDebugPrint((DISPLVL, "Miniport - AdapterMemorySize= 0x%X (%d meg)\n",
  2331. memsize, memsize/(1024*1024)));
  2332. //
  2333. // Return the Number of bytes of RAM installed.
  2334. //
  2335. return (memsize);
  2336. } // CirrusFindVmemSize()
  2337. /****************************************************************************
  2338. * FUNCTION NAME: CLWriteRegistryInfo()
  2339. *
  2340. * DESCRIPTION:
  2341. * Write hardware information to registry.
  2342. *
  2343. * REVISION HISTORY:
  2344. * 5/30/95 Benny Ng Initial version
  2345. ****************************************************************************/
  2346. VOID CLWriteRegistryInfo (PHW_DEVICE_EXTENSION hwDeviceExtension,
  2347. BOOLEAN hdbrsten)
  2348. {
  2349. PWSTR pszString;
  2350. ULONG cbString;
  2351. PAGED_CODE();
  2352. VideoDebugPrint((DISPLVL, "Miniport - CLWriteRegestryInfo.\n"));
  2353. // Store Memory Size
  2354. VideoPortSetRegistryParameters(hwDeviceExtension,
  2355. L"HardwareInformation.MemorySize",
  2356. &hwDeviceExtension->AdapterMemorySize,
  2357. sizeof(ULONG));
  2358. // Store chip Type
  2359. if (hwDeviceExtension->ChipID == CL_GD5462)
  2360. {
  2361. pszString = L"Cirrus Logic 5462";
  2362. cbString = sizeof(L"Cirrus Logic 5462");
  2363. }
  2364. else if (hwDeviceExtension->ChipID == CL_GD5464)
  2365. {
  2366. pszString = L"Cirrus Logic 5464";
  2367. cbString = sizeof(L"Cirrus Logic 5464");
  2368. }
  2369. else if (hwDeviceExtension->ChipID == CL_GD5465)
  2370. {
  2371. pszString = L"Cirrus Logic 5465";
  2372. cbString = sizeof(L"Cirrus Logic 5465");
  2373. }
  2374. else
  2375. {
  2376. pszString = L"Cirrus Logic 546x";
  2377. cbString = sizeof(L"Cirrus Logic 546x");
  2378. }
  2379. VideoPortSetRegistryParameters(hwDeviceExtension,
  2380. L"HardwareInformation.ChipType",
  2381. pszString,
  2382. cbString);
  2383. // Store DAC Type
  2384. pszString = L"Internal";
  2385. cbString = sizeof(L"Internal");
  2386. VideoPortSetRegistryParameters(hwDeviceExtension,
  2387. L"HardwareInformation.DacType",
  2388. pszString,
  2389. cbString);
  2390. // Store Adapter String
  2391. pszString = L"Cirrus Logic VisualMedia(TM) Accelerator";
  2392. cbString = sizeof(L"Cirrus Logic VisualMedia(TM) Accelerator");
  2393. VideoPortSetRegistryParameters(hwDeviceExtension,
  2394. L"HardwareInformation.AdapterString",
  2395. pszString,
  2396. cbString);
  2397. // HD BRST EN
  2398. if (hdbrsten)
  2399. {
  2400. pszString = L"1";
  2401. cbString = sizeof(L"1");
  2402. }
  2403. else
  2404. {
  2405. pszString = L"0";
  2406. cbString = sizeof(L"0");
  2407. };
  2408. VideoPortSetRegistryParameters(hwDeviceExtension,
  2409. L"HardwareInformation.HdBrstEn",
  2410. pszString,
  2411. cbString);
  2412. VideoDebugPrint((DISPLVL, "Miniport - CLWriteRegestryInfo - Exit.\n"));
  2413. } // end CLWriteRegistryInfo()
  2414. // Verify the BIOS ID.
  2415. // At offset 001e these is a string that says "IBM VGA Compatible".
  2416. //
  2417. #define CheckBiosID(BiosAddress) \
  2418. ( ( *(BiosAddress+0x1E) == 'I') \
  2419. && ( *(BiosAddress+0x1F) == 'B') \
  2420. && ( *(BiosAddress+0x20) == 'M') \
  2421. && ( *(BiosAddress+0x21) == ' ') \
  2422. && ( *(BiosAddress+0x22) == 'V') \
  2423. && ( *(BiosAddress+0x23) == 'G') \
  2424. && ( *(BiosAddress+0x24) == 'A') \
  2425. && ( *(BiosAddress+0x25) == ' ') \
  2426. && ( *(BiosAddress+0x26) == 'C') \
  2427. && ( *(BiosAddress+0x27) == 'o') \
  2428. && ( *(BiosAddress+0x28) == 'm') \
  2429. && ( *(BiosAddress+0x29) == 'p') \
  2430. && ( *(BiosAddress+0x2A) == 'a') \
  2431. && ( *(BiosAddress+0x2B) == 't') \
  2432. && ( *(BiosAddress+0x2C) == 'i') \
  2433. && ( *(BiosAddress+0x2D) == 'b') \
  2434. && ( *(BiosAddress+0x2E) == 'l') \
  2435. && ( *(BiosAddress+0x2F) == 'e') \
  2436. ) \
  2437. /****************************************************************************
  2438. * FUNCTION NAME: CLPatchModeTable()
  2439. *
  2440. * DESCRIPTION:
  2441. * This routine patches the ModeTable with info from the BIOS
  2442. *
  2443. * MUST be called AFTER ClValidateModes!
  2444. *
  2445. ****************************************************************************/
  2446. VOID CLPatchModeTable (PHW_DEVICE_EXTENSION HwDeviceExtension)
  2447. {
  2448. unsigned long index;
  2449. unsigned char *BiosAddress; // Pointer to start of BIOS.
  2450. ULONG SupParms; // Offset of SUpplimental parameter table.
  2451. unsigned char s_TPL; // Tiles per line.
  2452. unsigned char s_TFIFO; // Tiled display and threshold fifo.
  2453. USHORT TileWidth; // Tile width. 128 or 256.
  2454. USHORT FB_Pitch; // Frame buffer pitch.
  2455. VIDEO_X86_BIOS_ARGUMENTS biosregs;
  2456. PHYSICAL_ADDRESS PhysAddr; // Our Video Bios
  2457. PAGED_CODE();
  2458. VideoDebugPrint((DISPLVL, "Miniport - PatchModeTable.\n"));
  2459. if (HwDeviceExtension->Dont_Do_VGA)
  2460. {
  2461. VideoDebugPrint((DISPLVL,
  2462. "Miniport - PatchModeTable - No VGA! - Exit.\n"));
  2463. return;
  2464. }
  2465. //
  2466. // NVH
  2467. // We're going to do something weird here.
  2468. // The scan line lengths in the mode table entries in MTBL.C
  2469. // may not be right. So before we copy the mode info into NT, we are
  2470. // going to query the BIOS and patch the mode table entry if necessary.
  2471. // When we query the BIOS, it will hand us a 16 bit pointer
  2472. // in ES:DI that points to the supplimental parameter table
  2473. // for the mode we are interested in. From there we will get the
  2474. // information we need to patch the ModeTable in MTBL.C
  2475. // The tricky part is that VideoPortInt10 does not provide a way
  2476. // for the BIOS to pass back DS.
  2477. // A chat with the BIOS author revealed that DS will always be
  2478. // either 0xC000 or 0xE000. So we convert physical address 0x000C0000
  2479. // into a 32 bit pointer with VideoPortGetDeviceBase(), and then look
  2480. // at it to see if it points to the BIOS. If not, we try again with
  2481. // 0x000E0000
  2482. // Once we locate our BIOS we make BIOS call, and add the returned
  2483. // value of DI to our BIOS pointer, and viola! we have a usable pointer
  2484. // to the supplimental parameter table in the BIOS.
  2485. //
  2486. // Someday I will have to atone for my sins.
  2487. //
  2488. //
  2489. // Here we get a pointer to the Video BIOS so we can examine the
  2490. // mode tables. The BIOS may be at C0000, or maybe E0000. We'll try both.
  2491. // At offset 001e these is a string that says "IBM VGA Compatible".
  2492. //
  2493. PhysAddr.HighPart = 0;
  2494. PhysAddr.LowPart = 0xC0000;
  2495. BiosAddress = VideoPortGetDeviceBase(
  2496. HwDeviceExtension,
  2497. PhysAddr, // RangeStart
  2498. 0x10000, // RangeLength,
  2499. FALSE); // In memory space.
  2500. if (BiosAddress==NULL || !CheckBiosID(BiosAddress))
  2501. {
  2502. if (BiosAddress!=NULL)
  2503. VideoPortFreeDeviceBase(HwDeviceExtension,BiosAddress);
  2504. // It's at E0000.
  2505. PhysAddr.HighPart = 0;
  2506. PhysAddr.LowPart = 0xE0000;
  2507. BiosAddress = VideoPortGetDeviceBase(
  2508. HwDeviceExtension,
  2509. PhysAddr, // RangeStart
  2510. 0x10000, // RangeLength,
  2511. FALSE); // In memory space.
  2512. }
  2513. if (BiosAddress!=NULL && CheckBiosID(BiosAddress))
  2514. {
  2515. // Found it
  2516. VideoDebugPrint((DISPLVL, "PatchModeTable - Found BIOS at 0x%08X.\n",
  2517. BiosAddress));
  2518. }
  2519. else
  2520. {
  2521. // Didn't find it
  2522. if (BiosAddress!=NULL)
  2523. VideoPortFreeDeviceBase(HwDeviceExtension,BiosAddress);
  2524. VideoDebugPrint((DISPLVL,"PatchModeTable - Couldn't find the BIOS.\n"));
  2525. return;
  2526. }
  2527. //
  2528. // Get the BIOS version informaton
  2529. {
  2530. WORD ver;
  2531. UCHAR val;
  2532. unsigned char *pBiosAddrTmp;
  2533. ver = 0;
  2534. pBiosAddrTmp = BiosAddress + 0x5f;
  2535. ver = (*pBiosAddrTmp) - 0x30;
  2536. pBiosAddrTmp++;
  2537. pBiosAddrTmp++;
  2538. val = (*pBiosAddrTmp) - 0x30;
  2539. pBiosAddrTmp++;
  2540. val = (val << 4) + ((*pBiosAddrTmp) - 0x30);
  2541. ver = (ver << 8) | val;
  2542. HwDeviceExtension->BIOSVersion = ver;
  2543. }
  2544. //
  2545. // Now read the frame buffer pitch from the BIOS
  2546. // and patch the ModeTable.
  2547. //
  2548. for (index=0; index < TotalVideoModes; ++index)
  2549. {
  2550. // If we don't use the BIOS for this mode, don't patch it
  2551. if (ModeTable[index].SetModeString)
  2552. continue;
  2553. // If it's not a valid mode, don't patch it.
  2554. // All BIOS hires modes
  2555. // *should* be marked invalid by now, meaning the rest of this
  2556. // function does nothing.
  2557. if (ModeTable[index].ValidMode == FALSE)
  2558. continue;
  2559. // If it's not a hires mode, don't patch it.
  2560. if (ModeTable[index].BitsPerPixel < 8)
  2561. continue;
  2562. VideoDebugPrint((DISPLVL, " Patching Mode %d - %dx%dx%d@%d.\n",
  2563. index,
  2564. ModeTable[index].XResol ,
  2565. ModeTable[index].YResol ,
  2566. ModeTable[index].BitsPerPixel ,
  2567. ModeTable[index].Frequency
  2568. ));
  2569. // Ask the BIOS where the supplimental parameter
  2570. // table for this mode is.
  2571. biosregs.Eax = 0x1200 | ModeTable[index].BIOSModeNum;
  2572. biosregs.Ebx = 0xA0;
  2573. biosregs.Ecx = biosregs.Edx = biosregs.Esi = biosregs.Edi = 0;
  2574. VideoPortInt10(HwDeviceExtension, &biosregs);
  2575. SupParms = biosregs.Edi & 0x0000FFFF;
  2576. if (SupParms == 0x0000FFFF)
  2577. // BIOS call failed.
  2578. continue;
  2579. // Tiles per line is at offset 14 from start of table.
  2580. if (HwDeviceExtension->ChipID <= CL_GD5464_BD)
  2581. s_TPL = *(BiosAddress + SupParms + 14);
  2582. else
  2583. s_TPL = *(BiosAddress + SupParms + 15);
  2584. // If this is a tiled mode, patch the table.
  2585. if (s_TPL != 0)
  2586. {
  2587. // Tiled display register is at offset 15
  2588. if (HwDeviceExtension->ChipID <= CL_GD5464_BD)
  2589. s_TFIFO = *(BiosAddress + SupParms + 15);
  2590. else
  2591. s_TFIFO = *(BiosAddress + SupParms + 16);
  2592. // Bit 6 of s_TFIFO is 0 for 128 byte wide tiles and
  2593. // 1 for 256 byte wide tiles.
  2594. TileWidth = (s_TFIFO & 0x40) ? 256 : 128;
  2595. if (HwDeviceExtension->ChipID > CL_GD5464_BD)
  2596. s_TPL = (s_TFIFO & 0x40) ? s_TPL>> 1 : s_TPL;
  2597. // Calculate pitch of the frame buffer.
  2598. FB_Pitch = TileWidth * s_TPL;
  2599. // Patch the ModeTable entry.
  2600. ModeTable[index].BytesPerScanLine = FB_Pitch;
  2601. }
  2602. }
  2603. VideoPortFreeDeviceBase(HwDeviceExtension,BiosAddress);
  2604. VideoDebugPrint((DISPLVL, "Miniport - CLPatchModeTable - Exit.\n"));
  2605. } // end CLPatchModeTable()
  2606. /****************************************************************************
  2607. * FUNCTION NAME: CLValidateModes()
  2608. *
  2609. * DESCRIPTION:
  2610. * Determines which modes are valid and which are not.
  2611. *
  2612. * REVISION HISTORY:
  2613. * 5/30/95 Benny Ng Initial version
  2614. ****************************************************************************/
  2615. VOID CLValidateModes (PHW_DEVICE_EXTENSION HwDeviceExtension)
  2616. {
  2617. ULONG i,j;
  2618. ULONG ReqireMem;
  2619. PMODETABLE pVMode;
  2620. PAGED_CODE();
  2621. VideoDebugPrint((DISPLVL, "Miniport - CLValidateModes.\n"));
  2622. HwDeviceExtension->NumAvailableModes = 0;
  2623. HwDeviceExtension->NumTotalModes = TotalVideoModes;
  2624. //
  2625. // All the modes in the table start out marked invalid.
  2626. // We will step through the table one mode at a time, examining
  2627. // each mode to see if we will support it.
  2628. // If we decide to support the mode, we will mark it as valid.
  2629. //
  2630. for (i = 0; i < TotalVideoModes; i++)
  2631. {
  2632. pVMode = &ModeTable[i];
  2633. //
  2634. // Is the mode supported by this chip?
  2635. //
  2636. if (pVMode->ChipType & LG_ALL)
  2637. {
  2638. //
  2639. // This mode is valid for all laguna chips.
  2640. // Fall through.
  2641. //
  2642. ;
  2643. }
  2644. else if ((pVMode->ChipType & LG_5465) &&
  2645. (HwDeviceExtension->ChipID == CL_GD5465))
  2646. {
  2647. //
  2648. // We are a 5465 and this mode is valid for 5465 chips.
  2649. // Fall through.
  2650. //
  2651. ;
  2652. }
  2653. else if ((pVMode->ChipType & LG_5465AD) &&
  2654. ((HwDeviceExtension->ChipID == CL_GD5465) && (HwDeviceExtension->ChipRev>1)))
  2655. {
  2656. //
  2657. // We are a 5465AD and this mode is valid for 5465AD chips.
  2658. // Fall through.
  2659. //
  2660. ;
  2661. }
  2662. else if ((pVMode->ChipType & LG_5464) &&
  2663. (HwDeviceExtension->ChipID == CL_GD5464))
  2664. {
  2665. //
  2666. // We are a 5464 and this mode is valid for 5464 chips.
  2667. // Fall through.
  2668. //
  2669. ;
  2670. }
  2671. else if ((pVMode->ChipType & LG_5462) &&
  2672. (HwDeviceExtension->ChipID == CL_GD5462))
  2673. {
  2674. //
  2675. // We are a 5462 and this mode is valid for 5462 chips.
  2676. // Fall through.
  2677. //
  2678. ;
  2679. }
  2680. else
  2681. {
  2682. //
  2683. // This chip doesn't do this mode.
  2684. // Leave this mode marked invalid and get the next mode.
  2685. //
  2686. continue;
  2687. }
  2688. //
  2689. // Is this the RESET mode?
  2690. // We have once special mode in the mode table that resets the chip.
  2691. // We don't want to mark it as VALID, since it's not a real mode.
  2692. // But we do want to remember what it is, since we we need it for
  2693. // IOCTL_VIDEO_RESET_DEVICE
  2694. //
  2695. if (pVMode->XResol == 0)
  2696. {
  2697. resetmode = i;
  2698. continue;
  2699. }
  2700. //
  2701. // Does the video board have enough memory to do this mode?
  2702. //
  2703. ReqireMem = pVMode->NumOfPlanes * pVMode->BytesPerScanLine * pVMode->YResol;
  2704. if (HwDeviceExtension->AdapterMemorySize < ReqireMem)
  2705. {
  2706. //
  2707. // We don't have enough memory to support this mode.
  2708. // Leave this mode marked invalid and get the next mode.
  2709. //
  2710. continue;
  2711. };
  2712. //
  2713. // Disable BIOS modes if we don't do VGA
  2714. //
  2715. if (HwDeviceExtension->Dont_Do_VGA)
  2716. {
  2717. if (pVMode->BIOSModeNum != 0)
  2718. continue; // Skip this mode.
  2719. }
  2720. //
  2721. // The NT 4.0 Display Applet automatically trims Direct Draw modes
  2722. // from the mode list that it shows to the user.
  2723. // It bases it's decision on the number of scan lines in the mode.
  2724. // Modes with less then 480 scan lines don't even show up in the
  2725. // list of available modes.
  2726. //
  2727. // Unfortunatly we have some Direct Draw modes with 480 scan lines
  2728. // but fewer than 640 columns (like 320x480). The display applet
  2729. // thinks that these are desktop modes, since they have 480 scan lines,
  2730. // but we disagree. To prevent the user from selecting them, we
  2731. // will remove them entirely.
  2732. //
  2733. if ( (pVMode->YResol == 480) && (pVMode->XResol < 640))
  2734. {
  2735. if ((pVMode->BIOSModeNum == 0) || (pVMode->BIOSModeNum > 0x12))
  2736. {
  2737. // This mode has less than 640 columns.
  2738. // This mode is not a VGA mode.
  2739. continue; // Skip it.
  2740. }
  2741. }
  2742. #if 0
  2743. // Get the LowRes registry value.
  2744. if ((VideoPortGetRegistryParameters(HwDeviceExtension, L"LowRes", FALSE,
  2745. CLGetLowResValue, NULL) != NO_ERROR)
  2746. || (HwDeviceExtension->fLowRes == FALSE)
  2747. )
  2748. {
  2749. //
  2750. // Disable support for all low resolution modes (less than 640x350).
  2751. //
  2752. if ( (pVMode->XResol < 640) || (pVMode->YResol < 350) )
  2753. {
  2754. if ((pVMode->BIOSModeNum == 0) || (pVMode->BIOSModeNum > 0x12))
  2755. {
  2756. // This mode is a non-VGA low resolution mode, skip it.
  2757. continue;
  2758. }
  2759. }
  2760. }
  2761. #endif
  2762. //
  2763. // Mark the mode as available.
  2764. pVMode->ValidMode = TRUE;
  2765. HwDeviceExtension->NumAvailableModes++;
  2766. } // end for
  2767. //
  2768. // There may be duplicate modes in the BIOS and MODE.INI.
  2769. //
  2770. for (i = 0; i < TotalVideoModes; i++)
  2771. {
  2772. pVMode = &ModeTable[i];
  2773. if (pVMode->ValidMode != TRUE)
  2774. continue;
  2775. //
  2776. // We will favor the MODE.INI modes over the BIOS modes.
  2777. // We want the last instance of each mode in the table.
  2778. // So, for each mode M, we scan the rest of the table and
  2779. // if we find a mode that is equivilant to mode M, we
  2780. // disable this mode.
  2781. //
  2782. for (j=(i+1); j<TotalVideoModes; j++)
  2783. {
  2784. // Does this mode match pVMode?
  2785. if( ModeTable[j].ValidMode == TRUE &&
  2786. ModeTable[j].XResol == pVMode->XResol &&
  2787. ModeTable[j].YResol == pVMode->YResol &&
  2788. ModeTable[j].BitsPerPixel == pVMode->BitsPerPixel &&
  2789. /* Match refresh within +/- 1 Hz */
  2790. ModeTable[j].Frequency >= pVMode->Frequency-1 &&
  2791. ModeTable[j].Frequency <= pVMode->Frequency+1 )
  2792. {
  2793. // Yep, it's the same mode. Disable pVMode.
  2794. pVMode->ValidMode = FALSE;
  2795. }
  2796. } // end inner for loop
  2797. } // end outer for loop
  2798. VideoDebugPrint((DISPLVL, "Miniport - CLValidateModes - Exit.\n"));
  2799. } // end CLValidateModes()
  2800. #if 0
  2801. VP_STATUS CLGetLowResValue(PHW_DEVICE_EXTENSION HwDeviceExtension,
  2802. PVOID Context, PWSTR ValueName, PVOID ValueData, ULONG ValueLength)
  2803. {
  2804. PAGED_CODE();
  2805. if (ValueLength > 0 && ValueLength <= sizeof(DWORD))
  2806. {
  2807. HwDeviceExtension->fLowRes = (*(BYTE*) ValueData != 0);
  2808. return(NO_ERROR);
  2809. }
  2810. HwDeviceExtension->fLowRes = FALSE;
  2811. return(ERROR_INVALID_PARAMETER);
  2812. }
  2813. #endif
  2814. /****************************************************************************
  2815. * FUNCTION NAME: CopyModeInfo()
  2816. *
  2817. * DESCRIPTION:
  2818. * This routine copy the selected mode informations from mode table
  2819. * into the VIDEO_MODE_INFORMATION structure provided by NT.
  2820. *
  2821. * REVISION HISTORY:
  2822. * 5/30/95 Benny Ng Initial version
  2823. ****************************************************************************/
  2824. VOID CLCopyModeInfo (PHW_DEVICE_EXTENSION HwDeviceExtension,
  2825. PVIDEO_MODE_INFORMATION videoModes,
  2826. ULONG ModeIndex,
  2827. PMODETABLE ModeInfo)
  2828. {
  2829. PAGED_CODE();
  2830. //
  2831. // Copy the mode informations to window supplied buffer
  2832. //
  2833. videoModes->Length = sizeof(VIDEO_MODE_INFORMATION);
  2834. videoModes->ModeIndex = ModeIndex;
  2835. videoModes->VisScreenWidth = ModeInfo->XResol;
  2836. videoModes->VisScreenHeight = ModeInfo->YResol;
  2837. videoModes->ScreenStride = ModeInfo->BytesPerScanLine;
  2838. videoModes->NumberOfPlanes = ModeInfo->NumOfPlanes;
  2839. videoModes->BitsPerPlane = ModeInfo->BitsPerPixel;
  2840. videoModes->Frequency = ModeInfo->Frequency;
  2841. videoModes->XMillimeter = 320; // temp hardcoded constant
  2842. videoModes->YMillimeter = 240; // temp hardcoded constant
  2843. if (videoModes->BitsPerPlane >= 8)
  2844. {
  2845. //
  2846. // Calculate the bitmap width (note the '+ 1' on BitsPerPlane is
  2847. // so that '15bpp' works out right):
  2848. //
  2849. videoModes->VideoMemoryBitmapWidth =
  2850. videoModes->ScreenStride / ((videoModes->BitsPerPlane + 1) >> 3);
  2851. //
  2852. // Calculate the bitmap height.
  2853. //
  2854. videoModes->VideoMemoryBitmapHeight =
  2855. HwDeviceExtension->AdapterMemorySize / videoModes->ScreenStride;
  2856. }
  2857. else
  2858. {
  2859. videoModes->VideoMemoryBitmapWidth = 0;
  2860. videoModes->VideoMemoryBitmapHeight = 0;
  2861. };
  2862. //
  2863. // Set Mono/Color & Text/Graphic modes, interlace/non-interlace
  2864. //
  2865. videoModes->AttributeFlags = ModeInfo->fbType;
  2866. if ((ModeInfo->BitsPerPixel == 24) || (ModeInfo->BitsPerPixel == 32))
  2867. {
  2868. videoModes->NumberRedBits = 8;
  2869. videoModes->NumberGreenBits = 8;
  2870. videoModes->NumberBlueBits = 8;
  2871. videoModes->RedMask = 0xff0000;
  2872. videoModes->GreenMask = 0x00ff00;
  2873. videoModes->BlueMask = 0x0000ff;
  2874. }
  2875. else if (ModeInfo->BitsPerPixel == 16)
  2876. {
  2877. videoModes->NumberRedBits = 5;
  2878. videoModes->NumberGreenBits = 6;
  2879. videoModes->NumberBlueBits = 5;
  2880. videoModes->RedMask = 0x1F << 11;
  2881. videoModes->GreenMask = 0x3F << 5;
  2882. videoModes->BlueMask = 0x1F;
  2883. }
  2884. else
  2885. {
  2886. videoModes->NumberRedBits = 6;
  2887. videoModes->NumberGreenBits = 6;
  2888. videoModes->NumberBlueBits = 6;
  2889. videoModes->RedMask = 0;
  2890. videoModes->GreenMask = 0;
  2891. videoModes->BlueMask = 0;
  2892. videoModes->AttributeFlags |=
  2893. (VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE);
  2894. };
  2895. } // end CLCopyModeInfo()
  2896. //*****************************************************************************
  2897. //
  2898. // CLEnableTiling()
  2899. //
  2900. // Enable Tiled mode for Laguna chip.
  2901. //
  2902. //
  2903. //*****************************************************************************
  2904. VOID CLEnableTiling(
  2905. PHW_DEVICE_EXTENSION HwDeviceExtension,
  2906. PMODETABLE pReqModeTable
  2907. )
  2908. {
  2909. #undef LAGUNA_REGS
  2910. #define LAGUNA_REGS HwDeviceExtension->RegisterAddress
  2911. VOLATILE PUSHORT pControl_reg = (PUSHORT)(LAGUNA_REGS + 0x402);
  2912. VOLATILE PUCHAR pTileCtrl_reg = (PUCHAR) (LAGUNA_REGS + 0x407);
  2913. VOLATILE UCHAR* pPixelMask_reg = (UCHAR*) (LAGUNA_REGS + 0xA0);
  2914. VOLATILE USHORT* pDTTR_reg = (USHORT*)(LAGUNA_REGS + 0xEA);
  2915. VOLATILE USHORT* pTilingCtrl_reg = (USHORT*)(LAGUNA_REGS + 0x2C4);
  2916. PVIDEO_X86_BIOS_ARGUMENTS pInbiosargs;
  2917. PVIDEO_X86_BIOS_ARGUMENTS pOutbiosargs;
  2918. VIDEO_X86_BIOS_ARGUMENTS biosargs;
  2919. unsigned long VidMem;
  2920. unsigned long ulInterleave;
  2921. unsigned long TilesPerLine;
  2922. unsigned long WideTiles;
  2923. unsigned long BitsPerPixel;
  2924. VideoDebugPrint((DISPLVL, "Miniport - Setting tiling.\n"));
  2925. //
  2926. // If it's not a Hi Res mode, turn off tiling.
  2927. //
  2928. if (pReqModeTable->BitsPerPixel < 8)
  2929. {
  2930. VideoDebugPrint((DISPLVL, "Miniport - Not hi-res mode. No tiling.\n"));
  2931. *pControl_reg |= 0x1000; // Set bit 12 of CONTROL
  2932. if (HwDeviceExtension->ChipID >= CL_GD5465)
  2933. *pTilingCtrl_reg &= 0xFF7F; //Clear bit 7 of TILING_CONTROL
  2934. HwDeviceExtension->TileSize = 0;
  2935. HwDeviceExtension->TiledMode = 0;
  2936. HwDeviceExtension->TiledTPL = 0;
  2937. HwDeviceExtension->TiledInterleave = 0;
  2938. return;
  2939. }
  2940. //
  2941. // It is a hi res mode. Turn on tiling.
  2942. //
  2943. //
  2944. // If we used the BIOS to set the mode, use the BIOS to enable tiling.
  2945. // Also set TILE_CTRL, TILING_CTRL, CONTROL and DTTR.
  2946. //
  2947. if (!(pReqModeTable->SetModeString))
  2948. {
  2949. // Call BIOS to set tiling.
  2950. VideoDebugPrint((DISPLVL,
  2951. "Miniport - Using BIOS. Setting tiled mode.\n"));
  2952. VideoPortZeroMemory(&biosargs, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  2953. biosargs.Eax = 0x1200;
  2954. biosargs.Ebx = 0x00B3;
  2955. VideoPortInt10(HwDeviceExtension, &biosargs);
  2956. // Get tile size
  2957. WideTiles = (biosargs.Eax & 0xFF) - 1; // AL=1 for narrow, 2 for wide
  2958. // Get tiles per line
  2959. TilesPerLine = biosargs.Ebx & 0xFF; //BL is tiles per line
  2960. if ((HwDeviceExtension->ChipID >= CL_GD5465) && WideTiles)
  2961. TilesPerLine /= 2;
  2962. // Get color depth
  2963. BitsPerPixel = pReqModeTable->BitsPerPixel;
  2964. BitsPerPixel = (BitsPerPixel/ 8) - 1; // Convert 8,16,24,32 to 0,1,2,3
  2965. // Get memory interleave
  2966. ulInterleave = (BYTE)(biosargs.Ebx >> 8); // BH is memory interleave.
  2967. ulInterleave = ulInterleave << 6; // shift to bits 6-7
  2968. // Set DTTR bits 14-15
  2969. *pDTTR_reg &= 0x3FFF; // Clear bits 14-15
  2970. *pDTTR_reg |= (WORD) (ulInterleave << 8); // Set bits 14-15
  2971. // Set tile control reg.
  2972. *pTileCtrl_reg = (BYTE)( ulInterleave // set bits 6-7
  2973. | TilesPerLine); // Set bits 0-5
  2974. // Set tiling control reg
  2975. if (HwDeviceExtension->ChipID >= CL_GD5465)
  2976. {
  2977. *pTilingCtrl_reg &= 0x003F; // Clear bits 6-15
  2978. *pTilingCtrl_reg |= ( (ulInterleave << 8) // Set bits 14-15
  2979. | (TilesPerLine << 8) // Set bits 8-13
  2980. | (1 << 7) // set bit 7
  2981. | (WideTiles<<6) ); // Set bits 6
  2982. }
  2983. // Set control reg
  2984. *pControl_reg =(WORD) ( (BitsPerPixel << 13)
  2985. | (WideTiles << 11) );
  2986. }
  2987. //
  2988. // If we used MODE.INI to set the mode.
  2989. //
  2990. else
  2991. {
  2992. //
  2993. // Set memory interleave
  2994. //
  2995. VidMem = HwDeviceExtension->AdapterMemorySize >> 20;
  2996. ulInterleave = bLeave[VidMem - 1];
  2997. // TILE_CTRL bits 6-7
  2998. *pTileCtrl_reg &= 0x3F; // Clear bits 6-7
  2999. *pTileCtrl_reg |= (USHORT)ulInterleave; // Set bits 6-7
  3000. // DTTR bits 14-15
  3001. ulInterleave = ulInterleave << 8; // Shift interleave to bit 14-15
  3002. *pDTTR_reg &= 0x3FFF; // Clear bits 14-15
  3003. *pDTTR_reg |= (USHORT)ulInterleave; // Set bits 14-15
  3004. // TILING_CTRL bits 14-15
  3005. if (HwDeviceExtension->ChipID >= CL_GD5465)
  3006. {
  3007. *pTilingCtrl_reg &= 0x3FFF; // Clear bits 14-15
  3008. *pTilingCtrl_reg |= (USHORT)ulInterleave; // Set bits 14-15
  3009. }
  3010. else
  3011. {
  3012. WORD tpl = *pTileCtrl_reg;
  3013. WORD dttr = *pDTTR_reg;
  3014. // DTTR tiles per line - bits 8-13.
  3015. tpl = tpl & 0x003F; // tiles per line is in bits 0-5.
  3016. tpl = tpl << 8; // shift to bits 8-12.
  3017. dttr &= 0xC0FF; // Clear bits 8-13 in DTTR
  3018. dttr |= tpl; // Set bits 8-13 in DTTR
  3019. *pDTTR_reg = dttr;
  3020. // CONTROL enable tiling - bit 12.
  3021. *pControl_reg &= 0xEFFF; // clear bit 12
  3022. }
  3023. }
  3024. #if 0
  3025. //
  3026. // If the fetch tiles per line is greater than the display tiles per line
  3027. // we can reduce the fetch tiles per line by 1. This speeds things
  3028. // up a bit.
  3029. //
  3030. if (HwDeviceExtension->ChipID >= CL_GD5465)
  3031. {
  3032. unsigned long fetch_tpl = (*pDTTR_reg >> 8) & 0x3F;
  3033. unsigned long display_tpl = (*pTileCtrl_reg) & 0x3F;
  3034. if (fetch_tpl > display_tpl)
  3035. *pDTTR_reg -= 0x0100; // One less tile per line
  3036. }
  3037. #endif
  3038. //
  3039. // Now put some mode information into the HwDeviceExtension.
  3040. //
  3041. HwDeviceExtension->TileSize = ((*pControl_reg >> 11) & 3) + 1;
  3042. HwDeviceExtension->TiledMode = (UCHAR) pReqModeTable->BIOSModeNum;
  3043. HwDeviceExtension->TiledTPL = *pTileCtrl_reg & 0x3F;
  3044. HwDeviceExtension->TiledInterleave = *pTileCtrl_reg >> 6;
  3045. //
  3046. // Report some debug information.
  3047. //
  3048. VideoDebugPrint((DISPLVL, "\n"
  3049. " CONTROL(402): 0x%04X BPP=%2d Tiling=%s Size=%s \n",
  3050. *pControl_reg,
  3051. ((((*pControl_reg & 0x6000) >>13) +1) *8), // bpp
  3052. (*pControl_reg & 0x1000) ? "disabled" : "enabled ", // tile disable
  3053. (*pControl_reg & 0x0800) ? "wide " : "narrow" // tile size
  3054. ));
  3055. VideoDebugPrint((DISPLVL,
  3056. " TILE_CTRL(407): 0x%04X Interleave=%d TPL=%2d\n",
  3057. *pTileCtrl_reg,
  3058. (1<<((*pTileCtrl_reg & 0xC0) >> 6)), // Interleave
  3059. (*pTileCtrl_reg & 0x3F) // Tiles per line.
  3060. ));
  3061. VideoDebugPrint((DISPLVL,
  3062. " DTTR(EA): 0x%04X Interleave=%d FetchTPL=%2d Size=%s\n",
  3063. *pDTTR_reg,
  3064. (1<<((*pDTTR_reg & 0xC000) >> 14)), // Interleave
  3065. ((*pDTTR_reg & 0x3F00) >> 8), // Tiles per line.
  3066. ((*pDTTR_reg & 0x0040) ? "wide " : "narrow") // tile size
  3067. ));
  3068. if (HwDeviceExtension->ChipID >= CL_GD5465)
  3069. VideoDebugPrint((DISPLVL,
  3070. " TILING_CTRL(2C4): 0x%04X Interleave=%d TPL=%2d Tiling=%s Size=%s\n",
  3071. *pTilingCtrl_reg,
  3072. (1<<((*pTilingCtrl_reg & 0xC000) >> 14)), // Interleave
  3073. ((*pTilingCtrl_reg & 0x3F00) >> 8), // Tile per line
  3074. ((*pTilingCtrl_reg & 0x0080) ? "enabled " : "disabled"), // tile enable
  3075. ((*pTilingCtrl_reg & 0x0040) ? "wide " : "narrow") // tile size
  3076. ));
  3077. VideoDebugPrint((DISPLVL,"\n"));
  3078. }
  3079. #if MULTI_CLOCK
  3080. /******************************************************************************\
  3081. *
  3082. * CLOverrideFIFOThreshold()
  3083. *
  3084. * Description: Override the FIFO Threshold value for CL-GD5465 chips running
  3085. * at different clock speeds.
  3086. *
  3087. * Arguments: PHW_DEVICE_EXTENSION HwDeviceExtension
  3088. * Pointer to hardware device extension.
  3089. * PMODETABLE pReqModeTable
  3090. * Pointer to MODETABLE structure containing the video mode
  3091. * just set.
  3092. *
  3093. * Return value: Nothing.
  3094. *
  3095. \******************************************************************************/
  3096. void CLOverrideFIFOThreshold(PHW_DEVICE_EXTENSION HwDeviceExtension,
  3097. PMODETABLE pReqModeTable)
  3098. {
  3099. #undef LAGUNA_REGS
  3100. #define LAGUNA_REGS HwDeviceExtension->RegisterAddress
  3101. VOLATILE USHORT* pDisplayThreshold_reg = (USHORT*) (LAGUNA_REGS + 0x00EA);
  3102. VOLATILE BYTE* pBCLKMultiplier_reg = (BYTE*) (LAGUNA_REGS + 0x02C0);
  3103. int i;
  3104. BYTE BCLKMultiplier;
  3105. static struct _FIFOTABLE
  3106. {
  3107. USHORT xRes;
  3108. USHORT yRes;
  3109. UCHAR BitsPerPixel;
  3110. USHORT RefreshRate;
  3111. BYTE BCLKMin;
  3112. BYTE BCLKMax;
  3113. USHORT FIFOThreshold;
  3114. } FIFOTable[] =
  3115. // Here we define the FIFO Threshold override values for certain modes.
  3116. {
  3117. // xres, yres, bpp, refresh, clockmin, clockmax, FIFOThreshold
  3118. { 1600, 1200, 16, 70, 0x14, 0x17, 0x31},
  3119. { 1152, 864, 24, 85, 0x14, 0x17, 0x31},
  3120. { 1280, 960, 24, 75, 0x14, 0x17, 0x31},
  3121. { 1024, 768, 32, 85, 0x14, 0x17, 0x31},
  3122. };
  3123. // Get the current clock speed.
  3124. BCLKMultiplier = *pBCLKMultiplier_reg;
  3125. // Browse the table to find a match for the requested video mode.
  3126. for (i = 0; i < sizeof(FIFOTable) / sizeof(FIFOTable[0]); i++)
  3127. {
  3128. if ( (FIFOTable[i].xRes == pReqModeTable->XResol)
  3129. && (FIFOTable[i].yRes == pReqModeTable->YResol)
  3130. && (FIFOTable[i].BitsPerPixel == pReqModeTable->BitsPerPixel)
  3131. && (FIFOTable[i].RefreshRate == pReqModeTable->Frequency)
  3132. && (FIFOTable[i].BCLKMin <= BCLKMultiplier)
  3133. && (FIFOTable[i].BCLKMax >= BCLKMultiplier)
  3134. )
  3135. {
  3136. // The requested video mode has been found, so override the FIFO
  3137. // Threshold value.
  3138. VideoDebugPrint((DISPLVL, "\nMiniport - FIFO Threshold was %04X.\n",
  3139. *pDisplayThreshold_reg));
  3140. *pDisplayThreshold_reg = (*pDisplayThreshold_reg & ~0x003F)
  3141. | FIFOTable[i].FIFOThreshold;
  3142. VideoDebugPrint((DISPLVL,
  3143. "\nMiniport - FIFO Threshold changed to %04X.\n",
  3144. *pDisplayThreshold_reg));
  3145. break;
  3146. }
  3147. }
  3148. }
  3149. #endif
  3150. /****************************************************************************
  3151. * FUNCTION NAME: CLSetMode()
  3152. *
  3153. * DESCRIPTION:
  3154. * This routine sets the Laguna into the requested mode.
  3155. *
  3156. * REVISION HISTORY:
  3157. * 5/30/95 Benny Ng Initial version
  3158. ****************************************************************************/
  3159. static __inline void SetVW0_TEST0 (PHW_DEVICE_EXTENSION HwDeviceExtension)
  3160. {
  3161. #undef LAGUNA_REGS
  3162. #define LAGUNA_REGS HwDeviceExtension->RegisterAddress
  3163. VOLATILE ULONG* pVW0_TEST0 = (ULONG*) (LAGUNA_REGS + 0x80F0);
  3164. // Set VW0_TEST0 to 0x42 after mode change
  3165. if (HwDeviceExtension->ChipID >= CL_GD5465)
  3166. *pVW0_TEST0 = 0x42;
  3167. };
  3168. VP_STATUS CLSetMode (PHW_DEVICE_EXTENSION HwDeviceExtension,
  3169. PVIDEO_MODE Mode)
  3170. {
  3171. VP_STATUS status;
  3172. PMODETABLE pReqModeTable;
  3173. VIDEO_X86_BIOS_ARGUMENTS biosargs;
  3174. ULONG ReqMode;
  3175. USHORT ClrMemMask = 0x0000;
  3176. #undef LAGUNA_REGS
  3177. #define LAGUNA_REGS HwDeviceExtension->RegisterAddress
  3178. VOLATILE PUSHORT pStatus_reg = (PUSHORT)(LAGUNA_REGS + STATUS_REG);
  3179. VOLATILE PUSHORT pControl_reg = (PUSHORT)(LAGUNA_REGS + CONTROL_REG);
  3180. VOLATILE PUCHAR pTileCtrl_reg = (PUCHAR) (LAGUNA_REGS + TILE_CTRL_REG);
  3181. VOLATILE ULONG* pOP0_opRDRAM_reg = (ULONG*) (LAGUNA_REGS + 0x520);
  3182. VOLATILE WORD* pOP0_opRDRAM_X_reg = (WORD*) (LAGUNA_REGS + 0x520);
  3183. VOLATILE WORD* pOP0_opRDRAM_Y_reg = (WORD*) (LAGUNA_REGS + 0x522);
  3184. VOLATILE ULONG* pDRAWBLTDEF_reg = (ULONG*) (LAGUNA_REGS + 0x584);
  3185. VOLATILE ULONG* pOP0_opBGCOLOR_reg = (ULONG*) (LAGUNA_REGS + 0x5E4);
  3186. VOLATILE ULONG* pBITMASK_reg = (ULONG*) (LAGUNA_REGS + 0x5E8);
  3187. VOLATILE ULONG* pBLTEXT_EX_reg = (ULONG*) (LAGUNA_REGS + 0x700);
  3188. VOLATILE WORD* pBLTEXT_EX_X_reg = (WORD*) (LAGUNA_REGS + 0x700);
  3189. VOLATILE WORD* pBLTEXT_EX_Y_reg = (WORD*) (LAGUNA_REGS + 0x702);
  3190. VOLATILE BYTE* pMCLK_reg = (BYTE*) (LAGUNA_REGS + 0x08C);
  3191. VOLATILE USHORT* pDTTR_reg = (USHORT*)(LAGUNA_REGS + 0xEA);
  3192. VOLATILE ULONG* pVW0_HSTRT = (ULONG*) (LAGUNA_REGS + 0x8000);
  3193. VOLATILE ULONG* pVW0_CONTROL0 = (ULONG*) (LAGUNA_REGS + 0x80E4);
  3194. VOLATILE ULONG* pVW0_TEST0 = (ULONG*) (LAGUNA_REGS + 0x80F0);
  3195. VOLATILE BYTE* pMISC_OUTPUT_reg = (BYTE*) (LAGUNA_REGS + 0x0080);
  3196. #if 0 // Stress test
  3197. PAGED_CODE();
  3198. #endif
  3199. // Reset the video window registers to their boot state
  3200. if (HwDeviceExtension->ChipID >= CL_GD5465)
  3201. {
  3202. VOLATILE ULONG* pVW0_REGS;
  3203. *pVW0_CONTROL0 = 1; // Disable and arm VW0
  3204. // Fill VW0 regs between HSTRT and CONTROL0 with 0
  3205. for (pVW0_REGS = pVW0_HSTRT; pVW0_REGS < pVW0_CONTROL0; pVW0_REGS++)
  3206. *pVW0_REGS = 0;
  3207. *pVW0_CONTROL0 = 1; // arm VW0
  3208. *pVW0_TEST0 = 0xA; // Reset TEST0 reg to boot state
  3209. };
  3210. //
  3211. // AGP HACK!!!
  3212. // If we don't have access to VGA modes, then lie.
  3213. //
  3214. if (HwDeviceExtension->Dont_Do_VGA)
  3215. {
  3216. if ((Mode->RequestedMode) == DEFAULT_MODE)
  3217. {
  3218. VideoDebugPrint((DISPLVL,
  3219. "\nMiniport - Impliment DEFAULT_MODE for Dont_Do_VGA.\n"));
  3220. // Wait for chip to go idle.
  3221. while (*pStatus_reg & 0x07);
  3222. // disable tiling.
  3223. ReqMode = Mode->RequestedMode & ~VIDEO_MODE_NO_ZERO_MEMORY;
  3224. pReqModeTable = &ModeTable[ReqMode];
  3225. CLEnableTiling(HwDeviceExtension, pReqModeTable);
  3226. HwDeviceExtension->CurrentModeNum =Mode->RequestedMode;
  3227. SetVW0_TEST0(HwDeviceExtension);
  3228. return NO_ERROR;
  3229. }
  3230. }
  3231. //
  3232. // Check to see if we are requesting a valid mode
  3233. //
  3234. ReqMode = Mode->RequestedMode & ~VIDEO_MODE_NO_ZERO_MEMORY;
  3235. if (Mode->RequestedMode & VIDEO_MODE_NO_ZERO_MEMORY)
  3236. {
  3237. ClrMemMask = 0x8000;
  3238. }
  3239. if (ReqMode >= TotalVideoModes)
  3240. {
  3241. SetVW0_TEST0(HwDeviceExtension);
  3242. return ERROR_INVALID_PARAMETER;
  3243. }
  3244. //
  3245. // If selected mode = current mode then return.
  3246. //
  3247. if (HwDeviceExtension->CurrentModeNum == ReqMode)
  3248. {
  3249. SetVW0_TEST0(HwDeviceExtension);
  3250. return NO_ERROR;
  3251. }
  3252. //
  3253. // Points to the selected mode table slot
  3254. //
  3255. pReqModeTable = &ModeTable[ReqMode];
  3256. //
  3257. // Don't try to set the mode it it is not supported by the chip/card.
  3258. //
  3259. if (pReqModeTable->ValidMode != TRUE)
  3260. {
  3261. // The reset mode is marked invalid, but we still need to
  3262. // "set" it for IOCTL_VIDEO_RESET_DEVICE.
  3263. if (Mode->RequestedMode != resetmode)
  3264. {
  3265. SetVW0_TEST0(HwDeviceExtension);
  3266. return ERROR_INVALID_PARAMETER;
  3267. }
  3268. }
  3269. //
  3270. // Wait for chip to go idle.
  3271. //
  3272. while (*pStatus_reg & 0x07);
  3273. #if VS_CONTROL_HACK
  3274. // Enable PCI configuration registers.
  3275. CLEnablePCIConfigMMIO(HwDeviceExtension);
  3276. #endif
  3277. //
  3278. // If a SetModeString is available, then call SetMode().
  3279. //
  3280. if (pReqModeTable->SetModeString)
  3281. {
  3282. UCHAR reg_SR15;
  3283. // Set the mode.
  3284. VideoDebugPrint((DISPLVL, "Miniport - Calling SetMode\n"));
  3285. SetMode(pReqModeTable->SetModeString,
  3286. HwDeviceExtension->RegisterAddress,
  3287. NULL,
  3288. HwDeviceExtension->Dont_Do_VGA);
  3289. if (Mode->RequestedMode == resetmode)
  3290. {
  3291. // After doing HwReset, NT can call the BIOS to set a mode.
  3292. // There is one 'gotcha' here. If we previously set a mode without
  3293. // using the BIOS, then the BIOS doesn't know what the current mode
  3294. // is, and may not set the new mode correctly.
  3295. // If we clear bit 5 in SR15 prior to setting the mode, then the
  3296. // BIOS will 'set everything' when it sets the mode.
  3297. VideoPortWritePortUchar((PUCHAR) 0x3C4, 0x15); // Select SR15
  3298. reg_SR15 = VideoPortReadPortUchar((PUCHAR) 0x3C5); // Read SR15
  3299. reg_SR15 = reg_SR15 & 0xDF ; // 1101 1111 // Clear bit 5
  3300. VideoPortWritePortUchar((PUCHAR) 0x3C4, 0x15); // Select SR15
  3301. VideoPortWritePortUchar((PUCHAR) 0x3C5, reg_SR15); // Write SR15
  3302. }
  3303. }
  3304. //
  3305. // Otherwise, use BIOS to set the mode.
  3306. //
  3307. else
  3308. {
  3309. UCHAR reg_SR15;
  3310. VideoDebugPrint((DISPLVL, "Miniport - Using BIOS to set the mode\n"));
  3311. //
  3312. // Set the Vertical Monitor type.
  3313. //
  3314. if (!CLSetMonitorType(HwDeviceExtension, pReqModeTable->YResol,
  3315. pReqModeTable->MonitorTypeVal))
  3316. {
  3317. SetVW0_TEST0(HwDeviceExtension);
  3318. return ERROR_INVALID_PARAMETER;
  3319. };
  3320. //
  3321. // We are using the BIOS to set the mode.
  3322. // There is one 'gotcha' here. If we previously set a mode without
  3323. // using the BIOS, then the BIOS doesn't know what the current mode
  3324. // is, and may not set the new mode correctly.
  3325. // If we clear bit 5 in SR15 prior to setting the mode, then the
  3326. // BIOS will 'set everything' when it sets the mode.
  3327. //
  3328. VideoPortWritePortUchar((PUCHAR) 0x3C4, 0x15); // Select SR15
  3329. reg_SR15 = VideoPortReadPortUchar((PUCHAR) 0x3C5); // Read SR15
  3330. reg_SR15 = reg_SR15 & 0xDF ; // 1101 1111 // Clear bit 5
  3331. VideoPortWritePortUchar((PUCHAR) 0x3C4, 0x15); // Select SR15
  3332. VideoPortWritePortUchar((PUCHAR) 0x3C5, reg_SR15); // Write SR15
  3333. //
  3334. // Set the selected mode.
  3335. //
  3336. VideoPortZeroMemory(&biosargs, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  3337. biosargs.Eax = 0x4F02;
  3338. biosargs.Ebx = pReqModeTable->BIOSModeNum | ClrMemMask;
  3339. VideoDebugPrint((DISPLVL, "Miniport - Mode=%xH\n", biosargs.Ebx));
  3340. if ((status = VideoPortInt10(HwDeviceExtension, &biosargs)) != NO_ERROR)
  3341. {
  3342. SetVW0_TEST0(HwDeviceExtension);
  3343. return status;
  3344. };
  3345. if ((biosargs.Eax & 0xffff) != VESA_STATUS_SUCCESS)
  3346. {
  3347. SetVW0_TEST0(HwDeviceExtension);
  3348. VideoDebugPrint((1, "CLSetMode: Int10 call failed. Mode=%xH\n", biosargs.Ebx));
  3349. return ERROR_INVALID_PARAMETER;
  3350. }
  3351. } // End use BIOS to set mode.
  3352. // Set monitor sync polarity for hi-res modes.
  3353. if (pReqModeTable->XResol >= 320 || pReqModeTable->YResol >= 200)
  3354. {
  3355. *pMISC_OUTPUT_reg |= (BYTE) HwDeviceExtension->dwPolarity;
  3356. }
  3357. //
  3358. // Enable Tiling.
  3359. //
  3360. CLEnableTiling(HwDeviceExtension, pReqModeTable);
  3361. //
  3362. // SWAT, 7 Jun 97
  3363. // 5465AD: Set bit 4 in the CONTROL register to disable bugfix 201 which is
  3364. // causing hang ups in HostToScreen bitblts.
  3365. //
  3366. if ( (HwDeviceExtension->ChipID == CL_GD5465)
  3367. && (HwDeviceExtension->ChipRev >= 2)
  3368. )
  3369. {
  3370. *pControl_reg |= 0x0010;
  3371. }
  3372. //
  3373. // Turn down the clock a bit on the 5464 and 65.
  3374. //
  3375. VideoDebugPrint((DISPLVL, "Miniport - MCLK was %xH.\n", *pMCLK_reg));
  3376. if (HwDeviceExtension->ChipID == CL_GD5464)
  3377. {
  3378. *pMCLK_reg = 0x10;
  3379. VideoDebugPrint((DISPLVL, "Miniport - MCLK set to %xH.\n", *pMCLK_reg));
  3380. }
  3381. // else if (HwDeviceExtension->ChipID >= CL_GD5465)
  3382. // {
  3383. // pMCLK_reg = (BYTE*) (LAGUNA_REGS + 0x2C0);
  3384. // *pMCLK_reg = 0x13;
  3385. // VideoDebugPrint((DISPLVL, "Miniport - MCLK set to %xH.\n", *pMCLK_reg));
  3386. // }
  3387. #if MULTI_CLOCK
  3388. {
  3389. // The current mode table files have no single value for the FIFO Threshold
  3390. // register for all clock speeds. So we need to override the FIFO Threshold
  3391. // registers in case we are running at a clock speed that otherwise would
  3392. // produce a lot of noise on the screen. Notice we only implement this
  3393. // routine for the CL-GD5465 chip.
  3394. if (HwDeviceExtension->ChipID == CL_GD5465)
  3395. {
  3396. CLOverrideFIFOThreshold(HwDeviceExtension, pReqModeTable);
  3397. }
  3398. }
  3399. #endif
  3400. // Clear the video memory if we have a graphics mode.
  3401. if ((pReqModeTable->BitsPerPixel >= 8) && !ClrMemMask)
  3402. {
  3403. *pBITMASK_reg = 0xFFFFFFFF; // enable all bits
  3404. *pDRAWBLTDEF_reg = 0x100700F0; // solid color fill, ROP_PATCOPY
  3405. *pOP0_opBGCOLOR_reg = 0; // fill with black
  3406. //
  3407. // Chip bug.
  3408. // On the 5464 we must do 16 bit writes for the first BLT,
  3409. // or the chip might hang.
  3410. //
  3411. *pOP0_opRDRAM_X_reg = 0; // fill at 0,0
  3412. *pOP0_opRDRAM_Y_reg = 0; // fill at 0,0
  3413. *pBLTEXT_EX_X_reg = pReqModeTable->XResol;
  3414. *pBLTEXT_EX_Y_reg = pReqModeTable->YResol;
  3415. // Wait for the blit to complete.
  3416. while (*pStatus_reg & 0x07);
  3417. }
  3418. //
  3419. // Report some debug information.
  3420. //
  3421. VideoDebugPrint((DISPLVL,
  3422. "Miniport - CONTROL=%Xh, TILE_CTRL=%Xh, DTTR=%Xh\n",
  3423. *pControl_reg, *pTileCtrl_reg, *pDTTR_reg));
  3424. VideoDebugPrint((DISPLVL,
  3425. "Miniport - TileSize=%d, TiledTPL=%d, Interleave=%d\n",
  3426. HwDeviceExtension->TileSize, HwDeviceExtension->TiledTPL,
  3427. HwDeviceExtension->TiledInterleave));
  3428. //
  3429. // Store the new mode values.
  3430. //
  3431. HwDeviceExtension->CurrentMode = pReqModeTable;
  3432. HwDeviceExtension->CurrentModeNum = ReqMode;
  3433. SetVW0_TEST0(HwDeviceExtension);
  3434. return NO_ERROR;
  3435. } //end CLSetMode()
  3436. /****************************************************************************
  3437. * FUNCTION NAME: CLSetMonitorType()
  3438. *
  3439. * DESCRIPTION:
  3440. * Setup the monitor type.
  3441. *
  3442. * REVISION HISTORY:
  3443. * 5/30/95 Benny Ng Initial version
  3444. ****************************************************************************/
  3445. BOOLEAN CLSetMonitorType (PHW_DEVICE_EXTENSION HwDeviceExtension,
  3446. USHORT VertScanlines,
  3447. UCHAR MonitorTypeVal)
  3448. {
  3449. VIDEO_X86_BIOS_ARGUMENTS biosArguments;
  3450. ULONG tempEAX, tempEBX, tempECX;
  3451. BOOLEAN err = FALSE;
  3452. #if 0 // Stress test
  3453. PAGED_CODE();
  3454. #endif
  3455. VideoDebugPrint((DISPLVL, "Miniport - SetMonitorType\n"));
  3456. if (HwDeviceExtension->Dont_Do_VGA)
  3457. {
  3458. VideoDebugPrint((DISPLVL,
  3459. "\nMiniport - Impliment CLSetMonitorType for Dont_Do_VGA\n\n"));
  3460. return TRUE;
  3461. }
  3462. //
  3463. // Decode the selected frequency and selected vertical scanlines,
  3464. //
  3465. tempEAX = 0;
  3466. tempEBX = 0;
  3467. tempECX = 0;
  3468. if (VertScanlines <= 480)
  3469. {
  3470. // Set the Max vertical resolution & frequency
  3471. tempEAX = MonitorTypeVal & 0xF0;
  3472. }
  3473. else if (VertScanlines <= 600)
  3474. {
  3475. // Set the Max vertical resolution & frequency
  3476. tempEAX = 0x1;
  3477. tempEBX = MonitorTypeVal << 8;
  3478. }
  3479. else if (VertScanlines <= 768)
  3480. {
  3481. // Set the Max vertical resolution & frequency
  3482. tempEAX = 0x2;
  3483. tempEBX = MonitorTypeVal << 8;
  3484. }
  3485. else if (VertScanlines <= 1024)
  3486. {
  3487. // Set the Max vertical resolution & frequency
  3488. tempEAX = 0x3;
  3489. tempECX = MonitorTypeVal << 8;
  3490. }
  3491. else if (VertScanlines <= 1200)
  3492. {
  3493. // Set the Max vertical resolution & frequency
  3494. tempEAX = 0x4;
  3495. tempECX = MonitorTypeVal << 8;
  3496. }
  3497. else
  3498. {
  3499. err = TRUE;
  3500. };
  3501. //
  3502. // If invalid Vertical scanlines, return FALSE
  3503. //
  3504. if (err)
  3505. {
  3506. return FALSE;
  3507. };
  3508. //
  3509. // Set the selected monitor type
  3510. //
  3511. VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  3512. biosArguments.Eax = 0x00001200 | tempEAX;
  3513. biosArguments.Ebx = 0x000000A4 | tempEBX;
  3514. biosArguments.Ecx = tempECX;
  3515. if (VideoPortInt10(HwDeviceExtension, &biosArguments) == NO_ERROR)
  3516. {
  3517. return TRUE;
  3518. }
  3519. else
  3520. {
  3521. VideoDebugPrint((DISPLVL, "Miniport - Set Monitor Type failed\n"));
  3522. return FALSE;
  3523. };
  3524. } // end CLSetMonitorType()
  3525. /****************************************************************************
  3526. * FUNCTION NAME: CLPowerManagement()
  3527. *
  3528. * DESCRIPTION:
  3529. * This routine get or set the power state. If it is GET operation, it
  3530. * saves current power state in the VIDEO_POWER_MANAGEMENT structure
  3531. * provided by NT.
  3532. *
  3533. * REVISION HISTORY:
  3534. * 5/30/95 Benny Ng Initial version
  3535. ****************************************************************************/
  3536. VP_STATUS CLPowerManagement (PHW_DEVICE_EXTENSION HwDeviceExtension,
  3537. PVIDEO_POWER_MANAGEMENT pPMinfo,
  3538. BOOLEAN SetPowerState)
  3539. {
  3540. VP_STATUS status;
  3541. VIDEO_X86_BIOS_ARGUMENTS biosargs;
  3542. PAGED_CODE();
  3543. //
  3544. // Setup VIDEO_X86_BIOS_ARGUMENTS structure to do an INT 10 to
  3545. // set or get power state
  3546. //
  3547. VideoPortZeroMemory(&biosargs, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  3548. biosargs.Eax = 0x4F10;
  3549. if (SetPowerState)
  3550. {
  3551. switch (pPMinfo->PowerState)
  3552. {
  3553. case VideoPowerOn:
  3554. biosargs.Ebx = 0x0001;
  3555. break;
  3556. case VideoPowerStandBy:
  3557. biosargs.Ebx = 0x0101;
  3558. break;
  3559. case VideoPowerSuspend:
  3560. biosargs.Ebx = 0x0201;
  3561. break;
  3562. case VideoPowerOff:
  3563. biosargs.Ebx = 0x0401;
  3564. break;
  3565. default:
  3566. break;
  3567. };
  3568. }
  3569. else
  3570. {
  3571. biosargs.Ebx = 0x0002;
  3572. };
  3573. if (biosargs.Ebx == 0)
  3574. {
  3575. return ERROR_INVALID_PARAMETER;
  3576. };
  3577. //
  3578. // Do the BIOS call
  3579. //
  3580. if ((status = VideoPortInt10(HwDeviceExtension, &biosargs)) != NO_ERROR)
  3581. {
  3582. return status;
  3583. };
  3584. //
  3585. // If it is GET operation, saves the power state in the output buffer
  3586. //
  3587. if (!SetPowerState)
  3588. {
  3589. pPMinfo->Length = sizeof(VIDEO_POWER_MANAGEMENT);
  3590. pPMinfo->DPMSVersion = 0x1;
  3591. switch (biosargs.Ebx & 0x00000F00)
  3592. {
  3593. case 0x000:
  3594. pPMinfo->PowerState = VideoPowerOn;
  3595. break;
  3596. case 0x100:
  3597. pPMinfo->PowerState = VideoPowerStandBy;
  3598. break;
  3599. case 0x200:
  3600. pPMinfo->PowerState = VideoPowerSuspend;
  3601. break;
  3602. case 0x400:
  3603. pPMinfo->PowerState = VideoPowerOff;
  3604. break;
  3605. default:
  3606. pPMinfo->PowerState = (ULONG) -1;
  3607. break;
  3608. };
  3609. };
  3610. //
  3611. // Update the local copy of the power state
  3612. //
  3613. if (pPMinfo->PowerState != (ULONG) -1)
  3614. {
  3615. HwDeviceExtension->PowerState = pPMinfo->PowerState;
  3616. };
  3617. return NO_ERROR;
  3618. }; // CLGetPowerManagement()
  3619. //*****************************************************************************
  3620. //
  3621. // CLEnablePciBurst()
  3622. //
  3623. // Detect bad motherboard chip sets and don't turn on the HD_BRST_EN bit.
  3624. //
  3625. // Return TRUE if bursting was enabled.
  3626. // Return FALSE if it was disabled.
  3627. //
  3628. //*****************************************************************************
  3629. BOOLEAN CLEnablePciBurst(
  3630. PHW_DEVICE_EXTENSION hwDeviceExtension
  3631. )
  3632. {
  3633. PCI_COMMON_CONFIG PciCommonConfig;
  3634. BOOLEAN HDBrstEN;
  3635. USHORT VendorId, DevId, HWRev;
  3636. ULONG Slot, Bus, ulTmp, i;
  3637. #undef LAGUNA_REGS
  3638. #define LAGUNA_REGS (hwDeviceExtension->RegisterAddress)
  3639. VOLATILE ULONG *pHostMasterControl = (PULONG) (LAGUNA_REGS + 0x4440);
  3640. VOLATILE ULONG *pVSControl_reg = (PULONG) (LAGUNA_REGS + VSCONTROL_REG);
  3641. VOLATILE WORD *pFB_Cache_Ctrl = (WORD *) (LAGUNA_REGS + 0x2C8);
  3642. VOLATILE USHORT *pTilingCtrl_reg = (USHORT*)(LAGUNA_REGS + 0x2C4);
  3643. VOLATILE USHORT *pPerformance_reg = (USHORT*)(LAGUNA_REGS + 0x58C);
  3644. VOLATILE ULONG *pControl2_reg = (PULONG) (LAGUNA_REGS + 0x418);
  3645. PAGED_CODE();
  3646. VideoDebugPrint((DISPLVL, "Miniport - CLEnablePciBurst.\n"));
  3647. //
  3648. // There are three burst settings we need to concern ourselves with.
  3649. //
  3650. // FRAME BUFFER - Bursting to the frame buffer is broken on the
  3651. // 5462, 5464 and 5465. We always turn this off.
  3652. //
  3653. // HOSTDATA - Bursting to HOSTDATA works for some motherboard chipsets
  3654. // but not for others. We have a table listing the bad chipsets.
  3655. //
  3656. // HOST_X_Y - Bursting to the Host XY unit is broken on the 5464, but
  3657. // works on the 5465.
  3658. //
  3659. if ( (hwDeviceExtension->ChipID > CL_GD5465)
  3660. || ( (hwDeviceExtension->ChipID == CL_GD5465)
  3661. && (hwDeviceExtension->ChipRev >= 3)
  3662. )
  3663. )
  3664. {
  3665. // Enable frame buffer bursting on 5465AF and higher.
  3666. *pVSControl_reg |= (1 << 13);
  3667. VideoDebugPrint((DISPLVL, "-> Enabled frame buffer bursting.\n"));
  3668. }
  3669. else
  3670. {
  3671. // Disable frame buffer bursting on all other chips.
  3672. *pVSControl_reg &= ~(1 << 13);
  3673. VideoDebugPrint((DISPLVL, "-> Disabled frame buffer bursting.\n"));
  3674. }
  3675. //
  3676. // HostXY. Disable on 5464.
  3677. //
  3678. if (hwDeviceExtension->ChipID == CL_GD5464)
  3679. {
  3680. ulTmp = *pHostMasterControl;
  3681. ulTmp |= 0x3; // Set bit 0-1 to disable burst.
  3682. *pHostMasterControl = ulTmp;
  3683. VideoDebugPrint((DISPLVL, " Disabled HOST_XY bursting.\n"));
  3684. }
  3685. else if (hwDeviceExtension->ChipID > CL_GD5464)
  3686. {
  3687. ulTmp = *pHostMasterControl;
  3688. ulTmp &= 0xFFFFFFFC; // Clear bit 0-1 to enable burst.
  3689. *pHostMasterControl = ulTmp;
  3690. VideoDebugPrint((DISPLVL, " Enabled HOST_XY bursting.\n"));
  3691. }
  3692. //
  3693. // HOSTDATA bursting.
  3694. //
  3695. #if 1
  3696. HDBrstEN = FALSE; // force 'disabled' till the following code is validated
  3697. #else
  3698. HDBrstEN = TRUE; // default is 'enabled'.
  3699. // For each ID in our list of bad motherboards.
  3700. for (i = 0; i < NUMBADCHIPSET && HDBrstEN; i++)
  3701. {
  3702. VendorId = BadChipSet[i].VendorId;
  3703. DevId = BadChipSet[i].DeviceId;
  3704. HWRev = BadChipSet[i].HwRev;
  3705. //
  3706. // search PCI space and see if the bad ID is there.
  3707. //
  3708. Bus = 0;
  3709. Slot = 0;
  3710. while ( ulTmp = HalGetBusData(PCIConfiguration,
  3711. Bus,
  3712. Slot,
  3713. &PciCommonConfig,
  3714. PCI_COMMON_HDR_LENGTH) )
  3715. {
  3716. if ((ulTmp > 4) &&
  3717. (PciCommonConfig.VendorID == VendorId) &&
  3718. (PciCommonConfig.DeviceID == DevId))
  3719. {
  3720. // This motherboard is a bad one.
  3721. HDBrstEN = FALSE;
  3722. break; // quit looking.
  3723. }
  3724. if ( ++Slot == MAX_SLOTS )
  3725. {
  3726. Slot = 0;
  3727. Bus++;
  3728. }
  3729. } // end while
  3730. } // end for each id in our list of bad ones.
  3731. #endif
  3732. if (HDBrstEN)
  3733. {
  3734. ulTmp = *pVSControl_reg;
  3735. ulTmp |= 0x00001000; // Set bit 12 to enable.
  3736. *pVSControl_reg = ulTmp;
  3737. VideoDebugPrint((DISPLVL, " Enabled HOSTDATA bursting.\n"));
  3738. }
  3739. else
  3740. {
  3741. ulTmp = *pVSControl_reg;
  3742. ulTmp &= 0xFFFFEFFF; // Clear bit 12 to disable.
  3743. *pVSControl_reg = ulTmp;
  3744. VideoDebugPrint((DISPLVL, " Disabled HOSTDATA bursting.\n"));
  3745. }
  3746. //
  3747. // Frame buffer caching is broken on the 65
  3748. //
  3749. if (hwDeviceExtension->ChipID >= CL_GD5465)
  3750. {
  3751. //
  3752. // Frame buffer caching is broken on the 65
  3753. //
  3754. WORD temp = *pFB_Cache_Ctrl;
  3755. temp = temp & 0xFFFE; // turn off bit 0.
  3756. *pFB_Cache_Ctrl = temp;
  3757. }
  3758. //
  3759. // Enable 5465AD optimizations.
  3760. //
  3761. if ( ((hwDeviceExtension->ChipID==CL_GD5465) // 5465
  3762. && (hwDeviceExtension->ChipRev>1)) // rev AD
  3763. || (hwDeviceExtension->ChipID > CL_GD5465)) // and later.
  3764. {
  3765. // Reduce Address Translate Delay to 3 clocks.
  3766. *pTilingCtrl_reg = (*pTilingCtrl_reg| 0x0001);
  3767. // Enable 256-byte fetch.
  3768. *pPerformance_reg = (*pPerformance_reg & ~0x4000);
  3769. *pControl2_reg = (*pControl2_reg | 0x0010);
  3770. }
  3771. *pPerformance_reg = (*pPerformance_reg | 0x0484);
  3772. VideoDebugPrint((DISPLVL, "Miniport - CLEnablePciBurst - Exit.\n"));
  3773. return HDBrstEN;
  3774. }
  3775. //*****************************************************************************
  3776. //
  3777. // CLFindLagunaOnPciBus
  3778. //
  3779. // Scan all the slots on the PCI bus and look for a Laguna chip.
  3780. //
  3781. // If we find one, store it's PCI ID in the hwDeviceExtension, and
  3782. // and store it's PCI mappings in the AccessRanges structure.
  3783. //
  3784. // Return NO_ERROR if we find a Laguna
  3785. // Return ERROR_DEV_NOT_EXIST if we don't
  3786. //
  3787. //*****************************************************************************
  3788. VP_STATUS CLFindLagunaOnPciBus(
  3789. PHW_DEVICE_EXTENSION hwDeviceExtension,
  3790. PVIDEO_ACCESS_RANGE pAccessRanges // Points to the first of the two Laguna
  3791. // access ranges. We will fill these
  3792. // two ranges with data from PCI space.
  3793. )
  3794. {
  3795. UCHAR Command;
  3796. PCI_COMMON_CONFIG PciCommonConfig;
  3797. BOOLEAN DeviceFound = FALSE;
  3798. USHORT VendorId = VENDOR_ID; // Vender Id
  3799. ULONG Slot = 0;
  3800. ULONG ulTmp,i;
  3801. VP_STATUS status = ERROR_DEV_NOT_EXIST;
  3802. PAGED_CODE();
  3803. VideoDebugPrint((DISPLVL, "Miniport - Searching PCI bus for Laguna card.\n"));
  3804. #if _WIN32_WINNT >= 0x0500
  3805. status = VideoPortGetAccessRanges(hwDeviceExtension,
  3806. 0,
  3807. NULL,
  3808. NUM_MM_ACCESS_RANGES,
  3809. pAccessRanges,
  3810. NULL,
  3811. NULL,
  3812. NULL);
  3813. if (status == NO_ERROR)
  3814. {
  3815. ulTmp = VideoPortGetBusData(hwDeviceExtension,
  3816. PCIConfiguration,
  3817. 0,
  3818. &PciCommonConfig,
  3819. 0,
  3820. PCI_COMMON_HDR_LENGTH);
  3821. // Rev AC of the Laguna chip (5462) is not supported.
  3822. if ( (PciCommonConfig.DeviceID == CL_GD5462) // CL-GD5462
  3823. && (PciCommonConfig.RevisionID == 0) // Rev AC
  3824. )
  3825. {
  3826. status = ERROR_DEV_NOT_EXIST;
  3827. }
  3828. }
  3829. #else
  3830. //
  3831. // Loop through the PCI slots, looking our chip.
  3832. //
  3833. for (Slot = 0; Slot < MAX_SLOTS; Slot++)
  3834. {
  3835. // Get data from a PCI slot.
  3836. ulTmp = VideoPortGetBusData(hwDeviceExtension,
  3837. PCIConfiguration,
  3838. Slot,
  3839. &PciCommonConfig,
  3840. 0,
  3841. PCI_COMMON_HDR_LENGTH);
  3842. // Is the card in this slot a Cirrus card?
  3843. if ((ulTmp > 4) && (PciCommonConfig.VendorID != VendorId))
  3844. continue; // Nope. Next slot.
  3845. //
  3846. // It's a Cirrus card. But is it a Laguna?
  3847. // Loop through our list of Laguna devices and see if
  3848. // the card in this slot is on the list.
  3849. //
  3850. i = 0;
  3851. DeviceFound = FALSE;
  3852. while ((DeviceId[i] != 0) && (DeviceFound == FALSE))
  3853. {
  3854. if ( (PciCommonConfig.DeviceID == DeviceId[i])
  3855. #if 1 // PDR#11377
  3856. && (PciCommonConfig.Command &
  3857. (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE))
  3858. #endif
  3859. )
  3860. {
  3861. DeviceFound = TRUE; // It's a Laguna.
  3862. break; // Exit FOR loop.
  3863. }
  3864. i++;
  3865. }
  3866. if (! DeviceFound)
  3867. continue; // Nope, not a supported Laguna. Next slot.
  3868. // Rev AC of the Laguna chip (5462) is not supported.
  3869. if ((PciCommonConfig.DeviceID == CL_GD5462) &&
  3870. (PciCommonConfig.RevisionID == 0)) // Rev AC
  3871. continue; // move on to next PCI slot.
  3872. // We found a card we can use. Quit looking.
  3873. status = NO_ERROR;
  3874. break; // Exit FOR loop.
  3875. } // end for slot
  3876. #endif
  3877. //
  3878. // Did we find our chip?
  3879. //
  3880. if (status != NO_ERROR)
  3881. return status; // Nope. Return the error.
  3882. //
  3883. // Store the chip ID and revision in the DeviceExtention so
  3884. // the display driver can find out what chip it's using.
  3885. //
  3886. hwDeviceExtension->ChipID = PciCommonConfig.DeviceID;
  3887. hwDeviceExtension->ChipRev = PciCommonConfig.RevisionID;
  3888. // Save the slot number for future use.
  3889. hwDeviceExtension->SlotNumber = Slot;
  3890. //
  3891. // Tell PCI to enable the IO and memory addresses.
  3892. //
  3893. // Get PCI COMMAND reg.
  3894. ulTmp = VideoPortGetBusData(
  3895. hwDeviceExtension,
  3896. PCIConfiguration,
  3897. Slot,
  3898. &Command,
  3899. FIELD_OFFSET(PCI_COMMON_CONFIG, Command),
  3900. 1);
  3901. if (ulTmp != 1) // Error talking to PCI space.
  3902. return ERROR_DEV_NOT_EXIST;
  3903. // The 5464 and later can Bus Master.
  3904. if (hwDeviceExtension->ChipID >= CL_GD5464)
  3905. Command |= PCI_ENABLE_BUS_MASTER;
  3906. // Set PCI COMMAND reg.
  3907. VideoPortSetBusData(hwDeviceExtension,
  3908. PCIConfiguration,
  3909. Slot,
  3910. &Command,
  3911. FIELD_OFFSET(PCI_COMMON_CONFIG, Command),
  3912. 1);
  3913. //
  3914. // Get the PCI configuration data
  3915. //
  3916. ulTmp = VideoPortGetBusData(hwDeviceExtension,
  3917. PCIConfiguration,
  3918. Slot,
  3919. &PciCommonConfig,
  3920. 0,
  3921. PCI_COMMON_HDR_LENGTH);
  3922. //
  3923. // Setup Access Range for Register space
  3924. //
  3925. if (hwDeviceExtension->ChipID == CL_GD5462)
  3926. {
  3927. // 5462 decodes 16 k of register address space.
  3928. pAccessRanges->RangeStart.LowPart =
  3929. PciCommonConfig.u.type0.BaseAddresses[0] & 0xFFFFC000;
  3930. pAccessRanges->RangeStart.HighPart = 0x00000000;
  3931. pAccessRanges->RangeLength = (16 * 1024);
  3932. }
  3933. else if (hwDeviceExtension->ChipID <= CL_GD5464_BD)
  3934. {
  3935. // 5464 and BD decode 32 k of register address space.
  3936. pAccessRanges->RangeStart.LowPart =
  3937. PciCommonConfig.u.type0.BaseAddresses[0] & 0xFFFF8000;
  3938. pAccessRanges->RangeStart.HighPart = 0x00000000;
  3939. pAccessRanges->RangeLength = (32 * 1024);
  3940. }
  3941. else // For the 5465 and later we swapped the the PCI regs around.
  3942. {
  3943. // Use the defaults
  3944. pAccessRanges->RangeStart.LowPart =
  3945. PciCommonConfig.u.type0.BaseAddresses[1]
  3946. & DEFAULT_RESERVED_REGISTER_MASK;
  3947. pAccessRanges->RangeStart.HighPart = 0x00000000;
  3948. pAccessRanges->RangeLength = DEFAULT_RESERVED_REGISTER_SPACE;
  3949. }
  3950. pAccessRanges->RangeInIoSpace = FALSE;
  3951. pAccessRanges->RangeVisible = TRUE;
  3952. pAccessRanges->RangeShareable = FALSE;
  3953. //
  3954. // Setup Access Range for Frame buffer
  3955. // the 62 and the 64 both use the default frame buffer size.
  3956. //
  3957. ++pAccessRanges; // move to next access range to be filled in.
  3958. // The 65 and later have PCI BASE ADDR regs 0 and 1 reversed.
  3959. if (hwDeviceExtension->ChipID <= CL_GD5464_BD)
  3960. pAccessRanges->RangeStart.LowPart =
  3961. PciCommonConfig.u.type0.BaseAddresses[1] & DEFAULT_RESERVED_FB_MASK;
  3962. else
  3963. pAccessRanges->RangeStart.LowPart =
  3964. PciCommonConfig.u.type0.BaseAddresses[0] & DEFAULT_RESERVED_FB_MASK;
  3965. pAccessRanges->RangeStart.HighPart = 0x00000000;
  3966. pAccessRanges->RangeLength = DEFAULT_RESERVED_FB_SPACE;
  3967. pAccessRanges->RangeInIoSpace = FALSE;
  3968. pAccessRanges->RangeVisible = TRUE;
  3969. pAccessRanges->RangeShareable = FALSE;
  3970. status = NO_ERROR;
  3971. return status;
  3972. }
  3973. // ****************************************************************************
  3974. //
  3975. // ClAllocateCommonBuffer()
  3976. //
  3977. // Allocates a locked down common buffer for bus mastered data transfers.
  3978. //
  3979. // If the Alloc fails, it isn't fatal; we just don't do bus mastering.
  3980. // The driver can test the size of the common buffer to see if it exists.
  3981. //
  3982. // ****************************************************************************
  3983. VOID ClAllocateCommonBuffer(
  3984. PHW_DEVICE_EXTENSION HwDeviceExtension
  3985. )
  3986. {
  3987. PHYSICAL_ADDRESS logicalAddress;
  3988. PVOID VirtualAddr;
  3989. PADAPTER_OBJECT AdapterObject;
  3990. DEVICE_DESCRIPTION DeviceDescription;
  3991. ULONG NumberOfMapRegisters;
  3992. PAGED_CODE();
  3993. //
  3994. // No common buffer exists at this time.
  3995. //
  3996. HwDeviceExtension->CommonBufferSize = 0;
  3997. HwDeviceExtension->PhysicalCommonBufferAddr = 0;
  3998. HwDeviceExtension->VirtualCommonBufferAddr = 0;
  3999. #if NO_BUS_MASTER
  4000. return;
  4001. #else
  4002. //
  4003. // CL5462 doesn't do bus masters.
  4004. //
  4005. if (HwDeviceExtension->ChipID == CL_GD5462)
  4006. {
  4007. VideoDebugPrint((DISPLVL,
  4008. "Miniport - AllocCommonBuffer Failed: CL5462 doesn't bus master.\n"));
  4009. return;
  4010. }
  4011. // Set up the device attributes description
  4012. RtlZeroMemory(&DeviceDescription, sizeof(DeviceDescription));
  4013. DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
  4014. DeviceDescription.Master = TRUE;
  4015. DeviceDescription.ScatterGather = TRUE;
  4016. DeviceDescription.DemandMode = TRUE;
  4017. DeviceDescription.AutoInitialize = TRUE;
  4018. DeviceDescription.Dma32BitAddresses = TRUE;
  4019. DeviceDescription.IgnoreCount = FALSE;
  4020. DeviceDescription.Reserved1 = FALSE;
  4021. DeviceDescription.Reserved2 = FALSE;
  4022. DeviceDescription.BusNumber = HwDeviceExtension->SystemIoBusNumber;
  4023. DeviceDescription.DmaChannel = 0;
  4024. DeviceDescription.InterfaceType = PCIBus;
  4025. DeviceDescription.DmaWidth = Width32Bits;
  4026. DeviceDescription.DmaSpeed = 0;
  4027. DeviceDescription.MaximumLength = SIZE_BUS_MASTER_BUFFER;
  4028. DeviceDescription.DmaPort = 0;
  4029. NumberOfMapRegisters = SIZE_BUS_MASTER_BUFFER/PAGE_SIZE + 1;
  4030. // Get a pointer to the adapter object. This is required for allocating
  4031. // a buffer for bus mastering.
  4032. AdapterObject = (PADAPTER_OBJECT)HalGetAdapter(&DeviceDescription, &NumberOfMapRegisters);
  4033. if (AdapterObject == NULL)
  4034. VideoDebugPrint((DISPLVL, "Miniport - HalGetAdapter failed.\n"));
  4035. //
  4036. // Request a common buffer.
  4037. // The physical address of the common buffer will come back in
  4038. // logicalAddress
  4039. //
  4040. VirtualAddr = (void *)HalAllocateCommonBuffer(
  4041. AdapterObject, // (IN) Adapter object
  4042. SIZE_BUS_MASTER_BUFFER, // (IN) Length.
  4043. &logicalAddress, // (OUT) Phys address.
  4044. FALSE); // (IN) Not cachable.
  4045. //
  4046. // Warn if we got back a NULL
  4047. //
  4048. if (VirtualAddr == NULL)
  4049. {
  4050. VideoDebugPrint((DISPLVL,
  4051. "Miniport - AllocCommonBuffer Virtual Addr Failed.\n"));
  4052. return;
  4053. }
  4054. if ((logicalAddress.HighPart==0) && (logicalAddress.LowPart==0))
  4055. {
  4056. VideoDebugPrint((DISPLVL,
  4057. "Miniport - AllocCommonBuffer Physical Addr Failed.\n"));
  4058. return;
  4059. }
  4060. //
  4061. // CL5464 chip bug. If bit 27 of the address is 0, it will
  4062. // hose the chip.
  4063. //
  4064. if ( logicalAddress.LowPart & (1>>27) )
  4065. {
  4066. VideoDebugPrint((DISPLVL,
  4067. "Miniport - AllocCommonBuffer failed: Physical Addr bit 27 set.\n"));
  4068. return;
  4069. }
  4070. //
  4071. // Store the size and address of the common buffer.
  4072. // Size != 0 will indicate success to the rest of the driver.
  4073. //
  4074. HwDeviceExtension->CommonBufferSize = SIZE_BUS_MASTER_BUFFER;
  4075. HwDeviceExtension->VirtualCommonBufferAddr = (UCHAR*) VirtualAddr;
  4076. HwDeviceExtension->PhysicalCommonBufferAddr =
  4077. (UCHAR*) logicalAddress.LowPart;
  4078. VideoDebugPrint((DISPLVL,
  4079. "Miniport - Buffer is at HIGH: 0x%08X LOW: 0x%08X Virtual: 0x%08X\n",
  4080. logicalAddress.HighPart, logicalAddress.LowPart, VirtualAddr));
  4081. #endif // NO_BUS_MASTER
  4082. }
  4083. #if VS_CONTROL_HACK
  4084. // ****************************************************************************
  4085. //
  4086. // CLEnablePCIConfigMMIO()
  4087. //
  4088. // Enables memory-mapped access to PCI configuration registers.
  4089. //
  4090. // ****************************************************************************
  4091. VP_STATUS CLEnablePCIConfigMMIO(
  4092. PHW_DEVICE_EXTENSION HwDeviceExtension
  4093. )
  4094. {
  4095. ULONG VSCValue;
  4096. ULONG ulTmp;
  4097. // Get the current value of the VSC register
  4098. ulTmp = VideoPortGetBusData(
  4099. HwDeviceExtension,
  4100. PCIConfiguration, // bus data type
  4101. HwDeviceExtension->SlotNumber, // slot number
  4102. &VSCValue, // buffer for returned data
  4103. 0xfc, // VS Control offset
  4104. 4); // 4 bytes
  4105. if (ulTmp != 4) // we only want 4 bytes back
  4106. {
  4107. return(ERROR_DEV_NOT_EXIST);
  4108. }
  4109. else
  4110. {
  4111. // Set bit to enable memory-mapped access to PCI configuration regs
  4112. VSCValue |= 1;
  4113. VideoPortSetBusData(
  4114. HwDeviceExtension,
  4115. PCIConfiguration, // bus data type
  4116. HwDeviceExtension->SlotNumber, // slot number
  4117. &VSCValue, // value to set
  4118. 0xfc, // VS Control offset
  4119. 4); // 4 bytes
  4120. return(NO_ERROR);
  4121. }
  4122. }
  4123. #endif