Files
2026-04-21 15:08:17 -05:00

324 lines
7.8 KiB
C

/*
* PROJECT: ReactOS Boot Video Driver for ARM devices
* LICENSE: BSD - See COPYING.ARM in root directory
* PURPOSE: Main file
* COPYRIGHT: Copyright 2008 ReactOS Portable Systems Group <[email protected]>
*/
#include "precomp.h"
#define NDEBUG
#include <debug.h>
/* GLOBALS ********************************************************************/
#define LCDTIMING0_PPL(x) ((((x) / 16 - 1) & 0x3f) << 2)
#define LCDTIMING1_LPP(x) (((x) & 0x3ff) - 1)
#define LCDCONTROL_LCDPWR (1 << 11)
#define LCDCONTROL_LCDEN (1)
#define LCDCONTROL_LCDBPP(x) (((x) & 7) << 1)
#define LCDCONTROL_LCDTFT (1 << 5)
#define PL110_LCDTIMING0 (PVOID)0xE0020000
#define PL110_LCDTIMING1 (PVOID)0xE0020004
#define PL110_LCDTIMING2 (PVOID)0xE0020008
#define PL110_LCDUPBASE (PVOID)0xE0020010
#define PL110_LCDLPBASE (PVOID)0xE0020014
#define PL110_LCDCONTROL (PVOID)0xE0020018
static PUSHORT VgaArmBase;
static PHYSICAL_ADDRESS VgaPhysical;
/* PRIVATE FUNCTIONS *********************************************************/
FORCEINLINE
USHORT
VidpBuildColor(
_In_ UCHAR Color)
{
UCHAR Red, Green, Blue;
/* Extract color components */
Red = GetRValue(VidpDefaultPalette[Color]) >> 3;
Green = GetGValue(VidpDefaultPalette[Color]) >> 3;
Blue = GetBValue(VidpDefaultPalette[Color]) >> 3;
/* Build the 16-bit color mask */
return ((Red & 0x1F) << 11) | ((Green & 0x1F) << 6) | ((Blue & 0x1F));
}
FORCEINLINE
VOID
SetPixel(
_In_ ULONG Left,
_In_ ULONG Top,
_In_ UCHAR Color)
{
PUSHORT PixelPosition;
/* Calculate the pixel position */
PixelPosition = &VgaArmBase[Left + (Top * SCREEN_WIDTH)];
/* Set our color */
WRITE_REGISTER_USHORT(PixelPosition, VidpBuildColor(Color));
}
VOID
DisplayCharacter(
_In_ CHAR Character,
_In_ ULONG Left,
_In_ ULONG Top,
_In_ ULONG TextColor,
_In_ ULONG BackColor)
{
const UCHAR* FontChar;
ULONG i, j, XOffset;
/* Get the font line for this character */
FontChar = &VidpFontData[Character * BOOTCHAR_HEIGHT - Top];
/* Loop each pixel height */
for (i = BOOTCHAR_HEIGHT; i > 0; --i)
{
/* Loop each pixel width */
XOffset = Left;
for (j = (1 << 7); j > 0; j >>= 1)
{
/* Check if we should draw this pixel */
if (FontChar[Top] & (UCHAR)j)
{
/* We do, use the given Text Color */
SetPixel(XOffset, Top, (UCHAR)TextColor);
}
else if (BackColor < BV_COLOR_NONE)
{
/*
* This is a background pixel. We're drawing it
* unless it's transparent.
*/
SetPixel(XOffset, Top, (UCHAR)BackColor);
}
/* Increase X Offset */
XOffset++;
}
/* Move to the next Y ordinate */
Top++;
}
}
VOID
DoScroll(
_In_ ULONG Scroll)
{
ULONG Top, Offset;
PUSHORT SourceOffset, DestOffset;
PUSHORT i, j;
/* Set memory positions of the scroll */
SourceOffset = &VgaArmBase[(VidpScrollRegion.Top * (SCREEN_WIDTH / 8)) + (VidpScrollRegion.Left >> 3)];
DestOffset = &SourceOffset[Scroll * (SCREEN_WIDTH / 8)];
/* Start loop */
for (Top = VidpScrollRegion.Top; Top <= VidpScrollRegion.Bottom; ++Top)
{
/* Set number of bytes to loop and start offset */
Offset = VidpScrollRegion.Left >> 3;
j = SourceOffset;
/* Check if this is part of the scroll region */
if (Offset <= (VidpScrollRegion.Right >> 3))
{
/* Update position */
i = (PUSHORT)(DestOffset - SourceOffset);
/* Loop the X axis */
do
{
/* Write value in the new position so that we can do the scroll */
WRITE_REGISTER_USHORT(j, READ_REGISTER_USHORT(j + (ULONG_PTR)i));
/* Move to the next memory location to write to */
j++;
/* Move to the next byte in the region */
Offset++;
/* Make sure we don't go past the scroll region */
} while (Offset <= (VidpScrollRegion.Right >> 3));
}
/* Move to the next line */
SourceOffset += (SCREEN_WIDTH / 8);
DestOffset += (SCREEN_WIDTH / 8);
}
}
VOID
PreserveRow(
_In_ ULONG CurrentTop,
_In_ ULONG Height,
_In_ BOOLEAN Restore)
{
PUSHORT Position1, Position2;
ULONG Count;
/* Calculate the position in memory for the row */
if (Restore)
{
/* Restore the row by copying back the contents saved off-screen */
Position1 = &VgaArmBase[CurrentTop * (SCREEN_WIDTH / 8)];
Position2 = &VgaArmBase[SCREEN_HEIGHT * (SCREEN_WIDTH / 8)];
}
else
{
/* Preserve the row by saving its contents off-screen */
Position1 = &VgaArmBase[SCREEN_HEIGHT * (SCREEN_WIDTH / 8)];
Position2 = &VgaArmBase[CurrentTop * (SCREEN_WIDTH / 8)];
}
/* Set the count and loop every pixel */
Count = Height * (SCREEN_WIDTH / 8);
while (Count--)
{
/* Write the data back on the other position */
WRITE_REGISTER_USHORT(Position1, READ_REGISTER_USHORT(Position2));
/* Increase both positions */
Position1++;
Position2++;
}
}
VOID
VidpInitializeDisplay(VOID)
{
//
// Set framebuffer address
//
WRITE_REGISTER_ULONG(PL110_LCDUPBASE, VgaPhysical.LowPart);
WRITE_REGISTER_ULONG(PL110_LCDLPBASE, VgaPhysical.LowPart);
//
// Initialize timings to 640x480
//
WRITE_REGISTER_ULONG(PL110_LCDTIMING0, LCDTIMING0_PPL(SCREEN_WIDTH));
WRITE_REGISTER_ULONG(PL110_LCDTIMING1, LCDTIMING1_LPP(SCREEN_HEIGHT));
//
// Enable the LCD Display
//
WRITE_REGISTER_ULONG(PL110_LCDCONTROL,
LCDCONTROL_LCDEN |
LCDCONTROL_LCDTFT |
LCDCONTROL_LCDPWR |
LCDCONTROL_LCDBPP(4));
}
VOID
InitPaletteWithTable(
_In_reads_(Count) const ULONG* Table,
_In_ ULONG Count)
{
UNIMPLEMENTED;
}
/* PUBLIC FUNCTIONS **********************************************************/
BOOLEAN
NTAPI
VidInitialize(
_In_ BOOLEAN SetMode)
{
DPRINT1("bv-arm v0.1\n");
//
// Allocate framebuffer
// 600kb works out to 640x480@16bpp
//
VgaPhysical.QuadPart = -1;
VgaArmBase = MmAllocateContiguousMemory(600 * 1024, VgaPhysical);
if (!VgaArmBase) return FALSE;
//
// Get physical address
//
VgaPhysical = MmGetPhysicalAddress(VgaArmBase);
if (!VgaPhysical.QuadPart) return FALSE;
DPRINT1("[BV-ARM] Frame Buffer @ 0x%p 0p%p\n", VgaArmBase, VgaPhysical.LowPart);
//
// Setup the display
//
VidpInitializeDisplay();
//
// We are done!
//
return TRUE;
}
VOID
ResetDisplay(
_In_ BOOLEAN SetMode)
{
/* Re-initialize the display */
VidpInitializeDisplay();
/* Re-initialize the palette and fill the screen black */
InitializePalette();
VidSolidColorFill(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1, BV_COLOR_BLACK);
}
VOID
NTAPI
VidCleanUp(VOID)
{
UNIMPLEMENTED;
while (TRUE);
}
VOID
NTAPI
VidScreenToBufferBlt(
_Out_writes_bytes_all_(Height * Stride) PUCHAR Buffer,
_In_ ULONG Left,
_In_ ULONG Top,
_In_ ULONG Width,
_In_ ULONG Height,
_In_ ULONG Stride)
{
UNIMPLEMENTED;
while (TRUE);
}
VOID
NTAPI
VidSolidColorFill(
_In_ ULONG Left,
_In_ ULONG Top,
_In_ ULONG Right,
_In_ ULONG Bottom,
_In_ UCHAR Color)
{
int y, x;
//
// Loop along the Y-axis
//
for (y = Top; y <= Bottom; y++)
{
//
// Loop along the X-axis
//
for (x = Left; x <= Right; x++)
{
//
// Draw the pixel
//
SetPixel(x, y, Color);
}
}
}