source: trunk/hal/tsar_mips32/drivers/soclib_mtty.c @ 540

Last change on this file since 540 was 540, checked in by nicolas.van.phan@…, 6 years ago

TTY MUX 5/5 : Multiplex TTY character receiving

The multiplexing for receving chars is done by redirecting
the IRQs (when a char is received) to the right chdev (so the right
server DEV thread). When the user types an uppercase letter,
it is treated as a special char used to change the active tty
by redirecting the IRQs to the chdev corresponding to the appropriate
channel.

Add some documentation and example in the code.

Add mfences calls in spinlock_unlock_busy fix a bug on letty physical
hardware.

File size: 23.8 KB
RevLine 
[533]1/*
2 * soclib_mtty.c - soclib tty driver implementation.
3 *
4 * Author  Alain Greiner (2016,2017,2018)
5 *
6 * Copyright (c)  UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH..
9 *
10 * ALMOS-MKH. is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH. is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH.; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24
25#include <hal_kernel_types.h>
26#include <dev_txt.h>
27#include <chdev.h>
28#include <soclib_mtty.h>
29#include <remote_spinlock.h>
30#include <thread.h>
31#include <printk.h>
32#include <hal_special.h>
33
34#if (DEBUG_SYS_READ & 1)
35extern uint32_t  enter_tty_cmd_read;
36extern uint32_t  exit_tty_cmd_read;
37
38extern uint32_t  enter_tty_isr_read;
39extern uint32_t  exit_tty_isr_read;
40#endif
41
42#if (DEBUG_SYS_WRITE & 1)
43extern uint32_t  enter_tty_cmd_write;
44extern uint32_t  exit_tty_cmd_write;
45
46extern uint32_t  enter_tty_isr_write;
47extern uint32_t  exit_tty_isr_write;
48#endif
49
[539]50extern   chdev_directory_t    chdev_dir;  // allocated in the kernel_init.c file.
51extern   spinlock_t           txt0_lock;  // Initialized in kernel_init.c
[533]52////////////////////////////////////////////////////////////////////////////////////
53// These global variables implement the MTTY_RX  FIFOs (one per channel)
54////////////////////////////////////////////////////////////////////////////////////
55
56__attribute__((section(".kdata")))
[534]57mtty_fifo_t  mtty_rx_fifo[CONFIG_MAX_TXT_CHANNELS];
[533]58
59__attribute__((section(".kdata")))
[534]60mtty_fifo_t  mtty_tx_fifo[CONFIG_MAX_TXT_CHANNELS];
[533]61
62///////////////////////////////////////
63void soclib_mtty_init( chdev_t * chdev )
64{
65    xptr_t reg_xp;
66
67    // initialise function pointers in chdev
68    chdev->cmd = &soclib_mtty_cmd;
69    chdev->isr = &soclib_mtty_isr;
70    chdev->aux = &soclib_mtty_aux;
71
72    // get TTY channel and extended pointer on TTY peripheral base address
73    xptr_t   tty_xp  = chdev->base;
74    uint32_t channel = chdev->channel;
75    bool_t   is_rx   = chdev->is_rx;
76
77    // get SOCLIB_TTY device cluster and local pointer
78    cxy_t      tty_cxy = GET_CXY( tty_xp );
79    uint32_t * tty_ptr = GET_PTR( tty_xp );
80
81    // enable interruptions for RX but not for TX
[537]82    reg_xp = XPTR( tty_cxy , tty_ptr + MTTY_CONFIG );
[533]83    hal_remote_sw( reg_xp , MTTY_CONFIG_RX_ENABLE );
84
85    // reset relevant FIFO
86    if( is_rx )
87    {
[534]88        mtty_rx_fifo[channel].sts = 0;
89        mtty_rx_fifo[channel].ptr = 0;
90        mtty_rx_fifo[channel].ptw = 0;
[533]91    }
92    else
93    {
[534]94        mtty_tx_fifo[channel].sts = 0;
95        mtty_tx_fifo[channel].ptr = 0;
96        mtty_tx_fifo[channel].ptw = 0;
[533]97    }
98}  // end soclib_mtty_init()
99
100//////////////////////////////////////////////////////////////
101void __attribute__ ((noinline)) soclib_mtty_cmd( xptr_t th_xp )
102{
[534]103    mtty_fifo_t * fifo;     // MTTY_RX or MTTY_TX FIFO
[533]104    char         byte;     // byte value
105    uint32_t     done;     // number of bytes moved
106
107    // get client thread cluster and local pointer
108    cxy_t      th_cxy = GET_CXY( th_xp );
109    thread_t * th_ptr = GET_PTR( th_xp );
110
111    // get command arguments
112    uint32_t type     = hal_remote_lw ( XPTR( th_cxy , &th_ptr->txt_cmd.type   ) );
113    xptr_t   buf_xp   = hal_remote_lwd( XPTR( th_cxy , &th_ptr->txt_cmd.buf_xp ) );
114    uint32_t count    = hal_remote_lw ( XPTR( th_cxy , &th_ptr->txt_cmd.count  ) );
115    xptr_t   error_xp = XPTR( th_cxy , &th_ptr->txt_cmd.error );
116
117#if (DEBUG_SYS_READ & 1)
118if( type == TXT_READ) enter_tty_cmd_read = (uint32_t)hal_get_cycles();
119#endif
120
121#if (DEBUG_SYS_WRITE & 1)
122if( type == TXT_WRITE) enter_tty_cmd_write = (uint32_t)hal_get_cycles();
123#endif
124
125    // get TXT device cluster and pointers
126    xptr_t     dev_xp = (xptr_t)hal_remote_lwd( XPTR( th_cxy , &th_ptr->txt_cmd.dev_xp ) );
127    cxy_t      dev_cxy = GET_CXY( dev_xp );
128    chdev_t  * dev_ptr = GET_PTR( dev_xp );
129
130    // get cluster and pointers for SOCLIB_TTY peripheral base segment
131    xptr_t     tty_xp = (xptr_t)hal_remote_lwd( XPTR( dev_cxy , &dev_ptr->base ) );
132    cxy_t      tty_cxy = GET_CXY( tty_xp );
133    uint32_t * tty_ptr = GET_PTR( tty_xp );
134
135    // get TTY channel index and channel base address
136    uint32_t   channel = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->channel ) );
[537]137    uint32_t * base    = tty_ptr;
[533]138
139    ///////////////////////
140    if( type == TXT_WRITE )         // write bytes to MTTY_TX FIFO
141    {
[534]142        fifo = &mtty_tx_fifo[channel];
[533]143
144        done = 0;
145
146        while( done < count )
147        {
148            if( fifo->sts < MTTY_FIFO_DEPTH )   // put one byte to FIFO if TX_FIFO not full
149            {
150                // get one byte from command buffer
151                byte = hal_remote_lb( buf_xp + done );
152
153#if DEBUG_HAL_TXT_TX
154uint32_t tx_cycle = (uint32_t)hal_get_cycles();
155if( DEBUG_HAL_TXT_TX < tx_cycle )
156printk("\n[DBG] %s : thread %x put character <%c> to TXT%d_TX fifo / cycle %d\n",
157__FUNCTION__, CURRENT_THREAD, byte, channel, tx_cycle );
158#endif
159                // write byte to FIFO
160                fifo->data[fifo->ptw] = byte;
161
162                // prevent race
163                hal_fence();
164
165                // update FIFO state
166                fifo->ptw = (fifo->ptw + 1) % MTTY_FIFO_DEPTH;
167                hal_atomic_add( &fifo->sts , 1 );
168
169                // udate number of bytes moved
170                done++;
171
172                // enable TX_IRQ
[538]173                //      vci_multi_tty devices never raise TX IRQs
174                //      so the following instructions are useless
175                //      and moreover they kernel panic
176                // xptr_t config_xp = XPTR( tty_cxy , base + MTTY_CONFIG );
177                // uint32_t old = hal_remote_lw( config_xp );
178                // uint32_t new = old | MTTY_CONFIG_TX_ENABLE;
179                // hal_remote_atomic_cas( config_xp , old , new );
180                // hal_remote_sw( XPTR( tty_cxy , base + MTTY_CONFIG ) , MTTY_CONFIG_TX_ENABLE );
[533]181            }
182            else                                // block & deschedule if TX_FIFO full
183            {
184                // block on ISR
185                thread_block( XPTR( local_cxy , CURRENT_THREAD ) , THREAD_BLOCKED_ISR );
186
187                // deschedule
188                sched_yield( "MTTY_TX_FIFO full" ); 
189            }
190        }
191
192        // set error status in command and return
193        hal_remote_sw( error_xp , 0 );
194    }
195    ///////////////////////////
196    else if( type == TXT_READ )       // read bytes from MTTY_RX FIFO   
197    {
[534]198        fifo = &mtty_rx_fifo[channel];
[533]199
200        done = 0;
201
202        while( done < count )
203        {
204            if( fifo->sts > 0 )               // get byte from FIFO if not empty
205            {
206                // get one byte from FIFO
207                char byte = fifo->data[fifo->ptr];
208
209#if DEBUG_HAL_TXT_RX
210uint32_t rx_cycle = (uint32_t)hal_get_cycles();
211if( DEBUG_HAL_TXT_RX < rx_cycle )
212printk("\n[DBG] %s : thread %x get character <%c> from TXT%d_RX fifo / cycle %d\n",
213__FUNCTION__, CURRENT_THREAD, byte, channel, rx_cycle );
214#endif
215                // update FIFO state
216                fifo->ptr = (fifo->ptr + 1) % MTTY_FIFO_DEPTH;
217                hal_atomic_add( &fifo->sts , -1 );
218
219                // set byte to command buffer
220                hal_remote_sb( buf_xp + done , byte );
221
222                // udate number of bytes
223                done++;
224            }
225            else                             //  deschedule if FIFO empty
226            {
227                // block on ISR
228                thread_block( XPTR( local_cxy , CURRENT_THREAD ) , THREAD_BLOCKED_ISR );
229   
230                // deschedule
231                sched_yield( "MTTY_RX_FIFO empty" );
232            }
233        }  // end while
234
235        // set error status in command
236        hal_remote_sw( error_xp , 0 );
237    }
238    else
239    {
240        assert( false , __FUNCTION__ , "illegal TXT command\n" );
241    }
242
243#if (DEBUG_SYS_READ & 1)
244if( type == TXT_READ ) exit_tty_cmd_read = (uint32_t)hal_get_cycles();
245#endif
246
247#if (DEBUG_SYS_WRITE & 1)
248if( type == TXT_WRITE ) exit_tty_cmd_write = (uint32_t)hal_get_cycles();
249#endif
250
251}  // end soclib_mtty_cmd()
252
253/////////////////////////////////////////////////////////////////
254void __attribute__ ((noinline)) soclib_mtty_isr( chdev_t * chdev )
255{
256    thread_t   * server;            // pointer on TXT chdev server thread
257    lid_t        server_lid;        // local index of core running the server thread
258    uint32_t     channel;           // TXT chdev channel
259    bool_t       is_rx;             // TXT chdev direction
260    char         byte;              // byte value
261    xptr_t       owner_xp;          // extended pointer on TXT owner process
262    cxy_t        owner_cxy;         // TXT owner process cluster
263    process_t  * owner_ptr;         // local pointer on TXT owner process
264    pid_t        owner_pid;         // TXT owner process identifier
[534]265    mtty_fifo_t * fifo;              // pointer on MTTY_TX or MTTY_RX FIFO
[533]266    cxy_t        tty_cxy;           // soclib_mtty cluster
267    uint32_t   * tty_ptr;           // soclib_mtty segment base address
268    uint32_t   * base;              // soclib_mtty channel base address
269    xptr_t       status_xp;         // extended pointer on MTTY_STATUS register
270    xptr_t       write_xp;          // extended pointer on MTTY_WRITE register
271    xptr_t       read_xp;           // extended pointer on MTTY_READ register
272    xptr_t       parent_xp;         // extended pointer on parent process
273    cxy_t        parent_cxy;        // parent process cluster
274    process_t  * parent_ptr;        // local pointer on parent process
275    xptr_t       children_lock_xp;  // extended pointer on children processes lock
276    thread_t   * parent_main_ptr;   // extended pointer on parent process main thread
277    xptr_t       parent_main_xp;    // local pointer on parent process main thread
278
279    // get TXT chdev channel, direction and server thread
280    channel    = chdev->channel;
281    is_rx      = chdev->is_rx;
282    server     = chdev->server;
283    server_lid = server->core->lid;
284
285#if (DEBUG_SYS_READ & 1)
286if( is_rx ) enter_tty_isr_read = (uint32_t)hal_get_cycles();
287#endif
288
289#if (DEBUG_SYS_WRITE & 1)
290if( is_rx == 0 ) enter_tty_isr_write = (uint32_t)hal_get_cycles();
291#endif
292
293#if DEBUG_HAL_TXT_RX
294uint32_t rx_cycle = (uint32_t)hal_get_cycles();
295#endif
296
297#if DEBUG_HAL_TXT_TX
298uint32_t tx_cycle = (uint32_t)hal_get_cycles();
299#endif
300
301    // get SOCLIB_TTY peripheral cluster and local pointer
302    tty_cxy = GET_CXY( chdev->base );
303    tty_ptr = GET_PTR( chdev->base );
304
305    // get channel base address
[537]306    base    = tty_ptr;
[533]307
308    // get extended pointer on TTY registers
309    status_xp = XPTR( tty_cxy , base + MTTY_STATUS );
310    write_xp  = XPTR( tty_cxy , base + MTTY_WRITE );
311    read_xp   = XPTR( tty_cxy , base + MTTY_READ );
312
313    /////////////////////////// handle RX //////////////////////
314    if( is_rx )
315    {
[534]316        fifo = &mtty_rx_fifo[channel];
[533]317
318        // try to move bytes until MTTY_READ register empty
319        while( hal_remote_lw( status_xp ) & MTTY_STATUS_RX_FULL )   
320        {
321            // get one byte from MTTY_READ register & acknowledge RX_IRQ
322            byte = (char)hal_remote_lb( read_xp );
323
[540]324            // Ignore Carriage Returns
325            if( byte == 0xD )
326            {
327                continue;
328            }
329
330            // This is the MTTY multiplexing
331            // When a extended ASCII char are received (typing Ctrl-Shift-U then 100+n for example on the terminal)
332            // Two characters are received : 0xFFFFFFc4 then 0xFFFFFF80 + n
333            // When this second char is received, it is considered a metachar that determines the tty dest number
334            // Thus, if you want to make tty 5 the new target, type Ctrl+Shift+U then 105
335            // Now all keystrokes IRQs will be handled by the server DEV thread
336            // associated to RX channel number 5
337            if( (byte & 0xFF) > 0x80 && (byte & 0xFF) <= 0x89 )
338            {
339                // Disable MTTY IRQ for the core owning
340                // the current channel's server DEV thread
341                dev_pic_disable_irq( server_lid, XPTR( local_cxy , chdev ) );
342               
343                int         tty_destnb  = (int)(byte & 0xFF) - 0x80;
344                chdev_t *   new_chdev   = chdev_dir.txt_rx[tty_destnb];
345                lid_t       new_lid     = new_chdev->server->core->lid;
346
347                // Bind MTTY IRQ to the core owning the new channel's server DEV thread
348                dev_pic_bind_irq( new_lid , new_chdev );               
349
350                // Enable MTTY IRQ for the core owning
351                // the new channel's server DEV thread
352                dev_pic_enable_irq( new_lid , XPTR( local_cxy , new_chdev ) );
353
354                channel    = new_chdev->channel;
355                is_rx      = new_chdev->is_rx;
356                server     = new_chdev->server;
357                server_lid = new_lid;
358                fifo = &mtty_rx_fifo[channel];
359                continue;
360            }
361
[533]362            // filter special character ^Z  => block TXT owner process
363            if( byte == 0x1A ) 
364            {
365
366#if DEBUG_HAL_TXT_RX
367if( DEBUG_HAL_TXT_RX < rx_cycle )
368printk("\n[DBG] %s : read ^Z character from TXT%d\n", __FUNCTION__, channel );
369#endif
370                // get pointers on TXT owner process in owner cluster
371                owner_xp  = process_txt_get_owner( channel );
372               
373                // check process exist
374                assert( (owner_xp != XPTR_NULL) , __FUNCTION__, 
375                "TXT owner process not found\n" );
376
377                // get relevant infos on TXT owner process
378                owner_cxy = GET_CXY( owner_xp );
379                owner_ptr = GET_PTR( owner_xp );
380                owner_pid = hal_remote_lw( XPTR( owner_cxy , &owner_ptr->pid ) );
381
382                // block TXT owner process only if it is not the INIT process
383                if( owner_pid != 1 )
384                {
385                    // get parent process descriptor pointers
386                    parent_xp  = hal_remote_lwd( XPTR( owner_cxy , &owner_ptr->parent_xp ) );
387                    parent_cxy = GET_CXY( parent_xp );
388                    parent_ptr = GET_PTR( parent_xp );
389
390                    // get extended pointer on lock protecting children list in parent process
391                    children_lock_xp = XPTR( parent_cxy , &parent_ptr->children_lock ); 
392
393                    // get pointers on the parent process main thread
394                    parent_main_ptr = hal_remote_lpt(XPTR(parent_cxy,&parent_ptr->th_tbl[0])); 
395                    parent_main_xp  = XPTR( parent_cxy , parent_main_ptr );
396
397                    // transfer TXT ownership
398                    process_txt_transfer_ownership( owner_xp );
399
400                    // block all threads in all clusters, but the main thread
401                    process_sigaction( owner_pid , BLOCK_ALL_THREADS );
402
403                    // block the main thread
404                    xptr_t main_xp = XPTR( owner_cxy , &owner_ptr->th_tbl[0] );
405                    thread_block( main_xp , THREAD_BLOCKED_GLOBAL );
406
407                    // atomically update owner process termination state
408                    hal_remote_atomic_or( XPTR( owner_cxy , &owner_ptr->term_state ) ,
409                                          PROCESS_TERM_STOP );
410
411                    // take the children lock and unblock the parent process main thread
412                    remote_spinlock_lock( children_lock_xp );
413                    thread_unblock( parent_main_xp , THREAD_BLOCKED_WAIT );
414                    remote_spinlock_unlock( children_lock_xp );
415
416                    return;
417                }
418            }
419
420            // filter special character ^C  => kill TXT owner process
421            if( byte == 0x03 )
422            {
423
424#if DEBUG_HAL_TXT_RX
425if( DEBUG_HAL_TXT_RX < rx_cycle )
426printk("\n[DBG] %s : read ^C character from TXT%d\n", __FUNCTION__, channel );
427#endif
428                // get pointer on TXT owner process in owner cluster
429                owner_xp  = process_txt_get_owner( channel );
430
431                // check process exist
432                assert( (owner_xp != XPTR_NULL) , __FUNCTION__,
433                "TXT owner process not found\n" );
434
435                // get relevant infos on TXT owner process
436                owner_cxy = GET_CXY( owner_xp );
437                owner_ptr = GET_PTR( owner_xp );
438                owner_pid = hal_remote_lw( XPTR( owner_cxy , &owner_ptr->pid ) );
439
440                // kill TXT owner process only if it is not the INIT process
441                if( owner_pid != 1 )
442                {
443                    // get parent process descriptor pointers
444                    parent_xp  = hal_remote_lwd( XPTR( owner_cxy , &owner_ptr->parent_xp ) );
445                    parent_cxy = GET_CXY( parent_xp );
446                    parent_ptr = GET_PTR( parent_xp );
447
448                    // get extended pointer on lock protecting children list in parent process
449                    children_lock_xp = XPTR( parent_cxy , &parent_ptr->children_lock ); 
450
451                    // get pointers on the parent process main thread
452                    parent_main_ptr = hal_remote_lpt(XPTR(parent_cxy,&parent_ptr->th_tbl[0])); 
453                    parent_main_xp  = XPTR( parent_cxy , parent_main_ptr );
454
455                    // remove process from TXT list
456                    process_txt_detach( owner_xp );
457
458                    // mark for delete all thread in all clusters, but the main
459                    process_sigaction( owner_pid , DELETE_ALL_THREADS );
460               
461                    // block main thread
462                    xptr_t main_xp = XPTR( owner_cxy , &owner_ptr->th_tbl[0] );
463                    thread_block( main_xp , THREAD_BLOCKED_GLOBAL );
464
465                    // atomically update owner process termination state
466                    hal_remote_atomic_or( XPTR( owner_cxy , &owner_ptr->term_state ) ,
467                                          PROCESS_TERM_KILL );
468
469                    // take the children lock and unblock the parent process main thread
470                    remote_spinlock_lock( children_lock_xp );
471                    thread_unblock( parent_main_xp , THREAD_BLOCKED_WAIT );
472                    remote_spinlock_unlock( children_lock_xp );
473
474                    return;
475                }
476            }
477
478            // write byte in MTTY_RX FIFO if not full / discard byte if full
479            if ( fifo->sts < MTTY_FIFO_DEPTH )
480            {
481
482#if DEBUG_HAL_TXT_RX
483if( DEBUG_HAL_TXT_RX < rx_cycle )
484printk("\n[DBG] %s : put character <%c> to TXT%d_RX fifo\n",
485__FUNCTION__, byte, channel );
486#endif
487                // store byte into FIFO
488                fifo->data[fifo->ptw] = (char)byte; 
489
490                // avoid race
491                hal_fence();
492
493                // update RX_FIFO state
494                fifo->ptw = (fifo->ptw + 1) % MTTY_FIFO_DEPTH;
495                hal_atomic_add( &fifo->sts , 1 );
496
497                // unblock TXT_RX server thread
498                thread_unblock( XPTR( local_cxy , server ) , THREAD_BLOCKED_ISR );
499
500                // send IPI to core running server thread
501                dev_pic_send_ipi( local_cxy , server_lid );
502            }
503            else
504            {
505                printk("\n[WARNING] %s : MTTY_RX_FIFO[%d] full => discard character <%x>\n",
506                __FUNCTION__, channel, (uint32_t)byte );
507            }
508        }  // end while MTTY_READ register full
509
510    }  // end RX
511
512    ///////////////////////  handle TX  /////////////////////////////
513    else
514    {
[534]515        fifo = &mtty_tx_fifo[channel];
[533]516
517        // try to move bytes until TX_FIFO empty
518        while( fifo->sts > 0 )
519        {
520            // write one byte to MTTY_WRITE register if empty / exit loop if full
521            if( (hal_remote_lw( status_xp ) & MTTY_STATUS_TX_FULL) == 0 ) 
522            {
523                // get one byte from TX_FIFO
524                byte = fifo->data[fifo->ptr];
525
526#if DEBUG_HAL_TXT_TX
527if( DEBUG_HAL_TXT_TX < tx_cycle )
528printk("\n[DBG] %s : get character <%c> from TXT%d_TX fifo\n",
529__FUNCTION__, byte, channel );
530#endif
531                // update TX_FIFO state
532                fifo->ptr = (fifo->ptr + 1) % MTTY_FIFO_DEPTH;
533                hal_atomic_add( &fifo->sts , -1 );
534
535                // write byte to MTTY_WRITE register & acknowledge TX_IRQ
536                hal_remote_sb( write_xp , byte );
537            }
538        }
539
540        // disable TX_IRQ
[538]541        //      vci_multi_tty devices never raise TX IRQs
542        //      so the following instructions are useless
543        //      and moreover they kernel panic
544        // xptr_t config_xp = XPTR( tty_cxy , base + MTTY_CONFIG );
545        // uint32_t old = hal_remote_lw( config_xp );
546        // uint32_t new = old & ~(MTTY_CONFIG_TX_ENABLE);
547        // hal_remote_atomic_cas( config_xp , old , new );
548        // hal_remote_sw( XPTR( tty_cxy , base + MTTY_CONFIG ) , 0 );
[533]549
550        // unblock TXT_TX server thread
551        thread_unblock( XPTR( local_cxy , server ) , THREAD_BLOCKED_ISR );
552
553        // send IPI to core running server thread
554        dev_pic_send_ipi( local_cxy , server_lid );
555
556    }  // end TX
557
558    hal_fence();
559
560#if (DEBUG_SYS_READ & 1)
561if( is_rx ) exit_tty_isr_read = (uint32_t)hal_get_cycles();
562#endif
563
564#if (DEBUG_SYS_WRITE & 1)
565if( is_rx == 0 ) exit_tty_isr_write = (uint32_t)hal_get_cycles();
566#endif
567
568}  // end soclib_mtty_isr()
569
570/////////////////////////////////////////////////////////////
571void __attribute__ ((noinline)) soclib_mtty_aux( void * args )
572{
573    xptr_t     dev_xp = ((txt_sync_args_t *)args)->dev_xp;
574    char     * buffer = ((txt_sync_args_t *)args)->buffer;
575    uint32_t   count  = ((txt_sync_args_t *)args)->count;
[539]576    uint32_t   channel = ((txt_sync_args_t *)args)->channel;
[533]577   
578    // get TXT0 chdev cluster and local pointer
579    cxy_t     dev_cxy = GET_CXY( dev_xp );
580    chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );
581
582    // get extended pointer on TTY channel base address
583    xptr_t tty_xp = (xptr_t)hal_remote_lwd( XPTR( dev_cxy , &dev_ptr->base ) );
584
585    // get TTY channel segment cluster and local pointer
586    cxy_t      tty_cxy = GET_CXY( tty_xp );
587    uint32_t * tty_ptr = (uint32_t *)GET_PTR( tty_xp );
588
589    // get extended pointers on MTTY_WRITE & MTTY_STATUS registers
590    xptr_t write_xp  = XPTR( tty_cxy , tty_ptr + MTTY_WRITE );
591    xptr_t status_xp = XPTR( tty_cxy , tty_ptr + MTTY_STATUS );
592
593    // loop on characters (busy waiting policy)
[540]594    uint32_t   i;
[533]595    for( i = 0 ; i < count ; i++ )
596    {
[539]597        // This is the MTTY multiplexing
[540]598        // Before each character, we send the destination (RX) TTY number for this char.
[539]599        // The two bytes (dest number + char) must be sent consecutively,
600        // so to guarantee this atomicity, we use a lock to prevent other
601        // concurrent server DEV threads to write a byte in between our two bytes
602
603        // Send the destination TTY number
[540]604        // HACK: Remove this on the Lety physical prototype.
605        // This 'if' is here so that the kernel messages in simulation are readable
606        bool_t empty = false;
607        if (channel > 0) {
608            // For examples, "Hello" would appear "0H0e0l0l0o" on the simulation terminal
609            do {
610                // get MTTY_STATUS
611                uint32_t status = hal_remote_lw( status_xp );
612                empty  = ( (status & MTTY_STATUS_TX_FULL) == 0 );
[533]613
[540]614                // transfer one byte if TX buffer empty
615                if ( empty ) {
616                    hal_remote_sb( write_xp , channel + '0' );
617                }
618            } while ( empty == false );
[539]619        }
620
621        // Send the character
[540]622        do {
[539]623            // get MTTY_STATUS
[540]624            uint32_t status = hal_remote_lw( status_xp );
[539]625            empty  = ( (status & MTTY_STATUS_TX_FULL) == 0 );
626
627            // transfer one byte if TX buffer empty
[540]628            if ( empty ) {
629                hal_remote_sb( write_xp , buffer[i] );
630            }
631        } while ( empty == false );
[533]632    }
633}  // end soclib_mtty_aux()
634
635
636
Note: See TracBrowser for help on using the repository browser.