Ignore:
Timestamp:
Apr 26, 2017, 2:08:13 PM (7 years ago)
Author:
alain
Message:

Introduce dev_fbf, dev dma, dev_iob

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/kernel/devices/dev_txt.c

    r1 r3  
    3535/////////////////////////////////////////////////////////////////////////////////////////
    3636
    37 extern devices_directory_t  devices_dir;         // allocated in kernel_init.c
     37extern chdev_directory_t  chdev_dir;         // allocated in kernel_init.c
    3838
    39 extern devices_input_irq_t  devices_input_irq;   // allocated in kernel_init.c
     39extern chdev_pic_input_t  chdev_pic_input;   // allocated in kernel_init.c
    4040
    41 //////////////////////////////////
    42 void dev_txt_init( xptr_t  dev_xp )
     41////////////////////////////////////
     42void dev_txt_init( chdev_t * chdev )
    4343{
    44     // get device descriptor cluster and local pointer
    45     cxy_t      dev_cxy = GET_CXY( dev_xp );
    46     device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );
     44    // the local ICU chdev must be initialized before the TXT chdev, because
     45    // the TXT chdev initialisation requires allocation of a WTI from local ICU
     46    xptr_t  icu_xp  = chdev_dir.icu[local_cxy];
     47    assert( (icu_xp != XPTR_NULL) , __FUNCTION__ , "ICU not initialised before TXT" );
    4748
    48     // get implementation index from device descriptor
    49     uint32_t  impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) );
     49    // get implementation and channel index
     50    uint32_t  impl    = chdev->impl;
     51    uint32_t  channel = chdev->channel;
    5052
    51     // get channel index from device descriptor
    52     // uint32_t  channel = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->channel ) );
    53 
    54     // set fields "cmd", "isr", and "name" in device descriptor
    55     // and call implementation specific init function
    56 
    57     // TODO replace fixed "TXT_TTY" name by a channel indexed "TXT_TTY%d" name
    58     // as soon as the sprintk() function is available
    59 
     53    // set fields "cmd", "isr", and call driver init function
    6054    if( impl == IMPL_TXT_TTY )
    6155    {
    62         hal_remote_spt( XPTR( dev_cxy , &dev_ptr->cmd ) , &soclib_tty_command );
    63         hal_remote_spt( XPTR( dev_cxy , &dev_ptr->isr ) , &soclib_tty_isr );
    64         // sprintk( name , "TXT_TTY%d" , channel )
    65         hal_remote_memcpy( XPTR( dev_cxy , &dev_ptr->name ),
    66                            XPTR( local_cxy , "TXT_TTY" ) , 16 );
    67         soclib_tty_init( dev_xp );
     56        chdev->cmd = &soclib_tty_cmd;
     57        chdev->isr = &soclib_tty_isr;
     58        soclib_tty_init( chdev );
    6859    }
    6960    else
    7061    {
    71         printk("\n[PANIC] in %s: undefined TXT device implementation\n", __FUNCTION__ );
    72         hal_core_sleep();
     62        assert( false , __FUNCTION__ , "undefined TXT device implementation" );
    7363    }
    7464
     65    // get a WTI mailbox from local ICU
     66    uint32_t wti_id = dev_icu_wti_alloc();
     67
     68    assert( (wti_id != -1) , __FUNCTION__ , "cannot allocate WTI mailbox" );
     69
     70    // select a core
     71    lid_t lid = cluster_select_local_core();
     72
     73    // enable WTI IRQ and update WTI interrupt vector
     74    dev_icu_enable_irq( lid , WTI_TYPE , wti_id , chdev );
     75
     76    // link IOC IRQ to WTI mailbox in PIC component
     77    uint32_t irq_id = chdev_pic_input.txt[channel];
     78    dev_pic_bind_irq( irq_id , local_cxy , wti_id );
     79
    7580    // create server thread
    76     xptr_t     new_thread_xp;
    77     thread_t * new_thread_ptr;
     81    thread_t * new_thread;
    7882    error_t    error;
    7983
    80     if( dev_cxy == local_cxy )         // device cluster is local
    81     {
    82         error = thread_kernel_create( &new_thread_ptr,
    83                                       THREAD_DEV,
    84                                       &dev_txt_server,
    85                                       dev_ptr,
    86                                       cluster_select_local_core() );
    87  
    88         new_thread_xp = XPTR( local_cxy , new_thread_ptr );
    89     }
    90     else                                        // device cluster is remote
    91     {
    92         rpc_thread_kernel_create_client( dev_cxy,
    93                                          THREAD_DEV,
    94                                          &dev_txt_server,
    95                                          dev_ptr,
    96                                          &new_thread_xp,
    97                                          &error );
     84    error = thread_kernel_create( &new_thread,
     85                                  THREAD_DEV,
     86                                  &chdev_sequencial_server,
     87                                  chdev,
     88                                  lid );
     89    assert( (error == 0) , __FUNCTION__ , "cannot create server thread" );
    9890
    99         new_thread_ptr = (thread_t *)GET_PTR( new_thread_xp );
    100     }
    101     if( error )
    102     {
    103         printk("\n[PANIC] in %s : cannot create server thread\n", __FUNCTION__ );
    104         hal_core_sleep();
    105     }
    106 
    107     // initialises server field in device descriptor
    108     hal_remote_spt( XPTR( dev_cxy , &dev_ptr->server ) , new_thread_ptr );
     91    // set "server" field in chdev descriptor
     92    chdev->server = new_thread;
    10993   
    11094    // start server thread
    111     thread_unblock( new_thread_xp , THREAD_BLOCKED_GLOBAL );
     95    thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL );
    11296
    11397} // end dev_txt_init()
     
    11599
    116100//////////////////////////////////////////////////////////////////////////////////
    117 // This static function is called by dev_txt_read(), dev_txt_write(), and
    118 // dev_txt_sync_write() functions.
    119 // For the TXT_READ and TXT_WRITE operation types:
    120 //  - it build the command, and registers it in the calling thread descriptor.
    121 //  - then, it registers the calling thead in device waiting queue.
    122 //  - finally, it blocks on the THREAD_BLOCKED_DEV condition and deschedule.
    123 // For the TXT_SYNC_WRITE operation type:
    124 //  - it directly call the relevant driver, using a busy waiting policy.
     101// This static function is called by dev_txt_read(), dev_txt_write() functions.
    125102////////////////////////////////////i/////////////////////////////////////////////
    126103static error_t dev_txt_access( uint32_t   type,
     
    135112
    136113    // check channel argument
    137     if( channel >= CONFIG_MAX_TXT_CHANNELS )
    138     {
    139         printk("\n[PANIC] in %s : illegal channel index = %d\n", __FUNCTION__ , channel );
    140         hal_core_sleep();
    141     }
     114    assert( (channel < CONFIG_MAX_TXT_CHANNELS) , __FUNCTION__ , "illegal channel index" );
    142115
    143     // get extended pointer on remote TXT device descriptor
    144     xptr_t  dev_xp = devices_dir.txt[channel];
     116    // get extended pointer on remote TXT chdev descriptor
     117    xptr_t  dev_xp = chdev_dir.txt[channel];
    145118
    146     if ( dev_xp == XPTR_NULL )
    147     {
    148         printk("\n[PANIC] in %s : undefined TXT device descriptor for channel %d\n",
    149                __FUNCTION__ , channel );
    150         hal_core_sleep();
    151     }
     119    assert( (dev_xp != XPTR_NULL) , __FUNCTION__ , "undefined TXT chdev descriptor" );
    152120
    153121    // register command in calling thread descriptor
    154     this->dev.txt.dev_xp  = dev_xp;
    155     this->dev.txt.type    = type;
    156     this->dev.txt.buf_xp  = XPTR( local_cxy , buffer );
    157     this->dev.txt.count   = count;
     122    this->command.txt.dev_xp  = dev_xp;
     123    this->command.txt.type    = type;
     124    this->command.txt.buf_xp  = XPTR( local_cxy , buffer );
     125    this->command.txt.count   = count;
    158126
     127    // register client thread in waiting queue, activate server thread
     128    // block client thread on THREAD_BLOCKED_IO and deschedule.
     129    // it is re-activated by the ISR signaling IO operation completion.
     130    chdev_register_command( dev_xp , this );
    159131
    160     if( (type == TXT_READ) || (type == TXT_WRITE) )  // descheduling policy
    161     {
    162         // get a free WTI mailbox 
    163         uint32_t wti_id;
    164         while( 1 )
    165         {
    166             wti_id = dev_icu_wti_alloc();
    167             if( wti_id == -1 )  sched_yield();
    168             else                break;
    169         }
    170 
    171         // enable WTI IRQ in local ICU and update WTI interrupt vector
    172         dev_icu_enable_irq( local_cxy , CURRENT_CORE->lid , WTI_TYPE , wti_id , dev_xp );
    173 
    174         // link TXT IRQ to WTI mailbox in PIC component
    175         uint32_t irq_id = devices_input_irq.txt[channel];
    176         dev_pic_bind_irq( irq_id , local_cxy , wti_id );
    177 
    178         // register client thread in waiting queue, activate server thread
    179         // block client thread on THREAD_BLOCKED_IO and deschedule.
    180         // it is re-activated by the ISR signaling IO operation completion.
    181         device_register_command( dev_xp , this );
    182 
    183         // access PIC to unlink the IOC IRQ
    184         dev_pic_unbind_irq( irq_id );
    185 
    186         // disable WTI IRQ in ICU and update interrupt vector
    187         dev_icu_disable_irq( local_cxy , CURRENT_CORE->lid , WTI_TYPE , wti_id );
    188 
    189         // release  WTI mailbox
    190         dev_icu_wti_release( wti_id );
    191 
    192         txt_dmsg("\n[INFO] in %s : thread %x in process %x completes / error = %d\n",
    193                      __FUNCTION__ , this->trdid , this->process->pid , this->dev.txt.error );
    194     }
    195     else if( type == TXT_SYNC_WRITE )            // busy waiting policy
    196     {
    197         // get driver command function pointer from remote TXT device descriptor
    198         cxy_t       dev_cxy = GET_CXY( dev_xp );
    199         device_t  * dev_ptr = (device_t *)GET_PTR( dev_xp );
    200         dev_cmd_t * cmd = (dev_cmd_t *)hal_remote_lpt( XPTR( dev_cxy , &dev_ptr->cmd ) );
    201 
    202         // take the TXT device lock, because the calling thread does NOT
    203         // register in device waiting queue for this synchronous command,
    204         // and has exclusive access to the terminal...
    205         remote_spinlock_lock( XPTR( dev_cxy , &dev_ptr->wait_lock ) );
    206  
    207         // call directly driver command
    208         cmd( XPTR( local_cxy , this ) );
    209 
    210         // release the TXT device lock
    211         remote_spinlock_unlock( XPTR( dev_cxy , &dev_ptr->wait_lock ) );
    212     }   
     132    txt_dmsg("\n[INFO] in %s : thread %x in process %x completes / error = %d\n",
     133             __FUNCTION__ , this->trdid , this->process->pid , this->command.txt.error );
    213134
    214135    // return I/O operation status from calling thread descriptor
    215     return this->dev.txt.error; 
     136    return this->command.txt.error; 
    216137
    217138}  // end dev_txt_access()
     
    225146}
    226147 
    227 ///////////////////////////////////////////////
    228 error_t dev_txt_sync_write( uint32_t   channel,
    229                             char     * buffer,
    230                             uint32_t   count )
    231 {
    232     return dev_txt_access( TXT_SYNC_WRITE , channel , buffer , count );
    233 }
    234  
    235148/////////////////////////////////////////
    236149error_t dev_txt_read( uint32_t   channel,
     
    240153}
    241154
    242 /////////////////////////////////////
    243 void dev_txt_server( device_t * dev )
     155///////////////////////////////////////////////
     156error_t dev_txt_sync_write( uint32_t   channel,
     157                            char     * buffer,
     158                            uint32_t   count )
    244159{
    245     xptr_t          client_xp;    // extended pointer on waiting thread
    246     cxy_t           client_cxy;   // cluster of client thread
    247     thread_t      * client_ptr;   // local pointer on client thread
    248     thread_t      * server;       // local pointer on server thread
    249     xptr_t          root_xp;      // extended pointer on device waiting queue root
     160    // get pointer on calling thread
     161    thread_t * this = CURRENT_THREAD;
    250162
    251     server = CURRENT_THREAD;
     163    // get extended pointer on TXT[0] chdev
     164    xptr_t  dev_xp = chdev_dir.txt[channel];
    252165
    253     root_xp = XPTR( local_cxy , &dev->wait_root );
     166    // register command in calling thread
     167    this->command.txt.dev_xp  = dev_xp;
     168    this->command.txt.type    = TXT_SYNC_WRITE;
     169    this->command.txt.buf_xp  = XPTR( local_cxy , buffer );
     170    this->command.txt.count   = count;
    254171
    255         // infinite loop handling commands of threads
    256     // registered in the TXT waiting queue
    257     while( 1 )
    258     {
    259         // get lock protecting queue
    260         remote_spinlock_lock( XPTR( local_cxy , &dev->wait_lock ) );
     172    // get driver command function
     173    cxy_t       dev_cxy = GET_CXY( dev_xp );
     174    chdev_t   * dev_ptr = (chdev_t *)GET_PTR( dev_xp );
     175    dev_cmd_t * cmd = (dev_cmd_t *)hal_remote_lpt( XPTR( dev_cxy , &dev_ptr->cmd ) );
    261176
    262         // block and deschedule server thread if waiting queue empty
    263         if( xlist_is_empty( root_xp ) )
    264         {
    265             thread_block( server , THREAD_BLOCKED_DEV_QUEUE );
    266             remote_spinlock_unlock( XPTR( local_cxy , &dev->wait_lock ) );
    267             sched_yield();
    268         }
    269         else
    270         {
    271             remote_spinlock_unlock( XPTR( local_cxy , &dev->wait_lock ) );
    272         }
     177    // call directly driver command after taking chdev lock
     178    remote_spinlock_lock( XPTR( dev_cxy , &dev_ptr->wait_lock ) );
     179    cmd( XPTR( local_cxy , this ) );
     180    remote_spinlock_unlock( XPTR( dev_cxy , &dev_ptr->wait_lock ) );
    273181
    274         // get extended pointer on first client thread
    275         client_xp = XLIST_FIRST_ELEMENT( root_xp , thread_t , wait_list );
     182    // return I/O operation status from calling thread descriptor
     183    return this->command.txt.error;
     184 
     185}  // end dev_txt_sync_write()
    276186
    277         // call driver command function to start I/O operation
    278         dev->cmd( client_xp );
    279        
    280         // get client thread cluster and local pointer
    281         client_cxy = GET_CXY( client_xp );
    282         client_ptr = (thread_t *)GET_PTR( client_xp );
    283 
    284         // remove the client thread from waiting queue
    285         remote_spinlock_lock( XPTR( local_cxy , &dev->wait_lock ) );
    286         xlist_unlink( XPTR( client_cxy , &client_ptr->wait_list ) );
    287         remote_spinlock_unlock( XPTR( local_cxy , &dev->wait_lock ) );
    288 
    289     }  // end while
    290 
    291 }  // end dev_txt_server()
    292 
Note: See TracChangeset for help on using the changeset viewer.