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.

7386 lines
220 KiB

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