https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e901489574e085811ecdf…
commit e901489574e085811ecdff2097d1343d89d4f6b7
Author: Dmitry Borisov <di.sean(a)protonmail.com>
AuthorDate: Thu May 14 16:36:55 2020 +0600
Commit: Stanislav Motylkov <x86corez(a)gmail.com>
CommitDate: Fri May 15 22:28:34 2020 +0300
[BOOTVID] Add boot video driver for NEC PC-98 series (#2787)
---
drivers/base/bootvid/CMakeLists.txt | 13 +-
drivers/base/bootvid/bootvid.rc | 6 +
drivers/base/bootvid/i386/pc98/bootvid.c | 469 +++++++++++++++++++++++++++++++
drivers/base/bootvid/i386/pc98/pc98.h | 65 +++++
drivers/base/bootvid/precomp.h | 4 +
sdk/include/reactos/drivers/pc98/video.h | 273 ++++++++++++++----
6 files changed, 767 insertions(+), 63 deletions(-)
diff --git a/drivers/base/bootvid/CMakeLists.txt b/drivers/base/bootvid/CMakeLists.txt
index 10052eb2128..033a37c53ef 100644
--- a/drivers/base/bootvid/CMakeLists.txt
+++ b/drivers/base/bootvid/CMakeLists.txt
@@ -2,10 +2,15 @@
spec2def(bootvid.dll bootvid.spec ADD_IMPORTLIB)
if((ARCH STREQUAL "i386") OR (ARCH STREQUAL "amd64"))
- list(APPEND SOURCE
- i386/pc/bootvid.c
- i386/pc/bootdata.c
- i386/pc/vga.c)
+ if(SARCH STREQUAL "pc98")
+ list(APPEND SOURCE
+ i386/pc98/bootvid.c)
+ else()
+ list(APPEND SOURCE
+ i386/pc/bootvid.c
+ i386/pc/bootdata.c
+ i386/pc/vga.c)
+ endif()
elseif(ARCH STREQUAL "arm")
list(APPEND SOURCE
arm/bootvid.c)
diff --git a/drivers/base/bootvid/bootvid.rc b/drivers/base/bootvid/bootvid.rc
index 34ea5309796..18d91d14650 100644
--- a/drivers/base/bootvid/bootvid.rc
+++ b/drivers/base/bootvid/bootvid.rc
@@ -1,5 +1,11 @@
#define REACTOS_VERSION_DLL
+
+#if defined(SARCH_PC98)
+#define REACTOS_STR_FILE_DESCRIPTION "NEC PC-98 Boot Video Driver"
+#else
#define REACTOS_STR_FILE_DESCRIPTION "VGA Boot Driver"
+#endif
+
#define REACTOS_STR_INTERNAL_NAME "bootvid.dll"
#define REACTOS_STR_ORIGINAL_FILENAME "bootvid.dll"
#include <reactos/version.rc>
diff --git a/drivers/base/bootvid/i386/pc98/bootvid.c
b/drivers/base/bootvid/i386/pc98/bootvid.c
new file mode 100644
index 00000000000..e4b8b1b834b
--- /dev/null
+++ b/drivers/base/bootvid/i386/pc98/bootvid.c
@@ -0,0 +1,469 @@
+/*
+ * PROJECT: ReactOS Boot Video Driver for NEC PC-98 series
+ * LICENSE: GPL-2.0-or-later (
https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE: Main file
+ * COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean(a)protonmail.com)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include "precomp.h"
+
+/* GLOBALS ********************************************************************/
+
+static ULONG_PTR VideoMemoryI;
+ULONG_PTR FrameBuffer;
+
+#define PEGC_MAX_COLORS 256
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+static BOOLEAN
+GraphGetStatus(
+ _In_ UCHAR Status)
+{
+ UCHAR Result;
+
+ WRITE_PORT_UCHAR((PUCHAR)GRAPH_IO_o_STATUS_SELECT, Status);
+ KeStallExecutionProcessor(1);
+ Result = READ_PORT_UCHAR((PUCHAR)GRAPH_IO_i_STATUS);
+
+ return (Result & GRAPH_STATUS_SET) && (Result != 0xFF);
+}
+
+static BOOLEAN
+HasPegcController(VOID)
+{
+ BOOLEAN Success;
+
+ if (GraphGetStatus(GRAPH_STATUS_PEGC))
+ return TRUE;
+
+ WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_EGC_FF_UNPROTECT);
+ WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_MODE_PEGC_ENABLE);
+ Success = GraphGetStatus(GRAPH_STATUS_PEGC);
+ WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_MODE_PEGC_DISABLE);
+ WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_EGC_FF_PROTECT);
+
+ return Success;
+}
+
+static VOID
+TextSync(VOID)
+{
+ while (READ_PORT_UCHAR((PUCHAR)GDC1_IO_i_STATUS) & GDC_STATUS_VSYNC)
+ NOTHING;
+
+ while (!(READ_PORT_UCHAR((PUCHAR)GDC1_IO_i_STATUS) & GDC_STATUS_VSYNC))
+ NOTHING;
+}
+
+static VOID
+InitializeDisplay(VOID)
+{
+ SYNCPARAM SyncParameters;
+ CSRFORMPARAM CursorParameters;
+ CSRWPARAM CursorPosition;
+ PITCHPARAM PitchParameters;
+ PRAMPARAM RamParameters;
+ ZOOMPARAM ZoomParameters;
+ UCHAR RelayState;
+
+ /* RESET, without FIFO check */
+ WRITE_PORT_UCHAR((PUCHAR)GDC1_IO_o_COMMAND, GDC_COMMAND_RESET1);
+ WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_COMMAND, GDC_COMMAND_RESET1);
+
+ /* Configure chipset */
+ WRITE_PORT_UCHAR((PUCHAR)GDC1_IO_o_MODE_FLIPFLOP1, GRAPH_MODE_COLORED);
+ WRITE_PORT_UCHAR((PUCHAR)GDC1_IO_o_MODE_FLIPFLOP1, GDC2_MODE_ODD_RLINE_SHOW);
+ WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_MODE_COLORS_16);
+ WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_MODE_GRCG);
+ WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_MODE_LCD);
+ WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_MODE_LINES_400);
+ WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_CLOCK1_5MHZ);
+ WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_CLOCK2_5MHZ);
+ WRITE_PORT_UCHAR((PUCHAR)GRAPH_IO_o_HORIZONTAL_SCAN_RATE, GRAPH_HF_31KHZ);
+ WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_VIDEO_PAGE, 0);
+ WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_VIDEO_PAGE_ACCESS, 0);
+
+ /* =========================== MASTER ============================ */
+
+ /* MASTER */
+ WRITE_GDC1_COMMAND(GDC_COMMAND_MASTER);
+
+ /* SYNC */
+ SyncParameters.Flags = SYNC_DISPLAY_MODE_GRAPHICS_AND_CHARACTERS |
SYNC_VIDEO_FRAMING_NONINTERLACED |
+ SYNC_DRAW_ONLY_DURING_RETRACE_BLANKING |
SYNC_STATIC_RAM_NO_REFRESH;
+ SyncParameters.ScreenWidthChars = 80;
+ SyncParameters.HorizontalSyncWidth = 12;
+ SyncParameters.VerticalSyncWidth = 2;
+ SyncParameters.HorizontalFrontPorchWidth = 4;
+ SyncParameters.HorizontalBackPorchWidth = 4;
+ SyncParameters.VerticalFrontPorchWidth = 6;
+ SyncParameters.ScreenWidthLines = 480;
+ SyncParameters.VerticalBackPorchWidth = 37;
+ WRITE_GDC1_COMMAND(GDC_COMMAND_SYNC_ON);
+ WRITE_GDC_SYNC((PUCHAR)GDC1_IO_o_PARAM, &SyncParameters);
+
+ /* CSRFORM */
+ CursorParameters.Show = FALSE;
+ CursorParameters.Blink = FALSE;
+ CursorParameters.BlinkRate = 12;
+ CursorParameters.LinesPerRow = 16;
+ CursorParameters.StartScanLine = 0;
+ CursorParameters.EndScanLine = 15;
+ WRITE_GDC1_COMMAND(GDC_COMMAND_CSRFORM);
+ WRITE_GDC_CSRFORM((PUCHAR)GDC1_IO_o_PARAM, &CursorParameters);
+
+ /* PITCH */
+ PitchParameters.WordsPerScanline = BYTES_PER_SCANLINE;
+ WRITE_GDC1_COMMAND(GDC_COMMAND_PITCH);
+ WRITE_GDC_PITCH((PUCHAR)GDC1_IO_o_PARAM, &PitchParameters);
+
+ /* PRAM */
+ RamParameters.StartingAddress = 0;
+ RamParameters.Length = 1023;
+ RamParameters.ImageBit = FALSE;
+ RamParameters.WideDisplay = FALSE;
+ WRITE_GDC1_COMMAND(GDC_COMMAND_PRAM);
+ WRITE_GDC_PRAM((PUCHAR)GDC1_IO_o_PARAM, &RamParameters);
+
+ /* ZOOM */
+ ZoomParameters.DisplayZoomFactor = 0;
+ ZoomParameters.WritingZoomFactor = 0;
+ WRITE_GDC1_COMMAND(GDC_COMMAND_ZOOM);
+ WRITE_GDC_ZOOM((PUCHAR)GDC1_IO_o_PARAM, &ZoomParameters);
+
+ /* CSRW */
+ CursorPosition.CursorAddress = 0;
+ CursorPosition.DotAddress = 0;
+ WRITE_GDC1_COMMAND(GDC_COMMAND_CSRW);
+ WRITE_GDC_CSRW((PUCHAR)GDC1_IO_o_PARAM, &CursorPosition);
+
+ /* START */
+ WRITE_GDC1_COMMAND(GDC_COMMAND_BCTRL_START);
+
+ /* ============================ SLAVE ============================ */
+
+ /* SLAVE */
+ WRITE_GDC2_COMMAND(GDC_COMMAND_SLAVE);
+
+ /* SYNC */
+ SyncParameters.Flags = SYNC_DISPLAY_MODE_GRAPHICS | SYNC_VIDEO_FRAMING_NONINTERLACED
|
+ SYNC_DRAW_DURING_ACTIVE_DISPLAY_TIME_AND_RETRACE_BLANKING |
+ SYNC_STATIC_RAM_NO_REFRESH;
+ SyncParameters.ScreenWidthChars = 80;
+ SyncParameters.HorizontalSyncWidth = 12;
+ SyncParameters.VerticalSyncWidth = 2;
+ SyncParameters.HorizontalFrontPorchWidth = 4;
+ SyncParameters.HorizontalBackPorchWidth = 132;
+ SyncParameters.VerticalFrontPorchWidth = 6;
+ SyncParameters.ScreenWidthLines = 480;
+ SyncParameters.VerticalBackPorchWidth = 37;
+ WRITE_GDC2_COMMAND(GDC_COMMAND_SYNC_ON);
+ WRITE_GDC_SYNC((PUCHAR)GDC2_IO_o_PARAM, &SyncParameters);
+
+ /* CSRFORM */
+ CursorParameters.Show = FALSE;
+ CursorParameters.Blink = FALSE;
+ CursorParameters.BlinkRate = 0;
+ CursorParameters.LinesPerRow = 1;
+ CursorParameters.StartScanLine = 0;
+ CursorParameters.EndScanLine = 0;
+ WRITE_GDC2_COMMAND(GDC_COMMAND_CSRFORM);
+ WRITE_GDC_CSRFORM((PUCHAR)GDC2_IO_o_PARAM, &CursorParameters);
+
+ /* PITCH */
+ PitchParameters.WordsPerScanline = BYTES_PER_SCANLINE;
+ WRITE_GDC2_COMMAND(GDC_COMMAND_PITCH);
+ WRITE_GDC_PITCH((PUCHAR)GDC2_IO_o_PARAM, &PitchParameters);
+
+ /* PRAM */
+ RamParameters.StartingAddress = 0;
+ RamParameters.Length = 1023;
+ RamParameters.ImageBit = TRUE;
+ RamParameters.WideDisplay = FALSE;
+ WRITE_GDC2_COMMAND(GDC_COMMAND_PRAM);
+ WRITE_GDC_PRAM((PUCHAR)GDC2_IO_o_PARAM, &RamParameters);
+
+ /* ZOOM */
+ ZoomParameters.DisplayZoomFactor = 0;
+ ZoomParameters.WritingZoomFactor = 0;
+ WRITE_GDC2_COMMAND(GDC_COMMAND_ZOOM);
+ WRITE_GDC_ZOOM((PUCHAR)GDC2_IO_o_PARAM, &ZoomParameters);
+
+ /* CSRW */
+ CursorPosition.CursorAddress = 0;
+ CursorPosition.DotAddress = 0;
+ WRITE_GDC2_COMMAND(GDC_COMMAND_CSRW);
+ WRITE_GDC_CSRW((PUCHAR)GDC2_IO_o_PARAM, &CursorPosition);
+
+ /* Synchronize the master sync source */
+ TextSync();
+ TextSync();
+ TextSync();
+ TextSync();
+
+ /* START */
+ WRITE_GDC2_COMMAND(GDC_COMMAND_BCTRL_START);
+
+ /* 256 colors */
+ WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_EGC_FF_UNPROTECT);
+ WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_MODE_PEGC_ENABLE);
+ WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_MODE_LINES_800);
+ WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_EGC_FF_PROTECT);
+ WRITE_REGISTER_USHORT((PUSHORT)(VideoMemoryI + PEGC_MMIO_MODE), PEGC_MODE_PACKED);
+ WRITE_REGISTER_USHORT((PUSHORT)(VideoMemoryI + PEGC_MMIO_FRAMEBUFFER), PEGC_FB_MAP);
+
+ /* Select the video source */
+ RelayState = READ_PORT_UCHAR((PUCHAR)GRAPH_IO_i_RELAY) & ~(GRAPH_RELAY_0 |
GRAPH_RELAY_1);
+ RelayState |= GRAPH_VID_SRC_INTERNAL | GRAPH_SRC_GDC;
+ WRITE_PORT_UCHAR((PUCHAR)GRAPH_IO_o_RELAY, RelayState);
+}
+
+static VOID
+SetPaletteEntryRGB(
+ _In_ ULONG Id,
+ _In_ RGBQUAD Rgb)
+{
+ WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_PALETTE_INDEX, Id);
+ WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_RED, GetRValue(Rgb));
+ WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_GREEN, GetGValue(Rgb));
+ WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_BLUE, GetBValue(Rgb));
+}
+
+VOID
+NTAPI
+InitPaletteWithTable(
+ _In_ PULONG Table,
+ _In_ ULONG Count)
+{
+ ULONG i;
+ PULONG Entry = Table;
+
+ for (i = 0; i < Count; i++)
+ SetPaletteEntryRGB(i, *Entry++);
+
+ for (i = Count; i < PEGC_MAX_COLORS; i++)
+ SetPaletteEntryRGB(i, VidpDefaultPalette[BV_COLOR_BLACK]);
+}
+
+VOID
+NTAPI
+DisplayCharacter(
+ _In_ CHAR Character,
+ _In_ ULONG Left,
+ _In_ ULONG Top,
+ _In_ ULONG TextColor,
+ _In_ ULONG BackColor)
+{
+ ULONG X, Y, PixelMask;
+ PUCHAR FontChar = GetFontPtr(Character);
+
+ for (Y = Top;
+ Y < Top + BOOTCHAR_HEIGHT;
+ ++Y, FontChar += FONT_PTR_DELTA)
+ {
+ for (X = Left, PixelMask = 1 << (BOOTCHAR_WIDTH - 1);
+ X < Left + BOOTCHAR_WIDTH;
+ ++X, PixelMask >>= 1)
+ {
+ if (*FontChar & PixelMask)
+ SetPixel(X, Y, (UCHAR)TextColor);
+ else if (BackColor < BV_COLOR_NONE)
+ SetPixel(X, Y, (UCHAR)BackColor);
+ }
+ }
+}
+
+VOID
+NTAPI
+PreserveRow(
+ _In_ ULONG CurrentTop,
+ _In_ ULONG TopDelta,
+ _In_ BOOLEAN Restore)
+{
+ PUCHAR OldPosition, NewPosition;
+ ULONG PixelCount = TopDelta * SCREEN_WIDTH;
+
+ if (Restore)
+ {
+ /* Restore the row by copying back the contents saved off-screen */
+ OldPosition = (PUCHAR)(FrameBuffer + FB_OFFSET(0, SCREEN_HEIGHT));
+ NewPosition = (PUCHAR)(FrameBuffer + FB_OFFSET(0, CurrentTop));
+ }
+ else
+ {
+ /* Preserve the row by saving its contents off-screen */
+ OldPosition = (PUCHAR)(FrameBuffer + FB_OFFSET(0, CurrentTop));
+ NewPosition = (PUCHAR)(FrameBuffer + FB_OFFSET(0, SCREEN_HEIGHT));
+ }
+
+ while (PixelCount--)
+ WRITE_REGISTER_UCHAR(NewPosition++, READ_REGISTER_UCHAR(OldPosition++));
+}
+
+VOID
+PrepareForSetPixel(VOID)
+{
+ NOTHING;
+}
+
+VOID
+NTAPI
+DoScroll(
+ _In_ ULONG Scroll)
+{
+ USHORT i, Line;
+ PUCHAR Src, Dst;
+ PULONG SrcWide, DstWide;
+ USHORT PixelCount = (VidpScrollRegion[2] - VidpScrollRegion[0]) + 1;
+ ULONG_PTR SourceOffset = FrameBuffer + FB_OFFSET(VidpScrollRegion[0],
VidpScrollRegion[1] + Scroll);
+ ULONG_PTR DestinationOffset = FrameBuffer + FB_OFFSET(VidpScrollRegion[0],
VidpScrollRegion[1]);
+
+ for (Line = VidpScrollRegion[1]; Line <= VidpScrollRegion[3]; Line++)
+ {
+ SrcWide = (PULONG)SourceOffset;
+ DstWide = (PULONG)DestinationOffset;
+ for (i = 0; i < PixelCount / sizeof(ULONG); i++)
+ WRITE_REGISTER_ULONG(DstWide++, READ_REGISTER_ULONG(SrcWide++));
+
+ Src = (PUCHAR)SrcWide;
+ Dst = (PUCHAR)DstWide;
+ for (i = 0; i < PixelCount % sizeof(ULONG); i++)
+ WRITE_REGISTER_UCHAR(Dst++, READ_REGISTER_UCHAR(Src++));
+
+ SourceOffset += SCREEN_WIDTH;
+ DestinationOffset += SCREEN_WIDTH;
+ }
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+BOOLEAN
+NTAPI
+VidInitialize(
+ _In_ BOOLEAN SetMode)
+{
+ PHYSICAL_ADDRESS BaseAddress;
+
+ BaseAddress.QuadPart = VRAM_NORMAL_PLANE_I;
+ VideoMemoryI = (ULONG_PTR)MmMapIoSpace(BaseAddress, VRAM_PLANE_SIZE, MmNonCached);
+ if (!VideoMemoryI)
+ goto Failure;
+
+ if (!HasPegcController())
+ goto Failure;
+
+ BaseAddress.QuadPart = PEGC_FRAMEBUFFER_PACKED;
+ FrameBuffer = (ULONG_PTR)MmMapIoSpace(BaseAddress, PEGC_FRAMEBUFFER_SIZE,
MmNonCached);
+ if (!FrameBuffer)
+ goto Failure;
+
+ if (SetMode)
+ VidResetDisplay(TRUE);
+
+ return TRUE;
+
+Failure:
+ if (!VideoMemoryI) MmUnmapIoSpace((PVOID)VideoMemoryI, VRAM_PLANE_SIZE);
+ if (!FrameBuffer) MmUnmapIoSpace((PVOID)FrameBuffer, PEGC_FRAMEBUFFER_SIZE);
+
+ return FALSE;
+}
+
+VOID
+NTAPI
+VidCleanUp(VOID)
+{
+ WRITE_PORT_UCHAR((PUCHAR)GDC1_IO_o_MODE_FLIPFLOP1, GRAPH_MODE_DISPLAY_DISABLE);
+}
+
+VOID
+NTAPI
+VidResetDisplay(
+ _In_ BOOLEAN HalReset)
+{
+ PULONG PixelsPosition = (PULONG)(FrameBuffer + FB_OFFSET(0, 0));
+ ULONG PixelCount = ((SCREEN_WIDTH * SCREEN_HEIGHT) / sizeof(ULONG)) + 1;
+
+ /* Clear the current position */
+ VidpCurrentX = 0;
+ VidpCurrentY = 0;
+
+ /* Clear the screen with HAL if we were asked to */
+ if (HalReset)
+ HalResetDisplay();
+
+ WRITE_PORT_UCHAR((PUCHAR)GDC1_IO_o_MODE_FLIPFLOP1, GRAPH_MODE_DISPLAY_DISABLE);
+
+ /* 640x480 256-color 31 kHz mode */
+ InitializeDisplay();
+
+ /* Re-initialize the palette and fill the screen black */
+ InitializePalette();
+ while (PixelCount--)
+ WRITE_REGISTER_ULONG(PixelsPosition++, 0);
+
+ WRITE_PORT_UCHAR((PUCHAR)GDC1_IO_o_MODE_FLIPFLOP1, GRAPH_MODE_DISPLAY_ENABLE);
+}
+
+VOID
+NTAPI
+VidScreenToBufferBlt(
+ _Out_ PUCHAR Buffer,
+ _In_ ULONG Left,
+ _In_ ULONG Top,
+ _In_ ULONG Width,
+ _In_ ULONG Height,
+ _In_ ULONG Delta)
+{
+ ULONG X, Y;
+ PUCHAR OutputBuffer;
+ USHORT Px;
+ PUSHORT PixelsPosition = (PUSHORT)(FrameBuffer + FB_OFFSET(Left, Top));
+
+ /* Clear the destination buffer */
+ RtlZeroMemory(Buffer, Delta * Height);
+
+ for (Y = 0; Y < Height; Y++)
+ {
+ OutputBuffer = Buffer + Y * Delta;
+
+ for (X = 0; X < Width; X += 2)
+ {
+ Px = READ_REGISTER_USHORT(PixelsPosition++);
+ *OutputBuffer++ = (FIRSTBYTE(Px) << 4) | (SECONDBYTE(Px) & 0x0F);
+ }
+ }
+}
+
+VOID
+NTAPI
+VidSolidColorFill(
+ _In_ ULONG Left,
+ _In_ ULONG Top,
+ _In_ ULONG Right,
+ _In_ ULONG Bottom,
+ _In_ UCHAR Color)
+{
+ USHORT i, Line;
+ PUCHAR PixelPtr;
+ PULONG PixelsPtr;
+ ULONG WideColor = (Color << 24) | (Color << 16) | (Color << 8) |
Color;
+ USHORT PixelCount = (Right - Left) + 1;
+ ULONG_PTR StartOffset = FrameBuffer + FB_OFFSET(Left, Top);
+
+ for (Line = Top; Line <= Bottom; Line++)
+ {
+ PixelsPtr = (PULONG)StartOffset;
+ for (i = 0; i < PixelCount / sizeof(ULONG); i++)
+ WRITE_REGISTER_ULONG(PixelsPtr++, WideColor);
+
+ PixelPtr = (PUCHAR)PixelsPtr;
+ for (i = 0; i < PixelCount % sizeof(ULONG); i++)
+ WRITE_REGISTER_UCHAR(PixelPtr++, Color);
+
+ StartOffset += SCREEN_WIDTH;
+ }
+}
diff --git a/drivers/base/bootvid/i386/pc98/pc98.h
b/drivers/base/bootvid/i386/pc98/pc98.h
new file mode 100644
index 00000000000..2e84211e192
--- /dev/null
+++ b/drivers/base/bootvid/i386/pc98/pc98.h
@@ -0,0 +1,65 @@
+/*
+ * PROJECT: ReactOS Boot Video Driver for NEC PC-98 series
+ * LICENSE: GPL-2.0-or-later (
https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE: Arch-specific header file
+ * COPYRIGHT: Copyright 2020 Dmitry Borisov (di.sean(a)protonmail.com)
+ */
+
+#pragma once
+
+/* INCLUDES *******************************************************************/
+
+#include <drivers/pc98/video.h>
+
+/* GLOBALS ********************************************************************/
+
+#define BYTES_PER_SCANLINE (SCREEN_WIDTH / 8)
+#define FB_OFFSET(x, y) ((y) * SCREEN_WIDTH + (x))
+
+extern ULONG_PTR FrameBuffer;
+
+/* PROTOTYPES *****************************************************************/
+
+VOID
+NTAPI
+DisplayCharacter(
+ _In_ CHAR Character,
+ _In_ ULONG Left,
+ _In_ ULONG Top,
+ _In_ ULONG TextColor,
+ _In_ ULONG BackColor);
+
+VOID
+NTAPI
+DoScroll(
+ _In_ ULONG Scroll);
+
+VOID
+NTAPI
+InitPaletteWithTable(
+ _In_ PULONG Table,
+ _In_ ULONG Count);
+
+VOID
+NTAPI
+PreserveRow(
+ _In_ ULONG CurrentTop,
+ _In_ ULONG TopDelta,
+ _In_ BOOLEAN Restore);
+
+VOID
+PrepareForSetPixel(VOID);
+
+/* FUNCTIONS ******************************************************************/
+
+FORCEINLINE
+VOID
+SetPixel(
+ _In_ ULONG Left,
+ _In_ ULONG Top,
+ _In_ UCHAR Color)
+{
+ PUCHAR PixelPosition = (PUCHAR)(FrameBuffer + FB_OFFSET(Left, Top));
+
+ WRITE_REGISTER_UCHAR(PixelPosition, Color);
+}
diff --git a/drivers/base/bootvid/precomp.h b/drivers/base/bootvid/precomp.h
index da64ef71c86..a5a27f3ead2 100644
--- a/drivers/base/bootvid/precomp.h
+++ b/drivers/base/bootvid/precomp.h
@@ -7,8 +7,12 @@
/* Arch specific includes */
#if defined(_M_IX86) || defined(_M_AMD64)
+#if defined(SARCH_PC98)
+#include "i386/pc98/pc98.h"
+#else
#include "i386/pc/vga.h"
#include "i386/pc/pc.h"
+#endif
#elif defined(_M_ARM)
#include "arm/arm.h"
#else
diff --git a/sdk/include/reactos/drivers/pc98/video.h
b/sdk/include/reactos/drivers/pc98/video.h
index c55211d091b..35a5f704b75 100644
--- a/sdk/include/reactos/drivers/pc98/video.h
+++ b/sdk/include/reactos/drivers/pc98/video.h
@@ -9,16 +9,19 @@
/* Video memory ***************************************************************/
-#define VRAM_NORMAL_PLANE_B 0xA8000
-#define VRAM_NORMAL_PLANE_G 0xB0000
-#define VRAM_NORMAL_PLANE_R 0xB8000
-#define VRAM_NORMAL_PLANE_I 0xE0000
+#define VRAM_NORMAL_PLANE_B 0xA8000 /* Blue */
+#define VRAM_NORMAL_PLANE_G 0xB0000 /* Green */
+#define VRAM_NORMAL_PLANE_R 0xB8000 /* Red */
+#define VRAM_NORMAL_PLANE_I 0xE0000 /* Intensity */
#define VRAM_PLANE_SIZE 0x08000
#define VRAM_NORMAL_TEXT 0xA0000
#define VRAM_TEXT_ATTR_OFFSET 0x02000
#define VRAM_TEXT_SIZE 0x02000
#define VRAM_ATTR_SIZE 0x02000
+#define PEGC_FRAMEBUFFER_PACKED 0xF00000
+#define PEGC_FRAMEBUFFER_SIZE 0x080000
+
/* High-resolution machine */
#define VRAM_HI_RESO_PLANE_B 0xC0000
#define VRAM_HI_RESO_PLANE_G 0xC8000
@@ -52,39 +55,96 @@
#define GDC_ATTR_YELLOW 0xC0
#define GDC_ATTR_WHITE 0xE0
-#define GDC_COMMAND_RESET 0x00
+/* Operation type */
+#define GDC_MOD_REPLACE 0x00
+#define GDC_MOD_COMPLEMENT 0x01 /* XOR */
+#define GDC_MOD_CLEAR 0x02 /* AND */
+#define GDC_MOD_SET 0x03 /* OR */
+
+#define GDC_GRAPHICS_DRAWING 0x40
+
+#define GDC_COMMAND_RESET1 0x00
+#define GDC_COMMAND_RESET2 0x01
+#define GDC_COMMAND_STOP2 0x05
+#define GDC_COMMAND_RESET3 0x09
#define GDC_COMMAND_BCTRL_STOP 0x0C
#define GDC_COMMAND_BCTRL_START 0x0D
+
#define GDC_COMMAND_SYNC_ON 0x0E
+typedef struct _SYNCPARAM
+{
+ UCHAR Flags;
+#define SYNC_DISPLAY_MODE_GRAPHICS_AND_CHARACTERS 0x00
+#define SYNC_DISPLAY_MODE_GRAPHICS 0x02
+#define SYNC_DISPLAY_MODE_CHARACTERS 0x20
+
+#define SYNC_VIDEO_FRAMING_NONINTERLACED 0x00
+#define SYNC_VIDEO_FRAMING_INTERLACED_REPEAT_FOR_CHARACTERS 0x08
+#define SYNC_VIDEO_FRAMING_INTERLACED 0x09
+
+#define SYNC_DRAW_DURING_ACTIVE_DISPLAY_TIME_AND_RETRACE_BLANKING 0x00
+#define SYNC_DRAW_ONLY_DURING_RETRACE_BLANKING 0x10
+
+#define SYNC_STATIC_RAM_NO_REFRESH 0x00
+#define SYNC_DYNAMIC_RAM_REFRESH 0x04
+
+ UCHAR ScreenWidthChars;
+ UCHAR HorizontalSyncWidth;
+ UCHAR VerticalSyncWidth;
+ UCHAR HorizontalFrontPorchWidth;
+ UCHAR HorizontalBackPorchWidth;
+ UCHAR VerticalFrontPorchWidth;
+ USHORT ScreenWidthLines;
+ UCHAR VerticalBackPorchWidth;
+} SYNCPARAM, *PSYNCPARAM;
+
+FORCEINLINE
+VOID
+WRITE_GDC_SYNC(PUCHAR Port, PSYNCPARAM SyncParameters)
+{
+ WRITE_PORT_UCHAR(Port, SyncParameters->Flags & 0x3F);
+ WRITE_PORT_UCHAR(Port, SyncParameters->ScreenWidthChars - 2);
+ WRITE_PORT_UCHAR(Port, (SyncParameters->VerticalSyncWidth & 0x07) << 5
|
+ (SyncParameters->HorizontalSyncWidth - 1));
+ WRITE_PORT_UCHAR(Port, ((SyncParameters->HorizontalFrontPorchWidth - 1) <<
2) |
+ ((SyncParameters->VerticalSyncWidth & 0x18) >> 3));
+ WRITE_PORT_UCHAR(Port, SyncParameters->HorizontalBackPorchWidth - 1);
+ WRITE_PORT_UCHAR(Port, SyncParameters->VerticalFrontPorchWidth);
+ WRITE_PORT_UCHAR(Port, SyncParameters->ScreenWidthLines & 0xFF);
+ WRITE_PORT_UCHAR(Port, (SyncParameters->VerticalBackPorchWidth << 2) |
+ ((SyncParameters->ScreenWidthLines & 0x300) >> 8));
+}
+
#define GDC_COMMAND_SYNC_OFF 0x0F
#define GDC_COMMAND_WRITE 0x20
-#define GDC_COMMAND_SLAVE 0x6E
-#define GDC_COMMAND_MASTER 0x6F
+#define GDC_COMMAND_DMAW 0x24
-#define GDC_COMMAND_CSRFORM 0x4B
-typedef struct _CSRFORMPARAM
+#define GDC_COMMAND_ZOOM 0x46
+typedef struct _ZOOMPARAM
{
- BOOLEAN Show;
- BOOLEAN Blink;
- UCHAR BlinkRate;
- UCHAR LinesPerRow;
- UCHAR StartScanLine;
- UCHAR EndScanLine;
-} CSRFORMPARAM, *PCSRFORMPARAM;
+ UCHAR DisplayZoomFactor;
+ UCHAR WritingZoomFactor;
+} ZOOMPARAM, *PZOOMPARAM;
FORCEINLINE
VOID
-WRITE_GDC_CSRFORM(PUCHAR Port, PCSRFORMPARAM CursorParameters)
+WRITE_GDC_ZOOM(PUCHAR Port, PZOOMPARAM ZoomParameters)
{
- WRITE_PORT_UCHAR(Port, ((CursorParameters->Show & 0x01) << 7) |
- (CursorParameters->LinesPerRow - 1));
- WRITE_PORT_UCHAR(Port, ((CursorParameters->BlinkRate & 0x03) << 6) |
- ((!CursorParameters->Blink & 0x01) << 5) |
CursorParameters->StartScanLine);
- WRITE_PORT_UCHAR(Port, (CursorParameters->EndScanLine << 3) |
((CursorParameters->BlinkRate & 0x1C) >> 2));
+ WRITE_PORT_UCHAR(Port, ZoomParameters->DisplayZoomFactor << 4 |
ZoomParameters->WritingZoomFactor);
}
-#define GDC_COMMAND_START 0x6B
-#define GDC_COMMAND_ZOOM 0x46
+#define GDC_COMMAND_PITCH 0x47
+typedef struct _PITCHPARAM
+{
+ ULONG WordsPerScanline;
+} PITCHPARAM, *PPITCHPARAM;
+
+FORCEINLINE
+VOID
+WRITE_GDC_PITCH(PUCHAR Port, PPITCHPARAM PitchParameters)
+{
+ WRITE_PORT_UCHAR(Port, PitchParameters->WordsPerScanline);
+}
#define GDC_COMMAND_CSRW 0x49
typedef struct _CSRWPARAM
@@ -106,17 +166,62 @@ WRITE_GDC_CSRW(PUCHAR Port, PCSRWPARAM CursorParameters)
((CursorParameters->CursorAddress >> 16) & 0x03));
}
-#define GDC_COMMAND_PRAM 0x70
-#define GDC_COMMAND_PITCH 0x47
#define GDC_COMMAND_MASK 0x4A
+
+#define GDC_COMMAND_CSRFORM 0x4B
+typedef struct _CSRFORMPARAM
+{
+ BOOLEAN Show;
+ BOOLEAN Blink;
+ UCHAR BlinkRate;
+ UCHAR LinesPerRow;
+ UCHAR StartScanLine;
+ UCHAR EndScanLine;
+} CSRFORMPARAM, *PCSRFORMPARAM;
+
+FORCEINLINE
+VOID
+WRITE_GDC_CSRFORM(PUCHAR Port, PCSRFORMPARAM CursorParameters)
+{
+ WRITE_PORT_UCHAR(Port, ((CursorParameters->Show & 0x01) << 7) |
+ (CursorParameters->LinesPerRow - 1));
+ WRITE_PORT_UCHAR(Port, ((CursorParameters->BlinkRate & 0x03) << 6) |
+ ((!CursorParameters->Blink & 0x01) << 5) |
CursorParameters->StartScanLine);
+ WRITE_PORT_UCHAR(Port, (CursorParameters->EndScanLine << 3) |
((CursorParameters->BlinkRate & 0x1C) >> 2));
+}
+
#define GDC_COMMAND_FIGS 0x4C
-#define GDC_COMMAND_FIGD 0x6C
#define GDC_COMMAND_GCHRD 0x68
+#define GDC_COMMAND_START 0x6B
+#define GDC_COMMAND_FIGD 0x6C
+#define GDC_COMMAND_SLAVE 0x6E
+#define GDC_COMMAND_MASTER 0x6F
+
+#define GDC_COMMAND_PRAM 0x70
+typedef struct _PRAMPARAM
+{
+ ULONG StartingAddress;
+ USHORT Length;
+ BOOLEAN ImageBit;
+ BOOLEAN WideDisplay;
+} PRAMPARAM, *PPRAMPARAM;
+
+FORCEINLINE
+VOID
+WRITE_GDC_PRAM(PUCHAR Port, PPRAMPARAM RamParameters)
+{
+ WRITE_PORT_UCHAR(Port, RamParameters->StartingAddress & 0xFF);
+ WRITE_PORT_UCHAR(Port, (RamParameters->StartingAddress >> 8) & 0xFF);
+ WRITE_PORT_UCHAR(Port, ((RamParameters->Length & 0x0F) << 4) |
((RamParameters->StartingAddress >> 16) & 0x03));
+ WRITE_PORT_UCHAR(Port, ((RamParameters->WideDisplay & 0x01) << 7) |
((RamParameters->ImageBit & 0x01) << 6) |
+ ((RamParameters->Length >> 4) & 0x3F));
+}
+
+#define GDC_COMMAND_TEXTW 0x78
#define GDC_COMMAND_READ 0xA0
-#define GDC_COMMAND_CURD 0xE0
-#define GDC_COMMAND_LPRD 0xC0
#define GDC_COMMAND_DMAR 0xA4
-#define GDC_COMMAND_DMAW 0x24
+#define GDC_COMMAND_LPRD 0xC0
+#define GDC_COMMAND_CURD 0xE0
/* Master GDC *****************************************************************/
@@ -131,20 +236,20 @@ WRITE_GDC_CSRW(PUCHAR Port, PCSRWPARAM CursorParameters)
#define GDC1_IO_o_MODE_FLIPFLOP1 0x68
#define GDC1_MODE_VERTICAL_LINE 0x00 /* Character attribute */
#define GDC1_MODE_SIMPLE_GRAPHICS 0x01
- #define GDC1_MODE_COLORED 0x02
- #define GDC1_MODE_MONOCHROME 0x03
+ #define GRAPH_MODE_COLORED 0x02
+ #define GRAPH_MODE_MONOCHROME 0x03
#define GDC1_MODE_COLS_80 0x04
#define GDC1_MODE_COLS_40 0x05
#define GDC1_MODE_ANK_6_8 0x06
#define GDC1_MODE_ANK_7_13 0x07
- #define GDC1_MODE_LINES_400 0x08
- #define GDC1_MODE_LINES_200 0x09 /* Hide odd raster line */
+ #define GDC2_MODE_ODD_RLINE_SHOW 0x08
+ #define GDC2_MODE_ODD_RLINE_HIDE 0x09
#define GDC1_MODE_KCG_CODE 0x0A /* CG access during V-SYNC */
#define GDC1_MODE_KCG_BITMAP 0x0B
- #define GDC1_NVMW_PROTECT 0x0C
- #define GDC1_NVMW_UNPROTECT 0x0D /* Memory at TextVramSegment:(3FE2-3FFEh) */
- #define GDC1_MODE_DISPLAY_DISABLE 0x0E
- #define GDC1_MODE_DISPLAY_ENABLE 0x0F
+ #define GDC1_NVRAM_PROTECT 0x0C
+ #define GDC1_NVRAM_UNPROTECT 0x0D /* Memory at TextVramSegment:(3FE2-3FFEh) */
+ #define GRAPH_MODE_DISPLAY_DISABLE 0x0E
+ #define GRAPH_MODE_DISPLAY_ENABLE 0x0F
#define GDC1_IO_o_BORDER_COLOR 0x6C /* PC-H98 */
@@ -177,7 +282,7 @@ WRITE_GDC_CSRW(PUCHAR Port, PCSRWPARAM CursorParameters)
#define GDC2_MODE_EGC 0x05
#define GDC2_EGC_FF_PROTECT 0x06
#define GDC2_EGC_FF_UNPROTECT 0x07 /* Unprotect the EGC F/F registers */
- #define GDC2_MODE_PEGS_DISABLE 0x20
+ #define GDC2_MODE_PEGC_DISABLE 0x20
#define GDC2_MODE_PEGC_ENABLE 0x21
// #define GDC2_MODE_ 0x26
// #define GDC2_MODE_ 0x27
@@ -189,7 +294,7 @@ WRITE_GDC_CSRW(PUCHAR Port, PCSRWPARAM CursorParameters)
// #define GDC2_MODE_ 0x2D
#define GDC2_MODE_CRT 0x40
#define GDC2_MODE_LCD 0x41
- // #define GDC2_MODE_VRAM_PLAIN 0x62 /* PC-H98 */
+ // #define GDC2_MODE_VRAM_PLANAR 0x62 /* PC-H98 */
// #define GDC2_MODE_VRAM_PACKED 0x63
#define GDC2_MODE_LINES_400 0x68 /* 128 kB VRAM boundary */
#define GDC2_MODE_LINES_800 0x69 /* 256 kB VRAM boundary */
@@ -234,6 +339,36 @@ WRITE_GDC2_COMMAND(UCHAR Command)
WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_COMMAND, Command);
}
+/* Miscellaneous **************************************************************/
+
+#define GRAPH_IO_i_STATUS 0x9A0
+ #define GRAPH_STATUS_SET 0x01
+ #define GRAPH_GDC_CLOCK2_5MHZ 0x02
+
+#define GRAPH_IO_o_STATUS_SELECT 0x9A0
+ #define GRAPH_STATUS_GDC_CLOCK1_5MHZ 0x09
+ #define GRAPH_STATUS_PEGC 0x0A
+
+#define GRAPH_IO_i_DPMS 0x9A2
+#define GRAPH_IO_o_DPMS 0x9A2
+
+#define GRAPH_IO_i_HORIZONTAL_SCAN_RATE 0x9A8
+#define GRAPH_IO_o_HORIZONTAL_SCAN_RATE 0x9A8
+ #define GRAPH_HF_24KHZ 0x00
+ #define GRAPH_HF_31KHZ 0x01
+
+#define GRAPH_IO_i_RELAY 0xFAC
+ #define GRAPH_RELAY_0 0x01
+ #define GRAPH_RELAY_1 0x02
+
+#define GRAPH_IO_o_RELAY 0xFAC
+ /* Relay 0 */
+ #define GRAPH_VID_SRC_INTERNAL 0x00
+ #define GRAPH_VID_SRC_EXTERNAL 0x01
+ /* Relay 1 */
+ #define GRAPH_SRC_GDC 0x00
+ #define GRAPH_SRC_WAB 0x02
+
/* CRT Controller *************************************************************/
#define CRTC_IO_o_SCANLINE_START 0x70
@@ -247,25 +382,11 @@ WRITE_GDC2_COMMAND(UCHAR Command)
#define GRCG_IO_i_MODE 0x7C
#define GRCG_IO_o_MODE 0x7C
-typedef union _GRCG_MODE_REGISTER
-{
- struct
- {
- UCHAR DisablePlaneB:1;
- UCHAR DisablePlaneR:1;
- UCHAR DisablePlaneG:1;
- UCHAR DisablePlaneI:1;
- UCHAR Unused:2;
-
- UCHAR Mode:1;
-#define GRCG_MODE_TILE_DIRECT_WRITE 0
-#define GRCG_MODE_TILE_COMPARE_READ 0
-#define GRCG_MODE_READ_MODIFY_WRITE 1
-
- UCHAR Enable:1;
- };
- UCHAR Bits;
-} GRCG_MODE_REGISTER, *PGRCG_MODE_REGISTER;
+ #define GRCG_DISABLE 0x00
+ #define GRCG_ENABLE 0x80
+ #define GRCG_MODE_TILE_DIRECT_WRITE 0x80
+ #define GRCG_MODE_TILE_COMPARE_READ 0x80
+ #define GRCG_MODE_READ_MODIFY_WRITE 0xC0
#define GRCG_IO_o_TILE_PATTERN 0x7E
@@ -277,3 +398,37 @@ typedef union _GRCG_MODE_REGISTER
#define KCG_IO_o_PATTERN 0xA9
#define KCG_IO_i_PATTERN 0xA9
+
+/* EGC blitter ****************************************************************/
+
+#define EGC_IO_o_PLANE_ACCESS 0x4A0
+#define EGC_IO_o_PATTERN_DATA_PLANE_READ 0x4A2
+#define EGC_IO_o_READ_WRITE_MODE 0x4A4
+#define EGC_IO_o_FG_COLOR 0x4A6
+#define EGC_IO_o_MASK 0x4A8
+#define EGC_IO_o_BG_COLOR 0x4AA
+#define EGC_IO_o_BIT_ADDRESS 0x4AC
+#define EGC_IO_o_BIT_LENGTH 0x4AE
+
+#define PEGC_MMIO_BANK_0 0x004
+#define PEGC_MMIO_BANK_1 0x006
+
+#define PEGC_MMIO_MODE 0x100
+ #define PEGC_MODE_PACKED 0x00
+ #define PEGC_MODE_PLANAR 0x01
+
+#define PEGC_MMIO_FRAMEBUFFER 0x102
+ #define PEGC_FB_UNMAP 0x00
+ #define PEGC_FB_MAP 0x01
+ #define PEGC_FB_UNKNOWN1 0x02
+ #define PEGC_FB_UNKNOWN2 0x03
+
+#define PEGC_MMIO_PLANE_ACCESS 0x104
+#define PEGC_MMIO_ROP 0x108
+#define PEGC_MMIO_DATA_SELECT 0x10A
+#define PEGC_MMIO_MASK 0x10C
+#define PEGC_MMIO_BIT_LENGTH 0x110
+#define PEGC_MMIO_BIT_ADDRESS 0x112
+#define PEGC_MMIO_FG_COLOR 0x114
+#define PEGC_MMIO_BG_COLOR 0x118
+#define PEGC_MMIO_ROP_PATTERN 0x120