source: trunk/hal/tsar_mips32/drivers/soclib_tty.c @ 625

Last change on this file since 625 was 625, checked in by alain, 5 years ago

Fix a bug in the vmm_remove_vseg() function: the physical pages
associated to an user DATA vseg were released to the kernel when
the target process descriptor was in the reference cluster.
This physical pages release should be done only when the page
forks counter value is zero.
All other modifications are cosmetic.

File size: 20.4 KB
RevLine 
[75]1/*
2 * soclib_tty.c - soclib tty driver implementation.
3 *
[451]4 * Author  Alain Greiner (2016,2017,2018)
[75]5 *
6 * Copyright (c)  UPMC Sorbonne Universites
7 *
[570]8 * This file is part of ALMOS-MKH.
[75]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 *
[570]14 * ALMOS-MKH is distributed in the hope that it will be useful, but
[75]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
[570]20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
[75]21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
[451]24
25#include <hal_kernel_types.h>
[75]26#include <dev_txt.h>
27#include <chdev.h>
28#include <soclib_tty.h>
29#include <thread.h>
[407]30#include <printk.h>
[75]31#include <hal_special.h>
32
[438]33#if (DEBUG_SYS_READ & 1)
[435]34extern uint32_t  enter_tty_cmd_read;
35extern uint32_t  exit_tty_cmd_read;
[407]36
[435]37extern uint32_t  enter_tty_isr_read;
38extern uint32_t  exit_tty_isr_read;
[407]39#endif
40
[438]41#if (DEBUG_SYS_WRITE & 1)
[435]42extern uint32_t  enter_tty_cmd_write;
43extern uint32_t  exit_tty_cmd_write;
44
45extern uint32_t  enter_tty_isr_write;
46extern uint32_t  exit_tty_isr_write;
47#endif
48
[436]49////////////////////////////////////////////////////////////////////////////////////
50// These global variables implement the TTY_RX  FIFOs (one per channel)
51////////////////////////////////////////////////////////////////////////////////////
[570]52// Implementation note:
53// We allocate - in each cluster - two arrays of FIFOs containing as many entries
54// as the total number of TXT channels, but all entries are not used in all
55// clusters: for a given cluster K, a given entry corresponding to a given channel
56// and a given direction is only used if the associated chdev is in cluster K.
57// With this policy, the driver can ignore the actual placement of chdevs.
58////////////////////////////////////////////////////////////////////////////////////
[436]59
60__attribute__((section(".kdata")))
61tty_fifo_t  tty_rx_fifo[CONFIG_MAX_TXT_CHANNELS];
62
63__attribute__((section(".kdata")))
64tty_fifo_t  tty_tx_fifo[CONFIG_MAX_TXT_CHANNELS];
65
[75]66///////////////////////////////////////
67void soclib_tty_init( chdev_t * chdev )
68{
[407]69    xptr_t reg_xp;
70
[436]71    // initialise function pointers in chdev
[77]72    chdev->cmd = &soclib_tty_cmd;
73    chdev->isr = &soclib_tty_isr;
[407]74    chdev->aux = &soclib_tty_aux;
[77]75
[407]76    // get TTY channel and extended pointer on TTY peripheral base address
77    xptr_t   tty_xp  = chdev->base;
78    uint32_t channel = chdev->channel;
[436]79    bool_t   is_rx   = chdev->is_rx;
[75]80
81    // get SOCLIB_TTY device cluster and local pointer
82    cxy_t      tty_cxy = GET_CXY( tty_xp );
[435]83    uint32_t * tty_ptr = GET_PTR( tty_xp );
[75]84
[435]85    // set TTY_RX_IRQ_ENABLE
[407]86    reg_xp = XPTR( tty_cxy , tty_ptr + (channel * TTY_SPAN) + TTY_RX_IRQ_ENABLE );
[570]87    hal_remote_s32( reg_xp , 1 );
[407]88
89    // reset TTY_TX_IRQ_ENABLE
90    reg_xp = XPTR( tty_cxy , tty_ptr + (channel * TTY_SPAN) + TTY_TX_IRQ_ENABLE );
[570]91    hal_remote_s32( reg_xp , 0 );
[75]92
[436]93    // reset relevant FIFO
94    if( is_rx )
95    {
96        tty_rx_fifo[channel].sts = 0;
97        tty_rx_fifo[channel].ptr = 0;
98        tty_rx_fifo[channel].ptw = 0;
99    }
100    else
101    {
102        tty_tx_fifo[channel].sts = 0;
103        tty_tx_fifo[channel].ptr = 0;
104        tty_tx_fifo[channel].ptw = 0;
105    }
106}  // end soclib_tty_init()
107
[75]108//////////////////////////////////////////////////////////////
109void __attribute__ ((noinline)) soclib_tty_cmd( xptr_t th_xp )
110{
[436]111    tty_fifo_t * fifo;     // TTY_RX or TTY_TX FIFO
112    char         byte;     // byte value
113    uint32_t     done;     // number of bytes moved
[407]114
[436]115    // get client thread cluster and local pointer
116    cxy_t      th_cxy = GET_CXY( th_xp );
117    thread_t * th_ptr = GET_PTR( th_xp );
118
119    // get command arguments
[570]120    uint32_t type     = hal_remote_l32 ( XPTR( th_cxy , &th_ptr->txt_cmd.type   ) );
121    xptr_t   buf_xp   = hal_remote_l64( XPTR( th_cxy , &th_ptr->txt_cmd.buf_xp ) );
122    uint32_t count    = hal_remote_l32 ( XPTR( th_cxy , &th_ptr->txt_cmd.count  ) );
[436]123    xptr_t   error_xp = XPTR( th_cxy , &th_ptr->txt_cmd.error );
124
[438]125#if (DEBUG_SYS_READ & 1)
[435]126if( type == TXT_READ) enter_tty_cmd_read = (uint32_t)hal_get_cycles();
[407]127#endif
128
[438]129#if (DEBUG_SYS_WRITE & 1)
[435]130if( type == TXT_WRITE) enter_tty_cmd_write = (uint32_t)hal_get_cycles();
[432]131#endif
[407]132
[619]133#if( DEBUG_HAL_TXT_TX || DEBUG_HAL_TXT_RX )
134thread_t * this = CURRENT_THREAD;
135#endif
136
[440]137    // get TXT device cluster and pointers
[570]138    xptr_t     dev_xp = (xptr_t)hal_remote_l64( XPTR( th_cxy , &th_ptr->txt_cmd.dev_xp ) );
[440]139    cxy_t      dev_cxy = GET_CXY( dev_xp );
140    chdev_t  * dev_ptr = GET_PTR( dev_xp );
[436]141
[440]142    // get cluster and pointers for SOCLIB_TTY peripheral base segment
[570]143    xptr_t     tty_xp = (xptr_t)hal_remote_l64( XPTR( dev_cxy , &dev_ptr->base ) );
[436]144    cxy_t      tty_cxy = GET_CXY( tty_xp );
145    uint32_t * tty_ptr = GET_PTR( tty_xp );
146
147    // get TTY channel index and channel base address
[570]148    uint32_t   channel = hal_remote_l32( XPTR( dev_cxy , &dev_ptr->channel ) );
[436]149    uint32_t * base    = tty_ptr + TTY_SPAN * channel;
150
151    ///////////////////////
152    if( type == TXT_WRITE )         // write bytes to TTY_TX FIFO
[435]153    {
[436]154        fifo = &tty_tx_fifo[channel];
[75]155
[436]156        done = 0;
[75]157
[436]158        while( done < count )
159        {
160            if( fifo->sts < TTY_FIFO_DEPTH )   // put one byte to FIFO if TX_FIFO not full
161            {
162                // get one byte from command buffer
163                byte = hal_remote_lb( buf_xp + done );
[75]164
[451]165#if DEBUG_HAL_TXT_TX
[619]166uint32_t   tx_cycle = (uint32_t)hal_get_cycles();
[451]167if( DEBUG_HAL_TXT_TX < tx_cycle )
[619]168printk("\n[%s] thread[%x,%x] put character <%c> to TXT%d_TX fifo / cycle %d\n",
169__FUNCTION__, this->process->pid, this->trdid, byte, channel, tx_cycle );
[451]170#endif
[436]171                // write byte to FIFO
172                fifo->data[fifo->ptw] = byte;
[75]173
[436]174                // prevent race
175                hal_fence();
[75]176
[436]177                // update FIFO state
178                fifo->ptw = (fifo->ptw + 1) % TTY_FIFO_DEPTH;
179                hal_atomic_add( &fifo->sts , 1 );
[75]180
[436]181                // udate number of bytes moved
182                done++;
[75]183
[436]184                // enable TX_IRQ
[570]185                hal_remote_s32( XPTR( tty_cxy , base + TTY_TX_IRQ_ENABLE ) , 1 );
[436]186            }
187            else                                // block & deschedule if TX_FIFO full
188            {
189                // block on ISR
190                thread_block( XPTR( local_cxy , CURRENT_THREAD ) , THREAD_BLOCKED_ISR );
191
192                // deschedule
193                sched_yield( "TTY_TX_FIFO full" ); 
194            }
195        }
196
197        // set error status in command and return
[570]198        hal_remote_s32( error_xp , 0 );
[435]199    }
[436]200    ///////////////////////////
[619]201    else if( type == TXT_READ )       // read several bytes from TTY_RX FIFO   
[435]202    {
[436]203        fifo = &tty_rx_fifo[channel];
[75]204
[436]205        done = 0;
206
207        while( done < count )
208        {
209            if( fifo->sts > 0 )               // get byte from FIFO if not empty
210            {
211                // get one byte from FIFO
212                char byte = fifo->data[fifo->ptr];
213
[451]214#if DEBUG_HAL_TXT_RX
215uint32_t rx_cycle = (uint32_t)hal_get_cycles();
216if( DEBUG_HAL_TXT_RX < rx_cycle )
[619]217printk("\n[%s] thread[%x,%x] get character <%c> from TXT%d_RX fifo / cycle %d\n",
218__FUNCTION__, this->process->pid, this->trdid, byte, channel, rx_cycle );
[451]219#endif
[436]220                // update FIFO state
221                fifo->ptr = (fifo->ptr + 1) % TTY_FIFO_DEPTH;
222                hal_atomic_add( &fifo->sts , -1 );
223
224                // set byte to command buffer
225                hal_remote_sb( buf_xp + done , byte );
226
227                // udate number of bytes
228                done++;
229            }
230            else                             //  deschedule if FIFO empty
231            {
232                // block on ISR
233                thread_block( XPTR( local_cxy , CURRENT_THREAD ) , THREAD_BLOCKED_ISR );
234   
235                // deschedule
[446]236                sched_yield( "TTY_RX_FIFO empty" );
[436]237            }
238        }  // end while
239
240        // set error status in command
[570]241        hal_remote_s32( error_xp , 0 );
[435]242    }
243    else
244    {
[492]245        assert( false , "illegal TXT command\n" );
[435]246    }
247
[438]248#if (DEBUG_SYS_READ & 1)
[435]249if( type == TXT_READ ) exit_tty_cmd_read = (uint32_t)hal_get_cycles();
[407]250#endif
251
[438]252#if (DEBUG_SYS_WRITE & 1)
[435]253if( type == TXT_WRITE ) exit_tty_cmd_write = (uint32_t)hal_get_cycles();
254#endif
255
[407]256}  // end soclib_tty_cmd()
257
[75]258/////////////////////////////////////////////////////////////////
259void __attribute__ ((noinline)) soclib_tty_isr( chdev_t * chdev )
260{
[446]261    thread_t   * server;            // pointer on TXT chdev server thread
262    lid_t        server_lid;        // local index of core running the server thread
263    uint32_t     channel;           // TXT chdev channel
264    bool_t       is_rx;             // TXT chdev direction
265    char         byte;              // byte value
266    xptr_t       owner_xp;          // extended pointer on TXT owner process
267    cxy_t        owner_cxy;         // TXT owner process cluster
268    process_t  * owner_ptr;         // local pointer on TXT owner process
269    pid_t        owner_pid;         // TXT owner process identifier
270    tty_fifo_t * fifo;              // pointer on TTY_TX or TTY_RX FIFO
271    cxy_t        tty_cxy;           // soclib_tty cluster
272    uint32_t   * tty_ptr;           // soclib_tty segment base address
273    uint32_t   * base;              // soclib_tty channel base address
274    xptr_t       status_xp;         // extended pointer on TTY_STATUS register
275    xptr_t       write_xp;          // extended pointer on TTY_WRITE register
276    xptr_t       read_xp;           // extended pointer on TTY_READ register
277    xptr_t       parent_xp;         // extended pointer on parent process
278    cxy_t        parent_cxy;        // parent process cluster
279    process_t  * parent_ptr;        // local pointer on parent process
280    thread_t   * parent_main_ptr;   // extended pointer on parent process main thread
281    xptr_t       parent_main_xp;    // local pointer on parent process main thread
[75]282
[457]283    // get TXT chdev channel, direction, server thread, and server core
[436]284    channel    = chdev->channel;
285    is_rx      = chdev->is_rx;
286    server     = chdev->server;
287    server_lid = server->core->lid;
288
[438]289#if (DEBUG_SYS_READ & 1)
[436]290if( is_rx ) enter_tty_isr_read = (uint32_t)hal_get_cycles();
[407]291#endif
292
[438]293#if (DEBUG_SYS_WRITE & 1)
[436]294if( is_rx == 0 ) enter_tty_isr_write = (uint32_t)hal_get_cycles();
[435]295#endif
296
[438]297#if DEBUG_HAL_TXT_RX
[446]298uint32_t rx_cycle = (uint32_t)hal_get_cycles();
[432]299#endif
300
[438]301#if DEBUG_HAL_TXT_TX
[446]302uint32_t tx_cycle = (uint32_t)hal_get_cycles();
[436]303#endif
[75]304
[424]305    // get SOCLIB_TTY peripheral cluster and local pointer
[436]306    tty_cxy = GET_CXY( chdev->base );
307    tty_ptr = GET_PTR( chdev->base );
[424]308
309    // get channel base address
[436]310    base    = tty_ptr + TTY_SPAN * channel;
[424]311
312    // get extended pointer on TTY registers
313    status_xp = XPTR( tty_cxy , base + TTY_STATUS );
314    write_xp  = XPTR( tty_cxy , base + TTY_WRITE );
315    read_xp   = XPTR( tty_cxy , base + TTY_READ );
316
[436]317    /////////////////////////// handle RX //////////////////////
318    if( is_rx )
[424]319    {
[436]320        fifo = &tty_rx_fifo[channel];
[424]321
[436]322        // try to move bytes until TTY_READ register empty
[570]323        while( hal_remote_l32( status_xp ) & TTY_STATUS_RX_FULL )   
[435]324        {
[436]325            // get one byte from TTY_READ register & acknowledge RX_IRQ
326            byte = (char)hal_remote_lb( read_xp );
[424]327
[446]328            // filter special character ^Z  => block TXT owner process
[436]329            if( byte == 0x1A ) 
330            {
[446]331
332#if DEBUG_HAL_TXT_RX
333if( DEBUG_HAL_TXT_RX < rx_cycle )
[619]334printk("\n[%s] read ^Z character from TXT%d\n", __FUNCTION__, channel );
[446]335#endif
[436]336                // get pointers on TXT owner process in owner cluster
337                owner_xp  = process_txt_get_owner( channel );
338               
339                // check process exist
[492]340                assert( (owner_xp != XPTR_NULL) ,
[436]341                "TXT owner process not found\n" );
[435]342
[446]343                // get relevant infos on TXT owner process
[436]344                owner_cxy = GET_CXY( owner_xp );
345                owner_ptr = GET_PTR( owner_xp );
[570]346                owner_pid = hal_remote_l32( XPTR( owner_cxy , &owner_ptr->pid ) );
[424]347
[625]348// TXT owner cannot be the INIT process
349assert( (owner_pid != 1) , "INIT process cannot be the TXT owner" );
[446]350
[625]351                // get parent process descriptor pointers
352                parent_xp  = hal_remote_l64( XPTR( owner_cxy , &owner_ptr->parent_xp ) );
353                parent_cxy = GET_CXY( parent_xp );
354                parent_ptr = GET_PTR( parent_xp );
[446]355
[625]356                // get pointers on the parent process main thread
357                parent_main_ptr = hal_remote_lpt(XPTR(parent_cxy,&parent_ptr->th_tbl[0])); 
358                parent_main_xp  = XPTR( parent_cxy , parent_main_ptr );
[446]359
[625]360                // transfer TXT ownership
361                process_txt_transfer_ownership( owner_xp );
[424]362
[625]363                // mark for block all threads in all clusters, but the main
364                process_sigaction( owner_pid , BLOCK_ALL_THREADS );
[446]365
[625]366                // block the main thread
367                xptr_t main_xp = XPTR( owner_cxy , &owner_ptr->th_tbl[0] );
368                thread_block( main_xp , THREAD_BLOCKED_GLOBAL );
[446]369
[625]370                // atomically update owner process termination state
371                hal_remote_atomic_or( XPTR( owner_cxy , &owner_ptr->term_state ) ,
372                                      PROCESS_TERM_STOP );
[446]373
[625]374                // unblock the parent process main thread
375                thread_unblock( parent_main_xp , THREAD_BLOCKED_WAIT );
376
377                return;
[436]378            }
379
[446]380            // filter special character ^C  => kill TXT owner process
[436]381            if( byte == 0x03 )
382            {
[446]383
384#if DEBUG_HAL_TXT_RX
385if( DEBUG_HAL_TXT_RX < rx_cycle )
[619]386printk("\n[%s] read ^C character from TXT%d\n", __FUNCTION__, channel );
[446]387#endif
[440]388                // get pointer on TXT owner process in owner cluster
[436]389                owner_xp  = process_txt_get_owner( channel );
390
[625]391// check process exist
392assert( (owner_xp != XPTR_NULL) , "TXT owner process not found\n" );
[436]393
394                // get relevant infos on TXT owner process
395                owner_cxy = GET_CXY( owner_xp );
396                owner_ptr = GET_PTR( owner_xp );
[570]397                owner_pid = hal_remote_l32( XPTR( owner_cxy , &owner_ptr->pid ) );
[436]398
[625]399// TXT owner cannot be the INIT process
400assert( (owner_pid != 1) , "INIT process cannot be the TXT owner" );
[446]401
[625]402#if DEBUG_HAL_TXT_RX
403if( DEBUG_HAL_TXT_RX < rx_cycle )
404printk("\n[%s] TXT%d owner is process %x\n",
405__FUNCTION__, channel, owner_pid );
406#endif
407                // get parent process descriptor pointers
408                parent_xp  = hal_remote_l64( XPTR( owner_cxy , &owner_ptr->parent_xp ) );
409                parent_cxy = GET_CXY( parent_xp );
410                parent_ptr = GET_PTR( parent_xp );
[446]411
[625]412                // get pointers on the parent process main thread
413                parent_main_ptr = hal_remote_lpt(XPTR(parent_cxy,&parent_ptr->th_tbl[0])); 
414                parent_main_xp  = XPTR( parent_cxy , parent_main_ptr );
[436]415
[625]416                // transfer TXT ownership
417                process_txt_transfer_ownership( owner_xp );
418
419                // remove process from TXT list
420                // process_txt_detach( owner_xp );
421
422                // mark for delete all thread in all clusters, but the main
423                process_sigaction( owner_pid , DELETE_ALL_THREADS );
[435]424               
[625]425#if DEBUG_HAL_TXT_RX
426if( DEBUG_HAL_TXT_RX < rx_cycle )
427printk("\n[%s] marked for delete all threads of process but main\n",
428__FUNCTION__, owner_pid );
429#endif
430                // block main thread
431                xptr_t main_xp = XPTR( owner_cxy , &owner_ptr->th_tbl[0] );
432                thread_block( main_xp , THREAD_BLOCKED_GLOBAL );
[435]433
[625]434#if DEBUG_HAL_TXT_RX
435if( DEBUG_HAL_TXT_RX < rx_cycle )
436printk("\n[%s] blocked process %x main thread\n",
437__FUNCTION__, owner_pid );
438#endif
[446]439
[625]440                // atomically update owner process termination state
441                hal_remote_atomic_or( XPTR( owner_cxy , &owner_ptr->term_state ) ,
442                                      PROCESS_TERM_KILL );
[446]443
[625]444                // unblock the parent process main thread
445                thread_unblock( parent_main_xp , THREAD_BLOCKED_WAIT );
446
447#if DEBUG_HAL_TXT_RX
448if( DEBUG_HAL_TXT_RX < rx_cycle )
449printk("\n[%s] unblocked parent process %x main thread\n",
450__FUNCTION__, hal_remote_l32( XPTR( parent_cxy , &parent_ptr->pid) ) );
451#endif
452                return;
[436]453            }
[424]454
[436]455            // write byte in TTY_RX FIFO if not full / discard byte if full
456            if ( fifo->sts < TTY_FIFO_DEPTH )
457            {
[446]458
459#if DEBUG_HAL_TXT_RX
460if( DEBUG_HAL_TXT_RX < rx_cycle )
[619]461printk("\n[%s] put character <%c> to TXT%d_RX fifo\n",
[451]462__FUNCTION__, byte, channel );
[446]463#endif
[436]464                // store byte into FIFO
465                fifo->data[fifo->ptw] = (char)byte; 
466
467                // avoid race
468                hal_fence();
469
470                // update RX_FIFO state
471                fifo->ptw = (fifo->ptw + 1) % TTY_FIFO_DEPTH;
472                hal_atomic_add( &fifo->sts , 1 );
473
474                // unblock TXT_RX server thread
475                thread_unblock( XPTR( local_cxy , server ) , THREAD_BLOCKED_ISR );
476
[457]477                // send IPI to core running server thread if required
478                if( server_lid != CURRENT_THREAD->core->lid )
479                {
480                    dev_pic_send_ipi( local_cxy , server_lid );
481                }
[436]482            }
483            else
484            {
485                printk("\n[WARNING] %s : TTY_RX_FIFO[%d] full => discard character <%x>\n",
486                __FUNCTION__, channel, (uint32_t)byte );
487            }
488        }  // end while TTY_READ register full
489
490    }  // end RX
491
492    ///////////////////////  handle TX  /////////////////////////////
493    else
[424]494    {
[436]495        fifo = &tty_tx_fifo[channel];
496
497        // try to move bytes until TX_FIFO empty
498        while( fifo->sts > 0 )
[424]499        {
[446]500            // write one byte to TTY_WRITE register if empty / exit loop if full
[570]501            if( (hal_remote_l32( status_xp ) & TTY_STATUS_TX_FULL) == 0 ) 
[424]502            {
[436]503                // get one byte from TX_FIFO
504                byte = fifo->data[fifo->ptr];
[424]505
[446]506#if DEBUG_HAL_TXT_TX
507if( DEBUG_HAL_TXT_TX < tx_cycle )
[619]508printk("\n[%s] get character <%c> from TXT%d_TX fifo\n",
[451]509__FUNCTION__, byte, channel );
[446]510#endif
[436]511                // update TX_FIFO state
512                fifo->ptr = (fifo->ptr + 1) % TTY_FIFO_DEPTH;
513                hal_atomic_add( &fifo->sts , -1 );
514
515                // write byte to TTY_WRITE register & acknowledge TX_IRQ
[424]516                hal_remote_sb( write_xp , byte );
517            }
518        }
519
[435]520        // disable TX_IRQ
[570]521        hal_remote_s32( XPTR( tty_cxy , base + TTY_TX_IRQ_ENABLE ) , 0 );
[424]522
[436]523        // unblock TXT_TX server thread
524        thread_unblock( XPTR( local_cxy , server ) , THREAD_BLOCKED_ISR );
[424]525
[457]526        // send IPI to core running server thread if required
527        if( server_lid != CURRENT_THREAD->core->lid )
528        {
529            dev_pic_send_ipi( local_cxy , server_lid );
530        }
[446]531
[436]532    }  // end TX
533
[435]534    hal_fence();
[424]535
[438]536#if (DEBUG_SYS_READ & 1)
[436]537if( is_rx ) exit_tty_isr_read = (uint32_t)hal_get_cycles();
[424]538#endif
539
[438]540#if (DEBUG_SYS_WRITE & 1)
[436]541if( is_rx == 0 ) exit_tty_isr_write = (uint32_t)hal_get_cycles();
[435]542#endif
543
[424]544}  // end soclib_tty_isr()
545
[436]546/////////////////////////////////////////////////////////////
547void __attribute__ ((noinline)) soclib_tty_aux( void * args )
548{
549    uint32_t   status;
550    bool_t     empty;
551    uint32_t   i;
552
[570]553    xptr_t       dev_xp = ((txt_sync_args_t *)args)->dev_xp;
554    const char * buffer = ((txt_sync_args_t *)args)->buffer;
555    uint32_t     count  = ((txt_sync_args_t *)args)->count;
[436]556   
[570]557    // get chdev cluster and local pointer
[436]558    cxy_t     dev_cxy = GET_CXY( dev_xp );
[570]559    chdev_t * dev_ptr = GET_PTR( dev_xp );
[436]560
561    // get extended pointer on TTY channel base address
[570]562    xptr_t tty_xp = (xptr_t)hal_remote_l64( XPTR( dev_cxy , &dev_ptr->base ) );
[436]563
564    // get TTY channel segment cluster and local pointer
565    cxy_t      tty_cxy = GET_CXY( tty_xp );
[570]566    uint32_t * tty_ptr = GET_PTR( tty_xp );
[436]567
568    // get extended pointers on TTY_WRITE & TTY_STATUS registers
569    xptr_t write_xp  = XPTR( tty_cxy , tty_ptr + TTY_WRITE );
570    xptr_t status_xp = XPTR( tty_cxy , tty_ptr + TTY_STATUS );
571
[570]572    // loop on characters
[436]573    for( i = 0 ; i < count ; i++ )
574    {
[570]575        // busy waiting policy on TTY_STATUS register
[436]576        do
577        {
578            // get TTY_STATUS
[570]579            status = hal_remote_l32( status_xp );
[436]580            empty  = ( (status & TTY_STATUS_TX_FULL) == 0 );
581
582            // transfer one byte if TX buffer empty
583            if ( empty )  hal_remote_sb( write_xp , buffer[i] );
584        }
585        while ( empty == false );
586    }
587}  // end soclib_tty_aux()
588
589
590
Note: See TracBrowser for help on using the repository browser.