* [PATCH edk2-platforms v2 0/7] Add Broadcom GENET driver for RPi4
@ 2020-05-12 7:55 Ard Biesheuvel
2020-05-12 7:55 ` [PATCH edk2-platforms v2 1/7] Platform/RaspberryPi4: set DMA translation for BCM Genet driver Ard Biesheuvel
` (9 more replies)
0 siblings, 10 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2020-05-12 7:55 UTC (permalink / raw)
To: devel
Cc: leif, philmd, Ard Biesheuvel, Pete Batard, Jared McNeill,
Andrei Warkentin, Samer El-Haj-Mahmoud, Jeremy Linton
This is a followup to Samer's v1 [0], and incorporates all the delta
changes posted for review over the past couple of days. This is a
roundup of all that work, and therefore supersedes it.
It provides an implementation of the SimpleNetworkProtocol for the
Raspberry Pi4's GENET network controller, in a way that adheres to the
UEFI driver model.
The original submission was provided by Jared, based on Jeremy's MAC
programming-only driver and the existing BSD driver for the GENET IP.
Cumulative changes and fixes as well as review feedback were provided
by all of the below.
https://github.com/ardbiesheuvel/edk2-platforms/tree/rpi4_genet_combi_v2
Cc: Pete Batard <pete@akeo.ie>
Cc: Jared McNeill <jmcneill@invisible.ca>
Cc: Andrei Warkentin <awarkentin@vmware.com>
Cc: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>
Cc: Jeremy Linton <jeremy.linton@arm.com>
Andrei Warkentin (1):
Platform/RaspberryPi4: Remove PlatformPcdLib
Ard Biesheuvel (6):
Platform/RaspberryPi4: set DMA translation for BCM Genet driver
Silicon/Broadcom: Add BcmGenetPlatformDevice protocol
Silicon/Broadcom/BcmGenetDxe: Add GENET driver
Platform/RaspberryPi4: Clean up PCDs out of the GENET driver
Platform/RaspberryPi4: Register GENET platform device protocol
Platform/RaspberryPi4: remove ASIX 88772b driver
Silicon/Broadcom/Bcm27xx/Bcm27xx.dec | 2 +
Silicon/Broadcom/Drivers/Net/BcmNet.dec | 8 +-
Platform/RaspberryPi/RPi4/RPi4.dsc | 8 +-
Platform/RaspberryPi/RPi4/RPi4.fdf | 1 -
.../RaspberryPi/AcpiTables/AcpiTables.inf | 2 +-
.../Drivers/ConfigDxe/ConfigDxe.inf | 29 +-
.../Library/PlatformPcdLib/PlatformPcdLib.inf | 43 -
.../Drivers/Net/BcmGenetDxe/BcmGenetDxe.inf | 46 +-
.../Include/IndustryStandard/Bcm2711.h | 3 +
.../Drivers/Net/BcmGenetDxe/GenericPhy.h | 106 +++
.../Drivers/Net/BcmGenetDxe/GenetUtil.h | 364 ++++++++
.../Broadcom/Drivers/Net/Include/Net/Genet.h | 21 -
.../Include/Protocol/BcmGenetPlatformDevice.h | 24 +
.../RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c | 108 ++-
.../Library/PlatformPcdLib/PlatformPcdLib.c | 45 -
.../Drivers/Net/BcmGenetDxe/ComponentName.c | 198 +++++
.../Drivers/Net/BcmGenetDxe/DriverBinding.c | 408 +++++++++
.../Drivers/Net/BcmGenetDxe/GenericPhy.c | 405 +++++++++
.../Broadcom/Drivers/Net/BcmGenetDxe/Genet.c | 114 ---
.../Drivers/Net/BcmGenetDxe/GenetUtil.c | 816 +++++++++++++++++
.../Drivers/Net/BcmGenetDxe/SimpleNetwork.c | 834 ++++++++++++++++++
Platform/RaspberryPi/AcpiTables/Dsdt.asl | 2 +-
22 files changed, 3319 insertions(+), 268 deletions(-)
delete mode 100644 Platform/RaspberryPi/Library/PlatformPcdLib/PlatformPcdLib.inf
create mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenericPhy.h
create mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenetUtil.h
delete mode 100644 Silicon/Broadcom/Drivers/Net/Include/Net/Genet.h
create mode 100644 Silicon/Broadcom/Drivers/Net/Include/Protocol/BcmGenetPlatformDevice.h
delete mode 100644 Platform/RaspberryPi/Library/PlatformPcdLib/PlatformPcdLib.c
create mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/ComponentName.c
create mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/DriverBinding.c
create mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenericPhy.c
delete mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/Genet.c
create mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenetUtil.c
create mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/SimpleNetwork.c
--
2.17.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH edk2-platforms v2 1/7] Platform/RaspberryPi4: set DMA translation for BCM Genet driver
2020-05-12 7:55 [PATCH edk2-platforms v2 0/7] Add Broadcom GENET driver for RPi4 Ard Biesheuvel
@ 2020-05-12 7:55 ` Ard Biesheuvel
2020-05-12 7:55 ` [PATCH edk2-platforms v2 2/7] Silicon/Broadcom: Add BcmGenetPlatformDevice protocol Ard Biesheuvel
` (8 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2020-05-12 7:55 UTC (permalink / raw)
To: devel; +Cc: leif, philmd, Ard Biesheuvel
The driver for the Broadcom Genet network controller will shortly
be modified from a minimal MAC address programming driver to a true
SNP driver implementing full network functionality. Since this will
involve DMA, set the DmaLib parameters correctly in the platform.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
---
Platform/RaspberryPi/RPi4/RPi4.dsc | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Platform/RaspberryPi/RPi4/RPi4.dsc b/Platform/RaspberryPi/RPi4/RPi4.dsc
index 455dd2c2ac3c..ccc9eb923436 100644
--- a/Platform/RaspberryPi/RPi4/RPi4.dsc
+++ b/Platform/RaspberryPi/RPi4/RPi4.dsc
@@ -685,6 +685,9 @@ [Components.common]
Silicon/Broadcom/Drivers/Net/BcmGenetDxe/BcmGenetDxe.inf {
<LibraryClasses>
NULL|Platform/RaspberryPi/Library/PlatformPcdLib/PlatformPcdLib.inf
+ <PcdsFixedAtBuild>
+ gEmbeddedTokenSpaceGuid.PcdDmaDeviceOffset|0x00000000
+ gEmbeddedTokenSpaceGuid.PcdDmaDeviceLimit|0xffffffff
}
#
--
2.17.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH edk2-platforms v2 2/7] Silicon/Broadcom: Add BcmGenetPlatformDevice protocol
2020-05-12 7:55 [PATCH edk2-platforms v2 0/7] Add Broadcom GENET driver for RPi4 Ard Biesheuvel
2020-05-12 7:55 ` [PATCH edk2-platforms v2 1/7] Platform/RaspberryPi4: set DMA translation for BCM Genet driver Ard Biesheuvel
@ 2020-05-12 7:55 ` Ard Biesheuvel
2020-05-12 7:55 ` [PATCH edk2-platforms v2 3/7] Silicon/Broadcom/BcmGenetDxe: Add GENET driver Ard Biesheuvel
` (7 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2020-05-12 7:55 UTC (permalink / raw)
To: devel; +Cc: leif, philmd, Ard Biesheuvel
Add BcmGenetPlatformDevice definition for GENET. This protocol
will be used to register GENET platform device that is on a
non-discoverable bus.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
---
Silicon/Broadcom/Drivers/Net/BcmNet.dec | 4 ++++
Silicon/Broadcom/Drivers/Net/Include/Protocol/BcmGenetPlatformDevice.h | 24 ++++++++++++++++++++
2 files changed, 28 insertions(+)
diff --git a/Silicon/Broadcom/Drivers/Net/BcmNet.dec b/Silicon/Broadcom/Drivers/Net/BcmNet.dec
index 4a55946e8f80..fda3caf0b4ef 100644
--- a/Silicon/Broadcom/Drivers/Net/BcmNet.dec
+++ b/Silicon/Broadcom/Drivers/Net/BcmNet.dec
@@ -1,6 +1,7 @@
## @file
#
# Copyright (c) 2020, Pete Batard <pete@akeo.ie>
+# Copyright (c) 2020, ARM Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -18,6 +19,9 @@ [Includes]
[Guids]
gBcmNetTokenSpaceGuid = {0x12b97d70, 0x9149, 0x4c2f, {0x82, 0xd5, 0xad, 0xa9, 0x1e, 0x92, 0x75, 0xa1}}
+[Protocols]
+ gBcmGenetPlatformDeviceProtocolGuid = {0x5e485a22, 0x1bb0, 0x4e22, {0x85, 0x49, 0x41, 0xfc, 0xec, 0x85, 0xdf, 0xd3}}
+
[PcdsFixedAtBuild]
gBcmNetTokenSpaceGuid.PcdBcmGenetRegistersAddress|0x0|UINT64|0x00000001
diff --git a/Silicon/Broadcom/Drivers/Net/Include/Protocol/BcmGenetPlatformDevice.h b/Silicon/Broadcom/Drivers/Net/Include/Protocol/BcmGenetPlatformDevice.h
new file mode 100644
index 000000000000..3af4f4aec622
--- /dev/null
+++ b/Silicon/Broadcom/Drivers/Net/Include/Protocol/BcmGenetPlatformDevice.h
@@ -0,0 +1,24 @@
+/** @file
+
+ Copyright (c) 2020, ARM Limited. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef BCM_GENET_PLATFORM_DEVICE_H
+#define BCM_GENET_PLATFORM_DEVICE_H
+
+#include <Uefi/UefiBaseType.h>
+
+#define BCM_GENET_PLATFORM_DEVICE_PROTOCOL_GUID \
+ {0x5e485a22, 0x1bb0, 0x4e22, {0x85, 0x49, 0x41, 0xfc, 0xec, 0x85, 0xdf, 0xd3}}
+
+typedef struct {
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ EFI_MAC_ADDRESS MacAddress;
+} BCM_GENET_PLATFORM_DEVICE_PROTOCOL;
+
+extern EFI_GUID gBcmGenetPlatformDeviceProtocolGuid;
+
+#endif
--
2.17.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH edk2-platforms v2 3/7] Silicon/Broadcom/BcmGenetDxe: Add GENET driver
2020-05-12 7:55 [PATCH edk2-platforms v2 0/7] Add Broadcom GENET driver for RPi4 Ard Biesheuvel
2020-05-12 7:55 ` [PATCH edk2-platforms v2 1/7] Platform/RaspberryPi4: set DMA translation for BCM Genet driver Ard Biesheuvel
2020-05-12 7:55 ` [PATCH edk2-platforms v2 2/7] Silicon/Broadcom: Add BcmGenetPlatformDevice protocol Ard Biesheuvel
@ 2020-05-12 7:55 ` Ard Biesheuvel
2020-05-12 14:31 ` [edk2-devel] " Leif Lindholm
2020-05-12 7:55 ` [PATCH edk2-platforms v2 4/7] Platform/RaspberryPi4: Clean up PCDs out of the " Ard Biesheuvel
` (6 subsequent siblings)
9 siblings, 1 reply; 13+ messages in thread
From: Ard Biesheuvel @ 2020-05-12 7:55 UTC (permalink / raw)
To: devel; +Cc: leif, philmd, Ard Biesheuvel
Add support for the Broadcom GENET v5 ethernet controller
for the Raspberry Pi 4 (BCM2711)
Co-authored-by: Jared McNeill <jmcneill@invisible.ca>
Co-authored-by: Andrei Warkentin <awarkentin@vmware.com>
Co-authored-by: Samer El-Haj-Mahmoud <samer.el-haj-mahmoud@arm.com>
Co-authored-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
---
Silicon/Broadcom/Drivers/Net/BcmGenetDxe/BcmGenetDxe.inf | 46 +-
Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenericPhy.h | 106 +++
Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenetUtil.h | 364 +++++++++
Silicon/Broadcom/Drivers/Net/BcmGenetDxe/ComponentName.c | 198 +++++
Silicon/Broadcom/Drivers/Net/BcmGenetDxe/DriverBinding.c | 408 ++++++++++
Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenericPhy.c | 405 ++++++++++
Silicon/Broadcom/Drivers/Net/BcmGenetDxe/Genet.c | 114 ---
Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenetUtil.c | 816 +++++++++++++++++++
Silicon/Broadcom/Drivers/Net/BcmGenetDxe/SimpleNetwork.c | 834 ++++++++++++++++++++
9 files changed, 3164 insertions(+), 127 deletions(-)
diff --git a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/BcmGenetDxe.inf b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/BcmGenetDxe.inf
index 9e9301608f24..3e98983c6b07 100644
--- a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/BcmGenetDxe.inf
+++ b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/BcmGenetDxe.inf
@@ -1,40 +1,60 @@
## @file
+# Component description file for Broadcom GENET driver.
#
+# Copyright (c) 2020, Jared McNeill All rights reserved.<BR>
# Copyright (c) 2020, Jeremy Linton All rights reserved.<BR>
+# Copyright (c) 2020, ARM Limited. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
- INF_VERSION = 0x0001001A
+ INF_VERSION = 1.27
BASE_NAME = BcmGenetDxe
FILE_GUID = e2b1eaf3-50b7-4ae1-b79e-ec8020cb57ac
- MODULE_TYPE = DXE_DRIVER
- VERSION_STRING = 0.1
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
ENTRY_POINT = GenetEntryPoint
+ UNLOAD_IMAGE = GenetUnload
[Sources]
- Genet.c
+ ComponentName.c
+ DriverBinding.c
+ GenericPhy.c
+ GenericPhy.h
+ GenetUtil.c
+ GenetUtil.h
+ SimpleNetwork.c
[Packages]
- ArmPkg/ArmPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
MdeModulePkg/MdeModulePkg.dec
MdePkg/MdePkg.dec
+ NetworkPkg/NetworkPkg.dec
Silicon/Broadcom/Drivers/Net/BcmNet.dec
[LibraryClasses]
- ArmLib
BaseLib
+ BaseMemoryLib
+ DebugLib
+ DevicePathLib
+ DmaLib
IoLib
+ MemoryAllocationLib
+ NetLib
+ UefiBootServicesTableLib
UefiDriverEntryPoint
UefiLib
+[Protocols]
+ gBcmGenetPlatformDeviceProtocolGuid ## TO_START
+ gEfiDevicePathProtocolGuid ## BY_START
+ gEfiSimpleNetworkProtocolGuid ## BY_START
+
+[Guids]
+ gEfiEventExitBootServicesGuid
+
[FixedPcd]
- gBcmNetTokenSpaceGuid.PcdBcmGenetRegistersAddress
-
-[Pcd]
- gBcmNetTokenSpaceGuid.PcdBcmGenetMacAddress
-
-[Depex]
- TRUE
+ gEmbeddedTokenSpaceGuid.PcdDmaDeviceOffset
+ gEmbeddedTokenSpaceGuid.PcdDmaDeviceLimit
diff --git a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenericPhy.h b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenericPhy.h
new file mode 100644
index 000000000000..58b52722b4e3
--- /dev/null
+++ b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenericPhy.h
@@ -0,0 +1,106 @@
+/** @file
+
+ Copyright (c) 2020 Jared McNeill. All rights reserved.
+ Copyright (c) 2020 Andrey Warkentin <andrey.warkentin@gmail.com>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef GENERICPHY_H__
+#define GENERICPHY_H__
+
+#define GENERIC_PHY_BMCR 0x00
+#define GENERIC_PHY_BMCR_RESET BIT15
+#define GENERIC_PHY_BMCR_ANE BIT12
+#define GENERIC_PHY_BMCR_RESTART_AN BIT9
+#define GENERIC_PHY_BMSR 0x01
+#define GENERIC_PHY_BMSR_ANEG_COMPLETE BIT5
+#define GENERIC_PHY_BMSR_LINK_STATUS BIT2
+#define GENERIC_PHY_PHYIDR1 0x02
+#define GENERIC_PHY_PHYIDR2 0x03
+#define GENERIC_PHY_ANAR 0x04
+#define GENERIC_PHY_ANAR_100BASETX_FDX BIT8
+#define GENERIC_PHY_ANAR_100BASETX BIT7
+#define GENERIC_PHY_ANAR_10BASET_FDX BIT6
+#define GENERIC_PHY_ANAR_10BASET BIT5
+#define GENERIC_PHY_ANLPAR 0x05
+#define GENERIC_PHY_GBCR 0x09
+#define GENERIC_PHY_GBCR_1000BASET_FDX BIT9
+#define GENERIC_PHY_GBCR_1000BASET BIT8
+#define GENERIC_PHY_GBSR 0x0A
+
+typedef enum {
+ PHY_SPEED_NONE = 0,
+ PHY_SPEED_10 = 10,
+ PHY_SPEED_100 = 100,
+ PHY_SPEED_1000 = 1000
+} GENERIC_PHY_SPEED;
+
+typedef enum {
+ PHY_DUPLEX_HALF,
+ PHY_DUPLEX_FULL
+} GENERIC_PHY_DUPLEX;
+
+typedef
+EFI_STATUS
+(EFIAPI *GENERIC_PHY_READ) (
+ IN VOID *Priv,
+ IN UINT8 PhyAddr,
+ IN UINT8 Reg,
+ OUT UINT16 * Data
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *GENERIC_PHY_WRITE) (
+ IN VOID *Priv,
+ IN UINT8 PhyAddr,
+ IN UINT8 Reg,
+ IN UINT16 Data
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *GENERIC_PHY_RESET_ACTION) (
+ IN VOID *Priv
+ );
+
+typedef
+VOID
+(EFIAPI *GENERIC_PHY_CONFIGURE) (
+ IN VOID *Priv,
+ IN GENERIC_PHY_SPEED Speed,
+ IN GENERIC_PHY_DUPLEX Duplex
+ );
+
+typedef struct {
+ GENERIC_PHY_READ Read;
+ GENERIC_PHY_WRITE Write;
+ GENERIC_PHY_RESET_ACTION ResetAction;
+ GENERIC_PHY_CONFIGURE Configure;
+ VOID *PrivateData;
+
+ UINT8 PhyAddr;
+ BOOLEAN LinkUp;
+} GENERIC_PHY_PRIVATE_DATA;
+
+EFI_STATUS
+EFIAPI
+GenericPhyInit (
+ IN GENERIC_PHY_PRIVATE_DATA *Phy
+ );
+
+EFI_STATUS
+EFIAPI
+GenericPhyUpdateConfig (
+ IN GENERIC_PHY_PRIVATE_DATA *Phy
+ );
+
+EFI_STATUS
+EFIAPI
+GenericPhyReset (
+ IN GENERIC_PHY_PRIVATE_DATA *Phy
+ );
+
+#endif // GENERICPHY_H__
diff --git a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenetUtil.h b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenetUtil.h
new file mode 100644
index 000000000000..5ae2e0bad273
--- /dev/null
+++ b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenetUtil.h
@@ -0,0 +1,364 @@
+/** @file
+
+ Copyright (c) 2020 Jared McNeill <jmcneill@invisible.ca>
+ Copyright (c) 2020, ARM Limited. All rights reserved.
+ Copyright (c) 2020 Andrey Warkentin <andrey.warkentin@gmail.com>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef GENET_UTIL_H__
+#define GENET_UTIL_H__
+
+#include <Uefi.h>
+
+#include <Protocol/DriverSupportedEfiVersion.h>
+#include <Protocol/BcmGenetPlatformDevice.h>
+#include <Protocol/SimpleNetwork.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PcdLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NetLib.h>
+#include <Library/UefiLib.h>
+
+#include "GenericPhy.h"
+
+/*
+ * Aux control shadow register, bits 0-2 select function (0x00 to
+ * 0x07).
+ */
+#define BRGPHY_MII_AUXCTL 0x18 /* AUX control */
+#define BRGPHY_AUXCTL_SHADOW_MISC 0x07
+#define BRGPHY_AUXCTL_MISC_DATA_MASK 0x7ff8
+#define BRGPHY_AUXCTL_MISC_READ_SHIFT 12
+#define BRGPHY_AUXCTL_MISC_WRITE_EN 0x8000
+#define BRGPHY_AUXCTL_MISC_RGMII_SKEW_EN 0x0200
+
+/*
+ * Shadow register 0x1C, bit 15 is write enable,
+ * bits 14-10 select function (0x00 to 0x1F).
+ */
+#define BRGPHY_MII_SHADOW_1C 0x1C
+#define BRGPHY_SHADOW_1C_WRITE_EN 0x8000
+#define BRGPHY_SHADOW_1C_SELECT_MASK 0x7C00
+#define BRGPHY_SHADOW_1C_DATA_MASK 0x03FF
+
+/* Shadow 0x1C Clock Alignment Control Register (select value 0x03) */
+#define BRGPHY_SHADOW_1C_CLK_CTRL (0x03 << 10)
+#define BRGPHY_SHADOW_1C_GTXCLK_EN 0x0200
+
+#define MAX_ETHERNET_PKT_SIZE 1500
+
+#define GENET_VERSION 0x0a
+#define GENET_MAX_PACKET_SIZE 1536
+
+#define GENET_SYS_REV_CTRL 0x000
+#define SYS_REV_MAJOR (BIT27|BIT26|BIT25|BIT24)
+#define SYS_REV_MINOR (BIT19|BIT18|BIT17|BIT16)
+#define GENET_SYS_PORT_CTRL 0x004
+#define GENET_SYS_PORT_MODE_EXT_GPHY 3
+#define GENET_SYS_RBUF_FLUSH_CTRL 0x008
+#define GENET_SYS_RBUF_FLUSH_RESET BIT1
+#define GENET_SYS_TBUF_FLUSH_CTRL 0x00c
+#define GENET_EXT_RGMII_OOB_CTRL 0x08c
+#define GENET_EXT_RGMII_OOB_ID_MODE_DISABLE BIT16
+#define GENET_EXT_RGMII_OOB_RGMII_MODE_EN BIT6
+#define GENET_EXT_RGMII_OOB_OOB_DISABLE BIT5
+#define GENET_EXT_RGMII_OOB_RGMII_LINK BIT4
+#define GENET_INTRL2_CPU_STAT 0x200
+#define GENET_INTRL2_CPU_CLEAR 0x208
+#define GENET_INTRL2_CPU_STAT_MASK 0x20c
+#define GENET_INTRL2_CPU_SET_MASK 0x210
+#define GENET_INTRL2_CPU_CLEAR_MASK 0x214
+#define GENET_IRQ_MDIO_ERROR BIT24
+#define GENET_IRQ_MDIO_DONE BIT23
+#define GENET_IRQ_TXDMA_DONE BIT16
+#define GENET_IRQ_RXDMA_DONE BIT13
+#define GENET_RBUF_CTRL 0x300
+#define GENET_RBUF_BAD_DIS BIT2
+#define GENET_RBUF_ALIGN_2B BIT1
+#define GENET_RBUF_64B_EN BIT0
+#define GENET_RBUF_TBUF_SIZE_CTRL 0x3b4
+#define GENET_UMAC_CMD 0x808
+#define GENET_UMAC_CMD_LCL_LOOP_EN BIT15
+#define GENET_UMAC_CMD_SW_RESET BIT13
+#define GENET_UMAC_CMD_HD_EN BIT10
+#define GENET_UMAC_CMD_PROMISC BIT4
+#define GENET_UMAC_CMD_SPEED (BIT3|BIT2)
+#define GENET_UMAC_CMD_SPEED_10 0
+#define GENET_UMAC_CMD_SPEED_100 1
+#define GENET_UMAC_CMD_SPEED_1000 2
+#define GENET_UMAC_CMD_RXEN BIT1
+#define GENET_UMAC_CMD_TXEN BIT0
+#define GENET_UMAC_MAC0 0x80c
+#define GENET_UMAC_MAC1 0x810
+#define GENET_UMAC_MAX_FRAME_LEN 0x814
+#define GENET_UMAC_TX_FLUSH 0xb34
+#define GENET_UMAC_MIB_CTRL 0xd80
+#define GENET_UMAC_MIB_RESET_TX BIT2
+#define GENET_UMAC_MIB_RESET_RUNT BIT1
+#define GENET_UMAC_MIB_RESET_RX BIT0
+#define GENET_MDIO_CMD 0xe14
+#define GENET_MDIO_START_BUSY BIT29
+#define GENET_MDIO_READ BIT27
+#define GENET_MDIO_WRITE BIT26
+#define GENET_MDIO_PMD (BIT25|BIT24|BIT23|BIT22|BIT21)
+#define GENET_MDIO_REG (BIT20|BIT19|BIT18|BIT17|BIT16)
+#define GENET_UMAC_MDF_CTRL 0xe50
+#define GENET_UMAC_MDF_ADDR0(n) (0xe54 + (n) * 0x8)
+#define GENET_UMAC_MDF_ADDR1(n) (0xe58 + (n) * 0x8)
+#define GENET_MAX_MDF_FILTER 17
+
+#define GENET_DMA_DESC_COUNT 256
+#define GENET_DMA_DESC_SIZE 12
+#define GENET_DMA_DEFAULT_QUEUE 16
+
+#define GENET_DMA_RING_SIZE 0x40
+#define GENET_DMA_RINGS_SIZE (GENET_DMA_RING_SIZE * (GENET_DMA_DEFAULT_QUEUE + 1))
+
+#define GENET_RX_BASE 0x2000
+#define GENET_TX_BASE 0x4000
+
+#define GENET_RX_DMA_RINGBASE(qid) (GENET_RX_BASE + 0xc00 + GENET_DMA_RING_SIZE * (qid))
+#define GENET_RX_DMA_WRITE_PTR_LO(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x00)
+#define GENET_RX_DMA_WRITE_PTR_HI(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x04)
+#define GENET_RX_DMA_PROD_INDEX(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x08)
+#define GENET_RX_DMA_CONS_INDEX(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x0c)
+#define GENET_RX_DMA_RING_BUF_SIZE(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x10)
+#define GENET_RX_DMA_RING_BUF_SIZE_DESC_COUNT 0xffff0000
+#define GENET_RX_DMA_RING_BUF_SIZE_BUF_LENGTH 0x0000ffff
+#define GENET_RX_DMA_START_ADDR_LO(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x14)
+#define GENET_RX_DMA_START_ADDR_HI(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x18)
+#define GENET_RX_DMA_END_ADDR_LO(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x1c)
+#define GENET_RX_DMA_END_ADDR_HI(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x20)
+#define GENET_RX_DMA_XON_XOFF_THRES(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x28)
+#define GENET_RX_DMA_XON_XOFF_THRES_LO 0xffff0000
+#define GENET_RX_DMA_XON_XOFF_THRES_HI 0x0000ffff
+#define GENET_RX_DMA_READ_PTR_LO(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x2c)
+#define GENET_RX_DMA_READ_PTR_HI(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x30)
+
+#define GENET_TX_DMA_RINGBASE(qid) (GENET_TX_BASE + 0xc00 + GENET_DMA_RING_SIZE * (qid))
+#define GENET_TX_DMA_READ_PTR_LO(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x00)
+#define GENET_TX_DMA_READ_PTR_HI(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x04)
+#define GENET_TX_DMA_CONS_INDEX(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x08)
+#define GENET_TX_DMA_PROD_INDEX(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x0c)
+#define GENET_TX_DMA_RING_BUF_SIZE(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x10)
+#define GENET_TX_DMA_RING_BUF_SIZE_DESC_COUNT 0xffff0000
+#define GENET_TX_DMA_RING_BUF_SIZE_BUF_LENGTH 0x0000ffff
+#define GENET_TX_DMA_START_ADDR_LO(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x14)
+#define GENET_TX_DMA_START_ADDR_HI(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x18)
+#define GENET_TX_DMA_END_ADDR_LO(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x1c)
+#define GENET_TX_DMA_END_ADDR_HI(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x20)
+#define GENET_TX_DMA_MBUF_DONE_THRES(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x24)
+#define GENET_TX_DMA_FLOW_PERIOD(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x28)
+#define GENET_TX_DMA_WRITE_PTR_LO(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x2c)
+#define GENET_TX_DMA_WRITE_PTR_HI(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x30)
+
+#define GENET_RX_DESC_STATUS(idx) (GENET_RX_BASE + GENET_DMA_DESC_SIZE * (idx) + 0x00)
+#define GENET_RX_DESC_STATUS_BUFLEN (BIT27|BIT26|BIT25|BIT24|BIT23|BIT22|BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)
+#define GENET_RX_DESC_STATUS_OWN BIT15
+#define GENET_RX_DESC_STATUS_EOP BIT14
+#define GENET_RX_DESC_STATUS_SOP BIT13
+#define GENET_RX_DESC_STATUS_RX_ERROR BIT2
+#define GENET_RX_DESC_ADDRESS_LO(idx) (GENET_RX_BASE + GENET_DMA_DESC_SIZE * (idx) + 0x04)
+#define GENET_RX_DESC_ADDRESS_HI(idx) (GENET_RX_BASE + GENET_DMA_DESC_SIZE * (idx) + 0x08)
+
+#define GENET_TX_DESC_STATUS(idx) (GENET_TX_BASE + GENET_DMA_DESC_SIZE * (idx) + 0x00)
+#define GENET_TX_DESC_STATUS_BUFLEN (BIT27|BIT26|BIT25|BIT24|BIT23|BIT22|BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)
+#define GENET_TX_DESC_STATUS_OWN BIT15
+#define GENET_TX_DESC_STATUS_EOP BIT14
+#define GENET_TX_DESC_STATUS_SOP BIT13
+#define GENET_TX_DESC_STATUS_QTAG (BIT12|BIT11|BIT10|BIT9|BIT8|BIT7)
+#define GENET_TX_DESC_STATUS_CRC BIT6
+#define GENET_TX_DESC_ADDRESS_LO(idx) (GENET_TX_BASE + GENET_DMA_DESC_SIZE * (idx) + 0x04)
+#define GENET_TX_DESC_ADDRESS_HI(idx) (GENET_TX_BASE + GENET_DMA_DESC_SIZE * (idx) + 0x08)
+
+#define GENET_RX_DMA_RING_CFG (GENET_RX_BASE + 0x1040 + 0x00)
+#define GENET_RX_DMA_CTRL (GENET_RX_BASE + 0x1040 + 0x04)
+#define GENET_RX_DMA_CTRL_RBUF_EN(qid) (BIT1 << (qid))
+#define GENET_RX_DMA_CTRL_EN BIT0
+#define GENET_RX_SCB_BURST_SIZE (GENET_RX_BASE + 0x1040 + 0x0c)
+
+#define GENET_TX_DMA_RING_CFG (GENET_TX_BASE + 0x1040 + 0x00)
+#define GENET_TX_DMA_CTRL (GENET_TX_BASE + 0x1040 + 0x04)
+#define GENET_TX_DMA_CTRL_RBUF_EN(qid) (BIT1 << (qid))
+#define GENET_TX_DMA_CTRL_EN BIT0
+#define GENET_TX_SCB_BURST_SIZE (GENET_TX_BASE + 0x1040 + 0x0c)
+
+typedef struct {
+ EFI_PHYSICAL_ADDRESS PhysAddress;
+ VOID * Mapping;
+} GENET_MAP_INFO;
+
+typedef enum {
+ GENET_PHY_MODE_MII,
+ GENET_PHY_MODE_RGMII,
+ GENET_PHY_MODE_RGMII_RXID,
+ GENET_PHY_MODE_RGMII_TXID,
+ GENET_PHY_MODE_RGMII_ID,
+} GENET_PHY_MODE;
+
+typedef struct {
+ UINT32 Signature;
+ EFI_HANDLE ControllerHandle;
+
+ EFI_LOCK Lock;
+ EFI_EVENT ExitBootServicesEvent;
+
+ EFI_SIMPLE_NETWORK_PROTOCOL Snp;
+ EFI_SIMPLE_NETWORK_MODE SnpMode;
+
+ BCM_GENET_PLATFORM_DEVICE_PROTOCOL *Dev;
+
+ GENERIC_PHY_PRIVATE_DATA Phy;
+
+ UINT8 *TxBuffer[GENET_DMA_DESC_COUNT];
+ VOID *TxBufferMap[GENET_DMA_DESC_COUNT];
+ UINT8 TxQueued;
+ UINT16 TxNext;
+ UINT16 TxConsIndex;
+ UINT16 TxProdIndex;
+
+ EFI_PHYSICAL_ADDRESS RxBuffer;
+ GENET_MAP_INFO RxBufferMap[GENET_DMA_DESC_COUNT];
+ UINT16 RxConsIndex;
+ UINT16 RxProdIndex;
+
+ GENET_PHY_MODE PhyMode;
+
+ UINTN RegBase;
+} GENET_PRIVATE_DATA;
+
+extern EFI_COMPONENT_NAME_PROTOCOL gGenetComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gGenetComponentName2;
+
+extern CONST EFI_SIMPLE_NETWORK_PROTOCOL gGenetSimpleNetworkTemplate;
+
+#define GENET_DRIVER_SIGNATURE SIGNATURE_32('G', 'N', 'E', 'T')
+#define GENET_PRIVATE_DATA_FROM_SNP_THIS(a) CR(a, GENET_PRIVATE_DATA, Snp, GENET_DRIVER_SIGNATURE)
+
+#define GENET_RX_BUFFER(g, idx) ((UINT8 *)(UINTN)(g)->RxBuffer + GENET_MAX_PACKET_SIZE * (idx))
+
+EFI_STATUS
+EFIAPI
+GenetPhyRead (
+ IN VOID *Priv,
+ IN UINT8 PhyAddr,
+ IN UINT8 Reg,
+ OUT UINT16 *Data
+ );
+
+EFI_STATUS
+EFIAPI
+GenetPhyWrite (
+ IN VOID *Priv,
+ IN UINT8 PhyAddr,
+ IN UINT8 Reg,
+ IN UINT16 Data
+ );
+
+EFI_STATUS
+EFIAPI
+GenetPhyResetAction (
+ IN VOID *Priv
+ );
+
+VOID
+EFIAPI
+GenetPhyConfigure (
+ IN VOID *Priv,
+ IN GENERIC_PHY_SPEED Speed,
+ IN GENERIC_PHY_DUPLEX Duplex
+ );
+
+VOID
+GenetReset (
+ IN GENET_PRIVATE_DATA *Genet
+ );
+
+VOID
+EFIAPI
+GenetSetMacAddress (
+ IN GENET_PRIVATE_DATA *Genet,
+ IN EFI_MAC_ADDRESS *MacAddr
+ );
+
+VOID
+GenetSetPhyMode (
+ IN GENET_PRIVATE_DATA *Genet,
+ IN GENET_PHY_MODE PhyMode
+ );
+
+VOID
+GenetEnableTxRx (
+ IN GENET_PRIVATE_DATA *Genet
+ );
+
+VOID
+GenetDisableTxRx (
+ IN GENET_PRIVATE_DATA *Genet
+ );
+
+VOID
+GenetSetPromisc (
+ IN GENET_PRIVATE_DATA *Genet,
+ IN BOOLEAN Enable
+ );
+
+VOID
+GenetEnableBroadcastFilter (
+ IN GENET_PRIVATE_DATA *Genet,
+ IN BOOLEAN Enable
+ );
+
+VOID
+GenetDmaInitRings (
+ IN GENET_PRIVATE_DATA *Genet
+ );
+
+EFI_STATUS
+GenetDmaAlloc (
+ IN GENET_PRIVATE_DATA *Genet
+ );
+
+VOID
+GenetDmaFree (
+ IN GENET_PRIVATE_DATA *Genet
+ );
+
+VOID
+GenetDmaTriggerTx (
+ IN GENET_PRIVATE_DATA *Genet,
+ IN UINT8 DescIndex,
+ IN EFI_PHYSICAL_ADDRESS PhysAddr,
+ IN UINTN NumberOfBytes
+ );
+
+EFI_STATUS
+GenetDmaMapRxDescriptor (
+ IN GENET_PRIVATE_DATA *Genet,
+ IN UINT8 DescIndex
+ );
+
+VOID
+GenetDmaUnmapRxDescriptor (
+ IN GENET_PRIVATE_DATA *Genet,
+ IN UINT8 DescIndex
+ );
+
+VOID
+GenetTxIntr (
+ IN GENET_PRIVATE_DATA *Genet,
+ OUT VOID **TxBuf
+ );
+
+EFI_STATUS
+GenetRxIntr (
+ IN GENET_PRIVATE_DATA *Genet,
+ OUT UINT8 *DescIndex,
+ OUT UINTN *FrameLength
+ );
+
+#endif /* GENET_UTIL_H__ */
diff --git a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/ComponentName.c b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/ComponentName.c
new file mode 100644
index 000000000000..b4b8896593f3
--- /dev/null
+++ b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/ComponentName.c
@@ -0,0 +1,198 @@
+/** @file
+ UEFI Component Name(2) protocol implementation for GENET UEFI driver.
+
+ Copyright (c) 2020 Jared McNeill. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "GenetUtil.h"
+
+STATIC EFI_UNICODE_STRING_TABLE mGenetDriverNameTable[] = {
+ {
+ "eng;en",
+ L"Broadcom GENET Ethernet Driver"
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+STATIC EFI_UNICODE_STRING_TABLE mGenetDeviceNameTable[] = {
+ {
+ "eng;en",
+ L"Broadcom GENET Ethernet"
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GenetComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (Language,
+ This->SupportedLanguages,
+ mGenetDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gGenetComponentName2)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GenetComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return LookupUnicodeString2 (Language,
+ This->SupportedLanguages,
+ mGenetDeviceNameTable,
+ ControllerName,
+ (BOOLEAN)(This == &gGenetComponentName2)
+ );
+}
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME_PROTOCOL gGenetComponentName = {
+ (EFI_COMPONENT_NAME_GET_DRIVER_NAME) GenetComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME_GET_CONTROLLER_NAME) GenetComponentNameGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME2_PROTOCOL gGenetComponentName2 = {
+ GenetComponentNameGetDriverName,
+ GenetComponentNameGetControllerName,
+ "en"
+};
diff --git a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/DriverBinding.c b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/DriverBinding.c
new file mode 100644
index 000000000000..57f2fb17cb17
--- /dev/null
+++ b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/DriverBinding.c
@@ -0,0 +1,408 @@
+/** @file
+ Device driver for the Broadcom GENET controller
+
+ Copyright (c) 2020 Jared McNeill. All rights reserved.
+ Copyright (c) 2020, ARM Limited. All rights reserved.
+ Copyright (c) 2020 Andrey Warkentin <andrey.warkentin@gmail.com>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include <Protocol/BcmGenetPlatformDevice.h>
+
+#include "GenetUtil.h"
+
+/**
+ Tests to see if this driver supports a given controller.
+
+ @param This[in] A pointer to the EFI_DRIVER_BINDING_PROTOCOL
+ instance.
+ @param ControllerHandle[in] The handle of the controller to test.
+ @param RemainingDevicePath[in] The remaining device path.
+ (Ignored - this is not a bus driver.)
+
+ @retval EFI_SUCCESS The driver supports this controller.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle is
+ already being managed by the driver specified
+ by This.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle is
+ not supported by the driver specified by This.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GenetDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ BCM_GENET_PLATFORM_DEVICE_PROTOCOL *Dev;
+ EFI_STATUS Status;
+
+ //
+ // Connect to the non-discoverable device
+ //
+ Status = gBS->OpenProtocol (ControllerHandle,
+ &gBcmGenetPlatformDeviceProtocolGuid,
+ (VOID **)&Dev,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Clean up.
+ //
+ gBS->CloseProtocol (ControllerHandle,
+ &gBcmGenetPlatformDeviceProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Callback function to shut down the network device at ExitBootServices
+
+ @param Event Pointer to this event
+ @param Context Event handler private data
+
+**/
+STATIC
+VOID
+EFIAPI
+GenetNotifyExitBootServices (
+ EFI_EVENT Event,
+ VOID *Context
+ )
+{
+ GenetDisableTxRx ((GENET_PRIVATE_DATA *)Context);
+}
+
+/**
+ Starts a device controller or a bus controller.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL
+ instance.
+ @param[in] ControllerHandle The handle of the device to start. This
+ handle must support a protocol interface that
+ supplies an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath The remaining portion of the device path.
+ (Ignored - this is not a bus driver.)
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a
+ device error.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GenetDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ GENET_PRIVATE_DATA *Genet;
+ EFI_STATUS Status;
+
+ // Allocate Resources
+ Genet = AllocateZeroPool (sizeof (GENET_PRIVATE_DATA));
+ if (Genet == NULL) {
+ DEBUG ((DEBUG_ERROR,
+ "%a: Couldn't allocate private data\n", __FUNCTION__));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = gBS->OpenProtocol (ControllerHandle,
+ &gBcmGenetPlatformDeviceProtocolGuid,
+ (VOID **)&Genet->Dev,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR,
+ "%a: Couldn't open protocol: %r\n", __FUNCTION__, Status));
+ goto FreeDevice;
+ }
+
+ Status = GenetDmaAlloc (Genet);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR,
+ "%a: Couldn't allocate DMA buffers: %r\n", __FUNCTION__, Status));
+ goto FreeDevice;
+ }
+
+ Genet->Signature = GENET_DRIVER_SIGNATURE;
+ Genet->RegBase = Genet->Dev->BaseAddress;
+ Genet->Phy.PrivateData = Genet;
+ Genet->Phy.Read = GenetPhyRead;
+ Genet->Phy.Write = GenetPhyWrite;
+ Genet->Phy.Configure = GenetPhyConfigure;
+ Genet->Phy.ResetAction = GenetPhyResetAction;
+ Genet->PhyMode = GENET_PHY_MODE_RGMII_RXID;
+
+ EfiInitializeLock (&Genet->Lock, TPL_CALLBACK);
+ CopyMem (&Genet->Snp, &gGenetSimpleNetworkTemplate, sizeof Genet->Snp);
+
+ Genet->Snp.Mode = &Genet->SnpMode;
+ Genet->SnpMode.State = EfiSimpleNetworkStopped;
+ Genet->SnpMode.HwAddressSize = NET_ETHER_ADDR_LEN;
+ Genet->SnpMode.MediaHeaderSize = sizeof (ETHER_HEAD);
+ Genet->SnpMode.MaxPacketSize = MAX_ETHERNET_PKT_SIZE;
+ Genet->SnpMode.NvRamSize = 0;
+ Genet->SnpMode.NvRamAccessSize = 0;
+ Genet->SnpMode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
+ EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
+ EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
+ Genet->SnpMode.ReceiveFilterSetting = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
+ EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
+ Genet->SnpMode.MaxMCastFilterCount = 0;
+ Genet->SnpMode.MCastFilterCount = 0;
+ Genet->SnpMode.IfType = NET_IFTYPE_ETHERNET;
+ Genet->SnpMode.MacAddressChangeable = TRUE;
+ Genet->SnpMode.MultipleTxSupported = FALSE;
+ Genet->SnpMode.MediaPresentSupported = TRUE;
+ Genet->SnpMode.MediaPresent = FALSE;
+
+ SetMem (&Genet->SnpMode.BroadcastAddress, sizeof (EFI_MAC_ADDRESS), 0xff);
+
+ CopyMem (&Genet->SnpMode.PermanentAddress, &Genet->Dev->MacAddress,
+ sizeof(EFI_MAC_ADDRESS));
+ CopyMem (&Genet->SnpMode.CurrentAddress, &Genet->Dev->MacAddress,
+ sizeof(EFI_MAC_ADDRESS));
+
+ Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
+ GenetNotifyExitBootServices, Genet,
+ &gEfiEventExitBootServicesGuid,
+ &Genet->ExitBootServicesEvent);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN,
+ "GenetDriverBindingStart: failed to register for ExitBootServices event - %r\n",
+ Status));
+ goto FreeDevice;
+ }
+
+ Status = gBS->InstallMultipleProtocolInterfaces (&ControllerHandle,
+ &gEfiSimpleNetworkProtocolGuid, &Genet->Snp,
+ NULL);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR,
+ "%a: Couldn't install protocol interfaces: %r\n", __FUNCTION__, Status));
+ gBS->CloseProtocol (ControllerHandle,
+ &gBcmGenetPlatformDeviceProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle);
+ goto FreeEvent;
+ }
+
+ Genet->ControllerHandle = ControllerHandle;
+ return EFI_SUCCESS;
+
+FreeEvent:
+ gBS->CloseEvent (Genet->ExitBootServicesEvent);
+FreeDevice:
+ DEBUG ((DEBUG_WARN, "%a: Returning %r\n", __FUNCTION__, Status));
+ FreePool (Genet);
+ return Status;
+}
+
+
+/**
+ Stops a device controller or a bus controller.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL
+ instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle
+ must support a bus specific I/O protocol for the
+ driver to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in
+ ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be
+ NULL if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device
+ error.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GenetDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ )
+{
+ EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol;
+ GENET_PRIVATE_DATA *Genet;
+ EFI_STATUS Status;
+
+ Status = gBS->HandleProtocol (ControllerHandle,
+ &gEfiSimpleNetworkProtocolGuid,
+ (VOID **)&SnpProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Genet = GENET_PRIVATE_DATA_FROM_SNP_THIS (SnpProtocol);
+
+ ASSERT (Genet->ControllerHandle == ControllerHandle);
+
+ Status = gBS->UninstallProtocolInterface (ControllerHandle,
+ &gEfiSimpleNetworkProtocolGuid,
+ &Genet->Snp
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->CloseEvent (Genet->ExitBootServicesEvent);
+ ASSERT_EFI_ERROR (Status);
+
+ GenetDmaFree (Genet);
+
+ Status = gBS->CloseProtocol (ControllerHandle,
+ &gBcmGenetPlatformDeviceProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ FreePool (Genet);
+
+ return EFI_SUCCESS;
+}
+
+STATIC EFI_DRIVER_BINDING_PROTOCOL mGenetDriverBinding = {
+ GenetDriverBindingSupported,
+ GenetDriverBindingStart,
+ GenetDriverBindingStop,
+ GENET_VERSION,
+ NULL,
+ NULL
+};
+
+/**
+ The entry point of GENET UEFI Driver.
+
+ @param ImageHandle The image handle of the UEFI Driver.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The Driver or UEFI Driver exited normally.
+ @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater than
+ SystemTable->Hdr.Revision.
+
+**/
+EFI_STATUS
+EFIAPI
+GenetEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &mGenetDriverBinding,
+ ImageHandle,
+ &gGenetComponentName,
+ &gGenetComponentName2
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INIT | DEBUG_INFO, "Installed GENET UEFI driver!\n"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Unload function of GENET UEFI Driver.
+
+ @param ImageHandle The allocated handle for the EFI image
+
+ @retval EFI_SUCCESS The driver was unloaded successfully
+ @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
+
+**/
+EFI_STATUS
+EFIAPI
+GenetUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ UINTN Index;
+
+ //
+ // Retrieve all BcmGenetPlatformDevice handles in the handle database
+ //
+ Status = gBS->LocateHandleBuffer (ByProtocol,
+ &gBcmGenetPlatformDeviceProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Disconnect the driver from the handles in the handle database
+ //
+ for (Index = 0; Index < HandleCount && !EFI_ERROR (Status); Index++) {
+ Status = gBS->DisconnectController (HandleBuffer[Index],
+ gImageHandle,
+ NULL);
+ }
+
+ //
+ // Free the handle array
+ //
+ gBS->FreePool (HandleBuffer);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "%a: failed to disconnect all controllers - %r\n",
+ __FUNCTION__, Status));
+ return Status;
+ }
+
+ //
+ // Uninstall protocols installed by the driver in its entrypoint
+ //
+ Status = EfiLibUninstallDriverBindingComponentName2 (
+ &mGenetDriverBinding,
+ &gGenetComponentName,
+ &gGenetComponentName2
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenericPhy.c b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenericPhy.c
new file mode 100644
index 000000000000..ff67602c92ff
--- /dev/null
+++ b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenericPhy.c
@@ -0,0 +1,405 @@
+/** @file
+
+ Copyright (c) 2020 Jared McNeill. All rights reserved.
+ Copyright (c) 2020 Andrey Warkentin <andrey.warkentin@gmail.com>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include "GenericPhy.h"
+
+#define PHY_RESET_TIMEOUT 500
+
+/**
+ Perform a PHY register read.
+
+ @param Phy[in] Pointer to GENERIC_PHY_PRIVATE_DATA.
+ @param PhyAddr[in] PHY address.
+ @param Reg[in] PHY register.
+ @param Data[out] Pointer to register data read.
+
+ @retval EFI_SUCCESS Data read successfully.
+ @retval EFI_DEVICE_ERROR Failed to read data.
+
+**/
+STATIC
+EFI_STATUS
+GenericPhyRead (
+ IN GENERIC_PHY_PRIVATE_DATA *Phy,
+ IN UINT8 PhyAddr,
+ IN UINT8 Reg,
+ OUT UINT16 *Data
+ )
+{
+ return Phy->Read (Phy->PrivateData, PhyAddr, Reg, Data);
+}
+
+/**
+ Perform a PHY register write.
+
+ @param Phy[in] Pointer to GENERIC_PHY_PRIVATE_DATA.
+ @param PhyAddr[in] PHY address.
+ @param Reg[in] PHY register.
+ @param Data[in] Pointer to register data to write.
+
+ @retval EFI_SUCCESS Data written successfully.
+ @retval EFI_DEVICE_ERROR Failed to write data.
+
+**/
+STATIC
+EFI_STATUS
+GenericPhyWrite (
+ IN GENERIC_PHY_PRIVATE_DATA *Phy,
+ IN UINT8 PhyAddr,
+ IN UINT8 Reg,
+ IN UINT16 Data
+ )
+{
+ return Phy->Write (Phy->PrivateData, PhyAddr, Reg, Data);
+}
+
+/**
+ Process a PHY link speed change (e.g. with MAC layer).
+
+ @param Phy[in] Pointer to GENERIC_PHY_PRIVATE_DATA.
+ @param Speed[in] Speed setting.
+ @param Duplex[in] Duplex setting.
+
+**/
+STATIC
+VOID
+GenericPhyConfigure (
+ IN GENERIC_PHY_PRIVATE_DATA *Phy,
+ IN GENERIC_PHY_SPEED Speed,
+ IN GENERIC_PHY_DUPLEX Duplex
+ )
+{
+ Phy->Configure (Phy->PrivateData, Speed, Duplex);
+}
+
+/**
+ Detect address for the first PHY seen, probing all possible addresses.
+
+ @param Phy[in] Pointer to GENERIC_PHY_PRIVATE_DATA.
+
+ @retval EFI_SUCCESS Found a PHY and programmed Phy->PhyAddr
+ @retval EFI_DEVICE_ERROR Error reading/writing a PHY register.
+ @retval EFI_NOT_FOUND No PHY detected.
+
+**/
+STATIC
+EFI_STATUS
+GenericPhyDetect (
+ IN GENERIC_PHY_PRIVATE_DATA *Phy
+ )
+{
+ EFI_STATUS Status;
+ UINT8 PhyAddr;
+ UINT16 Id1, Id2;
+
+ for (PhyAddr = 0; PhyAddr < 32; PhyAddr++) {
+ Status = GenericPhyRead (Phy, PhyAddr, GENERIC_PHY_PHYIDR1, &Id1);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ Status = GenericPhyRead (Phy, PhyAddr, GENERIC_PHY_PHYIDR2, &Id2);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ if (Id1 != 0xFFFF && Id2 != 0xFFFF) {
+ Phy->PhyAddr = PhyAddr;
+ DEBUG ((DEBUG_INFO,
+ "%a: PHY detected at address 0x%02X (PHYIDR1=0x%04X, PHYIDR2=0x%04X)\n",
+ __FUNCTION__, PhyAddr, Id1, Id2));
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Start link auto-negotiation on a PHY.
+
+ @param Phy[in] Pointer to GENERIC_PHY_PRIVATE_DATA.
+
+ @retval EFI_SUCCESS Auto-netogiation started.
+ @retval EFI_DEVICE_ERROR PHY register read/write error.
+
+**/
+STATIC
+EFI_STATUS
+GenericPhyAutoNegotiate (
+ IN GENERIC_PHY_PRIVATE_DATA *Phy
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Anar, Gbcr, Bmcr;
+
+ Status = GenericPhyRead (Phy, Phy->PhyAddr, GENERIC_PHY_ANAR, &Anar);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Anar |= GENERIC_PHY_ANAR_100BASETX_FDX |
+ GENERIC_PHY_ANAR_100BASETX |
+ GENERIC_PHY_ANAR_10BASET_FDX |
+ GENERIC_PHY_ANAR_10BASET;
+ Status = GenericPhyWrite (Phy, Phy->PhyAddr, GENERIC_PHY_ANAR, Anar);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = GenericPhyRead (Phy, Phy->PhyAddr, GENERIC_PHY_GBCR, &Gbcr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Gbcr |= GENERIC_PHY_GBCR_1000BASET_FDX |
+ GENERIC_PHY_GBCR_1000BASET;
+ Status = GenericPhyWrite (Phy, Phy->PhyAddr, GENERIC_PHY_GBCR, Gbcr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = GenericPhyRead (Phy, Phy->PhyAddr, GENERIC_PHY_BMCR, &Bmcr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Bmcr |= GENERIC_PHY_BMCR_ANE |
+ GENERIC_PHY_BMCR_RESTART_AN;
+ return GenericPhyWrite (Phy, Phy->PhyAddr, GENERIC_PHY_BMCR, Bmcr);
+}
+
+/**
+ Initialize the first PHY detected, performing a reset and enabling
+ auto-negotiation.
+
+ @param Phy[in] Pointer to GENERIC_PHY_PRIVATE_DATA.
+
+ @retval EFI_SUCCESS Auto-negotiation started.
+ @retval EFI_DEVICE_ERROR PHY register read/write error.
+ @retval EFI_TIMEOUT PHY reset time-out.
+ @retval EFI_NOT_FOUND No PHY detected.
+
+**/
+EFI_STATUS
+EFIAPI
+GenericPhyInit (
+ IN GENERIC_PHY_PRIVATE_DATA *Phy
+ )
+{
+ EFI_STATUS Status;
+
+ ASSERT (Phy->Read != NULL);
+ ASSERT (Phy->Write != NULL);
+ ASSERT (Phy->Configure != NULL);
+
+ Status = GenericPhyDetect (Phy);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = GenericPhyReset (Phy);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return GenericPhyAutoNegotiate (Phy);
+}
+
+/**
+ Perform a PHY reset.
+
+ @param Phy[in] Pointer to GENERIC_PHY_PRIVATE_DATA.
+
+ @retval EFI_SUCCESS Auto-negotiation started.
+ @retval EFI_DEVICE_ERROR PHY register read/write error.
+ @retval EFI_TIMEOUT PHY reset time-out.
+
+**/
+EFI_STATUS
+EFIAPI
+GenericPhyReset (
+ IN GENERIC_PHY_PRIVATE_DATA *Phy
+ )
+{
+ EFI_STATUS Status;
+ UINTN Retry;
+ UINT16 Data;
+
+ // Start reset sequence
+ Status = GenericPhyWrite (Phy, Phy->PhyAddr, GENERIC_PHY_BMCR,
+ GENERIC_PHY_BMCR_RESET);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Wait up to 500ms for it to complete
+ for (Retry = PHY_RESET_TIMEOUT; Retry > 0; Retry--) {
+ Status = GenericPhyRead (Phy, Phy->PhyAddr, GENERIC_PHY_BMCR, &Data);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if ((Data & GENERIC_PHY_BMCR_RESET) == 0) {
+ break;
+ }
+ gBS->Stall (1000);
+ }
+ if (Retry == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ if (Phy->ResetAction != NULL) {
+ Phy->ResetAction (Phy->PrivateData);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Probe link status.
+
+ @param Phy[in] Pointer to GENERIC_PHY_PRIVATE_DATA.
+
+ @retval EFI_SUCCESS Link is up and auto-negotiation is complete.
+ @retval EFI_DEVICE_ERROR PHY register read/write error,
+
+**/
+STATIC
+EFI_STATUS
+GenericPhyGetLinkStatus (
+ IN GENERIC_PHY_PRIVATE_DATA *Phy
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Bmsr;
+
+ Status = GenericPhyRead (Phy, Phy->PhyAddr, GENERIC_PHY_BMSR, &Bmsr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((Bmsr & GENERIC_PHY_BMSR_LINK_STATUS) == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ if ((Bmsr & GENERIC_PHY_BMSR_ANEG_COMPLETE) == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Return PHY link configuration.
+
+ @param Phy[in] Pointer to GENERIC_PHY_PRIVATE_DATA.
+ @param Speed[out] Pointer to store link speed.
+ @param Duplex[out] Pointer to store link duplex setting.
+
+ @retval EFI_SUCCESS Link configuration settings read.
+ @retval EFI_DEVICE_ERROR PHY register read/write error,
+
+**/
+STATIC
+EFI_STATUS
+GenericPhyGetConfig (
+ IN GENERIC_PHY_PRIVATE_DATA *Phy,
+ OUT GENERIC_PHY_SPEED *Speed,
+ OUT GENERIC_PHY_DUPLEX *Duplex
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Gbcr, Gbsr, Anlpar, Anar;
+ UINT16 Gb, An;
+
+ Status = GenericPhyRead (Phy, Phy->PhyAddr, GENERIC_PHY_GBCR, &Gbcr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = GenericPhyRead (Phy, Phy->PhyAddr, GENERIC_PHY_GBSR, &Gbsr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = GenericPhyRead (Phy, Phy->PhyAddr, GENERIC_PHY_ANLPAR, &Anlpar);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = GenericPhyRead (Phy, Phy->PhyAddr, GENERIC_PHY_ANAR, &Anar);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Gb = (Gbsr >> 2) & Gbcr;
+ An = Anlpar & Anar;
+
+ if ((Gb & (GENERIC_PHY_GBCR_1000BASET_FDX |
+ GENERIC_PHY_GBCR_1000BASET)) != 0) {
+ *Speed = PHY_SPEED_1000;
+ *Duplex = (Gb & GENERIC_PHY_GBCR_1000BASET_FDX) ? PHY_DUPLEX_FULL
+ : PHY_DUPLEX_HALF;
+ } else if ((An & (GENERIC_PHY_ANAR_100BASETX_FDX |
+ GENERIC_PHY_ANAR_100BASETX)) != 0) {
+ *Speed = PHY_SPEED_100;
+ *Duplex = (An & GENERIC_PHY_ANAR_100BASETX_FDX) ? PHY_DUPLEX_FULL
+ : PHY_DUPLEX_HALF;
+ } else {
+ *Speed = PHY_SPEED_10;
+ *Duplex = (An & GENERIC_PHY_ANAR_10BASET_FDX) ? PHY_DUPLEX_FULL
+ : PHY_DUPLEX_HALF;
+ }
+
+ DEBUG ((DEBUG_INFO, "%a: Link speed %d Mbps, %a-duplex\n",
+ __FUNCTION__, *Speed, *Duplex == PHY_DUPLEX_FULL ? "full" : "half"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Update link status, propagating PHY link state into the MAC layer.
+
+ @param Phy[in] Pointer to GENERIC_PHY_PRIVATE_DATA.
+
+ @retval EFI_SUCCESS Link is up.
+ @retval EFI_DEVICE_ERROR PHY register read/write error.
+ @retval EFI_NOT_READY Link is down.
+
+**/
+EFI_STATUS
+EFIAPI
+GenericPhyUpdateConfig (
+ IN GENERIC_PHY_PRIVATE_DATA *Phy
+ )
+{
+ EFI_STATUS Status;
+ GENERIC_PHY_SPEED Speed;
+ GENERIC_PHY_DUPLEX Duplex;
+ BOOLEAN LinkUp;
+
+ Status = GenericPhyGetLinkStatus (Phy);
+ LinkUp = EFI_ERROR (Status) ? FALSE : TRUE;
+
+ if (Phy->LinkUp != LinkUp) {
+ if (LinkUp) {
+ DEBUG ((DEBUG_VERBOSE, "%a: Link is up\n", __FUNCTION__));
+
+ Status = GenericPhyGetConfig (Phy, &Speed, &Duplex);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ GenericPhyConfigure (Phy, Speed, Duplex);
+ } else {
+ DEBUG ((DEBUG_VERBOSE, "%a: Link is down\n", __FUNCTION__));
+ }
+ }
+
+ Phy->LinkUp = LinkUp;
+
+ return LinkUp ? EFI_SUCCESS : EFI_NOT_READY;
+}
diff --git a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/Genet.c b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/Genet.c
deleted file mode 100644
index d40ce8b07a9d..000000000000
--- a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/Genet.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/** @file
-
- Copyright (c) 2020, Jeremy Linton All rights reserved.<BR>
-
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
- This driver acts like a stub to set the Broadcom
- Genet MAC address, until the actual network driver
- is in place.
-
-**/
-
-#include <Library/ArmLib.h>
-#include <Library/DebugLib.h>
-#include <Library/IoLib.h>
-#include <Library/PcdLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/UefiLib.h>
-
-#include <Net/Genet.h>
-#include <PiDxe.h>
-
-STATIC
-VOID
-RMWRegister (
- UINT32 Offset,
- UINT32 Mask,
- UINT32 In
- )
-{
- EFI_PHYSICAL_ADDRESS Addr;
- UINT32 Data;
- UINT32 Shift;
-
- Addr = GENET_BASE_ADDRESS + Offset;
- Data = 0;
- Shift = 1;
- if (In) {
- while (!(Mask & Shift))
- Shift <<= 1;
- Data = (MmioRead32 (Addr) & ~Mask) | ((In * Shift) & Mask);
- } else {
- Data = MmioRead32 (Addr) & ~Mask;
- }
-
- MmioWrite32 (Addr, Data);
-
- ArmDataMemoryBarrier ();
-}
-
-STATIC
-VOID
-WdRegister (
- UINT32 Offset,
- UINT32 In
- )
-{
- EFI_PHYSICAL_ADDRESS Base = GENET_BASE_ADDRESS;
-
- MmioWrite32 (Base + Offset, In);
-
- ArmDataMemoryBarrier ();
-}
-
-STATIC
-VOID
-SetMacAddress (
- UINT8* MacAddr
-)
-{
- // Bring the UMAC out of reset
- RMWRegister (GENET_SYS_RBUF_FLUSH_CTRL, 0x2, 1);
- gBS->Stall (10);
- RMWRegister (GENET_SYS_RBUF_FLUSH_CTRL, 0x2, 0);
-
- // Update the MAC
- DEBUG ((DEBUG_INFO, "Using MAC address %02X:%02X:%02X:%02X:%02X:%02X\n",
- MacAddr[0], MacAddr[1], MacAddr[2], MacAddr[3], MacAddr[4], MacAddr[5]));
-
- WdRegister (GENET_UMAC_MAC0, (MacAddr[0] << 24) | (MacAddr[1] << 16) |
- (MacAddr[2] << 8) | MacAddr[3]);
- WdRegister (GENET_UMAC_MAC1, (MacAddr[4] << 8) | MacAddr[5]);
-
-}
-
-/**
- The entry point of Genet UEFI Driver.
-
- @param ImageHandle The image handle of the UEFI Driver.
- @param SystemTable A pointer to the EFI System Table.
-
- @retval EFI_SUCCESS The Driver or UEFI Driver exited normally.
- @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater than
- SystemTable->Hdr.Revision.
-
-**/
-EFI_STATUS
-EFIAPI
-GenetEntryPoint (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- UINT64 MacAddr;
-
- // Read the MAC address
- MacAddr = PcdGet64 (PcdBcmGenetMacAddress);
-
- if (MacAddr != 0) {
- SetMacAddress ((UINT8*)&MacAddr);
- }
-
- return EFI_SUCCESS;
-}
diff --git a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenetUtil.c b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenetUtil.c
new file mode 100644
index 000000000000..119691dbeb49
--- /dev/null
+++ b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenetUtil.c
@@ -0,0 +1,816 @@
+/** @file
+
+ Copyright (c) 2020 Jared McNeill. All rights reserved.
+ Copyright (c) 2020 Andrey Warkentin <andrey.warkentin@gmail.com>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "GenetUtil.h"
+
+#include <Library/DmaLib.h>
+#include <Library/IoLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#define __LOWEST_SET_BIT(__mask) ((((__mask) - 1) & (__mask)) ^ (__mask))
+#define __SHIFTOUT(__x, __mask) (((__x) & (__mask)) / __LOWEST_SET_BIT(__mask))
+#define __SHIFTIN(__x, __mask) ((__x) * __LOWEST_SET_BIT(__mask))
+
+#define GENET_PHY_RETRY 1000
+
+STATIC CONST
+EFI_PHYSICAL_ADDRESS mDmaAddressLimit = FixedPcdGet64 (PcdDmaDeviceLimit) -
+ FixedPcdGet64 (PcdDmaDeviceOffset);
+
+/**
+ Read a memory-mapped device CSR.
+
+ @param Genet[in] Pointer to GENERIC_PHY_PRIVATE_DATA instance.
+ @param Offset[in] Register offset.
+
+ @retval Value
+
+**/
+STATIC
+UINT32
+GenetMmioRead (
+ IN GENET_PRIVATE_DATA *Genet,
+ IN UINT32 Offset
+ )
+{
+ ASSERT ((Offset & 3) == 0);
+
+ return MmioRead32 (Genet->RegBase + Offset);
+}
+
+/**
+ Write a memory-mapped device CSR.
+
+ @param Genet[in] Pointer to GENERIC_PHY_PRIVATE_DATA instance.
+ @param Offset[in] Register offset.
+ @param Data[in] Data to write.
+
+ @retval Value
+
+**/
+STATIC
+VOID
+GenetMmioWrite (
+ IN GENET_PRIVATE_DATA *Genet,
+ IN UINT32 Offset,
+ IN UINT32 Data
+ )
+{
+ ASSERT ((Offset & 3) == 0);
+
+ MemoryFence ();
+ MmioWrite32 (Genet->RegBase + Offset, Data);
+}
+
+/**
+ Perform a GENET PHY register read.
+
+ @param Priv[in] Pointer to GENET_PRIVATE_DATA.
+ @param PhyAddr[in] PHY address.
+ @param Reg[in] PHY register.
+ @param Data[out] Pointer to register data read.
+
+ @retval EFI_SUCCESS Data read successfully.
+ @retval EFI_DEVICE_ERROR Failed to read data.
+
+**/
+EFI_STATUS
+EFIAPI
+GenetPhyRead (
+ IN VOID *Priv,
+ IN UINT8 PhyAddr,
+ IN UINT8 Reg,
+ OUT UINT16 *Data
+ )
+{
+ GENET_PRIVATE_DATA *Genet;
+ UINTN Retry;
+ UINT32 Value;
+
+ Genet = Priv;
+ Value = GENET_MDIO_READ |
+ GENET_MDIO_START_BUSY |
+ __SHIFTIN (PhyAddr, GENET_MDIO_PMD) |
+ __SHIFTIN (Reg, GENET_MDIO_REG);
+ GenetMmioWrite (Genet, GENET_MDIO_CMD, Value);
+
+ for (Retry = GENET_PHY_RETRY; Retry > 0; Retry--) {
+ Value = GenetMmioRead (Genet, GENET_MDIO_CMD);
+ if ((Value & GENET_MDIO_START_BUSY) == 0) {
+ *Data = Value & 0xffff;
+ break;
+ }
+ gBS->Stall (10);
+ }
+
+ if (Retry == 0) {
+ DEBUG ((DEBUG_ERROR,
+ "%a: Timeout reading PhyAddr %d, Reg %d\n", __FUNCTION__, PhyAddr, Reg));
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Perform a GENET PHY register write.
+
+ @param Priv[in] Pointer to GENET_PRIVATE_DATA.
+ @param PhyAddr[in] PHY address.
+ @param Reg[in] PHY register.
+ @param Data[in] Pointer to register data to write.
+
+ @retval EFI_SUCCESS Data written successfully.
+ @retval EFI_DEVICE_ERROR Failed to write data.
+
+**/
+EFI_STATUS
+EFIAPI
+GenetPhyWrite (
+ IN VOID *Priv,
+ IN UINT8 PhyAddr,
+ IN UINT8 Reg,
+ IN UINT16 Data
+ )
+{
+ GENET_PRIVATE_DATA *Genet;
+ UINTN Retry;
+ UINT32 Value;
+
+ Genet = Priv;
+ Value = GENET_MDIO_WRITE |
+ GENET_MDIO_START_BUSY |
+ __SHIFTIN (PhyAddr, GENET_MDIO_PMD) |
+ __SHIFTIN (Reg, GENET_MDIO_REG);
+ GenetMmioWrite (Genet, GENET_MDIO_CMD, Value | Data);
+
+ for (Retry = GENET_PHY_RETRY; Retry > 0; Retry--) {
+ Value = GenetMmioRead (Genet, GENET_MDIO_CMD);
+ if ((Value & GENET_MDIO_START_BUSY) == 0) {
+ break;
+ }
+ gBS->Stall (10);
+ }
+
+ if (Retry == 0) {
+ DEBUG ((DEBUG_ERROR,
+ "%a: Timeout writing PhyAddr %d, Reg %d\n", __FUNCTION__, PhyAddr, Reg));
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Process a PHY link speed change (e.g. with MAC layer).
+
+ @param Priv[in] Pointer to GENET_PRIVATE_DATA.
+ @param Speed[in] Speed setting.
+ @param Duplex[in] Duplex setting.
+
+**/
+VOID
+EFIAPI
+GenetPhyConfigure (
+ IN VOID *Priv,
+ IN GENERIC_PHY_SPEED Speed,
+ IN GENERIC_PHY_DUPLEX Duplex
+ )
+{
+ GENET_PRIVATE_DATA *Genet;
+ UINT32 Value;
+
+ Genet = Priv;
+ Value = GenetMmioRead (Genet, GENET_EXT_RGMII_OOB_CTRL);
+ Value &= ~GENET_EXT_RGMII_OOB_OOB_DISABLE;
+ Value |= GENET_EXT_RGMII_OOB_RGMII_LINK;
+ Value |= GENET_EXT_RGMII_OOB_RGMII_MODE_EN;
+ if (Genet->PhyMode == GENET_PHY_MODE_RGMII) {
+ Value |= GENET_EXT_RGMII_OOB_ID_MODE_DISABLE;
+ } else {
+ Value &= ~GENET_EXT_RGMII_OOB_ID_MODE_DISABLE;
+ }
+ GenetMmioWrite (Genet, GENET_EXT_RGMII_OOB_CTRL, Value);
+
+ Value = GenetMmioRead (Genet, GENET_UMAC_CMD);
+ Value &= ~GENET_UMAC_CMD_SPEED;
+ switch (Speed) {
+ case PHY_SPEED_1000:
+ Value |= __SHIFTIN (GENET_UMAC_CMD_SPEED_1000, GENET_UMAC_CMD_SPEED);
+ break;
+ case PHY_SPEED_100:
+ Value |= __SHIFTIN (GENET_UMAC_CMD_SPEED_100, GENET_UMAC_CMD_SPEED);
+ break;
+ default:
+ Value |= __SHIFTIN (GENET_UMAC_CMD_SPEED_10, GENET_UMAC_CMD_SPEED);
+ break;
+ }
+ if (Duplex == PHY_DUPLEX_FULL) {
+ Value &= ~GENET_UMAC_CMD_HD_EN;
+ } else {
+ Value |= GENET_UMAC_CMD_HD_EN;
+ }
+ GenetMmioWrite (Genet, GENET_UMAC_CMD, Value);
+}
+
+/**
+ Extra action to run after a PHY reset. This adds the appropriate clock
+ delay based on the PHY mode.
+
+ @param Priv[in] Pointer to GENET_PRIVATE_DATA.
+
+**/
+EFI_STATUS
+EFIAPI
+GenetPhyResetAction (
+ IN VOID *Priv
+ )
+{
+ GENET_PRIVATE_DATA *Genet;
+ UINT16 Value;
+ EFI_STATUS Status;
+
+ Genet = Priv;
+ Status = GenetPhyWrite (Priv, Genet->Phy.PhyAddr, BRGPHY_MII_AUXCTL,
+ BRGPHY_AUXCTL_SHADOW_MISC |
+ (BRGPHY_AUXCTL_SHADOW_MISC << BRGPHY_AUXCTL_MISC_READ_SHIFT));
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = GenetPhyRead (Priv, Genet->Phy.PhyAddr, BRGPHY_MII_AUXCTL, &Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Value &= BRGPHY_AUXCTL_MISC_DATA_MASK;
+
+ if (Genet->PhyMode == GENET_PHY_MODE_RGMII_RXID ||
+ Genet->PhyMode == GENET_PHY_MODE_RGMII_ID) {
+ Value |= BRGPHY_AUXCTL_MISC_RGMII_SKEW_EN;
+ } else {
+ Value &= ~BRGPHY_AUXCTL_MISC_RGMII_SKEW_EN;
+ }
+
+ Status = GenetPhyWrite (Priv, Genet->Phy.PhyAddr, BRGPHY_MII_AUXCTL,
+ BRGPHY_AUXCTL_MISC_WRITE_EN | BRGPHY_AUXCTL_SHADOW_MISC | Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = GenetPhyWrite (Priv, Genet->Phy.PhyAddr, BRGPHY_MII_SHADOW_1C,
+ BRGPHY_SHADOW_1C_CLK_CTRL);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = GenetPhyRead (Priv, Genet->Phy.PhyAddr, BRGPHY_MII_SHADOW_1C, &Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Value &= BRGPHY_SHADOW_1C_DATA_MASK;
+
+ if (Genet->PhyMode == GENET_PHY_MODE_RGMII_TXID ||
+ Genet->PhyMode == GENET_PHY_MODE_RGMII_ID) {
+ Value |= BRGPHY_SHADOW_1C_GTXCLK_EN;
+ } else {
+ Value &= ~BRGPHY_SHADOW_1C_GTXCLK_EN;
+ }
+
+ Status = GenetPhyWrite (Priv, Genet->Phy.PhyAddr, BRGPHY_MII_SHADOW_1C,
+ BRGPHY_SHADOW_1C_WRITE_EN | BRGPHY_SHADOW_1C_CLK_CTRL | Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Reset GENET.
+
+ @param Genet[in] Pointer to GENET_PRIVATE_DATA.
+
+**/
+VOID
+GenetReset (
+ IN GENET_PRIVATE_DATA *Genet
+ )
+{
+ UINT32 Value;
+
+ Value = GenetMmioRead (Genet, GENET_SYS_RBUF_FLUSH_CTRL);
+ Value |= GENET_SYS_RBUF_FLUSH_RESET;
+ GenetMmioWrite (Genet, GENET_SYS_RBUF_FLUSH_CTRL, Value);
+ gBS->Stall (10);
+
+ Value &= ~GENET_SYS_RBUF_FLUSH_RESET;
+ GenetMmioWrite (Genet, GENET_SYS_RBUF_FLUSH_CTRL, Value);
+ gBS->Stall (10);
+
+ GenetMmioWrite (Genet, GENET_SYS_RBUF_FLUSH_CTRL, 0);
+ gBS->Stall (10);
+
+ GenetMmioWrite (Genet, GENET_UMAC_CMD, 0);
+ GenetMmioWrite (Genet, GENET_UMAC_CMD,
+ GENET_UMAC_CMD_LCL_LOOP_EN | GENET_UMAC_CMD_SW_RESET);
+ gBS->Stall (10);
+ GenetMmioWrite (Genet, GENET_UMAC_CMD, 0);
+
+ GenetMmioWrite (Genet, GENET_UMAC_MIB_CTRL,
+ GENET_UMAC_MIB_RESET_RUNT | GENET_UMAC_MIB_RESET_RX | GENET_UMAC_MIB_RESET_TX);
+ GenetMmioWrite (Genet, GENET_UMAC_MIB_CTRL, 0);
+
+ GenetMmioWrite (Genet, GENET_UMAC_MAX_FRAME_LEN, GENET_MAX_PACKET_SIZE);
+
+ Value = GenetMmioRead (Genet, GENET_RBUF_CTRL);
+ Value |= GENET_RBUF_ALIGN_2B;
+ GenetMmioWrite (Genet, GENET_RBUF_CTRL, Value);
+
+ GenetMmioWrite (Genet, GENET_RBUF_TBUF_SIZE_CTRL, 1);
+}
+
+/**
+ Set the station address.
+
+ @param Genet[in] Pointer to GENET_PRIVATE_DATA.
+ @param MacAddr[in] MAC address to set.
+
+**/
+VOID
+EFIAPI
+GenetSetMacAddress (
+ IN GENET_PRIVATE_DATA *Genet,
+ IN EFI_MAC_ADDRESS *MacAddr
+ )
+{
+ UINT32 Value;
+
+ Value = MacAddr->Addr[3] |
+ MacAddr->Addr[2] << 8 |
+ MacAddr->Addr[1] << 16 |
+ MacAddr->Addr[0] << 24;
+ GenetMmioWrite (Genet, GENET_UMAC_MAC0, Value);
+ Value = MacAddr->Addr[5] |
+ MacAddr->Addr[4] << 8;
+ GenetMmioWrite (Genet, GENET_UMAC_MAC1, Value);
+}
+
+/**
+ Set a PHY mode.
+
+ @param Genet[in] Pointer to GENET_PRIVATE_DATA.
+ @param PhyMode[in] Mode to set.
+
+**/
+VOID
+GenetSetPhyMode (
+ IN GENET_PRIVATE_DATA *Genet,
+ IN GENET_PHY_MODE PhyMode
+ )
+{
+ UINT32 Value;
+
+ switch (PhyMode) {
+ case GENET_PHY_MODE_RGMII:
+ case GENET_PHY_MODE_RGMII_RXID:
+ case GENET_PHY_MODE_RGMII_TXID:
+ case GENET_PHY_MODE_RGMII_ID:
+ Value = GENET_SYS_PORT_MODE_EXT_GPHY;
+ break;
+ default:
+ Value = 0;
+ break;
+ }
+ GenetMmioWrite (Genet, GENET_SYS_PORT_CTRL, Value);
+}
+
+/**
+ Enable TX/RX.
+
+ @param Genet[in] Pointer to GENET_PRIVATE_DATA.
+
+**/
+VOID
+GenetEnableTxRx (
+ IN GENET_PRIVATE_DATA *Genet
+ )
+{
+ UINT32 Value;
+
+ // Start TX DMA on default queue
+ Value = GenetMmioRead (Genet, GENET_TX_DMA_CTRL);
+ Value |= GENET_TX_DMA_CTRL_EN |
+ GENET_TX_DMA_CTRL_RBUF_EN (GENET_DMA_DEFAULT_QUEUE);
+ GenetMmioWrite (Genet, GENET_TX_DMA_CTRL, Value);
+
+ // Start RX DMA on default queue
+ Value = GenetMmioRead (Genet, GENET_RX_DMA_CTRL);
+ Value |= GENET_RX_DMA_CTRL_EN |
+ GENET_RX_DMA_CTRL_RBUF_EN (GENET_DMA_DEFAULT_QUEUE);
+ GenetMmioWrite (Genet, GENET_RX_DMA_CTRL, Value);
+
+ // Enable transmitter and receiver
+ Value = GenetMmioRead (Genet, GENET_UMAC_CMD);
+ Value |= GENET_UMAC_CMD_TXEN | GENET_UMAC_CMD_RXEN;
+ GenetMmioWrite (Genet, GENET_UMAC_CMD, Value);
+
+ // Enable interrupts
+ GenetMmioWrite (Genet, GENET_INTRL2_CPU_CLEAR_MASK,
+ GENET_IRQ_TXDMA_DONE | GENET_IRQ_RXDMA_DONE);
+}
+
+/**
+ Disable TX/RX.
+
+ @param Genet[in] Pointer to GENET_PRIVATE_DATA.
+
+**/
+VOID
+GenetDisableTxRx (
+ IN GENET_PRIVATE_DATA *Genet
+ )
+{
+ UINT32 Value;
+
+ // Disable interrupts
+ GenetMmioWrite (Genet, GENET_INTRL2_CPU_SET_MASK, 0xFFFFFFFF);
+ GenetMmioWrite (Genet, GENET_INTRL2_CPU_CLEAR, 0xFFFFFFFF);
+
+ // Disable receiver
+ Value = GenetMmioRead (Genet, GENET_UMAC_CMD);
+ Value &= ~GENET_UMAC_CMD_RXEN;
+ GenetMmioWrite (Genet, GENET_UMAC_CMD, Value);
+
+ // Stop RX DMA
+ Value = GenetMmioRead (Genet, GENET_RX_DMA_CTRL);
+ Value &= ~GENET_RX_DMA_CTRL_EN;
+ Value &= ~GENET_RX_DMA_CTRL_RBUF_EN (GENET_DMA_DEFAULT_QUEUE);
+ GenetMmioWrite (Genet, GENET_RX_DMA_CTRL, Value);
+
+ // Stop TX DMA
+ Value = GenetMmioRead (Genet, GENET_TX_DMA_CTRL);
+ Value &= ~GENET_TX_DMA_CTRL_EN;
+ Value &= ~GENET_TX_DMA_CTRL_RBUF_EN (GENET_DMA_DEFAULT_QUEUE);
+ GenetMmioWrite (Genet, GENET_TX_DMA_CTRL, Value);
+
+ // Flush data in the TX FIFO
+ GenetMmioWrite (Genet, GENET_UMAC_TX_FLUSH, 1);
+ gBS->Stall (10);
+ GenetMmioWrite (Genet, GENET_UMAC_TX_FLUSH, 0);
+
+ // Disable transmitter
+ Value = GenetMmioRead (Genet, GENET_UMAC_CMD);
+ Value &= ~GENET_UMAC_CMD_TXEN;
+ GenetMmioWrite (Genet, GENET_UMAC_CMD, Value);
+}
+
+/**
+ Change promiscuous mode state.
+
+ @param Genet[in] Pointer to GENET_PRIVATE_DATA.
+ @param Enable[in] Promiscuous mode state.
+
+**/
+VOID
+GenetSetPromisc (
+ IN GENET_PRIVATE_DATA *Genet,
+ IN BOOLEAN Enable
+ )
+{
+ UINT32 Value;
+
+ Value = GenetMmioRead (Genet, GENET_UMAC_CMD);
+ if (Enable) {
+ Value |= GENET_UMAC_CMD_PROMISC;
+ } else {
+ Value &= ~GENET_UMAC_CMD_PROMISC;
+ }
+ GenetMmioWrite (Genet, GENET_UMAC_CMD, Value);
+}
+
+/**
+ Enable the MAC filter for the Ethernet broadcast address
+
+ @param Genet[in] Pointer to GENET_PRIVATE_DATA.
+ @param Enable[in] Promiscuous mode state.
+
+**/
+VOID
+GenetEnableBroadcastFilter (
+ IN GENET_PRIVATE_DATA *Genet,
+ IN BOOLEAN Enable
+ )
+{
+ CONST EFI_MAC_ADDRESS *MacAddr;
+ UINT32 Value;
+
+ if (Enable) {
+ MacAddr = &Genet->SnpMode.CurrentAddress;
+
+ GenetMmioWrite (Genet, GENET_UMAC_MDF_ADDR0 (0),
+ MacAddr->Addr[1] | MacAddr->Addr[0] << 8);
+ GenetMmioWrite (Genet, GENET_UMAC_MDF_ADDR1 (0),
+ MacAddr->Addr[5] | MacAddr->Addr[4] << 8 |
+ MacAddr->Addr[3] << 16 | MacAddr->Addr[2] << 24);
+
+ GenetMmioWrite (Genet, GENET_UMAC_MDF_ADDR0 (1), 0xffff);
+ GenetMmioWrite (Genet, GENET_UMAC_MDF_ADDR1 (1), 0xffffffff);
+
+ Value = BIT16 | BIT15; // enable filters 0 and 1
+ } else {
+ Value = 0;
+ }
+ GenetMmioWrite (Genet, GENET_UMAC_MDF_CTRL, Value);
+}
+
+/**
+ Configure DMA TX and RX queues, enabling them.
+
+ @param Genet[in] Pointer to GENET_PRIVATE_DATA.
+
+**/
+VOID
+GenetDmaInitRings (
+ IN GENET_PRIVATE_DATA *Genet
+ )
+{
+ UINT8 Qid;
+
+ Qid = GENET_DMA_DEFAULT_QUEUE;
+
+ Genet->TxQueued = 0;
+ Genet->TxNext = 0;
+ Genet->TxConsIndex = 0;
+ Genet->TxProdIndex = 0;
+
+ Genet->RxConsIndex = 0;
+ Genet->RxProdIndex = 0;
+
+ // Configure TX queue
+ GenetMmioWrite (Genet, GENET_TX_SCB_BURST_SIZE, 0x08);
+ GenetMmioWrite (Genet, GENET_TX_DMA_READ_PTR_LO (Qid), 0);
+ GenetMmioWrite (Genet, GENET_TX_DMA_READ_PTR_HI (Qid), 0);
+ GenetMmioWrite (Genet, GENET_TX_DMA_CONS_INDEX (Qid), 0);
+ GenetMmioWrite (Genet, GENET_TX_DMA_PROD_INDEX (Qid), 0);
+ GenetMmioWrite (Genet, GENET_TX_DMA_RING_BUF_SIZE (Qid),
+ __SHIFTIN (GENET_DMA_DESC_COUNT, GENET_TX_DMA_RING_BUF_SIZE_DESC_COUNT) |
+ __SHIFTIN (GENET_MAX_PACKET_SIZE, GENET_TX_DMA_RING_BUF_SIZE_BUF_LENGTH));
+ GenetMmioWrite (Genet, GENET_TX_DMA_START_ADDR_LO (Qid), 0);
+ GenetMmioWrite (Genet, GENET_TX_DMA_START_ADDR_HI (Qid), 0);
+ GenetMmioWrite (Genet, GENET_TX_DMA_END_ADDR_LO (Qid),
+ GENET_DMA_DESC_COUNT * GENET_DMA_DESC_SIZE / 4 - 1);
+ GenetMmioWrite (Genet, GENET_TX_DMA_END_ADDR_HI (Qid), 0);
+ GenetMmioWrite (Genet, GENET_TX_DMA_MBUF_DONE_THRES (Qid), 1);
+ GenetMmioWrite (Genet, GENET_TX_DMA_FLOW_PERIOD (Qid), 0);
+ GenetMmioWrite (Genet, GENET_TX_DMA_WRITE_PTR_LO (Qid), 0);
+ GenetMmioWrite (Genet, GENET_TX_DMA_WRITE_PTR_HI (Qid), 0);
+
+ // Enable TX queue
+ GenetMmioWrite (Genet, GENET_TX_DMA_RING_CFG, (1U << Qid));
+
+ // Configure RX queue
+ GenetMmioWrite (Genet, GENET_RX_SCB_BURST_SIZE, 0x08);
+ GenetMmioWrite (Genet, GENET_RX_DMA_WRITE_PTR_LO (Qid), 0);
+ GenetMmioWrite (Genet, GENET_RX_DMA_WRITE_PTR_HI (Qid), 0);
+ GenetMmioWrite (Genet, GENET_RX_DMA_PROD_INDEX (Qid), 0);
+ GenetMmioWrite (Genet, GENET_RX_DMA_CONS_INDEX (Qid), 0);
+ GenetMmioWrite (Genet, GENET_RX_DMA_RING_BUF_SIZE (Qid),
+ __SHIFTIN (GENET_DMA_DESC_COUNT, GENET_RX_DMA_RING_BUF_SIZE_DESC_COUNT) |
+ __SHIFTIN (GENET_MAX_PACKET_SIZE, GENET_RX_DMA_RING_BUF_SIZE_BUF_LENGTH));
+ GenetMmioWrite (Genet, GENET_RX_DMA_START_ADDR_LO (Qid), 0);
+ GenetMmioWrite (Genet, GENET_RX_DMA_START_ADDR_HI (Qid), 0);
+ GenetMmioWrite (Genet, GENET_RX_DMA_END_ADDR_LO (Qid),
+ GENET_DMA_DESC_COUNT * GENET_DMA_DESC_SIZE / 4 - 1);
+ GenetMmioWrite (Genet, GENET_RX_DMA_END_ADDR_HI (Qid), 0);
+ GenetMmioWrite (Genet, GENET_RX_DMA_XON_XOFF_THRES (Qid),
+ __SHIFTIN (5, GENET_RX_DMA_XON_XOFF_THRES_LO) |
+ __SHIFTIN (GENET_DMA_DESC_COUNT >> 4, GENET_RX_DMA_XON_XOFF_THRES_HI));
+ GenetMmioWrite (Genet, GENET_RX_DMA_READ_PTR_LO (Qid), 0);
+ GenetMmioWrite (Genet, GENET_RX_DMA_READ_PTR_HI (Qid), 0);
+
+ // Enable RX queue
+ GenetMmioWrite (Genet, GENET_RX_DMA_RING_CFG, (1U << Qid));
+}
+
+/**
+ Allocate DMA buffers for RX.
+
+ @param Genet[in] Pointer to GENET_PRIVATE_DATA.
+
+ @retval EFI_SUCCESS DMA buffers allocated.
+ @retval EFI_OUT_OF_RESOURCES DMA buffers could not be allocated.
+**/
+EFI_STATUS
+GenetDmaAlloc (
+ IN GENET_PRIVATE_DATA *Genet
+ )
+{
+ EFI_STATUS Status;
+
+ Genet->RxBuffer = mDmaAddressLimit;
+ Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData,
+ EFI_SIZE_TO_PAGES (GENET_MAX_PACKET_SIZE * GENET_DMA_DESC_COUNT),
+ &Genet->RxBuffer);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR,
+ "%a: Failed to allocate RX buffer: %r\n", __FUNCTION__, Status));
+ }
+ return Status;
+}
+
+/**
+ Given an RX buffer descriptor index, program the IO address of the buffer into the hardware.
+
+ @param Genet[in] Pointer to GENET_PRIVATE_DATA.
+ @param DescIndex[in] Index of RX buffer descriptor.
+
+ @retval EFI_SUCCESS DMA buffers allocated.
+ @retval Others Programmatic errors, as buffers come from DmaAllocateBuffer, and thus
+ cannot fail DmaMap (for the expected NonCoherentDmaLib).
+**/
+EFI_STATUS
+GenetDmaMapRxDescriptor (
+ IN GENET_PRIVATE_DATA * Genet,
+ IN UINT8 DescIndex
+ )
+{
+ EFI_STATUS Status;
+ UINTN DmaNumberOfBytes;
+
+ ASSERT (Genet->RxBufferMap[DescIndex].Mapping == NULL);
+ ASSERT (Genet->RxBuffer != 0);
+
+ DmaNumberOfBytes = GENET_MAX_PACKET_SIZE;
+ Status = DmaMap (MapOperationBusMasterWrite,
+ GENET_RX_BUFFER (Genet, DescIndex),
+ &DmaNumberOfBytes,
+ &Genet->RxBufferMap[DescIndex].PhysAddress,
+ &Genet->RxBufferMap[DescIndex].Mapping);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Failed to map RX buffer: %r\n",
+ __FUNCTION__, Status));
+ return Status;
+ }
+
+ GenetMmioWrite (Genet, GENET_RX_DESC_ADDRESS_LO (DescIndex),
+ Genet->RxBufferMap[DescIndex].PhysAddress & 0xFFFFFFFF);
+ GenetMmioWrite (Genet, GENET_RX_DESC_ADDRESS_HI (DescIndex),
+ (Genet->RxBufferMap[DescIndex].PhysAddress >> 32) & 0xFFFFFFFF);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Given an RX buffer descriptor index, undo the DmaMap operation on the buffer.
+
+ @param Genet[in] Pointer to GENET_PRIVATE_DATA.
+ @param DescIndex[in] Index of RX buffer descriptor.
+
+**/
+VOID
+GenetDmaUnmapRxDescriptor (
+ IN GENET_PRIVATE_DATA * Genet,
+ IN UINT8 DescIndex
+ )
+{
+ if (Genet->RxBufferMap[DescIndex].Mapping != NULL) {
+ DmaUnmap (Genet->RxBufferMap[DescIndex].Mapping);
+ Genet->RxBufferMap[DescIndex].Mapping = NULL;
+ }
+}
+
+/**
+ Free DMA buffers for RX, undoing GenetDmaAlloc.
+
+ @param Genet[in] Pointer to GENET_PRIVATE_DATA.
+ @param DescIndex[in] Index of RX buffer descriptor.
+
+**/
+VOID
+GenetDmaFree (
+ IN GENET_PRIVATE_DATA *Genet
+ )
+{
+ UINTN Idx;
+
+ for (Idx = 0; Idx < GENET_DMA_DESC_COUNT; Idx++) {
+ GenetDmaUnmapRxDescriptor (Genet, Idx);
+ }
+ gBS->FreePages (Genet->RxBuffer,
+ EFI_SIZE_TO_PAGES (GENET_MAX_PACKET_SIZE * GENET_DMA_DESC_COUNT));
+}
+
+/**
+ Queue TX transmission, given a buffer to transmit and a TX descriptor index.
+
+ @param Genet[in] Pointer to GENET_PRIVATE_DATA.
+ @param DescIndex[in] TX descriptor index.
+ @param PhysAddr[in] Buffer to transmit.
+ @param NumberOfBytes[in] Buffer length.
+
+**/
+VOID
+GenetDmaTriggerTx (
+ IN GENET_PRIVATE_DATA * Genet,
+ IN UINT8 DescIndex,
+ IN EFI_PHYSICAL_ADDRESS PhysAddr,
+ IN UINTN NumberOfBytes
+ )
+{
+ UINT32 DescStatus;
+
+ DescStatus = GENET_TX_DESC_STATUS_SOP |
+ GENET_TX_DESC_STATUS_EOP |
+ GENET_TX_DESC_STATUS_CRC |
+ GENET_TX_DESC_STATUS_QTAG |
+ __SHIFTIN (NumberOfBytes, GENET_TX_DESC_STATUS_BUFLEN);
+
+ GenetMmioWrite (Genet, GENET_TX_DESC_ADDRESS_LO (DescIndex),
+ PhysAddr & 0xFFFFFFFF);
+ GenetMmioWrite (Genet, GENET_TX_DESC_ADDRESS_HI (DescIndex),
+ (PhysAddr >> 32) & 0xFFFFFFFF);
+ GenetMmioWrite (Genet, GENET_TX_DESC_STATUS (DescIndex), DescStatus);
+
+ GenetMmioWrite (Genet, GENET_TX_DMA_PROD_INDEX (GENET_DMA_DEFAULT_QUEUE),
+ (DescIndex + 1) & 0xFFFF);
+}
+
+/**
+ Simulate a "TX interrupt", return the next (completed) TX buffer to recycle.
+
+ @param Genet[in] Pointer to GENET_PRIVATE_DATA.
+ @param TxBuf[out] Location to store pointer to next TX buffer to recycle.
+
+**/
+VOID
+GenetTxIntr (
+ IN GENET_PRIVATE_DATA *Genet,
+ OUT VOID **TxBuf
+ )
+{
+ UINT32 ConsIndex, Total;
+
+ ConsIndex = GenetMmioRead (Genet,
+ GENET_TX_DMA_CONS_INDEX (GENET_DMA_DEFAULT_QUEUE)) & 0xFFFF;
+
+ Total = (ConsIndex - Genet->TxConsIndex) & 0xFFFF;
+ if (Genet->TxQueued > 0 && Total > 0) {
+ DmaUnmap (Genet->TxBufferMap[Genet->TxNext]);
+ *TxBuf = Genet->TxBuffer[Genet->TxNext];
+ Genet->TxQueued--;
+ Genet->TxNext = (Genet->TxNext + 1) % GENET_DMA_DESC_COUNT;
+ Genet->TxConsIndex++;
+ } else {
+ *TxBuf = NULL;
+ }
+}
+
+/**
+ Simulate an "RX interrupt", returning the index of a completed RX buffer and
+ corresponding frame length.
+
+ @param Genet[in] Pointer to GENET_PRIVATE_DATA.
+ @param DescIndex[out] Location to store completed RX buffer index.
+ @param FrameLength[out] Location to store frame length.
+
+ @retval EFI_SUCCESS Data received.
+ @retval EFI_NOT_READY No RX buffers ready as no data received.
+
+**/
+EFI_STATUS
+GenetRxIntr (
+ IN GENET_PRIVATE_DATA *Genet,
+ OUT UINT8 *DescIndex,
+ OUT UINTN *FrameLength
+ )
+{
+ EFI_STATUS Status;
+ UINT32 ProdIndex, Total;
+ UINT32 DescStatus;
+
+ ProdIndex = GenetMmioRead (Genet,
+ GENET_RX_DMA_PROD_INDEX (GENET_DMA_DEFAULT_QUEUE)) & 0xFFFF;
+
+ Total = (ProdIndex - Genet->RxConsIndex) & 0xFFFF;
+ if (Total > 0) {
+ *DescIndex = Genet->RxConsIndex % GENET_DMA_DESC_COUNT;
+ DescStatus = GenetMmioRead (Genet, GENET_RX_DESC_STATUS (*DescIndex));
+ *FrameLength = __SHIFTOUT (DescStatus, GENET_RX_DESC_STATUS_BUFLEN);
+
+ Genet->RxConsIndex = (Genet->RxConsIndex + 1) & 0xFFFF;
+ GenetMmioWrite (Genet, GENET_RX_DMA_CONS_INDEX (GENET_DMA_DEFAULT_QUEUE),
+ Genet->RxConsIndex);
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_NOT_READY;
+ }
+
+ return Status;
+}
diff --git a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/SimpleNetwork.c b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/SimpleNetwork.c
new file mode 100644
index 000000000000..b2cae687b3d4
--- /dev/null
+++ b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/SimpleNetwork.c
@@ -0,0 +1,834 @@
+/** @file
+ Provides the Simple Network functions.
+
+ Copyright (c) 2020 Jared McNeill. All rights reserved.
+ Copyright (c) 2020 Andrey Warkentin <andrey.warkentin@gmail.com>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "GenetUtil.h"
+
+#include <Library/DmaLib.h>
+
+
+/**
+ Changes the state of a network interface from "stopped" to "started".
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS The network interface was started.
+ @retval EFI_ALREADY_STARTED The network interface is already in the started state.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The network interface is not in the right (stopped) state.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GenetSimpleNetworkStart (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This
+ )
+{
+ GENET_PRIVATE_DATA *Genet;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Genet = GENET_PRIVATE_DATA_FROM_SNP_THIS (This);
+ if (Genet->SnpMode.State == EfiSimpleNetworkStarted) {
+ return EFI_ALREADY_STARTED;
+ } else if (Genet->SnpMode.State != EfiSimpleNetworkStopped) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Genet->SnpMode.State = EfiSimpleNetworkStarted;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Changes the state of a network interface from "started" to "stopped".
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS The network interface was stopped.
+ @retval EFI_NOT_STARTED The network interface is already in the stopped state.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The network interface is not in the right (started) state.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GenetSimpleNetworkStop (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This
+ )
+{
+ GENET_PRIVATE_DATA *Genet;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Genet = GENET_PRIVATE_DATA_FROM_SNP_THIS (This);
+ if (Genet->SnpMode.State == EfiSimpleNetworkStopped) {
+ return EFI_NOT_STARTED;
+ } else if (Genet->SnpMode.State != EfiSimpleNetworkStarted) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ GenetDisableTxRx (Genet);
+
+ Genet->SnpMode.State = EfiSimpleNetworkStopped;
+ return EFI_SUCCESS;
+}
+
+/**
+ Resets a network adapter and allocates the transmit and receive buffers
+ required by the network interface; optionally, also requests allocation
+ of additional transmit and receive buffers.
+
+ @param This The protocol instance pointer.
+ @param ExtraRxBufferSize The size, in bytes, of the extra receive buffer space
+ that the driver should allocate for the network interface.
+ Some network interfaces will not be able to use the extra
+ buffer, and the caller will not know if it is actually
+ being used.
+ @param ExtraTxBufferSize The size, in bytes, of the extra transmit buffer space
+ that the driver should allocate for the network interface.
+ Some network interfaces will not be able to use the extra
+ buffer, and the caller will not know if it is actually
+ being used.
+
+ @retval EFI_SUCCESS The network interface was initialized.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_OUT_OF_RESOURCES There was not enough memory for the transmit and
+ receive buffers.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The network inteface is not in the right (started) state.
+ @retval EFI_DEVICE_ERROR PHY register read/write error.
+ @retval EFI_TIMEOUT PHY reset time-out.
+ @retval EFI_NOT_FOUND No PHY detected.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GenetSimpleNetworkInitialize (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN UINTN ExtraRxBufferSize, OPTIONAL
+ IN UINTN ExtraTxBufferSize OPTIONAL
+ )
+{
+ GENET_PRIVATE_DATA *Genet;
+ EFI_STATUS Status;
+ UINTN Idx;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Genet = GENET_PRIVATE_DATA_FROM_SNP_THIS (This);
+ if (Genet->SnpMode.State == EfiSimpleNetworkStopped) {
+ return EFI_NOT_STARTED;
+ } else if (Genet->SnpMode.State != EfiSimpleNetworkStarted) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ GenetReset (Genet);
+ GenetSetPhyMode (Genet, Genet->PhyMode);
+
+ Status = GenericPhyInit (&Genet->Phy);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ GenetSetMacAddress (Genet, &Genet->SnpMode.CurrentAddress);
+
+ GenetDmaInitRings (Genet);
+
+ // Map RX buffers
+ for (Idx = 0; Idx < GENET_DMA_DESC_COUNT; Idx++) {
+ Status = GenetDmaMapRxDescriptor (Genet, Idx);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ GenetEnableTxRx (Genet);
+
+ Genet->SnpMode.State = EfiSimpleNetworkInitialized;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Resets a network adapter and re-initializes it with the parameters that were
+ provided in the previous call to Initialize().
+
+ @param This The protocol instance pointer.
+ @param ExtendedVerification Indicates that the driver may perform a more
+ exhaustive verification operation of the device
+ during reset.
+
+ @retval EFI_SUCCESS The network interface was reset.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The network inteface is not in the right (initialized) state.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GenetSimpleNetworkReset (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ GENET_PRIVATE_DATA *Genet;
+ EFI_STATUS Status;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Genet = GENET_PRIVATE_DATA_FROM_SNP_THIS (This);
+ if (Genet->SnpMode.State == EfiSimpleNetworkStopped) {
+ return EFI_NOT_STARTED;
+ }
+ if (Genet->SnpMode.State != EfiSimpleNetworkInitialized) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = GenericPhyReset (&Genet->Phy);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Resets a network adapter and leaves it in a state that is safe for
+ another driver to initialize.
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS The network interface was shutdown.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The network inteface is not in the right (initialized) state.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GenetSimpleNetworkShutdown (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This
+ )
+{
+ GENET_PRIVATE_DATA *Genet;
+ UINTN Idx;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Genet = GENET_PRIVATE_DATA_FROM_SNP_THIS (This);
+ if (Genet->SnpMode.State == EfiSimpleNetworkStopped) {
+ return EFI_NOT_STARTED;
+ }
+ if (Genet->SnpMode.State != EfiSimpleNetworkInitialized) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ GenetDisableTxRx (Genet);
+
+ for (Idx = 0; Idx < GENET_DMA_DESC_COUNT; Idx++) {
+ GenetDmaUnmapRxDescriptor (Genet, Idx);
+ }
+
+ Genet->SnpMode.State = EfiSimpleNetworkStarted;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Manages the receive filters of a network interface.
+
+ @param This The protocol instance pointer.
+ @param Enable A bit mask of receive filters to enable on the network interface.
+ @param Disable A bit mask of receive filters to disable on the network interface.
+ @param ResetMCastFilter Set to TRUE to reset the contents of the multicast receive
+ filters on the network interface to their default values.
+ @param McastFilterCnt Number of multicast HW MAC addresses in the new
+ MCastFilter list. This value must be less than or equal to
+ the MCastFilterCnt field of EFI_SIMPLE_NETWORK_MODE. This
+ field is optional if ResetMCastFilter is TRUE.
+ @param MCastFilter A pointer to a list of new multicast receive filter HW MAC
+ addresses. This list will replace any existing multicast
+ HW MAC address list. This field is optional if
+ ResetMCastFilter is TRUE.
+
+ @retval EFI_SUCCESS The multicast receive filter list was updated.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The network inteface is not in the right (initialized) state.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GenetSimpleNetworkReceiveFilters (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN UINT32 Enable,
+ IN UINT32 Disable,
+ IN BOOLEAN ResetMCastFilter,
+ IN UINTN MCastFilterCnt, OPTIONAL
+ IN EFI_MAC_ADDRESS *MCastFilter OPTIONAL
+ )
+{
+ GENET_PRIVATE_DATA *Genet;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Genet = GENET_PRIVATE_DATA_FROM_SNP_THIS (This);
+ if (((Enable | Disable) & ~Genet->SnpMode.ReceiveFilterMask) != 0 ||
+ (!ResetMCastFilter && MCastFilterCnt > Genet->SnpMode.MaxMCastFilterCount)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Genet->SnpMode.State == EfiSimpleNetworkStopped) {
+ return EFI_NOT_STARTED;
+ }
+ if (Genet->SnpMode.State != EfiSimpleNetworkInitialized) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ GenetEnableBroadcastFilter (Genet,
+ (Enable & ~Disable & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0);
+
+ GenetSetPromisc (Genet,
+ (Enable & ~Disable & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Modifies or resets the current station address, if supported.
+
+ @param This The protocol instance pointer.
+ @param Reset Flag used to reset the station address to the network interfaces
+ permanent address.
+ @param New The new station address to be used for the network interface.
+
+ @retval EFI_SUCCESS The network interfaces station address was updated.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The network inteface is not in the right (initialized) state.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GenetSimpleNetworkStationAddress (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN BOOLEAN Reset,
+ IN EFI_MAC_ADDRESS *New OPTIONAL
+ )
+{
+ GENET_PRIVATE_DATA *Genet;
+
+ if (This == NULL || This->Mode == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Reset == TRUE && New == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Genet = GENET_PRIVATE_DATA_FROM_SNP_THIS (This);
+ if (Genet->SnpMode.State == EfiSimpleNetworkStopped) {
+ return EFI_NOT_STARTED;
+ }
+ if (Genet->SnpMode.State != EfiSimpleNetworkInitialized) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (Reset) {
+ // Use permanent address
+ CopyMem (&This->Mode->CurrentAddress, &This->Mode->PermanentAddress,
+ sizeof (This->Mode->CurrentAddress));
+ } else {
+ // Use specified address
+ CopyMem (&This->Mode->CurrentAddress, New,
+ sizeof (This->Mode->CurrentAddress));
+ }
+
+ GenetSetMacAddress (Genet, &Genet->SnpMode.CurrentAddress);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Resets or collects the statistics on a network interface.
+
+ @param This Protocol instance pointer.
+ @param Reset Set to TRUE to reset the statistics for the network interface.
+ @param StatisticsSize On input the size, in bytes, of StatisticsTable. On
+ output the size, in bytes, of the resulting table of
+ statistics.
+ @param StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that
+ contains the statistics.
+
+ @retval EFI_SUCCESS The statistics were collected from the network interface.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer
+ size needed to hold the statistics is returned in
+ StatisticsSize.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The network inteface is not in the right (initialized) state.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GenetSimpleNetworkStatistics (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN BOOLEAN Reset,
+ IN OUT UINTN *StatisticsSize, OPTIONAL
+ OUT EFI_NETWORK_STATISTICS *StatisticsTable OPTIONAL
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Performs read and write operations on the NVRAM device attached to a
+ network interface.
+
+ @param This The protocol instance pointer.
+ @param ReadWrite TRUE for read operations, FALSE for write operations.
+ @param Offset Byte offset in the NVRAM device at which to start the read or
+ write operation. This must be a multiple of NvRamAccessSize and
+ less than NvRamSize.
+ @param BufferSize The number of bytes to read or write from the NVRAM device.
+ This must also be a multiple of NvramAccessSize.
+ @param Buffer A pointer to the data buffer.
+
+ @retval EFI_SUCCESS The NVRAM access was performed.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GenetSimpleNetworkNvData (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN BOOLEAN ReadWrite,
+ IN UINTN Offset,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Reads the current interrupt status and recycled transmit buffer status from
+ a network interface.
+
+ @param This The protocol instance pointer.
+ @param InterruptStatus A pointer to the bit mask of the currently active interrupts
+ If this is NULL, the interrupt status will not be read from
+ the device. If this is not NULL, the interrupt status will
+ be read from the device. When the interrupt status is read,
+ it will also be cleared. Clearing the transmit interrupt
+ does not empty the recycled transmit buffer array.
+ @param TxBuf Recycled transmit buffer address. The network interface will
+ not transmit if its internal recycled transmit buffer array
+ is full. Reading the transmit buffer does not clear the
+ transmit interrupt. If this is NULL, then the transmit buffer
+ status will not be read. If there are no transmit buffers to
+ recycle and TxBuf is not NULL, * TxBuf will be set to NULL.
+
+ @retval EFI_SUCCESS The status of the network interface was retrieved.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The network inteface is not in the right (initialized) state.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GenetSimpleNetworkGetStatus (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ OUT UINT32 *InterruptStatus, OPTIONAL
+ OUT VOID **TxBuf OPTIONAL
+ )
+{
+ GENET_PRIVATE_DATA *Genet;
+ EFI_STATUS Status;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Genet = GENET_PRIVATE_DATA_FROM_SNP_THIS (This);
+ if (Genet->SnpMode.State == EfiSimpleNetworkStopped) {
+ return EFI_NOT_STARTED;
+ }
+ if (Genet->SnpMode.State != EfiSimpleNetworkInitialized) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = GenericPhyUpdateConfig (&Genet->Phy);
+ if (EFI_ERROR (Status)) {
+ Genet->SnpMode.MediaPresent = FALSE;
+ } else {
+ Genet->SnpMode.MediaPresent = TRUE;
+
+ if (TxBuf != NULL) {
+ GenetTxIntr (Genet, TxBuf);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Places a packet in the transmit queue of a network interface.
+
+ @param This The protocol instance pointer.
+ @param HeaderSize The size, in bytes, of the media header to be filled in by
+ the Transmit() function. If HeaderSize is non-zero, then it
+ must be equal to This->Mode->MediaHeaderSize and the DestAddr
+ and Protocol parameters must not be NULL.
+ @param BufferSize The size, in bytes, of the entire packet (media header and
+ data) to be transmitted through the network interface.
+ @param Buffer A pointer to the packet (media header followed by data) to be
+ transmitted. This parameter cannot be NULL. If HeaderSize is zero,
+ then the media header in Buffer must already be filled in by the
+ caller. If HeaderSize is non-zero, then the media header will be
+ filled in by the Transmit() function.
+ @param SrcAddr The source HW MAC address. If HeaderSize is zero, then this parameter
+ is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then
+ This->Mode->CurrentAddress is used for the source HW MAC address.
+ @param DestAddr The destination HW MAC address. If HeaderSize is zero, then this
+ parameter is ignored.
+ @param Protocol The type of header to build. If HeaderSize is zero, then this
+ parameter is ignored. See RFC 1700, section "Ether Types", for
+ examples.
+
+ @retval EFI_SUCCESS The packet was placed on the transmit queue.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_NOT_READY The network interface is too busy to accept this transmit request.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The network inteface is not in the right (initialized) state.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GenetSimpleNetworkTransmit (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ IN UINTN HeaderSize,
+ IN UINTN BufferSize,
+ IN VOID *Buffer,
+ IN EFI_MAC_ADDRESS *SrcAddr, OPTIONAL
+ IN EFI_MAC_ADDRESS *DestAddr, OPTIONAL
+ IN UINT16 *Protocol OPTIONAL
+ )
+{
+ GENET_PRIVATE_DATA *Genet;
+ EFI_STATUS Status;
+ UINT8 *Frame = Buffer;
+ UINT8 Desc;
+ PHYSICAL_ADDRESS DmaDeviceAddress;
+ UINTN DmaNumberOfBytes;
+
+ if (This == NULL || Buffer == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Invalid parameter (missing handle or buffer)\n",
+ __FUNCTION__));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Genet = GENET_PRIVATE_DATA_FROM_SNP_THIS (This);
+ if (Genet->SnpMode.State == EfiSimpleNetworkStopped) {
+ return EFI_NOT_STARTED;
+ }
+ if (Genet->SnpMode.State != EfiSimpleNetworkInitialized) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (!Genet->SnpMode.MediaPresent) {
+ //
+ // Don't bother transmitting if there's no link.
+ //
+ return EFI_NOT_READY;
+ }
+
+ if (HeaderSize != 0) {
+ if (HeaderSize != Genet->SnpMode.MediaHeaderSize) {
+ DEBUG ((DEBUG_ERROR,
+ "%a: Invalid parameter (header size mismatch; HeaderSize 0x%X, SnpMode.MediaHeaderSize 0x%X))\n",
+ __FUNCTION__, HeaderSize, Genet->SnpMode.MediaHeaderSize));
+ return EFI_INVALID_PARAMETER;
+ }
+ if (DestAddr == NULL || Protocol == NULL) {
+ DEBUG ((DEBUG_ERROR,
+ "%a: Invalid parameter (dest addr or protocol missing)\n",
+ __FUNCTION__));
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ if (BufferSize < Genet->SnpMode.MediaHeaderSize) {
+ DEBUG ((DEBUG_ERROR, "%a: Buffer too small\n", __FUNCTION__));
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ Status = EfiAcquireLockOrFail (&Genet->Lock);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Couldn't get lock: %r\n", __FUNCTION__, Status));
+ return EFI_ACCESS_DENIED;
+ }
+
+ if (Genet->TxQueued == GENET_DMA_DESC_COUNT - 1) {
+ EfiReleaseLock (&Genet->Lock);
+
+ DEBUG ((DEBUG_ERROR, "%a: Queue full\n", __FUNCTION__));
+ return EFI_NOT_READY;
+ }
+
+ if (HeaderSize != 0) {
+ CopyMem (&Frame[0], &DestAddr->Addr[0], NET_ETHER_ADDR_LEN);
+ CopyMem (&Frame[6], &SrcAddr->Addr[0], NET_ETHER_ADDR_LEN);
+ Frame[12] = (*Protocol & 0xFF00) >> 8;
+ Frame[13] = *Protocol & 0xFF;
+ }
+
+ Desc = Genet->TxProdIndex % GENET_DMA_DESC_COUNT;
+
+ Genet->TxBuffer[Desc] = Frame;
+
+ DmaNumberOfBytes = BufferSize;
+ Status = DmaMap (MapOperationBusMasterRead,
+ (VOID *)(UINTN)Frame,
+ &DmaNumberOfBytes,
+ &DmaDeviceAddress,
+ &Genet->TxBufferMap[Desc]);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: DmaMap failed: %r\n", __FUNCTION__, Status));
+ EfiReleaseLock (&Genet->Lock);
+ return Status;
+ }
+
+ GenetDmaTriggerTx (Genet, Desc, DmaDeviceAddress, DmaNumberOfBytes);
+
+ Genet->TxProdIndex = (Genet->TxProdIndex + 1) % 0xFFFF;
+ Genet->TxQueued++;
+
+ EfiReleaseLock (&Genet->Lock);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Receives a packet from a network interface.
+
+ @param This The protocol instance pointer.
+ @param HeaderSize The size, in bytes, of the media header received on the network
+ interface. If this parameter is NULL, then the media header size
+ will not be returned.
+ @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in
+ bytes, of the packet that was received on the network interface.
+ @param Buffer A pointer to the data buffer to receive both the media header and
+ the data.
+ @param SrcAddr The source HW MAC address. If this parameter is NULL, the
+ HW MAC source address will not be extracted from the media
+ header.
+ @param DestAddr The destination HW MAC address. If this parameter is NULL,
+ the HW MAC destination address will not be extracted from the
+ media header.
+ @param Protocol The media header type. If this parameter is NULL, then the
+ protocol will not be extracted from the media header. See
+ RFC 1700 section "Ether Types" for examples.
+
+ @retval EFI_SUCCESS The received data was stored in Buffer, and BufferSize has
+ been updated to the number of bytes received.
+ @retval EFI_NOT_STARTED The network interface has not been started.
+ @retval EFI_NOT_READY No packets received.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
+ @retval EFI_DEVICE_ERROR The network inteface is not in the right (initialized) state.
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GenetSimpleNetworkReceive (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ OUT UINTN *HeaderSize, OPTIONAL
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer,
+ OUT EFI_MAC_ADDRESS *SrcAddr, OPTIONAL
+ OUT EFI_MAC_ADDRESS *DestAddr, OPTIONAL
+ OUT UINT16 *Protocol OPTIONAL
+ )
+{
+ GENET_PRIVATE_DATA *Genet;
+ EFI_STATUS Status;
+ UINT8 DescIndex;
+ UINT8 *Frame;
+ UINTN FrameLength;
+
+ if (This == NULL || Buffer == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Invalid parameter (missing handle or buffer)\n",
+ __FUNCTION__));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Genet = GENET_PRIVATE_DATA_FROM_SNP_THIS (This);
+ if (Genet->SnpMode.State == EfiSimpleNetworkStopped) {
+ return EFI_NOT_STARTED;
+ }
+ if (Genet->SnpMode.State != EfiSimpleNetworkInitialized) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = EfiAcquireLockOrFail (&Genet->Lock);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Couldn't get lock: %r\n", __FUNCTION__, Status));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = GenetRxIntr (Genet, &DescIndex, &FrameLength);
+ if (EFI_ERROR (Status)) {
+ EfiReleaseLock (&Genet->Lock);
+ return Status;
+ }
+
+ ASSERT (Genet->RxBufferMap[DescIndex].Mapping != NULL);
+
+ GenetDmaUnmapRxDescriptor (Genet, DescIndex);
+
+ Frame = GENET_RX_BUFFER (Genet, DescIndex);
+
+ if (FrameLength > 2 + Genet->SnpMode.MediaHeaderSize) {
+ // Received frame has 2 bytes of padding at the start
+ Frame += 2;
+ FrameLength -= 2;
+
+ if (*BufferSize < FrameLength) {
+ DEBUG ((DEBUG_ERROR,
+ "%a: Buffer size (0x%X) is too small for frame (0x%X)\n",
+ __FUNCTION__, *BufferSize, FrameLength));
+ Status = GenetDmaMapRxDescriptor (Genet, DescIndex);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Failed to remap RX descriptor!\n",
+ __FUNCTION__));
+ }
+ EfiReleaseLock (&Genet->Lock);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (DestAddr != NULL) {
+ CopyMem (&DestAddr->Addr[0], &Frame[0], NET_ETHER_ADDR_LEN);
+ }
+ if (SrcAddr != NULL) {
+ CopyMem (&SrcAddr->Addr[0], &Frame[6], NET_ETHER_ADDR_LEN);
+ }
+ if (Protocol != NULL) {
+ *Protocol = (UINT16) ((Frame[12] << 8) | Frame[13]);
+ }
+ if (HeaderSize != NULL) {
+ *HeaderSize = Genet->SnpMode.MediaHeaderSize;
+ }
+
+ CopyMem (Buffer, Frame, FrameLength);
+ *BufferSize = FrameLength;
+
+ Status = EFI_SUCCESS;
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a: Short packet (FrameLength 0x%X)",
+ __FUNCTION__, FrameLength));
+ Status = EFI_NOT_READY;
+ }
+
+ Status = GenetDmaMapRxDescriptor (Genet, DescIndex);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Failed to remap RX descriptor!\n", __FUNCTION__));
+ }
+
+ EfiReleaseLock (&Genet->Lock);
+ return Status;
+}
+
+/**
+ This function converts a multicast IP address to a multicast HW MAC address
+ for all packet transactions.
+
+ @param [in] SimpleNetwork Protocol instance pointer
+ @param [in] IPv6 Set to TRUE if the multicast IP address is IPv6 [RFC2460].
+ Set to FALSE if the multicast IP address is IPv4 [RFC 791].
+ @param [in] IP The multicast IP address that is to be converted to a
+ multicast HW MAC address.
+ @param [in] MAC The multicast HW MAC address that is to be generated from IP.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The network inteface is not in the right (initialized) state.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GenetSimpleNetworkMCastIPtoMAC (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
+ IN BOOLEAN IPv6,
+ IN EFI_IP_ADDRESS *IP,
+ OUT EFI_MAC_ADDRESS *MAC
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+///
+/// Simple Network Protocol instance
+///
+CONST EFI_SIMPLE_NETWORK_PROTOCOL gGenetSimpleNetworkTemplate = {
+ EFI_SIMPLE_NETWORK_PROTOCOL_REVISION, // Revision
+ GenetSimpleNetworkStart, // Start
+ GenetSimpleNetworkStop, // Stop
+ GenetSimpleNetworkInitialize, // Initialize
+ GenetSimpleNetworkReset, // Reset
+ GenetSimpleNetworkShutdown, // Shutdown
+ GenetSimpleNetworkReceiveFilters, // ReceiveFilters
+ GenetSimpleNetworkStationAddress, // StationAddress
+ GenetSimpleNetworkStatistics, // Statistics
+ GenetSimpleNetworkMCastIPtoMAC, // MCastIpToMac
+ GenetSimpleNetworkNvData, // NvData
+ GenetSimpleNetworkGetStatus, // GetStatus
+ GenetSimpleNetworkTransmit, // Transmit
+ GenetSimpleNetworkReceive, // Receive
+ NULL, // WaitForPacket
+ NULL // Mode
+};
--
2.17.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH edk2-platforms v2 4/7] Platform/RaspberryPi4: Clean up PCDs out of the GENET driver
2020-05-12 7:55 [PATCH edk2-platforms v2 0/7] Add Broadcom GENET driver for RPi4 Ard Biesheuvel
` (2 preceding siblings ...)
2020-05-12 7:55 ` [PATCH edk2-platforms v2 3/7] Silicon/Broadcom/BcmGenetDxe: Add GENET driver Ard Biesheuvel
@ 2020-05-12 7:55 ` Ard Biesheuvel
2020-05-12 7:55 ` [PATCH edk2-platforms v2 5/7] Platform/RaspberryPi4: Register GENET platform device protocol Ard Biesheuvel
` (5 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2020-05-12 7:55 UTC (permalink / raw)
To: devel; +Cc: leif, philmd, Ard Biesheuvel
Move PCDs from GENET driver to Raspberry Pi and Bcm27xx packages.
The Genet driver follows the UEFI driver model, so it should not have
PCDs defined that describe MMIO and MAC addresses of a single instance.
Also, move related definitions around, and update references accordingly.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
---
Platform/RaspberryPi/RaspberryPi.dec | 3 +++
Silicon/Broadcom/Bcm27xx/Bcm27xx.dec | 2 ++
Silicon/Broadcom/Drivers/Net/BcmNet.dec | 6 ------
Platform/RaspberryPi/RPi4/RPi4.dsc | 2 +-
Platform/RaspberryPi/AcpiTables/AcpiTables.inf | 2 +-
Platform/RaspberryPi/Library/PlatformPcdLib/PlatformPcdLib.inf | 5 +++--
Silicon/Broadcom/Bcm27xx/Include/IndustryStandard/Bcm2711.h | 3 +++
Silicon/Broadcom/Drivers/Net/Include/Net/Genet.h | 21 --------------------
Platform/RaspberryPi/AcpiTables/Dsdt.asl | 2 +-
9 files changed, 14 insertions(+), 32 deletions(-)
diff --git a/Platform/RaspberryPi/RaspberryPi.dec b/Platform/RaspberryPi/RaspberryPi.dec
index 1a3c44e0eb01..7a22621a6905 100644
--- a/Platform/RaspberryPi/RaspberryPi.dec
+++ b/Platform/RaspberryPi/RaspberryPi.dec
@@ -68,3 +68,6 @@ [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
gRaspberryPiTokenSpaceGuid.PcdSystemTableMode|1|UINT32|0x0000001B
gRaspberryPiTokenSpaceGuid.PcdRamMoreThan3GB|0|UINT32|0x00000019
gRaspberryPiTokenSpaceGuid.PcdRamLimitTo3GB|0|UINT32|0x0000001A
+
+[PcdsDynamic]
+ gRaspberryPiTokenSpaceGuid.PcdBcmGenetMacAddress|0x0|UINT64|0x00000040
diff --git a/Silicon/Broadcom/Bcm27xx/Bcm27xx.dec b/Silicon/Broadcom/Bcm27xx/Bcm27xx.dec
index cd6f86670d9f..2ace631f2450 100644
--- a/Silicon/Broadcom/Bcm27xx/Bcm27xx.dec
+++ b/Silicon/Broadcom/Bcm27xx/Bcm27xx.dec
@@ -24,3 +24,5 @@ [PcdsFixedAtBuild.common]
gBcm27xxTokenSpaceGuid.PcdBcm27xxPciBusMmioAdr|0x0|UINT64|0x00000003
gBcm27xxTokenSpaceGuid.PcdBcm27xxPciBusMmioLen|0x0|UINT32|0x00000004
gBcm27xxTokenSpaceGuid.PcdBcm27xxPciCpuMmioAdr|0x0|UINT64|0x00000005
+
+ gBcm27xxTokenSpaceGuid.PcdBcmGenetRegistersAddress|0x0|UINT64|0x00000006
diff --git a/Silicon/Broadcom/Drivers/Net/BcmNet.dec b/Silicon/Broadcom/Drivers/Net/BcmNet.dec
index fda3caf0b4ef..4ddda6d3d6d0 100644
--- a/Silicon/Broadcom/Drivers/Net/BcmNet.dec
+++ b/Silicon/Broadcom/Drivers/Net/BcmNet.dec
@@ -21,9 +21,3 @@ [Guids]
[Protocols]
gBcmGenetPlatformDeviceProtocolGuid = {0x5e485a22, 0x1bb0, 0x4e22, {0x85, 0x49, 0x41, 0xfc, 0xec, 0x85, 0xdf, 0xd3}}
-
-[PcdsFixedAtBuild]
- gBcmNetTokenSpaceGuid.PcdBcmGenetRegistersAddress|0x0|UINT64|0x00000001
-
-[PcdsDynamic]
- gBcmNetTokenSpaceGuid.PcdBcmGenetMacAddress|0x0|UINT64|0x00000002
diff --git a/Platform/RaspberryPi/RPi4/RPi4.dsc b/Platform/RaspberryPi/RPi4/RPi4.dsc
index ccc9eb923436..0dca782c9058 100644
--- a/Platform/RaspberryPi/RPi4/RPi4.dsc
+++ b/Platform/RaspberryPi/RPi4/RPi4.dsc
@@ -405,8 +405,8 @@ [PcdsFixedAtBuild.common]
#
gRaspberryPiTokenSpaceGuid.PcdExtendedMemoryBase|0x40000000
gBcm27xxTokenSpaceGuid.PcdBcm27xxRegistersAddress|0xfc000000
+ gBcm27xxTokenSpaceGuid.PcdBcmGenetRegistersAddress|0xfd580000
gBcm283xTokenSpaceGuid.PcdBcm283xRegistersAddress|0xfe000000
- gBcmNetTokenSpaceGuid.PcdBcmGenetRegistersAddress|0xfd580000
# PCIe specific addresses
gBcm27xxTokenSpaceGuid.PcdBcm27xxPciRegBase|0xfd500000
diff --git a/Platform/RaspberryPi/AcpiTables/AcpiTables.inf b/Platform/RaspberryPi/AcpiTables/AcpiTables.inf
index e6b7d791ab47..28d2afe19733 100644
--- a/Platform/RaspberryPi/AcpiTables/AcpiTables.inf
+++ b/Platform/RaspberryPi/AcpiTables/AcpiTables.inf
@@ -54,8 +54,8 @@ [FixedPcd]
gArmTokenSpaceGuid.PcdGicDistributorBase
gBcm27xxTokenSpaceGuid.PcdBcm27xxPciCpuMmioAdr
gBcm27xxTokenSpaceGuid.PcdBcm27xxPciRegBase
+ gBcm27xxTokenSpaceGuid.PcdBcmGenetRegistersAddress
gBcm283xTokenSpaceGuid.PcdBcm283xRegistersAddress
- gBcmNetTokenSpaceGuid.PcdBcmGenetRegistersAddress
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
gEmbeddedTokenSpaceGuid.PcdInterruptBaseAddress
gRaspberryPiTokenSpaceGuid.PcdGicInterruptInterfaceHBase
diff --git a/Platform/RaspberryPi/Library/PlatformPcdLib/PlatformPcdLib.inf b/Platform/RaspberryPi/Library/PlatformPcdLib/PlatformPcdLib.inf
index 2a207d2b3e54..c97453e4e7c1 100644
--- a/Platform/RaspberryPi/Library/PlatformPcdLib/PlatformPcdLib.inf
+++ b/Platform/RaspberryPi/Library/PlatformPcdLib/PlatformPcdLib.inf
@@ -23,6 +23,7 @@ [Packages]
MdeModulePkg/MdeModulePkg.dec
Platform/RaspberryPi/RaspberryPi.dec
Silicon/Broadcom/Drivers/Net/BcmNet.dec
+ Silicon/Broadcom/Bcm27xx/Bcm27xx.dec
[LibraryClasses]
DebugLib
@@ -34,10 +35,10 @@ [Protocols]
gRaspberryPiFirmwareProtocolGuid ## CONSUMES
[Pcd]
- gBcmNetTokenSpaceGuid.PcdBcmGenetMacAddress ## SOMETIMES_PRODUCES
+ gRaspberryPiTokenSpaceGuid.PcdBcmGenetMacAddress ## SOMETIMES_PRODUCES
[FixedPcd]
- gBcmNetTokenSpaceGuid.PcdBcmGenetRegistersAddress
+ gBcm27xxTokenSpaceGuid.PcdBcmGenetRegistersAddress
[Depex]
gRaspberryPiFirmwareProtocolGuid
diff --git a/Silicon/Broadcom/Bcm27xx/Include/IndustryStandard/Bcm2711.h b/Silicon/Broadcom/Bcm27xx/Include/IndustryStandard/Bcm2711.h
index a1609ce9b517..e9c81cafa11c 100644
--- a/Silicon/Broadcom/Bcm27xx/Include/IndustryStandard/Bcm2711.h
+++ b/Silicon/Broadcom/Bcm27xx/Include/IndustryStandard/Bcm2711.h
@@ -83,4 +83,7 @@
#define BURST_SIZE_256 1
#define BURST_SIZE_512 2
+#define GENET_BASE_ADDRESS FixedPcdGet64 (PcdBcmGenetRegistersAddress)
+#define GENET_LENGTH 0x00010000
+
#endif /* BCM2711_H__ */
diff --git a/Silicon/Broadcom/Drivers/Net/Include/Net/Genet.h b/Silicon/Broadcom/Drivers/Net/Include/Net/Genet.h
deleted file mode 100644
index f56fb2977422..000000000000
--- a/Silicon/Broadcom/Drivers/Net/Include/Net/Genet.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/** @file
-
- Copyright (c) 2020, Pete Batard <pete@akeo.ie>
-
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef BCM_GENET_H__
-#define BCM_GENET_H__
-
-#include <Library/PcdLib.h>
-
-#define GENET_BASE_ADDRESS FixedPcdGet64 (PcdBcmGenetRegistersAddress)
-#define GENET_LENGTH 0x00010000
-
-#define GENET_SYS_RBUF_FLUSH_CTRL 0x0008
-#define GENET_UMAC_MAC0 0x080c
-#define GENET_UMAC_MAC1 0x0810
-
-#endif /* BCM_GENET_H__ */
diff --git a/Platform/RaspberryPi/AcpiTables/Dsdt.asl b/Platform/RaspberryPi/AcpiTables/Dsdt.asl
index 9358750f6a64..353af2d8762b 100644
--- a/Platform/RaspberryPi/AcpiTables/Dsdt.asl
+++ b/Platform/RaspberryPi/AcpiTables/Dsdt.asl
@@ -10,13 +10,13 @@
*
**/
+#include <IndustryStandard/Bcm2711.h>
#include <IndustryStandard/Bcm2836.h>
#include <IndustryStandard/Bcm2836Gpio.h>
#include <IndustryStandard/Bcm2836Gpu.h>
#include <IndustryStandard/Bcm2836Pwm.h>
#include <IndustryStandard/Bcm2836Sdio.h>
#include <IndustryStandard/Bcm2836SdHost.h>
-#include <Net/Genet.h>
#include "AcpiTables.h"
--
2.17.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH edk2-platforms v2 5/7] Platform/RaspberryPi4: Register GENET platform device protocol
2020-05-12 7:55 [PATCH edk2-platforms v2 0/7] Add Broadcom GENET driver for RPi4 Ard Biesheuvel
` (3 preceding siblings ...)
2020-05-12 7:55 ` [PATCH edk2-platforms v2 4/7] Platform/RaspberryPi4: Clean up PCDs out of the " Ard Biesheuvel
@ 2020-05-12 7:55 ` Ard Biesheuvel
2020-05-12 14:34 ` Leif Lindholm
2020-05-12 7:55 ` [PATCH edk2-platforms v2 6/7] Platform/RaspberryPi4: Remove PlatformPcdLib Ard Biesheuvel
` (4 subsequent siblings)
9 siblings, 1 reply; 13+ messages in thread
From: Ard Biesheuvel @ 2020-05-12 7:55 UTC (permalink / raw)
To: devel; +Cc: leif, philmd, Ard Biesheuvel
Register an event at EndOfDxe to instantiate the EFI device path protocol
with the GENET MAC address on a new handle, and install the
BcmGenetPlatformDeviceProtocol on that handle. This protocol is used to
pass platform information (GENET MAC address and register base address)
to the GENET driver, which will consume this in its implementation of the
UEFI driver model Supported/Start/Stop methods.
Co-authored-by: Samer El-Haj-Mahmoud <samer.el-haj-mahmoud@arm.com>
Co-authored-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
Co-authored-by: Andrei Warkentin <awarkentin@vmware.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
---
Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.inf | 29 ++++--
Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c | 108 ++++++++++++++++++--
2 files changed, 117 insertions(+), 20 deletions(-)
diff --git a/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.inf b/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.inf
index e47f3af69199..f20f3bcc1243 100644
--- a/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.inf
+++ b/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.inf
@@ -1,6 +1,8 @@
#/** @file
#
-# Copyright (c) 2019, ARM Limited. All rights reserved.
+# Component description file for the RasbperryPi DXE platform config driver.
+#
+# Copyright (c) 2019 - 2020, ARM Limited. All rights reserved.
# Copyright (c) 2018, Andrei Warkentin <andrey.warkentin@gmail.com>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -21,7 +23,6 @@ [Defines]
#
# VALID_ARCHITECTURES = AARCH64
#
-
[Sources]
ConfigDxe.c
ConfigDxeFormSetGuid.h
@@ -31,31 +32,36 @@ [Sources]
[Packages]
ArmPkg/ArmPkg.dec
ArmPlatformPkg/ArmPlatformPkg.dec
- MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ NetworkPkg/NetworkPkg.dec
+ Platform/RaspberryPi/RaspberryPi.dec
Silicon/Broadcom/Bcm27xx/Bcm27xx.dec
Silicon/Broadcom/Bcm283x/Bcm283x.dec
- Platform/RaspberryPi/RaspberryPi.dec
- EmbeddedPkg/EmbeddedPkg.dec
+ Silicon/Broadcom/Drivers/Net/BcmNet.dec
[LibraryClasses]
+ AcpiLib
BaseLib
DebugLib
DxeServicesTableLib
+ GpioLib
+ HiiLib
+ NetLib
PcdLib
UefiBootServicesTableLib
- UefiRuntimeServicesTableLib
UefiDriverEntryPoint
- HiiLib
- GpioLib
- AcpiLib
+ UefiRuntimeServicesTableLib
[Guids]
gConfigDxeFormSetGuid
+ gEfiEndOfDxeEventGroupGuid
[Protocols]
- gRaspberryPiFirmwareProtocolGuid ## CONSUMES
- gRaspberryPiConfigAppliedProtocolGuid ## PRODUCES
+ gBcmGenetPlatformDeviceProtocolGuid ## PRODUCES
+ gRaspberryPiFirmwareProtocolGuid ## CONSUMES
+ gRaspberryPiConfigAppliedProtocolGuid ## PRODUCES
[FixedPcd]
gRaspberryPiTokenSpaceGuid.PcdCpuLowSpeedMHz
@@ -64,6 +70,7 @@ [FixedPcd]
[Pcd]
gBcm27xxTokenSpaceGuid.PcdBcm27xxRegistersAddress
+ gBcm27xxTokenSpaceGuid.PcdBcmGenetRegistersAddress
gBcm283xTokenSpaceGuid.PcdBcm283xRegistersAddress
gRaspberryPiTokenSpaceGuid.PcdCpuClock
gRaspberryPiTokenSpaceGuid.PcdCustomCpuClock
diff --git a/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c b/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c
index 00867879da20..47ca0a89a3d8 100644
--- a/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c
+++ b/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c
@@ -1,6 +1,6 @@
/** @file
*
- * Copyright (c) 2019, ARM Limited. All rights reserved.
+ * Copyright (c) 2019 - 2020, ARM Limited. All rights reserved.
* Copyright (c) 2018 - 2019, Andrei Warkentin <andrey.warkentin@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -8,19 +8,21 @@
**/
#include <Uefi.h>
+#include <IndustryStandard/Bcm2711.h>
+#include <IndustryStandard/Bcm2836.h>
+#include <IndustryStandard/Bcm2836Gpio.h>
+#include <IndustryStandard/RpiMbox.h>
#include <Library/AcpiLib.h>
-#include <Library/HiiLib.h>
#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
#include <Library/DxeServicesTableLib.h>
+#include <Library/GpioLib.h>
+#include <Library/HiiLib.h>
#include <Library/IoLib.h>
+#include <Library/NetLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
-#include <Library/DevicePathLib.h>
-#include <IndustryStandard/RpiMbox.h>
-#include <IndustryStandard/Bcm2711.h>
-#include <IndustryStandard/Bcm2836.h>
-#include <IndustryStandard/Bcm2836Gpio.h>
-#include <Library/GpioLib.h>
+#include <Protocol/BcmGenetPlatformDevice.h>
#include <Protocol/RpiFirmware.h>
#include <ConfigVars.h>
#include "ConfigDxeFormSetGuid.h"
@@ -34,6 +36,8 @@ STATIC RASPBERRY_PI_FIRMWARE_PROTOCOL *mFwProtocol;
STATIC UINT32 mModelFamily = 0;
STATIC UINT32 mModelInstalledMB = 0;
+STATIC EFI_MAC_ADDRESS MacAddress;
+
/*
* The GUID inside Platform/RaspberryPi/RPi3/AcpiTables/AcpiTables.inf and
* Platform/RaspberryPi/RPi4/AcpiTables/AcpiTables.inf _must_ match below.
@@ -47,6 +51,18 @@ typedef struct {
EFI_DEVICE_PATH_PROTOCOL End;
} HII_VENDOR_DEVICE_PATH;
+#pragma pack (1)
+typedef struct {
+ MAC_ADDR_DEVICE_PATH MacAddrDP;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} GENET_DEVICE_PATH;
+
+typedef struct {
+ GENET_DEVICE_PATH DevicePath;
+ BCM_GENET_PLATFORM_DEVICE_PROTOCOL PlatformDevice;
+} GENET_DEVICE;
+#pragma pack ()
+
STATIC HII_VENDOR_DEVICE_PATH mVendorDevicePath = {
{
{
@@ -69,6 +85,65 @@ STATIC HII_VENDOR_DEVICE_PATH mVendorDevicePath = {
}
};
+STATIC GENET_DEVICE mGenetDevice = {
+ {
+ {
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_MAC_ADDR_DP,
+ {
+ (UINT8)(sizeof (MAC_ADDR_DEVICE_PATH)),
+ (UINT8)((sizeof (MAC_ADDR_DEVICE_PATH)) >> 8)
+ }
+ },
+ {{ 0 }},
+ NET_IFTYPE_ETHERNET
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ sizeof (EFI_DEVICE_PATH_PROTOCOL),
+ 0
+ }
+ }
+ },
+ {
+ GENET_BASE_ADDRESS,
+ {{ 0 }}
+ }
+};
+
+
+STATIC
+VOID
+EFIAPI
+RegisterDevices (
+ EFI_EVENT Event,
+ VOID *Context
+ )
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+
+ if (mModelFamily == 4) {
+ DEBUG ((DEBUG_INFO, "GENET: MAC address %02X:%02X:%02X:%02X:%02X:%02X\n",
+ MacAddress.Addr[0], MacAddress.Addr[1], MacAddress.Addr[2],
+ MacAddress.Addr[3], MacAddress.Addr[4], MacAddress.Addr[5]));
+
+ CopyMem (&mGenetDevice.DevicePath.MacAddrDP.MacAddress, MacAddress.Addr,
+ NET_ETHER_ADDR_LEN);
+ CopyMem (&mGenetDevice.PlatformDevice.MacAddress, MacAddress.Addr,
+ NET_ETHER_ADDR_LEN);
+
+ Handle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (&Handle,
+ &gEfiDevicePathProtocolGuid, &mGenetDevice.DevicePath,
+ &gBcmGenetPlatformDeviceProtocolGuid, &mGenetDevice.PlatformDevice,
+ NULL);
+ ASSERT_EFI_ERROR (Status);
+ }
+}
STATIC EFI_STATUS
InstallHiiPages (
@@ -242,6 +317,16 @@ SetupVariables (
PcdSet32 (PcdDisplayEnableSShot, PcdGet32 (PcdDisplayEnableSShot));
}
+ if (mModelFamily == 4) {
+ //
+ // Get the MAC address from the firmware.
+ //
+ Status = mFwProtocol->GetMacAddress (MacAddress.Addr);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "%a: failed to retrieve MAC address\n", __FUNCTION__));
+ }
+ }
+
return EFI_SUCCESS;
}
@@ -448,7 +533,8 @@ ConfigInitialize (
IN EFI_SYSTEM_TABLE *SystemTable
)
{
- EFI_STATUS Status;
+ EFI_STATUS Status;
+ EFI_EVENT EndOfDxeEvent;
Status = gBS->LocateProtocol (&gRaspberryPiFirmwareProtocolGuid,
NULL, (VOID**)&mFwProtocol);
@@ -494,5 +580,9 @@ ConfigInitialize (
ASSERT_EFI_ERROR (Status);
}
+ Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY, RegisterDevices,
+ NULL, &gEfiEndOfDxeEventGroupGuid, &EndOfDxeEvent);
+ ASSERT_EFI_ERROR (Status);
+
return EFI_SUCCESS;
}
--
2.17.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH edk2-platforms v2 6/7] Platform/RaspberryPi4: Remove PlatformPcdLib
2020-05-12 7:55 [PATCH edk2-platforms v2 0/7] Add Broadcom GENET driver for RPi4 Ard Biesheuvel
` (4 preceding siblings ...)
2020-05-12 7:55 ` [PATCH edk2-platforms v2 5/7] Platform/RaspberryPi4: Register GENET platform device protocol Ard Biesheuvel
@ 2020-05-12 7:55 ` Ard Biesheuvel
2020-05-12 7:55 ` [PATCH edk2-platforms v2 7/7] Platform/RaspberryPi4: remove ASIX 88772b driver Ard Biesheuvel
` (3 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2020-05-12 7:55 UTC (permalink / raw)
To: devel; +Cc: leif, philmd, Andrei Warkentin, Ard Biesheuvel
From: Andrei Warkentin <awarkentin@vmware.com>
Remove the PlatformPcdLib. It is completely unnecessary. Originally,
this was meant for the GENET driver, but now that ConfigDxe registers
the platform device, the library is superfluous.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
---
Platform/RaspberryPi/RaspberryPi.dec | 3 --
Platform/RaspberryPi/RPi4/RPi4.dsc | 2 -
Platform/RaspberryPi/Library/PlatformPcdLib/PlatformPcdLib.inf | 44 -------------------
Platform/RaspberryPi/Library/PlatformPcdLib/PlatformPcdLib.c | 45 --------------------
4 files changed, 94 deletions(-)
diff --git a/Platform/RaspberryPi/RaspberryPi.dec b/Platform/RaspberryPi/RaspberryPi.dec
index 7a22621a6905..1a3c44e0eb01 100644
--- a/Platform/RaspberryPi/RaspberryPi.dec
+++ b/Platform/RaspberryPi/RaspberryPi.dec
@@ -68,6 +68,3 @@ [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
gRaspberryPiTokenSpaceGuid.PcdSystemTableMode|1|UINT32|0x0000001B
gRaspberryPiTokenSpaceGuid.PcdRamMoreThan3GB|0|UINT32|0x00000019
gRaspberryPiTokenSpaceGuid.PcdRamLimitTo3GB|0|UINT32|0x0000001A
-
-[PcdsDynamic]
- gRaspberryPiTokenSpaceGuid.PcdBcmGenetMacAddress|0x0|UINT64|0x00000040
diff --git a/Platform/RaspberryPi/RPi4/RPi4.dsc b/Platform/RaspberryPi/RPi4/RPi4.dsc
index 0dca782c9058..5910082deb04 100644
--- a/Platform/RaspberryPi/RPi4/RPi4.dsc
+++ b/Platform/RaspberryPi/RPi4/RPi4.dsc
@@ -683,8 +683,6 @@ [Components.common]
#
!include NetworkPkg/Network.dsc.inc
Silicon/Broadcom/Drivers/Net/BcmGenetDxe/BcmGenetDxe.inf {
- <LibraryClasses>
- NULL|Platform/RaspberryPi/Library/PlatformPcdLib/PlatformPcdLib.inf
<PcdsFixedAtBuild>
gEmbeddedTokenSpaceGuid.PcdDmaDeviceOffset|0x00000000
gEmbeddedTokenSpaceGuid.PcdDmaDeviceLimit|0xffffffff
diff --git a/Platform/RaspberryPi/Library/PlatformPcdLib/PlatformPcdLib.inf b/Platform/RaspberryPi/Library/PlatformPcdLib/PlatformPcdLib.inf
deleted file mode 100644
index c97453e4e7c1..000000000000
--- a/Platform/RaspberryPi/Library/PlatformPcdLib/PlatformPcdLib.inf
+++ /dev/null
@@ -1,44 +0,0 @@
-#/** @file
-#
-# Copyright (c) 2020, Pete Batard <pete@akeo.ie>
-#
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-#**/
-
-[Defines]
- INF_VERSION = 0x0001001A
- BASE_NAME = PlatformPcdLib
- FILE_GUID = 3B8409D7-D3C7-4006-823B-BFB184435363
- MODULE_TYPE = DXE_DRIVER
- VERSION_STRING = 1.0
- LIBRARY_CLASS = NULL|DXE_DRIVER UEFI_APPLICATION
- CONSTRUCTOR = PlatformPcdLibConstructor
-
-[Sources]
- PlatformPcdLib.c
-
-[Packages]
- MdePkg/MdePkg.dec
- MdeModulePkg/MdeModulePkg.dec
- Platform/RaspberryPi/RaspberryPi.dec
- Silicon/Broadcom/Drivers/Net/BcmNet.dec
- Silicon/Broadcom/Bcm27xx/Bcm27xx.dec
-
-[LibraryClasses]
- DebugLib
- PcdLib
- UefiLib
- PrintLib
-
-[Protocols]
- gRaspberryPiFirmwareProtocolGuid ## CONSUMES
-
-[Pcd]
- gRaspberryPiTokenSpaceGuid.PcdBcmGenetMacAddress ## SOMETIMES_PRODUCES
-
-[FixedPcd]
- gBcm27xxTokenSpaceGuid.PcdBcmGenetRegistersAddress
-
-[Depex]
- gRaspberryPiFirmwareProtocolGuid
diff --git a/Platform/RaspberryPi/Library/PlatformPcdLib/PlatformPcdLib.c b/Platform/RaspberryPi/Library/PlatformPcdLib/PlatformPcdLib.c
deleted file mode 100644
index e78518c81374..000000000000
--- a/Platform/RaspberryPi/Library/PlatformPcdLib/PlatformPcdLib.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/** @file
- *
- * Copyright (c) 2020, Pete Batard <pete@akeo.ie>
- *
- * SPDX-License-Identifier: BSD-2-Clause-Patent
- *
- **/
-
-#include <Library/DebugLib.h>
-#include <Library/PcdLib.h>
-#include <Library/PrintLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/UefiLib.h>
-#include <Library/UefiRuntimeServicesTableLib.h>
-#include <Protocol/RpiFirmware.h>
-
-EFI_STATUS
-EFIAPI
-PlatformPcdLibConstructor (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- EFI_STATUS Status;
- UINT64 MacAddr;
- RASPBERRY_PI_FIRMWARE_PROTOCOL *mFwProtocol;
-
- if (PcdGet64 (PcdBcmGenetMacAddress) == 0) {
- Status = gBS->LocateProtocol (&gRaspberryPiFirmwareProtocolGuid, NULL,
- (VOID**)&mFwProtocol);
- ASSERT_EFI_ERROR(Status);
-
- //
- // Get the MAC address from the firmware
- //
- Status = mFwProtocol->GetMacAddress ((UINT8*) &MacAddr);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_WARN, "%a: failed to retrieve MAC address\n", __FUNCTION__));
- } else {
- PcdSet64S (PcdBcmGenetMacAddress, MacAddr);
- }
- }
-
- return EFI_SUCCESS;
-}
--
2.17.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH edk2-platforms v2 7/7] Platform/RaspberryPi4: remove ASIX 88772b driver
2020-05-12 7:55 [PATCH edk2-platforms v2 0/7] Add Broadcom GENET driver for RPi4 Ard Biesheuvel
` (5 preceding siblings ...)
2020-05-12 7:55 ` [PATCH edk2-platforms v2 6/7] Platform/RaspberryPi4: Remove PlatformPcdLib Ard Biesheuvel
@ 2020-05-12 7:55 ` Ard Biesheuvel
2020-05-12 8:26 ` [PATCH edk2-platforms v2 0/7] Add Broadcom GENET driver for RPi4 Ard Biesheuvel
` (2 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2020-05-12 7:55 UTC (permalink / raw)
To: devel; +Cc: leif, philmd, Ard Biesheuvel
The Raspberry Pi4 has gigabit ethernet builtin, for which we now
have a UEFI driver. So no need for the ASIX 88772b driver.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
Reviewed-by: Andrei Warkentin <andrey.warkentin@gmail.com>
Reviewed-by: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>
---
Platform/RaspberryPi/RPi4/RPi4.dsc | 1 -
Platform/RaspberryPi/RPi4/RPi4.fdf | 1 -
2 files changed, 2 deletions(-)
diff --git a/Platform/RaspberryPi/RPi4/RPi4.dsc b/Platform/RaspberryPi/RPi4/RPi4.dsc
index 5910082deb04..cbff9d9946e2 100644
--- a/Platform/RaspberryPi/RPi4/RPi4.dsc
+++ b/Platform/RaspberryPi/RPi4/RPi4.dsc
@@ -669,7 +669,6 @@ [Components.common]
MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
- Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772b/Ax88772b.inf
#
# SD/MMC support
diff --git a/Platform/RaspberryPi/RPi4/RPi4.fdf b/Platform/RaspberryPi/RPi4/RPi4.fdf
index b1f7aa2387df..1e13909a57ba 100644
--- a/Platform/RaspberryPi/RPi4/RPi4.fdf
+++ b/Platform/RaspberryPi/RPi4/RPi4.fdf
@@ -293,7 +293,6 @@ [FV.FvMain]
INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
INF MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
- INF Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772b/Ax88772b.inf
#
# SD/MMC support
--
2.17.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH edk2-platforms v2 0/7] Add Broadcom GENET driver for RPi4
2020-05-12 7:55 [PATCH edk2-platforms v2 0/7] Add Broadcom GENET driver for RPi4 Ard Biesheuvel
` (6 preceding siblings ...)
2020-05-12 7:55 ` [PATCH edk2-platforms v2 7/7] Platform/RaspberryPi4: remove ASIX 88772b driver Ard Biesheuvel
@ 2020-05-12 8:26 ` Ard Biesheuvel
2020-05-12 14:28 ` Ard Biesheuvel
2020-05-12 14:35 ` Leif Lindholm
9 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2020-05-12 8:26 UTC (permalink / raw)
To: devel
Cc: leif, philmd, Pete Batard, Jared McNeill, Andrei Warkentin,
Samer El-Haj-Mahmoud, Jeremy Linton
On 5/12/20 9:55 AM, Ard Biesheuvel wrote:
> This is a followup to Samer's v1 [0], and incorporates all the delta
> changes posted for review over the past couple of days. This is a
> roundup of all that work, and therefore supersedes it.
>
> It provides an implementation of the SimpleNetworkProtocol for the
> Raspberry Pi4's GENET network controller, in a way that adheres to the
> UEFI driver model.
>
> The original submission was provided by Jared, based on Jeremy's MAC
> programming-only driver and the existing BSD driver for the GENET IP.
> Cumulative changes and fixes as well as review feedback were provided
> by all of the below.
>
> https://github.com/ardbiesheuvel/edk2-platforms/tree/rpi4_genet_combi_v2
>
> Cc: Pete Batard <pete@akeo.ie>
> Cc: Jared McNeill <jmcneill@invisible.ca>
> Cc: Andrei Warkentin <awarkentin@vmware.com>
> Cc: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>
> Cc: Jeremy Linton <jeremy.linton@arm.com>
>
[0] https://edk2.groups.io/g/devel/message/58903
> Andrei Warkentin (1):
> Platform/RaspberryPi4: Remove PlatformPcdLib
>
> Ard Biesheuvel (6):
> Platform/RaspberryPi4: set DMA translation for BCM Genet driver
> Silicon/Broadcom: Add BcmGenetPlatformDevice protocol
> Silicon/Broadcom/BcmGenetDxe: Add GENET driver
> Platform/RaspberryPi4: Clean up PCDs out of the GENET driver
> Platform/RaspberryPi4: Register GENET platform device protocol
> Platform/RaspberryPi4: remove ASIX 88772b driver
>
> Silicon/Broadcom/Bcm27xx/Bcm27xx.dec | 2 +
> Silicon/Broadcom/Drivers/Net/BcmNet.dec | 8 +-
> Platform/RaspberryPi/RPi4/RPi4.dsc | 8 +-
> Platform/RaspberryPi/RPi4/RPi4.fdf | 1 -
> .../RaspberryPi/AcpiTables/AcpiTables.inf | 2 +-
> .../Drivers/ConfigDxe/ConfigDxe.inf | 29 +-
> .../Library/PlatformPcdLib/PlatformPcdLib.inf | 43 -
> .../Drivers/Net/BcmGenetDxe/BcmGenetDxe.inf | 46 +-
> .../Include/IndustryStandard/Bcm2711.h | 3 +
> .../Drivers/Net/BcmGenetDxe/GenericPhy.h | 106 +++
> .../Drivers/Net/BcmGenetDxe/GenetUtil.h | 364 ++++++++
> .../Broadcom/Drivers/Net/Include/Net/Genet.h | 21 -
> .../Include/Protocol/BcmGenetPlatformDevice.h | 24 +
> .../RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c | 108 ++-
> .../Library/PlatformPcdLib/PlatformPcdLib.c | 45 -
> .../Drivers/Net/BcmGenetDxe/ComponentName.c | 198 +++++
> .../Drivers/Net/BcmGenetDxe/DriverBinding.c | 408 +++++++++
> .../Drivers/Net/BcmGenetDxe/GenericPhy.c | 405 +++++++++
> .../Broadcom/Drivers/Net/BcmGenetDxe/Genet.c | 114 ---
> .../Drivers/Net/BcmGenetDxe/GenetUtil.c | 816 +++++++++++++++++
> .../Drivers/Net/BcmGenetDxe/SimpleNetwork.c | 834 ++++++++++++++++++
> Platform/RaspberryPi/AcpiTables/Dsdt.asl | 2 +-
> 22 files changed, 3319 insertions(+), 268 deletions(-)
> delete mode 100644 Platform/RaspberryPi/Library/PlatformPcdLib/PlatformPcdLib.inf
> create mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenericPhy.h
> create mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenetUtil.h
> delete mode 100644 Silicon/Broadcom/Drivers/Net/Include/Net/Genet.h
> create mode 100644 Silicon/Broadcom/Drivers/Net/Include/Protocol/BcmGenetPlatformDevice.h
> delete mode 100644 Platform/RaspberryPi/Library/PlatformPcdLib/PlatformPcdLib.c
> create mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/ComponentName.c
> create mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/DriverBinding.c
> create mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenericPhy.c
> delete mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/Genet.c
> create mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenetUtil.c
> create mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/SimpleNetwork.c
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH edk2-platforms v2 0/7] Add Broadcom GENET driver for RPi4
2020-05-12 7:55 [PATCH edk2-platforms v2 0/7] Add Broadcom GENET driver for RPi4 Ard Biesheuvel
` (7 preceding siblings ...)
2020-05-12 8:26 ` [PATCH edk2-platforms v2 0/7] Add Broadcom GENET driver for RPi4 Ard Biesheuvel
@ 2020-05-12 14:28 ` Ard Biesheuvel
2020-05-12 14:35 ` Leif Lindholm
9 siblings, 0 replies; 13+ messages in thread
From: Ard Biesheuvel @ 2020-05-12 14:28 UTC (permalink / raw)
To: devel
Cc: leif, philmd, Pete Batard, Jared McNeill, Andrei Warkentin,
Samer El-Haj-Mahmoud, Jeremy Linton
On 5/12/20 9:55 AM, Ard Biesheuvel wrote:
> This is a followup to Samer's v1 [0], and incorporates all the delta
> changes posted for review over the past couple of days. This is a
> roundup of all that work, and therefore supersedes it.
>
> It provides an implementation of the SimpleNetworkProtocol for the
> Raspberry Pi4's GENET network controller, in a way that adheres to the
> UEFI driver model.
>
> The original submission was provided by Jared, based on Jeremy's MAC
> programming-only driver and the existing BSD driver for the GENET IP.
> Cumulative changes and fixes as well as review feedback were provided
> by all of the below.
>
> https://github.com/ardbiesheuvel/edk2-platforms/tree/rpi4_genet_combi_v2
>
FYI in an off list discussion, Leif pointed out the the practice of
having one 'master' .h file including everything, which is included by
the .c files is not acceptable practice, even though it is widespread in
EDK2.
I pushed a delta patch to the branch above that fixes this, but I will
wait for other feedback before sending it out, or sending out a v3,
whichever is more appropriate.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [edk2-devel] [PATCH edk2-platforms v2 3/7] Silicon/Broadcom/BcmGenetDxe: Add GENET driver
2020-05-12 7:55 ` [PATCH edk2-platforms v2 3/7] Silicon/Broadcom/BcmGenetDxe: Add GENET driver Ard Biesheuvel
@ 2020-05-12 14:31 ` Leif Lindholm
0 siblings, 0 replies; 13+ messages in thread
From: Leif Lindholm @ 2020-05-12 14:31 UTC (permalink / raw)
To: devel, ard.biesheuvel; +Cc: philmd
On Tue, May 12, 2020 at 09:55:08 +0200, Ard Biesheuvel wrote:
> Add support for the Broadcom GENET v5 ethernet controller
> for the Raspberry Pi 4 (BCM2711)
>
> Co-authored-by: Jared McNeill <jmcneill@invisible.ca>
> Co-authored-by: Andrei Warkentin <awarkentin@vmware.com>
> Co-authored-by: Samer El-Haj-Mahmoud <samer.el-haj-mahmoud@arm.com>
> Co-authored-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
> ---
> Silicon/Broadcom/Drivers/Net/BcmGenetDxe/BcmGenetDxe.inf | 46 +-
> Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenericPhy.h | 106 +++
> Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenetUtil.h | 364 +++++++++
> Silicon/Broadcom/Drivers/Net/BcmGenetDxe/ComponentName.c | 198 +++++
> Silicon/Broadcom/Drivers/Net/BcmGenetDxe/DriverBinding.c | 408 ++++++++++
> Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenericPhy.c | 405 ++++++++++
> Silicon/Broadcom/Drivers/Net/BcmGenetDxe/Genet.c | 114 ---
> Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenetUtil.c | 816 +++++++++++++++++++
> Silicon/Broadcom/Drivers/Net/BcmGenetDxe/SimpleNetwork.c | 834 ++++++++++++++++++++
> 9 files changed, 3164 insertions(+), 127 deletions(-)
>
> diff --git a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/BcmGenetDxe.inf b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/BcmGenetDxe.inf
> index 9e9301608f24..3e98983c6b07 100644
> --- a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/BcmGenetDxe.inf
> +++ b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/BcmGenetDxe.inf
> @@ -1,40 +1,60 @@
> ## @file
> +# Component description file for Broadcom GENET driver.
> #
> +# Copyright (c) 2020, Jared McNeill All rights reserved.<BR>
> # Copyright (c) 2020, Jeremy Linton All rights reserved.<BR>
> +# Copyright (c) 2020, ARM Limited. All rights reserved.<BR>
> #
> # SPDX-License-Identifier: BSD-2-Clause-Patent
> #
> ##
>
> [Defines]
> - INF_VERSION = 0x0001001A
> + INF_VERSION = 1.27
> BASE_NAME = BcmGenetDxe
> FILE_GUID = e2b1eaf3-50b7-4ae1-b79e-ec8020cb57ac
> - MODULE_TYPE = DXE_DRIVER
> - VERSION_STRING = 0.1
> + MODULE_TYPE = UEFI_DRIVER
> + VERSION_STRING = 1.0
> ENTRY_POINT = GenetEntryPoint
> + UNLOAD_IMAGE = GenetUnload
>
> [Sources]
> - Genet.c
> + ComponentName.c
> + DriverBinding.c
> + GenericPhy.c
> + GenericPhy.h
> + GenetUtil.c
> + GenetUtil.h
> + SimpleNetwork.c
>
> [Packages]
> - ArmPkg/ArmPkg.dec
> + EmbeddedPkg/EmbeddedPkg.dec
> MdeModulePkg/MdeModulePkg.dec
> MdePkg/MdePkg.dec
> + NetworkPkg/NetworkPkg.dec
> Silicon/Broadcom/Drivers/Net/BcmNet.dec
>
> [LibraryClasses]
> - ArmLib
> BaseLib
> + BaseMemoryLib
> + DebugLib
> + DevicePathLib
> + DmaLib
> IoLib
> + MemoryAllocationLib
> + NetLib
> + UefiBootServicesTableLib
> UefiDriverEntryPoint
> UefiLib
>
> +[Protocols]
> + gBcmGenetPlatformDeviceProtocolGuid ## TO_START
> + gEfiDevicePathProtocolGuid ## BY_START
> + gEfiSimpleNetworkProtocolGuid ## BY_START
> +
> +[Guids]
> + gEfiEventExitBootServicesGuid
> +
> [FixedPcd]
> - gBcmNetTokenSpaceGuid.PcdBcmGenetRegistersAddress
> -
> -[Pcd]
> - gBcmNetTokenSpaceGuid.PcdBcmGenetMacAddress
> -
> -[Depex]
> - TRUE
> + gEmbeddedTokenSpaceGuid.PcdDmaDeviceOffset
> + gEmbeddedTokenSpaceGuid.PcdDmaDeviceLimit
> diff --git a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenericPhy.h b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenericPhy.h
> new file mode 100644
> index 000000000000..58b52722b4e3
> --- /dev/null
> +++ b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenericPhy.h
> @@ -0,0 +1,106 @@
> +/** @file
> +
> + Copyright (c) 2020 Jared McNeill. All rights reserved.
> + Copyright (c) 2020 Andrey Warkentin <andrey.warkentin@gmail.com>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef GENERICPHY_H__
> +#define GENERICPHY_H__
> +
> +#define GENERIC_PHY_BMCR 0x00
> +#define GENERIC_PHY_BMCR_RESET BIT15
> +#define GENERIC_PHY_BMCR_ANE BIT12
> +#define GENERIC_PHY_BMCR_RESTART_AN BIT9
> +#define GENERIC_PHY_BMSR 0x01
> +#define GENERIC_PHY_BMSR_ANEG_COMPLETE BIT5
> +#define GENERIC_PHY_BMSR_LINK_STATUS BIT2
> +#define GENERIC_PHY_PHYIDR1 0x02
> +#define GENERIC_PHY_PHYIDR2 0x03
> +#define GENERIC_PHY_ANAR 0x04
> +#define GENERIC_PHY_ANAR_100BASETX_FDX BIT8
> +#define GENERIC_PHY_ANAR_100BASETX BIT7
> +#define GENERIC_PHY_ANAR_10BASET_FDX BIT6
> +#define GENERIC_PHY_ANAR_10BASET BIT5
> +#define GENERIC_PHY_ANLPAR 0x05
> +#define GENERIC_PHY_GBCR 0x09
> +#define GENERIC_PHY_GBCR_1000BASET_FDX BIT9
> +#define GENERIC_PHY_GBCR_1000BASET BIT8
> +#define GENERIC_PHY_GBSR 0x0A
> +
> +typedef enum {
> + PHY_SPEED_NONE = 0,
> + PHY_SPEED_10 = 10,
> + PHY_SPEED_100 = 100,
> + PHY_SPEED_1000 = 1000
> +} GENERIC_PHY_SPEED;
> +
> +typedef enum {
> + PHY_DUPLEX_HALF,
> + PHY_DUPLEX_FULL
> +} GENERIC_PHY_DUPLEX;
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *GENERIC_PHY_READ) (
> + IN VOID *Priv,
> + IN UINT8 PhyAddr,
> + IN UINT8 Reg,
> + OUT UINT16 * Data
> + );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *GENERIC_PHY_WRITE) (
> + IN VOID *Priv,
> + IN UINT8 PhyAddr,
> + IN UINT8 Reg,
> + IN UINT16 Data
> + );
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *GENERIC_PHY_RESET_ACTION) (
> + IN VOID *Priv
> + );
> +
> +typedef
> +VOID
> +(EFIAPI *GENERIC_PHY_CONFIGURE) (
> + IN VOID *Priv,
> + IN GENERIC_PHY_SPEED Speed,
> + IN GENERIC_PHY_DUPLEX Duplex
> + );
> +
> +typedef struct {
> + GENERIC_PHY_READ Read;
> + GENERIC_PHY_WRITE Write;
> + GENERIC_PHY_RESET_ACTION ResetAction;
> + GENERIC_PHY_CONFIGURE Configure;
> + VOID *PrivateData;
> +
> + UINT8 PhyAddr;
> + BOOLEAN LinkUp;
> +} GENERIC_PHY_PRIVATE_DATA;
> +
> +EFI_STATUS
> +EFIAPI
> +GenericPhyInit (
> + IN GENERIC_PHY_PRIVATE_DATA *Phy
> + );
> +
> +EFI_STATUS
> +EFIAPI
> +GenericPhyUpdateConfig (
> + IN GENERIC_PHY_PRIVATE_DATA *Phy
> + );
> +
> +EFI_STATUS
> +EFIAPI
> +GenericPhyReset (
> + IN GENERIC_PHY_PRIVATE_DATA *Phy
> + );
> +
> +#endif // GENERICPHY_H__
> diff --git a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenetUtil.h b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenetUtil.h
> new file mode 100644
> index 000000000000..5ae2e0bad273
> --- /dev/null
> +++ b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenetUtil.h
> @@ -0,0 +1,364 @@
> +/** @file
> +
> + Copyright (c) 2020 Jared McNeill <jmcneill@invisible.ca>
> + Copyright (c) 2020, ARM Limited. All rights reserved.
> + Copyright (c) 2020 Andrey Warkentin <andrey.warkentin@gmail.com>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef GENET_UTIL_H__
> +#define GENET_UTIL_H__
> +
> +#include <Uefi.h>
> +
> +#include <Protocol/DriverSupportedEfiVersion.h>
> +#include <Protocol/BcmGenetPlatformDevice.h>
> +#include <Protocol/SimpleNetwork.h>
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/NetLib.h>
> +#include <Library/UefiLib.h>
Could we make sure this file includes only those headers it needs for
itself? (As per https://edk2-docs.gitbook.io/edk-ii-c-coding-standards-specification/5_source_files/53_include_files#5-3-4-include-files-may-include-only-those-headers-that-it-directly-depends-upon)
> +
> +#include "GenericPhy.h"
> +
> +/*
> + * Aux control shadow register, bits 0-2 select function (0x00 to
> + * 0x07).
> + */
> +#define BRGPHY_MII_AUXCTL 0x18 /* AUX control */
> +#define BRGPHY_AUXCTL_SHADOW_MISC 0x07
> +#define BRGPHY_AUXCTL_MISC_DATA_MASK 0x7ff8
> +#define BRGPHY_AUXCTL_MISC_READ_SHIFT 12
> +#define BRGPHY_AUXCTL_MISC_WRITE_EN 0x8000
> +#define BRGPHY_AUXCTL_MISC_RGMII_SKEW_EN 0x0200
> +
> +/*
> + * Shadow register 0x1C, bit 15 is write enable,
> + * bits 14-10 select function (0x00 to 0x1F).
> + */
> +#define BRGPHY_MII_SHADOW_1C 0x1C
> +#define BRGPHY_SHADOW_1C_WRITE_EN 0x8000
> +#define BRGPHY_SHADOW_1C_SELECT_MASK 0x7C00
> +#define BRGPHY_SHADOW_1C_DATA_MASK 0x03FF
> +
> +/* Shadow 0x1C Clock Alignment Control Register (select value 0x03) */
> +#define BRGPHY_SHADOW_1C_CLK_CTRL (0x03 << 10)
> +#define BRGPHY_SHADOW_1C_GTXCLK_EN 0x0200
> +
> +#define MAX_ETHERNET_PKT_SIZE 1500
> +
> +#define GENET_VERSION 0x0a
> +#define GENET_MAX_PACKET_SIZE 1536
> +
> +#define GENET_SYS_REV_CTRL 0x000
> +#define SYS_REV_MAJOR (BIT27|BIT26|BIT25|BIT24)
> +#define SYS_REV_MINOR (BIT19|BIT18|BIT17|BIT16)
> +#define GENET_SYS_PORT_CTRL 0x004
> +#define GENET_SYS_PORT_MODE_EXT_GPHY 3
> +#define GENET_SYS_RBUF_FLUSH_CTRL 0x008
> +#define GENET_SYS_RBUF_FLUSH_RESET BIT1
> +#define GENET_SYS_TBUF_FLUSH_CTRL 0x00c
> +#define GENET_EXT_RGMII_OOB_CTRL 0x08c
> +#define GENET_EXT_RGMII_OOB_ID_MODE_DISABLE BIT16
> +#define GENET_EXT_RGMII_OOB_RGMII_MODE_EN BIT6
> +#define GENET_EXT_RGMII_OOB_OOB_DISABLE BIT5
> +#define GENET_EXT_RGMII_OOB_RGMII_LINK BIT4
> +#define GENET_INTRL2_CPU_STAT 0x200
> +#define GENET_INTRL2_CPU_CLEAR 0x208
> +#define GENET_INTRL2_CPU_STAT_MASK 0x20c
> +#define GENET_INTRL2_CPU_SET_MASK 0x210
> +#define GENET_INTRL2_CPU_CLEAR_MASK 0x214
> +#define GENET_IRQ_MDIO_ERROR BIT24
> +#define GENET_IRQ_MDIO_DONE BIT23
> +#define GENET_IRQ_TXDMA_DONE BIT16
> +#define GENET_IRQ_RXDMA_DONE BIT13
> +#define GENET_RBUF_CTRL 0x300
> +#define GENET_RBUF_BAD_DIS BIT2
> +#define GENET_RBUF_ALIGN_2B BIT1
> +#define GENET_RBUF_64B_EN BIT0
> +#define GENET_RBUF_TBUF_SIZE_CTRL 0x3b4
> +#define GENET_UMAC_CMD 0x808
> +#define GENET_UMAC_CMD_LCL_LOOP_EN BIT15
> +#define GENET_UMAC_CMD_SW_RESET BIT13
> +#define GENET_UMAC_CMD_HD_EN BIT10
> +#define GENET_UMAC_CMD_PROMISC BIT4
> +#define GENET_UMAC_CMD_SPEED (BIT3|BIT2)
> +#define GENET_UMAC_CMD_SPEED_10 0
> +#define GENET_UMAC_CMD_SPEED_100 1
> +#define GENET_UMAC_CMD_SPEED_1000 2
> +#define GENET_UMAC_CMD_RXEN BIT1
> +#define GENET_UMAC_CMD_TXEN BIT0
> +#define GENET_UMAC_MAC0 0x80c
> +#define GENET_UMAC_MAC1 0x810
> +#define GENET_UMAC_MAX_FRAME_LEN 0x814
> +#define GENET_UMAC_TX_FLUSH 0xb34
> +#define GENET_UMAC_MIB_CTRL 0xd80
> +#define GENET_UMAC_MIB_RESET_TX BIT2
> +#define GENET_UMAC_MIB_RESET_RUNT BIT1
> +#define GENET_UMAC_MIB_RESET_RX BIT0
> +#define GENET_MDIO_CMD 0xe14
> +#define GENET_MDIO_START_BUSY BIT29
> +#define GENET_MDIO_READ BIT27
> +#define GENET_MDIO_WRITE BIT26
> +#define GENET_MDIO_PMD (BIT25|BIT24|BIT23|BIT22|BIT21)
> +#define GENET_MDIO_REG (BIT20|BIT19|BIT18|BIT17|BIT16)
> +#define GENET_UMAC_MDF_CTRL 0xe50
> +#define GENET_UMAC_MDF_ADDR0(n) (0xe54 + (n) * 0x8)
> +#define GENET_UMAC_MDF_ADDR1(n) (0xe58 + (n) * 0x8)
> +#define GENET_MAX_MDF_FILTER 17
> +
> +#define GENET_DMA_DESC_COUNT 256
> +#define GENET_DMA_DESC_SIZE 12
> +#define GENET_DMA_DEFAULT_QUEUE 16
> +
> +#define GENET_DMA_RING_SIZE 0x40
> +#define GENET_DMA_RINGS_SIZE (GENET_DMA_RING_SIZE * (GENET_DMA_DEFAULT_QUEUE + 1))
> +
> +#define GENET_RX_BASE 0x2000
> +#define GENET_TX_BASE 0x4000
> +
> +#define GENET_RX_DMA_RINGBASE(qid) (GENET_RX_BASE + 0xc00 + GENET_DMA_RING_SIZE * (qid))
> +#define GENET_RX_DMA_WRITE_PTR_LO(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x00)
> +#define GENET_RX_DMA_WRITE_PTR_HI(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x04)
> +#define GENET_RX_DMA_PROD_INDEX(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x08)
> +#define GENET_RX_DMA_CONS_INDEX(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x0c)
> +#define GENET_RX_DMA_RING_BUF_SIZE(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x10)
> +#define GENET_RX_DMA_RING_BUF_SIZE_DESC_COUNT 0xffff0000
> +#define GENET_RX_DMA_RING_BUF_SIZE_BUF_LENGTH 0x0000ffff
> +#define GENET_RX_DMA_START_ADDR_LO(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x14)
> +#define GENET_RX_DMA_START_ADDR_HI(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x18)
> +#define GENET_RX_DMA_END_ADDR_LO(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x1c)
> +#define GENET_RX_DMA_END_ADDR_HI(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x20)
> +#define GENET_RX_DMA_XON_XOFF_THRES(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x28)
> +#define GENET_RX_DMA_XON_XOFF_THRES_LO 0xffff0000
> +#define GENET_RX_DMA_XON_XOFF_THRES_HI 0x0000ffff
> +#define GENET_RX_DMA_READ_PTR_LO(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x2c)
> +#define GENET_RX_DMA_READ_PTR_HI(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x30)
> +
> +#define GENET_TX_DMA_RINGBASE(qid) (GENET_TX_BASE + 0xc00 + GENET_DMA_RING_SIZE * (qid))
> +#define GENET_TX_DMA_READ_PTR_LO(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x00)
> +#define GENET_TX_DMA_READ_PTR_HI(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x04)
> +#define GENET_TX_DMA_CONS_INDEX(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x08)
> +#define GENET_TX_DMA_PROD_INDEX(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x0c)
> +#define GENET_TX_DMA_RING_BUF_SIZE(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x10)
> +#define GENET_TX_DMA_RING_BUF_SIZE_DESC_COUNT 0xffff0000
> +#define GENET_TX_DMA_RING_BUF_SIZE_BUF_LENGTH 0x0000ffff
> +#define GENET_TX_DMA_START_ADDR_LO(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x14)
> +#define GENET_TX_DMA_START_ADDR_HI(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x18)
> +#define GENET_TX_DMA_END_ADDR_LO(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x1c)
> +#define GENET_TX_DMA_END_ADDR_HI(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x20)
> +#define GENET_TX_DMA_MBUF_DONE_THRES(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x24)
> +#define GENET_TX_DMA_FLOW_PERIOD(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x28)
> +#define GENET_TX_DMA_WRITE_PTR_LO(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x2c)
> +#define GENET_TX_DMA_WRITE_PTR_HI(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x30)
> +
> +#define GENET_RX_DESC_STATUS(idx) (GENET_RX_BASE + GENET_DMA_DESC_SIZE * (idx) + 0x00)
> +#define GENET_RX_DESC_STATUS_BUFLEN (BIT27|BIT26|BIT25|BIT24|BIT23|BIT22|BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)
> +#define GENET_RX_DESC_STATUS_OWN BIT15
> +#define GENET_RX_DESC_STATUS_EOP BIT14
> +#define GENET_RX_DESC_STATUS_SOP BIT13
> +#define GENET_RX_DESC_STATUS_RX_ERROR BIT2
> +#define GENET_RX_DESC_ADDRESS_LO(idx) (GENET_RX_BASE + GENET_DMA_DESC_SIZE * (idx) + 0x04)
> +#define GENET_RX_DESC_ADDRESS_HI(idx) (GENET_RX_BASE + GENET_DMA_DESC_SIZE * (idx) + 0x08)
> +
> +#define GENET_TX_DESC_STATUS(idx) (GENET_TX_BASE + GENET_DMA_DESC_SIZE * (idx) + 0x00)
> +#define GENET_TX_DESC_STATUS_BUFLEN (BIT27|BIT26|BIT25|BIT24|BIT23|BIT22|BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)
> +#define GENET_TX_DESC_STATUS_OWN BIT15
> +#define GENET_TX_DESC_STATUS_EOP BIT14
> +#define GENET_TX_DESC_STATUS_SOP BIT13
> +#define GENET_TX_DESC_STATUS_QTAG (BIT12|BIT11|BIT10|BIT9|BIT8|BIT7)
> +#define GENET_TX_DESC_STATUS_CRC BIT6
> +#define GENET_TX_DESC_ADDRESS_LO(idx) (GENET_TX_BASE + GENET_DMA_DESC_SIZE * (idx) + 0x04)
> +#define GENET_TX_DESC_ADDRESS_HI(idx) (GENET_TX_BASE + GENET_DMA_DESC_SIZE * (idx) + 0x08)
> +
> +#define GENET_RX_DMA_RING_CFG (GENET_RX_BASE + 0x1040 + 0x00)
> +#define GENET_RX_DMA_CTRL (GENET_RX_BASE + 0x1040 + 0x04)
> +#define GENET_RX_DMA_CTRL_RBUF_EN(qid) (BIT1 << (qid))
> +#define GENET_RX_DMA_CTRL_EN BIT0
> +#define GENET_RX_SCB_BURST_SIZE (GENET_RX_BASE + 0x1040 + 0x0c)
> +
> +#define GENET_TX_DMA_RING_CFG (GENET_TX_BASE + 0x1040 + 0x00)
> +#define GENET_TX_DMA_CTRL (GENET_TX_BASE + 0x1040 + 0x04)
> +#define GENET_TX_DMA_CTRL_RBUF_EN(qid) (BIT1 << (qid))
> +#define GENET_TX_DMA_CTRL_EN BIT0
> +#define GENET_TX_SCB_BURST_SIZE (GENET_TX_BASE + 0x1040 + 0x0c)
> +
> +typedef struct {
> + EFI_PHYSICAL_ADDRESS PhysAddress;
> + VOID * Mapping;
> +} GENET_MAP_INFO;
> +
> +typedef enum {
> + GENET_PHY_MODE_MII,
> + GENET_PHY_MODE_RGMII,
> + GENET_PHY_MODE_RGMII_RXID,
> + GENET_PHY_MODE_RGMII_TXID,
> + GENET_PHY_MODE_RGMII_ID,
> +} GENET_PHY_MODE;
> +
> +typedef struct {
> + UINT32 Signature;
> + EFI_HANDLE ControllerHandle;
> +
> + EFI_LOCK Lock;
> + EFI_EVENT ExitBootServicesEvent;
> +
> + EFI_SIMPLE_NETWORK_PROTOCOL Snp;
> + EFI_SIMPLE_NETWORK_MODE SnpMode;
> +
> + BCM_GENET_PLATFORM_DEVICE_PROTOCOL *Dev;
> +
> + GENERIC_PHY_PRIVATE_DATA Phy;
> +
> + UINT8 *TxBuffer[GENET_DMA_DESC_COUNT];
> + VOID *TxBufferMap[GENET_DMA_DESC_COUNT];
> + UINT8 TxQueued;
> + UINT16 TxNext;
> + UINT16 TxConsIndex;
> + UINT16 TxProdIndex;
> +
> + EFI_PHYSICAL_ADDRESS RxBuffer;
> + GENET_MAP_INFO RxBufferMap[GENET_DMA_DESC_COUNT];
> + UINT16 RxConsIndex;
> + UINT16 RxProdIndex;
> +
> + GENET_PHY_MODE PhyMode;
> +
> + UINTN RegBase;
> +} GENET_PRIVATE_DATA;
> +
> +extern EFI_COMPONENT_NAME_PROTOCOL gGenetComponentName;
> +extern EFI_COMPONENT_NAME2_PROTOCOL gGenetComponentName2;
> +
> +extern CONST EFI_SIMPLE_NETWORK_PROTOCOL gGenetSimpleNetworkTemplate;
> +
> +#define GENET_DRIVER_SIGNATURE SIGNATURE_32('G', 'N', 'E', 'T')
Swedish person has slight giggle, stays silent, moves on.
> +#define GENET_PRIVATE_DATA_FROM_SNP_THIS(a) CR(a, GENET_PRIVATE_DATA, Snp, GENET_DRIVER_SIGNATURE)
> +
> +#define GENET_RX_BUFFER(g, idx) ((UINT8 *)(UINTN)(g)->RxBuffer + GENET_MAX_PACKET_SIZE * (idx))
> +
> +EFI_STATUS
> +EFIAPI
> +GenetPhyRead (
> + IN VOID *Priv,
> + IN UINT8 PhyAddr,
> + IN UINT8 Reg,
> + OUT UINT16 *Data
> + );
> +
> +EFI_STATUS
> +EFIAPI
> +GenetPhyWrite (
> + IN VOID *Priv,
> + IN UINT8 PhyAddr,
> + IN UINT8 Reg,
> + IN UINT16 Data
> + );
> +
> +EFI_STATUS
> +EFIAPI
> +GenetPhyResetAction (
> + IN VOID *Priv
> + );
> +
> +VOID
> +EFIAPI
> +GenetPhyConfigure (
> + IN VOID *Priv,
> + IN GENERIC_PHY_SPEED Speed,
> + IN GENERIC_PHY_DUPLEX Duplex
> + );
> +
> +VOID
> +GenetReset (
> + IN GENET_PRIVATE_DATA *Genet
> + );
> +
> +VOID
> +EFIAPI
> +GenetSetMacAddress (
> + IN GENET_PRIVATE_DATA *Genet,
> + IN EFI_MAC_ADDRESS *MacAddr
> + );
> +
> +VOID
> +GenetSetPhyMode (
> + IN GENET_PRIVATE_DATA *Genet,
> + IN GENET_PHY_MODE PhyMode
> + );
> +
> +VOID
> +GenetEnableTxRx (
> + IN GENET_PRIVATE_DATA *Genet
> + );
> +
> +VOID
> +GenetDisableTxRx (
> + IN GENET_PRIVATE_DATA *Genet
> + );
> +
> +VOID
> +GenetSetPromisc (
> + IN GENET_PRIVATE_DATA *Genet,
> + IN BOOLEAN Enable
> + );
> +
> +VOID
> +GenetEnableBroadcastFilter (
> + IN GENET_PRIVATE_DATA *Genet,
> + IN BOOLEAN Enable
> + );
> +
> +VOID
> +GenetDmaInitRings (
> + IN GENET_PRIVATE_DATA *Genet
> + );
> +
> +EFI_STATUS
> +GenetDmaAlloc (
> + IN GENET_PRIVATE_DATA *Genet
> + );
> +
> +VOID
> +GenetDmaFree (
> + IN GENET_PRIVATE_DATA *Genet
> + );
> +
> +VOID
> +GenetDmaTriggerTx (
> + IN GENET_PRIVATE_DATA *Genet,
> + IN UINT8 DescIndex,
> + IN EFI_PHYSICAL_ADDRESS PhysAddr,
> + IN UINTN NumberOfBytes
> + );
> +
> +EFI_STATUS
> +GenetDmaMapRxDescriptor (
> + IN GENET_PRIVATE_DATA *Genet,
> + IN UINT8 DescIndex
> + );
> +
> +VOID
> +GenetDmaUnmapRxDescriptor (
> + IN GENET_PRIVATE_DATA *Genet,
> + IN UINT8 DescIndex
> + );
> +
> +VOID
> +GenetTxIntr (
> + IN GENET_PRIVATE_DATA *Genet,
> + OUT VOID **TxBuf
> + );
> +
> +EFI_STATUS
> +GenetRxIntr (
> + IN GENET_PRIVATE_DATA *Genet,
> + OUT UINT8 *DescIndex,
> + OUT UINTN *FrameLength
> + );
> +
> +#endif /* GENET_UTIL_H__ */
> diff --git a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/ComponentName.c b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/ComponentName.c
> new file mode 100644
> index 000000000000..b4b8896593f3
> --- /dev/null
> +++ b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/ComponentName.c
> @@ -0,0 +1,198 @@
> +/** @file
> + UEFI Component Name(2) protocol implementation for GENET UEFI driver.
> +
> + Copyright (c) 2020 Jared McNeill. All rights reserved.
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "GenetUtil.h"
> +
> +STATIC EFI_UNICODE_STRING_TABLE mGenetDriverNameTable[] = {
> + {
> + "eng;en",
> + L"Broadcom GENET Ethernet Driver"
> + },
> + {
> + NULL,
> + NULL
> + }
> +};
> +
> +STATIC EFI_UNICODE_STRING_TABLE mGenetDeviceNameTable[] = {
> + {
> + "eng;en",
> + L"Broadcom GENET Ethernet"
> + },
> + {
> + NULL,
> + NULL
> + }
> +};
> +
> +/**
> + Retrieves a Unicode string that is the user readable name of the driver.
> +
> + This function retrieves the user readable name of a driver in the form of a
> + Unicode string. If the driver specified by This has a user readable name in
> + the language specified by Language, then a pointer to the driver name is
> + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
> + by This does not support the language specified by Language,
> + then EFI_UNSUPPORTED is returned.
> +
> + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
> + EFI_COMPONENT_NAME_PROTOCOL instance.
> +
> + @param Language[in] A pointer to a Null-terminated ASCII string
> + array indicating the language. This is the
> + language of the driver name that the caller is
> + requesting, and it must match one of the
> + languages specified in SupportedLanguages. The
> + number of languages supported by a driver is up
> + to the driver writer. Language is specified
> + in RFC 4646 or ISO 639-2 language code format.
> +
> + @param DriverName[out] A pointer to the Unicode string to return.
> + This Unicode string is the name of the
> + driver specified by This in the language
> + specified by Language.
> +
> + @retval EFI_SUCCESS The Unicode string for the Driver specified by
> + This and the language specified by Language was
> + returned in DriverName.
> +
> + @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> + @retval EFI_INVALID_PARAMETER DriverName is NULL.
> +
> + @retval EFI_UNSUPPORTED The driver specified by This does not support
> + the language specified by Language.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GenetComponentNameGetDriverName (
> + IN EFI_COMPONENT_NAME2_PROTOCOL *This,
> + IN CHAR8 *Language,
> + OUT CHAR16 **DriverName
> + )
> +{
> + return LookupUnicodeString2 (Language,
> + This->SupportedLanguages,
> + mGenetDriverNameTable,
> + DriverName,
> + (BOOLEAN)(This == &gGenetComponentName2)
> + );
> +}
> +
> +/**
> + Retrieves a Unicode string that is the user readable name of the controller
> + that is being managed by a driver.
> +
> + This function retrieves the user readable name of the controller specified by
> + ControllerHandle and ChildHandle in the form of a Unicode string. If the
> + driver specified by This has a user readable name in the language specified by
> + Language, then a pointer to the controller name is returned in ControllerName,
> + and EFI_SUCCESS is returned. If the driver specified by This is not currently
> + managing the controller specified by ControllerHandle and ChildHandle,
> + then EFI_UNSUPPORTED is returned. If the driver specified by This does not
> + support the language specified by Language, then EFI_UNSUPPORTED is returned.
> +
> + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
> + EFI_COMPONENT_NAME_PROTOCOL instance.
> +
> + @param ControllerHandle[in] The handle of a controller that the driver
> + specified by This is managing. This handle
> + specifies the controller whose name is to be
> + returned.
> +
> + @param ChildHandle[in] The handle of the child controller to retrieve
> + the name of. This is an optional parameter that
> + may be NULL. It will be NULL for device
> + drivers. It will also be NULL for a bus drivers
> + that wish to retrieve the name of the bus
> + controller. It will not be NULL for a bus
> + driver that wishes to retrieve the name of a
> + child controller.
> +
> + @param Language[in] A pointer to a Null-terminated ASCII string
> + array indicating the language. This is the
> + language of the driver name that the caller is
> + requesting, and it must match one of the
> + languages specified in SupportedLanguages. The
> + number of languages supported by a driver is up
> + to the driver writer. Language is specified in
> + RFC 4646 or ISO 639-2 language code format.
> +
> + @param ControllerName[out] A pointer to the Unicode string to return.
> + This Unicode string is the name of the
> + controller specified by ControllerHandle and
> + ChildHandle in the language specified by
> + Language from the point of view of the driver
> + specified by This.
> +
> + @retval EFI_SUCCESS The Unicode string for the user readable name in
> + the language specified by Language for the
> + driver specified by This was returned in
> + DriverName.
> +
> + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
> +
> + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
> + EFI_HANDLE.
> +
> + @retval EFI_INVALID_PARAMETER Language is NULL.
> +
> + @retval EFI_INVALID_PARAMETER ControllerName is NULL.
> +
> + @retval EFI_UNSUPPORTED The driver specified by This is not currently
> + managing the controller specified by
> + ControllerHandle and ChildHandle.
> +
> + @retval EFI_UNSUPPORTED The driver specified by This does not support
> + the language specified by Language.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GenetComponentNameGetControllerName (
> + IN EFI_COMPONENT_NAME2_PROTOCOL *This,
> + IN EFI_HANDLE ControllerHandle,
> + IN EFI_HANDLE ChildHandle OPTIONAL,
> + IN CHAR8 *Language,
> + OUT CHAR16 **ControllerName
> + )
> +{
> + if (ChildHandle != NULL) {
> + return EFI_UNSUPPORTED;
> + }
> +
> + return LookupUnicodeString2 (Language,
> + This->SupportedLanguages,
> + mGenetDeviceNameTable,
> + ControllerName,
> + (BOOLEAN)(This == &gGenetComponentName2)
> + );
> +}
> +
> +//
> +// EFI Component Name Protocol
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED
> +EFI_COMPONENT_NAME_PROTOCOL gGenetComponentName = {
> + (EFI_COMPONENT_NAME_GET_DRIVER_NAME) GenetComponentNameGetDriverName,
> + (EFI_COMPONENT_NAME_GET_CONTROLLER_NAME) GenetComponentNameGetControllerName,
> + "eng"
> +};
> +
> +//
> +// EFI Component Name 2 Protocol
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED
> +EFI_COMPONENT_NAME2_PROTOCOL gGenetComponentName2 = {
> + GenetComponentNameGetDriverName,
> + GenetComponentNameGetControllerName,
> + "en"
> +};
> diff --git a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/DriverBinding.c b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/DriverBinding.c
> new file mode 100644
> index 000000000000..57f2fb17cb17
> --- /dev/null
> +++ b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/DriverBinding.c
> @@ -0,0 +1,408 @@
> +/** @file
> + Device driver for the Broadcom GENET controller
> +
> + Copyright (c) 2020 Jared McNeill. All rights reserved.
> + Copyright (c) 2020, ARM Limited. All rights reserved.
> + Copyright (c) 2020 Andrey Warkentin <andrey.warkentin@gmail.com>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +
> +#include <Protocol/BcmGenetPlatformDevice.h>
> +
> +#include "GenetUtil.h"
> +
> +/**
> + Tests to see if this driver supports a given controller.
> +
> + @param This[in] A pointer to the EFI_DRIVER_BINDING_PROTOCOL
> + instance.
> + @param ControllerHandle[in] The handle of the controller to test.
> + @param RemainingDevicePath[in] The remaining device path.
> + (Ignored - this is not a bus driver.)
> +
> + @retval EFI_SUCCESS The driver supports this controller.
> + @retval EFI_ALREADY_STARTED The device specified by ControllerHandle is
> + already being managed by the driver specified
> + by This.
> + @retval EFI_UNSUPPORTED The device specified by ControllerHandle is
> + not supported by the driver specified by This.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GenetDriverBindingSupported (
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE ControllerHandle,
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
> + )
> +{
> + BCM_GENET_PLATFORM_DEVICE_PROTOCOL *Dev;
> + EFI_STATUS Status;
> +
> + //
> + // Connect to the non-discoverable device
> + //
> + Status = gBS->OpenProtocol (ControllerHandle,
> + &gBcmGenetPlatformDeviceProtocolGuid,
> + (VOID **)&Dev,
> + This->DriverBindingHandle,
> + ControllerHandle,
> + EFI_OPEN_PROTOCOL_BY_DRIVER);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + //
> + // Clean up.
> + //
> + gBS->CloseProtocol (ControllerHandle,
> + &gBcmGenetPlatformDeviceProtocolGuid,
> + This->DriverBindingHandle,
> + ControllerHandle);
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Callback function to shut down the network device at ExitBootServices
> +
> + @param Event Pointer to this event
> + @param Context Event handler private data
> +
> +**/
> +STATIC
> +VOID
> +EFIAPI
> +GenetNotifyExitBootServices (
> + EFI_EVENT Event,
> + VOID *Context
> + )
> +{
> + GenetDisableTxRx ((GENET_PRIVATE_DATA *)Context);
> +}
> +
> +/**
> + Starts a device controller or a bus controller.
> +
> + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL
> + instance.
> + @param[in] ControllerHandle The handle of the device to start. This
> + handle must support a protocol interface that
> + supplies an I/O abstraction to the driver.
> + @param[in] RemainingDevicePath The remaining portion of the device path.
> + (Ignored - this is not a bus driver.)
> +
> + @retval EFI_SUCCESS The device was started.
> + @retval EFI_DEVICE_ERROR The device could not be started due to a
> + device error.
> + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
> + lack of resources.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GenetDriverBindingStart (
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE ControllerHandle,
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
> + )
> +{
> + GENET_PRIVATE_DATA *Genet;
> + EFI_STATUS Status;
> +
> + // Allocate Resources
> + Genet = AllocateZeroPool (sizeof (GENET_PRIVATE_DATA));
> + if (Genet == NULL) {
> + DEBUG ((DEBUG_ERROR,
> + "%a: Couldn't allocate private data\n", __FUNCTION__));
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + Status = gBS->OpenProtocol (ControllerHandle,
> + &gBcmGenetPlatformDeviceProtocolGuid,
> + (VOID **)&Genet->Dev,
> + This->DriverBindingHandle,
> + ControllerHandle,
> + EFI_OPEN_PROTOCOL_BY_DRIVER);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR,
> + "%a: Couldn't open protocol: %r\n", __FUNCTION__, Status));
> + goto FreeDevice;
> + }
> +
> + Status = GenetDmaAlloc (Genet);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR,
> + "%a: Couldn't allocate DMA buffers: %r\n", __FUNCTION__, Status));
> + goto FreeDevice;
> + }
> +
> + Genet->Signature = GENET_DRIVER_SIGNATURE;
> + Genet->RegBase = Genet->Dev->BaseAddress;
> + Genet->Phy.PrivateData = Genet;
> + Genet->Phy.Read = GenetPhyRead;
> + Genet->Phy.Write = GenetPhyWrite;
> + Genet->Phy.Configure = GenetPhyConfigure;
> + Genet->Phy.ResetAction = GenetPhyResetAction;
> + Genet->PhyMode = GENET_PHY_MODE_RGMII_RXID;
> +
> + EfiInitializeLock (&Genet->Lock, TPL_CALLBACK);
> + CopyMem (&Genet->Snp, &gGenetSimpleNetworkTemplate, sizeof Genet->Snp);
> +
> + Genet->Snp.Mode = &Genet->SnpMode;
> + Genet->SnpMode.State = EfiSimpleNetworkStopped;
> + Genet->SnpMode.HwAddressSize = NET_ETHER_ADDR_LEN;
> + Genet->SnpMode.MediaHeaderSize = sizeof (ETHER_HEAD);
> + Genet->SnpMode.MaxPacketSize = MAX_ETHERNET_PKT_SIZE;
> + Genet->SnpMode.NvRamSize = 0;
> + Genet->SnpMode.NvRamAccessSize = 0;
> + Genet->SnpMode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
> + EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
> + EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
> + Genet->SnpMode.ReceiveFilterSetting = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
> + EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
> + Genet->SnpMode.MaxMCastFilterCount = 0;
> + Genet->SnpMode.MCastFilterCount = 0;
> + Genet->SnpMode.IfType = NET_IFTYPE_ETHERNET;
> + Genet->SnpMode.MacAddressChangeable = TRUE;
> + Genet->SnpMode.MultipleTxSupported = FALSE;
> + Genet->SnpMode.MediaPresentSupported = TRUE;
> + Genet->SnpMode.MediaPresent = FALSE;
> +
> + SetMem (&Genet->SnpMode.BroadcastAddress, sizeof (EFI_MAC_ADDRESS), 0xff);
> +
> + CopyMem (&Genet->SnpMode.PermanentAddress, &Genet->Dev->MacAddress,
> + sizeof(EFI_MAC_ADDRESS));
> + CopyMem (&Genet->SnpMode.CurrentAddress, &Genet->Dev->MacAddress,
> + sizeof(EFI_MAC_ADDRESS));
> +
> + Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
> + GenetNotifyExitBootServices, Genet,
> + &gEfiEventExitBootServicesGuid,
> + &Genet->ExitBootServicesEvent);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_WARN,
> + "GenetDriverBindingStart: failed to register for ExitBootServices event - %r\n",
> + Status));
> + goto FreeDevice;
> + }
> +
> + Status = gBS->InstallMultipleProtocolInterfaces (&ControllerHandle,
> + &gEfiSimpleNetworkProtocolGuid, &Genet->Snp,
> + NULL);
> +
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR,
> + "%a: Couldn't install protocol interfaces: %r\n", __FUNCTION__, Status));
> + gBS->CloseProtocol (ControllerHandle,
> + &gBcmGenetPlatformDeviceProtocolGuid,
> + This->DriverBindingHandle,
> + ControllerHandle);
> + goto FreeEvent;
> + }
> +
> + Genet->ControllerHandle = ControllerHandle;
> + return EFI_SUCCESS;
> +
> +FreeEvent:
> + gBS->CloseEvent (Genet->ExitBootServicesEvent);
> +FreeDevice:
> + DEBUG ((DEBUG_WARN, "%a: Returning %r\n", __FUNCTION__, Status));
> + FreePool (Genet);
> + return Status;
> +}
> +
> +
> +/**
> + Stops a device controller or a bus controller.
> +
> + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL
> + instance.
> + @param[in] ControllerHandle A handle to the device being stopped. The handle
> + must support a bus specific I/O protocol for the
> + driver to use to stop the device.
> + @param[in] NumberOfChildren The number of child device handles in
> + ChildHandleBuffer.
> + @param[in] ChildHandleBuffer An array of child handles to be freed. May be
> + NULL if NumberOfChildren is 0.
> +
> + @retval EFI_SUCCESS The device was stopped.
> + @retval EFI_DEVICE_ERROR The device could not be stopped due to a device
> + error.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GenetDriverBindingStop (
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
> + IN EFI_HANDLE ControllerHandle,
> + IN UINTN NumberOfChildren,
> + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
> + )
> +{
> + EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol;
> + GENET_PRIVATE_DATA *Genet;
> + EFI_STATUS Status;
> +
> + Status = gBS->HandleProtocol (ControllerHandle,
> + &gEfiSimpleNetworkProtocolGuid,
> + (VOID **)&SnpProtocol
> + );
> + ASSERT_EFI_ERROR (Status);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Genet = GENET_PRIVATE_DATA_FROM_SNP_THIS (SnpProtocol);
> +
> + ASSERT (Genet->ControllerHandle == ControllerHandle);
> +
> + Status = gBS->UninstallProtocolInterface (ControllerHandle,
> + &gEfiSimpleNetworkProtocolGuid,
> + &Genet->Snp
> + );
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = gBS->CloseEvent (Genet->ExitBootServicesEvent);
> + ASSERT_EFI_ERROR (Status);
> +
> + GenetDmaFree (Genet);
> +
> + Status = gBS->CloseProtocol (ControllerHandle,
> + &gBcmGenetPlatformDeviceProtocolGuid,
> + This->DriverBindingHandle,
> + ControllerHandle);
> + ASSERT_EFI_ERROR (Status);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + FreePool (Genet);
> +
> + return EFI_SUCCESS;
> +}
> +
> +STATIC EFI_DRIVER_BINDING_PROTOCOL mGenetDriverBinding = {
> + GenetDriverBindingSupported,
> + GenetDriverBindingStart,
> + GenetDriverBindingStop,
> + GENET_VERSION,
> + NULL,
> + NULL
> +};
> +
> +/**
> + The entry point of GENET UEFI Driver.
> +
> + @param ImageHandle The image handle of the UEFI Driver.
> + @param SystemTable A pointer to the EFI System Table.
> +
> + @retval EFI_SUCCESS The Driver or UEFI Driver exited normally.
> + @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater than
> + SystemTable->Hdr.Revision.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +GenetEntryPoint (
> + IN EFI_HANDLE ImageHandle,
> + IN EFI_SYSTEM_TABLE *SystemTable
> + )
> +{
> + EFI_STATUS Status;
> +
> + Status = EfiLibInstallDriverBindingComponentName2 (
> + ImageHandle,
> + SystemTable,
> + &mGenetDriverBinding,
> + ImageHandle,
> + &gGenetComponentName,
> + &gGenetComponentName2
> + );
> +
> + ASSERT_EFI_ERROR (Status);
> +
> + DEBUG ((DEBUG_INIT | DEBUG_INFO, "Installed GENET UEFI driver!\n"));
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Unload function of GENET UEFI Driver.
> +
> + @param ImageHandle The allocated handle for the EFI image
> +
> + @retval EFI_SUCCESS The driver was unloaded successfully
> + @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +GenetUnload (
> + IN EFI_HANDLE ImageHandle
> + )
> +{
> + EFI_STATUS Status;
> + EFI_HANDLE *HandleBuffer;
> + UINTN HandleCount;
> + UINTN Index;
> +
> + //
> + // Retrieve all BcmGenetPlatformDevice handles in the handle database
> + //
> + Status = gBS->LocateHandleBuffer (ByProtocol,
> + &gBcmGenetPlatformDeviceProtocolGuid,
> + NULL,
> + &HandleCount,
> + &HandleBuffer);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + //
> + // Disconnect the driver from the handles in the handle database
> + //
> + for (Index = 0; Index < HandleCount && !EFI_ERROR (Status); Index++) {
> + Status = gBS->DisconnectController (HandleBuffer[Index],
> + gImageHandle,
> + NULL);
> + }
> +
> + //
> + // Free the handle array
> + //
> + gBS->FreePool (HandleBuffer);
> +
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_WARN, "%a: failed to disconnect all controllers - %r\n",
> + __FUNCTION__, Status));
> + return Status;
> + }
> +
> + //
> + // Uninstall protocols installed by the driver in its entrypoint
> + //
> + Status = EfiLibUninstallDriverBindingComponentName2 (
> + &mGenetDriverBinding,
> + &gGenetComponentName,
> + &gGenetComponentName2
> + );
> +
> + ASSERT_EFI_ERROR (Status);
> +
> + return EFI_SUCCESS;
> +}
> diff --git a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenericPhy.c b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenericPhy.c
> new file mode 100644
> index 000000000000..ff67602c92ff
> --- /dev/null
> +++ b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenericPhy.c
> @@ -0,0 +1,405 @@
> +/** @file
> +
> + Copyright (c) 2020 Jared McNeill. All rights reserved.
> + Copyright (c) 2020 Andrey Warkentin <andrey.warkentin@gmail.com>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Uefi.h>
> +
> +#include <Library/DebugLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include "GenericPhy.h"
> +
> +#define PHY_RESET_TIMEOUT 500
> +
> +/**
> + Perform a PHY register read.
> +
> + @param Phy[in] Pointer to GENERIC_PHY_PRIVATE_DATA.
> + @param PhyAddr[in] PHY address.
> + @param Reg[in] PHY register.
> + @param Data[out] Pointer to register data read.
> +
> + @retval EFI_SUCCESS Data read successfully.
> + @retval EFI_DEVICE_ERROR Failed to read data.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +GenericPhyRead (
> + IN GENERIC_PHY_PRIVATE_DATA *Phy,
> + IN UINT8 PhyAddr,
> + IN UINT8 Reg,
> + OUT UINT16 *Data
> + )
> +{
> + return Phy->Read (Phy->PrivateData, PhyAddr, Reg, Data);
> +}
> +
> +/**
> + Perform a PHY register write.
> +
> + @param Phy[in] Pointer to GENERIC_PHY_PRIVATE_DATA.
> + @param PhyAddr[in] PHY address.
> + @param Reg[in] PHY register.
> + @param Data[in] Pointer to register data to write.
> +
> + @retval EFI_SUCCESS Data written successfully.
> + @retval EFI_DEVICE_ERROR Failed to write data.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +GenericPhyWrite (
> + IN GENERIC_PHY_PRIVATE_DATA *Phy,
> + IN UINT8 PhyAddr,
> + IN UINT8 Reg,
> + IN UINT16 Data
> + )
> +{
> + return Phy->Write (Phy->PrivateData, PhyAddr, Reg, Data);
> +}
> +
> +/**
> + Process a PHY link speed change (e.g. with MAC layer).
> +
> + @param Phy[in] Pointer to GENERIC_PHY_PRIVATE_DATA.
> + @param Speed[in] Speed setting.
> + @param Duplex[in] Duplex setting.
> +
> +**/
> +STATIC
> +VOID
> +GenericPhyConfigure (
> + IN GENERIC_PHY_PRIVATE_DATA *Phy,
> + IN GENERIC_PHY_SPEED Speed,
> + IN GENERIC_PHY_DUPLEX Duplex
> + )
> +{
> + Phy->Configure (Phy->PrivateData, Speed, Duplex);
> +}
> +
> +/**
> + Detect address for the first PHY seen, probing all possible addresses.
> +
> + @param Phy[in] Pointer to GENERIC_PHY_PRIVATE_DATA.
> +
> + @retval EFI_SUCCESS Found a PHY and programmed Phy->PhyAddr
> + @retval EFI_DEVICE_ERROR Error reading/writing a PHY register.
> + @retval EFI_NOT_FOUND No PHY detected.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +GenericPhyDetect (
> + IN GENERIC_PHY_PRIVATE_DATA *Phy
> + )
> +{
> + EFI_STATUS Status;
> + UINT8 PhyAddr;
> + UINT16 Id1, Id2;
> +
> + for (PhyAddr = 0; PhyAddr < 32; PhyAddr++) {
> + Status = GenericPhyRead (Phy, PhyAddr, GENERIC_PHY_PHYIDR1, &Id1);
> + if (EFI_ERROR (Status)) {
> + continue;
> + }
> + Status = GenericPhyRead (Phy, PhyAddr, GENERIC_PHY_PHYIDR2, &Id2);
> + if (EFI_ERROR (Status)) {
> + continue;
> + }
> + if (Id1 != 0xFFFF && Id2 != 0xFFFF) {
> + Phy->PhyAddr = PhyAddr;
> + DEBUG ((DEBUG_INFO,
> + "%a: PHY detected at address 0x%02X (PHYIDR1=0x%04X, PHYIDR2=0x%04X)\n",
> + __FUNCTION__, PhyAddr, Id1, Id2));
> + return EFI_SUCCESS;
> + }
> + }
> +
> + return EFI_NOT_FOUND;
> +}
> +
> +/**
> + Start link auto-negotiation on a PHY.
> +
> + @param Phy[in] Pointer to GENERIC_PHY_PRIVATE_DATA.
> +
> + @retval EFI_SUCCESS Auto-netogiation started.
> + @retval EFI_DEVICE_ERROR PHY register read/write error.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +GenericPhyAutoNegotiate (
> + IN GENERIC_PHY_PRIVATE_DATA *Phy
> + )
> +{
> + EFI_STATUS Status;
> + UINT16 Anar, Gbcr, Bmcr;
This file contains a fair amount of definitely-not-camelcase variables
that apppear to refer to register names. Is there any chance of having
those register names added to a proper glossary as part of this file's
comment header?
> +
> + Status = GenericPhyRead (Phy, Phy->PhyAddr, GENERIC_PHY_ANAR, &Anar);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + Anar |= GENERIC_PHY_ANAR_100BASETX_FDX |
> + GENERIC_PHY_ANAR_100BASETX |
> + GENERIC_PHY_ANAR_10BASET_FDX |
> + GENERIC_PHY_ANAR_10BASET;
> + Status = GenericPhyWrite (Phy, Phy->PhyAddr, GENERIC_PHY_ANAR, Anar);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = GenericPhyRead (Phy, Phy->PhyAddr, GENERIC_PHY_GBCR, &Gbcr);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + Gbcr |= GENERIC_PHY_GBCR_1000BASET_FDX |
> + GENERIC_PHY_GBCR_1000BASET;
> + Status = GenericPhyWrite (Phy, Phy->PhyAddr, GENERIC_PHY_GBCR, Gbcr);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = GenericPhyRead (Phy, Phy->PhyAddr, GENERIC_PHY_BMCR, &Bmcr);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + Bmcr |= GENERIC_PHY_BMCR_ANE |
> + GENERIC_PHY_BMCR_RESTART_AN;
> + return GenericPhyWrite (Phy, Phy->PhyAddr, GENERIC_PHY_BMCR, Bmcr);
> +}
> +
> +/**
> + Initialize the first PHY detected, performing a reset and enabling
> + auto-negotiation.
> +
> + @param Phy[in] Pointer to GENERIC_PHY_PRIVATE_DATA.
> +
> + @retval EFI_SUCCESS Auto-negotiation started.
> + @retval EFI_DEVICE_ERROR PHY register read/write error.
> + @retval EFI_TIMEOUT PHY reset time-out.
> + @retval EFI_NOT_FOUND No PHY detected.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +GenericPhyInit (
> + IN GENERIC_PHY_PRIVATE_DATA *Phy
> + )
> +{
> + EFI_STATUS Status;
> +
> + ASSERT (Phy->Read != NULL);
> + ASSERT (Phy->Write != NULL);
> + ASSERT (Phy->Configure != NULL);
> +
> + Status = GenericPhyDetect (Phy);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = GenericPhyReset (Phy);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + return GenericPhyAutoNegotiate (Phy);
> +}
> +
> +/**
> + Perform a PHY reset.
> +
> + @param Phy[in] Pointer to GENERIC_PHY_PRIVATE_DATA.
> +
> + @retval EFI_SUCCESS Auto-negotiation started.
> + @retval EFI_DEVICE_ERROR PHY register read/write error.
> + @retval EFI_TIMEOUT PHY reset time-out.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +GenericPhyReset (
> + IN GENERIC_PHY_PRIVATE_DATA *Phy
> + )
> +{
> + EFI_STATUS Status;
> + UINTN Retry;
> + UINT16 Data;
> +
> + // Start reset sequence
> + Status = GenericPhyWrite (Phy, Phy->PhyAddr, GENERIC_PHY_BMCR,
> + GENERIC_PHY_BMCR_RESET);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + // Wait up to 500ms for it to complete
> + for (Retry = PHY_RESET_TIMEOUT; Retry > 0; Retry--) {
> + Status = GenericPhyRead (Phy, Phy->PhyAddr, GENERIC_PHY_BMCR, &Data);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + if ((Data & GENERIC_PHY_BMCR_RESET) == 0) {
> + break;
> + }
> + gBS->Stall (1000);
> + }
> + if (Retry == 0) {
> + return EFI_TIMEOUT;
> + }
> +
> + if (Phy->ResetAction != NULL) {
> + Phy->ResetAction (Phy->PrivateData);
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Probe link status.
> +
> + @param Phy[in] Pointer to GENERIC_PHY_PRIVATE_DATA.
> +
> + @retval EFI_SUCCESS Link is up and auto-negotiation is complete.
> + @retval EFI_DEVICE_ERROR PHY register read/write error,
> +
> +**/
> +STATIC
> +EFI_STATUS
> +GenericPhyGetLinkStatus (
> + IN GENERIC_PHY_PRIVATE_DATA *Phy
> + )
> +{
> + EFI_STATUS Status;
> + UINT16 Bmsr;
> +
> + Status = GenericPhyRead (Phy, Phy->PhyAddr, GENERIC_PHY_BMSR, &Bmsr);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + if ((Bmsr & GENERIC_PHY_BMSR_LINK_STATUS) == 0) {
> + return EFI_TIMEOUT;
> + }
> +
> + if ((Bmsr & GENERIC_PHY_BMSR_ANEG_COMPLETE) == 0) {
> + return EFI_TIMEOUT;
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Return PHY link configuration.
> +
> + @param Phy[in] Pointer to GENERIC_PHY_PRIVATE_DATA.
> + @param Speed[out] Pointer to store link speed.
> + @param Duplex[out] Pointer to store link duplex setting.
> +
> + @retval EFI_SUCCESS Link configuration settings read.
> + @retval EFI_DEVICE_ERROR PHY register read/write error,
> +
> +**/
> +STATIC
> +EFI_STATUS
> +GenericPhyGetConfig (
> + IN GENERIC_PHY_PRIVATE_DATA *Phy,
> + OUT GENERIC_PHY_SPEED *Speed,
> + OUT GENERIC_PHY_DUPLEX *Duplex
> + )
> +{
> + EFI_STATUS Status;
> + UINT16 Gbcr, Gbsr, Anlpar, Anar;
> + UINT16 Gb, An;
> +
> + Status = GenericPhyRead (Phy, Phy->PhyAddr, GENERIC_PHY_GBCR, &Gbcr);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + Status = GenericPhyRead (Phy, Phy->PhyAddr, GENERIC_PHY_GBSR, &Gbsr);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + Status = GenericPhyRead (Phy, Phy->PhyAddr, GENERIC_PHY_ANLPAR, &Anlpar);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + Status = GenericPhyRead (Phy, Phy->PhyAddr, GENERIC_PHY_ANAR, &Anar);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Gb = (Gbsr >> 2) & Gbcr;
> + An = Anlpar & Anar;
> +
> + if ((Gb & (GENERIC_PHY_GBCR_1000BASET_FDX |
> + GENERIC_PHY_GBCR_1000BASET)) != 0) {
> + *Speed = PHY_SPEED_1000;
> + *Duplex = (Gb & GENERIC_PHY_GBCR_1000BASET_FDX) ? PHY_DUPLEX_FULL
> + : PHY_DUPLEX_HALF;
> + } else if ((An & (GENERIC_PHY_ANAR_100BASETX_FDX |
> + GENERIC_PHY_ANAR_100BASETX)) != 0) {
> + *Speed = PHY_SPEED_100;
> + *Duplex = (An & GENERIC_PHY_ANAR_100BASETX_FDX) ? PHY_DUPLEX_FULL
> + : PHY_DUPLEX_HALF;
> + } else {
> + *Speed = PHY_SPEED_10;
> + *Duplex = (An & GENERIC_PHY_ANAR_10BASET_FDX) ? PHY_DUPLEX_FULL
> + : PHY_DUPLEX_HALF;
> + }
> +
> + DEBUG ((DEBUG_INFO, "%a: Link speed %d Mbps, %a-duplex\n",
> + __FUNCTION__, *Speed, *Duplex == PHY_DUPLEX_FULL ? "full" : "half"));
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Update link status, propagating PHY link state into the MAC layer.
> +
> + @param Phy[in] Pointer to GENERIC_PHY_PRIVATE_DATA.
> +
> + @retval EFI_SUCCESS Link is up.
> + @retval EFI_DEVICE_ERROR PHY register read/write error.
> + @retval EFI_NOT_READY Link is down.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +GenericPhyUpdateConfig (
> + IN GENERIC_PHY_PRIVATE_DATA *Phy
> + )
> +{
> + EFI_STATUS Status;
> + GENERIC_PHY_SPEED Speed;
> + GENERIC_PHY_DUPLEX Duplex;
> + BOOLEAN LinkUp;
> +
> + Status = GenericPhyGetLinkStatus (Phy);
> + LinkUp = EFI_ERROR (Status) ? FALSE : TRUE;
> +
> + if (Phy->LinkUp != LinkUp) {
> + if (LinkUp) {
> + DEBUG ((DEBUG_VERBOSE, "%a: Link is up\n", __FUNCTION__));
> +
> + Status = GenericPhyGetConfig (Phy, &Speed, &Duplex);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + GenericPhyConfigure (Phy, Speed, Duplex);
> + } else {
> + DEBUG ((DEBUG_VERBOSE, "%a: Link is down\n", __FUNCTION__));
> + }
> + }
> +
> + Phy->LinkUp = LinkUp;
> +
> + return LinkUp ? EFI_SUCCESS : EFI_NOT_READY;
> +}
> diff --git a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/Genet.c b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/Genet.c
> deleted file mode 100644
> index d40ce8b07a9d..000000000000
> --- a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/Genet.c
> +++ /dev/null
> @@ -1,114 +0,0 @@
> -/** @file
> -
> - Copyright (c) 2020, Jeremy Linton All rights reserved.<BR>
> -
> - SPDX-License-Identifier: BSD-2-Clause-Patent
> -
> - This driver acts like a stub to set the Broadcom
> - Genet MAC address, until the actual network driver
> - is in place.
> -
> -**/
> -
> -#include <Library/ArmLib.h>
> -#include <Library/DebugLib.h>
> -#include <Library/IoLib.h>
> -#include <Library/PcdLib.h>
> -#include <Library/UefiBootServicesTableLib.h>
> -#include <Library/UefiLib.h>
> -
> -#include <Net/Genet.h>
> -#include <PiDxe.h>
> -
> -STATIC
> -VOID
> -RMWRegister (
> - UINT32 Offset,
> - UINT32 Mask,
> - UINT32 In
> - )
> -{
> - EFI_PHYSICAL_ADDRESS Addr;
> - UINT32 Data;
> - UINT32 Shift;
> -
> - Addr = GENET_BASE_ADDRESS + Offset;
> - Data = 0;
> - Shift = 1;
> - if (In) {
> - while (!(Mask & Shift))
> - Shift <<= 1;
> - Data = (MmioRead32 (Addr) & ~Mask) | ((In * Shift) & Mask);
> - } else {
> - Data = MmioRead32 (Addr) & ~Mask;
> - }
> -
> - MmioWrite32 (Addr, Data);
> -
> - ArmDataMemoryBarrier ();
> -}
> -
> -STATIC
> -VOID
> -WdRegister (
> - UINT32 Offset,
> - UINT32 In
> - )
> -{
> - EFI_PHYSICAL_ADDRESS Base = GENET_BASE_ADDRESS;
> -
> - MmioWrite32 (Base + Offset, In);
> -
> - ArmDataMemoryBarrier ();
> -}
> -
> -STATIC
> -VOID
> -SetMacAddress (
> - UINT8* MacAddr
> -)
> -{
> - // Bring the UMAC out of reset
> - RMWRegister (GENET_SYS_RBUF_FLUSH_CTRL, 0x2, 1);
> - gBS->Stall (10);
> - RMWRegister (GENET_SYS_RBUF_FLUSH_CTRL, 0x2, 0);
> -
> - // Update the MAC
> - DEBUG ((DEBUG_INFO, "Using MAC address %02X:%02X:%02X:%02X:%02X:%02X\n",
> - MacAddr[0], MacAddr[1], MacAddr[2], MacAddr[3], MacAddr[4], MacAddr[5]));
> -
> - WdRegister (GENET_UMAC_MAC0, (MacAddr[0] << 24) | (MacAddr[1] << 16) |
> - (MacAddr[2] << 8) | MacAddr[3]);
> - WdRegister (GENET_UMAC_MAC1, (MacAddr[4] << 8) | MacAddr[5]);
> -
> -}
> -
> -/**
> - The entry point of Genet UEFI Driver.
> -
> - @param ImageHandle The image handle of the UEFI Driver.
> - @param SystemTable A pointer to the EFI System Table.
> -
> - @retval EFI_SUCCESS The Driver or UEFI Driver exited normally.
> - @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater than
> - SystemTable->Hdr.Revision.
> -
> -**/
> -EFI_STATUS
> -EFIAPI
> -GenetEntryPoint (
> - IN EFI_HANDLE ImageHandle,
> - IN EFI_SYSTEM_TABLE *SystemTable
> - )
> -{
> - UINT64 MacAddr;
> -
> - // Read the MAC address
> - MacAddr = PcdGet64 (PcdBcmGenetMacAddress);
> -
> - if (MacAddr != 0) {
> - SetMacAddress ((UINT8*)&MacAddr);
> - }
> -
> - return EFI_SUCCESS;
> -}
> diff --git a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenetUtil.c b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenetUtil.c
> new file mode 100644
> index 000000000000..119691dbeb49
> --- /dev/null
> +++ b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenetUtil.c
> @@ -0,0 +1,816 @@
> +/** @file
> +
> + Copyright (c) 2020 Jared McNeill. All rights reserved.
> + Copyright (c) 2020 Andrey Warkentin <andrey.warkentin@gmail.com>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "GenetUtil.h"
> +
> +#include <Library/DmaLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#define __LOWEST_SET_BIT(__mask) ((((__mask) - 1) & (__mask)) ^ (__mask))
> +#define __SHIFTOUT(__x, __mask) (((__x) & (__mask)) / __LOWEST_SET_BIT(__mask))
> +#define __SHIFTIN(__x, __mask) ((__x) * __LOWEST_SET_BIT(__mask))
Can we get rid of leading __ in macros?
Ideally, these macros would be in GenetUtil.h.
/
Leif
> +
> +#define GENET_PHY_RETRY 1000
> +
> +STATIC CONST
> +EFI_PHYSICAL_ADDRESS mDmaAddressLimit = FixedPcdGet64 (PcdDmaDeviceLimit) -
> + FixedPcdGet64 (PcdDmaDeviceOffset);
> +
> +/**
> + Read a memory-mapped device CSR.
> +
> + @param Genet[in] Pointer to GENERIC_PHY_PRIVATE_DATA instance.
> + @param Offset[in] Register offset.
> +
> + @retval Value
> +
> +**/
> +STATIC
> +UINT32
> +GenetMmioRead (
> + IN GENET_PRIVATE_DATA *Genet,
> + IN UINT32 Offset
> + )
> +{
> + ASSERT ((Offset & 3) == 0);
> +
> + return MmioRead32 (Genet->RegBase + Offset);
> +}
> +
> +/**
> + Write a memory-mapped device CSR.
> +
> + @param Genet[in] Pointer to GENERIC_PHY_PRIVATE_DATA instance.
> + @param Offset[in] Register offset.
> + @param Data[in] Data to write.
> +
> + @retval Value
> +
> +**/
> +STATIC
> +VOID
> +GenetMmioWrite (
> + IN GENET_PRIVATE_DATA *Genet,
> + IN UINT32 Offset,
> + IN UINT32 Data
> + )
> +{
> + ASSERT ((Offset & 3) == 0);
> +
> + MemoryFence ();
> + MmioWrite32 (Genet->RegBase + Offset, Data);
> +}
> +
> +/**
> + Perform a GENET PHY register read.
> +
> + @param Priv[in] Pointer to GENET_PRIVATE_DATA.
> + @param PhyAddr[in] PHY address.
> + @param Reg[in] PHY register.
> + @param Data[out] Pointer to register data read.
> +
> + @retval EFI_SUCCESS Data read successfully.
> + @retval EFI_DEVICE_ERROR Failed to read data.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +GenetPhyRead (
> + IN VOID *Priv,
> + IN UINT8 PhyAddr,
> + IN UINT8 Reg,
> + OUT UINT16 *Data
> + )
> +{
> + GENET_PRIVATE_DATA *Genet;
> + UINTN Retry;
> + UINT32 Value;
> +
> + Genet = Priv;
> + Value = GENET_MDIO_READ |
> + GENET_MDIO_START_BUSY |
> + __SHIFTIN (PhyAddr, GENET_MDIO_PMD) |
> + __SHIFTIN (Reg, GENET_MDIO_REG);
> + GenetMmioWrite (Genet, GENET_MDIO_CMD, Value);
> +
> + for (Retry = GENET_PHY_RETRY; Retry > 0; Retry--) {
> + Value = GenetMmioRead (Genet, GENET_MDIO_CMD);
> + if ((Value & GENET_MDIO_START_BUSY) == 0) {
> + *Data = Value & 0xffff;
> + break;
> + }
> + gBS->Stall (10);
> + }
> +
> + if (Retry == 0) {
> + DEBUG ((DEBUG_ERROR,
> + "%a: Timeout reading PhyAddr %d, Reg %d\n", __FUNCTION__, PhyAddr, Reg));
> + return EFI_DEVICE_ERROR;
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Perform a GENET PHY register write.
> +
> + @param Priv[in] Pointer to GENET_PRIVATE_DATA.
> + @param PhyAddr[in] PHY address.
> + @param Reg[in] PHY register.
> + @param Data[in] Pointer to register data to write.
> +
> + @retval EFI_SUCCESS Data written successfully.
> + @retval EFI_DEVICE_ERROR Failed to write data.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +GenetPhyWrite (
> + IN VOID *Priv,
> + IN UINT8 PhyAddr,
> + IN UINT8 Reg,
> + IN UINT16 Data
> + )
> +{
> + GENET_PRIVATE_DATA *Genet;
> + UINTN Retry;
> + UINT32 Value;
> +
> + Genet = Priv;
> + Value = GENET_MDIO_WRITE |
> + GENET_MDIO_START_BUSY |
> + __SHIFTIN (PhyAddr, GENET_MDIO_PMD) |
> + __SHIFTIN (Reg, GENET_MDIO_REG);
> + GenetMmioWrite (Genet, GENET_MDIO_CMD, Value | Data);
> +
> + for (Retry = GENET_PHY_RETRY; Retry > 0; Retry--) {
> + Value = GenetMmioRead (Genet, GENET_MDIO_CMD);
> + if ((Value & GENET_MDIO_START_BUSY) == 0) {
> + break;
> + }
> + gBS->Stall (10);
> + }
> +
> + if (Retry == 0) {
> + DEBUG ((DEBUG_ERROR,
> + "%a: Timeout writing PhyAddr %d, Reg %d\n", __FUNCTION__, PhyAddr, Reg));
> + return EFI_DEVICE_ERROR;
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Process a PHY link speed change (e.g. with MAC layer).
> +
> + @param Priv[in] Pointer to GENET_PRIVATE_DATA.
> + @param Speed[in] Speed setting.
> + @param Duplex[in] Duplex setting.
> +
> +**/
> +VOID
> +EFIAPI
> +GenetPhyConfigure (
> + IN VOID *Priv,
> + IN GENERIC_PHY_SPEED Speed,
> + IN GENERIC_PHY_DUPLEX Duplex
> + )
> +{
> + GENET_PRIVATE_DATA *Genet;
> + UINT32 Value;
> +
> + Genet = Priv;
> + Value = GenetMmioRead (Genet, GENET_EXT_RGMII_OOB_CTRL);
> + Value &= ~GENET_EXT_RGMII_OOB_OOB_DISABLE;
> + Value |= GENET_EXT_RGMII_OOB_RGMII_LINK;
> + Value |= GENET_EXT_RGMII_OOB_RGMII_MODE_EN;
> + if (Genet->PhyMode == GENET_PHY_MODE_RGMII) {
> + Value |= GENET_EXT_RGMII_OOB_ID_MODE_DISABLE;
> + } else {
> + Value &= ~GENET_EXT_RGMII_OOB_ID_MODE_DISABLE;
> + }
> + GenetMmioWrite (Genet, GENET_EXT_RGMII_OOB_CTRL, Value);
> +
> + Value = GenetMmioRead (Genet, GENET_UMAC_CMD);
> + Value &= ~GENET_UMAC_CMD_SPEED;
> + switch (Speed) {
> + case PHY_SPEED_1000:
> + Value |= __SHIFTIN (GENET_UMAC_CMD_SPEED_1000, GENET_UMAC_CMD_SPEED);
> + break;
> + case PHY_SPEED_100:
> + Value |= __SHIFTIN (GENET_UMAC_CMD_SPEED_100, GENET_UMAC_CMD_SPEED);
> + break;
> + default:
> + Value |= __SHIFTIN (GENET_UMAC_CMD_SPEED_10, GENET_UMAC_CMD_SPEED);
> + break;
> + }
> + if (Duplex == PHY_DUPLEX_FULL) {
> + Value &= ~GENET_UMAC_CMD_HD_EN;
> + } else {
> + Value |= GENET_UMAC_CMD_HD_EN;
> + }
> + GenetMmioWrite (Genet, GENET_UMAC_CMD, Value);
> +}
> +
> +/**
> + Extra action to run after a PHY reset. This adds the appropriate clock
> + delay based on the PHY mode.
> +
> + @param Priv[in] Pointer to GENET_PRIVATE_DATA.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +GenetPhyResetAction (
> + IN VOID *Priv
> + )
> +{
> + GENET_PRIVATE_DATA *Genet;
> + UINT16 Value;
> + EFI_STATUS Status;
> +
> + Genet = Priv;
> + Status = GenetPhyWrite (Priv, Genet->Phy.PhyAddr, BRGPHY_MII_AUXCTL,
> + BRGPHY_AUXCTL_SHADOW_MISC |
> + (BRGPHY_AUXCTL_SHADOW_MISC << BRGPHY_AUXCTL_MISC_READ_SHIFT));
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = GenetPhyRead (Priv, Genet->Phy.PhyAddr, BRGPHY_MII_AUXCTL, &Value);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Value &= BRGPHY_AUXCTL_MISC_DATA_MASK;
> +
> + if (Genet->PhyMode == GENET_PHY_MODE_RGMII_RXID ||
> + Genet->PhyMode == GENET_PHY_MODE_RGMII_ID) {
> + Value |= BRGPHY_AUXCTL_MISC_RGMII_SKEW_EN;
> + } else {
> + Value &= ~BRGPHY_AUXCTL_MISC_RGMII_SKEW_EN;
> + }
> +
> + Status = GenetPhyWrite (Priv, Genet->Phy.PhyAddr, BRGPHY_MII_AUXCTL,
> + BRGPHY_AUXCTL_MISC_WRITE_EN | BRGPHY_AUXCTL_SHADOW_MISC | Value);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = GenetPhyWrite (Priv, Genet->Phy.PhyAddr, BRGPHY_MII_SHADOW_1C,
> + BRGPHY_SHADOW_1C_CLK_CTRL);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = GenetPhyRead (Priv, Genet->Phy.PhyAddr, BRGPHY_MII_SHADOW_1C, &Value);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Value &= BRGPHY_SHADOW_1C_DATA_MASK;
> +
> + if (Genet->PhyMode == GENET_PHY_MODE_RGMII_TXID ||
> + Genet->PhyMode == GENET_PHY_MODE_RGMII_ID) {
> + Value |= BRGPHY_SHADOW_1C_GTXCLK_EN;
> + } else {
> + Value &= ~BRGPHY_SHADOW_1C_GTXCLK_EN;
> + }
> +
> + Status = GenetPhyWrite (Priv, Genet->Phy.PhyAddr, BRGPHY_MII_SHADOW_1C,
> + BRGPHY_SHADOW_1C_WRITE_EN | BRGPHY_SHADOW_1C_CLK_CTRL | Value);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Reset GENET.
> +
> + @param Genet[in] Pointer to GENET_PRIVATE_DATA.
> +
> +**/
> +VOID
> +GenetReset (
> + IN GENET_PRIVATE_DATA *Genet
> + )
> +{
> + UINT32 Value;
> +
> + Value = GenetMmioRead (Genet, GENET_SYS_RBUF_FLUSH_CTRL);
> + Value |= GENET_SYS_RBUF_FLUSH_RESET;
> + GenetMmioWrite (Genet, GENET_SYS_RBUF_FLUSH_CTRL, Value);
> + gBS->Stall (10);
> +
> + Value &= ~GENET_SYS_RBUF_FLUSH_RESET;
> + GenetMmioWrite (Genet, GENET_SYS_RBUF_FLUSH_CTRL, Value);
> + gBS->Stall (10);
> +
> + GenetMmioWrite (Genet, GENET_SYS_RBUF_FLUSH_CTRL, 0);
> + gBS->Stall (10);
> +
> + GenetMmioWrite (Genet, GENET_UMAC_CMD, 0);
> + GenetMmioWrite (Genet, GENET_UMAC_CMD,
> + GENET_UMAC_CMD_LCL_LOOP_EN | GENET_UMAC_CMD_SW_RESET);
> + gBS->Stall (10);
> + GenetMmioWrite (Genet, GENET_UMAC_CMD, 0);
> +
> + GenetMmioWrite (Genet, GENET_UMAC_MIB_CTRL,
> + GENET_UMAC_MIB_RESET_RUNT | GENET_UMAC_MIB_RESET_RX | GENET_UMAC_MIB_RESET_TX);
> + GenetMmioWrite (Genet, GENET_UMAC_MIB_CTRL, 0);
> +
> + GenetMmioWrite (Genet, GENET_UMAC_MAX_FRAME_LEN, GENET_MAX_PACKET_SIZE);
> +
> + Value = GenetMmioRead (Genet, GENET_RBUF_CTRL);
> + Value |= GENET_RBUF_ALIGN_2B;
> + GenetMmioWrite (Genet, GENET_RBUF_CTRL, Value);
> +
> + GenetMmioWrite (Genet, GENET_RBUF_TBUF_SIZE_CTRL, 1);
> +}
> +
> +/**
> + Set the station address.
> +
> + @param Genet[in] Pointer to GENET_PRIVATE_DATA.
> + @param MacAddr[in] MAC address to set.
> +
> +**/
> +VOID
> +EFIAPI
> +GenetSetMacAddress (
> + IN GENET_PRIVATE_DATA *Genet,
> + IN EFI_MAC_ADDRESS *MacAddr
> + )
> +{
> + UINT32 Value;
> +
> + Value = MacAddr->Addr[3] |
> + MacAddr->Addr[2] << 8 |
> + MacAddr->Addr[1] << 16 |
> + MacAddr->Addr[0] << 24;
> + GenetMmioWrite (Genet, GENET_UMAC_MAC0, Value);
> + Value = MacAddr->Addr[5] |
> + MacAddr->Addr[4] << 8;
> + GenetMmioWrite (Genet, GENET_UMAC_MAC1, Value);
> +}
> +
> +/**
> + Set a PHY mode.
> +
> + @param Genet[in] Pointer to GENET_PRIVATE_DATA.
> + @param PhyMode[in] Mode to set.
> +
> +**/
> +VOID
> +GenetSetPhyMode (
> + IN GENET_PRIVATE_DATA *Genet,
> + IN GENET_PHY_MODE PhyMode
> + )
> +{
> + UINT32 Value;
> +
> + switch (PhyMode) {
> + case GENET_PHY_MODE_RGMII:
> + case GENET_PHY_MODE_RGMII_RXID:
> + case GENET_PHY_MODE_RGMII_TXID:
> + case GENET_PHY_MODE_RGMII_ID:
> + Value = GENET_SYS_PORT_MODE_EXT_GPHY;
> + break;
> + default:
> + Value = 0;
> + break;
> + }
> + GenetMmioWrite (Genet, GENET_SYS_PORT_CTRL, Value);
> +}
> +
> +/**
> + Enable TX/RX.
> +
> + @param Genet[in] Pointer to GENET_PRIVATE_DATA.
> +
> +**/
> +VOID
> +GenetEnableTxRx (
> + IN GENET_PRIVATE_DATA *Genet
> + )
> +{
> + UINT32 Value;
> +
> + // Start TX DMA on default queue
> + Value = GenetMmioRead (Genet, GENET_TX_DMA_CTRL);
> + Value |= GENET_TX_DMA_CTRL_EN |
> + GENET_TX_DMA_CTRL_RBUF_EN (GENET_DMA_DEFAULT_QUEUE);
> + GenetMmioWrite (Genet, GENET_TX_DMA_CTRL, Value);
> +
> + // Start RX DMA on default queue
> + Value = GenetMmioRead (Genet, GENET_RX_DMA_CTRL);
> + Value |= GENET_RX_DMA_CTRL_EN |
> + GENET_RX_DMA_CTRL_RBUF_EN (GENET_DMA_DEFAULT_QUEUE);
> + GenetMmioWrite (Genet, GENET_RX_DMA_CTRL, Value);
> +
> + // Enable transmitter and receiver
> + Value = GenetMmioRead (Genet, GENET_UMAC_CMD);
> + Value |= GENET_UMAC_CMD_TXEN | GENET_UMAC_CMD_RXEN;
> + GenetMmioWrite (Genet, GENET_UMAC_CMD, Value);
> +
> + // Enable interrupts
> + GenetMmioWrite (Genet, GENET_INTRL2_CPU_CLEAR_MASK,
> + GENET_IRQ_TXDMA_DONE | GENET_IRQ_RXDMA_DONE);
> +}
> +
> +/**
> + Disable TX/RX.
> +
> + @param Genet[in] Pointer to GENET_PRIVATE_DATA.
> +
> +**/
> +VOID
> +GenetDisableTxRx (
> + IN GENET_PRIVATE_DATA *Genet
> + )
> +{
> + UINT32 Value;
> +
> + // Disable interrupts
> + GenetMmioWrite (Genet, GENET_INTRL2_CPU_SET_MASK, 0xFFFFFFFF);
> + GenetMmioWrite (Genet, GENET_INTRL2_CPU_CLEAR, 0xFFFFFFFF);
> +
> + // Disable receiver
> + Value = GenetMmioRead (Genet, GENET_UMAC_CMD);
> + Value &= ~GENET_UMAC_CMD_RXEN;
> + GenetMmioWrite (Genet, GENET_UMAC_CMD, Value);
> +
> + // Stop RX DMA
> + Value = GenetMmioRead (Genet, GENET_RX_DMA_CTRL);
> + Value &= ~GENET_RX_DMA_CTRL_EN;
> + Value &= ~GENET_RX_DMA_CTRL_RBUF_EN (GENET_DMA_DEFAULT_QUEUE);
> + GenetMmioWrite (Genet, GENET_RX_DMA_CTRL, Value);
> +
> + // Stop TX DMA
> + Value = GenetMmioRead (Genet, GENET_TX_DMA_CTRL);
> + Value &= ~GENET_TX_DMA_CTRL_EN;
> + Value &= ~GENET_TX_DMA_CTRL_RBUF_EN (GENET_DMA_DEFAULT_QUEUE);
> + GenetMmioWrite (Genet, GENET_TX_DMA_CTRL, Value);
> +
> + // Flush data in the TX FIFO
> + GenetMmioWrite (Genet, GENET_UMAC_TX_FLUSH, 1);
> + gBS->Stall (10);
> + GenetMmioWrite (Genet, GENET_UMAC_TX_FLUSH, 0);
> +
> + // Disable transmitter
> + Value = GenetMmioRead (Genet, GENET_UMAC_CMD);
> + Value &= ~GENET_UMAC_CMD_TXEN;
> + GenetMmioWrite (Genet, GENET_UMAC_CMD, Value);
> +}
> +
> +/**
> + Change promiscuous mode state.
> +
> + @param Genet[in] Pointer to GENET_PRIVATE_DATA.
> + @param Enable[in] Promiscuous mode state.
> +
> +**/
> +VOID
> +GenetSetPromisc (
> + IN GENET_PRIVATE_DATA *Genet,
> + IN BOOLEAN Enable
> + )
> +{
> + UINT32 Value;
> +
> + Value = GenetMmioRead (Genet, GENET_UMAC_CMD);
> + if (Enable) {
> + Value |= GENET_UMAC_CMD_PROMISC;
> + } else {
> + Value &= ~GENET_UMAC_CMD_PROMISC;
> + }
> + GenetMmioWrite (Genet, GENET_UMAC_CMD, Value);
> +}
> +
> +/**
> + Enable the MAC filter for the Ethernet broadcast address
> +
> + @param Genet[in] Pointer to GENET_PRIVATE_DATA.
> + @param Enable[in] Promiscuous mode state.
> +
> +**/
> +VOID
> +GenetEnableBroadcastFilter (
> + IN GENET_PRIVATE_DATA *Genet,
> + IN BOOLEAN Enable
> + )
> +{
> + CONST EFI_MAC_ADDRESS *MacAddr;
> + UINT32 Value;
> +
> + if (Enable) {
> + MacAddr = &Genet->SnpMode.CurrentAddress;
> +
> + GenetMmioWrite (Genet, GENET_UMAC_MDF_ADDR0 (0),
> + MacAddr->Addr[1] | MacAddr->Addr[0] << 8);
> + GenetMmioWrite (Genet, GENET_UMAC_MDF_ADDR1 (0),
> + MacAddr->Addr[5] | MacAddr->Addr[4] << 8 |
> + MacAddr->Addr[3] << 16 | MacAddr->Addr[2] << 24);
> +
> + GenetMmioWrite (Genet, GENET_UMAC_MDF_ADDR0 (1), 0xffff);
> + GenetMmioWrite (Genet, GENET_UMAC_MDF_ADDR1 (1), 0xffffffff);
> +
> + Value = BIT16 | BIT15; // enable filters 0 and 1
> + } else {
> + Value = 0;
> + }
> + GenetMmioWrite (Genet, GENET_UMAC_MDF_CTRL, Value);
> +}
> +
> +/**
> + Configure DMA TX and RX queues, enabling them.
> +
> + @param Genet[in] Pointer to GENET_PRIVATE_DATA.
> +
> +**/
> +VOID
> +GenetDmaInitRings (
> + IN GENET_PRIVATE_DATA *Genet
> + )
> +{
> + UINT8 Qid;
> +
> + Qid = GENET_DMA_DEFAULT_QUEUE;
> +
> + Genet->TxQueued = 0;
> + Genet->TxNext = 0;
> + Genet->TxConsIndex = 0;
> + Genet->TxProdIndex = 0;
> +
> + Genet->RxConsIndex = 0;
> + Genet->RxProdIndex = 0;
> +
> + // Configure TX queue
> + GenetMmioWrite (Genet, GENET_TX_SCB_BURST_SIZE, 0x08);
> + GenetMmioWrite (Genet, GENET_TX_DMA_READ_PTR_LO (Qid), 0);
> + GenetMmioWrite (Genet, GENET_TX_DMA_READ_PTR_HI (Qid), 0);
> + GenetMmioWrite (Genet, GENET_TX_DMA_CONS_INDEX (Qid), 0);
> + GenetMmioWrite (Genet, GENET_TX_DMA_PROD_INDEX (Qid), 0);
> + GenetMmioWrite (Genet, GENET_TX_DMA_RING_BUF_SIZE (Qid),
> + __SHIFTIN (GENET_DMA_DESC_COUNT, GENET_TX_DMA_RING_BUF_SIZE_DESC_COUNT) |
> + __SHIFTIN (GENET_MAX_PACKET_SIZE, GENET_TX_DMA_RING_BUF_SIZE_BUF_LENGTH));
> + GenetMmioWrite (Genet, GENET_TX_DMA_START_ADDR_LO (Qid), 0);
> + GenetMmioWrite (Genet, GENET_TX_DMA_START_ADDR_HI (Qid), 0);
> + GenetMmioWrite (Genet, GENET_TX_DMA_END_ADDR_LO (Qid),
> + GENET_DMA_DESC_COUNT * GENET_DMA_DESC_SIZE / 4 - 1);
> + GenetMmioWrite (Genet, GENET_TX_DMA_END_ADDR_HI (Qid), 0);
> + GenetMmioWrite (Genet, GENET_TX_DMA_MBUF_DONE_THRES (Qid), 1);
> + GenetMmioWrite (Genet, GENET_TX_DMA_FLOW_PERIOD (Qid), 0);
> + GenetMmioWrite (Genet, GENET_TX_DMA_WRITE_PTR_LO (Qid), 0);
> + GenetMmioWrite (Genet, GENET_TX_DMA_WRITE_PTR_HI (Qid), 0);
> +
> + // Enable TX queue
> + GenetMmioWrite (Genet, GENET_TX_DMA_RING_CFG, (1U << Qid));
> +
> + // Configure RX queue
> + GenetMmioWrite (Genet, GENET_RX_SCB_BURST_SIZE, 0x08);
> + GenetMmioWrite (Genet, GENET_RX_DMA_WRITE_PTR_LO (Qid), 0);
> + GenetMmioWrite (Genet, GENET_RX_DMA_WRITE_PTR_HI (Qid), 0);
> + GenetMmioWrite (Genet, GENET_RX_DMA_PROD_INDEX (Qid), 0);
> + GenetMmioWrite (Genet, GENET_RX_DMA_CONS_INDEX (Qid), 0);
> + GenetMmioWrite (Genet, GENET_RX_DMA_RING_BUF_SIZE (Qid),
> + __SHIFTIN (GENET_DMA_DESC_COUNT, GENET_RX_DMA_RING_BUF_SIZE_DESC_COUNT) |
> + __SHIFTIN (GENET_MAX_PACKET_SIZE, GENET_RX_DMA_RING_BUF_SIZE_BUF_LENGTH));
> + GenetMmioWrite (Genet, GENET_RX_DMA_START_ADDR_LO (Qid), 0);
> + GenetMmioWrite (Genet, GENET_RX_DMA_START_ADDR_HI (Qid), 0);
> + GenetMmioWrite (Genet, GENET_RX_DMA_END_ADDR_LO (Qid),
> + GENET_DMA_DESC_COUNT * GENET_DMA_DESC_SIZE / 4 - 1);
> + GenetMmioWrite (Genet, GENET_RX_DMA_END_ADDR_HI (Qid), 0);
> + GenetMmioWrite (Genet, GENET_RX_DMA_XON_XOFF_THRES (Qid),
> + __SHIFTIN (5, GENET_RX_DMA_XON_XOFF_THRES_LO) |
> + __SHIFTIN (GENET_DMA_DESC_COUNT >> 4, GENET_RX_DMA_XON_XOFF_THRES_HI));
> + GenetMmioWrite (Genet, GENET_RX_DMA_READ_PTR_LO (Qid), 0);
> + GenetMmioWrite (Genet, GENET_RX_DMA_READ_PTR_HI (Qid), 0);
> +
> + // Enable RX queue
> + GenetMmioWrite (Genet, GENET_RX_DMA_RING_CFG, (1U << Qid));
> +}
> +
> +/**
> + Allocate DMA buffers for RX.
> +
> + @param Genet[in] Pointer to GENET_PRIVATE_DATA.
> +
> + @retval EFI_SUCCESS DMA buffers allocated.
> + @retval EFI_OUT_OF_RESOURCES DMA buffers could not be allocated.
> +**/
> +EFI_STATUS
> +GenetDmaAlloc (
> + IN GENET_PRIVATE_DATA *Genet
> + )
> +{
> + EFI_STATUS Status;
> +
> + Genet->RxBuffer = mDmaAddressLimit;
> + Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData,
> + EFI_SIZE_TO_PAGES (GENET_MAX_PACKET_SIZE * GENET_DMA_DESC_COUNT),
> + &Genet->RxBuffer);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR,
> + "%a: Failed to allocate RX buffer: %r\n", __FUNCTION__, Status));
> + }
> + return Status;
> +}
> +
> +/**
> + Given an RX buffer descriptor index, program the IO address of the buffer into the hardware.
> +
> + @param Genet[in] Pointer to GENET_PRIVATE_DATA.
> + @param DescIndex[in] Index of RX buffer descriptor.
> +
> + @retval EFI_SUCCESS DMA buffers allocated.
> + @retval Others Programmatic errors, as buffers come from DmaAllocateBuffer, and thus
> + cannot fail DmaMap (for the expected NonCoherentDmaLib).
> +**/
> +EFI_STATUS
> +GenetDmaMapRxDescriptor (
> + IN GENET_PRIVATE_DATA * Genet,
> + IN UINT8 DescIndex
> + )
> +{
> + EFI_STATUS Status;
> + UINTN DmaNumberOfBytes;
> +
> + ASSERT (Genet->RxBufferMap[DescIndex].Mapping == NULL);
> + ASSERT (Genet->RxBuffer != 0);
> +
> + DmaNumberOfBytes = GENET_MAX_PACKET_SIZE;
> + Status = DmaMap (MapOperationBusMasterWrite,
> + GENET_RX_BUFFER (Genet, DescIndex),
> + &DmaNumberOfBytes,
> + &Genet->RxBufferMap[DescIndex].PhysAddress,
> + &Genet->RxBufferMap[DescIndex].Mapping);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "%a: Failed to map RX buffer: %r\n",
> + __FUNCTION__, Status));
> + return Status;
> + }
> +
> + GenetMmioWrite (Genet, GENET_RX_DESC_ADDRESS_LO (DescIndex),
> + Genet->RxBufferMap[DescIndex].PhysAddress & 0xFFFFFFFF);
> + GenetMmioWrite (Genet, GENET_RX_DESC_ADDRESS_HI (DescIndex),
> + (Genet->RxBufferMap[DescIndex].PhysAddress >> 32) & 0xFFFFFFFF);
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Given an RX buffer descriptor index, undo the DmaMap operation on the buffer.
> +
> + @param Genet[in] Pointer to GENET_PRIVATE_DATA.
> + @param DescIndex[in] Index of RX buffer descriptor.
> +
> +**/
> +VOID
> +GenetDmaUnmapRxDescriptor (
> + IN GENET_PRIVATE_DATA * Genet,
> + IN UINT8 DescIndex
> + )
> +{
> + if (Genet->RxBufferMap[DescIndex].Mapping != NULL) {
> + DmaUnmap (Genet->RxBufferMap[DescIndex].Mapping);
> + Genet->RxBufferMap[DescIndex].Mapping = NULL;
> + }
> +}
> +
> +/**
> + Free DMA buffers for RX, undoing GenetDmaAlloc.
> +
> + @param Genet[in] Pointer to GENET_PRIVATE_DATA.
> + @param DescIndex[in] Index of RX buffer descriptor.
> +
> +**/
> +VOID
> +GenetDmaFree (
> + IN GENET_PRIVATE_DATA *Genet
> + )
> +{
> + UINTN Idx;
> +
> + for (Idx = 0; Idx < GENET_DMA_DESC_COUNT; Idx++) {
> + GenetDmaUnmapRxDescriptor (Genet, Idx);
> + }
> + gBS->FreePages (Genet->RxBuffer,
> + EFI_SIZE_TO_PAGES (GENET_MAX_PACKET_SIZE * GENET_DMA_DESC_COUNT));
> +}
> +
> +/**
> + Queue TX transmission, given a buffer to transmit and a TX descriptor index.
> +
> + @param Genet[in] Pointer to GENET_PRIVATE_DATA.
> + @param DescIndex[in] TX descriptor index.
> + @param PhysAddr[in] Buffer to transmit.
> + @param NumberOfBytes[in] Buffer length.
> +
> +**/
> +VOID
> +GenetDmaTriggerTx (
> + IN GENET_PRIVATE_DATA * Genet,
> + IN UINT8 DescIndex,
> + IN EFI_PHYSICAL_ADDRESS PhysAddr,
> + IN UINTN NumberOfBytes
> + )
> +{
> + UINT32 DescStatus;
> +
> + DescStatus = GENET_TX_DESC_STATUS_SOP |
> + GENET_TX_DESC_STATUS_EOP |
> + GENET_TX_DESC_STATUS_CRC |
> + GENET_TX_DESC_STATUS_QTAG |
> + __SHIFTIN (NumberOfBytes, GENET_TX_DESC_STATUS_BUFLEN);
> +
> + GenetMmioWrite (Genet, GENET_TX_DESC_ADDRESS_LO (DescIndex),
> + PhysAddr & 0xFFFFFFFF);
> + GenetMmioWrite (Genet, GENET_TX_DESC_ADDRESS_HI (DescIndex),
> + (PhysAddr >> 32) & 0xFFFFFFFF);
> + GenetMmioWrite (Genet, GENET_TX_DESC_STATUS (DescIndex), DescStatus);
> +
> + GenetMmioWrite (Genet, GENET_TX_DMA_PROD_INDEX (GENET_DMA_DEFAULT_QUEUE),
> + (DescIndex + 1) & 0xFFFF);
> +}
> +
> +/**
> + Simulate a "TX interrupt", return the next (completed) TX buffer to recycle.
> +
> + @param Genet[in] Pointer to GENET_PRIVATE_DATA.
> + @param TxBuf[out] Location to store pointer to next TX buffer to recycle.
> +
> +**/
> +VOID
> +GenetTxIntr (
> + IN GENET_PRIVATE_DATA *Genet,
> + OUT VOID **TxBuf
> + )
> +{
> + UINT32 ConsIndex, Total;
> +
> + ConsIndex = GenetMmioRead (Genet,
> + GENET_TX_DMA_CONS_INDEX (GENET_DMA_DEFAULT_QUEUE)) & 0xFFFF;
> +
> + Total = (ConsIndex - Genet->TxConsIndex) & 0xFFFF;
> + if (Genet->TxQueued > 0 && Total > 0) {
> + DmaUnmap (Genet->TxBufferMap[Genet->TxNext]);
> + *TxBuf = Genet->TxBuffer[Genet->TxNext];
> + Genet->TxQueued--;
> + Genet->TxNext = (Genet->TxNext + 1) % GENET_DMA_DESC_COUNT;
> + Genet->TxConsIndex++;
> + } else {
> + *TxBuf = NULL;
> + }
> +}
> +
> +/**
> + Simulate an "RX interrupt", returning the index of a completed RX buffer and
> + corresponding frame length.
> +
> + @param Genet[in] Pointer to GENET_PRIVATE_DATA.
> + @param DescIndex[out] Location to store completed RX buffer index.
> + @param FrameLength[out] Location to store frame length.
> +
> + @retval EFI_SUCCESS Data received.
> + @retval EFI_NOT_READY No RX buffers ready as no data received.
> +
> +**/
> +EFI_STATUS
> +GenetRxIntr (
> + IN GENET_PRIVATE_DATA *Genet,
> + OUT UINT8 *DescIndex,
> + OUT UINTN *FrameLength
> + )
> +{
> + EFI_STATUS Status;
> + UINT32 ProdIndex, Total;
> + UINT32 DescStatus;
> +
> + ProdIndex = GenetMmioRead (Genet,
> + GENET_RX_DMA_PROD_INDEX (GENET_DMA_DEFAULT_QUEUE)) & 0xFFFF;
> +
> + Total = (ProdIndex - Genet->RxConsIndex) & 0xFFFF;
> + if (Total > 0) {
> + *DescIndex = Genet->RxConsIndex % GENET_DMA_DESC_COUNT;
> + DescStatus = GenetMmioRead (Genet, GENET_RX_DESC_STATUS (*DescIndex));
> + *FrameLength = __SHIFTOUT (DescStatus, GENET_RX_DESC_STATUS_BUFLEN);
> +
> + Genet->RxConsIndex = (Genet->RxConsIndex + 1) & 0xFFFF;
> + GenetMmioWrite (Genet, GENET_RX_DMA_CONS_INDEX (GENET_DMA_DEFAULT_QUEUE),
> + Genet->RxConsIndex);
> + Status = EFI_SUCCESS;
> + } else {
> + Status = EFI_NOT_READY;
> + }
> +
> + return Status;
> +}
> diff --git a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/SimpleNetwork.c b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/SimpleNetwork.c
> new file mode 100644
> index 000000000000..b2cae687b3d4
> --- /dev/null
> +++ b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/SimpleNetwork.c
> @@ -0,0 +1,834 @@
> +/** @file
> + Provides the Simple Network functions.
> +
> + Copyright (c) 2020 Jared McNeill. All rights reserved.
> + Copyright (c) 2020 Andrey Warkentin <andrey.warkentin@gmail.com>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "GenetUtil.h"
> +
> +#include <Library/DmaLib.h>
> +
> +
> +/**
> + Changes the state of a network interface from "stopped" to "started".
> +
> + @param This Protocol instance pointer.
> +
> + @retval EFI_SUCCESS The network interface was started.
> + @retval EFI_ALREADY_STARTED The network interface is already in the started state.
> + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
> + @retval EFI_DEVICE_ERROR The network interface is not in the right (stopped) state.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GenetSimpleNetworkStart (
> + IN EFI_SIMPLE_NETWORK_PROTOCOL *This
> + )
> +{
> + GENET_PRIVATE_DATA *Genet;
> +
> + if (This == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Genet = GENET_PRIVATE_DATA_FROM_SNP_THIS (This);
> + if (Genet->SnpMode.State == EfiSimpleNetworkStarted) {
> + return EFI_ALREADY_STARTED;
> + } else if (Genet->SnpMode.State != EfiSimpleNetworkStopped) {
> + return EFI_DEVICE_ERROR;
> + }
> +
> + Genet->SnpMode.State = EfiSimpleNetworkStarted;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Changes the state of a network interface from "started" to "stopped".
> +
> + @param This Protocol instance pointer.
> +
> + @retval EFI_SUCCESS The network interface was stopped.
> + @retval EFI_NOT_STARTED The network interface is already in the stopped state.
> + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
> + @retval EFI_DEVICE_ERROR The network interface is not in the right (started) state.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GenetSimpleNetworkStop (
> + IN EFI_SIMPLE_NETWORK_PROTOCOL *This
> + )
> +{
> + GENET_PRIVATE_DATA *Genet;
> +
> + if (This == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Genet = GENET_PRIVATE_DATA_FROM_SNP_THIS (This);
> + if (Genet->SnpMode.State == EfiSimpleNetworkStopped) {
> + return EFI_NOT_STARTED;
> + } else if (Genet->SnpMode.State != EfiSimpleNetworkStarted) {
> + return EFI_DEVICE_ERROR;
> + }
> +
> + GenetDisableTxRx (Genet);
> +
> + Genet->SnpMode.State = EfiSimpleNetworkStopped;
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Resets a network adapter and allocates the transmit and receive buffers
> + required by the network interface; optionally, also requests allocation
> + of additional transmit and receive buffers.
> +
> + @param This The protocol instance pointer.
> + @param ExtraRxBufferSize The size, in bytes, of the extra receive buffer space
> + that the driver should allocate for the network interface.
> + Some network interfaces will not be able to use the extra
> + buffer, and the caller will not know if it is actually
> + being used.
> + @param ExtraTxBufferSize The size, in bytes, of the extra transmit buffer space
> + that the driver should allocate for the network interface.
> + Some network interfaces will not be able to use the extra
> + buffer, and the caller will not know if it is actually
> + being used.
> +
> + @retval EFI_SUCCESS The network interface was initialized.
> + @retval EFI_NOT_STARTED The network interface has not been started.
> + @retval EFI_OUT_OF_RESOURCES There was not enough memory for the transmit and
> + receive buffers.
> + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
> + @retval EFI_DEVICE_ERROR The network inteface is not in the right (started) state.
> + @retval EFI_DEVICE_ERROR PHY register read/write error.
> + @retval EFI_TIMEOUT PHY reset time-out.
> + @retval EFI_NOT_FOUND No PHY detected.
> + @retval EFI_UNSUPPORTED This function is not supported by the network interface.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GenetSimpleNetworkInitialize (
> + IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
> + IN UINTN ExtraRxBufferSize, OPTIONAL
> + IN UINTN ExtraTxBufferSize OPTIONAL
> + )
> +{
> + GENET_PRIVATE_DATA *Genet;
> + EFI_STATUS Status;
> + UINTN Idx;
> +
> + if (This == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Genet = GENET_PRIVATE_DATA_FROM_SNP_THIS (This);
> + if (Genet->SnpMode.State == EfiSimpleNetworkStopped) {
> + return EFI_NOT_STARTED;
> + } else if (Genet->SnpMode.State != EfiSimpleNetworkStarted) {
> + return EFI_DEVICE_ERROR;
> + }
> +
> + GenetReset (Genet);
> + GenetSetPhyMode (Genet, Genet->PhyMode);
> +
> + Status = GenericPhyInit (&Genet->Phy);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + GenetSetMacAddress (Genet, &Genet->SnpMode.CurrentAddress);
> +
> + GenetDmaInitRings (Genet);
> +
> + // Map RX buffers
> + for (Idx = 0; Idx < GENET_DMA_DESC_COUNT; Idx++) {
> + Status = GenetDmaMapRxDescriptor (Genet, Idx);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + }
> +
> + GenetEnableTxRx (Genet);
> +
> + Genet->SnpMode.State = EfiSimpleNetworkInitialized;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Resets a network adapter and re-initializes it with the parameters that were
> + provided in the previous call to Initialize().
> +
> + @param This The protocol instance pointer.
> + @param ExtendedVerification Indicates that the driver may perform a more
> + exhaustive verification operation of the device
> + during reset.
> +
> + @retval EFI_SUCCESS The network interface was reset.
> + @retval EFI_NOT_STARTED The network interface has not been started.
> + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
> + @retval EFI_DEVICE_ERROR The network inteface is not in the right (initialized) state.
> + @retval EFI_UNSUPPORTED This function is not supported by the network interface.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GenetSimpleNetworkReset (
> + IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
> + IN BOOLEAN ExtendedVerification
> + )
> +{
> + GENET_PRIVATE_DATA *Genet;
> + EFI_STATUS Status;
> +
> + if (This == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Genet = GENET_PRIVATE_DATA_FROM_SNP_THIS (This);
> + if (Genet->SnpMode.State == EfiSimpleNetworkStopped) {
> + return EFI_NOT_STARTED;
> + }
> + if (Genet->SnpMode.State != EfiSimpleNetworkInitialized) {
> + return EFI_DEVICE_ERROR;
> + }
> +
> + Status = GenericPhyReset (&Genet->Phy);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Resets a network adapter and leaves it in a state that is safe for
> + another driver to initialize.
> +
> + @param This Protocol instance pointer.
> +
> + @retval EFI_SUCCESS The network interface was shutdown.
> + @retval EFI_NOT_STARTED The network interface has not been started.
> + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
> + @retval EFI_DEVICE_ERROR The network inteface is not in the right (initialized) state.
> + @retval EFI_UNSUPPORTED This function is not supported by the network interface.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GenetSimpleNetworkShutdown (
> + IN EFI_SIMPLE_NETWORK_PROTOCOL *This
> + )
> +{
> + GENET_PRIVATE_DATA *Genet;
> + UINTN Idx;
> +
> + if (This == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Genet = GENET_PRIVATE_DATA_FROM_SNP_THIS (This);
> + if (Genet->SnpMode.State == EfiSimpleNetworkStopped) {
> + return EFI_NOT_STARTED;
> + }
> + if (Genet->SnpMode.State != EfiSimpleNetworkInitialized) {
> + return EFI_DEVICE_ERROR;
> + }
> +
> + GenetDisableTxRx (Genet);
> +
> + for (Idx = 0; Idx < GENET_DMA_DESC_COUNT; Idx++) {
> + GenetDmaUnmapRxDescriptor (Genet, Idx);
> + }
> +
> + Genet->SnpMode.State = EfiSimpleNetworkStarted;
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Manages the receive filters of a network interface.
> +
> + @param This The protocol instance pointer.
> + @param Enable A bit mask of receive filters to enable on the network interface.
> + @param Disable A bit mask of receive filters to disable on the network interface.
> + @param ResetMCastFilter Set to TRUE to reset the contents of the multicast receive
> + filters on the network interface to their default values.
> + @param McastFilterCnt Number of multicast HW MAC addresses in the new
> + MCastFilter list. This value must be less than or equal to
> + the MCastFilterCnt field of EFI_SIMPLE_NETWORK_MODE. This
> + field is optional if ResetMCastFilter is TRUE.
> + @param MCastFilter A pointer to a list of new multicast receive filter HW MAC
> + addresses. This list will replace any existing multicast
> + HW MAC address list. This field is optional if
> + ResetMCastFilter is TRUE.
> +
> + @retval EFI_SUCCESS The multicast receive filter list was updated.
> + @retval EFI_NOT_STARTED The network interface has not been started.
> + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
> + @retval EFI_DEVICE_ERROR The network inteface is not in the right (initialized) state.
> + @retval EFI_UNSUPPORTED This function is not supported by the network interface.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GenetSimpleNetworkReceiveFilters (
> + IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
> + IN UINT32 Enable,
> + IN UINT32 Disable,
> + IN BOOLEAN ResetMCastFilter,
> + IN UINTN MCastFilterCnt, OPTIONAL
> + IN EFI_MAC_ADDRESS *MCastFilter OPTIONAL
> + )
> +{
> + GENET_PRIVATE_DATA *Genet;
> +
> + if (This == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Genet = GENET_PRIVATE_DATA_FROM_SNP_THIS (This);
> + if (((Enable | Disable) & ~Genet->SnpMode.ReceiveFilterMask) != 0 ||
> + (!ResetMCastFilter && MCastFilterCnt > Genet->SnpMode.MaxMCastFilterCount)) {
> + return EFI_INVALID_PARAMETER;
> + }
> + if (Genet->SnpMode.State == EfiSimpleNetworkStopped) {
> + return EFI_NOT_STARTED;
> + }
> + if (Genet->SnpMode.State != EfiSimpleNetworkInitialized) {
> + return EFI_DEVICE_ERROR;
> + }
> +
> + GenetEnableBroadcastFilter (Genet,
> + (Enable & ~Disable & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0);
> +
> + GenetSetPromisc (Genet,
> + (Enable & ~Disable & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0);
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Modifies or resets the current station address, if supported.
> +
> + @param This The protocol instance pointer.
> + @param Reset Flag used to reset the station address to the network interfaces
> + permanent address.
> + @param New The new station address to be used for the network interface.
> +
> + @retval EFI_SUCCESS The network interfaces station address was updated.
> + @retval EFI_NOT_STARTED The network interface has not been started.
> + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
> + @retval EFI_DEVICE_ERROR The network inteface is not in the right (initialized) state.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GenetSimpleNetworkStationAddress (
> + IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
> + IN BOOLEAN Reset,
> + IN EFI_MAC_ADDRESS *New OPTIONAL
> + )
> +{
> + GENET_PRIVATE_DATA *Genet;
> +
> + if (This == NULL || This->Mode == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> + if (Reset == TRUE && New == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Genet = GENET_PRIVATE_DATA_FROM_SNP_THIS (This);
> + if (Genet->SnpMode.State == EfiSimpleNetworkStopped) {
> + return EFI_NOT_STARTED;
> + }
> + if (Genet->SnpMode.State != EfiSimpleNetworkInitialized) {
> + return EFI_DEVICE_ERROR;
> + }
> +
> + if (Reset) {
> + // Use permanent address
> + CopyMem (&This->Mode->CurrentAddress, &This->Mode->PermanentAddress,
> + sizeof (This->Mode->CurrentAddress));
> + } else {
> + // Use specified address
> + CopyMem (&This->Mode->CurrentAddress, New,
> + sizeof (This->Mode->CurrentAddress));
> + }
> +
> + GenetSetMacAddress (Genet, &Genet->SnpMode.CurrentAddress);
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Resets or collects the statistics on a network interface.
> +
> + @param This Protocol instance pointer.
> + @param Reset Set to TRUE to reset the statistics for the network interface.
> + @param StatisticsSize On input the size, in bytes, of StatisticsTable. On
> + output the size, in bytes, of the resulting table of
> + statistics.
> + @param StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that
> + contains the statistics.
> +
> + @retval EFI_SUCCESS The statistics were collected from the network interface.
> + @retval EFI_NOT_STARTED The network interface has not been started.
> + @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer
> + size needed to hold the statistics is returned in
> + StatisticsSize.
> + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
> + @retval EFI_DEVICE_ERROR The network inteface is not in the right (initialized) state.
> + @retval EFI_UNSUPPORTED This function is not supported by the network interface.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GenetSimpleNetworkStatistics (
> + IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
> + IN BOOLEAN Reset,
> + IN OUT UINTN *StatisticsSize, OPTIONAL
> + OUT EFI_NETWORK_STATISTICS *StatisticsTable OPTIONAL
> + )
> +{
> + return EFI_UNSUPPORTED;
> +}
> +
> +/**
> + Performs read and write operations on the NVRAM device attached to a
> + network interface.
> +
> + @param This The protocol instance pointer.
> + @param ReadWrite TRUE for read operations, FALSE for write operations.
> + @param Offset Byte offset in the NVRAM device at which to start the read or
> + write operation. This must be a multiple of NvRamAccessSize and
> + less than NvRamSize.
> + @param BufferSize The number of bytes to read or write from the NVRAM device.
> + This must also be a multiple of NvramAccessSize.
> + @param Buffer A pointer to the data buffer.
> +
> + @retval EFI_SUCCESS The NVRAM access was performed.
> + @retval EFI_NOT_STARTED The network interface has not been started.
> + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
> + @retval EFI_UNSUPPORTED This function is not supported by the network interface.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GenetSimpleNetworkNvData (
> + IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
> + IN BOOLEAN ReadWrite,
> + IN UINTN Offset,
> + IN UINTN BufferSize,
> + IN OUT VOID *Buffer
> + )
> +{
> + return EFI_UNSUPPORTED;
> +}
> +
> +/**
> + Reads the current interrupt status and recycled transmit buffer status from
> + a network interface.
> +
> + @param This The protocol instance pointer.
> + @param InterruptStatus A pointer to the bit mask of the currently active interrupts
> + If this is NULL, the interrupt status will not be read from
> + the device. If this is not NULL, the interrupt status will
> + be read from the device. When the interrupt status is read,
> + it will also be cleared. Clearing the transmit interrupt
> + does not empty the recycled transmit buffer array.
> + @param TxBuf Recycled transmit buffer address. The network interface will
> + not transmit if its internal recycled transmit buffer array
> + is full. Reading the transmit buffer does not clear the
> + transmit interrupt. If this is NULL, then the transmit buffer
> + status will not be read. If there are no transmit buffers to
> + recycle and TxBuf is not NULL, * TxBuf will be set to NULL.
> +
> + @retval EFI_SUCCESS The status of the network interface was retrieved.
> + @retval EFI_NOT_STARTED The network interface has not been started.
> + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
> + @retval EFI_DEVICE_ERROR The network inteface is not in the right (initialized) state.
> + @retval EFI_UNSUPPORTED This function is not supported by the network interface.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GenetSimpleNetworkGetStatus (
> + IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
> + OUT UINT32 *InterruptStatus, OPTIONAL
> + OUT VOID **TxBuf OPTIONAL
> + )
> +{
> + GENET_PRIVATE_DATA *Genet;
> + EFI_STATUS Status;
> +
> + if (This == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Genet = GENET_PRIVATE_DATA_FROM_SNP_THIS (This);
> + if (Genet->SnpMode.State == EfiSimpleNetworkStopped) {
> + return EFI_NOT_STARTED;
> + }
> + if (Genet->SnpMode.State != EfiSimpleNetworkInitialized) {
> + return EFI_DEVICE_ERROR;
> + }
> +
> + Status = GenericPhyUpdateConfig (&Genet->Phy);
> + if (EFI_ERROR (Status)) {
> + Genet->SnpMode.MediaPresent = FALSE;
> + } else {
> + Genet->SnpMode.MediaPresent = TRUE;
> +
> + if (TxBuf != NULL) {
> + GenetTxIntr (Genet, TxBuf);
> + }
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Places a packet in the transmit queue of a network interface.
> +
> + @param This The protocol instance pointer.
> + @param HeaderSize The size, in bytes, of the media header to be filled in by
> + the Transmit() function. If HeaderSize is non-zero, then it
> + must be equal to This->Mode->MediaHeaderSize and the DestAddr
> + and Protocol parameters must not be NULL.
> + @param BufferSize The size, in bytes, of the entire packet (media header and
> + data) to be transmitted through the network interface.
> + @param Buffer A pointer to the packet (media header followed by data) to be
> + transmitted. This parameter cannot be NULL. If HeaderSize is zero,
> + then the media header in Buffer must already be filled in by the
> + caller. If HeaderSize is non-zero, then the media header will be
> + filled in by the Transmit() function.
> + @param SrcAddr The source HW MAC address. If HeaderSize is zero, then this parameter
> + is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then
> + This->Mode->CurrentAddress is used for the source HW MAC address.
> + @param DestAddr The destination HW MAC address. If HeaderSize is zero, then this
> + parameter is ignored.
> + @param Protocol The type of header to build. If HeaderSize is zero, then this
> + parameter is ignored. See RFC 1700, section "Ether Types", for
> + examples.
> +
> + @retval EFI_SUCCESS The packet was placed on the transmit queue.
> + @retval EFI_NOT_STARTED The network interface has not been started.
> + @retval EFI_NOT_READY The network interface is too busy to accept this transmit request.
> + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.
> + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
> + @retval EFI_DEVICE_ERROR The network inteface is not in the right (initialized) state.
> + @retval EFI_UNSUPPORTED This function is not supported by the network interface.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GenetSimpleNetworkTransmit (
> + IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
> + IN UINTN HeaderSize,
> + IN UINTN BufferSize,
> + IN VOID *Buffer,
> + IN EFI_MAC_ADDRESS *SrcAddr, OPTIONAL
> + IN EFI_MAC_ADDRESS *DestAddr, OPTIONAL
> + IN UINT16 *Protocol OPTIONAL
> + )
> +{
> + GENET_PRIVATE_DATA *Genet;
> + EFI_STATUS Status;
> + UINT8 *Frame = Buffer;
> + UINT8 Desc;
> + PHYSICAL_ADDRESS DmaDeviceAddress;
> + UINTN DmaNumberOfBytes;
> +
> + if (This == NULL || Buffer == NULL) {
> + DEBUG ((DEBUG_ERROR, "%a: Invalid parameter (missing handle or buffer)\n",
> + __FUNCTION__));
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Genet = GENET_PRIVATE_DATA_FROM_SNP_THIS (This);
> + if (Genet->SnpMode.State == EfiSimpleNetworkStopped) {
> + return EFI_NOT_STARTED;
> + }
> + if (Genet->SnpMode.State != EfiSimpleNetworkInitialized) {
> + return EFI_DEVICE_ERROR;
> + }
> +
> + if (!Genet->SnpMode.MediaPresent) {
> + //
> + // Don't bother transmitting if there's no link.
> + //
> + return EFI_NOT_READY;
> + }
> +
> + if (HeaderSize != 0) {
> + if (HeaderSize != Genet->SnpMode.MediaHeaderSize) {
> + DEBUG ((DEBUG_ERROR,
> + "%a: Invalid parameter (header size mismatch; HeaderSize 0x%X, SnpMode.MediaHeaderSize 0x%X))\n",
> + __FUNCTION__, HeaderSize, Genet->SnpMode.MediaHeaderSize));
> + return EFI_INVALID_PARAMETER;
> + }
> + if (DestAddr == NULL || Protocol == NULL) {
> + DEBUG ((DEBUG_ERROR,
> + "%a: Invalid parameter (dest addr or protocol missing)\n",
> + __FUNCTION__));
> + return EFI_INVALID_PARAMETER;
> + }
> + }
> +
> + if (BufferSize < Genet->SnpMode.MediaHeaderSize) {
> + DEBUG ((DEBUG_ERROR, "%a: Buffer too small\n", __FUNCTION__));
> + return EFI_BUFFER_TOO_SMALL;
> + }
> +
> + Status = EfiAcquireLockOrFail (&Genet->Lock);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "%a: Couldn't get lock: %r\n", __FUNCTION__, Status));
> + return EFI_ACCESS_DENIED;
> + }
> +
> + if (Genet->TxQueued == GENET_DMA_DESC_COUNT - 1) {
> + EfiReleaseLock (&Genet->Lock);
> +
> + DEBUG ((DEBUG_ERROR, "%a: Queue full\n", __FUNCTION__));
> + return EFI_NOT_READY;
> + }
> +
> + if (HeaderSize != 0) {
> + CopyMem (&Frame[0], &DestAddr->Addr[0], NET_ETHER_ADDR_LEN);
> + CopyMem (&Frame[6], &SrcAddr->Addr[0], NET_ETHER_ADDR_LEN);
> + Frame[12] = (*Protocol & 0xFF00) >> 8;
> + Frame[13] = *Protocol & 0xFF;
> + }
> +
> + Desc = Genet->TxProdIndex % GENET_DMA_DESC_COUNT;
> +
> + Genet->TxBuffer[Desc] = Frame;
> +
> + DmaNumberOfBytes = BufferSize;
> + Status = DmaMap (MapOperationBusMasterRead,
> + (VOID *)(UINTN)Frame,
> + &DmaNumberOfBytes,
> + &DmaDeviceAddress,
> + &Genet->TxBufferMap[Desc]);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "%a: DmaMap failed: %r\n", __FUNCTION__, Status));
> + EfiReleaseLock (&Genet->Lock);
> + return Status;
> + }
> +
> + GenetDmaTriggerTx (Genet, Desc, DmaDeviceAddress, DmaNumberOfBytes);
> +
> + Genet->TxProdIndex = (Genet->TxProdIndex + 1) % 0xFFFF;
> + Genet->TxQueued++;
> +
> + EfiReleaseLock (&Genet->Lock);
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Receives a packet from a network interface.
> +
> + @param This The protocol instance pointer.
> + @param HeaderSize The size, in bytes, of the media header received on the network
> + interface. If this parameter is NULL, then the media header size
> + will not be returned.
> + @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in
> + bytes, of the packet that was received on the network interface.
> + @param Buffer A pointer to the data buffer to receive both the media header and
> + the data.
> + @param SrcAddr The source HW MAC address. If this parameter is NULL, the
> + HW MAC source address will not be extracted from the media
> + header.
> + @param DestAddr The destination HW MAC address. If this parameter is NULL,
> + the HW MAC destination address will not be extracted from the
> + media header.
> + @param Protocol The media header type. If this parameter is NULL, then the
> + protocol will not be extracted from the media header. See
> + RFC 1700 section "Ether Types" for examples.
> +
> + @retval EFI_SUCCESS The received data was stored in Buffer, and BufferSize has
> + been updated to the number of bytes received.
> + @retval EFI_NOT_STARTED The network interface has not been started.
> + @retval EFI_NOT_READY No packets received.
> + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.
> + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
> + @retval EFI_DEVICE_ERROR The network inteface is not in the right (initialized) state.
> + @retval EFI_UNSUPPORTED This function is not supported by the network interface.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GenetSimpleNetworkReceive (
> + IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
> + OUT UINTN *HeaderSize, OPTIONAL
> + IN OUT UINTN *BufferSize,
> + OUT VOID *Buffer,
> + OUT EFI_MAC_ADDRESS *SrcAddr, OPTIONAL
> + OUT EFI_MAC_ADDRESS *DestAddr, OPTIONAL
> + OUT UINT16 *Protocol OPTIONAL
> + )
> +{
> + GENET_PRIVATE_DATA *Genet;
> + EFI_STATUS Status;
> + UINT8 DescIndex;
> + UINT8 *Frame;
> + UINTN FrameLength;
> +
> + if (This == NULL || Buffer == NULL) {
> + DEBUG ((DEBUG_ERROR, "%a: Invalid parameter (missing handle or buffer)\n",
> + __FUNCTION__));
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Genet = GENET_PRIVATE_DATA_FROM_SNP_THIS (This);
> + if (Genet->SnpMode.State == EfiSimpleNetworkStopped) {
> + return EFI_NOT_STARTED;
> + }
> + if (Genet->SnpMode.State != EfiSimpleNetworkInitialized) {
> + return EFI_DEVICE_ERROR;
> + }
> +
> + Status = EfiAcquireLockOrFail (&Genet->Lock);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "%a: Couldn't get lock: %r\n", __FUNCTION__, Status));
> + return EFI_ACCESS_DENIED;
> + }
> +
> + Status = GenetRxIntr (Genet, &DescIndex, &FrameLength);
> + if (EFI_ERROR (Status)) {
> + EfiReleaseLock (&Genet->Lock);
> + return Status;
> + }
> +
> + ASSERT (Genet->RxBufferMap[DescIndex].Mapping != NULL);
> +
> + GenetDmaUnmapRxDescriptor (Genet, DescIndex);
> +
> + Frame = GENET_RX_BUFFER (Genet, DescIndex);
> +
> + if (FrameLength > 2 + Genet->SnpMode.MediaHeaderSize) {
> + // Received frame has 2 bytes of padding at the start
> + Frame += 2;
> + FrameLength -= 2;
> +
> + if (*BufferSize < FrameLength) {
> + DEBUG ((DEBUG_ERROR,
> + "%a: Buffer size (0x%X) is too small for frame (0x%X)\n",
> + __FUNCTION__, *BufferSize, FrameLength));
> + Status = GenetDmaMapRxDescriptor (Genet, DescIndex);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "%a: Failed to remap RX descriptor!\n",
> + __FUNCTION__));
> + }
> + EfiReleaseLock (&Genet->Lock);
> + return EFI_BUFFER_TOO_SMALL;
> + }
> +
> + if (DestAddr != NULL) {
> + CopyMem (&DestAddr->Addr[0], &Frame[0], NET_ETHER_ADDR_LEN);
> + }
> + if (SrcAddr != NULL) {
> + CopyMem (&SrcAddr->Addr[0], &Frame[6], NET_ETHER_ADDR_LEN);
> + }
> + if (Protocol != NULL) {
> + *Protocol = (UINT16) ((Frame[12] << 8) | Frame[13]);
> + }
> + if (HeaderSize != NULL) {
> + *HeaderSize = Genet->SnpMode.MediaHeaderSize;
> + }
> +
> + CopyMem (Buffer, Frame, FrameLength);
> + *BufferSize = FrameLength;
> +
> + Status = EFI_SUCCESS;
> + } else {
> + DEBUG ((DEBUG_ERROR, "%a: Short packet (FrameLength 0x%X)",
> + __FUNCTION__, FrameLength));
> + Status = EFI_NOT_READY;
> + }
> +
> + Status = GenetDmaMapRxDescriptor (Genet, DescIndex);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "%a: Failed to remap RX descriptor!\n", __FUNCTION__));
> + }
> +
> + EfiReleaseLock (&Genet->Lock);
> + return Status;
> +}
> +
> +/**
> + This function converts a multicast IP address to a multicast HW MAC address
> + for all packet transactions.
> +
> + @param [in] SimpleNetwork Protocol instance pointer
> + @param [in] IPv6 Set to TRUE if the multicast IP address is IPv6 [RFC2460].
> + Set to FALSE if the multicast IP address is IPv4 [RFC 791].
> + @param [in] IP The multicast IP address that is to be converted to a
> + multicast HW MAC address.
> + @param [in] MAC The multicast HW MAC address that is to be generated from IP.
> +
> + @retval EFI_SUCCESS This operation was successful.
> + @retval EFI_NOT_STARTED The network interface was not started.
> + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
> + EFI_SIMPLE_NETWORK_PROTOCOL structure.
> + @retval EFI_DEVICE_ERROR The network inteface is not in the right (initialized) state.
> + @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +GenetSimpleNetworkMCastIPtoMAC (
> + IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
> + IN BOOLEAN IPv6,
> + IN EFI_IP_ADDRESS *IP,
> + OUT EFI_MAC_ADDRESS *MAC
> + )
> +{
> + return EFI_UNSUPPORTED;
> +}
> +
> +///
> +/// Simple Network Protocol instance
> +///
> +CONST EFI_SIMPLE_NETWORK_PROTOCOL gGenetSimpleNetworkTemplate = {
> + EFI_SIMPLE_NETWORK_PROTOCOL_REVISION, // Revision
> + GenetSimpleNetworkStart, // Start
> + GenetSimpleNetworkStop, // Stop
> + GenetSimpleNetworkInitialize, // Initialize
> + GenetSimpleNetworkReset, // Reset
> + GenetSimpleNetworkShutdown, // Shutdown
> + GenetSimpleNetworkReceiveFilters, // ReceiveFilters
> + GenetSimpleNetworkStationAddress, // StationAddress
> + GenetSimpleNetworkStatistics, // Statistics
> + GenetSimpleNetworkMCastIPtoMAC, // MCastIpToMac
> + GenetSimpleNetworkNvData, // NvData
> + GenetSimpleNetworkGetStatus, // GetStatus
> + GenetSimpleNetworkTransmit, // Transmit
> + GenetSimpleNetworkReceive, // Receive
> + NULL, // WaitForPacket
> + NULL // Mode
> +};
> --
> 2.17.1
>
>
>
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH edk2-platforms v2 5/7] Platform/RaspberryPi4: Register GENET platform device protocol
2020-05-12 7:55 ` [PATCH edk2-platforms v2 5/7] Platform/RaspberryPi4: Register GENET platform device protocol Ard Biesheuvel
@ 2020-05-12 14:34 ` Leif Lindholm
0 siblings, 0 replies; 13+ messages in thread
From: Leif Lindholm @ 2020-05-12 14:34 UTC (permalink / raw)
To: Ard Biesheuvel; +Cc: devel, philmd
On Tue, May 12, 2020 at 09:55:10 +0200, Ard Biesheuvel wrote:
> Register an event at EndOfDxe to instantiate the EFI device path protocol
> with the GENET MAC address on a new handle, and install the
> BcmGenetPlatformDeviceProtocol on that handle. This protocol is used to
> pass platform information (GENET MAC address and register base address)
> to the GENET driver, which will consume this in its implementation of the
> UEFI driver model Supported/Start/Stop methods.
>
> Co-authored-by: Samer El-Haj-Mahmoud <samer.el-haj-mahmoud@arm.com>
> Co-authored-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Co-authored-by: Andrei Warkentin <awarkentin@vmware.com>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
> ---
> Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.inf | 29 ++++--
> Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c | 108 ++++++++++++++++++--
> 2 files changed, 117 insertions(+), 20 deletions(-)
>
> diff --git a/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.inf b/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.inf
> index e47f3af69199..f20f3bcc1243 100644
> --- a/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.inf
> +++ b/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.inf
> @@ -1,6 +1,8 @@
> #/** @file
> #
> -# Copyright (c) 2019, ARM Limited. All rights reserved.
> +# Component description file for the RasbperryPi DXE platform config driver.
> +#
> +# Copyright (c) 2019 - 2020, ARM Limited. All rights reserved.
> # Copyright (c) 2018, Andrei Warkentin <andrey.warkentin@gmail.com>
> #
> # SPDX-License-Identifier: BSD-2-Clause-Patent
> @@ -21,7 +23,6 @@ [Defines]
> #
> # VALID_ARCHITECTURES = AARCH64
> #
> -
> [Sources]
> ConfigDxe.c
> ConfigDxeFormSetGuid.h
> @@ -31,31 +32,36 @@ [Sources]
> [Packages]
> ArmPkg/ArmPkg.dec
> ArmPlatformPkg/ArmPlatformPkg.dec
> - MdePkg/MdePkg.dec
> + EmbeddedPkg/EmbeddedPkg.dec
> MdeModulePkg/MdeModulePkg.dec
> + MdePkg/MdePkg.dec
> + NetworkPkg/NetworkPkg.dec
> + Platform/RaspberryPi/RaspberryPi.dec
> Silicon/Broadcom/Bcm27xx/Bcm27xx.dec
> Silicon/Broadcom/Bcm283x/Bcm283x.dec
> - Platform/RaspberryPi/RaspberryPi.dec
> - EmbeddedPkg/EmbeddedPkg.dec
> + Silicon/Broadcom/Drivers/Net/BcmNet.dec
>
> [LibraryClasses]
> + AcpiLib
> BaseLib
> DebugLib
> DxeServicesTableLib
> + GpioLib
> + HiiLib
> + NetLib
> PcdLib
> UefiBootServicesTableLib
> - UefiRuntimeServicesTableLib
> UefiDriverEntryPoint
> - HiiLib
> - GpioLib
> - AcpiLib
> + UefiRuntimeServicesTableLib
The cleanup is good, but could we separate functional and
non-functional changes into separate patches?
>
> [Guids]
> gConfigDxeFormSetGuid
> + gEfiEndOfDxeEventGroupGuid
>
> [Protocols]
> - gRaspberryPiFirmwareProtocolGuid ## CONSUMES
> - gRaspberryPiConfigAppliedProtocolGuid ## PRODUCES
> + gBcmGenetPlatformDeviceProtocolGuid ## PRODUCES
> + gRaspberryPiFirmwareProtocolGuid ## CONSUMES
> + gRaspberryPiConfigAppliedProtocolGuid ## PRODUCES
>
> [FixedPcd]
> gRaspberryPiTokenSpaceGuid.PcdCpuLowSpeedMHz
> @@ -64,6 +70,7 @@ [FixedPcd]
>
> [Pcd]
> gBcm27xxTokenSpaceGuid.PcdBcm27xxRegistersAddress
> + gBcm27xxTokenSpaceGuid.PcdBcmGenetRegistersAddress
> gBcm283xTokenSpaceGuid.PcdBcm283xRegistersAddress
> gRaspberryPiTokenSpaceGuid.PcdCpuClock
> gRaspberryPiTokenSpaceGuid.PcdCustomCpuClock
> diff --git a/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c b/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c
> index 00867879da20..47ca0a89a3d8 100644
> --- a/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c
> +++ b/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c
> @@ -1,6 +1,6 @@
> /** @file
> *
> - * Copyright (c) 2019, ARM Limited. All rights reserved.
> + * Copyright (c) 2019 - 2020, ARM Limited. All rights reserved.
> * Copyright (c) 2018 - 2019, Andrei Warkentin <andrey.warkentin@gmail.com>
> *
> * SPDX-License-Identifier: BSD-2-Clause-Patent
> @@ -8,19 +8,21 @@
> **/
>
> #include <Uefi.h>
> +#include <IndustryStandard/Bcm2711.h>
> +#include <IndustryStandard/Bcm2836.h>
> +#include <IndustryStandard/Bcm2836Gpio.h>
> +#include <IndustryStandard/RpiMbox.h>
> #include <Library/AcpiLib.h>
> -#include <Library/HiiLib.h>
> #include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> #include <Library/DxeServicesTableLib.h>
> +#include <Library/GpioLib.h>
> +#include <Library/HiiLib.h>
> #include <Library/IoLib.h>
> +#include <Library/NetLib.h>
> #include <Library/UefiBootServicesTableLib.h>
> #include <Library/UefiRuntimeServicesTableLib.h>
> -#include <Library/DevicePathLib.h>
> -#include <IndustryStandard/RpiMbox.h>
> -#include <IndustryStandard/Bcm2711.h>
> -#include <IndustryStandard/Bcm2836.h>
> -#include <IndustryStandard/Bcm2836Gpio.h>
> -#include <Library/GpioLib.h>
> +#include <Protocol/BcmGenetPlatformDevice.h>
> #include <Protocol/RpiFirmware.h>
> #include <ConfigVars.h>
> #include "ConfigDxeFormSetGuid.h"
> @@ -34,6 +36,8 @@ STATIC RASPBERRY_PI_FIRMWARE_PROTOCOL *mFwProtocol;
> STATIC UINT32 mModelFamily = 0;
> STATIC UINT32 mModelInstalledMB = 0;
>
> +STATIC EFI_MAC_ADDRESS MacAddress;
m-prefix on global variable?
/
Leif
> +
> /*
> * The GUID inside Platform/RaspberryPi/RPi3/AcpiTables/AcpiTables.inf and
> * Platform/RaspberryPi/RPi4/AcpiTables/AcpiTables.inf _must_ match below.
> @@ -47,6 +51,18 @@ typedef struct {
> EFI_DEVICE_PATH_PROTOCOL End;
> } HII_VENDOR_DEVICE_PATH;
>
> +#pragma pack (1)
> +typedef struct {
> + MAC_ADDR_DEVICE_PATH MacAddrDP;
> + EFI_DEVICE_PATH_PROTOCOL End;
> +} GENET_DEVICE_PATH;
> +
> +typedef struct {
> + GENET_DEVICE_PATH DevicePath;
> + BCM_GENET_PLATFORM_DEVICE_PROTOCOL PlatformDevice;
> +} GENET_DEVICE;
> +#pragma pack ()
> +
> STATIC HII_VENDOR_DEVICE_PATH mVendorDevicePath = {
> {
> {
> @@ -69,6 +85,65 @@ STATIC HII_VENDOR_DEVICE_PATH mVendorDevicePath = {
> }
> };
>
> +STATIC GENET_DEVICE mGenetDevice = {
> + {
> + {
> + {
> + MESSAGING_DEVICE_PATH,
> + MSG_MAC_ADDR_DP,
> + {
> + (UINT8)(sizeof (MAC_ADDR_DEVICE_PATH)),
> + (UINT8)((sizeof (MAC_ADDR_DEVICE_PATH)) >> 8)
> + }
> + },
> + {{ 0 }},
> + NET_IFTYPE_ETHERNET
> + },
> + {
> + END_DEVICE_PATH_TYPE,
> + END_ENTIRE_DEVICE_PATH_SUBTYPE,
> + {
> + sizeof (EFI_DEVICE_PATH_PROTOCOL),
> + 0
> + }
> + }
> + },
> + {
> + GENET_BASE_ADDRESS,
> + {{ 0 }}
> + }
> +};
> +
> +
> +STATIC
> +VOID
> +EFIAPI
> +RegisterDevices (
> + EFI_EVENT Event,
> + VOID *Context
> + )
> +{
> + EFI_HANDLE Handle;
> + EFI_STATUS Status;
> +
> + if (mModelFamily == 4) {
> + DEBUG ((DEBUG_INFO, "GENET: MAC address %02X:%02X:%02X:%02X:%02X:%02X\n",
> + MacAddress.Addr[0], MacAddress.Addr[1], MacAddress.Addr[2],
> + MacAddress.Addr[3], MacAddress.Addr[4], MacAddress.Addr[5]));
> +
> + CopyMem (&mGenetDevice.DevicePath.MacAddrDP.MacAddress, MacAddress.Addr,
> + NET_ETHER_ADDR_LEN);
> + CopyMem (&mGenetDevice.PlatformDevice.MacAddress, MacAddress.Addr,
> + NET_ETHER_ADDR_LEN);
> +
> + Handle = NULL;
> + Status = gBS->InstallMultipleProtocolInterfaces (&Handle,
> + &gEfiDevicePathProtocolGuid, &mGenetDevice.DevicePath,
> + &gBcmGenetPlatformDeviceProtocolGuid, &mGenetDevice.PlatformDevice,
> + NULL);
> + ASSERT_EFI_ERROR (Status);
> + }
> +}
>
> STATIC EFI_STATUS
> InstallHiiPages (
> @@ -242,6 +317,16 @@ SetupVariables (
> PcdSet32 (PcdDisplayEnableSShot, PcdGet32 (PcdDisplayEnableSShot));
> }
>
> + if (mModelFamily == 4) {
> + //
> + // Get the MAC address from the firmware.
> + //
> + Status = mFwProtocol->GetMacAddress (MacAddress.Addr);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_WARN, "%a: failed to retrieve MAC address\n", __FUNCTION__));
> + }
> + }
> +
> return EFI_SUCCESS;
> }
>
> @@ -448,7 +533,8 @@ ConfigInitialize (
> IN EFI_SYSTEM_TABLE *SystemTable
> )
> {
> - EFI_STATUS Status;
> + EFI_STATUS Status;
> + EFI_EVENT EndOfDxeEvent;
>
> Status = gBS->LocateProtocol (&gRaspberryPiFirmwareProtocolGuid,
> NULL, (VOID**)&mFwProtocol);
> @@ -494,5 +580,9 @@ ConfigInitialize (
> ASSERT_EFI_ERROR (Status);
> }
>
> + Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY, RegisterDevices,
> + NULL, &gEfiEndOfDxeEventGroupGuid, &EndOfDxeEvent);
> + ASSERT_EFI_ERROR (Status);
> +
> return EFI_SUCCESS;
> }
> --
> 2.17.1
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH edk2-platforms v2 0/7] Add Broadcom GENET driver for RPi4
2020-05-12 7:55 [PATCH edk2-platforms v2 0/7] Add Broadcom GENET driver for RPi4 Ard Biesheuvel
` (8 preceding siblings ...)
2020-05-12 14:28 ` Ard Biesheuvel
@ 2020-05-12 14:35 ` Leif Lindholm
9 siblings, 0 replies; 13+ messages in thread
From: Leif Lindholm @ 2020-05-12 14:35 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: devel, philmd, Pete Batard, Jared McNeill, Andrei Warkentin,
Samer El-Haj-Mahmoud, Jeremy Linton
On Tue, May 12, 2020 at 09:55:05 +0200, Ard Biesheuvel wrote:
> This is a followup to Samer's v1 [0], and incorporates all the delta
> changes posted for review over the past couple of days. This is a
> roundup of all that work, and therefore supersedes it.
>
> It provides an implementation of the SimpleNetworkProtocol for the
> Raspberry Pi4's GENET network controller, in a way that adheres to the
> UEFI driver model.
>
> The original submission was provided by Jared, based on Jeremy's MAC
> programming-only driver and the existing BSD driver for the GENET IP.
> Cumulative changes and fixes as well as review feedback were provided
> by all of the below.
>
> https://github.com/ardbiesheuvel/edk2-platforms/tree/rpi4_genet_combi_v2
>
> Cc: Pete Batard <pete@akeo.ie>
> Cc: Jared McNeill <jmcneill@invisible.ca>
> Cc: Andrei Warkentin <awarkentin@vmware.com>
> Cc: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>
> Cc: Jeremy Linton <jeremy.linton@arm.com>
For 1-2,4,6-7/7:
Reviewed-by: Leif Lindholm <leif@nuviainc.com>
> Andrei Warkentin (1):
> Platform/RaspberryPi4: Remove PlatformPcdLib
>
> Ard Biesheuvel (6):
> Platform/RaspberryPi4: set DMA translation for BCM Genet driver
> Silicon/Broadcom: Add BcmGenetPlatformDevice protocol
> Silicon/Broadcom/BcmGenetDxe: Add GENET driver
> Platform/RaspberryPi4: Clean up PCDs out of the GENET driver
> Platform/RaspberryPi4: Register GENET platform device protocol
> Platform/RaspberryPi4: remove ASIX 88772b driver
>
> Silicon/Broadcom/Bcm27xx/Bcm27xx.dec | 2 +
> Silicon/Broadcom/Drivers/Net/BcmNet.dec | 8 +-
> Platform/RaspberryPi/RPi4/RPi4.dsc | 8 +-
> Platform/RaspberryPi/RPi4/RPi4.fdf | 1 -
> .../RaspberryPi/AcpiTables/AcpiTables.inf | 2 +-
> .../Drivers/ConfigDxe/ConfigDxe.inf | 29 +-
> .../Library/PlatformPcdLib/PlatformPcdLib.inf | 43 -
> .../Drivers/Net/BcmGenetDxe/BcmGenetDxe.inf | 46 +-
> .../Include/IndustryStandard/Bcm2711.h | 3 +
> .../Drivers/Net/BcmGenetDxe/GenericPhy.h | 106 +++
> .../Drivers/Net/BcmGenetDxe/GenetUtil.h | 364 ++++++++
> .../Broadcom/Drivers/Net/Include/Net/Genet.h | 21 -
> .../Include/Protocol/BcmGenetPlatformDevice.h | 24 +
> .../RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c | 108 ++-
> .../Library/PlatformPcdLib/PlatformPcdLib.c | 45 -
> .../Drivers/Net/BcmGenetDxe/ComponentName.c | 198 +++++
> .../Drivers/Net/BcmGenetDxe/DriverBinding.c | 408 +++++++++
> .../Drivers/Net/BcmGenetDxe/GenericPhy.c | 405 +++++++++
> .../Broadcom/Drivers/Net/BcmGenetDxe/Genet.c | 114 ---
> .../Drivers/Net/BcmGenetDxe/GenetUtil.c | 816 +++++++++++++++++
> .../Drivers/Net/BcmGenetDxe/SimpleNetwork.c | 834 ++++++++++++++++++
> Platform/RaspberryPi/AcpiTables/Dsdt.asl | 2 +-
> 22 files changed, 3319 insertions(+), 268 deletions(-)
> delete mode 100644 Platform/RaspberryPi/Library/PlatformPcdLib/PlatformPcdLib.inf
> create mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenericPhy.h
> create mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenetUtil.h
> delete mode 100644 Silicon/Broadcom/Drivers/Net/Include/Net/Genet.h
> create mode 100644 Silicon/Broadcom/Drivers/Net/Include/Protocol/BcmGenetPlatformDevice.h
> delete mode 100644 Platform/RaspberryPi/Library/PlatformPcdLib/PlatformPcdLib.c
> create mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/ComponentName.c
> create mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/DriverBinding.c
> create mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenericPhy.c
> delete mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/Genet.c
> create mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/GenetUtil.c
> create mode 100644 Silicon/Broadcom/Drivers/Net/BcmGenetDxe/SimpleNetwork.c
>
> --
> 2.17.1
>
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2020-05-12 14:35 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-05-12 7:55 [PATCH edk2-platforms v2 0/7] Add Broadcom GENET driver for RPi4 Ard Biesheuvel
2020-05-12 7:55 ` [PATCH edk2-platforms v2 1/7] Platform/RaspberryPi4: set DMA translation for BCM Genet driver Ard Biesheuvel
2020-05-12 7:55 ` [PATCH edk2-platforms v2 2/7] Silicon/Broadcom: Add BcmGenetPlatformDevice protocol Ard Biesheuvel
2020-05-12 7:55 ` [PATCH edk2-platforms v2 3/7] Silicon/Broadcom/BcmGenetDxe: Add GENET driver Ard Biesheuvel
2020-05-12 14:31 ` [edk2-devel] " Leif Lindholm
2020-05-12 7:55 ` [PATCH edk2-platforms v2 4/7] Platform/RaspberryPi4: Clean up PCDs out of the " Ard Biesheuvel
2020-05-12 7:55 ` [PATCH edk2-platforms v2 5/7] Platform/RaspberryPi4: Register GENET platform device protocol Ard Biesheuvel
2020-05-12 14:34 ` Leif Lindholm
2020-05-12 7:55 ` [PATCH edk2-platforms v2 6/7] Platform/RaspberryPi4: Remove PlatformPcdLib Ard Biesheuvel
2020-05-12 7:55 ` [PATCH edk2-platforms v2 7/7] Platform/RaspberryPi4: remove ASIX 88772b driver Ard Biesheuvel
2020-05-12 8:26 ` [PATCH edk2-platforms v2 0/7] Add Broadcom GENET driver for RPi4 Ard Biesheuvel
2020-05-12 14:28 ` Ard Biesheuvel
2020-05-12 14:35 ` Leif Lindholm
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox