Index: /soft/giet_vm/giet_kernel/ctx_handler.h
===================================================================
--- /soft/giet_vm/giet_kernel/ctx_handler.h	(revision 448)
+++ /soft/giet_vm/giet_kernel/ctx_handler.h	(revision 449)
@@ -19,21 +19,21 @@
 // allocated to the task (private peripheral channel for multi-channels peripherals).
 /////////////////////////////////////////////////////////////////////////////////////////
-// ctx[0] <- ***   |ctx[8] <- $8    |ctx[16]<- $16   |ctx[24]<- $24
-// ctx[1] <- $1    |ctx[9] <- $9    |ctx[17]<- $17   |ctx[25]<- $25
-// ctx[2] <- $2    |ctx[10]<- $10   |ctx[18]<- $18   |ctx[26]<- LO
-// ctx[3] <- $3    |ctx[11]<- $11   |ctx[19]<- $19   |ctx[27]<- HI
-// ctx[4] <- $4    |ctx[12]<- $12   |ctx[20]<- $20   |ctx[28]<- $28
-// ctx[5] <- $5    |ctx[13]<- $13   |ctx[21]<- $21   |ctx[29]<- SP
-// ctx[6] <- $6    |ctx[14]<- $14   |ctx[22]<- $22   |ctx[30]<- $30
-// ctx[7] <- $7    |ctx[15]<- $15   |ctx[23]<- $23   |ctx[31]<- RA
+// ctx[0] <- ***   |ctx[8] <- $8     |ctx[16]<- $16   |ctx[24]<- $24
+// ctx[1] <- $1    |ctx[9] <- $9     |ctx[17]<- $17   |ctx[25]<- $25
+// ctx[2] <- $2    |ctx[10]<- $10    |ctx[18]<- $18   |ctx[26]<- LO
+// ctx[3] <- $3    |ctx[11]<- $11    |ctx[19]<- $19   |ctx[27]<- HI
+// ctx[4] <- $4    |ctx[12]<- $12    |ctx[20]<- $20   |ctx[28]<- $28
+// ctx[5] <- $5    |ctx[13]<- $13    |ctx[21]<- $21   |ctx[29]<- SP
+// ctx[6] <- $6    |ctx[14]<- $14    |ctx[22]<- $22   |ctx[30]<- $30
+// ctx[7] <- $7    |ctx[15]<- $15    |ctx[23]<- $23   |ctx[31]<- RA
 //
-// ctx[32]<- EPC   |ctx[40]<- TTY   |ctx[48]<- TRDID |ctx[56]<- ***
-// ctx[33]<- CR    |ctx[41]<- FBCMA |ctx[49]<- GTID  |ctx[57]<- ***
-// ctx[34]<- SR    |ctx[42]<- TXCMA |ctx[50]<- ***   |ctx[58]<- ***
-// ctx[35]<- BVAR  |ctx[43]<- RXCMA |ctx[51]<- ***   |ctx[59]<- ***
-// ctx[36]<- PTAB  |ctx[44]<- NIC   |ctx[52]<- ***   |ctx[60]<- ***
-// ctx[37]<- LTID  |ctx[45]<- HBA   |ctx[53]<- ***   |ctx[61]<- ***
-// ctx[38]<- VSID  |ctx[46]<- TIM   |ctx[54]<- ***   |ctx[62]<- ***
-// ctx[39]<- PTPR  |ctx[47]<- RUN   |ctx[55]<- ***   |ctx[63]<- ***
+// ctx[32]<- EPC   |ctx[40]<- TTY    |ctx[48]<- TRDID |ctx[56]<- ***
+// ctx[33]<- CR    |ctx[41]<- CMA_FB |ctx[49]<- GTID  |ctx[57]<- ***
+// ctx[34]<- SR    |ctx[42]<- CMA_RX |ctx[50]<- RUN   |ctx[58]<- ***
+// ctx[35]<- BVAR  |ctx[43]<- CMA_TX |ctx[51]<- ***   |ctx[59]<- ***
+// ctx[36]<- PTAB  |ctx[44]<- NIC_RX |ctx[52]<- ***   |ctx[60]<- ***
+// ctx[37]<- LTID  |ctx[45]<- NIC_TX |ctx[53]<- ***   |ctx[61]<- ***
+// ctx[38]<- VSID  |ctx[46]<- TIM    |ctx[54]<- ***   |ctx[62]<- ***
+// ctx[39]<- PTPR  |ctx[47]<- HBA    |ctx[55]<- ***   |ctx[63]<- ***
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -60,14 +60,15 @@
 
 #define CTX_TTY_ID       40  // private TTY channel index  
-#define CTX_FBCMA_ID     41  // private CMA channel index for FBF write
-#define CTX_TXCMA_ID     42  // private CMA channel index for NIC TX
-#define CTX_RXCMA_ID     43  // private CMA channel index for NIC RX
-#define CTX_NIC_ID       44  // private NIC channel index 
-#define CTX_HBA_ID       45  // private HBA channel index
+#define CTX_CMA_FB_ID    41  // private CMA channel index for FBF write
+#define CTX_CMA_RX_ID    42  // private CMA channel index for NIC_TX
+#define CTX_CMA_TX_ID    43  // private CMA channel index for NIC_RX
+#define CTX_NIC_RX_ID    44  // private NIC channel index RX transfer
+#define CTX_NIC_TX_ID    45  // private NIC channel index TX transfer
 #define CTX_TIM_ID       46  // ptivate TIM channel index
-#define CTX_RUN_ID       47  // Boolean: task runable
+#define CTX_HBA_ID       47  // private HBA channel index
 
 #define CTX_TRDID_ID     48  // Thread Task Index in vspace
 #define CTX_GTID_ID      49  // Global Task Index in all system
+#define CTX_RUN_ID       50  // Boolean: task runable
 
 /////////////////////////////////////////////////////////////////////////////////
Index: /soft/giet_vm/giet_kernel/kernel_init.c
===================================================================
--- /soft/giet_vm/giet_kernel/kernel_init.c	(revision 448)
+++ /soft/giet_vm/giet_kernel/kernel_init.c	(revision 449)
@@ -173,5 +173,5 @@
     }  // end for tasks
 
-    // step 4 : compute and set XCU masks
+    // step 3 : compute and set XCU masks
 
     unsigned int isr_switch_index = 0xFFFFFFFF;
@@ -211,5 +211,5 @@
     _xcu_set_mask( cluster_xy, channel, pti_mask, IRQ_TYPE_PTI );
 
-    // step 5 : start TICK timer if at least one task
+    // step 4 : start TICK timer if at least one task
     if (tasks > 0) 
     {
@@ -232,5 +232,5 @@
 #endif
 
-    // step 6 : each processor updates the idle_task context:
+    // step 5 : each processor updates the idle_task context:
     //          (CTX_SP, CTX_RA, CTX_EPC).
     //          The 4 Kbytes idle stack is implemented in the scheduler.
@@ -251,5 +251,5 @@
 #endif
 
-    // step 7 : when all processors reach the synchronisation barrier, 
+    // step 6 : when all processors reach the synchronisation barrier, 
     //          each processor set registers SP, SR, PTPR, EPC,
     //          with the values corresponding to the first allocated task,
Index: /soft/giet_vm/giet_kernel/kernel_utils.c
===================================================================
--- /soft/giet_vm/giet_kernel/kernel_utils.c	(revision 448)
+++ /soft/giet_vm/giet_kernel/kernel_utils.c	(revision 449)
@@ -162,4 +162,23 @@
 }  // end _printf()
 
+///////////////////////////////////////////////////
+unsigned int _atomic_increment( unsigned int* ptr )
+{
+    unsigned int value;
+
+    asm volatile (
+        "_atomic_increment_try:             \n"
+        "ll   $3,    0(%1)                  \n"
+        "move %0,    $3                     \n"
+        "addi $3,    $3,     1              \n"     
+        "sc   $3,    0(%1)                  \n"
+        "beqz $3,    _atomic_increment_try  \n"
+        : "=r" (value) 
+        : "r" (ptr)
+        : "$3", "memory" );
+
+    return value;
+}
+
 // Local Variables:
 // tab-width: 4
Index: /soft/giet_vm/giet_kernel/kernel_utils.h
===================================================================
--- /soft/giet_vm/giet_kernel/kernel_utils.h	(revision 448)
+++ /soft/giet_vm/giet_kernel/kernel_utils.h	(revision 449)
@@ -14,4 +14,7 @@
 extern void _printf( char* format, ... );
 
+///////////////////////////////////////////////////////////
+extern unsigned int _atomic_increment( unsigned int* ptr );
+
 #endif
 
Index: /soft/giet_vm/giet_kernel/sys_handler.c
===================================================================
--- /soft/giet_vm/giet_kernel/sys_handler.c	(revision 448)
+++ /soft/giet_vm/giet_kernel/sys_handler.c	(revision 449)
@@ -26,4 +26,33 @@
 #endif
 
+#if !defined(NB_TTY_CHANNELS) 
+# error: You must define NB_TTY_CHANNELS in the hard_config.h file
+#endif
+
+#if !defined(NB_TIM_CHANNELS) 
+# error: You must define NB_TIM_CHANNELS in the hard_config.h file
+#endif
+
+#if !defined(NB_NIC_CHANNELS) 
+# error: You must define NB_NIC_CHANNELS in the hard_config.h file
+#endif
+
+#if !defined(NB_CMA_CHANNELS) 
+# error: You must define NB_CMA_CHANNELS in the hard_config.h file
+#endif
+
+#if !defined(GIET_NIC_CHBUF_NBUFS) 
+# error: You must define GIET_NIC_CHBUF_NBUFS in the giet_config.h file
+#endif
+
+#if !defined(GIET_NIC_CHBUF_SIZE) 
+# error: You must define GIET_NIC_CHBUF_SIZE in the giet_config.h file
+#endif
+
+#if !defined(GIET_NIC_CHBUF_TIMEOUT) 
+# error: You must define GIET_NIC_CHBUF_TIMEOUT in the giet_config.h file
+#endif
+
+
 ////////////////////////////////////////////////////////////////////////////
 //     Channel allocators for peripherals
@@ -34,5 +63,15 @@
 unsigned int _tim_channel_allocator = 0;
 unsigned int _cma_channel_allocator = 0;
-unsigned int _nic_channel_allocator = 0;
+unsigned int _nic_rx_channel_allocator = 0;
+unsigned int _nic_tx_channel_allocator = 0;
+
+
+////////////////////////////////////////////////////////////////////////////
+//     NIC_RX and NIC_TX chbuf arrays
+////////////////////////////////////////////////////////////////////////////
+
+nic_chbuf_t  _nic_rx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(8)));
+nic_chbuf_t  _nic_tx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(8)));
+
 
 ////////////////////////////////////////////////////////////////////////////
@@ -72,7 +111,7 @@
     &_sys_vobj_get_length,  /* 0x1B */
     &_sys_xy_from_ptr,      /* 0x1C */
-    &_sys_nic_alloc,        /* 0x1D */
-    &_sys_nic_sync_send,    /* 0x1E */
-    &_sys_nic_sync_receive, /* 0x1F */
+    &_sys_ukn,              /* 0x1D */
+    &_sys_ukn,              /* 0x1E */
+    &_sys_ukn,              /* 0x1F */
 
     &_fat_user_open,        /* 0x20 */
@@ -93,12 +132,12 @@
     &_sys_ukn,              /* 0x2F */
 
-    &_sys_ukn,              /* 0x30 */
-    &_sys_ukn,              /* 0x31 */
-    &_sys_ukn,              /* 0x32 */
-    &_sys_ukn,              /* 0x33 */
-    &_sys_ukn,              /* 0x34 */
-    &_sys_ukn,              /* 0x35 */ 
-    &_sys_ukn,              /* 0x36 */
-    &_sys_ukn,              /* 0x37 */
+    &_sys_nic_alloc,        /* 0x30 */
+    &_sys_nic_alloc,        /* 0x31 */
+    &_sys_nic_start,        /* 0x32 */
+    &_sys_nic_start,        /* 0x33 */
+    &_sys_nic_move,         /* 0x34 */
+    &_sys_nic_move,         /* 0x35 */ 
+    &_sys_nic_stop,         /* 0x36 */
+    &_sys_nic_stop,         /* 0x37 */
     &_sys_ukn,              /* 0x38 */   
     &_sys_ukn,              /* 0x39 */
@@ -119,5 +158,5 @@
 {
     // get a new TTY terminal index
-    unsigned int channel = _tty_channel_allocator;
+    unsigned int channel = _atomic_increment( &_tty_channel_allocator );
     unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
     unsigned int vspace  = _get_context_slot( CTX_VSID_ID );
@@ -132,13 +171,7 @@
         _printf("\n[GIET WARNING] TTY channel %d allocated "
                 " to thread %d in vspace %d\n", channel, thread, vspace );
-    }
-
-    // register timer index in task context
-    _set_context_slot( CTX_TTY_ID, _tty_channel_allocator );
-
-    // update timer allocator
-    _tty_channel_allocator++;
-
-    return 0;
+        _set_context_slot( CTX_TTY_ID, channel );
+        return 0;
+    }
 }
 
@@ -227,5 +260,5 @@
 {
     // get a new timer index 
-    unsigned int channel = _tim_channel_allocator;
+    unsigned int channel = _atomic_increment(&_tim_channel_allocator);
     unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
     unsigned int vspace  = _get_context_slot( CTX_VSID_ID );
@@ -240,13 +273,7 @@
         _printf("\n[GIET WARNING] TIM channel %d allocated "
                 " to thread %d in vspace %d\n", channel, thread, vspace );
-    }
-
-    // register timer index in task context
-    _set_context_slot( CTX_TIM_ID, channel );
-
-    // update timer allocator
-    _tim_channel_allocator++;
-
-    return 0;
+        _set_context_slot( CTX_TIM_ID, channel );
+        return 0;
+    }
 }
 
@@ -289,108 +316,258 @@
 //////////////////////////////////////////////////////////////////////////////
 
-////////////////////
-int _sys_nic_alloc()
-{
-    // get a new NIC channel index 
-    unsigned int channel = _nic_channel_allocator;
-    unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
-    unsigned int vspace  = _get_context_slot( CTX_VSID_ID );
-
-    if ( channel >= NB_NIC_CHANNELS )
-    {
-        _printf("\n[GIET_ERROR] in _sys_nic_alloc() : not enough NIC channels\n");
-        return -1;
+///////////////////////////////////////////
+int _sys_nic_alloc( unsigned int is_rx )
+{
+    unsigned int nic_channel;
+    unsigned int cma_channel;
+
+    // get a NIC_RX or NIC_TX channel index 
+    if ( is_rx ) nic_channel = _atomic_increment(&_nic_rx_channel_allocator);
+    else         nic_channel = _atomic_increment(&_nic_tx_channel_allocator);
+
+    if ( (nic_channel >= NB_NIC_CHANNELS) )
+    {
+        _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough NIC channels\n");
+        return -1;
+    }
+
+    // get a CMA channel index
+    cma_channel = _atomic_increment(&_cma_channel_allocator);
+
+    if ( cma_channel >= NB_CMA_CHANNELS )
+    {
+        _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough CMA channels\n");
+        return -1;
+    }
+    
+    // register nic_index and cma_index in task context
+    if ( is_rx )
+    {
+        _set_context_slot( CTX_NIC_RX_ID, nic_channel );
+        _set_context_slot( CTX_CMA_RX_ID, cma_channel );
     }
     else
     {
-        _printf("\n[GIET WARNING] NIC channel %d allocated "
-                " to thread %d in vspace %d\n", channel, thread, vspace );
-    }
-
-    // register channel index in task context
-    _set_context_slot( CTX_NIC_ID, channel );
-
-    // update NIC channel allocator
-    _nic_channel_allocator++;
-
-    return 0;
-}
-
-////////////////////////////////////
-int _sys_nic_sync_send( void* vbuf )
-{
+        _set_context_slot( CTX_NIC_TX_ID, nic_channel );
+        _set_context_slot( CTX_CMA_TX_ID, cma_channel );
+    }
+
+#if GIET_DEBUG_NIC
+unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
+unsigned int vspace  = _get_context_slot( CTX_VSID_ID );
+_printf("\n[GIET DEBUG_NIC] NIC channel %d and CMA channel %d"
+        " allocated to task %d in vspace %d\n", 
+        nic_channel, cma_channel, thread, vspace );
+#endif
+
+    return 0;
+}
+
+////////////////////////////////////////
+int _sys_nic_start( unsigned int is_rx,
+                    unsigned int mac4,
+                    unsigned int mac2 )
+{
+    unsigned int nic_channel;
+    unsigned int cma_channel;
+
+    // get NIC channel index and CMA channel index
+    if ( is_rx )
+    {
+        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
+        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
+    }
+    else
+    {
+        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
+        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
+    }
+
+    if ( nic_channel >= NB_NIC_CHANNELS )
+    {
+        _printf("\n[GIET_ERROR] in _sys_nic_start(): NIC channel not allocated\n");
+        return -1;
+    }
+    if ( cma_channel >= NB_CMA_CHANNELS )
+    {
+        _printf("\n[GIET_ERROR] in _sys_nic_start(): CMA channel not allocated\n");
+        return -1;
+    }
+
+    unsigned int nic_chbuf_lsb;     // 32 LSB bits of the NIC chbuf physical address
+    unsigned int nic_chbuf_msb;     // 16 MSB bits of the NIC chbuf physical address
+    unsigned int ker_chbuf_lsb;     // 32 LSB bits of the kernel chbuf physical address
+    unsigned int ker_chbuf_msb;     // 16 MSB bits of the kernel chbuf physical address
+
+    // get the NIC chbuf descriptor physical address
+    unsigned int offset;
+    if ( is_rx ) offset = 0x1000;
+    else         offset = 0x1010;
+    nic_chbuf_lsb = SEG_NIC_BASE + (nic_channel * NIC_CHANNEL_SPAN) + offset;
+    nic_chbuf_msb = (X_IO << Y_WIDTH) + Y_IO;
+
+    // get the kernel chbuf descriptor physical address
+    unsigned int ker_chbuf_vaddr;
+    if ( is_rx ) ker_chbuf_vaddr = (unsigned int)( &_nic_rx_chbuf[nic_channel] );
+    else         ker_chbuf_vaddr = (unsigned int)( &_nic_tx_chbuf[nic_channel] );
+
+    // compute the kernel chbuf descriptor physical address
     unsigned int ppn;
     unsigned int flags;
-    unsigned int vaddr = (unsigned int)vbuf;
-
-    // get NIC channel index
-    unsigned int channel = _get_context_slot( CTX_NIC_ID );
-    if ( channel >= NB_NIC_CHANNELS )
-    {
-        _printf("\n[GIET_ERROR] in _sys_nic_sync_send() : illegal NIC channel index\n");
-        return -1;
-    }
-
-    // get page table pointer
-    unsigned int user_ptab = _get_context_slot( CTX_PTAB_ID );
+    unsigned int ptab  = _get_context_slot(CTX_PTAB_ID);
+    unsigned int ko    = _v2p_translate( (page_table_t*)ptab,
+                                          ker_chbuf_vaddr,
+                                          &ppn,
+                                          &flags );
+    if ( ko )
+    {
+        _puts("\n[GIET ERROR] in _nic_cma_start_receive() : kernel buffer unmapped\n");
+        return -1;
+    }
+
+    ker_chbuf_lsb = (ppn << 12) | (ker_chbuf_vaddr & 0x00000FFF);
+    ker_chbuf_msb = ppn >> 20;
+
+    // initializes CMA registers defining the source chbuf (NIc)
+    _cma_set_register( cma_channel, CHBUF_SRC_DESC , nic_chbuf_lsb );
+    _cma_set_register( cma_channel, CHBUF_DST_EXT  , nic_chbuf_msb );
+    _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, 2 );
+
+    // initializes CMA registers defining the destination chbuf (kernel)
+    _cma_set_register( cma_channel, CHBUF_DST_DESC , ker_chbuf_lsb );
+    _cma_set_register( cma_channel, CHBUF_DST_EXT  , ker_chbuf_msb );
+    _cma_set_register( cma_channel, CHBUF_DST_NBUFS, GIET_NIC_CHBUF_NBUFS );
+
+    // start CMA transfer
+    _cma_set_register( cma_channel, CHBUF_BUF_SIZE , 4096 );
+    _cma_set_register( cma_channel, CHBUF_PERIOD   , 300 );
+    _cma_set_register( cma_channel, CHBUF_RUN      , 1 );
+
+    // activates NIC channel
+    _nic_channel_start( nic_channel, is_rx, mac4, mac2 ); 
+    return 0;
+}
+
+//////////////////////////////////////
+int _sys_nic_move( unsigned int is_rx,
+                   void*        buffer )
+{
+    unsigned long long user_paddr;    // user buffer physical address 
+    unsigned long long kernel_paddr;  // kernel buffer physical address
 
     // Compute user buffer physical address and check access rights
-    unsigned int ko = _v2p_translate( (page_table_t*)user_ptab,
-                                      vaddr,
-                                      &ppn,
-                                      &flags );
-    if ( ko )
-    {
-        _printf("\n[GIET ERROR] in _sys_nic_sync_send() : user buffer unmapped\n");
-        return -1;
-    }
-    if ( (flags & PTE_U) == 0 )
-    {
-        _printf("\n[GIET ERROR] in _sys_nic_sync_send() : illegal buffer address\n");
-        return -1;
-    }
-    unsigned long long pbuf = ((unsigned long long)ppn << 12) | (vaddr & 0x00000FFF);
-
-    _nic_sync_send( channel, pbuf );
-
-    return 0;
-}
-
-///////////////////////////////////////
-int _sys_nic_sync_receive( void* vbuf )
-{
     unsigned int ppn;
     unsigned int flags;
-    unsigned int vaddr = (unsigned int)vbuf;
-
-    // get NIC channel index
-    unsigned int channel = _get_context_slot( CTX_NIC_ID );
+    unsigned int vaddr = (unsigned int)buffer;
+    unsigned int user_ptab = _get_context_slot( CTX_PTAB_ID );
+    unsigned int ko = _v2p_translate( (page_table_t*)user_ptab,
+                                       vaddr,
+                                       &ppn,
+                                       &flags );
+    if ( ko )
+    {
+        _printf("\n[GIET ERROR] in _sys_nic_tx_move() : user buffer unmapped\n");
+        return -1;
+    }
+    if ( (flags & PTE_U) == 0 )
+    {
+        _printf("\n[GIET ERROR] in _sys_nic_tx_move() : illegal buffer address\n");
+        return -1;
+    }
+    user_paddr = ((unsigned long long)ppn << 12) | (vaddr & 0x00000FFF);
+
+    // get NIC channel index, to get pointer on NIC_TX chbuf pointer
+    unsigned int channel;
+    if ( is_rx ) channel = _get_context_slot( CTX_NIC_RX_ID );
+    else         channel = _get_context_slot( CTX_NIC_TX_ID );
+
     if ( channel >= NB_NIC_CHANNELS )
     {
-        _printf("\n[GIET_ERROR] in _sys_nic_sync_send() : illegal NIC channel index\n");
-        return -1;
-    }
-
-    // get page table pointer
-    unsigned int user_ptab = _get_context_slot( CTX_PTAB_ID );
-
-    // Compute user buffer physical address and check access rights
-    unsigned int ko = _v2p_translate( (page_table_t*)user_ptab,
-                                      vaddr,
-                                      &ppn,
-                                      &flags );
-    if ( ko )
-    {
-        _printf("\n[GIET ERROR] in _sys_nic_sync_send() : user buffer unmapped\n");
-        return -1;
-    }
-    if ( (flags & PTE_U) == 0 )
-    {
-        _printf("\n[GIET ERROR] in _sys_nic_sync_send() : illegal buffer address\n");
-        return -1;
-    }
-    unsigned long long pbuf = ((unsigned long long)ppn << 12) | (vaddr & 0x00000FFF);
-
-    _nic_sync_receive( channel, pbuf );
+        _printf("\n[GIET_ERROR] in _sys_nic_move() : illegal NIC channel index\n");
+        return -1;
+    }
+
+    nic_chbuf_t* chbuf;
+    if ( is_rx ) chbuf = &_nic_rx_chbuf[channel];
+    else         chbuf = &_nic_tx_chbuf[channel];
+
+    // polling on the chbuf status
+    volatile unsigned long long desc;
+    unsigned int full;
+    unsigned int ok      = 0;
+    unsigned int index   = chbuf->index;
+    unsigned int timeout = GIET_NIC_CHBUF_TIMEOUT;
+    while( ok == 0 )
+    {
+        desc  = chbuf->buffer[index];
+        full  =  desc >> 63;
+        if ( (is_rx && full) || ((is_rx == 0) && (full == 0)) )  // success
+        {
+            ok = 1;
+        }
+        else                                                   // retry
+        {
+            timeout--;
+        }
+        if ( timeout == 0 )
+        {
+            _printf("\n[GIET_ERROR] in _sys_ni_move() : timeout\n");
+            return -1;
+        }
+    }
+    kernel_paddr = desc & 0x0000FFFFFFFFFFFFULL;
+    
+    // move one container using, a physical_memcpy
+    if ( is_rx ) _physical_memcpy( user_paddr, 
+                                   kernel_paddr, 
+                                   GIET_NIC_CHBUF_SIZE );
+
+    else         _physical_memcpy( kernel_paddr, 
+                                   user_paddr, 
+                                   GIET_NIC_CHBUF_SIZE );
+
+    // update chbuf status and index
+    if ( is_rx ) chbuf->buffer[index] = desc & 0x0000FFFFFFFFFFFFULL;
+    else         chbuf->buffer[index] = desc | 0x8000000000000000ULL;
+    if ( index == (GIET_NIC_CHBUF_NBUFS - 1) ) chbuf->index = 0;
+    else                                       chbuf->index = index + 1;
+
+    return 0;
+} // end _sys_nic_move()
+
+////////////////////////////////////////
+int _sys_nic_stop( unsigned int is_rx )
+{
+    unsigned int nic_channel;
+    unsigned int cma_channel;
+
+    // get NIC channel index and CMA channel index
+    if ( is_rx )
+    {
+        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
+        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
+    }
+    else
+    {
+        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
+        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
+    }
+
+    if ( nic_channel >= NB_NIC_CHANNELS )
+    {
+        _printf("\n[GIET_ERROR] in _sys_nic_start(): NIC channel not allocated\n");
+        return -1;
+    }
+    if ( cma_channel >= NB_CMA_CHANNELS )
+    {
+        _printf("\n[GIET_ERROR] in _sys_nic_start(): CMA channel not allocated\n");
+        return -1;
+    }
+
+    // desactivates the NIC channel
+    _nic_channel_stop( nic_channel, is_rx );
+
+    // desactivates the CMA channel
+    _cma_channel_stop( cma_channel );
 
     return 0;
@@ -434,8 +611,6 @@
 int _sys_fbf_cma_alloc()
 {
-#if NB_CMA_CHANNELS > 0
-
    // get a new CMA channel index 
-    unsigned int channel = _cma_channel_allocator;
+    unsigned int channel = _atomic_increment( &_cma_channel_allocator );
     unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
     unsigned int vspace  = _get_context_slot( CTX_VSID_ID );
@@ -450,20 +625,7 @@
         _printf("\n[GIET WARNING] FBF_CMA channel %d allocated "
                 " to thread %d in vspace %d\n", channel, thread, vspace );
-    }
-
-    // register channel index in task context
-    _set_context_slot( CTX_FBCMA_ID, channel );
-
-    // update CMA channel allocator
-    _cma_channel_allocator++;
-
-    return 0;
-
-#else
-
-    _printf("\n[GIET ERROR] in _fb_cma_start() : NB_CMA_CHANNELS = 0\n");
-    return -1;
-
-#endif
+        _set_context_slot( CTX_CMA_FB_ID, channel );
+        return 0;
+    }
 } // end sys_fbf_cma_alloc()
 
@@ -483,5 +645,5 @@
 
     // get channel index
-    unsigned int channel = _get_context_slot( CTX_FBCMA_ID );
+    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
 
     if ( channel >= NB_CMA_CHANNELS )
@@ -603,5 +765,5 @@
 
     // call CMA driver to start transfer
-    _cma_start_channel( channel, 
+    _cma_channel_start( channel, 
                         chbuf_paddr,
                         2,
@@ -628,5 +790,5 @@
 
     // get channel index
-    unsigned int channel = _get_context_slot( CTX_FBCMA_ID );
+    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
 
     if ( channel >= NB_CMA_CHANNELS )
@@ -709,5 +871,5 @@
 
     // get channel index
-    unsigned int channel = _get_context_slot( CTX_FBCMA_ID );
+    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
 
     if ( channel >= NB_CMA_CHANNELS )
@@ -718,5 +880,5 @@
 
     // Desactivate CMA channel
-    _cma_stop_channel( channel );
+    _cma_channel_stop( channel );
 
     return 0;
Index: /soft/giet_vm/giet_kernel/sys_handler.h
===================================================================
--- /soft/giet_vm/giet_kernel/sys_handler.h	(revision 448)
+++ /soft/giet_vm/giet_kernel/sys_handler.h	(revision 449)
@@ -14,4 +14,5 @@
 
 #include <mapping_info.h>
+#include <giet_config.h>
 
 ///////////////////////////////////////////////////////////////////////////////////
@@ -22,5 +23,5 @@
 
 ///////////////////////////////////////////////////////////////////////////////////
-// This structure can be used by the vci_chbuf_dma component to transfer a stream 
+// This structure is used by the vci_chbuf_dma component to transfer a stream 
 // of images from two buffers in user space to the frame buffer in kernel space.
 // It contains two chbuf descriptors
@@ -35,6 +36,26 @@
     unsigned long long  fbf;      // physical address + status for user buffer 0 
     unsigned int        length;   // buffer length (bytes)
-    unsigned int        padding;  // for 32 bytes alignment
+    unsigned int        padding;  // 8 bytes alignment
 } fbf_chbuf_t;   
+
+//////////////////////////////////////////////////////////////////////////////////
+// This structure define the generic chained buffer used by the vci_chbuf_dma
+// component to move a stream of containers to or from the vci_multi_nic component.
+// The same structure is used for both TX or RX transfers.
+// The single buffer size and the number of buffers must be defined by the 
+// GIET_NIC_CHBUF_SIZE and GIET_NIC_CHBUF_NBUFS parameters in giet_config.h.
+// - The buffer array is the chbuf descriptor, shared by the vci_chbuf_dma,
+//   and by the kernel.
+// - The index field is only used by the kernel. It define the currently pointed 
+//   buffer for read (RX transfer) or write (TX transfer).
+//////////////////////////////////////////////////////////////////////////////////
+
+typedef struct nic_chbuf_s
+{
+    unsigned long long  buffer[GIET_NIC_CHBUF_NBUFS];      // chbuf descriptor 
+    unsigned int        index;                             // current buffer index
+    unsigned int        padding;                           // 8 bytes alignment
+} nic_chbuf_t;
+
 
 //////////////////////////////////////////////////////////////////////////////////
@@ -72,9 +93,14 @@
 //////////////////////////////////////////////////////////////////////////////
 
-int _sys_nic_alloc();
+int _sys_nic_alloc( unsigned int is_rx );
 
-int _sys_nic_sync_send( void* vbuf );
+int _sys_nic_start( unsigned int is_rx,
+                    unsigned int mac4,
+                    unsigned int mac2 );
 
-int _sys_nic_sync_receive( void* vbuf );
+int _sys_nic_move( unsigned int is_rx,
+                   void*        buffer );
+
+int _sys_nic_stop( unsigned int is_rx );
 
 //////////////////////////////////////////////////////////////////////////////
