# Copyright (c) 2021 Xilinx, Inc.  All rights reserved.
# SPDX-License-Identifier: MIT
cmake_minimum_required(VERSION 3.3)

set(lwip_api_mode RAW_API CACHE STRING "Mode of operation for lwIP (RAW API/Sockets API)")
set_property(CACHE lwip_api_mode PROPERTY STRINGS RAW_API SOCKET_API)
option(lwip_no_sys_no_timers "Drops support for sys_timeout when NO_SYS==1" ON)
set(lwip_socket_mode_thread_prio 2 CACHE STRING "Priority of threads in socket mode")
option(lwip_tcp_keepalive "Enable keepalive processing with default interval" OFF)

set(lwip_temac_n_tx_descriptors 64 CACHE STRING "Number of TX Buffer Descriptors to be used in SDMA mode")
set(lwip_temac_n_rx_descriptors 64 CACHE STRING "Number of RX Buffer Descriptors to be used in SDMA mode")
set(lwip_temac_n_tx_coalesce 1 CACHE STRING "Setting for TX Interrupt coalescing.")
set(lwip_temac_n_rx_coalesce 1 CACHE STRING "Setting for RX Interrupt coalescing.")
option(lwip_temac_tcp_rx_checksum_offload "Offload TCP Receive checksum calculation (hardware support required)" OFF)
option(lwip_temac_tcp_tx_checksum_offload "Offload TCP Transmit checksum calculation (hardware support required)" OFF)
option(lwip_temac_tcp_ip_rx_checksum_offload "Offload TCP and IP Receive checksum calculation (hardware support required)" OFF)
option(lwip_temac_tcp_ip_tx_checksum_offload "Offload TCP and IP Transmit checksum calculation (hardware support required)" OFF)
set(lwip_temac_phy_link_speed CONFIG_LINKSPEED_AUTODETECT CACHE STRING "link speed as negotiated by the PHY")
set_property(CACHE lwip_temac_phy_link_speed PROPERTY STRINGS CONFIG_LINKSPEED10 CONFIG_LINKSPEED100 CONFIG_LINKSPEED1000 CONFIG_LINKSPEED_AUTODETECT)
option(lwip_temac_use_jumbo_frames "use jumbo frames" OFF)
set(lwip_temac_emac_number 0 CACHE STRING "Zynq Ethernet Interface number")

set(lwip_mem_size 131072 CACHE STRING "Size of the heap memory (bytes).")
set(lwip_memp_n_pbuf 16 CACHE STRING "Number of memp struct pbufs. Set this high if application sends lot of data out of ROM")
set(lwip_memp_n_udp_pcb 4 CACHE STRING "Number of active UDP PCBs. One per active UDP connection")
set(lwip_memp_n_tcp_pcb 32 CACHE STRING "Number of active TCP PCBs. One per active TCP connection")
set(lwip_memp_n_tcp_pcb_listen 8 CACHE STRING "Number of listening TCP connections")
set(lwip_memp_n_tcp_seg 256 CACHE STRING "Number of simultaneously queued TCP segments")
set(lwip_memp_n_sys_timeout 8 CACHE STRING "Number of simultaneously active timeouts")
set(lwip_memp_num_netbuf 8 CACHE STRING "Number of struct netbufs (socket mode only)")
set(lwip_memp_num_netconn 16 CACHE STRING "Number of struct netconns (socket mode only)")
set(lwip_memp_num_api_msg 16 CACHE STRING "Number of api msg structures (socket mode only)")
set(lwip_memp_num_tcpip_msg 64 CACHE STRING "Number of tcpip msg structures (socket mode only)")

set(lwip_pbuf_pool_size 256 CACHE STRING "Number of buffers in pbuf pool.")
set(lwip_pbuf_pool_bufsize 1700 CACHE STRING "Size of each pbuf in pbuf pool.")
set(lwip_pbuf_link_hlen 16 CACHE STRING "Number of bytes that should be allocated for a link level header.")

option(lwip_mbox_lwip_tcpip_core_locking_input "TCPIP input core locking" OFF)
set(lwip_mbox_tcpip_mbox_size 200 CACHE STRING "Size of TCPIP mbox queue.")
set(lwip_mbox_default_tcp_recvmbox_size 200 CACHE STRING "Size of TCP receive mbox queue.")
set(lwip_mbox_default_udp_recvmbox_size 100 CACHE STRING "Size of UDP receive mbox queue.")

set(lwip_arp_table_size 10 CACHE STRING "Number of active hardware address IP address pairs cached.")
set(lwip_arp_queueing 1 CACHE STRING "If enabled outgoing packets are queued during hardware address resolution.")
set_property(CACHE lwip_arp_queueing PROPERTY STRINGS 0x0 1)

set(lwip_ip_forward 0x0 CACHE STRING "Enable forwarding IP packets across network interfaces.")
set_property(CACHE lwip_ip_forward PROPERTY STRINGS 0x0 1)
set(lwip_ip_options 0x0 CACHE STRING "1 = IP options are allowed (but not parsed). 0 = packets with IP options are dropped")
set_property(CACHE lwip_ip_options PROPERTY STRINGS 0x0 1)
set(lwip_ip_reassembly 1 CACHE STRING "Reassemble incoming fragmented IP packets")
set_property(CACHE lwip_ip_reassembly PROPERTY STRINGS 0x0 1)
set(lwip_ip_frag 1 CACHE STRING "Fragment outgoing IP packets if their size exceeds MTU")
set_property(CACHE lwip_ip_frag PROPERTY STRINGS 0x0 1)
set(lwip_ip_reass_max_pbufs 128 CACHE STRING "Reassembly PBUF Queue Length")
set(lwip_ip_frag_max_mtu 1500 CACHE STRING "Assumed max MTU on any interface for IP frag buffer")
set(lwip_ip_default_ttl 255 CACHE STRING "Global default TTL used by transport layers")

option(lwip_icmp_options "ICMP Options" ON)
set(lwip_icmp_ttl 255 CACHE STRING "ICMP TTL value")

option(lwip_ipv6_options "IPv6 Options" ON)
option(lwip_ipv6_enable "IPv6 enable value" OFF)

option(lwip_igmp_options "IGMP Options" OFF)

option(lwip_udp_options "UDP Options" ON)
option(lwip_udp "Is UDP required" ON)
set(lwip_udp_ttl 255 CACHE STRING "UDP TTL value")

option(lwip_tcp_options "Is TCP required ?" ON)
option(lwip_tcp "Is TCP required ?" ON)
set(lwip_tcp_wnd 2048 CACHE STRING "TCP Window (bytes)")
set(lwip_tcp_snd_buf 8192 CACHE STRING "TCP sender buffer space (bytes)")
set(lwip_tcp_mss 1460 CACHE STRING "TCP Maximum segment size (bytes)")
set(lwip_tcp_ttl 255 CACHE STRING "TCP TTL value")
set(lwip_tcp_maxrtx 12 CACHE STRING "TCP Maximum retransmission value")
set(lwip_tcp_synmaxrtx 4 CACHE STRING "TCP Maximum SYN retransmission value")
set(lwip_tcp_queue_ooseq 1 CACHE STRING "Should TCP queue segments arriving out of order. Set to 0 if your device is low on memory")
set_property(CACHE lwip_tcp_queue_ooseq PROPERTY STRINGS 0 1)

option(lwip_dhcp_options "Is DHCP required?" ON)
option(lwip_dhcp "Is DHCP required?" OFF)
option(lwip_dhcp_does_arp_check "ARP check on offered addresses?" OFF)

option(lwip_stats_options "Turn on lwIP statistics?" ON)
option(lwip_stats "Turn on lwIP statistics?" OFF)

option(lwip_debug_options "Turn on lwIP Debug?" ON)
option(lwip_debug "Turn on lwIP Debug?" OFF)
option(lwip_ip_debug "Debug IP layer" OFF)
option(lwip_tcp_debug "Debug TCP layer" OFF)
option(lwip_udp_debug "Debug UDP layer" OFF)
option(lwip_icmp_debug "Debug ICMP protocol" OFF)
option(lwip_igmp_debug "Debug IGMP protocol" OFF)
option(lwip_netif_debug "Debug network interface layer" OFF)
option(lwip_sys_debug "Debug sys arch layer" OFF)
option(lwip_pbuf_debug "Debug pbuf layer" OFF)

if("${lwip_api_mode}" STREQUAL RAW_API)
    set(NO_SYS 1)
endif()

if(${lwip_no_sys_no_timers})
    set(NO_SYS_NO_TIMERS " ")
endif()

if(${lwip_tcp_keepalive})
    set(LWIP_TCP_KEEPALIVE " ")
endif()

set(MEM_SIZE ${lwip_mem_size})
set(MEMP_NUM_PBUF ${lwip_memp_n_pbuf})
set(MEMP_NUM_UDP_PCB ${lwip_memp_n_udp_pcb})
set(MEMP_NUM_TCP_PCB ${lwip_memp_n_tcp_pcb})
set(MEMP_NUM_TCP_PCB_LISTEN ${lwip_memp_n_tcp_pcb_listen})
set(MEMP_NUM_TCP_SEG ${lwip_memp_n_tcp_seg})
set(MEMP_NUM_SYS_TIMEOUT ${lwip_memp_n_sys_timeout})
set(MEMP_NUM_NETBUF ${lwip_memp_num_netbuf}) 
set(MEMP_NUM_NETCONN ${lwip_memp_num_netconn})
set(MEMP_NUM_TCPIP_MSG_API ${lwip_memp_num_api_msg})
set(MEMP_NUM_TCPIP_MSG_INPKT ${lwip_memp_num_tcpip_msg})

# PBUF options
set(PBUF_POOL_SIZE ${lwip_pbuf_pool_size})
set(PBUF_POOL_BUFSIZE ${lwip_pbuf_pool_bufsize})
set(PBUF_LINK_HLEN ${lwip_pbuf_link_hlen})

# ARP options
set(ARP_TABLE_SIZE ${lwip_arp_table_size})
set(ARP_QUEUEING ${lwip_arp_queueing})

#ICMP options
set(ICMP_TTL ${lwip_icmp_ttl})

#IPV6 options
if (${lwip_ipv6_enable})
   set(LWIP_IPV6 " ")
endif()
set(LWIP_IGMP ${lwip_igmp_options})

#IP options
set(IP_OPTIONS ${lwip_ip_options})
set(IP_FORWARD ${lwip_ip_forward})
set(IP_REASSEMBLY ${lwip_ip_reassembly})
set(IP_FRAG ${lwip_ip_frag})
set(IP_REASS_MAX_PBUFS ${lwip_ip_reass_max_pbufs})
set(IP_FRAG_MAX_MTU ${lwip_ip_frag_max_mtu})
set(IP_DEFAULT_TTL ${lwip_ip_default_ttl})

#UDP options
if (${lwip_udp})
    set(LWIP_UDP 1)
endif()

set(UDP_TTL ${lwip_udp_ttl})

#TCP options
if (${lwip_tcp})
    set(LWIP_TCP 1)
endif()
set(TCP_MSS ${lwip_tcp_mss})
set(TCP_SND_BUF ${lwip_tcp_snd_buf})
set(TCP_WND ${lwip_tcp_wnd})
set(TCP_TTL ${lwip_tcp_ttl})
set(TCP_MAXRTX ${lwip_tcp_maxrtx})
set(TCP_SYNMAXRTX ${lwip_tcp_synmaxrtx})
set(TCP_QUEUE_OOSEQ ${lwip_tcp_queue_ooseq})

## Checksum handling should be based on the MAC_INSTANCE variable
list(LENGTH MAC_INSTANCES _len)
if (${_len} GREATER 1)
    list(GET MAC_INSTANCES 0 MAC_INSTANCES)
endif()

if (${CONFIG_AXIETHERNET})
    if (MAC_INSTANCES IN_LIST AXIETHERNET_NUM_DRIVER_INSTANCES)
        if (${lwip_temac_tcp_ip_tx_checksum_offload})
            if (${axieth_txcsum} EQUAL 0x2)
                set(CHECKSUM_GEN_TCP " ")
                set(CHECKSUM_GEN_UDP " ")
                set(CHECKSUM_GEN_IP " ")
                set(LWIP_FULL_CSUM_OFFLOAD_TX 1)
            else()
                message(FATAL_ERROR "Wrong Tx checksum options. The selected Tx checksum does not match with the HW supported Tx csum offload option")
            endif()
        endif()
        if (${lwip_temac_tcp_ip_rx_checksum_offload})
            if (${axieth_rxcsum} EQUAL 0x2)
                set(CHECKSUM_CHECK_TCP " ")
                set(CHECKSUM_CHECK_UDP " ")
                set(CHECKSUM_CHECK_IP " ")
                set(LWIP_FULL_CSUM_OFFLOAD_RX 1)
            else()
                message(FATAL_ERROR "Wrong Rx checksum options. The selected Rx checksum does not match with the HW supported Rx csum offload option")
            endif()
        endif()
        if (${lwip_temac_tcp_tx_checksum_offload})
            if (${axieth_txcsum} EQUAL 0x1)
                set(CHECKSUM_GEN_TCP " ")
                set(LWIP_PARTIAL_CSUM_OFFLOAD_TX 1)
            else()
                message(FATAL_ERROR "Wrong Tx checksum options. The selected Tx checksum does not match with the HW supported Tx csum offload option")
            endif()
        endif()
        if (${lwip_temac_tcp_rx_checksum_offload})
            if (${axieth_rxcsum} EQUAL 0x1)
                set(CHECKSUM_CHECK_TCP " ")
                set(LWIP_PARTIAL_CSUM_OFFLOAD_RX 1)
            else()
                message(FATAL_ERROR "Wrong Rx checksum options. The selected Rx checksum does not match with the HW supported Rx csum offload option")
            endif()
        endif()
        if (NOT ${lwip_temac_tcp_ip_tx_checksum_offload} AND NOT ${lwip_temac_tcp_tx_checksum_offload})
            set(CHECKSUM_GEN_TCP " ")
            set(CHECKSUM_GEN_UDP " ")
            set(CHECKSUM_GEN_IP " ")
        endif()
        if (NOT ${lwip_temac_tcp_ip_rx_checksum_offload} AND NOT ${lwip_temac_tcp_rx_checksum_offload})
            set(CHECKSUM_CHECK_TCP " ")
            set(CHECKSUM_CHECK_UDP " ")
            set(CHECKSUM_CHECK_IP " ")
        endif()
    endif()
endif()

if(${CONFIG_EMACLITE})
    if (MAC_INSTANCES IN_LIST EMACLITE_NUM_DRIVER_INSTANCES)
        set(CHECKSUM_GEN_TCP " ")
	set(CHECKSUM_GEN_UDP " ")
	set(CHECKSUM_GEN_IP " ")
	set(CHECKSUM_CHECK_TCP " ")
	set(CHECKSUM_CHECK_UDP " ")
	set(CHECKSUM_CHECK_IP " ")
    endif()
endif()

if (${CONFIG_EMACPS})
    if (MAC_INSTANCES IN_LIST EMACPS_NUM_DRIVER_INSTANCES)
	set(LWIP_FULL_CSUM_OFFLOAD_RX 1)
	set(LWIP_FULL_CSUM_OFFLOAD_TX 1)
        set(index 0)
        LIST_INDEX(${index} ${MAC_INSTANCES} "${EMACPS_NUM_DRIVER_INSTANCES}")
        list(GET TOTAL_EMACPS_PROP_LIST ${index} x)
        set(y ${${x}})
        list(GET y -1 phy_type)
        if (${phy_type} EQUAL 0x5)
            set(XLWIP_CONFIG_PCS_PMA_1000BASEX_CORE_PRESENT 1)
        elseif (${phy_type} EQUAL 0x4)
            set(XLWIP_CONFIG_PCS_PMA_SGMII_CORE_PRESENT 1)
        endif()
    endif()
endif()

if(("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "microblaze") OR 
   ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "microblazeel") OR
   ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "plm_microblaze") OR
   ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "pmu_microblaze"))
    set(TCP_OVERSIZE 0x0)
else()
    set(TCP_OVERSIZE TCP_MSS)
endif()

if (${temac_use_jumbo_frames})
    set(USE_JUMBO_FRAMES 1)
endif()

if (${lwip_dhcp})
   set(LWIP_DHCP " ")
endif()
if (${lwip_dhcp_does_arp_check})
    set(DHCP_DOES_ARP_CHECK " ")
endif()

set(linkspeed "#define ${lwip_temac_phy_link_speed} 1")
if (${lwip_stats})
    set(LWIP_STATS 1)
    set(LWIP_STATS_DISPLAY 1)    
endif()

if (${lwip_debug})
    set(LWIP_DEBUG 1)
    set(DBG_TYPES_ON DBG_LEVEL_WARNING)
    if (${lwip_ip_debug})
        set(IP_DEBUG (LWIP_DBG_LEVEL_SEVERE | LWIP_DBG_ON))
    endif()
    if (${lwip_tcp_debug})
        set(TCP_DEBUG (LWIP_DBG_LEVEL_SEVERE | LWIP_DBG_ON))
        set(TCP_INPUT_DEBUG (LWIP_DBG_LEVEL_SEVERE | LWIP_DBG_ON))
        set(TCP_OUTPUT_DEBUG (LWIP_DBG_LEVEL_SEVERE | LWIP_DBG_ON))
        set(TCPIP_DEBUG (LWIP_DBG_LEVEL_SEVERE | LWIP_DBG_ON))
    endif()
    if (${lwip_udp_debug})
        set(UDP_DEBUG (LWIP_DBG_LEVEL_SEVERE | LWIP_DBG_ON))
    endif()
    if (${lwip_icmp_debug})
        set(ICMP_DEBUG (LWIP_DBG_LEVEL_SEVERE | LWIP_DBG_ON))
    endif()
    if (${lwip_igmp_debug})
        set(IGMP_DEBUG (LWIP_DBG_LEVEL_SEVERE | LWIP_DBG_ON))
    endif()
    if (${lwip_netif_debug})
        set(NETIF_DEBUG (LWIP_DBG_LEVEL_SEVERE | LWIP_DBG_ON))
    endif()
    if (${lwip_sys_debug})
        set(SYS_DEBUG (LWIP_DBG_LEVEL_SEVERE | LWIP_DBG_ON))
        set(API_MSG_DEBUG (LWIP_DBG_LEVEL_SEVERE | LWIP_DBG_ON))
    endif()
    if (${lwip_pbuf_debug})
        set(PBUF_DEBUG (LWIP_DBG_LEVEL_SEVERE | LWIP_DBG_ON))
    endif()
    set(MEMP_DEBUG (LWIP_DBG_LEVEL_SEVERE | LWIP_DBG_ON))
endif()

## xlwipconfig.h.in file handling
foreach(x IN LISTS TOTAL_AXIETHERNET_PROP_LIST)
    set(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET 1)
    set(y ${${x}})
    list(GET y -1 connected_ip)
    if (${connected_ip} EQUAL 0x1)
       set(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET_FIFO 1)
    elseif (${connected_ip} EQUAL 0x2)
       set(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET_DMA 1)
    elseif (${connected_ip} EQUAL 0x3)
       set(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET_MCDMA 1)
    endif()
endforeach()

if (${CONFIG_EMACLITE})
    set(XLWIP_CONFIG_INCLUDE_EMACLITE 1)
endif()

if (${CONFIG_EMACPS})
    set(XLWIP_CONFIG_INCLUDE_GEM 1)
endif()

set(XLWIP_CONFIG_N_TX_DESC ${lwip_temac_n_tx_descriptors})
set(XLWIP_CONFIG_N_RX_DESC ${lwip_temac_n_rx_descriptors})
set(XLWIP_CONFIG_N_TX_COALESCE ${lwip_temac_n_tx_coalesce})
set(XLWIP_CONFIG_N_RX_COALESCE ${lwip_temac_n_rx_coalesce})

if(("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeRTOS") AND
   ("${lwip_api_mode}" STREQUAL SOCKET_API))
    set(OS_IS_FREERTOS " ")
    set(LWIP_PROVIDE_ERRNO 1)
    set(DEFAULT_THREAD_PRIO ${lwip_socket_mode_thread_prio})
    set(LWIP_SOCKET " ")
    set(LWIP_COMPAT_SOCKETS " ")
    set(LWIP_NETCONN " ")
    if(("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "cortexa72")
        OR ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "cortexa53")
        OR ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "cortexa53-32")
	OR ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64"))
        set(TCPIP_THREAD_PRIO ${lwip_socket_mode_thread_prio})
    else()
        MATH(EXPR TCPIP_THREAD_PRIO "${lwip_socket_mode_thread_prio}+1")
    endif()
    set(TCPIP_THREAD_STACKSIZE 1024)
    set(DEFAULT_TCP_RECVMBOX_SIZE ${lwip_mbox_default_tcp_recvmbox_size})
    set(DEFAULT_ACCEPTMBOX_SIZE 5)
    set(TCPIP_MBOX_SIZE ${lwip_mbox_tcpip_mbox_size})
    set(DEFAULT_UDP_RECVMBOX_SIZE ${lwip_mbox_default_udp_recvmbox_size})
    set(DEFAULT_RAW_RECVMBOX_SIZE 30)
    set(LWIP_COMPAT_MUTEX 0x0)
    set(LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 1)
    if (${lwip_mbox_lwip_tcpip_core_locking_input})
        set(LWIP_TCPIP_CORE_LOCKING_INPUT 1)
    endif()
endif()

configure_file(${CMAKE_SOURCE_DIR}/../data/lwipopts.h.in ${CMAKE_BINARY_DIR}/include/lwipopts.h)
configure_file(${CMAKE_SOURCE_DIR}/../data/xlwipconfig.h.in ${CMAKE_BINARY_DIR}/include/xlwipconfig.h)
