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