Index: soft/giet_vm/sys/drivers.c
===================================================================
--- soft/giet_vm/sys/drivers.c	(revision 249)
+++ soft/giet_vm/sys/drivers.c	(revision 253)
@@ -5,5 +5,6 @@
 // Copyright (c) UPMC-LIP6
 ///////////////////////////////////////////////////////////////////////////////////
-// The drivers.c and drivers.h files are part ot the GIET-VM nano kernel.
+// The drivers.c and drivers.h files are part ot the GIET-VM kernel.
+//
 // They contains the drivers for the peripherals available in the SoCLib library:
 // - vci_multi_tty
@@ -11,15 +12,14 @@
 // - vci_multi_dma
 // - vci_multi_icu
-// - vci_xicu & vci_multi_icu
+// - vci_xicu
 // - vci_gcd
 // - vci_frame_buffer
 // - vci_block_device
-//
-// For the peripherals replicated in each cluster (ICU, TIMER, DMA),
+// - vci_multi_nic
+// - vci_chbuf_dma
+//
+// For the peripherals replicated in each cluster (ICU, TIMER, XCU, DMA, MMC),
 // the corresponding (virtual) base addresses must be completed by an offset 
 // depending on the cluster index.
-//
-// The following global parameter must be defined in the giet_config.h file:
-// - GIET_CLUSTER_INCREMENT
 //
 // The following global parameters must be defined in the hard_config.h file:
@@ -32,4 +32,5 @@
 // The following virtual base addresses must be defined in the giet_vsegs.ld file:
 // - seg_icu_base
+// - seg_xcu_base
 // - seg_tim_base
 // - seg_dma_base
@@ -42,5 +43,5 @@
 // - seg_iob_base
 // - seg_mmc_base
-//
+// - vseg_cluster_increment
 ///////////////////////////////////////////////////////////////////////////////////
 
@@ -68,8 +69,4 @@
 #if (NB_PROCS_MAX > 8)
 # error: NB_PROCS_MAX cannot be larger than 8!
-#endif
-
-#if !defined(GIET_CLUSTER_INCREMENT) 
-# error: You must define GIET_CLUSTER_INCREMENT in the giet_config.h file
 #endif
 
@@ -153,9 +150,7 @@
 // The (virtual) base address of the associated segment is:
 //
-//       timer_address = seg_icu_base + cluster_id * GIET_CLUSTER_INCREMENT
-//
-// - cluster id is an explicit argument of all access functions
-// - seg_icu_base must be defined in the giet_vsegs.ld file
-// - GIET_CLUSTER_INCREMENT must be defined in the giet_config.h file
+//       timer_address = seg_tim_base + cluster_id * vseg_cluster_increment
+//   or  timer_address = seg_xcu_base + cluster_id * vseg_cluster_increment
+//
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -184,11 +179,11 @@
 
 #if USE_XICU
-    unsigned int * timer_address = (unsigned int *) ((char *) &seg_icu_base + 
-                                                     (cluster_id * GIET_CLUSTER_INCREMENT));
+    unsigned int* timer_address = (unsigned int *) ((unsigned int)&seg_xcu_base + 
+                                  (cluster_id * (unsigned int)&vseg_cluster_increment));
 
     timer_address[XICU_REG(XICU_PTI_PER, local_id)] = period;
 #else
-    unsigned int* timer_address = (unsigned int *) ((char *) &seg_tim_base + 
-                                                    (cluster_id * GIET_CLUSTER_INCREMENT));
+    unsigned int* timer_address = (unsigned int *) ((unsigned int)&seg_tim_base + 
+                                  (cluster_id * (unsigned int)&vseg_cluster_increment));
 
     timer_address[local_id * TIMER_SPAN + TIMER_PERIOD] = period;
@@ -212,11 +207,11 @@
 
 #if USE_XICU
-    unsigned int * timer_address = (unsigned int *) ((char *) &seg_icu_base + 
-                                                     (cluster_id * GIET_CLUSTER_INCREMENT));
+    unsigned int * timer_address = (unsigned int *) ((unsigned int)&seg_xcu_base + 
+                                   (cluster_id * (unsigned int)&vseg_cluster_increment));
 
     timer_address[XICU_REG(XICU_PTI_PER, local_id)] = 0;
 #else
-    unsigned int* timer_address = (unsigned int *) ((char *) &seg_tim_base + 
-                                                    (cluster_id * GIET_CLUSTER_INCREMENT));
+    unsigned int* timer_address = (unsigned int *) ((unsigned int)&seg_tim_base + 
+                                  (cluster_id * (unsigned int)&vseg_cluster_increment));
 
     timer_address[local_id * TIMER_SPAN + TIMER_MODE] = 0;
@@ -224,5 +219,4 @@
     return 0;
 }
-
 
 //////////////////////////////////////////////////////////////////////////////
@@ -242,12 +236,12 @@
 
 #if USE_XICU
-    unsigned int * timer_address = (unsigned int *) ((char *) &seg_icu_base +
-                                                     (cluster_id * GIET_CLUSTER_INCREMENT));
+    unsigned int * timer_address = (unsigned int *) ((unsigned int)&seg_xcu_base +
+                                   (cluster_id * (unsigned int)&vseg_cluster_increment));
 
     unsigned int bloup = timer_address[XICU_REG(XICU_PTI_ACK, local_id)];
     bloup++; // to avoid a warning 
 #else
-    unsigned int * timer_address = (unsigned int *) ((char *) &seg_tim_base + 
-            (cluster_id * GIET_CLUSTER_INCREMENT));
+    unsigned int * timer_address = (unsigned int *) ((unsigned int)&seg_tim_base + 
+                                   (cluster_id * (unsigned int)&vseg_cluster_increment));
 
     timer_address[local_id * TIMER_SPAN + TIMER_RESETIRQ] = 0;
@@ -255,6 +249,4 @@
     return 0;
 }
-
-
 
 ///////////////////////////////////////////////////////////////////////
@@ -263,5 +255,5 @@
 // This function resets the period at the end of which
 // an interrupt is sent. To do so, we re-write the period
-// ini the proper register, what causes the count to restart.
+// in the proper register, what causes the count to restart.
 // The period value is read from the same (TIMER_PERIOD) register,
 // this is why in appearance we do nothing useful (read a value
@@ -269,5 +261,6 @@
 // This function is called during a context switch (user or preemptive)
 ///////////////////////////////////////////////////////////////////////
-unsigned int _timer_reset_irq_cpt(unsigned int cluster_id, unsigned int local_id) {
+unsigned int _timer_reset_irq_cpt( unsigned int cluster_id, 
+                                   unsigned int local_id) {
     // parameters checking 
     if (cluster_id >= NB_CLUSTERS) {
@@ -279,13 +272,18 @@
 
 #if USE_XICU
-    unsigned int * timer_address = (unsigned int *) ((char *) &seg_icu_base + (cluster_id * GIET_CLUSTER_INCREMENT));
+    unsigned int * timer_address = (unsigned int *) ((unsigned int) &seg_xcu_base + 
+                                   (cluster_id * (unsigned int)&vseg_cluster_increment));
+
     unsigned int timer_period = timer_address[XICU_REG(XICU_PTI_PER, local_id)];
 
-    // we write 0 first because if the timer is currently running, the corresponding timer counter is not reset
+    // we write 0 first because if the timer is currently running, 
+    //the corresponding timer counter is not reset
     timer_address[XICU_REG(XICU_PTI_PER, local_id)] = 0;
     timer_address[XICU_REG(XICU_PTI_PER, local_id)] = timer_period;
 #else
     // We suppose that the TIMER_MODE register value is 0x3
-    unsigned int * timer_address = (unsigned int *) ((char *) &seg_tim_base + (cluster_id * GIET_CLUSTER_INCREMENT));
+    unsigned int * timer_address = (unsigned int *) ((unsigned int)&seg_tim_base + 
+                                   (cluster_id * (unsigned int)&vseg_cluster_increment));
+
     unsigned int timer_period = timer_address[local_id * TIMER_SPAN + TIMER_PERIOD];
 
@@ -295,5 +293,4 @@
     return 0;
 }
-
 
 /////////////////////////////////////////////////////////////////////////////////
@@ -412,14 +409,12 @@
 // This hardware component is replicated in all clusters.
 // There is one vci_multi_icu (or vci_xicu) component per cluster, 
-// and the number of independant ICUs is equal to NB_PROCS_MAX, 
+// and the number of ICU channels is equal to NB_PROCS_MAX, 
 // because there is one private interrupt controler per processor.
 ////////////////////////////////////////////////////////////////////////////////
 // The (virtual) base address of the associated segment is:
 //
-//       icu_address = seg_icu_base + cluster_id * GIET_CLUSTER_INCREMENT
-//
-// - cluster id is an explicit argument of all access functions
-// - seg_icu_base must be defined in the giet_vsegs.ld file
-// - GIET_CLUSTER_INCREMENT must be defined in the giet_config.h file
+//       icu_address = seg_icu_base + cluster_id * vseg_cluster_increment
+//  or   icu_address = seg_xcu_base + cluster_id * vseg_cluster_increment
+//
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -434,5 +429,5 @@
                             unsigned int proc_id,
                             unsigned int value,
-                            unsigned int is_timer) 
+                            unsigned int is_PTI) 
 {
     // parameters checking 
@@ -440,8 +435,8 @@
     if (proc_id >= NB_PROCS_MAX)   return 1; 
 
-    unsigned int * icu_address = (unsigned int *) ((char *) &seg_icu_base + 
-                                                   (cluster_id * GIET_CLUSTER_INCREMENT));
 #if USE_XICU
-    if (is_timer) 
+    unsigned int * icu_address = (unsigned int *) ((unsigned int)&seg_xcu_base + 
+                                 (cluster_id * (unsigned int)&vseg_cluster_increment));
+    if (is_PTI) 
     {
         icu_address[XICU_REG(XICU_MSK_PTI_ENABLE, proc_id)] = value;
@@ -452,9 +447,11 @@
     }
 #else
+    unsigned int * icu_address = (unsigned int *) ((unsigned int)&seg_icu_base + 
+                                 (cluster_id * (unsigned int)&vseg_cluster_increment));
+
     icu_address[proc_id * ICU_SPAN + ICU_MASK_SET] = value; 
 #endif
     return 0;
 }
-
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -473,7 +470,8 @@
     if (proc_id >= NB_PROCS_MAX)    return 1;
 
-    unsigned int * icu_address = (unsigned int *) ((char *) &seg_icu_base + 
-                                                   (cluster_id * GIET_CLUSTER_INCREMENT));
 #if USE_XICU
+    unsigned int * icu_address = (unsigned int *) ((unsigned int)&seg_xcu_base + 
+                                 (cluster_id * (unsigned int)&vseg_cluster_increment));
+
     unsigned int prio = icu_address[XICU_REG(XICU_PRIO, proc_id)];
     unsigned int pti_ok = (prio & 0x00000001);
@@ -488,9 +486,11 @@
     else             { *buffer = 32; }
 #else
+    unsigned int * icu_address = (unsigned int *) ((unsigned int)&seg_icu_base + 
+                                 (cluster_id * (unsigned int)&vseg_cluster_increment));
+
     *buffer = icu_address[proc_id * ICU_SPAN + ICU_IT_VECTOR]; 
 #endif
     return 0;
 }
-
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -912,8 +912,6 @@
 // The (virtual) base address of the associated segment is:
 //
-//       dma_address = seg_dma_base + cluster_id * GIET_CLUSTER_INCREMENT
-//
-// - seg_dma_base  must be defined in the giet_vsegs.ld file
-// - GIET_CLUSTER_INCREMENT  must be defined in the giet_config.h file
+//       dma_address = seg_dma_base + cluster_id * vseg_cluster_increment
+//
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -942,6 +940,6 @@
 
     // compute DMA base address
-    unsigned int * dma_address = (unsigned int *) ((char *) &seg_dma_base + 
-                                                   (cluster_id * GIET_CLUSTER_INCREMENT));
+    unsigned int * dma_address = (unsigned int *) ((unsigned int)&seg_dma_base + 
+                                 (cluster_id * (unsigned int)&vseg_cluster_increment));
 
     dma_address[channel_id * DMA_SPAN + DMA_RESET] = 0;            
@@ -951,5 +949,4 @@
 #endif
 }
-
 
 //////////////////////////////////////////////////////////////////////////////////
@@ -966,6 +963,6 @@
 
     // compute DMA base address
-    unsigned int * dma_address = (unsigned int *) ((char *) &seg_dma_base + 
-                                                   (cluster_id * GIET_CLUSTER_INCREMENT));
+    unsigned int * dma_address = (unsigned int *) ((unsigned int)&seg_dma_base + 
+                                 (cluster_id * (unsigned int)&vseg_cluster_increment));
 
     *status = dma_address[channel_id * DMA_SPAN + DMA_LEN];
@@ -975,5 +972,4 @@
 #endif
 }
-
 
 //////////////////////////////////////////////////////////////////////////////////
@@ -1031,6 +1027,6 @@
     unsigned int cluster_id  = dma_id / NB_DMA_CHANNELS;
     unsigned int channel_id  = dma_id % NB_DMA_CHANNELS;
-    unsigned int * dma_vbase  = (unsigned int *) ((char *) &seg_dma_base + 
-                                                (cluster_id * GIET_CLUSTER_INCREMENT));
+    unsigned int * dma_vbase = (unsigned int *) ((unsigned int)&seg_dma_base + 
+                               (cluster_id * (unsigned int)&vseg_cluster_increment));
     // get page table address
     unsigned int user_ptab = _get_context_slot(CTX_PTAB_ID);
@@ -1196,5 +1192,4 @@
 }  // end _dma_transfer()  
 
-
 //////////////////////////////////////////////////////////////////////////////////
 // _dma_completed()
@@ -1257,15 +1252,21 @@
 //     VciFrameBuffer driver
 //////////////////////////////////////////////////////////////////////////////////
-// The vci_frame_buffer device can be accessed directly by software with memcpy(),
-// or it can be accessed through a multi-channels DMA component:
+// There three methods to access the VciFrameBuffer device:
 //  
-// The '_fb_sync_write' and '_fb_sync_read' functions use a memcpy strategy to
-// implement the transfer between a data buffer (user space) and the frame
+// 1) The _fb_sync_write() and _fb_sync_read() functions use a memcpy strategy 
+// to implement the transfer between a data buffer (user space) and the frame
 // buffer (kernel space). They are blocking until completion of the transfer.
 //
-// The '_fb_write()', '_fb_read()' and '_fb_completed()' functions use the 
-// VciMultiDma components (distributed in the clusters) to transfer data 
-// between the user buffer and the frame buffer. A DMA channel is
-// allocated to each task requesting it in the mapping_info data structure.
+// 2) The _fb_dma_write(), _fb_dma_read() and _fb_mdma_completed() functions use 
+// the VciMultiDma components (distributed in the clusters) to transfer data 
+// between the user buffer and the frame buffer. 
+// A DMA channel is allocated to the task requesting it in the mapping_info,
+// and stored in the task context.
+//
+// 3) The _fb_cma_init(), _fb_cma_write() and _fb_cma_stop() functions use
+// the VciChbufDma component (non replicated) to transfer a flow of images from
+// an user space chained buffer (two buffers) to the frame buffer.
+// A CMA channel is allocated to the task requesting it in the mapping_info,
+// and stored in the task context.
 //////////////////////////////////////////////////////////////////////////////////
 
@@ -1306,5 +1307,5 @@
 
 //////////////////////////////////////////////////////////////////////////////////
-// _fb_write()
+// _fb_dma_write()
 // Transfer data from a memory buffer to the frame_buffer device using  DMA.
 // - offset : offset (in bytes) in the frame buffer.
@@ -1313,7 +1314,7 @@
 // Returns 0 if success, > 0 if error.
 //////////////////////////////////////////////////////////////////////////////////
-unsigned int _fb_write( unsigned int   offset, 
-                        const void*    buffer, 
-                        unsigned int   length) 
+unsigned int _fb_dma_write( unsigned int   offset, 
+                            const void*    buffer, 
+                            unsigned int   length) 
 {
     return _dma_transfer( 0,             // frame buffer
@@ -1323,17 +1324,15 @@
                           length );
 }
-
-
-//////////////////////////////////////////////////////////////////////////////////
-// _fb_read()
+//////////////////////////////////////////////////////////////////////////////////
+// _fb_dma_read()
 // Transfer data from the frame_buffer device to a memory buffer using  DMA.
 // - offset : offset (in bytes) in the frame buffer.
-// - buffer : base address of the memory buffer.
-// - length : number of bytes to be transfered.
+// - buffer : virtual base address of the user buffer.
+// - length : buffer size (number of bytes)
 // Returns 0 if success, > 0 if error.
 //////////////////////////////////////////////////////////////////////////////////
-unsigned int _fb_read( unsigned int   offset, 
-                       const void*    buffer, 
-                       unsigned int   length ) 
+unsigned int _fb_dma_read( unsigned int   offset,  
+                           const void*    buffer, 
+                           unsigned int   length ) 
 {
     return _dma_transfer( 0,    // frame buffer
@@ -1343,6 +1342,4 @@
                           length );
 }
-
-
 //////////////////////////////////////////////////////////////////////////////////
 // _fb_completed()
@@ -1352,14 +1349,269 @@
 // (1 == read error / 2 == DMA idle error / 3 == write error)
 //////////////////////////////////////////////////////////////////////////////////
-unsigned int _fb_completed() 
+unsigned int _fb_dma_completed() 
 {
     return _dma_completed();
 }
 
+// This structure contains two chbuf descriptors that can be used by 
+// the VciChbufDma component to tranfer a flow of images:
+// - The SRC chbuf descriptor contain two slots (two user buffers)
+// - The DST chbuf descriptor contains only one slot (frame buffer)
+typedef struct fb_cma_channel_s
+{
+    paddr_t buf0;   // physical address + status for user buffer 0 
+    paddr_t buf1;   // physical address + status for user buffer 1
+    paddr_t fbf;    // physical address + status for frame buffer
+} fb_cma_channel_t;
+
+in_unckdata volatile fb_cma_channel_t _fb_cma_channel[NB_CMA_CHANNELS];
+
+//////////////////////////////////////////////////////////////////////////////////
+// _fb_cma_init()
+// This function does two things:
+// 1) Initialises the SRC chbuf descriptor (two buffers), and the DST
+//    chbuf descriptor (one single frame buffer), after translating  
+//    virtual addresses to physical addresses, and checking access rights.
+// 2) Starts the CMA hardware channel, that will permanently try to display
+//    images as soon as the SRC buffers are filled.
+// Arguments are:
+// - vbase0 : virtual base address of the first user buffer.
+// - vbase1 : virtual base address of the second user buffer.
+// - length : user buffer size (number of bytes)
+// Returns 0 if success, > 0 if error 
+//////////////////////////////////////////////////////////////////////////////////
+unsigned int _fb_cma_init( const void*  vbase0,
+                           const void*  vbase1,
+                           unsigned int length ) 
+{
+#if NB_CMA_CHANNELS > 0
+
+    unsigned int  channel_id;       // CMA channel index
+    unsigned int  user_ptab;        // page table virtual address
+    unsigned int  ko;               // unsuccessfull V2P translation
+    unsigned int  vpn;              // virtual page number
+    unsigned int  flags;            // protection flags
+    unsigned int  ppn;              // physical page number
+    paddr_t       src_chbuf_pbase;  // physical address for SRC chbuf descriptor
+    paddr_t       dst_chbuf_pbase;  // physical address for SRC chbuf descriptor
+
+    // get CMA channel index
+    channel_id = _get_context_slot(CTX_CMA_ID);
+    if ( channel_id >= NB_CMA_CHANNELS )
+    {
+        _get_lock(&_tty_put_lock);
+        _puts("\n[GIET ERROR] in _fb_cma_init() : CMA channel index too large\n");
+        _release_lock(&_tty_put_lock);
+        return 1;
+    }
+
+    // check user buffer virtual addresses and length alignment
+    if ( ((unsigned int)vbase0 & 0x3) || ((unsigned int)vbase1 & 0x3) || (length & 0x3) ) 
+    {
+        _get_lock(&_tty_put_lock);
+        _puts("\n[GIET ERROR] in _fb_cma_init() : user buffer not word aligned\n");
+        _release_lock(&_tty_put_lock);
+        return 1;
+    }
+
+    // get page table virtual address
+    user_ptab = _get_context_slot(CTX_PTAB_ID);
+
+    // get frame buffer virtual address
+
+    // compute and register frame buffer physical address
+    vpn = ((unsigned int)&seg_fbf_base) >> 12;
+    ko = _v2p_translate( (page_table_t*) user_ptab, 
+                         vpn, 
+                         &ppn, 
+                         &flags );
+    if (ko) 
+    {
+        _get_lock(&_tty_put_lock);
+        _puts("\n[GIET ERROR] in _fb_cma_init() : frame buffer unmapped\n");
+        _release_lock(&_tty_put_lock);
+        return 1;
+    }
+    _fb_cma_channel[channel_id].fbf = ((paddr_t)ppn << 12) | (vpn & 0x00000FFF);
+
+    // Compute and register first user buffer physical address
+    vpn = (unsigned int)vbase0 >> 12; 
+    ko = _v2p_translate( (page_table_t*) user_ptab, 
+                         vpn, 
+                         &ppn, 
+                         &flags );
+    if (ko) 
+    {
+        _get_lock(&_tty_put_lock);
+        _puts("\n[GIET ERROR] in _fb_cma_init() : user buffer 0 unmapped\n");
+        _release_lock(&_tty_put_lock);
+        return 1;
+    } 
+    if ((flags & PTE_U) == 0) 
+    {
+        _get_lock(&_tty_put_lock);
+        _puts("[GIET ERROR] in _fb_cma_init() : user buffer 0 not in user space\n");
+        _release_lock(&_tty_put_lock);
+        return 1; 
+    }
+    _fb_cma_channel[channel_id].buf0 = ((paddr_t)ppn << 12) | (vpn & 0x00000FFF);
+
+    // Compute and register second user buffer physical address
+    vpn = (unsigned int)vbase1 >> 12; 
+    ko = _v2p_translate( (page_table_t*) user_ptab, 
+                         vpn, 
+                         &ppn, 
+                         &flags );
+    if (ko) 
+    {
+        _get_lock(&_tty_put_lock);
+        _puts("\n[GIET ERROR] in _fb_cma_init() : user buffer 1 unmapped\n");
+        _release_lock(&_tty_put_lock);
+        return 1;
+    } 
+    if ((flags & PTE_U) == 0) 
+    {
+        _get_lock(&_tty_put_lock);
+        _puts("[GIET ERROR] in _fb_cma_init() : user buffer 1 not in user space\n");
+        _release_lock(&_tty_put_lock);
+        return 1; 
+    }
+    _fb_cma_channel[channel_id].buf1 = ((paddr_t)ppn << 12) | (vpn & 0x00000FFF);
+
+    // Compute physical adress of the SRC chbuf descriptor
+    vpn = ((unsigned int)(&_fb_cma_channel[channel_id].buf0)) >> 12;
+    ko = _v2p_translate( (page_table_t*) user_ptab, 
+                         vpn,
+                         &ppn, 
+                         &flags );
+    if (ko) 
+    {
+        _get_lock(&_tty_put_lock);
+        _puts("\n[GIET ERROR] in _fb_cma_init() : SRC chbuf descriptor unmapped\n");
+        _release_lock(&_tty_put_lock);
+        return 1;
+    } 
+    src_chbuf_pbase = (((paddr_t)ppn) << 12) | (vpn & 0x00000FFF);
+
+    // Compute physical adress of the DST chbuf descriptor
+    vpn = ((unsigned int)(&_fb_cma_channel[channel_id].fbf)) >> 12;
+    ko = _v2p_translate( (page_table_t*) user_ptab, 
+                         vpn,
+                         &ppn, 
+                         &flags );
+    if (ko) 
+    {
+        _get_lock(&_tty_put_lock);
+        _puts("\n[GIET ERROR] in _fb_cma_init() : DST chbuf descriptor unmapped\n");
+        _release_lock(&_tty_put_lock);
+        return 1;
+    } 
+    dst_chbuf_pbase = (((paddr_t)ppn) << 12) | (vpn & 0x00000FFF);
+
+    // CMA channel activation
+    unsigned int* cma_vbase = (unsigned int *)&seg_cma_base;
+    unsigned int  offset     = channel_id * CHBUF_CHANNEL_SPAN;
+
+    cma_vbase[offset + CHBUF_SRC_DESC]  = (unsigned int)(src_chbuf_pbase & 0xFFFFFFFF);
+    cma_vbase[offset + CHBUF_SRC_EXT]   = (unsigned int)(src_chbuf_pbase >> 32);
+    cma_vbase[offset + CHBUF_SRC_NBUFS] = 2;
+    cma_vbase[offset + CHBUF_DST_DESC]  = (unsigned int)(dst_chbuf_pbase & 0xFFFFFFFF);
+    cma_vbase[offset + CHBUF_DST_EXT]   = (unsigned int)(dst_chbuf_pbase >> 32);
+    cma_vbase[offset + CHBUF_DST_NBUFS] = 1;
+    cma_vbase[offset + CHBUF_BUF_SIZE]  = length;
+    cma_vbase[offset + CHBUF_PERIOD]    = 300;
+    cma_vbase[offset + CHBUF_RUN]       = 1;
+
+    return 0;
+
+#else
+
+    _get_lock(&_tty_put_lock);
+    _puts("\n[GIET ERROR] in _fb_cma_init() : no CMA channel allocated\n");
+    _release_lock(&_tty_put_lock);
+
+    return 1;
+#endif
+}
+//////////////////////////////////////////////////////////////////////////////////
+// _fb_cma_write()
+// This function updates the status of the SRC and DST chbuf descriptors
+// to allows the CMA component to transfer another buffer.
+// - buffer_id : user buffer index (0 => buf0 / not 0 => buf1)
+// Returns 0 if success, > 0 if error 
+//////////////////////////////////////////////////////////////////////////////////
+unsigned int _fb_cma_write( unsigned int buffer_id )
+{
+#if NB_CMA_CHANNELS > 0
+
+    // get CMA channel index 
+    unsigned int channel_id = _get_context_slot(CTX_CMA_ID);
+    if ( channel_id >= NB_CMA_CHANNELS )
+    {
+        _get_lock(&_tty_put_lock);
+        _puts("\n[GIET ERROR] in _fb_cma_write() : CMA channel index too large\n");
+        _release_lock(&_tty_put_lock);
+        return 1;
+    }
+    // set SRC full 
+    if ( buffer_id == 0 )
+    _fb_cma_channel[channel_id].buf0 = _fb_cma_channel[channel_id].buf0 
+                                       | 0x8000000000000000ULL;
+    else
+    _fb_cma_channel[channel_id].buf1 = _fb_cma_channel[channel_id].buf1 
+                                       | 0x8000000000000000ULL;
+    // set DST empty
+    _fb_cma_channel[channel_id].fbf  = _fb_cma_channel[channel_id].fbf
+                                       & 0x7FFFFFFFFFFFFFFFULL;
+    return 0;
+
+#else
+
+    _get_lock(&_tty_put_lock);
+    _puts("\n[GIET ERROR] in _fb_cma_channel() : no CMA channel allocated\n");
+    _release_lock(&_tty_put_lock);
+    return 1;
+
+#endif
+}
+//////////////////////////////////////////////////////////////////////////////////
+// _fb_cma_stop()
+// This function desactivates the CMA channel allocated to the calling task.
+// Returns 0 if success, > 0 if error 
+//////////////////////////////////////////////////////////////////////////////////
+unsigned int _fb_cma_stop( unsigned int buffer_id )
+{
+#if NB_CMA_CHANNELS > 0
+
+    // get CMA channel allocated 
+    unsigned int channel_id = _get_context_slot(CTX_CMA_ID);
+    if ( channel_id >= NB_CMA_CHANNELS )
+    {
+        _get_lock(&_tty_put_lock);
+        _puts("\n[GIET ERROR] in _fb_cma_stop() : CMA channel index too large\n");
+        _release_lock(&_tty_put_lock);
+        return 1;
+    }
+    // CMA channel desactivation
+    unsigned int* cma_vbase = (unsigned int *)&seg_cma_base;
+    unsigned int  offset     = channel_id * CHBUF_CHANNEL_SPAN;
+    cma_vbase[offset + CHBUF_RUN] = 0;
+    return 0;
+
+#else
+
+    _get_lock(&_tty_put_lock);
+    _puts("\n[GIET ERROR] in _fb_cma_stop() : no CMA channel allocated\n");
+    _release_lock(&_tty_put_lock);
+    return 1;
+
+#endif
+}
+    
 //////////////////////////////////////////////////////////////////////////////////
 //     VciMultiNic driver
 //////////////////////////////////////////////////////////////////////////////////
 // The VciMultiNic device can be accessed directly by software with memcpy(),
-// or it can be accessed through a multi-channels DMA component:
+// or it can be accessed through a multi-channels CMA component:
 //  
 // The '_nic_sync_write' and '_nic_sync_read' functions use a memcpy strategy to
@@ -1367,8 +1619,10 @@
 // buffer (kernel space). They are blocking until completion of the transfer.
 //
-// The '_nic_write()', '_nic_read()' and '_nic_completed()' functions use the 
-// VciMultiDma components (distributed in the clusters) to transfer data 
-// between the user buffer and the NIC. A  NIDMA channel is allocated to each 
-// task requesting it in the mapping_info data structure.
+// The _nic_cma_init() and _nic_cma_stop() functions use the VciChbufDma component 
+// to transfer a flow of packets from the NIC RX hard chbuf (two containers) 
+// to an user RX chbuf (two containers), and to transfer another flow of packets
+// from an user TX chbuf (two containers) to the NIC TX chbuf (two containers).
+// One NIC channel and two CMA channels must be allocated to the task 
+// in the mapping_info data structure.
 //////////////////////////////////////////////////////////////////////////////////
 
@@ -1376,79 +1630,63 @@
 // _nic_sync_write()
 // Transfer data from an memory buffer to the NIC device using a memcpy.
-// - offset : offset (in bytes) in the frame buffer.
 // - buffer : base address of the memory buffer.
 // - length : number of bytes to be transfered.
 //////////////////////////////////////////////////////////////////////////////////
-unsigned int _nic_sync_write( unsigned int   offset, 
-                              const void*    buffer, 
+unsigned int _nic_sync_write( const void*    buffer,
                               unsigned int   length ) 
 {
-    unsigned char* nic_address = (unsigned char *) &seg_nic_base + offset;
-    memcpy((void *) nic_address, (void *) buffer, length);
-    return 0;
-}
-
-
+    // To be defined
+    // unsigned char* nic_address = (unsigned char *) &seg_nic_base;
+    // memcpy((void *) nic_address, (void *) buffer, length);
+    return 0;
+}
 //////////////////////////////////////////////////////////////////////////////////
 // _nic_sync_read()
 // Transfer data from the NIC device to a memory buffer using a memcpy. 
-// - offset : offset (in bytes) in the frame buffer.
 // - buffer : base address of the memory buffer.
 // - length : number of bytes to be transfered.
 //////////////////////////////////////////////////////////////////////////////////
-unsigned int _nic_sync_read(unsigned int offset, const void * buffer, unsigned int length) {
-    unsigned char *nic_address = (unsigned char *) &seg_nic_base + offset;
-    memcpy((void *) buffer, (void *) nic_address, length);
-    return 0;
-}
-
-
-//////////////////////////////////////////////////////////////////////////////////
-// _nic_write()
-// Transfer data from a memory buffer to the NIC device using  DMA.
-// - offset : offset (in bytes) in the frame buffer.
-// - buffer : base address of the memory buffer.
-// - length : number of bytes to be transfered.
+unsigned int _nic_sync_read( const void*    buffer, 
+                             unsigned int   length ) 
+{
+    // To be defined
+    // unsigned char* nic_address = (unsigned char *) &seg_nic_base;
+    // memcpy((void *) buffer, (void *) nic_address, length);
+    return 0;
+}
+//////////////////////////////////////////////////////////////////////////////////
+// _nic_cma_rx_init()
 // Returns 0 if success, > 0 if error.
 //////////////////////////////////////////////////////////////////////////////////
-unsigned int _nic_write(unsigned int offset, const void * buffer, unsigned int length) {
-    return _dma_transfer(
-            1,            // NIC
-            0,            // write
-            offset,
-            (unsigned int) buffer,
-            length );    
-}
-
-
-//////////////////////////////////////////////////////////////////////////////////
-// _nic_read()
-// Transfer data from the NIC device to a memory buffer using  DMA.
-// - offset : offset (in bytes) in the frame buffer.
-// - buffer : base address of the memory buffer.
-// - length : number of bytes to be transfered.
+unsigned int _nic_cma_rx_init( const void*  buf0,
+                               const void*  buf1,
+                               unsigned int length ) 
+{
+    // to be defined
+    // unsigned char* nic_address = (unsigned char *) &seg_nic_base;
+    return 0;
+}
+//////////////////////////////////////////////////////////////////////////////////
+// _nic_cma_tx_init()
 // Returns 0 if success, > 0 if error.
 //////////////////////////////////////////////////////////////////////////////////
-unsigned int _nic_read(unsigned int offset, const void * buffer, unsigned int length) {
-    return _dma_transfer(
-            1,            // NIC
-            1,            // read
-            offset,
-            (unsigned int) buffer,
-            length );    
-}
-
-
-//////////////////////////////////////////////////////////////////////////////////
-// _nic_completed()
-// This function checks completion of a DMA transfer to or fom a NIC channel.
-// As it is a blocking call, the processor is busy waiting.
-// Returns 0 if success, > 0 if error 
-// (1 == read error / 2 == DMA idle error / 3 == write error)
-//////////////////////////////////////////////////////////////////////////////////
-unsigned int _nic_completed() 
-{
-    return _dma_completed();
-}
+unsigned int _nic_cma_tx_init( const void*  buf0,
+                               const void*  buf1,
+                               unsigned int length ) 
+{
+    // to be defined
+    // unsigned char* nic_address = (unsigned char *) &seg_nic_base;
+    return 0;
+}//////////////////////////////////////////////////////////////////////////////////
+// _nic_cma_stop()
+// Returns 0 if success, > 0 if error.
+//////////////////////////////////////////////////////////////////////////////////
+unsigned int _nic_cma_stop()
+{
+    // to be defined
+    // unsigned char* nic_address = (unsigned char *) &seg_nic_base;
+    return 0;
+}
+
 
 //////////////////////////////////////////////////////////////////////////////////
@@ -1458,4 +1696,9 @@
 // as a set of uncached, memory mapped registers.
 ///////////////////////////////////////////////////////////////////////////////////
+// The (virtual) base address of the associated segment is:
+//
+//       mmc_address = seg_mmc_base + cluster_id * vseg_cluster_increment
+//
+////////////////////////////////////////////////////////////////////////////////
 
 ///////////////////////////////////////////////////////////////////////////////////
@@ -1470,6 +1713,6 @@
     unsigned int cluster_id    = (unsigned int)((buf_paddr>>32)/(256/NB_CLUSTERS));
 
-    unsigned int * mmc_address = (unsigned int *) ((char *) &seg_mmc_base + 
-                                                   (cluster_id * GIET_CLUSTER_INCREMENT));
+    unsigned int * mmc_address = (unsigned int *) ((unsigned int)&seg_mmc_base + 
+                                 (cluster_id * (unsigned int)&vseg_cluster_increment));
 
     // get the lock protecting exclusive access to MEMC
@@ -1485,4 +1728,5 @@
     mmc_address[MEMC_LOCK] = 0;
 }
+
 ///////////////////////////////////////////////////////////////////////////////////
 // _heap_info()
