public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v4 edk2-platforms 1/1] Silicon/DesignWare/Driver: DwEmacSnpDxe: Add DesignWare EMAC driver
@ 2019-05-08  9:52 tzy.way.ooi
  2019-05-22  2:37 ` tzy.way.ooi
  0 siblings, 1 reply; 9+ messages in thread
From: tzy.way.ooi @ 2019-05-08  9:52 UTC (permalink / raw)
  To: devel
  Cc: Ooi Tzy Way, Ard BieSheuvel, Leif Lindholm, Michael D Kinney,
	Loh Tien Hock

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=utf-8, Size: 170750 bytes --]

From: Ooi Tzy Way <tzy.way.ooi@intel.com>

Add driver support for the Ethernet MAC based on Synopsys DesignWare
3504-0 Universal 10/100/1000 Ethernet MAC and KSZ9031 PHY

Cc: Ard BieSheuvel<ard.biesheuvel@linaro.org>
Cc: Leif Lindholm<leif.lindholm@linaro.org>
Cc: Michael D Kinney<michael.d.kinney@intel.com>
Cc: Loh Tien Hock<tien.hock.loh@intel.com>

Contributed-under: Tianocore Contribution Agreement 1.1
Signed-off-by: Ooi Tzy Way <tzy.way.ooi@intel.com>

---
v4:
- Describe the device with non-discoverable device protocol
- Expose the MMIO base address in the EFI ACPI address space descriptor
- Remove cache maintainence and use DmaLib for non-coherent DMA access
---
 Silicon/DesignWare/DesignWare.dec                        |   34 +
 Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.inf |   82 ++
 Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.h   |  229 ++++
 Silicon/DesignWare/Drivers/DwEmacSnpDxe/EmacDxeUtil.h    |  392 ++++++
 Silicon/DesignWare/Drivers/DwEmacSnpDxe/PhyDxeUtil.h     |  341 ++++++
 Silicon/DesignWare/Drivers/DwEmacSnpDxe/ComponentName.c  |  327 +++++
 Silicon/DesignWare/Drivers/DwEmacSnpDxe/DriverBinding.c  |  450 +++++++
 Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.c   | 1273 ++++++++++++++++++++
 Silicon/DesignWare/Drivers/DwEmacSnpDxe/EmacDxeUtil.c    |  684 +++++++++++
 Silicon/DesignWare/Drivers/DwEmacSnpDxe/PhyDxeUtil.c     |  621 ++++++++++
 10 files changed, 4433 insertions(+)

diff --git a/Silicon/DesignWare/DesignWare.dec b/Silicon/DesignWare/DesignWare.dec
new file mode 100755
index 000000000000..bad81fb6a023
--- /dev/null
+++ b/Silicon/DesignWare/DesignWare.dec
@@ -0,0 +1,34 @@
+  #Copyright (c) 2011 - 2019, Intel Corporaton. All rights reserved.
+  #This program and the accompanying materials
+  #are licensed and made available under the terms and conditions of the BSD License
+  #which accompanies this distribution.  The full text of the license may be found at
+  #http://opensource.org/licenses/bsd-license.php
+  #THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  #WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+[Defines]
+  DEC_SPECIFICATION              = 0x00010005
+  PACKAGE_NAME                   = DesignWarePkg
+  PACKAGE_GUID                   = 3b5936d8-c72d-412d-b4d9-3bf0dea73598
+  PACKAGE_VERSION                = 0.1
+
+################################################################################
+#
+# Include Section - list of Include Paths that are provided by this package.
+#                   Comments are used for Keywords and Module Types.
+#
+# Supported Module Types:
+#  BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION
+#
+################################################################################
+  
+[Guids.common]
+  gDesignWareTokenSpaceGuid = { 0x89cb1241, 0xd283, 0x4543, { 0x88, 0x9c, 0x6b, 0x62, 0x36, 0x1a, 0x95, 0x7a } }
+  gDwEmacNetNonDiscoverableDeviceGuid = { 0x401950CD, 0xF9CD, 0x4A65, { 0xAD, 0x8E, 0x84, 0x9F, 0x3B, 0xAF, 0x23, 0x04 } }
+
+
+[PcdsFixedAtBuild.common]
+  gDesignWareTokenSpaceGuid.PcdDwEmacDefaultMacAddress|0|UINT64|0x30000050
+  gDesignWareTokenSpaceGuid.PcdDwEmacDxeBaseAddress|0|UINT32|0x30000051
+  
+
diff --git a/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.inf b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.inf
new file mode 100755
index 000000000000..09e7f1e77f69
--- /dev/null
+++ b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.inf
@@ -0,0 +1,82 @@
+#/** @file
+#  DW Emac Simple Networking Protocol Driver (SNP) DXE Driver
+#
+#  Copyright (c) 2011 - 2019, Intel Corporaton. All rights reserved.
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#  The original software modules are licensed as follows:
+#
+#  Copyright (c) 2012-2014, ARM Limited. All rights reserved.
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution.  The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = DwEmacSnpDxe
+  FILE_GUID                      = 06f3315f-9fe6-4938-b83f-2c072af802ba
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 0.1
+  ENTRY_POINT                    = DwEmacSnpDxeEntry
+
+[Sources.common]
+  ComponentName.c
+  DriverBinding.c
+  DwEmacSnpDxe.c
+  EmacDxeUtil.c
+  PhyDxeUtil.c
+  DwEmacSnpDxe.h
+  EmacDxeUtil.h
+  PhyDxeUtil.h
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  NetworkPkg/NetworkPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  Silicon/DesignWare/DesignWare.dec
+
+[LibraryClasses]
+  BaseLib
+  UefiLib
+  NetLib
+  UefiDriverEntryPoint
+  BaseMemoryLib
+  ArmLib
+  IoLib
+  TimerLib
+  DevicePathLib
+  DebugLib
+  PrintLib
+  NonDiscoverableDeviceRegistrationLib
+  DmaLib
+
+[Protocols]
+  gEfiSimpleNetworkProtocolGuid
+  gEfiMetronomeArchProtocolGuid
+  gEfiPxeBaseCodeProtocolGuid
+  gEfiDevicePathProtocolGuid
+  gEfiDriverBindingProtocolGuid
+  gEdkiiNonDiscoverableDeviceProtocolGuid
+  
+[Guids]
+  gDwEmacNetNonDiscoverableDeviceGuid
+
+[Pcd]
+  gDesignWareTokenSpaceGuid.PcdDwEmacDefaultMacAddress
+  gDesignWareTokenSpaceGuid.PcdDwEmacDxeBaseAddress
+  
+[Depex]
+  TRUE
diff --git a/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.h b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.h
new file mode 100755
index 000000000000..677fdad8bd5d
--- /dev/null
+++ b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.h
@@ -0,0 +1,229 @@
+/** @file
+
+  Copyright (c) 2011 - 2019, Intel Corporaton. All rights reserved.
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+  
+  The original software modules are licensed as follows:
+
+  Copyright (c) 2012-2014, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD 3 Clause LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+
+#ifndef __DWEMAC_SNP_DXE_H__
+#define __DWEMAC_SNP_DXE_H__
+
+#include <Uefi.h>
+#include <Uefi/UefiSpec.h>
+#include <Base.h>
+
+// Protocols used by this driver
+#include <Protocol/SimpleNetwork.h>
+#include <Protocol/ComponentName2.h>
+#include <Protocol/PxeBaseCode.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/NonDiscoverableDevice.h>
+
+// Libraries used by this driver
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/NetLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/ArmLib.h>
+#include <Library/PrintLib.h>
+#include <Library/DmaLib.h>
+
+#include "PhyDxeUtil.h"
+#include "EmacDxeUtil.h"
+
+/*------------------------------------------------------------------------------
+  Information Structure
+------------------------------------------------------------------------------*/
+
+typedef struct {
+  MAC_ADDR_DEVICE_PATH      MacAddrDP;
+  EFI_DEVICE_PATH_PROTOCOL  End;
+} EFI_SIMPLE_NETWORK_DEVICE_PATH;
+
+typedef struct {
+  // Driver signature
+  UINT32            Signature;
+  EFI_HANDLE        ControllerHandle;
+
+  // EFI SNP protocol instances
+  EFI_SIMPLE_NETWORK_PROTOCOL Snp;
+  EFI_SIMPLE_NETWORK_MODE SnpMode;
+
+  // EFI Snp statistics instance
+  EFI_NETWORK_STATISTICS Stats;
+  
+  EMAC_DRIVER  MacDriver;
+  PHY_DRIVER   PhyDriver;
+  
+  NON_DISCOVERABLE_DEVICE           *Dev;
+  
+  EFI_LOCK                          Lock;
+  
+  // Array of the recycled transmit buffer address 
+  UINT64                 *RecycledTxBuf;
+  
+  // The maximum number of recycled buffer pointers in RecycledTxBuf.
+  UINT32                 MaxRecycledTxBuf;
+  
+  // Current number of recycled buffer pointers in RecycledTxBuf.
+  UINT32                 RecycledTxBufCount;
+  
+  // For DmaUnmap
+  VOID                            *MappingTxdesc;
+  VOID                            *MappingRxdesc;
+  VOID                            *MappingTxbuf;
+  VOID                            *MappingRxbuf;
+
+} EFI_SIMPLE_NETWORK_DRIVER;
+
+extern EFI_COMPONENT_NAME_PROTOCOL    gSnpComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL   gSnpComponentName2;
+
+
+#define SNP_DRIVER_SIGNATURE                    SIGNATURE_32('A', 'S', 'N', 'P')
+#define INSTANCE_FROM_SNP_THIS(a)               CR(a, EFI_SIMPLE_NETWORK_DRIVER, Snp, SNP_DRIVER_SIGNATURE)
+#define SNP_TX_BUFFER_INCREASEMENT              32
+#define SNP_MAX_TX_BUFFER_NUM                   65536
+
+/*---------------------------------------------------------------------------------------------------------------------
+
+  UEFI-Compliant functions for EFI_SIMPLE_NETWORK_PROTOCOL
+
+  Refer to the Simple Network Protocol section (21.1) in the UEFI 2.3.1 Specification for related definitions
+
+---------------------------------------------------------------------------------------------------------------------*/
+
+EFI_STATUS
+EFIAPI
+SnpStart (
+  IN        EFI_SIMPLE_NETWORK_PROTOCOL* Snp
+  );
+
+EFI_STATUS
+EFIAPI
+SnpStop (
+  IN        EFI_SIMPLE_NETWORK_PROTOCOL* Snp
+  );
+
+EFI_STATUS
+EFIAPI
+SnpInitialize (
+  IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
+  IN UINTN                       ExtraRxBufferSize OPTIONAL,
+  IN UINTN                       ExtraTxBufferSize OPTIONAL
+  );
+
+EFI_STATUS
+EFIAPI
+SnpReset (
+  IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
+  IN BOOLEAN                     ExtendedVerification
+  );
+
+EFI_STATUS
+EFIAPI
+SnpShutdown (
+  IN        EFI_SIMPLE_NETWORK_PROTOCOL* Snp
+  );
+
+EFI_STATUS
+EFIAPI
+SnpReceiveFilters (
+  IN  EFI_SIMPLE_NETWORK_PROTOCOL  *Snp,
+  IN  UINT32                       Enable,
+  IN  UINT32                       Disable,
+  IN  BOOLEAN                      ResetMCastFilter,
+  IN  UINTN                        MCastFilterCnt  OPTIONAL,
+  IN  EFI_MAC_ADDRESS              *MCastFilter  OPTIONAL
+  );
+
+EFI_STATUS
+EFIAPI
+SnpStationAddress (
+  IN        EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
+  IN        BOOLEAN                      Reset,
+  IN        EFI_MAC_ADDRESS             *NewMac
+);
+
+EFI_STATUS
+EFIAPI
+SnpStatistics (
+  IN        EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
+  IN        BOOLEAN                      Reset,
+  IN  OUT   UINTN                        *StatSize,
+      OUT   EFI_NETWORK_STATISTICS       *Statistics
+  );
+
+EFI_STATUS
+EFIAPI
+SnpMcastIptoMac (
+  IN        EFI_SIMPLE_NETWORK_PROTOCOL  *Snp,
+  IN        BOOLEAN                      IsIpv6,
+  IN        EFI_IP_ADDRESS               *Ip,
+      OUT   EFI_MAC_ADDRESS              *McastMac
+  );
+
+EFI_STATUS
+EFIAPI
+SnpNvData (
+  IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
+  IN BOOLEAN                     ReadWrite,
+  IN UINTN                       Offset,
+  IN UINTN                       BufferSize,
+  IN OUT VOID                    *Buffer
+  );
+
+EFI_STATUS
+EFIAPI
+SnpGetStatus (
+  IN  EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
+  OUT UINT32                      *IrqStat  OPTIONAL,
+  OUT VOID                        **TxBuff  OPTIONAL
+  );
+
+EFI_STATUS
+EFIAPI
+SnpTransmit (
+  IN  EFI_SIMPLE_NETWORK_PROTOCOL  *Snp,
+  IN  UINTN                        HdrSize,
+  IN  UINTN                        BuffSize,
+  IN  VOID*                        Data,
+  IN  EFI_MAC_ADDRESS              *SrcAddr  OPTIONAL,
+  IN  EFI_MAC_ADDRESS              *DstAddr  OPTIONAL,
+  IN  UINT16                       *Protocol OPTIONAL
+  );
+
+EFI_STATUS
+EFIAPI
+SnpReceive (
+  IN        EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
+      OUT   UINTN                       *HdrSize      OPTIONAL,
+  IN  OUT   UINTN                       *BuffSize,
+      OUT   VOID                        *Data,
+      OUT   EFI_MAC_ADDRESS             *SrcAddr      OPTIONAL,
+      OUT   EFI_MAC_ADDRESS             *DstAddr      OPTIONAL,
+      OUT   UINT16                      *Protocol     OPTIONAL
+  );
+
+#endif // __DWEMAC_SNP_DXE_H__
diff --git a/Silicon/DesignWare/Drivers/DwEmacSnpDxe/EmacDxeUtil.h b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/EmacDxeUtil.h
new file mode 100755
index 000000000000..872923252e73
--- /dev/null
+++ b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/EmacDxeUtil.h
@@ -0,0 +1,392 @@
+/** @file
+
+  Copyright (c) 2011 - 2019, Intel Corporaton. All rights reserved.
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+  
+  The original software modules are licensed as follows:
+
+  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+  Copyright (c) 2011 - 2014, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD 3 Clause LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+
+#ifndef __EMAC_DXE_UTIL_H__
+#define __EMAC_DXE_UTIL_H__
+
+#include <libfdt.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PrintLib.h>
+#include <Library/TimerLib.h>
+#include <Library/NetLib.h>
+#include <Library/ArmLib.h>
+
+// Protocols used by this driver
+#include <Protocol/SimpleNetwork.h>
+#include <Protocol/ComponentName2.h>
+#include <Protocol/PxeBaseCode.h>
+#include <Protocol/DevicePath.h>
+
+
+// Most common CRC32 Polynomial for little endian machines
+#define CRC_POLYNOMIAL         0xEDB88320
+#define HASH_TABLE_REG(n)      0x500 + (0x4 * n)
+#define RX_MAX_PACKET          1600
+
+#define CONFIG_ETH_BUFSIZE     2048
+#define CONFIG_TX_DESCR_NUM    10
+#define CONFIG_RX_DESCR_NUM    10
+#define TX_TOTAL_BUFSIZE       (CONFIG_ETH_BUFSIZE * CONFIG_TX_DESCR_NUM)
+#define RX_TOTAL_BUFSIZE       (CONFIG_ETH_BUFSIZE * CONFIG_RX_DESCR_NUM)
+
+// DMA status error bit
+#define RX_DMA_WRITE_DATA_TRANSFER_ERROR       0x0
+#define TX_DMA_READ_DATA_TRANSFER_ERROR        0x3
+#define RX_DMA_DESCRIPTOR_WRITE_ACCESS_ERROR   0x4
+#define TX_DMA_DESCRIPTOR_WRITE_ACCESS_ERROR   0x5
+#define RX_DMA_DESCRIPTOR_READ_ACCESS_ERROR    0x6
+#define TX_DMA_DESCRIPTOR_READ_ACCESS_ERROR    0x7
+
+// tx descriptor
+#define TDES0_OWN           BIT31
+#define TDES0_TXINT         BIT30
+#define TDES0_TXLAST        BIT29
+#define TDES0_TXFIRST       BIT28
+#define TDES0_TXCRCDIS      BIT27
+#define TDES0_TXRINGEND     BIT21
+#define TDES0_TXCHAIN       BIT20
+
+#define TDES1_SIZE1MASK     (0x1FFF << 0)
+#define TDES1_SIZE1SHFT     (0)
+#define TDES1_SIZE2MASK     (0x1FFF << 16)
+#define TDES1_SIZE2SHFT     (16)
+
+// rx descriptor
+#define RDES0_FL_MASK       0x3fff
+#define RDES0_FL_SHIFT      16
+#define RDES1_CHAINED       BIT14
+
+#define RDES0_CE            BIT1
+#define RDES0_DBE           BIT2
+#define RDES0_RE            BIT3
+#define RDES0_RWT           BIT4
+#define RDES0_LC            BIT6
+#define RDES0_GF            BIT7
+#define RDES0_OE            BIT11
+#define RDES0_LE            BIT12
+#define RDES0_SAF           BIT13
+#define RDES0_DE            BIT14
+#define RDES0_ES            BIT15
+#define RDES0_AFM           BIT30
+#define RDES0_OWN           BIT31
+
+
+// emac config phy interface setting
+#define PHY_INTERFACE_MODE_GMII      0
+#define PHY_INTERFACE_MODE_MII       1
+#define PHY_INTERFACE_MODE_RGMII     2
+#define PHY_INTERFACE_MODE_RMII      3
+
+// DW emac mask
+#define DW_EMAC_DMAGRP_BUS_MODE_SWR_SET_MSK             0x00000001
+#define DW_EMAC_DMAGRP_BUS_MODE_FB_SET_MSK              0x00010000
+#define DW_EMAC_DMAGRP_BUS_MODE_PBL_SET_MSK             0x00003f00
+#define DW_EMAC_DMAGRP_BUS_MODE_PR_SET_MSK              0x0000c000
+#define DW_EMAC_DMAGRP_OPERATION_MODE_FTF_SET_MSK       0x00100000
+#define DW_EMAC_DMAGRP_OPERATION_MODE_TSF_SET_MSK       0x00200000
+#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_TIE_SET_MSK     0x00000001
+#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_RIE_SET_MSK     0x00000040
+#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_NIE_SET_MSK     0x00010000
+#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_AIE_SET_MSK     0x00008000
+#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_FBE_SET_MSK     0x00002000
+#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_UNE_SET_MSK     0x00000020
+#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_TSE_SET_MSK     0x00000002
+#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_TUE_SET_MSK     0x00000004
+#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_TJE_SET_MSK     0x00000008
+#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_OVE_SET_MSK     0x00000010
+#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_RUE_SET_MSK     0x00000080
+#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_RSE_SET_MSK     0x00000100
+#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_RWE_SET_MSK     0x00000200
+#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_ETE_SET_MSK     0x00000400
+#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_ERE_SET_MSK     0x00004000
+#define DW_EMAC_DMAGRP_OPERATION_MODE_ST_SET_MSK        0x00002000
+#define DW_EMAC_DMAGRP_OPERATION_MODE_SR_SET_MSK        0x00000002
+#define DW_EMAC_GMACGRP_MAC_CONFIGURATION_RE_SET_MSK    0x00000004
+#define DW_EMAC_GMACGRP_MAC_CONFIGURATION_TE_SET_MSK    0x00000008
+#define DW_EMAC_GMACGRP_MAC_FRAME_FILTER_RESET          0x00000000
+#define DW_EMAC_GMACGRP_MAC_FRAME_FILTER_HMC_SET_MSK    0x00000004
+#define DW_EMAC_GMACGRP_MAC_FRAME_FILTER_DBF_SET_MSK    0x00000020
+#define DW_EMAC_GMACGRP_MAC_FRAME_FILTER_PR_SET_MSK     0x00000001
+#define DW_EMAC_GMACGRP_MAC_FRAME_FILTER_PM_SET_MSK     0x00000010
+#define DW_EMAC_DMAGRP_OPERATION_MODE_ST_CLR_MSK        0xffffdfff
+#define DW_EMAC_GMACGRP_MAC_CONFIGURATION_RE_CLR_MSK    0xfffffffb
+#define DW_EMAC_GMACGRP_MAC_CONFIGURATION_TE_CLR_MSK    0xfffffff7
+#define DW_EMAC_DMAGRP_OPERATION_MODE_SR_CLR_MSK        0xfffffffd
+#define DW_EMAC_DMAGRP_STATUS_NIS_SET_MSK               0x00010000
+#define DW_EMAC_DMAGRP_STATUS_RI_SET_MSK                0x00000040
+#define DW_EMAC_DMAGRP_STATUS_TI_SET_MSK                0x00000001
+#define DW_EMAC_DMAGRP_STATUS_TU_SET_MSK                0x00000004
+#define DW_EMAC_DMAGRP_STATUS_ERI_SET_MSK               0x00004000
+#define DW_EMAC_DMAGRP_STATUS_AIS_SET_MSK               0x00008000
+#define DW_EMAC_DMAGRP_STATUS_TPS_SET_MSK               0x00000002
+#define DW_EMAC_DMAGRP_STATUS_TJT_SET_MSK               0x00000008
+#define DW_EMAC_DMAGRP_STATUS_OVF_SET_MSK               0x00000010
+#define DW_EMAC_DMAGRP_STATUS_UNF_SET_MSK               0x00000020
+#define DW_EMAC_DMAGRP_STATUS_RU_SET_MSK                0x00000080
+#define DW_EMAC_DMAGRP_STATUS_RPS_SET_MSK               0x00000100
+#define DW_EMAC_DMAGRP_STATUS_RWT_SET_MSK               0x00000200
+#define DW_EMAC_DMAGRP_STATUS_ETI_SET_MSK               0x00000400
+#define DW_EMAC_DMAGRP_STATUS_FBI_SET_MSK               0x00002000
+#define DW_EMAC_GMACGRP_MAC_CONFIGURATION_PS_SET_MSK    0x00008000
+#define DW_EMAC_GMACGRP_MAC_CONFIGURATION_FES_SET_MSK   0x00004000
+#define DW_EMAC_GMACGRP_MAC_CONFIGURATION_DM_SET_MSK    0x00000800
+#define DW_EMAC_GMACGRP_MAC_CONFIGURATION_BE_SET_MSK    0x00200000
+#define DW_EMAC_GMACGRP_MAC_CONFIGURATION_DO_SET_MSK    0x00002000
+
+#define DW_EMAC_DMAGRP_BUS_MODE_SWR_GET(value) (((value) & 0x00000001) >> 0)
+#define DW_EMAC_DMAGRP_STATUS_EB_GET(value) (((value) & 0x03800000) >> 23)
+#define DW_EMAC_GMACGRP_GMII_ADDRESS_GB_GET(value) (((value) & 0x00000001) >> 0)
+#define DW_EMAC_GMACGRP_GMII_DATA_GD_GET(value) (((value) & 0x0000ffff) >> 0)
+#define DW_EMAC_DMAGRP_OPERATION_MODE_FTF_GET(value) (((value) & 0x00100000) >> 20)
+
+// DW emac registers offset
+//#define DWEMAC_OFST														((UINT32)PcdGet32 (PcdDwEmacDxeBaseAddress))
+#define DW_EMAC_GMACGRP_MAC_CONFIGURATION_OFST             				0x000
+#define DW_EMAC_GMACGRP_MAC_FRAME_FILTER_OFST              				0x004
+#define DW_EMAC_GMACGRP_GMII_ADDRESS_OFST                  				0x010
+#define DW_EMAC_GMACGRP_GMII_DATA_OFST                     				0x014
+#define DW_EMAC_GMACGRP_FLOW_CONTROL_OFST                  				0x018
+#define DW_EMAC_GMACGRP_VLAN_TAG_OFST                      				0x01c
+#define DW_EMAC_GMACGRP_VERSION_OFST                       				0x020
+#define DW_EMAC_GMACGRP_DEBUG_OFST                         				0x024
+#define DW_EMAC_GMACGRP_LPI_CONTROL_STATUS_OFST            				0x030
+#define DW_EMAC_GMACGRP_LPI_TIMERS_CONTROL_OFST            				0x034
+#define DW_EMAC_GMACGRP_INTERRUPT_STATUS_OFST              				0x038
+#define DW_EMAC_GMACGRP_INTERRUPT_MASK_OFST                				0x03c
+#define DW_EMAC_GMACGRP_MAC_ADDRESS0_HIGH_OFST             				0x040
+#define DW_EMAC_GMACGRP_MAC_ADDRESS0_LOW_OFST              				0x044
+#define DW_EMAC_GMACGRP_MAC_ADDRESS1_HIGH_OFST             				0x048
+#define DW_EMAC_GMACGRP_MAC_ADDRESS1_LOW_OFST              				0x04c
+#define DW_EMAC_GMACGRP_MAC_ADDRESS2_HIGH_OFST             				0x050
+#define DW_EMAC_GMACGRP_MAC_ADDRESS2_LOW_OFST              				0x054
+#define DW_EMAC_GMACGRP_MAC_ADDRESS3_HIGH_OFST             				0x058
+#define DW_EMAC_GMACGRP_MAC_ADDRESS3_LOW_OFST              				0x05c
+#define DW_EMAC_GMACGRP_MAC_ADDRESS4_HIGH_OFST             				0x060
+#define DW_EMAC_GMACGRP_MAC_ADDRESS4_LOW_OFST              				0x064
+#define DW_EMAC_GMACGRP_MAC_ADDRESS5_HIGH_OFST            				0x068
+#define DW_EMAC_GMACGRP_MAC_ADDRESS5_LOW_OFST             				0x06c
+#define DW_EMAC_GMACGRP_MAC_ADDRESS6_HIGH_OFST            				0x070
+#define DW_EMAC_GMACGRP_MAC_ADDRESS6_LOW_OFST             				0x074
+#define DW_EMAC_GMACGRP_MAC_ADDRESS7_HIGH_OFST            				0x078
+#define DW_EMAC_GMACGRP_MAC_ADDRESS7_LOW_OFST             				0x07c
+#define DW_EMAC_GMACGRP_MAC_ADDRESS8_HIGH_OFST            				0x080
+#define DW_EMAC_GMACGRP_MAC_ADDRESS8_LOW_OFST             				0x084
+#define DW_EMAC_GMACGRP_MAC_ADDRESS9_HIGH_OFST            				0x088
+#define DW_EMAC_GMACGRP_MAC_ADDRESS9_LOW_OFST             				0x08c
+#define DW_EMAC_GMACGRP_MAC_ADDRESS10_HIGH_OFST           				0x090
+#define DW_EMAC_GMACGRP_MAC_ADDRESS10_LOW_OFST            				0x094
+#define DW_EMAC_GMACGRP_MAC_ADDRESS11_HIGH_OFST           				0x098
+#define DW_EMAC_GMACGRP_MAC_ADDRESS11_LOW_OFST            				0x09c
+#define DW_EMAC_GMACGRP_MAC_ADDRESS12_HIGH_OFST           				0x0a0
+#define DW_EMAC_GMACGRP_MAC_ADDRESS12_LOW_OFST            				0x0a4
+#define DW_EMAC_GMACGRP_MAC_ADDRESS13_HIGH_OFST           				0x0a8
+#define DW_EMAC_GMACGRP_MAC_ADDRESS13_LOW_OFST            				0x0ac
+#define DW_EMAC_GMACGRP_MAC_ADDRESS14_HIGH_OFST           				0x0b0
+#define DW_EMAC_GMACGRP_MAC_ADDRESS14_LOW_OFST            				0x0b4
+#define DW_EMAC_GMACGRP_MAC_ADDRESS15_HIGH_OFST           				0x0b8
+#define DW_EMAC_GMACGRP_MAC_ADDRESS15_LOW_OFST            				0x0bc
+#define DW_EMAC_GMACGRP_SGMII_RGMII_SMII_CONTROL_STATUS_OFST        	0x0d8
+#define DW_EMAC_GMACGRP_WDOG_TIMEOUT_OFST                 				0x0dc
+#define DW_EMAC_GMACGRP_GENPIO_OFST                       				0x0e0
+#define DW_EMAC_GMACGRP_MMC_CONTROL_OFST                  				0X100
+#define DW_EMAC_GMACGRP_MMC_RECEIVE_INTERRUPT_OFST        				0x104
+#define DW_EMAC_GMACGRP_MMC_TRANSMIT_INTERRUPT_OFST       				0x108
+#define DW_EMAC_GMACGRP_MMC_RECEIVE_INTERRUPT_MASK_OFST   				0x10c
+#define DW_EMAC_GMACGRP_MMC_TRANSMIT_INTERRUPT_MASK_OFST  				0x110
+#define DW_EMAC_GMACGRP_TXOCTETCOUNT_GB_OFST        					0x114
+#define DW_EMAC_GMACGRP_TXFRAMECOUNT_GB_OFST        					0x118
+#define DW_EMAC_GMACGRP_TXBROADCASTFRAMES_G_OFST        				0x11c
+#define DW_EMAC_GMACGRP_TXMULTICASTFRAMES_G_OFST        				0x120
+#define DW_EMAC_GMACGRP_TXUNICASTFRAMES_GB_OFST        					0x13c
+#define DW_EMAC_GMACGRP_TXLATECOL_OFST        							0x158
+#define DW_EMAC_GMACGRP_TXEXESSCOL_OFST        							0x15c
+#define DW_EMAC_GMACGRP_TXFRAMECOUNT_G_OFST        						0x168
+#define DW_EMAC_GMACGRP_TXOVERSIZE_G_OFST        						0x178
+#define DW_EMAC_GMACGRP_RXFRAMECOUNT_GB_OFST        					0x180
+#define DW_EMAC_GMACGRP_RXOCTETCOUNT_GB_OFST        					0x184
+#define DW_EMAC_GMACGRP_RXBROADCASTFRAMES_G_OFST        				0x18c
+#define DW_EMAC_GMACGRP_RXMULTICASTFRAMES_G_OFST        				0x190
+#define DW_EMAC_GMACGRP_RXCRCERROR_OFST        							0x194
+#define DW_EMAC_GMACGRP_RXUNDERSIZE_G_OFST        						0x1a4
+#define DW_EMAC_GMACGRP_RXOVERSIZE_G_OFST        						0x1a8
+#define DW_EMAC_GMACGRP_RXUNICASTFRAMES_G_OFST        					0x1c4
+#define DW_EMAC_DMAGRP_BUS_MODE_OFST                      				0x1000
+#define DW_EMAC_DMAGRP_TRANSMIT_POLL_DEMAND_OFST          				0x1004
+#define DW_EMAC_DMAGRP_RECEIVE_POLL_DEMAND_OFST           				0x1008
+#define DW_EMAC_DMAGRP_RECEIVE_DESCRIPTOR_LIST_ADDRESS_OFST             0x100c
+#define DW_EMAC_DMAGRP_TRANSMIT_DESCRIPTOR_LIST_ADDRESS_OFST            0x1010
+#define DW_EMAC_DMAGRP_STATUS_OFST                                      0x1014
+#define DW_EMAC_DMAGRP_OPERATION_MODE_OFST                              0x1018
+#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_OFST                            0x101c
+#define DW_EMAC_DMAGRP_MISSED_FRAME_AND_BUFFER_OVERFLOW_COUNTER_OFST    0x1020
+#define DW_EMAC_DMAGRP_RECEIVE_INTERRUPT_WATCHDOG_TIMER_OFST            0x1024
+#define DW_EMAC_DMAGRP_AXI_BUS_MODE_OFST                                0x1028
+#define DW_EMAC_DMAGRP_AHB_OR_AXI_STATUS_OFST                           0x102c
+#define DW_EMAC_DMAGRP_CURRENT_HOST_TRANSMIT_DESCRIPTOR_OFST       	 	0x1048
+#define DW_EMAC_DMAGRP_CURRENT_HOST_RECEIVE_DESCRIPTOR_OFST        	 	0x104c
+#define DW_EMAC_DMAGRP_CURRENT_HOST_TRANSMIT_BUFFER_ADDRESS_OFST   	 	0x1050
+#define DW_EMAC_DMAGRP_CURRENT_HOST_RECEIVE_BUFFER_ADDRESS_OFST    	 	0x1054
+#define DW_EMAC_DMAGRP_HW_FEATURE_OFST                             	 	0x1058
+
+typedef struct {
+  UINT32 Tdes0;
+  UINT32 Tdes1;
+  UINT32 Addr;
+  UINT32 AddrNext;
+} DESIGNWARE_HW_DESCRIPTOR;
+
+
+typedef struct {
+  DESIGNWARE_HW_DESCRIPTOR  *TxdescRing[CONFIG_TX_DESCR_NUM];
+  DESIGNWARE_HW_DESCRIPTOR  *RxdescRing[CONFIG_RX_DESCR_NUM];
+  CHAR8                     *TxBuffer[TX_TOTAL_BUFSIZE];
+  CHAR8                     *RxBuffer[RX_TOTAL_BUFSIZE];
+  EFI_PHYSICAL_ADDRESS      TxdescRingMap[CONFIG_TX_DESCR_NUM];
+  EFI_PHYSICAL_ADDRESS      RxdescRingMap[CONFIG_RX_DESCR_NUM];
+  EFI_PHYSICAL_ADDRESS      TxBufferMap[TX_TOTAL_BUFSIZE];
+  EFI_PHYSICAL_ADDRESS      RxBufferMap[RX_TOTAL_BUFSIZE];
+  UINT32                   TxCurrentDescriptorNum;
+  UINT32                   TxNextDescriptorNum;
+  UINT32                   RxCurrentDescriptorNum;
+  UINT32                   RxNextDescriptorNum;
+} EMAC_DRIVER;
+
+VOID
+EFIAPI
+EmacChooseInterface (
+  IN UINT32 MacInterface
+  );
+
+VOID
+EFIAPI
+EmacSetMacAddress (
+  IN EFI_MAC_ADDRESS  *MacAddress,
+  IN UINT32           MacBaseAddress
+  );
+
+VOID
+EFIAPI
+EmacReadMacAddress (
+  OUT EFI_MAC_ADDRESS *MacAddress,
+  IN UINT32           MacBaseAddress
+  );
+
+EFI_STATUS
+EFIAPI
+EmacDxeInitialization (
+  IN EMAC_DRIVER *EmacDriver,
+  IN UINT32      MacBaseAddress
+  );
+
+EFI_STATUS
+EFIAPI
+EmacDmaInit (
+  IN EMAC_DRIVER *EmacDriver,
+  IN UINT32      MacBaseAddress
+  );
+
+EFI_STATUS
+EFIAPI
+EmacSetupTxdesc (
+  IN EMAC_DRIVER *EmacDriver,
+  IN UINT32      MacBaseAddress
+ );
+
+EFI_STATUS
+EFIAPI
+EmacSetupRxdesc (
+  IN EMAC_DRIVER *EmacDriver,
+  IN UINT32      MacBaseAddress
+  );
+
+VOID
+EFIAPI
+EmacStartTransmission (
+  IN UINT32           MacBaseAddress
+  );
+
+EFI_STATUS
+EFIAPI
+EmacRxFilters (
+  IN        UINT32           ReceiveFilterSetting,
+  IN        BOOLEAN          Reset,
+  IN        UINTN            NumMfilter             OPTIONAL,
+  IN        EFI_MAC_ADDRESS *Mfilter                OPTIONAL,
+  IN        UINT32           MacBaseAddress
+  );
+
+UINT32
+EFIAPI
+GenEtherCrc32 (
+  IN    EFI_MAC_ADDRESS *Mac,
+  IN    UINT32 AddrLen
+  );
+
+UINT8
+EFIAPI
+BitReverse (
+  UINT8 X
+  );
+
+VOID
+EFIAPI
+EmacStopTxRx (
+  IN          UINT32        MacBaseAddress
+  );
+
+EFI_STATUS
+EFIAPI
+EmacDmaStart (
+  IN          UINT32        MacBaseAddress
+  );
+
+VOID
+EFIAPI
+EmacGetDmaStatus (
+  OUT   UINT32 *IrqStat  OPTIONAL,
+  IN    UINT32           MacBaseAddress
+  );
+
+VOID
+EFIAPI
+EmacGetStatistic (
+  IN EFI_NETWORK_STATISTICS* Stats,
+  IN UINT32                  MacBaseAddress
+  );
+
+VOID
+EFIAPI
+EmacConfigAdjust (
+  IN UINT32 Speed,
+  IN UINT32 Duplex,
+  IN UINT32 MacBaseAddress
+  );
+
+#endif // __EMAC_DXE_UTIL_H__
diff --git a/Silicon/DesignWare/Drivers/DwEmacSnpDxe/PhyDxeUtil.h b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/PhyDxeUtil.h
new file mode 100755
index 000000000000..6fff3d61688a
--- /dev/null
+++ b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/PhyDxeUtil.h
@@ -0,0 +1,341 @@
+/** @file
+
+  Copyright (c) 2011 - 2019, Intel Corporaton. All rights reserved.
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+  
+  The original software modules are licensed as follows:
+
+  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+  Copyright (c) 2011 - 2014, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD 3 Clause LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+
+#ifndef __PHY_DXE_H__
+#define __PHY_DXE_H__
+
+#include <libfdt.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PrintLib.h>
+#include <Library/TimerLib.h>
+
+typedef struct {
+  UINT32 PhyAddr;
+  UINT32 PhyCurrentLink;
+  UINT32 PhyOldLink;
+} PHY_DRIVER;
+
+
+//
+// PHY Registers
+//
+#define PHY_BASIC_CTRL                     0
+#define PHY_BASIC_STATUS                   1
+#define PHY_ID1                            2
+#define PHY_ID2                            3
+#define PHY_AUTO_NEG_ADVERT                4
+#define PHY_AUTO_NEG_LINK_ABILITY          5
+#define PHY_AUTO_NEG_EXP                   6
+#define PHY_1000BASE_T_CONTROL	           9
+#define PHY_1000BASE_T_STATUS	           10
+#define PHY_MODE                           17
+#define PHY_SPECIAL_MODES                  18
+#define PHY_SPECIAL_CTLR                   27
+#define PHY_INT_SRC                        29
+#define PHY_INT_MASK                       30
+#define PHY_SPECIAL_PHY_CTLR               31
+
+// PHY control register bits
+#define PHYCTRL_COLL_TEST                       BIT7                  // Collision test enable
+#define PHYCTRL_DUPLEX_MODE                     BIT8                  // Set Duplex Mode
+#define PHYCTRL_RST_AUTO                        BIT9                  // Restart Auto-Negotiation of Link abilities
+#define PHYCTRL_PD                              BIT11                 // Power-Down switch
+#define PHYCTRL_AUTO_EN                         BIT12                 // Auto-Negotiation Enable
+#define PHYCTRL_SPEED_SEL                       BIT13                 // Link Speed Selection
+#define PHYCTRL_LOOPBK                          BIT14                 // Set loopback mode
+#define PHYCTRL_RESET                           BIT15                 // Do a PHY reset
+
+// PHY status register bits
+#define PHYSTS_EXT_CAP                        BIT0                  // Extended Capabilities Register capability
+#define PHYSTS_JABBER                         BIT1                  // Jabber condition detected
+#define PHYSTS_LINK_STS                       BIT2                  // Link Status
+#define PHYSTS_AUTO_CAP                       BIT3                  // Auto-Negotiation Capability
+#define PHYSTS_REMOTE_FAULT                   BIT4                  // Remote fault detected
+#define PHYSTS_AUTO_COMP                      BIT5                  // Auto-Negotiation Completed
+#define PHYSTS_10BASET_HDPLX                  BIT11                 // 10Mbps Half-Duplex ability
+#define PHYSTS_10BASET_FDPLX                  BIT12                 // 10Mbps Full-Duplex ability
+#define PHYSTS_100BASETX_HDPLX                BIT13                 // 100Mbps Half-Duplex ability
+#define PHYSTS_100BASETX_FDPLX                BIT14                 // 100Mbps Full-Duplex ability
+#define PHYSTS_100BASE_T4                     BIT15                 // Base T4 ability
+
+// PHY Auto-Negotiation advertisement
+#define PHYANA_SEL_MASK                       ((UINT32)0x1F)        // Link type selector
+#define PHYANA_10BASET                        BIT5                  // Advertise 10BASET capability
+#define PHYANA_10BASETFD                      BIT6                  // Advertise 10BASET Full duplex capability
+#define PHYANA_100BASETX                      BIT7                  // Advertise 100BASETX capability
+#define PHYANA_100BASETXFD                    BIT8                  // Advertise 100 BASETX Full duplex capability
+#define PHYANA_PAUSE_OP_MASK                  (3 << 10)             // Advertise PAUSE frame capability
+#define PHYANA_REMOTE_FAULT                   BIT13                 // Remote fault detected
+
+#define PHYLPA_SLCT		                      0x001f	// Same as advertise selector
+#define PHYLPA_10HALF		                  0x0020	// Can do 10mbps half-duplex
+#define PHYLPA_1000XFULL		              0x0020	// Can do 1000BASE-X full-duplex
+#define PHYLPA_10FULL		                  0x0040	// Can do 10mbps full-duplex
+#define PHYLPA_1000XHALF		              0x0040	// Can do 1000BASE-X half-duplex
+#define PHYLPA_100HALF		                  0x0080	// Can do 100mbps half-duplex
+#define PHYLPA_1000XPAUSE		              0x0080	// Can do 1000BASE-X pause
+#define PHYLPA_100FULL		                  0x0100	// Can do 100mbps full-duplex
+#define PHYLPA_1000XPAUSE_ASYM	              0x0100	// Can do 1000BASE-X pause asym
+#define PHYLPA_100BASE4		                  0x0200	// Can do 100mbps 4k packets
+#define PHYLPA_PAUSE_CAP		              0x0400	// Can pause
+#define PHYLPA_PAUSE_ASYM		              0x0800	// Can pause asymetrically
+#define PHYLPA_RESV		                      0x1000	// Unused
+#define PHYLPA_RFAULT		                  0x2000	// Link partner faulted
+#define PHYLPA_LPACK		                  0x4000	// Link partner acked us
+#define PHYLPA_NPAGE		                  0x8000	// Next page bit
+
+#define PHYLPA_DUPLEX		                 (LPA_10FULL | LPA_100FULL)
+#define PHYLPA_100			                 (LPA_100FULL | LPA_100HALF | LPA_100BASE4)
+
+// 1000BASE-T Status register
+#define PHYLPA_1000FULL		                  0x0800	/* Link partner 1000BASE-T full duplex */
+#define PHYLPA_1000HALF		                  0x0400	/* Link partner 1000BASE-T half duplex */
+
+// 1000BASE-T Control register
+#define PHYADVERTISE_1000FULL	              0x0200  /* Advertise 1000BASE-T full duplex */
+#define PHYADVERTISE_1000HALF	              0x0100  /* Advertise 1000BASE-T half duplex */
+
+#define SPEED_1000                            1000
+#define SPEED_100                             100
+#define SPEED_10                              10
+
+#define DUPLEX_FULL                           1
+#define DUPLEX_HALF                           0
+
+// PHY Super Special control/status
+#define PHYSSCS_HCDSPEED_MASK                (7 << 2)              // Speed indication
+#define PHYSSCS_AUTODONE                      BIT12                 // Auto-Negotiation Done
+
+// Flags for PHY reset
+#define PHY_RESET_PMT                         BIT0
+#define PHY_RESET_BCR                         BIT1
+#define PHY_RESET_CHECK_LINK                  BIT2
+
+// Flags for auto negotiation
+#define AUTO_NEGOTIATE_COLLISION_TEST         BIT0
+#define AUTO_NEGOTIATE_ADVERTISE_ALL          BIT1
+
+
+// Micrel KSZ9031 Extended registers
+#define PHY_KSZ9031RN_CONTROL_PAD_SKEW_REG	      4
+#define PHY_KSZ9031RN_RX_DATA_PAD_SKEW_REG	      5
+#define PHY_KSZ9031RN_TX_DATA_PAD_SKEW_REG	      6
+#define PHY_KSZ9031RN_CLK_PAD_SKEW_REG	          8
+
+// Data operations
+#define PHY_KSZ9031_MOD_DATA_NO_POST_INC	 0x1
+#define PHY_KSZ9031_MOD_DATA_POST_INC_RW	 0x2
+#define PHY_KSZ9031_MOD_DATA_POST_INC_W		 0x3
+
+#define PHY_KSZ9031RN_MMD_CTRL_REG	         0x0d
+#define PHY_KSZ9031RN_MMD_REGDATA_REG	     0x0e
+
+#define PHY_KSZ9031RN_CLK_SKEW_CLR_MASK                    0x3FF
+#define PHY_KSZ9031RN_CONTROL_SKEW_CLR_MASK                0xFF
+#define PHY_KSZ9031RN_RX_DATA_SKEW_CLR_MASK                0xFF
+#define PHY_KSZ9031RN_TX_DATA_SKEW_CLR_MASK                0xFF
+
+#define PHY_KSZ9031RN_CLK_PAD_SKEW_VALUE	          0x3FC
+#define PHY_KSZ9031RN_CONTROL_PAD_SKEW_VALUE	      0x70
+#define PHY_KSZ9031RN_RX_DATA_PAD_SKEW_VALUE	      0x7777
+#define PHY_KSZ9031RN_TX_DATA_PAD_SKEW_VALUE	      0x0
+
+
+#define PHY_KSZ9031RN_DEV_ADDR                  0x2
+
+// MMD Address 0h, Auto-Negotiation FLP burst transmit timing
+#define PHY_KSZ9031RN_MMD_DEV_ADDR_00       0x00
+#define PHY_KSZ9031RN_MMD_D0_FLP_LO_REG     3
+#define PHY_KSZ9031RN_MMD_D0_FLP_16MS_LO    0x1A80
+#define PHY_KSZ9031RN_MMD_D0_FLP_HI_REG     4
+#define PHY_KSZ9031RN_MMD_D0_FLP_16MS_HI    0x0006
+
+// HPS MII
+#define MII_BUSY		                    (1 << 0)
+#define MII_WRITE		                    (1 << 1)
+#define MII_CLKRANGE_60_100M	            (0x0)
+#define MII_CLKRANGE_100_150M	            (0x4)
+#define MII_CLKRANGE_20_35M	                (0x8)
+#define MII_CLKRANGE_35_60M	                (0xC)
+#define MII_CLKRANGE_150_250M	            (0x10)
+#define MII_CLKRANGE_250_300M	            (0x14)
+
+#define MIIADDRSHIFT		                (11)
+#define MIIREGSHIFT		                    (6)
+#define MII_REGMSK		                    (0x1F << 6)
+#define MII_ADDRMSK		                    (0x1F << 11)
+
+// Others
+#define PHY_INVALID_ID                      0xFFFF
+#define LINK_UP				                1
+#define LINK_DOWN                           0
+#define PHY_TIMEOUT                         200000
+
+
+EFI_STATUS
+EFIAPI
+PhyDxeInitialization (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      MacBaseAddress
+  );
+
+EFI_STATUS
+EFIAPI
+PhyDetectDevice (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      MacBaseAddress
+  );
+
+EFI_STATUS
+EFIAPI
+PhyConfig (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      MacBaseAddress
+  );
+
+EFI_STATUS
+EFIAPI
+PhySoftReset (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      MacBaseAddress
+  );
+
+EFI_STATUS
+EFIAPI
+PhyReadId (
+  IN UINT32  PhyAddr,
+  IN UINT32      MacBaseAddress
+  );
+
+VOID
+EFIAPI
+PhyConfigSkew (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      MacBaseAddress
+  );
+
+VOID
+EFIAPI
+PhyDisplayConfigSkew (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      MacBaseAddress
+  );
+
+VOID
+EFIAPI
+PhyConfigFlpBurstTiming (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      MacBaseAddress
+  );
+
+VOID
+EFIAPI
+PhyDisplayFlpBurstTiming (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      MacBaseAddress
+  );
+
+EFI_STATUS
+EFIAPI
+PhyAutoNego (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      MacBaseAddress
+  );
+
+EFI_STATUS
+EFIAPI
+PhyLinkAdjustEmacConfig (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      MacBaseAddress
+  );
+
+EFI_STATUS
+EFIAPI
+PhyCheckLinkStatus (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      MacBaseAddress
+  );
+
+EFI_STATUS
+EFIAPI
+PhyReadCapability (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32* Speed,
+  IN UINT32* Duplex,
+  IN UINT32      MacBaseAddress
+  );
+
+VOID
+EFIAPI
+PhyDisplayAbility (
+  IN UINT32 Speed,
+  IN UINT32 Duplex
+  );
+
+EFI_STATUS
+EFIAPI
+PhyRead (
+  IN  UINT32  Addr,
+  IN  UINT32  Reg,
+  OUT UINT32 *Data,
+  IN UINT32      MacBaseAddress
+  );
+
+EFI_STATUS
+EFIAPI
+PhyWrite (
+  IN UINT32 Addr,
+  IN UINT32 Reg,
+  IN UINT32 Data,
+  IN UINT32      MacBaseAddress
+  );
+
+EFI_STATUS
+EFIAPI
+Phy9031ExtendedWrite (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32 Mode,
+  IN UINT32 DevAddr,
+  IN UINT32 Regnum,
+  IN UINT16 Val,
+  IN UINT32      MacBaseAddress
+  );
+
+UINT32
+EFIAPI
+Phy9031ExtendedRead (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32 Mode,
+  IN UINT32 DevAddr,
+  IN UINT32 Regnum,
+  IN UINT32      MacBaseAddress
+  );
+
+
+#endif /* __PHY_DXE_H__ */
diff --git a/Silicon/DesignWare/Drivers/DwEmacSnpDxe/ComponentName.c b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/ComponentName.c
new file mode 100755
index 000000000000..08e91fae396e
--- /dev/null
+++ b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/ComponentName.c
@@ -0,0 +1,327 @@
+/** @file
+Copyright (c) 2011 - 2019, Intel Corporaton. All rights reserved.
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+  
+  The original software modules are licensed as follows:
+
+  Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+  ComponentName.c
+
+Abstract:
+
+
+**/
+
+#include "DwEmacSnpDxe.h"
+
+//
+// EFI Component Name Functions
+//
+/**
+  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.
+
+**/
+EFI_STATUS
+EFIAPI
+SnpGetDriverName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  );
+
+
+/**
+  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 not a valid EFI_HANDLE.
+
+  @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.
+
+**/
+EFI_STATUS
+EFIAPI
+SnpGetControllerName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,
+  IN  EFI_HANDLE                                      ControllerHandle,
+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,
+  IN  CHAR8                                           *Language,
+  OUT CHAR16                                          **ControllerName
+  );
+
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  gSnpComponentName = {
+  SnpGetDriverName,
+  SnpGetControllerName,
+  "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gSnpComponentName2 = {
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) SnpGetDriverName,
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) SnpGetControllerName,
+  "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSnpNameTable[] = {
+  {
+    "eng;en",
+    L"SNP DesignWare EMAC Driver"
+  },
+  {
+    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.
+
+**/
+EFI_STATUS
+EFIAPI
+SnpGetDriverName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  )
+{
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mSnpNameTable,
+           DriverName,
+           (BOOLEAN)(This == &gSnpComponentName)
+           );
+}
+
+/**
+  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 not a valid EFI_HANDLE.
+
+  @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.
+
+**/
+EFI_STATUS
+EFIAPI
+SnpGetControllerName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,
+  IN  EFI_HANDLE                                      ControllerHandle,
+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,
+  IN  CHAR8                                           *Language,
+  OUT CHAR16                                          **ControllerName
+  )
+{
+  return EFI_UNSUPPORTED;
+}
diff --git a/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DriverBinding.c b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DriverBinding.c
new file mode 100755
index 000000000000..2b750c03d432
--- /dev/null
+++ b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DriverBinding.c
@@ -0,0 +1,450 @@
+/** @file
+
+  Copyright (c) 2011 - 2019, Intel Corporaton. All rights reserved.
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ **/
+
+#include "DwEmacSnpDxe.h"
+
+STATIC
+EFI_STATUS
+EFIAPI
+DriverSupported (
+  IN  EFI_DRIVER_BINDING_PROTOCOL *This,
+  IN  EFI_HANDLE                  Controller,
+  IN  EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
+  );
+
+STATIC
+EFI_STATUS
+EFIAPI
+DriverStart (
+  IN  EFI_DRIVER_BINDING_PROTOCOL *This,
+  IN  EFI_HANDLE                  Controller,
+  IN  EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
+  );
+
+STATIC
+EFI_STATUS
+EFIAPI
+DriverStop (
+  IN  EFI_DRIVER_BINDING_PROTOCOL *This,
+  IN  EFI_HANDLE                  Controller,
+  IN  UINTN                       NumberOfChildren,
+  IN  EFI_HANDLE                  *ChildHandleBuffer
+  );
+
+STATIC EFI_DRIVER_BINDING_PROTOCOL mDriverBinding = {
+  DriverSupported,
+  DriverStart,
+  DriverStop,
+  0xa,
+  NULL,
+  NULL
+};
+
+EFI_SIMPLE_NETWORK_DEVICE_PATH PathTemplate =  {
+  {
+    {
+      MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP,
+      { (UINT8) (sizeof(MAC_ADDR_DEVICE_PATH)), (UINT8) ((sizeof(MAC_ADDR_DEVICE_PATH)) >> 8) }
+    },
+    { { 0 } },
+    0
+  },
+  {
+    END_DEVICE_PATH_TYPE,
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,
+    { sizeof(EFI_DEVICE_PATH_PROTOCOL), 0 }
+  }
+};
+
+STATIC EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR mDwEmacNetDesc[] = {
+ {
+    ACPI_ADDRESS_SPACE_DESCRIPTOR,                    // Desc
+    sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3,   // Len
+    ACPI_ADDRESS_SPACE_TYPE_MEM,                      // ResType
+    0,                                                // GenFlag
+    0,                                                // SpecificFlag
+    32,                                               // AddrSpaceGranularity
+    FixedPcdGet32 (PcdDwEmacDxeBaseAddress),          // AddrRangeMin
+    FixedPcdGet32 (PcdDwEmacDxeBaseAddress) +
+	SIZE_4KB - 1,                                     // AddrRangeMax
+    0,                                                // AddrTranslationOffset
+    SIZE_4KB,                                         // AddrLen
+  }, {
+    ACPI_ADDRESS_SPACE_DESCRIPTOR,                    // Desc
+    sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3,   // Len
+    ACPI_ADDRESS_SPACE_TYPE_MEM,                      // ResType
+    0,                                                // GenFlag
+    0,                                                // SpecificFlag
+    32,                                               // AddrSpaceGranularity
+    FixedPcdGet32 (PcdDwEmacDefaultMacAddress),       // AddrRangeMin
+    FixedPcdGet32 (PcdDwEmacDefaultMacAddress),       // AddrRangeMax
+    0,                                                // AddrTranslationOffset
+    1,                                                // AddrLen
+  }, {
+    ACPI_END_TAG_DESCRIPTOR                           // Desc
+  }
+};
+
+STATIC
+EFI_STATUS
+RegisterDevice (
+  IN  EFI_GUID                            *TypeGuid,
+  IN  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Desc,
+  OUT EFI_HANDLE                          *Handle
+  )
+{
+  NON_DISCOVERABLE_DEVICE             *Device;
+  EFI_STATUS                          Status;
+
+  Device = (NON_DISCOVERABLE_DEVICE *)AllocateZeroPool (sizeof (*Device));
+  if (Device == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Device->Type = TypeGuid;
+  Device->DmaType = NonDiscoverableDeviceDmaTypeNonCoherent;
+  Device->Resources = Desc;
+
+  Status = gBS->InstallMultipleProtocolInterfaces (Handle,
+                  &gEdkiiNonDiscoverableDeviceProtocolGuid, Device,
+                  NULL);
+  if (EFI_ERROR (Status)) {
+    goto FreeDevice;
+  }
+  return EFI_SUCCESS;
+
+  FreeDevice:
+  FreePool (Device);
+
+  return Status;
+}
+
+
+STATIC
+EFI_STATUS
+EFIAPI
+DriverSupported (
+  IN  EFI_DRIVER_BINDING_PROTOCOL *This,
+  IN  EFI_HANDLE                  Controller,
+  IN  EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
+  )
+{
+  NON_DISCOVERABLE_DEVICE    *Dev;
+  EFI_STATUS                 Status;
+
+  // Connect to the non-discoverable device
+  Status = gBS->OpenProtocol (Controller,
+                              &gEdkiiNonDiscoverableDeviceProtocolGuid,
+                              (VOID **) &Dev,
+                              This->DriverBindingHandle,
+                              Controller,
+                              EFI_OPEN_PROTOCOL_BY_DRIVER);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (CompareGuid (Dev->Type, &gDwEmacNetNonDiscoverableDeviceGuid) &&
+      Dev->DmaType == NonDiscoverableDeviceDmaTypeNonCoherent) {
+    Status = EFI_SUCCESS;
+  } else { 
+    Status = EFI_UNSUPPORTED;
+  }
+
+  // Clean up.
+  gBS->CloseProtocol (Controller,
+                      &gEdkiiNonDiscoverableDeviceProtocolGuid,
+                      This->DriverBindingHandle,
+                      Controller);
+
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+DriverStart (
+  IN  EFI_DRIVER_BINDING_PROTOCOL *This,
+  IN  EFI_HANDLE                  Controller,
+  IN  EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
+  )
+{
+  EFI_STATUS                       Status;
+  EFI_SIMPLE_NETWORK_DRIVER       *Snp;
+  EFI_SIMPLE_NETWORK_MODE         *SnpMode;
+  EFI_SIMPLE_NETWORK_DEVICE_PATH  *DevicePath;
+  UINT64                           DefaultMacAddress;
+  EFI_MAC_ADDRESS                 *SwapMacAddressPtr;
+  UINTN                           BufferSize;
+  UINTN                           BufferSizeBuf;
+
+  // Allocate Resources
+  Snp = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (EFI_SIMPLE_NETWORK_DRIVER)));
+  if (Snp == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  
+  BufferSize = EFI_PAGES_TO_SIZE ((sizeof (DESIGNWARE_HW_DESCRIPTOR))*10);
+  BufferSizeBuf = EFI_PAGES_TO_SIZE ((sizeof (CHAR8))*10*2048);
+  
+  // DMA Allocte Buffer and Map for TxdescRing
+  Status = DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES ((sizeof (DESIGNWARE_HW_DESCRIPTOR))*10), (VOID*)&Snp->MacDriver.TxdescRing);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "CreateDwEmacSnpDxe: DmaAllocateBuffer TxdescRing: %r\n", Status));
+    return Status;
+  }
+  Status = DmaMap (MapOperationBusMasterCommonBuffer, Snp->MacDriver.TxdescRing[0], &BufferSize, &Snp->MacDriver.TxdescRingMap[0], &Snp->MappingTxdesc);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "CreateDwEmacSnpDxe: DmaMap TxdescRing: %r\n", Status));
+    return Status;
+  }
+  
+  // DMA Allocte Buffer and Map for RxdescRing
+  Status = DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES ((sizeof (DESIGNWARE_HW_DESCRIPTOR))*10), (VOID*)&Snp->MacDriver.RxdescRing);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "CreateDwEmacSnpDxe: DmaAllocateBuffer RxdescRing: %r\n", Status));
+    return Status;
+  }
+  Status = DmaMap (MapOperationBusMasterCommonBuffer, Snp->MacDriver.RxdescRing[0], &BufferSize, &Snp->MacDriver.RxdescRingMap[0], &Snp->MappingRxdesc);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "CreateDwEmacSnpDxe: DmaMap RxdescRing: %r\n", Status));
+    return Status;
+  }
+  
+  // DMA Allocte Buffer and Map for TxBuffer
+  Status = DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES ((sizeof (CHAR8))*10*2048), (VOID*)&Snp->MacDriver.TxBuffer);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "CreateDwEmacSnpDxe: DmaAllocateBuffer TxBuffer: %r\n", Status));
+    return Status;
+  }
+  Status = DmaMap (MapOperationBusMasterCommonBuffer, Snp->MacDriver.TxBuffer[0], &BufferSizeBuf, &Snp->MacDriver.TxBufferMap[0], &Snp->MappingTxbuf);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "CreateDwEmacSnpDxe: DmaMap TxBuffer: %r\n", Status));
+    return Status;
+  }
+  
+  // DMA Allocte Buffer and Map for RxBuffer
+  Status = DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES ((sizeof (CHAR8))*10*2048), (VOID*)&Snp->MacDriver.RxBuffer);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "CreateDwEmacSnpDxe: DmaAllocateBuffer RxBuffer: %r\n", Status));
+    return Status;
+  }
+  Status = DmaMap (MapOperationBusMasterWrite, Snp->MacDriver.RxBuffer[0], &BufferSizeBuf, &Snp->MacDriver.RxBufferMap[0], &Snp->MappingRxbuf);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "CreateDwEmacSnpDxe: DmaMap RxBuffer: %r\n", Status));
+    return Status;
+  }
+  
+  
+  DevicePath = (EFI_SIMPLE_NETWORK_DEVICE_PATH*)AllocateCopyPool (sizeof (EFI_SIMPLE_NETWORK_DEVICE_PATH), &PathTemplate);
+  if (DevicePath == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  
+  Status = gBS->OpenProtocol (Controller,
+                              &gEdkiiNonDiscoverableDeviceProtocolGuid,
+                              (VOID **)&Snp->Dev,
+                              This->DriverBindingHandle,
+                              Controller,
+                              EFI_OPEN_PROTOCOL_BY_DRIVER);
+
+  // Initialized signature (used by INSTANCE_FROM_SNP_THIS macro)
+  Snp->Signature = SNP_DRIVER_SIGNATURE;
+  
+  EfiInitializeLock (&Snp->Lock, TPL_CALLBACK);
+  
+  // Initialize pointers
+  SnpMode = &(Snp->SnpMode);
+  Snp->Snp.Mode = SnpMode;
+
+  // Assign fields and func pointers
+  Snp->Snp.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
+  Snp->Snp.WaitForPacket = NULL;
+  Snp->Snp.Initialize = SnpInitialize;
+  Snp->Snp.Start = SnpStart;
+  Snp->Snp.Stop = SnpStop;
+  Snp->Snp.Reset = SnpReset;
+  Snp->Snp.Shutdown = SnpShutdown;
+  Snp->Snp.ReceiveFilters = SnpReceiveFilters;
+  Snp->Snp.StationAddress = SnpStationAddress;
+  Snp->Snp.Statistics = SnpStatistics;
+  Snp->Snp.MCastIpToMac = SnpMcastIptoMac;
+  Snp->Snp.NvData = SnpNvData;
+  Snp->Snp.GetStatus = SnpGetStatus;
+  Snp->Snp.Transmit = SnpTransmit;
+  Snp->Snp.Receive = SnpReceive;
+ 
+  Snp->RecycledTxBuf = AllocatePool (sizeof (UINT64) * SNP_TX_BUFFER_INCREASEMENT);
+  if (Snp->RecycledTxBuf == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+  }
+  
+  Snp->MaxRecycledTxBuf    = SNP_TX_BUFFER_INCREASEMENT;
+  Snp->RecycledTxBufCount  = 0;
+
+  // Start completing simple network mode structure
+  SnpMode->State = EfiSimpleNetworkStopped;
+  SnpMode->HwAddressSize = NET_ETHER_ADDR_LEN; // HW address is 6 bytes
+  SnpMode->MediaHeaderSize = sizeof(ETHER_HEAD); // Not sure of this
+  SnpMode->MaxPacketSize = EFI_PAGE_SIZE; // Preamble + SOF + Ether Frame (with VLAN tag +4bytes)
+  SnpMode->NvRamSize = 0;           // No NVRAM with this device
+  SnpMode->NvRamAccessSize = 0; // No NVRAM with this device
+
+  // Update network mode information
+  SnpMode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST     |
+                               EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST   |
+                               EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST   |
+                               EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS |
+                               EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
+
+  // We do not intend to receive anything for the time being.
+  SnpMode->ReceiveFilterSetting = 0;
+
+  // EMAC has 64bit hash table, can filter 64 MCast MAC Addresses
+  SnpMode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT;
+  SnpMode->MCastFilterCount = 0;
+  ZeroMem (&SnpMode->MCastFilter, MAX_MCAST_FILTER_CNT * sizeof(EFI_MAC_ADDRESS));
+
+  // Set the interface type (1: Ethernet or 6: IEEE 802 Networks)
+  SnpMode->IfType = NET_IFTYPE_ETHERNET;
+
+  // Mac address is changeable as it is loaded from erasable memory
+  SnpMode->MacAddressChangeable = TRUE;
+
+  // Can only transmit one packet at a time
+  SnpMode->MultipleTxSupported = FALSE;
+
+  // MediaPresent checks for cable connection and partner link
+  SnpMode->MediaPresentSupported = TRUE;
+  SnpMode->MediaPresent = FALSE;
+
+  // Set broadcast address
+  SetMem (&SnpMode->BroadcastAddress, sizeof (EFI_MAC_ADDRESS), 0xFF);
+
+  //Set current address
+  DefaultMacAddress = Snp->Dev->Resources[1].AddrRangeMin;
+  // Swap PCD human readable form to correct endianess
+  SwapMacAddressPtr = (EFI_MAC_ADDRESS *) &DefaultMacAddress;
+  SnpMode->CurrentAddress.Addr[0] = SwapMacAddressPtr->Addr[5];
+  SnpMode->CurrentAddress.Addr[1] = SwapMacAddressPtr->Addr[4];
+  SnpMode->CurrentAddress.Addr[2] = SwapMacAddressPtr->Addr[3];
+  SnpMode->CurrentAddress.Addr[3] = SwapMacAddressPtr->Addr[2];
+  SnpMode->CurrentAddress.Addr[4] = SwapMacAddressPtr->Addr[1];
+  SnpMode->CurrentAddress.Addr[5] = SwapMacAddressPtr->Addr[0];
+  
+  // Assign fields for device path
+  CopyMem (&DevicePath->MacAddrDP.MacAddress, &Snp->Snp.Mode->CurrentAddress, NET_ETHER_ADDR_LEN);
+  DevicePath->MacAddrDP.IfType = Snp->Snp.Mode->IfType;
+  
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &Controller,
+                  &gEfiSimpleNetworkProtocolGuid, &(Snp->Snp),
+				  &gEfiDevicePathProtocolGuid, DevicePath,
+				  NULL
+                  );
+
+  if (EFI_ERROR(Status)) {
+  gBS->CloseProtocol (Controller,
+                      &gEdkiiNonDiscoverableDeviceProtocolGuid, 
+					  This->DriverBindingHandle,
+                      Controller);
+
+  FreePages (Snp, EFI_SIZE_TO_PAGES (sizeof (EFI_SIMPLE_NETWORK_DRIVER)));
+  } else {
+    Snp->ControllerHandle = Controller;
+  }  
+
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+DriverStop (
+  IN  EFI_DRIVER_BINDING_PROTOCOL *This,
+  IN  EFI_HANDLE                  Controller,
+  IN  UINTN                       NumberOfChildren,
+  IN  EFI_HANDLE                  *ChildHandleBuffer
+  )
+{
+  EFI_STATUS Status;
+  EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol;
+  EFI_SIMPLE_NETWORK_DRIVER   *Snp;
+  
+  Status = gBS->HandleProtocol (
+                  Controller,
+                  &gEfiSimpleNetworkProtocolGuid,
+                  (VOID**)&SnpProtocol
+                );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "DriverStop: HandleProtocol: %r\n", Status));
+    return Status;
+  }
+
+  Snp = INSTANCE_FROM_SNP_THIS(SnpProtocol);
+  
+  Status = gBS->UninstallMultipleProtocolInterfaces (
+                  Controller,
+                  &gEfiSimpleNetworkProtocolGuid,
+                  &Snp->Snp,
+                  NULL);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "DriverStop: UninstallMultipleProtocolInterfaces: %r\n",
+      Status));
+    return Status;
+  }
+  
+  DmaUnmap(Snp->MappingTxdesc);
+  DmaUnmap(Snp->MappingRxdesc);
+  DmaUnmap(Snp->MappingTxbuf);
+  DmaUnmap(Snp->MappingRxbuf);
+  
+  FreePool (Snp->RecycledTxBuf);
+  FreePages (Snp, EFI_SIZE_TO_PAGES (sizeof (EFI_SIMPLE_NETWORK_DRIVER))); 
+
+  return Status;
+}
+
+
+/**
+   UEFI Driver Entry Point API
+   @param  ImageHandle       EFI_HANDLE.
+   @param  SystemTable       EFI_SYSTEM_TABLE.
+   @return EFI_SUCCESS       Success.
+   EFI_DEVICE_ERROR  Fail.
+**/
+
+EFI_STATUS
+EFIAPI
+DwEmacSnpDxeEntry (
+  IN  EFI_HANDLE ImageHandle,
+  IN  EFI_SYSTEM_TABLE *SystemTable
+  )
+{
+  EFI_STATUS        Status;
+  EFI_HANDLE        Handle;
+  
+  Handle = NULL;
+  Status = RegisterDevice (&gDwEmacNetNonDiscoverableDeviceGuid, mDwEmacNetDesc,
+             &Handle);
+  ASSERT_EFI_ERROR (Status);
+  
+  Status = EfiLibInstallDriverBindingComponentName2 (
+             ImageHandle,
+             SystemTable,
+             &mDriverBinding,
+             ImageHandle,
+             &gSnpComponentName,
+             &gSnpComponentName2
+             );
+
+  return Status;
+
+}
\ No newline at end of file
diff --git a/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.c b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.c
new file mode 100755
index 000000000000..cee1584c599e
--- /dev/null
+++ b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.c
@@ -0,0 +1,1273 @@
+/** @file
+  DW EMAC SNP DXE driver
+
+  Copyright (c) 2011 - 2019, Intel Corporaton. All rights reserved.
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+  
+  The original software modules are licensed as follows:
+
+  Copyright (c) 2012 - 2014, ARM Limited. All rights reserved.
+  Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD 3 Clause LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include "DwEmacSnpDxe.h"
+#include "EmacDxeUtil.h"
+#include "PhyDxeUtil.h"
+
+/**
+  Change the state of a network interface from "stopped" to "started."
+
+  This function starts a network interface. If the network interface successfully
+  starts, then EFI_SUCCESS will be returned.
+
+  @param  Snp                    A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
+
+  @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  This parameter was NULL or did not point to a valid
+                                 EFI_SIMPLE_NETWORK_PROTOCOL structure.
+  @retval EFI_DEVICE_ERROR       The command could not be sent to the network interface.
+  @retval EFI_UNSUPPORTED        This function is not supported by the network interface.
+
+**/
+EFI_STATUS
+EFIAPI
+SnpStart (
+  IN  EFI_SIMPLE_NETWORK_PROTOCOL    *This
+ )
+{
+  EFI_SIMPLE_NETWORK_DRIVER    *Snp;
+  DEBUG ((EFI_D_INFO,"SNP:DXE: %a ()\r\n", __FUNCTION__));
+
+  // Check Snp instance
+  if (This == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  
+  Snp = INSTANCE_FROM_SNP_THIS(This);
+  // Check state
+  if ((Snp->SnpMode.State == EfiSimpleNetworkStarted)    ||
+      (Snp->SnpMode.State == EfiSimpleNetworkInitialized)  ) {
+    return EFI_ALREADY_STARTED;
+  }
+
+  // Change state
+  Snp->SnpMode.State = EfiSimpleNetworkStarted;
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Changes the state of a network interface from "started" to "stopped."
+
+  This function stops a network interface. This call is only valid if the network
+  interface is in the started state. If the network interface was successfully
+  stopped, then EFI_SUCCESS will be returned.
+
+  @param  Snp                     A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL
+                                  instance.
+
+
+  @retval EFI_SUCCESS             The network interface was stopped.
+  @retval EFI_NOT_STARTED         The network interface has not been started.
+  @retval EFI_INVALID_PARAMETER   This parameter was NULL or did not point to a
+                                  valid EFI_SIMPLE_NETWORK_PROTOCOL structure.
+  @retval EFI_DEVICE_ERROR        The command could not be sent to the network
+                                  interface.
+  @retval EFI_UNSUPPORTED         This function is not supported by the network
+                                  interface.
+
+**/
+EFI_STATUS
+EFIAPI
+SnpStop (
+  IN        EFI_SIMPLE_NETWORK_PROTOCOL* This
+  )
+{
+  EFI_SIMPLE_NETWORK_DRIVER    *Snp;
+  UINT32        MacBase;
+  DEBUG ((EFI_D_INFO, "SNP:DXE: %a ()\r\n", __FUNCTION__));
+
+  // Check Snp Instance
+  if (This == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Snp = INSTANCE_FROM_SNP_THIS(This);
+  // Check state of the driver
+  if (Snp->SnpMode.State == EfiSimpleNetworkStopped) {
+    return EFI_NOT_STARTED;
+  }
+
+  //Get MAC base address
+  MacBase = (UINT32)Snp->Dev->Resources[0].AddrRangeMin;
+  
+  // Stop the Tx and Rx
+  EmacStopTxRx (MacBase);
+  // Change the state
+  switch (Snp->SnpMode.State) {
+    case EfiSimpleNetworkStarted:
+    case EfiSimpleNetworkInitialized:
+      Snp->SnpMode.State = EfiSimpleNetworkStopped;
+      break;
+    default:
+      return EFI_DEVICE_ERROR;
+  }
+
+  // Put the device into a power saving mode ?
+  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.
+
+  This function allocates the transmit and receive buffers required by the network
+  interface. If this allocation fails, then EFI_OUT_OF_RESOURCES is returned.
+  If the allocation succeeds and the network interface is successfully initialized,
+  then EFI_SUCCESS will be returned.
+
+  @param Snp                A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
+
+  @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 This parameter was NULL or did not point to a valid
+                                EFI_SIMPLE_NETWORK_PROTOCOL structure.
+  @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
+  @retval EFI_UNSUPPORTED       The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SnpInitialize (
+  IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+  IN UINTN                       ExtraRxBufferSize OPTIONAL,
+  IN UINTN                       ExtraTxBufferSize OPTIONAL
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_SIMPLE_NETWORK_DRIVER  *Snp;
+  UINT32                      MacBase;
+
+  DEBUG ((EFI_D_INFO, "SNP:DXE: %a ()\r\n", __FUNCTION__));
+
+  // Check Snp Instance
+  if (This == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Snp = INSTANCE_FROM_SNP_THIS (This);
+  // First check that driver has not already been initialized
+  if (Snp->SnpMode.State == EfiSimpleNetworkInitialized) {
+    return EFI_SUCCESS;
+  } else
+  if (Snp->SnpMode.State == EfiSimpleNetworkStopped) {
+    return EFI_NOT_STARTED;
+  }
+  
+  //Get MAC base address
+  MacBase = (UINT32)Snp->Dev->Resources[0].AddrRangeMin;
+
+  // Init PHY
+  Status = PhyDxeInitialization (&Snp->PhyDriver, MacBase);
+  if (EFI_ERROR (Status)) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  // Init EMAC
+  Status = EmacDxeInitialization (&Snp->MacDriver, MacBase);
+  if (EFI_ERROR (Status)) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  // Set MAC Address
+  EmacSetMacAddress (&Snp->SnpMode.CurrentAddress, MacBase);
+  EmacReadMacAddress(&Snp->SnpMode.CurrentAddress, MacBase);
+
+  // Init Link
+  Print (L"SNP:DXE: Auto-Negotiating Ethernet PHY Link ...\r\n");
+  Status = PhyLinkAdjustEmacConfig (&Snp->PhyDriver, MacBase);
+  if (EFI_ERROR(Status)) {
+    Print (L"SNP:DXE: Link is Down - Network Cable is not plugged in?\r\n");
+    return EFI_DEVICE_ERROR;
+  }
+
+  EmacStartTransmission (MacBase);
+
+  // Declare the driver as initialized
+  Snp->SnpMode.State = EfiSimpleNetworkInitialized;
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Resets a network adapter and reinitializes it with the parameters that were
+  provided in the previous call to Initialize().
+
+  This function resets a network adapter and reinitializes it with the parameters
+  that were provided in the previous call to Initialize(). The transmit and
+  receive queues are emptied and all pending interrupts are cleared.
+  Receive filters, the station address, the statistics, and the multicast-IP-to-HW
+  MAC addresses are not reset by this call. If the network interface was
+  successfully reset, then EFI_SUCCESS will be returned. If the driver has not
+  been initialized, EFI_DEVICE_ERROR will be returned.
+
+  @param Snp                  A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
+  @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 command could not be sent to the network interface.
+  @retval EFI_UNSUPPORTED       This function is not supported by the network interface.
+
+**/
+EFI_STATUS
+EFIAPI
+SnpReset (
+  IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
+  IN BOOLEAN                     ExtendedVerification
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_SIMPLE_NETWORK_DRIVER  *Snp;
+  UINT32                      MacBase;
+
+  Snp = INSTANCE_FROM_SNP_THIS (This);
+
+  DEBUG ((EFI_D_INFO, "SNP:DXE: %a ()\r\n", __FUNCTION__));
+
+  // Check Snp Instance
+  if (This == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // First check that driver has not already been initialized
+  if (Snp->SnpMode.State == EfiSimpleNetworkStarted) {
+    return EFI_DEVICE_ERROR;
+  } else if (Snp->SnpMode.State == EfiSimpleNetworkStopped) {
+    return EFI_NOT_STARTED;
+  }
+  
+  // Get MAC base address
+  MacBase = (UINT32)Snp->Dev->Resources[0].AddrRangeMin;
+
+  // Initiate a PHY reset
+  Status = PhySoftReset (&Snp->PhyDriver, MacBase);
+  if (EFI_ERROR (Status)) {
+    Snp->SnpMode.State = EfiSimpleNetworkStopped;
+    return EFI_NOT_STARTED;
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Resets a network adapter and leaves it in a state that is safe for another
+  driver to initialize.
+
+  This function releases the memory buffers assigned in the Initialize() call.
+  Pending transmits and receives are lost, and interrupts are cleared and disabled.
+  After this call, only the Initialize() and Stop() calls may be used. If the
+  network interface was successfully shutdown, then EFI_SUCCESS will be returned.
+  If the driver has not been initialized, EFI_DEVICE_ERROR will be returned.
+
+  @param  This  A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
+
+  @retval EFI_SUCCESS           The network interface was shutdown.
+  @retval EFI_NOT_STARTED       The network interface has not been started.
+  @retval EFI_INVALID_PARAMETER This parameter was NULL or did not point to a valid
+                                EFI_SIMPLE_NETWORK_PROTOCOL structure.
+  @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
+
+**/
+EFI_STATUS
+EFIAPI
+SnpShutdown (
+  IN        EFI_SIMPLE_NETWORK_PROTOCOL*  This
+  )
+{
+  EFI_SIMPLE_NETWORK_DRIVER  *Snp;
+  UINT32                      MacBase;
+  DEBUG ((EFI_D_INFO, "SNP:DXE: %a ()\r\n", __FUNCTION__));
+
+  // Check Snp Instance
+  if (This == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Snp = INSTANCE_FROM_SNP_THIS (This);
+  // First check that driver has not already been initialized
+  if (Snp->SnpMode.State == EfiSimpleNetworkStarted) {
+    return EFI_DEVICE_ERROR;
+  } else if (Snp->SnpMode.State == EfiSimpleNetworkStopped) {
+    return EFI_NOT_STARTED;
+  }
+  
+  //Get MAC base address
+  MacBase = (UINT32)Snp->Dev->Resources[0].AddrRangeMin;
+  
+  EmacStopTxRx (MacBase);
+
+  Snp->SnpMode.State = EfiSimpleNetworkStopped;
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Manages the multicast receive filters of a network interface.
+
+  This function is used enable and disable the hardware and software receive
+  filters for the underlying network device.
+  The receive filter change is broken down into three steps:
+  * The filter mask bits that are set (ON) in the Enable parameter are added to
+    the current receive filter settings.
+  * The filter mask bits that are set (ON) in the Disable parameter are subtracted
+    from the updated receive filter settings.
+  * If the resulting receive filter setting is not supported by the hardware a
+    more liberal setting is selected.
+  If the same bits are set in the Enable and Disable parameters, then the bits
+  in the Disable parameter takes precedence.
+  If the ResetMCastFilter parameter is TRUE, then the multicast address list
+  filter is disabled (irregardless of what other multicast bits are set in the
+  Enable and Disable parameters). The SNP->Mode->MCastFilterCount field is set
+  to zero. The Snp->Mode->MCastFilter contents are undefined.
+  After enabling or disabling receive filter settings, software should verify
+  the new settings by checking the Snp->Mode->ReceiveFilterSettings,
+  Snp->Mode->MCastFilterCount and Snp->Mode->MCastFilter fields.
+  Note: Some network drivers and/or devices will automatically promote receive
+    filter settings if the requested setting can not be honored. For example, if
+    a request for four multicast addresses is made and the underlying hardware
+    only supports two multicast addresses the driver might set the promiscuous
+    or promiscuous multicast receive filters instead. The receiving software is
+    responsible for discarding any extra packets that get through the hardware
+    receive filters.
+    Note: Note: To disable all receive filter hardware, the network driver must
+      be Shutdown() and Stopped(). Calling ReceiveFilters() with Disable set to
+      Snp->Mode->ReceiveFilterSettings will make it so no more packets are
+      returned by the Receive() function, but the receive hardware may still be
+      moving packets into system memory before inspecting and discarding them.
+      Unexpected system errors, reboots and hangs can occur if an OS is loaded
+      and the network devices are not Shutdown() and Stopped().
+  If ResetMCastFilter is TRUE, then the multicast receive filter list on the
+  network interface will be reset to the default multicast receive filter list.
+  If ResetMCastFilter is FALSE, and this network interface allows the multicast
+  receive filter list to be modified, then the MCastFilterCnt and MCastFilter
+  are used to update the current multicast receive filter list. The modified
+  receive filter list settings can be found in the MCastFilter field of
+  EFI_SIMPLE_NETWORK_MODE. If the network interface does not allow the multicast
+  receive filter list to be modified, then EFI_INVALID_PARAMETER will be returned.
+  If the driver has not been initialized, EFI_DEVICE_ERROR will be returned.
+  If the receive filter mask and multicast receive filter list have been
+  successfully updated on the network interface, EFI_SUCCESS will be returned.
+
+  @param Snp              A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
+  @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. For backward compatibility with EFI 1.1
+                          platforms, the EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit
+                          must be set when the ResetMCastFilter parameter is TRUE.
+  @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 following conditions is TRUE:
+                                 * This is NULL
+                                 * There are bits set in Enable that are not set
+                                   in Snp->Mode->ReceiveFilterMask
+                                 * There are bits set in Disable that are not set
+                                   in Snp->Mode->ReceiveFilterMask
+                                 * Multicast is being enabled (the
+                                   EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit is
+                                   set in Enable, it is not set in Disable, and
+                                   ResetMCastFilter is FALSE) and MCastFilterCount
+                                   is zero
+                                 * Multicast is being enabled and MCastFilterCount
+                                   is greater than Snp->Mode->MaxMCastFilterCount
+                                 * Multicast is being enabled and MCastFilter is NULL
+                                 * Multicast is being enabled and one or more of
+                                   the addresses in the MCastFilter list are not
+                                   valid multicast MAC addresses
+  @retval EFI_DEVICE_ERROR       One or more of the following conditions is TRUE:
+                                 * The network interface has been started but has
+                                   not been initialized
+                                 * An unexpected error was returned by the
+                                   underlying network driver or device
+  @retval EFI_UNSUPPORTED        This function is not supported by the network
+                                 interface.
+
+**/
+EFI_STATUS
+EFIAPI
+SnpReceiveFilters (
+  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
+  )
+{
+  UINT32                      ReceiveFilterSetting;
+  EFI_SIMPLE_NETWORK_DRIVER  *Snp;
+  UINT32                      MacBase;
+  
+  Snp = INSTANCE_FROM_SNP_THIS (This);
+  
+  // Check Snp Instance
+  if (Snp == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Check that driver was started and initialised
+  if (Snp->SnpMode.State == EfiSimpleNetworkStarted) {
+    return EFI_DEVICE_ERROR;
+  } else if (Snp->SnpMode.State == EfiSimpleNetworkStopped) {
+    return EFI_NOT_STARTED;
+  }
+
+   if ((Enable  & (~Snp->SnpMode.ReceiveFilterMask)) ||
+      (Disable & (~Snp->SnpMode.ReceiveFilterMask))    ) {
+    return EFI_INVALID_PARAMETER;
+  }
+  
+  //Get MAC base address
+  MacBase = (UINT32)Snp->Dev->Resources[0].AddrRangeMin;
+
+  ReceiveFilterSetting = (Snp->SnpMode.ReceiveFilterSetting | Enable) & (~Disable);
+
+  EmacRxFilters (ReceiveFilterSetting, ResetMCastFilter, MCastFilterCnt, MCastFilter, MacBase);
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Modifies or resets the current station address, if supported.
+
+  This function modifies or resets the current station address of a network
+  interface, if supported. If Reset is TRUE, then the current station address is
+  set to the network interface's permanent address. If Reset is FALSE, and the
+  network interface allows its station address to be modified, then the current
+  station address is changed to the address specified by New. If the network
+  interface does not allow its station address to be modified, then
+  EFI_INVALID_PARAMETER will be returned. If the station address is successfully
+  updated on the network interface, EFI_SUCCESS will be returned. If the driver
+  has not been initialized, EFI_DEVICE_ERROR will be returned.
+
+  @param Snp      A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
+  @param Reset    Flag used to reset the station address to the network interface's
+                  permanent address.
+  @param NewMac   New station address to be used for the network interface.
+
+
+  @retval EFI_SUCCESS           The network interface's station address was updated.
+  @retval EFI_NOT_STARTED       The Simple Network Protocol interface has not been
+                                started by calling Start().
+  @retval EFI_INVALID_PARAMETER The New station address was not accepted by the NIC.
+  @retval EFI_INVALID_PARAMETER Reset is FALSE and New is NULL.
+  @retval EFI_DEVICE_ERROR      The Simple Network Protocol interface has not
+                                been initialized by calling Initialize().
+  @retval EFI_DEVICE_ERROR      An error occurred attempting to set the new
+                                station address.
+  @retval EFI_UNSUPPORTED       The NIC does not support changing the network
+                                interface's station address.
+
+**/
+EFI_STATUS
+EFIAPI
+SnpStationAddress (
+  IN        EFI_SIMPLE_NETWORK_PROTOCOL *This,
+  IN        BOOLEAN                      Reset,
+  IN        EFI_MAC_ADDRESS             *NewMac
+)
+{
+  return EFI_UNSUPPORTED;
+}
+
+
+
+/**
+  Resets or collects the statistics on a network interface.
+
+  This function resets or collects the statistics on a network interface. If the
+  size of the statistics table specified by StatisticsSize is not big enough for
+  all the statistics that are collected by the network interface, then a partial
+  buffer of statistics is returned in StatisticsTable, StatisticsSize is set to
+  the size required to collect all the available statistics, and
+  EFI_BUFFER_TOO_SMALL is returned.
+  If StatisticsSize is big enough for all the statistics, then StatisticsTable
+  will be filled, StatisticsSize will be set to the size of the returned
+  StatisticsTable structure, and EFI_SUCCESS is returned.
+  If the driver has not been initialized, EFI_DEVICE_ERROR will be returned.
+  If Reset is FALSE, and both StatisticsSize and StatisticsTable are NULL, then
+  no operations will be performed, and EFI_SUCCESS will be returned.
+  If Reset is TRUE, then all of the supported statistics counters on this network
+  interface will be reset to zero.
+
+  @param Snp             A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
+  @param Reset           Set to TRUE to reset the statistics for the network interface.
+  @param StatSize        On input the size, in bytes, of StatisticsTable. On output
+                         the size, in bytes, of the resulting table of statistics.
+  @param Statistics      A pointer to the EFI_NETWORK_STATISTICS structure that
+                         contains the statistics. Type EFI_NETWORK_STATISTICS is
+                         defined in "Related Definitions" below.
+
+  @retval EFI_SUCCESS           The requested operation succeeded.
+  @retval EFI_NOT_STARTED       The Simple Network Protocol interface has not been
+                                started by calling Start().
+  @retval EFI_BUFFER_TOO_SMALL  StatisticsSize is not NULL and StatisticsTable is
+                                NULL. The current buffer size that is needed to
+                                hold all the statistics is returned in StatisticsSize.
+  @retval EFI_BUFFER_TOO_SMALL  StatisticsSize is not NULL and StatisticsTable is
+                                not NULL. The current buffer size that is needed
+                                to hold all the statistics is returned in
+                                StatisticsSize. A partial set of statistics is
+                                returned in StatisticsTable.
+  @retval EFI_INVALID_PARAMETER StatisticsSize is NULL and StatisticsTable is not
+                                NULL.
+  @retval EFI_DEVICE_ERROR      The Simple Network Protocol interface has not
+                                been initialized by calling Initialize().
+  @retval EFI_DEVICE_ERROR      An error was encountered collecting statistics
+                                from the NIC.
+  @retval EFI_UNSUPPORTED       The NIC does not support collecting statistics
+                                from the network interface.
+
+**/
+EFI_STATUS
+EFIAPI
+SnpStatistics (
+  IN        EFI_SIMPLE_NETWORK_PROTOCOL  *This,
+  IN        BOOLEAN                      Reset,
+  IN  OUT   UINTN                        *StatSize,
+      OUT   EFI_NETWORK_STATISTICS       *Statistics
+  )
+{
+  EFI_SIMPLE_NETWORK_DRIVER  *Snp;
+  UINT32                      MacBase;
+
+  Snp = INSTANCE_FROM_SNP_THIS (This);
+
+  DEBUG ((EFI_D_INFO, "SNP:DXE: %a ()\r\n", __FUNCTION__));
+
+  // Check Snp instance
+  if (This == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Check that driver was started and initialised
+  if (Snp->SnpMode.State == EfiSimpleNetworkStarted) {
+    return EFI_DEVICE_ERROR;
+  } else if (Snp->SnpMode.State == EfiSimpleNetworkStopped) {
+    return EFI_NOT_STARTED;
+  }
+
+  // Check pointless condition
+  if ((!Reset) && (StatSize == NULL) && (Statistics == NULL)) {
+    return EFI_SUCCESS;
+  }
+
+  // Check the parameters
+  if ((StatSize == NULL) && (Statistics != NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Do a reset if required
+  if (Reset) {
+    ZeroMem (&Snp->Stats, sizeof(EFI_NETWORK_STATISTICS));
+  }
+
+  // Check buffer size
+  if (*StatSize < sizeof(EFI_NETWORK_STATISTICS)) {
+    *StatSize = sizeof(EFI_NETWORK_STATISTICS);
+    return EFI_BUFFER_TOO_SMALL;
+  }
+  
+  //Get MAC base address
+  MacBase = (UINT32)Snp->Dev->Resources[0].AddrRangeMin;
+  
+  // read statistic counters
+  EmacGetStatistic (&Snp->Stats, MacBase);
+
+  // Fill in the statistics
+  CopyMem(&Statistics, &Snp->Stats, sizeof(EFI_NETWORK_STATISTICS));
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Converts a multicast IP address to a multicast HW MAC address.
+
+  This function converts a multicast IP address to a multicast HW MAC address
+  for all packet transactions. If the mapping is accepted, then EFI_SUCCESS will
+  be returned.
+
+  @param Snp         A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
+  @param IsIpv6      Set to TRUE if the multicast IP address is IPv6 [RFC 2460].
+                     Set to FALSE if the multicast IP address is IPv4 [RFC 791].
+  @param Ip          The multicast IP address that is to be converted to a multicast
+                     HW MAC address.
+  @param McastMac    The multicast HW MAC address that is to be generated from IP.
+
+  @retval EFI_SUCCESS           The multicast IP address was mapped to the
+                                multicast HW MAC address.
+  @retval EFI_NOT_STARTED       The Simple Network Protocol interface has not
+                                been started by calling Start().
+  @retval EFI_INVALID_PARAMETER IP is NULL.
+  @retval EFI_INVALID_PARAMETER MAC is NULL.
+  @retval EFI_INVALID_PARAMETER IP does not point to a valid IPv4 or IPv6
+                                multicast address.
+  @retval EFI_DEVICE_ERROR      The Simple Network Protocol interface has not
+                                been initialized by calling Initialize().
+  @retval EFI_UNSUPPORTED       IPv6 is TRUE and the implementation does not
+                                support IPv6 multicast to MAC address conversion.
+
+**/
+EFI_STATUS
+EFIAPI
+SnpMcastIptoMac (
+  IN        EFI_SIMPLE_NETWORK_PROTOCOL  *This,
+  IN        BOOLEAN                      IsIpv6,
+  IN        EFI_IP_ADDRESS               *Ip,
+      OUT   EFI_MAC_ADDRESS              *McastMac
+  )
+{
+
+  DEBUG ((EFI_D_INFO, "SNP:DXE: %a ()\r\n", __FUNCTION__));
+
+  // Check Snp instance
+  if (This == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  
+  EFI_SIMPLE_NETWORK_DRIVER  *Snp;
+
+  Snp = INSTANCE_FROM_SNP_THIS (This);
+
+  // Check that driver was started and initialised
+  if (Snp->SnpMode.State == EfiSimpleNetworkStarted) {
+    return EFI_DEVICE_ERROR;
+  } else if (Snp->SnpMode.State == EfiSimpleNetworkStopped) {
+    return EFI_NOT_STARTED;
+  }
+
+  // Check parameters
+  if ((McastMac == NULL) || (Ip == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Make sure MAC address is empty
+  ZeroMem (McastMac, sizeof(EFI_MAC_ADDRESS));
+
+  // If we need ipv4 address
+  if (!IsIpv6) {
+    // Most significant 25 bits of a multicast HW address are set.
+    // 01-00-5E is the IPv4 Ethernet Multicast Address (see RFC 1112)
+    McastMac->Addr[0] = 0x01;
+    McastMac->Addr[1] = 0x00;
+    McastMac->Addr[2] = 0x5E;
+
+    // Lower 23 bits from ipv4 address
+    McastMac->Addr[3] = (Ip->v4.Addr[1] & 0x7F); // Clear the most significant bit (25th bit of MAC must be 0)
+    McastMac->Addr[4] = Ip->v4.Addr[2];
+    McastMac->Addr[5] = Ip->v4.Addr[3];
+  } else {
+    // Most significant 16 bits of multicast v6 HW address are set
+    // 33-33 is the IPv6 Ethernet Multicast Address (see RFC 2464)
+    McastMac->Addr[0] = 0x33;
+    McastMac->Addr[1] = 0x33;
+
+    // lower four octets are taken from ipv6 address
+    McastMac->Addr[2] = Ip->v6.Addr[8];
+    McastMac->Addr[3] = Ip->v6.Addr[9];
+    McastMac->Addr[4] = Ip->v6.Addr[10];
+    McastMac->Addr[5] = Ip->v6.Addr[11];
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Performs read and write operations on the NVRAM device attached to a network
+  interface.
+
+  This function performs read and write operations on the NVRAM device attached
+  to a network interface. If ReadWrite is TRUE, a read operation is performed.
+  If ReadWrite is FALSE, a write operation is performed. Offset specifies the
+  byte offset at which to start either operation. Offset must be a multiple of
+  NvRamAccessSize , and it must have a value between zero and NvRamSize.
+  BufferSize specifies the length of the read or write operation. BufferSize must
+  also be a multiple of NvRamAccessSize, and Offset + BufferSize must not exceed
+  NvRamSize.
+  If any of the above conditions is not met, then EFI_INVALID_PARAMETER will be
+  returned.
+  If all the conditions are met and the operation is "read," the NVRAM device
+  attached to the network interface will be read into Buffer and EFI_SUCCESS
+  will be returned. If this is a write operation, the contents of Buffer will be
+  used to update the contents of the NVRAM device attached to the network
+  interface and EFI_SUCCESS will be returned.
+
+  It does the basic checking on the input parameters and retrieves snp structure
+  and then calls the read_nvdata() call which does the actual reading
+
+  @param Snp        A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
+  @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. (See EFI_SIMPLE_NETWORK_MODE)
+  @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 following conditions is TRUE:
+                                * The This parameter is NULL
+                                * The This parameter does not point to a valid
+                                  EFI_SIMPLE_NETWORK_PROTOCOL  structure
+                                * The Offset parameter is not a multiple of
+                                  EFI_SIMPLE_NETWORK_MODE.NvRamAccessSize
+                                * The Offset parameter is not less than
+                                  EFI_SIMPLE_NETWORK_MODE.NvRamSize
+                                * The BufferSize parameter is not a multiple of
+                                  EFI_SIMPLE_NETWORK_MODE.NvRamAccessSize
+                                * The Buffer parameter is NULL
+  @retval EFI_DEVICE_ERROR      The command could not be sent to the network
+                                interface.
+  @retval EFI_UNSUPPORTED       This function is not supported by the network
+                                interface.
+
+**/
+EFI_STATUS
+EFIAPI
+SnpNvData (
+  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.
+
+  This function gets the current interrupt and recycled transmit buffer status
+  from the network interface. The interrupt status is returned as a bit mask in
+  InterruptStatus. If InterruptStatus is NULL, the interrupt status will not be
+  read. If TxBuf is not NULL, a recycled transmit buffer address will be retrieved.
+  If a recycled transmit buffer address is returned in TxBuf, then the buffer has
+  been successfully transmitted, and the status for that buffer is cleared. If
+  the status of the network interface is successfully collected, EFI_SUCCESS
+  will be returned. If the driver has not been initialized, EFI_DEVICE_ERROR will
+  be returned.
+
+  @param Snp             A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
+  @param IrqStat         A pointer to the bit mask of the currently active
+                         interrupts (see "Related Definitions"). 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 TxBuff          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 This parameter was NULL or did not point to a valid
+                                EFI_SIMPLE_NETWORK_PROTOCOL structure.
+  @retval EFI_DEVICE_ERROR      The command could not be sent to the network
+                                interface.
+
+**/
+EFI_STATUS
+EFIAPI
+SnpGetStatus (
+  IN    EFI_SIMPLE_NETWORK_PROTOCOL *This,
+  OUT   UINT32                      *IrqStat  OPTIONAL,
+  OUT   VOID                        **TxBuff  OPTIONAL
+  )
+{
+  EFI_STATUS                 Status;
+  EFI_SIMPLE_NETWORK_DRIVER  *Snp;
+  UINT32                      MacBase;
+
+  Snp = INSTANCE_FROM_SNP_THIS (This);
+
+  // Check preliminaries
+  if (This == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  if (Snp->SnpMode.State != EfiSimpleNetworkInitialized) {
+    return EFI_NOT_STARTED;
+  }
+  
+  // Get MAC base address
+  MacBase = (UINT32)Snp->Dev->Resources[0].AddrRangeMin;
+  
+  // Update the media status
+  Status = PhyLinkAdjustEmacConfig (&Snp->PhyDriver, MacBase);
+  if (EFI_ERROR(Status)) {
+    Snp->SnpMode.MediaPresent = FALSE;
+  } else {
+    Snp->SnpMode.MediaPresent = TRUE;
+  }
+  
+  // TxBuff  
+  if (TxBuff != NULL) {
+    //
+    // Get a recycled buf from Snp->RecycledTxBuf
+    //
+    if (Snp->RecycledTxBufCount == 0) {
+      *TxBuff = NULL;
+    } else {
+      Snp->RecycledTxBufCount--;
+      *TxBuff = (VOID *) (UINTN) Snp->RecycledTxBuf[Snp->RecycledTxBufCount];
+    }
+  }
+  
+  // Check DMA Irq status
+  EmacGetDmaStatus (IrqStat, MacBase);
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Places a packet in the transmit queue of a network interface.
+
+  This function places the packet specified by Header and Buffer on the transmit
+  queue. If HeaderSize is nonzero and HeaderSize is not equal to
+  This->Mode->MediaHeaderSize, then EFI_INVALID_PARAMETER will be returned. If
+  BufferSize is less than This->Mode->MediaHeaderSize, then EFI_BUFFER_TOO_SMALL
+  will be returned. If Buffer is NULL, then EFI_INVALID_PARAMETER will be
+  returned. If HeaderSize is nonzero and DestAddr or Protocol is NULL, then
+  EFI_INVALID_PARAMETER will be returned. If the transmit engine of the network
+  interface is busy, then EFI_NOT_READY will be returned. If this packet can be
+  accepted by the transmit engine of the network interface, the packet contents
+  specified by Buffer will be placed on the transmit queue of the network
+  interface, and EFI_SUCCESS will be returned. GetStatus() can be used to
+  determine when the packet has actually been transmitted. The contents of the
+  Buffer must not be modified until the packet has actually been transmitted.
+  The Transmit() function performs nonblocking I/O. A caller who wants to perform
+  blocking I/O, should call Transmit(), and then GetStatus() until the
+  transmitted buffer shows up in the recycled transmit buffer.
+  If the driver has not been initialized, EFI_DEVICE_ERROR will be returned.
+
+  @param Snp        A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
+  @param HdrSize    The size, in bytes, of the media header to be filled in by the
+                    Transmit() function. If HeaderSize is nonzero, then it must
+                    be equal to This->Mode->MediaHeaderSize and the DestAddr and
+                    Protocol parameters must not be NULL.
+  @param BuffSize   The size, in bytes, of the entire packet (media header and
+                    data) to be transmitted through the network interface.
+  @param Data       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 nonzero, 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 nonzero and SrcAddr
+                    is NULL, then This->Mode->CurrentAddress is used for the
+                    source HW MAC address.
+  @param DstAddr    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 command could not be sent to the network interface.
+  @retval EFI_UNSUPPORTED       This function is not supported by the network interface.
+
+**/
+EFI_STATUS
+EFIAPI
+SnpTransmit (
+  IN  EFI_SIMPLE_NETWORK_PROTOCOL  *This,
+  IN  UINTN                        HdrSize,
+  IN  UINTN                        BuffSize,
+  IN  VOID*                        Data,
+  IN  EFI_MAC_ADDRESS              *SrcAddr  OPTIONAL,
+  IN  EFI_MAC_ADDRESS              *DstAddr  OPTIONAL,
+  IN  UINT16                       *Protocol OPTIONAL
+  )
+{
+  EFI_SIMPLE_NETWORK_DRIVER *Snp;
+  UINT32                     DescNum;
+  DESIGNWARE_HW_DESCRIPTOR  *TxDescriptor;
+  UINT8*                     EthernetPacket;
+  UINT64                    *Tmp;
+  UINT32                     MacBase;
+
+  EthernetPacket = Data;
+
+  Snp = INSTANCE_FROM_SNP_THIS (This);
+  
+  if (EFI_ERROR (EfiAcquireLockOrFail (&Snp->Lock))) {
+    return EFI_ACCESS_DENIED;
+  }
+
+  // Check preliminaries
+  if ((This == NULL) || (Data == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+  if (Snp->SnpMode.State != EfiSimpleNetworkInitialized) {
+    return EFI_NOT_STARTED;
+  }
+
+  Snp->MacDriver.TxCurrentDescriptorNum = Snp->MacDriver.TxNextDescriptorNum;
+  DescNum = Snp->MacDriver.TxCurrentDescriptorNum;
+
+  TxDescriptor = Snp->MacDriver.TxdescRing[0] + (DescNum);;
+
+  // Ensure header is correct size if non-zero
+  if (HdrSize) {
+    if (HdrSize != Snp->SnpMode.MediaHeaderSize) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    if ((DstAddr == NULL) || (Protocol == NULL)) {
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+  
+  // Ensure buffer size is valid
+  if (BuffSize < Snp->SnpMode.MediaHeaderSize) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+
+  if (HdrSize) {
+    EthernetPacket[0] = DstAddr->Addr[0];
+    EthernetPacket[1] = DstAddr->Addr[1];
+    EthernetPacket[2] = DstAddr->Addr[2];
+    EthernetPacket[3] = DstAddr->Addr[3];
+    EthernetPacket[4] = DstAddr->Addr[4];
+    EthernetPacket[5] = DstAddr->Addr[5];
+
+    EthernetPacket[6] = SrcAddr->Addr[0];
+    EthernetPacket[7] = SrcAddr->Addr[1];
+    EthernetPacket[8] = SrcAddr->Addr[2];
+    EthernetPacket[9] = SrcAddr->Addr[3];
+    EthernetPacket[10] = SrcAddr->Addr[4];
+    EthernetPacket[11] = SrcAddr->Addr[5];
+
+    EthernetPacket[13] = *Protocol & 0xFF;
+    EthernetPacket[12] = (*Protocol & 0xFF00) >> 8;
+  }
+
+  CopyMem((VOID*)(UINTN)TxDescriptor->Addr, EthernetPacket, BuffSize);
+  
+  TxDescriptor->Tdes1 = (BuffSize << TDES1_SIZE1SHFT) &
+                         TDES1_SIZE1MASK;
+  
+  TxDescriptor->Tdes0 |= (TDES0_TXFIRST |
+                          TDES0_TXLAST |
+                          TDES0_OWN);
+  
+  // Increase descriptor number
+  DescNum++;
+  if (DescNum >= CONFIG_TX_DESCR_NUM)
+    DescNum = 0;
+
+  Snp->MacDriver.TxNextDescriptorNum = DescNum;
+  
+  if ((Snp->MaxRecycledTxBuf + SNP_TX_BUFFER_INCREASEMENT) >= SNP_MAX_TX_BUFFER_NUM) {
+    return EFI_NOT_READY;
+  }
+
+  if (Snp->RecycledTxBufCount < Snp->MaxRecycledTxBuf) {
+    Snp->RecycledTxBuf[Snp->RecycledTxBufCount] = (UINT64) Data;
+    Snp->RecycledTxBufCount ++;
+  } else {
+    Tmp = AllocatePool (sizeof (UINT64) * (Snp->MaxRecycledTxBuf + SNP_TX_BUFFER_INCREASEMENT));
+    if (Tmp == NULL) {
+      return EFI_DEVICE_ERROR;
+    }
+    CopyMem (Tmp, Snp->RecycledTxBuf, sizeof (UINT64) * Snp->RecycledTxBufCount);
+    FreePool (Snp->RecycledTxBuf);
+    Snp->RecycledTxBuf    =  Tmp;
+    Snp->MaxRecycledTxBuf += SNP_TX_BUFFER_INCREASEMENT;
+  }
+  
+  // Get MAC base address
+  MacBase = (UINT32)Snp->Dev->Resources[0].AddrRangeMin;
+  
+  // Start the transmission
+  EmacDmaStart (MacBase);
+  
+  EfiReleaseLock (&Snp->Lock);
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Receives a packet from a network interface.
+
+  This function retrieves one packet from the receive queue of a network interface.
+  If there are no packets on the receive queue, then EFI_NOT_READY will be
+  returned. If there is a packet on the receive queue, and the size of the packet
+  is smaller than BufferSize, then the contents of the packet will be placed in
+  Buffer, and BufferSize will be updated with the actual size of the packet.
+  In addition, if SrcAddr, DestAddr, and Protocol are not NULL, then these values
+  will be extracted from the media header and returned. EFI_SUCCESS will be
+  returned if a packet was successfully received.
+  If BufferSize is smaller than the received packet, then the size of the receive
+  packet will be placed in BufferSize and EFI_BUFFER_TOO_SMALL will be returned.
+  If the driver has not been initialized, EFI_DEVICE_ERROR will be returned.
+
+  @param Snp        A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
+  @param HdrSize    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 BuffSize   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 Data       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 DstAddr   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 have been received on the network interface.
+  @retval EFI_BUFFER_TOO_SMALL  BufferSize is too small for the received packets.
+                                BufferSize has been updated to the required size.
+  @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+                                * The This parameter is NULL
+                                * The This parameter does not point to a valid
+                                  EFI_SIMPLE_NETWORK_PROTOCOL structure.
+                                * The BufferSize parameter is NULL
+                                * The Buffer parameter is NULL
+  @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.
+
+**/
+EFI_STATUS
+EFIAPI
+SnpReceive (
+  IN        EFI_SIMPLE_NETWORK_PROTOCOL *This,
+      OUT   UINTN                       *HdrSize      OPTIONAL,
+  IN  OUT   UINTN                       *BuffSize,
+      OUT   VOID                        *Data,
+      OUT   EFI_MAC_ADDRESS             *SrcAddr      OPTIONAL,
+      OUT   EFI_MAC_ADDRESS             *DstAddr      OPTIONAL,
+      OUT   UINT16                      *Protocol     OPTIONAL
+  )
+{
+  EFI_SIMPLE_NETWORK_DRIVER  *Snp;
+  EFI_MAC_ADDRESS Dst;
+  EFI_MAC_ADDRESS Src;
+  UINT32          Length, DesciptorStatus;
+  UINT8*          RawData;
+  UINT32 DescNum;
+  DESIGNWARE_HW_DESCRIPTOR *RxDescriptor;
+  
+  Snp = INSTANCE_FROM_SNP_THIS (This);
+
+  // Check preliminaries
+  if ((This == NULL) || (Data == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Snp->SnpMode.State != EfiSimpleNetworkInitialized) {
+    return EFI_NOT_STARTED;
+  }
+  
+  Snp = INSTANCE_FROM_SNP_THIS (This);
+  
+  if (EFI_ERROR (EfiAcquireLockOrFail (&Snp->Lock))) {
+    return EFI_ACCESS_DENIED;
+  }
+  
+  Snp->MacDriver.RxCurrentDescriptorNum = Snp->MacDriver.RxNextDescriptorNum;
+  DescNum = Snp->MacDriver.RxCurrentDescriptorNum;
+  RxDescriptor = Snp->MacDriver.RxdescRing[0]+(DescNum);
+  
+  RawData = (UINT8*) Data;
+
+  DesciptorStatus = RxDescriptor->Tdes0;
+
+  if (DesciptorStatus & ((UINT32)RDES0_OWN)) {
+	goto ReleaseLock;
+  }
+
+
+  if (DesciptorStatus & RDES0_SAF) {
+    DEBUG ((EFI_D_WARN, "SNP:DXE: Rx Descritpor Status Error: Source Address Filter Fail\n"));
+    return EFI_DEVICE_ERROR;
+  }
+
+  if (DesciptorStatus & RDES0_AFM) {
+    DEBUG ((EFI_D_WARN, "SNP:DXE: Rx Descritpor Status Error: Destination Address Filter Fail\n"));
+    return EFI_DEVICE_ERROR;
+  }
+
+  if (DesciptorStatus & RDES0_ES) {
+    // Check for errors
+    if (DesciptorStatus & RDES0_RE) {
+      DEBUG ((EFI_D_WARN, "SNP:DXE: Rx Descritpor Status Error: Receive Error\n"));
+    }
+    if (DesciptorStatus & RDES0_DE) {
+      DEBUG ((EFI_D_WARN, "SNP:DXE: Rx Descritpor Status Error: Receive Error\n"));
+    }
+    if (DesciptorStatus & RDES0_RWT) {
+      DEBUG ((EFI_D_WARN, "SNP:DXE: Rx Descritpor Status Error: Watchdog Timeout\n"));
+    }
+    if (DesciptorStatus & RDES0_LC) {
+      DEBUG ((EFI_D_WARN, "SNP:DXE: Rx Descritpor Status Error: Late Collision\n"));
+    }
+    if (DesciptorStatus & RDES0_GF) {
+      DEBUG ((EFI_D_WARN, "SNP:DXE: Rx Descritpor Status Error: Giant Frame\n"));
+    }
+    if (DesciptorStatus & RDES0_OE) {
+      DEBUG ((EFI_D_WARN, "SNP:DXE: Rx Descritpor Status Error: Overflow Error\n"));
+    }
+    if (DesciptorStatus & RDES0_LE) {
+      DEBUG ((EFI_D_WARN, "SNP:DXE: Rx Descritpor Status Error:Length Error\n"));
+    }
+    if (DesciptorStatus & RDES0_DBE) {
+      DEBUG ((EFI_D_WARN, "SNP:DXE: Rx Descritpor Status Error: Dribble Bit Error\n"));
+    }
+
+    // Check descriptor error status
+    if (DesciptorStatus & RDES0_CE) {
+      DEBUG ((EFI_D_WARN, "SNP:DXE: Rx Descritpor Status Error: CRC Error\n"));
+    }
+    return EFI_DEVICE_ERROR;
+  }
+
+  Length = (DesciptorStatus >> RDES0_FL_SHIFT) & RDES0_FL_MASK;
+  if (!Length) {
+    DEBUG ((EFI_D_WARN, "SNP:DXE: Error: Invalid Frame Packet length \r\n"));
+    return EFI_NOT_READY;
+  }
+  // Check buffer size
+  if (*BuffSize < Length) {
+    DEBUG ((EFI_D_WARN, "SNP:DXE: Error: Buffer size is too small\n"));
+    return EFI_BUFFER_TOO_SMALL;
+  }
+  *BuffSize = Length;
+  
+  if (HdrSize != NULL)
+    *HdrSize = Snp->SnpMode.MediaHeaderSize;
+
+  CopyMem (RawData, (VOID*)(UINTN) RxDescriptor->Addr, *BuffSize);
+
+  if (DstAddr != NULL) {
+    Dst.Addr[0] = RawData[0];
+    Dst.Addr[1] = RawData[1];
+    Dst.Addr[2] = RawData[2];
+    Dst.Addr[3] = RawData[3];
+    Dst.Addr[4] = RawData[4];
+    Dst.Addr[5] = RawData[5];
+    CopyMem (DstAddr, &Dst, NET_ETHER_ADDR_LEN);
+Print(L"received from source address %x %x\n\n", DstAddr, &Dst);
+  }
+ 
+  // Get the source address
+  if (SrcAddr != NULL) {
+    Src.Addr[0] = RawData[6];
+    Src.Addr[1] = RawData[7];
+    Src.Addr[2] = RawData[8];
+    Src.Addr[3] = RawData[9];
+    Src.Addr[4] = RawData[10];
+    Src.Addr[5] = RawData[11];
+Print(L"received from source address %x %x\n\n", SrcAddr, &Src);
+    CopyMem (SrcAddr,&Src, NET_ETHER_ADDR_LEN);
+  }
+
+  // Get the protocol
+  if (Protocol != NULL) {
+   *Protocol = NTOHS (RawData[12] | (RawData[13] >> 8) | (RawData[14] >> 16) | (RawData[15] >> 24));
+  }
+
+  RxDescriptor->Tdes0 |= (UINT32)RDES0_OWN;
+
+  DescNum++;
+
+  if (DescNum >= CONFIG_RX_DESCR_NUM)
+    DescNum = 0;
+
+  Snp->MacDriver.RxNextDescriptorNum = DescNum;
+  
+  EfiReleaseLock (&Snp->Lock);
+  
+  return EFI_SUCCESS;
+  
+  ReleaseLock:
+  EfiReleaseLock (&Snp->Lock);
+  return EFI_NOT_READY;
+  
+}
+
diff --git a/Silicon/DesignWare/Drivers/DwEmacSnpDxe/EmacDxeUtil.c b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/EmacDxeUtil.c
new file mode 100755
index 000000000000..a7f29f6cd0c7
--- /dev/null
+++ b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/EmacDxeUtil.c
@@ -0,0 +1,684 @@
+/** @file
+
+  Copyright (c) 2011 - 2019, Intel Corporaton. All rights reserved.
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+  
+  The original software modules are licensed as follows:
+
+  Copyright (c) 2012 - 2014, ARM Limited. All rights reserved.
+  Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD 3 Clause LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include "EmacDxeUtil.h"
+#include "PhyDxeUtil.h"
+
+VOID
+EFIAPI
+EmacSetMacAddress (
+  IN EFI_MAC_ADDRESS  *MacAddress,
+  IN UINT32            MacBaseAddress
+  )
+{
+  DEBUG ((EFI_D_INFO,"SNP:MAC: %a ()\r\n", __FUNCTION__));
+
+  // Note: This MAC_ADDR0 registers programming sequence cannot be swap:
+  // Must program HIGH Offset first before LOW Offset
+  // because synchronization is triggered when MAC Address0 Low Register are written.
+  MmioWrite32 (MacBaseAddress +DW_EMAC_GMACGRP_MAC_ADDRESS0_HIGH_OFST,
+               (UINT32)(MacAddress->Addr[4] & 0xFF) |
+                      ((MacAddress->Addr[5] & 0xFF) << 8)
+                    );
+  // MacAddress->Addr[0,1,2] is the 3 bytes OUI
+  MmioWrite32 (MacBaseAddress + DW_EMAC_GMACGRP_MAC_ADDRESS0_LOW_OFST,
+                       (MacAddress->Addr[0] & 0xFF) |
+                      ((MacAddress->Addr[1] & 0xFF) << 8) |
+                      ((MacAddress->Addr[2] & 0xFF) << 16) |
+                      ((MacAddress->Addr[3] & 0xFF) << 24)
+                    );
+
+  DEBUG ((EFI_D_INFO, "SNP:MAC: gmacgrp_mac_address0_low  = 0x%08X \r\n", MmioRead32 (MacBaseAddress + DW_EMAC_GMACGRP_MAC_ADDRESS0_LOW_OFST)));
+  DEBUG ((EFI_D_INFO, "SNP:MAC: gmacgrp_mac_address0_high = 0x%08X \r\n", MmioRead32 (MacBaseAddress +DW_EMAC_GMACGRP_MAC_ADDRESS0_HIGH_OFST)));
+}
+
+
+VOID
+EFIAPI
+EmacReadMacAddress (
+  OUT EFI_MAC_ADDRESS *MacAddress,
+  IN UINT32            MacBaseAddress
+  )
+{
+  UINT32          MacAddrHighValue;
+  UINT32          MacAddrLowValue;
+
+  DEBUG ((EFI_D_INFO, "SNP:MAC: %a ()\r\n", __FUNCTION__));
+
+  // Read the Mac Addr high register
+  MacAddrHighValue = (MmioRead32 (MacBaseAddress +DW_EMAC_GMACGRP_MAC_ADDRESS0_HIGH_OFST) & 0xFFFF);
+  // Read the Mac Addr low register
+  MacAddrLowValue = MmioRead32 (MacBaseAddress + DW_EMAC_GMACGRP_MAC_ADDRESS0_LOW_OFST);
+
+  SetMem (MacAddress, sizeof(*MacAddress), 0);
+  MacAddress->Addr[0] = (MacAddrLowValue & 0xFF);
+  MacAddress->Addr[1] = (MacAddrLowValue & 0xFF00) >> 8;
+  MacAddress->Addr[2] = (MacAddrLowValue & 0xFF0000) >> 16;
+  MacAddress->Addr[3] = (MacAddrLowValue & 0xFF000000) >> 24;
+  MacAddress->Addr[4] = (MacAddrHighValue & 0xFF);
+  MacAddress->Addr[5] = (MacAddrHighValue & 0xFF00) >> 8;
+
+  DEBUG ((EFI_D_INFO, "SNP:MAC: MAC Address = %02X:%02X:%02X:%02X:%02X:%02X\r\n",
+    MacAddress->Addr[0], MacAddress->Addr[1], MacAddress->Addr[2],
+    MacAddress->Addr[3], MacAddress->Addr[4], MacAddress->Addr[5]
+  ));
+
+}
+
+EFI_STATUS
+EFIAPI
+EmacDxeInitialization (
+  IN EMAC_DRIVER* EmacDriver,
+  IN UINT32 MacBaseAddress
+  )
+{
+  DEBUG ((EFI_D_INFO, "SNP:MAC: %a ()\r\n", __FUNCTION__));
+
+  // Init EMAC DMA
+  EmacDmaInit (EmacDriver, MacBaseAddress);
+
+  return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+EmacDmaInit (
+  IN   EMAC_DRIVER      *EmacDriver,
+  IN   UINT32           MacBaseAddress
+  )
+{
+  UINT32 DmaConf;
+  UINT32 DmaOpmode;
+  UINT32 InterruptEnable;
+
+  DEBUG ((EFI_D_INFO, "SNP:MAC: %a ()\r\n", __FUNCTION__));
+
+  // This section provides the instructions for initializing the DMA registers in the proper sequence. This
+  // initialization sequence can be done after the EMAC interface initialization has been completed. Perform
+  // the following steps to initialize the DMA:
+  // 1. Provide a software reset to reset all of the EMAC internal registers and logic. (DMA Register 0 (Bus
+  // Mode Register) – bit 0).
+
+  MmioOr32 (MacBaseAddress +
+             DW_EMAC_DMAGRP_BUS_MODE_OFST,
+             DW_EMAC_DMAGRP_BUS_MODE_SWR_SET_MSK);
+
+  // 2. Wait for the completion of the reset process (poll bit 0 of the DMA Register 0 (Bus Mode Register),
+  // which is only cleared after the reset operation is completed).
+  while (DW_EMAC_DMAGRP_BUS_MODE_SWR_GET (MmioRead32 (MacBaseAddress + DW_EMAC_DMAGRP_BUS_MODE_OFST)));
+
+  // 3. Poll the bits of Register 11 (AHB or AXI Status) to confirm that all previously initiated (before
+  // software reset) or ongoing transactions are complete.
+  // Note: If the application cannot poll the register after soft reset (because of performance reasons), then
+  // it is recommended that you continue with the next steps and check this register again (as
+  // mentioned in 12 on page 1-72) before triggering the DMA operations.†
+
+  // 4. Program the following fields to initialize the Bus Mode Register by setting values in DMA Register 0
+  // (Bus Mode Register):
+  // • Mixed Burst and AAL
+  // • Fixed burst or undefined burst
+  // • Burst length values and burst mode values
+  // • Descriptor Length (only valid if Ring Mode is used)
+  // • TX and RX DMA Arbitration scheme
+  // 5. Program the interface options in Register 10 (AXI Bus Mode Register). If fixed burst-length is enabled,
+  // then select the maximum burst-length possible on the bus (bits[7:1]).†
+
+  DmaConf = DW_EMAC_DMAGRP_BUS_MODE_FB_SET_MSK | DW_EMAC_DMAGRP_BUS_MODE_PBL_SET_MSK | DW_EMAC_DMAGRP_BUS_MODE_PR_SET_MSK;
+  MmioOr32 (MacBaseAddress +
+            DW_EMAC_DMAGRP_BUS_MODE_OFST,
+            DmaConf);
+
+  // 6. Create a proper descriptor chain for transmit and receive. In addition, ensure that the receive descriptors
+  // are owned by DMA (bit 31 of descriptor should be set). When OSF mode is used, at least two
+  // descriptors are required.
+  // 7. Make sure that your software creates three or more different transmit or receive descriptors in the
+  // chain before reusing any of the descriptors.
+  // 8. Initialize receive and transmit descriptor list address with the base address of the transmit and receive
+  // descriptor (Register 3 (Receive Descriptor List Address Register) and Register 4 (Transmit Descriptor
+  // List Address Register) respectively).
+  
+  EmacSetupTxdesc (EmacDriver, MacBaseAddress);
+  EmacSetupRxdesc (EmacDriver, MacBaseAddress);
+
+  // 9. Program the following fields to initialize the mode of operation in Register 6 (Operation Mode
+  // Register):
+  // • Receive and Transmit Store And Forward†
+  // • Receive and Transmit Threshold Control (RTC and TTC)†
+  // • Hardware Flow Control enable†
+  // • Flow Control Activation and De-activation thresholds for MTL Receive and Transmit FIFO buffers
+  // (RFA and RFD)†
+  // • Error frame and undersized good frame forwarding enable†
+  // • OSF Mode†
+
+  DmaOpmode = DW_EMAC_DMAGRP_OPERATION_MODE_FTF_SET_MSK | DW_EMAC_DMAGRP_OPERATION_MODE_TSF_SET_MSK;
+  MmioOr32 (MacBaseAddress +
+            DW_EMAC_DMAGRP_OPERATION_MODE_OFST,
+            DmaOpmode);
+  //while (DW_EMAC_DMAGRP_OPERATION_MODE_FTF_GET (MmioRead32 (MacBaseAddress + DW_EMAC_DMAGRP_OPERATION_MODE_OFST)));
+ 
+  // 10.Clear the interrupt requests, by writing to those bits of the status register (interrupt bits only) that are
+  // set. For example, by writing 1 into bit 16, the normal interrupt summary clears this bit (DMA Register 5 (Status Register)).
+  MmioOr32 (MacBaseAddress +
+            DW_EMAC_DMAGRP_STATUS_OFST,
+            0x1FFFF);
+
+  // 11.Enable the interrupts by programming Register 7 (Interrupt Enable Register).
+  InterruptEnable = DW_EMAC_DMAGRP_INTERRUPT_ENABLE_TIE_SET_MSK |
+                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_RIE_SET_MSK |
+                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_NIE_SET_MSK |
+                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_AIE_SET_MSK |
+                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_FBE_SET_MSK |
+                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_UNE_SET_MSK |
+                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_TSE_SET_MSK |
+                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_TUE_SET_MSK |
+                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_TJE_SET_MSK |
+                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_OVE_SET_MSK |
+                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_RUE_SET_MSK |
+                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_RSE_SET_MSK |
+                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_RWE_SET_MSK |
+                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_ETE_SET_MSK |
+                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_ERE_SET_MSK;
+   MmioWrite32 (MacBaseAddress +
+                DW_EMAC_DMAGRP_INTERRUPT_ENABLE_OFST,
+                InterruptEnable);
+
+  // 12.Read Register 11 (AHB or AXI Status) to confirm that all previous transactions are complete.†
+  // Note: If any previous transaction is still in progress when you read the Register 11 (AHB or AXI
+  // Status), then it is strongly recommended to check the slave components addressed by the
+  // master interface.
+  if (MmioRead32 (MacBaseAddress + DW_EMAC_DMAGRP_AHB_OR_AXI_STATUS_OFST) != 0) {
+    DEBUG ((EFI_D_INFO, "SNP:MAC: Error! Previous AXI transaction is still in progress\r\n"));
+    //check the slave components addressed by the master interface
+    return EFI_DEVICE_ERROR;
+  }
+
+  DmaOpmode = DW_EMAC_DMAGRP_OPERATION_MODE_ST_SET_MSK | DW_EMAC_DMAGRP_OPERATION_MODE_SR_SET_MSK;
+  MmioOr32 (MacBaseAddress +
+            DW_EMAC_DMAGRP_OPERATION_MODE_OFST,
+            DmaOpmode);
+
+  return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+EmacSetupTxdesc (
+  IN EMAC_DRIVER *EmacDriver,
+  IN UINT32 MacBaseAddress
+ )
+{
+  INTN Index;
+  DESIGNWARE_HW_DESCRIPTOR *TxDescriptor;
+
+  for (Index = 0; Index < CONFIG_TX_DESCR_NUM; Index++) {
+	TxDescriptor = (VOID*)EmacDriver->TxdescRingMap[0]+(Index*16);;
+	TxDescriptor->Addr = (UINT32)(UINTN) EmacDriver->TxBufferMap[0] + (Index*2048);
+	TxDescriptor->AddrNext = (UINT32)(UINTN) EmacDriver->TxdescRingMap[0] + ((Index + 1)*16);
+	TxDescriptor->Tdes0 = TDES0_TXCHAIN;
+    TxDescriptor->Tdes1 = 0;
+  }
+
+  // Correcting the last pointer of the chain
+  TxDescriptor->AddrNext = (UINT32)(UINTN) EmacDriver->TxdescRingMap[0];
+
+  // Write the address of tx descriptor list
+  MmioWrite32(MacBaseAddress +
+              DW_EMAC_DMAGRP_TRANSMIT_DESCRIPTOR_LIST_ADDRESS_OFST,
+              (UINT32)(UINTN) EmacDriver->TxdescRingMap[0]);
+
+  // Initialize the descriptor number
+  EmacDriver->TxCurrentDescriptorNum = 0;
+  EmacDriver->TxNextDescriptorNum = 0;
+  
+  return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+EmacSetupRxdesc (
+  IN EMAC_DRIVER *EmacDriver,
+  IN UINT32 MacBaseAddress
+  )
+{
+  INTN                      Index;
+  DESIGNWARE_HW_DESCRIPTOR *RxDescriptor;
+
+  for (Index = 0; Index < CONFIG_RX_DESCR_NUM; Index++) {
+	RxDescriptor = (VOID*) (EmacDriver->RxdescRingMap[0] + (Index*16));
+    RxDescriptor->Addr = (UINT32)(UINTN) EmacDriver->RxBufferMap[0] + (Index*2048);
+    RxDescriptor->AddrNext = (UINT32)(UINTN) EmacDriver->RxdescRingMap[0] + ((Index + 1)*16);
+    RxDescriptor->Tdes0 = RDES0_OWN;
+    RxDescriptor->Tdes1 = RDES1_CHAINED | RX_MAX_PACKET;
+  }
+
+  // Correcting the last pointer of the chain
+  RxDescriptor->AddrNext = (UINT32)(UINTN) EmacDriver->RxdescRingMap[0];
+
+  // Write the address of tx descriptor list
+  MmioWrite32(MacBaseAddress +
+              DW_EMAC_DMAGRP_RECEIVE_DESCRIPTOR_LIST_ADDRESS_OFST,
+              (UINT32)(UINTN) EmacDriver->RxdescRingMap[0]);
+
+  // Initialize the descriptor number
+  EmacDriver->RxCurrentDescriptorNum = 0;
+  EmacDriver->RxNextDescriptorNum = 0;
+ 
+  return EFI_SUCCESS;
+}
+
+
+VOID
+EFIAPI
+EmacStartTransmission (
+  IN UINT32 MacBaseAddress
+  )
+{
+  DEBUG ((EFI_D_INFO, "SNP:MAC: %a ()\r\n", __FUNCTION__));
+  MmioOr32 (MacBaseAddress +
+            DW_EMAC_GMACGRP_MAC_CONFIGURATION_OFST,
+            DW_EMAC_GMACGRP_MAC_CONFIGURATION_RE_SET_MSK |
+            DW_EMAC_GMACGRP_MAC_CONFIGURATION_TE_SET_MSK
+            );
+}
+
+
+EFI_STATUS
+EFIAPI
+EmacRxFilters (
+  IN        UINT32 ReceiveFilterSetting,
+  IN        BOOLEAN Reset,
+  IN        UINTN NumMfilter          OPTIONAL,
+  IN        EFI_MAC_ADDRESS *Mfilter  OPTIONAL,
+  IN        UINT32 MacBaseAddress
+  )
+ {
+  UINT32 MacFilter;
+  UINT32 Crc;
+  UINT32 Count;
+  UINT32 HashReg;
+  UINT32 HashBit;
+  UINT32 Reg;
+  UINT32 Val;
+
+  // If reset then clear the filter registers
+  if (Reset) {
+    for (Count = 0; Count < NumMfilter; Count++)
+    {
+      MmioWrite32 (MacBaseAddress + HASH_TABLE_REG(Count), 0x00000000);
+    }
+  }
+
+  // Set MacFilter to the reset value of the  DW_EMAC_GMACGRP_MAC_FRAME_FILTER register.
+  MacFilter =  DW_EMAC_GMACGRP_MAC_FRAME_FILTER_RESET;
+
+  if (ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) {
+    //DEBUG ((EFI_D_INFO, "SNP:MAC: Enable Unicast Frame Reception\n"));
+  }
+
+  if (ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) {
+
+    //DEBUG ((EFI_D_INFO, "SNP:MAC: Enable Hash Multicast Frame Reception\n"));
+    MacFilter |=  DW_EMAC_GMACGRP_MAC_FRAME_FILTER_HMC_SET_MSK;
+
+    // Set the hash tables
+    if ((NumMfilter > 0) && (!Reset)) {
+      // Go through each filter address and set appropriate bits on hash table
+      for (Count = 0; Count < NumMfilter; Count++) {
+        // Generate a 32-bit CRC
+        Crc = GenEtherCrc32 (&Mfilter[Count], 6);
+        // reserve CRC + take upper 8 bit = take lower 8 bit and reverse it
+        Val = BitReverse(Crc & 0xff);
+        // The most significant bits determines the register to be used (Hash Table Register X),
+        // and the least significant five bits determine the bit within the register.
+        // For example, a hash value of 8b'10111111 selects Bit 31 of the Hash Table Register 5.
+        HashReg = (Val >> 5);
+        HashBit = (Val & 31);
+
+        Reg = MmioRead32(MacBaseAddress + HASH_TABLE_REG(HashReg));
+        // set 1 to HashBit of HashReg
+        // for example, set 1 to bit 31 to Reg 5 as in above example
+        Reg |= (1 << HashBit);
+        MmioWrite32(MacBaseAddress + HASH_TABLE_REG(HashReg), Reg);
+      }
+    }
+  }
+
+  if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) == 0) {
+    MacFilter |=  DW_EMAC_GMACGRP_MAC_FRAME_FILTER_DBF_SET_MSK;
+  } else if (ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) {
+  }
+
+  if (ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) {
+    MacFilter |=  DW_EMAC_GMACGRP_MAC_FRAME_FILTER_PR_SET_MSK;
+  }
+
+  if (ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) {
+    MacFilter |= ( DW_EMAC_GMACGRP_MAC_FRAME_FILTER_PM_SET_MSK);
+  }
+
+  // Set MacFilter to EMAC register
+  MmioWrite32 (MacBaseAddress +  DW_EMAC_GMACGRP_MAC_FRAME_FILTER_OFST, MacFilter);
+  return EFI_SUCCESS;
+}
+
+
+UINT32
+EFIAPI
+GenEtherCrc32 (
+  IN    EFI_MAC_ADDRESS *Mac,
+  IN    UINT32 AddrLen
+  )
+{
+  INT32  Iter;
+  UINT32 Remainder;
+  UINT8  *Ptr;
+
+  Iter = 0;
+  Remainder = 0xFFFFFFFF;    // 0xFFFFFFFF is standard seed for Ethernet
+
+  // Convert Mac Address to array of bytes
+  Ptr = (UINT8*)Mac;
+
+  // Generate the Crc bit-by-bit (LSB first)
+  while (AddrLen--) {
+    Remainder ^= *Ptr++;
+    for (Iter = 0;Iter < 8;Iter++) {
+      // Check if exponent is set
+      if (Remainder & 1) {
+        Remainder = (Remainder >> 1) ^ CRC_POLYNOMIAL;
+      } else {
+        Remainder = (Remainder >> 1) ^ 0;
+      }
+    }
+  }
+
+  return (~Remainder);
+}
+
+
+STATIC CONST UINT8 NibbleTab[] = {
+    /* 0x0 0000 -> 0000 */  0x0,
+    /* 0x1 0001 -> 1000 */  0x8,
+    /* 0x2 0010 -> 0100 */  0x4,
+    /* 0x3 0011 -> 1100 */  0xc,
+    /* 0x4 0100 -> 0010 */  0x2,
+    /* 0x5 0101 -> 1010 */  0xa,
+    /* 0x6 0110 -> 0110 */  0x6,
+    /* 0x7 0111 -> 1110 */  0xe,
+    /* 0x8 1000 -> 0001 */  0x1,
+    /* 0x9 1001 -> 1001 */  0x9,
+    /* 0xa 1010 -> 0101 */  0x5,
+    /* 0xb 1011 -> 1101 */  0xd,
+    /* 0xc 1100 -> 0011 */  0x3,
+    /* 0xd 1101 -> 1011 */  0xb,
+    /* 0xe 1110 -> 0111 */  0x7,
+    /* 0xf 1111 -> 1111 */  0xf
+};
+
+UINT8
+EFIAPI
+BitReverse (
+  UINT8 X
+  )
+{
+  return (NibbleTab[X & 0xf] << 4) | NibbleTab[X >> 4];
+}
+
+
+VOID
+EFIAPI
+EmacStopTxRx (
+   IN    UINT32 MacBaseAddress
+  )
+{
+  DEBUG ((EFI_D_INFO, "SNP:MAC: %a ()\r\n", __FUNCTION__));
+
+  // Stop DMA TX
+  MmioAnd32 (MacBaseAddress +
+            DW_EMAC_DMAGRP_OPERATION_MODE_OFST,
+            DW_EMAC_DMAGRP_OPERATION_MODE_ST_CLR_MSK);
+
+  // Flush TX
+  MmioOr32 (MacBaseAddress +
+            DW_EMAC_DMAGRP_OPERATION_MODE_OFST,
+            DW_EMAC_DMAGRP_OPERATION_MODE_FTF_SET_MSK);
+
+  // Stop transmitters
+  MmioAnd32 (MacBaseAddress +
+            DW_EMAC_GMACGRP_MAC_CONFIGURATION_OFST,
+            DW_EMAC_GMACGRP_MAC_CONFIGURATION_RE_CLR_MSK &
+            DW_EMAC_GMACGRP_MAC_CONFIGURATION_TE_CLR_MSK);
+
+  // Stop DMA RX
+  MmioAnd32 (MacBaseAddress +
+            DW_EMAC_DMAGRP_OPERATION_MODE_OFST,
+            DW_EMAC_DMAGRP_OPERATION_MODE_SR_CLR_MSK);
+
+}
+
+
+EFI_STATUS
+EFIAPI
+EmacDmaStart (
+  IN UINT32 MacBaseAddress
+  )
+{
+  // Start the transmission
+  MmioWrite32(MacBaseAddress +
+              DW_EMAC_DMAGRP_TRANSMIT_POLL_DEMAND_OFST,
+              0x1);
+  return EFI_SUCCESS;
+}
+
+
+VOID
+EFIAPI
+EmacGetDmaStatus (
+  OUT   UINT32 *IrqStat  OPTIONAL,
+  IN    UINT32 MacBaseAddress
+  )
+{
+  UINT32  DmaStatus;
+  UINT32  ErrorBit;
+  UINT32  Mask = 0;
+
+  DmaStatus = MmioRead32 (MacBaseAddress +
+                           DW_EMAC_DMAGRP_STATUS_OFST);
+  if (DmaStatus & DW_EMAC_DMAGRP_STATUS_NIS_SET_MSK) {
+    Mask |= DW_EMAC_DMAGRP_STATUS_NIS_SET_MSK;
+    // Rx interrupt
+    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_RI_SET_MSK) {
+      *IrqStat |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
+      Mask |= DW_EMAC_DMAGRP_STATUS_RI_SET_MSK;
+    } else {
+      *IrqStat &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
+    }
+    // Tx interrupt
+    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_TI_SET_MSK) {
+      *IrqStat |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
+      Mask |= DW_EMAC_DMAGRP_STATUS_TI_SET_MSK;
+    } else {
+      *IrqStat &= ~EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
+    }
+    // Tx Buffer
+    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_TU_SET_MSK){
+      Mask |= DW_EMAC_DMAGRP_STATUS_TU_SET_MSK;
+      }
+    // Early receive interrupt
+    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_ERI_SET_MSK) {
+      Mask |= DW_EMAC_DMAGRP_STATUS_ERI_SET_MSK;
+    }
+  }
+  if (DmaStatus & DW_EMAC_DMAGRP_STATUS_AIS_SET_MSK) {
+    Mask |= DW_EMAC_DMAGRP_STATUS_AIS_SET_MSK;
+    // Transmit process stop
+    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_TPS_SET_MSK) {
+      DEBUG ((EFI_D_INFO, "SNP:MAC: Transmit process stop\n"));
+      Mask |= DW_EMAC_DMAGRP_STATUS_TPS_SET_MSK;
+    }
+    // Transmit jabber timeout
+    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_TJT_SET_MSK) {
+      DEBUG ((EFI_D_INFO, "SNP:MAC: Transmit jabber timeout\n"));
+      Mask |= DW_EMAC_DMAGRP_STATUS_TJT_SET_MSK;
+    }
+    // Receive FIFO overflow
+    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_OVF_SET_MSK) {
+      DEBUG ((EFI_D_INFO, "SNP:MAC: Receive FIFO overflow\n"));
+      Mask |= DW_EMAC_DMAGRP_STATUS_OVF_SET_MSK;
+    }
+    // Transmit FIFO underflow
+    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_UNF_SET_MSK) {
+      DEBUG ((EFI_D_INFO, "SNP:MAC: Receive FIFO underflow\n"));
+      Mask |= DW_EMAC_DMAGRP_STATUS_UNF_SET_MSK;
+    }
+    // Receive buffer unavailable
+    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_RU_SET_MSK) {
+      //DEBUG ((EFI_D_INFO, "SNP:MAC: Receive buffer unavailable\n"));
+      Mask |= DW_EMAC_DMAGRP_STATUS_RU_SET_MSK;
+    }
+
+    // Receive process stop
+    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_RPS_SET_MSK) {
+      DEBUG ((EFI_D_INFO, "SNP:MAC: Receive process stop\n"));
+      Mask |= DW_EMAC_DMAGRP_STATUS_RPS_SET_MSK;
+    }
+    // Receive watchdog timeout
+    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_RWT_SET_MSK) {
+      DEBUG ((EFI_D_INFO, "SNP:MAC: Receive watchdog timeout\n"));
+      Mask |= DW_EMAC_DMAGRP_STATUS_RWT_SET_MSK;
+    }
+    // Early transmit interrupt
+    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_ETI_SET_MSK) {
+      //DEBUG ((EFI_D_INFO, "SNP:MAC: Early transmit interrupt\n"));
+      Mask |= DW_EMAC_DMAGRP_STATUS_ETI_SET_MSK;
+    }
+    // Fatal bus error
+    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_FBI_SET_MSK) {
+      DEBUG ((EFI_D_INFO, "SNP:MAC: Fatal bus error:\n"));
+      Mask |= DW_EMAC_DMAGRP_STATUS_FBI_SET_MSK;
+
+      ErrorBit = DW_EMAC_DMAGRP_STATUS_EB_GET (DmaStatus);
+      switch (ErrorBit) {
+        case RX_DMA_WRITE_DATA_TRANSFER_ERROR:
+          DEBUG ((EFI_D_INFO, "SNP:MAC: Rx Dma write data transfer error\n"));
+          break;
+        case TX_DMA_READ_DATA_TRANSFER_ERROR:
+          DEBUG ((EFI_D_INFO, "SNP:MAC: Tx Dma read data transfer error\n"));
+          break;
+        case RX_DMA_DESCRIPTOR_WRITE_ACCESS_ERROR:
+          DEBUG ((EFI_D_INFO, "SNP:MAC: Rx Dma descriptor write access error\n"));
+          break;
+        case RX_DMA_DESCRIPTOR_READ_ACCESS_ERROR:
+          DEBUG ((EFI_D_INFO, "SNP:MAC: Rx Dma descriptor read access error\n"));
+          break;
+        case TX_DMA_DESCRIPTOR_WRITE_ACCESS_ERROR:
+          DEBUG ((EFI_D_INFO, "SNP:MAC: Tx Dma descriptor write access error\n"));
+          break;
+        case TX_DMA_DESCRIPTOR_READ_ACCESS_ERROR:
+          DEBUG ((EFI_D_INFO, "SNP:MAC: Tx Dma descriptor read access error\n"));
+          break;
+        default:
+          DEBUG ((EFI_D_INFO, "SNP:MAC: Undefined error\n"));
+          break;
+      }
+    }
+  }
+  MmioOr32 (MacBaseAddress +
+            DW_EMAC_DMAGRP_STATUS_OFST,
+            Mask);
+}
+
+
+VOID
+EFIAPI
+EmacGetStatistic (
+  OUT EFI_NETWORK_STATISTICS* Statistic,
+  IN UINT32 MacBaseAddress
+  )
+{
+  EFI_NETWORK_STATISTICS* Stats;
+
+  DEBUG ((EFI_D_INFO, "SNP:MAC: %a ()\r\n", __FUNCTION__));
+
+  // Allocate Resources
+  Stats = AllocateZeroPool (sizeof (EFI_NETWORK_STATISTICS));
+  if (Stats == NULL) {
+    return;
+  }
+
+  Stats->RxTotalFrames     = MmioRead32 (MacBaseAddress + DW_EMAC_GMACGRP_RXFRAMECOUNT_GB_OFST);
+  Stats->RxUndersizeFrames = MmioRead32 (MacBaseAddress + DW_EMAC_GMACGRP_RXUNDERSIZE_G_OFST);
+  Stats->RxOversizeFrames  = MmioRead32 (MacBaseAddress + DW_EMAC_GMACGRP_RXOVERSIZE_G_OFST);
+  Stats->RxUnicastFrames   = MmioRead32 (MacBaseAddress + DW_EMAC_GMACGRP_RXUNICASTFRAMES_G_OFST);
+  Stats->RxBroadcastFrames = MmioRead32 (MacBaseAddress + DW_EMAC_GMACGRP_RXBROADCASTFRAMES_G_OFST);
+  Stats->RxMulticastFrames = MmioRead32 (MacBaseAddress + DW_EMAC_GMACGRP_RXMULTICASTFRAMES_G_OFST);
+  Stats->RxCrcErrorFrames  = MmioRead32 (MacBaseAddress + DW_EMAC_GMACGRP_RXCRCERROR_OFST);
+  Stats->RxTotalBytes      = MmioRead32 (MacBaseAddress + DW_EMAC_GMACGRP_RXOCTETCOUNT_GB_OFST);
+  Stats->RxGoodFrames      = Stats->RxUnicastFrames + Stats->RxBroadcastFrames + Stats->RxMulticastFrames;
+
+  Stats->TxTotalFrames     = MmioRead32 (MacBaseAddress + DW_EMAC_GMACGRP_TXFRAMECOUNT_GB_OFST);
+  Stats->TxGoodFrames      = MmioRead32 (MacBaseAddress + DW_EMAC_GMACGRP_TXFRAMECOUNT_G_OFST);
+  Stats->TxOversizeFrames  = MmioRead32 (MacBaseAddress + DW_EMAC_GMACGRP_TXOVERSIZE_G_OFST);
+  Stats->TxUnicastFrames   = MmioRead32 (MacBaseAddress + DW_EMAC_GMACGRP_TXUNICASTFRAMES_GB_OFST);
+  Stats->TxBroadcastFrames = MmioRead32 (MacBaseAddress + DW_EMAC_GMACGRP_TXBROADCASTFRAMES_G_OFST);
+  Stats->TxMulticastFrames = MmioRead32 (MacBaseAddress + DW_EMAC_GMACGRP_TXMULTICASTFRAMES_G_OFST);
+  Stats->TxTotalBytes      = MmioRead32 (MacBaseAddress + DW_EMAC_GMACGRP_TXOCTETCOUNT_GB_OFST);
+  Stats->Collisions        = MmioRead32 (MacBaseAddress + DW_EMAC_GMACGRP_TXLATECOL_OFST) +
+                             MmioRead32 (MacBaseAddress + DW_EMAC_GMACGRP_TXEXESSCOL_OFST);
+
+  // Fill in the statistics
+  CopyMem(Statistic, Stats, sizeof(EFI_NETWORK_STATISTICS));
+}
+
+
+VOID
+EFIAPI
+EmacConfigAdjust (
+  IN UINT32 Speed,
+  IN UINT32 Duplex,
+  IN UINT32 MacBaseAddress
+  )
+{
+  UINT32 Config;
+
+  Config =0;
+  if (Speed != SPEED_1000)
+   Config |= DW_EMAC_GMACGRP_MAC_CONFIGURATION_PS_SET_MSK;
+
+  if (Speed == SPEED_100)
+    Config |= DW_EMAC_GMACGRP_MAC_CONFIGURATION_FES_SET_MSK;
+
+  if (Duplex == DUPLEX_FULL)
+    Config |= DW_EMAC_GMACGRP_MAC_CONFIGURATION_DM_SET_MSK;
+
+  MmioOr32 (MacBaseAddress +
+            DW_EMAC_GMACGRP_MAC_CONFIGURATION_OFST,
+            DW_EMAC_GMACGRP_MAC_CONFIGURATION_BE_SET_MSK |
+            DW_EMAC_GMACGRP_MAC_CONFIGURATION_DO_SET_MSK |
+            Config);
+
+}
diff --git a/Silicon/DesignWare/Drivers/DwEmacSnpDxe/PhyDxeUtil.c b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/PhyDxeUtil.c
new file mode 100755
index 000000000000..65a53b651814
--- /dev/null
+++ b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/PhyDxeUtil.c
@@ -0,0 +1,621 @@
+/** @file
+
+  Copyright (c) 2011 - 2019, Intel Corporaton. All rights reserved.
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+  
+  The original software modules are licensed as follows:
+
+  Copyright (c) 2012 - 2014, ARM Limited. All rights reserved.
+  Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD 3 Clause LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+
+#include "PhyDxeUtil.h"
+#include "EmacDxeUtil.h"
+
+EFI_STATUS
+EFIAPI
+PhyDxeInitialization (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      MacBaseAddress
+  )
+{
+  DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
+
+  // initialize the phyaddr
+  PhyDriver->PhyAddr = 0;
+  PhyDriver->PhyCurrentLink = LINK_DOWN;
+  PhyDriver->PhyOldLink = LINK_DOWN;
+
+  if (PhyDetectDevice (PhyDriver, MacBaseAddress) != EFI_SUCCESS) {
+    return EFI_NOT_FOUND;
+  }
+
+  PhyConfig (PhyDriver, MacBaseAddress);
+
+  return EFI_SUCCESS;
+}
+
+
+// PHY detect device
+EFI_STATUS
+EFIAPI
+PhyDetectDevice (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      MacBaseAddress
+  )
+{
+  UINT32 PhyAddr;
+
+  DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
+
+  for (PhyAddr = 0; PhyAddr < 32; PhyAddr++) {
+    if (PhyReadId (PhyAddr, MacBaseAddress) == EFI_SUCCESS) {
+      PhyDriver->PhyAddr = PhyAddr;
+      return EFI_SUCCESS;
+    }
+  }
+  Print (L"SNP:PHY: Fail to detect Ethernet PHY!\r\n");
+  return EFI_NOT_FOUND;
+}
+
+
+EFI_STATUS
+EFIAPI
+PhyConfig (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      MacBaseAddress
+  )
+{
+  EFI_STATUS Status;
+
+  DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
+
+  Status = PhySoftReset (PhyDriver, MacBaseAddress);
+  if (EFI_ERROR (Status)) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  // Configure TX/RX Skew
+  PhyConfigSkew (PhyDriver, MacBaseAddress);
+
+  // Read back and display Skew settings
+  PhyDisplayConfigSkew (PhyDriver, MacBaseAddress);
+
+  // Configure AN FLP Burst Trasmit timing interval
+  PhyConfigFlpBurstTiming (PhyDriver, MacBaseAddress);
+  PhyDisplayFlpBurstTiming (PhyDriver, MacBaseAddress);
+
+  // Configure AN and Advertise
+  PhyAutoNego (PhyDriver,MacBaseAddress);
+
+  return EFI_SUCCESS;
+}
+
+
+// Perform PHY software reset
+EFI_STATUS
+EFIAPI
+PhySoftReset (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      MacBaseAddress
+  )
+{
+  UINT32        TimeOut;
+  UINT32        Data32;
+  EFI_STATUS    Status;
+
+  DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
+
+  // PHY Basic Control Register reset
+  PhyWrite (PhyDriver->PhyAddr, PHY_BASIC_CTRL, PHYCTRL_RESET, MacBaseAddress);
+
+  // Wait for completion
+  TimeOut = 0;
+  do {
+    // Read PHY_BASIC_CTRL register from PHY
+    Status = PhyRead (PhyDriver->PhyAddr, PHY_BASIC_CTRL, &Data32, MacBaseAddress);
+    if (EFI_ERROR(Status)) {
+      return Status;
+    }
+    // Wait until PHYCTRL_RESET become zero
+    if ((Data32 & PHYCTRL_RESET) == 0) {
+      break;
+    }
+    MicroSecondDelay(1);
+  } while (TimeOut++ < PHY_TIMEOUT);
+  if (TimeOut >= PHY_TIMEOUT) {
+    DEBUG ((EFI_D_INFO, "SNP:PHY: ERROR! PhySoftReset timeout\n"));
+    return EFI_TIMEOUT;
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+// PHY read ID
+EFI_STATUS
+EFIAPI
+PhyReadId (
+  IN UINT32  PhyAddr,
+  IN UINT32  MacBaseAddress
+  )
+{
+  EFI_STATUS    Status;
+  UINT32        PhyId1;
+  UINT32        PhyId2;
+
+  //DEBUG ((EFI_D_INFO, "SNP:PHY: %a (0x%02X)\r\n", __FUNCTION__, PhyAddr));
+
+  Status = PhyRead (PhyAddr, PHY_ID1, &PhyId1, MacBaseAddress);
+  if (EFI_ERROR(Status)) return Status;
+  Status = PhyRead (PhyAddr, PHY_ID2, &PhyId2, MacBaseAddress);
+  if (EFI_ERROR(Status)) return Status;
+
+  if (PhyId1 == PHY_INVALID_ID || PhyId2 == PHY_INVALID_ID) {
+    return EFI_NOT_FOUND;
+  }
+
+  DEBUG ((EFI_D_INFO, "SNP:PHY: Ethernet PHY detected. PHY_ID1=0x%04X, PHY_ID2=0x%04X, PHY_ADDR=0x%02X\r\n", PhyId1, PhyId2, PhyAddr));
+  return EFI_SUCCESS;
+}
+
+
+VOID
+EFIAPI
+PhyConfigSkew (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      MacBaseAddress
+  )
+{
+  Phy9031ExtendedWrite(PhyDriver, PHY_KSZ9031_MOD_DATA_NO_POST_INC, PHY_KSZ9031RN_DEV_ADDR, PHY_KSZ9031RN_CONTROL_PAD_SKEW_REG, PHY_KSZ9031RN_CONTROL_PAD_SKEW_VALUE, MacBaseAddress);
+  Phy9031ExtendedWrite(PhyDriver, PHY_KSZ9031_MOD_DATA_NO_POST_INC, PHY_KSZ9031RN_DEV_ADDR, PHY_KSZ9031RN_CLK_PAD_SKEW_REG,     PHY_KSZ9031RN_CLK_PAD_SKEW_VALUE, MacBaseAddress);
+  Phy9031ExtendedWrite(PhyDriver, PHY_KSZ9031_MOD_DATA_NO_POST_INC, PHY_KSZ9031RN_DEV_ADDR, PHY_KSZ9031RN_RX_DATA_PAD_SKEW_REG, PHY_KSZ9031RN_RX_DATA_PAD_SKEW_VALUE, MacBaseAddress);
+  Phy9031ExtendedWrite(PhyDriver, PHY_KSZ9031_MOD_DATA_NO_POST_INC, PHY_KSZ9031RN_DEV_ADDR, PHY_KSZ9031RN_TX_DATA_PAD_SKEW_REG, PHY_KSZ9031RN_TX_DATA_PAD_SKEW_VALUE, MacBaseAddress);
+
+}
+
+
+VOID
+EFIAPI
+PhyDisplayConfigSkew (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      MacBaseAddress
+  )
+{
+  // Display skew configuration
+  DEBUG ((EFI_D_INFO, "SNP:PHY: Control Signal Pad Skew = 0x%04X\r\n", Phy9031ExtendedRead(PhyDriver, PHY_KSZ9031_MOD_DATA_NO_POST_INC, PHY_KSZ9031RN_DEV_ADDR, PHY_KSZ9031RN_CONTROL_PAD_SKEW_REG, MacBaseAddress)));
+  DEBUG ((EFI_D_INFO, "SNP:PHY: RGMII Clock Pad Skew    = 0x%04X\r\n", Phy9031ExtendedRead(PhyDriver, PHY_KSZ9031_MOD_DATA_NO_POST_INC, PHY_KSZ9031RN_DEV_ADDR, PHY_KSZ9031RN_CLK_PAD_SKEW_REG, MacBaseAddress)));
+  DEBUG ((EFI_D_INFO, "SNP:PHY: RGMII RX Data Pad Skew  = 0x%04X\r\n", Phy9031ExtendedRead(PhyDriver, PHY_KSZ9031_MOD_DATA_NO_POST_INC, PHY_KSZ9031RN_DEV_ADDR, PHY_KSZ9031RN_RX_DATA_PAD_SKEW_REG, MacBaseAddress)));
+  DEBUG ((EFI_D_INFO, "SNP:PHY: RGMII TX Data Pad Skew  = 0x%04X\r\n", Phy9031ExtendedRead(PhyDriver, PHY_KSZ9031_MOD_DATA_NO_POST_INC, PHY_KSZ9031RN_DEV_ADDR, PHY_KSZ9031RN_TX_DATA_PAD_SKEW_REG, MacBaseAddress)));
+}
+
+VOID
+EFIAPI
+PhyConfigFlpBurstTiming (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      MacBaseAddress
+  )
+{
+  Phy9031ExtendedWrite(PhyDriver, PHY_KSZ9031_MOD_DATA_NO_POST_INC, PHY_KSZ9031RN_MMD_DEV_ADDR_00, PHY_KSZ9031RN_MMD_D0_FLP_LO_REG, PHY_KSZ9031RN_MMD_D0_FLP_16MS_LO, MacBaseAddress);
+  Phy9031ExtendedWrite(PhyDriver, PHY_KSZ9031_MOD_DATA_NO_POST_INC, PHY_KSZ9031RN_MMD_DEV_ADDR_00, PHY_KSZ9031RN_MMD_D0_FLP_HI_REG, PHY_KSZ9031RN_MMD_D0_FLP_16MS_HI, MacBaseAddress);
+}
+
+VOID
+EFIAPI
+PhyDisplayFlpBurstTiming (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      MacBaseAddress
+  )
+{
+  // Display Auto-Negotiation FLP burst transmit timing
+  DEBUG ((EFI_D_INFO, "SNP:PHY: AN FLP Burst Transmit - LO = 0x%04X\r\n", Phy9031ExtendedRead(PhyDriver, PHY_KSZ9031_MOD_DATA_NO_POST_INC, PHY_KSZ9031RN_MMD_DEV_ADDR_00, PHY_KSZ9031RN_MMD_D0_FLP_LO_REG, MacBaseAddress)));
+  DEBUG ((EFI_D_INFO, "SNP:PHY: AN FLP Burst Transmit - HI = 0x%04X\r\n", Phy9031ExtendedRead(PhyDriver, PHY_KSZ9031_MOD_DATA_NO_POST_INC, PHY_KSZ9031RN_MMD_DEV_ADDR_00, PHY_KSZ9031RN_MMD_D0_FLP_HI_REG, MacBaseAddress)));
+}
+
+// Do auto-negotiation
+EFI_STATUS
+EFIAPI
+PhyAutoNego (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      MacBaseAddress
+  )
+{
+  EFI_STATUS    Status;
+  UINT32        PhyControl;
+  UINT32        PhyStatus;
+  UINT32        Features;
+
+  DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
+
+  // Read PHY Status
+  Status = PhyRead (PhyDriver->PhyAddr, PHY_BASIC_STATUS, &PhyStatus, MacBaseAddress);
+  if (EFI_ERROR(Status)) return Status;
+
+  // Check PHY Status if auto-negotiation is supported
+  if ((PhyStatus & PHYSTS_AUTO_CAP) == 0) {
+    DEBUG ((EFI_D_INFO, "SNP:PHY: Auto-negotiation is not supported.\n"));
+    return EFI_DEVICE_ERROR;
+  }
+
+  // Read PHY Auto-Nego Advertise capabilities register for 10/100 Base-T
+  Status = PhyRead (PhyDriver->PhyAddr, PHY_AUTO_NEG_ADVERT, &Features, MacBaseAddress);
+  if (EFI_ERROR(Status)) return Status;
+
+  // Set Advertise capabilities for 10Base-T/10Base-T full-duplex/100Base-T/100Base-T full-duplex
+  Features |= (PHYANA_10BASET | PHYANA_10BASETFD | PHYANA_100BASETX | PHYANA_100BASETXFD);
+  PhyWrite (PhyDriver->PhyAddr, PHY_AUTO_NEG_ADVERT, Features, MacBaseAddress);
+
+  // Read PHY Auto-Nego Advertise capabilities register for 1000 Base-T
+  Status = PhyRead (PhyDriver->PhyAddr, PHY_1000BASE_T_CONTROL, &Features, MacBaseAddress);
+  if (EFI_ERROR(Status)) return Status;
+
+  // Set Advertise capabilities for 1000 Base-T/1000 Base-T full-duplex
+  Features |= (PHYADVERTISE_1000FULL | PHYADVERTISE_1000HALF);
+  PhyWrite (PhyDriver->PhyAddr, PHY_1000BASE_T_CONTROL, Features, MacBaseAddress);
+
+  // Read control register
+  Status = PhyRead (PhyDriver->PhyAddr, PHY_BASIC_CTRL, &PhyControl, MacBaseAddress);
+  if (EFI_ERROR(Status)) return Status;
+
+  // Enable Auto-Negotiation
+  PhyControl |= PHYCTRL_AUTO_EN;
+  // Restart auto-negotiation
+  PhyControl |= PHYCTRL_RST_AUTO;
+  // Write this configuration
+  PhyWrite (PhyDriver->PhyAddr, PHY_BASIC_CTRL, PhyControl, MacBaseAddress); 
+
+  return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+PhyLinkAdjustEmacConfig (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      MacBaseAddress
+  )
+{
+  UINT32 Speed;
+  UINT32 Duplex;
+  EFI_STATUS Status;
+
+  //DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
+
+  Status = EFI_SUCCESS;
+  Speed = SPEED_10;
+  Duplex = DUPLEX_HALF;
+
+  if (PhyCheckLinkStatus (PhyDriver, MacBaseAddress) == EFI_SUCCESS) {
+    PhyDriver->PhyCurrentLink = LINK_UP;
+  } else {
+    PhyDriver->PhyCurrentLink = LINK_DOWN;
+  }
+
+  if (PhyDriver->PhyOldLink != PhyDriver->PhyCurrentLink) {
+    if (PhyDriver->PhyCurrentLink == LINK_UP) {
+      Print (L"SNP:PHY: Link is up - Network Cable is Plugged\r\n");
+      PhyReadCapability (PhyDriver, &Speed, &Duplex, MacBaseAddress);
+      EmacConfigAdjust (Speed, Duplex, MacBaseAddress);
+      Status = EFI_SUCCESS;
+    } else {
+      Print (L"SNP:PHY: Link is Down - Network Cable is Unplugged?\r\n");
+      Status = EFI_NOT_READY;
+    }
+  } else if (PhyDriver->PhyCurrentLink == LINK_DOWN) {
+    Status = EFI_NOT_READY;
+  }
+
+  PhyDriver->PhyOldLink = PhyDriver->PhyCurrentLink;
+
+  return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+PhyCheckLinkStatus (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      MacBaseAddress
+  )
+{
+  EFI_STATUS    Status;
+  UINT32        Data32;
+  UINTN         TimeOut;
+  UINT32        PhyBasicStatus;
+
+  //DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
+
+  // Get the PHY Status
+  Status = PhyRead (PhyDriver->PhyAddr, PHY_BASIC_STATUS, &PhyBasicStatus, MacBaseAddress);
+  if (EFI_ERROR(Status)) return Status;
+
+  // if Link is already up then dont need to proceed anymore
+  if (PhyBasicStatus & PHYSTS_LINK_STS) {
+    return EFI_SUCCESS;
+  }
+
+  // Wait until it is up or until Time Out
+  TimeOut = 0;
+  do {
+    // Read PHY_BASIC_STATUS register from PHY
+    Status = PhyRead (PhyDriver->PhyAddr, PHY_BASIC_STATUS, &Data32, MacBaseAddress);
+    if (EFI_ERROR(Status)) {
+      return Status;
+    }
+    // Wait until PHYSTS_LINK_STS become one
+    if (Data32 & PHYSTS_LINK_STS) {
+      // Link is up
+      break;
+    }
+    MicroSecondDelay(1);
+  } while (TimeOut++ < PHY_TIMEOUT);
+  if (TimeOut >= PHY_TIMEOUT) {
+    // Link is down
+    return EFI_TIMEOUT;
+  }
+
+  // Wait until autonego process has completed
+  TimeOut = 0;
+  do {
+    // Read PHY_BASIC_STATUS register from PHY
+    Status = PhyRead (PhyDriver->PhyAddr, PHY_BASIC_STATUS, &Data32, MacBaseAddress);
+    if (EFI_ERROR(Status)) {
+      return Status;
+    }
+    // Wait until PHYSTS_AUTO_COMP become one
+    if (Data32 & PHYSTS_AUTO_COMP) {
+      DEBUG ((EFI_D_INFO, "SNP:PHY: Auto Negotiation completed\r\n"));
+      break;
+    }
+    MicroSecondDelay(1);
+  } while (TimeOut++ < PHY_TIMEOUT);
+  if (TimeOut >= PHY_TIMEOUT) {
+    DEBUG ((EFI_D_INFO, "SNP:PHY: Error! Auto Negotiation timeout\n"));
+    return EFI_TIMEOUT;
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+PhyReadCapability (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32* Speed,
+  IN UINT32* Duplex,
+  IN UINT32  MacBaseAddress
+  )
+{
+  EFI_STATUS    Status;
+  UINT32        PartnerAbilityGb;
+  UINT32        AdvertisingGb;
+  UINT32        CommonAbilityGb;
+  UINT32        PartnerAbility;
+  UINT32        Advertising;
+  UINT32        CommonAbility;
+
+  //DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
+
+  // For 1000 Base-T
+
+  Status = PhyRead (PhyDriver->PhyAddr, PHY_1000BASE_T_STATUS, &PartnerAbilityGb, MacBaseAddress);
+  if (EFI_ERROR(Status)) return Status;
+
+  Status = PhyRead (PhyDriver->PhyAddr, PHY_1000BASE_T_CONTROL, &AdvertisingGb, MacBaseAddress);
+  if (EFI_ERROR(Status)) return Status;
+
+  CommonAbilityGb = PartnerAbilityGb & (AdvertisingGb << 2);
+
+  // For 10/100 Base-T
+
+  Status = PhyRead (PhyDriver->PhyAddr, PHY_AUTO_NEG_LINK_ABILITY, &PartnerAbility, MacBaseAddress);
+  if (EFI_ERROR(Status)) return Status;
+
+  Status = PhyRead (PhyDriver->PhyAddr, PHY_AUTO_NEG_EXP, &Advertising, MacBaseAddress);
+  if (EFI_ERROR(Status)) return Status;
+
+  CommonAbility = PartnerAbility & Advertising;
+
+  // Determine the Speed and Duplex
+  if (PartnerAbilityGb & (PHYLPA_1000FULL | PHYLPA_1000HALF)) {
+    *Speed = SPEED_1000;
+    if (CommonAbilityGb & PHYLPA_1000FULL) {
+      *Duplex = DUPLEX_FULL;
+    }
+  } else if (CommonAbility & (PHYLPA_100FULL | PHYLPA_100HALF)) {
+    *Speed = SPEED_100;
+    if (CommonAbility & PHYLPA_100FULL) {
+      *Duplex = DUPLEX_FULL;
+    } else if (CommonAbility & PHYLPA_10FULL) {
+      *Duplex = DUPLEX_FULL;
+    }
+  }
+
+  PhyDisplayAbility (*Speed, *Duplex);
+
+  return EFI_SUCCESS;
+}
+
+
+VOID
+EFIAPI
+PhyDisplayAbility (
+  IN UINT32 Speed,
+  IN UINT32 Duplex
+  )
+{
+  //DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
+
+  Print (L"SNP:PHY: ");
+  switch (Speed) {
+    case SPEED_1000:
+      Print (L"1 Gbps - ");
+      break;
+    case SPEED_100:
+      Print (L"100 Mbps - ");
+      break;
+    case SPEED_10:
+      Print (L"10 Mbps - ");
+      break;
+    default:
+      Print (L"Invalid link speed");
+      break;
+    }
+
+  switch (Duplex) {
+    case DUPLEX_FULL:
+      Print (L"Full Duplex\n");
+      break;
+    case DUPLEX_HALF:
+      Print (L"Half Duplex\n");
+      break;
+    default:
+      Print (L"Invalid duplex mode\n");
+      break;
+    }
+}
+
+
+// Function to read from MII register (PHY Access)
+EFI_STATUS
+EFIAPI
+PhyRead (
+  IN  UINT32  Addr,
+  IN  UINT32  Reg,
+  OUT UINT32 *Data,
+  IN  UINT32  MacBaseAddress
+  )
+{
+  UINT32        MiiConfig;
+  UINT32        Count;
+
+  //DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
+
+  // Check it is a valid Reg
+  ASSERT(Reg < 31);
+
+  MiiConfig = ((Addr << MIIADDRSHIFT) & MII_ADDRMSK) |
+              ((Reg << MIIREGSHIFT) & MII_REGMSK)|
+               MII_CLKRANGE_150_250M |
+               MII_BUSY;
+
+  // write this config to register
+  MmioWrite32(MacBaseAddress + DW_EMAC_GMACGRP_GMII_ADDRESS_OFST, MiiConfig);
+
+  // Wait for busy bit to clear
+  Count = 0;
+  while (Count < 10000) {
+    if (!(DW_EMAC_GMACGRP_GMII_ADDRESS_GB_GET(MmioRead32(MacBaseAddress + DW_EMAC_GMACGRP_GMII_ADDRESS_OFST))))
+	{
+      *Data = DW_EMAC_GMACGRP_GMII_DATA_GD_GET(MmioRead32(MacBaseAddress + DW_EMAC_GMACGRP_GMII_DATA_OFST));
+      return EFI_SUCCESS;
+	}
+    Count++;
+  };
+  DEBUG ((EFI_D_INFO, "SNP:PHY: MDIO busy bit timeout\r\n"));
+  return EFI_TIMEOUT;
+}
+
+
+// Function to write to the MII register (PHY Access)
+EFI_STATUS
+EFIAPI
+PhyWrite (
+  IN UINT32 Addr,
+  IN UINT32 Reg,
+  IN UINT32 Data,
+  IN UINT32 MacBaseAddress
+  )
+{
+  UINT32 MiiConfig;
+  UINT32 Count;
+
+  //DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
+
+  // Check it is a valid Reg
+  ASSERT(Reg < 31);
+
+  MiiConfig = ((Addr << MIIADDRSHIFT) & MII_ADDRMSK) |
+              ((Reg << MIIREGSHIFT) & MII_REGMSK)|
+               MII_WRITE |
+               MII_CLKRANGE_150_250M |
+               MII_BUSY;
+  // Write the desired value to the register first
+  MmioWrite32 (MacBaseAddress + DW_EMAC_GMACGRP_GMII_DATA_OFST, (Data & 0xFFFF));
+
+  // write this config to register
+  MmioWrite32(MacBaseAddress + DW_EMAC_GMACGRP_GMII_ADDRESS_OFST, MiiConfig);
+
+  // Wait for busy bit to clear
+  Count = 0;
+  while (Count < 1000) {
+      if (!(DW_EMAC_GMACGRP_GMII_ADDRESS_GB_GET(MmioRead32(MacBaseAddress + DW_EMAC_GMACGRP_GMII_ADDRESS_OFST))))
+        return EFI_SUCCESS;
+      Count++;
+    };
+
+  return EFI_TIMEOUT;
+}
+
+
+EFI_STATUS
+EFIAPI
+Phy9031ExtendedWrite (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      Mode,
+  IN UINT32      DevAddr,
+  IN UINT32      Regnum,
+  IN UINT16      Val,
+  IN UINT32      MacBaseAddress
+  )
+{
+  //DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
+
+  PhyWrite(PhyDriver->PhyAddr, PHY_KSZ9031RN_MMD_CTRL_REG, DevAddr, MacBaseAddress);
+  PhyWrite(PhyDriver->PhyAddr, PHY_KSZ9031RN_MMD_REGDATA_REG, Regnum, MacBaseAddress);
+  PhyWrite(PhyDriver->PhyAddr, PHY_KSZ9031RN_MMD_CTRL_REG, (Mode << 14) | DevAddr, MacBaseAddress);
+  return PhyWrite(PhyDriver->PhyAddr, PHY_KSZ9031RN_MMD_REGDATA_REG, Val, MacBaseAddress);
+}
+
+
+UINT32
+EFIAPI
+Phy9031ExtendedRead (
+  IN PHY_DRIVER* PhyDriver,
+  IN UINT32      Mode,
+  IN UINT32      DevAddr,
+  IN UINT32      Regnum,
+  IN UINT32      MacBaseAddress
+  )
+{
+  EFI_STATUS    Status;
+  UINT32        Data32;
+
+  //DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
+
+  PhyWrite(PhyDriver->PhyAddr, PHY_KSZ9031RN_MMD_CTRL_REG, DevAddr, MacBaseAddress);
+  PhyWrite(PhyDriver->PhyAddr, PHY_KSZ9031RN_MMD_REGDATA_REG, Regnum, MacBaseAddress);
+  PhyWrite(PhyDriver->PhyAddr, PHY_KSZ9031RN_MMD_CTRL_REG, (Mode << 14) | DevAddr, MacBaseAddress);
+
+  Status = PhyRead (PhyDriver->PhyAddr, PHY_KSZ9031RN_MMD_REGDATA_REG, &Data32, MacBaseAddress);
+  if (EFI_ERROR(Status)) return 0;
+
+  return Data32;
+}
+
+
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v4 edk2-platforms 1/1] Silicon/DesignWare/Driver: DwEmacSnpDxe: Add DesignWare EMAC driver
  2019-05-08  9:52 [PATCH v4 edk2-platforms 1/1] Silicon/DesignWare/Driver: DwEmacSnpDxe: Add DesignWare EMAC driver tzy.way.ooi
@ 2019-05-22  2:37 ` tzy.way.ooi
  2019-05-22  7:21   ` [edk2-devel] " Ard Biesheuvel
  0 siblings, 1 reply; 9+ messages in thread
From: tzy.way.ooi @ 2019-05-22  2:37 UTC (permalink / raw)
  To: devel@edk2.groups.io
  Cc: Kinney, Michael D, Loh, Tien Hock, ard.biesheuvel@linaro.org,
	leif.lindholm@linaro.org

Hi Maintainers, 

Please could you help to review this patch? Thanks.

Regards,
Tzy Way

On Wed, 2019-05-08 at 17:52 +0800, tzy.way.ooi@intel.com wrote:
> From: Ooi Tzy Way <tzy.way.ooi@intel.com>
> 
> Add driver support for the Ethernet MAC based on Synopsys DesignWare
> 3504-0 Universal 10/100/1000 Ethernet MAC and KSZ9031 PHY
> 
> Cc: Ard BieSheuvel<ard.biesheuvel@linaro.org>
> Cc: Leif Lindholm<leif.lindholm@linaro.org>
> Cc: Michael D Kinney<michael.d.kinney@intel.com>
> Cc: Loh Tien Hock<tien.hock.loh@intel.com>
> 
> Contributed-under: Tianocore Contribution Agreement 1.1
> Signed-off-by: Ooi Tzy Way <tzy.way.ooi@intel.com>
> 
> ---
> v4:
> - Describe the device with non-discoverable device protocol
> - Expose the MMIO base address in the EFI ACPI address space
> descriptor
> - Remove cache maintainence and use DmaLib for non-coherent DMA
> access
> ---
>  Silicon/DesignWare/DesignWare.dec                        |   34 +
>  Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.inf |   82 ++
>  Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.h   |  229 ++++
>  Silicon/DesignWare/Drivers/DwEmacSnpDxe/EmacDxeUtil.h    |  392
> ++++++
>  Silicon/DesignWare/Drivers/DwEmacSnpDxe/PhyDxeUtil.h     |  341
> ++++++
>  Silicon/DesignWare/Drivers/DwEmacSnpDxe/ComponentName.c  |  327
> +++++
>  Silicon/DesignWare/Drivers/DwEmacSnpDxe/DriverBinding.c  |  450
> +++++++
>  Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.c   | 1273
> ++++++++++++++++++++
>  Silicon/DesignWare/Drivers/DwEmacSnpDxe/EmacDxeUtil.c    |  684
> +++++++++++
>  Silicon/DesignWare/Drivers/DwEmacSnpDxe/PhyDxeUtil.c     |  621
> ++++++++++
>  10 files changed, 4433 insertions(+)
> 
> diff --git a/Silicon/DesignWare/DesignWare.dec
> b/Silicon/DesignWare/DesignWare.dec
> new file mode 100755
> index 000000000000..bad81fb6a023
> --- /dev/null
> +++ b/Silicon/DesignWare/DesignWare.dec
> @@ -0,0 +1,34 @@
> +  #Copyright (c) 2011 - 2019, Intel Corporaton. All rights reserved.
> +  #This program and the accompanying materials
> +  #are licensed and made available under the terms and conditions of
> the BSD License
> +  #which accompanies this distribution.  The full text of the
> license may be found at
> +  #http://opensource.org/licenses/bsd-license.php
> +  #THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  #WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +[Defines]
> +  DEC_SPECIFICATION              = 0x00010005
> +  PACKAGE_NAME                   = DesignWarePkg
> +  PACKAGE_GUID                   = 3b5936d8-c72d-412d-b4d9-
> 3bf0dea73598
> +  PACKAGE_VERSION                = 0.1
> +
> +####################################################################
> ############
> +#
> +# Include Section - list of Include Paths that are provided by this
> package.
> +#                   Comments are used for Keywords and Module Types.
> +#
> +# Supported Module Types:
> +#  BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER
> DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION
> +#
> +####################################################################
> ############
> +  
> +[Guids.common]
> +  gDesignWareTokenSpaceGuid = { 0x89cb1241, 0xd283, 0x4543, { 0x88,
> 0x9c, 0x6b, 0x62, 0x36, 0x1a, 0x95, 0x7a } }
> +  gDwEmacNetNonDiscoverableDeviceGuid = { 0x401950CD, 0xF9CD,
> 0x4A65, { 0xAD, 0x8E, 0x84, 0x9F, 0x3B, 0xAF, 0x23, 0x04 } }
> +
> +
> +[PcdsFixedAtBuild.common]
> +  gDesignWareTokenSpaceGuid.PcdDwEmacDefaultMacAddress|0|UINT64|0x30
> 000050
> +  gDesignWareTokenSpaceGuid.PcdDwEmacDxeBaseAddress|0|UINT32|0x30000
> 051
> +  
> +
> diff --git a/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.inf
> b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.inf
> new file mode 100755
> index 000000000000..09e7f1e77f69
> --- /dev/null
> +++ b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.inf
> @@ -0,0 +1,82 @@
> +#/** @file
> +#  DW Emac Simple Networking Protocol Driver (SNP) DXE Driver
> +#
> +#  Copyright (c) 2011 - 2019, Intel Corporaton. All rights reserved.
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of
> the BSD License
> +#  which accompanies this distribution.  The full text of the
> license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +#
> +#  The original software modules are licensed as follows:
> +#
> +#  Copyright (c) 2012-2014, ARM Limited. All rights reserved.
> +#
> +#  This program and the accompanying materials
> +#  are licensed and made available under the terms and conditions of
> the BSD License
> +#  which accompanies this distribution.  The full text of the
> license may be found at
> +#  http://opensource.org/licenses/bsd-license.php
> +#
> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +#
> +#**/
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = DwEmacSnpDxe
> +  FILE_GUID                      = 06f3315f-9fe6-4938-b83f-
> 2c072af802ba
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 0.1
> +  ENTRY_POINT                    = DwEmacSnpDxeEntry
> +
> +[Sources.common]
> +  ComponentName.c
> +  DriverBinding.c
> +  DwEmacSnpDxe.c
> +  EmacDxeUtil.c
> +  PhyDxeUtil.c
> +  DwEmacSnpDxe.h
> +  EmacDxeUtil.h
> +  PhyDxeUtil.h
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  NetworkPkg/NetworkPkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  MdePkg/MdePkg.dec
> +  Silicon/DesignWare/DesignWare.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  UefiLib
> +  NetLib
> +  UefiDriverEntryPoint
> +  BaseMemoryLib
> +  ArmLib
> +  IoLib
> +  TimerLib
> +  DevicePathLib
> +  DebugLib
> +  PrintLib
> +  NonDiscoverableDeviceRegistrationLib
> +  DmaLib
> +
> +[Protocols]
> +  gEfiSimpleNetworkProtocolGuid
> +  gEfiMetronomeArchProtocolGuid
> +  gEfiPxeBaseCodeProtocolGuid
> +  gEfiDevicePathProtocolGuid
> +  gEfiDriverBindingProtocolGuid
> +  gEdkiiNonDiscoverableDeviceProtocolGuid
> +  
> +[Guids]
> +  gDwEmacNetNonDiscoverableDeviceGuid
> +
> +[Pcd]
> +  gDesignWareTokenSpaceGuid.PcdDwEmacDefaultMacAddress
> +  gDesignWareTokenSpaceGuid.PcdDwEmacDxeBaseAddress
> +  
> +[Depex]
> +  TRUE
> diff --git a/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.h
> b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.h
> new file mode 100755
> index 000000000000..677fdad8bd5d
> --- /dev/null
> +++ b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.h
> @@ -0,0 +1,229 @@
> +/** @file
> +
> +  Copyright (c) 2011 - 2019, Intel Corporaton. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of
> the BSD License
> +  which accompanies this distribution.  The full text of the license
> may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +  
> +  The original software modules are licensed as follows:
> +
> +  Copyright (c) 2012-2014, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of
> the BSD License
> +  which accompanies this distribution.  The full text of the license
> may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD 3 Clause LICENSE ON AN
> "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +**/
> +
> +
> +#ifndef __DWEMAC_SNP_DXE_H__
> +#define __DWEMAC_SNP_DXE_H__
> +
> +#include <Uefi.h>
> +#include <Uefi/UefiSpec.h>
> +#include <Base.h>
> +
> +// Protocols used by this driver
> +#include <Protocol/SimpleNetwork.h>
> +#include <Protocol/ComponentName2.h>
> +#include <Protocol/PxeBaseCode.h>
> +#include <Protocol/DevicePath.h>
> +#include <Protocol/NonDiscoverableDevice.h>
> +
> +// Libraries used by this driver
> +#include <Library/UefiLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/NetLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/ArmLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/DmaLib.h>
> +
> +#include "PhyDxeUtil.h"
> +#include "EmacDxeUtil.h"
> +
> +/*----------------------------------------------------------------
> --------------
> +  Information Structure
> +------------------------------------------------------------------
> ------------*/
> +
> +typedef struct {
> +  MAC_ADDR_DEVICE_PATH      MacAddrDP;
> +  EFI_DEVICE_PATH_PROTOCOL  End;
> +} EFI_SIMPLE_NETWORK_DEVICE_PATH;
> +
> +typedef struct {
> +  // Driver signature
> +  UINT32            Signature;
> +  EFI_HANDLE        ControllerHandle;
> +
> +  // EFI SNP protocol instances
> +  EFI_SIMPLE_NETWORK_PROTOCOL Snp;
> +  EFI_SIMPLE_NETWORK_MODE SnpMode;
> +
> +  // EFI Snp statistics instance
> +  EFI_NETWORK_STATISTICS Stats;
> +  
> +  EMAC_DRIVER  MacDriver;
> +  PHY_DRIVER   PhyDriver;
> +  
> +  NON_DISCOVERABLE_DEVICE           *Dev;
> +  
> +  EFI_LOCK                          Lock;
> +  
> +  // Array of the recycled transmit buffer address 
> +  UINT64                 *RecycledTxBuf;
> +  
> +  // The maximum number of recycled buffer pointers in
> RecycledTxBuf.
> +  UINT32                 MaxRecycledTxBuf;
> +  
> +  // Current number of recycled buffer pointers in RecycledTxBuf.
> +  UINT32                 RecycledTxBufCount;
> +  
> +  // For DmaUnmap
> +  VOID                            *MappingTxdesc;
> +  VOID                            *MappingRxdesc;
> +  VOID                            *MappingTxbuf;
> +  VOID                            *MappingRxbuf;
> +
> +} EFI_SIMPLE_NETWORK_DRIVER;
> +
> +extern EFI_COMPONENT_NAME_PROTOCOL    gSnpComponentName;
> +extern EFI_COMPONENT_NAME2_PROTOCOL   gSnpComponentName2;
> +
> +
> +#define SNP_DRIVER_SIGNATURE                    SIGNATURE_32('A',
> 'S', 'N', 'P')
> +#define INSTANCE_FROM_SNP_THIS(a)               CR(a,
> EFI_SIMPLE_NETWORK_DRIVER, Snp, SNP_DRIVER_SIGNATURE)
> +#define SNP_TX_BUFFER_INCREASEMENT              32
> +#define SNP_MAX_TX_BUFFER_NUM                   65536
> +
> +/*----------------------------------------------------------------
> -----------------------------------------------------
> +
> +  UEFI-Compliant functions for EFI_SIMPLE_NETWORK_PROTOCOL
> +
> +  Refer to the Simple Network Protocol section (21.1) in the UEFI
> 2.3.1 Specification for related definitions
> +
> +------------------------------------------------------------------
> ---------------------------------------------------*/
> +
> +EFI_STATUS
> +EFIAPI
> +SnpStart (
> +  IN        EFI_SIMPLE_NETWORK_PROTOCOL* Snp
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +SnpStop (
> +  IN        EFI_SIMPLE_NETWORK_PROTOCOL* Snp
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +SnpInitialize (
> +  IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
> +  IN UINTN                       ExtraRxBufferSize OPTIONAL,
> +  IN UINTN                       ExtraTxBufferSize OPTIONAL
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +SnpReset (
> +  IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
> +  IN BOOLEAN                     ExtendedVerification
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +SnpShutdown (
> +  IN        EFI_SIMPLE_NETWORK_PROTOCOL* Snp
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +SnpReceiveFilters (
> +  IN  EFI_SIMPLE_NETWORK_PROTOCOL  *Snp,
> +  IN  UINT32                       Enable,
> +  IN  UINT32                       Disable,
> +  IN  BOOLEAN                      ResetMCastFilter,
> +  IN  UINTN                        MCastFilterCnt  OPTIONAL,
> +  IN  EFI_MAC_ADDRESS              *MCastFilter  OPTIONAL
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +SnpStationAddress (
> +  IN        EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
> +  IN        BOOLEAN                      Reset,
> +  IN        EFI_MAC_ADDRESS             *NewMac
> +);
> +
> +EFI_STATUS
> +EFIAPI
> +SnpStatistics (
> +  IN        EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
> +  IN        BOOLEAN                      Reset,
> +  IN  OUT   UINTN                        *StatSize,
> +      OUT   EFI_NETWORK_STATISTICS       *Statistics
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +SnpMcastIptoMac (
> +  IN        EFI_SIMPLE_NETWORK_PROTOCOL  *Snp,
> +  IN        BOOLEAN                      IsIpv6,
> +  IN        EFI_IP_ADDRESS               *Ip,
> +      OUT   EFI_MAC_ADDRESS              *McastMac
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +SnpNvData (
> +  IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
> +  IN BOOLEAN                     ReadWrite,
> +  IN UINTN                       Offset,
> +  IN UINTN                       BufferSize,
> +  IN OUT VOID                    *Buffer
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +SnpGetStatus (
> +  IN  EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
> +  OUT UINT32                      *IrqStat  OPTIONAL,
> +  OUT VOID                        **TxBuff  OPTIONAL
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +SnpTransmit (
> +  IN  EFI_SIMPLE_NETWORK_PROTOCOL  *Snp,
> +  IN  UINTN                        HdrSize,
> +  IN  UINTN                        BuffSize,
> +  IN  VOID*                        Data,
> +  IN  EFI_MAC_ADDRESS              *SrcAddr  OPTIONAL,
> +  IN  EFI_MAC_ADDRESS              *DstAddr  OPTIONAL,
> +  IN  UINT16                       *Protocol OPTIONAL
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +SnpReceive (
> +  IN        EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
> +      OUT   UINTN                       *HdrSize      OPTIONAL,
> +  IN  OUT   UINTN                       *BuffSize,
> +      OUT   VOID                        *Data,
> +      OUT   EFI_MAC_ADDRESS             *SrcAddr      OPTIONAL,
> +      OUT   EFI_MAC_ADDRESS             *DstAddr      OPTIONAL,
> +      OUT   UINT16                      *Protocol     OPTIONAL
> +  );
> +
> +#endif // __DWEMAC_SNP_DXE_H__
> diff --git a/Silicon/DesignWare/Drivers/DwEmacSnpDxe/EmacDxeUtil.h
> b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/EmacDxeUtil.h
> new file mode 100755
> index 000000000000..872923252e73
> --- /dev/null
> +++ b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/EmacDxeUtil.h
> @@ -0,0 +1,392 @@
> +/** @file
> +
> +  Copyright (c) 2011 - 2019, Intel Corporaton. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of
> the BSD License
> +  which accompanies this distribution.  The full text of the license
> may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +  
> +  The original software modules are licensed as follows:
> +
> +  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
> +  Copyright (c) 2011 - 2014, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of
> the BSD License
> +  which accompanies this distribution.  The full text of the license
> may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD 3 Clause LICENSE ON AN
> "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +**/
> +
> +
> +#ifndef __EMAC_DXE_UTIL_H__
> +#define __EMAC_DXE_UTIL_H__
> +
> +#include <libfdt.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/TimerLib.h>
> +#include <Library/NetLib.h>
> +#include <Library/ArmLib.h>
> +
> +// Protocols used by this driver
> +#include <Protocol/SimpleNetwork.h>
> +#include <Protocol/ComponentName2.h>
> +#include <Protocol/PxeBaseCode.h>
> +#include <Protocol/DevicePath.h>
> +
> +
> +// Most common CRC32 Polynomial for little endian machines
> +#define CRC_POLYNOMIAL         0xEDB88320
> +#define HASH_TABLE_REG(n)      0x500 + (0x4 * n)
> +#define RX_MAX_PACKET          1600
> +
> +#define CONFIG_ETH_BUFSIZE     2048
> +#define CONFIG_TX_DESCR_NUM    10
> +#define CONFIG_RX_DESCR_NUM    10
> +#define TX_TOTAL_BUFSIZE       (CONFIG_ETH_BUFSIZE *
> CONFIG_TX_DESCR_NUM)
> +#define RX_TOTAL_BUFSIZE       (CONFIG_ETH_BUFSIZE *
> CONFIG_RX_DESCR_NUM)
> +
> +// DMA status error bit
> +#define RX_DMA_WRITE_DATA_TRANSFER_ERROR       0x0
> +#define TX_DMA_READ_DATA_TRANSFER_ERROR        0x3
> +#define RX_DMA_DESCRIPTOR_WRITE_ACCESS_ERROR   0x4
> +#define TX_DMA_DESCRIPTOR_WRITE_ACCESS_ERROR   0x5
> +#define RX_DMA_DESCRIPTOR_READ_ACCESS_ERROR    0x6
> +#define TX_DMA_DESCRIPTOR_READ_ACCESS_ERROR    0x7
> +
> +// tx descriptor
> +#define TDES0_OWN           BIT31
> +#define TDES0_TXINT         BIT30
> +#define TDES0_TXLAST        BIT29
> +#define TDES0_TXFIRST       BIT28
> +#define TDES0_TXCRCDIS      BIT27
> +#define TDES0_TXRINGEND     BIT21
> +#define TDES0_TXCHAIN       BIT20
> +
> +#define TDES1_SIZE1MASK     (0x1FFF << 0)
> +#define TDES1_SIZE1SHFT     (0)
> +#define TDES1_SIZE2MASK     (0x1FFF << 16)
> +#define TDES1_SIZE2SHFT     (16)
> +
> +// rx descriptor
> +#define RDES0_FL_MASK       0x3fff
> +#define RDES0_FL_SHIFT      16
> +#define RDES1_CHAINED       BIT14
> +
> +#define RDES0_CE            BIT1
> +#define RDES0_DBE           BIT2
> +#define RDES0_RE            BIT3
> +#define RDES0_RWT           BIT4
> +#define RDES0_LC            BIT6
> +#define RDES0_GF            BIT7
> +#define RDES0_OE            BIT11
> +#define RDES0_LE            BIT12
> +#define RDES0_SAF           BIT13
> +#define RDES0_DE            BIT14
> +#define RDES0_ES            BIT15
> +#define RDES0_AFM           BIT30
> +#define RDES0_OWN           BIT31
> +
> +
> +// emac config phy interface setting
> +#define PHY_INTERFACE_MODE_GMII      0
> +#define PHY_INTERFACE_MODE_MII       1
> +#define PHY_INTERFACE_MODE_RGMII     2
> +#define PHY_INTERFACE_MODE_RMII      3
> +
> +// DW emac mask
> +#define DW_EMAC_DMAGRP_BUS_MODE_SWR_SET_MSK             0x00000001
> +#define DW_EMAC_DMAGRP_BUS_MODE_FB_SET_MSK              0x00010000
> +#define DW_EMAC_DMAGRP_BUS_MODE_PBL_SET_MSK             0x00003f00
> +#define DW_EMAC_DMAGRP_BUS_MODE_PR_SET_MSK              0x0000c000
> +#define DW_EMAC_DMAGRP_OPERATION_MODE_FTF_SET_MSK       0x00100000
> +#define DW_EMAC_DMAGRP_OPERATION_MODE_TSF_SET_MSK       0x00200000
> +#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_TIE_SET_MSK     0x00000001
> +#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_RIE_SET_MSK     0x00000040
> +#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_NIE_SET_MSK     0x00010000
> +#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_AIE_SET_MSK     0x00008000
> +#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_FBE_SET_MSK     0x00002000
> +#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_UNE_SET_MSK     0x00000020
> +#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_TSE_SET_MSK     0x00000002
> +#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_TUE_SET_MSK     0x00000004
> +#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_TJE_SET_MSK     0x00000008
> +#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_OVE_SET_MSK     0x00000010
> +#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_RUE_SET_MSK     0x00000080
> +#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_RSE_SET_MSK     0x00000100
> +#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_RWE_SET_MSK     0x00000200
> +#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_ETE_SET_MSK     0x00000400
> +#define DW_EMAC_DMAGRP_INTERRUPT_ENABLE_ERE_SET_MSK     0x00004000
> +#define DW_EMAC_DMAGRP_OPERATION_MODE_ST_SET_MSK        0x00002000
> +#define DW_EMAC_DMAGRP_OPERATION_MODE_SR_SET_MSK        0x00000002
> +#define DW_EMAC_GMACGRP_MAC_CONFIGURATION_RE_SET_MSK    0x00000004
> +#define DW_EMAC_GMACGRP_MAC_CONFIGURATION_TE_SET_MSK    0x00000008
> +#define DW_EMAC_GMACGRP_MAC_FRAME_FILTER_RESET          0x00000000
> +#define DW_EMAC_GMACGRP_MAC_FRAME_FILTER_HMC_SET_MSK    0x00000004
> +#define DW_EMAC_GMACGRP_MAC_FRAME_FILTER_DBF_SET_MSK    0x00000020
> +#define DW_EMAC_GMACGRP_MAC_FRAME_FILTER_PR_SET_MSK     0x00000001
> +#define DW_EMAC_GMACGRP_MAC_FRAME_FILTER_PM_SET_MSK     0x00000010
> +#define DW_EMAC_DMAGRP_OPERATION_MODE_ST_CLR_MSK        0xffffdfff
> +#define DW_EMAC_GMACGRP_MAC_CONFIGURATION_RE_CLR_MSK    0xfffffffb
> +#define DW_EMAC_GMACGRP_MAC_CONFIGURATION_TE_CLR_MSK    0xfffffff7
> +#define DW_EMAC_DMAGRP_OPERATION_MODE_SR_CLR_MSK        0xfffffffd
> +#define DW_EMAC_DMAGRP_STATUS_NIS_SET_MSK               0x00010000
> +#define DW_EMAC_DMAGRP_STATUS_RI_SET_MSK                0x00000040
> +#define DW_EMAC_DMAGRP_STATUS_TI_SET_MSK                0x00000001
> +#define DW_EMAC_DMAGRP_STATUS_TU_SET_MSK                0x00000004
> +#define DW_EMAC_DMAGRP_STATUS_ERI_SET_MSK               0x00004000
> +#define DW_EMAC_DMAGRP_STATUS_AIS_SET_MSK               0x00008000
> +#define DW_EMAC_DMAGRP_STATUS_TPS_SET_MSK               0x00000002
> +#define DW_EMAC_DMAGRP_STATUS_TJT_SET_MSK               0x00000008
> +#define DW_EMAC_DMAGRP_STATUS_OVF_SET_MSK               0x00000010
> +#define DW_EMAC_DMAGRP_STATUS_UNF_SET_MSK               0x00000020
> +#define DW_EMAC_DMAGRP_STATUS_RU_SET_MSK                0x00000080
> +#define DW_EMAC_DMAGRP_STATUS_RPS_SET_MSK               0x00000100
> +#define DW_EMAC_DMAGRP_STATUS_RWT_SET_MSK               0x00000200
> +#define DW_EMAC_DMAGRP_STATUS_ETI_SET_MSK               0x00000400
> +#define DW_EMAC_DMAGRP_STATUS_FBI_SET_MSK               0x00002000
> +#define DW_EMAC_GMACGRP_MAC_CONFIGURATION_PS_SET_MSK    0x00008000
> +#define DW_EMAC_GMACGRP_MAC_CONFIGURATION_FES_SET_MSK   0x00004000
> +#define DW_EMAC_GMACGRP_MAC_CONFIGURATION_DM_SET_MSK    0x00000800
> +#define DW_EMAC_GMACGRP_MAC_CONFIGURATION_BE_SET_MSK    0x00200000
> +#define DW_EMAC_GMACGRP_MAC_CONFIGURATION_DO_SET_MSK    0x00002000
> +
> +#define DW_EMAC_DMAGRP_BUS_MODE_SWR_GET(value) (((value) &
> 0x00000001) >> 0)
> +#define DW_EMAC_DMAGRP_STATUS_EB_GET(value) (((value) & 0x03800000)
> >> 23)
> +#define DW_EMAC_GMACGRP_GMII_ADDRESS_GB_GET(value) (((value) &
> 0x00000001) >> 0)
> +#define DW_EMAC_GMACGRP_GMII_DATA_GD_GET(value) (((value) &
> 0x0000ffff) >> 0)
> +#define DW_EMAC_DMAGRP_OPERATION_MODE_FTF_GET(value) (((value) &
> 0x00100000) >> 20)
> +
> +// DW emac registers offset
> +//#define DWEMAC_OFST						
> 								((UINT3
> 2)PcdGet32 (PcdDwEmacDxeBaseAddress))
> +#define DW_EMAC_GMACGRP_MAC_CONFIGURATION_OFST             		
> 		0x000
> +#define DW_EMAC_GMACGRP_MAC_FRAME_FILTER_OFST              		
> 		0x004
> +#define DW_EMAC_GMACGRP_GMII_ADDRESS_OFST                  		
> 		0x010
> +#define DW_EMAC_GMACGRP_GMII_DATA_OFST                     		
> 		0x014
> +#define DW_EMAC_GMACGRP_FLOW_CONTROL_OFST                  		
> 		0x018
> +#define DW_EMAC_GMACGRP_VLAN_TAG_OFST                      		
> 		0x01c
> +#define DW_EMAC_GMACGRP_VERSION_OFST                       		
> 		0x020
> +#define DW_EMAC_GMACGRP_DEBUG_OFST                         		
> 		0x024
> +#define DW_EMAC_GMACGRP_LPI_CONTROL_STATUS_OFST            		
> 		0x030
> +#define DW_EMAC_GMACGRP_LPI_TIMERS_CONTROL_OFST            		
> 		0x034
> +#define DW_EMAC_GMACGRP_INTERRUPT_STATUS_OFST              		
> 		0x038
> +#define DW_EMAC_GMACGRP_INTERRUPT_MASK_OFST                		
> 		0x03c
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS0_HIGH_OFST             		
> 		0x040
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS0_LOW_OFST              		
> 		0x044
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS1_HIGH_OFST             		
> 		0x048
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS1_LOW_OFST              		
> 		0x04c
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS2_HIGH_OFST             		
> 		0x050
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS2_LOW_OFST              		
> 		0x054
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS3_HIGH_OFST             		
> 		0x058
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS3_LOW_OFST              		
> 		0x05c
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS4_HIGH_OFST             		
> 		0x060
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS4_LOW_OFST              		
> 		0x064
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS5_HIGH_OFST            		
> 		0x068
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS5_LOW_OFST             		
> 		0x06c
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS6_HIGH_OFST            		
> 		0x070
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS6_LOW_OFST             		
> 		0x074
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS7_HIGH_OFST            		
> 		0x078
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS7_LOW_OFST             		
> 		0x07c
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS8_HIGH_OFST            		
> 		0x080
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS8_LOW_OFST             		
> 		0x084
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS9_HIGH_OFST            		
> 		0x088
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS9_LOW_OFST             		
> 		0x08c
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS10_HIGH_OFST           		
> 		0x090
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS10_LOW_OFST            		
> 		0x094
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS11_HIGH_OFST           		
> 		0x098
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS11_LOW_OFST            		
> 		0x09c
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS12_HIGH_OFST           		
> 		0x0a0
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS12_LOW_OFST            		
> 		0x0a4
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS13_HIGH_OFST           		
> 		0x0a8
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS13_LOW_OFST            		
> 		0x0ac
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS14_HIGH_OFST           		
> 		0x0b0
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS14_LOW_OFST            		
> 		0x0b4
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS15_HIGH_OFST           		
> 		0x0b8
> +#define DW_EMAC_GMACGRP_MAC_ADDRESS15_LOW_OFST            		
> 		0x0bc
> +#define DW_EMAC_GMACGRP_SGMII_RGMII_SMII_CONTROL_STATUS_OFST        
> 	0x0d8
> +#define DW_EMAC_GMACGRP_WDOG_TIMEOUT_OFST                 		
> 		0x0dc
> +#define DW_EMAC_GMACGRP_GENPIO_OFST                       		
> 		0x0e0
> +#define DW_EMAC_GMACGRP_MMC_CONTROL_OFST                  		
> 		0X100
> +#define DW_EMAC_GMACGRP_MMC_RECEIVE_INTERRUPT_OFST        		
> 		0x104
> +#define DW_EMAC_GMACGRP_MMC_TRANSMIT_INTERRUPT_OFST       		
> 		0x108
> +#define DW_EMAC_GMACGRP_MMC_RECEIVE_INTERRUPT_MASK_OFST   		
> 		0x10c
> +#define DW_EMAC_GMACGRP_MMC_TRANSMIT_INTERRUPT_MASK_OFST  		
> 		0x110
> +#define DW_EMAC_GMACGRP_TXOCTETCOUNT_GB_OFST        			
> 		0x114
> +#define DW_EMAC_GMACGRP_TXFRAMECOUNT_GB_OFST        			
> 		0x118
> +#define DW_EMAC_GMACGRP_TXBROADCASTFRAMES_G_OFST        		
> 		0x11c
> +#define DW_EMAC_GMACGRP_TXMULTICASTFRAMES_G_OFST        		
> 		0x120
> +#define DW_EMAC_GMACGRP_TXUNICASTFRAMES_GB_OFST        		
> 			0x13c
> +#define DW_EMAC_GMACGRP_TXLATECOL_OFST        			
> 				0x158
> +#define DW_EMAC_GMACGRP_TXEXESSCOL_OFST        			
> 				0x15c
> +#define DW_EMAC_GMACGRP_TXFRAMECOUNT_G_OFST        			
> 			0x168
> +#define DW_EMAC_GMACGRP_TXOVERSIZE_G_OFST        			
> 			0x178
> +#define DW_EMAC_GMACGRP_RXFRAMECOUNT_GB_OFST        			
> 		0x180
> +#define DW_EMAC_GMACGRP_RXOCTETCOUNT_GB_OFST        			
> 		0x184
> +#define DW_EMAC_GMACGRP_RXBROADCASTFRAMES_G_OFST        		
> 		0x18c
> +#define DW_EMAC_GMACGRP_RXMULTICASTFRAMES_G_OFST        		
> 		0x190
> +#define DW_EMAC_GMACGRP_RXCRCERROR_OFST        			
> 				0x194
> +#define DW_EMAC_GMACGRP_RXUNDERSIZE_G_OFST        			
> 			0x1a4
> +#define DW_EMAC_GMACGRP_RXOVERSIZE_G_OFST        			
> 			0x1a8
> +#define DW_EMAC_GMACGRP_RXUNICASTFRAMES_G_OFST        		
> 			0x1c4
> +#define DW_EMAC_DMAGRP_BUS_MODE_OFST                      		
> 		0x1000
> +#define DW_EMAC_DMAGRP_TRANSMIT_POLL_DEMAND_OFST          		
> 		0x1004
> +#define DW_EMAC_DMAGRP_RECEIVE_POLL_DEMAND_OFST           		
> 		0x1008
> +#define
> DW_EMAC_DMAGRP_RECEIVE_DESCRIPTOR_LIST_ADDRESS_OFST             0x100
> c
> +#define
> DW_EMAC_DMAGRP_TRANSMIT_DESCRIPTOR_LIST_ADDRESS_OFST            0x101
> 0
> +#define
> DW_EMAC_DMAGRP_STATUS_OFST                                      0x101
> 4
> +#define
> DW_EMAC_DMAGRP_OPERATION_MODE_OFST                              0x101
> 8
> +#define
> DW_EMAC_DMAGRP_INTERRUPT_ENABLE_OFST                            0x101
> c
> +#define
> DW_EMAC_DMAGRP_MISSED_FRAME_AND_BUFFER_OVERFLOW_COUNTER_OFST    0x102
> 0
> +#define
> DW_EMAC_DMAGRP_RECEIVE_INTERRUPT_WATCHDOG_TIMER_OFST            0x102
> 4
> +#define
> DW_EMAC_DMAGRP_AXI_BUS_MODE_OFST                                0x102
> 8
> +#define
> DW_EMAC_DMAGRP_AHB_OR_AXI_STATUS_OFST                           0x102
> c
> +#define DW_EMAC_DMAGRP_CURRENT_HOST_TRANSMIT_DESCRIPTOR_OFST       	
>  	0x1048
> +#define DW_EMAC_DMAGRP_CURRENT_HOST_RECEIVE_DESCRIPTOR_OFST        	
>  	0x104c
> +#define DW_EMAC_DMAGRP_CURRENT_HOST_TRANSMIT_BUFFER_ADDRESS_OFST   	
>  	0x1050
> +#define DW_EMAC_DMAGRP_CURRENT_HOST_RECEIVE_BUFFER_ADDRESS_OFST    	
>  	0x1054
> +#define DW_EMAC_DMAGRP_HW_FEATURE_OFST                             	
>  	0x1058
> +
> +typedef struct {
> +  UINT32 Tdes0;
> +  UINT32 Tdes1;
> +  UINT32 Addr;
> +  UINT32 AddrNext;
> +} DESIGNWARE_HW_DESCRIPTOR;
> +
> +
> +typedef struct {
> +  DESIGNWARE_HW_DESCRIPTOR  *TxdescRing[CONFIG_TX_DESCR_NUM];
> +  DESIGNWARE_HW_DESCRIPTOR  *RxdescRing[CONFIG_RX_DESCR_NUM];
> +  CHAR8                     *TxBuffer[TX_TOTAL_BUFSIZE];
> +  CHAR8                     *RxBuffer[RX_TOTAL_BUFSIZE];
> +  EFI_PHYSICAL_ADDRESS      TxdescRingMap[CONFIG_TX_DESCR_NUM];
> +  EFI_PHYSICAL_ADDRESS      RxdescRingMap[CONFIG_RX_DESCR_NUM];
> +  EFI_PHYSICAL_ADDRESS      TxBufferMap[TX_TOTAL_BUFSIZE];
> +  EFI_PHYSICAL_ADDRESS      RxBufferMap[RX_TOTAL_BUFSIZE];
> +  UINT32                   TxCurrentDescriptorNum;
> +  UINT32                   TxNextDescriptorNum;
> +  UINT32                   RxCurrentDescriptorNum;
> +  UINT32                   RxNextDescriptorNum;
> +} EMAC_DRIVER;
> +
> +VOID
> +EFIAPI
> +EmacChooseInterface (
> +  IN UINT32 MacInterface
> +  );
> +
> +VOID
> +EFIAPI
> +EmacSetMacAddress (
> +  IN EFI_MAC_ADDRESS  *MacAddress,
> +  IN UINT32           MacBaseAddress
> +  );
> +
> +VOID
> +EFIAPI
> +EmacReadMacAddress (
> +  OUT EFI_MAC_ADDRESS *MacAddress,
> +  IN UINT32           MacBaseAddress
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +EmacDxeInitialization (
> +  IN EMAC_DRIVER *EmacDriver,
> +  IN UINT32      MacBaseAddress
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +EmacDmaInit (
> +  IN EMAC_DRIVER *EmacDriver,
> +  IN UINT32      MacBaseAddress
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +EmacSetupTxdesc (
> +  IN EMAC_DRIVER *EmacDriver,
> +  IN UINT32      MacBaseAddress
> + );
> +
> +EFI_STATUS
> +EFIAPI
> +EmacSetupRxdesc (
> +  IN EMAC_DRIVER *EmacDriver,
> +  IN UINT32      MacBaseAddress
> +  );
> +
> +VOID
> +EFIAPI
> +EmacStartTransmission (
> +  IN UINT32           MacBaseAddress
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +EmacRxFilters (
> +  IN        UINT32           ReceiveFilterSetting,
> +  IN        BOOLEAN          Reset,
> +  IN        UINTN            NumMfilter             OPTIONAL,
> +  IN        EFI_MAC_ADDRESS *Mfilter                OPTIONAL,
> +  IN        UINT32           MacBaseAddress
> +  );
> +
> +UINT32
> +EFIAPI
> +GenEtherCrc32 (
> +  IN    EFI_MAC_ADDRESS *Mac,
> +  IN    UINT32 AddrLen
> +  );
> +
> +UINT8
> +EFIAPI
> +BitReverse (
> +  UINT8 X
> +  );
> +
> +VOID
> +EFIAPI
> +EmacStopTxRx (
> +  IN          UINT32        MacBaseAddress
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +EmacDmaStart (
> +  IN          UINT32        MacBaseAddress
> +  );
> +
> +VOID
> +EFIAPI
> +EmacGetDmaStatus (
> +  OUT   UINT32 *IrqStat  OPTIONAL,
> +  IN    UINT32           MacBaseAddress
> +  );
> +
> +VOID
> +EFIAPI
> +EmacGetStatistic (
> +  IN EFI_NETWORK_STATISTICS* Stats,
> +  IN UINT32                  MacBaseAddress
> +  );
> +
> +VOID
> +EFIAPI
> +EmacConfigAdjust (
> +  IN UINT32 Speed,
> +  IN UINT32 Duplex,
> +  IN UINT32 MacBaseAddress
> +  );
> +
> +#endif // __EMAC_DXE_UTIL_H__
> diff --git a/Silicon/DesignWare/Drivers/DwEmacSnpDxe/PhyDxeUtil.h
> b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/PhyDxeUtil.h
> new file mode 100755
> index 000000000000..6fff3d61688a
> --- /dev/null
> +++ b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/PhyDxeUtil.h
> @@ -0,0 +1,341 @@
> +/** @file
> +
> +  Copyright (c) 2011 - 2019, Intel Corporaton. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of
> the BSD License
> +  which accompanies this distribution.  The full text of the license
> may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +  
> +  The original software modules are licensed as follows:
> +
> +  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
> +  Copyright (c) 2011 - 2014, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of
> the BSD License
> +  which accompanies this distribution.  The full text of the license
> may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD 3 Clause LICENSE ON AN
> "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +**/
> +
> +
> +#ifndef __PHY_DXE_H__
> +#define __PHY_DXE_H__
> +
> +#include <libfdt.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/TimerLib.h>
> +
> +typedef struct {
> +  UINT32 PhyAddr;
> +  UINT32 PhyCurrentLink;
> +  UINT32 PhyOldLink;
> +} PHY_DRIVER;
> +
> +
> +//
> +// PHY Registers
> +//
> +#define PHY_BASIC_CTRL                     0
> +#define PHY_BASIC_STATUS                   1
> +#define PHY_ID1                            2
> +#define PHY_ID2                            3
> +#define PHY_AUTO_NEG_ADVERT                4
> +#define PHY_AUTO_NEG_LINK_ABILITY          5
> +#define PHY_AUTO_NEG_EXP                   6
> +#define PHY_1000BASE_T_CONTROL	           9
> +#define PHY_1000BASE_T_STATUS	           10
> +#define PHY_MODE                           17
> +#define PHY_SPECIAL_MODES                  18
> +#define PHY_SPECIAL_CTLR                   27
> +#define PHY_INT_SRC                        29
> +#define PHY_INT_MASK                       30
> +#define PHY_SPECIAL_PHY_CTLR               31
> +
> +// PHY control register bits
> +#define
> PHYCTRL_COLL_TEST                       BIT7                  //
> Collision test enable
> +#define
> PHYCTRL_DUPLEX_MODE                     BIT8                  // Set
> Duplex Mode
> +#define
> PHYCTRL_RST_AUTO                        BIT9                  //
> Restart Auto-Negotiation of Link abilities
> +#define
> PHYCTRL_PD                              BIT11                 //
> Power-Down switch
> +#define
> PHYCTRL_AUTO_EN                         BIT12                 //
> Auto-Negotiation Enable
> +#define
> PHYCTRL_SPEED_SEL                       BIT13                 // Link
> Speed Selection
> +#define
> PHYCTRL_LOOPBK                          BIT14                 // Set
> loopback mode
> +#define
> PHYCTRL_RESET                           BIT15                 // Do a
> PHY reset
> +
> +// PHY status register bits
> +#define
> PHYSTS_EXT_CAP                        BIT0                  //
> Extended Capabilities Register capability
> +#define
> PHYSTS_JABBER                         BIT1                  // Jabber
> condition detected
> +#define
> PHYSTS_LINK_STS                       BIT2                  // Link
> Status
> +#define
> PHYSTS_AUTO_CAP                       BIT3                  // Auto-
> Negotiation Capability
> +#define
> PHYSTS_REMOTE_FAULT                   BIT4                  // Remote
> fault detected
> +#define
> PHYSTS_AUTO_COMP                      BIT5                  // Auto-
> Negotiation Completed
> +#define
> PHYSTS_10BASET_HDPLX                  BIT11                 // 10Mbps
> Half-Duplex ability
> +#define
> PHYSTS_10BASET_FDPLX                  BIT12                 // 10Mbps
> Full-Duplex ability
> +#define
> PHYSTS_100BASETX_HDPLX                BIT13                 //
> 100Mbps Half-Duplex ability
> +#define
> PHYSTS_100BASETX_FDPLX                BIT14                 //
> 100Mbps Full-Duplex ability
> +#define
> PHYSTS_100BASE_T4                     BIT15                 // Base
> T4 ability
> +
> +// PHY Auto-Negotiation advertisement
> +#define
> PHYANA_SEL_MASK                       ((UINT32)0x1F)        // Link
> type selector
> +#define
> PHYANA_10BASET                        BIT5                  //
> Advertise 10BASET capability
> +#define
> PHYANA_10BASETFD                      BIT6                  //
> Advertise 10BASET Full duplex capability
> +#define
> PHYANA_100BASETX                      BIT7                  //
> Advertise 100BASETX capability
> +#define
> PHYANA_100BASETXFD                    BIT8                  //
> Advertise 100 BASETX Full duplex capability
> +#define PHYANA_PAUSE_OP_MASK                  (3 <<
> 10)             // Advertise PAUSE frame capability
> +#define
> PHYANA_REMOTE_FAULT                   BIT13                 // Remote
> fault detected
> +
> +#define PHYLPA_SLCT		                      0x001f	//
> Same as advertise selector
> +#define PHYLPA_10HALF		                  0x0020	//
> Can do 10mbps half-duplex
> +#define PHYLPA_1000XFULL		              0x0020	//
> Can do 1000BASE-X full-duplex
> +#define PHYLPA_10FULL		                  0x0040	//
> Can do 10mbps full-duplex
> +#define PHYLPA_1000XHALF		              0x0040	//
> Can do 1000BASE-X half-duplex
> +#define PHYLPA_100HALF		                  0x0080	//
> Can do 100mbps half-duplex
> +#define PHYLPA_1000XPAUSE		              0x0080	//
> Can do 1000BASE-X pause
> +#define PHYLPA_100FULL		                  0x0100	//
> Can do 100mbps full-duplex
> +#define PHYLPA_1000XPAUSE_ASYM	              0x0100	//
> Can do 1000BASE-X pause asym
> +#define PHYLPA_100BASE4		                  0x0200	//
> Can do 100mbps 4k packets
> +#define PHYLPA_PAUSE_CAP		              0x0400	//
> Can pause
> +#define PHYLPA_PAUSE_ASYM		              0x0800	//
> Can pause asymetrically
> +#define PHYLPA_RESV		                      0x1000	//
> Unused
> +#define PHYLPA_RFAULT		                  0x2000	//
> Link partner faulted
> +#define PHYLPA_LPACK		                  0x4000	// Link
> partner acked us
> +#define PHYLPA_NPAGE		                  0x8000	// Next page
> bit
> +
> +#define PHYLPA_DUPLEX		                 (LPA_10FULL |
> LPA_100FULL)
> +#define PHYLPA_100			                 (LPA_100FULL |
> LPA_100HALF | LPA_100BASE4)
> +
> +// 1000BASE-T Status register
> +#define PHYLPA_1000FULL		                  0x0800	/*
> Link partner 1000BASE-T full duplex */
> +#define PHYLPA_1000HALF		                  0x0400	/*
> Link partner 1000BASE-T half duplex */
> +
> +// 1000BASE-T Control register
> +#define PHYADVERTISE_1000FULL	              0x0200  /*
> Advertise 1000BASE-T full duplex */
> +#define PHYADVERTISE_1000HALF	              0x0100  /*
> Advertise 1000BASE-T half duplex */
> +
> +#define SPEED_1000                            1000
> +#define SPEED_100                             100
> +#define SPEED_10                              10
> +
> +#define DUPLEX_FULL                           1
> +#define DUPLEX_HALF                           0
> +
> +// PHY Super Special control/status
> +#define PHYSSCS_HCDSPEED_MASK                (7 <<
> 2)              // Speed indication
> +#define
> PHYSSCS_AUTODONE                      BIT12                 // Auto-
> Negotiation Done
> +
> +// Flags for PHY reset
> +#define PHY_RESET_PMT                         BIT0
> +#define PHY_RESET_BCR                         BIT1
> +#define PHY_RESET_CHECK_LINK                  BIT2
> +
> +// Flags for auto negotiation
> +#define AUTO_NEGOTIATE_COLLISION_TEST         BIT0
> +#define AUTO_NEGOTIATE_ADVERTISE_ALL          BIT1
> +
> +
> +// Micrel KSZ9031 Extended registers
> +#define PHY_KSZ9031RN_CONTROL_PAD_SKEW_REG	      4
> +#define PHY_KSZ9031RN_RX_DATA_PAD_SKEW_REG	      5
> +#define PHY_KSZ9031RN_TX_DATA_PAD_SKEW_REG	      6
> +#define PHY_KSZ9031RN_CLK_PAD_SKEW_REG	          8
> +
> +// Data operations
> +#define PHY_KSZ9031_MOD_DATA_NO_POST_INC	 0x1
> +#define PHY_KSZ9031_MOD_DATA_POST_INC_RW	 0x2
> +#define PHY_KSZ9031_MOD_DATA_POST_INC_W		 0x3
> +
> +#define PHY_KSZ9031RN_MMD_CTRL_REG	         0x0d
> +#define PHY_KSZ9031RN_MMD_REGDATA_REG	     0x0e
> +
> +#define PHY_KSZ9031RN_CLK_SKEW_CLR_MASK                    0x3FF
> +#define PHY_KSZ9031RN_CONTROL_SKEW_CLR_MASK                0xFF
> +#define PHY_KSZ9031RN_RX_DATA_SKEW_CLR_MASK                0xFF
> +#define PHY_KSZ9031RN_TX_DATA_SKEW_CLR_MASK                0xFF
> +
> +#define PHY_KSZ9031RN_CLK_PAD_SKEW_VALUE	          0x3FC
> +#define PHY_KSZ9031RN_CONTROL_PAD_SKEW_VALUE	      0x70
> +#define PHY_KSZ9031RN_RX_DATA_PAD_SKEW_VALUE	      0x7777
> +#define PHY_KSZ9031RN_TX_DATA_PAD_SKEW_VALUE	      0x0
> +
> +
> +#define PHY_KSZ9031RN_DEV_ADDR                  0x2
> +
> +// MMD Address 0h, Auto-Negotiation FLP burst transmit timing
> +#define PHY_KSZ9031RN_MMD_DEV_ADDR_00       0x00
> +#define PHY_KSZ9031RN_MMD_D0_FLP_LO_REG     3
> +#define PHY_KSZ9031RN_MMD_D0_FLP_16MS_LO    0x1A80
> +#define PHY_KSZ9031RN_MMD_D0_FLP_HI_REG     4
> +#define PHY_KSZ9031RN_MMD_D0_FLP_16MS_HI    0x0006
> +
> +// HPS MII
> +#define MII_BUSY		                    (1 << 0)
> +#define MII_WRITE		                    (1 << 1)
> +#define MII_CLKRANGE_60_100M	            (0x0)
> +#define MII_CLKRANGE_100_150M	            (0x4)
> +#define MII_CLKRANGE_20_35M	                (0x8)
> +#define MII_CLKRANGE_35_60M	                (0xC)
> +#define MII_CLKRANGE_150_250M	            (0x10)
> +#define MII_CLKRANGE_250_300M	            (0x14)
> +
> +#define MIIADDRSHIFT		                (11)
> +#define MIIREGSHIFT		                    (6)
> +#define MII_REGMSK		                    (0x1F << 6)
> +#define MII_ADDRMSK		                    (0x1F << 11)
> +
> +// Others
> +#define PHY_INVALID_ID                      0xFFFF
> +#define LINK_UP				                1
> +#define LINK_DOWN                           0
> +#define PHY_TIMEOUT                         200000
> +
> +
> +EFI_STATUS
> +EFIAPI
> +PhyDxeInitialization (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      MacBaseAddress
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +PhyDetectDevice (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      MacBaseAddress
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +PhyConfig (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      MacBaseAddress
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +PhySoftReset (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      MacBaseAddress
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +PhyReadId (
> +  IN UINT32  PhyAddr,
> +  IN UINT32      MacBaseAddress
> +  );
> +
> +VOID
> +EFIAPI
> +PhyConfigSkew (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      MacBaseAddress
> +  );
> +
> +VOID
> +EFIAPI
> +PhyDisplayConfigSkew (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      MacBaseAddress
> +  );
> +
> +VOID
> +EFIAPI
> +PhyConfigFlpBurstTiming (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      MacBaseAddress
> +  );
> +
> +VOID
> +EFIAPI
> +PhyDisplayFlpBurstTiming (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      MacBaseAddress
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +PhyAutoNego (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      MacBaseAddress
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +PhyLinkAdjustEmacConfig (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      MacBaseAddress
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +PhyCheckLinkStatus (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      MacBaseAddress
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +PhyReadCapability (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32* Speed,
> +  IN UINT32* Duplex,
> +  IN UINT32      MacBaseAddress
> +  );
> +
> +VOID
> +EFIAPI
> +PhyDisplayAbility (
> +  IN UINT32 Speed,
> +  IN UINT32 Duplex
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +PhyRead (
> +  IN  UINT32  Addr,
> +  IN  UINT32  Reg,
> +  OUT UINT32 *Data,
> +  IN UINT32      MacBaseAddress
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +PhyWrite (
> +  IN UINT32 Addr,
> +  IN UINT32 Reg,
> +  IN UINT32 Data,
> +  IN UINT32      MacBaseAddress
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +Phy9031ExtendedWrite (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32 Mode,
> +  IN UINT32 DevAddr,
> +  IN UINT32 Regnum,
> +  IN UINT16 Val,
> +  IN UINT32      MacBaseAddress
> +  );
> +
> +UINT32
> +EFIAPI
> +Phy9031ExtendedRead (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32 Mode,
> +  IN UINT32 DevAddr,
> +  IN UINT32 Regnum,
> +  IN UINT32      MacBaseAddress
> +  );
> +
> +
> +#endif /* __PHY_DXE_H__ */
> diff --git a/Silicon/DesignWare/Drivers/DwEmacSnpDxe/ComponentName.c
> b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/ComponentName.c
> new file mode 100755
> index 000000000000..08e91fae396e
> --- /dev/null
> +++ b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/ComponentName.c
> @@ -0,0 +1,327 @@
> +/** @file
> +Copyright (c) 2011 - 2019, Intel Corporaton. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of
> the BSD License
> +  which accompanies this distribution.  The full text of the license
> may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +  
> +  The original software modules are licensed as follows:
> +
> +  Copyright (c) 2006 - 2007, Intel Corporation. All rights
> reserved.<BR>
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of
> the BSD License
> +  which accompanies this distribution.  The full text of the license
> may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +
> +Module Name:
> +
> +  ComponentName.c
> +
> +Abstract:
> +
> +
> +**/
> +
> +#include "DwEmacSnpDxe.h"
> +
> +//
> +// EFI Component Name Functions
> +//
> +/**
> +  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.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SnpGetDriverName (
> +  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
> +  IN  CHAR8                        *Language,
> +  OUT CHAR16                       **DriverName
> +  );
> +
> +
> +/**
> +  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 not a valid
> EFI_HANDLE.
> +
> +  @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.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SnpGetControllerName (
> +  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,
> +  IN  EFI_HANDLE                                      ControllerHand
> le,
> +  IN  EFI_HANDLE                                      ChildHandle   
>      OPTIONAL,
> +  IN  CHAR8                                           *Language,
> +  OUT
> CHAR16                                          **ControllerName
> +  );
> +
> +
> +//
> +// EFI Component Name Protocol
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED
> EFI_COMPONENT_NAME_PROTOCOL  gSnpComponentName = {
> +  SnpGetDriverName,
> +  SnpGetControllerName,
> +  "eng"
> +};
> +
> +//
> +// EFI Component Name 2 Protocol
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL
> gSnpComponentName2 = {
> +  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) SnpGetDriverName,
> +  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) SnpGetControllerName,
> +  "en"
> +};
> +
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
> mSnpNameTable[] = {
> +  {
> +    "eng;en",
> +    L"SNP DesignWare EMAC Driver"
> +  },
> +  {
> +    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.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SnpGetDriverName (
> +  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
> +  IN  CHAR8                        *Language,
> +  OUT CHAR16                       **DriverName
> +  )
> +{
> +  return LookupUnicodeString2 (
> +           Language,
> +           This->SupportedLanguages,
> +           mSnpNameTable,
> +           DriverName,
> +           (BOOLEAN)(This == &gSnpComponentName)
> +           );
> +}
> +
> +/**
> +  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 not a valid
> EFI_HANDLE.
> +
> +  @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.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SnpGetControllerName (
> +  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,
> +  IN  EFI_HANDLE                                      ControllerHand
> le,
> +  IN  EFI_HANDLE                                      ChildHandle   
>      OPTIONAL,
> +  IN  CHAR8                                           *Language,
> +  OUT
> CHAR16                                          **ControllerName
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> diff --git a/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DriverBinding.c
> b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DriverBinding.c
> new file mode 100755
> index 000000000000..2b750c03d432
> --- /dev/null
> +++ b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DriverBinding.c
> @@ -0,0 +1,450 @@
> +/** @file
> +
> +  Copyright (c) 2011 - 2019, Intel Corporaton. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of
> the BSD License
> +  which accompanies this distribution.  The full text of the license
> may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> + **/
> +
> +#include "DwEmacSnpDxe.h"
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +DriverSupported (
> +  IN  EFI_DRIVER_BINDING_PROTOCOL *This,
> +  IN  EFI_HANDLE                  Controller,
> +  IN  EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
> +  );
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +DriverStart (
> +  IN  EFI_DRIVER_BINDING_PROTOCOL *This,
> +  IN  EFI_HANDLE                  Controller,
> +  IN  EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
> +  );
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +DriverStop (
> +  IN  EFI_DRIVER_BINDING_PROTOCOL *This,
> +  IN  EFI_HANDLE                  Controller,
> +  IN  UINTN                       NumberOfChildren,
> +  IN  EFI_HANDLE                  *ChildHandleBuffer
> +  );
> +
> +STATIC EFI_DRIVER_BINDING_PROTOCOL mDriverBinding = {
> +  DriverSupported,
> +  DriverStart,
> +  DriverStop,
> +  0xa,
> +  NULL,
> +  NULL
> +};
> +
> +EFI_SIMPLE_NETWORK_DEVICE_PATH PathTemplate =  {
> +  {
> +    {
> +      MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP,
> +      { (UINT8) (sizeof(MAC_ADDR_DEVICE_PATH)), (UINT8)
> ((sizeof(MAC_ADDR_DEVICE_PATH)) >> 8) }
> +    },
> +    { { 0 } },
> +    0
> +  },
> +  {
> +    END_DEVICE_PATH_TYPE,
> +    END_ENTIRE_DEVICE_PATH_SUBTYPE,
> +    { sizeof(EFI_DEVICE_PATH_PROTOCOL), 0 }
> +  }
> +};
> +
> +STATIC EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR mDwEmacNetDesc[] = {
> + {
> +    ACPI_ADDRESS_SPACE_DESCRIPTOR,                    // Desc
> +    sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3,   // Len
> +    ACPI_ADDRESS_SPACE_TYPE_MEM,                      // ResType
> +    0,                                                // GenFlag
> +    0,                                                //
> SpecificFlag
> +    32,                                               //
> AddrSpaceGranularity
> +    FixedPcdGet32 (PcdDwEmacDxeBaseAddress),          //
> AddrRangeMin
> +    FixedPcdGet32 (PcdDwEmacDxeBaseAddress) +
> +	SIZE_4KB - 1,                                     //
> AddrRangeMax
> +    0,                                                //
> AddrTranslationOffset
> +    SIZE_4KB,                                         // AddrLen
> +  }, {
> +    ACPI_ADDRESS_SPACE_DESCRIPTOR,                    // Desc
> +    sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3,   // Len
> +    ACPI_ADDRESS_SPACE_TYPE_MEM,                      // ResType
> +    0,                                                // GenFlag
> +    0,                                                //
> SpecificFlag
> +    32,                                               //
> AddrSpaceGranularity
> +    FixedPcdGet32 (PcdDwEmacDefaultMacAddress),       //
> AddrRangeMin
> +    FixedPcdGet32 (PcdDwEmacDefaultMacAddress),       //
> AddrRangeMax
> +    0,                                                //
> AddrTranslationOffset
> +    1,                                                // AddrLen
> +  }, {
> +    ACPI_END_TAG_DESCRIPTOR                           // Desc
> +  }
> +};
> +
> +STATIC
> +EFI_STATUS
> +RegisterDevice (
> +  IN  EFI_GUID                            *TypeGuid,
> +  IN  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Desc,
> +  OUT EFI_HANDLE                          *Handle
> +  )
> +{
> +  NON_DISCOVERABLE_DEVICE             *Device;
> +  EFI_STATUS                          Status;
> +
> +  Device = (NON_DISCOVERABLE_DEVICE *)AllocateZeroPool (sizeof
> (*Device));
> +  if (Device == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  Device->Type = TypeGuid;
> +  Device->DmaType = NonDiscoverableDeviceDmaTypeNonCoherent;
> +  Device->Resources = Desc;
> +
> +  Status = gBS->InstallMultipleProtocolInterfaces (Handle,
> +                  &gEdkiiNonDiscoverableDeviceProtocolGuid, Device,
> +                  NULL);
> +  if (EFI_ERROR (Status)) {
> +    goto FreeDevice;
> +  }
> +  return EFI_SUCCESS;
> +
> +  FreeDevice:
> +  FreePool (Device);
> +
> +  return Status;
> +}
> +
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +DriverSupported (
> +  IN  EFI_DRIVER_BINDING_PROTOCOL *This,
> +  IN  EFI_HANDLE                  Controller,
> +  IN  EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
> +  )
> +{
> +  NON_DISCOVERABLE_DEVICE    *Dev;
> +  EFI_STATUS                 Status;
> +
> +  // Connect to the non-discoverable device
> +  Status = gBS->OpenProtocol (Controller,
> +                              &gEdkiiNonDiscoverableDeviceProtocolGu
> id,
> +                              (VOID **) &Dev,
> +                              This->DriverBindingHandle,
> +                              Controller,
> +                              EFI_OPEN_PROTOCOL_BY_DRIVER);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  if (CompareGuid (Dev->Type, &gDwEmacNetNonDiscoverableDeviceGuid)
> &&
> +      Dev->DmaType == NonDiscoverableDeviceDmaTypeNonCoherent) {
> +    Status = EFI_SUCCESS;
> +  } else { 
> +    Status = EFI_UNSUPPORTED;
> +  }
> +
> +  // Clean up.
> +  gBS->CloseProtocol (Controller,
> +                      &gEdkiiNonDiscoverableDeviceProtocolGuid,
> +                      This->DriverBindingHandle,
> +                      Controller);
> +
> +  return Status;
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +DriverStart (
> +  IN  EFI_DRIVER_BINDING_PROTOCOL *This,
> +  IN  EFI_HANDLE                  Controller,
> +  IN  EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  EFI_SIMPLE_NETWORK_DRIVER       *Snp;
> +  EFI_SIMPLE_NETWORK_MODE         *SnpMode;
> +  EFI_SIMPLE_NETWORK_DEVICE_PATH  *DevicePath;
> +  UINT64                           DefaultMacAddress;
> +  EFI_MAC_ADDRESS                 *SwapMacAddressPtr;
> +  UINTN                           BufferSize;
> +  UINTN                           BufferSizeBuf;
> +
> +  // Allocate Resources
> +  Snp = AllocatePages (EFI_SIZE_TO_PAGES (sizeof
> (EFI_SIMPLE_NETWORK_DRIVER)));
> +  if (Snp == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  
> +  BufferSize = EFI_PAGES_TO_SIZE ((sizeof
> (DESIGNWARE_HW_DESCRIPTOR))*10);
> +  BufferSizeBuf = EFI_PAGES_TO_SIZE ((sizeof (CHAR8))*10*2048);
> +  
> +  // DMA Allocte Buffer and Map for TxdescRing
> +  Status = DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES
> ((sizeof (DESIGNWARE_HW_DESCRIPTOR))*10), (VOID*)&Snp-
> >MacDriver.TxdescRing);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "CreateDwEmacSnpDxe: DmaAllocateBuffer
> TxdescRing: %r\n", Status));
> +    return Status;
> +  }
> +  Status = DmaMap (MapOperationBusMasterCommonBuffer, Snp-
> >MacDriver.TxdescRing[0], &BufferSize, &Snp-
> >MacDriver.TxdescRingMap[0], &Snp->MappingTxdesc);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "CreateDwEmacSnpDxe: DmaMap TxdescRing:
> %r\n", Status));
> +    return Status;
> +  }
> +  
> +  // DMA Allocte Buffer and Map for RxdescRing
> +  Status = DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES
> ((sizeof (DESIGNWARE_HW_DESCRIPTOR))*10), (VOID*)&Snp-
> >MacDriver.RxdescRing);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "CreateDwEmacSnpDxe: DmaAllocateBuffer
> RxdescRing: %r\n", Status));
> +    return Status;
> +  }
> +  Status = DmaMap (MapOperationBusMasterCommonBuffer, Snp-
> >MacDriver.RxdescRing[0], &BufferSize, &Snp-
> >MacDriver.RxdescRingMap[0], &Snp->MappingRxdesc);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "CreateDwEmacSnpDxe: DmaMap RxdescRing:
> %r\n", Status));
> +    return Status;
> +  }
> +  
> +  // DMA Allocte Buffer and Map for TxBuffer
> +  Status = DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES
> ((sizeof (CHAR8))*10*2048), (VOID*)&Snp->MacDriver.TxBuffer);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "CreateDwEmacSnpDxe: DmaAllocateBuffer
> TxBuffer: %r\n", Status));
> +    return Status;
> +  }
> +  Status = DmaMap (MapOperationBusMasterCommonBuffer, Snp-
> >MacDriver.TxBuffer[0], &BufferSizeBuf, &Snp-
> >MacDriver.TxBufferMap[0], &Snp->MappingTxbuf);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "CreateDwEmacSnpDxe: DmaMap TxBuffer:
> %r\n", Status));
> +    return Status;
> +  }
> +  
> +  // DMA Allocte Buffer and Map for RxBuffer
> +  Status = DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES
> ((sizeof (CHAR8))*10*2048), (VOID*)&Snp->MacDriver.RxBuffer);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "CreateDwEmacSnpDxe: DmaAllocateBuffer
> RxBuffer: %r\n", Status));
> +    return Status;
> +  }
> +  Status = DmaMap (MapOperationBusMasterWrite, Snp-
> >MacDriver.RxBuffer[0], &BufferSizeBuf, &Snp-
> >MacDriver.RxBufferMap[0], &Snp->MappingRxbuf);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "CreateDwEmacSnpDxe: DmaMap RxBuffer:
> %r\n", Status));
> +    return Status;
> +  }
> +  
> +  
> +  DevicePath = (EFI_SIMPLE_NETWORK_DEVICE_PATH*)AllocateCopyPool
> (sizeof (EFI_SIMPLE_NETWORK_DEVICE_PATH), &PathTemplate);
> +  if (DevicePath == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  
> +  Status = gBS->OpenProtocol (Controller,
> +                              &gEdkiiNonDiscoverableDeviceProtocolGu
> id,
> +                              (VOID **)&Snp->Dev,
> +                              This->DriverBindingHandle,
> +                              Controller,
> +                              EFI_OPEN_PROTOCOL_BY_DRIVER);
> +
> +  // Initialized signature (used by INSTANCE_FROM_SNP_THIS macro)
> +  Snp->Signature = SNP_DRIVER_SIGNATURE;
> +  
> +  EfiInitializeLock (&Snp->Lock, TPL_CALLBACK);
> +  
> +  // Initialize pointers
> +  SnpMode = &(Snp->SnpMode);
> +  Snp->Snp.Mode = SnpMode;
> +
> +  // Assign fields and func pointers
> +  Snp->Snp.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
> +  Snp->Snp.WaitForPacket = NULL;
> +  Snp->Snp.Initialize = SnpInitialize;
> +  Snp->Snp.Start = SnpStart;
> +  Snp->Snp.Stop = SnpStop;
> +  Snp->Snp.Reset = SnpReset;
> +  Snp->Snp.Shutdown = SnpShutdown;
> +  Snp->Snp.ReceiveFilters = SnpReceiveFilters;
> +  Snp->Snp.StationAddress = SnpStationAddress;
> +  Snp->Snp.Statistics = SnpStatistics;
> +  Snp->Snp.MCastIpToMac = SnpMcastIptoMac;
> +  Snp->Snp.NvData = SnpNvData;
> +  Snp->Snp.GetStatus = SnpGetStatus;
> +  Snp->Snp.Transmit = SnpTransmit;
> +  Snp->Snp.Receive = SnpReceive;
> + 
> +  Snp->RecycledTxBuf = AllocatePool (sizeof (UINT64) *
> SNP_TX_BUFFER_INCREASEMENT);
> +  if (Snp->RecycledTxBuf == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +  }
> +  
> +  Snp->MaxRecycledTxBuf    = SNP_TX_BUFFER_INCREASEMENT;
> +  Snp->RecycledTxBufCount  = 0;
> +
> +  // Start completing simple network mode structure
> +  SnpMode->State = EfiSimpleNetworkStopped;
> +  SnpMode->HwAddressSize = NET_ETHER_ADDR_LEN; // HW address is 6
> bytes
> +  SnpMode->MediaHeaderSize = sizeof(ETHER_HEAD); // Not sure of this
> +  SnpMode->MaxPacketSize = EFI_PAGE_SIZE; // Preamble + SOF + Ether
> Frame (with VLAN tag +4bytes)
> +  SnpMode->NvRamSize = 0;           // No NVRAM with this device
> +  SnpMode->NvRamAccessSize = 0; // No NVRAM with this device
> +
> +  // Update network mode information
> +  SnpMode->ReceiveFilterMask =
> EFI_SIMPLE_NETWORK_RECEIVE_UNICAST     |
> +                               EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST 
>   |
> +                               EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST 
>   |
> +                               EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOU
> S |
> +                               EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOU
> S_MULTICAST;
> +
> +  // We do not intend to receive anything for the time being.
> +  SnpMode->ReceiveFilterSetting = 0;
> +
> +  // EMAC has 64bit hash table, can filter 64 MCast MAC Addresses
> +  SnpMode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT;
> +  SnpMode->MCastFilterCount = 0;
> +  ZeroMem (&SnpMode->MCastFilter, MAX_MCAST_FILTER_CNT *
> sizeof(EFI_MAC_ADDRESS));
> +
> +  // Set the interface type (1: Ethernet or 6: IEEE 802 Networks)
> +  SnpMode->IfType = NET_IFTYPE_ETHERNET;
> +
> +  // Mac address is changeable as it is loaded from erasable memory
> +  SnpMode->MacAddressChangeable = TRUE;
> +
> +  // Can only transmit one packet at a time
> +  SnpMode->MultipleTxSupported = FALSE;
> +
> +  // MediaPresent checks for cable connection and partner link
> +  SnpMode->MediaPresentSupported = TRUE;
> +  SnpMode->MediaPresent = FALSE;
> +
> +  // Set broadcast address
> +  SetMem (&SnpMode->BroadcastAddress, sizeof (EFI_MAC_ADDRESS),
> 0xFF);
> +
> +  //Set current address
> +  DefaultMacAddress = Snp->Dev->Resources[1].AddrRangeMin;
> +  // Swap PCD human readable form to correct endianess
> +  SwapMacAddressPtr = (EFI_MAC_ADDRESS *) &DefaultMacAddress;
> +  SnpMode->CurrentAddress.Addr[0] = SwapMacAddressPtr->Addr[5];
> +  SnpMode->CurrentAddress.Addr[1] = SwapMacAddressPtr->Addr[4];
> +  SnpMode->CurrentAddress.Addr[2] = SwapMacAddressPtr->Addr[3];
> +  SnpMode->CurrentAddress.Addr[3] = SwapMacAddressPtr->Addr[2];
> +  SnpMode->CurrentAddress.Addr[4] = SwapMacAddressPtr->Addr[1];
> +  SnpMode->CurrentAddress.Addr[5] = SwapMacAddressPtr->Addr[0];
> +  
> +  // Assign fields for device path
> +  CopyMem (&DevicePath->MacAddrDP.MacAddress, &Snp->Snp.Mode-
> >CurrentAddress, NET_ETHER_ADDR_LEN);
> +  DevicePath->MacAddrDP.IfType = Snp->Snp.Mode->IfType;
> +  
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +                  &Controller,
> +                  &gEfiSimpleNetworkProtocolGuid, &(Snp->Snp),
> +				  &gEfiDevicePathProtocolGuid,
> DevicePath,
> +				  NULL
> +                  );
> +
> +  if (EFI_ERROR(Status)) {
> +  gBS->CloseProtocol (Controller,
> +                      &gEdkiiNonDiscoverableDeviceProtocolGuid, 
> +					  This->DriverBindingHandle,
> +                      Controller);
> +
> +  FreePages (Snp, EFI_SIZE_TO_PAGES (sizeof
> (EFI_SIMPLE_NETWORK_DRIVER)));
> +  } else {
> +    Snp->ControllerHandle = Controller;
> +  }  
> +
> +  return Status;
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +DriverStop (
> +  IN  EFI_DRIVER_BINDING_PROTOCOL *This,
> +  IN  EFI_HANDLE                  Controller,
> +  IN  UINTN                       NumberOfChildren,
> +  IN  EFI_HANDLE                  *ChildHandleBuffer
> +  )
> +{
> +  EFI_STATUS Status;
> +  EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol;
> +  EFI_SIMPLE_NETWORK_DRIVER   *Snp;
> +  
> +  Status = gBS->HandleProtocol (
> +                  Controller,
> +                  &gEfiSimpleNetworkProtocolGuid,
> +                  (VOID**)&SnpProtocol
> +                );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "DriverStop: HandleProtocol: %r\n",
> Status));
> +    return Status;
> +  }
> +
> +  Snp = INSTANCE_FROM_SNP_THIS(SnpProtocol);
> +  
> +  Status = gBS->UninstallMultipleProtocolInterfaces (
> +                  Controller,
> +                  &gEfiSimpleNetworkProtocolGuid,
> +                  &Snp->Snp,
> +                  NULL);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "DriverStop:
> UninstallMultipleProtocolInterfaces: %r\n",
> +      Status));
> +    return Status;
> +  }
> +  
> +  DmaUnmap(Snp->MappingTxdesc);
> +  DmaUnmap(Snp->MappingRxdesc);
> +  DmaUnmap(Snp->MappingTxbuf);
> +  DmaUnmap(Snp->MappingRxbuf);
> +  
> +  FreePool (Snp->RecycledTxBuf);
> +  FreePages (Snp, EFI_SIZE_TO_PAGES (sizeof
> (EFI_SIMPLE_NETWORK_DRIVER))); 
> +
> +  return Status;
> +}
> +
> +
> +/**
> +   UEFI Driver Entry Point API
> +   @param  ImageHandle       EFI_HANDLE.
> +   @param  SystemTable       EFI_SYSTEM_TABLE.
> +   @return EFI_SUCCESS       Success.
> +   EFI_DEVICE_ERROR  Fail.
> +**/
> +
> +EFI_STATUS
> +EFIAPI
> +DwEmacSnpDxeEntry (
> +  IN  EFI_HANDLE ImageHandle,
> +  IN  EFI_SYSTEM_TABLE *SystemTable
> +  )
> +{
> +  EFI_STATUS        Status;
> +  EFI_HANDLE        Handle;
> +  
> +  Handle = NULL;
> +  Status = RegisterDevice (&gDwEmacNetNonDiscoverableDeviceGuid,
> mDwEmacNetDesc,
> +             &Handle);
> +  ASSERT_EFI_ERROR (Status);
> +  
> +  Status = EfiLibInstallDriverBindingComponentName2 (
> +             ImageHandle,
> +             SystemTable,
> +             &mDriverBinding,
> +             ImageHandle,
> +             &gSnpComponentName,
> +             &gSnpComponentName2
> +             );
> +
> +  return Status;
> +
> +}
> \ No newline at end of file
> diff --git a/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.c
> b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.c
> new file mode 100755
> index 000000000000..cee1584c599e
> --- /dev/null
> +++ b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/DwEmacSnpDxe.c
> @@ -0,0 +1,1273 @@
> +/** @file
> +  DW EMAC SNP DXE driver
> +
> +  Copyright (c) 2011 - 2019, Intel Corporaton. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of
> the BSD License
> +  which accompanies this distribution.  The full text of the license
> may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +  
> +  The original software modules are licensed as follows:
> +
> +  Copyright (c) 2012 - 2014, ARM Limited. All rights reserved.
> +  Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of
> the BSD License
> +  which accompanies this distribution.  The full text of the license
> may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD 3 Clause LICENSE ON AN
> "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +**/
> +
> +#include "DwEmacSnpDxe.h"
> +#include "EmacDxeUtil.h"
> +#include "PhyDxeUtil.h"
> +
> +/**
> +  Change the state of a network interface from "stopped" to
> "started."
> +
> +  This function starts a network interface. If the network interface
> successfully
> +  starts, then EFI_SUCCESS will be returned.
> +
> +  @param  Snp                    A pointer to the
> EFI_SIMPLE_NETWORK_PROTOCOL instance.
> +
> +  @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  This parameter was NULL or did not
> point to a valid
> +                                 EFI_SIMPLE_NETWORK_PROTOCOL
> structure.
> +  @retval EFI_DEVICE_ERROR       The command could not be sent to
> the network interface.
> +  @retval EFI_UNSUPPORTED        This function is not supported by
> the network interface.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SnpStart (
> +  IN  EFI_SIMPLE_NETWORK_PROTOCOL    *This
> + )
> +{
> +  EFI_SIMPLE_NETWORK_DRIVER    *Snp;
> +  DEBUG ((EFI_D_INFO,"SNP:DXE: %a ()\r\n", __FUNCTION__));
> +
> +  // Check Snp instance
> +  if (This == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  
> +  Snp = INSTANCE_FROM_SNP_THIS(This);
> +  // Check state
> +  if ((Snp->SnpMode.State == EfiSimpleNetworkStarted)    ||
> +      (Snp->SnpMode.State == EfiSimpleNetworkInitialized)  ) {
> +    return EFI_ALREADY_STARTED;
> +  }
> +
> +  // Change state
> +  Snp->SnpMode.State = EfiSimpleNetworkStarted;
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Changes the state of a network interface from "started" to
> "stopped."
> +
> +  This function stops a network interface. This call is only valid
> if the network
> +  interface is in the started state. If the network interface was
> successfully
> +  stopped, then EFI_SUCCESS will be returned.
> +
> +  @param  Snp                     A pointer to the
> EFI_SIMPLE_NETWORK_PROTOCOL
> +                                  instance.
> +
> +
> +  @retval EFI_SUCCESS             The network interface was stopped.
> +  @retval EFI_NOT_STARTED         The network interface has not been
> started.
> +  @retval EFI_INVALID_PARAMETER   This parameter was NULL or did not
> point to a
> +                                  valid EFI_SIMPLE_NETWORK_PROTOCOL
> structure.
> +  @retval EFI_DEVICE_ERROR        The command could not be sent to
> the network
> +                                  interface.
> +  @retval EFI_UNSUPPORTED         This function is not supported by
> the network
> +                                  interface.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SnpStop (
> +  IN        EFI_SIMPLE_NETWORK_PROTOCOL* This
> +  )
> +{
> +  EFI_SIMPLE_NETWORK_DRIVER    *Snp;
> +  UINT32        MacBase;
> +  DEBUG ((EFI_D_INFO, "SNP:DXE: %a ()\r\n", __FUNCTION__));
> +
> +  // Check Snp Instance
> +  if (This == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Snp = INSTANCE_FROM_SNP_THIS(This);
> +  // Check state of the driver
> +  if (Snp->SnpMode.State == EfiSimpleNetworkStopped) {
> +    return EFI_NOT_STARTED;
> +  }
> +
> +  //Get MAC base address
> +  MacBase = (UINT32)Snp->Dev->Resources[0].AddrRangeMin;
> +  
> +  // Stop the Tx and Rx
> +  EmacStopTxRx (MacBase);
> +  // Change the state
> +  switch (Snp->SnpMode.State) {
> +    case EfiSimpleNetworkStarted:
> +    case EfiSimpleNetworkInitialized:
> +      Snp->SnpMode.State = EfiSimpleNetworkStopped;
> +      break;
> +    default:
> +      return EFI_DEVICE_ERROR;
> +  }
> +
> +  // Put the device into a power saving mode ?
> +  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.
> +
> +  This function allocates the transmit and receive buffers required
> by the network
> +  interface. If this allocation fails, then EFI_OUT_OF_RESOURCES is
> returned.
> +  If the allocation succeeds and the network interface is
> successfully initialized,
> +  then EFI_SUCCESS will be returned.
> +
> +  @param Snp                A pointer to the
> EFI_SIMPLE_NETWORK_PROTOCOL instance.
> +
> +  @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 This parameter was NULL or did not
> point to a valid
> +                                EFI_SIMPLE_NETWORK_PROTOCOL
> structure.
> +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> network interface.
> +  @retval EFI_UNSUPPORTED       The increased buffer size feature is
> not supported.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SnpInitialize (
> +  IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
> +  IN UINTN                       ExtraRxBufferSize OPTIONAL,
> +  IN UINTN                       ExtraTxBufferSize OPTIONAL
> +  )
> +{
> +  EFI_STATUS                  Status;
> +  EFI_SIMPLE_NETWORK_DRIVER  *Snp;
> +  UINT32                      MacBase;
> +
> +  DEBUG ((EFI_D_INFO, "SNP:DXE: %a ()\r\n", __FUNCTION__));
> +
> +  // Check Snp Instance
> +  if (This == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Snp = INSTANCE_FROM_SNP_THIS (This);
> +  // First check that driver has not already been initialized
> +  if (Snp->SnpMode.State == EfiSimpleNetworkInitialized) {
> +    return EFI_SUCCESS;
> +  } else
> +  if (Snp->SnpMode.State == EfiSimpleNetworkStopped) {
> +    return EFI_NOT_STARTED;
> +  }
> +  
> +  //Get MAC base address
> +  MacBase = (UINT32)Snp->Dev->Resources[0].AddrRangeMin;
> +
> +  // Init PHY
> +  Status = PhyDxeInitialization (&Snp->PhyDriver, MacBase);
> +  if (EFI_ERROR (Status)) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  // Init EMAC
> +  Status = EmacDxeInitialization (&Snp->MacDriver, MacBase);
> +  if (EFI_ERROR (Status)) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  // Set MAC Address
> +  EmacSetMacAddress (&Snp->SnpMode.CurrentAddress, MacBase);
> +  EmacReadMacAddress(&Snp->SnpMode.CurrentAddress, MacBase);
> +
> +  // Init Link
> +  Print (L"SNP:DXE: Auto-Negotiating Ethernet PHY Link ...\r\n");
> +  Status = PhyLinkAdjustEmacConfig (&Snp->PhyDriver, MacBase);
> +  if (EFI_ERROR(Status)) {
> +    Print (L"SNP:DXE: Link is Down - Network Cable is not plugged
> in?\r\n");
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  EmacStartTransmission (MacBase);
> +
> +  // Declare the driver as initialized
> +  Snp->SnpMode.State = EfiSimpleNetworkInitialized;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Resets a network adapter and reinitializes it with the parameters
> that were
> +  provided in the previous call to Initialize().
> +
> +  This function resets a network adapter and reinitializes it with
> the parameters
> +  that were provided in the previous call to Initialize(). The
> transmit and
> +  receive queues are emptied and all pending interrupts are cleared.
> +  Receive filters, the station address, the statistics, and the
> multicast-IP-to-HW
> +  MAC addresses are not reset by this call. If the network interface
> was
> +  successfully reset, then EFI_SUCCESS will be returned. If the
> driver has not
> +  been initialized, EFI_DEVICE_ERROR will be returned.
> +
> +  @param Snp                  A pointer to the
> EFI_SIMPLE_NETWORK_PROTOCOL instance.
> +  @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 command could not be sent to the
> network interface.
> +  @retval EFI_UNSUPPORTED       This function is not supported by
> the network interface.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SnpReset (
> +  IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
> +  IN BOOLEAN                     ExtendedVerification
> +  )
> +{
> +  EFI_STATUS                  Status;
> +  EFI_SIMPLE_NETWORK_DRIVER  *Snp;
> +  UINT32                      MacBase;
> +
> +  Snp = INSTANCE_FROM_SNP_THIS (This);
> +
> +  DEBUG ((EFI_D_INFO, "SNP:DXE: %a ()\r\n", __FUNCTION__));
> +
> +  // Check Snp Instance
> +  if (This == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  // First check that driver has not already been initialized
> +  if (Snp->SnpMode.State == EfiSimpleNetworkStarted) {
> +    return EFI_DEVICE_ERROR;
> +  } else if (Snp->SnpMode.State == EfiSimpleNetworkStopped) {
> +    return EFI_NOT_STARTED;
> +  }
> +  
> +  // Get MAC base address
> +  MacBase = (UINT32)Snp->Dev->Resources[0].AddrRangeMin;
> +
> +  // Initiate a PHY reset
> +  Status = PhySoftReset (&Snp->PhyDriver, MacBase);
> +  if (EFI_ERROR (Status)) {
> +    Snp->SnpMode.State = EfiSimpleNetworkStopped;
> +    return EFI_NOT_STARTED;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Resets a network adapter and leaves it in a state that is safe for
> another
> +  driver to initialize.
> +
> +  This function releases the memory buffers assigned in the
> Initialize() call.
> +  Pending transmits and receives are lost, and interrupts are
> cleared and disabled.
> +  After this call, only the Initialize() and Stop() calls may be
> used. If the
> +  network interface was successfully shutdown, then EFI_SUCCESS will
> be returned.
> +  If the driver has not been initialized, EFI_DEVICE_ERROR will be
> returned.
> +
> +  @param  This  A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL
> instance.
> +
> +  @retval EFI_SUCCESS           The network interface was shutdown.
> +  @retval EFI_NOT_STARTED       The network interface has not been
> started.
> +  @retval EFI_INVALID_PARAMETER This parameter was NULL or did not
> point to a valid
> +                                EFI_SIMPLE_NETWORK_PROTOCOL
> structure.
> +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> network interface.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SnpShutdown (
> +  IN        EFI_SIMPLE_NETWORK_PROTOCOL*  This
> +  )
> +{
> +  EFI_SIMPLE_NETWORK_DRIVER  *Snp;
> +  UINT32                      MacBase;
> +  DEBUG ((EFI_D_INFO, "SNP:DXE: %a ()\r\n", __FUNCTION__));
> +
> +  // Check Snp Instance
> +  if (This == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Snp = INSTANCE_FROM_SNP_THIS (This);
> +  // First check that driver has not already been initialized
> +  if (Snp->SnpMode.State == EfiSimpleNetworkStarted) {
> +    return EFI_DEVICE_ERROR;
> +  } else if (Snp->SnpMode.State == EfiSimpleNetworkStopped) {
> +    return EFI_NOT_STARTED;
> +  }
> +  
> +  //Get MAC base address
> +  MacBase = (UINT32)Snp->Dev->Resources[0].AddrRangeMin;
> +  
> +  EmacStopTxRx (MacBase);
> +
> +  Snp->SnpMode.State = EfiSimpleNetworkStopped;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Manages the multicast receive filters of a network interface.
> +
> +  This function is used enable and disable the hardware and software
> receive
> +  filters for the underlying network device.
> +  The receive filter change is broken down into three steps:
> +  * The filter mask bits that are set (ON) in the Enable parameter
> are added to
> +    the current receive filter settings.
> +  * The filter mask bits that are set (ON) in the Disable parameter
> are subtracted
> +    from the updated receive filter settings.
> +  * If the resulting receive filter setting is not supported by the
> hardware a
> +    more liberal setting is selected.
> +  If the same bits are set in the Enable and Disable parameters,
> then the bits
> +  in the Disable parameter takes precedence.
> +  If the ResetMCastFilter parameter is TRUE, then the multicast
> address list
> +  filter is disabled (irregardless of what other multicast bits are
> set in the
> +  Enable and Disable parameters). The SNP->Mode->MCastFilterCount
> field is set
> +  to zero. The Snp->Mode->MCastFilter contents are undefined.
> +  After enabling or disabling receive filter settings, software
> should verify
> +  the new settings by checking the Snp->Mode->ReceiveFilterSettings,
> +  Snp->Mode->MCastFilterCount and Snp->Mode->MCastFilter fields.
> +  Note: Some network drivers and/or devices will automatically
> promote receive
> +    filter settings if the requested setting can not be honored. For
> example, if
> +    a request for four multicast addresses is made and the
> underlying hardware
> +    only supports two multicast addresses the driver might set the
> promiscuous
> +    or promiscuous multicast receive filters instead. The receiving
> software is
> +    responsible for discarding any extra packets that get through
> the hardware
> +    receive filters.
> +    Note: Note: To disable all receive filter hardware, the network
> driver must
> +      be Shutdown() and Stopped(). Calling ReceiveFilters() with
> Disable set to
> +      Snp->Mode->ReceiveFilterSettings will make it so no more
> packets are
> +      returned by the Receive() function, but the receive hardware
> may still be
> +      moving packets into system memory before inspecting and
> discarding them.
> +      Unexpected system errors, reboots and hangs can occur if an OS
> is loaded
> +      and the network devices are not Shutdown() and Stopped().
> +  If ResetMCastFilter is TRUE, then the multicast receive filter
> list on the
> +  network interface will be reset to the default multicast receive
> filter list.
> +  If ResetMCastFilter is FALSE, and this network interface allows
> the multicast
> +  receive filter list to be modified, then the MCastFilterCnt and
> MCastFilter
> +  are used to update the current multicast receive filter list. The
> modified
> +  receive filter list settings can be found in the MCastFilter field
> of
> +  EFI_SIMPLE_NETWORK_MODE. If the network interface does not allow
> the multicast
> +  receive filter list to be modified, then EFI_INVALID_PARAMETER
> will be returned.
> +  If the driver has not been initialized, EFI_DEVICE_ERROR will be
> returned.
> +  If the receive filter mask and multicast receive filter list have
> been
> +  successfully updated on the network interface, EFI_SUCCESS will be
> returned.
> +
> +  @param Snp              A pointer to the
> EFI_SIMPLE_NETWORK_PROTOCOL instance.
> +  @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. For backward compatibility with
> EFI 1.1
> +                          platforms, the
> EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit
> +                          must be set when the ResetMCastFilter
> parameter is TRUE.
> +  @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 following
> conditions is TRUE:
> +                                 * This is NULL
> +                                 * There are bits set in Enable that
> are not set
> +                                   in Snp->Mode->ReceiveFilterMask
> +                                 * There are bits set in Disable
> that are not set
> +                                   in Snp->Mode->ReceiveFilterMask
> +                                 * Multicast is being enabled (the
> +                                   EFI_SIMPLE_NETWORK_RECEIVE_MULTIC
> AST bit is
> +                                   set in Enable, it is not set in
> Disable, and
> +                                   ResetMCastFilter is FALSE) and
> MCastFilterCount
> +                                   is zero
> +                                 * Multicast is being enabled and
> MCastFilterCount
> +                                   is greater than Snp->Mode-
> >MaxMCastFilterCount
> +                                 * Multicast is being enabled and
> MCastFilter is NULL
> +                                 * Multicast is being enabled and
> one or more of
> +                                   the addresses in the MCastFilter
> list are not
> +                                   valid multicast MAC addresses
> +  @retval EFI_DEVICE_ERROR       One or more of the following
> conditions is TRUE:
> +                                 * The network interface has been
> started but has
> +                                   not been initialized
> +                                 * An unexpected error was returned
> by the
> +                                   underlying network driver or
> device
> +  @retval EFI_UNSUPPORTED        This function is not supported by
> the network
> +                                 interface.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SnpReceiveFilters (
> +  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
> +  )
> +{
> +  UINT32                      ReceiveFilterSetting;
> +  EFI_SIMPLE_NETWORK_DRIVER  *Snp;
> +  UINT32                      MacBase;
> +  
> +  Snp = INSTANCE_FROM_SNP_THIS (This);
> +  
> +  // Check Snp Instance
> +  if (Snp == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  // Check that driver was started and initialised
> +  if (Snp->SnpMode.State == EfiSimpleNetworkStarted) {
> +    return EFI_DEVICE_ERROR;
> +  } else if (Snp->SnpMode.State == EfiSimpleNetworkStopped) {
> +    return EFI_NOT_STARTED;
> +  }
> +
> +   if ((Enable  & (~Snp->SnpMode.ReceiveFilterMask)) ||
> +      (Disable & (~Snp->SnpMode.ReceiveFilterMask))    ) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  
> +  //Get MAC base address
> +  MacBase = (UINT32)Snp->Dev->Resources[0].AddrRangeMin;
> +
> +  ReceiveFilterSetting = (Snp->SnpMode.ReceiveFilterSetting |
> Enable) & (~Disable);
> +
> +  EmacRxFilters (ReceiveFilterSetting, ResetMCastFilter,
> MCastFilterCnt, MCastFilter, MacBase);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Modifies or resets the current station address, if supported.
> +
> +  This function modifies or resets the current station address of a
> network
> +  interface, if supported. If Reset is TRUE, then the current
> station address is
> +  set to the network interface's permanent address. If Reset is
> FALSE, and the
> +  network interface allows its station address to be modified, then
> the current
> +  station address is changed to the address specified by New. If the
> network
> +  interface does not allow its station address to be modified, then
> +  EFI_INVALID_PARAMETER will be returned. If the station address is
> successfully
> +  updated on the network interface, EFI_SUCCESS will be returned. If
> the driver
> +  has not been initialized, EFI_DEVICE_ERROR will be returned.
> +
> +  @param Snp      A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL
> instance.
> +  @param Reset    Flag used to reset the station address to the
> network interface's
> +                  permanent address.
> +  @param NewMac   New station address to be used for the network
> interface.
> +
> +
> +  @retval EFI_SUCCESS           The network interface's station
> address was updated.
> +  @retval EFI_NOT_STARTED       The Simple Network Protocol
> interface has not been
> +                                started by calling Start().
> +  @retval EFI_INVALID_PARAMETER The New station address was not
> accepted by the NIC.
> +  @retval EFI_INVALID_PARAMETER Reset is FALSE and New is NULL.
> +  @retval EFI_DEVICE_ERROR      The Simple Network Protocol
> interface has not
> +                                been initialized by calling
> Initialize().
> +  @retval EFI_DEVICE_ERROR      An error occurred attempting to set
> the new
> +                                station address.
> +  @retval EFI_UNSUPPORTED       The NIC does not support changing
> the network
> +                                interface's station address.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SnpStationAddress (
> +  IN        EFI_SIMPLE_NETWORK_PROTOCOL *This,
> +  IN        BOOLEAN                      Reset,
> +  IN        EFI_MAC_ADDRESS             *NewMac
> +)
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +
> +
> +/**
> +  Resets or collects the statistics on a network interface.
> +
> +  This function resets or collects the statistics on a network
> interface. If the
> +  size of the statistics table specified by StatisticsSize is not
> big enough for
> +  all the statistics that are collected by the network interface,
> then a partial
> +  buffer of statistics is returned in StatisticsTable,
> StatisticsSize is set to
> +  the size required to collect all the available statistics, and
> +  EFI_BUFFER_TOO_SMALL is returned.
> +  If StatisticsSize is big enough for all the statistics, then
> StatisticsTable
> +  will be filled, StatisticsSize will be set to the size of the
> returned
> +  StatisticsTable structure, and EFI_SUCCESS is returned.
> +  If the driver has not been initialized, EFI_DEVICE_ERROR will be
> returned.
> +  If Reset is FALSE, and both StatisticsSize and StatisticsTable are
> NULL, then
> +  no operations will be performed, and EFI_SUCCESS will be returned.
> +  If Reset is TRUE, then all of the supported statistics counters on
> this network
> +  interface will be reset to zero.
> +
> +  @param Snp             A pointer to the
> EFI_SIMPLE_NETWORK_PROTOCOL instance.
> +  @param Reset           Set to TRUE to reset the statistics for the
> network interface.
> +  @param StatSize        On input the size, in bytes, of
> StatisticsTable. On output
> +                         the size, in bytes, of the resulting table
> of statistics.
> +  @param Statistics      A pointer to the EFI_NETWORK_STATISTICS
> structure that
> +                         contains the statistics. Type
> EFI_NETWORK_STATISTICS is
> +                         defined in "Related Definitions" below.
> +
> +  @retval EFI_SUCCESS           The requested operation succeeded.
> +  @retval EFI_NOT_STARTED       The Simple Network Protocol
> interface has not been
> +                                started by calling Start().
> +  @retval EFI_BUFFER_TOO_SMALL  StatisticsSize is not NULL and
> StatisticsTable is
> +                                NULL. The current buffer size that
> is needed to
> +                                hold all the statistics is returned
> in StatisticsSize.
> +  @retval EFI_BUFFER_TOO_SMALL  StatisticsSize is not NULL and
> StatisticsTable is
> +                                not NULL. The current buffer size
> that is needed
> +                                to hold all the statistics is
> returned in
> +                                StatisticsSize. A partial set of
> statistics is
> +                                returned in StatisticsTable.
> +  @retval EFI_INVALID_PARAMETER StatisticsSize is NULL and
> StatisticsTable is not
> +                                NULL.
> +  @retval EFI_DEVICE_ERROR      The Simple Network Protocol
> interface has not
> +                                been initialized by calling
> Initialize().
> +  @retval EFI_DEVICE_ERROR      An error was encountered collecting
> statistics
> +                                from the NIC.
> +  @retval EFI_UNSUPPORTED       The NIC does not support collecting
> statistics
> +                                from the network interface.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SnpStatistics (
> +  IN        EFI_SIMPLE_NETWORK_PROTOCOL  *This,
> +  IN        BOOLEAN                      Reset,
> +  IN  OUT   UINTN                        *StatSize,
> +      OUT   EFI_NETWORK_STATISTICS       *Statistics
> +  )
> +{
> +  EFI_SIMPLE_NETWORK_DRIVER  *Snp;
> +  UINT32                      MacBase;
> +
> +  Snp = INSTANCE_FROM_SNP_THIS (This);
> +
> +  DEBUG ((EFI_D_INFO, "SNP:DXE: %a ()\r\n", __FUNCTION__));
> +
> +  // Check Snp instance
> +  if (This == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  // Check that driver was started and initialised
> +  if (Snp->SnpMode.State == EfiSimpleNetworkStarted) {
> +    return EFI_DEVICE_ERROR;
> +  } else if (Snp->SnpMode.State == EfiSimpleNetworkStopped) {
> +    return EFI_NOT_STARTED;
> +  }
> +
> +  // Check pointless condition
> +  if ((!Reset) && (StatSize == NULL) && (Statistics == NULL)) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  // Check the parameters
> +  if ((StatSize == NULL) && (Statistics != NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  // Do a reset if required
> +  if (Reset) {
> +    ZeroMem (&Snp->Stats, sizeof(EFI_NETWORK_STATISTICS));
> +  }
> +
> +  // Check buffer size
> +  if (*StatSize < sizeof(EFI_NETWORK_STATISTICS)) {
> +    *StatSize = sizeof(EFI_NETWORK_STATISTICS);
> +    return EFI_BUFFER_TOO_SMALL;
> +  }
> +  
> +  //Get MAC base address
> +  MacBase = (UINT32)Snp->Dev->Resources[0].AddrRangeMin;
> +  
> +  // read statistic counters
> +  EmacGetStatistic (&Snp->Stats, MacBase);
> +
> +  // Fill in the statistics
> +  CopyMem(&Statistics, &Snp->Stats, sizeof(EFI_NETWORK_STATISTICS));
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Converts a multicast IP address to a multicast HW MAC address.
> +
> +  This function converts a multicast IP address to a multicast HW
> MAC address
> +  for all packet transactions. If the mapping is accepted, then
> EFI_SUCCESS will
> +  be returned.
> +
> +  @param Snp         A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL
> instance.
> +  @param IsIpv6      Set to TRUE if the multicast IP address is IPv6
> [RFC 2460].
> +                     Set to FALSE if the multicast IP address is
> IPv4 [RFC 791].
> +  @param Ip          The multicast IP address that is to be
> converted to a multicast
> +                     HW MAC address.
> +  @param McastMac    The multicast HW MAC address that is to be
> generated from IP.
> +
> +  @retval EFI_SUCCESS           The multicast IP address was mapped
> to the
> +                                multicast HW MAC address.
> +  @retval EFI_NOT_STARTED       The Simple Network Protocol
> interface has not
> +                                been started by calling Start().
> +  @retval EFI_INVALID_PARAMETER IP is NULL.
> +  @retval EFI_INVALID_PARAMETER MAC is NULL.
> +  @retval EFI_INVALID_PARAMETER IP does not point to a valid IPv4 or
> IPv6
> +                                multicast address.
> +  @retval EFI_DEVICE_ERROR      The Simple Network Protocol
> interface has not
> +                                been initialized by calling
> Initialize().
> +  @retval EFI_UNSUPPORTED       IPv6 is TRUE and the implementation
> does not
> +                                support IPv6 multicast to MAC
> address conversion.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SnpMcastIptoMac (
> +  IN        EFI_SIMPLE_NETWORK_PROTOCOL  *This,
> +  IN        BOOLEAN                      IsIpv6,
> +  IN        EFI_IP_ADDRESS               *Ip,
> +      OUT   EFI_MAC_ADDRESS              *McastMac
> +  )
> +{
> +
> +  DEBUG ((EFI_D_INFO, "SNP:DXE: %a ()\r\n", __FUNCTION__));
> +
> +  // Check Snp instance
> +  if (This == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  
> +  EFI_SIMPLE_NETWORK_DRIVER  *Snp;
> +
> +  Snp = INSTANCE_FROM_SNP_THIS (This);
> +
> +  // Check that driver was started and initialised
> +  if (Snp->SnpMode.State == EfiSimpleNetworkStarted) {
> +    return EFI_DEVICE_ERROR;
> +  } else if (Snp->SnpMode.State == EfiSimpleNetworkStopped) {
> +    return EFI_NOT_STARTED;
> +  }
> +
> +  // Check parameters
> +  if ((McastMac == NULL) || (Ip == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  // Make sure MAC address is empty
> +  ZeroMem (McastMac, sizeof(EFI_MAC_ADDRESS));
> +
> +  // If we need ipv4 address
> +  if (!IsIpv6) {
> +    // Most significant 25 bits of a multicast HW address are set.
> +    // 01-00-5E is the IPv4 Ethernet Multicast Address (see RFC
> 1112)
> +    McastMac->Addr[0] = 0x01;
> +    McastMac->Addr[1] = 0x00;
> +    McastMac->Addr[2] = 0x5E;
> +
> +    // Lower 23 bits from ipv4 address
> +    McastMac->Addr[3] = (Ip->v4.Addr[1] & 0x7F); // Clear the most
> significant bit (25th bit of MAC must be 0)
> +    McastMac->Addr[4] = Ip->v4.Addr[2];
> +    McastMac->Addr[5] = Ip->v4.Addr[3];
> +  } else {
> +    // Most significant 16 bits of multicast v6 HW address are set
> +    // 33-33 is the IPv6 Ethernet Multicast Address (see RFC 2464)
> +    McastMac->Addr[0] = 0x33;
> +    McastMac->Addr[1] = 0x33;
> +
> +    // lower four octets are taken from ipv6 address
> +    McastMac->Addr[2] = Ip->v6.Addr[8];
> +    McastMac->Addr[3] = Ip->v6.Addr[9];
> +    McastMac->Addr[4] = Ip->v6.Addr[10];
> +    McastMac->Addr[5] = Ip->v6.Addr[11];
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Performs read and write operations on the NVRAM device attached to
> a network
> +  interface.
> +
> +  This function performs read and write operations on the NVRAM
> device attached
> +  to a network interface. If ReadWrite is TRUE, a read operation is
> performed.
> +  If ReadWrite is FALSE, a write operation is performed. Offset
> specifies the
> +  byte offset at which to start either operation. Offset must be a
> multiple of
> +  NvRamAccessSize , and it must have a value between zero and
> NvRamSize.
> +  BufferSize specifies the length of the read or write operation.
> BufferSize must
> +  also be a multiple of NvRamAccessSize, and Offset + BufferSize
> must not exceed
> +  NvRamSize.
> +  If any of the above conditions is not met, then
> EFI_INVALID_PARAMETER will be
> +  returned.
> +  If all the conditions are met and the operation is "read," the
> NVRAM device
> +  attached to the network interface will be read into Buffer and
> EFI_SUCCESS
> +  will be returned. If this is a write operation, the contents of
> Buffer will be
> +  used to update the contents of the NVRAM device attached to the
> network
> +  interface and EFI_SUCCESS will be returned.
> +
> +  It does the basic checking on the input parameters and retrieves
> snp structure
> +  and then calls the read_nvdata() call which does the actual
> reading
> +
> +  @param Snp        A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL
> instance.
> +  @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. (See
> EFI_SIMPLE_NETWORK_MODE)
> +  @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 following
> conditions is TRUE:
> +                                * The This parameter is NULL
> +                                * The This parameter does not point
> to a valid
> +                                  EFI_SIMPLE_NETWORK_PROTOCOL  struc
> ture
> +                                * The Offset parameter is not a
> multiple of
> +                                  EFI_SIMPLE_NETWORK_MODE.NvRamAcces
> sSize
> +                                * The Offset parameter is not less
> than
> +                                  EFI_SIMPLE_NETWORK_MODE.NvRamSize
> +                                * The BufferSize parameter is not a
> multiple of
> +                                  EFI_SIMPLE_NETWORK_MODE.NvRamAcces
> sSize
> +                                * The Buffer parameter is NULL
> +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> network
> +                                interface.
> +  @retval EFI_UNSUPPORTED       This function is not supported by
> the network
> +                                interface.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SnpNvData (
> +  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.
> +
> +  This function gets the current interrupt and recycled transmit
> buffer status
> +  from the network interface. The interrupt status is returned as a
> bit mask in
> +  InterruptStatus. If InterruptStatus is NULL, the interrupt status
> will not be
> +  read. If TxBuf is not NULL, a recycled transmit buffer address
> will be retrieved.
> +  If a recycled transmit buffer address is returned in TxBuf, then
> the buffer has
> +  been successfully transmitted, and the status for that buffer is
> cleared. If
> +  the status of the network interface is successfully collected,
> EFI_SUCCESS
> +  will be returned. If the driver has not been initialized,
> EFI_DEVICE_ERROR will
> +  be returned.
> +
> +  @param Snp             A pointer to the
> EFI_SIMPLE_NETWORK_PROTOCOL instance.
> +  @param IrqStat         A pointer to the bit mask of the currently
> active
> +                         interrupts (see "Related Definitions"). 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 TxBuff          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 This parameter was NULL or did not
> point to a valid
> +                                EFI_SIMPLE_NETWORK_PROTOCOL
> structure.
> +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> network
> +                                interface.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SnpGetStatus (
> +  IN    EFI_SIMPLE_NETWORK_PROTOCOL *This,
> +  OUT   UINT32                      *IrqStat  OPTIONAL,
> +  OUT   VOID                        **TxBuff  OPTIONAL
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  EFI_SIMPLE_NETWORK_DRIVER  *Snp;
> +  UINT32                      MacBase;
> +
> +  Snp = INSTANCE_FROM_SNP_THIS (This);
> +
> +  // Check preliminaries
> +  if (This == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  if (Snp->SnpMode.State != EfiSimpleNetworkInitialized) {
> +    return EFI_NOT_STARTED;
> +  }
> +  
> +  // Get MAC base address
> +  MacBase = (UINT32)Snp->Dev->Resources[0].AddrRangeMin;
> +  
> +  // Update the media status
> +  Status = PhyLinkAdjustEmacConfig (&Snp->PhyDriver, MacBase);
> +  if (EFI_ERROR(Status)) {
> +    Snp->SnpMode.MediaPresent = FALSE;
> +  } else {
> +    Snp->SnpMode.MediaPresent = TRUE;
> +  }
> +  
> +  // TxBuff  
> +  if (TxBuff != NULL) {
> +    //
> +    // Get a recycled buf from Snp->RecycledTxBuf
> +    //
> +    if (Snp->RecycledTxBufCount == 0) {
> +      *TxBuff = NULL;
> +    } else {
> +      Snp->RecycledTxBufCount--;
> +      *TxBuff = (VOID *) (UINTN) Snp->RecycledTxBuf[Snp-
> >RecycledTxBufCount];
> +    }
> +  }
> +  
> +  // Check DMA Irq status
> +  EmacGetDmaStatus (IrqStat, MacBase);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Places a packet in the transmit queue of a network interface.
> +
> +  This function places the packet specified by Header and Buffer on
> the transmit
> +  queue. If HeaderSize is nonzero and HeaderSize is not equal to
> +  This->Mode->MediaHeaderSize, then EFI_INVALID_PARAMETER will be
> returned. If
> +  BufferSize is less than This->Mode->MediaHeaderSize, then
> EFI_BUFFER_TOO_SMALL
> +  will be returned. If Buffer is NULL, then EFI_INVALID_PARAMETER
> will be
> +  returned. If HeaderSize is nonzero and DestAddr or Protocol is
> NULL, then
> +  EFI_INVALID_PARAMETER will be returned. If the transmit engine of
> the network
> +  interface is busy, then EFI_NOT_READY will be returned. If this
> packet can be
> +  accepted by the transmit engine of the network interface, the
> packet contents
> +  specified by Buffer will be placed on the transmit queue of the
> network
> +  interface, and EFI_SUCCESS will be returned. GetStatus() can be
> used to
> +  determine when the packet has actually been transmitted. The
> contents of the
> +  Buffer must not be modified until the packet has actually been
> transmitted.
> +  The Transmit() function performs nonblocking I/O. A caller who
> wants to perform
> +  blocking I/O, should call Transmit(), and then GetStatus() until
> the
> +  transmitted buffer shows up in the recycled transmit buffer.
> +  If the driver has not been initialized, EFI_DEVICE_ERROR will be
> returned.
> +
> +  @param Snp        A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL
> instance.
> +  @param HdrSize    The size, in bytes, of the media header to be
> filled in by the
> +                    Transmit() function. If HeaderSize is nonzero,
> then it must
> +                    be equal to This->Mode->MediaHeaderSize and the
> DestAddr and
> +                    Protocol parameters must not be NULL.
> +  @param BuffSize   The size, in bytes, of the entire packet (media
> header and
> +                    data) to be transmitted through the network
> interface.
> +  @param Data       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 nonzero, 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 nonzero
> and SrcAddr
> +                    is NULL, then This->Mode->CurrentAddress is used
> for the
> +                    source HW MAC address.
> +  @param DstAddr    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 command could not be sent to the
> network interface.
> +  @retval EFI_UNSUPPORTED       This function is not supported by
> the network interface.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SnpTransmit (
> +  IN  EFI_SIMPLE_NETWORK_PROTOCOL  *This,
> +  IN  UINTN                        HdrSize,
> +  IN  UINTN                        BuffSize,
> +  IN  VOID*                        Data,
> +  IN  EFI_MAC_ADDRESS              *SrcAddr  OPTIONAL,
> +  IN  EFI_MAC_ADDRESS              *DstAddr  OPTIONAL,
> +  IN  UINT16                       *Protocol OPTIONAL
> +  )
> +{
> +  EFI_SIMPLE_NETWORK_DRIVER *Snp;
> +  UINT32                     DescNum;
> +  DESIGNWARE_HW_DESCRIPTOR  *TxDescriptor;
> +  UINT8*                     EthernetPacket;
> +  UINT64                    *Tmp;
> +  UINT32                     MacBase;
> +
> +  EthernetPacket = Data;
> +
> +  Snp = INSTANCE_FROM_SNP_THIS (This);
> +  
> +  if (EFI_ERROR (EfiAcquireLockOrFail (&Snp->Lock))) {
> +    return EFI_ACCESS_DENIED;
> +  }
> +
> +  // Check preliminaries
> +  if ((This == NULL) || (Data == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  if (Snp->SnpMode.State != EfiSimpleNetworkInitialized) {
> +    return EFI_NOT_STARTED;
> +  }
> +
> +  Snp->MacDriver.TxCurrentDescriptorNum = Snp-
> >MacDriver.TxNextDescriptorNum;
> +  DescNum = Snp->MacDriver.TxCurrentDescriptorNum;
> +
> +  TxDescriptor = Snp->MacDriver.TxdescRing[0] + (DescNum);;
> +
> +  // Ensure header is correct size if non-zero
> +  if (HdrSize) {
> +    if (HdrSize != Snp->SnpMode.MediaHeaderSize) {
> +      return EFI_INVALID_PARAMETER;
> +    }
> +
> +    if ((DstAddr == NULL) || (Protocol == NULL)) {
> +      return EFI_INVALID_PARAMETER;
> +    }
> +  }
> +  
> +  // Ensure buffer size is valid
> +  if (BuffSize < Snp->SnpMode.MediaHeaderSize) {
> +    return EFI_BUFFER_TOO_SMALL;
> +  }
> +
> +
> +  if (HdrSize) {
> +    EthernetPacket[0] = DstAddr->Addr[0];
> +    EthernetPacket[1] = DstAddr->Addr[1];
> +    EthernetPacket[2] = DstAddr->Addr[2];
> +    EthernetPacket[3] = DstAddr->Addr[3];
> +    EthernetPacket[4] = DstAddr->Addr[4];
> +    EthernetPacket[5] = DstAddr->Addr[5];
> +
> +    EthernetPacket[6] = SrcAddr->Addr[0];
> +    EthernetPacket[7] = SrcAddr->Addr[1];
> +    EthernetPacket[8] = SrcAddr->Addr[2];
> +    EthernetPacket[9] = SrcAddr->Addr[3];
> +    EthernetPacket[10] = SrcAddr->Addr[4];
> +    EthernetPacket[11] = SrcAddr->Addr[5];
> +
> +    EthernetPacket[13] = *Protocol & 0xFF;
> +    EthernetPacket[12] = (*Protocol & 0xFF00) >> 8;
> +  }
> +
> +  CopyMem((VOID*)(UINTN)TxDescriptor->Addr, EthernetPacket,
> BuffSize);
> +  
> +  TxDescriptor->Tdes1 = (BuffSize << TDES1_SIZE1SHFT) &
> +                         TDES1_SIZE1MASK;
> +  
> +  TxDescriptor->Tdes0 |= (TDES0_TXFIRST |
> +                          TDES0_TXLAST |
> +                          TDES0_OWN);
> +  
> +  // Increase descriptor number
> +  DescNum++;
> +  if (DescNum >= CONFIG_TX_DESCR_NUM)
> +    DescNum = 0;
> +
> +  Snp->MacDriver.TxNextDescriptorNum = DescNum;
> +  
> +  if ((Snp->MaxRecycledTxBuf + SNP_TX_BUFFER_INCREASEMENT) >=
> SNP_MAX_TX_BUFFER_NUM) {
> +    return EFI_NOT_READY;
> +  }
> +
> +  if (Snp->RecycledTxBufCount < Snp->MaxRecycledTxBuf) {
> +    Snp->RecycledTxBuf[Snp->RecycledTxBufCount] = (UINT64) Data;
> +    Snp->RecycledTxBufCount ++;
> +  } else {
> +    Tmp = AllocatePool (sizeof (UINT64) * (Snp->MaxRecycledTxBuf +
> SNP_TX_BUFFER_INCREASEMENT));
> +    if (Tmp == NULL) {
> +      return EFI_DEVICE_ERROR;
> +    }
> +    CopyMem (Tmp, Snp->RecycledTxBuf, sizeof (UINT64) * Snp-
> >RecycledTxBufCount);
> +    FreePool (Snp->RecycledTxBuf);
> +    Snp->RecycledTxBuf    =  Tmp;
> +    Snp->MaxRecycledTxBuf += SNP_TX_BUFFER_INCREASEMENT;
> +  }
> +  
> +  // Get MAC base address
> +  MacBase = (UINT32)Snp->Dev->Resources[0].AddrRangeMin;
> +  
> +  // Start the transmission
> +  EmacDmaStart (MacBase);
> +  
> +  EfiReleaseLock (&Snp->Lock);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Receives a packet from a network interface.
> +
> +  This function retrieves one packet from the receive queue of a
> network interface.
> +  If there are no packets on the receive queue, then EFI_NOT_READY
> will be
> +  returned. If there is a packet on the receive queue, and the size
> of the packet
> +  is smaller than BufferSize, then the contents of the packet will
> be placed in
> +  Buffer, and BufferSize will be updated with the actual size of the
> packet.
> +  In addition, if SrcAddr, DestAddr, and Protocol are not NULL, then
> these values
> +  will be extracted from the media header and returned. EFI_SUCCESS
> will be
> +  returned if a packet was successfully received.
> +  If BufferSize is smaller than the received packet, then the size
> of the receive
> +  packet will be placed in BufferSize and EFI_BUFFER_TOO_SMALL will
> be returned.
> +  If the driver has not been initialized, EFI_DEVICE_ERROR will be
> returned.
> +
> +  @param Snp        A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL
> instance.
> +  @param HdrSize    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 BuffSize   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 Data       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 DstAddr   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 have been received on the
> network interface.
> +  @retval EFI_BUFFER_TOO_SMALL  BufferSize is too small for the
> received packets.
> +                                BufferSize has been updated to the
> required size.
> +  @retval EFI_INVALID_PARAMETER One or more of the following
> conditions is TRUE:
> +                                * The This parameter is NULL
> +                                * The This parameter does not point
> to a valid
> +                                  EFI_SIMPLE_NETWORK_PROTOCOL
> structure.
> +                                * The BufferSize parameter is NULL
> +                                * The Buffer parameter is NULL
> +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> network interface.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SnpReceive (
> +  IN        EFI_SIMPLE_NETWORK_PROTOCOL *This,
> +      OUT   UINTN                       *HdrSize      OPTIONAL,
> +  IN  OUT   UINTN                       *BuffSize,
> +      OUT   VOID                        *Data,
> +      OUT   EFI_MAC_ADDRESS             *SrcAddr      OPTIONAL,
> +      OUT   EFI_MAC_ADDRESS             *DstAddr      OPTIONAL,
> +      OUT   UINT16                      *Protocol     OPTIONAL
> +  )
> +{
> +  EFI_SIMPLE_NETWORK_DRIVER  *Snp;
> +  EFI_MAC_ADDRESS Dst;
> +  EFI_MAC_ADDRESS Src;
> +  UINT32          Length, DesciptorStatus;
> +  UINT8*          RawData;
> +  UINT32 DescNum;
> +  DESIGNWARE_HW_DESCRIPTOR *RxDescriptor;
> +  
> +  Snp = INSTANCE_FROM_SNP_THIS (This);
> +
> +  // Check preliminaries
> +  if ((This == NULL) || (Data == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (Snp->SnpMode.State != EfiSimpleNetworkInitialized) {
> +    return EFI_NOT_STARTED;
> +  }
> +  
> +  Snp = INSTANCE_FROM_SNP_THIS (This);
> +  
> +  if (EFI_ERROR (EfiAcquireLockOrFail (&Snp->Lock))) {
> +    return EFI_ACCESS_DENIED;
> +  }
> +  
> +  Snp->MacDriver.RxCurrentDescriptorNum = Snp-
> >MacDriver.RxNextDescriptorNum;
> +  DescNum = Snp->MacDriver.RxCurrentDescriptorNum;
> +  RxDescriptor = Snp->MacDriver.RxdescRing[0]+(DescNum);
> +  
> +  RawData = (UINT8*) Data;
> +
> +  DesciptorStatus = RxDescriptor->Tdes0;
> +
> +  if (DesciptorStatus & ((UINT32)RDES0_OWN)) {
> +	goto ReleaseLock;
> +  }
> +
> +
> +  if (DesciptorStatus & RDES0_SAF) {
> +    DEBUG ((EFI_D_WARN, "SNP:DXE: Rx Descritpor Status Error: Source
> Address Filter Fail\n"));
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  if (DesciptorStatus & RDES0_AFM) {
> +    DEBUG ((EFI_D_WARN, "SNP:DXE: Rx Descritpor Status Error:
> Destination Address Filter Fail\n"));
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  if (DesciptorStatus & RDES0_ES) {
> +    // Check for errors
> +    if (DesciptorStatus & RDES0_RE) {
> +      DEBUG ((EFI_D_WARN, "SNP:DXE: Rx Descritpor Status Error:
> Receive Error\n"));
> +    }
> +    if (DesciptorStatus & RDES0_DE) {
> +      DEBUG ((EFI_D_WARN, "SNP:DXE: Rx Descritpor Status Error:
> Receive Error\n"));
> +    }
> +    if (DesciptorStatus & RDES0_RWT) {
> +      DEBUG ((EFI_D_WARN, "SNP:DXE: Rx Descritpor Status Error:
> Watchdog Timeout\n"));
> +    }
> +    if (DesciptorStatus & RDES0_LC) {
> +      DEBUG ((EFI_D_WARN, "SNP:DXE: Rx Descritpor Status Error: Late
> Collision\n"));
> +    }
> +    if (DesciptorStatus & RDES0_GF) {
> +      DEBUG ((EFI_D_WARN, "SNP:DXE: Rx Descritpor Status Error:
> Giant Frame\n"));
> +    }
> +    if (DesciptorStatus & RDES0_OE) {
> +      DEBUG ((EFI_D_WARN, "SNP:DXE: Rx Descritpor Status Error:
> Overflow Error\n"));
> +    }
> +    if (DesciptorStatus & RDES0_LE) {
> +      DEBUG ((EFI_D_WARN, "SNP:DXE: Rx Descritpor Status
> Error:Length Error\n"));
> +    }
> +    if (DesciptorStatus & RDES0_DBE) {
> +      DEBUG ((EFI_D_WARN, "SNP:DXE: Rx Descritpor Status Error:
> Dribble Bit Error\n"));
> +    }
> +
> +    // Check descriptor error status
> +    if (DesciptorStatus & RDES0_CE) {
> +      DEBUG ((EFI_D_WARN, "SNP:DXE: Rx Descritpor Status Error: CRC
> Error\n"));
> +    }
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  Length = (DesciptorStatus >> RDES0_FL_SHIFT) & RDES0_FL_MASK;
> +  if (!Length) {
> +    DEBUG ((EFI_D_WARN, "SNP:DXE: Error: Invalid Frame Packet length
> \r\n"));
> +    return EFI_NOT_READY;
> +  }
> +  // Check buffer size
> +  if (*BuffSize < Length) {
> +    DEBUG ((EFI_D_WARN, "SNP:DXE: Error: Buffer size is too
> small\n"));
> +    return EFI_BUFFER_TOO_SMALL;
> +  }
> +  *BuffSize = Length;
> +  
> +  if (HdrSize != NULL)
> +    *HdrSize = Snp->SnpMode.MediaHeaderSize;
> +
> +  CopyMem (RawData, (VOID*)(UINTN) RxDescriptor->Addr, *BuffSize);
> +
> +  if (DstAddr != NULL) {
> +    Dst.Addr[0] = RawData[0];
> +    Dst.Addr[1] = RawData[1];
> +    Dst.Addr[2] = RawData[2];
> +    Dst.Addr[3] = RawData[3];
> +    Dst.Addr[4] = RawData[4];
> +    Dst.Addr[5] = RawData[5];
> +    CopyMem (DstAddr, &Dst, NET_ETHER_ADDR_LEN);
> +Print(L"received from source address %x %x\n\n", DstAddr, &Dst);
> +  }
> + 
> +  // Get the source address
> +  if (SrcAddr != NULL) {
> +    Src.Addr[0] = RawData[6];
> +    Src.Addr[1] = RawData[7];
> +    Src.Addr[2] = RawData[8];
> +    Src.Addr[3] = RawData[9];
> +    Src.Addr[4] = RawData[10];
> +    Src.Addr[5] = RawData[11];
> +Print(L"received from source address %x %x\n\n", SrcAddr, &Src);
> +    CopyMem (SrcAddr,&Src, NET_ETHER_ADDR_LEN);
> +  }
> +
> +  // Get the protocol
> +  if (Protocol != NULL) {
> +   *Protocol = NTOHS (RawData[12] | (RawData[13] >> 8) |
> (RawData[14] >> 16) | (RawData[15] >> 24));
> +  }
> +
> +  RxDescriptor->Tdes0 |= (UINT32)RDES0_OWN;
> +
> +  DescNum++;
> +
> +  if (DescNum >= CONFIG_RX_DESCR_NUM)
> +    DescNum = 0;
> +
> +  Snp->MacDriver.RxNextDescriptorNum = DescNum;
> +  
> +  EfiReleaseLock (&Snp->Lock);
> +  
> +  return EFI_SUCCESS;
> +  
> +  ReleaseLock:
> +  EfiReleaseLock (&Snp->Lock);
> +  return EFI_NOT_READY;
> +  
> +}
> +
> diff --git a/Silicon/DesignWare/Drivers/DwEmacSnpDxe/EmacDxeUtil.c
> b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/EmacDxeUtil.c
> new file mode 100755
> index 000000000000..a7f29f6cd0c7
> --- /dev/null
> +++ b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/EmacDxeUtil.c
> @@ -0,0 +1,684 @@
> +/** @file
> +
> +  Copyright (c) 2011 - 2019, Intel Corporaton. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of
> the BSD License
> +  which accompanies this distribution.  The full text of the license
> may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +  
> +  The original software modules are licensed as follows:
> +
> +  Copyright (c) 2012 - 2014, ARM Limited. All rights reserved.
> +  Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of
> the BSD License
> +  which accompanies this distribution.  The full text of the license
> may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD 3 Clause LICENSE ON AN
> "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +**/
> +
> +#include "EmacDxeUtil.h"
> +#include "PhyDxeUtil.h"
> +
> +VOID
> +EFIAPI
> +EmacSetMacAddress (
> +  IN EFI_MAC_ADDRESS  *MacAddress,
> +  IN UINT32            MacBaseAddress
> +  )
> +{
> +  DEBUG ((EFI_D_INFO,"SNP:MAC: %a ()\r\n", __FUNCTION__));
> +
> +  // Note: This MAC_ADDR0 registers programming sequence cannot be
> swap:
> +  // Must program HIGH Offset first before LOW Offset
> +  // because synchronization is triggered when MAC Address0 Low
> Register are written.
> +  MmioWrite32 (MacBaseAddress
> +DW_EMAC_GMACGRP_MAC_ADDRESS0_HIGH_OFST,
> +               (UINT32)(MacAddress->Addr[4] & 0xFF) |
> +                      ((MacAddress->Addr[5] & 0xFF) << 8)
> +                    );
> +  // MacAddress->Addr[0,1,2] is the 3 bytes OUI
> +  MmioWrite32 (MacBaseAddress +
> DW_EMAC_GMACGRP_MAC_ADDRESS0_LOW_OFST,
> +                       (MacAddress->Addr[0] & 0xFF) |
> +                      ((MacAddress->Addr[1] & 0xFF) << 8) |
> +                      ((MacAddress->Addr[2] & 0xFF) << 16) |
> +                      ((MacAddress->Addr[3] & 0xFF) << 24)
> +                    );
> +
> +  DEBUG ((EFI_D_INFO, "SNP:MAC: gmacgrp_mac_address0_low  = 0x%08X
> \r\n", MmioRead32 (MacBaseAddress +
> DW_EMAC_GMACGRP_MAC_ADDRESS0_LOW_OFST)));
> +  DEBUG ((EFI_D_INFO, "SNP:MAC: gmacgrp_mac_address0_high = 0x%08X
> \r\n", MmioRead32 (MacBaseAddress
> +DW_EMAC_GMACGRP_MAC_ADDRESS0_HIGH_OFST)));
> +}
> +
> +
> +VOID
> +EFIAPI
> +EmacReadMacAddress (
> +  OUT EFI_MAC_ADDRESS *MacAddress,
> +  IN UINT32            MacBaseAddress
> +  )
> +{
> +  UINT32          MacAddrHighValue;
> +  UINT32          MacAddrLowValue;
> +
> +  DEBUG ((EFI_D_INFO, "SNP:MAC: %a ()\r\n", __FUNCTION__));
> +
> +  // Read the Mac Addr high register
> +  MacAddrHighValue = (MmioRead32 (MacBaseAddress
> +DW_EMAC_GMACGRP_MAC_ADDRESS0_HIGH_OFST) & 0xFFFF);
> +  // Read the Mac Addr low register
> +  MacAddrLowValue = MmioRead32 (MacBaseAddress +
> DW_EMAC_GMACGRP_MAC_ADDRESS0_LOW_OFST);
> +
> +  SetMem (MacAddress, sizeof(*MacAddress), 0);
> +  MacAddress->Addr[0] = (MacAddrLowValue & 0xFF);
> +  MacAddress->Addr[1] = (MacAddrLowValue & 0xFF00) >> 8;
> +  MacAddress->Addr[2] = (MacAddrLowValue & 0xFF0000) >> 16;
> +  MacAddress->Addr[3] = (MacAddrLowValue & 0xFF000000) >> 24;
> +  MacAddress->Addr[4] = (MacAddrHighValue & 0xFF);
> +  MacAddress->Addr[5] = (MacAddrHighValue & 0xFF00) >> 8;
> +
> +  DEBUG ((EFI_D_INFO, "SNP:MAC: MAC Address =
> %02X:%02X:%02X:%02X:%02X:%02X\r\n",
> +    MacAddress->Addr[0], MacAddress->Addr[1], MacAddress->Addr[2],
> +    MacAddress->Addr[3], MacAddress->Addr[4], MacAddress->Addr[5]
> +  ));
> +
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +EmacDxeInitialization (
> +  IN EMAC_DRIVER* EmacDriver,
> +  IN UINT32 MacBaseAddress
> +  )
> +{
> +  DEBUG ((EFI_D_INFO, "SNP:MAC: %a ()\r\n", __FUNCTION__));
> +
> +  // Init EMAC DMA
> +  EmacDmaInit (EmacDriver, MacBaseAddress);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +EFI_STATUS
> +EFIAPI
> +EmacDmaInit (
> +  IN   EMAC_DRIVER      *EmacDriver,
> +  IN   UINT32           MacBaseAddress
> +  )
> +{
> +  UINT32 DmaConf;
> +  UINT32 DmaOpmode;
> +  UINT32 InterruptEnable;
> +
> +  DEBUG ((EFI_D_INFO, "SNP:MAC: %a ()\r\n", __FUNCTION__));
> +
> +  // This section provides the instructions for initializing the DMA
> registers in the proper sequence. This
> +  // initialization sequence can be done after the EMAC interface
> initialization has been completed. Perform
> +  // the following steps to initialize the DMA:
> +  // 1. Provide a software reset to reset all of the EMAC internal
> registers and logic. (DMA Register 0 (Bus
> +  // Mode Register) � bit 0).
> +
> +  MmioOr32 (MacBaseAddress +
> +             DW_EMAC_DMAGRP_BUS_MODE_OFST,
> +             DW_EMAC_DMAGRP_BUS_MODE_SWR_SET_MSK);
> +
> +  // 2. Wait for the completion of the reset process (poll bit 0 of
> the DMA Register 0 (Bus Mode Register),
> +  // which is only cleared after the reset operation is completed).
> +  while (DW_EMAC_DMAGRP_BUS_MODE_SWR_GET (MmioRead32 (MacBaseAddress
> + DW_EMAC_DMAGRP_BUS_MODE_OFST)));
> +
> +  // 3. Poll the bits of Register 11 (AHB or AXI Status) to confirm
> that all previously initiated (before
> +  // software reset) or ongoing transactions are complete.
> +  // Note: If the application cannot poll the register after soft
> reset (because of performance reasons), then
> +  // it is recommended that you continue with the next steps and
> check this register again (as
> +  // mentioned in 12 on page 1-72) before triggering the DMA
> operations.�
> +
> +  // 4. Program the following fields to initialize the Bus Mode
> Register by setting values in DMA Register 0
> +  // (Bus Mode Register):
> +  // � Mixed Burst and AAL
> +  // � Fixed burst or undefined burst
> +  // � Burst length values and burst mode values
> +  // � Descriptor Length (only valid if Ring Mode is used)
> +  // � TX and RX DMA Arbitration scheme
> +  // 5. Program the interface options in Register 10 (AXI Bus Mode
> Register). If fixed burst-length is enabled,
> +  // then select the maximum burst-length possible on the bus
> (bits[7:1]).�
> +
> +  DmaConf = DW_EMAC_DMAGRP_BUS_MODE_FB_SET_MSK |
> DW_EMAC_DMAGRP_BUS_MODE_PBL_SET_MSK |
> DW_EMAC_DMAGRP_BUS_MODE_PR_SET_MSK;
> +  MmioOr32 (MacBaseAddress +
> +            DW_EMAC_DMAGRP_BUS_MODE_OFST,
> +            DmaConf);
> +
> +  // 6. Create a proper descriptor chain for transmit and receive.
> In addition, ensure that the receive descriptors
> +  // are owned by DMA (bit 31 of descriptor should be set). When OSF
> mode is used, at least two
> +  // descriptors are required.
> +  // 7. Make sure that your software creates three or more different
> transmit or receive descriptors in the
> +  // chain before reusing any of the descriptors.
> +  // 8. Initialize receive and transmit descriptor list address with
> the base address of the transmit and receive
> +  // descriptor (Register 3 (Receive Descriptor List Address
> Register) and Register 4 (Transmit Descriptor
> +  // List Address Register) respectively).
> +  
> +  EmacSetupTxdesc (EmacDriver, MacBaseAddress);
> +  EmacSetupRxdesc (EmacDriver, MacBaseAddress);
> +
> +  // 9. Program the following fields to initialize the mode of
> operation in Register 6 (Operation Mode
> +  // Register):
> +  // � Receive and Transmit Store And Forward�
> +  // � Receive and Transmit Threshold Control (RTC and TTC)�
> +  // � Hardware Flow Control enable�
> +  // � Flow Control Activation and De-activation thresholds for MTL
> Receive and Transmit FIFO buffers
> +  // (RFA and RFD)�
> +  // � Error frame and undersized good frame forwarding enable�
> +  // � OSF Mode�
> +
> +  DmaOpmode = DW_EMAC_DMAGRP_OPERATION_MODE_FTF_SET_MSK |
> DW_EMAC_DMAGRP_OPERATION_MODE_TSF_SET_MSK;
> +  MmioOr32 (MacBaseAddress +
> +            DW_EMAC_DMAGRP_OPERATION_MODE_OFST,
> +            DmaOpmode);
> +  //while (DW_EMAC_DMAGRP_OPERATION_MODE_FTF_GET (MmioRead32
> (MacBaseAddress + DW_EMAC_DMAGRP_OPERATION_MODE_OFST)));
> + 
> +  // 10.Clear the interrupt requests, by writing to those bits of
> the status register (interrupt bits only) that are
> +  // set. For example, by writing 1 into bit 16, the normal
> interrupt summary clears this bit (DMA Register 5 (Status Register)).
> +  MmioOr32 (MacBaseAddress +
> +            DW_EMAC_DMAGRP_STATUS_OFST,
> +            0x1FFFF);
> +
> +  // 11.Enable the interrupts by programming Register 7 (Interrupt
> Enable Register).
> +  InterruptEnable = DW_EMAC_DMAGRP_INTERRUPT_ENABLE_TIE_SET_MSK |
> +                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_RIE_SET_MSK |
> +                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_NIE_SET_MSK |
> +                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_AIE_SET_MSK |
> +                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_FBE_SET_MSK |
> +                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_UNE_SET_MSK |
> +                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_TSE_SET_MSK |
> +                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_TUE_SET_MSK |
> +                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_TJE_SET_MSK |
> +                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_OVE_SET_MSK |
> +                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_RUE_SET_MSK |
> +                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_RSE_SET_MSK |
> +                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_RWE_SET_MSK |
> +                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_ETE_SET_MSK |
> +                    DW_EMAC_DMAGRP_INTERRUPT_ENABLE_ERE_SET_MSK;
> +   MmioWrite32 (MacBaseAddress +
> +                DW_EMAC_DMAGRP_INTERRUPT_ENABLE_OFST,
> +                InterruptEnable);
> +
> +  // 12.Read Register 11 (AHB or AXI Status) to confirm that all
> previous transactions are complete.�
> +  // Note: If any previous transaction is still in progress when you
> read the Register 11 (AHB or AXI
> +  // Status), then it is strongly recommended to check the slave
> components addressed by the
> +  // master interface.
> +  if (MmioRead32 (MacBaseAddress +
> DW_EMAC_DMAGRP_AHB_OR_AXI_STATUS_OFST) != 0) {
> +    DEBUG ((EFI_D_INFO, "SNP:MAC: Error! Previous AXI transaction is
> still in progress\r\n"));
> +    //check the slave components addressed by the master interface
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  DmaOpmode = DW_EMAC_DMAGRP_OPERATION_MODE_ST_SET_MSK |
> DW_EMAC_DMAGRP_OPERATION_MODE_SR_SET_MSK;
> +  MmioOr32 (MacBaseAddress +
> +            DW_EMAC_DMAGRP_OPERATION_MODE_OFST,
> +            DmaOpmode);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +EFI_STATUS
> +EFIAPI
> +EmacSetupTxdesc (
> +  IN EMAC_DRIVER *EmacDriver,
> +  IN UINT32 MacBaseAddress
> + )
> +{
> +  INTN Index;
> +  DESIGNWARE_HW_DESCRIPTOR *TxDescriptor;
> +
> +  for (Index = 0; Index < CONFIG_TX_DESCR_NUM; Index++) {
> +	TxDescriptor = (VOID*)EmacDriver->TxdescRingMap[0]+(Index*16);;
> +	TxDescriptor->Addr = (UINT32)(UINTN) EmacDriver->TxBufferMap[0] 
> + (Index*2048);
> +	TxDescriptor->AddrNext = (UINT32)(UINTN) EmacDriver-
> >TxdescRingMap[0] + ((Index + 1)*16);
> +	TxDescriptor->Tdes0 = TDES0_TXCHAIN;
> +    TxDescriptor->Tdes1 = 0;
> +  }
> +
> +  // Correcting the last pointer of the chain
> +  TxDescriptor->AddrNext = (UINT32)(UINTN) EmacDriver-
> >TxdescRingMap[0];
> +
> +  // Write the address of tx descriptor list
> +  MmioWrite32(MacBaseAddress +
> +              DW_EMAC_DMAGRP_TRANSMIT_DESCRIPTOR_LIST_ADDRESS_OFST,
> +              (UINT32)(UINTN) EmacDriver->TxdescRingMap[0]);
> +
> +  // Initialize the descriptor number
> +  EmacDriver->TxCurrentDescriptorNum = 0;
> +  EmacDriver->TxNextDescriptorNum = 0;
> +  
> +  return EFI_SUCCESS;
> +}
> +
> +
> +EFI_STATUS
> +EFIAPI
> +EmacSetupRxdesc (
> +  IN EMAC_DRIVER *EmacDriver,
> +  IN UINT32 MacBaseAddress
> +  )
> +{
> +  INTN                      Index;
> +  DESIGNWARE_HW_DESCRIPTOR *RxDescriptor;
> +
> +  for (Index = 0; Index < CONFIG_RX_DESCR_NUM; Index++) {
> +	RxDescriptor = (VOID*) (EmacDriver->RxdescRingMap[0] +
> (Index*16));
> +    RxDescriptor->Addr = (UINT32)(UINTN) EmacDriver->RxBufferMap[0]
> + (Index*2048);
> +    RxDescriptor->AddrNext = (UINT32)(UINTN) EmacDriver-
> >RxdescRingMap[0] + ((Index + 1)*16);
> +    RxDescriptor->Tdes0 = RDES0_OWN;
> +    RxDescriptor->Tdes1 = RDES1_CHAINED | RX_MAX_PACKET;
> +  }
> +
> +  // Correcting the last pointer of the chain
> +  RxDescriptor->AddrNext = (UINT32)(UINTN) EmacDriver-
> >RxdescRingMap[0];
> +
> +  // Write the address of tx descriptor list
> +  MmioWrite32(MacBaseAddress +
> +              DW_EMAC_DMAGRP_RECEIVE_DESCRIPTOR_LIST_ADDRESS_OFST,
> +              (UINT32)(UINTN) EmacDriver->RxdescRingMap[0]);
> +
> +  // Initialize the descriptor number
> +  EmacDriver->RxCurrentDescriptorNum = 0;
> +  EmacDriver->RxNextDescriptorNum = 0;
> + 
> +  return EFI_SUCCESS;
> +}
> +
> +
> +VOID
> +EFIAPI
> +EmacStartTransmission (
> +  IN UINT32 MacBaseAddress
> +  )
> +{
> +  DEBUG ((EFI_D_INFO, "SNP:MAC: %a ()\r\n", __FUNCTION__));
> +  MmioOr32 (MacBaseAddress +
> +            DW_EMAC_GMACGRP_MAC_CONFIGURATION_OFST,
> +            DW_EMAC_GMACGRP_MAC_CONFIGURATION_RE_SET_MSK |
> +            DW_EMAC_GMACGRP_MAC_CONFIGURATION_TE_SET_MSK
> +            );
> +}
> +
> +
> +EFI_STATUS
> +EFIAPI
> +EmacRxFilters (
> +  IN        UINT32 ReceiveFilterSetting,
> +  IN        BOOLEAN Reset,
> +  IN        UINTN NumMfilter          OPTIONAL,
> +  IN        EFI_MAC_ADDRESS *Mfilter  OPTIONAL,
> +  IN        UINT32 MacBaseAddress
> +  )
> + {
> +  UINT32 MacFilter;
> +  UINT32 Crc;
> +  UINT32 Count;
> +  UINT32 HashReg;
> +  UINT32 HashBit;
> +  UINT32 Reg;
> +  UINT32 Val;
> +
> +  // If reset then clear the filter registers
> +  if (Reset) {
> +    for (Count = 0; Count < NumMfilter; Count++)
> +    {
> +      MmioWrite32 (MacBaseAddress + HASH_TABLE_REG(Count),
> 0x00000000);
> +    }
> +  }
> +
> +  // Set MacFilter to the reset value of
> the  DW_EMAC_GMACGRP_MAC_FRAME_FILTER register.
> +  MacFilter =  DW_EMAC_GMACGRP_MAC_FRAME_FILTER_RESET;
> +
> +  if (ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) {
> +    //DEBUG ((EFI_D_INFO, "SNP:MAC: Enable Unicast Frame
> Reception\n"));
> +  }
> +
> +  if (ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) {
> +
> +    //DEBUG ((EFI_D_INFO, "SNP:MAC: Enable Hash Multicast Frame
> Reception\n"));
> +    MacFilter |=  DW_EMAC_GMACGRP_MAC_FRAME_FILTER_HMC_SET_MSK;
> +
> +    // Set the hash tables
> +    if ((NumMfilter > 0) && (!Reset)) {
> +      // Go through each filter address and set appropriate bits on
> hash table
> +      for (Count = 0; Count < NumMfilter; Count++) {
> +        // Generate a 32-bit CRC
> +        Crc = GenEtherCrc32 (&Mfilter[Count], 6);
> +        // reserve CRC + take upper 8 bit = take lower 8 bit and
> reverse it
> +        Val = BitReverse(Crc & 0xff);
> +        // The most significant bits determines the register to be
> used (Hash Table Register X),
> +        // and the least significant five bits determine the bit
> within the register.
> +        // For example, a hash value of 8b'10111111 selects Bit 31
> of the Hash Table Register 5.
> +        HashReg = (Val >> 5);
> +        HashBit = (Val & 31);
> +
> +        Reg = MmioRead32(MacBaseAddress + HASH_TABLE_REG(HashReg));
> +        // set 1 to HashBit of HashReg
> +        // for example, set 1 to bit 31 to Reg 5 as in above example
> +        Reg |= (1 << HashBit);
> +        MmioWrite32(MacBaseAddress + HASH_TABLE_REG(HashReg), Reg);
> +      }
> +    }
> +  }
> +
> +  if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST)
> == 0) {
> +    MacFilter |=  DW_EMAC_GMACGRP_MAC_FRAME_FILTER_DBF_SET_MSK;
> +  } else if (ReceiveFilterSetting &
> EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) {
> +  }
> +
> +  if (ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS)
> {
> +    MacFilter |=  DW_EMAC_GMACGRP_MAC_FRAME_FILTER_PR_SET_MSK;
> +  }
> +
> +  if (ReceiveFilterSetting &
> EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) {
> +    MacFilter |= ( DW_EMAC_GMACGRP_MAC_FRAME_FILTER_PM_SET_MSK);
> +  }
> +
> +  // Set MacFilter to EMAC register
> +  MmioWrite32 (MacBaseAddress
> +  DW_EMAC_GMACGRP_MAC_FRAME_FILTER_OFST, MacFilter);
> +  return EFI_SUCCESS;
> +}
> +
> +
> +UINT32
> +EFIAPI
> +GenEtherCrc32 (
> +  IN    EFI_MAC_ADDRESS *Mac,
> +  IN    UINT32 AddrLen
> +  )
> +{
> +  INT32  Iter;
> +  UINT32 Remainder;
> +  UINT8  *Ptr;
> +
> +  Iter = 0;
> +  Remainder = 0xFFFFFFFF;    // 0xFFFFFFFF is standard seed for
> Ethernet
> +
> +  // Convert Mac Address to array of bytes
> +  Ptr = (UINT8*)Mac;
> +
> +  // Generate the Crc bit-by-bit (LSB first)
> +  while (AddrLen--) {
> +    Remainder ^= *Ptr++;
> +    for (Iter = 0;Iter < 8;Iter++) {
> +      // Check if exponent is set
> +      if (Remainder & 1) {
> +        Remainder = (Remainder >> 1) ^ CRC_POLYNOMIAL;
> +      } else {
> +        Remainder = (Remainder >> 1) ^ 0;
> +      }
> +    }
> +  }
> +
> +  return (~Remainder);
> +}
> +
> +
> +STATIC CONST UINT8 NibbleTab[] = {
> +    /* 0x0 0000 -> 0000 */  0x0,
> +    /* 0x1 0001 -> 1000 */  0x8,
> +    /* 0x2 0010 -> 0100 */  0x4,
> +    /* 0x3 0011 -> 1100 */  0xc,
> +    /* 0x4 0100 -> 0010 */  0x2,
> +    /* 0x5 0101 -> 1010 */  0xa,
> +    /* 0x6 0110 -> 0110 */  0x6,
> +    /* 0x7 0111 -> 1110 */  0xe,
> +    /* 0x8 1000 -> 0001 */  0x1,
> +    /* 0x9 1001 -> 1001 */  0x9,
> +    /* 0xa 1010 -> 0101 */  0x5,
> +    /* 0xb 1011 -> 1101 */  0xd,
> +    /* 0xc 1100 -> 0011 */  0x3,
> +    /* 0xd 1101 -> 1011 */  0xb,
> +    /* 0xe 1110 -> 0111 */  0x7,
> +    /* 0xf 1111 -> 1111 */  0xf
> +};
> +
> +UINT8
> +EFIAPI
> +BitReverse (
> +  UINT8 X
> +  )
> +{
> +  return (NibbleTab[X & 0xf] << 4) | NibbleTab[X >> 4];
> +}
> +
> +
> +VOID
> +EFIAPI
> +EmacStopTxRx (
> +   IN    UINT32 MacBaseAddress
> +  )
> +{
> +  DEBUG ((EFI_D_INFO, "SNP:MAC: %a ()\r\n", __FUNCTION__));
> +
> +  // Stop DMA TX
> +  MmioAnd32 (MacBaseAddress +
> +            DW_EMAC_DMAGRP_OPERATION_MODE_OFST,
> +            DW_EMAC_DMAGRP_OPERATION_MODE_ST_CLR_MSK);
> +
> +  // Flush TX
> +  MmioOr32 (MacBaseAddress +
> +            DW_EMAC_DMAGRP_OPERATION_MODE_OFST,
> +            DW_EMAC_DMAGRP_OPERATION_MODE_FTF_SET_MSK);
> +
> +  // Stop transmitters
> +  MmioAnd32 (MacBaseAddress +
> +            DW_EMAC_GMACGRP_MAC_CONFIGURATION_OFST,
> +            DW_EMAC_GMACGRP_MAC_CONFIGURATION_RE_CLR_MSK &
> +            DW_EMAC_GMACGRP_MAC_CONFIGURATION_TE_CLR_MSK);
> +
> +  // Stop DMA RX
> +  MmioAnd32 (MacBaseAddress +
> +            DW_EMAC_DMAGRP_OPERATION_MODE_OFST,
> +            DW_EMAC_DMAGRP_OPERATION_MODE_SR_CLR_MSK);
> +
> +}
> +
> +
> +EFI_STATUS
> +EFIAPI
> +EmacDmaStart (
> +  IN UINT32 MacBaseAddress
> +  )
> +{
> +  // Start the transmission
> +  MmioWrite32(MacBaseAddress +
> +              DW_EMAC_DMAGRP_TRANSMIT_POLL_DEMAND_OFST,
> +              0x1);
> +  return EFI_SUCCESS;
> +}
> +
> +
> +VOID
> +EFIAPI
> +EmacGetDmaStatus (
> +  OUT   UINT32 *IrqStat  OPTIONAL,
> +  IN    UINT32 MacBaseAddress
> +  )
> +{
> +  UINT32  DmaStatus;
> +  UINT32  ErrorBit;
> +  UINT32  Mask = 0;
> +
> +  DmaStatus = MmioRead32 (MacBaseAddress +
> +                           DW_EMAC_DMAGRP_STATUS_OFST);
> +  if (DmaStatus & DW_EMAC_DMAGRP_STATUS_NIS_SET_MSK) {
> +    Mask |= DW_EMAC_DMAGRP_STATUS_NIS_SET_MSK;
> +    // Rx interrupt
> +    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_RI_SET_MSK) {
> +      *IrqStat |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
> +      Mask |= DW_EMAC_DMAGRP_STATUS_RI_SET_MSK;
> +    } else {
> +      *IrqStat &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
> +    }
> +    // Tx interrupt
> +    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_TI_SET_MSK) {
> +      *IrqStat |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
> +      Mask |= DW_EMAC_DMAGRP_STATUS_TI_SET_MSK;
> +    } else {
> +      *IrqStat &= ~EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
> +    }
> +    // Tx Buffer
> +    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_TU_SET_MSK){
> +      Mask |= DW_EMAC_DMAGRP_STATUS_TU_SET_MSK;
> +      }
> +    // Early receive interrupt
> +    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_ERI_SET_MSK) {
> +      Mask |= DW_EMAC_DMAGRP_STATUS_ERI_SET_MSK;
> +    }
> +  }
> +  if (DmaStatus & DW_EMAC_DMAGRP_STATUS_AIS_SET_MSK) {
> +    Mask |= DW_EMAC_DMAGRP_STATUS_AIS_SET_MSK;
> +    // Transmit process stop
> +    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_TPS_SET_MSK) {
> +      DEBUG ((EFI_D_INFO, "SNP:MAC: Transmit process stop\n"));
> +      Mask |= DW_EMAC_DMAGRP_STATUS_TPS_SET_MSK;
> +    }
> +    // Transmit jabber timeout
> +    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_TJT_SET_MSK) {
> +      DEBUG ((EFI_D_INFO, "SNP:MAC: Transmit jabber timeout\n"));
> +      Mask |= DW_EMAC_DMAGRP_STATUS_TJT_SET_MSK;
> +    }
> +    // Receive FIFO overflow
> +    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_OVF_SET_MSK) {
> +      DEBUG ((EFI_D_INFO, "SNP:MAC: Receive FIFO overflow\n"));
> +      Mask |= DW_EMAC_DMAGRP_STATUS_OVF_SET_MSK;
> +    }
> +    // Transmit FIFO underflow
> +    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_UNF_SET_MSK) {
> +      DEBUG ((EFI_D_INFO, "SNP:MAC: Receive FIFO underflow\n"));
> +      Mask |= DW_EMAC_DMAGRP_STATUS_UNF_SET_MSK;
> +    }
> +    // Receive buffer unavailable
> +    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_RU_SET_MSK) {
> +      //DEBUG ((EFI_D_INFO, "SNP:MAC: Receive buffer
> unavailable\n"));
> +      Mask |= DW_EMAC_DMAGRP_STATUS_RU_SET_MSK;
> +    }
> +
> +    // Receive process stop
> +    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_RPS_SET_MSK) {
> +      DEBUG ((EFI_D_INFO, "SNP:MAC: Receive process stop\n"));
> +      Mask |= DW_EMAC_DMAGRP_STATUS_RPS_SET_MSK;
> +    }
> +    // Receive watchdog timeout
> +    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_RWT_SET_MSK) {
> +      DEBUG ((EFI_D_INFO, "SNP:MAC: Receive watchdog timeout\n"));
> +      Mask |= DW_EMAC_DMAGRP_STATUS_RWT_SET_MSK;
> +    }
> +    // Early transmit interrupt
> +    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_ETI_SET_MSK) {
> +      //DEBUG ((EFI_D_INFO, "SNP:MAC: Early transmit interrupt\n"));
> +      Mask |= DW_EMAC_DMAGRP_STATUS_ETI_SET_MSK;
> +    }
> +    // Fatal bus error
> +    if (DmaStatus & DW_EMAC_DMAGRP_STATUS_FBI_SET_MSK) {
> +      DEBUG ((EFI_D_INFO, "SNP:MAC: Fatal bus error:\n"));
> +      Mask |= DW_EMAC_DMAGRP_STATUS_FBI_SET_MSK;
> +
> +      ErrorBit = DW_EMAC_DMAGRP_STATUS_EB_GET (DmaStatus);
> +      switch (ErrorBit) {
> +        case RX_DMA_WRITE_DATA_TRANSFER_ERROR:
> +          DEBUG ((EFI_D_INFO, "SNP:MAC: Rx Dma write data transfer
> error\n"));
> +          break;
> +        case TX_DMA_READ_DATA_TRANSFER_ERROR:
> +          DEBUG ((EFI_D_INFO, "SNP:MAC: Tx Dma read data transfer
> error\n"));
> +          break;
> +        case RX_DMA_DESCRIPTOR_WRITE_ACCESS_ERROR:
> +          DEBUG ((EFI_D_INFO, "SNP:MAC: Rx Dma descriptor write
> access error\n"));
> +          break;
> +        case RX_DMA_DESCRIPTOR_READ_ACCESS_ERROR:
> +          DEBUG ((EFI_D_INFO, "SNP:MAC: Rx Dma descriptor read
> access error\n"));
> +          break;
> +        case TX_DMA_DESCRIPTOR_WRITE_ACCESS_ERROR:
> +          DEBUG ((EFI_D_INFO, "SNP:MAC: Tx Dma descriptor write
> access error\n"));
> +          break;
> +        case TX_DMA_DESCRIPTOR_READ_ACCESS_ERROR:
> +          DEBUG ((EFI_D_INFO, "SNP:MAC: Tx Dma descriptor read
> access error\n"));
> +          break;
> +        default:
> +          DEBUG ((EFI_D_INFO, "SNP:MAC: Undefined error\n"));
> +          break;
> +      }
> +    }
> +  }
> +  MmioOr32 (MacBaseAddress +
> +            DW_EMAC_DMAGRP_STATUS_OFST,
> +            Mask);
> +}
> +
> +
> +VOID
> +EFIAPI
> +EmacGetStatistic (
> +  OUT EFI_NETWORK_STATISTICS* Statistic,
> +  IN UINT32 MacBaseAddress
> +  )
> +{
> +  EFI_NETWORK_STATISTICS* Stats;
> +
> +  DEBUG ((EFI_D_INFO, "SNP:MAC: %a ()\r\n", __FUNCTION__));
> +
> +  // Allocate Resources
> +  Stats = AllocateZeroPool (sizeof (EFI_NETWORK_STATISTICS));
> +  if (Stats == NULL) {
> +    return;
> +  }
> +
> +  Stats->RxTotalFrames     = MmioRead32 (MacBaseAddress +
> DW_EMAC_GMACGRP_RXFRAMECOUNT_GB_OFST);
> +  Stats->RxUndersizeFrames = MmioRead32 (MacBaseAddress +
> DW_EMAC_GMACGRP_RXUNDERSIZE_G_OFST);
> +  Stats->RxOversizeFrames  = MmioRead32 (MacBaseAddress +
> DW_EMAC_GMACGRP_RXOVERSIZE_G_OFST);
> +  Stats->RxUnicastFrames   = MmioRead32 (MacBaseAddress +
> DW_EMAC_GMACGRP_RXUNICASTFRAMES_G_OFST);
> +  Stats->RxBroadcastFrames = MmioRead32 (MacBaseAddress +
> DW_EMAC_GMACGRP_RXBROADCASTFRAMES_G_OFST);
> +  Stats->RxMulticastFrames = MmioRead32 (MacBaseAddress +
> DW_EMAC_GMACGRP_RXMULTICASTFRAMES_G_OFST);
> +  Stats->RxCrcErrorFrames  = MmioRead32 (MacBaseAddress +
> DW_EMAC_GMACGRP_RXCRCERROR_OFST);
> +  Stats->RxTotalBytes      = MmioRead32 (MacBaseAddress +
> DW_EMAC_GMACGRP_RXOCTETCOUNT_GB_OFST);
> +  Stats->RxGoodFrames      = Stats->RxUnicastFrames + Stats-
> >RxBroadcastFrames + Stats->RxMulticastFrames;
> +
> +  Stats->TxTotalFrames     = MmioRead32 (MacBaseAddress +
> DW_EMAC_GMACGRP_TXFRAMECOUNT_GB_OFST);
> +  Stats->TxGoodFrames      = MmioRead32 (MacBaseAddress +
> DW_EMAC_GMACGRP_TXFRAMECOUNT_G_OFST);
> +  Stats->TxOversizeFrames  = MmioRead32 (MacBaseAddress +
> DW_EMAC_GMACGRP_TXOVERSIZE_G_OFST);
> +  Stats->TxUnicastFrames   = MmioRead32 (MacBaseAddress +
> DW_EMAC_GMACGRP_TXUNICASTFRAMES_GB_OFST);
> +  Stats->TxBroadcastFrames = MmioRead32 (MacBaseAddress +
> DW_EMAC_GMACGRP_TXBROADCASTFRAMES_G_OFST);
> +  Stats->TxMulticastFrames = MmioRead32 (MacBaseAddress +
> DW_EMAC_GMACGRP_TXMULTICASTFRAMES_G_OFST);
> +  Stats->TxTotalBytes      = MmioRead32 (MacBaseAddress +
> DW_EMAC_GMACGRP_TXOCTETCOUNT_GB_OFST);
> +  Stats->Collisions        = MmioRead32 (MacBaseAddress +
> DW_EMAC_GMACGRP_TXLATECOL_OFST) +
> +                             MmioRead32 (MacBaseAddress +
> DW_EMAC_GMACGRP_TXEXESSCOL_OFST);
> +
> +  // Fill in the statistics
> +  CopyMem(Statistic, Stats, sizeof(EFI_NETWORK_STATISTICS));
> +}
> +
> +
> +VOID
> +EFIAPI
> +EmacConfigAdjust (
> +  IN UINT32 Speed,
> +  IN UINT32 Duplex,
> +  IN UINT32 MacBaseAddress
> +  )
> +{
> +  UINT32 Config;
> +
> +  Config =0;
> +  if (Speed != SPEED_1000)
> +   Config |= DW_EMAC_GMACGRP_MAC_CONFIGURATION_PS_SET_MSK;
> +
> +  if (Speed == SPEED_100)
> +    Config |= DW_EMAC_GMACGRP_MAC_CONFIGURATION_FES_SET_MSK;
> +
> +  if (Duplex == DUPLEX_FULL)
> +    Config |= DW_EMAC_GMACGRP_MAC_CONFIGURATION_DM_SET_MSK;
> +
> +  MmioOr32 (MacBaseAddress +
> +            DW_EMAC_GMACGRP_MAC_CONFIGURATION_OFST,
> +            DW_EMAC_GMACGRP_MAC_CONFIGURATION_BE_SET_MSK |
> +            DW_EMAC_GMACGRP_MAC_CONFIGURATION_DO_SET_MSK |
> +            Config);
> +
> +}
> diff --git a/Silicon/DesignWare/Drivers/DwEmacSnpDxe/PhyDxeUtil.c
> b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/PhyDxeUtil.c
> new file mode 100755
> index 000000000000..65a53b651814
> --- /dev/null
> +++ b/Silicon/DesignWare/Drivers/DwEmacSnpDxe/PhyDxeUtil.c
> @@ -0,0 +1,621 @@
> +/** @file
> +
> +  Copyright (c) 2011 - 2019, Intel Corporaton. All rights reserved.
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of
> the BSD License
> +  which accompanies this distribution.  The full text of the license
> may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +  
> +  The original software modules are licensed as follows:
> +
> +  Copyright (c) 2012 - 2014, ARM Limited. All rights reserved.
> +  Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of
> the BSD License
> +  which accompanies this distribution.  The full text of the license
> may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD 3 Clause LICENSE ON AN
> "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS
> OR IMPLIED.
> +**/
> +
> +
> +#include "PhyDxeUtil.h"
> +#include "EmacDxeUtil.h"
> +
> +EFI_STATUS
> +EFIAPI
> +PhyDxeInitialization (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      MacBaseAddress
> +  )
> +{
> +  DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
> +
> +  // initialize the phyaddr
> +  PhyDriver->PhyAddr = 0;
> +  PhyDriver->PhyCurrentLink = LINK_DOWN;
> +  PhyDriver->PhyOldLink = LINK_DOWN;
> +
> +  if (PhyDetectDevice (PhyDriver, MacBaseAddress) != EFI_SUCCESS) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  PhyConfig (PhyDriver, MacBaseAddress);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +// PHY detect device
> +EFI_STATUS
> +EFIAPI
> +PhyDetectDevice (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      MacBaseAddress
> +  )
> +{
> +  UINT32 PhyAddr;
> +
> +  DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
> +
> +  for (PhyAddr = 0; PhyAddr < 32; PhyAddr++) {
> +    if (PhyReadId (PhyAddr, MacBaseAddress) == EFI_SUCCESS) {
> +      PhyDriver->PhyAddr = PhyAddr;
> +      return EFI_SUCCESS;
> +    }
> +  }
> +  Print (L"SNP:PHY: Fail to detect Ethernet PHY!\r\n");
> +  return EFI_NOT_FOUND;
> +}
> +
> +
> +EFI_STATUS
> +EFIAPI
> +PhyConfig (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      MacBaseAddress
> +  )
> +{
> +  EFI_STATUS Status;
> +
> +  DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
> +
> +  Status = PhySoftReset (PhyDriver, MacBaseAddress);
> +  if (EFI_ERROR (Status)) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  // Configure TX/RX Skew
> +  PhyConfigSkew (PhyDriver, MacBaseAddress);
> +
> +  // Read back and display Skew settings
> +  PhyDisplayConfigSkew (PhyDriver, MacBaseAddress);
> +
> +  // Configure AN FLP Burst Trasmit timing interval
> +  PhyConfigFlpBurstTiming (PhyDriver, MacBaseAddress);
> +  PhyDisplayFlpBurstTiming (PhyDriver, MacBaseAddress);
> +
> +  // Configure AN and Advertise
> +  PhyAutoNego (PhyDriver,MacBaseAddress);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +// Perform PHY software reset
> +EFI_STATUS
> +EFIAPI
> +PhySoftReset (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      MacBaseAddress
> +  )
> +{
> +  UINT32        TimeOut;
> +  UINT32        Data32;
> +  EFI_STATUS    Status;
> +
> +  DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
> +
> +  // PHY Basic Control Register reset
> +  PhyWrite (PhyDriver->PhyAddr, PHY_BASIC_CTRL, PHYCTRL_RESET,
> MacBaseAddress);
> +
> +  // Wait for completion
> +  TimeOut = 0;
> +  do {
> +    // Read PHY_BASIC_CTRL register from PHY
> +    Status = PhyRead (PhyDriver->PhyAddr, PHY_BASIC_CTRL, &Data32,
> MacBaseAddress);
> +    if (EFI_ERROR(Status)) {
> +      return Status;
> +    }
> +    // Wait until PHYCTRL_RESET become zero
> +    if ((Data32 & PHYCTRL_RESET) == 0) {
> +      break;
> +    }
> +    MicroSecondDelay(1);
> +  } while (TimeOut++ < PHY_TIMEOUT);
> +  if (TimeOut >= PHY_TIMEOUT) {
> +    DEBUG ((EFI_D_INFO, "SNP:PHY: ERROR! PhySoftReset timeout\n"));
> +    return EFI_TIMEOUT;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +// PHY read ID
> +EFI_STATUS
> +EFIAPI
> +PhyReadId (
> +  IN UINT32  PhyAddr,
> +  IN UINT32  MacBaseAddress
> +  )
> +{
> +  EFI_STATUS    Status;
> +  UINT32        PhyId1;
> +  UINT32        PhyId2;
> +
> +  //DEBUG ((EFI_D_INFO, "SNP:PHY: %a (0x%02X)\r\n", __FUNCTION__,
> PhyAddr));
> +
> +  Status = PhyRead (PhyAddr, PHY_ID1, &PhyId1, MacBaseAddress);
> +  if (EFI_ERROR(Status)) return Status;
> +  Status = PhyRead (PhyAddr, PHY_ID2, &PhyId2, MacBaseAddress);
> +  if (EFI_ERROR(Status)) return Status;
> +
> +  if (PhyId1 == PHY_INVALID_ID || PhyId2 == PHY_INVALID_ID) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  DEBUG ((EFI_D_INFO, "SNP:PHY: Ethernet PHY detected.
> PHY_ID1=0x%04X, PHY_ID2=0x%04X, PHY_ADDR=0x%02X\r\n", PhyId1, PhyId2,
> PhyAddr));
> +  return EFI_SUCCESS;
> +}
> +
> +
> +VOID
> +EFIAPI
> +PhyConfigSkew (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      MacBaseAddress
> +  )
> +{
> +  Phy9031ExtendedWrite(PhyDriver, PHY_KSZ9031_MOD_DATA_NO_POST_INC,
> PHY_KSZ9031RN_DEV_ADDR, PHY_KSZ9031RN_CONTROL_PAD_SKEW_REG,
> PHY_KSZ9031RN_CONTROL_PAD_SKEW_VALUE, MacBaseAddress);
> +  Phy9031ExtendedWrite(PhyDriver, PHY_KSZ9031_MOD_DATA_NO_POST_INC,
> PHY_KSZ9031RN_DEV_ADDR,
> PHY_KSZ9031RN_CLK_PAD_SKEW_REG,     PHY_KSZ9031RN_CLK_PAD_SKEW_VALUE,
> MacBaseAddress);
> +  Phy9031ExtendedWrite(PhyDriver, PHY_KSZ9031_MOD_DATA_NO_POST_INC,
> PHY_KSZ9031RN_DEV_ADDR, PHY_KSZ9031RN_RX_DATA_PAD_SKEW_REG,
> PHY_KSZ9031RN_RX_DATA_PAD_SKEW_VALUE, MacBaseAddress);
> +  Phy9031ExtendedWrite(PhyDriver, PHY_KSZ9031_MOD_DATA_NO_POST_INC,
> PHY_KSZ9031RN_DEV_ADDR, PHY_KSZ9031RN_TX_DATA_PAD_SKEW_REG,
> PHY_KSZ9031RN_TX_DATA_PAD_SKEW_VALUE, MacBaseAddress);
> +
> +}
> +
> +
> +VOID
> +EFIAPI
> +PhyDisplayConfigSkew (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      MacBaseAddress
> +  )
> +{
> +  // Display skew configuration
> +  DEBUG ((EFI_D_INFO, "SNP:PHY: Control Signal Pad Skew =
> 0x%04X\r\n", Phy9031ExtendedRead(PhyDriver,
> PHY_KSZ9031_MOD_DATA_NO_POST_INC, PHY_KSZ9031RN_DEV_ADDR,
> PHY_KSZ9031RN_CONTROL_PAD_SKEW_REG, MacBaseAddress)));
> +  DEBUG ((EFI_D_INFO, "SNP:PHY: RGMII Clock Pad Skew    =
> 0x%04X\r\n", Phy9031ExtendedRead(PhyDriver,
> PHY_KSZ9031_MOD_DATA_NO_POST_INC, PHY_KSZ9031RN_DEV_ADDR,
> PHY_KSZ9031RN_CLK_PAD_SKEW_REG, MacBaseAddress)));
> +  DEBUG ((EFI_D_INFO, "SNP:PHY: RGMII RX Data Pad Skew  =
> 0x%04X\r\n", Phy9031ExtendedRead(PhyDriver,
> PHY_KSZ9031_MOD_DATA_NO_POST_INC, PHY_KSZ9031RN_DEV_ADDR,
> PHY_KSZ9031RN_RX_DATA_PAD_SKEW_REG, MacBaseAddress)));
> +  DEBUG ((EFI_D_INFO, "SNP:PHY: RGMII TX Data Pad Skew  =
> 0x%04X\r\n", Phy9031ExtendedRead(PhyDriver,
> PHY_KSZ9031_MOD_DATA_NO_POST_INC, PHY_KSZ9031RN_DEV_ADDR,
> PHY_KSZ9031RN_TX_DATA_PAD_SKEW_REG, MacBaseAddress)));
> +}
> +
> +VOID
> +EFIAPI
> +PhyConfigFlpBurstTiming (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      MacBaseAddress
> +  )
> +{
> +  Phy9031ExtendedWrite(PhyDriver, PHY_KSZ9031_MOD_DATA_NO_POST_INC,
> PHY_KSZ9031RN_MMD_DEV_ADDR_00, PHY_KSZ9031RN_MMD_D0_FLP_LO_REG,
> PHY_KSZ9031RN_MMD_D0_FLP_16MS_LO, MacBaseAddress);
> +  Phy9031ExtendedWrite(PhyDriver, PHY_KSZ9031_MOD_DATA_NO_POST_INC,
> PHY_KSZ9031RN_MMD_DEV_ADDR_00, PHY_KSZ9031RN_MMD_D0_FLP_HI_REG,
> PHY_KSZ9031RN_MMD_D0_FLP_16MS_HI, MacBaseAddress);
> +}
> +
> +VOID
> +EFIAPI
> +PhyDisplayFlpBurstTiming (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      MacBaseAddress
> +  )
> +{
> +  // Display Auto-Negotiation FLP burst transmit timing
> +  DEBUG ((EFI_D_INFO, "SNP:PHY: AN FLP Burst Transmit - LO =
> 0x%04X\r\n", Phy9031ExtendedRead(PhyDriver,
> PHY_KSZ9031_MOD_DATA_NO_POST_INC, PHY_KSZ9031RN_MMD_DEV_ADDR_00,
> PHY_KSZ9031RN_MMD_D0_FLP_LO_REG, MacBaseAddress)));
> +  DEBUG ((EFI_D_INFO, "SNP:PHY: AN FLP Burst Transmit - HI =
> 0x%04X\r\n", Phy9031ExtendedRead(PhyDriver,
> PHY_KSZ9031_MOD_DATA_NO_POST_INC, PHY_KSZ9031RN_MMD_DEV_ADDR_00,
> PHY_KSZ9031RN_MMD_D0_FLP_HI_REG, MacBaseAddress)));
> +}
> +
> +// Do auto-negotiation
> +EFI_STATUS
> +EFIAPI
> +PhyAutoNego (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      MacBaseAddress
> +  )
> +{
> +  EFI_STATUS    Status;
> +  UINT32        PhyControl;
> +  UINT32        PhyStatus;
> +  UINT32        Features;
> +
> +  DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
> +
> +  // Read PHY Status
> +  Status = PhyRead (PhyDriver->PhyAddr, PHY_BASIC_STATUS,
> &PhyStatus, MacBaseAddress);
> +  if (EFI_ERROR(Status)) return Status;
> +
> +  // Check PHY Status if auto-negotiation is supported
> +  if ((PhyStatus & PHYSTS_AUTO_CAP) == 0) {
> +    DEBUG ((EFI_D_INFO, "SNP:PHY: Auto-negotiation is not
> supported.\n"));
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  // Read PHY Auto-Nego Advertise capabilities register for 10/100
> Base-T
> +  Status = PhyRead (PhyDriver->PhyAddr, PHY_AUTO_NEG_ADVERT,
> &Features, MacBaseAddress);
> +  if (EFI_ERROR(Status)) return Status;
> +
> +  // Set Advertise capabilities for 10Base-T/10Base-T full-
> duplex/100Base-T/100Base-T full-duplex
> +  Features |= (PHYANA_10BASET | PHYANA_10BASETFD | PHYANA_100BASETX
> | PHYANA_100BASETXFD);
> +  PhyWrite (PhyDriver->PhyAddr, PHY_AUTO_NEG_ADVERT, Features,
> MacBaseAddress);
> +
> +  // Read PHY Auto-Nego Advertise capabilities register for 1000
> Base-T
> +  Status = PhyRead (PhyDriver->PhyAddr, PHY_1000BASE_T_CONTROL,
> &Features, MacBaseAddress);
> +  if (EFI_ERROR(Status)) return Status;
> +
> +  // Set Advertise capabilities for 1000 Base-T/1000 Base-T full-
> duplex
> +  Features |= (PHYADVERTISE_1000FULL | PHYADVERTISE_1000HALF);
> +  PhyWrite (PhyDriver->PhyAddr, PHY_1000BASE_T_CONTROL, Features,
> MacBaseAddress);
> +
> +  // Read control register
> +  Status = PhyRead (PhyDriver->PhyAddr, PHY_BASIC_CTRL, &PhyControl,
> MacBaseAddress);
> +  if (EFI_ERROR(Status)) return Status;
> +
> +  // Enable Auto-Negotiation
> +  PhyControl |= PHYCTRL_AUTO_EN;
> +  // Restart auto-negotiation
> +  PhyControl |= PHYCTRL_RST_AUTO;
> +  // Write this configuration
> +  PhyWrite (PhyDriver->PhyAddr, PHY_BASIC_CTRL, PhyControl,
> MacBaseAddress); 
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +EFI_STATUS
> +EFIAPI
> +PhyLinkAdjustEmacConfig (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      MacBaseAddress
> +  )
> +{
> +  UINT32 Speed;
> +  UINT32 Duplex;
> +  EFI_STATUS Status;
> +
> +  //DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
> +
> +  Status = EFI_SUCCESS;
> +  Speed = SPEED_10;
> +  Duplex = DUPLEX_HALF;
> +
> +  if (PhyCheckLinkStatus (PhyDriver, MacBaseAddress) == EFI_SUCCESS)
> {
> +    PhyDriver->PhyCurrentLink = LINK_UP;
> +  } else {
> +    PhyDriver->PhyCurrentLink = LINK_DOWN;
> +  }
> +
> +  if (PhyDriver->PhyOldLink != PhyDriver->PhyCurrentLink) {
> +    if (PhyDriver->PhyCurrentLink == LINK_UP) {
> +      Print (L"SNP:PHY: Link is up - Network Cable is Plugged\r\n");
> +      PhyReadCapability (PhyDriver, &Speed, &Duplex,
> MacBaseAddress);
> +      EmacConfigAdjust (Speed, Duplex, MacBaseAddress);
> +      Status = EFI_SUCCESS;
> +    } else {
> +      Print (L"SNP:PHY: Link is Down - Network Cable is
> Unplugged?\r\n");
> +      Status = EFI_NOT_READY;
> +    }
> +  } else if (PhyDriver->PhyCurrentLink == LINK_DOWN) {
> +    Status = EFI_NOT_READY;
> +  }
> +
> +  PhyDriver->PhyOldLink = PhyDriver->PhyCurrentLink;
> +
> +  return Status;
> +}
> +
> +
> +EFI_STATUS
> +EFIAPI
> +PhyCheckLinkStatus (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      MacBaseAddress
> +  )
> +{
> +  EFI_STATUS    Status;
> +  UINT32        Data32;
> +  UINTN         TimeOut;
> +  UINT32        PhyBasicStatus;
> +
> +  //DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
> +
> +  // Get the PHY Status
> +  Status = PhyRead (PhyDriver->PhyAddr, PHY_BASIC_STATUS,
> &PhyBasicStatus, MacBaseAddress);
> +  if (EFI_ERROR(Status)) return Status;
> +
> +  // if Link is already up then dont need to proceed anymore
> +  if (PhyBasicStatus & PHYSTS_LINK_STS) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  // Wait until it is up or until Time Out
> +  TimeOut = 0;
> +  do {
> +    // Read PHY_BASIC_STATUS register from PHY
> +    Status = PhyRead (PhyDriver->PhyAddr, PHY_BASIC_STATUS, &Data32,
> MacBaseAddress);
> +    if (EFI_ERROR(Status)) {
> +      return Status;
> +    }
> +    // Wait until PHYSTS_LINK_STS become one
> +    if (Data32 & PHYSTS_LINK_STS) {
> +      // Link is up
> +      break;
> +    }
> +    MicroSecondDelay(1);
> +  } while (TimeOut++ < PHY_TIMEOUT);
> +  if (TimeOut >= PHY_TIMEOUT) {
> +    // Link is down
> +    return EFI_TIMEOUT;
> +  }
> +
> +  // Wait until autonego process has completed
> +  TimeOut = 0;
> +  do {
> +    // Read PHY_BASIC_STATUS register from PHY
> +    Status = PhyRead (PhyDriver->PhyAddr, PHY_BASIC_STATUS, &Data32,
> MacBaseAddress);
> +    if (EFI_ERROR(Status)) {
> +      return Status;
> +    }
> +    // Wait until PHYSTS_AUTO_COMP become one
> +    if (Data32 & PHYSTS_AUTO_COMP) {
> +      DEBUG ((EFI_D_INFO, "SNP:PHY: Auto Negotiation
> completed\r\n"));
> +      break;
> +    }
> +    MicroSecondDelay(1);
> +  } while (TimeOut++ < PHY_TIMEOUT);
> +  if (TimeOut >= PHY_TIMEOUT) {
> +    DEBUG ((EFI_D_INFO, "SNP:PHY: Error! Auto Negotiation
> timeout\n"));
> +    return EFI_TIMEOUT;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +EFI_STATUS
> +EFIAPI
> +PhyReadCapability (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32* Speed,
> +  IN UINT32* Duplex,
> +  IN UINT32  MacBaseAddress
> +  )
> +{
> +  EFI_STATUS    Status;
> +  UINT32        PartnerAbilityGb;
> +  UINT32        AdvertisingGb;
> +  UINT32        CommonAbilityGb;
> +  UINT32        PartnerAbility;
> +  UINT32        Advertising;
> +  UINT32        CommonAbility;
> +
> +  //DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
> +
> +  // For 1000 Base-T
> +
> +  Status = PhyRead (PhyDriver->PhyAddr, PHY_1000BASE_T_STATUS,
> &PartnerAbilityGb, MacBaseAddress);
> +  if (EFI_ERROR(Status)) return Status;
> +
> +  Status = PhyRead (PhyDriver->PhyAddr, PHY_1000BASE_T_CONTROL,
> &AdvertisingGb, MacBaseAddress);
> +  if (EFI_ERROR(Status)) return Status;
> +
> +  CommonAbilityGb = PartnerAbilityGb & (AdvertisingGb << 2);
> +
> +  // For 10/100 Base-T
> +
> +  Status = PhyRead (PhyDriver->PhyAddr, PHY_AUTO_NEG_LINK_ABILITY,
> &PartnerAbility, MacBaseAddress);
> +  if (EFI_ERROR(Status)) return Status;
> +
> +  Status = PhyRead (PhyDriver->PhyAddr, PHY_AUTO_NEG_EXP,
> &Advertising, MacBaseAddress);
> +  if (EFI_ERROR(Status)) return Status;
> +
> +  CommonAbility = PartnerAbility & Advertising;
> +
> +  // Determine the Speed and Duplex
> +  if (PartnerAbilityGb & (PHYLPA_1000FULL | PHYLPA_1000HALF)) {
> +    *Speed = SPEED_1000;
> +    if (CommonAbilityGb & PHYLPA_1000FULL) {
> +      *Duplex = DUPLEX_FULL;
> +    }
> +  } else if (CommonAbility & (PHYLPA_100FULL | PHYLPA_100HALF)) {
> +    *Speed = SPEED_100;
> +    if (CommonAbility & PHYLPA_100FULL) {
> +      *Duplex = DUPLEX_FULL;
> +    } else if (CommonAbility & PHYLPA_10FULL) {
> +      *Duplex = DUPLEX_FULL;
> +    }
> +  }
> +
> +  PhyDisplayAbility (*Speed, *Duplex);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +VOID
> +EFIAPI
> +PhyDisplayAbility (
> +  IN UINT32 Speed,
> +  IN UINT32 Duplex
> +  )
> +{
> +  //DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
> +
> +  Print (L"SNP:PHY: ");
> +  switch (Speed) {
> +    case SPEED_1000:
> +      Print (L"1 Gbps - ");
> +      break;
> +    case SPEED_100:
> +      Print (L"100 Mbps - ");
> +      break;
> +    case SPEED_10:
> +      Print (L"10 Mbps - ");
> +      break;
> +    default:
> +      Print (L"Invalid link speed");
> +      break;
> +    }
> +
> +  switch (Duplex) {
> +    case DUPLEX_FULL:
> +      Print (L"Full Duplex\n");
> +      break;
> +    case DUPLEX_HALF:
> +      Print (L"Half Duplex\n");
> +      break;
> +    default:
> +      Print (L"Invalid duplex mode\n");
> +      break;
> +    }
> +}
> +
> +
> +// Function to read from MII register (PHY Access)
> +EFI_STATUS
> +EFIAPI
> +PhyRead (
> +  IN  UINT32  Addr,
> +  IN  UINT32  Reg,
> +  OUT UINT32 *Data,
> +  IN  UINT32  MacBaseAddress
> +  )
> +{
> +  UINT32        MiiConfig;
> +  UINT32        Count;
> +
> +  //DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
> +
> +  // Check it is a valid Reg
> +  ASSERT(Reg < 31);
> +
> +  MiiConfig = ((Addr << MIIADDRSHIFT) & MII_ADDRMSK) |
> +              ((Reg << MIIREGSHIFT) & MII_REGMSK)|
> +               MII_CLKRANGE_150_250M |
> +               MII_BUSY;
> +
> +  // write this config to register
> +  MmioWrite32(MacBaseAddress + DW_EMAC_GMACGRP_GMII_ADDRESS_OFST,
> MiiConfig);
> +
> +  // Wait for busy bit to clear
> +  Count = 0;
> +  while (Count < 10000) {
> +    if
> (!(DW_EMAC_GMACGRP_GMII_ADDRESS_GB_GET(MmioRead32(MacBaseAddress +
> DW_EMAC_GMACGRP_GMII_ADDRESS_OFST))))
> +	{
> +      *Data =
> DW_EMAC_GMACGRP_GMII_DATA_GD_GET(MmioRead32(MacBaseAddress +
> DW_EMAC_GMACGRP_GMII_DATA_OFST));
> +      return EFI_SUCCESS;
> +	}
> +    Count++;
> +  };
> +  DEBUG ((EFI_D_INFO, "SNP:PHY: MDIO busy bit timeout\r\n"));
> +  return EFI_TIMEOUT;
> +}
> +
> +
> +// Function to write to the MII register (PHY Access)
> +EFI_STATUS
> +EFIAPI
> +PhyWrite (
> +  IN UINT32 Addr,
> +  IN UINT32 Reg,
> +  IN UINT32 Data,
> +  IN UINT32 MacBaseAddress
> +  )
> +{
> +  UINT32 MiiConfig;
> +  UINT32 Count;
> +
> +  //DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
> +
> +  // Check it is a valid Reg
> +  ASSERT(Reg < 31);
> +
> +  MiiConfig = ((Addr << MIIADDRSHIFT) & MII_ADDRMSK) |
> +              ((Reg << MIIREGSHIFT) & MII_REGMSK)|
> +               MII_WRITE |
> +               MII_CLKRANGE_150_250M |
> +               MII_BUSY;
> +  // Write the desired value to the register first
> +  MmioWrite32 (MacBaseAddress + DW_EMAC_GMACGRP_GMII_DATA_OFST,
> (Data & 0xFFFF));
> +
> +  // write this config to register
> +  MmioWrite32(MacBaseAddress + DW_EMAC_GMACGRP_GMII_ADDRESS_OFST,
> MiiConfig);
> +
> +  // Wait for busy bit to clear
> +  Count = 0;
> +  while (Count < 1000) {
> +      if
> (!(DW_EMAC_GMACGRP_GMII_ADDRESS_GB_GET(MmioRead32(MacBaseAddress +
> DW_EMAC_GMACGRP_GMII_ADDRESS_OFST))))
> +        return EFI_SUCCESS;
> +      Count++;
> +    };
> +
> +  return EFI_TIMEOUT;
> +}
> +
> +
> +EFI_STATUS
> +EFIAPI
> +Phy9031ExtendedWrite (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      Mode,
> +  IN UINT32      DevAddr,
> +  IN UINT32      Regnum,
> +  IN UINT16      Val,
> +  IN UINT32      MacBaseAddress
> +  )
> +{
> +  //DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
> +
> +  PhyWrite(PhyDriver->PhyAddr, PHY_KSZ9031RN_MMD_CTRL_REG, DevAddr,
> MacBaseAddress);
> +  PhyWrite(PhyDriver->PhyAddr, PHY_KSZ9031RN_MMD_REGDATA_REG,
> Regnum, MacBaseAddress);
> +  PhyWrite(PhyDriver->PhyAddr, PHY_KSZ9031RN_MMD_CTRL_REG, (Mode <<
> 14) | DevAddr, MacBaseAddress);
> +  return PhyWrite(PhyDriver->PhyAddr, PHY_KSZ9031RN_MMD_REGDATA_REG,
> Val, MacBaseAddress);
> +}
> +
> +
> +UINT32
> +EFIAPI
> +Phy9031ExtendedRead (
> +  IN PHY_DRIVER* PhyDriver,
> +  IN UINT32      Mode,
> +  IN UINT32      DevAddr,
> +  IN UINT32      Regnum,
> +  IN UINT32      MacBaseAddress
> +  )
> +{
> +  EFI_STATUS    Status;
> +  UINT32        Data32;
> +
> +  //DEBUG ((EFI_D_INFO, "SNP:PHY: %a ()\r\n", __FUNCTION__));
> +
> +  PhyWrite(PhyDriver->PhyAddr, PHY_KSZ9031RN_MMD_CTRL_REG, DevAddr,
> MacBaseAddress);
> +  PhyWrite(PhyDriver->PhyAddr, PHY_KSZ9031RN_MMD_REGDATA_REG,
> Regnum, MacBaseAddress);
> +  PhyWrite(PhyDriver->PhyAddr, PHY_KSZ9031RN_MMD_CTRL_REG, (Mode <<
> 14) | DevAddr, MacBaseAddress);
> +
> +  Status = PhyRead (PhyDriver->PhyAddr,
> PHY_KSZ9031RN_MMD_REGDATA_REG, &Data32, MacBaseAddress);
> +  if (EFI_ERROR(Status)) return 0;
> +
> +  return Data32;
> +}
> +
> +

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [edk2-devel] [PATCH v4 edk2-platforms 1/1] Silicon/DesignWare/Driver: DwEmacSnpDxe: Add DesignWare EMAC driver
  2019-05-22  2:37 ` tzy.way.ooi
@ 2019-05-22  7:21   ` Ard Biesheuvel
  2019-05-31  9:14     ` Ooi, Tzy Way
  0 siblings, 1 reply; 9+ messages in thread
From: Ard Biesheuvel @ 2019-05-22  7:21 UTC (permalink / raw)
  To: edk2-devel-groups-io, tzy.way.ooi
  Cc: Kinney, Michael D, Loh, Tien Hock, leif.lindholm@linaro.org

On Wed, 22 May 2019 at 03:37, Ooi, Tzy Way <tzy.way.ooi@intel.com> wrote:
>
> Hi Maintainers,
>
> Please could you help to review this patch? Thanks.
>

I already did, but my email response got rejected twice

https://edk2.groups.io/g/devel/message/40829?p=,,,20,0,0,0::Created,,emac,20,2,0,31541649

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [edk2-devel] [PATCH v4 edk2-platforms 1/1] Silicon/DesignWare/Driver: DwEmacSnpDxe: Add DesignWare EMAC driver
  2019-05-22  7:21   ` [edk2-devel] " Ard Biesheuvel
@ 2019-05-31  9:14     ` Ooi, Tzy Way
  2019-05-31  9:19       ` Ard Biesheuvel
  0 siblings, 1 reply; 9+ messages in thread
From: Ooi, Tzy Way @ 2019-05-31  9:14 UTC (permalink / raw)
  To: Ard Biesheuvel, edk2-devel-groups-io
  Cc: Kinney, Michael D, Loh, Tien Hock, leif.lindholm@linaro.org

Thanks Biesheuvel.

I would like to confirm with you on regards of one of the comment. There is one comment where you mentioned that:
"I am aware that TX is usually the hot path in UEFI, but we should still try to map a buffer directly rather than copy the contents into uncached memory"

I would like to confirm with you if do you mean I should do the DmaMap here instead of doing it at the beginning of the code while DmaAllocate is executed?
Or do you mean I shouldn’t copy it into a uncached memory region?

Thank you
-----Original Message-----
From: Ard Biesheuvel <ard.biesheuvel@linaro.org> 
Sent: Wednesday, May 22, 2019 3:22 PM
To: edk2-devel-groups-io <devel@edk2.groups.io>; Ooi, Tzy Way <tzy.way.ooi@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Loh, Tien Hock <tien.hock.loh@intel.com>; leif.lindholm@linaro.org
Subject: Re: [edk2-devel] [PATCH v4 edk2-platforms 1/1] Silicon/DesignWare/Driver: DwEmacSnpDxe: Add DesignWare EMAC driver

On Wed, 22 May 2019 at 03:37, Ooi, Tzy Way <tzy.way.ooi@intel.com> wrote:
>
> Hi Maintainers,
>
> Please could you help to review this patch? Thanks.
>

I already did, but my email response got rejected twice

https://edk2.groups.io/g/devel/message/40829?p=,,,20,0,0,0::Created,,emac,20,2,0,31541649

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [edk2-devel] [PATCH v4 edk2-platforms 1/1] Silicon/DesignWare/Driver: DwEmacSnpDxe: Add DesignWare EMAC driver
  2019-05-31  9:14     ` Ooi, Tzy Way
@ 2019-05-31  9:19       ` Ard Biesheuvel
  2019-06-19 10:09         ` Ooi, Tzy Way
  0 siblings, 1 reply; 9+ messages in thread
From: Ard Biesheuvel @ 2019-05-31  9:19 UTC (permalink / raw)
  To: Ooi, Tzy Way
  Cc: edk2-devel-groups-io, Kinney, Michael D, Loh, Tien Hock,
	leif.lindholm@linaro.org

On Fri, 31 May 2019 at 11:14, Ooi, Tzy Way <tzy.way.ooi@intel.com> wrote:
>
> Thanks Biesheuvel.
>
> I would like to confirm with you on regards of one of the comment. There is one comment where you mentioned that:
> "I am aware that TX is usually the hot path in UEFI, but we should still try to map a buffer directly rather than copy the contents into uncached memory"
>
> I would like to confirm with you if do you mean I should do the DmaMap here instead of doing it at the beginning of the code while DmaAllocate is executed?

Yes.

Each time you receive a buffer, you DmaMap() it with the
MapOperationBusMasterRead attribute, and hand it to the device. After
the device is finished, you DmaUnmap() it again. This removes the need
for uncached memory.

On the RX path, you can allocate the buffers via AllocatePages()
rather than via DmaAllocateBuffer(), and map the for DMA using
DmaMap() with the MapOperationBusMasterWrite attribute. Once the
buffer is filled by the hardware, you can DmaUnmap() it and copy the
contents back to the caller, after which you can recycle the buffer or
free it.

> Or do you mean I shouldn’t copy it into a uncached memory region?
>

DmaAllocateBuffer() gives you an uncached region, so you should only
use it for data structures that are accessed and modified by the CPU
and the hardware at the same time, e.g., the descriptor rings. The
actual data buffers only need directional DMA, so using uncached
memory results in an unnecessary performance hit.


> Thank you
> -----Original Message-----
> From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Sent: Wednesday, May 22, 2019 3:22 PM
> To: edk2-devel-groups-io <devel@edk2.groups.io>; Ooi, Tzy Way <tzy.way.ooi@intel.com>
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Loh, Tien Hock <tien.hock.loh@intel.com>; leif.lindholm@linaro.org
> Subject: Re: [edk2-devel] [PATCH v4 edk2-platforms 1/1] Silicon/DesignWare/Driver: DwEmacSnpDxe: Add DesignWare EMAC driver
>
> On Wed, 22 May 2019 at 03:37, Ooi, Tzy Way <tzy.way.ooi@intel.com> wrote:
> >
> > Hi Maintainers,
> >
> > Please could you help to review this patch? Thanks.
> >
>
> I already did, but my email response got rejected twice
>
> https://edk2.groups.io/g/devel/message/40829?p=,,,20,0,0,0::Created,,emac,20,2,0,31541649

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [edk2-devel] [PATCH v4 edk2-platforms 1/1] Silicon/DesignWare/Driver: DwEmacSnpDxe: Add DesignWare EMAC driver
  2019-05-31  9:19       ` Ard Biesheuvel
@ 2019-06-19 10:09         ` Ooi, Tzy Way
  2019-06-19 10:12           ` Ard Biesheuvel
  0 siblings, 1 reply; 9+ messages in thread
From: Ooi, Tzy Way @ 2019-06-19 10:09 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: edk2-devel-groups-io, Kinney, Michael D, Loh, Tien Hock,
	leif.lindholm@linaro.org

Hi Bieshuevel,

In the DmaMap function, there is one line where my code look like this:

"Status = DmaMap (MapOperationBusMasterCommonBuffer, Snp->MacDriver.TxdescRing[0], &BufferSize, &Snp->MacDriver.TxdescRingMap[0], &Snp->MappingTxdesc);"

You asked me why the [0] and how many descriptor I am mapping. In my code, there is total 10 descriptors. The way I did in current code was I use DmaAllocateBuffer to allocate a memory size which is big enough for 10 descriptors. After that, I just map the first descriptor and I access the rest of the descriptor by using the first descriptor address plus the size for each descriptor to get the next descriptor address. Wonder if this method is ok? Or do I need to use DmaAllocateBuffer and DmaMap for 10 times for total 10 descriptors? 

Thank you

Best regards,
Tzy Way

-----Original Message-----
From: Ard Biesheuvel <ard.biesheuvel@linaro.org> 
Sent: Friday, May 31, 2019 5:20 PM
To: Ooi, Tzy Way <tzy.way.ooi@intel.com>
Cc: edk2-devel-groups-io <devel@edk2.groups.io>; Kinney, Michael D <michael.d.kinney@intel.com>; Loh, Tien Hock <tien.hock.loh@intel.com>; leif.lindholm@linaro.org
Subject: Re: [edk2-devel] [PATCH v4 edk2-platforms 1/1] Silicon/DesignWare/Driver: DwEmacSnpDxe: Add DesignWare EMAC driver

On Fri, 31 May 2019 at 11:14, Ooi, Tzy Way <tzy.way.ooi@intel.com> wrote:
>
> Thanks Biesheuvel.
>
> I would like to confirm with you on regards of one of the comment. There is one comment where you mentioned that:
> "I am aware that TX is usually the hot path in UEFI, but we should still try to map a buffer directly rather than copy the contents into uncached memory"
>
> I would like to confirm with you if do you mean I should do the DmaMap here instead of doing it at the beginning of the code while DmaAllocate is executed?

Yes.

Each time you receive a buffer, you DmaMap() it with the MapOperationBusMasterRead attribute, and hand it to the device. After the device is finished, you DmaUnmap() it again. This removes the need for uncached memory.

On the RX path, you can allocate the buffers via AllocatePages() rather than via DmaAllocateBuffer(), and map the for DMA using
DmaMap() with the MapOperationBusMasterWrite attribute. Once the buffer is filled by the hardware, you can DmaUnmap() it and copy the contents back to the caller, after which you can recycle the buffer or free it.

> Or do you mean I shouldn’t copy it into a uncached memory region?
>

DmaAllocateBuffer() gives you an uncached region, so you should only use it for data structures that are accessed and modified by the CPU and the hardware at the same time, e.g., the descriptor rings. The actual data buffers only need directional DMA, so using uncached memory results in an unnecessary performance hit.


> Thank you
> -----Original Message-----
> From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Sent: Wednesday, May 22, 2019 3:22 PM
> To: edk2-devel-groups-io <devel@edk2.groups.io>; Ooi, Tzy Way 
> <tzy.way.ooi@intel.com>
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Loh, Tien Hock 
> <tien.hock.loh@intel.com>; leif.lindholm@linaro.org
> Subject: Re: [edk2-devel] [PATCH v4 edk2-platforms 1/1] 
> Silicon/DesignWare/Driver: DwEmacSnpDxe: Add DesignWare EMAC driver
>
> On Wed, 22 May 2019 at 03:37, Ooi, Tzy Way <tzy.way.ooi@intel.com> wrote:
> >
> > Hi Maintainers,
> >
> > Please could you help to review this patch? Thanks.
> >
>
> I already did, but my email response got rejected twice
>
> https://edk2.groups.io/g/devel/message/40829?p=,,,20,0,0,0::Created,,e
> mac,20,2,0,31541649

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [edk2-devel] [PATCH v4 edk2-platforms 1/1] Silicon/DesignWare/Driver: DwEmacSnpDxe: Add DesignWare EMAC driver
  2019-06-19 10:09         ` Ooi, Tzy Way
@ 2019-06-19 10:12           ` Ard Biesheuvel
  2019-06-26  9:35             ` Ooi, Tzy Way
  0 siblings, 1 reply; 9+ messages in thread
From: Ard Biesheuvel @ 2019-06-19 10:12 UTC (permalink / raw)
  To: Ooi, Tzy Way
  Cc: edk2-devel-groups-io, Kinney, Michael D, Loh, Tien Hock,
	leif.lindholm@linaro.org

On Wed, 19 Jun 2019 at 12:09, Ooi, Tzy Way <tzy.way.ooi@intel.com> wrote:
>
> Hi Bieshuevel,
>
> In the DmaMap function, there is one line where my code look like this:
>
> "Status = DmaMap (MapOperationBusMasterCommonBuffer, Snp->MacDriver.TxdescRing[0], &BufferSize, &Snp->MacDriver.TxdescRingMap[0], &Snp->MappingTxdesc);"
>
> You asked me why the [0] and how many descriptor I am mapping. In my code, there is total 10 descriptors. The way I did in current code was I use DmaAllocateBuffer to allocate a memory size which is big enough for 10 descriptors. After that, I just map the first descriptor and I access the rest of the descriptor by using the first descriptor address plus the size for each descriptor to get the next descriptor address. Wonder if this method is ok? Or do I need to use DmaAllocateBuffer and DmaMap for 10 times for total 10 descriptors?
>

No, this is not ok. You have to allocate and map the size of the
memory that you will use. As long as you don't use more than a page,
it will not matter in practice, but it is wrong nonetheless

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [edk2-devel] [PATCH v4 edk2-platforms 1/1] Silicon/DesignWare/Driver: DwEmacSnpDxe: Add DesignWare EMAC driver
  2019-06-19 10:12           ` Ard Biesheuvel
@ 2019-06-26  9:35             ` Ooi, Tzy Way
  2019-06-26 10:00               ` Ard Biesheuvel
  0 siblings, 1 reply; 9+ messages in thread
From: Ooi, Tzy Way @ 2019-06-26  9:35 UTC (permalink / raw)
  To: devel@edk2.groups.io, ard.biesheuvel@linaro.org
  Cc: Kinney, Michael D, Loh, Tien Hock, leif.lindholm@linaro.org

Hi Bieshuevel,

You mentioned that "Are these discrete components? If so, I wonder we should use some kind of abstraction for the PHY operation". In our system, the MAC is only connected to this PHY, hence wonder if is it ok to still maintain as it is for now?

Also, may I know if you could explain more on what is abstraction for the PHY?  

Thank you

Best regards,
Tzy Way

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Ard Biesheuvel
Sent: Wednesday, June 19, 2019 6:12 PM
To: Ooi, Tzy Way <tzy.way.ooi@intel.com>
Cc: edk2-devel-groups-io <devel@edk2.groups.io>; Kinney, Michael D <michael.d.kinney@intel.com>; Loh, Tien Hock <tien.hock.loh@intel.com>; leif.lindholm@linaro.org
Subject: Re: [edk2-devel] [PATCH v4 edk2-platforms 1/1] Silicon/DesignWare/Driver: DwEmacSnpDxe: Add DesignWare EMAC driver

On Wed, 19 Jun 2019 at 12:09, Ooi, Tzy Way <tzy.way.ooi@intel.com> wrote:
>
> Hi Bieshuevel,
>
> In the DmaMap function, there is one line where my code look like this:
>
> "Status = DmaMap (MapOperationBusMasterCommonBuffer, Snp->MacDriver.TxdescRing[0], &BufferSize, &Snp->MacDriver.TxdescRingMap[0], &Snp->MappingTxdesc);"
>
> You asked me why the [0] and how many descriptor I am mapping. In my code, there is total 10 descriptors. The way I did in current code was I use DmaAllocateBuffer to allocate a memory size which is big enough for 10 descriptors. After that, I just map the first descriptor and I access the rest of the descriptor by using the first descriptor address plus the size for each descriptor to get the next descriptor address. Wonder if this method is ok? Or do I need to use DmaAllocateBuffer and DmaMap for 10 times for total 10 descriptors?
>

No, this is not ok. You have to allocate and map the size of the memory that you will use. As long as you don't use more than a page, it will not matter in practice, but it is wrong nonetheless




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [edk2-devel] [PATCH v4 edk2-platforms 1/1] Silicon/DesignWare/Driver: DwEmacSnpDxe: Add DesignWare EMAC driver
  2019-06-26  9:35             ` Ooi, Tzy Way
@ 2019-06-26 10:00               ` Ard Biesheuvel
  0 siblings, 0 replies; 9+ messages in thread
From: Ard Biesheuvel @ 2019-06-26 10:00 UTC (permalink / raw)
  To: edk2-devel-groups-io, Ooi, Tzy Way
  Cc: Kinney, Michael D, Loh, Tien Hock, leif.lindholm@linaro.org

On Wed, 26 Jun 2019 at 11:35, Ooi, Tzy Way <tzy.way.ooi@intel.com> wrote:
>
> Hi Bieshuevel,
>
> You mentioned that "Are these discrete components? If so, I wonder we should use some kind of abstraction for the PHY operation". In our system, the MAC is only connected to this PHY, hence wonder if is it ok to still maintain as it is for now?
>

I think that is ok for now, since it is what all ethernet drivers do.

> Also, may I know if you could explain more on what is abstraction for the PHY?
>

MAC <-> PHY communication uses a standardized programming interface
over a standardized bus, so there is bound to be an opportunity for
sharing more code between drivers than we do today.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2019-06-26 10:00 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-05-08  9:52 [PATCH v4 edk2-platforms 1/1] Silicon/DesignWare/Driver: DwEmacSnpDxe: Add DesignWare EMAC driver tzy.way.ooi
2019-05-22  2:37 ` tzy.way.ooi
2019-05-22  7:21   ` [edk2-devel] " Ard Biesheuvel
2019-05-31  9:14     ` Ooi, Tzy Way
2019-05-31  9:19       ` Ard Biesheuvel
2019-06-19 10:09         ` Ooi, Tzy Way
2019-06-19 10:12           ` Ard Biesheuvel
2019-06-26  9:35             ` Ooi, Tzy Way
2019-06-26 10:00               ` Ard Biesheuvel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox