[edk2-devel] [edk2-platform][PATCH v3 2/6] Drivers/ASIX: Add ASIX Ax88179 driver
Samer El-Haj-Mahmoud
samer.el-haj-mahmoud at arm.com
Mon Jun 8 13:38:28 UTC 2020
This is the initial revision of ASIX USB networking UEFI driver
version 2.9.0 for Ax88179 and Ax88178a
https://www.asix.com.tw/products.php?op=pItemdetail&PItemID=131;71;112
Original source code provided by ASIX is at:
https://github.com/samerhaj/uefi_drivers/blob/master/UsbNetworking/Asix/
zip/source/AX88179_178a_UEFI_v2.9.0_Source.zip
Cc: Ray Ni <ray.ni at intel.com>
Cc: Leif Lindholm <leif at nuviainc.com>
Cc: Ard Biesheuvel <ard.biesheuvel at arm.com>
Cc: Michael D Kinney <michael.d.kinney at intel.com>
Signed-off-by: Samer El-Haj-Mahmoud <samer.el-haj-mahmoud at arm.com>
---
Drivers/ASIX/Asix.dsc | 2 +-
Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf | 45 +
Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.h | 1053 +++++++++++++
Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.c | 1042 +++++++++++++
Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/ComponentName.c | 223 +++
Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/DriverBinding.c | 639 ++++++++
Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/SimpleNetwork.c | 1548 ++++++++++++++++++++
7 files changed, 4551 insertions(+), 1 deletion(-)
diff --git a/Drivers/ASIX/Asix.dsc b/Drivers/ASIX/Asix.dsc
index d65857bb1cd4..73b5cbd5a18f 100644
--- a/Drivers/ASIX/Asix.dsc
+++ b/Drivers/ASIX/Asix.dsc
@@ -64,4 +64,4 @@ [PcdsFixedAtBuild]
#
################################################################################
[Components]
-
+Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf
diff --git a/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf
new file mode 100644
index 000000000000..317ec538fa60
--- /dev/null
+++ b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf
@@ -0,0 +1,45 @@
+## @file
+# Component description file for ASIX AX88772 USB/Ethernet driver.
+#
+# This module provides support for the ASIX AX88772 USB/Ethernet adapter.
+# Copyright (c) 2011, Intel Corporation
+# Copyright (c) 2020, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010018
+ BASE_NAME = Ax88179
+ FILE_GUID = 27E5D3B6-7839-47C2-8618-5D2190729BC7
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = EntryPoint
+
+[Sources.common]
+ Ax88179.h
+ Ax88179.c
+ ComponentName.c
+ DriverBinding.c
+ SimpleNetwork.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ NetworkPkg/NetworkPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+
+[Protocols]
+ gEfiDevicePathProtocolGuid ## BY_START
+ gEfiSimpleNetworkProtocolGuid ## BY_START
+ gEfiUsbIoProtocolGuid ## TO_START
+
diff --git a/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.h b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.h
new file mode 100644
index 000000000000..498212ec149b
--- /dev/null
+++ b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.h
@@ -0,0 +1,1053 @@
+/** @file
+ Definitions for ASIX AX88179 Ethernet adapter.
+
+ Copyright (c) 2011, Intel Corporation
+ Copyright (c) 2020, ARM Limited. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef AX88179_H_
+#define AX88179_H_
+
+#include <Uefi.h>
+
+#include <Guid/EventGroup.h>
+
+#include <IndustryStandard/Pci.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/NetLib.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 FORCE_100Mbps 0
+#define REPORTLINK 1
+
+
+//------------------------------------------------------------------------------
+// Macros
+//------------------------------------------------------------------------------
+
+#define USB_IS_IN_ENDPOINT(EndPointAddr) (((EndPointAddr) & BIT7) != 0) ///< Return TRUE/FALSE for IN direction
+#define USB_IS_OUT_ENDPOINT(EndPointAddr) (((EndPointAddr) & BIT7) == 0) ///< Return TRUE/FALSE for OUT direction
+#define USB_IS_BULK_ENDPOINT(Attribute) (((Attribute) & (BIT0 | BIT1)) == USB_ENDPOINT_BULK) ///< Return TRUE/FALSE for BULK type
+#define USB_IS_INTERRUPT_ENDPOINT(Attribute) (((Attribute) & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT) ///< Return TRUE/FALSE for INTERRUPT type
+
+//------------------------------------------------------------------------------
+// Constants
+//------------------------------------------------------------------------------
+
+#define DEBUG_RX_BROADCAST 0x40000000 ///< Display RX broadcast messages
+#define DEBUG_RX_MULTICAST 0x20000000 ///< Display RX multicast messages
+#define DEBUG_RX_UNICAST 0x10000000 ///< Display RX unicast messages
+#define DEBUG_MAC_ADDRESS 0x08000000 ///< Display the MAC address
+#define DEBUG_LINK 0x04000000 ///< Display the link status
+#define DEBUG_TX 0x02000000 ///< Display the TX messages
+#define DEBUG_PHY 0x01000000 ///< Display the PHY register values
+#define DEBUG_SROM 0x00800000 ///< Display the SROM contents
+#define DEBUG_TIMER 0x00400000 ///< Display the timer routine entry/exit
+#define DEBUG_TPL 0x00200000 ///< Display the timer routine entry/exit
+
+
+#define ETHERNET_HEADER_SIZE sizeof (ETHERNET_HEADER) ///< Size in bytes of the Ethernet header
+#define MIN_ETHERNET_PKT_SIZE 60 ///< Minimum packet size including Ethernet header
+#define MAX_ETHERNET_PKT_SIZE 1500
+
+#define USB_NETWORK_CLASS 0x09 ///< USB Network class code
+#define USB_BUS_TIMEOUT 1000 ///< USB timeout in milliseconds
+
+#define AX88179_BULKIN_SIZE_INK 2
+#define AX88179_MAX_BULKIN_SIZE (1024 * AX88179_BULKIN_SIZE_INK)
+#define AX88179_MAX_PKT_SIZE 2048
+
+#define HC_DEBUG 0
+#define ADD_MACPATHNOD 1
+#define BULKIN_TIMEOUT 3 //5000
+#define TX_RETRY 0
+#define AUTONEG_DELAY 1000000
+
+/**
+ Verify new TPL value
+
+ This macro which is enabled when debug is enabled verifies that
+ the new TPL value is >= the current TPL value.
+**/
+#ifdef VERIFY_TPL
+#undef VERIFY_TPL
+#endif // VERIFY_TPL
+
+#if !defined(MDEPKG_NDEBUG)
+
+#define VERIFY_TPL(tpl) \
+{ \
+ EFI_TPL PreviousTpl; \
+ \
+ PreviousTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); \
+ gBS->RestoreTPL (PreviousTpl); \
+ if (PreviousTpl > tpl) { \
+ DEBUG ((DEBUG_ERROR, "Current TPL: %d, New TPL: %d\r\n", PreviousTpl, tpl)); \
+ ASSERT (PreviousTpl <= tpl); \
+ } \
+}
+
+#else // MDEPKG_NDEBUG
+
+#define VERIFY_TPL(tpl)
+
+#endif // MDEPKG_NDEBUG
+
+//------------------------------------------------------------------------------
+// Hardware Definition
+//------------------------------------------------------------------------------
+
+#define DEV_SIGNATURE SIGNATURE_32 ('A','X','8','8') ///< Signature of data structures in memory
+
+#define VENDOR_ID 0x0B95 ///< Vendor ID for Asix
+#define PRODUCT_ID 0x1790 ///< Product ID for the AX88179 USB 10/100 Ethernet controller
+#define PRODUCT_ID_178A 0x178A
+
+#define RESET_MSEC 1000 ///< Reset duration
+#define PHY_RESET_MSEC 100 ///< PHY reset duration
+
+//
+// RX Control register
+//
+
+
+//
+// Medium Status register
+//
+
+
+
+//
+// Software PHY Select register
+//
+
+#define SPHY_PSEL 0x01 ///< Select internal PHY
+#define SPHY_ASEL 0x02 ///< 1=Auto select, 0=Manual select
+
+//
+// Software Reset register
+//
+
+#define SRR_RR 0x01 ///< Clear receive frame length error
+#define SRR_RT 0x02 ///< Clear transmit frame length error
+#define SRR_PRTE 0x04 ///< External PHY reset pin tri-state enable
+#define SRR_PRL 0x08 ///< External PHY reset pin level
+#define SRR_BZ 0x10 ///< Force Bulk to return zero length packet
+#define SRR_IPRL 0x20 ///< Internal PHY reset control
+#define SRR_IPPD 0x40 ///< Internal PHY power down
+
+//
+// PHY ID values
+//
+
+#define PHY_ID_INTERNAL 0x0003 ///< Internal PHY
+
+//
+// USB Commands
+//
+
+#define CMD_PHY_ACCESS_SOFTWARE 0x06 ///< Software in control of PHY
+#define CMD_PHY_REG_READ 0x07 ///< Read PHY register, Value: PHY, Index: Register, Data: Register value
+#define CMD_PHY_REG_WRITE 0x08 ///< Write PHY register, Value: PHY, Index: Register, Data: New 16-bit value
+#define CMD_PHY_ACCESS_HARDWARE 0x0a ///< Hardware in control of PHY
+#define CMD_SROM_READ 0x0b ///< Read SROM register: Value: Address, Data: Value
+#define CMD_RX_CONTROL_WRITE 0x10 ///< Set the RX control register, Value: New value
+#define CMD_GAPS_WRITE 0x12 ///< Write the gaps register, Value: New value
+#define CMD_MAC_ADDRESS_READ 0x11 ///< Read the MAC address, Data: 6 byte MAC address
+#define CMD_MAC_ADDRESS_WRITE 0x14 ///< Set the MAC address, Data: New 6 byte MAC address
+
+#define CMD_MEDIUM_STATUS_READ 0x1a ///< Read medium status register, Data: Register value
+#define CMD_MEDIUM_STATUS_WRITE 0x1b ///< Write medium status register, Value: New value
+#define CMD_RESET 0x20 ///< Reset register, Value: New value
+#define CMD_PHY_SELECT 0x22 ///< PHY select register, Value: New value
+
+//------------------------------
+// USB Endpoints
+//------------------------------
+
+#define CONTROL_ENDPOINT 0 ///< Control endpoint
+#define INTERRUPT_ENDPOINT 1 ///< Interrupt endpoint
+#define BULK_IN_ENDPOINT 2 ///< Receive endpoint
+#define BULK_OUT_ENDPOINT 3 ///< Transmit endpoint
+
+//------------------------------
+// PHY Registers
+//------------------------------
+
+#define PHY_ANER 6 ///< Autonegotiation expansion register
+// BSMR - Register 1
+// ANAR and ANLPAR Registers 4, 5
+#define RXHDR_DROP 0x8000
+#define RXHDR_CRCERR 0x2000
+
+
+//------------------------------------------------------------------------------
+// Data Types
+//------------------------------------------------------------------------------
+
+/**
+ Ethernet header layout
+
+ IEEE 802.3-2002 Part 3 specification, section 3.1.1.
+**/
+#pragma pack(1)
+typedef struct {
+ UINT8 DestAddr[PXE_HWADDR_LEN_ETHER]; ///< Destination LAN address
+ UINT8 SrcAddr[PXE_HWADDR_LEN_ETHER]; ///< Source LAN address
+ UINT16 Type; ///< Protocol or length
+} ETHERNET_HEADER;
+#pragma pack()
+
+/**
+ Receive and Transmit packet structure
+**/
+#pragma pack(1)
+typedef struct _TX_PACKET {
+ UINT32 TxHdr1;
+ UINT32 TxHdr2;
+ UINT8 Data[AX88179_MAX_PKT_SIZE]; ///< Received packet data
+} TX_PACKET;
+#pragma pack()
+
+#pragma pack(1)
+typedef struct _RX_PACKET {
+ struct _RX_PACKET *Next;
+ UINT16 Length;
+ UINT16 EEEE;
+ UINT8 Data[AX88179_MAX_PKT_SIZE];
+} RX_PACKET;
+#pragma pack()
+
+/**
+ AX88179 control structure
+
+ The driver uses this structure to manage the Asix AX88179 10/100
+ Ethernet controller.
+**/
+typedef struct {
+ UINTN Signature; ///< Structure identification
+
+ //
+ // USB data
+ //
+ EFI_HANDLE Controller; ///< Controller handle
+ EFI_USB_IO_PROTOCOL *UsbIo; ///< USB driver interface
+
+ //
+ // Simple network protocol data
+ //
+ EFI_SIMPLE_NETWORK_PROTOCOL SimpleNetwork; ///< Driver's network stack interface
+ EFI_SIMPLE_NETWORK_MODE SimpleNetworkData; ///< Data for simple network
+
+ //
+ // Ethernet controller data
+ //
+ BOOLEAN Initialized; ///< Controller initialized
+ UINT16 PhyId; ///< PHY ID
+
+ //
+ // Link state
+ //
+ BOOLEAN LinkSpeed100Mbps; ///< Current link speed, FALSE = 10 Mbps
+ BOOLEAN LinkSpeed1000Mbps; ///< Current link speed, FALSE = 100/10 bps
+ BOOLEAN Complete; ///< Current state of auto-negotiation
+ BOOLEAN FullDuplex; ///< Current duplex
+ BOOLEAN LinkUp; ///< Current link state
+ BOOLEAN LinkIdle; ///< TRUE = No received traffic
+ EFI_EVENT Timer; ///< Timer to monitor link state and receive packets
+ UINTN PollCount; ///< Number of times the autonegotiation status was polled
+ UINTN SkipRXCnt;
+
+ UINT8 *BulkInbuf;
+ UINT16 PktCnt;
+ UINT8 *CurPktHdrOff;
+ UINT8 *CurPktOff;
+
+ TX_PACKET *TxTest;
+
+ INT8 MulticastHash[8];
+ EFI_MAC_ADDRESS MAC;
+
+ UINT16 CurMediumStatus;
+ UINT16 CurRxControl;
+ VOID * TxBuffer;
+
+ EFI_DEVICE_PATH_PROTOCOL *MyDevPath;
+ BOOLEAN Grub_f;
+ BOOLEAN FirstRst;
+ BOOLEAN SetZeroLen;
+ UINT8 RxBurst;
+ UINTN UsbMaxPktSize;
+} NIC_DEVICE;
+
+#define DEV_FROM_SIMPLE_NETWORK(a) CR (a, NIC_DEVICE, SimpleNetwork, DEV_SIGNATURE) ///< Locate NIC_DEVICE from Simple Network Protocol
+
+//------------------------------------------------------------------------------
+// Simple Network Protocol
+//------------------------------------------------------------------------------
+
+/**
+ Reset the network adapter.
+
+ Resets a network adapter and reinitializes it with the parameters that
+ were provided in the previous call to Initialize (). The transmit and
+ receive queues are cleared. Receive filters, the station address, the
+ statistics, and the multicast-IP-to-HW MAC addresses are not reset by
+ this call.
+
+ This routine calls ::Ax88179Reset to perform the adapter specific
+ reset operation. This routine also starts the link negotiation
+ by calling ::Ax88179NegotiateLinkStart.
+
+ @param [in] SimpleNetwork Protocol instance pointer
+ @param [in] ExtendedVerification Indicates that the driver may perform a more
+ exhaustive verification operation of the device
+ during reset.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Reset (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
+ IN BOOLEAN ExtendedVerification
+ );
+
+/**
+ Initialize the simple network protocol.
+
+ This routine calls ::Ax88179MacAddressGet to obtain the
+ MAC address.
+
+ @param [in] NicDevice NIC_DEVICE_INSTANCE pointer
+
+ @retval EFI_SUCCESS Setup was successful
+
+**/
+EFI_STATUS
+SN_Setup (
+ IN NIC_DEVICE *NicDevice
+ );
+
+/**
+ This routine starts the network interface.
+
+ @param [in] SimpleNetwork Protocol instance pointer
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_ALREADY_STARTED The network interface was already started.
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Start (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork
+ );
+
+/**
+ Set the MAC address.
+
+ This function modifies or resets the current station address of a
+ network interface. If Reset is TRUE, then the current station address
+ is set ot the network interface's permanent address. If Reset if FALSE
+ then the current station address is changed to the address specified by
+ New.
+
+ This routine calls ::Ax88179MacAddressSet to update the MAC address
+ in the network adapter.
+
+ @param [in] SimpleNetwork Protocol instance pointer
+ @param [in] Reset Flag used to reset the station address to the
+ network interface's permanent address.
+ @param [in] New New station address to be used for the network
+ interface.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_StationAddress (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
+ IN BOOLEAN Reset,
+ IN EFI_MAC_ADDRESS *New
+ );
+
+/**
+ This function resets or collects the statistics on a network interface.
+ If the size of the statistics table specified by StatisticsSize is not
+ big enough for all of the statistics that are collected by the network
+ interface, then a partial buffer of statistics is returned in
+ StatisticsTable.
+
+ @param [in] SimpleNetwork Protocol instance pointer
+ @param [in] Reset Set to TRUE to reset the statistics for the network interface.
+ @param [in, out] StatisticsSize On input the size, in bytes, of StatisticsTable. On output
+ the size, in bytes, of the resulting table of statistics.
+ @param [out] StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that
+ conains the statistics.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_BUFFER_TOO_SMALL The StatisticsTable is NULL or the buffer is too small.
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Statistics (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
+ IN BOOLEAN Reset,
+ IN OUT UINTN *StatisticsSize,
+ OUT EFI_NETWORK_STATISTICS *StatisticsTable
+ );
+
+/**
+ This function stops a network interface. This call is only valid
+ if the network interface is in the started state.
+
+ @param [in] SimpleNetwork Protocol instance pointer
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Stop (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork
+ );
+
+/**
+ This function releases the memory buffers assigned in the Initialize() call.
+ Ending transmits and receives are lost, and interrupts are cleared and disabled.
+ After this call, only Initialize() and Stop() calls may be used.
+
+ @param [in] SimpleNetwork Protocol instance pointer
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Shutdown (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork
+ );
+
+/**
+ Send a packet over the network.
+
+ This function places the packet specified by Header and Buffer on
+ the transmit queue. This function performs a non-blocking transmit
+ operation. When the transmit is complete, the buffer is returned
+ via the GetStatus() call.
+
+ This routine calls ::Ax88179Rx to empty the network adapter of
+ receive packets. The routine then passes the transmit packet
+ to the network adapter.
+
+ @param [in] SimpleNetwork Protocol instance pointer
+ @param [in] HeaderSize The size, in bytes, of the media header to be filled in by
+ the Transmit() function. If HeaderSize is non-zero, then
+ it must be equal to SimpleNetwork->Mode->MediaHeaderSize
+ and DestAddr and Protocol parameters must not be NULL.
+ @param [in] BufferSize The size, in bytes, of the entire packet (media header and
+ data) to be transmitted through the network interface.
+ @param [in] Buffer A pointer to the packet (media header followed by data) to
+ to be transmitted. This parameter can not be NULL. If
+ HeaderSize is zero, then the media header is Buffer must
+ already be filled in by the caller. If HeaderSize is nonzero,
+ then the media header will be filled in by the Transmit()
+ function.
+ @param [in] SrcAddr The source HW MAC address. If HeaderSize is zero, then
+ this parameter is ignored. If HeaderSize is nonzero and
+ SrcAddr is NULL, then SimpleNetwork->Mode->CurrentAddress
+ is used for the source HW MAC address.
+ @param [in] DestAddr The destination HW MAC address. If HeaderSize is zero, then
+ this parameter is ignored.
+ @param [in] Protocol The type of header to build. If HeaderSize is zero, then
+ this parameter is ignored.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_NOT_READY The network interface is too busy to accept this transmit request.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Transmit (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
+ IN UINTN HeaderSize,
+ IN UINTN BufferSize,
+ IN VOID *Buffer,
+ IN EFI_MAC_ADDRESS *SrcAddr,
+ IN EFI_MAC_ADDRESS *DestAddr,
+ IN UINT16 *Protocol
+ );
+
+//------------------------------------------------------------------------------
+// Support Routines
+//------------------------------------------------------------------------------
+
+/**
+ Get the MAC address
+
+ This routine calls ::Ax88179UsbCommand to request the MAC
+ address from the network adapter.
+
+ @param [in] NicDevice Pointer to the NIC_DEVICE structure
+ @param [out] MacAddress Address of a six byte buffer to receive the MAC address.
+
+ @retval EFI_SUCCESS The MAC address is available.
+ @retval other The MAC address is not valid.
+
+**/
+EFI_STATUS
+Ax88179MacAddressGet (
+ IN NIC_DEVICE *NicDevice,
+ OUT UINT8 *MacAddress
+ );
+
+
+/**
+ Clear the multicast hash table
+
+ @param [in] NicDevice Pointer to the NIC_DEVICE structure
+
+**/
+VOID
+Ax88179MulticastClear (
+ IN NIC_DEVICE *NicDevice
+ );
+
+/**
+ Enable a multicast address in the multicast hash table
+
+ This routine calls ::Ax88179Crc to compute the hash bit for
+ this MAC address.
+
+ @param [in] NicDevice Pointer to the NIC_DEVICE structure
+ @param [in] MacAddress Address of a six byte buffer to containing the MAC address.
+
+**/
+VOID
+Ax88179MulticastSet (
+ IN NIC_DEVICE *NicDevice,
+ IN UINT8 *MacAddress
+ );
+
+/**
+ Start the link negotiation
+
+ This routine calls ::Ax88179PhyWrite to start the PHY's link
+ negotiation.
+
+ @param [in] NicDevice Pointer to the NIC_DEVICE structure
+
+ @retval EFI_SUCCESS The link negotiation was started.
+ @retval other Failed to start the link negotiation.
+
+**/
+EFI_STATUS
+Ax88179NegotiateLinkStart (
+ IN NIC_DEVICE *NicDevice
+ );
+
+/**
+ Complete the negotiation of the PHY link
+
+ This routine calls ::Ax88179PhyRead to determine if the
+ link negotiation is complete.
+
+ @param [in] NicDevice Pointer to the NIC_DEVICE structure
+ @param [in, out] PollCount Address of number of times this routine was polled
+ @param [out] Complete Address of boolean to receive complate status.
+ @param [out] LinkUp Address of boolean to receive link status, TRUE=up.
+ @param [out] HiSpeed Address of boolean to receive link speed, TRUE=100Mbps.
+ @param [out] FullDuplex Address of boolean to receive link duplex, TRUE=full.
+
+ @retval EFI_SUCCESS The MAC address is available.
+ @retval other The MAC address is not valid.
+
+**/
+EFI_STATUS
+Ax88179NegotiateLinkComplete (
+ IN NIC_DEVICE *NicDevice,
+ IN OUT UINTN *PollCount,
+ OUT BOOLEAN *Complete,
+ OUT BOOLEAN *LinkUp,
+ OUT BOOLEAN *HiSpeed,
+ OUT BOOLEAN *GigaSpeed,
+ OUT BOOLEAN *FullDuplex
+ );
+
+/**
+ Read a register from the PHY
+
+ This routine calls ::Ax88179UsbCommand to read a PHY register.
+
+ @param [in] NicDevice Pointer to the NIC_DEVICE structure
+ @param [in] RegisterAddress Number of the register to read.
+ @param [in, out] PhyData Address of a buffer to receive the PHY register value
+
+ @retval EFI_SUCCESS The PHY data is available.
+ @retval other The PHY data is not valid.
+
+**/
+
+
+/**
+ Reset the AX88179
+
+ This routine uses ::Ax88179UsbCommand to reset the network
+ adapter. This routine also uses ::Ax88179PhyWrite to reset
+ the PHY.
+
+ @param [in] NicDevice Pointer to the NIC_DEVICE structure
+
+ @retval EFI_SUCCESS The MAC address is available.
+ @retval other The MAC address is not valid.
+
+**/
+EFI_STATUS
+Ax88179Reset (
+ IN NIC_DEVICE *NicDevice
+ );
+
+/**
+ Enable or disable the receiver
+
+ This routine calls ::Ax88179UsbCommand to update the
+ receiver state. This routine also calls ::Ax88179MacAddressSet
+ to establish the MAC address for the network adapter.
+
+ @param [in] NicDevice Pointer to the NIC_DEVICE structure
+ @param [in] RxFilter Simple network RX filter mask value
+
+ @retval EFI_SUCCESS The MAC address was set.
+ @retval other The MAC address was not set.
+
+**/
+EFI_STATUS
+Ax88179RxControl (
+ IN NIC_DEVICE *NicDevice,
+ IN UINT32 RxFilter
+ );
+
+ EFI_STATUS
+Ax88179ReloadSrom (
+ IN NIC_DEVICE *NicDevice
+ );
+
+/**
+ Read an SROM location
+
+ This routine calls ::Ax88179UsbCommand to read data from the
+ SROM.
+
+ @param [in] NicDevice Pointer to the NIC_DEVICE structure
+ @param [in] Address SROM address
+ @param [out] Data Buffer to receive the data
+
+ @retval EFI_SUCCESS The read was successful
+ @retval other The read failed
+
+**/
+EFI_STATUS
+Ax88179SromRead (
+ IN NIC_DEVICE *NicDevice,
+ IN UINT32 Address,
+ OUT UINT16 *Data
+ );
+
+
+EFI_STATUS
+Ax88179EnableSromWrite (
+ IN NIC_DEVICE *NicDevice
+ );
+
+
+EFI_STATUS
+Ax88179DisableSromWrite (
+ IN NIC_DEVICE *NicDevice
+ );
+
+EFI_STATUS
+Ax88179SromWrite (
+ IN NIC_DEVICE *NicDevice,
+ IN UINT32 Address,
+ OUT UINT16 *Data
+ );
+
+/**
+ Send a command to the USB device.
+
+ @param [in] NicDevice Pointer to the NIC_DEVICE structure
+ @param [in] Request Pointer to the request structure
+ @param [in, out] Buffer Data buffer address
+
+ @retval EFI_SUCCESS The USB transfer was successful
+ @retval other The USB transfer failed
+
+**/
+
+EFI_STATUS
+Ax88179UsbCommand (
+ IN NIC_DEVICE *NicDevice,
+ IN USB_DEVICE_REQUEST *Request,
+ IN OUT VOID *Buffer
+ );
+
+//------------------------------------------------------------------------------
+// EFI Component Name Protocol Support
+//------------------------------------------------------------------------------
+extern EFI_DRIVER_BINDING_PROTOCOL gDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gComponentName; ///< Component name protocol declaration
+extern EFI_COMPONENT_NAME2_PROTOCOL gComponentName2; ///< Component name 2 protocol declaration
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param [in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param [in] Language A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 3066 or ISO 639-2 language code format.
+ @param [out] DriverName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+GetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param [in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param [in] ControllerHandle The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+ @param [in] ChildHandle The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+ @param [in] Language A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 3066 or ISO 639-2 language code format.
+ @param [out] ControllerName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+GetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN OPTIONAL EFI_HANDLE ChildHandle,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+EFI_STATUS
+Ax88179SetMedium (
+ IN NIC_DEVICE * NicDevice
+ );
+
+//-----------------------------------------------------------------------------
+
+
+#define ACCESS_MAC 0x01
+#define ACCESS_PHY 0x02
+
+#define PLSR 0x02
+ #define PLSR_USB_FS 0x01
+ #define PLSR_USB_HS 0x02
+ #define PLSR_USB_SS 0x04
+
+#define NODE_ID 0x10
+
+#define RXCTL 0x0b
+ #define RXCTL_PRO 0x0001 ///< Receive all packets
+ #define RXCTL_AMALL 0x0002 ///< Receive all multicast packets
+ #define RXCTL_SEP 0x0004 ///< Save error packets
+ #define RXCTL_AB 0x0008 ///< Receive broadcast packets
+ #define RXCTL_AM 0x0010 ///< Use multicast destination address hash table
+ #define RXCTL_AP 0x0020 ///< Accept physical address from Multicast Filter
+ #define RXCTL_ARP 0x0040 ///< Accept runt packet
+ #define RXCTL_SO 0x0080 ///< Start operation
+ #define RXCTL_DROPCRCERR 0x0100 ///< RX header 1 formate selection
+ #define RXCTL_IPE 0x0200 ///< RX header 2 formate selection
+ #define RXCTL_TXPADCRC 0x0400 ///< RX header 3 formate selection
+ #define RXCTL_LPBK 0x1000 ///< MAC loop back for diagnostic
+
+#define MULCATFLTARRY 0x16 ///< Write the multicast hash table, Data: New 8 byte value
+
+#define MEDIUMSTSMOD 0x22
+ #define MEDIUMSTSMOD_GM 0x0001 ///< Gigabit Mode
+ #define MEDIUMSTSMOD_FD 0x0002 ///< Full duplex
+ #define MEDIUMSTSMOD_ONE 0x0004 ///< Must be one
+ #define MEDIUMSTSMOD_ENCK 0x0008 ///< Add in 04h
+ #define MEDIUMSTSMOD_RFC 0x0010 ///< RX flow control enable
+ #define MEDIUMSTSMOD_TFC 0x0020 ///< TX flow control enable
+ #define MEDIUMSTSMOD_JFE 0x0040 ///< Pause frame enable
+ #define MEDIUMSTSMOD_PF 0x0080 ///< Pause frame enable
+ #define MEDIUMSTSMOD_RE 0x0100 ///< Receive enable
+ #define MEDIUMSTSMOD_PS 0x0200 ///< Port speed 1=100, 0=10 Mbps
+ #define MEDIUMSTSMOD_SBP 0x0800 ///< Stop back pressure
+ #define MEDIUMSTSMOD_SM 0x1000 ///< Super MAC support
+
+#define MONITORSTAUS 0x24
+ #define MONITORSTAUS_PMETYPE 0x40
+ #define MONITORSTAUS_PMEPOL 0x20
+
+#define PHYPWRRSTCTL 0x26
+ #define PHYPWRRSTCTL_IPRL 0x20
+ #define PHYPWRRSTCTL_OSCDSSEL 0x80
+ #define PHYPWRRSTCTL_BZTYPE 0x4
+ #define PHYPWRRSTCTL_BZ 0x10
+
+#define SISSR 0x28
+ #define SISSR_PSEL 0x01
+ #define SISSR_ASEL 0x02
+
+#define RXBINQCTRL 0x2e
+ #define RXBINQCTRL_TIMEN 0x01
+ #define RXBINQCTRL_IFGEN 0x02
+ #define RXBINQCTRL_SIZEN 0x04
+
+#define RXBINQTIMERL 0x2f
+#define RXBINQTIMERH 0x30
+#define RXBINQSIZE 0x31
+#define RXBINQIFG 0x32
+
+#define CLKSELECT 0x33
+ #define CLKSELECT_ACS 0x02
+ #define CLKSELECT_BCS 0x01
+
+#define PAUSE_WATERLVL_HIGH 0x54
+#define PAUSE_WATERLVL_LOW 0x55
+
+#define RXFREEBUF 0x57
+ #define MAX_RXBUF_PAGE 0x067F
+
+#define PHY_BMCR 0 ///< Control register
+ #define BMCR_RESET 0x8000 ///< 1 = Reset the PHY, bit clears after reset
+ #define BMCR_LOOPBACK 0x4000 ///< 1 = Loopback enabled
+ #define BMCR_AUTONEGOTIATION_ENABLE 0x1000 ///< 1 = Enable autonegotiation
+ #define BMCR_POWER_DOWN 0x0800 ///< 1 = Power down
+ #define BMCR_ISOLATE 0x0400 ///< 0 = Isolate PHY
+ #define BMCR_RESTART_AUTONEGOTIATION 0x0200 ///< 1 = Restart autonegotiation
+ #define BMCR_FULL_DUPLEX 0x0100 ///< Full duplex operation
+ #define BMCR_COLLISION_TEST 0x0080 ///< 1 = Collision test enabled
+ #define BMCR_1000MBPS 0x40 ///< Forced mode in 1000Mbps
+ #define BMCR_100MBPS 0x2000 ///< Forced mode in 10Mbps
+
+#define PHY_BMSR 1 ///< Status register
+ #define BMSR_100BASET4 0x8000 ///< 1 = 100BASE-T4 mode
+ #define BMSR_100BASETX_FDX 0x4000 ///< 1 = 100BASE-TX full duplex
+ #define BMSR_100BASETX_HDX 0x2000 ///< 1 = 100BASE-TX half duplex
+ #define BMSR_10BASET_FDX 0x1000 ///< 1 = 10BASE-T full duplex
+ #define BMSR_10BASET_HDX 0x0800 ///< 1 = 10BASE-T half duplex
+ #define BMSR_MF 0x0040 ///< 1 = PHY accepts frames with preamble suppressed
+ #define BMSR_AUTONEG_CMPLT 0x0020 ///< 1 = Autonegotiation complete
+ #define BMSR_RF 0x0010 ///< 1 = Remote fault
+ #define BMSR_AUTONEG 0x0008 ///< 1 = Able to perform autonegotiation
+ #define BMSR_LINKST 0x0004 ///< 1 = Link up
+ #define BMSR_JABBER_DETECT 0x0002 ///< 1 = jabber condition detected
+ #define BMSR_EXTENDED_CAPABILITY 0x0001 ///< 1 = Extended register capable
+
+#define PHY_ANAR 4 ///< Autonegotiation advertisement register
+ #define AN_NP 0x8000 ///< 1 = Next page available
+ #define AN_RF 0x2000 ///< 1 = Remote fault indicated by link partner
+ #define AN_FCS 0x0400 ///< 1 = Flow control ability
+ #define AN_T4 0x0200 ///< 1 = 100BASE-T4 support
+ #define AN_TX_FDX 0x0100 ///< 1 = 100BASE-TX Full duplex
+ #define AN_TX_HDX 0x0080 ///< 1 = 100BASE-TX support
+ #define AN_10_FDX 0x0040 ///< 1 = 10BASE-T Full duplex
+ #define AN_10_HDX 0x0020 ///< 1 = 10BASE-T support
+ #define AN_CSMA_CD 0x0001 ///< 1 = IEEE 802.3 CSMA/CD support
+
+#define PHY_ANLPAR 5 ///< Autonegotiation link parter ability register
+
+#define PHY_PHYSR 0x11
+ #define PHYSR_SPEED_MASK 0xC000
+ #define PHYSR_1000 0x8000
+ #define PHYSR_100 0x4000
+ #define PHYSR_FULLDUP 0x2000
+ #define PHYSR_LINK 0x400
+
+EFI_STATUS
+Ax88179PhyRead (
+ IN NIC_DEVICE *NicDevice,
+ IN UINT8 RegisterAddress,
+ IN OUT UINT16 *PhyData
+ );
+
+EFI_STATUS
+Ax88179PhyWrite (
+ IN NIC_DEVICE *NicDevice,
+ IN UINT8 RegisterAddress,
+ IN UINT16 PhyData
+ );
+
+EFI_STATUS
+Ax88179MacRead (
+ IN UINT8 Offset,
+ IN UINT8 Length,
+ IN NIC_DEVICE * NicDevice,
+ IN OUT VOID *Data
+ );
+
+EFI_STATUS
+Ax88179SetIInInterval (
+ IN NIC_DEVICE *NicDevice,
+ IN UINT8 Offset
+ );
+
+EFI_STATUS
+Ax88179MacWrite (
+ IN UINT8 Offset,
+ IN UINT8 Length,
+ IN NIC_DEVICE *NicDevice,
+ IN OUT VOID *Data
+ );
+
+EFI_STATUS
+Ax88179MacAddressGet (
+ IN NIC_DEVICE *NicDevice,
+ OUT UINT8 *MacAddress
+ );
+
+EFI_STATUS
+Ax88179MacAddressSet (
+ IN NIC_DEVICE *NicDevice,
+ OUT UINT8 *MacAddress
+ );
+
+BOOLEAN
+Ax88179GetLinkStatus (
+ IN NIC_DEVICE *NicDevice
+);
+
+EFI_STATUS
+Ax88179BulkIn(
+ IN NIC_DEVICE *NicDevice
+);
+
+
+#endif // AX88179_H_
diff --git a/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.c b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.c
new file mode 100644
index 000000000000..a2af3c5618d1
--- /dev/null
+++ b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.c
@@ -0,0 +1,1042 @@
+ /** @file
+ Implement the interface to the AX88179 Ethernet controller.
+
+ This module implements the interface to the ASIX AX88179
+ USB to Ethernet MAC with integrated 10/100 PHY. Note that this implementation
+ only supports the integrated PHY since no other test cases were available.
+
+ Copyright (c) 2011, Intel Corporation
+ Copyright (c) 2020, ARM Limited. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Ax88179.h"
+
+
+/**
+ Compute the CRC
+
+ @param [in] MacAddress Address of a six byte buffer to containing the MAC address.
+
+ @returns The CRC-32 value associated with this MAC address
+
+**/
+UINT32
+Ax88179Crc (
+ IN UINT8 *MacAddress
+ )
+{
+ UINT32 BitNumber;
+ INT32 Carry;
+ INT32 Crc;
+ UINT32 Data;
+ UINT8 *End;
+
+ //
+ // Walk the MAC address
+ //
+ Crc = -1;
+ End = &MacAddress[PXE_HWADDR_LEN_ETHER];
+ while (End > MacAddress) {
+ Data = *MacAddress++;
+
+
+ //
+ // CRC32: x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1
+ //
+ // 1 0000 0100 1100 0001 0001 1101 1011 0111
+ //
+ for (BitNumber = 0; 8 > BitNumber; BitNumber++) {
+ Carry = ((Crc >> 31) & 1) ^ (Data & 1);
+ Crc <<= 1;
+ if (Carry != 0) {
+ Crc ^= 0x04c11db7;
+ }
+ Data >>= 1;
+ }
+ }
+
+ //
+ // Return the CRC value
+ //
+ return (UINT32) Crc;
+}
+
+/**
+ Get the MAC address
+
+ This routine calls ::Ax88179UsbCommand to request the MAC
+ address from the network adapter.
+
+ @param [in] NicDevice Pointer to the NIC_DEVICE structure
+ @param [out] MacAddress Address of a six byte buffer to receive the MAC address.
+
+ @retval EFI_SUCCESS The MAC address is available.
+ @retval other The MAC address is not valid.
+
+**/
+EFI_STATUS
+Ax88179MacAddressGet (
+ IN NIC_DEVICE *NicDevice,
+ OUT UINT8 *MacAddress
+ )
+{
+ EFI_STATUS Status;
+
+ Status = Ax88179MacRead (NODE_ID,
+ PXE_HWADDR_LEN_ETHER,
+ NicDevice,
+ MacAddress);
+
+ return Status;
+}
+
+/**
+ Set the MAC address
+
+ This routine calls ::Ax88179UsbCommand to set the MAC address
+ in the network adapter.
+
+ @param [in] NicDevice Pointer to the NIC_DEVICE structure
+ @param [in] MacAddress Address of a six byte buffer to containing the new MAC address.
+
+ @retval EFI_SUCCESS The MAC address was set.
+ @retval other The MAC address was not set.
+
+**/
+EFI_STATUS
+Ax88179MacAddressSet (
+ IN NIC_DEVICE *NicDevice,
+ OUT UINT8 *MacAddress
+ )
+{
+ EFI_STATUS Status;
+
+ Status = Ax88179MacWrite (NODE_ID,
+ PXE_HWADDR_LEN_ETHER,
+ NicDevice,
+ MacAddress);
+
+ return Status;
+}
+
+/**
+ Clear the multicast hash table
+
+ @param [in] NicDevice Pointer to the NIC_DEVICE structure
+
+**/
+VOID
+Ax88179MulticastClear (
+ IN NIC_DEVICE *NicDevice
+ )
+{
+ int Index = 0;
+ //
+ // Clear the multicast hash table
+ //
+ for (Index = 0 ; Index < 8 ; Index ++)
+ NicDevice->MulticastHash[Index] = 0;
+}
+
+/**
+ Enable a multicast address in the multicast hash table
+
+ This routine calls ::Ax88179Crc to compute the hash bit for
+ this MAC address.
+
+ @param [in] NicDevice Pointer to the NIC_DEVICE structure
+ @param [in] MacAddress Address of a six byte buffer to containing the MAC address.
+
+**/
+VOID
+Ax88179MulticastSet (
+ IN NIC_DEVICE *NicDevice,
+ IN UINT8 *MacAddress
+ )
+{
+ UINT32 Crc;
+
+ //
+ // Compute the CRC on the destination address
+ //
+ Crc = Ax88179Crc (MacAddress) >> 26;
+
+ //
+ // Set the bit corresponding to the destination address
+ //
+ NicDevice->MulticastHash [Crc >> 3] |= (1 << (Crc & 7));
+
+}
+
+/**
+ Start the link negotiation
+
+ This routine calls ::Ax88179PhyWrite to start the PHY's link
+ negotiation.
+
+ @param [in] NicDevice Pointer to the NIC_DEVICE structure
+
+ @retval EFI_SUCCESS The link negotiation was started.
+ @retval other Failed to start the link negotiation.
+
+**/
+EFI_STATUS
+Ax88179NegotiateLinkStart (
+ IN NIC_DEVICE *NicDevice
+ )
+{
+ UINT16 Control = 0;
+ EFI_STATUS Status;
+
+#if FORCE_100Mbps
+ Ax88179PhyRead (NicDevice,
+ 0x09,
+ &Control);
+ Control &= 0xFCFF;
+ Ax88179PhyWrite (NicDevice, 0x09, Control);
+#endif
+
+ //
+ // Set the link speed and duplex
+ //
+ Control = BMCR_AUTONEGOTIATION_ENABLE
+ | BMCR_RESTART_AUTONEGOTIATION;
+ if (NicDevice->LinkSpeed1000Mbps) {
+ Control |= BMCR_1000MBPS;
+ } else if (NicDevice->LinkSpeed100Mbps) {
+ Control |= BMCR_100MBPS;
+ }
+
+ if (NicDevice->FullDuplex) {
+ Control |= BMCR_FULL_DUPLEX;
+ }
+ Status = Ax88179PhyWrite (NicDevice, PHY_BMCR, Control);
+ if (!EFI_ERROR(Status))
+ gBS->Stall(3000000);
+ //
+ // Return the operation status
+ //
+ return Status;
+}
+
+
+
+/**
+ Complete the negotiation of the PHY link
+
+ This routine calls ::Ax88179PhyRead to determine if the
+ link negotiation is complete.
+
+ @param [in] NicDevice Pointer to the NIC_DEVICE structure
+ @param [in, out] PollCount Address of number of times this routine was polled
+ @param [out] Complete Address of boolean to receive complate status.
+ @param [out] LinkUp Address of boolean to receive link status, TRUE=up.
+ @param [out] HiSpeed Address of boolean to receive link speed, TRUE=100Mbps.
+ @param [out] FullDuplex Address of boolean to receive link duplex, TRUE=full.
+
+ @retval EFI_SUCCESS The MAC address is available.
+ @retval other The MAC address is not valid.
+
+**/
+EFI_STATUS
+Ax88179NegotiateLinkComplete (
+ IN NIC_DEVICE *NicDevice,
+ IN OUT UINTN *PollCount,
+ OUT BOOLEAN *Complete,
+ OUT BOOLEAN *LinkUp,
+ OUT BOOLEAN *HiSpeed,
+ OUT BOOLEAN *GigaSpeed,
+ OUT BOOLEAN *FullDuplex
+ )
+{
+ UINT16 PhyData;
+ EFI_STATUS Status;
+
+ //
+ // Determine if the link is up.
+ //
+ *Complete = FALSE;
+
+ //
+ // Get the link status
+ //
+ Status = Ax88179PhyRead (NicDevice,
+ PHY_PHYSR,
+ &PhyData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ *LinkUp = ((PhyData & PHYSR_LINK) != 0);
+ if (*LinkUp) {
+ //
+ // Determine if the autonegotiation is complete.
+ //
+ Status = Ax88179PhyRead (NicDevice,
+ PHY_BMSR,
+ &PhyData);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ *Complete = ((PhyData & BMSR_AUTONEG_CMPLT) != 0);
+
+ if (*Complete != 0) {
+ //
+ // Get the partners capabilities.
+ //
+ Status = Ax88179PhyRead (NicDevice,
+ PHY_PHYSR,
+ &PhyData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Autonegotiation is complete
+ // Determine the link speed.
+ //
+ *GigaSpeed = ((PhyData & PHYSR_SPEED_MASK) == PHYSR_1000);
+ *HiSpeed = ((PhyData & PHYSR_SPEED_MASK) == PHYSR_100);
+
+ //
+ // Determine the link duplex.
+ //
+ *FullDuplex = ((PhyData & PHYSR_FULLDUP) == PHYSR_FULLDUP);
+ }
+ }
+
+
+ //
+ // Return the operation status
+ //
+ return Status;
+}
+
+
+/**
+ Read a register from the PHY
+
+ This routine calls ::Ax88179UsbCommand to read a PHY register.
+
+ @param [in] NicDevice Pointer to the NIC_DEVICE structure
+ @param [in] RegisterAddress Number of the register to read.
+ @param [in, out] PhyData Address of a buffer to receive the PHY register value
+
+ @retval EFI_SUCCESS The PHY data is available.
+ @retval other The PHY data is not valid.
+
+**/
+EFI_STATUS
+Ax88179PhyRead (
+ IN NIC_DEVICE *NicDevice,
+ IN UINT8 RegisterAddress,
+ IN OUT UINT16 *PhyData
+ )
+{
+ USB_DEVICE_REQUEST SetupMsg;
+ EFI_STATUS Status;
+
+ //
+ // Read the PHY register address.
+ //
+ SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
+ | USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = ACCESS_PHY;
+ SetupMsg.Value = NicDevice->PhyId;
+ SetupMsg.Index = RegisterAddress;
+ SetupMsg.Length = sizeof (*PhyData);
+ Status = Ax88179UsbCommand (NicDevice,
+ &SetupMsg,
+ PhyData);
+
+ //
+ // Return the operation status.
+ //
+ return Status;
+}
+
+
+/**
+ Write to a PHY register
+
+ This routine calls ::Ax88179UsbCommand to write a PHY register.
+
+ @param [in] NicDevice Pointer to the NIC_DEVICE structure
+ @param [in] RegisterAddress Number of the register to read.
+ @param [in] PhyData Address of a buffer to receive the PHY register value
+
+ @retval EFI_SUCCESS The PHY data was written.
+ @retval other Failed to wwrite the PHY register.
+
+**/
+EFI_STATUS
+Ax88179PhyWrite (
+ IN NIC_DEVICE *NicDevice,
+ IN UINT8 RegisterAddress,
+ IN UINT16 PhyData
+ )
+{
+ USB_DEVICE_REQUEST SetupMsg;
+ EFI_STATUS Status;
+
+ //
+ // Write the PHY register
+ //
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+ SetupMsg.Request = ACCESS_PHY;
+ SetupMsg.Value = NicDevice->PhyId;
+ SetupMsg.Index = RegisterAddress;
+ SetupMsg.Length = sizeof (PhyData);
+ Status = Ax88179UsbCommand (NicDevice,
+ &SetupMsg,
+ &PhyData);
+ //
+ // Return the operation status.
+ //
+ return Status;
+}
+
+
+/**
+ Reset the AX88179
+
+ This routine uses ::Ax88179UsbCommand to reset the network
+ adapter. This routine also uses ::Ax88179PhyWrite to reset
+ the PHY.
+
+ @param [in] NicDevice Pointer to the NIC_DEVICE structure
+
+ @retval EFI_SUCCESS The MAC address is available.
+ @retval other The MAC address is not valid.
+
+**/
+EFI_STATUS
+Ax88179Reset (
+ IN NIC_DEVICE *NicDevice
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Val;
+ UINT8 Val8;
+
+ Status = Ax88179SetIInInterval(NicDevice, 0xff);
+
+ if (EFI_ERROR(Status)) goto err;
+
+ Val8 = 0;
+ Status = Ax88179MacRead (PLSR,
+ sizeof(Val8),
+ NicDevice,
+ &Val8);
+
+ if (EFI_ERROR(Status)) goto err;
+
+ if (Val8 & PLSR_USB_SS)
+ NicDevice->UsbMaxPktSize = 1024;
+ else
+ NicDevice->UsbMaxPktSize = 512;
+
+ Val = 0;
+ Status = Ax88179MacWrite (PHYPWRRSTCTL,
+ sizeof (Val),
+ NicDevice,
+ &Val);
+
+ if (EFI_ERROR(Status)) goto err;
+
+ gBS->Stall (10000);
+
+ Val = PHYPWRRSTCTL_IPRL;
+ Status = Ax88179MacWrite (PHYPWRRSTCTL,
+ sizeof (Val),
+ NicDevice,
+ &Val);
+
+ if (EFI_ERROR(Status)){
+ goto err;
+ }
+
+ gBS->Stall (200000);
+
+ Val = CLKSELECT_BCS | CLKSELECT_ACS;
+ Status = Ax88179MacWrite (CLKSELECT,
+ 1,
+ NicDevice,
+ &Val);
+
+ if (EFI_ERROR(Status)) goto err;
+
+ gBS->Stall (100000);
+
+ Val = 0x52;
+ Status = Ax88179MacWrite (PAUSE_WATERLVL_HIGH,
+ 1,
+ NicDevice,
+ &Val);
+
+ if (EFI_ERROR(Status)) goto err;
+
+ Val = 0x34;
+ Status = Ax88179MacWrite (PAUSE_WATERLVL_LOW,
+ 1,
+ NicDevice,
+ &Val);
+
+ if (EFI_ERROR(Status)) goto err;
+
+ Val = RXBINQCTRL_TIMEN | RXBINQCTRL_IFGEN | RXBINQCTRL_SIZEN;
+
+ Status = Ax88179MacWrite (RXBINQCTRL,
+ 0x01,
+ NicDevice,
+ &Val);
+
+ if (EFI_ERROR(Status)) goto err;
+
+ Val = 0;
+ Status = Ax88179MacWrite (RXBINQTIMERL,
+ 0x01,
+ NicDevice,
+ &Val);
+
+ if (EFI_ERROR(Status)) goto err;
+
+ Val = 0;
+ Status = Ax88179MacWrite (RXBINQTIMERH,
+ 0x01,
+ NicDevice,
+ &Val);
+
+ if (EFI_ERROR(Status)) goto err;
+
+ Val = 12; //AX88179_BULKIN_SIZE_INK - 1;
+ Status = Ax88179MacWrite (RXBINQSIZE,
+ 0x01,
+ NicDevice,
+ &Val);
+
+ if (EFI_ERROR(Status)) goto err;
+
+ Val = 0x0F;
+ Status = Ax88179MacWrite (RXBINQIFG,
+ 0x01,
+ NicDevice,
+ &Val);
+
+err:
+ return Status;
+}
+
+EFI_STATUS
+Ax88179RxControl (
+ IN NIC_DEVICE *NicDevice,
+ IN UINT32 RxFilter
+ )
+{
+ UINT16 MediumStatus;
+ UINT16 RxControl = 0;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ //
+ // Enable the receiver if something is to be received
+ //
+ if (RxFilter != 0) {
+ //
+ // Enable the receiver
+ //
+ Status = Ax88179MacRead (MEDIUMSTSMOD,
+ sizeof (MediumStatus),
+ NicDevice,
+ &MediumStatus);
+
+ if (!EFI_ERROR (Status) && NicDevice->CurMediumStatus != MediumStatus) {
+ MediumStatus = MEDIUMSTSMOD_RE | MEDIUMSTSMOD_ONE;
+ if (NicDevice->FullDuplex) {
+ MediumStatus |= MEDIUMSTSMOD_TFC | MEDIUMSTSMOD_RFC | MEDIUMSTSMOD_FD;
+ } else {
+ MediumStatus &= ~(MEDIUMSTSMOD_TFC | MEDIUMSTSMOD_RFC | MEDIUMSTSMOD_FD);
+ }
+ if (NicDevice->LinkSpeed1000Mbps) {
+ MediumStatus |= MEDIUMSTSMOD_GM;
+ MediumStatus |= MEDIUMSTSMOD_ENCK;
+ MediumStatus &= ~MEDIUMSTSMOD_PS;
+ } else {
+ MediumStatus &= ~MEDIUMSTSMOD_GM;
+ MediumStatus &= ~MEDIUMSTSMOD_ENCK;
+ if (NicDevice->LinkSpeed100Mbps) {
+ MediumStatus |= MEDIUMSTSMOD_PS;
+ } else {
+ MediumStatus &= ~MEDIUMSTSMOD_PS;
+ }
+ }
+ Status = Ax88179MacWrite (MEDIUMSTSMOD,
+ sizeof (MediumStatus),
+ NicDevice,
+ &MediumStatus);
+ if (!EFI_ERROR (Status)) {
+ NicDevice->CurMediumStatus = MediumStatus;
+ }
+ }
+ }
+
+ RxControl = RXCTL_SO | RXCTL_IPE;
+
+ //
+ // Enable multicast if requested
+ //
+ if ((RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
+ RxControl |= RXCTL_AM;
+ //
+ // Update the multicast hash table
+ //
+ Status = Ax88179MacWrite (MULCATFLTARRY,
+ 8,
+ NicDevice,
+ &NicDevice->MulticastHash);
+ }
+
+ //
+ // Enable all multicast if requested
+ //
+ if ((RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
+ RxControl |= RXCTL_AMALL;
+ }
+ //
+ // Enable broadcast if requested
+ //
+ if ((RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) {
+ RxControl |= RXCTL_AB;
+ }
+
+ //
+ // Enable promiscuous mode if requested
+ //
+ if ((RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {
+ RxControl |= RXCTL_PRO;
+ }
+
+ //
+ // Update the receiver control
+ //
+ if (NicDevice->CurRxControl != RxControl) {
+ Status = Ax88179MacWrite (RXCTL,
+ 0x02,
+ NicDevice,
+ &RxControl);
+ if (!EFI_ERROR (Status))
+ NicDevice->CurRxControl = RxControl;
+ }
+
+ //
+ // Return the operation status
+ //
+ return Status;
+}
+
+EFI_STATUS
+Ax88179ReloadSrom (
+ IN NIC_DEVICE *NicDevice
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_UNSUPPORTED;
+ return Status;
+
+}
+
+/**
+ Read an SROM location
+
+ This routine calls ::Ax88179UsbCommand to read data from the
+ SROM.
+
+ @param [in] NicDevice Pointer to the NIC_DEVICE structure
+ @param [in] Address SROM address
+ @param [out] Data Buffer to receive the data
+
+ @retval EFI_SUCCESS The read was successful
+ @retval other The read failed
+
+**/
+EFI_STATUS
+Ax88179SromRead (
+ IN NIC_DEVICE *NicDevice,
+ IN UINT32 Address,
+ OUT UINT16 *Data
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_UNSUPPORTED;
+ return Status;
+}
+
+EFI_STATUS
+Ax88179EnableSromWrite (
+ IN NIC_DEVICE *NicDevice
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_UNSUPPORTED;
+ return Status;
+}
+
+
+EFI_STATUS
+Ax88179DisableSromWrite (
+ IN NIC_DEVICE *NicDevice
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_UNSUPPORTED;
+ return Status;
+}
+
+/**
+ Write an SROM location
+
+ This routine calls ::Ax88179UsbCommand to write data from the
+ SROM.
+
+ @param [in] NicDevice Pointer to the NIC_DEVICE structure
+ @param [in] Address SROM address
+ @param [out] Data Buffer of data to write
+
+ @retval EFI_SUCCESS The write was successful
+ @retval other The write failed
+
+**/
+EFI_STATUS
+Ax88179SromWrite (
+ IN NIC_DEVICE *NicDevice,
+ IN UINT32 Address,
+ IN UINT16 *Data
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_UNSUPPORTED;
+ return Status;
+}
+
+/**
+ Send a command to the USB device.
+
+ @param [in] NicDevice Pointer to the NIC_DEVICE structure
+ @param [in] Request Pointer to the request structure
+ @param [in, out] Buffer Data buffer address
+
+ @retval EFI_SUCCESS The USB transfer was successful
+ @retval other The USB transfer failed
+
+**/
+EFI_STATUS
+Ax88179UsbCommand (
+ IN NIC_DEVICE *NicDevice,
+ IN USB_DEVICE_REQUEST *Request,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_USB_DATA_DIRECTION Direction;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_STATUS Status = EFI_TIMEOUT;
+ UINT32 CmdStatus = EFI_USB_NOERROR;
+ int i;
+ //
+ // Determine the transfer direction
+ //
+ Direction = EfiUsbNoData;
+ if (Request->Length != 0) {
+ Direction = ((Request->RequestType & USB_ENDPOINT_DIR_IN) != 0)
+ ? EfiUsbDataIn : EfiUsbDataOut;
+ }
+
+ //
+ // Issue the command
+ //
+ UsbIo = NicDevice->UsbIo;
+
+ for (i = 0 ; i < 3 && EFI_TIMEOUT == Status; i++) {
+ Status = UsbIo->UsbControlTransfer (UsbIo,
+ Request,
+ Direction,
+ USB_BUS_TIMEOUT,
+ Buffer,
+ Request->Length,
+ &CmdStatus);
+ }
+ //
+ // Determine the operation status
+ //
+ if (EFI_ERROR(Status) || EFI_ERROR(CmdStatus))
+ Status = EFI_DEVICE_ERROR;
+ //
+ // Return the operation status
+ //
+ return Status;
+}
+
+EFI_STATUS
+Ax88179MacRead (
+ IN UINT8 Offset,
+ IN UINT8 Length,
+ IN NIC_DEVICE *NicDevice,
+ IN OUT VOID *Data
+ )
+{
+
+ EFI_STATUS Status;
+ USB_DEVICE_REQUEST SetupMsg;
+
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE
+ | USB_ENDPOINT_DIR_IN;
+
+ SetupMsg.Request = ACCESS_MAC;
+ SetupMsg.Value = Offset;
+ SetupMsg.Index = Length;
+ SetupMsg.Length = SetupMsg.Index;
+
+ Status = Ax88179UsbCommand (NicDevice,
+ &SetupMsg,
+ Data);
+
+ return Status;
+
+}
+
+EFI_STATUS
+Ax88179MacWrite (
+ IN UINT8 Offset,
+ IN UINT8 Length,
+ IN NIC_DEVICE *NicDevice,
+ IN OUT VOID *Data
+ )
+{
+
+ EFI_STATUS Status;
+ USB_DEVICE_REQUEST SetupMsg;
+
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+
+ SetupMsg.Request = ACCESS_MAC;
+ SetupMsg.Value = Offset;
+ SetupMsg.Index = Length;
+ SetupMsg.Length = SetupMsg.Index;
+
+ Status = Ax88179UsbCommand (NicDevice,
+ &SetupMsg,
+ Data);
+
+ return Status;
+
+}
+
+EFI_STATUS
+Ax88179SetIInInterval (
+ IN NIC_DEVICE *NicDevice,
+ IN UINT8 Interval
+ )
+{
+
+ EFI_STATUS Status;
+ USB_DEVICE_REQUEST SetupMsg;
+
+ SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
+ | USB_TARGET_DEVICE;
+
+ SetupMsg.Request = 0x91;
+ SetupMsg.Value = Interval;
+ SetupMsg.Index = 0;
+ SetupMsg.Length = 0;
+
+ Status = Ax88179UsbCommand (NicDevice,
+ &SetupMsg,
+ NULL);
+
+ return Status;
+
+}
+
+EFI_STATUS
+Ax88179SetMedium (
+ IN NIC_DEVICE *NicDevice
+ )
+{
+ UINT16 MediumStatus;
+ EFI_STATUS Status;
+
+ MediumStatus = MEDIUMSTSMOD_RE | MEDIUMSTSMOD_ONE;
+ if (NicDevice->FullDuplex) {
+ MediumStatus |= MEDIUMSTSMOD_TFC | MEDIUMSTSMOD_RFC | MEDIUMSTSMOD_FD;
+ } else {
+ MediumStatus &= ~(MEDIUMSTSMOD_TFC | MEDIUMSTSMOD_RFC | MEDIUMSTSMOD_FD);
+ }
+ if (NicDevice->LinkSpeed1000Mbps) {
+ MediumStatus |= MEDIUMSTSMOD_GM;
+ MediumStatus &= ~MEDIUMSTSMOD_PS;
+ } else {
+ MediumStatus &= ~MEDIUMSTSMOD_GM;
+ if (NicDevice->LinkSpeed100Mbps) {
+ MediumStatus |= MEDIUMSTSMOD_PS;
+ } else {
+ MediumStatus &= ~MEDIUMSTSMOD_PS;
+ }
+ }
+ Status = Ax88179MacWrite (MEDIUMSTSMOD,
+ sizeof (MediumStatus),
+ NicDevice,
+ &MediumStatus);
+ if (!EFI_ERROR (Status)) {
+ NicDevice->CurMediumStatus = MediumStatus;
+ }
+
+ return Status;
+}
+
+
+BOOLEAN
+Ax88179GetLinkStatus (
+ IN NIC_DEVICE *NicDevice
+)
+{
+ UINT32 CmdStatus;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ UINT64 IntData = 0;
+ UINTN IntDataLeng = 8;
+ EFI_STATUS Status;
+
+ //
+ // Issue the command
+ //
+ UsbIo = NicDevice->UsbIo;
+ Status = UsbIo->UsbSyncInterruptTransfer(UsbIo,
+ USB_ENDPOINT_DIR_IN | INTERRUPT_ENDPOINT,
+ &IntData,
+ &IntDataLeng,
+ USB_BUS_TIMEOUT,
+ &CmdStatus);
+
+ if (EFI_ERROR(Status) || EFI_ERROR(CmdStatus) || 0 == IntDataLeng)
+ return FALSE;
+
+ return (IntData & 0x10000)? TRUE : FALSE;
+
+}
+
+EFI_STATUS
+Ax88179BulkIn(
+ IN NIC_DEVICE *NicDevice
+)
+{
+ int i;
+ UINT16 Val;
+ UINTN LengthInBytes = 0;
+ UINTN TmpLen = AX88179_MAX_BULKIN_SIZE;
+ UINTN CURBufSize = AX88179_MAX_BULKIN_SIZE;
+ UINTN PREBufSize = 0;
+ EFI_STATUS Status = EFI_NOT_READY;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ UINT32 TransferStatus;
+
+ NicDevice->SkipRXCnt = 0;
+
+ UsbIo = NicDevice->UsbIo;
+ for (i = 0 ; i < (AX88179_MAX_BULKIN_SIZE / 512) && UsbIo != NULL; i++) {
+ VOID* TmpAddr = 0;
+
+ if (NicDevice->SetZeroLen) {
+ Val = PHYPWRRSTCTL_IPRL | PHYPWRRSTCTL_BZ;
+ Status = Ax88179MacWrite (PHYPWRRSTCTL,
+ sizeof (Val),
+ NicDevice,
+ &Val);
+ if (EFI_ERROR(Status)) {
+ LengthInBytes = 0;
+ Status = EFI_NOT_READY;
+ goto no_pkt;
+ }
+ NicDevice->SetZeroLen = FALSE;
+ }
+ TmpAddr = (VOID*) &NicDevice->BulkInbuf[LengthInBytes];
+
+ Status = EFI_NOT_READY;
+ Status = UsbIo->UsbBulkTransfer (UsbIo,
+ USB_ENDPOINT_DIR_IN | BULK_IN_ENDPOINT,
+ TmpAddr,
+ &TmpLen,
+ BULKIN_TIMEOUT,
+ &TransferStatus);
+
+ if ((!EFI_ERROR (Status)) && (!EFI_ERROR (TransferStatus)) && TmpLen != 0) {
+ LengthInBytes += TmpLen;
+ if ((TmpLen % NicDevice->UsbMaxPktSize) != 0) {
+ goto done;
+ }
+ CURBufSize = CURBufSize - TmpLen;
+ TmpLen = CURBufSize;
+ NicDevice->SetZeroLen = TRUE;
+ } else if ((!EFI_ERROR (Status)) &&
+ (!EFI_ERROR (TransferStatus)) &&
+ (TmpLen == 0) &&
+ LengthInBytes) {
+ if (PREBufSize == CURBufSize) {
+ goto done;
+ }
+ TmpLen = CURBufSize;
+ PREBufSize = CURBufSize;
+ NicDevice->SetZeroLen = TRUE;
+ } else if ((!EFI_ERROR (Status)) &&
+ (!EFI_ERROR (TransferStatus)) &&
+ (TmpLen == 0)) {
+ NicDevice->SetZeroLen = TRUE;
+ LengthInBytes = 0;
+ Status = EFI_NOT_READY;
+ goto done;
+ } else if (EFI_TIMEOUT == Status && EFI_USB_ERR_TIMEOUT == TransferStatus) {
+ NicDevice->SetZeroLen = TRUE;
+ LengthInBytes = 0;
+ Status = EFI_NOT_READY;
+ goto done;
+ } else {
+ NicDevice->SetZeroLen = TRUE;
+ LengthInBytes = 0;
+ Status = EFI_NOT_READY;
+ goto done;
+ }
+ }
+
+done:
+ if (LengthInBytes != 0) {
+ UINT16 tmplen = 0;
+ UINT16 TmpPktCnt = 0;
+
+ TmpPktCnt = *((UINT16 *) (NicDevice->BulkInbuf + LengthInBytes - 4));
+ tmplen = *((UINT16*) (NicDevice->BulkInbuf + LengthInBytes - 2));
+
+ if (((UINTN)(((TmpPktCnt * 4 + 4 + 7) & 0xfff8) + tmplen)) == LengthInBytes) {
+ NicDevice->PktCnt = TmpPktCnt;
+ NicDevice->CurPktHdrOff = NicDevice->BulkInbuf + tmplen;
+ NicDevice->CurPktOff = NicDevice->BulkInbuf;
+ *((UINT16 *) (NicDevice->BulkInbuf + LengthInBytes - 4)) = 0;
+ *((UINT16*) (NicDevice->BulkInbuf + LengthInBytes - 2)) = 0;
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_NOT_READY;
+ }
+ } else {
+ Status = EFI_NOT_READY;
+ }
+no_pkt:
+ return Status;
+}
diff --git a/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/ComponentName.c b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/ComponentName.c
new file mode 100644
index 000000000000..daf917ce5b7d
--- /dev/null
+++ b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/ComponentName.c
@@ -0,0 +1,223 @@
+/** @file
+ UEFI Component Name(2) protocol implementation.
+
+ Copyright (c) 2011, Intel Corporation. All rights reserved.
+ Copyright (c) 2020, ARM Limited. All rights reserved
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Ax88179.h"
+
+/**
+ EFI Component Name Protocol declaration
+**/
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gComponentName = {
+ GetDriverName,
+ GetControllerName,
+ "eng"
+};
+
+/**
+ EFI Component Name 2 Protocol declaration
+**/
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) GetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) GetControllerName,
+ "en"
+};
+
+
+/**
+ Driver name table declaration
+**/
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
+mDriverNameTable[] = {
+ {"eng;en", L"ASIX AX88179 Ethernet Driver 2.9.0"},
+ {NULL, NULL}
+};
+
+/**
+ Controller name table declaration
+**/
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
+mControllerNameTable[] = {
+ {"eng;en", L"AX88179 USB3.0 Gigabit Ethernet Controller"},
+ {NULL, NULL}
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param [in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param [in] Language A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 3066 or ISO 639-2 language code format.
+ @param [out] DriverName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+GetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ EFI_STATUS Status;
+
+
+ Status = LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gComponentName)
+ );
+
+ return Status;
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param [in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param [in] ControllerHandle The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+ @param [in] ChildHandle The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+ @param [in] Language A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 3066 or ISO 639-2 language code format.
+ @param [out] ControllerName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+
+
+
+EFI_STATUS
+EFIAPI
+GetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN OPTIONAL EFI_HANDLE ChildHandle,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIoProtocol;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check Controller's handle
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &UsbIoProtocol,
+ gDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (!EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ gDriverBinding.DriverBindingHandle,
+ ControllerHandle
+ );
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Status != EFI_ALREADY_STARTED) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mControllerNameTable,
+ ControllerName,
+ (BOOLEAN)(This == &gComponentName)
+ );
+
+ return Status;
+}
+
diff --git a/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/DriverBinding.c b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/DriverBinding.c
new file mode 100644
index 000000000000..7a287cfbfb5d
--- /dev/null
+++ b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/DriverBinding.c
@@ -0,0 +1,639 @@
+/** @file
+ Implement the driver binding protocol for Asix AX88179 Ethernet driver.
+
+ Copyright (c) 2011, Intel Corporation
+ Copyright (c) 2020, ARM Limited. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Ax88179.h"
+
+/**
+ Verify the controller type
+
+ @param [in] This Protocol instance pointer.
+ @param [in] Controller Handle of device to test.
+ @param [in] pRemainingDevicePath Not used.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval other This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+DriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_USB_DEVICE_DESCRIPTOR Device;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_STATUS Status;
+
+ //
+ // Connect to the USB stack
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &UsbIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (!EFI_ERROR (Status)) {
+
+ //
+ // Get the interface descriptor to check the USB class and find a transport
+ // protocol handler.
+ //
+ Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &Device);
+ if (EFI_ERROR(Status)) {
+ Status = EFI_UNSUPPORTED;
+ } else {
+ //
+ // Validate the adapter
+ //
+ if ((VENDOR_ID == Device.IdVendor) &&
+ (PRODUCT_ID == Device.IdProduct)) {
+ Status = EFI_SUCCESS;
+ } else if ((VENDOR_ID == Device.IdVendor) &&
+ (PRODUCT_ID_178A == Device.IdProduct)) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Done with the USB stack
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+
+ //
+ // Return the device supported status
+ //
+ return Status;
+}
+
+
+/**
+ Start this driver on Controller by opening UsbIo and DevicePath protocols.
+ Initialize PXE structures, create a copy of the Controller Device Path with the
+ NIC's MAC address apEnded to it, install the NetworkInterfaceIdentifier protocol
+ on the newly created Device Path.
+
+ @param [in] This Protocol instance pointer.
+ @param [in] Controller Handle of device to work with.
+ @param [in] pRemainingDevicePath Not used, always produce all possible children.
+
+ @retval EFI_SUCCESS This driver is added to Controller.
+ @retval other This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+DriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ NIC_DEVICE *NicDevice;
+ UINTN LengthInBytes;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath = NULL;
+ MAC_ADDR_DEVICE_PATH MacDeviceNode;
+
+ //
+ // Allocate the device structure
+ //
+ LengthInBytes = sizeof (*NicDevice);
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ LengthInBytes,
+ (VOID **) &NicDevice
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ERR;
+ }
+
+ //
+ // Set the structure signature
+ //
+ ZeroMem (NicDevice, LengthInBytes);
+ NicDevice->Signature = DEV_SIGNATURE;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &NicDevice->UsbIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ERR;
+ }
+
+ //
+ // Initialize the simple network protocol
+ //
+ Status = SN_Setup (NicDevice);
+
+ if (EFI_ERROR(Status)){
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ goto ERR;
+ }
+
+ //
+ // Set Device Path
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR(Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ goto ERR;
+ }
+
+ ZeroMem (&MacDeviceNode, sizeof (MAC_ADDR_DEVICE_PATH));
+ MacDeviceNode.Header.Type = MESSAGING_DEVICE_PATH;
+ MacDeviceNode.Header.SubType = MSG_MAC_ADDR_DP;
+
+ SetDevicePathNodeLength (&MacDeviceNode.Header, sizeof (MAC_ADDR_DEVICE_PATH));
+
+ CopyMem (&MacDeviceNode.MacAddress,
+ &NicDevice->SimpleNetworkData.CurrentAddress,
+ PXE_HWADDR_LEN_ETHER);
+
+ MacDeviceNode.IfType = NicDevice->SimpleNetworkData.IfType;
+
+ NicDevice->MyDevPath = AppendDevicePathNode (
+ ParentDevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &MacDeviceNode
+ );
+
+ NicDevice->Controller = NULL;
+
+ //
+ // Install both the simple network and device path protocols.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &NicDevice->Controller,
+ &gEfiCallerIdGuid,
+ NicDevice,
+ &gEfiSimpleNetworkProtocolGuid,
+ &NicDevice->SimpleNetwork,
+ &gEfiDevicePathProtocolGuid,
+ NicDevice->MyDevPath,
+ NULL
+ );
+
+ if (EFI_ERROR(Status)){
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller);
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ goto ERR;
+ }
+
+ //
+ // Open For Child Device
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &NicDevice->UsbIo,
+ This->DriverBindingHandle,
+ NicDevice->Controller,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+
+ if (EFI_ERROR(Status)){
+ gBS->UninstallMultipleProtocolInterfaces (
+ &NicDevice->Controller,
+ &gEfiCallerIdGuid,
+ NicDevice,
+ &gEfiSimpleNetworkProtocolGuid,
+ &NicDevice->SimpleNetwork,
+ &gEfiDevicePathProtocolGuid,
+ NicDevice->MyDevPath,
+ NULL
+ );
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller);
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ goto ERR;
+ }
+
+ return Status;
+
+
+ERR:
+
+ if (NicDevice->BulkInbuf != NULL) {
+ gBS->FreePool (NicDevice->BulkInbuf);
+ }
+
+ if (NicDevice->TxTest != NULL) {
+ gBS->FreePool (NicDevice->TxTest);
+ }
+
+ if (NicDevice->MyDevPath != NULL) {
+ gBS->FreePool (NicDevice->MyDevPath);
+ }
+
+ if (NicDevice != NULL) {
+ gBS->FreePool (NicDevice);
+ }
+
+ return Status;
+}
+
+/**
+ Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and
+ closing the DevicePath and PciIo protocols on Controller.
+
+ @param [in] This Protocol instance pointer.
+ @param [in] Controller Handle of device to stop driver on.
+ @param [in] NumberOfChildren How many children need to be stopped.
+ @param [in] pChildHandleBuffer Not used.
+
+ @retval EFI_SUCCESS This driver is removed Controller.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+ @retval other This driver was not removed from this device.
+
+**/
+EFI_STATUS
+EFIAPI
+DriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL * This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE * ChildHandleBuffer
+ )
+{
+ BOOLEAN AllChildrenStopped;
+ EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork;
+ EFI_STATUS Status = EFI_SUCCESS;
+ NIC_DEVICE *NicDevice;
+ UINTN Index;
+
+ //
+ // Complete all outstanding transactions to Controller.
+ // Don't allow any new transaction to Controller to be started.
+ //
+ if (NumberOfChildren == 0) {
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiSimpleNetworkProtocolGuid,
+ (VOID **) &SimpleNetwork,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR(Status)) {
+ //
+ // This is a 2nd type handle(multi-lun root), it needs to close devicepath
+ // and usbio protocol.
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return EFI_SUCCESS;
+ }
+
+ NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiCallerIdGuid,
+ NicDevice,
+ &gEfiSimpleNetworkProtocolGuid,
+ &NicDevice->SimpleNetwork,
+ &gEfiDevicePathProtocolGuid,
+ NicDevice->MyDevPath,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Close the bus driver
+ //
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return EFI_SUCCESS;
+ }
+
+ AllChildrenStopped = TRUE;
+
+ for (Index = 0; Index < NumberOfChildren; Index++) {
+ Status = gBS->OpenProtocol (
+ ChildHandleBuffer[Index],
+ &gEfiSimpleNetworkProtocolGuid,
+ (VOID **) &SimpleNetwork,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ AllChildrenStopped = FALSE;
+ continue;
+ }
+
+ NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index]
+ );
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ChildHandleBuffer[Index],
+ &gEfiCallerIdGuid,
+ NicDevice,
+ &gEfiSimpleNetworkProtocolGuid,
+ &NicDevice->SimpleNetwork,
+ &gEfiDevicePathProtocolGuid,
+ NicDevice->MyDevPath,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &NicDevice->UsbIo,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index],
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ } else {
+ if (NicDevice->BulkInbuf != NULL) {
+ gBS->FreePool (NicDevice->BulkInbuf);
+ }
+
+ if (NicDevice->TxTest != NULL) {
+ gBS->FreePool (NicDevice->TxTest);
+ }
+
+ if (NicDevice->MyDevPath != NULL) {
+ gBS->FreePool (NicDevice->MyDevPath);
+ }
+
+ if (NicDevice != NULL) {
+ gBS->FreePool (NicDevice);
+ }
+ }
+ }
+
+ if (!AllChildrenStopped) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Driver binding protocol declaration
+**/
+EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
+ DriverSupported,
+ DriverStart,
+ DriverStop,
+ 0xa,
+ NULL,
+ NULL
+};
+
+
+/**
+ Ax88179 driver unload routine.
+
+ @param [in] ImageHandle Handle for the image.
+
+ @retval EFI_SUCCESS Image may be unloaded
+
+**/
+EFI_STATUS
+EFIAPI
+DriverUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ UINTN BufferSize;
+ UINTN Index;
+ UINTN Max;
+ EFI_HANDLE *Handle;
+ EFI_STATUS Status;
+
+ //
+ // Determine which devices are using this driver
+ //
+ BufferSize = 0;
+ Handle = NULL;
+ Status = gBS->LocateHandle (
+ ByProtocol,
+ &gEfiCallerIdGuid,
+ NULL,
+ &BufferSize,
+ NULL);
+ if (EFI_BUFFER_TOO_SMALL == Status) {
+ for (; ;) {
+ //
+ // One or more block IO devices are present
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ BufferSize,
+ (VOID **) &Handle
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ //
+ // Locate the block IO devices
+ //
+ Status = gBS->LocateHandle (
+ ByProtocol,
+ &gEfiCallerIdGuid,
+ NULL,
+ &BufferSize,
+ Handle);
+ if (EFI_ERROR (Status)) {
+ //
+ // Error getting handles
+ //
+
+ break;
+ }
+
+ //
+ // Remove any use of the driver
+ //
+ Max = BufferSize / sizeof (Handle[0]);
+ for (Index = 0; Max > Index; Index++) {
+ Status = DriverStop (&gDriverBinding,
+ Handle[Index],
+ 0,
+ NULL);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+ break;
+ }
+ } else {
+ if (EFI_NOT_FOUND == Status) {
+ //
+ // No devices were found
+ //
+ Status = EFI_SUCCESS;
+ }
+ }
+
+ //
+ // Free the handle array
+ //
+ if (Handle != NULL) {
+ gBS->FreePool (Handle);
+ }
+
+ //
+ // Remove the protocols installed by the EntryPoint routine.
+ //
+ if (!EFI_ERROR (Status)) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ ImageHandle,
+ &gEfiDriverBindingProtocolGuid,
+ &gDriverBinding,
+ &gEfiComponentNameProtocolGuid,
+ &gComponentName,
+ &gEfiComponentName2ProtocolGuid,
+ &gComponentName2,
+ NULL
+ );
+ }
+
+ //
+ // Return the unload status
+ //
+ return Status;
+}
+
+
+/**
+Ax88179 driver entry point.
+
+ at param [in] ImageHandle Handle for the image.
+ at param [in] SystemTable Address of the system table.
+
+ at retval EFI_SUCCESS Image successfully loaded.
+
+**/
+EFI_STATUS
+EFIAPI
+EntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ EFI_STATUS Status;
+
+ //
+ // Enable unload support
+ //
+ Status = gBS->HandleProtocol (
+ gImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **)&LoadedImage
+ );
+ if (!EFI_ERROR (Status)) {
+ LoadedImage->Unload = DriverUnload;
+ }
+
+ //
+ // Add the driver to the list of drivers
+ //
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gDriverBinding,
+ ImageHandle,
+ &gComponentName,
+ &gComponentName2
+ );
+
+ return Status;
+}
diff --git a/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/SimpleNetwork.c b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/SimpleNetwork.c
new file mode 100644
index 000000000000..948b73031463
--- /dev/null
+++ b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/SimpleNetwork.c
@@ -0,0 +1,1548 @@
+/** @file
+ Provides the Simple Network functions.
+
+ Copyright (c) 2011, Intel Corporation
+ Copyright (c) 2020, ARM Limited. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Ax88179.h"
+
+/**
+ This function updates the filtering on the receiver.
+
+ This support routine calls ::Ax88179MacAddressSet to update
+ the MAC address. This routine then rebuilds the multicast
+ hash by calling ::Ax88179MulticastClear and ::Ax88179MulticastSet.
+ Finally this routine enables the receiver by calling
+ ::Ax88179RxControl.
+
+ @param [in] SimpleNetwork Simple network mode pointer
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+ReceiveFilterUpdate (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork
+ )
+{
+ EFI_SIMPLE_NETWORK_MODE *Mode;
+ NIC_DEVICE *NicDevice;
+ EFI_STATUS Status;
+ UINT32 Index;
+
+ //
+ // Set the MAC address
+ //
+ NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
+ Mode = SimpleNetwork->Mode;
+ //
+ // Clear the multicast hash table
+ //
+ Ax88179MulticastClear (NicDevice);
+
+ //
+ // Load the multicast hash table
+ //
+ if ((Mode->ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
+ for (Index = 0; Index < Mode->MCastFilterCount; Index++) {
+ //
+ // Enable the next multicast address
+ //
+ Ax88179MulticastSet (NicDevice,
+ &Mode->MCastFilter[Index].Addr[0]);
+ }
+ }
+
+ //
+ // Enable the receiver
+ //
+ Status = Ax88179RxControl (NicDevice, Mode->ReceiveFilterSetting);
+
+ return Status;
+}
+
+
+/**
+ This function updates the SNP driver status.
+
+ This function gets the current interrupt and recycled transmit
+ buffer status from the network interface. The interrupt status
+ and the media status are returned as a bit mask in InterruptStatus.
+ If InterruptStatus is NULL, the interrupt status will not be read.
+ Upon successful return of the media status, the MediaPresent field
+ of EFI_SIMPLE_NETWORK_MODE will be updated to reflect any change
+ of media status. If TxBuf is not NULL, a recycled transmit buffer
+ address will be retrived. If a recycled transmit buffer address
+ is returned in TxBuf, then the buffer has been successfully
+ transmitted, and the status for that buffer is cleared.
+
+ This function calls ::Ax88179Rx to update the media status and
+ queue any receive packets.
+
+ @param [in] SimpleNetwork Protocol instance pointer
+ @param [in] InterruptStatus A pointer to the bit mask of the current active interrupts.
+ If this is NULL, the interrupt status will not be read from
+ the device. If this is not NULL, the interrupt status will
+ be read from teh device. When the interrupt status is read,
+ it will also be cleared. Clearing the transmit interrupt
+ does not empty the recycled transmit buffer array.
+ @param [out] TxBuf Recycled transmit buffer address. The network interface will
+ not transmit if its internal recycled transmit buffer array is
+ full. Reading the transmit buffer does not clear the transmit
+ interrupt. If this is NULL, then the transmit buffer status
+ will not be read. If there are not transmit buffers to recycle
+ and TxBuf is not NULL, *TxBuf will be set to NULL.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+
+**/
+
+EFI_STATUS
+EFIAPI
+SN_GetStatus (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
+ OUT UINT32 *InterruptStatus,
+ OUT VOID **TxBuf
+ )
+{
+ EFI_SIMPLE_NETWORK_MODE *Mode;
+ NIC_DEVICE *NicDevice;
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_TPL TplPrevious;
+
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
+ //
+ // Verify the parameters
+ //
+ if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
+ //
+ // Return the transmit buffer
+ //
+ NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
+
+ if ((TxBuf != NULL) && (NicDevice->TxBuffer != NULL)) {
+ *TxBuf = NicDevice->TxBuffer;
+ NicDevice->TxBuffer = NULL;
+ }
+
+ Mode = SimpleNetwork->Mode;
+ if (EfiSimpleNetworkInitialized == Mode->State) {
+ if ((TxBuf == NULL) && (InterruptStatus == NULL)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+
+#if REPORTLINK
+#else
+ if (!NicDevice->LinkUp || !NicDevice->Complete) {
+#endif
+ Status = Ax88179NegotiateLinkComplete (NicDevice,
+ &NicDevice->PollCount,
+ &NicDevice->Complete,
+ &NicDevice->LinkUp,
+ &NicDevice->LinkSpeed100Mbps,
+ &NicDevice->LinkSpeed1000Mbps,
+ &NicDevice->FullDuplex);
+
+ if (EFI_ERROR(Status))
+ goto EXIT;
+#if REPORTLINK
+ if (NicDevice->LinkUp && NicDevice->Complete) {
+ Mode->MediaPresent = TRUE;
+ Status = Ax88179SetMedium (NicDevice);
+ } else {
+ Mode->MediaPresent = FALSE;
+ }
+#else
+ if (NicDevice->LinkUp && NicDevice->Complete) {
+ Mode->MediaPresent = TRUE;
+ Mode->MediaPresentSupported = FALSE;
+ Status = Ax88179SetMedium (NicDevice);
+
+ }
+ }
+#endif
+ } else {
+ if (EfiSimpleNetworkStarted == Mode->State) {
+ Status = EFI_DEVICE_ERROR;
+ } else {
+ Status = EFI_NOT_STARTED ;
+ }
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ if (InterruptStatus != NULL) {
+ *InterruptStatus = 0;
+ }
+
+EXIT:
+ gBS->RestoreTPL(TplPrevious) ;
+
+ return Status;
+}
+
+/**
+ This function performs read and write operations on the NVRAM device
+ attached to a network interface.
+
+ @param [in] SimpleNetwork Protocol instance pointer
+ @param [in] ReadWrite TRUE for read operations, FALSE for write operations.
+ @param [in] Offset Byte offset in the NVRAM device at which to start the
+ read or write operation. This must be a multiple of
+ NvRamAccessSize and less than NvRamSize.
+ @param [in] BufferSize The number of bytes to read or write from the NVRAM device.
+ This must also be a multiple of NvramAccessSize.
+ @param [in, out] Buffer A pointer to the data buffer.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_NvData (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
+ IN BOOLEAN ReadWrite,
+ IN UINTN Offset,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ EFI_TPL TplPrevious;
+ EFI_SIMPLE_NETWORK_MODE *Mode;
+ NIC_DEVICE *NicDevice;
+ UINTN Index;
+
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
+ if ((SimpleNetwork == NULL) || (SimpleNetwork->Mode == NULL)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+
+ NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
+ Mode = SimpleNetwork->Mode;
+
+ if (EfiSimpleNetworkInitialized != Mode->State) {
+ Status = EFI_NOT_STARTED;
+ goto EXIT;
+ }
+
+ if (Offset != 0) {
+ if (((Offset % Mode->NvRamAccessSize) != 0) || (Offset >= Mode->NvRamSize)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+ }
+ //
+ // Offset must be a multiple of NvRamAccessSize and less than NvRamSize.
+ //
+ if ((BufferSize % Mode->NvRamAccessSize) != 0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+
+ if (BufferSize + Offset > Mode->NvRamSize) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+
+ if (Buffer == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+
+ //
+ // ReadWrite: TRUE FOR READ FALSE FOR WRITE
+ //
+ if (ReadWrite) {
+ for (Index = 0; Index < BufferSize / 2; Index++) {
+ Status = Ax88179SromRead (NicDevice,
+ (UINT32)(Offset/2 + Index),
+ (((UINT16*)Buffer) + Index));
+ }
+ } else {
+ Status = Ax88179EnableSromWrite(NicDevice);
+ if (EFI_ERROR(Status))
+ goto EXIT;
+
+ for (Index = 0; Index < BufferSize / 2; Index++) {
+ Status = Ax88179SromWrite (NicDevice,
+ (UINT32)(Offset/2 + Index),
+ (((UINT16*)Buffer) + Index));
+ }
+
+ Status = Ax88179DisableSromWrite(NicDevice);
+
+ if (BufferSize == 272)
+ Status = Ax88179ReloadSrom(NicDevice);
+ }
+
+ //
+ // Return the operation status
+ //
+EXIT:
+ gBS->RestoreTPL (TplPrevious);
+ return Status;
+}
+
+/**
+ Resets the network adapter and allocates the transmit and receive buffers
+ required by the network interface; optionally, also requests allocation of
+ additional transmit and receive buffers. This routine must be called before
+ any other routine in the Simple Network protocol is called.
+
+ @param [in] SimpleNetwork Protocol instance pointer
+ @param [in] ExtraRxBufferSize Size in bytes to add to the receive buffer allocation
+ @param [in] ExtraTxBufferSize Size in bytes to add to the transmit buffer allocation
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_OUT_OF_RESOURCES There was not enough memory for the transmit and receive buffers
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Initialize (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL * SimpleNetwork,
+ IN UINTN ExtraRxBufferSize,
+ IN UINTN ExtraTxBufferSize
+ )
+{
+ EFI_SIMPLE_NETWORK_MODE *Mode;
+ EFI_STATUS Status;
+ UINT32 TmpState;
+ EFI_TPL TplPrevious;
+ NIC_DEVICE *NicDevice;
+
+ TplPrevious = gBS->RaiseTPL (TPL_CALLBACK);
+
+ //
+ // Verify the parameters
+ //
+ if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
+ //
+ // Determine if the interface is already started
+ //
+ Mode = SimpleNetwork->Mode;
+ if (EfiSimpleNetworkStarted == Mode->State) {
+ if ((0 == ExtraRxBufferSize) && (0 == ExtraTxBufferSize)) {
+ //
+ // Start the adapter
+ //
+ TmpState = Mode->State;
+ Mode->State = EfiSimpleNetworkInitialized;
+ Status = SN_Reset (SimpleNetwork, FALSE);
+ if (EFI_ERROR (Status)) {
+ //
+ // Update the network state
+ //
+ Mode->State = TmpState;
+ } else {
+ Mode->MediaPresentSupported = TRUE;
+ NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
+ Mode->MediaPresent = Ax88179GetLinkStatus (NicDevice);
+ }
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+ } else {
+ Status = EFI_NOT_STARTED;
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return the operation status
+ //
+ gBS->RestoreTPL (TplPrevious);
+ return Status;
+}
+
+
+/**
+ This function converts a multicast IP address to a multicast HW MAC address
+ for all packet transactions.
+
+ @param [in] SimpleNetwork Protocol instance pointer
+ @param [in] IPv6 Set to TRUE if the multicast IP address is IPv6 [RFC2460].
+ Set to FALSE if the multicast IP address is IPv4 [RFC 791].
+ @param [in] IP The multicast IP address that is to be converted to a
+ multicast HW MAC address.
+ @param [in] MAC The multicast HW MAC address that is to be generated from IP.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_MCastIPtoMAC (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
+ IN BOOLEAN IPv6,
+ IN EFI_IP_ADDRESS *IP,
+ IN EFI_MAC_ADDRESS *MAC
+ )
+{
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+ EFI_SIMPLE_NETWORK_MODE *Mode;
+
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
+ if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
+ //
+ // The interface must be running
+ //
+ Mode = SimpleNetwork->Mode;
+ if (EfiSimpleNetworkInitialized == Mode->State) {
+ if (IP == NULL || MAC == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+ if (IPv6) {
+ Status = EFI_UNSUPPORTED;
+ goto EXIT;
+ } else {
+ //
+ // check if the ip given is a mcast IP
+ //
+ if ((IP->v4.Addr[0] & 0xF0) != 0xE0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ } else {
+ MAC->Addr[0] = 0x01;
+ MAC->Addr[1] = 0x00;
+ MAC->Addr[2] = 0x5e;
+ MAC->Addr[3] = (UINT8) (IP->v4.Addr[1] & 0x7f);
+ MAC->Addr[4] = (UINT8) IP->v4.Addr[2];
+ MAC->Addr[5] = (UINT8) IP->v4.Addr[3];
+ Status = EFI_SUCCESS;
+ }
+ }
+ } else {
+ if (EfiSimpleNetworkStarted == Mode->State) {
+ Status = EFI_DEVICE_ERROR;
+ } else {
+ Status = EFI_NOT_STARTED ;
+ }
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+EXIT:
+ gBS->RestoreTPL(TplPrevious);
+ return Status;
+}
+
+/**
+ Attempt to receive a packet from the network adapter.
+
+ This function retrieves one packet from the receive queue of the network
+ interface. If there are no packets on the receive queue, then EFI_NOT_READY
+ will be returned. If there is a packet on the receive queue, and the size
+ of the packet is smaller than BufferSize, then the contents of the packet
+ will be placed in Buffer, and BufferSize will be udpated with the actual
+ size of the packet. In addition, if SrcAddr, DestAddr, and Protocol are
+ not NULL, then these values will be extracted from the media header and
+ returned. If BufferSize is smaller than the received packet, then the
+ size of the receive packet will be placed in BufferSize and
+ EFI_BUFFER_TOO_SMALL will be returned.
+
+ This routine calls ::Ax88179Rx to update the media status and
+ empty the network adapter of receive packets.
+
+ @param [in] SimpleNetwork Protocol instance pointer
+ @param [out] HeaderSize The size, in bytes, of the media header to be filled in by
+ the Transmit() function. If HeaderSize is non-zero, then
+ it must be equal to SimpleNetwork->Mode->MediaHeaderSize
+ and DestAddr and Protocol parameters must not be NULL.
+ @param [out] BufferSize The size, in bytes, of the entire packet (media header and
+ data) to be transmitted through the network interface.
+ @param [out] Buffer A pointer to the packet (media header followed by data) to
+ to be transmitted. This parameter can not be NULL. If
+ HeaderSize is zero, then the media header is Buffer must
+ already be filled in by the caller. If HeaderSize is nonzero,
+ then the media header will be filled in by the Transmit()
+ function.
+ @param [out] SrcAddr The source HW MAC address. If HeaderSize is zero, then
+ this parameter is ignored. If HeaderSize is nonzero and
+ SrcAddr is NULL, then SimpleNetwork->Mode->CurrentAddress
+ is used for the source HW MAC address.
+ @param [out] DestAddr The destination HW MAC address. If HeaderSize is zero, then
+ this parameter is ignored.
+ @param [out] Protocol The type of header to build. If HeaderSize is zero, then
+ this parameter is ignored.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_NOT_READY No packets have been received on the network interface.
+ @retval EFI_BUFFER_TOO_SMALL The packet is larger than BufferSize bytes.
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Receive (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
+ OUT UINTN *HeaderSize,
+ OUT UINTN *BufferSize,
+ OUT VOID *Buffer,
+ OUT EFI_MAC_ADDRESS *SrcAddr,
+ OUT EFI_MAC_ADDRESS *DestAddr,
+ OUT UINT16 *Protocol
+ )
+{
+ ETHERNET_HEADER *Header;
+ EFI_SIMPLE_NETWORK_MODE *Mode;
+ NIC_DEVICE *NicDevice;
+ EFI_STATUS Status;
+ UINT16 Type = 0;
+ UINT16 CurrentPktLen;
+ BOOLEAN Valid = TRUE;
+ EFI_TPL TplPrevious;
+
+ TplPrevious = gBS->RaiseTPL (TPL_CALLBACK);
+ //
+ // Verify the parameters
+ //
+ if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
+ //
+ // The interface must be running
+ //
+ Mode = SimpleNetwork->Mode;
+ if (EfiSimpleNetworkInitialized == Mode->State) {
+ if ((BufferSize == NULL) || (Buffer == NULL)) {
+ Status = EFI_INVALID_PARAMETER;
+ gBS->RestoreTPL (TplPrevious);
+ return Status;
+ }
+
+ //
+ // Update the link status
+ //
+ NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
+
+ if (NicDevice->LinkUp && NicDevice->Complete) {
+ if ((HeaderSize != NULL) && (*HeaderSize == 7720)) {
+ NicDevice->Grub_f = TRUE;
+ }
+
+ if ((NicDevice->Grub_f) && (*HeaderSize != 7720)) {
+ gBS->RestoreTPL (TplPrevious);
+ return EFI_NOT_READY;
+ }
+
+ //
+ // Attempt to do bulk in
+ //
+ if (NicDevice->PktCnt == 0) {
+ Status = Ax88179BulkIn(NicDevice);
+ if (EFI_ERROR(Status))
+ goto no_pkt;
+ }
+ CurrentPktLen = *((UINT16*) (NicDevice->CurPktHdrOff + 2));
+ if (CurrentPktLen & (RXHDR_DROP | RXHDR_CRCERR))
+ Valid = FALSE;
+ CurrentPktLen &= 0x1fff;
+ CurrentPktLen -= 2; /*EEEE*/
+
+ if (Valid && (60 <= CurrentPktLen) &&
+ ((CurrentPktLen - 14) <= MAX_ETHERNET_PKT_SIZE) &&
+ (*((UINT16*)NicDevice->CurPktOff)) == 0xEEEE) {
+ if (*BufferSize < (UINTN)CurrentPktLen) {
+ gBS->RestoreTPL (TplPrevious);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ *BufferSize = CurrentPktLen;
+ CopyMem (Buffer, NicDevice->CurPktOff + 2, CurrentPktLen);
+
+ Header = (ETHERNET_HEADER *) NicDevice->CurPktOff + 2;
+
+ if ((HeaderSize != NULL) && ((*HeaderSize != 7720))) {
+ *HeaderSize = sizeof (*Header);
+ }
+
+ if (DestAddr != NULL) {
+ CopyMem (DestAddr, &Header->DestAddr, PXE_HWADDR_LEN_ETHER);
+ }
+ if (SrcAddr != NULL) {
+ CopyMem (SrcAddr, &Header->SrcAddr, PXE_HWADDR_LEN_ETHER);
+ }
+ if (Protocol != NULL) {
+ Type = Header->Type;
+ Type = (UINT16)((Type >> 8) | (Type << 8));
+ *Protocol = Type;
+ }
+ NicDevice->PktCnt--;
+ NicDevice->CurPktHdrOff += 4;
+ NicDevice->CurPktOff += (CurrentPktLen + 2 + 7) & 0xfff8;
+ Status = EFI_SUCCESS;
+ } else {
+ NicDevice->PktCnt = 0;
+ Status = EFI_NOT_READY;
+ }
+ } else {
+ Status = EFI_NOT_READY;
+ }
+ } else {
+ if (EfiSimpleNetworkStarted == Mode->State) {
+ Status = EFI_DEVICE_ERROR;
+ } else {
+ Status = EFI_NOT_STARTED;
+ }
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return the operation status
+ //
+no_pkt:
+ gBS->RestoreTPL (TplPrevious);
+ return Status;
+}
+
+/**
+ This function is used to enable and disable the hardware and software receive
+ filters for the underlying network device.
+
+ The receive filter change is broken down into three steps:
+
+ 1. The filter mask bits that are set (ON) in the Enable parameter
+ are added to the current receive filter settings.
+
+ 2. The filter mask bits that are set (ON) in the Disable parameter
+ are subtracted from the updated receive filter settins.
+
+ 3. If the resulting filter settigns is not supported by the hardware
+ a more liberal setting is selected.
+
+ If the same bits are set in the Enable and Disable parameters, then the bits
+ in the Disable parameter takes precedence.
+
+ If the ResetMCastFilter parameter is TRUE, then the multicast address list
+ filter is disabled (irregardless of what other multicast bits are set in
+ the enable and Disable parameters). The SNP->Mode->MCastFilterCount field
+ is set to zero. The SNP->Mode->MCastFilter contents are undefined.
+
+ After enableing or disabling receive filter settings, software should
+ verify the new settings by checking the SNP->Mode->ReceeiveFilterSettings,
+ SNP->Mode->MCastFilterCount and SNP->Mode->MCastFilter fields.
+
+ Note: Some network drivers and/or devices will automatically promote
+ receive filter settings if the requested setting can not be honored.
+ For example, if a request for four multicast addresses is made and
+ the underlying hardware only supports two multicast addresses the
+ driver might set the promiscuous or promiscuous multicast receive filters
+ instead. The receiving software is responsible for discarding any extra
+ packets that get through the hardware receive filters.
+
+ If ResetMCastFilter is TRUE, then the multicast receive filter list
+ on the network interface will be reset to the default multicast receive
+ filter list. If ResetMCastFilter is FALSE, and this network interface
+ allows the multicast receive filter list to be modified, then the
+ MCastFilterCnt and MCastFilter are used to update the current multicast
+ receive filter list. The modified receive filter list settings can be
+ found in the MCastFilter field of EFI_SIMPLE_NETWORK_MODE.
+
+ This routine calls ::ReceiveFilterUpdate to update the receive
+ state in the network adapter.
+
+ @param [in] SimpleNetwork Protocol instance pointer
+ @param [in] Enable A bit mask of receive filters to enable on the network interface.
+ @param [in] Disable A bit mask of receive filters to disable on the network interface.
+ For backward compatibility with EFI 1.1 platforms, the
+ EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit must be set
+ when the ResetMCastFilter parameter is TRUE.
+ @param [in] ResetMCastFilter Set to TRUE to reset the contents of the multicast receive
+ filters on the network interface to their default values.
+ @param [in] MCastFilterCnt Number of multicast HW MAC address in the new MCastFilter list.
+ This value must be less than or equal to the MaxMCastFilterCnt
+ field of EFI_SIMPLE_NETWORK_MODE. This field is optional if
+ ResetMCastFilter is TRUE.
+ @param [in] MCastFilter A pointer to a list of new multicast receive filter HW MAC
+ addresses. This list will replace any existing multicast
+ HW MAC address list. This field is optional if ResetMCastFilter
+ is TRUE.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_ReceiveFilters (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
+ IN UINT32 Enable,
+ IN UINT32 Disable,
+ IN BOOLEAN ResetMCastFilter,
+ IN UINTN MCastFilterCnt,
+ IN EFI_MAC_ADDRESS *MCastFilter
+ )
+{
+ EFI_SIMPLE_NETWORK_MODE *Mode;
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_TPL TplPrevious;
+ UINTN Index;
+ UINT8 Temp;
+
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
+ Mode = SimpleNetwork->Mode;
+
+ if (SimpleNetwork == NULL) {
+ gBS->RestoreTPL(TplPrevious);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (Mode->State) {
+ case EfiSimpleNetworkInitialized:
+ break;
+
+ case EfiSimpleNetworkStopped:
+ Status = EFI_NOT_STARTED;
+ gBS->RestoreTPL(TplPrevious);
+ return Status;
+
+ default:
+ Status = EFI_DEVICE_ERROR;
+ gBS->RestoreTPL(TplPrevious);
+ return Status;
+ }
+
+ //
+ // check if we are asked to enable or disable something that the SNP
+ // does not even support!
+ //
+ if (((Enable &~Mode->ReceiveFilterMask) != 0) ||
+ ((Disable &~Mode->ReceiveFilterMask) != 0)) {
+ Status = EFI_INVALID_PARAMETER;
+ gBS->RestoreTPL(TplPrevious);
+ return Status;
+ }
+
+ if (ResetMCastFilter) {
+ Disable |= (EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST & Mode->ReceiveFilterMask);
+ MCastFilterCnt = 0;
+ Mode->MCastFilterCount = 0;
+ if ((0 == (Mode->ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST)) &&
+ Enable == 0 && Disable == 2) {
+ gBS->RestoreTPL(TplPrevious);
+ return EFI_SUCCESS;
+ }
+ } else {
+ if (MCastFilterCnt != 0) {
+ EFI_MAC_ADDRESS * MulticastAddress;
+ MulticastAddress = MCastFilter;
+
+ if ((MCastFilterCnt > Mode->MaxMCastFilterCount) ||
+ (MCastFilter == NULL)) {
+ Status = EFI_INVALID_PARAMETER;
+ gBS->RestoreTPL(TplPrevious);
+ return Status;
+ }
+
+ for (Index = 0 ; Index < MCastFilterCnt ; Index++) {
+ Temp = MulticastAddress->Addr[0];
+ if ((Temp & 0x01) != 0x01) {
+ gBS->RestoreTPL(TplPrevious);
+ return EFI_INVALID_PARAMETER;
+ }
+ MulticastAddress++;
+ }
+
+ Mode->MCastFilterCount = (UINT32)MCastFilterCnt;
+ CopyMem (&Mode->MCastFilter[0],
+ MCastFilter,
+ MCastFilterCnt * sizeof (EFI_MAC_ADDRESS/**MCastFilter*/));
+ }
+ }
+
+ if (Enable == 0 && Disable == 0 && !ResetMCastFilter && MCastFilterCnt == 0) {
+ Status = EFI_SUCCESS;
+ gBS->RestoreTPL(TplPrevious);
+ return Status;
+ }
+
+ if ((Enable & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0 && MCastFilterCnt == 0) {
+ Status = EFI_INVALID_PARAMETER;
+ gBS->RestoreTPL(TplPrevious);
+ return Status;
+ }
+
+ Mode->ReceiveFilterSetting |= Enable;
+ Mode->ReceiveFilterSetting &= ~Disable;
+
+ Status = ReceiveFilterUpdate (SimpleNetwork);
+
+ gBS->RestoreTPL(TplPrevious);
+
+ return Status;
+}
+
+/**
+ Reset the network adapter.
+
+ Resets a network adapter and reinitializes it with the parameters that
+ were provided in the previous call to Initialize (). The transmit and
+ receive queues are cleared. Receive filters, the station address, the
+ statistics, and the multicast-IP-to-HW MAC addresses are not reset by
+ this call.
+
+ This routine calls ::Ax88179Reset to perform the adapter specific
+ reset operation. This routine also starts the link negotiation
+ by calling ::Ax88179NegotiateLinkStart.
+
+ @param [in] SimpleNetwork Protocol instance pointer
+ @param [in] ExtendedVerification Indicates that the driver may perform a more
+ exhaustive verification operation of the device
+ during reset.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Reset (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ EFI_SIMPLE_NETWORK_MODE *Mode;
+ NIC_DEVICE *NicDevice;
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
+ //
+ // Verify the parameters
+ //
+ if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
+ Mode = SimpleNetwork->Mode;
+ if (EfiSimpleNetworkInitialized == Mode->State) {
+ //
+ // Update the device state
+ //
+ NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
+
+ //
+ // Reset the device
+ //
+ if (!NicDevice->FirstRst) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = Ax88179Reset (NicDevice);
+ if (!EFI_ERROR (Status)) {
+ Status = ReceiveFilterUpdate (SimpleNetwork);
+ if (!EFI_ERROR (Status) && !NicDevice->LinkUp && NicDevice->FirstRst) {
+ Status = Ax88179NegotiateLinkStart (NicDevice);
+ NicDevice->FirstRst = FALSE;
+ }
+ }
+ }
+ } else {
+ Status = EFI_NOT_STARTED;
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ //
+ // Return the operation status
+ //
+ gBS->RestoreTPL(TplPrevious);
+ return Status;
+}
+
+/**
+ Initialize the simple network protocol.
+
+ This routine calls ::Ax88179MacAddressGet to obtain the
+ MAC address.
+
+ @param [in] NicDevice NIC_DEVICE_INSTANCE pointer
+
+ @retval EFI_SUCCESS Setup was successful
+
+**/
+EFI_STATUS
+SN_Setup (
+ IN NIC_DEVICE *NicDevice
+ )
+{
+ EFI_SIMPLE_NETWORK_MODE *Mode;
+ EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork;
+ EFI_STATUS Status;
+
+ //
+ // Initialize the simple network protocol
+ //
+ SimpleNetwork = &NicDevice->SimpleNetwork;
+ SimpleNetwork->Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
+ SimpleNetwork->Start = SN_Start;
+ SimpleNetwork->Stop = SN_Stop;
+ SimpleNetwork->Initialize = SN_Initialize;
+ SimpleNetwork->Reset = SN_Reset;
+ SimpleNetwork->Shutdown = SN_Shutdown;
+ SimpleNetwork->ReceiveFilters = SN_ReceiveFilters;
+ SimpleNetwork->StationAddress = SN_StationAddress;
+ SimpleNetwork->Statistics = SN_Statistics;
+ SimpleNetwork->MCastIpToMac = SN_MCastIPtoMAC;
+ SimpleNetwork->NvData = SN_NvData;
+ SimpleNetwork->GetStatus = SN_GetStatus;
+ SimpleNetwork->Transmit = SN_Transmit;
+ SimpleNetwork->Receive = SN_Receive;
+ SimpleNetwork->WaitForPacket = NULL;
+ Mode = &NicDevice->SimpleNetworkData;
+ SimpleNetwork->Mode = Mode;
+ Mode->State = EfiSimpleNetworkStopped;
+ Mode->HwAddressSize = PXE_HWADDR_LEN_ETHER;
+ Mode->MediaHeaderSize = sizeof (ETHERNET_HEADER);
+ Mode->MaxPacketSize = MAX_ETHERNET_PKT_SIZE;
+ Mode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
+ | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
+ | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
+ | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
+ | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
+ Mode->ReceiveFilterSetting = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
+ | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
+ Mode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT;
+ Mode->MCastFilterCount = 0;
+ Mode->NvRamSize = 512;
+ Mode->NvRamAccessSize = 2;
+ SetMem (&Mode->BroadcastAddress,
+ PXE_HWADDR_LEN_ETHER,
+ 0xff);
+ Mode->IfType = NET_IFTYPE_ETHERNET;
+ Mode->MacAddressChangeable = TRUE;
+ Mode->MultipleTxSupported = FALSE;
+ Mode->MediaPresentSupported = TRUE;
+ Mode->MediaPresent = FALSE;
+ //
+ // Read the MAC address
+ //
+ NicDevice->PhyId = PHY_ID_INTERNAL;
+ NicDevice->LinkSpeed100Mbps = FALSE;
+ NicDevice->LinkSpeed1000Mbps = TRUE;
+ NicDevice->FullDuplex = TRUE;
+ NicDevice->Complete = FALSE;
+ NicDevice->LinkUp = FALSE;
+ NicDevice->Grub_f = FALSE;
+ NicDevice->FirstRst = TRUE;
+ NicDevice->PktCnt = 0;
+ NicDevice->SkipRXCnt = 0;
+ NicDevice->UsbMaxPktSize = 512;
+ NicDevice->SetZeroLen = TRUE;
+
+ Status = Ax88179MacAddressGet (NicDevice,
+ &Mode->PermanentAddress.Addr[0]);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Use the hardware address as the current address
+ //
+ CopyMem (&Mode->CurrentAddress,
+ &Mode->PermanentAddress,
+ PXE_HWADDR_LEN_ETHER);
+
+ CopyMem (&NicDevice->MAC,
+ &Mode->PermanentAddress,
+ PXE_HWADDR_LEN_ETHER);
+
+ Status = gBS->AllocatePool (EfiBootServicesData,
+ AX88179_MAX_BULKIN_SIZE,
+ (VOID **) &NicDevice->BulkInbuf);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->AllocatePool (EfiBootServicesData,
+ sizeof (TX_PACKET),
+ (VOID **) &NicDevice->TxTest);
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (NicDevice->BulkInbuf);
+ }
+
+ //
+ // Return the setup status
+ //
+ return Status;
+}
+
+
+/**
+ This routine starts the network interface.
+
+ @param [in] SimpleNetwork Protocol instance pointer
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_ALREADY_STARTED The network interface was already started.
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Start (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork
+ )
+{
+ NIC_DEVICE *NicDevice;
+ EFI_SIMPLE_NETWORK_MODE *Mode;
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
+ //
+ // Verify the parameters
+ //
+ Status = EFI_INVALID_PARAMETER;
+ if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
+ Mode = SimpleNetwork->Mode;
+ if (EfiSimpleNetworkStopped == Mode->State) {
+ //
+ // Initialize the mode structure
+ // NVRAM access is not supported
+ //
+ ZeroMem (Mode, sizeof (*Mode));
+
+ Mode->State = EfiSimpleNetworkStarted;
+ Mode->HwAddressSize = PXE_HWADDR_LEN_ETHER;
+ Mode->MediaHeaderSize = sizeof (ETHERNET_HEADER);
+ Mode->MaxPacketSize = MAX_ETHERNET_PKT_SIZE;
+ Mode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
+ | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
+ | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
+ | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
+ | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
+ Mode->ReceiveFilterSetting = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
+ Mode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT;
+ Mode->MCastFilterCount = 0;
+ Mode->NvRamSize = 512;
+ Mode->NvRamAccessSize = 2;
+ NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
+ Status = Ax88179MacAddressGet (NicDevice, &Mode->PermanentAddress.Addr[0]);
+ CopyMem (&Mode->CurrentAddress,
+ &Mode->PermanentAddress,
+ sizeof (Mode->CurrentAddress));
+ SetMem(&Mode->BroadcastAddress, PXE_HWADDR_LEN_ETHER, 0xff);
+ Mode->IfType = NET_IFTYPE_ETHERNET;
+ Mode->MacAddressChangeable = TRUE;
+ Mode->MultipleTxSupported = FALSE;
+ Mode->MediaPresentSupported = TRUE;
+ Mode->MediaPresent = FALSE;
+
+ } else {
+ Status = EFI_ALREADY_STARTED;
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ gBS->RestoreTPL(TplPrevious);
+ return Status;
+}
+
+
+/**
+ Set the MAC address.
+
+ This function modifies or resets the current station address of a
+ network interface. If Reset is TRUE, then the current station address
+ is set ot the network interface's permanent address. If Reset if FALSE
+ then the current station address is changed to the address specified by
+ New.
+
+ This routine calls ::Ax88179MacAddressSet to update the MAC address
+ in the network adapter.
+
+ @param [in] SimpleNetwork Protocol instance pointer
+ @param [in] Reset Flag used to reset the station address to the
+ network interface's permanent address.
+ @param [in] New New station address to be used for the network
+ interface.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_StationAddress (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
+ IN BOOLEAN Reset,
+ IN EFI_MAC_ADDRESS *New
+ )
+{
+ NIC_DEVICE *NicDevice;
+ EFI_SIMPLE_NETWORK_MODE *Mode;
+ EFI_STATUS Status;
+
+ EFI_TPL TplPrevious;
+
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
+ //
+ // Verify the parameters
+ //
+ if ((SimpleNetwork != NULL) &&
+ (SimpleNetwork->Mode != NULL) &&
+ ((!Reset) || (Reset && (New != NULL)))) {
+ //
+ // Verify that the adapter is already started
+ //
+ NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
+ Mode = SimpleNetwork->Mode;
+ if (EfiSimpleNetworkInitialized == Mode->State) {
+ //
+ // Determine the adapter MAC address
+ //
+ if (Reset) {
+ //
+ // Use the permanent address
+ //
+ CopyMem (&Mode->CurrentAddress,
+ &Mode->PermanentAddress,
+ sizeof (Mode->CurrentAddress));
+ } else {
+ //
+ // Use the specified address
+ //
+ CopyMem (&Mode->CurrentAddress,
+ New,
+ sizeof (Mode->CurrentAddress));
+ }
+
+ //
+ // Update the address on the adapter
+ //
+ Status = Ax88179MacAddressSet (NicDevice, &Mode->CurrentAddress.Addr[0]);
+ } else {
+ if (EfiSimpleNetworkStarted == Mode->State) {
+ Status = EFI_DEVICE_ERROR; ;
+ } else {
+ Status = EFI_NOT_STARTED ;
+ }
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return the operation status
+ //
+ gBS->RestoreTPL(TplPrevious);
+ return Status;
+}
+
+
+/**
+ This function resets or collects the statistics on a network interface.
+ If the size of the statistics table specified by StatisticsSize is not
+ big enough for all of the statistics that are collected by the network
+ interface, then a partial buffer of statistics is returned in
+ StatisticsTable.
+
+ @param [in] SimpleNetwork Protocol instance pointer
+ @param [in] Reset Set to TRUE to reset the statistics for the network interface.
+ @param [in, out] StatisticsSize On input the size, in bytes, of StatisticsTable. On output
+ the size, in bytes, of the resulting table of statistics.
+ @param [out] StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that
+ conains the statistics.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_BUFFER_TOO_SMALL The StatisticsTable is NULL or the buffer is too small.
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+**/
+EFI_STATUS
+EFIAPI
+SN_Statistics (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
+ IN BOOLEAN Reset,
+ IN OUT UINTN *StatisticsSize,
+ OUT EFI_NETWORK_STATISTICS *StatisticsTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+ EFI_SIMPLE_NETWORK_MODE *Mode;
+
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
+ Mode = SimpleNetwork->Mode;
+
+ if (EfiSimpleNetworkInitialized == Mode->State) {
+ if ((StatisticsSize != NULL) && (*StatisticsSize == 0)) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto EXIT;
+ }
+
+ if(Reset) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_SUCCESS;
+ }
+ } else {
+ if (EfiSimpleNetworkStarted == Mode->State) {
+ Status = EFI_DEVICE_ERROR; ;
+ } else {
+ Status = EFI_NOT_STARTED ;
+ }
+ }
+
+ Status = EFI_UNSUPPORTED;
+EXIT:
+ gBS->RestoreTPL(TplPrevious);
+ return Status;
+}
+
+
+/**
+ This function stops a network interface. This call is only valid
+ if the network interface is in the started state.
+
+ @param [in] SimpleNetwork Protocol instance pointer
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Stop (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork
+ )
+{
+ EFI_SIMPLE_NETWORK_MODE *Mode;
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
+ //
+ // Verify the parameters
+ //
+ if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
+ //
+ // Determine if the interface is started
+ //
+ Mode = SimpleNetwork->Mode;
+
+ if (EfiSimpleNetworkStarted == Mode->State) {
+ Mode->State = EfiSimpleNetworkStopped;
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_NOT_STARTED;
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return the operation status
+ //
+ gBS->RestoreTPL(TplPrevious);
+ return Status;
+}
+
+
+/**
+ This function releases the memory buffers assigned in the Initialize() call.
+ Ending transmits and receives are lost, and interrupts are cleared and disabled.
+ After this call, only Initialize() and Stop() calls may be used.
+
+ @param [in] SimpleNetwork Protocol instance pointer
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+ @retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Shutdown (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork
+ )
+{
+ EFI_SIMPLE_NETWORK_MODE *Mode;
+ EFI_STATUS Status;
+ NIC_DEVICE *NicDevice;
+ EFI_TPL TplPrevious;
+
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
+ //
+ // Verify the parameters
+ //
+ if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
+ //
+ // Determine if the interface is already started
+ //
+ Mode = SimpleNetwork->Mode;
+ if (EfiSimpleNetworkInitialized == Mode->State) {
+ //
+ // Stop the adapter
+ //
+ NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
+
+ Status = Ax88179MacAddressGet (NicDevice, &Mode->PermanentAddress.Addr[0]);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Update the network state
+ //
+ Mode->State = EfiSimpleNetworkStarted;
+ } else if (EFI_DEVICE_ERROR == Status) {
+ Mode->State = EfiSimpleNetworkStopped;
+ }
+
+ } else {
+ Status = EFI_NOT_STARTED;
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return the operation status
+ //
+ gBS->RestoreTPL(TplPrevious);
+ return Status;
+}
+
+
+/**
+ Send a packet over the network.
+
+ This function places the packet specified by Header and Buffer on
+ the transmit queue. This function performs a non-blocking transmit
+ operation. When the transmit is complete, the buffer is returned
+ via the GetStatus() call.
+
+ This routine calls ::Ax88179Rx to empty the network adapter of
+ receive packets. The routine then passes the transmit packet
+ to the network adapter.
+
+ @param [in] SimpleNetwork Protocol instance pointer
+ @param [in] HeaderSize The size, in bytes, of the media header to be filled in by
+ the Transmit() function. If HeaderSize is non-zero, then
+ it must be equal to SimpleNetwork->Mode->MediaHeaderSize
+ and DestAddr and Protocol parameters must not be NULL.
+ @param [in] BufferSize The size, in bytes, of the entire packet (media header and
+ data) to be transmitted through the network interface.
+ @param [in] Buffer A pointer to the packet (media header followed by data) to
+ to be transmitted. This parameter can not be NULL. If
+ HeaderSize is zero, then the media header is Buffer must
+ already be filled in by the caller. If HeaderSize is nonzero,
+ then the media header will be filled in by the Transmit()
+ function.
+ @param [in] SrcAddr The source HW MAC address. If HeaderSize is zero, then
+ this parameter is ignored. If HeaderSize is nonzero and
+ SrcAddr is NULL, then SimpleNetwork->Mode->CurrentAddress
+ is used for the source HW MAC address.
+ @param [in] DestAddr The destination HW MAC address. If HeaderSize is zero, then
+ this parameter is ignored.
+ @param [in] Protocol The type of header to build. If HeaderSize is zero, then
+ this parameter is ignored.
+
+ @retval EFI_SUCCESS This operation was successful.
+ @retval EFI_NOT_STARTED The network interface was not started.
+ @retval EFI_NOT_READY The network interface is too busy to accept this transmit request.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.
+ @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did not point to a valid
+ EFI_SIMPLE_NETWORK_PROTOCOL structure.
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
+
+**/
+EFI_STATUS
+EFIAPI
+SN_Transmit (
+ IN EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork,
+ IN UINTN HeaderSize,
+ IN UINTN BufferSize,
+ IN VOID *Buffer,
+ IN EFI_MAC_ADDRESS *SrcAddr,
+ IN EFI_MAC_ADDRESS *DestAddr,
+ IN UINT16 *Protocol
+ )
+{
+ ETHERNET_HEADER *Header;
+ EFI_SIMPLE_NETWORK_MODE *Mode;
+ NIC_DEVICE *NicDevice;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_STATUS Status;
+ UINTN TransferLength;
+ UINT32 TransferStatus;
+ UINT16 Type = 0;
+ EFI_TPL TplPrevious;
+
+ TplPrevious = gBS->RaiseTPL(TPL_CALLBACK);
+ //
+ // Verify the parameters
+ //
+ if ((SimpleNetwork != NULL) && (SimpleNetwork->Mode != NULL)) {
+ //
+ // The interface must be running
+ //
+ Mode = SimpleNetwork->Mode;
+ if (EfiSimpleNetworkInitialized == Mode->State) {
+ //
+ // Update the link status
+ //
+ NicDevice = DEV_FROM_SIMPLE_NETWORK (SimpleNetwork);
+
+ if (NicDevice->LinkUp && NicDevice->Complete) {
+ if ((HeaderSize != 0) && (Mode->MediaHeaderSize != HeaderSize)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+ if (BufferSize < Mode->MediaHeaderSize) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+ if (Buffer == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+ if ((HeaderSize != 0) && (DestAddr == NULL)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+ if ((HeaderSize != 0) && (Protocol == NULL)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+ //
+ // Copy the packet into the USB buffer
+ //
+ // Buffer starting with 14 bytes 0
+ CopyMem (&NicDevice->TxTest->Data[0], Buffer, BufferSize);
+ NicDevice->TxTest->TxHdr1 = (UINT32) BufferSize;
+ NicDevice->TxTest->TxHdr2 = 0;
+ //
+ // Transmit the packet
+ //
+ Header = (ETHERNET_HEADER *) &NicDevice->TxTest->Data[0];
+ if (HeaderSize != 0) {
+ if (DestAddr != NULL) {
+ CopyMem (&Header->DestAddr, DestAddr, PXE_HWADDR_LEN_ETHER);
+ }
+ if (SrcAddr != NULL) {
+ CopyMem (&Header->SrcAddr, SrcAddr, PXE_HWADDR_LEN_ETHER);
+ } else {
+ CopyMem (&Header->SrcAddr, &Mode->CurrentAddress.Addr[0], PXE_HWADDR_LEN_ETHER);
+ }
+ if (Protocol != NULL) {
+ Type = *Protocol;
+ } else {
+ Type = (UINT16) BufferSize;
+ }
+ Type = (UINT16)((Type >> 8) | (Type << 8));
+ Header->Type = Type;
+ }
+
+ if (NicDevice->TxTest->TxHdr1 < MIN_ETHERNET_PKT_SIZE) {
+ NicDevice->TxTest->TxHdr1 = MIN_ETHERNET_PKT_SIZE;
+ ZeroMem (&NicDevice->TxTest->Data[BufferSize],
+ MIN_ETHERNET_PKT_SIZE - BufferSize);
+ }
+
+ TransferLength = sizeof (NicDevice->TxTest->TxHdr1)
+ + sizeof (NicDevice->TxTest->TxHdr2)
+ + NicDevice->TxTest->TxHdr1;
+ //
+ // Work around USB bus driver bug where a timeout set by receive
+ // succeeds but the timeout expires immediately after, causing the
+ // transmit operation to timeout.
+ //
+ UsbIo = NicDevice->UsbIo;
+ Status = UsbIo->UsbBulkTransfer (UsbIo,
+ BULK_OUT_ENDPOINT,
+ &NicDevice->TxTest->TxHdr1,
+ &TransferLength,
+ 0xfffffffe,
+ &TransferStatus);
+
+ if (!EFI_ERROR(Status) && !EFI_ERROR(Status)) {
+ NicDevice->TxBuffer = Buffer;
+ Status = EFI_SUCCESS;
+ } else if (EFI_TIMEOUT == Status && EFI_USB_ERR_TIMEOUT == TransferStatus) {
+ Status = EFI_NOT_READY;
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ }
+ } else {
+ //
+ // No packets available.
+ //
+ Status = EFI_NOT_READY;
+ }
+ } else {
+ if (EfiSimpleNetworkStarted == Mode->State) {
+ Status = EFI_DEVICE_ERROR;
+ } else {
+ Status = EFI_NOT_STARTED;
+ }
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+EXIT:
+ gBS->RestoreTPL (TplPrevious);
+ return Status;
+}
--
2.17.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#60864): https://edk2.groups.io/g/devel/message/60864
Mute This Topic: https://groups.io/mt/74751638/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-
More information about the edk2-devel-archive
mailing list