#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" /** Initialization function that should be passed to netif_add */ err_t LWIP_driver_init(struct netif *netif) { localNetif = netif; NETIF_INIT_SNMP(netif,snmp_ifType_ethernet_csmacd, 800); netif->name[0] = IFNAME0; netif->name[1] = IFNAME1; 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; } u32_t sys_now(void) { return *timestamp_current; } /** Called when a raw packet is ready to be transmitted. */ 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(p->tot_len, p->payload); } #if ETH_PAD_SIZE pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ #endif LINK_STATS_INC(link.xmit); return ERR_OK; } /** Called when a packet is received */ static void LWIP_driver_input(struct netif *netif) { struct eth_hdr *ethhdr; struct pbuf *p; /* move received packet into a new pbuf */ p = 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; } } static struct pbuf *low_level_input(struct netif *netif) { struct pbuf *p; u16_t len=netif->mtu; /* We allocate a pbuf chain of pbufs from the pool. */ p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); if (p != NULL) { KSZ8851SNL_receive(p->payload, &(p->len)); LINK_STATS_INC(link.recv); } else { //TODO drop packet(); LINK_STATS_INC(link.memerr); LINK_STATS_INC(link.drop); } return p; } /** Timestamp capabilities */ void LWIP_driver_timestamp_engine(void) { if (abs(timestamp_ETH_ARP - *timestamp_current) >= LWIP_ETH_ARP_INTERVAL) { etharp_tmr(); timestamp_ETH_ARP = *timestamp_current; } if (abs(timestamp_ETH_TCP - *timestamp_current) >= LWIP_ETH_TCP_INTERVAL) { tcp_tmr(); timestamp_ETH_TCP = *timestamp_current; } //TODO implement for the others if (abs(timestamp_ETH_TCP - *timestamp_current) >= LWIP_ETH_TCP_INTERVAL) { igmp_tmr(); timestamp_ETH_TCP = *timestamp_current; } } /** LWIP main loop */ void LWIP_loop(struct netif *netif, uint32_t *global_timestamp) { timestamp_current=global_timestamp; while(1) { LWIP_driver_timestamp_engine(); LWIP_driver_input(netif); } }