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.

7447 lines
208 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. et4000.c
  5. Abstract:
  6. This is the miniport driver for the Tseng 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 "et4000.h"
  18. extern VOID vInitDebugValidators(
  19. PHW_DEVICE_EXTENSION phwDeviceExtension,
  20. EMULATOR_ACCESS_ENTRY *pVgaEmulatorAccessEntries,
  21. ULONG nEmulatorAccessEntries
  22. );
  23. //
  24. // Function declarations
  25. //
  26. // Functions that start with 'VGA' are entry points for the OS port driver.
  27. //
  28. VP_STATUS
  29. VgaFindAdapter(
  30. PVOID HwDeviceExtension,
  31. PVOID HwContext,
  32. PWSTR ArgumentString,
  33. PVIDEO_PORT_CONFIG_INFO ConfigInfo,
  34. PUCHAR Again
  35. );
  36. BOOLEAN
  37. VgaInitialize(
  38. PVOID HwDeviceExtension
  39. );
  40. BOOLEAN
  41. VgaStartIO(
  42. PVOID HwDeviceExtension,
  43. PVIDEO_REQUEST_PACKET RequestPacket
  44. );
  45. //
  46. // Private function prototypes.
  47. //
  48. VP_STATUS
  49. VgaQueryAvailableModes(
  50. PHW_DEVICE_EXTENSION HwDeviceExtension,
  51. PVIDEO_MODE_INFORMATION ModeInformation,
  52. ULONG ModeInformationSize,
  53. PULONG OutputSize
  54. );
  55. VP_STATUS
  56. VgaQueryNumberOfAvailableModes(
  57. PHW_DEVICE_EXTENSION HwDeviceExtension,
  58. PVIDEO_NUM_MODES NumModes,
  59. ULONG NumModesSize,
  60. PULONG OutputSize
  61. );
  62. VP_STATUS
  63. VgaQueryCurrentMode(
  64. PHW_DEVICE_EXTENSION HwDeviceExtension,
  65. PVIDEO_MODE_INFORMATION ModeInformation,
  66. ULONG ModeInformationSize,
  67. PULONG OutputSize
  68. );
  69. VP_STATUS
  70. VgaSetMode(
  71. PHW_DEVICE_EXTENSION HwDeviceExtension,
  72. PVIDEO_MODE Mode,
  73. ULONG ModeSize
  74. );
  75. VP_STATUS
  76. VgaLoadAndSetFont(
  77. PHW_DEVICE_EXTENSION HwDeviceExtension,
  78. PVIDEO_LOAD_FONT_INFORMATION FontInformation,
  79. ULONG FontInformationSize
  80. );
  81. VP_STATUS
  82. VgaQueryCursorPosition(
  83. PHW_DEVICE_EXTENSION HwDeviceExtension,
  84. PVIDEO_CURSOR_POSITION CursorPosition,
  85. ULONG CursorPositionSize,
  86. PULONG OutputSize
  87. );
  88. VP_STATUS
  89. VgaSetCursorPosition(
  90. PHW_DEVICE_EXTENSION HwDeviceExtension,
  91. PVIDEO_CURSOR_POSITION CursorPosition,
  92. ULONG CursorPositionSize
  93. );
  94. VP_STATUS
  95. VgaQueryCursorAttributes(
  96. PHW_DEVICE_EXTENSION HwDeviceExtension,
  97. PVIDEO_CURSOR_ATTRIBUTES CursorAttributes,
  98. ULONG CursorAttributesSize,
  99. PULONG OutputSize
  100. );
  101. VP_STATUS
  102. VgaSetCursorAttributes(
  103. PHW_DEVICE_EXTENSION HwDeviceExtension,
  104. PVIDEO_CURSOR_ATTRIBUTES CursorAttributes,
  105. ULONG CursorAttributesSize
  106. );
  107. BOOLEAN
  108. VgaIsPresent(
  109. PHW_DEVICE_EXTENSION HwDeviceExtension
  110. );
  111. BOOLEAN
  112. ET4000IsPresent(
  113. PHW_DEVICE_EXTENSION HwDeviceExtension
  114. );
  115. BOOLEAN
  116. ET6000IsPresent(
  117. PHW_DEVICE_EXTENSION HwDeviceExtension,
  118. PVIDEO_ACCESS_RANGE pAccessRange
  119. );
  120. VOID
  121. VgaInterpretCmdStream(
  122. PVOID HwDeviceExtension,
  123. PUSHORT pusCmdStream
  124. );
  125. VP_STATUS
  126. VgaSetPaletteReg(
  127. PHW_DEVICE_EXTENSION HwDeviceExtension,
  128. PVIDEO_PALETTE_DATA PaletteBuffer,
  129. ULONG PaletteBufferSize
  130. );
  131. VP_STATUS
  132. VgaSetColorLookup(
  133. PHW_DEVICE_EXTENSION HwDeviceExtension,
  134. PVIDEO_CLUT ClutBuffer,
  135. ULONG ClutBufferSize
  136. );
  137. VP_STATUS
  138. VgaRestoreHardwareState(
  139. PHW_DEVICE_EXTENSION HwDeviceExtension,
  140. PVIDEO_HARDWARE_STATE HardwareState,
  141. ULONG HardwareStateSize
  142. );
  143. VP_STATUS
  144. VgaSaveHardwareState(
  145. PHW_DEVICE_EXTENSION HwDeviceExtension,
  146. PVIDEO_HARDWARE_STATE HardwareState,
  147. ULONG HardwareStateSize,
  148. PULONG OutputSize
  149. );
  150. VP_STATUS
  151. VgaGetBankSelectCode(
  152. PHW_DEVICE_EXTENSION HwDeviceExtension,
  153. PVIDEO_BANK_SELECT BankSelect,
  154. ULONG BankSelectSize,
  155. PULONG OutputSize
  156. );
  157. VOID
  158. LockET4000ExtendedRegs(
  159. PHW_DEVICE_EXTENSION HwDeviceExtension
  160. );
  161. VOID
  162. UnlockET4000ExtendedRegs(
  163. PHW_DEVICE_EXTENSION HwDeviceExtension
  164. );
  165. VOID
  166. ResetACToggle(
  167. PHW_DEVICE_EXTENSION HwDeviceExtension
  168. );
  169. ULONG
  170. ET4000GetMemorySize(
  171. PHW_DEVICE_EXTENSION HwDeviceExtension
  172. );
  173. BOOLEAN
  174. ET6000GetMemorySize(
  175. PHW_DEVICE_EXTENSION HwDeviceExtension
  176. );
  177. USHORT
  178. GetIndexedRegisterPacked(
  179. PUCHAR AddressPort,
  180. UCHAR index
  181. );
  182. VOID
  183. ET4000SaveAndSetLinear(
  184. PHW_DEVICE_EXTENSION HwDeviceExtension,
  185. PUSHORT SaveArray
  186. );
  187. VOID
  188. ET4000RestoreFromLinear(
  189. PHW_DEVICE_EXTENSION HwDeviceExtension,
  190. PUSHORT SaveArray
  191. );
  192. VOID
  193. vBankMap(
  194. LONG iBankRead,
  195. LONG iBankWrite,
  196. PVOID pvContext
  197. );
  198. BOOLEAN
  199. ET4000With1MegMemory(
  200. PHW_DEVICE_EXTENSION HwDeviceExtension
  201. );
  202. BOOLEAN
  203. ET4000w32With256KDrams(
  204. PHW_DEVICE_EXTENSION HwDeviceExtension,
  205. USHORT SegmentOffset
  206. );
  207. VOID
  208. VgaValidateModes(
  209. PHW_DEVICE_EXTENSION HwDeviceExtension
  210. );
  211. //
  212. // New entry points added for NT 5.0.
  213. //
  214. #if (_WIN32_WINNT >= 500)
  215. VP_STATUS
  216. ET4000GetPowerState(
  217. PHW_DEVICE_EXTENSION HwDeviceExtension,
  218. ULONG HwDeviceId,
  219. PVIDEO_POWER_MANAGEMENT VideoPowerManagement
  220. );
  221. VP_STATUS
  222. ET4000SetPowerState(
  223. PHW_DEVICE_EXTENSION HwDeviceExtension,
  224. ULONG HwDeviceId,
  225. PVIDEO_POWER_MANAGEMENT VideoPowerManagement
  226. );
  227. //
  228. // Routine to retrieve the Enhanced Display ID structure via DDC
  229. //
  230. ULONG
  231. ET4000GetVideoChildDescriptor(
  232. PVOID HwDeviceExtension,
  233. PVIDEO_CHILD_ENUM_INFO ChildEnumInfo,
  234. PVIDEO_CHILD_TYPE pChildType,
  235. PVOID pvChildDescriptor,
  236. PULONG pHwId,
  237. PULONG pUnused
  238. );
  239. #endif // _WIN32_WINNT >= 500
  240. #if defined(ALLOC_PRAGMA)
  241. #pragma alloc_text(PAGE,DriverEntry)
  242. #pragma alloc_text(PAGE,VgaFindAdapter)
  243. #pragma alloc_text(PAGE,VgaInitialize)
  244. #pragma alloc_text(PAGE,VgaStartIO)
  245. #pragma alloc_text(PAGE,VgaLoadAndSetFont)
  246. #pragma alloc_text(PAGE,VgaQueryCursorPosition)
  247. #pragma alloc_text(PAGE,VgaSetCursorPosition)
  248. #pragma alloc_text(PAGE,VgaQueryCursorAttributes)
  249. #pragma alloc_text(PAGE,VgaSetCursorAttributes)
  250. #pragma alloc_text(PAGE,VgaIsPresent)
  251. #pragma alloc_text(PAGE,ET4000IsPresent)
  252. #pragma alloc_text(PAGE,ET6000IsPresent)
  253. #pragma alloc_text(PAGE,VgaSetPaletteReg)
  254. #pragma alloc_text(PAGE,VgaSetColorLookup)
  255. #pragma alloc_text(PAGE,VgaRestoreHardwareState)
  256. #pragma alloc_text(PAGE,VgaSaveHardwareState)
  257. #pragma alloc_text(PAGE,VgaGetBankSelectCode)
  258. #pragma alloc_text(PAGE,LockET4000ExtendedRegs)
  259. #pragma alloc_text(PAGE,UnlockET4000ExtendedRegs)
  260. #pragma alloc_text(PAGE,ResetACToggle)
  261. #pragma alloc_text(PAGE,ET4000GetMemorySize)
  262. #pragma alloc_text(PAGE,ET6000GetMemorySize)
  263. #pragma alloc_text(PAGE,GetIndexedRegisterPacked)
  264. #pragma alloc_text(PAGE,ET4000SaveAndSetLinear)
  265. #pragma alloc_text(PAGE,ET4000RestoreFromLinear)
  266. #pragma alloc_text(PAGE,ET4000With1MegMemory)
  267. #pragma alloc_text(PAGE,ET4000w32With256KDrams)
  268. #pragma alloc_text(PAGE,VgaValidatorUcharEntry)
  269. #pragma alloc_text(PAGE,VgaValidatorUshortEntry)
  270. #pragma alloc_text(PAGE,VgaValidatorUlongEntry)
  271. #if (_WIN32_WINNT >= 500)
  272. #pragma alloc_text(PAGE_COM, ET4000SetPowerState)
  273. #pragma alloc_text(PAGE_COM, ET4000GetPowerState)
  274. #pragma alloc_text(PAGE_COM, ET4000GetVideoChildDescriptor)
  275. #endif // _WIN32_WINNT >= 500
  276. #endif
  277. ULONG
  278. DriverEntry(
  279. PVOID Context1,
  280. PVOID Context2
  281. )
  282. /*++
  283. Routine Description:
  284. Installable driver initialization entry point.
  285. This entry point is called directly by the I/O system.
  286. Arguments:
  287. Context1 - First context value passed by the operating system. This is
  288. the value with which the miniport driver calls VideoPortInitialize().
  289. Context2 - Second context value passed by the operating system. This is
  290. the value with which the miniport driver calls VideoPortInitialize().
  291. Return Value:
  292. Status from VideoPortInitialize()
  293. --*/
  294. {
  295. VIDEO_HW_INITIALIZATION_DATA hwInitData;
  296. ULONG status;
  297. ULONG initializationStatus;
  298. INTERFACE_TYPE aBusType[] = {PCIBus, Isa, Eisa, MicroChannel,
  299. InterfaceTypeUndefined};
  300. INTERFACE_TYPE *pBusType = aBusType;
  301. //
  302. // Zero out structure.
  303. //
  304. VideoPortZeroMemory(&hwInitData, sizeof(VIDEO_HW_INITIALIZATION_DATA));
  305. //
  306. // Specify sizes of structure and extension.
  307. //
  308. hwInitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA);
  309. //
  310. // Set entry points.
  311. //
  312. hwInitData.HwFindAdapter = VgaFindAdapter;
  313. hwInitData.HwInitialize = VgaInitialize;
  314. hwInitData.HwInterrupt = NULL;
  315. hwInitData.HwStartIO = VgaStartIO;
  316. #if (_WIN32_WINNT >= 500)
  317. //
  318. // Set new entry points added for NT 5.0.
  319. //
  320. hwInitData.HwSetPowerState = ET4000SetPowerState;
  321. hwInitData.HwGetPowerState = ET4000GetPowerState;
  322. hwInitData.HwGetVideoChildDescriptor = ET4000GetVideoChildDescriptor;
  323. hwInitData.HwLegacyResourceList = VgaAccessRange;
  324. hwInitData.HwLegacyResourceCount = 4;
  325. #endif // _WIN32_WINNT >= 500
  326. //
  327. // Determine the size we require for the device extension.
  328. //
  329. hwInitData.HwDeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
  330. //
  331. // Always start with parameters for device0 in this case.
  332. // We can leave it like this since we know we will only ever find one
  333. // VGA type adapter in a machine.
  334. //
  335. // hwInitData.StartingDeviceNumber = 0;
  336. //
  337. // Once all the relevant information has been stored, call the video
  338. // port driver to do the initialization.
  339. // For this device we will repeat this call three times, for ISA, EISA
  340. // and MCA.
  341. // We will return the minimum of all return values.
  342. //
  343. while (*pBusType != InterfaceTypeUndefined)
  344. {
  345. hwInitData.AdapterInterfaceType = *pBusType;
  346. initializationStatus = VideoPortInitialize(Context1,
  347. Context2,
  348. &hwInitData,
  349. NULL);
  350. if (initializationStatus == NO_ERROR)
  351. {
  352. return initializationStatus;
  353. }
  354. pBusType++;
  355. }
  356. //
  357. // We didn't find the card on any bus type, so lets
  358. // return the last error.
  359. //
  360. return initializationStatus;
  361. } // end DriverEntry()
  362. VP_STATUS
  363. VgaFindAdapter(
  364. PVOID HwDeviceExtension,
  365. PVOID HwContext,
  366. PWSTR ArgumentString,
  367. PVIDEO_PORT_CONFIG_INFO ConfigInfo,
  368. PUCHAR Again
  369. )
  370. /*++
  371. Routine Description:
  372. This routine is called to determine if the adapter for this driver
  373. is present in the system.
  374. If it is present, the function fills out some information describing
  375. the adapter.
  376. Arguments:
  377. HwDeviceExtension - Supplies the miniport driver's adapter storage. This
  378. storage is initialized to zero before this call.
  379. HwContext - Supplies the context value which was passed to
  380. VideoPortInitialize(). Must be NULL for PnP drivers.
  381. ArgumentString - Supplies a NULL terminated ASCII string. This string
  382. originates from the user.
  383. ConfigInfo - Returns the configuration information structure which is
  384. filled by the miniport driver. This structure is initialized with
  385. any known configuration information (such as SystemIoBusNumber) by
  386. the port driver. Where possible, drivers should have one set of
  387. defaults which do not require any supplied configuration information.
  388. Again - Indicates if the miniport driver wants the port driver to call
  389. its VIDEO_HW_FIND_ADAPTER function again with a new device extension
  390. and the same config info. This is used by the miniport drivers which
  391. can search for several adapters on a bus.
  392. Return Value:
  393. This routine must return:
  394. NO_ERROR - Indicates a host adapter was found and the
  395. configuration information was successfully determined.
  396. ERROR_INVALID_PARAMETER - Indicates an adapter was found but there was an
  397. error obtaining the configuration information. If possible an error
  398. should be logged.
  399. ERROR_DEV_NOT_EXIST - Indicates no host adapter was found for the
  400. supplied configuration information.
  401. --*/
  402. {
  403. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  404. VP_STATUS status;
  405. ULONG numAccessRanges=NUM_VGA_ACCESS_RANGES;
  406. int i;
  407. //
  408. // Make sure the size of the structure is at least as large as what we
  409. // are expecting (check version of the config info structure).
  410. //
  411. if (ConfigInfo->Length < sizeof(VIDEO_PORT_CONFIG_INFO)) {
  412. VideoDebugPrint((1, "VgaFindAdapter - *** Failed *** wrong config info size\n"));
  413. return ERROR_INVALID_PARAMETER;
  414. }
  415. //
  416. // No interrupt information is necessary.
  417. //
  418. //
  419. // If we are on a PCI bus, lets check and see if an ET6000
  420. // device is present. If so, we'll adjust the access ranges.
  421. //
  422. if (ConfigInfo->AdapterInterfaceType == PCIBus)
  423. {
  424. //
  425. // WARNING: this routine really checks for PCI devices.
  426. // There are ET4000s mounted on W32P boards. But the bottom line
  427. // here is that this routine can return TRUE for ET4000s.
  428. // Hence, the extra checks for ulChipID.
  429. //
  430. if (ET6000IsPresent(hwDeviceExtension, VgaAccessRange))
  431. {
  432. //
  433. // If we found an ET6000 we will use a linear frame buffer
  434. //
  435. hwDeviceExtension->bLinearModeSupported = FALSE;
  436. if (hwDeviceExtension->ulChipID == ET6000)
  437. hwDeviceExtension->bLinearModeSupported = TRUE;
  438. //
  439. // If we will map the frame buffer linearly, then we need
  440. // to make sure to verify its access range.
  441. //
  442. // Idiots. They have to verify the memory even if it's
  443. // banked.
  444. //
  445. numAccessRanges++;
  446. }
  447. else
  448. {
  449. //
  450. // All other devices are currently NOT on the PCI bus. They
  451. // are just detected as ISA cards.
  452. //
  453. // So just fail for the PCI bus.
  454. //
  455. VideoDebugPrint((1, "VgaFindAdapter - *** Failed *** PCI, but nto et6000\n"));
  456. return ERROR_DEV_NOT_EXIST;
  457. }
  458. }
  459. //
  460. // Check to see if there is a hardware resource conflict.
  461. //
  462. status = VideoPortVerifyAccessRanges(HwDeviceExtension,
  463. numAccessRanges,
  464. VgaAccessRange);
  465. if (status != NO_ERROR) {
  466. VideoDebugPrint((1, "VgaFindAdapter - *** Failed *** VerifyAccessRanges failed\n"));
  467. return status;
  468. }
  469. //
  470. // Get logical IO port addresses.
  471. //
  472. for (i = 0; i < 3; i++) {
  473. PUCHAR IOAddress;
  474. if ( (IOAddress =
  475. VideoPortGetDeviceBase(hwDeviceExtension,
  476. VgaAccessRange[i].RangeStart,
  477. VgaAccessRange[i].RangeLength,
  478. VgaAccessRange[i].RangeInIoSpace)) == NULL) {
  479. VideoDebugPrint((1, "VgaFindAdapter - *** Failed *** to get io address ndx(%d) start(%xh) len(%d)\n",
  480. i,
  481. VgaAccessRange[i].RangeStart.LowPart,
  482. VgaAccessRange[i].RangeLength
  483. ));
  484. return ERROR_INVALID_PARAMETER;
  485. } else {
  486. VideoDebugPrint((1, "VgaFindAdapter - Succeeded to get io address ndx(%d) start(%xh) len(%d)\n",
  487. i,
  488. VgaAccessRange[i].RangeStart.LowPart,
  489. VgaAccessRange[i].RangeLength
  490. ));
  491. if (i == 0) {
  492. //
  493. // The difference between the PORT address we asked for and the address we
  494. // were given is the offset at which the system is mapping the port i/o
  495. // space. On x86 systems this should be 0 and on other systems it will
  496. // probably not be 0.
  497. //
  498. hwDeviceExtension->IOAddress = IOAddress;
  499. VideoDebugPrint((1, "VgaFindAdapter - port(%x) mapped at (%x)\n",
  500. VgaAccessRange[i].RangeStart.LowPart,
  501. hwDeviceExtension->IOAddress));
  502. hwDeviceExtension->IOAddress -= VgaAccessRange[i].RangeStart.LowPart;
  503. VideoDebugPrint((1, "VgaFindAdapter - ports are mapped at offset (%x)\n",
  504. hwDeviceExtension->IOAddress));
  505. }
  506. }
  507. }
  508. //
  509. // Determine whether a VGA is present.
  510. //
  511. if (!VgaIsPresent(hwDeviceExtension)) {
  512. VideoDebugPrint((1, "VgaFindAdapter - *** Failed *** No VGA\n"));
  513. return ERROR_DEV_NOT_EXIST;
  514. }
  515. //
  516. // Video memory information
  517. //
  518. hwDeviceExtension->PhysicalVideoMemoryBase.HighPart = 0x00000000;
  519. hwDeviceExtension->PhysicalVideoMemoryBase.LowPart = MEM_VGA;
  520. hwDeviceExtension->PhysicalVideoMemoryLength = MEM_VGA_SIZE;
  521. //
  522. // Map the video memory into the system virtual address space so we can
  523. // clear it out and use it for save and restore.
  524. //
  525. if ( (hwDeviceExtension->VideoMemoryAddress =
  526. VideoPortGetDeviceBase(hwDeviceExtension,
  527. hwDeviceExtension->PhysicalVideoMemoryBase,
  528. hwDeviceExtension->PhysicalVideoMemoryLength, FALSE)) == NULL) {
  529. VideoDebugPrint((1, "VgaFindAdapter - Fail to get memory address\n"));
  530. return ERROR_INVALID_PARAMETER;
  531. }
  532. //
  533. // If an ET6000 is present, then we already found it above. If we
  534. // have not located an ET6000, then see if we are running on an
  535. // ET4000.
  536. //
  537. if (hwDeviceExtension->ulChipID != ET6000)
  538. {
  539. //
  540. // Determine whether an ET4000 is present.
  541. //
  542. if (!ET4000IsPresent(hwDeviceExtension))
  543. {
  544. VideoDebugPrint((1, "VgaFindAdapter - *** Failed *** !et4000 and !et6000\n"));
  545. return ERROR_DEV_NOT_EXIST;
  546. }
  547. }
  548. //
  549. // Pass a pointer to the emulator range we are using.
  550. //
  551. ConfigInfo->NumEmulatorAccessEntries = VGA_NUM_EMULATOR_ACCESS_ENTRIES;
  552. ConfigInfo->EmulatorAccessEntries = VgaEmulatorAccessEntries;
  553. ConfigInfo->EmulatorAccessEntriesContext = (ULONG) hwDeviceExtension;
  554. ConfigInfo->VdmPhysicalVideoMemoryAddress.LowPart = MEM_VGA;
  555. ConfigInfo->VdmPhysicalVideoMemoryAddress.HighPart = 0x00000000;
  556. ConfigInfo->VdmPhysicalVideoMemoryLength = MEM_VGA_SIZE;
  557. //
  558. // Minimum size of the buffer required to store the hardware state
  559. // information returned by IOCTL_VIDEO_SAVE_HARDWARE_STATE.
  560. //
  561. ConfigInfo->HardwareStateSize = VGA_TOTAL_STATE_SIZE;
  562. //
  563. // Indicate we do not wish to be called again for another initialization.
  564. //
  565. *Again = 0;
  566. //
  567. // Indicate a successful completion status.
  568. //
  569. return NO_ERROR;
  570. } // VgaFindAdapter()
  571. BOOLEAN
  572. VgaInitialize(
  573. PVOID HwDeviceExtension
  574. )
  575. /*++
  576. Routine Description:
  577. This routine does one time initialization of the device.
  578. Arguments:
  579. HwDeviceExtension - Pointer to the miniport driver's adapter information.
  580. Return Value:
  581. None.
  582. --*/
  583. {
  584. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  585. //
  586. // set up the default cursor position and type.
  587. //
  588. hwDeviceExtension->CursorPosition.Column = 0;
  589. hwDeviceExtension->CursorPosition.Row = 0;
  590. hwDeviceExtension->CursorTopScanLine = 0;
  591. hwDeviceExtension->CursorBottomScanLine = 31;
  592. hwDeviceExtension->CursorEnable = TRUE;
  593. hwDeviceExtension->BiosArea = (PUSHORT)NULL;
  594. //
  595. // We use VideoPortInt10 to retrieve the ET6000's memory size
  596. // information. We are doing only the ET6000 only so we can
  597. // minimize the impact to any other boards. By using Int10, we
  598. // can save ourselves some possibly tedious work in recognizing
  599. // the board's memory configuration.
  600. //
  601. if (hwDeviceExtension->ulChipID == ET6000)
  602. {
  603. return(ET6000GetMemorySize(hwDeviceExtension));
  604. }
  605. return TRUE;
  606. } // VgaInitialize()
  607. BOOLEAN
  608. VgaStartIO(
  609. PVOID HwDeviceExtension,
  610. PVIDEO_REQUEST_PACKET RequestPacket
  611. )
  612. /*++
  613. Routine Description:
  614. This routine is the main execution routine for the miniport driver. It
  615. acceptss a Video Request Packet, performs the request, and then returns
  616. with the appropriate status.
  617. Arguments:
  618. HwDeviceExtension - Pointer to the miniport driver's adapter information.
  619. RequestPacket - Pointer to the video request packet. This structure
  620. contains all the parameters passed to the VideoIoControl function.
  621. Return Value:
  622. This routine will return error codes from the various support routines
  623. and will also return ERROR_INSUFFICIENT_BUFFER for incorrectly sized
  624. buffers and ERROR_INVALID_FUNCTION for unsupported functions.
  625. --*/
  626. {
  627. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  628. VP_STATUS status;
  629. VIDEO_MODE videoMode;
  630. PVIDEO_MEMORY_INFORMATION memoryInformation;
  631. ULONG inIoSpace;
  632. PVIDEO_SHARE_MEMORY pShareMemory;
  633. PVIDEO_SHARE_MEMORY_INFORMATION pShareMemoryInformation;
  634. PHYSICAL_ADDRESS shareAddress;
  635. PVOID virtualAddress;
  636. ULONG sharedViewSize;
  637. //
  638. // Switch on the IoContolCode in the RequestPacket. It indicates which
  639. // function must be performed by the driver.
  640. //
  641. VideoDebugPrint((2, "W32StartIO Entry - %08.8x\n", RequestPacket->IoControlCode));
  642. switch (RequestPacket->IoControlCode) {
  643. case IOCTL_VIDEO_SHARE_VIDEO_MEMORY:
  644. VideoDebugPrint((2, "W32StartIO - ShareVideoMemory\n"));
  645. if ( (RequestPacket->OutputBufferLength < sizeof(VIDEO_SHARE_MEMORY_INFORMATION)) ||
  646. (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) ) {
  647. VideoDebugPrint((1, "IOCTL_VIDEO_SHARE_VIDEO_MEMORY - ERROR_INSUFFICIENT_BUFFER\n"));
  648. status = ERROR_INSUFFICIENT_BUFFER;
  649. break;
  650. }
  651. pShareMemory = RequestPacket->InputBuffer;
  652. if ( (pShareMemory->ViewOffset > hwDeviceExtension->AdapterMemorySize) ||
  653. ((pShareMemory->ViewOffset + pShareMemory->ViewSize) >
  654. hwDeviceExtension->AdapterMemorySize) ) {
  655. VideoDebugPrint((1, "IOCTL_VIDEO_SHARE_VIDEO_MEMORY - ERROR_INVALID_PARAMETER\n"));
  656. status = ERROR_INVALID_PARAMETER;
  657. break;
  658. }
  659. RequestPacket->StatusBlock->Information =
  660. sizeof(VIDEO_SHARE_MEMORY_INFORMATION);
  661. //
  662. // Beware: the input buffer and the output buffer are the same
  663. // buffer, and therefore data should not be copied from one to the
  664. // other
  665. //
  666. virtualAddress = pShareMemory->ProcessHandle;
  667. sharedViewSize = pShareMemory->ViewSize;
  668. #if defined(ALPHA)
  669. inIoSpace = 4;
  670. #else
  671. inIoSpace = 0;
  672. #endif
  673. //
  674. // NOTE: we are ignoring ViewOffset
  675. //
  676. shareAddress.QuadPart = VgaAccessRange[4].RangeStart.QuadPart;
  677. // hwDeviceExtension->PhysicalFrameBase.QuadPart;
  678. status = VideoPortMapMemory(hwDeviceExtension,
  679. shareAddress,
  680. &sharedViewSize,
  681. &inIoSpace,
  682. &virtualAddress);
  683. pShareMemoryInformation = RequestPacket->OutputBuffer;
  684. pShareMemoryInformation->SharedViewOffset = pShareMemory->ViewOffset;
  685. pShareMemoryInformation->VirtualAddress = virtualAddress;
  686. pShareMemoryInformation->SharedViewSize = sharedViewSize;
  687. break;
  688. case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY:
  689. VideoDebugPrint((2, "W32StartIO - UnshareVideoMemory\n"));
  690. if (RequestPacket->InputBufferLength < sizeof(VIDEO_SHARE_MEMORY)) {
  691. status = ERROR_INSUFFICIENT_BUFFER;
  692. break;
  693. }
  694. pShareMemory = RequestPacket->InputBuffer;
  695. status = VideoPortUnmapMemory(hwDeviceExtension,
  696. pShareMemory->RequestedVirtualAddress,
  697. pShareMemory->ProcessHandle);
  698. break;
  699. case IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES:
  700. VideoDebugPrint((1, "VgaStartIO - Map W32 MMU or ACL\n"));
  701. if (RequestPacket->OutputBufferLength <
  702. 3 * sizeof(VIDEO_PUBLIC_ACCESS_RANGES))
  703. {
  704. status = ERROR_INSUFFICIENT_BUFFER;
  705. }
  706. else
  707. {
  708. PVIDEO_PUBLIC_ACCESS_RANGES portAccess;
  709. PHYSICAL_ADDRESS base, pa;
  710. ULONG length;
  711. ULONG ulIndex;
  712. RequestPacket->StatusBlock->Information =
  713. 3 * sizeof(VIDEO_PUBLIC_ACCESS_RANGES);
  714. portAccess = RequestPacket->OutputBuffer;
  715. if (hwDeviceExtension->bInLinearMode)
  716. {
  717. base = VgaAccessRange[LINEAR_FRAME_BUFFER].RangeStart;
  718. ulIndex = 1;
  719. }
  720. else
  721. {
  722. base = VgaAccessRange[BANKED_FRAME_BUFFER].RangeStart;
  723. ulIndex = 0;
  724. }
  725. //
  726. // Map the first range
  727. //
  728. portAccess->VirtualAddress = (PVOID) NULL;
  729. portAccess->InIoSpace = FALSE;
  730. portAccess->MappedInIoSpace = portAccess->InIoSpace;
  731. //
  732. // We don't map this range if we are linear!
  733. //
  734. if (!hwDeviceExtension->bInLinearMode)
  735. {
  736. pa = base;
  737. pa.LowPart = RangeOffsets[ulIndex][0].ulOffset;
  738. length = RangeOffsets[ulIndex][0].ulLength;
  739. status = VideoPortMapMemory(hwDeviceExtension,
  740. pa,
  741. &length,
  742. &(portAccess->MappedInIoSpace),
  743. &(portAccess->VirtualAddress));
  744. if (status != NO_ERROR)
  745. {
  746. break;
  747. }
  748. }
  749. //
  750. // Map the second range
  751. //
  752. portAccess++;
  753. portAccess->VirtualAddress = (PVOID) NULL;
  754. portAccess->InIoSpace = FALSE;
  755. portAccess->MappedInIoSpace = portAccess->InIoSpace;
  756. pa = base;
  757. pa.LowPart = RangeOffsets[ulIndex][1].ulOffset;
  758. length = RangeOffsets[ulIndex][1].ulLength;
  759. VideoDebugPrint((1, "\n\n**** pa = 0x%x\n", pa.LowPart));
  760. status = VideoPortMapMemory(hwDeviceExtension,
  761. pa,
  762. &length,
  763. &(portAccess->MappedInIoSpace),
  764. &(portAccess->VirtualAddress));
  765. if (status != NO_ERROR)
  766. {
  767. break;
  768. }
  769. //
  770. // Map the third range
  771. //
  772. portAccess++;
  773. portAccess->VirtualAddress = (PVOID) NULL;
  774. portAccess->InIoSpace = TRUE;
  775. portAccess->MappedInIoSpace = portAccess->InIoSpace;
  776. pa.LowPart = PORT_IO_ADDR;
  777. length = PORT_IO_LEN;
  778. status = VideoPortMapMemory(hwDeviceExtension,
  779. pa,
  780. &length,
  781. &(portAccess->MappedInIoSpace),
  782. &(portAccess->VirtualAddress));
  783. }
  784. break;
  785. case IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES:
  786. VideoDebugPrint((2, "VgaStartIO - FreePublicAccessRanges\n"));
  787. {
  788. PVIDEO_MEMORY mappedMemory;
  789. if (RequestPacket->InputBufferLength < 2 * sizeof(VIDEO_MEMORY)) {
  790. status = ERROR_INSUFFICIENT_BUFFER;
  791. break;
  792. }
  793. status = NO_ERROR;
  794. mappedMemory = RequestPacket->InputBuffer;
  795. if (mappedMemory->RequestedVirtualAddress != NULL) {
  796. status = VideoPortUnmapMemory(hwDeviceExtension,
  797. mappedMemory->
  798. RequestedVirtualAddress,
  799. 0);
  800. }
  801. }
  802. break;
  803. case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
  804. VideoDebugPrint((2, "VgaStartIO - MapVideoMemory\n"));
  805. if ( (RequestPacket->OutputBufferLength <
  806. (RequestPacket->StatusBlock->Information =
  807. sizeof(VIDEO_MEMORY_INFORMATION))) ||
  808. (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) ) {
  809. status = ERROR_INSUFFICIENT_BUFFER;
  810. }
  811. memoryInformation = RequestPacket->OutputBuffer;
  812. memoryInformation->VideoRamBase = ((PVIDEO_MEMORY)
  813. (RequestPacket->InputBuffer))->RequestedVirtualAddress;
  814. #if defined(ALPHA)
  815. inIoSpace = 4;
  816. #else
  817. inIoSpace = 0;
  818. #endif
  819. if (hwDeviceExtension->bInLinearMode)
  820. {
  821. //
  822. // Map in the linear frame buffer
  823. //
  824. memoryInformation->VideoRamLength = hwDeviceExtension->AdapterMemorySize;
  825. status = VideoPortMapMemory(hwDeviceExtension,
  826. VgaAccessRange[4].RangeStart,
  827. &(memoryInformation->VideoRamLength),
  828. &(inIoSpace),
  829. &(memoryInformation->VideoRamBase));
  830. memoryInformation->FrameBufferLength = memoryInformation->VideoRamLength;
  831. memoryInformation->FrameBufferBase = memoryInformation->VideoRamBase;
  832. }
  833. else
  834. {
  835. //
  836. // Map in the banked frame buffer
  837. //
  838. memoryInformation->VideoRamLength = hwDeviceExtension->PhysicalVideoMemoryLength;
  839. status = VideoPortMapMemory(hwDeviceExtension,
  840. hwDeviceExtension->PhysicalVideoMemoryBase,
  841. &(memoryInformation->VideoRamLength),
  842. &inIoSpace,
  843. &(memoryInformation->VideoRamBase));
  844. memoryInformation->FrameBufferLength = hwDeviceExtension->PhysicalFrameLength;
  845. memoryInformation->FrameBufferBase =
  846. ((PUCHAR) (memoryInformation->VideoRamBase)) +
  847. (hwDeviceExtension->PhysicalFrameBase.LowPart -
  848. hwDeviceExtension->PhysicalVideoMemoryBase.LowPart);
  849. }
  850. break;
  851. case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
  852. VideoDebugPrint((2, "VgaStartIO - UnMapVideoMemory\n"));
  853. if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) {
  854. status = ERROR_INSUFFICIENT_BUFFER;
  855. }
  856. status = VideoPortUnmapMemory(hwDeviceExtension,
  857. ((PVIDEO_MEMORY)
  858. (RequestPacket->InputBuffer))->
  859. RequestedVirtualAddress,
  860. 0);
  861. break;
  862. case IOCTL_VIDEO_QUERY_AVAIL_MODES:
  863. VideoDebugPrint((2, "VgaStartIO - QueryAvailableModes\n"));
  864. status = VgaQueryAvailableModes(HwDeviceExtension,
  865. (PVIDEO_MODE_INFORMATION)
  866. RequestPacket->OutputBuffer,
  867. RequestPacket->OutputBufferLength,
  868. &RequestPacket->StatusBlock->Information);
  869. break;
  870. case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
  871. VideoDebugPrint((2, "VgaStartIO - QueryNumAvailableModes\n"));
  872. status = VgaQueryNumberOfAvailableModes(HwDeviceExtension,
  873. (PVIDEO_NUM_MODES)
  874. RequestPacket->OutputBuffer,
  875. RequestPacket->OutputBufferLength,
  876. &RequestPacket->StatusBlock->Information);
  877. break;
  878. case IOCTL_VIDEO_QUERY_CURRENT_MODE:
  879. VideoDebugPrint((2, "VgaStartIO - QueryCurrentMode\n"));
  880. status = VgaQueryCurrentMode(HwDeviceExtension,
  881. (PVIDEO_MODE_INFORMATION) RequestPacket->OutputBuffer,
  882. RequestPacket->OutputBufferLength,
  883. &RequestPacket->StatusBlock->Information);
  884. break;
  885. case IOCTL_VIDEO_SET_CURRENT_MODE:
  886. VideoDebugPrint((2, "VgaStartIO - SetCurrentModes\n"));
  887. status = VgaRestoreHardwareState(HwDeviceExtension,
  888. (PVIDEO_HARDWARE_STATE) RequestPacket->InputBuffer,
  889. RequestPacket->InputBufferLength);
  890. status = VgaSetMode(HwDeviceExtension,
  891. (PVIDEO_MODE) RequestPacket->InputBuffer,
  892. RequestPacket->InputBufferLength);
  893. break;
  894. case IOCTL_VIDEO_RESET_DEVICE:
  895. VideoDebugPrint((2, "VgaStartIO - Reset Device\n"));
  896. videoMode.RequestedMode = DEFAULT_MODE;
  897. status = VgaSetMode(HwDeviceExtension,
  898. (PVIDEO_MODE) &videoMode,
  899. sizeof(videoMode));
  900. break;
  901. case IOCTL_VIDEO_LOAD_AND_SET_FONT:
  902. VideoDebugPrint((2, "VgaStartIO - LoadAndSetFont\n"));
  903. status = VgaLoadAndSetFont(HwDeviceExtension,
  904. (PVIDEO_LOAD_FONT_INFORMATION) RequestPacket->InputBuffer,
  905. RequestPacket->InputBufferLength);
  906. break;
  907. case IOCTL_VIDEO_QUERY_CURSOR_POSITION:
  908. VideoDebugPrint((2, "VgaStartIO - QueryCursorPosition\n"));
  909. status = VgaQueryCursorPosition(HwDeviceExtension,
  910. (PVIDEO_CURSOR_POSITION) RequestPacket->OutputBuffer,
  911. RequestPacket->OutputBufferLength,
  912. &RequestPacket->StatusBlock->Information);
  913. break;
  914. case IOCTL_VIDEO_SET_CURSOR_POSITION:
  915. VideoDebugPrint((2, "VgaStartIO - SetCursorPosition\n"));
  916. status = VgaSetCursorPosition(HwDeviceExtension,
  917. (PVIDEO_CURSOR_POSITION)
  918. RequestPacket->InputBuffer,
  919. RequestPacket->InputBufferLength);
  920. break;
  921. case IOCTL_VIDEO_QUERY_CURSOR_ATTR:
  922. VideoDebugPrint((2, "VgaStartIO - QueryCursorAttributes\n"));
  923. status = VgaQueryCursorAttributes(HwDeviceExtension,
  924. (PVIDEO_CURSOR_ATTRIBUTES) RequestPacket->OutputBuffer,
  925. RequestPacket->OutputBufferLength,
  926. &RequestPacket->StatusBlock->Information);
  927. break;
  928. case IOCTL_VIDEO_SET_CURSOR_ATTR:
  929. VideoDebugPrint((2, "VgaStartIO - SetCursorAttributes\n"));
  930. status = VgaSetCursorAttributes(HwDeviceExtension,
  931. (PVIDEO_CURSOR_ATTRIBUTES) RequestPacket->InputBuffer,
  932. RequestPacket->InputBufferLength);
  933. break;
  934. case IOCTL_VIDEO_SET_PALETTE_REGISTERS:
  935. VideoDebugPrint((2, "VgaStartIO - SetPaletteRegs\n"));
  936. status = VgaSetPaletteReg(HwDeviceExtension,
  937. (PVIDEO_PALETTE_DATA) RequestPacket->InputBuffer,
  938. RequestPacket->InputBufferLength);
  939. break;
  940. case IOCTL_VIDEO_SET_COLOR_REGISTERS:
  941. VideoDebugPrint((2, "VgaStartIO - SetColorRegs\n"));
  942. status = VgaSetColorLookup(HwDeviceExtension,
  943. (PVIDEO_CLUT) RequestPacket->InputBuffer,
  944. RequestPacket->InputBufferLength);
  945. break;
  946. case IOCTL_VIDEO_ENABLE_VDM:
  947. VideoDebugPrint((2, "VgaStartIO - EnableVDM\n"));
  948. hwDeviceExtension->TrappedValidatorCount = 0;
  949. hwDeviceExtension->SequencerAddressValue = 0;
  950. hwDeviceExtension->CurrentNumVdmAccessRanges =
  951. NUM_MINIMAL_VGA_VALIDATOR_ACCESS_RANGE;
  952. hwDeviceExtension->CurrentVdmAccessRange =
  953. MinimalVgaValidatorAccessRange;
  954. VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
  955. hwDeviceExtension->CurrentNumVdmAccessRanges,
  956. hwDeviceExtension->CurrentVdmAccessRange);
  957. status = NO_ERROR;
  958. break;
  959. case IOCTL_VIDEO_RESTORE_HARDWARE_STATE:
  960. VideoDebugPrint((2, "VgaStartIO - RestoreHardwareState\n"));
  961. status = VgaRestoreHardwareState(HwDeviceExtension,
  962. (PVIDEO_HARDWARE_STATE) RequestPacket->InputBuffer,
  963. RequestPacket->InputBufferLength);
  964. break;
  965. case IOCTL_VIDEO_SAVE_HARDWARE_STATE:
  966. VideoDebugPrint((2, "VgaStartIO - SaveHardwareState\n"));
  967. status = VgaSaveHardwareState(HwDeviceExtension,
  968. (PVIDEO_HARDWARE_STATE) RequestPacket->OutputBuffer,
  969. RequestPacket->OutputBufferLength,
  970. &RequestPacket->StatusBlock->Information);
  971. break;
  972. case IOCTL_VIDEO_GET_BANK_SELECT_CODE:
  973. VideoDebugPrint((2, "VgaStartIO - GetBankSelectCode\n"));
  974. #if defined(i386)
  975. status = VgaGetBankSelectCode(HwDeviceExtension,
  976. (PVIDEO_BANK_SELECT) RequestPacket->OutputBuffer,
  977. RequestPacket->OutputBufferLength,
  978. &RequestPacket->StatusBlock->Information);
  979. #else
  980. status = ERROR_INVALID_FUNCTION;
  981. #endif
  982. break;
  983. //
  984. // Private IOCTLs established with the driver
  985. //
  986. case IOCTL_VIDEO_GET_VIDEO_CARD_INFO:
  987. VideoDebugPrint((2, "VgaStartIO - Get video card info\n"));
  988. if (RequestPacket->OutputBufferLength <
  989. (RequestPacket->StatusBlock->Information =
  990. sizeof(VIDEO_COPROCESSOR_INFORMATION)) )
  991. {
  992. status = ERROR_INSUFFICIENT_BUFFER;
  993. break;
  994. }
  995. // return the Coproc Base Address.
  996. ((PVIDEO_COPROCESSOR_INFORMATION) RequestPacket->OutputBuffer)->ulChipID =
  997. hwDeviceExtension->ulChipID;
  998. ((PVIDEO_COPROCESSOR_INFORMATION) RequestPacket->OutputBuffer)->ulRevLevel =
  999. hwDeviceExtension->ulRevLevel;
  1000. status = NO_ERROR;
  1001. break;
  1002. //
  1003. // if we get here, an invalid IoControlCode was specified.
  1004. //
  1005. default:
  1006. VideoDebugPrint((1, "Fell through vga startIO routine - invalid command\n"));
  1007. status = ERROR_INVALID_FUNCTION;
  1008. break;
  1009. }
  1010. RequestPacket->StatusBlock->Status = status;
  1011. #if DBG
  1012. VideoDebugPrint((2, "W32StartIO Exit - %08.8x\n", RequestPacket->IoControlCode));
  1013. #endif
  1014. return TRUE;
  1015. } // VgaStartIO()
  1016. //
  1017. // private routines
  1018. //
  1019. VP_STATUS
  1020. VgaLoadAndSetFont(
  1021. PHW_DEVICE_EXTENSION HwDeviceExtension,
  1022. PVIDEO_LOAD_FONT_INFORMATION FontInformation,
  1023. ULONG FontInformationSize
  1024. )
  1025. /*++
  1026. Routine Description:
  1027. Takes a buffer containing a user-defined font and loads it into the
  1028. VGA soft font memory and programs the VGA to the appropriate character
  1029. cell size.
  1030. Arguments:
  1031. HwDeviceExtension - Pointer to the miniport driver's device extension.
  1032. FontInformation - Pointer to the structure containing the information
  1033. about the loadable ROM font to be set.
  1034. FontInformationSize - Length of the input buffer supplied by the user.
  1035. Return Value:
  1036. NO_ERROR - information returned successfully
  1037. ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data.
  1038. ERROR_INVALID_PARAMETER - invalid video mode
  1039. --*/
  1040. {
  1041. PUCHAR destination;
  1042. PUCHAR source;
  1043. USHORT width;
  1044. ULONG i;
  1045. //
  1046. // check if a mode has been set
  1047. //
  1048. if (HwDeviceExtension->CurrentMode == NULL) {
  1049. return ERROR_INVALID_FUNCTION;
  1050. }
  1051. //
  1052. // Text mode only; If we are in a graphics mode, return an error
  1053. //
  1054. if (HwDeviceExtension->CurrentMode->fbType & VIDEO_MODE_GRAPHICS) {
  1055. return ERROR_INVALID_PARAMETER;
  1056. }
  1057. //
  1058. // Check if the size of the data in the input buffer is large enough
  1059. // and that it contains all the data.
  1060. //
  1061. if ( (FontInformationSize < sizeof(VIDEO_LOAD_FONT_INFORMATION)) ||
  1062. (FontInformationSize < sizeof(VIDEO_LOAD_FONT_INFORMATION) +
  1063. sizeof(UCHAR) * (FontInformation->FontSize - 1)) ) {
  1064. return ERROR_INSUFFICIENT_BUFFER;
  1065. }
  1066. //
  1067. // Check for the width and height of the font
  1068. //
  1069. if ( ((FontInformation->WidthInPixels != 8) &&
  1070. (FontInformation->WidthInPixels != 9)) ||
  1071. (FontInformation->HeightInPixels > 32) ) {
  1072. return ERROR_INVALID_PARAMETER;
  1073. }
  1074. //
  1075. // Check the size of the font buffer is the right size for the size
  1076. // font being passed down.
  1077. //
  1078. if (FontInformation->FontSize < FontInformation->HeightInPixels * 256 *
  1079. sizeof(UCHAR) ) {
  1080. return ERROR_INSUFFICIENT_BUFFER;
  1081. }
  1082. //
  1083. // Since the font parameters are valid, store the parameters in the
  1084. // device extension and load the font.
  1085. //
  1086. HwDeviceExtension->FontPelRows = FontInformation->HeightInPixels;
  1087. HwDeviceExtension->FontPelColumns = FontInformation->WidthInPixels;
  1088. HwDeviceExtension->CurrentMode->row =
  1089. HwDeviceExtension->CurrentMode->vres / HwDeviceExtension->FontPelRows;
  1090. width =
  1091. HwDeviceExtension->CurrentMode->hres / HwDeviceExtension->FontPelColumns;
  1092. if (width < (USHORT)HwDeviceExtension->CurrentMode->col) {
  1093. HwDeviceExtension->CurrentMode->col = width;
  1094. }
  1095. source = &(FontInformation->Font[0]);
  1096. //
  1097. // Set up the destination and source pointers for the font
  1098. //
  1099. destination = (PUCHAR)HwDeviceExtension->VideoMemoryAddress;
  1100. //
  1101. // Map font buffer at A0000
  1102. //
  1103. VgaInterpretCmdStream(HwDeviceExtension, EnableA000Data);
  1104. //
  1105. // Move the font to its destination
  1106. //
  1107. for (i = 1; i <= 256; i++) {
  1108. VideoPortWriteRegisterBufferUchar(destination,
  1109. source,
  1110. FontInformation->HeightInPixels);
  1111. destination += 32;
  1112. source += FontInformation->HeightInPixels;
  1113. }
  1114. VgaInterpretCmdStream(HwDeviceExtension, DisableA000Color);
  1115. //
  1116. // Restore to a text mode.
  1117. //
  1118. //
  1119. // Set Height of font.
  1120. //
  1121. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1122. CRTC_ADDRESS_PORT_COLOR, 0x9);
  1123. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1124. CRTC_DATA_PORT_COLOR,
  1125. (UCHAR)(FontInformation->HeightInPixels - 1));
  1126. //
  1127. // Set Width of font.
  1128. //
  1129. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1130. CRTC_ADDRESS_PORT_COLOR, 0x12);
  1131. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1132. CRTC_DATA_PORT_COLOR,
  1133. (UCHAR)(((USHORT)FontInformation->HeightInPixels *
  1134. (USHORT)HwDeviceExtension->CurrentMode->row) - 1));
  1135. i = HwDeviceExtension->CurrentMode->vres /
  1136. HwDeviceExtension->CurrentMode->row;
  1137. //
  1138. // Set Cursor End
  1139. //
  1140. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1141. CRTC_ADDRESS_PORT_COLOR, 0xb);
  1142. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1143. CRTC_DATA_PORT_COLOR, (UCHAR)--i);
  1144. //
  1145. // Set Cursor Statr
  1146. //
  1147. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1148. CRTC_ADDRESS_PORT_COLOR, 0xa);
  1149. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1150. CRTC_DATA_PORT_COLOR, (UCHAR)--i);
  1151. return NO_ERROR;
  1152. } //end VgaLoadAndSetFont()
  1153. VP_STATUS
  1154. VgaQueryCursorPosition(
  1155. PHW_DEVICE_EXTENSION HwDeviceExtension,
  1156. PVIDEO_CURSOR_POSITION CursorPosition,
  1157. ULONG CursorPositionSize,
  1158. PULONG OutputSize
  1159. )
  1160. /*++
  1161. Routine Description:
  1162. This routine returns the row and column of the cursor.
  1163. Arguments:
  1164. HwDeviceExtension - Pointer to the miniport driver's device extension.
  1165. CursorPosition - Pointer to the output buffer supplied by the user. This
  1166. is where the cursor position is stored.
  1167. CursorPositionSize - Length of the output buffer supplied by the user.
  1168. OutputSize - Pointer to a buffer in which to return the actual size of
  1169. the data in the buffer. If the buffer was not large enough, this
  1170. contains the minimum required buffer size.
  1171. Return Value:
  1172. NO_ERROR - information returned successfully
  1173. ERROR_INSUFFICIENT_BUFFER - output buffer not large enough to return
  1174. any useful data
  1175. ERROR_INVALID_PARAMETER - invalid video mode
  1176. --*/
  1177. {
  1178. //
  1179. // check if a mode has been set
  1180. //
  1181. if (HwDeviceExtension->CurrentMode == NULL) {
  1182. return ERROR_INVALID_FUNCTION;
  1183. }
  1184. //
  1185. // Text mode only; If we are in a graphics mode, return an error
  1186. //
  1187. if (HwDeviceExtension->CurrentMode->fbType & VIDEO_MODE_GRAPHICS) {
  1188. *OutputSize = 0;
  1189. return ERROR_INVALID_PARAMETER;
  1190. }
  1191. //
  1192. // If the buffer passed in is not large enough return an
  1193. // appropriate error code.
  1194. //
  1195. if (CursorPositionSize < (*OutputSize = sizeof(VIDEO_CURSOR_POSITION)) ) {
  1196. *OutputSize = 0;
  1197. return ERROR_INSUFFICIENT_BUFFER;
  1198. }
  1199. //
  1200. // Store the postition of the cursor into the buffer.
  1201. //
  1202. CursorPosition->Column = HwDeviceExtension->CursorPosition.Column;
  1203. CursorPosition->Row = HwDeviceExtension->CursorPosition.Row;
  1204. return NO_ERROR;
  1205. } // end VgaQueryCursorPosition()
  1206. VP_STATUS
  1207. VgaSetCursorPosition(
  1208. PHW_DEVICE_EXTENSION HwDeviceExtension,
  1209. PVIDEO_CURSOR_POSITION CursorPosition,
  1210. ULONG CursorPositionSize
  1211. )
  1212. /*++
  1213. Routine Description:
  1214. This routine verifies that the requested cursor position is within
  1215. the row and column bounds of the current mode and font. If valid, then
  1216. it sets the row and column of the cursor.
  1217. Arguments:
  1218. HwDeviceExtension - Pointer to the miniport driver's device extension.
  1219. CursorPosition - Pointer to the structure containing the cursor position.
  1220. CursorPositionSize - Length of the input buffer supplied by the user.
  1221. Return Value:
  1222. NO_ERROR - information returned successfully
  1223. ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data
  1224. ERROR_INVALID_PARAMETER - invalid video mode
  1225. --*/
  1226. {
  1227. USHORT position;
  1228. //
  1229. // check if a mode has been set
  1230. //
  1231. if (HwDeviceExtension->CurrentMode == NULL) {
  1232. return ERROR_INVALID_FUNCTION;
  1233. }
  1234. //
  1235. // Text mode only; If we are in a graphics mode, return an error
  1236. //
  1237. if (HwDeviceExtension->CurrentMode->fbType & VIDEO_MODE_GRAPHICS) {
  1238. return ERROR_INVALID_PARAMETER;
  1239. }
  1240. //
  1241. // Check if the size of the data in the input buffer is large enough.
  1242. //
  1243. if (CursorPositionSize < sizeof(VIDEO_CURSOR_POSITION)) {
  1244. return ERROR_INSUFFICIENT_BUFFER;
  1245. }
  1246. //
  1247. // Check if the new values for the cursor positions are in the valid
  1248. // bounds for the screen.
  1249. //
  1250. if ((CursorPosition->Column >= HwDeviceExtension->CurrentMode->col) ||
  1251. (CursorPosition->Row >= HwDeviceExtension->CurrentMode->row)) {
  1252. return ERROR_INVALID_PARAMETER;
  1253. }
  1254. //
  1255. // Store these new values in the device extension so we can use them in
  1256. // a QUERY.
  1257. //
  1258. HwDeviceExtension->CursorPosition.Column = CursorPosition->Column;
  1259. HwDeviceExtension->CursorPosition.Row = CursorPosition->Row;
  1260. //
  1261. // Calculate the position on the screen at which the cursor must be
  1262. // be displayed
  1263. //
  1264. position = (USHORT) (HwDeviceExtension->CurrentMode->col *
  1265. CursorPosition->Row + CursorPosition->Column);
  1266. //
  1267. // Address Cursor Location Low Register in CRT Controller Registers
  1268. //
  1269. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1270. CRTC_ADDRESS_PORT_COLOR, IND_CURSOR_LOW_LOC);
  1271. //
  1272. // Set Cursor Location Low Register
  1273. //
  1274. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1275. CRTC_DATA_PORT_COLOR, (UCHAR) (position & 0x00FF));
  1276. //
  1277. // Address Cursor Location High Register in CRT Controller Registers
  1278. //
  1279. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1280. CRTC_ADDRESS_PORT_COLOR, IND_CURSOR_HIGH_LOC);
  1281. //
  1282. // Set Cursor Location High Register
  1283. //
  1284. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1285. CRTC_DATA_PORT_COLOR, (UCHAR) (position >> 8));
  1286. return NO_ERROR;
  1287. } // end VgaSetCursorPosition()
  1288. VP_STATUS
  1289. VgaQueryCursorAttributes(
  1290. PHW_DEVICE_EXTENSION HwDeviceExtension,
  1291. PVIDEO_CURSOR_ATTRIBUTES CursorAttributes,
  1292. ULONG CursorAttributesSize,
  1293. PULONG OutputSize
  1294. )
  1295. /*++
  1296. Routine Description:
  1297. This routine returns information about the height and visibility of the
  1298. cursor.
  1299. Arguments:
  1300. HwDeviceExtension - Pointer to the miniport driver's device extension.
  1301. CursorAttributes - Pointer to the output buffer supplied by the user.
  1302. This is where the cursor type is stored.
  1303. CursorAttributesSize - Length of the output buffer supplied by the user.
  1304. OutputSize - Pointer to a buffer in which to return the actual size of
  1305. the data in the buffer. If the buffer was not large enough, this
  1306. contains the minimum required buffer size.
  1307. Return Value:
  1308. NO_ERROR - information returned successfully
  1309. ERROR_INSUFFICIENT_BUFFER - output buffer not large enough to return
  1310. any useful data
  1311. ERROR_INVALID_PARAMETER - invalid video mode
  1312. --*/
  1313. {
  1314. //
  1315. // check if a mode has been set
  1316. //
  1317. if (HwDeviceExtension->CurrentMode == NULL) {
  1318. return ERROR_INVALID_FUNCTION;
  1319. }
  1320. //
  1321. // Text mode only; If we are in a graphics mode, return an error
  1322. //
  1323. if (HwDeviceExtension->CurrentMode->fbType & VIDEO_MODE_GRAPHICS) {
  1324. *OutputSize = 0;
  1325. return ERROR_INVALID_PARAMETER;
  1326. }
  1327. //
  1328. // Find out the size of the data to be put in the the buffer and return
  1329. // that in the status information (whether or not the information is
  1330. // there). If the buffer passed in is not large enough return an
  1331. // appropriate error code.
  1332. //
  1333. if (CursorAttributesSize < (*OutputSize =
  1334. sizeof(VIDEO_CURSOR_ATTRIBUTES)) ) {
  1335. *OutputSize = 0;
  1336. return ERROR_INSUFFICIENT_BUFFER;
  1337. }
  1338. //
  1339. // Store the cursor information into the buffer.
  1340. //
  1341. CursorAttributes->Height = (USHORT) HwDeviceExtension->CursorTopScanLine;
  1342. CursorAttributes->Width = (USHORT) HwDeviceExtension->CursorBottomScanLine;
  1343. CursorAttributes->Enable = HwDeviceExtension->CursorEnable;
  1344. return NO_ERROR;
  1345. } // end VgaQueryCursorAttributes()
  1346. VP_STATUS
  1347. VgaSetCursorAttributes(
  1348. PHW_DEVICE_EXTENSION HwDeviceExtension,
  1349. PVIDEO_CURSOR_ATTRIBUTES CursorAttributes,
  1350. ULONG CursorAttributesSize
  1351. )
  1352. /*++
  1353. Routine Description:
  1354. This routine verifies that the requested cursor height is within the
  1355. bounds of the character cell. If valid, then it sets the new
  1356. visibility and height of the cursor.
  1357. Arguments:
  1358. HwDeviceExtension - Pointer to the miniport driver's device extension.
  1359. CursorType - Pointer to the structure containing the cursor information.
  1360. CursorTypeSize - Length of the input buffer supplied by the user.
  1361. Return Value:
  1362. NO_ERROR - information returned successfully
  1363. ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data
  1364. ERROR_INVALID_PARAMETER - invalid video mode
  1365. --*/
  1366. {
  1367. UCHAR cursorLine;
  1368. //
  1369. // check if a mode has been set
  1370. //
  1371. if (HwDeviceExtension->CurrentMode == NULL) {
  1372. return ERROR_INVALID_FUNCTION;
  1373. }
  1374. //
  1375. // Text mode only; If we are in a graphics mode, return an error
  1376. //
  1377. if (HwDeviceExtension->CurrentMode->fbType & VIDEO_MODE_GRAPHICS) {
  1378. return ERROR_INVALID_PARAMETER;
  1379. }
  1380. //
  1381. // Check if the size of the data in the input buffer is large enough.
  1382. //
  1383. if (CursorAttributesSize < sizeof(VIDEO_CURSOR_ATTRIBUTES)) {
  1384. return ERROR_INSUFFICIENT_BUFFER;
  1385. }
  1386. //
  1387. // Check if the new values for the cursor type are in the valid range.
  1388. //
  1389. if ((CursorAttributes->Height >= HwDeviceExtension->FontPelRows) ||
  1390. (CursorAttributes->Width > 31)) {
  1391. return ERROR_INVALID_PARAMETER;
  1392. }
  1393. //
  1394. // Store the cursor information in the device extension so we can use
  1395. // them in a QUERY.
  1396. //
  1397. HwDeviceExtension->CursorTopScanLine = (UCHAR) CursorAttributes->Height;
  1398. HwDeviceExtension->CursorBottomScanLine = (UCHAR) CursorAttributes->Width;
  1399. HwDeviceExtension->CursorEnable = CursorAttributes->Enable;
  1400. //
  1401. // Address Cursor Start Register in CRT Controller Registers
  1402. //
  1403. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1404. CRTC_ADDRESS_PORT_COLOR,
  1405. IND_CURSOR_START);
  1406. //
  1407. // Set Cursor Start Register by writting to CRTCtl Data Register
  1408. // Preserve the high three bits of this register.
  1409. //
  1410. // Only the Five low bits are used for the cursor height.
  1411. // Bit 5 is cursor enable, bit 6 and 7 preserved.
  1412. //
  1413. cursorLine = (UCHAR) CursorAttributes->Height & 0x1F;
  1414. cursorLine |= VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1415. CRTC_DATA_PORT_COLOR) & 0xC0;
  1416. if (!CursorAttributes->Enable) {
  1417. cursorLine |= 0x20; // Flip cursor off bit
  1418. }
  1419. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + CRTC_DATA_PORT_COLOR,
  1420. cursorLine);
  1421. //
  1422. // Address Cursor End Register in CRT Controller Registers
  1423. //
  1424. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1425. CRTC_ADDRESS_PORT_COLOR,
  1426. IND_CURSOR_END);
  1427. //
  1428. // Set Cursor End Register. Preserve the high three bits of this
  1429. // register.
  1430. //
  1431. cursorLine =
  1432. (CursorAttributes->Width < (USHORT)(HwDeviceExtension->FontPelRows - 1)) ?
  1433. CursorAttributes->Width : (HwDeviceExtension->FontPelRows - 1);
  1434. cursorLine &= 0x1f;
  1435. cursorLine |= VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1436. CRTC_DATA_PORT_COLOR) & 0xE0;
  1437. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + CRTC_DATA_PORT_COLOR,
  1438. cursorLine);
  1439. return NO_ERROR;
  1440. } // end VgaSetCursorAttributes()
  1441. BOOLEAN
  1442. VgaIsPresent(
  1443. PHW_DEVICE_EXTENSION HwDeviceExtension
  1444. )
  1445. /*++
  1446. Routine Description:
  1447. This routine returns TRUE if a VGA is present. Determining whether a VGA
  1448. is present is a two-step process. First, this routine walks bits through
  1449. the Bit Mask register, to establish that there are readable indexed
  1450. registers (EGAs normally don't have readable registers, and other adapters
  1451. are unlikely to have indexed registers). This test is done first because
  1452. it's a non-destructive EGA rejection test (correctly rejects EGAs, but
  1453. doesn't potentially mess up the screen or the accessibility of display
  1454. memory). Normally, this would be an adequate test, but some EGAs have
  1455. readable registers, so next, we check for the existence of the Chain4 bit
  1456. in the Memory Mode register; this bit doesn't exist in EGAs. It's
  1457. conceivable that there are EGAs with readable registers and a register bit
  1458. where Chain4 is stored, although I don't know of any; if a better test yet
  1459. is needed, memory could be written to in Chain4 mode, and then examined
  1460. plane by plane in non-Chain4 mode to make sure the Chain4 bit did what it's
  1461. supposed to do. However, the current test should be adequate to eliminate
  1462. just about all EGAs, and 100% of everything else.
  1463. If this function fails to find a VGA, it attempts to undo any damage it
  1464. may have inadvertently done while testing. The underlying assumption for
  1465. the damage control is that if there's any non-VGA adapter at the tested
  1466. ports, it's an EGA or an enhanced EGA, because: a) I don't know of any
  1467. other adapters that use 3C4/5 or 3CE/F, and b), if there are other
  1468. adapters, I certainly don't know how to restore their original states. So
  1469. all error recovery is oriented toward putting an EGA back in a writable
  1470. state, so that error messages are visible. The EGA's state on entry is
  1471. assumed to be text mode, so the Memory Mode register is restored to the
  1472. default state for text mode.
  1473. If a VGA is found, the VGA is returned to its original state after
  1474. testing is finished.
  1475. Arguments:
  1476. None.
  1477. Return Value:
  1478. TRUE if a VGA is present, FALSE if not.
  1479. --*/
  1480. {
  1481. UCHAR originalGCAddr;
  1482. UCHAR originalSCAddr;
  1483. UCHAR originalBitMask;
  1484. UCHAR originalReadMap;
  1485. UCHAR originalMemoryMode;
  1486. UCHAR testMask;
  1487. BOOLEAN returnStatus;
  1488. //
  1489. // Remember the original state of the Graphics Controller Address register.
  1490. //
  1491. originalGCAddr = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1492. GRAPH_ADDRESS_PORT);
  1493. //
  1494. // Write the Read Map register with a known state so we can verify
  1495. // that it isn't changed after we fool with the Bit Mask. This ensures
  1496. // that we're dealing with indexed registers, since both the Read Map and
  1497. // the Bit Mask are addressed at GRAPH_DATA_PORT.
  1498. //
  1499. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1500. GRAPH_ADDRESS_PORT, IND_READ_MAP);
  1501. //
  1502. // If we can't read back the Graphics Address register setting we just
  1503. // performed, it's not readable and this isn't a VGA.
  1504. //
  1505. if ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1506. GRAPH_ADDRESS_PORT) & GRAPH_ADDR_MASK) != IND_READ_MAP) {
  1507. return FALSE;
  1508. }
  1509. //
  1510. // Set the Read Map register to a known state.
  1511. //
  1512. originalReadMap = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1513. GRAPH_DATA_PORT);
  1514. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1515. GRAPH_DATA_PORT, READ_MAP_TEST_SETTING);
  1516. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1517. GRAPH_DATA_PORT) != READ_MAP_TEST_SETTING) {
  1518. //
  1519. // The Read Map setting we just performed can't be read back; not a
  1520. // VGA. Restore the default Read Map state.
  1521. //
  1522. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1523. GRAPH_DATA_PORT, READ_MAP_DEFAULT);
  1524. return FALSE;
  1525. }
  1526. //
  1527. // Remember the original setting of the Bit Mask register.
  1528. //
  1529. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1530. GRAPH_ADDRESS_PORT, IND_BIT_MASK);
  1531. if ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1532. GRAPH_ADDRESS_PORT) & GRAPH_ADDR_MASK) != IND_BIT_MASK) {
  1533. //
  1534. // The Graphics Address register setting we just made can't be read
  1535. // back; not a VGA. Restore the default Read Map state.
  1536. //
  1537. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1538. GRAPH_ADDRESS_PORT, IND_READ_MAP);
  1539. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1540. GRAPH_DATA_PORT, READ_MAP_DEFAULT);
  1541. return FALSE;
  1542. }
  1543. originalBitMask = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1544. GRAPH_DATA_PORT);
  1545. //
  1546. // Set up the initial test mask we'll write to and read from the Bit Mask.
  1547. //
  1548. testMask = 0xBB;
  1549. do {
  1550. //
  1551. // Write the test mask to the Bit Mask.
  1552. //
  1553. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1554. GRAPH_DATA_PORT, testMask);
  1555. //
  1556. // Make sure the Bit Mask remembered the value.
  1557. //
  1558. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1559. GRAPH_DATA_PORT) != testMask) {
  1560. //
  1561. // The Bit Mask is not properly writable and readable; not a VGA.
  1562. // Restore the Bit Mask and Read Map to their default states.
  1563. //
  1564. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1565. GRAPH_DATA_PORT, BIT_MASK_DEFAULT);
  1566. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1567. GRAPH_ADDRESS_PORT, IND_READ_MAP);
  1568. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1569. GRAPH_DATA_PORT, READ_MAP_DEFAULT);
  1570. return FALSE;
  1571. }
  1572. //
  1573. // Cycle the mask for next time.
  1574. //
  1575. testMask >>= 1;
  1576. } while (testMask != 0);
  1577. //
  1578. // There's something readable at GRAPH_DATA_PORT; now switch back and
  1579. // make sure that the Read Map register hasn't changed, to verify that
  1580. // we're dealing with indexed registers.
  1581. //
  1582. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1583. GRAPH_ADDRESS_PORT, IND_READ_MAP);
  1584. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1585. GRAPH_DATA_PORT) != READ_MAP_TEST_SETTING) {
  1586. //
  1587. // The Read Map is not properly writable and readable; not a VGA.
  1588. // Restore the Bit Mask and Read Map to their default states, in case
  1589. // this is an EGA, so subsequent writes to the screen aren't garbled.
  1590. //
  1591. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1592. GRAPH_DATA_PORT, READ_MAP_DEFAULT);
  1593. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1594. GRAPH_ADDRESS_PORT, IND_BIT_MASK);
  1595. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1596. GRAPH_DATA_PORT, BIT_MASK_DEFAULT);
  1597. return FALSE;
  1598. }
  1599. //
  1600. // We've pretty surely verified the existence of the Bit Mask register.
  1601. // Put the Graphics Controller back to the original state.
  1602. //
  1603. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1604. GRAPH_DATA_PORT, originalReadMap);
  1605. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1606. GRAPH_ADDRESS_PORT, IND_BIT_MASK);
  1607. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1608. GRAPH_DATA_PORT, originalBitMask);
  1609. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1610. GRAPH_ADDRESS_PORT, originalGCAddr);
  1611. //
  1612. // Now, check for the existence of the Chain4 bit.
  1613. //
  1614. //
  1615. // Remember the original states of the Sequencer Address and Memory Mode
  1616. // registers.
  1617. //
  1618. originalSCAddr = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1619. SEQ_ADDRESS_PORT);
  1620. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1621. SEQ_ADDRESS_PORT, IND_MEMORY_MODE);
  1622. if ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1623. SEQ_ADDRESS_PORT) & SEQ_ADDR_MASK) != IND_MEMORY_MODE) {
  1624. //
  1625. // Couldn't read back the Sequencer Address register setting we just
  1626. // performed.
  1627. //
  1628. return FALSE;
  1629. }
  1630. originalMemoryMode = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1631. SEQ_DATA_PORT);
  1632. //
  1633. // Toggle the Chain4 bit and read back the result. This must be done during
  1634. // sync reset, since we're changing the chaining state.
  1635. //
  1636. //
  1637. // Begin sync reset.
  1638. //
  1639. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  1640. SEQ_ADDRESS_PORT),
  1641. (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8)));
  1642. //
  1643. // Toggle the Chain4 bit.
  1644. //
  1645. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1646. SEQ_ADDRESS_PORT, IND_MEMORY_MODE);
  1647. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1648. SEQ_DATA_PORT, (UCHAR)(originalMemoryMode ^ CHAIN4_MASK));
  1649. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1650. SEQ_DATA_PORT) != (UCHAR) (originalMemoryMode ^ CHAIN4_MASK)) {
  1651. //
  1652. // Chain4 bit not there; not a VGA.
  1653. // Set text mode default for Memory Mode register.
  1654. //
  1655. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1656. SEQ_DATA_PORT, MEMORY_MODE_TEXT_DEFAULT);
  1657. //
  1658. // End sync reset.
  1659. //
  1660. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  1661. SEQ_ADDRESS_PORT),
  1662. (IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8)));
  1663. returnStatus = FALSE;
  1664. } else {
  1665. //
  1666. // It's a VGA.
  1667. //
  1668. //
  1669. // Restore the original Memory Mode setting.
  1670. //
  1671. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1672. SEQ_DATA_PORT, originalMemoryMode);
  1673. //
  1674. // End sync reset.
  1675. //
  1676. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  1677. SEQ_ADDRESS_PORT),
  1678. (USHORT)(IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8)));
  1679. //
  1680. // Restore the original Sequencer Address setting.
  1681. //
  1682. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1683. SEQ_ADDRESS_PORT, originalSCAddr);
  1684. returnStatus = TRUE;
  1685. }
  1686. return returnStatus;
  1687. } // VgaIsPresent()
  1688. BOOLEAN
  1689. ET4000IsPresent(
  1690. PHW_DEVICE_EXTENSION HwDeviceExtension
  1691. )
  1692. /*++
  1693. Routine Description:
  1694. This routine returns TRUE if an ET4000 is present. It assumes that it's
  1695. already been established that a VGA is present. It performs the Tseng
  1696. Labs-recommended ID test: we try to enable the extension registers, toggle
  1697. AC16 bit 4, and modify CRTC33. If all this works, then this is indeed an
  1698. ET4000.
  1699. If this function fails to find an ET4000, it attempts to undo any damage it
  1700. may have inadvertently done while testing. Because unlocking the
  1701. extensions involves touching the CGA/Mono Mode and Hercules Compatibility
  1702. registers, we'll restore them to their default states in case there's
  1703. one of those adapters or something emulating them at those addresses.
  1704. If an ET4000 is found, the adapter is returned to its original state after
  1705. testing is finished, except that extensions are left disabled.
  1706. Arguments:
  1707. None.
  1708. Return Value:
  1709. TRUE if an ET4000 is present, FALSE if not.
  1710. --*/
  1711. {
  1712. //
  1713. // SpeedSTAR message somewhere in first 4K of ROM (s/b around 0Axx)
  1714. //
  1715. #define MAX_ROM_SCAN 4096
  1716. UCHAR originalACIndex;
  1717. UCHAR originalAC16;
  1718. UCHAR originalCRTCIndex;
  1719. UCHAR originalCRTC33;
  1720. UCHAR temp1, temp2;
  1721. UCHAR videoEnable;
  1722. ULONG CRTCAddressPort, CRTCDataPort;
  1723. UCHAR *pRomAddr;
  1724. PHYSICAL_ADDRESS paRom = {0x000C0000,0x00000000};
  1725. PWSTR pwszChip, pwszAdapterString;
  1726. ULONG cbChip, cbAdapterString;
  1727. //
  1728. // Unlock the ET4000 extended registers.
  1729. //
  1730. UnlockET4000ExtendedRegs(HwDeviceExtension);
  1731. //
  1732. // Try to toggle AC16, bit 4.
  1733. //
  1734. ResetACToggle(HwDeviceExtension); // set the AC toggle to the Index state
  1735. //
  1736. // Save the original state of the AC Index.
  1737. //
  1738. originalACIndex = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1739. ATT_ADDRESS_PORT);
  1740. //
  1741. // Remember whether video was enabled or not.
  1742. //
  1743. videoEnable = originalACIndex & VIDEO_ENABLE;
  1744. //
  1745. // Try to toggle AC16, bit 4.
  1746. //
  1747. ResetACToggle(HwDeviceExtension); // set the AC toggle to the Index state
  1748. //
  1749. // Set the AC Index to 0x16.
  1750. //
  1751. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ATT_ADDRESS_PORT,
  1752. (UCHAR)(videoEnable | 0x16));
  1753. //
  1754. // Save the original state of AC register 16.
  1755. //
  1756. originalAC16 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1757. ATT_DATA_READ_PORT);
  1758. //
  1759. // Write one possible AC16 bit 4 state and read it back.
  1760. //
  1761. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1762. ATT_DATA_WRITE_PORT, (UCHAR) (originalAC16 ^ 0x10));
  1763. temp1 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1764. ATT_DATA_READ_PORT);
  1765. //
  1766. // Write the other possible AC16 bit 4 state and read it back. This also
  1767. // restores the original state of AC16.
  1768. //
  1769. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ATT_ADDRESS_PORT,
  1770. (UCHAR) (videoEnable | 0x16));
  1771. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1772. ATT_DATA_WRITE_PORT, originalAC16);
  1773. temp2 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1774. ATT_DATA_READ_PORT);
  1775. //
  1776. // Restore the original AC Index.
  1777. //
  1778. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1779. ATT_ADDRESS_PORT, originalACIndex);
  1780. //
  1781. // See if AC16 bit 4 toggled properly.
  1782. //
  1783. if ((temp2 != originalAC16) || (temp1 != (UCHAR) (originalAC16 ^ 0x10))) {
  1784. //
  1785. // Didn't toggle properly; not an ET4000.
  1786. //
  1787. //
  1788. // Restore CGA/MDA and Hercules registers that were potentially written
  1789. // to by the extensions enable sequence.
  1790. //
  1791. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1792. HERCULES_COMPATIBILITY_PORT, HERCULES_COMPATIBILITY_DEFAULT);
  1793. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1794. MISC_OUTPUT_REG_READ_PORT) & 0x01) {
  1795. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1796. MODE_CONTROL_PORT_COLOR, MODE_CONTROL_PORT_COLOR_DEFAULT);
  1797. } else {
  1798. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1799. MODE_CONTROL_PORT_MONO, MODE_CONTROL_PORT_MONO_DEFAULT);
  1800. }
  1801. return FALSE;
  1802. }
  1803. //
  1804. // At this point, it's either an ET3000 or an ET4000. See if CRTC33 is
  1805. // read/writable; if it is, this is an ET4000.
  1806. //
  1807. //
  1808. // Determine where the CRTC registers are addressed (color or mono).
  1809. //
  1810. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1811. MISC_OUTPUT_REG_READ_PORT) & 0x01) {
  1812. CRTCAddressPort = CRTC_ADDRESS_PORT_COLOR;
  1813. CRTCDataPort = CRTC_DATA_PORT_COLOR;
  1814. } else {
  1815. CRTCAddressPort = CRTC_ADDRESS_PORT_MONO;
  1816. CRTCDataPort = CRTC_DATA_PORT_MONO;
  1817. }
  1818. //
  1819. // Save the original state of the CRTC Index.
  1820. //
  1821. originalCRTCIndex = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1822. CRTCAddressPort);
  1823. //
  1824. // Try to modify CRTC33.
  1825. //
  1826. //
  1827. // Set the CRTC Index to 0x33.
  1828. //
  1829. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + CRTCAddressPort,
  1830. 0x33);
  1831. //
  1832. // Save the original state of CRTC register 33.
  1833. //
  1834. originalCRTC33 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1835. CRTCDataPort);
  1836. //
  1837. // Write out inverted CRTC33 state and read it back.
  1838. //
  1839. temp2 = ~originalCRTC33;
  1840. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + CRTCDataPort, temp2);
  1841. temp1 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1842. CRTCDataPort);
  1843. //
  1844. // Restore the original CRTC33 state.
  1845. //
  1846. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + CRTCDataPort,
  1847. originalCRTC33);
  1848. //
  1849. // Restore the original CRTC Index.
  1850. //
  1851. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + CRTCAddressPort,
  1852. originalCRTCIndex);
  1853. //
  1854. // Leave the Tseng extended registers locked.
  1855. //
  1856. LockET4000ExtendedRegs(HwDeviceExtension);
  1857. //
  1858. // See how CRTC33 changed.
  1859. //
  1860. // if all bits the same than must be W32, if just bits 0-3 then ET4000
  1861. // otherwise must be an ET3000
  1862. //
  1863. if (temp1 == temp2) {
  1864. UCHAR jID;
  1865. HwDeviceExtension->BoardID = TSENG4000W32;
  1866. pwszAdapterString = L"TSENG ET4000W32 Compatible";
  1867. cbAdapterString = sizeof(L"TSENG ET4000W32 Compatible");
  1868. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  1869. CRTCB_IO_PORT_INDEX,
  1870. IND_CRTCB_CHIP_ID);
  1871. {
  1872. UCHAR vfy;
  1873. vfy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1874. CRTCB_IO_PORT_INDEX);
  1875. if (vfy != IND_CRTCB_CHIP_ID)
  1876. {
  1877. VideoDebugPrint((1,"Write to CRTCB_IO_PORT_INDEX didn't work\n"));
  1878. VideoDebugPrint((1,"Wrote 0x%x, read back 0x%x\n", IND_CRTCB_CHIP_ID, vfy));
  1879. }
  1880. }
  1881. jID = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  1882. CRTCB_IO_PORT_DATA);
  1883. jID = (jID >> 4) & 0xF;
  1884. switch (jID) {
  1885. case 0x00: // W32 Rev Undefined
  1886. pwszChip = L"W32";
  1887. cbChip = sizeof(L"W32");
  1888. HwDeviceExtension->ulChipID = W32;
  1889. HwDeviceExtension->ulRevLevel = REV_UNDEF;
  1890. break;
  1891. case 0x01: // W32i Rev A
  1892. pwszChip = L"W32i, rev A";
  1893. cbChip = sizeof(L"W32i, rev A");
  1894. HwDeviceExtension->ulChipID = W32I;
  1895. HwDeviceExtension->ulRevLevel = REV_A;
  1896. break;
  1897. case 0x02: // W32p Rev A
  1898. pwszChip = L"W32p, rev A";
  1899. cbChip = sizeof(L"W32p, rev A");
  1900. HwDeviceExtension->ulChipID = W32P;
  1901. HwDeviceExtension->ulRevLevel = REV_A;
  1902. break;
  1903. case 0x03: // W32i Rev B
  1904. pwszChip = L"W32i, rev B";
  1905. cbChip = sizeof(L"W32i, rev B");
  1906. HwDeviceExtension->ulChipID = W32I;
  1907. HwDeviceExtension->ulRevLevel = REV_B;
  1908. break;
  1909. case 0x05: // W32p Rev B
  1910. pwszChip = L"W32p, rev B";
  1911. cbChip = sizeof(L"W32p, rev B");
  1912. HwDeviceExtension->ulChipID = W32P;
  1913. HwDeviceExtension->ulRevLevel = REV_B;
  1914. break;
  1915. case 0x06: // W32p Rev D
  1916. pwszChip = L"W32p, rev D";
  1917. cbChip = sizeof(L"W32p, rev D");
  1918. HwDeviceExtension->ulChipID = W32P;
  1919. HwDeviceExtension->ulRevLevel = REV_D;
  1920. break;
  1921. case 0x07: // W32p Rev C
  1922. pwszChip = L"W32p, rev C";
  1923. cbChip = sizeof(L"W32p, rev C");
  1924. HwDeviceExtension->ulChipID = W32P;
  1925. HwDeviceExtension->ulRevLevel = REV_C;
  1926. break;
  1927. case 0x0b: // W32i Rev C
  1928. //
  1929. // This puppy is rare (non production)
  1930. //
  1931. pwszChip = L"W32i, rev C";
  1932. cbChip = sizeof(L"W32i, rev C");
  1933. HwDeviceExtension->ulChipID = W32I;
  1934. HwDeviceExtension->ulRevLevel = REV_C;
  1935. break;
  1936. default:
  1937. //
  1938. // it must be a new rev of one of the W32 chips
  1939. //
  1940. pwszChip = L"W32 family, ID unknown";
  1941. cbChip = sizeof(L"W32 family, ID unknown");
  1942. //
  1943. // NOTE: Assume any unidentified W32 must be a W32p or newer
  1944. //
  1945. HwDeviceExtension->ulChipID = W32P;
  1946. HwDeviceExtension->ulRevLevel = REV_C;
  1947. VideoDebugPrint((1,"The video chip cannot be identified (0x%x)\n", jID));
  1948. break;
  1949. }
  1950. } else {
  1951. if ((temp1 & 0xf) == (temp2 & 0xf)) {
  1952. HwDeviceExtension->BoardID = TSENG4000;
  1953. pwszAdapterString = L"TSENG ET4000 Compatible";
  1954. cbAdapterString = sizeof(L"TSENG ET4000 Compatible");
  1955. HwDeviceExtension->ulChipID = ET4000;
  1956. HwDeviceExtension->ulRevLevel = REV_UNDEF;
  1957. pwszChip = L"ET4000";
  1958. cbChip = sizeof(L"ET4000");
  1959. } else {
  1960. //
  1961. // Didn't change properly; not an ET4000.
  1962. //
  1963. HwDeviceExtension->BoardID = TSENG3000;
  1964. HwDeviceExtension->ulChipID = ET3000;
  1965. HwDeviceExtension->ulRevLevel = REV_UNDEF;
  1966. VideoDebugPrint((1, "ET4000 not found\n"));
  1967. return FALSE;
  1968. }
  1969. }
  1970. //
  1971. // It *is* an ET4000 or a W32!
  1972. //
  1973. //
  1974. // Map in the ROM address space at 0xc000:0
  1975. //
  1976. pRomAddr = VideoPortGetDeviceBase(HwDeviceExtension,
  1977. paRom,
  1978. MAX_ROM_SCAN,
  1979. FALSE);
  1980. if (pRomAddr) { // Valid ROM address?
  1981. //
  1982. // Look for brand name signatures (from DIAMOND) in the ROM.
  1983. //
  1984. //
  1985. // We will try to recognize a few boards.
  1986. // make sure we are looking at a bios!
  1987. //
  1988. //if (*((PUSHORT) pRomAddr) == 0xAA55) {
  1989. if (VideoPortReadRegisterUshort((PUSHORT)pRomAddr) == 0xAA55) {
  1990. if (VideoPortScanRom(HwDeviceExtension,
  1991. pRomAddr,
  1992. MAX_ROM_SCAN,
  1993. "Stealth 32 ")) {
  1994. HwDeviceExtension->BoardID = STEALTH32;
  1995. pwszAdapterString = L"Diamond Stealth 32";
  1996. cbAdapterString = sizeof(L"Diamond Stealth 32");
  1997. } else if (VideoPortScanRom(HwDeviceExtension,
  1998. pRomAddr,
  1999. MAX_ROM_SCAN,
  2000. "SpeedSTAR 24 ")) {
  2001. HwDeviceExtension->BoardID = SPEEDSTAR24;
  2002. pwszAdapterString = L"Diamond SpeedSTAR 24";
  2003. cbAdapterString = sizeof(L"Diamond SpeedSTAR 24");
  2004. } else if (VideoPortScanRom(HwDeviceExtension,
  2005. pRomAddr,
  2006. MAX_ROM_SCAN,
  2007. "SpeedSTAR Plus ")) {
  2008. HwDeviceExtension->BoardID = SPEEDSTARPLUS;
  2009. pwszAdapterString = L"Diamond SpeedSTAR Plus";
  2010. cbAdapterString = sizeof(L"Diamond SpeedSTAR Plus");
  2011. } else if (VideoPortScanRom(HwDeviceExtension,
  2012. pRomAddr,
  2013. MAX_ROM_SCAN,
  2014. "SpeedSTAR ")) {
  2015. HwDeviceExtension->BoardID = SPEEDSTAR;
  2016. pwszAdapterString = L"Diamond SpeedSTAR";
  2017. cbAdapterString = sizeof(L"Diamond SpeedSTAR");
  2018. } else if (VideoPortScanRom(HwDeviceExtension,
  2019. pRomAddr,
  2020. MAX_ROM_SCAN,
  2021. "ProDesigner IIs/EISA")) {
  2022. HwDeviceExtension->BoardID = PRODESIGNERIISEISA;
  2023. pwszAdapterString = L"Orchid ProDesigner IIs/EISA";
  2024. cbAdapterString = sizeof(L"Orchid ProDesigner IIs/EISA");
  2025. } else if (VideoPortScanRom(HwDeviceExtension,
  2026. pRomAddr,
  2027. MAX_ROM_SCAN,
  2028. "ProDesigner IIs")) {
  2029. HwDeviceExtension->BoardID = PRODESIGNERIIS;
  2030. pwszAdapterString = L"Orchid ProDesigner IIs";
  2031. cbAdapterString = sizeof(L"Orchid ProDesigner IIs");
  2032. } else if (VideoPortScanRom(HwDeviceExtension,
  2033. pRomAddr,
  2034. MAX_ROM_SCAN,
  2035. "ProDesigner II")) {
  2036. HwDeviceExtension->BoardID = PRODESIGNER2;
  2037. pwszAdapterString = L"Orchid ProDesigner II";
  2038. cbAdapterString = sizeof(L"Orchid ProDesigner II");
  2039. }
  2040. }
  2041. VideoPortFreeDeviceBase(HwDeviceExtension, pRomAddr);
  2042. }
  2043. //
  2044. // Get the adapter memory size
  2045. //
  2046. HwDeviceExtension->AdapterMemorySize =
  2047. ET4000GetMemorySize(HwDeviceExtension);
  2048. //
  2049. // Finally, just validate the list of modes.
  2050. //
  2051. VgaValidateModes(HwDeviceExtension);
  2052. //
  2053. // We now have a complete hardware description of the hardware.
  2054. // Save the information to the registry so it can be used by
  2055. // configuration programs - such as the display applet
  2056. //
  2057. VideoPortSetRegistryParameters(HwDeviceExtension,
  2058. L"HardwareInformation.ChipType",
  2059. pwszChip,
  2060. cbChip);
  2061. VideoPortSetRegistryParameters(HwDeviceExtension,
  2062. L"HardwareInformation.MemorySize",
  2063. &HwDeviceExtension->AdapterMemorySize,
  2064. sizeof(ULONG));
  2065. VideoPortSetRegistryParameters(HwDeviceExtension,
  2066. L"HardwareInformation.AdapterString",
  2067. pwszAdapterString,
  2068. cbAdapterString);
  2069. return TRUE;
  2070. } // Et4000IsPresent()
  2071. ULONG
  2072. ET4000GetMemorySize(
  2073. PHW_DEVICE_EXTENSION HwDeviceExtension
  2074. )
  2075. /*++
  2076. Routine Description:
  2077. This routine returns the amount of memory in bytes on the ET4000 based
  2078. device. It assumes that it has already been established that an ET4000
  2079. is present.
  2080. Arguments:
  2081. None.
  2082. Return Value:
  2083. Device Memory Size in Bytes (256K, 512K, 1M, 2M, or 4M).
  2084. --*/
  2085. {
  2086. UCHAR originalCRTCIndex;
  2087. UCHAR VideoSystemConfig2;
  2088. USHORT Width32, factor, SizeInfo;
  2089. ULONG CRTCAddressPort, CRTCDataPort;
  2090. ULONG Size;
  2091. //
  2092. // Unlock the ET4000 extended registers.
  2093. //
  2094. UnlockET4000ExtendedRegs(HwDeviceExtension);
  2095. //
  2096. // Determine where the CRTC registers are addressed (color or mono).
  2097. //
  2098. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2099. MISC_OUTPUT_REG_READ_PORT) & 0x01) {
  2100. CRTCAddressPort = CRTC_ADDRESS_PORT_COLOR;
  2101. CRTCDataPort = CRTC_DATA_PORT_COLOR;
  2102. } else {
  2103. CRTCAddressPort = CRTC_ADDRESS_PORT_MONO;
  2104. CRTCDataPort = CRTC_DATA_PORT_MONO;
  2105. }
  2106. //
  2107. // Save the original state of the CRTC Index.
  2108. //
  2109. originalCRTCIndex = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2110. CRTCAddressPort);
  2111. //
  2112. // Set the CRTC Index to Video System Configuration Register 2
  2113. //
  2114. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + CRTCAddressPort,
  2115. IND_VID_SYS_CONFIG_2);
  2116. //
  2117. // Get the Config 2 reg
  2118. //
  2119. VideoSystemConfig2 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2120. CRTCDataPort);
  2121. //
  2122. // The ET4000/W32 and ET4000/AX have different register settings for
  2123. // determining memory size.
  2124. //
  2125. if (HwDeviceExtension->ulChipID >= W32) {
  2126. // It's a W32
  2127. //
  2128. // memory bus width determines whether to factor up by 2x
  2129. //
  2130. Width32 = (VideoSystemConfig2 & 1);
  2131. //
  2132. // Set up minimum memory size and determine multiplier factors
  2133. // based on Dram type and bus width
  2134. //
  2135. Size = 0x80000;
  2136. //
  2137. // check DRAM type
  2138. //
  2139. if (VideoSystemConfig2 & 0x8) { // either 256Kxn or 512Kxn
  2140. // We can determine if the chip type is 256Kxn by checking if
  2141. // mem location 0 is the same as memory location 512K (16 bit mem)
  2142. // or 1M (32 bit) (256K chips don't have ROW_ADR<9>)
  2143. if (ET4000w32With256KDrams(HwDeviceExtension,(USHORT) (8 << Width32)))
  2144. factor = 1;
  2145. else
  2146. // 512K drams
  2147. factor = 2;
  2148. }
  2149. else {
  2150. // 1M drams
  2151. factor = 4;
  2152. }
  2153. // calculate size based on factor and bus width
  2154. Size *= (factor << Width32);
  2155. VideoDebugPrint((1, "\nET4000GetMemorySize(w32): size(%08x),factor(%d),width32(%d)\n\n",Size,factor,Width32));
  2156. } else {
  2157. // ET4000 (not w32)
  2158. // Assume 256K (ie. either 64K Drams or VideoConfig2 (bits 0-1) == 1)
  2159. Size = 0x40000;
  2160. if (VideoSystemConfig2 & 8) { // Not 64K chips
  2161. // bits 0-1 indicate memory size 3=>1M, 2=>512K, 1=>256K
  2162. // (except 2 w/ VRAM might be 1M)
  2163. SizeInfo = (VideoSystemConfig2 & 3);
  2164. if (SizeInfo > 2)
  2165. Size = 0x100000;
  2166. else if (SizeInfo == 2) {
  2167. // Check VRAM bit
  2168. if (VideoSystemConfig2 & 0x80)
  2169. // Has VRAM - Check for 1 Meg
  2170. Size = (ET4000With1MegMemory(HwDeviceExtension))
  2171. ? 0x100000 : 0x80000;
  2172. else
  2173. Size = 0x80000;
  2174. }
  2175. }
  2176. VideoDebugPrint((1, "ET4000GetMemorySize(non-w32): size(%08x)\n",Size));
  2177. } // ET4000
  2178. //
  2179. // Restore the original CRTC Index.
  2180. //
  2181. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + CRTCAddressPort,
  2182. originalCRTCIndex);
  2183. //
  2184. // Leave the Tseng extended registers locked.
  2185. //
  2186. LockET4000ExtendedRegs(HwDeviceExtension);
  2187. // Give'm what they asked for
  2188. return Size;
  2189. } // Et4000GetMemorySize()
  2190. BOOLEAN
  2191. ET6000IsPresent(
  2192. PHW_DEVICE_EXTENSION HwDeviceExtension,
  2193. PVIDEO_ACCESS_RANGE pAccessRange
  2194. )
  2195. /*++
  2196. Routine Description:
  2197. This routine returns TRUE if an ET6000 is present. It assumes that it's
  2198. already been established that a VGA is present. It will look at the PCI
  2199. vendor and chip ID registers to identify the board.
  2200. Arguments:
  2201. Input: hwDeviceExtension
  2202. Return Value:
  2203. TRUE if an ET6000 is present, FALSE if not.
  2204. --*/
  2205. {
  2206. VP_STATUS status;
  2207. UCHAR originalCRTCIndex;
  2208. UCHAR videoEnable;
  2209. ULONG CRTCAddressPort, CRTCDataPort;
  2210. UCHAR temp;
  2211. PWSTR pwszChip, pwszAdapterString;
  2212. ULONG cbChip = 0, cbAdapterString = 0;
  2213. VIDEO_ACCESS_RANGE PCIAccessRanges[3];
  2214. ULONG ulSlot = 0;
  2215. USHORT usDeviceId = ET6000_DEVICE_ID;
  2216. USHORT usVendorId = ET6000_VENDOR_ID;
  2217. ULONG Address = 0;
  2218. UCHAR bits;
  2219. BOOLEAN bIsET4000 = FALSE;
  2220. PCI_COMMON_CONFIG ConfigData; /* Configuration information about PCI device */
  2221. if (VideoPortGetAccessRanges(HwDeviceExtension,
  2222. 0,
  2223. NULL,
  2224. 3,
  2225. PCIAccessRanges,
  2226. &usVendorId,
  2227. &usDeviceId,
  2228. &ulSlot) != NO_ERROR)
  2229. {
  2230. VideoDebugPrint((1, "Did not find an ET6000 in any pci slot\n"));
  2231. return FALSE;
  2232. }
  2233. else
  2234. {
  2235. VideoDebugPrint((1,"Found an ETX000 in pci slot %d\n", ulSlot));
  2236. HwDeviceExtension->ulSlot = ulSlot;
  2237. VideoPortGetBusData(HwDeviceExtension,
  2238. PCIConfiguration,
  2239. ulSlot,
  2240. (PVOID) &ConfigData,
  2241. 0,
  2242. sizeof(ULONG));
  2243. //
  2244. // Check for either 4000 or 6000!!!
  2245. //
  2246. if ((ConfigData.DeviceID == 0x3202 ) ||
  2247. (ConfigData.DeviceID == 0x3206 ) ||
  2248. (ConfigData.DeviceID == 0x3207))
  2249. {
  2250. VideoDebugPrint((1,"Found an ET4000 in pci slot %d\n", ulSlot));
  2251. bIsET4000 = TRUE;
  2252. HwDeviceExtension->BoardID = W32P;
  2253. pwszChip = L"ET4000";
  2254. cbChip = sizeof(L"ET4000");
  2255. pwszAdapterString = L"TSENG ET4000 Compatible";
  2256. cbAdapterString = sizeof(L"TSENG ET4000 Compatible");
  2257. HwDeviceExtension->ulChipID = ET4000;
  2258. HwDeviceExtension->ulRevLevel = REV_UNDEF;
  2259. }
  2260. else if (ConfigData.DeviceID == ET6000_DEVICE_ID )
  2261. {
  2262. VideoDebugPrint((1,"Found an ET6000 in pci slot %d\n", ulSlot));
  2263. pwszChip = L"ET6000";
  2264. cbChip = sizeof(L"ET6000");
  2265. pwszAdapterString = L"ET6000";
  2266. cbAdapterString = sizeof(L"ET6000");
  2267. HwDeviceExtension->ulChipID = ET6000;
  2268. HwDeviceExtension->ulRevLevel = REV_UNDEF;
  2269. HwDeviceExtension->BoardID = TSENG6000;
  2270. }
  2271. else
  2272. {
  2273. ASSERT(FALSE);
  2274. }
  2275. }
  2276. //
  2277. // Store the location of the linear frame buffer in the
  2278. // HwDeviceExtension.
  2279. //
  2280. // The frame buffer is returned in location 0. We do not
  2281. // need to store any of the other access ranges which
  2282. // may have been returned.
  2283. //
  2284. pAccessRange[LINEAR_FRAME_BUFFER].RangeStart = PCIAccessRanges[0].RangeStart;
  2285. pAccessRange[LINEAR_FRAME_BUFFER].RangeLength = PCIAccessRanges[0].RangeLength;
  2286. //
  2287. // Modify the entries in the RangeOffset array. This array
  2288. // contains offsets within the frame buffer from which
  2289. // to map access ranges.
  2290. //
  2291. RangeOffsets[1][0].ulOffset += PCIAccessRanges[0].RangeStart.LowPart;
  2292. RangeOffsets[1][1].ulOffset += PCIAccessRanges[0].RangeStart.LowPart;
  2293. //
  2294. // Make sure the frame buffer access range is stored in the
  2295. // pci configuration space.
  2296. //
  2297. VideoPortGetBusData(HwDeviceExtension,
  2298. PCIConfiguration,
  2299. ulSlot,
  2300. (PVOID) &Address,
  2301. FIELD_OFFSET(PCI_COMMON_CONFIG, u.type0.BaseAddresses),
  2302. sizeof(ULONG));
  2303. if (!bIsET4000 && (Address != PCIAccessRanges[0].RangeStart.LowPart))
  2304. {
  2305. VideoDebugPrint((1, "I really wish they we're equal, but\n"
  2306. "they're not, so make them equal!\n"));
  2307. VideoPortSetBusData(HwDeviceExtension,
  2308. PCIConfiguration,
  2309. ulSlot,
  2310. (PVOID) &PCIAccessRanges[0].RangeStart.LowPart,
  2311. FIELD_OFFSET(PCI_COMMON_CONFIG, u.type0.BaseAddresses),
  2312. sizeof(ULONG));
  2313. }
  2314. //
  2315. // We now have a complete hardware description of the hardware.
  2316. // Sa ve the information to the registry so it can be used by
  2317. // co nfiguration programs - such as the display applet
  2318. //
  2319. if (cbChip)
  2320. {
  2321. VideoPortSetRegistryParameters(HwDeviceExtension,
  2322. L"HardwareInformation.ChipType",
  2323. pwszChip,
  2324. cbChip);
  2325. }
  2326. if (cbAdapterString)
  2327. {
  2328. VideoPortSetRegistryParameters(HwDeviceExtension,
  2329. L"HardwareInformation.AdapterString",
  2330. pwszAdapterString,
  2331. cbAdapterString);
  2332. }
  2333. return TRUE;
  2334. } // Et6000IsPresent()
  2335. BOOLEAN
  2336. ET6000GetMemorySize(
  2337. PHW_DEVICE_EXTENSION HwDeviceExtension
  2338. )
  2339. {
  2340. VIDEO_X86_BIOS_ARGUMENTS biosArguments;
  2341. VP_STATUS status;
  2342. VideoDebugPrint((1,"ET6000GetMemorySize - enter\n"));
  2343. //
  2344. // Get the adapter memory size
  2345. //
  2346. VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  2347. biosArguments.Eax = 0x1203;
  2348. biosArguments.Ebx = 0x00F2;
  2349. status = VideoPortInt10(HwDeviceExtension, &biosArguments);
  2350. if (status != NO_ERROR)
  2351. {
  2352. VideoDebugPrint((1,"ET6000GetMemorySize - exit with error\n"));
  2353. return FALSE;
  2354. }
  2355. HwDeviceExtension->AdapterMemorySize = (biosArguments.Ebx & 0x0000FFFF) * 64 * 1024;
  2356. //
  2357. // Finally, just validate the list of modes.
  2358. //
  2359. VgaValidateModes(HwDeviceExtension);
  2360. VideoPortSetRegistryParameters(HwDeviceExtension,
  2361. L"HardwareInformation.MemorySize",
  2362. &HwDeviceExtension->AdapterMemorySize,
  2363. sizeof(ULONG));
  2364. VideoDebugPrint((1,"ET6000GetMemorySize - exit\n"));
  2365. return TRUE;
  2366. }
  2367. USHORT
  2368. GetIndexedRegisterPacked(
  2369. PUCHAR AddressPort,
  2370. UCHAR index
  2371. )
  2372. {
  2373. // - Returns the value of the indexed register encoded with
  2374. // with index value in a form for easy restoration.
  2375. // The format of the return value is :
  2376. // bits 0-7 contain the index
  2377. // bits 8-15 contains the value at the index
  2378. //
  2379. // *** Assumes the Data Port Address is always next port
  2380. USHORT usData;
  2381. VideoPortWritePortUchar(AddressPort++, index);
  2382. usData = (USHORT) VideoPortReadPortUchar(AddressPort);
  2383. return((USHORT) index + (usData << 8));
  2384. }
  2385. VOID
  2386. ET4000SaveAndSetLinear(
  2387. PHW_DEVICE_EXTENSION HwDeviceExtension,
  2388. PUSHORT SaveArray
  2389. )
  2390. {
  2391. ULONG i=0;
  2392. //
  2393. // Save the GRAPH and SEQ Index Registers
  2394. //
  2395. SaveArray[i++] = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2396. SEQ_ADDRESS_PORT);
  2397. SaveArray[i++] = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2398. GRAPH_ADDRESS_PORT);
  2399. //
  2400. // Save the Segment Select Registers
  2401. //
  2402. SaveArray[i++] = (USHORT) VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2403. SEGMENT_SELECT_PORT);
  2404. SaveArray[i++] = (USHORT) VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2405. SEGMENT_SELECT_HIGH); // W32 specific
  2406. //
  2407. // Save the Sequence registers and setup for linear mode
  2408. //
  2409. SaveArray[i++] = GetIndexedRegisterPacked(HwDeviceExtension->IOAddress+SEQ_ADDRESS_PORT,IND_MAP_MASK);
  2410. //
  2411. // Set to write to all planes
  2412. //
  2413. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2414. SEQ_ADDRESS_PORT), (USHORT) (IND_MAP_MASK + (0x0F << 8)));
  2415. SaveArray[i++] = GetIndexedRegisterPacked(HwDeviceExtension->IOAddress +
  2416. SEQ_ADDRESS_PORT,IND_MEMORY_MODE);
  2417. //
  2418. // set to chain 4
  2419. //
  2420. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2421. SEQ_ADDRESS_PORT), (USHORT) (IND_MEMORY_MODE + (0x0E << 8)));
  2422. SaveArray[i++]=GetIndexedRegisterPacked(HwDeviceExtension->IOAddress +
  2423. GRAPH_ADDRESS_PORT,IND_SET_RESET_ENABLE);
  2424. //
  2425. // set to no set/reset
  2426. //
  2427. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2428. GRAPH_ADDRESS_PORT), (USHORT) (IND_SET_RESET_ENABLE + (0x0 << 8)));
  2429. SaveArray[i++]=GetIndexedRegisterPacked(HwDeviceExtension->IOAddress +
  2430. GRAPH_ADDRESS_PORT,IND_DATA_ROTATE);
  2431. //
  2432. // set to no rotate / move
  2433. //
  2434. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2435. GRAPH_ADDRESS_PORT), (USHORT) (IND_DATA_ROTATE + (0x0 << 8)));
  2436. SaveArray[i]=GetIndexedRegisterPacked(HwDeviceExtension->IOAddress +
  2437. GRAPH_ADDRESS_PORT,IND_GRAPH_MODE);
  2438. //
  2439. // preserve ATT bits and set read/write mode, not odd/even
  2440. // *** value is in upper bits of SaveArray[i]. See format
  2441. // *** GetIndexedRegisterPacked call
  2442. //
  2443. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2444. GRAPH_ADDRESS_PORT), (USHORT) (SaveArray[i++] & 0x60FF));
  2445. SaveArray[i++]=GetIndexedRegisterPacked(HwDeviceExtension->IOAddress +
  2446. GRAPH_ADDRESS_PORT,IND_GRAPH_MISC);
  2447. //
  2448. // set A000/graphics not odd/even
  2449. //
  2450. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2451. GRAPH_ADDRESS_PORT), (USHORT) (IND_GRAPH_MISC + (0x05 << 8)));
  2452. SaveArray[i]=GetIndexedRegisterPacked(HwDeviceExtension->IOAddress +
  2453. GRAPH_ADDRESS_PORT,IND_BIT_MASK);
  2454. //
  2455. // set to all bits
  2456. //
  2457. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2458. GRAPH_ADDRESS_PORT), (USHORT) (IND_BIT_MASK + (0xff << 8)));
  2459. } // ET4000SaveAndSetLinear
  2460. VOID
  2461. ET4000RestoreFromLinear(
  2462. PHW_DEVICE_EXTENSION HwDeviceExtension,
  2463. PUSHORT SaveArray
  2464. )
  2465. {
  2466. ULONG i=0;
  2467. USHORT GraphAddr, SeqAddr;
  2468. ULONG j;
  2469. //
  2470. // Get stored Graph and Seq Ports
  2471. //
  2472. SeqAddr = SaveArray[i++];
  2473. GraphAddr = SaveArray[i++];
  2474. //
  2475. // Restore Saved Registers
  2476. //
  2477. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEGMENT_SELECT_PORT,
  2478. (UCHAR) SaveArray[i++]); // W32 specific
  2479. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEGMENT_SELECT_HIGH,
  2480. (UCHAR) SaveArray[i++]);
  2481. for (j=0; j<2; j++) {
  2482. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2483. SEQ_ADDRESS_PORT), SaveArray[i++]);
  2484. }
  2485. for (j=0; j<5; j++) {
  2486. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2487. GRAPH_ADDRESS_PORT), SaveArray[i++]);
  2488. }
  2489. //
  2490. // Restore Graph and Seq index registers
  2491. //
  2492. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
  2493. (UCHAR)SeqAddr);
  2494. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + GRAPH_ADDRESS_PORT,
  2495. (UCHAR)GraphAddr);
  2496. } // ET4000RestoreFromLinear
  2497. VOID
  2498. vBankMap(
  2499. LONG iBankRead,
  2500. LONG iBankWrite,
  2501. PVOID pvContext
  2502. )
  2503. {
  2504. PHW_DEVICE_EXTENSION HwDeviceExtension = pvContext;
  2505. //
  2506. // This function is not pageable because it is called by the memory manager
  2507. // during some page fault handling.
  2508. //
  2509. #define SEG_READ_SHIFT_LO 4
  2510. #define SEG_READ_SHIFT_HI 0
  2511. #define SEG_WRITE_SHIFT_LO 0
  2512. #define SEG_WRITE_SHIFT_HI 4
  2513. #define SEG_READ_MASK_LO 0x0F
  2514. #define SEG_READ_MASK_HI 0x30
  2515. #define SEG_WRITE_MASK_LO 0x0F
  2516. #define SEG_WRITE_MASK_HI 0x30
  2517. UCHAR jSegLo, jSegHi;
  2518. //
  2519. // map the read segement to iBankRead
  2520. // map the write segement to iBankWrite
  2521. //
  2522. jSegLo = (UCHAR)(((iBankRead & SEG_READ_MASK_LO) << SEG_READ_SHIFT_LO) |
  2523. ((iBankWrite & SEG_WRITE_MASK_LO) << SEG_WRITE_SHIFT_LO));
  2524. jSegHi = (UCHAR)(((iBankRead & SEG_READ_MASK_HI) >> SEG_READ_SHIFT_HI) |
  2525. ((iBankWrite & SEG_WRITE_MASK_HI) >> SEG_WRITE_SHIFT_HI));
  2526. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2527. SEGMENT_SELECT_PORT, jSegLo);
  2528. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2529. SEGMENT_SELECT_HIGH, jSegHi);
  2530. //VideoDebugPrint((1, "vBankMap(%d,%d)\n", iBankRead, iBankWrite));
  2531. } // vBankMap
  2532. BOOLEAN
  2533. ET4000With1MegMemory(
  2534. PHW_DEVICE_EXTENSION HwDeviceExtension
  2535. )
  2536. {
  2537. //
  2538. // Check if 1 Meg of memory on ET4000 (not W32)
  2539. //
  2540. UCHAR save1;
  2541. UCHAR temp1;
  2542. PUCHAR memory = HwDeviceExtension->VideoMemoryAddress;
  2543. ULONG j;
  2544. BOOLEAN ret = TRUE; // assume we'll find it
  2545. USHORT SaveArray[12]; // Array to save values when setting linear mode
  2546. //
  2547. // Set to Linear Graphics Mode and save previous state
  2548. //
  2549. ET4000SaveAndSetLinear(HwDeviceExtension, SaveArray);
  2550. //
  2551. // Set to read/write segment 8 (linear) which == segment 2 (planar)
  2552. //
  2553. VideoPortWritePortUchar(HwDeviceExtension->IOAddress+SEGMENT_SELECT_PORT,
  2554. 0x88);
  2555. //
  2556. // Save original memory value
  2557. //
  2558. save1 = VideoPortReadRegisterUchar(HwDeviceExtension->VideoMemoryAddress);
  2559. //
  2560. // Write values to display memory page and check if returned
  2561. // for now try 0x55 and 0xAA
  2562. //
  2563. temp1 = 0x55;
  2564. for (j=0; j<2 ;j++) {
  2565. //
  2566. // Write a value to memory
  2567. //
  2568. VideoPortWriteRegisterUchar(memory, temp1);
  2569. //
  2570. // Now read the value back
  2571. // If not the same then not 1 MEG
  2572. //
  2573. if (VideoPortReadRegisterUchar(memory) != temp1) {
  2574. ret = FALSE;
  2575. break;
  2576. }
  2577. //
  2578. // Force value to change.
  2579. //
  2580. temp1 ^= 0xff;
  2581. }
  2582. //
  2583. // restore original memory value
  2584. //
  2585. VideoPortWriteRegisterUchar(memory, save1);
  2586. //
  2587. // get back to original mode
  2588. //
  2589. ET4000RestoreFromLinear(HwDeviceExtension, SaveArray);
  2590. return ret;
  2591. } // ET4000w32With1Meg
  2592. BOOLEAN
  2593. ET4000w32With256KDrams(
  2594. PHW_DEVICE_EXTENSION HwDeviceExtension,
  2595. USHORT SegmentOffset
  2596. )
  2597. {
  2598. //
  2599. // Check if memory location 0 is identical to the memory location
  2600. // provided at the given SegmentOffset. If so, than the w32 based
  2601. // board must be using 256Kxn DRAM Chips. This routine is w32 specific
  2602. // and does not save the segment registers. It is assumed that the
  2603. // calling routine will save the regs.
  2604. //
  2605. UCHAR save1, save2;
  2606. UCHAR temp1;
  2607. PUCHAR flush, memory = HwDeviceExtension->VideoMemoryAddress;
  2608. UCHAR SelectValLo, SelectValHi, CurSelLo, CurSelHi ;
  2609. ULONG j;
  2610. BOOLEAN ret = TRUE; // assume we'll find 256K chips
  2611. USHORT SaveArray[12]; // Memory to save original state
  2612. //
  2613. // Set to Linear Graphics Mode and save previous state
  2614. //
  2615. ET4000SaveAndSetLinear(HwDeviceExtension,SaveArray);
  2616. //
  2617. // Point to segment 0 R/W
  2618. //
  2619. VideoPortWritePortUchar(HwDeviceExtension->IOAddress+SEGMENT_SELECT_PORT,
  2620. 0x0);
  2621. //
  2622. // high order bits now (w32 specific)
  2623. //
  2624. VideoPortWritePortUchar(HwDeviceExtension->IOAddress+SEGMENT_SELECT_HIGH,
  2625. 0x0);
  2626. //
  2627. // save byte at seg 0
  2628. //
  2629. save1 = VideoPortReadRegisterUchar(memory);
  2630. //
  2631. // setup selector offset values for both read & write
  2632. //
  2633. SelectValLo = (SegmentOffset & 0x0f);
  2634. SelectValLo += (SelectValLo << 4);
  2635. SelectValHi = (SegmentOffset & 0x30);
  2636. SelectValHi += (SelectValHi >> 4);
  2637. //
  2638. // Point to passed in segment R/W
  2639. //
  2640. VideoPortWritePortUchar(HwDeviceExtension->IOAddress+SEGMENT_SELECT_PORT,
  2641. SelectValLo);
  2642. VideoPortWritePortUchar(HwDeviceExtension->IOAddress+SEGMENT_SELECT_HIGH,
  2643. SelectValHi);
  2644. //
  2645. // Save original memory value
  2646. //
  2647. save2 = VideoPortReadRegisterUchar(memory);
  2648. //
  2649. // Write values to display memory and check if duplicated at
  2650. // segment offset; for now try 0x55 and 0xAA
  2651. //
  2652. CurSelLo = CurSelHi = 0;
  2653. temp1 = 0x55;
  2654. for (j=0; j<2 ;j++) {
  2655. //
  2656. // Write a value to memory
  2657. //
  2658. VideoPortWriteRegisterUchar(memory, temp1);
  2659. //
  2660. // point to other segment
  2661. //
  2662. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2663. SEGMENT_SELECT_PORT, CurSelLo);
  2664. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2665. SEGMENT_SELECT_HIGH, CurSelHi);
  2666. //
  2667. // Flush the W32 cache before reading
  2668. //
  2669. for (flush=memory; flush <= memory+256; flush+=32)
  2670. VideoPortReadRegisterUchar(flush);
  2671. //
  2672. // Now read the value back
  2673. // If not the same then not 256Kxn chips
  2674. //
  2675. if (VideoPortReadRegisterUchar(memory) != temp1) {
  2676. ret = FALSE;
  2677. break;
  2678. }
  2679. //
  2680. // switch to other segment
  2681. //
  2682. CurSelLo = (CurSelLo) ? 0 : SelectValLo;
  2683. CurSelHi = (CurSelHi) ? 0 : SelectValHi;
  2684. //
  2685. // Force value to change.
  2686. //
  2687. temp1 ^= 0xff;
  2688. }
  2689. //
  2690. // restore original memory values
  2691. // Point to segment 0 R/W
  2692. //
  2693. VideoPortWritePortUchar(HwDeviceExtension->IOAddress+SEGMENT_SELECT_PORT,
  2694. 0x0);
  2695. VideoPortWritePortUchar(HwDeviceExtension->IOAddress+SEGMENT_SELECT_HIGH,
  2696. 0x0);
  2697. //
  2698. // restore byte at seg 0
  2699. //
  2700. VideoPortWriteRegisterUchar(memory, save1);
  2701. //
  2702. // Point to passed in segment R/W
  2703. //
  2704. VideoPortWritePortUchar(HwDeviceExtension->IOAddress+SEGMENT_SELECT_PORT,
  2705. SelectValLo);
  2706. VideoPortWritePortUchar(HwDeviceExtension->IOAddress+SEGMENT_SELECT_HIGH,
  2707. SelectValHi);
  2708. //
  2709. // Save original memory value
  2710. //
  2711. VideoPortWriteRegisterUchar(memory, save2);
  2712. //
  2713. // Restore it to previous mode
  2714. //
  2715. ET4000RestoreFromLinear(HwDeviceExtension,SaveArray);
  2716. return ret;
  2717. } // ET4000With256KDrams
  2718. VP_STATUS
  2719. VgaSetPaletteReg(
  2720. PHW_DEVICE_EXTENSION HwDeviceExtension,
  2721. PVIDEO_PALETTE_DATA PaletteBuffer,
  2722. ULONG PaletteBufferSize
  2723. )
  2724. /*++
  2725. Routine Description:
  2726. This routine sets a specified portion of the EGA (not DAC) palette
  2727. registers.
  2728. Arguments:
  2729. HwDeviceExtension - Pointer to the miniport driver's device extension.
  2730. PaletteBuffer - Pointer to the structure containing the palette data.
  2731. PaletteBufferSize - Length of the input buffer supplied by the user.
  2732. Return Value:
  2733. NO_ERROR - information returned successfully
  2734. ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data.
  2735. ERROR_INVALID_PARAMETER - invalid palette size.
  2736. --*/
  2737. {
  2738. USHORT i;
  2739. //
  2740. // Check if the size of the data in the input buffer is large enough.
  2741. //
  2742. if ((PaletteBufferSize) < (sizeof(VIDEO_PALETTE_DATA)) ||
  2743. (PaletteBufferSize < (sizeof(VIDEO_PALETTE_DATA) +
  2744. (sizeof(USHORT) * (PaletteBuffer->NumEntries -1)) ))) {
  2745. return ERROR_INSUFFICIENT_BUFFER;
  2746. }
  2747. //
  2748. // Check to see if the parameters are valid.
  2749. //
  2750. if ( (PaletteBuffer->FirstEntry > VIDEO_MAX_COLOR_REGISTER ) ||
  2751. (PaletteBuffer->NumEntries == 0) ||
  2752. (PaletteBuffer->FirstEntry + PaletteBuffer->NumEntries >
  2753. VIDEO_MAX_PALETTE_REGISTER + 1 ) ) {
  2754. return ERROR_INVALID_PARAMETER;
  2755. }
  2756. //
  2757. // Reset ATC to index mode
  2758. //
  2759. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2760. ATT_INITIALIZE_PORT_COLOR);
  2761. //
  2762. // Blast out our palette values.
  2763. //
  2764. for (i = 0; i < PaletteBuffer->NumEntries; i++) {
  2765. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ATT_ADDRESS_PORT,
  2766. (UCHAR)(i+PaletteBuffer->FirstEntry));
  2767. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2768. ATT_DATA_WRITE_PORT,
  2769. (UCHAR)PaletteBuffer->Colors[i]);
  2770. }
  2771. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ATT_ADDRESS_PORT,
  2772. VIDEO_ENABLE);
  2773. return NO_ERROR;
  2774. } // end VgaSetPaletteReg()
  2775. VP_STATUS
  2776. VgaSetColorLookup(
  2777. PHW_DEVICE_EXTENSION HwDeviceExtension,
  2778. PVIDEO_CLUT ClutBuffer,
  2779. ULONG ClutBufferSize
  2780. )
  2781. /*++
  2782. Routine Description:
  2783. This routine sets a specified portion of the DAC color lookup table
  2784. settings.
  2785. Arguments:
  2786. HwDeviceExtension - Pointer to the miniport driver's device extension.
  2787. ClutBufferSize - Length of the input buffer supplied by the user.
  2788. ClutBuffer - Pointer to the structure containing the color lookup table.
  2789. Return Value:
  2790. NO_ERROR - information returned successfully
  2791. ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data.
  2792. ERROR_INVALID_PARAMETER - invalid clut size.
  2793. --*/
  2794. {
  2795. USHORT i;
  2796. //
  2797. // Check if the size of the data in the input buffer is large enough.
  2798. //
  2799. if ( (ClutBufferSize < sizeof(VIDEO_CLUT) - sizeof(ULONG)) ||
  2800. (ClutBufferSize < sizeof(VIDEO_CLUT) +
  2801. (sizeof(ULONG) * (ClutBuffer->NumEntries - 1)) ) ) {
  2802. return ERROR_INSUFFICIENT_BUFFER;
  2803. }
  2804. //
  2805. // Check to see if the parameters are valid.
  2806. //
  2807. if ( (ClutBuffer->NumEntries == 0) ||
  2808. (ClutBuffer->FirstEntry > VIDEO_MAX_COLOR_REGISTER) ||
  2809. (ClutBuffer->FirstEntry + ClutBuffer->NumEntries >
  2810. VIDEO_MAX_COLOR_REGISTER + 1) ) {
  2811. return ERROR_INVALID_PARAMETER;
  2812. }
  2813. //
  2814. // Set CLUT registers directly on the hardware
  2815. //
  2816. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2817. DAC_ADDRESS_WRITE_PORT,
  2818. (UCHAR) ClutBuffer->FirstEntry);
  2819. for (i = 0; i < ClutBuffer->NumEntries; i++) {
  2820. VideoPortWritePortBufferUchar((PUCHAR)HwDeviceExtension->IOAddress +
  2821. DAC_DATA_REG_PORT,
  2822. &(ClutBuffer->LookupTable[i].RgbArray.Red),
  2823. 0x03);
  2824. }
  2825. return NO_ERROR;
  2826. } // end VgaSetColorLookup()
  2827. VP_STATUS
  2828. VgaRestoreHardwareState(
  2829. PHW_DEVICE_EXTENSION HwDeviceExtension,
  2830. PVIDEO_HARDWARE_STATE HardwareState,
  2831. ULONG HardwareStateSize
  2832. )
  2833. /*++
  2834. Routine Description:
  2835. Restores all registers and memory of the VGA.
  2836. Note: HardwareState points to the actual buffer from which the state
  2837. is to be restored. This buffer will always be big enough (we specified
  2838. the required size at DriverEntry).
  2839. Note: The offset in the hardware state header from which each general
  2840. register is restored is the offset of the write address of that register
  2841. from the base I/O address of the VGA.
  2842. Arguments:
  2843. HwDeviceExtension - Pointer to the miniport driver's device extension.
  2844. HardwareState - Pointer to a structure from which the saved state is to be
  2845. restored (actually only info about and a pointer to the actual save
  2846. buffer).
  2847. HardwareStateSize - Length of the input buffer supplied by the user.
  2848. (Actually only the size of the HardwareState structure, not the
  2849. buffer it points to from which the state is actually restored. The
  2850. pointed-to buffer is assumed to be big enough.)
  2851. Return Value:
  2852. NO_ERROR - restore performed successfully
  2853. ERROR_INSUFFICIENT_BUFFER - input buffer not large enough to provide data
  2854. --*/
  2855. {
  2856. PVIDEO_HARDWARE_STATE_HEADER hardwareStateHeader;
  2857. ULONG i;
  2858. UCHAR dummy;
  2859. PUCHAR pScreen;
  2860. PUCHAR pucLatch;
  2861. PULONG pulBuffer;
  2862. PUCHAR port;
  2863. PUCHAR portValue;
  2864. PUCHAR portValueDAC;
  2865. ULONG bIsColor;
  2866. //
  2867. // Check if the size of the data in the input buffer is large enough.
  2868. //
  2869. if ((HardwareStateSize < sizeof(VIDEO_HARDWARE_STATE)) ||
  2870. (HardwareState->StateLength < VGA_TOTAL_STATE_SIZE)) {
  2871. return ERROR_INSUFFICIENT_BUFFER;
  2872. }
  2873. //
  2874. // Point to the buffer where the restore data is actually stored.
  2875. //
  2876. hardwareStateHeader = HardwareState->StateHeader;
  2877. //
  2878. // Make sure the offset are in the structure ...
  2879. //
  2880. if ((hardwareStateHeader->BasicSequencerOffset + VGA_NUM_SEQUENCER_PORTS >
  2881. HardwareState->StateLength) ||
  2882. (hardwareStateHeader->BasicCrtContOffset + VGA_NUM_CRTC_PORTS >
  2883. HardwareState->StateLength) ||
  2884. (hardwareStateHeader->BasicGraphContOffset + VGA_NUM_GRAPH_CONT_PORTS >
  2885. HardwareState->StateLength) ||
  2886. (hardwareStateHeader->BasicAttribContOffset + VGA_NUM_ATTRIB_CONT_PORTS >
  2887. HardwareState->StateLength) ||
  2888. (hardwareStateHeader->BasicDacOffset + (3 * VGA_NUM_DAC_ENTRIES) >
  2889. HardwareState->StateLength) ||
  2890. (hardwareStateHeader->BasicLatchesOffset + 4 >
  2891. HardwareState->StateLength) ||
  2892. (hardwareStateHeader->ExtendedSequencerOffset + EXT_NUM_SEQUENCER_PORTS >
  2893. HardwareState->StateLength) ||
  2894. (hardwareStateHeader->ExtendedCrtContOffset + EXT_NUM_CRTC_PORTS >
  2895. HardwareState->StateLength) ||
  2896. (hardwareStateHeader->ExtendedGraphContOffset + EXT_NUM_GRAPH_CONT_PORTS >
  2897. HardwareState->StateLength) ||
  2898. (hardwareStateHeader->ExtendedAttribContOffset + EXT_NUM_ATTRIB_CONT_PORTS >
  2899. HardwareState->StateLength) ||
  2900. (hardwareStateHeader->ExtendedDacOffset + (4 * EXT_NUM_DAC_ENTRIES) >
  2901. HardwareState->StateLength) ||
  2902. //
  2903. // Only check the validator state offset if there is unemulated data.
  2904. //
  2905. ((hardwareStateHeader->VGAStateFlags & VIDEO_STATE_UNEMULATED_VGA_STATE) &&
  2906. (hardwareStateHeader->ExtendedValidatorStateOffset + VGA_VALIDATOR_AREA_SIZE >
  2907. HardwareState->StateLength)) ||
  2908. (hardwareStateHeader->ExtendedMiscDataOffset + VGA_MISC_DATA_AREA_OFFSET >
  2909. HardwareState->StateLength) ||
  2910. (hardwareStateHeader->Plane1Offset + hardwareStateHeader->PlaneLength >
  2911. HardwareState->StateLength) ||
  2912. (hardwareStateHeader->Plane2Offset + hardwareStateHeader->PlaneLength >
  2913. HardwareState->StateLength) ||
  2914. (hardwareStateHeader->Plane3Offset + hardwareStateHeader->PlaneLength >
  2915. HardwareState->StateLength) ||
  2916. (hardwareStateHeader->Plane4Offset + hardwareStateHeader->PlaneLength >
  2917. HardwareState->StateLength) ||
  2918. (hardwareStateHeader->DIBOffset +
  2919. hardwareStateHeader->DIBBitsPerPixel / 8 *
  2920. hardwareStateHeader->DIBXResolution *
  2921. hardwareStateHeader->DIBYResolution > HardwareState->StateLength) ||
  2922. (hardwareStateHeader->DIBXlatOffset + hardwareStateHeader->DIBXlatLength >
  2923. HardwareState->StateLength)) {
  2924. return ERROR_INVALID_PARAMETER;
  2925. }
  2926. //
  2927. // Turn off the screen to avoid flickering. The screen will turn back on
  2928. // when we restore the DAC state at the end of this routine.
  2929. //
  2930. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2931. MISC_OUTPUT_REG_READ_PORT) & 0x01) {
  2932. port = INPUT_STATUS_1_COLOR + HwDeviceExtension->IOAddress;
  2933. } else {
  2934. port = INPUT_STATUS_1_MONO + HwDeviceExtension->IOAddress;
  2935. }
  2936. //
  2937. // Set DAC register 0 to display black.
  2938. //
  2939. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2940. DAC_ADDRESS_WRITE_PORT, 0);
  2941. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2942. DAC_DATA_REG_PORT, 0);
  2943. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2944. DAC_DATA_REG_PORT, 0);
  2945. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2946. DAC_DATA_REG_PORT, 0);
  2947. //
  2948. // Set the DAC mask register to force DAC register 0 to display all the
  2949. // time (this is the register we just set to display black). From now on,
  2950. // nothing but black will show up on the screen.
  2951. //
  2952. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2953. DAC_PIXEL_MASK_PORT, 0);
  2954. //
  2955. // Restore the latches and the contents of display memory.
  2956. //
  2957. // Set up the VGA's hardware to allow us to copy to each plane in turn.
  2958. //
  2959. // Begin sync reset.
  2960. //
  2961. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2962. SEQ_ADDRESS_PORT),
  2963. (USHORT) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8)));
  2964. //
  2965. // Turn off Chain mode and map display memory at A0000 for 64K.
  2966. //
  2967. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2968. GRAPH_ADDRESS_PORT, IND_GRAPH_MISC);
  2969. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2970. GRAPH_DATA_PORT, (UCHAR) ((VideoPortReadPortUchar(
  2971. HwDeviceExtension->IOAddress + GRAPH_DATA_PORT) & 0xF1) | 0x04));
  2972. //
  2973. // Turn off Chain4 mode and odd/even.
  2974. //
  2975. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2976. SEQ_ADDRESS_PORT, IND_MEMORY_MODE);
  2977. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2978. SEQ_DATA_PORT,
  2979. (UCHAR) ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2980. SEQ_DATA_PORT) & 0xF3) | 0x04));
  2981. //
  2982. // End sync reset.
  2983. //
  2984. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  2985. SEQ_ADDRESS_PORT), (USHORT) (IND_SYNC_RESET +
  2986. (END_SYNC_RESET_VALUE << 8)));
  2987. //
  2988. // Set the write mode to 0, the read mode to 0, and turn off odd/even.
  2989. //
  2990. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2991. GRAPH_ADDRESS_PORT, IND_GRAPH_MODE);
  2992. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  2993. GRAPH_DATA_PORT,
  2994. (UCHAR) ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  2995. GRAPH_DATA_PORT) & 0xE4) | 0x00));
  2996. //
  2997. // Set the Bit Mask to 0xFF to allow all CPU bits through.
  2998. //
  2999. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3000. GRAPH_ADDRESS_PORT), (USHORT) (IND_BIT_MASK + (0xFF << 8)));
  3001. //
  3002. // Set the Data Rotation and Logical Function fields to 0 to allow CPU
  3003. // data through unmodified.
  3004. //
  3005. VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
  3006. GRAPH_ADDRESS_PORT), (USHORT) (IND_DATA_ROTATE + (0 << 8)));
  3007. //
  3008. // Set Set/Reset Enable to 0 to select CPU data for all planes.
  3009. //
  3010. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3011. GRAPH_ADDRESS_PORT), (USHORT) (IND_SET_RESET_ENABLE + (0 << 8)));
  3012. //
  3013. // Point the Sequencer Index to the Map Mask register.
  3014. //
  3015. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3016. SEQ_ADDRESS_PORT, IND_MAP_MASK);
  3017. //
  3018. // Restore the latches.
  3019. //
  3020. // Point to the saved data for the first latch.
  3021. //
  3022. pucLatch = ((PUCHAR) (hardwareStateHeader)) +
  3023. hardwareStateHeader->BasicLatchesOffset;
  3024. //
  3025. // Point to first byte of display memory.
  3026. //
  3027. pScreen = (PUCHAR) HwDeviceExtension->VideoMemoryAddress;
  3028. //
  3029. // Write the contents to be restored to each of the four latches in turn.
  3030. //
  3031. for (i = 0; i < 4; i++) {
  3032. //
  3033. // Set the Map Mask to select the plane we want to restore next.
  3034. //
  3035. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3036. SEQ_DATA_PORT, (UCHAR)(1<<i));
  3037. //
  3038. // Write this plane's latch.
  3039. //
  3040. VideoPortWriteRegisterUchar(pScreen, *pucLatch++);
  3041. }
  3042. //
  3043. // Read the latched data into the latches, and the latches are set.
  3044. //
  3045. dummy = VideoPortReadRegisterUchar(pScreen);
  3046. //
  3047. // Point to the offset of the saved data for the first plane.
  3048. //
  3049. pulBuffer = &(hardwareStateHeader->Plane1Offset);
  3050. //
  3051. // Restore each of the four planes in turn.
  3052. //
  3053. for (i = 0; i < 4; i++) {
  3054. //
  3055. // Set the Map Mask to select the plane we want to restore next.
  3056. //
  3057. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3058. SEQ_DATA_PORT, (UCHAR)(1<<i));
  3059. //
  3060. // Restore this plane from the buffer.
  3061. //
  3062. VideoPortMoveMemory((PUCHAR) HwDeviceExtension->VideoMemoryAddress,
  3063. ((PUCHAR) (hardwareStateHeader)) + *pulBuffer,
  3064. hardwareStateHeader->PlaneLength);
  3065. pulBuffer++;
  3066. }
  3067. //
  3068. // If we have some unemulated data, put it back into the buffer
  3069. //
  3070. if (hardwareStateHeader->VGAStateFlags & VIDEO_STATE_UNEMULATED_VGA_STATE) {
  3071. if (!hardwareStateHeader->ExtendedValidatorStateOffset) {
  3072. return ERROR_INVALID_PARAMETER;
  3073. }
  3074. //
  3075. // Get the right offset in the struct and save all the data associated
  3076. // with the trapped validator data.
  3077. //
  3078. VideoPortMoveMemory(&(HwDeviceExtension->TrappedValidatorCount),
  3079. ((PUCHAR) (hardwareStateHeader)) +
  3080. hardwareStateHeader->ExtendedValidatorStateOffset,
  3081. VGA_VALIDATOR_AREA_SIZE);
  3082. //
  3083. // Check to see if this is an appropriate access range.
  3084. // We are trapping - so we must have the trapping access range enabled.
  3085. //
  3086. if (((HwDeviceExtension->CurrentVdmAccessRange != FullVgaValidatorAccessRange) ||
  3087. (HwDeviceExtension->CurrentNumVdmAccessRanges != NUM_FULL_VGA_VALIDATOR_ACCESS_RANGE)) &&
  3088. ((HwDeviceExtension->CurrentVdmAccessRange != MinimalVgaValidatorAccessRange) ||
  3089. (HwDeviceExtension->CurrentNumVdmAccessRanges != NUM_MINIMAL_VGA_VALIDATOR_ACCESS_RANGE))) {
  3090. return ERROR_INVALID_PARAMETER;
  3091. }
  3092. VideoPortSetTrappedEmulatorPorts(HwDeviceExtension,
  3093. HwDeviceExtension->CurrentNumVdmAccessRanges,
  3094. HwDeviceExtension->CurrentVdmAccessRange);
  3095. }
  3096. //
  3097. // Unlock et4000 extended regsiters so we can restore extended registers
  3098. //
  3099. UnlockET4000ExtendedRegs(HwDeviceExtension);
  3100. //
  3101. // Set the critical registers (clock and timing states) during sync reset.
  3102. //
  3103. // Begin sync reset.
  3104. //
  3105. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3106. SEQ_ADDRESS_PORT), (USHORT) (IND_SYNC_RESET +
  3107. (START_SYNC_RESET_VALUE << 8)));
  3108. //
  3109. // Restore the Miscellaneous Output register.
  3110. //
  3111. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3112. MISC_OUTPUT_REG_WRITE_PORT,
  3113. (UCHAR) (hardwareStateHeader->PortValue[MISC_OUTPUT_REG_WRITE_OFFSET] & 0xF7));
  3114. //
  3115. // Restore all Sequencer registers except the Sync Reset register, which
  3116. // is always not in reset (except when we send out a batched sync reset
  3117. // register set, but that can't be interrupted, so we know we're never in
  3118. // sync reset at save/restore time).
  3119. //
  3120. portValue = ((PUCHAR) hardwareStateHeader) +
  3121. hardwareStateHeader->BasicSequencerOffset + 1;
  3122. for (i = 1; i < VGA_NUM_SEQUENCER_PORTS; i++) {
  3123. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3124. SEQ_ADDRESS_PORT), (USHORT) (i + ((*portValue++) << 8)) );
  3125. }
  3126. //
  3127. // Restore extended sequencer registers
  3128. //
  3129. #ifdef EXTENDED_REGISTER_SAVE_RESTORE
  3130. if (hardwareStateHeader->ExtendedSequencerOffset) {
  3131. portValue = ((PUCHAR) hardwareStateHeader) +
  3132. hardwareStateHeader->ExtendedSequencerOffset;
  3133. for (i = ET4000_SEQUENCER_EXT_START; i <= ET4000_SEQUENCER_EXT_END; i++) {
  3134. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3135. SEQ_ADDRESS_PORT),
  3136. (USHORT) (i + ((*portValue++) << 8)) );
  3137. }
  3138. }
  3139. #endif
  3140. //
  3141. // Restore the Graphics Controller Miscellaneous register, which contains
  3142. // the Chain bit.
  3143. //
  3144. portValue = ((PUCHAR) hardwareStateHeader) +
  3145. hardwareStateHeader->BasicGraphContOffset + IND_GRAPH_MISC;
  3146. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3147. GRAPH_ADDRESS_PORT), (USHORT)(IND_GRAPH_MISC + (*portValue << 8)));
  3148. //
  3149. // End sync reset.
  3150. //
  3151. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3152. SEQ_ADDRESS_PORT), (USHORT) (IND_SYNC_RESET +
  3153. (END_SYNC_RESET_VALUE << 8)));
  3154. //
  3155. // Figure out if color/mono switchable registers are at 3BX or 3DX.
  3156. // At the same time, save the state of the Miscellaneous Output register
  3157. // which is read from 3CC but written at 3C2.
  3158. //
  3159. if (hardwareStateHeader->PortValue[MISC_OUTPUT_REG_WRITE_OFFSET] & 0x01) {
  3160. bIsColor = TRUE;
  3161. } else {
  3162. bIsColor = FALSE;
  3163. }
  3164. //
  3165. // Restore the CRT Controller indexed registers.
  3166. //
  3167. // Unlock CRTC registers 0-7.
  3168. //
  3169. portValue = (PUCHAR) hardwareStateHeader +
  3170. hardwareStateHeader->BasicCrtContOffset;
  3171. if (bIsColor) {
  3172. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3173. CRTC_ADDRESS_PORT_COLOR), (USHORT) (IND_CRTC_PROTECT +
  3174. (((*(portValue + IND_CRTC_PROTECT)) & 0x7F) << 8)));
  3175. } else {
  3176. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3177. CRTC_ADDRESS_PORT_MONO), (USHORT) (IND_CRTC_PROTECT +
  3178. (((*(portValue + IND_CRTC_PROTECT)) & 0x7F) << 8)));
  3179. }
  3180. //
  3181. // Restore extended crtc registers.
  3182. //
  3183. #ifdef EXTENDED_REGISTER_SAVE_RESTORE
  3184. if (hardwareStateHeader->ExtendedCrtContOffset) {
  3185. portValue = (PUCHAR) hardwareStateHeader +
  3186. hardwareStateHeader->ExtendedCrtContOffset;
  3187. for (i = ET4000_CRTC_EXT_START; i <= ET4000_CRTC_EXT_END; i++) {
  3188. if (bIsColor) {
  3189. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3190. CRTC_ADDRESS_PORT_COLOR),
  3191. (USHORT) (i + ((*portValue++) << 8)));
  3192. } else {
  3193. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3194. CRTC_ADDRESS_PORT_MONO),
  3195. (USHORT) (i + ((*portValue++) << 8)));
  3196. }
  3197. }
  3198. //
  3199. // Second set of crtc registers
  3200. //
  3201. for (i = ET4000_CRTC_1_EXT_START; i <= ET4000_CRTC_1_EXT_END; i++) {
  3202. if (bIsColor) {
  3203. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3204. CRTC_ADDRESS_PORT_COLOR),
  3205. (USHORT) (i + ((*portValue++) << 8)));
  3206. } else {
  3207. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3208. CRTC_ADDRESS_PORT_MONO),
  3209. (USHORT) (i + ((*portValue++) << 8)));
  3210. }
  3211. }
  3212. }
  3213. #endif
  3214. //
  3215. // Now restore the CRTC registers.
  3216. //
  3217. portValue = (PUCHAR) hardwareStateHeader +
  3218. hardwareStateHeader->BasicCrtContOffset;
  3219. for (i = 0; i < VGA_NUM_CRTC_PORTS; i++) {
  3220. if (bIsColor) {
  3221. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3222. CRTC_ADDRESS_PORT_COLOR),
  3223. (USHORT) (i + ((*portValue++) << 8)));
  3224. } else {
  3225. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3226. CRTC_ADDRESS_PORT_MONO),
  3227. (USHORT) (i + ((*portValue++) << 8)));
  3228. }
  3229. }
  3230. //
  3231. // Restore the Graphics Controller indexed registers.
  3232. //
  3233. portValue = (PUCHAR) hardwareStateHeader +
  3234. hardwareStateHeader->BasicGraphContOffset;
  3235. for (i = 0; i < VGA_NUM_GRAPH_CONT_PORTS; i++) {
  3236. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3237. GRAPH_ADDRESS_PORT), (USHORT) (i + ((*portValue++) << 8)));
  3238. }
  3239. //
  3240. // Restore the Attribute Controller indexed registers.
  3241. //
  3242. portValue = (PUCHAR) hardwareStateHeader +
  3243. hardwareStateHeader->BasicAttribContOffset;
  3244. //
  3245. // Reset the AC index/data toggle, then blast out all the register
  3246. // settings.
  3247. //
  3248. if (bIsColor) {
  3249. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3250. INPUT_STATUS_1_COLOR);
  3251. } else {
  3252. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3253. INPUT_STATUS_1_MONO);
  3254. }
  3255. for (i = 0; i < VGA_NUM_ATTRIB_CONT_PORTS; i++) {
  3256. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3257. ATT_ADDRESS_PORT, (UCHAR)i);
  3258. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3259. ATT_DATA_WRITE_PORT, *portValue++);
  3260. }
  3261. //
  3262. // Restore extended attribute controller registers.
  3263. //
  3264. #ifdef EXTENDED_REGISTER_SAVE_RESTORE
  3265. if (hardwareStateHeader->ExtendedAttribContOffset) {
  3266. portValue = (PUCHAR) hardwareStateHeader +
  3267. hardwareStateHeader->ExtendedAttribContOffset;
  3268. for (i = ET4000_ATTRIB_EXT_START; i <= ET4000_ATTRIB_EXT_END; i++) {
  3269. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3270. ATT_ADDRESS_PORT),
  3271. (USHORT) (i + ((*portValue++) << 8)));
  3272. }
  3273. }
  3274. #endif
  3275. //
  3276. // Lock et4000 extended regsiters back up
  3277. //
  3278. LockET4000ExtendedRegs(HwDeviceExtension);
  3279. //
  3280. // Restore DAC registers 1 through 255. We'll do register 0, the DAC Mask,
  3281. // and the index registers later.
  3282. // Set the DAC address port Index, then write out the DAC Data registers.
  3283. // Each three reads get Red, Green, and Blue components for that register.
  3284. //
  3285. // Write them one at a time due to problems on local bus machines.
  3286. //
  3287. portValueDAC = (PUCHAR) hardwareStateHeader +
  3288. hardwareStateHeader->BasicDacOffset + 3;
  3289. for (i = 1; i < VGA_NUM_DAC_ENTRIES; i++) {
  3290. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3291. DAC_ADDRESS_WRITE_PORT, (UCHAR)i);
  3292. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3293. DAC_DATA_REG_PORT, *portValueDAC++);
  3294. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3295. DAC_DATA_REG_PORT, *portValueDAC++);
  3296. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3297. DAC_DATA_REG_PORT, *portValueDAC++);
  3298. }
  3299. //
  3300. // Is this color or mono ?
  3301. //
  3302. if (bIsColor) {
  3303. port = HwDeviceExtension->IOAddress + INPUT_STATUS_1_COLOR;
  3304. } else {
  3305. port = HwDeviceExtension->IOAddress + INPUT_STATUS_1_MONO;
  3306. }
  3307. //
  3308. // Restore the Feature Control register.
  3309. //
  3310. if (bIsColor) {
  3311. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3312. FEAT_CTRL_WRITE_PORT_COLOR,
  3313. hardwareStateHeader->PortValue[FEAT_CTRL_WRITE_PORT_COLOR]);
  3314. } else {
  3315. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3316. FEAT_CTRL_WRITE_PORT_MONO,
  3317. hardwareStateHeader->PortValue[FEAT_CTRL_WRITE_PORT_MONO]);
  3318. }
  3319. //
  3320. // Restore the Sequencer Index.
  3321. //
  3322. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3323. SEQ_ADDRESS_PORT,
  3324. hardwareStateHeader->PortValue[SEQ_ADDRESS_OFFSET]);
  3325. //
  3326. // Restore the CRT Controller Index.
  3327. //
  3328. if (bIsColor) {
  3329. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3330. CRTC_ADDRESS_PORT_COLOR,
  3331. hardwareStateHeader->PortValue[CRTC_ADDRESS_PORT_COLOR]);
  3332. } else {
  3333. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3334. CRTC_ADDRESS_PORT_MONO,
  3335. hardwareStateHeader->PortValue[CRTC_ADDRESS_PORT_MONO]);
  3336. }
  3337. //
  3338. // Restore the Graphics Controller Index.
  3339. //
  3340. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3341. GRAPH_ADDRESS_PORT,
  3342. hardwareStateHeader->PortValue[GRAPH_ADDRESS_OFFSET]);
  3343. //
  3344. // Restore the Attribute Controller Index and index/data toggle state.
  3345. //
  3346. if (bIsColor) {
  3347. port = HwDeviceExtension->IOAddress + INPUT_STATUS_1_COLOR;
  3348. } else {
  3349. port = HwDeviceExtension->IOAddress + INPUT_STATUS_1_MONO;
  3350. }
  3351. VideoPortReadPortUchar(port); // reset the toggle to Index state
  3352. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3353. ATT_ADDRESS_PORT, // restore the AC Index
  3354. hardwareStateHeader->PortValue[ATT_ADDRESS_OFFSET]);
  3355. //
  3356. // If the toggle should be in Data state, we're all set. If it should be in
  3357. // Index state, reset it to that condition.
  3358. //
  3359. if (hardwareStateHeader->AttribIndexDataState == 0) {
  3360. //
  3361. // Reset the toggle to Index state.
  3362. //
  3363. VideoPortReadPortUchar(port);
  3364. }
  3365. //
  3366. // Restore DAC register 0 and the DAC Mask, to unblank the screen.
  3367. //
  3368. portValueDAC = (PUCHAR) hardwareStateHeader +
  3369. hardwareStateHeader->BasicDacOffset;
  3370. //
  3371. // Restore the DAC Mask register.
  3372. //
  3373. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3374. DAC_PIXEL_MASK_PORT,
  3375. hardwareStateHeader->PortValue[DAC_PIXEL_MASK_OFFSET]);
  3376. //
  3377. // Restore DAC register 0.
  3378. //
  3379. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3380. DAC_ADDRESS_WRITE_PORT, 0);
  3381. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3382. DAC_DATA_REG_PORT, *portValueDAC++);
  3383. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3384. DAC_DATA_REG_PORT, *portValueDAC++);
  3385. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3386. DAC_DATA_REG_PORT, *portValueDAC++);
  3387. //
  3388. // Restore the read/write state and the current index of the DAC.
  3389. //
  3390. // See whether the Read or Write Index was written to most recently.
  3391. // (The upper nibble stored at DAC_STATE_PORT is the # of reads/writes
  3392. // for the current index.)
  3393. //
  3394. if ((hardwareStateHeader->PortValue[DAC_STATE_OFFSET] & 0x0F) == 3) {
  3395. //
  3396. // The DAC Read Index was written to last. Restore the DAC by setting
  3397. // up to read from the saved index - 1, because the way the Read
  3398. // Index works is that it autoincrements after reading, so you actually
  3399. // end up reading the data for the index you read at the DAC Write
  3400. // Mask register - 1.
  3401. //
  3402. // Set the Read Index to the index we read, minus 1, accounting for
  3403. // wrap from 255 back to 0. The DAC hardware immediately reads this
  3404. // register into a temporary buffer, then adds 1 to the index.
  3405. //
  3406. if (hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_OFFSET] == 0) {
  3407. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3408. DAC_ADDRESS_READ_PORT, 255);
  3409. } else {
  3410. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3411. DAC_ADDRESS_READ_PORT, (UCHAR)
  3412. (hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_OFFSET] -
  3413. 1));
  3414. }
  3415. //
  3416. // Now read the hardware however many times are required to get to
  3417. // the partial read state we saved.
  3418. //
  3419. for (i = hardwareStateHeader->PortValue[DAC_STATE_OFFSET] >> 4;
  3420. i > 0; i--) {
  3421. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3422. DAC_DATA_REG_PORT);
  3423. }
  3424. } else {
  3425. //
  3426. // The DAC Write Index was written to last. Set the Write Index to the
  3427. // index value we read out of the DAC. Then, if a partial write
  3428. // (partway through an RGB triplet) was in place, write the partial
  3429. // values, which we obtained by writing them to the current DAC
  3430. // register. This DAC register will be wrong until the write is
  3431. // completed, but at least the values will be right once the write is
  3432. // finished, and most importantly we won't have messed up the sequence
  3433. // of RGB writes (which can be as long as 768 in a row).
  3434. //
  3435. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3436. DAC_ADDRESS_WRITE_PORT,
  3437. hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_OFFSET]);
  3438. //
  3439. // Now write to the hardware however many times are required to get to
  3440. // the partial write state we saved (if any).
  3441. //
  3442. // Point to the saved value for the DAC register that was in the
  3443. // process of being written to; we wrote the partial value out, so now
  3444. // we can restore it.
  3445. //
  3446. portValueDAC = (PUCHAR) hardwareStateHeader +
  3447. hardwareStateHeader->BasicDacOffset +
  3448. (hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_OFFSET] * 3);
  3449. for (i = hardwareStateHeader->PortValue[DAC_STATE_OFFSET] >> 4;
  3450. i > 0; i--) {
  3451. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3452. DAC_DATA_REG_PORT, *portValueDAC++);
  3453. }
  3454. }
  3455. return NO_ERROR;
  3456. } // end VgaRestoreHardwareState()
  3457. VP_STATUS
  3458. VgaSaveHardwareState(
  3459. PHW_DEVICE_EXTENSION HwDeviceExtension,
  3460. PVIDEO_HARDWARE_STATE HardwareState,
  3461. ULONG HardwareStateSize,
  3462. PULONG OutputSize
  3463. )
  3464. /*++
  3465. Routine Description:
  3466. Saves all registers and memory of the VGA.
  3467. Note: HardwareState points to the actual buffer in which the state
  3468. is saved. This buffer will always be big enough (we specified
  3469. the required size at DriverEntry).
  3470. Note: This routine leaves registers in any state it cares to, except
  3471. that it will not mess with any of the CRT or Sequencer parameters that
  3472. might make the monitor unhappy. It leaves the screen blanked by setting
  3473. the DAC Mask and DAC register 0 to all zero values. The next video
  3474. operation we expect after this is a mode set to take us back to Win32.
  3475. Note: The offset in the hardware state header in which each general
  3476. register is saved is the offset of the write address of that register from
  3477. the base I/O address of the VGA.
  3478. Arguments:
  3479. HwDeviceExtension - Pointer to the miniport driver's device extension.
  3480. HardwareState - Pointer to a structure in which the saved state will be
  3481. returned (actually only info about and a pointer to the actual save
  3482. buffer).
  3483. HardwareStateSize - Length of the output buffer supplied by the user.
  3484. (Actually only the size of the HardwareState structure, not the
  3485. buffer it points to where the state is actually saved. The pointed-
  3486. to buffer is assumed to be big enough.)
  3487. OutputSize - Pointer to a buffer in which to return the actual size of
  3488. the data returned in the buffer.
  3489. Return Value:
  3490. NO_ERROR - information returned successfully
  3491. ERROR_INSUFFICIENT_BUFFER - output buffer not large enough to return
  3492. any useful data
  3493. --*/
  3494. {
  3495. PVIDEO_HARDWARE_STATE_HEADER hardwareStateHeader;
  3496. PUCHAR port;
  3497. PUCHAR pScreen;
  3498. PUCHAR portValue;
  3499. PUCHAR portValueDAC;
  3500. PUCHAR bufferPointer;
  3501. ULONG i;
  3502. UCHAR dummy, originalACIndex, originalACData;
  3503. UCHAR ucCRTC03;
  3504. ULONG bIsColor;
  3505. //
  3506. // See if the buffer is big enough to hold the hardware state structure.
  3507. // (This is only the HardwareState structure itself, not the buffer it
  3508. // points to.)
  3509. //
  3510. if (HardwareStateSize < sizeof(VIDEO_HARDWARE_STATE) ) {
  3511. *OutputSize = 0; // nothing returned
  3512. return ERROR_INSUFFICIENT_BUFFER;
  3513. }
  3514. //
  3515. // Amount of data we're going to return in the output buffer.
  3516. // (The VIDEO_HARDWARE_STATE in the output buffer points to the actual
  3517. // buffer in which the state is stored, which is assumed to be large
  3518. // enough.)
  3519. //
  3520. *OutputSize = sizeof(VIDEO_HARDWARE_STATE);
  3521. //
  3522. // Indicate the size of the full state save info.
  3523. //
  3524. HardwareState->StateLength = VGA_TOTAL_STATE_SIZE;
  3525. //
  3526. // hardwareStateHeader is a structure of offsets at the start of the
  3527. // actual save area that indicates the locations in which various VGA
  3528. // register and memory components are saved.
  3529. //
  3530. hardwareStateHeader = HardwareState->StateHeader;
  3531. //
  3532. // Zero out the structure.
  3533. //
  3534. VideoPortZeroMemory(hardwareStateHeader, sizeof(VIDEO_HARDWARE_STATE_HEADER));
  3535. //
  3536. // Set the Length field, which is basically a version ID.
  3537. //
  3538. hardwareStateHeader->Length = sizeof(VIDEO_HARDWARE_STATE_HEADER);
  3539. //
  3540. // Set the basic register offsets properly.
  3541. //
  3542. hardwareStateHeader->BasicSequencerOffset = VGA_BASIC_SEQUENCER_OFFSET;
  3543. hardwareStateHeader->BasicCrtContOffset = VGA_BASIC_CRTC_OFFSET;
  3544. hardwareStateHeader->BasicGraphContOffset = VGA_BASIC_GRAPH_CONT_OFFSET;
  3545. hardwareStateHeader->BasicAttribContOffset = VGA_BASIC_ATTRIB_CONT_OFFSET;
  3546. hardwareStateHeader->BasicDacOffset = VGA_BASIC_DAC_OFFSET;
  3547. hardwareStateHeader->BasicLatchesOffset = VGA_BASIC_LATCHES_OFFSET;
  3548. //
  3549. // Set the entended register offsets properly.
  3550. //
  3551. hardwareStateHeader->ExtendedSequencerOffset = VGA_EXT_SEQUENCER_OFFSET;
  3552. hardwareStateHeader->ExtendedCrtContOffset = VGA_EXT_CRTC_OFFSET;
  3553. hardwareStateHeader->ExtendedGraphContOffset = VGA_EXT_GRAPH_CONT_OFFSET;
  3554. hardwareStateHeader->ExtendedAttribContOffset = VGA_EXT_ATTRIB_CONT_OFFSET;
  3555. hardwareStateHeader->ExtendedDacOffset = VGA_EXT_DAC_OFFSET;
  3556. //
  3557. // Figure out if color/mono switchable registers are at 3BX or 3DX.
  3558. // At the same time, save the state of the Miscellaneous Output register
  3559. // which is read from 3CC but written at 3C2.
  3560. //
  3561. if ((hardwareStateHeader->PortValue[MISC_OUTPUT_REG_WRITE_OFFSET] =
  3562. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3563. MISC_OUTPUT_REG_READ_PORT))
  3564. & 0x01) {
  3565. bIsColor = TRUE;
  3566. } else {
  3567. bIsColor = FALSE;
  3568. }
  3569. //
  3570. // Force the video subsystem enable state to enabled.
  3571. //
  3572. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3573. VIDEO_SUBSYSTEM_ENABLE_PORT, 1);
  3574. //
  3575. // Save the DAC state first, so we can set the DAC to blank the screen
  3576. // so nothing after this shows up at all.
  3577. //
  3578. // Save the DAC Mask register.
  3579. //
  3580. hardwareStateHeader->PortValue[DAC_PIXEL_MASK_OFFSET] =
  3581. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3582. DAC_PIXEL_MASK_PORT);
  3583. //
  3584. // Save the DAC Index register. Note that there is actually only one DAC
  3585. // Index register, which functions as either the Read Index or the Write
  3586. // Index as needed.
  3587. //
  3588. hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_OFFSET] =
  3589. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3590. DAC_ADDRESS_WRITE_PORT);
  3591. //
  3592. // Save the DAC read/write state. We determine if the DAC has been written
  3593. // to or read from at the current index 0, 1, or 2 times (the application
  3594. // is in the middle of reading or writing a DAC register triplet if the
  3595. // count is 1 or 2), and save enough info so we can restore things
  3596. // properly. The only hole is if the application writes to the Write Index,
  3597. // then reads from instead of writes to the Data register, or vice-versa,
  3598. // or if they do a partial read write, then never finish it.
  3599. // This is fairly ridiculous behavior, however, and anyway there's nothing
  3600. // we can do about it.
  3601. //
  3602. hardwareStateHeader->PortValue[DAC_STATE_OFFSET] =
  3603. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3604. DAC_STATE_PORT);
  3605. if (hardwareStateHeader->PortValue[DAC_STATE_OFFSET] == 3) {
  3606. //
  3607. // The DAC Read Index was written to last. Figure out how many reads
  3608. // have been done from the current index. We'll restart this on restore
  3609. // by setting the Read Index to the current index - 1 (the read index
  3610. // is one greater than the index being read), then doing the proper
  3611. // number of reads.
  3612. //
  3613. // Read the Data register once, and see if the index changes.
  3614. //
  3615. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3616. DAC_DATA_REG_PORT);
  3617. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3618. DAC_ADDRESS_WRITE_PORT) !=
  3619. hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_OFFSET]) {
  3620. //
  3621. // The DAC Index changed, so two reads had already been done from
  3622. // the current index. Store the count "2" in the upper nibble of
  3623. // the read/write state field.
  3624. //
  3625. hardwareStateHeader->PortValue[DAC_STATE_OFFSET] |= 0x20;
  3626. } else {
  3627. //
  3628. // Read the Data register again, and see if the index changes.
  3629. //
  3630. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3631. DAC_DATA_REG_PORT);
  3632. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3633. DAC_ADDRESS_WRITE_PORT) !=
  3634. hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_OFFSET]) {
  3635. //
  3636. // The DAC Index changed, so one read had already been done
  3637. // from the current index. Store the count "1" in the upper
  3638. // nibble of the read/write state field.
  3639. //
  3640. hardwareStateHeader->PortValue[DAC_STATE_OFFSET] |= 0x10;
  3641. }
  3642. //
  3643. // If neither 2 nor 1 reads had been done from the current index,
  3644. // then 0 reads were done, and we're all set, since the upper
  3645. // nibble of the read/write state field is already 0.
  3646. //
  3647. }
  3648. } else {
  3649. //
  3650. // The DAC Write Index was written to last. Figure out how many writes
  3651. // have been done to the current index. We'll restart this on restore
  3652. // by setting the Write Index to the proper index, then doing the
  3653. // proper number of writes. When we do the DAC register save, we'll
  3654. // read out the value that gets written (if there was a partial write
  3655. // in progress), so we can restore the proper data later. This will
  3656. // cause this current DAC location to be briefly wrong in the 1- and
  3657. // 2-bytes-written case (until the app finishes the write), but that's
  3658. // better than having the wrong DAC values written for good.
  3659. //
  3660. // Write the Data register once, and see if the index changes.
  3661. //
  3662. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3663. DAC_DATA_REG_PORT, 0);
  3664. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3665. DAC_ADDRESS_WRITE_PORT) !=
  3666. hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_OFFSET]) {
  3667. //
  3668. // The DAC Index changed, so two writes had already been done to
  3669. // the current index. Store the count "2" in the upper nibble of
  3670. // the read/write state field.
  3671. //
  3672. hardwareStateHeader->PortValue[DAC_STATE_OFFSET] |= 0x20;
  3673. } else {
  3674. //
  3675. // Write the Data register again, and see if the index changes.
  3676. //
  3677. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3678. DAC_DATA_REG_PORT, 0);
  3679. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3680. DAC_ADDRESS_WRITE_PORT) !=
  3681. hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_OFFSET]) {
  3682. //
  3683. // The DAC Index changed, so one write had already been done
  3684. // to the current index. Store the count "1" in the upper
  3685. // nibble of the read/write state field.
  3686. //
  3687. hardwareStateHeader->PortValue[DAC_STATE_OFFSET] |= 0x10;
  3688. }
  3689. //
  3690. // If neither 2 nor 1 writes had been done to the current index,
  3691. // then 0 writes were done, and we're all set.
  3692. //
  3693. }
  3694. }
  3695. //
  3696. // Now, read out the 256 18-bit DAC palette registers (256 RGB triplets),
  3697. // and blank the screen.
  3698. //
  3699. portValueDAC = (PUCHAR) hardwareStateHeader + VGA_BASIC_DAC_OFFSET;
  3700. //
  3701. // Read out DAC register 0, so we can set it to black.
  3702. //
  3703. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3704. DAC_ADDRESS_READ_PORT, 0);
  3705. *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3706. DAC_DATA_REG_PORT);
  3707. *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3708. DAC_DATA_REG_PORT);
  3709. *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3710. DAC_DATA_REG_PORT);
  3711. //
  3712. // Set DAC register 0 to display black.
  3713. //
  3714. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3715. DAC_ADDRESS_WRITE_PORT, 0);
  3716. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3717. DAC_DATA_REG_PORT, 0);
  3718. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3719. DAC_DATA_REG_PORT, 0);
  3720. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3721. DAC_DATA_REG_PORT, 0);
  3722. //
  3723. // Set the DAC mask register to force DAC register 0 to display all the
  3724. // time (this is the register we just set to display black). From now on,
  3725. // nothing but black will show up on the screen.
  3726. //
  3727. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3728. DAC_PIXEL_MASK_PORT, 0);
  3729. //
  3730. // The next line is a bug fix for the w32p
  3731. //
  3732. ResetACToggle(HwDeviceExtension); // set the AC toggle to the Index state
  3733. //
  3734. // Read out the Attribute Controller Index state, and deduce the Index/Data
  3735. // toggle state at the same time.
  3736. //
  3737. // Save the state of the Attribute Controller, both Index and Data,
  3738. // so we can test in which state the toggle currently is.
  3739. //
  3740. originalACIndex = hardwareStateHeader->PortValue[ATT_ADDRESS_OFFSET] =
  3741. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3742. ATT_ADDRESS_PORT);
  3743. originalACData = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3744. ATT_DATA_READ_PORT);
  3745. //
  3746. // The next line is a bug fix for the w32p
  3747. //
  3748. ResetACToggle(HwDeviceExtension); // set the AC toggle to the Index state
  3749. //
  3750. // Sequencer Index.
  3751. //
  3752. hardwareStateHeader->PortValue[SEQ_ADDRESS_OFFSET] =
  3753. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3754. SEQ_ADDRESS_PORT);
  3755. //
  3756. // Begin sync reset, just in case this is an SVGA and the currently
  3757. // indexed Attribute Controller register controls clocking stuff (a
  3758. // normal VGA won't require this).
  3759. //
  3760. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3761. SEQ_ADDRESS_PORT),
  3762. (USHORT) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8)));
  3763. //
  3764. // Now, write a different Index setting to the Attribute Controller, and
  3765. // see if the Index changes.
  3766. //
  3767. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3768. ATT_ADDRESS_PORT, (UCHAR) (originalACIndex ^ 0x10));
  3769. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3770. ATT_ADDRESS_PORT) == originalACIndex) {
  3771. //
  3772. // The Index didn't change, so the toggle was in the Data state.
  3773. //
  3774. hardwareStateHeader->AttribIndexDataState = 1;
  3775. //
  3776. // Restore the original Data state; we just corrupted it, and we need
  3777. // to read it out later; also, it may glitch the screen if not
  3778. // corrected. The toggle is already in the Index state.
  3779. //
  3780. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3781. ATT_ADDRESS_PORT, originalACIndex);
  3782. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3783. ATT_DATA_WRITE_PORT, originalACData);
  3784. } else {
  3785. //
  3786. // The Index did change, so the toggle was in the Index state.
  3787. // No need to restore anything, because the Data register didn't
  3788. // change, and we've already read out the Index register.
  3789. //
  3790. hardwareStateHeader->AttribIndexDataState = 0;
  3791. }
  3792. //
  3793. // End sync reset.
  3794. //
  3795. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  3796. SEQ_ADDRESS_PORT),
  3797. (USHORT) (IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8)));
  3798. //
  3799. // Save the rest of the DAC registers.
  3800. // Set the DAC address port Index, then read out the DAC Data registers.
  3801. // Each three reads get Red, Green, and Blue components for that register.
  3802. //
  3803. // Read them one at a time due to problems on local bus machines.
  3804. //
  3805. for (i = 1; i < VGA_NUM_DAC_ENTRIES; i++) {
  3806. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3807. DAC_ADDRESS_READ_PORT, (UCHAR)i);
  3808. *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3809. DAC_DATA_REG_PORT);
  3810. *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3811. DAC_DATA_REG_PORT);
  3812. *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3813. DAC_DATA_REG_PORT);
  3814. }
  3815. //
  3816. // Is this color or mono ?
  3817. //
  3818. if (bIsColor) {
  3819. port = HwDeviceExtension->IOAddress + INPUT_STATUS_1_COLOR;
  3820. } else {
  3821. port = HwDeviceExtension->IOAddress + INPUT_STATUS_1_MONO;
  3822. }
  3823. //
  3824. // The Feature Control register is read from 3CA but written at 3BA/3DA.
  3825. //
  3826. if (bIsColor) {
  3827. hardwareStateHeader->PortValue[FEAT_CTRL_WRITE_PORT_COLOR] =
  3828. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3829. FEAT_CTRL_READ_PORT);
  3830. } else {
  3831. hardwareStateHeader->PortValue[FEAT_CTRL_WRITE_PORT_MONO] =
  3832. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3833. FEAT_CTRL_READ_PORT);
  3834. }
  3835. //
  3836. // CRT Controller Index.
  3837. //
  3838. if (bIsColor) {
  3839. hardwareStateHeader->PortValue[CRTC_ADDRESS_PORT_COLOR] =
  3840. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3841. CRTC_ADDRESS_PORT_COLOR);
  3842. } else {
  3843. hardwareStateHeader->PortValue[CRTC_ADDRESS_PORT_MONO] =
  3844. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3845. CRTC_ADDRESS_PORT_MONO);
  3846. }
  3847. //
  3848. // Graphics Controller Index.
  3849. //
  3850. hardwareStateHeader->PortValue[GRAPH_ADDRESS_OFFSET] =
  3851. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3852. GRAPH_ADDRESS_PORT);
  3853. //
  3854. // Sequencer indexed registers.
  3855. //
  3856. portValue = ((PUCHAR) hardwareStateHeader) + VGA_BASIC_SEQUENCER_OFFSET;
  3857. for (i = 0; i < VGA_NUM_SEQUENCER_PORTS; i++) {
  3858. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3859. SEQ_ADDRESS_PORT, (UCHAR)i);
  3860. *portValue++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3861. SEQ_DATA_PORT);
  3862. }
  3863. //
  3864. // Save extended sequencer registers.
  3865. //
  3866. #ifdef EXTENDED_REGISTER_SAVE_RESTORE
  3867. portValue = ((PUCHAR) hardwareStateHeader) + VGA_EXT_SEQUENCER_OFFSET;
  3868. for (i = ET4000_SEQUENCER_EXT_START; i <= ET4000_SEQUENCER_EXT_END; i++) {
  3869. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3870. SEQ_ADDRESS_PORT, (UCHAR)i);
  3871. *portValue++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3872. SEQ_DATA_PORT);
  3873. }
  3874. #endif
  3875. //
  3876. // CRT Controller indexed registers.
  3877. //
  3878. //
  3879. // Remember the state of CRTC register 3, then force bit 7
  3880. // to 1 so we will read back the Vertical Retrace start and
  3881. // end registers rather than the light pen info.
  3882. //
  3883. if (bIsColor) {
  3884. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3885. CRTC_ADDRESS_PORT_COLOR, 3);
  3886. ucCRTC03 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3887. CRTC_DATA_PORT_COLOR);
  3888. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3889. CRTC_DATA_PORT_COLOR, (UCHAR) (ucCRTC03 | 0x80));
  3890. } else {
  3891. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3892. CRTC_ADDRESS_PORT_MONO, 3);
  3893. ucCRTC03 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3894. CRTC_DATA_PORT_MONO);
  3895. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3896. CRTC_DATA_PORT_MONO, (UCHAR) (ucCRTC03 | 0x80));
  3897. }
  3898. portValue = (PUCHAR) hardwareStateHeader + VGA_BASIC_CRTC_OFFSET;
  3899. for (i = 0; i < VGA_NUM_CRTC_PORTS; i++) {
  3900. if (bIsColor) {
  3901. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3902. CRTC_ADDRESS_PORT_COLOR, (UCHAR)i);
  3903. *portValue++ =
  3904. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3905. CRTC_DATA_PORT_COLOR);
  3906. } else {
  3907. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3908. CRTC_ADDRESS_PORT_MONO, (UCHAR)i);
  3909. *portValue++ =
  3910. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3911. CRTC_DATA_PORT_MONO);
  3912. }
  3913. }
  3914. //
  3915. // Save extended crtc registers.
  3916. //
  3917. #ifdef EXTENDED_REGISTER_SAVE_RESTORE
  3918. portValue = (PUCHAR) hardwareStateHeader + VGA_EXT_CRTC_OFFSET;
  3919. for (i = ET4000_CRTC_EXT_START; i <= ET4000_CRTC_EXT_END; i++) {
  3920. if (bIsColor) {
  3921. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3922. CRTC_ADDRESS_PORT_COLOR, (UCHAR)i);
  3923. *portValue++ =
  3924. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3925. CRTC_DATA_PORT_COLOR);
  3926. } else {
  3927. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3928. CRTC_ADDRESS_PORT_MONO, (UCHAR)i);
  3929. *portValue++ =
  3930. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3931. CRTC_DATA_PORT_MONO);
  3932. }
  3933. }
  3934. //
  3935. // Save second set of crtc registers.
  3936. //
  3937. for (i = ET4000_CRTC_1_EXT_START; i <= ET4000_CRTC_1_EXT_END; i++) {
  3938. if (bIsColor) {
  3939. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3940. CRTC_ADDRESS_PORT_COLOR, (UCHAR)i);
  3941. *portValue++ =
  3942. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3943. CRTC_DATA_PORT_COLOR);
  3944. } else {
  3945. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3946. CRTC_ADDRESS_PORT_MONO, (UCHAR)i);
  3947. *portValue++ =
  3948. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3949. CRTC_DATA_PORT_MONO);
  3950. }
  3951. }
  3952. #endif
  3953. portValue = (PUCHAR) hardwareStateHeader + VGA_BASIC_CRTC_OFFSET;
  3954. portValue[3] = ucCRTC03;
  3955. //
  3956. // Graphics Controller indexed registers.
  3957. //
  3958. portValue = (PUCHAR) hardwareStateHeader + VGA_BASIC_GRAPH_CONT_OFFSET;
  3959. for (i = 0; i < VGA_NUM_GRAPH_CONT_PORTS; i++) {
  3960. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3961. GRAPH_ADDRESS_PORT, (UCHAR)i);
  3962. *portValue++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3963. GRAPH_DATA_PORT);
  3964. }
  3965. //
  3966. // Attribute Controller indexed registers.
  3967. //
  3968. portValue = (PUCHAR) hardwareStateHeader + VGA_BASIC_ATTRIB_CONT_OFFSET;
  3969. //
  3970. // For each indexed AC register, reset the flip-flop for reading the
  3971. // attribute register, then write the desired index to the AC Index,
  3972. // then read the value of the indexed register from the AC Data register.
  3973. //
  3974. for (i = 0; i < VGA_NUM_ATTRIB_CONT_PORTS; i++) {
  3975. if (bIsColor) {
  3976. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3977. INPUT_STATUS_1_COLOR);
  3978. } else {
  3979. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3980. INPUT_STATUS_1_MONO);
  3981. }
  3982. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  3983. ATT_ADDRESS_PORT, (UCHAR)i);
  3984. *portValue++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  3985. ATT_DATA_READ_PORT);
  3986. }
  3987. #ifdef EXTENDED_REGISTER_SAVE_RESTORE
  3988. //
  3989. // Extended Attribute Controller indexed registers.
  3990. //
  3991. portValue = (PUCHAR) hardwareStateHeader + VGA_EXT_ATTRIB_CONT_OFFSET;
  3992. //
  3993. // For each indexed AC register, reset the flip-flop for reading the
  3994. // attribute register, then write the desired index to the AC Index,
  3995. // then read the value of the indexed register from the AC Data register.
  3996. //
  3997. for (i = ET4000_ATTRIB_EXT_START; i <= ET4000_ATTRIB_EXT_END; i++) {
  3998. if (bIsColor) {
  3999. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  4000. INPUT_STATUS_1_COLOR);
  4001. } else {
  4002. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  4003. INPUT_STATUS_1_MONO);
  4004. }
  4005. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4006. ATT_ADDRESS_PORT, (UCHAR)i);
  4007. *portValue++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  4008. ATT_DATA_READ_PORT);
  4009. }
  4010. #endif
  4011. //
  4012. // Save the latches. This destroys one byte of display memory in each
  4013. // plane, which is unfortunate but unavoidable. Chips that provide
  4014. // a way to read back the latches can avoid this problem.
  4015. //
  4016. // Set up the VGA's hardware so we can write the latches, then read them
  4017. // back.
  4018. //
  4019. //
  4020. // Begin sync reset.
  4021. //
  4022. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  4023. SEQ_ADDRESS_PORT),
  4024. (USHORT) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8)));
  4025. //
  4026. // Set the Miscellaneous register to make sure we can access video RAM.
  4027. //
  4028. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4029. MISC_OUTPUT_REG_WRITE_PORT, (UCHAR)(
  4030. hardwareStateHeader->PortValue[MISC_OUTPUT_REG_WRITE_OFFSET] |
  4031. 0x02));
  4032. //
  4033. // Turn off Chain mode and map display memory at A0000 for 64K.
  4034. //
  4035. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4036. GRAPH_ADDRESS_PORT, IND_GRAPH_MISC);
  4037. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4038. GRAPH_DATA_PORT,
  4039. (UCHAR) ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  4040. GRAPH_DATA_PORT) & 0xF1) | 0x04));
  4041. //
  4042. // Turn off Chain4 mode and odd/even.
  4043. //
  4044. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4045. SEQ_ADDRESS_PORT, IND_MEMORY_MODE);
  4046. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4047. SEQ_DATA_PORT,
  4048. (UCHAR) ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  4049. SEQ_DATA_PORT) & 0xF3) | 0x04));
  4050. //
  4051. // End sync reset.
  4052. //
  4053. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  4054. SEQ_ADDRESS_PORT),
  4055. (USHORT) (IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8)));
  4056. //
  4057. // Set the Map Mask to write to all planes.
  4058. //
  4059. VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
  4060. SEQ_ADDRESS_PORT), (USHORT) (IND_MAP_MASK + (0x0F << 8)));
  4061. //
  4062. // Set the write mode to 0, the read mode to 0, and turn off odd/even.
  4063. //
  4064. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4065. GRAPH_ADDRESS_PORT, IND_GRAPH_MODE);
  4066. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4067. GRAPH_DATA_PORT,
  4068. (UCHAR) ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  4069. GRAPH_DATA_PORT) & 0xE4) | 0x01));
  4070. //
  4071. // Point to the last byte of display memory.
  4072. //
  4073. pScreen = (PUCHAR) HwDeviceExtension->VideoMemoryAddress +
  4074. VGA_PLANE_SIZE - 1;
  4075. //
  4076. // Write the latches to the last byte of display memory.
  4077. //
  4078. VideoPortWriteRegisterUchar(pScreen, 0);
  4079. //
  4080. // Cycle through the four planes, reading the latch data from each plane.
  4081. //
  4082. //
  4083. // Point the Graphics Controller Index to the Read Map register.
  4084. //
  4085. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4086. GRAPH_ADDRESS_PORT, IND_READ_MAP);
  4087. portValue = (PUCHAR) hardwareStateHeader + VGA_BASIC_LATCHES_OFFSET;
  4088. for (i=0; i<4; i++) {
  4089. //
  4090. // Set the Read Map for the current plane.
  4091. //
  4092. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4093. GRAPH_DATA_PORT, (UCHAR)i);
  4094. //
  4095. // Read the latched data we've written to memory.
  4096. //
  4097. *portValue++ = VideoPortReadRegisterUchar(pScreen);
  4098. }
  4099. //
  4100. // Set the VDM flags
  4101. // We are a standard VGA, and then check if we have unemulated state.
  4102. //
  4103. #ifdef EXTENDED_REGISTER_SAVE_RESTORE
  4104. hardwareStateHeader->VGAStateFlags |= VIDEO_STATE_NON_STANDARD_VGA;
  4105. #endif
  4106. if (HwDeviceExtension->TrappedValidatorCount) {
  4107. hardwareStateHeader->VGAStateFlags |= VIDEO_STATE_UNEMULATED_VGA_STATE;
  4108. //
  4109. // Save the VDM Emulator data
  4110. // No need to save the state of the seuencer port register for our
  4111. // emulated data since it may change when we come back. It will be
  4112. // recomputed.
  4113. //
  4114. hardwareStateHeader->ExtendedValidatorStateOffset = VGA_VALIDATOR_OFFSET;
  4115. VideoPortMoveMemory(((PUCHAR) (hardwareStateHeader)) +
  4116. hardwareStateHeader->ExtendedValidatorStateOffset,
  4117. &(HwDeviceExtension->TrappedValidatorCount),
  4118. VGA_VALIDATOR_AREA_SIZE);
  4119. } else {
  4120. hardwareStateHeader->ExtendedValidatorStateOffset = 0;
  4121. }
  4122. //
  4123. // ET4000 feature:
  4124. //
  4125. // We also set the PACKED_CHAIN4_MODE for this adapter since it's memory
  4126. // does not follow the vga standard in 256 color mode (mode 13)
  4127. //
  4128. hardwareStateHeader->VGAStateFlags |= VIDEO_STATE_PACKED_CHAIN4_MODE;
  4129. //
  4130. // Set the size of each plane.
  4131. //
  4132. hardwareStateHeader->PlaneLength = VGA_PLANE_SIZE;
  4133. //
  4134. // Store all the offsets for the planes in the structure.
  4135. //
  4136. hardwareStateHeader->Plane1Offset = VGA_PLANE_0_OFFSET;
  4137. hardwareStateHeader->Plane2Offset = VGA_PLANE_1_OFFSET;
  4138. hardwareStateHeader->Plane3Offset = VGA_PLANE_2_OFFSET;
  4139. hardwareStateHeader->Plane4Offset = VGA_PLANE_3_OFFSET;
  4140. //
  4141. // Now copy the contents of video VRAM into the buffer.
  4142. //
  4143. // The VGA hardware is already set up so that video memory is readable;
  4144. // we already turned off Chain mode, mapped in at A0000, turned off Chain4,
  4145. // turned off odd/even, and set read mode 0 when we saved the latches.
  4146. //
  4147. // Point the Graphics Controller Index to the Read Map register.
  4148. //
  4149. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4150. GRAPH_ADDRESS_PORT, IND_READ_MAP);
  4151. //
  4152. // Point to the save area for the first plane.
  4153. //
  4154. bufferPointer = ((PUCHAR) (hardwareStateHeader)) +
  4155. hardwareStateHeader->Plane1Offset;
  4156. //
  4157. // Save the four planes consecutively.
  4158. //
  4159. for (i = 0; i < 4; i++) {
  4160. //
  4161. // Set the Read Map to select the plane we want to save next.
  4162. //
  4163. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4164. GRAPH_DATA_PORT, (UCHAR)i);
  4165. //
  4166. // Copy this plane into the buffer.
  4167. //
  4168. VideoPortMoveMemory(bufferPointer,
  4169. (PUCHAR) HwDeviceExtension->VideoMemoryAddress,
  4170. VGA_PLANE_SIZE);
  4171. //
  4172. // Point to the next plane's save area.
  4173. //
  4174. bufferPointer += VGA_PLANE_SIZE;
  4175. }
  4176. return NO_ERROR;
  4177. } // end VgaSaveHardwareState()
  4178. #if defined(i386)
  4179. VP_STATUS
  4180. VgaGetBankSelectCode(
  4181. PHW_DEVICE_EXTENSION HwDeviceExtension,
  4182. PVIDEO_BANK_SELECT BankSelect,
  4183. ULONG BankSelectSize,
  4184. PULONG OutputSize
  4185. )
  4186. /*++
  4187. Routine Description:
  4188. Returns information needed in order for caller to implement bank
  4189. management.
  4190. Arguments:
  4191. HwDeviceExtension - Pointer to the miniport driver's device extension.
  4192. BankSelect - Pointer to a VIDEO_BANK_SELECT structure in which the bank
  4193. select data will be returned (output buffer).
  4194. BankSelectSize - Length of the output buffer supplied by the user.
  4195. OutputSize - Pointer to a variable in which to return the actual size of
  4196. the data returned in the output buffer.
  4197. Return Value:
  4198. NO_ERROR - information returned successfully
  4199. ERROR_MORE_DATA - output buffer not large enough to hold all info (but
  4200. Size is returned, so caller can tell how large a buffer to allocate)
  4201. ERROR_INSUFFICIENT_BUFFER - output buffer not large enough to return
  4202. any useful data
  4203. ERROR_INVALID_PARAMETER - invalid video mode selection
  4204. --*/
  4205. {
  4206. ULONG codeSize = ((ULONG)&BankSwitchEnd) - ((ULONG)&BankSwitchStart);
  4207. PUCHAR pCode = (PUCHAR)BankSelect + sizeof(VIDEO_BANK_SELECT);
  4208. PVIDEOMODE pMode;
  4209. //
  4210. // check if a mode has been set
  4211. //
  4212. if (HwDeviceExtension->CurrentMode == NULL) {
  4213. return ERROR_INVALID_FUNCTION;
  4214. }
  4215. //
  4216. // The minimum passed buffer size is a VIDEO_BANK_SELECT
  4217. // structure, so that we can return the required size; we can't do
  4218. // anything if we don't have at least that much buffer.
  4219. //
  4220. if (BankSelectSize < sizeof(VIDEO_BANK_SELECT)) {
  4221. return ERROR_INSUFFICIENT_BUFFER;
  4222. }
  4223. //
  4224. // Size of banking info.
  4225. //
  4226. BankSelect->Length = sizeof(VIDEO_BANK_SELECT);
  4227. BankSelect->Size = sizeof(VIDEO_BANK_SELECT) + codeSize;
  4228. //
  4229. // There's room enough for everything, so fill in all fields in
  4230. // VIDEO_BANK_SELECT. (All fields are always returned; the caller can
  4231. // just choose to ignore them, based on BankingFlags and BankingType.)
  4232. //
  4233. pMode = HwDeviceExtension->CurrentMode;
  4234. BankSelect->BitmapWidthInBytes = pMode->wbytes;
  4235. BankSelect->BitmapSize = pMode->sbytes;
  4236. BankSelect->Granularity = 0x10000; // 64K bank start adjustment normally
  4237. //
  4238. // Set whether any banking is actually supported in this mode.
  4239. //
  4240. switch(pMode->banktype) {
  4241. case NoBanking:
  4242. case MemMgrBanking:
  4243. BankSelect->BankingType = VideoNotBanked;
  4244. BankSelect->PlanarHCBankingType = VideoNotBanked;
  4245. BankSelect->BankingFlags = 0;
  4246. break;
  4247. case NormalBanking:
  4248. //
  4249. // The ET4000 supports independent 64K read and write banks.
  4250. //
  4251. BankSelect->BankingType = VideoBanked1R1W;
  4252. BankSelect->PlanarHCBankingType = VideoNotBanked;
  4253. BankSelect->BankingFlags = 0;
  4254. break;
  4255. case PlanarHCBanking:
  4256. //
  4257. // The ET4000 supports independent 64K read and write banks
  4258. // in both non-planar and planar modes when using high-color.
  4259. //
  4260. BankSelect->BankingType = VideoBanked1R1W;
  4261. BankSelect->PlanarHCBankingType = VideoBanked1R1W;
  4262. BankSelect->BankingFlags = PLANAR_HC;
  4263. // 64K bank start adjustment in planar HC mode as well
  4264. BankSelect->PlanarHCGranularity = 0x10000;
  4265. BankSelect->PlanarHCBankCodeOffset = &PlanarHCBankSwitchStart -
  4266. &BankSwitchStart +
  4267. sizeof(VIDEO_BANK_SELECT);
  4268. BankSelect->PlanarHCEnableCodeOffset = &EnablePlanarHCStart -
  4269. &BankSwitchStart +
  4270. sizeof(VIDEO_BANK_SELECT);
  4271. BankSelect->PlanarHCDisableCodeOffset = &DisablePlanarHCStart -
  4272. &BankSwitchStart +
  4273. sizeof(VIDEO_BANK_SELECT);
  4274. break;
  4275. }
  4276. //
  4277. // If the buffer isn't big enough to hold all info, just return
  4278. // ERROR_MORE_DATA; Size is already set.
  4279. //
  4280. if (BankSelectSize < BankSelect->Size ) {
  4281. //
  4282. // We're returning only the VIDEO_BANK_SELECT structure.
  4283. //
  4284. *OutputSize = sizeof(VIDEO_BANK_SELECT);
  4285. return ERROR_MORE_DATA;
  4286. }
  4287. //
  4288. // Set the bank switch code's location in the returned buffer.
  4289. //
  4290. BankSelect->CodeOffset = sizeof(VIDEO_BANK_SELECT);
  4291. //
  4292. // Copy all banking code into the output buffer.
  4293. //
  4294. VideoPortMoveMemory(pCode,
  4295. &BankSwitchStart,
  4296. codeSize);
  4297. //
  4298. // Number of bytes we're returning is the full banking info size.
  4299. //
  4300. *OutputSize = BankSelect->Size;
  4301. return NO_ERROR;
  4302. } // end VgaGetBankSelectCode()
  4303. #endif
  4304. VP_STATUS
  4305. VgaValidatorUcharEntry(
  4306. ULONG Context,
  4307. ULONG Port,
  4308. UCHAR AccessMode,
  4309. PUCHAR Data
  4310. )
  4311. /*++
  4312. Routine Description:
  4313. Entry point into the validator for byte I/O operations.
  4314. The entry point will be called whenever a byte operation was performed
  4315. by a DOS application on one of the specified Video ports. The kernel
  4316. emulator will forward these requests.
  4317. Arguments:
  4318. Context - Context value that is passed to each call made to the validator
  4319. function. This is the value the miniport driver specified in the
  4320. MiniportConfigInfo->EmulatorAccessEntriesContext.
  4321. Port - Port on which the operation is to be performed.
  4322. AccessMode - Determines if it is a read or write operation.
  4323. Data - Pointer to a variable containing the data to be written or a
  4324. variable into which the read data should be stored.
  4325. Return Value:
  4326. NO_ERROR.
  4327. --*/
  4328. {
  4329. PHW_DEVICE_EXTENSION hwDeviceExtension = (PHW_DEVICE_EXTENSION) Context;
  4330. ULONG endEmulation;
  4331. UCHAR temp;
  4332. if (hwDeviceExtension->TrappedValidatorCount) {
  4333. //
  4334. // If we are processing a WRITE instruction, then store it in the
  4335. // playback buffer. If the buffer is full, then play it back right
  4336. // away, end sync reset and reinitialize the buffer with a sync
  4337. // reset instruction.
  4338. //
  4339. // If we have a READ, we must flush the buffer (which has the side
  4340. // effect of starting SyncReset), perform the read operation, stop
  4341. // sync reset, and put back a sync reset instruction in the buffer
  4342. // so we can go on appropriately
  4343. //
  4344. if (AccessMode & EMULATOR_WRITE_ACCESS) {
  4345. //
  4346. // Make sure Bit 3 of the Miscellaneous register is always 0.
  4347. // If it is 1 it could select a non-existent clock, and kill the
  4348. // system
  4349. //
  4350. if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
  4351. *Data &= 0xF7;
  4352. }
  4353. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4354. TrappedValidatorCount].Port = Port;
  4355. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4356. TrappedValidatorCount].AccessType = VGA_VALIDATOR_UCHAR_ACCESS;
  4357. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4358. TrappedValidatorCount].Data = *Data;
  4359. hwDeviceExtension->TrappedValidatorCount++;
  4360. //
  4361. // Check to see if this instruction was ending sync reset.
  4362. // If it did, we must flush the buffer and reset the trapped
  4363. // IO ports to the minimal set.
  4364. //
  4365. if ( (Port == SEQ_DATA_PORT) &&
  4366. ((*Data & END_SYNC_RESET_VALUE) == END_SYNC_RESET_VALUE) &&
  4367. (hwDeviceExtension->SequencerAddressValue == IND_SYNC_RESET)) {
  4368. endEmulation = 1;
  4369. } else {
  4370. //
  4371. // If we are accessing the seq address port, keep track of the
  4372. // data value
  4373. //
  4374. if (Port == SEQ_ADDRESS_PORT) {
  4375. hwDeviceExtension->SequencerAddressValue = *Data;
  4376. }
  4377. //
  4378. // If the buffer is not full, then just return right away.
  4379. //
  4380. if (hwDeviceExtension->TrappedValidatorCount <
  4381. VGA_MAX_VALIDATOR_DATA - 1) {
  4382. return NO_ERROR;
  4383. }
  4384. endEmulation = 0;
  4385. }
  4386. }
  4387. //
  4388. // We are either in a READ path or a WRITE path that caused a
  4389. // a full buffer. So flush the buffer either way.
  4390. //
  4391. // To do this put an END_SYNC_RESET at the end since we want to make
  4392. // the buffer is ended sync reset ended.
  4393. //
  4394. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4395. TrappedValidatorCount].Port = SEQ_ADDRESS_PORT;
  4396. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4397. TrappedValidatorCount].AccessType = VGA_VALIDATOR_USHORT_ACCESS;
  4398. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4399. TrappedValidatorCount].Data = (USHORT) (IND_SYNC_RESET +
  4400. (END_SYNC_RESET_VALUE << 8));
  4401. hwDeviceExtension->TrappedValidatorCount++;
  4402. VideoPortSynchronizeExecution(hwDeviceExtension,
  4403. VpHighPriority,
  4404. (PMINIPORT_SYNCHRONIZE_ROUTINE)
  4405. VgaPlaybackValidatorData,
  4406. hwDeviceExtension);
  4407. //
  4408. // Write back the real value of the sequencer address port.
  4409. //
  4410. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  4411. SEQ_ADDRESS_PORT,
  4412. (UCHAR) hwDeviceExtension->SequencerAddressValue);
  4413. //
  4414. // If we are in a READ path, read the data
  4415. //
  4416. if (AccessMode & EMULATOR_READ_ACCESS) {
  4417. *Data = VideoPortReadPortUchar(hwDeviceExtension->IOAddress + Port);
  4418. endEmulation = 0;
  4419. }
  4420. //
  4421. // If we are ending emulation, reset trapping to the minimal amount
  4422. // and exit.
  4423. //
  4424. if (endEmulation) {
  4425. VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
  4426. NUM_MINIMAL_VGA_VALIDATOR_ACCESS_RANGE,
  4427. MinimalVgaValidatorAccessRange);
  4428. return NO_ERROR;
  4429. }
  4430. //
  4431. // For both cases, put back a START_SYNC_RESET in the buffer.
  4432. //
  4433. hwDeviceExtension->TrappedValidatorCount = 1;
  4434. hwDeviceExtension->TrappedValidatorData[0].Port = SEQ_ADDRESS_PORT;
  4435. hwDeviceExtension->TrappedValidatorData[0].AccessType =
  4436. VGA_VALIDATOR_USHORT_ACCESS;
  4437. hwDeviceExtension->TrappedValidatorData[0].Data =
  4438. (ULONG) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8));
  4439. } else {
  4440. //
  4441. // Nothing trapped.
  4442. // Lets check is the IO is trying to do something that would require
  4443. // us to stop trapping
  4444. //
  4445. if (AccessMode & EMULATOR_WRITE_ACCESS) {
  4446. //
  4447. // Make sure Bit 3 of the Miscelaneous register is always 0.
  4448. // If it is 1 it could select a non-existant clock, and kill the
  4449. // system
  4450. //
  4451. if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
  4452. temp = VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
  4453. SEQ_ADDRESS_PORT);
  4454. VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
  4455. SEQ_ADDRESS_PORT),
  4456. (USHORT) (IND_SYNC_RESET +
  4457. (START_SYNC_RESET_VALUE << 8)));
  4458. VideoPortWritePortUchar(hwDeviceExtension->IOAddress + Port,
  4459. (UCHAR) (*Data & 0xF7) );
  4460. VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
  4461. SEQ_ADDRESS_PORT),
  4462. (USHORT) (IND_SYNC_RESET +
  4463. (END_SYNC_RESET_VALUE << 8)));
  4464. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  4465. SEQ_ADDRESS_PORT,
  4466. temp);
  4467. return NO_ERROR;
  4468. }
  4469. //
  4470. // If we get an access to the sequencer register, start trapping.
  4471. //
  4472. if ( (Port == SEQ_DATA_PORT) &&
  4473. ((*Data & END_SYNC_RESET_VALUE) != END_SYNC_RESET_VALUE) &&
  4474. (VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
  4475. SEQ_ADDRESS_PORT) == IND_SYNC_RESET)) {
  4476. VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
  4477. NUM_FULL_VGA_VALIDATOR_ACCESS_RANGE,
  4478. FullVgaValidatorAccessRange);
  4479. hwDeviceExtension->TrappedValidatorCount = 1;
  4480. hwDeviceExtension->TrappedValidatorData[0].Port = Port;
  4481. hwDeviceExtension->TrappedValidatorData[0].AccessType =
  4482. VGA_VALIDATOR_UCHAR_ACCESS;
  4483. hwDeviceExtension->TrappedValidatorData[0].Data = *Data;
  4484. //
  4485. // Start keeping track of the state of the sequencer port.
  4486. //
  4487. hwDeviceExtension->SequencerAddressValue = IND_SYNC_RESET;
  4488. } else {
  4489. VideoPortWritePortUchar(hwDeviceExtension->IOAddress + Port,
  4490. *Data);
  4491. }
  4492. } else {
  4493. *Data = VideoPortReadPortUchar(hwDeviceExtension->IOAddress + Port);
  4494. }
  4495. }
  4496. return NO_ERROR;
  4497. } // end VgaValidatorUcharEntry()
  4498. VP_STATUS
  4499. VgaValidatorUshortEntry(
  4500. ULONG Context,
  4501. ULONG Port,
  4502. UCHAR AccessMode,
  4503. PUSHORT Data
  4504. )
  4505. /*++
  4506. Routine Description:
  4507. Entry point into the validator for word I/O operations.
  4508. The entry point will be called whenever a byte operation was performed
  4509. by a DOS application on one of the specified Video ports. The kernel
  4510. emulator will forward these requests.
  4511. Arguments:
  4512. Context - Context value that is passed to each call made to the validator
  4513. function. This is the value the miniport driver specified in the
  4514. MiniportConfigInfo->EmulatorAccessEntriesContext.
  4515. Port - Port on which the operation is to be performed.
  4516. AccessMode - Determines if it is a read or write operation.
  4517. Data - Pointer to a variable containing the data to be written or a
  4518. variable into which the read data should be stored.
  4519. Return Value:
  4520. NO_ERROR.
  4521. --*/
  4522. {
  4523. PHW_DEVICE_EXTENSION hwDeviceExtension = (PHW_DEVICE_EXTENSION) Context;
  4524. ULONG endEmulation;
  4525. UCHAR temp;
  4526. if (hwDeviceExtension->TrappedValidatorCount) {
  4527. //
  4528. // If we are processing a WRITE instruction, then store it in the
  4529. // playback buffer. If the buffer is full, then play it back right
  4530. // away, end sync reset and reinitialize the buffer with a sync
  4531. // reset instruction.
  4532. //
  4533. // If we have a READ, we must flush the buffer (which has the side
  4534. // effect of starting SyncReset), perform the read operation, stop
  4535. // sync reset, and put back a sync reset instruction in the buffer
  4536. // so we can go on appropriately
  4537. //
  4538. if (AccessMode & EMULATOR_WRITE_ACCESS) {
  4539. //
  4540. // Make sure Bit 3 of the Miscellaneous register is always 0.
  4541. // If it is 1 it could select a non-existent clock, and kill the
  4542. // system
  4543. //
  4544. if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
  4545. *Data &= 0xFFF7;
  4546. }
  4547. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4548. TrappedValidatorCount].Port = Port;
  4549. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4550. TrappedValidatorCount].AccessType = VGA_VALIDATOR_USHORT_ACCESS;
  4551. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4552. TrappedValidatorCount].Data = *Data;
  4553. hwDeviceExtension->TrappedValidatorCount++;
  4554. //
  4555. // Check to see if this instruction was ending sync reset.
  4556. // If it did, we must flush the buffer and reset the trapped
  4557. // IO ports to the minimal set.
  4558. //
  4559. if (Port == SEQ_ADDRESS_PORT) {
  4560. //
  4561. // If we are accessing the seq address port, keep track of its
  4562. // value
  4563. //
  4564. hwDeviceExtension->SequencerAddressValue = (*Data & 0xFF);
  4565. }
  4566. if ((Port == SEQ_ADDRESS_PORT) &&
  4567. ( ((*Data >> 8) & END_SYNC_RESET_VALUE) ==
  4568. END_SYNC_RESET_VALUE) &&
  4569. (hwDeviceExtension->SequencerAddressValue == IND_SYNC_RESET)) {
  4570. endEmulation = 1;
  4571. } else {
  4572. //
  4573. // If the buffer is not full, then just return right away.
  4574. //
  4575. if (hwDeviceExtension->TrappedValidatorCount <
  4576. VGA_MAX_VALIDATOR_DATA - 1) {
  4577. return NO_ERROR;
  4578. }
  4579. endEmulation = 0;
  4580. }
  4581. }
  4582. //
  4583. // We are either in a READ path or a WRITE path that caused a
  4584. // a full buffer. So flush the buffer either way.
  4585. //
  4586. // To do this put an END_SYNC_RESET at the end since we want to make
  4587. // the buffer is ended sync reset ended.
  4588. //
  4589. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4590. TrappedValidatorCount].Port = SEQ_ADDRESS_PORT;
  4591. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4592. TrappedValidatorCount].AccessType = VGA_VALIDATOR_USHORT_ACCESS;
  4593. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4594. TrappedValidatorCount].Data = (USHORT) (IND_SYNC_RESET +
  4595. (END_SYNC_RESET_VALUE << 8));
  4596. hwDeviceExtension->TrappedValidatorCount++;
  4597. VideoPortSynchronizeExecution(hwDeviceExtension,
  4598. VpHighPriority,
  4599. (PMINIPORT_SYNCHRONIZE_ROUTINE)
  4600. VgaPlaybackValidatorData,
  4601. hwDeviceExtension);
  4602. //
  4603. // Write back the real value of the sequencer address port.
  4604. //
  4605. VideoPortWritePortUchar((PUCHAR) (hwDeviceExtension->IOAddress +
  4606. SEQ_ADDRESS_PORT),
  4607. (UCHAR) hwDeviceExtension->SequencerAddressValue);
  4608. //
  4609. // If we are in a READ path, read the data
  4610. //
  4611. if (AccessMode & EMULATOR_READ_ACCESS) {
  4612. *Data = VideoPortReadPortUshort((PUSHORT)(hwDeviceExtension->IOAddress
  4613. + Port));
  4614. endEmulation = 0;
  4615. }
  4616. //
  4617. // If we are ending emulation, reset trapping to the minimal amount
  4618. // and exit.
  4619. //
  4620. if (endEmulation) {
  4621. VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
  4622. NUM_MINIMAL_VGA_VALIDATOR_ACCESS_RANGE,
  4623. MinimalVgaValidatorAccessRange);
  4624. return NO_ERROR;
  4625. }
  4626. //
  4627. // For both cases, put back a START_SYNC_RESET in the buffer.
  4628. //
  4629. hwDeviceExtension->TrappedValidatorCount = 1;
  4630. hwDeviceExtension->TrappedValidatorData[0].Port = SEQ_ADDRESS_PORT;
  4631. hwDeviceExtension->TrappedValidatorData[0].AccessType =
  4632. VGA_VALIDATOR_USHORT_ACCESS;
  4633. hwDeviceExtension->TrappedValidatorData[0].Data =
  4634. (ULONG) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8));
  4635. } else {
  4636. //
  4637. // Nothing trapped.
  4638. // Lets check is the IO is trying to do something that would require
  4639. // us to stop trapping
  4640. //
  4641. if (AccessMode & EMULATOR_WRITE_ACCESS) {
  4642. //
  4643. // Make sure Bit 3 of the Miscelaneous register is always 0.
  4644. // If it is 1 it could select a non-existant clock, and kill the
  4645. // system
  4646. //
  4647. if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
  4648. temp = VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
  4649. SEQ_ADDRESS_PORT);
  4650. VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
  4651. SEQ_ADDRESS_PORT),
  4652. (USHORT) (IND_SYNC_RESET +
  4653. (START_SYNC_RESET_VALUE << 8)));
  4654. VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
  4655. (ULONG)Port),
  4656. (USHORT) (*Data & 0xFFF7) );
  4657. VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
  4658. SEQ_ADDRESS_PORT),
  4659. (USHORT) (IND_SYNC_RESET +
  4660. (END_SYNC_RESET_VALUE << 8)));
  4661. VideoPortWritePortUchar(hwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
  4662. temp);
  4663. return NO_ERROR;
  4664. }
  4665. if ( (Port == SEQ_ADDRESS_PORT) &&
  4666. (((*Data>> 8) & END_SYNC_RESET_VALUE) != END_SYNC_RESET_VALUE) &&
  4667. ((*Data & 0xFF) == IND_SYNC_RESET)) {
  4668. VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
  4669. NUM_FULL_VGA_VALIDATOR_ACCESS_RANGE,
  4670. FullVgaValidatorAccessRange);
  4671. hwDeviceExtension->TrappedValidatorCount = 1;
  4672. hwDeviceExtension->TrappedValidatorData[0].Port = Port;
  4673. hwDeviceExtension->TrappedValidatorData[0].AccessType =
  4674. VGA_VALIDATOR_USHORT_ACCESS;
  4675. hwDeviceExtension->TrappedValidatorData[0].Data = *Data;
  4676. //
  4677. // Start keeping track of the state of the sequencer port.
  4678. //
  4679. hwDeviceExtension->SequencerAddressValue = IND_SYNC_RESET;
  4680. } else {
  4681. VideoPortWritePortUshort((PUSHORT)(hwDeviceExtension->IOAddress +
  4682. Port),
  4683. *Data);
  4684. }
  4685. } else {
  4686. *Data = VideoPortReadPortUshort((PUSHORT)(hwDeviceExtension->IOAddress +
  4687. Port));
  4688. }
  4689. }
  4690. return NO_ERROR;
  4691. } // end VgaValidatorUshortEntry()
  4692. VP_STATUS
  4693. VgaValidatorUlongEntry(
  4694. ULONG Context,
  4695. ULONG Port,
  4696. UCHAR AccessMode,
  4697. PULONG Data
  4698. )
  4699. /*++
  4700. Routine Description:
  4701. Entry point into the validator for dword I/O operations.
  4702. The entry point will be called whenever a byte operation was performed
  4703. by a DOS application on one of the specified Video ports. The kernel
  4704. emulator will forward these requests.
  4705. Arguments:
  4706. Context - Context value that is passed to each call made to the validator
  4707. function. This is the value the miniport driver specified in the
  4708. MiniportConfigInfo->EmulatorAccessEntriesContext.
  4709. Port - Port on which the operation is to be performed.
  4710. AccessMode - Determines if it is a read or write operation.
  4711. Data - Pointer to a variable containing the data to be written or a
  4712. variable into which the read data should be stored.
  4713. Return Value:
  4714. NO_ERROR.
  4715. --*/
  4716. {
  4717. PHW_DEVICE_EXTENSION hwDeviceExtension = (PHW_DEVICE_EXTENSION) Context;
  4718. ULONG endEmulation;
  4719. UCHAR temp;
  4720. if (hwDeviceExtension->TrappedValidatorCount) {
  4721. //
  4722. // If we are processing a WRITE instruction, then store it in the
  4723. // playback buffer. If the buffer is full, then play it back right
  4724. // away, end sync reset and reinitialize the buffer with a sync
  4725. // reset instruction.
  4726. //
  4727. // If we have a READ, we must flush the buffer (which has the side
  4728. // effect of starting SyncReset), perform the read operation, stop
  4729. // sync reset, and put back a sync reset instruction in the buffer
  4730. // so we can go on appropriately
  4731. //
  4732. if (AccessMode & EMULATOR_WRITE_ACCESS) {
  4733. //
  4734. // Make sure Bit 3 of the Miscellaneous register is always 0.
  4735. // If it is 1 it could select a non-existent clock, and kill the
  4736. // system
  4737. //
  4738. if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
  4739. *Data &= 0xFFFFFFF7;
  4740. }
  4741. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4742. TrappedValidatorCount].Port = Port;
  4743. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4744. TrappedValidatorCount].AccessType = VGA_VALIDATOR_ULONG_ACCESS;
  4745. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4746. TrappedValidatorCount].Data = *Data;
  4747. hwDeviceExtension->TrappedValidatorCount++;
  4748. //
  4749. // Check to see if this instruction was ending sync reset.
  4750. // If it did, we must flush the buffer and reset the trapped
  4751. // IO ports to the minimal set.
  4752. //
  4753. if (Port == SEQ_ADDRESS_PORT) {
  4754. //
  4755. // If we are accessing the seq address port, keep track of its
  4756. // value
  4757. //
  4758. hwDeviceExtension->SequencerAddressValue = (*Data & 0xFF);
  4759. }
  4760. if ((Port == SEQ_ADDRESS_PORT) &&
  4761. ( ((*Data >> 8) & END_SYNC_RESET_VALUE) ==
  4762. END_SYNC_RESET_VALUE) &&
  4763. (hwDeviceExtension->SequencerAddressValue == IND_SYNC_RESET)) {
  4764. endEmulation = 1;
  4765. } else {
  4766. //
  4767. // If the buffer is not full, then just return right away.
  4768. //
  4769. if (hwDeviceExtension->TrappedValidatorCount <
  4770. VGA_MAX_VALIDATOR_DATA - 1) {
  4771. return NO_ERROR;
  4772. }
  4773. endEmulation = 0;
  4774. }
  4775. }
  4776. //
  4777. // We are either in a READ path or a WRITE path that caused a
  4778. // a full buffer. So flush the buffer either way.
  4779. //
  4780. // To do this put an END_SYNC_RESET at the end since we want to make
  4781. // the buffer is ended sync reset ended.
  4782. //
  4783. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4784. TrappedValidatorCount].Port = SEQ_ADDRESS_PORT;
  4785. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4786. TrappedValidatorCount].AccessType = VGA_VALIDATOR_USHORT_ACCESS;
  4787. hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
  4788. TrappedValidatorCount].Data = (USHORT) (IND_SYNC_RESET +
  4789. (END_SYNC_RESET_VALUE << 8));
  4790. hwDeviceExtension->TrappedValidatorCount++;
  4791. VideoPortSynchronizeExecution(hwDeviceExtension,
  4792. VpHighPriority,
  4793. (PMINIPORT_SYNCHRONIZE_ROUTINE)
  4794. VgaPlaybackValidatorData,
  4795. hwDeviceExtension);
  4796. //
  4797. // Write back the real value of the sequencer address port.
  4798. //
  4799. VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
  4800. SEQ_ADDRESS_PORT,
  4801. (UCHAR) hwDeviceExtension->SequencerAddressValue);
  4802. //
  4803. // If we are in a READ path, read the data
  4804. //
  4805. if (AccessMode & EMULATOR_READ_ACCESS) {
  4806. *Data = VideoPortReadPortUlong((PULONG) (hwDeviceExtension->IOAddress +
  4807. Port));
  4808. endEmulation = 0;
  4809. }
  4810. //
  4811. // If we are ending emulation, reset trapping to the minimal amount
  4812. // and exit.
  4813. //
  4814. if (endEmulation) {
  4815. VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
  4816. NUM_MINIMAL_VGA_VALIDATOR_ACCESS_RANGE,
  4817. MinimalVgaValidatorAccessRange);
  4818. return NO_ERROR;
  4819. }
  4820. //
  4821. // For both cases, put back a START_SYNC_RESET in the buffer.
  4822. //
  4823. hwDeviceExtension->TrappedValidatorCount = 1;
  4824. hwDeviceExtension->TrappedValidatorData[0].Port = SEQ_ADDRESS_PORT;
  4825. hwDeviceExtension->TrappedValidatorData[0].AccessType =
  4826. VGA_VALIDATOR_USHORT_ACCESS;
  4827. hwDeviceExtension->TrappedValidatorData[0].Data =
  4828. (ULONG) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8));
  4829. } else {
  4830. //
  4831. // Nothing trapped.
  4832. // Lets check is the IO is trying to do something that would require
  4833. // us to stop trapping
  4834. //
  4835. if (AccessMode & EMULATOR_WRITE_ACCESS) {
  4836. //
  4837. // Make sure Bit 3 of the Miscelaneous register is always 0.
  4838. // If it is 1 it could select a non-existant clock, and kill the
  4839. // system
  4840. //
  4841. if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
  4842. temp = VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
  4843. SEQ_ADDRESS_PORT);
  4844. VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
  4845. SEQ_ADDRESS_PORT),
  4846. (USHORT) (IND_SYNC_RESET +
  4847. (START_SYNC_RESET_VALUE << 8)));
  4848. VideoPortWritePortUlong((PULONG) (hwDeviceExtension->IOAddress +
  4849. Port),
  4850. (ULONG) (*Data & 0xFFFFFFF7) );
  4851. VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
  4852. SEQ_ADDRESS_PORT),
  4853. (USHORT) (IND_SYNC_RESET +
  4854. (END_SYNC_RESET_VALUE << 8)));
  4855. VideoPortWritePortUchar(hwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
  4856. temp);
  4857. return NO_ERROR;
  4858. }
  4859. if ( (Port == SEQ_ADDRESS_PORT) &&
  4860. (((*Data>> 8) & END_SYNC_RESET_VALUE) != END_SYNC_RESET_VALUE) &&
  4861. ((*Data & 0xFF) == IND_SYNC_RESET)) {
  4862. VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
  4863. NUM_FULL_VGA_VALIDATOR_ACCESS_RANGE,
  4864. FullVgaValidatorAccessRange);
  4865. hwDeviceExtension->TrappedValidatorCount = 1;
  4866. hwDeviceExtension->TrappedValidatorData[0].Port = Port;
  4867. hwDeviceExtension->TrappedValidatorData[0].AccessType =
  4868. VGA_VALIDATOR_ULONG_ACCESS;
  4869. hwDeviceExtension->TrappedValidatorData[0].Data = *Data;
  4870. //
  4871. // Start keeping track of the state of the sequencer port.
  4872. //
  4873. hwDeviceExtension->SequencerAddressValue = IND_SYNC_RESET;
  4874. } else {
  4875. VideoPortWritePortUlong((PULONG) (hwDeviceExtension->IOAddress +
  4876. Port),
  4877. *Data);
  4878. }
  4879. } else {
  4880. *Data = VideoPortReadPortUlong((PULONG) (hwDeviceExtension->IOAddress +
  4881. Port));
  4882. }
  4883. }
  4884. return NO_ERROR;
  4885. } // end VgaValidatorUlongEntry()
  4886. BOOLEAN
  4887. VgaPlaybackValidatorData(
  4888. PVOID Context
  4889. )
  4890. /*++
  4891. Routine Description:
  4892. Performs all the DOS apps IO port accesses that were trapped by the
  4893. validator. Only IO accesses that can be processed are WRITEs
  4894. The number of outstanding IO access in deviceExtension is set to
  4895. zero as a side effect.
  4896. This function must be called via a call to VideoPortSynchronizeRoutine.
  4897. Arguments:
  4898. Context - Context parameter passed to the synchronized routine.
  4899. Must be a pointer to the miniport driver's device extension.
  4900. Return Value:
  4901. TRUE.
  4902. --*/
  4903. {
  4904. PHW_DEVICE_EXTENSION hwDeviceExtension = Context;
  4905. ULONG ioBaseAddress = (ULONG) hwDeviceExtension->IOAddress;
  4906. ULONG i;
  4907. PVGA_VALIDATOR_DATA validatorData = hwDeviceExtension->TrappedValidatorData;
  4908. //
  4909. // Loop through the array of data and do instructions one by one.
  4910. //
  4911. for (i = 0; i < hwDeviceExtension->TrappedValidatorCount;
  4912. i++, validatorData++) {
  4913. //
  4914. // Calculate base address first
  4915. //
  4916. ioBaseAddress = (ULONG)hwDeviceExtension->IOAddress +
  4917. validatorData->Port;
  4918. //
  4919. // This is a write operation. We will automatically stop when the
  4920. // buffer is empty.
  4921. //
  4922. switch (validatorData->AccessType) {
  4923. case VGA_VALIDATOR_UCHAR_ACCESS :
  4924. VideoPortWritePortUchar((PUCHAR)ioBaseAddress,
  4925. (UCHAR) validatorData->Data);
  4926. break;
  4927. case VGA_VALIDATOR_USHORT_ACCESS :
  4928. VideoPortWritePortUshort((PUSHORT)ioBaseAddress,
  4929. (USHORT) validatorData->Data);
  4930. break;
  4931. case VGA_VALIDATOR_ULONG_ACCESS :
  4932. VideoPortWritePortUlong((PULONG)ioBaseAddress,
  4933. (ULONG) validatorData->Data);
  4934. break;
  4935. default:
  4936. VideoDebugPrint((1, "InvalidValidatorAccessType\n" ));
  4937. }
  4938. }
  4939. hwDeviceExtension->TrappedValidatorCount = 0;
  4940. return TRUE;
  4941. } // end VgaPlaybackValidatorData()
  4942. VOID
  4943. UnlockET4000ExtendedRegs(
  4944. PHW_DEVICE_EXTENSION HwDeviceExtension
  4945. )
  4946. /*++
  4947. Routine Description:
  4948. Allows access to the ET4000's extended (non-standard) registers.
  4949. Arguments:
  4950. None.
  4951. Return Value:
  4952. None.
  4953. --*/
  4954. {
  4955. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4956. HERCULES_COMPATIBILITY_PORT, UNLOCK_KEY_1);
  4957. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  4958. MISC_OUTPUT_REG_READ_PORT) & 0x01) {
  4959. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4960. MODE_CONTROL_PORT_COLOR, UNLOCK_KEY_2);
  4961. } else {
  4962. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4963. MODE_CONTROL_PORT_MONO, UNLOCK_KEY_2);
  4964. }
  4965. } // end UnlockET4000ExtendedRegs()
  4966. VOID
  4967. LockET4000ExtendedRegs(
  4968. PHW_DEVICE_EXTENSION HwDeviceExtension
  4969. )
  4970. /*++
  4971. Routine Description:
  4972. Turns off access to the ET4000's extended (non-standard) registers.
  4973. Arguments:
  4974. None.
  4975. Return Value:
  4976. None.
  4977. --*/
  4978. {
  4979. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4980. HERCULES_COMPATIBILITY_PORT, LOCK_KEY_1);
  4981. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  4982. MISC_OUTPUT_REG_READ_PORT) & 0x01) {
  4983. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4984. MODE_CONTROL_PORT_COLOR, LOCK_KEY_2);
  4985. } else {
  4986. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  4987. MODE_CONTROL_PORT_MONO, LOCK_KEY_2);
  4988. }
  4989. } // end LockET4000ExtendedRegs()
  4990. VOID
  4991. ResetACToggle(
  4992. PHW_DEVICE_EXTENSION HwDeviceExtension
  4993. )
  4994. /*++
  4995. Routine Description:
  4996. Resets the Attribute Controller Index/Data toggle to the Index state.
  4997. Arguments:
  4998. None.
  4999. Return Value:
  5000. None.
  5001. --*/
  5002. {
  5003. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  5004. MISC_OUTPUT_REG_READ_PORT) & 0x01) {
  5005. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  5006. INPUT_STATUS_1_COLOR);
  5007. } else {
  5008. VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  5009. INPUT_STATUS_1_MONO);
  5010. }
  5011. } // end ResetACToggle()
  5012. #if (_WIN32_WINNT >= 500)
  5013. VP_STATUS
  5014. ET4000GetPowerState(
  5015. PHW_DEVICE_EXTENSION HwDeviceExtension,
  5016. ULONG HwDeviceId,
  5017. PVIDEO_POWER_MANAGEMENT VideoPowerManagement
  5018. )
  5019. /*++
  5020. Routine Description:
  5021. This function is called to see if a given device can go into a given
  5022. power state.
  5023. Arguments:
  5024. HwDeviceExtension - Pointer to our hardware device extension structure.
  5025. HwDeviceId - Private unique 32 bit ID identifing the device.
  5026. 0xFFFFFFFF indicates the S3 card itself.
  5027. VideoPowerManagement - Pointer to the power management structure which
  5028. indicates the power state in question.
  5029. Return Value:
  5030. NO_ERROR if the device can go into the requested power state,
  5031. otherwise an appropriate error code is returned.
  5032. --*/
  5033. {
  5034. //
  5035. // We only support power setting for the monitor. Make sure the
  5036. // HwDeviceId matches one the the monitors we could report.
  5037. //
  5038. if ((HwDeviceId == QUERY_NONDDC_MONITOR_ID) ||
  5039. (HwDeviceId == QUERY_MONITOR_ID)) {
  5040. VIDEO_X86_BIOS_ARGUMENTS biosArguments;
  5041. //
  5042. // We are querying the power support for the monitor.
  5043. //
  5044. if ((VideoPowerManagement->PowerState == VideoPowerOn) ||
  5045. (VideoPowerManagement->PowerState == VideoPowerHibernate)) {
  5046. return NO_ERROR;
  5047. }
  5048. VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  5049. biosArguments.Eax = VESA_POWER_FUNCTION;
  5050. biosArguments.Ebx = VESA_GET_POWER_FUNC;
  5051. VideoPortInt10(HwDeviceExtension, &biosArguments);
  5052. if ((biosArguments.Eax & 0xffff) == VESA_STATUS_SUCCESS) {
  5053. switch (VideoPowerManagement->PowerState) {
  5054. case VideoPowerStandBy:
  5055. return (biosArguments.Ebx & VESA_POWER_STANDBY) ?
  5056. NO_ERROR : ERROR_INVALID_FUNCTION;
  5057. case VideoPowerSuspend:
  5058. return (biosArguments.Ebx & VESA_POWER_SUSPEND) ?
  5059. NO_ERROR : ERROR_INVALID_FUNCTION;
  5060. case VideoPowerOff:
  5061. return (biosArguments.Ebx & VESA_POWER_OFF) ?
  5062. NO_ERROR : ERROR_INVALID_FUNCTION;
  5063. default:
  5064. break;
  5065. }
  5066. }
  5067. VideoDebugPrint((1, "This device does not support Power Management.\n"));
  5068. return ERROR_INVALID_FUNCTION;
  5069. } else if (HwDeviceId == DISPLAY_ADAPTER_HW_ID) {
  5070. //
  5071. // We are querying power support for the graphics card.
  5072. //
  5073. switch (VideoPowerManagement->PowerState) {
  5074. case VideoPowerOn:
  5075. case VideoPowerStandBy:
  5076. case VideoPowerHibernate:
  5077. return NO_ERROR;
  5078. case VideoPowerOff:
  5079. case VideoPowerSuspend:
  5080. //
  5081. // Indicate that we can't do VideoPowerOff, because
  5082. // we have no way of coming back when power is re-applied
  5083. // to the card.
  5084. //
  5085. return ERROR_INVALID_FUNCTION;
  5086. default:
  5087. ASSERT(FALSE);
  5088. return ERROR_INVALID_FUNCTION;
  5089. }
  5090. } else {
  5091. VideoDebugPrint((1, "Unknown HwDeviceId"));
  5092. ASSERT(FALSE);
  5093. return ERROR_INVALID_PARAMETER;
  5094. }
  5095. }
  5096. VP_STATUS
  5097. ET4000SetPowerState(
  5098. PHW_DEVICE_EXTENSION HwDeviceExtension,
  5099. ULONG HwDeviceId,
  5100. PVIDEO_POWER_MANAGEMENT VideoPowerManagement
  5101. )
  5102. /*++
  5103. Routine Description:
  5104. Set the power state for a given device.
  5105. Arguments:
  5106. HwDeviceExtension - Pointer to our hardware device extension structure.
  5107. HwDeviceId - Private unique 32 bit ID identifing the device.
  5108. VideoPowerManagement - Power state information.
  5109. Return Value:
  5110. TRUE if power state can be set,
  5111. FALSE otherwise.
  5112. --*/
  5113. {
  5114. //
  5115. // Make sure we recognize the device.
  5116. //
  5117. if ((HwDeviceId == QUERY_NONDDC_MONITOR_ID) ||
  5118. (HwDeviceId == QUERY_MONITOR_ID)) {
  5119. VIDEO_X86_BIOS_ARGUMENTS biosArguments;
  5120. VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  5121. biosArguments.Eax = VESA_POWER_FUNCTION;
  5122. biosArguments.Ebx = VESA_SET_POWER_FUNC;
  5123. switch (VideoPowerManagement->PowerState) {
  5124. case VideoPowerOn:
  5125. case VideoPowerHibernate:
  5126. biosArguments.Ebx |= VESA_POWER_ON;
  5127. break;
  5128. case VideoPowerStandBy:
  5129. biosArguments.Ebx |= VESA_POWER_STANDBY;
  5130. break;
  5131. case VideoPowerSuspend:
  5132. biosArguments.Ebx |= VESA_POWER_SUSPEND;
  5133. break;
  5134. case VideoPowerOff:
  5135. biosArguments.Ebx |= VESA_POWER_OFF;
  5136. break;
  5137. default:
  5138. VideoDebugPrint((1, "Unknown power state.\n"));
  5139. ASSERT(FALSE);
  5140. return ERROR_INVALID_PARAMETER;
  5141. }
  5142. VideoPortInt10(HwDeviceExtension, &biosArguments);
  5143. return NO_ERROR;
  5144. } else if (HwDeviceId == DISPLAY_ADAPTER_HW_ID) {
  5145. switch (VideoPowerManagement->PowerState) {
  5146. case VideoPowerOn:
  5147. case VideoPowerStandBy:
  5148. case VideoPowerSuspend:
  5149. case VideoPowerOff:
  5150. case VideoPowerHibernate:
  5151. return NO_ERROR;
  5152. default:
  5153. ASSERT(FALSE);
  5154. return ERROR_INVALID_PARAMETER;
  5155. }
  5156. } else {
  5157. VideoDebugPrint((1, "Unknown HwDeviceId"));
  5158. ASSERT(FALSE);
  5159. return ERROR_INVALID_PARAMETER;
  5160. }
  5161. }
  5162. //
  5163. // Routine to retrieve the Enhanced Display ID structure via DDC
  5164. //
  5165. ULONG
  5166. ET4000GetVideoChildDescriptor(
  5167. PVOID HwDeviceExtension,
  5168. PVIDEO_CHILD_ENUM_INFO ChildEnumInfo,
  5169. PVIDEO_CHILD_TYPE pChildType,
  5170. PVOID pvChildDescriptor,
  5171. PULONG pHwId,
  5172. PULONG pUnused
  5173. )
  5174. {
  5175. PHW_DEVICE_EXTENSION pHwDeviceExtension = HwDeviceExtension;
  5176. ULONG Status;
  5177. ASSERT(pHwDeviceExtension != NULL && pMoreChildren != NULL);
  5178. VideoDebugPrint((2, "ET4000.SYS ET4000GetVideoChildDescriptor: *** Entry point ***\n"));
  5179. //
  5180. // Determine if the graphics adapter in the system supports
  5181. // DDC2 (our miniport only supports DDC2, not DDC1). This has
  5182. // the side effect (assuming both monitor and card support
  5183. // DDC2) of switching the monitor from DDC1 mode (repeated
  5184. // "blind" broadcast of EDID clocked by the vertical sync
  5185. // signal) to DDC2 mode (query/response not using any of the
  5186. // normal video lines - can transfer information rapidly
  5187. // without first disrupting the screen by switching into
  5188. // a pseudo-mode with a high vertical sync frequency).
  5189. //
  5190. // Since we must support hot-plugging of monitors, and our
  5191. // routine to obtain the EDID structure via DDC2 assumes that
  5192. // the monitor is in DDC2 mode, we must make this test each
  5193. // time this entry point is called.
  5194. //
  5195. switch (ChildEnumInfo->ChildIndex) {
  5196. case 0:
  5197. //
  5198. // Case 0 is used to enumerate devices found by the ACPI firmware.
  5199. //
  5200. // Since we do not support ACPI devices yet, we must return failure.
  5201. //
  5202. Status = ERROR_NO_MORE_DEVICES;
  5203. break;
  5204. case 1:
  5205. //
  5206. // We do not support monitor enumeration
  5207. //
  5208. Status = ERROR_NO_MORE_DEVICES;
  5209. break;
  5210. case DISPLAY_ADAPTER_HW_ID:
  5211. {
  5212. PUSHORT pPnpDeviceDescription = NULL;
  5213. ULONG stringSize = sizeof(L"*PNPXXXX");
  5214. //
  5215. // Special ID to handle return legacy PnP IDs for root enumerated
  5216. // devices.
  5217. //
  5218. *pChildType = VideoChip;
  5219. *pHwId = DISPLAY_ADAPTER_HW_ID;
  5220. //
  5221. // Figure out which card type and set pPnpDeviceDescription at
  5222. // associated string.
  5223. //
  5224. if ((pHwDeviceExtension->ulChipID == ET4000) ||
  5225. (pHwDeviceExtension->ulChipID == ET6000))
  5226. pPnpDeviceDescription = L"*PNP0906";
  5227. else if (pHwDeviceExtension->ulChipID == W32)
  5228. pPnpDeviceDescription = L"*PNP0912";
  5229. else if (pHwDeviceExtension->ulChipID == W32P)
  5230. pPnpDeviceDescription = L"*PNP091A";
  5231. else if (pHwDeviceExtension->ulChipID == W32I)
  5232. pPnpDeviceDescription = L"*PNP091A";
  5233. //
  5234. // Now just copy the string into memory provided.
  5235. //
  5236. if (pPnpDeviceDescription)
  5237. memcpy(pvChildDescriptor, pPnpDeviceDescription, stringSize);
  5238. Status = ERROR_MORE_DATA;
  5239. break;
  5240. }
  5241. default:
  5242. Status = ERROR_NO_MORE_DEVICES;
  5243. break;
  5244. }
  5245. return Status;
  5246. }
  5247. #endif // _WIN32_WINNT >= 500