EFI_TPL OldTpl;\r
EFI_STATUS Status;\r
QEMU_VIDEO_PRIVATE_DATA *Private;\r
+ BOOLEAN IsQxl;\r
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
ACPI_ADR_DEVICE_PATH AcpiDeviceNode;\r
PCI_TYPE00 Pci;\r
}\r
Private->Variant = Card->Variant;\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
break;\r
case QEMU_VIDEO_BOCHS_MMIO:\r
case QEMU_VIDEO_BOCHS:\r
- Status = QemuVideoBochsModeSetup (Private);\r
+ Status = QemuVideoBochsModeSetup (Private, IsQxl);\r
break;\r
default:\r
ASSERT (FALSE);\r
\r
EFI_STATUS\r
QemuVideoBochsModeSetup (\r
- QEMU_VIDEO_PRIVATE_DATA *Private\r
+ QEMU_VIDEO_PRIVATE_DATA *Private,\r
+ BOOLEAN IsQxl\r
)\r
{\r
UINT32 AvailableFbSize;\r
QEMU_VIDEO_BOCHS_MODES *VideoMode;\r
\r
//\r
- // fetch available framebuffer size\r
+ // Fetch the available framebuffer size.\r
+ //\r
+ // VBE_DISPI_INDEX_VIDEO_MEMORY_64K is expected to return the size of the\r
+ // drawable framebuffer. Up to and including qemu-2.1 however it used to\r
+ // return the size of PCI BAR 0 (ie. the full video RAM size).\r
+ //\r
+ // On stdvga the two concepts coincide with each other; the full memory size\r
+ // is usable for drawing.\r
//\r
- AvailableFbSize = BochsRead (Private, VBE_DISPI_INDEX_VIDEO_MEMORY_64K);\r
- AvailableFbSize *= SIZE_64KB;\r
+ // On QXL however, only a leading segment, "surface 0", can be used for\r
+ // drawing; the rest of the video memory is used for the QXL guest-host\r
+ // protocol. VBE_DISPI_INDEX_VIDEO_MEMORY_64K should report the size of\r
+ // "surface 0", but since it doesn't (up to and including qemu-2.1), we\r
+ // retrieve the size of the drawable portion from a field in the QXL ROM BAR,\r
+ // where it is also available.\r
+ //\r
+ if (IsQxl) {\r
+ UINT32 Signature;\r
+ UINT32 DrawStart;\r
+\r
+ Signature = 0;\r
+ DrawStart = 0xFFFFFFFF;\r
+ AvailableFbSize = 0;\r
+ if (EFI_ERROR (\r
+ Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32,\r
+ PCI_BAR_IDX2, 0, 1, &Signature)) ||\r
+ Signature != SIGNATURE_32 ('Q', 'X', 'R', 'O') ||\r
+ EFI_ERROR (\r
+ Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32,\r
+ PCI_BAR_IDX2, 36, 1, &DrawStart)) ||\r
+ DrawStart != 0 ||\r
+ EFI_ERROR (\r
+ Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32,\r
+ PCI_BAR_IDX2, 40, 1, &AvailableFbSize))) {\r
+ DEBUG ((EFI_D_ERROR, "%a: can't read size of drawable buffer from QXL "\r
+ "ROM\n", __FUNCTION__));\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ } else {\r
+ AvailableFbSize = BochsRead (Private, VBE_DISPI_INDEX_VIDEO_MEMORY_64K);\r
+ AvailableFbSize *= SIZE_64KB;\r
+ }\r
DEBUG ((EFI_D_VERBOSE, "%a: AvailableFbSize=0x%x\n", __FUNCTION__,\r
AvailableFbSize));\r
\r