477 lines
8.6 KiB
C
477 lines
8.6 KiB
C
/*++
|
||
|
||
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<ROWS*COLS; i++) {
|
||
VideoBuffer[i] = (REVERSE_ATTRIBUTE << 8) | ' ';
|
||
}
|
||
}
|
||
|
||
VOID
|
||
HalpPutCharacter(
|
||
IN UCHAR Character
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Places a character on the console screen. It uses the variables
|
||
HalpCursorX and HalpCursorY to determine the character's location.
|
||
|
||
Arguments:
|
||
|
||
Character - Supplies the character to be displayed
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
VideoBuffer[HalpCursorY*COLS + HalpCursorX] =
|
||
(USHORT)((REVERSE_ATTRIBUTE << 8) | Character);
|
||
}
|
||
|
||
VOID
|
||
HalpClearDisplay(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Clears the video display and sets the current cursor position to the
|
||
upper left-hand corner.
|
||
|
||
Arguments:
|
||
|
||
None
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
USHORT Attribute;
|
||
ULONG i;
|
||
|
||
Attribute = (REVERSE_ATTRIBUTE << 8) | ' ';
|
||
for (i=0; i < ROWS*COLS; i++) {
|
||
VideoBuffer[i] = Attribute;
|
||
}
|
||
HalpCursorX=0;
|
||
HalpCursorY=0;
|
||
|
||
}
|