\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
0x0100,\r
QEMU_VIDEO_BOCHS,\r
L"QEMU QXL VGA"\r
+ },{\r
+ 0x1af4,\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
EFI_STATUS Status;\r
EFI_PCI_IO_PROTOCOL *PciIo;\r
PCI_TYPE00 Pci;\r
- EFI_DEV_PATH *Node;\r
QEMU_VIDEO_CARD *Card;\r
\r
//\r
}\r
\r
Status = EFI_UNSUPPORTED;\r
- //\r
- // See if the I/O enable is on. Most systems only allow one VGA device to be turned on\r
- // at a time, so see if this is one that is turned on.\r
- //\r
- // if (((Pci.Hdr.Command & 0x01) == 0x01)) {\r
- //\r
- // See if this is a Cirrus Logic PCI controller\r
- //\r
+ if (!IS_PCI_VGA (&Pci)) {\r
+ goto Done;\r
+ }\r
Card = QemuVideoDetect(Pci.Hdr.VendorId, Pci.Hdr.DeviceId);\r
if (Card != NULL) {\r
DEBUG ((EFI_D_INFO, "QemuVideo: %s detected\n", Card->Name));\r
Status = EFI_SUCCESS;\r
- //\r
- // If this is an Intel 945 graphics controller,\r
- // go further check RemainingDevicePath validation\r
- //\r
- if (RemainingDevicePath != NULL) {\r
- Node = (EFI_DEV_PATH *) RemainingDevicePath;\r
- //\r
- // Check if RemainingDevicePath is the End of Device Path Node, \r
- // if yes, return EFI_SUCCESS\r
- //\r
- if (!IsDevicePathEnd (Node)) {\r
- //\r
- // If RemainingDevicePath isn't the End of Device Path Node,\r
- // check its validation\r
- //\r
- if (Node->DevPath.Type != ACPI_DEVICE_PATH ||\r
- Node->DevPath.SubType != ACPI_ADR_DP ||\r
- DevicePathNodeLength(&Node->DevPath) != sizeof(ACPI_ADR_DEVICE_PATH)) {\r
- Status = EFI_UNSUPPORTED;\r
- }\r
- }\r
- }\r
}\r
\r
Done:\r
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
)\r
{\r
+ EFI_TPL OldTpl;\r
EFI_STATUS Status;\r
QEMU_VIDEO_PRIVATE_DATA *Private;\r
- BOOLEAN PciAttributesSaved;\r
+ BOOLEAN IsQxl;\r
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
ACPI_ADR_DEVICE_PATH AcpiDeviceNode;\r
PCI_TYPE00 Pci;\r
QEMU_VIDEO_CARD *Card;\r
- EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *MmioDesc;\r
EFI_PCI_IO_PROTOCOL *ChildPciIo;\r
\r
- PciAttributesSaved = FALSE;\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
//\r
// Allocate Private context data for GOP inteface.\r
//\r
Private = AllocateZeroPool (sizeof (QEMU_VIDEO_PRIVATE_DATA));\r
if (Private == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
- goto Error;\r
+ goto RestoreTpl;\r
}\r
\r
//\r
// Set up context record\r
//\r
Private->Signature = QEMU_VIDEO_PRIVATE_DATA_SIGNATURE;\r
- Private->Handle = NULL;\r
\r
//\r
// Open PCI I/O Protocol\r
EFI_OPEN_PROTOCOL_BY_DRIVER\r
);\r
if (EFI_ERROR (Status)) {\r
- goto Error;\r
+ goto FreePrivate;\r
}\r
\r
//\r
&Pci\r
);\r
if (EFI_ERROR (Status)) {\r
- goto Error;\r
+ goto ClosePciIo;\r
}\r
\r
+ //\r
+ // Determine card variant.\r
+ //\r
Card = QemuVideoDetect(Pci.Hdr.VendorId, Pci.Hdr.DeviceId);\r
if (Card == NULL) {\r
Status = EFI_DEVICE_ERROR;\r
- goto Error;\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
+ // not match Private->Variant.\r
+ //\r
+ IsQxl = (BOOLEAN)(Card->Variant == QEMU_VIDEO_BOCHS);\r
\r
//\r
// Save original PCI attributes\r
);\r
\r
if (EFI_ERROR (Status)) {\r
- goto Error;\r
+ goto ClosePciIo;\r
}\r
- PciAttributesSaved = TRUE;\r
\r
+ //\r
+ // Set new PCI attributes\r
+ //\r
Status = Private->PciIo->Attributes (\r
Private->PciIo,\r
EfiPciIoAttributeOperationEnable,\r
NULL\r
);\r
if (EFI_ERROR (Status)) {\r
- goto Error;\r
+ goto ClosePciIo;\r
}\r
\r
//\r
// Check whenever the qemu stdvga mmio bar is present (qemu 1.3+).\r
//\r
if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *MmioDesc;\r
+\r
Status = Private->PciIo->GetBarAttributes (\r
Private->PciIo,\r
PCI_BAR_IDX2,\r
if ((BochsId & 0xFFF0) != VBE_DISPI_ID0) {\r
DEBUG ((EFI_D_INFO, "QemuVideo: BochsID mismatch (got 0x%x)\n", BochsId));\r
Status = EFI_DEVICE_ERROR;\r
- goto Error;\r
+ goto RestoreAttributes;\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
(VOID **) &ParentDevicePath\r
);\r
if (EFI_ERROR (Status)) {\r
- goto Error;\r
+ goto RestoreAttributes;\r
}\r
\r
//\r
// Set Gop Device Path\r
//\r
- if (RemainingDevicePath == NULL) {\r
- ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));\r
- AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;\r
- AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;\r
- AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);\r
- SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));\r
-\r
- Private->GopDevicePath = AppendDevicePathNode (\r
- ParentDevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode\r
- );\r
- } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
- //\r
- // If RemainingDevicePath isn't the End of Device Path Node, \r
- // only scan the specified device by RemainingDevicePath\r
- //\r
- Private->GopDevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath);\r
- } else {\r
- //\r
- // If RemainingDevicePath is the End of Device Path Node, \r
- // don't create child device and return EFI_SUCCESS\r
- //\r
- Private->GopDevicePath = NULL;\r
+ ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));\r
+ AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;\r
+ AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;\r
+ AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);\r
+ SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));\r
+\r
+ Private->GopDevicePath = AppendDevicePathNode (\r
+ ParentDevicePath,\r
+ (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode\r
+ );\r
+ if (Private->GopDevicePath == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto RestoreAttributes;\r
}\r
- \r
- if (Private->GopDevicePath != NULL) {\r
- //\r
- // Creat child handle and device path protocol firstly\r
- //\r
- Private->Handle = NULL;\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &Private->Handle,\r
- &gEfiDevicePathProtocolGuid,\r
- Private->GopDevicePath,\r
- NULL\r
- );\r
+\r
+ //\r
+ // Create new child handle and install the device path protocol on it.\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &Private->Handle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ Private->GopDevicePath,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto FreeGopDevicePath;\r
}\r
\r
//\r
break;\r
case QEMU_VIDEO_BOCHS_MMIO:\r
case QEMU_VIDEO_BOCHS:\r
- Status = QemuVideoBochsModeSetup (Private);\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
break;\r
}\r
if (EFI_ERROR (Status)) {\r
- goto Error;\r
+ goto UninstallGopDevicePath;\r
}\r
\r
- if (Private->GopDevicePath == NULL) {\r
- //\r
- // If RemainingDevicePath is the End of Device Path Node, \r
- // don't create child device and return EFI_SUCCESS\r
- //\r
- Status = EFI_SUCCESS;\r
- } else {\r
-\r
- //\r
- // Start the GOP software stack.\r
- //\r
- Status = QemuVideoGraphicsOutputConstructor (Private);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &Private->Handle,\r
- &gEfiGraphicsOutputProtocolGuid,\r
- &Private->GraphicsOutput,\r
- NULL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
+ //\r
+ // Start the GOP software stack.\r
+ //\r
+ Status = QemuVideoGraphicsOutputConstructor (Private);\r
+ if (EFI_ERROR (Status)) {\r
+ goto FreeModeData;\r
+ }\r
\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- (VOID **) &ChildPciIo,\r
- This->DriverBindingHandle,\r
- Private->Handle,\r
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &Private->Handle,\r
+ &gEfiGraphicsOutputProtocolGuid,\r
+ &Private->GraphicsOutput,\r
+ NULL\r
);\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
+ if (EFI_ERROR (Status)) {\r
+ goto DestructQemuVideoGraphics;\r
}\r
\r
-Error:\r
+ //\r
+ // Reference parent handle from child handle.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &ChildPciIo,\r
+ This->DriverBindingHandle,\r
+ Private->Handle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
if (EFI_ERROR (Status)) {\r
- if (Private) {\r
- if (Private->PciIo) {\r
- if (PciAttributesSaved == TRUE) {\r
- //\r
- // Restore original PCI attributes\r
- //\r
- Private->PciIo->Attributes (\r
- Private->PciIo,\r
- EfiPciIoAttributeOperationSet,\r
- Private->OriginalPciAttributes,\r
- NULL\r
- );\r
- }\r
- //\r
- // Close the PCI I/O Protocol\r
- //\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Private->Handle\r
- );\r
- }\r
+ goto UninstallGop;\r
+ }\r
\r
- gBS->FreePool (Private);\r
- }\r
+#if defined MDE_CPU_IA32 || defined MDE_CPU_X64\r
+ if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||\r
+ Private->Variant == QEMU_VIDEO_BOCHS) {\r
+ InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);\r
}\r
+#endif\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+ return EFI_SUCCESS;\r
+\r
+UninstallGop:\r
+ gBS->UninstallProtocolInterface (Private->Handle,\r
+ &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput);\r
+\r
+DestructQemuVideoGraphics:\r
+ QemuVideoGraphicsOutputDestructor (Private);\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
+ &gEfiDevicePathProtocolGuid, Private->GopDevicePath);\r
+\r
+FreeGopDevicePath:\r
+ FreePool (Private->GopDevicePath);\r
+\r
+RestoreAttributes:\r
+ Private->PciIo->Attributes (Private->PciIo, EfiPciIoAttributeOperationSet,\r
+ Private->OriginalPciAttributes, NULL);\r
+\r
+ClosePciIo:\r
+ gBS->CloseProtocol (Controller, &gEfiPciIoProtocolGuid,\r
+ This->DriverBindingHandle, Controller);\r
+\r
+FreePrivate:\r
+ FreePool (Private);\r
+\r
+RestoreTpl:\r
+ gBS->RestoreTPL (OldTpl);\r
\r
return Status;\r
}\r
EFI_STATUS Status;\r
QEMU_VIDEO_PRIVATE_DATA *Private;\r
\r
+ if (NumberOfChildren == 0) {\r
+ //\r
+ // Close the PCI I/O Protocol\r
+ //\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // free all resources for whose access we need the child handle, because the\r
+ // child handle is going away\r
+ //\r
+ ASSERT (NumberOfChildren == 1);\r
Status = gBS->OpenProtocol (\r
- Controller,\r
+ ChildHandleBuffer[0],\r
&gEfiGraphicsOutputProtocolGuid,\r
(VOID **) &GraphicsOutput,\r
This->DriverBindingHandle,\r
// Get our private context information\r
//\r
Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);\r
+ ASSERT (Private->Handle == ChildHandleBuffer[0]);\r
\r
QemuVideoGraphicsOutputDestructor (Private);\r
//\r
NULL\r
);\r
\r
- //\r
- // Close the PCI I/O Protocol\r
- //\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
gBS->CloseProtocol (\r
Controller,\r
&gEfiPciIoProtocolGuid,\r
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
+\r
//\r
// Free our instance data\r
//\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