Index: /soft/giet_vm/giet_drivers/hba_driver.c
===================================================================
--- /soft/giet_vm/giet_drivers/hba_driver.c	(revision 575)
+++ /soft/giet_vm/giet_drivers/hba_driver.c	(revision 576)
@@ -27,27 +27,44 @@
 ///////////////////////////////////////////////////////////////////////////////////
 
-// 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];
+//////////////////////////////////////////////////////////////////////////////////
+// The global variable hba_boot_mode defines the way the HBA component is used
+// and must be defined in both kernel_init.c and boot.c files.
+// - during the boot phase, only one processor has access to the HBA in synchronous
+//   mode, there is no need for the allocator to use a lock
+// - after the boot phase, the HBA device can be used by several processors. The
+//   allocator is protected by a sqt_lock.
+//////////////////////////////////////////////////////////////////////////////////
+	
+extern unsigned int _hba_boot_mode;
+
+__attribute__((section(".kdata")))
+sqt_lock_t          _hba_allocator_lock  __attribute__((aligned(64)));
+
+// state of each slot (allocated to a task or not)
+// access must be protected by the allocator_lock in descheduling mode
+__attribute__((section(".kdata")))
+unsigned int        _hba_allocated_cmd[32];
+
+// state of the command (active or not), for each possible slot
+// used only in descheduling mode
+__attribute__((section(".kdata")))
+unsigned int        _hba_active_cmd[32]; 
+
+// global index of the task, for each entry in the command list
+__attribute__((section(".kdata")))
+unsigned int        _hba_gtid[32];
+
+// status of HBA commands
+__attribute__((section(".kdata")))
+unsigned int        _hba_status;
 
 // command list : up to 32 commands
 __attribute__((section(".kdata")))
-hba_cmd_desc_t  _hba_cmd_list[32] __attribute__((aligned(0x40)));   
+hba_cmd_desc_t      _hba_cmd_list[32] __attribute__((aligned(0x40)));   
 
 // command tables array : one command table per entry in command list
 __attribute__((section(".kdata")))
-hba_cmd_table_t _hba_cmd_table[32] __attribute__((aligned(0x40))); 
-
-// 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;
+hba_cmd_table_t     _hba_cmd_table[32] __attribute__((aligned(0x40))); 
+
 
 //////////////////////////////////////////////////////////////////////////////
@@ -75,6 +92,61 @@
 
 ///////////////////////////////////////////////////////////////////////////////
-// This function register a command in both the command list
-// and the command table, and updates the HBA_PXCI register.
+// This blocking fonction allocates a free command index to the task. 
+// The hba_allocator_lock is used except in boot mode.
+// It returns the allocated command index (between 0 and 31)
+///////////////////////////////////////////////////////////////////////////////
+unsigned int _hba_cmd_alloc()
+{
+    unsigned int found = 0;
+    unsigned int c;           // command index for the loop
+    unsigned int cmd_id = -1; // allocated command index when found
+
+    while ( found == 0)
+    {
+        if ( !_hba_boot_mode )
+            _sqt_lock_acquire(&_hba_allocator_lock);
+
+        for ( c = 0; c < 32 ; c++ )
+        {
+            if (_hba_allocated_cmd[c] == 0)
+            {
+                found = 1;
+                cmd_id = c;
+                _hba_allocated_cmd[c] = 1;
+                break;
+            }
+        }
+
+        if ( !_hba_boot_mode )
+            _sqt_lock_release(&_hba_allocator_lock);
+    }
+
+    return cmd_id;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// This function releases the command index in the hba_allocated_cmd table.
+// There is no need to take the lock because only the task which owns the 
+// command can release it.
+// return 0 if success, -1 if error
+///////////////////////////////////////////////////////////////////////////////
+unsigned int _hba_cmd_release(unsigned int cmd_id)
+{
+    if ( _hba_allocated_cmd[cmd_id] == 0 )
+    {
+        _printf("\n[HBA ERROR] in _hba_access() : ask to release a command which is not allocated\n");
+        return -1;
+    }
+    
+    _hba_allocated_cmd[cmd_id] = 0;
+    return 0;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// This function gets a command index with the hba_cmd_alloc function. Then it
+// registers a command in both the command list and the command table. It
+// updates the HBA_PXCI register and the hba_active_cmd in descheduling mode.
+// At the end the command slot is released.
 // return 0 if success, -1 if error
 ///////////////////////////////////////////////////////////////////////////////
@@ -97,6 +169,6 @@
 #endif
 
+    unsigned int       cmd_id;            // command index
     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   
@@ -111,19 +183,9 @@
 
     // get one entry in Command List
-    // atomic increment on the _hba_cmd_ptw allocator
-    // only the 5 LSB bits are used to index the Command List
-    ptw = _atomic_increment( &_hba_cmd_ptw , 1 ) & 0x1F;
-
-    // blocked until allocated entry in Command List is empty
-    do
-    {
-        // get PXCI register
-        pxci = _hba_get_register( HBA_PXCI );
-    } 
-    while ( pxci & (1<<ptw) );
+    cmd_id = _hba_cmd_alloc();
 
     // compute pointers on command descriptor and command table    
-    cmd_desc  = &_hba_cmd_list[ptw];
-    cmd_table = &_hba_cmd_table[ptw];
+    cmd_desc  = &_hba_cmd_list[cmd_id];
+    cmd_table = &_hba_cmd_table[cmd_id];
 
     // set  buffer descriptor in command table 
@@ -182,5 +244,5 @@
     {
         // start HBA transfer
-        _hba_set_register( HBA_PXCI, (1<<ptw) );
+        _hba_set_register( HBA_PXCI, (1<<cmd_id) );
 
 #if GIET_DEBUG_IOC_DRIVER
@@ -188,10 +250,10 @@
 _printf("\n[DEBUG HBA] _hba_access() : P[%d,%d,%d] get slot %d in Cmd List "
         " at cycle %d / polling\n",
-        ptw , x , y , p , _get_proctime() );
+        x , y , p , cmd_id, _get_proctime() );
 #endif
         // disable IRQs in PXIE register
         _hba_set_register( HBA_PXIE , 0 );
 
-        // poll PXCI[ptw] until command completed by HBA
+        // poll PXCI[cmd_id] until command completed by HBA
         do
         {
@@ -204,5 +266,5 @@
 #endif
         }
-        while( pxci & (1<<ptw) ); 
+        while( pxci & (1<<cmd_id) ); 
              
         // get PXIS register
@@ -227,5 +289,5 @@
 _printf("\n[DEBUG HBA] _hba_access() : P[%d,%d,%d] get slot %d in Cmd List "
         "at cycle %d / descheduling\n",
-        ptw , x , y , p , _get_proctime() );
+        x , y , p , cmd_id, _get_proctime() );
 #endif
         unsigned int save_sr;
@@ -235,6 +297,6 @@
         _hba_set_register( HBA_PXIE , 0x00000001 ); 
 
-        // set _hba_gtid[ptw] 
-        _hba_gtid[ptw] = (procid<<16) + ltid;
+        // set _hba_gtid[cmd_id] 
+        _hba_gtid[cmd_id] = (procid<<16) + ltid;
 
         // enters critical section
@@ -245,5 +307,8 @@
 
         // start HBA transfer
-        _hba_set_register( HBA_PXCI, (1<<ptw) );
+        _hba_set_register( HBA_PXCI, (1<<cmd_id) );
+
+        // set _hba_active_cmd[cmd_id]
+        _hba_active_cmd[cmd_id] = 1;
 
         // deschedule task
@@ -260,15 +325,22 @@
 
         // get command status
-        pxis = _hba_status[ptw];
-    }    
-
-#if GIET_DEBUG_IOC_DRIVER
-if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
-_printf("\n[DEBUG HBA] _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;
+        pxis = _hba_status;
+    }
+    
+    // release the cmd index
+    unsigned int release_success;
+    release_success = _hba_cmd_release(cmd_id);
+
+#if GIET_DEBUG_IOC_DRIVER
+if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
+_printf("\n[DEBUG HBA] _hba_access() : P[%d,%d,%d] release slot %d in Cmd List "
+        "and exit at cycle %d\n",
+        x , y , p, cmd_id,
+        _get_proctime() );
+#endif
+
+    if ( release_success != 0 )   return -1;
+    else if ( pxis & 0x40000000 ) return pxis;
+    else                          return 0;
 
 } // end _hba_access()
@@ -298,9 +370,10 @@
     }
 
-    // initialise Command List pointers
-    _hba_cmd_ptw = 0;
-    _hba_cmd_ptr = 0;
-
-    // initialise Command Descriptors in Command List
+    // initialise allocator lock if not in boot mode
+    if ( !_hba_boot_mode )
+        _sqt_lock_init(&_hba_allocator_lock);
+
+    // initialise Command Descriptors in Command List, allocated command table
+    // and active command table
     unsigned int         c;      
     unsigned long long   paddr;
@@ -310,4 +383,6 @@
         _hba_cmd_list[c].ctba  = (unsigned int)(paddr);
         _hba_cmd_list[c].ctbau = (unsigned int)(paddr>>32);
+        _hba_allocated_cmd[c] = 0;
+        _hba_active_cmd[c] = 0;
     }
 
@@ -329,28 +404,34 @@
                unsigned int channel )   // unused 
 {
+    // save PXIS register if there is no previous error
+    if ( !(_hba_status & 0x40000000))
+        _hba_status = _hba_get_register( HBA_PXIS );
+
+    // reset PXIS register
+    _hba_set_register( HBA_PXIS , 0 );
+
+    unsigned int cmd_id;  // cmd index for the loops
+    
+    // save the current list of active cmd in a 32 bits word
+    unsigned int current_active_cmd = 0;
+    for ( cmd_id = 0 ; cmd_id < 32 ; cmd_id ++ )
+    {
+        if ( _hba_active_cmd[cmd_id] == 1 ) current_active_cmd += (1 << cmd_id);
+    }
+    
     // get HBA_PXCI containing commands status
-    unsigned int pxci = _hba_get_register( HBA_PXCI );
-
-    // we must handle all completed commands 
-    // active commands are between  (_hba_cmd_ptr) and (_hba_cmd_ptw-1) 
-    unsigned int current;
-    for ( current = _hba_cmd_ptr ; current != _hba_cmd_ptw ; current++ )
-    {
-        unsigned int ptr = current & 0x1F;
-        
-        if ( (pxci & (1<<ptr)) == 0 )    // command completed
+    unsigned int current_pxci = _hba_get_register( HBA_PXCI );
+
+    for ( cmd_id = 0 ; cmd_id < 32 ; cmd_id ++ )
+    {
+        if ( ( (current_active_cmd & (1<<cmd_id)) != 0) && // active command
+             ( (current_pxci & (1<<cmd_id)) == 0 ) )       // completed command
         {
-            // increment the 32 bits variable _hba_cmd_ptr
-            _hba_cmd_ptr = (_hba_cmd_ptr + 1);
-
-            // save PXIS register
-            _hba_status[ptr] = _hba_get_register( HBA_PXIS );
-
-            // reset PXIS register
-            _hba_set_register( HBA_PXIS , 0 );
- 
+            // desactivate the command
+            _hba_active_cmd[cmd_id] = 0;
+
             // identify waiting task 
-            unsigned int remote_procid  = _hba_gtid[ptr]>>16;
-            unsigned int ltid           = _hba_gtid[ptr] & 0xFFFF;
+            unsigned int remote_procid  = _hba_gtid[cmd_id]>>16;
+            unsigned int ltid           = _hba_gtid[cmd_id] & 0xFFFF;
             unsigned int remote_cluster = remote_procid >> P_WIDTH;
             unsigned int remote_x       = remote_cluster >> Y_WIDTH;
@@ -374,12 +455,8 @@
 if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
 _printf("\n[DEBUG HBA] _hba_isr() : command %d completed at cycle %d\n"
-        "  resume task %d running on P[%d,%d,%d] / status = %x\n",
-        ptr , _get_proctime() ,
-        ltid , remote_x , remote_y , remote_p , _hba_status[ptr] );
-#endif
-        }
-        else                         // command non completed
-        {
-            break;
+        "  resume task %d running on P[%d,%d,%d]\n",
+        cmd_id , _get_proctime() ,
+        ltid , remote_x , remote_y , remote_p );
+#endif 
         }
     }
