From: "Ni, Ray" <ray.ni@intel.com>
To: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>,
"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: Leif Lindholm <leif@nuviainc.com>,
Ard Biesheuvel <ard.biesheuvel@arm.com>,
"Kinney, Michael D" <michael.d.kinney@intel.com>
Subject: Re: [edk2-platform][PATCH v3 3/6] Drivers/ASIX: Add ASIX Ax88772c driver
Date: Tue, 9 Jun 2020 00:37:28 +0000 [thread overview]
Message-ID: <734D49CCEBEEF84792F5B80ED585239D5C5A4965@SHSMSX104.ccr.corp.intel.com> (raw)
In-Reply-To: <20200608133832.14100-4-Samer.El-Haj-Mahmoud@arm.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
> -----Original Message-----
> From: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>
> Sent: Monday, June 8, 2020 9:38 PM
> To: devel@edk2.groups.io
> Cc: Ni, Ray <ray.ni@intel.com>; Leif Lindholm <leif@nuviainc.com>; Ard Biesheuvel <ard.biesheuvel@arm.com>; Kinney,
> Michael D <michael.d.kinney@intel.com>
> Subject: [edk2-platform][PATCH v3 3/6] Drivers/ASIX: Add ASIX Ax88772c driver
>
> 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
>
> Original source code provided by ASIX is at:
> https://github.com/samerhaj/uefi_drivers/blob/master/UsbNetworking/Asix/
> zip/source/AX88772C_772B_772A_UEFI_v2.8.0_Source.zip
>
> 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>
> ---
> Drivers/ASIX/Asix.dsc | 1 +
> Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/Ax88772c.inf | 45 +
> Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.h | 1041 +++++++++++++
> Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.c | 1300 ++++++++++++++++
> Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/ComponentName.c | 222 +++
> Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/DriverBinding.c | 652 ++++++++
> Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/SimpleNetwork.c | 1581 ++++++++++++++++++++
> 7 files changed, 4842 insertions(+)
>
> diff --git a/Drivers/ASIX/Asix.dsc b/Drivers/ASIX/Asix.dsc
> index 73b5cbd5a18f..5e02e1176016 100644
> --- a/Drivers/ASIX/Asix.dsc
> +++ b/Drivers/ASIX/Asix.dsc
> @@ -65,3 +65,4 @@ [PcdsFixedAtBuild]
> ################################################################################
> [Components]
> Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf
> +Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/Ax88772c.inf
> diff --git a/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/Ax88772c.inf
> b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/Ax88772c.inf
> new file mode 100644
> index 000000000000..9889fc0b2067
> --- /dev/null
> +++ b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/Ax88772c.inf
> @@ -0,0 +1,45 @@
> +## @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>
> +# Copyright (c) 2020, ARM Limited. All rights reserved.
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> + INF_VERSION = 0x00010018
> + BASE_NAME = Ax88772c
> + FILE_GUID = B15239D6-6A01-4808-A0F7-B7F20F073555
> + MODULE_TYPE = UEFI_DRIVER
> + VERSION_STRING = 1.0
> +
> + ENTRY_POINT = EntryPoint
> +
> +[Sources.common]
> + Ax88772.h
> + Ax88772.c
> + ComponentName.c
> + DriverBinding.c
> + SimpleNetwork.c
> +
> +
> +[Packages]
> + MdePkg/MdePkg.dec
> + MdeModulePkg/MdeModulePkg.dec
> + NetworkPkg/NetworkPkg.dec
> +
> +[LibraryClasses]
> + BaseMemoryLib
> + DebugLib
> + UefiBootServicesTableLib
> + UefiDriverEntryPoint
> + UefiLib
> +
> +[Protocols]
> + gEfiDevicePathProtocolGuid ## BY_START
> + gEfiSimpleNetworkProtocolGuid ## BY_START
> + gEfiUsbIoProtocolGuid ## TO_START
> +
> diff --git a/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.h
> b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.h
> new file mode 100644
> index 000000000000..60afa65eee7a
> --- /dev/null
> +++ b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.h
> @@ -0,0 +1,1041 @@
> +/** @file
> + Definitions for ASIX AX88772 Ethernet adapter.
> +
> + Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.
> + Copyright (c) 2020, ARM Limited. All rights reserved.
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef AX88772_H_
> +#define AX88772_H_
> +
> +#include <Uefi.h>
> +
> +#include <Guid/EventGroup.h>
> +
> +#include <IndustryStandard/Pci.h>
> +
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/NetLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiDriverEntryPoint.h>
> +#include <Library/UefiLib.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 REPORTLINK 1
> +
> +#define ASIX_MCAST_FILTER_CNT 8
> +#define RXTHOU 0
> +
> +#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 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); \
> + } \
> +}
> +
> +#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
> +
> +#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
> +
> +
> +#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
> +
> +#define RXC_RH1M 0x0100 ///< Rx header 1
> +
> +//
> +// 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
> +
> +#define CMD_RXQTC 0x2a ///< RX Queue Cascade Threshold Control Register
> +
> +//------------------------------
> +// 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 DestAddr[PXE_HWADDR_LEN_ETHER]; ///< Destination LAN address
> + UINT8 SrcAddr[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 * Next; ///< 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 *UsbIo; ///< 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 Initialized; ///< Controller initialized
> + UINT16 PhyId; ///< PHY ID
> +
> + //
> + // Link state
> + //
> + BOOLEAN LinkSpeed100Mbps; ///< Current link speed, FALSE = 10 Mbps
> + BOOLEAN Complete; ///< Current state of auto-negotiation
> + BOOLEAN FullDuplex; ///< Current duplex
> + BOOLEAN LinkUp; ///< Current link state
> + UINTN PollCount; ///< Number of times the autonegotiation status was polled
> + UINT16 CurRxControl;
> + VOID *TxBuffer;
> + //
> + // Receive buffer list
> + //
> + UINT8 *BulkInbuf;
> + UINT8 *CurPktHdrOff;
> + UINT8 *CurPktOff;
> + UINT16 PktCnt;
> +
> + RX_TX_PACKET *TxTest;
> +
> + UINT8 MulticastHash[8];
> + EFI_MAC_ADDRESS MAC;
> +
> +
> + EFI_DEVICE_PATH_PROTOCOL *MyDevPath;
> + BOOLEAN Grub_f;
> + BOOLEAN FirstRst;
> + 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] SimpleNetwork Protocol instance pointer
> + @param [in] ExtendedVerification 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 SimpleNetwork 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 *SimpleNetwork,
> + IN BOOLEAN ExtendedVerification
> + );
> +
> +/**
> + Initialize the simple network protocol.
> +
> + This routine calls ::Ax88772MacAddressGet to obtain the
> + MAC address.
> +
> + @param [in] NicDevice NIC_DEVICE_INSTANCE pointer
> +
> + @retval EFI_SUCCESS Setup was successful
> +
> +**/
> +EFI_STATUS
> +SN_Setup (
> + IN NIC_DEVICE *NicDevice
> + );
> +
> +/**
> + This routine starts the network interface.
> +
> + @param [in] SimpleNetwork Protocol instance pointer
> +
> + @retval EFI_SUCCESS This operation was successful.
> + @retval EFI_ALREADY_STARTED The network interface was already started.
> + @retval EFI_INVALID_PARAMETER SimpleNetwork 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 *SimpleNetwork
> + );
> +
> +/**
> + 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
> + New.
> +
> + This routine calls ::Ax88772MacAddressSet to update the MAC address
> + in the network adapter.
> +
> + @param [in] SimpleNetwork Protocol instance pointer
> + @param [in] Reset Flag used to reset the station address to the
> + network interface's permanent address.
> + @param [in] New 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 SimpleNetwork 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 *SimpleNetwork,
> + IN BOOLEAN Reset,
> + IN EFI_MAC_ADDRESS *New
> + );
> +
> +/**
> + 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] SimpleNetwork Protocol instance pointer
> + @param [in] Reset Set to TRUE to reset the statistics for the network interface.
> + @param [in, out] StatisticsSize On input the size, in bytes, of StatisticsTable. On output
> + the size, in bytes, of the resulting table of statistics.
> + @param [out] StatisticsTable 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 StatisticsTable is NULL or the buffer is too small.
> + @retval EFI_INVALID_PARAMETER SimpleNetwork 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 *SimpleNetwork,
> + IN BOOLEAN Reset,
> + IN OUT UINTN *StatisticsSize,
> + OUT EFI_NETWORK_STATISTICS *StatisticsTable
> + );
> +
> +/**
> + This function stops a network interface. This call is only valid
> + if the network interface is in the started state.
> +
> + @param [in] SimpleNetwork Protocol instance pointer
> +
> + @retval EFI_SUCCESS This operation was successful.
> + @retval EFI_NOT_STARTED The network interface was not started.
> + @retval EFI_INVALID_PARAMETER SimpleNetwork 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 *SimpleNetwork
> + );
> +
> +/**
> + This function releases the memory buffers assigned in the Initialize() call.
> + Ending transmits and receives are lost, and interrupts are cleared and disabled.
> + After this call, only Initialize() and Stop() calls may be used.
> +
> + @param [in] SimpleNetwork Protocol instance pointer
> +
> + @retval EFI_SUCCESS This operation was successful.
> + @retval EFI_NOT_STARTED The network interface was not started.
> + @retval EFI_INVALID_PARAMETER SimpleNetwork 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 *SimpleNetwork
> + );
> +
> +/**
> + 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] SimpleNetwork 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] Buffer 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] SrcAddr 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] DestAddr The destination HW MAC address. If HeaderSize is zero, then
> + this parameter is ignored.
> + @param [in] Protocol 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 SimpleNetwork 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 *SimpleNetwork,
> + IN UINTN HeaderSize,
> + IN UINTN BufferSize,
> + IN VOID *Buffer,
> + IN EFI_MAC_ADDRESS *SrcAddr,
> + IN EFI_MAC_ADDRESS *DestAddr,
> + IN UINT16 *Protocol
> + );
> +
> +//------------------------------------------------------------------------------
> +// Support Routines
> +//------------------------------------------------------------------------------
> +
> +/**
> + Get the MAC address
> +
> + This routine calls ::Ax88772UsbCommand to request the MAC
> + address from the network adapter.
> +
> + @param [in] NicDevice Pointer to the NIC_DEVICE structure
> + @param [out] MacAddress 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 *NicDevice,
> + OUT UINT8 *MacAddress
> + );
> +
> +/**
> + Set the MAC address
> +
> + This routine calls ::Ax88772UsbCommand to set the MAC address
> + in the network adapter.
> +
> + @param [in] NicDevice Pointer to the NIC_DEVICE structure
> + @param [in] MacAddress 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 *NicDevice,
> + IN UINT8 *MacAddress
> + );
> +
> +/**
> + Clear the multicast hash table
> +
> + @param [in] NicDevice Pointer to the NIC_DEVICE structure
> +
> +**/
> +VOID
> +Ax88772MulticastClear (
> + IN NIC_DEVICE *NicDevice
> + );
> +
> +/**
> + Enable a multicast address in the multicast hash table
> +
> + This routine calls ::Ax88772Crc to compute the hash bit for
> + this MAC address.
> +
> + @param [in] NicDevice Pointer to the NIC_DEVICE structure
> + @param [in] MacAddress Address of a six byte buffer to containing the MAC address.
> +
> +**/
> +VOID
> +Ax88772MulticastSet (
> + IN NIC_DEVICE *NicDevice,
> + IN UINT8 *MacAddress
> + );
> +
> +/**
> + Start the link negotiation
> +
> + This routine calls ::Ax88772PhyWrite to start the PHY's link
> + negotiation.
> +
> + @param [in] NicDevice 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 *NicDevice
> + );
> +
> +/**
> + Complete the negotiation of the PHY link
> +
> + This routine calls ::Ax88772PhyRead to determine if the
> + link negotiation is complete.
> +
> + @param [in] NicDevice Pointer to the NIC_DEVICE structure
> + @param [in, out] PollCount Address of number of times this routine was polled
> + @param [out] Complete Address of boolean to receive complate status.
> + @param [out] LinkUp Address of boolean to receive link status, TRUE=up.
> + @param [out] HiSpeed Address of boolean to receive link speed, TRUE=100Mbps.
> + @param [out] FullDuplex 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 *NicDevice,
> + IN OUT UINTN *PollCount,
> + OUT BOOLEAN *Complete,
> + OUT BOOLEAN *LinkUp,
> + OUT BOOLEAN *HiSpeed,
> + OUT BOOLEAN *FullDuplex
> + );
> +
> +/**
> + Read a register from the PHY
> +
> + This routine calls ::Ax88772UsbCommand to read a PHY register.
> +
> + @param [in] NicDevice Pointer to the NIC_DEVICE structure
> + @param [in] RegisterAddress Number of the register to read.
> + @param [in, out] PhyData 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 * NicDevice,
> + IN UINT8 RegisterAddress,
> + IN OUT UINT16 * PhyData
> + );
> +
> +/**
> + Write to a PHY register
> +
> + This routine calls ::Ax88772UsbCommand to write a PHY register.
> +
> + @param [in] NicDevice 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 *NicDevice,
> + 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] NicDevice 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 *NicDevice
> + );
> +
> +VOID
> +Ax88772ChkLink (
> + IN NIC_DEVICE * NicDevice,
> + IN BOOLEAN UpdateLink
> + );
> +
> +/**
> + 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
> + Ending 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] NicDevice Pointer to the NIC_DEVICE structure
> + @param [in] UpdateLink TRUE = Update link status
> +
> +**/
> +VOID
> +Ax88772Rx (
> + IN NIC_DEVICE *NicDevice,
> + IN BOOLEAN UpdateLink
> + );
> +
> +/**
> + 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] NicDevice 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 *NicDevice,
> + IN UINT32 RxFilter
> + );
> +
> +EFI_STATUS
> +Ax88772ReloadSrom (
> + IN NIC_DEVICE *NicDevice
> + );
> +
> +/**
> + Read an SROM location
> +
> + This routine calls ::Ax88772UsbCommand to read data from the
> + SROM.
> +
> + @param [in] NicDevice Pointer to the NIC_DEVICE structure
> + @param [in] Address SROM address
> + @param [out] Data Buffer to receive the data
> +
> + @retval EFI_SUCCESS The read was successful
> + @retval other The read failed
> +
> +**/
> +EFI_STATUS
> +Ax88772SromRead (
> + IN NIC_DEVICE *NicDevice,
> + IN UINT32 Address,
> + OUT UINT16 *Data
> + );
> +
> +
> +EFI_STATUS
> +Ax88772EnableSromWrite (
> + IN NIC_DEVICE *NicDevice
> + );
> +
> +
> +EFI_STATUS
> +Ax88772DisableSromWrite (
> + IN NIC_DEVICE *NicDevice
> + );
> +
> +EFI_STATUS
> +Ax88772SromWrite (
> + IN NIC_DEVICE *NicDevice,
> + IN UINT32 Address,
> + OUT UINT16 *Data
> + );
> +
> +/**
> + Send a command to the USB device.
> +
> + @param [in] NicDevice Pointer to the NIC_DEVICE structure
> + @param [in] Request Pointer to the request structure
> + @param [in, out] Buffer Data buffer address
> +
> + @retval EFI_SUCCESS The USB transfer was successful
> + @retval other The USB transfer failed
> +
> +**/
> +EFI_STATUS
> +Ax88772UsbCommand (
> + IN NIC_DEVICE *NicDevice,
> + IN USB_DEVICE_REQUEST *Request,
> + IN OUT VOID *Buffer
> + );
> +
> +BOOLEAN
> +Ax88772GetLinkStatus (
> + IN NIC_DEVICE *NicDevice
> +) ;
> +
> +//------------------------------------------------------------------------------
> +// 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] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
> + EFI_COMPONENT_NAME_PROTOCOL instance.
> + @param [in] Language 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] DriverName 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 *This,
> + IN CHAR8 *Language,
> + OUT CHAR16 **DriverName
> + );
> +
> +
> +/**
> + Retrieves a Unicode string that is the user readable name of the controller
> + that is being managed by a driver.
> +
> + This function retrieves the user readable name of the controller specified by
> + ControllerHandle and ChildHandle in the form of a Unicode string. If the
> + driver specified by This has a user readable name in the language specified by
> + Language, then a pointer to the controller name is returned in ControllerName,
> + and EFI_SUCCESS is returned. If the driver specified by This is not currently
> + managing the controller specified by ControllerHandle and ChildHandle,
> + then EFI_UNSUPPORTED is returned. If the driver specified by This does not
> + support the language specified by Language, then EFI_UNSUPPORTED is returned.
> +
> + @param [in] This 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] Language 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] ControllerName 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 *This,
> + IN EFI_HANDLE ControllerHandle,
> + IN OPTIONAL EFI_HANDLE ChildHandle,
> + IN CHAR8 *Language,
> + OUT CHAR16 **ControllerName
> + );
> +
> +
> +EFI_STATUS
> +Ax88772BulkIn(
> + IN NIC_DEVICE *NicDevice
> +);
> +
> +//------------------------------------------------------------------------------
> +
> +#endif // AX88772_H_
> diff --git a/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.c
> b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.c
> new file mode 100644
> index 000000000000..32052ba9073a
> --- /dev/null
> +++ b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.c
> @@ -0,0 +1,1300 @@
> +/** @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.
> + Copyright (c) 2020, ARM Limited. All rights reserved.
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "Ax88772.h"
> +
> +
> +/**
> + Compute the CRC
> +
> + @param [in] MacAddress 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 *MacAddress
> + )
> +{
> + UINT32 BitNumber;
> + INT32 Carry;
> + INT32 Crc;
> + UINT32 Data;
> + UINT8 *End;
> +
> + //
> + // Walk the MAC address
> + //
> + Crc = -1;
> + End = &MacAddress[PXE_HWADDR_LEN_ETHER];
> + while (End > MacAddress) {
> + Data = *MacAddress++;
> +
> +
> + //
> + // 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 (Carry != 0) {
> + 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] NicDevice Pointer to the NIC_DEVICE structure
> + @param [out] MacAddress 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 *NicDevice,
> + OUT UINT8 *MacAddress
> + )
> +{
> + 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 (NicDevice,
> + &SetupMsg,
> + MacAddress);
> +
> + //
> + // 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] NicDevice Pointer to the NIC_DEVICE structure
> + @param [in] MacAddress 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 *NicDevice,
> + IN UINT8 *MacAddress
> + )
> +{
> + 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 (NicDevice,
> + &SetupMsg,
> + MacAddress);
> +
> + //
> + // Return the operation status
> + //
> + return Status;
> +}
> +
> +/**
> + Clear the multicast hash table
> +
> + @param [in] NicDevice Pointer to the NIC_DEVICE structure
> +
> +**/
> +VOID
> +Ax88772MulticastClear (
> + IN NIC_DEVICE *NicDevice
> + )
> +{
> + int Index = 0;
> + //
> + // Clear the multicast hash table
> + //
> + for (Index = 0 ; Index < 8 ; Index ++)
> + NicDevice->MulticastHash[Index] = 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] NicDevice Pointer to the NIC_DEVICE structure
> + @param [in] MacAddress Address of a six byte buffer to containing the MAC address.
> +
> +**/
> +VOID
> +Ax88772MulticastSet (
> + IN NIC_DEVICE *NicDevice,
> + IN UINT8 *MacAddress
> + )
> +{
> + UINT32 Crc;
> +
> + //
> + // Compute the CRC on the destination address
> + //
> + Crc = Ax88772Crc (MacAddress) >> 26;
> +
> + //
> + // Set the bit corresponding to the destination address
> + //
> + NicDevice->MulticastHash [Crc >> 3] |= (1 << (Crc & 7));
> +
> +}
> +
> +/**
> + Start the link negotiation
> +
> + This routine calls ::Ax88772PhyWrite to start the PHY's link
> + negotiation.
> +
> + @param [in] NicDevice 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 *NicDevice
> + )
> +{
> + UINT16 Control;
> + EFI_STATUS Status;
> +
> + //
> + // Set the supported capabilities.
> + //
> + Status = Ax88772PhyWrite (NicDevice,
> + 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 (NicDevice->LinkSpeed100Mbps) {
> + Control |= BMCR_100MBPS;
> + }
> + if (NicDevice->FullDuplex) {
> + Control |= BMCR_FULL_DUPLEX;
> + }
> + Status = Ax88772PhyWrite (NicDevice, 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] NicDevice Pointer to the NIC_DEVICE structure
> + @param [in, out] PollCount Address of number of times this routine was polled
> + @param [out] Complete Address of boolean to receive complate status.
> + @param [out] LinkUp Address of boolean to receive link status, TRUE=up.
> + @param [out] HiSpeed Address of boolean to receive link speed, TRUE=100Mbps.
> + @param [out] FullDuplex 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 *NicDevice,
> + IN OUT UINTN *PollCount,
> + OUT BOOLEAN *Complete,
> + OUT BOOLEAN *LinkUp,
> + OUT BOOLEAN *HiSpeed,
> + OUT BOOLEAN *FullDuplex
> + )
> +{
> + UINT16 Mask;
> + UINT16 PhyData;
> + EFI_STATUS Status;
> +
> + //
> + // Determine if the link is up.
> + //
> + *Complete = FALSE;
> +
> + //
> + // Get the link status
> + //
> + Status = Ax88772PhyRead (NicDevice,
> + PHY_BMSR,
> + &PhyData);
> +
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + *LinkUp = ((PhyData & BMSR_LINKST) != 0);
> + if (0 == *LinkUp) {
> + } else {
> + *Complete = ((PhyData & 0x20) != 0);
> + if (0 == *Complete) {
> + } else {
> + Status = Ax88772PhyRead (NicDevice,
> + PHY_ANLPAR,
> + &PhyData);
> +
> + if (!EFI_ERROR (Status)) {
> + //
> + // Autonegotiation is complete
> + // Determine the link speed.
> + //
> + *HiSpeed = ((PhyData & (AN_TX_FDX | AN_TX_HDX))!= 0);
> + //
> + // Determine the link duplex.
> + //
> + Mask = (*HiSpeed) ? AN_TX_FDX : AN_10_FDX;
> + *FullDuplex = (BOOLEAN)((PhyData & Mask) != 0);
> + }
> + }
> + }
> +
> + return Status;
> +}
> +
> +
> +/**
> + Read a register from the PHY
> +
> + This routine calls ::Ax88772UsbCommand to read a PHY register.
> +
> + @param [in] NicDevice Pointer to the NIC_DEVICE structure
> + @param [in] RegisterAddress Number of the register to read.
> + @param [in, out] PhyData 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 *NicDevice,
> + IN UINT8 RegisterAddress,
> + IN OUT 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 (NicDevice,
> + &SetupMsg,
> + NULL);
> + if (EFI_ERROR (Status)) {
> + return 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 = NicDevice->PhyId;
> + SetupMsg.Index = RegisterAddress;
> + SetupMsg.Length = sizeof(*PhyData);
> + Status = Ax88772UsbCommand(NicDevice,
> + &SetupMsg,
> + PhyData);
> + if (EFI_ERROR (Status)) {
> + return 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(NicDevice,
> + &SetupMsg,
> + NULL);
> +
> + //
> + // Return the operation status.
> + //
> + return Status;
> +}
> +
> +
> +/**
> + Write to a PHY register
> +
> + This routine calls ::Ax88772UsbCommand to write a PHY register.
> +
> + @param [in] NicDevice 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 *NicDevice,
> + 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 (NicDevice,
> + &SetupMsg,
> + NULL);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + //
> + // Write the PHY register
> + //
> + SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> + | USB_TARGET_DEVICE;
> + SetupMsg.Request = CMD_PHY_REG_WRITE;
> + SetupMsg.Value = NicDevice->PhyId;
> + SetupMsg.Index = RegisterAddress;
> + SetupMsg.Length = sizeof (PhyData);
> + Status = Ax88772UsbCommand (NicDevice,
> + &SetupMsg,
> + &PhyData);
> + if (EFI_ERROR (Status)) {
> + return 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 (NicDevice,
> + &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] NicDevice 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 *NicDevice
> + )
> +{
> + USB_DEVICE_REQUEST SetupMsg;
> + EFI_STATUS Status;
> +
> + 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 (NicDevice,
> + &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 (NicDevice,
> + &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 (NicDevice,
> + &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 (NicDevice,
> + &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 (NicDevice,
> + &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 (NicDevice,
> + &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 (NicDevice,
> + &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 (NicDevice,
> + &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 (NicDevice,
> + &SetupMsg,
> + NULL);
> +
> + if (EFI_ERROR(Status)) goto err;
> +
> + if (!NicDevice->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 (NicDevice,
> + &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] NicDevice 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 *NicDevice,
> + 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 (RxFilter != 0) {
> + //
> + // 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 (NicDevice,
> + &SetupMsg,
> + &MediumStatus);
> + if (!EFI_ERROR (Status)) {
> + if (0 == (MediumStatus & MS_RE)) {
> + MediumStatus |= MS_RE | MS_ONE;
> +
> + if (NicDevice->FullDuplex)
> + MediumStatus |= MS_TFC | MS_RFC | MS_FD;
> + else
> + MediumStatus &= ~(MS_TFC | MS_RFC | MS_FD);
> +
> + if (NicDevice->LinkSpeed100Mbps)
> + 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 (NicDevice,
> + &SetupMsg,
> + NULL);
> +
> + if (EFI_ERROR(Status))
> + goto EXIT;
> + }
> + } else {
> + goto EXIT;
> + }
> + }
> + RxControl = RXC_SO;
> + if (!NicDevice->Flag772A)
> + RxControl |= RXC_RH1M;
> +
> + //
> + // Enable multicast if requested
> + //
> + if ((RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
> + 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 (NicDevice ->MulticastHash);
> + Status = Ax88772UsbCommand (NicDevice,
> + &SetupMsg,
> + &NicDevice->MulticastHash);
> +
> + if (EFI_ERROR(Status))
> + goto EXIT;
> + }
> +
> + //
> + // Enable all multicast if requested
> + //
> + if ((RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
> + RxControl |= RXC_AMALL;
> + }
> +
> + //
> + // Enable broadcast if requested
> + //
> + if ((RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) {
> + RxControl |= RXC_AB;
> + }
> +
> + //
> + // Enable promiscuous mode if requested
> + //
> + if ((RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {
> + RxControl |= RXC_PRO;
> + }
> +
> + //
> + // Update the receiver control
> + //
> + if (NicDevice->CurRxControl != RxControl) {
> + SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
> + | USB_TARGET_DEVICE;
> + SetupMsg.Request = CMD_RX_CONTROL_WRITE;
> +#if RXTHOU
> + if (NicDevice->Flag772A)
> + RxControl |= 0x0300;
> +#endif
> + if (NicDevice->Flag772A)
> + RxControl &= ~(RXC_MFB);
> + SetupMsg.Value = RxControl;
> + SetupMsg.Index = 0;
> + SetupMsg.Length = 0;
> + Status = Ax88772UsbCommand (NicDevice,
> + &SetupMsg,
> + NULL);
> + if (!EFI_ERROR (Status))
> + NicDevice->CurRxControl = RxControl;
> + }
> +
> + //
> + // Return the operation status
> + //
> +EXIT:
> + return Status;
> +}
> +
> +
> +
> +EFI_STATUS
> +Ax88772ReloadSrom (
> + IN NIC_DEVICE *NicDevice
> + )
> +{
> + 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 (NicDevice,
> + &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] NicDevice Pointer to the NIC_DEVICE structure
> + @param [in] Address SROM address
> + @param [out] Data Buffer to receive the data
> +
> + @retval EFI_SUCCESS The read was successful
> + @retval other The read failed
> +
> +**/
> +EFI_STATUS
> +Ax88772SromRead (
> + IN NIC_DEVICE *NicDevice,
> + IN UINT32 Address,
> + OUT UINT16 *Data
> + )
> +{
> +
> + 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 (*Data);
> + Status = Ax88772UsbCommand (NicDevice,
> + &SetupMsg,
> + Data);
> +
> + //
> + // Return the operation status
> + //
> + return Status;
> +}
> +
> +EFI_STATUS
> +Ax88772EnableSromWrite (
> + IN NIC_DEVICE * NicDevice
> + )
> +{
> + 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 (NicDevice,
> + &SetupMsg,
> + NULL);
> +
> + if (EFI_SUCCESS == Status)
> + gBS->Stall(500000);
> +
> + return Status;
> +
> +}
> +
> +
> +EFI_STATUS
> +Ax88772DisableSromWrite (
> + IN NIC_DEVICE *NicDevice
> + )
> +{
> + 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 (NicDevice,
> + &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] NicDevice Pointer to the NIC_DEVICE structure
> + @param [in] Address SROM address
> + @param [out] Data Buffer of data to write
> +
> + @retval EFI_SUCCESS The write was successful
> + @retval other The write failed
> +
> +**/
> +EFI_STATUS
> +Ax88772SromWrite (
> + IN NIC_DEVICE *NicDevice,
> + IN UINT32 Address,
> + IN UINT16 *Data
> + )
> +{
> +
> + 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) (*Data);
> + SetupMsg.Length = 0;
> +
> + Status = Ax88772UsbCommand (NicDevice,
> + &SetupMsg,
> + NULL);
> +
> + //
> + // Return the operation status
> + //
> + return Status;
> +}
> +
> +/**
> + Send a command to the USB device.
> +
> + @param [in] NicDevice Pointer to the NIC_DEVICE structure
> + @param [in] Request Pointer to the request structure
> + @param [in, out] Buffer Data buffer address
> +
> + @retval EFI_SUCCESS The USB transfer was successful
> + @retval other The USB transfer failed
> +
> +**/
> +EFI_STATUS
> +Ax88772UsbCommand (
> + IN NIC_DEVICE *NicDevice,
> + IN USB_DEVICE_REQUEST *Request,
> + IN OUT VOID *Buffer
> + )
> +{
> + UINT32 CmdStatus;
> + EFI_USB_DATA_DIRECTION Direction;
> + EFI_USB_IO_PROTOCOL *UsbIo;
> + EFI_STATUS Status;
> +
> + //
> + // Determine the transfer direction
> + //
> + Direction = EfiUsbNoData;
> + if (Request->Length != 0) {
> + Direction = ((Request->RequestType & USB_ENDPOINT_DIR_IN) != 0)
> + ? EfiUsbDataIn : EfiUsbDataOut;
> + }
> +
> + //
> + // Issue the command
> + //
> + UsbIo = NicDevice->UsbIo;
> + Status = UsbIo->UsbControlTransfer (UsbIo,
> + Request,
> + Direction,
> + USB_BUS_TIMEOUT,
> + Buffer,
> + Request->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 *NicDevice
> +)
> +{
> + UINT32 CmdStatus;
> + EFI_USB_IO_PROTOCOL *UsbIo;
> + UINT64 IntData = 0;
> + UINTN IntDataLeng = 8;
> + EFI_STATUS Status;
> +
> + //
> + // Issue the command
> + //
> + UsbIo = NicDevice->UsbIo;
> + Status = UsbIo->UsbSyncInterruptTransfer(UsbIo,
> + 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 * NicDevice
> +)
> +{
> + UINTN Index;
> + UINTN LengthInBytes = 0;
> + UINTN TmpLen = AX88772_MAX_BULKIN_SIZE;
> + UINTN OrigTmpLen = 0;
> + UINT16 TmpLen2;
> + UINT16 TmpLenBar;
> + UINT16 TmpTotalLen = 0;
> + UINTN TotalLen = LengthInBytes;
> + EFI_STATUS Status = EFI_DEVICE_ERROR;
> + EFI_USB_IO_PROTOCOL *UsbIo;
> + UINT32 TransferStatus = 0;
> + UINT16 TmpPktCnt = 0;
> + UINT16 *TmpHdr = (UINT16 *)NicDevice->BulkInbuf;
> + USB_DEVICE_REQUEST SetupMsg;
> +
> + UsbIo = NicDevice->UsbIo;
> + for (Index = 0 ; Index < (AX88772_MAX_BULKIN_SIZE / 512) && UsbIo != NULL; Index++) {
> + VOID* TmpAddr = 0;
> +
> + TmpPktCnt = 0;
> + TmpAddr = (VOID*) &NicDevice->BulkInbuf[LengthInBytes];
> + OrigTmpLen = TmpLen;
> + Status = UsbIo->UsbBulkTransfer (UsbIo,
> + USB_ENDPOINT_DIR_IN | BULK_IN_ENDPOINT,
> + TmpAddr,
> + &TmpLen,
> + BULKIN_TIMEOUT,
> + &TransferStatus);
> +
> + if (OrigTmpLen == TmpLen) {
> + Status = EFI_NOT_READY;
> + goto no_pkt;
> + }
> +
> + if ((!EFI_ERROR (Status)) &&
> + (!EFI_ERROR (TransferStatus)) &&
> + TmpLen != 0) {
> + LengthInBytes += TmpLen;
> + if ((TmpLen % 512) != 0) {
> + goto done;
> + }
> + } else if ((!EFI_ERROR (Status)) &&
> + (!EFI_ERROR (TransferStatus)) &&
> + (TmpLen == 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 (NicDevice,
> + &SetupMsg,
> + NULL);
> + Status = EFI_NOT_READY;
> + goto done;
> + } else {
> + Status = EFI_DEVICE_ERROR;
> + goto done;
> + }
> + }
> +done:
> + if (LengthInBytes != 0) {
> +
> + do {
> + TmpLen2 = (*TmpHdr) & 0x7FF;
> + TmpLenBar = *(TmpHdr + 1);
> + TmpTotalLen = ((TmpLen + 4 + 1) & 0xfffe);
> +
> + if ((TmpLen2 & 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 ((NicDevice->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 (NicDevice,
> + &SetupMsg,
> + NULL);
> + }
> +
> + if (NicDevice->RxBurst < 2)
> + NicDevice->RxBurst++;
> +
> + } else {
> + if (NicDevice->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 (NicDevice,
> + &SetupMsg,
> + NULL);
> + }
> + NicDevice->RxBurst = 0;
> + }
> + }
> +
> + if (TmpPktCnt != 0) {
> + NicDevice->PktCnt = TmpPktCnt;
> + NicDevice->CurPktHdrOff = NicDevice->BulkInbuf;
> + NicDevice->CurPktOff = NicDevice->BulkInbuf + 4;
> + Status = EFI_SUCCESS;
> + }
> +
> +no_pkt:
> + return Status;
> +}
> +#else
> +EFI_STATUS
> +Ax88772BulkIn(
> + IN NIC_DEVICE *NicDevice
> +)
> +{
> + UINTN Index;
> + UINTN LengthInBytes = 0;
> + UINTN TmpLen = AX88772_MAX_BULKIN_SIZE;
> + UINTN OrigTmpLen = 0;
> + UINT16 TmpLen2;
> + UINT16 TmpLenBar;
> + UINT16 TmpTotalLen = 0;
> + UINTN CURBufSize = AX88772_MAX_BULKIN_SIZE;
> + EFI_STATUS Status = EFI_DEVICE_ERROR;
> + EFI_USB_IO_PROTOCOL *UsbIo;
> + UINT32 TransferStatus = 0;
> + UINT16 TmpPktCnt = 0;
> + UINT16 *TmpHdr = (UINT16 *)NicDevice->BulkInbuf;
> +
> + UsbIo = NicDevice->UsbIo;
> + for (Index = 0 ; Index < (AX88772_MAX_BULKIN_SIZE / 512) && UsbIo != NULL; Index++) {
> + VOID *TmpAddr = 0;
> +
> + TmpPktCnt = 0;
> + TmpAddr = (VOID*) &NicDevice->BulkInbuf[LengthInBytes];
> + OrigTmpLen = TmpLen;
> + Status = UsbIo->UsbBulkTransfer (UsbIo,
> + USB_ENDPOINT_DIR_IN | BULK_IN_ENDPOINT,
> + TmpAddr,
> + &TmpLen,
> + BULKIN_TIMEOUT,
> + &TransferStatus);
> +
> + if (OrigTmpLen == TmpLen) {
> + Status = EFI_NOT_READY;
> + goto no_pkt;
> + }
> +
> + if ((!EFI_ERROR (Status)) &&
> + (!EFI_ERROR (TransferStatus)) &&
> + TmpLen != 0) {
> +
> + LengthInBytes += TmpLen;
> + CURBufSize = CURBufSize - TmpLen;
> + TmpLen = CURBufSize;
> + do {
> + TmpLen2 = *TmpHdr;
> + TmpLenBar = *(TmpHdr + 1);
> + TmpTotalLen += ((TmpLen2 + 4 + 1) & 0xfffe);
> +
> + if (((TmpLen2 ^ TmpLenBar) == 0xffff)) {
> + if (TmpTotalLen == LengthInBytes) {
> + TmpPktCnt++;
> + Status = EFI_SUCCESS;
> + goto done;
> + } else if (TmpTotalLen > LengthInBytes) {
> + break;
> + }
> + } else if (((TmpLen2 ^ 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)) &&
> + (TmpLen == 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:
> + NicDevice->PktCnt = TmpPktCnt;
> + NicDevice->CurPktHdrOff = NicDevice->BulkInbuf;
> + NicDevice->CurPktOff = NicDevice->BulkInbuf + 4;
> +no_pkt:
> + return Status;
> +}
> +#endif
> diff --git a/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/ComponentName.c
> b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/ComponentName.c
> new file mode 100644
> index 000000000000..a8b450f77e8d
> --- /dev/null
> +++ b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/ComponentName.c
> @@ -0,0 +1,222 @@
> +/** @file
> + UEFI Component Name(2) protocol implementation.
> +
> + Copyright (c) 2011, Intel Corporation. All rights reserved.
> + Copyright (c) 2020, ARM Limited. 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] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
> + EFI_COMPONENT_NAME_PROTOCOL instance.
> + @param [in] Language 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] DriverName 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 *This,
> + IN CHAR8 *Language,
> + OUT CHAR16 **DriverName
> + )
> +{
> + EFI_STATUS Status;
> +
> +
> + Status = LookupUnicodeString2 (
> + Language,
> + This->SupportedLanguages,
> + mDriverNameTable,
> + DriverName,
> + (BOOLEAN)(This == &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] This 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] Language 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] ControllerName 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 *This,
> + IN EFI_HANDLE ControllerHandle,
> + IN OPTIONAL EFI_HANDLE ChildHandle,
> + IN CHAR8 *Language,
> + OUT CHAR16 **ControllerName
> + )
> +{
> +
> + 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 (
> + Language,
> + This->SupportedLanguages,
> + mControllerNameTable,
> + ControllerName,
> + (BOOLEAN)(This == &gComponentName)
> + );
> +
> + return Status;
> +}
> diff --git a/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/DriverBinding.c
> b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/DriverBinding.c
> new file mode 100644
> index 000000000000..08b1f287d7b9
> --- /dev/null
> +++ b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/DriverBinding.c
> @@ -0,0 +1,652 @@
> +/** @file
> + Implement the driver binding protocol for Asix AX88772 Ethernet driver.
> +
> + Copyright (c) 2011-2013, Intel Corporation. All rights reserved.
> + Copyright (c) 2020, ARM Limited. All rights reserved.
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "Ax88772.h"
> +
> +/**
> + Verify the controller type
> +
> + @param [in] This 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 *This,
> + IN EFI_HANDLE Controller,
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
> + )
> +{
> + EFI_USB_DEVICE_DESCRIPTOR Device;
> + EFI_USB_IO_PROTOCOL *UsbIo;
> + EFI_STATUS Status;
> +
> + //
> + // Connect to the USB stack
> + //
> + Status = gBS->OpenProtocol (
> + Controller,
> + &gEfiUsbIoProtocolGuid,
> + (VOID **) &UsbIo,
> + This->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 = UsbIo->UsbGetDeviceDescriptor (UsbIo, &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,
> + This->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 apEnded to it, install the NetworkInterfaceIdentifier protocol
> + on the newly created Device Path.
> +
> + @param [in] This 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 *This,
> + IN EFI_HANDLE Controller,
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
> + )
> +{
> + EFI_STATUS Status;
> + NIC_DEVICE *NicDevice;
> + UINTN LengthInBytes;
> + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath = NULL;
> + MAC_ADDR_DEVICE_PATH MacDeviceNode;
> + EFI_USB_DEVICE_DESCRIPTOR Device;
> +
> + //
> + // Allocate the device structure
> + //
> + LengthInBytes = sizeof (*NicDevice);
> + Status = gBS->AllocatePool (
> + EfiBootServicesData,
> + LengthInBytes,
> + (VOID **) &NicDevice
> + );
> +
> + if (EFI_ERROR (Status)) {
> + goto ERR;
> + }
> +
> + //
> + // Set the structure signature
> + //
> + ZeroMem (NicDevice, LengthInBytes);
> + NicDevice->Signature = DEV_SIGNATURE;
> +
> + Status = gBS->OpenProtocol (
> + Controller,
> + &gEfiUsbIoProtocolGuid,
> + (VOID **) &NicDevice->UsbIo,
> + This->DriverBindingHandle,
> + Controller,
> + EFI_OPEN_PROTOCOL_BY_DRIVER
> + );
> +
> + if (EFI_ERROR (Status)) {
> + goto ERR;
> + }
> +
> + NicDevice->Flag772A = FALSE;
> + NicDevice->UsbIo->UsbGetDeviceDescriptor (NicDevice->UsbIo, &Device);
> + if ((PRODUCT_AX88772A_ID == Device.IdProduct) ||
> + (PRODUCT_ID == Device.IdProduct))
> + NicDevice->Flag772A = TRUE;
> + //
> + // Initialize the simple network protocol
> + //
> + Status = SN_Setup (NicDevice);
> +
> + if (EFI_ERROR(Status)){
> + gBS->CloseProtocol (
> + Controller,
> + &gEfiUsbIoProtocolGuid,
> + This->DriverBindingHandle,
> + Controller
> + );
> + goto ERR;
> + }
> +
> + //
> + // Set Device Path
> + //
> + Status = gBS->OpenProtocol (
> + Controller,
> + &gEfiDevicePathProtocolGuid,
> + (VOID **) &ParentDevicePath,
> + This->DriverBindingHandle,
> + Controller,
> + EFI_OPEN_PROTOCOL_BY_DRIVER
> + );
> + if (EFI_ERROR(Status)) {
> + gBS->CloseProtocol (
> + Controller,
> + &gEfiUsbIoProtocolGuid,
> + This->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,
> + &NicDevice->SimpleNetworkData.CurrentAddress,
> + PXE_HWADDR_LEN_ETHER);
> +
> + MacDeviceNode.IfType = NicDevice->SimpleNetworkData.IfType;
> +
> + NicDevice->MyDevPath = AppendDevicePathNode (
> + ParentDevicePath,
> + (EFI_DEVICE_PATH_PROTOCOL *) &MacDeviceNode
> + );
> +
> + NicDevice->Controller = NULL;
> +
> + //
> + // Install both the simple network and device path protocols.
> + //
> + Status = gBS->InstallMultipleProtocolInterfaces (
> + &NicDevice->Controller,
> + &gEfiCallerIdGuid,
> + NicDevice,
> + &gEfiSimpleNetworkProtocolGuid,
> + &NicDevice->SimpleNetwork,
> + &gEfiDevicePathProtocolGuid,
> + NicDevice->MyDevPath,
> + NULL
> + );
> +
> + if (EFI_ERROR(Status)){
> + gBS->CloseProtocol (
> + Controller,
> + &gEfiDevicePathProtocolGuid,
> + This->DriverBindingHandle,
> + Controller);
> + gBS->CloseProtocol (
> + Controller,
> + &gEfiUsbIoProtocolGuid,
> + This->DriverBindingHandle,
> + Controller
> + );
> + goto ERR;
> + }
> +
> + //
> + // Open For Child Device
> + //
> + Status = gBS->OpenProtocol (
> + Controller,
> + &gEfiUsbIoProtocolGuid,
> + (VOID **) &NicDevice->UsbIo,
> + This->DriverBindingHandle,
> + NicDevice->Controller,
> + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
> + );
> +
> + if (EFI_ERROR(Status)){
> + gBS->UninstallMultipleProtocolInterfaces (
> + &NicDevice->Controller,
> + &gEfiCallerIdGuid,
> + NicDevice,
> + &gEfiSimpleNetworkProtocolGuid,
> + &NicDevice->SimpleNetwork,
> + &gEfiDevicePathProtocolGuid,
> + NicDevice->MyDevPath,
> + NULL
> + );
> + gBS->CloseProtocol (
> + Controller,
> + &gEfiDevicePathProtocolGuid,
> + This->DriverBindingHandle,
> + Controller);
> + gBS->CloseProtocol (
> + Controller,
> + &gEfiUsbIoProtocolGuid,
> + This->DriverBindingHandle,
> + Controller
> + );
> + goto ERR;
> + }
> +
> + return Status;
> +
> +
> +ERR:
> +
> + if (NicDevice->BulkInbuf != NULL) {
> + gBS->FreePool (NicDevice->BulkInbuf);
> + }
> +
> + if (NicDevice->TxTest != NULL) {
> + gBS->FreePool (NicDevice->TxTest);
> + }
> +
> + if (NicDevice->MyDevPath != NULL) {
> + gBS->FreePool (NicDevice->MyDevPath);
> + }
> +
> + if (NicDevice != NULL) {
> + gBS->FreePool (NicDevice);
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and
> + closing the DevicePath and PciIo protocols on Controller.
> +
> + @param [in] This 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 * This,
> + IN EFI_HANDLE Controller,
> + IN UINTN NumberOfChildren,
> + IN EFI_HANDLE * ChildHandleBuffer
> + )
> +{
> + BOOLEAN AllChildrenStopped;
> + EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork;
> + EFI_STATUS Status = EFI_SUCCESS;
> + NIC_DEVICE *NicDevice;
> + UINTN Index;
> +
> + //
> + // Complete all outstanding transactions to Controller.
> + // Don't allow any new transaction to Controller to be started.
> + //
> + if (NumberOfChildren == 0) {
> + Status = gBS->OpenProtocol (
> + Controller,
> + &gEfiSimpleNetworkProtocolGuid,
> + (VOID **) &SimpleNetwork,
> + This->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,
> + This->DriverBindingHandle,
> + Controller
> + );
> + gBS->CloseProtocol (
> + Controller,
> + &gEfiUsbIoProtocolGuid,
> + This->DriverBindingHandle,
> + Controller
> + );
> + return EFI_SUCCESS;
> + }
> +
> + NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
> +
> + Status = gBS->UninstallMultipleProtocolInterfaces (
> + Controller,
> + &gEfiCallerIdGuid,
> + NicDevice,
> + &gEfiSimpleNetworkProtocolGuid,
> + &NicDevice->SimpleNetwork,
> + &gEfiDevicePathProtocolGuid,
> + NicDevice->MyDevPath,
> + NULL
> + );
> +
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + //
> + // Close the bus driver
> + //
> + Status = gBS->CloseProtocol (
> + Controller,
> + &gEfiDevicePathProtocolGuid,
> + This->DriverBindingHandle,
> + Controller
> + );
> +
> + Status = gBS->CloseProtocol (
> + Controller,
> + &gEfiUsbIoProtocolGuid,
> + This->DriverBindingHandle,
> + Controller
> + );
> +
> + return EFI_SUCCESS;
> + }
> +
> + AllChildrenStopped = TRUE;
> +
> + for (Index = 0; Index < NumberOfChildren; Index++) {
> + Status = gBS->OpenProtocol (
> + ChildHandleBuffer[Index],
> + &gEfiSimpleNetworkProtocolGuid,
> + (VOID **) &SimpleNetwork,
> + This->DriverBindingHandle,
> + Controller,
> + EFI_OPEN_PROTOCOL_GET_PROTOCOL
> + );
> +
> + if (EFI_ERROR (Status)) {
> + AllChildrenStopped = FALSE;
> + continue;
> + }
> +
> + NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
> +
> + gBS->CloseProtocol (
> + Controller,
> + &gEfiUsbIoProtocolGuid,
> + This->DriverBindingHandle,
> + ChildHandleBuffer[Index]
> + );
> +
> + Status = gBS->UninstallMultipleProtocolInterfaces (
> + ChildHandleBuffer[Index],
> + &gEfiCallerIdGuid,
> + NicDevice,
> + &gEfiSimpleNetworkProtocolGuid,
> + &NicDevice->SimpleNetwork,
> + &gEfiDevicePathProtocolGuid,
> + NicDevice->MyDevPath,
> + NULL
> + );
> +
> + if (EFI_ERROR (Status)) {
> + Status = gBS->OpenProtocol (
> + Controller,
> + &gEfiUsbIoProtocolGuid,
> + (VOID **) &NicDevice->UsbIo,
> + This->DriverBindingHandle,
> + ChildHandleBuffer[Index],
> + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
> + );
> + } else {
> + if (NicDevice->BulkInbuf != NULL) {
> + gBS->FreePool (NicDevice->BulkInbuf);
> + }
> +
> + if (NicDevice->TxTest != NULL) {
> + gBS->FreePool (NicDevice->TxTest);
> + }
> +
> + if (NicDevice->MyDevPath != NULL) {
> + gBS->FreePool (NicDevice->MyDevPath);
> + }
> +
> + if (NicDevice != NULL) {
> + gBS->FreePool (NicDevice);
> + }
> + }
> + }
> +
> + 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 *Handle;
> + EFI_STATUS Status;
> +
> + //
> + // Determine which devices are using this driver
> + //
> + BufferSize = 0;
> + Handle = 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 (
> + EfiBootServicesData,
> + BufferSize,
> + (VOID **) &Handle
> + );
> + if (EFI_ERROR (Status)) {
> + break;
> + }
> +
> + //
> + // Locate the block IO devices
> + //
> + Status = gBS->LocateHandle (
> + ByProtocol,
> + &gEfiCallerIdGuid,
> + NULL,
> + &BufferSize,
> + Handle);
> + if (EFI_ERROR (Status)) {
> + //
> + // Error getting handles
> + //
> +
> + break;
> + }
> +
> + //
> + // Remove any use of the driver
> + //
> + Max = BufferSize / sizeof (Handle[0]);
> + for (Index = 0; Max > Index; Index++) {
> + Status = DriverStop (&gDriverBinding,
> + Handle[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 (Handle != NULL) {
> + gBS->FreePool (Handle);
> + }
> +
> + //
> + // 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] SystemTable Address of the system table.
> +
> +@retval EFI_SUCCESS Image successfully loaded.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +EntryPoint (
> + IN EFI_HANDLE ImageHandle,
> + IN EFI_SYSTEM_TABLE *SystemTable
> + )
> +{
> + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
> + EFI_STATUS Status;
> +
> + //
> + // Enable unload support
> + //
> + Status = gBS->HandleProtocol (
> + gImageHandle,
> + &gEfiLoadedImageProtocolGuid,
> + (VOID **)&LoadedImage
> + );
> + if (!EFI_ERROR (Status)) {
> + LoadedImage->Unload = DriverUnload;
> + }
> +
> + //
> + // Add the driver to the list of drivers
> + //
> + Status = EfiLibInstallDriverBindingComponentName2 (
> + ImageHandle,
> + SystemTable,
> + &gDriverBinding,
> + ImageHandle,
> + &gComponentName,
> + &gComponentName2
> + );
> +
> + return Status;
> +}
> diff --git a/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/SimpleNetwork.c
> b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/SimpleNetwork.c
> new file mode 100644
> index 000000000000..9a80bf3d33cd
> --- /dev/null
> +++ b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88772c/SimpleNetwork.c
> @@ -0,0 +1,1581 @@
> +/** @file
> + Provides the Simple Network functions.
> +
> + Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.
> + Copyright (c) 2020, ARM Limited. All rights reserved.
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "Ax88772.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] SimpleNetwork 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 SimpleNetwork parameter was NULL or did not point to a valid
> + EFI_SIMPLE_NETWORK_PROTOCOL structure.
> + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
> + @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
> +
> +**/
> +EFI_STATUS
> +ReceiveFilterUpdate (
> + IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork
> + )
> +{
> + EFI_SIMPLE_NETWORK_MODE *Mode;
> + NIC_DEVICE *NicDevice;
> + EFI_STATUS Status;
> + UINT32 Index;
> +
> + //
> + // Set the MAC address
> + //
> + NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
> + Mode = SimpleNetwork->Mode;
> + //
> + // Clear the multicast hash table
> + //
> + Ax88772MulticastClear (NicDevice);
> +
> + //
> + // Load the multicast hash table
> + //
> + if ((Mode->ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
> + for (Index = 0; Index < Mode->MCastFilterCount; Index++) {
> + //
> + // Enable the next multicast address
> + //
> + Ax88772MulticastSet (NicDevice,
> + &Mode->MCastFilter[Index].Addr[0]);
> + }
> + }
> +
> + Status = Ax88772RxControl (NicDevice, Mode->ReceiveFilterSetting);
> +
> + //
> + // Return the operation status
> + //
> + return Status;
> +}
> +
> +
> +/**
> + This function updates the SNP driver status.
> +
> + This function gets the current interrupt and recycled transmit
> + buffer status from the network interface. The interrupt status
> + and the media status are returned as a bit mask in InterruptStatus.
> + If InterruptStatus is NULL, the interrupt status will not be read.
> + Upon successful return of the media status, the MediaPresent field
> + of EFI_SIMPLE_NETWORK_MODE will be updated to reflect any change
> + of media status. If TxBuf is not NULL, a recycled transmit buffer
> + address will be retrived. If a recycled transmit buffer address
> + is returned in TxBuf, then the buffer has been successfully
> + transmitted, and the status for that buffer is cleared.
> +
> + This function calls ::Ax88772Rx to update the media status and
> + queue any receive packets.
> +
> + @param [in] SimpleNetwork Protocol instance pointer
> + @param [in] InterruptStatus A pointer to the bit mask of the current active interrupts.
> + If this is NULL, the interrupt status will not be read from
> + the device. If this is not NULL, the interrupt status will
> + be read from teh device. When the interrupt status is read,
> + it will also be cleared. Clearing the transmit interrupt
> + does not empty the recycled transmit buffer array.
> + @param [out] TxBuf Recycled transmit buffer address. The network interface will
> + not transmit if its internal recycled transmit buffer array is
> + full. Reading the transmit buffer does not clear the transmit
> + interrupt. If this is NULL, then the transmit buffer status
> + will not be read. If there are not transmit buffers to recycle
> + and TxBuf is not NULL, *TxBuf will be set to NULL.
> +
> + @retval EFI_SUCCESS This operation was successful.
> + @retval EFI_NOT_STARTED The network interface was not started.
> + @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
> + EFI_SIMPLE_NETWORK_PROTOCOL structure.
> + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
> +
> +**/
> +
> +EFI_STATUS
> +EFIAPI
> +SN_GetStatus (
> + IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
> + OUT UINT32 *InterruptStatus,
> + OUT VOID **TxBuf
> + )
> +{
> + EFI_SIMPLE_NETWORK_MODE *Mode;
> + NIC_DEVICE *NicDevice = NULL;
> + EFI_STATUS Status = EFI_SUCCESS;
> + EFI_TPL TplPrevious;
> +
> + TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
> + //
> + // Verify the parameters
> + //
> + if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
> + //
> + // Return the transmit buffer
> + //
> + NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
> +
> + if ((TxBuf != NULL) && (NicDevice->TxBuffer != NULL)) {
> + *TxBuf = NicDevice->TxBuffer;
> + NicDevice->TxBuffer = NULL;
> + }
> +
> + Mode = SimpleNetwork->Mode;
> + if (EfiSimpleNetworkInitialized == Mode->State) {
> + if ((TxBuf == NULL) && (InterruptStatus == NULL)) {
> + Status = EFI_INVALID_PARAMETER;
> + goto EXIT;
> + }
> +
> +#if REPORTLINK
> +#else
> + if (!NicDevice->LinkUp || !NicDevice->Complete) {
> +#endif
> + Status = Ax88772NegotiateLinkComplete (NicDevice,
> + &NicDevice->PollCount,
> + &NicDevice->Complete,
> + &NicDevice->LinkUp,
> + &NicDevice->LinkSpeed100Mbps,
> + &NicDevice->FullDuplex);
> +
> + if (EFI_ERROR(Status))
> + goto EXIT;
> +#if REPORTLINK
> + if (NicDevice->LinkUp && NicDevice->Complete) {
> + Mode->MediaPresent = TRUE;
> + Status = ReceiveFilterUpdate (SimpleNetwork);
> + } else {
> + Mode->MediaPresent = FALSE;
> + }
> +#else
> + if (NicDevice->LinkUp && NicDevice->Complete) {
> + Mode->MediaPresent = TRUE;
> + Mode->MediaPresentSupported = FALSE;
> + Status = ReceiveFilterUpdate (SimpleNetwork);
> + }
> + }
> +#endif
> + } else {
> + if (EfiSimpleNetworkStarted == Mode->State) {
> + Status = EFI_DEVICE_ERROR;
> + } else {
> + Status = EFI_NOT_STARTED ;
> + }
> + }
> + } else {
> + Status = EFI_INVALID_PARAMETER;
> + }
> + if (InterruptStatus != NULL) {
> + *InterruptStatus = 0;
> + }
> +
> +EXIT:
> + gBS->RestoreTPL(TplPrevious) ;
> +
> + return Status;
> +}
> +
> +/**
> + This function performs read and write operations on the NVRAM device
> + attached to a network interface.
> +
> + @param [in] SimpleNetwork Protocol instance pointer
> + @param [in] ReadWrite TRUE for read operations, FALSE for write operations.
> + @param [in] Offset Byte offset in the NVRAM device at which to start the
> + read or write operation. This must be a multiple of
> + NvRamAccessSize and less than NvRamSize.
> + @param [in] BufferSize The number of bytes to read or write from the NVRAM device.
> + This must also be a multiple of NvramAccessSize.
> + @param [in, out] Buffer A pointer to the data buffer.
> +
> + @retval EFI_SUCCESS This operation was successful.
> + @retval EFI_NOT_STARTED The network interface was not started.
> + @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
> + EFI_SIMPLE_NETWORK_PROTOCOL structure.
> + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
> + @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SN_NvData (
> + IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
> + IN BOOLEAN ReadWrite,
> + IN UINTN Offset,
> + IN UINTN BufferSize,
> + IN OUT VOID *Buffer
> + )
> +{
> + EFI_STATUS Status = EFI_INVALID_PARAMETER;
> + EFI_TPL TplPrevious;
> + EFI_SIMPLE_NETWORK_MODE *Mode;
> + NIC_DEVICE *NicDevice;
> + UINTN Index;
> +
> + TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
> + if ((SimpleNetwork == NULL) || (SimpleNetwork->Mode == NULL)) {
> + Status = EFI_INVALID_PARAMETER;
> + goto EXIT;
> + }
> +
> + NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
> + Mode = SimpleNetwork->Mode;
> +
> + if (EfiSimpleNetworkInitialized != Mode->State) {
> + Status = EFI_NOT_STARTED;
> + goto EXIT;
> + }
> +
> + if (Offset != 0) {
> + if (((Offset % Mode->NvRamAccessSize) != 0) ||
> + (Offset >= Mode->NvRamSize)) {
> + Status = EFI_INVALID_PARAMETER;
> + goto EXIT;
> + }
> + }
> + //
> + // Offset must be a multiple of NvRamAccessSize and less than NvRamSize.
> + //
> + if ((BufferSize % Mode->NvRamAccessSize) != 0) {
> + Status = EFI_INVALID_PARAMETER;
> + goto EXIT;
> + }
> +
> + if (BufferSize + Offset > Mode->NvRamSize) {
> + Status = EFI_INVALID_PARAMETER;
> + goto EXIT;
> + }
> +
> + if (Buffer == NULL) {
> + Status = EFI_INVALID_PARAMETER;
> + goto EXIT;
> + }
> +
> + //
> + // ReadWrite: TRUE FOR READ FALSE FOR WRITE
> + //
> + if (ReadWrite) {
> + for (Index = 0; Index < BufferSize / 2; Index++) {
> + Status = Ax88772SromRead (NicDevice,
> + (UINT32)(Offset/2 + Index),
> + (((UINT16*)Buffer) + Index));
> + }
> + } else {
> + Status = Ax88772EnableSromWrite(NicDevice);
> + if (EFI_ERROR(Status))
> + goto EXIT;
> +
> + for (Index = 0; Index < BufferSize / 2; Index++) {
> + Status = Ax88772SromWrite (NicDevice,
> + (UINT32)(Offset/2 + Index),
> + (((UINT16*)Buffer) + Index));
> + }
> +
> + Status = Ax88772DisableSromWrite(NicDevice);
> +
> + if (BufferSize == 272)
> + Status = Ax88772ReloadSrom(NicDevice);
> + }
> +
> + //
> + // Return the operation status
> + //
> +EXIT:
> + gBS->RestoreTPL (TplPrevious);
> + return Status;
> +}
> +
> +/**
> + Resets the network adapter and allocates the transmit and receive buffers
> + required by the network interface; optionally, also requests allocation of
> + additional transmit and receive buffers. This routine must be called before
> + any other routine in the Simple Network protocol is called.
> +
> + @param [in] SimpleNetwork Protocol instance pointer
> + @param [in] ExtraRxBufferSize Size in bytes to add to the receive buffer allocation
> + @param [in] ExtraTxBufferSize Size in bytes to add to the transmit buffer allocation
> +
> + @retval EFI_SUCCESS This operation was successful.
> + @retval EFI_NOT_STARTED The network interface was not started.
> + @retval EFI_OUT_OF_RESOURCES There was not enough memory for the transmit and receive buffers
> + @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
> + EFI_SIMPLE_NETWORK_PROTOCOL structure.
> + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
> + @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SN_Initialize (
> + IN EFI_SIMPLE_NETWORK_PROTOCOL * SimpleNetwork,
> + IN UINTN ExtraRxBufferSize,
> + IN UINTN ExtraTxBufferSize
> + )
> +{
> + EFI_SIMPLE_NETWORK_MODE *Mode;
> + EFI_STATUS Status;
> + UINT32 TmpState;
> + EFI_TPL TplPrevious;
> + NIC_DEVICE *NicDevice;
> +
> + TplPrevious = gBS->RaiseTPL (TPL_CALLBACK);
> +
> + //
> + // Verify the parameters
> + //
> + if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
> + //
> + // Determine if the interface is already started
> + //
> + Mode = SimpleNetwork->Mode;
> + if (EfiSimpleNetworkStarted == Mode->State) {
> + if ((0 == ExtraRxBufferSize) && (0 == ExtraTxBufferSize)) {
> + //
> + // Start the adapter
> + //
> + TmpState = Mode->State;
> + Mode->State = EfiSimpleNetworkInitialized;
> + Status = SN_Reset (SimpleNetwork, FALSE);
> + if (EFI_ERROR (Status)) {
> + //
> + // Update the network state
> + //
> + Mode->State = TmpState; // EfiSimpleNetworkInitialized;
> + } else {
> + Mode->MediaPresentSupported = TRUE;
> + NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
> + Mode->MediaPresent = Ax88772GetLinkStatus (NicDevice);
> + }
> + } else {
> + Status = EFI_UNSUPPORTED;
> + }
> + } else {
> + Status = EFI_NOT_STARTED;
> + }
> + } else {
> + Status = EFI_INVALID_PARAMETER;
> + }
> +
> + //
> + // Return the operation status
> + //
> + gBS->RestoreTPL (TplPrevious);
> + return Status;
> +}
> +
> +
> +/**
> + This function converts a multicast IP address to a multicast HW MAC address
> + for all packet transactions.
> +
> + @param [in] SimpleNetwork Protocol instance pointer
> + @param [in] IPv6 Set to TRUE if the multicast IP address is IPv6 [RFC2460].
> + Set to FALSE if the multicast IP address is IPv4 [RFC 791].
> + @param [in] IP The multicast IP address that is to be converted to a
> + multicast HW MAC address.
> + @param [in] MAC The multicast HW MAC address that is to be generated from IP.
> +
> + @retval EFI_SUCCESS This operation was successful.
> + @retval EFI_NOT_STARTED The network interface was not started.
> + @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
> + EFI_SIMPLE_NETWORK_PROTOCOL structure.
> + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
> + @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SN_MCastIPtoMAC (
> + IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
> + IN BOOLEAN IPv6,
> + IN EFI_IP_ADDRESS *IP,
> + IN EFI_MAC_ADDRESS *MAC
> + )
> +{
> + EFI_STATUS Status;
> + EFI_TPL TplPrevious;
> + EFI_SIMPLE_NETWORK_MODE *Mode;
> +
> + TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
> + if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
> + //
> + // The interface must be running
> + //
> + Mode = SimpleNetwork->Mode;
> + if (EfiSimpleNetworkInitialized == Mode->State) {
> + if (IP == NULL || MAC == NULL) {
> + Status = EFI_INVALID_PARAMETER;
> + goto EXIT;
> + }
> + if (IPv6) {
> + Status = EFI_UNSUPPORTED;
> + goto EXIT;
> + } else {
> + //
> + // check if the ip given is a mcast IP
> + //
> + if ((IP->v4.Addr[0] & 0xF0) != 0xE0) {
> + Status = EFI_INVALID_PARAMETER;
> + goto EXIT;
> + } else {
> + MAC->Addr[0] = 0x01;
> + MAC->Addr[1] = 0x00;
> + MAC->Addr[2] = 0x5e;
> + MAC->Addr[3] = (UINT8) (IP->v4.Addr[1] & 0x7f);
> + MAC->Addr[4] = (UINT8) IP->v4.Addr[2];
> + MAC->Addr[5] = (UINT8) IP->v4.Addr[3];
> + Status = EFI_SUCCESS;
> + }
> + }
> + } else {
> + if (EfiSimpleNetworkStarted == Mode->State) {
> + Status = EFI_DEVICE_ERROR;
> + } else {
> + Status = EFI_NOT_STARTED ;
> + }
> + }
> + } else {
> + Status = EFI_INVALID_PARAMETER;
> + }
> +
> +EXIT:
> + gBS->RestoreTPL(TplPrevious);
> + return Status;
> +}
> +
> +/**
> + Attempt to receive a packet from the network adapter.
> +
> + This function retrieves one packet from the receive queue of the network
> + interface. If there are no packets on the receive queue, then EFI_NOT_READY
> + will be returned. If there is a packet on the receive queue, and the size
> + of the packet is smaller than BufferSize, then the contents of the packet
> + will be placed in Buffer, and BufferSize will be udpated with the actual
> + size of the packet. In addition, if SrcAddr, DestAddr, and Protocol are
> + not NULL, then these values will be extracted from the media header and
> + returned. If BufferSize is smaller than the received packet, then the
> + size of the receive packet will be placed in BufferSize and
> + EFI_BUFFER_TOO_SMALL will be returned.
> +
> + This routine calls ::Ax88179Rx to update the media status and
> + empty the network adapter of receive packets.
> +
> + @param [in] SimpleNetwork Protocol instance pointer
> + @param [out] 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 [out] BufferSize The size, in bytes, of the entire packet (media header and
> + data) to be transmitted through the network interface.
> + @param [out] Buffer A pointer to the packet (media header followed by data) to
> + to be transmitted. This parameter can not be NULL. If
> + HeaderSize is zero, then the media header is Buffer must
> + already be filled in by the caller. If HeaderSize is nonzero,
> + then the media header will be filled in by the Transmit()
> + function.
> + @param [out] SrcAddr The source HW MAC address. If HeaderSize is zero, then
> + this parameter is ignored. If HeaderSize is nonzero and
> + SrcAddr is NULL, then SimpleNetwork->Mode->CurrentAddress
> + is used for the source HW MAC address.
> + @param [out] DestAddr The destination HW MAC address. If HeaderSize is zero, then
> + this parameter is ignored.
> + @param [out] Protocol The type of header to build. If HeaderSize is zero, then
> + this parameter is ignored.
> +
> + @retval EFI_SUCCESS This operation was successful.
> + @retval EFI_NOT_STARTED The network interface was not started.
> + @retval EFI_NOT_READY No packets have been received on the network interface.
> + @retval EFI_BUFFER_TOO_SMALL The packet is larger than BufferSize bytes.
> + @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
> + EFI_SIMPLE_NETWORK_PROTOCOL structure.
> + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SN_Receive (
> + IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
> + OUT UINTN *HeaderSize,
> + OUT UINTN *BufferSize,
> + OUT VOID *Buffer,
> + OUT EFI_MAC_ADDRESS *SrcAddr,
> + OUT EFI_MAC_ADDRESS *DestAddr,
> + OUT UINT16 *Protocol
> + )
> +{
> + ETHERNET_HEADER *Header;
> + EFI_SIMPLE_NETWORK_MODE *Mode;
> + NIC_DEVICE *NicDevice = NULL;
> + EFI_STATUS Status;
> + EFI_TPL TplPrevious;
> + UINT16 Type;
> + UINT16 CurrentPktLen;
> +
> +
> + TplPrevious = gBS->RaiseTPL (TPL_CALLBACK);
> + //
> + // Verify the parameters
> + //
> + if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
> + //
> + // The interface must be running
> + //
> + Mode = SimpleNetwork->Mode;
> + if (EfiSimpleNetworkInitialized == Mode->State) {
> + if ((BufferSize == NULL) || (Buffer == NULL)) {
> + Status = EFI_INVALID_PARAMETER;
> + gBS->RestoreTPL (TplPrevious);
> + return Status;
> + }
> +
> + //
> + // Update the link status
> + //
> + NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
> +
> + if (NicDevice->LinkUp && NicDevice->Complete) {
> + if ((HeaderSize != NULL) && (*HeaderSize == 7720)) {
> + NicDevice->Grub_f = TRUE;
> + }
> +
> + if ((NicDevice->Grub_f) && (*HeaderSize != 7720)) {
> + gBS->RestoreTPL (TplPrevious);
> + return EFI_NOT_READY;
> + }
> +
> + //
> + // Attempt to receive a packet
> + //
> + if (0 == NicDevice->PktCnt) {
> + Status = Ax88772BulkIn(NicDevice);
> + if (EFI_ERROR(Status)) {
> + goto no_pkt;
> + }
> + }
> +
> + CurrentPktLen = *((UINT16*) (NicDevice->CurPktHdrOff));
> + CurrentPktLen &= 0x7ff;
> +
> + if ((60 <= CurrentPktLen) &&
> + (CurrentPktLen - 14 <= MAX_ETHERNET_PKT_SIZE)) {
> + if (*BufferSize < (UINTN)CurrentPktLen) {
> + gBS->RestoreTPL (TplPrevious);
> + return EFI_BUFFER_TOO_SMALL;
> + }
> +
> + *BufferSize = CurrentPktLen;
> + CopyMem (Buffer, NicDevice->CurPktOff, CurrentPktLen);
> + Header = (ETHERNET_HEADER *) NicDevice->CurPktOff;
> +
> + if ((HeaderSize != NULL) && (*HeaderSize != 7720)) {
> + *HeaderSize = sizeof (*Header);
> + }
> + if (DestAddr != NULL) {
> + CopyMem (DestAddr, &Header->DestAddr, PXE_HWADDR_LEN_ETHER);
> + }
> + if (SrcAddr != NULL) {
> + CopyMem (SrcAddr, &Header->SrcAddr, PXE_HWADDR_LEN_ETHER);
> + }
> + if (Protocol != NULL) {
> + Type = Header->Type;
> + Type = (UINT16)((Type >> 8) | (Type << 8));
> + *Protocol = Type;
> + }
> + NicDevice->PktCnt--;
> + NicDevice->CurPktHdrOff += (CurrentPktLen + 4 + 1) & 0xfffe;
> + NicDevice->CurPktOff = NicDevice->CurPktHdrOff + 4;
> + Status = EFI_SUCCESS;
> + } else {
> + NicDevice->PktCnt = 0;
> + Status = EFI_DEVICE_ERROR;
> + }
> + } else {
> + //
> + // Link no up
> + //
> + Status = EFI_NOT_READY;
> + }
> + } else {
> + if (EfiSimpleNetworkStarted == Mode->State) {
> + Status = EFI_DEVICE_ERROR;
> + } else {
> + Status = EFI_NOT_STARTED;
> + }
> + }
> + } else {
> + Status = EFI_INVALID_PARAMETER;
> + }
> +
> + //
> + // Return the operation status
> + //
> +no_pkt:
> + gBS->RestoreTPL (TplPrevious);
> + return Status;
> +}
> +
> +/**
> + This function is used to enable and disable the hardware and software receive
> + filters for the underlying network device.
> +
> + The receive filter change is broken down into three steps:
> +
> + 1. The filter mask bits that are set (ON) in the Enable parameter
> + are added to the current receive filter settings.
> +
> + 2. The filter mask bits that are set (ON) in the Disable parameter
> + are subtracted from the updated receive filter settins.
> +
> + 3. If the resulting filter settigns is not supported by the hardware
> + a more liberal setting is selected.
> +
> + If the same bits are set in the Enable and Disable parameters, then the bits
> + in the Disable parameter takes precedence.
> +
> + If the ResetMCastFilter parameter is TRUE, then the multicast address list
> + filter is disabled (irregardless of what other multicast bits are set in
> + the enable and Disable parameters). The SNP->Mode->MCastFilterCount field
> + is set to zero. The SNP->Mode->MCastFilter contents are undefined.
> +
> + After enableing or disabling receive filter settings, software should
> + verify the new settings by checking the SNP->Mode->ReceeiveFilterSettings,
> + SNP->Mode->MCastFilterCount and SNP->Mode->MCastFilter fields.
> +
> + Note: Some network drivers and/or devices will automatically promote
> + receive filter settings if the requested setting can not be honored.
> + For example, if a request for four multicast addresses is made and
> + the underlying hardware only supports two multicast addresses the
> + driver might set the promiscuous or promiscuous multicast receive filters
> + instead. The receiving software is responsible for discarding any extra
> + packets that get through the hardware receive filters.
> +
> + If ResetMCastFilter is TRUE, then the multicast receive filter list
> + on the network interface will be reset to the default multicast receive
> + filter list. If ResetMCastFilter is FALSE, and this network interface
> + allows the multicast receive filter list to be modified, then the
> + MCastFilterCnt and MCastFilter are used to update the current multicast
> + receive filter list. The modified receive filter list settings can be
> + found in the MCastFilter field of EFI_SIMPLE_NETWORK_MODE.
> +
> + This routine calls ::ReceiveFilterUpdate to update the receive
> + state in the network adapter.
> +
> + @param [in] SimpleNetwork Protocol instance pointer
> + @param [in] Enable A bit mask of receive filters to enable on the network interface.
> + @param [in] Disable A bit mask of receive filters to disable on the network interface.
> + For backward compatibility with EFI 1.1 platforms, the
> + EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit must be set
> + when the ResetMCastFilter parameter is TRUE.
> + @param [in] ResetMCastFilter Set to TRUE to reset the contents of the multicast receive
> + filters on the network interface to their default values.
> + @param [in] MCastFilterCnt Number of multicast HW MAC address in the new MCastFilter list.
> + This value must be less than or equal to the MaxMCastFilterCnt
> + field of EFI_SIMPLE_NETWORK_MODE. This field is optional if
> + ResetMCastFilter is TRUE.
> + @param [in] MCastFilter A pointer to a list of new multicast receive filter HW MAC
> + addresses. This list will replace any existing multicast
> + HW MAC address list. This field is optional if ResetMCastFilter
> + is TRUE.
> +
> + @retval EFI_SUCCESS This operation was successful.
> + @retval EFI_NOT_STARTED The network interface was not started.
> + @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
> + EFI_SIMPLE_NETWORK_PROTOCOL structure.
> + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
> + @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +SN_ReceiveFilters (
> + IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
> + IN UINT32 Enable,
> + IN UINT32 Disable,
> + IN BOOLEAN ResetMCastFilter,
> + IN UINTN MCastFilterCnt,
> + IN EFI_MAC_ADDRESS *MCastFilter
> + )
> +{
> + EFI_SIMPLE_NETWORK_MODE *Mode;
> + EFI_STATUS Status = EFI_SUCCESS;
> + EFI_TPL TplPrevious;
> + UINTN Index;
> + UINT8 Temp;
> +
> + TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
> + Mode = SimpleNetwork->Mode;
> +
> + if (SimpleNetwork == NULL) {
> + gBS->RestoreTPL(TplPrevious);
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + switch (Mode->State) {
> + case EfiSimpleNetworkInitialized:
> + break;
> +
> + case EfiSimpleNetworkStopped:
> + Status = EFI_NOT_STARTED;
> + gBS->RestoreTPL(TplPrevious);
> + return Status;
> +
> + default:
> + Status = EFI_DEVICE_ERROR;
> + gBS->RestoreTPL(TplPrevious);
> + return Status;
> + }
> +
> + //
> + // check if we are asked to enable or disable something that the SNP
> + // does not even support!
> + //
> + if (((Enable &~Mode->ReceiveFilterMask) != 0) ||
> + ((Disable &~Mode->ReceiveFilterMask) != 0)) {
> + Status = EFI_INVALID_PARAMETER;
> + gBS->RestoreTPL(TplPrevious);
> + return Status;
> + }
> +
> + if (ResetMCastFilter) {
> + if ((0 == (Mode->ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST)) &&
> + Enable == 0 &&
> + Disable == 2) {
> + gBS->RestoreTPL(TplPrevious);
> + return EFI_SUCCESS;
> + }
> + Mode->MCastFilterCount = 0;
> + SetMem (&Mode->MCastFilter[0],
> + sizeof(EFI_MAC_ADDRESS) * MAX_MCAST_FILTER_CNT,
> + 0);
> + } else {
> + if (MCastFilterCnt != 0) {
> + EFI_MAC_ADDRESS * MulticastAddress;
> + MulticastAddress = MCastFilter;
> +
> + if ((MCastFilterCnt > Mode->MaxMCastFilterCount) ||
> + (MCastFilter == NULL)) {
> + Status = EFI_INVALID_PARAMETER;
> + gBS->RestoreTPL(TplPrevious);
> + return Status;
> + }
> +
> + for (Index = 0 ; Index < MCastFilterCnt ; Index++) {
> + Temp = MulticastAddress->Addr[0];
> + if ((Temp & 0x01) != 0x01) {
> + gBS->RestoreTPL(TplPrevious);
> + return EFI_INVALID_PARAMETER;
> + }
> + MulticastAddress++;
> + }
> +
> + Mode->MCastFilterCount = (UINT32)MCastFilterCnt;
> + CopyMem (&Mode->MCastFilter[0],
> + MCastFilter,
> + MCastFilterCnt * sizeof (EFI_MAC_ADDRESS));
> + }
> + }
> +
> + if (Enable == 0 && Disable == 0 && !ResetMCastFilter && MCastFilterCnt == 0) {
> + Status = EFI_SUCCESS;
> + gBS->RestoreTPL(TplPrevious);
> + return Status;
> + }
> +
> + if ((Enable & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0 && MCastFilterCnt == 0) {
> + Status = EFI_INVALID_PARAMETER;
> + gBS->RestoreTPL(TplPrevious);
> + return Status;
> + }
> +
> + Mode->ReceiveFilterSetting |= Enable;
> + Mode->ReceiveFilterSetting &= ~Disable;
> +
> + Status = ReceiveFilterUpdate (SimpleNetwork);
> +
> + if (EFI_DEVICE_ERROR == Status || EFI_INVALID_PARAMETER == Status)
> + Status = EFI_SUCCESS;
> +
> + gBS->RestoreTPL(TplPrevious);
> +
> + return Status;
> +}
> +
> +/**
> + Reset the network adapter.
> +
> + Resets a network adapter and reinitializes it with the parameters that
> + were provided in the previous call to Initialize (). The transmit and
> + receive queues are cleared. Receive filters, the station address, the
> + statistics, and the multicast-IP-to-HW MAC addresses are not reset by
> + this call.
> +
> + This routine calls ::Ax88772Reset to perform the adapter specific
> + reset operation. This routine also starts the link negotiation
> + by calling ::Ax88772NegotiateLinkStart.
> +
> + @param [in] SimpleNetwork Protocol instance pointer
> + @param [in] ExtendedVerification 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 SimpleNetwork 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 *SimpleNetwork,
> + IN BOOLEAN ExtendedVerification
> + )
> +{
> + EFI_SIMPLE_NETWORK_MODE *Mode;
> + NIC_DEVICE *NicDevice;
> + EFI_STATUS Status;
> + EFI_TPL TplPrevious;
> +
> + TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
> + //
> + // Verify the parameters
> + //
> + if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
> + Mode = SimpleNetwork->Mode;
> + if (EfiSimpleNetworkInitialized == Mode->State) {
> + //
> + // Update the device state
> + //
> + NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
> +
> + //
> + // Reset the device
> + //
> + if (!NicDevice->FirstRst) {
> + Status = EFI_SUCCESS;
> + } else {
> + Status = Ax88772Reset (NicDevice);
> + if (!EFI_ERROR (Status)) {
> + Status = ReceiveFilterUpdate (SimpleNetwork);
> + if (!EFI_ERROR (Status) && !NicDevice->LinkUp && NicDevice->FirstRst) {
> + Status = Ax88772NegotiateLinkStart (NicDevice);
> + NicDevice->FirstRst = FALSE;
> + }
> + }
> + }
> + } else {
> + Status = EFI_NOT_STARTED;
> + }
> + } else {
> + Status = EFI_INVALID_PARAMETER;
> + }
> + //
> + // Return the operation status
> + //
> + gBS->RestoreTPL(TplPrevious);
> + return Status;
> +}
> +
> +/**
> + Initialize the simple network protocol.
> +
> + This routine calls ::Ax88772MacAddressGet to obtain the
> + MAC address.
> +
> + @param [in] NicDevice NIC_DEVICE_INSTANCE pointer
> +
> + @retval EFI_SUCCESS Setup was successful
> +
> +**/
> +EFI_STATUS
> +SN_Setup (
> + IN NIC_DEVICE *NicDevice
> + )
> +{
> + EFI_SIMPLE_NETWORK_MODE *Mode;
> + EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork;
> + EFI_STATUS Status;
> +
> + //
> + // Initialize the simple network protocol
> + //
> + SimpleNetwork = &NicDevice->SimpleNetwork;
> + SimpleNetwork->Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
> + SimpleNetwork->Start = SN_Start;
> + SimpleNetwork->Stop = SN_Stop;
> + SimpleNetwork->Initialize = SN_Initialize;
> + SimpleNetwork->Reset = SN_Reset;
> + SimpleNetwork->Shutdown = SN_Shutdown;
> + SimpleNetwork->ReceiveFilters = SN_ReceiveFilters;
> + SimpleNetwork->StationAddress = SN_StationAddress;
> + SimpleNetwork->Statistics = SN_Statistics;
> + SimpleNetwork->MCastIpToMac = SN_MCastIPtoMAC;
> + SimpleNetwork->NvData = SN_NvData;
> + SimpleNetwork->GetStatus = SN_GetStatus;
> + SimpleNetwork->Transmit = SN_Transmit;
> + SimpleNetwork->Receive = SN_Receive;
> + SimpleNetwork->WaitForPacket = NULL;
> + Mode = &NicDevice->SimpleNetworkData;
> + SimpleNetwork->Mode = Mode;
> + Mode->State = EfiSimpleNetworkStopped;
> + Mode->HwAddressSize = PXE_HWADDR_LEN_ETHER;
> + Mode->MediaHeaderSize = sizeof (ETHERNET_HEADER);
> + Mode->MaxPacketSize = MAX_ETHERNET_PKT_SIZE;
> + Mode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
> + | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
> + | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
> + | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
> + | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
> + Mode->ReceiveFilterSetting = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
> + | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
> + Mode->MaxMCastFilterCount = ASIX_MCAST_FILTER_CNT;
> + Mode->MCastFilterCount = 0;
> + Mode->NvRamSize = 512;
> + Mode->NvRamAccessSize = 2;
> + SetMem (&Mode->BroadcastAddress,
> + PXE_HWADDR_LEN_ETHER,
> + 0xff);
> +
> + SetMem (&Mode->MCastFilter[0],
> + sizeof(EFI_MAC_ADDRESS) * MAX_MCAST_FILTER_CNT,
> + 0);
> +
> + Mode->IfType = NET_IFTYPE_ETHERNET;
> + Mode->MacAddressChangeable = TRUE;
> + Mode->MultipleTxSupported = FALSE;
> + Mode->MediaPresentSupported = TRUE;
> + Mode->MediaPresent = FALSE;
> +
> + //
> + // Read the MAC address
> + //
> + NicDevice->PhyId = PHY_ID_INTERNAL;
> + NicDevice->LinkSpeed100Mbps = TRUE;
> + NicDevice->FullDuplex = TRUE;
> + NicDevice->Complete = FALSE;
> + NicDevice->LinkUp = FALSE;
> + NicDevice->Grub_f = FALSE;
> + NicDevice->FirstRst = TRUE;
> + NicDevice->PktCnt = 0;
> +
> + Status = Ax88772MacAddressGet (
> + NicDevice,
> + &Mode->PermanentAddress.Addr[0]);
> +
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + //
> + // Use the hardware address as the current address
> + //
> + CopyMem (&Mode->CurrentAddress,
> + &Mode->PermanentAddress,
> + PXE_HWADDR_LEN_ETHER);
> +
> + CopyMem (&NicDevice->MAC,
> + &Mode->PermanentAddress,
> + PXE_HWADDR_LEN_ETHER);
> +
> + Status = gBS->AllocatePool (EfiBootServicesData,
> + AX88772_MAX_BULKIN_SIZE,
> + (VOID **) &NicDevice->BulkInbuf);
> +
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = gBS->AllocatePool (EfiBootServicesData,
> + sizeof (RX_TX_PACKET),
> + (VOID **) &NicDevice->TxTest);
> +
> + if (EFI_ERROR (Status)) {
> + gBS->FreePool (NicDevice->BulkInbuf);
> + return Status;
> + }
> +
> + //
> + // Return the setup status
> + //
> + return Status;
> +}
> +
> +
> +/**
> + This routine starts the network interface.
> +
> + @param [in] SimpleNetwork Protocol instance pointer
> +
> + @retval EFI_SUCCESS This operation was successful.
> + @retval EFI_ALREADY_STARTED The network interface was already started.
> + @retval EFI_INVALID_PARAMETER SimpleNetwork 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 *SimpleNetwork
> + )
> +{
> + NIC_DEVICE *NicDevice;
> + EFI_SIMPLE_NETWORK_MODE *Mode;
> + EFI_STATUS Status;
> + EFI_TPL TplPrevious;
> +
> + TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
> + //
> + // Verify the parameters
> + //
> + Status = EFI_INVALID_PARAMETER;
> + if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
> + Mode = SimpleNetwork->Mode;
> + if (EfiSimpleNetworkStopped == Mode->State) {
> + //
> + // Initialize the mode structure
> + // NVRAM access is not supported
> + //
> + ZeroMem (Mode, sizeof (*Mode));
> +
> + Mode->State = EfiSimpleNetworkStarted;
> + Mode->HwAddressSize = PXE_HWADDR_LEN_ETHER;
> + Mode->MediaHeaderSize = sizeof (ETHERNET_HEADER);
> + Mode->MaxPacketSize = MAX_ETHERNET_PKT_SIZE;
> + Mode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
> + | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
> + | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
> + | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
> + | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
> + Mode->ReceiveFilterSetting = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
> + Mode->MaxMCastFilterCount = ASIX_MCAST_FILTER_CNT;
> + Mode->MCastFilterCount = 0;
> +
> + SetMem (&Mode->MCastFilter[0],
> + sizeof(EFI_MAC_ADDRESS) * MAX_MCAST_FILTER_CNT,
> + 0);
> +
> + Mode->NvRamSize = 512;
> + Mode->NvRamAccessSize = 2;
> + NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
> + Status = Ax88772MacAddressGet (NicDevice, &Mode->PermanentAddress.Addr[0]);
> + CopyMem (&Mode->CurrentAddress,
> + &Mode->PermanentAddress,
> + sizeof (Mode->CurrentAddress));
> + SetMem(&Mode->BroadcastAddress, PXE_HWADDR_LEN_ETHER, 0xff);
> + Mode->IfType = NET_IFTYPE_ETHERNET;
> + Mode->MacAddressChangeable = TRUE;
> + Mode->MultipleTxSupported = FALSE;
> + Mode->MediaPresentSupported = TRUE;
> + Mode->MediaPresent = FALSE;
> +
> + } else {
> + Status = EFI_ALREADY_STARTED;
> + }
> + }
> +
> + //
> + // Return the operation status
> + //
> + gBS->RestoreTPL(TplPrevious);
> + return Status;
> +}
> +
> +
> +/**
> + Set the MAC address.
> +
> + This function modifies or resets the current station address of a
> + network interface. If Reset is TRUE, then the current station address
> + is set ot the network interface's permanent address. If Reset if FALSE
> + then the current station address is changed to the address specified by
> + New.
> +
> + This routine calls ::Ax88772MacAddressSet to update the MAC address
> + in the network adapter.
> +
> + @param [in] SimpleNetwork Protocol instance pointer
> + @param [in] Reset Flag used to reset the station address to the
> + network interface's permanent address.
> + @param [in] New 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 SimpleNetwork 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 *SimpleNetwork,
> + IN BOOLEAN Reset,
> + IN EFI_MAC_ADDRESS *New
> + )
> +{
> + NIC_DEVICE *NicDevice;
> + EFI_SIMPLE_NETWORK_MODE *Mode;
> + EFI_STATUS Status;
> +
> + EFI_TPL TplPrevious;
> +
> + TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
> + //
> + // Verify the parameters
> + //
> + if ((SimpleNetwork != NULL) &&
> + (SimpleNetwork->Mode != NULL) &&
> + ((!Reset) || (Reset && (New != NULL)))) {
> + //
> + // Verify that the adapter is already started
> + //
> + NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
> + Mode = SimpleNetwork->Mode;
> + if (EfiSimpleNetworkInitialized == Mode->State) {
> + //
> + // Determine the adapter MAC address
> + //
> + if (Reset) {
> + //
> + // Use the permanent address
> + //
> + CopyMem (&Mode->CurrentAddress,
> + &Mode->PermanentAddress,
> + sizeof (Mode->CurrentAddress));
> + } else {
> + //
> + // Use the specified address
> + //
> + CopyMem (&Mode->CurrentAddress,
> + New,
> + sizeof (Mode->CurrentAddress));
> + }
> +
> + //
> + // Update the address on the adapter
> + //
> + Status = Ax88772MacAddressSet (NicDevice, &Mode->CurrentAddress.Addr[0]);
> + } else {
> + if (EfiSimpleNetworkStarted == Mode->State) {
> + Status = EFI_DEVICE_ERROR; ;
> + } else {
> + Status = EFI_NOT_STARTED ;
> + }
> + }
> + } else {
> + Status = EFI_INVALID_PARAMETER;
> + }
> +
> + //
> + // Return the operation status
> + //
> + gBS->RestoreTPL(TplPrevious);
> + return Status;
> +}
> +
> +
> +/**
> + This function resets or collects the statistics on a network interface.
> + If the size of the statistics table specified by StatisticsSize is not
> + big enough for all of the statistics that are collected by the network
> + interface, then a partial buffer of statistics is returned in
> + StatisticsTable.
> +
> + @param [in] SimpleNetwork Protocol instance pointer
> + @param [in] Reset Set to TRUE to reset the statistics for the network interface.
> + @param [in, out] StatisticsSize On input the size, in bytes, of StatisticsTable. On output
> + the size, in bytes, of the resulting table of statistics.
> + @param [out] StatisticsTable 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 StatisticsTable is NULL or the buffer is too small.
> + @retval EFI_INVALID_PARAMETER SimpleNetwork 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 *SimpleNetwork,
> + IN BOOLEAN Reset,
> + IN OUT UINTN *StatisticsSize,
> + OUT EFI_NETWORK_STATISTICS *StatisticsTable
> + )
> +{
> + EFI_STATUS Status;
> + EFI_TPL TplPrevious;
> + EFI_SIMPLE_NETWORK_MODE *Mode;
> +
> + TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
> + Mode = SimpleNetwork->Mode;
> +
> + if (EfiSimpleNetworkInitialized == Mode->State) {
> + if ((StatisticsSize != NULL) && (*StatisticsSize == 0)) {
> + Status = EFI_BUFFER_TOO_SMALL;
> + goto EXIT;
> + }
> +
> + if(Reset) {
> + Status = EFI_SUCCESS;
> + } else {
> + Status = EFI_SUCCESS;
> + }
> + } else {
> + if (EfiSimpleNetworkStarted == Mode->State) {
> + Status = EFI_DEVICE_ERROR; ;
> + } else {
> + Status = EFI_NOT_STARTED ;
> + }
> + }
> + //
> + // This is not currently supported
> + //
> +
> +EXIT:
> + gBS->RestoreTPL(TplPrevious);
> + return Status;
> +}
> +
> +
> +/**
> + This function stops a network interface. This call is only valid
> + if the network interface is in the started state.
> +
> + @param [in] SimpleNetwork Protocol instance pointer
> +
> + @retval EFI_SUCCESS This operation was successful.
> + @retval EFI_NOT_STARTED The network interface was not started.
> + @retval EFI_INVALID_PARAMETER SimpleNetwork 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 *SimpleNetwork
> + )
> +{
> + EFI_SIMPLE_NETWORK_MODE *Mode;
> + EFI_STATUS Status;
> + EFI_TPL TplPrevious;
> +
> + TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
> + //
> + // Verify the parameters
> + //
> + if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
> + //
> + // Determine if the interface is started
> + //
> + Mode = SimpleNetwork->Mode;
> +
> + if (EfiSimpleNetworkStarted == Mode->State) {
> + Mode->State = EfiSimpleNetworkStopped;
> + Status = EFI_SUCCESS;
> + } else {
> + Status = EFI_NOT_STARTED;
> + }
> + } else {
> + Status = EFI_INVALID_PARAMETER;
> + }
> +
> + //
> + // Return the operation status
> + //
> + gBS->RestoreTPL(TplPrevious);
> + return Status;
> +}
> +
> +
> +/**
> + This function releases the memory buffers assigned in the Initialize() call.
> + Ending transmits and receives are lost, and interrupts are cleared and disabled.
> + After this call, only Initialize() and Stop() calls may be used.
> +
> + @param [in] SimpleNetwork Protocol instance pointer
> +
> + @retval EFI_SUCCESS This operation was successful.
> + @retval EFI_NOT_STARTED The network interface was not started.
> + @retval EFI_INVALID_PARAMETER SimpleNetwork 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 *SimpleNetwork
> + )
> +{
> + EFI_SIMPLE_NETWORK_MODE *Mode;
> + UINT32 RxFilter;
> + EFI_STATUS Status;
> + EFI_TPL TplPrevious;
> +
> + TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
> + //
> + // Verify the parameters
> + //
> + if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
> + //
> + // Determine if the interface is already started
> + //
> + Mode = SimpleNetwork->Mode;
> + if (EfiSimpleNetworkInitialized == Mode->State) {
> + //
> + // Stop the adapter
> + //
> + RxFilter = Mode->ReceiveFilterSetting;
> + Mode->ReceiveFilterSetting = 0;
> + Status = SN_Reset (SimpleNetwork, FALSE);
> + Mode->ReceiveFilterSetting = RxFilter;
> + if (!EFI_ERROR (Status)) {
> + //
> + // Update the network state
> + //
> + Mode->State = EfiSimpleNetworkStarted;
> + } else if (EFI_DEVICE_ERROR == Status) {
> + Mode->State = EfiSimpleNetworkStopped;
> + }
> +
> + } else {
> + Status = EFI_NOT_STARTED;
> + }
> + } else {
> + Status = EFI_INVALID_PARAMETER;
> + }
> +
> + //
> + // Return the operation status
> + //
> + gBS->RestoreTPL(TplPrevious);
> + return Status;
> +}
> +
> +
> +/**
> + Send a packet over the network.
> +
> + This function places the packet specified by Header and Buffer on
> + the transmit queue. This function performs a non-blocking transmit
> + operation. When the transmit is complete, the buffer is returned
> + via the GetStatus() call.
> +
> + This routine calls ::Ax88772Rx to empty the network adapter of
> + receive packets. The routine then passes the transmit packet
> + to the network adapter.
> +
> + @param [in] SimpleNetwork 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] Buffer 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] SrcAddr 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] DestAddr The destination HW MAC address. If HeaderSize is zero, then
> + this parameter is ignored.
> + @param [in] Protocol 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 SimpleNetwork 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 *SimpleNetwork,
> + IN UINTN HeaderSize,
> + IN UINTN BufferSize,
> + IN VOID *Buffer,
> + IN EFI_MAC_ADDRESS *SrcAddr,
> + IN EFI_MAC_ADDRESS *DestAddr,
> + IN UINT16 *Protocol
> + )
> +{
> + ETHERNET_HEADER *Header;
> + EFI_SIMPLE_NETWORK_MODE *Mode;
> + NIC_DEVICE *NicDevice;
> + EFI_USB_IO_PROTOCOL *UsbIo;
> + EFI_STATUS Status;
> + UINTN TransferLength;
> + UINT32 TransferStatus;
> + UINT16 Type;
> + EFI_TPL TplPrevious;
> +
> + TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
> + //
> + // Verify the parameters
> + //
> + if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
> + //
> + // The interface must be running
> + //
> + Mode = SimpleNetwork->Mode;
> + if (EfiSimpleNetworkInitialized == Mode->State) {
> + //
> + // Update the link status
> + //
> + NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
> +
> + //
> + // Release the synchronization with Ax88772Timer
> + //
> + if (NicDevice->LinkUp && NicDevice->Complete) {
> + //
> + // Copy the packet into the USB buffer
> + //
> +
> + if ((HeaderSize != 0) && (Mode->MediaHeaderSize != HeaderSize)) {
> + Status = EFI_INVALID_PARAMETER;
> + goto EXIT;
> + }
> + if (BufferSize < Mode->MediaHeaderSize) {
> + Status = EFI_INVALID_PARAMETER;
> + goto EXIT;
> + }
> + if (Buffer == NULL) {
> + Status = EFI_INVALID_PARAMETER;
> + goto EXIT;
> + }
> + if ((HeaderSize != 0) && (DestAddr == NULL)) {
> + Status = EFI_INVALID_PARAMETER;
> + goto EXIT;
> + }
> + if ((HeaderSize != 0) && (Protocol == NULL)) {
> + Status = EFI_INVALID_PARAMETER;
> + goto EXIT;
> + }
> +
> + CopyMem (&NicDevice->TxTest->Data[0], Buffer, BufferSize);
> + NicDevice->TxTest->Length = (UINT16) BufferSize;
> +
> + //
> + // Transmit the packet
> + //
> + Header = (ETHERNET_HEADER *) &NicDevice->TxTest->Data[0];
> + if (HeaderSize != 0) {
> + if (DestAddr != NULL) {
> + CopyMem (&Header->DestAddr, DestAddr, PXE_HWADDR_LEN_ETHER);
> + }
> + if (SrcAddr != NULL) {
> + CopyMem (&Header->SrcAddr, SrcAddr, PXE_HWADDR_LEN_ETHER);
> + } else {
> + CopyMem (&Header->SrcAddr, &Mode->CurrentAddress.Addr[0], PXE_HWADDR_LEN_ETHER);
> + }
> + if (Protocol != NULL) {
> + Type = *Protocol;
> + } else {
> + Type = NicDevice->TxTest->Length;
> + }
> + Type = (UINT16)((Type >> 8) | (Type << 8));
> + Header->Type = Type;
> + }
> +
> +
> + if (NicDevice->TxTest->Length < MIN_ETHERNET_PKT_SIZE) {
> + NicDevice->TxTest->Length = MIN_ETHERNET_PKT_SIZE;
> + ZeroMem (&NicDevice->TxTest->Data[BufferSize],
> + NicDevice->TxTest->Length - BufferSize);
> + }
> +
> + NicDevice->TxTest->LengthBar = ~(NicDevice->TxTest->Length);
> + TransferLength = sizeof (NicDevice->TxTest->Length)
> + + sizeof (NicDevice->TxTest->LengthBar)
> + + NicDevice->TxTest->Length;
> +
> + if (TransferLength % 512 == 0 || TransferLength % 1024 == 0)
> + TransferLength +=4;
> +#if RXTHOU
> + if (NicDevice->RxBurst == 1)
> + NicDevice->RxBurst--;
> +#endif
> + //
> + // Work around USB bus driver bug where a timeout set by receive
> + // succeeds but the timeout expires immediately after, causing the
> + // transmit operation to timeout.
> + //
> + UsbIo = NicDevice->UsbIo;
> + Status = UsbIo->UsbBulkTransfer (UsbIo,
> + BULK_OUT_ENDPOINT,
> + &NicDevice->TxTest->Length,
> + &TransferLength,
> + 0xfffffffe,
> + &TransferStatus);
> + if (EFI_SUCCESS == Status) {
> + Status = TransferStatus;
> + }
> + if (EFI_SUCCESS == Status && EFI_SUCCESS == TransferStatus) {
> + NicDevice->TxBuffer = Buffer;
> + } else {
> + if (EFI_DEVICE_ERROR == Status) {
> + SN_Reset (SimpleNetwork, FALSE);
> + }
> + Status = EFI_NOT_READY;
> + }
> + } else {
> + //
> + // No packets available.
> + //
> + Status = EFI_NOT_READY;
> + }
> + } else {
> + if (EfiSimpleNetworkStarted == Mode->State) {
> + Status = EFI_DEVICE_ERROR;
> + } else {
> + Status = EFI_NOT_STARTED;
> + }
> + }
> + } else {
> + Status = EFI_INVALID_PARAMETER;
> + }
> +
> +EXIT:
> + gBS->RestoreTPL (TplPrevious);
> + return Status;
> +}
> --
> 2.17.1
next prev parent reply other threads:[~2020-06-09 0:37 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-06-08 13:38 [edk2-platform][PATCH v3 0/6] Update ASIX USB Networking drivers Samer El-Haj-Mahmoud
2020-06-08 13:38 ` [edk2-platform][PATCH v3 1/6] Drivers/ASIX: Create ASIX package Samer El-Haj-Mahmoud
2020-06-09 0:37 ` Ni, Ray
2020-06-08 13:38 ` [edk2-platform][PATCH v3 2/6] Drivers/ASIX: Add ASIX Ax88179 driver Samer El-Haj-Mahmoud
2020-06-09 0:37 ` Ni, Ray
2020-06-08 13:38 ` [edk2-platform][PATCH v3 3/6] Drivers/ASIX: Add ASIX Ax88772c driver Samer El-Haj-Mahmoud
2020-06-09 0:37 ` Ni, Ray [this message]
2020-06-08 13:38 ` [edk2-platform][PATCH v3 4/6] Platform/RaspberryPi: Switch RPi3 USB NIC driver to Ax88772c Samer El-Haj-Mahmoud
2020-07-08 14:55 ` Ard Biesheuvel
2020-06-08 13:38 ` [edk2-platform][PATCH v3 5/6] Platform/HiSilicon: Switch HiKey " Samer El-Haj-Mahmoud
2020-07-08 14:55 ` Ard Biesheuvel
2020-06-08 13:38 ` [edk2-platform][PATCH v3 6/6] Drivers/OptionRomPkg: Remove old ASIX NIC drivers Samer El-Haj-Mahmoud
2020-06-09 0:36 ` Ni, Ray
2020-07-08 14:56 ` [edk2-platform][PATCH v3 0/6] Update ASIX USB Networking drivers Ard Biesheuvel
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=734D49CCEBEEF84792F5B80ED585239D5C5A4965@SHSMSX104.ccr.corp.intel.com \
--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