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.

1000 lines
26 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. modeset.c
  5. Abstract:
  6. This is the modeset code for the VGA miniport driver.
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. Revision History:
  11. --*/
  12. #include "dderror.h"
  13. #include "devioctl.h"
  14. #include "miniport.h"
  15. #include "ntddvdeo.h"
  16. #include "video.h"
  17. #include "vga.h"
  18. #include "vesa.h"
  19. #include "cmdcnst.h"
  20. #if defined(ALLOC_PRAGMA)
  21. #pragma alloc_text(PAGE,VgaQueryAvailableModes)
  22. #pragma alloc_text(PAGE,VgaQueryNumberOfAvailableModes)
  23. #pragma alloc_text(PAGE,VgaQueryCurrentMode)
  24. #pragma alloc_text(PAGE,VgaSetMode)
  25. #pragma alloc_text(PAGE,VgaInterpretCmdStream)
  26. #pragma alloc_text(PAGE,VgaZeroVideoMemory)
  27. #endif
  28. VP_STATUS
  29. VgaInterpretCmdStream(
  30. PHW_DEVICE_EXTENSION HwDeviceExtension,
  31. PUSHORT pusCmdStream
  32. )
  33. /*++
  34. Routine Description:
  35. Interprets the appropriate command array to set up VGA registers for the
  36. requested mode. Typically used to set the VGA into a particular mode by
  37. programming all of the registers
  38. Arguments:
  39. HwDeviceExtension - Pointer to the miniport driver's device extension.
  40. pusCmdStream - array of commands to be interpreted.
  41. Return Value:
  42. The status of the operation (can only fail on a bad command); TRUE for
  43. success, FALSE for failure.
  44. --*/
  45. {
  46. ULONG ulCmd;
  47. ULONG_PTR ulPort;
  48. UCHAR jValue;
  49. USHORT usValue;
  50. ULONG culCount;
  51. ULONG ulIndex;
  52. ULONG_PTR ulBase;
  53. if (pusCmdStream == NULL) {
  54. VideoDebugPrint((1, "VgaInterpretCmdStream - Invalid pusCmdStream\n"));
  55. return TRUE;
  56. }
  57. ulBase = (ULONG_PTR)HwDeviceExtension->IOAddress;
  58. //
  59. // Now set the adapter to the desired mode.
  60. //
  61. while ((ulCmd = *pusCmdStream++) != EOD) {
  62. //
  63. // Determine major command type
  64. //
  65. switch (ulCmd & 0xF0) {
  66. //
  67. // Basic input/output command
  68. //
  69. case INOUT:
  70. //
  71. // Determine type of inout instruction
  72. //
  73. if (!(ulCmd & IO)) {
  74. //
  75. // Out instruction. Single or multiple outs?
  76. //
  77. if (!(ulCmd & MULTI)) {
  78. //
  79. // Single out. Byte or word out?
  80. //
  81. if (!(ulCmd & BW)) {
  82. //
  83. // Single byte out
  84. //
  85. ulPort = *pusCmdStream++;
  86. jValue = (UCHAR) *pusCmdStream++;
  87. VideoPortWritePortUchar((PUCHAR)(ulBase+ulPort),
  88. jValue);
  89. } else {
  90. //
  91. // Single word out
  92. //
  93. ulPort = *pusCmdStream++;
  94. usValue = *pusCmdStream++;
  95. VideoPortWritePortUshort((PUSHORT)(ulBase+ulPort),
  96. usValue);
  97. }
  98. } else {
  99. //
  100. // Output a string of values
  101. // Byte or word outs?
  102. //
  103. if (!(ulCmd & BW)) {
  104. //
  105. // String byte outs. Do in a loop; can't use
  106. // VideoPortWritePortBufferUchar because the data
  107. // is in USHORT form
  108. //
  109. ulPort = ulBase + *pusCmdStream++;
  110. culCount = *pusCmdStream++;
  111. while (culCount--) {
  112. jValue = (UCHAR) *pusCmdStream++;
  113. VideoPortWritePortUchar((PUCHAR)ulPort,
  114. jValue);
  115. }
  116. } else {
  117. //
  118. // String word outs
  119. //
  120. ulPort = *pusCmdStream++;
  121. culCount = *pusCmdStream++;
  122. VideoPortWritePortBufferUshort((PUSHORT)
  123. (ulBase + ulPort), pusCmdStream, culCount);
  124. pusCmdStream += culCount;
  125. }
  126. }
  127. } else {
  128. // In instruction
  129. //
  130. // Currently, string in instructions aren't supported; all
  131. // in instructions are handled as single-byte ins
  132. //
  133. // Byte or word in?
  134. //
  135. if (!(ulCmd & BW)) {
  136. //
  137. // Single byte in
  138. //
  139. ulPort = *pusCmdStream++;
  140. jValue = VideoPortReadPortUchar((PUCHAR)ulBase+ulPort);
  141. } else {
  142. //
  143. // Single word in
  144. //
  145. ulPort = *pusCmdStream++;
  146. usValue = VideoPortReadPortUshort((PUSHORT)
  147. (ulBase+ulPort));
  148. }
  149. }
  150. break;
  151. //
  152. // Higher-level input/output commands
  153. //
  154. case METAOUT:
  155. //
  156. // Determine type of metaout command, based on minor
  157. // command field
  158. //
  159. switch (ulCmd & 0x0F) {
  160. //
  161. // Indexed outs
  162. //
  163. case INDXOUT:
  164. ulPort = ulBase + *pusCmdStream++;
  165. culCount = *pusCmdStream++;
  166. ulIndex = *pusCmdStream++;
  167. while (culCount--) {
  168. usValue = (USHORT) (ulIndex +
  169. (((ULONG)(*pusCmdStream++)) << 8));
  170. VideoPortWritePortUshort((PUSHORT)ulPort, usValue);
  171. ulIndex++;
  172. }
  173. break;
  174. //
  175. // Masked out (read, AND, XOR, write)
  176. //
  177. case MASKOUT:
  178. ulPort = *pusCmdStream++;
  179. jValue = VideoPortReadPortUchar((PUCHAR)ulBase+ulPort);
  180. jValue &= *pusCmdStream++;
  181. jValue ^= *pusCmdStream++;
  182. VideoPortWritePortUchar((PUCHAR)ulBase + ulPort,
  183. jValue);
  184. break;
  185. //
  186. // Attribute Controller out
  187. //
  188. case ATCOUT:
  189. ulPort = ulBase + *pusCmdStream++;
  190. culCount = *pusCmdStream++;
  191. ulIndex = *pusCmdStream++;
  192. while (culCount--) {
  193. // Write Attribute Controller index
  194. VideoPortWritePortUchar((PUCHAR)ulPort,
  195. (UCHAR)ulIndex);
  196. // Write Attribute Controller data
  197. jValue = (UCHAR) *pusCmdStream++;
  198. VideoPortWritePortUchar((PUCHAR)ulPort, jValue);
  199. ulIndex++;
  200. }
  201. break;
  202. //
  203. // None of the above; error
  204. //
  205. default:
  206. return FALSE;
  207. }
  208. break;
  209. //
  210. // NOP
  211. //
  212. case NCMD:
  213. break;
  214. //
  215. // Unknown command; error
  216. //
  217. default:
  218. return FALSE;
  219. }
  220. }
  221. return TRUE;
  222. } // end VgaInterpretCmdStream()
  223. VP_STATUS
  224. VgaSetMode(
  225. PHW_DEVICE_EXTENSION HwDeviceExtension,
  226. PVIDEO_MODE Mode,
  227. ULONG ModeSize,
  228. PULONG FrameBufferIsMoved
  229. )
  230. /*++
  231. Routine Description:
  232. This routine sets the VGA into the requested mode.
  233. Arguments:
  234. HwDeviceExtension - Pointer to the miniport driver's device extension.
  235. Mode - Pointer to the structure containing the information about the
  236. font to be set.
  237. ModeSize - Length of the input buffer supplied by the user.
  238. Return Value:
  239. ERROR_INSUFFICIENT_BUFFER if the input buffer was not large enough
  240. for the input data.
  241. ERROR_INVALID_PARAMETER if the mode number is invalid.
  242. NO_ERROR if the operation completed successfully.
  243. --*/
  244. {
  245. PVIDEOMODE pRequestedMode;
  246. //
  247. // Check if the size of the data in the input buffer is large enough.
  248. //
  249. if (ModeSize < sizeof(VIDEO_MODE)) {
  250. return ERROR_INSUFFICIENT_BUFFER;
  251. }
  252. *FrameBufferIsMoved = 0;
  253. //
  254. // Extract the clear memory bit.
  255. //
  256. if (Mode->RequestedMode & VIDEO_MODE_NO_ZERO_MEMORY) {
  257. Mode->RequestedMode &= ~VIDEO_MODE_NO_ZERO_MEMORY;
  258. } else {
  259. if (IS_LINEAR_MODE(&VgaModeList[Mode->RequestedMode]) == FALSE) {
  260. VgaZeroVideoMemory(HwDeviceExtension);
  261. }
  262. }
  263. //
  264. // Check to see if we are requesting a vlid mode
  265. //
  266. if (Mode->RequestedMode >= NumVideoModes) {
  267. ASSERT(FALSE);
  268. return ERROR_INVALID_PARAMETER;
  269. }
  270. pRequestedMode = &VgaModeList[Mode->RequestedMode];
  271. #ifdef INT10_MODE_SET
  272. {
  273. VIDEO_X86_BIOS_ARGUMENTS biosArguments;
  274. UCHAR temp;
  275. UCHAR dummy;
  276. UCHAR bIsColor;
  277. ULONG modeNumber;
  278. VP_STATUS status;
  279. ULONG MemoryBase;
  280. VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
  281. modeNumber = pRequestedMode->Int10ModeNumber;
  282. VideoDebugPrint((1, "Setting Mode: (%d,%d) @ %d bpp\n",
  283. pRequestedMode->hres,
  284. pRequestedMode->vres,
  285. pRequestedMode->bitsPerPlane * pRequestedMode->numPlanes));
  286. biosArguments.Eax = modeNumber & 0x0000FFFF;
  287. biosArguments.Ebx = modeNumber >> 16;
  288. status = VideoPortInt10(HwDeviceExtension, &biosArguments);
  289. if (status != NO_ERROR) {
  290. ASSERT(FALSE);
  291. return status;
  292. }
  293. //
  294. // If this was the VESA mode modeset, check the return value in eax
  295. //
  296. if (modeNumber >> 16) {
  297. if ((biosArguments.Eax & 0x0000FFFF) != VESA_STATUS_SUCCESS) {
  298. VideoDebugPrint((0, "Mode set failed! AX = 0x%x\n", biosArguments.Eax));
  299. return ERROR_INVALID_PARAMETER;
  300. }
  301. //
  302. // Double check if the current mode is the mode we just set.
  303. // This is to workaround the BIOS problem of some cards.
  304. //
  305. biosArguments.Eax = 0x4F03;
  306. status = VideoPortInt10(HwDeviceExtension, &biosArguments);
  307. if ( (status == NO_ERROR) &&
  308. ((biosArguments.Eax & 0x0000FFFF) == VESA_STATUS_SUCCESS) &&
  309. ((biosArguments.Ebx & 0x1FF) != ((modeNumber >> 16) & 0x1FF))) {
  310. VideoDebugPrint((0, "VGA: The BIOS of this video card is buggy!\n"));
  311. return ERROR_INVALID_PARAMETER;
  312. }
  313. //
  314. // Set the scan line width if we are stretching scan lines to avoid
  315. // broken rasters.
  316. //
  317. if (pRequestedMode->PixelsPerScan != pRequestedMode->hres) {
  318. VideoDebugPrint((1, "Setting scan line length to %d pixels\n",
  319. pRequestedMode->PixelsPerScan));
  320. biosArguments.Eax = 0x4f06;
  321. biosArguments.Ebx = 0x00;
  322. biosArguments.Ecx = pRequestedMode->PixelsPerScan;
  323. status = VideoPortInt10(HwDeviceExtension, &biosArguments);
  324. if ((status != NO_ERROR) ||
  325. ((biosArguments.Eax & 0x0000FFFF) != VESA_STATUS_SUCCESS) ||
  326. ((biosArguments.Ecx & 0xFFFF) != pRequestedMode->PixelsPerScan)) {
  327. VideoDebugPrint((1, "Scan line status: eax = 0x%x\n", biosArguments.Eax));
  328. return ERROR_INVALID_PARAMETER;
  329. }
  330. }
  331. }
  332. //
  333. // If we are trying to go into mode X, then we are now in
  334. // 320x200 256 color mode. Now let's finish the modeset
  335. // into MODE X.
  336. //
  337. if (pRequestedMode->hres == 320) {
  338. if ((pRequestedMode->vres == 240) || (pRequestedMode->vres == 480)) {
  339. VgaInterpretCmdStream(HwDeviceExtension, ModeX240);
  340. } else if ((pRequestedMode->vres == 200) || (pRequestedMode->vres == 400)) {
  341. VgaInterpretCmdStream(HwDeviceExtension, ModeX200);
  342. }
  343. if ((pRequestedMode->vres == 400) || (pRequestedMode->vres == 480)) {
  344. VgaInterpretCmdStream(HwDeviceExtension, ModeXDoubleScans);
  345. }
  346. }
  347. //
  348. // Fix to get 640x350 text mode
  349. //
  350. if (!(pRequestedMode->fbType & VIDEO_MODE_GRAPHICS)) {
  351. if ((pRequestedMode->hres == 640) &&
  352. (pRequestedMode->vres == 350)) {
  353. VgaInterpretCmdStream(HwDeviceExtension, VGA_TEXT_1);
  354. } else {
  355. //
  356. // Fix to make sure we always set the colors in text mode to be
  357. // intensity, and not flashing
  358. // For this zero out the Mode Control Regsiter bit 3 (index 0x10
  359. // of the Attribute controller).
  360. //
  361. if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  362. MISC_OUTPUT_REG_READ_PORT) & 0x01) {
  363. bIsColor = TRUE;
  364. } else {
  365. bIsColor = FALSE;
  366. }
  367. if (bIsColor) {
  368. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  369. INPUT_STATUS_1_COLOR);
  370. } else {
  371. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  372. INPUT_STATUS_1_MONO);
  373. }
  374. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  375. ATT_ADDRESS_PORT, (0x10 | VIDEO_ENABLE));
  376. temp = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  377. ATT_DATA_READ_PORT);
  378. temp &= 0xF7;
  379. if (bIsColor) {
  380. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  381. INPUT_STATUS_1_COLOR);
  382. } else {
  383. dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  384. INPUT_STATUS_1_MONO);
  385. }
  386. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  387. ATT_ADDRESS_PORT, (0x10 | VIDEO_ENABLE));
  388. VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
  389. ATT_DATA_WRITE_PORT, temp);
  390. }
  391. }
  392. //
  393. // Retrieve the base address again. This is to handle the case
  394. // when pci reprograms the bar
  395. //
  396. MemoryBase = GetVideoMemoryBaseAddress(HwDeviceExtension, pRequestedMode);
  397. if (MemoryBase && pRequestedMode->MemoryBase != MemoryBase) {
  398. *FrameBufferIsMoved = 1;
  399. pRequestedMode->MemoryBase = MemoryBase;
  400. }
  401. }
  402. #else
  403. VgaInterpretCmdStream(HwDeviceExtension, pRequestedMode->CmdStrings);
  404. #endif
  405. //
  406. // Update the location of the physical frame buffer within video memory.
  407. //
  408. HwDeviceExtension->PhysicalVideoMemoryBase.LowPart =
  409. pRequestedMode->MemoryBase;
  410. HwDeviceExtension->PhysicalVideoMemoryLength =
  411. pRequestedMode->MemoryLength;
  412. HwDeviceExtension->PhysicalFrameBaseOffset.LowPart =
  413. pRequestedMode->FrameOffset;
  414. HwDeviceExtension->PhysicalFrameLength =
  415. pRequestedMode->FrameLength;
  416. //
  417. // Store the new mode value.
  418. //
  419. HwDeviceExtension->CurrentMode = pRequestedMode;
  420. HwDeviceExtension->ModeIndex = Mode->RequestedMode;
  421. return NO_ERROR;
  422. } //end VgaSetMode()
  423. VP_STATUS
  424. VgaQueryAvailableModes(
  425. PHW_DEVICE_EXTENSION HwDeviceExtension,
  426. PVIDEO_MODE_INFORMATION ModeInformation,
  427. ULONG ModeInformationSize,
  428. PULONG OutputSize
  429. )
  430. /*++
  431. Routine Description:
  432. This routine returns the list of all available available modes on the
  433. card.
  434. Arguments:
  435. HwDeviceExtension - Pointer to the miniport driver's device extension.
  436. ModeInformation - Pointer to the output buffer supplied by the user.
  437. This is where the list of all valid modes is stored.
  438. ModeInformationSize - Length of the output buffer supplied by the user.
  439. OutputSize - Pointer to a buffer in which to return the actual size of
  440. the data in the buffer. If the buffer was not large enough, this
  441. contains the minimum required buffer size.
  442. Return Value:
  443. ERROR_INSUFFICIENT_BUFFER if the output buffer was not large enough
  444. for the data being returned.
  445. NO_ERROR if the operation completed successfully.
  446. --*/
  447. {
  448. PVIDEO_MODE_INFORMATION videoModes = ModeInformation;
  449. ULONG i;
  450. UNREFERENCED_PARAMETER(HwDeviceExtension);
  451. //
  452. // Find out the size of the data to be put in the buffer and return
  453. // that in the status information (whether or not the information is
  454. // there). If the buffer passed in is not large enough return an
  455. // appropriate error code.
  456. //
  457. if (ModeInformationSize < (*OutputSize =
  458. NumVideoModes * sizeof(VIDEO_MODE_INFORMATION)) ) {
  459. return ERROR_INSUFFICIENT_BUFFER;
  460. }
  461. //
  462. // For each mode supported by the card, store the mode characteristics
  463. // in the output buffer.
  464. //
  465. for (i = 0; i < NumVideoModes; i++, videoModes++) {
  466. videoModes->Length = sizeof(VIDEO_MODE_INFORMATION);
  467. videoModes->ModeIndex = i;
  468. videoModes->VisScreenWidth = VgaModeList[i].hres;
  469. videoModes->ScreenStride = VgaModeList[i].wbytes;
  470. videoModes->VisScreenHeight = VgaModeList[i].vres;
  471. videoModes->NumberOfPlanes = VgaModeList[i].numPlanes;
  472. videoModes->BitsPerPlane = VgaModeList[i].bitsPerPlane;
  473. videoModes->Frequency = VgaModeList[i].frequency;
  474. videoModes->XMillimeter = 320; // temporary hardcoded constant
  475. videoModes->YMillimeter = 240; // temporary hardcoded constant
  476. if (VgaModeList[i].bitsPerPlane < 15) {
  477. videoModes->NumberRedBits = 6;
  478. videoModes->NumberGreenBits = 6;
  479. videoModes->NumberBlueBits = 6;
  480. videoModes->RedMask = 0;
  481. videoModes->GreenMask = 0;
  482. videoModes->BlueMask = 0;
  483. } else if (VgaModeList[i].bitsPerPlane == 15) {
  484. videoModes->NumberRedBits = 6;
  485. videoModes->NumberGreenBits = 6;
  486. videoModes->NumberBlueBits = 6;
  487. videoModes->RedMask = 0x1F << 10;
  488. videoModes->GreenMask = 0x1F << 5;
  489. videoModes->BlueMask = 0x1F;
  490. } else if (VgaModeList[i].bitsPerPlane == 16) {
  491. videoModes->NumberRedBits = 6;
  492. videoModes->NumberGreenBits = 6;
  493. videoModes->NumberBlueBits = 6;
  494. videoModes->RedMask = 0x1F << 11;
  495. videoModes->GreenMask = 0x3F << 5;
  496. videoModes->BlueMask = 0x1F;
  497. } else {
  498. videoModes->NumberRedBits = 8;
  499. videoModes->NumberGreenBits = 8;
  500. videoModes->NumberBlueBits = 8;
  501. videoModes->RedMask = 0xff0000;
  502. videoModes->GreenMask = 0x00ff00;
  503. videoModes->BlueMask = 0x0000ff;
  504. }
  505. videoModes->AttributeFlags = VgaModeList[i].fbType |
  506. VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE;
  507. }
  508. return NO_ERROR;
  509. } // end VgaGetAvailableModes()
  510. VP_STATUS
  511. VgaQueryNumberOfAvailableModes(
  512. PHW_DEVICE_EXTENSION HwDeviceExtension,
  513. PVIDEO_NUM_MODES NumModes,
  514. ULONG NumModesSize,
  515. PULONG OutputSize
  516. )
  517. /*++
  518. Routine Description:
  519. This routine returns the number of available modes for this particular
  520. video card.
  521. Arguments:
  522. HwDeviceExtension - Pointer to the miniport driver's device extension.
  523. NumModes - Pointer to the output buffer supplied by the user. This is
  524. where the number of modes is stored.
  525. NumModesSize - Length of the output buffer supplied by the user.
  526. OutputSize - Pointer to a buffer in which to return the actual size of
  527. the data in the buffer.
  528. Return Value:
  529. ERROR_INSUFFICIENT_BUFFER if the output buffer was not large enough
  530. for the data being returned.
  531. NO_ERROR if the operation completed successfully.
  532. --*/
  533. {
  534. UNREFERENCED_PARAMETER(HwDeviceExtension);
  535. //
  536. // Find out the size of the data to be put in the the buffer and return
  537. // that in the status information (whether or not the information is
  538. // there). If the buffer passed in is not large enough return an
  539. // appropriate error code.
  540. //
  541. if (NumModesSize < (*OutputSize = sizeof(VIDEO_NUM_MODES)) ) {
  542. return ERROR_INSUFFICIENT_BUFFER;
  543. }
  544. //
  545. // Store the number of modes into the buffer.
  546. //
  547. NumModes->NumModes = NumVideoModes;
  548. NumModes->ModeInformationLength = sizeof(VIDEO_MODE_INFORMATION);
  549. return NO_ERROR;
  550. } // end VgaGetNumberOfAvailableModes()
  551. VP_STATUS
  552. VgaQueryCurrentMode(
  553. PHW_DEVICE_EXTENSION HwDeviceExtension,
  554. PVIDEO_MODE_INFORMATION ModeInformation,
  555. ULONG ModeInformationSize,
  556. PULONG OutputSize
  557. )
  558. /*++
  559. Routine Description:
  560. This routine returns a description of the current video mode.
  561. Arguments:
  562. HwDeviceExtension - Pointer to the miniport driver's device extension.
  563. ModeInformation - Pointer to the output buffer supplied by the user.
  564. This is where the current mode information is stored.
  565. ModeInformationSize - Length of the output buffer supplied by the user.
  566. OutputSize - Pointer to a buffer in which to return the actual size of
  567. the data in the buffer. If the buffer was not large enough, this
  568. contains the minimum required buffer size.
  569. Return Value:
  570. ERROR_INSUFFICIENT_BUFFER if the output buffer was not large enough
  571. for the data being returned.
  572. NO_ERROR if the operation completed successfully.
  573. --*/
  574. {
  575. //
  576. //
  577. // check if a mode has been set
  578. //
  579. if (HwDeviceExtension->CurrentMode == NULL) {
  580. return ERROR_INVALID_FUNCTION;
  581. }
  582. //
  583. // Find out the size of the data to be put in the the buffer and return
  584. // that in the status information (whether or not the information is
  585. // there). If the buffer passed in is not large enough return an
  586. // appropriate error code.
  587. //
  588. if (ModeInformationSize < (*OutputSize = sizeof(VIDEO_MODE_INFORMATION))) {
  589. return ERROR_INSUFFICIENT_BUFFER;
  590. }
  591. //
  592. // Store the characteristics of the current mode into the buffer.
  593. //
  594. ModeInformation->Length = sizeof(VIDEO_MODE_INFORMATION);
  595. ModeInformation->ModeIndex = HwDeviceExtension->ModeIndex;
  596. ModeInformation->VisScreenWidth = HwDeviceExtension->CurrentMode->hres;
  597. ModeInformation->ScreenStride = HwDeviceExtension->CurrentMode->wbytes;
  598. ModeInformation->VisScreenHeight = HwDeviceExtension->CurrentMode->vres;
  599. ModeInformation->NumberOfPlanes = HwDeviceExtension->CurrentMode->numPlanes;
  600. ModeInformation->BitsPerPlane = HwDeviceExtension->CurrentMode->bitsPerPlane;
  601. ModeInformation->Frequency = HwDeviceExtension->CurrentMode->frequency;
  602. ModeInformation->XMillimeter = 320; // temporary hardcoded constant
  603. ModeInformation->YMillimeter = 240; // temporary hardcoded constant
  604. if (HwDeviceExtension->CurrentMode->bitsPerPlane < 15) {
  605. ModeInformation->NumberRedBits = 6;
  606. ModeInformation->NumberGreenBits = 6;
  607. ModeInformation->NumberBlueBits = 6;
  608. ModeInformation->RedMask = 0;
  609. ModeInformation->GreenMask = 0;
  610. ModeInformation->BlueMask = 0;
  611. } else if (HwDeviceExtension->CurrentMode->bitsPerPlane == 15) {
  612. ModeInformation->NumberRedBits = 6;
  613. ModeInformation->NumberGreenBits = 6;
  614. ModeInformation->NumberBlueBits = 6;
  615. ModeInformation->RedMask = 0x1F << 10;
  616. ModeInformation->GreenMask = 0x1F << 5;
  617. ModeInformation->BlueMask = 0x1F;
  618. } else if (HwDeviceExtension->CurrentMode->bitsPerPlane == 16) {
  619. ModeInformation->NumberRedBits = 6;
  620. ModeInformation->NumberGreenBits = 6;
  621. ModeInformation->NumberBlueBits = 6;
  622. ModeInformation->RedMask = 0x1F << 11;
  623. ModeInformation->GreenMask = 0x3F << 5;
  624. ModeInformation->BlueMask = 0x1F;
  625. } else {
  626. ModeInformation->NumberRedBits = 8;
  627. ModeInformation->NumberGreenBits = 8;
  628. ModeInformation->NumberBlueBits = 8;
  629. ModeInformation->RedMask = 0xff0000;
  630. ModeInformation->GreenMask = 0x00ff00;
  631. ModeInformation->BlueMask = 0x0000ff;
  632. }
  633. ModeInformation->AttributeFlags = HwDeviceExtension->CurrentMode->fbType |
  634. VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE;
  635. return NO_ERROR;
  636. } // end VgaQueryCurrentMode()
  637. VOID
  638. VgaZeroVideoMemory(
  639. PHW_DEVICE_EXTENSION HwDeviceExtension
  640. )
  641. /*++
  642. Routine Description:
  643. This routine zeros the first 256K on the VGA.
  644. Arguments:
  645. HwDeviceExtension - Pointer to the miniport driver's device extension.
  646. Return Value:
  647. None.
  648. --*/
  649. {
  650. UCHAR temp;
  651. //
  652. // Map font buffer at A0000
  653. //
  654. // We need the 2 calls below to VideoPortStallExecution because on
  655. // some old cards the machine would hard hang without this delay.
  656. //
  657. VgaInterpretCmdStream(HwDeviceExtension, EnableA000Data);
  658. VideoPortStallExecution(25);
  659. //
  660. // Enable all planes.
  661. //
  662. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
  663. IND_MAP_MASK);
  664. temp = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
  665. SEQ_DATA_PORT) | (UCHAR)0x0F;
  666. VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_DATA_PORT,
  667. temp);
  668. //
  669. // Zero the memory.
  670. //
  671. VideoPortZeroDeviceMemory(HwDeviceExtension->VideoMemoryAddress, 0xFFFF);
  672. VideoPortStallExecution(25);
  673. VgaInterpretCmdStream(HwDeviceExtension, DisableA000Color);
  674. }