diff --git a/ports/ecos/README b/ports/ecos/README index 5f24987..b1a1e5a 100644 --- a/ports/ecos/README +++ b/ports/ecos/README @@ -1,5 +1,7 @@ This part of the lwip-contrib section is the ecos glue +Check out latest ecos or beta 2 if available and apply ioeth.diff to packages/io/eth + You must have the current lwip sources checked out and the scripts here will hopefully generate a correct EPK suitable for use with ecos. diff --git a/ports/ecos/ioeth.diff b/ports/ecos/ioeth.diff new file mode 100644 index 0000000..73a03d4 --- /dev/null +++ b/ports/ecos/ioeth.diff @@ -0,0 +1,424 @@ +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; ++}