From 212aac55fd13e985cebf88042f40479c01ac2e44 Mon Sep 17 00:00:00 2001 From: jljusten Date: Tue, 27 Nov 2012 19:11:11 +0000 Subject: [PATCH] QemuVideo: prepare to support more hardware Move to a table-driven hardware detection. Add a table with PCI IDs, card name and variant enum. Use the table for hardware detection and initialization. Rename Cirrus-specific data and code to carry "cirrus" in the name. 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@13967 6f19259b-4bc3-4df7-8a09-765794883524 --- OvmfPkg/QemuVideoDxe/Driver.c | 136 ++++++++++++++++++-------- OvmfPkg/QemuVideoDxe/Gop.c | 12 ++- OvmfPkg/QemuVideoDxe/Initialize.c | 20 ++-- OvmfPkg/QemuVideoDxe/Qemu.h | 23 ++++- OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf | 6 -- 5 files changed, 133 insertions(+), 64 deletions(-) diff --git a/OvmfPkg/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c index cb3e34970d..51929803b5 100644 --- a/OvmfPkg/QemuVideoDxe/Driver.c +++ b/OvmfPkg/QemuVideoDxe/Driver.c @@ -25,6 +25,45 @@ EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding = { NULL }; +QEMU_VIDEO_CARD gQemuVideoCardList[] = { + { + CIRRUS_LOGIC_VENDOR_ID, + CIRRUS_LOGIC_5430_DEVICE_ID, + QEMU_VIDEO_CIRRUS_5430, + L"Cirrus 5430" + },{ + CIRRUS_LOGIC_VENDOR_ID, + CIRRUS_LOGIC_5430_ALTERNATE_DEVICE_ID, + QEMU_VIDEO_CIRRUS_5430, + L"Cirrus 5430" + },{ + CIRRUS_LOGIC_VENDOR_ID, + CIRRUS_LOGIC_5446_DEVICE_ID, + QEMU_VIDEO_CIRRUS_5446, + L"Cirrus 5446" + },{ + 0 /* end of list */ + } +}; + +static QEMU_VIDEO_CARD* +QemuVideoDetect( + IN UINT16 VendorId, + IN UINT16 DeviceId + ) +{ + UINTN Index = 0; + + while (gQemuVideoCardList[Index].VendorId != 0) { + if (gQemuVideoCardList[Index].VendorId == VendorId && + gQemuVideoCardList[Index].DeviceId == DeviceId) { + return gQemuVideoCardList + Index; + } + Index++; + } + return NULL; +} + /** Check if this device is supported. @@ -48,6 +87,7 @@ QemuVideoControllerDriverSupported ( EFI_PCI_IO_PROTOCOL *PciIo; PCI_TYPE00 Pci; EFI_DEV_PATH *Node; + QEMU_VIDEO_CARD *Card; // // Open the PCI I/O Protocol @@ -87,35 +127,29 @@ QemuVideoControllerDriverSupported ( // // See if this is a Cirrus Logic PCI controller // - if (Pci.Hdr.VendorId == CIRRUS_LOGIC_VENDOR_ID) { + Card = QemuVideoDetect(Pci.Hdr.VendorId, Pci.Hdr.DeviceId); + if (Card != NULL) { + DEBUG ((EFI_D_INFO, "QemuVideo: %s detected\n", Card->Name)); + Status = EFI_SUCCESS; // - // See if this is a 5430 or a 5446 PCI controller + // If this is an Intel 945 graphics controller, + // go further check RemainingDevicePath validation // - if (Pci.Hdr.DeviceId == CIRRUS_LOGIC_5430_DEVICE_ID || - Pci.Hdr.DeviceId == CIRRUS_LOGIC_5430_ALTERNATE_DEVICE_ID || - Pci.Hdr.DeviceId == CIRRUS_LOGIC_5446_DEVICE_ID) { - - Status = EFI_SUCCESS; + if (RemainingDevicePath != NULL) { + Node = (EFI_DEV_PATH *) RemainingDevicePath; // - // If this is an Intel 945 graphics controller, - // go further check RemainingDevicePath validation + // Check if RemainingDevicePath is the End of Device Path Node, + // if yes, return EFI_SUCCESS // - if (RemainingDevicePath != NULL) { - Node = (EFI_DEV_PATH *) RemainingDevicePath; + if (!IsDevicePathEnd (Node)) { // - // Check if RemainingDevicePath is the End of Device Path Node, - // if yes, return EFI_SUCCESS + // If RemainingDevicePath isn't the End of Device Path Node, + // check its validation // - if (!IsDevicePathEnd (Node)) { - // - // If RemainingDevicePath isn't the End of Device Path Node, - // check its validation - // - if (Node->DevPath.Type != ACPI_DEVICE_PATH || - Node->DevPath.SubType != ACPI_ADR_DP || - DevicePathNodeLength(&Node->DevPath) != sizeof(ACPI_ADR_DEVICE_PATH)) { - Status = EFI_UNSUPPORTED; - } + if (Node->DevPath.Type != ACPI_DEVICE_PATH || + Node->DevPath.SubType != ACPI_ADR_DP || + DevicePathNodeLength(&Node->DevPath) != sizeof(ACPI_ADR_DEVICE_PATH)) { + Status = EFI_UNSUPPORTED; } } } @@ -161,7 +195,9 @@ QemuVideoControllerDriverStart ( BOOLEAN PciAttributesSaved; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; ACPI_ADR_DEVICE_PATH AcpiDeviceNode; - + PCI_TYPE00 Pci; + QEMU_VIDEO_CARD *Card; + PciAttributesSaved = FALSE; // // Allocate Private context data for GOP inteface. @@ -193,6 +229,27 @@ QemuVideoControllerDriverStart ( goto Error; } + // + // Read the PCI Configuration Header from the PCI Device + // + Status = Private->PciIo->Pci.Read ( + Private->PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + Card = QemuVideoDetect(Pci.Hdr.VendorId, Pci.Hdr.DeviceId); + if (Card == NULL) { + Status = EFI_DEVICE_ERROR; + goto Error; + } + Private->Variant = Card->Variant; + // // Save original PCI attributes // @@ -274,7 +331,16 @@ QemuVideoControllerDriverStart ( // // Construct video mode buffer // - Status = QemuVideoVideoModeSetup (Private); + switch (Private->Variant) { + case QEMU_VIDEO_CIRRUS_5430: + case QEMU_VIDEO_CIRRUS_5446: + Status = QemuVideoCirrusModeSetup (Private); + break; + default: + ASSERT (FALSE); + Status = EFI_DEVICE_ERROR; + break; + } if (EFI_ERROR (Status)) { goto Error; } @@ -640,27 +706,13 @@ DrawLogo ( **/ VOID -InitializeGraphicsMode ( +InitializeCirrusGraphicsMode ( QEMU_VIDEO_PRIVATE_DATA *Private, - QEMU_VIDEO_VIDEO_MODES *ModeData + QEMU_VIDEO_CIRRUS_MODES *ModeData ) { UINT8 Byte; UINTN Index; - UINT16 DeviceId; - EFI_STATUS Status; - - Status = Private->PciIo->Pci.Read ( - Private->PciIo, - EfiPciIoWidthUint16, - PCI_DEVICE_ID_OFFSET, - 1, - &DeviceId - ); - // - // Read the PCI Configuration Header from the PCI Device - // - ASSERT_EFI_ERROR (Status); outw (Private, SEQ_ADDRESS_REGISTER, 0x1206); outw (Private, SEQ_ADDRESS_REGISTER, 0x0012); @@ -669,7 +721,7 @@ InitializeGraphicsMode ( outw (Private, SEQ_ADDRESS_REGISTER, ModeData->SeqSettings[Index]); } - if (DeviceId != CIRRUS_LOGIC_5446_DEVICE_ID) { + if (Private->Variant == QEMU_VIDEO_CIRRUS_5430) { outb (Private, SEQ_ADDRESS_REGISTER, 0x0f); Byte = (UINT8) ((inb (Private, SEQ_DATA_REGISTER) & 0xc7) ^ 0x30); outb (Private, SEQ_DATA_REGISTER, Byte); diff --git a/OvmfPkg/QemuVideoDxe/Gop.c b/OvmfPkg/QemuVideoDxe/Gop.c index d364630c47..bd49ee9139 100644 --- a/OvmfPkg/QemuVideoDxe/Gop.c +++ b/OvmfPkg/QemuVideoDxe/Gop.c @@ -181,7 +181,17 @@ Routine Description: return EFI_OUT_OF_RESOURCES; } - InitializeGraphicsMode (Private, &QemuVideoVideoModes[ModeData->ModeNumber]); + switch (Private->Variant) { + case QEMU_VIDEO_CIRRUS_5430: + case QEMU_VIDEO_CIRRUS_5446: + InitializeCirrusGraphicsMode (Private, &QemuVideoCirrusModes[ModeData->ModeNumber]); + break; + default: + ASSERT (FALSE); + gBS->FreePool (Private->LineBuffer); + Private->LineBuffer = NULL; + return EFI_DEVICE_ERROR; + } This->Mode->Mode = ModeNumber; This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution; diff --git a/OvmfPkg/QemuVideoDxe/Initialize.c b/OvmfPkg/QemuVideoDxe/Initialize.c index 2491733df9..a369e22988 100644 --- a/OvmfPkg/QemuVideoDxe/Initialize.c +++ b/OvmfPkg/QemuVideoDxe/Initialize.c @@ -143,7 +143,7 @@ UINT16 Seq_1024_768_32bpp_60[15] = { /// /// Table of supported video modes /// -QEMU_VIDEO_VIDEO_MODES QemuVideoVideoModes[] = { +QEMU_VIDEO_CIRRUS_MODES QemuVideoCirrusModes[] = { // { 640, 480, 8, 60, Crtc_640_480_256_60, Seq_640_480_256_60, 0xe3 }, // { 800, 600, 8, 60, Crtc_800_600_256_60, Seq_800_600_256_60, 0xef }, { 640, 480, 32, 60, Crtc_640_480_32bpp_60, Seq_640_480_32bpp_60, 0xef }, @@ -154,38 +154,38 @@ QEMU_VIDEO_VIDEO_MODES QemuVideoVideoModes[] = { // { 960, 720, 32, 60, Crtc_960_720_32bpp_60, Seq_1024_768_32bpp_60, 0xef } }; -#define QEMU_VIDEO_MODE_COUNT \ - (sizeof (QemuVideoVideoModes) / sizeof (QemuVideoVideoModes[0])) +#define QEMU_VIDEO_CIRRUS_MODE_COUNT \ + (sizeof (QemuVideoCirrusModes) / sizeof (QemuVideoCirrusModes[0])) /** Construct the valid video modes for QemuVideo. **/ EFI_STATUS -QemuVideoVideoModeSetup ( +QemuVideoCirrusModeSetup ( QEMU_VIDEO_PRIVATE_DATA *Private ) { UINT32 Index; QEMU_VIDEO_MODE_DATA *ModeData; - QEMU_VIDEO_VIDEO_MODES *VideoMode; + QEMU_VIDEO_CIRRUS_MODES *VideoMode; // // Setup Video Modes // Private->ModeData = AllocatePool ( - sizeof (Private->ModeData[0]) * QEMU_VIDEO_MODE_COUNT + sizeof (Private->ModeData[0]) * QEMU_VIDEO_CIRRUS_MODE_COUNT ); ModeData = Private->ModeData; - VideoMode = &QemuVideoVideoModes[0]; - for (Index = 0; Index < QEMU_VIDEO_MODE_COUNT; Index ++) { + VideoMode = &QemuVideoCirrusModes[0]; + for (Index = 0; Index < QEMU_VIDEO_CIRRUS_MODE_COUNT; Index ++) { ModeData->ModeNumber = Index; ModeData->HorizontalResolution = VideoMode->Width; ModeData->VerticalResolution = VideoMode->Height; ModeData->ColorDepth = VideoMode->ColorDepth; ModeData->RefreshRate = VideoMode->RefreshRate; DEBUG ((EFI_D_INFO, - "Adding Video Mode %d: %dx%d, %d-bit, %d Hz\n", + "Adding Cirrus Video Mode %d: %dx%d, %d-bit, %d Hz\n", ModeData->ModeNumber, ModeData->HorizontalResolution, ModeData->VerticalResolution, @@ -196,7 +196,7 @@ QemuVideoVideoModeSetup ( ModeData ++ ; VideoMode ++; } - Private->MaxMode = QEMU_VIDEO_MODE_COUNT; + Private->MaxMode = QEMU_VIDEO_CIRRUS_MODE_COUNT; return EFI_SUCCESS; } diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h index 1c24a58bd5..f294901fa6 100644 --- a/OvmfPkg/QemuVideoDxe/Qemu.h +++ b/OvmfPkg/QemuVideoDxe/Qemu.h @@ -86,6 +86,18 @@ typedef struct { // #define QEMU_VIDEO_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('Q', 'V', 'I', 'D') +typedef enum { + QEMU_VIDEO_CIRRUS_5430 = 1, + QEMU_VIDEO_CIRRUS_5446, +} QEMU_VIDEO_VARIANT; + +typedef struct { + UINT16 VendorId; + UINT16 DeviceId; + QEMU_VIDEO_VARIANT Variant; + CHAR16 *Name; +} QEMU_VIDEO_CARD; + typedef struct { UINT64 Signature; EFI_HANDLE Handle; @@ -98,6 +110,7 @@ typedef struct { QEMU_VIDEO_MODE_DATA *ModeData; UINT8 *LineBuffer; BOOLEAN HardwareNeedsStarting; + QEMU_VIDEO_VARIANT Variant; } QEMU_VIDEO_PRIVATE_DATA; /// @@ -111,7 +124,7 @@ typedef struct { UINT8 *CrtcSettings; UINT16 *SeqSettings; UINT8 MiscSetting; -} QEMU_VIDEO_VIDEO_MODES; +} QEMU_VIDEO_CIRRUS_MODES; #define QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS(a) \ CR(a, QEMU_VIDEO_PRIVATE_DATA, GraphicsOutput, QEMU_VIDEO_PRIVATE_DATA_SIGNATURE) @@ -128,7 +141,7 @@ extern UINT8 Crtc_800_600_256_60[]; extern UINT16 Seq_800_600_256_60[]; extern UINT8 Crtc_1024_768_256_60[]; extern UINT16 Seq_1024_768_256_60[]; -extern QEMU_VIDEO_VIDEO_MODES QemuVideoVideoModes[]; +extern QEMU_VIDEO_CIRRUS_MODES QemuVideoCirrusModes[]; extern EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding; extern EFI_COMPONENT_NAME_PROTOCOL gQemuVideoComponentName; extern EFI_COMPONENT_NAME2_PROTOCOL gQemuVideoComponentName2; @@ -358,9 +371,9 @@ QemuVideoComponentNameGetControllerName ( // Local Function Prototypes // VOID -InitializeGraphicsMode ( +InitializeCirrusGraphicsMode ( QEMU_VIDEO_PRIVATE_DATA *Private, - QEMU_VIDEO_VIDEO_MODES *ModeData + QEMU_VIDEO_CIRRUS_MODES *ModeData ); VOID @@ -411,7 +424,7 @@ inw ( ); EFI_STATUS -QemuVideoVideoModeSetup ( +QemuVideoCirrusModeSetup ( QEMU_VIDEO_PRIVATE_DATA *Private ); diff --git a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf index fde743b048..30284fcce0 100644 --- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf +++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf @@ -23,12 +23,6 @@ ENTRY_POINT = InitializeQemuVideo - PCI_VENDOR_ID = 0x1013 - PCI_DEVICE_ID = 0x00A8 - PCI_CLASS_CODE = 0x030000 - PCI_REVISION = 0x00 - PCI_COMPRESS = TRUE - # # The following information is for reference only and not required by the build tools. #