Ignore:
File:
1 edited

Legend:

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

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