Index: devs/eth/arm/at91/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/arm/at91/current/ChangeLog,v
retrieving revision 1.4
diff -u -5 -w -p -r1.4 ChangeLog
--- devs/eth/arm/at91/current/ChangeLog	29 Jan 2009 17:47:59 -0000	1.4
+++ devs/eth/arm/at91/current/ChangeLog	15 Feb 2010 09:37:32 -0000
@@ -1,5 +1,11 @@
+2010-01-10  Robert Brusa <bob.brusa@gmail.com>
+
+	* src/if_at91.c: bug in buffer-to-list copy in routine
+	  at91_eth_recv fixed (It  handled the first list only
+	  correctly).
+	
 2007-04-08  Uwe Kindler  <uwe_kindler@web.de>
 
 	* cdl/at91_eth.cdl: Fixed typo. (Removed AT91RM9200 from
 	  CYGPKG_DEVS_ETH_ARM_AT91_DEBUG_LEVEL)
 	
Index: devs/eth/arm/at91/current/cdl/at91_eth.cdl
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/arm/at91/current/cdl/at91_eth.cdl,v
retrieving revision 1.3
diff -u -5 -w -p -r1.3 at91_eth.cdl
Index: devs/eth/arm/at91/current/src/if_at91.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/arm/at91/current/src/if_at91.c,v
retrieving revision 1.3
diff -u -5 -w -p -r1.3 if_at91.c
--- devs/eth/arm/at91/current/src/if_at91.c	29 Jan 2009 17:47:59 -0000	1.3
+++ devs/eth/arm/at91/current/src/if_at91.c	15 Feb 2010 09:37:32 -0000
@@ -37,13 +37,13 @@
 // -------------------------------------------                              
 // ####ECOSGPLCOPYRIGHTEND####                                              
 //==========================================================================
 //#####DESCRIPTIONBEGIN####
 //
-// Author(s):    Andrew Lunn, John Eigelaar
+// Author(s):    Andrew Lunn, John Eigelaar, Robert Brusa (rwb)
 // Contributors:  
-// Date:         2006-05-10
+// Date:         2006-05-10, 2010-01-10
 // Purpose:
 // Description:
 //
 //####DESCRIPTIONEND####
 //
@@ -919,76 +919,72 @@ at91_eth_deliver(struct eth_drv_sc *sc)
    {
       debug1_printf("AT91_ETH: Rx OVR\n");
    }
 
 }
-
+// rwb 100110 bugfix: list 0 ok, but higher lists where not handled correctly.
+// actually, the original code just ignored them.
 static void
 at91_eth_recv(struct eth_drv_sc *sc,
               struct eth_drv_sg *sg_list,
               int sg_len)
 {
    at91_eth_priv_t *priv = (at91_eth_priv_t *)sc->driver_private;
    int i;
-   cyg_uint32 bytes_in_buffer;
-   cyg_uint32 bytes_in_list = 0;
-   cyg_uint32 bytes_needed_list = 0;
-   cyg_uint32 buffer_pos = 0;
-   cyg_uint8 * sg_buf;
-   cyg_uint32 total_bytes = 0;
+								    // number of bytes in ..
+   cyg_uint32 bytes_in_buffer;		// in hw-receive-buffer rbd
+   cyg_uint32 bytes_in_list;		// in current list
+   cyg_uint32 bytes_needed_list;	// required to make current list full
+   cyg_uint32 buffer_pos = 0;		// allready copied away from rec-buffer rbd
+   cyg_uint8 * sg_buf;				// pointer where to copy to
+   cyg_uint32 total_bytes = 0;		// total # of bytes copied from buffers.
 
    for(i = 0;i<sg_len;i++)
    {
+	 bytes_in_list = 0;	// current list is empty
+     sg_buf = (cyg_uint8 *)(sg_list[i].buf); // define copy-to-pointer
+
       while(bytes_in_list < sg_list[i].len)
-      {
+      {	// list i not full yet, compute how many bytes still have room in this
+    	// list i.
          bytes_needed_list = sg_list[i].len - bytes_in_list;
 
          if(priv->rbd[priv->curr_rbd_idx].sr & AT91_EMAC_RBD_SR_EOF)
-         {
-	      bytes_in_buffer = 
-		((priv->rbd[priv->curr_rbd_idx].sr & AT91_EMAC_RBD_SR_LEN_MASK)
-		 - total_bytes) - buffer_pos;
+         { // eof-flag set
+        	 bytes_in_buffer = ((priv->rbd[priv->curr_rbd_idx].sr &
+        			 AT91_EMAC_RBD_SR_LEN_MASK) - total_bytes) - buffer_pos;
          }
          else
-         {
+         { // all the rest then
             bytes_in_buffer = AT91_EMAC_RX_BUFF_SIZE - buffer_pos;
          }
-
-         sg_buf = (cyg_uint8 *)(sg_list[i].buf);
-
          if(bytes_needed_list < bytes_in_buffer)
-         {
+         { // buffer has more bytes than there is room left in list
             if(sg_buf != NULL)
                memcpy(&sg_buf[bytes_in_list],
 		      &priv->rb[priv->curr_rbd_idx].rb[buffer_pos],
-		      bytes_needed_list);
+		      bytes_needed_list);				// current list is full now
             bytes_in_list += bytes_needed_list;
             buffer_pos += bytes_needed_list;
             total_bytes += bytes_needed_list;
          }
          else
-         {
+         {	//rest of buffer fits into list. List may become full.
             if(sg_buf != NULL)
               memcpy(&sg_buf[bytes_in_list],
 		     &priv->rb[priv->curr_rbd_idx].rb[buffer_pos],
 		     bytes_in_buffer);
             bytes_in_list += bytes_in_buffer;
             total_bytes += bytes_in_buffer;
-
-            /* Step our buffer on one */
-            priv->rbd[priv->curr_rbd_idx].addr &= 
-	      ~(AT91_EMAC_RBD_ADDR_OWNER_SW);
-            priv->curr_rbd_idx++;
-            if(priv->curr_rbd_idx >= CYGNUM_DEVS_ETH_ARM_AT91_RX_BUFS)
-            {
-               priv->curr_rbd_idx = 0;
-            }
+         	// wee need a new buffer. Step our buffer on one
             buffer_pos = 0;
-         }
-      }
-   }
-}
+            priv->rbd[priv->curr_rbd_idx].addr &= ~(AT91_EMAC_RBD_ADDR_OWNER_SW);
+            priv->curr_rbd_idx = (priv->curr_rbd_idx + 1) % CYGNUM_DEVS_ETH_ARM_AT91_RX_BUFS;
+         } // if !bytes...
+      } // while(bytes...
+   } // for (i
+} // end at91_eth_recv
 
 // routine called to handle ethernet controller in polled mode
 static void 
 at91_eth_poll(struct eth_drv_sc *sc)
 {
Index: devs/eth/arm/at91/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/arm/at91/current/ChangeLog,v
retrieving revision 1.4
diff -u -5 -w -p -r1.4 ChangeLog
--- devs/eth/arm/at91/current/ChangeLog	29 Jan 2009 17:47:59 -0000	1.4
+++ devs/eth/arm/at91/current/ChangeLog	15 Feb 2010 09:47:34 -0000
@@ -1,5 +1,11 @@
+2010-01-10  Robert Brusa <bob.brusa@gmail.com>
+
+	* src/if_at91.c: bug in buffer-to-list copy in routine
+	  at91_eth_recv fixed (It  handled the first list only
+	  correctly).
+	
 2007-04-08  Uwe Kindler  <uwe_kindler@web.de>
 
 	* cdl/at91_eth.cdl: Fixed typo. (Removed AT91RM9200 from
 	  CYGPKG_DEVS_ETH_ARM_AT91_DEBUG_LEVEL)
 	
Index: devs/eth/arm/at91/current/cdl/at91_eth.cdl
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/arm/at91/current/cdl/at91_eth.cdl,v
retrieving revision 1.3
diff -u -5 -w -p -r1.3 at91_eth.cdl
Index: devs/eth/arm/at91/current/src/if_at91.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/arm/at91/current/src/if_at91.c,v
retrieving revision 1.3
diff -u -5 -w -p -r1.3 if_at91.c
--- devs/eth/arm/at91/current/src/if_at91.c	29 Jan 2009 17:47:59 -0000	1.3
+++ devs/eth/arm/at91/current/src/if_at91.c	15 Feb 2010 09:47:35 -0000
@@ -37,13 +37,13 @@
 // -------------------------------------------                              
 // ####ECOSGPLCOPYRIGHTEND####                                              
 //==========================================================================
 //#####DESCRIPTIONBEGIN####
 //
-// Author(s):    Andrew Lunn, John Eigelaar
+// Author(s):    Andrew Lunn, John Eigelaar, Robert Brusa (rwb)
 // Contributors:  
-// Date:         2006-05-10
+// Date:         2006-05-10, 2010-01-10
 // Purpose:
 // Description:
 //
 //####DESCRIPTIONEND####
 //
@@ -919,76 +919,72 @@ at91_eth_deliver(struct eth_drv_sc *sc)
    {
       debug1_printf("AT91_ETH: Rx OVR\n");
    }
 
 }
-
+// rwb 100110 bugfix: list 0 ok, but higher lists where not handled correctly.
+// actually, the original code just ignored them.
 static void
 at91_eth_recv(struct eth_drv_sc *sc,
               struct eth_drv_sg *sg_list,
               int sg_len)
 {
    at91_eth_priv_t *priv = (at91_eth_priv_t *)sc->driver_private;
    int i;
-   cyg_uint32 bytes_in_buffer;
-   cyg_uint32 bytes_in_list = 0;
-   cyg_uint32 bytes_needed_list = 0;
-   cyg_uint32 buffer_pos = 0;
-   cyg_uint8 * sg_buf;
-   cyg_uint32 total_bytes = 0;
+								    // number of bytes in ..
+   cyg_uint32 bytes_in_buffer;		// in hw-receive-buffer rbd
+   cyg_uint32 bytes_in_list;		// in current list
+   cyg_uint32 bytes_needed_list;	// required to make current list full
+   cyg_uint32 buffer_pos = 0;		// allready copied away from rec-buffer rbd
+   cyg_uint8 * sg_buf;				// pointer where to copy to
+   cyg_uint32 total_bytes = 0;		// total # of bytes copied from buffers.
 
    for(i = 0;i<sg_len;i++)
    {
+	 bytes_in_list = 0;	// current list is empty
+     sg_buf = (cyg_uint8 *)(sg_list[i].buf); // define copy-to-pointer
+
       while(bytes_in_list < sg_list[i].len)
-      {
+      {	// list i not full yet, compute how many bytes still have room in this
+    	// list i.
          bytes_needed_list = sg_list[i].len - bytes_in_list;
 
          if(priv->rbd[priv->curr_rbd_idx].sr & AT91_EMAC_RBD_SR_EOF)
-         {
-	      bytes_in_buffer = 
-		((priv->rbd[priv->curr_rbd_idx].sr & AT91_EMAC_RBD_SR_LEN_MASK)
-		 - total_bytes) - buffer_pos;
+         { // eof-flag set
+        	 bytes_in_buffer = ((priv->rbd[priv->curr_rbd_idx].sr &
+        			 AT91_EMAC_RBD_SR_LEN_MASK) - total_bytes) - buffer_pos;
          }
          else
-         {
+         { // all the rest then
             bytes_in_buffer = AT91_EMAC_RX_BUFF_SIZE - buffer_pos;
          }
-
-         sg_buf = (cyg_uint8 *)(sg_list[i].buf);
-
          if(bytes_needed_list < bytes_in_buffer)
-         {
+         { // buffer has more bytes than there is room left in list
             if(sg_buf != NULL)
                memcpy(&sg_buf[bytes_in_list],
 		      &priv->rb[priv->curr_rbd_idx].rb[buffer_pos],
-		      bytes_needed_list);
+		      bytes_needed_list);				// current list is full now
             bytes_in_list += bytes_needed_list;
             buffer_pos += bytes_needed_list;
             total_bytes += bytes_needed_list;
          }
          else
-         {
+         {	//rest of buffer fits into list. List may become full.
             if(sg_buf != NULL)
               memcpy(&sg_buf[bytes_in_list],
 		     &priv->rb[priv->curr_rbd_idx].rb[buffer_pos],
 		     bytes_in_buffer);
             bytes_in_list += bytes_in_buffer;
             total_bytes += bytes_in_buffer;
-
-            /* Step our buffer on one */
-            priv->rbd[priv->curr_rbd_idx].addr &= 
-	      ~(AT91_EMAC_RBD_ADDR_OWNER_SW);
-            priv->curr_rbd_idx++;
-            if(priv->curr_rbd_idx >= CYGNUM_DEVS_ETH_ARM_AT91_RX_BUFS)
-            {
-               priv->curr_rbd_idx = 0;
-            }
+         	// wee need a new buffer. Step our buffer on one
             buffer_pos = 0;
-         }
-      }
-   }
-}
+            priv->rbd[priv->curr_rbd_idx].addr &= ~(AT91_EMAC_RBD_ADDR_OWNER_SW);
+            priv->curr_rbd_idx = (priv->curr_rbd_idx + 1) % CYGNUM_DEVS_ETH_ARM_AT91_RX_BUFS;
+         } // if !bytes...
+      } // while(bytes...
+   } // for (i
+} // end at91_eth_recv
 
 // routine called to handle ethernet controller in polled mode
 static void 
 at91_eth_poll(struct eth_drv_sc *sc)
 {
