From 6c06ac0ea83f06b5f41221cd96b0717640d8bcfc Mon Sep 17 00:00:00 2001 From: Aleksandar Andrejevic Date: Tue, 21 Jul 2015 00:46:12 +0000 Subject: [PATCH] [NTVDM] Start implementing VESA BIOS Extensions (VBE) for our emulated Cirrus Logic CL-GD5434. svn path=/trunk/; revision=68508 --- .../subsystems/mvdm/ntvdm/bios/bios32/vbe.c | 189 ++++++++++++++++++ .../subsystems/mvdm/ntvdm/bios/bios32/vbe.h | 108 ++++++++++ reactos/subsystems/mvdm/ntvdm/bios/vidbios.c | 13 ++ .../mvdm/ntvdm/hardware/video/svga.h | 11 +- 4 files changed, 320 insertions(+), 1 deletion(-) create mode 100644 reactos/subsystems/mvdm/ntvdm/bios/bios32/vbe.c create mode 100644 reactos/subsystems/mvdm/ntvdm/bios/bios32/vbe.h diff --git a/reactos/subsystems/mvdm/ntvdm/bios/bios32/vbe.c b/reactos/subsystems/mvdm/ntvdm/bios/bios32/vbe.c new file mode 100644 index 00000000000..e36df383b8e --- /dev/null +++ b/reactos/subsystems/mvdm/ntvdm/bios/bios32/vbe.c @@ -0,0 +1,189 @@ +/* + * COPYRIGHT: GPLv2+ - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: vbe.c + * PURPOSE: VDM VESA BIOS Extensions (for the Cirrus CL-GD5434 emulated card) + * PROGRAMMERS: Aleksandar Andrejevic + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "ntvdm.h" +#include "emulator.h" +#include "cpu/cpu.h" + +#include "vbe.h" + +#include "io.h" + +/* PRIVATE VARIABLES **********************************************************/ + +static const VBE_MODE Modes[VBE_MODE_COUNT] = { + { 0x00, 0x00, NULL /* TODO */, NULL /* VGA */ }, + { 0x01, 0x01, NULL /* TODO */, NULL /* VGA */ }, + { 0x02, 0x02, NULL /* TODO */, NULL /* VGA */ }, + { 0x03, 0x03, NULL /* TODO */, NULL /* VGA */ }, + { 0x04, 0x04, NULL /* TODO */, NULL /* VGA */ }, + { 0x05, 0x05, NULL /* TODO */, NULL /* VGA */ }, + { 0x06, 0x06, NULL /* TODO */, NULL /* VGA */ }, + { 0x07, 0x07, NULL /* TODO */, NULL /* VGA */ }, + { 0x0D, 0x0D, NULL /* TODO */, NULL /* VGA */ }, + { 0x0E, 0x0E, NULL /* TODO */, NULL /* VGA */ }, + { 0x0F, 0x0F, NULL /* TODO */, NULL /* VGA */ }, + { 0x10, 0x10, NULL /* TODO */, NULL /* VGA */ }, + { 0x11, 0x11, NULL /* TODO */, NULL /* VGA */ }, + { 0x12, 0x12, NULL /* TODO */, NULL /* VGA */ }, + { 0x13, 0x13, NULL /* TODO */, NULL /* VGA */ }, + { 0x14, 0xFFFF, NULL /* TODO */, NULL /* TODO */ }, + { 0x54, 0x10A, NULL /* TODO */, NULL /* TODO */ }, + { 0x55, 0x109, NULL /* TODO */, NULL /* TODO */ }, + { 0x58, 0x102, NULL /* TODO */, NULL /* TODO */ }, + { 0x5C, 0x103, NULL /* TODO */, NULL /* TODO */ }, + { 0x5D, 0x104, NULL /* TODO */, NULL /* TODO */ }, + { 0x5E, 0x100, NULL /* TODO */, NULL /* TODO */ }, + { 0x5F, 0x101, NULL /* TODO */, NULL /* TODO */ }, + { 0x60, 0x105, NULL /* TODO */, NULL /* TODO */ }, + { 0x64, 0x111, NULL /* TODO */, NULL /* TODO */ }, + { 0x65, 0x114, NULL /* TODO */, NULL /* TODO */ }, + { 0x66, 0x110, NULL /* TODO */, NULL /* TODO */ }, + { 0x67, 0x113, NULL /* TODO */, NULL /* TODO */ }, + { 0x68, 0x116, NULL /* TODO */, NULL /* TODO */ }, + { 0x69, 0x119, NULL /* TODO */, NULL /* TODO */ }, + { 0x6C, 0x106, NULL /* TODO */, NULL /* TODO */ }, + { 0x6D, 0x107, NULL /* TODO */, NULL /* TODO */ }, + { 0x71, 0x112, NULL /* TODO */, NULL /* TODO */ }, + { 0x72, 0xFFFF, NULL /* TODO */, NULL /* TODO */ }, + { 0x73, 0xFFFF, NULL /* TODO */, NULL /* TODO */ }, + { 0x74, 0x117, NULL /* TODO */, NULL /* TODO */ }, + { 0x75, 0x11A, NULL /* TODO */, NULL /* TODO */ }, + { 0x76, 0xFFFF, NULL /* TODO */, NULL /* TODO */ }, + { 0x78, 0x115, NULL /* TODO */, NULL /* TODO */ }, + { 0x79, 0x118, NULL /* TODO */, NULL /* TODO */ }, +}; + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID WINAPI VbeService(LPWORD Stack) +{ + INT i; + + switch (getAL()) + { + /* Get VBE Information */ + case 0x00: + { + VBE_INFORMATION Info; + PWORD Data = (PWORD)&Info; + + /* Function recognized */ + setAL(0x4F); + + ZeroMemory(&Info, sizeof(VBE_INFORMATION)); + Info.Signature = 'ASEV'; + Info.Version = 0x0102; + Info.OemName = OEM_NAME_PTR; + Info.Capabilities = 0; + Info.ModeList = MAKELONG(LOWORD(getDI() + + FIELD_OFFSET(VBE_INFORMATION, ModeListBuffer)), + getES()); + Info.VideoMemory = HIWORD(SVGA_BANK_SIZE * VGA_NUM_BANKS); + + /* Fill the mode list */ + for (i = 0; i < VBE_MODE_COUNT; i++) + { + /* Some modes don't have VESA numbers */ + if (Modes[i].VesaNumber != 0xFFFF) + { + Info.ModeListBuffer[i] = Modes[i].VesaNumber; + } + } + + Info.ModeListBuffer[VBE_MODE_COUNT] = 0xFFFF; + + /* Copy the data to the caller */ + for (i = 0; i < sizeof(VBE_INFORMATION) / sizeof(WORD); i++) + { + *(PWORD)SEG_OFF_TO_PTR(getES(), LOWORD(getDI() + i * 2)) = Data[i]; + } + + setAH(0); + break; + } + + /* Get VBE Mode Information */ + case 0x01: + { + WORD ModeNumber = getCX() & 0x1FF; + PWORD Data = NULL; + + /* Function recognized */ + setAL(0x4F); + + /* Find the mode */ + for (i = 0; i < VBE_MODE_COUNT; i++) + { + if ((!(ModeNumber & 0x100) && (ModeNumber == Modes[i].Number)) + || ((ModeNumber & 0x100) && (ModeNumber == Modes[i].VesaNumber))) + { + Data = (PWORD)Modes[i].Info; + + if (Data == NULL) + { + DPRINT1("WARNING: The mode information for mode %02X (%03X) is missing!\n", + Modes[i].Number, + Modes[i].VesaNumber); + } + } + } + + if (Data == NULL) + { + /* Mode not found */ + setAH(1); + break; + } + + /* Clear the buffer */ + for (i = 0; i < 128; i++) + { + *(PWORD)SEG_OFF_TO_PTR(getES(), LOWORD(getDI() + i * 2)) = 0; + } + + /* Copy the data to the caller */ + for (i = 0; i < sizeof(VBE_MODE_INFO) / sizeof(WORD); i++) + { + *(PWORD)SEG_OFF_TO_PTR(getES(), LOWORD(getDI() + i * 2)) = Data[i]; + } + + setAH(0); + break; + } + + default: + { + DPRINT1("VESA BIOS Extensions function %02Xh NOT IMPLEMENTED!\n", getAL()); + break; + } + } +} + +BOOLEAN VbeInitialize(VOID) +{ + BOOLEAN Success; + BYTE SeqIndex = IOReadB(VGA_SEQ_INDEX); + + /* Store the OEM name */ + strcpy(FAR_POINTER(OEM_NAME_PTR), OEM_NAME); + + /* Unlock SVGA extensions on the card */ + IOWriteB(VGA_SEQ_INDEX, SVGA_SEQ_UNLOCK_REG); + IOWriteB(VGA_SEQ_DATA, SVGA_SEQ_UNLOCKED); + + /* Check if it worked */ + Success = IOReadB(VGA_SEQ_DATA) == SVGA_SEQ_UNLOCKED; + + IOWriteB(VGA_SEQ_INDEX, SeqIndex); + return Success; +} diff --git a/reactos/subsystems/mvdm/ntvdm/bios/bios32/vbe.h b/reactos/subsystems/mvdm/ntvdm/bios/bios32/vbe.h new file mode 100644 index 00000000000..a68e8666b6d --- /dev/null +++ b/reactos/subsystems/mvdm/ntvdm/bios/bios32/vbe.h @@ -0,0 +1,108 @@ +/* + * COPYRIGHT: GPLv2+ - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: vbe.h + * PURPOSE: VDM VESA BIOS Extensions (for the Cirrus CL-GD5434 emulated card) + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef _VBE_H_ +#define _VBE_H_ + +#include "hardware/video/svga.h" + +/* DEFINITIONS ****************************************************************/ + +#define OEM_NAME "Cirrus Logic GD-5434 VGA" +#define OEM_NAME_PTR 0xF01D5091 + +#define VBE_MODE_COUNT 40 + +/* VBE Mode Attribute Flags */ +#define VBE_MODE_SUPPORTED (1 << 0) +#define VBE_MODE_OPTIONAL_INFO (1 << 1) +#define VBE_MODE_BIOS_SUPPORT (1 << 2) +#define VBE_MODE_COLOR (1 << 3) +#define VBE_MODE_GRAPHICS (1 << 4) + +/* VBE Window Attribute Flags */ +#define VBE_WINDOW_EXISTS (1 << 0) +#define VBE_WINDOW_READABLE (1 << 1) +#define VBE_WINDOW_WRITABLE (1 << 2) + +/* VBE Memory Models */ +#define VBE_MODEL_TEXT 0 +#define VBE_MODEL_CGA 1 +#define VBE_MODEL_HGC 2 +#define VBE_MODEL_EGA 3 +#define VBE_MODEL_PACKED 4 +#define VBE_MODEL_UNCHAINED 5 +#define VBE_MODEL_DIRECT 6 +#define VBE_MODEL_YUV 7 + +#pragma pack(push, 1) + +typedef struct _VBE_INFORMATION +{ + DWORD Signature; + WORD Version; + DWORD OemName; + DWORD Capabilities; + DWORD ModeList; + WORD VideoMemory; + WORD ModeListBuffer[118]; +} VBE_INFORMATION, *PVBE_INFORMATION; + +C_ASSERT(sizeof(VBE_INFORMATION) == 256); + +typedef struct _VBE_MODE_INFO +{ + WORD Attributes; + BYTE WindowAttrA; + BYTE WindowAttrB; + WORD WindowGranularity; + WORD WindowSize; + WORD WindowSegmentA; + WORD WindowSegmentB; + DWORD WindowPosFunc; + WORD BytesPerScanline; + WORD Width; + WORD Height; + BYTE CellWidth; + BYTE CellHeight; + BYTE NumPlanes; + BYTE BitsPerPixel; + BYTE NumBanks; + BYTE MemoryModel; + BYTE BankSize; + BYTE ImagePages; + BYTE Reserved; + BYTE RedMaskSize; + BYTE RedFieldPosition; + BYTE GreenMaskSize; + BYTE GreenFieldPosition; + BYTE BlueMaskSize; + BYTE BlueFieldPosition; + BYTE ReservedMaskSize; + BYTE ReservedFieldPosition; + BYTE DirectColorInfo; +} VBE_MODE_INFO, *PVBE_MODE_INFO; + +C_ASSERT(sizeof(VBE_MODE_INFO) % sizeof(WORD) == 0); + +#pragma pack(pop) + +typedef struct _VBE_MODE +{ + BYTE Number; + WORD VesaNumber; + PVBE_MODE_INFO Info; + PSVGA_REGISTERS Registers; // NULL means "forward to VGABIOS" +} VBE_MODE, *PVBE_MODE; + +/* FUNCTIONS ******************************************************************/ + +VOID WINAPI VbeService(LPWORD Stack); +BOOLEAN VbeInitialize(VOID); + +#endif // _VBE_H_ diff --git a/reactos/subsystems/mvdm/ntvdm/bios/vidbios.c b/reactos/subsystems/mvdm/ntvdm/bios/vidbios.c index 6ea9828773d..bdce03298ae 100644 --- a/reactos/subsystems/mvdm/ntvdm/bios/vidbios.c +++ b/reactos/subsystems/mvdm/ntvdm/bios/vidbios.c @@ -18,6 +18,7 @@ #include "memory.h" #include "bios.h" +#include "bios32/vbe.h" // #include "vidbios.h" #include "io.h" @@ -1953,6 +1954,7 @@ static CONST VGA_MODE VideoModes[BIOS_MAX_VIDEO_MODE + 1] = (((ModeNumber) >= 0x00 && (ModeNumber) <= 0x03) || ((ModeNumber) == 0x07)) static PVGA_STATIC_FUNC_TABLE VgaStaticFuncTable; +static BOOLEAN VbeInitialized = FALSE; /* PRIVATE FUNCTIONS **********************************************************/ @@ -3816,6 +3818,13 @@ VOID WINAPI VidBiosVideoService(LPWORD Stack) break; } + /* VESA BIOS Extensions */ + case 0x4F: + { + if (VbeInitialized) VbeService(Stack); + break; + } + default: { DPRINT1("BIOS Function INT 10h, AH = 0x%02X, AL = 0x%02X, BH = 0x%02X NOT IMPLEMENTED\n", @@ -3909,6 +3918,10 @@ BOOLEAN VidBiosInitialize(VOID) /* Register the BIOS support BOPs */ RegisterBop(BOP_VIDEO_INT, VidBiosVideoService); + /* Initialize VBE */ + VbeInitialized = VbeInitialize(); + if (!VbeInitialized) DPRINT1("Couldn't initialize VBE!\n"); + return TRUE; } diff --git a/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.h b/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.h index 4d98bb72e24..1dd1e8701c0 100644 --- a/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.h +++ b/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.h @@ -30,7 +30,7 @@ #define SVGA_IS_UNLOCKED (VgaSeqRegisters[SVGA_SEQ_UNLOCK_REG] == SVGA_SEQ_UNLOCKED) #define SVGA_BANK_SIZE 0x100000 -#define SVGA_SEQ_MAX_UNLOCKED_REG (SVGA_IS_UNLOCKED ? SVGA_SEQ_MAX_REG : VGA_SEQ_MAX_REG) +#define SVGA_SEQ_MAX_UNLOCKED_REG (SVGA_IS_UNLOCKED ? SVGA_SEQ_MAX_REG : SVGA_SEQ_EXT_MODE_REG) #define SVGA_CRTC_MAX_UNLOCKED_REG (SVGA_IS_UNLOCKED ? SVGA_CRTC_MAX_REG : VGA_CRTC_MAX_REG) #define SVGA_GC_MAX_UNLOCKED_REG (SVGA_IS_UNLOCKED ? SVGA_GC_MAX_REG : VGA_GC_MAX_REG) @@ -358,6 +358,15 @@ typedef struct _VGA_REGISTERS UCHAR Attribute[VGA_AC_MAX_REG]; } VGA_REGISTERS, *PVGA_REGISTERS; +typedef struct _SVGA_REGISTERS +{ + UCHAR Misc; + UCHAR Hidden; + UCHAR Sequencer[SVGA_SEQ_MAX_REG]; + UCHAR CRT[SVGA_CRTC_MAX_REG]; + UCHAR Graphics[SVGA_GC_MAX_REG]; + UCHAR Attribute[VGA_AC_MAX_REG]; +} SVGA_REGISTERS, *PSVGA_REGISTERS; /* FUNCTIONS ******************************************************************/