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

Introduce dev_fbf, dev dma, dev_iob

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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()
Note: See TracChangeset for help on using the changeset viewer.