<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>change log for rtems (2011-06-11)</title>
</head>
<body text='#000000' bgcolor='#ffffff'>
<a name='cs1'></a>
<table border='0' cellspacing='0' cellpadding='5' width='100%' bgcolor='#eeeeee'>
<tr><td colspan='3' bgcolor='#dddddd'>
 <font color='#bb2222'><strong>joel</strong></font>
</td></tr>
<tr><td colspan='3' bgcolor='#dddddd'><pre>2011-06-10 Joel Sherrill <joel.sherrill@oarcorp.com>

        * psxtmtests_plan.csv: Add sleep and nanosleep cases.
</pre></td></tr>
<tr><td width='1%'><a href="http://www.rtems.com/cgi-bin/viewcvs.cgi//rtems/testsuites/psxtmtests/ChangeLog.diff?r1=text&tr1=1.6&r2=text&tr2=1.7&diff_format=h">M</a></td><td width='1%'>1.7</td><td width='100%'>testsuites/psxtmtests/ChangeLog</td></tr>
<tr><td width='1%'><a href="http://www.rtems.com/cgi-bin/viewcvs.cgi//rtems/testsuites/psxtmtests/psxtmtests_plan.csv.diff?r1=text&tr1=1.2&r2=text&tr2=1.3&diff_format=h">M</a></td><td width='1%'>1.3</td><td width='100%'>testsuites/psxtmtests/psxtmtests_plan.csv</td></tr>
</table>
<pre>
<font color='#006600'>diff -u rtems/testsuites/psxtmtests/ChangeLog:1.6 rtems/testsuites/psxtmtests/ChangeLog:1.7
--- rtems/testsuites/psxtmtests/ChangeLog:1.6   Wed Apr 20 11:22:14 2011
+++ rtems/testsuites/psxtmtests/ChangeLog       Fri Jun 10 08:19:26 2011
</font><font color='#997700'>@@ -1,3 +1,7 @@
</font><font color='#000088'>+2011-06-10    Joel Sherrill <joel.sherrill@oarcorp.com>
+
+       * psxtmtests_plan.csv: Add sleep and nanosleep cases.
+
</font> 2011-04-20        Joel Sherrill <joel.sherrill@oarcorp.com>
 
        * README, psxtmtests_plan.csv: Add more possible test cases.

<font color='#006600'>diff -u rtems/testsuites/psxtmtests/psxtmtests_plan.csv:1.2 rtems/testsuites/psxtmtests/psxtmtests_plan.csv:1.3
--- rtems/testsuites/psxtmtests/psxtmtests_plan.csv:1.2 Wed Apr 20 11:22:14 2011
+++ rtems/testsuites/psxtmtests/psxtmtests_plan.csv     Fri Jun 10 08:19:26 2011
</font><font color='#997700'>@@ -111,3 +111,9 @@
</font> "sem_post - thread waiting, no preempt",,,
 "sem_post - thread waiting, preempt",,,
 "sem_getvalue",,"psxtmtest_single",
<font color='#000088'>+
+"sleep - yield","psxsleep01","psxtmtest_single",
+"sleep - blocking","psxsleep02","psxtmtest_blocking",
+"nanosleep - yield","psxnanosleep01","psxtmtest_single",
+"nanosleep - blocking","psxnanosleep02","psxtmtest_blocking",
+
</font></pre>
<p> </p>
<a name='cs2'></a>
<table border='0' cellspacing='0' cellpadding='5' width='100%' bgcolor='#eeeeee'>
<tr><td colspan='3' bgcolor='#dddddd'>
 <font color='#bb2222'><strong>joel</strong></font>
 <font color='#225522'><em>(on branch rtems-4-10-branch)</em></font>
</td></tr>
<tr><td colspan='3' bgcolor='#dddddd'><pre>2011-06-10 Joel Sherrill <joel.sherrilL@OARcorp.com>

        PR 1812/filesystem
        * libfs/src/imfs/imfs_stat.c: stat() implementation for IMFS did not
        set st_blksize field. Set it based upon user configuration.
</pre></td></tr>
<tr><td width='1%'><a href="http://www.rtems.com/cgi-bin/viewcvs.cgi//rtems/cpukit/ChangeLog.diff?r1=text&tr1=1.2848&r2=text&tr2=1.2849&diff_format=h">M</a></td><td width='1%'>1.2849</td><td width='100%'>cpukit/ChangeLog</td></tr>
<tr><td width='1%'><a href="http://www.rtems.com/cgi-bin/viewcvs.cgi//rtems/cpukit/ChangeLog.diff?r1=text&tr1=1.1539.2.73&r2=text&tr2=1.1539.2.74&diff_format=h">M</a></td><td width='1%'>1.1539.2.74</td><td width='100%'>cpukit/ChangeLog</td></tr>
<tr><td width='1%'><a href="http://www.rtems.com/cgi-bin/viewcvs.cgi//rtems/cpukit/ChangeLog.diff?r1=text&tr1=1.2346.2.92&r2=text&tr2=1.2346.2.93&diff_format=h">M</a></td><td width='1%'>1.2346.2.93</td><td width='100%'>cpukit/ChangeLog</td></tr>
<tr><td width='1%'><a href="http://www.rtems.com/cgi-bin/viewcvs.cgi//rtems/cpukit/libfs/src/imfs/imfs_stat.c.diff?r1=text&tr1=1.14&r2=text&tr2=1.15&diff_format=h">M</a></td><td width='1%'>1.15</td><td width='100%'>cpukit/libfs/src/imfs/imfs_stat.c</td></tr>
<tr><td width='1%'><a href="http://www.rtems.com/cgi-bin/viewcvs.cgi//rtems/cpukit/libfs/src/imfs/imfs_stat.c.diff?r1=text&tr1=1.11&r2=text&tr2=1.11.6.1&diff_format=h">M</a></td><td width='1%'>1.11.6.1</td><td width='100%'>cpukit/libfs/src/imfs/imfs_stat.c</td></tr>
<tr><td width='1%'><a href="http://www.rtems.com/cgi-bin/viewcvs.cgi//rtems/cpukit/libfs/src/imfs/imfs_stat.c.diff?r1=text&tr1=1.14&r2=text&tr2=1.14.2.1&diff_format=h">M</a></td><td width='1%'>1.14.2.1</td><td width='100%'>cpukit/libfs/src/imfs/imfs_stat.c</td></tr>
</table>
<pre>
<font color='#006600'>diff -u rtems/cpukit/ChangeLog:1.2848 rtems/cpukit/ChangeLog:1.2849
--- rtems/cpukit/ChangeLog:1.2848       Wed Jun  8 11:13:33 2011
+++ rtems/cpukit/ChangeLog      Fri Jun 10 13:16:42 2011
</font><font color='#997700'>@@ -1,3 +1,9 @@
</font><font color='#000088'>+2011-06-10    Joel Sherrill <joel.sherrilL@OARcorp.com>
+
+       PR 1812/filesystem
+       * libfs/src/imfs/imfs_stat.c: stat() implementation for IMFS did not
+       set st_blksize field. Set it based upon user configuration.
+
</font> 2011-06-08        Joel Sherrill <joel.sherrill@oarcorp.com>
 
        * score/src/smp.c: Fix typo so this compiles.

<font color='#006600'>diff -u rtems/cpukit/ChangeLog:1.1539.2.73 rtems/cpukit/ChangeLog:1.1539.2.74
--- rtems/cpukit/ChangeLog:1.1539.2.73  Mon Apr  4 12:08:57 2011
+++ rtems/cpukit/ChangeLog      Fri Jun 10 13:17:20 2011
</font><font color='#997700'>@@ -1,3 +1,9 @@
</font><font color='#000088'>+2011-06-10    Joel Sherrill <joel.sherrilL@OARcorp.com>
+
+       PR 1812/filesystem
+       * libfs/src/imfs/imfs_stat.c: stat() implementation for IMFS did not
+       set st_blksize field. Set it based upon user configuration.
+
</font> 2011-04-04        Sebastien Bourdeauducq <sebastien.bourdeauducq@gmail.com>
 
        PR 1722/networking

<font color='#006600'>diff -u rtems/cpukit/ChangeLog:1.2346.2.92 rtems/cpukit/ChangeLog:1.2346.2.93
--- rtems/cpukit/ChangeLog:1.2346.2.92  Thu May 26 18:33:59 2011
+++ rtems/cpukit/ChangeLog      Fri Jun 10 13:17:01 2011
</font><font color='#997700'>@@ -1,3 +1,9 @@
</font><font color='#000088'>+2011-06-10    Joel Sherrill <joel.sherrilL@OARcorp.com>
+
+       PR 1812/filesystem
+       * libfs/src/imfs/imfs_stat.c: stat() implementation for IMFS did not
+       set st_blksize field. Set it based upon user configuration.
+
</font> 2011-05-27        Bo Hansen <mdboha@gmail.com>
 
        PR 1776/networking

<font color='#006600'>diff -u rtems/cpukit/libfs/src/imfs/imfs_stat.c:1.14 rtems/cpukit/libfs/src/imfs/imfs_stat.c:1.15
--- rtems/cpukit/libfs/src/imfs/imfs_stat.c:1.14        Sat May 15 01:29:55 2010
+++ rtems/cpukit/libfs/src/imfs/imfs_stat.c     Fri Jun 10 13:16:42 2011
</font><font color='#997700'>@@ -77,5 +77,7 @@
</font>   buf->st_mtime = the_jnode->stat_mtime;
   buf->st_ctime = the_jnode->stat_ctime;
 
<font color='#000088'>+  buf->st_blksize = imfs_rq_memfile_bytes_per_block;
+
</font>   return 0;
 }

<font color='#006600'>diff -u rtems/cpukit/libfs/src/imfs/imfs_stat.c:1.11 rtems/cpukit/libfs/src/imfs/imfs_stat.c:1.11.6.1
--- rtems/cpukit/libfs/src/imfs/imfs_stat.c:1.11        Sat Apr 17 03:34:41 2004
+++ rtems/cpukit/libfs/src/imfs/imfs_stat.c     Fri Jun 10 13:17:21 2011
</font><font color='#997700'>@@ -64,5 +64,7 @@
</font>   buf->st_mtime = the_jnode->stat_mtime;
   buf->st_ctime = the_jnode->stat_ctime;
 
<font color='#000088'>+  buf->st_blksize = imfs_rq_memfile_bytes_per_block;
+
</font>   return 0;
 }

<font color='#006600'>diff -u rtems/cpukit/libfs/src/imfs/imfs_stat.c:1.14 rtems/cpukit/libfs/src/imfs/imfs_stat.c:1.14.2.1
--- rtems/cpukit/libfs/src/imfs/imfs_stat.c:1.14        Sat May 15 01:29:55 2010
+++ rtems/cpukit/libfs/src/imfs/imfs_stat.c     Fri Jun 10 13:17:02 2011
</font><font color='#997700'>@@ -77,5 +77,7 @@
</font>   buf->st_mtime = the_jnode->stat_mtime;
   buf->st_ctime = the_jnode->stat_ctime;
 
<font color='#000088'>+  buf->st_blksize = imfs_rq_memfile_bytes_per_block;
+
</font>   return 0;
 }
</pre>
<p> </p>
<a name='cs3'></a>
<table border='0' cellspacing='0' cellpadding='5' width='100%' bgcolor='#eeeeee'>
<tr><td colspan='3' bgcolor='#dddddd'>
 <font color='#bb2222'><strong>sh</strong></font>
</td></tr>
<tr><td colspan='3' bgcolor='#dddddd'><pre>2011-06-10 Sebastian Huber <sebastian.huber@embedded-brains.de>

        * network/smsc9218i.c: Optimizations.
</pre></td></tr>
<tr><td width='1%'><a href="http://www.rtems.com/cgi-bin/viewcvs.cgi//rtems/c/src/lib/libbsp/powerpc/mpc55xxevb/ChangeLog.diff?r1=text&tr1=1.67&r2=text&tr2=1.68&diff_format=h">M</a></td><td width='1%'>1.68</td><td width='100%'>c/src/lib/libbsp/powerpc/mpc55xxevb/ChangeLog</td></tr>
<tr><td width='1%'><a href="http://www.rtems.com/cgi-bin/viewcvs.cgi//rtems/c/src/lib/libbsp/powerpc/mpc55xxevb/network/smsc9218i.c.diff?r1=text&tr1=1.7&r2=text&tr2=1.8&diff_format=h">M</a></td><td width='1%'>1.8</td><td width='100%'>c/src/lib/libbsp/powerpc/mpc55xxevb/network/smsc9218i.c</td></tr>
</table>
<pre>
<font color='#006600'>diff -u rtems/c/src/lib/libbsp/powerpc/mpc55xxevb/ChangeLog:1.67 rtems/c/src/lib/libbsp/powerpc/mpc55xxevb/ChangeLog:1.68
--- rtems/c/src/lib/libbsp/powerpc/mpc55xxevb/ChangeLog:1.67    Tue Jun  7 09:10:54 2011
+++ rtems/c/src/lib/libbsp/powerpc/mpc55xxevb/ChangeLog Fri Jun 10 02:06:14 2011
</font><font color='#997700'>@@ -1,3 +1,7 @@
</font><font color='#000088'>+2011-06-10    Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+       * network/smsc9218i.c: Optimizations.
+
</font> 2011-06-07        Sebastian Huber <sebastian.huber@embedded-brains.de>
 
        * Makefile.am: Added custom memcpy().

<font color='#006600'>diff -u rtems/c/src/lib/libbsp/powerpc/mpc55xxevb/network/smsc9218i.c:1.7 rtems/c/src/lib/libbsp/powerpc/mpc55xxevb/network/smsc9218i.c:1.8
--- rtems/c/src/lib/libbsp/powerpc/mpc55xxevb/network/smsc9218i.c:1.7   Tue Jun  7 04:14:06 2011
+++ rtems/c/src/lib/libbsp/powerpc/mpc55xxevb/network/smsc9218i.c       Fri Jun 10 02:06:14 2011
</font><font color='#997700'>@@ -28,6 +28,7 @@
</font> #include <mpc55xx/regs.h>
 
 #include <errno.h>
<font color='#000088'>+#include <assert.h>
</font> #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
<font color='#997700'>@@ -57,12 +58,12 @@
</font> #include <libcpu/powerpc-utility.h>
 #include <bsp/smsc9218i.h>
 
<font color='#880000'>-#include <rtems/status-checks.h>
-
</font> #if MCLBYTES != 2048
   #warning "unexpected MCLBYTES value"
 #endif
 
<font color='#000088'>+#define ASSERT_SC(sc) assert((sc) == RTEMS_SUCCESSFUL)
+
</font> #define SMSC9218I_EVENT_TX RTEMS_EVENT_1
 
 #define SMSC9218I_EVENT_TX_START RTEMS_EVENT_2
<font color='#997700'>@@ -75,20 +76,24 @@
</font> 
 #define SMSC9218I_EVENT_PHY RTEMS_EVENT_6
 
<font color='#880000'>-#define SMSC9218I_EVENT_EDMA RTEMS_EVENT_7
</font><font color='#000088'>+#define SMSC9218I_EVENT_DMA RTEMS_EVENT_7
</font> 
<font color='#880000'>-#define SMSC9218I_EVENT_EDMA_ERROR RTEMS_EVENT_8
</font><font color='#000088'>+#define SMSC9218I_EVENT_DMA_ERROR RTEMS_EVENT_8
</font> 
 /* Adjust by two bytes for proper IP header alignment */
 #define SMSC9218I_RX_DATA_OFFSET 2
 
<font color='#880000'>-#define SMSC9218I_TX_JOBS 128U
</font><font color='#000088'>+#define SMSC9218I_RX_JOBS 32
</font> 
<font color='#880000'>-#define SMSC9218I_TX_JOBS_MAX (SMSC9218I_TX_JOBS - 1U)
</font><font color='#000088'>+#define SMSC9218I_TX_JOBS 64
</font> 
 /* Maximum number of fragments per frame, see manual section 3.11.3.2 */
 #define SMSC9218I_TX_FRAGMENT_MAX 86
 
<font color='#000088'>+#if SMSC9218I_TX_JOBS > SMSC9218I_TX_FRAGMENT_MAX
+  #error "too many TX jobs"
+#endif
+
</font> #define SMSC9218I_IRQ_CFG_GLOBAL_ENABLE \
   (SMSC9218I_IRQ_CFG_IRQ_EN | SMSC9218I_IRQ_CFG_IRQ_TYPE)
 
<font color='#997700'>@@ -102,11 +107,11 @@
</font> 
 #define SMSC9218I_EDMA_TX_CHANNEL 48
 
<font color='#880000'>-#define SMSC9218I_EDMA_TX_TCD_BMF_LINK 0x10011
</font><font color='#000088'>+#define SMSC9218I_TCD_BMF_LINK 0x10011
</font> 
<font color='#880000'>-#define SMSC9218I_EDMA_TX_TCD_BMF_INTERRUPT 0x10003
</font><font color='#000088'>+#define SMSC9218I_TCD_BMF_LAST 0x10003
</font> 
<font color='#880000'>-#define SMSC9218I_EDMA_TX_TCD_BMF_CLEAR 0x10000
</font><font color='#000088'>+#define SMSC9218I_TCD_BMF_CLEAR 0x10000
</font> 
 #define SMSC9218I_ERROR_INTERRUPTS \
   (SMSC9218I_INT_TXSO \
<font color='#997700'>@@ -114,6 +119,8 @@
</font>      | SMSC9218I_INT_RXE \
      | SMSC9218I_INT_TXE)
 
<font color='#000088'>+#define SMSC9218I_UNLIKELY(x) __builtin_expect((x), 0)
+
</font> #ifdef DEBUG
   #define SMSC9218I_PRINTF(...) printf(__VA_ARGS__)
   #define SMSC9218I_PRINTK(...) printk(__VA_ARGS__)
<font color='#997700'>@@ -137,21 +144,24 @@
</font>   rtems_id transmit_task;
   mpc55xx_edma_channel_entry edma_receive;
   mpc55xx_edma_channel_entry edma_transmit;
<font color='#000088'>+  unsigned phy_interrupts;
</font>   unsigned received_frames;
<font color='#880000'>-  unsigned receive_interrupts;
-  unsigned transmitted_frames;
-  unsigned transmit_interrupts;
</font>   unsigned receiver_errors;
<font color='#000088'>+  unsigned receive_interrupts;
+  unsigned receive_dma_interrupts;
</font>   unsigned receive_too_long_errors;
   unsigned receive_collision_errors;
   unsigned receive_crc_errors;
<font color='#880000'>-  unsigned receive_edma_errors;
</font><font color='#000088'>+  unsigned receive_dma_errors;
</font>   unsigned receive_drop;
   unsigned receive_watchdog_timeouts;
<font color='#000088'>+  unsigned transmitted_frames;
</font>   unsigned transmitter_errors;
<font color='#000088'>+  unsigned transmit_interrupts;
+  unsigned transmit_dma_interrupts;
</font>   unsigned transmit_status_overflows;
   unsigned transmit_frame_errors;
<font color='#880000'>-  unsigned transmit_edma_errors;
</font><font color='#000088'>+  unsigned transmit_dma_errors;
</font> } smsc9218i_driver_entry;
 
 typedef struct {
<font color='#997700'>@@ -166,37 +176,39 @@
</font>   struct mbuf *fragment_table [SMSC9218I_TX_JOBS];
   struct mbuf *frame;
   struct mbuf *next_fragment;
<font color='#880000'>-  unsigned empty_index;
-  unsigned transfer_index;
-  unsigned transfer_last_index;
-  unsigned todo_index;
-  unsigned empty;
-  unsigned transfer;
-  unsigned todo;
</font><font color='#000088'>+  int empty_index;
+  int transfer_index;
+  int transfer_last_index;
+  int todo_index;
+  int empty;
+  int transfer;
+  int todo;
</font>   uint32_t frame_length;
   uint32_t command_b;
   uint16_t tag;
   bool done;
<font color='#880000'>-  unsigned fixme_tiny_fragments;
-  unsigned fixme_too_many;
</font><font color='#000088'>+  unsigned frame_compact_count;
</font> } smsc9218i_transmit_job_control;
 
<font color='#880000'>-static void smsc9218i_edma_done(
-  mpc55xx_edma_channel_entry *e,
-  uint32_t error_status
-)
-{
-  rtems_event_set event = error_status == 0 ?
-    SMSC9218I_EVENT_EDMA : SMSC9218I_EVENT_EDMA_ERROR;
</font><font color='#000088'>+typedef struct {
+  struct tcd_t tcd_table [SMSC9218I_RX_JOBS];
+  struct mbuf *mbuf_table [SMSC9218I_RX_JOBS];
+  int consume;
+  int done;
+  int produce;
+} smsc9218i_receive_job_control;
</font> 
<font color='#880000'>-  SMSC9218I_PRINTK(
-    "edma: id = 0x%08x, error status = 0x%08x\n",
-    e->id,
-    error_status
-  );
</font><font color='#000088'>+static smsc9218i_receive_job_control smsc_rx_jc __attribute__((aligned (32)));
</font> 
<font color='#880000'>-  rtems_event_send(e->id, event);
-}
</font><font color='#000088'>+static void smsc9218i_transmit_dma_done(
+  mpc55xx_edma_channel_entry *channel_entry,
+  uint32_t error_status
+);
+
+static void smsc9218i_receive_dma_done(
+  mpc55xx_edma_channel_entry *e,
+  uint32_t error_status
+);
</font> 
 static smsc9218i_driver_entry smsc9218i_driver_data = {
   .state = SMSC9218I_NOT_INITIALIZED,
<font color='#997700'>@@ -204,12 +216,12 @@
</font>   .transmit_task = RTEMS_ID_NONE,
   .edma_receive = {
     .channel = SMSC9218I_EDMA_RX_CHANNEL,
<font color='#880000'>-    .done = smsc9218i_edma_done,
</font><font color='#000088'>+    .done = smsc9218i_receive_dma_done,
</font>     .id = RTEMS_ID_NONE
   },
   .edma_transmit = {
     .channel = SMSC9218I_EDMA_TX_CHANNEL,
<font color='#880000'>-    .done = smsc9218i_edma_done,
</font><font color='#000088'>+    .done = smsc9218i_transmit_dma_done,
</font>     .id = RTEMS_ID_NONE
   }
 };
<font color='#997700'>@@ -356,8 +368,8 @@
</font> 
   reg = regs->rx_fifo_inf;
   printf(
<font color='#880000'>-    "rx_fifo_inf: 0x%08" PRIx32 " (status unused = %" PRIu32
-      ", data unused = %" PRIu32 ")\n",
</font><font color='#000088'>+    "rx_fifo_inf: 0x%08" PRIx32 " (status used = %" PRIu32
+      ", data used = %" PRIu32 ")\n",
</font>     SMSC9218I_SWAP(reg),
     SMSC9218I_RX_FIFO_INF_GET_SUSED(reg),
     SMSC9218I_RX_FIFO_INF_GET_DUSED(reg)
<font color='#997700'>@@ -425,12 +437,186 @@
</font> }
 #endif
 
<font color='#000088'>+static void smsc9218i_flush_tcd(struct tcd_t *tcd)
+{
+  ppc_data_cache_block_store(tcd);
+}
+
+static uint32_t smsc9218i_align_up(uint32_t val)
+{
+  return 4U + ((val - 1U) & ~0x3U);
+}
+
+static void smsc9218i_discard_frame(
+  smsc9218i_driver_entry *e,
+  volatile smsc9218i_registers *regs,
+  uint32_t rx_fifo_status,
+  uint32_t frame_length,
+  uint32_t data_length
+)
+{
+  /* Update error counters */
+  if ((rx_fifo_status & SMSC9218I_RX_STS_ERROR_TOO_LONG) != 0) {
+    ++e->receive_too_long_errors;
+  }
+  if ((rx_fifo_status & SMSC9218I_RX_STS_ERROR_COLLISION) != 0) {
+    ++e->receive_collision_errors;
+  }
+  if ((rx_fifo_status & SMSC9218I_RX_STS_ERROR_CRC) != 0) {
+    ++e->receive_crc_errors;
+  }
+
+  /* Discard frame */
+  if (frame_length > 16) {
+    /* Fast forward */
+    regs->rx_dp_ctl = SMSC9218I_RX_DP_CTRL_FFWD;
+
+    while ((regs->rx_dp_ctl & SMSC9218I_RX_DP_CTRL_FFWD) != 0) {
+      /* Wait */
+    }
+  } else {
+    uint32_t len = data_length / 4;
+    uint32_t i = 0;
+
+    /* Discard data */
+    for (i = 0; i < len; ++i) {
+      regs->rx_fifo_data;
+    }
+  }
+}
+
+static void smsc9218i_setup_receive_dma(
+  smsc9218i_driver_entry *e,
+  volatile smsc9218i_registers *regs,
+  smsc9218i_receive_job_control *jc
+)
+{
+  int c = jc->consume;
+  int p = jc->produce;
+  int np = (p + 1) % SMSC9218I_RX_JOBS;
+  struct tcd_t *first = &jc->tcd_table [p];
+  struct tcd_t *last = NULL;
+
+  while (np != c) {
+    uint32_t rx_fifo_inf = 0;
+    uint32_t status_used = 0;
+
+    /* Clear FIFO level status */
+    regs->int_sts = SMSC9218I_INT_RSFL;
+
+    /* Next FIFO status */
+    rx_fifo_inf = regs->rx_fifo_inf;
+    status_used = SMSC9218I_RX_FIFO_INF_GET_SUSED(rx_fifo_inf);
+
+    if (status_used > 0) {
+      uint32_t status = regs->rx_fifo_status;
+      uint32_t frame_length = SMSC9218I_RX_STS_GET_LENGTH(status);
+      uint32_t data_length = smsc9218i_align_up(
+        SMSC9218I_RX_DATA_OFFSET + frame_length
+      );
+      bool frame_ok = (status & SMSC9218I_RX_STS_ERROR) == 0;
+
+      if (frame_ok) {
+        struct mbuf *m = jc->mbuf_table [p];
+        int mbuf_length = (int) frame_length - ETHER_HDR_LEN - ETHER_CRC_LEN;
+        struct tcd_t *current = &jc->tcd_table [p];
+
+        m->m_len = mbuf_length;
+        m->m_pkthdr.len = mbuf_length;
+
+        current->NBYTES = data_length;
+        smsc9218i_flush_tcd(current);
+
+        last = current;
+        p = np;
+        np = (p + 1) % SMSC9218I_RX_JOBS;
+      } else {
+        smsc9218i_discard_frame(e, regs, status, frame_length, data_length);
+      }
+    } else {
+      break;
+    }
+  }
+
+  jc->produce = p;
+
+  if (last != NULL) {
+    volatile struct tcd_t *channel = &EDMA.TCD [e->edma_receive.channel];
+
+    /* Setup last TCD */
+    last->BMF.R = SMSC9218I_TCD_BMF_LAST;
+    smsc9218i_flush_tcd(last);
+    ppc_synchronize_data();
+
+    /* Start eDMA transfer */
+    channel->SADDR = first->SADDR;
+    channel->SDF.R = first->SDF.R;
+    channel->NBYTES = first->NBYTES;
+    channel->SLAST = first->SLAST;
+    channel->DADDR = first->DADDR;
+    channel->CDF.R = first->CDF.R;
+    channel->DLAST_SGA = first->DLAST_SGA;
+    channel->BMF.R = SMSC9218I_TCD_BMF_CLEAR;
+    channel->BMF.R = first->BMF.R;
+  }
+}
+
+static void smsc9218i_receive_dma_done(
+  mpc55xx_edma_channel_entry *channel_entry,
+  uint32_t error_status
+)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  smsc9218i_driver_entry *e = &smsc9218i_driver_data;
+  volatile smsc9218i_registers *const regs = smsc9218i;
+  smsc9218i_receive_job_control *jc = &smsc_rx_jc;
+
+  SMSC9218I_PRINTK(
+    "edma: id = 0x%08x, error status = 0x%08x\n",
+    channel_entry->id,
+    error_status
+  );
+
+  ++e->receive_dma_interrupts;
+  if (SMSC9218I_UNLIKELY(error_status != 0)) {
+    ++e->receive_dma_errors;
+  }
+
+  sc = rtems_event_send(channel_entry->id, SMSC9218I_EVENT_DMA);
+  ASSERT_SC(sc);
+
+  jc->done = jc->produce;
+
+  smsc9218i_setup_receive_dma(e, regs, jc);
+}
+
+static void smsc9218i_transmit_dma_done(
+  mpc55xx_edma_channel_entry *channel_entry,
+  uint32_t error_status
+)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  smsc9218i_driver_entry *e = &smsc9218i_driver_data;
+  rtems_event_set event = error_status == 0 ?
+    SMSC9218I_EVENT_DMA : SMSC9218I_EVENT_DMA_ERROR;
+
+  SMSC9218I_PRINTK(
+    "edma: id = 0x%08x, error status = 0x%08x\n",
+    channel_entry->id,
+    error_status
+  );
+
+  ++e->transmit_dma_interrupts;
+
+  sc = rtems_event_send(channel_entry->id, event);
+  ASSERT_SC(sc);
+}
+
</font> static void smsc9218i_interrupt_handler(void *arg)
 {
<font color='#000088'>+  rtems_status_code sc = RTEMS_SUCCESSFUL;
</font>   smsc9218i_driver_entry *e = (smsc9218i_driver_entry *) arg;
   volatile smsc9218i_registers *const regs = smsc9218i;
<font color='#880000'>-  rtems_event_set re = 0;
-  rtems_event_set te = 0;
</font>   uint32_t int_en = regs->int_en;
   uint32_t int_sts = regs->int_sts & int_en;
   #ifdef DEBUG
<font color='#997700'>@@ -455,7 +641,7 @@
</font>   regs->int_sts = int_sts;
 
   /* Error interrupts */
<font color='#880000'>-  if ((int_sts & SMSC9218I_ERROR_INTERRUPTS) != 0) {
</font><font color='#000088'>+  if (SMSC9218I_UNLIKELY((int_sts & SMSC9218I_ERROR_INTERRUPTS) != 0)) {
</font>     if ((int_sts & SMSC9218I_INT_TXSO) != 0) {
       ++e->transmit_status_overflows;
     }
<font color='#997700'>@@ -472,34 +658,29 @@
</font> 
   /* Check receive interrupts */
   if ((int_sts & SMSC9218I_INT_RSFL) != 0) {
<font color='#000088'>+    smsc9218i_receive_job_control *jc = &smsc_rx_jc;
+
</font>     int_en &= ~SMSC9218I_INT_RSFL;
<font color='#880000'>-    re = SMSC9218I_EVENT_RX;
</font><font color='#000088'>+    ++e->receive_interrupts;
+    smsc9218i_setup_receive_dma(e, regs, jc);
</font>   }
 
   /* Check PHY interrupts */
<font color='#880000'>-  if ((int_sts & SMSC9218I_INT_PHY) != 0) {
</font><font color='#000088'>+  if (SMSC9218I_UNLIKELY((int_sts & SMSC9218I_INT_PHY) != 0)) {
+    SMSC9218I_PRINTK("interrupt: phy\n");
</font>     int_en &= ~SMSC9218I_INT_PHY;
<font color='#880000'>-    re |= SMSC9218I_EVENT_PHY;
-  }
-
-  /* Send events to receive task */
-  if (re != 0) {
-    SMSC9218I_PRINTK("interrupt: receive: 0x%08x\n", re);
-    ++e->receive_interrupts;
-    (void) rtems_event_send(e->receive_task, re);
</font><font color='#000088'>+    ++e->phy_interrupts;
+    sc = rtems_event_send(e->receive_task, SMSC9218I_EVENT_PHY);
+    ASSERT_SC(sc);
</font>   }
 
   /* Check transmit interrupts */
   if ((int_sts & SMSC9218I_INT_TDFA) != 0) {
<font color='#000088'>+    SMSC9218I_PRINTK("interrupt: transmit\n");
</font>     int_en &= ~SMSC9218I_INT_TDFA;
<font color='#880000'>-    te = SMSC9218I_EVENT_TX;
-  }
-
-  /* Send events to transmit task */
-  if (te != 0) {
-    SMSC9218I_PRINTK("interrupt: transmit: 0x%08x\n", te);
</font>     ++e->transmit_interrupts;
<font color='#880000'>-    (void) rtems_event_send(e->transmit_task, te);
</font><font color='#000088'>+    sc = rtems_event_send(e->transmit_task, SMSC9218I_EVENT_TX);
+    ASSERT_SC(sc);
</font>   }
 
   /* Update interrupt enable */
<font color='#997700'>@@ -509,17 +690,6 @@
</font>   regs->irq_cfg = SMSC9218I_IRQ_CFG_GLOBAL_ENABLE;
 }
 
<font color='#880000'>-static void smsc9218i_enable_receive_interrupts(
-  volatile smsc9218i_registers *regs
-)
-{
-  rtems_interrupt_level level;
-
-  rtems_interrupt_disable(level);
-  regs->int_en |= SMSC9218I_INT_RSFL;
-  rtems_interrupt_enable(level);
-}
-
</font> static void smsc9218i_enable_transmit_interrupts(
   volatile smsc9218i_registers *regs
 )
<font color='#997700'>@@ -580,50 +750,121 @@
</font>   smsc9218i_mac_write(regs, SMSC9218I_MAC_CR, mac_cr);
 }
 
<font color='#880000'>-static struct mbuf *smsc9218i_new_mbuf(struct ifnet *ifp)
</font><font color='#000088'>+static void smsc9218i_new_mbuf(
+  struct ifnet *ifp,
+  smsc9218i_receive_job_control *jc,
+  int i
+)
</font> {
   struct mbuf *m = m_gethdr(M_WAIT, MT_DATA);
<font color='#000088'>+  struct tcd_t *tcd = &jc->tcd_table [i];
+  char *data = NULL;
</font> 
   m->m_pkthdr.rcvif = ifp;
   MCLGET(m, M_WAIT);
 
<font color='#880000'>-  return m;
</font><font color='#000088'>+  data = mtod(m, char *);
+  m->m_data = data + SMSC9218I_RX_DATA_OFFSET + ETHER_HDR_LEN;
+
+  jc->mbuf_table [i] = m;
+
+  tcd->DADDR = (uint32_t) data;
+  tcd->BMF.R = SMSC9218I_TCD_BMF_LINK;
+
+  /* FIXME: This is maybe a problem in case of a lot of small frames */
+  rtems_cache_invalidate_multiple_data_lines(
+    data,
+    SMSC9218I_RX_DATA_OFFSET + ETHER_HDR_LEN + ETHERMTU + ETHER_CRC_LEN
+  );
</font> }
 
<font color='#880000'>-static void smsc9218i_receive_task(void *arg)
</font><font color='#000088'>+static void smsc9218i_init_receive_jobs(
+  smsc9218i_driver_entry *e,
+  volatile smsc9218i_registers *regs,
+  smsc9218i_receive_job_control *jc
+)
</font> {
   rtems_status_code sc = RTEMS_SUCCESSFUL;
<font color='#880000'>-  rtems_event_set events = 0;
-  smsc9218i_driver_entry *e = (smsc9218i_driver_entry *) arg;
</font>   struct ifnet *ifp = &e->arpcom.ac_if;
<font color='#880000'>-  volatile smsc9218i_registers *const regs = smsc9218i;
-  volatile struct tcd_t *tcd = &EDMA.TCD [e->edma_receive.channel];
-  struct tcd_t tcd_init = EDMA_TCD_DEFAULT;
-  uint32_t mac_cr = 0;
-
-  SMSC9218I_PRINTF("%s\n", __func__);
</font><font color='#000088'>+  int i = 0;
</font> 
   /* Obtain receive eDMA channel */
   e->edma_receive.id = e->receive_task;
   sc = mpc55xx_edma_obtain_channel(&e->edma_receive);
<font color='#880000'>-  RTEMS_CLEANUP_SC(sc, cleanup, "obtain receive eDMA channel");
</font><font color='#000088'>+  ASSERT_SC(sc);
+
+  for (i = 0; i < SMSC9218I_RX_JOBS; ++i) {
+    struct tcd_t *tcd = &jc->tcd_table [i];
+    struct tcd_t *next_tcd = &jc->tcd_table [(i + 1) % SMSC9218I_RX_JOBS];
+
+    tcd->SADDR = (uint32_t) &regs->rx_fifo_data;
+    tcd->SDF.B.SSIZE = 0x2;
+    tcd->SDF.B.DSIZE = 0x2;
+    tcd->CDF.B.CITER = 1;
+    tcd->CDF.B.DOFF = 4;
+    tcd->DLAST_SGA = (int32_t) next_tcd;
+
+    smsc9218i_new_mbuf(ifp, jc, i);
+  }
+}
+
+static void smsc9218i_ether_input(
+  smsc9218i_driver_entry *e,
+  volatile smsc9218i_registers *regs,
+  smsc9218i_receive_job_control *jc
+)
+{
+  rtems_interrupt_level level;
+  struct ifnet *ifp = &e->arpcom.ac_if;
+  int c = jc->consume;
+  int d = jc->done;
+
+  while (c != d) {
+    struct mbuf *m = jc->mbuf_table [c];
+    struct ether_header *eh = (struct ether_header *)
+      (mtod(m, char *) - ETHER_HDR_LEN);
+
+    ++e->received_frames;
+    ether_input(ifp, eh, m);
+    smsc9218i_new_mbuf(ifp, jc, c);
+
+    c = (c + 1) % SMSC9218I_RX_JOBS;
+  }
+
+  jc->consume = c;
+
+  rtems_interrupt_disable(level);
+  /* Enabling the receive interrupts while the DMA is active leads to chaos */
+  if (c == jc->produce) {
+    regs->int_en |= SMSC9218I_INT_RSFL;
+  }
+  rtems_interrupt_enable(level);
+}
+
+static void smsc9218i_receive_task(void *arg)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  rtems_interrupt_level level;
+  smsc9218i_receive_job_control *jc = &smsc_rx_jc;
+  smsc9218i_driver_entry *e = (smsc9218i_driver_entry *) arg;
+  volatile smsc9218i_registers *const regs = smsc9218i;
+  uint32_t mac_cr = 0;
</font> 
<font color='#880000'>-  /* Setup receive eDMA channel */
-  tcd_init.SDF.B.SSIZE = 2;
-  tcd_init.SDF.B.DSIZE = 2;
-  tcd_init.SADDR = (uint32_t) &regs->rx_fifo_data;
-  *tcd = tcd_init;
</font><font color='#000088'>+  smsc9218i_init_receive_jobs(e, regs, jc);
</font> 
   /* Configure receiver */
   regs->rx_cfg = SMSC9218I_RX_CFG_END_ALIGN_4
     | SMSC9218I_RX_CFG_DOFF(SMSC9218I_RX_DATA_OFFSET);
 
   /* Enable MAC receiver */
<font color='#880000'>-  mac_cr = smsc9218i_mac_read(regs, SMSC9218I_MAC_CR) | SMSC9218I_MAC_CR_RXEN;
</font><font color='#000088'>+  mac_cr = smsc9218i_mac_read(regs, SMSC9218I_MAC_CR);
+  mac_cr |= SMSC9218I_MAC_CR_RXEN;
</font>   smsc9218i_mac_write(regs, SMSC9218I_MAC_CR, mac_cr);
 
   /* Enable receive interrupts */
<font color='#880000'>-  smsc9218i_enable_receive_interrupts(regs);
</font><font color='#000088'>+  rtems_interrupt_disable(level);
+  regs->int_en |= SMSC9218I_INT_RSFL;
+  rtems_interrupt_enable(level);
</font> 
   /* Enable PHY interrupts */
   smsc9218i_phy_write(
<font color='#997700'>@@ -633,155 +874,25 @@
</font>   );
   smsc9218i_enable_phy_interrupts(regs);
 
<font color='#880000'>-  SMSC9218I_PRINTF(
-    "rx: phy_isr = 0x%08" PRIx32 ", phy_imr = 0x%08" PRIx32 "\n",
-    smsc9218i_phy_read(regs, SMSC9218I_PHY_ISR),
-    smsc9218i_phy_read(regs, SMSC9218I_PHY_IMR)
-  );
-
-  /* Main event loop */
</font>   while (true) {
<font color='#880000'>-    uint32_t rx_fifo_inf = 0;
-    uint32_t status_used = 0;
</font><font color='#000088'>+    rtems_event_set events;
</font> 
<font color='#880000'>-    /* Wait for events */
</font>     sc = rtems_bsdnet_event_receive(
<font color='#880000'>-      SMSC9218I_EVENT_RX | SMSC9218I_EVENT_PHY,
</font><font color='#000088'>+      SMSC9218I_EVENT_DMA | SMSC9218I_EVENT_PHY,
</font>       RTEMS_EVENT_ANY | RTEMS_WAIT,
       RTEMS_NO_TIMEOUT,
       &events
     );
<font color='#880000'>-    RTEMS_CLEANUP_SC(sc, cleanup, "wait for events");
</font><font color='#000088'>+    ASSERT_SC(sc);
</font> 
<font color='#880000'>-    if ((events & SMSC9218I_EVENT_PHY) != 0) {
-      smsc9218i_media_status_change(e, regs);
</font><font color='#000088'>+    if ((events & SMSC9218I_EVENT_DMA) != 0) {
+      smsc9218i_ether_input(e, regs, jc);
</font>     }
 
<font color='#880000'>-    rx_fifo_inf = regs->rx_fifo_inf;
-    status_used = SMSC9218I_RX_FIFO_INF_GET_SUSED(rx_fifo_inf);
-
-    SMSC9218I_PRINTF(
-      "rx: wake up: events = 0x%08" PRIx32 ", status used = %" PRIu32 "\n",
-      events,
-      status_used
-    );
-
-    while (status_used > 0) {
-      uint32_t rx_fifo_status = regs->rx_fifo_status;
-      uint32_t frame_length = SMSC9218I_RX_STS_GET_LENGTH(rx_fifo_status);
-      uint32_t data_length = frame_length + SMSC9218I_RX_DATA_OFFSET;
-      uint32_t data_misalign = data_length % 4;
-
-      /* Align data length on four byte boundary */
-      if (data_misalign > 0) {
-        data_length += 4 - data_misalign;
-      }
-
-      SMSC9218I_PRINTF(
-        "rx: status = 0x%08" PRIx32 ", frame length = %" PRIu32
-          ", data length = %" PRIu32 ", data used = %" PRIu32 "\n",
-        SMSC9218I_SWAP(rx_fifo_status),
-        frame_length,
-        data_length,
-        SMSC9218I_RX_FIFO_INF_GET_DUSED(rx_fifo_inf)
-      );
-
-      if ((rx_fifo_status & SMSC9218I_RX_STS_ERROR) == 0) {
-        struct mbuf *m = smsc9218i_new_mbuf(ifp);
-        struct ether_header *eh = (struct ether_header *)
-          (mtod(m, char *) + SMSC9218I_RX_DATA_OFFSET);
-        int mbuf_length = (int) frame_length - ETHER_HDR_LEN - ETHER_CRC_LEN;
-        char *data = mtod(m, char *);
-
-        /* Update mbuf */
-        m->m_len = mbuf_length;
-        m->m_pkthdr.len = mbuf_length;
-        m->m_data = data + ETHER_HDR_LEN + SMSC9218I_RX_DATA_OFFSET;
-
-        /* Invalidate data cache */
-        rtems_cache_invalidate_multiple_data_lines(data, data_length);
-
-        /* Start eDMA transfer */
-        tcd->DADDR = (uint32_t) data;
-        tcd->NBYTES = data_length;
-        tcd->CDF.R = SMSC9218I_EDMA_RX_TCD_CDF;
-        tcd->BMF.R = SMSC9218I_EDMA_RX_TCD_BMF;
-
-        /* Wait for eDMA events */
-        sc = rtems_bsdnet_event_receive(
-          SMSC9218I_EVENT_EDMA | SMSC9218I_EVENT_EDMA_ERROR,
-          RTEMS_EVENT_ANY | RTEMS_WAIT,
-          RTEMS_NO_TIMEOUT,
-          &events
-        );
-        RTEMS_CHECK_SC_TASK(sc, "wait for eDMA events");
-
-        if ((events & SMSC9218I_EVENT_EDMA_ERROR) == 0) {
-          /* Hand over */
-          ether_input(ifp, eh, m);
-
-          /* Increment received frames counter */
-          ++e->received_frames;
-        } else {
-          /* Increment receive eDMA error counter */
-          ++e->receive_edma_errors;
-        }
-
-        SMSC9218I_PRINTF("rx: eDMA done\n");
-      } else {
-        SMSC9218I_PRINTF("rx: error\n");
-
-        /* Update error counters */
-        if ((rx_fifo_status & SMSC9218I_RX_STS_ERROR_TOO_LONG) != 0) {
-          ++e->receive_too_long_errors;
-        }
-        if ((rx_fifo_status & SMSC9218I_RX_STS_ERROR_COLLISION) != 0) {
-          ++e->receive_collision_errors;
-        }
-        if ((rx_fifo_status & SMSC9218I_RX_STS_ERROR_CRC) != 0) {
-          ++e->receive_crc_errors;
-        }
-
-        /* Discard frame */
-        if (frame_length > 16) {
-          /* Fast forward */
-          regs->rx_dp_ctl = SMSC9218I_RX_DP_CTRL_FFWD;
-
-          while ((regs->rx_dp_ctl & SMSC9218I_RX_DP_CTRL_FFWD) != 0) {
-            /* Wait */
-          }
-        } else {
-          uint32_t len = data_length / 4;
-          uint32_t i = 0;
-
-          /* Discard data */
-          for (i = 0; i < len; ++i) {
-            regs->rx_fifo_data;
-          }
-        }
-      }
-
-      /* Clear FIFO level status */
-      regs->int_sts = SMSC9218I_INT_RSFL;
-
-      /* Next FIFO status */
-      rx_fifo_inf = regs->rx_fifo_inf;
-      status_used = SMSC9218I_RX_FIFO_INF_GET_SUSED(rx_fifo_inf);
</font><font color='#000088'>+    if ((events & SMSC9218I_EVENT_PHY) != 0) {
+      smsc9218i_media_status_change(e, regs);
</font>     }
<font color='#880000'>-
-    SMSC9218I_PRINTF("rx: done\n");
-
-    /* Nothing to do, enable receive interrupts */
-    smsc9218i_enable_receive_interrupts(regs);
</font>   }
<font color='#880000'>-
-cleanup:
-
-  /* Release network semaphore */
-  rtems_bsdnet_semaphore_release();
-
-  /* Terminate self */
-  (void) rtems_task_delete(RTEMS_SELF);
</font> }
 
 #if defined(DEBUG)
<font color='#997700'>@@ -791,8 +902,8 @@
</font> )
 {
   char out [SMSC9218I_TX_JOBS + 1];
<font color='#880000'>-  unsigned c = 0;
-  unsigned s = 0;
</font><font color='#000088'>+  int c = 0;
+  int s = 0;
</font> 
   out [SMSC9218I_TX_JOBS] = '\0';
 
<font color='#997700'>@@ -803,11 +914,7 @@
</font>   while (s > 0) {
     out [c] = 'E';
     --s;
<font color='#880000'>-    if (c < SMSC9218I_TX_JOBS_MAX) {
-      ++c;
-    } else {
-      c = 0;
-    }
</font><font color='#000088'>+    c = (c + 1) % SMSC9218I_TX_JOBS;
</font>   }
 
   c = jc->transfer_index;
<font color='#997700'>@@ -815,11 +922,7 @@
</font>   while (s > 0) {
     out [c] = 'T';
     --s;
<font color='#880000'>-    if (c < SMSC9218I_TX_JOBS_MAX) {
-      ++c;
-    } else {
-      c = 0;
-    }
</font><font color='#000088'>+    c = (c + 1) % SMSC9218I_TX_JOBS;
</font>   }
 
   c = jc->empty_index;
<font color='#997700'>@@ -827,11 +930,7 @@
</font>   while (s > 0) {
     out [c] = 'D';
     --s;
<font color='#880000'>-    if (c < SMSC9218I_TX_JOBS_MAX) {
-      ++c;
-    } else {
-      c = 0;
-    }
</font><font color='#000088'>+    c = (c + 1) % SMSC9218I_TX_JOBS;
</font>   }
 
   printf(
<font color='#997700'>@@ -845,6 +944,35 @@
</font> }
 #endif /* defined(DEBUG) */
 
<font color='#000088'>+static struct mbuf *smsc9218i_compact_frame(
+  smsc9218i_transmit_job_control *jc,
+  uint32_t frame_length
+)
+{
+  struct mbuf *old_m = jc->frame;
+  struct mbuf *new_m = m_gethdr(M_WAIT, MT_DATA);
+  char *data = NULL;
+
+  ++jc->frame_compact_count;
+
+  MCLGET(new_m, M_WAIT);
+  data = mtod(new_m, char *);
+
+  new_m->m_len = (int) frame_length;
+  new_m->m_pkthdr.len = (int) frame_length;
+
+  while (old_m != NULL) {
+    size_t len = (size_t) old_m->m_len;
+    memcpy(data, mtod(old_m, void *), len);
+    data += len;
+    old_m = m_free(old_m);
+  }
+
+  jc->frame = new_m;
+
+  return new_m;
+}
+
</font> static struct mbuf *smsc9218i_next_transmit_fragment(
   struct ifnet *ifp,
   smsc9218i_transmit_job_control *jc
<font color='#997700'>@@ -867,6 +995,7 @@
</font>       struct mbuf *p = NULL;
       uint32_t frame_length = 0;
       unsigned fragments = 0;
<font color='#000088'>+      bool tiny = false;
</font> 
       /* Calculate frame length and fragment number */
       do {
<font color='#997700'>@@ -875,10 +1004,7 @@
</font>         if (len > 0) {
           ++fragments;
           frame_length += (uint32_t) len;
<font color='#880000'>-
-          if (len < 4) {
-            ++jc->fixme_tiny_fragments;
-          }
</font><font color='#000088'>+          tiny = tiny || len < 4;
</font> 
           /* Next fragment */
           p = n;
<font color='#997700'>@@ -896,8 +1022,9 @@
</font>         }
       } while (n != NULL);
 
<font color='#880000'>-      if (fragments > SMSC9218I_TX_FRAGMENT_MAX) {
-        ++jc->fixme_too_many;
</font><font color='#000088'>+      if (SMSC9218I_UNLIKELY(tiny || fragments > SMSC9218I_TX_JOBS)) {
+        fragments = 1;
+        m = smsc9218i_compact_frame(jc, frame_length);
</font>       }
 
       /* Set frame length */
<font color='#997700'>@@ -910,13 +1037,13 @@
</font>       ++jc->tag;
 
       /* Command B */
<font color='#880000'>-      jc->command_b = SMSC9218I_TX_B_TAG(jc->tag)
</font><font color='#000088'>+      jc->command_b = ((uint32_t) SMSC9218I_TX_B_TAG(jc->tag))
</font>         | SMSC9218I_TX_B_FRAME_LENGTH(jc->frame_length);
 
       SMSC9218I_PRINTF(
<font color='#880000'>-        "tx: next frame: tag = %u, frame length = %" PRIu32
</font><font color='#000088'>+        "tx: next frame: tag = %i, frame length = %" PRIu32
</font>           ", fragments = %u\n",
<font color='#880000'>-        (unsigned) jc->tag,
</font><font color='#000088'>+        jc->tag,
</font>         frame_length,
         fragments
       );
<font color='#997700'>@@ -943,11 +1070,11 @@
</font>   struct ifnet *ifp
 )
 {
<font color='#880000'>-  unsigned n = jc->empty;
</font><font color='#000088'>+  int n = jc->empty;
</font> 
   if (n > 0) {
<font color='#880000'>-    unsigned c = jc->todo_index;
-    unsigned i = 0;
</font><font color='#000088'>+    int c = jc->todo_index;
+    int i = 0;
</font> 
     #ifdef DEBUG
       smsc9218i_transmit_job_dump(jc, "create");
<font color='#997700'>@@ -997,11 +1124,7 @@
</font>         break;
       }
 
<font color='#880000'>-      if (c < SMSC9218I_TX_JOBS_MAX) {
-        ++c;
-      } else {
-        c = 0;
-      }
</font><font color='#000088'>+      c = (c + 1) % SMSC9218I_TX_JOBS;
</font>     }
 
     /* Increment jobs to do */
<font color='#997700'>@@ -1031,11 +1154,10 @@
</font>   if (jc->transfer == 0) {
     uint32_t tx_fifo_inf = regs->tx_fifo_inf;
     uint32_t data_free = SMSC9218I_TX_FIFO_INF_GET_FREE(tx_fifo_inf);
<font color='#880000'>-    unsigned c = jc->transfer_index;
-    unsigned last_index = c;
-    unsigned i = 0;
-    unsigned n = jc->todo;
-    struct tcd_t *p = NULL;
</font><font color='#000088'>+    int c = jc->transfer_index;
+    int last_index = c;
+    int i = 0;
+    int n = jc->todo;
</font> 
     #ifdef DEBUG
       smsc9218i_transmit_job_dump(jc, "transfer");
<font color='#997700'>@@ -1052,20 +1174,13 @@
</font>         /* Index of last TCD */
         last_index = c;
 
<font color='#880000'>-        /* Cache flush for previous data TCD */
-        if (p != NULL) {
-          rtems_cache_flush_multiple_data_lines(p, sizeof(*p));
-        }
</font><font color='#000088'>+        /* Cache flush for data TCD */
+        smsc9218i_flush_tcd(tcd);
</font>       } else {
         break;
       }
 
<font color='#880000'>-      p = tcd;
-      if (c < SMSC9218I_TX_JOBS_MAX) {
-        ++c;
-      } else {
-        c = 0;
-      }
</font><font color='#000088'>+      c = (c + 1) % SMSC9218I_TX_JOBS;
</font>     }
 
     if (i > 0) {
<font color='#997700'>@@ -1092,10 +1207,8 @@
</font>       );
 
       /* Enable interrupt for last data TCD */
<font color='#880000'>-      last->BMF.R = SMSC9218I_EDMA_TX_TCD_BMF_INTERRUPT;
-
-      /* Cache flush for last data TCD */
-      rtems_cache_flush_multiple_data_lines(last, sizeof(*last));
</font><font color='#000088'>+      last->BMF.R = SMSC9218I_TCD_BMF_LAST;
+      smsc9218i_flush_tcd(last);
</font>       ppc_synchronize_data();
 
       /* Start eDMA transfer */
<font color='#997700'>@@ -1106,7 +1219,7 @@
</font>       channel->DADDR = start->DADDR;
       channel->CDF.R = start->CDF.R;
       channel->DLAST_SGA = start->DLAST_SGA;
<font color='#880000'>-      channel->BMF.R = SMSC9218I_EDMA_TX_TCD_BMF_CLEAR;
</font><font color='#000088'>+      channel->BMF.R = SMSC9218I_TCD_BMF_CLEAR;
</font>       channel->BMF.R = start->BMF.R;
 
       /* Transmit task may wait for events */
<font color='#997700'>@@ -1135,7 +1248,7 @@
</font>   uint32_t tx_fifo_inf = regs->tx_fifo_inf;
   uint32_t status_used = SMSC9218I_TX_FIFO_INF_GET_SUSED(tx_fifo_inf);
   uint32_t s = 0;
<font color='#880000'>-  unsigned n = jc->transfer;
</font><font color='#000088'>+  int n = jc->transfer;
</font> 
   for (s = 0; s < status_used; ++s) {
     uint32_t tx_fifo_status = regs->tx_fifo_status;
<font color='#997700'>@@ -1154,33 +1267,29 @@
</font>   }
 
   if (
<font color='#880000'>-    (events & (SMSC9218I_EVENT_EDMA | SMSC9218I_EVENT_EDMA_ERROR)) != 0
</font><font color='#000088'>+    (events & (SMSC9218I_EVENT_DMA | SMSC9218I_EVENT_DMA_ERROR)) != 0
</font>       && n > 0
   ) {
<font color='#880000'>-    unsigned c = jc->empty_index;
-    unsigned i = 0;
</font><font color='#000088'>+    int c = jc->empty_index;
+    int i = 0;
</font> 
     #ifdef DEBUG
       smsc9218i_transmit_job_dump(jc, "finish");
     #endif
 
<font color='#880000'>-    if ((events & SMSC9218I_EVENT_EDMA_ERROR) != 0) {
-      ++e->transmit_edma_errors;
</font><font color='#000088'>+    if ((events & SMSC9218I_EVENT_DMA_ERROR) != 0) {
+      ++e->transmit_dma_errors;
</font>     }
 
     /* Restore last data TCD */
     jc->data_tcd_table [jc->transfer_last_index].BMF.R =
<font color='#880000'>-      SMSC9218I_EDMA_TX_TCD_BMF_LINK;
</font><font color='#000088'>+      SMSC9218I_TCD_BMF_LINK;
</font> 
     for (i = 0; i < n; ++i) {
       /* Free fragment buffer */
       m_free(jc->fragment_table [c]);
 
<font color='#880000'>-      if (c < SMSC9218I_TX_JOBS_MAX) {
-        ++c;
-      } else {
-        c = 0;
-      }
</font><font color='#000088'>+      c = (c + 1) % SMSC9218I_TX_JOBS;
</font>     }
 
     /* Increment empty count */
<font color='#997700'>@@ -1202,7 +1311,7 @@
</font> }
 
 /* FIXME */
<font color='#880000'>-static smsc9218i_transmit_job_control smsc_jc  __attribute__ ((aligned (32))) = {
</font><font color='#000088'>+static smsc9218i_transmit_job_control smsc_tx_jc __attribute__((aligned (32))) = {
</font>   .frame = NULL,
   .next_fragment = NULL,
   .frame_length = 0,
<font color='#997700'>@@ -1225,7 +1334,7 @@
</font>   struct ifnet *ifp = &e->arpcom.ac_if;
   volatile smsc9218i_registers *const regs = smsc9218i;
   uint32_t mac_cr = 0;
<font color='#880000'>-  smsc9218i_transmit_job_control *jc = &smsc_jc;
</font><font color='#000088'>+  smsc9218i_transmit_job_control *jc = &smsc_tx_jc;
</font>   unsigned i = 0;
 
   SMSC9218I_PRINTF("%s\n", __func__);
<font color='#997700'>@@ -1233,11 +1342,11 @@
</font>   /* Obtain transmit eDMA channel */
   e->edma_transmit.id = e->transmit_task;
   sc = mpc55xx_edma_obtain_channel(&e->edma_transmit);
<font color='#880000'>-  RTEMS_CLEANUP_SC(sc, cleanup, "obtain transmit eDMA channel");
</font><font color='#000088'>+  ASSERT_SC(sc);
</font> 
   /* Setup transmit eDMA descriptors */
   for (i = 0; i < SMSC9218I_TX_JOBS; ++i) {
<font color='#880000'>-    unsigned ii = i < SMSC9218I_TX_JOBS_MAX ? i + 1 : 0;
</font><font color='#000088'>+    unsigned ii = (i + 1) % SMSC9218I_TX_JOBS;
</font>     struct tcd_t tcd = EDMA_TCD_DEFAULT;
     struct tcd_t *command_tcd = &jc->command_tcd_table [i];
     struct tcd_t *data_tcd = &jc->data_tcd_table [i];
<font color='#997700'>@@ -1247,15 +1356,15 @@
</font>     tcd.SDF.B.SOFF = 4;
     tcd.SDF.B.DSIZE = 2;
     tcd.CDF.B.CITER = 1;
<font color='#880000'>-    tcd.BMF.R = SMSC9218I_EDMA_TX_TCD_BMF_LINK;
</font><font color='#000088'>+    tcd.BMF.R = SMSC9218I_TCD_BMF_LINK;
</font>     tcd.DADDR = (uint32_t) &regs->tx_fifo_data;
 
<font color='#880000'>-    tcd.DLAST_SGA = (uint32_t) next_command_tcd;
</font><font color='#000088'>+    tcd.DLAST_SGA = (int32_t) next_command_tcd;
</font>     *data_tcd = tcd;
 
     tcd.SADDR = (uint32_t) &jc->command_table [i].a;
     tcd.NBYTES = 8;
<font color='#880000'>-    tcd.DLAST_SGA = (uint32_t) data_tcd;
</font><font color='#000088'>+    tcd.DLAST_SGA = (int32_t) data_tcd;
</font>     *command_tcd = tcd;
   }
 
<font color='#997700'>@@ -1281,13 +1390,13 @@
</font>     sc = rtems_bsdnet_event_receive(
       SMSC9218I_EVENT_TX
         | SMSC9218I_EVENT_TX_START
<font color='#880000'>-        | SMSC9218I_EVENT_EDMA
-        | SMSC9218I_EVENT_EDMA_ERROR,
</font><font color='#000088'>+        | SMSC9218I_EVENT_DMA
+        | SMSC9218I_EVENT_DMA_ERROR,
</font>       RTEMS_EVENT_ANY | RTEMS_WAIT,
       RTEMS_NO_TIMEOUT,
       &events
     );
<font color='#880000'>-    RTEMS_CLEANUP_SC(sc, cleanup, "wait for events");
</font><font color='#000088'>+    ASSERT_SC(sc);
</font> 
     SMSC9218I_PRINTF("tx: wake up: events = 0x%08" PRIx32 "\n", events);
 
<font color='#997700'>@@ -1475,7 +1584,7 @@
</font>     smsc9218i_interrupt_handler,
     e
   );
<font color='#880000'>-  RTEMS_SYSLOG_ERROR_SC(sc, "install interrupt handler\n");
</font><font color='#000088'>+  ASSERT_SC(sc);
</font> 
   /* Enable interrupts and use push-pull driver (active low) */
   regs->irq_cfg = SMSC9218I_IRQ_CFG_GLOBAL_ENABLE;
<font color='#997700'>@@ -1638,7 +1747,7 @@
</font> static void smsc9218i_interface_stats(smsc9218i_driver_entry *e)
 {
   volatile smsc9218i_registers *const regs = smsc9218i;
<font color='#880000'>-  smsc9218i_transmit_job_control *jc = &smsc_jc;
</font><font color='#000088'>+  smsc9218i_transmit_job_control *jc = &smsc_tx_jc;
</font>   int media = 0;
   bool media_ok = smsc9218i_media_status(e, &media);
 
<font color='#997700'>@@ -1651,23 +1760,25 @@
</font> 
   e->receive_drop += SMSC9218I_SWAP(regs->rx_drop);
 
<font color='#000088'>+  printf("PHY interrupts:            %u\n", e->phy_interrupts);
</font>   printf("received frames:           %u\n", e->received_frames);
<font color='#880000'>-  printf("receive interrupts:        %u\n", e->receive_interrupts);
-  printf("transmitted frames:        %u\n", e->transmitted_frames);
-  printf("transmit interrupts:       %u\n", e->transmit_interrupts);
</font>   printf("receiver errors:           %u\n", e->receiver_errors);
<font color='#000088'>+  printf("receive interrupts:        %u\n", e->receive_interrupts);
+  printf("receive DMA interrupts:    %u\n", e->receive_dma_interrupts);
</font>   printf("receive to long errors:    %u\n", e->receive_too_long_errors);
   printf("receive collision errors:  %u\n", e->receive_collision_errors);
   printf("receive CRC errors:        %u\n", e->receive_crc_errors);
<font color='#880000'>-  printf("receive eDMA errors:       %u\n", e->receive_edma_errors);
</font><font color='#000088'>+  printf("receive DMA errors:        %u\n", e->receive_dma_errors);
</font>   printf("receive drops:             %u\n", e->receive_drop);
   printf("receive watchdog timeouts: %u\n", e->receive_watchdog_timeouts);
<font color='#000088'>+  printf("transmitted frames:        %u\n", e->transmitted_frames);
</font>   printf("transmitter errors:        %u\n", e->transmitter_errors);
<font color='#000088'>+  printf("transmit interrupts:       %u\n", e->transmit_interrupts);
+  printf("transmit DMA interrupts:   %u\n", e->transmit_dma_interrupts);
</font>   printf("transmit status overflows: %u\n", e->transmit_status_overflows);
   printf("transmit frame errors:     %u\n", e->transmit_frame_errors);
<font color='#880000'>-  printf("transmit eDMA errors:      %u\n", e->transmit_edma_errors);
-  printf("fixme tiny fragments:      %u\n", jc->fixme_tiny_fragments);
-  printf("fixme too many:            %u\n", jc->fixme_too_many);
</font><font color='#000088'>+  printf("transmit DMA errors:       %u\n", e->transmit_dma_errors);
+  printf("frame compact count:       %u\n", jc->frame_compact_count);
</font> }
 
 static int smsc9218i_interface_ioctl(
<font color='#997700'>@@ -1683,7 +1794,7 @@
</font>   switch (command)  {
     case SIOCGIFMEDIA:
     case SIOCSIFMEDIA:
<font color='#880000'>-      rtems_mii_ioctl(&e->mdio, e, (int) command, (int *) data);
</font><font color='#000088'>+      rtems_mii_ioctl(&e->mdio, e, command, (int *) data);
</font>       break;
     case SIOCGIFADDR:
     case SIOCSIFADDR:
<font color='#997700'>@@ -1718,7 +1829,7 @@
</font>   ifp->if_flags |= IFF_OACTIVE;
 
   sc = rtems_event_send(e->transmit_task, SMSC9218I_EVENT_TX_START);
<font color='#880000'>-  RTEMS_SYSLOG_ERROR_SC(sc, "send transmit start event");
</font><font color='#000088'>+  ASSERT_SC(sc);
</font> }
 
 static void smsc9218i_interface_watchdog(struct ifnet *ifp)
<font color='#997700'>@@ -1726,7 +1837,7 @@
</font>   SMSC9218I_PRINTF("%s\n", __func__);
 }
 
<font color='#880000'>-static int smsc9218i_attach(struct rtems_bsdnet_ifconfig *config)
</font><font color='#000088'>+static void smsc9218i_attach(struct rtems_bsdnet_ifconfig *config)
</font> {
   smsc9218i_driver_entry *e = &smsc9218i_driver_data;
   struct ifnet *ifp = &e->arpcom.ac_if;
<font color='#997700'>@@ -1734,19 +1845,9 @@
</font>   int unit_number = rtems_bsdnet_parse_driver_name(config, &unit_name);
 
   /* Check parameter */
<font color='#880000'>-  if (unit_number < 0) {
-    RTEMS_SYSLOG_ERROR("parse error for interface name\n");
-    return 0;
-  }
-  if (unit_number != 0) {
-    RTEMS_DO_CLEANUP(smsc9218i_attach_cleanup, "unexpected unit number");
-  }
-  if (config->hardware_address == NULL) {
-    RTEMS_DO_CLEANUP(smsc9218i_attach_cleanup, "MAC address missing");
-  }
-  if (e->state != SMSC9218I_NOT_INITIALIZED) {
-    RTEMS_DO_CLEANUP(smsc9218i_attach_cleanup, "already attached");
-  }
</font><font color='#000088'>+  assert(unit_number == 0);
+  assert(config->hardware_address != NULL);
+  assert(e->state == SMSC9218I_NOT_INITIALIZED);
</font> 
   /* Interrupt number */
   config->irno = MPC55XX_IRQ_SIU_EXTERNAL_0;
<font color='#997700'>@@ -1787,27 +1888,18 @@
</font>   /* Attach the interface */
   if_attach(ifp);
   ether_ifattach(ifp);
<font color='#880000'>-
-  return 1;
-
-smsc9218i_attach_cleanup:
-
-  /* FIXME: Type */
-  free(unit_name, (int) 0xdeadbeef);
-
-  return 0;
</font> }
 
 int smsc9218i_attach_detach(
   struct rtems_bsdnet_ifconfig *config,
   int attaching
 ) {
<font color='#880000'>-  /* FIXME: Return value */
-
</font>   if (attaching) {
<font color='#880000'>-    return smsc9218i_attach(config);
</font><font color='#000088'>+    smsc9218i_attach(config);
</font>   } else {
     /* TODO */
<font color='#880000'>-    return 0;
</font>   }
<font color='#000088'>+
+  /* FIXME: Return value */
+  return 0;
</font> }
</pre>
<p> </p>

<p>--<br />
<small>Generated by <a href="http://www.codewiz.org/projects/index.html#loginfo">Deluxe Loginfo</a> 2.122 by Bernardo Innocenti <bernie@develer.com></small></p>
</body>
</html>