#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 "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->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 */ //err_t LWIP_driver_input(struct pbuf *pbuf, struct netif *netif) //{ // uint16_t length; // //TODO improve this // uint8_t payload[1500]; // KSZ8851SNL_receive(payload, &length); // struct pbuf *p = pbuf_alloc(PBUF_RAW, length, PBUF_POOL); // p->len=length; // p->tot_len+=length; // for (int i=0;ipayload)[i] = (uint8_t)payload[i]; // } // // ethernet_input(p, netif); // return ERR_OK; //} 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=100; //#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) { 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; } } /** 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(localNetif);//blocking call for the moment } }