summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/VBoxPkg/E1kNetDxe/E1kHwIo.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:49:04 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:49:04 +0000
commit16f504a9dca3fe3b70568f67b7d41241ae485288 (patch)
treec60f36ada0496ba928b7161059ba5ab1ab224f9d /src/VBox/Devices/EFI/Firmware/VBoxPkg/E1kNetDxe/E1kHwIo.c
parentInitial commit. (diff)
downloadvirtualbox-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.c182
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;
+}