From 54f9b9accbcb6dc7f965342fc75b478464de21a3 Mon Sep 17 00:00:00 2001 From: jljusten Date: Tue, 27 Nov 2012 19:11:29 +0000 Subject: [PATCH] QemuVideo: Add support for the bochs dispi interface Add code to handle qemu-emulated vga cards supporting the bochs dispi interface (standard vga, qxl vga). This requires qemu 1.3+ which provides the bochs dispi interface data register on a aligned io address. See http://git.qemu.org/?p=qemu.git;a=commitdiff;h=df9ffb726ff13f850b8829be1bc85ed621b903ac Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Gerd Hoffmann Reviewed-by: Laszlo Ersek Reviewed-by: Jordan Justen git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13968 6f19259b-4bc3-4df7-8a09-765794883524 --- OvmfPkg/QemuVideoDxe/Driver.c | 82 ++++++++++++++++++++++++++++++- OvmfPkg/QemuVideoDxe/Gop.c | 3 ++ OvmfPkg/QemuVideoDxe/Initialize.c | 52 ++++++++++++++++++++ OvmfPkg/QemuVideoDxe/Qemu.h | 60 ++++++++++++++++++++++ 4 files changed, 196 insertions(+), 1 deletion(-) diff --git a/OvmfPkg/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c index 51929803b5..04f73f3ba1 100644 --- a/OvmfPkg/QemuVideoDxe/Driver.c +++ b/OvmfPkg/QemuVideoDxe/Driver.c @@ -41,6 +41,16 @@ QEMU_VIDEO_CARD gQemuVideoCardList[] = { CIRRUS_LOGIC_5446_DEVICE_ID, QEMU_VIDEO_CIRRUS_5446, L"Cirrus 5446" + },{ + 0x1234, + 0x1111, + QEMU_VIDEO_BOCHS, + L"QEMU Standard VGA" + },{ + 0x1b36, + 0x0100, + QEMU_VIDEO_BOCHS, + L"QEMU QXL VGA" },{ 0 /* end of list */ } @@ -197,7 +207,7 @@ QemuVideoControllerDriverStart ( ACPI_ADR_DEVICE_PATH AcpiDeviceNode; PCI_TYPE00 Pci; QEMU_VIDEO_CARD *Card; - + PciAttributesSaved = FALSE; // // Allocate Private context data for GOP inteface. @@ -275,6 +285,19 @@ QemuVideoControllerDriverStart ( goto Error; } + // + // Check if accessing the bochs interface works. + // + if (Private->Variant == QEMU_VIDEO_BOCHS) { + UINT16 BochsId; + BochsId = BochsRead(Private, VBE_DISPI_INDEX_ID); + if ((BochsId & 0xFFF0) != VBE_DISPI_ID0) { + DEBUG ((EFI_D_INFO, "QemuVideo: BochsID mismatch (got 0x%x)\n", BochsId)); + Status = EFI_DEVICE_ERROR; + goto Error; + } + } + // // Get ParentDevicePath // @@ -336,6 +359,9 @@ QemuVideoControllerDriverStart ( case QEMU_VIDEO_CIRRUS_5446: Status = QemuVideoCirrusModeSetup (Private); break; + case QEMU_VIDEO_BOCHS: + Status = QemuVideoBochsModeSetup (Private); + break; default: ASSERT (FALSE); Status = EFI_DEVICE_ERROR; @@ -758,6 +784,60 @@ InitializeCirrusGraphicsMode ( ClearScreen (Private); } +VOID +BochsWrite ( + QEMU_VIDEO_PRIVATE_DATA *Private, + UINT16 Reg, + UINT16 Data + ) +{ + outw (Private, VBE_DISPI_IOPORT_INDEX, Reg); + outw (Private, VBE_DISPI_IOPORT_DATA, Data); +} + +UINT16 +BochsRead ( + QEMU_VIDEO_PRIVATE_DATA *Private, + UINT16 Reg + ) +{ + UINT16 Data; + + outw (Private, VBE_DISPI_IOPORT_INDEX, Reg); + Data = inw (Private, VBE_DISPI_IOPORT_DATA); + return Data; +} + +VOID +InitializeBochsGraphicsMode ( + QEMU_VIDEO_PRIVATE_DATA *Private, + QEMU_VIDEO_BOCHS_MODES *ModeData + ) +{ + DEBUG ((EFI_D_INFO, "InitializeBochsGraphicsMode: %dx%d @ %d\n", + ModeData->Width, ModeData->Height, ModeData->ColorDepth)); + + /* unblank */ + outb (Private, ATT_ADDRESS_REGISTER, 0x20); + + BochsWrite (Private, VBE_DISPI_INDEX_ENABLE, 0); + BochsWrite (Private, VBE_DISPI_INDEX_BANK, 0); + BochsWrite (Private, VBE_DISPI_INDEX_X_OFFSET, 0); + BochsWrite (Private, VBE_DISPI_INDEX_Y_OFFSET, 0); + + BochsWrite (Private, VBE_DISPI_INDEX_BPP, (UINT16) ModeData->ColorDepth); + BochsWrite (Private, VBE_DISPI_INDEX_XRES, (UINT16) ModeData->Width); + BochsWrite (Private, VBE_DISPI_INDEX_VIRT_WIDTH, (UINT16) ModeData->Width); + BochsWrite (Private, VBE_DISPI_INDEX_YRES, (UINT16) ModeData->Height); + BochsWrite (Private, VBE_DISPI_INDEX_VIRT_HEIGHT, (UINT16) ModeData->Height); + + BochsWrite (Private, VBE_DISPI_INDEX_ENABLE, + VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED); + + SetDefaultPalette (Private); + ClearScreen (Private); +} + EFI_STATUS EFIAPI InitializeQemuVideo ( diff --git a/OvmfPkg/QemuVideoDxe/Gop.c b/OvmfPkg/QemuVideoDxe/Gop.c index bd49ee9139..f6e9b6c14f 100644 --- a/OvmfPkg/QemuVideoDxe/Gop.c +++ b/OvmfPkg/QemuVideoDxe/Gop.c @@ -186,6 +186,9 @@ Routine Description: case QEMU_VIDEO_CIRRUS_5446: InitializeCirrusGraphicsMode (Private, &QemuVideoCirrusModes[ModeData->ModeNumber]); break; + case QEMU_VIDEO_BOCHS: + InitializeBochsGraphicsMode (Private, &QemuVideoBochsModes[ModeData->ModeNumber]); + break; default: ASSERT (FALSE); gBS->FreePool (Private->LineBuffer); diff --git a/OvmfPkg/QemuVideoDxe/Initialize.c b/OvmfPkg/QemuVideoDxe/Initialize.c index a369e22988..305797bd50 100644 --- a/OvmfPkg/QemuVideoDxe/Initialize.c +++ b/OvmfPkg/QemuVideoDxe/Initialize.c @@ -201,3 +201,55 @@ QemuVideoCirrusModeSetup ( return EFI_SUCCESS; } +/// +/// Table of supported video modes +/// +QEMU_VIDEO_BOCHS_MODES QemuVideoBochsModes[] = { + { 640, 480, 32 }, + { 800, 600, 32 }, + { 1024, 768, 24 }, +}; + +#define QEMU_VIDEO_BOCHS_MODE_COUNT \ + (sizeof (QemuVideoBochsModes) / sizeof (QemuVideoBochsModes[0])) + +EFI_STATUS +QemuVideoBochsModeSetup ( + QEMU_VIDEO_PRIVATE_DATA *Private + ) +{ + UINT32 Index; + QEMU_VIDEO_MODE_DATA *ModeData; + QEMU_VIDEO_BOCHS_MODES *VideoMode; + + // + // Setup Video Modes + // + Private->ModeData = AllocatePool ( + sizeof (Private->ModeData[0]) * QEMU_VIDEO_BOCHS_MODE_COUNT + ); + ModeData = Private->ModeData; + VideoMode = &QemuVideoBochsModes[0]; + for (Index = 0; Index < QEMU_VIDEO_BOCHS_MODE_COUNT; Index ++) { + ModeData->ModeNumber = Index; + ModeData->HorizontalResolution = VideoMode->Width; + ModeData->VerticalResolution = VideoMode->Height; + ModeData->ColorDepth = VideoMode->ColorDepth; + ModeData->RefreshRate = 60; + DEBUG ((EFI_D_INFO, + "Adding Bochs Video Mode %d: %dx%d, %d-bit, %d Hz\n", + ModeData->ModeNumber, + ModeData->HorizontalResolution, + ModeData->VerticalResolution, + ModeData->ColorDepth, + ModeData->RefreshRate + )); + + ModeData ++ ; + VideoMode ++; + } + Private->MaxMode = QEMU_VIDEO_BOCHS_MODE_COUNT; + + return EFI_SUCCESS; +} + diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h index f294901fa6..343fd347b6 100644 --- a/OvmfPkg/QemuVideoDxe/Qemu.h +++ b/OvmfPkg/QemuVideoDxe/Qemu.h @@ -89,6 +89,7 @@ typedef struct { typedef enum { QEMU_VIDEO_CIRRUS_5430 = 1, QEMU_VIDEO_CIRRUS_5446, + QEMU_VIDEO_BOCHS, } QEMU_VIDEO_VARIANT; typedef struct { @@ -126,6 +127,12 @@ typedef struct { UINT8 MiscSetting; } QEMU_VIDEO_CIRRUS_MODES; +typedef struct { + UINT32 Width; + UINT32 Height; + UINT32 ColorDepth; +} QEMU_VIDEO_BOCHS_MODES; + #define QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS(a) \ CR(a, QEMU_VIDEO_PRIVATE_DATA, GraphicsOutput, QEMU_VIDEO_PRIVATE_DATA_SIGNATURE) @@ -142,6 +149,7 @@ extern UINT16 Seq_800_600_256_60[]; extern UINT8 Crtc_1024_768_256_60[]; extern UINT16 Seq_1024_768_256_60[]; extern QEMU_VIDEO_CIRRUS_MODES QemuVideoCirrusModes[]; +extern QEMU_VIDEO_BOCHS_MODES QemuVideoBochsModes[]; extern EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding; extern EFI_COMPONENT_NAME_PROTOCOL gQemuVideoComponentName; extern EFI_COMPONENT_NAME2_PROTOCOL gQemuVideoComponentName2; @@ -163,6 +171,34 @@ extern EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL gQemuVideoDriverSupportedEfiVe #define PALETTE_INDEX_REGISTER 0x3c8 #define PALETTE_DATA_REGISTER 0x3c9 +#define VBE_DISPI_IOPORT_INDEX 0x01CE +#define VBE_DISPI_IOPORT_DATA 0x01D0 + +#define VBE_DISPI_INDEX_ID 0x0 +#define VBE_DISPI_INDEX_XRES 0x1 +#define VBE_DISPI_INDEX_YRES 0x2 +#define VBE_DISPI_INDEX_BPP 0x3 +#define VBE_DISPI_INDEX_ENABLE 0x4 +#define VBE_DISPI_INDEX_BANK 0x5 +#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 +#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 +#define VBE_DISPI_INDEX_X_OFFSET 0x8 +#define VBE_DISPI_INDEX_Y_OFFSET 0x9 +#define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa + +#define VBE_DISPI_ID0 0xB0C0 +#define VBE_DISPI_ID1 0xB0C1 +#define VBE_DISPI_ID2 0xB0C2 +#define VBE_DISPI_ID3 0xB0C3 +#define VBE_DISPI_ID4 0xB0C4 +#define VBE_DISPI_ID5 0xB0C5 + +#define VBE_DISPI_DISABLED 0x00 +#define VBE_DISPI_ENABLED 0x01 +#define VBE_DISPI_GETCAPS 0x02 +#define VBE_DISPI_8BIT_DAC 0x20 +#define VBE_DISPI_LFB_ENABLED 0x40 +#define VBE_DISPI_NOCLEARMEM 0x80 // // Graphics Output Hardware abstraction internal worker functions @@ -376,6 +412,12 @@ InitializeCirrusGraphicsMode ( QEMU_VIDEO_CIRRUS_MODES *ModeData ); +VOID +InitializeBochsGraphicsMode ( + QEMU_VIDEO_PRIVATE_DATA *Private, + QEMU_VIDEO_BOCHS_MODES *ModeData + ); + VOID SetPaletteColor ( QEMU_VIDEO_PRIVATE_DATA *Private, @@ -423,9 +465,27 @@ inw ( UINTN Address ); +VOID +BochsWrite ( + QEMU_VIDEO_PRIVATE_DATA *Private, + UINT16 Reg, + UINT16 Data + ); + +UINT16 +BochsRead ( + QEMU_VIDEO_PRIVATE_DATA *Private, + UINT16 Reg + ); + EFI_STATUS QemuVideoCirrusModeSetup ( QEMU_VIDEO_PRIVATE_DATA *Private ); +EFI_STATUS +QemuVideoBochsModeSetup ( + QEMU_VIDEO_PRIVATE_DATA *Private + ); + #endif -- 2.39.2