aboutsummaryrefslogtreecommitdiffstats
path: root/roms/edk2/OvmfPkg/Csm/CsmSupportLib/LegacyInterrupt.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/edk2/OvmfPkg/Csm/CsmSupportLib/LegacyInterrupt.c')
-rw-r--r--roms/edk2/OvmfPkg/Csm/CsmSupportLib/LegacyInterrupt.c214
1 files changed, 214 insertions, 0 deletions
diff --git a/roms/edk2/OvmfPkg/Csm/CsmSupportLib/LegacyInterrupt.c b/roms/edk2/OvmfPkg/Csm/CsmSupportLib/LegacyInterrupt.c
new file mode 100644
index 000000000..97ca21945
--- /dev/null
+++ b/roms/edk2/OvmfPkg/Csm/CsmSupportLib/LegacyInterrupt.c
@@ -0,0 +1,214 @@
+/** @file
+ Legacy Interrupt Support
+
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "LegacyInterrupt.h"
+
+//
+// Handle for the Legacy Interrupt Protocol instance produced by this driver
+//
+STATIC EFI_HANDLE mLegacyInterruptHandle = NULL;
+
+//
+// Legacy Interrupt Device number (0x01 on piix4, 0x1f on q35/mch)
+//
+STATIC UINT8 mLegacyInterruptDevice;
+
+//
+// The Legacy Interrupt Protocol instance produced by this driver
+//
+STATIC EFI_LEGACY_INTERRUPT_PROTOCOL mLegacyInterrupt = {
+ GetNumberPirqs,
+ GetLocation,
+ ReadPirq,
+ WritePirq
+};
+
+STATIC UINT8 PirqReg[MAX_PIRQ_NUMBER] = { PIRQA, PIRQB, PIRQC, PIRQD, PIRQE, PIRQF, PIRQG, PIRQH };
+
+
+/**
+ Return the number of PIRQs supported by this chipset.
+
+ @param[in] This Pointer to LegacyInterrupt Protocol
+ @param[out] NumberPirqs The pointer to return the max IRQ number supported
+
+ @retval EFI_SUCCESS Max PIRQs successfully returned
+
+**/
+EFI_STATUS
+EFIAPI
+GetNumberPirqs (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ OUT UINT8 *NumberPirqs
+ )
+{
+ *NumberPirqs = MAX_PIRQ_NUMBER;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Return PCI location of this device.
+ $PIR table requires this info.
+
+ @param[in] This - Protocol instance pointer.
+ @param[out] Bus - PCI Bus
+ @param[out] Device - PCI Device
+ @param[out] Function - PCI Function
+
+ @retval EFI_SUCCESS Bus/Device/Function returned
+
+**/
+EFI_STATUS
+EFIAPI
+GetLocation (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ OUT UINT8 *Bus,
+ OUT UINT8 *Device,
+ OUT UINT8 *Function
+ )
+{
+ *Bus = LEGACY_INT_BUS;
+ *Device = mLegacyInterruptDevice;
+ *Function = LEGACY_INT_FUNC;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Builds the PCI configuration address for the register specified by PirqNumber
+
+ @param[in] PirqNumber - The PIRQ number to build the PCI configuration address for
+
+ @return The PCI Configuration address for the PIRQ
+**/
+UINTN
+GetAddress (
+ UINT8 PirqNumber
+ )
+{
+ return PCI_LIB_ADDRESS(
+ LEGACY_INT_BUS,
+ mLegacyInterruptDevice,
+ LEGACY_INT_FUNC,
+ PirqReg[PirqNumber]
+ );
+}
+
+/**
+ Read the given PIRQ register
+
+ @param[in] This Protocol instance pointer
+ @param[in] PirqNumber The Pirq register 0 = A, 1 = B etc
+ @param[out] PirqData Value read
+
+ @retval EFI_SUCCESS Decoding change affected.
+ @retval EFI_INVALID_PARAMETER Invalid PIRQ number
+
+**/
+EFI_STATUS
+EFIAPI
+ReadPirq (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ IN UINT8 PirqNumber,
+ OUT UINT8 *PirqData
+ )
+{
+ if (PirqNumber >= MAX_PIRQ_NUMBER) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *PirqData = PciRead8 (GetAddress (PirqNumber));
+ *PirqData = (UINT8) (*PirqData & 0x7f);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Write the given PIRQ register
+
+ @param[in] This Protocol instance pointer
+ @param[in] PirqNumber The Pirq register 0 = A, 1 = B etc
+ @param[out] PirqData Value to write
+
+ @retval EFI_SUCCESS Decoding change affected.
+ @retval EFI_INVALID_PARAMETER Invalid PIRQ number
+
+**/
+EFI_STATUS
+EFIAPI
+WritePirq (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ IN UINT8 PirqNumber,
+ IN UINT8 PirqData
+ )
+{
+ if (PirqNumber >= MAX_PIRQ_NUMBER) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PciWrite8 (GetAddress (PirqNumber), PirqData);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Initialize Legacy Interrupt support
+
+ @retval EFI_SUCCESS Successfully initialized
+
+**/
+EFI_STATUS
+LegacyInterruptInstall (
+ VOID
+ )
+{
+ UINT16 HostBridgeDevId;
+ EFI_STATUS Status;
+
+ //
+ // Make sure the Legacy Interrupt Protocol is not already installed in the system
+ //
+ ASSERT_PROTOCOL_ALREADY_INSTALLED(NULL, &gEfiLegacyInterruptProtocolGuid);
+
+ //
+ // Query Host Bridge DID to determine platform type, then set device number
+ //
+ HostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);
+ switch (HostBridgeDevId) {
+ case INTEL_82441_DEVICE_ID:
+ mLegacyInterruptDevice = LEGACY_INT_DEV_PIIX4;
+ break;
+ case INTEL_Q35_MCH_DEVICE_ID:
+ mLegacyInterruptDevice = LEGACY_INT_DEV_Q35;
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
+ __FUNCTION__, HostBridgeDevId));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Make a new handle and install the protocol
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mLegacyInterruptHandle,
+ &gEfiLegacyInterruptProtocolGuid,
+ &mLegacyInterrupt,
+ NULL
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+