\r
**/\r
\r
-#include "Qemu.h"\r
+#include <IndustryStandard/VmwareSvga.h>\r
#include <IndustryStandard/Acpi.h>\r
+#include "Qemu.h"\r
+#include "UnalignedIoInternal.h"\r
\r
EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding = {\r
QemuVideoControllerDriverSupported,\r
0x1050,\r
QEMU_VIDEO_BOCHS_MMIO,\r
L"QEMU VirtIO VGA"\r
+ },{\r
+ VMWARE_PCI_VENDOR_ID_VMWARE,\r
+ VMWARE_PCI_DEVICE_ID_VMWARE_SVGA2,\r
+ QEMU_VIDEO_VMWARE_SVGA,\r
+ L"QEMU VMWare SVGA"\r
},{\r
0 /* end of list */\r
}\r
goto ClosePciIo;\r
}\r
Private->Variant = Card->Variant;\r
+ Private->FrameBufferVramBarIndex = PCI_BAR_IDX0;\r
\r
//\r
// IsQxl is based on the detected Card->Variant, which at a later point might\r
}\r
}\r
\r
+ //\r
+ // Check if accessing Vmware SVGA interface works\r
+ //\r
+ if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA) {\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *IoDesc;\r
+ UINT32 TargetId;\r
+ UINT32 SvgaIdRead;\r
+\r
+ IoDesc = NULL;\r
+ Status = Private->PciIo->GetBarAttributes (\r
+ Private->PciIo,\r
+ PCI_BAR_IDX0,\r
+ NULL,\r
+ (VOID**) &IoDesc\r
+ );\r
+ if (EFI_ERROR (Status) ||\r
+ IoDesc->ResType != ACPI_ADDRESS_SPACE_TYPE_IO ||\r
+ IoDesc->AddrRangeMin > MAX_UINT16 + 1 - (VMWARE_SVGA_VALUE_PORT + 4)) {\r
+ if (IoDesc != NULL) {\r
+ FreePool (IoDesc);\r
+ }\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto RestoreAttributes;\r
+ }\r
+ Private->VmwareSvgaBasePort = (UINT16) IoDesc->AddrRangeMin;\r
+ FreePool (IoDesc);\r
+\r
+ TargetId = VMWARE_SVGA_ID_2;\r
+ while (TRUE) {\r
+ VmwareSvgaWrite (Private, VmwareSvgaRegId, TargetId);\r
+ SvgaIdRead = VmwareSvgaRead (Private, VmwareSvgaRegId);\r
+ if ((SvgaIdRead == TargetId) || (TargetId <= VMWARE_SVGA_ID_0)) {\r
+ break;\r
+ }\r
+ TargetId--;\r
+ }\r
+\r
+ if (SvgaIdRead != TargetId) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "QemuVideo: QEMU_VIDEO_VMWARE_SVGA ID mismatch "\r
+ "(got 0x%x, base address 0x%x)\n",\r
+ SvgaIdRead,\r
+ Private->VmwareSvgaBasePort\r
+ ));\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto RestoreAttributes;\r
+ }\r
+\r
+ Private->FrameBufferVramBarIndex = PCI_BAR_IDX1;\r
+ }\r
+\r
//\r
// Get ParentDevicePath\r
//\r
case QEMU_VIDEO_BOCHS:\r
Status = QemuVideoBochsModeSetup (Private, IsQxl);\r
break;\r
+ case QEMU_VIDEO_VMWARE_SVGA:\r
+ Status = QemuVideoVmwareSvgaModeSetup (Private);\r
+ break;\r
default:\r
ASSERT (FALSE);\r
Status = EFI_DEVICE_ERROR;\r
\r
FreeModeData:\r
FreePool (Private->ModeData);\r
+ if (Private->VmwareSvgaModeInfo != NULL) {\r
+ FreePool (Private->VmwareSvgaModeInfo);\r
+ }\r
\r
UninstallGopDevicePath:\r
gBS->UninstallProtocolInterface (Private->Handle,\r
);\r
\r
FreePool (Private->ModeData);\r
+ if (Private->VmwareSvgaModeInfo != NULL) {\r
+ FreePool (Private->VmwareSvgaModeInfo);\r
+ }\r
gBS->UninstallProtocolInterface (Private->Handle,\r
&gEfiDevicePathProtocolGuid, Private->GopDevicePath);\r
FreePool (Private->GopDevicePath);\r
Private->PciIo->Mem.Write (\r
Private->PciIo,\r
EfiPciIoWidthFillUint32,\r
- 0,\r
+ Private->FrameBufferVramBarIndex,\r
0,\r
0x400000 >> 2,\r
&Color\r
return Data;\r
}\r
\r
+VOID\r
+VmwareSvgaWrite (\r
+ QEMU_VIDEO_PRIVATE_DATA *Private,\r
+ UINT16 Register,\r
+ UINT32 Value\r
+ )\r
+{\r
+ UnalignedIoWrite32 (\r
+ Private->VmwareSvgaBasePort + VMWARE_SVGA_INDEX_PORT,\r
+ Register\r
+ );\r
+ UnalignedIoWrite32 (\r
+ Private->VmwareSvgaBasePort + VMWARE_SVGA_VALUE_PORT,\r
+ Value\r
+ );\r
+}\r
+\r
+UINT32\r
+VmwareSvgaRead (\r
+ QEMU_VIDEO_PRIVATE_DATA *Private,\r
+ UINT16 Register\r
+ )\r
+{\r
+ UnalignedIoWrite32 (\r
+ Private->VmwareSvgaBasePort + VMWARE_SVGA_INDEX_PORT,\r
+ Register\r
+ );\r
+ return UnalignedIoRead32 (\r
+ Private->VmwareSvgaBasePort + VMWARE_SVGA_VALUE_PORT\r
+ );\r
+}\r
+\r
VOID\r
VgaOutb (\r
QEMU_VIDEO_PRIVATE_DATA *Private,\r
ClearScreen (Private);\r
}\r
\r
+VOID\r
+InitializeVmwareSvgaGraphicsMode (\r
+ QEMU_VIDEO_PRIVATE_DATA *Private,\r
+ QEMU_VIDEO_BOCHS_MODES *ModeData\r
+ )\r
+{\r
+ UINT32 Capabilities;\r
+\r
+ VmwareSvgaWrite (Private, VmwareSvgaRegWidth, ModeData->Width);\r
+ VmwareSvgaWrite (Private, VmwareSvgaRegHeight, ModeData->Height);\r
+\r
+ Capabilities = VmwareSvgaRead (\r
+ Private,\r
+ VmwareSvgaRegCapabilities\r
+ );\r
+ if ((Capabilities & VMWARE_SVGA_CAP_8BIT_EMULATION) != 0) {\r
+ VmwareSvgaWrite (\r
+ Private,\r
+ VmwareSvgaRegBitsPerPixel,\r
+ ModeData->ColorDepth\r
+ );\r
+ }\r
+\r
+ VmwareSvgaWrite (Private, VmwareSvgaRegEnable, 1);\r
+\r
+ SetDefaultPalette (Private);\r
+ ClearScreen (Private);\r
+}\r
+\r
EFI_STATUS\r
EFIAPI\r
InitializeQemuVideo (\r
\r
**/\r
\r
+#include <IndustryStandard/VmwareSvga.h>\r
#include "Qemu.h"\r
\r
STATIC\r
return EFI_SUCCESS;\r
}\r
\r
+STATIC\r
+EFI_STATUS\r
+QemuVideoVmwareSvgaCompleteModeData (\r
+ IN QEMU_VIDEO_PRIVATE_DATA *Private,\r
+ OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *FrameBufDesc;\r
+ UINT32 BytesPerLine, FbOffset, BytesPerPixel;\r
+\r
+ Info = Mode->Info;\r
+ CopyMem (Info, &Private->VmwareSvgaModeInfo[Mode->Mode], sizeof (*Info));\r
+ BytesPerPixel = Private->ModeData[Mode->Mode].ColorDepth / 8;\r
+ BytesPerLine = Info->PixelsPerScanLine * BytesPerPixel;\r
+\r
+ FbOffset = VmwareSvgaRead (Private, VmwareSvgaRegFbOffset);\r
+\r
+ Status = Private->PciIo->GetBarAttributes (\r
+ Private->PciIo,\r
+ PCI_BAR_IDX1,\r
+ NULL,\r
+ (VOID**) &FrameBufDesc\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin + FbOffset;\r
+ Mode->FrameBufferSize = BytesPerLine * Info->VerticalResolution;\r
+\r
+ FreePool (FrameBufDesc);\r
+ return Status;\r
+}\r
+\r
\r
//\r
// Graphics Output Protocol Member Functions\r
\r
*SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
\r
- ModeData = &Private->ModeData[ModeNumber];\r
- (*Info)->HorizontalResolution = ModeData->HorizontalResolution;\r
- (*Info)->VerticalResolution = ModeData->VerticalResolution;\r
- QemuVideoCompleteModeInfo (ModeData, *Info);\r
+ if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA) {\r
+ CopyMem (*Info, &Private->VmwareSvgaModeInfo[ModeNumber], sizeof (**Info));\r
+ } else {\r
+ ModeData = &Private->ModeData[ModeNumber];\r
+ (*Info)->HorizontalResolution = ModeData->HorizontalResolution;\r
+ (*Info)->VerticalResolution = ModeData->VerticalResolution;\r
+ QemuVideoCompleteModeInfo (ModeData, *Info);\r
+ }\r
\r
return EFI_SUCCESS;\r
}\r
case QEMU_VIDEO_BOCHS:\r
InitializeBochsGraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]);\r
break;\r
+ case QEMU_VIDEO_VMWARE_SVGA:\r
+ InitializeVmwareSvgaGraphicsMode (\r
+ Private,\r
+ &QemuVideoBochsModes[ModeData->InternalModeIndex]\r
+ );\r
+ break;\r
default:\r
ASSERT (FALSE);\r
return EFI_DEVICE_ERROR;\r
This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;\r
This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
\r
- QemuVideoCompleteModeData (Private, This->Mode);\r
+ if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA) {\r
+ QemuVideoVmwareSvgaCompleteModeData (Private, This->Mode);\r
+ } else {\r
+ QemuVideoCompleteModeData (Private, This->Mode);\r
+ }\r
\r
//\r
// Re-initialize the frame buffer configure when mode changes.\r
\r
**/\r
\r
+#include <IndustryStandard/VmwareSvga.h>\r
#include "Qemu.h"\r
\r
\r
return EFI_SUCCESS;\r
}\r
\r
+EFI_STATUS\r
+QemuVideoVmwareSvgaModeSetup (\r
+ QEMU_VIDEO_PRIVATE_DATA *Private\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 FbSize;\r
+ UINT32 MaxWidth, MaxHeight;\r
+ UINT32 Capabilities;\r
+ UINT32 BitsPerPixel;\r
+ UINT32 Index;\r
+ QEMU_VIDEO_MODE_DATA *ModeData;\r
+ QEMU_VIDEO_BOCHS_MODES *VideoMode;\r
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *ModeInfo;\r
+\r
+ VmwareSvgaWrite (Private, VmwareSvgaRegEnable, 0);\r
+\r
+ Private->ModeData =\r
+ AllocatePool (sizeof (Private->ModeData[0]) * QEMU_VIDEO_BOCHS_MODE_COUNT);\r
+ if (Private->ModeData == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ModeDataAllocError;\r
+ }\r
+\r
+ Private->VmwareSvgaModeInfo =\r
+ AllocatePool (\r
+ sizeof (Private->VmwareSvgaModeInfo[0]) * QEMU_VIDEO_BOCHS_MODE_COUNT\r
+ );\r
+ if (Private->VmwareSvgaModeInfo == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ModeInfoAllocError;\r
+ }\r
+\r
+ FbSize = VmwareSvgaRead (Private, VmwareSvgaRegFbSize);\r
+ MaxWidth = VmwareSvgaRead (Private, VmwareSvgaRegMaxWidth);\r
+ MaxHeight = VmwareSvgaRead (Private, VmwareSvgaRegMaxHeight);\r
+ Capabilities = VmwareSvgaRead (Private, VmwareSvgaRegCapabilities);\r
+ if ((Capabilities & VMWARE_SVGA_CAP_8BIT_EMULATION) != 0) {\r
+ BitsPerPixel = VmwareSvgaRead (\r
+ Private,\r
+ VmwareSvgaRegHostBitsPerPixel\r
+ );\r
+ VmwareSvgaWrite (\r
+ Private,\r
+ VmwareSvgaRegBitsPerPixel,\r
+ BitsPerPixel\r
+ );\r
+ } else {\r
+ BitsPerPixel = VmwareSvgaRead (\r
+ Private,\r
+ VmwareSvgaRegBitsPerPixel\r
+ );\r
+ }\r
+\r
+ if (FbSize == 0 ||\r
+ MaxWidth == 0 ||\r
+ MaxHeight == 0 ||\r
+ BitsPerPixel == 0 ||\r
+ BitsPerPixel % 8 != 0) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Rollback;\r
+ }\r
+\r
+ ModeData = Private->ModeData;\r
+ ModeInfo = Private->VmwareSvgaModeInfo;\r
+ VideoMode = &QemuVideoBochsModes[0];\r
+ for (Index = 0; Index < QEMU_VIDEO_BOCHS_MODE_COUNT; Index++) {\r
+ UINTN RequiredFbSize;\r
+\r
+ RequiredFbSize = (UINTN) VideoMode->Width * VideoMode->Height *\r
+ (BitsPerPixel / 8);\r
+ if (RequiredFbSize <= FbSize &&\r
+ VideoMode->Width <= MaxWidth &&\r
+ VideoMode->Height <= MaxHeight) {\r
+ UINT32 BytesPerLine;\r
+ UINT32 RedMask, GreenMask, BlueMask, PixelMask;\r
+\r
+ VmwareSvgaWrite (\r
+ Private,\r
+ VmwareSvgaRegWidth,\r
+ VideoMode->Width\r
+ );\r
+ VmwareSvgaWrite (\r
+ Private,\r
+ VmwareSvgaRegHeight,\r
+ VideoMode->Height\r
+ );\r
+\r
+ ModeData->InternalModeIndex = Index;\r
+ ModeData->HorizontalResolution = VideoMode->Width;\r
+ ModeData->VerticalResolution = VideoMode->Height;\r
+ ModeData->ColorDepth = BitsPerPixel;\r
+\r
+ //\r
+ // Setting VmwareSvgaRegWidth/VmwareSvgaRegHeight actually changes\r
+ // the device's display mode, so we save all properties of each mode up\r
+ // front to avoid inadvertent mode changes later.\r
+ //\r
+ ModeInfo->Version = 0;\r
+ ModeInfo->HorizontalResolution = ModeData->HorizontalResolution;\r
+ ModeInfo->VerticalResolution = ModeData->VerticalResolution;\r
+\r
+ ModeInfo->PixelFormat = PixelBitMask;\r
+\r
+ RedMask = VmwareSvgaRead (Private, VmwareSvgaRegRedMask);\r
+ ModeInfo->PixelInformation.RedMask = RedMask;\r
+\r
+ GreenMask = VmwareSvgaRead (Private, VmwareSvgaRegGreenMask);\r
+ ModeInfo->PixelInformation.GreenMask = GreenMask;\r
+\r
+ BlueMask = VmwareSvgaRead (Private, VmwareSvgaRegBlueMask);\r
+ ModeInfo->PixelInformation.BlueMask = BlueMask;\r
+\r
+ //\r
+ // Reserved mask is whatever bits in the pixel not containing RGB data,\r
+ // so start with binary 1s for every bit in the pixel, then mask off\r
+ // bits already used for RGB. Special case 32 to avoid undefined\r
+ // behaviour in the shift.\r
+ //\r
+ if (BitsPerPixel == 32) {\r
+ if (BlueMask == 0xff && GreenMask == 0xff00 && RedMask == 0xff0000) {\r
+ ModeInfo->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;\r
+ } else if (BlueMask == 0xff0000 &&\r
+ GreenMask == 0xff00 &&\r
+ RedMask == 0xff) {\r
+ ModeInfo->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;\r
+ }\r
+ PixelMask = MAX_UINT32;\r
+ } else {\r
+ PixelMask = (1u << BitsPerPixel) - 1;\r
+ }\r
+ ModeInfo->PixelInformation.ReservedMask =\r
+ PixelMask & ~(RedMask | GreenMask | BlueMask);\r
+\r
+ BytesPerLine = VmwareSvgaRead (Private, VmwareSvgaRegBytesPerLine);\r
+ ModeInfo->PixelsPerScanLine = BytesPerLine / (BitsPerPixel / 8);\r
+\r
+ ModeData++;\r
+ ModeInfo++;\r
+ }\r
+ VideoMode++;\r
+ }\r
+ Private->MaxMode = ModeData - Private->ModeData;\r
+ return EFI_SUCCESS;\r
+\r
+Rollback:\r
+ FreePool (Private->VmwareSvgaModeInfo);\r
+ Private->VmwareSvgaModeInfo = NULL;\r
+\r
+ModeInfoAllocError:\r
+ FreePool (Private->ModeData);\r
+ Private->ModeData = NULL;\r
+\r
+ModeDataAllocError:\r
+ return Status;\r
+}\r
QEMU_VIDEO_CIRRUS_5446,\r
QEMU_VIDEO_BOCHS,\r
QEMU_VIDEO_BOCHS_MMIO,\r
+ QEMU_VIDEO_VMWARE_SVGA,\r
} QEMU_VIDEO_VARIANT;\r
\r
typedef struct {\r
//\r
UINTN MaxMode;\r
QEMU_VIDEO_MODE_DATA *ModeData;\r
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *VmwareSvgaModeInfo;\r
\r
QEMU_VIDEO_VARIANT Variant;\r
FRAME_BUFFER_CONFIGURE *FrameBufferBltConfigure;\r
UINTN FrameBufferBltConfigureSize;\r
+ UINT8 FrameBufferVramBarIndex;\r
+ UINT16 VmwareSvgaBasePort;\r
} QEMU_VIDEO_PRIVATE_DATA;\r
\r
///\r
BOOLEAN IsQxl\r
);\r
\r
+EFI_STATUS\r
+QemuVideoVmwareSvgaModeSetup (\r
+ QEMU_VIDEO_PRIVATE_DATA *Private\r
+ );\r
+\r
VOID\r
InstallVbeShim (\r
IN CONST CHAR16 *CardName,\r
IN EFI_PHYSICAL_ADDRESS FrameBufferBase\r
);\r
+\r
+VOID\r
+VmwareSvgaWrite (\r
+ QEMU_VIDEO_PRIVATE_DATA *Private,\r
+ UINT16 Register,\r
+ UINT32 Value\r
+ );\r
+\r
+UINT32\r
+VmwareSvgaRead (\r
+ QEMU_VIDEO_PRIVATE_DATA *Private,\r
+ UINT16 Register\r
+ );\r
+\r
+VOID\r
+InitializeVmwareSvgaGraphicsMode (\r
+ QEMU_VIDEO_PRIVATE_DATA *Private,\r
+ QEMU_VIDEO_BOCHS_MODES *ModeData\r
+ );\r
+\r
#endif\r