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.

1043 lines
28 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. spvideo.c
  5. Abstract:
  6. Text setup display support.
  7. Author:
  8. Ted Miller (tedm) 29-July-1993
  9. Revision History:
  10. --*/
  11. #include "spprecmp.h"
  12. #include <hdlsblk.h>
  13. #include <hdlsterm.h>
  14. #pragma hdrstop
  15. extern BOOLEAN ForceConsole;
  16. //
  17. // Video function vectors.
  18. //
  19. PVIDEO_FUNCTION_VECTOR VideoFunctionVector;
  20. //
  21. // Other display paramters
  22. //
  23. SP_VIDEO_VARS VideoVars;
  24. BOOLEAN VideoInitialized = FALSE;
  25. POEM_FONT_FILE_HEADER FontHeader;
  26. ULONG FontBytesPerRow;
  27. ULONG FontCharacterHeight;
  28. ULONG FontCharacterWidth;
  29. //
  30. // bootfont.bin file image
  31. //
  32. PVOID BootFontImage = NULL;
  33. ULONG BootFontImageLength = 0;
  34. //
  35. // The following structures and constants are used in font files.
  36. //
  37. //
  38. // Define OS/2 executable resource information structure.
  39. //
  40. #define FONT_DIRECTORY 0x8007
  41. #define FONT_RESOURCE 0x8008
  42. typedef struct _RESOURCE_TYPE_INFORMATION {
  43. USHORT Ident;
  44. USHORT Number;
  45. LONG Proc;
  46. } RESOURCE_TYPE_INFORMATION, *PRESOURCE_TYPE_INFORMATION;
  47. //
  48. // Define OS/2 executable resource name information structure.
  49. //
  50. typedef struct _RESOURCE_NAME_INFORMATION {
  51. USHORT Offset;
  52. USHORT Length;
  53. USHORT Flags;
  54. USHORT Ident;
  55. USHORT Handle;
  56. USHORT Usage;
  57. } RESOURCE_NAME_INFORMATION, *PRESOURCE_NAME_INFORMATION;
  58. //
  59. // These values are passed to us by setupldr and represent monitor config
  60. // data from the monitor peripheral for the display we are supposed to use
  61. // during setup. They are used only for non-vga displays.
  62. //
  63. PMONITOR_CONFIGURATION_DATA MonitorConfigData;
  64. PCHAR MonitorFirmwareIdString;
  65. //
  66. // Function prototypes.
  67. //
  68. BOOLEAN
  69. pSpvidInitPalette(
  70. VOID
  71. );
  72. VOID
  73. SpvidInitialize0(
  74. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  75. )
  76. /*++
  77. Routine Description:
  78. Perform phase-0 display initialization. This routine is used to
  79. perform initialization that can be performed only at driver load time.
  80. Actions:
  81. - initialize the font. We retreive the hal oem font image
  82. from the loader block and copy it into locally allocated memory.
  83. This must be done here because the loader block is gone
  84. when setup is actually started.
  85. Arguments:
  86. LoaderBlock - supplies pointer to loader parameter block.
  87. Return Value:
  88. None. Does not return if error.
  89. --*/
  90. {
  91. POEM_FONT_FILE_HEADER fontHeader;
  92. PSETUP_LOADER_BLOCK SetupBlock;
  93. BOOLEAN bValidOemFont;
  94. //
  95. // Check if the file has a font file header. Use SEH so that we don't bugcheck if
  96. // we got passed something screwy.
  97. //
  98. try {
  99. fontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
  100. if ((fontHeader->Version != OEM_FONT_VERSION) ||
  101. (fontHeader->Type != OEM_FONT_TYPE) ||
  102. (fontHeader->Italic != OEM_FONT_ITALIC) ||
  103. (fontHeader->Underline != OEM_FONT_UNDERLINE) ||
  104. (fontHeader->StrikeOut != OEM_FONT_STRIKEOUT) ||
  105. (fontHeader->CharacterSet != OEM_FONT_CHARACTER_SET) ||
  106. (fontHeader->Family != OEM_FONT_FAMILY) ||
  107. (fontHeader->PixelWidth > 32))
  108. {
  109. bValidOemFont = FALSE;
  110. } else {
  111. bValidOemFont = TRUE;
  112. }
  113. } except(EXCEPTION_EXECUTE_HANDLER) {
  114. bValidOemFont = FALSE;
  115. }
  116. if(!bValidOemFont) {
  117. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: oem hal font image is not a .fnt file.\n"));
  118. SpBugCheck(SETUP_BUGCHECK_BAD_OEM_FONT,0,0,0);
  119. }
  120. FontHeader = SpMemAlloc(fontHeader->FileSize);
  121. RtlMoveMemory(FontHeader,fontHeader,fontHeader->FileSize);
  122. FontBytesPerRow = (FontHeader->PixelWidth + 7) / 8;
  123. FontCharacterHeight = FontHeader->PixelHeight;
  124. FontCharacterWidth = FontHeader->PixelWidth;
  125. //
  126. // Get pointer to the setup loader block.
  127. //
  128. SetupBlock = LoaderBlock->SetupLoaderBlock;
  129. //
  130. // Save away monitor data.
  131. //
  132. if(SetupBlock->Monitor) {
  133. RtlMoveMemory(
  134. MonitorConfigData = SpMemAlloc(sizeof(MONITOR_CONFIGURATION_DATA)),
  135. SetupBlock->Monitor,
  136. sizeof(MONITOR_CONFIGURATION_DATA)
  137. );
  138. }
  139. if(SetupBlock->MonitorId) {
  140. MonitorFirmwareIdString = SpDupString(SetupBlock->MonitorId);
  141. }
  142. //
  143. // save off bootfont.bin file image, if any
  144. //
  145. if (SetupBlock->BootFontFile && SetupBlock->BootFontFileLength) {
  146. BootFontImage = SpMemAlloc(SetupBlock->BootFontFileLength);
  147. if (BootFontImage) {
  148. BootFontImageLength = SetupBlock->BootFontFileLength;
  149. RtlMoveMemory(BootFontImage,
  150. SetupBlock->BootFontFile,
  151. BootFontImageLength);
  152. }
  153. }
  154. //
  155. // Initialize the global video state
  156. //
  157. RtlZeroMemory(&VideoVars, sizeof(SP_VIDEO_VARS));
  158. }
  159. VOID
  160. SpvidInitialize(
  161. VOID
  162. )
  163. {
  164. NTSTATUS Status;
  165. OBJECT_ATTRIBUTES Attributes;
  166. IO_STATUS_BLOCK IoStatusBlock;
  167. UNICODE_STRING UnicodeString;
  168. VIDEO_NUM_MODES NumModes;
  169. PVIDEO_MODE_INFORMATION VideoModes;
  170. PVIDEO_MODE_INFORMATION pVideoMode;
  171. ULONG VideoModesSize;
  172. ULONG mode;
  173. BOOLEAN IsVga;
  174. PVIDEO_FUNCTION_VECTOR NewVector;
  175. PVIDEO_MODE_INFORMATION GraphicsVideoMode = NULL;
  176. //
  177. // If video is already initialized, we are performing a reinit.
  178. //
  179. if(VideoInitialized) {
  180. //
  181. // Request video function vector from the locale/lang-specific module.
  182. //
  183. NewVector = SplangGetVideoFunctionVector(
  184. (VideoFunctionVector == &VgaVideoVector) ? SpVideoVga : SpVideoFrameBuffer,
  185. &VideoVars
  186. );
  187. //
  188. // If there is no alternate video then we're done. Else go into action.
  189. //
  190. if(NewVector) {
  191. SpvidTerminate();
  192. } else {
  193. return;
  194. }
  195. } else {
  196. NewVector = NULL;
  197. }
  198. //
  199. // Initialize the headless terminal. Once we decide
  200. // to start UTF8 encoding (i.e. we're on a FE build),
  201. // then never stop.
  202. //
  203. SpTermDoUtf8 = (SpTermDoUtf8 || (NewVector != NULL));
  204. SpTermInitialize();
  205. //
  206. // Open \Device\Video0.
  207. //
  208. RtlInitUnicodeString(&UnicodeString,L"\\Device\\Video0");
  209. InitializeObjectAttributes(
  210. &Attributes,
  211. &UnicodeString,
  212. OBJ_CASE_INSENSITIVE,
  213. NULL,
  214. NULL
  215. );
  216. Status = ZwCreateFile(
  217. &VideoVars.hDisplay,
  218. GENERIC_READ | SYNCHRONIZE | FILE_READ_ATTRIBUTES,
  219. &Attributes,
  220. &IoStatusBlock,
  221. NULL, // allocation size
  222. FILE_ATTRIBUTE_NORMAL,
  223. 0, // no sharing
  224. FILE_OPEN,
  225. FILE_SYNCHRONOUS_IO_NONALERT,
  226. NULL, // no EAs
  227. 0
  228. );
  229. if(!NT_SUCCESS(Status)) {
  230. //
  231. // if we're in headless mode, try to operate without the video card
  232. // present...otherwise we're done
  233. //
  234. if (HeadlessTerminalConnected) {
  235. //
  236. // if there's no video card, then we default into VGA mode,
  237. // which will do nothing if there is no video card
  238. //
  239. VideoFunctionVector = &VgaVideoVector;
  240. VideoVars.ScreenWidth = 80;
  241. VideoVars.ScreenHeight = HEADLESS_SCREEN_HEIGHT;
  242. //
  243. // Allocate a buffer for use translating unicode to oem.
  244. // Assuming each unicode char translates to a dbcs char,
  245. // we need a buffer twice the width of the screen to hold
  246. // (the width of the screen being the longest string
  247. // we'll display in one shot).
  248. //
  249. VideoVars.SpvCharTranslationBufferSize = (VideoVars.ScreenWidth+1)*2;
  250. VideoVars.SpvCharTranslationBuffer = SpMemAlloc(VideoVars.SpvCharTranslationBufferSize);
  251. VideoInitialized = TRUE;
  252. return;
  253. } else {
  254. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: NtOpenFile of \\device\\video0 returns %lx\n",Status));
  255. SpDisplayRawMessage(SP_SCRN_VIDEO_ERROR_RAW, 2, VIDEOBUG_OPEN, Status);
  256. while(TRUE); // loop forever
  257. }
  258. }
  259. //
  260. // Request a list of video modes.
  261. //
  262. Status = ZwDeviceIoControlFile(
  263. VideoVars.hDisplay,
  264. NULL,
  265. NULL,
  266. NULL,
  267. &IoStatusBlock,
  268. IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES,
  269. NULL,
  270. 0,
  271. &NumModes,
  272. sizeof(NumModes)
  273. );
  274. if(!NT_SUCCESS(Status)) {
  275. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to query video mode count (status = %lx)\n",Status));
  276. ZwClose(VideoVars.hDisplay);
  277. SpDisplayRawMessage(SP_SCRN_VIDEO_ERROR_RAW, 2, VIDEOBUG_GETNUMMODES, Status);
  278. while(TRUE); // loop forever
  279. }
  280. VideoModesSize = NumModes.NumModes * NumModes.ModeInformationLength;
  281. VideoModes = SpMemAlloc(VideoModesSize);
  282. Status = ZwDeviceIoControlFile(
  283. VideoVars.hDisplay,
  284. NULL,
  285. NULL,
  286. NULL,
  287. &IoStatusBlock,
  288. IOCTL_VIDEO_QUERY_AVAIL_MODES,
  289. NULL,
  290. 0,
  291. VideoModes,
  292. VideoModesSize
  293. );
  294. if(!NT_SUCCESS(Status)) {
  295. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to get list of video modes (status = %lx)\n",Status));
  296. SpMemFree(VideoModes);
  297. ZwClose(VideoVars.hDisplay);
  298. SpDisplayRawMessage(SP_SCRN_VIDEO_ERROR_RAW, 2, VIDEOBUG_GETMODES, Status);
  299. while(TRUE); // loop forever
  300. }
  301. //
  302. // If we have a 720 x 400 text mode, it's vga.
  303. // Otherwise it's a frame buffer.
  304. //
  305. IsVga = FALSE;
  306. pVideoMode = &VideoModes[0];
  307. for(mode=0; mode<NumModes.NumModes; mode++) {
  308. if(!IsVga && !(pVideoMode->AttributeFlags & VIDEO_MODE_GRAPHICS)
  309. && (pVideoMode->VisScreenWidth == 720)
  310. && (pVideoMode->VisScreenHeight == 400))
  311. {
  312. IsVga = TRUE;
  313. }
  314. if ((pVideoMode->AttributeFlags & VIDEO_MODE_GRAPHICS) &&
  315. (pVideoMode->VisScreenWidth == 640) &&
  316. (pVideoMode->VisScreenHeight == 480) &&
  317. (pVideoMode->NumberOfPlanes == 4) &&
  318. (pVideoMode->BitsPerPlane == 1)) {
  319. GraphicsVideoMode = pVideoMode;
  320. }
  321. pVideoMode = (PVIDEO_MODE_INFORMATION) (((PUCHAR) pVideoMode) + NumModes.ModeInformationLength);
  322. }
  323. VideoFunctionVector = NewVector ? NewVector : (IsVga ? &VgaVideoVector : &FrameBufferVideoVector);
  324. if (GraphicsVideoMode) {
  325. VideoVars.GraphicsModeInfo = *GraphicsVideoMode;
  326. } else {
  327. //
  328. // disable graphics mode
  329. //
  330. SP_SET_UPGRADE_GRAPHICS_MODE(FALSE);
  331. }
  332. spvidSpecificInitialize(VideoModes,NumModes.NumModes,NumModes.ModeInformationLength);
  333. // Set the terminal Height to the correct value
  334. if (HeadlessTerminalConnected) {
  335. VideoVars.ScreenHeight = HEADLESS_SCREEN_HEIGHT;
  336. }
  337. //
  338. // Allocate a buffer for use translating unicode to oem.
  339. // Assuming each unicode char translates to a dbcs char,
  340. // we need a buffer twice the width of the screen to hold
  341. // (the width of the screen being the longest string
  342. // we'll display in one shot).
  343. //
  344. VideoVars.SpvCharTranslationBufferSize = (VideoVars.ScreenWidth+1)*2;
  345. VideoVars.SpvCharTranslationBuffer = SpMemAlloc(VideoVars.SpvCharTranslationBufferSize);
  346. pSpvidInitPalette();
  347. CLEAR_ENTIRE_SCREEN();
  348. VideoInitialized = TRUE;
  349. SpMemFree(VideoModes);
  350. }
  351. VOID
  352. SpvidTerminate(
  353. VOID
  354. )
  355. {
  356. NTSTATUS Status;
  357. if(VideoInitialized) {
  358. spvidSpecificTerminate();
  359. SpTermTerminate();
  360. if (VideoVars.hDisplay) {
  361. Status = ZwClose(VideoVars.hDisplay);
  362. if(!NT_SUCCESS(Status)) {
  363. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to close \\device\\video0 (status = %lx)\n",Status));
  364. }
  365. }
  366. SpMemFree(VideoVars.SpvCharTranslationBuffer);
  367. VideoVars.SpvCharTranslationBuffer = NULL;
  368. VideoInitialized = FALSE;
  369. }
  370. }
  371. UCHAR
  372. GetDefaultAttr(
  373. void
  374. )
  375. {
  376. return (UCHAR)(ForceConsole ? (ATT_FG_WHITE | ATT_BG_BLACK) : (ATT_FG_WHITE | ATT_BG_BLUE));
  377. }
  378. UCHAR
  379. GetDefaultBackground(
  380. void
  381. )
  382. {
  383. return (UCHAR)(ForceConsole ? ATT_BLACK : ATT_BLUE);
  384. }
  385. UCHAR
  386. GetDefaultStatusAttr(
  387. void
  388. )
  389. {
  390. return (UCHAR)(ForceConsole ? (ATT_FG_WHITE | ATT_BG_BLACK) : (ATT_FG_BLACK | ATT_BG_WHITE));
  391. }
  392. UCHAR
  393. GetDefaultStatusBackground(
  394. void
  395. )
  396. {
  397. return (UCHAR)(ForceConsole ? ATT_BLACK : ATT_WHITE);
  398. }
  399. BOOLEAN
  400. SpvidGetModeParams(
  401. OUT PULONG XResolution,
  402. OUT PULONG YResolution,
  403. OUT PULONG BitsPerPixel,
  404. OUT PULONG VerticalRefresh,
  405. OUT PULONG InterlacedFlag
  406. )
  407. {
  408. if(VideoVars.VideoModeInfo.AttributeFlags & VIDEO_MODE_GRAPHICS) {
  409. *XResolution = VideoVars.VideoModeInfo.VisScreenWidth;
  410. *YResolution = VideoVars.VideoModeInfo.VisScreenHeight;
  411. *BitsPerPixel = VideoVars.VideoModeInfo.BitsPerPlane;
  412. *VerticalRefresh = VideoVars.VideoModeInfo.Frequency;
  413. *InterlacedFlag = (VideoVars.VideoModeInfo.AttributeFlags & VIDEO_MODE_INTERLACED) ? 1 : 0;
  414. return(TRUE);
  415. } else {
  416. //
  417. // VGA/text mode. Params are not interesting.
  418. //
  419. return(FALSE);
  420. }
  421. }
  422. BOOLEAN
  423. pSpvidInitPalette(
  424. VOID
  425. )
  426. /*++
  427. Routine Description:
  428. Set the display up so we can use the standard 16 cga attributes.
  429. If the video mode is direct color, then we construct a table of
  430. attribute to color mappings based on the number of bits for
  431. red, green, and blue.
  432. If the video mode is palette driven, then we actually construct
  433. a 16-color palette and pass it to the driver.
  434. Arguments:
  435. VOID
  436. Return Value:
  437. TRUE if display set up successfully, false if not.
  438. --*/
  439. {
  440. ULONG i;
  441. ULONG MaxVal[3];
  442. ULONG MidVal[3];
  443. #define C_RED 0
  444. #define C_GRE 1
  445. #define C_BLU 2
  446. if(VideoVars.VideoModeInfo.AttributeFlags & VIDEO_MODE_PALETTE_DRIVEN) {
  447. UCHAR Buffer[sizeof(VIDEO_CLUT)+(sizeof(VIDEO_CLUTDATA)*15)]; // size is close enough
  448. PVIDEO_CLUT clut = (PVIDEO_CLUT)Buffer;
  449. NTSTATUS Status;
  450. IO_STATUS_BLOCK IoStatusBlock;
  451. //
  452. // Palette driven. Set up the attribute to color table
  453. // as a one-to-one mapping so we can use attribute values
  454. // directly in the frame buffer and get the expected result.
  455. //
  456. MaxVal[C_RED] = ((1 << VideoVars.VideoModeInfo.NumberRedBits ) - 1);
  457. MaxVal[C_GRE] = ((1 << VideoVars.VideoModeInfo.NumberGreenBits) - 1);
  458. MaxVal[C_BLU] = ((1 << VideoVars.VideoModeInfo.NumberBlueBits ) - 1);
  459. MidVal[C_RED] = 2 * MaxVal[C_RED] / 3;
  460. MidVal[C_GRE] = 2 * MaxVal[C_GRE] / 3;
  461. MidVal[C_BLU] = 2 * MaxVal[C_BLU] / 3;
  462. clut->NumEntries = 16;
  463. clut->FirstEntry = 0;
  464. for(i=0; i<16; i++) {
  465. VideoVars.AttributeToColorValue[i] = i;
  466. clut->LookupTable[i].RgbArray.Red = (UCHAR)((i & ATT_RED )
  467. ? ((i & ATT_INTENSE) ? MaxVal[C_RED] : MidVal[C_RED])
  468. : 0);
  469. clut->LookupTable[i].RgbArray.Green = (UCHAR)((i & ATT_GREEN)
  470. ? ((i & ATT_INTENSE) ? MaxVal[C_GRE] : MidVal[C_GRE])
  471. : 0);
  472. clut->LookupTable[i].RgbArray.Blue = (UCHAR)((i & ATT_BLUE )
  473. ? ((i & ATT_INTENSE) ? MaxVal[C_BLU] : MidVal[C_BLU])
  474. : 0);
  475. clut->LookupTable[i].RgbArray.Unused = 0;
  476. }
  477. Status = ZwDeviceIoControlFile(
  478. VideoVars.hDisplay,
  479. NULL,
  480. NULL,
  481. NULL,
  482. &IoStatusBlock,
  483. IOCTL_VIDEO_SET_COLOR_REGISTERS,
  484. clut,
  485. sizeof(Buffer),
  486. NULL,
  487. 0
  488. );
  489. if(!NT_SUCCESS(Status)) {
  490. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set palette (status = %lx)\n",Status));
  491. return(FALSE);
  492. }
  493. } else {
  494. //
  495. // Direct color. Construct an attribute to color value table.
  496. //
  497. ULONG mask[3];
  498. ULONG bitcnt[3];
  499. ULONG bits;
  500. ULONG shift[3];
  501. unsigned color;
  502. //
  503. // Determine the ranges for each of red, green, and blue.
  504. //
  505. mask[C_RED] = VideoVars.VideoModeInfo.RedMask;
  506. mask[C_GRE] = VideoVars.VideoModeInfo.GreenMask;
  507. mask[C_BLU] = VideoVars.VideoModeInfo.BlueMask;
  508. bitcnt[C_RED] = VideoVars.VideoModeInfo.NumberRedBits;
  509. bitcnt[C_GRE] = VideoVars.VideoModeInfo.NumberGreenBits;
  510. bitcnt[C_BLU] = VideoVars.VideoModeInfo.NumberBlueBits;
  511. shift[C_RED] = 32;
  512. shift[C_GRE] = 32;
  513. shift[C_BLU] = 32;
  514. for(color=0; color<3; color++) {
  515. bits = 0;
  516. //
  517. // Count the number of 1 bits and determine the shift value
  518. // to shift in that color component.
  519. //
  520. for(i=0; i<32; i++) {
  521. if(mask[color] & (1 << i)) {
  522. bits++;
  523. //
  524. // Remember the position of the least significant bit
  525. // in this mask.
  526. //
  527. if(shift[color] == 32) {
  528. shift[color] = i;
  529. }
  530. }
  531. }
  532. //
  533. // Calculate the maximum color value for this color component.
  534. //
  535. MaxVal[color] = (1 << bits) - 1;
  536. //
  537. // Make sure we haven't overflowed the actual number of bits
  538. // available for this color component.
  539. //
  540. if(bitcnt[color] && (MaxVal[color] > ((ULONG)(1 << bitcnt[color]) - 1))) {
  541. MaxVal[color] = (ULONG)(1 << bitcnt[color]) - 1;
  542. }
  543. }
  544. MidVal[C_RED] = 2 * MaxVal[C_RED] / 3;
  545. MidVal[C_GRE] = 2 * MaxVal[C_GRE] / 3;
  546. MidVal[C_BLU] = 2 * MaxVal[C_BLU] / 3;
  547. //
  548. // Now go through and construct the color table.
  549. //
  550. for(i=0; i<16; i++) {
  551. VideoVars.AttributeToColorValue[i] =
  552. (((i & ATT_RED)
  553. ? ((i & ATT_INTENSE) ? MaxVal[C_RED] : MidVal[C_RED])
  554. : 0)
  555. << shift[C_RED])
  556. | (((i & ATT_GREEN)
  557. ? ((i & ATT_INTENSE) ? MaxVal[C_GRE] : MidVal[C_GRE])
  558. : 0)
  559. << shift[C_GRE])
  560. | (((i & ATT_BLUE)
  561. ? ((i & ATT_INTENSE) ? MaxVal[C_BLU] : MidVal[C_BLU])
  562. : 0)
  563. << shift[C_BLU]);
  564. }
  565. }
  566. //
  567. // Perform any display-specific palette setup.
  568. //
  569. return(spvidSpecificInitPalette());
  570. }
  571. VOID
  572. pSpvidMapVideoMemory(
  573. IN BOOLEAN Map
  574. )
  575. /*++
  576. Routine Description:
  577. Map or unmap video memory. Fills in or uses the VideoMemoryInfo global.
  578. Arguments:
  579. Map - if TRUE, map video memory.
  580. if FALSE, unmap video memory.
  581. Return Value:
  582. --*/
  583. {
  584. NTSTATUS Status;
  585. IO_STATUS_BLOCK IoStatusBlock;
  586. VIDEO_MEMORY VideoMemory;
  587. VideoMemory.RequestedVirtualAddress = Map ? NULL : VideoVars.VideoMemoryInfo.VideoRamBase;
  588. Status = ZwDeviceIoControlFile(
  589. VideoVars.hDisplay,
  590. NULL,
  591. NULL,
  592. NULL,
  593. &IoStatusBlock,
  594. Map ? IOCTL_VIDEO_MAP_VIDEO_MEMORY : IOCTL_VIDEO_UNMAP_VIDEO_MEMORY,
  595. &VideoMemory,
  596. sizeof(VideoMemory),
  597. Map ? &VideoVars.VideoMemoryInfo : NULL,
  598. Map ? sizeof(VideoVars.VideoMemoryInfo) : 0
  599. );
  600. if(!NT_SUCCESS(Status)) {
  601. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to %smap video memory (status = %lx)\n",Map ? "" : "un",Status));
  602. if(Map) {
  603. SpDisplayRawMessage(SP_SCRN_VIDEO_ERROR_RAW, 2, VIDEOBUG_MAP, Status);
  604. while(TRUE); // loop forever
  605. }
  606. }
  607. }
  608. VOID
  609. SpvidDisplayString(
  610. IN PWSTR String,
  611. IN UCHAR Attribute,
  612. IN ULONG X,
  613. IN ULONG Y
  614. )
  615. {
  616. //
  617. // Convert unicode string to oem, guarding against overflow.
  618. //
  619. RtlUnicodeToOemN(
  620. VideoVars.SpvCharTranslationBuffer,
  621. VideoVars.SpvCharTranslationBufferSize-1, // guarantee room for nul
  622. NULL,
  623. String,
  624. (wcslen(String)+1)*sizeof(WCHAR)
  625. );
  626. VideoVars.SpvCharTranslationBuffer[VideoVars.SpvCharTranslationBufferSize-1] = 0;
  627. spvidSpecificDisplayString(VideoVars.SpvCharTranslationBuffer,Attribute,X,Y);
  628. SpTermDisplayStringOnTerminal( String, Attribute, X, Y);
  629. }
  630. VOID
  631. SpvidDisplayOemString(
  632. IN PSTR String,
  633. IN UCHAR Attribute,
  634. IN ULONG X,
  635. IN ULONG Y
  636. )
  637. {
  638. spvidSpecificDisplayString(String,Attribute,X,Y);
  639. RtlOemToUnicodeN(
  640. (PWSTR)VideoVars.SpvCharTranslationBuffer,
  641. VideoVars.SpvCharTranslationBufferSize-1, // guarantee room for nul
  642. NULL,
  643. String,
  644. (strlen(String)+1)*sizeof(CHAR));
  645. //
  646. // make it a unicode NULL at the end
  647. //
  648. VideoVars.SpvCharTranslationBuffer[VideoVars.SpvCharTranslationBufferSize-1] = '\0';
  649. VideoVars.SpvCharTranslationBuffer[VideoVars.SpvCharTranslationBufferSize-2] = '\0';
  650. SpTermDisplayStringOnTerminal((PWSTR)VideoVars.SpvCharTranslationBuffer, Attribute, X, Y);
  651. }
  652. VOID
  653. SpvidClearScreenRegion(
  654. IN ULONG X,
  655. IN ULONG Y,
  656. IN ULONG W,
  657. IN ULONG H,
  658. IN UCHAR Attribute
  659. )
  660. /*++
  661. Routine Description:
  662. Clear out a screen region to a specific attribute.
  663. Arguments:
  664. X,Y,W,H - specify rectangle in 0-based character coordinates.
  665. If W or H are 0, clear the entire screen.
  666. Attribute - Low nibble specifies attribute to be filled in the rectangle
  667. (ie, the background color to be cleared to).
  668. Return Value:
  669. None.
  670. --*/
  671. {
  672. ULONG i;
  673. UCHAR FillAttribute;
  674. WCHAR TerminalLine[80];
  675. BOOLEAN ToEOL;
  676. if(!W || !H) {
  677. X = Y = 0;
  678. W = VideoVars.ScreenWidth;
  679. H = VideoVars.ScreenHeight;
  680. } else {
  681. ASSERT(X+W <= VideoVars.ScreenWidth);
  682. ASSERT(X <= VideoVars.ScreenWidth);
  683. ASSERT(W <= VideoVars.ScreenWidth);
  684. ASSERT(Y+H <= VideoVars.ScreenHeight);
  685. ASSERT(Y <= VideoVars.ScreenHeight);
  686. ASSERT(H <= VideoVars.ScreenHeight);
  687. if (W > VideoVars.ScreenWidth)
  688. W = VideoVars.ScreenWidth;
  689. if (X > VideoVars.ScreenWidth)
  690. X = VideoVars.ScreenWidth;
  691. if(X+W > VideoVars.ScreenWidth) {
  692. W = VideoVars.ScreenWidth-X;
  693. }
  694. if(Y > VideoVars.ScreenHeight) {
  695. Y = VideoVars.ScreenHeight;
  696. }
  697. if(H > VideoVars.ScreenHeight) {
  698. H = VideoVars.ScreenHeight;
  699. }
  700. if(Y+H > VideoVars.ScreenHeight) {
  701. H = VideoVars.ScreenHeight-Y;
  702. }
  703. }
  704. spvidSpecificClearRegion(X,Y,W,H,Attribute);
  705. FillAttribute = (Attribute << 4) | Attribute;
  706. ToEOL = FALSE;
  707. if (X + W < 80) {
  708. for (i = 0; i<W;i++) {
  709. TerminalLine[i] = L' ';
  710. }
  711. TerminalLine[W] = L'\0';
  712. } else {
  713. for (i = 0; i<(79-X); i++) {
  714. TerminalLine[i] = L' ';
  715. }
  716. TerminalLine[79 - X] = L'\0';
  717. if ((X == 0) && (Attribute == DEFAULT_BACKGROUND)) {
  718. ToEOL = TRUE;
  719. }
  720. }
  721. for(i=0; i<H; i++) {
  722. if (ToEOL) {
  723. SpTermDisplayStringOnTerminal(HEADLESS_CLEAR_TO_EOL_STRING,
  724. FillAttribute,
  725. X,
  726. Y + i
  727. );
  728. } else {
  729. SpTermDisplayStringOnTerminal(TerminalLine, FillAttribute, X, Y + i);
  730. }
  731. }
  732. }
  733. BOOLEAN
  734. SpvidScrollUp(
  735. IN ULONG TopLine,
  736. IN ULONG BottomLine,
  737. IN ULONG LineCount,
  738. IN UCHAR FillAttribute
  739. )
  740. {
  741. BOOLEAN vidSpecificRet;
  742. ULONG i;
  743. ULONG line;
  744. WCHAR TerminalLine[80];
  745. vidSpecificRet = spvidSpecificScrollUp(TopLine,BottomLine,LineCount,FillAttribute);
  746. if (!HeadlessTerminalConnected) {
  747. return(vidSpecificRet);
  748. }
  749. if ((TopLine == 0) && (BottomLine==VideoVars.ScreenHeight-1)) {
  750. //
  751. // Efficient scrolling for *whole screen* by
  752. // issuing the <CSI>x;80H escape, which moves the cursor to
  753. // the bottom right corner of the VT100. Each time we
  754. // move the cursor to this position, it makes the VT100 scroll
  755. // one line.
  756. //
  757. swprintf(TerminalLine, L"\033[%d;80H\n", BottomLine+1);
  758. for (i=0;i<LineCount; i++){
  759. SpTermSendStringToTerminal(TerminalLine,
  760. TRUE
  761. );
  762. }
  763. return vidSpecificRet;
  764. }
  765. //
  766. // We have to scroll it the hard way because we're not doing the
  767. // entire screen
  768. //
  769. //
  770. // Select the top and bottom line numbers via <CSI>x;yr escape
  771. // this will be some portion of the active display
  772. //
  773. swprintf(TerminalLine,L"\033[%d;%dr", TopLine+1, BottomLine+1);
  774. SpTermSendStringToTerminal(TerminalLine,
  775. TRUE
  776. );
  777. //
  778. // move the cursor to the bottom right corner of the selected area
  779. // via <CSI>x;80H escape. Each time we write to this area, it makes
  780. // the selected area scroll one line
  781. //
  782. swprintf(TerminalLine, L"\033[%d;80H\n", BottomLine+1);
  783. for(i = 0; i< LineCount; i++){
  784. SpTermSendStringToTerminal(TerminalLine,
  785. TRUE
  786. );
  787. }
  788. //
  789. // get a line of whitespace to clear out the bottom lines that may
  790. // have garbage in them now.
  791. //
  792. for (i=0;i<79;i++) {
  793. TerminalLine[i] = L' ';
  794. }
  795. TerminalLine[79] = '\0';
  796. line = BottomLine - LineCount + 1;
  797. for(i=0;i<LineCount;i++){
  798. SpTermDisplayStringOnTerminal(TerminalLine,
  799. FillAttribute,
  800. 0,
  801. line + i
  802. );
  803. }
  804. //
  805. // send <CSI>r escape, which resets the selected line numbers
  806. // so that the entire display is active again.
  807. //
  808. swprintf(TerminalLine, L"\033[r");
  809. SpTermSendStringToTerminal(TerminalLine,
  810. TRUE
  811. );
  812. return vidSpecificRet;
  813. }