Remove hard-coded list of PCI devices for which the Interrupt Line
register is initialized. Instead, provide a "visitor" function to
initialize the register only for present and applicable PCI devices.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Gabriel Somlo <so...@cmu.edu>
---

The one thing I'm not 100% sure about here is what would it look like if
we *did* have pci-to-pci bridges and non-root buses. Would the device path
simply be "longer", and, if I didn't break out after finding the first
HW_PCI_DP device path node would I keep finding more such nodes ? If so, I
could probably add their device numbers together to get the same effect
from SeaBIOS *_pci_slot_get_irq(), but I don't know where I'd manage to
get the original device's pci bus number for the eventual
PciWrite8 (PCI_LIB_ADDRESS (...)) call when setting up PCI_INT_LINE_OFFSET.

If we collectively decide to not worry about this scenario right now, please
disregard the above paragraph :)

Thanks,
  Gabriel

 OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c | 146 +++++++++++++++++++--------
 1 file changed, 102 insertions(+), 44 deletions(-)

diff --git a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c 
b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
index 62a8e19..c08112e 100644
--- a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
+++ b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c
@@ -25,7 +25,20 @@ EFI_EVENT     mEfiDevPathEvent;
 VOID          *mEmuVariableEventReg;
 EFI_EVENT     mEmuVariableEvent;
 BOOLEAN       mDetectVgaOnly;
+UINT16        mHostBridgeDevId;
 
+//
+// Table of host IRQs matching PCI IRQs A-D
+// (for configuring PCI Interrupt Line register)
+//
+CONST UINT8 PciHostIrqs[] = {
+  0x0a, 0x0a, 0x0b, 0x0b
+};
+
+//
+// Array Size macro
+//
+#define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0]))
 
 //
 // Type definitions
@@ -716,18 +729,98 @@ Returns:
 }
 
 
+/**
+  Configure PCI Interrupt Line register for applicable devices
+
+  @param[in]  Handle - Handle of PCI device instance
+  @param[in]  PciIo - PCI IO protocol instance
+  @param[in]  PciHdr - PCI Header register block
+
+  @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+SetPciIntLine (
+  IN EFI_HANDLE           Handle,
+  IN EFI_PCI_IO_PROTOCOL  *PciIo,
+  IN PCI_TYPE00           *PciHdr
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL  *DevPathNode;
+  PCI_DEVICE_PATH           *PciDevPathData;
+  UINTN                     Idx;
+
+  if (PciHdr->Device.InterruptPin != 0) {
+    DevPathNode = DevicePathFromHandle (Handle);
+    ASSERT (DevPathNode != NULL);
+
+    //
+    // Walk device path, searching for PCI hardware device type
+    //
+    while (!IsDevicePathEnd (DevPathNode)) {
+      if (DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH &&
+          DevicePathSubType (DevPathNode) == HW_PCI_DP) {
+
+        PciDevPathData = (PCI_DEVICE_PATH*) DevPathNode;
+
+        //
+        // Calculate index into PciHostIrqs[] table
+        // (assuming all devices connected directly to root PCI bus 0,
+        //  no non-root ports, no PCIe switches, no PCI-to-PCI bridges)
+        //
+        Idx = PciHdr->Device.InterruptPin - 1;
+        switch (mHostBridgeDevId) {
+          case INTEL_82441_DEVICE_ID:
+            Idx += PciDevPathData->Device - 1;
+            break;
+          case INTEL_Q35_MCH_DEVICE_ID:
+            if (PciDevPathData->Device <= 24) {
+              Idx += PciDevPathData->Device;
+            }
+            break;
+          default:
+            ASSERT (FALSE); // should never get here
+        }
+        Idx %= ARRAY_SIZE (PciHostIrqs);
+
+        //
+        // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
+        //
+        PciWrite8 (
+          PCI_LIB_ADDRESS (
+            0,
+            PciDevPathData->Device,
+            PciDevPathData->Function,
+            PCI_INT_LINE_OFFSET
+            ),
+          PciHostIrqs[Idx]
+          );
+
+        //
+        // Stop after first PCI hardware device path node found
+        //
+        return EFI_SUCCESS;
+      }
+      DevPathNode = NextDevicePathNode (DevPathNode);
+    }
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+
 VOID
 PciAcpiInitialization (
   )
 {
-  UINT16 HostBridgeDevId;
   UINTN  Pmba;
 
   //
   // Query Host Bridge DID to determine platform type
   //
-  HostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);
-  switch (HostBridgeDevId) {
+  mHostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);
+  switch (mHostBridgeDevId) {
     case INTEL_82441_DEVICE_ID:
       Pmba = POWER_MGMT_REGISTER_PIIX4 (0x40);
       //
@@ -754,54 +847,19 @@ PciAcpiInitialization (
       break;
     default:
       DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
-        __FUNCTION__, HostBridgeDevId));
+        __FUNCTION__, mHostBridgeDevId));
       ASSERT (FALSE);
   }
 
   //
+  // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
+  //
+  VisitAllPciInstances (SetPciIntLine);
+
+  //
   // Set ACPI SCI_EN bit in PMCNTRL
   //
   IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0);
-
-  //
-  // Initialize PCI_INTERRUPT_LINE for commonly encountered devices and slots
-  //
-  // 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)
-  //
-  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
-  }
 }
 
 
-- 
1.9.3


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

Reply via email to