generated from Embedded_Projects/Landzo_K60Z_LwIP
1078 lines
36 KiB
C
1078 lines
36 KiB
C
/*
|
|
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
|
* 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.
|
|
*
|
|
* Author: Adam Dunkels <adam@sics.se>
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) 2013-2016, Freescale Semiconductor, Inc.
|
|
* Copyright 2016 NXP
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
* are permitted provided that the following conditions are met:
|
|
*
|
|
* o Redistributions of source code must retain the above copyright notice, this list
|
|
* of conditions and the following disclaimer.
|
|
*
|
|
* o 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.
|
|
*
|
|
* o Neither the name of the copyright holder nor the names of its
|
|
* contributors may be used to endorse or promote products derived from this
|
|
* software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 SDRVL THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.
|
|
*/
|
|
|
|
#include "lwip/opt.h"
|
|
#include "lwip/def.h"
|
|
#include "lwip/mem.h"
|
|
#include "lwip/pbuf.h"
|
|
#include "lwip/stats.h"
|
|
#include "lwip/snmp.h"
|
|
#include "lwip/ethip6.h"
|
|
#include "netif/etharp.h"
|
|
#include "netif/ppp/pppoe.h"
|
|
#include "lwip/igmp.h"
|
|
#include "lwip/mld6.h"
|
|
|
|
#define USE_RTOS 1
|
|
#define FSL_RTOS_FREE_RTOS 1
|
|
|
|
#define LINK_SPEED_OF_YOUR_NETIF_IN_BPS 100000000
|
|
|
|
#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
|
|
#include "FreeRTOS.h"
|
|
#include "event_groups.h"
|
|
#include "task.h"
|
|
#endif
|
|
|
|
#include "ethernetif.h"
|
|
|
|
#include "fsl_enet.h"
|
|
#include "fsl_phy.h"
|
|
|
|
/*******************************************************************************
|
|
* Definitions
|
|
******************************************************************************/
|
|
/* Define those to better describe your network interface. */
|
|
#define IFNAME0 'e'
|
|
#define IFNAME1 'n'
|
|
|
|
#define ENET_ALIGN(x) \
|
|
((unsigned int)((x) + ((ENET_BUFF_ALIGNMENT)-1)) & (unsigned int)(~(unsigned int)((ENET_BUFF_ALIGNMENT)-1)))
|
|
|
|
#if defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0)
|
|
#define kENET_RxEvent kENET_RxIntEvent
|
|
#define kENET_TxEvent kENET_TxIntEvent
|
|
#endif
|
|
|
|
/**
|
|
* Helper struct to hold private data used to operate your ethernet interface.
|
|
*/
|
|
struct ethernetif
|
|
{
|
|
ENET_Type *base;
|
|
#if (defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0)) || \
|
|
(USE_RTOS && defined(FSL_RTOS_FREE_RTOS))
|
|
enet_handle_t handle;
|
|
#endif
|
|
uint32_t phyAddr;
|
|
#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
|
|
EventGroupHandle_t enetTransmitAccessEvent;
|
|
TaskHandle_t rxTaskHandle;
|
|
EventBits_t txFlag;
|
|
#endif
|
|
uint8_t RxBuffDescrip[ENET_RXBD_NUM * sizeof(enet_rx_bd_struct_t) + ENET_BUFF_ALIGNMENT];
|
|
uint8_t TxBuffDescrip[ENET_TXBD_NUM * sizeof(enet_tx_bd_struct_t) + ENET_BUFF_ALIGNMENT];
|
|
uint8_t RxDataBuff[ENET_RXBD_NUM * ENET_ALIGN(ENET_RXBUFF_SIZE) + ENET_BUFF_ALIGNMENT];
|
|
uint8_t TxDataBuff[ENET_TXBD_NUM * ENET_ALIGN(ENET_TXBUFF_SIZE) + ENET_BUFF_ALIGNMENT];
|
|
#if defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0)
|
|
uint8_t txIdx;
|
|
#if !(USE_RTOS && defined(FSL_RTOS_FREE_RTOS))
|
|
uint8_t rxIdx;
|
|
#endif
|
|
#endif
|
|
};
|
|
|
|
/*******************************************************************************
|
|
* Variables
|
|
******************************************************************************/
|
|
|
|
static struct ethernetif ethernetif_0;
|
|
|
|
/*******************************************************************************
|
|
* Code
|
|
******************************************************************************/
|
|
#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
|
|
#if defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0)
|
|
static void ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, void *param)
|
|
#elif defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0)
|
|
static void ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, uint8_t channel, void *param)
|
|
#endif /* FSL_FEATURE_SOC_*_ENET_COUNT */
|
|
{
|
|
struct netif *netif = (struct netif *)param;
|
|
struct ethernetif *ethernetif = netif->state;
|
|
|
|
BaseType_t xHigherPriorityTaskWoken = 0U;
|
|
|
|
switch (event)
|
|
{
|
|
case kENET_RxEvent:
|
|
{
|
|
if(__get_IPSR())
|
|
{
|
|
xTaskNotifyFromISR(ethernetif->rxTaskHandle, 0x1UL, eSetBits, &xHigherPriorityTaskWoken);
|
|
}
|
|
else
|
|
{
|
|
xTaskNotify(ethernetif->rxTaskHandle, 0x1UL, eSetBits);
|
|
}
|
|
break;
|
|
}
|
|
case kENET_TxEvent:
|
|
{
|
|
if (__get_IPSR())
|
|
{
|
|
xEventGroupSetBitsFromISR(ethernetif->enetTransmitAccessEvent, ethernetif->txFlag, &xHigherPriorityTaskWoken);
|
|
}
|
|
else
|
|
{
|
|
xEventGroupSetBits(ethernetif->enetTransmitAccessEvent, ethernetif->txFlag);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if(__get_IPSR())
|
|
{
|
|
if (pdTRUE == xHigherPriorityTaskWoken)
|
|
{
|
|
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if LWIP_IPV4 && LWIP_IGMP
|
|
static err_t ethernetif_igmp_mac_filter(struct netif *netif, const ip4_addr_t *group, u8_t action)
|
|
{
|
|
struct ethernetif *ethernetif = netif->state;
|
|
uint8_t multicastMacAddr[6];
|
|
err_t result;
|
|
|
|
multicastMacAddr[0] = 0x01U;
|
|
multicastMacAddr[1] = 0x00U;
|
|
multicastMacAddr[2] = 0x5EU;
|
|
multicastMacAddr[3] = (group->addr >> 8) & 0x7FU;
|
|
multicastMacAddr[4] = (group->addr >> 16) & 0xFFU;
|
|
multicastMacAddr[5] = (group->addr >> 24) & 0xFFU;
|
|
|
|
switch (action)
|
|
{
|
|
case IGMP_ADD_MAC_FILTER:
|
|
/* Adds the ENET device to a multicast group.*/
|
|
ENET_AddMulticastGroup(ethernetif->base, multicastMacAddr);
|
|
result = ERR_OK;
|
|
break;
|
|
case IGMP_DEL_MAC_FILTER:
|
|
/* Moves the ENET device from a multicast group.*/
|
|
#if 0
|
|
ENET_LeaveMulticastGroup(ethernetif->base, multicastMacAddr);
|
|
#endif
|
|
result = ERR_OK;
|
|
break;
|
|
default:
|
|
result = ERR_IF;
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
#endif
|
|
|
|
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
|
static err_t ethernetif_mld_mac_filter(struct netif *netif, const ip6_addr_t *group, enum netif_mac_filter_action action)
|
|
{
|
|
struct ethernetif *ethernetif = netif->state;
|
|
uint8_t multicastMacAddr[6];
|
|
err_t result;
|
|
|
|
multicastMacAddr[0] = 0x33U;
|
|
multicastMacAddr[1] = 0x33U;
|
|
multicastMacAddr[2] = (group->addr[3]) & 0xFFU;
|
|
multicastMacAddr[3] = (group->addr[3] >> 8) & 0xFFU;
|
|
multicastMacAddr[4] = (group->addr[3] >> 16) & 0xFFU;
|
|
multicastMacAddr[5] = (group->addr[3] >> 24) & 0xFFU;
|
|
|
|
switch (action)
|
|
{
|
|
case NETIF_ADD_MAC_FILTER:
|
|
/* Adds the ENET device to a multicast group.*/
|
|
ENET_AddMulticastGroup(ethernetif->base, multicastMacAddr);
|
|
result = ERR_OK;
|
|
break;
|
|
case NETIF_DEL_MAC_FILTER:
|
|
/* Moves the ENET device from a multicast group.*/
|
|
#if 0
|
|
ENET_LeaveMulticastGroup(ethernetif->base, multicastMacAddr);
|
|
#endif
|
|
result = ERR_OK;
|
|
break;
|
|
default:
|
|
result = ERR_IF;
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
#endif
|
|
|
|
#if defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0)
|
|
static inline enet_rx_bd_struct_t *get_rx_desc(struct ethernetif *ethernetif, uint32_t index)
|
|
{
|
|
return (enet_rx_bd_struct_t *)ENET_ALIGN(ðernetif->RxBuffDescrip[index * sizeof(enet_rx_bd_struct_t)]);
|
|
}
|
|
|
|
static inline enet_tx_bd_struct_t *get_tx_desc(struct ethernetif *ethernetif, uint32_t index)
|
|
{
|
|
return (enet_tx_bd_struct_t *)ENET_ALIGN(ðernetif->TxBuffDescrip[index * sizeof(enet_tx_bd_struct_t)]);
|
|
}
|
|
#endif
|
|
|
|
#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
|
|
static void enet_rx_task(void *params) {
|
|
struct netif *netif = params;
|
|
uint32_t ulNotifyValue = 0U;
|
|
|
|
for(;;) {
|
|
xTaskNotifyWait(0UL, 0xFFFFFFFFUL, &ulNotifyValue, portMAX_DELAY);
|
|
ethernetif_input(netif);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* Initializes ENET driver.
|
|
*/
|
|
#if defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0)
|
|
static void enet_init(struct netif *netif, struct ethernetif *ethernetif)
|
|
{
|
|
enet_config_t config;
|
|
uint32_t sysClock;
|
|
bool link = false;
|
|
phy_speed_t speed;
|
|
phy_duplex_t duplex;
|
|
uint32_t count = 0;
|
|
enet_buffer_config_t buffCfg;
|
|
|
|
/* prepare the buffer configuration. */
|
|
buffCfg.rxBdNumber = ENET_RXBD_NUM; /* Receive buffer descriptor number. */
|
|
buffCfg.txBdNumber = ENET_TXBD_NUM; /* Transmit buffer descriptor number. */
|
|
buffCfg.rxBuffSizeAlign = ENET_ALIGN(ENET_RXBUFF_SIZE); /* Aligned receive data buffer size. */
|
|
buffCfg.txBuffSizeAlign = ENET_ALIGN(ENET_TXBUFF_SIZE); /* Aligned transmit data buffer size. */
|
|
buffCfg.rxBdStartAddrAlign = (enet_rx_bd_struct_t *)ENET_ALIGN(
|
|
ethernetif->RxBuffDescrip); /* Aligned receive buffer descriptor start address. */
|
|
buffCfg.txBdStartAddrAlign = (enet_tx_bd_struct_t *)ENET_ALIGN(
|
|
ethernetif->TxBuffDescrip); /* Aligned transmit buffer descriptor start address. */
|
|
buffCfg.rxBufferAlign = (uint8_t *)ENET_ALIGN(ethernetif->RxDataBuff); /* Receive data buffer start address. */
|
|
buffCfg.txBufferAlign = (uint8_t *)ENET_ALIGN(ethernetif->TxDataBuff); /* Transmit data buffer start address. */
|
|
|
|
sysClock = CLOCK_GetFreq(kCLOCK_CoreSysClk);
|
|
|
|
ENET_GetDefaultConfig(&config);
|
|
|
|
PHY_Init(ethernetif->base, ethernetif->phyAddr, sysClock);
|
|
|
|
while ((count < ENET_ATONEGOTIATION_TIMEOUT) && (!link))
|
|
{
|
|
PHY_GetLinkStatus(ethernetif->base, ethernetif->phyAddr, &link);
|
|
|
|
if (link)
|
|
{
|
|
/* Get the actual PHY link speed. */
|
|
PHY_GetLinkSpeedDuplex(ethernetif->base, ethernetif->phyAddr, &speed, &duplex);
|
|
/* Change the MII speed and duplex for actual link status. */
|
|
config.miiSpeed = (enet_mii_speed_t)speed;
|
|
config.miiDuplex = (enet_mii_duplex_t)duplex;
|
|
}
|
|
|
|
count++;
|
|
}
|
|
|
|
#if 0 /* Disable assert. If initial auto-negation is timeout, \ \
|
|
the ENET set to default 100Mbs and full-duplex.*/
|
|
if (count == ENET_ATONEGOTIATION_TIMEOUT)
|
|
{
|
|
LWIP_ASSERT("\r\nPHY Link down, please check the cable connection.\r\n", 0);
|
|
}
|
|
#endif
|
|
|
|
#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
|
|
/* Create the Event for transmit busy release trigger. */
|
|
ethernetif->enetTransmitAccessEvent = xEventGroupCreate();
|
|
ethernetif->txFlag = 0x1;
|
|
|
|
config.interrupt |= kENET_RxFrameInterrupt | kENET_TxFrameInterrupt | kENET_TxBufferInterrupt;
|
|
|
|
NVIC_SetPriority(ENET_Receive_IRQn, ENET_PRIORITY);
|
|
NVIC_SetPriority(ENET_Transmit_IRQn, ENET_PRIORITY);
|
|
#ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE
|
|
NVIC_SetPriority(ENET_1588_Timer_IRQn, ENET_1588_PRIORITY);
|
|
#endif
|
|
#endif /* USE_RTOS */
|
|
|
|
/* Initialize the ENET module.*/
|
|
ENET_Init(ethernetif->base, ðernetif->handle, &config, &buffCfg, netif->hwaddr, sysClock);
|
|
|
|
#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
|
|
xTaskCreate(enet_rx_task, "enet_rx_task", 1024, netif, 16, ðernetif->rxTaskHandle);
|
|
|
|
ENET_SetCallback(ðernetif->handle, ethernet_callback, netif);
|
|
#endif
|
|
|
|
ENET_ActiveRead(ethernetif->base);
|
|
}
|
|
#elif defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0)
|
|
static void enet_init(struct netif *netif, struct ethernetif *ethernetif)
|
|
{
|
|
enet_config_t config;
|
|
uint32_t sysClock;
|
|
bool link = false;
|
|
phy_speed_t speed;
|
|
phy_duplex_t duplex;
|
|
uint32_t count = 0;
|
|
enet_buffer_config_t buffCfg;
|
|
uint32_t rxBufferStartAddr[ENET_RXBD_NUM];
|
|
uint32_t i;
|
|
|
|
/* calculate start addresses of all rx buffers */
|
|
for (i = 0; i < ENET_RXBD_NUM; i++)
|
|
{
|
|
rxBufferStartAddr[i] = ENET_ALIGN(ðernetif->RxDataBuff[i * ENET_ALIGN(ENET_RXBUFF_SIZE)]);
|
|
}
|
|
|
|
/* prepare the buffer configuration. */
|
|
buffCfg.rxRingLen = ENET_RXBD_NUM; /* The length of receive buffer descriptor ring. */
|
|
buffCfg.txRingLen = ENET_TXBD_NUM; /* The length of transmit buffer descriptor ring. */
|
|
buffCfg.txDescStartAddrAlign = get_tx_desc(ethernetif, 0U); /* Aligned transmit descriptor start address. */
|
|
buffCfg.txDescTailAddrAlign = get_tx_desc(ethernetif, 0U); /* Aligned transmit descriptor tail address. */
|
|
buffCfg.rxDescStartAddrAlign = get_rx_desc(ethernetif, 0U); /* Aligned receive descriptor start address. */
|
|
buffCfg.rxDescTailAddrAlign = get_rx_desc(ethernetif, ENET_RXBD_NUM); /* Aligned receive descriptor tail address. */
|
|
buffCfg.rxBufferStartAddr = rxBufferStartAddr; /* Start addresses of the rx buffers. */
|
|
buffCfg.rxBuffSizeAlign = ENET_ALIGN(ENET_RXBUFF_SIZE); /* Aligned receive data buffer size. */
|
|
|
|
sysClock = CLOCK_GetFreq(kCLOCK_CoreSysClk);
|
|
|
|
ENET_GetDefaultConfig(&config);
|
|
|
|
PHY_Init(ethernetif->base, ethernetif->phyAddr, 0);
|
|
|
|
while ((count < ENET_ATONEGOTIATION_TIMEOUT) && (!link))
|
|
{
|
|
PHY_GetLinkStatus(ethernetif->base, ethernetif->phyAddr, &link);
|
|
if (link)
|
|
{
|
|
/* Get the actual PHY link speed. */
|
|
PHY_GetLinkSpeedDuplex(ethernetif->base, ethernetif->phyAddr, &speed, &duplex);
|
|
/* Change the MII speed and duplex for actual link status. */
|
|
config.miiSpeed = (enet_mii_speed_t)speed;
|
|
config.miiDuplex = (enet_mii_duplex_t)duplex;
|
|
}
|
|
|
|
count++;
|
|
}
|
|
|
|
#if 0 /* Disable assert. If initial auto-negation is timeout, \ \
|
|
the ENET set to default 100Mbs and full-duplex.*/
|
|
if (count == ENET_ATONEGOTIATION_TIMEOUT)
|
|
{
|
|
LWIP_ASSERT("\r\nPHY Link down, please check the cable connection.\r\n", 0);
|
|
}
|
|
#endif
|
|
|
|
#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
|
|
/* Create the Event for transmit busy release trigger. */
|
|
ethernetif->enetTransmitAccessEvent = xEventGroupCreate();
|
|
ethernetif->txFlag = 0x1;
|
|
|
|
NVIC_SetPriority(ETHERNET_IRQn, ENET_PRIORITY);
|
|
#else
|
|
ethernetif->rxIdx = 0U;
|
|
#endif /* USE_RTOS */
|
|
|
|
ethernetif->txIdx = 0U;
|
|
|
|
ENET_Init(ethernetif->base, &config, netif->hwaddr, sysClock);
|
|
|
|
/* Create the handler. */
|
|
#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
|
|
ENET_EnableInterrupts(ethernetif->base, kENET_DmaTx | kENET_DmaRx);
|
|
ENET_CreateHandler(ethernetif->base, ðernetif->handle, &config, &buffCfg, ethernet_callback, netif);
|
|
#endif
|
|
|
|
ENET_DescriptorInit(ethernetif->base, &config, &buffCfg);
|
|
|
|
/* Active TX/RX. */
|
|
ENET_StartRxTx(ethernetif->base, 1, 1);
|
|
}
|
|
#endif /* FSL_FEATURE_SOC_*_ENET_COUNT */
|
|
|
|
/**
|
|
* In this function, the hardware should be initialized.
|
|
* Called from ethernetif_init().
|
|
*
|
|
* @param netif the already initialized lwip network interface structure
|
|
* for this ethernetif
|
|
*/
|
|
static void low_level_init(struct netif *netif)
|
|
{
|
|
struct ethernetif *ethernetif = netif->state;
|
|
|
|
/* set MAC hardware address length */
|
|
netif->hwaddr_len = ETHARP_HWADDR_LEN;
|
|
|
|
/* set MAC hardware address */
|
|
netif->hwaddr[0] = configMAC_ADDR0;
|
|
netif->hwaddr[1] = configMAC_ADDR1;
|
|
netif->hwaddr[2] = configMAC_ADDR2;
|
|
netif->hwaddr[3] = configMAC_ADDR3;
|
|
netif->hwaddr[4] = configMAC_ADDR4;
|
|
netif->hwaddr[5] = configMAC_ADDR5;
|
|
|
|
/* maximum transfer unit */
|
|
netif->mtu = 1500; /* TODO: define a config */
|
|
|
|
/* device capabilities */
|
|
/* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
|
|
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
|
|
|
|
/* ENET driver initialization.*/
|
|
enet_init(netif, ethernetif);
|
|
|
|
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
|
/*
|
|
* For hardware/netifs that implement MAC filtering.
|
|
* All-nodes link-local is handled by default, so we must let the hardware know
|
|
* to allow multicast packets in.
|
|
* Should set mld_mac_filter previously. */
|
|
if (netif->mld_mac_filter != NULL)
|
|
{
|
|
ip6_addr_t ip6_allnodes_ll;
|
|
ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
|
|
netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
|
|
}
|
|
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
|
}
|
|
|
|
/**
|
|
* Returns next buffer for TX.
|
|
* Can wait if no buffer available.
|
|
*/
|
|
static unsigned char *enet_get_tx_buffer(struct ethernetif *ethernetif)
|
|
{
|
|
#if defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0)
|
|
{
|
|
static unsigned char ucBuffer[ENET_FRAME_MAX_FRAMELEN];
|
|
return ucBuffer;
|
|
}
|
|
#elif defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0)
|
|
{
|
|
enet_tx_bd_struct_t *txBuffDesc = get_tx_desc(ethernetif, ethernetif->txIdx);
|
|
#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
|
|
while (1)
|
|
{
|
|
if (ENET_IsTxDescriptorDmaOwn(txBuffDesc))
|
|
{
|
|
xEventGroupWaitBits(ethernetif->enetTransmitAccessEvent, ethernetif->txFlag, pdTRUE, (BaseType_t) false,
|
|
portMAX_DELAY);
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
#else
|
|
{
|
|
uint32_t counter;
|
|
|
|
for (counter = ENET_TIMEOUT; counter != 0U; counter--)
|
|
{
|
|
if (!ENET_IsTxDescriptorDmaOwn(txBuffDesc))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (counter == 0U)
|
|
{
|
|
return (unsigned char *)NULL;
|
|
}
|
|
}
|
|
#endif
|
|
return (unsigned char *)ENET_ALIGN(ethernetif->TxDataBuff + (ethernetif->txIdx * ENET_ALIGN(ENET_TXBUFF_SIZE)));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Sends frame via ENET.
|
|
*/
|
|
static err_t enet_send_frame(struct ethernetif *ethernetif, unsigned char *data, const uint32_t length)
|
|
{
|
|
#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
|
|
{
|
|
status_t result;
|
|
|
|
do
|
|
{
|
|
result = ENET_SendFrame(ethernetif->base, ðernetif->handle, data, length);
|
|
|
|
if (result == kStatus_ENET_TxFrameBusy)
|
|
{
|
|
xEventGroupWaitBits(ethernetif->enetTransmitAccessEvent, ethernetif->txFlag, pdTRUE, (BaseType_t) false,
|
|
portMAX_DELAY);
|
|
}
|
|
|
|
} while (result == kStatus_ENET_TxFrameBusy);
|
|
return ERR_OK;
|
|
}
|
|
#elif defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0)
|
|
{
|
|
uint32_t counter;
|
|
|
|
for (counter = ENET_TIMEOUT; counter != 0U; counter--)
|
|
{
|
|
if (ENET_SendFrame(ethernetif->base, ðernetif->handle, data, length) != kStatus_ENET_TxFrameBusy)
|
|
{
|
|
return ERR_OK;
|
|
}
|
|
}
|
|
|
|
return ERR_TIMEOUT;
|
|
}
|
|
#elif defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0)
|
|
{
|
|
uint32_t tail;
|
|
enet_tx_bd_struct_t *txBuffDesc = get_tx_desc(ethernetif, ethernetif->txIdx);
|
|
|
|
ENET_SetupTxDescriptor(txBuffDesc, data, length, NULL, 0U, length, false, false, kENET_FirstLastFlag, 0U);
|
|
ethernetif->txIdx = (ethernetif->txIdx + 1U) % ENET_TXBD_NUM;
|
|
|
|
/* Update the transmit tail address. */
|
|
if (ethernetif->txIdx == 0U)
|
|
{
|
|
tail = (uint32_t)get_tx_desc(ethernetif, ENET_TXBD_NUM);
|
|
}
|
|
else
|
|
{
|
|
tail = (uint32_t)get_tx_desc(ethernetif, ethernetif->txIdx);
|
|
}
|
|
ENET_UpdateTxDescriptorTail(ethernetif->base, 0U, tail);
|
|
|
|
return ERR_OK;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* This function should do the actual transmission of the packet. The packet is
|
|
* contained in the pbuf that is passed to the function. This pbuf
|
|
* might be chained.
|
|
*
|
|
* @param netif the lwip network interface structure for this ethernetif
|
|
* @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
|
|
* @return ERR_OK if the packet could be sent
|
|
* an err_t value if the packet couldn't be sent
|
|
*
|
|
* @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
|
|
* strange results. You might consider waiting for space in the DMA queue
|
|
* to become available since the stack doesn't retry to send a packet
|
|
* dropped because of memory failure (except for the TCP timers).
|
|
*/
|
|
|
|
static err_t low_level_output(struct netif *netif, struct pbuf *p)
|
|
{
|
|
err_t result;
|
|
struct ethernetif *ethernetif = netif->state;
|
|
struct pbuf *q;
|
|
unsigned char *pucBuffer;
|
|
unsigned char *pucChar;
|
|
|
|
LWIP_ASSERT("Output packet buffer empty", p);
|
|
|
|
pucBuffer = enet_get_tx_buffer(ethernetif);
|
|
if (pucBuffer == NULL)
|
|
{
|
|
return ERR_BUF;
|
|
}
|
|
|
|
/* Initiate transfer. */
|
|
|
|
#if ETH_PAD_SIZE
|
|
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
|
|
#endif
|
|
|
|
if (p->len == p->tot_len)
|
|
{
|
|
#if defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0)
|
|
/* No pbuf chain, don't have to copy -> faster. */
|
|
pucBuffer = (unsigned char *)p->payload;
|
|
#elif defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0)
|
|
/* No pbuf chain, still have to copy as pbuf could be reclaimed early. */
|
|
memcpy(pucBuffer, p->payload, p->len);
|
|
#endif /* FSL_FEATURE_SOC_*_ENET_COUNT */
|
|
}
|
|
else
|
|
{
|
|
/* pbuf chain, copy into contiguous ucBuffer. */
|
|
if (p->tot_len >= ENET_FRAME_MAX_FRAMELEN)
|
|
{
|
|
return ERR_BUF;
|
|
}
|
|
else
|
|
{
|
|
pucChar = pucBuffer;
|
|
|
|
for (q = p; q != NULL; q = q->next)
|
|
{
|
|
/* Send the data from the pbuf to the interface, one pbuf at a
|
|
time. The size of the data in each pbuf is kept in the ->len
|
|
variable. */
|
|
/* send data from(q->payload, q->len); */
|
|
if (q == p)
|
|
{
|
|
memcpy(pucChar, q->payload, q->len);
|
|
pucChar += q->len;
|
|
}
|
|
else
|
|
{
|
|
memcpy(pucChar, q->payload, q->len);
|
|
pucChar += q->len;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Send frame. */
|
|
result = enet_send_frame(ethernetif, pucBuffer, p->tot_len);
|
|
|
|
MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
|
|
if (((u8_t *)p->payload)[0] & 1)
|
|
{
|
|
/* broadcast or multicast packet*/
|
|
MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
|
|
}
|
|
else
|
|
{
|
|
/* unicast packet */
|
|
MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
|
|
}
|
|
/* increase ifoutdiscards or ifouterrors on error */
|
|
|
|
#if ETH_PAD_SIZE
|
|
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
|
|
#endif
|
|
|
|
LINK_STATS_INC(link.xmit);
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Gets the length of received frame (if any).
|
|
*/
|
|
static status_t enet_get_rx_frame_size(struct ethernetif *ethernetif, uint32_t *length)
|
|
{
|
|
#if defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0)
|
|
{
|
|
return ENET_GetRxFrameSize(ðernetif->handle, length);
|
|
}
|
|
#elif defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0)
|
|
#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
|
|
{
|
|
return ENET_GetRxFrameSize(ethernetif->base, ðernetif->handle, length, 0U);
|
|
}
|
|
#else
|
|
{
|
|
uint8_t index = ethernetif->rxIdx;
|
|
enet_rx_bd_struct_t *rxDesc = get_rx_desc(ethernetif, index);
|
|
uint32_t rxControl = ENET_GetRxDescriptor(rxDesc);
|
|
|
|
/* Reset the length to zero. */
|
|
*length = 0;
|
|
|
|
if (rxControl & ENET_RXDESCRIP_WR_OWN_MASK)
|
|
{
|
|
return kStatus_ENET_RxFrameEmpty;
|
|
}
|
|
else
|
|
{
|
|
do
|
|
{
|
|
/* Application owns the buffer descriptor, get the length. */
|
|
if (rxControl & ENET_RXDESCRIP_WR_LD_MASK)
|
|
{
|
|
if (rxControl & ENET_RXDESCRIP_WR_ERRSUM_MASK)
|
|
{
|
|
return kStatus_ENET_RxFrameError;
|
|
}
|
|
else
|
|
{
|
|
*length = rxControl & ENET_RXDESCRIP_WR_PACKETLEN_MASK;
|
|
return kStatus_Success;
|
|
}
|
|
}
|
|
|
|
index = (index + 1U) % ENET_RXBD_NUM;
|
|
rxDesc = get_rx_desc(ethernetif, index);
|
|
rxControl = ENET_GetRxDescriptor(rxDesc);
|
|
} while (index != ethernetif->rxIdx);
|
|
|
|
return kStatus_ENET_RxFrameError;
|
|
}
|
|
}
|
|
#endif
|
|
#endif /* FSL_FEATURE_SOC_*_ENET_COUNT */
|
|
}
|
|
|
|
/**
|
|
* Reads frame from ENET.
|
|
*/
|
|
static void enet_read_frame(struct ethernetif *ethernetif, uint8_t *data, uint32_t length)
|
|
{
|
|
#if defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0)
|
|
{
|
|
ENET_ReadFrame(ethernetif->base, ðernetif->handle, data, length);
|
|
}
|
|
#elif defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0)
|
|
#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
|
|
{
|
|
ENET_ReadFrame(ethernetif->base, ðernetif->handle, data, length, 0U);
|
|
}
|
|
#else
|
|
{
|
|
enet_rx_bd_struct_t *rxDesc;
|
|
uint8_t index = ethernetif->rxIdx;
|
|
uint32_t rxControl;
|
|
bool isLastBuff = false;
|
|
uint32_t len = 0;
|
|
uint32_t offset = 0;
|
|
|
|
if (!data)
|
|
{
|
|
do
|
|
{
|
|
rxDesc = get_rx_desc(ethernetif, ethernetif->rxIdx);
|
|
ethernetif->rxIdx = (ethernetif->rxIdx + 1U) % ENET_RXBD_NUM;
|
|
rxControl = ENET_GetRxDescriptor(rxDesc);
|
|
|
|
/* Update the receive buffer descriptor. */
|
|
ENET_UpdateRxDescriptor(rxDesc, NULL, NULL, false, false);
|
|
|
|
/* Find the last buffer descriptor for the frame. */
|
|
if (rxControl & ENET_RXDESCRIP_WR_LD_MASK)
|
|
{
|
|
break;
|
|
}
|
|
} while (ethernetif->rxIdx != index);
|
|
}
|
|
else
|
|
{
|
|
while (!isLastBuff)
|
|
{
|
|
rxDesc = get_rx_desc(ethernetif, ethernetif->rxIdx);
|
|
ethernetif->rxIdx = (ethernetif->rxIdx + 1U) % ENET_RXBD_NUM;
|
|
rxControl = ENET_GetRxDescriptor(rxDesc);
|
|
|
|
if (rxControl & ENET_RXDESCRIP_WR_LD_MASK)
|
|
{
|
|
/* This is a valid frame. */
|
|
isLastBuff = true;
|
|
if (length == (rxControl & ENET_RXDESCRIP_WR_PACKETLEN_MASK))
|
|
{
|
|
/* Copy the frame to user's buffer. */
|
|
len = (rxControl & ENET_RXDESCRIP_WR_PACKETLEN_MASK) - offset;
|
|
if (len > ENET_ALIGN(ENET_RXBUFF_SIZE))
|
|
{
|
|
memcpy(data + offset, (void *)rxDesc->buff1Addr, ENET_ALIGN(ENET_RXBUFF_SIZE));
|
|
offset += ENET_ALIGN(ENET_RXBUFF_SIZE);
|
|
memcpy(data + offset, (void *)rxDesc->buff2Addr, len - ENET_ALIGN(ENET_RXBUFF_SIZE));
|
|
}
|
|
else
|
|
{
|
|
memcpy(data + offset, (void *)rxDesc->buff1Addr, len);
|
|
}
|
|
}
|
|
|
|
/* Update the receive buffer descriptor. */
|
|
ENET_UpdateRxDescriptor(rxDesc, NULL, NULL, false, false);
|
|
}
|
|
else
|
|
{
|
|
/* Store a frame on several buffer descriptors. */
|
|
isLastBuff = false;
|
|
/* Length check. */
|
|
if (offset >= length)
|
|
{
|
|
/* Updates the receive buffer descriptors. */
|
|
ENET_UpdateRxDescriptor(rxDesc, NULL, NULL, false, false);
|
|
break;
|
|
}
|
|
|
|
memcpy(data + offset, (void *)rxDesc->buff1Addr, ENET_ALIGN(ENET_RXBUFF_SIZE));
|
|
offset += ENET_ALIGN(ENET_RXBUFF_SIZE);
|
|
|
|
/* Update the receive buffer descriptor. */
|
|
ENET_UpdateRxDescriptor(rxDesc, NULL, NULL, false, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
ENET_UpdateRxDescriptorTail(ethernetif->base, 0U, (uint32_t)get_rx_desc(ethernetif, ENET_RXBD_NUM));
|
|
}
|
|
#endif /* USE_RTOS */
|
|
#endif /* FSL_FEATURE_SOC_*_ENET_COUNT */
|
|
}
|
|
|
|
/**
|
|
* Should allocate a pbuf and transfer the bytes of the incoming
|
|
* packet from the interface into the pbuf.
|
|
*
|
|
* @param netif the lwip network interface structure for this ethernetif
|
|
* @return a pbuf filled with the received packet (including MAC header)
|
|
* NULL on memory error
|
|
*/
|
|
static struct pbuf *low_level_input(struct netif *netif)
|
|
{
|
|
struct ethernetif *ethernetif = netif->state;
|
|
struct pbuf *p = NULL;
|
|
struct pbuf *q;
|
|
uint32_t len;
|
|
status_t status;
|
|
|
|
/* Obtain the size of the packet and put it into the "len"
|
|
variable. */
|
|
status = enet_get_rx_frame_size(ethernetif, &len);
|
|
|
|
if (kStatus_ENET_RxFrameEmpty != status)
|
|
{
|
|
/* Call enet_read_frame when there is a received frame. */
|
|
if (len != 0)
|
|
{
|
|
#if ETH_PAD_SIZE
|
|
len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
|
|
#endif
|
|
|
|
/* We allocate a pbuf chain of pbufs from the pool. */
|
|
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
|
|
|
|
if (p != NULL)
|
|
{
|
|
#if ETH_PAD_SIZE
|
|
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
|
|
#endif
|
|
if (p->next == 0) /* One-chain buffer.*/
|
|
{
|
|
enet_read_frame(ethernetif, p->payload, p->len);
|
|
}
|
|
else /* Multi-chain buffer.*/
|
|
{
|
|
uint8_t data_tmp[ENET_FRAME_MAX_FRAMELEN];
|
|
uint32_t data_tmp_len = 0;
|
|
|
|
enet_read_frame(ethernetif, data_tmp, p->tot_len);
|
|
|
|
/* We iterate over the pbuf chain until we have read the entire
|
|
* packet into the pbuf. */
|
|
for (q = p; (q != NULL) && ((data_tmp_len + q->len) <= sizeof(data_tmp)); q = q->next)
|
|
{
|
|
/* Read enough bytes to fill this pbuf in the chain. The
|
|
* available data in the pbuf is given by the q->len
|
|
* variable. */
|
|
memcpy(q->payload, &data_tmp[data_tmp_len], q->len);
|
|
data_tmp_len += q->len;
|
|
}
|
|
}
|
|
|
|
MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
|
|
if (((u8_t *)p->payload)[0] & 1)
|
|
{
|
|
/* broadcast or multicast packet*/
|
|
MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);
|
|
}
|
|
else
|
|
{
|
|
/* unicast packet*/
|
|
MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
|
|
}
|
|
#if ETH_PAD_SIZE
|
|
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
|
|
#endif
|
|
|
|
LINK_STATS_INC(link.recv);
|
|
}
|
|
else
|
|
{
|
|
/* drop packet*/
|
|
enet_read_frame(ethernetif, NULL, 0U);
|
|
|
|
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: Fail to allocate new memory space\n"));
|
|
|
|
LINK_STATS_INC(link.memerr);
|
|
LINK_STATS_INC(link.drop);
|
|
MIB2_STATS_NETIF_INC(netif, ifindiscards);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Update the received buffer when error happened. */
|
|
if (status == kStatus_ENET_RxFrameError)
|
|
{
|
|
#if 0 && defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0) /* Error statisctics */
|
|
enet_data_error_stats_t eErrStatic;
|
|
/* Get the error information of the received g_frame. */
|
|
ENET_GetRxErrBeforeReadFrame(ðernetif->handle, &eErrStatic);
|
|
#endif
|
|
|
|
/* Update the receive buffer. */
|
|
enet_read_frame(ethernetif, NULL, 0U);
|
|
|
|
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: RxFrameError\n"));
|
|
|
|
LINK_STATS_INC(link.drop);
|
|
MIB2_STATS_NETIF_INC(netif, ifindiscards);
|
|
}
|
|
}
|
|
}
|
|
return p;
|
|
}
|
|
|
|
/**
|
|
* This function should be called when a packet is ready to be read
|
|
* from the interface. It uses the function low_level_input() that
|
|
* should handle the actual reception of bytes from the network
|
|
* interface. Then the type of the received packet is determined and
|
|
* the appropriate input function is called.
|
|
*
|
|
* @param netif the lwip network interface structure for this ethernetif
|
|
*/
|
|
void ethernetif_input(struct netif *netif)
|
|
{
|
|
struct pbuf *p;
|
|
|
|
LWIP_ASSERT("netif != NULL", (netif != NULL));
|
|
|
|
/* move received packet into a new pbuf */
|
|
while ((p = low_level_input(netif)) != NULL)
|
|
{
|
|
/* pass all packets to ethernet_input, which decides what packets it supports */
|
|
if (netif->input(p, netif) != ERR_OK)
|
|
{
|
|
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
|
|
pbuf_free(p);
|
|
p = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Should be called at the beginning of the program to set up the
|
|
* network interface. It calls the function low_level_init() to do the
|
|
* actual setup of the hardware.
|
|
*
|
|
* This function should be passed as a parameter to netif_add().
|
|
*
|
|
* @param netif the lwip network interface structure for this ethernetif
|
|
* @return ERR_OK if the loopif is initialized
|
|
* ERR_MEM if private data couldn't be allocated
|
|
* any other err_t on error
|
|
*/
|
|
err_t ethernetif_init(struct netif *netif)
|
|
{
|
|
LWIP_ASSERT("netif != NULL", (netif != NULL));
|
|
|
|
#if LWIP_NETIF_HOSTNAME
|
|
/* Initialize interface hostname */
|
|
netif->hostname = "lwip";
|
|
#endif /* LWIP_NETIF_HOSTNAME */
|
|
|
|
/*
|
|
* Initialize the snmp variables and counters inside the struct netif.
|
|
* The last argument should be replaced with your link speed, in units
|
|
* of bits per second.
|
|
*/
|
|
MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
|
|
|
|
netif->state = ðernetif_0;
|
|
netif->name[0] = IFNAME0;
|
|
netif->name[1] = IFNAME1;
|
|
/* We directly use etharp_output() here to save a function call.
|
|
* You can instead declare your own function an call etharp_output()
|
|
* from it if you have to do some checks before sending (e.g. if link
|
|
* is available...) */
|
|
#if LWIP_IPV4
|
|
netif->output = etharp_output;
|
|
#endif
|
|
#if LWIP_IPV6
|
|
netif->output_ip6 = ethip6_output;
|
|
#endif /* LWIP_IPV6 */
|
|
netif->linkoutput = low_level_output;
|
|
|
|
#if LWIP_IPV4 && LWIP_IGMP
|
|
netif_set_igmp_mac_filter(netif, ethernetif_igmp_mac_filter);
|
|
netif->flags |= NETIF_FLAG_IGMP;
|
|
#endif
|
|
#if LWIP_IPV6 && LWIP_IPV6_MLD
|
|
netif_set_mld_mac_filter(netif, ethernetif_mld_mac_filter);
|
|
netif->flags |= NETIF_FLAG_MLD6;
|
|
#endif
|
|
|
|
/* Init ethernetif parameters.*/
|
|
ethernetif_0.base = ENET;
|
|
ethernetif_0.phyAddr = ENET_PHY_ADDRESS;
|
|
|
|
/* initialize the hardware */
|
|
low_level_init(netif);
|
|
|
|
return ERR_OK;
|
|
}
|