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.web10.13290.1589207901785820128 for ; Mon, 11 May 2020 07:38:22 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: ard.biesheuvel@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 954B6D6E; Mon, 11 May 2020 07:38:19 -0700 (PDT) Received: from [192.168.1.81] (unknown [10.37.8.255]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 569D53F68F; Mon, 11 May 2020 07:38:17 -0700 (PDT) Subject: Re: [edk2-platform][PATCH v1 3/4] Silicon/AsixPkg: Add ASIX Ax88179 driver To: Samer El-Haj-Mahmoud , devel@edk2.groups.io Cc: Ray Ni , Leif Lindholm , Michael D Kinney References: <20200510111530.26225-1-Samer.El-Haj-Mahmoud@arm.com> <20200510111530.26225-4-Samer.El-Haj-Mahmoud@arm.com> From: "Ard Biesheuvel" Message-ID: Date: Mon, 11 May 2020 16:38:14 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.7.0 MIME-Version: 1.0 In-Reply-To: <20200510111530.26225-4-Samer.El-Haj-Mahmoud@arm.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit On 5/10/20 1:15 PM, Samer El-Haj-Mahmoud wrote: > 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 > Cc: Michael D Kinney > > Signed-off-by: Samer El-Haj-Mahmoud Thanks for sending this. Comments inline. > --- > Silicon/ASIX/AsixPkg.dsc | 1 + > Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf | 66 + > Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88179/Ax88179.h | 1127 ++++++++++++++ > Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88179/Ax88179.c | 1026 +++++++++++++ > Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88179/ComponentName.c | 290 ++++ > Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88179/DriverBinding.c | 620 ++++++++ > Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88179/SimpleNetwork.c | 1585 ++++++++++++++++++++ > 7 files changed, 4715 insertions(+) > This is generally too big to review, but I don't see a better way tbh, given that this was contributed as is. Comments inline. Coding style remarks apply globally, not just where noted. > diff --git a/Silicon/ASIX/AsixPkg.dsc b/Silicon/ASIX/AsixPkg.dsc > index 0e4ffd0f1743..5e860d7b3c8f 100644 > --- a/Silicon/ASIX/AsixPkg.dsc > +++ b/Silicon/ASIX/AsixPkg.dsc > @@ -64,5 +64,6 @@ [PcdsFixedAtBuild] > # > ################################################################################ > [Components] > +Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf > Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772/Ax88772.inf > Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88772b/Ax88772b.inf > diff --git a/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf b/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf > new file mode 100644 > index 000000000000..a1883e9da1fd > --- /dev/null > +++ b/Silicon/ASIX/Drivers/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 This is dodgy. The USB stack is not runtime safe, so I don't see how this driver could do anything useful after the underlying infrastructure has been torn down. > + VERSION_STRING = 1.0 > + > + ENTRY_POINT = EntryPoint > + > +# > +# VALID_ARCHITECTURES = IA32 X64 EBC > +# Just drop this. No point in fixing it. > + > +[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 > + Put this in the right order please. > +[Protocols] > + gEfiDevicePathProtocolGuid ## BY_START > + gEfiSimpleNetworkProtocolGuid ## BY_START > + gEfiUsbIoProtocolGuid ## TO_START > + > +#[Guids] > + #gEfiEventExitBootServicesGuid ## PRODUCES ## Event > + #gEfiEventVirtualAddressChangeGuid ## PRODUCES ## Event > + #gEfiNicIp4ConfigVariableGuid > + This is runtime stuff. > +[Depex] > + gEfiBdsArchProtocolGuid AND > + gEfiCpuArchProtocolGuid AND > + gEfiMetronomeArchProtocolGuid AND > + gEfiMonotonicCounterArchProtocolGuid AND > + gEfiRealTimeClockArchProtocolGuid AND > + gEfiResetArchProtocolGuid AND > + gEfiRuntimeArchProtocolGuid AND > + gEfiSecurityArchProtocolGuid AND > + gEfiTimerArchProtocolGuid AND > + gEfiVariableWriteArchProtocolGuid AND > + gEfiVariableArchProtocolGuid AND > + gEfiWatchdogTimerArchProtocolGuid This depex should just be dropped once we change the type to UEFI_DRIVER > diff --git a/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88179/Ax88179.h b/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88179/Ax88179.h > new file mode 100644 > index 000000000000..82c9a3668d86 > --- /dev/null > +++ b/Silicon/ASIX/Drivers/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 > + Yuck. So no DEBUG() at all on non-VS? > +#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 No spaces inside () > +#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 this needs () > +#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 newline here, and please align the macros above > +/** > + 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*/ > + Who is 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 > + No 'p' prefixes for pointers. > + // > + // 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 No 'b' prefixes for booleans > + 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; wtf? > + BOOLEAN bFirstRst; > + BOOLEAN bSetZeroLen; > + UINT8 rxburst; CamelCase for variable names > + 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 Keep the * with the variable name, and align vertically > + ); > + > +/** > + 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/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88179/Ax88179.c b/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88179/Ax88179.c > new file mode 100644 > index 000000000000..7b2db9b74285 > --- /dev/null > +++ b/Silicon/ASIX/Drivers/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 ( Do we really need our own CRC implementation? > + 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)); No space inside [] or before [ Spaces around << and & > +} > + > +/** > + 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 )); No yoda style comparisons please. No redundant casts of boolean expressions to BOOLEAN > + 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: Leading uppercase for labels please > + 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)) Space before ( > + 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 )) Always use {} > + pNicDevice->CurMediumStatus = MediumStatus; indent > + > + 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/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88179/ComponentName.c b/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88179/ComponentName.c > new file mode 100644 > index 000000000000..bb7ea146be02 > --- /dev/null > +++ b/Silicon/ASIX/Drivers/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/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88179/DriverBinding.c b/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88179/DriverBinding.c > new file mode 100644 > index 000000000000..826a539e3f34 > --- /dev/null > +++ b/Silicon/ASIX/Drivers/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, Why is this runtime memory? > + 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++) { This is not a bus driver, so I don't think we need any of this stuff. > + 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/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88179/SimpleNetwork.c b/Silicon/ASIX/Drivers/Bus/Usb/UsbNetworking/Ax88179/SimpleNetwork.c > new file mode 100644 > index 000000000000..25986451dcbc > --- /dev/null > +++ b/Silicon/ASIX/Drivers/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. space after // > + // > + 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){ space between ) and { > + UINTN i; > + Please declare at function scope, and rename to something more idiomatic (Idx) > + 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; newline > + 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 > +*/ Drop this > + 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 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; Are these casts necessary? > + 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; NET_IFTYPE_ETHERNET? > + 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 )) { No 'success handling' please. This will return on error, so the remaining code can run unconditionally. > + // > + // 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); indentation > + } > + > + // > + // 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); > + > + > + redundant whitespace > + // > + // 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; drop this > +**/ > +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; > +} >