Index: soft/giet_vm/sys/drivers.c
===================================================================
--- soft/giet_vm/sys/drivers.c	(revision 203)
+++ soft/giet_vm/sys/drivers.c	(revision 204)
@@ -17,4 +17,6 @@
 //
 // The following global parameters must be defined in the giet_config.h file:
+// - CLUSTER_IO_ID
+// - CLUSTER_SIZE
 // - NB_CLUSTERS   
 // - NB_PROCS_MAX  
@@ -23,5 +25,5 @@
 // - NB_TTYS    
 //
-// The following virtual base addresses must be defined in the sys.ld file:
+// The following virtual base addresses must be defined in the giet.ld file:
 // - seg_icu_base
 // - seg_tim_base
@@ -31,4 +33,7 @@
 // - seg_fbf_base
 // - seg_ioc_base
+// As some peripherals can be replicated in the clusters (ICU, TIMER, DMA)
+// These addresses must be completed by an offset depending on the cluster index
+//    full_base_address = seg_***_base + cluster_id * CLUSTER_SIZE
 ///////////////////////////////////////////////////////////////////////////////////
 
@@ -54,6 +59,6 @@
 #endif
 
-#if !defined(CLUSTER_SPAN) 
-# error: You must define CLUSTER_SPAN in 'giet_config.h' file
+#if !defined(CLUSTER_SIZE) 
+# error: You must define CLUSTER_SIZE in 'giet_config.h' file
 #endif
 
@@ -132,11 +137,11 @@
 
 #if GIET_USE_XICU
-    unsigned int* timer_address = (unsigned int*)&seg_icu_base +
-                                  (cluster_id * CLUSTER_SPAN);
+    unsigned int* timer_address = (unsigned int*)((char*)&seg_icu_base +
+                                  (cluster_id * CLUSTER_SIZE) );
 
     timer_address[XICU_REG(XICU_PTI_PER, local_id)] = period;
 #else
-    unsigned int* timer_address = (unsigned int*)&seg_tim_base + 
-                                  (cluster_id * CLUSTER_SPAN);
+    unsigned int* timer_address = (unsigned int*)((char*)&seg_tim_base + 
+                                  (cluster_id * CLUSTER_SIZE) );
 
     timer_address[local_id * TIMER_SPAN + TIMER_PERIOD] = period;
@@ -160,11 +165,11 @@
 
 #if GIET_USE_XICU
-    unsigned int* timer_address = (unsigned int*)&seg_icu_base +
-                                  (cluster_id * CLUSTER_SPAN);
+    unsigned int* timer_address = (unsigned int*)((char*)&seg_icu_base +
+                                  (cluster_id * CLUSTER_SIZE) );
 
     timer_address[XICU_REG(XICU_PTI_PER, local_id)] = 0;
 #else
-    unsigned int* timer_address = (unsigned int*)&seg_tim_base + 
-                                  (cluster_id * CLUSTER_SPAN);
+    unsigned int* timer_address = (unsigned int*)((char*)&seg_tim_base + 
+                                  (cluster_id * CLUSTER_SIZE) );
 
     timer_address[local_id * TIMER_SPAN + TIMER_MODE] = 0;
@@ -176,5 +181,5 @@
 //     _timer_reset_irq()
 // This function acknowlegge a timer interrupt in the vci_timer (or vci_xicu) 
-// component by writing in the proper register the period value.
+// component by reading/writing in the proper register.
 // It can be used by both the isr_switch() for a "system" timer, 
 // or by the _isr_timer() for an "user" timer.
@@ -189,11 +194,12 @@
 
 #if GIET_USE_XICU
-    unsigned int* timer_address = (unsigned int*)&seg_icu_base +
-                                  (cluster_id * CLUSTER_SPAN);
+    unsigned int* timer_address = (unsigned int*)((char*)&seg_icu_base +
+                                  (cluster_id * (unsigned)CLUSTER_SIZE) );
 
     unsigned int bloup = timer_address[XICU_REG(XICU_PTI_ACK, local_id)];
+    bloup++;	// to avoid a warning 
 #else
-    unsigned int* timer_address = (unsigned int*)&seg_tim_base + 
-                                  (cluster_id * CLUSTER_SPAN);
+    unsigned int* timer_address = (unsigned int*)((char*)&seg_tim_base + 
+                                  (cluster_id * CLUSTER_SIZE) );
 
     timer_address[local_id * TIMER_SPAN + TIMER_RESETIRQ] = 0;
@@ -258,28 +264,31 @@
     }
 
-    unsigned int*	tty_address = (unsigned int*)&seg_tty_base + tty_id*TTY_SPAN;
+    unsigned int*	tty_address = (unsigned int*)( (char*)&seg_tty_base + 
+                                  (CLUSTER_IO_ID * (unsigned)CLUSTER_SIZE) ); 
 
     for (nwritten = 0; nwritten < length; nwritten++)
     {
         // check tty's status 
-        if ((tty_address[TTY_STATUS] & 0x2) == 0x2)
+        if ((tty_address[tty_id*TTY_SPAN + TTY_STATUS] & 0x2) == 0x2)
             break;
         else
             // write character 
-            tty_address[TTY_WRITE] = (unsigned int)buffer[nwritten];
+            tty_address[tty_id*TTY_SPAN + TTY_WRITE] = (unsigned int)buffer[nwritten];
     }
     return nwritten;
 }
 //////////////////////////////////////////////////////////////////////////////
-//      _tty_read_irq()
+//      _tty_read()
 // This non-blocking function uses the TTY_GET_IRQ[tty_id] interrupt and 
 // the associated kernel buffer, that has been written by the ISR.
+// It get the TTY terminal index from the context of the current task.
 // It fetches one single character from the _tty_get_buf[tty_id] kernel
 // buffer, writes this character to the user buffer, and resets the
 // _tty_get_full[tty_id] buffer.
+// The length argument is not used.
 // Returns 0 if the kernel buffer is empty, 1 if the buffer is full.
 //////////////////////////////////////////////////////////////////////////////
-unsigned int _tty_read_irq( char			*buffer, 
-                            unsigned int	length)
+unsigned int _tty_read( char			*buffer, 
+                        unsigned int	length)
 {
     unsigned int task_id  = _get_current_task_id();
@@ -304,33 +313,22 @@
 } 
 ////////////////////////////////////////////////////////////////////////////////
-//     _tty_read()
-// This non-blocking function fetches one character directly from the TTY_READ 
-// register of the TTY controler, and writes this character to the user buffer.
-// It doesn't use the TTY_GET_IRQ interrupt and the associated kernel buffer.
-// Returns 0 if the register is empty, 1 if the register is full.
-////////////////////////////////////////////////////////////////////////////////
-unsigned int _tty_read( char			*buffer, 
-                        unsigned int	length)
-{
-    unsigned int task_id  = _get_current_task_id();
-    unsigned int tty_id   = _get_context_slot(task_id, CTX_TTY_ID);
-
-    if ( tty_id >= NB_TTYS )
-    {
-        _tty_error( task_id );
-        return 0;
-    }
-
-    unsigned int*	tty_address = (unsigned int*)&seg_tty_base + tty_id*TTY_SPAN;
-
-    if ((tty_address[TTY_STATUS] & 0x1) != 0x1) 
-    {
-        return 0;
-    }
-    else
-    {
-        *buffer = (char)tty_address[TTY_READ];
-        return 1;
-    }
+//     _tty_get_char()
+// This function is used by the _isr_tty to read a character in the TTY
+// terminal defined by the tty_id argument. The character is stored
+// in requested buffer, and the IRQ is acknowledged.
+// Returns 0 if success, 1 if tty_id too large. 
+////////////////////////////////////////////////////////////////////////////////
+unsigned int _tty_get_char( unsigned int	tty_id,
+                            char*           buffer )
+{
+    // checking argument
+    if ( tty_id >= NB_TTYS ) return 1;
+
+    // compute terminal base address 
+    unsigned int *tty_address = (unsigned int*)( (char*)&seg_tty_base + 
+                                (CLUSTER_IO_ID * (unsigned)CLUSTER_SIZE) );
+
+    *buffer = (unsigned char)tty_address[tty_id*TTY_SPAN + TTY_READ];
+    return 0;
 }
 
@@ -359,6 +357,6 @@
     if ( proc_id    >= NB_PROCS_MAX )   return 1;
 
-    unsigned int* icu_address = (unsigned int*)&seg_icu_base + 
-                                (cluster_id * CLUSTER_SPAN);
+    unsigned int* icu_address = (unsigned int*)( (char*)&seg_icu_base + 
+                                (cluster_id * (unsigned)CLUSTER_SIZE) );
 #if GIET_USE_XICU
     if ( is_timer ) icu_address[XICU_REG(XICU_MSK_PTI_ENABLE, proc_id)] = value;
@@ -385,6 +383,6 @@
     if ( proc_id    >= NB_PROCS_MAX )   return 1;
 
-    unsigned int* icu_address = (unsigned int*)&seg_icu_base + 
-                                (cluster_id * CLUSTER_SPAN);
+    unsigned int* icu_address = (unsigned int*)( (char*)&seg_icu_base + 
+                                (cluster_id * (unsigned)CLUSTER_SIZE) );
 #if GIET_USE_XICU
     unsigned int prio   = icu_address[XICU_REG(XICU_PRIO, proc_id)];
@@ -422,11 +420,10 @@
                          unsigned int value)
 {
-    volatile unsigned int *gcd_address;
-
     // parameters checking
     if (register_index >= GCD_END)
         return 1;
 
-    gcd_address = (unsigned int*)&seg_gcd_base;
+    unsigned int* gcd_address = (unsigned int*)( (char*)&seg_gcd_base +
+                                (CLUSTER_IO_ID * (unsigned)CLUSTER_SIZE) );
 
     gcd_address[register_index] = value; // write word
@@ -441,11 +438,10 @@
                         unsigned int *buffer)
 {
-    volatile unsigned int *gcd_address;
-
     // parameters checking 
     if (register_index >= GCD_END)
         return 1;
 
-    gcd_address = (unsigned int*)&seg_gcd_base;
+    unsigned int* gcd_address = (unsigned int*)( (char*)&seg_gcd_base +
+                                (CLUSTER_IO_ID * (unsigned)CLUSTER_SIZE) );
 
     *buffer = gcd_address[register_index]; // read word
@@ -538,5 +534,7 @@
     if ( (unsigned int)user_vaddr & 0x3 ) return 1;
 
-    unsigned int*	ioc_address = (unsigned int*)&seg_ioc_base;
+    unsigned int*	ioc_address = (unsigned int*)( (char*)&seg_ioc_base +
+                                  (CLUSTER_IO_ID * (unsigned)CLUSTER_SIZE) );
+
     unsigned int	block_size   = ioc_address[BLOCK_DEVICE_BLOCK_SIZE];
     unsigned int	length       = count*block_size;
@@ -630,5 +628,6 @@
     if ( GIET_IOMMU_ACTIVE )
     {
-        unsigned int* iob_address = (unsigned int*)&seg_iob_base;
+        unsigned int* iob_address = (unsigned int*)( (char*)&seg_iob_base +
+                                    (CLUSTER_IO_ID * (unsigned)CLUSTER_SIZE) );
 
         for ( ix2 = 0 ; ix2 < _ioc_iommu_npages ; ix2++ )
@@ -687,4 +686,18 @@
                         (unsigned int)buffer,
                         count );
+}
+///////////////////////////////////////////////////////////////////////////////
+//     _ioc_get_status()
+// This function returns the transfert status, and acknowledge the IRQ.
+// Returns 0 if success, > 0 if error.
+///////////////////////////////////////////////////////////////////////////////
+unsigned int _ioc_get_status(unsigned int* status)
+{
+    // get IOC base address
+    unsigned int* ioc_address = (unsigned int*)( (char*)&seg_ioc_base +
+                                (CLUSTER_IO_ID * (unsigned)CLUSTER_SIZE) );
+
+    *status = ioc_address[BLOCK_DEVICE_STATUS]; // read status & reset IRQ 
+    return 0;
 }
 
@@ -718,4 +731,40 @@
 in_unckdata unsigned int            _dma_iommu_npages[NB_DMAS_MAX * NB_CLUSTERS];
 #endif
+
+//////////////////////////////////////////////////////////////////////////////////
+// _dma_reset_irq()
+//////////////////////////////////////////////////////////////////////////////////
+unsigned int _dma_reset_irq( unsigned int	cluster_id,
+                             unsigned int	local_id )
+{
+    // parameters checking 
+    if ( cluster_id >= NB_CLUSTERS ) return 1;
+    if ( local_id >= NB_DMAS_MAX )   return 1;
+
+    // compute DMA base address
+    unsigned int*	dma_address = (unsigned int*)( (char*)&seg_dma_base + 
+                                  (cluster_id * (unsigned)CLUSTER_SIZE) );
+
+    dma_address[local_id*DMA_SPAN + DMA_RESET] = 0;			
+    return 0;
+}
+//////////////////////////////////////////////////////////////////////////////////
+// _dma_get_status()
+//////////////////////////////////////////////////////////////////////////////////
+unsigned int _dma_get_status( unsigned int	cluster_id,
+                              unsigned int	local_id,
+                              unsigned int* status )
+{
+    // parameters checking 
+    if ( cluster_id >= NB_CLUSTERS ) return 1;
+    if ( local_id >= NB_DMAS_MAX )   return 1;
+
+    // compute DMA base address
+    unsigned int*	dma_address = (unsigned int*)( (char*)&seg_dma_base + 
+                                  (cluster_id * (unsigned)CLUSTER_SIZE) );
+    
+    *status = dma_address[local_id*DMA_SPAN + DMA_LEN];
+    return 0;
+}
 
 //////////////////////////////////////////////////////////////////////////////////
@@ -819,8 +868,8 @@
     unsigned int    cluster_id = dma_id / NB_DMAS_MAX;
     unsigned int    loc_id     = dma_id % NB_DMAS_MAX;
-    unsigned int*	dma_base   = (unsigned int*)&seg_dma_base +
-                                 (cluster_id * CLUSTER_SPAN) + 
-                                 (loc_id * DMA_SPAN);
-
+
+    unsigned int*	dma_base   = (unsigned int*)( (char*)&seg_dma_base +
+                                 (cluster_id * (unsigned)CLUSTER_SIZE) );
+ 
     // check user buffer address and length alignment
     if ( (user_vaddr & 0x3) || (length & 0x3) )
@@ -930,4 +979,5 @@
 
 */
+
     // invalidate data cache in case of memory write
     if ( to_user ) _dcache_buf_invalidate( (void*)user_vaddr, length );
@@ -939,13 +989,13 @@
     if ( to_user )
     {
-        dma_base[DMA_SRC] = (unsigned int)fb_pbase;
-        dma_base[DMA_DST] = (unsigned int)user_pbase;
+        dma_base[loc_id*DMA_SPAN + DMA_SRC] = (unsigned int)fb_pbase;
+        dma_base[loc_id*DMA_SPAN + DMA_DST] = (unsigned int)user_pbase;
     }
     else
     {
-        dma_base[DMA_SRC] = (unsigned int)user_pbase;
-        dma_base[DMA_DST] = (unsigned int)fb_pbase;
-    }
-    dma_base[DMA_LEN] = (unsigned int)length;
+        dma_base[loc_id*DMA_SPAN + DMA_SRC] = (unsigned int)user_pbase;
+        dma_base[loc_id*DMA_SPAN + DMA_DST] = (unsigned int)fb_pbase;
+    }
+    dma_base[loc_id*DMA_SPAN + DMA_LEN] = (unsigned int)length;
     
     return 0;
@@ -1011,5 +1061,7 @@
     if ( GIET_IOMMU_ACTIVE )
     {
-        unsigned int* iob_address = (unsigned int*)&seg_iob_base;
+        unsigned int* iob_address = (unsigned int*)( (char*)&seg_iob_base +
+                                    (CLUSTER_IO_ID * (unsigned)CLUSTER_SIZE) );
+
         unsigned int  ix1         = _dma_iommu_ix1 + dma_id;
         unsigned int  ix2;
