[syslinux:lwip] pxe: hook up the interrupt routine and the lwip receive routine

syslinux-bot for Eric W. Biederman hpa at zytor.com
Fri Apr 22 20:05:32 PDT 2011


Commit-ID:  4a9967816de45858b8afabd650e8122c7fc0c8b8
Gitweb:     http://syslinux.zytor.com/commit/4a9967816de45858b8afabd650e8122c7fc0c8b8
Author:     Eric W. Biederman <hpa at zytor.com>
AuthorDate: Sat, 9 Apr 2011 21:16:21 -0700
Committer:  Eric W. Biederman <ebiederm at xmission.com>
CommitDate: Tue, 12 Apr 2011 14:40:51 -0700

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 <ebiederm at xmission.com>


---
 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 <string.h>
 
 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);
 



More information about the Syslinux-commits mailing list