[edk2-devel] [edk2-platform][PATCH v1 1/2] OptionRomPkg: UsbNetworking: ASIX Ax88179 driver

Ni, Ray ray.ni at intel.com
Fri May 8 00:53:05 UTC 2020


Yes. The drivers are put to vendor specific folders such as Asix, Realtek.

Inside each vendor directory, packages are created to hold the UEFI drivers.
I don't have preference between a single package to hold all drivers, multiple packages to hold individual
drivers.


> -----Original Message-----
> From: devel at edk2.groups.io <devel at edk2.groups.io> On Behalf Of Samer El-Haj-Mahmoud
> Sent: Friday, May 8, 2020 12:20 AM
> To: Ni, Ray <ray.ni at intel.com>; devel at edk2.groups.io
> Cc: Leif Lindholm <leif at nuviainc.com>; Ard Biesheuvel <Ard.Biesheuvel at arm.com>; Kinney, Michael D
> <michael.d.kinney at intel.com>; Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud at arm.com>
> Subject: Re: [edk2-devel] [edk2-platform][PATCH v1 1/2] OptionRomPkg: UsbNetworking: ASIX Ax88179 driver
> 
> Thanks Ray
> 
> So you are suggesting we put the ASIX drivers under something like this?
> 
> edk2-platforms/Drivers/Asix/
> 
> If this is the case, then I think we should move the existing ASIX drivers (Ax88772 and Ax88772b) form edk2-
> platforms/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking to the new folder. It does not make sense to keep the old and
> new versions of the drivers in separate locations.
> 
> Also, I plan on submitting the Realtek USB NIC driver. I assume, following this pattern, that we will want to put it under
> edk2-platforms/Drivers/Realtek/ , correct?
> 
> Thanks,
> --Samer
> 
> 
> > -----Original Message-----
> > From: Ni, Ray <ray.ni at intel.com>
> > Sent: Thursday, May 7, 2020 1:23 AM
> > To: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud at arm.com>;
> > devel at edk2.groups.io
> > Cc: Leif Lindholm <leif at nuviainc.com>; Ard Biesheuvel
> > <Ard.Biesheuvel at arm.com>; Kinney, Michael D
> > <michael.d.kinney at intel.com>
> > Subject: RE: [edk2-platform][PATCH v1 1/2] OptionRomPkg: UsbNetworking:
> > ASIX Ax88179 driver
> >
> > Samer,
> > Can you please create a vendor directory Asix and a standalone package
> > inside Asix to hold the Ax88179 driver?
> > OptionRomPkg is legacy package that shouldn't be used to hold all UEFI
> > drivers.
> >
> > Thanks,
> > Ray
> >
> > > -----Original Message-----
> > > From: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud at arm.com>
> > > Sent: Thursday, May 7, 2020 11:37 AM
> > > To: devel at edk2.groups.io
> > > Cc: Ni, Ray <ray.ni at intel.com>; Leif Lindholm <leif at nuviainc.com>; Ard
> > Biesheuvel <ard.biesheuvel at arm.com>
> > > Subject: [edk2-platform][PATCH v1 1/2] OptionRomPkg: UsbNetworking:
> > ASIX Ax88179 driver
> > >
> > > This is the initial revision of ASIX USB networking UEFI driver
> > > version 2.9.0 for Ax88179 and Ax88178a
> > >
> > https://www.asix.com.tw/products.php?op=pItemdetail&PItemID=131;71;1
> > 12
> > >
> > > Source code contributed by ASIX.
> > >
> > > Cc: Ray Ni <ray.ni at intel.com>
> > > Cc: Leif Lindholm <leif at nuviainc.com>
> > > Cc: Ard Biesheuvel <ard.biesheuvel at arm.com>
> > >
> > > Signed-off-by: Samer El-Haj-Mahmoud <samer.el-haj-
> > mahmoud at arm.com>
> > > ---
> > >  Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf
> > |   66 +
> > >  Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.h
> > | 1127 ++++++++++++++
> > >  Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.c       |
> > 1026 +++++++++++++
> > >
> > Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/ComponentNam
> > e.c |  290 ++++
> > >  Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/DriverBinding.c
> > |  620 ++++++++
> > >
> > Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/SimpleNetwork.c
> > | 1585 ++++++++++++++++++++
> > >  6 files changed, 4714 insertions(+)
> > >
> > > diff --git
> > a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf
> > > b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf
> > > new file mode 100644
> > > index 000000000000..a1883e9da1fd
> > > --- /dev/null
> > > +++
> > b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf
> > > @@ -0,0 +1,66 @@
> > > +## @file
> > > +# Component description file for ASIX AX88772 USB/Ethernet driver.
> > > +#
> > > +# This module provides support for the ASIX AX88772 USB/Ethernet
> > adapter.
> > > +# Copyright (c) 2011, Intel Corporation
> > > +#
> > > +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +#
> > > +##
> > > +
> > > +[Defines]
> > > +  INF_VERSION                    = 0x00010018
> > > +  BASE_NAME                      = Ax88179
> > > +  FILE_GUID                      = 27E5D3B6-7839-47C2-8618-5D2190729BC7
> > > +  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
> > > +  VERSION_STRING                 = 1.0
> > > +
> > > +  ENTRY_POINT                    = EntryPoint
> > > +
> > > +#
> > > +#  VALID_ARCHITECTURES           = IA32 X64 EBC
> > > +#
> > > +
> > > +[Sources.common]
> > > +  Ax88179.h
> > > +  Ax88179.c
> > > +  ComponentName.c
> > > +  DriverBinding.c
> > > +  SimpleNetwork.c
> > > +
> > > +
> > > +[Packages]
> > > +  MdePkg/MdePkg.dec
> > > +  MdeModulePkg/MdeModulePkg.dec
> > > +
> > > +[LibraryClasses]
> > > +  UefiLib
> > > +  UefiBootServicesTableLib
> > > +  BaseMemoryLib
> > > +  DebugLib
> > > +  UefiRuntimeLib
> > > +  UefiDriverEntryPoint
> > > +
> > > +[Protocols]
> > > +  gEfiDevicePathProtocolGuid           ## BY_START
> > > +  gEfiSimpleNetworkProtocolGuid        ## BY_START
> > > +  gEfiUsbIoProtocolGuid                ## TO_START
> > > +
> > > +#[Guids]
> > > +  #gEfiEventExitBootServicesGuid        ## PRODUCES ## Event
> > > +  #gEfiEventVirtualAddressChangeGuid    ## PRODUCES ## Event
> > > +  #gEfiNicIp4ConfigVariableGuid
> > > +
> > > +[Depex]
> > > +  gEfiBdsArchProtocolGuid AND
> > > +  gEfiCpuArchProtocolGuid AND
> > > +  gEfiMetronomeArchProtocolGuid AND
> > > +  gEfiMonotonicCounterArchProtocolGuid AND
> > > +  gEfiRealTimeClockArchProtocolGuid AND
> > > +  gEfiResetArchProtocolGuid AND
> > > +  gEfiRuntimeArchProtocolGuid AND
> > > +  gEfiSecurityArchProtocolGuid AND
> > > +  gEfiTimerArchProtocolGuid AND
> > > +  gEfiVariableWriteArchProtocolGuid AND
> > > +  gEfiVariableArchProtocolGuid AND
> > > +  gEfiWatchdogTimerArchProtocolGuid
> > > diff --git
> > a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.h
> > > b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.h
> > > new file mode 100644
> > > index 000000000000..82c9a3668d86
> > > --- /dev/null
> > > +++
> > b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.h
> > > @@ -0,0 +1,1127 @@
> > > +/** @file
> > > +  Definitions for ASIX AX88179 Ethernet adapter.
> > > +
> > > +  Copyright (c) 2011, Intel Corporation
> > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#ifndef _AX88179_H_
> > > +#define _AX88179_H_
> > > +
> > > +#include <Uefi.h>
> > > +
> > > +#include <Guid/EventGroup.h>
> > > +
> > > +#include <IndustryStandard/Pci.h>
> > > +
> > > +#include <Library/BaseMemoryLib.h>
> > > +#include <Library/DebugLib.h>
> > > +#include <Library/DevicePathLib.h>
> > > +#include <Library/UefiBootServicesTableLib.h>
> > > +#include <Library/UefiDriverEntryPoint.h>
> > > +#include <Library/UefiLib.h>
> > > +#include <Library/UefiRuntimeLib.h>
> > > +
> > > +#include <Protocol/DevicePath.h>
> > > +#include <Protocol/LoadedImage.h>
> > > +#include <Protocol/NetworkInterfaceIdentifier.h>
> > > +#include <Protocol/SimpleNetwork.h>
> > > +#include <Protocol/UsbIo.h>
> > > +
> > > +
> > > +#define PASS_SCT      0
> > > +#define FORCE_100Mbps 0
> > > +#define REPORTLINK    1
> > > +
> > > +
> > > +//------------------------------------------------------------------------------
> > > +//  Macros
> > > +//------------------------------------------------------------------------------
> > > +
> > > +//#if defined(_MSC_VER)           /* Handle Microsoft VC++ compiler
> > specifics. */
> > > +#define DBG_ENTER()             DEBUG (( 0xffffffff, "Entering "
> > __FUNCTION__ "\n" )) ///<  Display routine entry
> > > +#define DBG_EXIT()              DEBUG (( 0xffffffff, "Exiting " __FUNCTION__
> > "\n" ))  ///<  Display routine exit
> > > +#define DBG_EXIT_DEC(Status)    DEBUG (( 0xffffffff, "Exiting "
> > __FUNCTION__ ", Status: %d\n", Status ))      ///<  Display
> > > routine exit with decimal value
> > > +#define DBG_EXIT_HEX(Status)    DEBUG (( 0xffffffff, "Exiting "
> > __FUNCTION__ ", Status: 0x%08x\n", Status ))  ///<  Display
> > > routine exit with hex value
> > > +#define DBG_EXIT_STATUS(Status) DEBUG (( 0xffffffff, "Exiting "
> > __FUNCTION__ ", Status: %r\n", Status ))      ///<  Display
> > > routine exit with status value
> > > +#define DBG_EXIT_TF(Status)     DEBUG (( 0xffffffff, "Exiting "
> > __FUNCTION__ ", returning %s\n", (FALSE == Status) ?
> > > L"FALSE" : L"TRUE" ))  ///<  Display routine with TRUE/FALSE value
> > > +//#else   //  _MSC_VER
> > > +//#define DBG_ENTER()               ///<  Display routine entry
> > > +//#define DBG_EXIT()                ///<  Display routine exit
> > > +//#define DBG_EXIT_DEC(Status)      ///<  Display routine exit with decimal
> > value
> > > +//#define DBG_EXIT_HEX(Status)      ///<  Display routine exit with hex
> > value
> > > +//#define DBG_EXIT_STATUS(Status)   ///<  Display routine exit with status
> > value
> > > +//#define DBG_EXIT_TF(Status)       ///<  Display routine with TRUE/FALSE
> > value
> > > +//#endif  //  _MSC_VER
> > > +
> > > +#define USB_IS_IN_ENDPOINT(EndPointAddr)      (((EndPointAddr) & BIT7)
> > != 0)  ///<  Return TRUE/FALSE for IN direction
> > > +#define USB_IS_OUT_ENDPOINT(EndPointAddr)     (((EndPointAddr) &
> > BIT7) == 0)  ///<  Return TRUE/FALSE for OUT
> > > direction
> > > +#define USB_IS_BULK_ENDPOINT(Attribute)       (((Attribute) & (BIT0 |
> > BIT1)) == USB_ENDPOINT_BULK)      ///<  Return
> > > TRUE/FALSE for BULK type
> > > +#define USB_IS_INTERRUPT_ENDPOINT(Attribute)  (((Attribute) & (BIT0 |
> > BIT1)) == USB_ENDPOINT_INTERRUPT) ///<
> > > Return TRUE/FALSE for INTERRUPT type
> > > +
> > > +//------------------------------------------------------------------------------
> > > +//  Constants
> > > +//------------------------------------------------------------------------------
> > > +
> > > +#define DEBUG_RX_BROADCAST  0x40000000  ///<  Display RX broadcast
> > messages
> > > +#define DEBUG_RX_MULTICAST  0x20000000  ///<  Display RX multicast
> > messages
> > > +#define DEBUG_RX_UNICAST    0x10000000  ///<  Display RX unicast
> > messages
> > > +#define DEBUG_MAC_ADDRESS   0x08000000  ///<  Display the MAC
> > address
> > > +#define DEBUG_LINK          0x04000000  ///<  Display the link status
> > > +#define DEBUG_TX            0x02000000  ///<  Display the TX messages
> > > +#define DEBUG_PHY           0x01000000  ///<  Display the PHY register
> > values
> > > +#define DEBUG_SROM          0x00800000  ///<  Display the SROM contents
> > > +#define DEBUG_TIMER         0x00400000  ///<  Display the timer routine
> > entry/exit
> > > +#define DEBUG_TPL           0x00200000  ///<  Display the timer routine
> > entry/exit
> > > +
> > > +
> > > +#define ETHERNET_HEADER_SIZE  sizeof ( ETHERNET_HEADER )  ///<  Size
> > in bytes of the Ethernet header
> > > +#define MIN_ETHERNET_PKT_SIZE 60    ///<  Minimum packet size
> > including Ethernet header
> > > +#define MAX_ETHERNET_PKT_SIZE 1500
> > > +
> > > +#define USB_NETWORK_CLASS   0x09    ///<  USB Network class code
> > > +#define USB_BUS_TIMEOUT     1000    ///<  USB timeout in milliseconds
> > > +
> > > +//#define TIMER_MSEC          20            ///<  Polling interval for the NIC
> > > +//#define TPL_AX88179         TPL_CALLBACK    ///<  TPL for routine
> > synchronization
> > > +
> > > +
> > > +#define AX88179_BULKIN_SIZE_INK     2
> > > +#define AX88179_MAX_BULKIN_SIZE    1024 *
> > AX88179_BULKIN_SIZE_INK
> > > +#define AX88179_MAX_PKT_SIZE  2048
> > > +
> > > +#define HC_DEBUG  0
> > > +#define ADD_MACPATHNOD  1
> > > +#define BULKIN_TIMEOUT  3 //5000
> > > +#define TX_RETRY 0
> > > +#define AUTONEG_DELAY 1000000
> > > +/**
> > > +  Verify new TPL value
> > > +
> > > +  This macro which is enabled when debug is enabled verifies that
> > > +  the new TPL value is >= the current TPL value.
> > > +**/
> > > +#ifdef VERIFY_TPL
> > > +#undef VERIFY_TPL
> > > +#endif  //  VERIFY_TPL
> > > +
> > > +#if !defined(MDEPKG_NDEBUG)
> > > +
> > > +#define VERIFY_TPL(tpl)                           \
> > > +{                                                 \
> > > +  EFI_TPL PreviousTpl;                            \
> > > +                                                  \
> > > +  PreviousTpl = gBS->RaiseTPL ( TPL_HIGH_LEVEL ); \
> > > +  gBS->RestoreTPL ( PreviousTpl );                \
> > > +  if ( PreviousTpl > tpl ) {                      \
> > > +    DEBUG (( DEBUG_ERROR, "Current TPL: %d, New TPL: %d\r\n",
> > PreviousTpl, tpl ));  \
> > > +    ASSERT ( PreviousTpl <= tpl );                \
> > > +  }                                               \
> > > +}
> > > +
> > > +#else   //  MDEPKG_NDEBUG
> > > +
> > > +#define VERIFY_TPL(tpl)
> > > +
> > > +#endif  //  MDEPKG_NDEBUG
> > > +
> > > +//------------------------------------------------------------------------------
> > > +//  Hardware Definition
> > > +//------------------------------------------------------------------------------
> > > +
> > > +#define DEV_SIGNATURE     SIGNATURE_32 ('A','X','8','8')  ///<  Signature
> > of data structures in memory
> > > +
> > > +#define VENDOR_ID         0x0B95  ///<  Vendor ID for Asix
> > > +#define PRODUCT_ID        0x1790  ///<  Product ID for the AX88179 USB
> > 10/100 Ethernet controller
> > > +#define PRODUCT_ID_178A   0x178A
> > > +
> > > +#define RESET_MSEC        1000    ///<  Reset duration
> > > +#define PHY_RESET_MSEC     100    ///<  PHY reset duration
> > > +
> > > +//
> > > +//  RX Control register
> > > +//
> > > +
> > > +
> > > +
> > > +/*Freddy*/
> > > +#define RXC_RH1M          0x0100  ///<  Rx header 1
> > > +#define RXC_RH2M          0x0200  ///<  Rx header 2
> > > +#define RXC_RH3M          0x0400  ///<  Rx header 3
> > > +/*Freddy*/
> > > +
> > > +//
> > > +//  Medium Status register
> > > +//
> > > +
> > > +
> > > +
> > > +//
> > > +//  Software PHY Select register
> > > +//
> > > +
> > > +#define SPHY_PSEL         0x01    ///<  Select internal PHY
> > > +#define SPHY_ASEL         0x02    ///<  1=Auto select, 0=Manual select
> > > +
> > > +//
> > > +//  Software Reset register
> > > +//
> > > +
> > > +#define SRR_RR            0x01    ///<  Clear receive frame length error
> > > +#define SRR_RT            0x02    ///<  Clear transmit frame length error
> > > +#define SRR_PRTE          0x04    ///<  External PHY reset pin tri-state enable
> > > +#define SRR_PRL           0x08    ///<  External PHY reset pin level
> > > +#define SRR_BZ            0x10    ///<  Force Bulk to return zero length packet
> > > +#define SRR_IPRL          0x20    ///<  Internal PHY reset control
> > > +#define SRR_IPPD          0x40    ///<  Internal PHY power down
> > > +
> > > +//
> > > +//  PHY ID values
> > > +//
> > > +
> > > +#define PHY_ID_INTERNAL   0x0003  ///<  Internal PHY
> > > +
> > > +//
> > > +//  USB Commands
> > > +//
> > > +
> > > +#define CMD_PHY_ACCESS_SOFTWARE   0x06  ///<  Software in control
> > of PHY
> > > +#define CMD_PHY_REG_READ          0x07  ///<  Read PHY register, Value:
> > PHY, Index: Register, Data: Register value
> > > +#define CMD_PHY_REG_WRITE         0x08  ///<  Write PHY register, Value:
> > PHY, Index: Register, Data: New 16-bit value
> > > +#define CMD_PHY_ACCESS_HARDWARE   0x0a  ///<  Hardware in control
> > of PHY
> > > +#define CMD_SROM_READ             0x0b  ///<  Read SROM register: Value:
> > Address, Data: Value
> > > +#define CMD_RX_CONTROL_WRITE      0x10  ///<  Set the RX control
> > register, Value: New value
> > > +#define CMD_GAPS_WRITE            0x12  ///<  Write the gaps register,
> > Value: New value
> > > +#define CMD_MAC_ADDRESS_READ      0x11  ///<  Read the MAC address,
> > Data: 6 byte MAC address
> > > +#define CMD_MAC_ADDRESS_WRITE     0x14  ///<  Set the MAC address,
> > Data: New 6 byte MAC address
> > > +
> > > +#define CMD_MEDIUM_STATUS_READ    0x1a  ///<  Read medium status
> > register, Data: Register value
> > > +#define CMD_MEDIUM_STATUS_WRITE   0x1b  ///<  Write medium status
> > register, Value: New value
> > > +#define CMD_RESET                 0x20  ///<  Reset register, Value: New value
> > > +#define CMD_PHY_SELECT            0x22  ///<  PHY select register, Value:
> > New value
> > > +
> > > +/*Freddy*/
> > > +#define CMD_RXQTC                 0x2a  ///<  RX Queue Cascade Threshold
> > Control Register
> > > +/*Freddy*/
> > > +
> > > +//------------------------------
> > > +//  USB Endpoints
> > > +//------------------------------
> > > +
> > > +#define CONTROL_ENDPOINT                0       ///<  Control endpoint
> > > +#define INTERRUPT_ENDPOINT              1       ///<  Interrupt endpoint
> > > +#define BULK_IN_ENDPOINT                2       ///<  Receive endpoint
> > > +#define BULK_OUT_ENDPOINT               3       ///<  Transmit endpoint
> > > +
> > > +//------------------------------
> > > +//  PHY Registers
> > > +//------------------------------
> > > +
> > > +
> > > +
> > > +
> > > +
> > > +#define PHY_ANER                        6       ///<  Autonegotiation expansion
> > register
> > > +
> > > +
> > > +
> > > +//  BSMR - Register 1
> > > +
> > > +
> > > +
> > > +//  ANAR and ANLPAR Registers 4, 5
> > > +
> > > +#define RXHDR_DROP 0x8000
> > > +//#define RXHDR_MIIERR 0x4000
> > > +#define RXHDR_CRCERR 0x2000
> > > +
> > > +
> > > +//------------------------------------------------------------------------------
> > > +//  Data Types
> > > +//------------------------------------------------------------------------------
> > > +
> > > +/**
> > > +  Ethernet header layout
> > > +
> > > +  IEEE 802.3-2002 Part 3 specification, section 3.1.1.
> > > +**/
> > > +#pragma pack(1)
> > > +typedef struct {
> > > +  UINT8 dest_addr[PXE_HWADDR_LEN_ETHER];  ///<  Destination LAN
> > address
> > > +  UINT8 src_addr[PXE_HWADDR_LEN_ETHER];   ///<  Source LAN address
> > > +  UINT16 type;                            ///<  Protocol or length
> > > +} ETHERNET_HEADER;
> > > +#pragma pack()
> > > +
> > > +/**
> > > +  Receive and Transmit packet structure
> > > +**/
> > > +
> > > +
> > > +
> > > +
> > > +#pragma pack(1)
> > > +typedef struct _TX_PACKET {
> > > +//  struct _TX_PACKET * pNext;       ///<  Next receive packet
> > > +  UINT32  TxHdr1;
> > > +  UINT32  TxHdr2;
> > > +  UINT8 Data[ AX88179_MAX_PKT_SIZE ]; ///<  Received packet data
> > > +} TX_PACKET;
> > > +#pragma pack()
> > > +
> > > +#pragma pack(1)
> > > +typedef struct _RX_PACKET {
> > > +  struct _RX_PACKET * pNext;
> > > +  UINT16  Length;
> > > +  UINT16  EEEE;
> > > +  UINT8 Data[ AX88179_MAX_PKT_SIZE ];
> > > +} RX_PACKET;
> > > +#pragma pack()
> > > +
> > > +
> > > +
> > > +
> > > +/**
> > > +  AX88179 control structure
> > > +
> > > +  The driver uses this structure to manage the Asix AX88179 10/100
> > > +  Ethernet controller.
> > > +**/
> > > +typedef struct {
> > > +  UINTN Signature;          ///<  Structure identification
> > > +
> > > +  //
> > > +  //  USB data
> > > +  //
> > > +  EFI_HANDLE Controller;        ///<  Controller handle
> > > +  EFI_USB_IO_PROTOCOL * pUsbIo; ///<  USB driver interface
> > > +
> > > +  //
> > > +  //  Simple network protocol data
> > > +  //
> > > +  EFI_SIMPLE_NETWORK_PROTOCOL SimpleNetwork;  ///<  Driver's
> > network stack interface
> > > +  EFI_SIMPLE_NETWORK_MODE SimpleNetworkData;  ///<  Data for
> > simple network
> > > +
> > > +  //
> > > +  // Ethernet controller data
> > > +  //
> > > +  BOOLEAN bInitialized;     ///<  Controller initialized
> > > +  UINT16 PhyId;             ///<  PHY ID
> > > +
> > > +  //
> > > +  //  Link state
> > > +  //
> > > +  BOOLEAN b100Mbps;         ///<  Current link speed, FALSE = 10 Mbps
> > > +  BOOLEAN b1000Mbps;        ///<  Current link speed, FALSE = 100/10 bps
> > > +  BOOLEAN bComplete;        ///<  Current state of auto-negotiation
> > > +  BOOLEAN bFullDuplex;      ///<  Current duplex
> > > +  BOOLEAN bLinkUp;          ///<  Current link state
> > > +  BOOLEAN bLinkIdle;        ///<  TRUE = No received traffic
> > > +  EFI_EVENT Timer;          ///<  Timer to monitor link state and receive
> > packets
> > > +  UINTN PollCount;          ///<  Number of times the autonegotiation status
> > was polled
> > > +  UINTN SkipRXCnt;
> > > +
> > > +  UINT8     *pBulkInbuf;
> > > +  UINT16    PktCnt;
> > > +  UINT8    * pCurPktHdrOff;
> > > +  UINT8     *pCurPktOff;
> > > +
> > > +  TX_PACKET * pTxTest;
> > > +
> > > +  INT8 MulticastHash[8];
> > > +  EFI_MAC_ADDRESS MAC;
> > > +
> > > +  UINT16 CurMediumStatus;
> > > +  UINT16 CurRxControl;
> > > +  VOID * pTxBuffer;
> > > +
> > > +  EFI_DEVICE_PATH_PROTOCOL                  *MyDevPath;
> > > +  BOOLEAN   Grub_f;
> > > +  BOOLEAN   bFirstRst;
> > > +  BOOLEAN   bSetZeroLen;
> > > +  UINT8 rxburst;
> > > +  UINTN usbMaxPktSize;
> > > +
> > > +} NIC_DEVICE;
> > > +
> > > +#define DEV_FROM_SIMPLE_NETWORK(a)  CR (a, NIC_DEVICE,
> > SimpleNetwork, DEV_SIGNATURE)  ///< Locate NIC_DEVICE
> > > from Simple Network Protocol
> > > +
> > > +//------------------------------------------------------------------------------
> > > +// Simple Network Protocol
> > > +//------------------------------------------------------------------------------
> > > +
> > > +/**
> > > +  Reset the network adapter.
> > > +
> > > +  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 cleared.  Receive filters, the station address, the
> > > +  statistics, and the multicast-IP-to-HW MAC addresses are not reset by
> > > +  this call.
> > > +
> > > +  This routine calls ::Ax88179Reset to perform the adapter specific
> > > +  reset operation.  This routine also starts the link negotiation
> > > +  by calling ::Ax88179NegotiateLinkStart.
> > > +
> > > +  @param [in] pSimpleNetwork    Protocol instance pointer
> > > +  @param [in] bExtendedVerification  Indicates that the driver may
> > perform a more
> > > +                                exhaustive verification operation of the device
> > > +                                during reset.
> > > +
> > > +  @retval EFI_SUCCESS           This operation was successful.
> > > +  @retval EFI_NOT_STARTED       The network interface was not started.
> > > +  @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was
> > NULL or did not point to a valid
> > > +                                EFI_SIMPLE_NETWORK_PROTOCOL structure.
> > > +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> > network interface.
> > > +  @retval EFI_UNSUPPORTED       The increased buffer size feature is not
> > supported.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +SN_Reset (
> > > +  IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
> > > +  IN BOOLEAN bExtendedVerification
> > > +  );
> > > +
> > > +/**
> > > +  Initialize the simple network protocol.
> > > +
> > > +  This routine calls ::Ax88179MacAddressGet to obtain the
> > > +  MAC address.
> > > +
> > > +  @param [in] pNicDevice       NIC_DEVICE_INSTANCE pointer
> > > +
> > > +  @retval EFI_SUCCESS     Setup was successful
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +SN_Setup (
> > > +  IN NIC_DEVICE * pNicDevice
> > > +  );
> > > +
> > > +/**
> > > +  This routine starts the network interface.
> > > +
> > > +  @param [in] pSimpleNetwork    Protocol instance pointer
> > > +
> > > +  @retval EFI_SUCCESS           This operation was successful.
> > > +  @retval EFI_ALREADY_STARTED   The network interface was already
> > started.
> > > +  @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was
> > NULL or did not point to a valid
> > > +                                EFI_SIMPLE_NETWORK_PROTOCOL structure.
> > > +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> > network interface.
> > > +  @retval EFI_UNSUPPORTED       The increased buffer size feature is not
> > supported.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +SN_Start (
> > > +  IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork
> > > +  );
> > > +
> > > +/**
> > > +  Set the MAC address.
> > > +
> > > +  This function modifies or resets the current station address of a
> > > +  network interface.  If Reset is TRUE, then the current station address
> > > +  is set ot the network interface's permanent address.  If Reset if FALSE
> > > +  then the current station address is changed to the address specified by
> > > +  pNew.
> > > +
> > > +  This routine calls ::Ax88179MacAddressSet to update the MAC address
> > > +  in the network adapter.
> > > +
> > > +  @param [in] pSimpleNetwork    Protocol instance pointer
> > > +  @param [in] bReset            Flag used to reset the station address to the
> > > +                                network interface's permanent address.
> > > +  @param [in] pNew              New station address to be used for the
> > network
> > > +                                interface.
> > > +
> > > +  @retval EFI_SUCCESS           This operation was successful.
> > > +  @retval EFI_NOT_STARTED       The network interface was not started.
> > > +  @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was
> > NULL or did not point to a valid
> > > +                                EFI_SIMPLE_NETWORK_PROTOCOL structure.
> > > +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> > network interface.
> > > +  @retval EFI_UNSUPPORTED       The increased buffer size feature is not
> > supported.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +SN_StationAddress (
> > > +  IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
> > > +  IN BOOLEAN bReset,
> > > +  IN EFI_MAC_ADDRESS * pNew
> > > +  );
> > > +
> > > +/**
> > > +  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 of the statistics that are collected by the network
> > > +  interface, then a partial buffer of statistics is returned in
> > > +  StatisticsTable.
> > > +
> > > +  @param [in] pSimpleNetwork    Protocol instance pointer
> > > +  @param [in] bReset            Set to TRUE to reset the statistics for the
> > network interface.
> > > +  @param [in, out] pStatisticsSize  On input the size, in bytes, of
> > StatisticsTable.  On output
> > > +                                the size, in bytes, of the resulting table of statistics.
> > > +  @param [out] pStatisticsTable A pointer to the
> > EFI_NETWORK_STATISTICS structure that
> > > +                                conains the statistics.
> > > +
> > > +  @retval EFI_SUCCESS           This operation was successful.
> > > +  @retval EFI_NOT_STARTED       The network interface was not started.
> > > +  @retval EFI_BUFFER_TOO_SMALL  The pStatisticsTable is NULL or the
> > buffer is too small.
> > > +  @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was
> > NULL or did not point to a valid
> > > +                                EFI_SIMPLE_NETWORK_PROTOCOL structure.
> > > +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> > network interface.
> > > +  @retval EFI_UNSUPPORTED       The increased buffer size feature is not
> > supported.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +SN_Statistics (
> > > +  IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
> > > +  IN BOOLEAN bReset,
> > > +  IN OUT UINTN * pStatisticsSize,
> > > +  OUT EFI_NETWORK_STATISTICS * pStatisticsTable
> > > +  );
> > > +
> > > +/**
> > > +  This function stops a network interface.  This call is only valid
> > > +  if the network interface is in the started state.
> > > +
> > > +  @param [in] pSimpleNetwork    Protocol instance pointer
> > > +
> > > +  @retval EFI_SUCCESS           This operation was successful.
> > > +  @retval EFI_NOT_STARTED       The network interface was not started.
> > > +  @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was
> > NULL or did not point to a valid
> > > +                                EFI_SIMPLE_NETWORK_PROTOCOL structure.
> > > +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> > network interface.
> > > +  @retval EFI_UNSUPPORTED       The increased buffer size feature is not
> > supported.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +SN_Stop (
> > > +  IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork
> > > +  );
> > > +
> > > +/**
> > > +  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 Initialize() and Stop() calls may be used.
> > > +
> > > +  @param [in] pSimpleNetwork    Protocol instance pointer
> > > +
> > > +  @retval EFI_SUCCESS           This operation was successful.
> > > +  @retval EFI_NOT_STARTED       The network interface was not started.
> > > +  @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was
> > NULL or did not point to a valid
> > > +                                EFI_SIMPLE_NETWORK_PROTOCOL structure.
> > > +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> > network interface.
> > > +  @retval EFI_UNSUPPORTED       The increased buffer size feature is not
> > supported.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +SN_Shutdown (
> > > +  IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork
> > > +  );
> > > +
> > > +/**
> > > +  Send a packet over the network.
> > > +
> > > +  This function places the packet specified by Header and Buffer on
> > > +  the transmit queue.  This function performs a non-blocking transmit
> > > +  operation.  When the transmit is complete, the buffer is returned
> > > +  via the GetStatus() call.
> > > +
> > > +  This routine calls ::Ax88179Rx to empty the network adapter of
> > > +  receive packets.  The routine then passes the transmit packet
> > > +  to the network adapter.
> > > +
> > > +  @param [in] pSimpleNetwork    Protocol instance pointer
> > > +  @param [in] HeaderSize        The size, in bytes, of the media header to be
> > filled in by
> > > +                                the Transmit() function.  If HeaderSize is non-zero, then
> > > +                                it must be equal to SimpleNetwork->Mode-
> > >MediaHeaderSize
> > > +                                and DestAddr and Protocol parameters must not be
> > NULL.
> > > +  @param [in] BufferSize        The size, in bytes, of the entire packet (media
> > header and
> > > +                                data) to be transmitted through the network interface.
> > > +  @param [in] pBuffer           A pointer to the packet (media header
> > followed by data) to
> > > +                                to be transmitted.  This parameter can not be NULL.  If
> > > +                                HeaderSize is zero, then the media header is 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 [in] pSrcAddr          The source HW MAC address.  If HeaderSize
> > is zero, then
> > > +                                this parameter is ignored.  If HeaderSize is nonzero and
> > > +                                SrcAddr is NULL, then SimpleNetwork->Mode-
> > >CurrentAddress
> > > +                                is used for the source HW MAC address.
> > > +  @param [in] pDestAddr         The destination HW MAC address.  If
> > HeaderSize is zero, then
> > > +                                this parameter is ignored.
> > > +  @param [in] pProtocol         The type of header to build.  If HeaderSize is
> > zero, then
> > > +                                this parameter is ignored.
> > > +
> > > +  @retval EFI_SUCCESS           This operation was successful.
> > > +  @retval EFI_NOT_STARTED       The network interface was not 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 pSimpleNetwork 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
> > > +SN_Transmit (
> > > +  IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
> > > +  IN UINTN HeaderSize,
> > > +  IN UINTN BufferSize,
> > > +  IN VOID * pBuffer,
> > > +  IN EFI_MAC_ADDRESS * pSrcAddr,
> > > +  IN EFI_MAC_ADDRESS * pDestAddr,
> > > +  IN UINT16 * pProtocol
> > > +  );
> > > +
> > > +//------------------------------------------------------------------------------
> > > +// Support Routines
> > > +//------------------------------------------------------------------------------
> > > +
> > > +/**
> > > +  Get the MAC address
> > > +
> > > +  This routine calls ::Ax88179UsbCommand to request the MAC
> > > +  address from the network adapter.
> > > +
> > > +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> > > +  @param [out] pMacAddress      Address of a six byte buffer to receive the
> > MAC address.
> > > +
> > > +  @retval EFI_SUCCESS          The MAC address is available.
> > > +  @retval other                The MAC address is not valid.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +Ax88179MacAddressGet (
> > > +  IN NIC_DEVICE * pNicDevice,
> > > +  OUT UINT8 * pMacAddress
> > > +  );
> > > +
> > > +
> > > +/**
> > > +  Clear the multicast hash table
> > > +
> > > +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> > > +
> > > +**/
> > > +VOID
> > > +Ax88179MulticastClear (
> > > +  IN NIC_DEVICE * pNicDevice
> > > +  );
> > > +
> > > +/**
> > > +  Enable a multicast address in the multicast hash table
> > > +
> > > +  This routine calls ::Ax88179Crc to compute the hash bit for
> > > +  this MAC address.
> > > +
> > > +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> > > +  @param [in] pMacAddress      Address of a six byte buffer to containing
> > the MAC address.
> > > +
> > > +**/
> > > +VOID
> > > +Ax88179MulticastSet (
> > > +  IN NIC_DEVICE * pNicDevice,
> > > +  IN UINT8 * pMacAddress
> > > +  );
> > > +
> > > +/**
> > > +  Start the link negotiation
> > > +
> > > +  This routine calls ::Ax88179PhyWrite to start the PHY's link
> > > +  negotiation.
> > > +
> > > +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> > > +
> > > +  @retval EFI_SUCCESS          The link negotiation was started.
> > > +  @retval other                Failed to start the link negotiation.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +Ax88179NegotiateLinkStart (
> > > +  IN NIC_DEVICE * pNicDevice
> > > +  );
> > > +
> > > +/**
> > > +  Complete the negotiation of the PHY link
> > > +
> > > +  This routine calls ::Ax88179PhyRead to determine if the
> > > +  link negotiation is complete.
> > > +
> > > +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> > > +  @param [in, out] pPollCount  Address of number of times this routine
> > was polled
> > > +  @param [out] pbComplete      Address of boolean to receive complate
> > status.
> > > +  @param [out] pbLinkUp        Address of boolean to receive link status,
> > TRUE=up.
> > > +  @param [out] pbHiSpeed       Address of boolean to receive link speed,
> > TRUE=100Mbps.
> > > +  @param [out] pbFullDuplex    Address of boolean to receive link duplex,
> > TRUE=full.
> > > +
> > > +  @retval EFI_SUCCESS          The MAC address is available.
> > > +  @retval other                The MAC address is not valid.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +Ax88179NegotiateLinkComplete (
> > > +  IN NIC_DEVICE * pNicDevice,
> > > +  IN OUT UINTN * pPollCount,
> > > +  OUT BOOLEAN * pbComplete,
> > > +  OUT BOOLEAN * pbLinkUp,
> > > +  OUT BOOLEAN * pbHiSpeed,
> > > +  OUT BOOLEAN * pbGigaSpeed,
> > > +  OUT BOOLEAN * pbFullDuplex
> > > +  );
> > > +
> > > +/**
> > > +  Read a register from the PHY
> > > +
> > > +  This routine calls ::Ax88179UsbCommand to read a PHY register.
> > > +
> > > +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> > > +  @param [in] RegisterAddress  Number of the register to read.
> > > +  @param [in, out] pPhyData    Address of a buffer to receive the PHY
> > register value
> > > +
> > > +  @retval EFI_SUCCESS          The PHY data is available.
> > > +  @retval other                The PHY data is not valid.
> > > +
> > > +**/
> > > +
> > > +
> > > +/**
> > > +  Reset the AX88179
> > > +
> > > +  This routine uses ::Ax88179UsbCommand to reset the network
> > > +  adapter.  This routine also uses ::Ax88179PhyWrite to reset
> > > +  the PHY.
> > > +
> > > +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> > > +
> > > +  @retval EFI_SUCCESS          The MAC address is available.
> > > +  @retval other                The MAC address is not valid.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +Ax88179Reset (
> > > +  IN NIC_DEVICE * pNicDevice
> > > +  );
> > > +#if 0
> > > +/**
> > > +  Receive a frame from the network.
> > > +
> > > +  This routine polls the USB receive interface for a packet.  If a packet
> > > +  is available, this routine adds the receive packet to the list of
> > > +  pending receive packets.
> > > +
> > > +  This routine calls ::Ax88179NegotiateLinkComplete to verify
> > > +  that the link is up.  This routine also calls ::SN_Reset to
> > > +  reset the network adapter when necessary.  Finally this
> > > +  routine attempts to receive one or more packets from the
> > > +  network adapter.
> > > +
> > > +  @param [in] pNicDevice  Pointer to the NIC_DEVICE structure
> > > +  @param [in] bUpdateLink TRUE = Update link status
> > > +
> > > +**/
> > > +VOID
> > > +Ax88179Rx (
> > > +  IN NIC_DEVICE * pNicDevice,
> > > +  IN BOOLEAN bUpdateLink
> > > +  );
> > > +#endif
> > > +/**
> > > +  Enable or disable the receiver
> > > +
> > > +  This routine calls ::Ax88179UsbCommand to update the
> > > +  receiver state.  This routine also calls ::Ax88179MacAddressSet
> > > +  to establish the MAC address for the network adapter.
> > > +
> > > +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> > > +  @param [in] RxFilter         Simple network RX filter mask value
> > > +
> > > +  @retval EFI_SUCCESS          The MAC address was set.
> > > +  @retval other                The MAC address was not set.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +Ax88179RxControl (
> > > +  IN NIC_DEVICE * pNicDevice,
> > > +  IN UINT32 RxFilter
> > > +  );
> > > +
> > > +  EFI_STATUS
> > > +Ax88179ReloadSrom  (
> > > +  IN NIC_DEVICE * pNicDevice
> > > +  );
> > > +
> > > +/**
> > > +  Read an SROM location
> > > +
> > > +  This routine calls ::Ax88179UsbCommand to read data from the
> > > +  SROM.
> > > +
> > > +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> > > +  @param [in] Address          SROM address
> > > +  @param [out] pData           Buffer to receive the data
> > > +
> > > +  @retval EFI_SUCCESS          The read was successful
> > > +  @retval other                The read failed
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +Ax88179SromRead (
> > > +  IN NIC_DEVICE * pNicDevice,
> > > +  IN UINT32 Address,
> > > +  OUT UINT16 * pData
> > > +  );
> > > +
> > > +
> > > +EFI_STATUS
> > > +Ax88179EnableSromWrite  (
> > > +  IN NIC_DEVICE * pNicDevice
> > > +  );
> > > +
> > > +
> > > +EFI_STATUS
> > > +Ax88179DisableSromWrite  (
> > > +  IN NIC_DEVICE * pNicDevice
> > > +  );
> > > +
> > > +EFI_STATUS
> > > +Ax88179SromWrite (
> > > +  IN NIC_DEVICE * pNicDevice,
> > > +  IN UINT32 Address,
> > > +  OUT UINT16 * pData
> > > +  );
> > > +
> > > +/**
> > > +  Send a command to the USB device.
> > > +
> > > +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> > > +  @param [in] pRequest         Pointer to the request structure
> > > +  @param [in, out] pBuffer     Data buffer address
> > > +
> > > +  @retval EFI_SUCCESS          The USB transfer was successful
> > > +  @retval other                The USB transfer failed
> > > +
> > > +**/
> > > +
> > > +EFI_STATUS
> > > +Ax88179UsbCommand (
> > > +  IN NIC_DEVICE * pNicDevice,
> > > +  IN USB_DEVICE_REQUEST * pRequest,
> > > +  IN OUT VOID * pBuffer
> > > +  );
> > > +
> > > +//------------------------------------------------------------------------------
> > > +// EFI Component Name Protocol Support
> > > +//------------------------------------------------------------------------------
> > > +extern EFI_DRIVER_BINDING_PROTOCOL   gDriverBinding;
> > > +extern EFI_COMPONENT_NAME_PROTOCOL   gComponentName;  ///<
> > Component name protocol declaration
> > > +extern EFI_COMPONENT_NAME2_PROTOCOL  gComponentName2; ///<
> > Component name 2 protocol declaration
> > > +
> > > +/**
> > > +  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 [in] pThis             A pointer to the
> > EFI_COMPONENT_NAME2_PROTOCOL or
> > > +                                EFI_COMPONENT_NAME_PROTOCOL instance.
> > > +  @param [in] pLanguage         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 3066 or ISO 639-2 language code format.
> > > +  @param [out] ppDriverName     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
> > > +GetDriverName (
> > > +  IN  EFI_COMPONENT_NAME_PROTOCOL * pThis,
> > > +  IN  CHAR8 * pLanguage,
> > > +  OUT CHAR16 ** ppDriverName
> > > +  );
> > > +
> > > +
> > > +/**
> > > +  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 [in] pThis             A pointer to the
> > EFI_COMPONENT_NAME2_PROTOCOL or
> > > +                                EFI_COMPONENT_NAME_PROTOCOL instance.
> > > +  @param [in] ControllerHandle  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 [in] ChildHandle       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 [in] pLanguage         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 3066 or ISO 639-2 language code format.
> > > +  @param [out] ppControllerName 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
> > > +GetControllerName (
> > > +  IN  EFI_COMPONENT_NAME_PROTOCOL * pThis,
> > > +  IN  EFI_HANDLE ControllerHandle,
> > > +  IN OPTIONAL EFI_HANDLE ChildHandle,
> > > +  IN  CHAR8 * pLanguage,
> > > +  OUT CHAR16 ** ppControllerName
> > > +  );
> > > +
> > > +EFI_STATUS
> > > +Ax88179SetMedium (
> > > +  IN NIC_DEVICE * pNicDevice
> > > +  );
> > > +//-----------------------------------------------------------------------------
> > > +
> > > +
> > > +
> > > +
> > > +
> > > +#define ACCESS_MAC  0x01
> > > +#define ACCESS_PHY  0x02
> > > +
> > > +#define PLSR                0x02
> > > +  #define PLSR_USB_FS  0x01
> > > +  #define PLSR_USB_HS  0x02
> > > +  #define PLSR_USB_SS  0x04
> > > +
> > > +#define NODE_ID               0x10
> > > +
> > > +#define RXCTL                 0x0b
> > > +  #define RXCTL_PRO         0x0001  ///<  Receive all packets
> > > +  #define RXCTL_AMALL       0x0002  ///<  Receive all multicast packets
> > > +  #define RXCTL_SEP         0x0004  ///<  Save error packets
> > > +  #define RXCTL_AB          0x0008  ///<  Receive broadcast packets
> > > +  #define RXCTL_AM          0x0010  ///<  Use multicast destination address
> > hash table
> > > +  #define RXCTL_AP          0x0020  ///<  Accept physical address from
> > Multicast Filter
> > > +  #define RXCTL_ARP         0x0040  ///<  Accept runt packet
> > > +  #define RXCTL_SO          0x0080  ///<  Start operation
> > > +  #define RXCTL_DROPCRCERR  0x0100  ///<  RX header 1 formate
> > selection
> > > +  #define RXCTL_IPE         0x0200  ///<  RX header 2 formate selection
> > > +  #define RXCTL_TXPADCRC    0x0400  ///<  RX header 3 formate selection
> > > +  #define RXCTL_LPBK        0x1000  ///<  MAC loop back for diagnostic
> > > +
> > > +#define MULCATFLTARRY       0x16  ///<  Write the multicast hash table,
> > Data: New 8 byte value
> > > +
> > > +#define MEDIUMSTSMOD          0x22
> > > +  #define MEDIUMSTSMOD_GM   0x0001  ///<  Gigabit Mode
> > > +  #define MEDIUMSTSMOD_FD   0x0002  ///<  Full duplex
> > > +  #define MEDIUMSTSMOD_ONE  0x0004  ///<  Must be one
> > > +  #define MEDIUMSTSMOD_ENCK 0x0008  ///<  Add in 04h
> > > +  #define MEDIUMSTSMOD_RFC  0x0010  ///<  RX flow control enable
> > > +  #define MEDIUMSTSMOD_TFC  0x0020  ///<  TX flow control enable
> > > +  #define MEDIUMSTSMOD_JFE  0x0040  ///<  Pause frame enable
> > > +  #define MEDIUMSTSMOD_PF   0x0080  ///<  Pause frame enable
> > > +  #define MEDIUMSTSMOD_RE   0x0100  ///<  Receive enable
> > > +  #define MEDIUMSTSMOD_PS   0x0200  ///<  Port speed 1=100, 0=10
> > Mbps
> > > +  #define MEDIUMSTSMOD_SBP  0x0800  ///<  Stop back pressure
> > > +  #define MEDIUMSTSMOD_SM   0x1000  ///<  Super MAC support
> > > +
> > > +#define MONITORSTAUS          0x24
> > > +  #define  MONITORSTAUS_PMETYPE   0x40
> > > +  #define  MONITORSTAUS_PMEPOL    0x20
> > > +
> > > +#define PHYPWRRSTCTL          0x26
> > > +  #define PHYPWRRSTCTL_IPRL     0x20
> > > +  #define PHYPWRRSTCTL_OSCDSSEL 0x80
> > > +  #define PHYPWRRSTCTL_BZTYPE       0x4
> > > +  #define PHYPWRRSTCTL_BZ      0x10
> > > +
> > > +#define SISSR                 0x28
> > > +  #define SISSR_PSEL        0x01
> > > +  #define SISSR_ASEL        0x02
> > > +
> > > +#define RXBINQCTRL            0x2e
> > > +  #define RXBINQCTRL_TIMEN  0x01
> > > +  #define RXBINQCTRL_IFGEN  0x02
> > > +  #define RXBINQCTRL_SIZEN  0x04
> > > +
> > > +#define RXBINQTIMERL          0x2f
> > > +#define RXBINQTIMERH          0x30
> > > +#define RXBINQSIZE            0x31
> > > +#define RXBINQIFG             0x32
> > > +
> > > +#define CLKSELECT             0x33
> > > +  #define CLKSELECT_ACS       0x02
> > > +  #define CLKSELECT_BCS       0x01
> > > +
> > > +#define PAUSE_WATERLVL_HIGH   0x54
> > > +#define PAUSE_WATERLVL_LOW    0x55
> > > +
> > > +#define RXFREEBUF             0x57
> > > +  #define MAX_RXBUF_PAGE    0x067F
> > > +
> > > +#define PHY_BMCR                        0       ///<  Control register
> > > +  #define BMCR_RESET                      0x8000  ///<  1 = Reset the PHY, bit
> > clears after reset
> > > +  #define BMCR_LOOPBACK                   0x4000  ///<  1 = Loopback enabled
> > > +  #define BMCR_AUTONEGOTIATION_ENABLE     0x1000  ///<  1 = Enable
> > autonegotiation
> > > +  #define BMCR_POWER_DOWN                 0x0800  ///<  1 = Power down
> > > +  #define BMCR_ISOLATE                    0x0400  ///<  0 = Isolate PHY
> > > +  #define BMCR_RESTART_AUTONEGOTIATION    0x0200  ///<  1 = Restart
> > autonegotiation
> > > +  #define BMCR_FULL_DUPLEX                0x0100  ///<  Full duplex operation
> > > +  #define BMCR_COLLISION_TEST             0x0080  ///<  1 = Collision test
> > enabled
> > > +  #define BMCR_1000MBPS                   0x40  ///<  Forced mode in
> > 1000Mbps
> > > +  #define BMCR_100MBPS                    0x2000    ///<  Forced mode in
> > 10Mbps
> > > +
> > > +#define PHY_BMSR                        1       ///<  Status register
> > > +  #define BMSR_100BASET4                  0x8000  ///<  1 = 100BASE-T4 mode
> > > +  #define BMSR_100BASETX_FDX              0x4000  ///<  1 = 100BASE-TX full
> > duplex
> > > +  #define BMSR_100BASETX_HDX              0x2000  ///<  1 = 100BASE-TX
> > half duplex
> > > +  #define BMSR_10BASET_FDX                0x1000  ///<  1 = 10BASE-T full
> > duplex
> > > +  #define BMSR_10BASET_HDX                0x0800  ///<  1 = 10BASE-T half
> > duplex
> > > +  #define BMSR_MF                         0x0040  ///<  1 = PHY accepts frames
> > with preamble suppressed
> > > +  #define BMSR_AUTONEG_CMPLT              0x0020  ///<  1 =
> > Autonegotiation complete
> > > +  #define BMSR_RF                         0x0010  ///<  1 = Remote fault
> > > +  #define BMSR_AUTONEG                    0x0008  ///<  1 = Able to perform
> > autonegotiation
> > > +  #define BMSR_LINKST                     0x0004  ///<  1 = Link up
> > > +  #define BMSR_JABBER_DETECT              0x0002  ///<  1 = jabber condition
> > detected
> > > +  #define BMSR_EXTENDED_CAPABILITY        0x0001  ///<  1 = Extended
> > register capable
> > > +
> > > +#define PHY_ANAR                        4       ///<  Autonegotiation advertisement
> > register
> > > +  #define AN_NP                           0x8000  ///<  1 = Next page available
> > > +  #define AN_RF                           0x2000  ///<  1 = Remote fault indicated by
> > link partner
> > > +  #define AN_FCS                          0x0400  ///<  1 = Flow control ability
> > > +  #define AN_T4                           0x0200  ///<  1 = 100BASE-T4 support
> > > +  #define AN_TX_FDX                       0x0100  ///<  1 = 100BASE-TX Full duplex
> > > +  #define AN_TX_HDX                       0x0080  ///<  1 = 100BASE-TX support
> > > +  #define AN_10_FDX                       0x0040  ///<  1 = 10BASE-T Full duplex
> > > +  #define AN_10_HDX                       0x0020  ///<  1 = 10BASE-T support
> > > +  #define AN_CSMA_CD                      0x0001  ///<  1 = IEEE 802.3 CSMA/CD
> > support
> > > +
> > > +#define PHY_ANLPAR                      5       ///<  Autonegotiation link parter
> > ability register
> > > +
> > > +#define PHY_PHYSR                       0x11
> > > +  #define PHYSR_SPEED_MASK                0xC000
> > > +  #define PHYSR_1000                      0x8000
> > > +  #define PHYSR_100                       0x4000
> > > +  #define PHYSR_FULLDUP                   0x2000
> > > +  #define PHYSR_LINK                      0x400
> > > +
> > > +EFI_STATUS
> > > +Ax88179PhyRead (
> > > +  IN NIC_DEVICE * pNicDevice,
> > > +  IN UINT8 RegisterAddress,
> > > +  IN OUT UINT16 * pPhyData
> > > +  );
> > > +
> > > +EFI_STATUS
> > > +Ax88179PhyWrite (
> > > +  IN NIC_DEVICE * pNicDevice,
> > > +  IN UINT8 RegisterAddress,
> > > +  IN UINT16 PhyData
> > > +  );
> > > +
> > > +EFI_STATUS
> > > +Ax88179MacRead (
> > > +  IN  UINT8 Offset,
> > > +  IN  UINT8 Length,
> > > +  IN  NIC_DEVICE * pNicDevice,
> > > +  IN  OUT  VOID * pData
> > > +  );
> > > +
> > > +EFI_STATUS
> > > +Ax88179SetIInInterval (
> > > +  IN  NIC_DEVICE * pNicDevice,
> > > +  IN  UINT8 Offset
> > > +  );
> > > +
> > > +EFI_STATUS
> > > +Ax88179MacWrite (
> > > +  IN  UINT8 Offset,
> > > +  IN  UINT8 Length,
> > > +  IN  NIC_DEVICE * pNicDevice,
> > > +  IN  OUT  VOID * pData
> > > +  );
> > > +
> > > +EFI_STATUS
> > > +Ax88179MacAddressGet (
> > > +  IN NIC_DEVICE * pNicDevice,
> > > +  OUT UINT8 * pMacAddress
> > > +  );
> > > +
> > > +EFI_STATUS
> > > +Ax88179MacAddressSet (
> > > +  IN NIC_DEVICE * pNicDevice,
> > > +  OUT UINT8 * pMacAddress
> > > +  );
> > > +
> > > +BOOLEAN
> > > +Ax88179GetLinkStatus (
> > > +  IN NIC_DEVICE * pNicDevice
> > > +);
> > > +
> > > +EFI_STATUS
> > > +Ax88179BulkIn(
> > > +  IN NIC_DEVICE * pNicDevice
> > > +);
> > > +
> > > +
> > > +#endif  //  _AX88179_H_
> > > diff --git
> > a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.c
> > > b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.c
> > > new file mode 100644
> > > index 000000000000..7b2db9b74285
> > > --- /dev/null
> > > +++
> > b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.c
> > > @@ -0,0 +1,1026 @@
> > > + /** @file
> > > +  Implement the interface to the AX88179 Ethernet controller.
> > > +
> > > +  This module implements the interface to the ASIX AX88179
> > > +  USB to Ethernet MAC with integrated 10/100 PHY.  Note that this
> > implementation
> > > +  only supports the integrated PHY since no other test cases were
> > available.
> > > +
> > > +  Copyright (c) 2011, Intel Corporation
> > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#include "Ax88179.h"
> > > +
> > > +
> > > +/**
> > > +  Compute the CRC
> > > +
> > > +  @param [in] pMacAddress      Address of a six byte buffer to containing
> > the MAC address.
> > > +
> > > +  @returns The CRC-32 value associated with this MAC address
> > > +
> > > +**/
> > > +UINT32
> > > +Ax88179Crc (
> > > +  IN UINT8 * pMacAddress
> > > +  )
> > > +{
> > > +  UINT32 BitNumber;
> > > +  INT32 Carry;
> > > +  INT32 Crc;
> > > +  UINT32 Data;
> > > +  UINT8 * pEnd;
> > > +
> > > +  //
> > > +  //  Walk the MAC address
> > > +  //
> > > +  Crc = -1;
> > > +  pEnd = &pMacAddress[ PXE_HWADDR_LEN_ETHER ];
> > > +  while ( pEnd > pMacAddress ) {
> > > +    Data = *pMacAddress++;
> > > +
> > > +
> > > +    //
> > > +    //  CRC32: x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 +
> > x4 + x2 + x + 1
> > > +    //
> > > +    //          1 0000 0100 1100 0001 0001 1101 1011 0111
> > > +    //
> > > +    for ( BitNumber = 0; 8 > BitNumber; BitNumber++ ) {
> > > +      Carry = (( Crc >> 31 ) & 1 ) ^ ( Data & 1 );
> > > +      Crc <<= 1;
> > > +      if ( 0 != Carry ) {
> > > +        Crc ^= 0x04c11db7;
> > > +      }
> > > +      Data >>= 1;
> > > +    }
> > > +  }
> > > +
> > > +  //
> > > +  //  Return the CRC value
> > > +  //
> > > +  return (UINT32) Crc;
> > > +}
> > > +
> > > +/**
> > > +  Get the MAC address
> > > +
> > > +  This routine calls ::Ax88179UsbCommand to request the MAC
> > > +  address from the network adapter.
> > > +
> > > +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> > > +  @param [out] pMacAddress      Address of a six byte buffer to receive the
> > MAC address.
> > > +
> > > +  @retval EFI_SUCCESS          The MAC address is available.
> > > +  @retval other                The MAC address is not valid.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +Ax88179MacAddressGet (
> > > +  IN NIC_DEVICE * pNicDevice,
> > > +  OUT UINT8 * pMacAddress
> > > +  )
> > > +{
> > > +  EFI_STATUS Status;
> > > +
> > > +  Status  = Ax88179MacRead (NODE_ID,
> > > +                            PXE_HWADDR_LEN_ETHER,
> > > +                            pNicDevice,
> > > +                            pMacAddress);
> > > +
> > > +  return Status;
> > > +}
> > > +
> > > +/**
> > > +  Set the MAC address
> > > +
> > > +  This routine calls ::Ax88179UsbCommand to set the MAC address
> > > +  in the network adapter.
> > > +
> > > +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> > > +  @param [in] pMacAddress      Address of a six byte buffer to containing
> > the new MAC address.
> > > +
> > > +  @retval EFI_SUCCESS          The MAC address was set.
> > > +  @retval other                The MAC address was not set.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +Ax88179MacAddressSet (
> > > +  IN NIC_DEVICE * pNicDevice,
> > > +  OUT UINT8 * pMacAddress
> > > +  )
> > > +{
> > > +  EFI_STATUS Status;
> > > +
> > > +  Status  = Ax88179MacWrite (NODE_ID,
> > > +                             PXE_HWADDR_LEN_ETHER,
> > > +                             pNicDevice,
> > > +                             pMacAddress);
> > > +
> > > +  return Status;
> > > +}
> > > +
> > > +/**
> > > +  Clear the multicast hash table
> > > +
> > > +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> > > +
> > > +**/
> > > +VOID
> > > +Ax88179MulticastClear (
> > > +  IN NIC_DEVICE * pNicDevice
> > > +  )
> > > +{
> > > +  int i = 0;
> > > +  //
> > > +  // Clear the multicast hash table
> > > +  //
> > > +
> > > +  for ( i = 0 ; i < 8 ; i++ )
> > > +      pNicDevice->MulticastHash[i] = 0;
> > > +}
> > > +/**
> > > +  Enable a multicast address in the multicast hash table
> > > +
> > > +  This routine calls ::Ax88179Crc to compute the hash bit for
> > > +  this MAC address.
> > > +
> > > +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> > > +  @param [in] pMacAddress      Address of a six byte buffer to containing
> > the MAC address.
> > > +
> > > +**/
> > > +VOID
> > > +Ax88179MulticastSet (
> > > +  IN NIC_DEVICE * pNicDevice,
> > > +  IN UINT8 * pMacAddress
> > > +  )
> > > +{
> > > +  UINT32 Crc;
> > > +  //
> > > +  // Compute the CRC on the destination address
> > > +  //
> > > +  Crc = Ax88179Crc (pMacAddress) >> 26;
> > > +  //
> > > +  //  Set the bit corresponding to the destination address
> > > +  //
> > > +  pNicDevice->MulticastHash [ Crc >> 3 ] |= ( 1<< (Crc& 7));
> > > +}
> > > +
> > > +/**
> > > +  Start the link negotiation
> > > +
> > > +  This routine calls ::Ax88179PhyWrite to start the PHY's link
> > > +  negotiation.
> > > +
> > > +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> > > +
> > > +  @retval EFI_SUCCESS          The link negotiation was started.
> > > +  @retval other                Failed to start the link negotiation.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +Ax88179NegotiateLinkStart (
> > > +  IN NIC_DEVICE * pNicDevice
> > > +  )
> > > +{
> > > +  UINT16 Control = 0;
> > > +  EFI_STATUS Status;
> > > +
> > > +#if FORCE_100Mbps
> > > +  Ax88179PhyRead ( pNicDevice,
> > > +                   0x09,
> > > +                   &Control );
> > > +  Control &= 0xFCFF;
> > > +  Ax88179PhyWrite ( pNicDevice, 0x09, Control );
> > > +#endif
> > > +
> > > +  //
> > > +  // Set the link speed and duplex
> > > +  //
> > > +  Control = BMCR_AUTONEGOTIATION_ENABLE
> > > +          | BMCR_RESTART_AUTONEGOTIATION;
> > > +  if ( pNicDevice->b1000Mbps ) {
> > > +    Control |= BMCR_1000MBPS;
> > > +  } else if ( pNicDevice->b100Mbps ) {
> > > +    Control |= BMCR_100MBPS;
> > > +  }
> > > +
> > > +  if ( pNicDevice->bFullDuplex ) {
> > > +    Control |= BMCR_FULL_DUPLEX;
> > > +  }
> > > +  Status = Ax88179PhyWrite ( pNicDevice, PHY_BMCR, Control );
> > > +  if (!EFI_ERROR(Status))
> > > +    gBS->Stall(3000000);
> > > +  //
> > > +  // Return the operation status
> > > +  //
> > > +  return Status;
> > > +}
> > > +
> > > +/**
> > > +  Complete the negotiation of the PHY link
> > > +
> > > +  This routine calls ::Ax88179PhyRead to determine if the
> > > +  link negotiation is complete.
> > > +
> > > +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> > > +  @param [in, out] pPollCount  Address of number of times this routine
> > was polled
> > > +  @param [out] pbComplete      Address of boolean to receive complate
> > status.
> > > +  @param [out] pbLinkUp        Address of boolean to receive link status,
> > TRUE=up.
> > > +  @param [out] pbHiSpeed       Address of boolean to receive link speed,
> > TRUE=100Mbps.
> > > +  @param [out] pbFullDuplex    Address of boolean to receive link duplex,
> > TRUE=full.
> > > +
> > > +  @retval EFI_SUCCESS          The MAC address is available.
> > > +  @retval other                The MAC address is not valid.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +Ax88179NegotiateLinkComplete (
> > > +  IN NIC_DEVICE * pNicDevice,
> > > +  IN OUT UINTN * pPollCount,
> > > +  OUT BOOLEAN * pbComplete,
> > > +  OUT BOOLEAN * pbLinkUp,
> > > +  OUT BOOLEAN * pbHiSpeed,
> > > +  OUT BOOLEAN * pbGigaSpeed,
> > > +  OUT BOOLEAN * pbFullDuplex
> > > +  )
> > > +{
> > > +  UINT16 PhyData;
> > > +  EFI_STATUS  Status;
> > > +
> > > +  //
> > > +  //  Determine if the link is up.
> > > +  //
> > > +  *pbComplete = FALSE;
> > > +
> > > +  //
> > > +  //  Get the link status
> > > +  //
> > > +  Status = Ax88179PhyRead ( pNicDevice,
> > > +                            PHY_PHYSR,
> > > +                            &PhyData );
> > > +
> > > +  if ( !EFI_ERROR ( Status )) {
> > > +    *pbLinkUp =  (BOOLEAN)( 0 != ( PhyData & PHYSR_LINK ));
> > > +    if (*pbLinkUp) {
> > > +      //
> > > +      //  Determine if the autonegotiation is complete.
> > > +      //
> > > +      Status = Ax88179PhyRead ( pNicDevice,
> > > +                            PHY_BMSR,
> > > +                            &PhyData );
> > > +      if ( !EFI_ERROR (Status)) {
> > > +          *pbComplete =  (BOOLEAN)( 0 != ( PhyData &
> > BMSR_AUTONEG_CMPLT ));
> > > +
> > > +          if ( 0 != *pbComplete ) {
> > > +            //
> > > +            //  Get the partners capabilities.
> > > +            //
> > > +            Status = Ax88179PhyRead ( pNicDevice,
> > > +                                      PHY_PHYSR,
> > > +                                      &PhyData );
> > > +            if ( !EFI_ERROR ( Status )) {
> > > +              //
> > > +              //  Autonegotiation is complete
> > > +              //  Determine the link speed.
> > > +              //
> > > +              *pbGigaSpeed = (BOOLEAN) (( PhyData & PHYSR_SPEED_MASK )
> > == PHYSR_1000 );
> > > +              *pbHiSpeed = (BOOLEAN)(( PhyData & PHYSR_SPEED_MASK ) ==
> > PHYSR_100 );
> > > +
> > > +              //
> > > +              //  Determine the link duplex.
> > > +              //
> > > +              *pbFullDuplex = (BOOLEAN)( (PhyData & PHYSR_FULLDUP) ==
> > PHYSR_FULLDUP);
> > > +          }
> > > +        }
> > > +      }
> > > +    }
> > > +  }
> > > +
> > > +
> > > +  //
> > > +  // Return the operation status
> > > +  //
> > > +  return Status;
> > > +}
> > > +
> > > +
> > > +/**
> > > +  Read a register from the PHY
> > > +
> > > +  This routine calls ::Ax88179UsbCommand to read a PHY register.
> > > +
> > > +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> > > +  @param [in] RegisterAddress  Number of the register to read.
> > > +  @param [in, out] pPhyData    Address of a buffer to receive the PHY
> > register value
> > > +
> > > +  @retval EFI_SUCCESS          The PHY data is available.
> > > +  @retval other                The PHY data is not valid.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +Ax88179PhyRead (
> > > +  IN NIC_DEVICE * pNicDevice,
> > > +  IN UINT8 RegisterAddress,
> > > +  IN OUT UINT16 * pPhyData
> > > +  )
> > > +{
> > > +  USB_DEVICE_REQUEST SetupMsg;
> > > +  EFI_STATUS Status;
> > > +
> > > +  //
> > > +  //  Read the PHY register address.
> > > +  //
> > > +  SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
> > > +                       | USB_REQ_TYPE_VENDOR
> > > +                       | USB_TARGET_DEVICE;
> > > +  SetupMsg.Request = ACCESS_PHY;
> > > +  SetupMsg.Value = pNicDevice->PhyId;
> > > +  SetupMsg.Index = RegisterAddress;
> > > +  SetupMsg.Length = sizeof ( *pPhyData );
> > > +  Status = Ax88179UsbCommand ( pNicDevice,
> > > +                               &SetupMsg,
> > > +                               pPhyData );
> > > +
> > > +  //
> > > +  //  Return the operation status.
> > > +  //
> > > +  return Status;
> > > +}
> > > +
> > > +
> > > +/**
> > > +  Write to a PHY register
> > > +
> > > +  This routine calls ::Ax88179UsbCommand to write a PHY register.
> > > +
> > > +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> > > +  @param [in] RegisterAddress  Number of the register to read.
> > > +  @param [in] PhyData          Address of a buffer to receive the PHY
> > register value
> > > +
> > > +  @retval EFI_SUCCESS          The PHY data was written.
> > > +  @retval other                Failed to wwrite the PHY register.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +Ax88179PhyWrite (
> > > +  IN NIC_DEVICE * pNicDevice,
> > > +  IN UINT8 RegisterAddress,
> > > +  IN UINT16 PhyData
> > > +  )
> > > +{
> > > +  USB_DEVICE_REQUEST SetupMsg;
> > > +  EFI_STATUS Status;
> > > +
> > > +  //
> > > +  //  Write the PHY register
> > > +  //
> > > +  SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> > > +                       | USB_TARGET_DEVICE;
> > > +  SetupMsg.Request = ACCESS_PHY;
> > > +  SetupMsg.Value = pNicDevice->PhyId;
> > > +  SetupMsg.Index = RegisterAddress;
> > > +  SetupMsg.Length = sizeof ( PhyData );
> > > +  Status = Ax88179UsbCommand ( pNicDevice,
> > > +                               &SetupMsg,
> > > +                               &PhyData );
> > > +  //
> > > +  //  Return the operation status.
> > > +  //
> > > +  return Status;
> > > +}
> > > +
> > > +
> > > +/**
> > > +  Reset the AX88179
> > > +
> > > +  This routine uses ::Ax88179UsbCommand to reset the network
> > > +  adapter.  This routine also uses ::Ax88179PhyWrite to reset
> > > +  the PHY.
> > > +
> > > +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> > > +
> > > +  @retval EFI_SUCCESS          The MAC address is available.
> > > +  @retval other                The MAC address is not valid.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +Ax88179Reset (
> > > +  IN NIC_DEVICE * pNicDevice
> > > +  )
> > > +{
> > > +  EFI_STATUS Status;
> > > +  UINT16  val;
> > > +  UINT8 val8;
> > > +
> > > +  Status = Ax88179SetIInInterval(pNicDevice, 0xff);
> > > +
> > > +  if (EFI_ERROR(Status)) goto err;
> > > +
> > > +  val8 = 0;
> > > +  Status  = Ax88179MacRead (PLSR,
> > > +                            sizeof(val8),
> > > +                            pNicDevice,
> > > +                            &val8);
> > > +
> > > +  if (EFI_ERROR(Status)) goto err;
> > > +
> > > +  if (val8 & PLSR_USB_SS)
> > > +    pNicDevice->usbMaxPktSize = 1024;
> > > +  else
> > > +    pNicDevice->usbMaxPktSize = 512;
> > > +
> > > +  val = 0;
> > > +  Status = Ax88179MacWrite ( PHYPWRRSTCTL,
> > > +                             sizeof (val),
> > > +                             pNicDevice,
> > > +                             &val);
> > > +
> > > +  if (EFI_ERROR(Status)) goto err;
> > > +
> > > +  gBS->Stall ( 10000 );
> > > +
> > > +  val =  PHYPWRRSTCTL_IPRL;
> > > +  Status = Ax88179MacWrite ( PHYPWRRSTCTL,
> > > +                             sizeof (val),
> > > +                             pNicDevice,
> > > +                             &val);
> > > +
> > > +  if (EFI_ERROR(Status)) goto err;
> > > +
> > > +  gBS->Stall ( 200000 );
> > > +
> > > +  val = CLKSELECT_BCS | CLKSELECT_ACS;
> > > +  Status = Ax88179MacWrite ( CLKSELECT,
> > > +                             1,
> > > +                             pNicDevice,
> > > +                             &val);
> > > +
> > > +  if (EFI_ERROR(Status)) goto err;
> > > +
> > > +  gBS->Stall ( 100000 );
> > > +
> > > +  val = 0x52;
> > > +  Status = Ax88179MacWrite ( PAUSE_WATERLVL_HIGH,
> > > +                             1,
> > > +                             pNicDevice,
> > > +                             &val);
> > > +
> > > +  if (EFI_ERROR(Status)) goto err;
> > > +
> > > +  val = 0x34;
> > > +  Status = Ax88179MacWrite ( PAUSE_WATERLVL_LOW,
> > > +                             1,
> > > +                             pNicDevice,
> > > +                             &val);
> > > +
> > > +  if (EFI_ERROR(Status)) goto err;
> > > +
> > > +  val = RXBINQCTRL_TIMEN | RXBINQCTRL_IFGEN | RXBINQCTRL_SIZEN;
> > > +
> > > +  Status =  Ax88179MacWrite ( RXBINQCTRL,
> > > +                              0x01,
> > > +                              pNicDevice,
> > > +                              &val);
> > > +
> > > +  if (EFI_ERROR(Status)) goto err;
> > > +
> > > +  val = 0;
> > > +  Status =  Ax88179MacWrite ( RXBINQTIMERL,
> > > +                              0x01,
> > > +                              pNicDevice,
> > > +                              &val);
> > > +
> > > +  if (EFI_ERROR(Status)) goto err;
> > > +
> > > +  val = 0;
> > > +  Status =  Ax88179MacWrite ( RXBINQTIMERH,
> > > +                              0x01,
> > > +                              pNicDevice,
> > > +                              &val);
> > > +
> > > +  if (EFI_ERROR(Status)) goto err;
> > > +
> > > +  val = 12; //AX88179_BULKIN_SIZE_INK - 1;
> > > +  Status =  Ax88179MacWrite ( RXBINQSIZE,
> > > +                              0x01,
> > > +                              pNicDevice,
> > > +                              &val);
> > > +
> > > +  if (EFI_ERROR(Status)) goto err;
> > > +
> > > +  val = 0x0F;
> > > +  Status =  Ax88179MacWrite ( RXBINQIFG,
> > > +                              0x01,
> > > +                              pNicDevice,
> > > +                              &val);
> > > +
> > > +err:
> > > +  return Status;
> > > +}
> > > +
> > > +EFI_STATUS
> > > +Ax88179RxControl (
> > > +  IN NIC_DEVICE * pNicDevice,
> > > +  IN UINT32 RxFilter
> > > +  )
> > > +{
> > > +  UINT16 MediumStatus;
> > > +  UINT16 RxControl = 0;
> > > +  EFI_STATUS Status = EFI_SUCCESS;
> > > +  //
> > > +  // Enable the receiver if something is to be received
> > > +  //
> > > +  if ( 0 != RxFilter ) {
> > > +    //
> > > +    //  Enable the receiver
> > > +    //
> > > +    Status  = Ax88179MacRead (MEDIUMSTSMOD,
> > > +                              sizeof ( MediumStatus ),
> > > +                              pNicDevice,
> > > +                              &MediumStatus);
> > > +
> > > +    if ( !EFI_ERROR ( Status ) && pNicDevice->CurMediumStatus !=
> > MediumStatus) {
> > > +        MediumStatus = MEDIUMSTSMOD_RE | MEDIUMSTSMOD_ONE;
> > > +        if ( pNicDevice->bFullDuplex ) {
> > > +          MediumStatus |= MEDIUMSTSMOD_TFC | MEDIUMSTSMOD_RFC |
> > MEDIUMSTSMOD_FD;
> > > +        } else {
> > > +          MediumStatus &= ~(MEDIUMSTSMOD_TFC | MEDIUMSTSMOD_RFC
> > | MEDIUMSTSMOD_FD);
> > > +        }
> > > +        if ( pNicDevice->b1000Mbps ) {
> > > +          MediumStatus |= MEDIUMSTSMOD_GM;
> > > +          MediumStatus |= MEDIUMSTSMOD_ENCK;
> > > +          MediumStatus &= ~MEDIUMSTSMOD_PS;
> > > +        } else {
> > > +          MediumStatus &= ~MEDIUMSTSMOD_GM;
> > > +          MediumStatus &= ~MEDIUMSTSMOD_ENCK;
> > > +          if ( pNicDevice->b100Mbps ) {
> > > +            MediumStatus |= MEDIUMSTSMOD_PS;
> > > +          }  else {
> > > +            MediumStatus &= ~MEDIUMSTSMOD_PS;
> > > +          }
> > > +        }
> > > +        Status  = Ax88179MacWrite (MEDIUMSTSMOD,
> > > +                                   sizeof ( MediumStatus ),
> > > +                                   pNicDevice,
> > > +                                   &MediumStatus);
> > > +        if ( !EFI_ERROR ( Status ))
> > > +          pNicDevice->CurMediumStatus = MediumStatus;
> > > +    }
> > > +  }
> > > +
> > > +  RxControl = RXCTL_SO | RXCTL_IPE;
> > > +
> > > +  //
> > > +  //  Enable multicast if requested
> > > +  //
> > > +  if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST )) {
> > > +    RxControl |= RXCTL_AM;
> > > +    //
> > > +    //  Update the multicast hash table
> > > +    //
> > > +    Status  = Ax88179MacWrite (MULCATFLTARRY,
> > > +                               8,
> > > +                               pNicDevice,
> > > +                               &pNicDevice->MulticastHash );
> > > +  }
> > > +
> > > +  //
> > > +  //  Enable all multicast if requested
> > > +  //
> > > +  if ( 0 != ( RxFilter &
> > EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST )) {
> > > +    RxControl |= RXCTL_AMALL;
> > > +  }
> > > +  //
> > > +  //  Enable broadcast if requested
> > > +  //
> > > +  if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST )) {
> > > +    RxControl |= RXCTL_AB;
> > > +  }
> > > +
> > > +  //
> > > +  //  Enable promiscuous mode if requested
> > > +  //
> > > +  if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS )) {
> > > +    RxControl |= RXCTL_PRO;
> > > +  }
> > > +
> > > +  //
> > > +  //  Update the receiver control
> > > +  //
> > > +  if (pNicDevice->CurRxControl != RxControl) {
> > > +    Status  = Ax88179MacWrite (RXCTL,
> > > +                               0x02,
> > > +                               pNicDevice,
> > > +                               &RxControl);
> > > +    if ( !EFI_ERROR ( Status ))
> > > +      pNicDevice->CurRxControl = RxControl;
> > > +  }
> > > +
> > > +  //
> > > +  // Return the operation status
> > > +  //
> > > +  return Status;
> > > +}
> > > +
> > > +EFI_STATUS
> > > +Ax88179ReloadSrom  (
> > > +  IN NIC_DEVICE * pNicDevice
> > > +  )
> > > +{
> > > +  EFI_STATUS Status;
> > > +
> > > +  Status = EFI_UNSUPPORTED;
> > > +  return Status;
> > > +
> > > +}
> > > +
> > > +/**
> > > +  Read an SROM location
> > > +
> > > +  This routine calls ::Ax88179UsbCommand to read data from the
> > > +  SROM.
> > > +
> > > +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> > > +  @param [in] Address          SROM address
> > > +  @param [out] pData           Buffer to receive the data
> > > +
> > > +  @retval EFI_SUCCESS          The read was successful
> > > +  @retval other                The read failed
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +Ax88179SromRead (
> > > +  IN NIC_DEVICE * pNicDevice,
> > > +  IN UINT32 Address,
> > > +  OUT UINT16 * pData
> > > +  )
> > > +{
> > > +  EFI_STATUS Status;
> > > +
> > > +  Status = EFI_UNSUPPORTED;
> > > +  return Status;
> > > +}
> > > +
> > > +EFI_STATUS
> > > +Ax88179EnableSromWrite  (
> > > +  IN NIC_DEVICE * pNicDevice
> > > +  )
> > > +{
> > > +  EFI_STATUS Status;
> > > +
> > > +  Status = EFI_UNSUPPORTED;
> > > +  return Status;
> > > +}
> > > +
> > > +
> > > +EFI_STATUS
> > > +Ax88179DisableSromWrite  (
> > > +  IN NIC_DEVICE * pNicDevice
> > > +  )
> > > +{
> > > +  EFI_STATUS Status;
> > > +
> > > +  Status = EFI_UNSUPPORTED;
> > > +  return Status;
> > > +}
> > > +
> > > +/**
> > > +  Write an SROM location
> > > +
> > > +  This routine calls ::Ax88179UsbCommand to write data from the
> > > +  SROM.
> > > +
> > > +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> > > +  @param [in] Address          SROM address
> > > +  @param [out] pData           Buffer of data to write
> > > +
> > > +  @retval EFI_SUCCESS          The write was successful
> > > +  @retval other                The write failed
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +Ax88179SromWrite (
> > > +  IN NIC_DEVICE * pNicDevice,
> > > +  IN UINT32 Address,
> > > +  IN UINT16 * pData
> > > +  )
> > > +{
> > > +  EFI_STATUS Status;
> > > +
> > > +  Status = EFI_UNSUPPORTED;
> > > +  return Status;
> > > +}
> > > +
> > > +
> > > +
> > > +/**
> > > +  Send a command to the USB device.
> > > +
> > > +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> > > +  @param [in] pRequest         Pointer to the request structure
> > > +  @param [in, out] pBuffer     Data buffer address
> > > +
> > > +  @retval EFI_SUCCESS          The USB transfer was successful
> > > +  @retval other                The USB transfer failed
> > > +
> > > +**/
> > > +
> > > +EFI_STATUS
> > > +Ax88179UsbCommand (
> > > +  IN NIC_DEVICE * pNicDevice,
> > > +  IN USB_DEVICE_REQUEST * pRequest,
> > > +  IN OUT VOID * pBuffer
> > > +  )
> > > +{
> > > +
> > > +  EFI_USB_DATA_DIRECTION Direction;
> > > +  EFI_USB_IO_PROTOCOL * pUsbIo;
> > > +  EFI_STATUS Status = EFI_TIMEOUT;
> > > +  UINT32 CmdStatus = EFI_USB_NOERROR;
> > > +  int i;
> > > +  //
> > > +  // Determine the transfer direction
> > > +  //
> > > +  Direction = EfiUsbNoData;
> > > +  if ( 0 != pRequest->Length ) {
> > > +    Direction = ( 0 != ( pRequest->RequestType & USB_ENDPOINT_DIR_IN ))
> > > +                        ? EfiUsbDataIn : EfiUsbDataOut;
> > > +  }
> > > +
> > > +  //
> > > +  // Issue the command
> > > +  //
> > > +  pUsbIo = pNicDevice->pUsbIo;
> > > +
> > > +  for ( i = 0 ; i < 3 && EFI_TIMEOUT == Status; i++) {
> > > +    Status = pUsbIo->UsbControlTransfer ( pUsbIo,
> > > +                                        pRequest,
> > > +                                        Direction,
> > > +                                        USB_BUS_TIMEOUT,
> > > +                                        pBuffer,
> > > +                                        pRequest->Length,
> > > +                                        &CmdStatus );
> > > +  }
> > > +  //
> > > +  // Determine the operation status
> > > +  //
> > > +  if (EFI_ERROR(Status) || EFI_ERROR(CmdStatus))
> > > +    Status = EFI_DEVICE_ERROR;
> > > +  //
> > > +  // Return the operation status
> > > +  //
> > > +  return Status;
> > > +}
> > > +
> > > +EFI_STATUS
> > > +Ax88179MacRead (
> > > +  IN  UINT8 Offset,
> > > +  IN  UINT8 Length,
> > > +  IN  NIC_DEVICE * pNicDevice,
> > > +  IN  OUT  VOID * pData
> > > +  )
> > > +{
> > > +
> > > +  EFI_STATUS Status;
> > > +  USB_DEVICE_REQUEST SetupMsg;
> > > +  SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> > > +                       | USB_TARGET_DEVICE
> > > +                       | USB_ENDPOINT_DIR_IN;
> > > +
> > > +  SetupMsg.Request = ACCESS_MAC;
> > > +  SetupMsg.Value  = Offset;
> > > +  SetupMsg.Index  = Length;
> > > +  SetupMsg.Length = SetupMsg.Index;
> > > +
> > > +  Status = Ax88179UsbCommand ( pNicDevice,
> > > +                               &SetupMsg,
> > > +                               pData );
> > > +
> > > +  return Status;
> > > +
> > > +}
> > > +
> > > +EFI_STATUS
> > > +Ax88179MacWrite (
> > > +  IN  UINT8 Offset,
> > > +  IN  UINT8 Length,
> > > +  IN  NIC_DEVICE * pNicDevice,
> > > +  IN  OUT  VOID * pData
> > > +  )
> > > +{
> > > +
> > > +  EFI_STATUS Status;
> > > +  USB_DEVICE_REQUEST SetupMsg;
> > > +  SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> > > +                       | USB_TARGET_DEVICE;
> > > +
> > > +  SetupMsg.Request = ACCESS_MAC;
> > > +  SetupMsg.Value  = Offset;
> > > +  SetupMsg.Index  = Length;
> > > +  SetupMsg.Length = SetupMsg.Index;
> > > +
> > > +  Status = Ax88179UsbCommand ( pNicDevice,
> > > +                               &SetupMsg,
> > > +                               pData );
> > > +
> > > +  return Status;
> > > +
> > > +}
> > > +
> > > +EFI_STATUS
> > > +Ax88179SetIInInterval (
> > > +  IN  NIC_DEVICE * pNicDevice,
> > > +  IN  UINT8 Interval
> > > +  )
> > > +{
> > > +
> > > +  EFI_STATUS Status;
> > > +  USB_DEVICE_REQUEST SetupMsg;
> > > +  SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> > > +                       | USB_TARGET_DEVICE;
> > > +
> > > +  SetupMsg.Request = 0x91;
> > > +  SetupMsg.Value  = Interval;
> > > +  SetupMsg.Index  = 0;
> > > +  SetupMsg.Length = 0;
> > > +
> > > +  Status = Ax88179UsbCommand ( pNicDevice,
> > > +                               &SetupMsg,
> > > +                               NULL );
> > > +
> > > +  return Status;
> > > +
> > > +}
> > > +
> > > +EFI_STATUS
> > > +Ax88179SetMedium (
> > > +  IN NIC_DEVICE * pNicDevice
> > > +  )
> > > +{
> > > +  UINT16 MediumStatus;
> > > +  EFI_STATUS Status;
> > > +
> > > +  MediumStatus = MEDIUMSTSMOD_RE | MEDIUMSTSMOD_ONE;
> > > +  if ( pNicDevice->bFullDuplex ) {
> > > +    MediumStatus |= MEDIUMSTSMOD_TFC | MEDIUMSTSMOD_RFC |
> > MEDIUMSTSMOD_FD;
> > > +  } else {
> > > +    MediumStatus &= ~(MEDIUMSTSMOD_TFC | MEDIUMSTSMOD_RFC |
> > MEDIUMSTSMOD_FD);
> > > +  }
> > > +  if ( pNicDevice->b1000Mbps ) {
> > > +    MediumStatus |= MEDIUMSTSMOD_GM;
> > > +    MediumStatus &= ~MEDIUMSTSMOD_PS;
> > > +  } else {
> > > +    MediumStatus &= ~MEDIUMSTSMOD_GM;
> > > +    if ( pNicDevice->b100Mbps ) {
> > > +      MediumStatus |= MEDIUMSTSMOD_PS;
> > > +    } else {
> > > +      MediumStatus &= ~MEDIUMSTSMOD_PS;
> > > +    }
> > > +  }
> > > +  Status  = Ax88179MacWrite (MEDIUMSTSMOD,
> > > +                             sizeof ( MediumStatus ),
> > > +                             pNicDevice,
> > > +                             &MediumStatus);
> > > +  if ( !EFI_ERROR ( Status ))
> > > +  pNicDevice->CurMediumStatus = MediumStatus;
> > > +
> > > +  return Status;
> > > +}
> > > +
> > > +
> > > +BOOLEAN
> > > +Ax88179GetLinkStatus (
> > > +  IN NIC_DEVICE * pNicDevice
> > > +)
> > > +{
> > > +  UINT32 CmdStatus;
> > > +  EFI_USB_IO_PROTOCOL * pUsbIo;
> > > +  UINT64    IntData = 0;
> > > +  UINTN     IntDataLeng = 8;
> > > +  EFI_STATUS Status;
> > > +
> > > +  //
> > > +  // Issue the command
> > > +  //
> > > +  pUsbIo = pNicDevice->pUsbIo;
> > > +  Status = pUsbIo->UsbSyncInterruptTransfer( pUsbIo,
> > > +                                        USB_ENDPOINT_DIR_IN | INTERRUPT_ENDPOINT,
> > > +                                        &IntData,
> > > +                                        &IntDataLeng,
> > > +                                        USB_BUS_TIMEOUT,
> > > +                                        &CmdStatus );
> > > +
> > > +  if ( EFI_ERROR(Status) || EFI_ERROR(CmdStatus) || 0 == IntDataLeng)
> > > +    return FALSE;
> > > +
> > > +  return (IntData & 0x10000)? TRUE : FALSE;
> > > +
> > > +}
> > > +
> > > +EFI_STATUS
> > > +Ax88179BulkIn(
> > > +  IN NIC_DEVICE * pNicDevice
> > > +)
> > > +{
> > > +  int i;
> > > +  UINT16  val;
> > > +  UINTN LengthInBytes = 0;
> > > +  UINTN TMP_LENG = AX88179_MAX_BULKIN_SIZE;
> > > +  UINTN CURBufSize = AX88179_MAX_BULKIN_SIZE;
> > > +  UINTN PREBufSize = 0;
> > > +  EFI_STATUS Status = EFI_NOT_READY;
> > > +  EFI_USB_IO_PROTOCOL *pUsbIo;
> > > +  UINT32 TransferStatus;
> > > +
> > > +  pNicDevice->SkipRXCnt = 0;
> > > +
> > > +  pUsbIo = pNicDevice->pUsbIo;
> > > +  for ( i = 0 ; i < (AX88179_MAX_BULKIN_SIZE / 512) && pUsbIo != NULL;
> > i++) {
> > > +    VOID* tmpAddr = 0;
> > > +
> > > +    if (pNicDevice->bSetZeroLen) {
> > > +      val =  PHYPWRRSTCTL_IPRL | PHYPWRRSTCTL_BZ;
> > > +      Status = Ax88179MacWrite ( PHYPWRRSTCTL,
> > > +                                 sizeof (val),
> > > +                                 pNicDevice,
> > > +                                 &val);
> > > +      if (EFI_ERROR(Status)) {
> > > +        LengthInBytes = 0;
> > > +        Status = EFI_NOT_READY;
> > > +        goto no_pkt;
> > > +      }
> > > +      pNicDevice->bSetZeroLen = FALSE;
> > > +    }
> > > +    tmpAddr = (VOID*) &pNicDevice->pBulkInbuf[LengthInBytes];
> > > +
> > > +    Status =  EFI_NOT_READY;
> > > +    Status = pUsbIo->UsbBulkTransfer ( pUsbIo,
> > > +                          USB_ENDPOINT_DIR_IN | BULK_IN_ENDPOINT,
> > > +                          tmpAddr,
> > > +                          &TMP_LENG,
> > > +                          BULKIN_TIMEOUT,
> > > +                          &TransferStatus );
> > > +
> > > +    if (( !EFI_ERROR ( Status )) && ( !EFI_ERROR ( TransferStatus )) &&
> > TMP_LENG != 0) {
> > > +      LengthInBytes += TMP_LENG;
> > > +      if ((TMP_LENG % pNicDevice->usbMaxPktSize) != 0) {
> > > +        goto done;
> > > +      }
> > > +      CURBufSize = CURBufSize - TMP_LENG;
> > > +      TMP_LENG = CURBufSize;
> > > +      pNicDevice->bSetZeroLen = TRUE;
> > > +    } else if (( !EFI_ERROR ( Status )) &&
> > > +               ( !EFI_ERROR ( TransferStatus )) &&
> > > +               ( TMP_LENG == 0) &&
> > > +               LengthInBytes) {
> > > +      if (PREBufSize == CURBufSize) {
> > > +        goto done;
> > > +      }
> > > +      TMP_LENG = CURBufSize;
> > > +      PREBufSize = CURBufSize;
> > > +      pNicDevice->bSetZeroLen = TRUE;
> > > +    } else if (( !EFI_ERROR ( Status )) &&
> > > +               ( !EFI_ERROR ( TransferStatus )) &&
> > > +               ( TMP_LENG == 0)) {
> > > +      pNicDevice->bSetZeroLen = TRUE;
> > > +      LengthInBytes = 0;
> > > +      Status = EFI_NOT_READY;
> > > +      goto done;
> > > +    } else if (EFI_TIMEOUT == Status && EFI_USB_ERR_TIMEOUT ==
> > TransferStatus) {
> > > +      pNicDevice->bSetZeroLen = TRUE;
> > > +      LengthInBytes = 0;
> > > +      Status = EFI_NOT_READY;
> > > +      goto done;
> > > +    } else {
> > > +      pNicDevice->bSetZeroLen = TRUE;
> > > +      LengthInBytes = 0;
> > > +      Status = EFI_NOT_READY;
> > > +      goto done;
> > > +    }
> > > +  }
> > > +
> > > +done:
> > > +  if (LengthInBytes != 0) {
> > > +    UINT16 tmplen = 0;
> > > +    UINT16 tmpPktCnt = 0;
> > > +
> > > +    tmpPktCnt = *((UINT16 *) (pNicDevice->pBulkInbuf + LengthInBytes -
> > 4));
> > > +    tmplen =  *((UINT16*) (pNicDevice->pBulkInbuf + LengthInBytes - 2));
> > > +
> > > +    if (((UINTN)(((tmpPktCnt * 4 + 4 + 7) & 0xfff8) + tmplen)) ==
> > LengthInBytes) {
> > > +      pNicDevice->PktCnt = tmpPktCnt;
> > > +      pNicDevice->pCurPktHdrOff = pNicDevice->pBulkInbuf + tmplen;
> > > +      pNicDevice->pCurPktOff = pNicDevice->pBulkInbuf;
> > > +      *((UINT16 *) (pNicDevice->pBulkInbuf + LengthInBytes - 4)) = 0;
> > > +      *((UINT16*) (pNicDevice->pBulkInbuf + LengthInBytes - 2)) = 0;
> > > +      Status = EFI_SUCCESS;
> > > +    } else {
> > > +      Status = EFI_NOT_READY;
> > > +    }
> > > +  } else {
> > > +    Status = EFI_NOT_READY;
> > > +  }
> > > +no_pkt:
> > > +   return Status;
> > > +}
> > > diff --git
> > a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/ComponentNa
> > me.c
> > >
> > b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/ComponentNa
> > me.c
> > > new file mode 100644
> > > index 000000000000..bb7ea146be02
> > > --- /dev/null
> > > +++
> > b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/ComponentNa
> > me.c
> > > @@ -0,0 +1,290 @@
> > > +/** @file
> > > +  UEFI Component Name(2) protocol implementation.
> > > +
> > > +  Copyright (c) 2011, Intel Corporation. All rights reserved.
> > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#include "Ax88179.h"
> > > +
> > > +/**
> > > +  EFI Component Name Protocol declaration
> > > +**/
> > > +GLOBAL_REMOVE_IF_UNREFERENCED
> > EFI_COMPONENT_NAME_PROTOCOL  gComponentName = {
> > > +  GetDriverName,
> > > +  GetControllerName,
> > > +  "eng"
> > > +};
> > > +
> > > +/**
> > > +  EFI Component Name 2 Protocol declaration
> > > +**/
> > > +GLOBAL_REMOVE_IF_UNREFERENCED
> > EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
> > > +  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) GetDriverName,
> > > +  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)
> > GetControllerName,
> > > +  "en"
> > > +};
> > > +
> > > +
> > > +/**
> > > +  Driver name table declaration
> > > +**/
> > > +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
> > > +mDriverNameTable[] = {
> > > +  {"eng;en", L"ASIX AX88179 Ethernet Driver 2.9.0"},
> > > +  {NULL,  NULL}
> > > +};
> > > +
> > > +/**
> > > +  Controller name table declaration
> > > +**/
> > > +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
> > > +mControllerNameTable[] = {
> > > +  {"eng;en", L"AX88179 USB3.0 Gigabit Ethernet Controller"},
> > > +  {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 [in] pThis             A pointer to the
> > EFI_COMPONENT_NAME2_PROTOCOL or
> > > +                                EFI_COMPONENT_NAME_PROTOCOL instance.
> > > +  @param [in] pLanguage         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 3066 or ISO 639-2 language code format.
> > > +  @param [out] ppDriverName     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
> > > +GetDriverName (
> > > +  IN  EFI_COMPONENT_NAME_PROTOCOL * pThis,
> > > +  IN  CHAR8 * pLanguage,
> > > +  OUT CHAR16 ** ppDriverName
> > > +  )
> > > +{
> > > +  EFI_STATUS Status;
> > > +
> > > +
> > > +  Status = LookupUnicodeString2 (
> > > +             pLanguage,
> > > +             pThis->SupportedLanguages,
> > > +             mDriverNameTable,
> > > +             ppDriverName,
> > > +             (BOOLEAN)(pThis == &gComponentName)
> > > +             );
> > > +
> > > +  return Status;
> > > +}
> > > +
> > > +/**
> > > +  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 [in] pThis             A pointer to the
> > EFI_COMPONENT_NAME2_PROTOCOL or
> > > +                                EFI_COMPONENT_NAME_PROTOCOL instance.
> > > +  @param [in] ControllerHandle  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 [in] ChildHandle       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 [in] pLanguage         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 3066 or ISO 639-2 language code format.
> > > +  @param [out] ppControllerName 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.
> > > +
> > > +**/
> > > +
> > > +
> > > +
> > > +#if PASS_SCT
> > > +EFI_STATUS
> > > +EFIAPI
> > > +GetControllerName (
> > > +  IN  EFI_COMPONENT_NAME_PROTOCOL * pThis,
> > > +  IN  EFI_HANDLE ControllerHandle,
> > > +  IN OPTIONAL EFI_HANDLE ChildHandle,
> > > +  IN  CHAR8 * pLanguage,
> > > +  OUT CHAR16 ** ppControllerName
> > > +  )
> > > +{
> > > +
> > > +  EFI_STATUS                  Status;
> > > +  EFI_USB_IO_PROTOCOL         *UsbIoProtocol;
> > > +
> > > +  //
> > > +  // This is a device driver, so ChildHandle must be NULL.
> > > +  //
> > > +  if (ChildHandle != NULL) {
> > > +    return EFI_UNSUPPORTED;
> > > +  }
> > > +
> > > +  //
> > > +  // Check Controller's handle
> > > +  //
> > > +  Status = gBS->OpenProtocol (
> > > +                  ControllerHandle,
> > > +                  &gEfiUsbIoProtocolGuid,
> > > +                  (VOID **) &UsbIoProtocol,
> > > +                  gDriverBinding.DriverBindingHandle,
> > > +                  ControllerHandle,
> > > +                  EFI_OPEN_PROTOCOL_BY_DRIVER
> > > +                  );
> > > +  if (!EFI_ERROR (Status)) {
> > > +    gBS->CloseProtocol (
> > > +           ControllerHandle,
> > > +           &gEfiUsbIoProtocolGuid,
> > > +           gDriverBinding.DriverBindingHandle,
> > > +           ControllerHandle
> > > +           );
> > > +    return EFI_UNSUPPORTED;
> > > +  }
> > > +
> > > +  if (Status != EFI_ALREADY_STARTED) {
> > > +    return EFI_UNSUPPORTED;
> > > +  }
> > > +
> > > +  Status =  LookupUnicodeString2 (
> > > +           pLanguage,
> > > +            pThis->SupportedLanguages,
> > > +           mControllerNameTable,
> > > +           ppControllerName,
> > > +           (BOOLEAN)(pThis == &gComponentName)
> > > +           );
> > > +
> > > +  return  Status;
> > > +}
> > > +#else
> > > +
> > > +EFI_STATUS
> > > +EFIAPI
> > > +GetControllerName (
> > > +  IN  EFI_COMPONENT_NAME_PROTOCOL * pThis,
> > > +  IN  EFI_HANDLE ControllerHandle,
> > > +  IN OPTIONAL EFI_HANDLE ChildHandle,
> > > +  IN  CHAR8 * pLanguage,
> > > +  OUT CHAR16 ** ppControllerName
> > > +  )
> > > +{
> > > +  EFI_STATUS Status;
> > > +  EFI_USB_IO_PROTOCOL         *UsbIoProtocol;
> > > +  EFI_USB_DEVICE_DESCRIPTOR Device;
> > > +
> > > +  //
> > > +  //  Connect to the USB stack
> > > +  //
> > > +  Status = gBS->OpenProtocol (
> > > +                  ControllerHandle,
> > > +                  &gEfiUsbIoProtocolGuid,
> > > +                  (VOID **) &UsbIoProtocol,
> > > +                  gDriverBinding.DriverBindingHandle,
> > > +                  ControllerHandle,
> > > +                  EFI_OPEN_PROTOCOL_BY_DRIVER
> > > +                  );
> > > +
> > > +
> > > +  if (!EFI_ERROR ( Status )) {
> > > +      Status = UsbIoProtocol->UsbGetDeviceDescriptor ( UsbIoProtocol,
> > &Device );
> > > +      if (EFI_ERROR(Status)) {
> > > +        Status = EFI_UNSUPPORTED;
> > > +      } else {
> > > +          //
> > > +          //  Validate the adapter
> > > +          //
> > > +          if (( VENDOR_ID == Device.IdVendor )
> > > +            && ( PRODUCT_ID == Device.IdProduct )) {
> > > +            *ppControllerName = L"AX88179 USB3.0 Gigabit Ethernet
> > Controller";
> > > +            Status = EFI_SUCCESS;
> > > +          } else if (( VENDOR_ID == Device.IdVendor )
> > > +            && ( PRODUCT_ID_178A == Device.IdProduct )) {
> > > +            *ppControllerName = L"AX88178A USB2.0 Gigabit Ethernet
> > Controller";
> > > +            Status = EFI_SUCCESS;
> > > +          } else {
> > > +            Status = EFI_UNSUPPORTED;
> > > +          }
> > > +
> > > +      }
> > > +
> > > +      gBS->CloseProtocol (
> > > +               ControllerHandle,
> > > +               &gEfiUsbIoProtocolGuid,
> > > +               gDriverBinding.DriverBindingHandle,
> > > +               ControllerHandle
> > > +               );
> > > +  }
> > > +  //
> > > +  // Return the operation status
> > > +  //
> > > +  if (Status != EFI_SUCCESS) {
> > > +    *ppControllerName = L"AX88179_178A Gigabit Ethernet Controller";
> > > +        Status = EFI_SUCCESS;
> > > +  }
> > > +  return Status;
> > > +}
> > > +
> > > +#endif
> > > diff --git
> > a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/DriverBinding.c
> > >
> > b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/DriverBinding.c
> > > new file mode 100644
> > > index 000000000000..826a539e3f34
> > > --- /dev/null
> > > +++
> > b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/DriverBinding.c
> > > @@ -0,0 +1,620 @@
> > > +/** @file
> > > +  Implement the driver binding protocol for Asix AX88179 Ethernet driver.
> > > +
> > > +  Copyright (c) 2011, Intel Corporation
> > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#include "Ax88179.h"
> > > +
> > > +/**
> > > +  Verify the controller type
> > > +
> > > +  @param [in] pThis                Protocol instance pointer.
> > > +  @param [in] Controller           Handle of device to test.
> > > +  @param [in] pRemainingDevicePath Not used.
> > > +
> > > +  @retval EFI_SUCCESS          This driver supports this device.
> > > +  @retval other                This driver does not support this device.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +DriverSupported (
> > > +  IN EFI_DRIVER_BINDING_PROTOCOL * pThis,
> > > +  IN EFI_HANDLE Controller,
> > > +  IN EFI_DEVICE_PATH_PROTOCOL * pRemainingDevicePath
> > > +  )
> > > +{
> > > +  EFI_USB_DEVICE_DESCRIPTOR Device;
> > > +  EFI_USB_IO_PROTOCOL * pUsbIo;
> > > +  EFI_STATUS Status;
> > > +
> > > +  //
> > > +  //  Connect to the USB stack
> > > +  //
> > > +  Status = gBS->OpenProtocol (
> > > +                  Controller,
> > > +                  &gEfiUsbIoProtocolGuid,
> > > +                  (VOID **) &pUsbIo,
> > > +                  pThis->DriverBindingHandle,
> > > +                  Controller,
> > > +                  EFI_OPEN_PROTOCOL_BY_DRIVER
> > > +                  );
> > > +  if (!EFI_ERROR ( Status )) {
> > > +
> > > +    //
> > > +    //  Get the interface descriptor to check the USB class and find a
> > transport
> > > +    //  protocol handler.
> > > +    //
> > > +    Status = pUsbIo->UsbGetDeviceDescriptor ( pUsbIo, &Device );
> > > +    if (EFI_ERROR(Status)) {
> > > +      Status = EFI_UNSUPPORTED;
> > > +    } else {
> > > +      //
> > > +      //  Validate the adapter
> > > +      //
> > > +      if (( VENDOR_ID == Device.IdVendor ) &&
> > > +          ( PRODUCT_ID == Device.IdProduct )) {
> > > +        Status = EFI_SUCCESS;
> > > +      } else if (( VENDOR_ID == Device.IdVendor ) &&
> > > +                 ( PRODUCT_ID_178A == Device.IdProduct )) {
> > > +        Status = EFI_SUCCESS;
> > > +      } else {
> > > +        Status = EFI_UNSUPPORTED;
> > > +      }
> > > +    }
> > > +    gBS->CloseProtocol (
> > > +           Controller,
> > > +           &gEfiUsbIoProtocolGuid,
> > > +           pThis->DriverBindingHandle,
> > > +           Controller
> > > +           );
> > > +  }
> > > +
> > > +  //
> > > +  //  Return the device supported status
> > > +  //
> > > +
> > > +  return Status;
> > > +}
> > > +
> > > +
> > > +/**
> > > +  Start this driver on Controller by opening UsbIo and DevicePath
> > protocols.
> > > +  Initialize PXE structures, create a copy of the Controller Device Path with
> > the
> > > +  NIC's MAC address appended to it, install the NetworkInterfaceIdentifier
> > protocol
> > > +  on the newly created Device Path.
> > > +
> > > +  @param [in] pThis                Protocol instance pointer.
> > > +  @param [in] Controller           Handle of device to work with.
> > > +  @param [in] pRemainingDevicePath Not used, always produce all
> > possible children.
> > > +
> > > +  @retval EFI_SUCCESS          This driver is added to Controller.
> > > +  @retval other                This driver does not support this device.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +DriverStart (
> > > +  IN EFI_DRIVER_BINDING_PROTOCOL * pThis,
> > > +  IN EFI_HANDLE Controller,
> > > +  IN EFI_DEVICE_PATH_PROTOCOL * pRemainingDevicePath
> > > +  )
> > > +{
> > > +  EFI_STATUS Status;
> > > +  NIC_DEVICE *pNicDevice;
> > > +  UINTN LengthInBytes;
> > > +  EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath = NULL;
> > > +  MAC_ADDR_DEVICE_PATH MacDeviceNode;
> > > +
> > > +  //
> > > +  //  Allocate the device structure
> > > +  //
> > > +  LengthInBytes = sizeof ( *pNicDevice );
> > > +  Status = gBS->AllocatePool (
> > > +                  EfiRuntimeServicesData,
> > > +                  LengthInBytes,
> > > +                  (VOID **) &pNicDevice
> > > +                  );
> > > +
> > > +  if (EFI_ERROR (Status)) {
> > > +    goto ERR;
> > > +  }
> > > +
> > > +  //
> > > +  //  Set the structure signature
> > > +  //
> > > +  ZeroMem ( pNicDevice, LengthInBytes );
> > > +  pNicDevice->Signature = DEV_SIGNATURE;
> > > +
> > > +  Status = gBS->OpenProtocol (
> > > +                    Controller,
> > > +                    &gEfiUsbIoProtocolGuid,
> > > +                    (VOID **) &pNicDevice->pUsbIo,
> > > +                    pThis->DriverBindingHandle,
> > > +                    Controller,
> > > +                    EFI_OPEN_PROTOCOL_BY_DRIVER
> > > +                    );
> > > +
> > > +  if (EFI_ERROR (Status)) {
> > > +    goto ERR;
> > > +  }
> > > +
> > > +  //
> > > +  //  Initialize the simple network protocol
> > > +  //
> > > +  Status = SN_Setup ( pNicDevice );
> > > +
> > > +  if (EFI_ERROR(Status)){
> > > +    gBS->CloseProtocol (
> > > +              Controller,
> > > +              &gEfiUsbIoProtocolGuid,
> > > +              pThis->DriverBindingHandle,
> > > +              Controller
> > > +              );
> > > +    goto ERR;
> > > +  }
> > > +  //
> > > +  // Set Device Path
> > > +  //
> > > +  Status = gBS->OpenProtocol (
> > > +                  Controller,
> > > +                  &gEfiDevicePathProtocolGuid,
> > > +                  (VOID **) &ParentDevicePath,
> > > +                  pThis->DriverBindingHandle,
> > > +                  Controller,
> > > +                  EFI_OPEN_PROTOCOL_BY_DRIVER
> > > +                  );
> > > +  if (EFI_ERROR(Status)) {
> > > +    gBS->CloseProtocol (
> > > +              Controller,
> > > +              &gEfiUsbIoProtocolGuid,
> > > +              pThis->DriverBindingHandle,
> > > +              Controller
> > > +              );
> > > +    goto ERR;
> > > +  }
> > > +
> > > +  ZeroMem (&MacDeviceNode, sizeof (MAC_ADDR_DEVICE_PATH));
> > > +  MacDeviceNode.Header.Type = MESSAGING_DEVICE_PATH;
> > > +  MacDeviceNode.Header.SubType = MSG_MAC_ADDR_DP;
> > > +
> > > +  SetDevicePathNodeLength (&MacDeviceNode.Header, sizeof
> > (MAC_ADDR_DEVICE_PATH));
> > > +
> > > +  CopyMem (&MacDeviceNode.MacAddress,
> > > +           &pNicDevice->SimpleNetworkData.CurrentAddress,
> > > +           PXE_HWADDR_LEN_ETHER);
> > > +
> > > +  MacDeviceNode.IfType = pNicDevice->SimpleNetworkData.IfType;
> > > +
> > > +  pNicDevice->MyDevPath = AppendDevicePathNode (
> > > +                                          ParentDevicePath,
> > > +                                          (EFI_DEVICE_PATH_PROTOCOL *)
> > &MacDeviceNode
> > > +                                          );
> > > +  pNicDevice->Controller = NULL;
> > > +
> > > +  //
> > > +  //  Install both the simple network and device path protocols.
> > > +  //
> > > +  Status = gBS->InstallMultipleProtocolInterfaces (
> > > +                          &pNicDevice->Controller,
> > > +                          &gEfiCallerIdGuid,
> > > +                          pNicDevice,
> > > +                          &gEfiSimpleNetworkProtocolGuid,
> > > +                          &pNicDevice->SimpleNetwork,
> > > +                          &gEfiDevicePathProtocolGuid,
> > > +                          pNicDevice->MyDevPath,
> > > +                          NULL
> > > +                          );
> > > +
> > > +  if (EFI_ERROR(Status)){
> > > +    gBS->CloseProtocol (
> > > +              Controller,
> > > +              &gEfiDevicePathProtocolGuid,
> > > +              pThis->DriverBindingHandle,
> > > +              Controller);
> > > +    gBS->CloseProtocol (
> > > +              Controller,
> > > +              &gEfiUsbIoProtocolGuid,
> > > +              pThis->DriverBindingHandle,
> > > +              Controller
> > > +              );
> > > +    goto ERR;
> > > +  }
> > > +
> > > +  //
> > > +  // Open For Child Device
> > > +  //
> > > +  Status = gBS->OpenProtocol (
> > > +                  Controller,
> > > +                  &gEfiUsbIoProtocolGuid,
> > > +                  (VOID **) &pNicDevice->pUsbIo,
> > > +                  pThis->DriverBindingHandle,
> > > +                  pNicDevice->Controller,
> > > +                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
> > > +                  );
> > > +
> > > +  if (EFI_ERROR(Status)){
> > > +    gBS->UninstallMultipleProtocolInterfaces (
> > > +                          &pNicDevice->Controller,
> > > +                          &gEfiCallerIdGuid,
> > > +                          pNicDevice,
> > > +                          &gEfiSimpleNetworkProtocolGuid,
> > > +                          &pNicDevice->SimpleNetwork,
> > > +                          &gEfiDevicePathProtocolGuid,
> > > +                          pNicDevice->MyDevPath,
> > > +                          NULL
> > > +                          );
> > > +    gBS->CloseProtocol (
> > > +              Controller,
> > > +              &gEfiDevicePathProtocolGuid,
> > > +              pThis->DriverBindingHandle,
> > > +              Controller);
> > > +    gBS->CloseProtocol (
> > > +              Controller,
> > > +              &gEfiUsbIoProtocolGuid,
> > > +              pThis->DriverBindingHandle,
> > > +              Controller
> > > +              );
> > > +    goto ERR;
> > > +  }
> > > +
> > > +  return Status;
> > > +
> > > +
> > > +ERR:
> > > +
> > > +  if ( NULL != pNicDevice->pBulkInbuf)
> > > +    gBS->FreePool (pNicDevice->pBulkInbuf);
> > > +  if ( NULL != pNicDevice->pTxTest)
> > > +    gBS->FreePool (pNicDevice->pTxTest);
> > > +  if ( NULL != pNicDevice->MyDevPath)
> > > +    gBS->FreePool (pNicDevice->MyDevPath);
> > > +  if (NULL != pNicDevice)
> > > +    gBS->FreePool ( pNicDevice );
> > > +  return Status;
> > > +
> > > +}
> > > +
> > > +/**
> > > +  Stop this driver on Controller by removing NetworkInterfaceIdentifier
> > protocol and
> > > +  closing the DevicePath and PciIo protocols on Controller.
> > > +
> > > +  @param [in] pThis                Protocol instance pointer.
> > > +  @param [in] Controller           Handle of device to stop driver on.
> > > +  @param [in] NumberOfChildren     How many children need to be
> > stopped.
> > > +  @param [in] pChildHandleBuffer   Not used.
> > > +
> > > +  @retval EFI_SUCCESS          This driver is removed Controller.
> > > +  @retval EFI_DEVICE_ERROR     The device could not be stopped due to a
> > device error.
> > > +  @retval other                This driver was not removed from this device.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +DriverStop (
> > > +  IN  EFI_DRIVER_BINDING_PROTOCOL * pThis,
> > > +  IN  EFI_HANDLE Controller,
> > > +  IN  UINTN NumberOfChildren,
> > > +  IN  EFI_HANDLE * ChildHandleBuffer
> > > +  )
> > > +{
> > > +  BOOLEAN AllChildrenStopped;
> > > +  EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork;
> > > +  EFI_STATUS Status = EFI_SUCCESS;
> > > +  NIC_DEVICE *pNicDevice;
> > > +  UINTN Index;
> > > +
> > > +  //
> > > +  // Complete all outstanding transactions to Controller.
> > > +  // Don't allow any new transaction to Controller to be started.
> > > +  //
> > > +  if (NumberOfChildren == 0) {
> > > +    Status = gBS->OpenProtocol (
> > > +                      Controller,
> > > +                      &gEfiSimpleNetworkProtocolGuid,
> > > +                      (VOID **) &SimpleNetwork,
> > > +                      pThis->DriverBindingHandle,
> > > +                      Controller,
> > > +                      EFI_OPEN_PROTOCOL_GET_PROTOCOL
> > > +                      );
> > > +
> > > +    if (EFI_ERROR(Status)) {
> > > +      //
> > > +      // This is a 2nd type handle(multi-lun root), it needs to close
> > devicepath
> > > +      // and usbio protocol.
> > > +      //
> > > +      gBS->CloseProtocol (
> > > +                Controller,
> > > +                &gEfiDevicePathProtocolGuid,
> > > +                pThis->DriverBindingHandle,
> > > +                Controller
> > > +                );
> > > +      gBS->CloseProtocol (
> > > +                Controller,
> > > +                &gEfiUsbIoProtocolGuid,
> > > +                pThis->DriverBindingHandle,
> > > +                Controller
> > > +                );
> > > +      return EFI_SUCCESS;
> > > +    }
> > > +
> > > +    pNicDevice = DEV_FROM_SIMPLE_NETWORK ( SimpleNetwork );
> > > +
> > > +    Status = gBS->UninstallMultipleProtocolInterfaces (
> > > +                          Controller,
> > > +                          &gEfiCallerIdGuid,
> > > +                          pNicDevice,
> > > +                          &gEfiSimpleNetworkProtocolGuid,
> > > +                          &pNicDevice->SimpleNetwork,
> > > +                          &gEfiDevicePathProtocolGuid,
> > > +                          pNicDevice->MyDevPath,
> > > +                          NULL
> > > +                          );
> > > +
> > > +    if (EFI_ERROR (Status)) {
> > > +      return Status;
> > > +    }
> > > +    //
> > > +    // Close the bus driver
> > > +    //
> > > +    Status = gBS->CloseProtocol (
> > > +                        Controller,
> > > +                        &gEfiDevicePathProtocolGuid,
> > > +                        pThis->DriverBindingHandle,
> > > +                        Controller
> > > +                        );
> > > +
> > > +    Status = gBS->CloseProtocol (
> > > +                        Controller,
> > > +                        &gEfiUsbIoProtocolGuid,
> > > +                        pThis->DriverBindingHandle,
> > > +                        Controller
> > > +                        );
> > > +    return EFI_SUCCESS;
> > > +  }
> > > +
> > > +  AllChildrenStopped = TRUE;
> > > +
> > > +  for (Index = 0; Index < NumberOfChildren; Index++) {
> > > +    Status = gBS->OpenProtocol (
> > > +                      ChildHandleBuffer[Index],
> > > +                      &gEfiSimpleNetworkProtocolGuid,
> > > +                      (VOID **) &SimpleNetwork,
> > > +                      pThis->DriverBindingHandle,
> > > +                      Controller,
> > > +                      EFI_OPEN_PROTOCOL_GET_PROTOCOL
> > > +                      );
> > > +
> > > +    if (EFI_ERROR (Status)) {
> > > +      AllChildrenStopped = FALSE;
> > > +      continue;
> > > +    }
> > > +
> > > +    pNicDevice = DEV_FROM_SIMPLE_NETWORK ( SimpleNetwork );
> > > +
> > > +    gBS->CloseProtocol (
> > > +              Controller,
> > > +              &gEfiUsbIoProtocolGuid,
> > > +              pThis->DriverBindingHandle,
> > > +              ChildHandleBuffer[Index]
> > > +              );
> > > +
> > > +    Status = gBS->UninstallMultipleProtocolInterfaces (
> > > +                          ChildHandleBuffer[Index],
> > > +                          &gEfiCallerIdGuid,
> > > +                          pNicDevice,
> > > +                          &gEfiSimpleNetworkProtocolGuid,
> > > +                          &pNicDevice->SimpleNetwork,
> > > +                          &gEfiDevicePathProtocolGuid,
> > > +                          pNicDevice->MyDevPath,
> > > +                          NULL
> > > +                          );
> > > +
> > > +    if (EFI_ERROR (Status)) {
> > > +      Status = gBS->OpenProtocol (
> > > +                        Controller,
> > > +                        &gEfiUsbIoProtocolGuid,
> > > +                        (VOID **) &pNicDevice->pUsbIo,
> > > +                        pThis->DriverBindingHandle,
> > > +                        ChildHandleBuffer[Index],
> > > +                        EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
> > > +                        );
> > > +    } else {
> > > +      if ( NULL != pNicDevice->pBulkInbuf)
> > > +        gBS->FreePool (pNicDevice->pBulkInbuf);
> > > +      if ( NULL != pNicDevice->pTxTest)
> > > +        gBS->FreePool (pNicDevice->pTxTest);
> > > +      if ( NULL != pNicDevice->MyDevPath)
> > > +        gBS->FreePool (pNicDevice->MyDevPath);
> > > +      if ( NULL != pNicDevice)
> > > +        gBS->FreePool (pNicDevice);
> > > +    }
> > > +  }
> > > +
> > > +  if (!AllChildrenStopped) {
> > > +    return EFI_DEVICE_ERROR;
> > > +  }
> > > +
> > > +  return EFI_SUCCESS;
> > > +}
> > > +
> > > +
> > > +/**
> > > +  Driver binding protocol declaration
> > > +**/
> > > +EFI_DRIVER_BINDING_PROTOCOL  gDriverBinding = {
> > > +  DriverSupported,
> > > +  DriverStart,
> > > +  DriverStop,
> > > +  0xa,
> > > +  NULL,
> > > +  NULL
> > > +};
> > > +
> > > +
> > > +/**
> > > +  Ax88179 driver unload routine.
> > > +
> > > +  @param [in] ImageHandle       Handle for the image.
> > > +
> > > +  @retval EFI_SUCCESS           Image may be unloaded
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +DriverUnload (
> > > +  IN EFI_HANDLE ImageHandle
> > > +  )
> > > +{
> > > +  UINTN BufferSize;
> > > +  UINTN Index;
> > > +  UINTN Max;
> > > +  EFI_HANDLE * pHandle;
> > > +  EFI_STATUS Status;
> > > +
> > > +  //
> > > +  //  Determine which devices are using this driver
> > > +  //
> > > +  BufferSize = 0;
> > > +  pHandle = NULL;
> > > +  Status = gBS->LocateHandle (
> > > +                  ByProtocol,
> > > +                  &gEfiCallerIdGuid,
> > > +                  NULL,
> > > +                  &BufferSize,
> > > +                  NULL );
> > > +  if ( EFI_BUFFER_TOO_SMALL == Status ) {
> > > +    for ( ; ; ) {
> > > +      //
> > > +      //  One or more block IO devices are present
> > > +      //
> > > +      Status = gBS->AllocatePool (
> > > +                      EfiRuntimeServicesData,
> > > +                      BufferSize,
> > > +                      (VOID **) &pHandle
> > > +                      );
> > > +      if ( EFI_ERROR ( Status )) {
> > > +        break;
> > > +      }
> > > +
> > > +      //
> > > +      //  Locate the block IO devices
> > > +      //
> > > +      Status = gBS->LocateHandle (
> > > +                      ByProtocol,
> > > +                      &gEfiCallerIdGuid,
> > > +                      NULL,
> > > +                      &BufferSize,
> > > +                      pHandle );
> > > +      if ( EFI_ERROR ( Status )) {
> > > +        //
> > > +        //  Error getting handles
> > > +        //
> > > +
> > > +        break;
> > > +      }
> > > +
> > > +      //
> > > +      //  Remove any use of the driver
> > > +      //
> > > +      Max = BufferSize / sizeof ( pHandle[ 0 ]);
> > > +      for ( Index = 0; Max > Index; Index++ ) {
> > > +        Status = DriverStop ( &gDriverBinding,
> > > +                              pHandle[ Index ],
> > > +                              0,
> > > +                              NULL );
> > > +        if ( EFI_ERROR ( Status )) {
> > > +          break;
> > > +        }
> > > +      }
> > > +      break;
> > > +    }
> > > +  } else {
> > > +    if ( EFI_NOT_FOUND == Status ) {
> > > +      //
> > > +      //  No devices were found
> > > +      //
> > > +      Status = EFI_SUCCESS;
> > > +    }
> > > +  }
> > > +
> > > +  //
> > > +  //  Free the handle array
> > > +  //
> > > +  if ( NULL != pHandle ) {
> > > +    gBS->FreePool ( pHandle );
> > > +  }
> > > +
> > > +  //
> > > +  //  Remove the protocols installed by the EntryPoint routine.
> > > +  //
> > > +  if ( !EFI_ERROR ( Status )) {
> > > +    gBS->UninstallMultipleProtocolInterfaces (
> > > +            ImageHandle,
> > > +            &gEfiDriverBindingProtocolGuid,
> > > +            &gDriverBinding,
> > > +            &gEfiComponentNameProtocolGuid,
> > > +            &gComponentName,
> > > +            &gEfiComponentName2ProtocolGuid,
> > > +            &gComponentName2,
> > > +            NULL
> > > +            );
> > > +  }
> > > +
> > > +  //
> > > +  //  Return the unload status
> > > +  //
> > > +
> > > +  return Status;
> > > +}
> > > +
> > > +
> > > +/**
> > > +Ax88179 driver entry point.
> > > +
> > > + at param [in] ImageHandle       Handle for the image.
> > > + at param [in] pSystemTable      Address of the system table.
> > > +
> > > + at retval EFI_SUCCESS           Image successfully loaded.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +EntryPoint (
> > > +  IN EFI_HANDLE ImageHandle,
> > > +  IN EFI_SYSTEM_TABLE * pSystemTable
> > > +  )
> > > +{
> > > +  EFI_LOADED_IMAGE_PROTOCOL * pLoadedImage;
> > > +  EFI_STATUS    Status;
> > > +
> > > +
> > > +  //
> > > +  //  Enable unload support
> > > +  //
> > > +  Status = gBS->HandleProtocol (
> > > +                  gImageHandle,
> > > +                  &gEfiLoadedImageProtocolGuid,
> > > +                  (VOID **)&pLoadedImage
> > > +                  );
> > > +  if (!EFI_ERROR (Status)) {
> > > +    pLoadedImage->Unload = DriverUnload;
> > > +  }
> > > +
> > > +  //
> > > +  //  Add the driver to the list of drivers
> > > +  //
> > > +  Status = EfiLibInstallDriverBindingComponentName2 (
> > > +             ImageHandle,
> > > +             pSystemTable,
> > > +             &gDriverBinding,
> > > +             ImageHandle,
> > > +             &gComponentName,
> > > +             &gComponentName2
> > > +             );
> > > +
> > > +  return Status;
> > > +}
> > > diff --git
> > a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/SimpleNetwork
> > .c
> > >
> > b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/SimpleNetwork
> > .c
> > > new file mode 100644
> > > index 000000000000..25986451dcbc
> > > --- /dev/null
> > > +++
> > b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/SimpleNetwork
> > .c
> > > @@ -0,0 +1,1585 @@
> > > +/** @file
> > > +  Provides the Simple Network functions.
> > > +
> > > +  Copyright (c) 2011, Intel Corporation
> > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +#include "Ax88179.h"
> > > +
> > > +/**
> > > +  This function updates the filtering on the receiver.
> > > +
> > > +  This support routine calls ::Ax88179MacAddressSet to update
> > > +  the MAC address.  This routine then rebuilds the multicast
> > > +  hash by calling ::Ax88179MulticastClear and ::Ax88179MulticastSet.
> > > +  Finally this routine enables the receiver by calling
> > > +  ::Ax88179RxControl.
> > > +  @param [in] pSimpleNetwork    Simple network mode pointer
> > > +
> > > +  @retval EFI_SUCCESS           This operation was successful.
> > > +  @retval EFI_NOT_STARTED       The network interface was not started.
> > > +  @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was
> > NULL or did not point to a valid
> > > +                                EFI_SIMPLE_NETWORK_PROTOCOL structure.
> > > +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> > network interface.
> > > +  @retval EFI_UNSUPPORTED       The increased buffer size feature is not
> > supported.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +ReceiveFilterUpdate (
> > > +  IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork
> > > +  )
> > > +{
> > > +  EFI_SIMPLE_NETWORK_MODE * pMode;
> > > +  NIC_DEVICE * pNicDevice;
> > > +  EFI_STATUS Status;
> > > +  UINT32 Index;
> > > +
> > > +  //
> > > +  // Set the MAC address
> > > +  //
> > > +  pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
> > > +  pMode = pSimpleNetwork->Mode;
> > > +  //
> > > +  // Clear the multicast hash table
> > > +  //
> > > +  Ax88179MulticastClear ( pNicDevice );
> > > +
> > > +  //
> > > +  // Load the multicast hash table
> > > +  //
> > > +  if ( 0 != ( pMode->ReceiveFilterSetting &
> > EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST )) {
> > > +    for ( Index = 0; Index < pMode->MCastFilterCount; Index++ ) {
> > > +      //
> > > +      // Enable the next multicast address
> > > +      //
> > > +      Ax88179MulticastSet ( pNicDevice,
> > > +                            &pMode->MCastFilter[ Index ].Addr[0]);
> > > +    }
> > > +  }
> > > +
> > > +  //
> > > +  // Enable the receiver
> > > +  //
> > > +  Status = Ax88179RxControl ( pNicDevice, pMode->ReceiveFilterSetting );
> > > +
> > > +  return Status;
> > > +}
> > > +
> > > +
> > > +/**
> > > +  This function updates the SNP driver status.
> > > +
> > > +  This function gets the current interrupt and recycled transmit
> > > +  buffer status from the network interface.  The interrupt status
> > > +  and the media status are returned as a bit mask in InterruptStatus.
> > > +  If InterruptStatus is NULL, the interrupt status will not be read.
> > > +  Upon successful return of the media status, the MediaPresent field
> > > +  of EFI_SIMPLE_NETWORK_MODE will be updated to reflect any change
> > > +  of media status.  If TxBuf is not NULL, a recycled transmit buffer
> > > +  address will be retrived.  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.
> > > +
> > > +  This function calls ::Ax88179Rx to update the media status and
> > > +  queue any receive packets.
> > > +
> > > +  @param [in] pSimpleNetwork    Protocol instance pointer
> > > +  @param [in] pInterruptStatus  A pointer to the bit mask of the current
> > active interrupts.
> > > +                                If this is NULL, the interrupt status will not be read from
> > > +                                the device.  If this is not NULL, the interrupt status will
> > > +                                be read from teh 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 [out] ppTxBuf          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 not transmit buffers to
> > recycle
> > > +                                and TxBuf is not NULL, *TxBuf will be set to NULL.
> > > +
> > > +  @retval EFI_SUCCESS           This operation was successful.
> > > +  @retval EFI_NOT_STARTED       The network interface was not started.
> > > +  @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was
> > NULL or did not point to a valid
> > > +                                EFI_SIMPLE_NETWORK_PROTOCOL structure.
> > > +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> > network interface.
> > > +
> > > +**/
> > > +
> > > +EFI_STATUS
> > > +EFIAPI
> > > +SN_GetStatus (
> > > +  IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
> > > +  OUT UINT32 * pInterruptStatus,
> > > +  OUT VOID ** ppTxBuf
> > > +  )
> > > +{
> > > +  EFI_SIMPLE_NETWORK_MODE * pMode;
> > > +  NIC_DEVICE * pNicDevice;
> > > +  EFI_STATUS Status = EFI_SUCCESS;
> > > +  EFI_TPL TplPrevious;
> > > +
> > > +  TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
> > > +  //
> > > +  // Verify the parameters
> > > +  //
> > > +  if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
> > > +    //
> > > +    // Return the transmit buffer
> > > +    //
> > > +    pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
> > > +
> > > +    if (( NULL != ppTxBuf ) && ( NULL != pNicDevice->pTxBuffer )) {
> > > +      *ppTxBuf = pNicDevice->pTxBuffer;
> > > +      pNicDevice->pTxBuffer = NULL;
> > > +    }
> > > +
> > > +    pMode = pSimpleNetwork->Mode;
> > > +    if (EfiSimpleNetworkInitialized == pMode->State) {
> > > +      if (NULL == ppTxBuf && NULL == pInterruptStatus) {
> > > +        Status = EFI_INVALID_PARAMETER;
> > > +        goto EXIT;
> > > +      }
> > > +#if REPORTLINK
> > > +#else
> > > +      if (!pNicDevice->bLinkUp || !pNicDevice->bComplete) {
> > > +#endif
> > > +        Status = Ax88179NegotiateLinkComplete ( pNicDevice,
> > > +                                                &pNicDevice->PollCount,
> > > +                                                &pNicDevice->bComplete,
> > > +                                                &pNicDevice->bLinkUp,
> > > +                                                &pNicDevice->b100Mbps,
> > > +                                                &pNicDevice->b1000Mbps,
> > > +                                                &pNicDevice->bFullDuplex );
> > > +
> > > +        if (EFI_ERROR(Status))
> > > +          goto EXIT;
> > > +#if REPORTLINK
> > > +        if (pNicDevice->bLinkUp && pNicDevice->bComplete) {
> > > +          pMode->MediaPresent = TRUE;
> > > +          Status = Ax88179SetMedium (pNicDevice);
> > > +        } else {
> > > +          pMode->MediaPresent = FALSE;
> > > +        }
> > > +#else
> > > +        if (pNicDevice->bLinkUp && pNicDevice->bComplete) {
> > > +          pMode->MediaPresent = TRUE;
> > > +          pMode->MediaPresentSupported = FALSE;
> > > +          Status = Ax88179SetMedium (pNicDevice);
> > > +
> > > +        }
> > > +      }
> > > +#endif
> > > +    } else {
> > > +      if (EfiSimpleNetworkStarted == pMode->State) {
> > > +        Status = EFI_DEVICE_ERROR; ;
> > > +      } else {
> > > +        Status = EFI_NOT_STARTED ;
> > > +      }
> > > +    }
> > > +  } else {
> > > +    Status = EFI_INVALID_PARAMETER;
> > > +  }
> > > +  if ( NULL != pInterruptStatus ) {
> > > +    *pInterruptStatus = 0;
> > > +  }
> > > +
> > > +EXIT:
> > > +  gBS->RestoreTPL(TplPrevious) ;
> > > +
> > > +  return Status;
> > > +}
> > > +
> > > +/**
> > > +  This function performs read and write operations on the NVRAM device
> > > +  attached to a network interface.
> > > +
> > > +  @param [in] pSimpleNetwork    Protocol instance pointer
> > > +  @param [in] ReadWrite         TRUE for read operations, FALSE for write
> > operations.
> > > +  @param [in] Offset            Byte offset in the NVRAM device at which to
> > start the
> > > +                                read or write operation.  This must be a multiple of
> > > +                                NvRamAccessSize and less than NvRamSize.
> > > +  @param [in] BufferSize        The number of bytes to read or write from
> > the NVRAM device.
> > > +                                This must also be a multiple of NvramAccessSize.
> > > +  @param [in, out] pBuffer      A pointer to the data buffer.
> > > +
> > > +  @retval EFI_SUCCESS           This operation was successful.
> > > +  @retval EFI_NOT_STARTED       The network interface was not started.
> > > +  @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was
> > NULL or did not point to a valid
> > > +                                EFI_SIMPLE_NETWORK_PROTOCOL structure.
> > > +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> > network interface.
> > > +  @retval EFI_UNSUPPORTED       The increased buffer size feature is not
> > supported.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +SN_NvData (
> > > +  IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
> > > +  IN BOOLEAN ReadWrite,
> > > +  IN UINTN Offset,
> > > +  IN UINTN BufferSize,
> > > +  IN OUT VOID * pBuffer
> > > +  )
> > > +{
> > > +  EFI_STATUS Status = EFI_INVALID_PARAMETER;
> > > +  EFI_TPL TplPrevious;
> > > +  EFI_SIMPLE_NETWORK_MODE * pMode;
> > > +  NIC_DEVICE * pNicDevice;
> > > +
> > > +  TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
> > > +
> > > +  if (( NULL == pSimpleNetwork ) || ( NULL == pSimpleNetwork->Mode )) {
> > > +    Status = EFI_INVALID_PARAMETER;
> > > +    goto  EXIT;
> > > +  }
> > > +
> > > +  pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
> > > +  pMode = pSimpleNetwork->Mode;
> > > +
> > > +#if PASS_SCT
> > > +  if (EfiSimpleNetworkInitialized != pMode->State) {
> > > +    Status = EFI_NOT_STARTED;
> > > +    goto  EXIT;
> > > +  }
> > > +#endif
> > > +
> > > +  if ( 0 != Offset ) {
> > > +    if ((0 != (Offset % pMode->NvRamAccessSize) ) || (Offset >= pMode-
> > >NvRamSize)) {
> > > +      Status = EFI_INVALID_PARAMETER;
> > > +      goto  EXIT;
> > > +    }
> > > +  }
> > > +  //
> > > +  //Offset must be a multiple of NvRamAccessSize and less than
> > NvRamSize.
> > > +  //
> > > +  if (0 != (BufferSize % pMode->NvRamAccessSize)) {
> > > +    Status = EFI_INVALID_PARAMETER;
> > > +    goto  EXIT;
> > > +  }
> > > +
> > > +  if (BufferSize + Offset > pMode->NvRamSize) {
> > > +    Status = EFI_INVALID_PARAMETER;
> > > +    goto  EXIT;
> > > +  }
> > > +
> > > +  if (NULL == pBuffer) {
> > > +    Status = EFI_INVALID_PARAMETER;
> > > +    goto  EXIT;
> > > +  }
> > > +
> > > +  //
> > > +  //ReadWrite: TRUE FOR READ FALSE FOR WRITE
> > > +  //
> > > +  if (ReadWrite){
> > > +    UINTN i;
> > > +
> > > +    for (i = 0; i < BufferSize / 2 ; i++) {
> > > +      Status = Ax88179SromRead ( pNicDevice,
> > > +                                 (UINT32)(Offset/2 + i),
> > > +                                 (((UINT16*)pBuffer) + i));
> > > +    }
> > > +  } else {
> > > +    UINTN i;
> > > +
> > > +    Status = Ax88179EnableSromWrite(pNicDevice);
> > > +    if (EFI_ERROR(Status)) goto EXIT;
> > > +
> > > +    for (i = 0; i < BufferSize / 2 ; i++){
> > > +      Status = Ax88179SromWrite ( pNicDevice,
> > > +                                  (UINT32)(Offset/2 + i),
> > > +                                  (((UINT16*)pBuffer) + i));
> > > +    }
> > > +    Status = Ax88179DisableSromWrite(pNicDevice);
> > > +
> > > +    if (BufferSize == 272)
> > > +      Status = Ax88179ReloadSrom(pNicDevice);
> > > +  }
> > > +
> > > +  //
> > > +  // Return the operation status
> > > +  //
> > > +EXIT:
> > > +  gBS->RestoreTPL (TplPrevious);
> > > +  return Status;
> > > +}
> > > +
> > > +/**
> > > +  Resets the 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 routine must be called
> > before
> > > +  any other routine in the Simple Network protocol is called.
> > > +
> > > +  @param [in] pSimpleNetwork    Protocol instance pointer
> > > +  @param [in] ExtraRxBufferSize Size in bytes to add to the receive buffer
> > allocation
> > > +  @param [in] ExtraTxBufferSize Size in bytes to add to the transmit buffer
> > allocation
> > > +
> > > +  @retval EFI_SUCCESS           This operation was successful.
> > > +  @retval EFI_NOT_STARTED       The network interface was not started.
> > > +  @retval EFI_OUT_OF_RESOURCES  There was not enough memory for
> > the transmit and receive buffers
> > > +  @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was
> > NULL or did not point to a valid
> > > +                                EFI_SIMPLE_NETWORK_PROTOCOL structure.
> > > +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> > network interface.
> > > +  @retval EFI_UNSUPPORTED       The increased buffer size feature is not
> > supported.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +SN_Initialize (
> > > +  IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
> > > +  IN UINTN ExtraRxBufferSize,
> > > +  IN UINTN ExtraTxBufferSize
> > > +  )
> > > +{
> > > +  EFI_SIMPLE_NETWORK_MODE * pMode;
> > > +  EFI_STATUS Status;
> > > +  UINT32  TmpState;
> > > +  EFI_TPL TplPrevious;
> > > +  NIC_DEVICE * pNicDevice;
> > > +  TplPrevious = gBS->RaiseTPL (TPL_CALLBACK);
> > > +
> > > +  //
> > > +  // Verify the parameters
> > > +  //
> > > +  if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
> > > +    //
> > > +    // Determine if the interface is already started
> > > +    //
> > > +    pMode = pSimpleNetwork->Mode;
> > > +    if ( EfiSimpleNetworkStarted == pMode->State ) {
> > > +      if (( 0 == ExtraRxBufferSize ) && ( 0 == ExtraTxBufferSize )) {
> > > +        //
> > > +        // Start the adapter
> > > +        //
> > > +        TmpState = pMode->State;
> > > +        pMode->State = EfiSimpleNetworkInitialized;
> > > +        Status = SN_Reset ( pSimpleNetwork, FALSE );
> > > +        if ( EFI_ERROR ( Status )) {
> > > +          //
> > > +          // Update the network state
> > > +          //
> > > +          pMode->State = TmpState;
> > > +        } else {
> > > +          pMode->MediaPresentSupported = TRUE;
> > > +          pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
> > > +          pMode->MediaPresent = Ax88179GetLinkStatus (pNicDevice);
> > > +        }
> > > +      } else {
> > > +        Status = EFI_UNSUPPORTED;
> > > +      }
> > > +    } else {
> > > +      Status = EFI_NOT_STARTED;
> > > +    }
> > > +  } else {
> > > +    Status = EFI_INVALID_PARAMETER;
> > > +  }
> > > +  //
> > > +  // Return the operation status
> > > +  //
> > > +  gBS->RestoreTPL (TplPrevious);
> > > +
> > > +  return Status;
> > > +}
> > > +
> > > +
> > > +/**
> > > +  This function converts a multicast IP address to a multicast HW MAC
> > address
> > > +  for all packet transactions.
> > > +
> > > +  @param [in] pSimpleNetwork    Protocol instance pointer
> > > +  @param [in] bIPv6             Set to TRUE if the multicast IP address is IPv6
> > [RFC2460].
> > > +                                Set to FALSE if the multicast IP address is IPv4 [RFC 791].
> > > +  @param [in] pIP               The multicast IP address that is to be converted
> > to a
> > > +                                multicast HW MAC address.
> > > +  @param [in] pMAC              The multicast HW MAC address that is to be
> > generated from IP.
> > > +
> > > +  @retval EFI_SUCCESS           This operation was successful.
> > > +  @retval EFI_NOT_STARTED       The network interface was not started.
> > > +  @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was
> > NULL or did not point to a valid
> > > +                                EFI_SIMPLE_NETWORK_PROTOCOL structure.
> > > +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> > network interface.
> > > +  @retval EFI_UNSUPPORTED       The increased buffer size feature is not
> > supported.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +SN_MCastIPtoMAC (
> > > +  IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
> > > +  IN BOOLEAN bIPv6,
> > > +  IN EFI_IP_ADDRESS * pIP,
> > > +  IN EFI_MAC_ADDRESS * pMAC
> > > +  )
> > > +{
> > > +  EFI_STATUS Status;
> > > +  EFI_TPL TplPrevious;
> > > +  EFI_SIMPLE_NETWORK_MODE * pMode;
> > > +
> > > +  TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
> > > +
> > > +  if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
> > > +    //
> > > +    // The interface must be running
> > > +    //
> > > +    pMode = pSimpleNetwork->Mode;
> > > +    if ( EfiSimpleNetworkInitialized == pMode->State ) {
> > > +      if (pIP == NULL || pMAC == NULL) {
> > > +        Status = EFI_INVALID_PARAMETER;
> > > +        goto EXIT;
> > > +      }
> > > +      if (bIPv6){
> > > +        Status = EFI_UNSUPPORTED;
> > > +        goto EXIT;
> > > +      } else {
> > > +        //
> > > +        // check if the ip given is a mcast IP
> > > +        //
> > > +        if ((pIP->v4.Addr[0] & 0xF0) != 0xE0) {
> > > +          Status = EFI_INVALID_PARAMETER;
> > > +          goto EXIT;
> > > +        } else {
> > > +          pMAC->Addr[0] = 0x01;
> > > +          pMAC->Addr[1] = 0x00;
> > > +          pMAC->Addr[2] = 0x5e;
> > > +          pMAC->Addr[3] = (UINT8) (pIP->v4.Addr[1] & 0x7f);
> > > +          pMAC->Addr[4] = (UINT8) pIP->v4.Addr[2];
> > > +          pMAC->Addr[5] = (UINT8) pIP->v4.Addr[3];
> > > +          Status = EFI_SUCCESS;
> > > +        }
> > > +      }
> > > +    } else {
> > > +      if (EfiSimpleNetworkStarted == pMode->State) {
> > > +        Status = EFI_DEVICE_ERROR; ;
> > > +      } else {
> > > +        Status = EFI_NOT_STARTED ;
> > > +      }
> > > +    }
> > > +  } else {
> > > +    Status = EFI_INVALID_PARAMETER;
> > > +  }
> > > +
> > > +EXIT:
> > > +  gBS->RestoreTPL(TplPrevious);
> > > +  return Status;
> > > +}
> > > +
> > > +/**
> > > +  Attempt to receive a packet from the network adapter.
> > > +
> > > +  This function retrieves one packet from the receive queue of the
> > 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 udpated 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.  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.
> > > +
> > > +  This routine calls ::Ax88179Rx to update the media status and
> > > +  empty the network adapter of receive packets.
> > > +
> > > +  @param [in] pSimpleNetwork    Protocol instance pointer
> > > +  @param [out] pHeaderSize      The size, in bytes, of the media header to
> > be filled in by
> > > +                                the Transmit() function.  If HeaderSize is non-zero, then
> > > +                                it must be equal to SimpleNetwork->Mode-
> > >MediaHeaderSize
> > > +                                and DestAddr and Protocol parameters must not be
> > NULL.
> > > +  @param [out] pBufferSize      The size, in bytes, of the entire packet
> > (media header and
> > > +                                data) to be transmitted through the network interface.
> > > +  @param [out] pBuffer          A pointer to the packet (media header
> > followed by data) to
> > > +                                to be transmitted.  This parameter can not be NULL.  If
> > > +                                HeaderSize is zero, then the media header is 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 [out] pSrcAddr         The source HW MAC address.  If HeaderSize
> > is zero, then
> > > +                                this parameter is ignored.  If HeaderSize is nonzero and
> > > +                                SrcAddr is NULL, then SimpleNetwork->Mode-
> > >CurrentAddress
> > > +                                is used for the source HW MAC address.
> > > +  @param [out] pDestAddr        The destination HW MAC address.  If
> > HeaderSize is zero, then
> > > +                                this parameter is ignored.
> > > +  @param [out] pProtocol        The type of header to build.  If HeaderSize is
> > zero, then
> > > +                                this parameter is ignored.
> > > +
> > > +  @retval EFI_SUCCESS           This operation was successful.
> > > +  @retval EFI_NOT_STARTED       The network interface was not started.
> > > +  @retval EFI_NOT_READY         No packets have been received on the
> > network interface.
> > > +  @retval EFI_BUFFER_TOO_SMALL  The packet is larger than BufferSize
> > bytes.
> > > +  @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was
> > NULL or did not point to a valid
> > > +                                EFI_SIMPLE_NETWORK_PROTOCOL structure.
> > > +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> > network interface.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +SN_Receive (
> > > +  IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
> > > +  OUT UINTN                      * pHeaderSize,
> > > +  OUT UINTN                      * pBufferSize,
> > > +  OUT VOID                       * pBuffer,
> > > +  OUT EFI_MAC_ADDRESS            * pSrcAddr,
> > > +  OUT EFI_MAC_ADDRESS            * pDestAddr,
> > > +  OUT UINT16                     * pProtocol
> > > +  )
> > > +{
> > > +  ETHERNET_HEADER * pHeader;
> > > +  EFI_SIMPLE_NETWORK_MODE * pMode;
> > > +  NIC_DEVICE * pNicDevice;
> > > +  EFI_STATUS Status;
> > > +  UINT16 Type = 0;
> > > +  UINT16  CurrentPktLen;
> > > +  BOOLEAN bValid = TRUE;
> > > +  EFI_TPL TplPrevious;
> > > +  TplPrevious = gBS->RaiseTPL (TPL_CALLBACK);
> > > +  //
> > > +  // Verify the parameters
> > > +  //
> > > +  if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
> > > +    //
> > > +    // The interface must be running
> > > +    //
> > > +    pMode = pSimpleNetwork->Mode;
> > > +    if ( EfiSimpleNetworkInitialized == pMode->State ) {
> > > +      if ((pBufferSize == NULL) || (pBuffer == NULL)) {
> > > +        Status = EFI_INVALID_PARAMETER;
> > > +        gBS->RestoreTPL (TplPrevious);
> > > +        return Status;
> > > +      }
> > > +      //
> > > +      // Update the link status
> > > +      //
> > > +      pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
> > > +      if ( pNicDevice->bLinkUp && pNicDevice->bComplete) {
> > > +        if ((NULL != pHeaderSize) && (7720 == *pHeaderSize)) {
> > > +          pNicDevice->Grub_f = TRUE;
> > > +        }
> > > +
> > > +        if ((pNicDevice->Grub_f) && (7720 != *pHeaderSize)) {
> > > +          gBS->RestoreTPL (TplPrevious);
> > > +          return EFI_NOT_READY;
> > > +        }
> > > +        //
> > > +        //  Attempt to do bulk in
> > > +        //
> > > +        if (0 == pNicDevice->PktCnt) {
> > > +          Status = Ax88179BulkIn(pNicDevice);
> > > +          if (EFI_ERROR(Status))
> > > +            goto  no_pkt;
> > > +        }
> > > +        CurrentPktLen = *((UINT16*) (pNicDevice->pCurPktHdrOff + 2));
> > > +        if (CurrentPktLen & (RXHDR_DROP | RXHDR_CRCERR))
> > > +          bValid = FALSE;
> > > +        CurrentPktLen &=  0x1fff;
> > > +        CurrentPktLen -= 2; /*EEEE*/
> > > +
> > > +        if (bValid && ( 60 <= CurrentPktLen ) &&
> > > +        ((CurrentPktLen - 14) <= MAX_ETHERNET_PKT_SIZE) &&
> > > +            (*((UINT16*)pNicDevice->pCurPktOff)) == 0xEEEE) {
> > > +          if (*pBufferSize < (UINTN)CurrentPktLen) {
> > > +            gBS->RestoreTPL (TplPrevious);
> > > +            return EFI_BUFFER_TOO_SMALL;
> > > +          }
> > > +          *pBufferSize = CurrentPktLen;
> > > +          CopyMem ( pBuffer, pNicDevice->pCurPktOff + 2, CurrentPktLen );
> > > +
> > > +          pHeader = (ETHERNET_HEADER *) pNicDevice->pCurPktOff + 2;
> > > +
> > > +          if ( NULL != pHeaderSize  && (7720 != *pHeaderSize)) {
> > > +            *pHeaderSize = sizeof ( *pHeader );
> > > +          }
> > > +
> > > +          if ( NULL != pDestAddr ) {
> > > +            CopyMem ( pDestAddr, &pHeader->dest_addr,
> > PXE_HWADDR_LEN_ETHER );
> > > +          }
> > > +          if ( NULL != pSrcAddr ) {
> > > +            CopyMem ( pSrcAddr, &pHeader->src_addr,
> > PXE_HWADDR_LEN_ETHER );
> > > +          }
> > > +          if ( NULL != pProtocol ) {
> > > +            Type = pHeader->type;
> > > +            Type = (UINT16)(( Type >> 8 ) | ( Type << 8 ));
> > > +            *pProtocol = Type;
> > > +          }
> > > +          pNicDevice->PktCnt--;
> > > +          pNicDevice->pCurPktHdrOff += 4;
> > > +          pNicDevice->pCurPktOff += (CurrentPktLen + 2 + 7) & 0xfff8;
> > > +          Status = EFI_SUCCESS;
> > > +        } else {
> > > +          pNicDevice->PktCnt = 0;
> > > +          Status = EFI_NOT_READY;
> > > +        }
> > > +      } else {
> > > +        Status = EFI_NOT_READY;
> > > +      }
> > > +    } else {
> > > +      if (EfiSimpleNetworkStarted == pMode->State) {
> > > +        Status = EFI_DEVICE_ERROR;
> > > +      } else {
> > > +        Status = EFI_NOT_STARTED ;
> > > +      }
> > > +    }
> > > +  } else {
> > > +    Status = EFI_INVALID_PARAMETER;
> > > +  }
> > > +  //
> > > +  // Return the operation status
> > > +  //
> > > +no_pkt:
> > > +  gBS->RestoreTPL (TplPrevious);
> > > +  return Status;
> > > +}
> > > +
> > > +
> > > +/**
> > > +  This function is used to enable and disable the hardware and software
> > receive
> > > +  filters for the underlying network device.
> > > +
> > > +  The receive filter change is broken down into three steps:
> > > +
> > > +    1.  The filter mask bits that are set (ON) in the Enable parameter
> > > +        are added to the current receive filter settings.
> > > +
> > > +    2.  The filter mask bits that are set (ON) in the Disable parameter
> > > +        are subtracted from the updated receive filter settins.
> > > +
> > > +    3.  If the resulting filter settigns 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 enableing or disabling receive filter settings, software should
> > > +  verify the new settings by checking the SNP->Mode-
> > >ReceeiveFilterSettings,
> > > +  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.
> > > +
> > > +  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.
> > > +
> > > +  This routine calls ::ReceiveFilterUpdate to update the receive
> > > +  state in the network adapter.
> > > +
> > > +  @param [in] pSimpleNetwork    Protocol instance pointer
> > > +  @param [in] Enable            A bit mask of receive filters to enable on the
> > network interface.
> > > +  @param [in] 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 [in] bResetMCastFilter Set to TRUE to reset the contents of the
> > multicast receive
> > > +                                filters on the network interface to their default values.
> > > +  @param [in] MCastFilterCnt    Number of multicast HW MAC address in
> > the new MCastFilter list.
> > > +                                This value must be less than or equal to the
> > MaxMCastFilterCnt
> > > +                                field of EFI_SIMPLE_NETWORK_MODE.  This field is
> > optional if
> > > +                                ResetMCastFilter is TRUE.
> > > +  @param [in] pMCastFilter      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           This operation was successful.
> > > +  @retval EFI_NOT_STARTED       The network interface was not started.
> > > +  @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was
> > NULL or did not point to a valid
> > > +                                EFI_SIMPLE_NETWORK_PROTOCOL structure.
> > > +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> > network interface.
> > > +  @retval EFI_UNSUPPORTED       The increased buffer size feature is not
> > supported.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +SN_ReceiveFilters (
> > > +  IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
> > > +  IN UINT32 Enable,
> > > +  IN UINT32 Disable,
> > > +/*
> > > +#define EFI_SIMPLE_NETWORK_RECEIVE_UNICAST               0x01
> > > +#define EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST             0x02
> > > +#define EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST             0x04
> > > +#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS           0x08
> > > +#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
> > 0x10
> > > +*/
> > > +  IN BOOLEAN bResetMCastFilter,
> > > +  IN UINTN MCastFilterCnt,
> > > +  IN EFI_MAC_ADDRESS * pMCastFilter
> > > +  )
> > > +{
> > > +  EFI_SIMPLE_NETWORK_MODE * pMode;
> > > +  EFI_STATUS Status = EFI_SUCCESS;
> > > +  EFI_TPL TplPrevious;
> > > +  NIC_DEVICE * pNicDevice;
> > > +
> > > +  TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
> > > +  pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
> > > +  pMode = pSimpleNetwork->Mode;
> > > +
> > > +  if (pSimpleNetwork == NULL) {
> > > +    gBS->RestoreTPL(TplPrevious);
> > > +    return EFI_INVALID_PARAMETER;
> > > +  }
> > > +
> > > +  switch (pMode->State) {
> > > +  case EfiSimpleNetworkInitialized:
> > > +    break;
> > > +  case EfiSimpleNetworkStopped:
> > > +    Status = EFI_NOT_STARTED;
> > > +    gBS->RestoreTPL(TplPrevious);
> > > +    return Status;
> > > +
> > > +  default:
> > > +    Status = EFI_DEVICE_ERROR;
> > > +    gBS->RestoreTPL(TplPrevious);
> > > +    return Status;
> > > +  }
> > > +
> > > +  //
> > > +  // check if we are asked to enable or disable something that the UNDI
> > > +  // does not even support!
> > > +  //
> > > +  if (((Enable &~pMode->ReceiveFilterMask) != 0) ||
> > > +      ((Disable &~pMode->ReceiveFilterMask) != 0)) {
> > > +    Status = EFI_INVALID_PARAMETER;
> > > +    gBS->RestoreTPL(TplPrevious);
> > > +    return Status;
> > > +  }
> > > +
> > > +  if (bResetMCastFilter) {
> > > +    Disable |= (EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST & pMode-
> > >ReceiveFilterMask);
> > > +    MCastFilterCnt = 0;
> > > +    pMode->MCastFilterCount = 0;
> > > +    if ( (0 == (pMode->ReceiveFilterSetting &
> > EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST)) &&
> > > +   Enable == 0 && Disable == 2) {
> > > +      gBS->RestoreTPL(TplPrevious);
> > > +      return EFI_SUCCESS;
> > > +    }
> > > +  } else {
> > > +    if (MCastFilterCnt != 0) {
> > > +      UINTN i;
> > > +
> > > +      EFI_MAC_ADDRESS * pMulticastAddress;
> > > +      pMulticastAddress =  pMCastFilter;
> > > +
> > > +      if ((MCastFilterCnt > pMode->MaxMCastFilterCount) ||
> > > +          (pMCastFilter == NULL)) {
> > > +        Status = EFI_INVALID_PARAMETER;
> > > +        gBS->RestoreTPL(TplPrevious);
> > > +        return Status;
> > > +      }
> > > +
> > > +      for ( i = 0 ; i < MCastFilterCnt ; i++ ) {
> > > +          UINT8  tmp;
> > > +
> > > +          tmp = pMulticastAddress->Addr[0];
> > > +          if ( (tmp & 0x01) != 0x01 ) {
> > > +            gBS->RestoreTPL(TplPrevious);
> > > +            return EFI_INVALID_PARAMETER;
> > > +          }
> > > +          pMulticastAddress++;
> > > +      }
> > > +
> > > +      pMode->MCastFilterCount = (UINT32)MCastFilterCnt;
> > > +      CopyMem (&pMode->MCastFilter[0],
> > > +               pMCastFilter,
> > > +               MCastFilterCnt * sizeof ( EFI_MAC_ADDRESS/**pMCastFilter*/ ));
> > > +    }
> > > +  }
> > > +
> > > +  if (Enable == 0 && Disable == 0 && !bResetMCastFilter &&
> > MCastFilterCnt == 0) {
> > > +    Status = EFI_SUCCESS;
> > > +    gBS->RestoreTPL(TplPrevious);
> > > +    return Status;
> > > +  }
> > > +
> > > +  if ((Enable & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0 &&
> > MCastFilterCnt == 0) {
> > > +    Status = EFI_INVALID_PARAMETER;
> > > +    gBS->RestoreTPL(TplPrevious);
> > > +    return Status;
> > > +  }
> > > +
> > > +  pMode->ReceiveFilterSetting |= Enable;
> > > +  pMode->ReceiveFilterSetting &= ~Disable;
> > > +
> > > +  Status = ReceiveFilterUpdate (pSimpleNetwork);
> > > +
> > > +  gBS->RestoreTPL(TplPrevious);
> > > +  return Status;
> > > +}
> > > +
> > > +/**
> > > +  Reset the network adapter.
> > > +
> > > +  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 cleared.  Receive filters, the station address, the
> > > +  statistics, and the multicast-IP-to-HW MAC addresses are not reset by
> > > +  this call.
> > > +
> > > +  This routine calls ::Ax88179Reset to perform the adapter specific
> > > +  reset operation.  This routine also starts the link negotiation
> > > +  by calling ::Ax88179NegotiateLinkStart.
> > > +
> > > +  @param [in] pSimpleNetwork    Protocol instance pointer
> > > +  @param [in] bExtendedVerification  Indicates that the driver may
> > perform a more
> > > +                                exhaustive verification operation of the device
> > > +                                during reset.
> > > +
> > > +  @retval EFI_SUCCESS           This operation was successful.
> > > +  @retval EFI_NOT_STARTED       The network interface was not started.
> > > +  @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was
> > NULL or did not point to a valid
> > > +                                EFI_SIMPLE_NETWORK_PROTOCOL structure.
> > > +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> > network interface.
> > > +  @retval EFI_UNSUPPORTED       The increased buffer size feature is not
> > supported.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +SN_Reset (
> > > +  IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
> > > +  IN BOOLEAN bExtendedVerification
> > > +  )
> > > +{
> > > +  EFI_SIMPLE_NETWORK_MODE * pMode;
> > > +  NIC_DEVICE * pNicDevice;
> > > +  EFI_STATUS Status;
> > > +  EFI_TPL TplPrevious;
> > > +
> > > +
> > > +  TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
> > > +
> > > +  //
> > > +  //  Verify the parameters
> > > +  //
> > > +  if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
> > > +    pMode = pSimpleNetwork->Mode;
> > > +    if ( EfiSimpleNetworkInitialized == pMode->State ) {
> > > +      //
> > > +      //  Update the device state
> > > +      //
> > > +      pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
> > > +
> > > +      //
> > > +      //  Reset the device
> > > +      //
> > > +      if (!pNicDevice->bFirstRst) {
> > > +        Status = EFI_SUCCESS;
> > > +      } else {
> > > +        Status = Ax88179Reset ( pNicDevice );
> > > +        if ( !EFI_ERROR ( Status )) {
> > > +          Status = ReceiveFilterUpdate ( pSimpleNetwork );
> > > +          if ( !EFI_ERROR ( Status ) && !pNicDevice->bLinkUp && pNicDevice-
> > >bFirstRst) {
> > > +            Status = Ax88179NegotiateLinkStart ( pNicDevice );
> > > +            pNicDevice->bFirstRst = FALSE;
> > > +          }
> > > +        }
> > > +      }
> > > +    } else {
> > > +      Status = EFI_NOT_STARTED;
> > > +    }
> > > +  } else {
> > > +    Status = EFI_INVALID_PARAMETER;
> > > +  }
> > > +  //
> > > +  // Return the operation status
> > > +  //
> > > +  gBS->RestoreTPL(TplPrevious);
> > > +  return Status;
> > > +}
> > > +
> > > +/**
> > > +  Initialize the simple network protocol.
> > > +
> > > +  This routine calls ::Ax88179MacAddressGet to obtain the
> > > +  MAC address.
> > > +
> > > +  @param [in] pNicDevice       NIC_DEVICE_INSTANCE pointer
> > > +
> > > +  @retval EFI_SUCCESS     Setup was successful
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +SN_Setup (
> > > +  IN NIC_DEVICE * pNicDevice
> > > +  )
> > > +{
> > > +  EFI_SIMPLE_NETWORK_MODE * pMode;
> > > +  EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork;
> > > +  EFI_STATUS Status;
> > > +
> > > +  //
> > > +  // Initialize the simple network protocol
> > > +  //
> > > +  pSimpleNetwork = &pNicDevice->SimpleNetwork;
> > > +  pSimpleNetwork->Revision =
> > EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
> > > +  pSimpleNetwork->Start = (EFI_SIMPLE_NETWORK_START)SN_Start;
> > > +  pSimpleNetwork->Stop = (EFI_SIMPLE_NETWORK_STOP)SN_Stop;
> > > +  pSimpleNetwork->Initialize =
> > (EFI_SIMPLE_NETWORK_INITIALIZE)SN_Initialize;
> > > +  pSimpleNetwork->Reset = (EFI_SIMPLE_NETWORK_RESET)SN_Reset;
> > > +  pSimpleNetwork->Shutdown =
> > (EFI_SIMPLE_NETWORK_SHUTDOWN)SN_Shutdown;
> > > +  pSimpleNetwork->ReceiveFilters =
> > (EFI_SIMPLE_NETWORK_RECEIVE_FILTERS)SN_ReceiveFilters;
> > > +  pSimpleNetwork->StationAddress =
> > (EFI_SIMPLE_NETWORK_STATION_ADDRESS)SN_StationAddress;
> > > +  pSimpleNetwork->Statistics =
> > (EFI_SIMPLE_NETWORK_STATISTICS)SN_Statistics;
> > > +  pSimpleNetwork->MCastIpToMac =
> > (EFI_SIMPLE_NETWORK_MCAST_IP_TO_MAC)SN_MCastIPtoMAC;
> > > +  pSimpleNetwork->NvData =
> > (EFI_SIMPLE_NETWORK_NVDATA)SN_NvData;
> > > +  pSimpleNetwork->GetStatus =
> > (EFI_SIMPLE_NETWORK_GET_STATUS)SN_GetStatus;
> > > +  pSimpleNetwork->Transmit =
> > (EFI_SIMPLE_NETWORK_TRANSMIT)SN_Transmit;
> > > +  pSimpleNetwork->Receive =
> > (EFI_SIMPLE_NETWORK_RECEIVE)SN_Receive;
> > > +  pSimpleNetwork->WaitForPacket = NULL;
> > > +  pMode = &pNicDevice->SimpleNetworkData;
> > > +  pSimpleNetwork->Mode = pMode;
> > > +  pMode->State = EfiSimpleNetworkStopped;
> > > +  pMode->HwAddressSize = PXE_HWADDR_LEN_ETHER;
> > > +  pMode->MediaHeaderSize = sizeof ( ETHERNET_HEADER );
> > > +  pMode->MaxPacketSize = MAX_ETHERNET_PKT_SIZE;
> > > +  pMode->ReceiveFilterMask =
> > EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
> > > +                           | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
> > > +                           | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
> > > +                           | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
> > > +                           |
> > EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
> > > +  pMode->ReceiveFilterSetting =
> > EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
> > > +                              | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
> > > +  pMode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT;
> > > +  pMode->MCastFilterCount = 0;
> > > +  pMode->NvRamSize = 512;
> > > +  pMode->NvRamAccessSize = 2;
> > > +  SetMem ( &pMode->BroadcastAddress,
> > > +           PXE_HWADDR_LEN_ETHER,
> > > +           0xff );
> > > +  pMode->IfType = EfiNetworkInterfaceUndi;
> > > +  pMode->MacAddressChangeable = TRUE;
> > > +  pMode->MultipleTxSupported = FALSE;
> > > +  pMode->MediaPresentSupported = TRUE;
> > > +  pMode->MediaPresent = FALSE;
> > > +  //
> > > +  //  Read the MAC address
> > > +  //
> > > +  pNicDevice->PhyId = PHY_ID_INTERNAL;
> > > +  pNicDevice->b100Mbps = FALSE;
> > > +  pNicDevice->b1000Mbps = TRUE;
> > > +  pNicDevice->bFullDuplex = TRUE;
> > > +  pNicDevice->bComplete = FALSE;
> > > +  pNicDevice->bLinkUp = FALSE;
> > > +  pNicDevice->Grub_f = FALSE;
> > > +  pNicDevice->bFirstRst = TRUE;
> > > +  pNicDevice->PktCnt = 0;
> > > +  pNicDevice->SkipRXCnt = 0;
> > > +  pNicDevice->usbMaxPktSize = 512;
> > > +  pNicDevice->bSetZeroLen = TRUE;
> > > +
> > > +  Status = Ax88179MacAddressGet ( pNicDevice,
> > > +                                  &pMode->PermanentAddress.Addr[0]);
> > > +  if ( !EFI_ERROR ( Status )) {
> > > +    //
> > > +    //  Use the hardware address as the current address
> > > +    //
> > > +    CopyMem ( &pMode->CurrentAddress,
> > > +              &pMode->PermanentAddress,
> > > +              PXE_HWADDR_LEN_ETHER );
> > > +
> > > +    CopyMem ( &pNicDevice->MAC,
> > > +              &pMode->PermanentAddress,
> > > +              PXE_HWADDR_LEN_ETHER );
> > > +
> > > +  } else {
> > > +    return Status;
> > > +  }
> > > +
> > > +  Status = gBS->AllocatePool ( EfiRuntimeServicesData,
> > > +                               AX88179_MAX_BULKIN_SIZE,
> > > +                               (VOID **) &pNicDevice->pBulkInbuf );
> > > +
> > > +  if (EFI_ERROR (Status)) {
> > > +  return Status;
> > > +  }
> > > +
> > > +  Status = gBS->AllocatePool ( EfiRuntimeServicesData,
> > > +                               sizeof ( TX_PACKET ),
> > > +                               (VOID **) &pNicDevice->pTxTest );
> > > +  if (EFI_ERROR (Status)) {
> > > +  gBS->FreePool (pNicDevice->pBulkInbuf);
> > > +  }
> > > +
> > > +  //
> > > +  //  Return the setup status
> > > +  //
> > > +  return Status;
> > > +}
> > > +
> > > +
> > > +/**
> > > +  This routine starts the network interface.
> > > +
> > > +  @param [in] pSimpleNetwork    Protocol instance pointer
> > > +
> > > +  @retval EFI_SUCCESS           This operation was successful.
> > > +  @retval EFI_ALREADY_STARTED   The network interface was already
> > started.
> > > +  @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was
> > NULL or did not point to a valid
> > > +                                EFI_SIMPLE_NETWORK_PROTOCOL structure.
> > > +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> > network interface.
> > > +  @retval EFI_UNSUPPORTED       The increased buffer size feature is not
> > supported.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +SN_Start (
> > > +  IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork
> > > +  )
> > > +{
> > > +  NIC_DEVICE * pNicDevice;
> > > +  EFI_SIMPLE_NETWORK_MODE * pMode;
> > > +  EFI_STATUS Status;
> > > +  EFI_TPL TplPrevious;
> > > +
> > > +
> > > +  TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
> > > +
> > > +
> > > +
> > > +  //
> > > +  // Verify the parameters
> > > +  //
> > > +  Status = EFI_INVALID_PARAMETER;
> > > +  if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
> > > +    pMode = pSimpleNetwork->Mode;
> > > +    if ( EfiSimpleNetworkStopped == pMode->State ) {
> > > +      //
> > > +      // Initialize the mode structure
> > > +      // NVRAM access is not supported
> > > +      //
> > > +      ZeroMem ( pMode, sizeof ( *pMode ));
> > > +
> > > +      pMode->State = EfiSimpleNetworkStarted;
> > > +      pMode->HwAddressSize = PXE_HWADDR_LEN_ETHER;
> > > +      pMode->MediaHeaderSize = sizeof ( ETHERNET_HEADER );
> > > +      pMode->MaxPacketSize = MAX_ETHERNET_PKT_SIZE;
> > > +      pMode->ReceiveFilterMask =
> > EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
> > > +                               | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
> > > +                               | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
> > > +                               | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
> > > +                               |
> > EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
> > > +      pMode->ReceiveFilterSetting =
> > EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
> > > +      pMode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT;
> > > +      pMode->MCastFilterCount = 0;
> > > +      pMode->NvRamSize = 512;
> > > +      pMode->NvRamAccessSize = 2;
> > > +      pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
> > > +      Status = Ax88179MacAddressGet ( pNicDevice, &pMode-
> > >PermanentAddress.Addr[0]);
> > > +      CopyMem ( &pMode->CurrentAddress,
> > > +                &pMode->PermanentAddress,
> > > +                sizeof ( pMode->CurrentAddress ));
> > > +      SetMem(&pMode->BroadcastAddress, PXE_HWADDR_LEN_ETHER,
> > 0xff);
> > > +      pMode->IfType = EfiNetworkInterfaceUndi;
> > > +      pMode->MacAddressChangeable = TRUE;
> > > +      pMode->MultipleTxSupported = FALSE;
> > > +      pMode->MediaPresentSupported = TRUE;
> > > +      pMode->MediaPresent = FALSE;
> > > +
> > > +    } else {
> > > +      Status = EFI_ALREADY_STARTED;
> > > +    }
> > > +  }
> > > +  //
> > > +  // Return the operation status
> > > +  //
> > > +  gBS->RestoreTPL(TplPrevious);
> > > +  return Status;
> > > +}
> > > +
> > > +
> > > +/**
> > > +  Set the MAC address.
> > > +
> > > +  This function modifies or resets the current station address of a
> > > +  network interface.  If Reset is TRUE, then the current station address
> > > +  is set ot the network interface's permanent address.  If Reset if FALSE
> > > +  then the current station address is changed to the address specified by
> > > +  pNew.
> > > +
> > > +  This routine calls ::Ax88179MacAddressSet to update the MAC address
> > > +  in the network adapter.
> > > +
> > > +  @param [in] pSimpleNetwork    Protocol instance pointer
> > > +  @param [in] bReset            Flag used to reset the station address to the
> > > +                                network interface's permanent address.
> > > +  @param [in] pNew              New station address to be used for the
> > network
> > > +                                interface.
> > > +
> > > +  @retval EFI_SUCCESS           This operation was successful.
> > > +  @retval EFI_NOT_STARTED       The network interface was not started.
> > > +  @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was
> > NULL or did not point to a valid
> > > +                                EFI_SIMPLE_NETWORK_PROTOCOL structure.
> > > +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> > network interface.
> > > +  @retval EFI_UNSUPPORTED       The increased buffer size feature is not
> > supported.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +SN_StationAddress (
> > > +  IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
> > > +  IN BOOLEAN bReset,
> > > +  IN EFI_MAC_ADDRESS * pNew
> > > +  )
> > > +{
> > > +  NIC_DEVICE * pNicDevice;
> > > +  EFI_SIMPLE_NETWORK_MODE * pMode;
> > > +  EFI_STATUS Status;
> > > +
> > > +  EFI_TPL TplPrevious;
> > > +
> > > +
> > > +  TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
> > > +  //
> > > +  // Verify the parameters
> > > +  //
> > > +  if (( NULL != pSimpleNetwork ) &&
> > > +      ( NULL != pSimpleNetwork->Mode ) &&
> > > +      (( !bReset ) || ( bReset && ( NULL != pNew )))) {
> > > +    //
> > > +    // Verify that the adapter is already started
> > > +    //
> > > +    pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
> > > +    pMode = pSimpleNetwork->Mode;
> > > +    if ( EfiSimpleNetworkInitialized == pMode->State ) {
> > > +      //
> > > +      // Determine the adapter MAC address
> > > +      //
> > > +      if ( bReset ) {
> > > +        //
> > > +        // Use the permanent address
> > > +        //
> > > +        CopyMem ( &pMode->CurrentAddress,
> > > +                  &pMode->PermanentAddress,
> > > +                  sizeof ( pMode->CurrentAddress ));
> > > +      } else {
> > > +        //
> > > +        // Use the specified address
> > > +        //
> > > +        CopyMem ( &pMode->CurrentAddress,
> > > +                  pNew,
> > > +                  sizeof ( pMode->CurrentAddress ));
> > > +      }
> > > +
> > > +      //
> > > +      // Update the address on the adapter
> > > +      //
> > > +      Status = Ax88179MacAddressSet ( pNicDevice, &pMode-
> > >CurrentAddress.Addr[0]);
> > > +    }  else {
> > > +      if (EfiSimpleNetworkStarted == pMode->State) {
> > > +          Status = EFI_DEVICE_ERROR; ;
> > > +      } else {
> > > +          Status = EFI_NOT_STARTED ;
> > > +      }
> > > +    }
> > > +  } else {
> > > +    Status = EFI_INVALID_PARAMETER;
> > > +  }
> > > +
> > > +  //
> > > +  // Return the operation status
> > > +  //
> > > +  gBS->RestoreTPL(TplPrevious);
> > > +  return Status;
> > > +}
> > > +
> > > +
> > > +/**
> > > +  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 of the statistics that are collected by the network
> > > +  interface, then a partial buffer of statistics is returned in
> > > +  StatisticsTable.
> > > +
> > > +  @param [in] pSimpleNetwork    Protocol instance pointer
> > > +  @param [in] bReset            Set to TRUE to reset the statistics for the
> > network interface.
> > > +  @param [in, out] pStatisticsSize  On input the size, in bytes, of
> > StatisticsTable.  On output
> > > +                                the size, in bytes, of the resulting table of statistics.
> > > +  @param [out] pStatisticsTable A pointer to the
> > EFI_NETWORK_STATISTICS structure that
> > > +                                conains the statistics.
> > > +
> > > +  @retval EFI_SUCCESS           This operation was successful.
> > > +  @retval EFI_NOT_STARTED       The network interface was not started.
> > > +  @retval EFI_BUFFER_TOO_SMALL  The pStatisticsTable is NULL or the
> > buffer is too small.
> > > +  @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was
> > NULL or did not point to a valid
> > > +                                EFI_SIMPLE_NETWORK_PROTOCOL structure.
> > > +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> > network interface.
> > > +  @retval EFI_UNSUPPORTED       The increased buffer size feature is not
> > supported.
> > > +
> > > +  typedef struct {
> > > +  UINT64 RxTotalFrames;
> > > +  UINT64 RxGoodFrames;
> > > +  UINT64 RxUndersizeFrames;
> > > +  UINT64 RxOversizeFrames;
> > > +  UINT64 RxDroppedFrames;
> > > +  UINT64 RxUnicastFrames;
> > > +  UINT64 RxBroadcastFrames;
> > > +  UINT64 RxMulticastFrames;
> > > +  UINT64 RxCrcErrorFrames;
> > > +  UINT64 RxTotalBytes;
> > > +  UINT64 TxTotalFrames;
> > > +  UINT64 TxGoodFrames;
> > > +  UINT64 TxUndersizeFrames;
> > > +  UINT64 TxOversizeFrames;
> > > +  UINT64 TxDroppedFrames;
> > > +  UINT64 TxUnicastFrames;
> > > +  UINT64 TxBroadcastFrames;
> > > +  UINT64 TxMulticastFrames;
> > > +  UINT64 TxCrcErrorFrames;
> > > +  UINT64 TxTotalBytes;
> > > +  UINT64 Collisions;
> > > +  UINT64 UnsupportedProtocol;
> > > +  } EFI_NETWORK_STATISTICS;
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +SN_Statistics (
> > > +  IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
> > > +  IN BOOLEAN bReset,
> > > +  IN OUT UINTN * pStatisticsSize,
> > > +  OUT EFI_NETWORK_STATISTICS * pStatisticsTable
> > > +  )
> > > +{
> > > +  EFI_STATUS Status;
> > > +  EFI_TPL TplPrevious;
> > > +  EFI_SIMPLE_NETWORK_MODE * pMode;
> > > +
> > > +
> > > +
> > > +  TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
> > > +
> > > +  pMode = pSimpleNetwork->Mode;
> > > +
> > > +  if ( EfiSimpleNetworkInitialized == pMode->State ) {
> > > +    if (NULL != pStatisticsSize && 0 == *pStatisticsSize) {
> > > +      Status = EFI_BUFFER_TOO_SMALL;
> > > +      goto EXIT;
> > > +    }
> > > +
> > > +    if(bReset) {
> > > +      Status = EFI_SUCCESS;
> > > +    } else {
> > > +      Status = EFI_SUCCESS;
> > > +    }
> > > +  } else {
> > > +    if (EfiSimpleNetworkStarted == pMode->State) {
> > > +      Status = EFI_DEVICE_ERROR; ;
> > > +    } else {
> > > +      Status = EFI_NOT_STARTED ;
> > > +    }
> > > +  }
> > > +
> > > +  Status = EFI_UNSUPPORTED;
> > > +EXIT:
> > > +  gBS->RestoreTPL(TplPrevious);
> > > +  return Status;
> > > +}
> > > +
> > > +
> > > +/**
> > > +  This function stops a network interface.  This call is only valid
> > > +  if the network interface is in the started state.
> > > +
> > > +  @param [in] pSimpleNetwork    Protocol instance pointer
> > > +
> > > +  @retval EFI_SUCCESS           This operation was successful.
> > > +  @retval EFI_NOT_STARTED       The network interface was not started.
> > > +  @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was
> > NULL or did not point to a valid
> > > +                                EFI_SIMPLE_NETWORK_PROTOCOL structure.
> > > +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> > network interface.
> > > +  @retval EFI_UNSUPPORTED       The increased buffer size feature is not
> > supported.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +SN_Stop (
> > > +  IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork
> > > +  )
> > > +{
> > > +  EFI_SIMPLE_NETWORK_MODE * pMode;
> > > +  EFI_STATUS Status;
> > > +  EFI_TPL TplPrevious;
> > > +
> > > +  TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
> > > +
> > > +  //
> > > +  // Verify the parameters
> > > +  //
> > > +  if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
> > > +    //
> > > +    // Determine if the interface is started
> > > +    //
> > > +    pMode = pSimpleNetwork->Mode;
> > > +    if ( EfiSimpleNetworkStarted == pMode->State ) {
> > > +        pMode->State = EfiSimpleNetworkStopped;
> > > +        Status = EFI_SUCCESS;
> > > +    } else {
> > > +        Status = EFI_NOT_STARTED;
> > > +    }
> > > +  } else {
> > > +    Status = EFI_INVALID_PARAMETER;
> > > +  }
> > > +  //
> > > +  // Return the operation status
> > > +  //
> > > +  gBS->RestoreTPL(TplPrevious);
> > > +  return Status;
> > > +}
> > > +
> > > +/**
> > > +  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 Initialize() and Stop() calls may be used.
> > > +
> > > +  @param [in] pSimpleNetwork    Protocol instance pointer
> > > +
> > > +  @retval EFI_SUCCESS           This operation was successful.
> > > +  @retval EFI_NOT_STARTED       The network interface was not started.
> > > +  @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was
> > NULL or did not point to a valid
> > > +                                EFI_SIMPLE_NETWORK_PROTOCOL structure.
> > > +  @retval EFI_DEVICE_ERROR      The command could not be sent to the
> > network interface.
> > > +  @retval EFI_UNSUPPORTED       The increased buffer size feature is not
> > supported.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +SN_Shutdown (
> > > +  IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork
> > > +  )
> > > +{
> > > +  EFI_SIMPLE_NETWORK_MODE * pMode;
> > > +  EFI_STATUS Status;
> > > +  NIC_DEVICE * pNicDevice;
> > > +  EFI_TPL TplPrevious;
> > > +
> > > +
> > > +  TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
> > > +
> > > +  //
> > > +  // Verify the parameters
> > > +  //
> > > +  if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
> > > +    //
> > > +    // Determine if the interface is already started
> > > +    //
> > > +    pMode = pSimpleNetwork->Mode;
> > > +    if ( EfiSimpleNetworkInitialized == pMode->State ) {
> > > +      //
> > > +      // Stop the adapter
> > > +      //
> > > +      pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
> > > +
> > > +      Status = Ax88179MacAddressGet ( pNicDevice, &pMode-
> > >PermanentAddress.Addr[0]);
> > > +      if ( !EFI_ERROR ( Status )) {
> > > +        //
> > > +        // Update the network state
> > > +        //
> > > +        pMode->State = EfiSimpleNetworkStarted;
> > > +      } else if ( EFI_DEVICE_ERROR == Status ) {
> > > +        pMode->State = EfiSimpleNetworkStopped;
> > > +      }
> > > +    } else {
> > > +      Status = EFI_NOT_STARTED;
> > > +    }
> > > +  } else {
> > > +    Status = EFI_INVALID_PARAMETER;
> > > +  }
> > > +  //
> > > +  // Return the operation status
> > > +  //
> > > +  gBS->RestoreTPL(TplPrevious );
> > > +  return Status;
> > > +}
> > > +
> > > +
> > > +/**
> > > +  Send a packet over the network.
> > > +
> > > +  This function places the packet specified by Header and Buffer on
> > > +  the transmit queue.  This function performs a non-blocking transmit
> > > +  operation.  When the transmit is complete, the buffer is returned
> > > +  via the GetStatus() call.
> > > +
> > > +  This routine calls ::Ax88179Rx to empty the network adapter of
> > > +  receive packets.  The routine then passes the transmit packet
> > > +  to the network adapter.
> > > +
> > > +  @param [in] pSimpleNetwork    Protocol instance pointer
> > > +  @param [in] HeaderSize        The size, in bytes, of the media header to be
> > filled in by
> > > +                                the Transmit() function.  If HeaderSize is non-zero, then
> > > +                                it must be equal to SimpleNetwork->Mode-
> > >MediaHeaderSize
> > > +                                and DestAddr and Protocol parameters must not be
> > NULL.
> > > +  @param [in] BufferSize        The size, in bytes, of the entire packet (media
> > header and
> > > +                                data) to be transmitted through the network interface.
> > > +  @param [in] pBuffer           A pointer to the packet (media header
> > followed by data) to
> > > +                                to be transmitted.  This parameter can not be NULL.  If
> > > +                                HeaderSize is zero, then the media header is 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 [in] pSrcAddr          The source HW MAC address.  If HeaderSize
> > is zero, then
> > > +                                this parameter is ignored.  If HeaderSize is nonzero and
> > > +                                SrcAddr is NULL, then SimpleNetwork->Mode-
> > >CurrentAddress
> > > +                                is used for the source HW MAC address.
> > > +  @param [in] pDestAddr         The destination HW MAC address.  If
> > HeaderSize is zero, then
> > > +                                this parameter is ignored.
> > > +  @param [in] pProtocol         The type of header to build.  If HeaderSize is
> > zero, then
> > > +                                this parameter is ignored.
> > > +
> > > +  @retval EFI_SUCCESS           This operation was successful.
> > > +  @retval EFI_NOT_STARTED       The network interface was not 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 pSimpleNetwork 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
> > > +SN_Transmit (
> > > +  IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
> > > +  IN UINTN HeaderSize,
> > > +  IN UINTN BufferSize,
> > > +  IN VOID * pBuffer,
> > > +  IN EFI_MAC_ADDRESS * pSrcAddr,
> > > +  IN EFI_MAC_ADDRESS * pDestAddr,
> > > +  IN UINT16 * pProtocol
> > > +  )
> > > +{
> > > +  ETHERNET_HEADER * pHeader;
> > > +  EFI_SIMPLE_NETWORK_MODE * pMode;
> > > +  NIC_DEVICE * pNicDevice;
> > > +  EFI_USB_IO_PROTOCOL * pUsbIo;
> > > +  EFI_STATUS Status;
> > > +  UINTN TransferLength;
> > > +  UINT32 TransferStatus;
> > > +  UINT16 Type = 0;
> > > +  EFI_TPL TplPrevious;
> > > +
> > > +  TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
> > > +  //
> > > +  // Verify the parameters
> > > +  //
> > > +  if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
> > > +    //
> > > +    // The interface must be running
> > > +    //
> > > +    pMode = pSimpleNetwork->Mode;
> > > +    if ( EfiSimpleNetworkInitialized == pMode->State ) {
> > > +      //
> > > +      // Update the link status
> > > +      //
> > > +      pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
> > > +
> > > +      if ( pNicDevice->bLinkUp && pNicDevice->bComplete) {
> > > +        if (0 != HeaderSize && pMode->MediaHeaderSize != HeaderSize)  {
> > > +            Status = EFI_INVALID_PARAMETER;
> > > +            goto EXIT;
> > > +        }
> > > +        if (BufferSize <  pMode->MediaHeaderSize) {
> > > +            Status = EFI_INVALID_PARAMETER;
> > > +            goto EXIT;
> > > +        }
> > > +        if (NULL == pBuffer) {
> > > +            Status = EFI_INVALID_PARAMETER;
> > > +            goto EXIT;
> > > +        }
> > > +        if (0 != HeaderSize && NULL == pDestAddr) {
> > > +            Status = EFI_INVALID_PARAMETER;
> > > +            goto EXIT;
> > > +        }
> > > +        if (0 != HeaderSize && NULL == pProtocol) {
> > > +            Status = EFI_INVALID_PARAMETER;
> > > +            goto EXIT;
> > > +        }
> > > +        //
> > > +        //  Copy the packet into the USB buffer
> > > +        //
> > > +        // pBuffer starting with 14 bytes 0
> > > +        CopyMem ( &pNicDevice->pTxTest->Data[0], pBuffer, BufferSize);
> > > +        pNicDevice->pTxTest->TxHdr1 = (UINT32) BufferSize;
> > > +        pNicDevice->pTxTest->TxHdr2 = 0;
> > > +        //
> > > +        //  Transmit the packet
> > > +        //
> > > +        pHeader = (ETHERNET_HEADER *) &pNicDevice->pTxTest->Data[0];
> > > +        if ( 0 != HeaderSize ) {
> > > +          if ( NULL != pDestAddr ) {
> > > +            CopyMem ( &pHeader->dest_addr, pDestAddr,
> > PXE_HWADDR_LEN_ETHER );
> > > +          }
> > > +          if ( NULL != pSrcAddr ) {
> > > +            CopyMem ( &pHeader->src_addr, pSrcAddr,
> > PXE_HWADDR_LEN_ETHER );
> > > +          } else {
> > > +            CopyMem ( &pHeader->src_addr, &pMode-
> > >CurrentAddress.Addr[0], PXE_HWADDR_LEN_ETHER );
> > > +          }
> > > +          if ( NULL != pProtocol ) {
> > > +            Type = *pProtocol;
> > > +          } else {
> > > +              Type = (UINT16) BufferSize;
> > > +          }
> > > +          Type = (UINT16)(( Type >> 8 ) | ( Type << 8 ));
> > > +          pHeader->type = Type;
> > > +        }
> > > +
> > > +        if ( pNicDevice->pTxTest->TxHdr1 < MIN_ETHERNET_PKT_SIZE ) {
> > > +          pNicDevice->pTxTest->TxHdr1 = MIN_ETHERNET_PKT_SIZE;
> > > +          ZeroMem ( &pNicDevice->pTxTest->Data[BufferSize],
> > > +                    MIN_ETHERNET_PKT_SIZE - BufferSize );
> > > +        }
> > > +
> > > +        TransferLength = sizeof ( pNicDevice->pTxTest->TxHdr1 )
> > > +                       + sizeof ( pNicDevice->pTxTest->TxHdr2 )
> > > +                       + pNicDevice->pTxTest->TxHdr1;
> > > +        //
> > > +        //  Work around USB bus driver bug where a timeout set by receive
> > > +        //  succeeds but the timeout expires immediately after, causing the
> > > +        //  transmit operation to timeout.
> > > +        //
> > > +        pUsbIo = pNicDevice->pUsbIo;
> > > +        Status = pUsbIo->UsbBulkTransfer ( pUsbIo,
> > > +                                           BULK_OUT_ENDPOINT,
> > > +                                           &pNicDevice->pTxTest->TxHdr1,
> > > +                                           &TransferLength,
> > > +                                           0xfffffffe,
> > > +                                           &TransferStatus );
> > > +
> > > +        if (!EFI_ERROR(Status) && !EFI_ERROR(Status)) {
> > > +              pNicDevice->pTxBuffer = pBuffer;
> > > +              Status = EFI_SUCCESS;
> > > +        } else if (EFI_TIMEOUT == Status && EFI_USB_ERR_TIMEOUT ==
> > TransferStatus) {
> > > +              Status = EFI_NOT_READY;
> > > +        } else {
> > > +              Status = EFI_DEVICE_ERROR;
> > > +        }
> > > +      } else {
> > > +        //
> > > +        // No packets available.
> > > +        //
> > > +        Status = EFI_NOT_READY;
> > > +      }
> > > +    } else {
> > > +      if (EfiSimpleNetworkStarted == pMode->State) {
> > > +          Status = EFI_DEVICE_ERROR; ;
> > > +      } else {
> > > +          Status = EFI_NOT_STARTED ;
> > > +      }
> > > +    }
> > > +  } else {
> > > +    Status = EFI_INVALID_PARAMETER;
> > > +  }
> > > +EXIT:
> > > +  gBS->RestoreTPL (TplPrevious);
> > > +  return Status;
> > > +}
> > > --
> > > 2.17.1
> 
> IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you
> are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person,
> use it for any purpose, or store or copy the information in any medium. Thank you.
> 
> 


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

View/Reply Online (#58822): https://edk2.groups.io/g/devel/message/58822
Mute This Topic: https://groups.io/mt/74044146/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