On 11/01/14 23:21, Gabriel L. Somlo wrote:
> 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 initialization of PCI_INTERRUPT_LINE registers *should*
> be accomplished programmatically by enumerating 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). At the time of this patch, the relevant bits of
> OVMF PCI initialization are shown in the following call tree:
> 
>   PlatformBdsPolicyBehavior ()
>   {
>     ...
>     ConnectRootBridge ()
>     {
>       ...
>       gBS->ConnectController ()  // PCI bus is enumerated from this call
>       ...
>     }
>     ...
>     PlatformBdsConnectSequence ()
>     {
>       ...
>       PciAcpiInitialization ()  // PCI initialization affected by this patch
>       ...
>     }
>     ...
>   }
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Gabriel Somlo <so...@cmu.edu>
> Reviewed-by: Paolo Bonzini <pbonz...@redhat.com>
> Reviewed-by: Jordan Justen <jordan.l.jus...@intel.com>
> ---
>  OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c      | 121 
> +++++++++++++---------
>  OvmfPkg/Library/PlatformBdsLib/BdsPlatform.h      |   2 +
>  OvmfPkg/Library/PlatformBdsLib/PlatformBdsLib.inf |   1 +
>  3 files changed, 77 insertions(+), 47 deletions(-)
> 
> diff --git a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c 
> b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
> index 2a1ca88..461f118 100644
> --- a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
> +++ b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
> @@ -717,63 +717,91 @@ 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);
> +  }
>  
>    //
> -  // 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 +966,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 72b0e14..7006fb3 100644
> --- a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.h
> +++ b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.h
> @@ -59,6 +59,8 @@ Abstract:
>  #include <Guid/HobList.h>
>  #include <Guid/GlobalVariable.h>
>  
> +#include <OvmfPlatforms.h>
> +
>  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 a2b72ba..03f5b22 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
> 

(1) Please use

  --diff-algorithm=patience

when formatting patches that basically rewrite functions whole-sale. It
usually prevents unrelated chunks of old and new code from intermixing.

(2) It's not hard to do the enumeration that you want. You just need to
locate all handles with PciIo protocol instances on them (since we're
just after a BdsLibConnectAll() call), open the PciIo protocol interface
on each in turn, read the header from the PCI config space, and do what
you want.

Luckily, this code already exists for you, precisely in this file --
"OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c". The function you want to
call is

  VisitAllPciInstances()

you just need to provide a callback function (of type
VISIT_PCI_INSTANCE_CALLBACK).

The PCI_TYPE00 structure, passed to the callback as third parameter, is
defined in "MdePkg/Include/IndustryStandard/Pci22.h". You probably care
about the

  Pci->Device.InterruptPin

field in the callback.

Let's see what other input parameters you need to compute the interrupt
line, beside the interrupt pin:

- slot/position: you can get this by opening the Device Path protocol
  on the handle (first param of the callback).

  - Search this file for gBS->HandleProtocol() calls with
   "gEfiDevicePathProtocolGuid", for examples.

  - Better yet, use the DevicePathFromHandle() convenience function
    from DevicePathLib.

  Once you have the device path protocol, iterate over the device path
  node by node, using the NextDevicePathNode() and IsDevicePathEnd()
  library functions. (You can actually find an example loop with these
  functions in this same file, "BdsPlatform.c"!)

  The device path node you're looking for has type HARDWARE_DEVICE_PATH
  and subtype HW_PCI_DP. (Again, the same loop serves as an example,
  with the DevicePathType() and DevicePathSubType() helper functions.)

  Assuming no bridges, just look for the first such node in each device
  path. When you find it, cast the node to PCI_DEVICE_PATH, and look at
  the "Function" and "Device" fields.
  (See "MdePkg/Include/Protocol/DevicePath.h".)

  You'll probably want to exclude some "special" (ie. chipset-related)
  PCI devices from this logic. You can use the same two fields to
  recognize those.

  For debugging purposes, you can use the ConvertDevicePathToText() /
  ConvertDeviceNodeToText() utility functions, just don't forget to
  FrePool() the formatted CHAR16 strings after logging them.

- "available host IRQs": I take it you meant "available *guest* IRQs".

  In general the "rotating scheme" uses 0x5, 0xa and 0xb. (== The _PRS
  ACPI method for LNK[A-D] / LNK[A-H] returns {5, 10, 11}.)

This can be implemented later on of course.

(3) If you feel pedantic, you can employ the PCI_INT_LINE_OFFSET macro
in place of 0x3c.

Acked-by: Laszlo Ersek <ler...@redhat.com>

Thanks a lot!
Laszlo

------------------------------------------------------------------------------
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to