From nobody Mon Apr 29 00:16:54 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+58773+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+58773+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1588822650; cv=none; d=zohomail.com; s=zohoarc; b=Sp1Uc7AXKtKNAsyXy6BpZROhR/dtoh2Bz7wlQweG4vyGf3fP6tU3poefG0i+iscXVB0+3SaMn9F5+/Lo4E1elOzJSvNtA+5vQP9lWOMCaY7Inz9UAf9H1AFE7aRuuHWzHEf3VpGw1Y2h2CtpPADb3OHLt75pkhUwWABgeA0QF4U= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1588822650; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To; bh=BkxQ5Ab404YBka22xY6fPYHTZXUSN8IFD32Rzyk9xNk=; b=IjX0Bvfv5ztbXd+fwpz343mxS6reLMqlesSmL3qaGqyaaWaPqXtBcojYdxBaXl5HDSDOoeMsdkh3hruLFStT55mPL/6dI9lVk5J9NNYwcHUzQk6UXnd9nCuK2ihhB0yn/QoTc5GTrpYHeWwvh81+855ups7/GK87bebOAqOaN6U= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+58773+1787277+3901457@groups.io Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1588822650063100.97884331761009; Wed, 6 May 2020 20:37:30 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id AbT7YY1788612xmh4XnAiuz8; Wed, 06 May 2020 20:37:29 -0700 X-Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web12.4028.1588822647870091118 for ; Wed, 06 May 2020 20:37:28 -0700 X-Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 53B74101E; Wed, 6 May 2020 20:37:26 -0700 (PDT) X-Received: from localhost.localdomain (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id DB0C43F305; Wed, 6 May 2020 20:37:25 -0700 (PDT) From: "Samer El-Haj-Mahmoud" To: devel@edk2.groups.io Cc: Ray Ni , Leif Lindholm , Ard Biesheuvel Subject: [edk2-devel] [edk2-platform][PATCH v1 1/2] OptionRomPkg: UsbNetworking: ASIX Ax88179 driver Date: Wed, 6 May 2020 23:37:19 -0400 Message-Id: <20200507033720.31152-2-Samer.El-Haj-Mahmoud@arm.com> In-Reply-To: <20200507033720.31152-1-Samer.El-Haj-Mahmoud@arm.com> References: <20200507033720.31152-1-Samer.El-Haj-Mahmoud@arm.com> Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,samer.el-haj-mahmoud@arm.com X-Gm-Message-State: zaMjMZhfBkreRD8blZs6hjZsx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1588822649; bh=m9/ZgmItoLEogAMLbrwUg7XBDzqZL2BSHEqjTmHhF6s=; h=Cc:Date:From:Reply-To:Subject:To; b=EoBt5Q3phhhbd9UKIFDrUuDtThZM1kazoVffkc50Fsk7Lh2W5GAvYHAfu/bRfyncLXe p9Jur1ZOqC1r8f+ASzwQYe/vDia13FJumDzOmHeegPwWXUVJaFO7AdZvht4o9FTO86fzt kO82ZDs8ze+62X0Egi7S3F3iaW2WTb0QemI= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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=3DpItemdetail&PItemID=3D131;71;112 Source code contributed by ASIX. Cc: Ray Ni Cc: Leif Lindholm Cc: Ard Biesheuvel Signed-off-by: Samer El-Haj-Mahmoud --- Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf | 66 + Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.h | 1127 = ++++++++++++++ Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.c | 1026 = +++++++++++++ Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/ComponentName.c | 290 = ++++ Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/DriverBinding.c | 620 = ++++++++ Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/SimpleNetwork.c | 1585 = ++++++++++++++++++++ 6 files changed, 4714 insertions(+) diff --git a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf= b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf new file mode 100644 index 000000000000..a1883e9da1fd --- /dev/null +++ b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf @@ -0,0 +1,66 @@ +## @file +# Component description file for ASIX AX88772 USB/Ethernet driver. +# +# This module provides support for the ASIX AX88772 USB/Ethernet adapter. +# Copyright (c) 2011, Intel Corporation +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010018 + BASE_NAME =3D Ax88179 + FILE_GUID =3D 27E5D3B6-7839-47C2-8618-5D2190729BC7 + MODULE_TYPE =3D DXE_RUNTIME_DRIVER + VERSION_STRING =3D 1.0 + + ENTRY_POINT =3D EntryPoint + +# +# VALID_ARCHITECTURES =3D IA32 X64 EBC +# + +[Sources.common] + Ax88179.h + Ax88179.c + ComponentName.c + DriverBinding.c + SimpleNetwork.c + + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiLib + UefiBootServicesTableLib + BaseMemoryLib + DebugLib + UefiRuntimeLib + UefiDriverEntryPoint + +[Protocols] + gEfiDevicePathProtocolGuid ## BY_START + gEfiSimpleNetworkProtocolGuid ## BY_START + gEfiUsbIoProtocolGuid ## TO_START + +#[Guids] + #gEfiEventExitBootServicesGuid ## PRODUCES ## Event + #gEfiEventVirtualAddressChangeGuid ## PRODUCES ## Event + #gEfiNicIp4ConfigVariableGuid + +[Depex] + gEfiBdsArchProtocolGuid AND + gEfiCpuArchProtocolGuid AND + gEfiMetronomeArchProtocolGuid AND + gEfiMonotonicCounterArchProtocolGuid AND + gEfiRealTimeClockArchProtocolGuid AND + gEfiResetArchProtocolGuid AND + gEfiRuntimeArchProtocolGuid AND + gEfiSecurityArchProtocolGuid AND + gEfiTimerArchProtocolGuid AND + gEfiVariableWriteArchProtocolGuid AND + gEfiVariableArchProtocolGuid AND + gEfiWatchdogTimerArchProtocolGuid diff --git a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.h b= /Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.h new file mode 100644 index 000000000000..82c9a3668d86 --- /dev/null +++ b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.h @@ -0,0 +1,1127 @@ +/** @file + Definitions for ASIX AX88179 Ethernet adapter. + + Copyright (c) 2011, Intel Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _AX88179_H_ +#define _AX88179_H_ + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +#define PASS_SCT 0 +#define FORCE_100Mbps 0 +#define REPORTLINK 1 + + +//------------------------------------------------------------------------= ------ +// Macros +//------------------------------------------------------------------------= ------ + +//#if defined(_MSC_VER) /* Handle Microsoft VC++ compiler specif= ics. */ +#define DBG_ENTER() DEBUG (( 0xffffffff, "Entering " __FUNCTIO= N__ "\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 val= ue +#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 =3D=3D 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 decima= l value +//#define DBG_EXIT_HEX(Status) ///< Display routine exit with hex va= lue +//#define DBG_EXIT_STATUS(Status) ///< Display routine exit with status= value +//#define DBG_EXIT_TF(Status) ///< Display routine with TRUE/FALSE = value +//#endif // _MSC_VER + +#define USB_IS_IN_ENDPOINT(EndPointAddr) (((EndPointAddr) & BIT7) != =3D 0) ///< Return TRUE/FALSE for IN direction +#define USB_IS_OUT_ENDPOINT(EndPointAddr) (((EndPointAddr) & BIT7) =3D= =3D 0) ///< Return TRUE/FALSE for OUT direction +#define USB_IS_BULK_ENDPOINT(Attribute) (((Attribute) & (BIT0 | BIT1= )) =3D=3D USB_ENDPOINT_BULK) ///< Return TRUE/FALSE for BULK type +#define USB_IS_INTERRUPT_ENDPOINT(Attribute) (((Attribute) & (BIT0 | BIT1= )) =3D=3D 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 val= ues +#define DEBUG_SROM 0x00800000 ///< Display the SROM contents +#define DEBUG_TIMER 0x00400000 ///< Display the timer routine en= try/exit +#define DEBUG_TPL 0x00200000 ///< Display the timer routine en= try/exit + + +#define ETHERNET_HEADER_SIZE sizeof ( ETHERNET_HEADER ) ///< Size in by= tes of the Ethernet header +#define MIN_ETHERNET_PKT_SIZE 60 ///< Minimum packet size including Et= hernet 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 synchr= onization + + +#define AX88179_BULKIN_SIZE_INK 2 +#define AX88179_MAX_BULKIN_SIZE 1024 * AX88179_BULKIN_SIZE_INK +#define AX88179_MAX_PKT_SIZE 2048 + +#define HC_DEBUG 0 +#define ADD_MACPATHNOD 1 +#define BULKIN_TIMEOUT 3 //5000 +#define TX_RETRY 0 +#define AUTONEG_DELAY 1000000 +/** + Verify new TPL value + + This macro which is enabled when debug is enabled verifies that + the new TPL value is >=3D 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 =3D 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 <=3D tpl ); \ + } \ +} + +#else // MDEPKG_NDEBUG + +#define VERIFY_TPL(tpl) + +#endif // MDEPKG_NDEBUG + +//------------------------------------------------------------------------= ------ +// Hardware Definition +//------------------------------------------------------------------------= ------ + +#define DEV_SIGNATURE SIGNATURE_32 ('A','X','8','8') ///< Signature = of data structures in memory + +#define VENDOR_ID 0x0B95 ///< Vendor ID for Asix +#define PRODUCT_ID 0x1790 ///< Product ID for the AX88179 USB 10/= 100 Ethernet controller +#define PRODUCT_ID_178A 0x178A + +#define RESET_MSEC 1000 ///< Reset duration +#define PHY_RESET_MSEC 100 ///< PHY reset duration + +// +// RX Control register +// + + + +/*Freddy*/ +#define RXC_RH1M 0x0100 ///< Rx header 1 +#define RXC_RH2M 0x0200 ///< Rx header 2 +#define RXC_RH3M 0x0400 ///< Rx header 3 +/*Freddy*/ + +// +// Medium Status register +// + + + +// +// Software PHY Select register +// + +#define SPHY_PSEL 0x01 ///< Select internal PHY +#define SPHY_ASEL 0x02 ///< 1=3DAuto select, 0=3DManual 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 e= nable +#define SRR_PRL 0x08 ///< External PHY reset pin level +#define SRR_BZ 0x10 ///< Force Bulk to return zero length p= acket +#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: PH= Y, Index: Register, Data: Register value +#define CMD_PHY_REG_WRITE 0x08 ///< Write PHY register, Value: P= HY, 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: A= ddress, 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, Val= ue: 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: N= ew 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 v= alue +#define CMD_PHY_SELECT 0x22 ///< PHY select register, Value: = New value + +/*Freddy*/ +#define CMD_RXQTC 0x2a ///< RX Queue Cascade Threshold C= ontrol 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 expa= nsion register + + + +// BSMR - Register 1 + + + +// ANAR and ANLPAR Registers 4, 5 + +#define RXHDR_DROP 0x8000 +//#define RXHDR_MIIERR 0x4000 +#define RXHDR_CRCERR 0x2000 + + +//------------------------------------------------------------------------= ------ +// Data Types +//------------------------------------------------------------------------= ------ + +/** + Ethernet header layout + + IEEE 802.3-2002 Part 3 specification, section 3.1.1. +**/ +#pragma pack(1) +typedef struct { + UINT8 dest_addr[PXE_HWADDR_LEN_ETHER]; ///< Destination LAN address + UINT8 src_addr[PXE_HWADDR_LEN_ETHER]; ///< Source LAN address + UINT16 type; ///< Protocol or length +} ETHERNET_HEADER; +#pragma pack() + +/** + Receive and Transmit packet structure +**/ + + + + +#pragma pack(1) +typedef struct _TX_PACKET { +// struct _TX_PACKET * pNext; ///< Next receive packet + UINT32 TxHdr1; + UINT32 TxHdr2; + UINT8 Data[ AX88179_MAX_PKT_SIZE ]; ///< Received packet data +} TX_PACKET; +#pragma pack() + +#pragma pack(1) +typedef struct _RX_PACKET { + struct _RX_PACKET * pNext; + UINT16 Length; + UINT16 EEEE; + UINT8 Data[ AX88179_MAX_PKT_SIZE ]; +} RX_PACKET; +#pragma pack() + + + + +/** + AX88179 control structure + + The driver uses this structure to manage the Asix AX88179 10/100 + Ethernet controller. +**/ +typedef struct { + UINTN Signature; ///< Structure identification + + // + // USB data + // + EFI_HANDLE Controller; ///< Controller handle + EFI_USB_IO_PROTOCOL * pUsbIo; ///< USB driver interface + + // + // Simple network protocol data + // + EFI_SIMPLE_NETWORK_PROTOCOL SimpleNetwork; ///< Driver's network stack= interface + EFI_SIMPLE_NETWORK_MODE SimpleNetworkData; ///< Data for simple network + + // + // Ethernet controller data + // + BOOLEAN bInitialized; ///< Controller initialized + UINT16 PhyId; ///< PHY ID + + // + // Link state + // + BOOLEAN b100Mbps; ///< Current link speed, FALSE =3D 10 Mbps + BOOLEAN b1000Mbps; ///< Current link speed, FALSE =3D 100/10 bps + BOOLEAN bComplete; ///< Current state of auto-negotiation + BOOLEAN bFullDuplex; ///< Current duplex + BOOLEAN bLinkUp; ///< Current link state + BOOLEAN bLinkIdle; ///< TRUE =3D No received traffic + EFI_EVENT Timer; ///< Timer to monitor link state and receive = packets + UINTN PollCount; ///< Number of times the autonegotiation stat= us was polled + UINTN SkipRXCnt; + + UINT8 *pBulkInbuf; + UINT16 PktCnt; + UINT8 * pCurPktHdrOff; + UINT8 *pCurPktOff; + + TX_PACKET * pTxTest; + + INT8 MulticastHash[8]; + EFI_MAC_ADDRESS MAC; + + UINT16 CurMediumStatus; + UINT16 CurRxControl; + VOID * pTxBuffer; + + EFI_DEVICE_PATH_PROTOCOL *MyDevPath; + BOOLEAN Grub_f; + BOOLEAN bFirstRst; + BOOLEAN bSetZeroLen; + UINT8 rxburst; + UINTN usbMaxPktSize; + +} NIC_DEVICE; + +#define DEV_FROM_SIMPLE_NETWORK(a) CR (a, NIC_DEVICE, SimpleNetwork, DEV_= SIGNATURE) ///< Locate NIC_DEVICE from Simple Network Protocol + +//------------------------------------------------------------------------= ------ +// Simple Network Protocol +//------------------------------------------------------------------------= ------ + +/** + Reset the network adapter. + + Resets a network adapter and reinitializes it with the parameters that + were provided in the previous call to Initialize (). The transmit and + receive queues are cleared. Receive filters, the station address, the + statistics, and the multicast-IP-to-HW MAC addresses are not reset by + this call. + + This routine calls ::Ax88179Reset to perform the adapter specific + reset operation. This routine also starts the link negotiation + by calling ::Ax88179NegotiateLinkStart. + + @param [in] pSimpleNetwork Protocol instance pointer + @param [in] bExtendedVerification Indicates that the driver may perform= a more + exhaustive verification operation of the d= evice + 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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +EFI_STATUS +EFIAPI +SN_Reset ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + IN BOOLEAN bExtendedVerification + ); + +/** + Initialize the simple network protocol. + + This routine calls ::Ax88179MacAddressGet to obtain the + MAC address. + + @param [in] pNicDevice NIC_DEVICE_INSTANCE pointer + + @retval EFI_SUCCESS Setup was successful + +**/ +EFI_STATUS +SN_Setup ( + IN NIC_DEVICE * pNicDevice + ); + +/** + This routine starts the network interface. + + @param [in] pSimpleNetwork Protocol instance pointer + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_ALREADY_STARTED The network interface was already started. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +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 net= work + 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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +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 th= e network interface. + @param [in, out] pStatisticsSize On input the size, in bytes, of Statis= ticsTable. On output + the size, in bytes, of the resulting table= of statistics. + @param [out] pStatisticsTable A pointer to the EFI_NETWORK_STATISTICS st= ructure 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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +EFI_STATUS +EFIAPI +SN_Stop ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork + ); + +/** + This function releases the memory buffers assigned in the Initialize() c= all. + 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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +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->M= ediaHeaderSize + 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 networ= k interface. + @param [in] pBuffer A pointer to the packet (media header foll= owed 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 He= aderSize 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 Header= Size is zero, then + this parameter is ignored. + @param [in] pProtocol The type of header to build. If HeaderSiz= e 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 accep= t this transmit request. + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk 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 th= e 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 stat= us. + @param [out] pbLinkUp Address of boolean to receive link status, = TRUE=3Dup. + @param [out] pbHiSpeed Address of boolean to receive link speed, T= RUE=3D100Mbps. + @param [out] pbFullDuplex Address of boolean to receive link duplex, = TRUE=3Dfull. + + @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 regi= ster 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 =3D 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 o= f 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 speci= fied + 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_PROTO= COL 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 calle= r 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 for= mat. + @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 specifie= d by + This and the language specified by Languag= e 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 supp= ort + 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 control= ler + that is being managed by a driver. + + This function retrieves the user readable name of the controller specifi= ed 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 specif= ied by + Language, then a pointer to the controller name is returned in Controlle= rName, + and EFI_SUCCESS is returned. If the driver specified by This is not cur= rently + 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 retu= rned. + + @param [in] pThis A pointer to the EFI_COMPONENT_NAME2_PROTO= COL 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 retr= ieve + the name of. This is an optional paramete= r that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus d= rivers + 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 calle= r 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 specifie= d 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 a= nd + ChildHandle in the language specified by + Language from the point of view of the dri= ver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable n= ame 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 va= lid + 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 curren= tly + managing the controller specified by + ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + 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 addres= s hash table + #define RXCTL_AP 0x0020 ///< Accept physical address from Mul= ticast 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, Da= ta: 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=3D100, 0=3D10 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 =3D Reset the PH= Y, bit clears after reset + #define BMCR_LOOPBACK 0x4000 ///< 1 =3D Loopback ena= bled + #define BMCR_AUTONEGOTIATION_ENABLE 0x1000 ///< 1 =3D Enable auton= egotiation + #define BMCR_POWER_DOWN 0x0800 ///< 1 =3D Power down + #define BMCR_ISOLATE 0x0400 ///< 0 =3D Isolate PHY + #define BMCR_RESTART_AUTONEGOTIATION 0x0200 ///< 1 =3D Restart auto= negotiation + #define BMCR_FULL_DUPLEX 0x0100 ///< Full duplex operat= ion + #define BMCR_COLLISION_TEST 0x0080 ///< 1 =3D Collision te= st enabled + #define BMCR_1000MBPS 0x40 ///< Forced mode in 1000M= bps + #define BMCR_100MBPS 0x2000 ///< Forced mode in 1= 0Mbps + +#define PHY_BMSR 1 ///< Status register + #define BMSR_100BASET4 0x8000 ///< 1 =3D 100BASE-T4 m= ode + #define BMSR_100BASETX_FDX 0x4000 ///< 1 =3D 100BASE-TX f= ull duplex + #define BMSR_100BASETX_HDX 0x2000 ///< 1 =3D 100BASE-TX h= alf duplex + #define BMSR_10BASET_FDX 0x1000 ///< 1 =3D 10BASE-T ful= l duplex + #define BMSR_10BASET_HDX 0x0800 ///< 1 =3D 10BASE-T hal= f duplex + #define BMSR_MF 0x0040 ///< 1 =3D PHY accepts = frames with preamble suppressed + #define BMSR_AUTONEG_CMPLT 0x0020 ///< 1 =3D Autonegotiat= ion complete + #define BMSR_RF 0x0010 ///< 1 =3D Remote fault + #define BMSR_AUTONEG 0x0008 ///< 1 =3D Able to perf= orm autonegotiation + #define BMSR_LINKST 0x0004 ///< 1 =3D Link up + #define BMSR_JABBER_DETECT 0x0002 ///< 1 =3D jabber condi= tion detected + #define BMSR_EXTENDED_CAPABILITY 0x0001 ///< 1 =3D Extended reg= ister capable + +#define PHY_ANAR 4 ///< Autonegotiation adve= rtisement register + #define AN_NP 0x8000 ///< 1 =3D Next page av= ailable + #define AN_RF 0x2000 ///< 1 =3D Remote fault= indicated by link partner + #define AN_FCS 0x0400 ///< 1 =3D Flow control= ability + #define AN_T4 0x0200 ///< 1 =3D 100BASE-T4 s= upport + #define AN_TX_FDX 0x0100 ///< 1 =3D 100BASE-TX F= ull duplex + #define AN_TX_HDX 0x0080 ///< 1 =3D 100BASE-TX s= upport + #define AN_10_FDX 0x0040 ///< 1 =3D 10BASE-T Ful= l duplex + #define AN_10_HDX 0x0020 ///< 1 =3D 10BASE-T sup= port + #define AN_CSMA_CD 0x0001 ///< 1 =3D IEEE 802.3 C= SMA/CD support + +#define PHY_ANLPAR 5 ///< Autonegotiation link= parter ability register + +#define PHY_PHYSR 0x11 + #define PHYSR_SPEED_MASK 0xC000 + #define PHYSR_1000 0x8000 + #define PHYSR_100 0x4000 + #define PHYSR_FULLDUP 0x2000 + #define PHYSR_LINK 0x400 + +EFI_STATUS +Ax88179PhyRead ( + IN NIC_DEVICE * pNicDevice, + IN UINT8 RegisterAddress, + IN OUT UINT16 * pPhyData + ); + +EFI_STATUS +Ax88179PhyWrite ( + IN NIC_DEVICE * pNicDevice, + IN UINT8 RegisterAddress, + IN UINT16 PhyData + ); + +EFI_STATUS +Ax88179MacRead ( + IN UINT8 Offset, + IN UINT8 Length, + IN NIC_DEVICE * pNicDevice, + IN OUT VOID * pData + ); + +EFI_STATUS +Ax88179SetIInInterval ( + IN NIC_DEVICE * pNicDevice, + IN UINT8 Offset + ); + +EFI_STATUS +Ax88179MacWrite ( + IN UINT8 Offset, + IN UINT8 Length, + IN NIC_DEVICE * pNicDevice, + IN OUT VOID * pData + ); + +EFI_STATUS +Ax88179MacAddressGet ( + IN NIC_DEVICE * pNicDevice, + OUT UINT8 * pMacAddress + ); + +EFI_STATUS +Ax88179MacAddressSet ( + IN NIC_DEVICE * pNicDevice, + OUT UINT8 * pMacAddress + ); + +BOOLEAN +Ax88179GetLinkStatus ( + IN NIC_DEVICE * pNicDevice +); + +EFI_STATUS +Ax88179BulkIn( + IN NIC_DEVICE * pNicDevice +); + + +#endif // _AX88179_H_ diff --git a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.c b= /Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.c new file mode 100644 index 000000000000..7b2db9b74285 --- /dev/null +++ b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/Ax88179.c @@ -0,0 +1,1026 @@ + /** @file + Implement the interface to the AX88179 Ethernet controller. + + This module implements the interface to the ASIX AX88179 + USB to Ethernet MAC with integrated 10/100 PHY. Note that this implemen= tation + only supports the integrated PHY since no other test cases were availabl= e. + + Copyright (c) 2011, Intel Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Ax88179.h" + + +/** + Compute the CRC + + @param [in] pMacAddress Address of a six byte buffer to containing = the MAC address. + + @returns The CRC-32 value associated with this MAC address + +**/ +UINT32 +Ax88179Crc ( + IN UINT8 * pMacAddress + ) +{ + UINT32 BitNumber; + INT32 Carry; + INT32 Crc; + UINT32 Data; + UINT8 * pEnd; + + // + // Walk the MAC address + // + Crc =3D -1; + pEnd =3D &pMacAddress[ PXE_HWADDR_LEN_ETHER ]; + while ( pEnd > pMacAddress ) { + Data =3D *pMacAddress++; + + + // + // CRC32: x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x= 5 + x4 + x2 + x + 1 + // + // 1 0000 0100 1100 0001 0001 1101 1011 0111 + // + for ( BitNumber =3D 0; 8 > BitNumber; BitNumber++ ) { + Carry =3D (( Crc >> 31 ) & 1 ) ^ ( Data & 1 ); + Crc <<=3D 1; + if ( 0 !=3D Carry ) { + Crc ^=3D 0x04c11db7; + } + Data >>=3D 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 th= e 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 =3D 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 =3D 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 =3D 0; + // + // Clear the multicast hash table + // + + for ( i =3D 0 ; i < 8 ; i++ ) + pNicDevice->MulticastHash[i] =3D 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 =3D Ax88179Crc (pMacAddress) >> 26; + // + // Set the bit corresponding to the destination address + // + pNicDevice->MulticastHash [ Crc >> 3 ] |=3D ( 1<< (Crc& 7)); +} + +/** + Start the link negotiation + + This routine calls ::Ax88179PhyWrite to start the PHY's link + negotiation. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + + @retval EFI_SUCCESS The link negotiation was started. + @retval other Failed to start the link negotiation. + +**/ +EFI_STATUS +Ax88179NegotiateLinkStart ( + IN NIC_DEVICE * pNicDevice + ) +{ + UINT16 Control =3D 0; + EFI_STATUS Status; + +#if FORCE_100Mbps + Ax88179PhyRead ( pNicDevice, + 0x09, + &Control ); + Control &=3D 0xFCFF; + Ax88179PhyWrite ( pNicDevice, 0x09, Control ); +#endif + + // + // Set the link speed and duplex + // + Control =3D BMCR_AUTONEGOTIATION_ENABLE + | BMCR_RESTART_AUTONEGOTIATION; + if ( pNicDevice->b1000Mbps ) { + Control |=3D BMCR_1000MBPS; + } else if ( pNicDevice->b100Mbps ) { + Control |=3D BMCR_100MBPS; + } + + if ( pNicDevice->bFullDuplex ) { + Control |=3D BMCR_FULL_DUPLEX; + } + Status =3D 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 stat= us. + @param [out] pbLinkUp Address of boolean to receive link status, = TRUE=3Dup. + @param [out] pbHiSpeed Address of boolean to receive link speed, T= RUE=3D100Mbps. + @param [out] pbFullDuplex Address of boolean to receive link duplex, = TRUE=3Dfull. + + @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 =3D FALSE; + + // + // Get the link status + // + Status =3D Ax88179PhyRead ( pNicDevice, + PHY_PHYSR, + &PhyData ); + + if ( !EFI_ERROR ( Status )) { + *pbLinkUp =3D (BOOLEAN)( 0 !=3D ( PhyData & PHYSR_LINK )); + if (*pbLinkUp) { + // + // Determine if the autonegotiation is complete. + // + Status =3D Ax88179PhyRead ( pNicDevice, + PHY_BMSR, + &PhyData ); + if ( !EFI_ERROR (Status)) { + *pbComplete =3D (BOOLEAN)( 0 !=3D ( PhyData & BMSR_AUTONEG_CMPL= T )); + + if ( 0 !=3D *pbComplete ) { + // + // Get the partners capabilities. + // + Status =3D Ax88179PhyRead ( pNicDevice, + PHY_PHYSR, + &PhyData ); + if ( !EFI_ERROR ( Status )) { + // + // Autonegotiation is complete + // Determine the link speed. + // + *pbGigaSpeed =3D (BOOLEAN) (( PhyData & PHYSR_SPEED_MASK ) = =3D=3D PHYSR_1000 ); + *pbHiSpeed =3D (BOOLEAN)(( PhyData & PHYSR_SPEED_MASK ) =3D= =3D PHYSR_100 ); + + // + // Determine the link duplex. + // + *pbFullDuplex =3D (BOOLEAN)( (PhyData & PHYSR_FULLDUP) =3D= =3D 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 regi= ster 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 =3D USB_ENDPOINT_DIR_IN + | USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D ACCESS_PHY; + SetupMsg.Value =3D pNicDevice->PhyId; + SetupMsg.Index =3D RegisterAddress; + SetupMsg.Length =3D sizeof ( *pPhyData ); + Status =3D 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 regi= ster 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 =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D ACCESS_PHY; + SetupMsg.Value =3D pNicDevice->PhyId; + SetupMsg.Index =3D RegisterAddress; + SetupMsg.Length =3D sizeof ( PhyData ); + Status =3D 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 =3D Ax88179SetIInInterval(pNicDevice, 0xff); + + if (EFI_ERROR(Status)) goto err; + + val8 =3D 0; + Status =3D Ax88179MacRead (PLSR, + sizeof(val8), + pNicDevice, + &val8); + + if (EFI_ERROR(Status)) goto err; + + if (val8 & PLSR_USB_SS) + pNicDevice->usbMaxPktSize =3D 1024; + else + pNicDevice->usbMaxPktSize =3D 512; + + val =3D 0; + Status =3D Ax88179MacWrite ( PHYPWRRSTCTL, + sizeof (val), + pNicDevice, + &val); + + if (EFI_ERROR(Status)) goto err; + + gBS->Stall ( 10000 ); + + val =3D PHYPWRRSTCTL_IPRL; + Status =3D Ax88179MacWrite ( PHYPWRRSTCTL, + sizeof (val), + pNicDevice, + &val); + + if (EFI_ERROR(Status)) goto err; + + gBS->Stall ( 200000 ); + + val =3D CLKSELECT_BCS | CLKSELECT_ACS; + Status =3D Ax88179MacWrite ( CLKSELECT, + 1, + pNicDevice, + &val); + + if (EFI_ERROR(Status)) goto err; + + gBS->Stall ( 100000 ); + + val =3D 0x52; + Status =3D Ax88179MacWrite ( PAUSE_WATERLVL_HIGH, + 1, + pNicDevice, + &val); + + if (EFI_ERROR(Status)) goto err; + + val =3D 0x34; + Status =3D Ax88179MacWrite ( PAUSE_WATERLVL_LOW, + 1, + pNicDevice, + &val); + + if (EFI_ERROR(Status)) goto err; + + val =3D RXBINQCTRL_TIMEN | RXBINQCTRL_IFGEN | RXBINQCTRL_SIZEN; + + Status =3D Ax88179MacWrite ( RXBINQCTRL, + 0x01, + pNicDevice, + &val); + + if (EFI_ERROR(Status)) goto err; + + val =3D 0; + Status =3D Ax88179MacWrite ( RXBINQTIMERL, + 0x01, + pNicDevice, + &val); + + if (EFI_ERROR(Status)) goto err; + + val =3D 0; + Status =3D Ax88179MacWrite ( RXBINQTIMERH, + 0x01, + pNicDevice, + &val); + + if (EFI_ERROR(Status)) goto err; + + val =3D 12; //AX88179_BULKIN_SIZE_INK - 1; + Status =3D Ax88179MacWrite ( RXBINQSIZE, + 0x01, + pNicDevice, + &val); + + if (EFI_ERROR(Status)) goto err; + + val =3D 0x0F; + Status =3D Ax88179MacWrite ( RXBINQIFG, + 0x01, + pNicDevice, + &val); + +err: + return Status; +} + +EFI_STATUS +Ax88179RxControl ( + IN NIC_DEVICE * pNicDevice, + IN UINT32 RxFilter + ) +{ + UINT16 MediumStatus; + UINT16 RxControl =3D 0; + EFI_STATUS Status =3D EFI_SUCCESS; + // + // Enable the receiver if something is to be received + // + if ( 0 !=3D RxFilter ) { + // + // Enable the receiver + // + Status =3D Ax88179MacRead (MEDIUMSTSMOD, + sizeof ( MediumStatus ), + pNicDevice, + &MediumStatus); + + if ( !EFI_ERROR ( Status ) && pNicDevice->CurMediumStatus !=3D MediumS= tatus) { + MediumStatus =3D MEDIUMSTSMOD_RE | MEDIUMSTSMOD_ONE; + if ( pNicDevice->bFullDuplex ) { + MediumStatus |=3D MEDIUMSTSMOD_TFC | MEDIUMSTSMOD_RFC | MEDIUMST= SMOD_FD; + } else { + MediumStatus &=3D ~(MEDIUMSTSMOD_TFC | MEDIUMSTSMOD_RFC | MEDIUM= STSMOD_FD); + } + if ( pNicDevice->b1000Mbps ) { + MediumStatus |=3D MEDIUMSTSMOD_GM; + MediumStatus |=3D MEDIUMSTSMOD_ENCK; + MediumStatus &=3D ~MEDIUMSTSMOD_PS; + } else { + MediumStatus &=3D ~MEDIUMSTSMOD_GM; + MediumStatus &=3D ~MEDIUMSTSMOD_ENCK; + if ( pNicDevice->b100Mbps ) { + MediumStatus |=3D MEDIUMSTSMOD_PS; + } else { + MediumStatus &=3D ~MEDIUMSTSMOD_PS; + } + } + Status =3D Ax88179MacWrite (MEDIUMSTSMOD, + sizeof ( MediumStatus ), + pNicDevice, + &MediumStatus); + if ( !EFI_ERROR ( Status )) + pNicDevice->CurMediumStatus =3D MediumStatus; + } + } + + RxControl =3D RXCTL_SO | RXCTL_IPE; + + // + // Enable multicast if requested + // + if ( 0 !=3D ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST )) { + RxControl |=3D RXCTL_AM; + // + // Update the multicast hash table + // + Status =3D Ax88179MacWrite (MULCATFLTARRY, + 8, + pNicDevice, + &pNicDevice->MulticastHash ); + } + + // + // Enable all multicast if requested + // + if ( 0 !=3D ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAS= T )) { + RxControl |=3D RXCTL_AMALL; + } + // + // Enable broadcast if requested + // + if ( 0 !=3D ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST )) { + RxControl |=3D RXCTL_AB; + } + + // + // Enable promiscuous mode if requested + // + if ( 0 !=3D ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS )) { + RxControl |=3D RXCTL_PRO; + } + + // + // Update the receiver control + // + if (pNicDevice->CurRxControl !=3D RxControl) { + Status =3D Ax88179MacWrite (RXCTL, + 0x02, + pNicDevice, + &RxControl); + if ( !EFI_ERROR ( Status )) + pNicDevice->CurRxControl =3D RxControl; + } + + // + // Return the operation status + // + return Status; +} + +EFI_STATUS +Ax88179ReloadSrom ( + IN NIC_DEVICE * pNicDevice + ) +{ + EFI_STATUS Status; + + Status =3D 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 =3D EFI_UNSUPPORTED; + return Status; +} + +EFI_STATUS +Ax88179EnableSromWrite ( + IN NIC_DEVICE * pNicDevice + ) +{ + EFI_STATUS Status; + + Status =3D EFI_UNSUPPORTED; + return Status; +} + + +EFI_STATUS +Ax88179DisableSromWrite ( + IN NIC_DEVICE * pNicDevice + ) +{ + EFI_STATUS Status; + + Status =3D 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 =3D 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 =3D EFI_TIMEOUT; + UINT32 CmdStatus =3D EFI_USB_NOERROR; + int i; + // + // Determine the transfer direction + // + Direction =3D EfiUsbNoData; + if ( 0 !=3D pRequest->Length ) { + Direction =3D ( 0 !=3D ( pRequest->RequestType & USB_ENDPOINT_DIR_IN )) + ? EfiUsbDataIn : EfiUsbDataOut; + } + + // + // Issue the command + // + pUsbIo =3D pNicDevice->pUsbIo; + + for ( i =3D 0 ; i < 3 && EFI_TIMEOUT =3D=3D Status; i++) { + Status =3D pUsbIo->UsbControlTransfer ( pUsbIo, + pRequest, + Direction, + USB_BUS_TIMEOUT, + pBuffer, + pRequest->Length, + &CmdStatus ); + } + // + // Determine the operation status + // + if (EFI_ERROR(Status) || EFI_ERROR(CmdStatus)) + Status =3D 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 =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE + | USB_ENDPOINT_DIR_IN; + + SetupMsg.Request =3D ACCESS_MAC; + SetupMsg.Value =3D Offset; + SetupMsg.Index =3D Length; + SetupMsg.Length =3D SetupMsg.Index; + + Status =3D 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 =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + + SetupMsg.Request =3D ACCESS_MAC; + SetupMsg.Value =3D Offset; + SetupMsg.Index =3D Length; + SetupMsg.Length =3D SetupMsg.Index; + + Status =3D 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 =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + + SetupMsg.Request =3D 0x91; + SetupMsg.Value =3D Interval; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D 0; + + Status =3D Ax88179UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + + return Status; + +} + +EFI_STATUS +Ax88179SetMedium ( + IN NIC_DEVICE * pNicDevice + ) +{ + UINT16 MediumStatus; + EFI_STATUS Status; + + MediumStatus =3D MEDIUMSTSMOD_RE | MEDIUMSTSMOD_ONE; + if ( pNicDevice->bFullDuplex ) { + MediumStatus |=3D MEDIUMSTSMOD_TFC | MEDIUMSTSMOD_RFC | MEDIUMSTSMOD_F= D; + } else { + MediumStatus &=3D ~(MEDIUMSTSMOD_TFC | MEDIUMSTSMOD_RFC | MEDIUMSTSMOD= _FD); + } + if ( pNicDevice->b1000Mbps ) { + MediumStatus |=3D MEDIUMSTSMOD_GM; + MediumStatus &=3D ~MEDIUMSTSMOD_PS; + } else { + MediumStatus &=3D ~MEDIUMSTSMOD_GM; + if ( pNicDevice->b100Mbps ) { + MediumStatus |=3D MEDIUMSTSMOD_PS; + } else { + MediumStatus &=3D ~MEDIUMSTSMOD_PS; + } + } + Status =3D Ax88179MacWrite (MEDIUMSTSMOD, + sizeof ( MediumStatus ), + pNicDevice, + &MediumStatus); + if ( !EFI_ERROR ( Status )) + pNicDevice->CurMediumStatus =3D MediumStatus; + + return Status; +} + + +BOOLEAN +Ax88179GetLinkStatus ( + IN NIC_DEVICE * pNicDevice +) +{ + UINT32 CmdStatus; + EFI_USB_IO_PROTOCOL * pUsbIo; + UINT64 IntData =3D 0; + UINTN IntDataLeng =3D 8; + EFI_STATUS Status; + + // + // Issue the command + // + pUsbIo =3D pNicDevice->pUsbIo; + Status =3D pUsbIo->UsbSyncInterruptTransfer( pUsbIo, + USB_ENDPOINT_DIR_IN | INTERRUPT_EN= DPOINT, + &IntData, + &IntDataLeng, + USB_BUS_TIMEOUT, + &CmdStatus ); + + if ( EFI_ERROR(Status) || EFI_ERROR(CmdStatus) || 0 =3D=3D IntDataLeng) + return FALSE; + + return (IntData & 0x10000)? TRUE : FALSE; + +} + +EFI_STATUS +Ax88179BulkIn( + IN NIC_DEVICE * pNicDevice +) +{ + int i; + UINT16 val; + UINTN LengthInBytes =3D 0; + UINTN TMP_LENG =3D AX88179_MAX_BULKIN_SIZE; + UINTN CURBufSize =3D AX88179_MAX_BULKIN_SIZE; + UINTN PREBufSize =3D 0; + EFI_STATUS Status =3D EFI_NOT_READY; + EFI_USB_IO_PROTOCOL *pUsbIo; + UINT32 TransferStatus; + + pNicDevice->SkipRXCnt =3D 0; + + pUsbIo =3D pNicDevice->pUsbIo; + for ( i =3D 0 ; i < (AX88179_MAX_BULKIN_SIZE / 512) && pUsbIo !=3D NULL;= i++) { + VOID* tmpAddr =3D 0; + + if (pNicDevice->bSetZeroLen) { + val =3D PHYPWRRSTCTL_IPRL | PHYPWRRSTCTL_BZ; + Status =3D Ax88179MacWrite ( PHYPWRRSTCTL, + sizeof (val), + pNicDevice, + &val); + if (EFI_ERROR(Status)) { + LengthInBytes =3D 0; + Status =3D EFI_NOT_READY; + goto no_pkt; + } + pNicDevice->bSetZeroLen =3D FALSE; + } + tmpAddr =3D (VOID*) &pNicDevice->pBulkInbuf[LengthInBytes]; + + Status =3D EFI_NOT_READY; + Status =3D pUsbIo->UsbBulkTransfer ( pUsbIo, + USB_ENDPOINT_DIR_IN | BULK_IN_ENDPOINT, + tmpAddr, + &TMP_LENG, + BULKIN_TIMEOUT, + &TransferStatus ); + + if (( !EFI_ERROR ( Status )) && ( !EFI_ERROR ( TransferStatus )) && TM= P_LENG !=3D 0) { + LengthInBytes +=3D TMP_LENG; + if ((TMP_LENG % pNicDevice->usbMaxPktSize) !=3D 0) { + goto done; + } + CURBufSize =3D CURBufSize - TMP_LENG; + TMP_LENG =3D CURBufSize; + pNicDevice->bSetZeroLen =3D TRUE; + } else if (( !EFI_ERROR ( Status )) && + ( !EFI_ERROR ( TransferStatus )) && + ( TMP_LENG =3D=3D 0) && + LengthInBytes) { + if (PREBufSize =3D=3D CURBufSize) { + goto done; + } + TMP_LENG =3D CURBufSize; + PREBufSize =3D CURBufSize; + pNicDevice->bSetZeroLen =3D TRUE; + } else if (( !EFI_ERROR ( Status )) && + ( !EFI_ERROR ( TransferStatus )) && + ( TMP_LENG =3D=3D 0)) { + pNicDevice->bSetZeroLen =3D TRUE; + LengthInBytes =3D 0; + Status =3D EFI_NOT_READY; + goto done; + } else if (EFI_TIMEOUT =3D=3D Status && EFI_USB_ERR_TIMEOUT =3D=3D Tra= nsferStatus) { + pNicDevice->bSetZeroLen =3D TRUE; + LengthInBytes =3D 0; + Status =3D EFI_NOT_READY; + goto done; + } else { + pNicDevice->bSetZeroLen =3D TRUE; + LengthInBytes =3D 0; + Status =3D EFI_NOT_READY; + goto done; + } + } + +done: + if (LengthInBytes !=3D 0) { + UINT16 tmplen =3D 0; + UINT16 tmpPktCnt =3D 0; + + tmpPktCnt =3D *((UINT16 *) (pNicDevice->pBulkInbuf + LengthInBytes - 4= )); + tmplen =3D *((UINT16*) (pNicDevice->pBulkInbuf + LengthInBytes - 2)); + + if (((UINTN)(((tmpPktCnt * 4 + 4 + 7) & 0xfff8) + tmplen)) =3D=3D Leng= thInBytes) { + pNicDevice->PktCnt =3D tmpPktCnt; + pNicDevice->pCurPktHdrOff =3D pNicDevice->pBulkInbuf + tmplen; + pNicDevice->pCurPktOff =3D pNicDevice->pBulkInbuf; + *((UINT16 *) (pNicDevice->pBulkInbuf + LengthInBytes - 4)) =3D 0; + *((UINT16*) (pNicDevice->pBulkInbuf + LengthInBytes - 2)) =3D 0; + Status =3D EFI_SUCCESS; + } else { + Status =3D EFI_NOT_READY; + } + } else { + Status =3D EFI_NOT_READY; + } +no_pkt: + return Status; +} diff --git a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/ComponentNa= me.c b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/ComponentName.c new file mode 100644 index 000000000000..bb7ea146be02 --- /dev/null +++ b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/ComponentName.c @@ -0,0 +1,290 @@ +/** @file + UEFI Component Name(2) protocol implementation. + + Copyright (c) 2011, Intel Corporation. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Ax88179.h" + +/** + EFI Component Name Protocol declaration +**/ +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gComponentName = =3D { + GetDriverName, + GetControllerName, + "eng" +}; + +/** + EFI Component Name 2 Protocol declaration +**/ +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gComponentName2= =3D { + (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[] =3D { + {"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[] =3D { + {"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 o= f 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 speci= fied + 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_PROTO= COL 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 calle= r 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 for= mat. + @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 specifie= d by + This and the language specified by Languag= e 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 supp= ort + 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 =3D LookupUnicodeString2 ( + pLanguage, + pThis->SupportedLanguages, + mDriverNameTable, + ppDriverName, + (BOOLEAN)(pThis =3D=3D &gComponentName) + ); + + return Status; +} + +/** + Retrieves a Unicode string that is the user readable name of the control= ler + that is being managed by a driver. + + This function retrieves the user readable name of the controller specifi= ed 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 specif= ied by + Language, then a pointer to the controller name is returned in Controlle= rName, + and EFI_SUCCESS is returned. If the driver specified by This is not cur= rently + 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 retu= rned. + + @param [in] pThis A pointer to the EFI_COMPONENT_NAME2_PROTO= COL 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 retr= ieve + the name of. This is an optional paramete= r that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus d= rivers + 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 calle= r 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 specifie= d 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 a= nd + ChildHandle in the language specified by + Language from the point of view of the dri= ver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable n= ame 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 va= lid + 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 curren= tly + managing the controller specified by + ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + 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 !=3D NULL) { + return EFI_UNSUPPORTED; + } + + // + // Check Controller's handle + // + Status =3D 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 !=3D EFI_ALREADY_STARTED) { + return EFI_UNSUPPORTED; + } + + Status =3D LookupUnicodeString2 ( + pLanguage, + pThis->SupportedLanguages, + mControllerNameTable, + ppControllerName, + (BOOLEAN)(pThis =3D=3D &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 =3D gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + (VOID **) &UsbIoProtocol, + gDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + + if (!EFI_ERROR ( Status )) { + Status =3D UsbIoProtocol->UsbGetDeviceDescriptor ( UsbIoProtocol, &D= evice ); + if (EFI_ERROR(Status)) { + Status =3D EFI_UNSUPPORTED; + } else { + // + // Validate the adapter + // + if (( VENDOR_ID =3D=3D Device.IdVendor ) + && ( PRODUCT_ID =3D=3D Device.IdProduct )) { + *ppControllerName =3D L"AX88179 USB3.0 Gigabit Ethernet Contro= ller"; + Status =3D EFI_SUCCESS; + } else if (( VENDOR_ID =3D=3D Device.IdVendor ) + && ( PRODUCT_ID_178A =3D=3D Device.IdProduct )) { + *ppControllerName =3D L"AX88178A USB2.0 Gigabit Ethernet Contr= oller"; + Status =3D EFI_SUCCESS; + } else { + Status =3D EFI_UNSUPPORTED; + } + + } + + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + gDriverBinding.DriverBindingHandle, + ControllerHandle + ); + } + // + // Return the operation status + // + if (Status !=3D EFI_SUCCESS) { + *ppControllerName =3D L"AX88179_178A Gigabit Ethernet Controller"; + Status =3D EFI_SUCCESS; + } + return Status; +} + +#endif diff --git a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/DriverBindi= ng.c b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/DriverBinding.c new file mode 100644 index 000000000000..826a539e3f34 --- /dev/null +++ b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/DriverBinding.c @@ -0,0 +1,620 @@ +/** @file + Implement the driver binding protocol for Asix AX88179 Ethernet driver. + + Copyright (c) 2011, Intel Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Ax88179.h" + +/** + Verify the controller type + + @param [in] pThis Protocol instance pointer. + @param [in] Controller Handle of device to test. + @param [in] pRemainingDevicePath Not used. + + @retval EFI_SUCCESS This driver supports this device. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +DriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL * pThis, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL * pRemainingDevicePath + ) +{ + EFI_USB_DEVICE_DESCRIPTOR Device; + EFI_USB_IO_PROTOCOL * pUsbIo; + EFI_STATUS Status; + + // + // Connect to the USB stack + // + Status =3D 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 tra= nsport + // protocol handler. + // + Status =3D pUsbIo->UsbGetDeviceDescriptor ( pUsbIo, &Device ); + if (EFI_ERROR(Status)) { + Status =3D EFI_UNSUPPORTED; + } else { + // + // Validate the adapter + // + if (( VENDOR_ID =3D=3D Device.IdVendor ) && + ( PRODUCT_ID =3D=3D Device.IdProduct )) { + Status =3D EFI_SUCCESS; + } else if (( VENDOR_ID =3D=3D Device.IdVendor ) && + ( PRODUCT_ID_178A =3D=3D Device.IdProduct )) { + Status =3D EFI_SUCCESS; + } else { + Status =3D 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 protocol= s. + Initialize PXE structures, create a copy of the Controller Device Path w= ith 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 c= hildren. + + @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 =3D NULL; + MAC_ADDR_DEVICE_PATH MacDeviceNode; + + // + // Allocate the device structure + // + LengthInBytes =3D sizeof ( *pNicDevice ); + Status =3D gBS->AllocatePool ( + EfiRuntimeServicesData, + LengthInBytes, + (VOID **) &pNicDevice + ); + + if (EFI_ERROR (Status)) { + goto ERR; + } + + // + // Set the structure signature + // + ZeroMem ( pNicDevice, LengthInBytes ); + pNicDevice->Signature =3D DEV_SIGNATURE; + + Status =3D 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 =3D SN_Setup ( pNicDevice ); + + if (EFI_ERROR(Status)){ + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + pThis->DriverBindingHandle, + Controller + ); + goto ERR; + } + // + // Set Device Path + // + Status =3D 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 =3D MESSAGING_DEVICE_PATH; + MacDeviceNode.Header.SubType =3D MSG_MAC_ADDR_DP; + + SetDevicePathNodeLength (&MacDeviceNode.Header, sizeof (MAC_ADDR_DEVICE_= PATH)); + + CopyMem (&MacDeviceNode.MacAddress, + &pNicDevice->SimpleNetworkData.CurrentAddress, + PXE_HWADDR_LEN_ETHER); + + MacDeviceNode.IfType =3D pNicDevice->SimpleNetworkData.IfType; + + pNicDevice->MyDevPath =3D AppendDevicePathNode ( + ParentDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &Ma= cDeviceNode + ); + pNicDevice->Controller =3D NULL; + + // + // Install both the simple network and device path protocols. + // + Status =3D 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 =3D 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 !=3D pNicDevice->pBulkInbuf) + gBS->FreePool (pNicDevice->pBulkInbuf); + if ( NULL !=3D pNicDevice->pTxTest) + gBS->FreePool (pNicDevice->pTxTest); + if ( NULL !=3D pNicDevice->MyDevPath) + gBS->FreePool (pNicDevice->MyDevPath); + if (NULL !=3D pNicDevice) + gBS->FreePool ( pNicDevice ); + return Status; + +} + +/** + Stop this driver on Controller by removing NetworkInterfaceIdentifier pr= otocol 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 de= vice error. + @retval other This driver was not removed from this devic= e. + +**/ +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 =3D 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 =3D=3D 0) { + Status =3D 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 devi= cepath + // and usbio protocol. + // + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + pThis->DriverBindingHandle, + Controller + ); + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + pThis->DriverBindingHandle, + Controller + ); + return EFI_SUCCESS; + } + + pNicDevice =3D DEV_FROM_SIMPLE_NETWORK ( SimpleNetwork ); + + Status =3D gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiCallerIdGuid, + pNicDevice, + &gEfiSimpleNetworkProtocolGuid, + &pNicDevice->SimpleNetwork, + &gEfiDevicePathProtocolGuid, + pNicDevice->MyDevPath, + NULL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Close the bus driver + // + Status =3D gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + pThis->DriverBindingHandle, + Controller + ); + + Status =3D gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + pThis->DriverBindingHandle, + Controller + ); + return EFI_SUCCESS; + } + + AllChildrenStopped =3D TRUE; + + for (Index =3D 0; Index < NumberOfChildren; Index++) { + Status =3D gBS->OpenProtocol ( + ChildHandleBuffer[Index], + &gEfiSimpleNetworkProtocolGuid, + (VOID **) &SimpleNetwork, + pThis->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + AllChildrenStopped =3D FALSE; + continue; + } + + pNicDevice =3D DEV_FROM_SIMPLE_NETWORK ( SimpleNetwork ); + + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + pThis->DriverBindingHandle, + ChildHandleBuffer[Index] + ); + + Status =3D gBS->UninstallMultipleProtocolInterfaces ( + ChildHandleBuffer[Index], + &gEfiCallerIdGuid, + pNicDevice, + &gEfiSimpleNetworkProtocolGuid, + &pNicDevice->SimpleNetwork, + &gEfiDevicePathProtocolGuid, + pNicDevice->MyDevPath, + NULL + ); + + if (EFI_ERROR (Status)) { + Status =3D gBS->OpenProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + (VOID **) &pNicDevice->pUsbIo, + pThis->DriverBindingHandle, + ChildHandleBuffer[Index], + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + } else { + if ( NULL !=3D pNicDevice->pBulkInbuf) + gBS->FreePool (pNicDevice->pBulkInbuf); + if ( NULL !=3D pNicDevice->pTxTest) + gBS->FreePool (pNicDevice->pTxTest); + if ( NULL !=3D pNicDevice->MyDevPath) + gBS->FreePool (pNicDevice->MyDevPath); + if ( NULL !=3D pNicDevice) + gBS->FreePool (pNicDevice); + } + } + + if (!AllChildrenStopped) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + + +/** + Driver binding protocol declaration +**/ +EFI_DRIVER_BINDING_PROTOCOL gDriverBinding =3D { + 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 =3D 0; + pHandle =3D NULL; + Status =3D gBS->LocateHandle ( + ByProtocol, + &gEfiCallerIdGuid, + NULL, + &BufferSize, + NULL ); + if ( EFI_BUFFER_TOO_SMALL =3D=3D Status ) { + for ( ; ; ) { + // + // One or more block IO devices are present + // + Status =3D gBS->AllocatePool ( + EfiRuntimeServicesData, + BufferSize, + (VOID **) &pHandle + ); + if ( EFI_ERROR ( Status )) { + break; + } + + // + // Locate the block IO devices + // + Status =3D gBS->LocateHandle ( + ByProtocol, + &gEfiCallerIdGuid, + NULL, + &BufferSize, + pHandle ); + if ( EFI_ERROR ( Status )) { + // + // Error getting handles + // + + break; + } + + // + // Remove any use of the driver + // + Max =3D BufferSize / sizeof ( pHandle[ 0 ]); + for ( Index =3D 0; Max > Index; Index++ ) { + Status =3D DriverStop ( &gDriverBinding, + pHandle[ Index ], + 0, + NULL ); + if ( EFI_ERROR ( Status )) { + break; + } + } + break; + } + } else { + if ( EFI_NOT_FOUND =3D=3D Status ) { + // + // No devices were found + // + Status =3D EFI_SUCCESS; + } + } + + // + // Free the handle array + // + if ( NULL !=3D 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 =3D gBS->HandleProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **)&pLoadedImage + ); + if (!EFI_ERROR (Status)) { + pLoadedImage->Unload =3D DriverUnload; + } + + // + // Add the driver to the list of drivers + // + Status =3D EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + pSystemTable, + &gDriverBinding, + ImageHandle, + &gComponentName, + &gComponentName2 + ); + + return Status; +} diff --git a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/SimpleNetwo= rk.c b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/SimpleNetwork.c new file mode 100644 index 000000000000..25986451dcbc --- /dev/null +++ b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88179/SimpleNetwork.c @@ -0,0 +1,1585 @@ +/** @file + Provides the Simple Network functions. + + Copyright (c) 2011, Intel Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Ax88179.h" + +/** + This function updates the filtering on the receiver. + + This support routine calls ::Ax88179MacAddressSet to update + the MAC address. This routine then rebuilds the multicast + hash by calling ::Ax88179MulticastClear and ::Ax88179MulticastSet. + Finally this routine enables the receiver by calling + ::Ax88179RxControl. + @param [in] pSimpleNetwork Simple network mode pointer + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +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 =3D DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + pMode =3D pSimpleNetwork->Mode; + // + // Clear the multicast hash table + // + Ax88179MulticastClear ( pNicDevice ); + + // + // Load the multicast hash table + // + if ( 0 !=3D ( pMode->ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_M= ULTICAST )) { + for ( Index =3D 0; Index < pMode->MCastFilterCount; Index++ ) { + // + // Enable the next multicast address + // + Ax88179MulticastSet ( pNicDevice, + &pMode->MCastFilter[ Index ].Addr[0]); + } + } + + // + // Enable the receiver + // + Status =3D 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 a= ctive interrupts. + If this is NULL, the interrupt status will= not be read from + the device. If this is not NULL, the inte= rrupt status will + be read from teh device. When the interru= pt status is read, + it will also be cleared. Clearing the tra= nsmit interrupt + does not empty the recycled transmit buffe= r array. + @param [out] ppTxBuf Recycled transmit buffer address. The net= work interface will + not transmit if its internal recycled tran= smit buffer array is + full. Reading the transmit buffer does no= t clear the transmit + interrupt. If this is NULL, then the tran= smit buffer status + will not be read. If there are not transm= it 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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk 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 =3D EFI_SUCCESS; + EFI_TPL TplPrevious; + + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + // + // Verify the parameters + // + if (( NULL !=3D pSimpleNetwork ) && ( NULL !=3D pSimpleNetwork->Mode )) { + // + // Return the transmit buffer + // + pNicDevice =3D DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + + if (( NULL !=3D ppTxBuf ) && ( NULL !=3D pNicDevice->pTxBuffer )) { + *ppTxBuf =3D pNicDevice->pTxBuffer; + pNicDevice->pTxBuffer =3D NULL; + } + + pMode =3D pSimpleNetwork->Mode; + if (EfiSimpleNetworkInitialized =3D=3D pMode->State) { + if (NULL =3D=3D ppTxBuf && NULL =3D=3D pInterruptStatus) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } +#if REPORTLINK +#else + if (!pNicDevice->bLinkUp || !pNicDevice->bComplete) { +#endif + Status =3D 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 =3D TRUE; + Status =3D Ax88179SetMedium (pNicDevice); + } else { + pMode->MediaPresent =3D FALSE; + } +#else + if (pNicDevice->bLinkUp && pNicDevice->bComplete) { + pMode->MediaPresent =3D TRUE; + pMode->MediaPresentSupported =3D FALSE; + Status =3D Ax88179SetMedium (pNicDevice); + + } + } +#endif + } else { + if (EfiSimpleNetworkStarted =3D=3D pMode->State) { + Status =3D EFI_DEVICE_ERROR; ; + } else { + Status =3D EFI_NOT_STARTED ; + } + } + } else { + Status =3D EFI_INVALID_PARAMETER; + } + if ( NULL !=3D pInterruptStatus ) { + *pInterruptStatus =3D 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 t= o start the + read or write operation. This must be a m= ultiple 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 NvramAcces= sSize. + @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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +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 =3D EFI_INVALID_PARAMETER; + EFI_TPL TplPrevious; + EFI_SIMPLE_NETWORK_MODE * pMode; + NIC_DEVICE * pNicDevice; + + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + + if (( NULL =3D=3D pSimpleNetwork ) || ( NULL =3D=3D pSimpleNetwork->Mode= )) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + + pNicDevice =3D DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + pMode =3D pSimpleNetwork->Mode; + +#if PASS_SCT + if (EfiSimpleNetworkInitialized !=3D pMode->State) { + Status =3D EFI_NOT_STARTED; + goto EXIT; + } +#endif + + if ( 0 !=3D Offset ) { + if ((0 !=3D (Offset % pMode->NvRamAccessSize) ) || (Offset >=3D pMode-= >NvRamSize)) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + } + // + //Offset must be a multiple of NvRamAccessSize and less than NvRamSize. + // + if (0 !=3D (BufferSize % pMode->NvRamAccessSize)) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + + if (BufferSize + Offset > pMode->NvRamSize) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + + if (NULL =3D=3D pBuffer) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + + // + //ReadWrite: TRUE FOR READ FALSE FOR WRITE + // + if (ReadWrite){ + UINTN i; + + for (i =3D 0; i < BufferSize / 2 ; i++) { + Status =3D Ax88179SromRead ( pNicDevice, + (UINT32)(Offset/2 + i), + (((UINT16*)pBuffer) + i)); + } + } else { + UINTN i; + + Status =3D Ax88179EnableSromWrite(pNicDevice); + if (EFI_ERROR(Status)) goto EXIT; + + for (i =3D 0; i < BufferSize / 2 ; i++){ + Status =3D Ax88179SromWrite ( pNicDevice, + (UINT32)(Offset/2 + i), + (((UINT16*)pBuffer) + i)); + } + Status =3D Ax88179DisableSromWrite(pNicDevice); + + if (BufferSize =3D=3D 272) + Status =3D 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 be= fore + 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 buffe= r 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 transm= it and receive buffers + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +EFI_STATUS +EFIAPI +SN_Initialize ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + IN UINTN ExtraRxBufferSize, + IN UINTN ExtraTxBufferSize + ) +{ + EFI_SIMPLE_NETWORK_MODE * pMode; + EFI_STATUS Status; + UINT32 TmpState; + EFI_TPL TplPrevious; + NIC_DEVICE * pNicDevice; + TplPrevious =3D gBS->RaiseTPL (TPL_CALLBACK); + + // + // Verify the parameters + // + if (( NULL !=3D pSimpleNetwork ) && ( NULL !=3D pSimpleNetwork->Mode )) { + // + // Determine if the interface is already started + // + pMode =3D pSimpleNetwork->Mode; + if ( EfiSimpleNetworkStarted =3D=3D pMode->State ) { + if (( 0 =3D=3D ExtraRxBufferSize ) && ( 0 =3D=3D ExtraTxBufferSize )= ) { + // + // Start the adapter + // + TmpState =3D pMode->State; + pMode->State =3D EfiSimpleNetworkInitialized; + Status =3D SN_Reset ( pSimpleNetwork, FALSE ); + if ( EFI_ERROR ( Status )) { + // + // Update the network state + // + pMode->State =3D TmpState; + } else { + pMode->MediaPresentSupported =3D TRUE; + pNicDevice =3D DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + pMode->MediaPresent =3D Ax88179GetLinkStatus (pNicDevice); + } + } else { + Status =3D EFI_UNSUPPORTED; + } + } else { + Status =3D EFI_NOT_STARTED; + } + } else { + Status =3D EFI_INVALID_PARAMETER; + } + // + // Return the operation status + // + gBS->RestoreTPL (TplPrevious); + + return Status; +} + + +/** + This function converts a multicast IP address to a multicast HW MAC addr= ess + 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 i= s IPv4 [RFC 791]. + @param [in] pIP The multicast IP address that is to be con= verted 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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +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 =3D gBS->RaiseTPL(TPL_CALLBACK); + + if (( NULL !=3D pSimpleNetwork ) && ( NULL !=3D pSimpleNetwork->Mode )) { + // + // The interface must be running + // + pMode =3D pSimpleNetwork->Mode; + if ( EfiSimpleNetworkInitialized =3D=3D pMode->State ) { + if (pIP =3D=3D NULL || pMAC =3D=3D NULL) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + if (bIPv6){ + Status =3D EFI_UNSUPPORTED; + goto EXIT; + } else { + // + // check if the ip given is a mcast IP + // + if ((pIP->v4.Addr[0] & 0xF0) !=3D 0xE0) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } else { + pMAC->Addr[0] =3D 0x01; + pMAC->Addr[1] =3D 0x00; + pMAC->Addr[2] =3D 0x5e; + pMAC->Addr[3] =3D (UINT8) (pIP->v4.Addr[1] & 0x7f); + pMAC->Addr[4] =3D (UINT8) pIP->v4.Addr[2]; + pMAC->Addr[5] =3D (UINT8) pIP->v4.Addr[3]; + Status =3D EFI_SUCCESS; + } + } + } else { + if (EfiSimpleNetworkStarted =3D=3D pMode->State) { + Status =3D EFI_DEVICE_ERROR; ; + } else { + Status =3D EFI_NOT_STARTED ; + } + } + } else { + Status =3D 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_R= EADY + will be returned. If there is a packet on the receive queue, and the si= ze + 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->M= ediaHeaderSize + 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 networ= k interface. + @param [out] pBuffer A pointer to the packet (media header foll= owed 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 He= aderSize 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 Header= Size is zero, then + this parameter is ignored. + @param [out] pProtocol The type of header to build. If HeaderSiz= e 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 netwo= rk interface. + @retval EFI_BUFFER_TOO_SMALL The packet is larger than BufferSize bytes. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk 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 =3D 0; + UINT16 CurrentPktLen; + BOOLEAN bValid =3D TRUE; + EFI_TPL TplPrevious; + TplPrevious =3D gBS->RaiseTPL (TPL_CALLBACK); + // + // Verify the parameters + // + if (( NULL !=3D pSimpleNetwork ) && ( NULL !=3D pSimpleNetwork->Mode )) { + // + // The interface must be running + // + pMode =3D pSimpleNetwork->Mode; + if ( EfiSimpleNetworkInitialized =3D=3D pMode->State ) { + if ((pBufferSize =3D=3D NULL) || (pBuffer =3D=3D NULL)) { + Status =3D EFI_INVALID_PARAMETER; + gBS->RestoreTPL (TplPrevious); + return Status; + } + // + // Update the link status + // + pNicDevice =3D DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + if ( pNicDevice->bLinkUp && pNicDevice->bComplete) { + if ((NULL !=3D pHeaderSize) && (7720 =3D=3D *pHeaderSize)) { + pNicDevice->Grub_f =3D TRUE; + } + + if ((pNicDevice->Grub_f) && (7720 !=3D *pHeaderSize)) { + gBS->RestoreTPL (TplPrevious); + return EFI_NOT_READY; + } + // + // Attempt to do bulk in + // + if (0 =3D=3D pNicDevice->PktCnt) { + Status =3D Ax88179BulkIn(pNicDevice); + if (EFI_ERROR(Status)) + goto no_pkt; + } + CurrentPktLen =3D *((UINT16*) (pNicDevice->pCurPktHdrOff + 2)); + if (CurrentPktLen & (RXHDR_DROP | RXHDR_CRCERR)) + bValid =3D FALSE; + CurrentPktLen &=3D 0x1fff; + CurrentPktLen -=3D 2; /*EEEE*/ + + if (bValid && ( 60 <=3D CurrentPktLen ) && + ((CurrentPktLen - 14) <=3D MAX_ETHERNET_PKT_SIZE) && + (*((UINT16*)pNicDevice->pCurPktOff)) =3D=3D 0xEEEE) { + if (*pBufferSize < (UINTN)CurrentPktLen) { + gBS->RestoreTPL (TplPrevious); + return EFI_BUFFER_TOO_SMALL; + } + *pBufferSize =3D CurrentPktLen; + CopyMem ( pBuffer, pNicDevice->pCurPktOff + 2, CurrentPktLen ); + + pHeader =3D (ETHERNET_HEADER *) pNicDevice->pCurPktOff + 2; + + if ( NULL !=3D pHeaderSize && (7720 !=3D *pHeaderSize)) { + *pHeaderSize =3D sizeof ( *pHeader ); + } + + if ( NULL !=3D pDestAddr ) { + CopyMem ( pDestAddr, &pHeader->dest_addr, PXE_HWADDR_LEN_ETHER= ); + } + if ( NULL !=3D pSrcAddr ) { + CopyMem ( pSrcAddr, &pHeader->src_addr, PXE_HWADDR_LEN_ETHER ); + } + if ( NULL !=3D pProtocol ) { + Type =3D pHeader->type; + Type =3D (UINT16)(( Type >> 8 ) | ( Type << 8 )); + *pProtocol =3D Type; + } + pNicDevice->PktCnt--; + pNicDevice->pCurPktHdrOff +=3D 4; + pNicDevice->pCurPktOff +=3D (CurrentPktLen + 2 + 7) & 0xfff8; + Status =3D EFI_SUCCESS; + } else { + pNicDevice->PktCnt =3D 0; + Status =3D EFI_NOT_READY; + } + } else { + Status =3D EFI_NOT_READY; + } + } else { + if (EfiSimpleNetworkStarted =3D=3D pMode->State) { + Status =3D EFI_DEVICE_ERROR; + } else { + Status =3D EFI_NOT_STARTED ; + } + } + } else { + Status =3D 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 re= ceive + 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 li= st + filter is disabled (irregardless of what other multicast bits are set in + the enable and Disable parameters). The SNP->Mode->MCastFilterCount fie= ld + 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->ReceeiveFilterSetting= s, + 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 o= n the network interface. + For backward compatibility with EFI 1.1 pl= atforms, the + EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit m= ust be set + when the ResetMCastFilter parameter is TRU= E. + @param [in] bResetMCastFilter Set to TRUE to reset the contents of the m= ulticast 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 t= he MaxMCastFilterCnt + field of EFI_SIMPLE_NETWORK_MODE. This fi= eld is optional if + ResetMCastFilter is TRUE. + @param [in] pMCastFilter A pointer to a list of new multicast recei= ve filter HW MAC + addresses. This list will replace any exi= sting multicast + HW MAC address list. This field is option= al 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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +EFI_STATUS +EFIAPI +SN_ReceiveFilters ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + IN UINT32 Enable, + IN UINT32 Disable, +/* +#define EFI_SIMPLE_NETWORK_RECEIVE_UNICAST 0x01 +#define EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST 0x02 +#define EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST 0x04 +#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS 0x08 +#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST 0x10 +*/ + IN BOOLEAN bResetMCastFilter, + IN UINTN MCastFilterCnt, + IN EFI_MAC_ADDRESS * pMCastFilter + ) +{ + EFI_SIMPLE_NETWORK_MODE * pMode; + EFI_STATUS Status =3D EFI_SUCCESS; + EFI_TPL TplPrevious; + NIC_DEVICE * pNicDevice; + + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + pNicDevice =3D DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + pMode =3D pSimpleNetwork->Mode; + + if (pSimpleNetwork =3D=3D NULL) { + gBS->RestoreTPL(TplPrevious); + return EFI_INVALID_PARAMETER; + } + + switch (pMode->State) { + case EfiSimpleNetworkInitialized: + break; + case EfiSimpleNetworkStopped: + Status =3D EFI_NOT_STARTED; + gBS->RestoreTPL(TplPrevious); + return Status; + + default: + Status =3D EFI_DEVICE_ERROR; + gBS->RestoreTPL(TplPrevious); + return Status; + } + + // + // check if we are asked to enable or disable something that the UNDI + // does not even support! + // + if (((Enable &~pMode->ReceiveFilterMask) !=3D 0) || + ((Disable &~pMode->ReceiveFilterMask) !=3D 0)) { + Status =3D EFI_INVALID_PARAMETER; + gBS->RestoreTPL(TplPrevious); + return Status; + } + + if (bResetMCastFilter) { + Disable |=3D (EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST & pMode->ReceiveFil= terMask); + MCastFilterCnt =3D 0; + pMode->MCastFilterCount =3D 0; + if ( (0 =3D=3D (pMode->ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEI= VE_MULTICAST)) && + Enable =3D=3D 0 && Disable =3D=3D 2) { + gBS->RestoreTPL(TplPrevious); + return EFI_SUCCESS; + } + } else { + if (MCastFilterCnt !=3D 0) { + UINTN i; + + EFI_MAC_ADDRESS * pMulticastAddress; + pMulticastAddress =3D pMCastFilter; + + if ((MCastFilterCnt > pMode->MaxMCastFilterCount) || + (pMCastFilter =3D=3D NULL)) { + Status =3D EFI_INVALID_PARAMETER; + gBS->RestoreTPL(TplPrevious); + return Status; + } + + for ( i =3D 0 ; i < MCastFilterCnt ; i++ ) { + UINT8 tmp; + + tmp =3D pMulticastAddress->Addr[0]; + if ( (tmp & 0x01) !=3D 0x01 ) { + gBS->RestoreTPL(TplPrevious); + return EFI_INVALID_PARAMETER; + } + pMulticastAddress++; + } + + pMode->MCastFilterCount =3D (UINT32)MCastFilterCnt; + CopyMem (&pMode->MCastFilter[0], + pMCastFilter, + MCastFilterCnt * sizeof ( EFI_MAC_ADDRESS/**pMCastFilter*/ = )); + } + } + + if (Enable =3D=3D 0 && Disable =3D=3D 0 && !bResetMCastFilter && MCastFi= lterCnt =3D=3D 0) { + Status =3D EFI_SUCCESS; + gBS->RestoreTPL(TplPrevious); + return Status; + } + + if ((Enable & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) !=3D 0 && MCastFilte= rCnt =3D=3D 0) { + Status =3D EFI_INVALID_PARAMETER; + gBS->RestoreTPL(TplPrevious); + return Status; + } + + pMode->ReceiveFilterSetting |=3D Enable; + pMode->ReceiveFilterSetting &=3D ~Disable; + + Status =3D 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 d= evice + 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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +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 =3D gBS->RaiseTPL(TPL_CALLBACK); + + // + // Verify the parameters + // + if (( NULL !=3D pSimpleNetwork ) && ( NULL !=3D pSimpleNetwork->Mode )) { + pMode =3D pSimpleNetwork->Mode; + if ( EfiSimpleNetworkInitialized =3D=3D pMode->State ) { + // + // Update the device state + // + pNicDevice =3D DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + + // + // Reset the device + // + if (!pNicDevice->bFirstRst) { + Status =3D EFI_SUCCESS; + } else { + Status =3D Ax88179Reset ( pNicDevice ); + if ( !EFI_ERROR ( Status )) { + Status =3D ReceiveFilterUpdate ( pSimpleNetwork ); + if ( !EFI_ERROR ( Status ) && !pNicDevice->bLinkUp && pNicDevice= ->bFirstRst) { + Status =3D Ax88179NegotiateLinkStart ( pNicDevice ); + pNicDevice->bFirstRst =3D FALSE; + } + } + } + } else { + Status =3D EFI_NOT_STARTED; + } + } else { + Status =3D 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 =3D &pNicDevice->SimpleNetwork; + pSimpleNetwork->Revision =3D EFI_SIMPLE_NETWORK_PROTOCOL_REVISION; + pSimpleNetwork->Start =3D (EFI_SIMPLE_NETWORK_START)SN_Start; + pSimpleNetwork->Stop =3D (EFI_SIMPLE_NETWORK_STOP)SN_Stop; + pSimpleNetwork->Initialize =3D (EFI_SIMPLE_NETWORK_INITIALIZE)SN_Initial= ize; + pSimpleNetwork->Reset =3D (EFI_SIMPLE_NETWORK_RESET)SN_Reset; + pSimpleNetwork->Shutdown =3D (EFI_SIMPLE_NETWORK_SHUTDOWN)SN_Shutdown; + pSimpleNetwork->ReceiveFilters =3D (EFI_SIMPLE_NETWORK_RECEIVE_FILTERS)S= N_ReceiveFilters; + pSimpleNetwork->StationAddress =3D (EFI_SIMPLE_NETWORK_STATION_ADDRESS)S= N_StationAddress; + pSimpleNetwork->Statistics =3D (EFI_SIMPLE_NETWORK_STATISTICS)SN_Statist= ics; + pSimpleNetwork->MCastIpToMac =3D (EFI_SIMPLE_NETWORK_MCAST_IP_TO_MAC)SN_= MCastIPtoMAC; + pSimpleNetwork->NvData =3D (EFI_SIMPLE_NETWORK_NVDATA)SN_NvData; + pSimpleNetwork->GetStatus =3D (EFI_SIMPLE_NETWORK_GET_STATUS)SN_GetStatu= s; + pSimpleNetwork->Transmit =3D (EFI_SIMPLE_NETWORK_TRANSMIT)SN_Transmit; + pSimpleNetwork->Receive =3D (EFI_SIMPLE_NETWORK_RECEIVE)SN_Receive; + pSimpleNetwork->WaitForPacket =3D NULL; + pMode =3D &pNicDevice->SimpleNetworkData; + pSimpleNetwork->Mode =3D pMode; + pMode->State =3D EfiSimpleNetworkStopped; + pMode->HwAddressSize =3D PXE_HWADDR_LEN_ETHER; + pMode->MediaHeaderSize =3D sizeof ( ETHERNET_HEADER ); + pMode->MaxPacketSize =3D MAX_ETHERNET_PKT_SIZE; + pMode->ReceiveFilterMask =3D 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_MULTIC= AST; + pMode->ReceiveFilterSetting =3D EFI_SIMPLE_NETWORK_RECEIVE_UNICAST + | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST; + pMode->MaxMCastFilterCount =3D MAX_MCAST_FILTER_CNT; + pMode->MCastFilterCount =3D 0; + pMode->NvRamSize =3D 512; + pMode->NvRamAccessSize =3D 2; + SetMem ( &pMode->BroadcastAddress, + PXE_HWADDR_LEN_ETHER, + 0xff ); + pMode->IfType =3D EfiNetworkInterfaceUndi; + pMode->MacAddressChangeable =3D TRUE; + pMode->MultipleTxSupported =3D FALSE; + pMode->MediaPresentSupported =3D TRUE; + pMode->MediaPresent =3D FALSE; + // + // Read the MAC address + // + pNicDevice->PhyId =3D PHY_ID_INTERNAL; + pNicDevice->b100Mbps =3D FALSE; + pNicDevice->b1000Mbps =3D TRUE; + pNicDevice->bFullDuplex =3D TRUE; + pNicDevice->bComplete =3D FALSE; + pNicDevice->bLinkUp =3D FALSE; + pNicDevice->Grub_f =3D FALSE; + pNicDevice->bFirstRst =3D TRUE; + pNicDevice->PktCnt =3D 0; + pNicDevice->SkipRXCnt =3D 0; + pNicDevice->usbMaxPktSize =3D 512; + pNicDevice->bSetZeroLen =3D TRUE; + + Status =3D Ax88179MacAddressGet ( pNicDevice, + &pMode->PermanentAddress.Addr[0]); + if ( !EFI_ERROR ( Status )) { + // + // Use the hardware address as the current address + // + CopyMem ( &pMode->CurrentAddress, + &pMode->PermanentAddress, + PXE_HWADDR_LEN_ETHER ); + + CopyMem ( &pNicDevice->MAC, + &pMode->PermanentAddress, + PXE_HWADDR_LEN_ETHER ); + + } else { + return Status; + } + + Status =3D gBS->AllocatePool ( EfiRuntimeServicesData, + AX88179_MAX_BULKIN_SIZE, + (VOID **) &pNicDevice->pBulkInbuf ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D gBS->AllocatePool ( EfiRuntimeServicesData, + sizeof ( TX_PACKET ), + (VOID **) &pNicDevice->pTxTest ); + if (EFI_ERROR (Status)) { + gBS->FreePool (pNicDevice->pBulkInbuf); + } + + // + // Return the setup status + // + return Status; +} + + +/** + This routine starts the network interface. + + @param [in] pSimpleNetwork Protocol instance pointer + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_ALREADY_STARTED The network interface was already started. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +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 =3D gBS->RaiseTPL(TPL_CALLBACK); + + + + // + // Verify the parameters + // + Status =3D EFI_INVALID_PARAMETER; + if (( NULL !=3D pSimpleNetwork ) && ( NULL !=3D pSimpleNetwork->Mode )) { + pMode =3D pSimpleNetwork->Mode; + if ( EfiSimpleNetworkStopped =3D=3D pMode->State ) { + // + // Initialize the mode structure + // NVRAM access is not supported + // + ZeroMem ( pMode, sizeof ( *pMode )); + + pMode->State =3D EfiSimpleNetworkStarted; + pMode->HwAddressSize =3D PXE_HWADDR_LEN_ETHER; + pMode->MediaHeaderSize =3D sizeof ( ETHERNET_HEADER ); + pMode->MaxPacketSize =3D MAX_ETHERNET_PKT_SIZE; + pMode->ReceiveFilterMask =3D 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_MU= LTICAST; + pMode->ReceiveFilterSetting =3D EFI_SIMPLE_NETWORK_RECEIVE_UNICAST; + pMode->MaxMCastFilterCount =3D MAX_MCAST_FILTER_CNT; + pMode->MCastFilterCount =3D 0; + pMode->NvRamSize =3D 512; + pMode->NvRamAccessSize =3D 2; + pNicDevice =3D DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + Status =3D Ax88179MacAddressGet ( pNicDevice, &pMode->PermanentAddre= ss.Addr[0]); + CopyMem ( &pMode->CurrentAddress, + &pMode->PermanentAddress, + sizeof ( pMode->CurrentAddress )); + SetMem(&pMode->BroadcastAddress, PXE_HWADDR_LEN_ETHER, 0xff); + pMode->IfType =3D EfiNetworkInterfaceUndi; + pMode->MacAddressChangeable =3D TRUE; + pMode->MultipleTxSupported =3D FALSE; + pMode->MediaPresentSupported =3D TRUE; + pMode->MediaPresent =3D FALSE; + + } else { + Status =3D 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 net= work + 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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +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 =3D gBS->RaiseTPL(TPL_CALLBACK); + // + // Verify the parameters + // + if (( NULL !=3D pSimpleNetwork ) && + ( NULL !=3D pSimpleNetwork->Mode ) && + (( !bReset ) || ( bReset && ( NULL !=3D pNew )))) { + // + // Verify that the adapter is already started + // + pNicDevice =3D DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + pMode =3D pSimpleNetwork->Mode; + if ( EfiSimpleNetworkInitialized =3D=3D 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 =3D Ax88179MacAddressSet ( pNicDevice, &pMode->CurrentAddress= .Addr[0]); + } else { + if (EfiSimpleNetworkStarted =3D=3D pMode->State) { + Status =3D EFI_DEVICE_ERROR; ; + } else { + Status =3D EFI_NOT_STARTED ; + } + } + } else { + Status =3D 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 th= e network interface. + @param [in, out] pStatisticsSize On input the size, in bytes, of Statis= ticsTable. On output + the size, in bytes, of the resulting table= of statistics. + @param [out] pStatisticsTable A pointer to the EFI_NETWORK_STATISTICS st= ructure 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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + + typedef struct { + UINT64 RxTotalFrames; + UINT64 RxGoodFrames; + UINT64 RxUndersizeFrames; + UINT64 RxOversizeFrames; + UINT64 RxDroppedFrames; + UINT64 RxUnicastFrames; + UINT64 RxBroadcastFrames; + UINT64 RxMulticastFrames; + UINT64 RxCrcErrorFrames; + UINT64 RxTotalBytes; + UINT64 TxTotalFrames; + UINT64 TxGoodFrames; + UINT64 TxUndersizeFrames; + UINT64 TxOversizeFrames; + UINT64 TxDroppedFrames; + UINT64 TxUnicastFrames; + UINT64 TxBroadcastFrames; + UINT64 TxMulticastFrames; + UINT64 TxCrcErrorFrames; + UINT64 TxTotalBytes; + UINT64 Collisions; + UINT64 UnsupportedProtocol; + } EFI_NETWORK_STATISTICS; +**/ +EFI_STATUS +EFIAPI +SN_Statistics ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + IN BOOLEAN bReset, + IN OUT UINTN * pStatisticsSize, + OUT EFI_NETWORK_STATISTICS * pStatisticsTable + ) +{ + EFI_STATUS Status; + EFI_TPL TplPrevious; + EFI_SIMPLE_NETWORK_MODE * pMode; + + + + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + + pMode =3D pSimpleNetwork->Mode; + + if ( EfiSimpleNetworkInitialized =3D=3D pMode->State ) { + if (NULL !=3D pStatisticsSize && 0 =3D=3D *pStatisticsSize) { + Status =3D EFI_BUFFER_TOO_SMALL; + goto EXIT; + } + + if(bReset) { + Status =3D EFI_SUCCESS; + } else { + Status =3D EFI_SUCCESS; + } + } else { + if (EfiSimpleNetworkStarted =3D=3D pMode->State) { + Status =3D EFI_DEVICE_ERROR; ; + } else { + Status =3D EFI_NOT_STARTED ; + } + } + + Status =3D 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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +EFI_STATUS +EFIAPI +SN_Stop ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork + ) +{ + EFI_SIMPLE_NETWORK_MODE * pMode; + EFI_STATUS Status; + EFI_TPL TplPrevious; + + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + + // + // Verify the parameters + // + if (( NULL !=3D pSimpleNetwork ) && ( NULL !=3D pSimpleNetwork->Mode )) { + // + // Determine if the interface is started + // + pMode =3D pSimpleNetwork->Mode; + if ( EfiSimpleNetworkStarted =3D=3D pMode->State ) { + pMode->State =3D EfiSimpleNetworkStopped; + Status =3D EFI_SUCCESS; + } else { + Status =3D EFI_NOT_STARTED; + } + } else { + Status =3D EFI_INVALID_PARAMETER; + } + // + // Return the operation status + // + gBS->RestoreTPL(TplPrevious); + return Status; +} + +/** + This function releases the memory buffers assigned in the Initialize() c= all. + 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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +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 =3D gBS->RaiseTPL(TPL_CALLBACK); + + // + // Verify the parameters + // + if (( NULL !=3D pSimpleNetwork ) && ( NULL !=3D pSimpleNetwork->Mode )) { + // + // Determine if the interface is already started + // + pMode =3D pSimpleNetwork->Mode; + if ( EfiSimpleNetworkInitialized =3D=3D pMode->State ) { + // + // Stop the adapter + // + pNicDevice =3D DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + + Status =3D Ax88179MacAddressGet ( pNicDevice, &pMode->PermanentAddre= ss.Addr[0]); + if ( !EFI_ERROR ( Status )) { + // + // Update the network state + // + pMode->State =3D EfiSimpleNetworkStarted; + } else if ( EFI_DEVICE_ERROR =3D=3D Status ) { + pMode->State =3D EfiSimpleNetworkStopped; + } + } else { + Status =3D EFI_NOT_STARTED; + } + } else { + Status =3D 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->M= ediaHeaderSize + 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 networ= k interface. + @param [in] pBuffer A pointer to the packet (media header foll= owed 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 He= aderSize 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 Header= Size is zero, then + this parameter is ignored. + @param [in] pProtocol The type of header to build. If HeaderSiz= e 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 accep= t this transmit request. + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk 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 =3D 0; + EFI_TPL TplPrevious; + + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + // + // Verify the parameters + // + if (( NULL !=3D pSimpleNetwork ) && ( NULL !=3D pSimpleNetwork->Mode )) { + // + // The interface must be running + // + pMode =3D pSimpleNetwork->Mode; + if ( EfiSimpleNetworkInitialized =3D=3D pMode->State ) { + // + // Update the link status + // + pNicDevice =3D DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + + if ( pNicDevice->bLinkUp && pNicDevice->bComplete) { + if (0 !=3D HeaderSize && pMode->MediaHeaderSize !=3D HeaderSize) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + if (BufferSize < pMode->MediaHeaderSize) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + if (NULL =3D=3D pBuffer) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + if (0 !=3D HeaderSize && NULL =3D=3D pDestAddr) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + if (0 !=3D HeaderSize && NULL =3D=3D pProtocol) { + Status =3D 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 =3D (UINT32) BufferSize; + pNicDevice->pTxTest->TxHdr2 =3D 0; + // + // Transmit the packet + // + pHeader =3D (ETHERNET_HEADER *) &pNicDevice->pTxTest->Data[0]; + if ( 0 !=3D HeaderSize ) { + if ( NULL !=3D pDestAddr ) { + CopyMem ( &pHeader->dest_addr, pDestAddr, PXE_HWADDR_LEN_ETHER= ); + } + if ( NULL !=3D 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 !=3D pProtocol ) { + Type =3D *pProtocol; + } else { + Type =3D (UINT16) BufferSize; + } + Type =3D (UINT16)(( Type >> 8 ) | ( Type << 8 )); + pHeader->type =3D Type; + } + + if ( pNicDevice->pTxTest->TxHdr1 < MIN_ETHERNET_PKT_SIZE ) { + pNicDevice->pTxTest->TxHdr1 =3D MIN_ETHERNET_PKT_SIZE; + ZeroMem ( &pNicDevice->pTxTest->Data[BufferSize], + MIN_ETHERNET_PKT_SIZE - BufferSize ); + } + + TransferLength =3D 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 =3D pNicDevice->pUsbIo; + Status =3D pUsbIo->UsbBulkTransfer ( pUsbIo, + BULK_OUT_ENDPOINT, + &pNicDevice->pTxTest->TxHdr1, + &TransferLength, + 0xfffffffe, + &TransferStatus ); + + if (!EFI_ERROR(Status) && !EFI_ERROR(Status)) { + pNicDevice->pTxBuffer =3D pBuffer; + Status =3D EFI_SUCCESS; + } else if (EFI_TIMEOUT =3D=3D Status && EFI_USB_ERR_TIMEOUT =3D=3D= TransferStatus) { + Status =3D EFI_NOT_READY; + } else { + Status =3D EFI_DEVICE_ERROR; + } + } else { + // + // No packets available. + // + Status =3D EFI_NOT_READY; + } + } else { + if (EfiSimpleNetworkStarted =3D=3D pMode->State) { + Status =3D EFI_DEVICE_ERROR; ; + } else { + Status =3D EFI_NOT_STARTED ; + } + } + } else { + Status =3D EFI_INVALID_PARAMETER; + } +EXIT: + gBS->RestoreTPL (TplPrevious); + return Status; +} --=20 2.17.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#58773): https://edk2.groups.io/g/devel/message/58773 Mute This Topic: https://groups.io/mt/74044146/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Mon Apr 29 00:16:54 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+58772+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+58772+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1588822649; cv=none; d=zohomail.com; s=zohoarc; b=fNOLYjDbGY70QK/vCC6xea49luqha7kxeAz5xlndmtI6CMp3QixY82v1dcGI1zjKLmp1XnYVnHhvG3R4+cgtjIf9i6LLZgeqJBZ8uQ4gjhNw5Fs/amV37/fwMOQNW/d7fRS/YaZelTp9XSuRw9kJoBWmFI1xSnTaNPPXqtOhEmk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1588822649; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To; bh=FsCX+NiVyl+v5XDkjlL0wMrIB541lXZCWNMiaBUYaEo=; b=ODC3A5YE9DVTf9UVYMTAp0r6Ey2taat/wMBLfNfKBlLpeInt0SRZuoYLgZXHWe1D7SNEU+3b1EWE2QCX7GE+YlytRNP50FcWzhzuygyYnEp5Mgymt1L6cdQW3I1eZI3V1eq14A6nWBeWRqG8l8Yqb9/m1oFp+8EAIngKsVzL4sg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+58772+1787277+3901457@groups.io Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1588822649575571.9671950753657; Wed, 6 May 2020 20:37:29 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id qaN0YY1788612xLiwag7623n; Wed, 06 May 2020 20:37:29 -0700 X-Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web12.4027.1588822647211029758 for ; Wed, 06 May 2020 20:37:27 -0700 X-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 D874E1042; Wed, 6 May 2020 20:37:26 -0700 (PDT) X-Received: from localhost.localdomain (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 670113F305; Wed, 6 May 2020 20:37:26 -0700 (PDT) From: "Samer El-Haj-Mahmoud" To: devel@edk2.groups.io Cc: Ray Ni , Leif Lindholm , Ard Biesheuvel Subject: [edk2-devel] [edk2-platform][PATCH v1 2/2] Drivers/OptionRomPkg: UsbNetworking: ASIX Ax88772c driver v2.8.0 Date: Wed, 6 May 2020 23:37:20 -0400 Message-Id: <20200507033720.31152-3-Samer.El-Haj-Mahmoud@arm.com> In-Reply-To: <20200507033720.31152-1-Samer.El-Haj-Mahmoud@arm.com> References: <20200507033720.31152-1-Samer.El-Haj-Mahmoud@arm.com> Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,samer.el-haj-mahmoud@arm.com X-Gm-Message-State: 8veodmWO0E7j4k1ixYqvJJ2Px1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1588822649; bh=8tNVuGuzKObnnxR7X+XxQxxaBStQ0w5hRsnyi1bSgSE=; h=Cc:Date:From:Reply-To:Subject:To; b=YNj1sotpTzr6bTwDT/1oQp0+YhnBEtE7e3icT8YWIsZrbndi/1BUZnB0ij6duzRD45Q 0m8gWfJKm9ZbpdMDDWlJGvzROCe8HEiYcBNiqQBXJ+A6a5IH3+UUgJr2/SCLUZPoXmjKe S3GmTUKGXbiGDxYGZJtoGYW3tfjXQyb3vho= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This is the initial revision of ASIX USB networking UEFI driver version 2.8.0 for Ax88772c / Ax88772b / Ax88772a https://www.asix.com.tw/download.php?sub=3Ddriverdetail&PItemID=3D136 Source code contributed by ASIX. Cc: Ray Ni Cc: Leif Lindholm Cc: Ard Biesheuvel Signed-off-by: Samer El-Haj-Mahmoud --- Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772c.inf | 65= + Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.h | 1097= +++++++++++++ Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.c | 1296= ++++++++++++++++ Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/ComponentName.c | 246= +++ Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/DriverBinding.c | 637= ++++++++ Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/SimpleNetwork.c | 1612= ++++++++++++++++++++ 6 files changed, 4953 insertions(+) diff --git a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772c.i= nf b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772c.inf new file mode 100644 index 000000000000..1d37a5dae34b --- /dev/null +++ b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772c.inf @@ -0,0 +1,65 @@ +## @file +# Component description file for ASIX AX88772 USB/Ethernet driver. +# +# This module provides support for the ASIX AX88772 USB/Ethernet adapter. +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010018 + BASE_NAME =3D Ax88772c + FILE_GUID =3D B15239D6-6A01-4808-A0F7-B7F20F073555 + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + + ENTRY_POINT =3D EntryPoint + +# +# VALID_ARCHITECTURES =3D IA32 X64 EBC +# + +[Sources.common] + Ax88772.h + Ax88772.c + ComponentName.c + DriverBinding.c + SimpleNetwork.c + + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiLib + UefiBootServicesTableLib + BaseMemoryLib + DebugLib + UefiDriverEntryPoint + +[Protocols] + gEfiDevicePathProtocolGuid ## BY_START + gEfiSimpleNetworkProtocolGuid ## BY_START + gEfiUsbIoProtocolGuid ## TO_START + +#[Guids] +# gEfiEventExitBootServicesGuid ## PRODUCES ## Event +# gEfiEventVirtualAddressChangeGuid ## PRODUCES ## Event +# gEfiNicIp4ConfigVariableGuid + +[Depex] + gEfiBdsArchProtocolGuid AND + gEfiCpuArchProtocolGuid AND + gEfiMetronomeArchProtocolGuid AND + gEfiMonotonicCounterArchProtocolGuid AND + gEfiRealTimeClockArchProtocolGuid AND + gEfiResetArchProtocolGuid AND + gEfiRuntimeArchProtocolGuid AND + gEfiSecurityArchProtocolGuid AND + gEfiTimerArchProtocolGuid AND + gEfiVariableWriteArchProtocolGuid AND + gEfiVariableArchProtocolGuid AND + gEfiWatchdogTimerArchProtocolGuid diff --git a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.h = b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.h new file mode 100644 index 000000000000..18317fd5c4f7 --- /dev/null +++ b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.h @@ -0,0 +1,1097 @@ +/** @file + Definitions for ASIX AX88772 Ethernet adapter. + + Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _AX88772_H_ +#define _AX88772_H_ + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define MAX_QUEUE_SIZE 50 +#define MAX_BULKIN_SIZE 16384 +#define HW_HDR_LENGTH 8 +#define PASS_SCT 0 +#define REPORTLINK 1 + +#define ARM 0 + +#if ARM +#define MAX_LINKIDLE_THRESHOLD 100 +#else +#define MAX_LINKIDLE_THRESHOLD 30 +#endif + +#define AMI 1 +#define ASIX_MCAST_FILTER_CNT 8 +#define RXTHOU 0 + +#if 0 +//------------------------------------------------------------------------= ------ +// Macros +//------------------------------------------------------------------------= ------ + +#if defined(_MSC_VER) /* Handle Microsoft VC++ compiler specific= s. */ +#define DBG_ENTER() DEBUG (( 0xffffffff, "Entering " __FUNCTIO= N__ "\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 val= ue +#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 =3D=3D 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 v= alue +#define DBG_EXIT_TF(Status) ///< Display routine with TRUE/FALSE va= lue +#endif // _MSC_VER + +#endif + +#define USB_IS_IN_ENDPOINT(EndPointAddr) (((EndPointAddr) & BIT7) != =3D 0) ///< Return TRUE/FALSE for IN direction +#define USB_IS_OUT_ENDPOINT(EndPointAddr) (((EndPointAddr) & BIT7) =3D= =3D 0) ///< Return TRUE/FALSE for OUT direction +#define USB_IS_BULK_ENDPOINT(Attribute) (((Attribute) & (BIT0 | BIT1= )) =3D=3D USB_ENDPOINT_BULK) ///< Return TRUE/FALSE for BULK type +#define USB_IS_INTERRUPT_ENDPOINT(Attribute) (((Attribute) & (BIT0 | BIT1= )) =3D=3D USB_ENDPOINT_INTERRUPT) ///< Return TRUE/FALSE for INTERRUPT type + + +#define PRINT(_L_STR) (gST->ConOut->OutputString(gST->ConOut,(_L_STR))) +//------------------------------------------------------------------------= ------ +// Constants +//------------------------------------------------------------------------= ------ + +#define DEBUG_RX_BROADCAST 0x40000000 ///< Display RX broadcast messages +#define DEBUG_RX_MULTICAST 0x20000000 ///< Display RX multicast messages +#define DEBUG_RX_UNICAST 0x10000000 ///< Display RX unicast messages +#define DEBUG_MAC_ADDRESS 0x08000000 ///< Display the MAC address +#define DEBUG_LINK 0x04000000 ///< Display the link status +#define DEBUG_TX 0x02000000 ///< Display the TX messages +#define DEBUG_PHY 0x01000000 ///< Display the PHY register val= ues +#define DEBUG_SROM 0x00800000 ///< Display the SROM contents +#define DEBUG_TIMER 0x00400000 ///< Display the timer routine en= try/exit +#define DEBUG_TPL 0x00200000 ///< Display the timer routine en= try/exit + +#if RXTHOU +#define AX88772_MAX_BULKIN_SIZE 1024 * 17 //32 +#else +#define AX88772_MAX_BULKIN_SIZE 1024 * 3 +#endif + +#define AX88772_MAX_PKT_SIZE 2048 ///< Maximum packet size + +#define ETHERNET_HEADER_SIZE sizeof ( ETHERNET_HEADER ) ///< Size in by= tes of the Ethernet header +#define MIN_ETHERNET_PKT_SIZE 60 ///< Minimum packet size including Et= hernet header +#define MAX_ETHERNET_PKT_SIZE 1500 ///< Ethernet spec 3.1.1: Minimum pac= ket size + +#define USB_NETWORK_CLASS 0x09 ///< USB Network class code +#define USB_BUS_TIMEOUT 1000 ///< USB timeout in milliseconds + +#define TIMER_MSEC 20 ///< Polling interval for the= NIC +//#define TPL_AX88772 TPL_CALLBACK ///< TPL for routine synchr= onization + +#define HC_DEBUG 0 + +#if RXTHOU +#define BULKIN_TIMEOUT 3 //10 //100 //1000 +#else +#define BULKIN_TIMEOUT 3000 +#endif + +#define AUTONEG_DELAY 2000000 +#define AUTONEG_POLL_CNT 5 + +/** + Verify new TPL value + + This macro which is enabled when debug is enabled verifies that + the new TPL value is >=3D 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 =3D 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 <=3D tpl ); \ + } \ +} + +#else // MDEPKG_NDEBUG + +#define VERIFY_TPL(tpl) + +#endif // MDEPKG_NDEBUG + +//------------------------------------------------------------------------= ------ +// Hardware Definition +//------------------------------------------------------------------------= ------ + +#define FreeQueueSize 10 + +#define DEV_SIGNATURE SIGNATURE_32 ('A','X','8','8') ///< Signature = of data structures in memory + +#define VENDOR_ID 0x0B95 ///< Vendor ID for Asix +#define VENDOR_AX88772B_LENOVO_ID 0x17EF + + +/* Freddy */ +#define PRODUCT_ID 0x7720 ///< Product ID for the AX88772 USB 10/= 100 Ethernet controller +#define PRODUCT_AX88772A_ID 0x772A +#define PRODUCT_AX88772B_ID 0x772b +#define PRODUCT_AX88772B_ASUS_ID 0x7e2b +#define PRODUCT_AX88772B_LENOVO_ID 0x7203 +/* Freddy */ + + +#define RESET_MSEC 1000 ///< Reset duration +#define PHY_RESET_MSEC 500 ///< PHY reset duration + +// +// RX Control register +// + +#define RXC_PRO 0x0001 ///< Receive all packets +#define RXC_AMALL 0x0002 ///< Receive all multicast packets +#define RXC_SEP 0x0004 ///< Save error packets +#define RXC_AB 0x0008 ///< Receive broadcast packets +#define RXC_AM 0x0010 ///< Use multicast destination address = hash table +#define RXC_AP 0x0020 ///< Accept physical address from Multi= cast Filter +#define RXC_SO 0x0080 ///< Start operation +#define RXC_MFB 0x0300 ///< Maximum frame burst +#define RXC_MFB_2048 0 ///< Maximum frame size: 2048 bytes +#define RXC_MFB_4096 0x0100 ///< Maximum frame size: 4096 bytes +#define RXC_MFB_8192 0x0200 ///< Maximum frame size: 8192 bytes +#define RXC_MFB_16384 0x0300 ///< Maximum frame size: 16384 bytes + +/*Freddy*/ +#define RXC_RH1M 0x0100 ///< Rx header 1 +#define RXC_RH2M 0x0200 ///< Rx header 2 +#define RXC_RH3M 0x0400 ///< Rx header 3 +/*Freddy*/ + +// +// Medium Status register +// + +#define MS_FD 0x0002 ///< Full duplex +#define MS_ONE 0x0004 ///< Must be one +#define MS_RFC 0x0010 ///< RX flow control enable +#define MS_TFC 0x0020 ///< TX flow control enable +#define MS_PF 0x0080 ///< Pause frame enable +#define MS_RE 0x0100 ///< Receive enable +#define MS_PS 0x0200 ///< Port speed 1=3D100, 0=3D10 Mbps +#define MS_SBP 0x0800 ///< Stop back pressure +#define MS_SM 0x1000 ///< Super MAC support + +// +// Software PHY Select register +// + +#define SPHY_PSEL (1 << 0) ///< Select internal PHY +#define SPHY_SSMII (1 << 2) +#define SPHY_SSEN (1 << 4) +#define SPHY_ASEL 0x02 ///< 1=3DAuto select, 0=3DManual select + +// +// Software Reset register +// + +#define SRR_RR 0x01 ///< Clear receive frame length error +#define SRR_RT 0x02 ///< Clear transmit frame length error +#define SRR_BZTYPE 0x04 ///< External PHY reset pin tri-state e= nable +#define SRR_PRL 0x08 ///< External PHY reset pin level +#define SRR_BZ 0x10 ///< Force Bulk to return zero length p= acket +#define SRR_IPRL 0x20 ///< Internal PHY reset control +#define SRR_IPPD 0x40 ///< Internal PHY power down + +// +// PHY ID values +// + +#define PHY_ID_INTERNAL 0x0010 ///< Internal PHY + +// +// USB Commands +// + +#define CMD_PHY_ACCESS_SOFTWARE 0x06 ///< Software in control of PHY +#define CMD_PHY_REG_READ 0x07 ///< Read PHY register, Value: PH= Y, Index: Register, Data: Register value +#define CMD_PHY_REG_WRITE 0x08 ///< Write PHY register, Value: P= HY, 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: A= ddress, Data: Value +#define CMD_SROM_WRITE 0x0c ///< Read SROM register: Value: A= ddress, Data: Value +#define CMD_SROM_WRITE_EN 0x0d +#define CMD_SROM_WRITE_DIS 0x0e +#define CMD_RX_CONTROL_WRITE 0x10 ///< Set the RX control register,= Value: New value +#define CMD_GAPS_WRITE 0x12 ///< Write the gaps register, Val= ue: New value +#define CMD_MAC_ADDRESS_READ 0x13 ///< Read the MAC address, Data: = 6 byte MAC address +#define CMD_MAC_ADDRESS_WRITE 0x14 ///< Set the MAC address, Data: N= ew 6 byte MAC address +#define CMD_MULTICAST_HASH_READ 0x15 ///< Read the multicast hash table +#define CMD_MULTICAST_HASH_WRITE 0x16 ///< Write the multicast hash tab= le, Data: New 8 byte value +#define CMD_MEDIUM_STATUS_READ 0x1a ///< Read medium status register,= Data: Register value +#define CMD_MEDIUM_STATUS_WRITE 0x1b ///< Write medium status register= , Value: New value +#define CMD_WRITE_GPIOS 0x1f +#define CMD_RESET 0x20 ///< Reset register, Value: New v= alue +#define CMD_PHY_SELECT 0x22 ///< PHY select register, Value: = New value + +/*Freddy*/ +#define CMD_RXQTC 0x2a ///< RX Queue Cascade Threshold C= ontrol Register +/*Freddy*/ + +//------------------------------ +// USB Endpoints +//------------------------------ + +#define CONTROL_ENDPOINT 0 ///< Control endpoint +#define INTERRUPT_ENDPOINT 1 ///< Interrupt endpoint +#define BULK_IN_ENDPOINT 2 ///< Receive endpoint +#define BULK_OUT_ENDPOINT 3 ///< Transmit endpoint + +//------------------------------ +// PHY Registers +//------------------------------ + +#define PHY_BMCR 0 ///< Control register +#define PHY_BMSR 1 ///< Status register +#define PHY_ANAR 4 ///< Autonegotiation adve= rtisement register +#define PHY_ANLPAR 5 ///< Autonegotiation link= parter ability register +#define PHY_ANER 6 ///< Autonegotiation expa= nsion register + +// BMCR - Register 0 + +#define BMCR_RESET 0x8000 ///< 1 =3D Reset the PHY,= bit clears after reset +#define BMCR_LOOPBACK 0x4000 ///< 1 =3D Loopback enabl= ed +#define BMCR_100MBPS 0x2000 ///< 100 Mbits/Sec +#define BMCR_10MBPS 0 ///< 10 Mbits/Sec +#define BMCR_AUTONEGOTIATION_ENABLE 0x1000 ///< 1 =3D Enable autoneg= otiation +#define BMCR_POWER_DOWN 0x0800 ///< 1 =3D Power down +#define BMCR_ISOLATE 0x0400 ///< 0 =3D Isolate PHY +#define BMCR_RESTART_AUTONEGOTIATION 0x0200 ///< 1 =3D Restart autone= gotiation +#define BMCR_FULL_DUPLEX 0x0100 ///< Full duplex operation +#define BMCR_HALF_DUPLEX 0 ///< Half duplex operation +#define BMCR_COLLISION_TEST 0x0080 ///< 1 =3D Collision test= enabled + +// BSMR - Register 1 + +#define BMSR_100BASET4 0x8000 ///< 1 =3D 100BASE-T4 mode +#define BMSR_100BASETX_FDX 0x4000 ///< 1 =3D 100BASE-TX ful= l duplex +#define BMSR_100BASETX_HDX 0x2000 ///< 1 =3D 100BASE-TX hal= f duplex +#define BMSR_10BASET_FDX 0x1000 ///< 1 =3D 10BASE-T full = duplex +#define BMSR_10BASET_HDX 0x0800 ///< 1 =3D 10BASE-T half = duplex +#define BMSR_MF 0x0040 ///< 1 =3D PHY accepts fr= ames with preamble suppressed +#define BMSR_AUTONEG_CMPLT 0x0020 ///< 1 =3D Autonegotiatio= n complete +#define BMSR_RF 0x0010 ///< 1 =3D Remote fault +#define BMSR_AUTONEG 0x0008 ///< 1 =3D Able to perfor= m autonegotiation +#define BMSR_LINKST 0x0004 ///< 1 =3D Link up +#define BMSR_JABBER_DETECT 0x0002 ///< 1 =3D jabber conditi= on detected +#define BMSR_EXTENDED_CAPABILITY 0x0001 ///< 1 =3D Extended regis= ter capable + +// ANAR and ANLPAR Registers 4, 5 + +#define AN_NP 0x8000 ///< 1 =3D Next page avai= lable +#define AN_ACK 0x4000 ///< 1 =3D Link partner a= cknowledged +#define AN_RF 0x2000 ///< 1 =3D Remote fault i= ndicated by link partner +#define AN_FCS 0x0400 ///< 1 =3D Flow control a= bility +#define AN_T4 0x0200 ///< 1 =3D 100BASE-T4 sup= port +#define AN_TX_FDX 0x0100 ///< 1 =3D 100BASE-TX Ful= l duplex +#define AN_TX_HDX 0x0080 ///< 1 =3D 100BASE-TX sup= port +#define AN_10_FDX 0x0040 ///< 1 =3D 10BASE-T Full = duplex +#define AN_10_HDX 0x0020 ///< 1 =3D 10BASE-T suppo= rt +#define AN_CSMA_CD 0x0001 ///< 1 =3D IEEE 802.3 CSM= A/CD support + + + +//------------------------------------------------------------------------= ------ +// Data Types +//------------------------------------------------------------------------= ------ + +/** + Ethernet header layout + + IEEE 802.3-2002 Part 3 specification, section 3.1.1. +**/ +#pragma pack(1) +typedef struct { + UINT8 dest_addr[PXE_HWADDR_LEN_ETHER]; ///< Destination LAN address + UINT8 src_addr[PXE_HWADDR_LEN_ETHER]; ///< Source LAN address + UINT16 type; ///< Protocol or length +} ETHERNET_HEADER; +#pragma pack() + +/** + Receive and Transmit packet structure +**/ +#pragma pack(1) +typedef struct _RX_TX_PACKET { + struct _RX_TX_PACKET * pNext; ///< Next receive packet + UINT16 Length; ///< Packet length + UINT16 LengthBar; ///< Complement of the length + UINT8 Data[ AX88772_MAX_PKT_SIZE ]; ///< Received packet data +} RX_TX_PACKET; +#pragma pack() + +/** + AX88772 control structure + + The driver uses this structure to manage the Asix AX88772 10/100 + Ethernet controller. +**/ +typedef struct { + UINTN Signature; ///< Structure identification + + // + // USB data + // + EFI_HANDLE Controller; ///< Controller handle + EFI_USB_IO_PROTOCOL * pUsbIo; ///< USB driver interface + + // + // Simple network protocol data + // + EFI_SIMPLE_NETWORK_PROTOCOL SimpleNetwork; ///< Driver's network stack= interface + EFI_SIMPLE_NETWORK_MODE SimpleNetworkData; ///< Data for simple network + + // + // Ethernet controller data + // + BOOLEAN bInitialized; ///< Controller initialized + UINT16 PhyId; ///< PHY ID + + // + // Link state + // + BOOLEAN b100Mbps; ///< Current link speed, FALSE =3D 10 Mbps + BOOLEAN bComplete; ///< Current state of auto-negotiation + BOOLEAN bFullDuplex; ///< Current duplex + BOOLEAN bLinkUp; ///< Current link state + UINTN PollCount; ///< Number of times the autonegotiation stat= us was polled + UINT16 CurRxControl; + VOID * pTxBuffer; + // + // Receive buffer list + // + UINT8 *pBulkInbuf; + UINT8 * pCurPktHdrOff; + UINT8 *pCurPktOff; + UINT16 PktCnt; + + RX_TX_PACKET * pTxTest; + + UINT8 MulticastHash[8]; + EFI_MAC_ADDRESS MAC; + + EFI_DEVICE_PATH_PROTOCOL *MyDevPath; + BOOLEAN Grub_f; + BOOLEAN bFirstRst; + BOOLEAN Flag772A; +#if RXTHOU + UINT8 rxburst; +#endif + +} NIC_DEVICE; + + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gComponentName2; + +#define DEV_FROM_SIMPLE_NETWORK(a) CR (a, NIC_DEVICE, SimpleNetwork, DEV_= SIGNATURE) ///< Locate NIC_DEVICE from Simple Network Protocol + +//------------------------------------------------------------------------= ------ +// Simple Network Protocol +//------------------------------------------------------------------------= ------ + +/** + Reset the network adapter. + + Resets a network adapter and reinitializes it with the parameters that + were provided in the previous call to Initialize (). The transmit and + receive queues are cleared. Receive filters, the station address, the + statistics, and the multicast-IP-to-HW MAC addresses are not reset by + this call. + + This routine calls ::Ax88772Reset to perform the adapter specific + reset operation. This routine also starts the link negotiation + by calling ::Ax88772NegotiateLinkStart. + + @param [in] pSimpleNetwork Protocol instance pointer + @param [in] bExtendedVerification Indicates that the driver may perform= a more + exhaustive verification operation of the d= evice + 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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +EFI_STATUS +EFIAPI +SN_Reset ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + IN BOOLEAN bExtendedVerification + ); + +/** + Initialize the simple network protocol. + + This routine calls ::Ax88772MacAddressGet to obtain the + MAC address. + + @param [in] pNicDevice NIC_DEVICE_INSTANCE pointer + + @retval EFI_SUCCESS Setup was successful + +**/ +EFI_STATUS +SN_Setup ( + IN NIC_DEVICE * pNicDevice + ); + +/** + This routine starts the network interface. + + @param [in] pSimpleNetwork Protocol instance pointer + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_ALREADY_STARTED The network interface was already started. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +EFI_STATUS +EFIAPI +SN_Start ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork + ); + +/** + Set the MAC address. + + This function modifies or resets the current station address of a + network interface. If Reset is TRUE, then the current station address + is set ot the network interface's permanent address. If Reset if FALSE + then the current station address is changed to the address specified by + pNew. + + This routine calls ::Ax88772MacAddressSet to update the MAC address + in the network adapter. + + @param [in] pSimpleNetwork Protocol instance pointer + @param [in] bReset Flag used to reset the station address to = the + network interface's permanent address. + @param [in] pNew New station address to be used for the net= work + 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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +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 th= e network interface. + @param [in, out] pStatisticsSize On input the size, in bytes, of Statis= ticsTable. On output + the size, in bytes, of the resulting table= of statistics. + @param [out] pStatisticsTable A pointer to the EFI_NETWORK_STATISTICS st= ructure 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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +EFI_STATUS +EFIAPI +SN_Stop ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork + ); + +/** + This function releases the memory buffers assigned in the Initialize() c= all. + 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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +EFI_STATUS +EFIAPI +SN_Shutdown ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork + ); + +/** + Send a packet over the network. + + This function places the packet specified by Header and Buffer on + the transmit queue. This function performs a non-blocking transmit + operation. When the transmit is complete, the buffer is returned + via the GetStatus() call. + + This routine calls ::Ax88772Rx to empty the network adapter of + receive packets. The routine then passes the transmit packet + to the network adapter. + + @param [in] pSimpleNetwork Protocol instance pointer + @param [in] HeaderSize The size, in bytes, of the media header to= be filled in by + the Transmit() function. If HeaderSize is= non-zero, then + it must be equal to SimpleNetwork->Mode->M= ediaHeaderSize + 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 networ= k interface. + @param [in] pBuffer A pointer to the packet (media header foll= owed 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 He= aderSize 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 Header= Size is zero, then + this parameter is ignored. + @param [in] pProtocol The type of header to build. If HeaderSiz= e 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 accep= t this transmit request. + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + +**/ +EFI_STATUS +EFIAPI +SN_Transmit ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + IN UINTN HeaderSize, + IN UINTN BufferSize, + IN VOID * pBuffer, + IN EFI_MAC_ADDRESS * pSrcAddr, + IN EFI_MAC_ADDRESS * pDestAddr, + IN UINT16 * pProtocol + ); + +//------------------------------------------------------------------------= ------ +// Support Routines +//------------------------------------------------------------------------= ------ + +/** + Get the MAC address + + This routine calls ::Ax88772UsbCommand to request the MAC + address from the network adapter. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [out] pMacAddress Address of a six byte buffer to receive th= e MAC address. + + @retval EFI_SUCCESS The MAC address is available. + @retval other The MAC address is not valid. + +**/ +EFI_STATUS +Ax88772MacAddressGet ( + IN NIC_DEVICE * pNicDevice, + OUT UINT8 * pMacAddress + ); + +/** + Set the MAC address + + This routine calls ::Ax88772UsbCommand to set the MAC address + in the network adapter. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] pMacAddress Address of a six byte buffer to containing = the new MAC address. + + @retval EFI_SUCCESS The MAC address was set. + @retval other The MAC address was not set. + +**/ +EFI_STATUS +Ax88772MacAddressSet ( + IN NIC_DEVICE * pNicDevice, + IN UINT8 * pMacAddress + ); + +/** + Clear the multicast hash table + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + +**/ +VOID +Ax88772MulticastClear ( + IN NIC_DEVICE * pNicDevice + ); + +/** + Enable a multicast address in the multicast hash table + + This routine calls ::Ax88772Crc to compute the hash bit for + this MAC address. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] pMacAddress Address of a six byte buffer to containing = the MAC address. + +**/ +VOID +Ax88772MulticastSet ( + IN NIC_DEVICE * pNicDevice, + IN UINT8 * pMacAddress + ); + +/** + Start the link negotiation + + This routine calls ::Ax88772PhyWrite to start the PHY's link + negotiation. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + + @retval EFI_SUCCESS The link negotiation was started. + @retval other Failed to start the link negotiation. + +**/ +EFI_STATUS +Ax88772NegotiateLinkStart ( + IN NIC_DEVICE * pNicDevice + ); + +/** + Complete the negotiation of the PHY link + + This routine calls ::Ax88772PhyRead to determine if the + link negotiation is complete. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in, out] pPollCount Address of number of times this routine was= polled + @param [out] pbComplete Address of boolean to receive complate stat= us. + @param [out] pbLinkUp Address of boolean to receive link status, = TRUE=3Dup. + @param [out] pbHiSpeed Address of boolean to receive link speed, T= RUE=3D100Mbps. + @param [out] pbFullDuplex Address of boolean to receive link duplex, = TRUE=3Dfull. + + @retval EFI_SUCCESS The MAC address is available. + @retval other The MAC address is not valid. + +**/ +EFI_STATUS +Ax88772NegotiateLinkComplete ( + IN NIC_DEVICE * pNicDevice, + IN OUT UINTN * pPollCount, + OUT BOOLEAN * pbComplete, + OUT BOOLEAN * pbLinkUp, + OUT BOOLEAN * pbHiSpeed, + OUT BOOLEAN * pbFullDuplex + ); + +/** + Read a register from the PHY + + This routine calls ::Ax88772UsbCommand to read a PHY register. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] RegisterAddress Number of the register to read. + @param [in, out] pPhyData Address of a buffer to receive the PHY regi= ster value + + @retval EFI_SUCCESS The PHY data is available. + @retval other The PHY data is not valid. + +**/ +EFI_STATUS +Ax88772PhyRead ( + IN NIC_DEVICE * pNicDevice, + IN UINT8 RegisterAddress, + IN OUT UINT16 * pPhyData + ); + +/** + Write to a PHY register + + This routine calls ::Ax88772UsbCommand to write a PHY register. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] RegisterAddress Number of the register to read. + @param [in] PhyData Address of a buffer to receive the PHY regi= ster value + + @retval EFI_SUCCESS The PHY data was written. + @retval other Failed to wwrite the PHY register. + +**/ +EFI_STATUS +Ax88772PhyWrite ( + IN NIC_DEVICE * pNicDevice, + IN UINT8 RegisterAddress, + IN UINT16 PhyData + ); + +/** + Reset the AX88772 + + This routine uses ::Ax88772UsbCommand to reset the network + adapter. This routine also uses ::Ax88772PhyWrite to reset + the PHY. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + + @retval EFI_SUCCESS The MAC address is available. + @retval other The MAC address is not valid. + +**/ +EFI_STATUS +Ax88772Reset ( + IN NIC_DEVICE * pNicDevice + ); + +VOID +Ax88772ChkLink ( + IN NIC_DEVICE * pNicDevice, + IN BOOLEAN bUpdateLink + ); + +/** + Receive a frame from the network. + + This routine polls the USB receive interface for a packet. If a packet + is available, this routine adds the receive packet to the list of + pending receive packets. + + This routine calls ::Ax88772NegotiateLinkComplete to verify + that the link is up. This routine also calls ::SN_Reset to + reset the network adapter when necessary. Finally this + routine attempts to receive one or more packets from the + network adapter. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] bUpdateLink TRUE =3D Update link status + +**/ +VOID +Ax88772Rx ( + IN NIC_DEVICE * pNicDevice, + IN BOOLEAN bUpdateLink + ); + +/** + Enable or disable the receiver + + This routine calls ::Ax88772UsbCommand to update the + receiver state. This routine also calls ::Ax88772MacAddressSet + to establish the MAC address for the network adapter. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] RxFilter Simple network RX filter mask value + + @retval EFI_SUCCESS The MAC address was set. + @retval other The MAC address was not set. + +**/ +EFI_STATUS +Ax88772RxControl ( + IN NIC_DEVICE * pNicDevice, + IN UINT32 RxFilter + ); + +EFI_STATUS +Ax88772ReloadSrom ( + IN NIC_DEVICE * pNicDevice + ); + +/** + Read an SROM location + + This routine calls ::Ax88772UsbCommand to read data from the + SROM. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] Address SROM address + @param [out] pData Buffer to receive the data + + @retval EFI_SUCCESS The read was successful + @retval other The read failed + +**/ +EFI_STATUS +Ax88772SromRead ( + IN NIC_DEVICE * pNicDevice, + IN UINT32 Address, + OUT UINT16 * pData + ); + + +EFI_STATUS +Ax88772EnableSromWrite ( + IN NIC_DEVICE * pNicDevice + ); + + +EFI_STATUS +Ax88772DisableSromWrite ( + IN NIC_DEVICE * pNicDevice + ); + +EFI_STATUS +Ax88772SromWrite ( + IN NIC_DEVICE * pNicDevice, + IN UINT32 Address, + OUT UINT16 * pData + ); +#if 0 +/** + This routine is called at a regular interval to poll for + receive packets. + + This routine polls the link state and gets any receive packets + by calling ::Ax88772Rx. + + @param [in] Event Timer event + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + +**/ +VOID +Ax88772Timer ( + IN EFI_EVENT Event, + IN NIC_DEVICE * pNicDevice + ); +#endif +/** + Send a command to the USB device. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] pRequest Pointer to the request structure + @param [in, out] pBuffer Data buffer address + + @retval EFI_SUCCESS The USB transfer was successful + @retval other The USB transfer failed + +**/ +EFI_STATUS +Ax88772UsbCommand ( + IN NIC_DEVICE * pNicDevice, + IN USB_DEVICE_REQUEST * pRequest, + IN OUT VOID * pBuffer + ); + +BOOLEAN +Ax88772GetLinkStatus ( + IN NIC_DEVICE * pNicDevice +) ; + +//------------------------------------------------------------------------= ------ +// EFI Component Name Protocol Support +//------------------------------------------------------------------------= ------ + +extern EFI_COMPONENT_NAME_PROTOCOL gComponentName; ///< Component name= protocol declaration +extern EFI_COMPONENT_NAME2_PROTOCOL gComponentName2; ///< Component name= 2 protocol declaration + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form o= f 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 speci= fied + 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_PROTO= COL 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 calle= r 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 for= mat. + @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 specifie= d by + This and the language specified by Languag= e 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 supp= ort + 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 control= ler + that is being managed by a driver. + + This function retrieves the user readable name of the controller specifi= ed 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 specif= ied by + Language, then a pointer to the controller name is returned in Controlle= rName, + and EFI_SUCCESS is returned. If the driver specified by This is not cur= rently + 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 retu= rned. + + @param [in] pThis A pointer to the EFI_COMPONENT_NAME2_PROTO= COL 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 retr= ieve + the name of. This is an optional paramete= r that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus d= rivers + 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 calle= r 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 specifie= d 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 a= nd + ChildHandle in the language specified by + Language from the point of view of the dri= ver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable n= ame 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 va= lid + 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 curren= tly + managing the controller specified by + ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +GetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL * pThis, + IN EFI_HANDLE ControllerHandle, + IN OPTIONAL EFI_HANDLE ChildHandle, + IN CHAR8 * pLanguage, + OUT CHAR16 ** ppControllerName + ); + + +EFI_STATUS +Ax88772BulkIn( + IN NIC_DEVICE * pNicDevice +); + +//------------------------------------------------------------------------= ------ + +#endif // _AX88772_H_ diff --git a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.c = b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.c new file mode 100644 index 000000000000..a905dc548197 --- /dev/null +++ b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/Ax88772.c @@ -0,0 +1,1296 @@ +/** @file + Implement the interface to the AX88772 Ethernet controller. + + This module implements the interface to the ASIX AX88772 + USB to Ethernet MAC with integrated 10/100 PHY. Note that this implemen= tation + only supports the integrated PHY since no other test cases were availabl= e. + + Copyright (c) 2011, Intel Corporation. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Ax88772.h" + + +/** + Compute the CRC + + @param [in] pMacAddress Address of a six byte buffer to containing = the MAC address. + + @returns The CRC-32 value associated with this MAC address + +**/ +UINT32 +Ax88772Crc ( + IN UINT8 * pMacAddress + ) +{ + UINT32 BitNumber; + INT32 Carry; + INT32 Crc; + UINT32 Data; + UINT8 * pEnd; + + // + // Walk the MAC address + // + Crc =3D -1; + pEnd =3D &pMacAddress[ PXE_HWADDR_LEN_ETHER ]; + while ( pEnd > pMacAddress ) { + Data =3D *pMacAddress++; + + + // + // CRC32: x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x= 5 + x4 + x2 + x + 1 + // + // 1 0000 0100 1100 0001 0001 1101 1011 0111 + // + for ( BitNumber =3D 0; 8 > BitNumber; BitNumber++ ) { + Carry =3D (( Crc >> 31 ) & 1 ) ^ ( Data & 1 ); + Crc <<=3D 1; + if ( 0 !=3D Carry ) { + Crc ^=3D 0x04c11db7; + } + Data >>=3D 1; + } + } + + // + // Return the CRC value + // + + return (UINT32) Crc; +} + + +/** + Get the MAC address + + This routine calls ::Ax88772UsbCommand to request the MAC + address from the network adapter. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [out] pMacAddress Address of a six byte buffer to receive th= e MAC address. + + @retval EFI_SUCCESS The MAC address is available. + @retval other The MAC address is not valid. + +**/ +EFI_STATUS +Ax88772MacAddressGet ( + IN NIC_DEVICE * pNicDevice, + OUT UINT8 * pMacAddress + ) +{ + USB_DEVICE_REQUEST SetupMsg; + EFI_STATUS Status; + + // + // Set the register address. + // + SetupMsg.RequestType =3D USB_ENDPOINT_DIR_IN + | USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_MAC_ADDRESS_READ; + SetupMsg.Value =3D 0; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D PXE_HWADDR_LEN_ETHER; + + // + // Read the PHY register + // + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + pMacAddress ); + + // + // Return the operation status + // + return Status; +} + + +/** + Set the MAC address + + This routine calls ::Ax88772UsbCommand to set the MAC address + in the network adapter. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] pMacAddress Address of a six byte buffer to containing = the new MAC address. + + @retval EFI_SUCCESS The MAC address was set. + @retval other The MAC address was not set. + +**/ +EFI_STATUS +Ax88772MacAddressSet ( + IN NIC_DEVICE * pNicDevice, + IN UINT8 * pMacAddress + ) +{ + USB_DEVICE_REQUEST SetupMsg; + EFI_STATUS Status; + + // + // Set the register address. + // + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_MAC_ADDRESS_WRITE; + SetupMsg.Value =3D 0; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D PXE_HWADDR_LEN_ETHER; + + // + // Read the PHY register + // + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + pMacAddress ); + + // + // Return the operation status + // + return Status; +} + +/** + Clear the multicast hash table + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + +**/ +VOID +Ax88772MulticastClear ( + IN NIC_DEVICE * pNicDevice + ) +{ + int i =3D 0; + // + // Clear the multicast hash table + // + for ( i =3D 0 ; i < 8 ; i ++ ) + pNicDevice->MulticastHash[i] =3D 0; +} + + +/** + Enable a multicast address in the multicast hash table + + This routine calls ::Ax88772Crc to compute the hash bit for + this MAC address. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] pMacAddress Address of a six byte buffer to containing = the MAC address. + +**/ +VOID +Ax88772MulticastSet ( + IN NIC_DEVICE * pNicDevice, + IN UINT8 * pMacAddress + ) +{ + UINT32 Crc; + + // + // Compute the CRC on the destination address + // + Crc =3D Ax88772Crc ( pMacAddress ) >> 26; + + // + // Set the bit corresponding to the destination address + // + pNicDevice->MulticastHash [ Crc >> 3 ] |=3D ( 1<< (Crc& 7)); + +} + +/** + Start the link negotiation + + This routine calls ::Ax88772PhyWrite to start the PHY's link + negotiation. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + + @retval EFI_SUCCESS The link negotiation was started. + @retval other Failed to start the link negotiation. + +**/ +EFI_STATUS +Ax88772NegotiateLinkStart ( + IN NIC_DEVICE * pNicDevice + ) +{ + UINT16 Control; + EFI_STATUS Status; + + // + // Set the supported capabilities. + // + Status =3D Ax88772PhyWrite ( pNicDevice, + PHY_ANAR, + AN_CSMA_CD + | AN_TX_FDX | AN_TX_HDX + | AN_10_FDX | AN_10_HDX | AN_FCS ); + if ( !EFI_ERROR ( Status )) { + // + // Set the link speed and duplex + // + Control =3D BMCR_AUTONEGOTIATION_ENABLE + | BMCR_RESTART_AUTONEGOTIATION; + if ( pNicDevice->b100Mbps ) { + Control |=3D BMCR_100MBPS; + } + if ( pNicDevice->bFullDuplex ) { + Control |=3D BMCR_FULL_DUPLEX; + } + Status =3D Ax88772PhyWrite ( pNicDevice, PHY_BMCR, Control ); + + if (!EFI_ERROR(Status)) + gBS->Stall(3000000); + } + return Status; +} + + + +/** + Complete the negotiation of the PHY link + + This routine calls ::Ax88772PhyRead to determine if the + link negotiation is complete. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in, out] pPollCount Address of number of times this routine was= polled + @param [out] pbComplete Address of boolean to receive complate stat= us. + @param [out] pbLinkUp Address of boolean to receive link status, = TRUE=3Dup. + @param [out] pbHiSpeed Address of boolean to receive link speed, T= RUE=3D100Mbps. + @param [out] pbFullDuplex Address of boolean to receive link duplex, = TRUE=3Dfull. + + @retval EFI_SUCCESS The MAC address is available. + @retval other The MAC address is not valid. + +**/ +EFI_STATUS +Ax88772NegotiateLinkComplete ( + IN NIC_DEVICE * pNicDevice, + IN OUT UINTN * pPollCount, + OUT BOOLEAN * pbComplete, + OUT BOOLEAN * pbLinkUp, + OUT BOOLEAN * pbHiSpeed, + OUT BOOLEAN * pbFullDuplex + ) +{ + UINT16 Mask; + UINT16 PhyData; + EFI_STATUS Status; + + // + // Determine if the link is up. + // + *pbComplete =3D FALSE; + + // + // Get the link status + // + Status =3D Ax88772PhyRead ( pNicDevice, + PHY_BMSR, + &PhyData ); + + if ( !EFI_ERROR ( Status )) { + *pbLinkUp =3D (BOOLEAN)( 0 !=3D ( PhyData & BMSR_LINKST )); + if ( 0 =3D=3D *pbLinkUp ) { + } else { + *pbComplete =3D (BOOLEAN)( 0 !=3D ( PhyData & 0x20 )); + if ( 0 =3D=3D *pbComplete ) { + } else { + Status =3D Ax88772PhyRead ( pNicDevice, + PHY_ANLPAR, + &PhyData ); + if ( !EFI_ERROR ( Status )) { + // + // Autonegotiation is complete + // Determine the link speed. + // + *pbHiSpeed =3D (BOOLEAN)( 0 !=3D ( PhyData & ( AN_TX_FDX | AN_TX= _HDX ))); + + // + // Determine the link duplex. + // + Mask =3D ( *pbHiSpeed ) ? AN_TX_FDX : AN_10_FDX; + *pbFullDuplex =3D (BOOLEAN)( 0 !=3D ( PhyData & Mask )); + } + } + } + } else { + } + return Status; +} + + +/** + Read a register from the PHY + + This routine calls ::Ax88772UsbCommand to read a PHY register. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] RegisterAddress Number of the register to read. + @param [in, out] pPhyData Address of a buffer to receive the PHY regi= ster value + + @retval EFI_SUCCESS The PHY data is available. + @retval other The PHY data is not valid. + +**/ +EFI_STATUS +Ax88772PhyRead ( + IN NIC_DEVICE * pNicDevice, + IN UINT8 RegisterAddress, + IN OUT UINT16 * pPhyData + ) +{ + USB_DEVICE_REQUEST SetupMsg; + EFI_STATUS Status; + + // + // Request access to the PHY + // + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_PHY_ACCESS_SOFTWARE; + SetupMsg.Value =3D 0; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D 0; + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + if ( !EFI_ERROR ( Status )) { + // + // Read the PHY register address. + // + SetupMsg.RequestType =3D USB_ENDPOINT_DIR_IN + | USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_PHY_REG_READ; + SetupMsg.Value =3D pNicDevice->PhyId; + SetupMsg.Index =3D RegisterAddress; + SetupMsg.Length =3D sizeof ( *pPhyData ); + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + pPhyData ); + if ( !EFI_ERROR ( Status )) { + + // + // Release the PHY to the hardware + // + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_PHY_ACCESS_HARDWARE; + SetupMsg.Value =3D 0; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D 0; + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + } + } + + // + // Return the operation status. + // + return Status; +} + + +/** + Write to a PHY register + + This routine calls ::Ax88772UsbCommand to write a PHY register. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] RegisterAddress Number of the register to read. + @param [in] PhyData Address of a buffer to receive the PHY regi= ster value + + @retval EFI_SUCCESS The PHY data was written. + @retval other Failed to wwrite the PHY register. + +**/ +EFI_STATUS +Ax88772PhyWrite ( + IN NIC_DEVICE * pNicDevice, + IN UINT8 RegisterAddress, + IN UINT16 PhyData + ) +{ + USB_DEVICE_REQUEST SetupMsg; + EFI_STATUS Status; + + // + // Request access to the PHY + // + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_PHY_ACCESS_SOFTWARE; + SetupMsg.Value =3D 0; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D 0; + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + if ( !EFI_ERROR ( Status )) { + // + // Write the PHY register + // + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_PHY_REG_WRITE; + SetupMsg.Value =3D pNicDevice->PhyId; + SetupMsg.Index =3D RegisterAddress; + SetupMsg.Length =3D sizeof ( PhyData ); + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + &PhyData ); + if ( !EFI_ERROR ( Status )) { + + // + // Release the PHY to the hardware + // + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_PHY_ACCESS_HARDWARE; + SetupMsg.Value =3D 0; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D 0; + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + } + } + + // + // Return the operation status. + // + return Status; +} + + +/** + Reset the AX88772 + + This routine uses ::Ax88772UsbCommand to reset the network + adapter. This routine also uses ::Ax88772PhyWrite to reset + the PHY. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + + @retval EFI_SUCCESS The MAC address is available. + @retval other The MAC address is not valid. + +**/ +EFI_STATUS +Ax88772Reset ( + IN NIC_DEVICE * pNicDevice + ) +{ + USB_DEVICE_REQUEST SetupMsg; + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *pUsbIo; + + pUsbIo =3D pNicDevice->pUsbIo; + + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_PHY_ACCESS_HARDWARE; + SetupMsg.Value =3D 0; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D 0; + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + + if (EFI_ERROR(Status)) goto err; + + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_PHY_SELECT; + SetupMsg.Value =3D SPHY_PSEL; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D 0; + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + + if (EFI_ERROR(Status)) goto err; + + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_RESET; + SetupMsg.Value =3D SRR_IPRL ; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D 0; + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + + if (EFI_ERROR(Status)) goto err; + + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_RESET; + SetupMsg.Value =3D SRR_IPPD | SRR_IPRL ; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D 0; + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + + gBS->Stall ( 200000 ); + + if (EFI_ERROR(Status)) goto err; + + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_RESET; + SetupMsg.Value =3D SRR_IPRL ; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D 0; + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + + gBS->Stall ( 200000 ); + + if (EFI_ERROR(Status)) goto err; + + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_RESET; + SetupMsg.Value =3D 0; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D 0; + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + + if (EFI_ERROR(Status)) goto err; + + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_PHY_SELECT; + SetupMsg.Value =3D SPHY_PSEL; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D 0; + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + + if (EFI_ERROR(Status)) goto err; + + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_RESET; + SetupMsg.Value =3D SRR_IPRL | SRR_BZ | SRR_BZTYPE; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D 0; + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + + if (EFI_ERROR(Status)) goto err; + + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_RX_CONTROL_WRITE; + SetupMsg.Value =3D 0; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D 0; + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + + if (EFI_ERROR(Status)) goto err; + + if (!pNicDevice->Flag772A) { + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_RXQTC; +#if RXTHOU + /*size cannot exceed 3K*/ + //SetupMsg.Value =3D 0x0; + //SetupMsg.Index =3D 0x8001; + /*size cannot exceed 16K*/ + SetupMsg.Value =3D 0x8300; + SetupMsg.Index =3D 0x8500; + /*size cannot exceed 32K*/ + //SetupMsg.Value =3D 0x8784; + //SetupMsg.Index =3D 0x8A00; + SetupMsg.Length =3D 0; +#else + SetupMsg.Value =3D 0x8000; + SetupMsg.Index =3D 0x8001; +#endif + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + } +err: + return Status; +} + +/** + Enable or disable the receiver + + This routine calls ::Ax88772UsbCommand to update the + receiver state. This routine also calls ::Ax88772MacAddressSet + to establish the MAC address for the network adapter. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] RxFilter Simple network RX filter mask value + + @retval EFI_SUCCESS The MAC address was set. + @retval other The MAC address was not set. + +**/ +EFI_STATUS +Ax88772RxControl ( + IN NIC_DEVICE * pNicDevice, + IN UINT32 RxFilter + ) +{ + UINT16 MediumStatus; + UINT16 RxControl; + USB_DEVICE_REQUEST SetupMsg; + EFI_STATUS Status =3D EFI_SUCCESS; + + // + // Enable the receiver if something is to be received + // + if ( 0 !=3D RxFilter ) { + // + // Enable the receiver + // + SetupMsg.RequestType =3D USB_ENDPOINT_DIR_IN + | USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_MEDIUM_STATUS_READ; + SetupMsg.Value =3D 0; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D sizeof ( MediumStatus ); + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + &MediumStatus ); + if ( !EFI_ERROR ( Status )) { + if ( 0 =3D=3D ( MediumStatus & MS_RE )) { + MediumStatus |=3D MS_RE | MS_ONE; + + if ( pNicDevice->bFullDuplex ) + MediumStatus |=3D MS_TFC | MS_RFC | MS_FD; + else + MediumStatus &=3D ~(MS_TFC | MS_RFC | MS_FD); + + if ( pNicDevice->b100Mbps ) + MediumStatus |=3D MS_PS; + else + MediumStatus &=3D ~MS_PS; + + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_MEDIUM_STATUS_WRITE; + SetupMsg.Value =3D MediumStatus; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D 0; + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + + if (EFI_ERROR(Status)) + goto EXIT; + } + } else { + goto EXIT; + } + } + RxControl =3D RXC_SO; + if (!pNicDevice->Flag772A) + RxControl |=3D RXC_RH1M; + + // + // Enable multicast if requested + // + if ( 0 !=3D ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST )) { + RxControl |=3D RXC_AM; + // + // Update the multicast hash table + // + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_MULTICAST_HASH_WRITE; + SetupMsg.Value =3D 0; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D sizeof ( pNicDevice ->MulticastHash ); + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + &pNicDevice->MulticastHash ); + + if (EFI_ERROR(Status)) + goto EXIT; + } + + // + // Enable all multicast if requested + // + if ( 0 !=3D ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAS= T )) { + RxControl |=3D RXC_AMALL; + } + + // + // Enable broadcast if requested + // + if ( 0 !=3D ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST )) { + RxControl |=3D RXC_AB; + } + + // + // Enable promiscuous mode if requested + // + if ( 0 !=3D ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS )) { + RxControl |=3D RXC_PRO; + } + + // + // Update the receiver control + // + if (pNicDevice->CurRxControl !=3D RxControl) { + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_RX_CONTROL_WRITE; +#if RXTHOU + if (pNicDevice->Flag772A) + RxControl |=3D 0x0300; +#endif + if (pNicDevice->Flag772A) + RxControl &=3D ~(RXC_MFB); + SetupMsg.Value =3D RxControl; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D 0; + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + if ( !EFI_ERROR ( Status )) + pNicDevice->CurRxControl =3D RxControl; + } + + // + // Return the operation status + // +EXIT: + return Status; +} + + + +EFI_STATUS +Ax88772ReloadSrom ( + IN NIC_DEVICE * pNicDevice + ) +{ + USB_DEVICE_REQUEST SetupMsg; + EFI_STATUS Status; + + // + // Read a value from the SROM + // + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + + SetupMsg.Request =3D CMD_WRITE_GPIOS; + SetupMsg.Value =3D 0x80; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D 0 ; + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + + if (EFI_SUCCESS =3D=3D Status) + gBS->Stall(500000); + + return Status; + +} + + +/** + Read an SROM location + + This routine calls ::Ax88772UsbCommand to read data from the + SROM. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] Address SROM address + @param [out] pData Buffer to receive the data + + @retval EFI_SUCCESS The read was successful + @retval other The read failed + +**/ +EFI_STATUS +Ax88772SromRead ( + IN NIC_DEVICE * pNicDevice, + IN UINT32 Address, + OUT UINT16 * pData + ) +{ + + USB_DEVICE_REQUEST SetupMsg; + EFI_STATUS Status; + + // + // Read a value from the SROM + // + SetupMsg.RequestType =3D USB_ENDPOINT_DIR_IN + | USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_SROM_READ; + SetupMsg.Value =3D (UINT16) Address; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D sizeof ( *pData ); + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + pData ); + + // + // Return the operation status + // + return Status; +} + +EFI_STATUS +Ax88772EnableSromWrite ( + IN NIC_DEVICE * pNicDevice + ) +{ + USB_DEVICE_REQUEST SetupMsg; + EFI_STATUS Status; + + // + // Read a value from the SROM + // + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + + SetupMsg.Request =3D CMD_SROM_WRITE_EN; + SetupMsg.Value =3D 0; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D 0 ; + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + + if (EFI_SUCCESS =3D=3D Status) + gBS->Stall(500000); + + return Status; + +} + + +EFI_STATUS +Ax88772DisableSromWrite ( + IN NIC_DEVICE * pNicDevice + ) +{ + USB_DEVICE_REQUEST SetupMsg; + EFI_STATUS Status; + + // + // Read a value from the SROM + // + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + + SetupMsg.Request =3D CMD_SROM_WRITE_DIS; + SetupMsg.Value =3D 0; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D 0; + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + + if (EFI_SUCCESS =3D=3D Status) + gBS->Stall(500000); + + return Status; + +} + +/** + Write an SROM location + + This routine calls ::Ax88772UsbCommand to write data from the + SROM. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] Address SROM address + @param [out] pData Buffer of data to write + + @retval EFI_SUCCESS The write was successful + @retval other The write failed + +**/ +EFI_STATUS +Ax88772SromWrite ( + IN NIC_DEVICE * pNicDevice, + IN UINT32 Address, + IN UINT16 * pData + ) +{ + + USB_DEVICE_REQUEST SetupMsg; + EFI_STATUS Status; + + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + + SetupMsg.Request =3D CMD_SROM_WRITE; + SetupMsg.Value =3D (UINT16) Address; + SetupMsg.Index =3D (UINT16) (*pData); + SetupMsg.Length =3D 0; + + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + + // + // Return the operation status + // + return Status; +} + +/** + Send a command to the USB device. + + @param [in] pNicDevice Pointer to the NIC_DEVICE structure + @param [in] pRequest Pointer to the request structure + @param [in, out] pBuffer Data buffer address + + @retval EFI_SUCCESS The USB transfer was successful + @retval other The USB transfer failed + +**/ +EFI_STATUS +Ax88772UsbCommand ( + IN NIC_DEVICE * pNicDevice, + IN USB_DEVICE_REQUEST * pRequest, + IN OUT VOID * pBuffer + ) +{ + UINT32 CmdStatus; + EFI_USB_DATA_DIRECTION Direction; + EFI_USB_IO_PROTOCOL * pUsbIo; + EFI_STATUS Status; + + // + // Determine the transfer direction + // + Direction =3D EfiUsbNoData; + if ( 0 !=3D pRequest->Length ) { + Direction =3D ( 0 !=3D ( pRequest->RequestType & USB_ENDPOINT_DIR_IN )) + ? EfiUsbDataIn : EfiUsbDataOut; + } + + // + // Issue the command + // + pUsbIo =3D pNicDevice->pUsbIo; + Status =3D pUsbIo->UsbControlTransfer ( pUsbIo, + pRequest, + Direction, + USB_BUS_TIMEOUT, + pBuffer, + pRequest->Length, + &CmdStatus ); + + // + // Determine the operation status + // + if ( !EFI_ERROR ( Status )) { + Status =3D CmdStatus; + } else { + // + // Only use status values associated with the Simple Network protocol + // + if ( EFI_TIMEOUT =3D=3D Status ) { + Status =3D EFI_DEVICE_ERROR; + } + } + + // + // Return the operation status + // + return Status; +} + +BOOLEAN +Ax88772GetLinkStatus ( + IN NIC_DEVICE * pNicDevice +) +{ + UINT32 CmdStatus; + EFI_USB_IO_PROTOCOL * pUsbIo; + UINT64 IntData =3D 0; + UINTN IntDataLeng =3D 8; + EFI_STATUS Status; + + // + // Issue the command + // + pUsbIo =3D pNicDevice->pUsbIo; + Status =3D pUsbIo->UsbSyncInterruptTransfer( pUsbIo, + USB_ENDPOINT_DIR_IN | INTERRUPT_EN= DPOINT, + &IntData, + &IntDataLeng, + USB_BUS_TIMEOUT, + &CmdStatus ); + + if ( EFI_ERROR(Status) || EFI_ERROR(CmdStatus) || 0 =3D=3D IntDataLeng) { + return FALSE; + } + return (IntData & 0x800000)? FALSE : TRUE; + +} + +#if RXTHOU +EFI_STATUS +Ax88772BulkIn( + IN NIC_DEVICE * pNicDevice +) +{ + int i; + UINTN LengthInBytes =3D 0; + UINTN TMP_LENG =3D AX88772_MAX_BULKIN_SIZE; + UINTN ORI_TMP_LENG =3D 0; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + EFI_USB_IO_PROTOCOL *pUsbIo; + UINT32 TransferStatus =3D 0; + UINT16 tmpPktCnt =3D 0; + UINT16 * tmpHdr =3D (UINT16 *)pNicDevice->pBulkInbuf; + USB_DEVICE_REQUEST SetupMsg; + + pUsbIo =3D pNicDevice->pUsbIo; + for ( i =3D 0 ; i < (AX88772_MAX_BULKIN_SIZE / 512) && pUsbIo !=3D NULL;= i++) { + VOID* tmpAddr =3D 0; + + tmpPktCnt =3D 0; + tmpAddr =3D (VOID*) &pNicDevice->pBulkInbuf[LengthInBytes]; + ORI_TMP_LENG =3D TMP_LENG; + Status =3D pUsbIo->UsbBulkTransfer ( pUsbIo, + USB_ENDPOINT_DIR_IN | BULK_IN_ENDPOINT, + tmpAddr, + &TMP_LENG, + BULKIN_TIMEOUT, + &TransferStatus ); + + if (ORI_TMP_LENG =3D=3D TMP_LENG) { + Status =3D EFI_NOT_READY; + goto no_pkt; + } + + if (( !EFI_ERROR ( Status )) && + ( !EFI_ERROR ( TransferStatus )) && + TMP_LENG !=3D 0) { + LengthInBytes +=3D TMP_LENG; + if ((TMP_LENG % 512) !=3D 0) { + goto done; + } + } else if (( !EFI_ERROR ( Status )) && + ( !EFI_ERROR ( TransferStatus )) && + (TMP_LENG =3D=3D 0)) { + Status =3D EFI_NOT_READY; + goto done; + } else if (EFI_TIMEOUT =3D=3D Status && EFI_USB_ERR_TIMEOUT =3D=3D Tra= nsferStatus) { + SetupMsg.RequestType =3D USB_REQ_TYPE_STANDARD | 0x02; + SetupMsg.Request =3D 0x01; + SetupMsg.Value =3D 0; + SetupMsg.Index =3D 0x82; + SetupMsg.Length =3D 0; + Status =3D Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + Status =3D EFI_NOT_READY; + goto done; + } else { + Status =3D EFI_DEVICE_ERROR; + goto done; + } + } +done: + if (LengthInBytes !=3D 0) { + UINT16 tmpLen; + UINT16 tmpLenBar; + UINT16 tmpTotalLen =3D 0; + UINTN TotalLen =3D LengthInBytes; + + do { + tmpLen =3D (*tmpHdr) & 0x7FF; + tmpLenBar =3D *(tmpHdr + 1); + tmpTotalLen =3D ((tmpLen + 4 + 1) & 0xfffe); + + if ((tmpLen & 0x7FF) + (tmpLenBar & 0x7FF) =3D=3D 0x7FF) { + tmpPktCnt++; + } else { + if ( tmpPktCnt !=3D 0) { + break; + } + Status =3D EFI_NOT_READY; + goto no_pkt; + } + tmpHdr +=3D (tmpTotalLen / 2); + TotalLen -=3D tmpTotalLen; + } while (TotalLen > 0); + + if (LengthInBytes >=3D 1000 && tmpPktCnt !=3D 0) { + if ((pNicDevice->rxburst) =3D=3D 1) { + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_RESET; + SetupMsg.Value =3D SRR_IPRL; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D 0; + Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + } + + if (pNicDevice->rxburst < 2) + pNicDevice->rxburst++; + + } else { + if (pNicDevice->rxburst >=3D 2) { + SetupMsg.RequestType =3D USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D CMD_RESET; + SetupMsg.Value =3D SRR_IPRL| SRR_BZ | SRR_BZTYPE; + SetupMsg.Index =3D 0; + SetupMsg.Length =3D 0; + Ax88772UsbCommand ( pNicDevice, + &SetupMsg, + NULL ); + } + pNicDevice->rxburst =3D 0; + } + } + + if (tmpPktCnt !=3D 0) { + pNicDevice->PktCnt =3D tmpPktCnt; + pNicDevice->pCurPktHdrOff =3D pNicDevice->pBulkInbuf; + pNicDevice->pCurPktOff =3D pNicDevice->pBulkInbuf + 4; + Status =3D EFI_SUCCESS; + } + +no_pkt: + return Status; +} +#else +EFI_STATUS +Ax88772BulkIn( + IN NIC_DEVICE * pNicDevice +) +{ + int i; + UINTN LengthInBytes =3D 0; + UINTN TMP_LENG =3D AX88772_MAX_BULKIN_SIZE; + UINTN ORI_TMP_LENG =3D 0; + UINTN CURBufSize =3D AX88772_MAX_BULKIN_SIZE; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + EFI_USB_IO_PROTOCOL *pUsbIo; + UINT32 TransferStatus =3D 0; + UINT16 tmpPktCnt =3D 0; + UINT16 * tmpHdr =3D (UINT16 *)pNicDevice->pBulkInbuf; + + pUsbIo =3D pNicDevice->pUsbIo; + for ( i =3D 0 ; i < (AX88772_MAX_BULKIN_SIZE / 512) && pUsbIo !=3D NULL;= i++) { + VOID* tmpAddr =3D 0; + + tmpPktCnt =3D 0; + tmpAddr =3D (VOID*) &pNicDevice->pBulkInbuf[LengthInBytes]; + ORI_TMP_LENG =3D TMP_LENG; + Status =3D pUsbIo->UsbBulkTransfer ( pUsbIo, + USB_ENDPOINT_DIR_IN | BULK_IN_ENDPOINT, + tmpAddr, + &TMP_LENG, + BULKIN_TIMEOUT, + &TransferStatus ); + + if (ORI_TMP_LENG =3D=3D TMP_LENG) { + Status =3D EFI_NOT_READY; + goto no_pkt; + } + + if (( !EFI_ERROR ( Status )) && + ( !EFI_ERROR ( TransferStatus )) && + TMP_LENG !=3D 0) { + UINT16 tmpLen; + UINT16 tmpLenBar; + UINT16 tmpTotalLen =3D 0; + + LengthInBytes +=3D TMP_LENG; + CURBufSize =3D CURBufSize - TMP_LENG; + TMP_LENG =3D CURBufSize; + do { + tmpLen =3D *tmpHdr; + tmpLenBar =3D *(tmpHdr + 1); + tmpTotalLen +=3D ((tmpLen + 4 + 1) & 0xfffe); + + if (((tmpLen ^ tmpLenBar) =3D=3D 0xffff)) { + if (tmpTotalLen =3D=3D LengthInBytes) { + tmpPktCnt++; + Status =3D EFI_SUCCESS; + goto done; + } else if (tmpTotalLen > LengthInBytes) { + break; + } + } else if (((tmpLen ^ tmpLenBar) !=3D 0xffff)) { + if ( tmpPktCnt !=3D 0) { + Status =3D EFI_SUCCESS; + goto done; + } + Status =3D EFI_NOT_READY; + goto no_pkt; + } + tmpHdr +=3D (tmpTotalLen / 2); + tmpPktCnt++; + }while (tmpTotalLen < LengthInBytes); + } else if (( !EFI_ERROR ( Status )) && + ( !EFI_ERROR ( TransferStatus )) && + (TMP_LENG =3D=3D 0)) { + if ( tmpPktCnt !=3D 0) { + Status =3D EFI_SUCCESS; + goto done; + } + Status =3D EFI_NOT_READY; + goto no_pkt; + } else if (EFI_TIMEOUT =3D=3D Status && EFI_USB_ERR_TIMEOUT =3D=3D Tra= nsferStatus) { + if ( tmpPktCnt !=3D 0) { + Status =3D EFI_SUCCESS; + goto done; + } + Status =3D EFI_NOT_READY; + goto no_pkt; + } else { + if ( tmpPktCnt !=3D 0) { + Status =3D EFI_SUCCESS; + goto done; + } + Status =3D EFI_DEVICE_ERROR; + goto no_pkt; + } + } +done: + pNicDevice->PktCnt =3D tmpPktCnt; + pNicDevice->pCurPktHdrOff =3D pNicDevice->pBulkInbuf; + pNicDevice->pCurPktOff =3D pNicDevice->pBulkInbuf + 4; +no_pkt: + return Status; +} +#endif diff --git a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/ComponentN= ame.c b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/ComponentName.c new file mode 100644 index 000000000000..8e2ba86f945e --- /dev/null +++ b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/ComponentName.c @@ -0,0 +1,246 @@ +/** @file + UEFI Component Name(2) protocol implementation. + + Copyright (c) 2011, Intel Corporation. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Ax88772.h" + +/** + EFI Component Name Protocol declaration +**/ +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gComponentName = =3D { + GetDriverName, + GetControllerName, + "eng" +}; + +/** + EFI Component Name 2 Protocol declaration +**/ +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gComponentName2= =3D { + (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[] =3D { + {"eng;en", L"ASIX AX88772B Ethernet Driver 2.8.0"}, + {NULL, NULL} +}; + + +/** + Controller name table declaration +**/ +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE +mControllerNameTable[] =3D { + {"eng;en", L"ASIX AX88772B USB Fast Ethernet Controller"}, + {NULL, NULL} +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form o= f 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 speci= fied + 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_PROTO= COL 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 calle= r 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 for= mat. + @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 specifie= d by + This and the language specified by Languag= e 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 supp= ort + 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 =3D LookupUnicodeString2 ( + pLanguage, + pThis->SupportedLanguages, + mDriverNameTable, + ppDriverName, + (BOOLEAN)(pThis =3D=3D &gComponentName) + ); + + return Status; +} + +/** + Retrieves a Unicode string that is the user readable name of the control= ler + that is being managed by a driver. + + This function retrieves the user readable name of the controller specifi= ed 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 specif= ied by + Language, then a pointer to the controller name is returned in Controlle= rName, + and EFI_SUCCESS is returned. If the driver specified by This is not cur= rently + 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 retu= rned. + + @param [in] pThis A pointer to the EFI_COMPONENT_NAME2_PROTO= COL 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 retr= ieve + the name of. This is an optional paramete= r that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus d= rivers + 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 calle= r 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 specifie= d 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 a= nd + ChildHandle in the language specified by + Language from the point of view of the dri= ver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable n= ame 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 va= lid + 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 curren= tly + managing the controller specified by + ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + 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 !=3D NULL) { + return EFI_UNSUPPORTED; + } + // + // Check Controller's handle + // + Status =3D 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 !=3D EFI_ALREADY_STARTED) { + return EFI_UNSUPPORTED; + } + + Status =3D LookupUnicodeString2 ( + pLanguage, + pThis->SupportedLanguages, + mControllerNameTable, + ppControllerName, + (BOOLEAN)(pThis =3D=3D &gComponentName) + ); + + return Status; +} +#else +EFI_STATUS +EFIAPI +GetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL * pThis, + IN EFI_HANDLE ControllerHandle, + IN OPTIONAL EFI_HANDLE ChildHandle, + IN CHAR8 * pLanguage, + OUT CHAR16 ** ppControllerName + ) +{ + EFI_STATUS Status; + + // + // Set the controller name + // + *ppControllerName =3D L"ASIX AX88772B USB Fast Ethernet Controller"; + Status =3D EFI_SUCCESS; + + // + // Return the operation status + // + + return Status; +} + +#endif diff --git a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/DriverBind= ing.c b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/DriverBinding.c new file mode 100644 index 000000000000..5edb7cbb2630 --- /dev/null +++ b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/DriverBinding.c @@ -0,0 +1,637 @@ +/** @file + Implement the driver binding protocol for Asix AX88772 Ethernet driver. + + Copyright (c) 2011-2013, Intel Corporation. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Ax88772.h" +#include +/** + 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 =3D 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 tra= nsport + // protocol handler. + // + Status =3D pUsbIo->UsbGetDeviceDescriptor ( pUsbIo, &Device ); + if (EFI_ERROR ( Status )) { + Status =3D EFI_UNSUPPORTED; + } else { + // + // Validate the adapter + // + if ( VENDOR_ID =3D=3D Device.IdVendor ) { + if (PRODUCT_AX88772B_ID !=3D Device.IdProduct) { + } else if (PRODUCT_AX88772B_ASUS_ID =3D=3D Device.IdProduct) { + } else if (PRODUCT_AX88772A_ID =3D=3D Device.IdProduct) { + } else if (PRODUCT_ID =3D=3D Device.IdProduct) { + } else { + Status =3D EFI_UNSUPPORTED; + } + } else if ( VENDOR_AX88772B_LENOVO_ID =3D=3D Device.IdVendor ) { + if (PRODUCT_AX88772B_LENOVO_ID !=3D Device.IdProduct) { + Status =3D EFI_UNSUPPORTED; + } + } else { + Status =3D EFI_UNSUPPORTED; + } + } + + // + // Done with the USB stack + // + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + pThis->DriverBindingHandle, + Controller + ); + } + + // + // Return the device supported status + // + return Status; +} + + +/** + Start this driver on Controller by opening UsbIo and DevicePath protocol= s. + Initialize PXE structures, create a copy of the Controller Device Path w= ith 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 c= hildren. + + @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 =3D NULL; + MAC_ADDR_DEVICE_PATH MacDeviceNode; + EFI_USB_DEVICE_DESCRIPTOR Device; + + // + // Allocate the device structure + // + LengthInBytes =3D sizeof ( *pNicDevice ); + Status =3D gBS->AllocatePool ( + EfiRuntimeServicesData, + LengthInBytes, + (VOID **) &pNicDevice + ); + + if (EFI_ERROR (Status)) { + goto ERR; + } + + // + // Set the structure signature + // + ZeroMem ( pNicDevice, LengthInBytes ); + pNicDevice->Signature =3D DEV_SIGNATURE; + + Status =3D gBS->OpenProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + (VOID **) &pNicDevice->pUsbIo, + pThis->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + goto ERR; + } + + pNicDevice->Flag772A =3D FALSE; + pNicDevice->pUsbIo->UsbGetDeviceDescriptor ( pNicDevice->pUsbIo, &Device= ); + if ((PRODUCT_AX88772A_ID =3D=3D Device.IdProduct) || + (PRODUCT_ID =3D=3D Device.IdProduct)) + pNicDevice->Flag772A =3D TRUE; + // + // Initialize the simple network protocol + // + Status =3D SN_Setup ( pNicDevice ); + + if (EFI_ERROR(Status)){ + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + pThis->DriverBindingHandle, + Controller + ); + goto ERR; + } + + // + // Set Device Path + // + + Status =3D 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 =3D MESSAGING_DEVICE_PATH; + MacDeviceNode.Header.SubType =3D MSG_MAC_ADDR_DP; + + SetDevicePathNodeLength (&MacDeviceNode.Header, sizeof (MAC_ADDR_DEVICE_= PATH)); + + CopyMem (&MacDeviceNode.MacAddress, + &pNicDevice->SimpleNetworkData.CurrentAddress, + PXE_HWADDR_LEN_ETHER); + + MacDeviceNode.IfType =3D pNicDevice->SimpleNetworkData.IfType; + + pNicDevice->MyDevPath =3D AppendDevicePathNode ( + ParentDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &Ma= cDeviceNode + ); + + pNicDevice->Controller =3D NULL; + + // + // Install both the simple network and device path protocols. + // + Status =3D 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 =3D 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 !=3D pNicDevice->pBulkInbuf) + gBS->FreePool (pNicDevice->pBulkInbuf); + if ( NULL !=3D pNicDevice->pTxTest) + gBS->FreePool (pNicDevice->pTxTest); + if ( NULL !=3D pNicDevice->MyDevPath) + gBS->FreePool (pNicDevice->MyDevPath); + if (NULL !=3D pNicDevice) + gBS->FreePool ( pNicDevice ); + return Status; +} + +/** + Stop this driver on Controller by removing NetworkInterfaceIdentifier pr= otocol 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 de= vice error. + @retval other This driver was not removed from this devic= e. + +**/ +EFI_STATUS +EFIAPI +DriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL * pThis, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE * ChildHandleBuffer + ) +{ + BOOLEAN AllChildrenStopped; + UINTN Index; + EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork; + EFI_STATUS Status =3D EFI_SUCCESS; + NIC_DEVICE *pNicDevice; + + // + // Complete all outstanding transactions to Controller. + // Don't allow any new transaction to Controller to be started. + // + if (NumberOfChildren =3D=3D 0) { + Status =3D 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 devi= cepath + // and usbio protocol. + // + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + pThis->DriverBindingHandle, + Controller + ); + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + pThis->DriverBindingHandle, + Controller + ); + return EFI_SUCCESS; + } + + pNicDevice =3D DEV_FROM_SIMPLE_NETWORK ( SimpleNetwork ); + + Status =3D gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiCallerIdGuid, + pNicDevice, + &gEfiSimpleNetworkProtocolGuid, + &pNicDevice->SimpleNetwork, + &gEfiDevicePathProtocolGuid, + pNicDevice->MyDevPath, + NULL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Close the bus driver + // + Status =3D gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + pThis->DriverBindingHandle, + Controller + ); + + if (EFI_ERROR(Status)){ } + + Status =3D gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + pThis->DriverBindingHandle, + Controller + ); + + if (EFI_ERROR(Status)){ } + + return EFI_SUCCESS; + } + + AllChildrenStopped =3D TRUE; + + for (Index =3D 0; Index < NumberOfChildren; Index++) { + Status =3D gBS->OpenProtocol ( + ChildHandleBuffer[Index], + &gEfiSimpleNetworkProtocolGuid, + (VOID **) &SimpleNetwork, + pThis->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + AllChildrenStopped =3D FALSE; + continue; + } + + pNicDevice =3D DEV_FROM_SIMPLE_NETWORK ( SimpleNetwork ); + + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + pThis->DriverBindingHandle, + ChildHandleBuffer[Index] + ); + + Status =3D gBS->UninstallMultipleProtocolInterfaces ( + ChildHandleBuffer[Index], + &gEfiCallerIdGuid, + pNicDevice, + &gEfiSimpleNetworkProtocolGuid, + &pNicDevice->SimpleNetwork, + &gEfiDevicePathProtocolGuid, + pNicDevice->MyDevPath, + NULL + ); + + if (EFI_ERROR (Status)) { + Status =3D gBS->OpenProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + (VOID **) &pNicDevice->pUsbIo, + pThis->DriverBindingHandle, + ChildHandleBuffer[Index], + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + } else { + if ( NULL !=3D pNicDevice->pBulkInbuf) + gBS->FreePool (pNicDevice->pBulkInbuf); + if ( NULL !=3D pNicDevice->pTxTest) + gBS->FreePool (pNicDevice->pTxTest); + if ( NULL !=3D pNicDevice->MyDevPath) + gBS->FreePool (pNicDevice->MyDevPath); + if ( NULL !=3D pNicDevice) + gBS->FreePool (pNicDevice); + } + } + + if (!AllChildrenStopped) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + + +/** + Driver binding protocol declaration +**/ +EFI_DRIVER_BINDING_PROTOCOL gDriverBinding =3D { + DriverSupported, + DriverStart, + DriverStop, + 0xa, + NULL, + NULL +}; + + +/** + Ax88772 driver unload routine. + + @param [in] ImageHandle Handle for the image. + + @retval EFI_SUCCESS Image may be unloaded + +**/ +EFI_STATUS +EFIAPI +DriverUnload ( + IN EFI_HANDLE ImageHandle + ) +{ + UINTN BufferSize; + UINTN Index; + UINTN Max; + EFI_HANDLE * pHandle; + EFI_STATUS Status; + + + // + // Determine which devices are using this driver + // + BufferSize =3D 0; + pHandle =3D NULL; + Status =3D gBS->LocateHandle ( + ByProtocol, + &gEfiCallerIdGuid, + NULL, + &BufferSize, + NULL ); + if ( EFI_BUFFER_TOO_SMALL =3D=3D Status ) { + for ( ; ; ) { + // + // One or more block IO devices are present + // + Status =3D gBS->AllocatePool ( + EfiRuntimeServicesData, + BufferSize, + (VOID **) &pHandle + ); + if ( EFI_ERROR ( Status )) { + + break; + } + + // + // Locate the block IO devices + // + Status =3D gBS->LocateHandle ( + ByProtocol, + &gEfiCallerIdGuid, + NULL, + &BufferSize, + pHandle ); + if ( EFI_ERROR ( Status )) { + // + // Error getting handles + // + break; + } + + // + // Remove any use of the driver + // + Max =3D BufferSize / sizeof ( pHandle[ 0 ]); + for ( Index =3D 0; Max > Index; Index++ ) { + Status =3D DriverStop ( &gDriverBinding, + pHandle[ Index ], + 0, + NULL ); + if ( EFI_ERROR ( Status )) { + break; + } + } + break; + } + } else { + if ( EFI_NOT_FOUND =3D=3D Status ) { + // + // No devices were found + // + Status =3D EFI_SUCCESS; + } + } + + // + // Free the handle array + // + if ( NULL !=3D pHandle ) { + gBS->FreePool ( pHandle ); + } + + // + // Remove the protocols installed by the EntryPoint routine. + // + if ( !EFI_ERROR ( Status )) { + gBS->UninstallMultipleProtocolInterfaces ( + ImageHandle, + &gEfiDriverBindingProtocolGuid, + &gDriverBinding, + &gEfiComponentNameProtocolGuid, + &gComponentName, + &gEfiComponentName2ProtocolGuid, + &gComponentName2, + NULL + ); + } + + // + // Return the unload status + // + return Status; +} + + +/** +Ax88772 driver entry point. + +@param [in] ImageHandle Handle for the image. +@param [in] pSystemTable Address of the system table. + +@retval EFI_SUCCESS Image successfully loaded. + +**/ +EFI_STATUS +EFIAPI +EntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE * pSystemTable + ) +{ + EFI_LOADED_IMAGE_PROTOCOL * pLoadedImage; + EFI_STATUS Status; + + // + // Enable unload support + // + Status =3D gBS->HandleProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **)&pLoadedImage + ); + if (!EFI_ERROR (Status)) { + pLoadedImage->Unload =3D DriverUnload; + } + + // + // Add the driver to the list of drivers + // + Status =3D EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + pSystemTable, + &gDriverBinding, + ImageHandle, + &gComponentName, + &gComponentName2 + ); + if ( !EFI_ERROR ( Status )) { } + return Status; +} diff --git a/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/SimpleNetw= ork.c b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/SimpleNetwork.c new file mode 100644 index 000000000000..b4627092a676 --- /dev/null +++ b/Drivers/OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772c/SimpleNetwork.c @@ -0,0 +1,1612 @@ +/** @file + Provides the Simple Network functions. + + Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Ax88772.h" +#include +/** + This function updates the filtering on the receiver. + + This support routine calls ::Ax88772MacAddressSet to update + the MAC address. This routine then rebuilds the multicast + hash by calling ::Ax88772MulticastClear and ::Ax88772MulticastSet. + Finally this routine enables the receiver by calling + ::Ax88772RxControl. + + @param [in] pSimpleNetwork Simple network mode pointer + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +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 =3D DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + pMode =3D pSimpleNetwork->Mode; + + // + // Clear the multicast hash table + // + Ax88772MulticastClear ( pNicDevice ); + + // + // Load the multicast hash table + // + if ( 0 !=3D ( pMode->ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE= _MULTICAST )) { + for ( Index =3D 0; Index < pMode->MCastFilterCount; Index++ ) { + // + // Enable the next multicast address + // + Ax88772MulticastSet ( pNicDevice, + &pMode->MCastFilter[ Index ].Addr[0]); + } + } + + Status =3D Ax88772RxControl ( pNicDevice, pMode->ReceiveFilterSetting = ); + + // + // Return the operation status + // + return Status; +} + + +/** + This function updates the SNP driver status. + + This function gets the current interrupt and recycled transmit + buffer status from the network interface. The interrupt status + and the media status are returned as a bit mask in InterruptStatus. + If InterruptStatus is NULL, the interrupt status will not be read. + Upon successful return of the media status, the MediaPresent field + of EFI_SIMPLE_NETWORK_MODE will be updated to reflect any change + of media status. If TxBuf is not NULL, a recycled transmit buffer + address will be retrived. If a recycled transmit buffer address + is returned in TxBuf, then the buffer has been successfully + transmitted, and the status for that buffer is cleared. + + This function calls ::Ax88772Rx to update the media status and + queue any receive packets. + + @param [in] pSimpleNetwork Protocol instance pointer + @param [in] pInterruptStatus A pointer to the bit mask of the current a= ctive interrupts. + If this is NULL, the interrupt status will= not be read from + the device. If this is not NULL, the inte= rrupt status will + be read from teh device. When the interru= pt status is read, + it will also be cleared. Clearing the tra= nsmit interrupt + does not empty the recycled transmit buffe= r array. + @param [out] ppTxBuf Recycled transmit buffer address. The net= work interface will + not transmit if its internal recycled tran= smit buffer array is + full. Reading the transmit buffer does no= t clear the transmit + interrupt. If this is NULL, then the tran= smit buffer status + will not be read. If there are not transm= it 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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk 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 =3D NULL; + EFI_STATUS Status =3D EFI_SUCCESS; + EFI_TPL TplPrevious; + + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + + // + // Verify the parameters + // + if (( NULL !=3D pSimpleNetwork ) && ( NULL !=3D pSimpleNetwork->Mode )) { + // + // Return the transmit buffer + // + pNicDevice =3D DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + + if (( NULL !=3D ppTxBuf ) && + ( NULL !=3D pNicDevice->pTxBuffer )) { + *ppTxBuf =3D pNicDevice->pTxBuffer; + pNicDevice->pTxBuffer =3D NULL; + } + + pMode =3D pSimpleNetwork->Mode; + if (EfiSimpleNetworkInitialized =3D=3D pMode->State) { + if (NULL =3D=3D ppTxBuf && NULL =3D=3D pInterruptStatus) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + +#if REPORTLINK +#else + if (!pNicDevice->bLinkUp || !pNicDevice->bComplete) { +#endif + Status =3D Ax88772NegotiateLinkComplete ( pNicDevice, + &pNicDevice->PollCount, + &pNicDevice->bComplete, + &pNicDevice->bLinkUp, + &pNicDevice->b100Mbps, + &pNicDevice->bFullDuplex ); + if (EFI_ERROR(Status)) + goto EXIT; +#if REPORTLINK + if (pNicDevice->bLinkUp && pNicDevice->bComplete) { + pMode->MediaPresent =3D TRUE; + Status =3D ReceiveFilterUpdate ( pSimpleNetwork ); + } else { + pMode->MediaPresent =3D FALSE; + } +#else + if (pNicDevice->bLinkUp && pNicDevice->bComplete) { + pMode->MediaPresent =3D TRUE; + pMode->MediaPresentSupported =3D FALSE; + Status =3D ReceiveFilterUpdate ( pSimpleNetwork ); + } + } +#endif + } else { + if (EfiSimpleNetworkStarted =3D=3D pMode->State) { + Status =3D EFI_DEVICE_ERROR; + } else { + Status =3D EFI_NOT_STARTED ; + } + } + } else { + Status =3D EFI_INVALID_PARAMETER; + } + if ( NULL !=3D pInterruptStatus ) { + *pInterruptStatus =3D 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 t= o start the + read or write operation. This must be a m= ultiple 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 NvramAcces= sSize. + @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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +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 =3D EFI_INVALID_PARAMETER; + EFI_TPL TplPrevious; + EFI_SIMPLE_NETWORK_MODE * pMode; + NIC_DEVICE * pNicDevice; + + + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + + if (( NULL =3D=3D pSimpleNetwork ) || ( NULL =3D=3D pSimpleNetwork->Mode= )) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + + pNicDevice =3D DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + pMode =3D pSimpleNetwork->Mode; + +#if PASS_SCT + if (EfiSimpleNetworkInitialized !=3D pMode->State) { + Status =3D EFI_NOT_STARTED; + goto EXIT; + } +#endif + + if ( 0 !=3D Offset ) { + if ((0 !=3D (Offset % pMode->NvRamAccessSize) ) || + (Offset >=3D pMode->NvRamSize)) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + } + // + // Offset must be a multiple of NvRamAccessSize and less than NvRamSize. + // + if (0 !=3D (BufferSize % pMode->NvRamAccessSize)) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + + if (BufferSize + Offset > pMode->NvRamSize) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + + if (NULL =3D=3D pBuffer) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + + // + // ReadWrite: TRUE FOR READ FALSE FOR WRITE + // + if (ReadWrite){ + UINTN i; + + for (i =3D 0; i < BufferSize / 2; i++) { + Status =3D Ax88772SromRead ( pNicDevice, + (UINT32)(Offset/2 + i), + (((UINT16*)pBuffer) + i)); + } + } else { + UINTN i; + + Status =3D Ax88772EnableSromWrite(pNicDevice); + if (EFI_ERROR(Status)) + goto EXIT; + + for (i =3D 0; i < BufferSize / 2; i++){ + Status =3D Ax88772SromWrite ( pNicDevice, + (UINT32)(Offset/2 + i), + (((UINT16*)pBuffer) + i)); + } + + Status =3D Ax88772DisableSromWrite(pNicDevice); + + if (BufferSize =3D=3D 272) + Status =3D Ax88772ReloadSrom(pNicDevice); + } + + // + // Return the operation status + // +EXIT: + gBS->RestoreTPL (TplPrevious); + return Status; +} + + + +/** + Resets the network adapter and allocates the transmit and receive buffers + required by the network interface; optionally, also requests allocation = of + additional transmit and receive buffers. This routine must be called be= fore + 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 buffe= r 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 transm= it and receive buffers + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +EFI_STATUS +EFIAPI +SN_Initialize ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + IN UINTN ExtraRxBufferSize, + IN UINTN ExtraTxBufferSize + ) +{ + EFI_SIMPLE_NETWORK_MODE * pMode; + EFI_STATUS Status; + UINT32 TmpState; + EFI_TPL TplPrevious; + NIC_DEVICE * pNicDevice; + + TplPrevious =3D gBS->RaiseTPL (TPL_CALLBACK); + + // + // Verify the parameters + // + if (( NULL !=3D pSimpleNetwork ) && ( NULL !=3D pSimpleNetwork->Mode )) { + // + // Determine if the interface is already started + // + pMode =3D pSimpleNetwork->Mode; + if ( EfiSimpleNetworkStarted =3D=3D pMode->State ) { + if (( 0 =3D=3D ExtraRxBufferSize ) && ( 0 =3D=3D ExtraTxBufferSize )= ) { + // + // Start the adapter + // + TmpState =3D pMode->State; + pMode->State =3D EfiSimpleNetworkInitialized; + Status =3D SN_Reset ( pSimpleNetwork, FALSE ); + if ( EFI_ERROR ( Status )) { + // + // Update the network state + // + pMode->State =3D TmpState ; // EfiSimpleNetworkInitialized; + } else { + pMode->MediaPresentSupported =3D TRUE; + pNicDevice =3D DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + pMode->MediaPresent =3D Ax88772GetLinkStatus (pNicDevice); + } + } else { + Status =3D EFI_UNSUPPORTED; + } + } else { + Status =3D EFI_NOT_STARTED; + } + } else { + Status =3D EFI_INVALID_PARAMETER; + } + + // + // Return the operation status + // + gBS->RestoreTPL (TplPrevious); + return Status; +} + + +/** + This function converts a multicast IP address to a multicast HW MAC addr= ess + 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 i= s IPv4 [RFC 791]. + @param [in] pIP The multicast IP address that is to be con= verted 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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +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 =3D gBS->RaiseTPL(TPL_CALLBACK); + + if (( NULL !=3D pSimpleNetwork ) && ( NULL !=3D pSimpleNetwork->Mode )) { + // + // The interface must be running + // + pMode =3D pSimpleNetwork->Mode; + if ( EfiSimpleNetworkInitialized =3D=3D pMode->State ) { + if (pIP =3D=3D NULL || pMAC =3D=3D NULL) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + + if (bIPv6) { + Status =3D EFI_UNSUPPORTED; + goto EXIT; + } else { + // + // check if the ip given is a mcast IP + // + if ((pIP->v4.Addr[0] & 0xF0) !=3D 0xE0) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } else { + pMAC->Addr[0] =3D 0x01; + pMAC->Addr[1] =3D 0x00; + pMAC->Addr[2] =3D 0x5e; + pMAC->Addr[3] =3D (UINT8) (pIP->v4.Addr[1] & 0x7f); + pMAC->Addr[4] =3D (UINT8) pIP->v4.Addr[2]; + pMAC->Addr[5] =3D (UINT8) pIP->v4.Addr[3]; + Status =3D EFI_SUCCESS; + } + } + } else { + if (EfiSimpleNetworkStarted =3D=3D pMode->State) { + Status =3D EFI_DEVICE_ERROR; + } else { + Status =3D EFI_NOT_STARTED ; + } + } + } else { + Status =3D EFI_INVALID_PARAMETER; + } + +EXIT: + gBS->RestoreTPL(TplPrevious); + return Status; +} + +EFI_STATUS +EFIAPI +SN_Receive ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + OUT UINTN * pHeaderSize, + OUT UINTN * pBufferSize, + OUT VOID * pBuffer, + OUT EFI_MAC_ADDRESS * pSrcAddr, + OUT EFI_MAC_ADDRESS * pDestAddr, + OUT UINT16 * pProtocol + ) +{ + ETHERNET_HEADER * pHeader; + EFI_SIMPLE_NETWORK_MODE * pMode; + NIC_DEVICE * pNicDevice =3D NULL; + EFI_STATUS Status; + EFI_TPL TplPrevious; + UINT16 Type; + UINT16 CurrentPktLen; + + + TplPrevious =3D gBS->RaiseTPL (TPL_CALLBACK); + + // + // Verify the parameters + // + if (( NULL !=3D pSimpleNetwork ) && ( NULL !=3D pSimpleNetwork->Mode )) { + // + // The interface must be running + // + pMode =3D pSimpleNetwork->Mode; + if ( EfiSimpleNetworkInitialized =3D=3D pMode->State ) { + + if ((pBufferSize =3D=3D NULL) || (pBuffer =3D=3D NULL)) { + Status =3D EFI_INVALID_PARAMETER; + gBS->RestoreTPL (TplPrevious); + return Status; + } + + // + // Update the link status + // + pNicDevice =3D DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + + if ( pNicDevice->bLinkUp && pNicDevice->bComplete) { + if ((NULL !=3D pHeaderSize) && (7720 =3D=3D *pHeaderSize)) { + pNicDevice->Grub_f =3D TRUE; + } + + if ((pNicDevice->Grub_f) && (7720 !=3D *pHeaderSize)) { + gBS->RestoreTPL (TplPrevious); + return EFI_NOT_READY; + } + + // + // Attempt to receive a packet + // + if (0 =3D=3D pNicDevice->PktCnt) { + Status =3D Ax88772BulkIn(pNicDevice); + if (EFI_ERROR(Status)) { + goto no_pkt; + } + } + + CurrentPktLen =3D *((UINT16*) (pNicDevice->pCurPktHdrOff)); + CurrentPktLen &=3D 0x7ff; + + if (( 60 <=3D CurrentPktLen ) && + ( CurrentPktLen - 14 <=3D MAX_ETHERNET_PKT_SIZE)) { + if (*pBufferSize < (UINTN)CurrentPktLen) { + gBS->RestoreTPL (TplPrevious); + return EFI_BUFFER_TOO_SMALL; + } + + *pBufferSize =3D CurrentPktLen; + CopyMem ( pBuffer, pNicDevice->pCurPktOff, CurrentPktLen ); + pHeader =3D (ETHERNET_HEADER *) pNicDevice->pCurPktOff; + + if ( NULL !=3D pHeaderSize && (7720 !=3D *pHeaderSize)) { + *pHeaderSize =3D sizeof ( *pHeader ); + } + if ( NULL !=3D pDestAddr ) { + CopyMem ( pDestAddr, &pHeader->dest_addr, PXE_HWADDR_LEN_ETH= ER ); + } + if ( NULL !=3D pSrcAddr ) { + CopyMem ( pSrcAddr, &pHeader->src_addr, PXE_HWADDR_LEN_ETHER= ); + } + if ( NULL !=3D pProtocol ) { + Type =3D pHeader->type; + Type =3D (UINT16)(( Type >> 8 ) | ( Type << 8 )); + *pProtocol =3D Type; + } + pNicDevice->PktCnt--; + pNicDevice->pCurPktHdrOff +=3D (CurrentPktLen + 4 + 1) & 0xfff= e; + pNicDevice->pCurPktOff =3D pNicDevice->pCurPktHdrOff + 4; + Status =3D EFI_SUCCESS; + } else { + pNicDevice->PktCnt =3D 0; + Status =3D EFI_DEVICE_ERROR; + } + } else { + // + // Link no up + // + Status =3D EFI_NOT_READY; + } + } else { + if (EfiSimpleNetworkStarted =3D=3D pMode->State) { + Status =3D EFI_DEVICE_ERROR; + } else { + Status =3D EFI_NOT_STARTED; + } + } + } else { + Status =3D 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 re= ceive + 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 li= st + filter is disabled (irregardless of what other multicast bits are set in + the enable and Disable parameters). The SNP->Mode->MCastFilterCount fie= ld + 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->ReceeiveFilterSetting= s, + 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 o= n the network interface. + For backward compatibility with EFI 1.1 pl= atforms, the + EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit m= ust be set + when the ResetMCastFilter parameter is TRU= E. + @param [in] bResetMCastFilter Set to TRUE to reset the contents of the m= ulticast 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 t= he MaxMCastFilterCnt + field of EFI_SIMPLE_NETWORK_MODE. This fi= eld is optional if + ResetMCastFilter is TRUE. + @param [in] pMCastFilter A pointer to a list of new multicast recei= ve filter HW MAC + addresses. This list will replace any exi= sting multicast + HW MAC address list. This field is option= al 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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +EFI_STATUS +EFIAPI +SN_ReceiveFilters ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + IN UINT32 Enable, + IN UINT32 Disable, +/* +#define EFI_SIMPLE_NETWORK_RECEIVE_UNICAST 0x01 +#define EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST 0x02 +#define EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST 0x04 +#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS 0x08 +#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST 0x10 +*/ + IN BOOLEAN bResetMCastFilter, + IN UINTN MCastFilterCnt, + IN EFI_MAC_ADDRESS * pMCastFilter + ) +{ + EFI_SIMPLE_NETWORK_MODE * pMode; + + EFI_STATUS Status =3D EFI_SUCCESS; + EFI_TPL TplPrevious; + + + NIC_DEVICE * pNicDevice; + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + + pNicDevice =3D DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + pMode =3D pSimpleNetwork->Mode; + + + if (pSimpleNetwork =3D=3D NULL) { + gBS->RestoreTPL(TplPrevious); + return EFI_INVALID_PARAMETER; + } + + + switch (pMode->State) { + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStopped: + Status =3D EFI_NOT_STARTED; + gBS->RestoreTPL(TplPrevious); + return Status; + + default: + Status =3D EFI_DEVICE_ERROR; + gBS->RestoreTPL(TplPrevious); + return Status; + } + + // + // check if we are asked to enable or disable something that the UNDI + // does not even support! + // + if (((Enable &~pMode->ReceiveFilterMask) !=3D 0) || + ((Disable &~pMode->ReceiveFilterMask) !=3D 0)) { + Status =3D EFI_INVALID_PARAMETER; + gBS->RestoreTPL(TplPrevious); + return Status; + } + + if (bResetMCastFilter) { + if ( (0 =3D=3D (pMode->ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEI= VE_MULTICAST)) && + Enable =3D=3D 0 && + Disable =3D=3D 2) { + gBS->RestoreTPL(TplPrevious); + return EFI_SUCCESS; + } + pMode->MCastFilterCount =3D 0; + SetMem ( &pMode->MCastFilter[0], + sizeof(EFI_MAC_ADDRESS) * MAX_MCAST_FILTER_CNT, + 0); + } else { + if (MCastFilterCnt !=3D 0) { + UINTN i; + EFI_MAC_ADDRESS * pMulticastAddress; + pMulticastAddress =3D pMCastFilter; + + if ((MCastFilterCnt > pMode->MaxMCastFilterCount) || + (pMCastFilter =3D=3D NULL)) { + Status =3D EFI_INVALID_PARAMETER; + gBS->RestoreTPL(TplPrevious); + return Status; + } + + for ( i =3D 0 ; i < MCastFilterCnt ; i++ ) { + UINT8 tmp; + tmp =3D pMulticastAddress->Addr[0]; + if ( (tmp & 0x01) !=3D 0x01 ) { + gBS->RestoreTPL(TplPrevious); + return EFI_INVALID_PARAMETER; + } + pMulticastAddress++; + } + + pMode->MCastFilterCount =3D (UINT32)MCastFilterCnt; + CopyMem (&pMode->MCastFilter[0], + pMCastFilter, + MCastFilterCnt * sizeof ( EFI_MAC_ADDRESS )); + } + } + + if (Enable =3D=3D 0 && Disable =3D=3D 0 && !bResetMCastFilter && MCastFi= lterCnt =3D=3D 0) { + Status =3D EFI_SUCCESS; + gBS->RestoreTPL(TplPrevious); + return Status; + } + + if ((Enable & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) !=3D 0 && MCastFilte= rCnt =3D=3D 0) { + Status =3D EFI_INVALID_PARAMETER; + gBS->RestoreTPL(TplPrevious); + return Status; + } + + pMode->ReceiveFilterSetting |=3D Enable; + pMode->ReceiveFilterSetting &=3D ~Disable; + + Status =3D ReceiveFilterUpdate (pSimpleNetwork); + + if (EFI_DEVICE_ERROR =3D=3D Status || EFI_INVALID_PARAMETER =3D=3D Statu= s) + Status =3D EFI_SUCCESS; + + + gBS->RestoreTPL(TplPrevious); + + return Status; +} + +/** + Reset the network adapter. + + Resets a network adapter and reinitializes it with the parameters that + were provided in the previous call to Initialize (). The transmit and + receive queues are cleared. Receive filters, the station address, the + statistics, and the multicast-IP-to-HW MAC addresses are not reset by + this call. + + This routine calls ::Ax88772Reset to perform the adapter specific + reset operation. This routine also starts the link negotiation + by calling ::Ax88772NegotiateLinkStart. + + @param [in] pSimpleNetwork Protocol instance pointer + @param [in] bExtendedVerification Indicates that the driver may perform= a more + exhaustive verification operation of the d= evice + 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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +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 =3D gBS->RaiseTPL(TPL_CALLBACK); + + // + // Verify the parameters + // + if (( NULL !=3D pSimpleNetwork ) && ( NULL !=3D pSimpleNetwork->Mode )) { + pMode =3D pSimpleNetwork->Mode; + if ( EfiSimpleNetworkInitialized =3D=3D pMode->State ) { + // + // Update the device state + // + pNicDevice =3D DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + + // + // Reset the device + // + if (!pNicDevice->bFirstRst) { + Status =3D EFI_SUCCESS; + } else { + Status =3D Ax88772Reset ( pNicDevice ); + if ( !EFI_ERROR ( Status )) { + Status =3D ReceiveFilterUpdate ( pSimpleNetwork ); + if ( !EFI_ERROR ( Status ) && !pNicDevice->bLinkUp && pNicDevice= ->bFirstRst) { + Status =3D Ax88772NegotiateLinkStart ( pNicDevice ); + pNicDevice->bFirstRst =3D FALSE; + } + } + } + } else { + Status =3D EFI_NOT_STARTED; + } + } else { + Status =3D EFI_INVALID_PARAMETER; + } + // + // Return the operation status + // + gBS->RestoreTPL(TplPrevious); + + return Status; +} + +/** + Initialize the simple network protocol. + + This routine calls ::Ax88772MacAddressGet to obtain the + MAC address. + + @param [in] pNicDevice NIC_DEVICE_INSTANCE pointer + + @retval EFI_SUCCESS Setup was successful + +**/ +EFI_STATUS +SN_Setup ( + IN NIC_DEVICE * pNicDevice + ) +{ + + + EFI_SIMPLE_NETWORK_MODE * pMode; + EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork; + EFI_STATUS Status; + + // + // Initialize the simple network protocol + // + pSimpleNetwork =3D &pNicDevice->SimpleNetwork; + pSimpleNetwork->Revision =3D EFI_SIMPLE_NETWORK_PROTOCOL_REVISION; + pSimpleNetwork->Start =3D (EFI_SIMPLE_NETWORK_START)SN_Start; + pSimpleNetwork->Stop =3D (EFI_SIMPLE_NETWORK_STOP)SN_Stop; + pSimpleNetwork->Initialize =3D (EFI_SIMPLE_NETWORK_INITIALIZE)SN_Initial= ize; + pSimpleNetwork->Reset =3D (EFI_SIMPLE_NETWORK_RESET)SN_Reset; + pSimpleNetwork->Shutdown =3D (EFI_SIMPLE_NETWORK_SHUTDOWN)SN_Shutdown; + pSimpleNetwork->ReceiveFilters =3D (EFI_SIMPLE_NETWORK_RECEIVE_FILTERS)S= N_ReceiveFilters; + pSimpleNetwork->StationAddress =3D (EFI_SIMPLE_NETWORK_STATION_ADDRESS)S= N_StationAddress; + pSimpleNetwork->Statistics =3D (EFI_SIMPLE_NETWORK_STATISTICS)SN_Statist= ics; + pSimpleNetwork->MCastIpToMac =3D (EFI_SIMPLE_NETWORK_MCAST_IP_TO_MAC)SN_= MCastIPtoMAC; + pSimpleNetwork->NvData =3D (EFI_SIMPLE_NETWORK_NVDATA)SN_NvData; + pSimpleNetwork->GetStatus =3D (EFI_SIMPLE_NETWORK_GET_STATUS)SN_GetStatu= s; + pSimpleNetwork->Transmit =3D (EFI_SIMPLE_NETWORK_TRANSMIT)SN_Transmit; + pSimpleNetwork->Receive =3D (EFI_SIMPLE_NETWORK_RECEIVE)SN_Receive; + pSimpleNetwork->WaitForPacket =3D NULL; + pMode =3D &pNicDevice->SimpleNetworkData; + pSimpleNetwork->Mode =3D pMode; + pMode->State =3D EfiSimpleNetworkStopped; + pMode->HwAddressSize =3D PXE_HWADDR_LEN_ETHER; + pMode->MediaHeaderSize =3D sizeof ( ETHERNET_HEADER ); + pMode->MaxPacketSize =3D MAX_ETHERNET_PKT_SIZE; + pMode->ReceiveFilterMask =3D 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_MULTIC= AST; + pMode->ReceiveFilterSetting =3D EFI_SIMPLE_NETWORK_RECEIVE_UNICAST + | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST; + pMode->MaxMCastFilterCount =3D ASIX_MCAST_FILTER_CNT; + pMode->MCastFilterCount =3D 0; + pMode->NvRamSize =3D 512; + pMode->NvRamAccessSize =3D 2; + SetMem ( &pMode->BroadcastAddress, + PXE_HWADDR_LEN_ETHER, + 0xff ); + + SetMem ( &pMode->MCastFilter[0], + sizeof(EFI_MAC_ADDRESS) * MAX_MCAST_FILTER_CNT, + 0); + + pMode->IfType =3D EfiNetworkInterfaceUndi; + pMode->MacAddressChangeable =3D TRUE; + pMode->MultipleTxSupported =3D FALSE; + pMode->MediaPresentSupported =3D TRUE; + pMode->MediaPresent =3D FALSE; + + // + // Read the MAC address + // + pNicDevice->PhyId =3D PHY_ID_INTERNAL; + pNicDevice->b100Mbps =3D TRUE; + pNicDevice->bFullDuplex =3D TRUE; + pNicDevice->bComplete =3D FALSE; + pNicDevice->bLinkUp =3D FALSE; + pNicDevice->Grub_f =3D FALSE; + pNicDevice->bFirstRst =3D TRUE; + pNicDevice->PktCnt =3D 0; + + Status =3D Ax88772MacAddressGet ( + pNicDevice, + &pMode->PermanentAddress.Addr[0]); + + if ( !EFI_ERROR ( Status )) { + + // + // Use the hardware address as the current address + // + + CopyMem ( &pMode->CurrentAddress, + &pMode->PermanentAddress, + PXE_HWADDR_LEN_ETHER ); + + CopyMem ( &pNicDevice->MAC, + &pMode->PermanentAddress, + PXE_HWADDR_LEN_ETHER ); + + + if (EFI_ERROR(Status)) { + return Status; + } + } else { + return Status; + } + + Status =3D gBS->AllocatePool ( EfiRuntimeServicesData, + AX88772_MAX_BULKIN_SIZE, + (VOID **) &pNicDevice->pBulkInbuf ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D gBS->AllocatePool ( EfiRuntimeServicesData, + sizeof ( RX_TX_PACKET ), + (VOID **) &pNicDevice->pTxTest ); + + if (EFI_ERROR (Status)) { + gBS->FreePool (pNicDevice->pBulkInbuf); + return Status; + } + + // + // Return the setup status + // + return Status; +} + + +/** + This routine starts the network interface. + + @param [in] pSimpleNetwork Protocol instance pointer + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_ALREADY_STARTED The network interface was already started. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +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 =3D gBS->RaiseTPL(TPL_CALLBACK); + + // + // Verify the parameters + // + Status =3D EFI_INVALID_PARAMETER; + if (( NULL !=3D pSimpleNetwork ) && ( NULL !=3D pSimpleNetwork->Mode )) { + pMode =3D pSimpleNetwork->Mode; + if ( EfiSimpleNetworkStopped =3D=3D pMode->State ) { + // + // Initialize the mode structure + // NVRAM access is not supported + // + ZeroMem ( pMode, sizeof ( *pMode )); + + pMode->State =3D EfiSimpleNetworkStarted; + pMode->HwAddressSize =3D PXE_HWADDR_LEN_ETHER; + pMode->MediaHeaderSize =3D sizeof ( ETHERNET_HEADER ); + pMode->MaxPacketSize =3D MAX_ETHERNET_PKT_SIZE; + pMode->ReceiveFilterMask =3D 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_MU= LTICAST; + pMode->ReceiveFilterSetting =3D EFI_SIMPLE_NETWORK_RECEIVE_UNICAST; + pMode->MaxMCastFilterCount =3D ASIX_MCAST_FILTER_CNT; + pMode->MCastFilterCount =3D 0; + + SetMem ( &pMode->MCastFilter[0], + sizeof(EFI_MAC_ADDRESS) * MAX_MCAST_FILTER_CNT, + 0); + + pMode->NvRamSize =3D 512; + pMode->NvRamAccessSize =3D 2; + pNicDevice =3D DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + Status =3D Ax88772MacAddressGet ( pNicDevice, &pMode->PermanentAddre= ss.Addr[0]); + CopyMem ( &pMode->CurrentAddress, + &pMode->PermanentAddress, + sizeof ( pMode->CurrentAddress )); + SetMem(&pMode->BroadcastAddress, PXE_HWADDR_LEN_ETHER, 0xff); + pMode->IfType =3D EfiNetworkInterfaceUndi; + pMode->MacAddressChangeable =3D TRUE; + pMode->MultipleTxSupported =3D FALSE; + + pMode->MediaPresentSupported =3D TRUE; + pMode->MediaPresent =3D FALSE; + + } else { + Status =3D EFI_ALREADY_STARTED; + } + } + + // + // Return the operation status + // + gBS->RestoreTPL(TplPrevious); + return Status; +} + + +/** + Set the MAC address. + + This function modifies or resets the current station address of a + network interface. If Reset is TRUE, then the current station address + is set ot the network interface's permanent address. If Reset if FALSE + then the current station address is changed to the address specified by + pNew. + + This routine calls ::Ax88772MacAddressSet to update the MAC address + in the network adapter. + + @param [in] pSimpleNetwork Protocol instance pointer + @param [in] bReset Flag used to reset the station address to = the + network interface's permanent address. + @param [in] pNew New station address to be used for the net= work + 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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +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 =3D gBS->RaiseTPL(TPL_CALLBACK); + + // + // Verify the parameters + // + if (( NULL !=3D pSimpleNetwork ) && + ( NULL !=3D pSimpleNetwork->Mode ) && + (( !bReset ) || ( bReset && ( NULL !=3D pNew )))) { + // + // Verify that the adapter is already started + // + pNicDevice =3D DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + pMode =3D pSimpleNetwork->Mode; + if ( EfiSimpleNetworkInitialized =3D=3D 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 =3D Ax88772MacAddressSet ( pNicDevice, &pMode->CurrentAddress= .Addr[0]); + } else { + if (EfiSimpleNetworkStarted =3D=3D pMode->State) { + Status =3D EFI_DEVICE_ERROR; ; + } else { + Status =3D EFI_NOT_STARTED ; + } + } + } else { + Status =3D 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 th= e network interface. + @param [in, out] pStatisticsSize On input the size, in bytes, of Statis= ticsTable. On output + the size, in bytes, of the resulting table= of statistics. + @param [out] pStatisticsTable A pointer to the EFI_NETWORK_STATISTICS st= ructure 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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + + typedef struct { + UINT64 RxTotalFrames; + UINT64 RxGoodFrames; + UINT64 RxUndersizeFrames; + UINT64 RxOversizeFrames; + UINT64 RxDroppedFrames; + UINT64 RxUnicastFrames; + UINT64 RxBroadcastFrames; + UINT64 RxMulticastFrames; + UINT64 RxCrcErrorFrames; + UINT64 RxTotalBytes; + UINT64 TxTotalFrames; + UINT64 TxGoodFrames; + UINT64 TxUndersizeFrames; + UINT64 TxOversizeFrames; + UINT64 TxDroppedFrames; + UINT64 TxUnicastFrames; + UINT64 TxBroadcastFrames; + UINT64 TxMulticastFrames; + UINT64 TxCrcErrorFrames; + UINT64 TxTotalBytes; + UINT64 Collisions; + UINT64 UnsupportedProtocol; + } EFI_NETWORK_STATISTICS; +**/ +EFI_STATUS +EFIAPI +SN_Statistics ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + IN BOOLEAN bReset, + IN OUT UINTN * pStatisticsSize, + OUT EFI_NETWORK_STATISTICS * pStatisticsTable + ) +{ + EFI_STATUS Status; + EFI_TPL TplPrevious; + EFI_SIMPLE_NETWORK_MODE * pMode; + + + + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + + pMode =3D pSimpleNetwork->Mode; + + if ( EfiSimpleNetworkInitialized =3D=3D pMode->State ) { + if (NULL !=3D pStatisticsSize && 0 =3D=3D *pStatisticsSize) { + Status =3D EFI_BUFFER_TOO_SMALL; + goto EXIT; + } + if(bReset) { + Status =3D EFI_SUCCESS; + } else { + Status =3D EFI_SUCCESS; + } + } else { + if (EfiSimpleNetworkStarted =3D=3D pMode->State) { + Status =3D EFI_DEVICE_ERROR; ; + } else { + Status =3D EFI_NOT_STARTED ; + } + } + // + // This is not currently supported + // + +EXIT: + gBS->RestoreTPL(TplPrevious); + return Status; +} + + +/** + This function stops a network interface. This call is only valid + if the network interface is in the started state. + + @param [in] pSimpleNetwork Protocol instance pointer + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +EFI_STATUS +EFIAPI +SN_Stop ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork + ) +{ + EFI_SIMPLE_NETWORK_MODE * pMode; + EFI_STATUS Status; + + EFI_TPL TplPrevious; + + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + + // + // Verify the parameters + // + if (( NULL !=3D pSimpleNetwork ) && ( NULL !=3D pSimpleNetwork->Mode )) { + // + // Determine if the interface is started + // + pMode =3D pSimpleNetwork->Mode; + + if ( EfiSimpleNetworkStarted =3D=3D pMode->State ) { + pMode->State =3D EfiSimpleNetworkStopped; + Status =3D EFI_SUCCESS; + } else { + Status =3D EFI_NOT_STARTED; + } + } else { + Status =3D EFI_INVALID_PARAMETER; + } + + // + // Return the operation status + // + gBS->RestoreTPL(TplPrevious); + return Status; +} + + +/** + This function releases the memory buffers assigned in the Initialize() c= all. + 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 n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + @retval EFI_UNSUPPORTED The increased buffer size feature is not s= upported. + +**/ +EFI_STATUS +EFIAPI +SN_Shutdown ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork + ) +{ + EFI_SIMPLE_NETWORK_MODE * pMode; + UINT32 RxFilter; + EFI_STATUS Status; + + EFI_TPL TplPrevious; + + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + + // + // Verify the parameters + // + if (( NULL !=3D pSimpleNetwork ) && ( NULL !=3D pSimpleNetwork->Mode )) { + // + // Determine if the interface is already started + // + pMode =3D pSimpleNetwork->Mode; + if ( EfiSimpleNetworkInitialized =3D=3D pMode->State ) { + // + // Stop the adapter + // + RxFilter =3D pMode->ReceiveFilterSetting; + pMode->ReceiveFilterSetting =3D 0; + Status =3D SN_Reset ( pSimpleNetwork, FALSE ); + pMode->ReceiveFilterSetting =3D RxFilter; + if ( !EFI_ERROR ( Status )) { + // + // Update the network state + // + pMode->State =3D EfiSimpleNetworkStarted; + } else if ( EFI_DEVICE_ERROR =3D=3D Status ) { + pMode->State =3D EfiSimpleNetworkStopped; + } + + } else { + Status =3D EFI_NOT_STARTED; + } + } else { + Status =3D EFI_INVALID_PARAMETER; + } + + // + // Return the operation status + // + gBS->RestoreTPL(TplPrevious ); + return Status; +} + + +/** + Send a packet over the network. + + This function places the packet specified by Header and Buffer on + the transmit queue. This function performs a non-blocking transmit + operation. When the transmit is complete, the buffer is returned + via the GetStatus() call. + + This routine calls ::Ax88772Rx to empty the network adapter of + receive packets. The routine then passes the transmit packet + to the network adapter. + + @param [in] pSimpleNetwork Protocol instance pointer + @param [in] HeaderSize The size, in bytes, of the media header to= be filled in by + the Transmit() function. If HeaderSize is= non-zero, then + it must be equal to SimpleNetwork->Mode->M= ediaHeaderSize + 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 networ= k interface. + @param [in] pBuffer A pointer to the packet (media header foll= owed 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 He= aderSize 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 Header= Size is zero, then + this parameter is ignored. + @param [in] pProtocol The type of header to build. If HeaderSiz= e 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 accep= t this transmit request. + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. + @retval EFI_INVALID_PARAMETER pSimpleNetwork parameter was NULL or did n= ot point to a valid + EFI_SIMPLE_NETWORK_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The command could not be sent to the netwo= rk interface. + +**/ +EFI_STATUS +EFIAPI +SN_Transmit ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * pSimpleNetwork, + IN UINTN HeaderSize, + IN UINTN BufferSize, + IN VOID * pBuffer, + IN EFI_MAC_ADDRESS * pSrcAddr, + IN EFI_MAC_ADDRESS * pDestAddr, + IN UINT16 * pProtocol + ) +{ + ETHERNET_HEADER * pHeader; + EFI_SIMPLE_NETWORK_MODE * pMode; + NIC_DEVICE * pNicDevice; + EFI_USB_IO_PROTOCOL * pUsbIo; + EFI_STATUS Status; + UINTN TransferLength; + UINT32 TransferStatus; + UINT16 Type; + EFI_TPL TplPrevious; + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + + // Verify the parameters + // + if (( NULL !=3D pSimpleNetwork ) && ( NULL !=3D pSimpleNetwork->Mode )) { + // + // The interface must be running + // + pMode =3D pSimpleNetwork->Mode; + if ( EfiSimpleNetworkInitialized =3D=3D pMode->State ) { + // + // Update the link status + // + pNicDevice =3D DEV_FROM_SIMPLE_NETWORK ( pSimpleNetwork ); + + // + // Release the synchronization with Ax88772Timer + // + if ( pNicDevice->bLinkUp && pNicDevice->bComplete) { + // + // Copy the packet into the USB buffer + // + + if (0 !=3D HeaderSize && pMode->MediaHeaderSize !=3D HeaderSize) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + if (BufferSize < pMode->MediaHeaderSize) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + if (NULL =3D=3D pBuffer) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + if (0 !=3D HeaderSize && NULL =3D=3D pDestAddr) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + if (0 !=3D HeaderSize && NULL =3D=3D pProtocol) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + + CopyMem ( &pNicDevice->pTxTest->Data[0], pBuffer, BufferSize ); + pNicDevice->pTxTest->Length =3D (UINT16) BufferSize; + + // + // Transmit the packet + // + pHeader =3D (ETHERNET_HEADER *) &pNicDevice->pTxTest->Data[0]; + if ( 0 !=3D HeaderSize ) { + if ( NULL !=3D pDestAddr ) { + CopyMem ( &pHeader->dest_addr, pDestAddr, PXE_HWADDR_LEN_ETHER= ); + } + if ( NULL !=3D 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 !=3D pProtocol ) { + Type =3D *pProtocol; + } else { + Type =3D pNicDevice->pTxTest->Length; + } + Type =3D (UINT16)(( Type >> 8 ) | ( Type << 8 )); + pHeader->type =3D Type; + } + + + if ( pNicDevice->pTxTest->Length < MIN_ETHERNET_PKT_SIZE ) { + pNicDevice->pTxTest->Length =3D MIN_ETHERNET_PKT_SIZE; + ZeroMem ( &pNicDevice->pTxTest->Data[ BufferSize], + pNicDevice->pTxTest->Length - BufferSize ); + } + + pNicDevice->pTxTest->LengthBar =3D ~(pNicDevice->pTxTest->Length); + TransferLength =3D sizeof ( pNicDevice->pTxTest->Length ) + + sizeof ( pNicDevice->pTxTest->LengthBar ) + + pNicDevice->pTxTest->Length; + + if (TransferLength % 512 =3D=3D 0 || TransferLength % 1024 =3D=3D = 0) + TransferLength +=3D4; +#if RXTHOU + if (pNicDevice->rxburst =3D=3D 1) + pNicDevice->rxburst--; +#endif + // + // Work around USB bus driver bug where a timeout set by receive + // succeeds but the timeout expires immediately after, causing the + // transmit operation to timeout. + // + pUsbIo =3D pNicDevice->pUsbIo; + Status =3D pUsbIo->UsbBulkTransfer ( pUsbIo, + BULK_OUT_ENDPOINT, + &pNicDevice->pTxTest->Length, + &TransferLength, + 0xfffffffe, + &TransferStatus ); + if ( EFI_SUCCESS =3D=3D Status) { + Status =3D TransferStatus; + } + if ( EFI_SUCCESS =3D=3D Status && EFI_SUCCESS =3D=3D TransferStatu= s) { + pNicDevice->pTxBuffer =3D pBuffer; + } else { + if ( EFI_DEVICE_ERROR =3D=3D Status ) { + SN_Reset ( pSimpleNetwork, FALSE ); + } + Status =3D EFI_NOT_READY; + } + } else { + // + // No packets available. + // + + Status =3D EFI_NOT_READY; + } + } else { + if (EfiSimpleNetworkStarted =3D=3D pMode->State) { + Status =3D EFI_DEVICE_ERROR; ; + } else { + Status =3D EFI_NOT_STARTED ; + } + } + } else { + Status =3D EFI_INVALID_PARAMETER; + } + +EXIT: + gBS->RestoreTPL (TplPrevious); + + return Status; +} --=20 2.17.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#58772): https://edk2.groups.io/g/devel/message/58772 Mute This Topic: https://groups.io/mt/74044145/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-