- Cleaned up the Boot Video driver.

- Replaced most of the magic numbers by defines.
- Changed the video mode setting to directly program the VGA registers instead of using Ke386CallBios.
- Properly map the video memory.

svn path=/trunk/; revision=8534
This commit is contained in:
Filip Navara 2004-03-04 18:55:09 +00:00
parent 5c30d2cc66
commit a2f24f38dc
3 changed files with 599 additions and 639 deletions

View file

@ -1,12 +1,24 @@
/* $Id: bootvid.c,v 1.6 2004/02/10 16:22:55 navaraf Exp $ /*
* ReactOS Boot video driver
* *
* COPYRIGHT: See COPYING in the top level directory * Copyright (C) 2003 Casper S. Hornstroup
* PROJECT: ReactOS kernel * Copyright (C) 2004 Filip Navara
* FILE: ntoskrnl/inbv/bootvid.c *
* PURPOSE: Boot video support * This program is free software; you can redistribute it and/or
* PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) * modify it under the terms of the GNU General Public License
* UPDATE HISTORY: * as published by the Free Software Foundation; either version 2
* 12-07-2003 CSH Created * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Id: bootvid.c,v 1.7 2004/03/04 18:55:08 navaraf Exp $
*/ */
/* INCLUDES ******************************************************************/ /* INCLUDES ******************************************************************/
@ -15,106 +27,56 @@
#include <ddk/ntbootvid.h> #include <ddk/ntbootvid.h>
#include <reactos/resource.h> #include <reactos/resource.h>
#include <rosrtl/string.h> #include <rosrtl/string.h>
#include "bootvid.h"
#include "../../../ntoskrnl/include/internal/v86m.h" #define NDEBUG
/*#define NDEBUG*/
#include <debug.h> #include <debug.h>
#define RT_BITMAP 2
typedef struct tagRGBQUAD {
unsigned char rgbBlue;
unsigned char rgbGreen;
unsigned char rgbRed;
unsigned char rgbReserved;
} RGBQUAD, *PRGBQUAD;
typedef long FXPT2DOT30;
typedef struct tagCIEXYZ {
FXPT2DOT30 ciexyzX;
FXPT2DOT30 ciexyzY;
FXPT2DOT30 ciexyzZ;
} CIEXYZ;
typedef CIEXYZ * LPCIEXYZ;
typedef struct tagCIEXYZTRIPLE {
CIEXYZ ciexyzRed;
CIEXYZ ciexyzGreen;
CIEXYZ ciexyzBlue;
} CIEXYZTRIPLE;
typedef CIEXYZTRIPLE *LPCIEXYZTRIPLE;
typedef struct {
DWORD bV5Size;
LONG bV5Width;
LONG bV5Height;
WORD bV5Planes;
WORD bV5BitCount;
DWORD bV5Compression;
DWORD bV5SizeImage;
LONG bV5XPelsPerMeter;
LONG bV5YPelsPerMeter;
DWORD bV5ClrUsed;
DWORD bV5ClrImportant;
DWORD bV5RedMask;
DWORD bV5GreenMask;
DWORD bV5BlueMask;
DWORD bV5AlphaMask;
DWORD bV5CSType;
CIEXYZTRIPLE bV5Endpoints;
DWORD bV5GammaRed;
DWORD bV5GammaGreen;
DWORD bV5GammaBlue;
DWORD bV5Intent;
DWORD bV5ProfileData;
DWORD bV5ProfileSize;
DWORD bV5Reserved;
} BITMAPV5HEADER, *PBITMAPV5HEADER;
#define MISC 0x3c2
#define SEQ 0x3c4
#define CRTC 0x3d4
#define GRAPHICS 0x3ce
#define FEATURE 0x3da
#define ATTRIB 0x3c0
#define STATUS 0x3da
typedef struct {
ULONG r;
ULONG g;
ULONG b;
} FADER_PALETTE_ENTRY;
/* In pixelsups.S */
extern VOID
InbvPutPixels(int x, int y, unsigned long c);
/* GLOBALS *******************************************************************/ /* GLOBALS *******************************************************************/
char *vidmem; /*
* NOTE:
* This is based on SvgaLib 640x480x16 mode definition with the
* following changes:
* - Graphics: Data Rotate (Index 3)
* Set to zero to indicate that the data written to video memory by
* CPU should be processed unmodified.
* - Graphics: Mode Register (index 5)
* Set to Write Mode 2 and Read Mode 0.
*/
static VGA_REGISTERS Mode12Regs =
{
/* CRT Controller Registers */
{0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xE3},
/* Attribute Controller Registers */
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
0x0C, 0x0D, 0x0E, 0x0F, 0x81, 0x00, 0x0F, 0x00, 0x00},
/* Graphics Controller Registers */
{0x00, 0x0F, 0x00, 0x00, 0x00, 0x02, 0x05, 0x0F, 0xFF},
/* Sequencer Registers */
{0x03, 0x01, 0x0F, 0x00, 0x06},
/* Misc Output Register */
0xE3
};
PUCHAR VideoMemory;
/* Must be 4 bytes per entry */ /* Must be 4 bytes per entry */
long maskbit[640]; long maskbit[640];
long y80[480];
static HANDLE BitmapThreadHandle; static HANDLE BitmapThreadHandle;
static CLIENT_ID BitmapThreadId; static CLIENT_ID BitmapThreadId;
static BOOLEAN BitmapIsDrawn;
static PUCHAR BootimageBitmap; static PUCHAR BootimageBitmap;
static BOOLEAN InGraphicsMode = FALSE;
/* DATA **********************************************************************/ /* DATA **********************************************************************/
static BOOLEAN VideoAddressSpaceInitialized = FALSE;
static PVOID NonBiosBaseAddress;
static PDRIVER_OBJECT BootVidDriverObject = NULL; static PDRIVER_OBJECT BootVidDriverObject = NULL;
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
static BOOLEAN STATIC BOOLEAN FASTCALL
InbvFindBootimage() InbvFindBootimage()
{ {
PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry; PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry;
@ -127,20 +89,24 @@ InbvFindBootimage()
ResourceInfo.Name = IDB_BOOTIMAGE; ResourceInfo.Name = IDB_BOOTIMAGE;
ResourceInfo.Language = 0x09; ResourceInfo.Language = 0x09;
Status = LdrFindResource_U(BaseAddress, Status = LdrFindResource_U(
BaseAddress,
&ResourceInfo, &ResourceInfo,
RESOURCE_DATA_LEVEL, RESOURCE_DATA_LEVEL,
&ResourceDataEntry); &ResourceDataEntry);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT("LdrFindResource_U() failed with status 0x%.08x\n", Status); DPRINT("LdrFindResource_U() failed with status 0x%.08x\n", Status);
return FALSE; return FALSE;
} }
Status = LdrAccessResource(BaseAddress, Status = LdrAccessResource(
BaseAddress,
ResourceDataEntry, ResourceDataEntry,
(PVOID*)&BootimageBitmap, (PVOID*)&BootimageBitmap,
&Size); &Size);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT("LdrAccessResource() failed with status 0x%.08x\n", Status); DPRINT("LdrAccessResource() failed with status 0x%.08x\n", Status);
@ -151,150 +117,32 @@ InbvFindBootimage()
} }
static BOOLEAN STATIC BOOLEAN FASTCALL
InbvInitializeVideoAddressSpace(VOID) InbvMapVideoMemory(VOID)
{ {
OBJECT_ATTRIBUTES ObjectAttributes; PHYSICAL_ADDRESS PhysicalAddress;
UNICODE_STRING PhysMemName;
NTSTATUS Status;
HANDLE PhysMemHandle;
PVOID BaseAddress;
LARGE_INTEGER Offset;
ULONG ViewSize;
CHAR IVT[1024];
CHAR BDA[256];
PVOID start = (PVOID)0x0;
/* PhysicalAddress.QuadPart = 0xA0000;
* Open the physical memory section VideoMemory = MmMapIoSpace(PhysicalAddress, 0x10000, FALSE);
*/
RtlRosInitUnicodeStringFromLiteral(&PhysMemName, L"\\Device\\PhysicalMemory");
InitializeObjectAttributes(&ObjectAttributes,
&PhysMemName,
0,
NULL,
NULL);
Status = ZwOpenSection(&PhysMemHandle, SECTION_ALL_ACCESS,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
DPRINT("Couldn't open \\Device\\PhysicalMemory\n");
return FALSE;
}
/* return VideoMemory != NULL;
* Map the BIOS and device registers into the address space }
*/
Offset.QuadPart = 0xa0000;
ViewSize = 0x100000 - 0xa0000;
BaseAddress = (PVOID)0xa0000;
Status = NtMapViewOfSection(PhysMemHandle,
NtCurrentProcess(),
&BaseAddress,
0,
8192,
&Offset,
&ViewSize,
ViewUnmap,
0,
PAGE_EXECUTE_READWRITE);
if (!NT_SUCCESS(Status))
{
DPRINT("Couldn't map physical memory (%x)\n", Status);
NtClose(PhysMemHandle);
return FALSE;
}
NtClose(PhysMemHandle);
if (BaseAddress != (PVOID)0xa0000)
{
DPRINT("Couldn't map physical memory at the right address "
"(was %x)\n", BaseAddress);
return FALSE;
}
/*
* Map some memory to use for the non-BIOS parts of the v86 mode address
* space
*/
NonBiosBaseAddress = (PVOID)0x1;
ViewSize = 0xa0000 - 0x1000;
Status = NtAllocateVirtualMemory(NtCurrentProcess(),
&NonBiosBaseAddress,
0,
&ViewSize,
MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
if (!NT_SUCCESS(Status))
{
DPRINT("Failed to allocate virtual memory (Status %x)\n", Status);
return FALSE;
}
if (NonBiosBaseAddress != (PVOID)0x0)
{
DPRINT("Failed to allocate virtual memory at right address "
"(was %x)\n", NonBiosBaseAddress);
return FALSE;
}
/*
* Get the real mode IVT from the kernel
*/
Status = NtVdmControl(0, IVT);
if (!NT_SUCCESS(Status))
{
DPRINT("NtVdmControl failed (status %x)\n", Status);
return FALSE;
}
/*
* Copy the real mode IVT into the right place
*/
memcpy(start, IVT, 1024);
/*
* Get the BDA from the kernel
*/
Status = NtVdmControl(1, BDA);
if (!NT_SUCCESS(Status))
{
DPRINT("NtVdmControl failed (status %x)\n", Status);
return FALSE;
}
/*
* Copy the BDA into the right place
*/
memcpy((PVOID)0x400, BDA, 256);
STATIC BOOLEAN FASTCALL
InbvUnmapVideoMemory(VOID)
{
MmUnmapIoSpace(VideoMemory, 0x10000);
return TRUE; return TRUE;
} }
static BOOLEAN STATIC VOID FASTCALL
InbvDeinitializeVideoAddressSpace(VOID)
{
ULONG RegionSize;
PUCHAR ViewBase;
RegionSize = 0xa0000 - 0x1000;
NtFreeVirtualMemory(NtCurrentProcess(),
&NonBiosBaseAddress,
&RegionSize,
MEM_RELEASE);
ViewBase = (PUCHAR) 0xa0000;
ZwUnmapViewOfSection(NtCurrentProcess(), ViewBase);
return TRUE;
}
static VOID
vgaPreCalc() vgaPreCalc()
{ {
ULONG j; ULONG j;
for(j = 0; j < 80; j++) for (j = 0; j < 80; j++)
{ {
maskbit[j * 8 + 0] = 128; maskbit[j * 8 + 0] = 128;
maskbit[j * 8 + 1] = 64; maskbit[j * 8 + 1] = 64;
@ -305,9 +153,56 @@ vgaPreCalc()
maskbit[j * 8 + 6] = 2; maskbit[j * 8 + 6] = 2;
maskbit[j * 8 + 7] = 1; maskbit[j * 8 + 7] = 1;
} }
for(j = 0; j < 480; j++) }
STATIC VOID FASTCALL
vgaSetRegisters(PVGA_REGISTERS Registers)
{
int i;
/* Update misc output register */
WRITE_PORT_UCHAR(MISC, Registers->Misc);
/* Synchronous reset on */
WRITE_PORT_UCHAR(SEQ, 0x00);
WRITE_PORT_UCHAR(SEQDATA, 0x01);
/* Write sequencer registers */
for (i = 1; i < sizeof(Registers->Sequencer); i++)
{ {
y80[j] = j * 80; /* 80 = 640 / 8 = Number of bytes per scanline */ WRITE_PORT_UCHAR(SEQ, i);
WRITE_PORT_UCHAR(SEQDATA, Registers->Sequencer[i]);
}
/* Synchronous reset off */
WRITE_PORT_UCHAR(SEQ, 0x00);
WRITE_PORT_UCHAR(SEQDATA, 0x03);
/* Deprotect CRT registers 0-7 */
WRITE_PORT_UCHAR(CRTC, 0x11);
WRITE_PORT_UCHAR(CRTCDATA, Registers->CRT[0x11] & 0x7f);
/* Write CRT registers */
for (i = 0; i < sizeof(Registers->CRT); i++)
{
WRITE_PORT_UCHAR(CRTC, i);
WRITE_PORT_UCHAR(CRTCDATA, Registers->CRT[i]);
}
/* Write graphics controller registers */
for (i = 0; i < sizeof(Registers->Graphics); i++)
{
WRITE_PORT_UCHAR(GRAPHICS, i);
WRITE_PORT_UCHAR(GRAPHICSDATA, Registers->Graphics[i]);
}
/* Write attribute controller registers */
for (i = 0; i < sizeof(Registers->Attribute); i++)
{
READ_PORT_UCHAR(STATUS);
WRITE_PORT_UCHAR(ATTRIB, i);
WRITE_PORT_UCHAR(ATTRIB, Registers->Attribute[i]);
} }
} }
@ -315,121 +210,71 @@ vgaPreCalc()
static VOID static VOID
InbvInitVGAMode(VOID) InbvInitVGAMode(VOID)
{ {
KV86M_REGISTERS Regs; /* Zero out video memory (clear a possibly trashed screen) */
NTSTATUS Status; RtlZeroMemory(VideoMemory, 0x10000);
ULONG i;
vidmem = (char *)(0xd0000000 + 0xa0000); vgaSetRegisters(&Mode12Regs);
memset(&Regs, 0, sizeof(Regs));
Regs.Eax = 0x0012;
Status = Ke386CallBios(0x10, &Regs);
assert(NT_SUCCESS(Status));
/* Get VGA registers into the correct state */
/* Reset the internal flip-flop. */
(VOID)READ_PORT_UCHAR((PUCHAR)FEATURE);
/* Write the 16 palette registers. */
for (i = 0; i < 16; i++)
{
WRITE_PORT_UCHAR((PUCHAR)ATTRIB, i);
WRITE_PORT_UCHAR((PUCHAR)ATTRIB, i);
}
/* Write the mode control register - graphics mode; 16 color DAC. */
WRITE_PORT_UCHAR((PUCHAR)ATTRIB, 0x10);
WRITE_PORT_UCHAR((PUCHAR)ATTRIB, 0x81);
/* Write the color select register - select first 16 DAC registers. */
WRITE_PORT_UCHAR((PUCHAR)ATTRIB, 0x14);
WRITE_PORT_UCHAR((PUCHAR)ATTRIB, 0x00);
/* Get the VGA into the mode we want to work with */
WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08); /* Set */
WRITE_PORT_UCHAR((PUCHAR)0x3cf,0); /* the MASK */
WRITE_PORT_USHORT((PUSHORT)0x3ce,0x0205); /* write mode = 2 (bits 0,1) read mode = 0 (bit 3) */
(UCHAR) READ_REGISTER_UCHAR(vidmem); /* Update bit buffer */
WRITE_REGISTER_UCHAR(vidmem, 0); /* Write the pixel */
WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08);
WRITE_PORT_UCHAR((PUCHAR)0x3cf,0xff);
/* Set the PEL mask. */ /* Set the PEL mask. */
WRITE_PORT_UCHAR((PUCHAR)0x3c6, 0xff); WRITE_PORT_UCHAR(PELMASK, 0xff);
/* Zero out video memory (clear a possibly trashed screen) */
RtlZeroMemory(vidmem, 64000);
vgaPreCalc(); vgaPreCalc();
} }
BOOL BOOL STDCALL
STDCALL
VidResetDisplay(VOID) VidResetDisplay(VOID)
{ {
/* /*
We are only using standard VGA facilities so we can rely on the HAL 'int10mode3' * We are only using standard VGA facilities so we can rely on the
reset to cleanup the hardware state. * HAL 'int10mode3' reset to cleanup the hardware state.
*/ */
InGraphicsMode = FALSE;
return FALSE; return FALSE;
} }
VOID VOID STDCALL
STDCALL
VidCleanUp(VOID) VidCleanUp(VOID)
{ {
/* InbvUnmapVideoMemory();
We are only using standard VGA facilities so we can rely on the HAL 'int10mode3'
reset to cleanup the hardware state.
*/
InGraphicsMode = FALSE;
} }
static __inline__ VOID STATIC VOID FASTCALL
InbvSetColor(int cindex, unsigned char red, unsigned char green, unsigned char blue) InbvSetColor(INT Index, UCHAR Red, UCHAR Green, UCHAR Blue)
{ {
red = (red * 63) / 255; WRITE_PORT_UCHAR(PELINDEX, Index);
green = (green * 63) / 255; WRITE_PORT_UCHAR(PELDATA, Red >> 2);
blue = (blue * 63) / 255; WRITE_PORT_UCHAR(PELDATA, Green >> 2);
WRITE_PORT_UCHAR(PELDATA, Blue >> 2);
WRITE_PORT_UCHAR((PUCHAR)0x03c8, cindex);
(VOID)READ_PORT_UCHAR((PUCHAR)FEATURE);
(VOID)READ_PORT_UCHAR((PUCHAR)FEATURE);
WRITE_PORT_UCHAR((PUCHAR)0x03c9, red);
(VOID)READ_PORT_UCHAR((PUCHAR)FEATURE);
(VOID)READ_PORT_UCHAR((PUCHAR)FEATURE);
WRITE_PORT_UCHAR((PUCHAR)0x03c9, green);
(VOID)READ_PORT_UCHAR((PUCHAR)FEATURE);
(VOID)READ_PORT_UCHAR((PUCHAR)FEATURE);
WRITE_PORT_UCHAR((PUCHAR)0x03c9, blue);
(VOID)READ_PORT_UCHAR((PUCHAR)FEATURE);
(VOID)READ_PORT_UCHAR((PUCHAR)FEATURE);
} }
static __inline__ VOID STATIC VOID FASTCALL
InbvSetBlackPalette() InbvSetBlackPalette()
{ {
register ULONG r = 0; register ULONG r = 0;
/* Disable screen and enable palette access. */ /* Disable screen and enable palette access. */
(VOID)READ_PORT_UCHAR((PUCHAR)FEATURE); READ_PORT_UCHAR(STATUS);
WRITE_PORT_UCHAR((PUCHAR)0x3c0, 0x00); WRITE_PORT_UCHAR(ATTRIB, 0x00);
for (r = 0; r < 16; r++) for (r = 0; r < 16; r++)
{ {
InbvSetColor(r, 0, 0, 0); InbvSetColor(r, 0, 0, 0);
} }
/* Enable screen and enable palette access. */ /* Enable screen and enable palette access. */
(VOID)READ_PORT_UCHAR((PUCHAR)FEATURE); READ_PORT_UCHAR(STATUS);
WRITE_PORT_UCHAR((PUCHAR)0x3c0, 0x20); WRITE_PORT_UCHAR(ATTRIB, 0x20);
} }
static VOID STATIC VOID FASTCALL
InbvDisplayBitmap(ULONG Width, ULONG Height, PCHAR ImageData) InbvDisplayBitmap(ULONG Width, ULONG Height, PCHAR ImageData)
{ {
ULONG j,k,y; ULONG j, k, y;
register ULONG i; register ULONG i;
register ULONG x; register ULONG x;
register ULONG c; register ULONG c;
@ -456,7 +301,7 @@ InbvDisplayBitmap(ULONG Width, ULONG Height, PCHAR ImageData)
c = ImageData[k + x]; c = ImageData[k + x];
for (i = 1; i < 4; i++) for (i = 1; i < 4; i++)
{ {
if (x + i*8 < Width) if (x + i * 8 < Width)
{ {
c |= (ImageData[k + x + i * 8] << i * 8); c |= (ImageData[k + x + i * 8] << i * 8);
} }
@ -464,7 +309,7 @@ InbvDisplayBitmap(ULONG Width, ULONG Height, PCHAR ImageData)
} }
InbvPutPixels(x, 479 - y, c); InbvPutPixels(x, 479 - y, c);
x += 8*4; x += 8 * 4;
} }
} }
k += Width; k += Width;
@ -472,7 +317,7 @@ InbvDisplayBitmap(ULONG Width, ULONG Height, PCHAR ImageData)
} }
static VOID STATIC VOID FASTCALL
InbvDisplayCompressedBitmap() InbvDisplayCompressedBitmap()
{ {
PBITMAPV5HEADER bminfo; PBITMAPV5HEADER bminfo;
@ -609,16 +454,13 @@ InbvDisplayCompressedBitmap()
} }
#define PALETTE_FADE_STEPS 20 STATIC VOID FASTCALL
#define PALETTE_FADE_TIME 20 * 10000 /* 20ms */
static VOID
InbvFadeUpPalette() InbvFadeUpPalette()
{ {
PBITMAPV5HEADER bminfo; PBITMAPV5HEADER bminfo;
PRGBQUAD Palette; PRGBQUAD Palette;
ULONG i; ULONG i;
unsigned char r,g,b; unsigned char r, g, b;
register ULONG c; register ULONG c;
LARGE_INTEGER Interval; LARGE_INTEGER Interval;
FADER_PALETTE_ENTRY FaderPalette[16]; FADER_PALETTE_ENTRY FaderPalette[16];
@ -627,8 +469,8 @@ InbvFadeUpPalette()
RtlZeroMemory(&FaderPalette, sizeof(FaderPalette)); RtlZeroMemory(&FaderPalette, sizeof(FaderPalette));
RtlZeroMemory(&FaderPaletteDelta, sizeof(FaderPaletteDelta)); RtlZeroMemory(&FaderPaletteDelta, sizeof(FaderPaletteDelta));
bminfo = (PBITMAPV5HEADER) &BootimageBitmap[0]; //sizeof(BITMAPFILEHEADER)]; bminfo = (PBITMAPV5HEADER)&BootimageBitmap[0];
Palette = (PRGBQUAD) &BootimageBitmap[/* sizeof(BITMAPFILEHEADER) + */ bminfo->bV5Size]; Palette = (PRGBQUAD)&BootimageBitmap[bminfo->bV5Size];
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
{ {
@ -643,8 +485,9 @@ InbvFadeUpPalette()
for (i = 0; i < PALETTE_FADE_STEPS; i++) for (i = 0; i < PALETTE_FADE_STEPS; i++)
{ {
/* Disable screen and enable palette access. */ /* Disable screen and enable palette access. */
(VOID)READ_PORT_UCHAR((PUCHAR)FEATURE); READ_PORT_UCHAR(STATUS);
WRITE_PORT_UCHAR((PUCHAR)0x3c0, 0x00); WRITE_PORT_UCHAR(ATTRIB, 0x00);
for (c = 0; c < bminfo->bV5ClrUsed; c++) for (c = 0; c < bminfo->bV5ClrUsed; c++)
{ {
/* Add the delta */ /* Add the delta */
@ -668,16 +511,19 @@ InbvFadeUpPalette()
/* Update the hardware */ /* Update the hardware */
InbvSetColor(c, r, g, b); InbvSetColor(c, r, g, b);
} }
/* Enable screen and disable palette access. */ /* Enable screen and disable palette access. */
(VOID)READ_PORT_UCHAR((PUCHAR)FEATURE); READ_PORT_UCHAR(STATUS);
WRITE_PORT_UCHAR((PUCHAR)0x3c0, 0x20); WRITE_PORT_UCHAR(ATTRIB, 0x20);
/* Wait for a bit. */ /* Wait for a bit. */
Interval.QuadPart = -PALETTE_FADE_TIME; Interval.QuadPart = -PALETTE_FADE_TIME;
KeDelayExecutionThread(KernelMode, FALSE, &Interval); KeDelayExecutionThread(KernelMode, FALSE, &Interval);
} }
} }
static VOID STDCALL
STATIC VOID STDCALL
InbvBitmapThreadMain(PVOID Ignored) InbvBitmapThreadMain(PVOID Ignored)
{ {
if (InbvFindBootimage()) if (InbvFindBootimage())
@ -689,98 +535,83 @@ InbvBitmapThreadMain(PVOID Ignored)
{ {
DbgPrint("Warning: Cannot find boot image\n"); DbgPrint("Warning: Cannot find boot image\n");
} }
BitmapIsDrawn = TRUE;
} }
BOOLEAN STATIC BOOLEAN STDCALL
STDCALL
VidIsBootDriverInstalled(VOID)
{
return InGraphicsMode;
}
BOOLEAN
STDCALL
VidInitialize(VOID) VidInitialize(VOID)
{ {
NTSTATUS Status; NTSTATUS Status;
if (!VideoAddressSpaceInitialized) InbvMapVideoMemory();
{
InbvInitializeVideoAddressSpace();
}
InbvInitVGAMode(); InbvInitVGAMode();
InGraphicsMode = TRUE; Status = PsCreateSystemThread(
&BitmapThreadHandle,
BitmapIsDrawn = FALSE;
Status = PsCreateSystemThread(&BitmapThreadHandle,
THREAD_ALL_ACCESS, THREAD_ALL_ACCESS,
NULL, NULL,
NULL, NULL,
&BitmapThreadId, &BitmapThreadId,
InbvBitmapThreadMain, InbvBitmapThreadMain,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
return FALSE; return FALSE;
} }
NtClose(BitmapThreadHandle);
InbvDeinitializeVideoAddressSpace(); NtClose(BitmapThreadHandle);
VideoAddressSpaceInitialized = FALSE;
return TRUE; return TRUE;
} }
NTSTATUS STDCALL NTSTATUS STDCALL
VidDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) VidDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{ {
PIO_STACK_LOCATION piosStack = IoGetCurrentIrpStackLocation(Irp); PIO_STACK_LOCATION IrpSp;
NTSTATUS nErrCode; NTSTATUS Status;
NTBOOTVID_FUNCTION_TABLE* FunctionTable; NTBOOTVID_FUNCTION_TABLE* FunctionTable;
nErrCode = STATUS_SUCCESS; IrpSp = IoGetCurrentIrpStackLocation(Irp);
Status = STATUS_SUCCESS;
switch(piosStack->MajorFunction) switch(IrpSp->MajorFunction)
{ {
/* opening and closing handles to the device */ /* Opening and closing handles to the device */
case IRP_MJ_CREATE: case IRP_MJ_CREATE:
case IRP_MJ_CLOSE: case IRP_MJ_CLOSE:
break; break;
case IRP_MJ_DEVICE_CONTROL: case IRP_MJ_DEVICE_CONTROL:
switch (piosStack->Parameters.DeviceIoControl.IoControlCode) switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
{ {
case IOCTL_BOOTVID_INITIALIZE: case IOCTL_BOOTVID_INITIALIZE:
VidInitialize(); VidInitialize();
FunctionTable = (NTBOOTVID_FUNCTION_TABLE*) FunctionTable = (NTBOOTVID_FUNCTION_TABLE *)
Irp->AssociatedIrp.SystemBuffer; Irp->AssociatedIrp.SystemBuffer;
FunctionTable->ResetDisplay = VidResetDisplay; FunctionTable->ResetDisplay = VidResetDisplay;
break; break;
case IOCTL_BOOTVID_CLEANUP: case IOCTL_BOOTVID_CLEANUP:
VidCleanUp(); VidCleanUp();
break; break;
default: default:
nErrCode = STATUS_NOT_IMPLEMENTED; Status = STATUS_NOT_IMPLEMENTED;
break; break;
} }
break; break;
/* unsupported operations */ /* Unsupported operations */
default: default:
nErrCode = STATUS_NOT_IMPLEMENTED; Status = STATUS_NOT_IMPLEMENTED;
} }
Irp->IoStatus.Status = nErrCode; Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT); IoCompleteRequest(Irp, IO_NO_INCREMENT);
return nErrCode; return Status;
} }
@ -793,23 +624,25 @@ DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
BootVidDriverObject = DriverObject; BootVidDriverObject = DriverObject;
/* register driver routines */ /* Register driver routines */
DriverObject->MajorFunction[IRP_MJ_CLOSE] = VidDispatch; DriverObject->MajorFunction[IRP_MJ_CLOSE] = VidDispatch;
DriverObject->MajorFunction[IRP_MJ_CREATE] = VidDispatch; DriverObject->MajorFunction[IRP_MJ_CREATE] = VidDispatch;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VidDispatch; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VidDispatch;
DriverObject->DriverUnload = NULL; DriverObject->DriverUnload = NULL;
/* create device */ DriverObject->Flags |= DO_BUFFERED_IO;
/* Create device */
RtlRosInitUnicodeStringFromLiteral(&DeviceName, L"\\Device\\BootVid"); RtlRosInitUnicodeStringFromLiteral(&DeviceName, L"\\Device\\BootVid");
Status = IoCreateDevice(DriverObject, 0, &DeviceName, FILE_DEVICE_BOOTVID, Status = IoCreateDevice(
0, FALSE, &BootVidDevice); DriverObject,
if (! NT_SUCCESS(Status)) 0,
{ &DeviceName,
return Status; FILE_DEVICE_BOOTVID,
} 0,
FALSE,
BootVidDevice->Flags |= DO_BUFFERED_IO; &BootVidDevice);
return Status; return Status;
} }

View file

@ -0,0 +1,124 @@
/*
* ReactOS Boot video driver
*
* Copyright (C) 2003 Casper S. Hornstroup
* Copyright (C) 2004 Filip Navara
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Id: bootvid.h,v 1.1 2004/03/04 18:55:09 navaraf Exp $
*/
#ifndef _BOOTVID_H
#define _BOOTVID_H
#define PALETTE_FADE_STEPS 20
#define PALETTE_FADE_TIME 20 * 10000 /* 20ms */
/*
* Windows Bitmap structures
*/
#define RT_BITMAP 2
typedef struct tagRGBQUAD
{
unsigned char rgbBlue;
unsigned char rgbGreen;
unsigned char rgbRed;
unsigned char rgbReserved;
} RGBQUAD, *PRGBQUAD;
typedef long FXPT2DOT30;
typedef struct tagCIEXYZ
{
FXPT2DOT30 ciexyzX;
FXPT2DOT30 ciexyzY;
FXPT2DOT30 ciexyzZ;
} CIEXYZ, *LPCIEXYZ;
typedef struct tagCIEXYZTRIPLE
{
CIEXYZ ciexyzRed;
CIEXYZ ciexyzGreen;
CIEXYZ ciexyzBlue;
} CIEXYZTRIPLE, *LPCIEXYZTRIPLE;
typedef struct {
DWORD bV5Size;
LONG bV5Width;
LONG bV5Height;
WORD bV5Planes;
WORD bV5BitCount;
DWORD bV5Compression;
DWORD bV5SizeImage;
LONG bV5XPelsPerMeter;
LONG bV5YPelsPerMeter;
DWORD bV5ClrUsed;
DWORD bV5ClrImportant;
DWORD bV5RedMask;
DWORD bV5GreenMask;
DWORD bV5BlueMask;
DWORD bV5AlphaMask;
DWORD bV5CSType;
CIEXYZTRIPLE bV5Endpoints;
DWORD bV5GammaRed;
DWORD bV5GammaGreen;
DWORD bV5GammaBlue;
DWORD bV5Intent;
DWORD bV5ProfileData;
DWORD bV5ProfileSize;
DWORD bV5Reserved;
} BITMAPV5HEADER, *PBITMAPV5HEADER;
/*
* Private driver structures
*/
typedef struct {
ULONG r;
ULONG g;
ULONG b;
} FADER_PALETTE_ENTRY;
typedef struct _VGA_REGISTERS
{
UCHAR CRT[24];
UCHAR Attribute[21];
UCHAR Graphics[9];
UCHAR Sequencer[5];
UCHAR Misc;
} VGA_REGISTERS, *PVGA_REGISTERS;
/* VGA registers */
#define MISC (PUCHAR)0x3c2
#define SEQ (PUCHAR)0x3c4
#define SEQDATA (PUCHAR)0x3c5
#define CRTC (PUCHAR)0x3d4
#define CRTCDATA (PUCHAR)0x3d5
#define GRAPHICS (PUCHAR)0x3ce
#define GRAPHICSDATA (PUCHAR)0x3cf
#define ATTRIB (PUCHAR)0x3c0
#define STATUS (PUCHAR)0x3da
#define PELMASK (PUCHAR)0x3c6
#define PELINDEX (PUCHAR)0x3c8
#define PELDATA (PUCHAR)0x3c9
/* In pixelsups.S */
extern VOID
InbvPutPixels(int x, int y, unsigned long c);
#endif /* _BOOTVID_H */

View file

@ -1,4 +1,4 @@
/* $Id: pixelsup_i386.S,v 1.1 2003/08/24 12:11:13 dwelch Exp $ /* $Id: pixelsup_i386.S,v 1.2 2004/03/04 18:55:09 navaraf Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -52,44 +52,47 @@ _InbvPutPixels:
.nomask: .nomask:
/* Compute offset in video memory and put it in EBX /* Compute offset in video memory and put it in EBX
offset = (x >> 3) + y80[y]; */ offset = (x >> 3) + (y << 4) + (y << 6); */
movl 0xC(%ebp), %esi /* y */ movl 0xC(%ebp), %esi /* y */
movl _y80(,%esi, 4), %ebx movl %esi, %ebx
shll $0x6, %ebx
shll $0x4, %esi
addl %esi, %ebx
movl 0x8(%ebp), %eax /* x */ movl 0x8(%ebp), %eax /* x */
shrl $0x3, %eax shrl $0x3, %eax
addl %eax, %ebx addl %eax, %ebx
/* Latch first byte /* Latch first byte
(UCHAR) READ_REGISTER_UCHAR(vidmem + offset+0); */ (UCHAR) READ_REGISTER_UCHAR(VideoMemory + offset+0); */
movl (_vidmem), %esi movl (_VideoMemory), %esi
addl %ebx, %esi addl %ebx, %esi
movb 0x0(%esi), %bl movb 0x0(%esi), %bl
/* Write color index for first pixel /* Write color index for first pixel
*((PUCHAR)(vidmem + offset+0)) = (c >> 0*8) & 0xff; */ *((PUCHAR)(VideoMemory + offset+0)) = (c >> 0*8) & 0xff; */
movl 0x10(%ebp), %eax movl 0x10(%ebp), %eax
movb %al, 0x0(%esi) movb %al, 0x0(%esi)
/* Latch second byte /* Latch second byte
(UCHAR) READ_REGISTER_UCHAR(vidmem + offset+1); */ (UCHAR) READ_REGISTER_UCHAR(VideoMemory + offset+1); */
movb 0x1(%esi), %bl movb 0x1(%esi), %bl
/* Write color index for second pixel /* Write color index for second pixel
*((PUCHAR)(vidmem + offset+1)) = (c >> 1*8) & 0xff; */ *((PUCHAR)(VideoMemory + offset+1)) = (c >> 1*8) & 0xff; */
shrl $0x8, %eax shrl $0x8, %eax
movb %al, 0x1(%esi) movb %al, 0x1(%esi)
/* Latch third byte /* Latch third byte
(UCHAR) READ_REGISTER_UCHAR(vidmem + offset+2); */ (UCHAR) READ_REGISTER_UCHAR(VideoMemory + offset+2); */
movb 0x2(%esi), %bl movb 0x2(%esi), %bl
/* Write color index for third pixel /* Write color index for third pixel
*((PUCHAR)(vidmem + offset+2)) = (c >> 2*8) & 0xff; */ *((PUCHAR)(VideoMemory + offset+2)) = (c >> 2*8) & 0xff; */
shrl $0x8, %eax shrl $0x8, %eax
movb %al, 0x2(%esi) movb %al, 0x2(%esi)
/* Latch fourth byte /* Latch fourth byte
(UCHAR) READ_REGISTER_UCHAR(vidmem + offset+3); */ (UCHAR) READ_REGISTER_UCHAR(VideoMemory + offset+3); */
movb 0x3(%esi), %bl movb 0x3(%esi), %bl
/* Write color index for fourth pixel /* Write color index for fourth pixel
*((PUCHAR)(vidmem + offset+3)) = (c >> 3*8) & 0xff; */ *((PUCHAR)(VideoMemory + offset+3)) = (c >> 3*8) & 0xff; */
shrl $0x8, %eax shrl $0x8, %eax
movb %al, 0x3(%esi) movb %al, 0x3(%esi)