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