Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

899 lines
21 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. fevga.c (was textmode\kernel\spvidgvg.c)
  5. Abstract:
  6. Text setup display support for Vga (Graphics mode) displays.
  7. Author:
  8. Hideyuki Nagase (hideyukn) 01-July-1994
  9. Revision History:
  10. --*/
  11. #include <precomp.h>
  12. #pragma hdrstop
  13. #if defined(_X86_)
  14. #undef READ_PORT_UCHAR
  15. #undef READ_PORT_USHORT
  16. #undef READ_PORT_ULONG
  17. #undef WRITE_PORT_UCHAR
  18. #undef WRITE_PORT_USHORT
  19. #undef WRITE_PORT_ULONG
  20. #undef READ_REGISTER_UCHAR
  21. #undef READ_REGISTER_USHORT
  22. #undef READ_REGISTER_ULONG
  23. #undef WRITE_REGISTER_UCHAR
  24. #undef WRITE_REGISTER_USHORT
  25. #undef WRITE_REGISTER_ULONG
  26. #endif
  27. #include "ioaccess.h"
  28. //
  29. // Include VGA hardware header
  30. //
  31. #include "hw.h"
  32. //
  33. // Vector for vga graphics mode functions.
  34. //
  35. #define GET_IMAGE(p) (*p)
  36. #define GET_IMAGE_POST_INC(p) (*p); p++;
  37. #define GET_IMAGE_REVERSE(p) ((*p) ^ 0xFF)
  38. #define GET_IMAGE_POST_INC_REVERSE(p) ((*p) ^ 0xFF); p++;
  39. #define BIT_OFF_IMAGE 0x00
  40. #define BIT_ON_IMAGE 0xFF
  41. #define WRITE_GRAPHICS_CONTROLLER(x) VgaGraphicsModeWriteController((x))
  42. VIDEO_FUNCTION_VECTOR VgaGraphicsModeVideoVector =
  43. {
  44. VgaGraphicsModeDisplayString,
  45. VgaGraphicsModeClearRegion,
  46. VgaGraphicsModeSpecificInit,
  47. VgaGraphicsModeSpecificReInit,
  48. VgaGraphicsModeSpecificTerminate,
  49. VgaGraphicsModeSpecificInitPalette,
  50. VgaGraphicsModeSpecificScrollUp
  51. };
  52. //
  53. // Number of bytes that make up a row of characters.
  54. // Equal to the screen stride (number of bytes on a scan line)
  55. // multiplies by the height of a char in bytes.
  56. //
  57. ULONG CharRowDelta;
  58. ULONG CharLineFeed;
  59. extern BOOTFONTBIN_HEADER BootFontHeader;
  60. BOOLEAN VgaGraphicsModeInitialized = FALSE;
  61. BOOLEAN VgaGraphicsModeFontInit = FALSE;
  62. PVOID VgaGraphicsControllerPort = NULL;
  63. VOID
  64. VgaGraphicsModeInitRegs(
  65. VOID
  66. );
  67. VOID
  68. VgaGraphicsModeSetAttribute(
  69. UCHAR Attribute
  70. );
  71. ULONG
  72. pVgaGraphicsModeDetermineModeToUse(
  73. IN PVIDEO_MODE_INFORMATION VideoModes,
  74. IN ULONG NumberOfModes
  75. );
  76. VOID
  77. VgaGraphicsModeWriteController(
  78. WORD Data
  79. );
  80. VOID
  81. VgaGraphicsModeSpecificInit(
  82. IN PVIDEO_MODE_INFORMATION VideoModes,
  83. IN ULONG NumberOfModes,
  84. IN ULONG ModeSize
  85. )
  86. /*++
  87. Routine Description:
  88. Perform frame buffer specific initialization. This includes
  89. - setting the desired video mode.
  90. Arguments:
  91. None.
  92. Return Value:
  93. --*/
  94. {
  95. NTSTATUS Status;
  96. IO_STATUS_BLOCK IoStatusBlock;
  97. VIDEO_MODE VideoMode;
  98. ULONG mode;
  99. VIDEO_CURSOR_ATTRIBUTES VideoCursorAttributes;
  100. PVIDEO_MODE_INFORMATION pVideoMode = &VideoModes[0];
  101. if(VgaGraphicsModeInitialized) {
  102. return;
  103. }
  104. //
  105. // Find out our 640*480 graphics mode
  106. //
  107. //
  108. // Try to find VGA standard mode.
  109. //
  110. for(mode=0; mode<NumberOfModes; mode++) {
  111. if( (pVideoMode->AttributeFlags & VIDEO_MODE_GRAPHICS)
  112. && !(pVideoMode->AttributeFlags & VIDEO_MODE_NO_OFF_SCREEN)
  113. && (pVideoMode->VisScreenWidth == 640)
  114. && (pVideoMode->VisScreenHeight == 480)
  115. && (pVideoMode->BitsPerPlane == 1 )
  116. && (pVideoMode->NumberOfPlanes == 4 ) )
  117. {
  118. break;
  119. }
  120. pVideoMode = (PVIDEO_MODE_INFORMATION) (((PUCHAR) pVideoMode) + ModeSize);
  121. }
  122. if(mode == (ULONG)(-1)) {
  123. KdPrint(("SETUP: Desired video mode not supported!\n"));
  124. SpDisplayRawMessage(SP_SCRN_VIDEO_ERROR_RAW, 2, VIDEOBUG_BADMODE, 0);
  125. while(TRUE); // loop forever
  126. }
  127. //
  128. // Save away the mode info in a global.
  129. //
  130. VideoVariables->VideoModeInfo = VideoModes[mode];
  131. //
  132. // Set the desired mode.
  133. //
  134. VideoMode.RequestedMode = VideoVariables->VideoModeInfo.ModeIndex;
  135. //
  136. // Change the video mode
  137. //
  138. Status = ZwDeviceIoControlFile(
  139. VideoVariables->hDisplay,
  140. NULL,
  141. NULL,
  142. NULL,
  143. &IoStatusBlock,
  144. IOCTL_VIDEO_SET_CURRENT_MODE,
  145. &VideoMode,
  146. sizeof(VideoMode),
  147. NULL,
  148. 0
  149. );
  150. if(!NT_SUCCESS(Status)) {
  151. KdPrint(("SETUP: Unable to set mode %u (status = %lx)\n",VideoMode.RequestedMode,Status));
  152. SpDisplayRawMessage(SP_SCRN_VIDEO_ERROR_RAW, 2, VIDEOBUG_SETMODE, Status);
  153. while(TRUE); // loop forever
  154. }
  155. //
  156. // Set up some global data.
  157. //
  158. // 80 * 25 Text screen.
  159. //
  160. // ( 8 * 80 = 640 ) , ( 19 * 25 = 475 )
  161. //
  162. VideoVariables->ScreenWidth = 80; // VideoModeInfo.ScreenStride / usSBCSCharWidth;
  163. VideoVariables->ScreenHeight = 25;
  164. //
  165. // Logical FontGlyph information
  166. //
  167. FEFontCharacterHeight = BootFontHeader.CharacterImageHeight +
  168. BootFontHeader.CharacterTopPad +
  169. BootFontHeader.CharacterBottomPad;
  170. FEFontCharacterWidth = BootFontHeader.CharacterImageSbcsWidth;
  171. CharLineFeed = FEFontCharacterHeight;
  172. CharRowDelta = VideoVariables->VideoModeInfo.ScreenStride * CharLineFeed;
  173. //
  174. // Map the video memory.
  175. //
  176. pSpvidMapVideoMemory(TRUE);
  177. //
  178. // Set initialized flag
  179. //
  180. VgaGraphicsModeInitialized = TRUE;
  181. //
  182. // Initialize vga registers
  183. //
  184. VgaGraphicsModeInitRegs();
  185. VideoVariables->ActiveVideoBuffer = VideoVariables->VideoMemoryInfo.FrameBufferBase;
  186. //
  187. // Allocate background VGA buffer, if needed
  188. //
  189. if (SP_IS_UPGRADE_GRAPHICS_MODE()) {
  190. VideoVariables->VideoBufferSize = VideoVariables->VideoMemoryInfo.FrameBufferLength;
  191. VideoVariables->VideoBuffer = SpMemAlloc(VideoVariables->VideoBufferSize);
  192. if (VideoVariables->VideoBuffer) {
  193. VideoVariables->ActiveVideoBuffer = VideoVariables->VideoBuffer;
  194. } else {
  195. //
  196. // ran out of memory
  197. //
  198. VideoVariables->VideoBufferSize = 0;
  199. SP_SET_UPGRADE_GRAPHICS_MODE(FALSE);
  200. }
  201. }
  202. KdPrint(("NOW - WE ARE WORKING ON VGA GRAPHICS MODE\n"));
  203. KdPrint((" Vram Base - %x\n",VideoVariables->VideoMemoryInfo.FrameBufferBase));
  204. KdPrint((" Vram Length - %x\n",VideoVariables->VideoMemoryInfo.FrameBufferLength));
  205. KdPrint((" I/O Port - %x\n",VgaGraphicsControllerPort));
  206. }
  207. VOID
  208. VgaGraphicsModeSpecificReInit(
  209. VOID
  210. )
  211. {
  212. NTSTATUS Status;
  213. IO_STATUS_BLOCK IoStatusBlock;
  214. VIDEO_MODE VideoMode;
  215. ULONG mode;
  216. VIDEO_CURSOR_ATTRIBUTES VideoCursorAttributes;
  217. if (!VgaGraphicsModeInitialized) {
  218. return;
  219. }
  220. //
  221. // Set the desired mode.
  222. //
  223. VideoMode.RequestedMode = VideoVariables->VideoModeInfo.ModeIndex;
  224. //
  225. // Change the video mode
  226. //
  227. Status = ZwDeviceIoControlFile(
  228. VideoVariables->hDisplay,
  229. NULL,
  230. NULL,
  231. NULL,
  232. &IoStatusBlock,
  233. IOCTL_VIDEO_SET_CURRENT_MODE,
  234. &VideoMode,
  235. sizeof(VideoMode),
  236. NULL,
  237. 0
  238. );
  239. if(!NT_SUCCESS(Status)) {
  240. KdPrint(("SETUP: Unable to set mode %u (status = %lx)\n",VideoMode.RequestedMode,Status));
  241. SpDisplayRawMessage(SP_SCRN_VIDEO_ERROR_RAW, 2, VIDEOBUG_SETMODE, Status);
  242. while(TRUE); // loop forever
  243. }
  244. //
  245. // Initialize vga registers
  246. //
  247. VgaGraphicsModeInitRegs();
  248. VgaGraphicsModeSpecificInitPalette();
  249. //
  250. // Blast the cached data in video buffer to the actual
  251. // video memory now
  252. //
  253. if (SP_IS_UPGRADE_GRAPHICS_MODE() && VideoVariables->VideoBuffer &&
  254. VideoVariables->VideoBufferSize) {
  255. PUCHAR Source = VideoVariables->VideoBuffer;
  256. PUCHAR Destination = VideoVariables->VideoMemoryInfo.FrameBufferBase;
  257. ULONG Index;
  258. for (Index=0; Index < VideoVariables->VideoBufferSize; Index++) {
  259. WRITE_REGISTER_UCHAR(Destination + Index, *(Source + Index));
  260. }
  261. SP_SET_UPGRADE_GRAPHICS_MODE(FALSE);
  262. }
  263. VideoVariables->ActiveVideoBuffer = VideoVariables->VideoMemoryInfo.FrameBufferBase;
  264. KdPrint(("NOW - WE ARE WORKING ON VGA GRAPHICS MODE (ReInit)\n"));
  265. KdPrint((" Vram Base - %x\n",VideoVariables->VideoMemoryInfo.FrameBufferBase));
  266. KdPrint((" Vram Length - %x\n",VideoVariables->VideoMemoryInfo.FrameBufferLength));
  267. KdPrint((" I/O Port - %x\n",VgaGraphicsControllerPort));
  268. }
  269. BOOLEAN
  270. VgaGraphicsModeSpecificInitPalette(
  271. VOID
  272. )
  273. {
  274. //
  275. // There is no vga-specific palette initialization.
  276. //
  277. return(TRUE);
  278. }
  279. VOID
  280. VgaGraphicsModeSpecificTerminate(
  281. VOID
  282. )
  283. /*++
  284. Routine Description:
  285. Perform frame buffer specific termination. This includes
  286. - unmapping the frame buffer from memory
  287. Arguments:
  288. None.
  289. Return Value:
  290. --*/
  291. {
  292. if(VgaGraphicsModeInitialized) {
  293. pSpvidMapVideoMemory(FALSE);
  294. // !!! LATER !!!
  295. //
  296. // We should call ...
  297. //
  298. // IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES
  299. //
  300. if (VideoVariables->VideoBuffer && VideoVariables->VideoBufferSize) {
  301. SpMemFree(VideoVariables->VideoBuffer);
  302. VideoVariables->VideoBuffer = 0;
  303. VideoVariables->VideoBufferSize = 0;
  304. }
  305. VgaGraphicsModeInitialized = FALSE;
  306. }
  307. }
  308. VOID
  309. VgaGraphicsModeDisplayString(
  310. IN PSTR String,
  311. IN UCHAR Attribute,
  312. IN ULONG X, // 0-based coordinates (character units)
  313. IN ULONG Y
  314. )
  315. /*++
  316. Routine Description:
  317. Write a string of characters to the display.
  318. Arguments:
  319. String - supplies a string of character in the OEM charset to be displayed
  320. at the given position.
  321. Attribute - supplies the attributes for characters in the string.
  322. X,Y - specify the character-based (0-based) position of the output.
  323. Return Value:
  324. None.
  325. --*/
  326. {
  327. PBYTE Origin,dest,pGlyphRow;
  328. BYTE Image;
  329. USHORT I;
  330. USHORT J;
  331. PUCHAR pch;
  332. ULONG CurrentColumn;
  333. //
  334. // Eliminate invalid coord.
  335. //
  336. if( X >= VideoVariables->ScreenWidth ) X = 0;
  337. if( Y >= VideoVariables->ScreenHeight ) Y = 3;
  338. //
  339. // Set current color/attribute.
  340. //
  341. VgaGraphicsModeSetAttribute(Attribute);
  342. //
  343. // Calculate the address of the upper left pixel of the first character
  344. // to be displayed.
  345. //
  346. Origin = (PUCHAR)VideoVariables->ActiveVideoBuffer
  347. + (Y * CharRowDelta)
  348. + ((X * FEFontCharacterWidth) / 8);
  349. //
  350. // Set current column.
  351. //
  352. CurrentColumn = X;
  353. //
  354. // Output each character in the string.
  355. //
  356. for(pch=String; *pch; pch++) {
  357. dest = Origin;
  358. if(DbcsFontIsDBCSLeadByte(*pch)) {
  359. USHORT Word;
  360. if((CurrentColumn+1) >= VideoVariables->ScreenWidth) {
  361. break;
  362. }
  363. Word = ((*pch) << 8) | (*(pch+1));
  364. pGlyphRow = DbcsFontGetDbcsFontChar(Word);
  365. if(pGlyphRow == NULL) {
  366. pGlyphRow = DbcsFontGetDbcsFontChar(FEFontDefaultChar);
  367. }
  368. for (I = 0; I < BootFontHeader.CharacterTopPad; I += 1) {
  369. WRITE_REGISTER_UCHAR(dest , BIT_OFF_IMAGE);
  370. WRITE_REGISTER_UCHAR(dest+1, BIT_OFF_IMAGE);
  371. dest += VideoVariables->VideoModeInfo.ScreenStride;
  372. }
  373. for (I = 0; I < BootFontHeader.CharacterImageHeight; I += 1) {
  374. Image = GET_IMAGE_POST_INC(pGlyphRow);
  375. WRITE_REGISTER_UCHAR(dest ,Image);
  376. Image = GET_IMAGE_POST_INC(pGlyphRow);
  377. WRITE_REGISTER_UCHAR(dest+1,Image);
  378. dest += VideoVariables->VideoModeInfo.ScreenStride;
  379. }
  380. for (I = 0; I < BootFontHeader.CharacterBottomPad; I += 1) {
  381. WRITE_REGISTER_UCHAR(dest , BIT_OFF_IMAGE);
  382. WRITE_REGISTER_UCHAR(dest+1, BIT_OFF_IMAGE);
  383. dest += VideoVariables->VideoModeInfo.ScreenStride;
  384. }
  385. //
  386. // Skip Dbcs trailing byte
  387. //
  388. pch++;
  389. Origin += (BootFontHeader.CharacterImageDbcsWidth / 8);
  390. CurrentColumn += 2;
  391. } else if(DbcsFontIsGraphicsChar(*pch)) {
  392. if(CurrentColumn >= VideoVariables->ScreenWidth) {
  393. break;
  394. }
  395. //
  396. // Graphics Character special
  397. //
  398. pGlyphRow = DbcsFontGetGraphicsChar(*pch);
  399. if(pGlyphRow == NULL) {
  400. pGlyphRow = DbcsFontGetGraphicsChar(0x0);
  401. }
  402. for (I = 0; I < FEFontCharacterHeight; I += 1) {
  403. Image = GET_IMAGE_POST_INC_REVERSE(pGlyphRow);
  404. WRITE_REGISTER_UCHAR(dest,Image);
  405. dest += VideoVariables->VideoModeInfo.ScreenStride;
  406. }
  407. Origin += (BootFontHeader.CharacterImageSbcsWidth / 8);
  408. CurrentColumn += 1;
  409. } else {
  410. if(CurrentColumn >= VideoVariables->ScreenWidth) {
  411. break;
  412. }
  413. pGlyphRow = DbcsFontGetSbcsFontChar(*pch);
  414. if(pGlyphRow == NULL) {
  415. pGlyphRow = DbcsFontGetSbcsFontChar(0x20);
  416. }
  417. for (I = 0; I < BootFontHeader.CharacterTopPad; I += 1) {
  418. WRITE_REGISTER_UCHAR(dest,BIT_OFF_IMAGE);
  419. dest += VideoVariables->VideoModeInfo.ScreenStride;
  420. }
  421. for (I = 0; I < BootFontHeader.CharacterImageHeight; I += 1) {
  422. Image = GET_IMAGE_POST_INC(pGlyphRow);
  423. WRITE_REGISTER_UCHAR(dest,Image);
  424. dest += VideoVariables->VideoModeInfo.ScreenStride;
  425. }
  426. for (I = 0; I < BootFontHeader.CharacterBottomPad; I += 1) {
  427. WRITE_REGISTER_UCHAR(dest,BIT_OFF_IMAGE);
  428. dest += VideoVariables->VideoModeInfo.ScreenStride;
  429. }
  430. Origin += (BootFontHeader.CharacterImageSbcsWidth / 8);
  431. CurrentColumn += 1;
  432. }
  433. }
  434. }
  435. VOID
  436. VgaGraphicsModeClearRegion(
  437. IN ULONG X,
  438. IN ULONG Y,
  439. IN ULONG W,
  440. IN ULONG H,
  441. IN UCHAR Attribute
  442. )
  443. /*++
  444. Routine Description:
  445. Clear out a screen region to a specific attribute.
  446. Arguments:
  447. X,Y,W,H - specify rectangle in 0-based character coordinates.
  448. Attribute - Low nibble specifies attribute to be filled in the rectangle
  449. (ie, the background color to be cleared to).
  450. Return Value:
  451. None.
  452. --*/
  453. {
  454. PUCHAR Destination,Temp;
  455. UCHAR FillOddStart,FillOddEnd;
  456. ULONG i,j;
  457. ULONG XStartInBits, XEndInBits;
  458. ULONG FillLength;
  459. ASSERT(X+W <= VideoVariables->ScreenWidth);
  460. ASSERT(Y+H <= VideoVariables->ScreenHeight);
  461. if(X+W > VideoVariables->ScreenWidth) {
  462. W = VideoVariables->ScreenWidth-X;
  463. }
  464. if(Y+H > VideoVariables->ScreenHeight) {
  465. H = VideoVariables->ScreenHeight-Y;
  466. }
  467. //
  468. // Set color/attribute
  469. //
  470. VgaGraphicsModeSetAttribute(Attribute);
  471. //
  472. // Compute destination start address
  473. //
  474. Destination = (PUCHAR)VideoVariables->ActiveVideoBuffer
  475. + (Y * CharRowDelta)
  476. + ((X * FEFontCharacterWidth) / 8);
  477. //
  478. // Compute amounts in Byte (including overhang).
  479. //
  480. FillLength = (W * FEFontCharacterWidth) / 8;
  481. //
  482. // Fill the region.
  483. //
  484. for( i = 0 ; i < (H * CharLineFeed) ; i++ ) {
  485. Temp = Destination;
  486. //
  487. // Write bytes in this row
  488. //
  489. for( j = 0 ; j < FillLength ; j++ ) {
  490. WRITE_REGISTER_UCHAR( Temp, BIT_ON_IMAGE );
  491. Temp ++;
  492. }
  493. //
  494. // Move to next row.
  495. //
  496. Destination += VideoVariables->VideoModeInfo.ScreenStride;
  497. }
  498. }
  499. #pragma optimize("",off)
  500. BOOLEAN
  501. VgaGraphicsModeSpecificScrollUp(
  502. IN ULONG TopLine,
  503. IN ULONG BottomLine,
  504. IN ULONG LineCount,
  505. IN UCHAR FillAttribute
  506. )
  507. {
  508. PUCHAR Source,Target;
  509. ULONG Count,u;
  510. //
  511. // Make sure we're in read mode 0 and write mode 1.
  512. //
  513. VgaGraphicsModeWriteController(0x0105);
  514. Target = (PUCHAR)VideoVariables->ActiveVideoBuffer
  515. + (TopLine * CharRowDelta);
  516. Source = Target + (LineCount * CharRowDelta);
  517. Count = (((BottomLine - TopLine) + 1) - LineCount) * CharRowDelta;
  518. //
  519. // The transfer *MUST* be done byte-by-byte because of the way
  520. // VGA latches work.
  521. //
  522. for(u=0; u<Count; u++) {
  523. *Target++ = *Source++;
  524. }
  525. //
  526. // Reset read and write mode to default value.
  527. //
  528. VgaGraphicsModeWriteController(0x0005);
  529. VgaGraphicsModeClearRegion(
  530. 0,
  531. (BottomLine - LineCount) + 1,
  532. VideoVariables->ScreenWidth,
  533. LineCount,
  534. FillAttribute
  535. );
  536. return(TRUE);
  537. }
  538. #pragma optimize("", on)
  539. VOID
  540. VgaGraphicsModeInitRegs(
  541. VOID
  542. )
  543. {
  544. NTSTATUS Status;
  545. IO_STATUS_BLOCK IoStatusBlock;
  546. VIDEO_PUBLIC_ACCESS_RANGES VideoAccessRange;
  547. Status = ZwDeviceIoControlFile(
  548. VideoVariables->hDisplay,
  549. NULL,
  550. NULL,
  551. NULL,
  552. &IoStatusBlock,
  553. IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES,
  554. NULL,
  555. 0,
  556. &VideoAccessRange, // output buffer
  557. sizeof (VideoAccessRange)
  558. );
  559. if(!NT_SUCCESS(Status)) {
  560. KdPrint(("SETUP: Unable to get VGA public access ranges (%x)\n",Status));
  561. SpDisplayRawMessage(SP_SCRN_VIDEO_ERROR_RAW, 2, VIDEOBUG_SETMODE, Status);
  562. while(TRUE); // loop forever
  563. }
  564. VgaGraphicsControllerPort =
  565. (PVOID)(((BYTE *)VideoAccessRange.VirtualAddress) + (VGA_BASE + GRAF_ADDR));
  566. }
  567. //
  568. // Need to turn off optimization for this
  569. // routine. Since the write and read to
  570. // GVRAM seem useless to the compiler.
  571. //
  572. #pragma optimize( "", off )
  573. VOID
  574. VgaGraphicsModeSetAttribute(
  575. UCHAR Attribute
  576. )
  577. /*++
  578. Routine Description:
  579. Sets the attribute by setting up various VGA registers.
  580. The comments only say what registers are set to what, so
  581. to understand the logic, follow the code while looking at
  582. Figure 5-5 of PC&PS/2 Video Systems by Richard Wilton.
  583. The book is published by Microsoft Press.
  584. Arguments:
  585. Attribute - New attribute to set to.
  586. Attribute:
  587. High nibble - background attribute.
  588. Low nibble - foreground attribute.
  589. Return Value:
  590. Nothing.
  591. --*/
  592. {
  593. UCHAR temp = 0;
  594. union WordOrByte {
  595. struct Word { USHORT ax; } x;
  596. struct Byte { UCHAR al, ah; } h;
  597. } regs;
  598. //
  599. // Address of GVRAM off the screen.
  600. // Physical memory = (0xa9600);
  601. //
  602. PUCHAR OffTheScreen = ((PUCHAR)VideoVariables->VideoMemoryInfo.FrameBufferBase + 0x9600);
  603. //
  604. // TDB : How to handle this with background buffering ?
  605. //
  606. if (SP_IS_UPGRADE_GRAPHICS_MODE())
  607. return; // nop
  608. //
  609. // Reset Data Rotate/Function Select
  610. // regisger (register 3 with 00 indicating replace bits)
  611. //
  612. WRITE_GRAPHICS_CONTROLLER( 0x0003 ); // Need to reset Data Rotate/Function Select.
  613. //
  614. // Set Enable Set/Reset toall (0f)
  615. // (regsiter 1 with F indicating each pixel is updated
  616. // with the value in set register (register 0) using the logical
  617. // operation in Data Rotate/Function selection register).
  618. //
  619. WRITE_GRAPHICS_CONTROLLER( 0x0f01 );
  620. //
  621. // Put background color into Set/Reset register.
  622. // This is done to put the background color into
  623. // the latches later.
  624. //
  625. regs.x.ax = (USHORT)(Attribute & 0x00f0) << 4;
  626. WRITE_GRAPHICS_CONTROLLER( regs.x.ax );
  627. //
  628. // Put the background attribute in temp variable
  629. //
  630. temp = regs.h.ah;
  631. //
  632. // Put Set/Reset register value into GVRAM
  633. // off the screen.
  634. //
  635. WRITE_REGISTER_UCHAR( OffTheScreen , temp );
  636. //
  637. // Read from screen, so the latches will be
  638. // updated with the background color.
  639. //
  640. temp = READ_REGISTER_UCHAR( OffTheScreen );
  641. //
  642. // Set Data Rotate/Function Select register
  643. // to be XOR.
  644. //
  645. WRITE_GRAPHICS_CONTROLLER( 0x1803 );
  646. //
  647. // XOR the foreground and background color and
  648. // put it in Set/Reset register.
  649. //
  650. regs.h.ah = (Attribute >> 4) ^ (Attribute & 0x0f);
  651. regs.h.al = 0;
  652. WRITE_GRAPHICS_CONTROLLER( regs.x.ax );
  653. //
  654. // Put Inverse(~) of the XOR of foreground and
  655. // ground attribute into Enable Set/Reset register.
  656. //
  657. regs.x.ax = ~regs.x.ax & 0x0f01;
  658. WRITE_GRAPHICS_CONTROLLER( regs.x.ax );
  659. }
  660. //
  661. // Turn optimization on again.
  662. //
  663. #pragma optimize( "", on )
  664. VOID
  665. VgaGraphicsModeWriteController(
  666. USHORT Data
  667. )
  668. {
  669. MEMORY_BARRIER();
  670. WRITE_PORT_USHORT(VgaGraphicsControllerPort,Data);
  671. }