display.c
来自「一个类似windows」· C语言 代码 · 共 797 行 · 第 1/2 页
C
797 行
/*
* ReactOS kernel
* Copyright (C) 1998, 1999, 2000, 2001, 2002 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: display.c 21261 2006-03-08 23:26:25Z audit $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/hal/x86/display.c
* PURPOSE: Blue screen display
* PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
* UPDATE HISTORY:
* Created 08/10/99
*/
/*
* Portions of this code are from the XFree86 Project and available from the
* following license:
*
* Copyright (C) 1994-2003 The XFree86 Project, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
* NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of the XFree86 Project shall
* not be used in advertising or otherwise to promote the sale, use or other
* dealings in this Software without prior written authorization from the
* XFree86 Project.
*/
/* DISPLAY OWNERSHIP
*
* So, who owns the physical display and is allowed to write to it?
*
* In MS NT, upon boot HAL owns the display. Somewhere in the boot
* sequence (haven't figured out exactly where or by who), some
* component calls HalAcquireDisplayOwnership. From that moment on,
* the display is owned by that component and is switched to graphics
* mode. The display is not supposed to return to text mode, except
* in case of a bug check. The bug check will call HalDisplayString
* to output a string to the text screen. HAL will notice that it
* currently doesn't own the display and will re-take ownership, by
* calling the callback function passed to HalAcquireDisplayOwnership.
* After the bugcheck, execution is halted. So, under NT, the only
* possible sequence of display modes is text mode -> graphics mode ->
* text mode (the latter hopefully happening very infrequently).
*
* Things are a little bit different in the current state of ReactOS.
* We want to have a functional interactive text mode. We should be
* able to switch from text mode to graphics mode when a GUI app is
* started and switch back to text mode when it's finished. Then, when
* another GUI app is started, another switch to and from graphics mode
* is possible. Also, when the system bugchecks in graphics mode we want
* to switch back to text mode to show the registers and stack trace.
* Last but not least, HalDisplayString is used a lot more in ReactOS,
* e.g. to print debug messages when the /DEBUGPORT=SCREEN boot option
* is present.
* 3 Components are involved in Reactos: HAL, BLUE.SYS and VIDEOPRT.SYS.
* As in NT, on boot HAL owns the display. When entering the text mode
* command interpreter, BLUE.SYS kicks in. It will write directly to the
* screen, more or less behind HALs back.
* When a GUI app is started, WIN32K.SYS will open the DISPLAY device.
* This open call will end up in VIDEOPRT.SYS. That component will then
* take ownership of the display by calling HalAcquireDisplayOwnership.
* When the GUI app terminates (WIN32K.SYS will close the DISPLAY device),
* we want to give ownership of the display back to HAL. Using the
* standard exported HAL functions, that's a bit of a problem, because
* there is no function defined to do that. In NT, this is handled by
* HalDisplayString, but that solution isn't satisfactory in ReactOS,
* because HalDisplayString is (in some cases) also used to output debug
* messages. If we do it the NT way, the first debug message output while
* in graphics mode would switch the display back to text mode.
* So, instead, if HalDisplayString detects that HAL doesn't have ownership
* of the display, it doesn't do anything.
* To return ownership to HAL, a new function is exported,
* HalReleaseDisplayOwnership. This function is called by the DISPLAY
* device Close routine in VIDEOPRT.SYS. It is also called at the beginning
* of a bug check, so HalDisplayString is activated again.
* Now, while the display is in graphics mode (not owned by HAL), BLUE.SYS
* should also refrain from writing to the screen buffer. The text mode
* screen buffer might overlap the graphics mode screen buffer, so changing
* something in the text mode buffer might mess up the graphics screen. To
* allow BLUE.SYS to detect if HAL owns the display, another new function is
* exported, HalQueryDisplayOwnership. BLUE.SYS will call this function to
* check if it's allowed to touch the text mode buffer.
*
* In an ideal world, when HAL takes ownership of the display, it should set
* up the CRT using real-mode (actually V86 mode, but who cares) INT 0x10
* calls. Unfortunately, this will require HAL to setup a real-mode interrupt
* table etc. So, we chickened out of that by having the loader set up the
* display before switching to protected mode. If HAL is given back ownership
* after a GUI app terminates, the INT 0x10 calls are made by VIDEOPRT.SYS,
* since there is already support for them via the VideoPortInt10 routine.
*/
#include <hal.h>
#define NDEBUG
#include <debug.h>
#define SCREEN_SYNCHRONIZATION
#define VGA_GRAPH_MEM 0xa0000
#define VGA_CHAR_MEM 0xb8000
#define VGA_END_MEM 0xbffff
#define VGA_AC_INDEX 0x3c0
#define VGA_AC_READ 0x3c1
#define VGA_AC_WRITE 0x3c0
#define VGA_MISC_WRITE 0x3c2
#define VGA_SEQ_INDEX 0x3c4
#define VGA_SEQ_DATA 0x3c5
#define VGA_DAC_MASK 0x3c6
#define VGA_DAC_READ_INDEX 0x3c7
#define VGA_DAC_WRITE_INDEX 0x3c8
#define VGA_DAC_DATA 0x3c9
#define VGA_FEATURE_READ 0x3ca
#define VGA_MISC_READ 0x3cc
#define VGA_GC_INDEX 0x3ce
#define VGA_GC_DATA 0x3cf
#define VGA_CRTC_INDEX 0x3d4
#define VGA_CRTC_DATA 0x3d5
#define VGA_INSTAT_READ 0x3da
#define VGA_SEQ_NUM_REGISTERS 5
#define VGA_CRTC_NUM_REGISTERS 25
#define VGA_GC_NUM_REGISTERS 9
#define VGA_AC_NUM_REGISTERS 21
#define CRTC_COLUMNS 0x01
#define CRTC_OVERFLOW 0x07
#define CRTC_ROWS 0x12
#define CRTC_SCANLINES 0x09
#define CRTC_CURHI 0x0e
#define CRTC_CURLO 0x0f
#define CHAR_ATTRIBUTE_BLACK 0x00 /* black on black */
#define CHAR_ATTRIBUTE 0x17 /* grey on blue */
#define FONT_AMOUNT (8*8192)
/* VARIABLES ****************************************************************/
static ULONG CursorX = 0; /* Cursor Position */
static ULONG CursorY = 0;
static ULONG SizeX = 80; /* Display size */
static ULONG SizeY = 25;
static BOOLEAN DisplayInitialized = FALSE;
static BOOLEAN HalOwnsDisplay = TRUE;
static PUSHORT VideoBuffer = NULL;
static PUCHAR GraphVideoBuffer = NULL;
static PHAL_RESET_DISPLAY_PARAMETERS HalResetDisplayParameters = NULL;
static UCHAR SavedTextPalette[768];
static UCHAR SavedTextMiscOutReg;
static UCHAR SavedTextCrtcReg[VGA_CRTC_NUM_REGISTERS];
static UCHAR SavedTextAcReg[VGA_AC_NUM_REGISTERS];
static UCHAR SavedTextGcReg[VGA_GC_NUM_REGISTERS];
static UCHAR SavedTextSeqReg[VGA_SEQ_NUM_REGISTERS];
static UCHAR SavedTextFont[2][FONT_AMOUNT];
static BOOLEAN TextPaletteEnabled = FALSE;
/* PRIVATE FUNCTIONS *********************************************************/
VOID FASTCALL
HalClearDisplay (UCHAR CharAttribute)
{
WORD *ptr = (WORD*)VideoBuffer;
ULONG i;
for (i = 0; i < SizeX * SizeY; i++, ptr++)
*ptr = ((CharAttribute << 8) + ' ');
CursorX = 0;
CursorY = 0;
}
/* STATIC FUNCTIONS *********************************************************/
VOID STATIC
HalScrollDisplay (VOID)
{
PUSHORT ptr;
int i;
ptr = VideoBuffer + SizeX;
RtlMoveMemory(VideoBuffer,
ptr,
SizeX * (SizeY - 1) * 2);
ptr = VideoBuffer + (SizeX * (SizeY - 1));
for (i = 0; i < (int)SizeX; i++, ptr++)
{
*ptr = (CHAR_ATTRIBUTE << 8) + ' ';
}
}
VOID STATIC FASTCALL
HalPutCharacter (CHAR Character)
{
PUSHORT ptr;
ptr = VideoBuffer + ((CursorY * SizeX) + CursorX);
*ptr = (CHAR_ATTRIBUTE << 8) + Character;
}
VOID STATIC
HalDisablePalette(VOID)
{
(VOID)READ_PORT_UCHAR((PUCHAR)VGA_INSTAT_READ);
WRITE_PORT_UCHAR((PUCHAR)VGA_AC_INDEX, 0x20);
TextPaletteEnabled = FALSE;
}
VOID STATIC
HalEnablePalette(VOID)
{
(VOID)READ_PORT_UCHAR((PUCHAR)VGA_INSTAT_READ);
WRITE_PORT_UCHAR((PUCHAR)VGA_AC_INDEX, 0x00);
TextPaletteEnabled = TRUE;
}
UCHAR STATIC FASTCALL
HalReadGc(ULONG Index)
{
WRITE_PORT_UCHAR((PUCHAR)VGA_GC_INDEX, (UCHAR)Index);
return(READ_PORT_UCHAR((PUCHAR)VGA_GC_DATA));
}
VOID STATIC FASTCALL
HalWriteGc(ULONG Index, UCHAR Value)
{
WRITE_PORT_UCHAR((PUCHAR)VGA_GC_INDEX, (UCHAR)Index);
WRITE_PORT_UCHAR((PUCHAR)VGA_GC_DATA, Value);
}
UCHAR STATIC FASTCALL
HalReadSeq(ULONG Index)
{
WRITE_PORT_UCHAR((PUCHAR)VGA_SEQ_INDEX, (UCHAR)Index);
return(READ_PORT_UCHAR((PUCHAR)VGA_SEQ_DATA));
}
VOID STATIC FASTCALL
HalWriteSeq(ULONG Index, UCHAR Value)
{
WRITE_PORT_UCHAR((PUCHAR)VGA_SEQ_INDEX, (UCHAR)Index);
WRITE_PORT_UCHAR((PUCHAR)VGA_SEQ_DATA, Value);
}
VOID STATIC FASTCALL
HalWriteAc(ULONG Index, UCHAR Value)
{
if (TextPaletteEnabled)
{
Index &= ~0x20;
}
else
{
Index |= 0x20;
}
(VOID)READ_PORT_UCHAR((PUCHAR)VGA_INSTAT_READ);
WRITE_PORT_UCHAR((PUCHAR)VGA_AC_INDEX, (UCHAR)Index);
WRITE_PORT_UCHAR((PUCHAR)VGA_AC_WRITE, Value);
}
UCHAR STATIC FASTCALL
HalReadAc(ULONG Index)
{
if (TextPaletteEnabled)
{
Index &= ~0x20;
}
else
{
Index |= 0x20;
}
(VOID)READ_PORT_UCHAR((PUCHAR)VGA_INSTAT_READ);
WRITE_PORT_UCHAR((PUCHAR)VGA_AC_INDEX, (UCHAR)Index);
return(READ_PORT_UCHAR((PUCHAR)VGA_AC_READ));
}
VOID STATIC FASTCALL
HalWriteCrtc(ULONG Index, UCHAR Value)
{
WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, (UCHAR)Index);
WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA, Value);
}
UCHAR STATIC FASTCALL
HalReadCrtc(ULONG Index)
{
WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, (UCHAR)Index);
return(READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA));
}
VOID STATIC FASTCALL
HalResetSeq(BOOLEAN Start)
{
if (Start)
{
HalWriteSeq(0x00, 0x01);
}
else
{
HalWriteSeq(0x00, 0x03);
}
}
VOID STATIC FASTCALL
HalBlankScreen(BOOLEAN On)
{
UCHAR Scrn;
Scrn = HalReadSeq(0x01);
if (On)
{
Scrn &= ~0x20;
}
else
{
Scrn |= 0x20;
}
HalResetSeq(TRUE);
HalWriteSeq(0x01, Scrn);
HalResetSeq(FALSE);
}
VOID STATIC
HalSaveFont(VOID)
{
UCHAR Attr10;
UCHAR MiscOut, Gc4, Gc5, Gc6, Seq2, Seq4;
ULONG i;
/* Check if we are already in graphics mode. */
Attr10 = HalReadAc(0x10);
if (Attr10 & 0x01)
{
return;
}
/* Save registers. */
MiscOut = READ_PORT_UCHAR((PUCHAR)VGA_MISC_READ);
Gc4 = HalReadGc(0x04);
Gc5 = HalReadGc(0x05);
Gc6 = HalReadGc(0x06);
Seq2 = HalReadSeq(0x02);
Seq4 = HalReadSeq(0x04);
/* Force colour mode. */
WRITE_PORT_UCHAR((PUCHAR)VGA_MISC_WRITE, (UCHAR)(MiscOut | 0x01));
HalBlankScreen(FALSE);
for (i = 0; i < 2; i++)
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?