[edk2-devel] [PATCH v4 edk2-platforms 1/1] Silicon/DesignWare/Driver: DwEmacSnpDxe: Add DesignWare EMAC driver

Ooi, Tzy Way tzy.way.ooi at intel.com
Wed May 22 02:37:47 UTC 2019


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 at intel.com wrote:
> From: Ooi Tzy Way <tzy.way.ooi at 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 at linaro.org>
> Cc: Leif Lindholm<leif.lindholm at linaro.org>
> Cc: Michael D Kinney<michael.d.kinney at intel.com>
> Cc: Loh Tien Hock<tien.hock.loh at intel.com>
> 
> Contributed-under: Tianocore Contribution Agreement 1.1
> Signed-off-by: Ooi Tzy Way <tzy.way.ooi at 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;
> +}
> +
> +

-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#41186): https://edk2.groups.io/g/devel/message/41186
Mute This Topic: https://groups.io/mt/31541649/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-





More information about the edk2-devel-archive mailing list