From 4a9967816de45858b8afabd650e8122c7fc0c8b8 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sat, 9 Apr 2011 21:16:21 -0700 Subject: [PATCH] pxe: hook up the interrupt routine and the lwip receive routine Hook up the interrupt routine to the lwip receive routine; this should be able to receive packets as written. Signed-off-by: Eric W. Biederman --- core/fs/pxe/isr.c | 53 ++++++++++++++++++++++++ core/fs/pxe/pxe.c | 3 ++ core/lwip/src/netif/undiif.c | 98 ++++++++++++++++++++++++-------------------- 3 files changed, 110 insertions(+), 44 deletions(-) diff --git a/core/fs/pxe/isr.c b/core/fs/pxe/isr.c index ae5fab7..882f41f 100644 --- a/core/fs/pxe/isr.c +++ b/core/fs/pxe/isr.c @@ -7,6 +7,8 @@ #include "core.h" #include "thread.h" +#include "pxe.h" +#include extern uint8_t pxe_irq_pending; static DECLARE_INIT_SEMAPHORE(pxe_receive_thread_sem, 0); @@ -34,8 +36,59 @@ static void pm_return(void) __schedule(); } +void undiif_input(t_PXENV_UNDI_ISR *); + +static void pxe_receive_thread(void *dummy) +{ + static __lowmem t_PXENV_UNDI_ISR isr; + uint16_t func; + bool done; + + (void)dummy; + + for (;;) { + sem_down(&pxe_receive_thread_sem, 0); + func = PXENV_UNDI_ISR_IN_PROCESS; /* First time */ + + done = false; + while (!done) { + memset(&isr, 0, sizeof isr); + isr.FuncFlag = func; + func = PXENV_UNDI_ISR_IN_GET_NEXT; /* Next time */ + + pxe_call(PXENV_UNDI_ISR, &isr); + + switch (isr.FuncFlag) { + case PXENV_UNDI_ISR_OUT_DONE: + done = true; + break; + + case PXENV_UNDI_ISR_OUT_TRANSMIT: + /* Transmit complete - nothing for us to do */ + break; + + case PXENV_UNDI_ISR_OUT_RECEIVE: + undiif_input(&isr); + break; + + case PXENV_UNDI_ISR_OUT_BUSY: + /* ISR busy, this should not happen */ + done = true; + break; + + default: + /* Invalid return code, this should not happen */ + done = true; + break; + } + } + } +} + + void pxe_init_isr(void) { start_idle_thread(); + start_thread("pxe receive", 16384, 0, pxe_receive_thread, NULL); core_pm_hook = pm_return; } diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c index 4bdd08a..d655526 100644 --- a/core/fs/pxe/pxe.c +++ b/core/fs/pxe/pxe.c @@ -1066,8 +1066,11 @@ static void network_init(void) */ static int pxe_fs_init(struct fs_info *fs) { + extern void pxe_init_isr(void); /* XXX */ (void)fs; /* drop the compile warning message */ + pxe_init_isr(); + /* This block size is actually arbitrary... */ fs->sector_shift = fs->block_shift = TFTP_BLOCKSIZE_LG2; fs->sector_size = fs->block_size = 1 << TFTP_BLOCKSIZE_LG2; diff --git a/core/lwip/src/netif/undiif.c b/core/lwip/src/netif/undiif.c index 192f396..d557f29 100644 --- a/core/lwip/src/netif/undiif.c +++ b/core/lwip/src/netif/undiif.c @@ -66,19 +66,7 @@ int pxe_call(int, void *); #define IFNAME0 'u' #define IFNAME1 'n' -/** - * Helper struct to hold private data used to operate your ethernet interface. - * Keeping the ethernet address of the MAC in this struct is not necessary - * as it is already kept in the struct netif. - * But this is only an example, anyway... - */ -struct undiif { - struct eth_addr *ethaddr; - /* Add whatever per-interface state that is needed here. */ -}; - -/* Forward declarations. */ -static void undiif_input(struct netif *netif); +static struct netif *undi_netif; /** * In this function, the hardware should be initialized. @@ -180,6 +168,14 @@ low_level_output(struct netif *netif, struct pbuf *p) return ERR_OK; } +static void get_packet_fragment(t_PXENV_UNDI_ISR *isr) +{ + do { + isr->FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT; + pxe_call(PXENV_UNDI_ISR, &isr); + } while (isr->FuncFlag != PXENV_UNDI_ISR_OUT_RECEIVE); +} + /** * Should allocate a pbuf and transfer the bytes of the incoming * packet from the interface into the pbuf. @@ -189,15 +185,15 @@ low_level_output(struct netif *netif, struct pbuf *p) * NULL on memory error */ static struct pbuf * -low_level_input(struct netif *netif) +low_level_input(t_PXENV_UNDI_ISR *isr) { - struct undiif *undiif = netif->state; struct pbuf *p, *q; - u16_t len; + const char *r; + int len; /* Obtain the size of the packet and put it into the "len" variable. */ - len = 0; + len = isr->FrameLength; #if ETH_PAD_SIZE len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ @@ -207,20 +203,40 @@ low_level_input(struct netif *netif) p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); if (p != NULL) { - #if ETH_PAD_SIZE pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ #endif - /* We iterate over the pbuf chain until we have read the entire - * packet into the pbuf. */ - for(q = p; q != NULL; q = q->next) { - /* Read enough bytes to fill this pbuf in the chain. The + /* + * We iterate over the pbuf chain until we have read the entire + * packet into the pbuf. + */ + r = GET_PTR(isr->Frame); + for (q = p; q != NULL; q = q->next) { + /* + * Read enough bytes to fill this pbuf in the chain. The * available data in the pbuf is given by the q->len - * variable. */ - // read data into(q->payload, q->len); + * variable. + */ + char *s = q->payload; + int ql = q->len; + + while (ql) { + int qb = isr->BufferLength < ql ? isr->BufferLength : ql; + + if (!qb) { + /* + * Only received a partial frame, must get the next one... + */ + get_packet_fragment(isr); + } else { + memcpy(s, r, qb); + s += qb; + r += qb; + ql -= qb; + } + } } - // acknowledge that packet has been read(); #if ETH_PAD_SIZE pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ @@ -228,7 +244,13 @@ low_level_input(struct netif *netif) LINK_STATS_INC(link.recv); } else { - // drop packet(); + /* + * Dropped packet: we really should make sure we drain any partial + * frame here... + */ + while ((len -= isr->BufferLength) > 0) + get_packet_fragment(isr); + LINK_STATS_INC(link.memerr); LINK_STATS_INC(link.drop); } @@ -245,17 +267,13 @@ low_level_input(struct netif *netif) * * @param netif the lwip network interface structure for this undiif */ -static void -undiif_input(struct netif *netif) +void undiif_input(t_PXENV_UNDI_ISR *isr) { - struct undiif *undiif; struct eth_hdr *ethhdr; struct pbuf *p; - undiif = netif->state; - /* move received packet into a new pbuf */ - p = low_level_input(netif); + p = low_level_input(isr); /* no packet could be read, silently ignore this */ if (p == NULL) return; /* points to packet payload, which starts with an Ethernet header */ @@ -271,7 +289,7 @@ undiif_input(struct netif *netif) case ETHTYPE_PPPOE: #endif /* PPPOE_SUPPORT */ /* full packet send to tcpip_thread to process */ - if (netif->input(p, netif)!=ERR_OK) + if (undi_netif->input(p, undi_netif)!=ERR_OK) { LWIP_DEBUGF(NETIF_DEBUG, ("undiif_input: IP input error\n")); pbuf_free(p); p = NULL; @@ -300,19 +318,13 @@ undiif_input(struct netif *netif) err_t undiif_init(struct netif *netif) { - struct undiif *undiif; - LWIP_ASSERT("netif != NULL", (netif != NULL)); - undiif = mem_malloc(sizeof(struct undiif)); - if (undiif == NULL) { - LWIP_DEBUGF(NETIF_DEBUG, ("undiif_init: out of memory\n")); - return ERR_MEM; - } + undi_netif = netif; #if LWIP_NETIF_HOSTNAME /* Initialize interface hostname */ - netif->hostname = "lwip"; + netif->hostname = "undi"; #endif /* LWIP_NETIF_HOSTNAME */ /* @@ -322,7 +334,7 @@ undiif_init(struct netif *netif) */ NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS); - netif->state = undiif; + netif->state = NULL; /* Private pointer if we need it */ netif->name[0] = IFNAME0; netif->name[1] = IFNAME1; /* We directly use etharp_output() here to save a function call. @@ -332,8 +344,6 @@ undiif_init(struct netif *netif) netif->output = etharp_output; netif->linkoutput = low_level_output; - undiif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]); - /* initialize the hardware */ low_level_init(netif); -- 2.7.4