Index: trunk/hal/tsar_mips32/drivers/soclib_tty.c
===================================================================
--- trunk/hal/tsar_mips32/drivers/soclib_tty.c	(revision 435)
+++ trunk/hal/tsar_mips32/drivers/soclib_tty.c	(revision 436)
@@ -46,4 +46,14 @@
 #endif
 
+////////////////////////////////////////////////////////////////////////////////////
+// These global variables implement the TTY_RX  FIFOs (one per channel)
+////////////////////////////////////////////////////////////////////////////////////
+
+__attribute__((section(".kdata")))
+tty_fifo_t  tty_rx_fifo[CONFIG_MAX_TXT_CHANNELS];
+
+__attribute__((section(".kdata")))
+tty_fifo_t  tty_tx_fifo[CONFIG_MAX_TXT_CHANNELS];
+
 ///////////////////////////////////////
 void soclib_tty_init( chdev_t * chdev )
@@ -51,4 +61,5 @@
     xptr_t reg_xp;
 
+    // initialise function pointers in chdev
     chdev->cmd = &soclib_tty_cmd;
     chdev->isr = &soclib_tty_isr;
@@ -58,4 +69,5 @@
     xptr_t   tty_xp  = chdev->base;
     uint32_t channel = chdev->channel;
+    bool_t   is_rx   = chdev->is_rx;
 
     // get SOCLIB_TTY device cluster and local pointer
@@ -70,17 +82,26 @@
     reg_xp = XPTR( tty_cxy , tty_ptr + (channel * TTY_SPAN) + TTY_TX_IRQ_ENABLE );
     hal_remote_sw( reg_xp , 0 );
-}
+
+    // reset relevant FIFO
+    if( is_rx )
+    {
+        tty_rx_fifo[channel].sts = 0;
+        tty_rx_fifo[channel].ptr = 0;
+        tty_rx_fifo[channel].ptw = 0;
+    }
+    else
+    {
+        tty_tx_fifo[channel].sts = 0;
+        tty_tx_fifo[channel].ptr = 0;
+        tty_tx_fifo[channel].ptw = 0;
+    }
+}  // end soclib_tty_init()
 
 //////////////////////////////////////////////////////////////
 void __attribute__ ((noinline)) soclib_tty_cmd( xptr_t th_xp )
 {
-
-#if (CONFIG_DEBUG_SYS_READ & 1)
-if( type == TXT_READ) enter_tty_cmd_read = (uint32_t)hal_get_cycles();
-#endif
-
-#if (CONFIG_DEBUG_SYS_WRITE & 1)
-if( type == TXT_WRITE) enter_tty_cmd_write = (uint32_t)hal_get_cycles();
-#endif
+    tty_fifo_t * fifo;     // TTY_RX or TTY_TX FIFO
+    char         byte;     // byte value
+    uint32_t     done;     // number of bytes moved
 
     // get client thread cluster and local pointer
@@ -88,49 +109,127 @@
     thread_t * th_ptr = GET_PTR( th_xp );
 
-    // get command type and extended pointer on TXT device
-    uint32_t type = hal_remote_lw ( XPTR( th_cxy , &th_ptr->txt_cmd.type ) );
-
-#if CONFIG_DEBUG_HAL_TXT
+    // get command arguments
+    uint32_t type     = hal_remote_lw ( XPTR( th_cxy , &th_ptr->txt_cmd.type   ) );
+    xptr_t   buf_xp   = hal_remote_lwd( XPTR( th_cxy , &th_ptr->txt_cmd.buf_xp ) );
+    uint32_t count    = hal_remote_lw ( XPTR( th_cxy , &th_ptr->txt_cmd.count  ) );
+    xptr_t   error_xp = XPTR( th_cxy , &th_ptr->txt_cmd.error );
+
+#if (CONFIG_DEBUG_SYS_READ & 1)
+if( type == TXT_READ) enter_tty_cmd_read = (uint32_t)hal_get_cycles();
+#endif
+
+#if (CONFIG_DEBUG_SYS_WRITE & 1)
+if( type == TXT_WRITE) enter_tty_cmd_write = (uint32_t)hal_get_cycles();
+#endif
+
+#if CONFIG_DEBUG_HAL_TXT_RX
 uint32_t cycle = (uint32_t)hal_get_cycles();
-if (CONFIG_DEBUG_HAL_TXT < cycle )
-printk("\n[DBG] %s : thread %x enter for %s / cycle %d\n",
-__FUNCTION__ , CURRENT_THREAD , dev_txt_type_str(type) , cycle );
-#endif
-
-    if( type == TXT_WRITE )         // block, enable TX_IRQ, and dechedule for a WRITE
-    {
-        xptr_t dev_xp = (xptr_t)hal_remote_lwd( XPTR( th_cxy , &th_ptr->txt_cmd.dev_xp ) );
-
-        // get TXT device cluster and local pointer
-        cxy_t     dev_cxy = GET_CXY( dev_xp );
-        chdev_t * dev_ptr = GET_PTR( dev_xp );
-
-        // get extended pointer on SOCLIB_TTY base segment
-        xptr_t tty_xp = (xptr_t)hal_remote_lwd( XPTR( dev_cxy , &dev_ptr->base ) );
-
-        // get SOCLIB_TTY base segment cluster and local pointer
-        cxy_t      tty_cxy = GET_CXY( tty_xp );
-        uint32_t * tty_ptr = GET_PTR( tty_xp );
-
-        // get TTY channel index and channel base address
-        uint32_t   channel = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->channel ) );
-        uint32_t * base    = tty_ptr + TTY_SPAN * channel;
-
-        // block server thread 
-        thread_block( CURRENT_THREAD , THREAD_BLOCKED_DEV_ISR );
-
-        // enable relevant TX_IRQ for a WRITE
-        hal_remote_sw( XPTR( tty_cxy , base + TTY_TX_IRQ_ENABLE ) , 1 );
-
-        // deschedule
-        sched_yield( "waiting TXT_TX_ISR completion" );
+if( (CONFIG_DEBUG_HAL_TXT_RX < cycle) && (type == TXT_READ) )
+printk("\n[DBG] %s : thread %x enter for RX / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD , cycle );
+#endif
+
+#if CONFIG_DEBUG_HAL_TXT_TX
+uint32_t cycle = (uint32_t)hal_get_cycles();
+if( (CONFIG_DEBUG_HAL_TXT_TX < cycle) && (type == TXT_WRITE) )
+printk("\n[DBG] %s : thread %x enter for TX / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD , cycle );
+#endif
+
+    // get TXT device pointers
+    xptr_t    dev_xp = (xptr_t)hal_remote_lwd( XPTR( th_cxy , &th_ptr->txt_cmd.dev_xp ) );
+    cxy_t     dev_cxy = GET_CXY( dev_xp );
+    chdev_t * dev_ptr = GET_PTR( dev_xp );
+
+    // get extended pointer on SOCLIB_TTY base segment
+    xptr_t tty_xp = (xptr_t)hal_remote_lwd( XPTR( dev_cxy , &dev_ptr->base ) );
+
+    // get SOCLIB_TTY base segment cluster and local pointer
+    cxy_t      tty_cxy = GET_CXY( tty_xp );
+    uint32_t * tty_ptr = GET_PTR( tty_xp );
+
+    // get TTY channel index and channel base address
+    uint32_t   channel = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->channel ) );
+    uint32_t * base    = tty_ptr + TTY_SPAN * channel;
+
+    ///////////////////////
+    if( type == TXT_WRITE )         // write bytes to TTY_TX FIFO
+    {
+        fifo = &tty_tx_fifo[channel];
+
+        done = 0;
+
+        while( done < count )
+        {
+            if( fifo->sts < TTY_FIFO_DEPTH )   // put one byte to FIFO if TX_FIFO not full
+            {
+                // get one byte from command buffer
+                byte = hal_remote_lb( buf_xp + done );
+
+                // write byte to FIFO
+                fifo->data[fifo->ptw] = byte;
+
+                // prevent race
+                hal_fence();
+
+                // update FIFO state
+                fifo->ptw = (fifo->ptw + 1) % TTY_FIFO_DEPTH;
+                hal_atomic_add( &fifo->sts , 1 );
+
+                // udate number of bytes moved
+                done++;
+
+                // enable TX_IRQ 
+                hal_remote_sw( XPTR( tty_cxy , base + TTY_TX_IRQ_ENABLE ) , 1 );
+            }
+            else                                // block & deschedule if TX_FIFO full
+            {
+                // block on ISR
+                thread_block( XPTR( local_cxy , CURRENT_THREAD ) , THREAD_BLOCKED_ISR );
+
+                // deschedule
+                sched_yield( "TTY_TX_FIFO full" ); 
+            }
+        }
+
+        // set error status in command and return
+        hal_remote_sw( error_xp , 0 );
     }
-    else if( type == TXT_READ )        // block, and deschedule for a READ
-    {
-        // block server thread
-        thread_block( CURRENT_THREAD , THREAD_BLOCKED_DEV_ISR );
-
-        // deschedule
-        sched_yield( "waiting TXT_RX_ISR completion" );
+    ///////////////////////////
+    else if( type == TXT_READ )       // read bytes from TTY_RX FIFO   
+    {
+        fifo = &tty_rx_fifo[channel];
+
+        done = 0;
+
+        while( done < count )
+        {
+            if( fifo->sts > 0 )               // get byte from FIFO if not empty
+            {
+                // get one byte from FIFO
+                char byte = fifo->data[fifo->ptr];
+
+                // update FIFO state
+                fifo->ptr = (fifo->ptr + 1) % TTY_FIFO_DEPTH;
+                hal_atomic_add( &fifo->sts , -1 );
+
+                // set byte to command buffer
+                hal_remote_sb( buf_xp + done , byte );
+
+                // udate number of bytes
+                done++;
+            }
+            else                             //  deschedule if FIFO empty
+            {
+                // block on ISR
+                thread_block( XPTR( local_cxy , CURRENT_THREAD ) , THREAD_BLOCKED_ISR );
+    
+                // deschedule
+                sched_yield( "TTY_TX_FIFO_RX empty" );
+            }
+        }  // end while
+
+        // set error status in command
+        hal_remote_sw( error_xp , 0 );
     }
     else
@@ -139,9 +238,16 @@
     }
 
-#if CONFIG_DEBUG_HAL_TXT
+#if CONFIG_DEBUG_HAL_TXT_RX
 cycle = (uint32_t)hal_get_cycles();
-if (CONFIG_DEBUG_HAL_TXT < cycle )
-printk("\n[DBG] %s : thread %x exit after %s / cycle %d\n", 
-__FUNCTION__ , CURRENT_THREAD , dev_txt_type_str( type ) , cycle );
+if( (CONFIG_DEBUG_HAL_TXT_RX < cycle) && (type == TXT_READ) )
+printk("\n[DBG] %s : thread %x exit after RX / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD , cycle );
+#endif
+
+#if CONFIG_DEBUG_HAL_TXT_TX
+cycle = (uint32_t)hal_get_cycles();
+if( (CONFIG_DEBUG_HAL_TXT_TX < cycle) && (type == TXT_WRITE) )
+printk("\n[DBG] %s : thread %x exit after TX / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD , cycle );
 #endif
 
@@ -155,4 +261,223 @@
 
 }  // end soclib_tty_cmd()
+
+/////////////////////////////////////////////////////////////////
+void __attribute__ ((noinline)) soclib_tty_isr( chdev_t * chdev )
+{
+    thread_t   * server;       // pointer on TXT chdev server thread
+    lid_t        server_lid;   // local index of core running the server thread
+    uint32_t     channel;      // TXT chdev channel
+    bool_t       is_rx;        // TXT chdev direction
+    char         byte;         // byte value
+    xptr_t       owner_xp;     // extended pointer on foreground process in owner cluster
+    cxy_t        owner_cxy;   
+    process_t  * owner_ptr;
+    pid_t        owner_pid;
+    tty_fifo_t * fifo;         // pointer on TTY_TX or TTY_RX FIFO
+    cxy_t        tty_cxy;      // soclib_tty cluster
+    uint32_t *   tty_ptr;      // soclib_tty segment base address
+    uint32_t   * base;         // soclib_tty channel base address
+    xptr_t       status_xp;    // extended pointer on TTY_STATUS register
+    xptr_t       write_xp;     // extended pointer on TTY_WRITE register
+    xptr_t       read_xp;      // extended pointer on TTY_READ register
+
+    // get TXT chdev channel, direction and server thread
+    channel    = chdev->channel;
+    is_rx      = chdev->is_rx;
+    server     = chdev->server;
+    server_lid = server->core->lid;
+
+#if (CONFIG_DEBUG_SYS_READ & 1)
+if( is_rx ) enter_tty_isr_read = (uint32_t)hal_get_cycles();
+#endif
+
+#if (CONFIG_DEBUG_SYS_WRITE & 1)
+if( is_rx == 0 ) enter_tty_isr_write = (uint32_t)hal_get_cycles();
+#endif
+
+#if CONFIG_DEBUG_HAL_TXT_RX
+uint32_t cycle = (uint32_t)hal_get_cycles();
+if( (CONFIG_DEBUG_HAL_TXT_RX < cycle) && is_rx )
+printk("\n[DBG] %s : enter for RX / cycle %d\n", __FUNCTION__ , cycle );
+#endif
+
+#if CONFIG_DEBUG_HAL_TXT_TX
+uint32_t cycle = (uint32_t)hal_get_cycles();
+if( (CONFIG_DEBUG_HAL_TXT_TX < cycle) && (is_rx == 0) )
+printk("\n[DBG] %s : enter for TX / cycle %d\n", __FUNCTION__ , cycle );
+#endif
+
+    // get SOCLIB_TTY peripheral cluster and local pointer
+    tty_cxy = GET_CXY( chdev->base );
+    tty_ptr = GET_PTR( chdev->base );
+
+    // get channel base address
+    base    = tty_ptr + TTY_SPAN * channel;
+
+    // get extended pointer on TTY registers
+    status_xp = XPTR( tty_cxy , base + TTY_STATUS );
+    write_xp  = XPTR( tty_cxy , base + TTY_WRITE );
+    read_xp   = XPTR( tty_cxy , base + TTY_READ );
+
+    /////////////////////////// handle RX //////////////////////
+    if( is_rx )
+    {
+        fifo = &tty_rx_fifo[channel];
+
+        // try to move bytes until TTY_READ register empty
+        while( hal_remote_lw( status_xp ) & TTY_STATUS_RX_FULL )   
+        {
+            // get one byte from TTY_READ register & acknowledge RX_IRQ
+            byte = (char)hal_remote_lb( read_xp );
+
+            // filter special character ^Z
+            if( byte == 0x1A ) 
+            {
+                // get pointers on TXT owner process in owner cluster
+                owner_xp  = process_txt_get_owner( channel );
+               
+                // check process exist
+                assert( (owner_xp != XPTR_NULL) , __FUNCTION__, 
+                "TXT owner process not found\n" );
+
+                // get relevant infos on owner process
+                owner_cxy = GET_CXY( owner_xp );
+                owner_ptr = GET_PTR( owner_xp );
+                owner_pid = hal_remote_lw( XPTR( owner_cxy , &owner_ptr->pid ) );
+
+                // block owner process only if it is not a KSH
+                if( process_get_ppid( owner_xp ) > 1 )
+                {
+                    // send stop signal to owner process
+                    process_sigaction( owner_pid , BLOCK_ALL_THREADS );
+
+                    // atomically update owner process termination state
+                    hal_remote_atomic_or( XPTR( owner_cxy , &owner_ptr->term_state ) ,
+                                          PROCESS_TERM_STOP );
+                    return;
+                }
+            }
+
+            // filter special character ^C
+            if( byte == 0x03 )
+            {
+                // get pointers on TXT owner process in owner cluster
+                owner_xp  = process_txt_get_owner( channel );
+
+                // check process exist
+                assert( (owner_xp != XPTR_NULL) , __FUNCTION__,
+                "TXT owner process not found\n" );
+
+                // get relevant infos on TXT owner process
+                owner_cxy = GET_CXY( owner_xp );
+                owner_ptr = GET_PTR( owner_xp );
+                owner_pid = hal_remote_lw( XPTR( owner_cxy , &owner_ptr->pid ) );
+
+                // kill TXT owner process only if it is not INIT
+                if( owner_pid != 1 )
+                {
+                    // remove process from TXT list
+                    process_txt_detach( owner_xp );
+
+                    // mark for delete all processes in all clusters, but the main
+                    process_sigaction( owner_pid , DELETE_ALL_THREADS );
+                
+                    // get pointer on target process main thread
+                    xptr_t main_xp = XPTR( owner_cxy , &owner_ptr->th_tbl[0] );
+
+                    // block main thread
+                    thread_block( main_xp , THREAD_BLOCKED_GLOBAL );
+
+                    // atomically update owner process termination state
+                    hal_remote_atomic_or( XPTR( owner_cxy , &owner_ptr->term_state ) ,
+                                          PROCESS_TERM_KILL );
+                    return;
+                }
+            }
+
+            // write byte in TTY_RX FIFO if not full / discard byte if full
+            if ( fifo->sts < TTY_FIFO_DEPTH )
+            {
+                // store byte into FIFO 
+                fifo->data[fifo->ptw] = (char)byte; 
+
+                // avoid race 
+                hal_fence();
+
+                // update RX_FIFO state
+                fifo->ptw = (fifo->ptw + 1) % TTY_FIFO_DEPTH;
+                hal_atomic_add( &fifo->sts , 1 );
+
+                // unblock TXT_RX server thread 
+                thread_unblock( XPTR( local_cxy , server ) , THREAD_BLOCKED_ISR );
+
+                // send IPI to core running server thread
+                dev_pic_send_ipi( local_cxy , server_lid );
+            }
+            else
+            {
+                printk("\n[WARNING] %s : TTY_RX_FIFO[%d] full => discard character <%x>\n",
+                __FUNCTION__, channel, (uint32_t)byte );
+            }
+        }  // end while TTY_READ register full
+
+    }  // end RX
+
+    ///////////////////////  handle TX  /////////////////////////////
+    else
+    {
+        fifo = &tty_tx_fifo[channel];
+
+        // try to move bytes until TX_FIFO empty
+        while( fifo->sts > 0 )
+        {
+            // write one byte to TTY_WRITE register if empty / exit while if full
+            if( (hal_remote_lw( status_xp ) & TTY_STATUS_TX_FULL) == 0 ) 
+            {
+                // get one byte from TX_FIFO
+                byte = fifo->data[fifo->ptr];
+
+                // update TX_FIFO state
+                fifo->ptr = (fifo->ptr + 1) % TTY_FIFO_DEPTH;
+                hal_atomic_add( &fifo->sts , -1 );
+
+                // write byte to TTY_WRITE register & acknowledge TX_IRQ
+                hal_remote_sb( write_xp , byte );
+            }
+        }
+
+        // disable TX_IRQ 
+        hal_remote_sw( XPTR( tty_cxy , base + TTY_TX_IRQ_ENABLE ) , 0 );
+
+        // unblock TXT_TX server thread
+        thread_unblock( XPTR( local_cxy , server ) , THREAD_BLOCKED_ISR );
+
+        // send IPI to core running server thread
+        dev_pic_send_ipi( local_cxy , server_lid );
+    }  // end TX
+
+    hal_fence();
+
+#if CONFIG_DEBUG_HAL_TXT_RX
+cycle = (uint32_t)hal_get_cycles();
+if( (CONFIG_DEBUG_HAL_TXT_RX < cycle) && is_rx )
+printk("\n[DBG] %s : exit after RX / cycle %d\n", __FUNCTION__, cycle );
+#endif
+
+#if CONFIG_DEBUG_HAL_TXT_TX
+cycle = (uint32_t)hal_get_cycles();
+if( (CONFIG_DEBUG_HAL_TXT_TX < cycle) && (is_rx == 0) )
+printk("\n[DBG] %s : exit after TX / cycle %d\n", __FUNCTION__, cycle );
+#endif
+
+#if (CONFIG_DEBUG_SYS_READ & 1)
+if( is_rx ) exit_tty_isr_read = (uint32_t)hal_get_cycles();
+#endif
+
+#if (CONFIG_DEBUG_SYS_WRITE & 1)
+if( is_rx == 0 ) exit_tty_isr_write = (uint32_t)hal_get_cycles();
+#endif
+
+}  // end soclib_tty_isr()
 
 /////////////////////////////////////////////////////////////
@@ -182,5 +507,5 @@
     xptr_t status_xp = XPTR( tty_cxy , tty_ptr + TTY_STATUS );
 
-    // loop on characters (busy waiting strategy)
+    // loop on characters (busy waiting policy)
     for( i = 0 ; i < count ; i++ )
     {
@@ -199,196 +524,3 @@
 
 
-/////////////////////////////////////////////////////////////////
-void __attribute__ ((noinline)) soclib_tty_isr( chdev_t * chdev )
-{
-    uint32_t    type;         // command type
-    uint32_t    count;        // number of bytes in buffer
-    xptr_t      buf_xp;       // extended pointer on buffer
-    xptr_t      error_xp;     // extended pointer on error field in command
-    xptr_t      status_xp;    // extended pointer on TTY_STATUS register
-    xptr_t      write_xp;     // extended pointer on TTY_WRITE register
-    xptr_t      read_xp;      // extended pointer on TTY_READ register
-    uint32_t    status;       // TTY terminal status
-    char        byte;         // read byte
-    xptr_t      client_xp;    // first client thread in waiting queue
-    cxy_t       client_cxy;   // firts client thread cluster
-    thread_t  * client_ptr;   // first client thread pointer
-    pid_t       pid;          // foreground process identifier
-    xptr_t      owner_xp;     // extended pointer on foreground process in owner cluster
-    cxy_t       owner_cxy;   
-    process_t * owner_ptr;
-    uint32_t    i;
-
-#if (CONFIG_DEBUG_SYS_READ & 1)
-enter_tty_isr_read = (uint32_t)hal_get_cycles();
-#endif
-
-#if (CONFIG_DEBUG_SYS_WRITE & 1)
-enter_tty_isr_write = (uint32_t)hal_get_cycles();
-#endif
-
-#if CONFIG_DEBUG_HAL_TXT
-uint32_t cycle = (uint32_t)hal_get_cycles();
-if (CONFIG_DEBUG_HAL_TXT < cycle)
-printk("\n[DBG] %s : enter / cycle %d\n", __FUNCTION__ , cycle );
-#endif
-
-    // get extended pointer on chdev queue root
-    xptr_t root_xp   = XPTR( local_cxy , &chdev->wait_root );
-
-    // get chdev channel 
-    uint32_t channel = chdev->channel;
-
-    // get first command if queue non empty
-    if( xlist_is_empty( root_xp ) == false )
-    {
-        // get extended pointer on first client thread
-        client_xp = XLIST_FIRST_ELEMENT( root_xp , thread_t , wait_list );
-
-        // get client thread cluster and local pointer
-        client_cxy = GET_CXY( client_xp );
-        client_ptr = GET_PTR( client_xp );
-
-        // get command arguments
-        type     = hal_remote_lw ( XPTR( client_cxy , &client_ptr->txt_cmd.type   ) );
-        count    = hal_remote_lw ( XPTR( client_cxy , &client_ptr->txt_cmd.count  ) );
-        buf_xp   = hal_remote_lwd( XPTR( client_cxy , &client_ptr->txt_cmd.buf_xp ) );
-        error_xp =                 XPTR( client_cxy , &client_ptr->txt_cmd.error  );
-    }
-    else
-    {
-        type     = 0xFFFFFFFF;
-
-        // these lines to avoid a GCC warning
-        count      = 0;
-        buf_xp     = XPTR_NULL;
-        error_xp   = XPTR_NULL;
-        client_cxy = 0;
-        client_ptr = NULL;
-    }
-
-    // get SOCLIB_TTY peripheral cluster and local pointer
-    cxy_t      tty_cxy = GET_CXY( chdev->base );
-    uint32_t * tty_ptr = GET_PTR( chdev->base );
-
-    // get channel base address
-    uint32_t * base = tty_ptr + TTY_SPAN * chdev->channel;
-
-    // get extended pointer on TTY registers
-    status_xp = XPTR( tty_cxy , base + TTY_STATUS );
-    write_xp  = XPTR( tty_cxy , base + TTY_WRITE );
-    read_xp   = XPTR( tty_cxy , base + TTY_READ );
-
-    // get TTY_STATUS register value
-    status = hal_remote_lw( status_xp );
-
-    // 1. handle RX if TTY_READ buffer full
-    if( status & TTY_STATUS_RX_FULL )   
-    {
-        // get a byte from TTY_READ / acknowledge RX_IRQ
-        byte = (char)hal_remote_lb( read_xp );
-
-        // check character value
-        if( byte == 0x1A )          // ^Z  =>  stop onwner process
-        {
-            // get pid of terminal owner process
-            pid = process_get_txt_owner( channel );
-
-            // get cluster and pointers on owner process descriptor
-            owner_xp  = cluster_get_owner_process_from_pid( pid );
-            owner_cxy = GET_CXY( owner_xp );
-            owner_ptr = GET_PTR( owner_xp );
-
-            // send stop signal to owner process
-            process_sigaction( pid , BLOCK_ALL_THREADS );
-                
-            // atomically update owner process termination state
-            hal_remote_atomic_or( XPTR( owner_cxy , &owner_ptr->term_state ) ,
-                                  PROCESS_TERM_STOP );
-            return;
-        }
-        else if( byte == 0x03 )     // ^C  => kill owner process
-        {
-            // get pid of terminal owner process
-            pid = process_get_txt_owner( channel );
-
-            // get cluster and pointers on owner process descriptor
-            owner_xp  = cluster_get_owner_process_from_pid( pid );
-            owner_cxy = GET_CXY( owner_xp );
-            owner_ptr = GET_PTR( owner_xp );
-
-            // send kill signal to owner process
-            process_sigaction( pid , DELETE_ALL_THREADS );
-                
-            // atomically update owner process termination state
-            hal_remote_atomic_or( XPTR( owner_cxy , &owner_ptr->term_state ) ,
-                                  PROCESS_TERM_KILL );
-            return;
-        }
-        else if( type == TXT_READ ) // pending TXT_READ
-        {
-            // write character to command buffer
-            hal_remote_sb( buf_xp , byte );
-
-            // set I/O operation status in command
-            hal_remote_sw( error_xp , 0 );
-
-            // unblock server thread
-            thread_unblock( XPTR( local_cxy , chdev->server ) , THREAD_BLOCKED_DEV_ISR );
-        }
-    }
-
-    // 3. handle TX if TXT_WRITE
-    if( type == TXT_WRITE )
-    {
-        // loop on characters
-        for( i = 0 ; i < count ; i++ )
-        {
-            // get TTY_STATUS
-            status = hal_remote_lw( status_xp );
-
-            if( (status & TTY_STATUS_TX_FULL) == 0 ) // TTY_TX empty => move one byte
-            {
-                // get one byte from command buffer
-                byte = (char)hal_remote_lb( buf_xp + i );
-
-                // write byte to TTY_WRITE / acknowledge TX_IRQ
-                hal_remote_sb( write_xp , byte );
-            }
-            else         // TTY_TX full => update command arguments and exit ISR for retry
-            {
-                hal_remote_sw ( XPTR( client_cxy , &client_ptr->txt_cmd.count ), count-i );
-                hal_remote_swd( XPTR( client_cxy , &client_ptr->txt_cmd.buf_xp ), buf_xp+i );
-                return;
-            }
-        }
-
-        // set I/O operation status in command
-        hal_remote_sw( error_xp , 0 );
-
-        // disable TX_IRQ 
-        hal_remote_sw( XPTR( tty_cxy , base + TTY_TX_IRQ_ENABLE ) , 0 );
-
-        // unblock server thread
-        thread_unblock( XPTR( local_cxy , chdev->server ) , THREAD_BLOCKED_DEV_ISR );
-    }
-
-    hal_fence();
-
-#if CONFIG_DEBUG_HAL_TXT
-cycle = (uint32_t)hal_get_cycles();
-if (CONFIG_DEBUG_HAL_TXT < cycle)
-printk("\n[DBG] %s : exit after %s / cycle %d\n",
-__FUNCTION__ , dev_txt_type_str( type ) , cycle );
-#endif
-
-#if (CONFIG_DEBUG_SYS_READ & 1)
-if( type == TXT_READ) exit_tty_isr_read = (uint32_t)hal_get_cycles();
-#endif
-
-#if (CONFIG_DEBUG_SYS_WRITE & 1)
-if( type == TXT_WRITE) exit_tty_isr_write = (uint32_t)hal_get_cycles();
-#endif
-
-}  // end soclib_tty_isr()
-
+
