diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:49:04 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:49:04 +0000 |
commit | 16f504a9dca3fe3b70568f67b7d41241ae485288 (patch) | |
tree | c60f36ada0496ba928b7161059ba5ab1ab224f9d /src/VBox/Devices/EFI/Firmware/VBoxPkg/E1kNetDxe/E1kHwIo.c | |
parent | Initial commit. (diff) | |
download | virtualbox-upstream.tar.xz virtualbox-upstream.zip |
Adding upstream version 7.0.6-dfsg.upstream/7.0.6-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/VBoxPkg/E1kNetDxe/E1kHwIo.c')
-rw-r--r-- | src/VBox/Devices/EFI/Firmware/VBoxPkg/E1kNetDxe/E1kHwIo.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/VBoxPkg/E1kNetDxe/E1kHwIo.c b/src/VBox/Devices/EFI/Firmware/VBoxPkg/E1kNetDxe/E1kHwIo.c new file mode 100644 index 00000000..f203048b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/VBoxPkg/E1kNetDxe/E1kHwIo.c @@ -0,0 +1,182 @@ +/** @file + + This file implements the hardware register access functions of the e1000 driver. + + Copyright (c) 2021, Oracle and/or its affiliates.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <IndustryStandard/Pci.h> +#include <Library/UefiLib.h> +#include <Library/UefiBootServicesTableLib.h> + +#include "E1kNet.h" + +EFI_STATUS +EFIAPI +E1kNetRegWrite32 ( + IN E1K_NET_DEV *Dev, + IN UINT32 Addr, + IN UINT32 Data + ) +{ + EFI_STATUS Status; + + Status = Dev->PciIo->Io.Write ( + Dev->PciIo, + EfiPciIoWidthUint32, + PCI_BAR_IDX2, + 0, // IOADDR + 1, + &Addr + ); + if (!EFI_ERROR (Status)) + { + Status = Dev->PciIo->Io.Write ( + Dev->PciIo, + EfiPciIoWidthUint32, + PCI_BAR_IDX2, + 4, // IODATA + 1, + &Data + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +E1kNetRegRead32 ( + IN E1K_NET_DEV *Dev, + IN UINT32 Addr, + OUT UINT32 *Data + ) +{ + EFI_STATUS Status; + + Status = Dev->PciIo->Io.Write ( + Dev->PciIo, + EfiPciIoWidthUint32, + PCI_BAR_IDX2, + 0, // IOADDR + 1, + &Addr + ); + if (!EFI_ERROR (Status)) + { + return Dev->PciIo->Io.Read ( + Dev->PciIo, + EfiPciIoWidthUint32, + PCI_BAR_IDX2, + 4, // IODATA + 1, + Data + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +E1kNetRegSet32 ( + IN E1K_NET_DEV *Dev, + IN UINT32 Addr, + IN UINT32 Set) +{ + UINT32 Reg; + EFI_STATUS Status; + + Status = E1kNetRegRead32 (Dev, Addr, &Reg); + if (EFI_ERROR (Status)) { + return Status; + } + + Reg |= Set; + Status = E1kNetRegWrite32 (Dev, Addr, Reg); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +E1kNetRegClear32 ( + IN E1K_NET_DEV *Dev, + IN UINT32 Addr, + IN UINT32 Clear) +{ + UINT32 Reg; + EFI_STATUS Status; + + Status = E1kNetRegRead32 (Dev, Addr, &Reg); + if (EFI_ERROR (Status)) { + return Status; + } + + Reg &= ~Clear; + Status = E1kNetRegWrite32 (Dev, Addr, Reg); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +E1kNetDevReset ( + IN E1K_NET_DEV *Dev + ) +{ + EFI_STATUS Status; + + // + // Reset hardware + // + Status = E1kNetRegSet32 (Dev, E1K_REG_CTRL, E1K_REG_CTRL_RST); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Wait for the reset to complete + // + for (;;) + { + UINT32 Ctrl; + + Status = E1kNetRegRead32 (Dev, E1K_REG_CTRL, &Ctrl); + if (EFI_ERROR (Status)) { + return Status; + } + + /// @todo Timeout? + if (!(Ctrl & E1K_REG_CTRL_RST)) + break; + } + + // + // Reset the PHY. + // + Status = E1kNetRegSet32 (Dev, E1K_REG_CTRL, E1K_REG_CTRL_PHY_RST); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Wait for the specified amount of 3us and de-assert the PHY reset signal. + // + gBS->Stall(3); + Status = E1kNetRegClear32 (Dev, E1K_REG_CTRL, E1K_REG_CTRL_PHY_RST); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} |