From 2e70cf8ade0dd1e023274f7358c7c72cfd17460c Mon Sep 17 00:00:00 2001 From: Gabriel Somlo Date: Fri, 14 Nov 2014 00:39:04 +0000 Subject: OvmfPkg: PlatformBdsLib: Platform dependent PCI/IRQ initialization Merge PciInitialization() and AcpiInitialization() into a single function, PciAcpiInitialization(), and use a PCD set during PEI to detect the underlying platform type (PIIX4 or Q35/MCH) and therefore the addresses of the registers to be initialized. Add LNK[A-H] routing target initialization for the Q35 platform. Additionally, initialize PCI_INTERRUPT_LINE registers for the typical set of PCI devices included by QEMU with the Q35 machine type. The corresponding PIIX4 initialization of PCI_INTERRUPT_LINE registers is cleaned up and the list of PIIX4 PCI devices updated to the list typically included with QEMU. NOTE: The list of PCI devices for which we initialize PCI_INTERRUPT_LINE is hard-coded, and, depending on how QEMU devices are configured on the command line, may miss some devices, or (harmlessly) attempt to initialize devices which are not present in the system. A subsequent patch will replace this hard-coded list with a mechanism to correctly initialize PCI_INTERRUPT_LINE for applicable present PCI devices only. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Gabriel Somlo Reviewed-by: Paolo Bonzini Reviewed-by: Jordan Justen Reviewed-by: Gerd Hoffmann git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16379 6f19259b-4bc3-4df7-8a09-765794883524 --- OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c | 122 +++++++++++++--------- OvmfPkg/Library/PlatformBdsLib/BdsPlatform.h | 2 + OvmfPkg/Library/PlatformBdsLib/PlatformBdsLib.inf | 1 + 3 files changed, 78 insertions(+), 47 deletions(-) diff --git a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c index 4b76c6e890..6fc5a89780 100644 --- a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c +++ b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c @@ -717,63 +717,92 @@ Returns: VOID -PciInitialization ( +PciAcpiInitialization ( ) { - // - // Bus 0, Device 0, Function 0 - Host to PCI Bridge - // - PciWrite8 (PCI_LIB_ADDRESS (0, 0, 0, 0x3c), 0x00); - - // - // Bus 0, Device 1, Function 0 - PCI to ISA Bridge - // - PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x3c), 0x00); - PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // LNKA routing target - PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // LNKB routing target - PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // LNKC routing target - PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // LNKD routing target - - // - // Bus 0, Device 1, Function 1 - IDE Controller - // - PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x3c), 0x00); - PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x0d), 0x40); + UINT16 HostBridgeDevId; + UINTN Pmba; // - // Bus 0, Device 1, Function 3 - Power Managment Controller + // Query Host Bridge DID to determine platform type // - PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3c), 0x09); - PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3d), 0x01); // INTA - - // - // Bus 0, Device 2, Function 0 - Video Controller - // - PciWrite8 (PCI_LIB_ADDRESS (0, 2, 0, 0x3c), 0x00); + HostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId); + switch (HostBridgeDevId) { + case INTEL_82441_DEVICE_ID: + Pmba = POWER_MGMT_REGISTER_PIIX4 (0x40); + // + // 00:01.0 ISA Bridge (PIIX4) LNK routing targets + // + PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A + PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B + PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C + PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D + break; + case INTEL_Q35_MCH_DEVICE_ID: + Pmba = POWER_MGMT_REGISTER_Q35 (0x40); + // + // 00:1f.0 LPC Bridge (Q35) LNK routing targets + // + PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A + PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B + PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C + PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D + PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E + PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F + PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G + PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H + break; + default: + DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n", + __FUNCTION__, HostBridgeDevId)); + ASSERT (FALSE); + return; + } // - // Bus 0, Device 3, Function 0 - Network Controller + // Set ACPI SCI_EN bit in PMCNTRL // - PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3c), 0x0a); - PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3d), 0x01); // INTA (-> LNKC) + IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0); // - // Bus 0, Device 5, Function 0 - RAM Memory + // Initialize PCI_INTERRUPT_LINE for commonly encountered devices and slots // - PciWrite8 (PCI_LIB_ADDRESS (0, 5, 0, 0x3c), 0x0b); - PciWrite8 (PCI_LIB_ADDRESS (0, 5, 0, 0x3d), 0x01); // INTA (-> LNKA) -} - - -VOID -AcpiInitialization ( - VOID - ) -{ - // - // Set ACPI SCI_EN bit in PMCNTRL + // FIXME: This should instead be accomplished programmatically by + // ennumerating all PCI devices present in the system and + // computing PCI_INTERRUPT_LINE from PCI_INTERRUPT_PIN, the + // slot/position of the device, and the available host IRQs + // (for an example, see SeaBIOS pci_bios_init_devices() in + // src/fw/pciinit.c) // - IoOr16 ((PciRead32 (PCI_LIB_ADDRESS (0, 1, 3, 0x40)) & ~BIT0) + 4, BIT0); + switch (HostBridgeDevId) { + case INTEL_82441_DEVICE_ID: + PciWrite8 (PCI_LIB_ADDRESS (0, 1, 2, 0x3c), 0x0b); // usb (northbr.) + PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3c), 0x0a); // acpi (northbr.) + PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3c), 0x0b); + PciWrite8 (PCI_LIB_ADDRESS (0, 4, 0, 0x3c), 0x0b); + PciWrite8 (PCI_LIB_ADDRESS (0, 5, 0, 0x3c), 0x0a); + PciWrite8 (PCI_LIB_ADDRESS (0, 6, 0, 0x3c), 0x0a); + PciWrite8 (PCI_LIB_ADDRESS (0, 7, 0, 0x3c), 0x0b); + PciWrite8 (PCI_LIB_ADDRESS (0, 8, 0, 0x3c), 0x0b); + break; + case INTEL_Q35_MCH_DEVICE_ID: + PciWrite8 (PCI_LIB_ADDRESS (0, 2, 0, 0x3c), 0x0b); + PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3c), 0x0b); + PciWrite8 (PCI_LIB_ADDRESS (0, 4, 0, 0x3c), 0x0a); + PciWrite8 (PCI_LIB_ADDRESS (0, 5, 0, 0x3c), 0x0a); + PciWrite8 (PCI_LIB_ADDRESS (0, 6, 0, 0x3c), 0x0b); + PciWrite8 (PCI_LIB_ADDRESS (0, 7, 0, 0x3c), 0x0b); + PciWrite8 (PCI_LIB_ADDRESS (0, 8, 0, 0x3c), 0x0a); + PciWrite8 (PCI_LIB_ADDRESS (0, 0x1d, 0, 0x3c), 0x0a); // uhci1 + PciWrite8 (PCI_LIB_ADDRESS (0, 0x1d, 1, 0x3c), 0x0a); // uhci2 + PciWrite8 (PCI_LIB_ADDRESS (0, 0x1d, 2, 0x3c), 0x0b); // uhci3 + PciWrite8 (PCI_LIB_ADDRESS (0, 0x1d, 7, 0x3c), 0x0b); // ehci1 + PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 2, 0x3c), 0x0a); // ahci (northbr.) + PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 3, 0x3c), 0x0a); // smbus (northbr.) + break; + default: + ASSERT (FALSE); // should never be reached + } } @@ -938,8 +967,7 @@ Returns: // BdsLibConnectAll (); - PciInitialization (); - AcpiInitialization (); + PciAcpiInitialization (); // // Clear the logo after all devices are connected. diff --git a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.h b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.h index 72b0e149e0..7006fb3795 100644 --- a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.h +++ b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.h @@ -59,6 +59,8 @@ Abstract: #include #include +#include + extern BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole[]; extern EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[]; extern EFI_DEVICE_PATH_PROTOCOL *gPlatformDriverOption[]; diff --git a/OvmfPkg/Library/PlatformBdsLib/PlatformBdsLib.inf b/OvmfPkg/Library/PlatformBdsLib/PlatformBdsLib.inf index a2b72bad35..03f5b229cf 100644 --- a/OvmfPkg/Library/PlatformBdsLib/PlatformBdsLib.inf +++ b/OvmfPkg/Library/PlatformBdsLib/PlatformBdsLib.inf @@ -58,6 +58,7 @@ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId [Pcd.IA32, Pcd.X64] gEfiMdePkgTokenSpaceGuid.PcdFSBClock -- cgit v1.2.3