From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=209.132.183.28; helo=mx1.redhat.com; envelope-from=lersek@redhat.com; receiver=edk2-devel@lists.01.org Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 0BC81211E2EE2 for ; Wed, 3 Apr 2019 05:05:23 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 43D093134339; Wed, 3 Apr 2019 12:05:23 +0000 (UTC) Received: from lacos-laptop-7.usersys.redhat.com (ovpn-120-127.rdu2.redhat.com [10.10.120.127]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8C7B86014C; Wed, 3 Apr 2019 12:05:21 +0000 (UTC) To: Hao Wu , edk2-devel@lists.01.org Cc: Jordan Justen , David Woodhouse References: <20190403070036.1404-1-hao.a.wu@intel.com> <20190403070036.1404-2-hao.a.wu@intel.com> From: Laszlo Ersek Message-ID: <60a63892-f20c-00bd-58c7-960267d7fa80@redhat.com> Date: Wed, 3 Apr 2019 14:05:15 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 MIME-Version: 1.0 In-Reply-To: <20190403070036.1404-2-hao.a.wu@intel.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.49]); Wed, 03 Apr 2019 12:05:23 +0000 (UTC) Subject: Re: [RFC PATCH v1 1/8] OvmfPkg: Copy 8259InterruptControllerDxe driver from PcAtChipsetPkg X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 03 Apr 2019 12:05:24 -0000 Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit On 04/03/19 09:00, Hao Wu wrote: > REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1496 > > This commit copies the exact 8259InterruptControllerDxe driver from > PcAtChipsetPkg to OvmfPkg. > > Cc: Jordan Justen > Cc: Laszlo Ersek > Cc: Ard Biesheuvel > Cc: David Woodhouse > Cc: Ray Ni > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Hao Wu > --- > OvmfPkg/8259InterruptControllerDxe/8259.inf | 52 ++ > OvmfPkg/8259InterruptControllerDxe/8259.h | 226 +++++++ > OvmfPkg/8259InterruptControllerDxe/8259.c | 628 ++++++++++++++++++++ > OvmfPkg/8259InterruptControllerDxe/Legacy8259.uni | 22 + > OvmfPkg/8259InterruptControllerDxe/Legacy8259Extra.uni | 20 + > 5 files changed, 948 insertions(+) > > diff --git a/OvmfPkg/8259InterruptControllerDxe/8259.inf b/OvmfPkg/8259InterruptControllerDxe/8259.inf > new file mode 100644 > index 0000000000..1d9be675e3 > --- /dev/null > +++ b/OvmfPkg/8259InterruptControllerDxe/8259.inf > @@ -0,0 +1,52 @@ > +## @file > +# 8259 Interrupt Controller driver that provides Legacy 8259 protocol. > +# > +# Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
> +# This program and the accompanying materials > +# are licensed and made available under the terms and conditions of the BSD License > +# which accompanies this distribution. The full text of the license may be found at > +# http://opensource.org/licenses/bsd-license.php > +# > +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > +# > +## > + > +[Defines] > + INF_VERSION = 0x00010005 > + BASE_NAME = Legacy8259 > + MODULE_UNI_FILE = Legacy8259.uni > + FILE_GUID = 79CA4208-BBA1-4a9a-8456-E1E66A81484E When creating customized copies, we usually like to generate new FILE_GUIDs at once -- but in this case, I agree that the GUID should remain unchanged, as ultimately this code copy will amount to a rename / move. I also verified this patch with "git show --find-copies-harder". Reviewed-by: Laszlo Ersek Thanks, Laszlo > + MODULE_TYPE = DXE_DRIVER > + VERSION_STRING = 1.0 > + ENTRY_POINT = Install8259 > + > +[Sources] > + 8259.c > + 8259.h > + > +[Packages] > + MdePkg/MdePkg.dec > + IntelFrameworkPkg/IntelFrameworkPkg.dec > + PcAtChipsetPkg/PcAtChipsetPkg.dec > + > +[LibraryClasses] > + UefiBootServicesTableLib > + DebugLib > + UefiDriverEntryPoint > + IoLib > + PcdLib > + > +[Protocols] > + gEfiLegacy8259ProtocolGuid ## PRODUCES > + gEfiPciIoProtocolGuid ## SOMETIMES_CONSUMES > + > +[Pcd] > + gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeMask ## CONSUMES > + gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel ## CONSUMES > + > +[Depex] > + TRUE > + > +[UserExtensions.TianoCore."ExtraFiles"] > + Legacy8259Extra.uni > diff --git a/OvmfPkg/8259InterruptControllerDxe/8259.h b/OvmfPkg/8259InterruptControllerDxe/8259.h > new file mode 100644 > index 0000000000..0d4c1e8223 > --- /dev/null > +++ b/OvmfPkg/8259InterruptControllerDxe/8259.h > @@ -0,0 +1,226 @@ > +/** @file > + Driver implementing the Tiano Legacy 8259 Protocol > + > +Copyright (c) 2005 - 2009, Intel Corporation. All rights reserved.
> +This program and the accompanying materials > +are licensed and made available under the terms and conditions of the BSD License > +which accompanies this distribution. The full text of the license may be found at > +http://opensource.org/licenses/bsd-license.php. > + > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > +**/ > + > +#ifndef _8259_H__ > +#define _8259_H__ > + > +#include > + > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +// 8259 Hardware definitions > + > +#define LEGACY_MODE_BASE_VECTOR_MASTER 0x08 > +#define LEGACY_MODE_BASE_VECTOR_SLAVE 0x70 > + > +#define PROTECTED_MODE_BASE_VECTOR_MASTER 0x68 > +#define PROTECTED_MODE_BASE_VECTOR_SLAVE 0x70 > + > +#define LEGACY_8259_CONTROL_REGISTER_MASTER 0x20 > +#define LEGACY_8259_MASK_REGISTER_MASTER 0x21 > +#define LEGACY_8259_CONTROL_REGISTER_SLAVE 0xA0 > +#define LEGACY_8259_MASK_REGISTER_SLAVE 0xA1 > +#define LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER 0x4D0 > +#define LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE 0x4D1 > + > +#define LEGACY_8259_EOI 0x20 > + > +// Protocol Function Prototypes > + > +/** > + Sets the base address for the 8259 master and slave PICs. > + > + @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance. > + @param[in] MasterBase Interrupt vectors for IRQ0-IRQ7. > + @param[in] SlaveBase Interrupt vectors for IRQ8-IRQ15. > + > + @retval EFI_SUCCESS The 8259 PIC was programmed successfully. > + @retval EFI_DEVICE_ERROR There was an error while writing to the 8259 PIC. > + > +**/ > +EFI_STATUS > +EFIAPI > +Interrupt8259SetVectorBase ( > + IN EFI_LEGACY_8259_PROTOCOL *This, > + IN UINT8 MasterBase, > + IN UINT8 SlaveBase > + ); > + > +/** > + Gets the current 16-bit real mode and 32-bit protected-mode IRQ masks. > + > + @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance. > + @param[out] LegacyMask 16-bit mode interrupt mask for IRQ0-IRQ15. > + @param[out] LegacyEdgeLevel 16-bit mode edge/level mask for IRQ-IRQ15. > + @param[out] ProtectedMask 32-bit mode interrupt mask for IRQ0-IRQ15. > + @param[out] ProtectedEdgeLevel 32-bit mode edge/level mask for IRQ0-IRQ15. > + > + @retval EFI_SUCCESS The 8259 PIC was programmed successfully. > + @retval EFI_DEVICE_ERROR There was an error while reading the 8259 PIC. > + > +**/ > +EFI_STATUS > +EFIAPI > +Interrupt8259GetMask ( > + IN EFI_LEGACY_8259_PROTOCOL *This, > + OUT UINT16 *LegacyMask, OPTIONAL > + OUT UINT16 *LegacyEdgeLevel, OPTIONAL > + OUT UINT16 *ProtectedMask, OPTIONAL > + OUT UINT16 *ProtectedEdgeLevel OPTIONAL > + ); > + > +/** > + Sets the current 16-bit real mode and 32-bit protected-mode IRQ masks. > + > + @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance. > + @param[in] LegacyMask 16-bit mode interrupt mask for IRQ0-IRQ15. > + @param[in] LegacyEdgeLevel 16-bit mode edge/level mask for IRQ-IRQ15. > + @param[in] ProtectedMask 32-bit mode interrupt mask for IRQ0-IRQ15. > + @param[in] ProtectedEdgeLevel 32-bit mode edge/level mask for IRQ0-IRQ15. > + > + @retval EFI_SUCCESS The 8259 PIC was programmed successfully. > + @retval EFI_DEVICE_ERROR There was an error while writing the 8259 PIC. > + > +**/ > +EFI_STATUS > +EFIAPI > +Interrupt8259SetMask ( > + IN EFI_LEGACY_8259_PROTOCOL *This, > + IN UINT16 *LegacyMask, OPTIONAL > + IN UINT16 *LegacyEdgeLevel, OPTIONAL > + IN UINT16 *ProtectedMask, OPTIONAL > + IN UINT16 *ProtectedEdgeLevel OPTIONAL > + ); > + > +/** > + Sets the mode of the PICs. > + > + @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance. > + @param[in] Mode 16-bit real or 32-bit protected mode. > + @param[in] Mask The value with which to set the interrupt mask. > + @param[in] EdgeLevel The value with which to set the edge/level mask. > + > + @retval EFI_SUCCESS The mode was set successfully. > + @retval EFI_INVALID_PARAMETER The mode was not set. > + > +**/ > +EFI_STATUS > +EFIAPI > +Interrupt8259SetMode ( > + IN EFI_LEGACY_8259_PROTOCOL *This, > + IN EFI_8259_MODE Mode, > + IN UINT16 *Mask, OPTIONAL > + IN UINT16 *EdgeLevel OPTIONAL > + ); > + > +/** > + Translates the IRQ into a vector. > + > + @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance. > + @param[in] Irq IRQ0-IRQ15. > + @param[out] Vector The vector that is assigned to the IRQ. > + > + @retval EFI_SUCCESS The Vector that matches Irq was returned. > + @retval EFI_INVALID_PARAMETER Irq is not valid. > + > +**/ > +EFI_STATUS > +EFIAPI > +Interrupt8259GetVector ( > + IN EFI_LEGACY_8259_PROTOCOL *This, > + IN EFI_8259_IRQ Irq, > + OUT UINT8 *Vector > + ); > + > +/** > + Enables the specified IRQ. > + > + @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance. > + @param[in] Irq IRQ0-IRQ15. > + @param[in] LevelTriggered 0 = Edge triggered; 1 = Level triggered. > + > + @retval EFI_SUCCESS The Irq was enabled on the 8259 PIC. > + @retval EFI_INVALID_PARAMETER The Irq is not valid. > + > +**/ > +EFI_STATUS > +EFIAPI > +Interrupt8259EnableIrq ( > + IN EFI_LEGACY_8259_PROTOCOL *This, > + IN EFI_8259_IRQ Irq, > + IN BOOLEAN LevelTriggered > + ); > + > +/** > + Disables the specified IRQ. > + > + @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance. > + @param[in] Irq IRQ0-IRQ15. > + > + @retval EFI_SUCCESS The Irq was disabled on the 8259 PIC. > + @retval EFI_INVALID_PARAMETER The Irq is not valid. > + > +**/ > +EFI_STATUS > +EFIAPI > +Interrupt8259DisableIrq ( > + IN EFI_LEGACY_8259_PROTOCOL *This, > + IN EFI_8259_IRQ Irq > + ); > + > +/** > + Reads the PCI configuration space to get the interrupt number that is assigned to the card. > + > + @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance. > + @param[in] PciHandle PCI function for which to return the vector. > + @param[out] Vector IRQ number that corresponds to the interrupt line. > + > + @retval EFI_SUCCESS The interrupt line value was read successfully. > + > +**/ > +EFI_STATUS > +EFIAPI > +Interrupt8259GetInterruptLine ( > + IN EFI_LEGACY_8259_PROTOCOL *This, > + IN EFI_HANDLE PciHandle, > + OUT UINT8 *Vector > + ); > + > +/** > + Issues the End of Interrupt (EOI) commands to PICs. > + > + @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance. > + @param[in] Irq The interrupt for which to issue the EOI command. > + > + @retval EFI_SUCCESS The EOI command was issued. > + @retval EFI_INVALID_PARAMETER The Irq is not valid. > + > +**/ > +EFI_STATUS > +EFIAPI > +Interrupt8259EndOfInterrupt ( > + IN EFI_LEGACY_8259_PROTOCOL *This, > + IN EFI_8259_IRQ Irq > + ); > + > +#endif > diff --git a/OvmfPkg/8259InterruptControllerDxe/8259.c b/OvmfPkg/8259InterruptControllerDxe/8259.c > new file mode 100644 > index 0000000000..a89e893649 > --- /dev/null > +++ b/OvmfPkg/8259InterruptControllerDxe/8259.c > @@ -0,0 +1,628 @@ > +/** @file > + This contains the installation function for the driver. > + > +Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
> +This program and the accompanying materials > +are licensed and made available under the terms and conditions of the BSD License > +which accompanies this distribution. The full text of the license may be found at > +http://opensource.org/licenses/bsd-license.php > + > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > +**/ > + > +#include "8259.h" > + > +// > +// Global for the Legacy 8259 Protocol that is produced by this driver > +// > +EFI_LEGACY_8259_PROTOCOL mInterrupt8259 = { > + Interrupt8259SetVectorBase, > + Interrupt8259GetMask, > + Interrupt8259SetMask, > + Interrupt8259SetMode, > + Interrupt8259GetVector, > + Interrupt8259EnableIrq, > + Interrupt8259DisableIrq, > + Interrupt8259GetInterruptLine, > + Interrupt8259EndOfInterrupt > +}; > + > +// > +// Global for the handle that the Legacy 8259 Protocol is installed > +// > +EFI_HANDLE m8259Handle = NULL; > + > +UINT8 mMasterBase = 0xff; > +UINT8 mSlaveBase = 0xff; > +EFI_8259_MODE mMode = Efi8259ProtectedMode; > +UINT16 mProtectedModeMask = 0xffff; > +UINT16 mLegacyModeMask; > +UINT16 mProtectedModeEdgeLevel = 0x0000; > +UINT16 mLegacyModeEdgeLevel; > + > +// > +// Worker Functions > +// > + > +/** > + Write to mask and edge/level triggered registers of master and slave PICs. > + > + @param[in] Mask low byte for master PIC mask register, > + high byte for slave PIC mask register. > + @param[in] EdgeLevel low byte for master PIC edge/level triggered register, > + high byte for slave PIC edge/level triggered register. > + > +**/ > +VOID > +Interrupt8259WriteMask ( > + IN UINT16 Mask, > + IN UINT16 EdgeLevel > + ) > +{ > + IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, (UINT8) Mask); > + IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, (UINT8) (Mask >> 8)); > + IoWrite8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER, (UINT8) EdgeLevel); > + IoWrite8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE, (UINT8) (EdgeLevel >> 8)); > +} > + > +/** > + Read from mask and edge/level triggered registers of master and slave PICs. > + > + @param[out] Mask low byte for master PIC mask register, > + high byte for slave PIC mask register. > + @param[out] EdgeLevel low byte for master PIC edge/level triggered register, > + high byte for slave PIC edge/level triggered register. > + > +**/ > +VOID > +Interrupt8259ReadMask ( > + OUT UINT16 *Mask, > + OUT UINT16 *EdgeLevel > + ) > +{ > + UINT16 MasterValue; > + UINT16 SlaveValue; > + > + if (Mask != NULL) { > + MasterValue = IoRead8 (LEGACY_8259_MASK_REGISTER_MASTER); > + SlaveValue = IoRead8 (LEGACY_8259_MASK_REGISTER_SLAVE); > + > + *Mask = (UINT16) (MasterValue | (SlaveValue << 8)); > + } > + > + if (EdgeLevel != NULL) { > + MasterValue = IoRead8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER); > + SlaveValue = IoRead8 (LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE); > + > + *EdgeLevel = (UINT16) (MasterValue | (SlaveValue << 8)); > + } > +} > + > +// > +// Legacy 8259 Protocol Interface Functions > +// > + > +/** > + Sets the base address for the 8259 master and slave PICs. > + > + @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance. > + @param[in] MasterBase Interrupt vectors for IRQ0-IRQ7. > + @param[in] SlaveBase Interrupt vectors for IRQ8-IRQ15. > + > + @retval EFI_SUCCESS The 8259 PIC was programmed successfully. > + @retval EFI_DEVICE_ERROR There was an error while writing to the 8259 PIC. > + > +**/ > +EFI_STATUS > +EFIAPI > +Interrupt8259SetVectorBase ( > + IN EFI_LEGACY_8259_PROTOCOL *This, > + IN UINT8 MasterBase, > + IN UINT8 SlaveBase > + ) > +{ > + UINT8 Mask; > + EFI_TPL OriginalTpl; > + > + OriginalTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); > + // > + // Set vector base for slave PIC > + // > + if (SlaveBase != mSlaveBase) { > + mSlaveBase = SlaveBase; > + > + // > + // Initialization sequence is needed for setting vector base. > + // > + > + // > + // Preserve interrtup mask register before initialization sequence > + // because it will be cleared during initialization > + // > + Mask = IoRead8 (LEGACY_8259_MASK_REGISTER_SLAVE); > + > + // > + // ICW1: cascade mode, ICW4 write required > + // > + IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE, 0x11); > + > + // > + // ICW2: new vector base (must be multiple of 8) > + // > + IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, mSlaveBase); > + > + // > + // ICW3: slave indentification code must be 2 > + // > + IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0x02); > + > + // > + // ICW4: fully nested mode, non-buffered mode, normal EOI, IA processor > + // > + IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0x01); > + > + // > + // Restore interrupt mask register > + // > + IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, Mask); > + } > + > + // > + // Set vector base for master PIC > + // > + if (MasterBase != mMasterBase) { > + mMasterBase = MasterBase; > + > + // > + // Initialization sequence is needed for setting vector base. > + // > + > + // > + // Preserve interrtup mask register before initialization sequence > + // because it will be cleared during initialization > + // > + Mask = IoRead8 (LEGACY_8259_MASK_REGISTER_MASTER); > + > + // > + // ICW1: cascade mode, ICW4 write required > + // > + IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER, 0x11); > + > + // > + // ICW2: new vector base (must be multiple of 8) > + // > + IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, mMasterBase); > + > + // > + // ICW3: slave PIC is cascaded on IRQ2 > + // > + IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0x04); > + > + // > + // ICW4: fully nested mode, non-buffered mode, normal EOI, IA processor > + // > + IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0x01); > + > + // > + // Restore interrupt mask register > + // > + IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, Mask); > + } > + > + IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE, LEGACY_8259_EOI); > + IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER, LEGACY_8259_EOI); > + > + gBS->RestoreTPL (OriginalTpl); > + > + return EFI_SUCCESS; > +} > + > +/** > + Gets the current 16-bit real mode and 32-bit protected-mode IRQ masks. > + > + @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance. > + @param[out] LegacyMask 16-bit mode interrupt mask for IRQ0-IRQ15. > + @param[out] LegacyEdgeLevel 16-bit mode edge/level mask for IRQ-IRQ15. > + @param[out] ProtectedMask 32-bit mode interrupt mask for IRQ0-IRQ15. > + @param[out] ProtectedEdgeLevel 32-bit mode edge/level mask for IRQ0-IRQ15. > + > + @retval EFI_SUCCESS The 8259 PIC was programmed successfully. > + @retval EFI_DEVICE_ERROR There was an error while reading the 8259 PIC. > + > +**/ > +EFI_STATUS > +EFIAPI > +Interrupt8259GetMask ( > + IN EFI_LEGACY_8259_PROTOCOL *This, > + OUT UINT16 *LegacyMask, OPTIONAL > + OUT UINT16 *LegacyEdgeLevel, OPTIONAL > + OUT UINT16 *ProtectedMask, OPTIONAL > + OUT UINT16 *ProtectedEdgeLevel OPTIONAL > + ) > +{ > + if (LegacyMask != NULL) { > + *LegacyMask = mLegacyModeMask; > + } > + > + if (LegacyEdgeLevel != NULL) { > + *LegacyEdgeLevel = mLegacyModeEdgeLevel; > + } > + > + if (ProtectedMask != NULL) { > + *ProtectedMask = mProtectedModeMask; > + } > + > + if (ProtectedEdgeLevel != NULL) { > + *ProtectedEdgeLevel = mProtectedModeEdgeLevel; > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Sets the current 16-bit real mode and 32-bit protected-mode IRQ masks. > + > + @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance. > + @param[in] LegacyMask 16-bit mode interrupt mask for IRQ0-IRQ15. > + @param[in] LegacyEdgeLevel 16-bit mode edge/level mask for IRQ-IRQ15. > + @param[in] ProtectedMask 32-bit mode interrupt mask for IRQ0-IRQ15. > + @param[in] ProtectedEdgeLevel 32-bit mode edge/level mask for IRQ0-IRQ15. > + > + @retval EFI_SUCCESS The 8259 PIC was programmed successfully. > + @retval EFI_DEVICE_ERROR There was an error while writing the 8259 PIC. > + > +**/ > +EFI_STATUS > +EFIAPI > +Interrupt8259SetMask ( > + IN EFI_LEGACY_8259_PROTOCOL *This, > + IN UINT16 *LegacyMask, OPTIONAL > + IN UINT16 *LegacyEdgeLevel, OPTIONAL > + IN UINT16 *ProtectedMask, OPTIONAL > + IN UINT16 *ProtectedEdgeLevel OPTIONAL > + ) > +{ > + if (LegacyMask != NULL) { > + mLegacyModeMask = *LegacyMask; > + } > + > + if (LegacyEdgeLevel != NULL) { > + mLegacyModeEdgeLevel = *LegacyEdgeLevel; > + } > + > + if (ProtectedMask != NULL) { > + mProtectedModeMask = *ProtectedMask; > + } > + > + if (ProtectedEdgeLevel != NULL) { > + mProtectedModeEdgeLevel = *ProtectedEdgeLevel; > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Sets the mode of the PICs. > + > + @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance. > + @param[in] Mode 16-bit real or 32-bit protected mode. > + @param[in] Mask The value with which to set the interrupt mask. > + @param[in] EdgeLevel The value with which to set the edge/level mask. > + > + @retval EFI_SUCCESS The mode was set successfully. > + @retval EFI_INVALID_PARAMETER The mode was not set. > + > +**/ > +EFI_STATUS > +EFIAPI > +Interrupt8259SetMode ( > + IN EFI_LEGACY_8259_PROTOCOL *This, > + IN EFI_8259_MODE Mode, > + IN UINT16 *Mask, OPTIONAL > + IN UINT16 *EdgeLevel OPTIONAL > + ) > +{ > + if (Mode == mMode) { > + return EFI_SUCCESS; > + } > + > + if (Mode == Efi8259LegacyMode) { > + // > + // In Efi8259ProtectedMode, mask and edge/level trigger registers should > + // be changed through this protocol, so we can track them in the > + // corresponding module variables. > + // > + Interrupt8259ReadMask (&mProtectedModeMask, &mProtectedModeEdgeLevel); > + > + if (Mask != NULL) { > + // > + // Update the Mask for the new mode > + // > + mLegacyModeMask = *Mask; > + } > + > + if (EdgeLevel != NULL) { > + // > + // Update the Edge/Level triggered mask for the new mode > + // > + mLegacyModeEdgeLevel = *EdgeLevel; > + } > + > + mMode = Mode; > + > + // > + // Write new legacy mode mask/trigger level > + // > + Interrupt8259WriteMask (mLegacyModeMask, mLegacyModeEdgeLevel); > + > + return EFI_SUCCESS; > + } > + > + if (Mode == Efi8259ProtectedMode) { > + // > + // Save the legacy mode mask/trigger level > + // > + Interrupt8259ReadMask (&mLegacyModeMask, &mLegacyModeEdgeLevel); > + // > + // Always force Timer to be enabled after return from 16-bit code. > + // This always insures that on next entry, timer is counting. > + // > + mLegacyModeMask &= 0xFFFE; > + > + if (Mask != NULL) { > + // > + // Update the Mask for the new mode > + // > + mProtectedModeMask = *Mask; > + } > + > + if (EdgeLevel != NULL) { > + // > + // Update the Edge/Level triggered mask for the new mode > + // > + mProtectedModeEdgeLevel = *EdgeLevel; > + } > + > + mMode = Mode; > + > + // > + // Write new protected mode mask/trigger level > + // > + Interrupt8259WriteMask (mProtectedModeMask, mProtectedModeEdgeLevel); > + > + return EFI_SUCCESS; > + } > + > + return EFI_INVALID_PARAMETER; > +} > + > +/** > + Translates the IRQ into a vector. > + > + @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance. > + @param[in] Irq IRQ0-IRQ15. > + @param[out] Vector The vector that is assigned to the IRQ. > + > + @retval EFI_SUCCESS The Vector that matches Irq was returned. > + @retval EFI_INVALID_PARAMETER Irq is not valid. > + > +**/ > +EFI_STATUS > +EFIAPI > +Interrupt8259GetVector ( > + IN EFI_LEGACY_8259_PROTOCOL *This, > + IN EFI_8259_IRQ Irq, > + OUT UINT8 *Vector > + ) > +{ > + if ((UINT32)Irq > Efi8259Irq15) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (Irq <= Efi8259Irq7) { > + *Vector = (UINT8) (mMasterBase + Irq); > + } else { > + *Vector = (UINT8) (mSlaveBase + (Irq - Efi8259Irq8)); > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Enables the specified IRQ. > + > + @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance. > + @param[in] Irq IRQ0-IRQ15. > + @param[in] LevelTriggered 0 = Edge triggered; 1 = Level triggered. > + > + @retval EFI_SUCCESS The Irq was enabled on the 8259 PIC. > + @retval EFI_INVALID_PARAMETER The Irq is not valid. > + > +**/ > +EFI_STATUS > +EFIAPI > +Interrupt8259EnableIrq ( > + IN EFI_LEGACY_8259_PROTOCOL *This, > + IN EFI_8259_IRQ Irq, > + IN BOOLEAN LevelTriggered > + ) > +{ > + if ((UINT32)Irq > Efi8259Irq15) { > + return EFI_INVALID_PARAMETER; > + } > + > + mProtectedModeMask = (UINT16) (mProtectedModeMask & ~(1 << Irq)); > + if (LevelTriggered) { > + mProtectedModeEdgeLevel = (UINT16) (mProtectedModeEdgeLevel | (1 << Irq)); > + } else { > + mProtectedModeEdgeLevel = (UINT16) (mProtectedModeEdgeLevel & ~(1 << Irq)); > + } > + > + Interrupt8259WriteMask (mProtectedModeMask, mProtectedModeEdgeLevel); > + > + return EFI_SUCCESS; > +} > + > +/** > + Disables the specified IRQ. > + > + @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance. > + @param[in] Irq IRQ0-IRQ15. > + > + @retval EFI_SUCCESS The Irq was disabled on the 8259 PIC. > + @retval EFI_INVALID_PARAMETER The Irq is not valid. > + > +**/ > +EFI_STATUS > +EFIAPI > +Interrupt8259DisableIrq ( > + IN EFI_LEGACY_8259_PROTOCOL *This, > + IN EFI_8259_IRQ Irq > + ) > +{ > + if ((UINT32)Irq > Efi8259Irq15) { > + return EFI_INVALID_PARAMETER; > + } > + > + mProtectedModeMask = (UINT16) (mProtectedModeMask | (1 << Irq)); > + > + mProtectedModeEdgeLevel = (UINT16) (mProtectedModeEdgeLevel & ~(1 << Irq)); > + > + Interrupt8259WriteMask (mProtectedModeMask, mProtectedModeEdgeLevel); > + > + return EFI_SUCCESS; > +} > + > +/** > + Reads the PCI configuration space to get the interrupt number that is assigned to the card. > + > + @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance. > + @param[in] PciHandle PCI function for which to return the vector. > + @param[out] Vector IRQ number that corresponds to the interrupt line. > + > + @retval EFI_SUCCESS The interrupt line value was read successfully. > + > +**/ > +EFI_STATUS > +EFIAPI > +Interrupt8259GetInterruptLine ( > + IN EFI_LEGACY_8259_PROTOCOL *This, > + IN EFI_HANDLE PciHandle, > + OUT UINT8 *Vector > + ) > +{ > + EFI_PCI_IO_PROTOCOL *PciIo; > + UINT8 InterruptLine; > + EFI_STATUS Status; > + > + Status = gBS->HandleProtocol ( > + PciHandle, > + &gEfiPciIoProtocolGuid, > + (VOID **) &PciIo > + ); > + if (EFI_ERROR (Status)) { > + return EFI_INVALID_PARAMETER; > + } > + > + PciIo->Pci.Read ( > + PciIo, > + EfiPciIoWidthUint8, > + PCI_INT_LINE_OFFSET, > + 1, > + &InterruptLine > + ); > + // > + // Interrupt line is same location for standard PCI cards, standard > + // bridge and CardBus bridge. > + // > + *Vector = InterruptLine; > + > + return EFI_SUCCESS; > +} > + > +/** > + Issues the End of Interrupt (EOI) commands to PICs. > + > + @param[in] This Indicates the EFI_LEGACY_8259_PROTOCOL instance. > + @param[in] Irq The interrupt for which to issue the EOI command. > + > + @retval EFI_SUCCESS The EOI command was issued. > + @retval EFI_INVALID_PARAMETER The Irq is not valid. > + > +**/ > +EFI_STATUS > +EFIAPI > +Interrupt8259EndOfInterrupt ( > + IN EFI_LEGACY_8259_PROTOCOL *This, > + IN EFI_8259_IRQ Irq > + ) > +{ > + if ((UINT32)Irq > Efi8259Irq15) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (Irq >= Efi8259Irq8) { > + IoWrite8 (LEGACY_8259_CONTROL_REGISTER_SLAVE, LEGACY_8259_EOI); > + } > + > + IoWrite8 (LEGACY_8259_CONTROL_REGISTER_MASTER, LEGACY_8259_EOI); > + > + return EFI_SUCCESS; > +} > + > +/** > + Driver Entry point. > + > + @param[in] ImageHandle ImageHandle of the loaded driver. > + @param[in] SystemTable Pointer to the EFI System Table. > + > + @retval EFI_SUCCESS One or more of the drivers returned a success code. > + @retval !EFI_SUCCESS Error installing Legacy 8259 Protocol. > + > +**/ > +EFI_STATUS > +EFIAPI > +Install8259 ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_STATUS Status; > + EFI_8259_IRQ Irq; > + > + // > + // Initialze mask values from PCDs > + // > + mLegacyModeMask = PcdGet16 (Pcd8259LegacyModeMask); > + mLegacyModeEdgeLevel = PcdGet16 (Pcd8259LegacyModeEdgeLevel); > + > + // > + // Clear all pending interrupt > + // > + for (Irq = Efi8259Irq0; Irq <= Efi8259Irq15; Irq++) { > + Interrupt8259EndOfInterrupt (&mInterrupt8259, Irq); > + } > + > + // > + // Set the 8259 Master base to 0x68 and the 8259 Slave base to 0x70 > + // > + Status = Interrupt8259SetVectorBase (&mInterrupt8259, PROTECTED_MODE_BASE_VECTOR_MASTER, PROTECTED_MODE_BASE_VECTOR_SLAVE); > + > + // > + // Set all 8259 interrupts to edge triggered and disabled > + // > + Interrupt8259WriteMask (mProtectedModeMask, mProtectedModeEdgeLevel); > + > + // > + // Install 8259 Protocol onto a new handle > + // > + Status = gBS->InstallProtocolInterface ( > + &m8259Handle, > + &gEfiLegacy8259ProtocolGuid, > + EFI_NATIVE_INTERFACE, > + &mInterrupt8259 > + ); > + return Status; > +} > diff --git a/OvmfPkg/8259InterruptControllerDxe/Legacy8259.uni b/OvmfPkg/8259InterruptControllerDxe/Legacy8259.uni > new file mode 100644 > index 0000000000..4db40af797 > --- /dev/null > +++ b/OvmfPkg/8259InterruptControllerDxe/Legacy8259.uni > @@ -0,0 +1,22 @@ > +// /** @file > +// 8259 Interrupt Controller driver that provides Legacy 8259 protocol. > +// > +// 8259 Interrupt Controller driver that provides Legacy 8259 protocol. > +// > +// Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
> +// > +// This program and the accompanying materials > +// are licensed and made available under the terms and conditions of the BSD License > +// which accompanies this distribution. The full text of the license may be found at > +// http://opensource.org/licenses/bsd-license.php > +// > +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > +// > +// **/ > + > + > +#string STR_MODULE_ABSTRACT #language en-US "8259 Interrupt Controller driver that provides Legacy 8259 protocol" > + > +#string STR_MODULE_DESCRIPTION #language en-US "8259 Interrupt Controller driver that provides Legacy 8259 protocol." > + > diff --git a/OvmfPkg/8259InterruptControllerDxe/Legacy8259Extra.uni b/OvmfPkg/8259InterruptControllerDxe/Legacy8259Extra.uni > new file mode 100644 > index 0000000000..f3f7d26677 > --- /dev/null > +++ b/OvmfPkg/8259InterruptControllerDxe/Legacy8259Extra.uni > @@ -0,0 +1,20 @@ > +// /** @file > +// Legacy8259 Localized Strings and Content > +// > +// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
> +// > +// This program and the accompanying materials > +// are licensed and made available under the terms and conditions of the BSD License > +// which accompanies this distribution. The full text of the license may be found at > +// http://opensource.org/licenses/bsd-license.php > +// > +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > +// > +// **/ > + > +#string STR_PROPERTIES_MODULE_NAME > +#language en-US > +"Legacy 8259 Interrupt Controller DXE Driver" > + > + >