#include "lwip_driver.h" #include "efm32.h" #include "em_cmu.h" #include "ksz8851snl_driver.h" #include "lwip/def.h" #include "lwip/mem.h" #include "lwip/pbuf.h" #include "lwip/sys.h" #include #include #include #include "netif/etharp.h" #include "netif/ppp_oe.h" //TODO remove when finished implementing #include "ping.h" /***************************************************************************//** * @addtogroup Drivers * @{ ******************************************************************************/ void LWIP_driver_timestamp_engine(void); static struct pbuf* LWIP_low_level_input(struct netif *netif); /****************************************************************************** * @brief Initialize lwIP internal variables and structures. * It should be passed to netif_add. * * @param netif * the used network interface * * @return * error status *****************************************************************************/ err_t LWIP_driver_init(struct netif *netif) { #ifdef PING_BEHAVIOUR ping_init(); #endif //PING_BEHAVIOUR localNetif = netif; NETIF_INIT_SNMP(netif,snmp_ifType_ethernet_csmacd, 104857600);/** 100 MBits/sec */ netif->name[0] = IFNAME0; netif->name[1] = IFNAME1; /** set the output methods to be used */ netif->output = etharp_output; netif->linkoutput = LWIP_driver_output; /** set the HW address length */ netif->hwaddr_len = ETH_MAC_ADDR_LEN; /** set the HW address */ KSZ8851SNL_getMACAddress(netif->hwaddr); /** set the maximum transfer unit */ netif->mtu = 1500; /** Set the flags according to device capabilities */ netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_LINK_UP | NETIF_FLAG_ETHARP ; /** initialize the timers */ timestamp_ETH_ARP = *timestamp_current; timestamp_ETH_TCP = *timestamp_current; /** initialize the hardware */ KSZ8851SNL_init(); return ERR_OK; } /****************************************************************************** * @brief Returns the current timestamp. * * @return * current timestamp value *****************************************************************************/ u32_t sys_now(void) { return *timestamp_current; } /****************************************************************************** * @brief Transmit a raw packet. * * @param netif * the used network interface * @param p * the raw packet to be sent * * @return * error status *****************************************************************************/ err_t LWIP_driver_output(struct netif *netif, struct pbuf *p) { struct pbuf *q; #if ETH_PAD_SIZE pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ #endif for(q = p; q != NULL; q = q->next) { KSZ8851SNL_send(q->tot_len, q->payload); } #if ETH_PAD_SIZE pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ #endif LINK_STATS_INC(link.xmit); return ERR_OK; } /****************************************************************************** * @brief Pass the received raw packet to lwIP, using LWIP_low_level_input() to * handle the actual receival of data from the ethernet controller, * to the appropriate handle from lwIP * * @param netif * the used network interface *****************************************************************************/ void LWIP_driver_input(struct netif *netif) { struct eth_hdr *ethhdr; struct pbuf *p; /* move received packet into a new pbuf */ p = LWIP_low_level_input(netif); /** no packet could be read, silently ignore this */ if (p == NULL) return; /* points to packet payload, which starts with an Ethernet header */ ethhdr = p->payload; switch (htons(ethhdr->type)) { /* IP or ARP packet? */ case ETHTYPE_IP: case ETHTYPE_ARP: #if PPPOE_SUPPORT /* PPPoE packet? */ case ETHTYPE_PPPOEDISC: case ETHTYPE_PPPOE: #endif /* PPPOE_SUPPORT */ /* full packet send to tcpip_thread to process */ if (netif->input(p, netif)!=ERR_OK) { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); pbuf_free(p); p = NULL; } break; default: pbuf_free(p); p = NULL; break; } } /****************************************************************************** * @brief Tries to allocate a pbuf and transfers the data received from the * ethernet controller into the pbuf * * @return * the filled pbuf with the received data or NULL otherwise *****************************************************************************/ static struct pbuf *LWIP_low_level_input(struct netif *netif) { struct pbuf *p; uint16_t len=netif->mtu+14;//TODO get the actual size from 0x7E when the INT are used // uint16_t len=KSZ8851SNL_curr_frame_size()+14; /* We allocate a pbuf chain of pbufs from the pool. */ p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); if (p != NULL) { if (KSZ8851SNL_receive(p->payload, &p->len) != 0) { LINK_STATS_INC(link.recv); } else { pbuf_free(p); p = NULL; } } else { LINK_STATS_INC(link.memerr); LINK_STATS_INC(link.drop); } return p; } /****************************************************************************** * @brief Controls the timestamps and timeout calls *****************************************************************************/ /** Timestamp capabilities */ void LWIP_driver_timestamp_engine(void) { //TODO revert files // if (abs(timestamp_ETH_ARP - *timestamp_current) >= ARP_TMR_INTERVAL ) { // timestamp_ETH_ARP = *timestamp_current; // etharp_tmr(); // } if (abs(timestamp_ETH_ARP - *timestamp_current) >= 5000 ) { #ifdef PING_BEHAVIOUR ping_send_now(); #endif //PING_BEHAVIOUR } if (abs(timestamp_ETH_TCP - *timestamp_current) >= TCP_TMR_INTERVAL) { tcp_tmr(); timestamp_ETH_TCP = *timestamp_current; } // //#if LWIP_IGMP // if (abs(timestamp_ETH_IGMP - *timestamp_current) >= IGMP_TMR_INTERVAL) { // igmp_tmr(); // timestamp_ETH_IGMP = *timestamp_current; // } //#endif //LWIP_IGMP // //#if DNS_IGMP // if (abs(timestamp_ETH_DNS - *timestamp_current) >= DNS_TMR_INTERVAL) { // dns_tmr(); // timestamp_ETH_DNS = *timestamp_current; // } //#endif //DNS_IGMP // //#if dhcp_coarse_tmr // if (abs(timestamp_ETH_TCP - *timestamp_current) >= DNS_TMR_INTERVAL) { // dhcp_coarse_tmr(); // timestamp_ETH_TCP = *timestamp_current; // } //#endif //DNS_IGMP // //#if DNS_IGMP // if (abs(timestamp_ETH_TCP - *timestamp_current) >= DNS_TMR_INTERVAL) { // dhcp_fine_tmr(); // timestamp_ETH_TCP = *timestamp_current; // } //#endif //DNS_IGMP // //#if DNS_IGMP // if (abs(timestamp_ETH_TCP - *timestamp_current) >= DNS_TMR_INTERVAL) { // ip_reass_tmr(); // timestamp_ETH_TCP = *timestamp_current; // } //#endif //DNS_IGMP // //#if DNS_IGMP // if (abs(timestamp_ETH_TCP - *timestamp_current) >= DNS_TMR_INTERVAL) { // autoip_tmr(); // timestamp_ETH_TCP = *timestamp_current; // } //#endif //DNS_IGMP } /****************************************************************************** * @brief lwIP main loop that calls the appropriate methods: * timestamp restarts * check for new data * * @param netif * the used network interface * @param global_timestamp * a reference to the main module current tick number *****************************************************************************/ /** LWIP main loop */ void LWIP_loop(struct netif *netif, uint32_t *global_timestamp) { timestamp_current=global_timestamp; while(1) { LWIP_driver_timestamp_engine(); } } /** @} (end group Drivers) */