Changeset 3


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

Introduce dev_fbf, dev dma, dev_iob

Location:
trunk/kernel/devices
Files:
4 added
12 edited
2 moved

Legend:

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

    r1 r3  
    2424#include <hal_types.h>
    2525#include <hal_special.h>
    26 #include <device.h>
     26#include <chdev.h>
    2727#include <thread.h>
    2828#include <cluster.h>
     
    3737/////////////////////////////////////////////////////////////////////////////////////////
    3838
    39 extern devices_directory_t  devices_dir;         // allocated in kernel_init.c
    40 
    41 extern devices_input_irq_t  devices_input_irq;   // allocated in kernel_init.c
    42 
    43 
    44 ///////////////////////////////////
    45 void 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 );
     39extern chdev_directory_t  chdev_dir;         // allocated in kernel_init.c
     40
     41extern chdev_pic_input_t  chdev_pic_input;   // allocated in kernel_init.c
     42
     43/////////////////////////////////
     44void 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 );
    6755   
    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
     56    // get implementation
     57    uint32_t impl = icu->impl;
     58
     59    // call the relevant driver init function
    7360    if( impl == IMPL_ICU_XCU )
    7461    {
    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++ )
     62        uint32_t  lid;
     63        for( lid = 0 ; lid < LOCAL_CLUSTER->cores_nr ; lid++ )
    8064        {
    81             soclib_xcu_init( dev_ptr , lid );
     65            soclib_xcu_init( icu , lid );
    8266        }
    8367    }
    8468    else
    8569    {
    86         printk("\n[PANIC] %s : undefined ICU implementation for cluste %x\n",
    87                __FUNCTION__ , local_cxy );
    88         hal_core_sleep();
     70        assert( false , __FUNCTION__ , "undefined ICU implementation" );
    8971    }
    9072} // end dev_icu_init()
    9173
    9274/////////////////////////////////////////////////////////////////////////////////////
    93 // This static function check the irq_type / irq_index arguments for a remote ICU.
     75// This static function check the irq_type / irq_index arguments.
    9476// 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
    9677/////////////////////////////////////////////////////////////////////////////////////
    97 static inline void dev_icu_check_irq( xptr_t     icu_xp,
     78static inline void dev_icu_check_irq( chdev_t  * icu,
    9879                                      uint32_t   irq_type,
    9980                                      uint32_t   irq_index )
    10081{
    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 
    10582    if( irq_type == HWI_TYPE )
    10683    {
    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         }
     84        assert( (irq_index < icu->ext.icu.hwi_nr) , __FUNCTION__ , "illegal HWI" );
    11385    }
    11486    if( irq_type == WTI_TYPE )
    11587    {
    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         }
     88        assert( (irq_index < icu->ext.icu.wti_nr) , __FUNCTION__ , "illegal WTI" );
    12289    }
    12390    if( irq_type == PTI_TYPE )
    12491    {
    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 ////////////////////////////////////////////
    135 void dev_icu_enable_irq( cxy_t      icu_cxy,
    136                          lid_t      lid,
     92        assert( (irq_index < icu->ext.icu.pti_nr) , __FUNCTION__ , "illegal PTI" );
     93    }
     94}  // end dev_icu_check_irq()
     95
     96////////////////////////////////////////
     97void dev_icu_enable_irq( lid_t      lid,
    13798                         uint32_t   irq_type,
    13899                         uint32_t   irq_index,
    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 );
     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 );
    144105
    145106    // check IRQ type and index
    146     dev_icu_check_irq( icu_xp , irq_type , irq_index );
     107    dev_icu_check_irq( icu , irq_type , irq_index );
    147108
    148109    // (1) call implementation specific ICU driver to enable IRQ
    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 );
     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;
    174123
    175124}  // end dev_icu_enable_irq()
    176125
    177 /////////////////////////////////////////////
    178 void dev_icu_disable_irq( cxy_t      icu_cxy,
    179                           lid_t      lid,
     126/////////////////////////////////////////
     127void dev_icu_disable_irq( lid_t      lid,
    180128                          uint32_t   irq_type,
    181129                          uint32_t   irq_index )
    182130{
    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 );
     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 );
    186134
    187135    // check IRQ type and index
    188     dev_icu_check_irq( icu_xp , irq_type , irq_index );
     136    dev_icu_check_irq( icu , irq_type , irq_index );
    189137
    190138    // (1) call the implementation specific ICU driver to disable IRQ
    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();
     139    if( icu->impl == IMPL_ICU_XCU )
     140    {
     141        soclib_xcu_disable_irq( icu , 1<<irq_index , irq_type , lid );
    199142    }
    200143
    201144    // (2) get selected remote core local pointer, and remove
    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 );
     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 );
    207149
    208150} // end dev_icu_disable_irq()
     
    212154                         uint32_t   period )
    213155{
    214     // get pointer on local ICU device descriptor
    215     core_t   * core = CURRENT_CORE;
    216     device_t * icu  = core->icu;
     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 );
    217159
    218160    // check 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     }
     161    assert( (pti_index < icu->ext.icu.pti_nr) , __FUNCTION__ , "illegal PTI index" );
    224162
    225163    // call the implementation specific driver ICU to set period
     
    233171void dev_icu_ack_timer( uint32_t pti_index )
    234172{
    235     // get pointer on local ICU device descriptor
    236     core_t   * core = CURRENT_CORE;
    237     device_t * icu  = core->icu;
     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 );
    238176
    239177    // check 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     }
     178    assert( (pti_index < icu->ext.icu.pti_nr) , __FUNCTION__ , "illegal PTI index" );
    245179
    246180    // call the implementation specific driver ICU to acknowledge PTI IRQ
     
    249183        soclib_xcu_ack_timer( icu , pti_index );
    250184    }
    251     else
    252     {
    253         printk("\n[PANIC] in %s : undefined ICU implementation" , __FUNCTION__ );
    254         hal_core_sleep();
    255     }
    256 
    257185}  // end dev_icu_ack_timer()
    258186
     
    270198    uint32_t    y = cxy & ((1<<y_width)-1);
    271199
    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];
     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];
    283206
    284207     // get target ICU cluster and local pointer
    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 ) );   
     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 ) );   
    290213
    291214    // call the implementation specific ICU driver to send IPI
     
    293216    {
    294217        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();
    300218    }
    301219}  // end dev_icu_send_ipi()
     
    307225    uint32_t   wti_status;   // WTI index + 1  / no pending WTI if 0
    308226    uint32_t   pti_status;   // PTI index + 1  / no pending PTI if 0
    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
     227    chdev_t  * src_chdev;    // pointer on source chdev descriptor
    312228    uint32_t   index;        // IRQ index
    313229
    314     // get pointer on local ICU device descriptor
    315230    core_t   * core = CURRENT_CORE;
    316     device_t * icu  = core->icu;
     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 );
    317235
    318236    // call the implementation specific ICU driver 
     
    322240        soclib_xcu_get_status( icu , core->lid , &hwi_status , &wti_status , &pti_status );
    323241    }
    324     else
    325     {
    326         printk("\n[PANIC] in %s : undefined ICU implementation" , __FUNCTION__ );
    327         hal_core_sleep();
    328     }
    329242
    330243    // analyse ICU status and handle up to 3 pending IRQ (one WTI, one HWI, one PTI)
    331244
    332     if( wti_status )          // pending WTI TODO what about IPIs ???  [AG]
     245    if( wti_status )          // pending WTI
    333246        {
    334247        index = wti_status - 1;
    335248
    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
     249        if( index < LOCAL_CLUSTER->cores_nr )   // it is an IPI
    349250        {
    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();
     251            assert( (index == core->lid) , __FUNCTION__ , "illegal IPI index" );
     252
     253            // TODO acknowledge WTI [AG]
     254
     255            // TODO force scheduling [AG]
    353256        }
    354         else                                 // call relevant ISR
     257        else                                    // it is an external device
    355258        {
    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 );
     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            }
    360277        }
    361278        }
     
    365282        index = hwi_status - 1;
    366283
    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
     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
    373288                {
    374289            printk("\n[WARNING] in %s : no handler for HWI %d on core %d in cluster %x\n",
    375290                   __FUNCTION__ , index , core->lid , local_cxy );
    376291                core->spurious_irqs ++;
    377             dev_icu_disable_irq( local_cxy , core->lid , HWI_TYPE , index );
     292            dev_icu_disable_irq( core->lid , HWI_TYPE , index );
    378293                }
    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         }
    385294        else                    // call relevant ISR
    386295        {
     
    388297                     __FUNCTION__ , index , core->lid , local_cxy );
    389298
    390                     src_dev_ptr->isr( src_dev_ptr );
     299            // call ISR
     300                    src_chdev->isr( src_chdev );
    391301        }
    392302        }
     
    402312        dev_icu_ack_timer( index );
    403313
    404         // execute all actions related to TICK event
     314        // TODO execute all actions related to TICK event
    405315        core_clock( core );
    406316        }
     
    410320uint32_t dev_icu_wti_alloc()
    411321{
    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;
     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;
    418328    spinlock_t * lock   = &icu->ext.icu.wti_lock;
    419329    uint32_t     size   =  icu->ext.icu.wti_nr;
     
    437347void dev_icu_wti_release( uint32_t index )
    438348{
    439     // get pointer on local ICU device descriptor
    440     core_t   * core = CURRENT_CORE;
    441     device_t * icu  = core->icu;
     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 );
    442352
    443353    // get bitmap pointer, lock, and size
    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;
     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;
    447357
    448358    // check 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     }
     359    assert( (index < size) , __FUNCTION__ , "illegal WTI index" );
    455360
    456361    // get lock protecting WTI allocator
     
    462367    // release lock
    463368    spinlock_unlock( lock );
     369
    464370}  // end dev_icu_wti_release()
    465371
    466 ///////////////////////////////////////
    467 xptr_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;
     372//////////////////////////////////////////////
     373uint32_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 );
    475380
    476381    // call implementation specific ICU driver
    477382    if( icu->impl == IMPL_ICU_XCU )
    478383    {
    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 
     384        wti_ptr = soclib_xcu_wti_ptr( icu , wti_id );   
     385    }
     386
     387    return wti_ptr;
    490388}   // end dev_icu_wti_xptr()
    491389
  • trunk/kernel/devices/dev_icu.h

    r1 r3  
    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 should be routed to the core that started the I/O operation.
     37 * operation. Each IRQ is 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, centralized or distributed
     41 * This component can be implemented as a dedicated hardware component 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 iby this ICU device:
     46 * ALMOS-MKH defines three types of IRQs, that are handled by 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  * 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.
     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.
    7676 *
    7777 * The ICU peripheral does not execute I/O operations, but is just acting as a
    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
     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
    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 device_s;
     86struct chdev_s;
    8787
    8888/*****************************************************************************************
     
    127127/*****************************************************************************************
    128128 * This function makes two initialisations:
    129  * - It initialises the ICU specific fields of the device descriptor.
     129 * - It initialises the ICU specific fields of the chdev descriptor.
    130130 * - it initialises the implementation specific ICU hardware device and associated
    131131 *   data structures if required.
    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  ****************************************************************************************/
    139 void 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.
     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 ****************************************************************************************/
     139void 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.
    147147 * The target core is identified by its local index.
    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
     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
    151151 *   relevant interrupt vector of the 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.
     152 * - It register the IRQ type and index in the "source" chdev descriptor.
     153 *****************************************************************************************
     154 * @ lid        : local index of selected core.
    156155 * @ irq_type   : HWI/WTI/PTI.
    157  * @ irq_id     : IRQ index in remote ICU
    158  * @ src_dev_xp : extended pointer on device descriptor source of IRQ.
    159  ****************************************************************************************/
    160 void 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.
     156 * @ irq_id     : IRQ index in ICU
     157 * @ chdev      : pointer on source chdev descriptor.
     158 ****************************************************************************************/
     159void 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.
    169167 * The core is identified by its local index.
    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
     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
    173171 *   relevant interrupt vector of the selected core.
    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).
     172 * - The IRQ type and index fields are not modified in the "source" chdev descriptor.
     173 *****************************************************************************************
    177174 * @ lid       : local index of selected core in remote cluster.
    178175 * @ irq_type  : HWI/WTI/PTI.
    179176 * @ irq_id    : IRQ index.
    180177 ****************************************************************************************/
    181 void dev_icu_disable_irq( cxy_t      cxy,
    182                           lid_t      lid,
     178void dev_icu_disable_irq( lid_t      lid,
    183179                          uint32_t   irq_type,
    184180                          uint32_t   irq_id );
     
    187183 * This function set the period value for a timer identified by the PTI index,
    188184 * in the local ICU device descriptor.
     185 * It must be called by a local thread.
    189186 *****************************************************************************************
    190187 * @ pti_id    : PTI index.
     
    197194 * This function acknowledge a PTI IRQ for a timer identified by the PTI index,
    198195 * in the local ICU device descriptor.
     196 * It must be called by a local thread.
    199197 *****************************************************************************************
    200198 * @ pti_id    : PTI index.
     
    204202/*****************************************************************************************
    205203 * This function send an IPI (Inter Processor Interrupt) to a core identified by
    206  * its cluster identifier and local index.
     204 * its cluster identifier and local index.
     205 * It can be called by any thread running in any cluster.
    207206 * This IPI force a context switch, and the handling of pending RPC(s).
    208207 *****************************************************************************************
     
    226225
    227226/*****************************************************************************************
    228  * This function implements the WTI mailbox allocator. It is used by all I/O operations
    229  * for completion signaling.
     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.
    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.
    242243 * It does not access the hardware device.
    243244 *****************************************************************************************
     
    247248
    248249/*****************************************************************************************
    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  ****************************************************************************************/
    257 xptr_t  dev_icu_wti_xptr( cxy_t    cxy,
    258                           uint32_t wti_id );
     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 ****************************************************************************************/
     256uint32_t * dev_icu_wti_ptr( uint32_t wti_id );
    259257
    260258#endif  /* _DEV_ICU_H_ */
  • trunk/kernel/devices/dev_iob.c

    r1 r3  
    11/*
    2  * dev_iox.c - IOX (bridge to external I/O) generic device API implementation.
     2 * dev_iob.c - IOB (bridge to external I/O) generic device API implementation.
    33 *
    44 * Authors   Alain Greiner  (2017)
     
    1414 * ALMOS-MKH is distributed in the hope that it will be useful, but
    1515 * WITHOUT ANY WARRANTY; without even the implied warranty of
    16  * MERCHANTABILITY or FITNESS FOR A PARTIOXLAR PURPOSE.  See the GNU
     16 * MERCHANTABILITY or FITNESS FOR A PARTIOBLAR PURPOSE.  See the GNU
    1717 * General Public License for more details.
    1818 *
     
    2626#include <hal_special.h>
    2727#include <remote_spinlock.h>
    28 #include <device.h>
     28#include <chdev.h>
    2929#include <printk.h>
    3030#include <soclib_iob.h>
    31 #include <dev_iox.h>
     31#include <dev_iob.h>
    3232
    33 //////////////////////////////////
    34 void dev_iox_init( xptr_t dev_xp )
     33////////////////////////////////////
     34void dev_iob_init( chdev_t * chdev )
    3535{
    36     // get IOX device descriptor cluster and local pointer
    37     cxy_t      dev_cxy = GET_CXY( dev_xp );
    38     device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );
    39 
    40     // get implementation from device descriptor
    41     uint32_t  impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) );
     36    // get implementation
     37    uint32_t  impl = chdev->impl;
    4238
    4339    // call driver init function
    44     if( impl == IMPL_IOX_IOB )
     40    if( impl == IMPL_IOB_TSR )
    4541    {
    46         soclib_iob_init( dev_xp );
     42        soclib_iob_init( chdev );
    4743    }
    4844    else
    4945    {
    50         printk("\n[PANIC] in %s: undefined IOX device implementation\n", __FUNCTION__ );
    51         hal_core_sleep();
     46        assert( false , __FUNCTION__ , "undefined IOB device implementation\n" );
    5247    }
    5348}
    5449
    5550//////////////////////////////////////////
    56 void dev_iox_iommu_enable( xptr_t dev_xp )
     51void dev_iob_iommu_enable( xptr_t dev_xp )
    5752{
    58     // get IOX device descriptor cluster and local pointer
    59     cxy_t      dev_cxy = GET_CXY( dev_xp );
    60     device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );
     53    // get IOB chdev descriptor cluster and local pointer
     54    cxy_t     dev_cxy = GET_CXY( dev_xp );
     55    chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );
    6156
    62     // get implementation from device descriptor
     57    // get implementation from chdev descriptor
    6358    uint32_t  impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) );
    6459
    6560    // call driver function
    66     if( impl == IMPL_IOX_IOB )
     61    if( impl == IMPL_IOB_TSR )
    6762    {
    6863        remote_spinlock_lock( XPTR( dev_cxy , &dev_ptr->wait_lock ) );
     
    7267    else
    7368    {
    74         printk("\n[PANIC] in %s: undefined IOX device implementation\n", __FUNCTION__ );
     69        printk("\n[PANIC] in %s: undefined IOB device implementation\n", __FUNCTION__ );
    7570        hal_core_sleep();
    7671    }
     
    7873
    7974///////////////////////////////////////////
    80 void dev_iox_iommu_disable( xptr_t dev_xp )
     75void dev_iob_iommu_disable( xptr_t dev_xp )
    8176{
    82     // get IOX device descriptor cluster and local pointer
    83     cxy_t      dev_cxy = GET_CXY( dev_xp );
    84     device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );
     77    // get IOB chdev descriptor cluster and local pointer
     78    cxy_t     dev_cxy = GET_CXY( dev_xp );
     79    chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );
    8580
    86     // get implementation from device descriptor
     81    // get implementation from chdev descriptor
    8782    uint32_t  impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) );
    8883
    8984    // call driver function
    90     if( impl == IMPL_IOX_IOB )
     85    if( impl == IMPL_IOB_TSR )
    9186    {
    9287        remote_spinlock_lock( XPTR( dev_cxy , &dev_ptr->wait_lock ) );
     
    9691    else
    9792    {
    98         printk("\n[PANIC] in %s: undefined IOX device implementation\n", __FUNCTION__ );
     93        printk("\n[PANIC] in %s: undefined IOB device implementation\n", __FUNCTION__ );
    9994        hal_core_sleep();
    10095    }
     
    10297
    10398////////////////////////////////////////
    104 void dev_iox_set_ptpr( xptr_t    dev_xp,
     99void dev_iob_set_ptpr( xptr_t    dev_xp,
    105100                       uint32_t  wdata )
    106101{
    107     // get IOX device descriptor cluster and local pointer
    108     cxy_t      dev_cxy = GET_CXY( dev_xp );
    109     device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );
     102    // get IOB chdev descriptor cluster and local pointer
     103    cxy_t     dev_cxy = GET_CXY( dev_xp );
     104    chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );
    110105
    111     // get implementation from device descriptor
     106    // get implementation from chdev descriptor
    112107    uint32_t  impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) );
    113108
    114109    // call driver function
    115     if( impl == IMPL_IOX_IOB )
     110    if( impl == IMPL_IOB_TSR )
    116111    {
    117112        remote_spinlock_lock( XPTR( dev_cxy , &dev_ptr->wait_lock ) );
     
    121116    else
    122117    {
    123         printk("\n[PANIC] in %s: undefined IOX device implementation\n", __FUNCTION__ );
     118        printk("\n[PANIC] in %s: undefined IOB device implementation\n", __FUNCTION__ );
    124119        hal_core_sleep();
    125120    }
     
    127122                       
    128123////////////////////////////////////////
    129 void dev_iox_inval_page( xptr_t  dev_xp,
     124void dev_iob_inval_page( xptr_t  dev_xp,
    130125                         vpn_t   vpn )
    131126{
    132     // get IOX device descriptor cluster and local pointer
    133     cxy_t      dev_cxy = GET_CXY( dev_xp );
    134     device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );
     127    // get IOB chdev descriptor cluster and local pointer
     128    cxy_t     dev_cxy = GET_CXY( dev_xp );
     129    chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );
    135130
    136     // get implementation from device descriptor
     131    // get implementation from chdev descriptor
    137132    uint32_t  impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) );
    138133
    139134    // call driver function
    140     if( impl == IMPL_IOX_IOB )
     135    if( impl == IMPL_IOB_TSR )
    141136    {
    142137        remote_spinlock_lock( XPTR( dev_cxy , &dev_ptr->wait_lock ) );
     
    146141    else
    147142    {
    148         printk("\n[PANIC] in %s: undefined IOX device implementation\n", __FUNCTION__ );
     143        printk("\n[PANIC] in %s: undefined IOB device implementation\n", __FUNCTION__ );
    149144        hal_core_sleep();
    150145    }
     
    152147
    153148///////////////////////////////////////////
    154 void dev_iox_get_status( xptr_t     dev_xp,
     149void dev_iob_get_status( xptr_t     dev_xp,
    155150                         uint32_t * error,
    156151                         uint32_t * bvar,
    157152                         uint32_t * srcid )
    158153{
    159     // get IOX device descriptor cluster and local pointer
    160     cxy_t      dev_cxy = GET_CXY( dev_xp );
    161     device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );
     154    // get IOB chdev descriptor cluster and local pointer
     155    cxy_t     dev_cxy = GET_CXY( dev_xp );
     156    chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );
    162157
    163     // get implementation from device descriptor
     158    // get implementation from chdev descriptor
    164159    uint32_t  impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) );
    165160
    166161    // call driver function
    167     if( impl == IMPL_IOX_IOB )
     162    if( impl == IMPL_IOB_TSR )
    168163    {
    169164        remote_spinlock_lock( XPTR( dev_cxy , &dev_ptr->wait_lock ) );
     
    175170    else
    176171    {
    177         printk("\n[PANIC] in %s: undefined IOX device implementation\n", __FUNCTION__ );
     172        printk("\n[PANIC] in %s: undefined IOB device implementation\n", __FUNCTION__ );
    178173        hal_core_sleep();
    179174    }
  • trunk/kernel/devices/dev_iob.h

    r1 r3  
    11/*
    2  * dev_iox.h - IOX (bridge to external I/O) generic device API.
     2 * dev_iob.h - IOB (bridge to external I/O) generic device API.
    33 *
    44 * Authors   Alain Greiner  (2016)
     
    1414 * ALMOS-MKH is distributed in the hope that it will be useful, but
    1515 * WITHOUT ANY WARRANTY; without even the implied warranty of
    16  * MERCHANTABILITY or FITNESS FOR A PARTIOXLAR PURPOSE.  See the GNU
     16 * MERCHANTABILITY or FITNESS FOR A PARTIOBLAR PURPOSE.  See the GNU
    1717 * General Public License for more details.
    1818 *
     
    2222 */
    2323
    24 #ifndef _DEV_IOX_H_
    25 #define _DEV_IOX_H_
     24#ifndef _DEV_IOB_H_
     25#define _DEV_IOB_H_
    2626
    2727#include <almos_config.h>
     
    3030
    3131/*****************************************************************************************
    32  *     Generic IOX (bridge to external IO peripherals) definition.
     32 *     Generic IOB (bridge to external IO peripherals) definition.
    3333 *
    34  * The IOX device is used to access external peripherals. It implements an IO-MMU service
     34 * The IOB device is used to access external peripherals. It implements an IO-MMU service
    3535 * for DMA transactions launched by DMA capable external peripherals.
    36  * This IOX peripheral is acting as a dynamically configurable bridge, used for others
    37  * I/O operations. Therefore, ALMOS-MKH does not use the IOX device waiting queue,
    38  * and calls directly the IOX driver blocking functions, using the device lock to
    39  * get exclusive access to the IOX bridge internal state.
     36 * This IOB peripheral is acting as a dynamically configurable bridge, used for others
     37 * I/O operations. Therefore, ALMOS-MKH does not use the IOB device waiting queue,
     38 * and calls directly the IOB driver blocking functions, using the device lock to
     39 * get exclusive access to the IOB bridge internal state.
    4040 ****************************************************************************************/
    4141 
     42/****  Forward declarations  ****/
     43
     44struct chdev_s;
    4245
    4346/*****************************************************************************************
    44  * This enum defines the various implementations of the IOX generic device.
     47 * This enum defines the various implementations of the IOB generic device.
    4548 * This array must be kept consistent with the define in arch_info.h file
    4649 ****************************************************************************************/
    4750
    48 enum iox_impl_e
     51enum iob_impl_e
    4952{
    50     IMPL_IOX_IOB =   0,         /* vci_iob component used in TSAR                       */
    51     IMPL_IOX_I86 =   1,         /* TBD                                                  */
     53    IMPL_IOB_TSR =   0,         /* vci_iob component used in TSAR                       */
     54    IMPL_IOB_I86 =   1,         /* TBD                                                  */
    5255}
    53 iox_impl_t;
     56iob_impl_t;
    5457
    5558/*****************************************************************************************
    56  * This function initializes the IOX device descriptor with IOMMU disabled.
     59 * This function initializes the IOB device descriptor with IOMMU disabled.
    5760 *****************************************************************************************
    58  * @ dev_xp     : extended pointer on IOX device descriptor.
     61 * @ chdev      :  pointer on IOB chdev descriptor.
    5962 ****************************************************************************************/
    60 void dev_iox_init( xptr_t dev_xp );
     63void dev_iob_init( struct chdev_s * chdev );
    6164
    6265/*****************************************************************************************
    63  * This function activates the IOMMU for the IOX device identified by its
     66 * This function activates the IOMMU for the IOB device identified by its
    6467 * extended pointer.
    6568 *****************************************************************************************
    66  * @ dev_xp   : extended pointer on IOX device descriptor.
     69 * @ dev_xp   : extended pointer on IOB device descriptor.
    6770 ****************************************************************************************/
    68 void dev_iox_iommu_enable( xptr_t dev_xp );
     71void dev_iob_iommu_enable( xptr_t dev_xp );
    6972
    7073/*****************************************************************************************
    71  * This function desactivates the IO-MMU for the IOX device identified by its
     74 * This function desactivates the IO-MMU for the IOB device identified by its
    7275 * extended pointer.
    7376 *****************************************************************************************
    74  * @ dev_xp   : extended pointer on IOX device descriptor.
     77 * @ dev_xp   : extended pointer on IOB device descriptor.
    7578 ****************************************************************************************/
    76 void dev_iox_iommu_disable( xptr_t dev_xp );
     79void dev_iob_iommu_disable( xptr_t dev_xp );
    7780
    7881/*****************************************************************************************
    7982 * This function set a new value in the IO-MMU PTPR register.
    8083 *****************************************************************************************
    81  * @ dev_xp   : extended pointer on IOX device descriptor.
     84 * @ dev_xp   : extended pointer on IOB device descriptor.
    8285 * @ wdata    : value to be written in PTPR register.
    8386 ****************************************************************************************/
    84 void dev_iox_set_ptpr( xptr_t    dev_xp,
     87void dev_iob_set_ptpr( xptr_t    dev_xp,
    8588                       uint32_t  wdata );
    8689                       
     
    8891 * This function invalidates an IOMMU TLB entry identified by its vpn.
    8992 *****************************************************************************************
    90  * @ dev_xp   : extended pointer on IOX device descriptor.
     93 * @ dev_xp   : extended pointer on IOB device descriptor.
    9194 * @ vpn      : virtual page number in IO virtual space.
    9295 ****************************************************************************************/
    93 void dev_iox_inval_page( xptr_t  dev_xp,
     96void dev_iob_inval_page( xptr_t  dev_xp,
    9497                         vpn_t   vpn );
    9598
     
    97100 * This function return informations relative to an error reported by the IOMMU.
    98101 *****************************************************************************************
    99  * @ dev_xp   : extended pointer on IOX device descriptor.
     102 * @ dev_xp   : extended pointer on IOB device descriptor.
    100103 * @ error    : [out] pointer on buffer for erro type.
    101104 * @ bvar     : [out] pointer on buffer for bad virtual address.
    102105 * @ srcid    : [out] pointer on buffer for faulty peripheral index.
    103106 ****************************************************************************************/
    104 void dev_iox_get_status( xptr_t     dev_xp,
     107void dev_iob_get_status( xptr_t     dev_xp,
    105108                         uint32_t * error,
    106109                         uint32_t * bvar,
    107110                         uint32_t * srcid );
    108111
    109 #endif  /* _DEV_IOX_H_ */
     112#endif  /* _DEV_IOB_H_ */
  • trunk/kernel/devices/dev_ioc.c

    r1 r3  
    3232#include <thread.h>
    3333#include <printk.h>
     34#include <chdev.h>
    3435#include <dev_ioc.h>
    3536
     
    3839/////////////////////////////////////////////////////////////////////////////////////////
    3940
    40 extern devices_directory_t  devices_dir;         // allocated in kernel_init.c
     41extern chdev_directory_t  chdev_dir;         // allocated in kernel_init.c
    4142
    42 extern devices_input_irq_t  devices_input_irq;   // allocated in kernel_init.c
     43extern chdev_pic_input_t  chdev_pic_input;   // allocated in kernel_init.c
    4344
    44 //////////////////////////////////
    45 void dev_ioc_init( xptr_t dev_xp )
     45////////////////////////////////////
     46void dev_ioc_init( chdev_t * chdev )
    4647{
    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 );
     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" );
    5052
    51     // get implementation from device descriptor
    52     uint32_t  impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) );
     53    // get implementation and channel from chdev descriptor
     54    uint32_t  impl    = chdev->impl;
     55    uint32_t  channel = chdev->channel;
    5356
    54     // set driver specific fields in device descriptor
    55     // and call driver init function
     57    // set driver specific fields in chdev descriptor and call driver init function
    5658    if( impl == IMPL_IOC_BDV )
    5759    {
    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 );
     60        chdev->cmd = &soclib_bdv_cmd;
     61        chdev->isr = &soclib_bdv_isr;
     62        soclib_bdv_init( chdev );
    6363    }
    6464    else if( impl == IMPL_IOC_HBA )
    6565    {
    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 );
     66        chdev->cmd = &soclib_hba_command;
     67        chdev->isr = &soclib_hba_isr;
     68        soclib_hba_init( chdev );
    7169    }
    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 //    }
    9670    else
    9771    {
    98         printk("\n[PANIC] in %s: undefined IOC device implementation\n", __FUNCTION__ );
    99         hal_core_sleep();
     72        assert( false , __FUNCTION__ , "undefined IOC device implementation" );
    10073    }
    10174
     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 );
     89
    10290    // create server thread
    103     thread_t * new_thread_ptr;
    104     xptr_t     new_thread_xp;
     91    thread_t * new_thread;
    10592    error_t    error;
    10693
    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() );
     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" );
    114100
    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 );
     101    // set "server" field in chdev descriptor
     102    chdev->server = new_thread;
    136103   
    137104    // start server thread
    138     thread_unblock( new_thread_xp , THREAD_BLOCKED_GLOBAL );
     105    thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL );
    139106 
    140107}  // end dev_ioc_init()
     
    144111// It builds and registers the command in the calling thread descriptor, after
    145112// translation of buffer virtual address to physical address.
    146 // Then, it registers the calling thead in device waiting queue.
     113// Then, it registers the calling thead in chdev waiting queue.
    147114// Finally it blocks on the THREAD_BLOCKED_DEV condition and deschedule.
    148115////////////////////////////////////i/////////////////////////////////////////////
     
    152119                               uint32_t  count )
    153120{
    154     thread_t  * this      = CURRENT_THREAD;              // pointer on client thread
    155     cxy_t       local_cxy = local_cxy;                   // client thread cluster
     121    thread_t * this = CURRENT_THREAD;              // pointer on client thread
    156122
    157123    error_t     error;
    158124    paddr_t     buf_paddr;
    159     bool_t      ident = CONFIG_KERNEL_IDENTITY;
    160125
    161126    // Get buffer physical address
    162     error = vmm_v2p_translate( ident , buffer , &buf_paddr );
     127    error = vmm_v2p_translate( CONFIG_KERNEL_IDENTITY , buffer , &buf_paddr );
    163128 
    164129    if( error )  return EINVAL;
    165130
    166131    ioc_dmsg("\n[INFO] in %s : thread %x in process %x"
    167              " for lba = %x / vaddr = %x / paddr = %llx\n",
     132             " for lba = %x / vaddr = %x / paddr = %l / at cycle %d\n",
    168133             __FUNCTION__ , this->trdid , this->process->pid ,
    169              lba , (uint32_t)buffer , buf_paddr );
     134             lba , (uint32_t)buffer , buf_paddr , hal_time_stamp() );
    170135
    171136#if USE_IOB    // software L2/L3 cache coherence for memory buffer
     
    176141#endif     // end software L2/L3 cache coherence
    177142
    178     // get extended pointer on IOC device descriptor
    179     xptr_t  dev_xp = devices_dir.ioc;
     143    // get extended pointer on IOC chdev descriptor
     144    xptr_t  dev_xp = chdev_dir.ioc[0];
    180145
    181     if ( dev_xp == XPTR_NULL )
    182     {
    183         printk("\n[PANIC] in %s : undefined IOC device descriptor\n", __FUNCTION__ );
    184         hal_core_sleep();
    185     }
     146    assert( (dev_xp != XPTR_NULL) , __FUNCTION__ , "undefined IOC chdev descriptor" );
    186147
    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     }
     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;
    195154
    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,
     155    // register client thread in IOC chdev waiting queue, activate server thread,
    211156    // block client thread on THREAD_BLOCKED_IO and deschedule.
    212157    // it is re-activated by the ISR signaling IO operation completion.
    213     device_register_command( dev_xp , this );
     158    chdev_register_command( dev_xp , this );
    214159
    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 );
     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() );
    226164
    227165    // return I/O operation status
    228     return this->dev.ioc.error; 
     166    return this->command.ioc.error; 
    229167
    230168}  // end dev_ioc_access()
     
    245183    return dev_ioc_access( false , buffer , lba , count );
    246184}
    247                        
    248 /////////////////////////////////////
    249 void 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

    r1 r3  
    2525#define _DEV_IOC_H
    2626
     27#include <almos_config.h>
    2728#include <hal_types.h>
    2829
    2930/****  Forward declarations  ****/
    3031
    31 struct device_s;
     32struct chdev_s;
    3233
    3334/*****************************************************************************************
     
    104105
    105106/******************************************************************************************
    106  * This function completes the IOC device descriptor initialisation,
     107 * This function completes the IOC chdev descriptor initialisation,
    107108 * namely the link with the implementation specific driver.
    108  * The func, impl, channel, is_rxt, base, and size fields must be previously initialised.
     109 * The func, impl, channel, is_rx, base fields have been previously initialised.
    109110 * It calls the specific driver initialisation function, to initialise the hardware
    110111 * device and the specific data structures when required.
    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.
     112 * It creates the associated server thread and allocates a WTI from local ICU.
     113 * It must de executed by a local thread.
    114114 ******************************************************************************************
    115  * @ xp_dev     : extended pointer on IOC device descriptor.
     115 * @ chdev     : local pointer on IOC chdev descriptor.
    116116 *****************************************************************************************/
    117 void dev_ioc_init( xptr_t  xp_dev );
     117void dev_ioc_init( struct chdev_s * chdev );
    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  *****************************************************************************************/
    169 void dev_ioc_server( struct device_s * dev );
    170 
    171151#endif  /* _DEV_IOC_H */
  • trunk/kernel/devices/dev_mmc.c

    r1 r3  
    2626#include <soclib_mmc.h>
    2727#include <printk.h>
     28#include <chdev.h>
    2829#include <thread.h>
    2930#include <dev_mmc.h>
     
    3334/////////////////////////////////////////////////////////////////////////////////////////
    3435
    35 extern devices_directory_t  devices_dir;         // allocated in kernel_init.c
    36 
    37 extern devices_input_irq_t  devices_input_irq;   // allocated in kernel_init.c
    38 
    39 //////////////////////////////////
    40 void 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 
     36extern chdev_directory_t  chdev_dir;         // allocated in kernel_init.c
     37
     38extern chdev_icu_input_t  chdev_icu_input;   // allocated in kernel_init.c
     39
     40////////////////////////////////////
     41void dev_mmc_init( chdev_t * chdev )
     42{
    4643    // get implementation from device descriptor
    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
     44    uint32_t  impl = chdev->impl;
     45
     46    // set driver specific fields in device descriptor and call driver init function
    5147    if( impl == IMPL_MMC_TSR )
    5248    {
    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 );
     49        chdev->cmd = &soclib_mmc_cmd;
     50        chdev->isr = &soclib_mmc_isr;
     51        soclib_mmc_init( chdev );
    5852    }
    5953    else
    6054    {
    61         printk("\n[PANIC] in %s: undefined MMC device implementation\n", __FUNCTION__ );
    62         hal_core_sleep();
     55        assert( false , __FUNCTION__ , "undefined MMC device implementation" );
    6356    }
    6457}  // end dev_mmc_init()
     
    7265{
    7366    mmc_dmsg("\n[INFO] %s enters for thread %x in process %x : command = %d\n",
    74                  __FUNCTION__ , this->trdid , this->process->pid , this->dev.mmc.type );
     67                 __FUNCTION__ , this->trdid , this->process->pid , this->command.mmc.type );
    7568
    7669    // get extended pointer on MMC device
    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     }
     70    xptr_t  dev_xp  = this->command.mmc.dev_xp;
     71
     72    assert( (dev_xp != XPTR_NULL) , __FUNCTION__ , "undefined MMC device descriptor" );
    8673
    8774    // get MMC device cluster identifier & local pointer
    88     cxy_t      dev_cxy = GET_CXY( dev_xp );
    89     device_t * dev_ptr = (device_t *)GET_PTR( dev_xp );
     75    cxy_t     dev_cxy = GET_CXY( dev_xp );
     76    chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );
    9077
    9178    // get driver command function pointer from MMC device descriptor
     
    116103    cxy_t cxy = CXY_FROM_PADDR( buf_paddr );
    117104
    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     }
     105    assert( ((buf_paddr & (CONFIG_CACHE_LINE_SIZE -1)) == 0) , __FUNCTION__ ,
     106             "buffer not aligned on cache line" );
    125107
    126108    // get extended pointer on MMC device descriptor
    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; 
     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; 
    140122
    141123
     
    150132    cxy_t cxy = CXY_FROM_PADDR( buf_paddr );
    151133
    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; 
     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; 
    171148
    172149
     
    180157
    181158    // store command arguments in thread descriptor
    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; 
     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; 
    192169}
    193170                       
     
    201178
    202179    // store command arguments in thread descriptor
    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; 
     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; 
    213190}
    214191                       
     
    222199
    223200    // store command arguments in thread descriptor
    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; 
     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; 
    234211}
    235212
  • trunk/kernel/devices/dev_mmc.h

    r1 r3  
    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, do not register in the device waiting queue, and no server thread
     48 * spinlock, but do not register in the device waiting queue, and no server thread
    4949 * is used for this device.
    5050 ****************************************************************************************/
    5151 
     52/****  Forward declarations  ****/
     53
     54struct chdev_s;
     55
    5256/******************************************************************************************
    5357 * This enum defines the various implementations of the generic MMC peripheral.
     
    9296 * It must be executed once in any cluster containing an L2 cache.
    9397 *****************************************************************************************
    94  * @ mmc_xp     : extended pointer on MMC device descriptor.
     98 * @ chdev      : pointer on MMC device descriptor.
    9599 ****************************************************************************************/
    96 void dev_mmc_init( xptr_t  mmc_xp );
     100void dev_mmc_init( struct chdev_s * chdev );
    97101
    98102/*****************************************************************************************
  • trunk/kernel/devices/dev_nic.c

    r1 r3  
    2525#include <hal_special.h>
    2626#include <printk.h>
    27 #include <device.h>
     27#include <chdev.h>
    2828#include <thread.h>
    2929#include <soclib_nic.h>
     
    3434/////////////////////////////////////////////////////////////////////////////////////////
    3535
    36 extern devices_directory_t  devices_dir;         // allocated in kernel_init.c
    37 
    38 extern devices_input_irq_t  devices_input_irq;   // allocated in kernel_init.c
    39 
    40 
    41 //////////////////////////////////
    42 void dev_nic_init( xptr_t dev_xp )
     36extern chdev_directory_t  chdev_dir;         // allocated in kernel_init.c
     37
     38extern chdev_pic_input_t  chdev_pic_input;   // allocated in kernel_init.c
     39
     40////////////////////////////////////
     41void dev_nic_init( chdev_t * chdev )
    4342{
    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
     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
    5554    if( impl == IMPL_NIC_SOC )
    5655    {
    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 //    }
     56        chdev->cmd = &soclib_nic_cmd;
     57        chdev->isr = &soclib_nic_isr;
     58        soclib_nic_init( chdev );
     59    }
    7160    else
    7261    {
    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 );
     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 );
    9675
    9776    // link NIC IRQ to WTI mailbox in PIC component
    9877    uint32_t irq_id;
    99     if( is_rx ) irq_id = devices_input_irq.nic_rx[channel];
    100     else        irq_id = devices_input_irq.nic_tx[channel];
     78    if( is_rx ) irq_id = chdev_pic_input.nic_rx[channel];
     79    else        irq_id = chdev_pic_input.nic_tx[channel];
    10180    dev_pic_bind_irq( irq_id , local_cxy , wti_id );
    10281
    10382    // create server thread
    104     thread_t * new_thread_ptr;
    105     xptr_t     new_thread_xp;
     83    thread_t * new_thread;
    10684    error_t    error;
    10785
    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 );
     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;
    13796   
    13897    // start server thread
    139     thread_unblock( new_thread_xp , THREAD_BLOCKED_GLOBAL );
     98    thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL );
    14099
    141100}  // end dev_nic_init()
     
    156115                 __FUNCTION__ , core->lid , local_cxy );
    157116
    158     // get pointer on NIC-RX device descriptor
     117    // get pointer on NIC-RX chdev descriptor
    159118    uint32_t   channel = thread_ptr->dev_channel;
    160     xptr_t     dev_xp  = devices_dir.nic_rx[channel];
     119    xptr_t     dev_xp  = chdev_dir.nic_rx[channel];
    161120    cxy_t      dev_cxy = GET_CXY( dev_xp );
    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     }
     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" );
    175126
    176127    // initialize command in thread descriptor
    177     thread_ptr->dev.nic.dev_xp = dev_xp;
     128    thread_ptr->command.nic.dev_xp = dev_xp;
    178129
    179130    // call driver to test readable
    180     thread_ptr->dev.nic.cmd = NIC_CMD_READABLE;
    181     dev_ptr->cmd( thread_xp );
    182 
    183     // check error
    184     error = thread_ptr->dev.nic.error;
     131    thread_ptr->command.nic.cmd = NIC_CMD_READABLE;
     132    dev_ptr->cmd( thread_xp );
     133
     134    // check error
     135    error = thread_ptr->command.nic.error;
    185136    if( error ) return error;
    186137
    187138    // block and deschedule if queue non readable
    188     if( thread_ptr->dev.nic.status == false ) 
     139    if( thread_ptr->command.nic.status == false ) 
    189140    {
    190141        // get NIC-RX IRQ index and type
     
    193144
    194145        // enable NIC-RX IRQ
    195         dev_icu_enable_irq( local_cxy , core->lid , irq_type , irq_id , dev_xp );
     146        dev_icu_enable_irq( core->lid , irq_type , irq_id , dev_ptr );
    196147
    197148        // block on THREAD_BLOCKED I/O condition and deschedule
     
    200151
    201152        // disable NIC-RX channel IRQ
    202         dev_icu_disable_irq( local_cxy , core->lid , irq_type , irq_id );
     153        dev_icu_disable_irq( core->lid , irq_type , irq_id );
    203154    }
    204155
    205156    // call driver for actual read
    206     thread_ptr->dev.nic.cmd     = NIC_CMD_READ;
    207     thread_ptr->dev.nic.buffer  = pkd->buffer;
    208     dev_ptr->cmd( thread_xp );
    209 
    210     // check error
    211     error = thread_ptr->dev.nic.error;
     157    thread_ptr->command.nic.cmd     = NIC_CMD_READ;
     158    thread_ptr->command.nic.buffer  = pkd->buffer;
     159    dev_ptr->cmd( thread_xp );
     160
     161    // check error
     162    error = thread_ptr->command.nic.error;
    212163    if( error ) return error;
    213164
    214165    // returns packet length   
    215     pkd->length = thread_ptr->dev.nic.length;
     166    pkd->length = thread_ptr->command.nic.length;
    216167
    217168    nic_dmsg("\n[INFO] %s exit for NIC-RX thread on core %d in cluster %x\n",
     
    238189                 __FUNCTION__ , core->lid , local_cxy );
    239190
    240     // get pointer on NIC-TX device descriptor
     191    // get pointer on NIC-TX chdev descriptor
    241192    uint32_t   channel = thread_ptr->dev_channel;
    242     xptr_t     dev_xp  = devices_dir.nic_tx[channel];
     193    xptr_t     dev_xp  = chdev_dir.nic_tx[channel];
    243194    cxy_t      dev_cxy = GET_CXY( dev_xp );
    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     }
     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" );
    257200
    258201    // initialize command in thread descriptor
    259     thread_ptr->dev.nic.dev_xp = dev_xp;
     202    thread_ptr->command.nic.dev_xp = dev_xp;
    260203
    261204    // call driver to test writable
    262     thread_ptr->dev.nic.cmd    = NIC_CMD_WRITABLE;
    263     dev_ptr->cmd( thread_xp );
    264 
    265     // check error
    266     error = thread_ptr->dev.nic.error;
     205    thread_ptr->command.nic.cmd    = NIC_CMD_WRITABLE;
     206    dev_ptr->cmd( thread_xp );
     207
     208    // check error
     209    error = thread_ptr->command.nic.error;
    267210    if( error ) return error;
    268211
    269212    // block and deschedule if queue non writable
    270     if( thread_ptr->dev.nic.status == false ) 
     213    if( thread_ptr->command.nic.status == false ) 
    271214    {
    272215        // get NIC-TX IRQ index and type
     
    275218
    276219        // enable NIC-TX IRQ
    277         dev_icu_enable_irq( local_cxy , core->lid , irq_type , irq_id , dev_xp );
     220        dev_icu_enable_irq( core->lid , irq_type , irq_id , dev_ptr );
    278221
    279222        // block on THREAD_BLOCKED I/O condition and deschedule
     
    282225
    283226        // disable NIC-TX IRQ
    284         dev_icu_disable_irq( local_cxy , core->lid , irq_type , irq_id );
     227        dev_icu_disable_irq( core->lid , irq_type , irq_id );
    285228    }
    286229
    287230    // call driver for actual write
    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;
    291     dev_ptr->cmd( thread_xp );
    292 
    293     // check error
    294     error = thread_ptr->dev.nic.error;
     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;
     234    dev_ptr->cmd( thread_xp );
     235
     236    // check error
     237    error = thread_ptr->command.nic.error;
    295238    if( error ) return error;
    296239
  • trunk/kernel/devices/dev_nic.h

    r1 r3  
    7575/****  Forward declarations  ****/
    7676
    77 struct device_s;
     77struct chdev_s;
    7878
    7979/******************************************************************************************
     
    137137
    138138/******************************************************************************************
    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  *****************************************************************************************/
    145 void dev_nic_init( xptr_t  dev_xp );
     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 *****************************************************************************************/
     149void dev_nic_init( struct chdev_s * chdev );
    146150
    147151/******************************************************************************************
     
    219223 * becomes non empty.
    220224 ******************************************************************************************
    221  * @ dev     : local pointer on NIC channel device descriptor.
    222  *****************************************************************************************/
    223 void dev_nic_server( struct device_s * dev );
     225 * @ dev     : local pointer on NIC chdev descriptor.
     226 *****************************************************************************************/
     227void dev_nic_server( struct chdev_s * chdev );
    224228
    225229
  • trunk/kernel/devices/dev_pic.c

    r1 r3  
    2525#include <hal_special.h>
    2626#include <dev_icu.h>
    27 #include <device.h>
     27#include <chdev.h>
    2828#include <memcpy.h>
    2929#include <printk.h>
     
    3535/////////////////////////////////////////////////////////////////////////////////////////
    3636
    37 extern devices_directory_t  devices_dir;         // allocated in kernel_init.c
     37extern chdev_directory_t  chdev_dir;         // allocated in kernel_init.c
    3838
    39 extern devices_input_irq_t  devices_input_irq;   // allocated in kernel_init.c
    40 
    41 
     39extern chdev_pic_input_t  chdev_pic_input;   // allocated in kernel_init.c
    4240
    4341///////////////////////////////////
    44 void dev_pic_init( xptr_t   dev_xp,
    45                    uint32_t irq_nr )
     42void dev_pic_init( chdev_t * chdev,
     43                   uint32_t  irq_nr )
    4644{
    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 );
     45    // set PIC chdev extension field
     46    chdev->ext.pic.irq_nr = irq_nr;
    5047
    51     // set PIC device extension field
    52     dev_ptr->ext.pic.irq_nr = irq_nr;
     48    // get implementation
     49    uint32_t impl = chdev->impl;
    5350
    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
     51    // call the relevant driver init function
    5952    if( impl == IMPL_PIC_SOC )
    6053    {
    61         memcpy( dev_ptr->name , "PIC_TSR" , 16 );
    62         soclib_pic_init( dev_xp );
     54        soclib_pic_init( chdev );
    6355    }
    6456    else
    6557    {
    66         printk("PANIC in %s: illegal PIC device implementation\n", __FUNCTION__ );
    67         hal_core_sleep();
     58        assert( false , __FUNCTION__ , "illegal PIC device implementation" );
    6859    }
    6960} // end dev_pic_init()
     
    7566{
    7667    // get extended pointer on WTI mailbox
    77     xptr_t wti_xp = dev_icu_wti_xptr( cxy , wti_id );
     68    xptr_t wti_xp = XPTR( cxy , dev_icu_wti_ptr( wti_id ) );
    7869
    79     // get extended pointer on PIC device from directory
    80     xptr_t dev_xp = devices_dir.pic;
     70    // get extended pointer on PIC chdev from directory
     71    xptr_t dev_xp = chdev_dir.pic;
    8172
    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 );
     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 );
    8576
    8677    // get implementation index and segment base
     
    9283        soclib_pic_bind_irq( dev_xp , irq_id , wti_xp );
    9384    }
    94     else
    95     {
    96         printk("PANIC in %s: illegal PIC device implementation\n", __FUNCTION__ );
    97         hal_core_sleep();
    98     }
    9985}  // end dev_pic_link_wti()
    10086
     
    10288void dev_pic_unbind_irq( uint32_t irq_id )
    10389{
    104     // get extended pointer on PIC device from directory
    105     xptr_t dev_xp = devices_dir.pic;
     90    // get extended pointer on PIC chdev from directory
     91    xptr_t dev_xp = chdev_dir.pic;
    10692
    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 );
     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 );
    11096
    11197    // get implementation index
     
    117103        soclib_pic_unbind_irq( dev_xp , irq_id );
    118104    }
    119     else
    120     {
    121         printk("PANIC in %s: illegal PIC device implementation\n", __FUNCTION__ );
    122         hal_core_sleep();
    123     }
    124    
    125105} // end dev_pic_disable_irq()
    126106
  • trunk/kernel/devices/dev_pic.h

    r1 r3  
    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 ''devices_input_irq'' global variable in kernel initialization.
     41 * and are stored in the ''chdev_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
     52struct chdev_s;
     53
    5054/*****************************************************************************************
    51  * This defines the (implementation independant) extension for the generic ICU device.
     55 * This defines the (implementation independant) extension for the PIC device.
    5256 ****************************************************************************************/
    5357
     
    7276/*****************************************************************************************
    7377 * This function makes two initialisations:
    74  * - It initializes the PIC specific fields of the device descriptor.
     78 * - It initializes the PIC specific fields of the chdev descriptor.
    7579 * - it initializes the implementation specific PIC hardware device.
    7680 * It must be executed once in the kernel initialisation phase.
     
    7983 * @ uint32_t   : actual number of input IRQs.
    8084 ****************************************************************************************/
    81 void dev_pic_init( xptr_t   xp_dev,
    82                    uint32_t irq_nr );
     85void dev_pic_init( struct chdev_s * chdev,
     86                   uint32_t         irq_nr );
    8387
    8488/*****************************************************************************************
  • trunk/kernel/devices/dev_txt.c

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

    r1 r3  
    3030/****  Forward declarations  ****/
    3131
    32 struct device_s ;
     32struct chdev_s ;
    3333
    3434/******************************************************************************************
     
    7979
    8080/******************************************************************************************
    81  * This function completes the TXT device descriptor initialisation,
     81 * This function completes the TXT chdev descriptor initialisation,
    8282 * namely the link with the implementation specific driver.
    83  * The func, impl, channel, is_rxt, base, and size fields must be previously initialised.
     83 * The func, impl, channel, is_rxt, base fields have been 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.
    87  * It can be executed in another cluster than cluster containing the device descriptor
    88  * or the hardware device itself.
     86 * It creates the associated server thread and allocates a WTI from local ICU.
     87 * It must de executed by a local thread.
    8988 ******************************************************************************************
    90  * @ xp_dev     : extended pointer on TXT device descriptor.
     89 * @ chdev     : local pointer on TXT device descriptor.
    9190 *****************************************************************************************/
    92 void dev_txt_init( xptr_t xp_dev );
     91void dev_txt_init( struct chdev_s * chdev );
    9392
    9493/******************************************************************************************
    9594 * This blocking function read a single character from the terminal identified
    9695 * by the "channel" argument. The corresponding request is actually registered in the
    97  * device pending requests queue, and the calling thread is descheduled, blocked until
     96 * chdev requests queue, and the calling thread is descheduled, blocked until
    9897 * transfer completion.
    9998 * It must be called in the client cluster.
     
    109108 * This blocking function writes a character string on the terminal identified
    110109 * by the "channel" argument. The corresponding request is actually registered in the
    111  * device pending requests queue, and the calling thread is descheduled, blocked until
     110 * chdev requests queue, and the calling thread is descheduled, blocked until
    112111 * transfer completion.
    113112 * It must be called in the client cluster.
     
    123122
    124123 /***************************************************************************************
    125  * This low-level blocking function is used by the kernel to display one character on a
     124 * This low-level blocking function is used by the kernel to display one string on a
    126125 * given TXT channel without descheduling the calling thread,  without registering it
    127126 * in the TXT device waiting queue, and without using the TXT irq.
     
    136135                            uint32_t   count );
    137136
    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  *****************************************************************************************/
    153 void dev_txt_server( struct device_s * dev );
    154 
    155137
    156138#endif  /* _DEV_TXT_H_ */
Note: See TracChangeset for help on using the changeset viewer.