public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Leif Lindholm" <leif@nuviainc.com>
To: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>
Cc: devel@edk2.groups.io, Ray Ni <ray.ni@intel.com>,
	Ard Biesheuvel <ard.biesheuvel@arm.com>,
	Michael D Kinney <michael.d.kinney@intel.com>
Subject: Re: [edk2-platform][PATCH v1 4/4] Silicon/AsixPkg: Add ASIX Ax88772c driver
Date: Tue, 12 May 2020 14:22:48 +0100	[thread overview]
Message-ID: <20200512132248.GE21486@vanye> (raw)
In-Reply-To: <20200510111530.26225-5-Samer.El-Haj-Mahmoud@arm.com>

On Sun, May 10, 2020 at 07:15:30 -0400, Samer El-Haj-Mahmoud wrote:
> This is the initial revision of ASIX USB networking UEFI driver
> version 2.8.0 for Ax88772c / Ax88772b / Ax88772a
> https://www.asix.com.tw/download.php?sub=driverdetail&PItemID=136
> 
> Source code contributed by ASIX.

Same source version questions as for 3/4.
Same request to use "provided" rather than "contributed".

> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Leif Lindholm <leif@nuviainc.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> 
> Signed-off-by: Samer El-Haj-Mahmoud <samer.el-haj-mahmoud@arm.com>
> ---
>  Silicon/ASIX/AsixPkg.dsc                                            |    1 +
>  Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/Ax88772c.inf    |   65 +
>  Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.h       | 1097 +++++++++++++
>  Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.c       | 1296 ++++++++++++++++
>  Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/ComponentName.c |  246 +++
>  Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/DriverBinding.c |  637 ++++++++
>  Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/SimpleNetwork.c | 1612 ++++++++++++++++++++
>  7 files changed, 4954 insertions(+)
> 
> diff --git a/Silicon/ASIX/AsixPkg.dsc b/Silicon/ASIX/AsixPkg.dsc
> index 5e860d7b3c8f..5227a3f30930 100644
> --- a/Silicon/ASIX/AsixPkg.dsc
> +++ b/Silicon/ASIX/AsixPkg.dsc
> @@ -67,3 +67,4 @@ [Components]
>  Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf
>  Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772/Ax88772.inf
>  Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772b/Ax88772b.inf
> +Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/Ax88772c.inf
> diff --git a/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/Ax88772c.inf b/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/Ax88772c.inf
> new file mode 100644
> index 000000000000..1d37a5dae34b
> --- /dev/null
> +++ b/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/Ax88772c.inf
> @@ -0,0 +1,65 @@
> +## @file
> +# Component description file for ASIX AX88772 USB/Ethernet driver.
> +#
> +# This module provides support for the ASIX AX88772 USB/Ethernet adapter.
> +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>

Same question regarding Intel copyright.

> +#
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010018
> +  BASE_NAME                      = Ax88772c
> +  FILE_GUID                      = B15239D6-6A01-4808-A0F7-B7F20F073555
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +
> +  ENTRY_POINT                    = EntryPoint
> +
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64 EBC
> +#
> +
> +[Sources.common]
> +  Ax88772.h
> +  Ax88772.c
> +  ComponentName.c
> +  DriverBinding.c
> +  SimpleNetwork.c
> +
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[LibraryClasses]
> +  UefiLib
> +  UefiBootServicesTableLib
> +  BaseMemoryLib
> +  DebugLib
> +  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/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.h b/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.h
> new file mode 100644
> index 000000000000..18317fd5c4f7
> --- /dev/null
> +++ b/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.h
> @@ -0,0 +1,1097 @@
> +/** @file
> +  Definitions for ASIX AX88772 Ethernet adapter.
> +
> +  Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef _AX88772_H_
> +#define _AX88772_H_

Please drop leading _.

> +
> +#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 MAX_QUEUE_SIZE 50
> +#define MAX_BULKIN_SIZE 16384
> +#define HW_HDR_LENGTH 8
> +#define PASS_SCT      0
> +#define REPORTLINK    1
> +
> +#define ARM  0
> +
> +#if ARM
> +#define MAX_LINKIDLE_THRESHOLD  100
> +#else
> +#define MAX_LINKIDLE_THRESHOLD  30
> +#endif

?

> +
> +#define AMI    1
> +#define ASIX_MCAST_FILTER_CNT 8
> +#define RXTHOU 0

Again, ?

> +
> +#if 0

Delete, don't #if out.

> +//------------------------------------------------------------------------------
> +//  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
> +
> +#endif
> +
> +#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
> +
> +
> +#define PRINT(_L_STR) (gST->ConOut->OutputString(gST->ConOut,(_L_STR)))
> +//------------------------------------------------------------------------------
> +//  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
> +
> +#if RXTHOU
> +#define AX88772_MAX_BULKIN_SIZE    1024 * 17 //32
> +#else
> +#define AX88772_MAX_BULKIN_SIZE    1024 * 3
> +#endif
> +
> +#define AX88772_MAX_PKT_SIZE  2048  ///< Maximum packet size
> +
> +#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  ///<  Ethernet spec 3.1.1: Minimum packet size
> +
> +#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_AX88772         TPL_CALLBACK    ///<  TPL for routine synchronization

Delete, don't comment out.

> +
> +#define HC_DEBUG  0
> +
> +#if RXTHOU
> +#define BULKIN_TIMEOUT  3 //10 //100 //1000
> +#else
> +#define BULKIN_TIMEOUT  3000
> +#endif
> +
> +#define AUTONEG_DELAY   2000000
> +#define AUTONEG_POLL_CNT    5
> +
> +/**
> +  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 );                \

No space after ( or before ).

> +  }                                               \
> +}
> +
> +#else   //  MDEPKG_NDEBUG
> +
> +#define VERIFY_TPL(tpl)
> +
> +#endif  //  MDEPKG_NDEBUG
> +
> +//------------------------------------------------------------------------------
> +//  Hardware Definition
> +//------------------------------------------------------------------------------
> +
> +#define FreeQueueSize     10
> +
> +#define DEV_SIGNATURE     SIGNATURE_32 ('A','X','8','8')  ///<  Signature of data structures in memory
> +
> +#define VENDOR_ID         0x0B95  ///<  Vendor ID for Asix
> +#define VENDOR_AX88772B_LENOVO_ID  0x17EF
> +
> +
> +/* Freddy */
> +#define PRODUCT_ID        0x7720  ///<  Product ID for the AX88772 USB 10/100 Ethernet controller
> +#define PRODUCT_AX88772A_ID   0x772A
> +#define PRODUCT_AX88772B_ID   0x772b
> +#define PRODUCT_AX88772B_ASUS_ID 0x7e2b
> +#define PRODUCT_AX88772B_LENOVO_ID 0x7203
> +/* Freddy */
> +
> +
> +#define RESET_MSEC        1000    ///<  Reset duration
> +#define PHY_RESET_MSEC     500    ///<  PHY reset duration
> +
> +//
> +//  RX Control register
> +//
> +
> +#define RXC_PRO           0x0001  ///<  Receive all packets
> +#define RXC_AMALL         0x0002  ///<  Receive all multicast packets
> +#define RXC_SEP           0x0004  ///<  Save error packets
> +#define RXC_AB            0x0008  ///<  Receive broadcast packets
> +#define RXC_AM            0x0010  ///<  Use multicast destination address hash table
> +#define RXC_AP            0x0020  ///<  Accept physical address from Multicast Filter
> +#define RXC_SO            0x0080  ///<  Start operation
> +#define RXC_MFB           0x0300  ///<  Maximum frame burst
> +#define RXC_MFB_2048      0       ///<  Maximum frame size:  2048 bytes
> +#define RXC_MFB_4096      0x0100  ///<  Maximum frame size:  4096 bytes
> +#define RXC_MFB_8192      0x0200  ///<  Maximum frame size:  8192 bytes
> +#define RXC_MFB_16384     0x0300  ///<  Maximum frame size: 16384 bytes
> +
> +/*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
> +//
> +
> +#define MS_FD             0x0002  ///<  Full duplex
> +#define MS_ONE            0x0004  ///<  Must be one
> +#define MS_RFC            0x0010  ///<  RX flow control enable
> +#define MS_TFC            0x0020  ///<  TX flow control enable
> +#define MS_PF             0x0080  ///<  Pause frame enable
> +#define MS_RE             0x0100  ///<  Receive enable
> +#define MS_PS             0x0200  ///<  Port speed 1=100, 0=10 Mbps
> +#define MS_SBP            0x0800  ///<  Stop back pressure
> +#define MS_SM             0x1000  ///<  Super MAC support
> +
> +//
> +//  Software PHY Select register
> +//
> +
> +#define SPHY_PSEL         (1 << 0)    ///<  Select internal PHY
> +#define SPHY_SSMII        (1 << 2)
> +#define SPHY_SSEN         (1 << 4)
> +#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_BZTYPE        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   0x0010  ///<  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_SROM_WRITE            0x0c  ///<  Read SROM register: Value: Address, Data: Value
> +#define CMD_SROM_WRITE_EN         0x0d
> +#define CMD_SROM_WRITE_DIS        0x0e
> +#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      0x13  ///<  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_MULTICAST_HASH_READ   0x15  ///<  Read the multicast hash table
> +#define CMD_MULTICAST_HASH_WRITE  0x16  ///<  Write the multicast hash table, Data: New 8 byte value
> +#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_WRITE_GPIOS           0x1f
> +#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*/

Here's Freddy again.
Unfortunately, this one appears to be actually used.

> +
> +//------------------------------
> +//  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_BMCR                        0       ///<  Control register
> +#define PHY_BMSR                        1       ///<  Status register
> +#define PHY_ANAR                        4       ///<  Autonegotiation advertisement register
> +#define PHY_ANLPAR                      5       ///<  Autonegotiation link parter ability register
> +#define PHY_ANER                        6       ///<  Autonegotiation expansion register
> +
> +//  BMCR - Register 0
> +
> +#define BMCR_RESET                      0x8000  ///<  1 = Reset the PHY, bit clears after reset
> +#define BMCR_LOOPBACK                   0x4000  ///<  1 = Loopback enabled
> +#define BMCR_100MBPS                    0x2000  ///<  100 Mbits/Sec
> +#define BMCR_10MBPS                     0       ///<  10 Mbits/Sec
> +#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_HALF_DUPLEX                0       ///<  Half duplex operation
> +#define BMCR_COLLISION_TEST             0x0080  ///<  1 = Collision test enabled
> +
> +//  BSMR - Register 1
> +
> +#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
> +
> +//  ANAR and ANLPAR Registers 4, 5
> +
> +#define AN_NP                           0x8000  ///<  1 = Next page available
> +#define AN_ACK                          0x4000  ///<  1 = Link partner acknowledged
> +#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
> +
> +
> +
> +//------------------------------------------------------------------------------
> +//  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 _RX_TX_PACKET {
> +  struct _RX_TX_PACKET * pNext;       ///<  Next receive packet
> +  UINT16 Length;                      ///<  Packet length
> +  UINT16 LengthBar;                   ///<  Complement of the length
> +  UINT8 Data[ AX88772_MAX_PKT_SIZE ]; ///<  Received packet data
> +} RX_TX_PACKET;
> +#pragma pack()
> +
> +/**
> +  AX88772 control structure
> +
> +  The driver uses this structure to manage the Asix AX88772 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

No Hungarian notation - drop the leading p:s and b:s.

> +  BOOLEAN bComplete;        ///<  Current state of auto-negotiation
> +  BOOLEAN bFullDuplex;      ///<  Current duplex
> +  BOOLEAN bLinkUp;          ///<  Current link state
> +  UINTN PollCount;          ///<  Number of times the autonegotiation status was polled
> +  UINT16 CurRxControl;
> +  VOID * pTxBuffer;
> +  //
> +  //  Receive buffer list
> +  //
> +  UINT8     *pBulkInbuf;
> +  UINT8    * pCurPktHdrOff;
> +  UINT8     *pCurPktOff;
> +  UINT16    PktCnt;
> +
> +  RX_TX_PACKET * pTxTest;
> +
> +  UINT8 MulticastHash[8];
> +  EFI_MAC_ADDRESS MAC;
> +
> +  EFI_DEVICE_PATH_PROTOCOL                  *MyDevPath;
> +  BOOLEAN   Grub_f;

Yeah, again.

> +  BOOLEAN   bFirstRst;
> +  BOOLEAN   Flag772A;
> +#if RXTHOU
> +  UINT8 rxburst;
> +#endif
> +
> +} NIC_DEVICE;
> +
> +
> +//
> +// Global Variables
> +//
> +extern EFI_DRIVER_BINDING_PROTOCOL   gDriverBinding;
> +extern EFI_COMPONENT_NAME_PROTOCOL   gComponentName;
> +extern EFI_COMPONENT_NAME2_PROTOCOL  gComponentName2;
> +
> +#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 ::Ax88772Reset to perform the adapter specific
> +  reset operation.  This routine also starts the link negotiation
> +  by calling ::Ax88772NegotiateLinkStart.
> +
> +  @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 ::Ax88772MacAddressGet 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 ::Ax88772MacAddressSet 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 ::Ax88772Rx 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 ::Ax88772UsbCommand 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
> +Ax88772MacAddressGet (
> +  IN NIC_DEVICE * pNicDevice,
> +  OUT UINT8 * pMacAddress
> +  );
> +
> +/**
> +  Set the MAC address
> +
> +  This routine calls ::Ax88772UsbCommand 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
> +Ax88772MacAddressSet (
> +  IN NIC_DEVICE * pNicDevice,
> +  IN UINT8 * pMacAddress
> +  );
> +
> +/**
> +  Clear the multicast hash table
> +
> +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> +
> +**/
> +VOID
> +Ax88772MulticastClear (
> +  IN NIC_DEVICE * pNicDevice
> +  );
> +
> +/**
> +  Enable a multicast address in the multicast hash table
> +
> +  This routine calls ::Ax88772Crc 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
> +Ax88772MulticastSet (
> +  IN NIC_DEVICE * pNicDevice,
> +  IN UINT8 * pMacAddress
> +  );
> +
> +/**
> +  Start the link negotiation
> +
> +  This routine calls ::Ax88772PhyWrite 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
> +Ax88772NegotiateLinkStart (
> +  IN NIC_DEVICE * pNicDevice
> +  );
> +
> +/**
> +  Complete the negotiation of the PHY link
> +
> +  This routine calls ::Ax88772PhyRead 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
> +Ax88772NegotiateLinkComplete (
> +  IN NIC_DEVICE * pNicDevice,
> +  IN OUT UINTN * pPollCount,
> +  OUT BOOLEAN * pbComplete,
> +  OUT BOOLEAN * pbLinkUp,
> +  OUT BOOLEAN * pbHiSpeed,
> +  OUT BOOLEAN * pbFullDuplex
> +  );
> +
> +/**
> +  Read a register from the PHY
> +
> +  This routine calls ::Ax88772UsbCommand 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
> +Ax88772PhyRead (
> +  IN NIC_DEVICE * pNicDevice,
> +  IN UINT8 RegisterAddress,
> +  IN OUT UINT16 * pPhyData
> +  );
> +
> +/**
> +  Write to a PHY register
> +
> +  This routine calls ::Ax88772UsbCommand 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
> +Ax88772PhyWrite (
> +  IN NIC_DEVICE * pNicDevice,
> +  IN UINT8 RegisterAddress,
> +  IN UINT16 PhyData
> +  );
> +
> +/**
> +  Reset the AX88772
> +
> +  This routine uses ::Ax88772UsbCommand to reset the network
> +  adapter.  This routine also uses ::Ax88772PhyWrite 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
> +Ax88772Reset (
> +  IN NIC_DEVICE * pNicDevice
> +  );
> +
> +VOID
> +Ax88772ChkLink (
> +  IN NIC_DEVICE * pNicDevice,
> +  IN BOOLEAN bUpdateLink
> +  );
> +
> +/**
> +  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 ::Ax88772NegotiateLinkComplete 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
> +Ax88772Rx (
> +  IN NIC_DEVICE * pNicDevice,
> +  IN BOOLEAN bUpdateLink
> +  );
> +
> +/**
> +  Enable or disable the receiver
> +
> +  This routine calls ::Ax88772UsbCommand to update the
> +  receiver state.  This routine also calls ::Ax88772MacAddressSet
> +  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
> +Ax88772RxControl (
> +  IN NIC_DEVICE * pNicDevice,
> +  IN UINT32 RxFilter
> +  );
> +
> +EFI_STATUS
> +Ax88772ReloadSrom  (
> +  IN NIC_DEVICE * pNicDevice
> +  );
> +
> +/**
> +  Read an SROM location
> +
> +  This routine calls ::Ax88772UsbCommand 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
> +Ax88772SromRead (
> +  IN NIC_DEVICE * pNicDevice,
> +  IN UINT32 Address,
> +  OUT UINT16 * pData
> +  );
> +
> +
> +EFI_STATUS
> +Ax88772EnableSromWrite  (
> +  IN NIC_DEVICE * pNicDevice
> +  );
> +
> +
> +EFI_STATUS
> +Ax88772DisableSromWrite  (
> +  IN NIC_DEVICE * pNicDevice
> +  );
> +
> +EFI_STATUS
> +Ax88772SromWrite (
> +  IN NIC_DEVICE * pNicDevice,
> +  IN UINT32 Address,
> +  OUT UINT16 * pData
> +  );
> +#if 0

Delete, don't #ifdef out.

> +/**
> +  This routine is called at a regular interval to poll for
> +  receive packets.
> +
> +  This routine polls the link state and gets any receive packets
> +  by calling ::Ax88772Rx.
> +
> +  @param [in] Event            Timer event
> +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> +
> +**/
> +VOID
> +Ax88772Timer (
> +  IN EFI_EVENT Event,
> +  IN NIC_DEVICE * pNicDevice
> +  );
> +#endif
> +/**
> +  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
> +Ax88772UsbCommand (
> +  IN NIC_DEVICE * pNicDevice,
> +  IN USB_DEVICE_REQUEST * pRequest,
> +  IN OUT VOID * pBuffer
> +  );
> +
> +BOOLEAN
> +Ax88772GetLinkStatus (
> +  IN NIC_DEVICE * pNicDevice
> +) ;
> +
> +//------------------------------------------------------------------------------
> +// EFI Component Name Protocol Support
> +//------------------------------------------------------------------------------
> +
> +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
> +Ax88772BulkIn(
> +  IN NIC_DEVICE * pNicDevice
> +);
> +
> +//------------------------------------------------------------------------------
> +
> +#endif  //  _AX88772_H_
> diff --git a/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.c b/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.c
> new file mode 100644
> index 000000000000..a905dc548197
> --- /dev/null
> +++ b/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.c
> @@ -0,0 +1,1296 @@
> +/** @file
> +  Implement the interface to the AX88772 Ethernet controller.
> +
> +  This module implements the interface to the ASIX AX88772
> +  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. All rights reserved.
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "Ax88772.h"

Please include headers needed for this file in this file.
Keep only include statements in Ax88772.h used by Ax88772.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
> +Ax88772Crc (
> +  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 ::Ax88772UsbCommand 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
> +Ax88772MacAddressGet (
> +  IN NIC_DEVICE * pNicDevice,
> +  OUT UINT8 * pMacAddress
> +  )
> +{
> +  USB_DEVICE_REQUEST SetupMsg;
> +  EFI_STATUS Status;
> +
> +  //
> +  //  Set the register address.
> +  //
> +  SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
> +                       | USB_REQ_TYPE_VENDOR
> +                       | USB_TARGET_DEVICE;
> +  SetupMsg.Request = CMD_MAC_ADDRESS_READ;
> +  SetupMsg.Value = 0;
> +  SetupMsg.Index = 0;
> +  SetupMsg.Length = PXE_HWADDR_LEN_ETHER;
> +
> +  //
> +  //  Read the PHY register
> +  //
> +  Status = Ax88772UsbCommand ( pNicDevice,
> +                               &SetupMsg,
> +                               pMacAddress );
> +
> +  //
> +  // Return the operation status
> +  //
> +  return Status;
> +}
> +
> +
> +/**
> +  Set the MAC address
> +
> +  This routine calls ::Ax88772UsbCommand 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
> +Ax88772MacAddressSet (
> +  IN NIC_DEVICE * pNicDevice,
> +  IN UINT8 * pMacAddress
> +  )
> +{
> +  USB_DEVICE_REQUEST SetupMsg;
> +  EFI_STATUS Status;
> +
> +  //
> +  //  Set the register address.
> +  //
> +  SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                       | USB_TARGET_DEVICE;
> +  SetupMsg.Request = CMD_MAC_ADDRESS_WRITE;
> +  SetupMsg.Value = 0;
> +  SetupMsg.Index = 0;
> +  SetupMsg.Length = PXE_HWADDR_LEN_ETHER;
> +
> +  //
> +  //  Read the PHY register
> +  //
> +  Status = Ax88772UsbCommand ( pNicDevice,
> +                               &SetupMsg,
> +                               pMacAddress );
> +
> +  //
> +  // Return the operation status
> +  //
> +  return Status;
> +}
> +
> +/**
> +  Clear the multicast hash table
> +
> +  @param [in] pNicDevice       Pointer to the NIC_DEVICE structure
> +
> +**/
> +VOID
> +Ax88772MulticastClear (
> +  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 ::Ax88772Crc 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
> +Ax88772MulticastSet (
> +  IN NIC_DEVICE * pNicDevice,
> +  IN UINT8 * pMacAddress
> +  )
> +{
> +  UINT32 Crc;
> +
> +  //
> +  //  Compute the CRC on the destination address
> +  //
> +  Crc = Ax88772Crc ( pMacAddress ) >> 26;
> +
> +  //
> +  //  Set the bit corresponding to the destination address
> +  //
> +  pNicDevice->MulticastHash [ Crc >> 3 ] |= ( 1<< (Crc& 7));
> +
> +}
> +
> +/**
> +  Start the link negotiation
> +
> +  This routine calls ::Ax88772PhyWrite 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
> +Ax88772NegotiateLinkStart (
> +  IN NIC_DEVICE * pNicDevice
> +  )
> +{
> +  UINT16 Control;
> +  EFI_STATUS Status;
> +
> +  //
> +  // Set the supported capabilities.
> +  //
> +  Status = Ax88772PhyWrite ( pNicDevice,
> +                             PHY_ANAR,
> +                             AN_CSMA_CD
> +                             | AN_TX_FDX | AN_TX_HDX
> +                             | AN_10_FDX | AN_10_HDX | AN_FCS );
> +  if ( !EFI_ERROR ( Status )) {
> +    //
> +    // Set the link speed and duplex
> +    //
> +    Control = BMCR_AUTONEGOTIATION_ENABLE
> +            | BMCR_RESTART_AUTONEGOTIATION;
> +    if ( pNicDevice->b100Mbps ) {
> +      Control |= BMCR_100MBPS;
> +    }
> +    if ( pNicDevice->bFullDuplex ) {
> +      Control |= BMCR_FULL_DUPLEX;
> +    }
> +    Status = Ax88772PhyWrite ( pNicDevice, PHY_BMCR, Control );
> +
> +    if (!EFI_ERROR(Status))
> +        gBS->Stall(3000000);
> +  }
> +  return Status;
> +}
> +
> +
> +
> +/**
> +  Complete the negotiation of the PHY link
> +
> +  This routine calls ::Ax88772PhyRead 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
> +Ax88772NegotiateLinkComplete (
> +  IN NIC_DEVICE * pNicDevice,
> +  IN OUT UINTN * pPollCount,
> +  OUT BOOLEAN * pbComplete,
> +  OUT BOOLEAN * pbLinkUp,
> +  OUT BOOLEAN * pbHiSpeed,
> +  OUT BOOLEAN * pbFullDuplex
> +  )
> +{
> +  UINT16 Mask;
> +  UINT16 PhyData;
> +  EFI_STATUS  Status;
> +
> +  //
> +  //  Determine if the link is up.
> +  //
> +  *pbComplete = FALSE;
> +
> +  //
> +  //  Get the link status
> +  //
> +  Status = Ax88772PhyRead ( pNicDevice,
> +                            PHY_BMSR,
> +                            &PhyData );
> +
> +  if ( !EFI_ERROR ( Status )) {

Success handling.

> +    *pbLinkUp = (BOOLEAN)( 0 != ( PhyData & BMSR_LINKST ));
> +    if ( 0 == *pbLinkUp ) {
> +    } else {
> +      *pbComplete = (BOOLEAN)( 0 != ( PhyData & 0x20 ));
> +      if ( 0 == *pbComplete ) {
> +      } else {
> +        Status = Ax88772PhyRead ( pNicDevice,
> +                                  PHY_ANLPAR,
> +                                  &PhyData );
> +        if ( !EFI_ERROR ( Status )) {
> +          //
> +          //  Autonegotiation is complete
> +          //  Determine the link speed.
> +          //
> +          *pbHiSpeed = (BOOLEAN)( 0 != ( PhyData & ( AN_TX_FDX | AN_TX_HDX )));
> +
> +          //
> +          //  Determine the link duplex.
> +          //
> +          Mask = ( *pbHiSpeed ) ? AN_TX_FDX : AN_10_FDX;
> +          *pbFullDuplex = (BOOLEAN)( 0 != ( PhyData & Mask ));
> +        }
> +      }
> +    }
> +  } else {
> +  }
> +  return Status;
> +}
> +
> +
> +/**
> +  Read a register from the PHY
> +
> +  This routine calls ::Ax88772UsbCommand 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
> +Ax88772PhyRead (
> +  IN NIC_DEVICE * pNicDevice,
> +  IN UINT8 RegisterAddress,
> +  IN OUT UINT16 * pPhyData
> +  )
> +{
> +  USB_DEVICE_REQUEST SetupMsg;
> +  EFI_STATUS Status;
> +
> +  //
> +  //  Request access to the PHY
> +  //
> +  SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                       | USB_TARGET_DEVICE;
> +  SetupMsg.Request = CMD_PHY_ACCESS_SOFTWARE;
> +  SetupMsg.Value = 0;
> +  SetupMsg.Index = 0;
> +  SetupMsg.Length = 0;
> +  Status = Ax88772UsbCommand ( pNicDevice,
> +                               &SetupMsg,
> +                               NULL );
> +  if ( !EFI_ERROR ( Status )) {
> +    //
> +    //  Read the PHY register address.
> +    //
> +    SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
> +                         | USB_REQ_TYPE_VENDOR
> +                         | USB_TARGET_DEVICE;
> +    SetupMsg.Request = CMD_PHY_REG_READ;
> +    SetupMsg.Value = pNicDevice->PhyId;
> +    SetupMsg.Index = RegisterAddress;
> +    SetupMsg.Length = sizeof ( *pPhyData );
> +    Status = Ax88772UsbCommand ( pNicDevice,
> +                                 &SetupMsg,
> +                                 pPhyData );
> +    if ( !EFI_ERROR ( Status )) {
> +
> +      //
> +      //  Release the PHY to the hardware
> +      //
> +      SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                           | USB_TARGET_DEVICE;
> +      SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE;
> +      SetupMsg.Value = 0;
> +      SetupMsg.Index = 0;
> +      SetupMsg.Length = 0;
> +      Status = Ax88772UsbCommand ( pNicDevice,
> +                                   &SetupMsg,
> +                                   NULL );
> +    }
> +  }
> +
> +  //
> +  //  Return the operation status.
> +  //
> +  return Status;
> +}
> +
> +
> +/**
> +  Write to a PHY register
> +
> +  This routine calls ::Ax88772UsbCommand 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
> +Ax88772PhyWrite (
> +  IN NIC_DEVICE * pNicDevice,
> +  IN UINT8 RegisterAddress,
> +  IN UINT16 PhyData
> +  )
> +{
> +  USB_DEVICE_REQUEST SetupMsg;
> +  EFI_STATUS Status;
> +
> +  //
> +  //  Request access to the PHY
> +  //
> +  SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                       | USB_TARGET_DEVICE;
> +  SetupMsg.Request = CMD_PHY_ACCESS_SOFTWARE;
> +  SetupMsg.Value = 0;
> +  SetupMsg.Index = 0;
> +  SetupMsg.Length = 0;
> +  Status = Ax88772UsbCommand ( pNicDevice,
> +                               &SetupMsg,
> +                               NULL );
> +  if ( !EFI_ERROR ( Status )) {
> +    //
> +    //  Write the PHY register
> +    //
> +    SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                         | USB_TARGET_DEVICE;
> +    SetupMsg.Request = CMD_PHY_REG_WRITE;
> +    SetupMsg.Value = pNicDevice->PhyId;
> +    SetupMsg.Index = RegisterAddress;
> +    SetupMsg.Length = sizeof ( PhyData );
> +    Status = Ax88772UsbCommand ( pNicDevice,
> +                                 &SetupMsg,
> +                                 &PhyData );
> +    if ( !EFI_ERROR ( Status )) {
> +
> +      //
> +      //  Release the PHY to the hardware
> +      //
> +      SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                           | USB_TARGET_DEVICE;
> +      SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE;
> +      SetupMsg.Value = 0;
> +      SetupMsg.Index = 0;
> +      SetupMsg.Length = 0;
> +      Status = Ax88772UsbCommand ( pNicDevice,
> +                                   &SetupMsg,
> +                                   NULL );
> +    }
> +  }
> +
> +  //
> +  //  Return the operation status.
> +  //
> +  return Status;
> +}
> +
> +
> +/**
> +  Reset the AX88772
> +
> +  This routine uses ::Ax88772UsbCommand to reset the network
> +  adapter.  This routine also uses ::Ax88772PhyWrite 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
> +Ax88772Reset (
> +  IN NIC_DEVICE * pNicDevice
> +  )
> +{
> +  USB_DEVICE_REQUEST SetupMsg;
> +  EFI_STATUS Status;
> +  EFI_USB_IO_PROTOCOL *pUsbIo;
> +
> +  pUsbIo = pNicDevice->pUsbIo;
> +
> +  SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                           | USB_TARGET_DEVICE;
> +  SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE;
> +  SetupMsg.Value = 0;
> +  SetupMsg.Index = 0;
> +  SetupMsg.Length = 0;
> +  Status = Ax88772UsbCommand ( pNicDevice,
> +                               &SetupMsg,
> +                               NULL );
> +
> +  if (EFI_ERROR(Status)) goto err;
> +
> +  SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                          | USB_TARGET_DEVICE;
> +  SetupMsg.Request = CMD_PHY_SELECT;
> +  SetupMsg.Value = SPHY_PSEL;
> +  SetupMsg.Index = 0;
> +  SetupMsg.Length = 0;
> +  Status = Ax88772UsbCommand ( pNicDevice,
> +                               &SetupMsg,
> +                               NULL );
> +
> +  if (EFI_ERROR(Status)) goto err;
> +
> +  SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                       | USB_TARGET_DEVICE;
> +  SetupMsg.Request = CMD_RESET;
> +  SetupMsg.Value = SRR_IPRL ;
> +  SetupMsg.Index = 0;
> +  SetupMsg.Length = 0;
> +  Status = Ax88772UsbCommand ( pNicDevice,
> +                               &SetupMsg,
> +                               NULL );
> +
> +  if (EFI_ERROR(Status)) goto err;
> +
> +  SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                       | USB_TARGET_DEVICE;
> +  SetupMsg.Request = CMD_RESET;
> +  SetupMsg.Value = SRR_IPPD | SRR_IPRL ;
> +  SetupMsg.Index = 0;
> +  SetupMsg.Length = 0;
> +  Status = Ax88772UsbCommand ( pNicDevice,
> +                               &SetupMsg,
> +                               NULL );
> +
> +  gBS->Stall ( 200000 );
> +
> +  if (EFI_ERROR(Status)) goto err;
> +
> +  SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                       | USB_TARGET_DEVICE;
> +  SetupMsg.Request = CMD_RESET;
> +  SetupMsg.Value =  SRR_IPRL  ;
> +  SetupMsg.Index = 0;
> +  SetupMsg.Length = 0;
> +  Status = Ax88772UsbCommand ( pNicDevice,
> +                               &SetupMsg,
> +                               NULL );
> +
> +  gBS->Stall ( 200000 );
> +
> +  if (EFI_ERROR(Status)) goto err;
> +
> +  SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                       | USB_TARGET_DEVICE;
> +  SetupMsg.Request = CMD_RESET;
> +  SetupMsg.Value = 0;
> +  SetupMsg.Index = 0;
> +  SetupMsg.Length = 0;
> +  Status = Ax88772UsbCommand ( pNicDevice,
> +                               &SetupMsg,
> +                               NULL );
> +
> +  if (EFI_ERROR(Status)) goto err;
> +
> +  SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                       | USB_TARGET_DEVICE;
> +  SetupMsg.Request = CMD_PHY_SELECT;
> +  SetupMsg.Value = SPHY_PSEL;
> +  SetupMsg.Index = 0;
> +  SetupMsg.Length = 0;
> +  Status = Ax88772UsbCommand ( pNicDevice,
> +                               &SetupMsg,
> +                               NULL );
> +
> +  if (EFI_ERROR(Status)) goto err;
> +
> +  SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                       | USB_TARGET_DEVICE;
> +  SetupMsg.Request = CMD_RESET;
> +  SetupMsg.Value =  SRR_IPRL | SRR_BZ | SRR_BZTYPE;
> +  SetupMsg.Index = 0;
> +  SetupMsg.Length = 0;
> +  Status = Ax88772UsbCommand ( pNicDevice,
> +                               &SetupMsg,
> +                               NULL );
> +
> +  if (EFI_ERROR(Status)) goto err;
> +
> +  SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                       | USB_TARGET_DEVICE;
> +  SetupMsg.Request = CMD_RX_CONTROL_WRITE;
> +  SetupMsg.Value = 0;
> +  SetupMsg.Index = 0;
> +  SetupMsg.Length = 0;
> +  Status = Ax88772UsbCommand ( pNicDevice,
> +                               &SetupMsg,
> +                               NULL );
> +
> +  if (EFI_ERROR(Status)) goto err;
> +
> +  if (!pNicDevice->Flag772A) {
> +    SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                         | USB_TARGET_DEVICE;
> +    SetupMsg.Request = CMD_RXQTC;
> +#if RXTHOU
> +    /*size cannot exceed 3K*/
> +    //SetupMsg.Value = 0x0;
> +    //SetupMsg.Index = 0x8001;
> +    /*size cannot exceed 16K*/
> +    SetupMsg.Value = 0x8300;
> +    SetupMsg.Index = 0x8500;
> +    /*size cannot exceed 32K*/
> +    //SetupMsg.Value = 0x8784;
> +    //SetupMsg.Index = 0x8A00;
> +    SetupMsg.Length = 0;
> +#else
> +    SetupMsg.Value = 0x8000;
> +    SetupMsg.Index = 0x8001;
> +#endif
> +    Status = Ax88772UsbCommand ( pNicDevice,
> +                                 &SetupMsg,
> +                                 NULL );
> +  }
> +err:
> +  return Status;
> +}
> +
> +/**
> +  Enable or disable the receiver
> +
> +  This routine calls ::Ax88772UsbCommand to update the
> +  receiver state.  This routine also calls ::Ax88772MacAddressSet
> +  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
> +Ax88772RxControl (
> +  IN NIC_DEVICE * pNicDevice,
> +  IN UINT32 RxFilter
> +  )
> +{
> +  UINT16 MediumStatus;
> +  UINT16 RxControl;
> +  USB_DEVICE_REQUEST SetupMsg;
> +  EFI_STATUS Status = EFI_SUCCESS;
> +
> +  //
> +  // Enable the receiver if something is to be received
> +  //
> +  if ( 0 != RxFilter ) {

No Jeopardy tests.

> +    //
> +    //  Enable the receiver
> +    //
> +    SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
> +                         | USB_REQ_TYPE_VENDOR
> +                         | USB_TARGET_DEVICE;
> +    SetupMsg.Request = CMD_MEDIUM_STATUS_READ;
> +    SetupMsg.Value = 0;
> +    SetupMsg.Index = 0;
> +    SetupMsg.Length = sizeof ( MediumStatus );
> +    Status = Ax88772UsbCommand ( pNicDevice,
> +                                 &SetupMsg,
> +                                 &MediumStatus );
> +    if ( !EFI_ERROR ( Status )) {
> +      if ( 0 == ( MediumStatus & MS_RE )) {
> +        MediumStatus |= MS_RE | MS_ONE;
> +
> +        if ( pNicDevice->bFullDuplex )
> +          MediumStatus |= MS_TFC | MS_RFC | MS_FD;
> +        else
> +          MediumStatus &= ~(MS_TFC | MS_RFC | MS_FD);
> +
> +        if ( pNicDevice->b100Mbps )
> +          MediumStatus |= MS_PS;
> +        else
> +          MediumStatus &= ~MS_PS;
> +
> +        SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                             | USB_TARGET_DEVICE;
> +        SetupMsg.Request = CMD_MEDIUM_STATUS_WRITE;
> +        SetupMsg.Value = MediumStatus;
> +        SetupMsg.Index = 0;
> +        SetupMsg.Length = 0;
> +        Status = Ax88772UsbCommand ( pNicDevice,
> +                                     &SetupMsg,
> +                                     NULL );
> +
> +        if (EFI_ERROR(Status))
> +              goto EXIT;
> +      }
> +    } else {
> +        goto EXIT;
> +    }
> +  }
> +  RxControl = RXC_SO;
> +  if (!pNicDevice->Flag772A)
> +    RxControl |= RXC_RH1M;
> +
> +  //
> +  //  Enable multicast if requested
> +  //
> +  if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST )) {
> +      RxControl |= RXC_AM;
> +      //
> +      //  Update the multicast hash table
> +      //
> +      SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                           | USB_TARGET_DEVICE;
> +      SetupMsg.Request = CMD_MULTICAST_HASH_WRITE;
> +      SetupMsg.Value = 0;
> +      SetupMsg.Index = 0;
> +      SetupMsg.Length = sizeof ( pNicDevice ->MulticastHash );
> +      Status = Ax88772UsbCommand ( pNicDevice,
> +                                   &SetupMsg,
> +                                   &pNicDevice->MulticastHash );
> +
> +      if (EFI_ERROR(Status))
> +              goto EXIT;
> +  }
> +
> +  //
> +  //  Enable all multicast if requested
> +  //
> +  if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST )) {
> +      RxControl |= RXC_AMALL;
> +  }
> +
> +  //
> +  //  Enable broadcast if requested
> +  //
> +  if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST )) {
> +      RxControl |= RXC_AB;
> +  }
> +
> +  //
> +  //  Enable promiscuous mode if requested
> +  //
> +  if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS )) {
> +      RxControl |= RXC_PRO;
> +  }
> +
> +  //
> +  //  Update the receiver control
> +  //
> +  if (pNicDevice->CurRxControl != RxControl) {
> +    SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                         | USB_TARGET_DEVICE;
> +    SetupMsg.Request = CMD_RX_CONTROL_WRITE;
> +#if RXTHOU
> +    if (pNicDevice->Flag772A)
> +      RxControl |= 0x0300;
> +#endif
> +    if (pNicDevice->Flag772A)
> +      RxControl &= ~(RXC_MFB);
> +    SetupMsg.Value = RxControl;
> +    SetupMsg.Index = 0;
> +    SetupMsg.Length = 0;
> +    Status = Ax88772UsbCommand ( pNicDevice,
> +                                 &SetupMsg,
> +                                 NULL );
> +    if ( !EFI_ERROR ( Status ))
> +      pNicDevice->CurRxControl = RxControl;
> +  }
> +
> +  //
> +  // Return the operation status
> +  //
> +EXIT:
> +  return Status;
> +}
> +
> +
> +
> +EFI_STATUS
> +Ax88772ReloadSrom  (
> +  IN NIC_DEVICE * pNicDevice
> +  )
> +{
> +  USB_DEVICE_REQUEST SetupMsg;
> +  EFI_STATUS Status;
> +
> +  //
> +  //  Read a value from the SROM
> +  //
> +  SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                       | USB_TARGET_DEVICE;
> +
> +  SetupMsg.Request = CMD_WRITE_GPIOS;
> +  SetupMsg.Value = 0x80;
> +  SetupMsg.Index = 0;
> +  SetupMsg.Length = 0 ;
> +  Status = Ax88772UsbCommand ( pNicDevice,
> +                               &SetupMsg,
> +                               NULL );
> +
> +  if (EFI_SUCCESS == Status)
> +          gBS->Stall(500000);
> +
> +  return Status;
> +
> +}
> +
> +
> +/**
> +  Read an SROM location
> +
> +  This routine calls ::Ax88772UsbCommand 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
> +Ax88772SromRead (
> +  IN NIC_DEVICE * pNicDevice,
> +  IN UINT32 Address,
> +  OUT UINT16 * pData
> +  )
> +{
> +
> +  USB_DEVICE_REQUEST SetupMsg;
> +  EFI_STATUS Status;
> +
> +  //
> +  //  Read a value from the SROM
> +  //
> +  SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
> +                       | USB_REQ_TYPE_VENDOR
> +                       | USB_TARGET_DEVICE;
> +  SetupMsg.Request = CMD_SROM_READ;
> +  SetupMsg.Value = (UINT16) Address;
> +  SetupMsg.Index = 0;
> +  SetupMsg.Length = sizeof ( *pData );
> +  Status = Ax88772UsbCommand ( pNicDevice,
> +                               &SetupMsg,
> +                               pData );
> +
> +  //
> +  // Return the operation status
> +  //
> +  return Status;
> +}
> +
> +EFI_STATUS
> +Ax88772EnableSromWrite  (
> +  IN NIC_DEVICE * pNicDevice
> +  )
> +{
> +  USB_DEVICE_REQUEST SetupMsg;
> +  EFI_STATUS Status;
> +
> +  //
> +  //  Read a value from the SROM
> +  //
> +  SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                       | USB_TARGET_DEVICE;
> +
> +  SetupMsg.Request = CMD_SROM_WRITE_EN;
> +  SetupMsg.Value = 0;
> +  SetupMsg.Index = 0;
> +  SetupMsg.Length = 0 ;
> +  Status = Ax88772UsbCommand ( pNicDevice,
> +                               &SetupMsg,
> +                               NULL );
> +
> +  if (EFI_SUCCESS == Status)
> +          gBS->Stall(500000);
> +
> +  return Status;
> +
> +}
> +
> +
> +EFI_STATUS
> +Ax88772DisableSromWrite  (
> +  IN NIC_DEVICE * pNicDevice
> +  )
> +{
> +  USB_DEVICE_REQUEST SetupMsg;
> +  EFI_STATUS Status;
> +
> +  //
> +  //  Read a value from the SROM
> +  //
> +  SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                       | USB_TARGET_DEVICE;
> +
> +  SetupMsg.Request = CMD_SROM_WRITE_DIS;
> +  SetupMsg.Value = 0;
> +  SetupMsg.Index = 0;
> +  SetupMsg.Length = 0;
> +  Status = Ax88772UsbCommand ( pNicDevice,
> +                      &SetupMsg,
> +                      NULL );
> +
> +  if (EFI_SUCCESS == Status)
> +          gBS->Stall(500000);
> +
> +  return Status;
> +
> +}
> +
> +/**
> +  Write an SROM location
> +
> +  This routine calls ::Ax88772UsbCommand 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
> +Ax88772SromWrite (
> +  IN NIC_DEVICE * pNicDevice,
> +  IN UINT32 Address,
> +  IN UINT16 * pData
> +  )
> +{
> +
> +  USB_DEVICE_REQUEST SetupMsg;
> +  EFI_STATUS Status;
> +
> +  SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                       | USB_TARGET_DEVICE;
> +
> +  SetupMsg.Request = CMD_SROM_WRITE;
> +  SetupMsg.Value = (UINT16) Address;
> +  SetupMsg.Index = (UINT16) (*pData);
> +  SetupMsg.Length = 0;
> +
> +  Status = Ax88772UsbCommand ( pNicDevice,
> +                               &SetupMsg,
> +                               NULL );
> +
> +  //
> +  // Return the operation status
> +  //
> +  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
> +Ax88772UsbCommand (
> +  IN NIC_DEVICE * pNicDevice,
> +  IN USB_DEVICE_REQUEST * pRequest,
> +  IN OUT VOID * pBuffer
> +  )
> +{
> +  UINT32 CmdStatus;
> +  EFI_USB_DATA_DIRECTION Direction;
> +  EFI_USB_IO_PROTOCOL * pUsbIo;
> +  EFI_STATUS Status;
> +
> +  //
> +  // 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;
> +  Status = pUsbIo->UsbControlTransfer ( pUsbIo,
> +                                        pRequest,
> +                                        Direction,
> +                                        USB_BUS_TIMEOUT,
> +                                        pBuffer,
> +                                        pRequest->Length,
> +                                        &CmdStatus );
> +
> +  //
> +  // Determine the operation status
> +  //
> +  if ( !EFI_ERROR ( Status )) {
> +    Status = CmdStatus;
> +  } else {
> +    //
> +    // Only use status values associated with the Simple Network protocol
> +    //
> +    if ( EFI_TIMEOUT == Status ) {
> +      Status = EFI_DEVICE_ERROR;
> +    }
> +  }
> +
> +  //
> +  // Return the operation status
> +  //
> +  return Status;
> +}
> +
> +BOOLEAN
> +Ax88772GetLinkStatus (
> +  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 & 0x800000)? FALSE : TRUE;
> +
> +}
> +
> +#if RXTHOU
> +EFI_STATUS
> +Ax88772BulkIn(
> +  IN NIC_DEVICE * pNicDevice
> +)
> +{
> +  int i;
> +  UINTN LengthInBytes = 0;
> +  UINTN TMP_LENG = AX88772_MAX_BULKIN_SIZE;
> +  UINTN ORI_TMP_LENG = 0;
> +  EFI_STATUS Status = EFI_DEVICE_ERROR;
> +  EFI_USB_IO_PROTOCOL *pUsbIo;
> +  UINT32 TransferStatus = 0;
> +  UINT16 tmpPktCnt = 0;
> +  UINT16 * tmpHdr = (UINT16 *)pNicDevice->pBulkInbuf;
> +  USB_DEVICE_REQUEST SetupMsg;
> +
> +  pUsbIo = pNicDevice->pUsbIo;
> +  for ( i = 0 ; i < (AX88772_MAX_BULKIN_SIZE / 512) && pUsbIo != NULL; i++) {
> +    VOID* tmpAddr = 0;
> +
> +    tmpPktCnt = 0;
> +    tmpAddr = (VOID*) &pNicDevice->pBulkInbuf[LengthInBytes];
> +    ORI_TMP_LENG = TMP_LENG;
> +    Status = pUsbIo->UsbBulkTransfer ( pUsbIo,
> +                          USB_ENDPOINT_DIR_IN | BULK_IN_ENDPOINT,
> +                          tmpAddr,
> +                          &TMP_LENG,
> +                          BULKIN_TIMEOUT,
> +                          &TransferStatus );
> +
> +    if (ORI_TMP_LENG == TMP_LENG) {
> +      Status = EFI_NOT_READY;
> +      goto no_pkt;
> +    }
> +
> +    if (( !EFI_ERROR ( Status )) &&
> +        ( !EFI_ERROR ( TransferStatus )) &&
> +        TMP_LENG != 0) {
> +      LengthInBytes += TMP_LENG;
> +      if ((TMP_LENG % 512) != 0) {
> +        goto done;
> +      }
> +    } else if (( !EFI_ERROR ( Status )) &&
> +               ( !EFI_ERROR ( TransferStatus )) &&
> +               (TMP_LENG == 0)) {
> +      Status = EFI_NOT_READY;
> +      goto done;
> +    } else if (EFI_TIMEOUT == Status && EFI_USB_ERR_TIMEOUT == TransferStatus) {
> +      SetupMsg.RequestType = USB_REQ_TYPE_STANDARD | 0x02;
> +      SetupMsg.Request = 0x01;
> +      SetupMsg.Value =  0;
> +      SetupMsg.Index = 0x82;
> +      SetupMsg.Length = 0;
> +      Status = Ax88772UsbCommand ( pNicDevice,
> +                                   &SetupMsg,
> +                                   NULL );
> +      Status = EFI_NOT_READY;
> +      goto done;
> +    } else {
> +      Status = EFI_DEVICE_ERROR;
> +      goto done;
> +    }
> +  }
> +done:
> +  if (LengthInBytes != 0) {
> +    UINT16 tmpLen;
> +    UINT16 tmpLenBar;
> +    UINT16 tmpTotalLen = 0;
> +    UINTN TotalLen = LengthInBytes;
> +
> +    do {
> +      tmpLen = (*tmpHdr) & 0x7FF;
> +      tmpLenBar = *(tmpHdr + 1);
> +      tmpTotalLen = ((tmpLen + 4 + 1) & 0xfffe);
> +
> +      if ((tmpLen & 0x7FF) + (tmpLenBar & 0x7FF) == 0x7FF) {
> +        tmpPktCnt++;
> +      } else {
> +        if ( tmpPktCnt != 0) {
> +          break;
> +        }
> +        Status = EFI_NOT_READY;
> +        goto no_pkt;
> +      }
> +      tmpHdr += (tmpTotalLen / 2);
> +      TotalLen -= tmpTotalLen;
> +    } while (TotalLen > 0);
> +
> +  if (LengthInBytes >= 1000 && tmpPktCnt != 0) {
> +    if ((pNicDevice->rxburst) == 1) {
> +      SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                           | USB_TARGET_DEVICE;
> +      SetupMsg.Request = CMD_RESET;
> +      SetupMsg.Value =  SRR_IPRL;
> +      SetupMsg.Index = 0;
> +      SetupMsg.Length = 0;
> +      Ax88772UsbCommand ( pNicDevice,
> +                          &SetupMsg,
> +                          NULL );
> +    }
> +
> +    if (pNicDevice->rxburst < 2)
> +    pNicDevice->rxburst++;
> +
> +  } else {
> +    if (pNicDevice->rxburst >= 2) {
> +      SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> +                           | USB_TARGET_DEVICE;
> +      SetupMsg.Request = CMD_RESET;
> +      SetupMsg.Value =  SRR_IPRL| SRR_BZ | SRR_BZTYPE;
> +      SetupMsg.Index = 0;
> +      SetupMsg.Length = 0;
> +      Ax88772UsbCommand ( pNicDevice,
> +                          &SetupMsg,
> +                          NULL );
> +      }
> +      pNicDevice->rxburst = 0;
> +    }
> +  }
> +
> +  if (tmpPktCnt != 0) {
> +    pNicDevice->PktCnt = tmpPktCnt;
> +    pNicDevice->pCurPktHdrOff = pNicDevice->pBulkInbuf;
> +    pNicDevice->pCurPktOff = pNicDevice->pBulkInbuf + 4;
> +    Status = EFI_SUCCESS;
> +  }
> +
> +no_pkt:
> +  return Status;
> +}
> +#else
> +EFI_STATUS
> +Ax88772BulkIn(
> +  IN NIC_DEVICE * pNicDevice
> +)
> +{
> +  int i;
> +  UINTN LengthInBytes = 0;
> +  UINTN TMP_LENG = AX88772_MAX_BULKIN_SIZE;
> +  UINTN ORI_TMP_LENG = 0;
> +  UINTN CURBufSize = AX88772_MAX_BULKIN_SIZE;
> +  EFI_STATUS Status = EFI_DEVICE_ERROR;
> +  EFI_USB_IO_PROTOCOL *pUsbIo;
> +  UINT32 TransferStatus = 0;
> +  UINT16 tmpPktCnt = 0;
> +  UINT16 * tmpHdr = (UINT16 *)pNicDevice->pBulkInbuf;
> +
> +  pUsbIo = pNicDevice->pUsbIo;
> +  for ( i = 0 ; i < (AX88772_MAX_BULKIN_SIZE / 512) && pUsbIo != NULL; i++) {
> +    VOID* tmpAddr = 0;
> +
> +    tmpPktCnt = 0;
> +    tmpAddr = (VOID*) &pNicDevice->pBulkInbuf[LengthInBytes];
> +    ORI_TMP_LENG = TMP_LENG;
> +    Status = pUsbIo->UsbBulkTransfer ( pUsbIo,
> +                          USB_ENDPOINT_DIR_IN | BULK_IN_ENDPOINT,
> +                          tmpAddr,
> +                          &TMP_LENG,
> +                          BULKIN_TIMEOUT,
> +                          &TransferStatus );
> +
> +    if (ORI_TMP_LENG == TMP_LENG) {
> +      Status = EFI_NOT_READY;
> +      goto no_pkt;
> +    }
> +
> +    if (( !EFI_ERROR ( Status )) &&
> +        ( !EFI_ERROR ( TransferStatus )) &&
> +        TMP_LENG != 0) {
> +      UINT16 tmpLen;
> +      UINT16 tmpLenBar;
> +      UINT16 tmpTotalLen = 0;
> +
> +      LengthInBytes += TMP_LENG;
> +      CURBufSize = CURBufSize - TMP_LENG;
> +      TMP_LENG = CURBufSize;
> +      do {
> +        tmpLen = *tmpHdr;
> +        tmpLenBar = *(tmpHdr + 1);
> +        tmpTotalLen += ((tmpLen + 4 + 1) & 0xfffe);
> +
> +        if (((tmpLen ^ tmpLenBar) == 0xffff))  {
> +          if (tmpTotalLen == LengthInBytes) {
> +            tmpPktCnt++;
> +            Status = EFI_SUCCESS;
> +            goto done;
> +          } else if (tmpTotalLen > LengthInBytes) {
> +            break;
> +          }
> +        } else if (((tmpLen ^ tmpLenBar) != 0xffff)) {
> +          if ( tmpPktCnt != 0) {
> +            Status = EFI_SUCCESS;
> +            goto done;
> +          }
> +          Status = EFI_NOT_READY;
> +          goto no_pkt;
> +        }
> +        tmpHdr += (tmpTotalLen / 2);
> +        tmpPktCnt++;
> +      }while (tmpTotalLen < LengthInBytes);
> +    } else if (( !EFI_ERROR ( Status )) &&
> +               ( !EFI_ERROR ( TransferStatus )) &&
> +               (TMP_LENG == 0)) {
> +      if ( tmpPktCnt != 0) {
> +        Status = EFI_SUCCESS;
> +        goto done;
> +      }
> +      Status = EFI_NOT_READY;
> +      goto no_pkt;
> +    } else if (EFI_TIMEOUT == Status && EFI_USB_ERR_TIMEOUT == TransferStatus) {
> +      if ( tmpPktCnt != 0) {
> +        Status = EFI_SUCCESS;
> +        goto done;
> +      }
> +      Status = EFI_NOT_READY;
> +      goto no_pkt;
> +    } else {
> +      if ( tmpPktCnt != 0) {
> +        Status = EFI_SUCCESS;
> +        goto done;
> +      }
> +      Status = EFI_DEVICE_ERROR;
> +      goto no_pkt;
> +    }
> +  }
> +done:
> +  pNicDevice->PktCnt = tmpPktCnt;
> +  pNicDevice->pCurPktHdrOff = pNicDevice->pBulkInbuf;
> +  pNicDevice->pCurPktOff = pNicDevice->pBulkInbuf + 4;
> +no_pkt:
> +  return Status;
> +}
> +#endif
> diff --git a/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/ComponentName.c b/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/ComponentName.c
> new file mode 100644
> index 000000000000..8e2ba86f945e
> --- /dev/null
> +++ b/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/ComponentName.c
> @@ -0,0 +1,246 @@
> +/** @file
> +  UEFI Component Name(2) protocol implementation.
> +
> +  Copyright (c) 2011, Intel Corporation. All rights reserved.
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "Ax88772.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 AX88772B Ethernet Driver 2.8.0"},
> +  {NULL,  NULL}
> +};
> +
> +
> +/**
> +  Controller name table declaration
> +**/
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
> +mControllerNameTable[] = {
> +  {"eng;en", L"ASIX AX88772B USB Fast 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

Same as for 3/4.

> +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;
> +
> +  //
> +  // Set the controller name
> +  //
> +  *ppControllerName = L"ASIX AX88772B USB Fast Ethernet Controller";
> +  Status = EFI_SUCCESS;
> +
> +  //
> +  // Return the operation status
> +  //
> +
> +  return Status;
> +}
> +
> +#endif
> diff --git a/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/DriverBinding.c b/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/DriverBinding.c
> new file mode 100644
> index 000000000000..5edb7cbb2630
> --- /dev/null
> +++ b/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/DriverBinding.c
> @@ -0,0 +1,637 @@
> +/** @file
> +  Implement the driver binding protocol for Asix AX88772 Ethernet driver.
> +
> +  Copyright (c) 2011-2013, Intel Corporation. All rights reserved.
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "Ax88772.h"
> +#include <Library/MemoryAllocationLib.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 ) {
> +        if (PRODUCT_AX88772B_ID != Device.IdProduct) {
> +        } else if (PRODUCT_AX88772B_ASUS_ID == Device.IdProduct) {
> +        } else if (PRODUCT_AX88772A_ID == Device.IdProduct) {
> +        } else if (PRODUCT_ID == Device.IdProduct) {
> +        } else {
> +          Status = EFI_UNSUPPORTED;
> +        }
> +      } else if ( VENDOR_AX88772B_LENOVO_ID == Device.IdVendor ) {
> +        if (PRODUCT_AX88772B_LENOVO_ID != Device.IdProduct) {
> +          Status = EFI_UNSUPPORTED;
> +        }
> +      } else {
> +        Status = EFI_UNSUPPORTED;
> +      }
> +    }
> +
> +    //
> +    //  Done with the USB stack
> +    //
> +    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;
> +  EFI_USB_DEVICE_DESCRIPTOR Device;
> +
> +  //
> +  //  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;
> +  }
> +
> +  pNicDevice->Flag772A = FALSE;
> +  pNicDevice->pUsbIo->UsbGetDeviceDescriptor ( pNicDevice->pUsbIo, &Device );
> +  if ((PRODUCT_AX88772A_ID == Device.IdProduct) ||
> +      (PRODUCT_ID == Device.IdProduct))
> +    pNicDevice->Flag772A = TRUE;
> +  //
> +  //  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;
> +  UINTN Index;
> +  EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork;
> +  EFI_STATUS Status = EFI_SUCCESS;
> +  NIC_DEVICE *pNicDevice;
> +
> +  //
> +  // 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
> +                       );
> +
> +    if (EFI_ERROR(Status)){ }
> +
> +    Status = gBS->CloseProtocol (
> +                       Controller,
> +                       &gEfiUsbIoProtocolGuid,
> +                       pThis->DriverBindingHandle,
> +                       Controller
> +                       );
> +
> +    if (EFI_ERROR(Status)){ }
> +
> +    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
> +};
> +
> +
> +/**
> +  Ax88772 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;
> +}
> +
> +
> +/**
> +Ax88772 driver entry point.
> +
> +@param [in] ImageHandle       Handle for the image.
> +@param [in] pSystemTable      Address of the system table.
> +
> +@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
> +             );
> +  if ( !EFI_ERROR ( Status )) { }
> +  return Status;
> +}
> diff --git a/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/SimpleNetwork.c b/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/SimpleNetwork.c
> new file mode 100644
> index 000000000000..b4627092a676
> --- /dev/null
> +++ b/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772c/SimpleNetwork.c
> @@ -0,0 +1,1612 @@
> +/** @file
> +  Provides the Simple Network functions.
> +
> +  Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "Ax88772.h"

Include all headers used by file, Ax88772.h should include only those
headers needed for its definitions.

/
    Leif

> +#include <Library/MemoryAllocationLib.h>
> +/**
> +  This function updates the filtering on the receiver.
> +
> +  This support routine calls ::Ax88772MacAddressSet to update
> +  the MAC address.  This routine then rebuilds the multicast
> +  hash by calling ::Ax88772MulticastClear and ::Ax88772MulticastSet.
> +  Finally this routine enables the receiver by calling
> +  ::Ax88772RxControl.
> +
> +  @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 (

  reply	other threads:[~2020-05-12 13:22 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-10 11:15 [edk2-platform][PATCH v1 0/4] Update ASIX USB Networking drivers Samer El-Haj-Mahmoud
2020-05-10 11:15 ` [edk2-platform][PATCH v1 1/4] Silicon/AsixPkg: Create AsixPkg Samer El-Haj-Mahmoud
2020-05-10 11:15 ` [edk2-platform][PATCH v1 2/4] Drivers/OptionRomPkg: Move ASIX drivers to AsixPkg Samer El-Haj-Mahmoud
2020-05-11  5:18   ` Ni, Ray
2020-05-14 15:54     ` Samer El-Haj-Mahmoud
2020-05-15  6:43       ` [edk2-devel] " Ni, Ray
2020-05-10 11:15 ` [edk2-platform][PATCH v1 3/4] Silicon/AsixPkg: Add ASIX Ax88179 driver Samer El-Haj-Mahmoud
2020-05-11 14:38   ` Ard Biesheuvel
2020-05-11 15:04     ` [edk2-devel] " Samer El-Haj-Mahmoud
2020-05-11 15:06       ` Ard Biesheuvel
2020-05-12 13:02   ` Leif Lindholm
2020-05-14 15:45     ` Samer El-Haj-Mahmoud
2020-05-10 11:15 ` [edk2-platform][PATCH v1 4/4] Silicon/AsixPkg: Add ASIX Ax88772c driver Samer El-Haj-Mahmoud
2020-05-12 13:22   ` Leif Lindholm [this message]
2020-05-14 15:51     ` Samer El-Haj-Mahmoud
2020-05-11 15:50 ` [edk2-platform][PATCH v1 0/4] Update ASIX USB Networking drivers Ard Biesheuvel
2020-05-12 11:15   ` Leif Lindholm
2020-05-14 13:30     ` Samer El-Haj-Mahmoud

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200512132248.GE21486@vanye \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox