Index: io/eth/current//include/eth_drv.h =================================================================== RCS file: /cvs/ecos/ecos/packages/io/eth/current/include/eth_drv.h,v retrieving revision 1.8 diff -u -r1.8 eth_drv.h --- io/eth/current//include/eth_drv.h 13 Aug 2002 15:55:53 -0000 1.8 +++ io/eth/current//include/eth_drv.h 1 Mar 2003 10:36:59 -0000 @@ -81,6 +81,9 @@ #else // !CYGPKG_NET #include #endif +#ifdef CYGPKG_NET_LWIP +#include "lwip/netif.h" +#endif struct eth_drv_sg { CYG_ADDRESS buf; @@ -141,6 +144,9 @@ #ifndef CYGPKG_NET struct arpcom { +#ifdef CYGPKG_NET_LWIP + struct netif ac_if; +#endif unsigned char esa[6]; }; #endif Index: io/eth/current//src/lwip/eth_drv.c =================================================================== RCS file: /cvs/ecos/ecos/packages/io/eth/current/src/lwip/eth_drv.c,v retrieving revision 1.2 diff -u -r1.2 eth_drv.c --- io/eth/current//src/lwip/eth_drv.c 23 May 2002 23:06:02 -0000 1.2 +++ io/eth/current//src/lwip/eth_drv.c 1 Mar 2003 10:37:01 -0000 @@ -69,113 +69,149 @@ #include #include +#include "lwip/opt.h" +#include "lwip/ip.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" + +#include "netif/etharp.h" + + + // Define table boundaries -CYG_HAL_TABLE_BEGIN( __NETDEVTAB__, netdev ); -CYG_HAL_TABLE_END( __NETDEVTAB_END__, netdev ); +CYG_HAL_TABLE_BEGIN(__NETDEVTAB__, netdev); +CYG_HAL_TABLE_END(__NETDEVTAB_END__, netdev); // Interfaces exported to drivers static void eth_drv_init(struct eth_drv_sc *sc, unsigned char *enaddr); static void eth_drv_recv(struct eth_drv_sc *sc, int total_len); -static void eth_drv_tx_done(struct eth_drv_sc *sc, CYG_ADDRWORD key, int status); +static void eth_drv_tx_done(struct eth_drv_sc *sc, CYG_ADDRWORD key, + int status); -struct eth_drv_funs eth_drv_funs = {eth_drv_init, eth_drv_recv, eth_drv_tx_done}; +struct eth_drv_funs eth_drv_funs = + { eth_drv_init, eth_drv_recv, eth_drv_tx_done }; -struct eth_drv_sc *__local_enet_sc; - -//this is where lwIP keeps hw address -unsigned char *lwip_hw_addr; cyg_sem_t delivery; -//lwIP callback to pass received data to -typedef void (*lwip_input_t)(char *,int); -static lwip_input_t lwip_input; -void input_thread(void * arg) -{ - struct eth_drv_sc * sc; - //sc = (struct eth_drv_sc *)arg; - sc = __local_enet_sc; - for(;;) { - cyg_semaphore_wait(&delivery); - (sc->funs->deliver)(sc); - } +//DSR called from the low level driver.Signals the input_thread +void +eth_drv_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) +{ + struct eth_drv_sc *sc = (struct eth_drv_sc *) data; + sc->state |= ETH_DRV_NEEDS_DELIVERY; + cyg_semaphore_post(&delivery); +} + +//Input thread signalled by DSR calls deliver() on low level drivers +static void +input_thread(void *arg) +{ + cyg_netdevtab_entry_t *t; + + for (;;) { + cyg_semaphore_wait(&delivery); + + for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++) { + struct eth_drv_sc *sc = (struct eth_drv_sc *)t->device_instance; + if (sc->state & ETH_DRV_NEEDS_DELIVERY) { + sc->state &= ~ETH_DRV_NEEDS_DELIVERY; + (sc->funs->deliver) (sc); + } + } + } } -void -eth_drv_dsr(cyg_vector_t vector, - cyg_ucount32 count, - cyg_addrword_t data) +// Initialize all network devices +static void +init_hw_drivers(void) { - // struct eth_drv_sc *sc = (struct eth_drv_sc *)data; - // sc->state |= ETH_DRV_NEEDS_DELIVERY; - cyg_semaphore_post(&delivery); + cyg_netdevtab_entry_t *t; + + for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++) { + if (t->init(t)) { + t->status = CYG_NETDEVTAB_STATUS_AVAIL; + } else { + // What to do if device init fails? + t->status = 0; // Device not [currently] available + } + } } +static void +arp_timer(void *arg) +{ + etharp_tmr(); + sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler) arp_timer, NULL); +} -//Called from lwIP init code to init the hw devices -//and pass the lwip input callback address -void init_hw_drivers(unsigned char *hw_addr,lwip_input_t input) +void +ecosglue_init(void) { - cyg_netdevtab_entry_t *t; - - lwip_hw_addr = hw_addr; - lwip_input = input; - -// Initialize all network devices - for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++) { - if (t->init(t)) { - t->status = CYG_NETDEVTAB_STATUS_AVAIL; - } else { - // What to do if device init fails? - t->status = 0; // Device not [currently] available - } - } + init_hw_drivers(); + sys_thread_new(input_thread, (void*)0); + etharp_init(); + sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler) arp_timer, NULL); } -// +extern void lwip_set_addr(struct netif *); + +err_t +ecosif_init(struct netif *netif); + + + // This function is called during system initialization to register a // network interface with the system. -// static void eth_drv_init(struct eth_drv_sc *sc, unsigned char *enaddr) { - // enaddr == 0 -> hardware init was incomplete (no ESA) - if (enaddr != 0) { - // Set up hardware address - memcpy(&sc->sc_arpcom.esa, enaddr, ETHER_ADDR_LEN); - memcpy(lwip_hw_addr, enaddr, ETHER_ADDR_LEN); - __local_enet_sc = sc; - // Perform any hardware initialization - (sc->funs->start)(sc, (unsigned char *)&sc->sc_arpcom.esa, 0); - } - cyg_semaphore_init(&delivery,0); + struct netif *netif = &sc->sc_arpcom.ac_if; + + netif->state = sc; + ecosif_init(netif); + + // enaddr == 0 -> hardware init was incomplete (no ESA) + if (enaddr != 0) { + // Set up hardware address + memcpy(&sc->sc_arpcom.esa, enaddr, ETHER_ADDR_LEN); + memcpy(netif->hwaddr, enaddr, ETHER_ADDR_LEN); + // Perform any hardware initialization + (sc->funs->start) (sc, (unsigned char *) &sc->sc_arpcom.esa, 0); + } + +// cyg_semaphore_init(&delivery, 0); } // // Send a packet of data to the hardware // -cyg_sem_t packet_sent; +cyg_sem_t packet_sent; -void -eth_drv_write(char *eth_hdr, char *buf, int len) +static void +eth_drv_send(struct netif *netif, struct pbuf *p) { - struct eth_drv_sg sg_list[MAX_ETH_DRV_SG]; - struct eth_drv_sc *sc = __local_enet_sc; - int sg_len = 1; + struct eth_drv_sg sg_list[MAX_ETH_DRV_SG]; + struct eth_drv_sc *sc = netif->state; + int sg_len = 0; + struct pbuf *q; + + while (!(sc->funs->can_send) (sc)) { + cyg_thread_delay(1); + } + + for (q = p; q != NULL; q = q->next) { + sg_list[sg_len].buf = (CYG_ADDRESS) q->payload; + sg_list[sg_len++].len = q->len; + } + + (sc->funs->send) (sc, sg_list, sg_len, p->tot_len, + (CYG_ADDRWORD) & packet_sent); - while (!(sc->funs->can_send)(sc)) { - cyg_thread_delay(1); - } - - sg_list[0].buf = (CYG_ADDRESS)buf; - sg_list[0].len = len; -// cyg_semaphore_init(&packet_sent,0); - (sc->funs->send)(sc, sg_list, sg_len, len, (CYG_ADDRWORD)&packet_sent); - -// cyg_semaphore_wait(&packet_sent); } // @@ -185,15 +221,16 @@ static void eth_drv_tx_done(struct eth_drv_sc *sc, CYG_ADDRWORD key, int status) { -#if 0 - CYGARC_HAL_SAVE_GP(); - if (key == (CYG_ADDRWORD)&packet_sent) { -// cyg_semaphore_post((cyg_sem_t *)&packet_sent); - } - CYGARC_HAL_RESTORE_GP(); -#endif +#if 0 + CYGARC_HAL_SAVE_GP(); + if (key == (CYG_ADDRWORD) & packet_sent) { +// cyg_semaphore_post((cyg_sem_t *)&packet_sent); + } + CYGARC_HAL_RESTORE_GP(); +#endif } +static void ecosif_input(struct netif *netif, struct pbuf* pbuf); #define MAX_ETH_MSG 1540 // @@ -204,23 +241,129 @@ static void eth_drv_recv(struct eth_drv_sc *sc, int total_len) { - struct eth_drv_sg sg_list[MAX_ETH_DRV_SG]; - int sg_len = 0; - unsigned char buf[MAX_ETH_MSG]; - CYGARC_HAL_SAVE_GP(); + struct eth_drv_sg sg_list[MAX_ETH_DRV_SG]; + struct netif *netif = &sc->sc_arpcom.ac_if; + + struct pbuf *p, *q; + + int sg_len = 0; + CYGARC_HAL_SAVE_GP(); + + if ((total_len > MAX_ETH_MSG) || (total_len < 0)) { + total_len = MAX_ETH_MSG; + } + + p = pbuf_alloc(PBUF_RAW, total_len, PBUF_POOL); + + if (p == NULL) { + diag_printf("ecosif_input: low_level_input returned NULL\n"); + return; + } + + for (q = p; q != NULL; q = q->next) { + sg_list[sg_len].buf = (CYG_ADDRESS) q->payload; + sg_list[sg_len++].len = q->len; + } + (sc->funs->recv) (sc, sg_list, sg_len); + ecosif_input(netif, p); + CYGARC_HAL_RESTORE_GP(); +} - if ((total_len > MAX_ETH_MSG) || (total_len < 0)) { - total_len = MAX_ETH_MSG; - } - sg_list[0].buf = (CYG_ADDRESS)buf; - sg_list[0].len = total_len; - sg_len = 1; +#define IFNAME0 'e' +#define IFNAME1 't' - (sc->funs->recv)(sc, sg_list, sg_len); - (lwip_input)((char*)sg_list[0].buf,total_len); - CYGARC_HAL_RESTORE_GP(); + + +/* + * low_level_output(): + * + * 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.We pass the data down to the eCos hw independent + * ethernet driver + */ + +static err_t +low_level_output(struct netif *netif, struct pbuf *p) +{ + /* signal that packet should be sent(); */ + eth_drv_send(netif, p); + return ERR_OK; +} + +/* + * ecosif_output(): + * + * This function is called by the TCP/IP stack when an IP packet + * should be sent. It calls the function called low_level_output() to + * do the actual transmission of the packet. + * + */ +static err_t +ecosif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr) +{ + + p = etharp_output(netif, ipaddr, p); + if (p) { + low_level_output(netif, p); + p = NULL; + } + return ERR_OK; } -// EOF src/lwip/eth_drv.c + +/* + * ecosif_input(): + * This function is called when the eCos hw independent driver + * has some data to pass up to lwIP.It does it through ecosif_input. + */ +static void +ecosif_input(struct netif *netif, struct pbuf *p) +{ + struct eth_drv_sc *sc; + struct eth_hdr *ethhdr; + struct pbuf *q; + + sc = netif->state; + /* We allocate a pbuf chain of pbufs from the pool. */ + ethhdr = p->payload; + + q = NULL; + + switch (htons(ethhdr->type)) { + case ETHTYPE_IP: + DEBUGF(0, ("ecosif_input: IP packet\n")); + q = etharp_ip_input(netif, p); + pbuf_header(p, -14); + netif->input(p, netif); + break; + case ETHTYPE_ARP: + DEBUGF(0, ("ecosif_input: ARP packet\n")); + q = etharp_arp_input(netif, (struct eth_addr *) &sc->sc_arpcom.esa, p); + break; + default: + pbuf_free(p); + break; + } + + if (q != NULL) { + DEBUGF(0, ("ecosif_input: Sending ARP reply\n")); + low_level_output(netif, q); + pbuf_free(q); + } +} + +err_t +ecosif_init(struct netif *netif) +{ + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + netif->hwaddr_len = 6; + netif->output = ecosif_output; + netif->linkoutput = low_level_output; + netif->mtu = 1500; + lwip_set_addr(netif); + return ERR_OK; +}