From: "Samer El-Haj-Mahmoud" <samer.el-haj-mahmoud@arm.com>
To: devel@edk2.groups.io
Cc: Ray Ni <ray.ni@intel.com>, Leif Lindholm <leif@nuviainc.com>,
Ard Biesheuvel <ard.biesheuvel@arm.com>
Subject: [edk2-platform][PATCH v1 2/2] Drivers/OptionRomPkg: UsbNetworking: ASIX Ax88772c driver v2.8.0
Date: Wed, 6 May 2020 23:37:20 -0400 [thread overview]
Message-ID: <20200507033720.31152-3-Samer.El-Haj-Mahmoud@arm.com> (raw)
In-Reply-To: <20200507033720.31152-1-Samer.El-Haj-Mahmoud@arm.com>
This is the initial revision of ASIX USB networking UEFI driver
version 2.8.0 for Ax88772c / Ax88772b / Ax88772a
https://www.asix.com.tw/download.php?sub=driverdetail&PItemID=136
Source code contributed by ASIX.
Cc: Ray Ni <ray.ni@intel.com>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Samer El-Haj-Mahmoud <samer.el-haj-mahmoud@arm.com>
---
Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772c.inf | 65 +
Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.h | 1097 +++++++++++++
Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.c | 1296 ++++++++++++++++
Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/ComponentName.c | 246 +++
Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/DriverBinding.c | 637 ++++++++
Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/SimpleNetwork.c | 1612 ++++++++++++++++++++
6 files changed, 4953 insertions(+)
diff --git a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772c.inf b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772c.inf
new file mode 100644
index 000000000000..1d37a5dae34b
--- /dev/null
+++ b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772c.inf
@@ -0,0 +1,65 @@
+## @file
+# Component description file for ASIX AX88772 USB/Ethernet driver.
+#
+# This module provides support for the ASIX AX88772 USB/Ethernet adapter.
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010018
+ BASE_NAME = Ax88772c
+ FILE_GUID = B15239D6-6A01-4808-A0F7-B7F20F073555
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = EntryPoint
+
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources.common]
+ Ax88772.h
+ Ax88772.c
+ ComponentName.c
+ DriverBinding.c
+ SimpleNetwork.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ UefiLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ UefiDriverEntryPoint
+
+[Protocols]
+ gEfiDevicePathProtocolGuid ## BY_START
+ gEfiSimpleNetworkProtocolGuid ## BY_START
+ gEfiUsbIoProtocolGuid ## TO_START
+
+#[Guids]
+# gEfiEventExitBootServicesGuid ## PRODUCES ## Event
+# gEfiEventVirtualAddressChangeGuid ## PRODUCES ## Event
+# gEfiNicIp4ConfigVariableGuid
+
+[Depex]
+ gEfiBdsArchProtocolGuid AND
+ gEfiCpuArchProtocolGuid AND
+ gEfiMetronomeArchProtocolGuid AND
+ gEfiMonotonicCounterArchProtocolGuid AND
+ gEfiRealTimeClockArchProtocolGuid AND
+ gEfiResetArchProtocolGuid AND
+ gEfiRuntimeArchProtocolGuid AND
+ gEfiSecurityArchProtocolGuid AND
+ gEfiTimerArchProtocolGuid AND
+ gEfiVariableWriteArchProtocolGuid AND
+ gEfiVariableArchProtocolGuid AND
+ gEfiWatchdogTimerArchProtocolGuid
diff --git a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.h b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.h
new file mode 100644
index 000000000000..18317fd5c4f7
--- /dev/null
+++ b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.h
@@ -0,0 +1,1097 @@
+/** @file
+ Definitions for ASIX AX88772 Ethernet adapter.
+
+ Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _AX88772_H_
+#define _AX88772_H_
+
+#include <Uefi.h>
+
+#include <Guid/EventGroup.h>
+
+#include <IndustryStandard/Pci.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeLib.h>
+
+#include <Protocol/DevicePath.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/NetworkInterfaceIdentifier.h>
+#include <Protocol/SimpleNetwork.h>
+#include <Protocol/UsbIo.h>
+
+#define MAX_QUEUE_SIZE 50
+#define MAX_BULKIN_SIZE 16384
+#define HW_HDR_LENGTH 8
+#define PASS_SCT 0
+#define REPORTLINK 1
+
+#define ARM 0
+
+#if ARM
+#define MAX_LINKIDLE_THRESHOLD 100
+#else
+#define MAX_LINKIDLE_THRESHOLD 30
+#endif
+
+#define AMI 1
+#define ASIX_MCAST_FILTER_CNT 8
+#define RXTHOU 0
+
+#if 0
+//------------------------------------------------------------------------------
+// Macros
+//------------------------------------------------------------------------------
+
+#if defined(_MSC_VER) /* Handle Microsoft VC++ compiler specifics. */
+#define DBG_ENTER() DEBUG (( 0xffffffff, "Entering " __FUNCTION__ "\n" )) ///< Display routine entry
+#define DBG_EXIT() DEBUG (( 0xffffffff, "Exiting " __FUNCTION__ "\n" )) ///< Display routine exit
+#define DBG_EXIT_DEC(Status) DEBUG (( 0xffffffff, "Exiting " __FUNCTION__ ", Status: %d\n", Status )) ///< Display routine exit with decimal value
+#define DBG_EXIT_HEX(Status) DEBUG (( 0xffffffff, "Exiting " __FUNCTION__ ", Status: 0x%08x\n", Status )) ///< Display routine exit with hex value
+#define DBG_EXIT_STATUS(Status) DEBUG (( 0xffffffff, "Exiting " __FUNCTION__ ", Status: %r\n", Status )) ///< Display routine exit with status value
+#define DBG_EXIT_TF(Status) DEBUG (( 0xffffffff, "Exiting " __FUNCTION__ ", returning %s\n", (FALSE == Status) ? L"FALSE" : L"TRUE" )) ///< Display routine with TRUE/FALSE value
+#else // _MSC_VER
+#define DBG_ENTER() ///< Display routine entry
+#define DBG_EXIT() ///< Display routine exit
+#define DBG_EXIT_DEC(Status) ///< Display routine exit with decimal value
+#define DBG_EXIT_HEX(Status) ///< Display routine exit with hex value
+#define DBG_EXIT_STATUS(Status) ///< Display routine exit with status value
+#define DBG_EXIT_TF(Status) ///< Display routine with TRUE/FALSE value
+#endif // _MSC_VER
+
+#endif
+
+#define USB_IS_IN_ENDPOINT(EndPointAddr) (((EndPointAddr) & BIT7) != 0) ///< Return TRUE/FALSE for IN direction
+#define USB_IS_OUT_ENDPOINT(EndPointAddr) (((EndPointAddr) & BIT7) == 0) ///< Return TRUE/FALSE for OUT direction
+#define USB_IS_BULK_ENDPOINT(Attribute) (((Attribute) & (BIT0 | BIT1)) == USB_ENDPOINT_BULK) ///< Return TRUE/FALSE for BULK type
+#define USB_IS_INTERRUPT_ENDPOINT(Attribute) (((Attribute) & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT) ///< Return TRUE/FALSE for INTERRUPT type
+
+
+#define PRINT(_L_STR) (gST->ConOut->OutputString(gST->ConOut,(_L_STR)))
+//------------------------------------------------------------------------------
+// Constants
+//------------------------------------------------------------------------------
+
+#define DEBUG_RX_BROADCAST 0x40000000 ///< Display RX broadcast messages
+#define DEBUG_RX_MULTICAST 0x20000000 ///< Display RX multicast messages
+#define DEBUG_RX_UNICAST 0x10000000 ///< Display RX unicast messages
+#define DEBUG_MAC_ADDRESS 0x08000000 ///< Display the MAC address
+#define DEBUG_LINK 0x04000000 ///< Display the link status
+#define DEBUG_TX 0x02000000 ///< Display the TX messages
+#define DEBUG_PHY 0x01000000 ///< Display the PHY register values
+#define DEBUG_SROM 0x00800000 ///< Display the SROM contents
+#define DEBUG_TIMER 0x00400000 ///< Display the timer routine entry/exit
+#define DEBUG_TPL 0x00200000 ///< Display the timer routine entry/exit
+
+#if RXTHOU
+#define AX88772_MAX_BULKIN_SIZE 1024 * 17 //32
+#else
+#define AX88772_MAX_BULKIN_SIZE 1024 * 3
+#endif
+
+#define AX88772_MAX_PKT_SIZE 2048 ///< Maximum packet size
+
+#define ETHERNET_HEADER_SIZE sizeof ( ETHERNET_HEADER ) ///< Size in bytes of the Ethernet header
+#define MIN_ETHERNET_PKT_SIZE 60 ///< Minimum packet size including Ethernet header
+#define MAX_ETHERNET_PKT_SIZE 1500 ///< Ethernet spec 3.1.1: Minimum packet size
+
+#define USB_NETWORK_CLASS 0x09 ///< USB Network class code
+#define USB_BUS_TIMEOUT 1000 ///< USB timeout in milliseconds
+
+#define TIMER_MSEC 20 ///< Polling interval for the NIC
+//#define TPL_AX88772 TPL_CALLBACK ///< TPL for routine synchronization
+
+#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
+
+
+/* Freddy */
+#define PRODUCT_ID 0x7720 ///< Product ID for the AX88772 USB 10/100 Ethernet controller
+#define PRODUCT_AX88772A_ID 0x772A
+#define PRODUCT_AX88772B_ID 0x772b
+#define PRODUCT_AX88772B_ASUS_ID 0x7e2b
+#define PRODUCT_AX88772B_LENOVO_ID 0x7203
+/* Freddy */
+
+
+#define RESET_MSEC 1000 ///< Reset duration
+#define PHY_RESET_MSEC 500 ///< PHY reset duration
+
+//
+// RX Control register
+//
+
+#define RXC_PRO 0x0001 ///< Receive all packets
+#define RXC_AMALL 0x0002 ///< Receive all multicast packets
+#define RXC_SEP 0x0004 ///< Save error packets
+#define RXC_AB 0x0008 ///< Receive broadcast packets
+#define RXC_AM 0x0010 ///< Use multicast destination address hash table
+#define RXC_AP 0x0020 ///< Accept physical address from Multicast Filter
+#define RXC_SO 0x0080 ///< Start operation
+#define RXC_MFB 0x0300 ///< Maximum frame burst
+#define RXC_MFB_2048 0 ///< Maximum frame size: 2048 bytes
+#define RXC_MFB_4096 0x0100 ///< Maximum frame size: 4096 bytes
+#define RXC_MFB_8192 0x0200 ///< Maximum frame size: 8192 bytes
+#define RXC_MFB_16384 0x0300 ///< Maximum frame size: 16384 bytes
+
+/*Freddy*/
+#define RXC_RH1M 0x0100 ///< Rx header 1
+#define RXC_RH2M 0x0200 ///< Rx header 2
+#define RXC_RH3M 0x0400 ///< Rx header 3
+/*Freddy*/
+
+//
+// Medium Status register
+//
+
+#define MS_FD 0x0002 ///< Full duplex
+#define MS_ONE 0x0004 ///< Must be one
+#define MS_RFC 0x0010 ///< RX flow control enable
+#define MS_TFC 0x0020 ///< TX flow control enable
+#define MS_PF 0x0080 ///< Pause frame enable
+#define MS_RE 0x0100 ///< Receive enable
+#define MS_PS 0x0200 ///< Port speed 1=100, 0=10 Mbps
+#define MS_SBP 0x0800 ///< Stop back pressure
+#define MS_SM 0x1000 ///< Super MAC support
+
+//
+// Software PHY Select register
+//
+
+#define SPHY_PSEL (1 << 0) ///< Select internal PHY
+#define SPHY_SSMII (1 << 2)
+#define SPHY_SSEN (1 << 4)
+#define SPHY_ASEL 0x02 ///< 1=Auto select, 0=Manual select
+
+//
+// Software Reset register
+//
+
+#define SRR_RR 0x01 ///< Clear receive frame length error
+#define SRR_RT 0x02 ///< Clear transmit frame length error
+#define SRR_BZTYPE 0x04 ///< External PHY reset pin tri-state enable
+#define SRR_PRL 0x08 ///< External PHY reset pin level
+#define SRR_BZ 0x10 ///< Force Bulk to return zero length packet
+#define SRR_IPRL 0x20 ///< Internal PHY reset control
+#define SRR_IPPD 0x40 ///< Internal PHY power down
+
+//
+// PHY ID values
+//
+
+#define PHY_ID_INTERNAL 0x0010 ///< Internal PHY
+
+//
+// USB Commands
+//
+
+#define CMD_PHY_ACCESS_SOFTWARE 0x06 ///< Software in control of PHY
+#define CMD_PHY_REG_READ 0x07 ///< Read PHY register, Value: PHY, Index: Register, Data: Register value
+#define CMD_PHY_REG_WRITE 0x08 ///< Write PHY register, Value: PHY, Index: Register, Data: New 16-bit value
+#define CMD_PHY_ACCESS_HARDWARE 0x0a ///< Hardware in control of PHY
+#define CMD_SROM_READ 0x0b ///< Read SROM register: Value: Address, Data: Value
+#define CMD_SROM_WRITE 0x0c ///< Read SROM register: Value: Address, Data: Value
+#define CMD_SROM_WRITE_EN 0x0d
+#define CMD_SROM_WRITE_DIS 0x0e
+#define CMD_RX_CONTROL_WRITE 0x10 ///< Set the RX control register, Value: New value
+#define CMD_GAPS_WRITE 0x12 ///< Write the gaps register, Value: New value
+#define CMD_MAC_ADDRESS_READ 0x13 ///< Read the MAC address, Data: 6 byte MAC address
+#define CMD_MAC_ADDRESS_WRITE 0x14 ///< Set the MAC address, Data: New 6 byte MAC address
+#define CMD_MULTICAST_HASH_READ 0x15 ///< Read the multicast hash table
+#define CMD_MULTICAST_HASH_WRITE 0x16 ///< Write the multicast hash table, Data: New 8 byte value
+#define CMD_MEDIUM_STATUS_READ 0x1a ///< Read medium status register, Data: Register value
+#define CMD_MEDIUM_STATUS_WRITE 0x1b ///< Write medium status register, Value: New value
+#define CMD_WRITE_GPIOS 0x1f
+#define CMD_RESET 0x20 ///< Reset register, Value: New value
+#define CMD_PHY_SELECT 0x22 ///< PHY select register, Value: New value
+
+/*Freddy*/
+#define CMD_RXQTC 0x2a ///< RX Queue Cascade Threshold Control Register
+/*Freddy*/
+
+//------------------------------
+// USB Endpoints
+//------------------------------
+
+#define CONTROL_ENDPOINT 0 ///< Control endpoint
+#define INTERRUPT_ENDPOINT 1 ///< Interrupt endpoint
+#define BULK_IN_ENDPOINT 2 ///< Receive endpoint
+#define BULK_OUT_ENDPOINT 3 ///< Transmit endpoint
+
+//------------------------------
+// PHY Registers
+//------------------------------
+
+#define PHY_BMCR 0 ///< Control register
+#define PHY_BMSR 1 ///< Status register
+#define PHY_ANAR 4 ///< Autonegotiation advertisement register
+#define PHY_ANLPAR 5 ///< Autonegotiation link parter ability register
+#define PHY_ANER 6 ///< Autonegotiation expansion register
+
+// BMCR - Register 0
+
+#define BMCR_RESET 0x8000 ///< 1 = Reset the PHY, bit clears after reset
+#define BMCR_LOOPBACK 0x4000 ///< 1 = Loopback enabled
+#define BMCR_100MBPS 0x2000 ///< 100 Mbits/Sec
+#define BMCR_10MBPS 0 ///< 10 Mbits/Sec
+#define BMCR_AUTONEGOTIATION_ENABLE 0x1000 ///< 1 = Enable autonegotiation
+#define BMCR_POWER_DOWN 0x0800 ///< 1 = Power down
+#define BMCR_ISOLATE 0x0400 ///< 0 = Isolate PHY
+#define BMCR_RESTART_AUTONEGOTIATION 0x0200 ///< 1 = Restart autonegotiation
+#define BMCR_FULL_DUPLEX 0x0100 ///< Full duplex operation
+#define BMCR_HALF_DUPLEX 0 ///< Half duplex operation
+#define BMCR_COLLISION_TEST 0x0080 ///< 1 = Collision test enabled
+
+// BSMR - Register 1
+
+#define BMSR_100BASET4 0x8000 ///< 1 = 100BASE-T4 mode
+#define BMSR_100BASETX_FDX 0x4000 ///< 1 = 100BASE-TX full duplex
+#define BMSR_100BASETX_HDX 0x2000 ///< 1 = 100BASE-TX half duplex
+#define BMSR_10BASET_FDX 0x1000 ///< 1 = 10BASE-T full duplex
+#define BMSR_10BASET_HDX 0x0800 ///< 1 = 10BASE-T half duplex
+#define BMSR_MF 0x0040 ///< 1 = PHY accepts frames with preamble suppressed
+#define BMSR_AUTONEG_CMPLT 0x0020 ///< 1 = Autonegotiation complete
+#define BMSR_RF 0x0010 ///< 1 = Remote fault
+#define BMSR_AUTONEG 0x0008 ///< 1 = Able to perform autonegotiation
+#define BMSR_LINKST 0x0004 ///< 1 = Link up
+#define BMSR_JABBER_DETECT 0x0002 ///< 1 = jabber condition detected
+#define BMSR_EXTENDED_CAPABILITY 0x0001 ///< 1 = Extended register capable
+
+// ANAR and ANLPAR Registers 4, 5
+
+#define AN_NP 0x8000 ///< 1 = Next page available
+#define AN_ACK 0x4000 ///< 1 = Link partner acknowledged
+#define AN_RF 0x2000 ///< 1 = Remote fault indicated by link partner
+#define AN_FCS 0x0400 ///< 1 = Flow control ability
+#define AN_T4 0x0200 ///< 1 = 100BASE-T4 support
+#define AN_TX_FDX 0x0100 ///< 1 = 100BASE-TX Full duplex
+#define AN_TX_HDX 0x0080 ///< 1 = 100BASE-TX support
+#define AN_10_FDX 0x0040 ///< 1 = 10BASE-T Full duplex
+#define AN_10_HDX 0x0020 ///< 1 = 10BASE-T support
+#define AN_CSMA_CD 0x0001 ///< 1 = IEEE 802.3 CSMA/CD support
+
+
+
+//------------------------------------------------------------------------------
+// Data Types
+//------------------------------------------------------------------------------
+
+/**
+ Ethernet header layout
+
+ IEEE 802.3-2002 Part 3 specification, section 3.1.1.
+**/
+#pragma pack(1)
+typedef struct {
+ UINT8 dest_addr[PXE_HWADDR_LEN_ETHER]; ///< Destination LAN address
+ UINT8 src_addr[PXE_HWADDR_LEN_ETHER]; ///< Source LAN address
+ UINT16 type; ///< Protocol or length
+} ETHERNET_HEADER;
+#pragma pack()
+
+/**
+ Receive and Transmit packet structure
+**/
+#pragma pack(1)
+typedef struct _RX_TX_PACKET {
+ struct _RX_TX_PACKET * pNext; ///< Next receive packet
+ UINT16 Length; ///< Packet length
+ UINT16 LengthBar; ///< Complement of the length
+ UINT8 Data[ AX88772_MAX_PKT_SIZE ]; ///< Received packet data
+} RX_TX_PACKET;
+#pragma pack()
+
+/**
+ AX88772 control structure
+
+ The driver uses this structure to manage the Asix AX88772 10/100
+ Ethernet controller.
+**/
+typedef struct {
+ UINTN Signature; ///< Structure identification
+
+ //
+ // USB data
+ //
+ EFI_HANDLE Controller; ///< Controller handle
+ EFI_USB_IO_PROTOCOL * pUsbIo; ///< USB driver interface
+
+ //
+ // Simple network protocol data
+ //
+ EFI_SIMPLE_NETWORK_PROTOCOL SimpleNetwork; ///< Driver's network stack interface
+ EFI_SIMPLE_NETWORK_MODE SimpleNetworkData; ///< Data for simple network
+
+ //
+ // Ethernet controller data
+ //
+ BOOLEAN bInitialized; ///< Controller initialized
+ UINT16 PhyId; ///< PHY ID
+
+ //
+ // Link state
+ //
+ BOOLEAN b100Mbps; ///< Current link speed, FALSE = 10 Mbps
+ BOOLEAN bComplete; ///< Current state of auto-negotiation
+ BOOLEAN bFullDuplex; ///< Current duplex
+ BOOLEAN bLinkUp; ///< Current link state
+ UINTN PollCount; ///< Number of times the autonegotiation status was polled
+ UINT16 CurRxControl;
+ VOID * pTxBuffer;
+ //
+ // Receive buffer list
+ //
+ UINT8 *pBulkInbuf;
+ UINT8 * pCurPktHdrOff;
+ UINT8 *pCurPktOff;
+ UINT16 PktCnt;
+
+ RX_TX_PACKET * pTxTest;
+
+ UINT8 MulticastHash[8];
+ EFI_MAC_ADDRESS MAC;
+
+ EFI_DEVICE_PATH_PROTOCOL *MyDevPath;
+ BOOLEAN Grub_f;
+ BOOLEAN bFirstRst;
+ BOOLEAN Flag772A;
+#if RXTHOU
+ UINT8 rxburst;
+#endif
+
+} NIC_DEVICE;
+
+
+//
+// Global Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gComponentName2;
+
+#define DEV_FROM_SIMPLE_NETWORK(a) CR (a, NIC_DEVICE, SimpleNetwork, DEV_SIGNATURE) ///< Locate NIC_DEVICE from Simple Network Protocol
+
+//------------------------------------------------------------------------------
+// Simple Network Protocol
+//------------------------------------------------------------------------------
+
+/**
+ Reset the network adapter.
+
+ Resets a network adapter and reinitializes it with the parameters that
+ were provided in the previous call to Initialize (). The transmit and
+ receive queues are cleared. Receive filters, the station address, the
+ statistics, and the multicast-IP-to-HW MAC addresses are not reset by
+ this call.
+
+ This routine calls ::Ax88772Reset to perform the adapter specific
+ reset operation. This routine also starts the link negotiation
+ by calling ::Ax88772NegotiateLinkStart.
+
+ @param [in] pSimpleNetwork Protocol instance pointer
+ @param [in] bExtendedVerification Indicates that the driver may perform a more
+ exhaustive verification operation of the device
+ during reset.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Reset (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
+ IN BOOLEAN bExtendedVerification
+ );
+
+/**
+ Initialize the simple network protocol.
+
+ This routine calls ::Ax88772MacAddressGet to obtain the
+ MAC address.
+
+ @param [in] pNicDevice NIC_DEVICE_INSTANCE pointer
+
+ @retval EFI_SUCCESS Setup was successful
+
+**/
+EFI_STATUS
+SN_Setup (
+ IN NIC_DEVICE * pNicDevice
+ );
+
+/**
+ This routine starts the network interface.
+
+ @param [in] pSimpleNetwork Protocol instance pointer
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_ALREADY_STARTED The network interface was already started.
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Start (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork
+ );
+
+/**
+ Set the MAC address.
+
+ This function modifies or resets the current station address of a
+ network interface. If Reset is TRUE, then the current station address
+ is set ot the network interface's permanent address. If Reset if FALSE
+ then the current station address is changed to the address specified by
+ pNew.
+
+ This routine calls ::Ax88772MacAddressSet to update the MAC address
+ in the network adapter.
+
+ @param [in] pSimpleNetwork Protocol instance pointer
+ @param [in] bReset Flag used to reset the station address to the
+ network interface's permanent address.
+ @param [in] pNew New station address to be used for the network
+ interface.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_StationAddress (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
+ IN BOOLEAN bReset,
+ IN EFI_MAC_ADDRESS * pNew
+ );
+
+/**
+ This function resets or collects the statistics on a network interface.
+ If the size of the statistics table specified by StatisticsSize is not
+ big enough for all of the statistics that are collected by the network
+ interface, then a partial buffer of statistics is returned in
+ StatisticsTable.
+
+ @param [in] pSimpleNetwork Protocol instance pointer
+ @param [in] bReset Set to TRUE to reset the statistics for the network interface.
+ @param [in, out] pStatisticsSize On input the size, in bytes, of StatisticsTable. On output
+ the size, in bytes, of the resulting table of statistics.
+ @param [out] pStatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that
+ conains the statistics.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_BUFFER_TOO_SMALL The pStatisticsTable is NULL or the buffer is too small.
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Statistics (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
+ IN BOOLEAN bReset,
+ IN OUT UINTN * pStatisticsSize,
+ OUT EFI_NETWORK_STATISTICS * pStatisticsTable
+ );
+
+/**
+ This function stops a network interface. This call is only valid
+ if the network interface is in the started state.
+
+ @param [in] pSimpleNetwork Protocol instance pointer
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Stop (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork
+ );
+
+/**
+ This function releases the memory buffers assigned in the Initialize() call.
+ Pending transmits and receives are lost, and interrupts are cleared and disabled.
+ After this call, only Initialize() and Stop() calls may be used.
+
+ @param [in] pSimpleNetwork Protocol instance pointer
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Shutdown (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork
+ );
+
+/**
+ Send a packet over the network.
+
+ This function places the packet specified by Header and Buffer on
+ the transmit queue. This function performs a non-blocking transmit
+ operation. When the transmit is complete, the buffer is returned
+ via the GetStatus() call.
+
+ This routine calls ::Ax88772Rx to empty the network adapter of
+ receive packets. The routine then passes the transmit packet
+ to the network adapter.
+
+ @param [in] pSimpleNetwork Protocol instance pointer
+ @param [in] HeaderSize The size, in bytes, of the media header to be filled in by
+ the Transmit() function. If HeaderSize is non-zero, then
+ it must be equal to SimpleNetwork->Mode->MediaHeaderSize
+ and DestAddr and Protocol parameters must not be NULL.
+ @param [in] BufferSize The size, in bytes, of the entire packet (media header and
+ data) to be transmitted through the network interface.
+ @param [in] pBuffer A pointer to the packet (media header followed by data) to
+ to be transmitted. This parameter can not be NULL. If
+ HeaderSize is zero, then the media header is Buffer must
+ already be filled in by the caller. If HeaderSize is nonzero,
+ then the media header will be filled in by the Transmit()
+ function.
+ @param [in] pSrcAddr The source HW MAC address. If HeaderSize is zero, then
+ this parameter is ignored. If HeaderSize is nonzero and
+ SrcAddr is NULL, then SimpleNetwork->Mode->CurrentAddress
+ is used for the source HW MAC address.
+ @param [in] pDestAddr The destination HW MAC address. If HeaderSize is zero, then
+ this parameter is ignored.
+ @param [in] pProtocol The type of header to build. If HeaderSize is zero, then
+ this parameter is ignored.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_NOT_READY The network interface is too busy to accept this transmit request.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Transmit (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
+ IN UINTN HeaderSize,
+ IN UINTN BufferSize,
+ IN VOID * pBuffer,
+ IN EFI_MAC_ADDRESS * pSrcAddr,
+ IN EFI_MAC_ADDRESS * pDestAddr,
+ IN UINT16 * pProtocol
+ );
+
+//------------------------------------------------------------------------------
+// Support Routines
+//------------------------------------------------------------------------------
+
+/**
+ Get the MAC address
+
+ This routine calls ::Ax88772UsbCommand to request the MAC
+ address from the network adapter.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+ @param [out] pMacAddress Address of a six byte buffer to receive the MAC address.
+
+ @retval EFI_SUCCESS The MAC address is available.
+ @retval other The MAC address is not valid.
+
+**/
+EFI_STATUS
+Ax88772MacAddressGet (
+ IN NIC_DEVICE * pNicDevice,
+ OUT UINT8 * pMacAddress
+ );
+
+/**
+ Set the MAC address
+
+ This routine calls ::Ax88772UsbCommand to set the MAC address
+ in the network adapter.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+ @param [in] pMacAddress Address of a six byte buffer to containing the new MAC address.
+
+ @retval EFI_SUCCESS The MAC address was set.
+ @retval other The MAC address was not set.
+
+**/
+EFI_STATUS
+Ax88772MacAddressSet (
+ IN NIC_DEVICE * pNicDevice,
+ IN UINT8 * pMacAddress
+ );
+
+/**
+ Clear the multicast hash table
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+
+**/
+VOID
+Ax88772MulticastClear (
+ IN NIC_DEVICE * pNicDevice
+ );
+
+/**
+ Enable a multicast address in the multicast hash table
+
+ This routine calls ::Ax88772Crc to compute the hash bit for
+ this MAC address.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+ @param [in] pMacAddress Address of a six byte buffer to containing the MAC address.
+
+**/
+VOID
+Ax88772MulticastSet (
+ IN NIC_DEVICE * pNicDevice,
+ IN UINT8 * pMacAddress
+ );
+
+/**
+ Start the link negotiation
+
+ This routine calls ::Ax88772PhyWrite to start the PHY's link
+ negotiation.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+
+ @retval EFI_SUCCESS The link negotiation was started.
+ @retval other Failed to start the link negotiation.
+
+**/
+EFI_STATUS
+Ax88772NegotiateLinkStart (
+ IN NIC_DEVICE * pNicDevice
+ );
+
+/**
+ Complete the negotiation of the PHY link
+
+ This routine calls ::Ax88772PhyRead to determine if the
+ link negotiation is complete.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+ @param [in, out] pPollCount Address of number of times this routine was polled
+ @param [out] pbComplete Address of boolean to receive complate status.
+ @param [out] pbLinkUp Address of boolean to receive link status, TRUE=up.
+ @param [out] pbHiSpeed Address of boolean to receive link speed, TRUE=100Mbps.
+ @param [out] pbFullDuplex Address of boolean to receive link duplex, TRUE=full.
+
+ @retval EFI_SUCCESS The MAC address is available.
+ @retval other The MAC address is not valid.
+
+**/
+EFI_STATUS
+Ax88772NegotiateLinkComplete (
+ IN NIC_DEVICE * pNicDevice,
+ IN OUT UINTN * pPollCount,
+ OUT BOOLEAN * pbComplete,
+ OUT BOOLEAN * pbLinkUp,
+ OUT BOOLEAN * pbHiSpeed,
+ OUT BOOLEAN * pbFullDuplex
+ );
+
+/**
+ Read a register from the PHY
+
+ This routine calls ::Ax88772UsbCommand to read a PHY register.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+ @param [in] RegisterAddress Number of the register to read.
+ @param [in, out] pPhyData Address of a buffer to receive the PHY register value
+
+ @retval EFI_SUCCESS The PHY data is available.
+ @retval other The PHY data is not valid.
+
+**/
+EFI_STATUS
+Ax88772PhyRead (
+ IN NIC_DEVICE * pNicDevice,
+ IN UINT8 RegisterAddress,
+ IN OUT UINT16 * pPhyData
+ );
+
+/**
+ Write to a PHY register
+
+ This routine calls ::Ax88772UsbCommand to write a PHY register.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+ @param [in] RegisterAddress Number of the register to read.
+ @param [in] PhyData Address of a buffer to receive the PHY register value
+
+ @retval EFI_SUCCESS The PHY data was written.
+ @retval other Failed to wwrite the PHY register.
+
+**/
+EFI_STATUS
+Ax88772PhyWrite (
+ IN NIC_DEVICE * pNicDevice,
+ IN UINT8 RegisterAddress,
+ IN UINT16 PhyData
+ );
+
+/**
+ Reset the AX88772
+
+ This routine uses ::Ax88772UsbCommand to reset the network
+ adapter. This routine also uses ::Ax88772PhyWrite to reset
+ the PHY.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+
+ @retval EFI_SUCCESS The MAC address is available.
+ @retval other The MAC address is not valid.
+
+**/
+EFI_STATUS
+Ax88772Reset (
+ IN NIC_DEVICE * pNicDevice
+ );
+
+VOID
+Ax88772ChkLink (
+ IN NIC_DEVICE * pNicDevice,
+ IN BOOLEAN bUpdateLink
+ );
+
+/**
+ Receive a frame from the network.
+
+ This routine polls the USB receive interface for a packet. If a packet
+ is available, this routine adds the receive packet to the list of
+ pending receive packets.
+
+ This routine calls ::Ax88772NegotiateLinkComplete to verify
+ that the link is up. This routine also calls ::SN_Reset to
+ reset the network adapter when necessary. Finally this
+ routine attempts to receive one or more packets from the
+ network adapter.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+ @param [in] bUpdateLink TRUE = Update link status
+
+**/
+VOID
+Ax88772Rx (
+ IN NIC_DEVICE * pNicDevice,
+ IN BOOLEAN bUpdateLink
+ );
+
+/**
+ Enable or disable the receiver
+
+ This routine calls ::Ax88772UsbCommand to update the
+ receiver state. This routine also calls ::Ax88772MacAddressSet
+ to establish the MAC address for the network adapter.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+ @param [in] RxFilter Simple network RX filter mask value
+
+ @retval EFI_SUCCESS The MAC address was set.
+ @retval other The MAC address was not set.
+
+**/
+EFI_STATUS
+Ax88772RxControl (
+ IN NIC_DEVICE * pNicDevice,
+ IN UINT32 RxFilter
+ );
+
+EFI_STATUS
+Ax88772ReloadSrom (
+ IN NIC_DEVICE * pNicDevice
+ );
+
+/**
+ Read an SROM location
+
+ This routine calls ::Ax88772UsbCommand to read data from the
+ SROM.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+ @param [in] Address SROM address
+ @param [out] pData Buffer to receive the data
+
+ @retval EFI_SUCCESS The read was successful
+ @retval other The read failed
+
+**/
+EFI_STATUS
+Ax88772SromRead (
+ IN NIC_DEVICE * pNicDevice,
+ IN UINT32 Address,
+ OUT UINT16 * pData
+ );
+
+
+EFI_STATUS
+Ax88772EnableSromWrite (
+ IN NIC_DEVICE * pNicDevice
+ );
+
+
+EFI_STATUS
+Ax88772DisableSromWrite (
+ IN NIC_DEVICE * pNicDevice
+ );
+
+EFI_STATUS
+Ax88772SromWrite (
+ IN NIC_DEVICE * pNicDevice,
+ IN UINT32 Address,
+ OUT UINT16 * pData
+ );
+#if 0
+/**
+ This routine is called at a regular interval to poll for
+ receive packets.
+
+ This routine polls the link state and gets any receive packets
+ by calling ::Ax88772Rx.
+
+ @param [in] Event Timer event
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+
+**/
+VOID
+Ax88772Timer (
+ IN EFI_EVENT Event,
+ IN NIC_DEVICE * pNicDevice
+ );
+#endif
+/**
+ Send a command to the USB device.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+ @param [in] pRequest Pointer to the request structure
+ @param [in, out] pBuffer Data buffer address
+
+ @retval EFI_SUCCESS The USB transfer was successful
+ @retval other The USB transfer failed
+
+**/
+EFI_STATUS
+Ax88772UsbCommand (
+ IN NIC_DEVICE * pNicDevice,
+ IN USB_DEVICE_REQUEST * pRequest,
+ IN OUT VOID * pBuffer
+ );
+
+BOOLEAN
+Ax88772GetLinkStatus (
+ IN NIC_DEVICE * pNicDevice
+) ;
+
+//------------------------------------------------------------------------------
+// EFI Component Name Protocol Support
+//------------------------------------------------------------------------------
+
+extern EFI_COMPONENT_NAME_PROTOCOL gComponentName; ///< Component name protocol declaration
+extern EFI_COMPONENT_NAME2_PROTOCOL gComponentName2; ///< Component name 2 protocol declaration
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param [in] pThis A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param [in] pLanguage A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 3066 or ISO 639-2 language code format.
+ @param [out] ppDriverName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+GetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL * pThis,
+ IN CHAR8 * pLanguage,
+ OUT CHAR16 ** ppDriverName
+ );
+
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param [in] pThis A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param [in] ControllerHandle The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+ @param [in] ChildHandle The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+ @param [in] pLanguage A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 3066 or ISO 639-2 language code format.
+ @param [out] ppControllerName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+GetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL * pThis,
+ IN EFI_HANDLE ControllerHandle,
+ IN OPTIONAL EFI_HANDLE ChildHandle,
+ IN CHAR8 * pLanguage,
+ OUT CHAR16 ** ppControllerName
+ );
+
+
+EFI_STATUS
+Ax88772BulkIn(
+ IN NIC_DEVICE * pNicDevice
+);
+
+//------------------------------------------------------------------------------
+
+#endif // _AX88772_H_
diff --git a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.c b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.c
new file mode 100644
index 000000000000..a905dc548197
--- /dev/null
+++ b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.c
@@ -0,0 +1,1296 @@
+/** @file
+ Implement the interface to the AX88772 Ethernet controller.
+
+ This module implements the interface to the ASIX AX88772
+ USB to Ethernet MAC with integrated 10/100 PHY. Note that this implementation
+ only supports the integrated PHY since no other test cases were available.
+
+ Copyright (c) 2011, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Ax88772.h"
+
+
+/**
+ Compute the CRC
+
+ @param [in] pMacAddress Address of a six byte buffer to containing the MAC address.
+
+ @returns The CRC-32 value associated with this MAC address
+
+**/
+UINT32
+Ax88772Crc (
+ IN UINT8 * pMacAddress
+ )
+{
+ UINT32 BitNumber;
+ INT32 Carry;
+ INT32 Crc;
+ UINT32 Data;
+ UINT8 * pEnd;
+
+ //
+ // Walk the MAC address
+ //
+ Crc = -1;
+ pEnd = &pMacAddress[ PXE_HWADDR_LEN_ETHER ];
+ while ( pEnd > pMacAddress ) {
+ Data = *pMacAddress++;
+
+
+ //
+ // CRC32: x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1
+ //
+ // 1 0000 0100 1100 0001 0001 1101 1011 0111
+ //
+ for ( BitNumber = 0; 8 > BitNumber; BitNumber++ ) {
+ Carry = (( Crc >> 31 ) & 1 ) ^ ( Data & 1 );
+ Crc <<= 1;
+ if ( 0 != Carry ) {
+ Crc ^= 0x04c11db7;
+ }
+ Data >>= 1;
+ }
+ }
+
+ //
+ // Return the CRC value
+ //
+
+ return (UINT32) Crc;
+}
+
+
+/**
+ Get the MAC address
+
+ This routine calls ::Ax88772UsbCommand to request the MAC
+ address from the network adapter.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+ @param [out] pMacAddress Address of a six byte buffer to receive the MAC address.
+
+ @retval EFI_SUCCESS The MAC address is available.
+ @retval other The MAC address is not valid.
+
+**/
+EFI_STATUS
+Ax88772MacAddressGet (
+ IN NIC_DEVICE * pNicDevice,
+ OUT UINT8 * pMacAddress
+ )
+{
+ USB_DEVICE_REQUEST SetupMsg;
+ EFI_STATUS Status;
+
+ //
+ // Set the register address.
+ //
+ SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
+ | USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_MAC_ADDRESS_READ;
+ SetupMsg.Value = 0;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = PXE_HWADDR_LEN_ETHER;
+
+ //
+ // Read the PHY register
+ //
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ pMacAddress );
+
+ //
+ // Return the operation status
+ //
+ return Status;
+}
+
+
+/**
+ Set the MAC address
+
+ This routine calls ::Ax88772UsbCommand to set the MAC address
+ in the network adapter.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+ @param [in] pMacAddress Address of a six byte buffer to containing the new MAC address.
+
+ @retval EFI_SUCCESS The MAC address was set.
+ @retval other The MAC address was not set.
+
+**/
+EFI_STATUS
+Ax88772MacAddressSet (
+ IN NIC_DEVICE * pNicDevice,
+ IN UINT8 * pMacAddress
+ )
+{
+ USB_DEVICE_REQUEST SetupMsg;
+ EFI_STATUS Status;
+
+ //
+ // Set the register address.
+ //
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_MAC_ADDRESS_WRITE;
+ SetupMsg.Value = 0;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = PXE_HWADDR_LEN_ETHER;
+
+ //
+ // Read the PHY register
+ //
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ pMacAddress );
+
+ //
+ // Return the operation status
+ //
+ return Status;
+}
+
+/**
+ Clear the multicast hash table
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+
+**/
+VOID
+Ax88772MulticastClear (
+ IN NIC_DEVICE * pNicDevice
+ )
+{
+ int i = 0;
+ //
+ // Clear the multicast hash table
+ //
+ for ( i = 0 ; i < 8 ; i ++ )
+ pNicDevice->MulticastHash[i] = 0;
+}
+
+
+/**
+ Enable a multicast address in the multicast hash table
+
+ This routine calls ::Ax88772Crc to compute the hash bit for
+ this MAC address.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+ @param [in] pMacAddress Address of a six byte buffer to containing the MAC address.
+
+**/
+VOID
+Ax88772MulticastSet (
+ IN NIC_DEVICE * pNicDevice,
+ IN UINT8 * pMacAddress
+ )
+{
+ UINT32 Crc;
+
+ //
+ // Compute the CRC on the destination address
+ //
+ Crc = Ax88772Crc ( pMacAddress ) >> 26;
+
+ //
+ // Set the bit corresponding to the destination address
+ //
+ pNicDevice->MulticastHash [ Crc >> 3 ] |= ( 1<< (Crc& 7));
+
+}
+
+/**
+ Start the link negotiation
+
+ This routine calls ::Ax88772PhyWrite to start the PHY's link
+ negotiation.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+
+ @retval EFI_SUCCESS The link negotiation was started.
+ @retval other Failed to start the link negotiation.
+
+**/
+EFI_STATUS
+Ax88772NegotiateLinkStart (
+ IN NIC_DEVICE * pNicDevice
+ )
+{
+ UINT16 Control;
+ EFI_STATUS Status;
+
+ //
+ // Set the supported capabilities.
+ //
+ Status = Ax88772PhyWrite ( pNicDevice,
+ PHY_ANAR,
+ AN_CSMA_CD
+ | AN_TX_FDX | AN_TX_HDX
+ | AN_10_FDX | AN_10_HDX | AN_FCS );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Set the link speed and duplex
+ //
+ Control = BMCR_AUTONEGOTIATION_ENABLE
+ | BMCR_RESTART_AUTONEGOTIATION;
+ if ( pNicDevice->b100Mbps ) {
+ Control |= BMCR_100MBPS;
+ }
+ if ( pNicDevice->bFullDuplex ) {
+ Control |= BMCR_FULL_DUPLEX;
+ }
+ Status = Ax88772PhyWrite ( pNicDevice, PHY_BMCR, Control );
+
+ if (!EFI_ERROR(Status))
+ gBS->Stall(3000000);
+ }
+ return Status;
+}
+
+
+
+/**
+ Complete the negotiation of the PHY link
+
+ This routine calls ::Ax88772PhyRead to determine if the
+ link negotiation is complete.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+ @param [in, out] pPollCount Address of number of times this routine was polled
+ @param [out] pbComplete Address of boolean to receive complate status.
+ @param [out] pbLinkUp Address of boolean to receive link status, TRUE=up.
+ @param [out] pbHiSpeed Address of boolean to receive link speed, TRUE=100Mbps.
+ @param [out] pbFullDuplex Address of boolean to receive link duplex, TRUE=full.
+
+ @retval EFI_SUCCESS The MAC address is available.
+ @retval other The MAC address is not valid.
+
+**/
+EFI_STATUS
+Ax88772NegotiateLinkComplete (
+ IN NIC_DEVICE * pNicDevice,
+ IN OUT UINTN * pPollCount,
+ OUT BOOLEAN * pbComplete,
+ OUT BOOLEAN * pbLinkUp,
+ OUT BOOLEAN * pbHiSpeed,
+ OUT BOOLEAN * pbFullDuplex
+ )
+{
+ UINT16 Mask;
+ UINT16 PhyData;
+ EFI_STATUS Status;
+
+ //
+ // Determine if the link is up.
+ //
+ *pbComplete = FALSE;
+
+ //
+ // Get the link status
+ //
+ Status = Ax88772PhyRead ( pNicDevice,
+ PHY_BMSR,
+ &PhyData );
+
+ if ( !EFI_ERROR ( Status )) {
+ *pbLinkUp = (BOOLEAN)( 0 != ( PhyData & BMSR_LINKST ));
+ if ( 0 == *pbLinkUp ) {
+ } else {
+ *pbComplete = (BOOLEAN)( 0 != ( PhyData & 0x20 ));
+ if ( 0 == *pbComplete ) {
+ } else {
+ Status = Ax88772PhyRead ( pNicDevice,
+ PHY_ANLPAR,
+ &PhyData );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Autonegotiation is complete
+ // Determine the link speed.
+ //
+ *pbHiSpeed = (BOOLEAN)( 0 != ( PhyData & ( AN_TX_FDX | AN_TX_HDX )));
+
+ //
+ // Determine the link duplex.
+ //
+ Mask = ( *pbHiSpeed ) ? AN_TX_FDX : AN_10_FDX;
+ *pbFullDuplex = (BOOLEAN)( 0 != ( PhyData & Mask ));
+ }
+ }
+ }
+ } else {
+ }
+ return Status;
+}
+
+
+/**
+ Read a register from the PHY
+
+ This routine calls ::Ax88772UsbCommand to read a PHY register.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+ @param [in] RegisterAddress Number of the register to read.
+ @param [in, out] pPhyData Address of a buffer to receive the PHY register value
+
+ @retval EFI_SUCCESS The PHY data is available.
+ @retval other The PHY data is not valid.
+
+**/
+EFI_STATUS
+Ax88772PhyRead (
+ IN NIC_DEVICE * pNicDevice,
+ IN UINT8 RegisterAddress,
+ IN OUT UINT16 * pPhyData
+ )
+{
+ USB_DEVICE_REQUEST SetupMsg;
+ EFI_STATUS Status;
+
+ //
+ // Request access to the PHY
+ //
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_PHY_ACCESS_SOFTWARE;
+ SetupMsg.Value = 0;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = 0;
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ NULL );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Read the PHY register address.
+ //
+ SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
+ | USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_PHY_REG_READ;
+ SetupMsg.Value = pNicDevice->PhyId;
+ SetupMsg.Index = RegisterAddress;
+ SetupMsg.Length = sizeof ( *pPhyData );
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ pPhyData );
+ if ( !EFI_ERROR ( Status )) {
+
+ //
+ // Release the PHY to the hardware
+ //
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE;
+ SetupMsg.Value = 0;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = 0;
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ NULL );
+ }
+ }
+
+ //
+ // Return the operation status.
+ //
+ return Status;
+}
+
+
+/**
+ Write to a PHY register
+
+ This routine calls ::Ax88772UsbCommand to write a PHY register.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+ @param [in] RegisterAddress Number of the register to read.
+ @param [in] PhyData Address of a buffer to receive the PHY register value
+
+ @retval EFI_SUCCESS The PHY data was written.
+ @retval other Failed to wwrite the PHY register.
+
+**/
+EFI_STATUS
+Ax88772PhyWrite (
+ IN NIC_DEVICE * pNicDevice,
+ IN UINT8 RegisterAddress,
+ IN UINT16 PhyData
+ )
+{
+ USB_DEVICE_REQUEST SetupMsg;
+ EFI_STATUS Status;
+
+ //
+ // Request access to the PHY
+ //
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_PHY_ACCESS_SOFTWARE;
+ SetupMsg.Value = 0;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = 0;
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ NULL );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Write the PHY register
+ //
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_PHY_REG_WRITE;
+ SetupMsg.Value = pNicDevice->PhyId;
+ SetupMsg.Index = RegisterAddress;
+ SetupMsg.Length = sizeof ( PhyData );
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ &PhyData );
+ if ( !EFI_ERROR ( Status )) {
+
+ //
+ // Release the PHY to the hardware
+ //
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE;
+ SetupMsg.Value = 0;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = 0;
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ NULL );
+ }
+ }
+
+ //
+ // Return the operation status.
+ //
+ return Status;
+}
+
+
+/**
+ Reset the AX88772
+
+ This routine uses ::Ax88772UsbCommand to reset the network
+ adapter. This routine also uses ::Ax88772PhyWrite to reset
+ the PHY.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+
+ @retval EFI_SUCCESS The MAC address is available.
+ @retval other The MAC address is not valid.
+
+**/
+EFI_STATUS
+Ax88772Reset (
+ IN NIC_DEVICE * pNicDevice
+ )
+{
+ USB_DEVICE_REQUEST SetupMsg;
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *pUsbIo;
+
+ pUsbIo = pNicDevice->pUsbIo;
+
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE;
+ SetupMsg.Value = 0;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = 0;
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ NULL );
+
+ if (EFI_ERROR(Status)) goto err;
+
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_PHY_SELECT;
+ SetupMsg.Value = SPHY_PSEL;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = 0;
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ NULL );
+
+ if (EFI_ERROR(Status)) goto err;
+
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_RESET;
+ SetupMsg.Value = SRR_IPRL ;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = 0;
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ NULL );
+
+ if (EFI_ERROR(Status)) goto err;
+
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_RESET;
+ SetupMsg.Value = SRR_IPPD | SRR_IPRL ;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = 0;
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ NULL );
+
+ gBS->Stall ( 200000 );
+
+ if (EFI_ERROR(Status)) goto err;
+
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_RESET;
+ SetupMsg.Value = SRR_IPRL ;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = 0;
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ NULL );
+
+ gBS->Stall ( 200000 );
+
+ if (EFI_ERROR(Status)) goto err;
+
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_RESET;
+ SetupMsg.Value = 0;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = 0;
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ NULL );
+
+ if (EFI_ERROR(Status)) goto err;
+
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_PHY_SELECT;
+ SetupMsg.Value = SPHY_PSEL;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = 0;
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ NULL );
+
+ if (EFI_ERROR(Status)) goto err;
+
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_RESET;
+ SetupMsg.Value = SRR_IPRL | SRR_BZ | SRR_BZTYPE;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = 0;
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ NULL );
+
+ if (EFI_ERROR(Status)) goto err;
+
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_RX_CONTROL_WRITE;
+ SetupMsg.Value = 0;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = 0;
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ NULL );
+
+ if (EFI_ERROR(Status)) goto err;
+
+ if (!pNicDevice->Flag772A) {
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_RXQTC;
+#if RXTHOU
+ /*size cannot exceed 3K*/
+ //SetupMsg.Value = 0x0;
+ //SetupMsg.Index = 0x8001;
+ /*size cannot exceed 16K*/
+ SetupMsg.Value = 0x8300;
+ SetupMsg.Index = 0x8500;
+ /*size cannot exceed 32K*/
+ //SetupMsg.Value = 0x8784;
+ //SetupMsg.Index = 0x8A00;
+ SetupMsg.Length = 0;
+#else
+ SetupMsg.Value = 0x8000;
+ SetupMsg.Index = 0x8001;
+#endif
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ NULL );
+ }
+err:
+ return Status;
+}
+
+/**
+ Enable or disable the receiver
+
+ This routine calls ::Ax88772UsbCommand to update the
+ receiver state. This routine also calls ::Ax88772MacAddressSet
+ to establish the MAC address for the network adapter.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+ @param [in] RxFilter Simple network RX filter mask value
+
+ @retval EFI_SUCCESS The MAC address was set.
+ @retval other The MAC address was not set.
+
+**/
+EFI_STATUS
+Ax88772RxControl (
+ IN NIC_DEVICE * pNicDevice,
+ IN UINT32 RxFilter
+ )
+{
+ UINT16 MediumStatus;
+ UINT16 RxControl;
+ USB_DEVICE_REQUEST SetupMsg;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ //
+ // Enable the receiver if something is to be received
+ //
+ if ( 0 != RxFilter ) {
+ //
+ // Enable the receiver
+ //
+ SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
+ | USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_MEDIUM_STATUS_READ;
+ SetupMsg.Value = 0;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = sizeof ( MediumStatus );
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ &MediumStatus );
+ if ( !EFI_ERROR ( Status )) {
+ if ( 0 == ( MediumStatus & MS_RE )) {
+ MediumStatus |= MS_RE | MS_ONE;
+
+ if ( pNicDevice->bFullDuplex )
+ MediumStatus |= MS_TFC | MS_RFC | MS_FD;
+ else
+ MediumStatus &= ~(MS_TFC | MS_RFC | MS_FD);
+
+ if ( pNicDevice->b100Mbps )
+ MediumStatus |= MS_PS;
+ else
+ MediumStatus &= ~MS_PS;
+
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_MEDIUM_STATUS_WRITE;
+ SetupMsg.Value = MediumStatus;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = 0;
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ NULL );
+
+ if (EFI_ERROR(Status))
+ goto EXIT;
+ }
+ } else {
+ goto EXIT;
+ }
+ }
+ RxControl = RXC_SO;
+ if (!pNicDevice->Flag772A)
+ RxControl |= RXC_RH1M;
+
+ //
+ // Enable multicast if requested
+ //
+ if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST )) {
+ RxControl |= RXC_AM;
+ //
+ // Update the multicast hash table
+ //
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_MULTICAST_HASH_WRITE;
+ SetupMsg.Value = 0;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = sizeof ( pNicDevice ->MulticastHash );
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ &pNicDevice->MulticastHash );
+
+ if (EFI_ERROR(Status))
+ goto EXIT;
+ }
+
+ //
+ // Enable all multicast if requested
+ //
+ if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST )) {
+ RxControl |= RXC_AMALL;
+ }
+
+ //
+ // Enable broadcast if requested
+ //
+ if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST )) {
+ RxControl |= RXC_AB;
+ }
+
+ //
+ // Enable promiscuous mode if requested
+ //
+ if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS )) {
+ RxControl |= RXC_PRO;
+ }
+
+ //
+ // Update the receiver control
+ //
+ if (pNicDevice->CurRxControl != RxControl) {
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_RX_CONTROL_WRITE;
+#if RXTHOU
+ if (pNicDevice->Flag772A)
+ RxControl |= 0x0300;
+#endif
+ if (pNicDevice->Flag772A)
+ RxControl &= ~(RXC_MFB);
+ SetupMsg.Value = RxControl;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = 0;
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ NULL );
+ if ( !EFI_ERROR ( Status ))
+ pNicDevice->CurRxControl = RxControl;
+ }
+
+ //
+ // Return the operation status
+ //
+EXIT:
+ return Status;
+}
+
+
+
+EFI_STATUS
+Ax88772ReloadSrom (
+ IN NIC_DEVICE * pNicDevice
+ )
+{
+ USB_DEVICE_REQUEST SetupMsg;
+ EFI_STATUS Status;
+
+ //
+ // Read a value from the SROM
+ //
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+
+ SetupMsg.Request = CMD_WRITE_GPIOS;
+ SetupMsg.Value = 0x80;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = 0 ;
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ NULL );
+
+ if (EFI_SUCCESS == Status)
+ gBS->Stall(500000);
+
+ return Status;
+
+}
+
+
+/**
+ Read an SROM location
+
+ This routine calls ::Ax88772UsbCommand to read data from the
+ SROM.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+ @param [in] Address SROM address
+ @param [out] pData Buffer to receive the data
+
+ @retval EFI_SUCCESS The read was successful
+ @retval other The read failed
+
+**/
+EFI_STATUS
+Ax88772SromRead (
+ IN NIC_DEVICE * pNicDevice,
+ IN UINT32 Address,
+ OUT UINT16 * pData
+ )
+{
+
+ USB_DEVICE_REQUEST SetupMsg;
+ EFI_STATUS Status;
+
+ //
+ // Read a value from the SROM
+ //
+ SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
+ | USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_SROM_READ;
+ SetupMsg.Value = (UINT16) Address;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = sizeof ( *pData );
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ pData );
+
+ //
+ // Return the operation status
+ //
+ return Status;
+}
+
+EFI_STATUS
+Ax88772EnableSromWrite (
+ IN NIC_DEVICE * pNicDevice
+ )
+{
+ USB_DEVICE_REQUEST SetupMsg;
+ EFI_STATUS Status;
+
+ //
+ // Read a value from the SROM
+ //
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+
+ SetupMsg.Request = CMD_SROM_WRITE_EN;
+ SetupMsg.Value = 0;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = 0 ;
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ NULL );
+
+ if (EFI_SUCCESS == Status)
+ gBS->Stall(500000);
+
+ return Status;
+
+}
+
+
+EFI_STATUS
+Ax88772DisableSromWrite (
+ IN NIC_DEVICE * pNicDevice
+ )
+{
+ USB_DEVICE_REQUEST SetupMsg;
+ EFI_STATUS Status;
+
+ //
+ // Read a value from the SROM
+ //
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+
+ SetupMsg.Request = CMD_SROM_WRITE_DIS;
+ SetupMsg.Value = 0;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = 0;
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ NULL );
+
+ if (EFI_SUCCESS == Status)
+ gBS->Stall(500000);
+
+ return Status;
+
+}
+
+/**
+ Write an SROM location
+
+ This routine calls ::Ax88772UsbCommand to write data from the
+ SROM.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+ @param [in] Address SROM address
+ @param [out] pData Buffer of data to write
+
+ @retval EFI_SUCCESS The write was successful
+ @retval other The write failed
+
+**/
+EFI_STATUS
+Ax88772SromWrite (
+ IN NIC_DEVICE * pNicDevice,
+ IN UINT32 Address,
+ IN UINT16 * pData
+ )
+{
+
+ USB_DEVICE_REQUEST SetupMsg;
+ EFI_STATUS Status;
+
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+
+ SetupMsg.Request = CMD_SROM_WRITE;
+ SetupMsg.Value = (UINT16) Address;
+ SetupMsg.Index = (UINT16) (*pData);
+ SetupMsg.Length = 0;
+
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ NULL );
+
+ //
+ // Return the operation status
+ //
+ return Status;
+}
+
+/**
+ Send a command to the USB device.
+
+ @param [in] pNicDevice Pointer to the NIC_DEVICE structure
+ @param [in] pRequest Pointer to the request structure
+ @param [in, out] pBuffer Data buffer address
+
+ @retval EFI_SUCCESS The USB transfer was successful
+ @retval other The USB transfer failed
+
+**/
+EFI_STATUS
+Ax88772UsbCommand (
+ IN NIC_DEVICE * pNicDevice,
+ IN USB_DEVICE_REQUEST * pRequest,
+ IN OUT VOID * pBuffer
+ )
+{
+ UINT32 CmdStatus;
+ EFI_USB_DATA_DIRECTION Direction;
+ EFI_USB_IO_PROTOCOL * pUsbIo;
+ EFI_STATUS Status;
+
+ //
+ // Determine the transfer direction
+ //
+ Direction = EfiUsbNoData;
+ if ( 0 != pRequest->Length ) {
+ Direction = ( 0 != ( pRequest->RequestType & USB_ENDPOINT_DIR_IN ))
+ ? EfiUsbDataIn : EfiUsbDataOut;
+ }
+
+ //
+ // Issue the command
+ //
+ pUsbIo = pNicDevice->pUsbIo;
+ Status = pUsbIo->UsbControlTransfer ( pUsbIo,
+ pRequest,
+ Direction,
+ USB_BUS_TIMEOUT,
+ pBuffer,
+ pRequest->Length,
+ &CmdStatus );
+
+ //
+ // Determine the operation status
+ //
+ if ( !EFI_ERROR ( Status )) {
+ Status = CmdStatus;
+ } else {
+ //
+ // Only use status values associated with the Simple Network protocol
+ //
+ if ( EFI_TIMEOUT == Status ) {
+ Status = EFI_DEVICE_ERROR;
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ return Status;
+}
+
+BOOLEAN
+Ax88772GetLinkStatus (
+ IN NIC_DEVICE * pNicDevice
+)
+{
+ UINT32 CmdStatus;
+ EFI_USB_IO_PROTOCOL * pUsbIo;
+ UINT64 IntData = 0;
+ UINTN IntDataLeng = 8;
+ EFI_STATUS Status;
+
+ //
+ // Issue the command
+ //
+ pUsbIo = pNicDevice->pUsbIo;
+ Status = pUsbIo->UsbSyncInterruptTransfer( pUsbIo,
+ USB_ENDPOINT_DIR_IN | INTERRUPT_ENDPOINT,
+ &IntData,
+ &IntDataLeng,
+ USB_BUS_TIMEOUT,
+ &CmdStatus );
+
+ if ( EFI_ERROR(Status) || EFI_ERROR(CmdStatus) || 0 == IntDataLeng) {
+ return FALSE;
+ }
+ return (IntData & 0x800000)? FALSE : TRUE;
+
+}
+
+#if RXTHOU
+EFI_STATUS
+Ax88772BulkIn(
+ IN NIC_DEVICE * pNicDevice
+)
+{
+ int i;
+ UINTN LengthInBytes = 0;
+ UINTN TMP_LENG = AX88772_MAX_BULKIN_SIZE;
+ UINTN ORI_TMP_LENG = 0;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ EFI_USB_IO_PROTOCOL *pUsbIo;
+ UINT32 TransferStatus = 0;
+ UINT16 tmpPktCnt = 0;
+ UINT16 * tmpHdr = (UINT16 *)pNicDevice->pBulkInbuf;
+ USB_DEVICE_REQUEST SetupMsg;
+
+ pUsbIo = pNicDevice->pUsbIo;
+ for ( i = 0 ; i < (AX88772_MAX_BULKIN_SIZE / 512) && pUsbIo != NULL; i++) {
+ VOID* tmpAddr = 0;
+
+ tmpPktCnt = 0;
+ tmpAddr = (VOID*) &pNicDevice->pBulkInbuf[LengthInBytes];
+ ORI_TMP_LENG = TMP_LENG;
+ Status = pUsbIo->UsbBulkTransfer ( pUsbIo,
+ USB_ENDPOINT_DIR_IN | BULK_IN_ENDPOINT,
+ tmpAddr,
+ &TMP_LENG,
+ BULKIN_TIMEOUT,
+ &TransferStatus );
+
+ if (ORI_TMP_LENG == TMP_LENG) {
+ Status = EFI_NOT_READY;
+ goto no_pkt;
+ }
+
+ if (( !EFI_ERROR ( Status )) &&
+ ( !EFI_ERROR ( TransferStatus )) &&
+ TMP_LENG != 0) {
+ LengthInBytes += TMP_LENG;
+ if ((TMP_LENG % 512) != 0) {
+ goto done;
+ }
+ } else if (( !EFI_ERROR ( Status )) &&
+ ( !EFI_ERROR ( TransferStatus )) &&
+ (TMP_LENG == 0)) {
+ Status = EFI_NOT_READY;
+ goto done;
+ } else if (EFI_TIMEOUT == Status && EFI_USB_ERR_TIMEOUT == TransferStatus) {
+ SetupMsg.RequestType = USB_REQ_TYPE_STANDARD | 0x02;
+ SetupMsg.Request = 0x01;
+ SetupMsg.Value = 0;
+ SetupMsg.Index = 0x82;
+ SetupMsg.Length = 0;
+ Status = Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ NULL );
+ Status = EFI_NOT_READY;
+ goto done;
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ goto done;
+ }
+ }
+done:
+ if (LengthInBytes != 0) {
+ UINT16 tmpLen;
+ UINT16 tmpLenBar;
+ UINT16 tmpTotalLen = 0;
+ UINTN TotalLen = LengthInBytes;
+
+ do {
+ tmpLen = (*tmpHdr) & 0x7FF;
+ tmpLenBar = *(tmpHdr + 1);
+ tmpTotalLen = ((tmpLen + 4 + 1) & 0xfffe);
+
+ if ((tmpLen & 0x7FF) + (tmpLenBar & 0x7FF) == 0x7FF) {
+ tmpPktCnt++;
+ } else {
+ if ( tmpPktCnt != 0) {
+ break;
+ }
+ Status = EFI_NOT_READY;
+ goto no_pkt;
+ }
+ tmpHdr += (tmpTotalLen / 2);
+ TotalLen -= tmpTotalLen;
+ } while (TotalLen > 0);
+
+ if (LengthInBytes >= 1000 && tmpPktCnt != 0) {
+ if ((pNicDevice->rxburst) == 1) {
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_RESET;
+ SetupMsg.Value = SRR_IPRL;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = 0;
+ Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ NULL );
+ }
+
+ if (pNicDevice->rxburst < 2)
+ pNicDevice->rxburst++;
+
+ } else {
+ if (pNicDevice->rxburst >= 2) {
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = CMD_RESET;
+ SetupMsg.Value = SRR_IPRL| SRR_BZ | SRR_BZTYPE;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = 0;
+ Ax88772UsbCommand ( pNicDevice,
+ &SetupMsg,
+ NULL );
+ }
+ pNicDevice->rxburst = 0;
+ }
+ }
+
+ if (tmpPktCnt != 0) {
+ pNicDevice->PktCnt = tmpPktCnt;
+ pNicDevice->pCurPktHdrOff = pNicDevice->pBulkInbuf;
+ pNicDevice->pCurPktOff = pNicDevice->pBulkInbuf + 4;
+ Status = EFI_SUCCESS;
+ }
+
+no_pkt:
+ return Status;
+}
+#else
+EFI_STATUS
+Ax88772BulkIn(
+ IN NIC_DEVICE * pNicDevice
+)
+{
+ int i;
+ UINTN LengthInBytes = 0;
+ UINTN TMP_LENG = AX88772_MAX_BULKIN_SIZE;
+ UINTN ORI_TMP_LENG = 0;
+ UINTN CURBufSize = AX88772_MAX_BULKIN_SIZE;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ EFI_USB_IO_PROTOCOL *pUsbIo;
+ UINT32 TransferStatus = 0;
+ UINT16 tmpPktCnt = 0;
+ UINT16 * tmpHdr = (UINT16 *)pNicDevice->pBulkInbuf;
+
+ pUsbIo = pNicDevice->pUsbIo;
+ for ( i = 0 ; i < (AX88772_MAX_BULKIN_SIZE / 512) && pUsbIo != NULL; i++) {
+ VOID* tmpAddr = 0;
+
+ tmpPktCnt = 0;
+ tmpAddr = (VOID*) &pNicDevice->pBulkInbuf[LengthInBytes];
+ ORI_TMP_LENG = TMP_LENG;
+ Status = pUsbIo->UsbBulkTransfer ( pUsbIo,
+ USB_ENDPOINT_DIR_IN | BULK_IN_ENDPOINT,
+ tmpAddr,
+ &TMP_LENG,
+ BULKIN_TIMEOUT,
+ &TransferStatus );
+
+ if (ORI_TMP_LENG == TMP_LENG) {
+ Status = EFI_NOT_READY;
+ goto no_pkt;
+ }
+
+ if (( !EFI_ERROR ( Status )) &&
+ ( !EFI_ERROR ( TransferStatus )) &&
+ TMP_LENG != 0) {
+ UINT16 tmpLen;
+ UINT16 tmpLenBar;
+ UINT16 tmpTotalLen = 0;
+
+ LengthInBytes += TMP_LENG;
+ CURBufSize = CURBufSize - TMP_LENG;
+ TMP_LENG = CURBufSize;
+ do {
+ tmpLen = *tmpHdr;
+ tmpLenBar = *(tmpHdr + 1);
+ tmpTotalLen += ((tmpLen + 4 + 1) & 0xfffe);
+
+ if (((tmpLen ^ tmpLenBar) == 0xffff)) {
+ if (tmpTotalLen == LengthInBytes) {
+ tmpPktCnt++;
+ Status = EFI_SUCCESS;
+ goto done;
+ } else if (tmpTotalLen > LengthInBytes) {
+ break;
+ }
+ } else if (((tmpLen ^ tmpLenBar) != 0xffff)) {
+ if ( tmpPktCnt != 0) {
+ Status = EFI_SUCCESS;
+ goto done;
+ }
+ Status = EFI_NOT_READY;
+ goto no_pkt;
+ }
+ tmpHdr += (tmpTotalLen / 2);
+ tmpPktCnt++;
+ }while (tmpTotalLen < LengthInBytes);
+ } else if (( !EFI_ERROR ( Status )) &&
+ ( !EFI_ERROR ( TransferStatus )) &&
+ (TMP_LENG == 0)) {
+ if ( tmpPktCnt != 0) {
+ Status = EFI_SUCCESS;
+ goto done;
+ }
+ Status = EFI_NOT_READY;
+ goto no_pkt;
+ } else if (EFI_TIMEOUT == Status && EFI_USB_ERR_TIMEOUT == TransferStatus) {
+ if ( tmpPktCnt != 0) {
+ Status = EFI_SUCCESS;
+ goto done;
+ }
+ Status = EFI_NOT_READY;
+ goto no_pkt;
+ } else {
+ if ( tmpPktCnt != 0) {
+ Status = EFI_SUCCESS;
+ goto done;
+ }
+ Status = EFI_DEVICE_ERROR;
+ goto no_pkt;
+ }
+ }
+done:
+ pNicDevice->PktCnt = tmpPktCnt;
+ pNicDevice->pCurPktHdrOff = pNicDevice->pBulkInbuf;
+ pNicDevice->pCurPktOff = pNicDevice->pBulkInbuf + 4;
+no_pkt:
+ return Status;
+}
+#endif
diff --git a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/ComponentName.c b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/ComponentName.c
new file mode 100644
index 000000000000..8e2ba86f945e
--- /dev/null
+++ b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/ComponentName.c
@@ -0,0 +1,246 @@
+/** @file
+ UEFI Component Name(2) protocol implementation.
+
+ Copyright (c) 2011, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Ax88772.h"
+
+/**
+ EFI Component Name Protocol declaration
+**/
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gComponentName = {
+ GetDriverName,
+ GetControllerName,
+ "eng"
+};
+
+/**
+ EFI Component Name 2 Protocol declaration
+**/
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) GetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) GetControllerName,
+ "en"
+};
+
+
+/**
+ Driver name table declaration
+**/
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
+mDriverNameTable[] = {
+ {"eng;en", L"ASIX AX88772B Ethernet Driver 2.8.0"},
+ {NULL, NULL}
+};
+
+
+/**
+ Controller name table declaration
+**/
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
+mControllerNameTable[] = {
+ {"eng;en", L"ASIX AX88772B USB Fast Ethernet Controller"},
+ {NULL, NULL}
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param [in] pThis A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param [in] pLanguage A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 3066 or ISO 639-2 language code format.
+ @param [out] ppDriverName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+GetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL * pThis,
+ IN CHAR8 * pLanguage,
+ OUT CHAR16 ** ppDriverName
+ )
+{
+ EFI_STATUS Status;
+
+ Status = LookupUnicodeString2 (
+ pLanguage,
+ pThis->SupportedLanguages,
+ mDriverNameTable,
+ ppDriverName,
+ (BOOLEAN)(pThis == &gComponentName)
+ );
+
+ return Status;
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param [in] pThis A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param [in] ControllerHandle The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+ @param [in] ChildHandle The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+ @param [in] pLanguage A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 3066 or ISO 639-2 language code format.
+ @param [out] ppControllerName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+
+
+#if PASS_SCT
+EFI_STATUS
+EFIAPI
+GetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL * pThis,
+ IN EFI_HANDLE ControllerHandle,
+ IN OPTIONAL EFI_HANDLE ChildHandle,
+ IN CHAR8 * pLanguage,
+ OUT CHAR16 ** ppControllerName
+ )
+{
+
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIoProtocol;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Check Controller's handle
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &UsbIoProtocol,
+ gDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (!EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ gDriverBinding.DriverBindingHandle,
+ ControllerHandle
+ );
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Status != EFI_ALREADY_STARTED) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = LookupUnicodeString2 (
+ pLanguage,
+ pThis->SupportedLanguages,
+ mControllerNameTable,
+ ppControllerName,
+ (BOOLEAN)(pThis == &gComponentName)
+ );
+
+ return Status;
+}
+#else
+EFI_STATUS
+EFIAPI
+GetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL * pThis,
+ IN EFI_HANDLE ControllerHandle,
+ IN OPTIONAL EFI_HANDLE ChildHandle,
+ IN CHAR8 * pLanguage,
+ OUT CHAR16 ** ppControllerName
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Set the controller name
+ //
+ *ppControllerName = L"ASIX AX88772B USB Fast Ethernet Controller";
+ Status = EFI_SUCCESS;
+
+ //
+ // Return the operation status
+ //
+
+ return Status;
+}
+
+#endif
diff --git a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/DriverBinding.c b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/DriverBinding.c
new file mode 100644
index 000000000000..5edb7cbb2630
--- /dev/null
+++ b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/DriverBinding.c
@@ -0,0 +1,637 @@
+/** @file
+ Implement the driver binding protocol for Asix AX88772 Ethernet driver.
+
+ Copyright (c) 2011-2013, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Ax88772.h"
+#include <Library/MemoryAllocationLib.h>
+/**
+ Verify the controller type
+
+ @param [in] pThis Protocol instance pointer.
+ @param [in] Controller Handle of device to test.
+ @param [in] pRemainingDevicePath Not used.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval other This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+DriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL * pThis,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL * pRemainingDevicePath
+ )
+{
+ EFI_USB_DEVICE_DESCRIPTOR Device;
+ EFI_USB_IO_PROTOCOL * pUsbIo;
+ EFI_STATUS Status;
+
+ //
+ // Connect to the USB stack
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &pUsbIo,
+ pThis->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (!EFI_ERROR ( Status )) {
+ //
+ // Get the interface descriptor to check the USB class and find a transport
+ // protocol handler.
+ //
+ Status = pUsbIo->UsbGetDeviceDescriptor ( pUsbIo, &Device );
+ if (EFI_ERROR ( Status )) {
+ Status = EFI_UNSUPPORTED;
+ } else {
+ //
+ // Validate the adapter
+ //
+ if ( VENDOR_ID == Device.IdVendor ) {
+ if (PRODUCT_AX88772B_ID != Device.IdProduct) {
+ } else if (PRODUCT_AX88772B_ASUS_ID == Device.IdProduct) {
+ } else if (PRODUCT_AX88772A_ID == Device.IdProduct) {
+ } else if (PRODUCT_ID == Device.IdProduct) {
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+ } else if ( VENDOR_AX88772B_LENOVO_ID == Device.IdVendor ) {
+ if (PRODUCT_AX88772B_LENOVO_ID != Device.IdProduct) {
+ Status = EFI_UNSUPPORTED;
+ }
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Done with the USB stack
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ pThis->DriverBindingHandle,
+ Controller
+ );
+ }
+
+ //
+ // Return the device supported status
+ //
+ return Status;
+}
+
+
+/**
+ Start this driver on Controller by opening UsbIo and DevicePath protocols.
+ Initialize PXE structures, create a copy of the Controller Device Path with the
+ NIC's MAC address appended to it, install the NetworkInterfaceIdentifier protocol
+ on the newly created Device Path.
+
+ @param [in] pThis Protocol instance pointer.
+ @param [in] Controller Handle of device to work with.
+ @param [in] pRemainingDevicePath Not used, always produce all possible children.
+
+ @retval EFI_SUCCESS This driver is added to Controller.
+ @retval other This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+DriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL * pThis,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL * pRemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ NIC_DEVICE *pNicDevice;
+ UINTN LengthInBytes;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath = NULL;
+ MAC_ADDR_DEVICE_PATH MacDeviceNode;
+ EFI_USB_DEVICE_DESCRIPTOR Device;
+
+ //
+ // Allocate the device structure
+ //
+ LengthInBytes = sizeof ( *pNicDevice );
+ Status = gBS->AllocatePool (
+ EfiRuntimeServicesData,
+ LengthInBytes,
+ (VOID **) &pNicDevice
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ERR;
+ }
+
+ //
+ // Set the structure signature
+ //
+ ZeroMem ( pNicDevice, LengthInBytes );
+ pNicDevice->Signature = DEV_SIGNATURE;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &pNicDevice->pUsbIo,
+ pThis->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ERR;
+ }
+
+ pNicDevice->Flag772A = FALSE;
+ pNicDevice->pUsbIo->UsbGetDeviceDescriptor ( pNicDevice->pUsbIo, &Device );
+ if ((PRODUCT_AX88772A_ID == Device.IdProduct) ||
+ (PRODUCT_ID == Device.IdProduct))
+ pNicDevice->Flag772A = TRUE;
+ //
+ // Initialize the simple network protocol
+ //
+ Status = SN_Setup ( pNicDevice );
+
+ if (EFI_ERROR(Status)){
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ pThis->DriverBindingHandle,
+ Controller
+ );
+ goto ERR;
+ }
+
+ //
+ // Set Device Path
+ //
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ pThis->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR(Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ pThis->DriverBindingHandle,
+ Controller
+ );
+ goto ERR;
+ }
+
+ ZeroMem (&MacDeviceNode, sizeof (MAC_ADDR_DEVICE_PATH));
+ MacDeviceNode.Header.Type = MESSAGING_DEVICE_PATH;
+ MacDeviceNode.Header.SubType = MSG_MAC_ADDR_DP;
+
+ SetDevicePathNodeLength (&MacDeviceNode.Header, sizeof (MAC_ADDR_DEVICE_PATH));
+
+ CopyMem (&MacDeviceNode.MacAddress,
+ &pNicDevice->SimpleNetworkData.CurrentAddress,
+ PXE_HWADDR_LEN_ETHER);
+
+ MacDeviceNode.IfType = pNicDevice->SimpleNetworkData.IfType;
+
+ pNicDevice->MyDevPath = AppendDevicePathNode (
+ ParentDevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &MacDeviceNode
+ );
+
+ pNicDevice->Controller = NULL;
+
+ //
+ // Install both the simple network and device path protocols.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &pNicDevice->Controller,
+ &gEfiCallerIdGuid,
+ pNicDevice,
+ &gEfiSimpleNetworkProtocolGuid,
+ &pNicDevice->SimpleNetwork,
+ &gEfiDevicePathProtocolGuid,
+ pNicDevice->MyDevPath,
+ NULL
+ );
+
+ if (EFI_ERROR(Status)){
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ pThis->DriverBindingHandle,
+ Controller);
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ pThis->DriverBindingHandle,
+ Controller
+ );
+ goto ERR;
+ }
+
+ //
+ // Open For Child Device
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &pNicDevice->pUsbIo,
+ pThis->DriverBindingHandle,
+ pNicDevice->Controller,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+
+ if (EFI_ERROR(Status)){
+ gBS->UninstallMultipleProtocolInterfaces (
+ &pNicDevice->Controller,
+ &gEfiCallerIdGuid,
+ pNicDevice,
+ &gEfiSimpleNetworkProtocolGuid,
+ &pNicDevice->SimpleNetwork,
+ &gEfiDevicePathProtocolGuid,
+ pNicDevice->MyDevPath,
+ NULL
+ );
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ pThis->DriverBindingHandle,
+ Controller);
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ pThis->DriverBindingHandle,
+ Controller
+ );
+ goto ERR;
+ }
+
+ return Status;
+ERR:
+ if ( NULL != pNicDevice->pBulkInbuf)
+ gBS->FreePool (pNicDevice->pBulkInbuf);
+ if ( NULL != pNicDevice->pTxTest)
+ gBS->FreePool (pNicDevice->pTxTest);
+ if ( NULL != pNicDevice->MyDevPath)
+ gBS->FreePool (pNicDevice->MyDevPath);
+ if (NULL != pNicDevice)
+ gBS->FreePool ( pNicDevice );
+ return Status;
+}
+
+/**
+ Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and
+ closing the DevicePath and PciIo protocols on Controller.
+
+ @param [in] pThis Protocol instance pointer.
+ @param [in] Controller Handle of device to stop driver on.
+ @param [in] NumberOfChildren How many children need to be stopped.
+ @param [in] pChildHandleBuffer Not used.
+
+ @retval EFI_SUCCESS This driver is removed Controller.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+ @retval other This driver was not removed from this device.
+
+**/
+EFI_STATUS
+EFIAPI
+DriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL * pThis,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE * ChildHandleBuffer
+ )
+{
+ BOOLEAN AllChildrenStopped;
+ UINTN Index;
+ EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork;
+ EFI_STATUS Status = EFI_SUCCESS;
+ NIC_DEVICE *pNicDevice;
+
+ //
+ // Complete all outstanding transactions to Controller.
+ // Don't allow any new transaction to Controller to be started.
+ //
+ if (NumberOfChildren == 0) {
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiSimpleNetworkProtocolGuid,
+ (VOID **) &SimpleNetwork,
+ pThis->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR(Status)) {
+ //
+ // This is a 2nd type handle(multi-lun root), it needs to close devicepath
+ // and usbio protocol.
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ pThis->DriverBindingHandle,
+ Controller
+ );
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ pThis->DriverBindingHandle,
+ Controller
+ );
+ return EFI_SUCCESS;
+ }
+
+ pNicDevice = DEV_FROM_SIMPLE_NETWORK ( SimpleNetwork );
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiCallerIdGuid,
+ pNicDevice,
+ &gEfiSimpleNetworkProtocolGuid,
+ &pNicDevice->SimpleNetwork,
+ &gEfiDevicePathProtocolGuid,
+ pNicDevice->MyDevPath,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Close the bus driver
+ //
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ pThis->DriverBindingHandle,
+ Controller
+ );
+
+ if (EFI_ERROR(Status)){ }
+
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ pThis->DriverBindingHandle,
+ Controller
+ );
+
+ if (EFI_ERROR(Status)){ }
+
+ return EFI_SUCCESS;
+ }
+
+ AllChildrenStopped = TRUE;
+
+ for (Index = 0; Index < NumberOfChildren; Index++) {
+ Status = gBS->OpenProtocol (
+ ChildHandleBuffer[Index],
+ &gEfiSimpleNetworkProtocolGuid,
+ (VOID **) &SimpleNetwork,
+ pThis->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ AllChildrenStopped = FALSE;
+ continue;
+ }
+
+ pNicDevice = DEV_FROM_SIMPLE_NETWORK ( SimpleNetwork );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ pThis->DriverBindingHandle,
+ ChildHandleBuffer[Index]
+ );
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ChildHandleBuffer[Index],
+ &gEfiCallerIdGuid,
+ pNicDevice,
+ &gEfiSimpleNetworkProtocolGuid,
+ &pNicDevice->SimpleNetwork,
+ &gEfiDevicePathProtocolGuid,
+ pNicDevice->MyDevPath,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &pNicDevice->pUsbIo,
+ pThis->DriverBindingHandle,
+ ChildHandleBuffer[Index],
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ } else {
+ if ( NULL != pNicDevice->pBulkInbuf)
+ gBS->FreePool (pNicDevice->pBulkInbuf);
+ if ( NULL != pNicDevice->pTxTest)
+ gBS->FreePool (pNicDevice->pTxTest);
+ if ( NULL != pNicDevice->MyDevPath)
+ gBS->FreePool (pNicDevice->MyDevPath);
+ if ( NULL != pNicDevice)
+ gBS->FreePool (pNicDevice);
+ }
+ }
+
+ if (!AllChildrenStopped) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Driver binding protocol declaration
+**/
+EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
+ DriverSupported,
+ DriverStart,
+ DriverStop,
+ 0xa,
+ NULL,
+ NULL
+};
+
+
+/**
+ Ax88772 driver unload routine.
+
+ @param [in] ImageHandle Handle for the image.
+
+ @retval EFI_SUCCESS Image may be unloaded
+
+**/
+EFI_STATUS
+EFIAPI
+DriverUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ UINTN BufferSize;
+ UINTN Index;
+ UINTN Max;
+ EFI_HANDLE * pHandle;
+ EFI_STATUS Status;
+
+
+ //
+ // Determine which devices are using this driver
+ //
+ BufferSize = 0;
+ pHandle = NULL;
+ Status = gBS->LocateHandle (
+ ByProtocol,
+ &gEfiCallerIdGuid,
+ NULL,
+ &BufferSize,
+ NULL );
+ if ( EFI_BUFFER_TOO_SMALL == Status ) {
+ for ( ; ; ) {
+ //
+ // One or more block IO devices are present
+ //
+ Status = gBS->AllocatePool (
+ EfiRuntimeServicesData,
+ BufferSize,
+ (VOID **) &pHandle
+ );
+ if ( EFI_ERROR ( Status )) {
+
+ break;
+ }
+
+ //
+ // Locate the block IO devices
+ //
+ Status = gBS->LocateHandle (
+ ByProtocol,
+ &gEfiCallerIdGuid,
+ NULL,
+ &BufferSize,
+ pHandle );
+ if ( EFI_ERROR ( Status )) {
+ //
+ // Error getting handles
+ //
+ break;
+ }
+
+ //
+ // Remove any use of the driver
+ //
+ Max = BufferSize / sizeof ( pHandle[ 0 ]);
+ for ( Index = 0; Max > Index; Index++ ) {
+ Status = DriverStop ( &gDriverBinding,
+ pHandle[ Index ],
+ 0,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ }
+ break;
+ }
+ } else {
+ if ( EFI_NOT_FOUND == Status ) {
+ //
+ // No devices were found
+ //
+ Status = EFI_SUCCESS;
+ }
+ }
+
+ //
+ // Free the handle array
+ //
+ if ( NULL != pHandle ) {
+ gBS->FreePool ( pHandle );
+ }
+
+ //
+ // Remove the protocols installed by the EntryPoint routine.
+ //
+ if ( !EFI_ERROR ( Status )) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ ImageHandle,
+ &gEfiDriverBindingProtocolGuid,
+ &gDriverBinding,
+ &gEfiComponentNameProtocolGuid,
+ &gComponentName,
+ &gEfiComponentName2ProtocolGuid,
+ &gComponentName2,
+ NULL
+ );
+ }
+
+ //
+ // Return the unload status
+ //
+ return Status;
+}
+
+
+/**
+Ax88772 driver entry point.
+
+@param [in] ImageHandle Handle for the image.
+@param [in] pSystemTable Address of the system table.
+
+@retval EFI_SUCCESS Image successfully loaded.
+
+**/
+EFI_STATUS
+EFIAPI
+EntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE * pSystemTable
+ )
+{
+ EFI_LOADED_IMAGE_PROTOCOL * pLoadedImage;
+ EFI_STATUS Status;
+
+ //
+ // Enable unload support
+ //
+ Status = gBS->HandleProtocol (
+ gImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **)&pLoadedImage
+ );
+ if (!EFI_ERROR (Status)) {
+ pLoadedImage->Unload = DriverUnload;
+ }
+
+ //
+ // Add the driver to the list of drivers
+ //
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ pSystemTable,
+ &gDriverBinding,
+ ImageHandle,
+ &gComponentName,
+ &gComponentName2
+ );
+ if ( !EFI_ERROR ( Status )) { }
+ return Status;
+}
diff --git a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/SimpleNetwork.c b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/SimpleNetwork.c
new file mode 100644
index 000000000000..b4627092a676
--- /dev/null
+++ b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/SimpleNetwork.c
@@ -0,0 +1,1612 @@
+/** @file
+ Provides the Simple Network functions.
+
+ Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Ax88772.h"
+#include <Library/MemoryAllocationLib.h>
+/**
+ This function updates the filtering on the receiver.
+
+ This support routine calls ::Ax88772MacAddressSet to update
+ the MAC address. This routine then rebuilds the multicast
+ hash by calling ::Ax88772MulticastClear and ::Ax88772MulticastSet.
+ Finally this routine enables the receiver by calling
+ ::Ax88772RxControl.
+
+ @param [in] pSimpleNetwork Simple network mode pointer
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+ReceiveFilterUpdate (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork
+ )
+{
+ EFI_SIMPLE_NETWORK_MODE * pMode;
+ NIC_DEVICE * pNicDevice;
+ EFI_STATUS Status;
+ UINT32 Index;
+
+ //
+ // Set the MAC address
+ //
+ pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
+ pMode = pSimpleNetwork->Mode;
+
+ //
+ // Clear the multicast hash table
+ //
+ Ax88772MulticastClear ( pNicDevice );
+
+ //
+ // Load the multicast hash table
+ //
+ if ( 0 != ( pMode->ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST )) {
+ for ( Index = 0; Index < pMode->MCastFilterCount; Index++ ) {
+ //
+ // Enable the next multicast address
+ //
+ Ax88772MulticastSet ( pNicDevice,
+ &pMode->MCastFilter[ Index ].Addr[0]);
+ }
+ }
+
+ Status = Ax88772RxControl ( pNicDevice, pMode->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] pSimpleNetwork Protocol instance pointer
+ @param [in] pInterruptStatus A pointer to the bit mask of the current active interrupts.
+ If this is NULL, the interrupt status will not be read from
+ the device. If this is not NULL, the interrupt status will
+ be read from teh device. When the interrupt status is read,
+ it will also be cleared. Clearing the transmit interrupt
+ does not empty the recycled transmit buffer array.
+ @param [out] ppTxBuf Recycled transmit buffer address. The network interface will
+ not transmit if its internal recycled transmit buffer array is
+ full. Reading the transmit buffer does not clear the transmit
+ interrupt. If this is NULL, then the transmit buffer status
+ will not be read. If there are not transmit buffers to recycle
+ and TxBuf is not NULL, *TxBuf will be set to NULL.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+
+**/
+
+EFI_STATUS
+EFIAPI
+SN_GetStatus (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
+ OUT UINT32 * pInterruptStatus,
+ OUT VOID ** ppTxBuf
+ )
+{
+ EFI_SIMPLE_NETWORK_MODE * pMode;
+ NIC_DEVICE * pNicDevice = NULL;
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_TPL TplPrevious;
+
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
+
+ //
+ // Verify the parameters
+ //
+ if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
+ //
+ // Return the transmit buffer
+ //
+ pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
+
+ if (( NULL != ppTxBuf ) &&
+ ( NULL != pNicDevice->pTxBuffer )) {
+ *ppTxBuf = pNicDevice->pTxBuffer;
+ pNicDevice->pTxBuffer = NULL;
+ }
+
+ pMode = pSimpleNetwork->Mode;
+ if (EfiSimpleNetworkInitialized == pMode->State) {
+ if (NULL == ppTxBuf && NULL == pInterruptStatus) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+
+#if REPORTLINK
+#else
+ if (!pNicDevice->bLinkUp || !pNicDevice->bComplete) {
+#endif
+ Status = Ax88772NegotiateLinkComplete ( pNicDevice,
+ &pNicDevice->PollCount,
+ &pNicDevice->bComplete,
+ &pNicDevice->bLinkUp,
+ &pNicDevice->b100Mbps,
+ &pNicDevice->bFullDuplex );
+ if (EFI_ERROR(Status))
+ goto EXIT;
+#if REPORTLINK
+ if (pNicDevice->bLinkUp && pNicDevice->bComplete) {
+ pMode->MediaPresent = TRUE;
+ Status = ReceiveFilterUpdate ( pSimpleNetwork );
+ } else {
+ pMode->MediaPresent = FALSE;
+ }
+#else
+ if (pNicDevice->bLinkUp && pNicDevice->bComplete) {
+ pMode->MediaPresent = TRUE;
+ pMode->MediaPresentSupported = FALSE;
+ Status = ReceiveFilterUpdate ( pSimpleNetwork );
+ }
+ }
+#endif
+ } else {
+ if (EfiSimpleNetworkStarted == pMode->State) {
+ Status = EFI_DEVICE_ERROR;
+ } else {
+ Status = EFI_NOT_STARTED ;
+ }
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ if ( NULL != pInterruptStatus ) {
+ *pInterruptStatus = 0;
+ }
+EXIT:
+ gBS->RestoreTPL(TplPrevious) ;
+
+ return Status;
+}
+
+/**
+ This function performs read and write operations on the NVRAM device
+ attached to a network interface.
+
+ @param [in] pSimpleNetwork Protocol instance pointer
+ @param [in] ReadWrite TRUE for read operations, FALSE for write operations.
+ @param [in] Offset Byte offset in the NVRAM device at which to start the
+ read or write operation. This must be a multiple of
+ NvRamAccessSize and less than NvRamSize.
+ @param [in] BufferSize The number of bytes to read or write from the NVRAM device.
+ This must also be a multiple of NvramAccessSize.
+ @param [in, out] pBuffer A pointer to the data buffer.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_NvData (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
+ IN BOOLEAN ReadWrite,
+ IN UINTN Offset,
+ IN UINTN BufferSize,
+ IN OUT VOID * pBuffer
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ EFI_TPL TplPrevious;
+ EFI_SIMPLE_NETWORK_MODE * pMode;
+ NIC_DEVICE * pNicDevice;
+
+
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
+
+ if (( NULL == pSimpleNetwork ) || ( NULL == pSimpleNetwork->Mode )) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+
+ pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
+ pMode = pSimpleNetwork->Mode;
+
+#if PASS_SCT
+ if (EfiSimpleNetworkInitialized != pMode->State) {
+ Status = EFI_NOT_STARTED;
+ goto EXIT;
+ }
+#endif
+
+ if ( 0 != Offset ) {
+ if ((0 != (Offset % pMode->NvRamAccessSize) ) ||
+ (Offset >= pMode->NvRamSize)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+ }
+ //
+ // Offset must be a multiple of NvRamAccessSize and less than NvRamSize.
+ //
+ if (0 != (BufferSize % pMode->NvRamAccessSize)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+
+ if (BufferSize + Offset > pMode->NvRamSize) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+
+ if (NULL == pBuffer) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+
+ //
+ // ReadWrite: TRUE FOR READ FALSE FOR WRITE
+ //
+ if (ReadWrite){
+ UINTN i;
+
+ for (i = 0; i < BufferSize / 2; i++) {
+ Status = Ax88772SromRead ( pNicDevice,
+ (UINT32)(Offset/2 + i),
+ (((UINT16*)pBuffer) + i));
+ }
+ } else {
+ UINTN i;
+
+ Status = Ax88772EnableSromWrite(pNicDevice);
+ if (EFI_ERROR(Status))
+ goto EXIT;
+
+ for (i = 0; i < BufferSize / 2; i++){
+ Status = Ax88772SromWrite ( pNicDevice,
+ (UINT32)(Offset/2 + i),
+ (((UINT16*)pBuffer) + i));
+ }
+
+ Status = Ax88772DisableSromWrite(pNicDevice);
+
+ if (BufferSize == 272)
+ Status = Ax88772ReloadSrom(pNicDevice);
+ }
+
+ //
+ // Return the operation status
+ //
+EXIT:
+ gBS->RestoreTPL (TplPrevious);
+ return Status;
+}
+
+
+
+/**
+ Resets the network adapter and allocates the transmit and receive buffers
+ required by the network interface; optionally, also requests allocation of
+ additional transmit and receive buffers. This routine must be called before
+ any other routine in the Simple Network protocol is called.
+
+ @param [in] pSimpleNetwork Protocol instance pointer
+ @param [in] ExtraRxBufferSize Size in bytes to add to the receive buffer allocation
+ @param [in] ExtraTxBufferSize Size in bytes to add to the transmit buffer allocation
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_OUT_OF_RESOURCES There was not enough memory for the transmit and receive buffers
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Initialize (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
+ IN UINTN ExtraRxBufferSize,
+ IN UINTN ExtraTxBufferSize
+ )
+{
+ EFI_SIMPLE_NETWORK_MODE * pMode;
+ EFI_STATUS Status;
+ UINT32 TmpState;
+ EFI_TPL TplPrevious;
+ NIC_DEVICE * pNicDevice;
+
+ TplPrevious = gBS->RaiseTPL (TPL_CALLBACK);
+
+ //
+ // Verify the parameters
+ //
+ if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
+ //
+ // Determine if the interface is already started
+ //
+ pMode = pSimpleNetwork->Mode;
+ if ( EfiSimpleNetworkStarted == pMode->State ) {
+ if (( 0 == ExtraRxBufferSize ) && ( 0 == ExtraTxBufferSize )) {
+ //
+ // Start the adapter
+ //
+ TmpState = pMode->State;
+ pMode->State = EfiSimpleNetworkInitialized;
+ Status = SN_Reset ( pSimpleNetwork, FALSE );
+ if ( EFI_ERROR ( Status )) {
+ //
+ // Update the network state
+ //
+ pMode->State = TmpState ; // EfiSimpleNetworkInitialized;
+ } else {
+ pMode->MediaPresentSupported = TRUE;
+ pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
+ pMode->MediaPresent = Ax88772GetLinkStatus (pNicDevice);
+ }
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+ } else {
+ Status = EFI_NOT_STARTED;
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return the operation status
+ //
+ gBS->RestoreTPL (TplPrevious);
+ return Status;
+}
+
+
+/**
+ This function converts a multicast IP address to a multicast HW MAC address
+ for all packet transactions.
+
+ @param [in] pSimpleNetwork Protocol instance pointer
+ @param [in] bIPv6 Set to TRUE if the multicast IP address is IPv6 [RFC2460].
+ Set to FALSE if the multicast IP address is IPv4 [RFC 791].
+ @param [in] pIP The multicast IP address that is to be converted to a
+ multicast HW MAC address.
+ @param [in] pMAC The multicast HW MAC address that is to be generated from IP.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_MCastIPtoMAC (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
+ IN BOOLEAN bIPv6,
+ IN EFI_IP_ADDRESS * pIP,
+ IN EFI_MAC_ADDRESS * pMAC
+ )
+{
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+ EFI_SIMPLE_NETWORK_MODE * pMode;
+
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
+
+ if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
+ //
+ // The interface must be running
+ //
+ pMode = pSimpleNetwork->Mode;
+ if ( EfiSimpleNetworkInitialized == pMode->State ) {
+ if (pIP == NULL || pMAC == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+
+ if (bIPv6) {
+ Status = EFI_UNSUPPORTED;
+ goto EXIT;
+ } else {
+ //
+ // check if the ip given is a mcast IP
+ //
+ if ((pIP->v4.Addr[0] & 0xF0) != 0xE0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ } else {
+ pMAC->Addr[0] = 0x01;
+ pMAC->Addr[1] = 0x00;
+ pMAC->Addr[2] = 0x5e;
+ pMAC->Addr[3] = (UINT8) (pIP->v4.Addr[1] & 0x7f);
+ pMAC->Addr[4] = (UINT8) pIP->v4.Addr[2];
+ pMAC->Addr[5] = (UINT8) pIP->v4.Addr[3];
+ Status = EFI_SUCCESS;
+ }
+ }
+ } else {
+ if (EfiSimpleNetworkStarted == pMode->State) {
+ Status = EFI_DEVICE_ERROR;
+ } else {
+ Status = EFI_NOT_STARTED ;
+ }
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+EXIT:
+ gBS->RestoreTPL(TplPrevious);
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+SN_Receive (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
+ OUT UINTN * pHeaderSize,
+ OUT UINTN * pBufferSize,
+ OUT VOID * pBuffer,
+ OUT EFI_MAC_ADDRESS * pSrcAddr,
+ OUT EFI_MAC_ADDRESS * pDestAddr,
+ OUT UINT16 * pProtocol
+ )
+{
+ ETHERNET_HEADER * pHeader;
+ EFI_SIMPLE_NETWORK_MODE * pMode;
+ NIC_DEVICE * pNicDevice = NULL;
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+ UINT16 Type;
+ UINT16 CurrentPktLen;
+
+
+ TplPrevious = gBS->RaiseTPL (TPL_CALLBACK);
+
+ //
+ // Verify the parameters
+ //
+ if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
+ //
+ // The interface must be running
+ //
+ pMode = pSimpleNetwork->Mode;
+ if ( EfiSimpleNetworkInitialized == pMode->State ) {
+
+ if ((pBufferSize == NULL) || (pBuffer == NULL)) {
+ Status = EFI_INVALID_PARAMETER;
+ gBS->RestoreTPL (TplPrevious);
+ return Status;
+ }
+
+ //
+ // Update the link status
+ //
+ pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
+
+ if ( pNicDevice->bLinkUp && pNicDevice->bComplete) {
+ if ((NULL != pHeaderSize) && (7720 == *pHeaderSize)) {
+ pNicDevice->Grub_f = TRUE;
+ }
+
+ if ((pNicDevice->Grub_f) && (7720 != *pHeaderSize)) {
+ gBS->RestoreTPL (TplPrevious);
+ return EFI_NOT_READY;
+ }
+
+ //
+ // Attempt to receive a packet
+ //
+ if (0 == pNicDevice->PktCnt) {
+ Status = Ax88772BulkIn(pNicDevice);
+ if (EFI_ERROR(Status)) {
+ goto no_pkt;
+ }
+ }
+
+ CurrentPktLen = *((UINT16*) (pNicDevice->pCurPktHdrOff));
+ CurrentPktLen &= 0x7ff;
+
+ if (( 60 <= CurrentPktLen ) &&
+ ( CurrentPktLen - 14 <= MAX_ETHERNET_PKT_SIZE)) {
+ if (*pBufferSize < (UINTN)CurrentPktLen) {
+ gBS->RestoreTPL (TplPrevious);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *pBufferSize = CurrentPktLen;
+ CopyMem ( pBuffer, pNicDevice->pCurPktOff, CurrentPktLen );
+ pHeader = (ETHERNET_HEADER *) pNicDevice->pCurPktOff;
+
+ if ( NULL != pHeaderSize && (7720 != *pHeaderSize)) {
+ *pHeaderSize = sizeof ( *pHeader );
+ }
+ if ( NULL != pDestAddr ) {
+ CopyMem ( pDestAddr, &pHeader->dest_addr, PXE_HWADDR_LEN_ETHER );
+ }
+ if ( NULL != pSrcAddr ) {
+ CopyMem ( pSrcAddr, &pHeader->src_addr, PXE_HWADDR_LEN_ETHER );
+ }
+ if ( NULL != pProtocol ) {
+ Type = pHeader->type;
+ Type = (UINT16)(( Type >> 8 ) | ( Type << 8 ));
+ *pProtocol = Type;
+ }
+ pNicDevice->PktCnt--;
+ pNicDevice->pCurPktHdrOff += (CurrentPktLen + 4 + 1) & 0xfffe;
+ pNicDevice->pCurPktOff = pNicDevice->pCurPktHdrOff + 4;
+ Status = EFI_SUCCESS;
+ } else {
+ pNicDevice->PktCnt = 0;
+ Status = EFI_DEVICE_ERROR;
+ }
+ } else {
+ //
+ // Link no up
+ //
+ Status = EFI_NOT_READY;
+ }
+ } else {
+ if (EfiSimpleNetworkStarted == pMode->State) {
+ Status = EFI_DEVICE_ERROR;
+ } else {
+ Status = EFI_NOT_STARTED;
+ }
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return the operation status
+ //
+no_pkt:
+ gBS->RestoreTPL (TplPrevious);
+ return Status;
+}
+
+/**
+ This function is used to enable and disable the hardware and software receive
+ filters for the underlying network device.
+
+ The receive filter change is broken down into three steps:
+
+ 1. The filter mask bits that are set (ON) in the Enable parameter
+ are added to the current receive filter settings.
+
+ 2. The filter mask bits that are set (ON) in the Disable parameter
+ are subtracted from the updated receive filter settins.
+
+ 3. If the resulting filter settigns is not supported by the hardware
+ a more liberal setting is selected.
+
+ If the same bits are set in the Enable and Disable parameters, then the bits
+ in the Disable parameter takes precedence.
+
+ If the ResetMCastFilter parameter is TRUE, then the multicast address list
+ filter is disabled (irregardless of what other multicast bits are set in
+ the enable and Disable parameters). The SNP->Mode->MCastFilterCount field
+ is set to zero. The SNP->Mode->MCastFilter contents are undefined.
+
+ After enableing or disabling receive filter settings, software should
+ verify the new settings by checking the SNP->Mode->ReceeiveFilterSettings,
+ SNP->Mode->MCastFilterCount and SNP->Mode->MCastFilter fields.
+
+ Note: Some network drivers and/or devices will automatically promote
+ receive filter settings if the requested setting can not be honored.
+ For example, if a request for four multicast addresses is made and
+ the underlying hardware only supports two multicast addresses the
+ driver might set the promiscuous or promiscuous multicast receive filters
+ instead. The receiving software is responsible for discarding any extra
+ packets that get through the hardware receive filters.
+
+ If ResetMCastFilter is TRUE, then the multicast receive filter list
+ on the network interface will be reset to the default multicast receive
+ filter list. If ResetMCastFilter is FALSE, and this network interface
+ allows the multicast receive filter list to be modified, then the
+ MCastFilterCnt and MCastFilter are used to update the current multicast
+ receive filter list. The modified receive filter list settings can be
+ found in the MCastFilter field of EFI_SIMPLE_NETWORK_MODE.
+
+ This routine calls ::ReceiveFilterUpdate to update the receive
+ state in the network adapter.
+
+ @param [in] pSimpleNetwork Protocol instance pointer
+ @param [in] Enable A bit mask of receive filters to enable on the network interface.
+ @param [in] Disable A bit mask of receive filters to disable on the network interface.
+ For backward compatibility with EFI 1.1 platforms, the
+ EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit must be set
+ when the ResetMCastFilter parameter is TRUE.
+ @param [in] bResetMCastFilter Set to TRUE to reset the contents of the multicast receive
+ filters on the network interface to their default values.
+ @param [in] MCastFilterCnt Number of multicast HW MAC address in the new MCastFilter list.
+ This value must be less than or equal to the MaxMCastFilterCnt
+ field of EFI_SIMPLE_NETWORK_MODE. This field is optional if
+ ResetMCastFilter is TRUE.
+ @param [in] pMCastFilter A pointer to a list of new multicast receive filter HW MAC
+ addresses. This list will replace any existing multicast
+ HW MAC address list. This field is optional if ResetMCastFilter
+ is TRUE.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_ReceiveFilters (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
+ IN UINT32 Enable,
+ IN UINT32 Disable,
+/*
+#define EFI_SIMPLE_NETWORK_RECEIVE_UNICAST 0x01
+#define EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST 0x02
+#define EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST 0x04
+#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS 0x08
+#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST 0x10
+*/
+ IN BOOLEAN bResetMCastFilter,
+ IN UINTN MCastFilterCnt,
+ IN EFI_MAC_ADDRESS * pMCastFilter
+ )
+{
+ EFI_SIMPLE_NETWORK_MODE * pMode;
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_TPL TplPrevious;
+
+
+ NIC_DEVICE * pNicDevice;
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
+
+ pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
+ pMode = pSimpleNetwork->Mode;
+
+
+ if (pSimpleNetwork == NULL) {
+ gBS->RestoreTPL(TplPrevious);
+ return EFI_INVALID_PARAMETER;
+ }
+
+
+ switch (pMode->State) {
+ case EfiSimpleNetworkInitialized:
+ break;
+
+ case EfiSimpleNetworkStopped:
+ Status = EFI_NOT_STARTED;
+ gBS->RestoreTPL(TplPrevious);
+ return Status;
+
+ default:
+ Status = EFI_DEVICE_ERROR;
+ gBS->RestoreTPL(TplPrevious);
+ return Status;
+ }
+
+ //
+ // check if we are asked to enable or disable something that the UNDI
+ // does not even support!
+ //
+ if (((Enable &~pMode->ReceiveFilterMask) != 0) ||
+ ((Disable &~pMode->ReceiveFilterMask) != 0)) {
+ Status = EFI_INVALID_PARAMETER;
+ gBS->RestoreTPL(TplPrevious);
+ return Status;
+ }
+
+ if (bResetMCastFilter) {
+ if ( (0 == (pMode->ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST)) &&
+ Enable == 0 &&
+ Disable == 2) {
+ gBS->RestoreTPL(TplPrevious);
+ return EFI_SUCCESS;
+ }
+ pMode->MCastFilterCount = 0;
+ SetMem ( &pMode->MCastFilter[0],
+ sizeof(EFI_MAC_ADDRESS) * MAX_MCAST_FILTER_CNT,
+ 0);
+ } else {
+ if (MCastFilterCnt != 0) {
+ UINTN i;
+ EFI_MAC_ADDRESS * pMulticastAddress;
+ pMulticastAddress = pMCastFilter;
+
+ if ((MCastFilterCnt > pMode->MaxMCastFilterCount) ||
+ (pMCastFilter == NULL)) {
+ Status = EFI_INVALID_PARAMETER;
+ gBS->RestoreTPL(TplPrevious);
+ return Status;
+ }
+
+ for ( i = 0 ; i < MCastFilterCnt ; i++ ) {
+ UINT8 tmp;
+ tmp = pMulticastAddress->Addr[0];
+ if ( (tmp & 0x01) != 0x01 ) {
+ gBS->RestoreTPL(TplPrevious);
+ return EFI_INVALID_PARAMETER;
+ }
+ pMulticastAddress++;
+ }
+
+ pMode->MCastFilterCount = (UINT32)MCastFilterCnt;
+ CopyMem (&pMode->MCastFilter[0],
+ pMCastFilter,
+ MCastFilterCnt * sizeof ( EFI_MAC_ADDRESS ));
+ }
+ }
+
+ if (Enable == 0 && Disable == 0 && !bResetMCastFilter && MCastFilterCnt == 0) {
+ Status = EFI_SUCCESS;
+ gBS->RestoreTPL(TplPrevious);
+ return Status;
+ }
+
+ if ((Enable & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0 && MCastFilterCnt == 0) {
+ Status = EFI_INVALID_PARAMETER;
+ gBS->RestoreTPL(TplPrevious);
+ return Status;
+ }
+
+ pMode->ReceiveFilterSetting |= Enable;
+ pMode->ReceiveFilterSetting &= ~Disable;
+
+ Status = ReceiveFilterUpdate (pSimpleNetwork);
+
+ 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] pSimpleNetwork Protocol instance pointer
+ @param [in] bExtendedVerification Indicates that the driver may perform a more
+ exhaustive verification operation of the device
+ during reset.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Reset (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
+ IN BOOLEAN bExtendedVerification
+ )
+{
+ EFI_SIMPLE_NETWORK_MODE * pMode;
+ NIC_DEVICE * pNicDevice;
+ EFI_STATUS Status;
+
+ EFI_TPL TplPrevious;
+
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
+
+ //
+ // Verify the parameters
+ //
+ if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
+ pMode = pSimpleNetwork->Mode;
+ if ( EfiSimpleNetworkInitialized == pMode->State ) {
+ //
+ // Update the device state
+ //
+ pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
+
+ //
+ // Reset the device
+ //
+ if (!pNicDevice->bFirstRst) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = Ax88772Reset ( pNicDevice );
+ if ( !EFI_ERROR ( Status )) {
+ Status = ReceiveFilterUpdate ( pSimpleNetwork );
+ if ( !EFI_ERROR ( Status ) && !pNicDevice->bLinkUp && pNicDevice->bFirstRst) {
+ Status = Ax88772NegotiateLinkStart ( pNicDevice );
+ pNicDevice->bFirstRst = FALSE;
+ }
+ }
+ }
+ } else {
+ Status = EFI_NOT_STARTED;
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ //
+ // Return the operation status
+ //
+ gBS->RestoreTPL(TplPrevious);
+
+ return Status;
+}
+
+/**
+ Initialize the simple network protocol.
+
+ This routine calls ::Ax88772MacAddressGet to obtain the
+ MAC address.
+
+ @param [in] pNicDevice NIC_DEVICE_INSTANCE pointer
+
+ @retval EFI_SUCCESS Setup was successful
+
+**/
+EFI_STATUS
+SN_Setup (
+ IN NIC_DEVICE * pNicDevice
+ )
+{
+
+
+ EFI_SIMPLE_NETWORK_MODE * pMode;
+ EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork;
+ EFI_STATUS Status;
+
+ //
+ // Initialize the simple network protocol
+ //
+ pSimpleNetwork = &pNicDevice->SimpleNetwork;
+ pSimpleNetwork->Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
+ pSimpleNetwork->Start = (EFI_SIMPLE_NETWORK_START)SN_Start;
+ pSimpleNetwork->Stop = (EFI_SIMPLE_NETWORK_STOP)SN_Stop;
+ pSimpleNetwork->Initialize = (EFI_SIMPLE_NETWORK_INITIALIZE)SN_Initialize;
+ pSimpleNetwork->Reset = (EFI_SIMPLE_NETWORK_RESET)SN_Reset;
+ pSimpleNetwork->Shutdown = (EFI_SIMPLE_NETWORK_SHUTDOWN)SN_Shutdown;
+ pSimpleNetwork->ReceiveFilters = (EFI_SIMPLE_NETWORK_RECEIVE_FILTERS)SN_ReceiveFilters;
+ pSimpleNetwork->StationAddress = (EFI_SIMPLE_NETWORK_STATION_ADDRESS)SN_StationAddress;
+ pSimpleNetwork->Statistics = (EFI_SIMPLE_NETWORK_STATISTICS)SN_Statistics;
+ pSimpleNetwork->MCastIpToMac = (EFI_SIMPLE_NETWORK_MCAST_IP_TO_MAC)SN_MCastIPtoMAC;
+ pSimpleNetwork->NvData = (EFI_SIMPLE_NETWORK_NVDATA)SN_NvData;
+ pSimpleNetwork->GetStatus = (EFI_SIMPLE_NETWORK_GET_STATUS)SN_GetStatus;
+ pSimpleNetwork->Transmit = (EFI_SIMPLE_NETWORK_TRANSMIT)SN_Transmit;
+ pSimpleNetwork->Receive = (EFI_SIMPLE_NETWORK_RECEIVE)SN_Receive;
+ pSimpleNetwork->WaitForPacket = NULL;
+ pMode = &pNicDevice->SimpleNetworkData;
+ pSimpleNetwork->Mode = pMode;
+ pMode->State = EfiSimpleNetworkStopped;
+ pMode->HwAddressSize = PXE_HWADDR_LEN_ETHER;
+ pMode->MediaHeaderSize = sizeof ( ETHERNET_HEADER );
+ pMode->MaxPacketSize = MAX_ETHERNET_PKT_SIZE;
+ pMode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
+ | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
+ | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
+ | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
+ | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
+ pMode->ReceiveFilterSetting = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
+ | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
+ pMode->MaxMCastFilterCount = ASIX_MCAST_FILTER_CNT;
+ pMode->MCastFilterCount = 0;
+ pMode->NvRamSize = 512;
+ pMode->NvRamAccessSize = 2;
+ SetMem ( &pMode->BroadcastAddress,
+ PXE_HWADDR_LEN_ETHER,
+ 0xff );
+
+ SetMem ( &pMode->MCastFilter[0],
+ sizeof(EFI_MAC_ADDRESS) * MAX_MCAST_FILTER_CNT,
+ 0);
+
+ pMode->IfType = EfiNetworkInterfaceUndi;
+ pMode->MacAddressChangeable = TRUE;
+ pMode->MultipleTxSupported = FALSE;
+ pMode->MediaPresentSupported = TRUE;
+ pMode->MediaPresent = FALSE;
+
+ //
+ // Read the MAC address
+ //
+ pNicDevice->PhyId = PHY_ID_INTERNAL;
+ pNicDevice->b100Mbps = TRUE;
+ pNicDevice->bFullDuplex = TRUE;
+ pNicDevice->bComplete = FALSE;
+ pNicDevice->bLinkUp = FALSE;
+ pNicDevice->Grub_f = FALSE;
+ pNicDevice->bFirstRst = TRUE;
+ pNicDevice->PktCnt = 0;
+
+ Status = Ax88772MacAddressGet (
+ pNicDevice,
+ &pMode->PermanentAddress.Addr[0]);
+
+ if ( !EFI_ERROR ( Status )) {
+
+ //
+ // Use the hardware address as the current address
+ //
+
+ CopyMem ( &pMode->CurrentAddress,
+ &pMode->PermanentAddress,
+ PXE_HWADDR_LEN_ETHER );
+
+ CopyMem ( &pNicDevice->MAC,
+ &pMode->PermanentAddress,
+ PXE_HWADDR_LEN_ETHER );
+
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ } else {
+ return Status;
+ }
+
+ Status = gBS->AllocatePool ( EfiRuntimeServicesData,
+ AX88772_MAX_BULKIN_SIZE,
+ (VOID **) &pNicDevice->pBulkInbuf );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->AllocatePool ( EfiRuntimeServicesData,
+ sizeof ( RX_TX_PACKET ),
+ (VOID **) &pNicDevice->pTxTest );
+
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (pNicDevice->pBulkInbuf);
+ return Status;
+ }
+
+ //
+ // Return the setup status
+ //
+ return Status;
+}
+
+
+/**
+ This routine starts the network interface.
+
+ @param [in] pSimpleNetwork Protocol instance pointer
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_ALREADY_STARTED The network interface was already started.
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Start (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork
+ )
+{
+ NIC_DEVICE * pNicDevice;
+ EFI_SIMPLE_NETWORK_MODE * pMode;
+ EFI_STATUS Status;
+
+ EFI_TPL TplPrevious;
+
+
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
+
+ //
+ // Verify the parameters
+ //
+ Status = EFI_INVALID_PARAMETER;
+ if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
+ pMode = pSimpleNetwork->Mode;
+ if ( EfiSimpleNetworkStopped == pMode->State ) {
+ //
+ // Initialize the mode structure
+ // NVRAM access is not supported
+ //
+ ZeroMem ( pMode, sizeof ( *pMode ));
+
+ pMode->State = EfiSimpleNetworkStarted;
+ pMode->HwAddressSize = PXE_HWADDR_LEN_ETHER;
+ pMode->MediaHeaderSize = sizeof ( ETHERNET_HEADER );
+ pMode->MaxPacketSize = MAX_ETHERNET_PKT_SIZE;
+ pMode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
+ | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
+ | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
+ | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
+ | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
+ pMode->ReceiveFilterSetting = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
+ pMode->MaxMCastFilterCount = ASIX_MCAST_FILTER_CNT;
+ pMode->MCastFilterCount = 0;
+
+ SetMem ( &pMode->MCastFilter[0],
+ sizeof(EFI_MAC_ADDRESS) * MAX_MCAST_FILTER_CNT,
+ 0);
+
+ pMode->NvRamSize = 512;
+ pMode->NvRamAccessSize = 2;
+ pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
+ Status = Ax88772MacAddressGet ( pNicDevice, &pMode->PermanentAddress.Addr[0]);
+ CopyMem ( &pMode->CurrentAddress,
+ &pMode->PermanentAddress,
+ sizeof ( pMode->CurrentAddress ));
+ SetMem(&pMode->BroadcastAddress, PXE_HWADDR_LEN_ETHER, 0xff);
+ pMode->IfType = EfiNetworkInterfaceUndi;
+ pMode->MacAddressChangeable = TRUE;
+ pMode->MultipleTxSupported = FALSE;
+
+ pMode->MediaPresentSupported = TRUE;
+ pMode->MediaPresent = FALSE;
+
+ } else {
+ Status = EFI_ALREADY_STARTED;
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ gBS->RestoreTPL(TplPrevious);
+ return Status;
+}
+
+
+/**
+ Set the MAC address.
+
+ This function modifies or resets the current station address of a
+ network interface. If Reset is TRUE, then the current station address
+ is set ot the network interface's permanent address. If Reset if FALSE
+ then the current station address is changed to the address specified by
+ pNew.
+
+ This routine calls ::Ax88772MacAddressSet to update the MAC address
+ in the network adapter.
+
+ @param [in] pSimpleNetwork Protocol instance pointer
+ @param [in] bReset Flag used to reset the station address to the
+ network interface's permanent address.
+ @param [in] pNew New station address to be used for the network
+ interface.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_StationAddress (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
+ IN BOOLEAN bReset,
+ IN EFI_MAC_ADDRESS * pNew
+ )
+{
+ NIC_DEVICE * pNicDevice;
+ EFI_SIMPLE_NETWORK_MODE * pMode;
+ EFI_STATUS Status;
+
+ EFI_TPL TplPrevious;
+
+
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
+
+ //
+ // Verify the parameters
+ //
+ if (( NULL != pSimpleNetwork ) &&
+ ( NULL != pSimpleNetwork->Mode ) &&
+ (( !bReset ) || ( bReset && ( NULL != pNew )))) {
+ //
+ // Verify that the adapter is already started
+ //
+ pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
+ pMode = pSimpleNetwork->Mode;
+ if ( EfiSimpleNetworkInitialized == pMode->State ) {
+ //
+ // Determine the adapter MAC address
+ //
+ if ( bReset ) {
+ //
+ // Use the permanent address
+ //
+ CopyMem ( &pMode->CurrentAddress,
+ &pMode->PermanentAddress,
+ sizeof ( pMode->CurrentAddress ));
+ } else {
+ //
+ // Use the specified address
+ //
+ CopyMem ( &pMode->CurrentAddress,
+ pNew,
+ sizeof ( pMode->CurrentAddress ));
+ }
+
+ //
+ // Update the address on the adapter
+ //
+ Status = Ax88772MacAddressSet ( pNicDevice, &pMode->CurrentAddress.Addr[0]);
+ } else {
+ if (EfiSimpleNetworkStarted == pMode->State) {
+ Status = EFI_DEVICE_ERROR; ;
+ } else {
+ Status = EFI_NOT_STARTED ;
+ }
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return the operation status
+ //
+ gBS->RestoreTPL(TplPrevious);
+
+ return Status;
+}
+
+
+/**
+ This function resets or collects the statistics on a network interface.
+ If the size of the statistics table specified by StatisticsSize is not
+ big enough for all of the statistics that are collected by the network
+ interface, then a partial buffer of statistics is returned in
+ StatisticsTable.
+
+ @param [in] pSimpleNetwork Protocol instance pointer
+ @param [in] bReset Set to TRUE to reset the statistics for the network interface.
+ @param [in, out] pStatisticsSize On input the size, in bytes, of StatisticsTable. On output
+ the size, in bytes, of the resulting table of statistics.
+ @param [out] pStatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that
+ conains the statistics.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_BUFFER_TOO_SMALL The pStatisticsTable is NULL or the buffer is too small.
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+ typedef struct {
+ UINT64 RxTotalFrames;
+ UINT64 RxGoodFrames;
+ UINT64 RxUndersizeFrames;
+ UINT64 RxOversizeFrames;
+ UINT64 RxDroppedFrames;
+ UINT64 RxUnicastFrames;
+ UINT64 RxBroadcastFrames;
+ UINT64 RxMulticastFrames;
+ UINT64 RxCrcErrorFrames;
+ UINT64 RxTotalBytes;
+ UINT64 TxTotalFrames;
+ UINT64 TxGoodFrames;
+ UINT64 TxUndersizeFrames;
+ UINT64 TxOversizeFrames;
+ UINT64 TxDroppedFrames;
+ UINT64 TxUnicastFrames;
+ UINT64 TxBroadcastFrames;
+ UINT64 TxMulticastFrames;
+ UINT64 TxCrcErrorFrames;
+ UINT64 TxTotalBytes;
+ UINT64 Collisions;
+ UINT64 UnsupportedProtocol;
+ } EFI_NETWORK_STATISTICS;
+**/
+EFI_STATUS
+EFIAPI
+SN_Statistics (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
+ IN BOOLEAN bReset,
+ IN OUT UINTN * pStatisticsSize,
+ OUT EFI_NETWORK_STATISTICS * pStatisticsTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+ EFI_SIMPLE_NETWORK_MODE * pMode;
+
+
+
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
+
+ pMode = pSimpleNetwork->Mode;
+
+ if ( EfiSimpleNetworkInitialized == pMode->State ) {
+ if (NULL != pStatisticsSize && 0 == *pStatisticsSize) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto EXIT;
+ }
+ if(bReset) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_SUCCESS;
+ }
+ } else {
+ if (EfiSimpleNetworkStarted == pMode->State) {
+ Status = EFI_DEVICE_ERROR; ;
+ } else {
+ Status = EFI_NOT_STARTED ;
+ }
+ }
+ //
+ // 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] pSimpleNetwork Protocol instance pointer
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Stop (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork
+ )
+{
+ EFI_SIMPLE_NETWORK_MODE * pMode;
+ EFI_STATUS Status;
+
+ EFI_TPL TplPrevious;
+
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
+
+ //
+ // Verify the parameters
+ //
+ if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
+ //
+ // Determine if the interface is started
+ //
+ pMode = pSimpleNetwork->Mode;
+
+ if ( EfiSimpleNetworkStarted == pMode->State ) {
+ pMode->State = EfiSimpleNetworkStopped;
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_NOT_STARTED;
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return the operation status
+ //
+ gBS->RestoreTPL(TplPrevious);
+ return Status;
+}
+
+
+/**
+ This function releases the memory buffers assigned in the Initialize() call.
+ Pending transmits and receives are lost, and interrupts are cleared and disabled.
+ After this call, only Initialize() and Stop() calls may be used.
+
+ @param [in] pSimpleNetwork Protocol instance pointer
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Shutdown (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork
+ )
+{
+ EFI_SIMPLE_NETWORK_MODE * pMode;
+ UINT32 RxFilter;
+ EFI_STATUS Status;
+
+ EFI_TPL TplPrevious;
+
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
+
+ //
+ // Verify the parameters
+ //
+ if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
+ //
+ // Determine if the interface is already started
+ //
+ pMode = pSimpleNetwork->Mode;
+ if ( EfiSimpleNetworkInitialized == pMode->State ) {
+ //
+ // Stop the adapter
+ //
+ RxFilter = pMode->ReceiveFilterSetting;
+ pMode->ReceiveFilterSetting = 0;
+ Status = SN_Reset ( pSimpleNetwork, FALSE );
+ pMode->ReceiveFilterSetting = RxFilter;
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Update the network state
+ //
+ pMode->State = EfiSimpleNetworkStarted;
+ } else if ( EFI_DEVICE_ERROR == Status ) {
+ pMode->State = EfiSimpleNetworkStopped;
+ }
+
+ } else {
+ Status = EFI_NOT_STARTED;
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return the operation status
+ //
+ gBS->RestoreTPL(TplPrevious );
+ return Status;
+}
+
+
+/**
+ Send a packet over the network.
+
+ This function places the packet specified by Header and Buffer on
+ the transmit queue. This function performs a non-blocking transmit
+ operation. When the transmit is complete, the buffer is returned
+ via the GetStatus() call.
+
+ This routine calls ::Ax88772Rx to empty the network adapter of
+ receive packets. The routine then passes the transmit packet
+ to the network adapter.
+
+ @param [in] pSimpleNetwork Protocol instance pointer
+ @param [in] HeaderSize The size, in bytes, of the media header to be filled in by
+ the Transmit() function. If HeaderSize is non-zero, then
+ it must be equal to SimpleNetwork->Mode->MediaHeaderSize
+ and DestAddr and Protocol parameters must not be NULL.
+ @param [in] BufferSize The size, in bytes, of the entire packet (media header and
+ data) to be transmitted through the network interface.
+ @param [in] pBuffer A pointer to the packet (media header followed by data) to
+ to be transmitted. This parameter can not be NULL. If
+ HeaderSize is zero, then the media header is Buffer must
+ already be filled in by the caller. If HeaderSize is nonzero,
+ then the media header will be filled in by the Transmit()
+ function.
+ @param [in] pSrcAddr The source HW MAC address. If HeaderSize is zero, then
+ this parameter is ignored. If HeaderSize is nonzero and
+ SrcAddr is NULL, then SimpleNetwork->Mode->CurrentAddress
+ is used for the source HW MAC address.
+ @param [in] pDestAddr The destination HW MAC address. If HeaderSize is zero, then
+ this parameter is ignored.
+ @param [in] pProtocol The type of header to build. If HeaderSize is zero, then
+ this parameter is ignored.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_NOT_READY The network interface is too busy to accept this transmit request.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.
+ @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Transmit (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork,
+ IN UINTN HeaderSize,
+ IN UINTN BufferSize,
+ IN VOID * pBuffer,
+ IN EFI_MAC_ADDRESS * pSrcAddr,
+ IN EFI_MAC_ADDRESS * pDestAddr,
+ IN UINT16 * pProtocol
+ )
+{
+ ETHERNET_HEADER * pHeader;
+ EFI_SIMPLE_NETWORK_MODE * pMode;
+ NIC_DEVICE * pNicDevice;
+ EFI_USB_IO_PROTOCOL * pUsbIo;
+ EFI_STATUS Status;
+ UINTN TransferLength;
+ UINT32 TransferStatus;
+ UINT16 Type;
+ EFI_TPL TplPrevious;
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
+
+ // Verify the parameters
+ //
+ if (( NULL != pSimpleNetwork ) && ( NULL != pSimpleNetwork->Mode )) {
+ //
+ // The interface must be running
+ //
+ pMode = pSimpleNetwork->Mode;
+ if ( EfiSimpleNetworkInitialized == pMode->State ) {
+ //
+ // Update the link status
+ //
+ pNicDevice = DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork );
+
+ //
+ // Release the synchronization with Ax88772Timer
+ //
+ if ( pNicDevice->bLinkUp && pNicDevice->bComplete) {
+ //
+ // Copy the packet into the USB buffer
+ //
+
+ if (0 != HeaderSize && pMode->MediaHeaderSize != HeaderSize) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+ if (BufferSize < pMode->MediaHeaderSize) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+ if (NULL == pBuffer) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+ if (0 != HeaderSize && NULL == pDestAddr) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+ if (0 != HeaderSize && NULL == pProtocol) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+
+ CopyMem ( &pNicDevice->pTxTest->Data[0], pBuffer, BufferSize );
+ pNicDevice->pTxTest->Length = (UINT16) BufferSize;
+
+ //
+ // Transmit the packet
+ //
+ pHeader = (ETHERNET_HEADER *) &pNicDevice->pTxTest->Data[0];
+ if ( 0 != HeaderSize ) {
+ if ( NULL != pDestAddr ) {
+ CopyMem ( &pHeader->dest_addr, pDestAddr, PXE_HWADDR_LEN_ETHER );
+ }
+ if ( NULL != pSrcAddr ) {
+ CopyMem ( &pHeader->src_addr, pSrcAddr, PXE_HWADDR_LEN_ETHER );
+ }
+ else {
+ CopyMem ( &pHeader->src_addr, &pMode->CurrentAddress.Addr[0], PXE_HWADDR_LEN_ETHER );
+ }
+ if ( NULL != pProtocol ) {
+ Type = *pProtocol;
+ } else {
+ Type = pNicDevice->pTxTest->Length;
+ }
+ Type = (UINT16)(( Type >> 8 ) | ( Type << 8 ));
+ pHeader->type = Type;
+ }
+
+
+ if ( pNicDevice->pTxTest->Length < MIN_ETHERNET_PKT_SIZE ) {
+ pNicDevice->pTxTest->Length = MIN_ETHERNET_PKT_SIZE;
+ ZeroMem ( &pNicDevice->pTxTest->Data[ BufferSize],
+ pNicDevice->pTxTest->Length - BufferSize );
+ }
+
+ pNicDevice->pTxTest->LengthBar = ~(pNicDevice->pTxTest->Length);
+ TransferLength = sizeof ( pNicDevice->pTxTest->Length )
+ + sizeof ( pNicDevice->pTxTest->LengthBar )
+ + pNicDevice->pTxTest->Length;
+
+ if (TransferLength % 512 == 0 || TransferLength % 1024 == 0)
+ TransferLength +=4;
+#if RXTHOU
+ if (pNicDevice->rxburst == 1)
+ pNicDevice->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.
+ //
+ pUsbIo = pNicDevice->pUsbIo;
+ Status = pUsbIo->UsbBulkTransfer ( pUsbIo,
+ BULK_OUT_ENDPOINT,
+ &pNicDevice->pTxTest->Length,
+ &TransferLength,
+ 0xfffffffe,
+ &TransferStatus );
+ if ( EFI_SUCCESS == Status) {
+ Status = TransferStatus;
+ }
+ if ( EFI_SUCCESS == Status && EFI_SUCCESS == TransferStatus) {
+ pNicDevice->pTxBuffer = pBuffer;
+ } else {
+ if ( EFI_DEVICE_ERROR == Status ) {
+ SN_Reset ( pSimpleNetwork, FALSE );
+ }
+ Status = EFI_NOT_READY;
+ }
+ } else {
+ //
+ // No packets available.
+ //
+
+ Status = EFI_NOT_READY;
+ }
+ } else {
+ if (EfiSimpleNetworkStarted == pMode->State) {
+ Status = EFI_DEVICE_ERROR; ;
+ } else {
+ Status = EFI_NOT_STARTED ;
+ }
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+EXIT:
+ gBS->RestoreTPL (TplPrevious);
+
+ return Status;
+}
--
2.17.1
prev parent reply other threads:[~2020-05-07 3:37 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-07 3:37 [edk2-platform][PATCH v1 0/2] Update ASIX USB Networking drivers Samer El-Haj-Mahmoud
2020-05-07 3:37 ` [edk2-platform][PATCH v1 1/2] OptionRomPkg: UsbNetworking: ASIX Ax88179 driver Samer El-Haj-Mahmoud
2020-05-07 5:22 ` Ni, Ray
2020-05-07 16:20 ` Samer El-Haj-Mahmoud
2020-05-08 0:53 ` [edk2-devel] " Ni, Ray
2020-05-07 3:37 ` Samer El-Haj-Mahmoud [this message]
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=20200507033720.31152-3-Samer.El-Haj-Mahmoud@arm.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