Index: /soft/giet_vm/giet_kernel/sys_handler.c
===================================================================
--- /soft/giet_vm/giet_kernel/sys_handler.c	(revision 613)
+++ /soft/giet_vm/giet_kernel/sys_handler.c	(revision 614)
@@ -102,16 +102,17 @@
 
 ////////////////////////////////////////////////////////////////////////////
-//     NIC_RX and NIC_TX chbuf arrays 
+//     NIC_RX and NIC_TX kernel chbuf arrays 
 ////////////////////////////////////////////////////////////////////////////
 
 __attribute__((section(".kdata")))
-nic_chbuf_t  _nic_rx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(64)));
+ker_chbuf_t  _nic_ker_rx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(64)));
 
 __attribute__((section(".kdata")))
-nic_chbuf_t  _nic_tx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(64)));
+ker_chbuf_t  _nic_ker_tx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(64)));
 
 ////////////////////////////////////////////////////////////////////////////
 // FBF related chbuf descriptors array, indexed by the CMA channel index.
 // Physical addresses of these chbuf descriptors required for L2 cache sync.
+// FBF status
 ////////////////////////////////////////////////////////////////////////////
 
@@ -121,4 +122,7 @@
 __attribute__((section(".kdata")))
 unsigned long long _fbf_chbuf_paddr[NB_CMA_CHANNELS];
+
+__attribute__((section(".kdata")))
+buffer_status_t _fbf_status[NB_CMA_CHANNELS] __attribute__((aligned(64)));
 
 ////////////////////////////////////////////////////////////////////////////
@@ -141,14 +145,14 @@
     &_sys_global_task_id,            /* 0x09 */ 
     &_sys_fbf_cma_alloc,             /* 0x0A */
-    &_sys_fbf_cma_start,             /* 0x0B */
-    &_sys_fbf_cma_display,           /* 0x0C */
-    &_sys_fbf_cma_stop,              /* 0x0D */
-    &_sys_task_exit,                 /* 0x0E */
-    &_sys_procs_number,              /* 0x0F */
-
-    &_sys_fbf_sync_write,            /* 0x10 */
-    &_sys_fbf_sync_read,             /* 0x11 */
-    &_sys_thread_id,                 /* 0x12 */
-    &_sys_ukn,                       /* 0x13 */
+    &_sys_fbf_cma_init_buf,          /* 0x0B */
+    &_sys_fbf_cma_start,             /* 0x0C */
+    &_sys_fbf_cma_display,           /* 0x0D */
+    &_sys_fbf_cma_stop,              /* 0x0E */
+    &_sys_task_exit,                 /* 0x0F */
+
+    &_sys_procs_number,              /* 0x10 */
+    &_sys_fbf_sync_write,            /* 0x11 */
+    &_sys_fbf_sync_read,             /* 0x12 */
+    &_sys_thread_id,                 /* 0x13 */
     &_sys_tim_alloc,                 /* 0x14 */
     &_sys_tim_start,                 /* 0x15 */ 
@@ -785,4 +789,8 @@
     }
 
+    ////////////////////////////////////////////////////////
+    // Step 1: get and register CMA and NIC channel index //
+    ////////////////////////////////////////////////////////
+
     // get a NIC_RX or NIC_TX channel index 
     unsigned int nic_channel;
@@ -826,9 +834,16 @@
     }
 
+    /////////////////////////////////////////////////////////////////////////////////
+    // Step 2: loop on all the clusters                                            //
+    // Allocate the kernel containers and status, compute the container and the    //
+    // status physical addresses, fill and synchronize the kernel CHBUF descriptor //
+    /////////////////////////////////////////////////////////////////////////////////
+
     // physical addresses to be registered in the CMA registers
     unsigned long long nic_chbuf_pbase;     // NIC chbuf physical address
     unsigned long long ker_chbuf_pbase;     // kernel chbuf physical address
 
-    // allocate one kernel container per cluster in the (xmax / ymax) mesh
+    // allocate one kernel container and one status variable per cluster in the
+    // (xmax / ymax) mesh
     unsigned int        cx;                 // cluster X coordinate
     unsigned int        cy;                 // cluster Y coordinate
@@ -836,4 +851,5 @@
     unsigned int        vaddr;              // virtual address
     unsigned long long  cont_paddr;         // container physical address
+    unsigned long long  sts_paddr;          // container status physical address
 
     unsigned int        flags;              // for _v2p_translate()
@@ -859,13 +875,66 @@
             cont_paddr = _v2p_translate( vaddr , &flags );
 
+            // checking container address alignment
+            if ( cont_paddr & 0x3F )
+            {
+                _printf("\n[GIET ERROR] in _sys_nic_alloc() : container address of cluster[%d,%d] not aligned\n",
+                        cx, cy);
+                return -1;
+            }
+
+#if GIET_DEBUG_NIC
+_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc()\n"
+        " allocates in cluster[%d,%d]:\n"
+        " - container vaddr = %x / paddr = %l\n",
+        thread , cx , cy , vaddr, cont_paddr );
+#endif
+
+            // allocate the kernel container status
+            // it occupies 64 bytes but only last bit is useful (1 for full and 0 for empty)
+            vaddr = (unsigned int)_remote_malloc( 64, cx, cy );
+
+            if ( vaddr == 0 )  // not enough kernel heap memory in cluster[cx,cy]
+            {
+                _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough kenel heap"
+                        " in cluster[%d,%d]\n", cx, cy );
+                return -1;
+            }
+
+            // compute status physical address
+            sts_paddr = _v2p_translate( vaddr , &flags );
+
+            // checking status address alignment
+            if ( sts_paddr & 0x3F )
+            {
+                _printf("\n[GIET ERROR] in _sys_nic_alloc() : status address of cluster[%d,%d] not aligned\n",
+                        cx, cy);
+                return -1;
+            }
+
             // initialize chbuf entry
-            if ( is_rx ) _nic_rx_chbuf[nic_channel].buffer[index].desc = cont_paddr;
-            else         _nic_tx_chbuf[nic_channel].buffer[index].desc = cont_paddr;
+            // The buffer descriptor has the following structure:
+            // - the 26 LSB bits contain bits[6:31] of the buffer physical address
+            // - the 26 following bits contain bits[6:31] of the physical address where the
+            //   buffer status is located
+            // - the 12 MSB bits contain the common address extension of the buffer and its
+            //   status
+            if ( is_rx )
+                _nic_ker_rx_chbuf[nic_channel].buf_desc[index] =
+                    (unsigned long long)
+                    ((sts_paddr & 0xFFFFFFFFULL) >> 6) +
+                    (((cont_paddr & 0xFFFFFFFFFFFULL) >> 6) << 26);
+            else
+                _nic_ker_tx_chbuf[nic_channel].buf_desc[index] =
+                    (unsigned long long)
+                    ((sts_paddr & 0xFFFFFFC0ULL) >> 6) +
+                    (((cont_paddr & 0xFFFFFFFFFC0ULL) >> 6) << 26);
 
 #if GIET_DEBUG_NIC
-_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc()"
-        " allocates container in cluster[%d,%d]\n"
-        "  vaddr = %x / paddr = %l\n",
-        thread , cx , cy , vaddr , cont_paddr );
+_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc()\n"
+        " - status vaddr = %x / paddr = %l\n"
+        " Buffer descriptor = %l\n",
+        thread, vaddr, sts_paddr,
+        (unsigned long long)((sts_paddr & 0xFFFFFFFFULL) >> 6) + 
+        (((cont_paddr & 0xFFFFFFFFFFFULL) >> 6) << 26) );
 #endif
         }
@@ -875,28 +944,16 @@
     if ( is_rx )
     {
-        _nic_rx_chbuf[nic_channel].xmax = xmax;
-        _nic_rx_chbuf[nic_channel].ymax = ymax;
+        _nic_ker_rx_chbuf[nic_channel].xmax = xmax;
+        _nic_ker_rx_chbuf[nic_channel].ymax = ymax;
     }
     else
     {
-        _nic_tx_chbuf[nic_channel].xmax = xmax;
-        _nic_tx_chbuf[nic_channel].ymax = ymax;
-    }
-
-    // compute the NIC chbuf descriptor physical address
-    unsigned int offset;
-    if ( is_rx ) offset = 0x4000;
-    else         offset = 0x4080;
-    nic_chbuf_pbase = (((unsigned long long)((X_IO << Y_WIDTH) + Y_IO))<<32) |
-                      (SEG_NIC_BASE + (nic_channel<<15) + offset);
-
-#if GIET_DEBUG_NIC
-_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc() get NIC chbuf : paddr = %l\n",
-        thread , nic_chbuf_pbase );
-#endif
+        _nic_ker_tx_chbuf[nic_channel].xmax = xmax;
+        _nic_ker_tx_chbuf[nic_channel].ymax = ymax;
+    }
 
     // compute the kernel chbuf descriptor physical address
-    if ( is_rx ) vaddr = (unsigned int)( &_nic_rx_chbuf[nic_channel] );
-    else         vaddr = (unsigned int)( &_nic_tx_chbuf[nic_channel] );
+    if ( is_rx ) vaddr = (unsigned int)( &_nic_ker_rx_chbuf[nic_channel] );
+    else         vaddr = (unsigned int)( &_nic_ker_tx_chbuf[nic_channel] );
 
     ker_chbuf_pbase = _v2p_translate( vaddr , &flags );
@@ -909,7 +966,25 @@
 
     // sync the kernel chbuf in L2 after write in L2
-    _mmc_sync( ker_chbuf_pbase, sizeof( nic_chbuf_t ) );
-
-    // initializes CMA registers defining the source & destination chbufs 
+    _mmc_sync( ker_chbuf_pbase, sizeof( ker_chbuf_t ) );
+
+    ///////////////////////////////////////////////////////////////
+    // Step 3: compute the NIC chbuf descriptor physical address //
+    ///////////////////////////////////////////////////////////////
+
+    unsigned int offset;
+    if ( is_rx ) offset = 0x4100;
+    else         offset = 0x4110;
+    nic_chbuf_pbase = (((unsigned long long)((X_IO << Y_WIDTH) + Y_IO))<<32) |
+                      (SEG_NIC_BASE + (nic_channel<<15) + offset);
+
+#if GIET_DEBUG_NIC
+_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc() get NIC chbuf : paddr = %l\n",
+        thread , nic_chbuf_pbase );
+#endif
+
+    ////////////////////////////////////////////////////////////////////////////////
+    // Step 4: initialize CMA registers defining the source & destination chbufs //
+    ////////////////////////////////////////////////////////////////////////////////
+
     if ( is_rx )               // NIC to kernel
     {
@@ -984,9 +1059,9 @@
 
     // activates NIC channel
-    _nic_channel_start( nic_channel, is_rx, GIET_NIC_MAC4, GIET_NIC_MAC2 ); 
+    _nic_channel_start( nic_channel, is_rx, GIET_NIC_MAC4, GIET_NIC_MAC2 );
 
 #if GIET_DEBUG_NIC
-_printf("\n[GIET DEBUG NIC] Task %d exit _sys_nic_start() at cycle %d\n",
-        thread , _get_proctime() );
+    _printf("\n[GIET DEBUG NIC] Task %d exit _sys_nic_start() at cycle %d\n",
+            thread , _get_proctime() );
 #endif
 
@@ -1015,11 +1090,11 @@
 
     // get kernel chbuf virtual address
-    nic_chbuf_t* chbuf;
-    if ( is_rx )  chbuf = &_nic_rx_chbuf[channel];
-    else          chbuf = &_nic_tx_chbuf[channel];
+    ker_chbuf_t* ker_chbuf;
+    if ( is_rx )  ker_chbuf = &_nic_ker_rx_chbuf[channel];
+    else          ker_chbuf = &_nic_ker_tx_chbuf[channel];
 
     // get xmax / ymax parameters
-    unsigned int xmax = chbuf->xmax;
-    unsigned int ymax = chbuf->ymax;
+    unsigned int xmax = ker_chbuf->xmax;
+    unsigned int ymax = ker_chbuf->ymax;
 
     // get cluster coordinates for the processor running the calling task
@@ -1042,18 +1117,18 @@
     }
     
-    unsigned long long user_buffer_paddr;    // user buffer physical address 
-    unsigned long long kernel_buffer_paddr;  // kernel buffer physical address
-    unsigned long long kernel_chbuf_paddr;   // kernel chbuf physical address
-    unsigned long long buffer_descriptor;    // kernel buffer descriptor
-    unsigned long long buffer_desc_paddr;    // kernel buffer descriptor paddr
-    unsigned int       index;                // kernel buffer index in chbuf
-    unsigned int       flags;                // for _v2P_translate
+    unsigned long long usr_buf_paddr;       // user buffer physical address 
+    unsigned long long ker_buf_paddr;       // kernel buffer physical address
+    unsigned long long ker_sts_paddr;       // kernel buffer status physical address
+    unsigned long long ker_buf_desc;        // kernel buffer descriptor
+    unsigned int       ker_sts;             // kernel buffer status (full or empty)
+    unsigned int       index;               // kernel buffer index in chbuf
+    unsigned int       flags;               // for _v2P_translate
 
     // Compute user buffer physical address and check access rights
-    user_buffer_paddr = _v2p_translate( (unsigned int)buffer , &flags );
+    usr_buf_paddr = _v2p_translate( (unsigned int)buffer , &flags );
 
     if ( (flags & PTE_U) == 0 )
     {
-        _printf("\n[GIET ERROR] in _sys_nic_tx_move() : illegal buffer address\n");
+        _printf("\n[GIET ERROR] in _sys_nic_tx_move() : illegal user buffer address\n");
         return -1;
     }
@@ -1061,34 +1136,39 @@
 #if GIET_DEBUG_NIC
 _printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() get user buffer : paddr = %l\n",
-        thread, user_buffer_paddr );
-#endif
-
-    // compute kernel chbuf physical address (required for sync)
-    kernel_chbuf_paddr = _v2p_translate( (unsigned int)chbuf , &flags );
+        thread, usr_buf_paddr );
+#endif
+
+    // compute buffer index, buffer descriptor paddr and buffer status paddr
+    index = (ymax * cx) + cy;
+    ker_buf_desc = ker_chbuf->buf_desc[index];
+    ker_sts_paddr = ((ker_buf_desc & 0xFFF0000000000000ULL) >> 20) +
+                    ((ker_buf_desc & 0x3FFFFFFULL) << 6);
+
+#if GIET_DEBUG_NIC
+_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() read ker_buf_desc %d at cycle %d\n"
+        "  kernel buffer descriptor = %l\n",
+        thread, index, _get_proctime(), ker_buf_desc );
+#endif
 
     // poll local kernel container status until success
     while ( 1 )
     {
-        // compute buffer index and buffer descriptor paddr
-        index = (ymax * cx) + cy;
-        buffer_desc_paddr = kernel_chbuf_paddr + (index<<6);
-
         // inval buffer descriptor in L2 before read in L2
-        _mmc_inval( buffer_desc_paddr , 8 );
-        buffer_descriptor = chbuf->buffer[index].desc;
+        _mmc_inval( ker_sts_paddr, 4 );
+        ker_sts = _physical_read( ker_sts_paddr );
 
 #if GIET_DEBUG_NIC
-_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() read buf_desc %d at cycle %d\n"
-        "  paddr = %l / buffer descriptor = %l\n",
-        thread, index, _get_proctime(), buffer_desc_paddr, buffer_descriptor );
+_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() read ker_buf_sts %d at cycle %d\n"
+        "  paddr = %l / kernel buffer status = %x\n",
+        thread, index, _get_proctime(), ker_sts_paddr, ker_sts );
 #endif
 
         // test buffer status and break if found
-        if ( ( is_rx != 0 ) && (buffer_descriptor >> 63) == 1 )  break;
-        if ( ( is_rx == 0 ) && (buffer_descriptor >> 63) == 0 )  break;
+        if ( ( is_rx != 0 ) && ( ker_sts == 0x1 ) ) break;
+        if ( ( is_rx == 0 ) && ( ker_sts == 0 ) ) break;
     }
 
     // compute kernel buffer physical address
-    kernel_buffer_paddr = buffer_descriptor & 0x0000FFFFFFFFFFFFULL;
+    ker_buf_paddr = (ker_buf_desc & 0xFFFFFFFFFC000000ULL) >> 20;
     
     // move one container
@@ -1096,14 +1176,14 @@
     {
         // inval kernel buffer in L2 before read in L2
-        _mmc_inval( kernel_buffer_paddr, NIC_CONTAINER_SIZE );
+        _mmc_inval( ker_buf_paddr, NIC_CONTAINER_SIZE );
 
         // transfer data from kernel buffer to user buffer
-        _physical_memcpy( user_buffer_paddr, 
-                          kernel_buffer_paddr, 
+        _physical_memcpy( usr_buf_paddr, 
+                          ker_buf_paddr, 
                           NIC_CONTAINER_SIZE );
 #if GIET_DEBUG_NIC
 _printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() transfer kernel buffer %l\n"
         " to user buffer %l at cycle %d\n",
-        thread , kernel_buffer_paddr , user_buffer_paddr , _get_proctime() );
+        thread , ker_buf_paddr , usr_buf_paddr , _get_proctime() );
 #endif
 
@@ -1112,15 +1192,15 @@
     {
         // transfer data from user buffer to kernel buffer
-        _physical_memcpy( kernel_buffer_paddr, 
-                          user_buffer_paddr, 
+        _physical_memcpy( ker_buf_paddr, 
+                          usr_buf_paddr, 
                           NIC_CONTAINER_SIZE );
 
         // sync kernel buffer in L2 after write in L2
-        _mmc_sync( kernel_buffer_paddr, NIC_CONTAINER_SIZE );
+        _mmc_sync( ker_buf_paddr, NIC_CONTAINER_SIZE );
 
 #if GIET_DEBUG_NIC
 _printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() transfer "
         "user buffer %l to kernel buffer %l at cycle %d\n",
-        thread , user_buffer_paddr , kernel_buffer_paddr , _get_proctime() );
+        thread , usr_buf_paddr , ker_buf_paddr , _get_proctime() );
 #endif
 
@@ -1128,9 +1208,9 @@
 
     // update kernel chbuf status 
-    if ( is_rx ) chbuf->buffer[index].desc = kernel_buffer_paddr & 0x0000FFFFFFFFFFFFULL;
-    else         chbuf->buffer[index].desc = kernel_buffer_paddr | 0x8000000000000000ULL;
+    if ( is_rx ) _physical_write ( ker_sts_paddr, 0 );
+    else         _physical_write ( ker_sts_paddr, 0x1 );
 
     // sync kernel chbuf in L2 after write in L2
-    _mmc_sync( kernel_chbuf_paddr + (index<<6) , 8 );
+    _mmc_sync( ker_sts_paddr, 4 );
 
 #if GIET_DEBUG_NIC
@@ -1339,8 +1419,10 @@
 } // end sys_fbf_cma_alloc()
 
-////////////////////////////////////////////
-int _sys_fbf_cma_start( void*        vbase0, 
-                        void*        vbase1,  
-                        unsigned int length ) 
+
+////////////////////////
+int _sys_fbf_cma_init_buf(void*        buf0_vbase, 
+                          void*        buf1_vbase, 
+                          void*        sts0_vaddr,
+                          void*        sts1_vaddr )
 {
 #if NB_CMA_CHANNELS > 0
@@ -1348,4 +1430,10 @@
     unsigned int       vaddr;           // virtual address
     unsigned int       flags;           // for _v2p_translate()
+    unsigned long long fbf_paddr;       // fbf physical address
+    unsigned long long fbf_sts_paddr;   // fbf status physical address
+    unsigned long long buf0_pbase;      // buffer 0 base physical address
+    unsigned long long sts0_paddr;      // buffer 0 status physical address
+    unsigned long long buf1_pbase;      // buffer 1 base physical address
+    unsigned long long sts1_paddr;      // buffer 1 status physical address
 
     // get channel index
@@ -1354,26 +1442,35 @@
     if ( channel >= NB_CMA_CHANNELS )
     {
-        _printf("\n[GIET ERROR] in _fbf_cma_start() : CMA channel index too large\n");
+        _printf("\n[GIET ERROR] in _fbf_cma_init_buf() : CMA channel index too large\n");
         return -1;
     }
 
 #if GIET_DEBUG_FBF_CMA
-_printf("\n[FBF_CMA DEBUG] enters _sys_fbf_cma_start()\n"
-        " - channel      = %d\n"
-        " - buf0   vbase = %x\n"
-        " - buf1   vbase = %x\n"
-        " - buffer size  = %x\n",
+_printf("\n[FBF_CMA DEBUG] enters _sys_fbf_cma_init_buf()\n"
+        " - channel           = %d\n"
+        " - buf0        vbase = %x\n"
+        " - buf1        vbase = %x\n"
+        " - sts0        vaddr = %x\n"
+        " - sts1        vaddr = %x\n",
         channel,
-        (unsigned int)vbase0,
-        (unsigned int)vbase1,
-        length );
-#endif
-
-    // checking user buffers virtual addresses and length alignment
-    if ( ((unsigned int)vbase0 & 0x3) || 
-         ((unsigned int)vbase1 & 0x3) || 
-         (length & 0x3) ) 
-    {
-        _printf("\n[GIET ERROR] in _fbf_cma_start() : user buffer not aligned\n");
+        (unsigned int)buf0_vbase,
+        (unsigned int)buf1_vbase,
+        (unsigned int)sts0_vaddr,
+        (unsigned int)sts1_vaddr );
+#endif
+
+    // checking user buffers virtual addresses alignment
+    if ( ((unsigned int)buf0_vbase & 0x3F) || 
+         ((unsigned int)buf1_vbase & 0x3F) ) 
+    {
+        _printf("\n[GIET ERROR] in _fbf_cma_inti_buf() : user buffer not aligned\n");
+        return -1;
+    }
+
+    // checking user buffers status virtual addresses alignment
+    if ( ((unsigned int)sts0_vaddr & 0x3F) ||
+         ((unsigned int)sts1_vaddr & 0x3F) )
+    {
+        _printf("\n[GIET ERROR] in _fbf_cma_init_buf() : user buffer status not aligned\n");
         return -1;
     }
@@ -1381,10 +1478,15 @@
     // compute frame buffer physical address and initialize _fbf_chbuf[channel]
     vaddr = (unsigned int)SEG_FBF_BASE;
-    _fbf_chbuf[channel].fbf.desc = _v2p_translate( vaddr , &flags );
+    fbf_paddr = _v2p_translate( vaddr , &flags );
+    vaddr = (unsigned int)&_fbf_status[channel];
+    fbf_sts_paddr = _v2p_translate( vaddr , &flags );
+
+    _fbf_chbuf[channel].fbf_desc =
+        (unsigned long long) ((fbf_sts_paddr & 0xFFFFFFFFULL) >> 6) +
+        (((fbf_paddr & 0xFFFFFFFFULL) >> 6 ) << 26);
 
     // Compute user buffer 0 physical addresses and intialize _fbf_chbuf[channel]
-    vaddr = (unsigned int)vbase0;
-    _fbf_chbuf[channel].buf0.desc = _v2p_translate( vaddr , &flags );
-
+    vaddr = (unsigned int)buf0_vbase;
+    buf0_pbase = _v2p_translate( vaddr , &flags );
     if ((flags & PTE_U) == 0) 
     {
@@ -1393,8 +1495,19 @@
     }
 
+    vaddr = (unsigned int)sts0_vaddr;
+    sts0_paddr = _v2p_translate( vaddr , &flags );
+    if ((flags & PTE_U) == 0) 
+    {
+        _printf("\n[GIET ERROR] in _fbf_cma_start() : sts0 not in user space\n");
+        return -1;
+    }
+
+    _fbf_chbuf[channel].buf0_desc = 
+        (unsigned long long) ((sts0_paddr & 0xFFFFFFFFULL) >> 6) +
+        (((buf0_pbase & 0xFFFFFFFFULL) >> 6 ) << 26);
+
     // Compute user buffer 1 physical addresses and intialize _fbf_chbuf[channel]
-    vaddr = (unsigned int)vbase1;
-    _fbf_chbuf[channel].buf1.desc = _v2p_translate( vaddr , &flags );
-
+    vaddr = (unsigned int)buf1_vbase;
+    buf1_pbase = _v2p_translate( vaddr , &flags );
     if ((flags & PTE_U) == 0) 
     {
@@ -1403,6 +1516,15 @@
     }
 
-    // initializes buffer length
-    _fbf_chbuf[channel].length = length;
+    vaddr = (unsigned int)sts1_vaddr;
+    sts1_paddr = _v2p_translate( vaddr , &flags );
+    if ((flags & PTE_U) == 0) 
+    {
+        _printf("\n[GIET ERROR] in _fbf_cma_start() : sts1 not in user space\n");
+        return -1;
+    }
+
+    _fbf_chbuf[channel].buf1_desc = 
+        (unsigned long long) ((sts1_paddr & 0xFFFFFFFFULL) >> 6) +
+        (((buf1_pbase & 0xFFFFFFFFULL) >> 6 ) << 26);
 
     // Compute and register physical adress of the fbf_chbuf descriptor
@@ -1410,4 +1532,58 @@
     _fbf_chbuf_paddr[channel] = _v2p_translate( vaddr , &flags );
  
+#if GIET_DEBUG_FBF_CMA
+_printf(" - fbf         pbase = %l\n"
+        " - fbf status  paddr = %l\n"
+        " - buf0        pbase = %l\n"
+        " - buf0 status paddr = %l\n" 
+        " - buf1        pbase = %l\n"
+        " - buf0 status paddr = %l\n" 
+        " - chbuf       pbase = %l\n",
+        fbf_paddr,
+        fbf_sts_paddr,
+        buf0_pbase,
+        sts0_paddr,
+        buf1_pbase,
+        sts1_paddr,
+        _fbf_chbuf_paddr[channel] );
+#endif
+
+    return 0;
+
+#else
+
+    _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : NB_CMA_CHANNELS = 0\n");
+    return -1;
+
+#endif  
+} // end sys_fbf_cma_init_buf()
+
+////////////////////////////////////////////
+int _sys_fbf_cma_start( unsigned int length ) 
+{
+#if NB_CMA_CHANNELS > 0
+
+    // get channel index
+    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
+
+    if ( channel >= NB_CMA_CHANNELS )
+    {
+        _printf("\n[GIET ERROR] in _fbf_cma_start() : CMA channel index too large\n");
+        return -1;
+    }
+
+    // check buffers initialization
+    if ( ( _fbf_chbuf[channel].buf0_desc == 0x0ULL ) &&
+         ( _fbf_chbuf[channel].buf1_desc == 0x0ULL) &&
+         ( _fbf_chbuf[channel].fbf_desc == 0x0ULL) )
+    {
+        _printf("\n[GIET ERROR] in _sys_fbf_cma_start() :\n"
+                "Buffer initialization has not been done\n");
+        return -1;
+    }
+
+    // initializes buffer length
+    _fbf_chbuf[channel].length = length;
+
     if ( USE_IOB )
     {
@@ -1415,15 +1591,4 @@
         _mmc_sync( _fbf_chbuf_paddr[channel] , sizeof( fbf_chbuf_t ) );
     }
-
-#if GIET_DEBUG_FBF_CMA
-_printf(" - fbf    pbase = %l\n"
-        " - buf0   pbase = %l\n"
-        " - buf1   pbase = %l\n"
-        " - chbuf  pbase = %l\n",
-        _fbf_chbuf[channel].fbf.desc,
-        _fbf_chbuf[channel].buf0.desc,
-        _fbf_chbuf[channel].buf1.desc,
-        _fbf_chbuf_paddr[channel] );
-#endif
 
     // start CMA transfer
@@ -1431,5 +1596,5 @@
     unsigned int src_chbuf_paddr_lsb = (unsigned int)(paddr & 0xFFFFFFFF);
     unsigned int src_chbuf_paddr_ext = (unsigned int)(paddr >> 32);
-    unsigned int dst_chbuf_paddr_lsb = src_chbuf_paddr_lsb + 128;
+    unsigned int dst_chbuf_paddr_lsb = src_chbuf_paddr_lsb + 16;
     unsigned int dst_chbuf_paddr_ext = src_chbuf_paddr_ext;
 
@@ -1476,79 +1641,75 @@
 #if GIET_DEBUG_FBF_CMA
 _printf("\n[FBF_CMA DEBUG] enters _sys_fb_cma_display()\n"
-        " - cma channel     = %d\n"
-        " - buffer index    = %d\n"
-        " - buf0_desc value = %l\n"
-        " - buf1_desc value = %l\n"
-        " - fbf_desc  value = %l\n",
+        " - cma channel      = %d\n"
+        " - buffer index     = %d\n"
+        " - buf0_desc value  = %l\n"
+        " - buf1_desc value  = %l\n"
+        " - fbf_desc  value  = %l\n",
         channel , buffer_index,
-        _fbf_chbuf[channel].buf0.desc,
-        _fbf_chbuf[channel].buf1.desc,
-        _fbf_chbuf[channel].fbf.desc );
-#endif
+        _fbf_chbuf[channel].buf0_desc,
+        _fbf_chbuf[channel].buf1_desc,
+        _fbf_chbuf[channel].fbf_desc );
+#endif
+
+    unsigned long long buf_sts_paddr;
+    unsigned long long buf_paddr;
+    unsigned long long fbf_sts_paddr;
 
     if ( buffer_index == 0 )    // user buffer 0
     {
-        // INVAL L1 and L2 cache copies of user buffer descriptor,
+        buf_sts_paddr =
+            ((pdesc->buf0_desc & 0xFFF0000000000000ULL) >> 20) + // compute address extension
+            ((pdesc->buf0_desc & 0x3FFFFFFULL) << 6);            // compute 32 LSB of the address
+
+        buf_paddr =
+            (pdesc->buf0_desc & 0xFFFFFFFFFC000000ULL) >> 20;  // compute the entire address
+    }
+    else                        // user buffer 1
+    {
+        buf_sts_paddr =
+            ((pdesc->buf1_desc & 0xFFF0000000000000ULL) >> 20) +
+            ((pdesc->buf1_desc & 0x3FFFFFFULL) << 6);
+
+        buf_paddr =
+            (pdesc->buf1_desc & 0xFFFFFFFFFC000000ULL) >> 20;
+    }
+
+    fbf_sts_paddr =
+        ((pdesc->fbf_desc & 0xFFF0000000000000ULL) >> 20) +
+        ((pdesc->fbf_desc & 0x3FFFFFFULL) << 6);
+
+#if GIET_DEBUG_FBF_CMA
+_printf(" - fbf status paddr = %l\n"
+        " - buf        pbase = %l\n"
+        " - buf status paddr = %l\n",
+        fbf_sts_paddr,
+        buf_paddr,
+        buf_sts_paddr );
+#endif
+        
+    // waiting user buffer released by the CMA component)
+    while ( full )
+    {  
+        // INVAL L2 cache copy of user buffer descriptor,
         // because it has been modified in RAM by the CMA component 
-        _dcache_buf_invalidate( (unsigned int)pdesc , sizeof(buffer_descriptor_t) );
-        _mmc_inval( _fbf_chbuf_paddr[channel] , sizeof(buffer_descriptor_t) );
-
-        // waiting user buffer released by the CMA component)
-        while ( full )
-        {  
-            full = (unsigned int)(pdesc->buf0.desc >> 63);
-        }
-
-        // SYNC request for the user buffer, because 
-        // it will be read from XRAM by the CMA component
-        _mmc_sync( pdesc->buf0.desc , pdesc->length );
-
-        // set user buffer status
-        pdesc->buf0.desc = pdesc->buf0.desc | 0x8000000000000000ULL;
-
-        // reset fbf buffer status
-        pdesc->fbf.desc  = pdesc->fbf.desc  & 0x7FFFFFFFFFFFFFFFULL;
-
-        // SYNC request, because these buffer descriptors
-        // will be read from XRAM by the CMA component
-        _mmc_sync( _fbf_chbuf_paddr[channel] , sizeof(fbf_chbuf_t) );
-    }
-    else                        // user buffer 1
-    {
-        // INVAL L1 and L2 cache copies of user buffer descriptor, 
-        // because it has been modified in RAM by the CMA component 
-        _dcache_buf_invalidate( (unsigned int)pdesc + 64, sizeof(buffer_descriptor_t) );
-        _mmc_inval( _fbf_chbuf_paddr[channel] + 64, sizeof(buffer_descriptor_t) );
-
-        // waiting user buffer released by the CMA component)
-        while ( full )
-        {  
-            full = (unsigned int)(pdesc->buf1.desc >> 63);
-        }
-
-        // SYNC request for the user buffer, because 
-        // it will be read from XRAM by the CMA component
-        _mmc_sync( pdesc->buf1.desc , pdesc->length );
-
-        // set user buffer status
-        pdesc->buf1.desc = pdesc->buf1.desc | 0x8000000000000000ULL;
-
-        // reset fbf buffer status
-        pdesc->fbf.desc  = pdesc->fbf.desc  & 0x7FFFFFFFFFFFFFFFULL;
-
-        // SYNC request, because these buffer descriptors
-        // will be read from XRAM by the CMA component
-        _mmc_sync( _fbf_chbuf_paddr[channel] , sizeof(fbf_chbuf_t) );
-    }
-
-#if GIET_DEBUG_FBF_CMA
-_printf("\n[FBF_CMA DEBUG] exit _sys_fb_cma_display()\n"
-        " - buf0_desc value = %l\n"
-        " - buf1_desc value = %l\n"
-        " - fbf_desc  value = %l\n",
-        _fbf_chbuf[channel].buf0.desc,
-        _fbf_chbuf[channel].buf1.desc,
-        _fbf_chbuf[channel].fbf.desc );
-#endif
+        _mmc_inval( buf_sts_paddr , 4 );        
+
+        full = _physical_read( buf_sts_paddr );
+    }
+
+    // SYNC request for the user buffer, because 
+    // it will be read from XRAM by the CMA component
+    _mmc_sync( buf_paddr , pdesc->length );
+
+    // set user buffer status
+    _physical_write( buf_sts_paddr, 0x1 );
+
+    // reset fbf buffer status
+    _physical_write( fbf_sts_paddr, 0x0 );
+    
+    // SYNC request, because these buffer descriptors
+    // will be read from XRAM by the CMA component
+    _mmc_sync( buf_sts_paddr, 4 );
+    _mmc_sync( fbf_sts_paddr, 4 );
 
     return 0;
@@ -1561,5 +1722,4 @@
 #endif
 } // end _sys_fbf_cma_display()
-
 
 ///////////////////////
Index: /soft/giet_vm/giet_kernel/sys_handler.h
===================================================================
--- /soft/giet_vm/giet_kernel/sys_handler.h	(revision 613)
+++ /soft/giet_vm/giet_kernel/sys_handler.h	(revision 614)
@@ -24,19 +24,17 @@
 
 ///////////////////////////////////////////////////////////////////////////////
-// This structure is used by the nic_chbuf_t and fbf_chbuf_t structures.
-// It describes a single buffer descriptor. The useful information is 
-// contained in one single 64 bits word (desc field): 
-// - the 48 LSB bits contain the buffer physical address
-// - the MSB bit 63 indicates the buffer state (empty if 0)
-// This descriptor must be aligned on a cache line (64 bytes) to simplify 
+// This structure is used by the CMA component to store the status of the
+// frame buffer (full or empty). The useful information is contained in the
+// "status" integer (1 for full and 0 for empty).
+// This structure must be aligned on a cache line (64 bytes) to simplify 
 // the software L2/L3 cache coherence when the IO bridge is used. 
 ///////////////////////////////////////////////////////////////////////////////
 
-typedef struct buffer_descriptor_s
+typedef struct buffer_status_s
 {
-    unsigned long long  desc;
-    unsigned int        padding[14];
-} buffer_descriptor_t;
- 
+    unsigned int status;
+    unsigned int padding[15];
+} buffer_status_t;
+
 ///////////////////////////////////////////////////////////////////////////////
 // This structure is used by the CMA component to move a stream 
@@ -45,5 +43,11 @@
 // - The SRC chbuf contains two buffers (buf0 & buf1), in user space.
 // - The DST cbuf contains one single buffer (fbf), that is the frame buffer.
-// - The length field define the buffer size (bytes)
+// Each buffer is described with a 64 bits buffer descriptor:
+// - the 26 LSB bits contain bits[6:31] of the buffer physical address
+// - the 26 following bits contain bits[6:31] of the physical address where the
+//   buffer status is located
+// - the 12 MSB bits contain the common address extension of the buffer and its
+//   status
+// The length field define the buffer size (bytes)
 // This structure must be 64 bytes aligned.
 ///////////////////////////////////////////////////////////////////////////////
@@ -51,9 +55,9 @@
 typedef struct fbf_chbuf_s
 {
-    buffer_descriptor_t  buf0;         // first user buffer descriptor 
-    buffer_descriptor_t  buf1;         // second user buffer descriptor
-    buffer_descriptor_t  fbf;          // frame buffer descriptor 
-    unsigned int         length;       // buffer length (bytes)
-    unsigned int         padding[15];  // padding for 64 bytes alignment
+    unsigned long long  buf0_desc;     // first user buffer descriptor 
+    unsigned long long  buf1_desc;     // second user buffer descriptor
+    unsigned long long  fbf_desc;      // frame buffer descriptor 
+    unsigned int        length;        // buffer length (bytes)
+    unsigned int        padding[9];    // padding for 64 bytes alignment
 } fbf_chbuf_t;   
 
@@ -65,13 +69,19 @@
 // The number of distributed containers can be smaller than (X_SIZE * YSIZE).
 // The actual number of buffers used in the chbuf is defined by (xmax * ymax).
+// Each buffer is described with a 64 bits buffer descriptor:
+// - the 26 LSB bits contain bits[6:31] of the buffer physical address
+// - the 26 following bits contain bits[6:31] of the physical address where the
+//   buffer status is located
+// - the 12 MSB bits contain the common address extension of the buffer and its
+//   status
 // This structure must be 64 bytes aligned.
 ///////////////////////////////////////////////////////////////////////////////
 
-typedef struct nic_chbuf_s
+typedef struct ker_chbuf_s
 {
-    buffer_descriptor_t  buffer[X_SIZE*Y_SIZE];  // kernel chbuf
-    unsigned int         xmax;                   // nb clusters in a row
-    unsigned int         ymax;                   // nb clusters in a column
-} nic_chbuf_t;
+    unsigned long long   buf_desc[X_SIZE*Y_SIZE]; // kernel chbuf descriptor
+    unsigned int         xmax;                        // nb clusters in a row
+    unsigned int         ymax;                        // nb clusters in a column
+} ker_chbuf_t;
 
 
@@ -171,7 +181,10 @@
 int _sys_fbf_cma_alloc();
 
-int _sys_fbf_cma_start( void*        vbase0, 
-                        void*        vbase1,  
-                        unsigned int length );
+int _sys_fbf_cma_init_buf(void*        buf0_vbase, 
+                          void*        buf1_vbase, 
+                          void*        sts0_vaddr,
+                          void*        sts1_vaddr );
+
+int _sys_fbf_cma_start( unsigned int length );
 
 int _sys_fbf_cma_display( unsigned int buffer_index );
Index: /soft/giet_vm/giet_libs/stdio.c
===================================================================
--- /soft/giet_vm/giet_libs/stdio.c	(revision 613)
+++ /soft/giet_vm/giet_libs/stdio.c	(revision 614)
@@ -698,13 +698,22 @@
 
 ///////////////////////////////////////////
-void giet_fbf_cma_start( void *       buf0,
-                         void *       buf1,
-                         unsigned int length )
+void giet_fbf_cma_init_buf( void* buf0_vbase, 
+                            void* buf1_vbase,
+                            void* sts0_vaddr,
+                            void* sts1_vaddr )
+{
+    if ( sys_call( SYSCALL_FBF_CMA_INIT_BUF,
+                   (unsigned int)buf0_vbase, 
+                   (unsigned int)buf1_vbase,
+                   (unsigned int)sts0_vaddr, 
+                   (unsigned int)sts1_vaddr ) )   giet_exit("error in giet_fbf_cma_init_buf()");
+}
+
+///////////////////////////////////////////
+void giet_fbf_cma_start( unsigned int length )
 {
     if ( sys_call( SYSCALL_FBF_CMA_START,
-                   (unsigned int)buf0, 
-                   (unsigned int)buf1, 
-                   length,
-                   0 ) )   giet_exit("error in giet_fbf_cma_start()");
+                   length, 
+                   0, 0, 0 ) )   giet_exit("error in giet_fbf_cma_start()");
 }
 
Index: /soft/giet_vm/giet_libs/stdio.h
===================================================================
--- /soft/giet_vm/giet_libs/stdio.h	(revision 613)
+++ /soft/giet_vm/giet_libs/stdio.h	(revision 614)
@@ -27,14 +27,14 @@
 #define SYSCALL_GLOBAL_TASK_ID       0x09
 #define SYSCALL_FBF_CMA_ALLOC        0x0A
-#define SYSCALL_FBF_CMA_START        0x0B
-#define SYSCALL_FBF_CMA_DISPLAY      0x0C
-#define SYSCALL_FBF_CMA_STOP         0x0D
-#define SYSCALL_EXIT                 0x0E
-#define SYSCALL_PROCS_NUMBER         0x0F
-
-#define SYSCALL_FBF_SYNC_WRITE       0x10
-#define SYSCALL_FBF_SYNC_READ        0x11
-#define SYSCALL_THREAD_ID            0x12
-//                                   0x13
+#define SYSCALL_FBF_CMA_INIT_BUF     0x0B
+#define SYSCALL_FBF_CMA_START        0x0C
+#define SYSCALL_FBF_CMA_DISPLAY      0x0D
+#define SYSCALL_FBF_CMA_STOP         0x0E
+#define SYSCALL_EXIT                 0x0F
+
+#define SYSCALL_PROCS_NUMBER         0x10
+#define SYSCALL_FBF_SYNC_WRITE       0x11
+#define SYSCALL_FBF_SYNC_READ        0x12
+#define SYSCALL_THREAD_ID            0x13
 #define SYSCALL_TIM_ALLOC            0x14
 #define SYSCALL_TIM_START            0x15
@@ -228,7 +228,10 @@
 extern void giet_fbf_cma_alloc();
 
-extern void giet_fbf_cma_start( void*        buf0, 
-                                void*        buf1,
-                                unsigned int length );
+extern void giet_fbf_cma_init_buf( void* buf0_vbase, 
+                                   void* buf1_vbase,
+                                   void* sts0_vaddr,
+                                   void* sts1_vaddr );
+
+extern void giet_fbf_cma_start( unsigned int length );
 
 extern void giet_fbf_cma_display( unsigned int buffer );
