diff --git a/ChangeLog b/ChangeLog
index 039e56e8bc9b23ae234661354a1ecbfbe94942e0..ca1a55e7b3e1eb32c70b7c7b17b597e3e07d9a94 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2252,3 +2252,4 @@
 	  because CodeSourcery doesn't support hard flowing point!)
 	* arch/arm/src/stm32/chip/stm32_eth.h:  Add Ethernet register definitions
 	  for the STM32 F4.
+	* arch/arm/srcm/stm32/stm32_eth.c:  Adds an Ethernet driver for the STM32 F4.
diff --git a/arch/arm/src/stm32/stm32_eth.c b/arch/arm/src/stm32/stm32_eth.c
index 6f1f4a9444a415591f635c9481d5a223ba30a27a..e54c139b48e934918c5b93fb8cd3ab42771366f8 100755
--- a/arch/arm/src/stm32/stm32_eth.c
+++ b/arch/arm/src/stm32/stm32_eth.c
@@ -149,6 +149,11 @@
 #ifndef CONFIG_STM32_ETH_BUFSIZE
 #  define CONFIG_STM32_ETH_BUFSIZE  CONFIG_NET_BUFSIZE
 #endif
+
+#if CONFIG_STM32_ETH_BUFSIZE > ETH_TDES1_TBS1_MASK
+#  error "CONFIG_STM32_ETH_BUFSIZE is too large"
+#endif
+
 #ifndef CONFIG_STM32_ETH_NRXDESC
 #  define CONFIG_STM32_ETH_NRXDESC 8
 #endif
@@ -156,11 +161,9 @@
 #  define CONFIG_STM32_ETH_NTXDESC 4
 #endif
 
-#if CONFIG_STM32_ETH_NTXDESC > 2
-#  define STM32_ETH_NFREEBUFFERS CONFIG_STM32_ETH_NTXDESC
-#else
-#  define STM32_ETH_NFREEBUFFERS 2
-#endif
+/* We need at least one more free buffer than transmit buffers */
+
+#define STM32_ETH_NFREEBUFFERS (CONFIG_STM32_ETH_NTXDESC+1)
 
 /* Clocking *****************************************************************/
 /* Set MACMIIAR CR bits depending on HCLK setting */
@@ -396,9 +399,9 @@
  * ETH_DMABMR_DSL   Bits 2-6: Descriptor skip length
  * ETH_DMABMR_EDFE  Bit 7: Enhanced descriptor format enable
  * ETH_DMABMR_PBL   Bits 8-13: Programmable burst length
- * ETH_DMABMR_RTPR  Bits 14-15: Rx Tx priority ratio
+ * ETH_DMABMR_RTPR  Bits 14-15: RX TX priority ratio
  * ETH_DMABMR_FB    Bit 16: Fixed burst
- * ETH_DMABMR_RDP   Bits 17-22: Rx DMA PBL
+ * ETH_DMABMR_RDP   Bits 17-22: RX DMA PBL
  * ETH_DMABMR_USP   Bit 23: Use separate PBL
  * ETH_DMABMR_FPM   Bit 24: 4xPBL mode
  * ETH_DMABMR_AAB   Bit 25: Address-aligned beats
@@ -418,9 +421,9 @@
  * ETH_DMABMR_DSL   Descriptor skip length             0
  * ETH_DMABMR_EDFE  Enhanced descriptor format enable  Depends on CONFIG_STM32_ETH_ENHANCEDDESC
  * ETH_DMABMR_PBL   Programmable burst length          32 beats
- * ETH_DMABMR_RTPR  Rx Tx priority ratio               2:1
+ * ETH_DMABMR_RTPR  RX TX priority ratio               2:1
  * ETH_DMABMR_FB    Fixed burst                        1 (enabled)
- * ETH_DMABMR_RDP   Rx DMA PBL                         32 beats
+ * ETH_DMABMR_RDP   RX DMA PBL                         32 beats
  * ETH_DMABMR_USP   Use separate PBL                   1 (enabled)
  * ETH_DMABMR_FPM   4xPBL mode                         0 (disabled)
  * ETH_DMABMR_AAB   Address-aligned beats              1 (enabled)
@@ -489,10 +492,13 @@ struct stm32_ethmac_s
 
   /* Used to track transmit and receive descriptors */
 
-  struct eth_txdesc_s *txdesc;      /* Next TX descriptor */
-  struct eth_rxdesc_s *rxdesc;      /* Next RX descriptor */
-  struct eth_rxdesc_s *rxfirst;     /* First RX descriptor of the segment */
-  uint32_t             segcount;    /* Segment count */
+  struct eth_txdesc_s *txhead;      /* Next available TX descriptor */
+  struct eth_rxdesc_s *rxhead;      /* Next available RX descriptor */
+
+  struct eth_txdesc_s *txtail;      /* First "in_flight" TX descriptor */
+  struct eth_rxdesc_s *rxcurr;      /* First RX descriptor of the segment */
+  uint16_t             segments;    /* RX segment count */
+  uint16_t             inflight;    /* Number of TX transfers "in_flight" */
   sq_queue_t           freeb;       /* The free buffer list */
 
   /* Descriptor allocations */
@@ -530,9 +536,10 @@ static int  stm32_uiptxpoll(struct uip_driver_s *dev);
 /* Interrupt handling */
 
 static void stm32_freesegment(FAR struct stm32_ethmac_s *priv,
-                              FAR struct eth_rxdesc_s *rxfirst, int nsegments);
+                              FAR struct eth_rxdesc_s *rxfirst, int segments);
 static int  stm32_recvframe(FAR struct stm32_ethmac_s *priv);
 static void stm32_receive(FAR struct stm32_ethmac_s *priv);
+static void stm32_freeframe(FAR struct stm32_ethmac_s *priv);
 static void stm32_txdone(FAR struct stm32_ethmac_s *priv);
 static int  stm32_interrupt(int irq, FAR void *context);
 
@@ -543,12 +550,12 @@ static void stm32_txtimeout(int argc, uint32_t arg, ...);
 
 /* NuttX callback functions */
 
-static int stm32_ifup(struct uip_driver_s *dev);
-static int stm32_ifdown(struct uip_driver_s *dev);
-static int stm32_txavail(struct uip_driver_s *dev);
+static int  stm32_ifup(struct uip_driver_s *dev);
+static int  stm32_ifdown(struct uip_driver_s *dev);
+static int  stm32_txavail(struct uip_driver_s *dev);
 #ifdef CONFIG_NET_IGMP
-static int stm32_addmac(struct uip_driver_s *dev, FAR const uint8_t *mac);
-static int stm32_rmmac(struct uip_driver_s *dev, FAR const uint8_t *mac);
+static int  stm32_addmac(struct uip_driver_s *dev, FAR const uint8_t *mac);
+static int  stm32_rmmac(struct uip_driver_s *dev, FAR const uint8_t *mac);
 #endif
 
 /* Descriptor Initialization */
@@ -558,17 +565,18 @@ static void stm32_rxdescinit(FAR struct stm32_ethmac_s *priv);
 
 /* PHY Initialization */
 
-static int stm32_phyread(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t *value);
-static int stm32_phywrite(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t value);
-static int stm32_phyinit(FAR struct stm32_ethmac_s *priv);
+static int  stm32_phyread(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t *value);
+static int  stm32_phywrite(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t value);
+static int  stm32_phyinit(FAR struct stm32_ethmac_s *priv);
 
 /* MAC/DMA Initialization */
 
 static inline void stm32_ethgpioconfig(FAR struct stm32_ethmac_s *priv);
 static void stm32_ethreset(FAR struct stm32_ethmac_s *priv);
-static int stm32_macconfig(FAR struct stm32_ethmac_s *priv);
-static int stm32_macenable(FAR struct stm32_ethmac_s *priv);
-static int stm32_ethconfig(FAR struct stm32_ethmac_s *priv);
+static int  stm32_macconfig(FAR struct stm32_ethmac_s *priv);
+static void stm32_macaddress(FAR struct stm32_ethmac_s *priv);
+static int  stm32_macenable(FAR struct stm32_ethmac_s *priv);
+static int  stm32_ethconfig(FAR struct stm32_ethmac_s *priv);
 
 /****************************************************************************
  * Private Functions
@@ -701,18 +709,149 @@ static inline bool stm32_isfreebuffer(FAR struct stm32_ethmac_s *priv)
 
 static int stm32_transmit(FAR struct stm32_ethmac_s *priv)
 {
+  struct eth_txdesc_s *txdesc;
   uint32_t regval;
 
+  /* The internal uIP buffer size may be configured to be larger than the
+   * Ethernet buffer size.
+   */
+
+#if CONFIG_NET_BUFSIZE > CONFIG_STM32_ETH_BUFSIZE
+  struct eth_txdesc_s *txnext;
+  uint8_t *buffer;
+  int bufcount;
+  int lastsize;
+  int i;
+#endif
+
   /* Verify that the hardware is ready to send another packet.  If we get
    * here, then we are committed to sending a packet; Higher level logic
    * must have assured that there is no transmission in progress.
    */
 
-  /* Increment statistics */
+  txdesc = priv->txhead;
+  DEBUGASSERT(txdesc && (txdesc->tdes0 & ETH_TDES0_OWN) == 0);
+
+  /* Is the size to be sent greater than the size of the Ethernet buffer? */
+
+#if CONFIG_NET_BUFSIZE > CONFIG_STM32_ETH_BUFSIZE
+  if (priv->dev.d_len > CONFIG_STM32_ETH_BUFSIZE)
+    {
+      /* Yes... how many buffers will be need to send the packet? */
+
+      bufcount = (priv->dev.d_len + (CONFIG_STM32_ETH_BUFSIZE-1)) / CONFIG_STM32_ETH_BUFSIZE;
+      lastsize = priv->dev.d_len - (bufcount - 1) * CONFIG_STM32_ETH_BUFSIZE;
+
+      /* Set the first segment bit in the first TX descriptor */
+
+      txdesc->tdes0 |= ETH_TDES0_FS;
+
+      /* Set up all but the last TX descriptor */
+
+      txnext = txdesc;
+      buffer = priv->dev.d_buf;
+
+      for (i = 0; i < bufcount; i++)
+        {
+          /* This could be a normal event but the design does not handle it */
+
+          DEBUGASSERT((txnext->tdes0 & ETH_TDES0_OWN) == 0);
+
+          /* Set the Buffer1 address pointer */
+
+          txdesc->tdes2 = (uint32_t)buffer;
+
+          /* Set the buffer size in all TX descriptors, set the last segment
+           * bit in the last TX descriptor
+           */
+
+          if (i == (bufcount-1))
+            {
+              txnext->tdes0 |= ETH_TDES0_LS;
+              txnext->tdes1  = lastsize;
+              buffer        += lastsize;
+            }
+          else
+            {
+              txnext->tdes1  = CONFIG_STM32_ETH_BUFSIZE;
+              buffer        += CONFIG_STM32_ETH_BUFSIZE;
+            }
+
+          /* Give descriptor back to DMA */
+
+          txnext->tdes0 |= ETH_TDES0_OWN;
+          txnext         = (struct eth_txdesc_s *)txnext->tdes3;
+        }
+
+      /* Remember the start of the next available TX descriptor */
+ 
+      txdesc = txnext;
+    }
+  else
+#endif
+    {
+      /* The single descriptor is both the first and last segment */
+
+      txdesc->tdes0 |= (ETH_TDES0_FS | ETH_TDES0_LS);
+
+      /* Set frame size */
+
+      DEBUGASSERT(priv->dev.d_len <= CONFIG_NET_BUFSIZE);
+      txdesc->tdes1 = priv->dev.d_len;
 
-  /* Send the packet: address=priv->dev.d_buf, length=priv->dev.d_len */
+      /* Set the Buffer1 address pointer */
 
-  /* Enable Tx interrupts */
+      txdesc->tdes2 = (uint32_t)priv->dev.d_buf;
+
+      /* Set OWN bit of the TX descriptor tdes0.  This gives the buffer to
+       * Ethernet DMA
+       */
+
+      txdesc->tdes0 |= ETH_TDES0_OWN;
+
+      /* Point to the next available TX descriptor */
+
+      txdesc = (struct eth_txdesc_s *)txdesc->tdes3;
+    }
+
+  /* Remember where we left off in the TX descriptor chain */
+
+  priv->txhead = txdesc;
+
+  /* Detach the buffer from priv->dev structure.  That buffer is now
+   * "in-flight".
+   */
+
+  priv->dev.d_buf = NULL;
+
+  /* If there is no other TX buffer, in flight, then remember this
+   * as the location to check for TX done events.
+   */
+
+  if (!priv->txtail)
+    {
+      DEBUGASSERT(priv->inflight == 0);
+      priv->txtail = txdesc;
+    }
+
+  /* Increment the number of TX transfer in-flight */
+
+  priv->inflight++;
+
+  /* Check if the TX Buffer unavailable flag is set */
+
+  if ((getreg32(STM32_ETH_DMASR) & ETH_DMAINT_TBUI) != 0)
+    {
+      /* Clear TX Buffer unavailable flag */
+
+      putreg32(ETH_DMAINT_TBUI, STM32_ETH_DMASR);
+
+      /* Resume DMA transmission */
+
+      putreg32(0, STM32_ETH_DMATPDR);
+    }
+
+  /* Enable TX interrupts */
 
   regval  = getreg32(STM32_ETH_DMAIER);
   regval |= ETH_DMAINT_XMIT_ENABLE;
@@ -758,12 +897,24 @@ static int stm32_uiptxpoll(struct uip_driver_s *dev)
 
   if (priv->dev.d_len > 0)
     {
+      /* Send the packet */
+
       uip_arp_out(&priv->dev);
       stm32_transmit(priv);
 
-      /* Check if there is room in the device to hold another packet. If not,
-       * return a non-zero value to terminate the poll.
+      /* Check if the next TX descriptor is owned by the Ethernet DMA or CPU.  We
+       * cannot perform the TX poll if we are unable to accept another packet for
+       * transmission.
        */
+
+      if ((priv->txhead->tdes0 & ETH_TDES0_OWN) == 0)
+        {
+          /* There is room in the device to hold another packet. Return a non-
+           * zero value to terminate the poll.
+           */
+
+          return -EBUSY;
+        }
     }
 
   /* If zero is returned, the polling will continue until all connections have
@@ -792,7 +943,7 @@ static int stm32_uiptxpoll(struct uip_driver_s *dev)
  ****************************************************************************/
 
 static void stm32_freesegment(FAR struct stm32_ethmac_s *priv,
-                              FAR struct eth_rxdesc_s *rxfirst, int nsegments)
+                              FAR struct eth_rxdesc_s *rxfirst, int segments)
 {
   struct eth_rxdesc_s *rxdesc;
   int i;
@@ -800,7 +951,7 @@ static void stm32_freesegment(FAR struct stm32_ethmac_s *priv,
   /* Set OWN bit in RX descriptors.  This gives the buffers back to DMA */
 
   rxdesc = rxfirst;
-  for (i = 0; i < nsegments; i++)
+  for (i = 0; i < segments; i++)
     {
       rxdesc->rdes0 = ETH_RDES0_OWN;
       rxdesc = (struct eth_rxdesc_s *)rxdesc->rdes3;
@@ -808,8 +959,8 @@ static void stm32_freesegment(FAR struct stm32_ethmac_s *priv,
 
   /* Reset the segment managment logic */
 
-  priv->rxfirst  = NULL;
-  priv->segcount = 0;
+  priv->rxcurr   = NULL;
+  priv->segments = 0;
 
   /* Check if the RX Buffer unavailable flag is set */
 
@@ -849,7 +1000,7 @@ static void stm32_freesegment(FAR struct stm32_ethmac_s *priv,
 static int stm32_recvframe(FAR struct stm32_ethmac_s *priv)
 {
   struct eth_rxdesc_s *rxdesc;
-  struct eth_rxdesc_s *rxfirst;
+  struct eth_rxdesc_s *rxcurr;
   uint8_t *buffer;
   int i;
 
@@ -865,7 +1016,7 @@ static int stm32_recvframe(FAR struct stm32_ethmac_s *priv)
 
   /* Scan descriptors owned by the CPU */
 
-  rxdesc = priv->rxdesc;
+  rxdesc = priv->rxhead;
   for (i = 0;
        (rxdesc->rdes0 & ETH_RDES0_OWN) == 0 && i < CONFIG_STM32_ETH_NRXDESC;
        i++)
@@ -875,8 +1026,8 @@ static int stm32_recvframe(FAR struct stm32_ethmac_s *priv)
       if ((rxdesc->rdes0 & ETH_RDES0_FS) != 0 &&
           (rxdesc->rdes0 & ETH_RDES0_LS) == 0)
         {
-          priv->rxfirst  = rxdesc;
-          priv->segcount = 1;   
+          priv->rxcurr   = rxdesc;
+          priv->segments = 1;   
         }
     
       /* Check if this is an intermediate segment in the frame */
@@ -884,24 +1035,24 @@ static int stm32_recvframe(FAR struct stm32_ethmac_s *priv)
       else if (((rxdesc->rdes0 & ETH_RDES0_LS) == 0)&&
                ((rxdesc->rdes0 & ETH_RDES0_FS) == 0))
         {
-          priv->segcount++;
+          priv->segments++;
         }
 
       /* Otherwise, it is the last segment in the frame */
 
       else
         { 
-          priv->segcount++;
+          priv->segments++;
 
           /* Check if the there is only one segment in the frame */
 
-          if (priv->segcount == 1)
+          if (priv->segments == 1)
             {
-              rxfirst = rxdesc;
+              rxcurr = rxdesc;
             }
           else
             {
-              rxfirst = priv->rxfirst;
+              rxcurr = priv->rxcurr;
             }
 
           /* Check if any errors are reported in the frame */
@@ -929,15 +1080,16 @@ static int stm32_recvframe(FAR struct stm32_ethmac_s *priv)
                * buffer.
                */
 
-              dev->d_buf     = (uint8_t*)rxfirst->rdes2;
-              rxfirst->rdes2 = (uint32_t)buffer;
+              DEBUGASSERT(dev->d_buf == NULL);
+              dev->d_buf    = (uint8_t*)rxcurr->rdes2;
+              rxcurr->rdes2 = (uint32_t)buffer;
 
               /* Return success, remebering where we should re-start scanning
                * and resetting the segment scanning logic
                */
 
-              priv->rxdesc   = (struct eth_rxdesc_s*)rxdesc->rdes3;
-              stm32_freesegment(priv, rxfirst, priv->segcount);
+              priv->rxhead   = (struct eth_rxdesc_s*)rxdesc->rdes3;
+              stm32_freesegment(priv, rxcurr, priv->segments);
               return OK;
             }
           else
@@ -947,7 +1099,7 @@ static int stm32_recvframe(FAR struct stm32_ethmac_s *priv)
                */
 
               nlldbg("DROPPED: RX descriptor errors: %08x\n", rxdesc->rdes0);
-              stm32_freesegment(priv, rxfirst, priv->segcount);
+              stm32_freesegment(priv, rxcurr, priv->segments);
             }
         }
 
@@ -956,11 +1108,11 @@ static int stm32_recvframe(FAR struct stm32_ethmac_s *priv)
       rxdesc = (struct eth_rxdesc_s*)rxdesc->rdes3;
     }
 
-  /* We get here after all of the descriptors have been scanned.  Remember
-   * where we left off.
+  /* We get here after all of the descriptors have been scanned or when rxdesc points
+   * to the first descriptor owned by the DMA.  Remember where we left off.
    */
 
-  priv->rxdesc = rxdesc;
+  priv->rxhead = rxdesc;
   return -EAGAIN; 
 }
 
@@ -1003,9 +1155,9 @@ static void stm32_receive(FAR struct stm32_ethmac_s *priv)
       /* We only accept IP packets of the configured type and ARP packets */
 
 #ifdef CONFIG_NET_IPv6
-      if (BUF->type == HTONS(UIP_ETHTYPE_IP6))
+      else if (BUF->type == HTONS(UIP_ETHTYPE_IP6))
 #else
-      if (BUF->type == HTONS(UIP_ETHTYPE_IP))
+      else if (BUF->type == HTONS(UIP_ETHTYPE_IP))
 #endif
         {
           uip_arp_ipin(&priv->dev);
@@ -1034,6 +1186,102 @@ static void stm32_receive(FAR struct stm32_ethmac_s *priv)
               stm32_transmit(priv);
             }
         }
+      else
+        {
+          nlldbg("DROPPED: Unknown type: %04x\n", BUF->type);
+        }
+
+      /* We are finished with the RX buffer.  NOTE:  If the buffer is
+       * re-used for transmission, the dev->d_buf field will have been
+       * nullified.
+       */
+
+      if (dev->d_buf)
+        {
+          /* Free the receive packet buffer */
+
+          stm32_freebuffer(priv, dev->d_buf);
+          dev->d_buf = NULL;
+        }
+    }
+}
+
+/****************************************************************************
+ * Function: stm32_freeframe
+ *
+ * Description:
+ *   Scans the TX descriptors and frees the buffers of completed TX transfers.
+ *
+ * Parameters:
+ *   priv  - Reference to the driver state structure
+ *
+ * Returned Value:
+ *   None.
+ *
+ * Assumptions:
+ *   Global interrupts are disabled by interrupt handling logic.
+ *
+ ****************************************************************************/
+
+static void stm32_freeframe(FAR struct stm32_ethmac_s *priv)
+{
+  struct eth_txdesc_s *txdesc;
+  int i;
+
+  /* Scan for "in-flight" descriptors owned by the CPU */
+
+  txdesc = priv->txtail;
+  if (txdesc)
+    {
+      DEBUGASSERT(priv->inflight > 0);
+
+      for (i = 0; (txdesc->tdes0 & ETH_TDES0_OWN) == 0; i++)
+        {
+          /* There should be a buffer assigned to all in-flight
+           * TX descriptors.
+           */
+
+          DEBUGASSERT(txdesc->tdes2 != 0);
+
+          /* Check if this is the first segment of a TX frame. */
+
+          if ((txdesc->tdes0 & ETH_TDES0_FS) != 0)
+            {
+              /* Yes.. Free the buffer */
+
+              stm32_freebuffer(priv, (uint8_t*)txdesc->tdes2);
+            }
+
+          /* In any event, make sure that TDES2 is nullified. */
+
+          txdesc->tdes2 = 0;
+
+          /* Check if this is the last segement of a TX frame */
+
+          if ((txdesc->tdes0 & ETH_TDES0_FS) != 0)
+            {
+              /* Yes.. Decrement the number of frames "in-flight".
+               * If there are no more frames in-flight, then bail.
+               */
+
+              if (--priv->inflight <= 0)
+                {
+                  priv->txtail   = NULL;
+                  priv->inflight = 0;
+                  return;
+                }
+            }
+
+          /* Try the next descriptor in the TX chain */
+
+          txdesc = (struct eth_txdesc_s*)txdesc->tdes3;
+        }
+
+      /* We get here if (1) there are still frames "in-flight". Remember
+       * where we left off.
+       */
+
+      priv->txtail = txdesc;
     }
 }
 
@@ -1058,17 +1306,24 @@ static void stm32_txdone(FAR struct stm32_ethmac_s *priv)
 {
   uint32_t regval;
 
-  /* Check for errors and update statistics */
+  DEBUGASSERT(priv->txtail != NULL);
+
+  /* Scan the TX desciptor change, returning buffers to free list */
+
+  stm32_freeframe(priv);
 
   /* If no further xmits are pending, then cancel the TX timeout */
 
-  wd_cancel(priv->txtimeout);
+  if (priv->inflight <= 0)
+    {
+      wd_cancel(priv->txtimeout);
 
-  /* And disable further Tx interrupts. */
+      /* And disable further TX interrupts. */
 
-  regval = getreg32(STM32_ETH_DMAIER);
-  regval &= ~ETH_DMAINT_XMIT_DISABLE;
-  putreg32(regval, STM32_ETH_DMAIER);
+      regval = getreg32(STM32_ETH_DMAIER);
+      regval &= ~ETH_DMAINT_XMIT_DISABLE;
+      putreg32(regval, STM32_ETH_DMAIER);
+    }
 
   /* Then poll uIP for new XMIT data */
 
@@ -1127,7 +1382,7 @@ static int stm32_interrupt(int irq, FAR void *context)
         }
 
       /* Check if a packet transmission just completed.  If so, call
-       * stm32_txdone(). This may disable further Tx interrupts if there
+       * stm32_txdone(). This may disable further TX interrupts if there
        * are no pending tansmissions.
        */
 
@@ -1194,9 +1449,12 @@ static void stm32_txtimeout(int argc, uint32_t arg, ...)
 {
   FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)arg;
 
-  /* Increment statistics and dump debug info */
+  /* Then reset the hardware.  Just take the interface down, then back
+   * up again.
+   */
 
-  /* Then reset the hardware */
+  stm32_ifdown(&priv->dev);
+  stm32_ifup(&priv->dev);
 
   /* Then poll uIP for new XMIT data */
 
@@ -1225,16 +1483,20 @@ static void stm32_polltimer(int argc, uint32_t arg, ...)
 {
   FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)arg;
 
-  /* Check if there is room in the send another TX packet.  We cannot perform
-   * the TX poll if he are unable to accept another packet for transmission.
+  /* Check if the next TX descriptor is owned by the Ethernet DMA or CPU.  We
+   * cannot perform the TX poll if we are unable to accept another packet for
+   * transmission.
    */
 
-  /* If so, update TCP timing states and poll uIP for new XMIT data. Hmmm..
-   * might be bug here.  Does this mean if there is a transmit in progress,
-   * we will missing TCP time state updates?
-   */
+  if ((priv->txhead->tdes0 & ETH_TDES0_OWN) == 0)
+    {
+      /* If so, update TCP timing states and poll uIP for new XMIT data. Hmmm..
+       * might be bug here.  Does this mean if there is a transmit in progress,
+       * we will missing TCP time state updates?
+       */
 
-  (void)uip_timer(&priv->dev, stm32_uiptxpoll, STM32_POLLHSEC);
+      (void)uip_timer(&priv->dev, stm32_uiptxpoll, STM32_POLLHSEC);
+    }
 
   /* Setup the watchdog poll timer again */
 
@@ -1365,11 +1627,18 @@ static int stm32_txavail(struct uip_driver_s *dev)
 
   if (priv->ifup)
     {
-      /* Check if there is room in the hardware to hold another outgoing packet. */
+      /* Check if the next TX descriptor is owned by the Ethernet DMA or
+       * CPU.  We cannot perform the TX poll if we are unable to accept
+       * another packet for
+       * transmission.
+       */
 
-      /* If so, then poll uIP for new XMIT data */
+      if ((priv->txhead->tdes0 & ETH_TDES0_OWN) == 0)
+        {
+          /* If we have the descriptor, then poll uIP for new XMIT data */
 
-      (void)uip_poll(&priv->dev, stm32_uiptxpoll);
+          (void)uip_poll(&priv->dev, stm32_uiptxpoll);
+        }
     }
 
   irqrestore(flags);
@@ -1400,6 +1669,7 @@ static int stm32_addmac(struct uip_driver_s *dev, FAR const uint8_t *mac)
   FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private;
 
   /* Add the MAC address to the hardware multicast routing table */
+#error "Missing logic"
 
   return OK;
 }
@@ -1429,6 +1699,7 @@ static int stm32_rmmac(struct uip_driver_s *dev, FAR const uint8_t *mac)
   FAR struct stm32_ethmac_s *priv = (FAR struct stm32_ethmac_s *)dev->d_private;
 
   /* Add the MAC address to the hardware multicast routing table */
+#error "Missing logic"
 
   return OK;
 }
@@ -1455,9 +1726,19 @@ static void stm32_txdescinit(FAR struct stm32_ethmac_s *priv)
   struct eth_txdesc_s *txdesc;
   int i;
   
-  /* Set the priv->txdesc pointer with the first descriptor in the table */
+  /* priv->txhead will point to the first, available TX descriptor in the chain.
+   * Set the priv->txhead pointer to the first descriptor in the table.
+   */
+
+  priv->txhead = priv->txtable;
 
-  priv->txdesc = priv->txtable;
+  /* priv->txtail will point to the first segment of the oldest pending
+   * "in-flight" TX transfer.  NULL means that there are no active TX
+   * transfers.
+   */
+
+   priv->txtail   = NULL;
+   priv->inflight = 0;
 
   /* Initialize each TX descriptor */   
 
@@ -1470,7 +1751,7 @@ static void stm32_txdescinit(FAR struct stm32_ethmac_s *priv)
       txdesc->tdes0 = ETH_TDES0_TCH;  
        
 #ifdef CHECKSUM_BY_HARDWARE
-      /* Enable the checksum insertion for the Tx frames */
+      /* Enable the checksum insertion for the TX frames */
 
       txdesc->tdes0 |= ETH_TDES0_CIC_ALL;
 #endif
@@ -1479,7 +1760,7 @@ static void stm32_txdescinit(FAR struct stm32_ethmac_s *priv)
        * are used)
        */
 
-      txdesc->tdes2 = 0;;
+      txdesc->tdes2 = 0;
     
       /* Initialize the next descriptor with the Next Descriptor Polling Enable */
 
@@ -1527,9 +1808,18 @@ static void stm32_rxdescinit(FAR struct stm32_ethmac_s *priv)
   struct eth_rxdesc_s *rxdesc;
   int i;
   
-  /* Set the priv->rxdesc pointer with the first one of the table list */
+  /* priv->rxhead will point to the first,  RX descriptor in the chain.
+   * This will be where we receive the first incomplete frame.
+   */
 
-  priv->rxdesc = priv->rxtable; 
+  priv->rxhead = priv->rxtable;
+
+  /* If we accumulate the frame in segments, priv->rxcurr points to the
+   * RX descriptor of the first segment in the current TX frame.
+   */
+
+  priv->rxcurr   = NULL;
+  priv->segments = 0;
 
   /* Initialize each TX descriptor */   
 
@@ -1537,7 +1827,7 @@ static void stm32_rxdescinit(FAR struct stm32_ethmac_s *priv)
     {
       rxdesc = &priv->rxtable[i];
 
-      /* Set Own bit of the Rx descriptor rdes0 */
+      /* Set Own bit of the RX descriptor rdes0 */
 
       rxdesc->rdes0 = ETH_RDES0_OWN;
 
@@ -2079,6 +2369,41 @@ static int stm32_macconfig(FAR struct stm32_ethmac_s *priv)
   return OK;
 }
 
+/****************************************************************************
+ * Function: stm32_macaddress
+ *
+ * Description:
+ *   Configure the selected MAC address.
+ *
+ * Parameters:
+ *   priv - A reference to the private driver state structure
+ *
+ * Returned Value:
+ *   OK on success; Negated errno on failure.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static void stm32_macaddress(FAR struct stm32_ethmac_s *priv)
+{
+  uint32_t regval;
+
+  /* Set the MAC address high register */
+  
+  regval = ((uint32_t)priv->dev.d_mac.ether_addr_octet[5] << 8) |
+            (uint32_t)priv->dev.d_mac.ether_addr_octet[4];
+  putreg32(regval, STM32_ETH_MACA0HR);
+
+  /* Set the MAC address low register */
+  
+  regval = ((uint32_t)priv->dev.d_mac.ether_addr_octet[3] << 24) |
+           ((uint32_t)priv->dev.d_mac.ether_addr_octet[2] << 16) |
+           ((uint32_t)priv->dev.d_mac.ether_addr_octet[1] <<  8) | 
+            (uint32_t)priv->dev.d_mac.ether_addr_octet[0];
+  putreg32(regval, STM32_ETH_MACA0LR);
+}
+
 /****************************************************************************
  * Function: stm32_macenable
  *
@@ -2099,6 +2424,10 @@ static int stm32_macenable(FAR struct stm32_ethmac_s *priv)
 {
   uint32_t regval;
 
+  /* Set the MAC address */
+
+  stm32_macaddress(priv);
+
   /* Enable transmit state machine of the MAC for transmission on the MII */  
 
   regval  = getreg32(STM32_ETH_MACCR);
@@ -2203,11 +2532,11 @@ static int stm32_ethconfig(FAR struct stm32_ethmac_s *priv)
 
   stm32_initbuffer(priv);
 
-  /* Initialize Tx Descriptors list: Chain Mode */
+  /* Initialize TX Descriptors list: Chain Mode */
 
   stm32_txdescinit(priv);
 
-  /* Initialize Rx Descriptors list: Chain Mode  */
+  /* Initialize RX Descriptors list: Chain Mode  */
 
   stm32_rxdescinit(priv);
 
diff --git a/configs/stm3240g-eval/README.txt b/configs/stm3240g-eval/README.txt
index 25ee3ce349a731f02a85242a4125ca716c00bfc4..6c2a793f700cf8e4aac9cf33c3768b80555ac8c9 100755
--- a/configs/stm3240g-eval/README.txt
+++ b/configs/stm3240g-eval/README.txt
@@ -419,4 +419,12 @@ Where <subdir> is one of the following:
     examples/ostest.  By default, this project assumes that you are
     using the DFU bootloader.
 
-    CONFIG_STM32_BUILDROOT=y	  : CodeSourcery under Windows
+    CONFIG_STM32_CODESOURCERYW=y  : CodeSourcery under Windows
+
+  nsh:
+  ---
+    Configures the NuttShell (nsh) located at apps/examples/nsh.  The
+    Configuration enables both the serial and telnet NSH interfaces.
+
+    CONFIG_STM32_CODESOURCERYW=y  : CodeSourcery under Windows
+