Index: trunk/hal/tsar_mips32/drivers/soclib_dma.c
===================================================================
--- trunk/hal/tsar_mips32/drivers/soclib_dma.c	(revision 570)
+++ trunk/hal/tsar_mips32/drivers/soclib_dma.c	(revision 657)
@@ -2,5 +2,5 @@
  * soclib_dma.c - soclib Multi Channels DMA driver implementation
  *
- * Author     Alain Greiner (2017)
+ * Author     Alain Greiner (2017,2018,2019,2020)
 
  * Copyright (c) UPMC Sorbonne Universites
@@ -39,6 +39,6 @@
     chdev->isr = &soclib_dma_isr;
 
-    // enable interrupts
-	hal_remote_s32( XPTR( dma_cxy , dma_ptr + DMA_IRQ_DISABLED ) , 0 );
+    // disable interrupts
+	hal_remote_s32( XPTR( dma_cxy , dma_ptr + DMA_IRQ_DISABLED ) , 1 );
 
 } // soclib_dma_init()
@@ -47,18 +47,32 @@
 void __attribute__ ((noinline)) soclib_dma_cmd( xptr_t thread_xp )
 {
+    bool_t     sync;
     xptr_t     dev_xp;       // extended pointer on DMA devive
     xptr_t     dst_xp;       // extended pointer on destination buffer
     xptr_t     src_xp;       // extended pointer on source buffer
     uint32_t   size;         // buffer size
+    uint32_t   status;       // DMA status
 
     // get client thread cluster and local pointer
-    cxy_t      thread_cxy = GET_CXY( thread_xp );
-    thread_t * thread_ptr = (thread_t *)GET_PTR( thread_xp );
-
-    // get command arguments and extended pointer on DMA device
-    dev_xp = (xptr_t)hal_remote_l64( XPTR( thread_cxy , &thread_ptr->dma_cmd.dev_xp ) );
-    dst_xp = (xptr_t)hal_remote_l64( XPTR( thread_cxy , &thread_ptr->dma_cmd.dst_xp ) );
-    src_xp = (xptr_t)hal_remote_l64( XPTR( thread_cxy , &thread_ptr->dma_cmd.src_xp ) );
-    size   =         hal_remote_l32 ( XPTR( thread_cxy , &thread_ptr->dma_cmd.size   ) );
+    cxy_t      client_cxy = GET_CXY( thread_xp );
+    thread_t * client_ptr = (thread_t *)GET_PTR( thread_xp );
+
+#if (DEBUG_HAL_IOC_RX || DEBUG_HAL_IOC_TX)
+uint32_t    cycle        = (uint32_t)hal_get_cycles();
+thread_t  * this         = CURRENT_THREAD;
+process_t * process      = hal_remote_lpt( XPTR( th_cxy , &th_ptr->process ) );
+pid_t       client_pid   = hal_remote_l32( XPTR( th_cxy , &process->pid ) );
+trdid_t     client_trdid = hal_remote_l32( XPTR( th_cxy , &th_ptr->trdid ) );
+#endif 
+
+// TODO both the client and the server threads are allways local,
+// we could replace all these remote accesses by local accesses !!!  [AG]
+
+    // get command arguments and extended pointer on DMA device descriptor
+    sync   =         hal_remote_l32( XPTR( client_cxy , &client_ptr->dma_cmd.sync   ) );
+    dev_xp = (xptr_t)hal_remote_l64( XPTR( client_cxy , &client_ptr->dma_cmd.dev_xp ) );
+    dst_xp = (xptr_t)hal_remote_l64( XPTR( client_cxy , &client_ptr->dma_cmd.dst_xp ) );
+    src_xp = (xptr_t)hal_remote_l64( XPTR( client_cxy , &client_ptr->dma_cmd.src_xp ) );
+    size   =         hal_remote_l32( XPTR( client_cxy , &client_ptr->dma_cmd.size   ) );
 
     // get DMA device cluster and local pointer
@@ -66,10 +80,8 @@
     chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );
 
-    // get extended pointer on SOCLIB-DMA peripheral
-    xptr_t     dma_xp = hal_remote_l32( XPTR( dev_cxy , &dev_ptr->base ) );
-
-    // get SOCLIB_DMA device cluster and local pointer
+    // get pointers on DMA peripheral
+    xptr_t     dma_xp  = hal_remote_l32( XPTR( dev_cxy , &dev_ptr->base ) );
     cxy_t      dma_cxy = GET_CXY( dma_xp );
-    uint32_t * dma_ptr = (uint32_t *)GET_PTR( dma_xp );
+    uint32_t * dma_ptr = GET_PTR( dma_xp );
 
     // get DMA channel index and channel base address
@@ -82,15 +94,84 @@
     uint32_t   src_msb = (uint32_t)(src_xp>>32);
 
-    // set SOCLIB_DMA registers to start tranfer operation
+    // set SOCLIB_DMA registers and launch tranfer operation
     hal_remote_s32( XPTR( dma_cxy , base + DMA_SRC     ) , src_lsb ); 
     hal_remote_s32( XPTR( dma_cxy , base + DMA_SRC_EXT ) , src_msb ); 
     hal_remote_s32( XPTR( dma_cxy , base + DMA_DST     ) , dst_lsb );
     hal_remote_s32( XPTR( dma_cxy , base + DMA_DST_EXT ) , dst_msb );
-    hal_remote_s32( XPTR( dma_cxy , base + DMA_LEN     ) , size    );
-
-    // Block and deschedule server thread
-    thread_block( XPTR( local_cxy , CURRENT_THREAD ) , THREAD_BLOCKED_ISR );
-    sched_yield("blocked on ISR");
-    
+    hal_remote_s32( XPTR( dma_cxy , base + DMA_LEN_STS ) , size    );
+
+ #if DEBUG_HAL_DMA
+if( DEBUG_HAL_DMA < cycle )
+printk("\n[%s] thread[%x,%x] launched DMA for client thread[%x,%x] / cycle %d\n",
+__FUNCTION__, this->process->pid, this->trdid, client_pid, client_trdid, cycle );
+#endif
+
+    // waiting policy  depends on the command type
+    // - for an asynchronous command, this function is called by the server thread
+    //   => block and deschedule after launching the transfer. 
+    //   The operation status is reported in the command by the ISR, and the
+    //   server thread is re-activated by the ISR.
+    // - for a synchronous command, this function is called by the client thread
+    //   => mask the DMA_IRQ and poll the DMA status register until transfer completion,
+    //   and reports status in the command when the transfer is completed.
+
+    if( sync )                            // client thread poll status until completion
+    {
+        while( 1 )
+        {
+            status = hal_remote_l32( XPTR( dma_cxy , base + DMA_LEN_STS ) );
+
+            if( (status == DMA_SUCCESS) || (status == DMA_IDLE) )
+            {
+                // set operation status in command
+                hal_remote_s32( XPTR( client_cxy , &client_ptr->dma_cmd.error ) , 0 );
+
+#if DEBUG_HAL_DMA
+cycle = (uint32_t)hal_get_cycles();
+if( DEBUG_HAL_DMA < cycle )
+printk("\n[%s] thread[%x,%x] exit after SYNC success / cycle %d\n",
+__FUNCTION__, this->process->pid, this->trdid, cycle );
+#endif
+                // exit while
+                break;
+            }
+            else if( (status == DMA_ERROR_READ) || (status == DMA_ERROR_WRITE) )
+            {
+                // set operation status in command
+                hal_remote_s32( XPTR( client_cxy , &client_ptr->dma_cmd.error ) , 1 );
+
+#if DEBUG_HAL_DMA
+cycle = (uint32_t)hal_get_cycles();
+if( DEBUG_HAL_DMA < cycle )
+printk("\n[%s] thread[%x,%x] exit after SYNC failure / cycle %d\n",
+__FUNCTION__, this->process->pid, this->trdid, cycle );
+#endif
+                // exit while
+                break;
+            }
+        }
+    }    
+    else                                // server thread block and deschedule
+    {
+        // server thread blocks on ISR
+        thread_block( XPTR( local_cxy , CURRENT_THREAD ) , THREAD_BLOCKED_ISR );
+
+        // enable DMA interrupts
+	    hal_remote_s32( XPTR( dma_cxy , dma_ptr + DMA_IRQ_DISABLED ) , 0 );
+
+        // server thread deschedules
+        sched_yield("blocked on ISR");
+
+        // disable DMA interrupts
+	    hal_remote_s32( XPTR( dma_cxy , dma_ptr + DMA_IRQ_DISABLED ) , 1 );
+
+#if DEBUG_HAL_DMA
+cycle = (uint32_t)hal_get_cycles();
+if( DEBUG_HAL_DMA < cycle )
+printk("\n[%s] thread[%x,%x] exit after ASYNC / client thread[%x,%x] / cycle %d\n",
+__FUNCTION__ , this->process->pid, this->trdid, client_pid, client_trdid, cycle );
+#endif
+
+    }
 } // soclib_dma_cmd()
 
@@ -98,10 +179,10 @@
 void __attribute__ ((noinline)) soclib_dma_isr( chdev_t * chdev )
 {
-    // get extended pointer on client thread
+    // get extended pointer on server thread
+    xptr_t server_xp = XPTR( local_cxy , &chdev->server );
+
+   // get extended pointer on client thread
     xptr_t root      = XPTR( local_cxy , &chdev->wait_root );
     xptr_t client_xp = XLIST_FIRST( root , thread_t , wait_list );
-
-    // get extended pointer on server thread
-    xptr_t server_xp = XPTR( local_cxy , &chdev->server );
 
     // get client thread cluster and local pointer
@@ -113,9 +194,9 @@
     uint32_t * dma_ptr  = (uint32_t *)GET_PTR( chdev->base );
 
-    // get DMA channel base address
+    // build DMA channel base address
     uint32_t * base = dma_ptr + (DMA_SPAN * chdev->channel);
 
     // get DMA status register 
-	uint32_t status = hal_remote_l32( XPTR( dma_cxy , base + DMA_LEN ) );   
+	uint32_t status = hal_remote_l32( XPTR( dma_cxy , base + DMA_LEN_STS ) );   
 
     // acknowledge IRQ
@@ -129,7 +210,4 @@
     thread_unblock( server_xp , THREAD_BLOCKED_ISR );
 
-    // unblock client thread
-    thread_unblock( client_xp , THREAD_BLOCKED_IO );
-
 } // soclib_dma_isr()
 
