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.

5792 lines
171 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. vga.c
  5. Abstract:
  6. This is the miniport driver for the VGA card.
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. Revision History:
  11. --*/
  12. #include "dderror.h"
  13. #include "devioctl.h"
  14. #include "miniport.h"
  15. #include "ntddvdeo.h"
  16. #include "video.h"
  17. #include "vga.h"
  18. #include "vesa.h"
  19. #define DEBUG_CODE
  20. #if defined(DEBUG_CODE)
  21. ULONG TrapRoutineEntered = 0;
  22. #if defined(_X86_)
  23. #define MY_ASSERT __asm {int 3}
  24. #else
  25. #define MY_ASSERT
  26. #endif
  27. #endif
  28. VP_STATUS
  29. GetDeviceDataCallback(
  30. PVOID HwDeviceExtension,
  31. PVOID Context,
  32. VIDEO_DEVICE_DATA_TYPE DeviceDataType,
  33. PVOID Identifier,
  34. ULONG IdentifierLength,
  35. PVOID ConfigurationData,
  36. ULONG ConfigurationDataLength,
  37. PVOID ComponentInformation,
  38. ULONG ComponentInformationLength
  39. );
  40. #if defined(ALLOC_PRAGMA)
  41. #pragma alloc_text(INIT,DriverEntry)
  42. #pragma alloc_text(PAGE,VgaFindAdapter)
  43. #pragma alloc_text(PAGE,VgaInitialize)
  44. #pragma alloc_text(PAGE,VgaStartIO)
  45. #pragma alloc_text(PAGE,VgaLoadAndSetFont)
  46. #pragma alloc_text(PAGE,VgaQueryCursorPosition)
  47. #pragma alloc_text(PAGE,VgaSetCursorPosition)
  48. #pragma alloc_text(PAGE,VgaQueryCursorAttributes)
  49. #pragma alloc_text(PAGE,VgaSetCursorAttributes)
  50. #pragma alloc_text(PAGE,VgaIsPresent)
  51. #pragma alloc_text(PAGE,VgaSetPaletteReg)
  52. #pragma alloc_text(PAGE,VgaSetColorLookup)
  53. #pragma alloc_text(PAGE,VgaRestoreHardwareState)
  54. #pragma alloc_text(PAGE,VgaSaveHardwareState)
  55. #pragma alloc_text(PAGE,VgaGetBankSelectCode)
  56. #pragma alloc_text(PAGE,VgaValidatorUcharEntry)
  57. #pragma alloc_text(PAGE,VgaValidatorUshortEntry)
  58. #pragma alloc_text(PAGE,VgaValidatorUlongEntry)
  59. #pragma alloc_text(PAGE,GetDeviceDataCallback)
  60. #pragma alloc_text(PAGE,VgaSetBankPosition)
  61. #pragma alloc_text(PAGE,VgaAcquireResources)
  62. #pragma alloc_text(PAGE,VgaGetPowerState)
  63. #pragma alloc_text(PAGE,VgaSetPowerState)
  64. #pragma alloc_text(PAGE,VgaGetChildDescriptor)
  65. #pragma alloc_text(PAGE,VgaGetMonitorEdid)
  66. #endif
  67. ULONG
  68. DriverEntry(
  69. PVOID Context1,
  70. PVOID Context2
  71. )
  72. /*++
  73. Routine Description:
  74. Installable driver initialization entry point.
  75. This entry point is called directly by the I/O system.
  76. Arguments:
  77. Context1 - First context value passed by the operating system. This is
  78. the value with which the miniport driver calls VideoPortInitialize().
  79. Context2 - Second context value passed by the operating system. This is
  80. the value with which the miniport driver calls VideoPortInitialize().
  81. Return Value:
  82. Status from VideoPortInitialize()
  83. --*/
  84. {
  85. VIDEO_HW_INITIALIZATION_DATA hwInitData;
  86. ULONG initializationStatus;
  87. //
  88. // Zero out structure.
  89. //
  90. VideoPortZeroMemory(&hwInitData, sizeof(VIDEO_HW_INITIALIZATION_DATA));
  91. //
  92. // Specify sizes of structure and extension.
  93. //
  94. hwInitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA);
  95. //
  96. // Set entry points.
  97. //
  98. hwInitData.HwFindAdapter = VgaFindAdapter;
  99. hwInitData.HwInitialize = VgaInitialize;
  100. hwInitData.HwInterrupt = NULL;
  101. hwInitData.HwStartIO = VgaStartIO;
  102. #if defined(PLUG_AND_PLAY)
  103. hwInitData.HwGetPowerState = VgaGetPowerState;
  104. hwInitData.HwSetPowerState = VgaSetPowerState;
  105. hwInitData.HwGetVideoChildDescriptor = VgaGetChildDescriptor;
  106. hwInitData.HwLegacyResourceList = VgaAccessRange;
  107. hwInitData.HwLegacyResourceCount = NUM_STD_VGA_ACCESS_RANGES;
  108. #endif
  109. //
  110. // Determine the size we require for the device extension.
  111. //
  112. hwInitData.HwDeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
  113. //
  114. // Both numbers for these fields are zero since they are allocated
  115. // statically in the driver. We will pass pointers and sizes later in
  116. // the find adapter routine.
  117. //
  118. // hwInitData.NumberOfAccessRanges = 0;
  119. // hwInitData.NumEmulatorAccessEntries = 0;
  120. //
  121. // Always start with parameters for device0 in this case.
  122. // We can leave it like this since we know we will only ever find one
  123. // VGA type adapter in a machine.
  124. //
  125. // hwInitData.StartingDeviceNumber = 0;
  126. //
  127. // Once all the relevant information has been stored, call the video
  128. // port driver to do the initialization.
  129. //
  130. hwInitData.AdapterInterfaceType = Isa;
  131. initializationStatus = VideoPortInitialize(Context1,
  132. Context2,
  133. &hwInitData,
  134. NULL);
  135. if (initializationStatus == NO_ERROR)
  136. {
  137. return initializationStatus;
  138. }
  139. hwInitData.AdapterInterfaceType = PCIBus;
  140. initializationStatus = VideoPortInitialize(Context1,
  141. Context2,
  142. &hwInitData,
  143. NULL);
  144. if (initializationStatus == NO_ERROR)
  145. {
  146. return initializationStatus;
  147. }
  148. hwInitData.AdapterInterfaceType = Eisa;
  149. initializationStatus = VideoPortInitialize(Context1,
  150. Context2,
  151. &hwInitData,
  152. NULL);
  153. if (initializationStatus == NO_ERROR)
  154. {
  155. return initializationStatus;
  156. }
  157. hwInitData.AdapterInterfaceType = MicroChannel;
  158. initializationStatus = VideoPortInitialize(Context1,
  159. Context2,
  160. &hwInitData,
  161. NULL);
  162. if (initializationStatus == NO_ERROR)
  163. {
  164. return initializationStatus;
  165. }
  166. //
  167. // For MIPS ACER machines
  168. //
  169. // *** Must keep this at the end since it will cause the global access
  170. // range structure to change in the driver. ***
  171. //
  172. hwInitData.AdapterInterfaceType = Internal;
  173. initializationStatus = VideoPortInitialize(Context1,
  174. Context2,
  175. &hwInitData,
  176. NULL);
  177. return initializationStatus;
  178. } // end DriverEntry()
  179. VP_STATUS
  180. GetDeviceDataCallback(
  181. PVOID HwDeviceExtension,
  182. PVOID Context,
  183. VIDEO_DEVICE_DATA_TYPE DeviceDataType,
  184. PVOID Identifier,
  185. ULONG IdentifierLength,
  186. PVOID ConfigurationData,
  187. ULONG ConfigurationDataLength,
  188. PVOID ComponentInformation,
  189. ULONG ComponentInformationLength
  190. )
  191. {
  192. PVIDEO_ACCESS_RANGE accessRange = Context;
  193. PVIDEO_HARDWARE_CONFIGURATION_DATA configData = ConfigurationData;
  194. ULONG i;
  195. VideoDebugPrint((2, "VGA: controller information is present\n"));
  196. //
  197. // We do not want to try to detect the vga if there isn't one present.
  198. // (Kind of a paradox?) The only MIPS box I am aware of which has
  199. // an vga on the internal bus is the NeTPower NeTstation 100 and the Acer.
  200. // It has an identifier of "ALI_S3".
  201. //
  202. if (!Identifier)
  203. {
  204. return ERROR_DEV_NOT_EXIST;
  205. }
  206. if (VideoPortCompareMemory(L"ALI_S3",
  207. Identifier,
  208. sizeof(L"ALI_S3")) != sizeof(L"ALI_S3"))
  209. {
  210. return ERROR_DEV_NOT_EXIST;
  211. }
  212. //
  213. // Now lets get the base for the IO ports and memory location out of the
  214. // configuration information.
  215. //
  216. VideoDebugPrint((2, "VGA: Internal Bus, get new IO bases\n"));
  217. //
  218. // For MIPS machine with an Internal Bus, adjust the access ranges.
  219. //
  220. VideoDebugPrint((3, "VGA: FrameBase Offset = %08lx\n", configData->FrameBase));
  221. VideoDebugPrint((3, "VGA: IoBase Offset = %08lx\n", configData->ControlBase));
  222. for (i=0; i < NUM_VGA_ACCESS_RANGES; i++)
  223. {
  224. if (accessRange[i].RangeInIoSpace)
  225. {
  226. accessRange[i].RangeStart.LowPart += configData->ControlBase;
  227. accessRange[i].RangeInIoSpace = 0;
  228. }
  229. else
  230. {
  231. accessRange[i].RangeStart.LowPart += configData->FrameBase;
  232. }
  233. }
  234. return NO_ERROR;
  235. } //end GetDeviceDataCallback()
  236. #if !defined(PLUG_AND_PLAY)
  237. VP_STATUS
  238. VgaAcquireResources(
  239. PHW_DEVICE_EXTENSION HwDeviceExtension
  240. )
  241. /*++
  242. Routine Description:
  243. This routine tries to acquire the vga resources.
  244. Arguments:
  245. Pointer to HwDeviceExtension
  246. Returns:
  247. Status code indicating whether or not the resources where acquired.
  248. --*/
  249. {
  250. VP_STATUS status;
  251. ULONG i, NumVgaAccessRanges = NUM_VGA_ACCESS_RANGES;
  252. //
  253. // We only want the vga to claim resources if it loaded because
  254. // no other drivers were present. If other drivers were present,
  255. // and claimed VGA resources, then we should only function as a
  256. // vga compatible driver (provide full screen support).
  257. //
  258. // We'll do the following:
  259. //
  260. // (1) We'll try to grab VGA resources exclusively.
  261. //
  262. // (2) If we get the resources then we are operating as the fall
  263. // back device. No other video drivers loaded. Keep resources.
  264. //
  265. // (3) If we do not get the resources exclusively, try to claim
  266. // them shared.
  267. //
  268. // (4) If we get the resources then we are loading to provide vga
  269. // full screen support. Free the resource so that we aren't
  270. // holding legacy resources (so system can sleep/undock/etc).
  271. //
  272. // (5) If we still couldn't get the resources, then fail to load!
  273. //
  274. for (i=0; i<NUM_VGA_ACCESS_RANGES; i++) {
  275. VgaAccessRange[i].RangeShareable = FALSE;
  276. }
  277. status = VideoPortVerifyAccessRanges(HwDeviceExtension,
  278. NumVgaAccessRanges,
  279. VgaAccessRange);
  280. if (status != NO_ERROR) {
  281. //
  282. // Deal with the fact that the ATI HACK doesn't work
  283. // if the device is on the other side of a PCI bridge.
  284. //
  285. NumVgaAccessRanges -= 2;
  286. status = VideoPortVerifyAccessRanges(HwDeviceExtension,
  287. NumVgaAccessRanges,
  288. VgaAccessRange);
  289. if (status != NO_ERROR) {
  290. //
  291. // We couldn't get the resource exclusively. Try to get
  292. // them shared.
  293. //
  294. for (i=0; i<NumVgaAccessRanges; i++) {
  295. VgaAccessRange[i].RangeShareable = TRUE;
  296. }
  297. status = VideoPortVerifyAccessRanges(HwDeviceExtension,
  298. NumVgaAccessRanges,
  299. VgaAccessRange);
  300. if (status == NO_ERROR) {
  301. //
  302. // We were able to get the resource shared so we must be
  303. // providing vga full screen support. Release our claim
  304. // on resources.
  305. //
  306. VideoPortVerifyAccessRanges(HwDeviceExtension,
  307. 0,
  308. NULL);
  309. return NO_ERROR;
  310. } else {
  311. //
  312. // If we haven't gotten the resources by now, that means we
  313. // couldn't get them shared. This means we can't load at all.
  314. //
  315. return status;
  316. }
  317. }
  318. }
  319. //
  320. // We got the resources exclusively which means we are acting
  321. // as a fall back driver. But lets claim the resources as
  322. // shared so that a PnP Driver that uses the resources can still
  323. // load.
  324. //
  325. for (i=0; i<NumVgaAccessRanges; i++) {
  326. VgaAccessRange[i].RangeShareable = TRUE;
  327. }
  328. status = VideoPortVerifyAccessRanges(HwDeviceExtension,
  329. NumVgaAccessRanges,
  330. VgaAccessRange);
  331. return status;
  332. }
  333. #endif
  334. VP_STATUS
  335. VgaFindAdapter(
  336. PVOID HwDeviceExtension,
  337. PVOID HwContext,
  338. PWSTR ArgumentString,
  339. PVIDEO_PORT_CONFIG_INFO ConfigInfo,
  340. PUCHAR Again
  341. )
  342. /*++
  343. Routine Description:
  344. This routine is called to determine if the adapter for this driver
  345. is present in the system.
  346. If it is present, the function fills out some information describing
  347. the adapter.
  348. Arguments:
  349. HwDeviceExtension - Supplies the miniport driver's adapter storage. This
  350. storage is initialized to zero before this call.
  351. HwContext - Supplies the context value which was passed to
  352. VideoPortInitialize().
  353. ArgumentString - Supplies a NULL terminated ASCII string. This string
  354. originates from the user.
  355. ConfigInfo - Returns the configuration information structure which is
  356. filled by the miniport driver. This structure is initialized with
  357. any known configuration information (such as SystemIoBusNumber) by
  358. the port driver. Where possible, drivers should have one set of
  359. defaults which do not require any supplied configuration information.
  360. Again - Indicates if the miniport driver wants the port driver to call
  361. its VIDEO_HW_FIND_ADAPTER function again with a new device extension
  362. and the same config info. This is used by the miniport drivers which
  363. can search for several adapters on a bus.
  364. Return Value:
  365. This routine must return:
  366. NO_ERROR - Indicates a host adapter was found and the
  367. configuration information was successfully determined.
  368. ERROR_INVALID_PARAMETER - Indicates an adapter was found but there was an
  369. error obtaining the configuration information. If possible an error
  370. should be logged.
  371. ERROR_DEV_NOT_EXIST - Indicates no host adapter was found for the
  372. supplied configuration information.
  373. --*/
  374. {
  375. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  376. VP_STATUS status;
  377. #if defined(PLUG_AND_PLAY)
  378. ULONG VgaStatus;
  379. #endif
  380. //
  381. // Make sure the size of the structure is at least as large as what we
  382. // are expecting (check version of the config info structure).
  383. //
  384. if (ConfigInfo->Length < sizeof(VIDEO_PORT_CONFIG_INFO)) {
  385. return ERROR_INVALID_PARAMETER;
  386. }
  387. //
  388. // Make sure we only load one copy of the vga driver
  389. //
  390. if (VgaLoaded) {
  391. return ERROR_DEV_NOT_EXIST;
  392. }
  393. //
  394. // No interrupt information is necessary.
  395. //
  396. if (ConfigInfo->AdapterInterfaceType == Internal) {
  397. //
  398. // First check if there is a video adapter on the internal bus.
  399. // Exit right away if there is not.
  400. //
  401. if (NO_ERROR != VideoPortGetDeviceData(hwDeviceExtension,
  402. VpControllerData,
  403. &GetDeviceDataCallback,
  404. VgaAccessRange)) {
  405. VideoDebugPrint((2, "VGA: VideoPort get controller info failed\n"));
  406. return ERROR_INVALID_PARAMETER;
  407. }
  408. }
  409. #if !defined(PLUG_AND_PLAY)
  410. //
  411. // If this is a Plug and Play driver, then we got our resources from
  412. // Plug and Play. If we are a legacy driver, we need to report our
  413. // resources here.
  414. //
  415. status = VgaAcquireResources(hwDeviceExtension);
  416. if (status != NO_ERROR) {
  417. return status;
  418. }
  419. #endif
  420. //
  421. // Get logical IO port addresses.
  422. //
  423. if ( (hwDeviceExtension->IOAddress =
  424. VideoPortGetDeviceBase(hwDeviceExtension,
  425. VgaAccessRange->RangeStart,
  426. VGA_MAX_IO_PORT - VGA_BASE_IO_PORT + 1,
  427. VgaAccessRange->RangeInIoSpace)) == NULL) {
  428. VideoDebugPrint((2, "VgaFindAdapter - Fail to get io address\n"));
  429. return ERROR_INVALID_PARAMETER;
  430. }
  431. #if !defined(PLUG_AND_PLAY)
  432. //
  433. // Determine whether a VGA is present.
  434. //
  435. if (!VgaIsPresent(hwDeviceExtension)) {
  436. return ERROR_DEV_NOT_EXIST;
  437. }
  438. #else
  439. //
  440. // If we are running as a Plug and Play driver, then make sure we
  441. // aren't being loaded for a disabled device. If the device is
  442. // disabled, then fail to load.
  443. //
  444. VideoPortGetVgaStatus(hwDeviceExtension, &VgaStatus);
  445. if (VgaStatus == 0) {
  446. return ERROR_DEV_NOT_EXIST;
  447. }
  448. #endif
  449. //
  450. // Pass a pointer to the emulator range we are using.
  451. //
  452. ConfigInfo->NumEmulatorAccessEntries = VGA_NUM_EMULATOR_ACCESS_ENTRIES;
  453. ConfigInfo->EmulatorAccessEntries = VgaEmulatorAccessEntries;
  454. ConfigInfo->EmulatorAccessEntriesContext = (ULONG_PTR) hwDeviceExtension;
  455. ConfigInfo->VdmPhysicalVideoMemoryAddress = VgaAccessRange[VGA_MEMORY].RangeStart;
  456. ConfigInfo->VdmPhysicalVideoMemoryLength = VgaAccessRange[VGA_MEMORY].RangeLength;
  457. //
  458. // Minimum size of the buffer required to store the hardware state
  459. // information returned by IOCTL_VIDEO_SAVE_HARDWARE_STATE.
  460. //
  461. ConfigInfo->HardwareStateSize = VGA_TOTAL_STATE_SIZE;
  462. //
  463. // Map the video memory into the system virtual address space so we can
  464. // clear it out and use it for save and restore.
  465. //
  466. if ( (hwDeviceExtension->VideoMemoryAddress =
  467. VideoPortGetDeviceBase(hwDeviceExtension,
  468. VgaAccessRange[VGA_MEMORY].RangeStart,
  469. VgaAccessRange[VGA_MEMORY].RangeLength, FALSE)) == NULL) {
  470. VideoDebugPrint((1, "VgaFindAdapter - Fail to get memory address\n"));
  471. return ERROR_INVALID_PARAMETER;
  472. }
  473. //
  474. // Indicate we do not wish to be called again for another initialization.
  475. //
  476. *Again = 0;
  477. //
  478. // Keep track of if we already got loaded, since we can be called back
  479. // for a secondary bus (some machines have 2 PCI buses).
  480. // If *we* acquired the resources, then we won't conflict with ourselves
  481. // since we grabbed the resources as shared.
  482. //
  483. VgaLoaded = 1;
  484. //
  485. // Indicate a successful completion status.
  486. //
  487. return NO_ERROR;
  488. } // VgaFindAdapter()
  489. BOOLEAN
  490. VgaInitialize(
  491. PVOID HwDeviceExtension
  492. )
  493. /*++
  494. Routine Description:
  495. This routine does one time initialization of the device.
  496. Arguments:
  497. HwDeviceExtension - Pointer to the miniport driver's adapter information.
  498. Return Value:
  499. None.
  500. --*/
  501. {
  502. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  503. VIDEO_X86_BIOS_ARGUMENTS biosArguments;
  504. VP_STATUS Status;
  505. //
  506. // set up the default cursor position and type.
  507. //
  508. hwDeviceExtension->CursorPosition.Column = 0;
  509. hwDeviceExtension->CursorPosition.Row = 0;
  510. hwDeviceExtension->CursorTopScanLine = 0;
  511. hwDeviceExtension->CursorBottomScanLine = 31;
  512. hwDeviceExtension->CursorEnable = TRUE;
  513. InitializeModeTable(hwDeviceExtension);
  514. #if defined(PLUG_AND_PLAY)
  515. //
  516. // Set initial monitor power state
  517. //
  518. hwDeviceExtension->MonitorPowerState = VideoPowerOn;
  519. //
  520. // Retrieve and cache away the monitor power states we support
  521. //
  522. VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  523. biosArguments.Eax = VESA_POWER_FUNCTION;
  524. biosArguments.Ebx = VESA_GET_POWER_FUNC;
  525. Status = VideoPortInt10(HwDeviceExtension, &biosArguments);
  526. if ((Status == NO_ERROR) &&
  527. VESA_SUCCESS(biosArguments.Eax)) {
  528. hwDeviceExtension->MonitorPowerCapabilities = biosArguments.Ebx;
  529. }
  530. VgaInitializeSpecialCase(HwDeviceExtension);
  531. #endif
  532. return TRUE;
  533. } // VgaInitialize()
  534. BOOLEAN
  535. VgaStartIO(
  536. PVOID HwDeviceExtension,
  537. PVIDEO_REQUEST_PACKET RequestPacket
  538. )
  539. /*++
  540. Routine Description:
  541. This routine is the main execution routine for the miniport driver. It
  542. acceptss a Video Request Packet, performs the request, and then returns
  543. with the appropriate status.
  544. Arguments:
  545. HwDeviceExtension - Pointer to the miniport driver's adapter information.
  546. RequestPacket - Pointer to the video request packet. This structure
  547. contains all the parameters passed to the VideoIoControl function.
  548. Return Value:
  549. This routine will return error codes from the various support routines
  550. and will also return ERROR_INSUFFICIENT_BUFFER for incorrectly sized
  551. buffers and ERROR_INVALID_FUNCTION for unsupported functions.
  552. --*/
  553. {
  554. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  555. VP_STATUS status;
  556. VIDEO_MODE videoMode;
  557. PVIDEO_MEMORY_INFORMATION memoryInformation;
  558. ULONG inIoSpace;
  559. #if DBG
  560. //
  561. // Keep a history of the commands.
  562. // This will help track down the chip being in a DOS session while
  563. // GDI and the S3 display driver "think" it's in GUI mode.
  564. gaIOControlCode[giControlCode++] = RequestPacket->IoControlCode;
  565. giControlCode %= MAX_CONTROL_HISTORY;
  566. #endif
  567. //
  568. // Switch on the IoContolCode in the RequestPacket. It indicates which
  569. // function must be performed by the driver.
  570. //
  571. switch (RequestPacket->IoControlCode) {
  572. case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
  573. VideoDebugPrint((2, "VgaStartIO - MapVideoMemory\n"));
  574. if ( (RequestPacket->OutputBufferLength <
  575. (RequestPacket->StatusBlock->Information =
  576. sizeof(VIDEO_MEMORY_INFORMATION))) ||
  577. (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) ) {
  578. status = ERROR_INSUFFICIENT_BUFFER;
  579. }
  580. memoryInformation = RequestPacket->OutputBuffer;
  581. memoryInformation->VideoRamBase = ((PVIDEO_MEMORY)
  582. (RequestPacket->InputBuffer))->RequestedVirtualAddress;
  583. memoryInformation->VideoRamLength =
  584. hwDeviceExtension->PhysicalVideoMemoryLength;
  585. inIoSpace = 0;
  586. #if defined(PLUG_AND_PLAY)
  587. //
  588. // Let try to take advantage of write combining if using a VESA mode.
  589. //
  590. // We only do this for the PnP version of the VGA driver because,
  591. // the videoprt can only detect if we can safely do USWC when we
  592. // use a PnP driver.
  593. //
  594. // We'll also only do this if we are using a linear frame buffer
  595. // because the Intel i810 hard hangs if you try to use USWC on it's
  596. // banked frame buffer.
  597. //
  598. if (IS_LINEAR_MODE(hwDeviceExtension->CurrentMode)) {
  599. inIoSpace |= VIDEO_MEMORY_SPACE_P6CACHE;
  600. }
  601. #endif
  602. status = VideoPortMapMemory(hwDeviceExtension,
  603. hwDeviceExtension->PhysicalVideoMemoryBase,
  604. &(memoryInformation->VideoRamLength),
  605. &inIoSpace,
  606. &(memoryInformation->VideoRamBase));
  607. memoryInformation->FrameBufferBase =
  608. ((PUCHAR) (memoryInformation->VideoRamBase)) +
  609. hwDeviceExtension->PhysicalFrameBaseOffset.LowPart;
  610. memoryInformation->FrameBufferLength =
  611. hwDeviceExtension->PhysicalFrameLength;
  612. break;
  613. case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
  614. VideoDebugPrint((2, "VgaStartIO - UnMapVideoMemory\n"));
  615. if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) {
  616. status = ERROR_INSUFFICIENT_BUFFER;
  617. }
  618. status = VideoPortUnmapMemory(hwDeviceExtension,
  619. ((PVIDEO_MEMORY)
  620. (RequestPacket->InputBuffer))->
  621. RequestedVirtualAddress,
  622. 0);
  623. break;
  624. case IOCTL_VIDEO_QUERY_AVAIL_MODES:
  625. VideoDebugPrint((2, "VgaStartIO - QueryAvailableModes\n"));
  626. RequestPacket->StatusBlock->Information = 0;
  627. status = VgaQueryAvailableModes(hwDeviceExtension,
  628. (PVIDEO_MODE_INFORMATION)
  629. RequestPacket->OutputBuffer,
  630. RequestPacket->OutputBufferLength,
  631. (PULONG)(&RequestPacket->StatusBlock->Information));
  632. break;
  633. case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
  634. VideoDebugPrint((2, "VgaStartIO - QueryNumAvailableModes\n"));
  635. RequestPacket->StatusBlock->Information = 0;
  636. status = VgaQueryNumberOfAvailableModes(hwDeviceExtension,
  637. (PVIDEO_NUM_MODES)
  638. RequestPacket->OutputBuffer,
  639. RequestPacket->OutputBufferLength,
  640. (PULONG)(&RequestPacket->StatusBlock->Information));
  641. break;
  642. case IOCTL_VIDEO_QUERY_CURRENT_MODE:
  643. VideoDebugPrint((2, "VgaStartIO - QueryCurrentMode\n"));
  644. RequestPacket->StatusBlock->Information = 0;
  645. status = VgaQueryCurrentMode(hwDeviceExtension,
  646. (PVIDEO_MODE_INFORMATION) RequestPacket->OutputBuffer,
  647. RequestPacket->OutputBufferLength,
  648. (PULONG)(&RequestPacket->StatusBlock->Information));
  649. break;
  650. case IOCTL_VIDEO_SET_CURRENT_MODE:
  651. VideoDebugPrint((2, "VgaStartIO - SetCurrentModes\n"));
  652. {
  653. ULONG FrameBufferIsMoved = 0;
  654. status = VgaSetMode(hwDeviceExtension,
  655. (PVIDEO_MODE) RequestPacket->InputBuffer,
  656. RequestPacket->InputBufferLength,
  657. &FrameBufferIsMoved);
  658. if (RequestPacket->OutputBufferLength >= sizeof(ULONG)) {
  659. RequestPacket->StatusBlock->Information = sizeof(ULONG);
  660. *(PULONG)RequestPacket->OutputBuffer = FrameBufferIsMoved;
  661. }
  662. }
  663. break;
  664. case IOCTL_VIDEO_RESET_DEVICE:
  665. VideoDebugPrint((2, "VgaStartIO - Reset Device\n"));
  666. videoMode.RequestedMode = DEFAULT_MODE;
  667. {
  668. ULONG FrameBufferIsMoved = 0;
  669. status = VgaSetMode(hwDeviceExtension,
  670. (PVIDEO_MODE) &videoMode,
  671. sizeof(videoMode),
  672. &FrameBufferIsMoved);
  673. }
  674. break;
  675. case IOCTL_VIDEO_LOAD_AND_SET_FONT:
  676. VideoDebugPrint((2, "VgaStartIO - LoadAndSetFont\n"));
  677. status = VgaLoadAndSetFont(hwDeviceExtension,
  678. (PVIDEO_LOAD_FONT_INFORMATION) RequestPacket->InputBuffer,
  679. RequestPacket->InputBufferLength);
  680. break;
  681. case IOCTL_VIDEO_QUERY_CURSOR_POSITION:
  682. VideoDebugPrint((2, "VgaStartIO - QueryCursorPosition\n"));
  683. RequestPacket->StatusBlock->Information = 0;
  684. status = VgaQueryCursorPosition(hwDeviceExtension,
  685. (PVIDEO_CURSOR_POSITION) RequestPacket->OutputBuffer,
  686. RequestPacket->OutputBufferLength,
  687. (PULONG)(&RequestPacket->StatusBlock->Information));
  688. break;
  689. case IOCTL_VIDEO_SET_CURSOR_POSITION:
  690. VideoDebugPrint((2, "VgaStartIO - SetCursorPosition\n"));
  691. status = VgaSetCursorPosition(hwDeviceExtension,
  692. (PVIDEO_CURSOR_POSITION)
  693. RequestPacket->InputBuffer,
  694. RequestPacket->InputBufferLength);
  695. break;
  696. case IOCTL_VIDEO_QUERY_CURSOR_ATTR:
  697. VideoDebugPrint((2, "VgaStartIO - QueryCursorAttributes\n"));
  698. RequestPacket->StatusBlock->Information = 0;
  699. status = VgaQueryCursorAttributes(hwDeviceExtension,
  700. (PVIDEO_CURSOR_ATTRIBUTES) RequestPacket->OutputBuffer,
  701. RequestPacket->OutputBufferLength,
  702. (PULONG)(&RequestPacket->StatusBlock->Information));
  703. break;
  704. case IOCTL_VIDEO_SET_CURSOR_ATTR:
  705. VideoDebugPrint((2, "VgaStartIO - SetCursorAttributes\n"));
  706. status = VgaSetCursorAttributes(hwDeviceExtension,
  707. (PVIDEO_CURSOR_ATTRIBUTES) RequestPacket->InputBuffer,
  708. RequestPacket->InputBufferLength);
  709. break;
  710. case IOCTL_VIDEO_SET_PALETTE_REGISTERS:
  711. VideoDebugPrint((2, "VgaStartIO - SetPaletteRegs\n"));
  712. status = VgaSetPaletteReg(hwDeviceExtension,
  713. (PVIDEO_PALETTE_DATA) RequestPacket->InputBuffer,
  714. RequestPacket->InputBufferLength);
  715. break;
  716. case IOCTL_VIDEO_SET_COLOR_REGISTERS:
  717. VideoDebugPrint((2, "VgaStartIO - SetColorRegs\n"));
  718. status = VgaSetColorLookup(hwDeviceExtension,
  719. (PVIDEO_CLUT) RequestPacket->InputBuffer,
  720. RequestPacket->InputBufferLength);
  721. break;
  722. case IOCTL_VIDEO_ENABLE_VDM:
  723. VideoDebugPrint((2, "VgaStartIO - EnableVDM\n"));
  724. hwDeviceExtension->TrappedValidatorCount = 0;
  725. hwDeviceExtension->SequencerAddressValue = 0;
  726. hwDeviceExtension->CurrentNumVdmAccessRanges =
  727. NUM_MINIMAL_VGA_VALIDATOR_ACCESS_RANGE;
  728. hwDeviceExtension->CurrentVdmAccessRange =
  729. MinimalVgaValidatorAccessRange;
  730. VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
  731. hwDeviceExtension->CurrentNumVdmAccessRanges,
  732. hwDeviceExtension->CurrentVdmAccessRange);
  733. status = NO_ERROR;
  734. break;
  735. case IOCTL_VIDEO_RESTORE_HARDWARE_STATE:
  736. VideoDebugPrint((2, "VgaStartIO - RestoreHardwareState\n"));
  737. try {
  738. if(IsSavedModeVesa((PVIDEO_HARDWARE_STATE) RequestPacket->InputBuffer)){
  739. status = VesaRestoreHardwareState(hwDeviceExtension,
  740. (PVIDEO_HARDWARE_STATE) RequestPacket->InputBuffer,
  741. RequestPacket->InputBufferLength);
  742. } else {
  743. status = VgaRestoreHardwareState(hwDeviceExtension,
  744. (PVIDEO_HARDWARE_STATE) RequestPacket->InputBuffer,
  745. RequestPacket->InputBufferLength);
  746. }
  747. }
  748. except (1) {
  749. status = ERROR_INVALID_PARAMETER;
  750. }
  751. break;
  752. case IOCTL_VIDEO_SAVE_HARDWARE_STATE:
  753. VideoDebugPrint((2, "VgaStartIO - SaveHardwareState\n"));
  754. RequestPacket->StatusBlock->Information = 0;
  755. {
  756. USHORT ModeNumber;
  757. ModeNumber = VBEGetMode(hwDeviceExtension);
  758. try {
  759. if (ModeNumber & 0x100) {
  760. status = VesaSaveHardwareState(hwDeviceExtension,
  761. (PVIDEO_HARDWARE_STATE) RequestPacket->OutputBuffer,
  762. RequestPacket->OutputBufferLength,
  763. ModeNumber);
  764. } else {
  765. status = VgaSaveHardwareState(hwDeviceExtension,
  766. (PVIDEO_HARDWARE_STATE) RequestPacket->OutputBuffer,
  767. RequestPacket->OutputBufferLength,
  768. (PULONG)(&RequestPacket->StatusBlock->Information));
  769. }
  770. } except (1) {
  771. status = ERROR_INVALID_PARAMETER;
  772. }
  773. }
  774. break;
  775. case IOCTL_VIDEO_GET_BANK_SELECT_CODE:
  776. VideoDebugPrint((2, "VgaStartIO - GetBankSelectCode\n"));
  777. RequestPacket->StatusBlock->Information = 0;
  778. status = VgaGetBankSelectCode(hwDeviceExtension,
  779. (PVIDEO_BANK_SELECT) RequestPacket->OutputBuffer,
  780. RequestPacket->OutputBufferLength,
  781. (PULONG)(&RequestPacket->StatusBlock->Information));
  782. break;
  783. case IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES:
  784. VideoDebugPrint((2, "VgaStartIO - Query Public Address Ranges\n"));
  785. if (RequestPacket->OutputBufferLength <
  786. (RequestPacket->StatusBlock->Information =
  787. sizeof(VIDEO_PUBLIC_ACCESS_RANGES)) )
  788. {
  789. status = ERROR_INSUFFICIENT_BUFFER;
  790. }
  791. else
  792. {
  793. PVIDEO_PUBLIC_ACCESS_RANGES publicAccessRanges;
  794. PHYSICAL_ADDRESS PhysicalRegisterAddress;
  795. ULONG RegisterLength;
  796. PVOID MappedAddress;
  797. publicAccessRanges = RequestPacket->OutputBuffer;
  798. PhysicalRegisterAddress.LowPart = VGA_END_BREAK_PORT;
  799. PhysicalRegisterAddress.HighPart = 0;
  800. RegisterLength = VGA_MAX_IO_PORT - VGA_END_BREAK_PORT;
  801. publicAccessRanges->InIoSpace = TRUE;
  802. MappedAddress = NULL;
  803. status = VideoPortMapMemory(
  804. HwDeviceExtension,
  805. PhysicalRegisterAddress,
  806. &RegisterLength,
  807. &(publicAccessRanges->InIoSpace),
  808. &MappedAddress
  809. );
  810. publicAccessRanges->VirtualAddress = (PVOID)((ULONG_PTR)MappedAddress - VGA_END_BREAK_PORT);
  811. }
  812. break;
  813. case IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES:
  814. VideoDebugPrint((2, "VgaStartIO - Free Public Address Ranges\n"));
  815. if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))
  816. {
  817. status = ERROR_INSUFFICIENT_BUFFER;
  818. }
  819. else
  820. {
  821. PVIDEO_MEMORY mappedMemory;
  822. mappedMemory = RequestPacket->InputBuffer;
  823. status = VideoPortUnmapMemory(
  824. HwDeviceExtension,
  825. (PVOID)((ULONG_PTR)(mappedMemory->RequestedVirtualAddress)
  826. + VGA_END_BREAK_PORT),
  827. 0);
  828. }
  829. break;
  830. case IOCTL_VIDEO_SET_BANK_POSITION:
  831. VideoDebugPrint((2, "VgaStartIO - Set Bank Position\n"));
  832. if (RequestPacket->InputBufferLength < sizeof(BANK_POSITION)) {
  833. status = ERROR_INSUFFICIENT_BUFFER;
  834. } else {
  835. PBANK_POSITION BankPosition;
  836. BankPosition = RequestPacket->InputBuffer;
  837. status = VgaSetBankPosition(
  838. HwDeviceExtension,
  839. BankPosition);
  840. }
  841. break;
  842. //
  843. // if we get here, an invalid IoControlCode was specified.
  844. //
  845. default:
  846. VideoDebugPrint((1, "Fell through vga startIO routine - invalid command\n"));
  847. status = ERROR_INVALID_FUNCTION;
  848. break;
  849. }
  850. #if DBG
  851. //
  852. // Keep a history of the commands.
  853. // This will help track down the chip being in a DOS session while
  854. // GDI and the S3 display driver "think" it's in GUI mode.
  855. gaIOControlCode[giControlCode++] = 0x00005555;
  856. giControlCode %= MAX_CONTROL_HISTORY;
  857. #endif
  858. RequestPacket->StatusBlock->Status = status;
  859. return TRUE;
  860. } // VgaStartIO()
  861. //
  862. // private routines
  863. //
  864. VP_STATUS
  865. VgaLoadAndSetFont(
  866. PHW_DEVICE_EXTENSION HwDeviceExtension,
  867. PVIDEO_LOAD_FONT_INFORMATION FontInformation,
  868. ULONG FontInformationSize
  869. )
  870. /*++
  871. Routine Description:
  872. Takes a buffer containing a user-defined font and loads it into the
  873. VGA soft font memory and programs the VGA to the appropriate character
  874. cell size.
  875. Arguments:
  876. HwDeviceExtension - Pointer to the miniport driver's device extension.
  877. FontInformation - Pointer to the structure containing the information
  878. about the loadable ROM font to be set.
  879. FontInformationSize - Length of the input buffer supplied by the user.
  880. Return Value:
  881. NO_ERROR - information returned successfully
  882. ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data.
  883. ERROR_INVALID_PARAMETER - invalid video mode
  884. --*/
  885. {
  886. PUCHAR destination;
  887. PUCHAR source;
  888. USHORT width;
  889. ULONG i;
  890. UCHAR cr9;
  891. //
  892. // check if a mode has been set
  893. //
  894. if (HwDeviceExtension->CurrentMode == NULL) {
  895. return ERROR_INVALID_FUNCTION;
  896. }
  897. //
  898. // Text mode only; If we are in a graphics mode, return an error
  899. //
  900. if (HwDeviceExtension->CurrentMode->fbType & VIDEO_MODE_GRAPHICS) {
  901. return ERROR_INVALID_PARAMETER;
  902. }
  903. //
  904. // Check if the size of the data in the input buffer is large enough
  905. // and that it contains all the data.
  906. //
  907. if ( (FontInformationSize < sizeof(VIDEO_LOAD_FONT_INFORMATION)) ||
  908. (FontInformationSize < sizeof(VIDEO_LOAD_FONT_INFORMATION) +
  909. sizeof(UCHAR) * (FontInformation->FontSize - 1)) ) {
  910. return ERROR_INSUFFICIENT_BUFFER;
  911. }
  912. //
  913. // Check for the width and height of the font
  914. //
  915. if ( ((FontInformation->WidthInPixels != 8) &&
  916. (FontInformation->WidthInPixels != 9)) ||
  917. (FontInformation->HeightInPixels > 32) ) {
  918. return ERROR_INVALID_PARAMETER;
  919. }
  920. //
  921. // Check the size of the font buffer is the right size for the size
  922. // font being passed down.
  923. //
  924. if (FontInformation->FontSize < FontInformation->HeightInPixels * 256 *
  925. sizeof(UCHAR) ) {
  926. return ERROR_INSUFFICIENT_BUFFER;
  927. }
  928. //
  929. // Since the font parameters are valid, store the parameters in the
  930. // device extension and load the font.
  931. //
  932. HwDeviceExtension->FontPelRows = FontInformation->HeightInPixels;
  933. HwDeviceExtension->FontPelColumns = FontInformation->WidthInPixels;
  934. HwDeviceExtension->CurrentMode->row =
  935. HwDeviceExtension->CurrentMode->vres / HwDeviceExtension->FontPelRows;
  936. width =
  937. HwDeviceExtension->CurrentMode->hres / HwDeviceExtension->FontPelColumns;
  938. if (width < (USHORT)HwDeviceExtension->CurrentMode->col) {
  939. HwDeviceExtension->CurrentMode->col = width;
  940. }
  941. source = &(FontInformation->Font[0]);
  942. //
  943. // Set up the destination and source pointers for the font
  944. //
  945. destination = (PUCHAR)HwDeviceExtension->VideoMemoryAddress;
  946. //
  947. // Map font buffer at A0000
  948. //
  949. VgaInterpretCmdStream(HwDeviceExtension, EnableA000Data);
  950. //
  951. // Move the font to its destination
  952. //
  953. for (i = 1; i <= 256; i++) {
  954. VideoPortWriteRegisterBufferUchar(destination,
  955. source,
  956. FontInformation->HeightInPixels);
  957. destination += 32;
  958. source += FontInformation->HeightInPixels;
  959. }
  960. VgaInterpretCmdStream(HwDeviceExtension, DisableA000Color);
  961. //
  962. // Restore to a text mode.
  963. //
  964. //
  965. // Set Height of font.
  966. //
  967. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  968. CRTC_ADDRESS_PORT_COLOR, 0x9);
  969. cr9 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  970. CRTC_DATA_PORT_COLOR) & 0xE0;
  971. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  972. CRTC_DATA_PORT_COLOR,
  973. (UCHAR)(cr9 | (FontInformation->HeightInPixels - 1)));
  974. //
  975. // Set Width of font.
  976. //
  977. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  978. CRTC_ADDRESS_PORT_COLOR, 0x12);
  979. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  980. CRTC_DATA_PORT_COLOR,
  981. (UCHAR)(((USHORT)FontInformation->HeightInPixels *
  982. (USHORT)HwDeviceExtension->CurrentMode->row) - 1));
  983. i = HwDeviceExtension->CurrentMode->vres /
  984. HwDeviceExtension->CurrentMode->row;
  985. //
  986. // Set Cursor End
  987. //
  988. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  989. CRTC_ADDRESS_PORT_COLOR, 0xb);
  990. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  991. CRTC_DATA_PORT_COLOR, (UCHAR)--i);
  992. //
  993. // Set Cursor Statr
  994. //
  995. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  996. CRTC_ADDRESS_PORT_COLOR, 0xa);
  997. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  998. CRTC_DATA_PORT_COLOR, (UCHAR)--i);
  999. return NO_ERROR;
  1000. } //end VgaLoadAndSetFont()
  1001. VP_STATUS
  1002. VgaQueryCursorPosition(
  1003. PHW_DEVICE_EXTENSION HwDeviceExtension,
  1004. PVIDEO_CURSOR_POSITION CursorPosition,
  1005. ULONG CursorPositionSize,
  1006. PULONG OutputSize
  1007. )
  1008. /*++
  1009. Routine Description:
  1010. This routine returns the row and column of the cursor.
  1011. Arguments:
  1012. HwDeviceExtension - Pointer to the miniport driver's device extension.
  1013. CursorPosition - Pointer to the output buffer supplied by the user. This
  1014. is where the cursor position is stored.
  1015. CursorPositionSize - Length of the output buffer supplied by the user.
  1016. OutputSize - Pointer to a buffer in which to return the actual size of
  1017. the data in the buffer. If the buffer was not large enough, this
  1018. contains the minimum required buffer size.
  1019. Return Value:
  1020. NO_ERROR - information returned successfully
  1021. ERROR_INSUFFICIENT_BUFFER - output buffer not large enough to return
  1022. any useful data
  1023. ERROR_INVALID_PARAMETER - invalid video mode
  1024. --*/
  1025. {
  1026. //
  1027. // check if a mode has been set
  1028. //
  1029. if (HwDeviceExtension->CurrentMode == NULL) {
  1030. return ERROR_INVALID_FUNCTION;
  1031. }
  1032. //
  1033. // Text mode only; If we are in a graphics mode, return an error
  1034. //
  1035. if (HwDeviceExtension->CurrentMode->fbType & VIDEO_MODE_GRAPHICS) {
  1036. *OutputSize = 0;
  1037. return ERROR_INVALID_PARAMETER;
  1038. }
  1039. //
  1040. // If the buffer passed in is not large enough return an
  1041. // appropriate error code.
  1042. //
  1043. if (CursorPositionSize < (*OutputSize = sizeof(VIDEO_CURSOR_POSITION)) ) {
  1044. *OutputSize = 0;
  1045. return ERROR_INSUFFICIENT_BUFFER;
  1046. }
  1047. //
  1048. // Store the postition of the cursor into the buffer.
  1049. //
  1050. CursorPosition->Column = HwDeviceExtension->CursorPosition.Column;
  1051. CursorPosition->Row = HwDeviceExtension->CursorPosition.Row;
  1052. return NO_ERROR;
  1053. } // end VgaQueryCursorPosition()
  1054. VP_STATUS
  1055. VgaSetCursorPosition(
  1056. PHW_DEVICE_EXTENSION HwDeviceExtension,
  1057. PVIDEO_CURSOR_POSITION CursorPosition,
  1058. ULONG CursorPositionSize
  1059. )
  1060. /*++
  1061. Routine Description:
  1062. This routine verifies that the requested cursor position is within
  1063. the row and column bounds of the current mode and font. If valid, then
  1064. it sets the row and column of the cursor.
  1065. Arguments:
  1066. HwDeviceExtension - Pointer to the miniport driver's device extension.
  1067. CursorPosition - Pointer to the structure containing the cursor position.
  1068. CursorPositionSize - Length of the input buffer supplied by the user.
  1069. Return Value:
  1070. NO_ERROR - information returned successfully
  1071. ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data
  1072. ERROR_INVALID_PARAMETER - invalid video mode
  1073. --*/
  1074. {
  1075. USHORT position;
  1076. //
  1077. // check if a mode has been set
  1078. //
  1079. if (HwDeviceExtension->CurrentMode == NULL) {
  1080. return ERROR_INVALID_FUNCTION;
  1081. }
  1082. //
  1083. // Text mode only; If we are in a graphics mode, return an error
  1084. //
  1085. if (HwDeviceExtension->CurrentMode->fbType & VIDEO_MODE_GRAPHICS) {
  1086. return ERROR_INVALID_PARAMETER;
  1087. }
  1088. //
  1089. // Check if the size of the data in the input buffer is large enough.
  1090. //
  1091. if (CursorPositionSize < sizeof(VIDEO_CURSOR_POSITION)) {
  1092. return ERROR_INSUFFICIENT_BUFFER;
  1093. }
  1094. //
  1095. // Check if the new values for the cursor positions are in the valid
  1096. // bounds for the screen.
  1097. //
  1098. if ((CursorPosition->Column >= HwDeviceExtension->CurrentMode->col) ||
  1099. (CursorPosition->Row >= HwDeviceExtension->CurrentMode->row)) {
  1100. return ERROR_INVALID_PARAMETER;
  1101. }
  1102. //
  1103. // Store these new values in the device extension so we can use them in
  1104. // a QUERY.
  1105. //
  1106. HwDeviceExtension->CursorPosition.Column = CursorPosition->Column;
  1107. HwDeviceExtension->CursorPosition.Row = CursorPosition->Row;
  1108. //
  1109. // Calculate the position on the screen at which the cursor must be
  1110. // be displayed
  1111. //
  1112. position = (USHORT) (HwDeviceExtension->CurrentMode->col *
  1113. CursorPosition->Row + CursorPosition->Column);
  1114. //
  1115. // Address Cursor Location Low Register in CRT Controller Registers
  1116. //
  1117. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1118. CRTC_ADDRESS_PORT_COLOR, IND_CURSOR_LOW_LOC);
  1119. //
  1120. // Set Cursor Location Low Register
  1121. //
  1122. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1123. CRTC_DATA_PORT_COLOR, (UCHAR) (position & 0x00FF));
  1124. //
  1125. // Address Cursor Location High Register in CRT Controller Registers
  1126. //
  1127. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1128. CRTC_ADDRESS_PORT_COLOR, IND_CURSOR_HIGH_LOC);
  1129. //
  1130. // Set Cursor Location High Register
  1131. //
  1132. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1133. CRTC_DATA_PORT_COLOR, (UCHAR) (position >> 8));
  1134. return NO_ERROR;
  1135. } // end VgaSetCursorPosition()
  1136. VP_STATUS
  1137. VgaQueryCursorAttributes(
  1138. PHW_DEVICE_EXTENSION HwDeviceExtension,
  1139. PVIDEO_CURSOR_ATTRIBUTES CursorAttributes,
  1140. ULONG CursorAttributesSize,
  1141. PULONG OutputSize
  1142. )
  1143. /*++
  1144. Routine Description:
  1145. This routine returns information about the height and visibility of the
  1146. cursor.
  1147. Arguments:
  1148. HwDeviceExtension - Pointer to the miniport driver's device extension.
  1149. CursorAttributes - Pointer to the output buffer supplied by the user.
  1150. This is where the cursor type is stored.
  1151. CursorAttributesSize - Length of the output buffer supplied by the user.
  1152. OutputSize - Pointer to a buffer in which to return the actual size of
  1153. the data in the buffer. If the buffer was not large enough, this
  1154. contains the minimum required buffer size.
  1155. Return Value:
  1156. NO_ERROR - information returned successfully
  1157. ERROR_INSUFFICIENT_BUFFER - output buffer not large enough to return
  1158. any useful data
  1159. ERROR_INVALID_PARAMETER - invalid video mode
  1160. --*/
  1161. {
  1162. //
  1163. // check if a mode has been set
  1164. //
  1165. if (HwDeviceExtension->CurrentMode == NULL) {
  1166. return ERROR_INVALID_FUNCTION;
  1167. }
  1168. //
  1169. // Text mode only; If we are in a graphics mode, return an error
  1170. //
  1171. if (HwDeviceExtension->CurrentMode->fbType & VIDEO_MODE_GRAPHICS) {
  1172. *OutputSize = 0;
  1173. return ERROR_INVALID_PARAMETER;
  1174. }
  1175. //
  1176. // Find out the size of the data to be put in the the buffer and return
  1177. // that in the status information (whether or not the information is
  1178. // there). If the buffer passed in is not large enough return an
  1179. // appropriate error code.
  1180. //
  1181. if (CursorAttributesSize < (*OutputSize =
  1182. sizeof(VIDEO_CURSOR_ATTRIBUTES)) ) {
  1183. *OutputSize = 0;
  1184. return ERROR_INSUFFICIENT_BUFFER;
  1185. }
  1186. //
  1187. // Store the cursor information into the buffer.
  1188. //
  1189. CursorAttributes->Height = (USHORT) HwDeviceExtension->CursorTopScanLine;
  1190. CursorAttributes->Width = (USHORT) HwDeviceExtension->CursorBottomScanLine;
  1191. CursorAttributes->Enable = HwDeviceExtension->CursorEnable;
  1192. return NO_ERROR;
  1193. } // end VgaQueryCursorAttributes()
  1194. VP_STATUS
  1195. VgaSetCursorAttributes(
  1196. PHW_DEVICE_EXTENSION HwDeviceExtension,
  1197. PVIDEO_CURSOR_ATTRIBUTES CursorAttributes,
  1198. ULONG CursorAttributesSize
  1199. )
  1200. /*++
  1201. Routine Description:
  1202. This routine verifies that the requested cursor height is within the
  1203. bounds of the character cell. If valid, then it sets the new
  1204. visibility and height of the cursor.
  1205. Arguments:
  1206. HwDeviceExtension - Pointer to the miniport driver's device extension.
  1207. CursorType - Pointer to the structure containing the cursor information.
  1208. CursorTypeSize - Length of the input buffer supplied by the user.
  1209. Return Value:
  1210. NO_ERROR - information returned successfully
  1211. ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data
  1212. ERROR_INVALID_PARAMETER - invalid video mode
  1213. --*/
  1214. {
  1215. UCHAR cursorLine;
  1216. //
  1217. // check if a mode has been set
  1218. //
  1219. if (HwDeviceExtension->CurrentMode == NULL) {
  1220. return ERROR_INVALID_FUNCTION;
  1221. }
  1222. //
  1223. // Text mode only; If we are in a graphics mode, return an error
  1224. //
  1225. if (HwDeviceExtension->CurrentMode->fbType & VIDEO_MODE_GRAPHICS) {
  1226. return ERROR_INVALID_PARAMETER;
  1227. }
  1228. //
  1229. // Check if the size of the data in the input buffer is large enough.
  1230. //
  1231. if (CursorAttributesSize < sizeof(VIDEO_CURSOR_ATTRIBUTES)) {
  1232. return ERROR_INSUFFICIENT_BUFFER;
  1233. }
  1234. //
  1235. // Check if the new values for the cursor type are in the valid range.
  1236. //
  1237. if ((CursorAttributes->Height >= HwDeviceExtension->FontPelRows) ||
  1238. (CursorAttributes->Width > 31)) {
  1239. return ERROR_INVALID_PARAMETER;
  1240. }
  1241. //
  1242. // Store the cursor information in the device extension so we can use
  1243. // them in a QUERY.
  1244. //
  1245. HwDeviceExtension->CursorTopScanLine = (UCHAR) CursorAttributes->Height;
  1246. HwDeviceExtension->CursorBottomScanLine = (UCHAR) CursorAttributes->Width;
  1247. HwDeviceExtension->CursorEnable = CursorAttributes->Enable;
  1248. //
  1249. // Address Cursor Start Register in CRT Controller Registers
  1250. //
  1251. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1252. CRTC_ADDRESS_PORT_COLOR,
  1253. IND_CURSOR_START);
  1254. //
  1255. // Set Cursor Start Register by writting to CRTCtl Data Register
  1256. // Preserve the high three bits of this register.
  1257. //
  1258. // Only the Five low bits are used for the cursor height.
  1259. // Bit 5 is cursor enable, bit 6 and 7 preserved.
  1260. //
  1261. cursorLine = (UCHAR) CursorAttributes->Height & 0x1F;
  1262. cursorLine |= VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1263. CRTC_DATA_PORT_COLOR) & 0xC0;
  1264. if (!CursorAttributes->Enable) {
  1265. cursorLine |= 0x20; // Flip cursor off bit
  1266. }
  1267. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + CRTC_DATA_PORT_COLOR,
  1268. cursorLine);
  1269. //
  1270. // Address Cursor End Register in CRT Controller Registers
  1271. //
  1272. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1273. CRTC_ADDRESS_PORT_COLOR,
  1274. IND_CURSOR_END);
  1275. //
  1276. // Set Cursor End Register. Preserve the high three bits of this
  1277. // register.
  1278. //
  1279. cursorLine =
  1280. (CursorAttributes->Width < (USHORT)(HwDeviceExtension->FontPelRows - 1)) ?
  1281. CursorAttributes->Width : (HwDeviceExtension->FontPelRows - 1);
  1282. cursorLine &= 0x1f;
  1283. cursorLine |= VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1284. CRTC_DATA_PORT_COLOR) & 0xE0;
  1285. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + CRTC_DATA_PORT_COLOR,
  1286. cursorLine);
  1287. return NO_ERROR;
  1288. } // end VgaSetCursorAttributes()
  1289. BOOLEAN
  1290. VgaIsPresent(
  1291. PHW_DEVICE_EXTENSION HwDeviceExtension
  1292. )
  1293. /*++
  1294. Routine Description:
  1295. This routine returns TRUE if a VGA is present. Determining whether a VGA
  1296. is present is a two-step process. First, this routine walks bits through
  1297. the Bit Mask register, to establish that there are readable indexed
  1298. registers (EGAs normally don't have readable registers, and other adapters
  1299. are unlikely to have indexed registers). This test is done first because
  1300. it's a non-destructive EGA rejection test (correctly rejects EGAs, but
  1301. doesn't potentially mess up the screen or the accessibility of display
  1302. memory). Normally, this would be an adequate test, but some EGAs have
  1303. readable registers, so next, we check for the existence of the Chain4 bit
  1304. in the Memory Mode register; this bit doesn't exist in EGAs. It's
  1305. conceivable that there are EGAs with readable registers and a register bit
  1306. where Chain4 is stored, although I don't know of any; if a better test yet
  1307. is needed, memory could be written to in Chain4 mode, and then examined
  1308. plane by plane in non-Chain4 mode to make sure the Chain4 bit did what it's
  1309. supposed to do. However, the current test should be adequate to eliminate
  1310. just about all EGAs, and 100% of everything else.
  1311. If this function fails to find a VGA, it attempts to undo any damage it
  1312. may have inadvertently done while testing. The underlying assumption for
  1313. the damage control is that if there's any non-VGA adapter at the tested
  1314. ports, it's an EGA or an enhanced EGA, because: a) I don't know of any
  1315. other adapters that use 3C4/5 or 3CE/F, and b), if there are other
  1316. adapters, I certainly don't know how to restore their original states. So
  1317. all error recovery is oriented toward putting an EGA back in a writable
  1318. state, so that error messages are visible. The EGA's state on entry is
  1319. assumed to be text mode, so the Memory Mode register is restored to the
  1320. default state for text mode.
  1321. If a VGA is found, the VGA is returned to its original state after
  1322. testing is finished.
  1323. Arguments:
  1324. None.
  1325. Return Value:
  1326. TRUE if a VGA is present, FALSE if not.
  1327. --*/
  1328. {
  1329. UCHAR originalGCAddr;
  1330. UCHAR originalSCAddr;
  1331. UCHAR originalBitMask;
  1332. UCHAR originalReadMap;
  1333. UCHAR originalMemoryMode;
  1334. UCHAR testMask;
  1335. BOOLEAN returnStatus;
  1336. //
  1337. // Remember the original state of the Graphics Controller Address register.
  1338. //
  1339. originalGCAddr = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1340. GRAPH_ADDRESS_PORT);
  1341. //
  1342. // Write the Read Map register with a known state so we can verify
  1343. // that it isn't changed after we fool with the Bit Mask. This ensures
  1344. // that we're dealing with indexed registers, since both the Read Map and
  1345. // the Bit Mask are addressed at GRAPH_DATA_PORT.
  1346. //
  1347. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1348. GRAPH_ADDRESS_PORT, IND_READ_MAP);
  1349. //
  1350. // If we can't read back the Graphics Address register setting we just
  1351. // performed, it's not readable and this isn't a VGA.
  1352. //
  1353. if ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1354. GRAPH_ADDRESS_PORT) & GRAPH_ADDR_MASK) != IND_READ_MAP) {
  1355. return FALSE;
  1356. }
  1357. //
  1358. // Set the Read Map register to a known state.
  1359. //
  1360. originalReadMap = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1361. GRAPH_DATA_PORT);
  1362. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1363. GRAPH_DATA_PORT, READ_MAP_TEST_SETTING);
  1364. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1365. GRAPH_DATA_PORT) != READ_MAP_TEST_SETTING) {
  1366. //
  1367. // The Read Map setting we just performed can't be read back; not a
  1368. // VGA. Restore the default Read Map state.
  1369. //
  1370. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1371. GRAPH_DATA_PORT, READ_MAP_DEFAULT);
  1372. return FALSE;
  1373. }
  1374. //
  1375. // Remember the original setting of the Bit Mask register.
  1376. //
  1377. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1378. GRAPH_ADDRESS_PORT, IND_BIT_MASK);
  1379. if ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1380. GRAPH_ADDRESS_PORT) & GRAPH_ADDR_MASK) != IND_BIT_MASK) {
  1381. //
  1382. // The Graphics Address register setting we just made can't be read
  1383. // back; not a VGA. Restore the default Read Map state.
  1384. //
  1385. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1386. GRAPH_ADDRESS_PORT, IND_READ_MAP);
  1387. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1388. GRAPH_DATA_PORT, READ_MAP_DEFAULT);
  1389. return FALSE;
  1390. }
  1391. originalBitMask = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1392. GRAPH_DATA_PORT);
  1393. //
  1394. // Set up the initial test mask we'll write to and read from the Bit Mask.
  1395. //
  1396. testMask = 0xBB;
  1397. do {
  1398. //
  1399. // Write the test mask to the Bit Mask.
  1400. //
  1401. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1402. GRAPH_DATA_PORT, testMask);
  1403. //
  1404. // Make sure the Bit Mask remembered the value.
  1405. //
  1406. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1407. GRAPH_DATA_PORT) != testMask) {
  1408. //
  1409. // The Bit Mask is not properly writable and readable; not a VGA.
  1410. // Restore the Bit Mask and Read Map to their default states.
  1411. //
  1412. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1413. GRAPH_DATA_PORT, BIT_MASK_DEFAULT);
  1414. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1415. GRAPH_ADDRESS_PORT, IND_READ_MAP);
  1416. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1417. GRAPH_DATA_PORT, READ_MAP_DEFAULT);
  1418. return FALSE;
  1419. }
  1420. //
  1421. // Cycle the mask for next time.
  1422. //
  1423. testMask >>= 1;
  1424. } while (testMask != 0);
  1425. //
  1426. // There's something readable at GRAPH_DATA_PORT; now switch back and
  1427. // make sure that the Read Map register hasn't changed, to verify that
  1428. // we're dealing with indexed registers.
  1429. //
  1430. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1431. GRAPH_ADDRESS_PORT, IND_READ_MAP);
  1432. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1433. GRAPH_DATA_PORT) != READ_MAP_TEST_SETTING) {
  1434. //
  1435. // The Read Map is not properly writable and readable; not a VGA.
  1436. // Restore the Bit Mask and Read Map to their default states, in case
  1437. // this is an EGA, so subsequent writes to the screen aren't garbled.
  1438. //
  1439. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1440. GRAPH_DATA_PORT, READ_MAP_DEFAULT);
  1441. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1442. GRAPH_ADDRESS_PORT, IND_BIT_MASK);
  1443. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1444. GRAPH_DATA_PORT, BIT_MASK_DEFAULT);
  1445. return FALSE;
  1446. }
  1447. //
  1448. // We've pretty surely verified the existence of the Bit Mask register.
  1449. // Put the Graphics Controller back to the original state.
  1450. //
  1451. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1452. GRAPH_DATA_PORT, originalReadMap);
  1453. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1454. GRAPH_ADDRESS_PORT, IND_BIT_MASK);
  1455. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1456. GRAPH_DATA_PORT, originalBitMask);
  1457. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1458. GRAPH_ADDRESS_PORT, originalGCAddr);
  1459. //
  1460. // Now, check for the existence of the Chain4 bit.
  1461. //
  1462. //
  1463. // Remember the original states of the Sequencer Address and Memory Mode
  1464. // registers.
  1465. //
  1466. originalSCAddr = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1467. SEQ_ADDRESS_PORT);
  1468. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1469. SEQ_ADDRESS_PORT, IND_MEMORY_MODE);
  1470. if ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1471. SEQ_ADDRESS_PORT) & SEQ_ADDR_MASK) != IND_MEMORY_MODE) {
  1472. //
  1473. // Couldn't read back the Sequencer Address register setting we just
  1474. // performed.
  1475. //
  1476. return FALSE;
  1477. }
  1478. originalMemoryMode = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1479. SEQ_DATA_PORT);
  1480. //
  1481. // Toggle the Chain4 bit and read back the result. This must be done during
  1482. // sync reset, since we're changing the chaining state.
  1483. //
  1484. //
  1485. // Begin sync reset.
  1486. //
  1487. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  1488. SEQ_ADDRESS_PORT),
  1489. (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8)));
  1490. //
  1491. // Toggle the Chain4 bit.
  1492. //
  1493. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1494. SEQ_ADDRESS_PORT, IND_MEMORY_MODE);
  1495. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1496. SEQ_DATA_PORT, (UCHAR)(originalMemoryMode ^ CHAIN4_MASK));
  1497. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1498. SEQ_DATA_PORT) != (UCHAR) (originalMemoryMode ^ CHAIN4_MASK)) {
  1499. //
  1500. // Chain4 bit not there; not a VGA.
  1501. // Set text mode default for Memory Mode register.
  1502. //
  1503. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1504. SEQ_DATA_PORT, MEMORY_MODE_TEXT_DEFAULT);
  1505. //
  1506. // End sync reset.
  1507. //
  1508. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  1509. SEQ_ADDRESS_PORT),
  1510. (IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8)));
  1511. returnStatus = FALSE;
  1512. } else {
  1513. //
  1514. // It's a VGA.
  1515. //
  1516. //
  1517. // Restore the original Memory Mode setting.
  1518. //
  1519. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1520. SEQ_DATA_PORT, originalMemoryMode);
  1521. //
  1522. // End sync reset.
  1523. //
  1524. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  1525. SEQ_ADDRESS_PORT),
  1526. (USHORT)(IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8)));
  1527. //
  1528. // Restore the original Sequencer Address setting.
  1529. //
  1530. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1531. SEQ_ADDRESS_PORT, originalSCAddr);
  1532. returnStatus = TRUE;
  1533. }
  1534. return returnStatus;
  1535. } // VgaIsPresent()
  1536. VP_STATUS
  1537. VgaSetPaletteReg(
  1538. PHW_DEVICE_EXTENSION HwDeviceExtension,
  1539. PVIDEO_PALETTE_DATA PaletteBuffer,
  1540. ULONG PaletteBufferSize
  1541. )
  1542. /*++
  1543. Routine Description:
  1544. This routine sets a specified portion of the EGA (not DAC) palette
  1545. registers.
  1546. Arguments:
  1547. HwDeviceExtension - Pointer to the miniport driver's device extension.
  1548. PaletteBuffer - Pointer to the structure containing the palette data.
  1549. PaletteBufferSize - Length of the input buffer supplied by the user.
  1550. Return Value:
  1551. NO_ERROR - information returned successfully
  1552. ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data.
  1553. ERROR_INVALID_PARAMETER - invalid palette size.
  1554. --*/
  1555. {
  1556. USHORT i;
  1557. //
  1558. // Check if the size of the data in the input buffer is large enough.
  1559. //
  1560. if ((PaletteBufferSize) < (sizeof(VIDEO_PALETTE_DATA)) ||
  1561. (PaletteBufferSize < (sizeof(VIDEO_PALETTE_DATA) +
  1562. (sizeof(USHORT) * (PaletteBuffer->NumEntries -1)) ))) {
  1563. return ERROR_INSUFFICIENT_BUFFER;
  1564. }
  1565. //
  1566. // Check to see if the parameters are valid.
  1567. //
  1568. if ( (PaletteBuffer->FirstEntry > VIDEO_MAX_COLOR_REGISTER ) ||
  1569. (PaletteBuffer->NumEntries == 0) ||
  1570. (PaletteBuffer->FirstEntry + PaletteBuffer->NumEntries >
  1571. VIDEO_MAX_PALETTE_REGISTER + 1 ) ) {
  1572. return ERROR_INVALID_PARAMETER;
  1573. }
  1574. //
  1575. // Reset ATC to index mode
  1576. //
  1577. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1578. ATT_INITIALIZE_PORT_COLOR);
  1579. //
  1580. // Blast out our palette values.
  1581. //
  1582. for (i = 0; i < PaletteBuffer->NumEntries; i++) {
  1583. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ATT_ADDRESS_PORT,
  1584. (UCHAR)(i+PaletteBuffer->FirstEntry));
  1585. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1586. ATT_DATA_WRITE_PORT,
  1587. (UCHAR)PaletteBuffer->Colors[i]);
  1588. }
  1589. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ATT_ADDRESS_PORT,
  1590. VIDEO_ENABLE);
  1591. return NO_ERROR;
  1592. } // end VgaSetPaletteReg()
  1593. VP_STATUS
  1594. VgaSetColorLookup(
  1595. PHW_DEVICE_EXTENSION HwDeviceExtension,
  1596. PVIDEO_CLUT ClutBuffer,
  1597. ULONG ClutBufferSize
  1598. )
  1599. /*++
  1600. Routine Description:
  1601. This routine sets a specified portion of the DAC color lookup table
  1602. settings.
  1603. Arguments:
  1604. HwDeviceExtension - Pointer to the miniport driver's device extension.
  1605. ClutBufferSize - Length of the input buffer supplied by the user.
  1606. ClutBuffer - Pointer to the structure containing the color lookup table.
  1607. Return Value:
  1608. NO_ERROR - information returned successfully
  1609. ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data.
  1610. ERROR_INVALID_PARAMETER - invalid clut size.
  1611. --*/
  1612. {
  1613. USHORT i;
  1614. BOOLEAN PaletteIsSet = FALSE;
  1615. VP_STATUS status;
  1616. //
  1617. // Check if the size of the data in the input buffer is large enough.
  1618. //
  1619. if ( (ClutBufferSize < sizeof(VIDEO_CLUT) - sizeof(ULONG)) ||
  1620. (ClutBufferSize < sizeof(VIDEO_CLUT) +
  1621. (sizeof(ULONG) * (ClutBuffer->NumEntries - 1)) ) ) {
  1622. return ERROR_INSUFFICIENT_BUFFER;
  1623. }
  1624. //
  1625. // Check to see if the parameters are valid.
  1626. //
  1627. if ( (ClutBuffer->NumEntries == 0) ||
  1628. (ClutBuffer->FirstEntry > VIDEO_MAX_COLOR_REGISTER) ||
  1629. (ClutBuffer->FirstEntry + ClutBuffer->NumEntries >
  1630. VIDEO_MAX_COLOR_REGISTER + 1) ) {
  1631. return ERROR_INVALID_PARAMETER;
  1632. }
  1633. if (HwDeviceExtension->CurrentMode->bitsPerPlane >= 8) {
  1634. INT10_BIOS_ARGUMENTS BiosArguments;
  1635. PVIDEO_PORT_INT10_INTERFACE pInt10 = &HwDeviceExtension->Int10;
  1636. PPALETTE_ENTRY Palette = VideoPortAllocatePool(HwDeviceExtension,
  1637. VpPagedPool,
  1638. ClutBuffer->NumEntries *
  1639. sizeof(PALETTE_ENTRY),
  1640. ' agV');
  1641. if (Palette) {
  1642. USHORT VdmSeg;
  1643. USHORT VdmOff;
  1644. ULONG Length = 0x1000;
  1645. if (pInt10->Size &&
  1646. pInt10->Int10AllocateBuffer(pInt10->Context,
  1647. &VdmSeg,
  1648. &VdmOff,
  1649. &Length) == NO_ERROR) {
  1650. for (i=0; i<ClutBuffer->NumEntries; i++) {
  1651. Palette[i].Blue = ClutBuffer->LookupTable[i].RgbArray.Blue;
  1652. Palette[i].Green = ClutBuffer->LookupTable[i].RgbArray.Green;
  1653. Palette[i].Red = ClutBuffer->LookupTable[i].RgbArray.Red;
  1654. Palette[i].Alignment = 0;
  1655. }
  1656. if( NO_ERROR == pInt10->Int10WriteMemory(pInt10->Context,
  1657. VdmSeg,
  1658. VdmOff,
  1659. Palette,
  1660. sizeof(PALETTE_ENTRY) * ClutBuffer->NumEntries)) {
  1661. BiosArguments.Eax = 0x4f09;
  1662. BiosArguments.Ebx = 0x0000;
  1663. BiosArguments.Ecx = ClutBuffer->NumEntries;
  1664. BiosArguments.Edx = ClutBuffer->FirstEntry;
  1665. BiosArguments.Edi = VdmOff;
  1666. BiosArguments.SegEs = VdmSeg;
  1667. status = pInt10->Int10CallBios(pInt10->Context, &BiosArguments);
  1668. if (status == NO_ERROR && VESA_SUCCESS(BiosArguments.Eax)) {
  1669. PaletteIsSet = TRUE;
  1670. }
  1671. }
  1672. pInt10->Int10FreeBuffer(pInt10->Context,
  1673. VdmSeg,
  1674. VdmOff);
  1675. }
  1676. VideoPortFreePool(HwDeviceExtension, Palette);
  1677. }
  1678. }
  1679. if(!PaletteIsSet && !(HwDeviceExtension->CurrentMode->NonVgaHardware)) {
  1680. //
  1681. // Set CLUT registers directly on the hardware
  1682. //
  1683. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1684. DAC_ADDRESS_WRITE_PORT, (UCHAR) ClutBuffer->FirstEntry);
  1685. //
  1686. // Now write the data entries, relying on auto-increment.
  1687. //
  1688. for (i = 0; i < ClutBuffer->NumEntries; i++) {
  1689. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1690. DAC_DATA_REG_PORT,
  1691. ClutBuffer->LookupTable[i].RgbArray.Red);
  1692. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1693. DAC_DATA_REG_PORT,
  1694. ClutBuffer->LookupTable[i].RgbArray.Green);
  1695. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1696. DAC_DATA_REG_PORT,
  1697. ClutBuffer->LookupTable[i].RgbArray.Blue);
  1698. }
  1699. PaletteIsSet = TRUE;
  1700. }
  1701. if(PaletteIsSet) {
  1702. return NO_ERROR;
  1703. } else {
  1704. return ERROR_INVALID_PARAMETER;
  1705. }
  1706. } // end VgaSetColorLookup()
  1707. VP_STATUS
  1708. VgaRestoreHardwareState(
  1709. PHW_DEVICE_EXTENSION HwDeviceExtension,
  1710. PVIDEO_HARDWARE_STATE HardwareState,
  1711. ULONG HardwareStateSize
  1712. )
  1713. /*++
  1714. Routine Description:
  1715. Restores all registers and memory of the VGA.
  1716. Note: HardwareState points to the actual buffer from which the state
  1717. is to be restored. This buffer will always be big enough (we specified
  1718. the required size at DriverEntry).
  1719. Note: The offset in the hardware state header from which each general
  1720. register is restored is the offset of the write address of that register
  1721. from the base I/O address of the VGA.
  1722. Arguments:
  1723. HwDeviceExtension - Pointer to the miniport driver's device extension.
  1724. HardwareState - Pointer to a structure from which the saved state is to be
  1725. restored (actually only info about and a pointer to the actual save
  1726. buffer).
  1727. HardwareStateSize - Length of the input buffer supplied by the user.
  1728. (Actually only the size of the HardwareState structure, not the
  1729. buffer it points to from which the state is actually restored. The
  1730. pointed-to buffer is assumed to be big enough.)
  1731. Return Value:
  1732. NO_ERROR - restore performed successfully
  1733. ERROR_INSUFFICIENT_BUFFER - input buffer not large enough to provide data
  1734. --*/
  1735. {
  1736. PVIDEO_HARDWARE_STATE_HEADER hardwareStateHeader;
  1737. ULONG i;
  1738. UCHAR dummy;
  1739. PUCHAR pScreen;
  1740. PUCHAR pucLatch;
  1741. PULONG pulBuffer;
  1742. PUCHAR port;
  1743. PUCHAR portValue;
  1744. PUCHAR portValueDAC;
  1745. ULONG bIsColor;
  1746. //
  1747. // Check if the size of the data in the input buffer is large enough.
  1748. //
  1749. if ((HardwareStateSize < sizeof(VIDEO_HARDWARE_STATE)) ||
  1750. (HardwareState->StateLength < VGA_TOTAL_STATE_SIZE)) {
  1751. return ERROR_INSUFFICIENT_BUFFER;
  1752. }
  1753. //
  1754. // Point to the buffer where the restore data is actually stored.
  1755. //
  1756. hardwareStateHeader = HardwareState->StateHeader;
  1757. //
  1758. // Make sure the offset are in the structure ...
  1759. //
  1760. if ((hardwareStateHeader->BasicSequencerOffset + VGA_NUM_SEQUENCER_PORTS >
  1761. HardwareState->StateLength) ||
  1762. (hardwareStateHeader->BasicCrtContOffset + VGA_NUM_CRTC_PORTS >
  1763. HardwareState->StateLength) ||
  1764. (hardwareStateHeader->BasicGraphContOffset + VGA_NUM_GRAPH_CONT_PORTS >
  1765. HardwareState->StateLength) ||
  1766. (hardwareStateHeader->BasicAttribContOffset + VGA_NUM_ATTRIB_CONT_PORTS >
  1767. HardwareState->StateLength) ||
  1768. (hardwareStateHeader->BasicDacOffset + (3 * VGA_NUM_DAC_ENTRIES) >
  1769. HardwareState->StateLength) ||
  1770. (hardwareStateHeader->BasicLatchesOffset + 4 >
  1771. HardwareState->StateLength) ||
  1772. (hardwareStateHeader->ExtendedSequencerOffset + EXT_NUM_SEQUENCER_PORTS >
  1773. HardwareState->StateLength) ||
  1774. (hardwareStateHeader->ExtendedCrtContOffset + EXT_NUM_CRTC_PORTS >
  1775. HardwareState->StateLength) ||
  1776. (hardwareStateHeader->ExtendedGraphContOffset + EXT_NUM_GRAPH_CONT_PORTS >
  1777. HardwareState->StateLength) ||
  1778. (hardwareStateHeader->ExtendedAttribContOffset + EXT_NUM_ATTRIB_CONT_PORTS >
  1779. HardwareState->StateLength) ||
  1780. (hardwareStateHeader->ExtendedDacOffset + (4 * EXT_NUM_DAC_ENTRIES) >
  1781. HardwareState->StateLength) ||
  1782. //
  1783. // Only check the validator state offset if there is unemulated data.
  1784. //
  1785. ((hardwareStateHeader->VGAStateFlags & VIDEO_STATE_UNEMULATED_VGA_STATE) &&
  1786. (hardwareStateHeader->ExtendedValidatorStateOffset + VGA_VALIDATOR_AREA_SIZE >
  1787. HardwareState->StateLength)) ||
  1788. (hardwareStateHeader->ExtendedMiscDataOffset + VGA_MISC_DATA_AREA_OFFSET >
  1789. HardwareState->StateLength) ||
  1790. (hardwareStateHeader->Plane1Offset + hardwareStateHeader->PlaneLength >
  1791. HardwareState->StateLength) ||
  1792. (hardwareStateHeader->Plane2Offset + hardwareStateHeader->PlaneLength >
  1793. HardwareState->StateLength) ||
  1794. (hardwareStateHeader->Plane3Offset + hardwareStateHeader->PlaneLength >
  1795. HardwareState->StateLength) ||
  1796. (hardwareStateHeader->Plane4Offset + hardwareStateHeader->PlaneLength >
  1797. HardwareState->StateLength) ||
  1798. (hardwareStateHeader->DIBOffset +
  1799. hardwareStateHeader->DIBBitsPerPixel / 8 *
  1800. hardwareStateHeader->DIBXResolution *
  1801. hardwareStateHeader->DIBYResolution > HardwareState->StateLength) ||
  1802. (hardwareStateHeader->DIBXlatOffset + hardwareStateHeader->DIBXlatLength >
  1803. HardwareState->StateLength)) {
  1804. return ERROR_INVALID_PARAMETER;
  1805. }
  1806. //
  1807. // Turn off the screen to avoid flickering. The screen will turn back on
  1808. // when we restore the DAC state at the end of this routine.
  1809. //
  1810. //
  1811. // Set DAC register 0 to display black.
  1812. //
  1813. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1814. DAC_ADDRESS_WRITE_PORT, 0);
  1815. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1816. DAC_DATA_REG_PORT, 0);
  1817. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1818. DAC_DATA_REG_PORT, 0);
  1819. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1820. DAC_DATA_REG_PORT, 0);
  1821. //
  1822. // Set the DAC mask register to force DAC register 0 to display all the
  1823. // time (this is the register we just set to display black). From now on,
  1824. // nothing but black will show up on the screen.
  1825. //
  1826. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1827. DAC_PIXEL_MASK_PORT, 0);
  1828. //
  1829. // Restore the latches and the contents of display memory.
  1830. //
  1831. // Set up the VGA's hardware to allow us to copy to each plane in turn.
  1832. //
  1833. // Begin sync reset.
  1834. //
  1835. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  1836. SEQ_ADDRESS_PORT),
  1837. (USHORT) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8)));
  1838. //
  1839. // Turn off Chain mode and map display memory at A0000 for 64K.
  1840. //
  1841. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1842. GRAPH_ADDRESS_PORT, IND_GRAPH_MISC);
  1843. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1844. GRAPH_DATA_PORT, (UCHAR) ((VideoPortReadPortUchar(
  1845. HwDeviceExtension->IOAddress + GRAPH_DATA_PORT) & 0xF1) | 0x04));
  1846. //
  1847. // Turn off Chain4 mode and odd/even.
  1848. //
  1849. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1850. SEQ_ADDRESS_PORT, IND_MEMORY_MODE);
  1851. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1852. SEQ_DATA_PORT,
  1853. (UCHAR) ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1854. SEQ_DATA_PORT) & 0xF3) | 0x04));
  1855. //
  1856. // End sync reset.
  1857. //
  1858. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  1859. SEQ_ADDRESS_PORT), (USHORT) (IND_SYNC_RESET +
  1860. (END_SYNC_RESET_VALUE << 8)));
  1861. //
  1862. // Set the write mode to 0, the read mode to 0, and turn off odd/even.
  1863. //
  1864. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1865. GRAPH_ADDRESS_PORT, IND_GRAPH_MODE);
  1866. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1867. GRAPH_DATA_PORT,
  1868. (UCHAR) ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1869. GRAPH_DATA_PORT) & 0xE4) | 0x00));
  1870. //
  1871. // Set the Bit Mask to 0xFF to allow all CPU bits through.
  1872. //
  1873. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  1874. GRAPH_ADDRESS_PORT), (USHORT) (IND_BIT_MASK + (0xFF << 8)));
  1875. //
  1876. // Set the Data Rotation and Logical Function fields to 0 to allow CPU
  1877. // data through unmodified.
  1878. //
  1879. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  1880. GRAPH_ADDRESS_PORT), (USHORT) (IND_DATA_ROTATE + (0 << 8)));
  1881. //
  1882. // Set Set/Reset Enable to 0 to select CPU data for all planes.
  1883. //
  1884. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  1885. GRAPH_ADDRESS_PORT), (USHORT) (IND_SET_RESET_ENABLE + (0 << 8)));
  1886. //
  1887. // Point the Sequencer Index to the Map Mask register.
  1888. //
  1889. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1890. SEQ_ADDRESS_PORT, IND_MAP_MASK);
  1891. //
  1892. // Restore the latches.
  1893. //
  1894. // Point to the saved data for the first latch.
  1895. //
  1896. pucLatch = ((PUCHAR) (hardwareStateHeader)) +
  1897. hardwareStateHeader->BasicLatchesOffset;
  1898. //
  1899. // Point to first byte of display memory.
  1900. //
  1901. pScreen = (PUCHAR) HwDeviceExtension->VideoMemoryAddress;
  1902. //
  1903. // Write the contents to be restored to each of the four latches in turn.
  1904. //
  1905. for (i = 0; i < 4; i++) {
  1906. //
  1907. // Set the Map Mask to select the plane we want to restore next.
  1908. //
  1909. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1910. SEQ_DATA_PORT, (UCHAR)(1<<i));
  1911. //
  1912. // Write this plane's latch.
  1913. //
  1914. VideoPortWriteRegisterUchar(pScreen, *pucLatch++);
  1915. }
  1916. //
  1917. // Read the latched data into the latches, and the latches are set.
  1918. //
  1919. dummy = VideoPortReadRegisterUchar(pScreen);
  1920. //
  1921. // Point to the offset of the saved data for the first plane.
  1922. //
  1923. pulBuffer = &(hardwareStateHeader->Plane1Offset);
  1924. //
  1925. // Restore each of the four planes in turn.
  1926. //
  1927. for (i = 0; i < 4; i++) {
  1928. //
  1929. // Set the Map Mask to select the plane we want to restore next.
  1930. //
  1931. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1932. SEQ_DATA_PORT, (UCHAR)(1<<i));
  1933. //
  1934. // Restore this plane from the buffer.
  1935. //
  1936. VideoPortMoveMemory((PUCHAR) HwDeviceExtension->VideoMemoryAddress,
  1937. ((PUCHAR) (hardwareStateHeader)) + *pulBuffer,
  1938. hardwareStateHeader->PlaneLength);
  1939. pulBuffer++;
  1940. }
  1941. //
  1942. // If we have some unemulated data, put it back into the buffer
  1943. //
  1944. if (hardwareStateHeader->VGAStateFlags & VIDEO_STATE_UNEMULATED_VGA_STATE) {
  1945. if (!hardwareStateHeader->ExtendedValidatorStateOffset) {
  1946. ASSERT(FALSE);
  1947. return ERROR_INVALID_PARAMETER;
  1948. }
  1949. //
  1950. // Get the right offset in the struct and save all the data associated
  1951. // with the trapped validator data.
  1952. //
  1953. VideoPortMoveMemory(&(HwDeviceExtension->TrappedValidatorCount),
  1954. ((PUCHAR) (hardwareStateHeader)) +
  1955. hardwareStateHeader->ExtendedValidatorStateOffset,
  1956. VGA_VALIDATOR_AREA_SIZE);
  1957. //
  1958. // Check to see if this is an appropriate access range.
  1959. // We are trapping - so we must have the trapping access range enabled.
  1960. //
  1961. if (((HwDeviceExtension->CurrentVdmAccessRange != FullVgaValidatorAccessRange) ||
  1962. (HwDeviceExtension->CurrentNumVdmAccessRanges != NUM_FULL_VGA_VALIDATOR_ACCESS_RANGE)) &&
  1963. ((HwDeviceExtension->CurrentVdmAccessRange != MinimalVgaValidatorAccessRange) ||
  1964. (HwDeviceExtension->CurrentNumVdmAccessRanges != NUM_MINIMAL_VGA_VALIDATOR_ACCESS_RANGE))) {
  1965. ASSERT (FALSE);
  1966. return ERROR_INVALID_PARAMETER;
  1967. }
  1968. VideoPortSetTrappedEmulatorPorts(HwDeviceExtension,
  1969. HwDeviceExtension->CurrentNumVdmAccessRanges,
  1970. HwDeviceExtension->CurrentVdmAccessRange);
  1971. }
  1972. //
  1973. // Set the critical registers (clock and timing states) during sync reset.
  1974. //
  1975. // Begin sync reset.
  1976. //
  1977. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  1978. SEQ_ADDRESS_PORT), (USHORT) (IND_SYNC_RESET +
  1979. (START_SYNC_RESET_VALUE << 8)));
  1980. //
  1981. // Restore the Miscellaneous Output register.
  1982. //
  1983. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1984. MISC_OUTPUT_REG_WRITE_PORT,
  1985. (UCHAR) (hardwareStateHeader->PortValue[MISC_OUTPUT_REG_WRITE_PORT] & 0xF7));
  1986. //
  1987. // Restore all Sequencer registers except the Sync Reset register, which
  1988. // is always not in reset (except when we send out a batched sync reset
  1989. // register set, but that can't be interrupted, so we know we're never in
  1990. // sync reset at save/restore time).
  1991. //
  1992. portValue = ((PUCHAR) hardwareStateHeader) +
  1993. hardwareStateHeader->BasicSequencerOffset + 1;
  1994. for (i = 1; i < VGA_NUM_SEQUENCER_PORTS; i++) {
  1995. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  1996. SEQ_ADDRESS_PORT), (USHORT) (i + ((*portValue++) << 8)) );
  1997. }
  1998. //
  1999. // Restore the Graphics Controller Miscellaneous register, which contains
  2000. // the Chain bit.
  2001. //
  2002. portValue = ((PUCHAR) hardwareStateHeader) +
  2003. hardwareStateHeader->BasicGraphContOffset + IND_GRAPH_MISC;
  2004. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2005. GRAPH_ADDRESS_PORT), (USHORT)(IND_GRAPH_MISC + (*portValue << 8)));
  2006. //
  2007. // End sync reset.
  2008. //
  2009. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2010. SEQ_ADDRESS_PORT), (USHORT) (IND_SYNC_RESET +
  2011. (END_SYNC_RESET_VALUE << 8)));
  2012. //
  2013. // Figure out if color/mono switchable registers are at 3BX or 3DX.
  2014. // At the same time, save the state of the Miscellaneous Output register
  2015. // which is read from 3CC but written at 3C2.
  2016. //
  2017. if (hardwareStateHeader->PortValue[MISC_OUTPUT_REG_WRITE_PORT] & 0x01) {
  2018. bIsColor = TRUE;
  2019. } else {
  2020. bIsColor = FALSE;
  2021. }
  2022. //
  2023. // Restore the CRT Controller indexed registers.
  2024. //
  2025. // Unlock CRTC registers 0-7.
  2026. //
  2027. portValue = (PUCHAR) hardwareStateHeader +
  2028. hardwareStateHeader->BasicCrtContOffset;
  2029. if (bIsColor) {
  2030. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2031. CRTC_ADDRESS_PORT_COLOR), (USHORT) (IND_CRTC_PROTECT +
  2032. (((*(portValue + IND_CRTC_PROTECT)) & 0x7F) << 8)));
  2033. } else {
  2034. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2035. CRTC_ADDRESS_PORT_MONO), (USHORT) (IND_CRTC_PROTECT +
  2036. (((*(portValue + IND_CRTC_PROTECT)) & 0x7F) << 8)));
  2037. }
  2038. //
  2039. // Now restore the CRTC registers.
  2040. //
  2041. for (i = 0; i < VGA_NUM_CRTC_PORTS; i++) {
  2042. if (bIsColor) {
  2043. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2044. CRTC_ADDRESS_PORT_COLOR),
  2045. (USHORT) (i + ((*portValue++) << 8)));
  2046. } else {
  2047. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2048. CRTC_ADDRESS_PORT_MONO),
  2049. (USHORT) (i + ((*portValue++) << 8)));
  2050. }
  2051. }
  2052. //
  2053. // Restore the Graphics Controller indexed registers.
  2054. //
  2055. portValue = (PUCHAR) hardwareStateHeader +
  2056. hardwareStateHeader->BasicGraphContOffset;
  2057. for (i = 0; i < VGA_NUM_GRAPH_CONT_PORTS; i++) {
  2058. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2059. GRAPH_ADDRESS_PORT), (USHORT) (i + ((*portValue++) << 8)));
  2060. }
  2061. //
  2062. // Restore the Attribute Controller indexed registers.
  2063. //
  2064. portValue = (PUCHAR) hardwareStateHeader +
  2065. hardwareStateHeader->BasicAttribContOffset;
  2066. //
  2067. // Reset the AC index/data toggle, then blast out all the register
  2068. // settings.
  2069. //
  2070. if (bIsColor) {
  2071. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2072. INPUT_STATUS_1_COLOR);
  2073. } else {
  2074. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2075. INPUT_STATUS_1_MONO);
  2076. }
  2077. for (i = 0; i < VGA_NUM_ATTRIB_CONT_PORTS; i++) {
  2078. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2079. ATT_ADDRESS_PORT, (UCHAR)i);
  2080. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2081. ATT_DATA_WRITE_PORT, *portValue++);
  2082. }
  2083. //
  2084. // Restore DAC registers 1 through 255. We'll do register 0, the DAC Mask,
  2085. // and the index registers later.
  2086. // Set the DAC address port Index, then write out the DAC Data registers.
  2087. // Each three reads get Red, Green, and Blue components for that register.
  2088. //
  2089. // Write them one at a time due to problems on local bus machines.
  2090. //
  2091. portValueDAC = (PUCHAR) hardwareStateHeader +
  2092. hardwareStateHeader->BasicDacOffset + 3;
  2093. for (i = 1; i < VGA_NUM_DAC_ENTRIES; i++) {
  2094. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2095. DAC_ADDRESS_WRITE_PORT, (UCHAR)i);
  2096. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2097. DAC_DATA_REG_PORT, *portValueDAC++);
  2098. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2099. DAC_DATA_REG_PORT, *portValueDAC++);
  2100. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2101. DAC_DATA_REG_PORT, *portValueDAC++);
  2102. }
  2103. //
  2104. // Extended registers are not supported in this driver.
  2105. //
  2106. //
  2107. // Restore the Feature Control register.
  2108. //
  2109. if (bIsColor) {
  2110. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2111. FEAT_CTRL_WRITE_PORT_COLOR,
  2112. hardwareStateHeader->PortValue[FEAT_CTRL_WRITE_PORT_COLOR]);
  2113. } else {
  2114. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2115. FEAT_CTRL_WRITE_PORT_MONO,
  2116. hardwareStateHeader->PortValue[FEAT_CTRL_WRITE_PORT_MONO]);
  2117. }
  2118. //
  2119. // Restore the Sequencer Index.
  2120. //
  2121. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2122. SEQ_ADDRESS_PORT,
  2123. hardwareStateHeader->PortValue[SEQ_ADDRESS_PORT]);
  2124. //
  2125. // Restore the CRT Controller Index.
  2126. //
  2127. if (bIsColor) {
  2128. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2129. CRTC_ADDRESS_PORT_COLOR,
  2130. hardwareStateHeader->PortValue[CRTC_ADDRESS_PORT_COLOR]);
  2131. } else {
  2132. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2133. CRTC_ADDRESS_PORT_MONO,
  2134. hardwareStateHeader->PortValue[CRTC_ADDRESS_PORT_MONO]);
  2135. }
  2136. //
  2137. // Restore the Graphics Controller Index.
  2138. //
  2139. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2140. GRAPH_ADDRESS_PORT,
  2141. hardwareStateHeader->PortValue[GRAPH_ADDRESS_PORT]);
  2142. //
  2143. // Restore the Attribute Controller Index and index/data toggle state.
  2144. //
  2145. if (bIsColor) {
  2146. port = HwDeviceExtension->IOAddress + INPUT_STATUS_1_COLOR;
  2147. } else {
  2148. port = HwDeviceExtension->IOAddress + INPUT_STATUS_1_MONO;
  2149. }
  2150. VideoPortReadPortUchar(port); // reset the toggle to Index state
  2151. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2152. ATT_ADDRESS_PORT, // restore the AC Index
  2153. hardwareStateHeader->PortValue[ATT_ADDRESS_PORT]);
  2154. //
  2155. // If the toggle should be in Data state, we're all set. If it should be in
  2156. // Index state, reset it to that condition.
  2157. //
  2158. if (hardwareStateHeader->AttribIndexDataState == 0) {
  2159. //
  2160. // Reset the toggle to Index state.
  2161. //
  2162. VideoPortReadPortUchar(port);
  2163. }
  2164. //
  2165. // Restore DAC register 0 and the DAC Mask, to unblank the screen.
  2166. //
  2167. portValueDAC = (PUCHAR) hardwareStateHeader +
  2168. hardwareStateHeader->BasicDacOffset;
  2169. //
  2170. // Restore the DAC Mask register.
  2171. //
  2172. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2173. DAC_PIXEL_MASK_PORT,
  2174. hardwareStateHeader->PortValue[DAC_PIXEL_MASK_PORT]);
  2175. //
  2176. // Restore DAC register 0.
  2177. //
  2178. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2179. DAC_ADDRESS_WRITE_PORT, 0);
  2180. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2181. DAC_DATA_REG_PORT, *portValueDAC++);
  2182. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2183. DAC_DATA_REG_PORT, *portValueDAC++);
  2184. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2185. DAC_DATA_REG_PORT, *portValueDAC++);
  2186. //
  2187. // Restore the read/write state and the current index of the DAC.
  2188. //
  2189. // See whether the Read or Write Index was written to most recently.
  2190. // (The upper nibble stored at DAC_STATE_PORT is the # of reads/writes
  2191. // for the current index.)
  2192. //
  2193. if ((hardwareStateHeader->PortValue[DAC_STATE_PORT] & 0x0F) == 3) {
  2194. //
  2195. // The DAC Read Index was written to last. Restore the DAC by setting
  2196. // up to read from the saved index - 1, because the way the Read
  2197. // Index works is that it autoincrements after reading, so you actually
  2198. // end up reading the data for the index you read at the DAC Write
  2199. // Mask register - 1.
  2200. //
  2201. // Set the Read Index to the index we read, minus 1, accounting for
  2202. // wrap from 255 back to 0. The DAC hardware immediately reads this
  2203. // register into a temporary buffer, then adds 1 to the index.
  2204. //
  2205. if (hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT] == 0) {
  2206. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2207. DAC_ADDRESS_READ_PORT, 255);
  2208. } else {
  2209. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2210. DAC_ADDRESS_READ_PORT, (UCHAR)
  2211. (hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT] -
  2212. 1));
  2213. }
  2214. //
  2215. // Now read the hardware however many times are required to get to
  2216. // the partial read state we saved.
  2217. //
  2218. for (i = hardwareStateHeader->PortValue[DAC_STATE_PORT] >> 4;
  2219. i > 0; i--) {
  2220. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2221. DAC_DATA_REG_PORT);
  2222. }
  2223. } else {
  2224. //
  2225. // The DAC Write Index was written to last. Set the Write Index to the
  2226. // index value we read out of the DAC. Then, if a partial write
  2227. // (partway through an RGB triplet) was in place, write the partial
  2228. // values, which we obtained by writing them to the current DAC
  2229. // register. This DAC register will be wrong until the write is
  2230. // completed, but at least the values will be right once the write is
  2231. // finished, and most importantly we won't have messed up the sequence
  2232. // of RGB writes (which can be as long as 768 in a row).
  2233. //
  2234. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2235. DAC_ADDRESS_WRITE_PORT,
  2236. hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT]);
  2237. //
  2238. // Now write to the hardware however many times are required to get to
  2239. // the partial write state we saved (if any).
  2240. //
  2241. // Point to the saved value for the DAC register that was in the
  2242. // process of being written to; we wrote the partial value out, so now
  2243. // we can restore it.
  2244. //
  2245. portValueDAC = (PUCHAR) hardwareStateHeader +
  2246. hardwareStateHeader->BasicDacOffset +
  2247. (hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT] * 3);
  2248. for (i = hardwareStateHeader->PortValue[DAC_STATE_PORT] >> 4;
  2249. i > 0; i--) {
  2250. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2251. DAC_DATA_REG_PORT, *portValueDAC++);
  2252. }
  2253. }
  2254. return NO_ERROR;
  2255. } // end VgaRestoreHardwareState()
  2256. VP_STATUS
  2257. VgaSaveHardwareState(
  2258. PHW_DEVICE_EXTENSION HwDeviceExtension,
  2259. PVIDEO_HARDWARE_STATE HardwareState,
  2260. ULONG HardwareStateSize,
  2261. PULONG OutputSize
  2262. )
  2263. /*++
  2264. Routine Description:
  2265. Saves all registers and memory of the VGA.
  2266. Note: HardwareState points to the actual buffer in which the state
  2267. is saved. This buffer will always be big enough (we specified
  2268. the required size at DriverEntry).
  2269. Note: This routine leaves registers in any state it cares to, except
  2270. that it will not mess with any of the CRT or Sequencer parameters that
  2271. might make the monitor unhappy. It leaves the screen blanked by setting
  2272. the DAC Mask and DAC register 0 to all zero values. The next video
  2273. operation we expect after this is a mode set to take us back to Win32.
  2274. Note: The offset in the hardware state header in which each general
  2275. register is saved is the offset of the write address of that register from
  2276. the base I/O address of the VGA.
  2277. Arguments:
  2278. HwDeviceExtension - Pointer to the miniport driver's device extension.
  2279. HardwareState - Pointer to a structure in which the saved state will be
  2280. returned (actually only info about and a pointer to the actual save
  2281. buffer).
  2282. HardwareStateSize - Length of the output buffer supplied by the user.
  2283. (Actually only the size of the HardwareState structure, not the
  2284. buffer it points to where the state is actually saved. The pointed-
  2285. to buffer is assumed to be big enough.)
  2286. OutputSize - Pointer to a buffer in which to return the actual size of
  2287. the data returned in the buffer.
  2288. Return Value:
  2289. NO_ERROR - information returned successfully
  2290. ERROR_INSUFFICIENT_BUFFER - output buffer not large enough to return
  2291. any useful data
  2292. --*/
  2293. {
  2294. PVIDEO_HARDWARE_STATE_HEADER hardwareStateHeader;
  2295. PUCHAR pScreen;
  2296. PUCHAR portValue;
  2297. PUCHAR portValueDAC;
  2298. PUCHAR bufferPointer;
  2299. ULONG i;
  2300. UCHAR dummy, originalACIndex, originalACData;
  2301. UCHAR ucCRTC03;
  2302. ULONG bIsColor;
  2303. //
  2304. // See if the buffer is big enough to hold the hardware state structure.
  2305. // (This is only the HardwareState structure itself, not the buffer it
  2306. // points to.)
  2307. //
  2308. if (HardwareStateSize < sizeof(VIDEO_HARDWARE_STATE) ) {
  2309. *OutputSize = 0; // nothing returned
  2310. return ERROR_INSUFFICIENT_BUFFER;
  2311. }
  2312. //
  2313. // Amount of data we're going to return in the output buffer.
  2314. // (The VIDEO_HARDWARE_STATE in the output buffer points to the actual
  2315. // buffer in which the state is stored, which is assumed to be large
  2316. // enough.)
  2317. //
  2318. *OutputSize = sizeof(VIDEO_HARDWARE_STATE);
  2319. //
  2320. // Indicate the size of the full state save info.
  2321. //
  2322. HardwareState->StateLength = VGA_TOTAL_STATE_SIZE;
  2323. //
  2324. // hardwareStateHeader is a structure of offsets at the start of the
  2325. // actual save area that indicates the locations in which various VGA
  2326. // register and memory components are saved.
  2327. //
  2328. hardwareStateHeader = HardwareState->StateHeader;
  2329. //
  2330. // Zero out the structure.
  2331. //
  2332. VideoPortZeroMemory(hardwareStateHeader, sizeof(VIDEO_HARDWARE_STATE_HEADER));
  2333. //
  2334. // Set the Length field, which is basically a version ID.
  2335. //
  2336. hardwareStateHeader->Length = sizeof(VIDEO_HARDWARE_STATE_HEADER);
  2337. //
  2338. // Set the basic register offsets properly.
  2339. //
  2340. hardwareStateHeader->BasicSequencerOffset = VGA_BASIC_SEQUENCER_OFFSET;
  2341. hardwareStateHeader->BasicCrtContOffset = VGA_BASIC_CRTC_OFFSET;
  2342. hardwareStateHeader->BasicGraphContOffset = VGA_BASIC_GRAPH_CONT_OFFSET;
  2343. hardwareStateHeader->BasicAttribContOffset = VGA_BASIC_ATTRIB_CONT_OFFSET;
  2344. hardwareStateHeader->BasicDacOffset = VGA_BASIC_DAC_OFFSET;
  2345. hardwareStateHeader->BasicLatchesOffset = VGA_BASIC_LATCHES_OFFSET;
  2346. //
  2347. // Set the entended register offsets properly.
  2348. //
  2349. hardwareStateHeader->ExtendedSequencerOffset = VGA_EXT_SEQUENCER_OFFSET;
  2350. hardwareStateHeader->ExtendedCrtContOffset = VGA_EXT_CRTC_OFFSET;
  2351. hardwareStateHeader->ExtendedGraphContOffset = VGA_EXT_GRAPH_CONT_OFFSET;
  2352. hardwareStateHeader->ExtendedAttribContOffset = VGA_EXT_ATTRIB_CONT_OFFSET;
  2353. hardwareStateHeader->ExtendedDacOffset = VGA_EXT_DAC_OFFSET;
  2354. //
  2355. // Figure out if color/mono switchable registers are at 3BX or 3DX.
  2356. // At the same time, save the state of the Miscellaneous Output register
  2357. // which is read from 3CC but written at 3C2.
  2358. //
  2359. if ((hardwareStateHeader->PortValue[MISC_OUTPUT_REG_WRITE_PORT] =
  2360. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2361. MISC_OUTPUT_REG_READ_PORT))
  2362. & 0x01) {
  2363. bIsColor = TRUE;
  2364. } else {
  2365. bIsColor = FALSE;
  2366. }
  2367. //
  2368. // Force the video subsystem enable state to enabled.
  2369. //
  2370. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2371. VIDEO_SUBSYSTEM_ENABLE_PORT, 1);
  2372. //
  2373. // Save the DAC state first, so we can set the DAC to blank the screen
  2374. // so nothing after this shows up at all.
  2375. //
  2376. // Save the DAC Mask register.
  2377. //
  2378. hardwareStateHeader->PortValue[DAC_PIXEL_MASK_PORT] =
  2379. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2380. DAC_PIXEL_MASK_PORT);
  2381. //
  2382. // Save the DAC Index register. Note that there is actually only one DAC
  2383. // Index register, which functions as either the Read Index or the Write
  2384. // Index as needed.
  2385. //
  2386. hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT] =
  2387. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2388. DAC_ADDRESS_WRITE_PORT);
  2389. //
  2390. // Save the DAC read/write state. We determine if the DAC has been written
  2391. // to or read from at the current index 0, 1, or 2 times (the application
  2392. // is in the middle of reading or writing a DAC register triplet if the
  2393. // count is 1 or 2), and save enough info so we can restore things
  2394. // properly. The only hole is if the application writes to the Write Index,
  2395. // then reads from instead of writes to the Data register, or vice-versa,
  2396. // or if they do a partial read write, then never finish it.
  2397. // This is fairly ridiculous behavior, however, and anyway there's nothing
  2398. // we can do about it.
  2399. //
  2400. hardwareStateHeader->PortValue[DAC_STATE_PORT] =
  2401. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2402. DAC_STATE_PORT);
  2403. if (hardwareStateHeader->PortValue[DAC_STATE_PORT] == 3) {
  2404. //
  2405. // The DAC Read Index was written to last. Figure out how many reads
  2406. // have been done from the current index. We'll restart this on restore
  2407. // by setting the Read Index to the current index - 1 (the read index
  2408. // is one greater than the index being read), then doing the proper
  2409. // number of reads.
  2410. //
  2411. // Read the Data register once, and see if the index changes.
  2412. //
  2413. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2414. DAC_DATA_REG_PORT);
  2415. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2416. DAC_ADDRESS_WRITE_PORT) !=
  2417. hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT]) {
  2418. //
  2419. // The DAC Index changed, so two reads had already been done from
  2420. // the current index. Store the count "2" in the upper nibble of
  2421. // the read/write state field.
  2422. //
  2423. hardwareStateHeader->PortValue[DAC_STATE_PORT] |= 0x20;
  2424. } else {
  2425. //
  2426. // Read the Data register again, and see if the index changes.
  2427. //
  2428. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2429. DAC_DATA_REG_PORT);
  2430. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2431. DAC_ADDRESS_WRITE_PORT) !=
  2432. hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT]) {
  2433. //
  2434. // The DAC Index changed, so one read had already been done
  2435. // from the current index. Store the count "1" in the upper
  2436. // nibble of the read/write state field.
  2437. //
  2438. hardwareStateHeader->PortValue[DAC_STATE_PORT] |= 0x10;
  2439. }
  2440. //
  2441. // If neither 2 nor 1 reads had been done from the current index,
  2442. // then 0 reads were done, and we're all set, since the upper
  2443. // nibble of the read/write state field is already 0.
  2444. //
  2445. }
  2446. } else {
  2447. //
  2448. // The DAC Write Index was written to last. Figure out how many writes
  2449. // have been done to the current index. We'll restart this on restore
  2450. // by setting the Write Index to the proper index, then doing the
  2451. // proper number of writes. When we do the DAC register save, we'll
  2452. // read out the value that gets written (if there was a partial write
  2453. // in progress), so we can restore the proper data later. This will
  2454. // cause this current DAC location to be briefly wrong in the 1- and
  2455. // 2-bytes-written case (until the app finishes the write), but that's
  2456. // better than having the wrong DAC values written for good.
  2457. //
  2458. // Write the Data register once, and see if the index changes.
  2459. //
  2460. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2461. DAC_DATA_REG_PORT, 0);
  2462. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2463. DAC_ADDRESS_WRITE_PORT) !=
  2464. hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT]) {
  2465. //
  2466. // The DAC Index changed, so two writes had already been done to
  2467. // the current index. Store the count "2" in the upper nibble of
  2468. // the read/write state field.
  2469. //
  2470. hardwareStateHeader->PortValue[DAC_STATE_PORT] |= 0x20;
  2471. } else {
  2472. //
  2473. // Write the Data register again, and see if the index changes.
  2474. //
  2475. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2476. DAC_DATA_REG_PORT, 0);
  2477. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2478. DAC_ADDRESS_WRITE_PORT) !=
  2479. hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT]) {
  2480. //
  2481. // The DAC Index changed, so one write had already been done
  2482. // to the current index. Store the count "1" in the upper
  2483. // nibble of the read/write state field.
  2484. //
  2485. hardwareStateHeader->PortValue[DAC_STATE_PORT] |= 0x10;
  2486. }
  2487. //
  2488. // If neither 2 nor 1 writes had been done to the current index,
  2489. // then 0 writes were done, and we're all set.
  2490. //
  2491. }
  2492. }
  2493. //
  2494. // Now, read out the 256 18-bit DAC palette registers (256 RGB triplets),
  2495. // and blank the screen.
  2496. //
  2497. portValueDAC = (PUCHAR) hardwareStateHeader + VGA_BASIC_DAC_OFFSET;
  2498. //
  2499. // Read out DAC register 0, so we can set it to black.
  2500. //
  2501. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2502. DAC_ADDRESS_READ_PORT, 0);
  2503. *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2504. DAC_DATA_REG_PORT);
  2505. *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2506. DAC_DATA_REG_PORT);
  2507. *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2508. DAC_DATA_REG_PORT);
  2509. //
  2510. // Set DAC register 0 to display black.
  2511. //
  2512. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2513. DAC_ADDRESS_WRITE_PORT, 0);
  2514. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2515. DAC_DATA_REG_PORT, 0);
  2516. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2517. DAC_DATA_REG_PORT, 0);
  2518. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2519. DAC_DATA_REG_PORT, 0);
  2520. //
  2521. // Set the DAC mask register to force DAC register 0 to display all the
  2522. // time (this is the register we just set to display black). From now on,
  2523. // nothing but black will show up on the screen.
  2524. //
  2525. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2526. DAC_PIXEL_MASK_PORT, 0);
  2527. //
  2528. // Read out the Attribute Controller Index state, and deduce the Index/Data
  2529. // toggle state at the same time.
  2530. //
  2531. // Save the state of the Attribute Controller, both Index and Data,
  2532. // so we can test in which state the toggle currently is.
  2533. //
  2534. originalACIndex = hardwareStateHeader->PortValue[ATT_ADDRESS_PORT] =
  2535. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2536. ATT_ADDRESS_PORT);
  2537. originalACData = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2538. ATT_DATA_READ_PORT);
  2539. //
  2540. // Sequencer Index.
  2541. //
  2542. hardwareStateHeader->PortValue[SEQ_ADDRESS_PORT] =
  2543. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2544. SEQ_ADDRESS_PORT);
  2545. //
  2546. // Begin sync reset, just in case this is an SVGA and the currently
  2547. // indexed Attribute Controller register controls clocking stuff (a
  2548. // normal VGA won't require this).
  2549. //
  2550. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2551. SEQ_ADDRESS_PORT),
  2552. (USHORT) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8)));
  2553. //
  2554. // Now, write a different Index setting to the Attribute Controller, and
  2555. // see if the Index changes.
  2556. //
  2557. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2558. ATT_ADDRESS_PORT, (UCHAR) (originalACIndex ^ 0x10));
  2559. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2560. ATT_ADDRESS_PORT) == originalACIndex) {
  2561. //
  2562. // The Index didn't change, so the toggle was in the Data state.
  2563. //
  2564. hardwareStateHeader->AttribIndexDataState = 1;
  2565. //
  2566. // Restore the original Data state; we just corrupted it, and we need
  2567. // to read it out later; also, it may glitch the screen if not
  2568. // corrected. The toggle is already in the Index state.
  2569. //
  2570. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2571. ATT_ADDRESS_PORT, originalACIndex);
  2572. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2573. ATT_DATA_WRITE_PORT, originalACData);
  2574. } else {
  2575. //
  2576. // The Index did change, so the toggle was in the Index state.
  2577. // No need to restore anything, because the Data register didn't
  2578. // change, and we've already read out the Index register.
  2579. //
  2580. hardwareStateHeader->AttribIndexDataState = 0;
  2581. }
  2582. //
  2583. // End sync reset.
  2584. //
  2585. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2586. SEQ_ADDRESS_PORT),
  2587. (USHORT) (IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8)));
  2588. //
  2589. // Save the rest of the DAC registers.
  2590. // Set the DAC address port Index, then read out the DAC Data registers.
  2591. // Each three reads get Red, Green, and Blue components for that register.
  2592. //
  2593. // Read them one at a time due to problems on local bus machines.
  2594. //
  2595. for (i = 1; i < VGA_NUM_DAC_ENTRIES; i++) {
  2596. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2597. DAC_ADDRESS_READ_PORT, (UCHAR)i);
  2598. *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2599. DAC_DATA_REG_PORT);
  2600. *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2601. DAC_DATA_REG_PORT);
  2602. *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2603. DAC_DATA_REG_PORT);
  2604. }
  2605. //
  2606. // The Feature Control register is read from 3CA but written at 3BA/3DA.
  2607. //
  2608. if (bIsColor) {
  2609. hardwareStateHeader->PortValue[FEAT_CTRL_WRITE_PORT_COLOR] =
  2610. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2611. FEAT_CTRL_READ_PORT);
  2612. } else {
  2613. hardwareStateHeader->PortValue[FEAT_CTRL_WRITE_PORT_MONO] =
  2614. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2615. FEAT_CTRL_READ_PORT);
  2616. }
  2617. //
  2618. // CRT Controller Index.
  2619. //
  2620. if (bIsColor) {
  2621. hardwareStateHeader->PortValue[CRTC_ADDRESS_PORT_COLOR] =
  2622. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2623. CRTC_ADDRESS_PORT_COLOR);
  2624. } else {
  2625. hardwareStateHeader->PortValue[CRTC_ADDRESS_PORT_MONO] =
  2626. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2627. CRTC_ADDRESS_PORT_MONO);
  2628. }
  2629. //
  2630. // Graphics Controller Index.
  2631. //
  2632. hardwareStateHeader->PortValue[GRAPH_ADDRESS_PORT] =
  2633. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2634. GRAPH_ADDRESS_PORT);
  2635. //
  2636. // Sequencer indexed registers.
  2637. //
  2638. portValue = ((PUCHAR) hardwareStateHeader) + VGA_BASIC_SEQUENCER_OFFSET;
  2639. for (i = 0; i < VGA_NUM_SEQUENCER_PORTS; i++) {
  2640. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2641. SEQ_ADDRESS_PORT, (UCHAR)i);
  2642. *portValue++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2643. SEQ_DATA_PORT);
  2644. }
  2645. //
  2646. // CRT Controller indexed registers.
  2647. //
  2648. //
  2649. // Remember the state of CRTC register 3, then force bit 7
  2650. // to 1 so we will read back the Vertical Retrace start and
  2651. // end registers rather than the light pen info.
  2652. //
  2653. if (bIsColor) {
  2654. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2655. CRTC_ADDRESS_PORT_COLOR, 3);
  2656. ucCRTC03 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2657. CRTC_DATA_PORT_COLOR);
  2658. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2659. CRTC_DATA_PORT_COLOR, (UCHAR) (ucCRTC03 | 0x80));
  2660. } else {
  2661. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2662. CRTC_ADDRESS_PORT_MONO, 3);
  2663. ucCRTC03 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2664. CRTC_DATA_PORT_MONO);
  2665. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2666. CRTC_DATA_PORT_MONO, (UCHAR) (ucCRTC03 | 0x80));
  2667. }
  2668. portValue = (PUCHAR) hardwareStateHeader + VGA_BASIC_CRTC_OFFSET;
  2669. for (i = 0; i < VGA_NUM_CRTC_PORTS; i++) {
  2670. if (bIsColor) {
  2671. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2672. CRTC_ADDRESS_PORT_COLOR, (UCHAR)i);
  2673. *portValue++ =
  2674. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2675. CRTC_DATA_PORT_COLOR);
  2676. } else {
  2677. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2678. CRTC_ADDRESS_PORT_MONO, (UCHAR)i);
  2679. *portValue++ =
  2680. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2681. CRTC_DATA_PORT_MONO);
  2682. }
  2683. }
  2684. portValue = (PUCHAR) hardwareStateHeader + VGA_BASIC_CRTC_OFFSET;
  2685. portValue[3] = ucCRTC03;
  2686. //
  2687. // Graphics Controller indexed registers.
  2688. //
  2689. portValue = (PUCHAR) hardwareStateHeader + VGA_BASIC_GRAPH_CONT_OFFSET;
  2690. for (i = 0; i < VGA_NUM_GRAPH_CONT_PORTS; i++) {
  2691. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2692. GRAPH_ADDRESS_PORT, (UCHAR)i);
  2693. *portValue++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2694. GRAPH_DATA_PORT);
  2695. }
  2696. //
  2697. // Attribute Controller indexed registers.
  2698. //
  2699. portValue = (PUCHAR) hardwareStateHeader + VGA_BASIC_ATTRIB_CONT_OFFSET;
  2700. //
  2701. // For each indexed AC register, reset the flip-flop for reading the
  2702. // attribute register, then write the desired index to the AC Index,
  2703. // then read the value of the indexed register from the AC Data register.
  2704. //
  2705. for (i = 0; i < VGA_NUM_ATTRIB_CONT_PORTS; i++) {
  2706. if (bIsColor) {
  2707. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2708. INPUT_STATUS_1_COLOR);
  2709. } else {
  2710. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2711. INPUT_STATUS_1_MONO);
  2712. }
  2713. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2714. ATT_ADDRESS_PORT, (UCHAR)i);
  2715. *portValue++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2716. ATT_DATA_READ_PORT);
  2717. }
  2718. //
  2719. // Save the latches. This destroys one byte of display memory in each
  2720. // plane, which is unfortunate but unavoidable. Chips that provide
  2721. // a way to read back the latches can avoid this problem.
  2722. //
  2723. // Set up the VGA's hardware so we can write the latches, then read them
  2724. // back.
  2725. //
  2726. //
  2727. // Begin sync reset.
  2728. //
  2729. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2730. SEQ_ADDRESS_PORT),
  2731. (USHORT) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8)));
  2732. //
  2733. // Set the Miscellaneous register to make sure we can access video RAM.
  2734. //
  2735. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2736. MISC_OUTPUT_REG_WRITE_PORT, (UCHAR)(
  2737. hardwareStateHeader->PortValue[MISC_OUTPUT_REG_WRITE_PORT] |
  2738. 0x02));
  2739. //
  2740. // Turn off Chain mode and map display memory at A0000 for 64K.
  2741. //
  2742. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2743. GRAPH_ADDRESS_PORT, IND_GRAPH_MISC);
  2744. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2745. GRAPH_DATA_PORT,
  2746. (UCHAR) ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2747. GRAPH_DATA_PORT) & 0xF1) | 0x04));
  2748. //
  2749. // Turn off Chain4 mode and odd/even.
  2750. //
  2751. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2752. SEQ_ADDRESS_PORT, IND_MEMORY_MODE);
  2753. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2754. SEQ_DATA_PORT,
  2755. (UCHAR) ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2756. SEQ_DATA_PORT) & 0xF3) | 0x04));
  2757. //
  2758. // End sync reset.
  2759. //
  2760. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2761. SEQ_ADDRESS_PORT),
  2762. (USHORT) (IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8)));
  2763. //
  2764. // Set the Map Mask to write to all planes.
  2765. //
  2766. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2767. SEQ_ADDRESS_PORT), (USHORT) (IND_MAP_MASK + (0x0F << 8)));
  2768. //
  2769. // Set the write mode to 0, the read mode to 0, and turn off odd/even.
  2770. //
  2771. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2772. GRAPH_ADDRESS_PORT, IND_GRAPH_MODE);
  2773. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2774. GRAPH_DATA_PORT,
  2775. (UCHAR) ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2776. GRAPH_DATA_PORT) & 0xE4) | 0x01));
  2777. //
  2778. // Point to the last byte of display memory.
  2779. //
  2780. pScreen = (PUCHAR) HwDeviceExtension->VideoMemoryAddress +
  2781. VGA_PLANE_SIZE - 1;
  2782. //
  2783. // Write the latches to the last byte of display memory.
  2784. //
  2785. VideoPortWriteRegisterUchar(pScreen, 0);
  2786. //
  2787. // Cycle through the four planes, reading the latch data from each plane.
  2788. //
  2789. //
  2790. // Point the Graphics Controller Index to the Read Map register.
  2791. //
  2792. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2793. GRAPH_ADDRESS_PORT, IND_READ_MAP);
  2794. portValue = (PUCHAR) hardwareStateHeader + VGA_BASIC_LATCHES_OFFSET;
  2795. for (i=0; i<4; i++) {
  2796. //
  2797. // Set the Read Map for the current plane.
  2798. //
  2799. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2800. GRAPH_DATA_PORT, (UCHAR)i);
  2801. //
  2802. // Read the latched data we've written to memory.
  2803. //
  2804. *portValue++ = VideoPortReadRegisterUchar(pScreen);
  2805. }
  2806. //
  2807. // Set the VDM flags
  2808. // We are a standard VGA, and then check if we have unemulated state.
  2809. //
  2810. hardwareStateHeader->VGAStateFlags = 0;
  2811. if (HwDeviceExtension->TrappedValidatorCount) {
  2812. hardwareStateHeader->VGAStateFlags |= VIDEO_STATE_UNEMULATED_VGA_STATE;
  2813. //
  2814. // Save the VDM Emulator data
  2815. // No need to save the state of the sequencer port register for our
  2816. // emulated data since it may change when we come back. It will be
  2817. // recomputed.
  2818. //
  2819. hardwareStateHeader->ExtendedValidatorStateOffset = VGA_VALIDATOR_OFFSET;
  2820. VideoPortMoveMemory(((PUCHAR) (hardwareStateHeader)) +
  2821. hardwareStateHeader->ExtendedValidatorStateOffset,
  2822. &(HwDeviceExtension->TrappedValidatorCount),
  2823. VGA_VALIDATOR_AREA_SIZE);
  2824. } else {
  2825. hardwareStateHeader->ExtendedValidatorStateOffset = 0;
  2826. }
  2827. //
  2828. // Set the size of each plane.
  2829. //
  2830. hardwareStateHeader->PlaneLength = VGA_PLANE_SIZE;
  2831. //
  2832. // Store all the offsets for the planes in the structure.
  2833. //
  2834. hardwareStateHeader->Plane1Offset = VGA_PLANE_0_OFFSET;
  2835. hardwareStateHeader->Plane2Offset = VGA_PLANE_1_OFFSET;
  2836. hardwareStateHeader->Plane3Offset = VGA_PLANE_2_OFFSET;
  2837. hardwareStateHeader->Plane4Offset = VGA_PLANE_3_OFFSET;
  2838. //
  2839. // Now copy the contents of video VRAM into the buffer.
  2840. //
  2841. // The VGA hardware is already set up so that video memory is readable;
  2842. // we already turned off Chain mode, mapped in at A0000, turned off Chain4,
  2843. // turned off odd/even, and set read mode 0 when we saved the latches.
  2844. //
  2845. // Point the Graphics Controller Index to the Read Map register.
  2846. //
  2847. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2848. GRAPH_ADDRESS_PORT, IND_READ_MAP);
  2849. //
  2850. // Point to the save area for the first plane.
  2851. //
  2852. bufferPointer = ((PUCHAR) (hardwareStateHeader)) +
  2853. hardwareStateHeader->Plane1Offset;
  2854. //
  2855. // Save the four planes consecutively.
  2856. //
  2857. for (i = 0; i < 4; i++) {
  2858. //
  2859. // Set the Read Map to select the plane we want to save next.
  2860. //
  2861. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2862. GRAPH_DATA_PORT, (UCHAR)i);
  2863. //
  2864. // Copy this plane into the buffer.
  2865. //
  2866. VideoPortMoveMemory(bufferPointer,
  2867. (PUCHAR) HwDeviceExtension->VideoMemoryAddress,
  2868. VGA_PLANE_SIZE);
  2869. //
  2870. // Point to the next plane's save area.
  2871. //
  2872. bufferPointer += VGA_PLANE_SIZE;
  2873. }
  2874. //
  2875. // Reenable video output
  2876. //
  2877. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2878. DAC_PIXEL_MASK_PORT, 0xff);
  2879. return NO_ERROR;
  2880. } // end VgaSaveHardwareState()
  2881. VP_STATUS
  2882. VgaGetBankSelectCode(
  2883. PHW_DEVICE_EXTENSION HwDeviceExtension,
  2884. PVIDEO_BANK_SELECT BankSelect,
  2885. ULONG BankSelectSize,
  2886. PULONG OutputSize
  2887. )
  2888. /*++
  2889. Routine Description:
  2890. Returns information needed in order for caller to implement bank
  2891. management.
  2892. Arguments:
  2893. HwDeviceExtension - Pointer to the miniport driver's device extension.
  2894. BankSelect - Pointer to a VIDEO_BANK_SELECT structure in which the bank
  2895. select data will be returned (output buffer).
  2896. BankSelectSize - Length of the output buffer supplied by the user.
  2897. OutputSize - Pointer to a variable in which to return the actual size of
  2898. the data returned in the output buffer.
  2899. Return Value:
  2900. NO_ERROR - information returned successfully
  2901. ERROR_MORE_DATA - output buffer not large enough to hold all info (but
  2902. Size is returned, so caller can tell how large a buffer to allocate)
  2903. ERROR_INSUFFICIENT_BUFFER - output buffer not large enough to return
  2904. any useful data
  2905. --*/
  2906. {
  2907. PUCHAR pCode = (PUCHAR)BankSelect + sizeof(VIDEO_BANK_SELECT);
  2908. //
  2909. // check if a mode has been set
  2910. //
  2911. if (HwDeviceExtension->CurrentMode == NULL) {
  2912. return ERROR_INVALID_FUNCTION;
  2913. }
  2914. //
  2915. // The minimum passed buffer size is a VIDEO_BANK_SELECT
  2916. // structure, so that we can return the required size; we can't do
  2917. // anything if we don't have at least that much buffer.
  2918. //
  2919. if (BankSelectSize < sizeof(VIDEO_BANK_SELECT)) {
  2920. return ERROR_INSUFFICIENT_BUFFER;
  2921. }
  2922. //
  2923. // Size of banking info.
  2924. //
  2925. BankSelect->Length = sizeof(VIDEO_BANK_SELECT);
  2926. BankSelect->Size = sizeof(VIDEO_BANK_SELECT);
  2927. //
  2928. // There's room enough for everything, so fill in required fields in
  2929. // VIDEO_BANK_SELECT.
  2930. //
  2931. // That's pretty easy in this case, since there's no banking; only
  2932. // the banking type, the bitmap width, and the bitmap size need to be
  2933. // filled in. We'll provide dummy bank switch code, too, that just
  2934. // returns, because it shouldn't ever be called.
  2935. //
  2936. BankSelect->BankingFlags = 0;
  2937. BankSelect->BankingType = VideoBanked1RW;
  2938. BankSelect->PlanarHCBankingType = VideoBanked1RW;
  2939. BankSelect->BitmapWidthInBytes = HwDeviceExtension->CurrentMode->wbytes;
  2940. BankSelect->BitmapSize = HwDeviceExtension->CurrentMode->sbytes;
  2941. BankSelect->Granularity = HwDeviceExtension->CurrentMode->Granularity;
  2942. if(! BankSelect->Granularity )
  2943. BankSelect->Granularity = 0x10000;
  2944. BankSelect->PlanarHCGranularity = BankSelect->Granularity >> 2;
  2945. //
  2946. // If the buffer isn't big enough to hold all info, just return
  2947. // ERROR_MORE_DATA; Size is already set.
  2948. //
  2949. if (BankSelectSize < BankSelect->Size ) {
  2950. //
  2951. // We're returning only the VIDEO_BANK_SELECT structure.
  2952. //
  2953. *OutputSize = sizeof(VIDEO_BANK_SELECT);
  2954. return ERROR_MORE_DATA;
  2955. }
  2956. //
  2957. // Set the bank switch code's location in the returned buffer.
  2958. //
  2959. BankSelect->CodeOffset = sizeof(VIDEO_BANK_SELECT);
  2960. BankSelect->PlanarHCBankCodeOffset = sizeof(VIDEO_BANK_SELECT);
  2961. BankSelect->PlanarHCEnableCodeOffset = sizeof(VIDEO_BANK_SELECT);
  2962. BankSelect->PlanarHCDisableCodeOffset = sizeof(VIDEO_BANK_SELECT);
  2963. //
  2964. // Number of bytes we're returning is the full banking info size.
  2965. //
  2966. *OutputSize = BankSelect->Size;
  2967. return NO_ERROR;
  2968. } // end VgaGetBankSelectCode()
  2969. VP_STATUS
  2970. VgaValidatorUcharEntry(
  2971. ULONG_PTR Context,
  2972. ULONG Port,
  2973. UCHAR AccessMode,
  2974. PUCHAR Data
  2975. )
  2976. /*++
  2977. Routine Description:
  2978. Entry point into the validator for byte I/O operations.
  2979. The entry point will be called whenever a byte operation was performed
  2980. by a DOS application on one of the specified Video ports. The kernel
  2981. emulator will forward these requests.
  2982. Arguments:
  2983. Context - Context value that is passed to each call made to the validator
  2984. function. This is the value the miniport driver specified in the
  2985. MiniportConfigInfo->EmulatorAccessEntriesContext.
  2986. Port - Port on which the operation is to be performed.
  2987. AccessMode - Determines if it is a read or write operation.
  2988. Data - Pointer to a variable containing the data to be written or a
  2989. variable into which the read data should be stored.
  2990. Return Value:
  2991. NO_ERROR.
  2992. --*/
  2993. {
  2994. PHW_DEVICE_EXTENSION hwDeviceExtension = (PHW_DEVICE_EXTENSION) Context;
  2995. ULONG endEmulation;
  2996. UCHAR temp;
  2997. #if defined(DEBUG_CODE)
  2998. if(TrapRoutineEntered)
  2999. {MY_ASSERT;}
  3000. else
  3001. TrapRoutineEntered = 1;
  3002. #endif
  3003. Port -= VGA_BASE_IO_PORT;
  3004. if (hwDeviceExtension->TrappedValidatorCount) {
  3005. //
  3006. // If we are processing a WRITE instruction, then store it in the
  3007. // playback buffer. If the buffer is full, then play it back right
  3008. // away, end sync reset and reinitialize the buffer with a sync
  3009. // reset instruction.
  3010. //
  3011. // If we have a READ, we must flush the buffer (which has the side
  3012. // effect of starting SyncReset), perform the read operation, stop
  3013. // sync reset, and put back a sync reset instruction in the buffer
  3014. // so we can go on appropriately
  3015. //
  3016. if (AccessMode & EMULATOR_WRITE_ACCESS) {
  3017. //
  3018. // Make sure Bit 3 of the Miscellaneous register is always 0.
  3019. // If it is 1 it could select a non-existent clock, and kill the
  3020. // system
  3021. //
  3022. if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
  3023. *Data &= 0xF7;
  3024. }
  3025. #if defined(DEBUG_CODE)
  3026. if(hwDeviceExtension->TrappedValidatorCount > VGA_MAX_VALIDATOR_DATA - 1)
  3027. {MY_ASSERT;}
  3028. #endif
  3029. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  3030. TrappedValidatorCount].Port = Port;
  3031. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  3032. TrappedValidatorCount].AccessType = VGA_VALIDATOR_UCHAR_ACCESS;
  3033. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  3034. TrappedValidatorCount].Data = *Data;
  3035. hwDeviceExtension->TrappedValidatorCount++;
  3036. //
  3037. // Check to see if this instruction was ending sync reset.
  3038. // If it did, we must flush the buffer and reset the trapped
  3039. // IO ports to the minimal set.
  3040. //
  3041. if ( (Port == SEQ_DATA_PORT) &&
  3042. ((*Data & END_SYNC_RESET_VALUE) == END_SYNC_RESET_VALUE) &&
  3043. (hwDeviceExtension->SequencerAddressValue == IND_SYNC_RESET)) {
  3044. endEmulation = 1;
  3045. } else {
  3046. //
  3047. // If we are accessing the seq address port, keep track of the
  3048. // data value
  3049. //
  3050. if (Port == SEQ_ADDRESS_PORT) {
  3051. hwDeviceExtension->SequencerAddressValue = *Data;
  3052. }
  3053. //
  3054. // If the buffer is not full, then just return right away.
  3055. //
  3056. if (hwDeviceExtension->TrappedValidatorCount <
  3057. VGA_MAX_VALIDATOR_DATA - 1) {
  3058. #if defined(DEBUG_CODE)
  3059. TrapRoutineEntered = 0;
  3060. #endif
  3061. return NO_ERROR;
  3062. }
  3063. endEmulation = 0;
  3064. }
  3065. }
  3066. //
  3067. // We are either in a READ path or a WRITE path that caused a
  3068. // a full buffer. So flush the buffer either way.
  3069. //
  3070. // To do this put an END_SYNC_RESET at the end since we want to make
  3071. // the buffer is ended sync reset ended.
  3072. //
  3073. #if defined(DEBUG_CODE)
  3074. if(hwDeviceExtension->TrappedValidatorCount > VGA_MAX_VALIDATOR_DATA - 1)
  3075. {MY_ASSERT;}
  3076. #endif
  3077. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  3078. TrappedValidatorCount].Port = SEQ_ADDRESS_PORT;
  3079. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  3080. TrappedValidatorCount].AccessType = VGA_VALIDATOR_USHORT_ACCESS;
  3081. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  3082. TrappedValidatorCount].Data = (USHORT) (IND_SYNC_RESET +
  3083. (END_SYNC_RESET_VALUE << 8));
  3084. hwDeviceExtension->TrappedValidatorCount++;
  3085. VideoPortSynchronizeExecution(hwDeviceExtension,
  3086. VpHighPriority,
  3087. (PMINIPORT_SYNCHRONIZE_ROUTINE)
  3088. VgaPlaybackValidatorData,
  3089. hwDeviceExtension);
  3090. //
  3091. // Write back the real value of the sequencer address port.
  3092. //
  3093. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  3094. SEQ_ADDRESS_PORT,
  3095. (UCHAR) hwDeviceExtension->SequencerAddressValue);
  3096. //
  3097. // If we are in a READ path, read the data
  3098. //
  3099. if (AccessMode & EMULATOR_READ_ACCESS) {
  3100. *Data = VideoPortReadPortUchar(hwDeviceExtension->IOAddress + Port);
  3101. endEmulation = 0;
  3102. }
  3103. //
  3104. // If we are ending emulation, reset trapping to the minimal amount
  3105. // and exit.
  3106. //
  3107. if (endEmulation) {
  3108. VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
  3109. NUM_MINIMAL_VGA_VALIDATOR_ACCESS_RANGE,
  3110. MinimalVgaValidatorAccessRange);
  3111. #if defined(DEBUG_CODE)
  3112. TrapRoutineEntered = 0;
  3113. #endif
  3114. return NO_ERROR;
  3115. }
  3116. //
  3117. // For both cases, put back a START_SYNC_RESET in the buffer.
  3118. //
  3119. hwDeviceExtension->TrappedValidatorCount = 1;
  3120. hwDeviceExtension->TrappedValidatorData[0].Port = SEQ_ADDRESS_PORT;
  3121. hwDeviceExtension->TrappedValidatorData[0].AccessType =
  3122. VGA_VALIDATOR_USHORT_ACCESS;
  3123. hwDeviceExtension->TrappedValidatorData[0].Data =
  3124. (ULONG) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8));
  3125. } else {
  3126. //
  3127. // Nothing trapped.
  3128. // Lets check is the IO is trying to do something that would require
  3129. // us to stop trapping
  3130. //
  3131. if (AccessMode & EMULATOR_WRITE_ACCESS) {
  3132. //
  3133. // Make sure Bit 3 of the Miscelaneous register is always 0.
  3134. // If it is 1 it could select a non-existant clock, and kill the
  3135. // system
  3136. //
  3137. if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
  3138. temp = VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
  3139. SEQ_ADDRESS_PORT);
  3140. VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
  3141. SEQ_ADDRESS_PORT),
  3142. (USHORT) (IND_SYNC_RESET +
  3143. (START_SYNC_RESET_VALUE << 8)));
  3144. VideoPortWritePortUchar(hwDeviceExtension->IOAddress + Port,
  3145. (UCHAR) (*Data & 0xF7) );
  3146. VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
  3147. SEQ_ADDRESS_PORT),
  3148. (USHORT) (IND_SYNC_RESET +
  3149. (END_SYNC_RESET_VALUE << 8)));
  3150. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  3151. SEQ_ADDRESS_PORT,
  3152. temp);
  3153. #if defined(DEBUG_CODE)
  3154. TrapRoutineEntered = 0;
  3155. #endif
  3156. return NO_ERROR;
  3157. }
  3158. //
  3159. // If we get an access to the sequencer register, start trapping.
  3160. //
  3161. if ( (Port == SEQ_DATA_PORT) &&
  3162. ((*Data & END_SYNC_RESET_VALUE) != END_SYNC_RESET_VALUE) &&
  3163. (VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
  3164. SEQ_ADDRESS_PORT) == IND_SYNC_RESET)) {
  3165. VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
  3166. NUM_FULL_VGA_VALIDATOR_ACCESS_RANGE,
  3167. FullVgaValidatorAccessRange);
  3168. hwDeviceExtension->TrappedValidatorCount = 1;
  3169. hwDeviceExtension->TrappedValidatorData[0].Port = Port;
  3170. hwDeviceExtension->TrappedValidatorData[0].AccessType =
  3171. VGA_VALIDATOR_UCHAR_ACCESS;
  3172. hwDeviceExtension->TrappedValidatorData[0].Data = *Data;
  3173. //
  3174. // Start keeping track of the state of the sequencer port.
  3175. //
  3176. hwDeviceExtension->SequencerAddressValue = IND_SYNC_RESET;
  3177. } else {
  3178. VideoPortWritePortUchar(hwDeviceExtension->IOAddress + Port,
  3179. *Data);
  3180. }
  3181. } else {
  3182. *Data = VideoPortReadPortUchar(hwDeviceExtension->IOAddress + Port);
  3183. }
  3184. }
  3185. #if defined(DEBUG_CODE)
  3186. TrapRoutineEntered = 0;
  3187. #endif
  3188. return NO_ERROR;
  3189. } // end VgaValidatorUcharEntry()
  3190. VP_STATUS
  3191. VgaValidatorUshortEntry(
  3192. ULONG_PTR Context,
  3193. ULONG Port,
  3194. UCHAR AccessMode,
  3195. PUSHORT Data
  3196. )
  3197. /*++
  3198. Routine Description:
  3199. Entry point into the validator for word I/O operations.
  3200. The entry point will be called whenever a byte operation was performed
  3201. by a DOS application on one of the specified Video ports. The kernel
  3202. emulator will forward these requests.
  3203. Arguments:
  3204. Context - Context value that is passed to each call made to the validator
  3205. function. This is the value the miniport driver specified in the
  3206. MiniportConfigInfo->EmulatorAccessEntriesContext.
  3207. Port - Port on which the operation is to be performed.
  3208. AccessMode - Determines if it is a read or write operation.
  3209. Data - Pointer to a variable containing the data to be written or a
  3210. variable into which the read data should be stored.
  3211. Return Value:
  3212. NO_ERROR.
  3213. --*/
  3214. {
  3215. PHW_DEVICE_EXTENSION hwDeviceExtension = (PHW_DEVICE_EXTENSION) Context;
  3216. ULONG endEmulation;
  3217. UCHAR temp;
  3218. #if defined(DEBUG_CODE)
  3219. if(TrapRoutineEntered)
  3220. {MY_ASSERT;}
  3221. else
  3222. TrapRoutineEntered = 1;
  3223. #endif
  3224. Port -= VGA_BASE_IO_PORT;
  3225. if (hwDeviceExtension->TrappedValidatorCount) {
  3226. //
  3227. // If we are processing a WRITE instruction, then store it in the
  3228. // playback buffer. If the buffer is full, then play it back right
  3229. // away, end sync reset and reinitialize the buffer with a sync
  3230. // reset instruction.
  3231. //
  3232. // If we have a READ, we must flush the buffer (which has the side
  3233. // effect of starting SyncReset), perform the read operation, stop
  3234. // sync reset, and put back a sync reset instruction in the buffer
  3235. // so we can go on appropriately
  3236. //
  3237. if (AccessMode & EMULATOR_WRITE_ACCESS) {
  3238. //
  3239. // Make sure Bit 3 of the Miscellaneous register is always 0.
  3240. // If it is 1 it could select a non-existent clock, and kill the
  3241. // system
  3242. //
  3243. if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
  3244. *Data &= 0xFFF7;
  3245. }
  3246. #if defined(DEBUG_CODE)
  3247. if(hwDeviceExtension->TrappedValidatorCount > VGA_MAX_VALIDATOR_DATA - 1)
  3248. {MY_ASSERT;}
  3249. #endif
  3250. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  3251. TrappedValidatorCount].Port = Port;
  3252. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  3253. TrappedValidatorCount].AccessType = VGA_VALIDATOR_USHORT_ACCESS;
  3254. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  3255. TrappedValidatorCount].Data = *Data;
  3256. hwDeviceExtension->TrappedValidatorCount++;
  3257. //
  3258. // Check to see if this instruction was ending sync reset.
  3259. // If it did, we must flush the buffer and reset the trapped
  3260. // IO ports to the minimal set.
  3261. //
  3262. if (Port == SEQ_ADDRESS_PORT) {
  3263. //
  3264. // If we are accessing the seq address port, keep track of its
  3265. // value
  3266. //
  3267. hwDeviceExtension->SequencerAddressValue = (*Data & 0xFF);
  3268. }
  3269. if ((Port == SEQ_ADDRESS_PORT) &&
  3270. ( ((*Data >> 8) & END_SYNC_RESET_VALUE) ==
  3271. END_SYNC_RESET_VALUE) &&
  3272. (hwDeviceExtension->SequencerAddressValue == IND_SYNC_RESET)) {
  3273. endEmulation = 1;
  3274. } else {
  3275. //
  3276. // If the buffer is not full, then just return right away.
  3277. //
  3278. if (hwDeviceExtension->TrappedValidatorCount <
  3279. VGA_MAX_VALIDATOR_DATA - 1) {
  3280. #if defined(DEBUG_CODE)
  3281. TrapRoutineEntered = 0;
  3282. #endif
  3283. return NO_ERROR;
  3284. }
  3285. endEmulation = 0;
  3286. }
  3287. }
  3288. //
  3289. // We are either in a READ path or a WRITE path that caused a
  3290. // a full buffer. So flush the buffer either way.
  3291. //
  3292. // To do this put an END_SYNC_RESET at the end since we want to make
  3293. // the buffer is ended sync reset ended.
  3294. //
  3295. #if defined(DEBUG_CODE)
  3296. if(hwDeviceExtension->TrappedValidatorCount > VGA_MAX_VALIDATOR_DATA - 1)
  3297. {MY_ASSERT;}
  3298. #endif
  3299. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  3300. TrappedValidatorCount].Port = SEQ_ADDRESS_PORT;
  3301. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  3302. TrappedValidatorCount].AccessType = VGA_VALIDATOR_USHORT_ACCESS;
  3303. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  3304. TrappedValidatorCount].Data = (USHORT) (IND_SYNC_RESET +
  3305. (END_SYNC_RESET_VALUE << 8));
  3306. hwDeviceExtension->TrappedValidatorCount++;
  3307. VideoPortSynchronizeExecution(hwDeviceExtension,
  3308. VpHighPriority,
  3309. (PMINIPORT_SYNCHRONIZE_ROUTINE)
  3310. VgaPlaybackValidatorData,
  3311. hwDeviceExtension);
  3312. //
  3313. // Write back the real value of the sequencer address port.
  3314. //
  3315. VideoPortWritePortUchar((PUCHAR) (hwDeviceExtension->IOAddress +
  3316. SEQ_ADDRESS_PORT),
  3317. (UCHAR) hwDeviceExtension->SequencerAddressValue);
  3318. //
  3319. // If we are in a READ path, read the data
  3320. //
  3321. if (AccessMode & EMULATOR_READ_ACCESS) {
  3322. *Data = VideoPortReadPortUshort((PUSHORT)(hwDeviceExtension->IOAddress
  3323. + Port));
  3324. endEmulation = 0;
  3325. }
  3326. //
  3327. // If we are ending emulation, reset trapping to the minimal amount
  3328. // and exit.
  3329. //
  3330. if (endEmulation) {
  3331. VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
  3332. NUM_MINIMAL_VGA_VALIDATOR_ACCESS_RANGE,
  3333. MinimalVgaValidatorAccessRange);
  3334. #if defined(DEBUG_CODE)
  3335. TrapRoutineEntered = 0;
  3336. #endif
  3337. return NO_ERROR;
  3338. }
  3339. //
  3340. // For both cases, put back a START_SYNC_RESET in the buffer.
  3341. //
  3342. hwDeviceExtension->TrappedValidatorCount = 1;
  3343. hwDeviceExtension->TrappedValidatorData[0].Port = SEQ_ADDRESS_PORT;
  3344. hwDeviceExtension->TrappedValidatorData[0].AccessType =
  3345. VGA_VALIDATOR_USHORT_ACCESS;
  3346. hwDeviceExtension->TrappedValidatorData[0].Data =
  3347. (ULONG) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8));
  3348. } else {
  3349. //
  3350. // Nothing trapped.
  3351. // Lets check is the IO is trying to do something that would require
  3352. // us to stop trapping
  3353. //
  3354. if (AccessMode & EMULATOR_WRITE_ACCESS) {
  3355. //
  3356. // Make sure Bit 3 of the Miscelaneous register is always 0.
  3357. // If it is 1 it could select a non-existant clock, and kill the
  3358. // system
  3359. //
  3360. if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
  3361. temp = VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
  3362. SEQ_ADDRESS_PORT);
  3363. VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
  3364. SEQ_ADDRESS_PORT),
  3365. (USHORT) (IND_SYNC_RESET +
  3366. (START_SYNC_RESET_VALUE << 8)));
  3367. VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
  3368. (ULONG)Port),
  3369. (USHORT) (*Data & 0xFFF7) );
  3370. VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
  3371. SEQ_ADDRESS_PORT),
  3372. (USHORT) (IND_SYNC_RESET +
  3373. (END_SYNC_RESET_VALUE << 8)));
  3374. VideoPortWritePortUchar(hwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
  3375. temp);
  3376. #if defined(DEBUG_CODE)
  3377. TrapRoutineEntered = 0;
  3378. #endif
  3379. return NO_ERROR;
  3380. }
  3381. if ( (Port == SEQ_ADDRESS_PORT) &&
  3382. (((*Data>> 8) & END_SYNC_RESET_VALUE) != END_SYNC_RESET_VALUE) &&
  3383. ((*Data & 0xFF) == IND_SYNC_RESET)) {
  3384. VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
  3385. NUM_FULL_VGA_VALIDATOR_ACCESS_RANGE,
  3386. FullVgaValidatorAccessRange);
  3387. hwDeviceExtension->TrappedValidatorCount = 1;
  3388. hwDeviceExtension->TrappedValidatorData[0].Port = Port;
  3389. hwDeviceExtension->TrappedValidatorData[0].AccessType =
  3390. VGA_VALIDATOR_USHORT_ACCESS;
  3391. hwDeviceExtension->TrappedValidatorData[0].Data = *Data;
  3392. //
  3393. // Start keeping track of the state of the sequencer port.
  3394. //
  3395. hwDeviceExtension->SequencerAddressValue = IND_SYNC_RESET;
  3396. } else {
  3397. VideoPortWritePortUshort((PUSHORT)(hwDeviceExtension->IOAddress +
  3398. Port),
  3399. *Data);
  3400. }
  3401. } else {
  3402. *Data = VideoPortReadPortUshort((PUSHORT)(hwDeviceExtension->IOAddress +
  3403. Port));
  3404. }
  3405. }
  3406. #if defined(DEBUG_CODE)
  3407. TrapRoutineEntered = 0;
  3408. #endif
  3409. return NO_ERROR;
  3410. } // end VgaValidatorUshortEntry()
  3411. VP_STATUS
  3412. VgaValidatorUlongEntry(
  3413. ULONG_PTR Context,
  3414. ULONG Port,
  3415. UCHAR AccessMode,
  3416. PULONG Data
  3417. )
  3418. /*++
  3419. Routine Description:
  3420. Entry point into the validator for dword I/O operations.
  3421. The entry point will be called whenever a byte operation was performed
  3422. by a DOS application on one of the specified Video ports. The kernel
  3423. emulator will forward these requests.
  3424. Arguments:
  3425. Context - Context value that is passed to each call made to the validator
  3426. function. This is the value the miniport driver specified in the
  3427. MiniportConfigInfo->EmulatorAccessEntriesContext.
  3428. Port - Port on which the operation is to be performed.
  3429. AccessMode - Determines if it is a read or write operation.
  3430. Data - Pointer to a variable containing the data to be written or a
  3431. variable into which the read data should be stored.
  3432. Return Value:
  3433. NO_ERROR.
  3434. --*/
  3435. {
  3436. PHW_DEVICE_EXTENSION hwDeviceExtension = (PHW_DEVICE_EXTENSION) Context;
  3437. ULONG endEmulation;
  3438. UCHAR temp;
  3439. #if defined(DEBUG_CODE)
  3440. if(TrapRoutineEntered)
  3441. {MY_ASSERT;}
  3442. else
  3443. TrapRoutineEntered = 1;
  3444. #endif
  3445. Port -= VGA_BASE_IO_PORT;
  3446. if (hwDeviceExtension->TrappedValidatorCount) {
  3447. //
  3448. // If we are processing a WRITE instruction, then store it in the
  3449. // playback buffer. If the buffer is full, then play it back right
  3450. // away, end sync reset and reinitialize the buffer with a sync
  3451. // reset instruction.
  3452. //
  3453. // If we have a READ, we must flush the buffer (which has the side
  3454. // effect of starting SyncReset), perform the read operation, stop
  3455. // sync reset, and put back a sync reset instruction in the buffer
  3456. // so we can go on appropriately
  3457. //
  3458. if (AccessMode & EMULATOR_WRITE_ACCESS) {
  3459. //
  3460. // Make sure Bit 3 of the Miscellaneous register is always 0.
  3461. // If it is 1 it could select a non-existent clock, and kill the
  3462. // system
  3463. //
  3464. if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
  3465. *Data &= 0xFFFFFFF7;
  3466. }
  3467. #if defined(DEBUG_CODE)
  3468. if(hwDeviceExtension->TrappedValidatorCount > VGA_MAX_VALIDATOR_DATA - 1)
  3469. {MY_ASSERT;}
  3470. #endif
  3471. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  3472. TrappedValidatorCount].Port = Port;
  3473. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  3474. TrappedValidatorCount].AccessType = VGA_VALIDATOR_ULONG_ACCESS;
  3475. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  3476. TrappedValidatorCount].Data = *Data;
  3477. hwDeviceExtension->TrappedValidatorCount++;
  3478. //
  3479. // Check to see if this instruction was ending sync reset.
  3480. // If it did, we must flush the buffer and reset the trapped
  3481. // IO ports to the minimal set.
  3482. //
  3483. if (Port == SEQ_ADDRESS_PORT) {
  3484. //
  3485. // If we are accessing the seq address port, keep track of its
  3486. // value
  3487. //
  3488. hwDeviceExtension->SequencerAddressValue = (*Data & 0xFF);
  3489. }
  3490. if ((Port == SEQ_ADDRESS_PORT) &&
  3491. ( ((*Data >> 8) & END_SYNC_RESET_VALUE) ==
  3492. END_SYNC_RESET_VALUE) &&
  3493. (hwDeviceExtension->SequencerAddressValue == IND_SYNC_RESET)) {
  3494. endEmulation = 1;
  3495. } else {
  3496. //
  3497. // If the buffer is not full, then just return right away.
  3498. //
  3499. if (hwDeviceExtension->TrappedValidatorCount <
  3500. VGA_MAX_VALIDATOR_DATA - 1) {
  3501. #if defined(DEBUG_CODE)
  3502. TrapRoutineEntered = 0;
  3503. #endif
  3504. return NO_ERROR;
  3505. }
  3506. endEmulation = 0;
  3507. }
  3508. }
  3509. //
  3510. // We are either in a READ path or a WRITE path that caused a
  3511. // a full buffer. So flush the buffer either way.
  3512. //
  3513. // To do this put an END_SYNC_RESET at the end since we want to make
  3514. // the buffer is ended sync reset ended.
  3515. //
  3516. #if defined(DEBUG_CODE)
  3517. if(hwDeviceExtension->TrappedValidatorCount > VGA_MAX_VALIDATOR_DATA - 1)
  3518. {MY_ASSERT;}
  3519. #endif
  3520. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  3521. TrappedValidatorCount].Port = SEQ_ADDRESS_PORT;
  3522. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  3523. TrappedValidatorCount].AccessType = VGA_VALIDATOR_USHORT_ACCESS;
  3524. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  3525. TrappedValidatorCount].Data = (USHORT) (IND_SYNC_RESET +
  3526. (END_SYNC_RESET_VALUE << 8));
  3527. hwDeviceExtension->TrappedValidatorCount++;
  3528. VideoPortSynchronizeExecution(hwDeviceExtension,
  3529. VpHighPriority,
  3530. (PMINIPORT_SYNCHRONIZE_ROUTINE)
  3531. VgaPlaybackValidatorData,
  3532. hwDeviceExtension);
  3533. //
  3534. // Write back the real value of the sequencer address port.
  3535. //
  3536. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  3537. SEQ_ADDRESS_PORT,
  3538. (UCHAR) hwDeviceExtension->SequencerAddressValue);
  3539. //
  3540. // If we are in a READ path, read the data
  3541. //
  3542. if (AccessMode & EMULATOR_READ_ACCESS) {
  3543. *Data = VideoPortReadPortUlong((PULONG) (hwDeviceExtension->IOAddress +
  3544. Port));
  3545. endEmulation = 0;
  3546. }
  3547. //
  3548. // If we are ending emulation, reset trapping to the minimal amount
  3549. // and exit.
  3550. //
  3551. if (endEmulation) {
  3552. VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
  3553. NUM_MINIMAL_VGA_VALIDATOR_ACCESS_RANGE,
  3554. MinimalVgaValidatorAccessRange);
  3555. #if defined(DEBUG_CODE)
  3556. TrapRoutineEntered = 0;
  3557. #endif
  3558. return NO_ERROR;
  3559. }
  3560. //
  3561. // For both cases, put back a START_SYNC_RESET in the buffer.
  3562. //
  3563. hwDeviceExtension->TrappedValidatorCount = 1;
  3564. hwDeviceExtension->TrappedValidatorData[0].Port = SEQ_ADDRESS_PORT;
  3565. hwDeviceExtension->TrappedValidatorData[0].AccessType =
  3566. VGA_VALIDATOR_USHORT_ACCESS;
  3567. hwDeviceExtension->TrappedValidatorData[0].Data =
  3568. (ULONG) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8));
  3569. } else {
  3570. //
  3571. // Nothing trapped.
  3572. // Lets check is the IO is trying to do something that would require
  3573. // us to stop trapping
  3574. //
  3575. if (AccessMode & EMULATOR_WRITE_ACCESS) {
  3576. //
  3577. // Make sure Bit 3 of the Miscelaneous register is always 0.
  3578. // If it is 1 it could select a non-existant clock, and kill the
  3579. // system
  3580. //
  3581. if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
  3582. temp = VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
  3583. SEQ_ADDRESS_PORT);
  3584. VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
  3585. SEQ_ADDRESS_PORT),
  3586. (USHORT) (IND_SYNC_RESET +
  3587. (START_SYNC_RESET_VALUE << 8)));
  3588. VideoPortWritePortUlong((PULONG) (hwDeviceExtension->IOAddress +
  3589. Port),
  3590. (ULONG) (*Data & 0xFFFFFFF7) );
  3591. VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
  3592. SEQ_ADDRESS_PORT),
  3593. (USHORT) (IND_SYNC_RESET +
  3594. (END_SYNC_RESET_VALUE << 8)));
  3595. VideoPortWritePortUchar(hwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
  3596. temp);
  3597. #if defined(DEBUG_CODE)
  3598. TrapRoutineEntered = 0;
  3599. #endif
  3600. return NO_ERROR;
  3601. }
  3602. if ( (Port == SEQ_ADDRESS_PORT) &&
  3603. (((*Data>> 8) & END_SYNC_RESET_VALUE) != END_SYNC_RESET_VALUE) &&
  3604. ((*Data & 0xFF) == IND_SYNC_RESET)) {
  3605. VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
  3606. NUM_FULL_VGA_VALIDATOR_ACCESS_RANGE,
  3607. FullVgaValidatorAccessRange);
  3608. hwDeviceExtension->TrappedValidatorCount = 1;
  3609. hwDeviceExtension->TrappedValidatorData[0].Port = Port;
  3610. hwDeviceExtension->TrappedValidatorData[0].AccessType =
  3611. VGA_VALIDATOR_ULONG_ACCESS;
  3612. hwDeviceExtension->TrappedValidatorData[0].Data = *Data;
  3613. //
  3614. // Start keeping track of the state of the sequencer port.
  3615. //
  3616. hwDeviceExtension->SequencerAddressValue = IND_SYNC_RESET;
  3617. } else {
  3618. VideoPortWritePortUlong((PULONG) (hwDeviceExtension->IOAddress +
  3619. Port),
  3620. *Data);
  3621. }
  3622. } else {
  3623. *Data = VideoPortReadPortUlong((PULONG) (hwDeviceExtension->IOAddress +
  3624. Port));
  3625. }
  3626. }
  3627. #if defined(DEBUG_CODE)
  3628. TrapRoutineEntered = 0;
  3629. #endif
  3630. return NO_ERROR;
  3631. } // end VgaValidatorUlongEntry()
  3632. BOOLEAN
  3633. VgaPlaybackValidatorData(
  3634. PVOID Context
  3635. )
  3636. /*++
  3637. Routine Description:
  3638. Performs all the DOS apps IO port accesses that were trapped by the
  3639. validator. Only IO accesses that can be processed are WRITEs
  3640. The number of outstanding IO access in deviceExtension is set to
  3641. zero as a side effect.
  3642. This function must be called via a call to VideoPortSynchronizeRoutine.
  3643. Arguments:
  3644. Context - Context parameter passed to the synchronized routine.
  3645. Must be a pointer to the miniport driver's device extension.
  3646. Return Value:
  3647. TRUE.
  3648. --*/
  3649. {
  3650. PHW_DEVICE_EXTENSION hwDeviceExtension = Context;
  3651. ULONG_PTR ioBaseAddress = (ULONG_PTR) hwDeviceExtension->IOAddress;
  3652. ULONG i;
  3653. PVGA_VALIDATOR_DATA validatorData = hwDeviceExtension->TrappedValidatorData;
  3654. //
  3655. // Loop through the array of data and do instructions one by one.
  3656. //
  3657. for (i = 0; i < hwDeviceExtension->TrappedValidatorCount;
  3658. i++, validatorData++) {
  3659. //
  3660. // Calculate base address first
  3661. //
  3662. ioBaseAddress = (ULONG_PTR)hwDeviceExtension->IOAddress +
  3663. validatorData->Port;
  3664. //
  3665. // This is a write operation. We will automatically stop when the
  3666. // buffer is empty.
  3667. //
  3668. switch (validatorData->AccessType) {
  3669. case VGA_VALIDATOR_UCHAR_ACCESS :
  3670. VideoPortWritePortUchar((PUCHAR)ioBaseAddress,
  3671. (UCHAR) validatorData->Data);
  3672. break;
  3673. case VGA_VALIDATOR_USHORT_ACCESS :
  3674. VideoPortWritePortUshort((PUSHORT)ioBaseAddress,
  3675. (USHORT) validatorData->Data);
  3676. break;
  3677. case VGA_VALIDATOR_ULONG_ACCESS :
  3678. VideoPortWritePortUlong((PULONG)ioBaseAddress,
  3679. (ULONG) validatorData->Data);
  3680. break;
  3681. default:
  3682. VideoDebugPrint((0, "InvalidValidatorAccessType\n" ));
  3683. }
  3684. }
  3685. hwDeviceExtension->TrappedValidatorCount = 0;
  3686. return TRUE;
  3687. } // end VgaPlaybackValidatorData()
  3688. VP_STATUS
  3689. VgaSetBankPosition(
  3690. PHW_DEVICE_EXTENSION hwDeviceExtension,
  3691. PBANK_POSITION BankPosition
  3692. )
  3693. {
  3694. PVIDEO_PORT_INT10_INTERFACE Int10 = &hwDeviceExtension->Int10;
  3695. INT10_BIOS_ARGUMENTS BiosArguments;
  3696. VP_STATUS status;
  3697. if(!Int10->Size) {
  3698. return ERROR_INVALID_FUNCTION;
  3699. }
  3700. BiosArguments.Eax = 0x4f05;
  3701. BiosArguments.Ebx = 0;
  3702. BiosArguments.Edx = BankPosition->WriteBankPosition;
  3703. status = Int10->Int10CallBios(Int10->Context, &BiosArguments);
  3704. if ((status != NO_ERROR) ||
  3705. !VESA_SUCCESS(BiosArguments.Eax)) {
  3706. //
  3707. // This could fail if the video hardware is still in linear
  3708. // mode. This could also fail if the bios is buggy. We don't
  3709. // want to return a failure code in either case. (Please read
  3710. // the code around "BankIoctlSupported" in display driver for
  3711. // more details).
  3712. //
  3713. }
  3714. BiosArguments.Eax = 0x4f05;
  3715. BiosArguments.Ebx = 1;
  3716. BiosArguments.Edx = BankPosition->ReadBankPosition;
  3717. status = Int10->Int10CallBios(Int10->Context, &BiosArguments);
  3718. if ((status != NO_ERROR) ||
  3719. !VESA_SUCCESS(BiosArguments.Eax)) {
  3720. //
  3721. // See comment above
  3722. //
  3723. }
  3724. return NO_ERROR;
  3725. }
  3726. #if defined(PLUG_AND_PLAY)
  3727. VP_STATUS
  3728. VgaGetPowerState(
  3729. PHW_DEVICE_EXTENSION HwDeviceExtension,
  3730. ULONG HwDeviceId,
  3731. PVIDEO_POWER_MANAGEMENT VideoPowerManagement
  3732. )
  3733. /*++
  3734. Routine Description:
  3735. Returns power state information.
  3736. Arguments:
  3737. HwDeviceExtension - Pointer to our hardware device extension structure.
  3738. HwDeviceId - Private unique 32 bit ID identifing the device.
  3739. VideoPowerControl - Points to a VIDEO_POWER_MANAGEMENT structure that
  3740. specifies the power state for which support is
  3741. being queried.
  3742. Return Value:
  3743. VP_STATUS value (NO_ERROR or error value)
  3744. --*/
  3745. {
  3746. //
  3747. // We only support power setting for the monitor. Make sure the
  3748. // HwDeviceId matches one the the monitors we could report.
  3749. //
  3750. if (HwDeviceId == VGA_MONITOR_ID) {
  3751. ULONG MonitorPowerCapabilities = HwDeviceExtension->MonitorPowerCapabilities;
  3752. //
  3753. // We are querying the power support for the monitor.
  3754. //
  3755. if ((VideoPowerManagement->PowerState == VideoPowerOn) ||
  3756. (VideoPowerManagement->PowerState == VideoPowerHibernate) ||
  3757. (VideoPowerManagement->PowerState == VideoPowerShutdown)) {
  3758. return NO_ERROR;
  3759. }
  3760. switch (VideoPowerManagement->PowerState) {
  3761. case VideoPowerStandBy:
  3762. return (MonitorPowerCapabilities & VESA_POWER_STANDBY) ?
  3763. NO_ERROR : ERROR_INVALID_FUNCTION;
  3764. case VideoPowerSuspend:
  3765. return (MonitorPowerCapabilities & VESA_POWER_SUSPEND) ?
  3766. NO_ERROR : ERROR_INVALID_FUNCTION;
  3767. case VideoPowerOff:
  3768. return (MonitorPowerCapabilities & VESA_POWER_OFF) ?
  3769. NO_ERROR : ERROR_INVALID_FUNCTION;
  3770. default:
  3771. break;
  3772. }
  3773. VideoDebugPrint((1, "This device does not support Power Management.\n"));
  3774. return ERROR_INVALID_FUNCTION;
  3775. } else if (HwDeviceId == DISPLAY_ADAPTER_HW_ID) {
  3776. //
  3777. // We are querying power support for the graphics card.
  3778. //
  3779. switch (VideoPowerManagement->PowerState) {
  3780. case VideoPowerOn:
  3781. case VideoPowerHibernate:
  3782. case VideoPowerShutdown:
  3783. return NO_ERROR;
  3784. case VideoPowerStandBy:
  3785. case VideoPowerOff:
  3786. case VideoPowerSuspend:
  3787. //
  3788. // Indicate that we can't do VideoPowerOff, because
  3789. // we have no way of coming back when power is re-applied
  3790. // to the card.
  3791. //
  3792. return ERROR_INVALID_FUNCTION;
  3793. default:
  3794. ASSERT(FALSE);
  3795. return ERROR_INVALID_PARAMETER;
  3796. }
  3797. } else {
  3798. VideoDebugPrint((1, "Unknown HwDeviceId"));
  3799. ASSERT(FALSE);
  3800. return ERROR_INVALID_PARAMETER;
  3801. }
  3802. }
  3803. VP_STATUS
  3804. VgaSetPowerState(
  3805. PHW_DEVICE_EXTENSION HwDeviceExtension,
  3806. ULONG HwDeviceId,
  3807. PVIDEO_POWER_MANAGEMENT VideoPowerManagement
  3808. )
  3809. /*++
  3810. Routine Description:
  3811. Set the power state for a given device.
  3812. Arguments:
  3813. HwDeviceExtension - Pointer to our hardware device extension structure.
  3814. HwDeviceId - Private unique 32 bit ID identifing the device.
  3815. VideoPowerControl - Points to a VIDEO_POWER_MANAGEMENT structure that
  3816. specifies the power state to be set.
  3817. Return Value:
  3818. VP_STATUS value (NO_ERROR, if all's well)
  3819. --*/
  3820. {
  3821. //
  3822. // Make sure we recognize the device.
  3823. //
  3824. if (HwDeviceId == VGA_MONITOR_ID) {
  3825. VIDEO_X86_BIOS_ARGUMENTS biosArguments;
  3826. VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  3827. biosArguments.Eax = VESA_POWER_FUNCTION;
  3828. biosArguments.Ebx = VESA_SET_POWER_FUNC;
  3829. switch (VideoPowerManagement->PowerState) {
  3830. case VideoPowerOn:
  3831. case VideoPowerHibernate:
  3832. biosArguments.Ebx |= VESA_POWER_ON;
  3833. break;
  3834. case VideoPowerStandBy:
  3835. biosArguments.Ebx |= VESA_POWER_STANDBY;
  3836. break;
  3837. case VideoPowerSuspend:
  3838. biosArguments.Ebx |= VESA_POWER_SUSPEND;
  3839. break;
  3840. case VideoPowerOff:
  3841. biosArguments.Ebx |= VESA_POWER_OFF;
  3842. break;
  3843. case VideoPowerShutdown:
  3844. return NO_ERROR;
  3845. default:
  3846. VideoDebugPrint((1, "Unknown power state.\n"));
  3847. ASSERT(FALSE);
  3848. return ERROR_INVALID_PARAMETER;
  3849. }
  3850. VideoPortInt10(HwDeviceExtension, &biosArguments);
  3851. //
  3852. // track the current monitor power state
  3853. //
  3854. HwDeviceExtension->MonitorPowerState = VideoPowerManagement->PowerState;
  3855. return NO_ERROR;
  3856. } else if (HwDeviceId == DISPLAY_ADAPTER_HW_ID) {
  3857. switch (VideoPowerManagement->PowerState) {
  3858. case VideoPowerOn:
  3859. case VideoPowerHibernate:
  3860. case VideoPowerShutdown:
  3861. return NO_ERROR;
  3862. case VideoPowerStandBy:
  3863. case VideoPowerSuspend:
  3864. case VideoPowerOff:
  3865. return ERROR_INVALID_PARAMETER;
  3866. default:
  3867. //
  3868. // We indicated in S3GetPowerState that we couldn't
  3869. // do VideoPowerOff. So we should not get a call to
  3870. // do it here.
  3871. //
  3872. ASSERT(FALSE);
  3873. return ERROR_INVALID_PARAMETER;
  3874. }
  3875. } else {
  3876. VideoDebugPrint((1, "Unknown HwDeviceId"));
  3877. ASSERT(FALSE);
  3878. return ERROR_INVALID_PARAMETER;
  3879. }
  3880. }
  3881. ULONG
  3882. VgaGetChildDescriptor(
  3883. PVOID HwDeviceExtension,
  3884. PVIDEO_CHILD_ENUM_INFO ChildEnumInfo,
  3885. PVIDEO_CHILD_TYPE pChildType,
  3886. PVOID pChildDescriptor,
  3887. PULONG pUId,
  3888. PULONG pUnused
  3889. )
  3890. /*++
  3891. Routine Description:
  3892. Enumerate all child devices controlled by the Permedia 2 chip.
  3893. This includes DDC monitors attached to the board, as well as other devices
  3894. which may be connected to a proprietary bus.
  3895. Arguments:
  3896. HwDeviceExtension -
  3897. Pointer to our hardware device extension structure.
  3898. ChildEnumInfo -
  3899. Information about the device that should be enumerated.
  3900. pChildType -
  3901. Type of child we are enumerating - monitor, I2C ...
  3902. pChildDescriptor -
  3903. Identification structure of the device (EDID, string)
  3904. pUId -
  3905. Private unique 32 bit ID to passed back to the miniport
  3906. pUnused -
  3907. Do not use
  3908. Return Value:
  3909. ERROR_NO_MORE_DEVICES -
  3910. if no more child devices exist.
  3911. ERROR_INVALID_NAME -
  3912. The miniport could not enumerate the child device identified in
  3913. ChildEnumInfo but does have more devices to be enumerated.
  3914. ERROR_MORE_DATA -
  3915. There are more devices to be enumerated.
  3916. Note:
  3917. In the event of a failure return, none of the fields are valid except for
  3918. the return value and the pMoreChildren field.
  3919. --*/
  3920. {
  3921. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  3922. switch(ChildEnumInfo->ChildIndex)
  3923. {
  3924. case 0:
  3925. //
  3926. // Case 0 is used to enumerate devices found by the ACPI bios.
  3927. // We don't support these, so return appropriate error.
  3928. //
  3929. return ERROR_NO_MORE_DEVICES;
  3930. case 1:
  3931. //
  3932. // Enumerate the monitor
  3933. //
  3934. *pChildType = Monitor;
  3935. //
  3936. // Try to read the EDID from the monitor using the video BIOS
  3937. //
  3938. VgaGetMonitorEdid(hwDeviceExtension,
  3939. pChildDescriptor,
  3940. ChildEnumInfo->ChildDescriptorSize);
  3941. *pUId = VGA_MONITOR_ID;
  3942. break;
  3943. default:
  3944. return ERROR_NO_MORE_DEVICES;
  3945. }
  3946. return ERROR_MORE_DATA;
  3947. }
  3948. VOID
  3949. VgaGetMonitorEdid(
  3950. PHW_DEVICE_EXTENSION hwDeviceExtension,
  3951. PUCHAR Buffer,
  3952. ULONG Size
  3953. )
  3954. /*++
  3955. --*/
  3956. {
  3957. PVIDEO_PORT_INT10_INTERFACE pInt10;
  3958. INT10_BIOS_ARGUMENTS BiosArguments;
  3959. VP_STATUS status;
  3960. USHORT VdmSeg;
  3961. USHORT VdmOff;
  3962. ULONG Length = 0x1000;
  3963. pInt10 = &hwDeviceExtension->Int10;
  3964. //
  3965. // Some video bios's get stuck in an infinite loop if we try to
  3966. // read the edid while the monitor is powered off. If the
  3967. // monitor is off, we'll return the most recently retrieved EDID
  3968. // value instead of trying to retrieve it again.
  3969. //
  3970. if ((hwDeviceExtension->MonitorPowerState == VideoPowerOn) &&
  3971. !(hwDeviceExtension->AlwaysUseCachedEdid)) {
  3972. //
  3973. // Zero initialize the buffer
  3974. //
  3975. memset(Buffer, 0, Size);
  3976. if (pInt10->Size) {
  3977. if (pInt10->Int10AllocateBuffer(pInt10->Context,
  3978. &VdmSeg,
  3979. &VdmOff,
  3980. &Length) != NO_ERROR) {
  3981. return;
  3982. }
  3983. //
  3984. // Call VESA BIOS to get read EDID
  3985. //
  3986. BiosArguments.Eax = 0x4f15;
  3987. BiosArguments.Ebx = 1;
  3988. BiosArguments.Ecx = 0;
  3989. BiosArguments.Edx = 0;
  3990. BiosArguments.SegEs = VdmSeg;
  3991. BiosArguments.Edi = VdmOff;
  3992. status = pInt10->Int10CallBios(pInt10->Context, &BiosArguments);
  3993. //
  3994. // Check to see if DDC is supported
  3995. //
  3996. if (status == NO_ERROR && VESA_SUCCESS(BiosArguments.Eax)) {
  3997. //
  3998. // We retrieved a valid EDID block. Copy it into
  3999. // our buffer.
  4000. //
  4001. if (pInt10->Int10ReadMemory(pInt10->Context,
  4002. VdmSeg,
  4003. VdmOff,
  4004. Buffer,
  4005. min(Size, EDID_BUFFER_SIZE)) == NO_ERROR) {
  4006. //
  4007. // copy the edid into our edid cache
  4008. //
  4009. memcpy(hwDeviceExtension->EdidBuffer, Buffer, EDID_BUFFER_SIZE);
  4010. }
  4011. }
  4012. pInt10->Int10FreeBuffer(pInt10->Context,
  4013. VdmSeg,
  4014. VdmOff);
  4015. }
  4016. } else {
  4017. //
  4018. // return the cached edid. If we haven't cached an edid yet, the
  4019. // zero initialized buffer will be copied.
  4020. //
  4021. memcpy(Buffer, hwDeviceExtension->EdidBuffer, EDID_BUFFER_SIZE);
  4022. }
  4023. }
  4024. #define S3_VENDORID 0x5333
  4025. #define SAV4_DEVICEID 0x8a22
  4026. #define NV3_VENDORID 0x12D2
  4027. #define NV3_DEVICEID 0x0018
  4028. #define NV3_SUBVENDORID 0x8086
  4029. #define NV3_SUBSYSTEMID 0x5243
  4030. VOID
  4031. VgaInitializeSpecialCase(
  4032. PHW_DEVICE_EXTENSION hwDeviceExtension
  4033. )
  4034. {
  4035. PCI_COMMON_CONFIG ConfigSpace;
  4036. hwDeviceExtension->AlwaysUseCachedEdid = FALSE;
  4037. if (PCI_COMMON_HDR_LENGTH ==
  4038. VideoPortGetBusData(hwDeviceExtension,
  4039. PCIConfiguration,
  4040. 0,
  4041. &ConfigSpace,
  4042. 0,
  4043. PCI_COMMON_HDR_LENGTH)) {
  4044. hwDeviceExtension->DeviceID = ConfigSpace.DeviceID;
  4045. hwDeviceExtension->VendorID = ConfigSpace.VendorID;
  4046. if(hwDeviceExtension->VendorID == S3_VENDORID &&
  4047. hwDeviceExtension->DeviceID == SAV4_DEVICEID) {
  4048. //
  4049. // System hard hangs if we retrieve EDID through SAV4's bios while
  4050. // GDI or driver is accessing framebuffer. So we only read EDID once
  4051. // at HwInitialize time.
  4052. //
  4053. VgaGetMonitorEdid (hwDeviceExtension, hwDeviceExtension->EdidBuffer, EDID_BUFFER_SIZE);
  4054. hwDeviceExtension->AlwaysUseCachedEdid = TRUE;
  4055. }
  4056. if(hwDeviceExtension->VendorID == NV3_VENDORID &&
  4057. hwDeviceExtension->DeviceID == NV3_DEVICEID &&
  4058. ConfigSpace.u.type0.SubVendorID == NV3_SUBVENDORID &&
  4059. ConfigSpace.u.type0.SubSystemID == NV3_SUBSYSTEMID) {
  4060. //
  4061. // The video bios of this device spins while we try to retrive
  4062. // EDID with VESA function 0x4f15. We'll avoid to call this VESA
  4063. // function for this device.
  4064. //
  4065. hwDeviceExtension->AlwaysUseCachedEdid = TRUE;
  4066. }
  4067. }
  4068. }
  4069. #endif