Index: /soft/giet_vm/giet_drivers/bdv_driver.c
===================================================================
--- /soft/giet_vm/giet_drivers/bdv_driver.c	(revision 528)
+++ /soft/giet_vm/giet_drivers/bdv_driver.c	(revision 529)
@@ -2,14 +2,11 @@
 // File      : bdv_driver.c
 // Date      : 23/05/2013
-// Author    : alain greiner
-// Maintainer: cesar fuguet
+// Author    : alain greiner cesar fuguet
 // Copyright (c) UPMC-LIP6
 ///////////////////////////////////////////////////////////////////////////////////
 // Implementation notes:
-// 1. In order to share code, the two _bdv_read() and _bdv_write() functions
-//    call the same _bdv_access() function.
-// 2. All accesses to BDV registers are done by the two
-//    _bdv_set_register() and _bdv_get_register() low-level functions,
-//    that are handling virtual / physical extended addressing.
+// All accesses to BDV registers are done by the two
+// _bdv_set_register() and _bdv_get_register() low-level functions,
+// that are handling virtual / physical extended addressing.
 ///////////////////////////////////////////////////////////////////////////////////
 
@@ -18,21 +15,25 @@
 #include <bdv_driver.h>
 #include <xcu_driver.h>
-#include <ioc_driver.h>
+#include <kernel_locks.h>
 #include <utils.h>
 #include <tty0.h>
 #include <ctx_handler.h>
-
-///////////////////////////////////////////////////////////////////////////////
-// BDV global variables
-///////////////////////////////////////////////////////////////////////////////
-
+#include <irq_handler.h>
+
+///////////////////////////////////////////////////////////////////////////////
+//      Global variables
+///////////////////////////////////////////////////////////////////////////////
+
+// lock protecting single channel BDV peripheral
 __attribute__((section(".kdata")))
 spin_lock_t  _bdv_lock __attribute__((aligned(64)));
 
+// global index of the waiting task (only used in descheduling mode)
+__attribute__((section(".kdata")))
+unsigned int _bdv_gtid;
+
+// BDV peripheral status (only used in descheduling mode)
 __attribute__((section(".kdata")))
 unsigned int _bdv_status;
-
-__attribute__((section(".kdata")))
-unsigned int _bdv_gtid;
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -56,19 +57,13 @@
 
 ///////////////////////////////////////////////////////////////////////////////
-// This function transfer data between a memory buffer and the block device.
-// The buffer lentgth is (count*block_size) bytes.
-// Arguments are:
-// - to_mem     : from external storage to memory when non 0.
-// - mode       : BOOT / KERNEL / USER
-// - lba        : first block index on the external storage.
-// - buf_paddr  : physical base address of the memory buffer.
-// - count      : number of blocks to be transfered.
-// Returns 0 if success, > 0 if error.
-///////////////////////////////////////////////////////////////////////////////
-static unsigned int _bdv_access( unsigned int       to_mem,
-                                 unsigned int       mode,
-                                 unsigned int       lba,
-                                 unsigned long long buf_paddr,
-                                 unsigned int       count) 
+//      Extern functions
+///////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////
+unsigned int _bdv_access( unsigned int       use_irq,
+                          unsigned int       to_mem,
+                          unsigned int       lba,
+                          unsigned long long buf_paddr,
+                          unsigned int       count) 
 {
     unsigned int procid  = _get_procid();
@@ -78,41 +73,21 @@
 
 #if GIET_DEBUG_IOC_DRIVER
-_puts("\n[BDV DEBUG] _bdv_access() : P[");
-_putd( x );
-_puts(",");
-_putd( y );
-_puts(",");
-_putd( p );
-_puts("] enters at cycle ");
-_putd( _get_proctime() );
-_puts("\n - to_mem  = ");
-_putd( to_mem );
-_puts("\n - mode    = ");
-_putd( mode );
-_puts("\n - paddr   = ");
-_putl( buf_paddr );
-_puts("\n - sectors = ");
-_putd( count );
-_puts("\n - lba     = ");
-_putx( lba );
-_puts("\n");
-#endif
-
-    unsigned int       error = 0;
+_printf("\n[BDV DEBUG] P[%d,%d,%d] enters _bdv_access at cycle %d\n"
+        "  use_irq = %d / to_mem = %d / lba = %x / paddr = %l / count = %d\n",
+        x , y , p , _get_proctime() , use_irq , to_mem , lba , buf_paddr, count );
+#endif
+
+    // check buffer alignment
+    if( buf_paddr & 0x1FF )
+    {
+        _printf("\n[BDV ERROR] in _bdv_access() : buffer not block aligned\n");
+        return -1;
+    }
+
+    unsigned int error;
+    unsigned int status;
 
     // get the lock protecting BDV
     _spin_lock_acquire( &_bdv_lock );
-
-#if GIET_DEBUG_IOC_DRIVER
-_puts("\n[BDV DEBUG] _bdv_access() : P[");
-_putd( x );
-_puts(",");
-_putd( y );
-_puts(",");
-_putd( p );
-_puts("] get _bdv_lock at cycle ");
-_putd( _get_proctime() );
-_puts("\n");
-#endif
 
     // set device registers
@@ -122,7 +97,9 @@
     _bdv_set_register( BLOCK_DEVICE_LBA       , lba );
 
-    // In BOOT mode, we launch transfer, and poll the BDV_STATUS 
-    // register because IRQs are masked.
-    if ( mode == IOC_BOOT_MODE ) 
+    /////////////////////////////////////////////////////////////////////
+    // In synchronous mode, we launch transfer, 
+    // and poll the BDV_STATUS register until completion.
+    /////////////////////////////////////////////////////////////////////
+    if ( use_irq == 0 ) 
     {
         // Launch transfert
@@ -131,15 +108,9 @@
 
 #if GIET_DEBUG_IOC_DRIVER
-_puts("\n[BDV DEBUG] _bdv_access() : P[");
-_putd( x );
-_puts(",");
-_putd( y );
-_puts(",");
-_putd( p );
-_puts("] launch transfer in polling mode at cycle ");
-_putd( _get_proctime() );
-_puts("\n");
-#endif
-        unsigned int status;
+_printf("\n[BDV DEBUG] _bdv_access() : P[%d,%d,%d] launch transfer"
+        " in polling mode at cycle %d\n",
+        x , y , p , _get_proctime() );
+#endif
+
         do
         {
@@ -147,11 +118,6 @@
 
 #if GIET_DEBUG_IOC_DRIVER
-_puts("\n[BDV DEBUG] _bdv_access() : P[");
-_putd( x );
-_puts(",");
-_putd( y );
-_puts(",");
-_putd( p );
-_puts("] wait on BDV_STATUS register ...\n");
+_printf("\n[BDV DEBUG] _bdv_access() : P[%d,%d,%d] wait on BDV_STATUS ...\n",
+        x , y , p );
 #endif
         }
@@ -164,24 +130,24 @@
         error = ( (status == BLOCK_DEVICE_READ_ERROR) ||
                   (status == BLOCK_DEVICE_WRITE_ERROR) );
-
-        // release lock
-        _spin_lock_release( &_bdv_lock );      
-    }
-    // in USER or KERNEL mode, we deschedule the task.
-    // When the task is rescheduled, we check the _bdv_status variable, 
-    // and release the lock.
+    }
+
+    /////////////////////////////////////////////////////////////////
+    // in descheduling mode, we deschedule the task
+    // and use an interrupt to reschedule the task.
     // We need a critical section, because we must reset the RUN bit
-	// before to launch the transfer, and we don't want to be descheduled
-	// between these two operations. 
+	// before to launch the transfer, and we don't want to be 
+    // descheduled between these two operations. 
+    /////////////////////////////////////////////////////////////////
     else
     {
         unsigned int save_sr;
+        unsigned int wti_index;
         unsigned int ltid = _get_current_task_id();
 
-        // activates BDV interrupts
+        // activates BDV interrupt
         _bdv_set_register( BLOCK_DEVICE_IRQ_ENABLE, 1 );
 
-        // set the _bdv_status variable
-        _bdv_status = BLOCK_DEVICE_BUSY;
+        // allocate a WTI mailbox to the calling proc if external IRQ
+        if ( USE_PIC ) _ext_irq_alloc( ISR_BDV , 0 , &wti_index );
 
         // enters critical section
@@ -197,13 +163,7 @@
 
 #if GIET_DEBUG_IOC_DRIVER
-_puts("\n[BDV DEBUG] _bdv_access() : P[");
-_putd( x );
-_puts(",");
-_putd( y );
-_puts(",");
-_putd( p );
-_puts("] launch transfer in interrupt mode at cycle ");
-_putd( _get_proctime() );
-_puts("\n");
+_printf("\n[BDV DEBUG] _bdv_access() : P[%d,%d,%d] launch transfer"
+        " in descheduling mode at cycle %d\n",
+        x , y , p , _get_proctime() );
 #endif
 
@@ -212,12 +172,11 @@
 
 #if GIET_DEBUG_IOC_DRIVER
-_puts("\n[BDV DEBUG] _bdv_access() : P[");
-_putd( x );
-_puts(",");
-_putd( y );
-_puts(",");
-_putd( p );
-_puts("] resume execution after descheduling\n");
-#endif
+_printf("\n[BDV DEBUG] _bdv_access() : P[%d,%d,%d] resume execution at cycle %d\n",
+        x , y , p , _get_proctime() );
+#endif
+
+        // release WTI mailbox if external IRQ
+        if ( USE_PIC ) _ext_irq_release( ISR_BDV , 0 , wti_index );
+
         // restore SR
         _it_restore( &save_sr );
@@ -226,22 +185,12 @@
         error = ( (_bdv_status == BLOCK_DEVICE_READ_ERROR) ||
                   (_bdv_status == BLOCK_DEVICE_WRITE_ERROR) );
-
-        // reset _bdv_status and release lock
-        _bdv_status = BLOCK_DEVICE_IDLE; 
-        _spin_lock_release( &_bdv_lock );      
-    }
-
-#if GIET_DEBUG_IOC_DRIVER
-_puts("\n[BDV DEBUG] _bdv_access() : P[");
-_putd( x );
-_puts(",");
-_putd( y );
-_puts(",");
-_putd( p );
-_puts("] exit at cycle ");
-_putd( _get_proctime() );
-_puts(" / error = ");
-_putd( error );
-_puts("\n");
+    }
+
+    // release lock
+    _spin_lock_release( &_bdv_lock );      
+
+#if GIET_DEBUG_IOC_DRIVER
+_printf("\n[BDV DEBUG] _bdv_access() : P[%d,%d,%d] exit at cycle %d\n",
+        x , y , p , _get_proctime() );
 #endif
 
@@ -249,8 +198,4 @@
 } // end _bdv_access()
 
-///////////////////////////////////////////////////////////////////////////////
-//      External functions
-///////////////////////////////////////////////////////////////////////////////
-
 ////////////////////////
 unsigned int _bdv_init()
@@ -264,42 +209,4 @@
     _bdv_set_register( BLOCK_DEVICE_IRQ_ENABLE, 0 );
     return 0;
-}
-
-////////////////////////////////////////////////
-unsigned int _bdv_read( unsigned int       mode,  
-                        unsigned int       lba, 
-                        unsigned long long buffer, 
-                        unsigned int       count) 
-{
-    return _bdv_access( 1,        // read access
-                        mode,  
-                        lba,
-                        buffer,
-                        count );
-}
-
-/////////////////////////////////////////////////
-unsigned int _bdv_write( unsigned int       mode,  
-                         unsigned int       lba, 
-                         unsigned long long buffer, 
-                         unsigned int       count ) 
-{
-    return _bdv_access( 0,        // write access
-                        mode,  
-                        lba,
-                        buffer,
-                        count );
-}
-
-//////////////////////////////
-unsigned int _bdv_get_status()
-{
-    return _bdv_get_register( BLOCK_DEVICE_STATUS );
-}
-
-//////////////////////////////////
-unsigned int _bdv_get_block_size()
-{
-    return _bdv_get_register( BLOCK_DEVICE_BLOCK_SIZE );
 }
 
@@ -309,5 +216,5 @@
                unsigned int channel )   // unused 
 {
-    // get BDV status (and reset IRQ)
+    // get BDV status and reset BDV_IRQ
     unsigned int status =  _bdv_get_register( BLOCK_DEVICE_STATUS ); 
 
@@ -316,6 +223,6 @@
          (status == BLOCK_DEVICE_BUSY) )   return;
  
-    // save status in kernel buffer _bdv_status
-    _bdv_status = status; 
+    // register status in global variable
+    _bdv_status = status;
 
     // identify task waiting on BDV
@@ -333,39 +240,23 @@
                     ltid,        
                     CTX_RUN_ID,  // CTX_RUN slot 
-                    1 );         // running
-
-    // requires a context switch for remote processor running the waiting task 
+                    1 );         // running value
+
+    // send a WAKUP WTI to processor running the sleeping task 
     _xcu_send_wti( remote_cluster,   
                    remote_p, 
-                   0 );          // don't force context switch if not idle
-
-#if GIET_DEBUG_IRQS  // we don't take the TTY lock to avoid deadlock
+                   0 );          // don't force context switch 
+
+#if GIET_DEBUG_IOC_DRIVER  
 unsigned int procid  = _get_procid();
 unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
 unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
 unsigned int p       = procid & ((1<<P_WIDTH)-1);
-
-_puts("\n[IRQS DEBUG] Processor[");
-_putd(x );
-_puts(",");
-_putd(y );
-_puts(",");
-_putd(p );
-_puts("] enters _bdv_isr() at cycle ");
-_putd(_get_proctime() );
-_puts("\n  for task ");
-_putd(ltid );
-_puts(" running on processor[");
-_putd(remote_x );
-_puts(",");
-_putd(remote_y );
-_puts(",");
-_putd(remote_p );
-_puts(" / bdv status = ");
-_putx(_bdv_status );
-_puts("\n");
-#endif
-
-}
+_printf("\n[IOC DEBUG] Processor[%d,%d,%d] enters _bdv_isr() at cycle %d\n"
+        "  for task %d running on P[%d,%d,%d] / bdv_status = %x\n",
+        x , y , p , _get_proctime() ,
+        ltid , remote_x , remote_y , remote_p , status );
+#endif
+
+} // end bdv_isr()
 
 
Index: /soft/giet_vm/giet_drivers/bdv_driver.h
===================================================================
--- /soft/giet_vm/giet_drivers/bdv_driver.h	(revision 528)
+++ /soft/giet_vm/giet_drivers/bdv_driver.h	(revision 529)
@@ -10,35 +10,17 @@
 // a single channel, block oriented, external storage contrÃŽler.
 //
-// The _bdv_read() and _bdv_write() functions are always blocking.
-// They can be called in 3 modes:
+// The _bdv_access() function supports both read and write access to block device,
+// and implement two operating modes:
 //
-// - In BOOT mode, these functions use a polling policy on the BDV STATUS 
+// - in "synchronous" mode, it uses a polling policy on the BDV STATUS 
 //   register to detect transfer completion, as interrupts are not activated. 
 //   This mode is used by the boot code to load the map.bin file into memory
 //   (before MMU activation), or to load the .elf files (after MMU activation). 
-//
-// - In KERNEL mode, these functions use a descheduling strategy:
-//   The ISR executed when transfer completes should restart the calling task.
-//   There is no checking of user access right to the memory buffer. 
-//   This mode must be used, for an "open" system call.
-//
-// - In USER mode, these functions use a descheduling strategy:
-//   The ISR executed when transfer completes should restart the calling task, 
-//   The user access right to the memory buffer must be checked.
-//   This mode must be used for a "read/write" system call.
-//
+// - In "descheduling" mode, ir uses a descheduling + IRQ policy.
+//   The ISR executed when transfer completes should restart the calling task,
+//   as the calling task global index has been saved in the _bdv_gtid variable.
+//   
 // As the BDV component can be used by several programs running in parallel,
-// the _bdv_lock variable guaranties exclusive access to the device.  The
-// _bdv_read() and _bdv_write() functions use atomic LL/SC to get the lock.
-//
-// Finally, the memory buffer must fulfill the following conditions:
-// - The buffer must be word aligned, 
-// - The buffer must be mapped in user space for an user access, 
-// - The buffer must be writable in case of (to_mem) access,
-// - The total number of physical pages occupied by the user buffer cannot
-//   be larger than 512 pages if the IOMMU is activated,
-// - All physical pages occupied by the user buffer must be contiguous
-//   if the IOMMU is not activated.
-// An error code is returned if these conditions are not verified.
+// the _bdv_lock variable guaranties exclusive access to the device.
 //
 // The SEG_IOC_BASE address must be defined in the hard_config.h file.
@@ -86,10 +68,12 @@
 
 ///////////////////////////////////////////////////////////////////////////////
-// BDV global variables
+//           Global variables
 ///////////////////////////////////////////////////////////////////////////////
 
 extern spin_lock_t  _bdv_lock;
+
+extern unsigned int _bdv_gtid;
+
 extern unsigned int _bdv_status;
-extern unsigned int _bdv_gtid;
 
 ///////////////////////////////////////////////////////////////////////////////////
@@ -104,38 +88,17 @@
 
 ///////////////////////////////////////////////////////////////////////////////////
-// Transfer data from the block device to a memory buffer. 
-// - mode     : BOOT / KERNEL / USER
+// Transfer data to/from the block device from/to a memory buffer. 
+// - use_irq  : descheduling + IRQ if non zero / polling if zero
+// - to_mem   : from external storage to memory when non 0.
 // - lba      : first block index on the block device
-// - buffer   : base address of the memory buffer (must be word aligned)
-// - count    : number of blocks to be transfered.
-// Returns 0 if success, > 0 if error.
-////////////////////////////////////////////////////////////////////////////////////
-extern unsigned int _bdv_read(  unsigned int       mode,
-                                unsigned int       lba, 
-                                unsigned long long buffer,
-                                unsigned int       count );
-
-///////////////////////////////////////////////////////////////////////////////////
-// Transfer data from a memory buffer to the block device. 
-// - mode     : BOOT / KERNEL / USER
-// - lba      : first block index on the block device
-// - buffer   : base address of the memory buffer (must be word aligned)
+// - buffer   : pbase address of the memory buffer (must be word aligned)
 // - count    : number of blocks to be transfered.
 // Returns 0 if success, > 0 if error.
 ///////////////////////////////////////////////////////////////////////////////////
-extern unsigned int _bdv_write( unsigned int       mode,
-                                unsigned int       lba, 
-                                unsigned long long buffer, 
-                                unsigned int       count );
-
-///////////////////////////////////////////////////////////////////////////////////
-// Returns device status.
-///////////////////////////////////////////////////////////////////////////////////
-extern unsigned int _bdv_get_status();
-
-///////////////////////////////////////////////////////////////////////////////////
-// Returns block size.
-///////////////////////////////////////////////////////////////////////////////////
-extern unsigned int _bdv_get_block_size();
+extern unsigned int _bdv_access( unsigned int       use_irq,
+                                 unsigned int       to_mem,
+                                 unsigned int       lba, 
+                                 unsigned long long buffer,
+                                 unsigned int       count );
 
 ///////////////////////////////////////////////////////////////////////////////////
Index: /soft/giet_vm/giet_drivers/dma_driver.c
===================================================================
--- /soft/giet_vm/giet_drivers/dma_driver.c	(revision 528)
+++ /soft/giet_vm/giet_drivers/dma_driver.c	(revision 529)
@@ -88,62 +88,64 @@
 
 ////////////////////////////////////////////////
-unsigned int _dma_init( unsigned int cluster_xy,
-                        unsigned int channel_id )
-{
-#if NB_DMA_CHANNELS > 0
-
-    // parameters checking 
+void _dma_disable_irq( unsigned int cluster_xy,
+                       unsigned int channel_id )
+{
+#if NB_DMA_CHANNELS > 0
+
+    // check DMA channel parameters 
     unsigned int x = cluster_xy >> Y_WIDTH;
     unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
-    if (x >= X_SIZE)                    return 1; 
-    if (y >= Y_SIZE)                    return 1; 
-    if (channel_id >= NB_DMA_CHANNELS)  return 1; 
+    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) )
+    {
+        _puts("\n[DMA ERROR] in _dma_disable_irq() : illegal DMA channel ");
+        _exit();
+    }
 
     // disable interrupt for selected channel
     _dma_set_register(cluster_xy, channel_id, DMA_IRQ_DISABLE, 1);
-    return 0;
-#else
-    return 1;
-#endif
-}
-
-//////////////////////////////////////////////////
-unsigned int _dma_reset( unsigned int cluster_xy, 
+
+#endif
+}
+
+/////////////////////////////////////////////////
+void _dma_reset_channel( unsigned int cluster_xy, 
                          unsigned int channel_id ) 
 {
 #if NB_DMA_CHANNELS > 0
 
-    // parameters checking 
+    // check DMA channel parameters 
     unsigned int x = cluster_xy >> Y_WIDTH;
     unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
-    if (x >= X_SIZE)                    return 1; 
-    if (y >= Y_SIZE)                    return 1; 
-    if (channel_id >= NB_DMA_CHANNELS)  return 1; 
+    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) )
+    {
+        _puts("\n[DMA ERROR] in _dma_reset_channel() : illegal DMA channel ");
+        _exit();
+    }
 
     // reset selected channel
     _dma_set_register(cluster_xy, channel_id, DMA_RESET, 0);
-    return 0;
-#else
-    return 1;
-#endif
-}
-
-//////////////////////////////////////////////////////
-unsigned int _dma_get_status( unsigned int cluster_xy, 
-                              unsigned int channel_id ) 
-{
-#if NB_DMA_CHANNELS > 0
-
-    // parameters checking 
+
+#endif
+}
+
+///////////////////////////////////////////////////////
+void _dma_get_status( unsigned int  cluster_xy, 
+                      unsigned int  channel_id,
+                      unsigned int* status ) 
+{
+#if NB_DMA_CHANNELS > 0
+
+    // check DMA channel parameters 
     unsigned int x = cluster_xy >> Y_WIDTH;
     unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
-    if (x >= X_SIZE)                    return 1; 
-    if (y >= Y_SIZE)                    return 1; 
-    if (channel_id >= NB_DMA_CHANNELS)  return 1;
-
-    // get selected channel status
-    return _dma_get_register(cluster_xy, channel_id, DMA_LEN);
-#else
-    return DMA_IDLE;
+    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) )
+    {
+        _puts("\n[DMA ERROR] in _dma_get_status() : illegal DMA channel ");
+        _exit();
+    }
+
+    // returns selected channel status
+    *status = _dma_get_register(cluster_xy, channel_id, DMA_LEN);
+
 #endif
 }
@@ -157,4 +159,13 @@
 {
 #if NB_DMA_CHANNELS > 0
+
+    // check DMA channel parameters 
+    unsigned int x = cluster_xy >> Y_WIDTH;
+    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
+    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) )
+    {
+        _puts("\n[DMA ERROR] in _dma_start_transfer() : illegal DMA channel ");
+        _exit();
+    }
 
     // selected channel configuration and lauching
@@ -169,5 +180,4 @@
     _dma_set_register(cluster_xy, channel_id, DMA_LEN,
             (unsigned int)size);
-
 #endif
 }
@@ -176,18 +186,9 @@
 void _dma_physical_copy( unsigned int       cluster_xy,  // DMA cluster
                          unsigned int       channel_id,  // DMA channel
-                         unsigned long long dst_paddr,   // destination physical address
-                         unsigned long long src_paddr,   // source physical address
+                         unsigned long long dst_paddr,   // dest physical address
+                         unsigned long long src_paddr,   // src physical address
                          unsigned int       size )       // bytes
 {
 #if NB_DMA_CHANNELS > 0
-
-    // check DMA channel parameters 
-    unsigned int x = cluster_xy >> Y_WIDTH;
-    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
-    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) )
-    {
-        _puts("\n[DMA ERROR] in _dma_physical_copy() : illegal DMA channel ");
-        _exit();
-    }
 
     // check buffers alignment constraints
@@ -199,4 +200,6 @@
 
 #if GIET_DEBUG_DMA_DRIVER
+unsigned int x = cluster_xy >> Y_WIDTH;
+unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
 _puts("\n[DMA DEBUG] enter _dma_physical_copy() for channel[");
 _putd( x );
@@ -212,34 +215,38 @@
 _putl( dst_paddr );
 _puts("\n - bytes       = ");
-_putd( size );
-_puts("\n");
-#endif
-
-    // dma channel configuration & lauching
+_putx( size );
+_puts("\n");
+#endif
+
+    // dma channel configuration 
+    _dma_disable_irq( cluster_xy, channel_id );
+
+    // dma transfer lauching
     _dma_start_transfer( cluster_xy, channel_id, dst_paddr, src_paddr, size ); 
 
     // scan dma channel status 
-    unsigned int status = _dma_get_status( cluster_xy, channel_id );
+    unsigned int status;
+    do
+    {
+        _dma_get_status( cluster_xy, channel_id , &status );
+
+#if GIET_DEBUG_DMA_DRIVER
+_puts("\n[DMA DEBUG] _dma_physical_copy() : ... waiting on DMA_STATUS\n");
+#endif
+
+    }
     while( (status != DMA_SUCCESS) && 
            (status != DMA_READ_ERROR) &&
-           (status != DMA_WRITE_ERROR) )
-    {
-        status = _dma_get_status( cluster_xy, channel_id );
-
-#if GIET_DEBUG_DMA_DRIVER
-_puts("\n[DMA DEBUG] _dma_physical_copy() : ... waiting on DMA_STATUS register\n");
-#endif
-
-    }
+           (status != DMA_WRITE_ERROR) );
     
     // analyse status
     if( status != DMA_SUCCESS )
     {
-        _puts("\n[DMA ERROR] in _dma_physical_copy() : bad DMA_STATUS");
+        _puts("\n[DMA ERROR] in _dma_physical_copy() : ERROR_STATUS");
         _exit();
     }
 
     // reset dma channel
-    _dma_reset( cluster_xy, channel_id );
+    _dma_reset_channel( cluster_xy , channel_id );
 
 #if GIET_DEBUG_DMA_DRIVER
@@ -261,5 +268,4 @@
 void  _dma_copy( unsigned int cluster_xy,    // DMA cluster
                  unsigned int channel_id,    // DMA channel
-                 unsigned int vspace_id,     // vspace index for v2p translation
                  unsigned int dst_vaddr,     // dst_vaddr buffer vbase
                  unsigned int src_vaddr,     // src_vaddr buffer vbase
@@ -268,13 +274,4 @@
 #if NB_DMA_CHANNELS > 0
 
-    // check DMA channel parameters 
-    unsigned int x = cluster_xy >> Y_WIDTH;
-    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
-    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) )
-    {
-        _puts("\n[DMA ERROR] in _dma_copy() : illegal DMA channel ");
-        _exit();
-    }
-
     // check buffers alignment constraints
     if ( (dst_vaddr & 0x3)   || (src_vaddr & 0x3) || (size & 0x3) )
@@ -284,8 +281,11 @@
     }
 
-    unsigned int ppn;
+    unsigned long long src_paddr;
+    unsigned long long dst_paddr;
     unsigned int flags;
 
 #if GIET_DEBUG_DMA_DRIVER
+unsigned int x = cluster_xy >> Y_WIDTH;
+unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
 _puts("\n[DMA DEBUG] enter _dma_copy() for channel[");
 _putd( x );
@@ -305,31 +305,9 @@
 #endif
 
-    // checking alignment constraints
-    if ( (((unsigned int)dst_vaddr) & 0x3) ||
-         (((unsigned int)src_vaddr) & 0x3) ||
-         (size & 0x3) )
-    {
-        _puts("\n[DMA ERROR] in _dma_copy() : buffer unaligned\n");
-        _exit();
-    }
-
-    // get vspace page table pointer 
-    unsigned int pt = _ptabs_vaddr[vspace_id];
-
     // get src_paddr buffer physical addresse
-    _v2p_translate( (page_table_t*)pt,              // page table pointer
-                     src_vaddr>>12,                  // vpn 
-                     &ppn,                           // ppn
-                     &flags );                       // flags
-    unsigned long long src_paddr = (((unsigned long long)ppn) << 12) | 
-                                   (unsigned long long)(src_vaddr & 0x00000FFF);
+    src_paddr = _v2p_translate( src_vaddr , &flags );
 
     // get dst_paddr buffer physical addresse
-    _v2p_translate( (page_table_t*)pt,              // page table pointer
-                     dst_vaddr>>12,                  // vpn 
-                     &ppn,                           // ppn
-                     &flags );                       // flags
-    unsigned long long dst_paddr = (((unsigned long long)ppn) << 12) | 
-                                   (unsigned long long)(dst_vaddr & 0x00000FFF);
+    dst_paddr = _v2p_translate( dst_vaddr , &flags );
 
 #if GIET_DEBUG_DMA_DRIVER
@@ -345,16 +323,17 @@
 
     // scan dma channel status 
-    unsigned int status = _dma_get_status( cluster_xy, channel_id );
+    unsigned int status;
+    do
+    {
+        _dma_get_status( cluster_xy, channel_id , &status );
+
+#if GIET_DEBUG_DMA_DRIVER
+_puts("\n[DMA DEBUG] _dma_physical_copy() : ... waiting on DMA_STATUS\n");
+#endif
+
+    }
     while( (status != DMA_SUCCESS) && 
            (status != DMA_READ_ERROR) &&
-           (status != DMA_WRITE_ERROR) )
-    {
-        status = _dma_get_status( cluster_xy, channel_id );
-
-#if GIET_DEBUG_DMA_DRIVER
-_puts("\n[DMA DEBUG] _dma_copy() : ... waiting on DMA_STATUS register\n");
-#endif
-
-    }
+           (status != DMA_WRITE_ERROR) );
     
     // analyse status
@@ -365,5 +344,5 @@
     }
     // reset dma channel
-    _dma_reset( cluster_xy, channel_id );
+    _dma_reset_channel( cluster_xy, channel_id );
 
 #if GIET_DEBUG_DMA_DRIVER
@@ -380,4 +359,5 @@
 #endif
 } // end _dma_copy
+
 
 /////////////////////////////////////
Index: /soft/giet_vm/giet_drivers/dma_driver.h
===================================================================
--- /soft/giet_vm/giet_drivers/dma_driver.h	(revision 528)
+++ /soft/giet_vm/giet_drivers/dma_driver.h	(revision 529)
@@ -15,5 +15,5 @@
 //
 // A DMA channel is a private ressource allocated to a given processor.
-// It is exclusively used by the kernet to speedup data transfers, and
+// It is exclusively used by the kernel to speedup data transfers, and
 // there is no lock protecting exclusive access to the channel.
 // As the kernel uses a polling policy on the DMA_STATUS register to detect
@@ -23,5 +23,5 @@
 //    SEG_DMA_BASE + cluster_xy * PERI_CLUSTER_INCREMENT + DMA_SPAN * channel_id
 //
-// The SEG_DMA_BASE virtual address mus be defined in the hard_config.h file.
+// The SEG_DMA_BASE virtual address must be defined in the hard_config.h file.
 //////////////////////////////////////////////////////////////////////////////////
 
@@ -63,23 +63,27 @@
 //////////////////////////////////////////////////////////////////////////////////
 // This function disables interrupts for one DMA channel in one cluster.
-// AS the GIET-VM uses a polling policy to detect DMA transfer completion,
-// the DMA component initialisation must disable interrupts.
-// Returns 0 if success, returns > 0 if error.
+// In case of error (illegal DMA channel), an error 
+// message is displayed on TTY0, and system crash.
 //////////////////////////////////////////////////////////////////////////////////
-extern unsigned int _dma_init( unsigned int cluster_xy,
-                               unsigned int channel_id );
+extern void _dma_disable_irq( unsigned int cluster_xy,
+                              unsigned int channel_id );
 
 //////////////////////////////////////////////////////////////////////////////////
 // This function re-initialises one DMA channel in one cluster after transfer
 // completion. It actually forces the channel to return in IDLE state.
+// In case of error (illegal DMA channel), an error 
+// message is displayed on TTY0, and system crash.
 //////////////////////////////////////////////////////////////////////////////////
-extern unsigned int _dma_reset( unsigned int  cluster_xy, 
+extern void _dma_reset_channel( unsigned int  cluster_xy, 
                                 unsigned int  channel_id );
 
 //////////////////////////////////////////////////////////////////////////////////
-// This function returns the status of a DMA channel in a given cluster
+// This function returns the status of a DMA channel in a given cluster.
+// In case of error (illegal DMA channel), an error 
+// message is displayed on TTY0, and system crash.
 //////////////////////////////////////////////////////////////////////////////////
-extern unsigned int _dma_get_status( unsigned int  cluster_xy, 
-                                     unsigned int  channel_id );
+extern void _dma_get_status( unsigned int  cluster_xy, 
+                             unsigned int  channel_id,
+                             unsigned int* status );
 
 //////////////////////////////////////////////////////////////////////////////////
@@ -87,4 +91,6 @@
 // for the source and destination buffers in a DMA channel in a given cluster
 // and sets the transfer size to lauch the transfer.
+// In case of error (illegal DMA channel), an error 
+// message is displayed on TTY0, and system crash.
 //////////////////////////////////////////////////////////////////////////////////
 extern void _dma_start_transfer( unsigned int       cluster_xy,
@@ -118,7 +124,4 @@
 // This function copies a source memory buffer to a destination memory buffer,
 // making virtual to physical address translation: the MMU should be activated. 
-// This blocking function is supposed to be used by the kernel only, 
-// and uses a polling policy on DMA_STATUS register to detect completion.
-// Therefore, the DMA_IRQ is NOT used.
 // The source and destination buffers base addresses must be word aligned, 
 // and the buffer's size must be multiple of 4.
@@ -128,5 +131,4 @@
 extern void _dma_copy(  unsigned int cluster_xy,
                         unsigned int channel_id,
-                        unsigned int vspace_id,
                         unsigned int dst_vaddr,
                         unsigned int src_vaddr,
@@ -134,6 +136,5 @@
 
 //////////////////////////////////////////////////////////////////////////////////
-// This ISR should not be used by the GIET_VM, because the DMA is only
-// used by the kernel in the boot phase, with a polling strategy.
+// Interrupt Service Routine.
 //////////////////////////////////////////////////////////////////////////////////
 extern void _dma_isr( unsigned int irq_type,
Index: /soft/giet_vm/giet_drivers/hba_driver.c
===================================================================
--- /soft/giet_vm/giet_drivers/hba_driver.c	(revision 528)
+++ /soft/giet_vm/giet_drivers/hba_driver.c	(revision 529)
@@ -1,3 +1,3 @@
-///////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////
 // File     : hba_driver.c
 // Date     : 23/11/2013
@@ -6,124 +6,125 @@
 ///////////////////////////////////////////////////////////////////////////////////
 // Implementation notes:
-// 1. In order to share code, the two _hba_read() and _hba_write() functions
-//    call the same _hba_set_cmd() function.
-// 2. All accesses to HBA registers are done by the two
-//    _hba_set_register() and _hba_get_register() low-level functions,
-//    that are handling virtual / physical extended addressing.
+// All accesses to HBA registers are done by the two
+// _hba_set_register() and _hba_get_register() low-level functions,
+// that are handling virtual / physical extended addressing.
 ///////////////////////////////////////////////////////////////////////////////////
 
 #include <giet_config.h>
-#include <ioc_driver.h>
+#include <hard_config.h>
+#include <hba_driver.h>
+#include <xcu_driver.h>
+#include <kernel_locks.h>
 #include <utils.h>
 #include <tty0.h>
-#include <iob_driver.h>
 #include <ctx_handler.h>
-#include <mmc_driver.h>
-#include <hba_driver.h>
+#include <irq_handler.h>
 #include <vmem.h>
 
-#if !defined( NB_IOC_CHANNELS )
-# error: You must define NB_IOC_CHANNELS in the hard_config.h file
-#endif
-
-#if ( NB_IOC_CHANNELS > 8 )
-# error: NB_IOC_CHANNELS cannot be larger than 8
-#endif
-
-#define in_unckdata __attribute__((section (".unckdata")))
-
-//////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////
 //               Global variables
-//////////////////////////////////////////////////////////////////
-
-// command list array (one per channel)
-hba_cmd_list_t   hba_cmd_list[NB_IOC_CHANNELS] __attribute__((aligned(0x1000)));   
-
-// command tables array (32 command tables per channel)
-hba_cmd_table_t  hba_cmd_table[NB_IOC_CHANNELS][32] __attribute__((aligned(0x1000))); 
-
-// command list physical addresses array (one per channel)
-paddr_t          hba_cmd_list_paddr[NB_IOC_CHANNELS];
-
-// command tables physical addresses array (32 command tables per channel)
-paddr_t          hba_cmd_table_paddr[NB_IOC_CHANNELS][32];
-
-// command list pointer array (one per channel)
-unsigned int     hba_cmd_slot[NB_IOC_CHANNELS];
+///////////////////////////////////////////////////////////////////////////////////
+
+// global index ot the task, for each entry in the command list
+__attribute__((section(".kdata")))
+unsigned int _hba_gtid[32];
+
+// status of the command, for each entry in the command list
+__attribute__((section(".kdata")))
+unsigned int _hba_status[32];
+
+// command list : up to 32 commands
+__attribute__((section(".kdata")))
+hba_cmd_desc_t  _hba_cmd_list[32] __attribute__((aligned(0x1000)));   
+
+// command tables array : one command table per entry in command list
+__attribute__((section(".kdata")))
+hba_cmd_table_t _hba_cmd_table[32] __attribute__((aligned(0x1000))); 
+
+// command list write index : next slot to register a command 
+__attribute__((section(".kdata")))
+unsigned int     _hba_cmd_ptw;
+
+// command list read index : next slot to poll a completed command 
+__attribute__((section(".kdata")))
+unsigned int     _hba_cmd_ptr;
 
 //////////////////////////////////////////////////////////////////////////////
-// This low level function returns the value of register (channel / index)
+// This low level function returns the value of register (index)
 //////////////////////////////////////////////////////////////////////////////
-unsigned int _hba_get_register( unsigned int channel,
-                                unsigned int index )
-{
-    unsigned int* vaddr = (unsigned int*)SEG_IOC_BASE + channel*HBA_SPAN + index;
+unsigned int _hba_get_register( unsigned int index )
+{
+    unsigned int* vaddr = (unsigned int*)SEG_IOC_BASE + index;
     return _io_extended_read( vaddr );
 }
 
 //////////////////////////////////////////////////////////////////////////////
-// This low level function set a new value in register (channel / index)  
+// This low level function set a new value in register (index)  
 //////////////////////////////////////////////////////////////////////////////
-void _hba_set_register( unsigned int channel,
-                        unsigned int index,
+void _hba_set_register( unsigned int index,
                         unsigned int value )
 {
-    unsigned int* vaddr = (unsigned int*)SEG_IOC_BASE + channel*HBA_SPAN + index;
+    unsigned int* vaddr = (unsigned int*)SEG_IOC_BASE + index;
     _io_extended_write( vaddr, value );
 }
 
+///////////////////////////////////////////////////////////////////////////////
+//      Extern functions
+///////////////////////////////////////////////////////////////////////////////
 
 ///////////////////////////////////////////////////////////////////////////////
 // This function register a command in both the command list
 // and the command table, and updates the HBA_PXCI register.
-// It uses the AHCI Scatter/Gather mechanisme to split the user 
-// buffer in several physical buffers, with the constraint that each physical
-// buffer must be an integer number of blocks entirely contained in a single
-// page frame. 
 // return 0 if success, -1 if error
 ///////////////////////////////////////////////////////////////////////////////
-unsigned int _hba_cmd_set( unsigned int  channel,     // channel index
-                           unsigned int  is_read,     // to memory
-                           unsigned int  lba,         // logic block address
-                           paddr_t       buffer,      // buffer physical address
-                           unsigned int  count )      // number of blocks
-{
-    unsigned int       block_size;     // defined by the block device (bytes)
-    unsigned int       pxci;           // command list status
-    unsigned int       cmd_id;         // command index in command list
-
+unsigned int _hba_access( unsigned int       use_irq,
+                          unsigned int       to_mem,
+                          unsigned int       lba,  
+                          unsigned long long buf_paddr,
+                          unsigned int       count )   
+{
+    unsigned int procid  = _get_procid();
+    unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
+    unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH) - 1);
+    unsigned int p       = procid & ((1<<P_WIDTH)-1);
+
+#if GIET_DEBUG_IOC_DRIVER
+_printf("\n[HBA DEBUG] P[%d,%d,%d] enters _hba_access at cycle %d\n"
+        "  use_irq = %d / to_mem = %d / lba = %x / paddr = %l / count = %d\n",
+        x , y , p , _get_proctime() , use_irq , to_mem , lba , buf_paddr, count );
+#endif
+
+    unsigned int       pxci;           // HBA_PXCI register value
+    unsigned int       ptw;            // command list write pointer
+    unsigned int       pxis;           // HBA_PXIS register value
     hba_cmd_desc_t*    cmd_desc;       // command descriptor pointer   
     hba_cmd_table_t*   cmd_table;      // command table pointer
 
-    block_size = _hba_get_block_size();
-
     // check buffer alignment
-    if( buffer & (block_size-1) )
-    {
-        _puts("\n[GIET ERROR] in _hba_set_cmd() : user buffer not block aligned\n");
+    if( buf_paddr & 0x1FF )
+    {
+        _printf("\n[HBA ERROR] in _hba_access() : buffer not block aligned\n");
         return -1;
     }
 
-    // get command list status from PXCI register
-    pxci = _hba_get_register( channel, HBA_PXCI );
-
-    // get command index and return error if command list full
-    cmd_id = hba_cmd_slot[channel];
-    if( pxci & (1<<cmd_id ) ) 
-    {
-        _puts("\n[GIET ERROR] in _hba_set_cmd() : command list full for channel ");
-        _putd( channel );
-        _puts("\n");
-        return -1;
-    }
-
+    // get pointer on the next possible entry in command list 
+    ptw = _atomic_increment( &_hba_cmd_ptw , 1 );
+
+    // poll PXCI register until pointed entry empty
+    do
+    {
+        // get PXCI register
+        pxci = _hba_get_register( HBA_PXCI );
+    } 
+    while ( pxci & (1<<ptw) );
+    
     // compute pointers on command descriptor and command table    
-    cmd_desc  = (hba_cmd_desc_t*)(&(hba_cmd_list[channel].desc[cmd_id]));
-    cmd_table = (hba_cmd_table_t*)(&(hba_cmd_table[channel][cmd_id]));
+    cmd_desc  = &_hba_cmd_list[ptw];
+    cmd_table = &_hba_cmd_table[ptw];
 
     // set  buffer descriptor in command table 
-    cmd_table->entry[0].dba  = (unsigned int)(buffer);
-    cmd_table->entry[0].dbau = (unsigned int)(buffer >> 32);
-    cmd_table->entry[0].dbc  = count * block_size;
+    cmd_table->entry[0].dba  = (unsigned int)(buf_paddr);
+    cmd_table->entry[0].dbau = (unsigned int)(buf_paddr >> 32);
+    cmd_table->entry[0].dbc  = count * 512;
 
     // initialize command table header
@@ -138,214 +139,208 @@
     cmd_desc->prdtl[0] = 1;
     cmd_desc->prdtl[1] = 0;
-    cmd_desc->ctba     = (unsigned int)(hba_cmd_table_paddr[channel][cmd_id]);
-    cmd_desc->ctbau    = (unsigned int)(hba_cmd_table_paddr[channel][cmd_id]>>32);
-    if( is_read ) cmd_desc->flag[0] = 0x00;
-    else          cmd_desc->flag[0] = 0x40;     
+    if( to_mem ) cmd_desc->flag[0] = 0x00;
+    else         cmd_desc->flag[0] = 0x40;     
    
-    // update PXCI register
-    _hba_set_register( channel, HBA_PXCI, (1<<cmd_id) );
-
-    // update command pointer 
-    hba_cmd_slot[channel] = (cmd_id + 1)%32;
-
-    return  0;
-} 
-
-/* This can be used for a future use with buffer in virtual space
-
-    // get user space page table virtual address
-    user_pt_vbase     = _get_context_slot(CTX_PTAB_ID);
-    vpn_min           = buf_vaddr >> 12;
-    vpn_max           = (buf_vaddr + (block_size*count) - 1) >> 12;
-    offset            = buf_vaddr & 0xFFF;
-    offset_last       = (buf_vaddr + (block_size*count) - 1) & 0xFFF;
-
-    // initialize all buffer descriptors in command table 
-    // (loop on all virtual pages covering the user buffer)
-    for( vpn = vpn_min, buf_id = 0 ; vpn <= vpn_max ; vpn++ )
-    {
-        paddr_t      paddr;
-        unsigned int count;
-        unsigned int ppn;
-        unsigned int flags;
-        unsigned int ko;
-        unsigned int buf_id = 0;
-
-        // get ppn and flags 
-        _v2p_translate( (page_table_t*)user_pt_vbase,
-                        vpn,
-                        &ppn,
-                        &flags );
-
-        // check access rights
-        if ((flags & PTE_U) == 0)
+    // set command in PXCI[ptw]
+    _hba_set_register( HBA_PXCI, pxci + (1<<ptw) );
+
+
+    /////////////////////////////////////////////////////////////////////
+    // In synchronous mode, we poll the PXCI register until completion
+    /////////////////////////////////////////////////////////////////////
+    if ( use_irq == 0 ) 
+    {
+
+#if GIET_DEBUG_IOC_DRIVER
+_printf("\n[HBA DEBUG] _hba_access() : P[%d,%d,%d] launch transfer"
+        " in polling mode at cycle %d\n",
+        x , y , p , _get_proctime() );
+#endif
+        // disable IRQs in PXIE register
+        _hba_set_register( HBA_PXIE , 0 );
+
+        // poll PXCI[ptw] until command completed by HBA
+        do
         {
-            _puts("[GIET ERROR] in _hba_set_cmd() : user buffer not in user space\n");
-            return -1;
+            pxci = _hba_get_register( HBA_PXCI ) & (1<<ptw);
+
+#if GIET_DEBUG_IOC_DRIVER
+_printf("\n[HBA DEBUG] _hba_access() : P[%d,%d,%d] wait on HBA_STATUS ...\n",
+        x , y , p );
+#endif
         }
-        if (((flags & PTE_W) == 0 ) && (is_read == 0) )
+        while( pxci & (1<<ptw) ); 
+             
+        // get PXIS register
+        pxis = _hba_get_register( HBA_PXIS );
+
+        // reset PXIS register
+        _hba_set_register( HBA_PXIS , 0 );
+    }
+
+    /////////////////////////////////////////////////////////////////
+    // in descheduling mode, we deschedule the task
+    // and use an interrupt to reschedule the task.
+    // We need a critical section, because we must reset the RUN bit
+	// before to launch the transfer, and we don't want to be 
+    // descheduled between these two operations. 
+    /////////////////////////////////////////////////////////////////
+    else
+    {
+
+#if GIET_DEBUG_IOC_DRIVER
+_printf("\n[HBA DEBUG] _hba_access() : P[%d,%d,%d] launch transfer"
+        " in descheduling mode at cycle %d\n",
+        x , y , p , _get_proctime() );
+#endif
+        unsigned int save_sr;
+        unsigned int ltid = _get_current_task_id();
+
+        // activates HBA interrupts 
+        _hba_set_register( HBA_PXIE , 0x00000001 ); 
+
+        // set _hba_gtid[ptw] 
+        _hba_gtid[ptw] = (procid<<16) + ltid;
+
+        // enters critical section
+        _it_disable( &save_sr ); 
+
+        // reset runnable 
+        _set_task_slot( x, y, p, ltid, CTX_RUN_ID, 0 );  
+
+        // deschedule task
+        _ctx_switch();                      
+
+#if GIET_DEBUG_IOC_DRIVER
+_printf("\n[HBA DEBUG] _hba_access() : P[%d,%d,%d] resume execution at cycle %d\n",
+        x , y , p , _get_proctime() );
+#endif
+
+        // restore SR
+        _it_restore( &save_sr );
+
+        // get command status
+        pxis = _hba_status[ptw];
+    }    
+
+#if GIET_DEBUG_IOC_DRIVER
+_printf("\n[HBA DEBUG] _hba_access() : P[%d,%d,%d] exit at cycle %d\n",
+        x , y , p , _get_proctime() );
+#endif
+
+    if ( pxis & 0x40000000 ) return pxis;
+    else                     return 0;
+
+} // end _hba_access()
+
+
+////////////////////////
+unsigned int _hba_init()
+{
+    unsigned int       flags;
+    unsigned int       vaddr;
+    unsigned long long paddr;
+    unsigned int       c;      
+    unsigned int       pxclb;
+    unsigned int       pxclbu;
+
+    // command list pointers
+    _hba_cmd_ptw = 0;
+    _hba_cmd_ptr = 0;
+
+    // Command list physical addresse
+    vaddr  = (unsigned int)(_hba_cmd_list);
+    paddr  = _v2p_translate( vaddr , &flags );
+    pxclb  = (unsigned int)paddr;
+    pxclbu = (unsigned int)(paddr>>32);
+
+    // Command tables physical addresses
+    for( c=0 ; c<32 ; c++ )
+    {
+        // compute command table physical address 
+        // for one entry in the command list
+        vaddr = (unsigned int)(&_hba_cmd_table[c]);
+        paddr = _v2p_translate( vaddr , &flags );
+
+        // initialise the corresponding command descriptor
+        _hba_cmd_list[c].ctba  = (unsigned int)paddr;
+        _hba_cmd_list[c].ctbau = (unsigned int)(paddr>>32);
+    }
+
+    // set HBA registers 
+    _hba_set_register( HBA_PXCLB , pxclb  );
+    _hba_set_register( HBA_PXCLBU, pxclbu );
+    _hba_set_register( HBA_PXIE  , 0      );
+    _hba_set_register( HBA_PXIS  , 0      );
+    _hba_set_register( HBA_PXCI  , 0      );
+    _hba_set_register( HBA_PXCMD , 1      );
+
+    return 0;
+}
+
+
+/////////////////////////////////////
+void _hba_isr( unsigned int irq_type,   // HWI / WTI
+               unsigned int irq_id,     // index returned by ICU
+               unsigned int channel )   // unused 
+{
+    // get HBA_PXCI containing commands status
+    unsigned int pxci = _hba_get_register( HBA_PXCI );
+
+    // scan active commands from (_hba_cmd_ptr) to (_hba_cmd_ptw-1) 
+    unsigned int c;
+    for ( c = _hba_cmd_ptr ; 
+          c != _hba_cmd_ptw ; 
+          c = (c + 1) % 32 )
+    {
+        if ( (pxci & (1<<c)) == 0 )    // command completed
         {
-            _puts("[GIET ERROR] in _hba_set_cmd() : user buffer not writable\n");
-            return -1;
+            // increment read pointer;
+            _hba_cmd_ptr++;
+
+            // save PXIS register
+            _hba_status[c] = _hba_get_register( HBA_PXIS );
+
+            // reset PXIS register
+            _hba_set_register( HBA_PXIS , 0 );
+ 
+            // identify waiting task 
+            unsigned int remote_procid  = _hba_gtid[c]>>16;
+            unsigned int ltid           = _hba_gtid[c] & 0xFFFF;
+            unsigned int remote_cluster = remote_procid >> P_WIDTH;
+            unsigned int remote_x       = remote_cluster >> Y_WIDTH;
+            unsigned int remote_y       = remote_cluster & ((1<<Y_WIDTH)-1);
+            unsigned int remote_p       = remote_procid & ((1<<P_WIDTH)-1);
+ 
+            // re-activates waiting task
+            _set_task_slot( remote_x,
+                            remote_y,
+                            remote_p,
+                            ltid,
+                            CTX_RUN_ID,
+                            1 );
+
+            // send a WAKUP WTI to processor running the waiting task 
+            _xcu_send_wti( remote_cluster , 
+                           remote_p , 
+                           0 );          // don't force context switch
+
+#if GIET_DEBUG_IOC_DRIVER  
+unsigned int procid  = _get_procid();
+unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
+unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
+unsigned int p       = procid & ((1<<P_WIDTH)-1);
+_printf("\n[HBA DEBUG] Processor[%d,%d,%d] executes _hba_isr() :\n"
+        "  resume task %d running on P[%d,%d,%d] / status = %x at cyle %d\n",
+        x , y , p , 
+        ltid , remote_x , remote_y , remote_p , _hba_status[c] , _get_proctime() );
+#endif
         }
-
-        // check buffer index overflow
-        if( buf_id > 245 )
+        else                         // command non completed
         {
-            _puts("[GIET ERROR] in _hba_set_cmd() : max number of buffers is 248\n");
-            return -1;   
-        }
-
-        // buffer allocation
-        if( vpn == vpn_min )       // first page: one single buffer
-        {
-            paddr = (((paddr_t)ppn) << 12) + offset;
-            count = 0x1000 - offset;
-            cmd_table->entry[buf_id].dba  = (unsigned int)(paddr);
-            cmd_table->entry[buf_id].dbau = (unsigned int)(paddr >> 32);
-            cmd_table->entry[buf_id].dbc  = count;
-
-            buf_id++;
-        }
-        else if( vpn == vpn_max )  // last page: one single buffer
-        {
-            paddr = (((paddr_t)ppn) << 12);
-            count = offset_last;
-            cmd_table->entry[buf_id].dba  = (unsigned int)(paddr);
-            cmd_table->entry[buf_id].dbau = (unsigned int)(paddr >> 32);
-            cmd_table->entry[buf_id].dbc  = count;
-
-            buf_id++;
-        }
-        else if( offset )          // midle page and offset != 0: two buffers  
-        {
-            paddr = (((paddr_t)ppn) << 12);
-            
-            count = offset;
-            cmd_table->entry[buf_id].dba  = (unsigned int)(paddr);
-            cmd_table->entry[buf_id].dbau = (unsigned int)(paddr >> 32);
-            cmd_table->entry[buf_id].dbc  = count;
-
-            buf_id++;
-
-            paddr = (((paddr_t)ppn) << 12) + offset;
-            count = 0x1000 - offset; 
-            cmd_table->entry[buf_id].dba  = (unsigned int)(paddr);
-            cmd_table->entry[buf_id].dbau = (unsigned int)(paddr >> 32);
-            cmd_table->entry[buf_id].dbc  = count;
-
-            buf_id++;
-        }
-        else                      // middle page and offset == 0: one buffer
-        {
-            paddr = (((paddr_t)ppn) << 12);
-            count = 0x1000; 
-            cmd_table->entry[buf_id].dba  = (unsigned int)(paddr);
-            cmd_table->entry[buf_id].dbau = (unsigned int)(paddr >> 32);
-            cmd_table->entry[buf_id].dbc  = count;
-
-            buf_id++;
+            break;
         }
     }
-*/
-
-
-//////////////////////////////////////////////
-unsigned int _hba_init( unsigned int channel )
-{
-    unsigned int ppn;
-    unsigned int flags;
-    unsigned int vbase;
-    unsigned int c;               // c == command index
-
-    // get page_table pointer
-    unsigned int pt = _get_context_slot(CTX_PTAB_ID);
-
-    // HBA registers TODO: ne faut_il pas un V2P pour PXCLB/PXCLBU ? (AG)
-    _hba_set_register( channel, HBA_PXCLB , (unsigned int)&hba_cmd_list[channel] );
-    _hba_set_register( channel, HBA_PXCLBU, 0 );
-    _hba_set_register( channel, HBA_PXIE  , 0x40000001 );
-    _hba_set_register( channel, HBA_PXIS  , 0 );
-    _hba_set_register( channel, HBA_PXCI  , 0 );
-    _hba_set_register( channel, HBA_PXCMD , 1 );
-
-    // command list pointer       
-    hba_cmd_slot[channel] = 0;
-
-    // Command list physical addresse
-    vbase = (unsigned int)(&hba_cmd_list[channel]);
-    _v2p_translate( (page_table_t*)pt,
-                     vbase>>12,
-                     &ppn,
-                     &flags );
-    hba_cmd_list_paddr[channel] = ((paddr_t)ppn) | (vbase & 0xFFF);
-
-    // Command tables physical addresses
-    for( c=0 ; c<32 ; c++ )
-    {
-        vbase = (unsigned int)(&hba_cmd_table[channel][c]);
-        _v2p_translate( (page_table_t*)pt,
-                         vbase>>12,
-                         &ppn,
-                         &flags );
-        hba_cmd_table_paddr[channel][c] = ((paddr_t)ppn) | (vbase & 0xFFF);
-    }
-
-    return 0;
-}
-
-///////////////////////////////////////////////
-unsigned int _hba_write( unsigned int  channel,
-                         unsigned int  mode,
-                         unsigned int  lba,
-                         paddr_t       buffer, 
-                         unsigned int  count )
-{
-    return _hba_cmd_set( channel, 
-                         0,         // write 
-                         lba, 
-                         buffer, 
-                         count );
-}
-
-//////////////////////////////////////////////
-unsigned int _hba_read( unsigned int  channel,
-                        unsigned int  mode,
-                        unsigned int  lba, 
-                        paddr_t       buffer, 
-                        unsigned int  count )
-{
-    return _hba_cmd_set( channel,
-                         1,          // read
-                         lba, 
-                         buffer, 
-                         count );
-}
-
-//////////////////////////////////
-unsigned int _hba_get_block_size()
-{
-    // TODO The block size must be obtained from the hardware...
-    return 512;
-}
-
-////////////////////////////////////////////////////
-unsigned int _hba_get_status( unsigned int channel ) 
-{
-
-    if( channel >= NB_IOC_CHANNELS )
-    {
-        _puts("\n[GIET ERROR] in _hba_get_status() : illegal channel\n");
-        _exit();
-    }
-
-    // get HBA_PXIS value
-    unsigned int status = _hba_get_register( channel, HBA_PXIS );
-
-    // reset HBA_PXIS
-    _hba_set_register( channel, HBA_PXIS, 0 );
-
-    return status;
-}
+} // end _hba_isr()
 
 // Local Variables:
Index: /soft/giet_vm/giet_drivers/hba_driver.h
===================================================================
--- /soft/giet_vm/giet_drivers/hba_driver.h	(revision 528)
+++ /soft/giet_vm/giet_drivers/hba_driver.h	(revision 529)
@@ -8,4 +8,31 @@
 // This driver supports the SocLib VciMultiAhci component, that is a multi-channels,
 // block oriented, external storage contrÃŽler, respecting the AHCI standard.
+//
+// 1. Each HBA channel define an independant physical disk, but this driver
+//    supports only channel 0, because the GIET-VM uses only one physical disk.
+//
+// 2. The "command list" can contain up to 32 independant commands, posted
+//    by different user tasks. These independant transfers are handled 
+//    by the HBA device in the same order as they have been written by the
+//    driver(s) in the command list. There is no global lock protecting the
+//    the HBA device, but the command list being a shared structure, the driver
+//    must use an atomic_increment() to get a slot in the command list,
+//    and increment the write pointer.
+//
+// 3. This driver implements two operating mode: 
+//    - In synchronous mode, the calling task poll the HBA_PXCI register to
+//    detect the command completion (busy waiting). 
+//    - In descheduling mode, the calling task is descheduled, and must be
+//    restart when the command is completed.
+// 
+// 4. As several user tasks can concurrently register commands in the command
+//    list, and there is only one HBA interrupt, this interrupt is not linked
+//    to a specific task. In descheduling mode, the HBA IRQ is a "global" IRQ
+//    that is statically routed to processor P[x_io,y_io,0] in cluster_io. 
+//    The associated global HBA_ISR send a WAKUP WTI to all tasks that have
+//    a completed command. This HBA_ISR uses a read pointer on the command 
+//    to identify the first expected command completion. The incrementation 
+//    of this read pointer does not require atomic_increment as there is
+//    no concurrent access for this pointer. 
 //
 // The SEG_IOC_BASE virtual address must be defined in the hard_config.h file.
@@ -74,5 +101,5 @@
 
 ///////////////////////////////////////////////////////////////////////////////////
-// Data structures for command list array
+// Data structure for command descriptor in command list
 ///////////////////////////////////////////////////////////////////////////////////
 
@@ -92,11 +119,4 @@
 } hba_cmd_desc_t;
 
-typedef struct hba_cmd_list_s  // size = 512 bytes
-{
-    // 32 command descriptors
-    hba_cmd_desc_t desc[32];
-
-} hba_cmd_list_t;
-
 ///////////////////////////////////////////////////////////////////////////////////
 //              access functions  
@@ -110,41 +130,23 @@
 // - the command tables physical addresses array,
 ///////////////////////////////////////////////////////////////////////////////////
-extern unsigned int _hba_init ( unsigned int channel ); 
+extern unsigned int _hba_init (); 
 
 ///////////////////////////////////////////////////////////////////////////////////
-// This function register a write command in Command List and Command Table
+// This function register a command in Command List and Command Table
 // for a single physical buffer, and updates the HBA_PXCI register.
 // Returns 0 if success, > 0 if error.
 ///////////////////////////////////////////////////////////////////////////////////
-extern unsigned int _hba_write( unsigned int channel,     // channel index
-                                unsigned int mode,        // BOOT / KERNEL / USER
-                                unsigned int lba,         // logic bloc address on device
-                                unsigned long long paddr, // memory buffer base address
-                                unsigned int count );     // number of blocs
+extern unsigned int _hba_access( unsigned int       use_irq,
+                                 unsigned int       to_mem,
+                                 unsigned int       lba, 
+                                 unsigned long long paddr, 
+                                 unsigned int       count );
 
-//////////////////////////////////////////////////////////////////////////////////
-// This function register a read command in Command List and Command Table
-// for a single physical buffer, and updates the HBA_PXCI register.
-// Returns 0 if success, > 0 if error.
-//////////////////////////////////////////////////////////////////////////////////
-extern unsigned int _hba_read ( unsigned int channel,     // channel index
-                                unsigned int mode,        // BOOT / KERNEL / USER
-                                unsigned int lba,         // logic bloc address on device
-                                unsigned long long paddr, // memory buffer base address
-                                unsigned int count );     // number of blocks
-
-/////////////////////////////////////////////////////////////////////////////////
-// This function returns the block_size of HBA controller
-/////////////////////////////////////////////////////////////////////////////////
-extern unsigned int _hba_get_block_size ();
-
-/////////////////////////////////////////////////////////////////////////////////////
-// This function returns the content of the HBA_PXIS register for a given channel, 
-// and reset this register to acknoledge IRQ.
-// return 0 if success, > 0 if error
-/////////////////////////////////////////////////////////////////////////////////////
-extern unsigned int _hba_get_status( unsigned int   channel );
-
-
+///////////////////////////////////////////////////////////////////////////////////
+// Interrupt Service Routine executed in descheduling mode.
+///////////////////////////////////////////////////////////////////////////////////
+extern void _hba_isr( unsigned int irq_type,
+                      unsigned int irq_id,
+                      unsigned int channel );
 #endif
 
Index: ft/giet_vm/giet_drivers/ioc_driver.c
===================================================================
--- /soft/giet_vm/giet_drivers/ioc_driver.c	(revision 528)
+++ 	(revision )
@@ -1,309 +1,0 @@
-///////////////////////////////////////////////////////////////////////////////////
-// File       : ioc_driver.c
-// Date       : 23/05/2013
-// Author     : alain greiner
-// Maintainer : cesar fuguet
-// Copyright (c) UPMC-LIP6
-///////////////////////////////////////////////////////////////////////////////////
-// Implementation notes:
-// 1) In order to share the code, the two _ioc_read() and _ioc_write() functions
-// call the same _ioc_access() function, and this function call the selected
-// physical driver (BDV / HBA / SPI / RDK).
-// 2) The IOMMU is not supported yet, but the method is the following:
-// A fixed size 2 Mbytes vseg is allocated to the IOC peripheral, in the I/O 
-// virtual space, and the user buffer is dynamically remapped to one single
-// big page in the IOMMU page table.
-// The user buffer is unmapped by the _ioc_completed() function when 
-// the transfer is completed.
-///////////////////////////////////////////////////////////////////////////////////
-
-#include <giet_config.h>
-#include <ioc_driver.h>
-#include <bdv_driver.h>
-#include <hba_driver.h>
-#include <sdc_driver.h>
-#include <rdk_driver.h>
-#include <utils.h>
-#include <tty0.h>
-#include <iob_driver.h>
-#include <ctx_handler.h>
-#include <mmc_driver.h>
-#include <vmem.h>
-
-#if !defined( SEG_IOC_BASE )
-# error: You must define SEG_IOC_BASE in the hard_config.h file
-#endif
-
-#if !defined( USE_IOB )
-# error: You must define USE_IOB in the hard_config.h file
-#endif
-
-#if !defined(GIET_USE_IOMMU) 
-# error: You must define GIET_USE_IOMMU in the giet_config.h file
-#endif
-
-#if (USE_IOC_BDV + USE_IOC_SPI + USE_IOC_HBA + USE_IOC_RDK) != 1
-# error: You must use only one IOC controller type (BDV or SPI or HBA or RDK)
-#endif
-
-#if USE_IOC_BDV
-# include <bdv_driver.h>
-#endif
-
-#if USE_IOC_SPI
-# include <sdc_driver.h>
-#endif
-
-#if USE_IOC_HBA
-# include <hba_driver.h>
-#endif
-
-#if USE_IOC_RDK
-# include <rdk_driver.h>
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// IOC global variables
-///////////////////////////////////////////////////////////////////////////////
-
-__attribute__((section (".kdata")))
-volatile unsigned int _ioc_iommu_ix1 = 0;
-
-__attribute__((section (".kdata")))
-volatile unsigned int _ioc_iommu_npages; 
-
-///////////////////////////////////////////////////////////////////////////////
-// This function transfer data between a memory buffer and the block device.
-// The buffer lentgth is (count*block_size) bytes.
-// Arguments are:
-// - to_mem     : from external storage to memory when non 0.
-// - mode       : BOOT_PA / BOOT_VA / KERNEL / USER 
-// - lba        : first block index on the external storage.
-// - buf_vaddr  : virtual base address of the memory buffer.
-// - count      : number of blocks to be transfered.
-// Returns 0 if success, > 0 if error.
-///////////////////////////////////////////////////////////////////////////////
-static unsigned int _ioc_access( unsigned int to_mem,
-                                 unsigned int channel,
-                                 unsigned int mode,
-                                 unsigned int lba,
-                                 unsigned int buf_vaddr,
-                                 unsigned int count) 
-{
-
-#if GIET_DEBUG_IOC_DRIVER
-unsigned int procid  = _get_procid();
-unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
-unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
-unsigned int p       = procid & ((1<<P_WIDTH)-1);
-_printf("\n[IOC DEBUG] _ioc_access() : P[%d,%d,%d] enters at cycle %d\n"
-        " - channel  = %d\n"
-        " - mode     = %d\n"
-        " - vaddr    = %x\n"
-        " - sectors  = %d\n"
-        " - lba      = %x\n",
-        x, y , p, _get_proctime(), channel, mode, buf_vaddr, count, lba );
-#endif
-
-    unsigned int error;            // return value
-    unsigned int pt_vbase;         // page table vbase address
-    unsigned int ppn;              // user buffer first page PPN
-    unsigned int flags;            // user buffer protection flags
-    paddr_t      buf_paddr;        // user buffer physical address (if no IOMMU),
-
-    // check buffer alignment
-    if ((unsigned int) buf_vaddr & 0x3)
-    {
-        _puts("\n[IOC ERROR] in _ioc_access() : buffer not word aligned\n");
-        _exit(); 
-    }
-
-    // check channel 
-    if ( (USE_IOC_HBA == 0) && (channel > 0) )
-    {
-        _puts("\n[IOC ERROR] in _ioc_access() : channel must be 0 when HBA not used\n");
-        _exit(); 
-    }
-
-    unsigned int length = count << 9;  // count * 512 bytes
-
-    // computing memory buffer physical address
-    if ( (mode == IOC_BOOT_MODE) && ((_get_mmu_mode() & 0x4) == 0) ) // identity
-    {
-        buf_paddr = (paddr_t)buf_vaddr;
-    }
-    else                                                 // V2P translation required
-    {
-        // get page table virtual address
-        pt_vbase = _get_context_slot(CTX_PTAB_ID);
-
-        // get user buffer first page ppn and flags
-        _v2p_translate( (page_table_t*)pt_vbase,
-                        buf_vaddr >> 12,
-                        &ppn,
-                        &flags );
-
-        // check access rights
-        if ( (mode == IOC_USER_MODE) && ((flags & PTE_U) == 0) )
-        {
-            _puts("\n[IOC ERROR] in _ioc_access() : buffer not user accessible\n");
-            _exit(); 
-        }
-
-        if ( ((flags & PTE_W) == 0 ) && to_mem )
-        {
-            _puts("\n[IOC ERROR] in _ioc_access() : buffer not writable\n");
-            _exit(); 
-        }
-
-        buf_paddr = (((paddr_t)ppn) << 12) | (buf_vaddr & 0xFFF);
-    }
-
-    // cache coherence for both L1 & L2 caches
-
-    if ( to_mem ) // memory write : invalidate data caches 
-    {
-        // L1 cache (only if L1 cache coherence not guaranteed by hardware)
-        if ( GIET_NO_HARD_CC ) _dcache_buf_invalidate( buf_vaddr, length );
-
-        // L2 cache (only if we use an IO-Bridge component in architecture))
-        if ( USE_IOB ) _mmc_inval( buf_paddr, length );
-    }
-    else         // memory read : update data caches
-    {
-        // L1 cache : nothing to do for L1 write-through
-
-        // L2 cache (only if we use an IO-Bridge component in architecture))
-        if ( USE_IOB ) _mmc_sync( buf_paddr, length );
-    }
-
-    // select the proper physical device 
-
-#if   ( USE_IOC_BDV )
-        if (to_mem) error = _bdv_read ( mode, lba, buf_paddr, count);
-        else        error = _bdv_write( mode, lba, buf_paddr, count);
-#elif ( USE_IOC_SPI )
-        if (to_mem) error = _sdc_read (mode, lba, buf_paddr, count);
-        else        error = _sdc_write(mode, lba, buf_paddr, count);
-#elif ( USE_IOC_HBA )
-        if (to_mem) error = _hba_read (channel, mode, lba, buf_paddr, count);
-        else        error = _hba_write(channel, mode, lba, buf_paddr, count);
-#elif ( USE_IOC_RDK )
-        if (to_mem) error = _rdk_read (lba, buf_vaddr, count);
-        else        error = _rdk_write(lba, buf_vaddr, count);
-#endif
-
-    return error;
-} // end _ioc_access()
-
-//////////////////////////////////////////////
-unsigned int _ioc_init( unsigned int channel )
-{
-
-#if   ( USE_IOC_BDV ) 
-
-    return _bdv_init();
-
-#elif ( USE_IOC_SPI ) 
-
-    return _sdc_init();
-    
-#elif ( USE_IOC_HBA ) 
-
-    return _hba_init( channel );
-    
-#elif ( USE_IOC_RDK ) 
-
-    return _rdk_init();
-    
-#endif
-    
-}
-
-//////////////////////////////////////////////
-unsigned int _ioc_read( unsigned int channel,
-                        unsigned int mode,  
-                        unsigned int lba, 
-                        void*        buffer, 
-                        unsigned int count) 
-{
-    return _ioc_access( 1,        // read access
-                        channel,
-                        mode,  
-                        lba,
-                        (unsigned int) buffer,
-                        count );
-}
-
-//////////////////////////////////////////////
-unsigned int _ioc_write( unsigned int channel,
-                         unsigned int mode,  
-                         unsigned int lba, 
-                         const void*  buffer, 
-                         unsigned int count ) 
-{
-    return _ioc_access( 0,        // write access
-                        channel,
-                        mode,  
-                        lba,
-                        (unsigned int) buffer,
-                        count );
-}
-
-/////////////////////////////////////////////////////
-unsigned int _ioc_get_status( unsigned int  channel )
-{
-
-#if   ( USE_IOC_BDV ) 
-
-    return _bdv_get_status( );
-
-#elif ( USE_IOC_SPI ) 
-
-    return _sdc_get_status( );
-
-#elif ( USE_IOC_HBA ) 
-
-    return _hba_get_status( channel );
-
-#elif ( USE_IOC_RDK )
-
-    return _rdk_get_status();
-
-#endif
-
-}
-
-//////////////////////////////////
-unsigned int _ioc_get_block_size() 
-{
-
-#if   ( USE_IOC_BDV ) 
-
-    return _bdv_get_block_size();
-    
-#elif ( USE_IOC_SPI ) 
-
-    return _sdc_get_block_size();
-    
-#elif ( USE_IOC_HBA ) 
-
-    return _hba_get_block_size();
-    
-#elif ( USE_IOC_RDK ) 
-
-    return 512;
-
-#endif
-
-}
-
-
-// Local Variables:
-// tab-width: 4
-// c-basic-offset: 4
-// c-file-offsets:((innamespace . 0)(inline-open . 0))
-// indent-tabs-mode: nil
-// End:
-// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
-
Index: ft/giet_vm/giet_drivers/ioc_driver.h
===================================================================
--- /soft/giet_vm/giet_drivers/ioc_driver.h	(revision 528)
+++ 	(revision )
@@ -1,154 +1,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// File     : ioc_driver.h
-// Date     : 01/11/2013
-// Author   : alain greiner
-// Copyright (c) UPMC-LIP6
-///////////////////////////////////////////////////////////////////////////////
-// The ioc_driver.c and ioc_driver.h files are part ot the GIET-VM kernel.
-//
-// This abstact driver define a generic API, supporting various physical
-// block device controlers, including:
-// - vci_block_device : single channel                     => bdv_driver
-// - vci_ahci         : multi channels                     => hba_driver
-// - sd_card          : single channel                     => sdc_driver
-// - ramdisk (single channel meory mapped virtual disk)    => rdk_driver
-//
-// It can exist only one block-device type in the architecture, that must be
-// defined by one of the following configuration variables in hard_config.h file:
-// USE_IOC_BDV, USE_IOC_SDC, USE_IOC_HBA, USE_IOC_RDK.
-//
-// Any physical block device driver must provide the 5 five functions defined
-// by this generic driver.
-//
-// The _ioc_read() and _ioc_write() functions are always blocking for
-// the calling user program.
-//
-// These functions compute the physical address of the memory buffer before 
-// calling the proper physical device. We know that the user buffer is mapped 
-// to a contiguous physical buffer because, for each vseg, the page tables
-// are statically constructed to use contiguous physical memory.
-//
-// These functions can be called in 3 modes:
-//
-// - In BOOT mode, these functions use the buffer virtual address
-//   as a physical address if the MMU is not activated.
-//   They make a V2P translation if the MMU is activated.
-//   This mode is used to load the map.bin file (before memory activation),
-//   or to load the various .elf files (after MMU activation).
-//
-// - In KERNEL mode, these functions make a V2P translation to
-//   compute the buffer physical address.
-//   There is no checking of user access right to the memory buffer.  
-//   This mode must be used for an "open" system call.
-//
-// - In USER mode, these functions make a V2P translation to
-//   compute the buffer physical address. 
-//   The user access right to the memory buffer are checked.  
-//   This mode must be used for a "read" or "write" system call.
-//
-// Finally, the memory buffer must fulfill the following conditions:
-// - The buffer must be word aligned, 
-// - The buffer must be mapped in user space for an user access, 
-// - The buffer must be writable in case of (to_mem) access,
-// - The total number of physical pages occupied by the user buffer cannot
-//   be larger than 512 pages if the IOMMU is activated,
-// - All physical pages occupied by the user buffer must be contiguous
-//   if the IOMMU is not activated.
-// Exit if these conditions are not verified.
-//
-// The SEG_IOC_BASE virtual base address must be defined in hard_config.h,
-// as it is used by the BDV, HBA and SPI drivers.
-//
-// If the RAMDISK is used, an extra memory segment with virtual base address
-// SEG_RDK_BASE, used by RDK driver, must be defined in hard_config.h.
-//
-// The IOMMU is not supported yet, but the method is the following:
-// A fixed size 2 Mbytes vseg is allocated to the IOC peripheral, in the I/O 
-// virtual space, and the user buffer is dynamically remapped to one single
-// big page in the IOMMU page table.
-// The user buffer is unmapped by the _ioc_completed() function when 
-// the transfer is completed.
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef _GIET_IOC_DRIVER_H_
-#define _GIET_IOC_DRIVER_H_
-
-///////////////////////////////////////////////////////////////////////////////
-// IOC (vci_block device) registers offsets
-///////////////////////////////////////////////////////////////////////////////
-
-enum IOC_driver_modes
-{
-    IOC_BOOT_MODE   = 0,     //  Polling IOC_STATUS / no access right checking
-    IOC_KERNEL_MODE = 1,     //  Descheduling + IRQ / no access right checking
-    IOC_USER_MODE   = 2,     //  Descheduling + IRQ / access right checking
-};
-
-///////////////////////////////////////////////////////////////////////////////
-//      External global variables
-///////////////////////////////////////////////////////////////////////////////
-
-extern volatile unsigned int _ioc_iommu_ix1;
-extern volatile unsigned int _ioc_iommu_npages; 
-
-///////////////////////////////////////////////////////////////////////////////
-//      External functions                            
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// This function cheks block size, and desactivates interrupts.
-// Return 0 for success, non zero if error.
-///////////////////////////////////////////////////////////////////////////////
-extern unsigned int _ioc_init( unsigned int channel );
-
-///////////////////////////////////////////////////////////////////////////////
-// Transfer data from a memory buffer to the disk. 
-// - mode     : BOOT / KERNEL / USER 
-// - lba      : first block index on the block device
-// - buffer   : base address of the memory buffer (must be word aligned)
-// - count    : number of blocks to be transfered.
-// Returns 0 if success, > 0 if error.
-///////////////////////////////////////////////////////////////////////////////
-extern unsigned int _ioc_write( unsigned int channel,
-                                unsigned int mode,
-                                unsigned int lba, 
-                                const void*  buffer, 
-                                unsigned int count );
-
-///////////////////////////////////////////////////////////////////////////////
-// Transfer data from the disk to a memory buffer. 
-// - mode     : BOOT / KERNEL / USER 
-// - lba      : first block index on the block device
-// - buffer   : base address of the memory buffer (must be word aligned)
-// - count    : number of blocks to be transfered.
-// Returns 0 if success, > 0 if error.
-///////////////////////////////////////////////////////////////////////////////
-extern unsigned int _ioc_read(  unsigned int channel,
-                                unsigned int mode,
-                                unsigned int lba, 
-                                void*        buffer,
-                                unsigned int count );
-
-///////////////////////////////////////////////////////////////////////////////
-// This function returns in the status variable, the transfert status, and
-// acknowledge the IRQ if required.
-// Returns 0 if success, > 0 if error
-///////////////////////////////////////////////////////////////////////////////
-extern unsigned int _ioc_get_status( unsigned int channel );
-
-///////////////////////////////////////////////////////////////////////////////
-// This function returns the block_size for the block device.
-///////////////////////////////////////////////////////////////////////////////
-extern unsigned int _ioc_get_block_size();
-
-
-#endif
-
-// Local Variables:
-// tab-width: 4
-// c-basic-offset: 4
-// c-file-offsets:((innamespace . 0)(inline-open . 0))
-// indent-tabs-mode: nil
-// End:
-// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
-
Index: /soft/giet_vm/giet_drivers/mwr_driver.c
===================================================================
--- /soft/giet_vm/giet_drivers/mwr_driver.c	(revision 528)
+++ /soft/giet_vm/giet_drivers/mwr_driver.c	(revision 529)
@@ -11,4 +11,5 @@
 #include <mwr_driver.h>
 #include <utils.h>
+#include <kernel_locks.h>
 #include <tty0.h>
 #include <io.h>
@@ -38,5 +39,14 @@
 #endif
 
-extern unsigned int _coproc_done[X_SIZE*Y_SIZE];
+
+/////////////////////////////////////////////////////////////////////////////
+//      Global variables
+/////////////////////////////////////////////////////////////////////////////
+
+__attribute__((section(".kdata")))
+simple_lock_t  _coproc_lock[X_SIZE*Y_SIZE];
+
+__attribute__((section(".kdata")))
+unsigned int   _coproc_done[X_SIZE*Y_SIZE];
 
 /////////////////////////////////////////////////////////////////////////////
Index: /soft/giet_vm/giet_drivers/rdk_driver.c
===================================================================
--- /soft/giet_vm/giet_drivers/rdk_driver.c	(revision 528)
+++ /soft/giet_vm/giet_drivers/rdk_driver.c	(revision 529)
@@ -1,3 +1,3 @@
-///////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
 // File      : rdk_driver.c
 // Date      : 13/02/2014
@@ -5,5 +5,5 @@
 // Maintainer: cesar fuguet
 // Copyright (c) UPMC-LIP6
-///////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
 
 #include <giet_config.h>
@@ -17,86 +17,38 @@
 #endif
 
-//////////////////////////////////////////////
-unsigned int _rdk_init( unsigned int channel )
-{
-    return 0;
-}
-
-//////////////////////////////////////////
-unsigned int _rdk_read( unsigned int lba, 
-                        unsigned int buffer, 
-                        unsigned int count) 
+/////////////////////////////////////////////////////
+unsigned int _rdk_access( unsigned int       use_irq,    // not used
+                          unsigned int       to_mem,
+                          unsigned int       lba, 
+                          unsigned long long buf_vaddr,  // actually vaddr
+                          unsigned int       count) 
 {
 #if USE_IOC_RDK
 
 #if GIET_DEBUG_IOC_DRIVER
-_puts("\n[IOC DEBUG] Enter _rdk_read() at cycle ");
-_putd( _get_proctime() );
-_puts("\n - vaddr   = "); 
-_putx( buffer );
--puts("\n - sectors = "); 
-_putd( count );
--puts("\n - lba     = "); 
-_putx( lba );
-_puts("\n");
+unsigned int procid  = _get_procid();
+unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
+unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH) - 1);
+unsigned int p       = procid & ((1<<P_WIDTH)-1);
+_printf("\n[RDK DEBUG] P[%d,%d,%d] enters _rdk_access at cycle %d\n"
+        "  use_irq = %d / to_mem = %d / lba = %x / paddr = %x / count = %d\n",
+        x , y , p , _get_proctime() , use_irq , to_mem , lba , buf_vaddr, count );
 #endif
 
-    char* src = (char*)SEG_RDK_BASE + (512*lba);
-    char* dst = (char*)buffer;
-    memcpy( dst, src, count*512 );
+    char* rdk = (char*)SEG_RDK_BASE + (512*lba);
+    char* buf = (char*)buf_paddr;
+
+    if ( to_mem ) memcpy( buf, rdk, count*512 );
+    else          memcpy( rdk, buf, count*512 );
+
     return 0;
 
 #else
 
-    _puts("[GIET ERROR] _rdk_read() should not be used if USE_IOC_RDK not set\n");
+    _printf("[RDK ERROR] _rdk_access() but USE_IOC_RDK not set\n");
     return 1;
 
 #endif
 }
-
-//////////////////////////////////////////
-unsigned int _rdk_write( unsigned int lba, 
-                         unsigned int buffer, 
-                         unsigned int count ) 
-{
-#if USE_IOC_RDK
-
-#if GIET_DEBUG_IOC_DRIVER
-_puts("\n[IOC DEBUG] Enter _rdk_write() at cycle ");
-_putd( _get_proctime() );
-_puts("\n - vaddr   = "); 
-_putx( buffer );
--puts("\n - sectors = "); 
-_putd( count );
--puts("\n - lba     = "); 
-_putx( lba );
-_puts("\n");
-#endif
-
-    char* dst = (char*)SEG_RDK_BASE + (512*lba);
-    char* src = (char*)buffer;
-    memcpy( dst, src, count*512 );
-    return 0;
-
-#else
-
-    _puts("[GIET ERROR] _rdk_write() should not be used if USE_IOC_RDK not set\n");
-    return 1;
-
-#endif
-}
-
-//////////////////////////////////
-unsigned int _rdk_get_block_size() 
-{
-    return 512;
-}
-
-//////////////////////////////
-unsigned int _rdk_get_status() 
-{
-    return 0;
-}
-
 
 // Local Variables:
Index: /soft/giet_vm/giet_drivers/rdk_driver.h
===================================================================
--- /soft/giet_vm/giet_drivers/rdk_driver.h	(revision 528)
+++ /soft/giet_vm/giet_drivers/rdk_driver.h	(revision 529)
@@ -1,8 +1,8 @@
-///////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
 // File      : rdk_driver.h
 // Date      : 13/02/2014
 // Author    : alain greiner
 // Copyright (c) UPMC-LIP6
-///////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
 // The rdk_driver.c and rdk_driver.h files are part ot the GIET-VM kernel.
 //
@@ -10,58 +10,31 @@
 // in the physical address space. 
 //
-// The _rdk_read() and _rdk_write() blocking functions use a software memcpy,
-// whatever the selected mode. They return only when the transfer is completed.
-// As the number of concurrent accesses is not bounded, these functions
-// don't use the _ioc_lock variable.
+// The _rdk_access() function use a software memcpy to implement both the read
+// and write accesses, whatever the selected IRQ mode. It returns only when 
+// the transfer is completed. The memory buffer address is a virtual address.
+//
+// As the number of concurrent accesses is not bounded, it does not use any lock.
 //
 // The SEG_RDK_BASE virtual address must be defined in the hard_config.h
 // file when the USE_RAMDISK flag is set.
-///////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
 
 #ifndef _GIET_RDK_DRIVERS_H_
 #define _GIET_RDK_DRIVERS_H_
 
-///////////////////////////////////////////////////////////////////////////////////
-// BDV access functions and variables (vci_block_device)
-///////////////////////////////////////////////////////////////////////////////////
-
 ///////////////////////////////////////////////////////////////////////////////
-// This function does nothing, but is required by the IOC API.
-///////////////////////////////////////////////////////////////////////////////
-extern unsigned int _rdk_init();
-
-///////////////////////////////////////////////////////////////////////////////
-// Transfer data from a memory buffer to the RAMDISK. 
-// - mode     : BOOT / KERNEL / USER (unused)
-// - lba      : first block index on the block device
-// - buffer   : virtual base address of the memory buffer
-// - count    : number of blocks to be transfered.
+// Transfer data between a memory buffer and the RAMDISK. 
+// - use_irq   : not used: accees is always synchronous.
+// - to_mem    : to memory buffer when non zero
+// - lba       : first block index on the block device
+// - buf_vaddr : virtual base address of the memory buffer
+// - count     : number of blocks to be transfered.
 // Returns 0 if success, > 0 if error.
 ///////////////////////////////////////////////////////////////////////////////
-extern unsigned int _rdk_write( unsigned int lba, 
-                                unsigned int buffer, 
-                                unsigned int count );
-
-///////////////////////////////////////////////////////////////////////////////
-// Transfer data from the RAMDISK to a memory buffer. 
-// - mode     : BOOT / KERNEL / USER (unused)
-// - lba      : first block index on the block device
-// - buffer   : virtual base address of the memory buffer
-// - count    : number of blocks to be transfered.
-// Returns 0 if success, > 0 if error.
-///////////////////////////////////////////////////////////////////////////////
-extern unsigned int _rdk_read(  unsigned int lba, 
-                                unsigned int buffer,
-                                unsigned int count );
-
-///////////////////////////////////////////////////////////////////////////////
-// This function returns the block size.
-///////////////////////////////////////////////////////////////////////////////
-extern unsigned int _rdk_get_block_size();
-
-///////////////////////////////////////////////////////////////////////////////////
-// This function returns always 0, but is required by the IOC API.
-///////////////////////////////////////////////////////////////////////////////
-extern unsigned int _rdk_get_status();
+extern unsigned int _rdk_access( unsigned int use_irq,
+                                 unsigned int to_mem,
+                                 unsigned int lba, 
+                                 unsigned long long buf_vaddr,
+                                 unsigned int count );
 
 #endif
Index: /soft/giet_vm/giet_drivers/sdc_driver.c
===================================================================
--- /soft/giet_vm/giet_drivers/sdc_driver.c	(revision 528)
+++ /soft/giet_vm/giet_drivers/sdc_driver.c	(revision 529)
@@ -372,5 +372,5 @@
     if (sdcard_rsp)
     {
-        _puts("[SDC ERROR] During SD card blocklen initialization\n");
+        _puts("[SDC ERROR] During SD card block size initialization\n");
         _exit();
     }
@@ -389,12 +389,13 @@
 
     return 0;
-}
-
-
-//////////////////////////////////////////
-unsigned int _sdc_read( unsigned int mode,
-                        unsigned int lba,
-                        paddr_t      buffer,
-                        unsigned int count )
+} // end _sdc_init()
+
+
+/////////////////////////////////////////////////////
+unsigned int _sdc_access( unsigned int       use_irq,  // unused
+                          unsigned int       to_mem,
+                          unsigned int       lba,
+                          unsigned long long buf_paddr,
+                          unsigned int       count )
 {
     unsigned char args[4];
@@ -404,69 +405,49 @@
     unsigned int last = lba + count;
 
-    for ( ; curr < last ; curr++ )
-    {
-        _sdc_lseek(curr);
-
-        for (i = 0; i < 4; i++)
-        {
-            args[i] = (sdcard.access_pointer >> (32 - (i+1)*8)) & 0xFF;
+    if ( to_mem )  // read access
+    {
+        for ( ; curr < last ; curr++ )
+        {
+            _sdc_lseek(curr);
+
+            for (i = 0; i < 4; i++)
+            {
+                args[i] = (sdcard.access_pointer >> (32 - (i+1)*8)) & 0xFF;
+            }
+
+            _sdc_enable();
+
+            sdcard_rsp = _sdc_send_command(17, SDCARD_CMD, args, 0x00);
+            if ( SDCARD_CHECK_R1_ERROR(sdcard_rsp) )
+            {
+                _sdc_disable();
+                return sdcard_rsp;
+            }
+
+            _sdc_wait_data_block();
+
+            if (spi_get_data(sdcard.spi, buf_paddr, 512 ))
+            {
+                _sdc_disable();
+                return 1;
+            }
+
+            // Get the CRC16 (comes at the end of the data block)
+            _sdc_receive_char(); // first byte
+            _sdc_receive_char(); // second byte
+
+            _sdc_disable();
+
+            buf_paddr += 512;
         }
-
-        _sdc_enable();
-
-        sdcard_rsp = _sdc_send_command(17, SDCARD_CMD, args, 0x00);
-        if ( SDCARD_CHECK_R1_ERROR(sdcard_rsp) )
-        {
-            _sdc_disable();
-            return sdcard_rsp;
-        }
-
-        _sdc_wait_data_block();
-
-        if (spi_get_data(sdcard.spi, buffer, 512 ))
-        {
-            _sdc_disable();
-            return 1;
-        }
-
-        // Get the CRC16 (comes at the end of the data block)
-        _sdc_receive_char(); // first byte
-        _sdc_receive_char(); // second byte
-
-        _sdc_disable();
-
-        buffer += 512;
+    }
+    else            // write access
+    {
+        _printf("[SDC ERROR] function _sdc_write() not iplemented yet\n");
+        _exit();
     }
 
     return 0;
-}
-
-///////////////////////////////////////////
-unsigned int _sdc_write( unsigned int mode,
-                         unsigned int lba,
-                         paddr_t      buffer,
-                         unsigned int count )
-{
-    _puts("[SDC ERROR] function _sdc_write() not iplemented yet\n");
-    _exit();
-
-    return 0;  // to avoid a warning
-}
-
-//////////////////////////////
-unsigned int _sdc_get_status()
-{
-    _puts("[SDC ERROR] function _sdc_get_status() should not be called\n");
-    _exit();
-
-    return 0;  // to avoid a warning
-}
-
-//////////////////////////////////
-unsigned int _sdc_get_block_size()
-{
-    if (sdcard.sdhc) return sdcard.block_length*512;
-    else             return sdcard.block_length;
-}
+}  // _end sdc_access()
 
 // Local Variables:
Index: /soft/giet_vm/giet_drivers/sdc_driver.h
===================================================================
--- /soft/giet_vm/giet_drivers/sdc_driver.h	(revision 528)
+++ /soft/giet_vm/giet_drivers/sdc_driver.h	(revision 529)
@@ -46,41 +46,17 @@
 
 ///////////////////////////////////////////////////////////////////////////////
-// Transfer data from the block device to a memory buffer. 
-// - mode     : BOOT / KERNEL / USER
-// - lba      : first block index on the block device
-// - buffer   : base address of the memory buffer (must be word aligned)
-// - count    : number of blocks to be transfered.
+// Transfer data between the block device and a memory buffer. 
+// - use_irq   : not used, as DMA is not supported yet
+// - to_mem    : to memory if non zero
+// - lba       : first block index on the block device
+// - buf_vaddr : base address of the memory buffer
+// - count     : number of blocks to be transfered.
 // Returns 0 if success, > 0 if error.
 ///////////////////////////////////////////////////////////////////////////////
-unsigned int _sdc_read( unsigned int mode,
-                        unsigned int lba,
-                        paddr_t      buffer,
-                        unsigned int count);
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Transfer data from memory buffer to SD card device. 
-// - mode     : BOOT / KERNEL / USER
-// - lba      : destination first block index on the SD card
-// - buffer   : base address of the memory buffer (must be word aligned)
-// - count    : number of blocks to be transfered.
-// Returns 0 if success, > 0 if error.
-// WARNING: The _sdc_write() is not implemented yet.
-///////////////////////////////////////////////////////////////////////////////
-unsigned int _sdc_write( unsigned int mode,
-                         unsigned int lba,
-                         paddr_t      buffer,
-                         unsigned int count);
-
-///////////////////////////////////////////////////////////////////////////////
-// This function should not be called for the SDC card.
-///////////////////////////////////////////////////////////////////////////////
-unsigned int _sdc_get_status();
-
-///////////////////////////////////////////////////////////////////////////////
-// Returns the block size in bytes of the SD card.
-///////////////////////////////////////////////////////////////////////////////
-unsigned int _sdc_get_block_size();
-
+unsigned int _sdc_access( unsigned int       use_irq,  
+                          unsigned int       to_mem,
+                          unsigned int       lba,
+                          unsigned long long buf_vaddr,
+                          unsigned int       count);
 
 ///////////////////////////////////////////////////////////////////////////////
Index: /soft/giet_vm/giet_drivers/tim_driver.c
===================================================================
--- /soft/giet_vm/giet_drivers/tim_driver.c	(revision 528)
+++ /soft/giet_vm/giet_drivers/tim_driver.c	(revision 529)
@@ -1,8 +1,8 @@
-//////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
 // File     : tim_driver.c
 // Date     : 23/05/2013
 // Author   : alain greiner
 // Copyright (c) UPMC-LIP6
-//////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
 
 #include <giet_config.h>
@@ -48,7 +48,7 @@
 #endif
 
-/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
 //                      global variables
-/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
 
 #define in_unckdata __attribute__((section (".unckdata")))
@@ -59,9 +59,9 @@
 #endif
 
-/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
 //                      access functions
-/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
 
-//////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////
 unsigned int _timer_get_register( unsigned int channel,
                                   unsigned int index )
Index: /soft/giet_vm/giet_drivers/xcu_driver.c
===================================================================
--- /soft/giet_vm/giet_drivers/xcu_driver.c	(revision 528)
+++ /soft/giet_vm/giet_drivers/xcu_driver.c	(revision 529)
@@ -87,5 +87,4 @@
                     unsigned int irq_type ) 
 {
-#if USE_XCU
     // parameters checking 
     unsigned int x = cluster_xy >> Y_WIDTH;
@@ -106,9 +105,4 @@
 
     _xcu_set_register(cluster_xy, func, channel, value);
-
-#else
-    _printf("[GIET ERROR] _xcu_set_mask() should not be used if USE_XCU not set\n");
-    _exit();
-#endif
 }
 
@@ -119,5 +113,4 @@
                      unsigned int * irq_type )
 {
-#if USE_XCU
     // parameters checking 
     unsigned int x = cluster_xy >> Y_WIDTH;
@@ -153,9 +146,4 @@
         *index = 32;
     }
- 
-#else
-    _printf("[GIET ERROR] _xcu_get_index should not be used if USE_XCU is not set\n");
-    _exit();
-#endif
 }
 
@@ -165,5 +153,4 @@
                     unsigned int wdata )
 { 
-#if USE_XCU
     // parameters checking 
     unsigned int x = cluster_xy >> Y_WIDTH;
@@ -174,9 +161,4 @@
 
     _xcu_set_register(cluster_xy, XCU_WTI_REG, wti_index, wdata);
-
-#else
-    _printf("[GIET ERROR] _xcu_send_wti() should not be used if USE_XCU is not set\n");
-    _exit();
-#endif
 } 
 
@@ -186,5 +168,4 @@
                           unsigned int wdata )
 { 
-#if USE_XCU
     // parameters checking 
     unsigned int x = cluster_xy >> Y_WIDTH;
@@ -199,10 +180,6 @@
 
     _physical_write(paddr, wdata);
-
-#else
-    _puts("[GIET ERROR] _xcu_send_wti() should not be used if USE_XCU is not set\n");
-    _exit();
-#endif
-}
+}
+
 ///////////////////////////////////////////////////
 void _xcu_get_wti_value( unsigned int   cluster_xy,
@@ -210,5 +187,4 @@
                          unsigned int * value )
 {
-#if USE_XCU
     // parameters checking 
     unsigned int x = cluster_xy >> Y_WIDTH;
@@ -219,9 +195,4 @@
  
     *value = _xcu_get_register(cluster_xy, XCU_WTI_REG, wti_index);
-
-#else
-    _printf("[GIET ERROR] in _xcu_get_wti_value() USE_XCU is not set\n");
-    _exit();
-#endif
 }
 
@@ -230,13 +201,7 @@
                            unsigned int * address )
 {
-#if USE_XCU
-    if (wti_index >= 32)           _exit(); 
+    if (wti_index >= 32)  _exit(); 
  
     *address = SEG_XCU_BASE + (XCU_REG(XCU_WTI_REG, wti_index)<<2); 
-
-#else
-    _printf("[GIET ERROR] in _xcu_get_wti_address() USE_XCU is not set\n");
-    _exit();
-#endif
 }
 
@@ -246,5 +211,4 @@
                        unsigned int period )
 {
-#if USE_XCU
     // parameters checking 
     unsigned int x = cluster_xy >> Y_WIDTH;
@@ -254,9 +218,4 @@
 
     _xcu_set_register(cluster_xy, XCU_PTI_PER, pti_index, period);
-
-#else
-    _printf("[GIET ERROR] in _xcu_timer_start() USE_XCU is not set\n");
-    _exit();
-#endif
 }
 
@@ -265,5 +224,4 @@
                       unsigned int pti_index) 
 {
-#if USE_XCU
     // parameters checking 
     unsigned int x = cluster_xy >> Y_WIDTH;
@@ -273,16 +231,10 @@
 
     _xcu_set_register(cluster_xy, XCU_PTI_PER, pti_index, 0);
-
-#else
-    _printf("[GIET ERROR] in _xcu_timer_stop() USE_XCU is not set\n");
-    _exit();
-#endif
 }
 
 ///////////////////////////////////////////////////////////
-unsigned int _xcu_timer_reset_irq( unsigned int cluster_xy, 
-                                   unsigned int pti_index ) 
-{
-#if USE_XCU
+void _xcu_timer_reset_irq( unsigned int cluster_xy, 
+                           unsigned int pti_index ) 
+{
     // parameters checking 
     unsigned int x = cluster_xy >> Y_WIDTH;
@@ -292,11 +244,5 @@
 
     // This return value is not used / avoid a compilation warning.
-    return _xcu_get_register(cluster_xy, XCU_PTI_ACK, pti_index);
-
-#else
-    _puts("[GIET ERROR] in _xcu_timer_reset_irq() USE_XCU is not set\n");
-    _exit();
-    return 0;
-#endif
+    x = _xcu_get_register(cluster_xy, XCU_PTI_ACK, pti_index);
 }
 
@@ -305,5 +251,4 @@
                            unsigned int pti_index ) 
 {
-#if USE_XCU
     // parameters checking 
     unsigned int x = cluster_xy >> Y_WIDTH;
@@ -318,9 +263,4 @@
     _xcu_set_register(cluster_xy, XCU_PTI_PER, pti_index, 0);
     _xcu_set_register(cluster_xy, XCU_PTI_PER, pti_index, per);
-
-#else
-    _puts("[GIET ERROR] in _xcu_timer_reset_cpt() USE_XCU is not set\n");
-    _exit();
-#endif
 }
 
Index: /soft/giet_vm/giet_drivers/xcu_driver.h
===================================================================
--- /soft/giet_vm/giet_drivers/xcu_driver.h	(revision 528)
+++ /soft/giet_vm/giet_drivers/xcu_driver.h	(revision 529)
@@ -139,6 +139,6 @@
 // or by the _isr_timer() for an "user" timer.
 //////////////////////////////////////////////////////////////////////////////
-extern unsigned int _xcu_timer_reset_irq( unsigned int cluster_xy, 
-                                          unsigned int pti_index );
+extern void _xcu_timer_reset_irq( unsigned int cluster_xy, 
+                                  unsigned int pti_index );
 
 //////////////////////////////////////////////////////////////////////////////
