Index: soft/giet_vm/sys/drivers.c
===================================================================
--- soft/giet_vm/sys/drivers.c	(revision 246)
+++ soft/giet_vm/sys/drivers.c	(revision 249)
@@ -41,4 +41,5 @@
 // - seg_cma_base
 // - seg_iob_base
+// - seg_mmc_base
 //
 ///////////////////////////////////////////////////////////////////////////////////
@@ -57,4 +58,8 @@
 #endif
 
+#if (NB_CLUSTERS > 256)
+# error: NB_CLUSTERS cannot be larger than 256!
+#endif
+
 #if !defined(NB_PROCS_MAX) 
 # error: You must define NB_PROCS_MAX in the hard_config.h file
@@ -69,4 +74,8 @@
 #endif
 
+#if !defined(GIET_USE_IOMMU) 
+# error: You must define GIET_USE_IOMMU in the giet_config.h file
+#endif
+
 #if !defined(NB_TTY_CHANNELS)
 # error: You must define NB_TTY_CHANNELS in the hard_config.h file
@@ -121,6 +130,6 @@
 #endif
 
-#if !defined( IOMMU_ACTIVE )
-# error: You must define IOMMU_ACTIVE in the hard_config.h file
+#if !defined( USE_IOB )
+# error: You must define USE_IOB in the hard_config.h file
 #endif
 
@@ -314,10 +323,6 @@
 
     _get_lock(&_tty_put_lock);
-    if (tty_id == 0xFFFFFFFF) {
-        _puts("\n[GIET ERROR] no TTY assigned to the task ");
-    }
-    else {
-        _puts("\n[GIET ERROR] TTY index too large for task ");
-    }
+    if (tty_id == 0xFFFFFFFF) _puts("\n[GIET ERROR] no TTY assigned to the task ");
+    else                      _puts("\n[GIET ERROR] TTY index too large for task ");
     _putd(task_id);
     _puts(" on processor ");
@@ -671,5 +676,5 @@
         if (ix2 == 0) ppn_first = ppn;
 
-        if (IOMMU_ACTIVE) // the user buffer must be remapped in the I/0 space
+        if ( GIET_USE_IOMMU && USE_IOB ) // user buffer remapped in the I/0 space
         {
             // check buffer length < 2 Mbytes
@@ -710,5 +715,5 @@
     _ioc_iommu_npages = (user_vpn_max - user_vpn_min) + 1;
 
-    // invalidate data cache in case of memory write
+    // invalidate local data cache in case of memory write
     if (to_mem) _dcache_buf_invalidate((void *) user_vaddr, length);
 
@@ -737,9 +742,12 @@
 #endif
 
+    // Invalidate L2 cache if IO Bridge is used
+    if ( to_mem && USE_IOB ) _memc_inval( buf_paddr, length );
+    
     // get the lock on ioc device 
     _get_lock(&_ioc_lock);
 
     // peripheral configuration  
-    if ( IOMMU_ACTIVE ) 
+    if ( GIET_USE_IOMMU && USE_IOB ) 
     {
         ioc_address[BLOCK_DEVICE_BUFFER] = buf_xaddr;
@@ -791,5 +799,5 @@
 
     // unmap the buffer from IOMMU page table if IOMMU is activated
-    if (IOMMU_ACTIVE) 
+    if ( GIET_USE_IOMMU && USE_IOB ) 
     {
         unsigned int * iob_address = (unsigned int *) &seg_iob_base;
@@ -1107,5 +1115,5 @@
     if ( ix2 == 0 ) ppn_first = ppn;
 
-    if ( IOMMU_ACTIVE )    // the user buffer must be remapped in the I/0 space
+    if ( GIET_USE_IOMMU && USE_IOB )    // user buffer remapped in the I/0 space
     {
     // check buffer length < 2 Mbytes
@@ -1444,4 +1452,37 @@
 }
 
+//////////////////////////////////////////////////////////////////////////////////
+//     VciMemCache driver
+//////////////////////////////////////////////////////////////////////////////////
+// The VciMemCache device can be accessed through a configuration interface.
+// as a set of uncached, memory mapped registers.
+///////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////
+// _memc_inval()
+// This function invalidate all cache lines covering a memory buffer defined
+// by the physical base address, and the length.
+// The buffer address MSB are used to compute the cluster index.
+///////////////////////////////////////////////////////////////////////////////////
+void _memc_inval( paddr_t      buf_paddr,
+                  unsigned int buf_length )
+{
+    unsigned int cluster_id    = (unsigned int)((buf_paddr>>32)/(256/NB_CLUSTERS));
+
+    unsigned int * mmc_address = (unsigned int *) ((char *) &seg_mmc_base + 
+                                                   (cluster_id * GIET_CLUSTER_INCREMENT));
+
+    // get the lock protecting exclusive access to MEMC
+    while ( mmc_address[MEMC_LOCK] ) { asm volatile("nop"); }
+
+    // write inval arguments
+    mmc_address[MEMC_ADDR_LO]    = (unsigned int)buf_paddr;
+    mmc_address[MEMC_ADDR_HI]    = (unsigned int)(buf_paddr>>32);
+    mmc_address[MEMC_BUF_LENGTH] = buf_length;
+    mmc_address[MEMC_CMD_TYPE]   = MEMC_CMD_INVAL;
+
+    // release the lock protecting MEMC
+    mmc_address[MEMC_LOCK] = 0;
+}
 ///////////////////////////////////////////////////////////////////////////////////
 // _heap_info()
