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.

8805 lines
276 KiB

  1. //---------------------------------------------------------------------------
  2. /*++
  3. Copyright (c) 1992-1997 Microsoft Corporation.
  4. Copyright (c) 1996-1997 Cirrus Logic, Inc.,
  5. Module Name:
  6. C I R R U S . C
  7. Abstract:
  8. This is the miniport driver for the Cirrus Logic
  9. 6410/6420/542x/543x/544x/548x/754x/755x VGA's.
  10. Environment:
  11. Kernel mode only
  12. Notes:
  13. Revision History:
  14. * $Log: S:/projects/drivers/ntsrc/miniport/cirrus.c_v $
  15. *
  16. * Rev 1.16 Apr 03 1997 15:44:40 unknown
  17. *
  18. *
  19. * Rev 1.10 Jan 08 1997 14:25:40 unknown
  20. * Fix the 440FX and 5446AC coexist problem.
  21. *
  22. * Rev 1.9 18 Dec 1996 14:03:48 PLCHU
  23. *
  24. *
  25. * Rev 1.7 Dec 06 1996 11:14:16 unknown
  26. *
  27. *
  28. * Rev 1.6 Nov 26 1996 16:29:02 unknown
  29. *
  30. *
  31. * Rev 1.8 Nov 26 1996 16:02:20 unknown
  32. * Add conditional compile for P6Cache
  33. *
  34. * Rev 1.7 Nov 26 1996 14:32:42 unknown
  35. * turn on PCI14 and second aperture for 5480
  36. *
  37. * Rev 1.6 Nov 18 1996 16:23:32 unknown
  38. * Add P6 Cache flag and fix 5436BG hung bug for HCT
  39. *
  40. * Rev 1.5 Nov 05 1996 14:49:56 unknown
  41. * turn off PCI14 for 5480 temporaryly
  42. *
  43. * Rev 1.4 Nov 01 1996 16:44:54 unknown
  44. *
  45. * Rev 1.3 Oct 14 1996 10:49:36 unknown
  46. * Add 100Hz monitor support and Detailed timnig calculation
  47. *
  48. * Rev 1.4 07 Aug 1996 14:43:02 frido
  49. * Added better support for monochrome text modes.
  50. *
  51. * Rev 1.3 06 Aug 1996 18:35:54 frido
  52. * Changed the way the video memory is shared in linear mode.
  53. *
  54. * Rev 1.2 06 Aug 1996 17:19:20 frido
  55. * Removed banking in linear mode.
  56. *
  57. * chu01 08-26-96 Distinguish CL-5480 and CL-5436/46 because the former
  58. * has new fratures such as XY-clipping, XY-position and
  59. * BLT command list that the others do not have.
  60. * jl01 09-24-96 Fix Alt+Tab switching between "Introducing Windows NT"
  61. * and "Main". Refer to PDR#5409.
  62. * jl02 10-21-96 Add CL-5446BE support.
  63. * sge01 10-14-96 VGA register and MMIO register can be relocatable.
  64. * sge02 10-22-96 VideoMemoryAddress use linear address instead of A0000.
  65. * sge03 10-23-96 Add second aperture maping
  66. * chu02 10-31-96 DDC2B enabling / disabling
  67. * sge04 11-04-96 Disable PCI14 for 5480 temporaryly
  68. * sge05 11-07-96 Add P6Cache support
  69. * sge06 11-26-96 Add conditional compile for P6Cache support
  70. * jl03 12-05-96 Set CL-5446BE flag "CL5446BE"
  71. * chu03 12-16-96 Enable color correction
  72. * sge07 12-16-96 Check mono or color mode before reading input status
  73. * sge08 01-08-97 Fix the 440FX and 5446AC coexist problem.
  74. * myf0 08-19-96 added 85hz supported
  75. * myf1 08-20-96 supported panning scrolling
  76. * myf2 08-20-96 fixed hardware save/restore state bug for matterhorn
  77. * myf3 09-01-96 Added IOCTL_CIRRUS_PRIVATE_BIOS_CALL for TV supported
  78. * myf4 09-01-96 patch Viking BIOS bug, PDR #4287, begin
  79. * myf5 09-01-96 Fixed PDR #4365 keep all default refresh rate
  80. * myf6 09-17-96 Merged Desktop SRC1001 & MINI102
  81. * myf7 09-19-96 Fixed exclude 60Hz refresh rate select
  82. * myf8 *09-21-96* May be need change CheckandUpdateDDC2BMonitor --keystring[]
  83. * myf9 09-21-96 8x6 panel in 6x4x256 mode, cursor can't move to bottom scrn
  84. * ms0809 09-25-96 fixed dstn panel icon corrupted
  85. * ms923 09-25-96 merge MS-923 Disp.zip code
  86. * myf10 09-26-96 Fixed DSTN reserved half-frame buffer bug.
  87. * myf11 09-26-96 Fixed 755x CE chip HW bug, access ramdac before disable HW
  88. * icons and cursor
  89. * myf12 10-01-96 Supported Hot Key switch display
  90. * myf13 10-05-96 Fixed /w panning scrolling, vertical expension on bug
  91. * myf14 10-15-96 Fixed PDR#6917, 6x4 panel can't panning scrolling for 754x
  92. * myf15 10-16-96 Fixed disable memory mapped IO for 754x, 755x
  93. * myf16 10-22-96 Fixed PDR #6933,panel type set different demo board setting
  94. * smith 10-22-96 Disable Timer event, because sometimes creat PAGE_FAULT or
  95. * IRQ level can't handle
  96. * myf17 11-04-96 Added special escape code must be use 11/5/96 later NTCTRL,
  97. * and added Matterhorn LF Device ID==0x4C
  98. * myf18 11-04-96 Fixed PDR #7075,
  99. * myf19 11-06-96 Fixed Vinking can't work problem, because DEVICEID = 0x30
  100. * is different from data book (CR27=0x2C)
  101. * myf20 11-12-96 Fixed DSTN panel initial reserved 128K memoru
  102. * myf21 11-15-96 fixed #7495 during change resolution, screen appear garbage
  103. * image, because not clear video memory.
  104. * myf22 11-19-96 Added 640x480x256/640x480x64K -85Hz refresh rate for 7548
  105. * myf23 11-21-96 Added fixed NT 3.51 S/W cursor panning problem
  106. * myf24 11-22-96 Added fixed NT 4.0 Japanese dos full screen problem
  107. * myf25 12-03-96 Fixed 8x6x16M 2560byte/line patch H/W bug PDR#7843, and
  108. * fixed pre-install microsoft requested
  109. * myf26 12-11-96 Fixed Japanese NT 4.0 Dos-full screen bug for LCD enable
  110. * myf27 01-09-96 Fixed NT3.51 PDR#7986, horizontal lines appears at logon
  111. * windows, set 8x6x64K mode boot up CRT, jumper set 8x6 DSTN
  112. * Fixed NT3.51 PDR#7987, set 64K color modes, garbage on
  113. * screen when boot up XGA panel.
  114. * myf28 02-03-97 Fixed NT3.51 PDR#8357, mode 3, 12, panning scrolling bug
  115. * myf29 02-12-97 Support Gamma correction graphic/video LUT for 755x
  116. * myf30 02-10-97 Fixed NT3.51, 6x4 LCD boot set 256 coloe, test 64K mode
  117. * jl04 02-11-97 Fix 542x VLB banking issue.
  118. * myf31 02-25-97 Fixed RadiSys system, set MCLK to 66MHz
  119. * myf32 03-02-97 Display each chip information
  120. * sge09 03-10-97 Add P6CACHE condition compile.
  121. * chu04 03-10-97 Chip type "5430/40", instead of "5430" requested by Intel.
  122. * chu05 03-13-97 For 5436 checked build NT, read 4-byte PCI
  123. * configuration register to access index 0x53 instead of
  124. * the whole 256 bytes.
  125. * chu06 03-26-97 Common routine to get Cirrus chip and revision IDs.
  126. * jl05 03-28-97 Fix for NT3.51
  127. --*/
  128. //---------------------------------------------------------------------------
  129. #include <dderror.h>
  130. #include <devioctl.h>
  131. #include <miniport.h>
  132. #include <ntddvdeo.h>
  133. #include <video.h>
  134. #include "cirrus.h"
  135. #include "clioctl.h"
  136. #include "sr754x.h"
  137. #include "cmdcnst.h"
  138. #define DDC2B 1
  139. #define QUERY_MONITOR_ID 0x22446688
  140. #define QUERY_NONDDC_MONITOR_ID 0x11223344
  141. #define LCD_type 1
  142. #define CRT_type 2
  143. #define SIM_type 3
  144. //---------------------------------------------------------------------------
  145. //
  146. // Function declarations
  147. //
  148. // Functions that start with 'VGA' are entry points for the OS port driver.
  149. //
  150. VP_STATUS
  151. VgaFindAdapter(
  152. PVOID HwDeviceExtension,
  153. PVOID HwContext,
  154. PWSTR ArgumentString,
  155. PVIDEO_PORT_CONFIG_INFO ConfigInfo,
  156. PUCHAR Again
  157. );
  158. BOOLEAN
  159. VgaInitialize(
  160. PVOID HwDeviceExtension
  161. );
  162. BOOLEAN
  163. VgaStartIO(
  164. PVOID HwDeviceExtension,
  165. PVIDEO_REQUEST_PACKET RequestPacket
  166. );
  167. //crus, smith
  168. VOID
  169. CirrusHwTimer(
  170. PVOID HwDeviceExtension
  171. );
  172. //
  173. // Private function prototypes.
  174. //
  175. VP_STATUS
  176. VgaQueryAvailableModes(
  177. PHW_DEVICE_EXTENSION HwDeviceExtension,
  178. PVIDEO_MODE_INFORMATION ModeInformation,
  179. ULONG ModeInformationSize,
  180. PULONG OutputSize
  181. );
  182. VP_STATUS
  183. VgaQueryNumberOfAvailableModes(
  184. PHW_DEVICE_EXTENSION HwDeviceExtension,
  185. PVIDEO_NUM_MODES NumModes,
  186. ULONG NumModesSize,
  187. PULONG OutputSize
  188. );
  189. VP_STATUS
  190. VgaQueryCurrentMode(
  191. PHW_DEVICE_EXTENSION HwDeviceExtension,
  192. PVIDEO_MODE_INFORMATION ModeInformation,
  193. ULONG ModeInformationSize,
  194. PULONG OutputSize
  195. );
  196. VP_STATUS
  197. VgaSetMode(
  198. PHW_DEVICE_EXTENSION HwDeviceExtension,
  199. PVIDEO_MODE Mode,
  200. ULONG ModeSize
  201. );
  202. VP_STATUS
  203. VgaLoadAndSetFont(
  204. PHW_DEVICE_EXTENSION HwDeviceExtension,
  205. PVIDEO_LOAD_FONT_INFORMATION FontInformation,
  206. ULONG FontInformationSize
  207. );
  208. #ifdef PANNING_SCROLL
  209. VP_STATUS
  210. CirrusSetDisplayPitch (
  211. PHW_DEVICE_EXTENSION HwDeviceExtension,
  212. PANNMODE PanningMode
  213. );
  214. #endif
  215. VP_STATUS
  216. VgaQueryCursorPosition(
  217. PHW_DEVICE_EXTENSION HwDeviceExtension,
  218. PVIDEO_CURSOR_POSITION CursorPosition,
  219. ULONG CursorPositionSize,
  220. PULONG OutputSize
  221. );
  222. VP_STATUS
  223. VgaSetCursorPosition(
  224. PHW_DEVICE_EXTENSION HwDeviceExtension,
  225. PVIDEO_CURSOR_POSITION CursorPosition,
  226. ULONG CursorPositionSize
  227. );
  228. VP_STATUS
  229. VgaQueryCursorAttributes(
  230. PHW_DEVICE_EXTENSION HwDeviceExtension,
  231. PVIDEO_CURSOR_ATTRIBUTES CursorAttributes,
  232. ULONG CursorAttributesSize,
  233. PULONG OutputSize
  234. );
  235. VP_STATUS
  236. VgaSetCursorAttributes(
  237. PHW_DEVICE_EXTENSION HwDeviceExtension,
  238. PVIDEO_CURSOR_ATTRIBUTES CursorAttributes,
  239. ULONG CursorAttributesSize
  240. );
  241. BOOLEAN
  242. VgaIsPresent(
  243. PHW_DEVICE_EXTENSION HwDeviceExtension
  244. );
  245. BOOLEAN
  246. CirrusLogicIsPresent(
  247. PHW_DEVICE_EXTENSION HwDeviceExtension
  248. );
  249. ULONG
  250. CirrusFindVmemSize(
  251. PHW_DEVICE_EXTENSION HwDeviceExtension
  252. );
  253. VOID
  254. CirrusValidateModes(
  255. PHW_DEVICE_EXTENSION HwDeviceExtension
  256. );
  257. VOID
  258. SetCirrusBanking(
  259. PHW_DEVICE_EXTENSION HwDeviceExtension,
  260. USHORT BankNumber
  261. );
  262. VOID
  263. vBankMap_CL64xx(
  264. ULONG iBankRead,
  265. ULONG iBankWrite,
  266. PVOID pvContext
  267. );
  268. VOID
  269. vBankMap_CL543x(
  270. ULONG iBankRead,
  271. ULONG iBankWrite,
  272. PVOID pvContext
  273. );
  274. VOID
  275. vBankMap_CL542x(
  276. ULONG iBankRead,
  277. ULONG iBankWrite,
  278. PVOID pvContext
  279. );
  280. USHORT
  281. CirrusFind6410DisplayType(
  282. PHW_DEVICE_EXTENSION HwDeviceExtension
  283. );
  284. USHORT
  285. CirrusFind6245DisplayType(
  286. PHW_DEVICE_EXTENSION HwDeviceExtension,
  287. PUCHAR CRTCAddrPort,
  288. PUCHAR CRTCDataPort
  289. );
  290. USHORT
  291. CirrusFind754xDisplayType(
  292. PHW_DEVICE_EXTENSION HwDeviceExtension,
  293. PUCHAR CRTCAddrPort,
  294. PUCHAR CRTCDataPort
  295. );
  296. USHORT
  297. CirrusFind755xDisplayType(
  298. PHW_DEVICE_EXTENSION HwDeviceExtension,
  299. PUCHAR CRTCAddrPort,
  300. PUCHAR CRTCDataPort
  301. );
  302. BOOLEAN
  303. CirrusFind6340(
  304. PHW_DEVICE_EXTENSION HwDeviceExtension
  305. );
  306. VOID
  307. AccessHWiconcursor(
  308. PHW_DEVICE_EXTENSION HwDeviceExtension,
  309. SHORT Access_flag
  310. );
  311. VOID
  312. VgaInterpretCmdStream(
  313. PVOID HwDeviceExtension,
  314. PUSHORT pusCmdStream
  315. );
  316. VP_STATUS
  317. VgaSetPaletteReg(
  318. PHW_DEVICE_EXTENSION HwDeviceExtension,
  319. PVIDEO_PALETTE_DATA PaletteBuffer,
  320. ULONG PaletteBufferSize
  321. );
  322. VP_STATUS
  323. VgaSetColorLookup(
  324. PHW_DEVICE_EXTENSION HwDeviceExtension,
  325. PVIDEO_CLUT ClutBuffer,
  326. ULONG ClutBufferSize
  327. );
  328. VP_STATUS
  329. VgaRestoreHardwareState(
  330. PHW_DEVICE_EXTENSION HwDeviceExtension,
  331. PVIDEO_HARDWARE_STATE HardwareState,
  332. ULONG HardwareStateSize
  333. );
  334. VP_STATUS
  335. VgaSaveHardwareState(
  336. PHW_DEVICE_EXTENSION HwDeviceExtension,
  337. PVIDEO_HARDWARE_STATE HardwareState,
  338. ULONG HardwareStateSize,
  339. PULONG OutputSize
  340. );
  341. VP_STATUS
  342. VgaGetBankSelectCode(
  343. PHW_DEVICE_EXTENSION HwDeviceExtension,
  344. PVIDEO_BANK_SELECT BankSelect,
  345. ULONG BankSelectSize,
  346. PULONG OutputSize
  347. );
  348. BOOLEAN
  349. CirrusConfigurePCI(
  350. PHW_DEVICE_EXTENSION HwDeviceExtension,
  351. PULONG NumPCIAccessRanges,
  352. PVIDEO_ACCESS_RANGE PCIAccessRanges
  353. );
  354. VOID
  355. WriteRegistryInfo(
  356. PHW_DEVICE_EXTENSION hwDeviceExtension
  357. );
  358. VP_STATUS
  359. CirrusGetDeviceDataCallback(
  360. PVOID HwDeviceExtension,
  361. PVOID Context,
  362. VIDEO_DEVICE_DATA_TYPE DeviceDataType,
  363. PVOID Identifier,
  364. ULONG IdentifierLength,
  365. PVOID ConfigurationData,
  366. ULONG ConfigurationDataLength,
  367. PVOID ComponentInformation,
  368. ULONG ComponentInformationLength
  369. );
  370. VOID
  371. IOWaitDisplEnableThenWrite(
  372. PHW_DEVICE_EXTENSION hwDeviceExtension,
  373. ULONG port,
  374. UCHAR value
  375. );
  376. VOID
  377. ReadVESATiming(
  378. PHW_DEVICE_EXTENSION hwDeviceExtension
  379. );
  380. #if (_WIN32_WINNT <= 0x0400)
  381. VOID
  382. CheckAndUpdateDDC2BMonitor(
  383. PHW_DEVICE_EXTENSION HwDeviceExtension
  384. );
  385. #endif // (_WIN32_WINNT <= 0x0400)
  386. VOID
  387. CirrusUpdate440FX(
  388. PHW_DEVICE_EXTENSION HwDeviceExtension
  389. );
  390. //
  391. // NOTE:
  392. //
  393. // This is a High Priority system callback. DO NOT mark this
  394. // routine as pageable!
  395. //
  396. BOOLEAN
  397. IOCallback(
  398. PHW_DEVICE_EXTENSION HwDeviceExtension
  399. );
  400. VP_STATUS
  401. VgaGetGammaFactor(
  402. PHW_DEVICE_EXTENSION HwDeviceExtension,
  403. PGAMMA_VALUE value,
  404. ULONG ValueLength,
  405. PULONG OutputSize
  406. );
  407. VP_STATUS
  408. VgaGetContrastFactor(
  409. PHW_DEVICE_EXTENSION HwDeviceExtension,
  410. PCONTRAST_VALUE value,
  411. ULONG ValueLength,
  412. PULONG OutputSize
  413. );
  414. UCHAR
  415. GetCirrusChipId(
  416. PHW_DEVICE_EXTENSION HwDeviceExtension
  417. );
  418. USHORT
  419. GetCirrusChipRevisionId(
  420. PHW_DEVICE_EXTENSION HwDeviceExtension
  421. );
  422. #if defined(ALLOC_PRAGMA)
  423. #pragma alloc_text(PAGE,DriverEntry)
  424. #pragma alloc_text(PAGE,VgaFindAdapter)
  425. #pragma alloc_text(PAGE,VgaInitialize)
  426. #pragma alloc_text(PAGE,VgaStartIO)
  427. #pragma alloc_text(PAGE,CirrusHwTimer)
  428. #pragma alloc_text(PAGE,VgaLoadAndSetFont)
  429. #pragma alloc_text(PAGE,VgaQueryCursorPosition)
  430. #pragma alloc_text(PAGE,VgaSetCursorPosition)
  431. #pragma alloc_text(PAGE,VgaQueryCursorAttributes)
  432. #pragma alloc_text(PAGE,VgaSetCursorAttributes)
  433. #pragma alloc_text(PAGE,VgaIsPresent)
  434. #pragma alloc_text(PAGE,CirrusLogicIsPresent)
  435. #pragma alloc_text(PAGE,CirrusFindVmemSize)
  436. #pragma alloc_text(PAGE,SetCirrusBanking)
  437. #ifdef PANNING_SCROLL
  438. #pragma alloc_text(PAGE,CirrusSetDisplayPitch)
  439. #endif
  440. #pragma alloc_text(PAGE,CirrusFind6245DisplayType)
  441. #pragma alloc_text(PAGE,CirrusFind754xDisplayType)
  442. #pragma alloc_text(PAGE,CirrusFind755xDisplayType)
  443. #pragma alloc_text(PAGE,CirrusFind6410DisplayType)
  444. #pragma alloc_text(PAGE,CirrusFind6340)
  445. #pragma alloc_text(PAGE,AccessHWiconcursor)
  446. #pragma alloc_text(PAGE,CirrusConfigurePCI)
  447. #pragma alloc_text(PAGE,VgaSetPaletteReg)
  448. #pragma alloc_text(PAGE,VgaSetColorLookup)
  449. #pragma alloc_text(PAGE,VgaRestoreHardwareState)
  450. #pragma alloc_text(PAGE,VgaSaveHardwareState)
  451. #pragma alloc_text(PAGE,VgaGetBankSelectCode)
  452. #pragma alloc_text(PAGE,VgaValidatorUcharEntry)
  453. #pragma alloc_text(PAGE,VgaValidatorUshortEntry)
  454. #pragma alloc_text(PAGE,VgaValidatorUlongEntry)
  455. #pragma alloc_text(PAGE,WriteRegistryInfo)
  456. #pragma alloc_text(PAGE,CirrusGetDeviceDataCallback)
  457. #pragma alloc_text(PAGE,CirrusUpdate440FX)
  458. #pragma alloc_text(PAGE,VgaGetGammaFactor)
  459. #pragma alloc_text(PAGE,VgaGetContrastFactor)
  460. #if (_WIN32_WINNT >= 0x0500)
  461. #pragma alloc_text(PAGE,CirrusGetChildDescriptor)
  462. #pragma alloc_text(PAGE,CirrusGetPowerState)
  463. #pragma alloc_text(PAGE,CirrusSetPowerState)
  464. #endif
  465. #endif
  466. BOOLEAN
  467. GetDdcInformation(
  468. PHW_DEVICE_EXTENSION HwDeviceExtension,
  469. PUCHAR QueryBuffer,
  470. ULONG BufferSize);
  471. ULONG
  472. CirrusGetChildDescriptor(
  473. PVOID pHwDeviceExtension,
  474. PVIDEO_CHILD_ENUM_INFO ChildEnumInfo,
  475. PVIDEO_CHILD_TYPE pChildType,
  476. PVOID pChildDescriptor,
  477. PULONG pHwId,
  478. PULONG pUnused
  479. )
  480. /*++
  481. Routine Description:
  482. Enumerate all devices controlled by the ATI graphics chip.
  483. This includes DDC monitors attached to the board, as well as other devices
  484. which may be connected to a proprietary bus.
  485. Arguments:
  486. HwDeviceExtension - Pointer to our hardware device extension structure.
  487. ChildIndex - Index of the child the system wants informaion for.
  488. pChildType - Type of child we are enumerating - monitor, I2C ...
  489. pChildDescriptor - Identification structure of the device (EDID, string)
  490. ppHwId - Private unique 32 bit ID to passed back to the miniport
  491. pMoreChildren - Should the miniport be called
  492. Return Value:
  493. Status from VideoPortInitialize()
  494. Note:
  495. In the event of a failure return, none of the fields are valid except for
  496. the return value and the pMoreChildren field.
  497. --*/
  498. {
  499. PHW_DEVICE_EXTENSION hwDeviceExtension = pHwDeviceExtension;
  500. ULONG Status;
  501. switch (ChildEnumInfo->ChildIndex) {
  502. case 0:
  503. //
  504. // Case 0 is used to enumerate devices found by the ACPI firmware.
  505. //
  506. // Since we do not support ACPI devices yet, we must return failure.
  507. //
  508. Status = ERROR_NO_MORE_DEVICES;
  509. break;
  510. case 1:
  511. //
  512. // This is the last device we enumerate. Tell the system we don't
  513. // have any more.
  514. //
  515. *pChildType = Monitor;
  516. //
  517. // Obtain the EDID structure via DDC.
  518. //
  519. if (GetDdcInformation(hwDeviceExtension,
  520. pChildDescriptor,
  521. ChildEnumInfo->ChildDescriptorSize))
  522. {
  523. *pHwId = QUERY_MONITOR_ID;
  524. VideoDebugPrint((1, "CirrusGetChildDescriptor - successfully read EDID structure\n"));
  525. } else {
  526. //
  527. // Alway return TRUE, since we always have a monitor output
  528. // on the card and it just may not be a detectable device.
  529. //
  530. *pHwId = QUERY_NONDDC_MONITOR_ID;
  531. VideoDebugPrint((1, "CirrusGetChildDescriptor - DDC not supported\n"));
  532. }
  533. Status = ERROR_MORE_DATA;
  534. break;
  535. case DISPLAY_ADAPTER_HW_ID:
  536. //
  537. // Special ID to handle return legacy PnP IDs for root enumerated
  538. // devices.
  539. //
  540. *pChildType = VideoChip;
  541. *pHwId = DISPLAY_ADAPTER_HW_ID;
  542. memcpy(pChildDescriptor, hwDeviceExtension->LegacyPnPId, 8*sizeof(WCHAR));
  543. Status = ERROR_MORE_DATA;
  544. break;
  545. default:
  546. Status = ERROR_NO_MORE_DEVICES;
  547. break;
  548. }
  549. return Status;
  550. }
  551. VP_STATUS
  552. CirrusGetPowerState(
  553. PHW_DEVICE_EXTENSION HwDeviceExtension,
  554. ULONG HwDeviceId,
  555. PVIDEO_POWER_MANAGEMENT VideoPowerManagement
  556. )
  557. /*++
  558. Routine Description:
  559. Returns power state information.
  560. Arguments:
  561. HwDeviceExtension - Pointer to our hardware device extension structure.
  562. HwDeviceId - Private unique 32 bit ID identifing the device.
  563. VideoPowerManagement - Power state information.
  564. Return Value:
  565. TRUE if power state can be set,
  566. FALSE otherwise.
  567. --*/
  568. {
  569. //
  570. // We only support power setting for the monitor. Make sure the
  571. // HwDeviceId matches one the the monitors we could report.
  572. //
  573. if ((HwDeviceId == QUERY_NONDDC_MONITOR_ID) ||
  574. (HwDeviceId == QUERY_MONITOR_ID)) {
  575. //
  576. // We are querying the power support for the monitor.
  577. //
  578. if ((VideoPowerManagement->PowerState == VideoPowerOn) ||
  579. (VideoPowerManagement->PowerState == VideoPowerHibernate)) {
  580. return NO_ERROR;
  581. }
  582. switch (VideoPowerManagement->PowerState) {
  583. case VideoPowerStandBy:
  584. return (HwDeviceExtension->PMCapability & VESA_POWER_STANDBY) ?
  585. NO_ERROR : ERROR_INVALID_FUNCTION;
  586. case VideoPowerSuspend:
  587. return (HwDeviceExtension->PMCapability & VESA_POWER_SUSPEND) ?
  588. NO_ERROR : ERROR_INVALID_FUNCTION;
  589. case VideoPowerOff:
  590. return (HwDeviceExtension->PMCapability & VESA_POWER_OFF) ?
  591. NO_ERROR : ERROR_INVALID_FUNCTION;
  592. default:
  593. break;
  594. }
  595. VideoDebugPrint((1, "This device does not support Power Management.\n"));
  596. return ERROR_INVALID_FUNCTION;
  597. } else if (HwDeviceId == DISPLAY_ADAPTER_HW_ID) {
  598. //
  599. // We are querying power support for the graphics card.
  600. //
  601. switch (VideoPowerManagement->PowerState) {
  602. case VideoPowerOn:
  603. case VideoPowerHibernate:
  604. case VideoPowerStandBy:
  605. return NO_ERROR;
  606. case VideoPowerOff:
  607. case VideoPowerSuspend:
  608. if ((HwDeviceExtension->ChipType & CL754x) ||
  609. (HwDeviceExtension->ChipType & CL755x) ||
  610. (HwDeviceExtension->ChipType & CL756x)) {
  611. //
  612. // We will allow the system to go into S3 sleep state
  613. // for machines with laptop chipsets. The system
  614. // bios will be responsible for re-posting on wake up.
  615. //
  616. return NO_ERROR;
  617. } else {
  618. //
  619. // Indicate that we can't do VideoPowerOff, because
  620. // we have no way of coming back when power is re-applied
  621. // to the card.
  622. //
  623. return ERROR_INVALID_FUNCTION;
  624. }
  625. default:
  626. ASSERT(FALSE);
  627. return ERROR_INVALID_FUNCTION;
  628. }
  629. } else {
  630. VideoDebugPrint((1, "Unknown HwDeviceId"));
  631. ASSERT(FALSE);
  632. return ERROR_INVALID_PARAMETER;
  633. }
  634. }
  635. VP_STATUS
  636. CirrusSetPowerState(
  637. PHW_DEVICE_EXTENSION HwDeviceExtension,
  638. ULONG HwDeviceId,
  639. PVIDEO_POWER_MANAGEMENT VideoPowerManagement
  640. )
  641. /*++
  642. Routine Description:
  643. Set the power state for a given device.
  644. Arguments:
  645. HwDeviceExtension - Pointer to our hardware device extension structure.
  646. HwDeviceId - Private unique 32 bit ID identifing the device.
  647. VideoPowerManagement - Power state information.
  648. Return Value:
  649. TRUE if power state can be set,
  650. FALSE otherwise.
  651. --*/
  652. {
  653. //
  654. // Make sure we recognize the device.
  655. //
  656. if ((HwDeviceId == QUERY_NONDDC_MONITOR_ID) ||
  657. (HwDeviceId == QUERY_MONITOR_ID)) {
  658. VIDEO_X86_BIOS_ARGUMENTS biosArguments;
  659. VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  660. biosArguments.Eax = VESA_POWER_FUNCTION;
  661. biosArguments.Ebx = VESA_SET_POWER_FUNC;
  662. switch (VideoPowerManagement->PowerState) {
  663. case VideoPowerOn:
  664. case VideoPowerHibernate:
  665. biosArguments.Ebx |= VESA_POWER_ON;
  666. break;
  667. case VideoPowerStandBy:
  668. biosArguments.Ebx |= VESA_POWER_STANDBY;
  669. break;
  670. case VideoPowerSuspend:
  671. biosArguments.Ebx |= VESA_POWER_SUSPEND;
  672. break;
  673. case VideoPowerOff:
  674. biosArguments.Ebx |= VESA_POWER_OFF;
  675. break;
  676. default:
  677. VideoDebugPrint((1, "Unknown power state.\n"));
  678. ASSERT(FALSE);
  679. return ERROR_INVALID_PARAMETER;
  680. }
  681. VideoPortInt10(HwDeviceExtension, &biosArguments);
  682. //
  683. // I have no idea why, but on some machines after a while
  684. // the Pixel Mask Register gets set to zero. Then when
  685. // we power back up, we can no longer see the screen. It is
  686. // black.
  687. //
  688. // By setting the register here, we can prevent this
  689. // problem. There should be no harmful side effects to
  690. // this.
  691. //
  692. if (VideoPowerManagement->PowerState == VideoPowerOn) {
  693. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  694. DAC_PIXEL_MASK_PORT, 0xff);
  695. }
  696. return NO_ERROR;
  697. } else if (HwDeviceId == DISPLAY_ADAPTER_HW_ID) {
  698. switch (VideoPowerManagement->PowerState) {
  699. case VideoPowerOn:
  700. case VideoPowerStandBy:
  701. case VideoPowerSuspend:
  702. case VideoPowerOff:
  703. case VideoPowerHibernate:
  704. return NO_ERROR;
  705. default:
  706. ASSERT(FALSE);
  707. return ERROR_INVALID_PARAMETER;
  708. }
  709. } else {
  710. VideoDebugPrint((1, "Unknown HwDeviceId"));
  711. ASSERT(FALSE);
  712. return ERROR_INVALID_PARAMETER;
  713. }
  714. }
  715. //---------------------------------------------------------------------------
  716. ULONG
  717. DriverEntry(
  718. PVOID Context1,
  719. PVOID Context2
  720. )
  721. /*++
  722. Routine Description:
  723. Installable driver initialization entry point.
  724. This entry point is called directly by the I/O system.
  725. Arguments:
  726. Context1 - First context value passed by the operating system. This is
  727. the value with which the miniport driver calls VideoPortInitialize().
  728. Context2 - Second context value passed by the operating system. This is
  729. the value with which the miniport driver calls 3VideoPortInitialize().
  730. Return Value:
  731. Status from VideoPortInitialize()
  732. --*/
  733. {
  734. VIDEO_HW_INITIALIZATION_DATA hwInitData;
  735. ULONG status;
  736. ULONG initializationStatus = (ULONG) -1;
  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 = VgaFindAdapter;
  749. hwInitData.HwInitialize = VgaInitialize;
  750. hwInitData.HwInterrupt = NULL;
  751. hwInitData.HwStartIO = VgaStartIO;
  752. #if (_WIN32_WINNT>= 0x0500)
  753. hwInitData.HwGetVideoChildDescriptor = CirrusGetChildDescriptor;
  754. hwInitData.HwGetPowerState = CirrusGetPowerState;
  755. hwInitData.HwSetPowerState = CirrusSetPowerState;
  756. hwInitData.HwLegacyResourceList = VgaAccessRange;
  757. hwInitData.HwLegacyResourceCount = 3;
  758. #endif
  759. //
  760. // Determine the size we require for the device extension.
  761. //
  762. hwInitData.HwDeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
  763. //
  764. // Always start with parameters for device0 in this case.
  765. // We can leave it like this since we know we will only ever find one
  766. // VGA type adapter in a machine.
  767. //
  768. // hwInitData.StartingDeviceNumber = 0;
  769. //
  770. // Once all the relevant information has been stored, call the video
  771. // port driver to do the initialization.
  772. // For this device we will repeat this call three times, for ISA, EISA
  773. // and PCI.
  774. // We will return the minimum of all return values.
  775. //
  776. //
  777. // We will try the PCI bus first so that our ISA detection does'nt claim
  778. // PCI cards (since it is impossible to differentiate between the two
  779. // by looking at the registers).
  780. //
  781. //
  782. // NOTE: since this driver only supports one adapter, we will return
  783. // as soon as we find a device, without going on to the following buses.
  784. // Normally one would call for each bus type and return the smallest
  785. // value.
  786. //
  787. hwInitData.AdapterInterfaceType = PCIBus;
  788. initializationStatus = VideoPortInitialize(Context1,
  789. Context2,
  790. &hwInitData,
  791. NULL);
  792. if (initializationStatus == NO_ERROR)
  793. {
  794. return initializationStatus;
  795. }
  796. hwInitData.AdapterInterfaceType = MicroChannel;
  797. initializationStatus = VideoPortInitialize(Context1,
  798. Context2,
  799. &hwInitData,
  800. NULL);
  801. //
  802. // Return immediately instead of checkin for smallest return code.
  803. //
  804. if (initializationStatus == NO_ERROR)
  805. {
  806. return initializationStatus;
  807. }
  808. hwInitData.AdapterInterfaceType = Isa;
  809. initializationStatus = VideoPortInitialize(Context1,
  810. Context2,
  811. &hwInitData,
  812. NULL);
  813. if (initializationStatus == NO_ERROR)
  814. {
  815. return initializationStatus;
  816. }
  817. hwInitData.AdapterInterfaceType = Eisa;
  818. initializationStatus = VideoPortInitialize(Context1,
  819. Context2,
  820. &hwInitData,
  821. NULL);
  822. if (initializationStatus == NO_ERROR)
  823. {
  824. return initializationStatus;
  825. }
  826. hwInitData.AdapterInterfaceType = Internal;
  827. status = VideoPortInitialize(Context1,
  828. Context2,
  829. &hwInitData,
  830. NULL);
  831. if (initializationStatus > status) {
  832. initializationStatus = status;
  833. }
  834. return initializationStatus;
  835. } // end DriverEntry()
  836. //---------------------------------------------------------------------------
  837. VP_STATUS
  838. VgaFindAdapter(
  839. PVOID HwDeviceExtension,
  840. PVOID HwContext,
  841. PWSTR ArgumentString,
  842. PVIDEO_PORT_CONFIG_INFO ConfigInfo,
  843. PUCHAR Again
  844. )
  845. /*++
  846. Routine Description:
  847. This routine is called to determine if the adapter for this driver
  848. is present in the system.
  849. If it is present, the function fills out some information describing
  850. the adapter.
  851. Arguments:
  852. HwDeviceExtension - Supplies the miniport driver's adapter storage. This
  853. storage is initialized to zero before this call.
  854. HwContext - Supplies the context value which was passed to
  855. VideoPortInitialize(). Must be NULL for PnP drivers.
  856. ArgumentString - Supplies a NULL terminated ASCII string. This string
  857. originates from the user.
  858. ConfigInfo - Returns the configuration information structure which is
  859. filled by the miniport driver. This structure is initialized with
  860. any known configuration information (such as SystemIoBusNumber) by
  861. the port driver. Where possible, drivers should have one set of
  862. defaults which do not require any supplied configuration information.
  863. Again - Indicates if the miniport driver wants the port driver to call
  864. its VIDEO_HW_FIND_ADAPTER function again with a new device extension
  865. and the same config info. This is used by the miniport drivers which
  866. can search for several adapters on a bus.
  867. Return Value:
  868. This routine must return:
  869. NO_ERROR - Indicates a host adapter was found and the
  870. configuration information was successfully determined.
  871. ERROR_INVALID_PARAMETER - Indicates an adapter was found but there was an
  872. error obtaining the configuration information. If possible an error
  873. should be logged.
  874. ERROR_DEV_NOT_EXIST - Indicates no host adapter was found for the
  875. supplied configuration information.
  876. --*/
  877. {
  878. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  879. VP_STATUS status;
  880. ULONG NumAccessRanges = NUM_VGA_ACCESS_RANGES;
  881. ULONG VESATimingBits ;
  882. VIDEO_ACCESS_RANGE AccessRangesTemp[5];
  883. //
  884. // if there are two cirrus cards and the one that is disabled is the second
  885. // one FindAdapter is called for, then we need to avoid writing to the global
  886. // VgaAccessRange. So make local copy of it
  887. //
  888. VideoPortMoveMemory((PUCHAR) AccessRangesTemp,
  889. (PUCHAR) VgaAccessRange,
  890. 5*sizeof(VIDEO_ACCESS_RANGE));
  891. //
  892. // Make sure the size of the structure is at least as large as what we
  893. // are expecting (check version of the config info structure).
  894. //
  895. if (ConfigInfo->Length < sizeof(VIDEO_PORT_CONFIG_INFO)) {
  896. return ERROR_INVALID_PARAMETER;
  897. }
  898. //
  899. // Store the bus type
  900. //
  901. hwDeviceExtension->BusType = ConfigInfo->AdapterInterfaceType;
  902. //
  903. // Assign pfnVideoPortReadXxx and pfnVideoPortWriteXxx
  904. //
  905. hwDeviceExtension->gPortRWfn.pfnVideoPortReadPortUchar = VideoPortReadPortUchar ;
  906. hwDeviceExtension->gPortRWfn.pfnVideoPortReadPortUshort = VideoPortReadPortUshort ;
  907. hwDeviceExtension->gPortRWfn.pfnVideoPortReadPortUlong = VideoPortReadPortUlong ;
  908. hwDeviceExtension->gPortRWfn.pfnVideoPortWritePortUchar = VideoPortWritePortUchar ;
  909. hwDeviceExtension->gPortRWfn.pfnVideoPortWritePortUshort = VideoPortWritePortUshort ;
  910. hwDeviceExtension->gPortRWfn.pfnVideoPortWritePortUlong = VideoPortWritePortUlong ;
  911. //
  912. // Detect the PCI card.
  913. //
  914. if (ConfigInfo->AdapterInterfaceType == PCIBus)
  915. {
  916. VideoDebugPrint((1, "Cirrus!VgaFindAdapter: "
  917. "ConfigInfo->AdapterInterfaceType == PCIBus\n"));//1
  918. if (!CirrusConfigurePCI(HwDeviceExtension,
  919. &NumAccessRanges,
  920. AccessRangesTemp))
  921. {
  922. VideoDebugPrint((1, "Failure Returned From CirrusConfigurePCI\n"));//1
  923. return ERROR_DEV_NOT_EXIST;
  924. }
  925. }
  926. else
  927. {
  928. VideoDebugPrint((1, "Cirrus!VgaFindAdapter: "
  929. "ConfigInfo->AdapterInterfaceType != PCIBus\n"));//1
  930. }
  931. //
  932. // No interrupt information is necessary.
  933. //
  934. if (AccessRangesTemp[3].RangeLength == 0)
  935. {
  936. //
  937. // The last access range (range[3]) is the access range for
  938. // the linear frame buffer. If this access range has a
  939. // range length of 0, then some HAL's will fail the request.
  940. // Therefore, if we are not using the last access range,
  941. // I'll not try to reserve it.
  942. //
  943. NumAccessRanges--;
  944. }
  945. //
  946. // Check to see if there is a hardware resource conflict.
  947. // (or if card is disabled)
  948. //
  949. status = VideoPortVerifyAccessRanges(HwDeviceExtension,
  950. NumAccessRanges,
  951. AccessRangesTemp);
  952. if (status != NO_ERROR) {
  953. VideoDebugPrint((1, "ERROR: VPVerifyAccessRanges failed!\n"));
  954. return status;
  955. }
  956. //
  957. // VideoPortVerifyAccessRanges will fail for a card that is disabled.
  958. // This card is not disabled. We can write to the global VgaAccessRange
  959. //
  960. VideoPortMoveMemory((PUCHAR) VgaAccessRange,
  961. (PUCHAR) AccessRangesTemp,
  962. NumAccessRanges*sizeof(VIDEO_ACCESS_RANGE));
  963. //
  964. // Get logical IO port addresses.
  965. //
  966. if (hwDeviceExtension->bMMAddress)
  967. {
  968. if ((hwDeviceExtension->IOAddress =
  969. VideoPortGetDeviceBase(hwDeviceExtension,
  970. VgaAccessRange[4].RangeStart,
  971. VGA_MAX_IO_PORT - VGA_END_BREAK_PORT + 1,
  972. VgaAccessRange[4].RangeInIoSpace)) == NULL)
  973. {
  974. VideoDebugPrint((2, "VgaFindAdapter - Fail to get io address\n"));
  975. return ERROR_INVALID_PARAMETER;
  976. }
  977. hwDeviceExtension->IOAddress -= VGA_END_BREAK_PORT;
  978. }
  979. else
  980. {
  981. if ((hwDeviceExtension->IOAddress =
  982. VideoPortGetDeviceBase(hwDeviceExtension,
  983. VgaAccessRange->RangeStart,
  984. VGA_MAX_IO_PORT - VGA_BASE_IO_PORT + 1,
  985. VgaAccessRange->RangeInIoSpace)) == NULL)
  986. {
  987. VideoDebugPrint((2, "VgaFindAdapter - Fail to get io address\n"));
  988. return ERROR_INVALID_PARAMETER;
  989. }
  990. hwDeviceExtension->IOAddress -= VGA_BASE_IO_PORT;
  991. }
  992. //
  993. // Determine whether a VGA is present.
  994. //
  995. if (!VgaIsPresent(hwDeviceExtension)) {
  996. VideoDebugPrint((1, "CirrusFindAdapter - VGA Failed\n"));
  997. return ERROR_DEV_NOT_EXIST;
  998. }
  999. //
  1000. // Minimum size of the buffer required to store the hardware state
  1001. // information returned by IOCTL_VIDEO_SAVE_HARDWARE_STATE.
  1002. //
  1003. ConfigInfo->HardwareStateSize = VGA_TOTAL_STATE_SIZE;
  1004. //
  1005. // now that we have the video memory address in protected mode, lets do
  1006. // the required video card initialization. We will try to detect a Cirrus
  1007. // Logic chipset...
  1008. //
  1009. //
  1010. // Determine whether an CL6410/6420/542x/543x is present.
  1011. //
  1012. //
  1013. // CirrusLogicIsPresent may set up the
  1014. // hwDeviceExtesion->AdapterMemorySize field. Set it
  1015. // to 0 now, so I can compare against this later to
  1016. // see if CirrusLogicIsPresent assigned a value.
  1017. //
  1018. hwDeviceExtension->AdapterMemorySize = 0;
  1019. if (!CirrusLogicIsPresent(hwDeviceExtension))
  1020. {
  1021. VideoDebugPrint((1, "CirrusFindAdapter - Failed\n"));
  1022. return ERROR_DEV_NOT_EXIST;
  1023. }
  1024. //
  1025. // Pass a pointer to the emulator range we are using.
  1026. //
  1027. ConfigInfo->NumEmulatorAccessEntries = VGA_NUM_EMULATOR_ACCESS_ENTRIES;
  1028. ConfigInfo->EmulatorAccessEntries = VgaEmulatorAccessEntries;
  1029. ConfigInfo->EmulatorAccessEntriesContext = (ULONG_PTR) hwDeviceExtension;
  1030. //
  1031. // There is really no reason to have the frame buffer mapped. On an
  1032. // x86 we use if for save/restore (supposedly) but even then we
  1033. // would only need to map a 64K window, not all 16 Meg!
  1034. //
  1035. #ifdef _X86_
  1036. //
  1037. // Map the video memory into the system virtual address space so we can
  1038. // clear it out and use it for save and restore.
  1039. //
  1040. if ( (hwDeviceExtension->VideoMemoryAddress =
  1041. VideoPortGetDeviceBase(hwDeviceExtension,
  1042. VgaAccessRange[2].RangeStart,
  1043. VgaAccessRange[2].RangeLength,
  1044. FALSE)) == NULL)
  1045. {
  1046. VideoDebugPrint((1, "VgaFindAdapter - Fail to get memory address\n"));
  1047. return ERROR_INVALID_PARAMETER;
  1048. }
  1049. #endif
  1050. //
  1051. // Size the memory
  1052. //
  1053. //
  1054. // The size may have been set up in detection code, so
  1055. // don't destroy if already set.
  1056. //
  1057. if( hwDeviceExtension->AdapterMemorySize == 0 )
  1058. {
  1059. hwDeviceExtension->AdapterMemorySize =
  1060. CirrusFindVmemSize(hwDeviceExtension);
  1061. }
  1062. //
  1063. // Write hardware info into registry
  1064. //
  1065. WriteRegistryInfo(hwDeviceExtension);
  1066. ConfigInfo->VdmPhysicalVideoMemoryAddress.LowPart = MEM_VGA;
  1067. ConfigInfo->VdmPhysicalVideoMemoryLength = MEM_VGA_SIZE;
  1068. ConfigInfo->VdmPhysicalVideoMemoryAddress.HighPart = 0x00000000;
  1069. #if 0
  1070. // removed the following call. This fixes MS bug #163251
  1071. //#if DDC2B
  1072. //
  1073. // Check DDC2B monitor, get EDID table.
  1074. // Turn on/off extended modes according the properties of the monitor.
  1075. //
  1076. // The miniport takes forever to load doing DDC on an
  1077. // ISA 5434 in a DELL XPS P120c.
  1078. // (IDEKIyama Vision Master 17 Monitor).
  1079. //
  1080. // Let only try to get DDC info on PCI cards for now.
  1081. // CIRRUS - Can you fix this?
  1082. if (ConfigInfo->AdapterInterfaceType == PCIBus) {
  1083. ReadVESATiming ( hwDeviceExtension ) ;
  1084. }
  1085. #endif
  1086. //
  1087. // Determines which modes are valid.
  1088. //
  1089. #if DDC2B
  1090. CirrusValidateModes(hwDeviceExtension);
  1091. #endif
  1092. #if (_WIN32_WINNT <= 0x0400)
  1093. CheckAndUpdateDDC2BMonitor(hwDeviceExtension);
  1094. #endif (_WIN32_WINNT <= 0x0400)
  1095. if (hwDeviceExtension->NumAvailableModes == 0)
  1096. {
  1097. VideoDebugPrint((1, "FindAdapter failed because there are no"
  1098. "available modes.\n"));
  1099. return ERROR_INVALID_PARAMETER;
  1100. }
  1101. //
  1102. // Fix the 5446Ac and 440FX core logic coexist bug.
  1103. //
  1104. if (hwDeviceExtension->ChipType == CL5446)
  1105. {
  1106. CirrusUpdate440FX(hwDeviceExtension);
  1107. }
  1108. //
  1109. // Once modes are validated, all 543x's are the same (the number
  1110. // of modes available is the only difference).
  1111. //
  1112. #if 0
  1113. //myf31: for RadiSYS special driver, change MCLK to 66MHz
  1114. if (hwDeviceExtension->ChipType == CL7555)
  1115. {
  1116. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  1117. SEQ_ADDRESS_PORT, 0x1F);
  1118. SR1F = VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
  1119. SEQ_DATA_PORT) & 0xC0;
  1120. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  1121. SEQ_DATA_PORT, (SR1F | 0x25));
  1122. }
  1123. //myf31 end
  1124. #endif
  1125. if ((hwDeviceExtension->ChipType == CL5434) ||
  1126. (hwDeviceExtension->ChipType == CL5434_6) ||
  1127. (hwDeviceExtension->ChipType == CL5436) ||
  1128. (hwDeviceExtension->ChipType == CL5446) ||
  1129. (hwDeviceExtension->ChipType == CL5446BE) ||
  1130. (hwDeviceExtension->ChipType == CL5480))
  1131. {
  1132. hwDeviceExtension->ChipType = CL543x;
  1133. }
  1134. //
  1135. // Indicate we do not wish to be called again for another initialization.
  1136. //
  1137. *Again = 0;
  1138. //
  1139. // Indicate a successful completion status.
  1140. //
  1141. return NO_ERROR;
  1142. }
  1143. //---------------------------------------------------------------------------
  1144. BOOLEAN
  1145. VgaInitialize(
  1146. PVOID HwDeviceExtension
  1147. )
  1148. /*++
  1149. Routine Description:
  1150. This routine does one time initialization of the device.
  1151. Arguments:
  1152. HwDeviceExtension - Pointer to the miniport driver's adapter information.
  1153. Return Value:
  1154. None.
  1155. --*/
  1156. {
  1157. VP_STATUS status;
  1158. VIDEO_X86_BIOS_ARGUMENTS biosArguments;
  1159. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  1160. //
  1161. // Get the BIOS version number.
  1162. //
  1163. VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  1164. biosArguments.Eax = 0x1200;
  1165. biosArguments.Ebx = 0x81;
  1166. status = VideoPortInt10(HwDeviceExtension, &biosArguments);
  1167. if (status == NO_ERROR)
  1168. {
  1169. hwDeviceExtension->ulBIOSVersionNumber = biosArguments.Eax;
  1170. }
  1171. else
  1172. hwDeviceExtension->ulBIOSVersionNumber = 0;
  1173. hwDeviceExtension->bBlockSwitch = 0;
  1174. biosArguments.Eax = 0x1200;
  1175. biosArguments.Ebx = 0x9A;
  1176. status = VideoPortInt10(HwDeviceExtension, &biosArguments);
  1177. hwDeviceExtension->bDisplaytype = CRT_type;
  1178. if (status == NO_ERROR)
  1179. {
  1180. if (!(biosArguments.Eax & 0x0100))
  1181. hwDeviceExtension->bDisplaytype = LCD_type;
  1182. else if (!(biosArguments.Ebx & 0x0200))
  1183. hwDeviceExtension->bDisplaytype = SIM_type;
  1184. }
  1185. VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  1186. biosArguments.Eax = VESA_POWER_FUNCTION;
  1187. biosArguments.Ebx = VESA_GET_POWER_FUNC;
  1188. status = VideoPortInt10(HwDeviceExtension, &biosArguments);
  1189. if ((status == NO_ERROR) &&
  1190. ((biosArguments.Eax & 0xffff) == VESA_STATUS_SUCCESS))
  1191. {
  1192. hwDeviceExtension->PMCapability = biosArguments.Ebx;
  1193. }
  1194. else
  1195. {
  1196. hwDeviceExtension->PMCapability = 0;
  1197. }
  1198. //
  1199. // set up the default cursor position and type.
  1200. //
  1201. hwDeviceExtension->CursorPosition.Column = 0;
  1202. hwDeviceExtension->CursorPosition.Row = 0;
  1203. hwDeviceExtension->CursorTopScanLine = 0;
  1204. hwDeviceExtension->CursorBottomScanLine = 31;
  1205. hwDeviceExtension->CursorEnable = TRUE;
  1206. return TRUE;
  1207. }
  1208. //---------------------------------------------------------------------------
  1209. BOOLEAN
  1210. VgaStartIO(
  1211. PVOID pHwDeviceExtension,
  1212. PVIDEO_REQUEST_PACKET RequestPacket
  1213. )
  1214. /*++
  1215. Routine Description:
  1216. This routine is the main execution routine for the miniport driver. It
  1217. accepts a Video Request Packet, performs the request, and then returns
  1218. with the appropriate status.
  1219. Arguments:
  1220. HwDeviceExtension - Pointer to the miniport driver's adapter information.
  1221. RequestPacket - Pointer to the video request packet. This structure
  1222. contains all the parameters passed to the VideoIoControl function.
  1223. Return Value:
  1224. This routine will return error codes from the various support routines
  1225. and will also return ERROR_INSUFFICIENT_BUFFER for incorrectly sized
  1226. buffers and ERROR_INVALID_FUNCTION for unsupported functions.
  1227. --*/
  1228. {
  1229. PHW_DEVICE_EXTENSION hwDeviceExtension = pHwDeviceExtension;
  1230. PHW_DEVICE_EXTENSION HwDeviceExtension = pHwDeviceExtension;
  1231. VP_STATUS status;
  1232. VIDEO_MODE videoMode;
  1233. PVIDEO_MEMORY_INFORMATION memoryInformation;
  1234. ULONG inIoSpace;
  1235. ULONG physicalFrameLength;
  1236. PVIDEO_SHARE_MEMORY pShareMemory;
  1237. PVIDEO_SHARE_MEMORY_INFORMATION pShareMemoryInformation;
  1238. PHYSICAL_ADDRESS shareAddress;
  1239. PVOID virtualAddress;
  1240. ULONG sharedViewSize;
  1241. UCHAR SR0A;
  1242. //
  1243. // Switch on the IoContolCode in the RequestPacket. It indicates which
  1244. // function must be performed by the driver.
  1245. //
  1246. switch (RequestPacket->IoControlCode)
  1247. {
  1248. case IOCTL_VIDEO_SHARE_VIDEO_MEMORY:
  1249. VideoDebugPrint((2, "VgaStartIO - ShareVideoMemory\n"));
  1250. if ((RequestPacket->OutputBufferLength < sizeof(VIDEO_SHARE_MEMORY_INFORMATION)) ||
  1251. (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) )
  1252. {
  1253. VideoDebugPrint((1, "VgaStartIO - ShareVideoMemory - ERROR_INSUFFICIENT_BUFFER\n"));
  1254. status = ERROR_INSUFFICIENT_BUFFER;
  1255. break;
  1256. }
  1257. pShareMemory = RequestPacket->InputBuffer;
  1258. RequestPacket->StatusBlock->Information =
  1259. sizeof(VIDEO_SHARE_MEMORY_INFORMATION);
  1260. //
  1261. // Beware: the input buffer and the output buffer are the same
  1262. // buffer, and therefore data should not be copied from one to the
  1263. // other
  1264. //
  1265. virtualAddress = pShareMemory->ProcessHandle;
  1266. sharedViewSize = pShareMemory->ViewSize;
  1267. //
  1268. // If you change to using a dense space frame buffer, make this
  1269. // value a 4 for the ALPHA.
  1270. //
  1271. inIoSpace = 0;
  1272. //
  1273. // NOTE: we are ignoring ViewOffset
  1274. //
  1275. shareAddress.QuadPart =
  1276. hwDeviceExtension->PhysicalFrameOffset.QuadPart +
  1277. hwDeviceExtension->PhysicalVideoMemoryBase.QuadPart;
  1278. if (hwDeviceExtension->LinearMode)
  1279. {
  1280. //
  1281. // Add P6CACHE support
  1282. //
  1283. #if P6CACHE
  1284. #if (_WIN32_WINNT >= 0x0400)
  1285. inIoSpace |= VIDEO_MEMORY_SPACE_P6CACHE;
  1286. #endif
  1287. #endif
  1288. status = VideoPortMapMemory(hwDeviceExtension,
  1289. shareAddress,
  1290. &sharedViewSize,
  1291. &inIoSpace,
  1292. &virtualAddress);
  1293. }
  1294. else
  1295. {
  1296. ULONG ulBankSize;
  1297. VOID (*pfnBank)(ULONG,ULONG,PVOID);
  1298. switch (hwDeviceExtension->ChipType) {
  1299. case CL542x: pfnBank = vBankMap_CL542x;
  1300. break;
  1301. case CL543x: pfnBank = vBankMap_CL543x;
  1302. break;
  1303. default: pfnBank = vBankMap_CL64xx;
  1304. break;
  1305. };
  1306. #if ONE_64K_BANK
  1307. //
  1308. // The Cirrus Logic VGA's support one 64K read/write bank.
  1309. //
  1310. ulBankSize = 0x10000; // 64K bank start adjustment
  1311. #endif
  1312. #if TWO_32K_BANKS
  1313. //
  1314. // The Cirrus Logic VGA's support two 32K read/write banks.
  1315. //
  1316. ulBankSize = 0x8000; // 32K bank start adjustment
  1317. #endif
  1318. status = VideoPortMapBankedMemory(hwDeviceExtension,
  1319. shareAddress,
  1320. &sharedViewSize,
  1321. &inIoSpace,
  1322. &virtualAddress,
  1323. ulBankSize,
  1324. FALSE,
  1325. pfnBank,
  1326. (PVOID)hwDeviceExtension);
  1327. }
  1328. pShareMemoryInformation = RequestPacket->OutputBuffer;
  1329. pShareMemoryInformation->SharedViewOffset = pShareMemory->ViewOffset;
  1330. pShareMemoryInformation->VirtualAddress = virtualAddress;
  1331. pShareMemoryInformation->SharedViewSize = sharedViewSize;
  1332. break;
  1333. case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY:
  1334. VideoDebugPrint((2, "VgaStartIO - UnshareVideoMemory\n"));
  1335. if (RequestPacket->InputBufferLength < sizeof(VIDEO_SHARE_MEMORY)) {
  1336. status = ERROR_INSUFFICIENT_BUFFER;
  1337. break;
  1338. }
  1339. pShareMemory = RequestPacket->InputBuffer;
  1340. status = VideoPortUnmapMemory(hwDeviceExtension,
  1341. pShareMemory->RequestedVirtualAddress,
  1342. pShareMemory->ProcessHandle);
  1343. break;
  1344. case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
  1345. VideoDebugPrint((2, "VgaStartIO - MapVideoMemory\n"));
  1346. if ((RequestPacket->OutputBufferLength <
  1347. (RequestPacket->StatusBlock->Information =
  1348. sizeof(VIDEO_MEMORY_INFORMATION))) ||
  1349. (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) )
  1350. {
  1351. status = ERROR_INSUFFICIENT_BUFFER;
  1352. }
  1353. memoryInformation = RequestPacket->OutputBuffer;
  1354. memoryInformation->VideoRamBase = ((PVIDEO_MEMORY)
  1355. (RequestPacket->InputBuffer))->RequestedVirtualAddress;
  1356. //
  1357. // We reserved 16 meg for the frame buffer, however, it makes
  1358. // no sense to map more memory than there is on the card. So
  1359. // only map the amount of memory we have on the card.
  1360. //
  1361. memoryInformation->VideoRamLength =
  1362. hwDeviceExtension->AdapterMemorySize;
  1363. //
  1364. // If you change to using a dense space frame buffer, make this
  1365. // value a 4 for the ALPHA.
  1366. //
  1367. inIoSpace = 0;
  1368. //
  1369. // Add P6CACHE support
  1370. //
  1371. physicalFrameLength = hwDeviceExtension->PhysicalVideoMemoryLength;
  1372. #if P6CACHE
  1373. #if (_WIN32_WINNT >= 0x0400)
  1374. //
  1375. // We saw corrupted screen in 16 color mode on 54M40 if P6CAHCHE
  1376. // is enabled. We only turn on P6CACHE when we see two access
  1377. // ranges (so that we know this request is from cirrus.dll but
  1378. // not from vga.dll)
  1379. //
  1380. if (RequestPacket->OutputBufferLength >= // if we have room for
  1381. sizeof(VIDEO_MEMORY_INFORMATION) * 2) // another access range
  1382. {
  1383. inIoSpace |= VIDEO_MEMORY_SPACE_P6CACHE;
  1384. if ( physicalFrameLength < 0x00400000)
  1385. {
  1386. physicalFrameLength = 0x00400000;
  1387. }
  1388. }
  1389. #endif
  1390. #endif
  1391. status = VideoPortMapMemory(hwDeviceExtension,
  1392. hwDeviceExtension->PhysicalVideoMemoryBase,
  1393. &physicalFrameLength,
  1394. &inIoSpace,
  1395. &(memoryInformation->VideoRamBase));
  1396. if (status != NO_ERROR) {
  1397. VideoDebugPrint((1, "VgaStartIO - IOCTL_VIDEO_MAP_VIDEO_MEMORY failed VideoPortMapMemory (%x)\n", status));
  1398. break;
  1399. }
  1400. memoryInformation->FrameBufferBase =
  1401. ((PUCHAR) (memoryInformation->VideoRamBase)) +
  1402. hwDeviceExtension->PhysicalFrameOffset.LowPart;
  1403. memoryInformation->FrameBufferLength =
  1404. hwDeviceExtension->PhysicalFrameLength ?
  1405. hwDeviceExtension->PhysicalFrameLength :
  1406. memoryInformation->VideoRamLength;
  1407. VideoDebugPrint((2, "physical VideoMemoryBase %08lx\n", hwDeviceExtension->PhysicalVideoMemoryBase));
  1408. VideoDebugPrint((2, "physical VideoMemoryLength %08lx\n", hwDeviceExtension->PhysicalVideoMemoryLength));
  1409. VideoDebugPrint((2, "VideoMemoryBase %08lx\n", memoryInformation->VideoRamBase));
  1410. VideoDebugPrint((2, "VideoMemoryLength %08lx\n", memoryInformation->VideoRamLength));
  1411. VideoDebugPrint((2, "physical framebuf offset %08lx\n", hwDeviceExtension->PhysicalFrameOffset.LowPart));
  1412. VideoDebugPrint((2, "framebuf base %08lx\n", memoryInformation->FrameBufferBase));
  1413. VideoDebugPrint((2, "physical framebuf len %08lx\n", hwDeviceExtension->PhysicalFrameLength));
  1414. VideoDebugPrint((2, "framebuf length %08lx\n", memoryInformation->FrameBufferLength));
  1415. //
  1416. // add address mapping for system to screen blt
  1417. //
  1418. if (RequestPacket->OutputBufferLength >= // if we have room for
  1419. sizeof(VIDEO_MEMORY_INFORMATION) * 2) // another access range
  1420. {
  1421. RequestPacket->StatusBlock->Information =
  1422. sizeof(VIDEO_MEMORY_INFORMATION) * 2;
  1423. memoryInformation++;
  1424. memoryInformation->VideoRamBase = (PVOID)NULL;
  1425. if (hwDeviceExtension->bSecondAperture)
  1426. {
  1427. //
  1428. // We reserved 16 meg for the frame buffer, however, it makes
  1429. // no sense to map more memory than there is on the card. So
  1430. // only map the amount of memory we have on the card.
  1431. //
  1432. memoryInformation->VideoRamLength =
  1433. hwDeviceExtension->AdapterMemorySize;
  1434. //
  1435. // If you change to using a dense space frame buffer, make this
  1436. // value a 4 for the ALPHA.
  1437. //
  1438. inIoSpace = 0;
  1439. //
  1440. // Add P6CACHE support
  1441. //
  1442. #if P6CACHE
  1443. #if (_WIN32_WINNT >= 0x0400)
  1444. inIoSpace |= VIDEO_MEMORY_SPACE_P6CACHE;
  1445. #endif
  1446. #endif
  1447. shareAddress.QuadPart =
  1448. hwDeviceExtension->PhysicalVideoMemoryBase.QuadPart +
  1449. 0x1000000; // add 16M offset
  1450. status = VideoPortMapMemory(hwDeviceExtension,
  1451. shareAddress,
  1452. &physicalFrameLength,
  1453. &inIoSpace,
  1454. &(memoryInformation->VideoRamBase));
  1455. if (status != NO_ERROR)
  1456. {
  1457. VideoDebugPrint((1, "VgaStartIO - IOCTL_VIDEO_MAP_VIDEO_MEMORY failed for system to screen blt mapping (%x)\n", status));
  1458. }
  1459. }
  1460. }
  1461. break;
  1462. case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
  1463. VideoDebugPrint((2, "VgaStartIO - UnMapVideoMemory\n"));
  1464. if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))
  1465. {
  1466. status = ERROR_INSUFFICIENT_BUFFER;
  1467. }
  1468. status = VideoPortUnmapMemory(hwDeviceExtension,
  1469. ((PVIDEO_MEMORY)
  1470. (RequestPacket->InputBuffer))->
  1471. RequestedVirtualAddress,
  1472. 0);
  1473. break;
  1474. case IOCTL_VIDEO_QUERY_AVAIL_MODES:
  1475. VideoDebugPrint((2, "VgaStartIO - QueryAvailableModes\n"));
  1476. RequestPacket->StatusBlock->Information = 0;
  1477. status = VgaQueryAvailableModes(HwDeviceExtension,
  1478. (PVIDEO_MODE_INFORMATION)
  1479. RequestPacket->OutputBuffer,
  1480. RequestPacket->OutputBufferLength,
  1481. (PULONG)&RequestPacket->StatusBlock->Information);
  1482. break;
  1483. case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
  1484. VideoDebugPrint((2, "VgaStartIO - QueryNumAvailableModes\n"));
  1485. RequestPacket->StatusBlock->Information = 0;
  1486. status = VgaQueryNumberOfAvailableModes(HwDeviceExtension,
  1487. (PVIDEO_NUM_MODES)
  1488. RequestPacket->OutputBuffer,
  1489. RequestPacket->OutputBufferLength,
  1490. (PULONG)&RequestPacket->StatusBlock->Information);
  1491. break;
  1492. case IOCTL_VIDEO_QUERY_CURRENT_MODE:
  1493. VideoDebugPrint((2, "VgaStartIO - QueryCurrentMode\n"));
  1494. RequestPacket->StatusBlock->Information = 0;
  1495. status = VgaQueryCurrentMode(HwDeviceExtension,
  1496. (PVIDEO_MODE_INFORMATION) RequestPacket->OutputBuffer,
  1497. RequestPacket->OutputBufferLength,
  1498. (PULONG)&RequestPacket->StatusBlock->Information);
  1499. break;
  1500. case IOCTL_VIDEO_SET_CURRENT_MODE:
  1501. VideoDebugPrint((2, "VgaStartIO - SetCurrentModes\n"));
  1502. status = VgaSetMode(HwDeviceExtension,
  1503. (PVIDEO_MODE) RequestPacket->InputBuffer,
  1504. RequestPacket->InputBufferLength);
  1505. break;
  1506. case IOCTL_VIDEO_RESET_DEVICE:
  1507. VideoDebugPrint((2, "VgaStartIO - Reset Device\n"));
  1508. videoMode.RequestedMode = DEFAULT_MODE;
  1509. VgaSetMode(HwDeviceExtension,
  1510. (PVIDEO_MODE) &videoMode,
  1511. sizeof(videoMode));
  1512. //
  1513. // Always return succcess since settings the text mode will fail on
  1514. // non-x86.
  1515. //
  1516. // Also, failiure to set the text mode is not fatal in any way, since
  1517. // this operation must be followed by another set mode operation.
  1518. //
  1519. status = NO_ERROR;
  1520. break;
  1521. case IOCTL_VIDEO_LOAD_AND_SET_FONT:
  1522. VideoDebugPrint((2, "VgaStartIO - LoadAndSetFont\n"));
  1523. status = VgaLoadAndSetFont(HwDeviceExtension,
  1524. (PVIDEO_LOAD_FONT_INFORMATION) RequestPacket->InputBuffer,
  1525. RequestPacket->InputBufferLength);
  1526. break;
  1527. case IOCTL_VIDEO_QUERY_CURSOR_POSITION:
  1528. VideoDebugPrint((2, "VgaStartIO - QueryCursorPosition\n"));
  1529. RequestPacket->StatusBlock->Information = 0;
  1530. status = VgaQueryCursorPosition(HwDeviceExtension,
  1531. (PVIDEO_CURSOR_POSITION) RequestPacket->OutputBuffer,
  1532. RequestPacket->OutputBufferLength,
  1533. (PULONG)&RequestPacket->StatusBlock->Information);
  1534. break;
  1535. case IOCTL_VIDEO_SET_CURSOR_POSITION:
  1536. VideoDebugPrint((2, "VgaStartIO - SetCursorPosition\n"));
  1537. status = VgaSetCursorPosition(HwDeviceExtension,
  1538. (PVIDEO_CURSOR_POSITION)
  1539. RequestPacket->InputBuffer,
  1540. RequestPacket->InputBufferLength);
  1541. break;
  1542. case IOCTL_VIDEO_QUERY_CURSOR_ATTR:
  1543. VideoDebugPrint((2, "VgaStartIO - QueryCursorAttributes\n"));
  1544. RequestPacket->StatusBlock->Information = 0;
  1545. status = VgaQueryCursorAttributes(HwDeviceExtension,
  1546. (PVIDEO_CURSOR_ATTRIBUTES) RequestPacket->OutputBuffer,
  1547. RequestPacket->OutputBufferLength,
  1548. (PULONG)&RequestPacket->StatusBlock->Information);
  1549. break;
  1550. case IOCTL_VIDEO_SET_CURSOR_ATTR:
  1551. VideoDebugPrint((2, "VgaStartIO - SetCursorAttributes\n"));
  1552. status = VgaSetCursorAttributes(HwDeviceExtension,
  1553. (PVIDEO_CURSOR_ATTRIBUTES) RequestPacket->InputBuffer,
  1554. RequestPacket->InputBufferLength);
  1555. break;
  1556. case IOCTL_VIDEO_SET_PALETTE_REGISTERS:
  1557. VideoDebugPrint((2, "VgaStartIO - SetPaletteRegs\n"));
  1558. status = VgaSetPaletteReg(HwDeviceExtension,
  1559. (PVIDEO_PALETTE_DATA) RequestPacket->InputBuffer,
  1560. RequestPacket->InputBufferLength);
  1561. break;
  1562. case IOCTL_VIDEO_SET_COLOR_REGISTERS:
  1563. VideoDebugPrint((2, "VgaStartIO - SetColorRegs\n"));
  1564. status = VgaSetColorLookup(HwDeviceExtension,
  1565. (PVIDEO_CLUT) RequestPacket->InputBuffer,
  1566. RequestPacket->InputBufferLength);
  1567. break;
  1568. case IOCTL_VIDEO_ENABLE_VDM:
  1569. VideoDebugPrint((2, "VgaStartIO - EnableVDM\n"));
  1570. hwDeviceExtension->TrappedValidatorCount = 0;
  1571. hwDeviceExtension->SequencerAddressValue = 0;
  1572. hwDeviceExtension->CurrentNumVdmAccessRanges =
  1573. NUM_MINIMAL_VGA_VALIDATOR_ACCESS_RANGE;
  1574. hwDeviceExtension->CurrentVdmAccessRange =
  1575. MinimalVgaValidatorAccessRange;
  1576. VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
  1577. hwDeviceExtension->CurrentNumVdmAccessRanges,
  1578. hwDeviceExtension->CurrentVdmAccessRange);
  1579. status = NO_ERROR;
  1580. break;
  1581. case IOCTL_VIDEO_RESTORE_HARDWARE_STATE:
  1582. VideoDebugPrint((2, "VgaStartIO - RestoreHardwareState\n"));
  1583. try {
  1584. status = VgaRestoreHardwareState(HwDeviceExtension,
  1585. (PVIDEO_HARDWARE_STATE) RequestPacket->InputBuffer,
  1586. RequestPacket->InputBufferLength);
  1587. } except (1) {
  1588. status = ERROR_INVALID_PARAMETER;
  1589. }
  1590. break;
  1591. case IOCTL_VIDEO_SAVE_HARDWARE_STATE:
  1592. VideoDebugPrint((2, "VgaStartIO - SaveHardwareState\n"));
  1593. try {
  1594. RequestPacket->StatusBlock->Information = 0;
  1595. status = VgaSaveHardwareState(HwDeviceExtension,
  1596. (PVIDEO_HARDWARE_STATE) RequestPacket->OutputBuffer,
  1597. RequestPacket->OutputBufferLength,
  1598. (PULONG)&RequestPacket->StatusBlock->Information);
  1599. } except (1) {
  1600. status = ERROR_INVALID_PARAMETER;
  1601. }
  1602. break;
  1603. case IOCTL_VIDEO_GET_BANK_SELECT_CODE:
  1604. VideoDebugPrint((2, "VgaStartIO - GetBankSelectCode\n"));
  1605. RequestPacket->StatusBlock->Information = 0;
  1606. status = VgaGetBankSelectCode(HwDeviceExtension,
  1607. (PVIDEO_BANK_SELECT) RequestPacket->OutputBuffer,
  1608. RequestPacket->OutputBufferLength,
  1609. (PULONG)&RequestPacket->StatusBlock->Information);
  1610. VideoDebugPrint((2, "VgaStartIO - END GetBankSelectCode\n"));
  1611. break;
  1612. case IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES:
  1613. {
  1614. PVIDEO_PUBLIC_ACCESS_RANGES portAccess;
  1615. PHYSICAL_ADDRESS physicalPortAddress;
  1616. ULONG physicalPortLength;
  1617. if (RequestPacket->OutputBufferLength <
  1618. sizeof(VIDEO_PUBLIC_ACCESS_RANGES))
  1619. {
  1620. status = ERROR_INSUFFICIENT_BUFFER;
  1621. break;
  1622. }
  1623. RequestPacket->StatusBlock->Information =
  1624. sizeof(VIDEO_PUBLIC_ACCESS_RANGES);
  1625. portAccess = RequestPacket->OutputBuffer;
  1626. //
  1627. // The first public access range is the IO ports.
  1628. //
  1629. //
  1630. // On the alpha, VGA.DLL will call into the cirrus miniport
  1631. // trying to get a pointer to the IO ports. So, we can never
  1632. // return MMIO to the VGA driver. We'll assume that if the
  1633. // size of the OutputBuffer is only big enough for one access
  1634. // range then the VGA driver is asking for the ranges, and
  1635. // thus we should map them as IO space.
  1636. //
  1637. if ((hwDeviceExtension->bMMAddress) &&
  1638. (RequestPacket->OutputBufferLength >=
  1639. sizeof(VIDEO_PUBLIC_ACCESS_RANGES) * 2))
  1640. {
  1641. // PC97 Compliant
  1642. portAccess->VirtualAddress = (PVOID) NULL;
  1643. portAccess->InIoSpace = FALSE;
  1644. portAccess->MappedInIoSpace = portAccess->InIoSpace;
  1645. // for VGA register
  1646. physicalPortLength = VGA_MAX_IO_PORT - VGA_END_BREAK_PORT + 1;
  1647. status = VideoPortMapMemory(hwDeviceExtension,
  1648. VgaAccessRange[4].RangeStart,
  1649. &physicalPortLength,
  1650. &(portAccess->MappedInIoSpace),
  1651. &(portAccess->VirtualAddress));
  1652. (PUCHAR)portAccess->VirtualAddress -= VGA_END_BREAK_PORT;
  1653. VideoDebugPrint((1, "VgaStartIO - memory mapping to (%x)\n", portAccess->VirtualAddress));
  1654. if (status == NO_ERROR)
  1655. {
  1656. RequestPacket->StatusBlock->Information =
  1657. sizeof(VIDEO_PUBLIC_ACCESS_RANGES) * 2;
  1658. portAccess++;
  1659. //
  1660. // map a region for memory mapped IO
  1661. //
  1662. portAccess->VirtualAddress = (PVOID) NULL; // Requested VA
  1663. portAccess->InIoSpace = FALSE;
  1664. portAccess->MappedInIoSpace = portAccess->InIoSpace;
  1665. // MMIO register
  1666. physicalPortAddress = VgaAccessRange[4].RangeStart;
  1667. physicalPortAddress.QuadPart += RELOCATABLE_MEMORY_MAPPED_IO_OFFSET;
  1668. physicalPortLength = 0x100;
  1669. status = VideoPortMapMemory(hwDeviceExtension,
  1670. physicalPortAddress,
  1671. &physicalPortLength,
  1672. &(portAccess->MappedInIoSpace),
  1673. &(portAccess->VirtualAddress));
  1674. VideoDebugPrint((1, "The base MMIO address is: %x\n",
  1675. portAccess->VirtualAddress));
  1676. }
  1677. }
  1678. else
  1679. {
  1680. portAccess->VirtualAddress = (PVOID) NULL;
  1681. portAccess->InIoSpace = TRUE;
  1682. portAccess->MappedInIoSpace = portAccess->InIoSpace;
  1683. physicalPortLength = VGA_MAX_IO_PORT - VGA_BASE_IO_PORT + 1;
  1684. status = VideoPortMapMemory(hwDeviceExtension,
  1685. VgaAccessRange->RangeStart,
  1686. &physicalPortLength,
  1687. &(portAccess->MappedInIoSpace),
  1688. &(portAccess->VirtualAddress));
  1689. (PUCHAR)portAccess->VirtualAddress -= VGA_BASE_IO_PORT;
  1690. VideoDebugPrint((1, "VgaStartIO - mapping ports to (%x)\n", portAccess->VirtualAddress));
  1691. if ((status == NO_ERROR) &&
  1692. (RequestPacket->OutputBufferLength >= // if we have room for
  1693. sizeof(VIDEO_PUBLIC_ACCESS_RANGES) * 2)) // another access range
  1694. {
  1695. RequestPacket->StatusBlock->Information =
  1696. sizeof(VIDEO_PUBLIC_ACCESS_RANGES) * 2;
  1697. portAccess++;
  1698. //
  1699. // If we are running on a chip which supports Memory Mapped
  1700. // IO, then return a pointer to the MMIO Ports. Otherwise,
  1701. // return zero to indicate we do not support memory mapped IO.
  1702. //
  1703. if (((hwDeviceExtension->ChipType == CL543x) ||
  1704. (hwDeviceExtension->ChipType & CL755x)) && //myf15
  1705. (hwDeviceExtension->BusType != Isa) &&
  1706. (VideoPortGetDeviceData(hwDeviceExtension,
  1707. VpMachineData,
  1708. &CirrusGetDeviceDataCallback,
  1709. NULL) != NO_ERROR))
  1710. {
  1711. //
  1712. // map a region for memory mapped IO
  1713. //
  1714. // memory mapped IO is located in physical addresses B8000
  1715. // to BFFFF, but we will only touch the first 256 bytes.
  1716. //
  1717. portAccess->VirtualAddress = (PVOID) NULL; // Requested VA
  1718. portAccess->InIoSpace = FALSE;
  1719. portAccess->MappedInIoSpace = portAccess->InIoSpace;
  1720. physicalPortAddress = VgaAccessRange[2].RangeStart;
  1721. physicalPortAddress.QuadPart += MEMORY_MAPPED_IO_OFFSET;
  1722. physicalPortLength = 0x100;
  1723. status = VideoPortMapMemory(hwDeviceExtension,
  1724. physicalPortAddress,
  1725. &physicalPortLength,
  1726. &(portAccess->MappedInIoSpace),
  1727. &(portAccess->VirtualAddress));
  1728. VideoDebugPrint((1, "The base MMIO address is: %x\n",
  1729. portAccess->VirtualAddress));
  1730. }
  1731. else
  1732. {
  1733. portAccess->VirtualAddress = 0;
  1734. }
  1735. }
  1736. }
  1737. }
  1738. break;
  1739. case IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES:
  1740. if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))
  1741. {
  1742. status = ERROR_INSUFFICIENT_BUFFER;
  1743. break;
  1744. }
  1745. //
  1746. // We decrement VGA_BASE_IO_PORT before we hand this out,
  1747. // so we should increment before we try to free it.
  1748. //
  1749. (PUCHAR)((PVIDEO_MEMORY)RequestPacket->InputBuffer)->
  1750. RequestedVirtualAddress += VGA_BASE_IO_PORT;
  1751. status = VideoPortUnmapMemory(hwDeviceExtension,
  1752. ((PVIDEO_MEMORY)
  1753. (RequestPacket->InputBuffer))->
  1754. RequestedVirtualAddress,
  1755. 0);
  1756. break;
  1757. case IOCTL_CIRRUS_GET_GAMMA_FACTOR:
  1758. VideoDebugPrint((2, "VgaStartIO - GetGammaFactor\n"));
  1759. RequestPacket->StatusBlock->Information = 0;
  1760. status = VgaGetGammaFactor(hwDeviceExtension,
  1761. (PGAMMA_VALUE) RequestPacket->OutputBuffer,
  1762. RequestPacket->OutputBufferLength,
  1763. (PULONG)&RequestPacket->StatusBlock->Information);
  1764. break ;
  1765. case IOCTL_CIRRUS_GET_CONTRAST_FACTOR:
  1766. VideoDebugPrint((2, "VgaStartIO - GetContrastFactor\n"));
  1767. RequestPacket->StatusBlock->Information = 0;
  1768. status = VgaGetContrastFactor(hwDeviceExtension,
  1769. (PCONTRAST_VALUE) RequestPacket->OutputBuffer,
  1770. RequestPacket->OutputBufferLength,
  1771. (PULONG)&RequestPacket->StatusBlock->Information);
  1772. break ;
  1773. case IOCTL_CIRRUS_GET_CAPABILITIES:
  1774. VideoDebugPrint((2, "VgaStartIO - CirrusGetCapabilities\n"));
  1775. RequestPacket->StatusBlock->Information = 0;
  1776. status = VgaQueryAvailableModes(HwDeviceExtension,
  1777. (PVIDEO_MODE_INFORMATION)
  1778. RequestPacket->OutputBuffer,
  1779. RequestPacket->OutputBufferLength,
  1780. (PULONG)&RequestPacket->StatusBlock->Information);
  1781. break;
  1782. case IOCTL_CIRRUS_SET_DISPLAY_PITCH:
  1783. VideoDebugPrint((2, "VgaStartIO - CirrusSetDisplayPitch\n"));
  1784. status = VgaSetMode(HwDeviceExtension,
  1785. (PVIDEO_MODE) RequestPacket->InputBuffer,
  1786. RequestPacket->InputBufferLength);
  1787. break;
  1788. //
  1789. // if we get here, an invalid IoControlCode was specified.
  1790. //
  1791. default:
  1792. VideoDebugPrint((1, "Fell through vga startIO routine - invalid command\n"));
  1793. status = ERROR_INVALID_FUNCTION;
  1794. break;
  1795. }
  1796. RequestPacket->StatusBlock->Status = status;
  1797. return TRUE;
  1798. }
  1799. //---------------------------------------------------------------------------
  1800. VOID
  1801. CirrusHwTimer(
  1802. PVOID pHwDeviceExtension
  1803. )
  1804. /*++
  1805. Routine Description:
  1806. This routine is the main execution routine for the miniport driver. It
  1807. accepts a Video Request Packet, performs the request, and then returns
  1808. with the appropriate status.
  1809. Arguments:
  1810. HwDeviceExtension - Pointer to the miniport driver's HwVidTimer
  1811. information.
  1812. Return Value:
  1813. This routine will return error codes from the various support routines
  1814. and will also return ERROR_INSUFFICIENT_BUFFER for incorrectly sized
  1815. buffers and ERROR_INVALID_FUNCTION for unsupported functions.
  1816. --*/
  1817. {
  1818. PHW_DEVICE_EXTENSION hwDeviceExtension = pHwDeviceExtension;
  1819. PHW_DEVICE_EXTENSION HwDeviceExtension = pHwDeviceExtension;
  1820. VIDEO_MODE videoMode;
  1821. UCHAR SR0A, SR14, savSEQidx, savCRTidx, lcd;
  1822. SHORT Displaytype;
  1823. ULONG ulCRTCAddress, ulCRTCData;
  1824. if (VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
  1825. MISC_OUTPUT_REG_READ_PORT) & 0x01)
  1826. {
  1827. ulCRTCAddress = CRTC_ADDRESS_PORT_COLOR;
  1828. ulCRTCData = CRTC_DATA_PORT_COLOR;
  1829. }
  1830. else
  1831. {
  1832. ulCRTCAddress = CRTC_ADDRESS_PORT_MONO;
  1833. ulCRTCData = CRTC_DATA_PORT_MONO;
  1834. }
  1835. if (!(hwDeviceExtension->bBlockSwitch)) //not block switch
  1836. {
  1837. savSEQidx = VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
  1838. SEQ_ADDRESS_PORT);
  1839. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  1840. SEQ_ADDRESS_PORT, 0x14);
  1841. SR14 = VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
  1842. SEQ_DATA_PORT);
  1843. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  1844. SEQ_DATA_PORT, (UCHAR)(SR14 | 0x04));
  1845. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  1846. SEQ_ADDRESS_PORT, 0x0A);
  1847. SR0A = VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
  1848. SEQ_DATA_PORT);
  1849. Displaytype = ((SR14 & 0x02) | (SR0A & 0x01));
  1850. if (Displaytype == 0)
  1851. Displaytype = LCD_type;
  1852. else if (Displaytype == 1)
  1853. Displaytype = CRT_type;
  1854. else if (Displaytype == 3)
  1855. Displaytype = SIM_type;
  1856. VideoDebugPrint((1, "CirrusHwTimer :\n"
  1857. "\tPreDisplaytype: %d, Currenttype :%d\n",
  1858. hwDeviceExtension->bDisplaytype,
  1859. Displaytype));
  1860. VideoDebugPrint((1, "CirrusHwTimer :\n"
  1861. "\tCurrentMode: %x\n",
  1862. hwDeviceExtension->bCurrentMode));
  1863. if (hwDeviceExtension->bDisplaytype != Displaytype)
  1864. {
  1865. hwDeviceExtension->bDisplaytype = Displaytype;
  1866. savCRTidx = VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
  1867. ulCRTCAddress);
  1868. if (hwDeviceExtension->ChipType & CL754x)
  1869. {
  1870. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  1871. ulCRTCAddress, 0x20);
  1872. lcd = VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
  1873. ulCRTCData);
  1874. if (Displaytype == LCD_type)
  1875. {
  1876. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  1877. ulCRTCData, (UCHAR)((lcd & 0x9F) | 0x20));
  1878. }
  1879. else if (Displaytype == CRT_type)
  1880. {
  1881. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  1882. ulCRTCData, (UCHAR)((lcd & 0x9F)| 0x40));
  1883. }
  1884. else if (Displaytype == SIM_type)
  1885. {
  1886. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  1887. ulCRTCData, (UCHAR)((lcd & 0x9F)| 0x60));
  1888. }
  1889. }
  1890. else if (hwDeviceExtension->ChipType & CL755x)
  1891. {
  1892. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  1893. ulCRTCAddress, 0x80);
  1894. lcd = VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
  1895. ulCRTCData);
  1896. if (Displaytype == LCD_type)
  1897. {
  1898. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  1899. ulCRTCData, (UCHAR)((lcd & 0xFC) | 0x01));
  1900. }
  1901. else if (Displaytype == CRT_type)
  1902. {
  1903. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  1904. ulCRTCData, (UCHAR)((lcd & 0xFC)| 0x02));
  1905. }
  1906. else if (Displaytype == SIM_type)
  1907. {
  1908. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  1909. ulCRTCData, (UCHAR)((lcd & 0xFC)| 0x03));
  1910. }
  1911. }
  1912. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  1913. ulCRTCAddress, savCRTidx);
  1914. }
  1915. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  1916. SEQ_ADDRESS_PORT, 0x14);
  1917. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  1918. SEQ_DATA_PORT, (UCHAR)(SR14 & 0xFB));
  1919. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  1920. SEQ_ADDRESS_PORT, savSEQidx);
  1921. }
  1922. }
  1923. //---------------------------------------------------------------------------
  1924. //
  1925. // private routines
  1926. //
  1927. VP_STATUS
  1928. VgaLoadAndSetFont(
  1929. PHW_DEVICE_EXTENSION HwDeviceExtension,
  1930. PVIDEO_LOAD_FONT_INFORMATION FontInformation,
  1931. ULONG FontInformationSize
  1932. )
  1933. /*++
  1934. Routine Description:
  1935. Takes a buffer containing a user-defined font and loads it into the
  1936. VGA soft font memory and programs the VGA to the appropriate character
  1937. cell size.
  1938. Arguments:
  1939. HwDeviceExtension - Pointer to the miniport driver's device extension.
  1940. FontInformation - Pointer to the structure containing the information
  1941. about the loadable ROM font to be set.
  1942. FontInformationSize - Length of the input buffer supplied by the user.
  1943. Return Value:
  1944. NO_ERROR - information returned successfully
  1945. ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data.
  1946. ERROR_INVALID_PARAMETER - invalid video mode
  1947. --*/
  1948. {
  1949. PUCHAR destination;
  1950. PUCHAR source;
  1951. USHORT width;
  1952. ULONG i;
  1953. ULONG ulCRTCAddress, ulCRTCData;
  1954. //
  1955. // check if a mode has been set
  1956. //
  1957. if (HwDeviceExtension->CurrentMode == NULL) {
  1958. return ERROR_INVALID_FUNCTION;
  1959. }
  1960. //
  1961. // Text mode only; If we are in a graphics mode, return an error
  1962. //
  1963. if (HwDeviceExtension->CurrentMode->fbType & VIDEO_MODE_GRAPHICS) {
  1964. return ERROR_INVALID_PARAMETER;
  1965. }
  1966. //
  1967. // Check if the size of the data in the input buffer is large enough
  1968. // and that it contains all the data.
  1969. //
  1970. if ( (FontInformationSize < sizeof(VIDEO_LOAD_FONT_INFORMATION)) ||
  1971. (FontInformationSize < sizeof(VIDEO_LOAD_FONT_INFORMATION) +
  1972. sizeof(UCHAR) * (FontInformation->FontSize - 1)) )
  1973. {
  1974. return ERROR_INSUFFICIENT_BUFFER;
  1975. }
  1976. //
  1977. // Check for the width and height of the font
  1978. //
  1979. if ( ((FontInformation->WidthInPixels != 8) &&
  1980. (FontInformation->WidthInPixels != 9)) ||
  1981. (FontInformation->HeightInPixels > 32) ) {
  1982. return ERROR_INVALID_PARAMETER;
  1983. }
  1984. //
  1985. // Check the size of the font buffer is the right size for the size
  1986. // font being passed down.
  1987. //
  1988. if (FontInformation->FontSize < FontInformation->HeightInPixels * 256 *
  1989. sizeof(UCHAR) ) {
  1990. return ERROR_INSUFFICIENT_BUFFER;
  1991. }
  1992. //
  1993. // Since the font parameters are valid, store the parameters in the
  1994. // device extension and load the font.
  1995. //
  1996. HwDeviceExtension->FontPelRows = FontInformation->HeightInPixels;
  1997. HwDeviceExtension->FontPelColumns = FontInformation->WidthInPixels;
  1998. HwDeviceExtension->CurrentMode->row =
  1999. HwDeviceExtension->CurrentMode->vres / HwDeviceExtension->FontPelRows;
  2000. width =
  2001. HwDeviceExtension->CurrentMode->hres / HwDeviceExtension->FontPelColumns;
  2002. if (width < (USHORT)HwDeviceExtension->CurrentMode->col) {
  2003. HwDeviceExtension->CurrentMode->col = width;
  2004. }
  2005. source = &(FontInformation->Font[0]);
  2006. //
  2007. // Set up the destination and source pointers for the font
  2008. //
  2009. destination = (PUCHAR)HwDeviceExtension->VideoMemoryAddress;
  2010. //
  2011. // Map font buffer at A0000
  2012. //
  2013. VgaInterpretCmdStream(HwDeviceExtension, EnableA000Data);
  2014. //
  2015. // Move the font to its destination
  2016. //
  2017. for (i = 1; i <= 256; i++) {
  2018. VideoPortWriteRegisterBufferUchar(destination,
  2019. source,
  2020. FontInformation->HeightInPixels);
  2021. destination += 32;
  2022. source += FontInformation->HeightInPixels;
  2023. }
  2024. VgaInterpretCmdStream(HwDeviceExtension, DisableA000Color);
  2025. //
  2026. // Restore to a text mode.
  2027. //
  2028. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2029. MISC_OUTPUT_REG_READ_PORT) & 0x01)
  2030. {
  2031. ulCRTCAddress = CRTC_ADDRESS_PORT_COLOR;
  2032. ulCRTCData = CRTC_DATA_PORT_COLOR;
  2033. }
  2034. else
  2035. {
  2036. ulCRTCAddress = CRTC_ADDRESS_PORT_MONO;
  2037. ulCRTCData = CRTC_DATA_PORT_MONO;
  2038. }
  2039. //
  2040. // Set Height of font.
  2041. //
  2042. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ulCRTCAddress, 0x09);
  2043. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ulCRTCData,
  2044. (UCHAR)(FontInformation->HeightInPixels - 1));
  2045. //
  2046. // Set Width of font.
  2047. //
  2048. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ulCRTCAddress, 0x12);
  2049. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ulCRTCData,
  2050. (UCHAR)(((USHORT)FontInformation->HeightInPixels *
  2051. (USHORT)HwDeviceExtension->CurrentMode->row) - 1));
  2052. i = HwDeviceExtension->CurrentMode->vres /
  2053. HwDeviceExtension->CurrentMode->row;
  2054. //
  2055. // Set Cursor End
  2056. //
  2057. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ulCRTCAddress, 0x0B);
  2058. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ulCRTCData,
  2059. (UCHAR)--i);
  2060. //
  2061. // Set Cursor Start
  2062. //
  2063. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ulCRTCAddress, 0x0A);
  2064. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ulCRTCData,
  2065. (UCHAR)--i);
  2066. return NO_ERROR;
  2067. } //end VgaLoadAndSetFont()
  2068. //---------------------------------------------------------------------------
  2069. VP_STATUS
  2070. VgaQueryCursorPosition(
  2071. PHW_DEVICE_EXTENSION HwDeviceExtension,
  2072. PVIDEO_CURSOR_POSITION CursorPosition,
  2073. ULONG CursorPositionSize,
  2074. PULONG OutputSize
  2075. )
  2076. /*++
  2077. Routine Description:
  2078. This routine returns the row and column of the cursor.
  2079. Arguments:
  2080. HwDeviceExtension - Pointer to the miniport driver's device extension.
  2081. CursorPosition - Pointer to the output buffer supplied by the user. This
  2082. is where the cursor position is stored.
  2083. CursorPositionSize - Length of the output buffer supplied by the user.
  2084. OutputSize - Pointer to a buffer in which to return the actual size of
  2085. the data in the buffer. If the buffer was not large enough, this
  2086. contains the minimum required buffer size.
  2087. Return Value:
  2088. NO_ERROR - information returned successfully
  2089. ERROR_INSUFFICIENT_BUFFER - output buffer not large enough to return
  2090. any useful data
  2091. ERROR_INVALID_PARAMETER - invalid video mode
  2092. --*/
  2093. {
  2094. //
  2095. // check if a mode has been set
  2096. //
  2097. if (HwDeviceExtension->CurrentMode == NULL) {
  2098. return ERROR_INVALID_FUNCTION;
  2099. }
  2100. //
  2101. // Text mode only; If we are in a graphics mode, return an error
  2102. //
  2103. if (HwDeviceExtension->CurrentMode->fbType & VIDEO_MODE_GRAPHICS) {
  2104. *OutputSize = 0;
  2105. return ERROR_INVALID_PARAMETER;
  2106. }
  2107. //
  2108. // If the buffer passed in is not large enough return an
  2109. // appropriate error code.
  2110. //
  2111. if (CursorPositionSize < (*OutputSize = sizeof(VIDEO_CURSOR_POSITION)) ) {
  2112. *OutputSize = 0;
  2113. return ERROR_INSUFFICIENT_BUFFER;
  2114. }
  2115. //
  2116. // Store the postition of the cursor into the buffer.
  2117. //
  2118. CursorPosition->Column = HwDeviceExtension->CursorPosition.Column;
  2119. CursorPosition->Row = HwDeviceExtension->CursorPosition.Row;
  2120. return NO_ERROR;
  2121. } // end VgaQueryCursorPosition()
  2122. //---------------------------------------------------------------------------
  2123. VP_STATUS
  2124. VgaSetCursorPosition(
  2125. PHW_DEVICE_EXTENSION HwDeviceExtension,
  2126. PVIDEO_CURSOR_POSITION CursorPosition,
  2127. ULONG CursorPositionSize
  2128. )
  2129. /*++
  2130. Routine Description:
  2131. This routine verifies that the requested cursor position is within
  2132. the row and column bounds of the current mode and font. If valid, then
  2133. it sets the row and column of the cursor.
  2134. Arguments:
  2135. HwDeviceExtension - Pointer to the miniport driver's device extension.
  2136. CursorPosition - Pointer to the structure containing the cursor position.
  2137. CursorPositionSize - Length of the input buffer supplied by the user.
  2138. Return Value:
  2139. NO_ERROR - information returned successfully
  2140. ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data
  2141. ERROR_INVALID_PARAMETER - invalid video mode
  2142. --*/
  2143. {
  2144. USHORT position;
  2145. ULONG ulCRTCAddress, ulCRTCData;
  2146. //
  2147. // check if a mode has been set
  2148. //
  2149. if (HwDeviceExtension->CurrentMode == NULL) {
  2150. return ERROR_INVALID_FUNCTION;
  2151. }
  2152. //
  2153. // Text mode only; If we are in a graphics mode, return an error
  2154. //
  2155. if (HwDeviceExtension->CurrentMode->fbType & VIDEO_MODE_GRAPHICS) {
  2156. return ERROR_INVALID_PARAMETER;
  2157. }
  2158. //
  2159. // Check if the size of the data in the input buffer is large enough.
  2160. //
  2161. if (CursorPositionSize < sizeof(VIDEO_CURSOR_POSITION)) {
  2162. return ERROR_INSUFFICIENT_BUFFER;
  2163. }
  2164. //
  2165. // Check if the new values for the cursor positions are in the valid
  2166. // bounds for the screen.
  2167. //
  2168. if ((CursorPosition->Column >= HwDeviceExtension->CurrentMode->col) ||
  2169. (CursorPosition->Row >= HwDeviceExtension->CurrentMode->row)) {
  2170. return ERROR_INVALID_PARAMETER;
  2171. }
  2172. //
  2173. // Store these new values in the device extension so we can use them in
  2174. // a QUERY.
  2175. //
  2176. HwDeviceExtension->CursorPosition.Column = CursorPosition->Column;
  2177. HwDeviceExtension->CursorPosition.Row = CursorPosition->Row;
  2178. //
  2179. // Calculate the position on the screen at which the cursor must be
  2180. // be displayed
  2181. //
  2182. position = (USHORT) (HwDeviceExtension->CurrentMode->col *
  2183. CursorPosition->Row + CursorPosition->Column);
  2184. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2185. MISC_OUTPUT_REG_READ_PORT) & 0x01)
  2186. {
  2187. ulCRTCAddress = CRTC_ADDRESS_PORT_COLOR;
  2188. ulCRTCData = CRTC_DATA_PORT_COLOR;
  2189. }
  2190. else
  2191. {
  2192. ulCRTCAddress = CRTC_ADDRESS_PORT_MONO;
  2193. ulCRTCData = CRTC_DATA_PORT_MONO;
  2194. }
  2195. //
  2196. // Address Cursor Location Low Register in CRT Controller Registers
  2197. //
  2198. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ulCRTCAddress,
  2199. IND_CURSOR_LOW_LOC);
  2200. //
  2201. // Set Cursor Location Low Register
  2202. //
  2203. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ulCRTCData,
  2204. (UCHAR) (position & 0x00FF));
  2205. //
  2206. // Address Cursor Location High Register in CRT Controller Registers
  2207. //
  2208. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ulCRTCAddress,
  2209. IND_CURSOR_HIGH_LOC);
  2210. //
  2211. // Set Cursor Location High Register
  2212. //
  2213. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ulCRTCData,
  2214. (UCHAR) (position >> 8));
  2215. return NO_ERROR;
  2216. } // end VgaSetCursorPosition()
  2217. //---------------------------------------------------------------------------
  2218. VP_STATUS
  2219. VgaQueryCursorAttributes(
  2220. PHW_DEVICE_EXTENSION HwDeviceExtension,
  2221. PVIDEO_CURSOR_ATTRIBUTES CursorAttributes,
  2222. ULONG CursorAttributesSize,
  2223. PULONG OutputSize
  2224. )
  2225. /*++
  2226. Routine Description:
  2227. This routine returns information about the height and visibility of the
  2228. cursor.
  2229. Arguments:
  2230. HwDeviceExtension - Pointer to the miniport driver's device extension.
  2231. CursorAttributes - Pointer to the output buffer supplied by the user.
  2232. This is where the cursor type is stored.
  2233. CursorAttributesSize - Length of the output buffer supplied by the user.
  2234. OutputSize - Pointer to a buffer in which to return the actual size of
  2235. the data in the buffer. If the buffer was not large enough, this
  2236. contains the minimum required buffer size.
  2237. Return Value:
  2238. NO_ERROR - information returned successfully
  2239. ERROR_INSUFFICIENT_BUFFER - output buffer not large enough to return
  2240. any useful data
  2241. ERROR_INVALID_PARAMETER - invalid video mode
  2242. --*/
  2243. {
  2244. //
  2245. // check if a mode has been set
  2246. //
  2247. if (HwDeviceExtension->CurrentMode == NULL) {
  2248. return ERROR_INVALID_FUNCTION;
  2249. }
  2250. //
  2251. // Text mode only; If we are in a graphics mode, return an error
  2252. //
  2253. if (HwDeviceExtension->CurrentMode->fbType & VIDEO_MODE_GRAPHICS) {
  2254. *OutputSize = 0;
  2255. return ERROR_INVALID_PARAMETER;
  2256. }
  2257. //
  2258. // Find out the size of the data to be put in the the buffer and return
  2259. // that in the status information (whether or not the information is
  2260. // there). If the buffer passed in is not large enough return an
  2261. // appropriate error code.
  2262. //
  2263. if (CursorAttributesSize < (*OutputSize =
  2264. sizeof(VIDEO_CURSOR_ATTRIBUTES)) ) {
  2265. *OutputSize = 0;
  2266. return ERROR_INSUFFICIENT_BUFFER;
  2267. }
  2268. //
  2269. // Store the cursor information into the buffer.
  2270. //
  2271. CursorAttributes->Height = (USHORT) HwDeviceExtension->CursorTopScanLine;
  2272. CursorAttributes->Width = (USHORT) HwDeviceExtension->CursorBottomScanLine;
  2273. if (HwDeviceExtension->cursor_vert_exp_flag)
  2274. CursorAttributes->Enable = FALSE;
  2275. else
  2276. CursorAttributes->Enable = TRUE;
  2277. CursorAttributes->Enable = HwDeviceExtension->CursorEnable;
  2278. return NO_ERROR;
  2279. } // end VgaQueryCursorAttributes()
  2280. //---------------------------------------------------------------------------
  2281. VP_STATUS
  2282. VgaSetCursorAttributes(
  2283. PHW_DEVICE_EXTENSION HwDeviceExtension,
  2284. PVIDEO_CURSOR_ATTRIBUTES CursorAttributes,
  2285. ULONG CursorAttributesSize
  2286. )
  2287. /*++
  2288. Routine Description:
  2289. This routine verifies that the requested cursor height is within the
  2290. bounds of the character cell. If valid, then it sets the new
  2291. visibility and height of the cursor.
  2292. Arguments:
  2293. HwDeviceExtension - Pointer to the miniport driver's device extension.
  2294. CursorType - Pointer to the structure containing the cursor information.
  2295. CursorTypeSize - Length of the input buffer supplied by the user.
  2296. Return Value:
  2297. NO_ERROR - information returned successfully
  2298. ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data
  2299. ERROR_INVALID_PARAMETER - invalid video mode
  2300. --*/
  2301. {
  2302. UCHAR cursorLine;
  2303. ULONG ulCRTCAddress, ulCRTCData;
  2304. //
  2305. // check if a mode has been set
  2306. //
  2307. if (HwDeviceExtension->CurrentMode == NULL) {
  2308. return ERROR_INVALID_FUNCTION;
  2309. }
  2310. //
  2311. // Text mode only; If we are in a graphics mode, return an error
  2312. //
  2313. if (HwDeviceExtension->CurrentMode->fbType & VIDEO_MODE_GRAPHICS) {
  2314. return ERROR_INVALID_PARAMETER;
  2315. }
  2316. //
  2317. // Check if the size of the data in the input buffer is large enough.
  2318. //
  2319. if (CursorAttributesSize < sizeof(VIDEO_CURSOR_ATTRIBUTES)) {
  2320. return ERROR_INSUFFICIENT_BUFFER;
  2321. }
  2322. //
  2323. // Check if the new values for the cursor type are in the valid range.
  2324. //
  2325. if ((CursorAttributes->Height >= HwDeviceExtension->FontPelRows) ||
  2326. (CursorAttributes->Width > 31)) {
  2327. return ERROR_INVALID_PARAMETER;
  2328. }
  2329. //
  2330. // Store the cursor information in the device extension so we can use
  2331. // them in a QUERY.
  2332. //
  2333. HwDeviceExtension->CursorTopScanLine = (UCHAR) CursorAttributes->Height;
  2334. HwDeviceExtension->CursorBottomScanLine = (UCHAR) CursorAttributes->Width;
  2335. HwDeviceExtension->CursorEnable = CursorAttributes->Enable;
  2336. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2337. MISC_OUTPUT_REG_READ_PORT) & 0x01)
  2338. {
  2339. ulCRTCAddress = CRTC_ADDRESS_PORT_COLOR;
  2340. ulCRTCData = CRTC_DATA_PORT_COLOR;
  2341. }
  2342. else
  2343. {
  2344. ulCRTCAddress = CRTC_ADDRESS_PORT_MONO;
  2345. ulCRTCData = CRTC_DATA_PORT_MONO;
  2346. }
  2347. //
  2348. // Address Cursor Start Register in CRT Controller Registers
  2349. //
  2350. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ulCRTCAddress,
  2351. IND_CURSOR_START);
  2352. //
  2353. // Set Cursor Start Register by writting to CRTCtl Data Register
  2354. // Preserve the high three bits of this register.
  2355. //
  2356. // Only the Five low bits are used for the cursor height.
  2357. // Bit 5 is cursor enable, bit 6 and 7 preserved.
  2358. //
  2359. cursorLine = (UCHAR) CursorAttributes->Height & 0x1F;
  2360. cursorLine |= VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2361. ulCRTCData) & 0xC0;
  2362. if (!CursorAttributes->Enable) {
  2363. cursorLine |= 0x20; // Flip cursor off bit
  2364. }
  2365. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ulCRTCData,
  2366. cursorLine);
  2367. //
  2368. // Address Cursor End Register in CRT Controller Registers
  2369. //
  2370. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ulCRTCAddress,
  2371. IND_CURSOR_END);
  2372. //
  2373. // Set Cursor End Register. Preserve the high three bits of this
  2374. // register.
  2375. //
  2376. cursorLine =
  2377. (CursorAttributes->Width < (USHORT)(HwDeviceExtension->FontPelRows - 1)) ?
  2378. CursorAttributes->Width : (HwDeviceExtension->FontPelRows - 1);
  2379. cursorLine &= 0x1f;
  2380. cursorLine |= VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2381. ulCRTCData) & 0xE0;
  2382. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ulCRTCData,
  2383. cursorLine);
  2384. return NO_ERROR;
  2385. } // end VgaSetCursorAttributes()
  2386. //---------------------------------------------------------------------------
  2387. BOOLEAN
  2388. VgaIsPresent(
  2389. PHW_DEVICE_EXTENSION HwDeviceExtension
  2390. )
  2391. /*++
  2392. Routine Description:
  2393. This routine returns TRUE if a VGA is present. Determining whether a VGA
  2394. is present is a two-step process. First, this routine walks bits through
  2395. the Bit Mask register, to establish that there are readable indexed
  2396. registers (EGAs normally don't have readable registers, and other adapters
  2397. are unlikely to have indexed registers). This test is done first because
  2398. it's a non-destructive EGA rejection test (correctly rejects EGAs, but
  2399. doesn't potentially mess up the screen or the accessibility of display
  2400. memory). Normally, this would be an adequate test, but some EGAs have
  2401. readable registers, so next, we check for the existence of the Chain4 bit
  2402. in the Memory Mode register; this bit doesn't exist in EGAs. It's
  2403. conceivable that there are EGAs with readable registers and a register bit
  2404. where Chain4 is stored, although I don't know of any; if a better test yet
  2405. is needed, memory could be written to in Chain4 mode, and then examined
  2406. plane by plane in non-Chain4 mode to make sure the Chain4 bit did what it's
  2407. supposed to do. However, the current test should be adequate to eliminate
  2408. just about all EGAs, and 100% of everything else.
  2409. If this function fails to find a VGA, it attempts to undo any damage it
  2410. may have inadvertently done while testing. The underlying assumption for
  2411. the damage control is that if there's any non-VGA adapter at the tested
  2412. ports, it's an EGA or an enhanced EGA, because: a) I don't know of any
  2413. other adapters that use 3C4/5 or 3CE/F, and b), if there are other
  2414. adapters, I certainly don't know how to restore their original states. So
  2415. all error recovery is oriented toward putting an EGA back in a writable
  2416. state, so that error messages are visible. The EGA's state on entry is
  2417. assumed to be text mode, so the Memory Mode register is restored to the
  2418. default state for text mode.
  2419. If a VGA is found, the VGA is returned to its original state after
  2420. testing is finished.
  2421. Arguments:
  2422. None.
  2423. Return Value:
  2424. TRUE if a VGA is present, FALSE if not.
  2425. --*/
  2426. {
  2427. UCHAR originalGCAddr;
  2428. UCHAR originalSCAddr;
  2429. UCHAR originalBitMask;
  2430. UCHAR originalReadMap;
  2431. UCHAR originalMemoryMode;
  2432. UCHAR testMask;
  2433. BOOLEAN returnStatus;
  2434. //
  2435. // Remember the original state of the Graphics Controller Address register.
  2436. //
  2437. originalGCAddr = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2438. GRAPH_ADDRESS_PORT);
  2439. //
  2440. // Write the Read Map register with a known state so we can verify
  2441. // that it isn't changed after we fool with the Bit Mask. This ensures
  2442. // that we're dealing with indexed registers, since both the Read Map and
  2443. // the Bit Mask are addressed at GRAPH_DATA_PORT.
  2444. //
  2445. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2446. GRAPH_ADDRESS_PORT, IND_READ_MAP);
  2447. //
  2448. // If we can't read back the Graphics Address register setting we just
  2449. // performed, it's not readable and this isn't a VGA.
  2450. //
  2451. if ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2452. GRAPH_ADDRESS_PORT) & GRAPH_ADDR_MASK) != IND_READ_MAP) {
  2453. return FALSE;
  2454. }
  2455. //
  2456. // Set the Read Map register to a known state.
  2457. //
  2458. originalReadMap = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2459. GRAPH_DATA_PORT);
  2460. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2461. GRAPH_DATA_PORT, READ_MAP_TEST_SETTING);
  2462. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2463. GRAPH_DATA_PORT) != READ_MAP_TEST_SETTING) {
  2464. //
  2465. // The Read Map setting we just performed can't be read back; not a
  2466. // VGA. Restore the default Read Map state.
  2467. //
  2468. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2469. GRAPH_DATA_PORT, READ_MAP_DEFAULT);
  2470. return FALSE;
  2471. }
  2472. //
  2473. // Remember the original setting of the Bit Mask register.
  2474. //
  2475. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2476. GRAPH_ADDRESS_PORT, IND_BIT_MASK);
  2477. if ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2478. GRAPH_ADDRESS_PORT) & GRAPH_ADDR_MASK) != IND_BIT_MASK) {
  2479. //
  2480. // The Graphics Address register setting we just made can't be read
  2481. // back; not a VGA. Restore the default Read Map state.
  2482. //
  2483. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2484. GRAPH_ADDRESS_PORT, IND_READ_MAP);
  2485. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2486. GRAPH_DATA_PORT, READ_MAP_DEFAULT);
  2487. return FALSE;
  2488. }
  2489. originalBitMask = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2490. GRAPH_DATA_PORT);
  2491. //
  2492. // Set up the initial test mask we'll write to and read from the Bit Mask.
  2493. //
  2494. testMask = 0xBB;
  2495. do {
  2496. //
  2497. // Write the test mask to the Bit Mask.
  2498. //
  2499. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2500. GRAPH_DATA_PORT, testMask);
  2501. //
  2502. // Make sure the Bit Mask remembered the value.
  2503. //
  2504. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2505. GRAPH_DATA_PORT) != testMask) {
  2506. //
  2507. // The Bit Mask is not properly writable and readable; not a VGA.
  2508. // Restore the Bit Mask and Read Map to their default states.
  2509. //
  2510. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2511. GRAPH_DATA_PORT, BIT_MASK_DEFAULT);
  2512. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2513. GRAPH_ADDRESS_PORT, IND_READ_MAP);
  2514. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2515. GRAPH_DATA_PORT, READ_MAP_DEFAULT);
  2516. return FALSE;
  2517. }
  2518. //
  2519. // Cycle the mask for next time.
  2520. //
  2521. testMask >>= 1;
  2522. } while (testMask != 0);
  2523. //
  2524. // There's something readable at GRAPH_DATA_PORT; now switch back and
  2525. // make sure that the Read Map register hasn't changed, to verify that
  2526. // we're dealing with indexed registers.
  2527. //
  2528. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2529. GRAPH_ADDRESS_PORT, IND_READ_MAP);
  2530. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2531. GRAPH_DATA_PORT) != READ_MAP_TEST_SETTING) {
  2532. //
  2533. // The Read Map is not properly writable and readable; not a VGA.
  2534. // Restore the Bit Mask and Read Map to their default states, in case
  2535. // this is an EGA, so subsequent writes to the screen aren't garbled.
  2536. //
  2537. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2538. GRAPH_DATA_PORT, READ_MAP_DEFAULT);
  2539. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2540. GRAPH_ADDRESS_PORT, IND_BIT_MASK);
  2541. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2542. GRAPH_DATA_PORT, BIT_MASK_DEFAULT);
  2543. return FALSE;
  2544. }
  2545. //
  2546. // We've pretty surely verified the existence of the Bit Mask register.
  2547. // Put the Graphics Controller back to the original state.
  2548. //
  2549. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2550. GRAPH_DATA_PORT, originalReadMap);
  2551. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2552. GRAPH_ADDRESS_PORT, IND_BIT_MASK);
  2553. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2554. GRAPH_DATA_PORT, originalBitMask);
  2555. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2556. GRAPH_ADDRESS_PORT, originalGCAddr);
  2557. //
  2558. // Now, check for the existence of the Chain4 bit.
  2559. //
  2560. //
  2561. // Remember the original states of the Sequencer Address and Memory Mode
  2562. // registers.
  2563. //
  2564. originalSCAddr = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2565. SEQ_ADDRESS_PORT);
  2566. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2567. SEQ_ADDRESS_PORT, IND_MEMORY_MODE);
  2568. if ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2569. SEQ_ADDRESS_PORT) & SEQ_ADDR_MASK) != IND_MEMORY_MODE) {
  2570. //
  2571. // Couldn't read back the Sequencer Address register setting we just
  2572. // performed.
  2573. //
  2574. return FALSE;
  2575. }
  2576. originalMemoryMode = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2577. SEQ_DATA_PORT);
  2578. //
  2579. // Toggle the Chain4 bit and read back the result. This must be done during
  2580. // sync reset, since we're changing the chaining state.
  2581. //
  2582. //
  2583. // Begin sync reset.
  2584. //
  2585. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  2586. SEQ_ADDRESS_PORT),
  2587. (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8)));
  2588. //
  2589. // Toggle the Chain4 bit.
  2590. //
  2591. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2592. SEQ_ADDRESS_PORT, IND_MEMORY_MODE);
  2593. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2594. SEQ_DATA_PORT, (UCHAR)(originalMemoryMode ^ CHAIN4_MASK));
  2595. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2596. SEQ_DATA_PORT) != (UCHAR) (originalMemoryMode ^ CHAIN4_MASK)) {
  2597. //
  2598. // Chain4 bit not there; not a VGA.
  2599. // Set text mode default for Memory Mode register.
  2600. //
  2601. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2602. SEQ_DATA_PORT, MEMORY_MODE_TEXT_DEFAULT);
  2603. //
  2604. // End sync reset.
  2605. //
  2606. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2607. SEQ_ADDRESS_PORT),
  2608. (IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8)));
  2609. returnStatus = FALSE;
  2610. } else {
  2611. //
  2612. // It's a VGA.
  2613. //
  2614. //
  2615. // Restore the original Memory Mode setting.
  2616. //
  2617. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2618. SEQ_DATA_PORT, originalMemoryMode);
  2619. //
  2620. // End sync reset.
  2621. //
  2622. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  2623. SEQ_ADDRESS_PORT),
  2624. (USHORT)(IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8)));
  2625. //
  2626. // Restore the original Sequencer Address setting.
  2627. //
  2628. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2629. SEQ_ADDRESS_PORT, originalSCAddr);
  2630. returnStatus = TRUE;
  2631. }
  2632. return returnStatus;
  2633. } // VgaIsPresent()
  2634. //---------------------------------------------------------------------------
  2635. VP_STATUS
  2636. VgaSetPaletteReg(
  2637. PHW_DEVICE_EXTENSION HwDeviceExtension,
  2638. PVIDEO_PALETTE_DATA PaletteBuffer,
  2639. ULONG PaletteBufferSize
  2640. )
  2641. /*++
  2642. Routine Description:
  2643. This routine sets a specified portion of the EGA (not DAC) palette
  2644. registers.
  2645. Arguments:
  2646. HwDeviceExtension - Pointer to the miniport driver's device extension.
  2647. PaletteBuffer - Pointer to the structure containing the palette data.
  2648. PaletteBufferSize - Length of the input buffer supplied by the user.
  2649. Return Value:
  2650. NO_ERROR - information returned successfully
  2651. ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data.
  2652. ERROR_INVALID_PARAMETER - invalid palette size.
  2653. --*/
  2654. {
  2655. USHORT i;
  2656. //
  2657. // Check if the size of the data in the input buffer is large enough.
  2658. //
  2659. if ((PaletteBufferSize) < (sizeof(VIDEO_PALETTE_DATA)) ||
  2660. (PaletteBufferSize < (sizeof(VIDEO_PALETTE_DATA) +
  2661. (sizeof(USHORT) * (PaletteBuffer->NumEntries -1)) ))) {
  2662. return ERROR_INSUFFICIENT_BUFFER;
  2663. }
  2664. //
  2665. // Check to see if the parameters are valid.
  2666. //
  2667. if ( (PaletteBuffer->FirstEntry > VIDEO_MAX_COLOR_REGISTER ) ||
  2668. (PaletteBuffer->NumEntries == 0) ||
  2669. (PaletteBuffer->FirstEntry + PaletteBuffer->NumEntries >
  2670. VIDEO_MAX_PALETTE_REGISTER + 1 ) ) {
  2671. return ERROR_INVALID_PARAMETER;
  2672. }
  2673. //
  2674. // Reset ATC to index mode
  2675. //
  2676. //
  2677. // check to see mono or color first
  2678. //
  2679. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2680. MISC_OUTPUT_REG_READ_PORT) & 0x01) {
  2681. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2682. ATT_INITIALIZE_PORT_COLOR);
  2683. } else {
  2684. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2685. ATT_INITIALIZE_PORT_MONO); //frido 07-Aug-96
  2686. }
  2687. //
  2688. // Blast out our palette values.
  2689. //
  2690. for (i = 0; i < PaletteBuffer->NumEntries; i++) {
  2691. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ATT_ADDRESS_PORT,
  2692. (UCHAR)(i+PaletteBuffer->FirstEntry));
  2693. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2694. ATT_DATA_WRITE_PORT,
  2695. (UCHAR)PaletteBuffer->Colors[i]);
  2696. }
  2697. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ATT_ADDRESS_PORT,
  2698. VIDEO_ENABLE);
  2699. return NO_ERROR;
  2700. } // end VgaSetPaletteReg()
  2701. //---------------------------------------------------------------------------
  2702. VP_STATUS
  2703. VgaSetColorLookup(
  2704. PHW_DEVICE_EXTENSION HwDeviceExtension,
  2705. PVIDEO_CLUT ClutBuffer,
  2706. ULONG ClutBufferSize
  2707. )
  2708. /*++
  2709. Routine Description:
  2710. This routine sets a specified portion of the DAC color lookup table
  2711. settings.
  2712. Arguments:
  2713. HwDeviceExtension - Pointer to the miniport driver's device extension.
  2714. ClutBufferSize - Length of the input buffer supplied by the user.
  2715. ClutBuffer - Pointer to the structure containing the color lookup table.
  2716. Return Value:
  2717. NO_ERROR - information returned successfully
  2718. ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data.
  2719. ERROR_INVALID_PARAMETER - invalid clut size.
  2720. --*/
  2721. {
  2722. ULONG i;
  2723. //
  2724. // Check if the size of the data in the input buffer is large enough.
  2725. //
  2726. if ( (ClutBufferSize < sizeof(VIDEO_CLUT) - sizeof(ULONG)) ||
  2727. (ClutBufferSize < sizeof(VIDEO_CLUT) +
  2728. (sizeof(ULONG) * (ClutBuffer->NumEntries - 1)) ) ) {
  2729. return ERROR_INSUFFICIENT_BUFFER;
  2730. }
  2731. //
  2732. // Check to see if the parameters are valid.
  2733. //
  2734. if ( (ClutBuffer->NumEntries == 0) ||
  2735. (ClutBuffer->FirstEntry > VIDEO_MAX_COLOR_REGISTER) ||
  2736. (ClutBuffer->FirstEntry + ClutBuffer->NumEntries >
  2737. VIDEO_MAX_COLOR_REGISTER + 1) ) {
  2738. return ERROR_INVALID_PARAMETER;
  2739. }
  2740. //
  2741. // Set CLUT registers directly on the hardware
  2742. //
  2743. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2744. DAC_ADDRESS_WRITE_PORT, (UCHAR) ClutBuffer->FirstEntry);
  2745. for (i = 0; i < ClutBuffer->NumEntries; i++) {
  2746. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2747. DAC_ADDRESS_WRITE_PORT,
  2748. (UCHAR)(i + ClutBuffer->FirstEntry));
  2749. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2750. DAC_DATA_REG_PORT,
  2751. ClutBuffer->LookupTable[i].RgbArray.Red);
  2752. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2753. DAC_DATA_REG_PORT,
  2754. ClutBuffer->LookupTable[i].RgbArray.Green);
  2755. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2756. DAC_DATA_REG_PORT,
  2757. ClutBuffer->LookupTable[i].RgbArray.Blue);
  2758. }
  2759. return NO_ERROR;
  2760. } // end VgaSetColorLookup()
  2761. //---------------------------------------------------------------------------
  2762. VP_STATUS
  2763. VgaRestoreHardwareState(
  2764. PHW_DEVICE_EXTENSION HwDeviceExtension,
  2765. PVIDEO_HARDWARE_STATE HardwareState,
  2766. ULONG HardwareStateSize
  2767. )
  2768. /*++
  2769. Routine Description:
  2770. Restores all registers and memory of the VGA.
  2771. Note: HardwareState points to the actual buffer from which the state
  2772. is to be restored. This buffer will always be big enough (we specified
  2773. the required size at DriverEntry).
  2774. Note: The offset in the hardware state header from which each general
  2775. register is restored is the offset of the write address of that register
  2776. from the base I/O address of the VGA.
  2777. Arguments:
  2778. HwDeviceExtension - Pointer to the miniport driver's device extension.
  2779. HardwareState - Pointer to a structure from which the saved state is to be
  2780. restored (actually only info about and a pointer to the actual save
  2781. buffer).
  2782. HardwareStateSize - Length of the input buffer supplied by the user.
  2783. (Actually only the size of the HardwareState structure, not the
  2784. buffer it points to from which the state is actually restored. The
  2785. pointed-to buffer is assumed to be big enough.)
  2786. Return Value:
  2787. NO_ERROR - restore performed successfully
  2788. ERROR_INSUFFICIENT_BUFFER - input buffer not large enough to provide data
  2789. --*/
  2790. {
  2791. PVIDEO_HARDWARE_STATE_HEADER hardwareStateHeader;
  2792. ULONG i;
  2793. UCHAR dummy;
  2794. PUCHAR pScreen;
  2795. PUCHAR pucLatch;
  2796. PULONG pulBuffer;
  2797. PUCHAR port;
  2798. PUCHAR portValue;
  2799. PUCHAR portValueDAC;
  2800. ULONG bIsColor;
  2801. ULONG portIO ;
  2802. UCHAR value ;
  2803. //
  2804. // Check if the size of the data in the input buffer is large enough.
  2805. //
  2806. if ((HardwareStateSize < sizeof(VIDEO_HARDWARE_STATE)) ||
  2807. (HardwareState->StateLength < VGA_TOTAL_STATE_SIZE)) {
  2808. return ERROR_INSUFFICIENT_BUFFER;
  2809. }
  2810. //
  2811. // Point to the buffer where the restore data is actually stored.
  2812. //
  2813. hardwareStateHeader = HardwareState->StateHeader;
  2814. //
  2815. // Make sure the offset are in the structure ...
  2816. //
  2817. if ((hardwareStateHeader->BasicSequencerOffset + VGA_NUM_SEQUENCER_PORTS >
  2818. HardwareState->StateLength) ||
  2819. (hardwareStateHeader->BasicCrtContOffset + VGA_NUM_CRTC_PORTS >
  2820. HardwareState->StateLength) ||
  2821. (hardwareStateHeader->BasicGraphContOffset + VGA_NUM_GRAPH_CONT_PORTS >
  2822. HardwareState->StateLength) ||
  2823. (hardwareStateHeader->BasicAttribContOffset + VGA_NUM_ATTRIB_CONT_PORTS >
  2824. HardwareState->StateLength) ||
  2825. (hardwareStateHeader->BasicDacOffset + (3 * VGA_NUM_DAC_ENTRIES) >
  2826. HardwareState->StateLength) ||
  2827. (hardwareStateHeader->BasicLatchesOffset + 4 >
  2828. HardwareState->StateLength) ||
  2829. (hardwareStateHeader->ExtendedSequencerOffset + EXT_NUM_SEQUENCER_PORTS >
  2830. HardwareState->StateLength) ||
  2831. (hardwareStateHeader->ExtendedCrtContOffset + EXT_NUM_CRTC_PORTS >
  2832. HardwareState->StateLength) ||
  2833. (hardwareStateHeader->ExtendedGraphContOffset + EXT_NUM_GRAPH_CONT_PORTS >
  2834. HardwareState->StateLength) ||
  2835. (hardwareStateHeader->ExtendedAttribContOffset + EXT_NUM_ATTRIB_CONT_PORTS >
  2836. HardwareState->StateLength) ||
  2837. (hardwareStateHeader->ExtendedDacOffset + (4 * EXT_NUM_DAC_ENTRIES) >
  2838. HardwareState->StateLength) ||
  2839. //
  2840. // Only check the validator state offset if there is unemulated data.
  2841. //
  2842. ((hardwareStateHeader->VGAStateFlags & VIDEO_STATE_UNEMULATED_VGA_STATE) &&
  2843. (hardwareStateHeader->ExtendedValidatorStateOffset + VGA_VALIDATOR_AREA_SIZE >
  2844. HardwareState->StateLength)) ||
  2845. (hardwareStateHeader->ExtendedMiscDataOffset + VGA_MISC_DATA_AREA_OFFSET >
  2846. HardwareState->StateLength) ||
  2847. (hardwareStateHeader->Plane1Offset + hardwareStateHeader->PlaneLength >
  2848. HardwareState->StateLength) ||
  2849. (hardwareStateHeader->Plane2Offset + hardwareStateHeader->PlaneLength >
  2850. HardwareState->StateLength) ||
  2851. (hardwareStateHeader->Plane3Offset + hardwareStateHeader->PlaneLength >
  2852. HardwareState->StateLength) ||
  2853. (hardwareStateHeader->Plane4Offset + hardwareStateHeader->PlaneLength >
  2854. HardwareState->StateLength) ||
  2855. (hardwareStateHeader->DIBOffset +
  2856. hardwareStateHeader->DIBBitsPerPixel / 8 *
  2857. hardwareStateHeader->DIBXResolution *
  2858. hardwareStateHeader->DIBYResolution > HardwareState->StateLength) ||
  2859. (hardwareStateHeader->DIBXlatOffset + hardwareStateHeader->DIBXlatLength >
  2860. HardwareState->StateLength)) {
  2861. return ERROR_INVALID_PARAMETER;
  2862. }
  2863. //
  2864. // Turn off the screen to avoid flickering. The screen will turn back on
  2865. // when we restore the DAC state at the end of this routine.
  2866. //
  2867. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2868. MISC_OUTPUT_REG_READ_PORT) & 0x01) {
  2869. port = INPUT_STATUS_1_COLOR + HwDeviceExtension->IOAddress;
  2870. } else {
  2871. port = INPUT_STATUS_1_MONO + HwDeviceExtension->IOAddress;
  2872. }
  2873. //
  2874. // Set DAC register 0 to display black.
  2875. //
  2876. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2877. DAC_ADDRESS_WRITE_PORT, 0);
  2878. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2879. DAC_DATA_REG_PORT, 0);
  2880. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2881. DAC_DATA_REG_PORT, 0);
  2882. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2883. DAC_DATA_REG_PORT, 0);
  2884. //
  2885. // Set the DAC mask register to force DAC register 0 to display all the
  2886. // time (this is the register we just set to display black). From now on,
  2887. // nothing but black will show up on the screen.
  2888. //
  2889. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2890. DAC_PIXEL_MASK_PORT, 0);
  2891. //
  2892. // Restore the latches and the contents of display memory.
  2893. //
  2894. // Set up the VGA's hardware to allow us to copy to each plane in turn.
  2895. //
  2896. // Begin sync reset.
  2897. //
  2898. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2899. SEQ_ADDRESS_PORT),
  2900. (USHORT) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8)));
  2901. //
  2902. // Turn off Chain mode and map display memory at A0000 for 64K.
  2903. //
  2904. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2905. GRAPH_ADDRESS_PORT, IND_GRAPH_MISC);
  2906. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2907. GRAPH_DATA_PORT, (UCHAR) ((VideoPortReadPortUchar(
  2908. HwDeviceExtension->IOAddress + GRAPH_DATA_PORT) & 0xF1) | 0x04));
  2909. //
  2910. // Turn off Chain4 mode and odd/even.
  2911. //
  2912. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2913. SEQ_ADDRESS_PORT, IND_MEMORY_MODE);
  2914. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2915. SEQ_DATA_PORT,
  2916. (UCHAR) ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2917. SEQ_DATA_PORT) & 0xF3) | 0x04));
  2918. //
  2919. // End sync reset.
  2920. //
  2921. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2922. SEQ_ADDRESS_PORT), (USHORT) (IND_SYNC_RESET +
  2923. (END_SYNC_RESET_VALUE << 8)));
  2924. //
  2925. // Set the write mode to 0, the read mode to 0, and turn off odd/even.
  2926. //
  2927. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2928. GRAPH_ADDRESS_PORT, IND_GRAPH_MODE);
  2929. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2930. GRAPH_DATA_PORT,
  2931. (UCHAR) ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2932. GRAPH_DATA_PORT) & 0xE4) | 0x00));
  2933. //
  2934. // Set the Bit Mask to 0xFF to allow all CPU bits through.
  2935. //
  2936. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2937. GRAPH_ADDRESS_PORT), (USHORT) (IND_BIT_MASK + (0xFF << 8)));
  2938. //
  2939. // Set the Data Rotation and Logical Function fields to 0 to allow CPU
  2940. // data through unmodified.
  2941. //
  2942. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  2943. GRAPH_ADDRESS_PORT), (USHORT) (IND_DATA_ROTATE + (0 << 8)));
  2944. //
  2945. // Set Set/Reset Enable to 0 to select CPU data for all planes.
  2946. //
  2947. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2948. GRAPH_ADDRESS_PORT), (USHORT) (IND_SET_RESET_ENABLE + (0 << 8)));
  2949. //
  2950. // Point the Sequencer Index to the Map Mask register.
  2951. //
  2952. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2953. SEQ_ADDRESS_PORT, IND_MAP_MASK);
  2954. //
  2955. // Restore the latches.
  2956. //
  2957. // Point to the saved data for the first latch.
  2958. //
  2959. pucLatch = ((PUCHAR) (hardwareStateHeader)) +
  2960. hardwareStateHeader->BasicLatchesOffset;
  2961. //
  2962. // Point to first byte of display memory.
  2963. //
  2964. pScreen = (PUCHAR) HwDeviceExtension->VideoMemoryAddress;
  2965. //
  2966. // Write the contents to be restored to each of the four latches in turn.
  2967. //
  2968. for (i = 0; i < 4; i++) {
  2969. //
  2970. // Set the Map Mask to select the plane we want to restore next.
  2971. //
  2972. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2973. SEQ_DATA_PORT, (UCHAR)(1<<i));
  2974. //
  2975. // Write this plane's latch.
  2976. //
  2977. VideoPortWriteRegisterUchar(pScreen, *pucLatch++);
  2978. }
  2979. //
  2980. // Read the latched data into the latches, and the latches are set.
  2981. //
  2982. dummy = VideoPortReadRegisterUchar(pScreen);
  2983. //
  2984. // Point to the offset of the saved data for the first plane.
  2985. //
  2986. pulBuffer = &(hardwareStateHeader->Plane1Offset);
  2987. //
  2988. // Restore each of the four planes in turn.
  2989. //
  2990. for (i = 0; i < 4; i++) {
  2991. //
  2992. // Set the Map Mask to select the plane we want to restore next.
  2993. //
  2994. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2995. SEQ_DATA_PORT, (UCHAR)(1<<i));
  2996. //
  2997. // Restore this plane from the buffer.
  2998. //
  2999. VideoPortMoveMemory((PUCHAR) HwDeviceExtension->VideoMemoryAddress,
  3000. ((PUCHAR) (hardwareStateHeader)) + *pulBuffer,
  3001. hardwareStateHeader->PlaneLength);
  3002. pulBuffer++;
  3003. }
  3004. //
  3005. // If we have some unemulated data, put it back into the buffer
  3006. //
  3007. if (hardwareStateHeader->VGAStateFlags & VIDEO_STATE_UNEMULATED_VGA_STATE) {
  3008. if (!hardwareStateHeader->ExtendedValidatorStateOffset) {
  3009. return ERROR_INVALID_PARAMETER;
  3010. }
  3011. //
  3012. // Get the right offset in the struct and save all the data associated
  3013. // with the trapped validator data.
  3014. //
  3015. VideoPortMoveMemory(&(HwDeviceExtension->TrappedValidatorCount),
  3016. ((PUCHAR) (hardwareStateHeader)) +
  3017. hardwareStateHeader->ExtendedValidatorStateOffset,
  3018. VGA_VALIDATOR_AREA_SIZE);
  3019. //
  3020. // Check to see if this is an appropriate access range.
  3021. // We are trapping - so we must have the trapping access range enabled.
  3022. //
  3023. if (((HwDeviceExtension->CurrentVdmAccessRange != FullVgaValidatorAccessRange) ||
  3024. (HwDeviceExtension->CurrentNumVdmAccessRanges != NUM_FULL_VGA_VALIDATOR_ACCESS_RANGE)) &&
  3025. ((HwDeviceExtension->CurrentVdmAccessRange != MinimalVgaValidatorAccessRange) ||
  3026. (HwDeviceExtension->CurrentNumVdmAccessRanges != NUM_MINIMAL_VGA_VALIDATOR_ACCESS_RANGE))) {
  3027. return ERROR_INVALID_PARAMETER;
  3028. }
  3029. VideoPortSetTrappedEmulatorPorts(HwDeviceExtension,
  3030. HwDeviceExtension->CurrentNumVdmAccessRanges,
  3031. HwDeviceExtension->CurrentVdmAccessRange);
  3032. }
  3033. //
  3034. // Set the critical registers (clock and timing states) during sync reset.
  3035. //
  3036. // Begin sync reset.
  3037. //
  3038. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3039. SEQ_ADDRESS_PORT), (USHORT) (IND_SYNC_RESET +
  3040. (START_SYNC_RESET_VALUE << 8)));
  3041. //
  3042. // Restore the Miscellaneous Output register.
  3043. //
  3044. portIO = MISC_OUTPUT_REG_WRITE_PORT ;
  3045. value = (UCHAR) (hardwareStateHeader->PortValue[MISC_OUTPUT_REG_WRITE_PORT-VGA_BASE_IO_PORT] & 0xF7) ;
  3046. IOWaitDisplEnableThenWrite ( HwDeviceExtension,
  3047. portIO,
  3048. value ) ;
  3049. //
  3050. // Restore all Sequencer registers except the Sync Reset register, which
  3051. // is always not in reset (except when we send out a batched sync reset
  3052. // register set, but that can't be interrupted, so we know we're never in
  3053. // sync reset at save/restore time).
  3054. //
  3055. portValue = ((PUCHAR) hardwareStateHeader) +
  3056. hardwareStateHeader->BasicSequencerOffset + 1;
  3057. for (i = 1; i < VGA_NUM_SEQUENCER_PORTS; i++) {
  3058. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3059. SEQ_ADDRESS_PORT), (USHORT) (i + ((*portValue++) << 8)) );
  3060. }
  3061. //
  3062. // Restore extended sequencer registers
  3063. //
  3064. #ifdef EXTENDED_REGISTER_SAVE_RESTORE
  3065. if (hardwareStateHeader->ExtendedSequencerOffset) {
  3066. portValue = ((PUCHAR) hardwareStateHeader) +
  3067. hardwareStateHeader->ExtendedSequencerOffset;
  3068. if ((HwDeviceExtension->ChipType != CL6410) &&
  3069. (HwDeviceExtension->ChipType != CL6420))
  3070. {
  3071. //
  3072. // No extended sequencer registers for the CL64xx
  3073. //
  3074. //
  3075. // The first section in restore must open the extension registers
  3076. //
  3077. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3078. SEQ_ADDRESS_PORT),
  3079. IND_CL_EXTS_ENB + (0x0012 << 8) );
  3080. for (i = CL542x_SEQUENCER_EXT_START;
  3081. i <= CL542x_SEQUENCER_EXT_END;
  3082. i++) {
  3083. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3084. SEQ_ADDRESS_PORT),
  3085. (USHORT) (i + ((*portValue++) << 8)) );
  3086. }
  3087. }
  3088. }
  3089. #endif
  3090. //
  3091. // Restore the Graphics Controller Miscellaneous register, which contains
  3092. // the Chain bit.
  3093. //
  3094. portValue = ((PUCHAR) hardwareStateHeader) +
  3095. hardwareStateHeader->BasicGraphContOffset + IND_GRAPH_MISC;
  3096. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3097. GRAPH_ADDRESS_PORT), (USHORT)(IND_GRAPH_MISC + (*portValue << 8)));
  3098. //
  3099. // End sync reset.
  3100. //
  3101. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3102. SEQ_ADDRESS_PORT), (USHORT) (IND_SYNC_RESET +
  3103. (END_SYNC_RESET_VALUE << 8)));
  3104. //
  3105. // Figure out if color/mono switchable registers are at 3BX or 3DX.
  3106. // At the same time, save the state of the Miscellaneous Output register
  3107. // which is read from 3CC but written at 3C2.
  3108. //
  3109. if (hardwareStateHeader->PortValue[MISC_OUTPUT_REG_WRITE_PORT-VGA_BASE_IO_PORT] & 0x01) {
  3110. bIsColor = TRUE;
  3111. } else {
  3112. bIsColor = FALSE;
  3113. }
  3114. //
  3115. // Restore the CRT Controller indexed registers.
  3116. //
  3117. // Unlock CRTC registers 0-7.
  3118. //
  3119. portValue = (PUCHAR) hardwareStateHeader +
  3120. hardwareStateHeader->BasicCrtContOffset;
  3121. if (bIsColor) {
  3122. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3123. CRTC_ADDRESS_PORT_COLOR), (USHORT) (IND_CRTC_PROTECT +
  3124. (((*(portValue + IND_CRTC_PROTECT)) & 0x7F) << 8)));
  3125. } else {
  3126. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3127. CRTC_ADDRESS_PORT_MONO), (USHORT) (IND_CRTC_PROTECT +
  3128. (((*(portValue + IND_CRTC_PROTECT)) & 0x7F) << 8)));
  3129. }
  3130. //
  3131. // Restore extended crtc registers.
  3132. //
  3133. #ifdef EXTENDED_REGISTER_SAVE_RESTORE
  3134. if (hardwareStateHeader->ExtendedCrtContOffset) {
  3135. portValue = (PUCHAR) hardwareStateHeader +
  3136. hardwareStateHeader->ExtendedCrtContOffset;
  3137. if ((HwDeviceExtension->ChipType != CL6410) &&
  3138. (HwDeviceExtension->ChipType != CL6420))
  3139. {
  3140. //
  3141. // No CRTC Extensions in CL64xx chipset
  3142. //
  3143. for (i = CL542x_CRTC_EXT_START; i <= CL542x_CRTC_EXT_END; i++) {
  3144. if (bIsColor) {
  3145. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3146. CRTC_ADDRESS_PORT_COLOR),
  3147. (USHORT) (i + ((*portValue++) << 8)));
  3148. } else {
  3149. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3150. CRTC_ADDRESS_PORT_MONO),
  3151. (USHORT) (i + ((*portValue++) << 8)));
  3152. }
  3153. }
  3154. }
  3155. /* myf2, crus
  3156. if (HwDeviceExtension->ChipType & CL755x)
  3157. {
  3158. for (i = 0x81; i <= 0x91; i++)
  3159. {
  3160. if (bIsColor)
  3161. {
  3162. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3163. CRTC_ADDRESS_PORT_COLOR),
  3164. (USHORT) (i + ((*portValue++) << 8)));
  3165. } else {
  3166. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3167. CRTC_ADDRESS_PORT_MONO),
  3168. (USHORT) (i + ((*portValue++) << 8)));
  3169. }
  3170. }
  3171. }
  3172. crus, myf2 */
  3173. }
  3174. #endif
  3175. //
  3176. // Now restore the CRTC registers.
  3177. //
  3178. portValue = (PUCHAR) hardwareStateHeader +
  3179. hardwareStateHeader->BasicCrtContOffset;
  3180. for (i = 0; i < VGA_NUM_CRTC_PORTS; i++) {
  3181. if (bIsColor) {
  3182. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3183. CRTC_ADDRESS_PORT_COLOR),
  3184. (USHORT) (i + ((*portValue++) << 8)));
  3185. } else {
  3186. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3187. CRTC_ADDRESS_PORT_MONO),
  3188. (USHORT) (i + ((*portValue++) << 8)));
  3189. }
  3190. }
  3191. //
  3192. // Restore the Graphics Controller indexed registers.
  3193. //
  3194. portValue = (PUCHAR) hardwareStateHeader +
  3195. hardwareStateHeader->BasicGraphContOffset;
  3196. for (i = 0; i < VGA_NUM_GRAPH_CONT_PORTS; i++) {
  3197. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3198. GRAPH_ADDRESS_PORT), (USHORT) (i + ((*portValue++) << 8)));
  3199. }
  3200. //
  3201. // Restore extended graphics controller registers.
  3202. //
  3203. #ifdef EXTENDED_REGISTER_SAVE_RESTORE
  3204. if (hardwareStateHeader->ExtendedGraphContOffset) {
  3205. portValue = (PUCHAR) hardwareStateHeader +
  3206. hardwareStateHeader->ExtendedGraphContOffset;
  3207. if ((HwDeviceExtension->ChipType != CL6410) &&
  3208. (HwDeviceExtension->ChipType != CL6420))
  3209. {
  3210. for (i = CL542x_GRAPH_EXT_START; i <= CL542x_GRAPH_EXT_END; i++) {
  3211. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3212. GRAPH_ADDRESS_PORT),
  3213. (USHORT) (i + ((*portValue++) << 8)));
  3214. }
  3215. } else { // must be a CL64xx
  3216. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  3217. GRAPH_ADDRESS_PORT),
  3218. CL64xx_EXTENSION_ENABLE_INDEX +
  3219. (CL64xx_EXTENSION_ENABLE_VALUE << 8));
  3220. for (i = CL64xx_GRAPH_EXT_START; i <= CL64xx_GRAPH_EXT_END; i++) {
  3221. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3222. GRAPH_ADDRESS_PORT),
  3223. (USHORT) (i + ((*portValue++) << 8)));
  3224. }
  3225. }
  3226. }
  3227. #endif
  3228. //
  3229. // Restore the Attribute Controller indexed registers.
  3230. //
  3231. portValue = (PUCHAR) hardwareStateHeader +
  3232. hardwareStateHeader->BasicAttribContOffset;
  3233. //
  3234. // Reset the AC index/data toggle, then blast out all the register
  3235. // settings.
  3236. //
  3237. if (bIsColor) {
  3238. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3239. INPUT_STATUS_1_COLOR);
  3240. } else {
  3241. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3242. INPUT_STATUS_1_MONO);
  3243. }
  3244. for (i = 0; i < VGA_NUM_ATTRIB_CONT_PORTS; i++) {
  3245. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3246. ATT_ADDRESS_PORT, (UCHAR)i);
  3247. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3248. ATT_DATA_WRITE_PORT, *portValue++);
  3249. }
  3250. //
  3251. // Restore DAC registers 1 through 255. We'll do register 0, the DAC Mask,
  3252. // and the index registers later.
  3253. // Set the DAC address port Index, then write out the DAC Data registers.
  3254. // Each three reads get Red, Green, and Blue components for that register.
  3255. //
  3256. // Write them one at a time due to problems on local bus machines.
  3257. //
  3258. portValueDAC = (PUCHAR) hardwareStateHeader +
  3259. hardwareStateHeader->BasicDacOffset + 3;
  3260. for (i = 1; i < VGA_NUM_DAC_ENTRIES; i++) {
  3261. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3262. DAC_ADDRESS_WRITE_PORT, (UCHAR)i);
  3263. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3264. DAC_DATA_REG_PORT, *portValueDAC++);
  3265. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3266. DAC_DATA_REG_PORT, *portValueDAC++);
  3267. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3268. DAC_DATA_REG_PORT, *portValueDAC++);
  3269. }
  3270. //
  3271. // Is this color or mono ?
  3272. //
  3273. if (bIsColor) {
  3274. port = HwDeviceExtension->IOAddress + INPUT_STATUS_1_COLOR;
  3275. } else {
  3276. port = HwDeviceExtension->IOAddress + INPUT_STATUS_1_MONO;
  3277. }
  3278. //
  3279. // Restore the Feature Control register.
  3280. //
  3281. if (bIsColor) {
  3282. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3283. FEAT_CTRL_WRITE_PORT_COLOR,
  3284. hardwareStateHeader->PortValue[FEAT_CTRL_WRITE_PORT_COLOR-VGA_BASE_IO_PORT]);
  3285. } else {
  3286. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3287. FEAT_CTRL_WRITE_PORT_MONO,
  3288. hardwareStateHeader->PortValue[FEAT_CTRL_WRITE_PORT_MONO-VGA_BASE_IO_PORT]);
  3289. }
  3290. //
  3291. // Restore the Sequencer Index.
  3292. //
  3293. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3294. SEQ_ADDRESS_PORT,
  3295. hardwareStateHeader->PortValue[SEQ_ADDRESS_PORT-VGA_BASE_IO_PORT]);
  3296. //
  3297. // Restore the CRT Controller Index.
  3298. //
  3299. if (bIsColor) {
  3300. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3301. CRTC_ADDRESS_PORT_COLOR,
  3302. hardwareStateHeader->PortValue[CRTC_ADDRESS_PORT_COLOR-VGA_BASE_IO_PORT]);
  3303. } else {
  3304. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3305. CRTC_ADDRESS_PORT_MONO,
  3306. hardwareStateHeader->PortValue[CRTC_ADDRESS_PORT_MONO-VGA_BASE_IO_PORT]);
  3307. }
  3308. //
  3309. // Restore the Graphics Controller Index.
  3310. //
  3311. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3312. GRAPH_ADDRESS_PORT,
  3313. hardwareStateHeader->PortValue[GRAPH_ADDRESS_PORT-VGA_BASE_IO_PORT]);
  3314. //
  3315. // Restore the Attribute Controller Index and index/data toggle state.
  3316. //
  3317. if (bIsColor) {
  3318. port = HwDeviceExtension->IOAddress + INPUT_STATUS_1_COLOR;
  3319. } else {
  3320. port = HwDeviceExtension->IOAddress + INPUT_STATUS_1_MONO;
  3321. }
  3322. VideoPortReadPortUchar(port); // reset the toggle to Index state
  3323. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3324. ATT_ADDRESS_PORT, // restore the AC Index
  3325. hardwareStateHeader->PortValue[ATT_ADDRESS_PORT-VGA_BASE_IO_PORT]);
  3326. //
  3327. // If the toggle should be in Data state, we're all set. If it should be in
  3328. // Index state, reset it to that condition.
  3329. //
  3330. if (hardwareStateHeader->AttribIndexDataState == 0) {
  3331. //
  3332. // Reset the toggle to Index state.
  3333. //
  3334. VideoPortReadPortUchar(port);
  3335. }
  3336. //
  3337. // Restore DAC register 0 and the DAC Mask, to unblank the screen.
  3338. //
  3339. portValueDAC = (PUCHAR) hardwareStateHeader +
  3340. hardwareStateHeader->BasicDacOffset;
  3341. //
  3342. // Restore the DAC Mask register.
  3343. //
  3344. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3345. DAC_PIXEL_MASK_PORT,
  3346. hardwareStateHeader->PortValue[DAC_PIXEL_MASK_PORT-VGA_BASE_IO_PORT]);
  3347. //
  3348. // Restore DAC register 0.
  3349. //
  3350. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3351. DAC_ADDRESS_WRITE_PORT, 0);
  3352. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3353. DAC_DATA_REG_PORT, *portValueDAC++);
  3354. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3355. DAC_DATA_REG_PORT, *portValueDAC++);
  3356. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3357. DAC_DATA_REG_PORT, *portValueDAC++);
  3358. //
  3359. // Restore the read/write state and the current index of the DAC.
  3360. //
  3361. // See whether the Read or Write Index was written to most recently.
  3362. // (The upper nibble stored at DAC_STATE_PORT is the # of reads/writes
  3363. // for the current index.)
  3364. //
  3365. if ((hardwareStateHeader->PortValue[DAC_STATE_PORT-VGA_BASE_IO_PORT] & 0x0F) == 3) {
  3366. //
  3367. // The DAC Read Index was written to last. Restore the DAC by setting
  3368. // up to read from the saved index - 1, because the way the Read
  3369. // Index works is that it autoincrements after reading, so you actually
  3370. // end up reading the data for the index you read at the DAC Write
  3371. // Mask register - 1.
  3372. //
  3373. // Set the Read Index to the index we read, minus 1, accounting for
  3374. // wrap from 255 back to 0. The DAC hardware immediately reads this
  3375. // register into a temporary buffer, then adds 1 to the index.
  3376. //
  3377. if (hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT-VGA_BASE_IO_PORT] == 0) {
  3378. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3379. DAC_ADDRESS_READ_PORT, 255);
  3380. } else {
  3381. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3382. DAC_ADDRESS_READ_PORT, (UCHAR)
  3383. (hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT-VGA_BASE_IO_PORT] -
  3384. 1));
  3385. }
  3386. //
  3387. // Now read the hardware however many times are required to get to
  3388. // the partial read state we saved.
  3389. //
  3390. for (i = hardwareStateHeader->PortValue[DAC_STATE_PORT-VGA_BASE_IO_PORT] >> 4;
  3391. i > 0; i--) {
  3392. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3393. DAC_DATA_REG_PORT);
  3394. }
  3395. } else {
  3396. //
  3397. // The DAC Write Index was written to last. Set the Write Index to the
  3398. // index value we read out of the DAC. Then, if a partial write
  3399. // (partway through an RGB triplet) was in place, write the partial
  3400. // values, which we obtained by writing them to the current DAC
  3401. // register. This DAC register will be wrong until the write is
  3402. // completed, but at least the values will be right once the write is
  3403. // finished, and most importantly we won't have messed up the sequence
  3404. // of RGB writes (which can be as long as 768 in a row).
  3405. //
  3406. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3407. DAC_ADDRESS_WRITE_PORT,
  3408. hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT-VGA_BASE_IO_PORT]);
  3409. //
  3410. // Now write to the hardware however many times are required to get to
  3411. // the partial write state we saved (if any).
  3412. //
  3413. // Point to the saved value for the DAC register that was in the
  3414. // process of being written to; we wrote the partial value out, so now
  3415. // we can restore it.
  3416. //
  3417. portValueDAC = (PUCHAR) hardwareStateHeader +
  3418. hardwareStateHeader->BasicDacOffset +
  3419. (hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT-VGA_BASE_IO_PORT] * 3);
  3420. for (i = hardwareStateHeader->PortValue[DAC_STATE_PORT-VGA_BASE_IO_PORT] >> 4;
  3421. i > 0; i--) {
  3422. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3423. DAC_DATA_REG_PORT, *portValueDAC++);
  3424. }
  3425. }
  3426. return NO_ERROR;
  3427. } // end VgaRestoreHardwareState()
  3428. //---------------------------------------------------------------------------
  3429. VP_STATUS
  3430. VgaSaveHardwareState(
  3431. PHW_DEVICE_EXTENSION HwDeviceExtension,
  3432. PVIDEO_HARDWARE_STATE HardwareState,
  3433. ULONG HardwareStateSize,
  3434. PULONG OutputSize
  3435. )
  3436. /*++
  3437. Routine Description:
  3438. Saves all registers and memory of the VGA.
  3439. Note: HardwareState points to the actual buffer in which the state
  3440. is saved. This buffer will always be big enough (we specified
  3441. the required size at DriverEntry).
  3442. Note: This routine leaves registers in any state it cares to, except
  3443. that it will not mess with any of the CRT or Sequencer parameters that
  3444. might make the monitor unhappy. It leaves the screen blanked by setting
  3445. the DAC Mask and DAC register 0 to all zero values. The next video
  3446. operation we expect after this is a mode set to take us back to Win32.
  3447. Note: The offset in the hardware state header in which each general
  3448. register is saved is the offset of the write address of that register from
  3449. the base I/O address of the VGA.
  3450. Arguments:
  3451. HwDeviceExtension - Pointer to the miniport driver's device extension.
  3452. HardwareState - Pointer to a structure in which the saved state will be
  3453. returned (actually only info about and a pointer to the actual save
  3454. buffer).
  3455. HardwareStateSize - Length of the output buffer supplied by the user.
  3456. (Actually only the size of the HardwareState structure, not the
  3457. buffer it points to where the state is actually saved. The pointed-
  3458. to buffer is assumed to be big enough.)
  3459. OutputSize - Pointer to a buffer in which to return the actual size of
  3460. the data returned in the buffer.
  3461. Return Value:
  3462. NO_ERROR - information returned successfully
  3463. ERROR_INSUFFICIENT_BUFFER - output buffer not large enough to return
  3464. any useful data
  3465. --*/
  3466. {
  3467. PVIDEO_HARDWARE_STATE_HEADER hardwareStateHeader;
  3468. PUCHAR port;
  3469. PUCHAR pScreen;
  3470. PUCHAR portValue;
  3471. PUCHAR portValueDAC;
  3472. PUCHAR bufferPointer;
  3473. ULONG i;
  3474. UCHAR dummy, originalACIndex, originalACData;
  3475. UCHAR ucCRTC03;
  3476. ULONG bIsColor;
  3477. ULONG portIO ;
  3478. UCHAR value ;
  3479. //
  3480. // See if the buffer is big enough to hold the hardware state structure.
  3481. // (This is only the HardwareState structure itself, not the buffer it
  3482. // points to.)
  3483. //
  3484. if (HardwareStateSize < sizeof(VIDEO_HARDWARE_STATE) ) {
  3485. *OutputSize = 0; // nothing returned
  3486. return ERROR_INSUFFICIENT_BUFFER;
  3487. }
  3488. //
  3489. // Amount of data we're going to return in the output buffer.
  3490. // (The VIDEO_HARDWARE_STATE in the output buffer points to the actual
  3491. // buffer in which the state is stored, which is assumed to be large
  3492. // enough.)
  3493. //
  3494. *OutputSize = sizeof(VIDEO_HARDWARE_STATE);
  3495. //
  3496. // Indicate the size of the full state save info.
  3497. //
  3498. HardwareState->StateLength = VGA_TOTAL_STATE_SIZE;
  3499. //
  3500. // hardwareStateHeader is a structure of offsets at the start of the
  3501. // actual save area that indicates the locations in which various VGA
  3502. // register and memory components are saved.
  3503. //
  3504. hardwareStateHeader = HardwareState->StateHeader;
  3505. //
  3506. // Zero out the structure.
  3507. //
  3508. VideoPortZeroMemory(hardwareStateHeader, sizeof(VIDEO_HARDWARE_STATE_HEADER));
  3509. //
  3510. // Set the Length field, which is basically a version ID.
  3511. //
  3512. hardwareStateHeader->Length = sizeof(VIDEO_HARDWARE_STATE_HEADER);
  3513. //
  3514. // Set the basic register offsets properly.
  3515. //
  3516. hardwareStateHeader->BasicSequencerOffset = VGA_BASIC_SEQUENCER_OFFSET;
  3517. hardwareStateHeader->BasicCrtContOffset = VGA_BASIC_CRTC_OFFSET;
  3518. hardwareStateHeader->BasicGraphContOffset = VGA_BASIC_GRAPH_CONT_OFFSET;
  3519. hardwareStateHeader->BasicAttribContOffset = VGA_BASIC_ATTRIB_CONT_OFFSET;
  3520. hardwareStateHeader->BasicDacOffset = VGA_BASIC_DAC_OFFSET;
  3521. hardwareStateHeader->BasicLatchesOffset = VGA_BASIC_LATCHES_OFFSET;
  3522. //
  3523. // Set the entended register offsets properly.
  3524. //
  3525. hardwareStateHeader->ExtendedSequencerOffset = VGA_EXT_SEQUENCER_OFFSET;
  3526. hardwareStateHeader->ExtendedCrtContOffset = VGA_EXT_CRTC_OFFSET;
  3527. hardwareStateHeader->ExtendedGraphContOffset = VGA_EXT_GRAPH_CONT_OFFSET;
  3528. hardwareStateHeader->ExtendedAttribContOffset = VGA_EXT_ATTRIB_CONT_OFFSET;
  3529. hardwareStateHeader->ExtendedDacOffset = VGA_EXT_DAC_OFFSET;
  3530. //
  3531. // Figure out if color/mono switchable registers are at 3BX or 3DX.
  3532. // At the same time, save the state of the Miscellaneous Output register
  3533. // which is read from 3CC but written at 3C2.
  3534. //
  3535. if ((hardwareStateHeader->PortValue[MISC_OUTPUT_REG_WRITE_PORT-VGA_BASE_IO_PORT] =
  3536. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3537. MISC_OUTPUT_REG_READ_PORT))
  3538. & 0x01) {
  3539. bIsColor = TRUE;
  3540. } else {
  3541. bIsColor = FALSE;
  3542. }
  3543. //
  3544. // Force the video subsystem enable state to enabled.
  3545. //
  3546. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3547. VIDEO_SUBSYSTEM_ENABLE_PORT, 1);
  3548. //
  3549. // Save the DAC state first, so we can set the DAC to blank the screen
  3550. // so nothing after this shows up at all.
  3551. //
  3552. // Save the DAC Mask register.
  3553. //
  3554. hardwareStateHeader->PortValue[DAC_PIXEL_MASK_PORT-VGA_BASE_IO_PORT] =
  3555. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3556. DAC_PIXEL_MASK_PORT);
  3557. //
  3558. // Save the DAC Index register. Note that there is actually only one DAC
  3559. // Index register, which functions as either the Read Index or the Write
  3560. // Index as needed.
  3561. //
  3562. hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT-VGA_BASE_IO_PORT] =
  3563. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3564. DAC_ADDRESS_WRITE_PORT);
  3565. //
  3566. // Save the DAC read/write state. We determine if the DAC has been written
  3567. // to or read from at the current index 0, 1, or 2 times (the application
  3568. // is in the middle of reading or writing a DAC register triplet if the
  3569. // count is 1 or 2), and save enough info so we can restore things
  3570. // properly. The only hole is if the application writes to the Write Index,
  3571. // then reads from instead of writes to the Data register, or vice-versa,
  3572. // or if they do a partial read write, then never finish it.
  3573. // This is fairly ridiculous behavior, however, and anyway there's nothing
  3574. // we can do about it.
  3575. //
  3576. hardwareStateHeader->PortValue[DAC_STATE_PORT-VGA_BASE_IO_PORT] =
  3577. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3578. DAC_STATE_PORT);
  3579. if (hardwareStateHeader->PortValue[DAC_STATE_PORT-VGA_BASE_IO_PORT] == 3) {
  3580. //
  3581. // The DAC Read Index was written to last. Figure out how many reads
  3582. // have been done from the current index. We'll restart this on restore
  3583. // by setting the Read Index to the current index - 1 (the read index
  3584. // is one greater than the index being read), then doing the proper
  3585. // number of reads.
  3586. //
  3587. // Read the Data register once, and see if the index changes.
  3588. //
  3589. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3590. DAC_DATA_REG_PORT);
  3591. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3592. DAC_ADDRESS_WRITE_PORT) !=
  3593. hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT-VGA_BASE_IO_PORT]) {
  3594. //
  3595. // The DAC Index changed, so two reads had already been done from
  3596. // the current index. Store the count "2" in the upper nibble of
  3597. // the read/write state field.
  3598. //
  3599. hardwareStateHeader->PortValue[DAC_STATE_PORT-VGA_BASE_IO_PORT] |= 0x20;
  3600. } else {
  3601. //
  3602. // Read the Data register again, and see if the index changes.
  3603. //
  3604. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3605. DAC_DATA_REG_PORT);
  3606. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3607. DAC_ADDRESS_WRITE_PORT) !=
  3608. hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT-VGA_BASE_IO_PORT]) {
  3609. //
  3610. // The DAC Index changed, so one read had already been done
  3611. // from the current index. Store the count "1" in the upper
  3612. // nibble of the read/write state field.
  3613. //
  3614. hardwareStateHeader->PortValue[DAC_STATE_PORT-VGA_BASE_IO_PORT] |= 0x10;
  3615. }
  3616. //
  3617. // If neither 2 nor 1 reads had been done from the current index,
  3618. // then 0 reads were done, and we're all set, since the upper
  3619. // nibble of the read/write state field is already 0.
  3620. //
  3621. }
  3622. } else {
  3623. //
  3624. // The DAC Write Index was written to last. Figure out how many writes
  3625. // have been done to the current index. We'll restart this on restore
  3626. // by setting the Write Index to the proper index, then doing the
  3627. // proper number of writes. When we do the DAC register save, we'll
  3628. // read out the value that gets written (if there was a partial write
  3629. // in progress), so we can restore the proper data later. This will
  3630. // cause this current DAC location to be briefly wrong in the 1- and
  3631. // 2-bytes-written case (until the app finishes the write), but that's
  3632. // better than having the wrong DAC values written for good.
  3633. //
  3634. // Write the Data register once, and see if the index changes.
  3635. //
  3636. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3637. DAC_DATA_REG_PORT, 0);
  3638. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3639. DAC_ADDRESS_WRITE_PORT) !=
  3640. hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT-VGA_BASE_IO_PORT]) {
  3641. //
  3642. // The DAC Index changed, so two writes had already been done to
  3643. // the current index. Store the count "2" in the upper nibble of
  3644. // the read/write state field.
  3645. //
  3646. hardwareStateHeader->PortValue[DAC_STATE_PORT-VGA_BASE_IO_PORT] |= 0x20;
  3647. } else {
  3648. //
  3649. // Write the Data register again, and see if the index changes.
  3650. //
  3651. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3652. DAC_DATA_REG_PORT, 0);
  3653. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3654. DAC_ADDRESS_WRITE_PORT) !=
  3655. hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT-VGA_BASE_IO_PORT]) {
  3656. //
  3657. // The DAC Index changed, so one write had already been done
  3658. // to the current index. Store the count "1" in the upper
  3659. // nibble of the read/write state field.
  3660. //
  3661. hardwareStateHeader->PortValue[DAC_STATE_PORT-VGA_BASE_IO_PORT] |= 0x10;
  3662. }
  3663. //
  3664. // If neither 2 nor 1 writes had been done to the current index,
  3665. // then 0 writes were done, and we're all set.
  3666. //
  3667. }
  3668. }
  3669. //
  3670. // Now, read out the 256 18-bit DAC palette registers (256 RGB triplets),
  3671. // and blank the screen.
  3672. //
  3673. portValueDAC = (PUCHAR) hardwareStateHeader + VGA_BASIC_DAC_OFFSET;
  3674. //
  3675. // Read out DAC register 0, so we can set it to black.
  3676. //
  3677. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3678. DAC_ADDRESS_READ_PORT, 0);
  3679. *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3680. DAC_DATA_REG_PORT);
  3681. *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3682. DAC_DATA_REG_PORT);
  3683. *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3684. DAC_DATA_REG_PORT);
  3685. //
  3686. // Set DAC register 0 to display black.
  3687. //
  3688. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3689. DAC_ADDRESS_WRITE_PORT, 0);
  3690. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3691. DAC_DATA_REG_PORT, 0);
  3692. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3693. DAC_DATA_REG_PORT, 0);
  3694. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3695. DAC_DATA_REG_PORT, 0);
  3696. //
  3697. // Set the DAC mask register to force DAC register 0 to display all the
  3698. // time (this is the register we just set to display black). From now on,
  3699. // nothing but black will show up on the screen.
  3700. //
  3701. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3702. DAC_PIXEL_MASK_PORT, 0);
  3703. //
  3704. // Read out the Attribute Controller Index state, and deduce the Index/Data
  3705. // toggle state at the same time.
  3706. //
  3707. // Save the state of the Attribute Controller, both Index and Data,
  3708. // so we can test in which state the toggle currently is.
  3709. //
  3710. originalACIndex = hardwareStateHeader->PortValue[ATT_ADDRESS_PORT-VGA_BASE_IO_PORT] =
  3711. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3712. ATT_ADDRESS_PORT);
  3713. originalACData = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3714. ATT_DATA_READ_PORT);
  3715. //
  3716. // Sequencer Index.
  3717. //
  3718. hardwareStateHeader->PortValue[SEQ_ADDRESS_PORT-VGA_BASE_IO_PORT] =
  3719. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3720. SEQ_ADDRESS_PORT);
  3721. //
  3722. // Begin sync reset, just in case this is an SVGA and the currently
  3723. // indexed Attribute Controller register controls clocking stuff (a
  3724. // normal VGA won't require this).
  3725. //
  3726. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3727. SEQ_ADDRESS_PORT),
  3728. (USHORT) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8)));
  3729. //
  3730. // Now, write a different Index setting to the Attribute Controller, and
  3731. // see if the Index changes.
  3732. //
  3733. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3734. ATT_ADDRESS_PORT, (UCHAR) (originalACIndex ^ 0x10));
  3735. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3736. ATT_ADDRESS_PORT) == originalACIndex) {
  3737. //
  3738. // The Index didn't change, so the toggle was in the Data state.
  3739. //
  3740. hardwareStateHeader->AttribIndexDataState = 1;
  3741. //
  3742. // Restore the original Data state; we just corrupted it, and we need
  3743. // to read it out later; also, it may glitch the screen if not
  3744. // corrected. The toggle is already in the Index state.
  3745. //
  3746. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3747. ATT_ADDRESS_PORT, originalACIndex);
  3748. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3749. ATT_DATA_WRITE_PORT, originalACData);
  3750. } else {
  3751. //
  3752. // The Index did change, so the toggle was in the Index state.
  3753. // No need to restore anything, because the Data register didn't
  3754. // change, and we've already read out the Index register.
  3755. //
  3756. hardwareStateHeader->AttribIndexDataState = 0;
  3757. }
  3758. //
  3759. // End sync reset.
  3760. //
  3761. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3762. SEQ_ADDRESS_PORT),
  3763. (USHORT) (IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8)));
  3764. //
  3765. // Save the rest of the DAC registers.
  3766. // Set the DAC address port Index, then read out the DAC Data registers.
  3767. // Each three reads get Red, Green, and Blue components for that register.
  3768. //
  3769. // Read them one at a time due to problems on local bus machines.
  3770. //
  3771. for (i = 1; i < VGA_NUM_DAC_ENTRIES; i++) {
  3772. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3773. DAC_ADDRESS_READ_PORT, (UCHAR)i);
  3774. *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3775. DAC_DATA_REG_PORT);
  3776. *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3777. DAC_DATA_REG_PORT);
  3778. *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3779. DAC_DATA_REG_PORT);
  3780. }
  3781. //
  3782. // Is this color or mono ?
  3783. //
  3784. if (bIsColor) {
  3785. port = HwDeviceExtension->IOAddress + INPUT_STATUS_1_COLOR;
  3786. } else {
  3787. port = HwDeviceExtension->IOAddress + INPUT_STATUS_1_MONO;
  3788. }
  3789. //
  3790. // The Feature Control register is read from 3CA but written at 3BA/3DA.
  3791. //
  3792. if (bIsColor) {
  3793. hardwareStateHeader->PortValue[FEAT_CTRL_WRITE_PORT_COLOR-VGA_BASE_IO_PORT] =
  3794. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3795. FEAT_CTRL_READ_PORT);
  3796. } else {
  3797. hardwareStateHeader->PortValue[FEAT_CTRL_WRITE_PORT_MONO-VGA_BASE_IO_PORT] =
  3798. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3799. FEAT_CTRL_READ_PORT);
  3800. }
  3801. //
  3802. // CRT Controller Index.
  3803. //
  3804. if (bIsColor) {
  3805. hardwareStateHeader->PortValue[CRTC_ADDRESS_PORT_COLOR-VGA_BASE_IO_PORT] =
  3806. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3807. CRTC_ADDRESS_PORT_COLOR);
  3808. } else {
  3809. hardwareStateHeader->PortValue[CRTC_ADDRESS_PORT_MONO-VGA_BASE_IO_PORT] =
  3810. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3811. CRTC_ADDRESS_PORT_MONO);
  3812. }
  3813. //
  3814. // Graphics Controller Index.
  3815. //
  3816. hardwareStateHeader->PortValue[GRAPH_ADDRESS_PORT-VGA_BASE_IO_PORT] =
  3817. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3818. GRAPH_ADDRESS_PORT);
  3819. //
  3820. // Sequencer indexed registers.
  3821. //
  3822. portValue = ((PUCHAR) hardwareStateHeader) + VGA_BASIC_SEQUENCER_OFFSET;
  3823. for (i = 0; i < VGA_NUM_SEQUENCER_PORTS; i++) {
  3824. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3825. SEQ_ADDRESS_PORT, (UCHAR)i);
  3826. *portValue++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3827. SEQ_DATA_PORT);
  3828. }
  3829. //
  3830. // Save extended sequencer registers.
  3831. //
  3832. #ifdef EXTENDED_REGISTER_SAVE_RESTORE
  3833. portValue = ((PUCHAR) hardwareStateHeader) + VGA_EXT_SEQUENCER_OFFSET;
  3834. if ((HwDeviceExtension->ChipType != CL6410) &&
  3835. (HwDeviceExtension->ChipType != CL6420))
  3836. {
  3837. //
  3838. // No extended sequencer registers for the CL64xx
  3839. //
  3840. for (i = CL542x_SEQUENCER_EXT_START;
  3841. i <= CL542x_SEQUENCER_EXT_END;
  3842. i++) {
  3843. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3844. SEQ_ADDRESS_PORT, (UCHAR)i);
  3845. *portValue++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3846. SEQ_DATA_PORT);
  3847. }
  3848. }
  3849. #endif
  3850. //
  3851. // CRT Controller indexed registers.
  3852. //
  3853. //
  3854. // Remember the state of CRTC register 3, then force bit 7
  3855. // to 1 so we will read back the Vertical Retrace start and
  3856. // end registers rather than the light pen info.
  3857. //
  3858. if (bIsColor) {
  3859. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3860. CRTC_ADDRESS_PORT_COLOR, 3);
  3861. ucCRTC03 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3862. CRTC_DATA_PORT_COLOR);
  3863. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3864. CRTC_DATA_PORT_COLOR, (UCHAR) (ucCRTC03 | 0x80));
  3865. } else {
  3866. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3867. CRTC_ADDRESS_PORT_MONO, 3);
  3868. ucCRTC03 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3869. CRTC_DATA_PORT_MONO);
  3870. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3871. CRTC_DATA_PORT_MONO, (UCHAR) (ucCRTC03 | 0x80));
  3872. }
  3873. portValue = (PUCHAR) hardwareStateHeader + VGA_BASIC_CRTC_OFFSET;
  3874. for (i = 0; i < VGA_NUM_CRTC_PORTS; i++) {
  3875. if (bIsColor) {
  3876. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3877. CRTC_ADDRESS_PORT_COLOR, (UCHAR)i);
  3878. *portValue++ =
  3879. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3880. CRTC_DATA_PORT_COLOR);
  3881. }
  3882. else {
  3883. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3884. CRTC_ADDRESS_PORT_MONO, (UCHAR)i);
  3885. *portValue++ =
  3886. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3887. CRTC_DATA_PORT_MONO);
  3888. }
  3889. }
  3890. portValue = (PUCHAR) hardwareStateHeader + VGA_BASIC_CRTC_OFFSET;
  3891. portValue[3] = ucCRTC03;
  3892. //
  3893. // Save extended crtc registers.
  3894. //
  3895. #ifdef EXTENDED_REGISTER_SAVE_RESTORE
  3896. portValue = (PUCHAR) hardwareStateHeader + VGA_EXT_CRTC_OFFSET;
  3897. if ((HwDeviceExtension->ChipType != CL6410) &&
  3898. (HwDeviceExtension->ChipType != CL6420))
  3899. {
  3900. //
  3901. // No CRTC Extensions in CL64xx chipset
  3902. //
  3903. for (i = CL542x_CRTC_EXT_START; i <= CL542x_CRTC_EXT_END; i++) {
  3904. if (bIsColor) {
  3905. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3906. CRTC_ADDRESS_PORT_COLOR, (UCHAR)i);
  3907. *portValue++ =
  3908. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3909. CRTC_DATA_PORT_COLOR);
  3910. } else {
  3911. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3912. CRTC_ADDRESS_PORT_MONO, (UCHAR)i);
  3913. *portValue++ =
  3914. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3915. CRTC_DATA_PORT_MONO);
  3916. }
  3917. }
  3918. }
  3919. /* myf2, crus
  3920. if (HwDeviceExtension->ChipType & CL755x)
  3921. {
  3922. for (i = 0x81; i <= 0x91; i++)
  3923. {
  3924. if (bIsColor)
  3925. {
  3926. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3927. CRTC_ADDRESS_PORT_COLOR, (UCHAR)i);
  3928. *portValue++ =
  3929. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3930. CRTC_DATA_PORT_COLOR);
  3931. } else {
  3932. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3933. CRTC_ADDRESS_PORT_MONO, (UCHAR)i);
  3934. *portValue++ =
  3935. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3936. CRTC_DATA_PORT_MONO);
  3937. }
  3938. }
  3939. }
  3940. crus, myf2 */
  3941. //if ((HwDeviceExtension->ChipType & CL754x) || //myf32
  3942. // (HwDeviceExtension->ChipType & CL755x) || //myf32
  3943. // (HwDeviceExtension->ChipType == CL756x)) {
  3944. // {
  3945. // NordicSaveRegs(HwDeviceExtension,
  3946. // (PUSHORT)hardwareStateHeader + sizeof(NORDIC_REG_SAVE_BUF));
  3947. // }
  3948. #endif
  3949. //
  3950. // Graphics Controller indexed registers.
  3951. //
  3952. portValue = (PUCHAR) hardwareStateHeader + VGA_BASIC_GRAPH_CONT_OFFSET;
  3953. for (i = 0; i < VGA_NUM_GRAPH_CONT_PORTS; i++) {
  3954. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3955. GRAPH_ADDRESS_PORT, (UCHAR)i);
  3956. *portValue++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3957. GRAPH_DATA_PORT);
  3958. }
  3959. //
  3960. // Save extended graphics controller registers.
  3961. //
  3962. #ifdef EXTENDED_REGISTER_SAVE_RESTORE
  3963. portValue = (PUCHAR) hardwareStateHeader + VGA_EXT_GRAPH_CONT_OFFSET;
  3964. if ((HwDeviceExtension->ChipType != CL6410) &&
  3965. (HwDeviceExtension->ChipType != CL6420))
  3966. {
  3967. for (i = CL542x_GRAPH_EXT_START; i <= CL542x_GRAPH_EXT_END; i++) {
  3968. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3969. GRAPH_ADDRESS_PORT, (UCHAR)i);
  3970. *portValue++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3971. GRAPH_DATA_PORT);
  3972. }
  3973. } else { // must be a CL64xx
  3974. for (i = CL64xx_GRAPH_EXT_START; i <= CL64xx_GRAPH_EXT_END; i++) {
  3975. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3976. GRAPH_ADDRESS_PORT, (UCHAR)i);
  3977. *portValue++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3978. GRAPH_DATA_PORT);
  3979. }
  3980. }
  3981. #endif
  3982. //
  3983. // Attribute Controller indexed registers.
  3984. //
  3985. portValue = (PUCHAR) hardwareStateHeader + VGA_BASIC_ATTRIB_CONT_OFFSET;
  3986. //
  3987. // For each indexed AC register, reset the flip-flop for reading the
  3988. // attribute register, then write the desired index to the AC Index,
  3989. // then read the value of the indexed register from the AC Data register.
  3990. //
  3991. for (i = 0; i < VGA_NUM_ATTRIB_CONT_PORTS; i++) {
  3992. if (bIsColor) {
  3993. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3994. INPUT_STATUS_1_COLOR);
  3995. } else {
  3996. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3997. INPUT_STATUS_1_MONO);
  3998. }
  3999. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4000. ATT_ADDRESS_PORT, (UCHAR)i);
  4001. *portValue++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  4002. ATT_DATA_READ_PORT);
  4003. }
  4004. //
  4005. // Save the latches. This destroys one byte of display memory in each
  4006. // plane, which is unfortunate but unavoidable. Chips that provide
  4007. // a way to read back the latches can avoid this problem.
  4008. //
  4009. // Set up the VGA's hardware so we can write the latches, then read them
  4010. // back.
  4011. //
  4012. //
  4013. // Begin sync reset.
  4014. //
  4015. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  4016. SEQ_ADDRESS_PORT),
  4017. (USHORT) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8)));
  4018. //
  4019. // Set the Miscellaneous register to make sure we can access video RAM.
  4020. //
  4021. portIO = MISC_OUTPUT_REG_WRITE_PORT ;
  4022. value = (UCHAR) (hardwareStateHeader->
  4023. PortValue[MISC_OUTPUT_REG_WRITE_PORT-VGA_BASE_IO_PORT] |
  4024. 0x02) ;
  4025. IOWaitDisplEnableThenWrite ( HwDeviceExtension,
  4026. portIO,
  4027. value ) ;
  4028. //
  4029. // Turn off Chain mode and map display memory at A0000 for 64K.
  4030. //
  4031. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4032. GRAPH_ADDRESS_PORT, IND_GRAPH_MISC);
  4033. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4034. GRAPH_DATA_PORT,
  4035. (UCHAR) ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  4036. GRAPH_DATA_PORT) & 0xF1) | 0x04));
  4037. //
  4038. // Turn off Chain4 mode and odd/even.
  4039. //
  4040. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4041. SEQ_ADDRESS_PORT, IND_MEMORY_MODE);
  4042. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4043. SEQ_DATA_PORT,
  4044. (UCHAR) ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  4045. SEQ_DATA_PORT) & 0xF3) | 0x04));
  4046. //
  4047. // End sync reset.
  4048. //
  4049. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  4050. SEQ_ADDRESS_PORT),
  4051. (USHORT) (IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8)));
  4052. //
  4053. // Set the Map Mask to write to all planes.
  4054. //
  4055. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  4056. SEQ_ADDRESS_PORT), (USHORT) (IND_MAP_MASK + (0x0F << 8)));
  4057. //
  4058. // Set the write mode to 0, the read mode to 0, and turn off odd/even.
  4059. //
  4060. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4061. GRAPH_ADDRESS_PORT, IND_GRAPH_MODE);
  4062. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4063. GRAPH_DATA_PORT,
  4064. (UCHAR) ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  4065. GRAPH_DATA_PORT) & 0xE4) | 0x01));
  4066. //
  4067. // Point to the last byte of display memory.
  4068. //
  4069. pScreen = (PUCHAR) HwDeviceExtension->VideoMemoryAddress +
  4070. VGA_PLANE_SIZE - 1;
  4071. //
  4072. // Write the latches to the last byte of display memory.
  4073. //
  4074. VideoPortWriteRegisterUchar(pScreen, 0);
  4075. //
  4076. // Cycle through the four planes, reading the latch data from each plane.
  4077. //
  4078. //
  4079. // Point the Graphics Controller Index to the Read Map register.
  4080. //
  4081. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4082. GRAPH_ADDRESS_PORT, IND_READ_MAP);
  4083. portValue = (PUCHAR) hardwareStateHeader + VGA_BASIC_LATCHES_OFFSET;
  4084. for (i=0; i<4; i++) {
  4085. //
  4086. // Set the Read Map for the current plane.
  4087. //
  4088. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4089. GRAPH_DATA_PORT, (UCHAR)i);
  4090. //
  4091. // Read the latched data we've written to memory.
  4092. //
  4093. *portValue++ = VideoPortReadRegisterUchar(pScreen);
  4094. }
  4095. //
  4096. // Set the VDM flags
  4097. // We are a standard VGA, and then check if we have unemulated state.
  4098. //
  4099. hardwareStateHeader->VGAStateFlags = 0;
  4100. #ifdef EXTENDED_REGISTER_SAVE_RESTORE
  4101. hardwareStateHeader->VGAStateFlags |= VIDEO_STATE_NON_STANDARD_VGA;
  4102. #endif
  4103. if (HwDeviceExtension->TrappedValidatorCount) {
  4104. hardwareStateHeader->VGAStateFlags |= VIDEO_STATE_UNEMULATED_VGA_STATE;
  4105. //
  4106. // Save the VDM Emulator data
  4107. // No need to save the state of the seuencer port register for our
  4108. // emulated data since it may change when we come back. It will be
  4109. // recomputed.
  4110. //
  4111. hardwareStateHeader->ExtendedValidatorStateOffset = VGA_VALIDATOR_OFFSET;
  4112. VideoPortMoveMemory(((PUCHAR) (hardwareStateHeader)) +
  4113. hardwareStateHeader->ExtendedValidatorStateOffset,
  4114. &(HwDeviceExtension->TrappedValidatorCount),
  4115. VGA_VALIDATOR_AREA_SIZE);
  4116. } else {
  4117. hardwareStateHeader->ExtendedValidatorStateOffset = 0;
  4118. }
  4119. //
  4120. // Set the size of each plane.
  4121. //
  4122. hardwareStateHeader->PlaneLength = VGA_PLANE_SIZE;
  4123. //
  4124. // Store all the offsets for the planes in the structure.
  4125. //
  4126. hardwareStateHeader->Plane1Offset = VGA_PLANE_0_OFFSET;
  4127. hardwareStateHeader->Plane2Offset = VGA_PLANE_1_OFFSET;
  4128. hardwareStateHeader->Plane3Offset = VGA_PLANE_2_OFFSET;
  4129. hardwareStateHeader->Plane4Offset = VGA_PLANE_3_OFFSET;
  4130. //
  4131. // Now copy the contents of video VRAM into the buffer.
  4132. //
  4133. // The VGA hardware is already set up so that video memory is readable;
  4134. // we already turned off Chain mode, mapped in at A0000, turned off Chain4,
  4135. // turned off odd/even, and set read mode 0 when we saved the latches.
  4136. //
  4137. // Point the Graphics Controller Index to the Read Map register.
  4138. //
  4139. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4140. GRAPH_ADDRESS_PORT, IND_READ_MAP);
  4141. //
  4142. // Point to the save area for the first plane.
  4143. //
  4144. bufferPointer = ((PUCHAR) (hardwareStateHeader)) +
  4145. hardwareStateHeader->Plane1Offset;
  4146. //
  4147. // Save the four planes consecutively.
  4148. //
  4149. for (i = 0; i < 4; i++) {
  4150. //
  4151. // Set the Read Map to select the plane we want to save next.
  4152. //
  4153. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4154. GRAPH_DATA_PORT, (UCHAR)i);
  4155. //
  4156. // Copy this plane into the buffer.
  4157. //
  4158. // Some cirrus cards have a bug where DWORD reads from
  4159. // the frame buffer fail. When we restore the video
  4160. // memory, fonts are corrupted.
  4161. //
  4162. #if 1
  4163. {
  4164. int c;
  4165. for (c = 0; c < VGA_PLANE_SIZE / 2; c++)
  4166. {
  4167. ((PUSHORT)bufferPointer)[c] =
  4168. ((PUSHORT)(HwDeviceExtension->VideoMemoryAddress))[c];
  4169. }
  4170. }
  4171. #else
  4172. VideoPortMoveMemory(bufferPointer,
  4173. (PUCHAR) HwDeviceExtension->VideoMemoryAddress,
  4174. VGA_PLANE_SIZE);
  4175. #endif
  4176. //
  4177. // Point to the next plane's save area.
  4178. //
  4179. bufferPointer += VGA_PLANE_SIZE;
  4180. }
  4181. return NO_ERROR;
  4182. } // end VgaSaveHardwareState()
  4183. //---------------------------------------------------------------------------
  4184. VP_STATUS
  4185. VgaGetBankSelectCode(
  4186. PHW_DEVICE_EXTENSION HwDeviceExtension,
  4187. PVIDEO_BANK_SELECT BankSelect,
  4188. ULONG BankSelectSize,
  4189. PULONG OutputSize
  4190. )
  4191. /*++
  4192. Routine Description:
  4193. Returns information needed in order for caller to implement bank
  4194. management.
  4195. Arguments:
  4196. HwDeviceExtension - Pointer to the miniport driver's device extension.
  4197. BankSelect - Pointer to a VIDEO_BANK_SELECT structure in which the bank
  4198. select data will be returned (output buffer).
  4199. BankSelectSize - Length of the output buffer supplied by the user.
  4200. OutputSize - Pointer to a variable in which to return the actual size of
  4201. the data returned in the output buffer.
  4202. Return Value:
  4203. NO_ERROR - information returned successfully
  4204. ERROR_MORE_DATA - output buffer not large enough to hold all info (but
  4205. Size is returned, so caller can tell how large a buffer to allocate)
  4206. ERROR_INSUFFICIENT_BUFFER - output buffer not large enough to return
  4207. any useful data
  4208. ERROR_INVALID_PARAMETER - invalid video mode selection
  4209. --*/
  4210. {
  4211. #ifdef _X86_
  4212. ULONG codeSize;
  4213. ULONG codePlanarSize;
  4214. ULONG codeEnablePlanarSize;
  4215. ULONG codeDisablePlanarSize;
  4216. PUCHAR pCodeDest;
  4217. PUCHAR pCodeBank;
  4218. PUCHAR pCodePlanarBank;
  4219. PUCHAR pCodeEnablePlanar;
  4220. PUCHAR pCodeDisablePlanar;
  4221. ULONG AdapterType = HwDeviceExtension->ChipType;
  4222. PVIDEOMODE pMode = HwDeviceExtension->CurrentMode;
  4223. //
  4224. // check if a mode has been set
  4225. //
  4226. if (HwDeviceExtension->CurrentMode == NULL) {
  4227. return ERROR_INVALID_FUNCTION;
  4228. }
  4229. //
  4230. // The minimum passed buffer size is a VIDEO_BANK_SELECT
  4231. // structure, so that we can return the required size; we can't do
  4232. // anything if we don't have at least that much buffer.
  4233. //
  4234. if (BankSelectSize < sizeof(VIDEO_BANK_SELECT)) {
  4235. return ERROR_INSUFFICIENT_BUFFER;
  4236. }
  4237. //
  4238. // Determine the banking type, and set whether any banking is actually
  4239. // supported in this mode.
  4240. //
  4241. BankSelect->BankingFlags = 0;
  4242. codeSize = 0;
  4243. codePlanarSize = 0;
  4244. codeEnablePlanarSize = 0;
  4245. codeDisablePlanarSize = 0;
  4246. pCodeBank = NULL;
  4247. switch(pMode->banktype) {
  4248. case NoBanking:
  4249. BankSelect->BankingType = VideoNotBanked;
  4250. BankSelect->Granularity = 0;
  4251. break;
  4252. case PlanarHCBanking:
  4253. BankSelect->BankingFlags = PLANAR_HC; // planar mode supported
  4254. #if ONE_64K_BANK
  4255. //
  4256. // The Cirrus Logic VGA's support one 64K read/write bank.
  4257. //
  4258. BankSelect->PlanarHCBankingType = VideoBanked1RW;
  4259. BankSelect->PlanarHCGranularity = 0x10000; // 64K bank start adjustment
  4260. // in planar HC mode as well
  4261. #endif
  4262. #if TWO_32K_BANKS
  4263. //
  4264. // The Cirrus Logic VGA's support two 32K read/write banks.
  4265. //
  4266. BankSelect->PlanarHCBankingType = VideoBanked2RW;
  4267. BankSelect->PlanarHCGranularity = 0x8000; // 32K bank start adjustment
  4268. // in planar HC mode as well
  4269. #endif
  4270. // 64K bank start adjustment in planar HC mode as well
  4271. if ((HwDeviceExtension->ChipType != CL6410) &&
  4272. (HwDeviceExtension->ChipType != CL6420))
  4273. {
  4274. if ((HwDeviceExtension->ChipType != CL542x) &&
  4275. (HwDeviceExtension->ChipType != CL6245))
  4276. {
  4277. codePlanarSize = ((ULONG)&CL543xPlanarHCBankSwitchEnd) -
  4278. ((ULONG)&CL543xPlanarHCBankSwitchStart);
  4279. pCodePlanarBank = &CL543xPlanarHCBankSwitchStart;
  4280. }
  4281. else
  4282. {
  4283. codePlanarSize = ((ULONG)&CL542xPlanarHCBankSwitchEnd) -
  4284. ((ULONG)&CL542xPlanarHCBankSwitchStart);
  4285. pCodePlanarBank = &CL542xPlanarHCBankSwitchStart;
  4286. }
  4287. codeEnablePlanarSize = ((ULONG)&CL542xEnablePlanarHCEnd) -
  4288. ((ULONG)&CL542xEnablePlanarHCStart);
  4289. codeDisablePlanarSize = ((ULONG)&CL542xDisablePlanarHCEnd) -
  4290. ((ULONG)&CL542xDisablePlanarHCStart);
  4291. pCodeEnablePlanar = &CL542xEnablePlanarHCStart;
  4292. pCodeDisablePlanar = &CL542xDisablePlanarHCStart;
  4293. }
  4294. else
  4295. { // must be a CL64xx product
  4296. codePlanarSize = ((ULONG)&CL64xxPlanarHCBankSwitchEnd) -
  4297. ((ULONG)&CL64xxPlanarHCBankSwitchStart);
  4298. codeEnablePlanarSize = ((ULONG)&CL64xxEnablePlanarHCEnd) -
  4299. ((ULONG)&CL64xxEnablePlanarHCStart);
  4300. codeDisablePlanarSize = ((ULONG)&CL64xxDisablePlanarHCEnd) -
  4301. ((ULONG)&CL64xxDisablePlanarHCStart);
  4302. pCodePlanarBank = &CL64xxPlanarHCBankSwitchStart;
  4303. pCodeEnablePlanar = &CL64xxEnablePlanarHCStart;
  4304. pCodeDisablePlanar = &CL64xxDisablePlanarHCStart;
  4305. }
  4306. //
  4307. // Fall through to the normal banking case
  4308. //
  4309. case NormalBanking:
  4310. #if ONE_64K_BANK
  4311. //
  4312. // The Cirrus Logic VGA's support one 64K read/write bank.
  4313. //
  4314. BankSelect->BankingType = VideoBanked1RW;
  4315. BankSelect->Granularity = 0x10000;
  4316. #endif
  4317. #if TWO_32K_BANKS
  4318. //
  4319. // The Cirrus Logic VGA's support two 32K read/write banks.
  4320. //
  4321. BankSelect->BankingType = VideoBanked2RW;
  4322. BankSelect->Granularity = 0x8000;
  4323. #endif
  4324. if ((AdapterType == CL542x) ||
  4325. (AdapterType == CL6245))
  4326. {
  4327. codeSize = ((ULONG)&CL542xBankSwitchEnd) -
  4328. ((ULONG)&CL542xBankSwitchStart);
  4329. pCodeBank = &CL542xBankSwitchStart;
  4330. }
  4331. else if ((AdapterType == CL6410) ||
  4332. (AdapterType == CL6420))
  4333. {
  4334. codeSize = ((ULONG)&CL64xxBankSwitchEnd) -
  4335. ((ULONG)&CL64xxBankSwitchStart);
  4336. pCodeBank = &CL64xxBankSwitchStart;
  4337. }
  4338. else
  4339. {
  4340. codeSize = ((ULONG)&CL543xBankSwitchEnd) -
  4341. ((ULONG)&CL543xBankSwitchStart);
  4342. pCodeBank = &CL543xBankSwitchStart;
  4343. }
  4344. break;
  4345. }
  4346. //
  4347. // Size of banking info.
  4348. //
  4349. BankSelect->Size = sizeof(VIDEO_BANK_SELECT) + codeSize;
  4350. if (BankSelect->BankingFlags & PLANAR_HC) {
  4351. BankSelect->Size += codePlanarSize + codeEnablePlanarSize +
  4352. codeDisablePlanarSize;
  4353. }
  4354. //
  4355. // This serves an a ID for the version of the structure we're using.
  4356. //
  4357. BankSelect->Length = sizeof(VIDEO_BANK_SELECT);
  4358. //
  4359. // If the buffer isn't big enough to hold all info, just return
  4360. // ERROR_MORE_DATA; Size is already set.
  4361. //
  4362. if (BankSelectSize < BankSelect->Size ) {
  4363. //
  4364. // We're returning only the VIDEO_BANK_SELECT structure.
  4365. //
  4366. *OutputSize = sizeof(VIDEO_BANK_SELECT);
  4367. return ERROR_MORE_DATA;
  4368. }
  4369. //
  4370. // There's room enough for everything, so fill in all fields in
  4371. // VIDEO_BANK_SELECT. (All fields are always returned; the caller can
  4372. // just choose to ignore them, based on BankingFlags and BankingType.)
  4373. //
  4374. BankSelect->BitmapWidthInBytes = pMode->wbytes;
  4375. BankSelect->BitmapSize = pMode->sbytes;
  4376. //
  4377. // Copy all banking code into the output buffer.
  4378. //
  4379. pCodeDest = (PUCHAR)BankSelect + sizeof(VIDEO_BANK_SELECT);
  4380. if (pCodeBank != NULL) {
  4381. BankSelect->CodeOffset = pCodeDest - (PUCHAR)BankSelect;
  4382. VideoPortMoveMemory(pCodeDest,
  4383. pCodeBank,
  4384. codeSize);
  4385. pCodeDest += codeSize;
  4386. }
  4387. if (BankSelect->BankingFlags & PLANAR_HC) {
  4388. //
  4389. // Copy appropriate high-color planar Bank Switch code:
  4390. //
  4391. BankSelect->PlanarHCBankCodeOffset = pCodeDest - (PUCHAR)BankSelect;
  4392. VideoPortMoveMemory(pCodeDest,
  4393. pCodePlanarBank,
  4394. codePlanarSize);
  4395. pCodeDest += codePlanarSize;
  4396. //
  4397. // Copy high-color planar bank mode Enable code:
  4398. //
  4399. BankSelect->PlanarHCEnableCodeOffset = pCodeDest - (PUCHAR)BankSelect;
  4400. VideoPortMoveMemory(pCodeDest,
  4401. pCodeEnablePlanar,
  4402. codeEnablePlanarSize);
  4403. pCodeDest += codeEnablePlanarSize;
  4404. //
  4405. // Copy high-color planar bank mode Disable code:
  4406. //
  4407. BankSelect->PlanarHCDisableCodeOffset = pCodeDest - (PUCHAR)BankSelect;
  4408. VideoPortMoveMemory(pCodeDest,
  4409. pCodeDisablePlanar,
  4410. codeDisablePlanarSize);
  4411. }
  4412. //
  4413. // Number of bytes we're returning is the full banking info size.
  4414. //
  4415. *OutputSize = BankSelect->Size;
  4416. return NO_ERROR;
  4417. #else
  4418. //
  4419. // This function is only defined for x86
  4420. //
  4421. return ERROR_INVALID_FUNCTION;
  4422. #endif
  4423. } // end VgaGetBankSelectCode()
  4424. //---------------------------------------------------------------------------
  4425. VP_STATUS
  4426. VgaValidatorUcharEntry(
  4427. ULONG_PTR Context,
  4428. ULONG Port,
  4429. UCHAR AccessMode,
  4430. PUCHAR Data
  4431. )
  4432. /*++
  4433. Routine Description:
  4434. Entry point into the validator for byte I/O operations.
  4435. The entry point will be called whenever a byte operation was performed
  4436. by a DOS application on one of the specified Video ports. The kernel
  4437. emulator will forward these requests.
  4438. Arguments:
  4439. Context - Context value that is passed to each call made to the validator
  4440. function. This is the value the miniport driver specified in the
  4441. MiniportConfigInfo->EmulatorAccessEntriesContext.
  4442. Port - Port on which the operation is to be performed.
  4443. AccessMode - Determines if it is a read or write operation.
  4444. Data - Pointer to a variable containing the data to be written or a
  4445. variable into which the read data should be stored.
  4446. Return Value:
  4447. NO_ERROR.
  4448. --*/
  4449. {
  4450. PHW_DEVICE_EXTENSION hwDeviceExtension = (PHW_DEVICE_EXTENSION) Context;
  4451. PHW_DEVICE_EXTENSION HwDeviceExtension = (PHW_DEVICE_EXTENSION) Context;
  4452. ULONG endEmulation;
  4453. UCHAR temp;
  4454. UCHAR tempB ;
  4455. ULONG portIO ;
  4456. if (hwDeviceExtension->TrappedValidatorCount) {
  4457. //
  4458. // If we are processing a WRITE instruction, then store it in the
  4459. // playback buffer. If the buffer is full, then play it back right
  4460. // away, end sync reset and reinitialize the buffer with a sync
  4461. // reset instruction.
  4462. //
  4463. // If we have a READ, we must flush the buffer (which has the side
  4464. // effect of starting SyncReset), perform the read operation, stop
  4465. // sync reset, and put back a sync reset instruction in the buffer
  4466. // so we can go on appropriately
  4467. //
  4468. if (AccessMode & EMULATOR_WRITE_ACCESS) {
  4469. //
  4470. // Make sure Bit 3 of the Miscellaneous register is always 0.
  4471. // If it is 1 it could select a non-existent clock, and kill the
  4472. // system
  4473. //
  4474. if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
  4475. *Data &= 0xF7;
  4476. }
  4477. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4478. TrappedValidatorCount].Port = Port;
  4479. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4480. TrappedValidatorCount].AccessType = VGA_VALIDATOR_UCHAR_ACCESS;
  4481. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4482. TrappedValidatorCount].Data = *Data;
  4483. hwDeviceExtension->TrappedValidatorCount++;
  4484. //
  4485. // Check to see if this instruction was ending sync reset.
  4486. // If it did, we must flush the buffer and reset the trapped
  4487. // IO ports to the minimal set.
  4488. //
  4489. if ( (Port == SEQ_DATA_PORT) &&
  4490. ((*Data & END_SYNC_RESET_VALUE) == END_SYNC_RESET_VALUE) &&
  4491. (hwDeviceExtension->SequencerAddressValue == IND_SYNC_RESET)) {
  4492. endEmulation = 1;
  4493. } else {
  4494. //
  4495. // If we are accessing the seq address port, keep track of the
  4496. // data value
  4497. //
  4498. if (Port == SEQ_ADDRESS_PORT) {
  4499. hwDeviceExtension->SequencerAddressValue = *Data;
  4500. }
  4501. //
  4502. // If the buffer is not full, then just return right away.
  4503. //
  4504. if (hwDeviceExtension->TrappedValidatorCount <
  4505. VGA_MAX_VALIDATOR_DATA - 1) {
  4506. return NO_ERROR;
  4507. }
  4508. endEmulation = 0;
  4509. }
  4510. }
  4511. //
  4512. // We are either in a READ path or a WRITE path that caused a
  4513. // a full buffer. So flush the buffer either way.
  4514. //
  4515. // To do this put an END_SYNC_RESET at the end since we want to make
  4516. // the buffer is ended sync reset ended.
  4517. //
  4518. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4519. TrappedValidatorCount].Port = SEQ_ADDRESS_PORT;
  4520. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4521. TrappedValidatorCount].AccessType = VGA_VALIDATOR_USHORT_ACCESS;
  4522. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4523. TrappedValidatorCount].Data = (USHORT) (IND_SYNC_RESET +
  4524. (END_SYNC_RESET_VALUE << 8));
  4525. hwDeviceExtension->TrappedValidatorCount++;
  4526. VideoPortSynchronizeExecution(hwDeviceExtension,
  4527. VpHighPriority,
  4528. (PMINIPORT_SYNCHRONIZE_ROUTINE)
  4529. VgaPlaybackValidatorData,
  4530. hwDeviceExtension);
  4531. //
  4532. // Write back the real value of the sequencer address port.
  4533. //
  4534. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  4535. SEQ_ADDRESS_PORT,
  4536. (UCHAR) hwDeviceExtension->SequencerAddressValue);
  4537. //
  4538. // If we are in a READ path, read the data
  4539. //
  4540. if (AccessMode & EMULATOR_READ_ACCESS) {
  4541. *Data = VideoPortReadPortUchar(hwDeviceExtension->IOAddress + Port);
  4542. endEmulation = 0;
  4543. }
  4544. //
  4545. // If we are ending emulation, reset trapping to the minimal amount
  4546. // and exit.
  4547. //
  4548. if (endEmulation) {
  4549. VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
  4550. NUM_MINIMAL_VGA_VALIDATOR_ACCESS_RANGE,
  4551. MinimalVgaValidatorAccessRange);
  4552. return NO_ERROR;
  4553. }
  4554. //
  4555. // For both cases, put back a START_SYNC_RESET in the buffer.
  4556. //
  4557. hwDeviceExtension->TrappedValidatorCount = 1;
  4558. hwDeviceExtension->TrappedValidatorData[0].Port = SEQ_ADDRESS_PORT;
  4559. hwDeviceExtension->TrappedValidatorData[0].AccessType =
  4560. VGA_VALIDATOR_USHORT_ACCESS;
  4561. hwDeviceExtension->TrappedValidatorData[0].Data =
  4562. (ULONG) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8));
  4563. } else {
  4564. //
  4565. // Nothing trapped.
  4566. // Lets check is the IO is trying to do something that would require
  4567. // us to stop trapping
  4568. //
  4569. if (AccessMode & EMULATOR_WRITE_ACCESS) {
  4570. //
  4571. // Make sure Bit 3 of the Miscelaneous register is always 0.
  4572. // If it is 1 it could select a non-existant clock, and kill the
  4573. // system
  4574. //
  4575. if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
  4576. temp = VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
  4577. SEQ_ADDRESS_PORT);
  4578. VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
  4579. SEQ_ADDRESS_PORT),
  4580. (USHORT) (IND_SYNC_RESET +
  4581. (START_SYNC_RESET_VALUE << 8)));
  4582. tempB = (UCHAR) (*Data & 0xF7) ;
  4583. portIO = Port ;
  4584. IOWaitDisplEnableThenWrite ( hwDeviceExtension,
  4585. portIO,
  4586. tempB ) ;
  4587. VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
  4588. SEQ_ADDRESS_PORT),
  4589. (USHORT) (IND_SYNC_RESET +
  4590. (END_SYNC_RESET_VALUE << 8)));
  4591. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  4592. SEQ_ADDRESS_PORT,
  4593. temp);
  4594. return NO_ERROR;
  4595. }
  4596. //
  4597. // If we get an access to the sequencer register, start trapping.
  4598. //
  4599. if ( (Port == SEQ_DATA_PORT) &&
  4600. ((*Data & END_SYNC_RESET_VALUE) != END_SYNC_RESET_VALUE) &&
  4601. (VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
  4602. SEQ_ADDRESS_PORT) == IND_SYNC_RESET)) {
  4603. VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
  4604. NUM_FULL_VGA_VALIDATOR_ACCESS_RANGE,
  4605. FullVgaValidatorAccessRange);
  4606. hwDeviceExtension->TrappedValidatorCount = 1;
  4607. hwDeviceExtension->TrappedValidatorData[0].Port = Port;
  4608. hwDeviceExtension->TrappedValidatorData[0].AccessType =
  4609. VGA_VALIDATOR_UCHAR_ACCESS;
  4610. hwDeviceExtension->TrappedValidatorData[0].Data = *Data;
  4611. //
  4612. // Start keeping track of the state of the sequencer port.
  4613. //
  4614. hwDeviceExtension->SequencerAddressValue = IND_SYNC_RESET;
  4615. } else {
  4616. VideoPortWritePortUchar(hwDeviceExtension->IOAddress + Port,
  4617. *Data);
  4618. }
  4619. } else {
  4620. *Data = VideoPortReadPortUchar(hwDeviceExtension->IOAddress + Port);
  4621. }
  4622. }
  4623. return NO_ERROR;
  4624. } // end VgaValidatorUcharEntry()
  4625. //---------------------------------------------------------------------------
  4626. VP_STATUS
  4627. VgaValidatorUshortEntry(
  4628. ULONG_PTR Context,
  4629. ULONG Port,
  4630. UCHAR AccessMode,
  4631. PUSHORT Data
  4632. )
  4633. /*++
  4634. Routine Description:
  4635. Entry point into the validator for word I/O operations.
  4636. The entry point will be called whenever a byte operation was performed
  4637. by a DOS application on one of the specified Video ports. The kernel
  4638. emulator will forward these requests.
  4639. Arguments:
  4640. Context - Context value that is passed to each call made to the validator
  4641. function. This is the value the miniport driver specified in the
  4642. MiniportConfigInfo->EmulatorAccessEntriesContext.
  4643. Port - Port on which the operation is to be performed.
  4644. AccessMode - Determines if it is a read or write operation.
  4645. Data - Pointer to a variable containing the data to be written or a
  4646. variable into which the read data should be stored.
  4647. Return Value:
  4648. NO_ERROR.
  4649. --*/
  4650. {
  4651. PHW_DEVICE_EXTENSION hwDeviceExtension = (PHW_DEVICE_EXTENSION) Context;
  4652. PHW_DEVICE_EXTENSION HwDeviceExtension = (PHW_DEVICE_EXTENSION) Context;
  4653. ULONG endEmulation;
  4654. UCHAR temp;
  4655. UCHAR tempB ;
  4656. if (hwDeviceExtension->TrappedValidatorCount) {
  4657. //
  4658. // If we are processing a WRITE instruction, then store it in the
  4659. // playback buffer. If the buffer is full, then play it back right
  4660. // away, end sync reset and reinitialize the buffer with a sync
  4661. // reset instruction.
  4662. //
  4663. // If we have a READ, we must flush the buffer (which has the side
  4664. // effect of starting SyncReset), perform the read operation, stop
  4665. // sync reset, and put back a sync reset instruction in the buffer
  4666. // so we can go on appropriately
  4667. //
  4668. if (AccessMode & EMULATOR_WRITE_ACCESS) {
  4669. //
  4670. // Make sure Bit 3 of the Miscellaneous register is always 0.
  4671. // If it is 1 it could select a non-existent clock, and kill the
  4672. // system
  4673. //
  4674. if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
  4675. *Data &= 0xFFF7;
  4676. }
  4677. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4678. TrappedValidatorCount].Port = Port;
  4679. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4680. TrappedValidatorCount].AccessType = VGA_VALIDATOR_USHORT_ACCESS;
  4681. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4682. TrappedValidatorCount].Data = *Data;
  4683. hwDeviceExtension->TrappedValidatorCount++;
  4684. //
  4685. // Check to see if this instruction was ending sync reset.
  4686. // If it did, we must flush the buffer and reset the trapped
  4687. // IO ports to the minimal set.
  4688. //
  4689. if (Port == SEQ_ADDRESS_PORT) {
  4690. //
  4691. // If we are accessing the seq address port, keep track of its
  4692. // value
  4693. //
  4694. hwDeviceExtension->SequencerAddressValue = (*Data & 0xFF);
  4695. }
  4696. if ((Port == SEQ_ADDRESS_PORT) &&
  4697. ( ((*Data >> 8) & END_SYNC_RESET_VALUE) ==
  4698. END_SYNC_RESET_VALUE) &&
  4699. (hwDeviceExtension->SequencerAddressValue == IND_SYNC_RESET)) {
  4700. endEmulation = 1;
  4701. } else {
  4702. //
  4703. // If the buffer is not full, then just return right away.
  4704. //
  4705. if (hwDeviceExtension->TrappedValidatorCount <
  4706. VGA_MAX_VALIDATOR_DATA - 1) {
  4707. return NO_ERROR;
  4708. }
  4709. endEmulation = 0;
  4710. }
  4711. }
  4712. //
  4713. // We are either in a READ path or a WRITE path that caused a
  4714. // a full buffer. So flush the buffer either way.
  4715. //
  4716. // To do this put an END_SYNC_RESET at the end since we want to make
  4717. // the buffer is ended sync reset ended.
  4718. //
  4719. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4720. TrappedValidatorCount].Port = SEQ_ADDRESS_PORT;
  4721. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4722. TrappedValidatorCount].AccessType = VGA_VALIDATOR_USHORT_ACCESS;
  4723. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4724. TrappedValidatorCount].Data = (USHORT) (IND_SYNC_RESET +
  4725. (END_SYNC_RESET_VALUE << 8));
  4726. hwDeviceExtension->TrappedValidatorCount++;
  4727. VideoPortSynchronizeExecution(hwDeviceExtension,
  4728. VpHighPriority,
  4729. (PMINIPORT_SYNCHRONIZE_ROUTINE)
  4730. VgaPlaybackValidatorData,
  4731. hwDeviceExtension);
  4732. //
  4733. // Write back the real value of the sequencer address port.
  4734. //
  4735. VideoPortWritePortUchar((PUCHAR) (hwDeviceExtension->IOAddress +
  4736. SEQ_ADDRESS_PORT),
  4737. (UCHAR) hwDeviceExtension->SequencerAddressValue);
  4738. //
  4739. // If we are in a READ path, read the data
  4740. //
  4741. if (AccessMode & EMULATOR_READ_ACCESS) {
  4742. *Data = VideoPortReadPortUshort((PUSHORT)(hwDeviceExtension->IOAddress
  4743. + Port));
  4744. endEmulation = 0;
  4745. }
  4746. //
  4747. // If we are ending emulation, reset trapping to the minimal amount
  4748. // and exit.
  4749. //
  4750. if (endEmulation) {
  4751. VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
  4752. NUM_MINIMAL_VGA_VALIDATOR_ACCESS_RANGE,
  4753. MinimalVgaValidatorAccessRange);
  4754. return NO_ERROR;
  4755. }
  4756. //
  4757. // For both cases, put back a START_SYNC_RESET in the buffer.
  4758. //
  4759. hwDeviceExtension->TrappedValidatorCount = 1;
  4760. hwDeviceExtension->TrappedValidatorData[0].Port = SEQ_ADDRESS_PORT;
  4761. hwDeviceExtension->TrappedValidatorData[0].AccessType =
  4762. VGA_VALIDATOR_USHORT_ACCESS;
  4763. hwDeviceExtension->TrappedValidatorData[0].Data =
  4764. (ULONG) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8));
  4765. } else {
  4766. //
  4767. // Nothing trapped.
  4768. // Lets check is the IO is trying to do something that would require
  4769. // us to stop trapping
  4770. //
  4771. if (AccessMode & EMULATOR_WRITE_ACCESS) {
  4772. //
  4773. // Make sure Bit 3 of the Miscelaneous register is always 0.
  4774. // If it is 1 it could select a non-existant clock, and kill the
  4775. // system
  4776. //
  4777. if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
  4778. temp = VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
  4779. SEQ_ADDRESS_PORT);
  4780. VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
  4781. SEQ_ADDRESS_PORT),
  4782. (USHORT) (IND_SYNC_RESET +
  4783. (START_SYNC_RESET_VALUE << 8)));
  4784. VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
  4785. (ULONG)Port),
  4786. (USHORT) (*Data & 0xFFF7) );
  4787. VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
  4788. SEQ_ADDRESS_PORT),
  4789. (USHORT) (IND_SYNC_RESET +
  4790. (END_SYNC_RESET_VALUE << 8)));
  4791. VideoPortWritePortUchar(hwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
  4792. temp);
  4793. return NO_ERROR;
  4794. }
  4795. if ( (Port == SEQ_ADDRESS_PORT) &&
  4796. (((*Data>> 8) & END_SYNC_RESET_VALUE) != END_SYNC_RESET_VALUE) &&
  4797. ((*Data & 0xFF) == IND_SYNC_RESET)) {
  4798. VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
  4799. NUM_FULL_VGA_VALIDATOR_ACCESS_RANGE,
  4800. FullVgaValidatorAccessRange);
  4801. hwDeviceExtension->TrappedValidatorCount = 1;
  4802. hwDeviceExtension->TrappedValidatorData[0].Port = Port;
  4803. hwDeviceExtension->TrappedValidatorData[0].AccessType =
  4804. VGA_VALIDATOR_USHORT_ACCESS;
  4805. hwDeviceExtension->TrappedValidatorData[0].Data = *Data;
  4806. //
  4807. // Start keeping track of the state of the sequencer port.
  4808. //
  4809. hwDeviceExtension->SequencerAddressValue = IND_SYNC_RESET;
  4810. } else {
  4811. VideoPortWritePortUshort((PUSHORT)(hwDeviceExtension->IOAddress +
  4812. Port),
  4813. *Data);
  4814. }
  4815. } else {
  4816. *Data = VideoPortReadPortUshort((PUSHORT)(hwDeviceExtension->IOAddress +
  4817. Port));
  4818. }
  4819. }
  4820. return NO_ERROR;
  4821. } // end VgaValidatorUshortEntry()
  4822. //---------------------------------------------------------------------------
  4823. VP_STATUS
  4824. VgaValidatorUlongEntry(
  4825. ULONG_PTR Context,
  4826. ULONG Port,
  4827. UCHAR AccessMode,
  4828. PULONG Data
  4829. )
  4830. /*++
  4831. Routine Description:
  4832. Entry point into the validator for dword I/O operations.
  4833. The entry point will be called whenever a byte operation was performed
  4834. by a DOS application on one of the specified Video ports. The kernel
  4835. emulator will forward these requests.
  4836. Arguments:
  4837. Context - Context value that is passed to each call made to the validator
  4838. function. This is the value the miniport driver specified in the
  4839. MiniportConfigInfo->EmulatorAccessEntriesContext.
  4840. Port - Port on which the operation is to be performed.
  4841. AccessMode - Determines if it is a read or write operation.
  4842. Data - Pointer to a variable containing the data to be written or a
  4843. variable into which the read data should be stored.
  4844. Return Value:
  4845. NO_ERROR.
  4846. --*/
  4847. {
  4848. PHW_DEVICE_EXTENSION hwDeviceExtension = (PHW_DEVICE_EXTENSION) Context;
  4849. PHW_DEVICE_EXTENSION HwDeviceExtension = (PHW_DEVICE_EXTENSION) Context;
  4850. ULONG endEmulation;
  4851. UCHAR temp;
  4852. if (hwDeviceExtension->TrappedValidatorCount) {
  4853. //
  4854. // If we are processing a WRITE instruction, then store it in the
  4855. // playback buffer. If the buffer is full, then play it back right
  4856. // away, end sync reset and reinitialize the buffer with a sync
  4857. // reset instruction.
  4858. //
  4859. // If we have a READ, we must flush the buffer (which has the side
  4860. // effect of starting SyncReset), perform the read operation, stop
  4861. // sync reset, and put back a sync reset instruction in the buffer
  4862. // so we can go on appropriately
  4863. //
  4864. if (AccessMode & EMULATOR_WRITE_ACCESS) {
  4865. //
  4866. // Make sure Bit 3 of the Miscellaneous register is always 0.
  4867. // If it is 1 it could select a non-existent clock, and kill the
  4868. // system
  4869. //
  4870. if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
  4871. *Data &= 0xFFFFFFF7;
  4872. }
  4873. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4874. TrappedValidatorCount].Port = Port;
  4875. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4876. TrappedValidatorCount].AccessType = VGA_VALIDATOR_ULONG_ACCESS;
  4877. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4878. TrappedValidatorCount].Data = *Data;
  4879. hwDeviceExtension->TrappedValidatorCount++;
  4880. //
  4881. // Check to see if this instruction was ending sync reset.
  4882. // If it did, we must flush the buffer and reset the trapped
  4883. // IO ports to the minimal set.
  4884. //
  4885. if (Port == SEQ_ADDRESS_PORT) {
  4886. //
  4887. // If we are accessing the seq address port, keep track of its
  4888. // value
  4889. //
  4890. hwDeviceExtension->SequencerAddressValue = (*Data & 0xFF);
  4891. }
  4892. if ((Port == SEQ_ADDRESS_PORT) &&
  4893. ( ((*Data >> 8) & END_SYNC_RESET_VALUE) ==
  4894. END_SYNC_RESET_VALUE) &&
  4895. (hwDeviceExtension->SequencerAddressValue == IND_SYNC_RESET)) {
  4896. endEmulation = 1;
  4897. } else {
  4898. //
  4899. // If the buffer is not full, then just return right away.
  4900. //
  4901. if (hwDeviceExtension->TrappedValidatorCount <
  4902. VGA_MAX_VALIDATOR_DATA - 1) {
  4903. return NO_ERROR;
  4904. }
  4905. endEmulation = 0;
  4906. }
  4907. }
  4908. //
  4909. // We are either in a READ path or a WRITE path that caused a
  4910. // a full buffer. So flush the buffer either way.
  4911. //
  4912. // To do this put an END_SYNC_RESET at the end since we want to make
  4913. // the buffer is ended sync reset ended.
  4914. //
  4915. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4916. TrappedValidatorCount].Port = SEQ_ADDRESS_PORT;
  4917. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4918. TrappedValidatorCount].AccessType = VGA_VALIDATOR_USHORT_ACCESS;
  4919. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4920. TrappedValidatorCount].Data = (USHORT) (IND_SYNC_RESET +
  4921. (END_SYNC_RESET_VALUE << 8));
  4922. hwDeviceExtension->TrappedValidatorCount++;
  4923. VideoPortSynchronizeExecution(hwDeviceExtension,
  4924. VpHighPriority,
  4925. (PMINIPORT_SYNCHRONIZE_ROUTINE)
  4926. VgaPlaybackValidatorData,
  4927. hwDeviceExtension);
  4928. //
  4929. // Write back the real value of the sequencer address port.
  4930. //
  4931. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  4932. SEQ_ADDRESS_PORT,
  4933. (UCHAR) hwDeviceExtension->SequencerAddressValue);
  4934. //
  4935. // If we are in a READ path, read the data
  4936. //
  4937. if (AccessMode & EMULATOR_READ_ACCESS) {
  4938. *Data = VideoPortReadPortUlong((PULONG) (hwDeviceExtension->IOAddress +
  4939. Port));
  4940. endEmulation = 0;
  4941. }
  4942. //
  4943. // If we are ending emulation, reset trapping to the minimal amount
  4944. // and exit.
  4945. //
  4946. if (endEmulation) {
  4947. VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
  4948. NUM_MINIMAL_VGA_VALIDATOR_ACCESS_RANGE,
  4949. MinimalVgaValidatorAccessRange);
  4950. return NO_ERROR;
  4951. }
  4952. //
  4953. // For both cases, put back a START_SYNC_RESET in the buffer.
  4954. //
  4955. hwDeviceExtension->TrappedValidatorCount = 1;
  4956. hwDeviceExtension->TrappedValidatorData[0].Port = SEQ_ADDRESS_PORT;
  4957. hwDeviceExtension->TrappedValidatorData[0].AccessType =
  4958. VGA_VALIDATOR_USHORT_ACCESS;
  4959. hwDeviceExtension->TrappedValidatorData[0].Data =
  4960. (ULONG) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8));
  4961. } else {
  4962. //
  4963. // Nothing trapped.
  4964. // Lets check is the IO is trying to do something that would require
  4965. // us to stop trapping
  4966. //
  4967. if (AccessMode & EMULATOR_WRITE_ACCESS) {
  4968. //
  4969. // Make sure Bit 3 of the Miscelaneous register is always 0.
  4970. // If it is 1 it could select a non-existant clock, and kill the
  4971. // system
  4972. //
  4973. if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
  4974. temp = VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
  4975. SEQ_ADDRESS_PORT);
  4976. VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
  4977. SEQ_ADDRESS_PORT),
  4978. (USHORT) (IND_SYNC_RESET +
  4979. (START_SYNC_RESET_VALUE << 8)));
  4980. VideoPortWritePortUlong((PULONG) (hwDeviceExtension->IOAddress +
  4981. Port),
  4982. (ULONG) (*Data & 0xFFFFFFF7) );
  4983. VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
  4984. SEQ_ADDRESS_PORT),
  4985. (USHORT) (IND_SYNC_RESET +
  4986. (END_SYNC_RESET_VALUE << 8)));
  4987. VideoPortWritePortUchar(hwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
  4988. temp);
  4989. return NO_ERROR;
  4990. }
  4991. if ( (Port == SEQ_ADDRESS_PORT) &&
  4992. (((*Data>> 8) & END_SYNC_RESET_VALUE) != END_SYNC_RESET_VALUE) &&
  4993. ((*Data & 0xFF) == IND_SYNC_RESET)) {
  4994. VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
  4995. NUM_FULL_VGA_VALIDATOR_ACCESS_RANGE,
  4996. FullVgaValidatorAccessRange);
  4997. hwDeviceExtension->TrappedValidatorCount = 1;
  4998. hwDeviceExtension->TrappedValidatorData[0].Port = Port;
  4999. hwDeviceExtension->TrappedValidatorData[0].AccessType =
  5000. VGA_VALIDATOR_ULONG_ACCESS;
  5001. hwDeviceExtension->TrappedValidatorData[0].Data = *Data;
  5002. //
  5003. // Start keeping track of the state of the sequencer port.
  5004. //
  5005. hwDeviceExtension->SequencerAddressValue = IND_SYNC_RESET;
  5006. } else {
  5007. VideoPortWritePortUlong((PULONG) (hwDeviceExtension->IOAddress +
  5008. Port),
  5009. *Data);
  5010. }
  5011. } else {
  5012. *Data = VideoPortReadPortUlong((PULONG) (hwDeviceExtension->IOAddress +
  5013. Port));
  5014. }
  5015. }
  5016. return NO_ERROR;
  5017. } // end VgaValidatorUlongEntry()
  5018. //---------------------------------------------------------------------------
  5019. BOOLEAN
  5020. VgaPlaybackValidatorData(
  5021. PVOID Context
  5022. )
  5023. /*++
  5024. Routine Description:
  5025. Performs all the DOS apps IO port accesses that were trapped by the
  5026. validator. Only IO accesses that can be processed are WRITEs
  5027. The number of outstanding IO access in deviceExtension is set to
  5028. zero as a side effect.
  5029. This function must be called via a call to VideoPortSynchronizeRoutine.
  5030. Arguments:
  5031. Context - Context parameter passed to the synchronized routine.
  5032. Must be a pointer to the miniport driver's device extension.
  5033. Return Value:
  5034. TRUE.
  5035. --*/
  5036. {
  5037. PHW_DEVICE_EXTENSION hwDeviceExtension = Context;
  5038. PHW_DEVICE_EXTENSION HwDeviceExtension = Context;
  5039. ULONG_PTR ioBaseAddress = PtrToUlong(hwDeviceExtension->IOAddress);
  5040. UCHAR i;
  5041. PVGA_VALIDATOR_DATA validatorData = hwDeviceExtension->TrappedValidatorData;
  5042. //
  5043. // Loop through the array of data and do instructions one by one.
  5044. //
  5045. for (i = 0; i < hwDeviceExtension->TrappedValidatorCount;
  5046. i++, validatorData++) {
  5047. //
  5048. // Calculate base address first
  5049. //
  5050. ioBaseAddress = PtrToUlong(hwDeviceExtension->IOAddress) +
  5051. validatorData->Port;
  5052. //
  5053. // This is a write operation. We will automatically stop when the
  5054. // buffer is empty.
  5055. //
  5056. switch (validatorData->AccessType) {
  5057. case VGA_VALIDATOR_UCHAR_ACCESS :
  5058. VideoPortWritePortUchar((PUCHAR)ioBaseAddress,
  5059. (UCHAR) validatorData->Data);
  5060. break;
  5061. case VGA_VALIDATOR_USHORT_ACCESS :
  5062. VideoPortWritePortUshort((PUSHORT)ioBaseAddress,
  5063. (USHORT) validatorData->Data);
  5064. break;
  5065. case VGA_VALIDATOR_ULONG_ACCESS :
  5066. VideoPortWritePortUlong((PULONG)ioBaseAddress,
  5067. (ULONG) validatorData->Data);
  5068. break;
  5069. default:
  5070. VideoDebugPrint((1, "InvalidValidatorAccessType\n" ));
  5071. }
  5072. }
  5073. hwDeviceExtension->TrappedValidatorCount = 0;
  5074. return TRUE;
  5075. } // end VgaPlaybackValidatorData()
  5076. //---------------------------------------------------------------------------
  5077. BOOLEAN
  5078. CirrusLogicIsPresent(
  5079. PHW_DEVICE_EXTENSION HwDeviceExtension
  5080. )
  5081. /*++
  5082. Routine Description:
  5083. This routine returns TRUE if an CL6410, 6420, 542x, or 543x is present.
  5084. It assumes that it's already been established that a VGA is present.
  5085. It performs the Cirrus Logic recommended ID test for each chip type:
  5086. 6410: we try to enable the extension registers and read back a 1, then
  5087. disable the extensions are read back a 0 in GR0A.
  5088. 6420: same as above
  5089. 54xx: Enable extended registers by writing 0x12 to the extensions
  5090. enable register, and reading back 0x12. Then read from the
  5091. ID register and make sure it specifies a 542x, 543x.
  5092. Finally, disable the extensions and make sure the
  5093. extensions enable register reads back 0x0F.
  5094. If this function fails to find an Cirrus Logic VGA, it attempts to undo any
  5095. damage it may have inadvertently done while testing.
  5096. If a Cirrus Logic VGA is found, the adapter is returned to its original
  5097. state after testing is finished, except that extensions are left enabled.
  5098. Arguments:
  5099. None.
  5100. Return Value:
  5101. TRUE if an CL6410/6420/542x/543x is present, FALSE if not.
  5102. --*/
  5103. {
  5104. #define MAX_ROM_SCAN 4096
  5105. UCHAR *pRomAddr;
  5106. PHYSICAL_ADDRESS paRom = {0x000C0000,0x00000000};
  5107. UCHAR originalGRIndex;
  5108. UCHAR originalGR0A;
  5109. UCHAR originalCRTCIndex;
  5110. UCHAR originalSeqIndex;
  5111. UCHAR originalExtsEnb;
  5112. UCHAR SystemBusSelect;
  5113. PUCHAR CRTCAddressPort, CRTCDataPort;
  5114. UCHAR temp1, temp2, temp3;
  5115. UCHAR revision;
  5116. ULONG rev10bit;
  5117. BOOLEAN retvalue = FALSE; // default return value
  5118. // Set default value, assuming it is not CL-GD5480.
  5119. HwDeviceExtension->BitBLTEnhance = FALSE ;
  5120. //
  5121. // first, save the Graphics controller index
  5122. //
  5123. originalGRIndex = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  5124. GRAPH_ADDRESS_PORT);
  5125. //
  5126. // Then save the value of GR0A
  5127. //
  5128. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  5129. GRAPH_ADDRESS_PORT, CL64xx_EXTENSION_ENABLE_INDEX);
  5130. originalGR0A = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  5131. GRAPH_DATA_PORT);
  5132. //
  5133. // then, Unlock the CL6410 extended registers., GR0A = 0ECH
  5134. //
  5135. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  5136. GRAPH_DATA_PORT, CL64xx_EXTENSION_ENABLE_VALUE);
  5137. //
  5138. // read back GR0A, it should be a 1
  5139. //
  5140. temp1 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  5141. GRAPH_DATA_PORT);
  5142. //
  5143. // then, Lock the CL6410 extended registers., GR0A = 0CEH
  5144. //
  5145. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  5146. GRAPH_DATA_PORT, CL64xx_EXTENSION_DISABLE_VALUE);
  5147. //
  5148. // read back GR0A, it should be a 0
  5149. //
  5150. temp2 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  5151. GRAPH_DATA_PORT);
  5152. //
  5153. // restore the GR0A value
  5154. // this will not have any effect if the chip IS a CL6410 or 6420
  5155. //
  5156. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  5157. GRAPH_DATA_PORT, originalGR0A);
  5158. //
  5159. // now restore the graphics index
  5160. //
  5161. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  5162. GRAPH_ADDRESS_PORT, originalGRIndex);
  5163. //
  5164. // now test to see if the returned values were correct!
  5165. //
  5166. if ((temp1 == 1) && (temp2 == 0))
  5167. {
  5168. //
  5169. // By golly, it *is* a CL6410 or CL6420!
  5170. //
  5171. // but now we have to determine the chip type, and which display is
  5172. // active.
  5173. // reenable the extension registers first
  5174. //
  5175. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  5176. GRAPH_ADDRESS_PORT), CL64xx_EXTENSION_ENABLE_INDEX +
  5177. (CL64xx_EXTENSION_ENABLE_VALUE << 8));
  5178. //
  5179. // now get the chip type at ERAA
  5180. //
  5181. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  5182. GRAPH_ADDRESS_PORT, 0xaa);
  5183. revision = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  5184. GRAPH_DATA_PORT);
  5185. //
  5186. // now restore the graphics index
  5187. //
  5188. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  5189. GRAPH_ADDRESS_PORT, originalGRIndex);
  5190. if ((revision & 0xf0) == 0x80) // 6410 rev code
  5191. {
  5192. VideoDebugPrint((1, "CL 6410 found\n"));
  5193. //
  5194. // we don't support 6340 in this driver, so force it not to be
  5195. // installed.
  5196. //
  5197. if (!CirrusFind6340(HwDeviceExtension))
  5198. {
  5199. HwDeviceExtension->ChipType = CL6410;
  5200. HwDeviceExtension->AdapterMemorySize = 0x00040000; // 256K
  5201. HwDeviceExtension->DisplayType =
  5202. CirrusFind6410DisplayType(HwDeviceExtension);
  5203. retvalue = TRUE;
  5204. }
  5205. }
  5206. else if ((revision & 0xf0) == 0x70) // 6420 rev code
  5207. {
  5208. VideoDebugPrint((1, "CL 6420 found\n"));
  5209. //
  5210. // we don't support 6340 in this driver, so force it not to be
  5211. // installed.
  5212. //
  5213. if (!CirrusFind6340(HwDeviceExtension))
  5214. {
  5215. HwDeviceExtension->ChipType = CL6420;
  5216. HwDeviceExtension->ChipRevision = (USHORT) revision;
  5217. HwDeviceExtension->DisplayType =
  5218. CirrusFind6410DisplayType(HwDeviceExtension);
  5219. VideoDebugPrint((2, "CL 64xxx Adapter Memory size = %08lx\n",
  5220. HwDeviceExtension->AdapterMemorySize));
  5221. retvalue = TRUE;
  5222. }
  5223. }
  5224. else // we dont support 5410 at this time
  5225. {
  5226. VideoDebugPrint((1, "Unsupported CL VGA chip found\n"));
  5227. }
  5228. }
  5229. if (retvalue == FALSE) // Did not detect a 64x0, see if it's a 542x
  5230. {
  5231. //
  5232. // Determine where the CRTC registers are addressed (color or mono).
  5233. //
  5234. CRTCAddressPort = HwDeviceExtension->IOAddress;
  5235. CRTCDataPort = HwDeviceExtension->IOAddress;
  5236. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  5237. MISC_OUTPUT_REG_READ_PORT) & 0x01)
  5238. {
  5239. CRTCAddressPort += CRTC_ADDRESS_PORT_COLOR;
  5240. CRTCDataPort += CRTC_DATA_PORT_COLOR;
  5241. }
  5242. else
  5243. {
  5244. CRTCAddressPort += CRTC_ADDRESS_PORT_MONO;
  5245. CRTCDataPort += CRTC_DATA_PORT_MONO;
  5246. }
  5247. //
  5248. // Save the original state of the CRTC and Sequencer Indices.
  5249. //
  5250. originalCRTCIndex = VideoPortReadPortUchar(CRTCAddressPort);
  5251. originalSeqIndex = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  5252. SEQ_ADDRESS_PORT);
  5253. //
  5254. // Try to enable all extensions:
  5255. // a) Set the Sequencer Index to IND_CL_EXTS_ENB.
  5256. //
  5257. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
  5258. IND_CL_EXTS_ENB);
  5259. //
  5260. // b) Save the original state of Sequencer register IND_CL_EXTS_ENB.
  5261. //
  5262. originalExtsEnb = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  5263. SEQ_DATA_PORT);
  5264. //
  5265. // c) Write enabling value (0x12) to extension enable register
  5266. //
  5267. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  5268. SEQ_ADDRESS_PORT),(USHORT)((0x12 << 8) + IND_CL_EXTS_ENB));
  5269. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
  5270. IND_CL_EXTS_ENB);
  5271. temp1 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  5272. SEQ_DATA_PORT);
  5273. //
  5274. // Read Chip ID Value from CRTC Register (Ignoring revision bits)
  5275. //
  5276. VideoPortWritePortUchar(CRTCAddressPort, IND_CL_ID_REG);
  5277. temp3 = VideoPortReadPortUchar(CRTCDataPort);
  5278. //
  5279. // Detect if CL-GD6245 chips ID=0x16
  5280. //
  5281. if (temp3 != 0x16)
  5282. {
  5283. rev10bit = (ULONG)temp3 & 0x3; // lo bits of ID are high bits of rev code
  5284. temp3 = temp3 >> 2; // shift off revision bits
  5285. }
  5286. //
  5287. // Write another value (!= 0x12) to IND_CL_EXTS_ENB to disable extensions
  5288. // Should read back as 0x0F
  5289. //
  5290. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  5291. SEQ_ADDRESS_PORT),(USHORT)((0 << 8) + IND_CL_EXTS_ENB));
  5292. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
  5293. IND_CL_EXTS_ENB);
  5294. temp2 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  5295. SEQ_DATA_PORT);
  5296. //
  5297. // Restore the original IND_CL_EXTS_ENB state.
  5298. //
  5299. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress
  5300. + SEQ_ADDRESS_PORT),
  5301. (USHORT)((originalExtsEnb << 8) + IND_CL_EXTS_ENB));
  5302. //
  5303. // Check values read from IND_CL_EXTS_ENB and IND_CL_ID_REG to be correct
  5304. //
  5305. if ((temp1 != (UCHAR) (0x12)) ||
  5306. (temp2 != (UCHAR) (0x0F)) ||
  5307. (temp3 > (UCHAR) (0x2F)) || // 2F is 5480
  5308. (temp3 < (UCHAR) (0x0B)) ) // 0B is Nordic (7542)
  5309. {
  5310. //
  5311. // Did not find appropriate CL VGA Chip.
  5312. //
  5313. VideoDebugPrint((1, "CL VGA chip not found\n"));
  5314. retvalue = FALSE;
  5315. }
  5316. //
  5317. // Detect if CL-GD6245 chips
  5318. //
  5319. else if ((temp1 == (UCHAR) (0x12)) &&
  5320. (temp2 == (UCHAR) (0x0F)) &&
  5321. (temp3 == (UCHAR) (0x16))) //6245
  5322. {
  5323. VideoDebugPrint((1, "CL 6245 found\n"));
  5324. HwDeviceExtension->ChipType = CL6245;
  5325. HwDeviceExtension->DisplayType =
  5326. CirrusFind6245DisplayType(HwDeviceExtension,
  5327. CRTCAddressPort,
  5328. CRTCDataPort);
  5329. retvalue = TRUE;
  5330. }
  5331. else
  5332. {
  5333. //
  5334. // It's a supported CL adapter.
  5335. //
  5336. // Save actual Chip ID in ChipRevision field of HwDeviceExtension
  5337. //
  5338. HwDeviceExtension->ChipRevision = temp3;
  5339. if ((temp3 > (UCHAR) (0x27)) || // 27 is 5429
  5340. (temp3 < (UCHAR) (0x22) ) ) // 22 is 5422
  5341. {
  5342. if ((temp3 >= (UCHAR) (0x0B)) && // Nordic
  5343. (temp3 <= (UCHAR) (0x0E)) ) // Everest
  5344. {
  5345. if (temp3 == (UCHAR)0x0B)
  5346. {
  5347. VideoDebugPrint((1, "CL 7542 found\n")); //myf32
  5348. HwDeviceExtension->ChipType = CL7542;
  5349. }
  5350. if (temp3 == (UCHAR)0x0C)
  5351. {
  5352. VideoDebugPrint((1, "CL 7543 found\n")); //myf32
  5353. HwDeviceExtension->ChipType = CL7543;
  5354. }
  5355. if (temp3 == (UCHAR)0x0D)
  5356. {
  5357. VideoDebugPrint((1, "CL 7541 found\n")); //myf32
  5358. HwDeviceExtension->ChipType = CL7541;
  5359. }
  5360. if (temp3 == (UCHAR)0x0E)
  5361. {
  5362. VideoDebugPrint((1, "CL 7548 found\n")); //myf32
  5363. HwDeviceExtension->ChipType = CL7548;
  5364. }
  5365. HwDeviceExtension->DisplayType =
  5366. CirrusFind754xDisplayType(HwDeviceExtension,
  5367. CRTCAddressPort,
  5368. CRTCDataPort);
  5369. } else if ((temp3 == (UCHAR) (0x10)) ||
  5370. (temp3 == (UCHAR) (0x13))) { //myf17, CF
  5371. if (temp3 == (UCHAR)0x10)
  5372. {
  5373. VideoDebugPrint((1, "CL 7555 found\n")) ;
  5374. HwDeviceExtension->ChipType = CL7555;
  5375. }
  5376. if (temp3 == (UCHAR)0x13)
  5377. {
  5378. VideoDebugPrint((1, "CL 7556 found\n")) ;
  5379. HwDeviceExtension->ChipType = CL7556;
  5380. }
  5381. HwDeviceExtension -> DisplayType =
  5382. CirrusFind755xDisplayType(HwDeviceExtension,
  5383. CRTCAddressPort,
  5384. CRTCDataPort) ;
  5385. } else if (temp3 == (UCHAR) (0x11)) {
  5386. VideoDebugPrint((1, "CL 756x found\n")) ;
  5387. HwDeviceExtension->ChipType = CL756x ;
  5388. HwDeviceExtension->DisplayType =
  5389. CirrusFind755xDisplayType(HwDeviceExtension,
  5390. CRTCAddressPort,
  5391. CRTCDataPort) ;
  5392. } else {
  5393. VideoDebugPrint((1, "CL 543x found\n"));
  5394. HwDeviceExtension->ChipType = CL543x;
  5395. HwDeviceExtension->DisplayType = crt;
  5396. // jl03 Read CR27(b1 & b0) + CR25 for chip revision
  5397. VideoPortWritePortUchar(CRTCAddressPort, IND_CL_REV_REG);
  5398. revision = (VideoPortReadPortUchar(CRTCDataPort));
  5399. rev10bit = (ULONG)(rev10bit << 8) | revision;
  5400. if (temp3 == (UCHAR) (0x2A)) // or a 5434?
  5401. {
  5402. VideoDebugPrint((1, "CL 5434 found\n"));
  5403. //
  5404. //Default to .8u 5434
  5405. //
  5406. HwDeviceExtension->ChipType = CL5434;
  5407. //
  5408. // Read the revision code from CR25&27 and compare to
  5409. // lowest rev that we know to be .6u
  5410. //
  5411. /* jl03
  5412. VideoPortWritePortUchar(CRTCAddressPort, IND_CL_REV_REG);
  5413. revision = (VideoPortReadPortUchar(CRTCDataPort));
  5414. rev10bit = (ULONG)(rev10bit << 8) | revision;
  5415. */
  5416. if ((rev10bit >= 0xB0) || // B0 is rev "EP", first .6u 5434
  5417. (rev10bit == 0x28) ) // 28 is rev "AH" also .6u 5434
  5418. {
  5419. VideoDebugPrint((1, "CL 5434.6 found\n"));
  5420. HwDeviceExtension->ChipType = CL5434_6;
  5421. }
  5422. } else if (temp3 == (UCHAR) (0x2B)) { // 5436
  5423. HwDeviceExtension->ChipType = CL5436 ;
  5424. } else if (temp3 == (UCHAR) (0x2E)) { // 5446
  5425. HwDeviceExtension->ChipType = CL5446 ;
  5426. if (rev10bit == 0x45)
  5427. HwDeviceExtension->ChipType = CL5446BE ; // jl02 5446-BE
  5428. } else if (temp3 == (UCHAR) (0x2F)) { // 5480
  5429. HwDeviceExtension->ChipType = CL5480;
  5430. HwDeviceExtension->BitBLTEnhance = TRUE ;
  5431. } else if (temp3 == (UCHAR) (0x3A)) { // 54UM36 ?
  5432. HwDeviceExtension->ChipType = CL54UM36 ;
  5433. }
  5434. }
  5435. }
  5436. else
  5437. {
  5438. VideoDebugPrint((1, "CL 542x found\n"));
  5439. HwDeviceExtension->ChipType = CL542x;
  5440. HwDeviceExtension->DisplayType = crt;
  5441. }
  5442. retvalue = TRUE;
  5443. }
  5444. //
  5445. // Restore modified index registers
  5446. //
  5447. VideoPortWritePortUchar(
  5448. (HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT),
  5449. originalSeqIndex);
  5450. VideoPortWritePortUchar(CRTCAddressPort, originalCRTCIndex);
  5451. }
  5452. if (retvalue)
  5453. {
  5454. //
  5455. // Restore the original Sequencer and CRTC Indices.
  5456. //
  5457. HwDeviceExtension->AutoFeature = FALSE ;
  5458. if ((HwDeviceExtension->ChipType == CL5436) ||
  5459. (HwDeviceExtension->ChipType == CL5446) ||
  5460. (HwDeviceExtension->ChipType == CL5446BE) ||
  5461. (HwDeviceExtension->ChipType == CL5480) ||
  5462. (HwDeviceExtension->ChipType & CL754x) ||
  5463. (HwDeviceExtension->ChipType & CL755x) ||
  5464. (HwDeviceExtension->ChipType == CL54UM36))
  5465. {
  5466. HwDeviceExtension->AutoFeature = TRUE;
  5467. }
  5468. }
  5469. return retvalue;
  5470. } // CirrusLogicIsPresent()
  5471. //---------------------------------------------------------------------------
  5472. #ifdef PANNING_SCROLL
  5473. VP_STATUS
  5474. CirrusSetDisplayPitch (
  5475. PHW_DEVICE_EXTENSION HwDeviceExtension,
  5476. PANNMODE PanningMode
  5477. )
  5478. {
  5479. PUCHAR CRTCAddressPort, CRTCDataPort;
  5480. USHORT RequestedPitchInBytes = PanningMode.wbytes;
  5481. USHORT PitchInQuadWords = RequestedPitchInBytes >> 3;
  5482. UCHAR savSEQidx, Panel_Type, LCD, ChipID;
  5483. //
  5484. // Determine where the CRTC registers are addressed (color or mono).
  5485. //
  5486. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  5487. MISC_OUTPUT_REG_READ_PORT) & 0x01)
  5488. {
  5489. CRTCAddressPort = CRTC_ADDRESS_PORT_COLOR;
  5490. CRTCDataPort = CRTC_DATA_PORT_COLOR;
  5491. }
  5492. else
  5493. {
  5494. CRTCAddressPort = CRTC_ADDRESS_PORT_MONO;
  5495. CRTCDataPort = CRTC_DATA_PORT_MONO;
  5496. }
  5497. //
  5498. // Write out the requested pitch in quad words to CR13
  5499. //
  5500. VideoPortWritePortUchar(CRTCAddressPort, 0x13);
  5501. VideoPortWritePortUchar(CRTCDataPort,
  5502. (UCHAR) (PitchInQuadWords & 0xFF) );
  5503. //
  5504. // See if requested pitch overflows to bit 4 in CR1B
  5505. // NOTE: In either case we must either set or reset the bit.
  5506. //
  5507. VideoPortWritePortUchar(CRTCAddressPort, 0x1B);
  5508. if (PitchInQuadWords & 0x100)
  5509. {
  5510. VideoPortWritePortUchar(CRTCDataPort,
  5511. (UCHAR)(VideoPortReadPortUchar(CRTCDataPort) | 0x10) );
  5512. }
  5513. else
  5514. {
  5515. VideoPortWritePortUchar(CRTCDataPort,
  5516. (UCHAR)(VideoPortReadPortUchar(CRTCDataPort) & ~0x10) );
  5517. }
  5518. VideoDebugPrint((1,"CirrusSetDisplayPitch - Exit (not error)\n"));
  5519. return NO_ERROR;
  5520. }
  5521. #endif // PANNING_SCROLL
  5522. //---------------------------------------------------------------------------
  5523. //
  5524. // The memory manager needs a "C" interface to the banking functions
  5525. //
  5526. /*++
  5527. Routine Description:
  5528. Each of these functions is a "C" callable interface to the ASM banking
  5529. functions. They are NON paged because they are called from the
  5530. Memory Manager during some page faults.
  5531. Arguments:
  5532. iBankRead - Index of bank we want mapped in to read from.
  5533. iBankWrite - Index of bank we want mapped in to write to.
  5534. Return Value:
  5535. None.
  5536. --*/
  5537. VOID
  5538. vBankMap_CL64xx(
  5539. ULONG iBankRead,
  5540. ULONG iBankWrite,
  5541. PVOID pvContext
  5542. )
  5543. {
  5544. VideoDebugPrint((1, "vBankMap_CL64xx(%d,%d) - enter\n",iBankRead,iBankWrite));
  5545. #ifdef _X86_
  5546. _asm {
  5547. mov eax,iBankRead
  5548. mov edx,iBankWrite
  5549. lea ebx,CL64xxBankSwitchStart
  5550. call ebx
  5551. }
  5552. #endif
  5553. VideoDebugPrint((1, "vBankMap_CL64xx - exit\n"));
  5554. }
  5555. VOID
  5556. vBankMap_CL543x(
  5557. ULONG iBankRead,
  5558. ULONG iBankWrite,
  5559. PVOID pvContext
  5560. )
  5561. {
  5562. VideoDebugPrint((1, "vBankMap_CL543x(%d,%d) - enter\n",iBankRead,iBankWrite));
  5563. #ifdef _X86_
  5564. _asm {
  5565. mov eax,iBankRead
  5566. mov edx,iBankWrite
  5567. lea ebx,CL543xBankSwitchStart
  5568. call ebx
  5569. }
  5570. #endif
  5571. VideoDebugPrint((1, "vBankMap_CL543x - exit\n"));
  5572. }
  5573. VOID
  5574. vBankMap_CL542x(
  5575. ULONG iBankRead,
  5576. ULONG iBankWrite,
  5577. PVOID pvContext
  5578. )
  5579. {
  5580. VideoDebugPrint((1, "vBankMap_CL542x(%d,%d) - enter\n",iBankRead,iBankWrite));
  5581. #ifdef _X86_
  5582. _asm {
  5583. mov eax,iBankRead
  5584. mov edx,iBankWrite
  5585. lea ebx,CL542xBankSwitchStart
  5586. call ebx
  5587. }
  5588. #endif
  5589. VideoDebugPrint((1, "vBankMap_CL542x - exit\n"));
  5590. }
  5591. //---------------------------------------------------------------------------
  5592. ULONG
  5593. CirrusFindVmemSize(
  5594. PHW_DEVICE_EXTENSION HwDeviceExtension
  5595. )
  5596. /*++
  5597. Routine Description:
  5598. This routine returns the amount of vram detected for the
  5599. Cirrus Logic 6420 and 542x ONLY. It assumes that it is already known that
  5600. a Cirrus Logic VGA is in the system.
  5601. Arguments:
  5602. HwDeviceExtension - Pointer to the miniport driver's device extension.
  5603. Return Value:
  5604. Number of butes of VRAM.
  5605. --*/
  5606. {
  5607. UCHAR temp;
  5608. ULONG memsize=0;
  5609. UCHAR originalSeqIndex;
  5610. UCHAR originalGraphicsIndex;
  5611. UCHAR PostScratchPad;
  5612. if (HwDeviceExtension->ChipType == CL6420) {
  5613. #ifdef _X86_
  5614. originalGraphicsIndex =
  5615. VideoPortReadPortUchar((HwDeviceExtension->IOAddress +
  5616. GRAPH_ADDRESS_PORT));
  5617. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  5618. GRAPH_ADDRESS_PORT, 0x9a); // Video memory config register
  5619. temp = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  5620. GRAPH_DATA_PORT); // get the data
  5621. if ((temp & 0x07) == 0) { // 0 is accurate always
  5622. memsize = 0x00040000;
  5623. } else {
  5624. //
  5625. // We know now that the amount of vram is >256k. But we don't
  5626. // know if it is 512k or 1meg.
  5627. // They tell us to actually go out and see if memory is there by
  5628. // writing into it and reading it back.
  5629. //
  5630. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  5631. SEQ_ADDRESS_PORT),0x0f02);
  5632. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  5633. GRAPH_ADDRESS_PORT),0x0506);
  5634. //
  5635. // now pick a bank, and do the write
  5636. //
  5637. SetCirrusBanking(HwDeviceExtension,1); // start of 2nd 256k
  5638. VideoPortWriteRegisterUchar(HwDeviceExtension->VideoMemoryAddress,
  5639. 0x55);
  5640. SetCirrusBanking(HwDeviceExtension,3); // 3*256k is 768k
  5641. VideoPortWriteRegisterUchar(HwDeviceExtension->VideoMemoryAddress,
  5642. 0xaa);
  5643. SetCirrusBanking(HwDeviceExtension,1); // start of 2nd 256k
  5644. if (VideoPortReadRegisterUchar(HwDeviceExtension->VideoMemoryAddress)
  5645. == 0x55) {
  5646. memsize = 0x00100000; // 1 MEG
  5647. } else {
  5648. memsize = 0x00080000; // 512K
  5649. }
  5650. SetCirrusBanking(HwDeviceExtension,0); // reset the memory value
  5651. VgaInterpretCmdStream(HwDeviceExtension, DisableA000Color);
  5652. VideoPortWritePortUchar((HwDeviceExtension->IOAddress
  5653. + GRAPH_ADDRESS_PORT),
  5654. originalGraphicsIndex);
  5655. }
  5656. VideoPortWritePortUchar((HwDeviceExtension->IOAddress +
  5657. GRAPH_ADDRESS_PORT), originalGraphicsIndex);
  5658. #endif
  5659. return memsize;
  5660. } else { // its 542x or 543x
  5661. originalSeqIndex = VideoPortReadPortUchar((HwDeviceExtension->IOAddress +
  5662. SEQ_ADDRESS_PORT));
  5663. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  5664. SEQ_ADDRESS_PORT),
  5665. (USHORT)((0x12 << 8) + IND_CL_EXTS_ENB));
  5666. //
  5667. // Read the POST scratch pad reg to determine amount of Video
  5668. // memory
  5669. //
  5670. if (HwDeviceExtension->ChipType == CL542x) {
  5671. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
  5672. IND_CL_SCRATCH_PAD);
  5673. PostScratchPad = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  5674. SEQ_DATA_PORT);
  5675. PostScratchPad = ((PostScratchPad & 0x18) >> 3); // in bits 3 and 4
  5676. }
  5677. else if (HwDeviceExtension->ChipType == CL6245) {
  5678. VideoPortWritePortUchar((HwDeviceExtension->IOAddress +
  5679. SEQ_ADDRESS_PORT),originalSeqIndex);
  5680. memsize = 0x00080000; // 512K
  5681. return memsize;
  5682. }
  5683. else
  5684. { // its 543x or 754x
  5685. if ((HwDeviceExtension->ChipType & CL754x) ||
  5686. (HwDeviceExtension->ChipType & CL755x) ||
  5687. (HwDeviceExtension->ChipType == CL756x))
  5688. {
  5689. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
  5690. IND_NORD_SCRATCH_PAD);
  5691. }
  5692. else // it's 543x, 5434, or 5434_6 by default
  5693. {
  5694. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
  5695. IND_ALP_SCRATCH_PAD);
  5696. }
  5697. // Nordic family uses same bits as 543x, but in different register
  5698. PostScratchPad = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  5699. SEQ_DATA_PORT);
  5700. PostScratchPad &= 0x0F; // It's in bits 0-3
  5701. }
  5702. VideoPortWritePortUchar((HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT),
  5703. originalSeqIndex);
  5704. //
  5705. // Installed video memory is stored in scratch pad register by POST.
  5706. //
  5707. switch (PostScratchPad) {
  5708. case 0x00:
  5709. memsize = 0x00040000; // 256K
  5710. break;
  5711. case 0x01:
  5712. memsize = 0x00080000; // 512K
  5713. break;
  5714. case 0x02:
  5715. memsize = 0x00100000; // 1 MEG
  5716. break;
  5717. case 0x03:
  5718. memsize = 0x00200000; // 2 MEG
  5719. break;
  5720. case 0x04:
  5721. memsize = 0x00400000; // 4 MEG
  5722. break;
  5723. case 0x05:
  5724. memsize = 0x00300000; // 3 MEG
  5725. break;
  5726. }
  5727. //
  5728. // The 542x cards don't properly address more than 1MB of
  5729. // video memory, so lie and limit these cards to 1MB.
  5730. //
  5731. if ((HwDeviceExtension->ChipType == CL542x) &&
  5732. (memsize > 0x00100000)) {
  5733. memsize = 0x00100000; // 1 MEG
  5734. }
  5735. //
  5736. // The memory size should not be zero!
  5737. //
  5738. ASSERT(memsize != 0);
  5739. return memsize;
  5740. }
  5741. } // CirrusFindVmemSize()
  5742. //---------------------------------------------------------------------------
  5743. VOID
  5744. SetCirrusBanking(
  5745. PHW_DEVICE_EXTENSION HwDeviceExtension,
  5746. USHORT BankNumber
  5747. )
  5748. /*++
  5749. Routine Description:
  5750. Arguments:
  5751. HwDeviceExtension - Pointer to the miniport driver's device extension.
  5752. BankNumber - the 256k bank number to set in 1RW mode(we will set this mode).
  5753. Return Value:
  5754. vmem256k, vmem512k, or vmem1Meg ONLY ( these are defined in cirrus.h).
  5755. --*/
  5756. {
  5757. if ((HwDeviceExtension->ChipType == CL542x) ||
  5758. (HwDeviceExtension->ChipType == CL6245)) {
  5759. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  5760. GRAPH_ADDRESS_PORT), 0x1206);
  5761. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  5762. GRAPH_ADDRESS_PORT), 0x010b);
  5763. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  5764. GRAPH_ADDRESS_PORT),
  5765. (USHORT)(0x0009 + (BankNumber << (8+4))) );
  5766. } else if ((HwDeviceExtension->ChipType == CL543x) ||
  5767. (HwDeviceExtension->ChipType & CL755x) || //myf15, crus
  5768. (HwDeviceExtension->ChipType & CL754x) ) {
  5769. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  5770. GRAPH_ADDRESS_PORT), 0x1206);
  5771. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  5772. GRAPH_ADDRESS_PORT), 0x210b);
  5773. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  5774. GRAPH_ADDRESS_PORT),
  5775. (USHORT)(0x0009 + (BankNumber << (8+2))) );
  5776. } else { // 6410 or 6420
  5777. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  5778. GRAPH_ADDRESS_PORT), 0xec0a);
  5779. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  5780. GRAPH_ADDRESS_PORT), 0x030d);
  5781. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  5782. GRAPH_ADDRESS_PORT),
  5783. (USHORT)(0x000e + (BankNumber << (8+4))) );
  5784. }
  5785. } // SetCirrusBanking()
  5786. //---------------------------------------------------------------------------
  5787. USHORT
  5788. CirrusFind6410DisplayType(
  5789. PHW_DEVICE_EXTENSION HwDeviceExtension
  5790. )
  5791. /*++
  5792. Routine Description:
  5793. Determines the display type for CL6410 or CL6420 crt/panel controllers.
  5794. Arguments:
  5795. HwDeviceExtension - Pointer to the miniport driver's device extension.
  5796. Return Value:
  5797. crt, panel as defined in cirrus.h
  5798. --*/
  5799. {
  5800. UCHAR originalGraphicsIndex;
  5801. UCHAR temp1;
  5802. //
  5803. // now we need to check to see which display we are on...
  5804. //
  5805. originalGraphicsIndex =
  5806. VideoPortReadPortUchar((HwDeviceExtension->IOAddress +
  5807. GRAPH_ADDRESS_PORT));
  5808. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  5809. GRAPH_ADDRESS_PORT, 0xd6);
  5810. temp1 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  5811. GRAPH_DATA_PORT);
  5812. VideoPortWritePortUchar((HwDeviceExtension->IOAddress
  5813. + GRAPH_ADDRESS_PORT), originalGraphicsIndex);
  5814. if (temp1 & 0x02) { // display is LCD Panel
  5815. return panel;
  5816. } else { // the display is a crt
  5817. return crt;
  5818. }
  5819. } // CirrusFind6410DisplayType()
  5820. // crus
  5821. //---------------------------------------------------------------------------
  5822. USHORT
  5823. CirrusFind6245DisplayType(
  5824. PHW_DEVICE_EXTENSION HwDeviceExtension,
  5825. PUCHAR CRTCAddrPort, PUCHAR CRTCDataPort
  5826. )
  5827. /*++
  5828. Routine Description:
  5829. Determines the display type for CL6245 crt/panel controllers.
  5830. Arguments:
  5831. HwDeviceExtension - Pointer to the miniport driver's device extension.
  5832. Return Value:
  5833. crt, panel as defined in cirrus.h
  5834. --*/
  5835. {
  5836. UCHAR originalCRTCIndex, originalLCDControl;
  5837. UCHAR originalSEQIndex;
  5838. USHORT temp2, temp4;
  5839. USHORT temp1, temp3;
  5840. //
  5841. // we need to check to see which display we are on...
  5842. //
  5843. originalCRTCIndex = VideoPortReadPortUchar(CRTCAddrPort);
  5844. VideoPortWritePortUchar(CRTCAddrPort, 0x20);
  5845. temp1 = VideoPortReadPortUchar(CRTCDataPort);
  5846. temp3 = 0;
  5847. temp4 = 0;
  5848. if (temp1 & 0x40) temp3 = 1;
  5849. if (temp1 & 0x20)
  5850. {
  5851. originalSEQIndex =
  5852. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  5853. SEQ_ADDRESS_PORT);
  5854. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  5855. SEQ_ADDRESS_PORT, 0x1A);
  5856. temp4 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  5857. SEQ_DATA_PORT) & 0x40;
  5858. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  5859. SEQ_ADDRESS_PORT, originalSEQIndex);
  5860. // Allow access to extended CRTC regs and read R8X[5], must CR1D[7]=1
  5861. //
  5862. VideoPortWritePortUchar(CRTCAddrPort, 0x1D);
  5863. originalLCDControl = VideoPortReadPortUchar(CRTCDataPort);
  5864. VideoPortWritePortUchar(CRTCDataPort,
  5865. (UCHAR) (originalLCDControl | 0x80));
  5866. VideoPortWritePortUchar(CRTCAddrPort, 0x08);
  5867. temp1 = (VideoPortReadPortUchar(CRTCDataPort) & 0x20);
  5868. VideoPortWritePortUchar (CRTCAddrPort, 0x1D);
  5869. VideoPortWritePortUchar (CRTCDataPort, originalLCDControl);
  5870. // CR1C bit 6,7 set indicate LCD type, TFT, STN color or STN mono
  5871. // STN mono, R8X bit 5 set Single or Dual
  5872. // STN color, CR1C bit 7,6 must 10 & SR1A bit 6 set Dual or Single
  5873. VideoPortWritePortUchar (CRTCAddrPort, 0x1C);
  5874. temp2 = VideoPortReadPortUchar(CRTCDataPort) & 0xC0;
  5875. if (temp2 == 0) //STN mono LCD
  5876. {
  5877. if (temp1 == 0)
  5878. temp3 |= (USHORT)Dual_LCD | Mono_LCD | STN_LCD;
  5879. else
  5880. temp3 |= (USHORT)Single_LCD | Mono_LCD | STN_LCD;
  5881. }
  5882. else if (temp2 == 0x80) //STN color LCD
  5883. {
  5884. if (temp4)
  5885. {
  5886. temp3 |= (USHORT)Dual_LCD | Color_LCD | STN_LCD;
  5887. }
  5888. else
  5889. {
  5890. temp3 |= (USHORT)Single_LCD | Color_LCD | STN_LCD;
  5891. }
  5892. }
  5893. else if (temp2 == 0xC0) //TFT LCD
  5894. {
  5895. temp3 |= (USHORT)TFT_LCD; //myf28
  5896. }
  5897. // Restore LCD Display Controls register and CRTC index to original state
  5898. //
  5899. VideoPortWritePortUchar(CRTCAddrPort, originalCRTCIndex);
  5900. return (temp3 | panel);
  5901. }
  5902. else // the display is a crt
  5903. {
  5904. VideoPortWritePortUchar(CRTCAddrPort, originalCRTCIndex);
  5905. return (temp3);
  5906. }
  5907. } // CirrusFind6245DisplayType()
  5908. // end crus
  5909. //---------------------------------------------------------------------------
  5910. USHORT
  5911. CirrusFind754xDisplayType(
  5912. PHW_DEVICE_EXTENSION HwDeviceExtension,
  5913. PUCHAR CRTCAddrPort, PUCHAR CRTCDataPort
  5914. )
  5915. /*++
  5916. Routine Description:
  5917. Determines the display type for CL754x crt/panel controllers.
  5918. Arguments:
  5919. HwDeviceExtension - Pointer to the miniport driver's device extension.
  5920. CRTCAddrPort, CRTCDataPort - Index of CRTC registers for current mode.
  5921. Return Value:
  5922. crt, panel, or panel8x6 as defined in cirrus.h
  5923. --*/
  5924. {
  5925. // crus
  5926. //
  5927. // update 754X Display Type Detect code
  5928. //
  5929. UCHAR originalCRTCIndex, originalLCDControl; // temp1;
  5930. UCHAR originalSEQIndex;
  5931. USHORT temp1, temp2, temp4;
  5932. USHORT temp3, temp5; // crus
  5933. // we need to check to see which display we are on...
  5934. //
  5935. originalCRTCIndex = VideoPortReadPortUchar(CRTCAddrPort);
  5936. VideoPortWritePortUchar(CRTCAddrPort, 0x20);
  5937. temp1 = VideoPortReadPortUchar(CRTCDataPort);
  5938. temp3 = 0; temp4 = 0; //myf28
  5939. if (temp1 & 0x40) temp3 = 1;
  5940. if (!(temp1 & 0x20)) temp3 |= Jump_type; //myf27
  5941. else temp3 &= (~Jump_type); //myf27,myf28
  5942. //myf27 if (temp1 & 0x20)
  5943. {
  5944. originalSEQIndex =
  5945. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  5946. SEQ_ADDRESS_PORT);
  5947. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  5948. SEQ_ADDRESS_PORT, 0x21);
  5949. temp4 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  5950. SEQ_DATA_PORT) & 0x40;
  5951. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  5952. SEQ_ADDRESS_PORT, originalSEQIndex);
  5953. // bit 5 set indicates that display is on LCD Panel
  5954. // Check extended reg to see if panel supports 800x600 display
  5955. //
  5956. VideoPortWritePortUchar(CRTCAddrPort, 0x2D);
  5957. originalLCDControl = VideoPortReadPortUchar(CRTCDataPort);
  5958. // Allow access to extended CRTC regs and read R9X[3:2]
  5959. //
  5960. VideoPortWritePortUchar(CRTCDataPort,
  5961. (UCHAR) (originalLCDControl | 0x80));
  5962. VideoPortWritePortUchar(CRTCAddrPort, 0x09);
  5963. temp1 = (VideoPortReadPortUchar(CRTCDataPort) & 0x0C) >> 2;
  5964. VideoPortWritePortUchar (CRTCAddrPort, 0x08);
  5965. temp5 = VideoPortReadPortUchar(CRTCDataPort) & 0x20;
  5966. VideoPortWritePortUchar (CRTCAddrPort, 0x2D);
  5967. VideoPortWritePortUchar (CRTCDataPort, originalLCDControl);
  5968. // CR2C bit 6,7 set indicate LCD type, TFT, STN color or STN mono
  5969. // STN mono, R8X bit 5 set Single or Dual
  5970. // STN color, CR2C bit 7,6 must 10 & SR21 bit 6 set Dual or Single
  5971. VideoPortWritePortUchar (CRTCAddrPort, 0x2C);
  5972. temp2 = VideoPortReadPortUchar(CRTCDataPort) & 0xC0;
  5973. if (temp2 == 0) //STN mono LCD
  5974. {
  5975. if (temp5 == 0)
  5976. temp3 |= (USHORT)Dual_LCD | Mono_LCD | STN_LCD;
  5977. else
  5978. temp3 |= (USHORT)Single_LCD | Mono_LCD | STN_LCD;
  5979. }
  5980. else if (temp2 == 0x80) //STN color LCD
  5981. {
  5982. if (temp4)
  5983. {
  5984. temp3 |= (USHORT)Dual_LCD | Color_LCD | STN_LCD;
  5985. }
  5986. else
  5987. {
  5988. temp3 |= (USHORT)Single_LCD | Color_LCD | STN_LCD;
  5989. }
  5990. }
  5991. else if (temp2 == 0xC0) //TFT LCD
  5992. {
  5993. temp3 |= (USHORT)TFT_LCD; //myf28
  5994. }
  5995. // Restore LCD Display Controls register and CRTC index to original state
  5996. //
  5997. VideoPortWritePortUchar(CRTCAddrPort, originalCRTCIndex);
  5998. if (temp1 == 1) // this means panel connected is 800x600
  5999. {
  6000. // will support either 800x600 or 640x480
  6001. // return panel type
  6002. return (temp3 | panel8x6);
  6003. }
  6004. else if (temp1 == 2)
  6005. {
  6006. return (temp3 | panel10x7);
  6007. }
  6008. else if (temp1 == 0)
  6009. {
  6010. return (temp3 | panel);
  6011. }
  6012. else //temp1 =4 :reserve
  6013. {
  6014. return (temp3);
  6015. }
  6016. }
  6017. //myf27 else // the display is a crt
  6018. //myf27 {
  6019. //myf27 VideoPortWritePortUchar(CRTCAddrPort, originalCRTCIndex);
  6020. //myf27 return (temp3);
  6021. //myf27 }
  6022. } // CirrusFind754xDisplayType()
  6023. //---------------------------------------------------------------------------
  6024. USHORT
  6025. CirrusFind755xDisplayType(
  6026. PHW_DEVICE_EXTENSION HwDeviceExtension,
  6027. PUCHAR CRTCAddrPort, PUCHAR CRTCDataPort
  6028. )
  6029. /*++
  6030. Routine Description:
  6031. Determines the display type for CL754x crt/panel controllers.
  6032. Arguments:
  6033. HwDeviceExtension - Pointer to the miniport driver's device extension.
  6034. CRTCAddrPort, CRTCDataPort - Index of CRTC registers for current mode.
  6035. Return Value:
  6036. crt, panel, or panel8x6 LCD_type as defined in cirrus.h
  6037. --*/
  6038. {
  6039. UCHAR originalCRTCIndex, originalLCDControl;
  6040. USHORT temp1, temp2, temp3;
  6041. // we need to check to see which display we are on...
  6042. //
  6043. originalCRTCIndex = VideoPortReadPortUchar(CRTCAddrPort);
  6044. VideoPortWritePortUchar(CRTCAddrPort, 0x80);
  6045. temp3 = 0;
  6046. if (VideoPortReadPortUchar(CRTCDataPort) & 0x02) temp3 = crt;
  6047. if (!(VideoPortReadPortUchar(CRTCDataPort) & 0x01)) //myf27
  6048. temp3 |= Jump_type; //myf27
  6049. else temp3 &= (~Jump_type); //myf27, myf28
  6050. //myf27 if (VideoPortReadPortUchar(CRTCDataPort) & 0x01)
  6051. {
  6052. // bit 0 set indicates that display is on LCD Panel
  6053. // Check extended reg to see panel data format
  6054. //
  6055. VideoPortWritePortUchar (CRTCAddrPort, 0x83);
  6056. originalLCDControl = VideoPortReadPortUchar(CRTCDataPort);
  6057. temp1 = originalLCDControl & 0x03;
  6058. // check LCD support mode
  6059. // CR83 bit 6:4 set indicate LCD type, TFT, DSTN color
  6060. temp2 = originalLCDControl & 0x70;
  6061. // temp3 = crt; //myf7, crus
  6062. if (temp2 == 0) //DSTN color LCD
  6063. {
  6064. temp3 |= Dual_LCD | Color_LCD | STN_LCD;
  6065. }
  6066. else if (temp2 == 0x20) //TFT color LCD
  6067. temp3 |= (USHORT)TFT_LCD;
  6068. // Restore CRTC index to original state
  6069. //
  6070. VideoPortWritePortUchar(CRTCAddrPort, originalCRTCIndex);
  6071. if (temp1 == 1) // this means panel connected is 800x600
  6072. {
  6073. // will support either 800x600 or 640x480
  6074. return (temp3 | panel8x6);
  6075. }
  6076. else if (temp1 == 2)
  6077. {
  6078. return (temp3 | panel10x7);
  6079. }
  6080. else
  6081. {
  6082. return (temp3 | panel);
  6083. }
  6084. }
  6085. //myf27 else // the display is a crt
  6086. //myf27 {
  6087. //myf27 VideoPortWritePortUchar(CRTCAddrPort, originalCRTCIndex);
  6088. //myf27 return crt;
  6089. //myf27 }
  6090. } // CirrusFind755xDisplayType()
  6091. //---------------------------------------------------------------------------
  6092. BOOLEAN
  6093. CirrusFind6340(
  6094. PHW_DEVICE_EXTENSION HwDeviceExtension
  6095. )
  6096. /*++
  6097. Routine Description:
  6098. Determines if a CL6340 (Peacock) Color LCD controller is in the system
  6099. along with a 6410 or 6420.
  6100. Assumes that a 6410 or 6420 is already in the system.
  6101. Arguments:
  6102. HwDeviceExtension - Pointer to the miniport driver's device extension.
  6103. Return Value:
  6104. TRUE, 6340 detected
  6105. FALSE, 6340 not detected
  6106. --*/
  6107. {
  6108. UCHAR originalGraphicsIndex;
  6109. UCHAR originalSRIndex;
  6110. UCHAR GRA1value;
  6111. UCHAR temp1,temp2;
  6112. originalGraphicsIndex =
  6113. VideoPortReadPortUchar((HwDeviceExtension->IOAddress +
  6114. GRAPH_ADDRESS_PORT));
  6115. originalSRIndex =
  6116. VideoPortReadPortUchar((HwDeviceExtension->IOAddress +
  6117. SEQ_ADDRESS_PORT));
  6118. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  6119. GRAPH_ADDRESS_PORT, CL64xx_TRISTATE_CONTROL_REG);
  6120. GRA1value = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  6121. GRAPH_DATA_PORT);
  6122. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  6123. GRAPH_DATA_PORT, (UCHAR) (0x80 | GRA1value));
  6124. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  6125. SEQ_ADDRESS_PORT), (USHORT) CL6340_ENABLE_READBACK_REGISTER +
  6126. (CL6340_ENABLE_READBACK_ALLSEL_VALUE << 8));
  6127. VideoPortWritePortUchar((HwDeviceExtension->IOAddress +
  6128. SEQ_ADDRESS_PORT), CL6340_IDENTIFICATION_REGISTER);
  6129. temp1 = VideoPortReadPortUchar((HwDeviceExtension->IOAddress +
  6130. SEQ_DATA_PORT));
  6131. temp2 = VideoPortReadPortUchar((HwDeviceExtension->IOAddress +
  6132. SEQ_DATA_PORT));
  6133. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  6134. SEQ_ADDRESS_PORT), (USHORT) CL6340_ENABLE_READBACK_REGISTER +
  6135. (CL6340_ENABLE_READBACK_OFF_VALUE << 8));
  6136. // Graphics index still points to CL64xx_TRISTATE_CONTROL_REG
  6137. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  6138. GRAPH_DATA_PORT, (UCHAR) (0x7f & GRA1value));
  6139. // now restore the Graphics and Sequencer indexes
  6140. VideoPortWritePortUchar((HwDeviceExtension->IOAddress +
  6141. GRAPH_ADDRESS_PORT),originalGraphicsIndex);
  6142. VideoPortWritePortUchar((HwDeviceExtension->IOAddress +
  6143. SEQ_ADDRESS_PORT),originalSRIndex);
  6144. // check the values for value peacock data
  6145. if ( ((temp1 & 0xf0) == 0x70 && (temp2 & 0xf0) == 0x80) ||
  6146. ((temp1 & 0xf0) == 0x80 && (temp2 & 0xf0) == 0x70) )
  6147. return TRUE;
  6148. else
  6149. return FALSE;
  6150. } // CirrusFind6410DisplayType()
  6151. BOOLEAN
  6152. CirrusConfigurePCI(
  6153. PHW_DEVICE_EXTENSION HwDeviceExtension,
  6154. PULONG NumPCIAccessRanges,
  6155. PVIDEO_ACCESS_RANGE PCIAccessRanges
  6156. )
  6157. {
  6158. USHORT VendorId = 0x1013; // Vender Id for Cirrus Logic
  6159. //
  6160. // The device id order is important. We want "most powerful"
  6161. // first on the assumption that someone might want to plug
  6162. // in a "more powerful" adapter into a system that has a "less
  6163. // powerful" on-board device.
  6164. //
  6165. USHORT DeviceId[] = {0x00BC, // 5480
  6166. 0x00B8, // 5446
  6167. 0x00AC, // 5436
  6168. 0x00E8, // UM36
  6169. 0x00A8, // 5434
  6170. 0x00A0, // 5430/5440
  6171. 0x1200, // Nordic
  6172. 0x1202, // Viking
  6173. 0x1204, // Nordic Light
  6174. 0x0038, // Everest, myf14, crus
  6175. 0x0040, // Matterhorn
  6176. 0x004C, // Matterhorn, LV, myf17
  6177. 0};
  6178. ULONG Slot;
  6179. ULONG ulRet;
  6180. PUSHORT pDeviceId;
  6181. VP_STATUS status;
  6182. UCHAR Command;
  6183. PCI_COMMON_CONFIG pciBuffer; // jl02
  6184. PPCI_COMMON_CONFIG pciData; // jl02
  6185. VIDEO_ACCESS_RANGE AccessRanges[3];
  6186. VideoPortZeroMemory(AccessRanges, 3 * sizeof(VIDEO_ACCESS_RANGE));
  6187. pDeviceId = DeviceId;
  6188. while (*pDeviceId != 0)
  6189. {
  6190. Slot = 0;
  6191. status = VideoPortGetAccessRanges(HwDeviceExtension,
  6192. 0,
  6193. NULL,
  6194. 3,
  6195. AccessRanges,
  6196. &VendorId,
  6197. pDeviceId,
  6198. &Slot);
  6199. if (status == NO_ERROR)
  6200. {
  6201. VideoDebugPrint((2, "\t Found Cirrus chip in Slot[0x%02.2x]\n",
  6202. Slot));
  6203. PCIAccessRanges[3].RangeStart = AccessRanges[0].RangeStart;
  6204. PCIAccessRanges[3].RangeLength = AccessRanges[0].RangeLength;
  6205. VideoDebugPrint((1, "VideoMemoryAddress %x , length %x\n",
  6206. PCIAccessRanges[3].RangeStart.LowPart,
  6207. PCIAccessRanges[3].RangeLength));
  6208. // sge01 begin
  6209. //
  6210. // checking CL5480 or CL5446BE
  6211. //
  6212. pciData = (PPCI_COMMON_CONFIG) &pciBuffer;
  6213. VideoPortGetBusData(HwDeviceExtension,
  6214. PCIConfiguration,
  6215. Slot,
  6216. (PVOID) pciData,
  6217. 0,
  6218. PCI_COMMON_HDR_LENGTH);
  6219. #if (_WIN32_WINNT >= 0x0400)
  6220. if ((pciData->DeviceID == 0x00B8 && pciData->RevisionID == 0x45)
  6221. || (pciData->DeviceID == 0x00BC))
  6222. {
  6223. HwDeviceExtension->bMMAddress = TRUE;
  6224. HwDeviceExtension->bSecondAperture = TRUE;
  6225. PCIAccessRanges[4].RangeStart = AccessRanges[1].RangeStart;
  6226. PCIAccessRanges[4].RangeLength = AccessRanges[1].RangeLength;
  6227. VideoDebugPrint((1, "MMIOMemoryAddress %x , length %x\n",
  6228. PCIAccessRanges[2].RangeStart.LowPart,
  6229. PCIAccessRanges[2].RangeLength));
  6230. //
  6231. // Assign pfnVideoPortReadXxx and pfnVideoPortWriteXxx
  6232. //
  6233. HwDeviceExtension->gPortRWfn.pfnVideoPortReadPortUchar = VideoPortReadRegisterUchar;
  6234. HwDeviceExtension->gPortRWfn.pfnVideoPortReadPortUshort = VideoPortReadRegisterUshort;
  6235. HwDeviceExtension->gPortRWfn.pfnVideoPortReadPortUlong = VideoPortReadRegisterUlong;
  6236. HwDeviceExtension->gPortRWfn.pfnVideoPortWritePortUchar = VideoPortWriteRegisterUchar;
  6237. HwDeviceExtension->gPortRWfn.pfnVideoPortWritePortUshort = VideoPortWriteRegisterUshort;
  6238. HwDeviceExtension->gPortRWfn.pfnVideoPortWritePortUlong = VideoPortWriteRegisterUlong;
  6239. }
  6240. #else // else of NT 4.0
  6241. if ((pciData->DeviceID == 0x00BC) ||
  6242. ((pciData->DeviceID == 0x00B8) && (pciData->RevisionID == 0x45)))
  6243. {
  6244. HwDeviceExtension->bMMAddress = FALSE;
  6245. HwDeviceExtension->bSecondAperture = TRUE;
  6246. //
  6247. //
  6248. // Assign pfnVideoPortReadXxx and pfnVideoPortWriteXxx
  6249. //
  6250. HwDeviceExtension->gPortRWfn.pfnVideoPortReadPortUchar = VideoPortReadPortUchar;
  6251. HwDeviceExtension->gPortRWfn.pfnVideoPortReadPortUshort = VideoPortReadPortUshort;
  6252. HwDeviceExtension->gPortRWfn.pfnVideoPortReadPortUlong = VideoPortReadPortUlong;
  6253. HwDeviceExtension->gPortRWfn.pfnVideoPortWritePortUchar = VideoPortWritePortUchar;
  6254. HwDeviceExtension->gPortRWfn.pfnVideoPortWritePortUshort = VideoPortWritePortUshort;
  6255. HwDeviceExtension->gPortRWfn.pfnVideoPortWritePortUlong = VideoPortWritePortUlong;
  6256. }
  6257. #endif // end of NT 4.0
  6258. else
  6259. {
  6260. HwDeviceExtension->bMMAddress = FALSE;
  6261. HwDeviceExtension->bSecondAperture = FALSE;
  6262. //
  6263. // Assign pfnVideoPortReadXxx and pfnVideoPortWriteXxx
  6264. //
  6265. HwDeviceExtension->gPortRWfn.pfnVideoPortReadPortUchar = VideoPortReadPortUchar;
  6266. HwDeviceExtension->gPortRWfn.pfnVideoPortReadPortUshort = VideoPortReadPortUshort;
  6267. HwDeviceExtension->gPortRWfn.pfnVideoPortReadPortUlong = VideoPortReadPortUlong;
  6268. HwDeviceExtension->gPortRWfn.pfnVideoPortWritePortUchar = VideoPortWritePortUchar;
  6269. HwDeviceExtension->gPortRWfn.pfnVideoPortWritePortUshort = VideoPortWritePortUshort;
  6270. HwDeviceExtension->gPortRWfn.pfnVideoPortWritePortUlong = VideoPortWritePortUlong;
  6271. }
  6272. VideoDebugPrint((1, "Read Write Functions are mapped"));
  6273. //sge01 end
  6274. return TRUE;
  6275. }
  6276. else
  6277. {
  6278. //
  6279. // We did not find the device. Use the next device ID.
  6280. //
  6281. VideoDebugPrint((1, "Check for DeviceID = %x failed.\n", *pDeviceId));
  6282. pDeviceId++;
  6283. }
  6284. }
  6285. VideoDebugPrint((1, "Returning a false from CirrusConfigurePCI\n"));
  6286. return FALSE;
  6287. }
  6288. VOID
  6289. WriteRegistryInfo(
  6290. PHW_DEVICE_EXTENSION hwDeviceExtension
  6291. )
  6292. {
  6293. PWSTR pwszChipType;
  6294. ULONG cbString;
  6295. PWSTR pnpId;
  6296. //
  6297. // Store Memory Size
  6298. //
  6299. VideoPortSetRegistryParameters(hwDeviceExtension,
  6300. L"HardwareInformation.MemorySize",
  6301. &hwDeviceExtension->AdapterMemorySize,
  6302. sizeof(ULONG));
  6303. //
  6304. // Store chip Type
  6305. //
  6306. switch (hwDeviceExtension->ChipType)
  6307. {
  6308. case CL6410: pwszChipType = L"Cirrus Logic 6410";
  6309. cbString = sizeof(L"Cirrus Logic 6410");
  6310. pnpId = L"*PNP0904";
  6311. break;
  6312. case CL6420: pwszChipType = L"Cirrus Logic 6420";
  6313. cbString = sizeof(L"Cirrus Logic 6420");
  6314. pnpId = L"*PNP0904";
  6315. break;
  6316. case CL542x: if (hwDeviceExtension->ChipRevision >= 0x22 &&
  6317. hwDeviceExtension->ChipRevision <= 0x27)
  6318. {
  6319. static PWSTR RevTable[] = { L"Cirrus Logic 5420",
  6320. L"Cirrus Logic 5422",
  6321. L"Cirrus Logic 5426", // yes, the 26
  6322. L"Cirrus Logic 5424", // is before
  6323. L"Cirrus Logic 5428", // the 24
  6324. L"Cirrus Logic 5429" };
  6325. pwszChipType =
  6326. RevTable[hwDeviceExtension->ChipRevision - 0x22];
  6327. }
  6328. else
  6329. {
  6330. pwszChipType = L"Cirrus Logic 542x";
  6331. }
  6332. cbString = sizeof(L"Cirrus Logic 542x");
  6333. pnpId = L"*PNP0904";
  6334. break;
  6335. case CL543x: if (hwDeviceExtension->ChipRevision == CL5430_ID)
  6336. {
  6337. pwszChipType = L"Cirrus Logic 5430/40"; // chu04
  6338. cbString = sizeof(L"Cirrus Logic 5430/40"); // chu04
  6339. }
  6340. else
  6341. {
  6342. pwszChipType = L"Cirrus Logic 543x";
  6343. cbString = sizeof(L"Cirrus Logic 543x");
  6344. }
  6345. pnpId = L"*PNP0905";
  6346. break;
  6347. case CL5434_6:
  6348. pwszChipType = L"Cirrus Logic 5434 (.6 micron)";
  6349. cbString = sizeof(L"Cirrus Logic 5434 (.6 micron)");
  6350. pnpId = L"*PNP0905";
  6351. break;
  6352. case CL5434: pwszChipType = L"Cirrus Logic 5434";
  6353. cbString = sizeof(L"Cirrus Logic 5434");
  6354. pnpId = L"*PNP0905";
  6355. break;
  6356. case CL5436: pwszChipType = L"Cirrus Logic 5436";
  6357. cbString = sizeof(L"Cirrus Logic 5436");
  6358. pnpId = L"*PNP0905";
  6359. break;
  6360. case CL5446: pwszChipType = L"Cirrus Logic 5446";
  6361. cbString = sizeof(L"Cirrus Logic 5446");
  6362. pnpId = L"*PNP0905";
  6363. break;
  6364. #if 1 // jl02
  6365. case CL5446BE:
  6366. pwszChipType = L"Cirrus Logic 5446BE";
  6367. cbString = sizeof(L"Cirrus Logic 5446BE");
  6368. pnpId = L"*PNP0905";
  6369. break;
  6370. #endif // jl02
  6371. case CL5480: pwszChipType = L"Cirrus Logic 5480";
  6372. cbString = sizeof(L"Cirrus Logic 5480");
  6373. pnpId = L"*PNP0905";
  6374. break;
  6375. //myf32 begin
  6376. case CL7541: pwszChipType = L"Cirrus Logic 7541";
  6377. cbString = sizeof(L"Cirrus Logic 7541");
  6378. pnpId = L"*PNP0914";
  6379. break;
  6380. case CL7542: pwszChipType = L"Cirrus Logic 7542";
  6381. cbString = sizeof(L"Cirrus Logic 7542");
  6382. pnpId = L"*PNP0914";
  6383. break;
  6384. case CL7543: pwszChipType = L"Cirrus Logic 7543";
  6385. cbString = sizeof(L"Cirrus Logic 7543");
  6386. pnpId = L"*PNP0914";
  6387. break;
  6388. case CL7548: pwszChipType = L"Cirrus Logic 7548";
  6389. cbString = sizeof(L"Cirrus Logic 7548");
  6390. pnpId = L"*PNP0914";
  6391. break;
  6392. case CL7555: pwszChipType = L"Cirrus Logic 7555";
  6393. cbString = sizeof(L"Cirrus Logic 7555");
  6394. pnpId = L"*PNP0914";
  6395. break;
  6396. case CL7556: pwszChipType = L"Cirrus Logic 7556";
  6397. cbString = sizeof(L"Cirrus Logic 7556");
  6398. pnpId = L"*PNP0914";
  6399. break;
  6400. //myf32
  6401. case CL756x: pwszChipType = L"Cirrus Logic 756x";
  6402. cbString = sizeof(L"Cirrus Logic 756x");
  6403. pnpId = L"*PNP0914";
  6404. break;
  6405. // crus
  6406. case CL6245: pwszChipType = L"Cirrus Logic 6245";
  6407. cbString = sizeof(L"Cirrus Logic 6245");
  6408. pnpId = L"*PNP0904";
  6409. break;
  6410. default:
  6411. //
  6412. // we should never get here
  6413. //
  6414. ASSERT(FALSE);
  6415. pwszChipType = NULL;
  6416. cbString = 0;
  6417. pnpId = NULL;
  6418. }
  6419. if (pnpId)
  6420. {
  6421. memcpy(hwDeviceExtension->LegacyPnPId, pnpId, 8*sizeof(WCHAR));
  6422. }
  6423. VideoPortSetRegistryParameters(hwDeviceExtension,
  6424. L"HardwareInformation.ChipType",
  6425. pwszChipType,
  6426. cbString);
  6427. //
  6428. // Store Adapter String
  6429. //
  6430. // the only interesting adapter string is
  6431. // for the speedstar pro
  6432. //
  6433. #pragma prefast(suppress: 209, "Byte count is correct here (PREfast bug 611168)")
  6434. VideoPortSetRegistryParameters(hwDeviceExtension,
  6435. L"HardwareInformation.DacType",
  6436. L"Integrated RAMDAC",
  6437. sizeof(L"Integrated RAMDAC") );
  6438. if( hwDeviceExtension->BoardType == SPEEDSTARPRO )
  6439. {
  6440. #pragma prefast(suppress: 209, "Byte count is correct here (PREfast bug 611168)")
  6441. VideoPortSetRegistryParameters(hwDeviceExtension,
  6442. L"HardwareInformation.AdapterString",
  6443. L"SpeedStar PRO",
  6444. sizeof(L"SpeedStar PRO"));
  6445. }
  6446. else
  6447. {
  6448. #pragma prefast(suppress: 209, "Byte count is correct here (PREfast bug 611168)")
  6449. VideoPortSetRegistryParameters(hwDeviceExtension,
  6450. L"HardwareInformation.AdapterString",
  6451. L"Cirrus Logic Compatible",
  6452. sizeof (L"Cirrus Logic Compatible") );
  6453. }
  6454. }
  6455. VOID
  6456. IOWaitDisplEnableThenWrite(
  6457. PHW_DEVICE_EXTENSION hwDeviceExtension,
  6458. ULONG portIO,
  6459. UCHAR value
  6460. )
  6461. {
  6462. PHW_DEVICE_EXTENSION HwDeviceExtension = hwDeviceExtension;
  6463. USHORT FCReg ; // feature control register
  6464. UCHAR PSReg ; // 3?4.25
  6465. UCHAR DeviceID ; // 3?4.27
  6466. UCHAR bIsColor ; // 1 : Color, 0 : Mono
  6467. UCHAR tempB, tempB1 ;
  6468. ULONG port ;
  6469. PUCHAR CRTCAddrPort, CRTCDataPort;
  6470. // Figure out if color/mono switchable registers are at 3BX or 3DX.
  6471. port = PtrToUlong(hwDeviceExtension->IOAddress) + portIO ;
  6472. tempB = VideoPortReadPortUchar (hwDeviceExtension->IOAddress +
  6473. MISC_OUTPUT_REG_READ_PORT) ;
  6474. tempB &= 0x01 ;
  6475. if (tempB)
  6476. {
  6477. bIsColor = TRUE ;
  6478. FCReg = FEAT_CTRL_WRITE_PORT_COLOR ;
  6479. CRTCAddrPort = hwDeviceExtension->IOAddress + CRTC_ADDRESS_PORT_COLOR;
  6480. }
  6481. else
  6482. {
  6483. bIsColor = FALSE ;
  6484. FCReg = FEAT_CTRL_WRITE_PORT_MONO ;
  6485. CRTCAddrPort = hwDeviceExtension->IOAddress + CRTC_ADDRESS_PORT_MONO;
  6486. }
  6487. CRTCDataPort = CRTCAddrPort + 1;
  6488. tempB = VideoPortReadPortUchar(CRTCAddrPort);
  6489. VideoPortWritePortUchar(CRTCAddrPort, 0x27);
  6490. DeviceID = VideoPortReadPortUchar(CRTCDataPort);
  6491. VideoPortWritePortUchar(CRTCAddrPort, 0x25);
  6492. PSReg = VideoPortReadPortUchar(CRTCDataPort);
  6493. VideoPortWritePortUchar (CRTCAddrPort, tempB);
  6494. if ((DeviceID == 0xAC) && // 5436
  6495. ((PSReg == 0x45) || (PSReg == 0x47))) // BG or BE
  6496. {
  6497. hwDeviceExtension->DEPort = portIO;
  6498. hwDeviceExtension->DEValue = value;
  6499. while (!(0x1 & VideoPortReadPortUchar(hwDeviceExtension->IOAddress + FCReg)));
  6500. while ( (0x1 & VideoPortReadPortUchar(hwDeviceExtension->IOAddress + FCReg)));
  6501. VideoPortSynchronizeExecution(hwDeviceExtension,
  6502. VpHighPriority,
  6503. (PMINIPORT_SYNCHRONIZE_ROUTINE) IOCallback,
  6504. hwDeviceExtension);
  6505. }
  6506. else
  6507. {
  6508. VideoPortWritePortUchar(hwDeviceExtension->IOAddress + portIO, value);
  6509. }
  6510. } // IOWaitDisplEnableThenWrite
  6511. //sge08
  6512. VOID
  6513. CirrusUpdate440FX(
  6514. PHW_DEVICE_EXTENSION HwDeviceExtension
  6515. )
  6516. /*++
  6517. Routine Description:
  6518. Check and Update 440FX PCI[53] bit 1 if necessary.
  6519. Arguments:
  6520. HwDeviceExtension - Pointer to the miniport driver's device extension.
  6521. Return Value:
  6522. The routine has no return.
  6523. --*/
  6524. {
  6525. USHORT chipRevisionId ;
  6526. UCHAR chipId ;
  6527. PUCHAR pBuffer;
  6528. ULONG Slot;
  6529. USHORT VendorId = 0x8086; // Vender Id for Intel
  6530. USHORT DeviceId = 0x1237; // VS440FX
  6531. VP_STATUS status;
  6532. PCI_COMMON_CONFIG pciBuffer;
  6533. PPCI_COMMON_CONFIG pciData;
  6534. chipId = GetCirrusChipId(HwDeviceExtension) ; // chu06
  6535. chipRevisionId = GetCirrusChipRevisionId(HwDeviceExtension) ; // chu06
  6536. if ((chipId == 0xB8) && // 5446
  6537. (chipRevisionId == 0x0023)) // AC
  6538. {
  6539. //
  6540. // We got it's 5446AC, then to find 440FX
  6541. //
  6542. pciData = (PPCI_COMMON_CONFIG)&pciBuffer;
  6543. for (Slot = 0; Slot < 32; Slot++)
  6544. {
  6545. // chu05
  6546. // For 5436 checked build NT, system always crashes when you
  6547. // access the whole 256-byte PCI configuration registers.
  6548. // Since we only care index 53h bit 1, we access 4 bytes, rather
  6549. // than whole 256 bytes.
  6550. VideoPortGetBusData(HwDeviceExtension,
  6551. PCIConfiguration,
  6552. Slot,
  6553. (PVOID) pciData,
  6554. 0,
  6555. sizeof(PCI_COMMON_HDR_LENGTH)); // chu05
  6556. if ((pciData->VendorID == VendorId) &&
  6557. (pciData->DeviceID == DeviceId))
  6558. {
  6559. //
  6560. // Access a double word, which contains index 53h.
  6561. //
  6562. VideoPortGetBusData(HwDeviceExtension,
  6563. PCIConfiguration,
  6564. Slot,
  6565. (PVOID) pciData,
  6566. 0x53,
  6567. 0x04); // chu05
  6568. // We borrow the space which is the first 4 bytes of PCI
  6569. // configuration register. Please be aware that, at this
  6570. // moment, the content is index 53h, rather than
  6571. // vendor ID.
  6572. pciBuffer.DeviceSpecific[19] =
  6573. (UCHAR) pciData->VendorID ; // chu05
  6574. //
  6575. // Found the Intel VS440FX motherboard.
  6576. //
  6577. //
  6578. // Clear bit 1 of Register 0x53
  6579. //
  6580. pciBuffer.DeviceSpecific[19] &= 0xFD;
  6581. //
  6582. // Write Register 0x53 back.
  6583. //
  6584. pBuffer = (PUCHAR)&pciBuffer;
  6585. pBuffer += 0x53;
  6586. VideoPortSetBusData(HwDeviceExtension,
  6587. PCIConfiguration,
  6588. Slot,
  6589. (PVOID) pBuffer,
  6590. 0x53,
  6591. 1);
  6592. //
  6593. // Read back only 4 bytes to verify it.
  6594. //
  6595. VideoPortGetBusData(HwDeviceExtension,
  6596. PCIConfiguration,
  6597. Slot,
  6598. (PVOID) pciData,
  6599. 0x53,
  6600. 0x04); // chu05
  6601. break; // we have already modify it
  6602. }
  6603. }
  6604. }
  6605. }
  6606.