/*++ Copyright (c) 1991 Microsoft Corporation Module Name: xxdisp.c Abstract: This module implements the HAL display initialization and output routines for a x86 system. Author: David N. Cutler (davec) 27-Apr-1991 Environment: Kernel mode Revision History: --*/ #include "halp.h" // // Private function prototypes // VOID HalpClearDisplay( VOID ); VOID HalpNextLine( VOID ); VOID HalpScrollDisplay( VOID ); VOID HalpPutCharacter( IN UCHAR Character ); #define REVERSE_ATTRIBUTE 0x17 #define ROWS 50 #define COLS 80 ULONG HalpCursorX=0; ULONG HalpCursorY=0; KSPIN_LOCK HalpDisplayLock; PUSHORT VideoBuffer; // // If someone calls HalDisplayString before HalInitSystem, we need to be // able to put something up on screen anyway. // BOOLEAN HalpDisplayInitialized=FALSE; // // This is how we tell if GDI has taken over the display. If so, we are // in graphics mode and we need to reset the display to text mode before // displaying anything. (Panic stop) // BOOLEAN HalpOwnsDisplay=TRUE; PHAL_RESET_DISPLAY_PARAMETERS HalpResetDisplayParameters; BOOLEAN HalpDoingCrashDump = FALSE; VOID HalAcquireDisplayOwnership ( IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters ) /*++ Routine Description: This routine switches ownership of the display away from the HAL to the system display driver. It is called when the system has reached a point during bootstrap where it is self supporting and can output its own messages. Once ownership has passed to the system display driver any attempts to output messages using HalDisplayString must result in ownership of the display reverting to the HAL and the display hardware reinitialized for use by the HAL. Arguments: ResetDisplayParameters - if non-NULL the address of a function the hal can call to reset the video card. The function returns TRUE if the display was reset. Return Value: None. --*/ { HalpResetDisplayParameters=ResetDisplayParameters; HalpOwnsDisplay=FALSE; return; } VOID HalpVideoReboot() { if (HalpResetDisplayParameters && !HalpOwnsDisplay) { // // Video work-around. The video driver has a reset function, // call it before resetting the system in case the bios doesn't // know how to reset the displays video mode. // if (HalpResetDisplayParameters(COLS, ROWS)) { // display was reset, make sure it's blank HalpClearDisplay(); } } } VOID HalpInitializeDisplay( VOID ) /*++ Routine Description: Initializes the VGA display. This uses HalpMapPhysicalMemory to map the video buffer at 0xb8000 - 0xba000 into high virtual memory. Arguments: None. Return Value: None. --*/ { if (HalpDisplayInitialized == FALSE) { HalpDisplayInitialized = TRUE; KeInitializeSpinLock(&HalpDisplayLock); // // If somebody called HalDisplayString before Phase 0 initialization, // the video buffer has already been mapped and cleared, and a // message has already been displayed. So we don't want to clear // the screen again, or map the screen again. // // // Map two pages of memory starting at physical address 0xb8000. // VideoBuffer = (PUSHORT)HalpMapPhysicalMemory((PVOID)0xb8000,2); HalpClearDisplay(); } } VOID HalDisplayString ( PUCHAR String ) /*++ Routine Description: This routine displays a character string on the display screen. Arguments: String - Supplies a pointer to the characters that are to be displayed. Return Value: None. --*/ { if (!HalpDisplayInitialized && HalpOwnsDisplay) { // // If somebody has called HalDisplayString before Phase 0 // initialization, we need to make sure we get our message out // anyway. So we initialize the display before HalInitSystem does. // HalpInitializeDisplay is smart enough to only map the video // buffer and clear the screen the first time it is called. // HalpInitializeDisplay(); } // // Synchronize access to the display so that MP systems won't // get garbage output due to simultaneous calls. It also prevents // two processors from attempting to call BIOS and reset the display // simultaneously. // KiAcquireSpinLock(&HalpDisplayLock); if (HalpOwnsDisplay == FALSE) { // // The display has been put in graphics mode, and we need to // reset it to text mode before we can display any text on it. // if (HalpResetDisplayParameters) { HalpOwnsDisplay = HalpResetDisplayParameters(COLS, ROWS); } if (HalpOwnsDisplay == FALSE) { HalpBiosDisplayReset(); } HalpOwnsDisplay = TRUE; HalpDoingCrashDump = TRUE; HalpClearDisplay(); } while (*String) { switch (*String) { case '\n': HalpNextLine(); break; case '\r': HalpCursorX = 0; break; default: HalpPutCharacter(*String); if (++HalpCursorX == COLS) { HalpNextLine(); } } ++String; } KiReleaseSpinLock(&HalpDisplayLock); return; } VOID HalpDisplayDebugStatus ( PUCHAR str, ULONG len ) { PUSHORT p; if (!HalpDisplayInitialized || !HalpOwnsDisplay) { return; } for (p = &VideoBuffer [COLS - len]; len; str++, p++, len--) { *p = (USHORT)((REVERSE_ATTRIBUTE << 8) | *str); } } VOID HalQueryDisplayParameters ( OUT PULONG WidthInCharacters, OUT PULONG HeightInLines, OUT PULONG CursorColumn, OUT PULONG CursorRow ) /*++ Routine Description: This routine return information about the display area and current cursor position. Arguments: WidthInCharacter - Supplies a pointer to a varible that receives the width of the display area in characters. HeightInLines - Supplies a pointer to a variable that receives the height of the display area in lines. CursorColumn - Supplies a pointer to a variable that receives the current display column position. CursorRow - Supplies a pointer to a variable that receives the current display row position. Return Value: None. --*/ { *WidthInCharacters = COLS; *HeightInLines = ROWS; *CursorColumn = HalpCursorX; *CursorRow = HalpCursorX; } VOID HalSetDisplayParameters ( IN ULONG CursorColumn, IN ULONG CursorRow ) /*++ Routine Description: This routine set the current cursor position on the display area. Arguments: CursorColumn - Supplies the new display column position. CursorRow - Supplies a the new display row position. Return Value: None. --*/ { HalpCursorX = CursorColumn >= COLS ? COLS-1 : CursorColumn; HalpCursorY = CursorRow >= ROWS ? ROWS-1 : CursorRow; } VOID HalpNextLine( VOID ) /*++ Routine Description: Moves the cursor to the start of the next line, scrolling if necessary. Arguments: None. Return Value: None. --*/ { if (HalpCursorY==ROWS-1) { HalpScrollDisplay(); } else { ++HalpCursorY; } HalpCursorX = 0; } VOID HalpScrollDisplay( VOID ) /*++ Routine Description: Scrolls the text on the display up one line. Arguments: None Return Value: None. --*/ { PUSHORT NewStart; ULONG i; NewStart = VideoBuffer+COLS; RtlMoveMemory(VideoBuffer, NewStart, (ROWS-1)*COLS*sizeof(USHORT)); for (i=(ROWS-1)*COLS; i