Changes in / [3:1]


Ignore:
Location:
/trunk/kernel/devices
Files:
4 added
6 deleted
12 edited

Legend:

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

    r3 r1  
    2424#include <hal_types.h>
    2525#include <hal_special.h>
    26 #include <chdev.h>
     26#include <device.h>
    2727#include <thread.h>
    2828#include <cluster.h>
     
    3737/////////////////////////////////////////////////////////////////////////////////////////
    3838
    39 extern chdev_directory_t  chdev_dir;         // allocated in kernel_init.c
    40 
    41 extern chdev_pic_input_t  chdev_pic_input;   // allocated in kernel_init.c
    42 
    43 /////////////////////////////////
    44 void dev_icu_init( chdev_t * icu,
    45                    uint32_t  hwi_nr,
    46                    uint32_t  wti_nr,
    47                    uint32_t  pti_nr )
    48 {
    49     // set ICU chdev extension fields
    50     icu->ext.icu.hwi_nr     = hwi_nr;
    51     icu->ext.icu.wti_nr     = wti_nr;
    52     icu->ext.icu.pti_nr     = pti_nr;
    53     icu->ext.icu.wti_bitmap = 0;
    54     spinlock_init( &icu->ext.icu.wti_lock );
     39extern devices_directory_t  devices_dir;         // allocated in kernel_init.c
     40
     41extern devices_input_irq_t  devices_input_irq;   // allocated in kernel_init.c
     42
     43
     44///////////////////////////////////
     45void dev_icu_init( xptr_t   dev_xp,
     46                   uint32_t hwi_nr,
     47                   uint32_t wti_nr,
     48                   uint32_t pti_nr )
     49{
     50    // get ICU device cluster and local pointer
     51    cxy_t      dev_cxy = GET_CXY( dev_xp );
     52    device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );
     53
     54    if( dev_cxy != local_cxy )
     55    {
     56        printk("\n[PANIC] %s for cluster %x must be local\n",
     57               __FUNCTION__ , local_cxy );
     58        hal_core_sleep();
     59    }
     60
     61    // set ICU device extension fields
     62    dev_ptr->ext.icu.hwi_nr     = hwi_nr;
     63    dev_ptr->ext.icu.wti_nr     = wti_nr;
     64    dev_ptr->ext.icu.pti_nr     = pti_nr;
     65    dev_ptr->ext.icu.wti_bitmap = 0;
     66    spinlock_init( &dev_ptr->ext.icu.wti_lock );
    5567   
    56     // get implementation
    57     uint32_t impl = icu->impl;
    58 
    59     // call the relevant driver init function
     68    // get implementation index from ICU device descriptor
     69    uint32_t impl = dev_ptr->impl;
     70
     71    // set field "name" in device descriptor
     72    // and call the relevant driver init function
    6073    if( impl == IMPL_ICU_XCU )
    6174    {
    62         uint32_t  lid;
    63         for( lid = 0 ; lid < LOCAL_CLUSTER->cores_nr ; lid++ )
    64         {
    65             soclib_xcu_init( icu , lid );
    66         }
    67     }
    68     else
    69     {
    70         assert( false , __FUNCTION__ , "undefined ICU implementation" );
     75        memcpy( dev_ptr->name , "ICU_XCU" , 16 );
     76
     77        uint32_t     lid;
     78        cluster_t  * cluster = LOCAL_CLUSTER;
     79        for( lid = 0 ; lid < cluster->cores_nr ; lid++ )
     80        {
     81            soclib_xcu_init( dev_ptr , lid );
     82        }
     83    }
     84    else
     85    {
     86        printk("\n[PANIC] %s : undefined ICU implementation for cluste %x\n",
     87               __FUNCTION__ , local_cxy );
     88        hal_core_sleep();
    7189    }
    7290} // end dev_icu_init()
    7391
    7492/////////////////////////////////////////////////////////////////////////////////////
    75 // This static function check the irq_type / irq_index arguments.
     93// This static function check the irq_type / irq_index arguments for a remote ICU.
    7694// It is called by the dev_icu_enable_irq() & dev_icu_disable_irq() functions.
     95// returns 0 if OK / returns non zero if invalid arguments
    7796/////////////////////////////////////////////////////////////////////////////////////
    78 static inline void dev_icu_check_irq( chdev_t  * icu,
     97static inline void dev_icu_check_irq( xptr_t     icu_xp,
    7998                                      uint32_t   irq_type,
    8099                                      uint32_t   irq_index )
    81100{
     101    // get cluster and local pointer on remote ICU
     102    cxy_t      icu_cxy = GET_CXY( icu_xp );
     103    device_t * icu_ptr = (device_t *)GET_PTR( icu_xp );
     104
    82105    if( irq_type == HWI_TYPE )
    83106    {
    84         assert( (irq_index < icu->ext.icu.hwi_nr) , __FUNCTION__ , "illegal HWI" );
     107        if( irq_index >= hal_remote_lw( XPTR( icu_cxy , &icu_ptr->ext.icu.hwi_nr ) ) )
     108        {
     109            printk("\n[PANIC] in %s : illegal HWI index = %d for ICU in cluster %x\n",
     110                   __FUNCTION__ , irq_index , icu_cxy );
     111            hal_core_sleep();
     112        }
    85113    }
    86114    if( irq_type == WTI_TYPE )
    87115    {
    88         assert( (irq_index < icu->ext.icu.wti_nr) , __FUNCTION__ , "illegal WTI" );
     116        if( irq_index >= hal_remote_lw( XPTR( icu_cxy , &icu_ptr->ext.icu.wti_nr ) ) )
     117        {
     118            printk("\n[PANIC] in %s : illegal WTI index = %d for ICU in cluster %x\n",
     119                   __FUNCTION__ , irq_index , icu_cxy );
     120            hal_core_sleep();
     121        }
    89122    }
    90123    if( irq_type == PTI_TYPE )
    91124    {
    92         assert( (irq_index < icu->ext.icu.pti_nr) , __FUNCTION__ , "illegal PTI" );
    93     }
    94 }  // end dev_icu_check_irq()
    95 
    96 ////////////////////////////////////////
    97 void dev_icu_enable_irq( lid_t      lid,
     125        if( irq_index >= hal_remote_lw( XPTR( icu_cxy , &icu_ptr->ext.icu.pti_nr ) ) )
     126        {
     127            printk("\n[PANIC] in %s : illegal PTI index = %d for ICU in cluster %x\n",
     128                   __FUNCTION__ , irq_index , icu_cxy );
     129            hal_core_sleep();
     130        }
     131    }
     132}  // end dev_icu check irq()
     133
     134////////////////////////////////////////////
     135void dev_icu_enable_irq( cxy_t      icu_cxy,
     136                         lid_t      lid,
    98137                         uint32_t   irq_type,
    99138                         uint32_t   irq_index,
    100                          chdev_t  * src_chdev )
    101 {
    102     // get local pointer on local ICU chdev
    103     xptr_t    icu_xp = chdev_dir.icu[local_cxy];
    104     chdev_t * icu    = (chdev_t *)GET_PTR( icu_xp );
     139                         xptr_t     src_dev_xp )
     140{
     141    // get extended pointer & local pointer on remote ICU device
     142    xptr_t     icu_xp  = devices_dir.icu[icu_cxy];
     143    device_t * icu_ptr = (device_t *)GET_PTR( icu_xp );
    105144
    106145    // check IRQ type and index
    107     dev_icu_check_irq( icu , irq_type , irq_index );
     146    dev_icu_check_irq( icu_xp , irq_type , irq_index );
    108147
    109148    // (1) call implementation specific ICU driver to enable IRQ
    110     if( icu->impl == IMPL_ICU_XCU )
    111     {
    112         soclib_xcu_enable_irq( icu , 1<<irq_index , irq_type , lid );
    113     }
    114 
    115     // (2) get selected core local pointer, and register
    116     // source chdev pointer in relevant interrupt vector
    117     core_t * core = &LOCAL_CLUSTER->core_tbl[lid];
    118         core_set_irq_vector_entry( core , irq_type , irq_index , src_chdev );
    119 
    120     // (3) register IRQ type and index in source chdev descriptor
    121     src_chdev->irq_type = irq_type;
    122     src_chdev->irq_id   = irq_index;
     149    if( icu_ptr->impl == IMPL_ICU_XCU )
     150    {
     151        soclib_xcu_enable_irq( icu_xp , 1<<irq_index , irq_type , lid );
     152    }
     153    else
     154    {
     155        printk("\n[PANIC] in %s : undefined ICU implementation" , __FUNCTION__ );
     156        hal_core_sleep();
     157    }
     158
     159    // (2) get selected remote core local pointer, and register
     160    // source device xptr in relevant interrupt vector
     161
     162    core_t * core_ptr = hal_remote_lpt( XPTR( icu_cxy , &LOCAL_CLUSTER->core_tbl[lid] ) );
     163    xptr_t   core_xp  = XPTR( icu_cxy , core_ptr );
     164        core_set_irq_vector_entry( core_xp , irq_type , irq_index , src_dev_xp );
     165
     166    // (3) get extended pointer on source device, and
     167    // register IRQ type and index in source device descriptor
     168
     169    cxy_t      src_dev_cxy = GET_CXY( src_dev_xp );
     170    device_t * src_dev_ptr = (device_t *)GET_PTR( src_dev_xp );
     171
     172    hal_remote_sw( XPTR( src_dev_cxy , &src_dev_ptr->irq_type ) , irq_type );
     173    hal_remote_sw( XPTR( src_dev_cxy , &src_dev_ptr->irq_id   ) , irq_index );
    123174
    124175}  // end dev_icu_enable_irq()
    125176
    126 /////////////////////////////////////////
    127 void dev_icu_disable_irq( lid_t      lid,
     177/////////////////////////////////////////////
     178void dev_icu_disable_irq( cxy_t      icu_cxy,
     179                          lid_t      lid,
    128180                          uint32_t   irq_type,
    129181                          uint32_t   irq_index )
    130182{
    131     // get local pointer on local ICU chdev
    132     xptr_t    icu_xp = chdev_dir.icu[local_cxy];
    133     chdev_t * icu    = (chdev_t *)GET_PTR( icu_xp );
     183    // get extended pointer & local pointer on remote ICU device
     184    xptr_t  icu_xp = devices_dir.icu[icu_cxy];
     185    device_t * icu_ptr = (device_t *)GET_PTR( icu_xp );
    134186
    135187    // check IRQ type and index
    136     dev_icu_check_irq( icu , irq_type , irq_index );
     188    dev_icu_check_irq( icu_xp , irq_type , irq_index );
    137189
    138190    // (1) call the implementation specific ICU driver to disable IRQ
    139     if( icu->impl == IMPL_ICU_XCU )
    140     {
    141         soclib_xcu_disable_irq( icu , 1<<irq_index , irq_type , lid );
     191    if( icu_ptr->impl == IMPL_ICU_XCU )
     192    {
     193        soclib_xcu_disable_irq( icu_xp , 1<<irq_index , irq_type , lid );
     194    }
     195    else
     196    {
     197        printk("\n[PANIC] in %s : undefined ICU implementation" , __FUNCTION__ );
     198        hal_core_sleep();
    142199    }
    143200
    144201    // (2) get selected remote core local pointer, and remove
    145     // the source chdev xptr from relevant interrupt vector
    146 
    147     core_t * core = &LOCAL_CLUSTER->core_tbl[lid];
    148         core_set_irq_vector_entry( core , irq_type , irq_index , NULL );
     202    // the source device xptr from relevant interrupt vector
     203
     204    core_t * core_ptr = hal_remote_lpt( XPTR( icu_cxy , &LOCAL_CLUSTER->core_tbl[lid] ) );
     205    xptr_t   core_xp  = XPTR( icu_cxy , core_ptr );
     206        core_set_irq_vector_entry( core_xp , irq_type , irq_index , XPTR_NULL );
    149207
    150208} // end dev_icu_disable_irq()
     
    154212                         uint32_t   period )
    155213{
    156     // get local pointer on local ICU chdev
    157     xptr_t    icu_xp = chdev_dir.icu[local_cxy];
    158     chdev_t * icu    = (chdev_t *)GET_PTR( icu_xp );
     214    // get pointer on local ICU device descriptor
     215    core_t   * core = CURRENT_CORE;
     216    device_t * icu  = core->icu;
    159217
    160218    // check PTI index
    161     assert( (pti_index < icu->ext.icu.pti_nr) , __FUNCTION__ , "illegal PTI index" );
     219    if( pti_index >= icu->ext.icu.pti_nr )
     220    {
     221        printk("\n[PANIC] in %s : illegal PTI index = %d\n", __FUNCTION__ , pti_index );
     222        hal_core_sleep();
     223    }
    162224
    163225    // call the implementation specific driver ICU to set period
     
    171233void dev_icu_ack_timer( uint32_t pti_index )
    172234{
    173     // get local pointer on local ICU chdev
    174     xptr_t    icu_xp = chdev_dir.icu[local_cxy];
    175     chdev_t * icu    = (chdev_t *)GET_PTR( icu_xp );
     235    // get pointer on local ICU device descriptor
     236    core_t   * core = CURRENT_CORE;
     237    device_t * icu  = core->icu;
    176238
    177239    // check PTI index
    178     assert( (pti_index < icu->ext.icu.pti_nr) , __FUNCTION__ , "illegal PTI index" );
     240    if( pti_index >= icu->ext.icu.pti_nr )
     241    {
     242        printk("\n[PANIC] in %s : illegal PTI index = %d\n", __FUNCTION__ , pti_index );
     243        hal_core_sleep();
     244    }
    179245
    180246    // call the implementation specific driver ICU to acknowledge PTI IRQ
     
    183249        soclib_xcu_ack_timer( icu , pti_index );
    184250    }
     251    else
     252    {
     253        printk("\n[PANIC] in %s : undefined ICU implementation" , __FUNCTION__ );
     254        hal_core_sleep();
     255    }
     256
    185257}  // end dev_icu_ack_timer()
    186258
     
    198270    uint32_t    y = cxy & ((1<<y_width)-1);
    199271
    200     assert( ((x < x_size) && (y < y_size)) , __FUNCTION__ , "illegal cluster identifier" );
    201 
    202     assert( (lid < cores_nr) , __FUNCTION__ , "illegal core local index" );
    203 
    204     // get extended pointer on target ICU chdev
    205     xptr_t icu_xp = chdev_dir.icu[cxy];
     272    if( (x >= x_size) || (y >= y_size) )
     273    {
     274        hal_core_sleep("%s : illegal cluster identifier = %x\n", __FUNCTION__ , cxy );
     275    }
     276    if( lid >= cores_nr )
     277    {
     278        hal_core_sleep("%s : illegal core local index = %d\n", __FUNCTION__ , lid );
     279    }
     280
     281    // get extended pointer on target ICU device
     282    xptr_t icu_xp = devices_dir.icu[cxy];
    206283
    207284     // get target ICU cluster and local pointer
    208     cxy_t     icu_cxy = GET_CXY( icu_xp );
    209     chdev_t * icu_ptr = (chdev_t *)GET_PTR( icu_xp );
    210 
    211     // get implementation from remote ICU chdev
    212     uint32_t impl = hal_remote_lw( XPTR( icu_cxy , &icu_ptr->impl ) );   
     285    cxy_t      cxy_icu = GET_CXY( icu_xp );
     286    device_t * ptr_icu = (device_t *)GET_PTR( icu_xp );
     287
     288    // get driver implementation from target ICU device
     289    uint32_t impl = hal_remote_lw( XPTR( cxy_icu , &ptr_icu->impl ) );   
    213290
    214291    // call the implementation specific ICU driver to send IPI
     
    216293    {
    217294        soclib_xcu_send_ipi( icu_xp , lid );
     295    }
     296    else
     297    {
     298        printk("\n[PANIC] in %s : undefined ICU implementation" , __FUNCTION__ );
     299        hal_core_sleep();
    218300    }
    219301}  // end dev_icu_send_ipi()
     
    225307    uint32_t   wti_status;   // WTI index + 1  / no pending WTI if 0
    226308    uint32_t   pti_status;   // PTI index + 1  / no pending PTI if 0
    227     chdev_t  * src_chdev;    // pointer on source chdev descriptor
     309    xptr_t     src_dev_xp;   // extended pointer on source device descriptor
     310    cxy_t      src_dev_cxy;  // source device cluster
     311    device_t * src_dev_ptr;  // source device local pointer
    228312    uint32_t   index;        // IRQ index
    229313
    230     core_t   * core = CURRENT_CORE;
    231 
    232     // get local pointer on local ICU chdev
    233     xptr_t    icu_xp = chdev_dir.icu[local_cxy];
    234     chdev_t * icu    = (chdev_t *)GET_PTR( icu_xp );
     314    // get pointer on local ICU device descriptor
     315    core_t   * core = CURRENT_CORE;
     316    device_t * icu  = core->icu;
    235317
    236318    // call the implementation specific ICU driver 
     
    240322        soclib_xcu_get_status( icu , core->lid , &hwi_status , &wti_status , &pti_status );
    241323    }
     324    else
     325    {
     326        printk("\n[PANIC] in %s : undefined ICU implementation" , __FUNCTION__ );
     327        hal_core_sleep();
     328    }
    242329
    243330    // analyse ICU status and handle up to 3 pending IRQ (one WTI, one HWI, one PTI)
    244331
    245     if( wti_status )          // pending WTI
     332    if( wti_status )          // pending WTI TODO what about IPIs ???  [AG]
    246333        {
    247334        index = wti_status - 1;
    248335
    249         if( index < LOCAL_CLUSTER->cores_nr )   // it is an IPI
    250         {
    251             assert( (index == core->lid) , __FUNCTION__ , "illegal IPI index" );
    252 
    253             // TODO acknowledge WTI [AG]
    254 
    255             // TODO force scheduling [AG]
    256         }
    257         else                                    // it is an external device
    258         {
    259             // get pointer on IRQ source chdev
    260                     src_chdev = core->wti_vector[index];
    261 
    262                     if( src_chdev == NULL )        // strange, but not fatal => disable IRQ
    263                     {
    264                 printk("\n[WARNING] in %s : no handler for WTI %d on core %d in cluster %x\n",
    265                        __FUNCTION__ , index , core->lid , local_cxy );
    266                     core->spurious_irqs ++;
    267                 dev_icu_disable_irq( core->lid , WTI_TYPE , index );
    268             }
    269             else                                 // call relevant ISR
    270             {
    271                         icu_dmsg("\n[INFO] %s received WTI : index = %d for cpu %d in cluster %d\n",
    272                          __FUNCTION__ , index , core->lid , local_cxy );
    273 
    274                 // call ISR
    275                     src_chdev->isr( src_chdev );
    276             }
     336        // get extended pointer on IRQ source device
     337                src_dev_xp  = core->wti_vector[index];
     338        src_dev_cxy = GET_CXY( src_dev_xp );
     339        src_dev_ptr = (device_t *)GET_PTR( src_dev_xp );
     340
     341                if( src_dev_xp == XPTR_NULL )        // strange, but not fatal => disable IRQ
     342                {
     343            printk("\n[WARNING] in %s : no handler for WTI %d on core %d in cluster %x\n",
     344                   __FUNCTION__ , index , core->lid , local_cxy );
     345                core->spurious_irqs ++;
     346            dev_icu_disable_irq( local_cxy , core->lid , WTI_TYPE , index );
     347                }
     348        else if( src_dev_cxy != local_cxy )  // WTI must be handled in device cluster
     349        {
     350            printk("\n[PANIC] in %s : non local WTI %d on core %d in cluster %x\n",
     351                   __FUNCTION__ , index , core->lid , local_cxy );
     352            hal_core_sleep();
     353        }
     354        else                                 // call relevant ISR
     355        {
     356                    icu_dmsg("\n[INFO] %s received WTI : index = %d for cpu %d in cluster %d\n",
     357                     __FUNCTION__ , index , core->lid , local_cxy );
     358
     359                src_dev_ptr->isr( src_dev_ptr );
    277360        }
    278361        }
     
    282365        index = hwi_status - 1;
    283366
    284         // get pointer on IRQ source chdev
    285                 src_chdev = core->hwi_vector[index];
    286 
    287                 if( src_chdev == NULL )        // strange, but not fatal => disable IRQ
     367        // get pointer on IRQ source device
     368                src_dev_xp  = core->wti_vector[index];
     369        src_dev_cxy = GET_CXY( src_dev_xp );
     370        src_dev_ptr = (device_t *)GET_PTR( src_dev_xp );
     371
     372                if( src_dev_xp == XPTR_NULL )        // strange, but not fatal => disable IRQ
    288373                {
    289374            printk("\n[WARNING] in %s : no handler for HWI %d on core %d in cluster %x\n",
    290375                   __FUNCTION__ , index , core->lid , local_cxy );
    291376                core->spurious_irqs ++;
    292             dev_icu_disable_irq( core->lid , HWI_TYPE , index );
     377            dev_icu_disable_irq( local_cxy , core->lid , HWI_TYPE , index );
    293378                }
     379        else if( src_dev_cxy != local_cxy )  // HWI must be handled in device cluster
     380        {
     381            printk("\n[PANIC] in %s : non local HWI %d on core %d in cluster %x\n",
     382                   __FUNCTION__ , index , core->lid , local_cxy );
     383            hal_core_sleep();
     384        }
    294385        else                    // call relevant ISR
    295386        {
     
    297388                     __FUNCTION__ , index , core->lid , local_cxy );
    298389
    299             // call ISR
    300                     src_chdev->isr( src_chdev );
     390                    src_dev_ptr->isr( src_dev_ptr );
    301391        }
    302392        }
     
    312402        dev_icu_ack_timer( index );
    313403
    314         // TODO execute all actions related to TICK event
     404        // execute all actions related to TICK event
    315405        core_clock( core );
    316406        }
     
    320410uint32_t dev_icu_wti_alloc()
    321411{
    322     // get local pointer on local ICU chdev
    323     xptr_t    icu_xp = chdev_dir.icu[local_cxy];
    324     chdev_t * icu    = (chdev_t *)GET_PTR( icu_xp );
    325 
    326     // get bitmap pointer, lock pointer, and size
    327     uint32_t   * bitmap = &icu->ext.icu.wti_bitmap;
     412    // get pointer on local ICU device descriptor
     413    core_t   * core = CURRENT_CORE;
     414    device_t * icu  = core->icu;
     415
     416    // get bitmap pointer, lock, and size
     417    bitmap_t   * bitmap = &icu->ext.icu.wti_bitmap;
    328418    spinlock_t * lock   = &icu->ext.icu.wti_lock;
    329419    uint32_t     size   =  icu->ext.icu.wti_nr;
     
    347437void dev_icu_wti_release( uint32_t index )
    348438{
    349     // get pointer on local ICU chdev descriptor
    350     xptr_t    icu_xp  = chdev_dir.icu[local_cxy];
    351     chdev_t * icu_ptr = (chdev_t *)GET_PTR( icu_xp );
     439    // get pointer on local ICU device descriptor
     440    core_t   * core = CURRENT_CORE;
     441    device_t * icu  = core->icu;
    352442
    353443    // get bitmap pointer, lock, and size
    354     bitmap_t   * bitmap = &icu_ptr->ext.icu.wti_bitmap;
    355     spinlock_t * lock   = &icu_ptr->ext.icu.wti_lock;
    356     uint32_t     size   =  icu_ptr->ext.icu.wti_nr;
     444    bitmap_t   * bitmap = &icu->ext.icu.wti_bitmap;
     445    spinlock_t * lock   = &icu->ext.icu.wti_lock;
     446    uint32_t     size   =  icu->ext.icu.wti_nr;
    357447
    358448    // check index
    359     assert( (index < size) , __FUNCTION__ , "illegal WTI index" );
     449    if( index >= size )
     450    {
     451        printk("\n[PANIC] in %s : illegal WTI index = %d on core %d in cluster %x\n",
     452               __FUNCTION__ , index , core->lid , local_cxy );
     453        hal_core_sleep();
     454    }
    360455
    361456    // get lock protecting WTI allocator
     
    367462    // release lock
    368463    spinlock_unlock( lock );
    369 
    370464}  // end dev_icu_wti_release()
    371465
    372 //////////////////////////////////////////////
    373 uint32_t * dev_icu_wti_ptr( uint32_t  wti_id )
    374 {
    375     uint32_t *  wti_ptr = NULL;
    376 
    377     // get pointer on local ICU chdev descriptor
    378     xptr_t    icu_xp  = chdev_dir.icu[local_cxy];
    379     chdev_t * icu     = (chdev_t *)GET_PTR( icu_xp );
     466///////////////////////////////////////
     467xptr_t dev_icu_wti_xptr( cxy_t     cxy,
     468                         uint32_t  wti_id )
     469{
     470    uint32_t * ptr = NULL;    // local pointer on mailbox
     471   
     472    // get pointer on local ICU device descriptor
     473    core_t   * core = CURRENT_CORE;
     474    device_t * icu  = core->icu;
    380475
    381476    // call implementation specific ICU driver
    382477    if( icu->impl == IMPL_ICU_XCU )
    383478    {
    384         wti_ptr = soclib_xcu_wti_ptr( icu , wti_id );   
    385     }
    386 
    387     return wti_ptr;
     479        ptr = soclib_xcu_wti_ptr( icu , wti_id );   
     480    }
     481    else
     482    {
     483        printk("\n[PANIC] in %s : undefined ICU implementation" , __FUNCTION__ );
     484        hal_core_sleep();
     485    }
     486
     487    // return extended pointer on mailbox
     488    return XPTR( cxy , ptr );
     489
    388490}   // end dev_icu_wti_xptr()
    389491
  • /trunk/kernel/devices/dev_icu.h

    r3 r1  
    3535 * acting in all clusters containing cores. He is in charge of concentrating all IRQs
    3636 * (interrupt requests) generated by peripherals to signal the completion of an I/O
    37  * operation. Each IRQ is routed to the core that started the I/O operation.
     37 * operation. Each IRQ should be routed to the core that started the I/O operation.
    3838 * The ICU device must also help the kernel to select the ISR (Interrupt Service Routine)
    3939 * that must be executed by the target core.
    4040 *
    41  * This component can be implemented as a dedicated hardware component distributed
     41 * This component can be implemented as a dedicated hardware, centralized or distributed
    4242 * in all clusters, or emulated in software, as long as it implements the specified API.
    4343 * For the TSAR architecture, this generic ICU device is implemented by the two hardware
    4444 * components soclib_xicu and and soclib_iopic, and their associated drivers.
    4545 *
    46  * ALMOS-MKH defines three types of IRQs, that are handled by this ICU device:
     46 * ALMOS-MKH defines three types of IRQs, that are handled iby this ICU device:
    4747 * - HWI : The HardWare Interrupts are generated by local internal peripherals.
    4848 *   They are connected to the local ICU, to be routed to a given local core.
     
    7272 * uses three interrupts vectors, implemented as three arrays (HWI/WTI/PTI),
    7373 * stored in the core descriptor. Each entry in one interrupt vector array contains
    74  * a pointer on the chdev descriptor that is the "source" of the interrupt.
    75  * This chdev descriptor contains a link to the ISR to be executed.
     74 * an extended pointer on the device descriptor that is the "source" of the interrupt.
     75 * This device descriptor contains a link to the ISR to be executed.
    7676 *
    7777 * The ICU peripheral does not execute I/O operations, but is just acting as a
    78  * dynamically configurable interrupt router for other I/O operations.
    79  * Therefore, ALMOS-MKH does not use the ICU device waiting queue, but calls directly
     78 * dynamically configurable interrupt router for another I/O operation.
     79 * Therefore, ALMOS-MKH does not use the iCU device waiting queue, but calls directly
    8080 * the ICU driver blocking functions, using the device lock to get exclusive access to
    8181 * the ICU device state.
     
    8484/****  Forward declarations  ****/
    8585
    86 struct chdev_s;
     86struct device_s;
    8787
    8888/*****************************************************************************************
     
    127127/*****************************************************************************************
    128128 * This function makes two initialisations:
    129  * - It initialises the ICU specific fields of the chdev descriptor.
     129 * - It initialises the ICU specific fields of the device descriptor.
    130130 * - it initialises the implementation specific ICU hardware device and associated
    131131 *   data structures if required.
    132  * It must be called by a local thread.
    133  *****************************************************************************************
    134  * @ icu     : pointer on ICU chdev descriptor.
    135  * @ hwi_nr  : number of HWI irqs.
    136  * @ wti_nr  : number of WTI irqs.
    137  * @ pti_nr  : number of PTI irqs.
    138  ****************************************************************************************/
    139 void dev_icu_init( struct chdev_s  * icu,
    140                    uint32_t          hwi_nr,
    141                    uint32_t          wti_nr,
    142                    uint32_t          pti_nr );
    143 
    144 /*****************************************************************************************
    145  * This function enables the routing of a given IRQ, to a given core in the local cluster.
    146  * This IRQ is identified by its type (HWI/WTI/PTI) and index in the local ICU.
     132 * It must be executed once in the cluster containing the ICU device descriptor.
     133 *****************************************************************************************
     134 * @ icu_xp     : extended pointer on ICU device descriptor.
     135 * @ hwi_nr     : number of HWI irqs.
     136 * @ wti_nr     : number of WTI irqs.
     137 * @ pti_nr     : number of PTI irqs.
     138 ****************************************************************************************/
     139void dev_icu_init( xptr_t    icu_xp,
     140                   uint32_t  hwi_nr,
     141                   uint32_t  wti_nr,
     142                   uint32_t  pti_nr );
     143
     144/*****************************************************************************************
     145 * This function enables the routing of a given IRQ, to a given core in a remote cluster.
     146 * This IRQ is identified by its type (HWI/WTI/PTI) and index in the remote ICU.
    147147 * The target core is identified by its local index.
    148  * It must be called by a local thread.
    149  * - It unmask the selected IRQ in the ICU.
    150  * - It registers the pointer on the "source" chdev descriptor in the
     148 * As it uses remote accesses, it can be executed by any thread in any cluster.
     149 * - It unmask the selected IRQ in the remote ICU.
     150 * - It registers the extended pointer on the "source" device descriptor in the
    151151 *   relevant interrupt vector of the selected core.
    152  * - It register the IRQ type and index in the "source" chdev descriptor.
    153  *****************************************************************************************
    154  * @ lid        : local index of selected core.
     152 * - It register the IRQ type and index in the "source" device descriptor.
     153 *****************************************************************************************
     154 * @ cxy        : remote cluster identifier (can be the local custer).
     155 * @ lid        : local index of selected core in remote cluster.
    155156 * @ irq_type   : HWI/WTI/PTI.
    156  * @ irq_id     : IRQ index in ICU
    157  * @ chdev      : pointer on source chdev descriptor.
    158  ****************************************************************************************/
    159 void dev_icu_enable_irq( lid_t             lid,
    160                          uint32_t          irq_type,
    161                          uint32_t          irq_id,
    162                          struct chdev_s  * chdev );
    163 
    164 /*****************************************************************************************
    165  * This function disables one given IRQ for a given core in the local cluster.
    166  * This IRQ is identified by its type (HWI/WTI/PTI) and index in the local ICU.
     157 * @ irq_id     : IRQ index in remote ICU
     158 * @ src_dev_xp : extended pointer on device descriptor source of IRQ.
     159 ****************************************************************************************/
     160void dev_icu_enable_irq( cxy_t      cxy,
     161                         lid_t      lid,
     162                         uint32_t   irq_type,
     163                         uint32_t   irq_id,
     164                         xptr_t     src_dev_xp );
     165
     166/*****************************************************************************************
     167 * This function disables one given IRQ for a given core in a remote cluster.
     168 * This IRQ is identified by its type (HWI/WTI/PTI) and index in the remote ICU.
    167169 * The core is identified by its local index.
    168  * It must be called by a local thread.
    169  * - It mask the selected IRQ in the ICU.
    170  * - It removes the pointer on the "source" chdev descriptor from the
     170 * As it uses remote accesses, it can be executed by any thread in any cluster.
     171 * - It mask the selected IRQ in the remote ICU.
     172 * - It removes the extended pointer on the "source" device descriptor from the
    171173 *   relevant interrupt vector of the selected core.
    172  * - The IRQ type and index fields are not modified in the "source" chdev descriptor.
    173  *****************************************************************************************
     174 * - The IRQ type and index fields are not modified in the "source" device descriptor.
     175 *****************************************************************************************
     176 * @ cxy       : remote cluster identifier (can be the local custer).
    174177 * @ lid       : local index of selected core in remote cluster.
    175178 * @ irq_type  : HWI/WTI/PTI.
    176179 * @ irq_id    : IRQ index.
    177180 ****************************************************************************************/
    178 void dev_icu_disable_irq( lid_t      lid,
     181void dev_icu_disable_irq( cxy_t      cxy,
     182                          lid_t      lid,
    179183                          uint32_t   irq_type,
    180184                          uint32_t   irq_id );
     
    183187 * This function set the period value for a timer identified by the PTI index,
    184188 * in the local ICU device descriptor.
    185  * It must be called by a local thread.
    186189 *****************************************************************************************
    187190 * @ pti_id    : PTI index.
     
    194197 * This function acknowledge a PTI IRQ for a timer identified by the PTI index,
    195198 * in the local ICU device descriptor.
    196  * It must be called by a local thread.
    197199 *****************************************************************************************
    198200 * @ pti_id    : PTI index.
     
    202204/*****************************************************************************************
    203205 * This function send an IPI (Inter Processor Interrupt) to a core identified by
    204  * its cluster identifier and local index.
    205  * It can be called by any thread running in any cluster.
     206 * its cluster identifier and local index.
    206207 * This IPI force a context switch, and the handling of pending RPC(s).
    207208 *****************************************************************************************
     
    225226
    226227/*****************************************************************************************
    227  * This function implements the WTI mailbox allocator for the local ICU.
    228  * These mailbox are used by I/O operations for completion signaling.
    229  * It must be called by a thread running in the cluster containing the target ICU.
     228 * This function implements the WTI mailbox allocator. It is used by all I/O operations
     229 * for completion signaling.
    230230 * If there is no mailbox available, the client thread must deschedule and retry later.
    231231 * If N is the total number of WTI mailboxes in a cluster, and NC the number of cores,
     
    240240/*****************************************************************************************
    241241 * This function releases a dynamically allocated WTI mailbox.
    242  * It must be called by a thread running in the cluster containing the target ICU.
    243242 * It does not access the hardware device.
    244243 *****************************************************************************************
     
    248247
    249248/*****************************************************************************************
    250  * This function returns a pointer on the WTI mailbox identified by its index
    251  * in the local ICU device.
    252  *****************************************************************************************
    253  * @ wti_id   : WTI mailbox index.
    254  * @ returns pointer on mailbox register.
    255  ****************************************************************************************/
    256 uint32_t * dev_icu_wti_ptr( uint32_t wti_id );
     249 * This function returns an extended pointer on a WTI mailbox identified by its
     250 * cluster identifier and local index in ICU.
     251 * WARNING: we assume that all ICU hardware devices have the same local base address.
     252 *****************************************************************************************
     253 * @ cxy      : mailbox cluster identifier
     254 * @ wti_id   : mailbox WTI index.
     255 * @ returns extended pointer on mailbox register.
     256 ****************************************************************************************/
     257xptr_t  dev_icu_wti_xptr( cxy_t    cxy,
     258                          uint32_t wti_id );
    257259
    258260#endif  /* _DEV_ICU_H_ */
  • /trunk/kernel/devices/dev_ioc.c

    r3 r1  
    3232#include <thread.h>
    3333#include <printk.h>
    34 #include <chdev.h>
    3534#include <dev_ioc.h>
    3635
     
    3938/////////////////////////////////////////////////////////////////////////////////////////
    4039
    41 extern chdev_directory_t  chdev_dir;         // allocated in kernel_init.c
    42 
    43 extern chdev_pic_input_t  chdev_pic_input;   // allocated in kernel_init.c
    44 
    45 ////////////////////////////////////
    46 void dev_ioc_init( chdev_t * chdev )
    47 {
    48     // the local ICU chdev must be initialized before the IOC chdev, because
    49     // the IOC chdev initialisation requires allocation of a WTI from local ICU
    50     xptr_t  icu_xp  = chdev_dir.icu[local_cxy];
    51     assert( (icu_xp != XPTR_NULL) , __FUNCTION__ , "ICU not initialised before IOC" );
    52 
    53     // get implementation and channel from chdev descriptor
    54     uint32_t  impl    = chdev->impl;
    55     uint32_t  channel = chdev->channel;
    56 
    57     // set driver specific fields in chdev descriptor and call driver init function
     40extern devices_directory_t  devices_dir;         // allocated in kernel_init.c
     41
     42extern devices_input_irq_t  devices_input_irq;   // allocated in kernel_init.c
     43
     44//////////////////////////////////
     45void dev_ioc_init( xptr_t dev_xp )
     46{
     47    // get IOC device descriptor cluster and local pointer
     48    cxy_t      dev_cxy = GET_CXY( dev_xp );
     49    device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );
     50
     51    // get implementation from device descriptor
     52    uint32_t  impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) );
     53
     54    // set driver specific fields in device descriptor
     55    // and call driver init function
    5856    if( impl == IMPL_IOC_BDV )
    5957    {
    60         chdev->cmd = &soclib_bdv_cmd;
    61         chdev->isr = &soclib_bdv_isr;
    62         soclib_bdv_init( chdev );
     58        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->cmd ) , &soclib_bdv_command );
     59        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->isr ) , &soclib_bdv_isr );
     60        hal_remote_memcpy( XPTR( dev_cxy , &dev_ptr->name ),
     61                           XPTR( local_cxy , "IOC_BDV" ) , 16 );
     62        soclib_bdv_init( dev_xp );
    6363    }
    6464    else if( impl == IMPL_IOC_HBA )
    6565    {
    66         chdev->cmd = &soclib_hba_command;
    67         chdev->isr = &soclib_hba_isr;
    68         soclib_hba_init( chdev );
    69     }
     66        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->cmd ) , &soclib_hba_command );
     67        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->isr ) , &soclib_hba_isr );
     68        hal_remote_memcpy( XPTR( dev_cxy , &dev_ptr->name ),
     69                           XPTR( local_cxy , "IOC_HBA" ) , 16 );
     70        soclib_hba_init( dev_xp );
     71    }
     72//    else if( impl == IMPL_IOC_SDC )
     73//    {
     74//        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->cmd ) , &soclib_sdc_command );
     75//        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->isr ) , &soclib_sdc_isr );
     76//        hal_remote_memcpy( XPTR( dev_cxy , &dev_ptr->name ),
     77//                           XPTR( local_cxy , "IOC_SDC" ) , 16 );
     78//        soclib_sdc_init( dev_xp );
     79//    }
     80//    else if( impl == IMPL_IOC_SPI )
     81//    {
     82//        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->cmd ) , &soclib_spi_command );
     83//        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->isr ) , &soclib_spi_isr );
     84//        hal_remote_memcpy( XPTR( dev_cxy , &dev_ptr->name ),
     85//                           XPTR( local_cxy , "IOC_SPI" ) , 16 );
     86//        soclib_spi_init( dev_xp );
     87//    }
     88//    else if( impl == IMPL_IOC_RDK )
     89//    {
     90//        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->cmd ) , &soclib_rdk_command );
     91//        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->isr ) , &soclib_rdk_isr );
     92//        hal_remote_memcpy( XPTR( dev_cxy , &dev_ptr->name ),
     93//                           XPTR( local_cxy , "IOC_RDK" ) , 16 );
     94//        soclib_rdk_init( dev_xp );
     95//    }
    7096    else
    7197    {
    72         assert( false , __FUNCTION__ , "undefined IOC device implementation" );
    73     }
    74 
    75     // get a WTI mailbox from local ICU
    76     uint32_t wti_id = dev_icu_wti_alloc();
    77 
    78     assert( (wti_id != -1) , __FUNCTION__ , "cannot allocate WTI mailbox" );
    79 
    80     // select a core
    81     lid_t lid = cluster_select_local_core();
    82 
    83     // enable WTI IRQ and update WTI interrupt vector
    84     dev_icu_enable_irq( lid , WTI_TYPE , wti_id , chdev );
    85 
    86     // link IOC IRQ to WTI mailbox in PIC component
    87     uint32_t irq_id = chdev_pic_input.ioc[channel];
    88     dev_pic_bind_irq( irq_id , local_cxy , wti_id );
     98        printk("\n[PANIC] in %s: undefined IOC device implementation\n", __FUNCTION__ );
     99        hal_core_sleep();
     100    }
    89101
    90102    // create server thread
    91     thread_t * new_thread;
     103    thread_t * new_thread_ptr;
     104    xptr_t     new_thread_xp;
    92105    error_t    error;
    93106
    94     error = thread_kernel_create( &new_thread,
    95                                   THREAD_DEV,
    96                                   &chdev_sequencial_server,
    97                                   chdev,
    98                                   lid );
    99     assert( (error == 0) , __FUNCTION__ , "cannot create server thread" );
    100 
    101     // set "server" field in chdev descriptor
    102     chdev->server = new_thread;
     107    if( dev_cxy == local_cxy )         // device cluster is local
     108    {
     109        error = thread_kernel_create( &new_thread_ptr,
     110                                      THREAD_DEV,
     111                                      &dev_ioc_server,
     112                                      dev_ptr,
     113                                      cluster_select_local_core() );
     114
     115        new_thread_xp = XPTR( local_cxy , new_thread_ptr );
     116    }
     117    else                                    // device cluster is remote
     118    {
     119        rpc_thread_kernel_create_client( dev_cxy,
     120                                         THREAD_DEV,
     121                                         &dev_ioc_server,
     122                                         dev_ptr,
     123                                         &new_thread_xp,
     124                                         &error );
     125
     126        new_thread_ptr = (thread_t *)GET_PTR( new_thread_xp );
     127    }
     128    if( error )
     129    {
     130        printk("\n[PANIC] in %s : cannot create server thread\n", __FUNCTION__ );
     131        hal_core_sleep();
     132    }
     133
     134    // set "server" field in device descriptor
     135    hal_remote_spt( XPTR( dev_cxy , &dev_ptr->server ) , new_thread_ptr );
    103136   
    104137    // start server thread
    105     thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL );
     138    thread_unblock( new_thread_xp , THREAD_BLOCKED_GLOBAL );
    106139 
    107140}  // end dev_ioc_init()
     
    111144// It builds and registers the command in the calling thread descriptor, after
    112145// translation of buffer virtual address to physical address.
    113 // Then, it registers the calling thead in chdev waiting queue.
     146// Then, it registers the calling thead in device waiting queue.
    114147// Finally it blocks on the THREAD_BLOCKED_DEV condition and deschedule.
    115148////////////////////////////////////i/////////////////////////////////////////////
     
    119152                               uint32_t  count )
    120153{
    121     thread_t * this = CURRENT_THREAD;              // pointer on client thread
     154    thread_t  * this      = CURRENT_THREAD;              // pointer on client thread
     155    cxy_t       local_cxy = local_cxy;                   // client thread cluster
    122156
    123157    error_t     error;
    124158    paddr_t     buf_paddr;
     159    bool_t      ident = CONFIG_KERNEL_IDENTITY;
    125160
    126161    // Get buffer physical address
    127     error = vmm_v2p_translate( CONFIG_KERNEL_IDENTITY , buffer , &buf_paddr );
     162    error = vmm_v2p_translate( ident , buffer , &buf_paddr );
    128163 
    129164    if( error )  return EINVAL;
    130165
    131166    ioc_dmsg("\n[INFO] in %s : thread %x in process %x"
    132              " for lba = %x / vaddr = %x / paddr = %l / at cycle %d\n",
     167             " for lba = %x / vaddr = %x / paddr = %llx\n",
    133168             __FUNCTION__ , this->trdid , this->process->pid ,
    134              lba , (uint32_t)buffer , buf_paddr , hal_time_stamp() );
     169             lba , (uint32_t)buffer , buf_paddr );
    135170
    136171#if USE_IOB    // software L2/L3 cache coherence for memory buffer
     
    141176#endif     // end software L2/L3 cache coherence
    142177
    143     // get extended pointer on IOC chdev descriptor
    144     xptr_t  dev_xp = chdev_dir.ioc[0];
    145 
    146     assert( (dev_xp != XPTR_NULL) , __FUNCTION__ , "undefined IOC chdev descriptor" );
    147 
    148     // register command in calling thread descriptor
    149     this->command.ioc.dev_xp    = dev_xp;
    150     this->command.ioc.to_mem    = to_mem;
    151     this->command.ioc.buf_xp    = XPTR( local_cxy , buffer );
    152     this->command.ioc.lba       = lba;
    153     this->command.ioc.count     = count;
    154 
    155     // register client thread in IOC chdev waiting queue, activate server thread,
     178    // get extended pointer on IOC device descriptor
     179    xptr_t  dev_xp = devices_dir.ioc;
     180
     181    if ( dev_xp == XPTR_NULL )
     182    {
     183        printk("\n[PANIC] in %s : undefined IOC device descriptor\n", __FUNCTION__ );
     184        hal_core_sleep();
     185    }
     186
     187    // get a free WTI mailbox 
     188    uint32_t wti_id;
     189    while( 1 )
     190    {
     191        wti_id = dev_icu_wti_alloc();
     192        if( wti_id == -1 )  sched_yield();
     193        else                break;
     194    }
     195
     196    // enable WTI IRQ in local ICU and update WTI interrupt vector
     197    dev_icu_enable_irq( local_cxy, CURRENT_CORE->lid , WTI_TYPE , wti_id , dev_xp );
     198
     199    // link IOC IRQ to WTI mailbox in PIC component
     200    uint32_t irq_id = devices_input_irq.ioc;
     201    dev_pic_bind_irq( irq_id , local_cxy , wti_id );
     202
     203    // store command in thread descriptor
     204    this->dev.ioc.dev_xp    = dev_xp;
     205    this->dev.ioc.to_mem    = to_mem;
     206    this->dev.ioc.buf_xp    = XPTR( local_cxy , buffer );
     207    this->dev.ioc.lba       = lba;
     208    this->dev.ioc.count     = count;
     209
     210    // register client thread in waiting queue, activate server thread,
    156211    // block client thread on THREAD_BLOCKED_IO and deschedule.
    157212    // it is re-activated by the ISR signaling IO operation completion.
    158     chdev_register_command( dev_xp , this );
    159 
    160     ioc_dmsg("\n[INFO] in %s : thread %x in process %x"
    161              " completes / error = %d / at cycle %d\n",
    162              __FUNCTION__ , this->trdid , this->process->pid ,
    163              this->dev.ioc.error , hal_time_stamp() );
     213    device_register_command( dev_xp , this );
     214
     215    // access PIC to unlink the IOC IRQ
     216    dev_pic_unbind_irq( irq_id );
     217
     218    // disable WTI IRQ in ICU and update interrupt vector
     219    dev_icu_disable_irq( local_cxy , CURRENT_CORE->lid , WTI_TYPE , wti_id );
     220
     221    // release  WTI mailbox
     222    dev_icu_wti_release( wti_id );
     223
     224    ioc_dmsg("\n[INFO] in %s : thread %x in process %x completes / error = %d\n",
     225             __FUNCTION__ , this->trdid , this->process->pid , this->dev.ioc.error );
    164226
    165227    // return I/O operation status
    166     return this->command.ioc.error; 
     228    return this->dev.ioc.error; 
    167229
    168230}  // end dev_ioc_access()
     
    183245    return dev_ioc_access( false , buffer , lba , count );
    184246}
     247                       
     248/////////////////////////////////////
     249void dev_ioc_server( device_t * dev )
     250{
     251    xptr_t     client_xp;    // extended pointer on waiting thread
     252    cxy_t      client_cxy;   // cluster of client thread
     253    thread_t * client_ptr;   // local pointer on client thread
     254    thread_t * server;       // local pointer on server thread
     255    xptr_t     root_xp;      // extended pointer on device waiting queue root
     256
     257    server    = CURRENT_THREAD;
     258
     259    root_xp   = XPTR( local_cxy , &dev->wait_root );
     260
     261        // infinite loop handling commands registered in the IOC waiting queue
     262    // TODO If we want to implement an "elevator" mecanism (i.e. sort all
     263    // pending command on the LBA to optimize physical device accesses),
     264    // it should be done in this loop...
     265
     266    while( 1 )
     267    {
     268        // get lock protecting queue
     269        remote_spinlock_lock( XPTR( local_cxy , &dev->wait_lock ) );
     270
     271        // block and deschedule server thread if waiting queue empty
     272        if( xlist_is_empty( root_xp ) )
     273        {
     274            thread_block( server , THREAD_BLOCKED_DEV_QUEUE );
     275            remote_spinlock_unlock( XPTR( local_cxy , &dev->wait_lock ) );
     276            sched_yield();
     277        }
     278        else
     279        {
     280            remote_spinlock_unlock( XPTR( local_cxy , &dev->wait_lock ) );
     281        }
     282
     283        // get extended pointer on first client thread
     284        client_xp = XLIST_FIRST_ELEMENT( root_xp , thread_t , wait_list );
     285
     286        // call driver command function to start I/O operation
     287        dev->cmd( client_xp );
     288       
     289        // get client thread cluster and local pointer
     290        client_cxy = GET_CXY( client_xp );
     291        client_ptr = (thread_t *)GET_PTR( client_xp );
     292
     293        // remove the client thread from waiting queue
     294        remote_spinlock_lock( XPTR( local_cxy , &dev->wait_lock ) );
     295        xlist_unlink( XPTR( client_cxy , &client_ptr->wait_list ) );
     296        remote_spinlock_unlock( XPTR( local_cxy , &dev->wait_lock ) );
     297
     298    }  // end while
     299
     300}  // end dev_ioc_server()
  • /trunk/kernel/devices/dev_ioc.h

    r3 r1  
    2525#define _DEV_IOC_H
    2626
    27 #include <almos_config.h>
    2827#include <hal_types.h>
    2928
    3029/****  Forward declarations  ****/
    3130
    32 struct chdev_s;
     31struct device_s;
    3332
    3433/*****************************************************************************************
     
    105104
    106105/******************************************************************************************
    107  * This function completes the IOC chdev descriptor initialisation,
     106 * This function completes the IOC device descriptor initialisation,
    108107 * namely the link with the implementation specific driver.
    109  * The func, impl, channel, is_rx, base fields have been previously initialised.
     108 * The func, impl, channel, is_rxt, base, and size fields must be previously initialised.
    110109 * It calls the specific driver initialisation function, to initialise the hardware
    111110 * device and the specific data structures when required.
    112  * It creates the associated server thread and allocates a WTI from local ICU.
    113  * It must de executed by a local thread.
     111 * It creates the associated server thread.
     112 * It can be executed in another cluster than the cluster containing the device descriptor
     113 * or the hardware device itself.
    114114 ******************************************************************************************
    115  * @ chdev     : local pointer on IOC chdev descriptor.
     115 * @ xp_dev     : extended pointer on IOC device descriptor.
    116116 *****************************************************************************************/
    117 void dev_ioc_init( struct chdev_s * chdev );
     117void dev_ioc_init( xptr_t  xp_dev );
    118118
    119119/******************************************************************************************
     
    149149                       uint32_t       count );
    150150
     151/******************************************************************************************
     152 * This function is executed by the server thread associated to the IOC device descriptor.
     153 * This thread is created and activated by the dev_ioc_init() function.
     154 * It executes an infinite loop to handle sequencially all commands registered
     155 * by the client threads in the device waiting queue, calling the driver CMD function.
     156 * 
     157 * - If the peripheral can only handle one single command, the driver block the server
     158 *   thread on the THREAD_BLOCKED_DEV_ISR condition, waiting I/O operation conmpletion.
     159 *   The server thread must be reacticated by the driver ISR function.
     160 * - If the peripheral can handle several commands in parallel (AHCI is an example), the
     161 *   driver does not block the server thread (it is only descheduled if the number of
     162 *   commands exceeeds the max number of parallel commands supported by the peripheral.
     163 *
     164 * When the waiting queue is empty, the server thread blocks on the THREAD_BLOCKED_CMD
     165 * condition and deschedule. It is re-activated by a client thread registering a command.
     166 ******************************************************************************************
     167 * @ dev     : local pointer on IOC device descriptor.
     168 *****************************************************************************************/
     169void dev_ioc_server( struct device_s * dev );
     170
    151171#endif  /* _DEV_IOC_H */
  • /trunk/kernel/devices/dev_mmc.c

    r3 r1  
    2626#include <soclib_mmc.h>
    2727#include <printk.h>
    28 #include <chdev.h>
    2928#include <thread.h>
    3029#include <dev_mmc.h>
     
    3433/////////////////////////////////////////////////////////////////////////////////////////
    3534
    36 extern chdev_directory_t  chdev_dir;         // allocated in kernel_init.c
    37 
    38 extern chdev_icu_input_t  chdev_icu_input;   // allocated in kernel_init.c
    39 
    40 ////////////////////////////////////
    41 void dev_mmc_init( chdev_t * chdev )
    42 {
     35extern devices_directory_t  devices_dir;         // allocated in kernel_init.c
     36
     37extern devices_input_irq_t  devices_input_irq;   // allocated in kernel_init.c
     38
     39//////////////////////////////////
     40void dev_mmc_init( xptr_t dev_xp )
     41{
     42    // get MMC device descriptor cluster and local pointer
     43    cxy_t      dev_cxy = GET_CXY( dev_xp );
     44    device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );
     45
    4346    // get implementation from device descriptor
    44     uint32_t  impl = chdev->impl;
    45 
    46     // set driver specific fields in device descriptor and call driver init function
     47    uint32_t  impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) );
     48
     49    // set driver specific fields in device descriptor
     50    // and call driver init function
    4751    if( impl == IMPL_MMC_TSR )
    4852    {
    49         chdev->cmd = &soclib_mmc_cmd;
    50         chdev->isr = &soclib_mmc_isr;
    51         soclib_mmc_init( chdev );
     53        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->cmd ) , &soclib_mmc_command );
     54        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->isr ) , &soclib_mmc_isr );
     55        hal_remote_memcpy( XPTR( dev_cxy , &dev_ptr->name ),
     56                           XPTR( local_cxy , "MMC_TSR" ) , 16 );
     57        soclib_mmc_init( dev_xp );
    5258    }
    5359    else
    5460    {
    55         assert( false , __FUNCTION__ , "undefined MMC device implementation" );
     61        printk("\n[PANIC] in %s: undefined MMC device implementation\n", __FUNCTION__ );
     62        hal_core_sleep();
    5663    }
    5764}  // end dev_mmc_init()
     
    6572{
    6673    mmc_dmsg("\n[INFO] %s enters for thread %x in process %x : command = %d\n",
    67                  __FUNCTION__ , this->trdid , this->process->pid , this->command.mmc.type );
     74                 __FUNCTION__ , this->trdid , this->process->pid , this->dev.mmc.type );
    6875
    6976    // get extended pointer on MMC device
    70     xptr_t  dev_xp  = this->command.mmc.dev_xp;
    71 
    72     assert( (dev_xp != XPTR_NULL) , __FUNCTION__ , "undefined MMC device descriptor" );
     77    xptr_t  dev_xp  = this->dev.mmc.dev_xp;
     78
     79    if ( dev_xp == XPTR_NULL )
     80    {
     81        printk("\n[PANIC] in %s : undefined MMC device descriptor "
     82               "in cluster %x for thread %x in process %x\n",
     83               __FUNCTION__ , local_cxy , this->trdid , this->process->pid );
     84        hal_core_sleep();
     85    }
    7386
    7487    // get MMC device cluster identifier & local pointer
    75     cxy_t     dev_cxy = GET_CXY( dev_xp );
    76     chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );
     88    cxy_t      dev_cxy = GET_CXY( dev_xp );
     89    device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );
    7790
    7891    // get driver command function pointer from MMC device descriptor
     
    103116    cxy_t cxy = CXY_FROM_PADDR( buf_paddr );
    104117
    105     assert( ((buf_paddr & (CONFIG_CACHE_LINE_SIZE -1)) == 0) , __FUNCTION__ ,
    106              "buffer not aligned on cache line" );
     118    if ( buf_paddr & (CONFIG_CACHE_LINE_SIZE -1) )
     119    {
     120        printk("\n[PANIC] in %s : buffer not aligned on cache line "
     121               "for thread %x / target cluster %x\n",
     122               __FUNCTION__ , this->trdid , cxy );
     123        hal_core_sleep();
     124    }
    107125
    108126    // get extended pointer on MMC device descriptor
    109     xptr_t  dev_xp = chdev_dir.mmc[cxy];
    110 
    111     // store command arguments in thread descriptor
    112     this->command.mmc.dev_xp    = dev_xp;
    113     this->command.mmc.type      = MMC_CC_INVAL;
    114     this->command.mmc.buf_paddr = buf_paddr;
    115     this->command.mmc.buf_size  = buf_size;
    116 
    117     // execute operation
    118     dev_mmc_access( this );
    119 
    120     // return operation status
    121     return this->command.mmc.error; 
     127    xptr_t  dev_xp = devices_dir.mmc[cxy];
     128
     129    // store command arguments in thread descriptor
     130    this->dev.mmc.dev_xp    = dev_xp;
     131    this->dev.mmc.type      = MMC_CC_INVAL;
     132    this->dev.mmc.buf_paddr = buf_paddr;
     133    this->dev.mmc.buf_size  = buf_size;
     134
     135    // execute operation
     136    dev_mmc_access( this );
     137
     138    // return operation status
     139    return this->dev.mmc.error; 
    122140
    123141
     
    132150    cxy_t cxy = CXY_FROM_PADDR( buf_paddr );
    133151
    134     assert( ((buf_paddr & (CONFIG_CACHE_LINE_SIZE -1)) == 0) , __FUNCTION__ ,
    135              "buffer not aligned on cache line" );
    136 
    137     // store command arguments in thread descriptor
    138     this->command.mmc.dev_xp    = chdev_dir.mmc[cxy];
    139     this->command.mmc.type      = MMC_CC_SYNC;
    140     this->command.mmc.buf_paddr = buf_paddr;
    141     this->command.mmc.buf_size  = buf_size;
    142 
    143     // execute operation
    144     dev_mmc_access( this );
    145 
    146     // return operation status
    147     return this->command.mmc.error; 
     152    if ( buf_paddr & (CONFIG_CACHE_LINE_SIZE -1) )
     153    {
     154        printk("\n[PANIC] in %s : buffer not aligned on cache line "
     155               "for thread %x / target cluster %x\n",
     156               __FUNCTION__ , this->trdid , cxy );
     157        hal_core_sleep();
     158    }
     159
     160    // store command arguments in thread descriptor
     161    this->dev.mmc.dev_xp    = devices_dir.mmc[cxy];
     162    this->dev.mmc.type      = MMC_CC_SYNC;
     163    this->dev.mmc.buf_paddr = buf_paddr;
     164    this->dev.mmc.buf_size  = buf_size;
     165
     166    // execute operation
     167    dev_mmc_access( this );
     168
     169    // return operation status
     170    return this->dev.mmc.error; 
    148171
    149172
     
    157180
    158181    // store command arguments in thread descriptor
    159     this->command.mmc.dev_xp    = chdev_dir.mmc[cxy];
    160     this->command.mmc.type      = MMC_SET_ERROR;
    161     this->command.mmc.reg_index = index;
    162     this->command.mmc.reg_ptr   = &wdata;
    163 
    164     // execute operation
    165     dev_mmc_access( this );
    166 
    167     // return operation status
    168     return this->command.mmc.error; 
     182    this->dev.mmc.dev_xp    = devices_dir.mmc[cxy];
     183    this->dev.mmc.type      = MMC_SET_ERROR;
     184    this->dev.mmc.reg_index = index;
     185    this->dev.mmc.reg_ptr   = &wdata;
     186
     187    // execute operation
     188    dev_mmc_access( this );
     189
     190    // return operation status
     191    return this->dev.mmc.error; 
    169192}
    170193                       
     
    178201
    179202    // store command arguments in thread descriptor
    180     this->command.mmc.dev_xp    = chdev_dir.mmc[cxy];
    181     this->command.mmc.type      = MMC_GET_ERROR;
    182     this->command.mmc.reg_index = index;
    183     this->command.mmc.reg_ptr   = rdata;
    184 
    185     // execute operation
    186     dev_mmc_access( this );
    187 
    188     // return operation status
    189     return this->command.mmc.error; 
     203    this->dev.mmc.dev_xp    = devices_dir.mmc[cxy];
     204    this->dev.mmc.type      = MMC_GET_ERROR;
     205    this->dev.mmc.reg_index = index;
     206    this->dev.mmc.reg_ptr   = rdata;
     207
     208    // execute operation
     209    dev_mmc_access( this );
     210
     211    // return operation status
     212    return this->dev.mmc.error; 
    190213}
    191214                       
     
    199222
    200223    // store command arguments in thread descriptor
    201     this->command.mmc.dev_xp    = chdev_dir.mmc[cxy];
    202     this->command.mmc.type      = MMC_GET_INSTRU;
    203     this->command.mmc.reg_index = index;
    204     this->command.mmc.reg_ptr   = rdata;
    205 
    206     // execute operation
    207     dev_mmc_access( this );
    208 
    209     // return operation status
    210     return this->command.mmc.error; 
     224    this->dev.mmc.dev_xp    = devices_dir.mmc[cxy];
     225    this->dev.mmc.type      = MMC_GET_INSTRU;
     226    this->dev.mmc.reg_index = index;
     227    this->dev.mmc.reg_ptr   = rdata;
     228
     229    // execute operation
     230    dev_mmc_access( this );
     231
     232    // return operation status
     233    return this->dev.mmc.error; 
    211234}
    212235
  • /trunk/kernel/devices/dev_mmc.h

    r3 r1  
    4646 * As these operations consume few cycles, and access conflicts are expected to be
    4747 * rare events, the calling threads use a busy waiting strategy to get the device
    48  * spinlock, but do not register in the device waiting queue, and no server thread
     48 * spinlock, do not register in the device waiting queue, and no server thread
    4949 * is used for this device.
    5050 ****************************************************************************************/
    5151 
    52 /****  Forward declarations  ****/
    53 
    54 struct chdev_s;
    55 
    5652/******************************************************************************************
    5753 * This enum defines the various implementations of the generic MMC peripheral.
     
    9692 * It must be executed once in any cluster containing an L2 cache.
    9793 *****************************************************************************************
    98  * @ chdev      : pointer on MMC device descriptor.
     94 * @ mmc_xp     : extended pointer on MMC device descriptor.
    9995 ****************************************************************************************/
    100 void dev_mmc_init( struct chdev_s * chdev );
     96void dev_mmc_init( xptr_t  mmc_xp );
    10197
    10298/*****************************************************************************************
  • /trunk/kernel/devices/dev_nic.c

    r3 r1  
    2525#include <hal_special.h>
    2626#include <printk.h>
    27 #include <chdev.h>
     27#include <device.h>
    2828#include <thread.h>
    2929#include <soclib_nic.h>
     
    3434/////////////////////////////////////////////////////////////////////////////////////////
    3535
    36 extern chdev_directory_t  chdev_dir;         // allocated in kernel_init.c
    37 
    38 extern chdev_pic_input_t  chdev_pic_input;   // allocated in kernel_init.c
    39 
    40 ////////////////////////////////////
    41 void dev_nic_init( chdev_t * chdev )
     36extern devices_directory_t  devices_dir;         // allocated in kernel_init.c
     37
     38extern devices_input_irq_t  devices_input_irq;   // allocated in kernel_init.c
     39
     40
     41//////////////////////////////////
     42void dev_nic_init( xptr_t dev_xp )
    4243{
    43     // the local ICU chdev must be initialized before the NIC chdev, because
    44     // the NIC chdevs initialisation requires allocation of a WTI from local ICU
    45     xptr_t  icu_xp  = chdev_dir.icu[local_cxy];
    46     assert( (icu_xp != XPTR_NULL) , __FUNCTION__ , "ICU not initialised before NIC" );
    47 
    48     // get "impl" , "channel" , "is_rx" fields from chdev descriptor
    49     uint32_t  impl    = chdev->impl;
    50     uint32_t  is_rx   = chdev->is_rx;
    51     uint32_t  channel = chdev->channel;
    52 
    53     // set driver specific fields in chdev descriptor and call driver init function
     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 );
     47
     48    // get "impl" , "channel" , "is_rx" fields from device descriptor
     49    uint32_t  impl    = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) );
     50    uint32_t  is_rx   = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->is_rx ) );
     51    uint32_t  channel = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->channel ) );
     52
     53    // set driver specific fields in device descriptor
     54    // and call driver init function
    5455    if( impl == IMPL_NIC_SOC )
    5556    {
    56         chdev->cmd = &soclib_nic_cmd;
    57         chdev->isr = &soclib_nic_isr;
    58         soclib_nic_init( chdev );
    59     }
     57        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->cmd ) , &soclib_nic_cmd );
     58        hal_remote_spt( XPTR( dev_cxy , &dev_ptr->isr ) , &soclib_nic_isr );
     59        hal_remote_memcpy( XPTR( dev_cxy , &dev_ptr->name ),
     60                           XPTR( local_cxy , "NIC_SOC" ) , 16 );
     61        soclib_nic_init( dev_xp );
     62    }
     63//    else if( impl == IMPL_NIC_I86)
     64//    {
     65//        hal_remote_spt( XPTR( cxy , &ptr->cmd ) , &i86_nic_cmd );
     66//        hal_remote_spt( XPTR( cxy , &ptr->isr ) , &i86_nic_isr );
     67//        hal_remote_memcpy( XPTR( cxy , &ptr->name ),
     68//                           XPTR( local_cxy , "NIC_I86" ) , 16 );
     69//        i86_nic_init( dev );
     70//    }
    6071    else
    6172    {
    62         assert( false , __FUNCTION__ , "undefined NIC device implementation" );
    63     }
    64 
    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 );
     73        printk("\n[PANIC] in %s : undefined NIC device implementation\n", __FUNCTION__ );
     74        hal_core_sleep();
     75    }
     76
     77    // get a free WTI mailbox for this NIC device
     78    uint32_t wti_id;
     79    if( dev_cxy == local_cxy )                       // NIC device cluster is local
     80    {
     81        wti_id = dev_icu_wti_alloc();
     82    }
     83    else                                             // NIC device cluster is remote
     84    {
     85        rpc_icu_wti_alloc_client( dev_cxy , &wti_id );
     86    }
     87
     88    if( wti_id == -1 )
     89    {
     90        printk("\n[PANIC] in %s : cannot allocate WTI mailbox\n", __FUNCTION__ );
     91        hal_core_sleep();
     92    }
     93
     94    // enable WTI IRQ in remote ICU and update WTI interrupt vector
     95    dev_icu_enable_irq( dev_cxy, 0 , WTI_TYPE , wti_id , dev_xp );
    7596
    7697    // link NIC IRQ to WTI mailbox in PIC component
    7798    uint32_t irq_id;
    78     if( is_rx ) irq_id = chdev_pic_input.nic_rx[channel];
    79     else        irq_id = chdev_pic_input.nic_tx[channel];
     99    if( is_rx ) irq_id = devices_input_irq.nic_rx[channel];
     100    else        irq_id = devices_input_irq.nic_tx[channel];
    80101    dev_pic_bind_irq( irq_id , local_cxy , wti_id );
    81102
    82103    // create server thread
    83     thread_t * new_thread;
     104    thread_t * new_thread_ptr;
     105    xptr_t     new_thread_xp;
    84106    error_t    error;
    85107
    86     error = thread_kernel_create( &new_thread,
    87                                   THREAD_DEV,
    88                                   &chdev_sequencial_server,
    89                                   chdev,
    90                                   lid );
    91 
    92     assert( (error == 0) , __FUNCTION__ , "cannot create server thread" );
    93 
    94     // set "server" field in chdev descriptor
    95     chdev->server = new_thread;
     108    if( dev_cxy == local_cxy )                        // device cluster is local
     109    {
     110        error = thread_kernel_create( &new_thread_ptr,
     111                                      THREAD_DEV,
     112                                      &dev_ioc_server,
     113                                      dev_ptr,
     114                                      cluster_select_local_core() );
     115
     116        new_thread_xp = XPTR( local_cxy , new_thread_ptr );
     117    }
     118    else                                              // device cluster is remote
     119    {
     120        rpc_thread_kernel_create_client( dev_cxy,
     121                                         THREAD_DEV,
     122                                         &dev_ioc_server,
     123                                         dev_ptr,
     124                                         &new_thread_xp,
     125                                         &error );
     126
     127        new_thread_ptr = (thread_t *)GET_PTR( new_thread_xp );
     128    }
     129    if( error )
     130    {
     131        printk("\n[PANIC] in %s : cannot create server thread\n", __FUNCTION__ );
     132        hal_core_sleep();
     133    }
     134
     135    // set "server" field in device descriptor
     136    hal_remote_spt( XPTR( dev_cxy , &dev_ptr->server ) , new_thread_ptr );
    96137   
    97138    // start server thread
    98     thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL );
     139    thread_unblock( new_thread_xp , THREAD_BLOCKED_GLOBAL );
    99140
    100141}  // end dev_nic_init()
     
    115156                 __FUNCTION__ , core->lid , local_cxy );
    116157
    117     // get pointer on NIC-RX chdev descriptor
     158    // get pointer on NIC-RX device descriptor
    118159    uint32_t   channel = thread_ptr->dev_channel;
    119     xptr_t     dev_xp  = chdev_dir.nic_rx[channel];
     160    xptr_t     dev_xp  = devices_dir.nic_rx[channel];
    120161    cxy_t      dev_cxy = GET_CXY( dev_xp );
    121     chdev_t  * dev_ptr = (chdev_t *)GET_PTR( dev_xp );
    122 
    123     assert( (dev_xp != XPTR_NULL) , __FUNCTION__ , "undefined NIC chdev descriptor" );
    124 
    125     assert( (dev_cxy == local_cxy) , __FUNCTION__ , " chdev must be local" );
     162    device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );
     163
     164    if ( dev_xp == XPTR_NULL )
     165    {
     166        printk("\n[PANIC] in %s : undefined NIC device descriptor\n", __FUNCTION__ );
     167        hal_core_sleep();
     168    }
     169
     170    if ( dev_cxy != local_cxy )
     171    {
     172        printk("\n[PANIC] in %s : device descriptor must be local\n", __FUNCTION__ );
     173        hal_core_sleep();
     174    }
    126175
    127176    // initialize command in thread descriptor
    128     thread_ptr->command.nic.dev_xp = dev_xp;
     177    thread_ptr->dev.nic.dev_xp = dev_xp;
    129178
    130179    // call driver to test readable
    131     thread_ptr->command.nic.cmd = NIC_CMD_READABLE;
     180    thread_ptr->dev.nic.cmd = NIC_CMD_READABLE;
    132181    dev_ptr->cmd( thread_xp );
    133182
    134183    // check error
    135     error = thread_ptr->command.nic.error;
     184    error = thread_ptr->dev.nic.error;
    136185    if( error ) return error;
    137186
    138187    // block and deschedule if queue non readable
    139     if( thread_ptr->command.nic.status == false ) 
     188    if( thread_ptr->dev.nic.status == false ) 
    140189    {
    141190        // get NIC-RX IRQ index and type
     
    144193
    145194        // enable NIC-RX IRQ
    146         dev_icu_enable_irq( core->lid , irq_type , irq_id , dev_ptr );
     195        dev_icu_enable_irq( local_cxy , core->lid , irq_type , irq_id , dev_xp );
    147196
    148197        // block on THREAD_BLOCKED I/O condition and deschedule
     
    151200
    152201        // disable NIC-RX channel IRQ
    153         dev_icu_disable_irq( core->lid , irq_type , irq_id );
     202        dev_icu_disable_irq( local_cxy , core->lid , irq_type , irq_id );
    154203    }
    155204
    156205    // call driver for actual read
    157     thread_ptr->command.nic.cmd     = NIC_CMD_READ;
    158     thread_ptr->command.nic.buffer  = pkd->buffer;
     206    thread_ptr->dev.nic.cmd     = NIC_CMD_READ;
     207    thread_ptr->dev.nic.buffer  = pkd->buffer;
    159208    dev_ptr->cmd( thread_xp );
    160209
    161210    // check error
    162     error = thread_ptr->command.nic.error;
     211    error = thread_ptr->dev.nic.error;
    163212    if( error ) return error;
    164213
    165214    // returns packet length   
    166     pkd->length = thread_ptr->command.nic.length;
     215    pkd->length = thread_ptr->dev.nic.length;
    167216
    168217    nic_dmsg("\n[INFO] %s exit for NIC-RX thread on core %d in cluster %x\n",
     
    189238                 __FUNCTION__ , core->lid , local_cxy );
    190239
    191     // get pointer on NIC-TX chdev descriptor
     240    // get pointer on NIC-TX device descriptor
    192241    uint32_t   channel = thread_ptr->dev_channel;
    193     xptr_t     dev_xp  = chdev_dir.nic_tx[channel];
     242    xptr_t     dev_xp  = devices_dir.nic_tx[channel];
    194243    cxy_t      dev_cxy = GET_CXY( dev_xp );
    195     chdev_t  * dev_ptr = (chdev_t *)GET_PTR( dev_xp );
    196 
    197     assert ( (dev_xp != XPTR_NULL) , __FUNCTION__ , "undefined NIC chdev descriptor" );
    198 
    199     assert( (dev_cxy == local_cxy) , __FUNCTION__ , " chdev must be local" );
     244    device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );
     245
     246    if ( dev_xp == XPTR_NULL )
     247    {
     248        printk("\n[PANIC] in %s : undefined NIC device descriptor\n", __FUNCTION__ );
     249        hal_core_sleep();
     250    }
     251
     252    if ( dev_cxy != local_cxy )
     253    {
     254        printk("\n[PANIC] in %s : device descriptor must be local\n", __FUNCTION__ );
     255        hal_core_sleep();
     256    }
    200257
    201258    // initialize command in thread descriptor
    202     thread_ptr->command.nic.dev_xp = dev_xp;
     259    thread_ptr->dev.nic.dev_xp = dev_xp;
    203260
    204261    // call driver to test writable
    205     thread_ptr->command.nic.cmd    = NIC_CMD_WRITABLE;
     262    thread_ptr->dev.nic.cmd    = NIC_CMD_WRITABLE;
    206263    dev_ptr->cmd( thread_xp );
    207264
    208265    // check error
    209     error = thread_ptr->command.nic.error;
     266    error = thread_ptr->dev.nic.error;
    210267    if( error ) return error;
    211268
    212269    // block and deschedule if queue non writable
    213     if( thread_ptr->command.nic.status == false ) 
     270    if( thread_ptr->dev.nic.status == false ) 
    214271    {
    215272        // get NIC-TX IRQ index and type
     
    218275
    219276        // enable NIC-TX IRQ
    220         dev_icu_enable_irq( core->lid , irq_type , irq_id , dev_ptr );
     277        dev_icu_enable_irq( local_cxy , core->lid , irq_type , irq_id , dev_xp );
    221278
    222279        // block on THREAD_BLOCKED I/O condition and deschedule
     
    225282
    226283        // disable NIC-TX IRQ
    227         dev_icu_disable_irq( core->lid , irq_type , irq_id );
     284        dev_icu_disable_irq( local_cxy , core->lid , irq_type , irq_id );
    228285    }
    229286
    230287    // call driver for actual write
    231     thread_ptr->command.nic.cmd    = NIC_CMD_WRITE;
    232     thread_ptr->command.nic.buffer = pkd->buffer;
    233     thread_ptr->command.nic.length = pkd->length;
     288    thread_ptr->dev.nic.cmd    = NIC_CMD_WRITE;
     289    thread_ptr->dev.nic.buffer = pkd->buffer;
     290    thread_ptr->dev.nic.length = pkd->length;
    234291    dev_ptr->cmd( thread_xp );
    235292
    236293    // check error
    237     error = thread_ptr->command.nic.error;
     294    error = thread_ptr->dev.nic.error;
    238295    if( error ) return error;
    239296
  • /trunk/kernel/devices/dev_nic.h

    r3 r1  
    7575/****  Forward declarations  ****/
    7676
    77 struct chdev_s;
     77struct device_s;
    7878
    7979/******************************************************************************************
     
    137137
    138138/******************************************************************************************
    139  * This function completes the NIC-RX and NIC-TX chdev descriptors initialisation.
    140  * namely the link with the implementation specific driver.
    141  * The func, impl, channel, is_rx, base fields have been previously initialised.
    142  * It calls the specific driver initialisation function, to initialise the hardware
    143  * device and the specific data structures when required.
    144  * It creates the associated server thread and allocates a WTI from local ICU.
    145  * It must de executed by a local thread.
    146  ******************************************************************************************
    147  * @ chdev    : local pointer on NIC chdev descriptor.
    148  *****************************************************************************************/
    149 void dev_nic_init( struct chdev_s * chdev );
     139 * This function completes the NIC-RX and NIC-TX devices descriptors initialisation.
     140 * The func, impl, channel, is_rx, base, and size have been previously initialised.
     141 * It calls the driver initialisation function.
     142 ******************************************************************************************
     143 * @ dev_xp     : extended pointer on NIC-RX or NIC-TX device descriptor.
     144 *****************************************************************************************/
     145void dev_nic_init( xptr_t  dev_xp );
    150146
    151147/******************************************************************************************
     
    223219 * becomes non empty.
    224220 ******************************************************************************************
    225  * @ dev     : local pointer on NIC chdev descriptor.
    226  *****************************************************************************************/
    227 void dev_nic_server( struct chdev_s * chdev );
     221 * @ dev     : local pointer on NIC channel device descriptor.
     222 *****************************************************************************************/
     223void dev_nic_server( struct device_s * dev );
    228224
    229225
  • /trunk/kernel/devices/dev_pic.c

    r3 r1  
    2525#include <hal_special.h>
    2626#include <dev_icu.h>
    27 #include <chdev.h>
     27#include <device.h>
    2828#include <memcpy.h>
    2929#include <printk.h>
     
    3535/////////////////////////////////////////////////////////////////////////////////////////
    3636
    37 extern chdev_directory_t  chdev_dir;         // allocated in kernel_init.c
     37extern devices_directory_t  devices_dir;         // allocated in kernel_init.c
    3838
    39 extern chdev_pic_input_t  chdev_pic_input;   // allocated in kernel_init.c
     39extern devices_input_irq_t  devices_input_irq;   // allocated in kernel_init.c
     40
     41
    4042
    4143///////////////////////////////////
    42 void dev_pic_init( chdev_t * chdev,
    43                    uint32_t  irq_nr )
     44void dev_pic_init( xptr_t   dev_xp,
     45                   uint32_t irq_nr )
    4446{
    45     // set PIC chdev extension field
    46     chdev->ext.pic.irq_nr = irq_nr;
     47    // get PIC device cluster and local pointer
     48    cxy_t      dev_cxy = GET_CXY( dev_xp );
     49    device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );
    4750
    48     // get implementation
    49     uint32_t impl = chdev->impl;
     51    // set PIC device extension field
     52    dev_ptr->ext.pic.irq_nr = irq_nr;
    5053
    51     // call the relevant driver init function
     54    // get implementation index from PIC device descriptor
     55    uint32_t impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) );
     56
     57    // set the "name" field in PIC device descriptor
     58    // and call the relevant driver init function
    5259    if( impl == IMPL_PIC_SOC )
    5360    {
    54         soclib_pic_init( chdev );
     61        memcpy( dev_ptr->name , "PIC_TSR" , 16 );
     62        soclib_pic_init( dev_xp );
    5563    }
    5664    else
    5765    {
    58         assert( false , __FUNCTION__ , "illegal PIC device implementation" );
     66        printk("PANIC in %s: illegal PIC device implementation\n", __FUNCTION__ );
     67        hal_core_sleep();
    5968    }
    6069} // end dev_pic_init()
     
    6675{
    6776    // get extended pointer on WTI mailbox
    68     xptr_t wti_xp = XPTR( cxy , dev_icu_wti_ptr( wti_id ) );
     77    xptr_t wti_xp = dev_icu_wti_xptr( cxy , wti_id );
    6978
    70     // get extended pointer on PIC chdev from directory
    71     xptr_t dev_xp = chdev_dir.pic;
     79    // get extended pointer on PIC device from directory
     80    xptr_t dev_xp = devices_dir.pic;
    7281
    73     // get PIC chdev cluster and local pointer
    74     cxy_t     dev_cxy = GET_CXY( dev_xp );
    75     chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );
     82    // get PIC device cluster and local pointer
     83    cxy_t      dev_cxy = GET_CXY( dev_xp );
     84    device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );
    7685
    7786    // get implementation index and segment base
     
    8392        soclib_pic_bind_irq( dev_xp , irq_id , wti_xp );
    8493    }
     94    else
     95    {
     96        printk("PANIC in %s: illegal PIC device implementation\n", __FUNCTION__ );
     97        hal_core_sleep();
     98    }
    8599}  // end dev_pic_link_wti()
    86100
     
    88102void dev_pic_unbind_irq( uint32_t irq_id )
    89103{
    90     // get extended pointer on PIC chdev from directory
    91     xptr_t dev_xp = chdev_dir.pic;
     104    // get extended pointer on PIC device from directory
     105    xptr_t dev_xp = devices_dir.pic;
    92106
    93     // get PIC chdev cluster and local pointer
    94     cxy_t     dev_cxy = GET_CXY( dev_xp );
    95     chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );
     107    // get PIC device cluster and local pointer
     108    cxy_t      dev_cxy = GET_CXY( dev_xp );
     109    device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );
    96110
    97111    // get implementation index
     
    103117        soclib_pic_unbind_irq( dev_xp , irq_id );
    104118    }
     119    else
     120    {
     121        printk("PANIC in %s: illegal PIC device implementation\n", __FUNCTION__ );
     122        hal_core_sleep();
     123    }
     124   
    105125} // end dev_pic_disable_irq()
    106126
  • /trunk/kernel/devices/dev_pic.h

    r3 r1  
    3939 * in the PIC device extension. 
    4040 * The "source" device for each input IRQ is also defined in the ''arch_info'' file,
    41  * and are stored in the ''chdev_input_irq'' global variable in kernel initialization.
     41 * and are stored in the ''devices_input_irq'' global variable in kernel initialization.
    4242 *
    4343 * This external peripheral does not execute I/O operations, but is just acting as a
     
    4848 ****************************************************************************************/
    4949 
    50 /****  Forward declarations  ****/
    51 
    52 struct chdev_s;
    53 
    5450/*****************************************************************************************
    55  * This defines the (implementation independant) extension for the PIC device.
     51 * This defines the (implementation independant) extension for the generic ICU device.
    5652 ****************************************************************************************/
    5753
     
    7672/*****************************************************************************************
    7773 * This function makes two initialisations:
    78  * - It initializes the PIC specific fields of the chdev descriptor.
     74 * - It initializes the PIC specific fields of the device descriptor.
    7975 * - it initializes the implementation specific PIC hardware device.
    8076 * It must be executed once in the kernel initialisation phase.
     
    8379 * @ uint32_t   : actual number of input IRQs.
    8480 ****************************************************************************************/
    85 void dev_pic_init( struct chdev_s * chdev,
    86                    uint32_t         irq_nr );
     81void dev_pic_init( xptr_t   xp_dev,
     82                   uint32_t irq_nr );
    8783
    8884/*****************************************************************************************
  • /trunk/kernel/devices/dev_txt.c

    r3 r1  
    3535/////////////////////////////////////////////////////////////////////////////////////////
    3636
    37 extern chdev_directory_t  chdev_dir;         // allocated in kernel_init.c
    38 
    39 extern chdev_pic_input_t  chdev_pic_input;   // allocated in kernel_init.c
    40 
    41 ////////////////////////////////////
    42 void dev_txt_init( chdev_t * chdev )
    43 {
    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" );
    48 
    49     // get implementation and channel index
    50     uint32_t  impl    = chdev->impl;
    51     uint32_t  channel = chdev->channel;
    52 
    53     // set fields "cmd", "isr", and call driver init function
     37extern devices_directory_t  devices_dir;         // allocated in kernel_init.c
     38
     39extern devices_input_irq_t  devices_input_irq;   // allocated in kernel_init.c
     40
     41//////////////////////////////////
     42void dev_txt_init( xptr_t  dev_xp )
     43{
     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 );
     47
     48    // get implementation index from device descriptor
     49    uint32_t  impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) );
     50
     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
    5460    if( impl == IMPL_TXT_TTY )
    5561    {
    56         chdev->cmd = &soclib_tty_cmd;
    57         chdev->isr = &soclib_tty_isr;
    58         soclib_tty_init( chdev );
     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 );
    5968    }
    6069    else
    6170    {
    62         assert( false , __FUNCTION__ , "undefined TXT device implementation" );
    63     }
    64 
    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 );
     71        printk("\n[PANIC] in %s: undefined TXT device implementation\n", __FUNCTION__ );
     72        hal_core_sleep();
     73    }
    7974
    8075    // create server thread
    81     thread_t * new_thread;
     76    xptr_t     new_thread_xp;
     77    thread_t * new_thread_ptr;
    8278    error_t    error;
    8379
    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" );
    90 
    91     // set "server" field in chdev descriptor
    92     chdev->server = new_thread;
     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 );
     98
     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 );
    93109   
    94110    // start server thread
    95     thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL );
     111    thread_unblock( new_thread_xp , THREAD_BLOCKED_GLOBAL );
    96112
    97113} // end dev_txt_init()
     
    99115
    100116//////////////////////////////////////////////////////////////////////////////////
    101 // This static function is called by dev_txt_read(), dev_txt_write() functions.
     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.
    102125////////////////////////////////////i/////////////////////////////////////////////
    103126static error_t dev_txt_access( uint32_t   type,
     
    112135
    113136    // check channel argument
    114     assert( (channel < CONFIG_MAX_TXT_CHANNELS) , __FUNCTION__ , "illegal channel index" );
    115 
    116     // get extended pointer on remote TXT chdev descriptor
    117     xptr_t  dev_xp = chdev_dir.txt[channel];
    118 
    119     assert( (dev_xp != XPTR_NULL) , __FUNCTION__ , "undefined TXT chdev descriptor" );
     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    }
     142
     143    // get extended pointer on remote TXT device descriptor
     144    xptr_t  dev_xp = devices_dir.txt[channel];
     145
     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    }
    120152
    121153    // register command in calling thread descriptor
    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;
    126 
    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 );
    131 
    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 );
     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;
     158
     159
     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    }   
    134213
    135214    // return I/O operation status from calling thread descriptor
    136     return this->command.txt.error; 
     215    return this->dev.txt.error; 
    137216
    138217}  // end dev_txt_access()
     
    146225}
    147226 
    148 /////////////////////////////////////////
    149 error_t dev_txt_read( uint32_t   channel,
    150                       char     * buffer )
    151 {
    152     return dev_txt_access( TXT_READ , channel , buffer , 1 );
    153 }
    154 
    155227///////////////////////////////////////////////
    156228error_t dev_txt_sync_write( uint32_t   channel,
     
    158230                            uint32_t   count )
    159231{
    160     // get pointer on calling thread
    161     thread_t * this = CURRENT_THREAD;
    162 
    163     // get extended pointer on TXT[0] chdev
    164     xptr_t  dev_xp = chdev_dir.txt[channel];
    165 
    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;
    171 
    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 ) );
    176 
    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 ) );
    181 
    182     // return I/O operation status from calling thread descriptor
    183     return this->command.txt.error;
    184  
    185 }  // end dev_txt_sync_write()
    186 
     232    return dev_txt_access( TXT_SYNC_WRITE , channel , buffer , count );
     233}
     234 
     235/////////////////////////////////////////
     236error_t dev_txt_read( uint32_t   channel,
     237                      char     * buffer )
     238{
     239    return dev_txt_access( TXT_READ , channel , buffer , 1 );
     240}
     241
     242/////////////////////////////////////
     243void dev_txt_server( device_t * dev )
     244{
     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
     250
     251    server = CURRENT_THREAD;
     252
     253    root_xp = XPTR( local_cxy , &dev->wait_root );
     254
     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 ) );
     261
     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        }
     273
     274        // get extended pointer on first client thread
     275        client_xp = XLIST_FIRST_ELEMENT( root_xp , thread_t , wait_list );
     276
     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
  • /trunk/kernel/devices/dev_txt.h

    r3 r1  
    3030/****  Forward declarations  ****/
    3131
    32 struct chdev_s ;
     32struct device_s ;
    3333
    3434/******************************************************************************************
     
    7979
    8080/******************************************************************************************
    81  * This function completes the TXT chdev descriptor initialisation,
     81 * This function completes the TXT device descriptor initialisation,
    8282 * namely the link with the implementation specific driver.
    83  * The func, impl, channel, is_rxt, base fields have been previously initialised.
     83 * The func, impl, channel, is_rxt, base, and size fields must be previously initialised.
    8484 * It calls the specific driver initialisation function, to initialise the hardware
    8585 * device and the driver specific data structures when required.
    86  * It creates the associated server thread and allocates a WTI from local ICU.
    87  * It must de executed by a local thread.
     86 * It creates the associated server thread.
     87 * It can be executed in another cluster than cluster containing the device descriptor
     88 * or the hardware device itself.
    8889 ******************************************************************************************
    89  * @ chdev     : local pointer on TXT device descriptor.
     90 * @ xp_dev     : extended pointer on TXT device descriptor.
    9091 *****************************************************************************************/
    91 void dev_txt_init( struct chdev_s * chdev );
     92void dev_txt_init( xptr_t xp_dev );
    9293
    9394/******************************************************************************************
    9495 * This blocking function read a single character from the terminal identified
    9596 * by the "channel" argument. The corresponding request is actually registered in the
    96  * chdev requests queue, and the calling thread is descheduled, blocked until
     97 * device pending requests queue, and the calling thread is descheduled, blocked until
    9798 * transfer completion.
    9899 * It must be called in the client cluster.
     
    108109 * This blocking function writes a character string on the terminal identified
    109110 * by the "channel" argument. The corresponding request is actually registered in the
    110  * chdev requests queue, and the calling thread is descheduled, blocked until
     111 * device pending requests queue, and the calling thread is descheduled, blocked until
    111112 * transfer completion.
    112113 * It must be called in the client cluster.
     
    122123
    123124 /***************************************************************************************
    124  * This low-level blocking function is used by the kernel to display one string on a
     125 * This low-level blocking function is used by the kernel to display one character on a
    125126 * given TXT channel without descheduling the calling thread,  without registering it
    126127 * in the TXT device waiting queue, and without using the TXT irq.
     
    135136                            uint32_t   count );
    136137
     138/******************************************************************************************
     139 * This function is executed by the server thread associated to the TXT device descriptor.
     140 * This thread is created and lauched by the dev_txt_init() function, and is used
     141 * by the TXT_READ and TXT_WRITE operation types. It executes an infinite loop to handle
     142 * sequencially all commands registered by the client threads in the device waiting queue.
     143 * 
     144 * The driver CMD function is blocking, and returns only when the command is completed.
     145 * can use a busy waiting policy, or block the server thread on the THREAD_BLOCKED_IO_ISR
     146 * condition and deschedule, using the ISR to reactivate the server thread.
     147 *
     148 * When the waiting queue is empty, the server thread blocks on the THREAD_BLOCKED_IO_CMD
     149 * condition and deschedule. It is re-activated by a client thread registering a command.
     150 ******************************************************************************************
     151 * @ dev     : local pointer on device descriptor.
     152 *****************************************************************************************/
     153void dev_txt_server( struct device_s * dev );
     154
    137155
    138156#endif  /* _DEV_TXT_H_ */
Note: See TracChangeset for help on using the changeset viewer.