diff options
Diffstat (limited to 'embeddedsw/ThirdParty/sw_services/lwip211/src/contrib/ports/xilinx/netif/xadapter.c')
-rw-r--r-- | embeddedsw/ThirdParty/sw_services/lwip211/src/contrib/ports/xilinx/netif/xadapter.c | 425 |
1 files changed, 425 insertions, 0 deletions
diff --git a/embeddedsw/ThirdParty/sw_services/lwip211/src/contrib/ports/xilinx/netif/xadapter.c b/embeddedsw/ThirdParty/sw_services/lwip211/src/contrib/ports/xilinx/netif/xadapter.c new file mode 100644 index 0000000..9594ff5 --- /dev/null +++ b/embeddedsw/ThirdParty/sw_services/lwip211/src/contrib/ports/xilinx/netif/xadapter.c @@ -0,0 +1,425 @@ +/* + * Copyright (C) 2007 - 2021 Xilinx, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include "lwipopts.h" +#include "xlwipconfig.h" +#include "xemac_ieee_reg.h" + +#if !NO_SYS +#endif + +#include "lwip/mem.h" +#include "lwip/stats.h" +#include "lwip/sys.h" +#include "lwip/ip.h" +#include "lwip/tcp.h" +#include "lwip/udp.h" +#include "lwip/priv/tcp_priv.h" + +#include "netif/etharp.h" +#include "netif/xadapter.h" + +#ifdef XLWIP_CONFIG_INCLUDE_EMACLITE +#include "netif/xemacliteif.h" +#endif + +#ifdef XLWIP_CONFIG_INCLUDE_AXI_ETHERNET +#include "netif/xaxiemacif.h" +#endif + +#ifdef XLWIP_CONFIG_INCLUDE_GEM +#include "netif/xemacpsif.h" +#endif + +#if !NO_SYS +#include "lwip/tcpip.h" + +#define THREAD_STACKSIZE 256 +#define LINK_DETECT_THREAD_INTERVAL 1000 /* one second */ + +void link_detect_thread(void *p); +#endif + +/* global lwip debug variable used for debugging */ +int lwip_runtime_debug = 0; + +enum ethernet_link_status eth_link_status = ETH_LINK_UNDEFINED; +u32_t phyaddrforemac; + +void +lwip_raw_init() +{ + ip_init(); /* Doesn't do much, it should be called to handle future changes. */ +#if LWIP_UDP + udp_init(); /* Clears the UDP PCB list. */ +#endif +#if LWIP_TCP + tcp_init(); /* Clears the TCP PCB list and clears some internal TCP timers. */ + /* Note: you must call tcp_fasttmr() and tcp_slowtmr() at the */ + /* predefined regular intervals after this initialization. */ +#endif +} + +static enum xemac_types +find_mac_type(unsigned base) +{ + int i; + + for (i = 0; i < xtopology_n_emacs; i++) { + if (xtopology[i].emac_baseaddr == base) + return xtopology[i].emac_type; + } + + return xemac_type_unknown; +} + +int +xtopology_find_index(unsigned base) +{ + int i; + + for (i = 0; i < xtopology_n_emacs; i++) { + if (xtopology[i].emac_baseaddr == base) + return i; + } + + return -1; +} + +/* + * xemac_add: this is a wrapper around lwIP's netif_add function. + * The objective is to provide portability between the different Xilinx MAC's + * This function can be used to add both xps_ethernetlite and xps_ll_temac + * based interfaces + */ +struct netif * +xemac_add(struct netif *netif, + ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw, + unsigned char *mac_ethernet_address, + UINTPTR mac_baseaddr) +{ + int i; + +#if !NO_SYS + /* Start thread to detect link periodically for Hot Plug autodetect */ + sys_thread_new("link_detect_thread", link_detect_thread, netif, + THREAD_STACKSIZE, tskIDLE_PRIORITY); +#endif + + /* set mac address */ + netif->hwaddr_len = 6; + for (i = 0; i < 6; i++) + netif->hwaddr[i] = mac_ethernet_address[i]; + + /* initialize based on MAC type */ + switch (find_mac_type(mac_baseaddr)) { + case xemac_type_xps_emaclite: +#ifdef XLWIP_CONFIG_INCLUDE_EMACLITE + return netif_add(netif, ipaddr, netmask, gw, + (void*)mac_baseaddr, + xemacliteif_init, +#if NO_SYS + ethernet_input +#else + tcpip_input +#endif + ); +#else + return NULL; +#endif + case xemac_type_axi_ethernet: +#ifdef XLWIP_CONFIG_INCLUDE_AXI_ETHERNET + return netif_add(netif, ipaddr, netmask, gw, + (void*)mac_baseaddr, + xaxiemacif_init, +#if NO_SYS + ethernet_input +#else + tcpip_input +#endif + ); +#else + return NULL; +#endif +#if defined (__arm__) || defined (__aarch64__) + case xemac_type_emacps: +#ifdef XLWIP_CONFIG_INCLUDE_GEM + return netif_add(netif, ipaddr, netmask, gw, + (void*)mac_baseaddr, + xemacpsif_init, +#if NO_SYS + ethernet_input +#else + tcpip_input +#endif + + ); +#endif +#endif + default: + xil_printf("unable to determine type of EMAC with baseaddress 0x%08x\r\n", + mac_baseaddr); + return NULL; + } +} + +#if !NO_SYS +/* + * The input thread calls lwIP to process any received packets. + * This thread waits until a packet is received (sem_rx_data_available), + * and then calls xemacif_input which processes 1 packet at a time. + */ +void +xemacif_input_thread(struct netif *netif) +{ + struct xemac_s *emac = (struct xemac_s *)netif->state; + while (1) { + /* sleep until there are packets to process + * This semaphore is set by the packet receive interrupt + * routine. + */ + sys_sem_wait(&emac->sem_rx_data_available); + + /* move all received packets to lwIP */ + xemacif_input(netif); + } +} +#endif + +int +xemacif_input(struct netif *netif) +{ + struct xemac_s *emac = (struct xemac_s *)netif->state; + + int n_packets = 0; + + switch (emac->type) { + case xemac_type_xps_emaclite: +#ifdef XLWIP_CONFIG_INCLUDE_EMACLITE + n_packets = xemacliteif_input(netif); + break; +#else + print("incorrect configuration: xps_ethernetlite drivers not present?"); + while(1); + return 0; +#endif + case xemac_type_axi_ethernet: +#ifdef XLWIP_CONFIG_INCLUDE_AXI_ETHERNET + n_packets = xaxiemacif_input(netif); + break; +#else + print("incorrect configuration: axi_ethernet drivers not present?"); + while(1); + return 0; +#endif +#if defined (__arm__) || defined (__aarch64__) + case xemac_type_emacps: +#ifdef XLWIP_CONFIG_INCLUDE_GEM + n_packets = xemacpsif_input(netif); + break; +#else + xil_printf("incorrect configuration: ps7_ethernet drivers not present?\r\n"); + while(1); + return 0; +#endif +#endif + default: + print("incorrect configuration: unknown temac type"); + while(1); + return 0; + } + + return n_packets; +} + +#if defined(XLWIP_CONFIG_INCLUDE_GEM) +static u32_t phy_link_detect(XEmacPs *xemacp, u32_t phy_addr) +{ + u16_t status; + + /* Read Phy Status register twice to get the confirmation of the current + * link status. + */ + XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + + if (status & IEEE_STAT_LINK_STATUS) + return 1; + return 0; +} +#elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET) +static u32_t phy_link_detect(XAxiEthernet *xemacp, u32_t phy_addr) +{ + u16_t status; + + /* Read Phy Status register twice to get the confirmation of the current + * link status. + */ + XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + + if (status & IEEE_STAT_LINK_STATUS) + return 1; + return 0; +} +#elif defined(XLWIP_CONFIG_INCLUDE_EMACLITE) +static u32_t phy_link_detect(XEmacLite *xemacp, u32_t phy_addr) +{ + u16_t status; + + /* Read Phy Status register twice to get the confirmation of the current + * link status. + */ + XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + + if (status & IEEE_STAT_LINK_STATUS) + return 1; + return 0; +} +#endif + +#if defined(XLWIP_CONFIG_INCLUDE_GEM) +static u32_t phy_autoneg_status(XEmacPs *xemacp, u32_t phy_addr) +{ + u16_t status; + + /* Read Phy Status register twice to get the confirmation of the current + * link status. + */ + XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + + if (status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) + return 1; + return 0; +} +#elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET) +static u32_t phy_autoneg_status(XAxiEthernet *xemacp, u32_t phy_addr) +{ + u16_t status; + + /* Read Phy Status register twice to get the confirmation of the current + * link status. + */ + XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + + if (status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) + return 1; + return 0; +} +#elif defined(XLWIP_CONFIG_INCLUDE_EMACLITE) +static u32_t phy_autoneg_status(XEmacLite *xemacp, u32_t phy_addr) +{ + u16_t status; + + /* Read Phy Status register twice to get the confirmation of the current + * link status. + */ + XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status); + + if (status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) + return 1; + return 0; +} +#endif + +void eth_link_detect(struct netif *netif) +{ + u32_t link_speed, phy_link_status; + struct xemac_s *xemac = (struct xemac_s *)(netif->state); + +#if defined(XLWIP_CONFIG_INCLUDE_GEM) + xemacpsif_s *xemacs = (xemacpsif_s *)(xemac->state); + XEmacPs *xemacp = &xemacs->emacps; +#elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET) + xaxiemacif_s *xemacs = (xaxiemacif_s *)(xemac->state); + XAxiEthernet *xemacp = &xemacs->axi_ethernet; +#elif defined(XLWIP_CONFIG_INCLUDE_EMACLITE) + xemacliteif_s *xemacs = (xemacliteif_s *)(xemac->state); + XEmacLite *xemacp = xemacs->instance; +#endif + + if ((xemacp->IsReady != (u32)XIL_COMPONENT_IS_READY) || + (eth_link_status == ETH_LINK_UNDEFINED)) + return; + + phy_link_status = phy_link_detect(xemacp, phyaddrforemac); + + if ((eth_link_status == ETH_LINK_UP) && (!phy_link_status)) + eth_link_status = ETH_LINK_DOWN; + + switch (eth_link_status) { + case ETH_LINK_UNDEFINED: + case ETH_LINK_UP: + return; + case ETH_LINK_DOWN: + netif_set_link_down(netif); + eth_link_status = ETH_LINK_NEGOTIATING; + xil_printf("Ethernet Link down\r\n"); + break; + case ETH_LINK_NEGOTIATING: + if (phy_link_status && + phy_autoneg_status(xemacp, phyaddrforemac)) { + + /* Initiate Phy setup to get link speed */ +#if defined(XLWIP_CONFIG_INCLUDE_GEM) + link_speed = phy_setup_emacps(xemacp, + phyaddrforemac); + XEmacPs_SetOperatingSpeed(xemacp, link_speed); +#elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET) + link_speed = phy_setup_axiemac(xemacp); + XAxiEthernet_SetOperatingSpeed(xemacp, + link_speed); +#endif + netif_set_link_up(netif); + eth_link_status = ETH_LINK_UP; + xil_printf("Ethernet Link up\r\n"); + } + break; + } +} + +#if !NO_SYS +void link_detect_thread(void *p) +{ + struct netif *netif = (struct netif *) p; + + while (1) { + /* Call eth_link_detect() every second to detect Ethernet link + * change. + */ + eth_link_detect(netif); + vTaskDelay(LINK_DETECT_THREAD_INTERVAL / portTICK_RATE_MS); + } +} +#endif |