Index: soft/giet_vm/sys/drivers.c
===================================================================
--- soft/giet_vm/sys/drivers.c	(revision 199)
+++ soft/giet_vm/sys/drivers.c	(revision 203)
@@ -11,5 +11,5 @@
 // - vci_multi_dma
 // - vci_multi_icu
-// - vci_xicu
+// - vci_xicu & vci_multi_icu
 // - vci_gcd
 // - vci_frame_buffer
@@ -23,11 +23,11 @@
 // - NB_TTYS    
 //
-// The following base addresses must be defined in the sys.ld file:
+// The following virtual base addresses must be defined in the sys.ld file:
 // - seg_icu_base
-// - seg_timer_base
+// - seg_tim_base
 // - seg_tty_base
 // - seg_gcd_base
 // - seg_dma_base
-// - seg_fb_base
+// - seg_fbf_base
 // - seg_ioc_base
 ///////////////////////////////////////////////////////////////////////////////////
@@ -93,19 +93,17 @@
 #define in_unckdata __attribute__((section (".unckdata")))
 
-
 //////////////////////////////////////////////////////////////////////////////
-// 	VciMultiTimer driver
+// 	Timers driver
 //////////////////////////////////////////////////////////////////////////////
-// There is one multi_timer (or xicu) component per cluster.
-// The global index is cluster_id*(NB_PROCS_MAX+NB_TIMERS_MAX) + local_id
+// The timers can be implemented in a vci_timer component or in a vci_xicu 
+// component (depending on the GIET_USE_XICU parameter).
+// There is one timer (or xicu) component per cluster.
 // There is two types of timers: 
 // - "system" timers : one per processor, used for context switch.
 //   local_id in [0, NB_PROCS_MAX-1],
 // - "user" timers : requested by the task in the mapping_info data structure.
-//   local_id in [NB_PROC_MAX, NB_PROCS_MAX+NB_TIMERS_MAX-1],
-//   For each user timer, the tty_id is stored in the context of the task
-//   and must be explicitely defined in the boot code.
-// These timers can be implemented in a vci_multi_timer component 
-// or in a vci_xicu component (depending on the GIET_USE_XICU parameter).
+//   local_id in [NB_PROC_MAX, NB_PROCS_MAX + NB_TIMERS_MAX - 1]
+//   For each user timer, the timer_id is stored in the context of the task.
+// The global index is cluster_id * (NB_PROCS_MAX+NB_TIMERS_MAX) + local_id
 //////////////////////////////////////////////////////////////////////////////
 
@@ -118,99 +116,90 @@
 
 //////////////////////////////////////////////////////////////////////////////
-//     _timer_access()
-// This function is the only way to access a timer device.
-// It can be a multi-timer component or an xicu component.
-// It can be used by the kernel to initialise a "system" timer,
+//     _timer_start()
+// This function activates a timer in the vci_timer (or vci_xicu) component
+// by writing in the proper register the period value.
+// It can be used by both the kernel to initialise a "system" timer,
 // or by a task (through a system call) to configure an "user" timer.
 // Returns 0 if success, > 0 if error.
 //////////////////////////////////////////////////////////////////////////////
-unsigned int _timer_access( unsigned int	read,
-                            unsigned int	cluster_id,
-                            unsigned int	local_id,
-                            unsigned int	register_id, 
-                            unsigned int*	buffer )
+unsigned int _timer_start( unsigned int	cluster_id,
+                           unsigned int	local_id,
+                           unsigned int	period )
 {
     // parameters checking 
-    if ( register_id >= TIMER_SPAN)					return 1;
     if ( cluster_id >= NB_CLUSTERS)					return 1;
     if ( local_id >= NB_TIMERS_MAX + NB_PROCS_MAX ) return 1;
 
 #if GIET_USE_XICU
-
-    unsigned int* timer_address = //TODO
-
+    unsigned int* timer_address = (unsigned int*)&seg_icu_base +
+                                  (cluster_id * CLUSTER_SPAN);
+
+    timer_address[XICU_REG(XICU_PTI_PER, local_id)] = period;
 #else
-
-    unsigned int* timer_address = (unsigned int*)&seg_timer_base + 
-                                  (cluster_id * CLUSTER_SPAN)  +
-                                  (local_id * TIMER_SPAN);
-#endif
-
-    if (read)	*buffer = timer_address[register_id]; // read word 
-    else		timer_address[register_id] = *buffer; // write word
+    unsigned int* timer_address = (unsigned int*)&seg_tim_base + 
+                                  (cluster_id * CLUSTER_SPAN);
+
+    timer_address[local_id * TIMER_SPAN + TIMER_PERIOD] = period;
+    timer_address[local_id * TIMER_SPAN + TIMER_MODE]   = 0x3;
+#endif
+
     return 0;
 }
 //////////////////////////////////////////////////////////////////////////////
-//     _timer_write()
-// This function implements a write access to a "user" timer register.
-// It gets the cluster_id and local_id from the global index stored in
-// the task context and use the timer_access() function to make the write.
+//     _timer_stop()
+// This function desactivates a timer in the vci_timer (or vci_xicu) component
+// by writing in the proper register.
 // Returns 0 if success, > 0 if error.
 //////////////////////////////////////////////////////////////////////////////
-unsigned int _timer_write( unsigned int register_id, 
-                           unsigned int value )
-{
-    unsigned int buffer     = value;
-    unsigned int task_id    = _get_current_task_id();
-    unsigned int timer_id   = _get_context_slot(task_id, CTX_TIMER_ID);
-    unsigned int cluster_id = timer_id / (NB_PROCS_MAX + NB_TIMERS_MAX);
-    unsigned int local_id   = timer_id % (NB_PROCS_MAX + NB_TIMERS_MAX);
-
-    // checking user timer
-    if ( local_id < NB_PROCS_MAX ) 
-    {
-        return 2;
-    }
-    else
-    {
-        return _timer_access ( 0,				// write access
-                               cluster_id,
-                               local_id,
-                               register_id,
-                               &buffer );
-    }
+unsigned int _timer_stop( unsigned int	cluster_id,
+                          unsigned int	local_id )
+{
+    // parameters checking 
+    if ( cluster_id >= NB_CLUSTERS)					return 1;
+    if ( local_id >= NB_TIMERS_MAX + NB_PROCS_MAX ) return 1;
+
+#if GIET_USE_XICU
+    unsigned int* timer_address = (unsigned int*)&seg_icu_base +
+                                  (cluster_id * CLUSTER_SPAN);
+
+    timer_address[XICU_REG(XICU_PTI_PER, local_id)] = 0;
+#else
+    unsigned int* timer_address = (unsigned int*)&seg_tim_base + 
+                                  (cluster_id * CLUSTER_SPAN);
+
+    timer_address[local_id * TIMER_SPAN + TIMER_MODE] = 0;
+#endif
+
+    return 0;
 }
 //////////////////////////////////////////////////////////////////////////////
-//     _timer_read()
-// This function implements a read access to a "user" timer register.
-// It gets the cluster_id and local_id from the global index stored in
-// the task context and use the timer_access() function to make the read.
+//     _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.
+// It can be used by both the isr_switch() for a "system" timer, 
+// or by the _isr_timer() for an "user" timer.
 // Returns 0 if success, > 0 if error.
 //////////////////////////////////////////////////////////////////////////////
-unsigned int _timer_read( unsigned int  register_id, 
-                          unsigned int* buffer )
-{
-    unsigned int task_id    = _get_current_task_id();
-    unsigned int timer_id   = _get_context_slot(task_id, CTX_TIMER_ID);
-    unsigned int cluster_id = timer_id / (NB_PROCS_MAX + NB_TIMERS_MAX);
-    unsigned int local_id   = timer_id % (NB_PROCS_MAX + NB_TIMERS_MAX);
-
-    // checking user timer
-    if ( local_id < NB_PROCS_MAX ) 
-    {
-        return 2;
-    }
-    else
-    {
-        return _timer_access ( 1,				// read access
-                               cluster_id,
-                               local_id,
-                               register_id,
-                               buffer );
-    }
-}
-/////////////////////////////////////////////////////////////////////////////////
-//     _timer_check()
-/////////////////////////////////////////////////////////////////////////////////
+unsigned int _timer_reset_irq( unsigned int	cluster_id,
+                               unsigned int	local_id )
+{
+    // parameters checking 
+    if ( cluster_id >= NB_CLUSTERS)					return 1;
+    if ( local_id >= NB_TIMERS_MAX + NB_PROCS_MAX ) return 1;
+
+#if GIET_USE_XICU
+    unsigned int* timer_address = (unsigned int*)&seg_icu_base +
+                                  (cluster_id * CLUSTER_SPAN);
+
+    unsigned int bloup = timer_address[XICU_REG(XICU_PTI_ACK, local_id)];
+#else
+    unsigned int* timer_address = (unsigned int*)&seg_tim_base + 
+                                  (cluster_id * CLUSTER_SPAN);
+
+    timer_address[local_id * TIMER_SPAN + TIMER_RESETIRQ] = 0;
+#endif
+
+    return 0;
+}
 
 /////////////////////////////////////////////////////////////////////////////////
@@ -349,66 +338,70 @@
 // 	VciMultiIcu and VciXicu drivers
 ////////////////////////////////////////////////////////////////////////////////
-// There is in principle one vci_multi_icu (or vci_xicu) component per cluster, 
-// and the number of independant ICUs is equal to NB_PROCS_MAX, because there is 
-// one private interrupr controler per processor.
-////////////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////////////
-//     _icu_write()
-// Write a 32-bit word in a memory mapped register of the MULTI_ICU device,
-// identified by the cluster index, and a processor local index.
-// Returns 0 if success, > 0 if error.
-////////////////////////////////////////////////////////////////////////////////
-unsigned int _icu_write( unsigned int cluster_index,
-                         unsigned int proc_index,
-                         unsigned int register_index, 
-                         unsigned int value )
-{
+// There is one vci_multi_icu (or vci_xicu) component per cluster, 
+// and the number of independant ICUs is equal to NB_PROCS_MAX, 
+// because there is one private interrupr controler per processor.
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+//     _icu_set_mask()
+// This function can be used with both the vci_xicu & vci_multi_icu components.
+// It set the mask register for the ICU channel identified by the cluster index 
+// and the processor index: all '1' bits are set / all '0' bits are not modified.
+// Returns 0 if success, > 0 if error.
+////////////////////////////////////////////////////////////////////////////////
+unsigned int _icu_set_mask( unsigned int cluster_id,
+                            unsigned int proc_id,
+                            unsigned int value,
+                            unsigned int is_timer )
+{
+    // parameters checking 
+    if ( cluster_id >= NB_CLUSTERS)		return 1;
+    if ( proc_id    >= NB_PROCS_MAX )   return 1;
+
+    unsigned int* icu_address = (unsigned int*)&seg_icu_base + 
+                                (cluster_id * CLUSTER_SPAN);
 #if GIET_USE_XICU
-
+    if ( is_timer ) icu_address[XICU_REG(XICU_MSK_PTI_ENABLE, proc_id)] = value;
+    else            icu_address[XICU_REG(XICU_MSK_HWI_ENABLE, proc_id)] = value;
 #else
-
+    icu_address[proc_id * ICU_SPAN + ICU_MASK_SET] = value; 
+#endif
+
+    return 0;
+}
+////////////////////////////////////////////////////////////////////////////////
+//     _icu_get_index()
+// This function can be used with both the vci_xicu & vci_multi_icu components.
+// It returns the index of the highest priority (smaller index) active HWI.
+// The ICU channel is identified by the cluster index and the processor index.
+// Returns 0 if success, > 0 if error.
+////////////////////////////////////////////////////////////////////////////////
+unsigned int _icu_get_index(  unsigned int cluster_id,
+                              unsigned int proc_id,
+                              unsigned int* buffer )
+{
     // parameters checking 
-    if ( register_index >= ICU_SPAN) 		return 1;
-    if ( cluster_index >= NB_CLUSTERS)		return 1;
-    if ( proc_index >= NB_PROCS_MAX )       return 1;
-
-    unsigned int *icu_address = (unsigned int*)&seg_icu_base + 
-                                (cluster_index * CLUSTER_SPAN)  +
-                                (proc_index * ICU_SPAN);
-
-    icu_address[register_index] = value;   // write word 
+    if ( cluster_id >= NB_CLUSTERS)		return 1;
+    if ( proc_id    >= NB_PROCS_MAX )   return 1;
+
+    unsigned int* icu_address = (unsigned int*)&seg_icu_base + 
+                                (cluster_id * CLUSTER_SPAN);
+#if GIET_USE_XICU
+    unsigned int prio   = icu_address[XICU_REG(XICU_PRIO, proc_id)];
+    unsigned int pti_ok = (prio & 0x00000001);
+    unsigned int hwi_ok = (prio & 0x00000002);
+    unsigned int swi_ok = (prio & 0x00000004);
+    unsigned int pti_id = (prio & 0x00001F00) >> 8;
+    unsigned int hwi_id = (prio & 0x001F0000) >> 16;
+    unsigned int swi_id = (prio & 0x1F000000) >> 24;
+    if      (pti_ok)	*buffer = pti_id;
+    else if (hwi_ok)	*buffer = hwi_id;
+    else if (swi_ok)	*buffer = swi_id;
+    else                *buffer = 32;
+#else
+    *buffer = icu_address[proc_id * ICU_SPAN + ICU_IT_VECTOR]; 
+#endif
+
     return 0;
-
-#endif
-}
-////////////////////////////////////////////////////////////////////////////////
-//     _icu_read()
-// Read a 32-bit word in a memory mapped register of the MULTI_ICU device,
-// identified by the cluster index and a processor local index.
-// Returns 0 if success, > 0 if error.
-////////////////////////////////////////////////////////////////////////////////
-unsigned int _icu_read(  unsigned int cluster_index,
-                         unsigned int proc_index,
-                         unsigned int register_index, 
-                         unsigned int* buffer )
-{
-#if GIET_USE_XICU
-
-#else
-
-    // parameters checking 
-    if ( register_index >= ICU_SPAN) 		return 1;
-    if ( cluster_index >= NB_CLUSTERS)		return 1;
-    if ( proc_index >= NB_PROCS_MAX )       return 1;
-
-    unsigned int *icu_address = (unsigned int*)&seg_icu_base + 
-                                (cluster_index * CLUSTER_SPAN)  +
-                                (proc_index * ICU_SPAN);
-
-    *buffer = icu_address[register_index]; // read word 
-    return 0;
-
-#endif
 }
 
@@ -763,5 +756,5 @@
     else
     {
-        unsigned char *fb_address = (unsigned char*)&seg_fb_base + offset;
+        unsigned char *fb_address = (unsigned char*)&seg_fbf_base + offset;
         memcpy((void*)fb_address, (void*)buffer, length);
         return 0;
@@ -789,5 +782,5 @@
     else
     {
-        unsigned char *fb_address = (unsigned char*)&seg_fb_base + offset;
+        unsigned char *fb_address = (unsigned char*)&seg_fbf_base + offset;
         memcpy((void*)buffer, (void*)fb_address, length);
         return 0;
@@ -833,5 +826,7 @@
     if ( (user_vaddr & 0x3) || (length & 0x3) )
     {
+        _get_lock(&_tty_put_lock);
         _puts("[GIET ERROR] in _fbdma_access() : user buffer not word aligned\n");
+        _release_lock(&_tty_put_lock);
         return 1;
     }
@@ -841,5 +836,5 @@
 
     // compute frame buffer pbase address
-    unsigned int fb_vaddr = (unsigned int)&seg_fb_base + offset;
+    unsigned int fb_vaddr = (unsigned int)&seg_fbf_base + offset;
 
     ko = _v2p_translate( (page_table_t*)user_ptab,
@@ -851,5 +846,7 @@
     if ( ko )
     {
+        _get_lock(&_tty_put_lock);
         _puts("[GIET ERROR] in _fbdma_access() : frame buffer unmapped\n");
+        _release_lock(&_tty_put_lock);
         return 2;
     }
@@ -864,15 +861,21 @@
     if ( ko )
     {
+        _get_lock(&_tty_put_lock);
         _puts("[GIET ERROR] in _fbdma_access() : user buffer unmapped\n");
+        _release_lock(&_tty_put_lock);
         return 3;
     } 
     if ( (flags & PTE_U) == 0 )
     {
+        _get_lock(&_tty_put_lock);
         _puts("[GIET ERROR] in _fbdma_access() : user buffer not in user space\n");
+        _release_lock(&_tty_put_lock);
         return 4; 
     }
     if ( ( (flags & PTE_W) == 0 ) && to_user ) 
     {
+        _get_lock(&_tty_put_lock);
         _puts("[GIET ERROR] in _fbdma_access() : user buffer not writable\n");
+        _release_lock(&_tty_put_lock);
         return 5;
     }
