/*
 * lip_eth.c
 *
 *  Created on: 31.08.2010
 *      Author: borisov
 */

#ifndef LIP_ETH_C_
#define LIP_ETH_C_

#include "lip/lip_defs.h"
#include "lip_ll_port_features.h"
#include "lcspec.h"
#include "lip_eth_defs.h"
#include "lip/ll/lip_ll.h"
#include "lip_vlan_cfg_defs.h"
#if LIP_VLAN_ENABLE
    #include "lip_vlan.h"
#endif
#if LIP_SW_SUPPORT_KSZ8567
#include "lip/phy/ksz8567/lip_sw_ksz8567.h"
#endif



#define LIP_ETH_FLAGS_BROADCAST         0x2
#define LIP_ETH_FLAGS_MULTICAST         0x4


#if LIP_LL_PORT_FEATURE_HW_TX_ETH_SA_INS
    /** Минимальный размер передаваемых в пакете данных (без CRC и других аппаратно добавляемых полей) */
    #define LIP_ETH_MIN_TXDATA_SIZE           (LIP_ETH_MIN_PACKET_SIZE - LIP_MAC_ADDR_SIZE)
#else
    #define LIP_ETH_MIN_TXDATA_SIZE           LIP_ETH_MIN_PACKET_SIZE
#endif

/* тип протокола, используется как в пакете
 * Ethernet, так и в пакете ARP
 */
typedef enum {
    LIP_ETHTYPE_IPv4    = 0x0800,
    LIP_ETHTYPE_ARP     = 0x0806,
    LIP_ETHTYPE_CVLAN   = 0x8100, /**< Customer VLAN Tag (IEEE 802.1Q-2018 Table 9-1) */
    LIP_ETHTYPE_IPv6    = 0x86dd,
    LIP_ETHTYPE_SVLAN   = 0x88A8, /**< Service VLAN Tag or Backbone VLAN Tag (IEEE 802.1Q-2018 Table 9-1) */
    LIP_ETHTYPE_ITAG    = 0x88E7, /**< Backbone Service Instance Tag (IEEE 802.1Q-2018 Table 9-1) */
    LIP_ETHTYPE_PTP     = 0x88F7, /**< PTP over Ethernet (IEEE 1588, Annex E) */
    LIP_ETHTYPE_OPC_UADP= 0xB62C, /**< OPC UA Pub/Sub over TSN */
} t_lip_ethtype;

typedef uint8_t t_lip_mac_addr[LIP_MAC_ADDR_SIZE];

#include "lcspec_pack_start.h"
typedef struct {
    t_lip_mac_addr da;
    t_lip_mac_addr sa;
    uint16_t type;
} LATTRIBUTE_PACKED t_lip_eth_hdr;
#include "lcspec_pack_restore.h"

typedef struct {
    t_lip_rx_frame *ll_frame;
    uint16_t        flags;
    uint16_t        type;
    t_lip_payload   pl;
} t_lip_eth_rx_packet;

#define LIP_ETH_HDR_SIZE (sizeof(t_lip_eth_hdr))


extern const uint8_t g_lip_broadcast_mac[LIP_MAC_ADDR_SIZE];

#define lip_eth_is_bcast(_addr) !memcmp(_addr, g_lip_broadcast_mac, LIP_MAC_ADDR_SIZE)



/***************************************************************************//** 
    Установка mac-адреса устройства. Функция должна вызываться сразу после
    вызова lip_init() 
    @param mac   указатель на массив длиной #LIP_MAC_ADDR_SIZE с устанавливаемым 
                 MAC-адресом 
 ******************************************************************************/
void lip_eth_set_mac_addr(const uint8_t *mac);

const uint8_t *lip_eth_cur_mac(void);

t_lip_errs lip_eth_send(const uint8_t *buf, size_t size, t_lip_ethtype type, const uint8_t *dest_addr);
t_lip_tx_frame *lip_eth_frame_prepare(const t_lip_tx_frame_info *finfo, t_lip_ethtype type, const uint8_t *dest_addr);
#define lip_eth_frame_flush     lip_tx_frame_flush
void *lip_eth_prepare_def(t_lip_ethtype type, const uint8_t *dest_addr, int *max_size);
t_lip_errs lip_eth_flush_split(size_t size, const uint8_t *data, int data_size);
#define lip_eth_flush(size) lip_eth_flush_split(size, NULL, 0)

#if LIP_SW_SUPPORT_KSZ8567
#define lip_tx_frame_prepare        lip_sw_ksz8567_tx_prepare
#define lip_tx_frame_flush          lip_sw_ksz8567_tx_flush
#define lip_rx_process              lip_sw_ksz8567_process_packet
#else
#define lip_tx_frame_prepare        lip_mac_tx_frame_prepare
#define lip_tx_frame_flush          lip_mac_tx_frame_flush
#define lip_rx_process(rx_frame)    LIP_ERR_SUCCESS
#endif

#if LIP_ETH_RX_UNSUP_TYPE_CB
    void lip_eth_user_packet_process(t_lip_payload *pl, const t_lip_eth_rx_packet *eth_packet);
#endif

#endif /* LIP_ETH_C_ */
