From nobody Tue Feb 10 19:09:00 2026 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+60864+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+60864+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1591625029; cv=none; d=zohomail.com; s=zohoarc; b=naM1QN/q9cE3IFwVpdoZ9pFDhmOxi9ti9uEPrjzOalHVJ7LxAmndegwt+oU4bFZWDudBNhUFX2qqU8CGUOY9WETNJNCPVStPrHUd8CjYkRxOs16N51GL0wGimZ8rOYJp07Qv7jmzilXAd0h9WjMcPMXPyjcuwd0X6bL5Yc+e/40= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1591625029; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To; bh=MydpCvx4Bl0AduWbP4f2hR3CeLcafaqC2O/1CGksVSE=; b=fcRvz1X791faUPK+0qKvphYUYYfMAqMoYMoOU6sDcvd4K5wzOEFYWTXjJYOlvQwUkasPpDlb2DX9C93mfEf08yJcxThOls0+970G/OBrYpDh8aedVHbI9rb4c5a0F2nP8qrp4UjpF8Nz0pAG0NpTwDyPsxe/XyQIOzB+o1Jf8kg= 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+60864+1787277+3901457@groups.io Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1591625028917586.3139767926202; Mon, 8 Jun 2020 07:03:48 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id fAMUYY1788612xsSuMYXuCDg; Mon, 08 Jun 2020 07:03:48 -0700 X-Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web12.30017.1591623516302809171 for ; Mon, 08 Jun 2020 06:38:36 -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 2226A1042; Mon, 8 Jun 2020 06:38:35 -0700 (PDT) X-Received: from localhost.localdomain (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id A3D343F52E; Mon, 8 Jun 2020 06:38:34 -0700 (PDT) From: "Samer El-Haj-Mahmoud" To: devel@edk2.groups.io Cc: Ray Ni , Leif Lindholm , Ard Biesheuvel , Michael D Kinney Subject: [edk2-devel] [edk2-platform][PATCH v3 2/6] Drivers/ASIX: Add ASIX Ax88179 driver Date: Mon, 8 Jun 2020 09:38:28 -0400 Message-Id: <20200608133832.14100-3-Samer.El-Haj-Mahmoud@arm.com> In-Reply-To: <20200608133832.14100-1-Samer.El-Haj-Mahmoud@arm.com> References: <20200608133832.14100-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: BcoFgKqwyEHznjmkJ5P7lrb6x1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1591625028; bh=KK116xAGQSqnxOqYnSbKnXFLSfWjaFTBKW4f51EXXBU=; h=Cc:Date:From:Reply-To:Subject:To; b=payZNeHf+wHJLfDXiQf7opP9vHi7DrnDEx7gAtiJSPck5D5v/Guc8LKCAGpSfeGKlO3 keWkLBKJOuX4vIQKpn9CTzes1EZxokxv5tAN9udd2inD76m1fIe/GRK0PI8o2NaCsCT7i H3nOJDgQrfYydDYNmTYfi5VLtS84P/zfr24= 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 Original source code provided by ASIX is at: https://github.com/samerhaj/uefi_drivers/blob/master/UsbNetworking/Asix/ zip/source/AX88179_178a_UEFI_v2.9.0_Source.zip Cc: Ray Ni Cc: Leif Lindholm Cc: Ard Biesheuvel Cc: Michael D Kinney Signed-off-by: Samer El-Haj-Mahmoud Reviewed-by: Ray Ni --- Drivers/ASIX/Asix.dsc | 2 +- Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf | 45 + Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.h | 1053 ++++++++= +++++ Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.c | 1042 ++++++++= +++++ Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/ComponentName.c | 223 +++ Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/DriverBinding.c | 639 ++++++++ Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/SimpleNetwork.c | 1548 ++++++++= ++++++++++++ 7 files changed, 4551 insertions(+), 1 deletion(-) diff --git a/Drivers/ASIX/Asix.dsc b/Drivers/ASIX/Asix.dsc index d65857bb1cd4..73b5cbd5a18f 100644 --- a/Drivers/ASIX/Asix.dsc +++ b/Drivers/ASIX/Asix.dsc @@ -64,4 +64,4 @@ [PcdsFixedAtBuild] # ##########################################################################= ###### [Components] - +Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf diff --git a/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf b/Drive= rs/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf new file mode 100644 index 000000000000..317ec538fa60 --- /dev/null +++ b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.inf @@ -0,0 +1,45 @@ +## @file +# Component description file for ASIX AX88772 USB/Ethernet driver. +# +# This module provides support for the ASIX AX88772 USB/Ethernet adapter. +# Copyright (c) 2011, Intel Corporation +# Copyright (c) 2020, ARM Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010018 + BASE_NAME =3D Ax88179 + FILE_GUID =3D 27E5D3B6-7839-47C2-8618-5D2190729BC7 + MODULE_TYPE =3D UEFI_DRIVER + VERSION_STRING =3D 1.0 + + ENTRY_POINT =3D EntryPoint + +[Sources.common] + Ax88179.h + Ax88179.c + ComponentName.c + DriverBinding.c + SimpleNetwork.c + + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + NetworkPkg/NetworkPkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiLib + +[Protocols] + gEfiDevicePathProtocolGuid ## BY_START + gEfiSimpleNetworkProtocolGuid ## BY_START + gEfiUsbIoProtocolGuid ## TO_START + diff --git a/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.h b/Drivers= /ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.h new file mode 100644 index 000000000000..498212ec149b --- /dev/null +++ b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.h @@ -0,0 +1,1053 @@ +/** @file + Definitions for ASIX AX88179 Ethernet adapter. + + Copyright (c) 2011, Intel Corporation + Copyright (c) 2020, ARM Limited. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef AX88179_H_ +#define AX88179_H_ + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +#define FORCE_100Mbps 0 +#define REPORTLINK 1 + + +//------------------------------------------------------------------------= ------ +// Macros +//------------------------------------------------------------------------= ------ + +#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 byte= s 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 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 +// + + +// +// 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 + +//------------------------------ +// 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_CRCERR 0x2000 + + +//------------------------------------------------------------------------= ------ +// Data Types +//------------------------------------------------------------------------= ------ + +/** + Ethernet header layout + + IEEE 802.3-2002 Part 3 specification, section 3.1.1. +**/ +#pragma pack(1) +typedef struct { + UINT8 DestAddr[PXE_HWADDR_LEN_ETHER]; ///< Destination LAN address + UINT8 SrcAddr[PXE_HWADDR_LEN_ETHER]; ///< Source LAN address + UINT16 Type; ///< Protocol or length +} ETHERNET_HEADER; +#pragma pack() + +/** + Receive and Transmit packet structure +**/ +#pragma pack(1) +typedef struct _TX_PACKET { + UINT32 TxHdr1; + UINT32 TxHdr2; + UINT8 Data[AX88179_MAX_PKT_SIZE]; ///< Received packet data +} TX_PACKET; +#pragma pack() + +#pragma pack(1) +typedef struct _RX_PACKET { + struct _RX_PACKET *Next; + UINT16 Length; + UINT16 EEEE; + UINT8 Data[AX88179_MAX_PKT_SIZE]; +} RX_PACKET; +#pragma pack() + +/** + AX88179 control structure + + The driver uses this structure to manage the Asix AX88179 10/100 + Ethernet controller. +**/ +typedef struct { + UINTN Signature; ///< Structure identificat= ion + + // + // USB data + // + EFI_HANDLE Controller; ///< Controller handle + EFI_USB_IO_PROTOCOL *UsbIo; ///< USB driver interface + + // + // Simple network protocol data + // + EFI_SIMPLE_NETWORK_PROTOCOL SimpleNetwork; ///< Driver's network st= ack interface + EFI_SIMPLE_NETWORK_MODE SimpleNetworkData; ///< Data for simple net= work + + // + // Ethernet controller data + // + BOOLEAN Initialized; ///< Controller initialized + UINT16 PhyId; ///< PHY ID + + // + // Link state + // + BOOLEAN LinkSpeed100Mbps; ///< Current link speed, = FALSE =3D 10 Mbps + BOOLEAN LinkSpeed1000Mbps; ///< Current link speed, = FALSE =3D 100/10 bps + BOOLEAN Complete; ///< Current state of aut= o-negotiation + BOOLEAN FullDuplex; ///< Current duplex + BOOLEAN LinkUp; ///< Current link state + BOOLEAN LinkIdle; ///< TRUE =3D No received= traffic + EFI_EVENT Timer; ///< Timer to monitor lin= k state and receive packets + UINTN PollCount; ///< Number of times the = autonegotiation status was polled + UINTN SkipRXCnt; + + UINT8 *BulkInbuf; + UINT16 PktCnt; + UINT8 *CurPktHdrOff; + UINT8 *CurPktOff; + + TX_PACKET *TxTest; + + INT8 MulticastHash[8]; + EFI_MAC_ADDRESS MAC; + + UINT16 CurMediumStatus; + UINT16 CurRxControl; + VOID * TxBuffer; + + EFI_DEVICE_PATH_PROTOCOL *MyDevPath; + BOOLEAN Grub_f; + BOOLEAN FirstRst; + BOOLEAN SetZeroLen; + UINT8 RxBurst; + UINTN UsbMaxPktSize; +} NIC_DEVICE; + +#define DEV_FROM_SIMPLE_NETWORK(a) CR (a, NIC_DEVICE, SimpleNetwork, DEV_= SIGNATURE) ///< Locate NIC_DEVICE from Simple Network Protocol + +//------------------------------------------------------------------------= ------ +// Simple Network Protocol +//------------------------------------------------------------------------= ------ + +/** + Reset the network adapter. + + Resets a network adapter and reinitializes it with the parameters that + were provided in the previous call to Initialize (). The transmit and + receive queues are cleared. Receive filters, the station address, the + statistics, and the multicast-IP-to-HW MAC addresses are not reset by + this call. + + This routine calls ::Ax88179Reset to perform the adapter specific + reset operation. This routine also starts the link negotiation + by calling ::Ax88179NegotiateLinkStart. + + @param [in] SimpleNetwork Protocol instance pointer + @param [in] ExtendedVerification Indicates that the driver may perform = a more + exhaustive verification operation of the 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 SimpleNetwork parameter was NULL or did no= t 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 *SimpleNetwork, + IN BOOLEAN ExtendedVerification + ); + +/** + Initialize the simple network protocol. + + This routine calls ::Ax88179MacAddressGet to obtain the + MAC address. + + @param [in] NicDevice NIC_DEVICE_INSTANCE pointer + + @retval EFI_SUCCESS Setup was successful + +**/ +EFI_STATUS +SN_Setup ( + IN NIC_DEVICE *NicDevice + ); + +/** + This routine starts the network interface. + + @param [in] SimpleNetwork Protocol instance pointer + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_ALREADY_STARTED The network interface was already started. + @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did no= t 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 *SimpleNetwork + ); + +/** + Set the MAC address. + + This function modifies or resets the current station address of a + network interface. If Reset is TRUE, then the current station address + is set ot the network interface's permanent address. If Reset if FALSE + then the current station address is changed to the address specified by + New. + + This routine calls ::Ax88179MacAddressSet to update the MAC address + in the network adapter. + + @param [in] SimpleNetwork Protocol instance pointer + @param [in] Reset Flag used to reset the station address to t= he + network interface's permanent address. + @param [in] New New station address to be used for the netw= ork + interface. + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did no= t 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 *SimpleNetwork, + IN BOOLEAN Reset, + IN EFI_MAC_ADDRESS *New + ); + +/** + This function resets or collects the statistics on a network interface. + If the size of the statistics table specified by StatisticsSize is not + big enough for all of the statistics that are collected by the network + interface, then a partial buffer of statistics is returned in + StatisticsTable. + + @param [in] SimpleNetwork Protocol instance pointer + @param [in] Reset Set to TRUE to reset the statistics for the= network interface. + @param [in, out] StatisticsSize On input the size, in bytes, of Statist= icsTable. On output + the size, in bytes, of the resulting table= of statistics. + @param [out] StatisticsTable A pointer to the EFI_NETWORK_STATISTICS str= ucture that + conains the statistics. + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_BUFFER_TOO_SMALL The StatisticsTable is NULL or the buffer = is too small. + @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did no= t 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 *SimpleNetwork, + IN BOOLEAN Reset, + IN OUT UINTN *StatisticsSize, + OUT EFI_NETWORK_STATISTICS *StatisticsTable + ); + +/** + This function stops a network interface. This call is only valid + if the network interface is in the started state. + + @param [in] SimpleNetwork Protocol instance pointer + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did no= t 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 *SimpleNetwork + ); + +/** + This function releases the memory buffers assigned in the Initialize() c= all. + Ending transmits and receives are lost, and interrupts are cleared and d= isabled. + After this call, only Initialize() and Stop() calls may be used. + + @param [in] SimpleNetwork Protocol instance pointer + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did no= t 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 *SimpleNetwork + ); + +/** + Send a packet over the network. + + This function places the packet specified by Header and Buffer on + the transmit queue. This function performs a non-blocking transmit + operation. When the transmit is complete, the buffer is returned + via the GetStatus() call. + + This routine calls ::Ax88179Rx to empty the network adapter of + receive packets. The routine then passes the transmit packet + to the network adapter. + + @param [in] SimpleNetwork Protocol instance pointer + @param [in] HeaderSize The size, in bytes, of the media header to= be filled in by + the Transmit() function. If HeaderSize is= non-zero, then + it must be equal to SimpleNetwork->Mode->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] Buffer A pointer to the packet (media header follo= wed 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] SrcAddr The source HW MAC address. If HeaderSize i= s zero, then + this parameter is ignored. If HeaderSize = is nonzero and + SrcAddr is NULL, then SimpleNetwork->Mode-= >CurrentAddress + is used for the source HW MAC address. + @param [in] DestAddr The destination HW MAC address. If HeaderS= ize is zero, then + this parameter is ignored. + @param [in] Protocol The type of header to build. If HeaderSize= is zero, then + this parameter is ignored. + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_NOT_READY The network interface is too busy to accep= t this transmit request. + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. + @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did no= t 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 *SimpleNetwork, + IN UINTN HeaderSize, + IN UINTN BufferSize, + IN VOID *Buffer, + IN EFI_MAC_ADDRESS *SrcAddr, + IN EFI_MAC_ADDRESS *DestAddr, + IN UINT16 *Protocol + ); + +//------------------------------------------------------------------------= ------ +// Support Routines +//------------------------------------------------------------------------= ------ + +/** + Get the MAC address + + This routine calls ::Ax88179UsbCommand to request the MAC + address from the network adapter. + + @param [in] NicDevice Pointer to the NIC_DEVICE structure + @param [out] MacAddress Address of a six byte buffer to receive the= MAC address. + + @retval EFI_SUCCESS The MAC address is available. + @retval other The MAC address is not valid. + +**/ +EFI_STATUS +Ax88179MacAddressGet ( + IN NIC_DEVICE *NicDevice, + OUT UINT8 *MacAddress + ); + + +/** + Clear the multicast hash table + + @param [in] NicDevice Pointer to the NIC_DEVICE structure + +**/ +VOID +Ax88179MulticastClear ( + IN NIC_DEVICE *NicDevice + ); + +/** + Enable a multicast address in the multicast hash table + + This routine calls ::Ax88179Crc to compute the hash bit for + this MAC address. + + @param [in] NicDevice Pointer to the NIC_DEVICE structure + @param [in] MacAddress Address of a six byte buffer to containing t= he MAC address. + +**/ +VOID +Ax88179MulticastSet ( + IN NIC_DEVICE *NicDevice, + IN UINT8 *MacAddress + ); + +/** + Start the link negotiation + + This routine calls ::Ax88179PhyWrite to start the PHY's link + negotiation. + + @param [in] NicDevice Pointer to the NIC_DEVICE structure + + @retval EFI_SUCCESS The link negotiation was started. + @retval other Failed to start the link negotiation. + +**/ +EFI_STATUS +Ax88179NegotiateLinkStart ( + IN NIC_DEVICE *NicDevice + ); + +/** + Complete the negotiation of the PHY link + + This routine calls ::Ax88179PhyRead to determine if the + link negotiation is complete. + + @param [in] NicDevice Pointer to the NIC_DEVICE structure + @param [in, out] PollCount Address of number of times this routine was = polled + @param [out] Complete Address of boolean to receive complate status. + @param [out] LinkUp Address of boolean to receive link status, TR= UE=3Dup. + @param [out] HiSpeed Address of boolean to receive link speed, TRU= E=3D100Mbps. + @param [out] FullDuplex Address of boolean to receive link duplex, TR= UE=3Dfull. + + @retval EFI_SUCCESS The MAC address is available. + @retval other The MAC address is not valid. + +**/ +EFI_STATUS +Ax88179NegotiateLinkComplete ( + IN NIC_DEVICE *NicDevice, + IN OUT UINTN *PollCount, + OUT BOOLEAN *Complete, + OUT BOOLEAN *LinkUp, + OUT BOOLEAN *HiSpeed, + OUT BOOLEAN *GigaSpeed, + OUT BOOLEAN *FullDuplex + ); + +/** + Read a register from the PHY + + This routine calls ::Ax88179UsbCommand to read a PHY register. + + @param [in] NicDevice Pointer to the NIC_DEVICE structure + @param [in] RegisterAddress Number of the register to read. + @param [in, out] PhyData Address of a buffer to receive the PHY regis= ter value + + @retval EFI_SUCCESS The PHY data is available. + @retval other The PHY data is not valid. + +**/ + + +/** + Reset the AX88179 + + This routine uses ::Ax88179UsbCommand to reset the network + adapter. This routine also uses ::Ax88179PhyWrite to reset + the PHY. + + @param [in] NicDevice Pointer to the NIC_DEVICE structure + + @retval EFI_SUCCESS The MAC address is available. + @retval other The MAC address is not valid. + +**/ +EFI_STATUS +Ax88179Reset ( + IN NIC_DEVICE *NicDevice + ); + +/** + Enable or disable the receiver + + This routine calls ::Ax88179UsbCommand to update the + receiver state. This routine also calls ::Ax88179MacAddressSet + to establish the MAC address for the network adapter. + + @param [in] NicDevice Pointer to the NIC_DEVICE structure + @param [in] RxFilter Simple network RX filter mask value + + @retval EFI_SUCCESS The MAC address was set. + @retval other The MAC address was not set. + +**/ +EFI_STATUS +Ax88179RxControl ( + IN NIC_DEVICE *NicDevice, + IN UINT32 RxFilter + ); + + EFI_STATUS +Ax88179ReloadSrom ( + IN NIC_DEVICE *NicDevice + ); + +/** + Read an SROM location + + This routine calls ::Ax88179UsbCommand to read data from the + SROM. + + @param [in] NicDevice Pointer to the NIC_DEVICE structure + @param [in] Address SROM address + @param [out] Data Buffer to receive the data + + @retval EFI_SUCCESS The read was successful + @retval other The read failed + +**/ +EFI_STATUS +Ax88179SromRead ( + IN NIC_DEVICE *NicDevice, + IN UINT32 Address, + OUT UINT16 *Data + ); + + +EFI_STATUS +Ax88179EnableSromWrite ( + IN NIC_DEVICE *NicDevice + ); + + +EFI_STATUS +Ax88179DisableSromWrite ( + IN NIC_DEVICE *NicDevice + ); + +EFI_STATUS +Ax88179SromWrite ( + IN NIC_DEVICE *NicDevice, + IN UINT32 Address, + OUT UINT16 *Data + ); + +/** + Send a command to the USB device. + + @param [in] NicDevice Pointer to the NIC_DEVICE structure + @param [in] Request Pointer to the request structure + @param [in, out] Buffer Data buffer address + + @retval EFI_SUCCESS The USB transfer was successful + @retval other The USB transfer failed + +**/ + +EFI_STATUS +Ax88179UsbCommand ( + IN NIC_DEVICE *NicDevice, + IN USB_DEVICE_REQUEST *Request, + IN OUT VOID *Buffer + ); + +//------------------------------------------------------------------------= ------ +// EFI Component Name Protocol Support +//------------------------------------------------------------------------= ------ +extern EFI_DRIVER_BINDING_PROTOCOL gDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gComponentName; ///< Component name= protocol declaration +extern EFI_COMPONENT_NAME2_PROTOCOL gComponentName2; ///< Component name= 2 protocol declaration + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form 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] This A pointer to the EFI_COMPONENT_NAME2_PROTOC= OL or + EFI_COMPONENT_NAME_PROTOCOL instance. + @param [in] Language A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the 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] DriverName A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver 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 *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + + +/** + 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] This A pointer to the EFI_COMPONENT_NAME2_PROTOC= OL 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] Language 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] ControllerName 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 *This, + IN EFI_HANDLE ControllerHandle, + IN OPTIONAL EFI_HANDLE ChildHandle, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +EFI_STATUS +Ax88179SetMedium ( + IN NIC_DEVICE * NicDevice + ); + +//------------------------------------------------------------------------= ----- + + +#define ACCESS_MAC 0x01 +#define ACCESS_PHY 0x02 + +#define PLSR 0x02 + #define PLSR_USB_FS 0x01 + #define PLSR_USB_HS 0x02 + #define PLSR_USB_SS 0x04 + +#define NODE_ID 0x10 + +#define RXCTL 0x0b + #define RXCTL_PRO 0x0001 ///< Receive all packets + #define RXCTL_AMALL 0x0002 ///< Receive all multicast packets + #define RXCTL_SEP 0x0004 ///< Save error packets + #define RXCTL_AB 0x0008 ///< Receive broadcast packets + #define RXCTL_AM 0x0010 ///< Use multicast destination 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 *NicDevice, + IN UINT8 RegisterAddress, + IN OUT UINT16 *PhyData + ); + +EFI_STATUS +Ax88179PhyWrite ( + IN NIC_DEVICE *NicDevice, + IN UINT8 RegisterAddress, + IN UINT16 PhyData + ); + +EFI_STATUS +Ax88179MacRead ( + IN UINT8 Offset, + IN UINT8 Length, + IN NIC_DEVICE * NicDevice, + IN OUT VOID *Data + ); + +EFI_STATUS +Ax88179SetIInInterval ( + IN NIC_DEVICE *NicDevice, + IN UINT8 Offset + ); + +EFI_STATUS +Ax88179MacWrite ( + IN UINT8 Offset, + IN UINT8 Length, + IN NIC_DEVICE *NicDevice, + IN OUT VOID *Data + ); + +EFI_STATUS +Ax88179MacAddressGet ( + IN NIC_DEVICE *NicDevice, + OUT UINT8 *MacAddress + ); + +EFI_STATUS +Ax88179MacAddressSet ( + IN NIC_DEVICE *NicDevice, + OUT UINT8 *MacAddress + ); + +BOOLEAN +Ax88179GetLinkStatus ( + IN NIC_DEVICE *NicDevice +); + +EFI_STATUS +Ax88179BulkIn( + IN NIC_DEVICE *NicDevice +); + + +#endif // AX88179_H_ diff --git a/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.c b/Drivers= /ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.c new file mode 100644 index 000000000000..a2af3c5618d1 --- /dev/null +++ b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/Ax88179.c @@ -0,0 +1,1042 @@ + /** @file + Implement the interface to the AX88179 Ethernet controller. + + This module implements the interface to the ASIX AX88179 + USB to Ethernet MAC with integrated 10/100 PHY. Note that this implemen= tation + only supports the integrated PHY since no other test cases were availabl= e. + + Copyright (c) 2011, Intel Corporation + Copyright (c) 2020, ARM Limited. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Ax88179.h" + + +/** + Compute the CRC + + @param [in] MacAddress Address of a six byte buffer to containing t= he MAC address. + + @returns The CRC-32 value associated with this MAC address + +**/ +UINT32 +Ax88179Crc ( + IN UINT8 *MacAddress + ) +{ + UINT32 BitNumber; + INT32 Carry; + INT32 Crc; + UINT32 Data; + UINT8 *End; + + // + // Walk the MAC address + // + Crc =3D -1; + End =3D &MacAddress[PXE_HWADDR_LEN_ETHER]; + while (End > MacAddress) { + Data =3D *MacAddress++; + + + // + // 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 (Carry !=3D 0) { + 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] NicDevice Pointer to the NIC_DEVICE structure + @param [out] MacAddress Address of a six byte buffer to receive the= MAC address. + + @retval EFI_SUCCESS The MAC address is available. + @retval other The MAC address is not valid. + +**/ +EFI_STATUS +Ax88179MacAddressGet ( + IN NIC_DEVICE *NicDevice, + OUT UINT8 *MacAddress + ) +{ + EFI_STATUS Status; + + Status =3D Ax88179MacRead (NODE_ID, + PXE_HWADDR_LEN_ETHER, + NicDevice, + MacAddress); + + return Status; +} + +/** + Set the MAC address + + This routine calls ::Ax88179UsbCommand to set the MAC address + in the network adapter. + + @param [in] NicDevice Pointer to the NIC_DEVICE structure + @param [in] MacAddress Address of a six byte buffer to containing t= he new MAC address. + + @retval EFI_SUCCESS The MAC address was set. + @retval other The MAC address was not set. + +**/ +EFI_STATUS +Ax88179MacAddressSet ( + IN NIC_DEVICE *NicDevice, + OUT UINT8 *MacAddress + ) +{ + EFI_STATUS Status; + + Status =3D Ax88179MacWrite (NODE_ID, + PXE_HWADDR_LEN_ETHER, + NicDevice, + MacAddress); + + return Status; +} + +/** + Clear the multicast hash table + + @param [in] NicDevice Pointer to the NIC_DEVICE structure + +**/ +VOID +Ax88179MulticastClear ( + IN NIC_DEVICE *NicDevice + ) +{ + int Index =3D 0; + // + // Clear the multicast hash table + // + for (Index =3D 0 ; Index < 8 ; Index ++) + NicDevice->MulticastHash[Index] =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] NicDevice Pointer to the NIC_DEVICE structure + @param [in] MacAddress Address of a six byte buffer to containing t= he MAC address. + +**/ +VOID +Ax88179MulticastSet ( + IN NIC_DEVICE *NicDevice, + IN UINT8 *MacAddress + ) +{ + UINT32 Crc; + + // + // Compute the CRC on the destination address + // + Crc =3D Ax88179Crc (MacAddress) >> 26; + + // + // Set the bit corresponding to the destination address + // + NicDevice->MulticastHash [Crc >> 3] |=3D (1 << (Crc & 7)); + +} + +/** + Start the link negotiation + + This routine calls ::Ax88179PhyWrite to start the PHY's link + negotiation. + + @param [in] NicDevice Pointer to the NIC_DEVICE structure + + @retval EFI_SUCCESS The link negotiation was started. + @retval other Failed to start the link negotiation. + +**/ +EFI_STATUS +Ax88179NegotiateLinkStart ( + IN NIC_DEVICE *NicDevice + ) +{ + UINT16 Control =3D 0; + EFI_STATUS Status; + +#if FORCE_100Mbps + Ax88179PhyRead (NicDevice, + 0x09, + &Control); + Control &=3D 0xFCFF; + Ax88179PhyWrite (NicDevice, 0x09, Control); +#endif + + // + // Set the link speed and duplex + // + Control =3D BMCR_AUTONEGOTIATION_ENABLE + | BMCR_RESTART_AUTONEGOTIATION; + if (NicDevice->LinkSpeed1000Mbps) { + Control |=3D BMCR_1000MBPS; + } else if (NicDevice->LinkSpeed100Mbps) { + Control |=3D BMCR_100MBPS; + } + + if (NicDevice->FullDuplex) { + Control |=3D BMCR_FULL_DUPLEX; + } + Status =3D Ax88179PhyWrite (NicDevice, PHY_BMCR, Control); + if (!EFI_ERROR(Status)) + gBS->Stall(3000000); + // + // Return the operation status + // + return Status; +} + + + +/** + Complete the negotiation of the PHY link + + This routine calls ::Ax88179PhyRead to determine if the + link negotiation is complete. + + @param [in] NicDevice Pointer to the NIC_DEVICE structure + @param [in, out] PollCount Address of number of times this routine was = polled + @param [out] Complete Address of boolean to receive complate status. + @param [out] LinkUp Address of boolean to receive link status, TR= UE=3Dup. + @param [out] HiSpeed Address of boolean to receive link speed, TRU= E=3D100Mbps. + @param [out] FullDuplex Address of boolean to receive link duplex, TR= UE=3Dfull. + + @retval EFI_SUCCESS The MAC address is available. + @retval other The MAC address is not valid. + +**/ +EFI_STATUS +Ax88179NegotiateLinkComplete ( + IN NIC_DEVICE *NicDevice, + IN OUT UINTN *PollCount, + OUT BOOLEAN *Complete, + OUT BOOLEAN *LinkUp, + OUT BOOLEAN *HiSpeed, + OUT BOOLEAN *GigaSpeed, + OUT BOOLEAN *FullDuplex + ) +{ + UINT16 PhyData; + EFI_STATUS Status; + + // + // Determine if the link is up. + // + *Complete =3D FALSE; + + // + // Get the link status + // + Status =3D Ax88179PhyRead (NicDevice, + PHY_PHYSR, + &PhyData); + if (EFI_ERROR (Status)) { + return Status; + } + + *LinkUp =3D ((PhyData & PHYSR_LINK) !=3D 0); + if (*LinkUp) { + // + // Determine if the autonegotiation is complete. + // + Status =3D Ax88179PhyRead (NicDevice, + PHY_BMSR, + &PhyData); + if (EFI_ERROR(Status)) { + return Status; + } + + *Complete =3D ((PhyData & BMSR_AUTONEG_CMPLT) !=3D 0); + + if (*Complete !=3D 0) { + // + // Get the partners capabilities. + // + Status =3D Ax88179PhyRead (NicDevice, + PHY_PHYSR, + &PhyData); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Autonegotiation is complete + // Determine the link speed. + // + *GigaSpeed =3D ((PhyData & PHYSR_SPEED_MASK) =3D=3D PHYSR_1000); + *HiSpeed =3D ((PhyData & PHYSR_SPEED_MASK) =3D=3D PHYSR_100); + + // + // Determine the link duplex. + // + *FullDuplex =3D ((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] NicDevice Pointer to the NIC_DEVICE structure + @param [in] RegisterAddress Number of the register to read. + @param [in, out] PhyData Address of a buffer to receive the PHY regis= ter value + + @retval EFI_SUCCESS The PHY data is available. + @retval other The PHY data is not valid. + +**/ +EFI_STATUS +Ax88179PhyRead ( + IN NIC_DEVICE *NicDevice, + IN UINT8 RegisterAddress, + IN OUT UINT16 *PhyData + ) +{ + USB_DEVICE_REQUEST SetupMsg; + EFI_STATUS Status; + + // + // Read the PHY register address. + // + SetupMsg.RequestType =3D USB_ENDPOINT_DIR_IN + | USB_REQ_TYPE_VENDOR + | USB_TARGET_DEVICE; + SetupMsg.Request =3D ACCESS_PHY; + SetupMsg.Value =3D NicDevice->PhyId; + SetupMsg.Index =3D RegisterAddress; + SetupMsg.Length =3D sizeof (*PhyData); + Status =3D Ax88179UsbCommand (NicDevice, + &SetupMsg, + PhyData); + + // + // Return the operation status. + // + return Status; +} + + +/** + Write to a PHY register + + This routine calls ::Ax88179UsbCommand to write a PHY register. + + @param [in] NicDevice Pointer to the NIC_DEVICE structure + @param [in] RegisterAddress Number of the register to read. + @param [in] PhyData Address of a buffer to receive the PHY 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 *NicDevice, + 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 NicDevice->PhyId; + SetupMsg.Index =3D RegisterAddress; + SetupMsg.Length =3D sizeof (PhyData); + Status =3D Ax88179UsbCommand (NicDevice, + &SetupMsg, + &PhyData); + // + // Return the operation status. + // + return Status; +} + + +/** + Reset the AX88179 + + This routine uses ::Ax88179UsbCommand to reset the network + adapter. This routine also uses ::Ax88179PhyWrite to reset + the PHY. + + @param [in] NicDevice Pointer to the NIC_DEVICE structure + + @retval EFI_SUCCESS The MAC address is available. + @retval other The MAC address is not valid. + +**/ +EFI_STATUS +Ax88179Reset ( + IN NIC_DEVICE *NicDevice + ) +{ + EFI_STATUS Status; + UINT16 Val; + UINT8 Val8; + + Status =3D Ax88179SetIInInterval(NicDevice, 0xff); + + if (EFI_ERROR(Status)) goto err; + + Val8 =3D 0; + Status =3D Ax88179MacRead (PLSR, + sizeof(Val8), + NicDevice, + &Val8); + + if (EFI_ERROR(Status)) goto err; + + if (Val8 & PLSR_USB_SS) + NicDevice->UsbMaxPktSize =3D 1024; + else + NicDevice->UsbMaxPktSize =3D 512; + + Val =3D 0; + Status =3D Ax88179MacWrite (PHYPWRRSTCTL, + sizeof (Val), + NicDevice, + &Val); + + if (EFI_ERROR(Status)) goto err; + + gBS->Stall (10000); + + Val =3D PHYPWRRSTCTL_IPRL; + Status =3D Ax88179MacWrite (PHYPWRRSTCTL, + sizeof (Val), + NicDevice, + &Val); + + if (EFI_ERROR(Status)){ + goto err; + } + + gBS->Stall (200000); + + Val =3D CLKSELECT_BCS | CLKSELECT_ACS; + Status =3D Ax88179MacWrite (CLKSELECT, + 1, + NicDevice, + &Val); + + if (EFI_ERROR(Status)) goto err; + + gBS->Stall (100000); + + Val =3D 0x52; + Status =3D Ax88179MacWrite (PAUSE_WATERLVL_HIGH, + 1, + NicDevice, + &Val); + + if (EFI_ERROR(Status)) goto err; + + Val =3D 0x34; + Status =3D Ax88179MacWrite (PAUSE_WATERLVL_LOW, + 1, + NicDevice, + &Val); + + if (EFI_ERROR(Status)) goto err; + + Val =3D RXBINQCTRL_TIMEN | RXBINQCTRL_IFGEN | RXBINQCTRL_SIZEN; + + Status =3D Ax88179MacWrite (RXBINQCTRL, + 0x01, + NicDevice, + &Val); + + if (EFI_ERROR(Status)) goto err; + + Val =3D 0; + Status =3D Ax88179MacWrite (RXBINQTIMERL, + 0x01, + NicDevice, + &Val); + + if (EFI_ERROR(Status)) goto err; + + Val =3D 0; + Status =3D Ax88179MacWrite (RXBINQTIMERH, + 0x01, + NicDevice, + &Val); + + if (EFI_ERROR(Status)) goto err; + + Val =3D 12; //AX88179_BULKIN_SIZE_INK - 1; + Status =3D Ax88179MacWrite (RXBINQSIZE, + 0x01, + NicDevice, + &Val); + + if (EFI_ERROR(Status)) goto err; + + Val =3D 0x0F; + Status =3D Ax88179MacWrite (RXBINQIFG, + 0x01, + NicDevice, + &Val); + +err: + return Status; +} + +EFI_STATUS +Ax88179RxControl ( + IN NIC_DEVICE *NicDevice, + 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 (RxFilter !=3D 0) { + // + // Enable the receiver + // + Status =3D Ax88179MacRead (MEDIUMSTSMOD, + sizeof (MediumStatus), + NicDevice, + &MediumStatus); + + if (!EFI_ERROR (Status) && NicDevice->CurMediumStatus !=3D MediumStatu= s) { + MediumStatus =3D MEDIUMSTSMOD_RE | MEDIUMSTSMOD_ONE; + if (NicDevice->FullDuplex) { + MediumStatus |=3D MEDIUMSTSMOD_TFC | MEDIUMSTSMOD_RFC | MEDIUMST= SMOD_FD; + } else { + MediumStatus &=3D ~(MEDIUMSTSMOD_TFC | MEDIUMSTSMOD_RFC | MEDIUM= STSMOD_FD); + } + if (NicDevice->LinkSpeed1000Mbps) { + MediumStatus |=3D MEDIUMSTSMOD_GM; + MediumStatus |=3D MEDIUMSTSMOD_ENCK; + MediumStatus &=3D ~MEDIUMSTSMOD_PS; + } else { + MediumStatus &=3D ~MEDIUMSTSMOD_GM; + MediumStatus &=3D ~MEDIUMSTSMOD_ENCK; + if (NicDevice->LinkSpeed100Mbps) { + MediumStatus |=3D MEDIUMSTSMOD_PS; + } else { + MediumStatus &=3D ~MEDIUMSTSMOD_PS; + } + } + Status =3D Ax88179MacWrite (MEDIUMSTSMOD, + sizeof (MediumStatus), + NicDevice, + &MediumStatus); + if (!EFI_ERROR (Status)) { + NicDevice->CurMediumStatus =3D MediumStatus; + } + } + } + + RxControl =3D RXCTL_SO | RXCTL_IPE; + + // + // Enable multicast if requested + // + if ((RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) !=3D 0) { + RxControl |=3D RXCTL_AM; + // + // Update the multicast hash table + // + Status =3D Ax88179MacWrite (MULCATFLTARRY, + 8, + NicDevice, + &NicDevice->MulticastHash); + } + + // + // Enable all multicast if requested + // + if ((RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) !=3D 0= ) { + RxControl |=3D RXCTL_AMALL; + } + // + // Enable broadcast if requested + // + if ((RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) !=3D 0) { + RxControl |=3D RXCTL_AB; + } + + // + // Enable promiscuous mode if requested + // + if ((RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) !=3D 0) { + RxControl |=3D RXCTL_PRO; + } + + // + // Update the receiver control + // + if (NicDevice->CurRxControl !=3D RxControl) { + Status =3D Ax88179MacWrite (RXCTL, + 0x02, + NicDevice, + &RxControl); + if (!EFI_ERROR (Status)) + NicDevice->CurRxControl =3D RxControl; + } + + // + // Return the operation status + // + return Status; +} + +EFI_STATUS +Ax88179ReloadSrom ( + IN NIC_DEVICE *NicDevice + ) +{ + 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] NicDevice Pointer to the NIC_DEVICE structure + @param [in] Address SROM address + @param [out] Data Buffer to receive the data + + @retval EFI_SUCCESS The read was successful + @retval other The read failed + +**/ +EFI_STATUS +Ax88179SromRead ( + IN NIC_DEVICE *NicDevice, + IN UINT32 Address, + OUT UINT16 *Data + ) +{ + EFI_STATUS Status; + + Status =3D EFI_UNSUPPORTED; + return Status; +} + +EFI_STATUS +Ax88179EnableSromWrite ( + IN NIC_DEVICE *NicDevice + ) +{ + EFI_STATUS Status; + + Status =3D EFI_UNSUPPORTED; + return Status; +} + + +EFI_STATUS +Ax88179DisableSromWrite ( + IN NIC_DEVICE *NicDevice + ) +{ + 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] NicDevice Pointer to the NIC_DEVICE structure + @param [in] Address SROM address + @param [out] Data Buffer of data to write + + @retval EFI_SUCCESS The write was successful + @retval other The write failed + +**/ +EFI_STATUS +Ax88179SromWrite ( + IN NIC_DEVICE *NicDevice, + IN UINT32 Address, + IN UINT16 *Data + ) +{ + EFI_STATUS Status; + + Status =3D EFI_UNSUPPORTED; + return Status; +} + +/** + Send a command to the USB device. + + @param [in] NicDevice Pointer to the NIC_DEVICE structure + @param [in] Request Pointer to the request structure + @param [in, out] Buffer Data buffer address + + @retval EFI_SUCCESS The USB transfer was successful + @retval other The USB transfer failed + +**/ +EFI_STATUS +Ax88179UsbCommand ( + IN NIC_DEVICE *NicDevice, + IN USB_DEVICE_REQUEST *Request, + IN OUT VOID *Buffer + ) +{ + EFI_USB_DATA_DIRECTION Direction; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_STATUS Status =3D EFI_TIMEOUT; + UINT32 CmdStatus =3D EFI_USB_NOERROR; + int i; + // + // Determine the transfer direction + // + Direction =3D EfiUsbNoData; + if (Request->Length !=3D 0) { + Direction =3D ((Request->RequestType & USB_ENDPOINT_DIR_IN) !=3D 0) + ? EfiUsbDataIn : EfiUsbDataOut; + } + + // + // Issue the command + // + UsbIo =3D NicDevice->UsbIo; + + for (i =3D 0 ; i < 3 && EFI_TIMEOUT =3D=3D Status; i++) { + Status =3D UsbIo->UsbControlTransfer (UsbIo, + Request, + Direction, + USB_BUS_TIMEOUT, + Buffer, + Request->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 *NicDevice, + IN OUT VOID *Data + ) +{ + + 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 (NicDevice, + &SetupMsg, + Data); + + return Status; + +} + +EFI_STATUS +Ax88179MacWrite ( + IN UINT8 Offset, + IN UINT8 Length, + IN NIC_DEVICE *NicDevice, + IN OUT VOID *Data + ) +{ + + EFI_STATUS Status; + USB_DEVICE_REQUEST SetupMsg; + + SetupMsg.RequestType =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 (NicDevice, + &SetupMsg, + Data); + + return Status; + +} + +EFI_STATUS +Ax88179SetIInInterval ( + IN NIC_DEVICE *NicDevice, + 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 (NicDevice, + &SetupMsg, + NULL); + + return Status; + +} + +EFI_STATUS +Ax88179SetMedium ( + IN NIC_DEVICE *NicDevice + ) +{ + UINT16 MediumStatus; + EFI_STATUS Status; + + MediumStatus =3D MEDIUMSTSMOD_RE | MEDIUMSTSMOD_ONE; + if (NicDevice->FullDuplex) { + MediumStatus |=3D MEDIUMSTSMOD_TFC | MEDIUMSTSMOD_RFC | MEDIUMSTSMOD_F= D; + } else { + MediumStatus &=3D ~(MEDIUMSTSMOD_TFC | MEDIUMSTSMOD_RFC | MEDIUMSTSMOD= _FD); + } + if (NicDevice->LinkSpeed1000Mbps) { + MediumStatus |=3D MEDIUMSTSMOD_GM; + MediumStatus &=3D ~MEDIUMSTSMOD_PS; + } else { + MediumStatus &=3D ~MEDIUMSTSMOD_GM; + if (NicDevice->LinkSpeed100Mbps) { + MediumStatus |=3D MEDIUMSTSMOD_PS; + } else { + MediumStatus &=3D ~MEDIUMSTSMOD_PS; + } + } + Status =3D Ax88179MacWrite (MEDIUMSTSMOD, + sizeof (MediumStatus), + NicDevice, + &MediumStatus); + if (!EFI_ERROR (Status)) { + NicDevice->CurMediumStatus =3D MediumStatus; + } + + return Status; +} + + +BOOLEAN +Ax88179GetLinkStatus ( + IN NIC_DEVICE *NicDevice +) +{ + UINT32 CmdStatus; + EFI_USB_IO_PROTOCOL *UsbIo; + UINT64 IntData =3D 0; + UINTN IntDataLeng =3D 8; + EFI_STATUS Status; + + // + // Issue the command + // + UsbIo =3D NicDevice->UsbIo; + Status =3D UsbIo->UsbSyncInterruptTransfer(UsbIo, + 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 *NicDevice +) +{ + int i; + UINT16 Val; + UINTN LengthInBytes =3D 0; + UINTN TmpLen =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 *UsbIo; + UINT32 TransferStatus; + + NicDevice->SkipRXCnt =3D 0; + + UsbIo =3D NicDevice->UsbIo; + for (i =3D 0 ; i < (AX88179_MAX_BULKIN_SIZE / 512) && UsbIo !=3D NULL; i= ++) { + VOID* TmpAddr =3D 0; + + if (NicDevice->SetZeroLen) { + Val =3D PHYPWRRSTCTL_IPRL | PHYPWRRSTCTL_BZ; + Status =3D Ax88179MacWrite (PHYPWRRSTCTL, + sizeof (Val), + NicDevice, + &Val); + if (EFI_ERROR(Status)) { + LengthInBytes =3D 0; + Status =3D EFI_NOT_READY; + goto no_pkt; + } + NicDevice->SetZeroLen =3D FALSE; + } + TmpAddr =3D (VOID*) &NicDevice->BulkInbuf[LengthInBytes]; + + Status =3D EFI_NOT_READY; + Status =3D UsbIo->UsbBulkTransfer (UsbIo, + USB_ENDPOINT_DIR_IN | BULK_IN_ENDPOINT, + TmpAddr, + &TmpLen, + BULKIN_TIMEOUT, + &TransferStatus); + + if ((!EFI_ERROR (Status)) && (!EFI_ERROR (TransferStatus)) && TmpLen != =3D 0) { + LengthInBytes +=3D TmpLen; + if ((TmpLen % NicDevice->UsbMaxPktSize) !=3D 0) { + goto done; + } + CURBufSize =3D CURBufSize - TmpLen; + TmpLen =3D CURBufSize; + NicDevice->SetZeroLen =3D TRUE; + } else if ((!EFI_ERROR (Status)) && + (!EFI_ERROR (TransferStatus)) && + (TmpLen =3D=3D 0) && + LengthInBytes) { + if (PREBufSize =3D=3D CURBufSize) { + goto done; + } + TmpLen =3D CURBufSize; + PREBufSize =3D CURBufSize; + NicDevice->SetZeroLen =3D TRUE; + } else if ((!EFI_ERROR (Status)) && + (!EFI_ERROR (TransferStatus)) && + (TmpLen =3D=3D 0)) { + NicDevice->SetZeroLen =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) { + NicDevice->SetZeroLen =3D TRUE; + LengthInBytes =3D 0; + Status =3D EFI_NOT_READY; + goto done; + } else { + NicDevice->SetZeroLen =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 *) (NicDevice->BulkInbuf + LengthInBytes - 4)); + tmplen =3D *((UINT16*) (NicDevice->BulkInbuf + LengthInBytes - 2)); + + if (((UINTN)(((TmpPktCnt * 4 + 4 + 7) & 0xfff8) + tmplen)) =3D=3D Leng= thInBytes) { + NicDevice->PktCnt =3D TmpPktCnt; + NicDevice->CurPktHdrOff =3D NicDevice->BulkInbuf + tmplen; + NicDevice->CurPktOff =3D NicDevice->BulkInbuf; + *((UINT16 *) (NicDevice->BulkInbuf + LengthInBytes - 4)) =3D 0; + *((UINT16*) (NicDevice->BulkInbuf + 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/ASIX/Bus/Usb/UsbNetworking/Ax88179/ComponentName.c b/D= rivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/ComponentName.c new file mode 100644 index 000000000000..daf917ce5b7d --- /dev/null +++ b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/ComponentName.c @@ -0,0 +1,223 @@ +/** @file + UEFI Component Name(2) protocol implementation. + + Copyright (c) 2011, Intel Corporation. All rights reserved. + Copyright (c) 2020, ARM Limited. All rights reserved + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Ax88179.h" + +/** + EFI Component Name Protocol declaration +**/ +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gComponentName = =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] This A pointer to the EFI_COMPONENT_NAME2_PROTOC= OL or + EFI_COMPONENT_NAME_PROTOCOL instance. + @param [in] Language A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the 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] DriverName A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver 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 *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + EFI_STATUS Status; + + + Status =3D LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mDriverNameTable, + DriverName, + (BOOLEAN)(This =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] This A pointer to the EFI_COMPONENT_NAME2_PROTOC= OL 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] Language 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] ControllerName 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 *This, + IN EFI_HANDLE ControllerHandle, + IN OPTIONAL EFI_HANDLE ChildHandle, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIoProtocol; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle !=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 ( + Language, + This->SupportedLanguages, + mControllerNameTable, + ControllerName, + (BOOLEAN)(This =3D=3D &gComponentName) + ); + + return Status; +} + diff --git a/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/DriverBinding.c b/D= rivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/DriverBinding.c new file mode 100644 index 000000000000..7a287cfbfb5d --- /dev/null +++ b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/DriverBinding.c @@ -0,0 +1,639 @@ +/** @file + Implement the driver binding protocol for Asix AX88179 Ethernet driver. + + Copyright (c) 2011, Intel Corporation + Copyright (c) 2020, ARM Limited. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Ax88179.h" + +/** + Verify the controller type + + @param [in] This Protocol instance pointer. + @param [in] Controller Handle of device to test. + @param [in] pRemainingDevicePath Not used. + + @retval EFI_SUCCESS This driver supports this device. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +DriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_USB_DEVICE_DESCRIPTOR Device; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_STATUS Status; + + // + // Connect to the USB stack + // + Status =3D gBS->OpenProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + (VOID **) &UsbIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (!EFI_ERROR (Status)) { + + // + // Get the interface descriptor to check the USB class and find a tra= nsport + // protocol handler. + // + Status =3D UsbIo->UsbGetDeviceDescriptor (UsbIo, &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; + } + } + + // + // Done with the USB stack + // + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + + // + // Return the device supported status + // + return Status; +} + + +/** + Start this driver on Controller by opening UsbIo and DevicePath protocol= s. + Initialize PXE structures, create a copy of the Controller Device Path w= ith the + NIC's MAC address apEnded to it, install the NetworkInterfaceIdentifier = protocol + on the newly created Device Path. + + @param [in] This Protocol instance pointer. + @param [in] Controller Handle of device to work with. + @param [in] pRemainingDevicePath Not used, always produce all possible 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 *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + NIC_DEVICE *NicDevice; + UINTN LengthInBytes; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath =3D NULL; + MAC_ADDR_DEVICE_PATH MacDeviceNode; + + // + // Allocate the device structure + // + LengthInBytes =3D sizeof (*NicDevice); + Status =3D gBS->AllocatePool ( + EfiBootServicesData, + LengthInBytes, + (VOID **) &NicDevice + ); + + if (EFI_ERROR (Status)) { + goto ERR; + } + + // + // Set the structure signature + // + ZeroMem (NicDevice, LengthInBytes); + NicDevice->Signature =3D DEV_SIGNATURE; + + Status =3D gBS->OpenProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + (VOID **) &NicDevice->UsbIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + goto ERR; + } + + // + // Initialize the simple network protocol + // + Status =3D SN_Setup (NicDevice); + + if (EFI_ERROR(Status)){ + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + goto ERR; + } + + // + // Set Device Path + // + Status =3D gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR(Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + goto ERR; + } + + ZeroMem (&MacDeviceNode, sizeof (MAC_ADDR_DEVICE_PATH)); + MacDeviceNode.Header.Type =3D MESSAGING_DEVICE_PATH; + MacDeviceNode.Header.SubType =3D MSG_MAC_ADDR_DP; + + SetDevicePathNodeLength (&MacDeviceNode.Header, sizeof (MAC_ADDR_DEVICE_= PATH)); + + CopyMem (&MacDeviceNode.MacAddress, + &NicDevice->SimpleNetworkData.CurrentAddress, + PXE_HWADDR_LEN_ETHER); + + MacDeviceNode.IfType =3D NicDevice->SimpleNetworkData.IfType; + + NicDevice->MyDevPath =3D AppendDevicePathNode ( + ParentDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &Ma= cDeviceNode + ); + + NicDevice->Controller =3D NULL; + + // + // Install both the simple network and device path protocols. + // + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &NicDevice->Controller, + &gEfiCallerIdGuid, + NicDevice, + &gEfiSimpleNetworkProtocolGuid, + &NicDevice->SimpleNetwork, + &gEfiDevicePathProtocolGuid, + NicDevice->MyDevPath, + NULL + ); + + if (EFI_ERROR(Status)){ + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller); + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + goto ERR; + } + + // + // Open For Child Device + // + Status =3D gBS->OpenProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + (VOID **) &NicDevice->UsbIo, + This->DriverBindingHandle, + NicDevice->Controller, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + + if (EFI_ERROR(Status)){ + gBS->UninstallMultipleProtocolInterfaces ( + &NicDevice->Controller, + &gEfiCallerIdGuid, + NicDevice, + &gEfiSimpleNetworkProtocolGuid, + &NicDevice->SimpleNetwork, + &gEfiDevicePathProtocolGuid, + NicDevice->MyDevPath, + NULL + ); + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller); + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + goto ERR; + } + + return Status; + + +ERR: + + if (NicDevice->BulkInbuf !=3D NULL) { + gBS->FreePool (NicDevice->BulkInbuf); + } + + if (NicDevice->TxTest !=3D NULL) { + gBS->FreePool (NicDevice->TxTest); + } + + if (NicDevice->MyDevPath !=3D NULL) { + gBS->FreePool (NicDevice->MyDevPath); + } + + if (NicDevice !=3D NULL) { + gBS->FreePool (NicDevice); + } + + return Status; +} + +/** + Stop this driver on Controller by removing NetworkInterfaceIdentifier pr= otocol and + closing the DevicePath and PciIo protocols on Controller. + + @param [in] This Protocol instance pointer. + @param [in] Controller Handle of device to stop driver on. + @param [in] NumberOfChildren How many children need to be stopped. + @param [in] pChildHandleBuffer Not used. + + @retval EFI_SUCCESS This driver is removed Controller. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a de= vice error. + @retval other This driver was not removed from this devic= e. + +**/ +EFI_STATUS +EFIAPI +DriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL * This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE * ChildHandleBuffer + ) +{ + BOOLEAN AllChildrenStopped; + EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork; + EFI_STATUS Status =3D EFI_SUCCESS; + NIC_DEVICE *NicDevice; + UINTN Index; + + // + // Complete all outstanding transactions to Controller. + // Don't allow any new transaction to Controller to be started. + // + if (NumberOfChildren =3D=3D 0) { + Status =3D gBS->OpenProtocol ( + Controller, + &gEfiSimpleNetworkProtocolGuid, + (VOID **) &SimpleNetwork, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR(Status)) { + // + // This is a 2nd type handle(multi-lun root), it needs to close devi= cepath + // and usbio protocol. + // + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return EFI_SUCCESS; + } + + NicDevice =3D DEV_FROM_SIMPLE_NETWORK (SimpleNetwork); + + Status =3D gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiCallerIdGuid, + NicDevice, + &gEfiSimpleNetworkProtocolGuid, + &NicDevice->SimpleNetwork, + &gEfiDevicePathProtocolGuid, + NicDevice->MyDevPath, + NULL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Close the bus driver + // + Status =3D gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + Status =3D gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return EFI_SUCCESS; + } + + AllChildrenStopped =3D TRUE; + + for (Index =3D 0; Index < NumberOfChildren; Index++) { + Status =3D gBS->OpenProtocol ( + ChildHandleBuffer[Index], + &gEfiSimpleNetworkProtocolGuid, + (VOID **) &SimpleNetwork, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + AllChildrenStopped =3D FALSE; + continue; + } + + NicDevice =3D DEV_FROM_SIMPLE_NETWORK (SimpleNetwork); + + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ChildHandleBuffer[Index] + ); + + Status =3D gBS->UninstallMultipleProtocolInterfaces ( + ChildHandleBuffer[Index], + &gEfiCallerIdGuid, + NicDevice, + &gEfiSimpleNetworkProtocolGuid, + &NicDevice->SimpleNetwork, + &gEfiDevicePathProtocolGuid, + NicDevice->MyDevPath, + NULL + ); + + if (EFI_ERROR (Status)) { + Status =3D gBS->OpenProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + (VOID **) &NicDevice->UsbIo, + This->DriverBindingHandle, + ChildHandleBuffer[Index], + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + } else { + if (NicDevice->BulkInbuf !=3D NULL) { + gBS->FreePool (NicDevice->BulkInbuf); + } + + if (NicDevice->TxTest !=3D NULL) { + gBS->FreePool (NicDevice->TxTest); + } + + if (NicDevice->MyDevPath !=3D NULL) { + gBS->FreePool (NicDevice->MyDevPath); + } + + if (NicDevice !=3D NULL) { + gBS->FreePool (NicDevice); + } + } + } + + 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 *Handle; + EFI_STATUS Status; + + // + // Determine which devices are using this driver + // + BufferSize =3D 0; + Handle =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 ( + EfiBootServicesData, + BufferSize, + (VOID **) &Handle + ); + if (EFI_ERROR (Status)) { + break; + } + + // + // Locate the block IO devices + // + Status =3D gBS->LocateHandle ( + ByProtocol, + &gEfiCallerIdGuid, + NULL, + &BufferSize, + Handle); + if (EFI_ERROR (Status)) { + // + // Error getting handles + // + + break; + } + + // + // Remove any use of the driver + // + Max =3D BufferSize / sizeof (Handle[0]); + for (Index =3D 0; Max > Index; Index++) { + Status =3D DriverStop (&gDriverBinding, + Handle[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 (Handle !=3D NULL) { + gBS->FreePool (Handle); + } + + // + // Remove the protocols installed by the EntryPoint routine. + // + if (!EFI_ERROR (Status)) { + gBS->UninstallMultipleProtocolInterfaces ( + ImageHandle, + &gEfiDriverBindingProtocolGuid, + &gDriverBinding, + &gEfiComponentNameProtocolGuid, + &gComponentName, + &gEfiComponentName2ProtocolGuid, + &gComponentName2, + NULL + ); + } + + // + // Return the unload status + // + return Status; +} + + +/** +Ax88179 driver entry point. + +@param [in] ImageHandle Handle for the image. +@param [in] SystemTable Address of the system table. + +@retval EFI_SUCCESS Image successfully loaded. + +**/ +EFI_STATUS +EFIAPI +EntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_STATUS Status; + + // + // Enable unload support + // + Status =3D gBS->HandleProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **)&LoadedImage + ); + if (!EFI_ERROR (Status)) { + LoadedImage->Unload =3D DriverUnload; + } + + // + // Add the driver to the list of drivers + // + Status =3D EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gDriverBinding, + ImageHandle, + &gComponentName, + &gComponentName2 + ); + + return Status; +} diff --git a/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/SimpleNetwork.c b/D= rivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/SimpleNetwork.c new file mode 100644 index 000000000000..948b73031463 --- /dev/null +++ b/Drivers/ASIX/Bus/Usb/UsbNetworking/Ax88179/SimpleNetwork.c @@ -0,0 +1,1548 @@ +/** @file + Provides the Simple Network functions. + + Copyright (c) 2011, Intel Corporation + Copyright (c) 2020, ARM Limited. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Ax88179.h" + +/** + This function updates the filtering on the receiver. + + This support routine calls ::Ax88179MacAddressSet to update + the MAC address. This routine then rebuilds the multicast + hash by calling ::Ax88179MulticastClear and ::Ax88179MulticastSet. + Finally this routine enables the receiver by calling + ::Ax88179RxControl. + + @param [in] SimpleNetwork Simple network mode pointer + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did no= t 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 *SimpleNetwork + ) +{ + EFI_SIMPLE_NETWORK_MODE *Mode; + NIC_DEVICE *NicDevice; + EFI_STATUS Status; + UINT32 Index; + + // + // Set the MAC address + // + NicDevice =3D DEV_FROM_SIMPLE_NETWORK (SimpleNetwork); + Mode =3D SimpleNetwork->Mode; + // + // Clear the multicast hash table + // + Ax88179MulticastClear (NicDevice); + + // + // Load the multicast hash table + // + if ((Mode->ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) = !=3D 0) { + for (Index =3D 0; Index < Mode->MCastFilterCount; Index++) { + // + // Enable the next multicast address + // + Ax88179MulticastSet (NicDevice, + &Mode->MCastFilter[Index].Addr[0]); + } + } + + // + // Enable the receiver + // + Status =3D Ax88179RxControl (NicDevice, Mode->ReceiveFilterSetting); + + return Status; +} + + +/** + This function updates the SNP driver status. + + This function gets the current interrupt and recycled transmit + buffer status from the network interface. The interrupt status + and the media status are returned as a bit mask in InterruptStatus. + If InterruptStatus is NULL, the interrupt status will not be read. + Upon successful return of the media status, the MediaPresent field + of EFI_SIMPLE_NETWORK_MODE will be updated to reflect any change + of media status. If TxBuf is not NULL, a recycled transmit buffer + address will be retrived. If a recycled transmit buffer address + is returned in TxBuf, then the buffer has been successfully + transmitted, and the status for that buffer is cleared. + + This function calls ::Ax88179Rx to update the media status and + queue any receive packets. + + @param [in] SimpleNetwork Protocol instance pointer + @param [in] InterruptStatus A pointer to the bit mask of the current ac= tive 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] TxBuf Recycled transmit buffer address. The netwo= rk 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 SimpleNetwork parameter was NULL or did no= t 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 *SimpleNetwork, + OUT UINT32 *InterruptStatus, + OUT VOID **TxBuf + ) +{ + EFI_SIMPLE_NETWORK_MODE *Mode; + NIC_DEVICE *NicDevice; + EFI_STATUS Status =3D EFI_SUCCESS; + EFI_TPL TplPrevious; + + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + // + // Verify the parameters + // + if ((SimpleNetwork !=3D NULL) && (SimpleNetwork->Mode !=3D NULL)) { + // + // Return the transmit buffer + // + NicDevice =3D DEV_FROM_SIMPLE_NETWORK (SimpleNetwork); + + if ((TxBuf !=3D NULL) && (NicDevice->TxBuffer !=3D NULL)) { + *TxBuf =3D NicDevice->TxBuffer; + NicDevice->TxBuffer =3D NULL; + } + + Mode =3D SimpleNetwork->Mode; + if (EfiSimpleNetworkInitialized =3D=3D Mode->State) { + if ((TxBuf =3D=3D NULL) && (InterruptStatus =3D=3D NULL)) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + +#if REPORTLINK +#else + if (!NicDevice->LinkUp || !NicDevice->Complete) { +#endif + Status =3D Ax88179NegotiateLinkComplete (NicDevice, + &NicDevice->PollCount, + &NicDevice->Complete, + &NicDevice->LinkUp, + &NicDevice->LinkSpeed100Mb= ps, + &NicDevice->LinkSpeed1000M= bps, + &NicDevice->FullDuplex); + + if (EFI_ERROR(Status)) + goto EXIT; +#if REPORTLINK + if (NicDevice->LinkUp && NicDevice->Complete) { + Mode->MediaPresent =3D TRUE; + Status =3D Ax88179SetMedium (NicDevice); + } else { + Mode->MediaPresent =3D FALSE; + } +#else + if (NicDevice->LinkUp && NicDevice->Complete) { + Mode->MediaPresent =3D TRUE; + Mode->MediaPresentSupported =3D FALSE; + Status =3D Ax88179SetMedium (NicDevice); + + } + } +#endif + } else { + if (EfiSimpleNetworkStarted =3D=3D Mode->State) { + Status =3D EFI_DEVICE_ERROR; + } else { + Status =3D EFI_NOT_STARTED ; + } + } + } else { + Status =3D EFI_INVALID_PARAMETER; + } + if (InterruptStatus !=3D NULL) { + *InterruptStatus =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] SimpleNetwork Protocol instance pointer + @param [in] ReadWrite TRUE for read operations, FALSE for write = operations. + @param [in] Offset Byte offset in the NVRAM device at which 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] Buffer A pointer to the data buffer. + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did no= t 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 *SimpleNetwork, + IN BOOLEAN ReadWrite, + IN UINTN Offset, + IN UINTN BufferSize, + IN OUT VOID *Buffer + ) +{ + EFI_STATUS Status =3D EFI_INVALID_PARAMETER; + EFI_TPL TplPrevious; + EFI_SIMPLE_NETWORK_MODE *Mode; + NIC_DEVICE *NicDevice; + UINTN Index; + + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + if ((SimpleNetwork =3D=3D NULL) || (SimpleNetwork->Mode =3D=3D NULL)) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + + NicDevice =3D DEV_FROM_SIMPLE_NETWORK (SimpleNetwork); + Mode =3D SimpleNetwork->Mode; + + if (EfiSimpleNetworkInitialized !=3D Mode->State) { + Status =3D EFI_NOT_STARTED; + goto EXIT; + } + + if (Offset !=3D 0) { + if (((Offset % Mode->NvRamAccessSize) !=3D 0) || (Offset >=3D Mode->Nv= RamSize)) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + } + // + // Offset must be a multiple of NvRamAccessSize and less than NvRamSize. + // + if ((BufferSize % Mode->NvRamAccessSize) !=3D 0) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + + if (BufferSize + Offset > Mode->NvRamSize) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + + if (Buffer =3D=3D NULL) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + + // + // ReadWrite: TRUE FOR READ FALSE FOR WRITE + // + if (ReadWrite) { + for (Index =3D 0; Index < BufferSize / 2; Index++) { + Status =3D Ax88179SromRead (NicDevice, + (UINT32)(Offset/2 + Index), + (((UINT16*)Buffer) + Index)); + } + } else { + Status =3D Ax88179EnableSromWrite(NicDevice); + if (EFI_ERROR(Status)) + goto EXIT; + + for (Index =3D 0; Index < BufferSize / 2; Index++) { + Status =3D Ax88179SromWrite (NicDevice, + (UINT32)(Offset/2 + Index), + (((UINT16*)Buffer) + Index)); + } + + Status =3D Ax88179DisableSromWrite(NicDevice); + + if (BufferSize =3D=3D 272) + Status =3D Ax88179ReloadSrom(NicDevice); + } + + // + // Return the operation status + // +EXIT: + gBS->RestoreTPL (TplPrevious); + return Status; +} + +/** + Resets the network adapter and allocates the transmit and receive buffers + required by the network interface; optionally, also requests allocation = of + additional transmit and receive buffers. This routine must be called be= fore + any other routine in the Simple Network protocol is called. + + @param [in] SimpleNetwork Protocol instance pointer + @param [in] ExtraRxBufferSize Size in bytes to add to the receive buffer= allocation + @param [in] ExtraTxBufferSize Size in bytes to add to the transmit 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 SimpleNetwork parameter was NULL or did no= t 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 * SimpleNetwork, + IN UINTN ExtraRxBufferSize, + IN UINTN ExtraTxBufferSize + ) +{ + EFI_SIMPLE_NETWORK_MODE *Mode; + EFI_STATUS Status; + UINT32 TmpState; + EFI_TPL TplPrevious; + NIC_DEVICE *NicDevice; + + TplPrevious =3D gBS->RaiseTPL (TPL_CALLBACK); + + // + // Verify the parameters + // + if ((SimpleNetwork !=3D NULL) && (SimpleNetwork->Mode !=3D NULL)) { + // + // Determine if the interface is already started + // + Mode =3D SimpleNetwork->Mode; + if (EfiSimpleNetworkStarted =3D=3D Mode->State) { + if ((0 =3D=3D ExtraRxBufferSize) && (0 =3D=3D ExtraTxBufferSize)) { + // + // Start the adapter + // + TmpState =3D Mode->State; + Mode->State =3D EfiSimpleNetworkInitialized; + Status =3D SN_Reset (SimpleNetwork, FALSE); + if (EFI_ERROR (Status)) { + // + // Update the network state + // + Mode->State =3D TmpState; + } else { + Mode->MediaPresentSupported =3D TRUE; + NicDevice =3D DEV_FROM_SIMPLE_NETWORK (SimpleNetwork); + Mode->MediaPresent =3D Ax88179GetLinkStatus (NicDevice); + } + } 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] SimpleNetwork Protocol instance pointer + @param [in] IPv6 Set to TRUE if the multicast IP address is = IPv6 [RFC2460]. + Set to FALSE if the multicast IP address i= s IPv4 [RFC 791]. + @param [in] IP The multicast IP address that is to be conv= erted to a + multicast HW MAC address. + @param [in] MAC The multicast HW MAC address that is to be = generated from IP. + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did no= t 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 *SimpleNetwork, + IN BOOLEAN IPv6, + IN EFI_IP_ADDRESS *IP, + IN EFI_MAC_ADDRESS *MAC + ) +{ + EFI_STATUS Status; + EFI_TPL TplPrevious; + EFI_SIMPLE_NETWORK_MODE *Mode; + + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + if ((SimpleNetwork !=3D NULL) && (SimpleNetwork->Mode !=3D NULL)) { + // + // The interface must be running + // + Mode =3D SimpleNetwork->Mode; + if (EfiSimpleNetworkInitialized =3D=3D Mode->State) { + if (IP =3D=3D NULL || MAC =3D=3D NULL) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + if (IPv6) { + Status =3D EFI_UNSUPPORTED; + goto EXIT; + } else { + // + // check if the ip given is a mcast IP + // + if ((IP->v4.Addr[0] & 0xF0) !=3D 0xE0) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } else { + MAC->Addr[0] =3D 0x01; + MAC->Addr[1] =3D 0x00; + MAC->Addr[2] =3D 0x5e; + MAC->Addr[3] =3D (UINT8) (IP->v4.Addr[1] & 0x7f); + MAC->Addr[4] =3D (UINT8) IP->v4.Addr[2]; + MAC->Addr[5] =3D (UINT8) IP->v4.Addr[3]; + Status =3D EFI_SUCCESS; + } + } + } else { + if (EfiSimpleNetworkStarted =3D=3D Mode->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] SimpleNetwork Protocol instance pointer + @param [out] HeaderSize The size, in bytes, of the media header to = be filled in by + the Transmit() function. If HeaderSize is= non-zero, then + it must be equal to SimpleNetwork->Mode->M= ediaHeaderSize + and DestAddr and Protocol parameters must = not be NULL. + @param [out] BufferSize The size, in bytes, of the entire packet (m= edia header and + data) to be transmitted through the networ= k interface. + @param [out] Buffer A pointer to the packet (media header follo= wed 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] SrcAddr The source HW MAC address. If HeaderSize i= s zero, then + this parameter is ignored. If HeaderSize = is nonzero and + SrcAddr is NULL, then SimpleNetwork->Mode-= >CurrentAddress + is used for the source HW MAC address. + @param [out] DestAddr The destination HW MAC address. If HeaderS= ize is zero, then + this parameter is ignored. + @param [out] Protocol The type of header to build. If HeaderSize= is zero, then + this parameter is ignored. + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_NOT_READY No packets have been received on the netwo= rk interface. + @retval EFI_BUFFER_TOO_SMALL The packet is larger than BufferSize bytes. + @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did no= t 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 *SimpleNetwork, + OUT UINTN *HeaderSize, + OUT UINTN *BufferSize, + OUT VOID *Buffer, + OUT EFI_MAC_ADDRESS *SrcAddr, + OUT EFI_MAC_ADDRESS *DestAddr, + OUT UINT16 *Protocol + ) +{ + ETHERNET_HEADER *Header; + EFI_SIMPLE_NETWORK_MODE *Mode; + NIC_DEVICE *NicDevice; + EFI_STATUS Status; + UINT16 Type =3D 0; + UINT16 CurrentPktLen; + BOOLEAN Valid =3D TRUE; + EFI_TPL TplPrevious; + + TplPrevious =3D gBS->RaiseTPL (TPL_CALLBACK); + // + // Verify the parameters + // + if ((SimpleNetwork !=3D NULL) && (SimpleNetwork->Mode !=3D NULL)) { + // + // The interface must be running + // + Mode =3D SimpleNetwork->Mode; + if (EfiSimpleNetworkInitialized =3D=3D Mode->State) { + if ((BufferSize =3D=3D NULL) || (Buffer =3D=3D NULL)) { + Status =3D EFI_INVALID_PARAMETER; + gBS->RestoreTPL (TplPrevious); + return Status; + } + + // + // Update the link status + // + NicDevice =3D DEV_FROM_SIMPLE_NETWORK (SimpleNetwork); + + if (NicDevice->LinkUp && NicDevice->Complete) { + if ((HeaderSize !=3D NULL) && (*HeaderSize =3D=3D 7720)) { + NicDevice->Grub_f =3D TRUE; + } + + if ((NicDevice->Grub_f) && (*HeaderSize !=3D 7720)) { + gBS->RestoreTPL (TplPrevious); + return EFI_NOT_READY; + } + + // + // Attempt to do bulk in + // + if (NicDevice->PktCnt =3D=3D 0) { + Status =3D Ax88179BulkIn(NicDevice); + if (EFI_ERROR(Status)) + goto no_pkt; + } + CurrentPktLen =3D *((UINT16*) (NicDevice->CurPktHdrOff + 2)); + if (CurrentPktLen & (RXHDR_DROP | RXHDR_CRCERR)) + Valid =3D FALSE; + CurrentPktLen &=3D 0x1fff; + CurrentPktLen -=3D 2; /*EEEE*/ + + if (Valid && (60 <=3D CurrentPktLen) && + ((CurrentPktLen - 14) <=3D MAX_ETHERNET_PKT_SIZE) && + (*((UINT16*)NicDevice->CurPktOff)) =3D=3D 0xEEEE) { + if (*BufferSize < (UINTN)CurrentPktLen) { + gBS->RestoreTPL (TplPrevious); + return EFI_BUFFER_TOO_SMALL; + } + *BufferSize =3D CurrentPktLen; + CopyMem (Buffer, NicDevice->CurPktOff + 2, CurrentPktLen); + + Header =3D (ETHERNET_HEADER *) NicDevice->CurPktOff + 2; + + if ((HeaderSize !=3D NULL) && ((*HeaderSize !=3D 7720))) { + *HeaderSize =3D sizeof (*Header); + } + + if (DestAddr !=3D NULL) { + CopyMem (DestAddr, &Header->DestAddr, PXE_HWADDR_LEN_ETHER); + } + if (SrcAddr !=3D NULL) { + CopyMem (SrcAddr, &Header->SrcAddr, PXE_HWADDR_LEN_ETHER); + } + if (Protocol !=3D NULL) { + Type =3D Header->Type; + Type =3D (UINT16)((Type >> 8) | (Type << 8)); + *Protocol =3D Type; + } + NicDevice->PktCnt--; + NicDevice->CurPktHdrOff +=3D 4; + NicDevice->CurPktOff +=3D (CurrentPktLen + 2 + 7) & 0xfff8; + Status =3D EFI_SUCCESS; + } else { + NicDevice->PktCnt =3D 0; + Status =3D EFI_NOT_READY; + } + } else { + Status =3D EFI_NOT_READY; + } + } else { + if (EfiSimpleNetworkStarted =3D=3D Mode->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] SimpleNetwork Protocol instance pointer + @param [in] Enable A bit mask of receive filters to enable on= the network interface. + @param [in] Disable A bit mask of receive filters to disable 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] ResetMCastFilter Set to TRUE to reset the contents of the mu= lticast 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] MCastFilter A pointer to a list of new multicast receiv= e 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 SimpleNetwork parameter was NULL or did no= t 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 *SimpleNetwork, + IN UINT32 Enable, + IN UINT32 Disable, + IN BOOLEAN ResetMCastFilter, + IN UINTN MCastFilterCnt, + IN EFI_MAC_ADDRESS *MCastFilter + ) +{ + EFI_SIMPLE_NETWORK_MODE *Mode; + EFI_STATUS Status =3D EFI_SUCCESS; + EFI_TPL TplPrevious; + UINTN Index; + UINT8 Temp; + + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + Mode =3D SimpleNetwork->Mode; + + if (SimpleNetwork =3D=3D NULL) { + gBS->RestoreTPL(TplPrevious); + return EFI_INVALID_PARAMETER; + } + + switch (Mode->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 SNP + // does not even support! + // + if (((Enable &~Mode->ReceiveFilterMask) !=3D 0) || + ((Disable &~Mode->ReceiveFilterMask) !=3D 0)) { + Status =3D EFI_INVALID_PARAMETER; + gBS->RestoreTPL(TplPrevious); + return Status; + } + + if (ResetMCastFilter) { + Disable |=3D (EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST & Mode->ReceiveFilt= erMask); + MCastFilterCnt =3D 0; + Mode->MCastFilterCount =3D 0; + if ((0 =3D=3D (Mode->ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE= _MULTICAST)) && + Enable =3D=3D 0 && Disable =3D=3D 2) { + gBS->RestoreTPL(TplPrevious); + return EFI_SUCCESS; + } + } else { + if (MCastFilterCnt !=3D 0) { + EFI_MAC_ADDRESS * MulticastAddress; + MulticastAddress =3D MCastFilter; + + if ((MCastFilterCnt > Mode->MaxMCastFilterCount) || + (MCastFilter =3D=3D NULL)) { + Status =3D EFI_INVALID_PARAMETER; + gBS->RestoreTPL(TplPrevious); + return Status; + } + + for (Index =3D 0 ; Index < MCastFilterCnt ; Index++) { + Temp =3D MulticastAddress->Addr[0]; + if ((Temp & 0x01) !=3D 0x01) { + gBS->RestoreTPL(TplPrevious); + return EFI_INVALID_PARAMETER; + } + MulticastAddress++; + } + + Mode->MCastFilterCount =3D (UINT32)MCastFilterCnt; + CopyMem (&Mode->MCastFilter[0], + MCastFilter, + MCastFilterCnt * sizeof (EFI_MAC_ADDRESS/**MCastFilter*/)); + } + } + + if (Enable =3D=3D 0 && Disable =3D=3D 0 && !ResetMCastFilter && MCastFil= terCnt =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; + } + + Mode->ReceiveFilterSetting |=3D Enable; + Mode->ReceiveFilterSetting &=3D ~Disable; + + Status =3D ReceiveFilterUpdate (SimpleNetwork); + + gBS->RestoreTPL(TplPrevious); + + return Status; +} + +/** + Reset the network adapter. + + Resets a network adapter and reinitializes it with the parameters that + were provided in the previous call to Initialize (). The transmit and + receive queues are cleared. Receive filters, the station address, the + statistics, and the multicast-IP-to-HW MAC addresses are not reset by + this call. + + This routine calls ::Ax88179Reset to perform the adapter specific + reset operation. This routine also starts the link negotiation + by calling ::Ax88179NegotiateLinkStart. + + @param [in] SimpleNetwork Protocol instance pointer + @param [in] ExtendedVerification Indicates that the driver may perform = a more + exhaustive verification operation of the 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 SimpleNetwork parameter was NULL or did no= t 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 *SimpleNetwork, + IN BOOLEAN ExtendedVerification + ) +{ + EFI_SIMPLE_NETWORK_MODE *Mode; + NIC_DEVICE *NicDevice; + EFI_STATUS Status; + EFI_TPL TplPrevious; + + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + // + // Verify the parameters + // + if ((SimpleNetwork !=3D NULL) && (SimpleNetwork->Mode !=3D NULL)) { + Mode =3D SimpleNetwork->Mode; + if (EfiSimpleNetworkInitialized =3D=3D Mode->State) { + // + // Update the device state + // + NicDevice =3D DEV_FROM_SIMPLE_NETWORK (SimpleNetwork); + + // + // Reset the device + // + if (!NicDevice->FirstRst) { + Status =3D EFI_SUCCESS; + } else { + Status =3D Ax88179Reset (NicDevice); + if (!EFI_ERROR (Status)) { + Status =3D ReceiveFilterUpdate (SimpleNetwork); + if (!EFI_ERROR (Status) && !NicDevice->LinkUp && NicDevice->Firs= tRst) { + Status =3D Ax88179NegotiateLinkStart (NicDevice); + NicDevice->FirstRst =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] NicDevice NIC_DEVICE_INSTANCE pointer + + @retval EFI_SUCCESS Setup was successful + +**/ +EFI_STATUS +SN_Setup ( + IN NIC_DEVICE *NicDevice + ) +{ + EFI_SIMPLE_NETWORK_MODE *Mode; + EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork; + EFI_STATUS Status; + + // + // Initialize the simple network protocol + // + SimpleNetwork =3D &NicDevice->SimpleNetwork; + SimpleNetwork->Revision =3D EFI_SIMPLE_NETWORK_PROTOCOL_REVISION; + SimpleNetwork->Start =3D SN_Start; + SimpleNetwork->Stop =3D SN_Stop; + SimpleNetwork->Initialize =3D SN_Initialize; + SimpleNetwork->Reset =3D SN_Reset; + SimpleNetwork->Shutdown =3D SN_Shutdown; + SimpleNetwork->ReceiveFilters =3D SN_ReceiveFilters; + SimpleNetwork->StationAddress =3D SN_StationAddress; + SimpleNetwork->Statistics =3D SN_Statistics; + SimpleNetwork->MCastIpToMac =3D SN_MCastIPtoMAC; + SimpleNetwork->NvData =3D SN_NvData; + SimpleNetwork->GetStatus =3D SN_GetStatus; + SimpleNetwork->Transmit =3D SN_Transmit; + SimpleNetwork->Receive =3D SN_Receive; + SimpleNetwork->WaitForPacket =3D NULL; + Mode =3D &NicDevice->SimpleNetworkData; + SimpleNetwork->Mode =3D Mode; + Mode->State =3D EfiSimpleNetworkStopped; + Mode->HwAddressSize =3D PXE_HWADDR_LEN_ETHER; + Mode->MediaHeaderSize =3D sizeof (ETHERNET_HEADER); + Mode->MaxPacketSize =3D MAX_ETHERNET_PKT_SIZE; + Mode->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; + Mode->ReceiveFilterSetting =3D EFI_SIMPLE_NETWORK_RECEIVE_UNICAST + | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST; + Mode->MaxMCastFilterCount =3D MAX_MCAST_FILTER_CNT; + Mode->MCastFilterCount =3D 0; + Mode->NvRamSize =3D 512; + Mode->NvRamAccessSize =3D 2; + SetMem (&Mode->BroadcastAddress, + PXE_HWADDR_LEN_ETHER, + 0xff); + Mode->IfType =3D NET_IFTYPE_ETHERNET; + Mode->MacAddressChangeable =3D TRUE; + Mode->MultipleTxSupported =3D FALSE; + Mode->MediaPresentSupported =3D TRUE; + Mode->MediaPresent =3D FALSE; + // + // Read the MAC address + // + NicDevice->PhyId =3D PHY_ID_INTERNAL; + NicDevice->LinkSpeed100Mbps =3D FALSE; + NicDevice->LinkSpeed1000Mbps =3D TRUE; + NicDevice->FullDuplex =3D TRUE; + NicDevice->Complete =3D FALSE; + NicDevice->LinkUp =3D FALSE; + NicDevice->Grub_f =3D FALSE; + NicDevice->FirstRst =3D TRUE; + NicDevice->PktCnt =3D 0; + NicDevice->SkipRXCnt =3D 0; + NicDevice->UsbMaxPktSize =3D 512; + NicDevice->SetZeroLen =3D TRUE; + + Status =3D Ax88179MacAddressGet (NicDevice, + &Mode->PermanentAddress.Addr[0]); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Use the hardware address as the current address + // + CopyMem (&Mode->CurrentAddress, + &Mode->PermanentAddress, + PXE_HWADDR_LEN_ETHER); + + CopyMem (&NicDevice->MAC, + &Mode->PermanentAddress, + PXE_HWADDR_LEN_ETHER); + + Status =3D gBS->AllocatePool (EfiBootServicesData, + AX88179_MAX_BULKIN_SIZE, + (VOID **) &NicDevice->BulkInbuf); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D gBS->AllocatePool (EfiBootServicesData, + sizeof (TX_PACKET), + (VOID **) &NicDevice->TxTest); + if (EFI_ERROR (Status)) { + gBS->FreePool (NicDevice->BulkInbuf); + } + + // + // Return the setup status + // + return Status; +} + + +/** + This routine starts the network interface. + + @param [in] SimpleNetwork Protocol instance pointer + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_ALREADY_STARTED The network interface was already started. + @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did no= t 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 *SimpleNetwork + ) +{ + NIC_DEVICE *NicDevice; + EFI_SIMPLE_NETWORK_MODE *Mode; + EFI_STATUS Status; + EFI_TPL TplPrevious; + + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + // + // Verify the parameters + // + Status =3D EFI_INVALID_PARAMETER; + if ((SimpleNetwork !=3D NULL) && (SimpleNetwork->Mode !=3D NULL)) { + Mode =3D SimpleNetwork->Mode; + if (EfiSimpleNetworkStopped =3D=3D Mode->State) { + // + // Initialize the mode structure + // NVRAM access is not supported + // + ZeroMem (Mode, sizeof (*Mode)); + + Mode->State =3D EfiSimpleNetworkStarted; + Mode->HwAddressSize =3D PXE_HWADDR_LEN_ETHER; + Mode->MediaHeaderSize =3D sizeof (ETHERNET_HEADER); + Mode->MaxPacketSize =3D MAX_ETHERNET_PKT_SIZE; + Mode->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; + Mode->ReceiveFilterSetting =3D EFI_SIMPLE_NETWORK_RECEIVE_UNICAST; + Mode->MaxMCastFilterCount =3D MAX_MCAST_FILTER_CNT; + Mode->MCastFilterCount =3D 0; + Mode->NvRamSize =3D 512; + Mode->NvRamAccessSize =3D 2; + NicDevice =3D DEV_FROM_SIMPLE_NETWORK (SimpleNetwork); + Status =3D Ax88179MacAddressGet (NicDevice, &Mode->PermanentAddress.= Addr[0]); + CopyMem (&Mode->CurrentAddress, + &Mode->PermanentAddress, + sizeof (Mode->CurrentAddress)); + SetMem(&Mode->BroadcastAddress, PXE_HWADDR_LEN_ETHER, 0xff); + Mode->IfType =3D NET_IFTYPE_ETHERNET; + Mode->MacAddressChangeable =3D TRUE; + Mode->MultipleTxSupported =3D FALSE; + Mode->MediaPresentSupported =3D TRUE; + Mode->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 + New. + + This routine calls ::Ax88179MacAddressSet to update the MAC address + in the network adapter. + + @param [in] SimpleNetwork Protocol instance pointer + @param [in] Reset Flag used to reset the station address to t= he + network interface's permanent address. + @param [in] New New station address to be used for the netw= ork + interface. + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did no= t 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 *SimpleNetwork, + IN BOOLEAN Reset, + IN EFI_MAC_ADDRESS *New + ) +{ + NIC_DEVICE *NicDevice; + EFI_SIMPLE_NETWORK_MODE *Mode; + EFI_STATUS Status; + + EFI_TPL TplPrevious; + + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + // + // Verify the parameters + // + if ((SimpleNetwork !=3D NULL) && + (SimpleNetwork->Mode !=3D NULL) && + ((!Reset) || (Reset && (New !=3D NULL)))) { + // + // Verify that the adapter is already started + // + NicDevice =3D DEV_FROM_SIMPLE_NETWORK (SimpleNetwork); + Mode =3D SimpleNetwork->Mode; + if (EfiSimpleNetworkInitialized =3D=3D Mode->State) { + // + // Determine the adapter MAC address + // + if (Reset) { + // + // Use the permanent address + // + CopyMem (&Mode->CurrentAddress, + &Mode->PermanentAddress, + sizeof (Mode->CurrentAddress)); + } else { + // + // Use the specified address + // + CopyMem (&Mode->CurrentAddress, + New, + sizeof (Mode->CurrentAddress)); + } + + // + // Update the address on the adapter + // + Status =3D Ax88179MacAddressSet (NicDevice, &Mode->CurrentAddress.Ad= dr[0]); + } else { + if (EfiSimpleNetworkStarted =3D=3D Mode->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] SimpleNetwork Protocol instance pointer + @param [in] Reset Set to TRUE to reset the statistics for the= network interface. + @param [in, out] StatisticsSize On input the size, in bytes, of Statist= icsTable. On output + the size, in bytes, of the resulting table= of statistics. + @param [out] StatisticsTable A pointer to the EFI_NETWORK_STATISTICS str= ucture that + conains the statistics. + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_BUFFER_TOO_SMALL The StatisticsTable is NULL or the buffer = is too small. + @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did no= t 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 *SimpleNetwork, + IN BOOLEAN Reset, + IN OUT UINTN *StatisticsSize, + OUT EFI_NETWORK_STATISTICS *StatisticsTable + ) +{ + EFI_STATUS Status; + EFI_TPL TplPrevious; + EFI_SIMPLE_NETWORK_MODE *Mode; + + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + Mode =3D SimpleNetwork->Mode; + + if (EfiSimpleNetworkInitialized =3D=3D Mode->State) { + if ((StatisticsSize !=3D NULL) && (*StatisticsSize =3D=3D 0)) { + Status =3D EFI_BUFFER_TOO_SMALL; + goto EXIT; + } + + if(Reset) { + Status =3D EFI_SUCCESS; + } else { + Status =3D EFI_SUCCESS; + } + } else { + if (EfiSimpleNetworkStarted =3D=3D Mode->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] SimpleNetwork Protocol instance pointer + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did no= t 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 *SimpleNetwork + ) +{ + EFI_SIMPLE_NETWORK_MODE *Mode; + EFI_STATUS Status; + EFI_TPL TplPrevious; + + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + // + // Verify the parameters + // + if ((SimpleNetwork !=3D NULL) && (SimpleNetwork->Mode !=3D NULL)) { + // + // Determine if the interface is started + // + Mode =3D SimpleNetwork->Mode; + + if (EfiSimpleNetworkStarted =3D=3D Mode->State) { + Mode->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. + Ending transmits and receives are lost, and interrupts are cleared and d= isabled. + After this call, only Initialize() and Stop() calls may be used. + + @param [in] SimpleNetwork Protocol instance pointer + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did no= t 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 *SimpleNetwork + ) +{ + EFI_SIMPLE_NETWORK_MODE *Mode; + EFI_STATUS Status; + NIC_DEVICE *NicDevice; + EFI_TPL TplPrevious; + + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + // + // Verify the parameters + // + if ((SimpleNetwork !=3D NULL) && (SimpleNetwork->Mode !=3D NULL)) { + // + // Determine if the interface is already started + // + Mode =3D SimpleNetwork->Mode; + if (EfiSimpleNetworkInitialized =3D=3D Mode->State) { + // + // Stop the adapter + // + NicDevice =3D DEV_FROM_SIMPLE_NETWORK (SimpleNetwork); + + Status =3D Ax88179MacAddressGet (NicDevice, &Mode->PermanentAddress.= Addr[0]); + if (!EFI_ERROR (Status)) { + // + // Update the network state + // + Mode->State =3D EfiSimpleNetworkStarted; + } else if (EFI_DEVICE_ERROR =3D=3D Status) { + Mode->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] SimpleNetwork Protocol instance pointer + @param [in] HeaderSize The size, in bytes, of the media header to= be filled in by + the Transmit() function. If HeaderSize is= non-zero, then + it must be equal to SimpleNetwork->Mode->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] Buffer A pointer to the packet (media header follo= wed 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] SrcAddr The source HW MAC address. If HeaderSize i= s zero, then + this parameter is ignored. If HeaderSize = is nonzero and + SrcAddr is NULL, then SimpleNetwork->Mode-= >CurrentAddress + is used for the source HW MAC address. + @param [in] DestAddr The destination HW MAC address. If HeaderS= ize is zero, then + this parameter is ignored. + @param [in] Protocol The type of header to build. If HeaderSize= is zero, then + this parameter is ignored. + + @retval EFI_SUCCESS This operation was successful. + @retval EFI_NOT_STARTED The network interface was not started. + @retval EFI_NOT_READY The network interface is too busy to accep= t this transmit request. + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. + @retval EFI_INVALID_PARAMETER SimpleNetwork parameter was NULL or did no= t 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 *SimpleNetwork, + IN UINTN HeaderSize, + IN UINTN BufferSize, + IN VOID *Buffer, + IN EFI_MAC_ADDRESS *SrcAddr, + IN EFI_MAC_ADDRESS *DestAddr, + IN UINT16 *Protocol + ) +{ + ETHERNET_HEADER *Header; + EFI_SIMPLE_NETWORK_MODE *Mode; + NIC_DEVICE *NicDevice; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_STATUS Status; + UINTN TransferLength; + UINT32 TransferStatus; + UINT16 Type =3D 0; + EFI_TPL TplPrevious; + + TplPrevious =3D gBS->RaiseTPL(TPL_CALLBACK); + // + // Verify the parameters + // + if ((SimpleNetwork !=3D NULL) && (SimpleNetwork->Mode !=3D NULL)) { + // + // The interface must be running + // + Mode =3D SimpleNetwork->Mode; + if (EfiSimpleNetworkInitialized =3D=3D Mode->State) { + // + // Update the link status + // + NicDevice =3D DEV_FROM_SIMPLE_NETWORK (SimpleNetwork); + + if (NicDevice->LinkUp && NicDevice->Complete) { + if ((HeaderSize !=3D 0) && (Mode->MediaHeaderSize !=3D HeaderSize)= ) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + if (BufferSize < Mode->MediaHeaderSize) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + if (Buffer =3D=3D NULL) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + if ((HeaderSize !=3D 0) && (DestAddr =3D=3D NULL)) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + if ((HeaderSize !=3D 0) && (Protocol =3D=3D NULL)) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + // + // Copy the packet into the USB buffer + // + // Buffer starting with 14 bytes 0 + CopyMem (&NicDevice->TxTest->Data[0], Buffer, BufferSize); + NicDevice->TxTest->TxHdr1 =3D (UINT32) BufferSize; + NicDevice->TxTest->TxHdr2 =3D 0; + // + // Transmit the packet + // + Header =3D (ETHERNET_HEADER *) &NicDevice->TxTest->Data[0]; + if (HeaderSize !=3D 0) { + if (DestAddr !=3D NULL) { + CopyMem (&Header->DestAddr, DestAddr, PXE_HWADDR_LEN_ETHER); + } + if (SrcAddr !=3D NULL) { + CopyMem (&Header->SrcAddr, SrcAddr, PXE_HWADDR_LEN_ETHER); + } else { + CopyMem (&Header->SrcAddr, &Mode->CurrentAddress.Addr[0], PXE_= HWADDR_LEN_ETHER); + } + if (Protocol !=3D NULL) { + Type =3D *Protocol; + } else { + Type =3D (UINT16) BufferSize; + } + Type =3D (UINT16)((Type >> 8) | (Type << 8)); + Header->Type =3D Type; + } + + if (NicDevice->TxTest->TxHdr1 < MIN_ETHERNET_PKT_SIZE) { + NicDevice->TxTest->TxHdr1 =3D MIN_ETHERNET_PKT_SIZE; + ZeroMem (&NicDevice->TxTest->Data[BufferSize], + MIN_ETHERNET_PKT_SIZE - BufferSize); + } + + TransferLength =3D sizeof (NicDevice->TxTest->TxHdr1) + + sizeof (NicDevice->TxTest->TxHdr2) + + NicDevice->TxTest->TxHdr1; + // + // Work around USB bus driver bug where a timeout set by receive + // succeeds but the timeout expires immediately after, causing the + // transmit operation to timeout. + // + UsbIo =3D NicDevice->UsbIo; + Status =3D UsbIo->UsbBulkTransfer (UsbIo, + BULK_OUT_ENDPOINT, + &NicDevice->TxTest->TxHdr1, + &TransferLength, + 0xfffffffe, + &TransferStatus); + + if (!EFI_ERROR(Status) && !EFI_ERROR(Status)) { + NicDevice->TxBuffer =3D Buffer; + 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 Mode->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 (#60864): https://edk2.groups.io/g/devel/message/60864 Mute This Topic: https://groups.io/mt/74751638/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-