Source code of Windows XP (NT5)
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.

6334 lines
179 KiB

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