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.9 diff -u -r1.9 eth_drv.h --- io/eth//current/include/eth_drv.h 11 Mar 2003 15:41:12 -0000 1.9 +++ io/eth//current/include/eth_drv.h 21 Mar 2003 16:30:52 -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/README =================================================================== RCS file: /cvs/ecos/ecos/packages/io/eth/current/src/lwip/README,v retrieving revision 1.1 diff -u -r1.1 README --- io/eth//current/src/lwip/README 20 May 2002 22:24:21 -0000 1.1 +++ io/eth//current/src/lwip/README 21 Mar 2003 16:30:52 -0000 @@ -1,10 +1,2 @@ An EPK of lwip is available from http://humans.iv.ro/jani which has the most up-to-date package (at least until it all gets integrated). - -It has just been tested on another ARM similar to the EB40 with CS89000 -and it works there too (that board has 128K of RAM). - -Alternatively, lw.diff is the diff against the lwip-0.5.3 tree. It contains -eCos support + an eCos project sample based on unixsim. Look at -lwip-0.5.3/proj/ecos to see how to use it. Modify the Makefile to suit -your needs and to reflect your eCos project dir. 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 21 Mar 2003 16:30:53 -0000 @@ -47,7 +47,6 @@ // Description: Based on the standalone driver for RedBoot. // // TODO: -// support more than 1 lowlevel device // play nice with RedBoot too // //####DESCRIPTIONEND#### @@ -69,113 +68,92 @@ #include #include -// Define table boundaries -CYG_HAL_TABLE_BEGIN( __NETDEVTAB__, netdev ); -CYG_HAL_TABLE_END( __NETDEVTAB_END__, netdev ); +#include "lwip/opt.h" +#include "lwip/ip.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" + +#include "netif/etharp.h" + + + // 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); - -struct eth_drv_funs eth_drv_funs = {eth_drv_init, eth_drv_recv, eth_drv_tx_done}; +static void eth_drv_tx_done(struct eth_drv_sc *sc, CYG_ADDRWORD key, + int status); -struct eth_drv_sc *__local_enet_sc; +struct eth_drv_funs eth_drv_funs = + { eth_drv_init, eth_drv_recv, eth_drv_tx_done }; -//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) +extern void lwip_dsr_stuff(void); +//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; - //sc = (struct eth_drv_sc *)arg; - sc = __local_enet_sc; - for(;;) { - cyg_semaphore_wait(&delivery); - (sc->funs->deliver)(sc); - } - + struct eth_drv_sc *sc = (struct eth_drv_sc *) data; + sc->state |= ETH_DRV_NEEDS_DELIVERY; + lwip_dsr_stuff(); } -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); -} +extern void lwip_set_addr(struct netif *); -//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) -{ - 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 - } - } -} +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; - - 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); + 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); + } // @@ -185,15 +163,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 +183,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; - if ((total_len > MAX_ETH_MSG) || (total_len < 0)) { - total_len = MAX_ETH_MSG; - } + int sg_len = 0; + CYGARC_HAL_SAVE_GP(); - sg_list[0].buf = (CYG_ADDRESS)buf; - sg_list[0].len = total_len; - sg_len = 1; + 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(); +} + + +#define IFNAME0 'e' +#define IFNAME1 't' + + + +/* + * 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; +} - (sc->funs->recv)(sc, sg_list, sg_len); - (lwip_input)((char*)sg_list[0].buf,total_len); - CYGARC_HAL_RESTORE_GP(); +/* + * 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; +}