Changeset 188 for trunk/kernel


Ignore:
Timestamp:
Jul 12, 2017, 8:12:41 PM (5 years ago)
Author:
alain
Message:

Redefine the PIC device API.

Location:
trunk/kernel
Files:
35 edited

Legend:

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

    r23 r188  
    4040extern chdev_directory_t  chdev_dir;         // allocated in kernel_init.c
    4141
    42 extern chdev_icu_input_t  chdev_icu_input;   // allocated in kernel_init.c
    43 
    4442////////////////////////////////////
    4543void dev_dma_init( chdev_t * chdev )
     
    6462    }
    6563
    66     // get DMA HWI IRQ index
    67     uint32_t hwi_id = chdev_icu_input.dma[channel];
     64    // bind IRQ to the core defined by the DMA channel
     65    dev_pic_bind_irq( channel , chdev );
    6866
    69     // enable HWI IRQ in local ICU, and update  interrupt vector
    70     // the selected core is defined by the DMA channel index
    71     dev_icu_enable_irq( channel , HWI_TYPE , hwi_id , chdev );
     67    // enable IRQ
     68    dev_pic_enable_irq( channel, chdev );
    7269
    7370    // create server thread
     
    9087    // start server thread
    9188    thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL );
    92    
     89
    9390} // dev_dma_init()
    9491
  • trunk/kernel/devices/dev_fbf.c

    r65 r188  
    4141extern chdev_directory_t  chdev_dir;         // allocated in kernel_init.c
    4242
    43 extern chdev_pic_input_t  chdev_input_irq;   // allocated in kernel_init.c
    44 
    4543////////////////////////////////////
    46 void dev_fbf_init( chdev_t  * chdev,
    47                    uint32_t   width,
    48                    uint32_t   height )
     44void dev_fbf_init( chdev_t  * chdev )
    4945{
    5046    // set FBF chdev extension fields
    51     // TODO for the "width" and "height", fields, this should be done in the impementation
     47    // TODO this should be done in the impementation
    5248    // TODO specific part, as these parameters must be obtained from the hardware.
    53     chdev->ext.fbf.width  = width;
    54     chdev->ext.fbf.height = height;
     49    chdev->ext.fbf.width  = CONFIG_FBF_WIDTH;
     50    chdev->ext.fbf.height = CONFIG_FBF_HEIGHT;
    5551
    5652    // get implementation
     
    5955    // set chdev name
    6056    strcpy( chdev->name, "fbf" );
     57
    6158    // call driver init function
    6259    if( impl == IMPL_FBF_SCL )
  • trunk/kernel/devices/dev_fbf.h

    r3 r188  
    9090
    9191/******************************************************************************************
    92  * This function completes the FBF chdev descriptor initialisation,
    93  * namely the width and height parameters.
    94  * TODO : these parameters should be provided by the hardware through a dedicated
    95  * software API ...
     92 * This function completes the FBF chdev descriptor initialisation.
    9693 * It calls the specific driver initialisation function, to initialise the hardware
    9794 * device and the specific data structures when required by the implementation.
    9895 * It must be called by a local thread.
     96 *
     97 * TODO In this first approach, the "width" and "height" parameters are defined
     98 * by the CONFIG_FBF_WIDTH & CONFIG_FBF_HEIGHT in the kernel_config.h file.
     99 * These parameters should be provided by the driver, accessing dedicated
     100 * adressable registers in the FBF controler.
    99101 ******************************************************************************************
    100102 * @ chdev      : pointer on FBF chdev descriptor.
    101  * @ width      : number of pixels (bytes) per line.
    102  * @ height     : total number of lines.
    103103 *****************************************************************************************/
    104 void dev_fbf_init( struct chdev_s * chdev,
    105                    uint32_t         width,
    106                    uint32_t         height );
     104void dev_fbf_init( struct chdev_s * chdev );
    107105
    108106/******************************************************************************************
  • trunk/kernel/devices/dev_ioc.c

    r101 r188  
    3939/////////////////////////////////////////////////////////////////////////////////////////
    4040
    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" );
     41extern chdev_directory_t  chdev_dir;     // allocated in kernel_init.c
     42
     43//////////////////////////////////
     44void dev_ioc_init( chdev_t * ioc )
     45{
     46    // the PIC chdev must be initialized before the IOC chdev, because
     47    // the IOC chdev initialisation requires the routing of an external IRQ
     48    xptr_t  pic_xp  = chdev_dir.pic;
     49
     50    assert( (pic_xp != XPTR_NULL) , __FUNCTION__ , "PIC not initialised before IOC" );
    5251
    5352    // get implementation and channel from chdev descriptor
    54     uint32_t  impl    = chdev->impl;
    55     uint32_t  channel = chdev->channel;
     53    uint32_t  impl    = ioc->impl;
     54    uint32_t  channel = ioc->channel;
    5655
    5756    // set chdev name
    58     strcpy( chdev->name , "ioc" );
     57    snprintf( ioc->name , 16 , "ioc_%d" , channel );
    5958
    6059    // set driver specific fields in chdev descriptor and call driver init function
    6160    if( impl == IMPL_IOC_BDV )
    6261    {
    63         chdev->cmd = &soclib_bdv_cmd;
    64         chdev->isr = &soclib_bdv_isr;
    65         soclib_bdv_init( chdev );
     62        ioc->cmd = &soclib_bdv_cmd;
     63        ioc->isr = &soclib_bdv_isr;
     64        soclib_bdv_init( ioc );
    6665    }
    6766    else if( impl == IMPL_IOC_HBA )
    6867    {
    69         chdev->cmd = &soclib_hba_cmd;
    70         chdev->isr = &soclib_hba_isr;
    71         soclib_hba_init( chdev );
     68        ioc->cmd = &soclib_hba_cmd;
     69        ioc->isr = &soclib_hba_isr;
     70        soclib_hba_init( ioc );
    7271    }
    7372    else
     
    7675    }
    7776
    78     // get a WTI mailbox from local ICU
    79     uint32_t wti_id = dev_icu_wti_alloc();
    80 
    81     assert( (wti_id != -1) , __FUNCTION__ , "cannot allocate WTI mailbox" );
    82 
    83     // select a core
     77    // select a core to execute the IOC server thread
    8478    lid_t lid = cluster_select_local_core();
    8579
    86     // enable WTI IRQ and update WTI interrupt vector
    87     dev_icu_enable_irq( lid , WTI_TYPE , wti_id , chdev );
    88 
    89     // link IOC IRQ to WTI mailbox in PIC component
    90     uint32_t irq_id = chdev_pic_input.ioc[channel];
    91     dev_pic_bind_irq( irq_id , local_cxy , wti_id );
     80    // bind the IOC IRQ to the selected core
     81    dev_pic_bind_irq( lid , ioc );
     82
     83    // enable IRQ
     84    dev_pic_enable_irq( lid ,ioc );
    9285
    9386    // create server thread
     
    9891                                  THREAD_DEV,
    9992                                  &chdev_sequencial_server,
    100                                   chdev,
     93                                  ioc,
    10194                                  lid );
     95
    10296    assert( (error == 0) , __FUNCTION__ , "cannot create server thread" );
    10397
    104     // set "server" field in chdev descriptor
    105     chdev->server = new_thread;
     98    // set "server" field in ioc descriptor
     99    ioc->server = new_thread;
    106100   
    107101    // start server thread
  • trunk/kernel/devices/dev_ioc.h

    r23 r188  
    108108typedef struct ioc_command_s
    109109{
    110     xptr_t      dev_xp;     /*! extended pointer on device descriptor                    */
     110    xptr_t      dev_xp;     /*! extended pointer on IOC device descriptor                */
    111111    uint32_t    type;       /*! IOC_READ / IOC_WRITE / IOC_SYNC_READ                     */
    112112    uint32_t    lba;        /*! first block index                                        */
  • trunk/kernel/devices/dev_mmc.c

    r23 r188  
    3535
    3636extern chdev_directory_t  chdev_dir;         // allocated in kernel_init.c
    37 
    38 extern chdev_icu_input_t  chdev_icu_input;   // allocated in kernel_init.c
    3937
    4038////////////////////////////////////
     
    5957    }
    6058
    61     // get MMC HWI IRQ index
    62     uint32_t hwi_id = chdev_icu_input.mmc;
    63 
    64     // enable HWI IRQ to CP0 in local ICU, and update  interrupt vector
    65     dev_icu_enable_irq( 0 , HWI_TYPE , hwi_id , chdev );
     59    // bind IRQ to CP0
     60    dev_pic_bind_irq( 0 , chdev );
    6661   
     62    // enable IRQ
     63    dev_pic_enable_irq( 0 , chdev );
     64
    6765}  // end dev_mmc_init()
    6866
  • trunk/kernel/devices/dev_nic.c

    r23 r188  
    22 * dev_nic.c - NIC (Network Controler) generic device API implementation.
    33 *
    4  * Author  Alain Greiner    (2016)
     4 * Author  Alain Greiner    (2016,2017)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    3636extern chdev_directory_t  chdev_dir;         // allocated in kernel_init.c
    3737
    38 extern chdev_pic_input_t  chdev_pic_input;   // allocated in kernel_init.c
    39 
    40 ////////////////////////////////////
    41 void dev_nic_init( chdev_t * chdev )
     38//////////////////////////////////
     39void dev_nic_init( chdev_t * nic )
    4240{
    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" );
     41    // the PIC chdev must be initialized before the NIC chdev, because
     42    // the NIC chdev initialisation requires the routing of an external IRQ.
     43    xptr_t  pic_xp  = chdev_dir.pic;
     44
     45    assert( (pic_xp != XPTR_NULL) , __FUNCTION__ , "ICU not initialised before NIC" );
    4746
    4847    // 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;
     48    uint32_t  impl    = nic->impl;
     49    uint32_t  channel = nic->channel;
     50    bool_t    is_rx   = nic->is_rx;
    5251
    5352    // set chdev name
    54     snprintf( chdev->name , 16 , "nic_%d" , chdev->channel );
     53    if( is_rx ) snprintf( nic->name , 16 , "nic_rx_%d" , channel );
     54    else        snprintf( nic->name , 16 , "nic_tx_%d" , channel );
    5555
    5656    // set driver specific fields in chdev descriptor and call driver init function
    5757    if( impl == IMPL_NIC_SOC )
    5858    {
    59         chdev->cmd = &soclib_nic_cmd;
    60         chdev->isr = &soclib_nic_isr;
    61         soclib_nic_init( chdev );
     59        nic->cmd = &soclib_nic_cmd;
     60        nic->isr = &soclib_nic_isr;
     61        soclib_nic_init( nic );
    6262    }
    6363    else
     
    6666    }
    6767
    68     // get a WTI mailbox from local ICU
    69     uint32_t wti_id = dev_icu_wti_alloc();
    70 
    71     assert( (wti_id != -1) , __FUNCTION__ , "cannot allocate WTI mailbox" );
    72 
    73     // select a core
     68    // select a core to execute the NIC server thread
    7469    lid_t lid = cluster_select_local_core();
    7570
    76     // enable WTI IRQ and update WTI interrupt vector
    77     dev_icu_enable_irq( lid , WTI_TYPE , wti_id , chdev );
    78 
    79     // link NIC IRQ to WTI mailbox in PIC component
    80     uint32_t irq_id;
    81     if( is_rx ) irq_id = chdev_pic_input.nic_rx[channel];
    82     else        irq_id = chdev_pic_input.nic_tx[channel];
    83     dev_pic_bind_irq( irq_id , local_cxy , wti_id );
     71    // bind the NIC IRQ to the selected core
     72    // but does NOT enable it
     73    dev_pic_bind_irq( lid , nic );
    8474
    8575    // create server thread
     
    9080                                  THREAD_DEV,
    9181                                  &chdev_sequencial_server,
    92                                   chdev,
     82                                  nic,
    9383                                  lid );
    9484
     
    9686
    9787    // set "server" field in chdev descriptor
    98     chdev->server = new_thread;
     88    nic->server = new_thread;
    9989   
    10090    // start server thread
     
    142132    if( thread_ptr->command.nic.status == false ) 
    143133    {
    144         // get NIC-RX IRQ index and type
    145         uint32_t   irq_type = dev_ptr->irq_type;
    146         uint32_t   irq_id   = dev_ptr->irq_id;
    147 
    148134        // enable NIC-RX IRQ
    149         dev_icu_enable_irq( core->lid , irq_type , irq_id , dev_ptr );
    150 
    151         // block on THREAD_BLOCKED I/O condition and deschedule
     135        dev_pic_enable_irq( core->lid , dev_ptr );
     136
     137        // block on THREAD_BLOCKED_IO condition and deschedule
    152138        thread_block( thread_ptr , THREAD_BLOCKED_IO );
    153139        sched_yield();
    154140
    155         // disable NIC-RX channel IRQ
    156         dev_icu_disable_irq( core->lid , irq_type , irq_id );
     141        // disable NIC-RX IRQ
     142        dev_pic_disable_irq( core->lid , dev_ptr );
    157143    }
    158144
     
    206192
    207193    // call driver to test writable
    208     thread_ptr->command.nic.cmd    = NIC_CMD_WRITABLE;
     194    thread_ptr->command.nic.cmd = NIC_CMD_WRITABLE;
    209195    dev_ptr->cmd( thread_xp );
    210196
     
    216202    if( thread_ptr->command.nic.status == false ) 
    217203    {
    218         // get NIC-TX IRQ index and type
    219         uint32_t   irq_type = dev_ptr->irq_type;
    220         uint32_t   irq_id   = dev_ptr->irq_id;
    221 
    222204        // enable NIC-TX IRQ
    223         dev_icu_enable_irq( core->lid , irq_type , irq_id , dev_ptr );
     205        dev_pic_enable_irq( core->lid ,dev_ptr );
    224206
    225207        // block on THREAD_BLOCKED I/O condition and deschedule
     
    228210
    229211        // disable NIC-TX IRQ
    230         dev_icu_disable_irq( core->lid , irq_type , irq_id );
     212        dev_pic_disable_irq( core->lid , dev_ptr );
    231213    }
    232214
  • trunk/kernel/devices/dev_pic.c

    r23 r188  
    2424#include <hal_types.h>
    2525#include <hal_special.h>
    26 #include <dev_icu.h>
    2726#include <chdev.h>
    28 #include <memcpy.h>
    2927#include <printk.h>
    3028#include <soclib_pic.h>
    3129#include <dev_pic.h>
     30#include <cluster.h>
    3231
    3332/////////////////////////////////////////////////////////////////////////////////////////
     
    3736extern chdev_directory_t  chdev_dir;         // allocated in kernel_init.c
    3837
    39 extern chdev_pic_input_t  chdev_pic_input;   // allocated in kernel_init.c
    40 
    4138///////////////////////////////////
    42 void dev_pic_init( chdev_t * chdev,
    43                    uint32_t  irq_nr )
     39void dev_pic_init( chdev_t  * pic )
    4440{
    45     // set PIC chdev extension field
    46     chdev->ext.pic.irq_nr = irq_nr;
    47 
    4841    // get implementation
    49     uint32_t impl = chdev->impl;
     42    uint32_t impl = pic->impl;
    5043
    5144    // set chdev name
    52     strcpy( chdev->name , "pic" );
    53  
    54     // call the relevant driver init function
    55     if( impl == IMPL_PIC_SOC )
     45    strcpy( pic->name , "pic" );
     46
     47    // call the relevant driver init function,
     48    // and register commands in PIC device extension
     49    if( impl == IMPL_PIC_SCL )
    5650    {
    57         soclib_pic_init( chdev );
     51        // call the PIC SOCLIB driver
     52        soclib_pic_init( pic );
     53
     54        // update the PIC chdev extension
     55        pic->ext.pic.enable_timer = &soclib_pic_enable_timer;
     56        pic->ext.pic.enable_irq   = &soclib_pic_enable_irq;
     57        pic->ext.pic.disable_irq  = &soclib_pic_disable_irq;
     58        pic->ext.pic.bind_irq     = &soclib_pic_bind_irq;
     59        pic->ext.pic.send_ipi     = &soclib_pic_send_ipi;
     60        pic->ext.pic.extend_init  = &soclib_pic_extend_init;
     61    }
     62    else if( impl == IMPL_PIC_I86 )
     63    {
     64        assert( false , __FUNCTION__ , "missing implementation for X86\n" );
    5865    }
    5966    else
    6067    {
    61         assert( false , __FUNCTION__ , "illegal PIC device implementation" );
     68        assert( false , __FUNCTION__ , "undefined PIC device implementation" );
    6269    }
    6370} // end dev_pic_init()
    6471
    65 /////////////////////////////////////////
    66 void dev_pic_bind_irq( uint32_t   irq_id,
    67                        cxy_t      cxy,
    68                        uint32_t   wti_id )
     72/////////////////////////////////////////////////
     73void dev_pic_extend_init( uint32_t * lapic_base )
    6974{
    70     // get extended pointer on WTI mailbox
    71     xptr_t wti_xp = XPTR( cxy , dev_icu_wti_ptr( wti_id ) );
     75    // get pointer on PIC chdev
     76    chdev_t * pic = (chdev_t *)GET_PTR( chdev_dir.pic );
    7277
    73     // get extended pointer on PIC chdev from directory
    74     xptr_t dev_xp = chdev_dir.pic;
     78    // call relevant driver function
     79    pic->ext.pic.extend_init( lapic_base );
     80}
    7581
    76     // get PIC chdev cluster and local pointer
    77     cxy_t     dev_cxy = GET_CXY( dev_xp );
    78     chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );
     82/////////////////////////////////////
     83void dev_pic_bind_irq( lid_t     lid,
     84                       chdev_t * src_chdev )
     85{
     86    // get pointer on PIC chdev
     87    chdev_t * pic = (chdev_t *)GET_PTR( chdev_dir.pic );
    7988
    80     // get implementation index and segment base
    81     uint32_t impl   = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) );
     89    // call relevant driver function
     90    pic->ext.pic.bind_irq( lid , src_chdev );
     91
    8292
    83     // call the implementation specific driver function
    84     if( impl == IMPL_PIC_SOC )
    85     {
    86         soclib_pic_bind_irq( dev_xp , irq_id , wti_xp );
    87     }
    88 }  // end dev_pic_link_wti()
     93///////////////////////////////////////
     94void dev_pic_enable_irq( lid_t     lid,
     95                         chdev_t * src_chdev )
     96{
     97    // get pointer on PIC chdev
     98    chdev_t * pic = (chdev_t *)GET_PTR( chdev_dir.pic );
    8999
    90 //////////////////////////////////////////
    91 void dev_pic_unbind_irq( uint32_t irq_id )
     100    // call relevant driver function
     101    pic->ext.pic.enable_irq( src_chdev );
     102}
     103
     104////////////////////////////////////////
     105void dev_pic_disable_irq( lid_t     lid,
     106                          chdev_t * src_chdev )
    92107{
    93     // get extended pointer on PIC chdev from directory
    94     xptr_t dev_xp = chdev_dir.pic;
     108    // get pointer on PIC chdev
     109    chdev_t * pic = (chdev_t *)GET_PTR( chdev_dir.pic );
    95110
    96     // get PIC chdev cluster and local pointer
    97     cxy_t     dev_cxy = GET_CXY( dev_xp );
    98     chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );
     111    // call relevant driver function
     112    pic->ext.pic.disable_irq( src_chdev );
     113}
    99114
    100     // get implementation index
    101     uint32_t impl = hal_remote_lw( XPTR( dev_cxy , &dev_ptr->impl ) );
     115////////////////////////////////////////////
     116void dev_pic_enable_timer( uint32_t period )
     117{
     118    // get pointer on PIC chdev
     119    chdev_t * pic = (chdev_t *)GET_PTR( chdev_dir.pic );
    102120
    103     // call the implementation specific driver function
    104     if( impl == IMPL_PIC_SOC )
    105     {
    106         soclib_pic_unbind_irq( dev_xp , irq_id );
    107     }
    108 } // end dev_pic_disable_irq()
     121    // call relevant driver function
     122    pic->ext.pic.enable_timer( period );
     123}
     124
     125//////////////////////////////////
     126void dev_pic_send_ipi( cxy_t  cxy,
     127                       lid_t  lid )
     128{
     129    // get pointer on PIC chdev
     130    chdev_t * pic = (chdev_t *)GET_PTR( chdev_dir.pic );
     131
     132    // call relevant driver function
     133    pic->ext.pic.send_ipi( cxy , lid );
     134}
    109135
    110136
  • trunk/kernel/devices/dev_pic.h

    r14 r188  
    11/*
    2  * dev_pic.h - PIC (External Interrupt Controler) generic device API definition.
     2 * dev_pic.h - PIC (Programmable Interrupt Controler) generic device API definition.
    33 *
    44 * Authors   Alain Greiner  (2016)
     
    2929
    3030/*****************************************************************************************
    31  *     Generic External Interrupt Controler definition
    32  *
    33  * The PIC generic device describes an external interrupt Controler, that translates
    34  * N input IRQs generated by external peripherals to N WTI IRQs, that will be routed
    35  * to a dynamically allocated WTI mailbox in a given cluster.
    36  *
    37  * The max number of input IRQs is defined by the CONFIG_MAX_IRQS_PER_PIC parameter.
    38  * The actual number of connected IRQs is defined in the ''arch_info'' file, and stored
    39  * in the PIC device extension. 
    40  * The "source" device for each input IRQ is also defined in the ''arch_info'' file,
    41  * and are stored in the ''chdev_input_irq'' global variable in kernel initialization.
    42  *
    43  * This external peripheral does not execute I/O operations, but is just acting as a
    44  * dynamically configurable interrupt router for another I/O operation. Therefore,
    45  * ALMOS-MKH does not use the PIC device waiting queue, but call directly the relevant
    46  * driver blocking functions to dynamically "bind" or "unbind" an external IRQ to a
    47  * WTI mailbox.
     31 *     Generic Programmable Interrupt Controler definition
     32 *
     33 * The PIC generic device describes the the programmable hardware infrastructure used
     34 * to route a given IRQ to a given core, in a given cluster, and to help the interrupt
     35 * handler to select  and execute the relevant ISR (Interrupt Service Routine).
     36 * It handles the following type of interrupts:
     37 * - External IRQs generated by the external (shared) peripherals.
     38 * - Internal IRQs generated by the internal (replicated) peripherals.
     39 * - Timer IRQs generated by the timers (one timer per core).
     40 * - Inter Processor IRQs (IPI) generated by software.
     41 *
     42 * In most supported manycores architectures, the PIC device contains two types
     43 * of hardware components:
     44 * - the IOPIC is an external component, handling all external peripherals IRQs.
     45 * - The LAPIC is an internal component, replicated in each cluster, handling local
     46 *   peripherals IRQS, Timer IRQs and IPIs (inter-processor-interupts).
     47 *
     48 * The "source" device for each input IRQ to the external IOPIC component, is defined
     49 * in the "arch_info" file, and registered in the "iopic_input" global variable
     50 * at kernel initialization.
     51 *
     52 * The "source" device for each input IRQ to the replicated LAPIC components, is defined
     53 * in the "arch_info" file, and stored in the "lapic_input" global variable
     54 * at kernel initialization.
     55 *
     56 * The PIC device defines 4 generic commands that can be used by each kernel instance,
     57 * - to create in local cluster the PIC implementation specific interupt vector(s),
     58 * - to bind a given IRQ (internal or external IRQ to a given core in the local cluster,
     59 * - to configure and activate the TICK timer for a given core in the local cluster,
     60 * - to allows the software to send an IPI to any core in any cluster.
     61 * This API is detailed below, and must be implemented by all PIC implementations.
     62 *
     63 * In each cluster, a PIC implementation specific structure can be linked to the
     64 * cluster manager or to the core descriptors to register the interrupt vectors
     65 * used by the kernel to select the relevant ISR when an interrupt is received
     66 * by a given core in agiven cluster.
     67 
     68 * This PIC device does not execute itself I/O operations. It is just acting as a
     69 * configurable interrupt router for I/O operation executed by other peripherals.
     70 * Therefore, ALMOS-MKH does not use the PIC device waiting queue, does not creates
     71 * a server thread for the PIC device, and does not register the command in the calling
     72 * thread descriptor, but call directly the relevant driver function.
    4873 ****************************************************************************************/
    4974 
     
    5378
    5479/*****************************************************************************************
    55  * This defines the (implementation independant) extension for the PIC device.
    56  ****************************************************************************************/
    57 
     80 * This defines the specific extension for the PIC chdev descriptor.
     81 * It contains four function pointers on the four PIC command types,
     82 * that must be implemented by all drivers.
     83 ****************************************************************************************/
     84
     85typedef void   (pic_bind_t)    ( lid_t lid , struct chdev_s * src_chdev );   
     86typedef void   (pic_enable_t)  ( struct chdev_s * src_chdev );   
     87typedef void   (pic_disable_t) ( struct chdev_s * src_chdev );   
     88typedef void   (pic_timer_t)   ( uint32_t period );   
     89typedef void   (pic_ipi_t)     ( cxy_t cxy , lid_t lid );
     90typedef void   (pic_init_t)    ( uint32_t * lapic_base );
     91 
    5892typedef struct pic_extend_s
    5993{
    60     uint32_t    irq_nr;     /*! actual number of input IRQs to the PIC device           */
     94    pic_bind_t    * bind_irq;      /*! pointer on the driver "bind_irq" function        */
     95    pic_enable_t  * enable_irq;    /*! pointer on the driver "enable_irq" function      */
     96    pic_disable_t * disable_irq;   /*! pointer on the driver "disable_irq" function     */
     97    pic_timer_t   * enable_timer;  /*! pointer on the driver "enable_timer" function    */
     98    pic_ipi_t     * send_ipi;      /*! pointer on the driver "send_ipi" function        */
     99    pic_init_t    * extend_init;   /*! pointer on the driver "init_extend" function     */
    61100}
    62101pic_extend_t;
    63102
    64 /*****************************************************************************************
    65  * This enum defines the various implementations of the PIC external interrupt controller.
     103/******************************************************************************************
     104 * This structure defines the input IRQS for the external IOPIC controller, that is used
     105 * by external peripherals (IOC, NIC, TXT, etc.) to signal completion of an I/O operation.
     106 * It describes the hardware wiring of IRQs between external peripherals and the IOPIC,
     107 * as each entry contains the input IRQ index in IOPIC.
     108 * For a multi-channels peripheral, there is one chdev and one IRQ per channel.
     109 * This structure is replicated in each cluster. It is allocated as a global variable
     110 * in the kernel_init.c file.
     111 *****************************************************************************************/
     112
     113typedef struct iopic_input_s
     114{
     115    uint32_t   txt[CONFIG_MAX_TXT_CHANNELS];
     116    uint32_t   ioc[CONFIG_MAX_IOC_CHANNELS];
     117    uint32_t   nic_rx[CONFIG_MAX_NIC_CHANNELS];
     118    uint32_t   nic_tx[CONFIG_MAX_NIC_CHANNELS];
     119    uint32_t   iob;
     120}
     121iopic_input_t;
     122
     123/******************************************************************************************
     124 * This structure defines the input IRQS for the internal LAPIC controllers, that are used
     125 * by internal peripherals IRQS (DMA, MMC) to signal completion of an I/O operation.
     126 * It describes the hardware wiring of IRQs between internal peripherals and ICU,
     127 * as each entry contains the input IRQ index in the LAPIC component.
     128 * For a multi-channels peripheral, there is one chdev and one IRQ per channel.
     129 * This structure is replicated in each cluster. It is allocated as a global variable
     130 * in the kernel_init.c file.
     131 *****************************************************************************************/
     132
     133typedef struct lapic_input_s
     134{
     135    uint32_t   dma[CONFIG_MAX_DMA_CHANNELS];
     136    uint32_t   mmc;                             // MMC is single channel
     137}
     138lapic_input_t;
     139
     140/*****************************************************************************************
     141 * This enum defines the various implementations of the PIC device.
    66142 * This array must be kept consistent with the define in arch_info.h file
    67143 ****************************************************************************************/
     
    69145enum pic_impl_e
    70146{
    71     IMPL_PIC_SOC =   0,     
     147    IMPL_PIC_SCL =   0,     
    72148    IMPL_PIC_I86 =   1,
    73149}
     
    75151
    76152/*****************************************************************************************
    77  * This function makes two initialisations:
     153 * This function makes two initialisations :
    78154 * - It initializes the PIC specific fields of the chdev descriptor.
    79  * - it initializes the implementation specific PIC hardware device.
    80  * It must be executed once in the kernel initialisation phase.
    81  *****************************************************************************************
    82  * @ xp_dev     : extended pointer on PIC device descriptor.
    83  * @ uint32_t   : actual number of input IRQs.
    84  ****************************************************************************************/
    85 void dev_pic_init( struct chdev_s * chdev,
    86                    uint32_t         irq_nr );
    87 
    88 /*****************************************************************************************
    89  * This function link a WTI mailbox to the PIC input IRQ identified by its index,
    90  * and unmask the selected input IRQ, calling the relevant driver.
    91  *****************************************************************************************
    92  * @ irq_id    : input IRQ index.
    93  * @ cxy       : WTI mailbox cluster.
    94  * @ wti_id    : WTI mailbox index in cluster.
    95  ****************************************************************************************/
    96 void dev_pic_bind_irq( uint32_t   irq_id,
    97                        cxy_t      cxy,
    98                        uint32_t   wti_id );
    99 
    100 /*****************************************************************************************
    101  * This function mask a PIC input IRQ identified by its index, calling te relevant driver.
    102  *****************************************************************************************
    103  * @ irq_id    : input IRQ index.
    104  ****************************************************************************************/
    105 void dev_pic_unbind_irq( uint32_t   irq_id );
    106                        
     155 * - it initializes the implementation specific PIC hardware registers.
     156 * It is executed once in cluster containing the PIC chdev, during kernel initialisation.
     157 * The calling core goes to sleep in case of failure.
     158 *****************************************************************************************
     159 * @ pic        : local pointer on PIC device descriptor.
     160 ****************************************************************************************/
     161void dev_pic_init( struct chdev_s * pic );
     162
     163/*****************************************************************************************
     164 * This function completes the PIC infrastructure initialisation in each cluster.
     165 * It allocates memory for the local PIC extensions in the core descriptors and/or
     166 * in the cluster manager, as required by the specific PIC implementation.
     167 * This function is called by CPO in all clusters, during kernel initialisation phase.
     168 * The calling core goes to sleep in case of failure.
     169 *****************************************************************************************
     170 * @ lapic_base  : local pointer on LAPIC component segment base.
     171 ****************************************************************************************/
     172void dev_pic_extend_init( uint32_t * lapic_base );
     173
     174/*****************************************************************************************
     175 * This function configure the PIC device to route the IRQ generated by a local chdev,
     176 * defined by the <src_chdev> argument, to a local core identified by the <lid> argument.
     177 * This is a static binding, defined during kernel init: IRQ can be enabled/disabled,
     178 * but the binding cannot be released. It can be used for both internal & external IRQs.
     179 * WARNING : the IRQ must be explicitely enabled by the dev_pic_enable_irq() function.
     180 *****************************************************************************************
     181 * @ lid        : target core local index.
     182 * @ src_chdev  : local pointer on source chdev descriptor.
     183 ****************************************************************************************/
     184void dev_pic_bind_irq( lid_t            lid,
     185                       struct chdev_s * src_chdev );
     186
     187/*****************************************************************************************
     188 * This function disables the IRQ generated by a local chdev, defined by the <src_chdev>
     189 * argument. It can be used for both internal & external IRQs.
     190 *****************************************************************************************
     191 * @ lid        : target core local index.
     192 * @ src_chdev  : local pointer on source chdev descriptor.
     193 ****************************************************************************************/
     194void dev_pic_disable_irq( lid_t            lid,
     195                          struct chdev_s * src_chdev );
     196
     197/*****************************************************************************************
     198 * This function enables the IRQ generated by a local chdev, defined by the <src_chdev>
     199 * argument. It can be used for both internal & external IRQs.
     200 *****************************************************************************************
     201 * @ lid        : target core local index.
     202 * @ src_chdev  : local pointer on source chdev descriptor.
     203 ****************************************************************************************/
     204void dev_pic_enable_irq( lid_t            lid,
     205                         struct chdev_s * src_chdev );
     206
     207/*****************************************************************************************
     208 * This function activates the TICK timer for the calling core.
     209 * The <period> argument define the number of cycles between IRQs.
     210 *****************************************************************************************
     211 * @ period      : number of cycles between IRQs.
     212 ****************************************************************************************/
     213void dev_pic_enable_timer( uint32_t period );
     214
     215/*****************************************************************************************
     216 * This function allows the calling thread to send an IPI to any core in any cluster.
     217 * The target core is identified by the <cxy> & <lid> arguments.
     218 *****************************************************************************************
     219 * @ cxy        : target core cluster.
     220 * @ lid        : target core local index.
     221 ****************************************************************************************/
     222void dev_pic_send_ipi( cxy_t  cxy,
     223                       lid_t  lid );
     224
    107225
    108226#endif  /* _DEV_PIC_H_ */
  • trunk/kernel/devices/dev_txt.c

    r101 r188  
    3838extern chdev_directory_t  chdev_dir;         // allocated in kernel_init.c
    3939
    40 extern chdev_pic_input_t  chdev_pic_input;   // allocated in kernel_init.c
     40//////////////////////////////////
     41void dev_txt_init( chdev_t * txt )
     42{
     43    // For all TXT channels other than the TXT0 (kernel terminal),
     44    // the PIC chdev must be initialized before the TXT chdev, because
     45    // the TXT chdev initialization requires the routing of an external IRQ
    4146
    42 ////////////////////////////////////
    43 void dev_txt_init( chdev_t * chdev )
    44 {
    45     // the local ICU chdev must be initialized before the TXT chdev, because
    46     // the TXT chdev initialization requires allocation of a WTI from local ICU
    47     xptr_t  icu_xp  = chdev_dir.icu[local_cxy];
    48     assert( (icu_xp != XPTR_NULL) , __FUNCTION__ , "ICU not initialised before TXT" );
     47    xptr_t    pic_xp  = chdev_dir.pic;
     48    uint32_t  channel = txt->channel;
     49    uint32_t  impl    = txt->impl;
    4950
    50     // get implementation and channel index
    51     uint32_t  impl    = chdev->impl;
    52     uint32_t  channel = chdev->channel;
     51    assert( (pic_xp != XPTR_NULL) || (channel == 0) , __FUNCTION__ ,
     52            "PIC not initialised before TXT" );
    5353
    5454    // set chdev name
    55     snprintf( chdev->name , 16 , "txt_%d" , chdev->channel );
     55    snprintf( txt->name , 16 , "txt_%d" , channel );
    5656
    5757    // set fields "cmd", "isr", and call driver init function
    5858    if( impl == IMPL_TXT_TTY )
    5959    {
    60         chdev->cmd = &soclib_tty_cmd;
    61         chdev->isr = &soclib_tty_isr;
    62         soclib_tty_init( chdev );
     60        txt->cmd = &soclib_tty_cmd;
     61        txt->isr = &soclib_tty_isr;
     62        soclib_tty_init( txt );
    6363    }
    6464    else
     
    6767    }
    6868
    69     // get a WTI mailbox from local ICU
    70     uint32_t wti_id = dev_icu_wti_alloc();
     69    // no server thread and no IRQ routing for TXT0
     70    if( channel != 0 )
     71    {
     72        // select a core to execute the TXT server thread
     73        lid_t lid = cluster_select_local_core();
    7174
    72     assert( (wti_id != -1) , __FUNCTION__ , "cannot allocate WTI mailbox" );
     75        // bind TXT IRQ to the selected core
     76        dev_pic_bind_irq( lid , txt );
    7377
    74     // select a core
    75     lid_t lid = cluster_select_local_core();
     78        // enable TXT IRQ
     79        dev_pic_enable_irq( lid , txt );
    7680
    77     // enable WTI IRQ and update WTI interrupt vector
    78     dev_icu_enable_irq( lid , WTI_TYPE , wti_id , chdev );
     81        // create server thread
     82        thread_t * new_thread;
     83        error_t    error;
    7984
    80     // link IOC IRQ to WTI mailbox in PIC component
    81     uint32_t irq_id = chdev_pic_input.txt[channel];
    82     dev_pic_bind_irq( irq_id , local_cxy , wti_id );
     85        error = thread_kernel_create( &new_thread,
     86                                      THREAD_DEV,
     87                                      &chdev_sequencial_server,
     88                                      txt,
     89                                      lid );
    8390
    84     // create server thread
    85     thread_t * new_thread;
    86     error_t    error;
     91        assert( (error == 0) , __FUNCTION__ , "cannot create server thread" );
    8792
    88     error = thread_kernel_create( &new_thread,
    89                                   THREAD_DEV,
    90                                   &chdev_sequencial_server,
    91                                   chdev,
    92                                   lid );
    93     assert( (error == 0) , __FUNCTION__ , "cannot create server thread" );
     93        // set "server" field in chdev descriptor
     94        txt->server = new_thread;
    9495
    95     // set "server" field in chdev descriptor
    96     chdev->server = new_thread;
    97 
    98     // start server thread
    99     thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL );
     96        // start server thread
     97        thread_unblock( XPTR( local_cxy , new_thread ) , THREAD_BLOCKED_GLOBAL );
     98    }
    10099}
    101100
  • trunk/kernel/kern/chdev.h

    r23 r188  
    120120    uint32_t             channel;     /*! channel index                                  */
    121121    bool_t               is_rx;       /*! relevant for NIC peripheral channels only      */
    122         xptr_t               base;        /*! extended pointer on channel segment paddr      */
     122        xptr_t               base;        /*! extended pointer on channel device segment     */
    123123    char                 name[16];    /*! name (required by DEVFS)                       */
    124124
     
    177177
    178178/******************************************************************************************
    179  * This structure defines the input IRQS for the PIC device, that is used by all external
    180  * peripherals (IOC, NIC, TXT, etc.) to signal completion of an I/O operation. It describes
    181  * the hardware wiring of IRQs between external peripherals and PIC, as each entry in this
    182  * structure contains the input IRQ index in PIC. Value is -1 for an unused input.
    183  * For a multi-channels peripheral, there is one chdev and one IRQ per channel.
    184  * This structure is replicated in each cluster. It is allocated as a global variable
    185  * in the kernel_init.c file, and is initialised during kernel init.
    186  *****************************************************************************************/
    187 
    188 typedef struct chdev_pic_input_s
    189 {
    190     uint32_t   txt[CONFIG_MAX_TXT_CHANNELS];
    191     uint32_t   ioc[CONFIG_MAX_IOC_CHANNELS];
    192     uint32_t   nic_rx[CONFIG_MAX_NIC_CHANNELS];
    193     uint32_t   nic_tx[CONFIG_MAX_NIC_CHANNELS];
    194 }
    195 chdev_pic_input_t;
    196 
    197 /******************************************************************************************
    198  * This structure defines the input IRQS for the ICU device, that is used by all internal
    199  * peripherals IRQS (DMA, MMC, etc.) to signal completion of an I/O operation. It describes
    200  * the hardware wiring of IRQs between internal peripherals and ICU, as each entry in this
    201  * structure contains the input IRQ index in ICU. Value is -1 for an unused input.
    202  * For a multi-channels peripheral, there is one chdev and one IRQ per channel.
    203  * This structure is replicated in each cluster. It is allocated as a global variable
    204  * in the kernel_init.c file, and is initialised during kernel init.
    205  *****************************************************************************************/
    206 
    207 typedef struct chdev_icu_input_s
    208 {
    209     uint32_t   dma[CONFIG_MAX_DMA_CHANNELS];
    210     uint32_t   mmc;                             // MMC is single channel
    211 }
    212 chdev_icu_input_t;
    213 
    214 /******************************************************************************************
    215179 * This function display relevant values for a chdev descriptor.
    216180 ******************************************************************************************
  • trunk/kernel/kern/cluster.h

    r101 r188  
    133133
    134134    pmgr_t            pmgr;            /*! embedded process manager                       */
     135
     136    void            * pic_extend;      /*! PIC implementation specific extension          */
    135137}
    136138cluster_t;
  • trunk/kernel/kern/core.c

    r126 r188  
    3030#include <thread.h>
    3131#include <chdev.h>
    32 #include <dev_icu.h>
     32#include <dev_pic.h>
    3333#include <rpc.h>
    3434#include <cluster.h>
     
    5050        core->usage             = 0;
    5151        core->spurious_irqs     = 0;
    52         core->rpc_threads       = 0;
    53 
    54         list_root_init( &core->rpc_free_list );
    55 
    56         core->thread_rpc        = NULL;
     52    core->rpc_threads       = 0;
    5753        core->thread_idle       = NULL;
    5854        core->fpu_owner         = NULL;
    5955        core->rand_last         = hal_time_stamp() & 0xFFF;
    6056
     57    // initialize scheduler
    6158        sched_init( core );
    6259}
     
    167164}
    168165
     166
     167/* deprecated [AG] july 20017
    169168///////////////////////////////////////////////////
    170169void core_set_irq_vector_entry( core_t   * core,
     
    177176        else                            core->pti_vector[irq_id] = chdev;
    178177}
     178*/
  • trunk/kernel/kern/core.h

    r101 r188  
    3636struct thread_s;
    3737struct chdev_s;
    38 
     38enum   pic_impl_e;
    3939
    4040/****************************************************************************************
    4141 * This structure defines the core descriptor.
    42  * - It contains an embedded private scheduler.
    43  * - It contains the three interrupt vectors, implemented as three arrays of pointers
    44  *   on the source channel devices, for all IRQs allocated to the core.
     42 * Besides the core identifiers (gid,lid), it contains an embedded private scheduler.
     43 * It contains an architecture specific extension to store the interrupt vector(s).
     44 * The core_init()function must allocate memory for this extension, depending on the
     45 * PIC device implementation type.
    4546 ***************************************************************************************/
    4647
     
    5556        uint32_t            usage;          /*! cumulated busy_percent (idle / total)      */
    5657        uint32_t            spurious_irqs;  /*! for instrumentation...                     */
     58    uint32_t            rpc_threads;    /*! current RPC threads number for this core   */
    5759        struct thread_s   * thread_rpc;     /*! pointer on current RPC thread descriptor   */
    5860        struct thread_s   * thread_idle;    /*! pointer on idle thread descriptor          */
    5961        struct thread_s   * fpu_owner;      /*! pointer on current FPU owner thread        */
    6062    uint32_t            rand_last;      /*! last computed random value                 */
    61         uint32_t            rpc_threads;    /*! total number of RPC threads for this core  */
    62         list_entry_t        rpc_free_list;  /*! root of the list of free RPC threads       */
    63 
    6463        scheduler_t         scheduler;      /*! embedded private scheduler                 */
    6564
    66     struct chdev_s    * hwi_vector[CONFIG_MAX_HWIS_PER_ICU];     /*! on source device  */
    67     struct chdev_s    * pti_vector[CONFIG_MAX_PTIS_PER_ICU];     /*! on source device  */
    68     struct chdev_s    * wti_vector[CONFIG_MAX_WTIS_PER_ICU];     /*! on source device  */
     65    void              * pic_extend;     /*! PIC implementation specific extension      */
    6966}
    7067core_t;
    7168
    72 /***************************************************************************************
     69/****************************************************************************************
    7370 * This macro returns a pointer on the calling core descriptor.
    74  **************************************************************************************/
     71 ***************************************************************************************/
    7572
    7673#define CURRENT_CORE  (CURRENT_THREAD->core)
    7774
    7875/***************************************************************************************
    79  * TODO this initialisation must be completed for the thread_idle field... [AG]
    80  * This function initializes a core descriptor from information found in arch_info.
     76 * This function initializes a core descriptor.
    8177 * It makes the association [gid] <=> [lid], as defined in arch_info, via the
    8278 * boot_info_t structure build by the bootloader in each cluster.
     79 * It allocates memory for the PIC infrastructure specific core extension.
     80 * It does NOT initialize the <thread_idle> and the <pic_extend> fields,
     81 * that must be completed later.
    8382 ***************************************************************************************
    8483 * @ core      : pointer on core descriptor to initialise.
    85  * @ lid       : local core index
    86  * @ gid       : global core identifier (hardware index)
     84 * @ lid       : local core index in cluster.
     85 * @ gid       : global core identifier (hardware index).
    8786 **************************************************************************************/
    88 void core_init( core_t   * core,
    89                 lid_t      lid,
    90                 gid_t      gid );
     87void core_init( core_t          * core,
     88                lid_t             lid,
     89                gid_t             gid );
    9190
    9291/***************************************************************************************
  • trunk/kernel/kern/do_interrupt.c

    r140 r188  
    3030void do_interrupt( thread_t * this )
    3131{
    32     // update user time
    33     thread_user_time_update( this );
    34 
    35     // access ICU device to call the relevant ISR
    36     dev_icu_irq_handler();
    37 
    38     // handle pending signals for interrupted thread
    39     thread_signals_handle( this );
    40 
    41     // update kernel time
    42     thread_kernel_time_update( this );
    4332}
  • trunk/kernel/kern/kernel_init.c

    r127 r188  
    8585cluster_t            cluster_manager                         CONFIG_CACHE_LINE_ALIGNED;
    8686
     87// This variable defines the TXT0 kernel terminal
     88__attribute__((section(".kdata")))
     89chdev_t              txt0_chdev                              CONFIG_CACHE_LINE_ALIGNED;
     90
    8791// This variables define the kernel process0 descriptor
    8892__attribute__((section(".kdata")))
     
    9397chdev_directory_t    chdev_dir                               CONFIG_CACHE_LINE_ALIGNED;
    9498
    95 // This variable contains the input IRQ indexes for the PIC device
     99// This variable contains the input IRQ indexes for the IOPIC controller
    96100__attribute__((section(".kdata")))
    97 chdev_pic_input_t    chdev_pic_input                         CONFIG_CACHE_LINE_ALIGNED;
    98 
    99 // This variable contains the input IRQ indexes for the ICU device
     101iopic_input_t         iopic_input                             CONFIG_CACHE_LINE_ALIGNED;
     102
     103// This variable contains the input IRQ indexes for the LAPIC controller
    100104__attribute__((section(".kdata")))
    101 chdev_icu_input_t    chdev_icu_input                         CONFIG_CACHE_LINE_ALIGNED;
     105lapic_input_t        lapic_input                             CONFIG_CACHE_LINE_ALIGNED;
    102106
    103107// This variable defines the local cluster identifier
    104108__attribute__((section(".kdata")))
    105109cxy_t                local_cxy                               CONFIG_CACHE_LINE_ALIGNED;
    106 
    107 // This variable defines the TXT0 chdev descriptor
    108 __attribute__((section(".kdata")))
    109 chdev_t              txt0_chdev                              CONFIG_CACHE_LINE_ALIGNED;
    110110
    111111// This variable is used for CP0 cores synchronisation in kernel_init()
     
    142142
    143143///////////////////////////////////////////////////////////////////////////////////////////
    144 // This static function initializes the TXT0 chdev descriptor, associated to the "kernel
    145 // terminal", and shared by all kernel instances for debug messages. It also registers it
    146 // in the chdev directory, containing extended pointers on all chdevs.
    147 // The global variable txt0_chdev is replicated in all clusters, but only the chdev
    148 // allocated in I/O cluster is used by ALMOS-MKH.
    149 // Therefore, this function must be called by a thread running in the I/O cluster.
     144// This function initializes the TXT0 chdev descriptor, that is the "kernel terminal",
     145// shared by all kernel instances for debug messages.
     146// It is a global variable (replicated in all clusters), because this terminal is used
     147// before the kmem allocator initialisation, but only the instance in cluster containing
     148// the calling core is registered in the "chdev_dir" directory.
    150149// As this TXT0 chdev supports only the TXT_SYNC_WRITE command, we don't create
    151150// a server thread, we don't allocate a WTI, and we don't initialize the waiting queue.
     
    158157    uint32_t        dev_nr;          // actual number of devices in this cluster
    159158    xptr_t          base;            // remote pointer on segment base
    160     uint32_t        type;            // peripheral type
    161159    uint32_t        func;            // device functional index
    162160    uint32_t        impl;            // device implementation index
     
    164162    uint32_t        x;               // X cluster coordinate
    165163    uint32_t        y;               // Y cluster coordinate
     164    uint32_t        channels;        // number of channels
    166165
    167166    // get number of peripherals and base of devices array from boot_info
     
    173172    {
    174173        base        = dev_tbl[i].base;
    175         type        = dev_tbl[i].type;
    176         func        = FUNC_FROM_TYPE( type );
    177         impl        = IMPL_FROM_TYPE( type );
     174        func        = FUNC_FROM_TYPE( dev_tbl[i].type );
     175        impl        = IMPL_FROM_TYPE( dev_tbl[i].type );
     176        channels    = dev_tbl[i].channels;
    178177
    179178        if (func == DEV_FUNC_TXT )
    180179        {
    181             // initialize basic fields
    182             txt0_chdev.func     = func;
    183             txt0_chdev.impl     = impl;
    184             txt0_chdev.channel  = 0;
    185             txt0_chdev.is_rx    = 0;
    186             txt0_chdev.base     = base;
    187 
    188             // initialize lock
     180            assert( (channels > 0) , __FUNCTION__ ,
     181                    "numner of TXT channels cannot be 0\n");
     182
     183            // initializes TXT0 basic fields
     184            txt0_chdev.func    = func;
     185            txt0_chdev.impl    = impl;
     186            txt0_chdev.channel = 0;
     187            txt0_chdev.base    = base;
     188            txt0_chdev.is_rx   = false;
     189
     190            // initializes lock
    189191            remote_spinlock_init( XPTR( local_cxy , &txt0_chdev.wait_lock ) );
    190 
    191             // TODO use generic device initialisation
    192             // hal_drivers_txt_init( &txt0_chdev );
    193 
    194             if( impl == IMPL_TXT_TTY )
    195             {
    196                 txt0_chdev.cmd = &soclib_tty_cmd;
    197                 txt0_chdev.isr = &soclib_tty_isr;
    198                 soclib_tty_init( &txt0_chdev );
    199             }
    200 
    201             // initialize the replicated chdev_dir[x][y] structures
     192           
     193            // TXT specific initialisation:
     194            // no server thread & no IRQ routing for channel 0
     195            dev_txt_init( &txt0_chdev );                 
     196
     197            // register the TXT0 in all chdev_dir[x][y] structures
    202198            for( x = 0 ; x < info->x_size ; x++ )
    203199            {
     
    210206            }
    211207
    212             kinit_dmsg("\n[INFO] %s : core[%x][0] created TXT0 chdev"
    213                        " / paddr = %l at cycle %d\n",
    214                        __FUNCTION__ , local_cxy , chdev_func_str( func ),
    215                        XPTR(local_cxy , &txt0_chdev) , hal_get_cycles() );
    216         }
    217     }
    218 }
    219 
    220 ///////////////////////////////////////////////////////////////////////////////////////////
    221 // This static function allocates memory for the chdev (channel_device) descriptors
    222 // associated to the internal peripherals contained in the local cluster. These internal
    223 // devices (ICU, MMC, DMA) chdev descriptors are placed in the local cluster.
    224 // It initialises these device descriptors as specified by the boot_info_t structure,
    225 // including the dynamic linking with the driver for the specified implementation.
    226 // Finally, all copies of the devices directory are initialised.
     208                    kinit_dmsg("\n[INFO] %s created TXT0 chdev in cluster %x at cycle %d\n",
     209                       __FUNCTION__ , local_cxy , (uint32_t)hal_time_stamp() );
     210        }
     211        } // end loop on devices
     212}  // end txt0_device_init()
     213
     214///////////////////////////////////////////////////////////////////////////////////////////
     215// This function allocates memory and initializes the chdev descriptors for the internal
     216// peripherals contained in the local cluster, other than the LAPIC, as specified by
     217// the boot_info, including the linking with the driver for the specified implementation.
     218// The relevant entries in all copies of the devices directory are initialised.
    227219///////////////////////////////////////////////////////////////////////////////////////////
    228220// @ info    : pointer on the local boot-info structure.
     
    230222static void internal_devices_init( boot_info_t * info )
    231223{
    232     boot_device_t * dev;             // pointer on boot_info device (ICU/MMC/DMA)
    233     uint32_t        x;               // X cluster coordinate
    234     uint32_t        y;               // Y cluster coordinate
    235     chdev_t       * chdev_ptr;       // local pointer on chdev descriptor
    236     xptr_t          chdev_xp;        // extended pointer on chdev descriptor
    237 
    238     ///////////  ICU   //////////
    239 
    240     dev = &info->dev_icu;
    241 
    242     assert( ((info->cores_nr == 0) || (dev->channels != 0)) , __FUNCTION__ ,
    243             "ICU device must exist in cluster containing cores" );
    244 
    245     assert( (dev->channels == 1) , __FUNCTION__ ,
    246             "channels number must be 1 for ICU device" );
    247 
    248     assert( (FUNC_FROM_TYPE( dev->type ) == DEV_FUNC_ICU ) , __FUNCTION__ ,
    249             " inconsistent ICU  device type");
    250 
    251     // create one chdev in local cluster
    252     chdev_ptr = chdev_create( FUNC_FROM_TYPE( dev->type ),
    253                               IMPL_FROM_TYPE( dev->type ),
    254                               0,                              // channel
    255                               false,                          // TX
    256                               dev->base );
    257 
    258     assert( (chdev_ptr != NULL) , __FUNCTION__ , "cannot allocate ICU chdev" );
    259 
    260     // get extended pointer on chdev descriptor
    261     chdev_xp = XPTR( local_cxy , chdev_ptr );
    262 
    263     // make ICU specific initialisation
    264     // TODO remove these three parameters
    265     dev_icu_init( chdev_ptr , dev->param0 , dev->param1 , dev->param2 );
    266 
    267     // initialize the ICU field in the chdev_dir[x][y] structures
    268     // replicated in all clusters, and containing extended pointers
    269     // on all remotely accessible devices
    270     for( x = 0 ; x < info->x_size ; x++ )
    271     {
    272         for( y = 0 ; y < info->y_size ; y++ )
    273         {
    274             cxy_t  cxy = (x<<info->y_width) + y;
    275             hal_remote_swd( XPTR( cxy , &chdev_dir.icu[local_cxy] ) , chdev_xp );
    276         }
    277     }
    278 
    279     // initialize the entries of the local chdev_icu_input structure
    280     // defining how internal peripherals are connected to ICU
    281     uint32_t   id;
    282     uint8_t    valid;
    283     uint32_t   src_type;
    284     uint8_t    src_ch;
    285     uint32_t   src_func;
    286     for( id = 0 ; id < CONFIG_MAX_HWIS_PER_ICU ; id++ )
    287     {
    288         valid    = dev->irq[id].valid;
    289         src_type = dev->irq[id].dev_type;
    290         src_ch   = dev->irq[id].channel;
    291         src_func = FUNC_FROM_TYPE( src_type );
    292 
    293         if( valid ) // only valid local IRQs are registered
    294         {
    295             if     ( src_func == DEV_FUNC_MMC ) chdev_icu_input.mmc = id;
    296             else if( src_func == DEV_FUNC_DMA ) chdev_icu_input.dma[src_ch] = id;
    297             else assert( false , __FUNCTION__ , "illegal source device for ICU input" );
    298         }
    299     }
    300 
    301     kinit_dmsg("\n[INFO] %s : core[%x][0] created ICU chdev at cycle %d\n",
    302                __FUNCTION__ , local_cxy , hal_get_cycles() );
    303 
    304     /////////// MMC internal chdev ///////////
    305 
    306     dev = &info->dev_mmc;
    307 
    308     if( dev->channels != 0 )   // MMC device is defined
    309     {
    310         assert( (dev->channels == 1) , __FUNCTION__ ,
    311             "channels number must be 1 for MMC device" );
    312 
    313         assert( (FUNC_FROM_TYPE( dev->type ) == DEV_FUNC_MMC ) , __FUNCTION__ ,
    314             " inconsistent MMC device type");
    315 
    316         // create one chdev in local cluster
    317         chdev_ptr = chdev_create( FUNC_FROM_TYPE( dev->type ),
    318                                   IMPL_FROM_TYPE( dev->type ),
    319                                   0,                              // channel
    320                                   false,                          // TX
    321                                   dev->base );
    322 
    323         assert( (chdev_ptr != NULL) , __FUNCTION__ , "cannot allocate MMC chdev" );
    324 
    325         // get extended pointer on chdev descriptor
    326         chdev_xp = XPTR( local_cxy , chdev_ptr );
    327 
    328         // make MMC specific initialisation
    329         dev_mmc_init( chdev_ptr );
    330 
    331         // initialize the MMC field in the chdev_dir[x][y] structures
    332         // replicated in all clusters, and containing extended pointers
    333         // on all remotely accessible devices
    334         for( x = 0 ; x < info->x_size ; x++ )
    335         {
    336             for( y = 0 ; y < info->y_size ; y++ )
     224    boot_device_t * dev_tbl;         // pointer on array of internaldevices in boot_info
     225        uint32_t        dev_nr;          // actual number of devices in this cluster
     226        xptr_t          base;            // remote pointer on segment base
     227    uint32_t        func;            // device functionnal index
     228    uint32_t        impl;            // device implementation index
     229        uint32_t        i;               // device index in dev_tbl
     230        uint32_t        x;               // X cluster coordinate
     231        uint32_t        y;               // Y cluster coordinate
     232        uint32_t        channels;        // number of channels
     233        uint32_t        channel;         // channel index
     234        chdev_t       * chdev_ptr;       // local pointer on created chdev
     235
     236    // get number of internal peripherals and base from boot_info
     237        dev_nr  = info->int_dev_nr;
     238    dev_tbl = info->int_dev;
     239
     240    // loop on internal peripherals
     241        for( i = 0 ; i < dev_nr ; i++ )
     242        {
     243        base        = dev_tbl[i].base;
     244        channels    = dev_tbl[i].channels;
     245        func        = FUNC_FROM_TYPE( dev_tbl[i].type );
     246        impl        = IMPL_FROM_TYPE( dev_tbl[i].type );
     247
     248        //////////////////////////
     249        if( func == DEV_FUNC_MMC ) 
     250        {
     251            assert( (channels == 1) , __FUNCTION__ ,
     252                    "MMC device must be single channel\n" );
     253
     254            // create chdev in local cluster
     255            chdev_ptr = chdev_create( func,
     256                                      impl,
     257                                      0,          // channel
     258                                      false,      // direction
     259                                      base );
     260
     261            assert( (chdev_ptr != NULL) , __FUNCTION__ ,
     262                    "cannot allocate memory for MMC chdev\n" );
     263           
     264            // make MMC specific initialisation
     265            dev_mmc_init( chdev_ptr );
     266
     267            // set the MMC field in all chdev_dir[x][y] structures
     268            for( x = 0 ; x < info->x_size ; x++ )
    337269            {
    338                 cxy_t  cxy = (x<<info->y_width) + y;
    339                 hal_remote_swd( XPTR( cxy , &chdev_dir.mmc[local_cxy] ) , chdev_xp );
     270                for( y = 0 ; y < info->y_size ; y++ )
     271                {
     272                    cxy_t  cxy = (x<<info->y_width) + y;
     273                    hal_remote_swd( XPTR( cxy , &chdev_dir.mmc[local_cxy] ),
     274                                    XPTR( local_cxy , chdev_ptr ) );
     275                }
    340276            }
    341         }
    342 
    343         kinit_dmsg("\n[INFO] %s : core[%x][0] created MMC chdev at cycle %d\n",
    344                    __FUNCTION__ , local_cxy , hal_get_cycles() );
    345     }
    346 
    347     /////////// DMA internal chdevs //////////
    348 
    349     dev = &info->dev_dma;
    350 
    351     if( dev->channels != 0 )   // DMA device is defined
    352     {
    353         assert( (FUNC_FROM_TYPE( dev->type ) == DEV_FUNC_DMA ) , __FUNCTION__ ,
    354                 " inconsistent DMA  device type");
    355 
    356         // create one chdev per channel in local cluster
    357         uint32_t channel;
    358         for( channel = 0 ; channel < dev->channels ; channel++ )
    359         {
    360             chdev_ptr = chdev_create( FUNC_FROM_TYPE( dev->type ),
    361                                       IMPL_FROM_TYPE( dev->type ),
    362                                       channel,                        // channel
    363                                       false,                          // TX
    364                                       dev->base );
    365 
    366             assert( (chdev_ptr != NULL) , __FUNCTION__ , "cannot allocate DMA chdev" );
    367 
    368             // get extended pointer on channel descriptor
    369             chdev_xp = XPTR( local_cxy , chdev_ptr );
    370 
    371             // make DMA specific initialisation
    372             dev_dma_init( chdev_ptr );
    373 
    374             // initialize only the DMA[channel] field in the local chdev_dir[x][y]
    375             // structure because the DMA device is not remotely accessible.
    376             chdev_dir.dma[channel] = chdev_xp;
    377 
    378             kinit_dmsg("\n[INFO] %s : core[%x][0] created DMA[%d] chdev at cycle %d\n",
    379                        __FUNCTION__ , local_cxy , channel , hal_get_cycles() );
     277
     278            if( local_cxy == 0 )
     279            kinit_dmsg("\n[INFO] %s created MMC chdev in cluster 0 at cycle %d\n",
     280                       __FUNCTION__ , local_cxy , (uint32_t)hal_time_stamp() );
     281        }
     282        ///////////////////////////////
     283        else if( func == DEV_FUNC_DMA )
     284        {
     285            // create one chdev per channel in local cluster
     286            for( channel = 0 ; channel < channels ; channel++ )
     287            {   
     288                // create chdev[channel] in local cluster
     289                chdev_ptr = chdev_create( func,
     290                                          impl,
     291                                          channel,
     292                                          false,     // direction
     293                                          base );
     294
     295                assert( (chdev_ptr != NULL) , __FUNCTION__ ,
     296                        "cannot allocate memory for DMA chdev" );
     297           
     298                // make DMA specific initialisation
     299                dev_dma_init( chdev_ptr );     
     300
     301                // initialize only the DMA[channel] field in the local chdev_dir[x][y]
     302                // structure because the DMA device is not remotely accessible.
     303                chdev_dir.dma[channel] = XPTR( local_cxy , chdev_ptr );
     304
     305                kinit_dmsg("\n[INFO] %s created DMA[%d] chdev in cluster 0 at cycle %d\n",
     306                           __FUNCTION__ , channel , (uint32_t)hal_time_stamp() );
     307            }
    380308        }
    381309    }
     
    383311
    384312///////////////////////////////////////////////////////////////////////////////////////////
    385 // This static function allocates memory for the chdev descriptors associated
    386 // to the external (shared) peripherals contained in the local cluster. These external
    387 // devices (IOB, IOC, TXT, NIC, etc ) are distributed on all clusters.
    388 // It initialises these device descriptors as specified by the boot_info_t structure,
     313// This function allocates memory and initializes the chdev descriptors for the 
     314// external (shared) peripherals other than the IOPIC, as specified by the boot_info,
    389315// including the dynamic linking with the driver for the specified implementation.
    390 // Finally, all copies of the devices directory are initialised.
    391 //
    392 // The number of channel_devices depends on the device functional type.
    393 // There are three nested loops to build the full set of external channel_devices:
    394 // - loop on external devices.
    395 // - loop on channels for multi-channels devices.
    396 // - loop on directions (RX/TX) for NIC device.
    397 // The set of channel_devices is indexed by the chdev_gid global index, that is used
    398 // to select the cluster containing a given chdev[func,channel,direction].
    399 // All clusters scan the full set of chdevs, but only the cluster matching
    400 // (chdev_gid % (x_size*y_size)) create the corresponding chdev.
    401 //
    402 // TODO check that cluster IO contains a PIC [AG]
    403 // TODO make a default initialisation for the chdev_dir structure (XPTR_NULL )  [AG]
     316// These chdev descriptors are distributed on all clusters, using a modulo on a global
     317// index, identically computed in all clusters: In each cluster, the local CP0 core
     318// computes the global index for all external chdevs, and creates only the chdevs that
     319// must be placed in the local cluster.
     320// The relevant entries in all copies of the devices directory are initialised.
    404321///////////////////////////////////////////////////////////////////////////////////////////
    405322// @ info    : pointer on the local boot-info structure.
     
    407324static void external_devices_init( boot_info_t * info )
    408325{
    409     boot_device_t * dev_tbl;         // pointer on array of devices in boot_info
    410     uint32_t        dev_nr;          // actual number of devices in this cluster
    411     xptr_t          base;            // remote pointer on segment base
    412     uint32_t        type;            // peripheral type
     326    boot_device_t * dev_tbl;         // pointer on array of external devices in boot_info
     327        uint32_t        dev_nr;          // actual number of external devices
     328        xptr_t          base;            // remote pointer on segment base
    413329    uint32_t        func;            // device functionnal index
    414330    uint32_t        impl;            // device implementation index
    415     uint32_t        i;               // device index in dev_tbl
    416     uint32_t        x;               // X cluster coordinate
    417     uint32_t        y;               // Y cluster coordinate
    418     uint32_t        channels_nr;     // number of channels
    419     uint32_t        channel;         // channel index
    420     uint32_t        directions_nr;   // number of directions
    421     uint32_t        direction;       // direction index
    422     uint32_t        p0;              // device parameter 0
    423     uint32_t        p1;              // device parameter 1
    424     uint32_t        p2;              // device parameter 2
    425     uint32_t        p3;              // device parameter 3
    426     uint32_t        first_channel;   // used in loop on channels
    427 
     331        uint32_t        i;               // device index in dev_tbl
     332        uint32_t        x;               // X cluster coordinate
     333        uint32_t        y;               // Y cluster coordinate
     334        uint32_t        channels;        // number of channels
     335        uint32_t        channel;         // channel index
     336        uint32_t        directions;      // number of directions (1 or 2)
     337        uint32_t        rx;              // direction index (0 or 1)
     338    uint32_t        first_channel;   // used in loop on channels for TXT
    428339    chdev_t       * chdev;           // local pointer on one channel_device descriptor
    429     xptr_t          chdev_xp;        // extended pointer on channel_device descriptor
    430     uint32_t        chdev_gid = 0;   // global index of channel_device descriptor
     340    uint32_t        ext_chdev_gid;   // global index of external chdev
    431341
    432342    // get number of peripherals and base of devices array from boot_info
     
    434344    dev_tbl     = info->ext_dev;
    435345
     346    // initializes global index (PIC is already placed in cluster 0
     347    ext_chdev_gid = 1;
     348
    436349    // loop on external peripherals
    437350    for( i = 0 ; i < dev_nr ; i++ )
    438351    {
    439         base        = dev_tbl[i].base;
    440         type        = dev_tbl[i].type;
    441         channels_nr = dev_tbl[i].channels;
    442         p0          = dev_tbl[i].param0;
    443         p1          = dev_tbl[i].param1;
    444         p2          = dev_tbl[i].param2;
    445         p3          = dev_tbl[i].param3;
    446 
    447         func     = FUNC_FROM_TYPE( type );
    448         impl     = IMPL_FROM_TYPE( type );
     352        base     = dev_tbl[i].base;
     353        channels = dev_tbl[i].channels;
     354        func     = FUNC_FROM_TYPE( dev_tbl[i].type );
     355        impl     = IMPL_FROM_TYPE( dev_tbl[i].type );
    449356
    450357        // There is one chdev per direction for NIC
    451         if (func == DEV_FUNC_NIC) directions_nr = 2;
    452         else                      directions_nr = 1;
     358        if (func == DEV_FUNC_NIC) directions = 2;
     359        else                      directions = 1;
    453360
    454361        // The TXT0 chdev has already been created
     
    456363        else                      first_channel = 0;
    457364
    458         // do nothing for ROM, that does not require a device descriptor.
     365        // do nothing for RO, that does not require a device descriptor.
    459366        if( func == DEV_FUNC_ROM ) continue;
    460367
    461         // check external device functional type
    462         if( (func != DEV_FUNC_IOB) &&
    463             (func != DEV_FUNC_PIC) &&
    464             (func != DEV_FUNC_IOC) &&
    465             (func != DEV_FUNC_TXT) &&
    466             (func != DEV_FUNC_NIC) &&
    467             (func != DEV_FUNC_FBF) )
    468         {
    469             assert( false , __FUNCTION__ , "undefined external peripheral type" );
    470         }
     368        // do nothing for PIC, that is already initialized
     369        if( func == DEV_FUNC_PIC ) continue;
     370
     371        // check PIC device initialized
     372        assert( (chdev_dir.pic != XPTR_NULL ) , __FUNCTION__ ,
     373              "PIC device must be initialized before other devices\n" );
     374
     375        // check external device functionnal type
     376        assert( ( (func == DEV_FUNC_IOB) ||
     377                  (func == DEV_FUNC_IOC) ||
     378                  (func == DEV_FUNC_TXT) ||
     379                  (func == DEV_FUNC_NIC) ||
     380                  (func == DEV_FUNC_FBF) ) , __FUNCTION__ ,
     381                  "undefined external peripheral type\n" );
    471382
    472383        // loops on channels
    473         for( channel = first_channel ; channel < channels_nr ; channel++ )
     384        for( channel = first_channel ; channel < channels ; channel++ )
    474385        {
    475386            // loop on directions
    476             for( direction = 0 ; direction < directions_nr ; direction++ )
     387            for( rx = 0 ; rx < directions ; rx++ )
    477388            {
    478                 // get target cluster for chdev[func,channel,direction]
    479                 uint32_t offset     = chdev_gid % ( info->x_size * info->y_size );
     389                // compute target cluster for chdev[func,channel,direction]
     390                uint32_t offset     = ext_chdev_gid % ( info->x_size * info->y_size );
    480391                uint32_t cx         = offset / info->y_size;
    481392                uint32_t cy         = offset % info->y_size;
     
    489400                                          impl,
    490401                                          channel,
    491                                           direction,
     402                                          rx,          // direction
    492403                                          base );
    493404
     
    495406                            "cannot allocate external device" );
    496407
    497                     // get extended pointer on chdev
    498                     chdev_xp = XPTR( local_cxy , chdev );
    499 
    500408                    // make device type specific initialisation
    501                     // the number of parameters depends on the device type
    502                     // TODO : remove the parameters that  must be provided by the drivers
    503409                    if     ( func == DEV_FUNC_IOB ) dev_iob_init( chdev );
    504410                    else if( func == DEV_FUNC_IOC ) dev_ioc_init( chdev );
    505411                    else if( func == DEV_FUNC_TXT ) dev_txt_init( chdev );
    506412                    else if( func == DEV_FUNC_NIC ) dev_nic_init( chdev );
    507                     else if( func == DEV_FUNC_PIC ) dev_pic_init( chdev , p0 );
    508                     else if( func == DEV_FUNC_FBF ) dev_fbf_init( chdev , p0 , p1 );
    509                     else
    510                     {
    511                         assert( false , __FUNCTION__ , "undefined device type" );
    512                     }
     413                    else if( func == DEV_FUNC_FBF ) dev_fbf_init( chdev );
    513414
    514415                    // all external (shared) devices are remotely accessible
     
    517418                    xptr_t * entry;
    518419
    519                     if( func == DEV_FUNC_IOB ) entry  = &chdev_dir.iob;
    520                     if( func == DEV_FUNC_PIC ) entry  = &chdev_dir.pic;
    521                     if( func == DEV_FUNC_TXT ) entry  = &chdev_dir.txt[channel];
    522                     if( func == DEV_FUNC_IOC ) entry  = &chdev_dir.ioc[channel];
    523                     if( func == DEV_FUNC_FBF ) entry  = &chdev_dir.fbf[channel];
    524                     if( func == DEV_FUNC_NIC ) entry  = &chdev_dir.nic_tx[channel];
     420                    if(func==DEV_FUNC_IOB            ) entry  = &chdev_dir.iob;
     421                    if(func==DEV_FUNC_IOC             ) entry  = &chdev_dir.ioc[channel];
     422                    if(func==DEV_FUNC_TXT            ) entry  = &chdev_dir.txt[channel];
     423                    if(func==DEV_FUNC_FBF             ) entry  = &chdev_dir.fbf[channel];
     424                    if((func==DEV_FUNC_NIC) && (rx==0)) entry  = &chdev_dir.nic_tx[channel];
     425                    if((func==DEV_FUNC_NIC) && (rx==1)) entry  = &chdev_dir.nic_rx[channel];
    525426
    526427                    for( x = 0 ; x < info->x_size ; x++ )
     
    529430                        {
    530431                            cxy_t  cxy = (x<<info->y_width) + y;
    531                             hal_remote_swd( XPTR( cxy , entry ) , chdev_xp );
     432                            hal_remote_swd( XPTR( cxy , entry ),
     433                                            XPTR( local_cxy , chdev ) );
    532434                        }
    533435                    }
    534436
    535                     kinit_dmsg("\n[INFO] %s : core[%x][0] create chdev %s[%d] at cycle %d\n",
    536                                __FUNCTION__ , local_cxy , chdev_func_str( func ),
    537                                channel , hal_get_cycles() );
     437                            kinit_dmsg("\n[INFO] %s create chdev %s[%d] in cluster %x at cycle %d\n",
     438                               __FUNCTION__ , chdev_func_str( func ), channel,
     439                               local_cxy , (uint32_t)hal_time_stamp() );
    538440
    539441                }  // end if match
    540442
    541443                // increment chdev global index (matching or not)
    542                 chdev_gid++;
     444                ext_chdev_gid++;
    543445
    544446            } // end loop on directions
    545 
    546447        }  // end loop on channels
    547 
    548         // initialize the entries of the local chdev_pic_input structure
    549         // defining how external peripherals are connected to PIC
     448        } // end loop on devices
     449}  // end external_devices_init()
     450
     451///////////////////////////////////////////////////////////////////////////////////////////
     452// This function is called by CP0 in cluster 0 to allocate memory and initialize the PIC
     453// device, namely the informations attached to the external IOPIC controller.
     454// This initialisation must be done before other devices initialisation because the IRQ
     455// routing infrastructure is required for internal and external devices initialisation.
     456///////////////////////////////////////////////////////////////////////////////////////////
     457// @ info    : pointer on the local boot-info structure.
     458///////////////////////////////////////////////////////////////////////////////////////////
     459static void iopic_init( boot_info_t * info )
     460{
     461    boot_device_t * dev_tbl;         // pointer on boot_info external devices array
     462        uint32_t        dev_nr;          // actual number of external devices
     463        xptr_t          base;            // remote pointer on segment base
     464    uint32_t        func;            // device functionnal index
     465    uint32_t        impl;            // device implementation index
     466        uint32_t        i;               // device index in dev_tbl
     467    uint32_t        x;               // cluster X coordinate
     468    uint32_t        y;               // cluster Y coordinate
     469    bool_t          found;           // IOPIC found
     470        chdev_t       * chdev;           // pointer on PIC chdev descriptor
     471
     472    // get number of external peripherals and base of array from boot_info
     473        dev_nr      = info->ext_dev_nr;
     474    dev_tbl     = info->ext_dev;
     475
     476    // loop on external peripherals to get the IOPIC 
     477        for( i = 0 , found = false ; i < dev_nr ; i++ )
     478        {
     479        func = FUNC_FROM_TYPE( dev_tbl[i].type );
     480
    550481        if( func == DEV_FUNC_PIC )
    551482        {
    552             uint32_t   id;
    553             uint8_t    valid;
    554             uint32_t   dev_type;
    555             uint8_t    channel;
    556             uint8_t    is_rx;
    557 
    558             // loop on PIC inputs
    559             for( id = 0 ; id < CONFIG_MAX_IRQS_PER_PIC ; id++ )
     483            base     = dev_tbl[i].base;
     484            impl     = IMPL_FROM_TYPE( dev_tbl[i].type );
     485            found    = true;
     486            break;
     487        }
     488    }
     489
     490    assert( found , __FUNCTION__ , "PIC device not found\n" );
     491
     492    // allocate and initialize the PIC chdev in local cluster
     493    chdev = chdev_create( func,
     494                          impl,
     495                          0,      // channel
     496                          0,      // direction,
     497                          base );
     498
     499    assert( (chdev != NULL), __FUNCTION__ , "no memory for PIC chdev\n" );
     500
     501    // make PIC device type specific initialisation
     502    dev_pic_init( chdev );
     503
     504    // register extended pointer on PIC chdev in "chdev_dir" array in all clusters
     505    xptr_t * entry = &chdev_dir.pic;   
     506               
     507    for( x = 0 ; x < info->x_size ; x++ )
     508    {
     509        for( y = 0 ; y < info->y_size ; y++ )
     510        {
     511            cxy_t  cxy = (x<<info->y_width) + y;
     512            hal_remote_swd( XPTR( cxy , entry ) ,
     513                            XPTR( local_cxy , chdev ) );
     514        }
     515    }
     516
     517    // initialize the "iopic_input" structure
     518    // defining how external IRQs are connected to IOPIC
     519    uint32_t   id;
     520    uint8_t    valid;
     521    uint32_t   type;
     522    uint8_t    channel;
     523    uint8_t    is_rx;
     524
     525    for( id = 0 ; id < CONFIG_MAX_EXTERNAL_IRQS ; id++ )
     526    {
     527        valid   = dev_tbl[i].irq[id].valid;
     528        type    = dev_tbl[i].irq[id].dev_type;
     529        channel = dev_tbl[i].irq[id].channel;
     530        is_rx   = dev_tbl[i].irq[id].is_rx;
     531
     532        if( valid )  // only valid inputs are registered
     533        {
     534            uint32_t * index;  // local pointer on one entry
     535            uint16_t func = FUNC_FROM_TYPE( type );
     536
     537            if     ( func == DEV_FUNC_TXT )
     538            index = &iopic_input.txt[channel];
     539            else if( func == DEV_FUNC_IOC )
     540            index = &iopic_input.ioc[channel];
     541            else if( (func == DEV_FUNC_NIC) && (is_rx == 0) )
     542            index = &iopic_input.nic_tx[channel];
     543            else if( (func == DEV_FUNC_NIC) && (is_rx != 0) )
     544            index = &iopic_input.nic_rx[channel];
     545            else if( func == DEV_FUNC_IOB )
     546            index = &iopic_input.iob;
     547            else
     548            assert( false , __FUNCTION__ , "illegal source device for IOPIC input" );
     549
     550            // set entry in local structure
     551            *index = id;
     552        }
     553    }
     554
     555    kinit_dmsg("\n[INFO] %s created IOPIC chdev in cluster %x at cycle %d\n",
     556               __FUNCTION__ , local_cxy , (uint32_t)hal_time_stamp() );
     557   
     558}  // end iopic_init()
     559
     560///////////////////////////////////////////////////////////////////////////////////////////
     561// This function is called by all CP0s in all cluster to complete the PIC device
     562// initialisation, namely the informations attached to the LAPIC controller.
     563// This initialisation must be done after the IOPIC initialisation, but before other
     564// devices initialisation because the IRQ routing infrastructure is required for both
     565// internal and external devices initialisation.
     566///////////////////////////////////////////////////////////////////////////////////////////
     567// @ info    : pointer on the local boot-info structure.
     568///////////////////////////////////////////////////////////////////////////////////////////
     569static void lapic_init( boot_info_t * info )
     570{
     571    boot_device_t * dev_tbl;      // pointer on boot_info internal devices array
     572    uint32_t        dev_nr;       // number of internal devices
     573    uint32_t        i;            // device index in dev_tbl
     574        xptr_t          base;         // remote pointer on segment base
     575    uint32_t        func;         // device functionnal type in boot_info
     576    bool_t          found;        // LAPIC found
     577
     578    // get number of internal peripherals and base
     579        dev_nr      = info->int_dev_nr;
     580    dev_tbl     = info->int_dev;
     581
     582    // loop on internal peripherals to get the lapic device
     583        for( i = 0 , found = false ; i < dev_nr ; i++ )
     584        {
     585        func = FUNC_FROM_TYPE( dev_tbl[i].type );
     586
     587        if( func == DEV_FUNC_ICU )
     588        {
     589            base     = dev_tbl[i].base;
     590            found    = true;
     591            break;
     592        }
     593    }
     594
     595    // if the LAPIC controller is not defined in the boot_info,
     596    // we simply don't initialize the PIC extensions in the kernel,
     597    // making the assumption that the LAPIC related informations
     598    // are hidden in the hardware specific PIC driver.
     599    if( found )
     600    {
     601        // initialise the PIC extensions for
     602        // the core descriptor and core manager extensions
     603        dev_pic_extend_init( (uint32_t *)GET_PTR( base ) );
     604
     605        // initialize the "lapic_input" structure
     606        // defining how internal IRQs are connected to LAPIC
     607        uint32_t        id;
     608        uint8_t         valid;
     609        uint8_t         channel;
     610        uint32_t        func;
     611
     612        for( id = 0 ; id < CONFIG_MAX_INTERNAL_IRQS ; id++ )
     613        {
     614            valid    = dev_tbl[i].irq[id].valid;
     615            func     = FUNC_FROM_TYPE( dev_tbl[i].irq[id].dev_type );
     616            channel  = dev_tbl[i].irq[id].channel;
     617
     618            if( valid ) // only valid local IRQs are registered
    560619            {
    561                 valid     = dev_tbl[i].irq[id].valid;
    562                 dev_type  = dev_tbl[i].irq[id].dev_type;
    563                 channel   = dev_tbl[i].irq[id].channel;
    564                 is_rx     = dev_tbl[i].irq[id].is_rx;
    565 
    566                 if( valid )  // only valid inputs are registered
    567                 {
    568                     uint32_t * index;  // local pointer on one entry
    569                     uint16_t dev_func = FUNC_FROM_TYPE( dev_type );
    570 
    571                     if( dev_func == DEV_FUNC_TXT )
    572                     {
    573                         index = &chdev_pic_input.txt[channel];
    574                     }
    575                     else if( dev_func == DEV_FUNC_IOC )
    576                     {
    577                         index = &chdev_pic_input.ioc[channel];
    578                     }
    579                     else if( (dev_func == DEV_FUNC_NIC) && (is_rx == 0) )
    580                     {
    581                         index = &chdev_pic_input.nic_tx[channel];
    582                     }
    583                     else if( (dev_func == DEV_FUNC_NIC) && (is_rx != 0) )
    584                     {
    585                         index = &chdev_pic_input.nic_rx[channel];
    586                     }
    587                     else
    588                     {
    589                         assert( false , __FUNCTION__ , "illegal source device for PIC input" );
    590                     }
    591 
    592                     // set entry in local structure
    593                     *index = id;
    594                 }
    595             } // end loop on PIC inputs
    596         } // end PIC
    597     } // end loop on devices
    598 }  // end external_devices_init()
    599 
     620                if     ( func == DEV_FUNC_MMC ) lapic_input.mmc = id;
     621                else if( func == DEV_FUNC_DMA ) lapic_input.dma[channel] = id;
     622                else assert( false , __FUNCTION__ , "illegal source device for LAPIC input" );
     623            }
     624        }
     625    }
     626}  // end lapic_init()
    600627
    601628///////////////////////////////////////////////////////////////////////////////////////////
     
    645672void kernel_init( boot_info_t * info )
    646673{
    647     lid_t        core_lid = -1;      // running core local index
    648     cxy_t        core_cxy = -1;      // running core cluster identifier
    649     gid_t        core_gid;           // running core hardware identifier
    650     cluster_t  * cluster;            // pointer on local cluster manager
    651     core_t     * core;               // pointer on running core descriptor
    652     thread_t   * thread;             // pointer on idle thread descriptor
     674    lid_t        core_lid = -1;        // running core local index
     675    cxy_t        core_cxy = -1;        // running core cluster identifier
     676    gid_t        core_gid;             // running core hardware identifier
     677    cluster_t  * cluster;              // pointer on local cluster manager
     678    core_t     * core;                 // pointer on running core descriptor
     679    thread_t   * thread;               // pointer on idle thread descriptor
     680    xptr_t       vfs_root_inode_xp;    // extended pointer on VFS root inode
     681//  xptr_t       devfs_root_inode_xp;  // extended pointer on DEVFS root inode
    653682    error_t      error;
    654683
    655     // all cores get and check core identifiers
     684    cxy_t        io_cxy = info->io_cxy;
     685
     686    /////////////////////////////////////////////////////////////////////////////////
     687    // STEP 0 : Each core get its core identifier from boot_info, and makes
     688    //          a partial initialisation of its private idle thread descriptor.
     689    //          CP0 initializes the "local_cxy" global variable.
     690    //          CP0 in cluster IO initializes the TXT0 chdev to print log messages.
     691    /////////////////////////////////////////////////////////////////////////////////
     692
    656693    error = get_core_identifiers( info,
    657694                                  &core_lid,
     
    668705    hal_set_current_thread( thread );
    669706
     707    // each core initializes the idle thread "locks_root" and "xlocks_root" fields
    670708    list_root_init( &thread->locks_root );
    671     xlist_root_init( XPTR( local_cxy, &thread->xlocks_root ) );
    672 
    673     // CP0 in I/O cluster initializes TXT0 chdev descriptor
    674     if( (core_lid == 0) && (core_cxy == info->io_cxy) ) txt0_device_init( info );
    675 
    676     /////////////////////////////////////////////////////////////////////////////////
    677     // global & local synchro to protect access to TXT0 terminal
    678     if( core_lid == 0 ) remote_barrier( XPTR( info->io_cxy , &global_barrier ),
     709    xlist_root_init( XPTR( local_cxy , &thread->xlocks_root ) );
     710
     711    // CP0 in I/O cluster initialises TXT0 chdev descriptor
     712    if( (core_lid == 0) && (core_cxy == io_cxy) ) txt0_device_init( info );
     713
     714    /////////////////////////////////////////////////////////////////////////////////
     715    if( core_lid == 0 ) remote_barrier( XPTR( io_cxy , &global_barrier ),
    679716                                        (info->x_size * info->y_size) );
    680717    barrier_wait( &local_barrier , info->cores_nr );
    681     /////////////////////////////////////////////////////////////////////////////////
    682 
    683     if( (core_lid ==  0) && (local_cxy == info->io_cxy) )
    684     {
    685         kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 0 at cycle %d\n",
    686                    __FUNCTION__ , core_cxy , core_lid , hal_get_cycles() );
    687     }
    688 
    689     // all cores check core identifiers
     718
     719    if( (core_lid ==  0) && (local_cxy == 0) )
     720    kinit_dmsg("\n[INFO] %s exit barrier 0 at cycle %d : TXT0 initialized\n",
     721               __FUNCTION__, (uint32_t)hal_time_stamp());
     722
     723    /////////////////////////////////////////////////////////////////////////////
     724    // STEP 1 : all cores check its core identifier.
     725    //          CP0 initializes the local cluster manager.
     726    //          This includes the memory allocators.
     727    /////////////////////////////////////////////////////////////////////////////
     728
     729    // all cores check identifiers
    690730    if( error )
    691731    {
     
    696736    }
    697737
    698     // CP0 initializes the local cluster manager (cores and memory allocators)
     738    // CP0 initializes cluster manager
    699739    if( core_lid == 0 )
    700740    {
     
    703743        if( error )
    704744        {
    705             nolock_printk("\n[PANIC] in %s : cannot initialise cluster manager in cluster %x",
     745            nolock_printk("\n[PANIC] in %s : cannot initialise cluster %x",
    706746                   __FUNCTION__ , local_cxy );
    707747            hal_core_sleep();
     
    710750
    711751    /////////////////////////////////////////////////////////////////////////////////
    712     // global & local synchro, to protect access to cluster manager
    713     if( core_lid == 0 ) remote_barrier( XPTR( info->io_cxy , &global_barrier ),
     752    if( core_lid == 0 ) remote_barrier( XPTR( io_cxy , &global_barrier ),
    714753                                        (info->x_size * info->y_size) );
    715754    barrier_wait( &local_barrier , info->cores_nr );
    716755    /////////////////////////////////////////////////////////////////////////////////
    717756
    718     if( (core_lid ==  0) && (local_cxy == info->io_cxy) )
    719     {
    720         kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 1 at cycle %d\n",
    721                    __FUNCTION__ , core_cxy , core_lid , hal_get_cycles() );
    722     }
    723 
    724     // all cores get pointer on local cluster manager and on core descriptor
     757    if( (core_lid ==  0) && (local_cxy == 0) )
     758    kinit_dmsg("\n[INFO] %s exit barrier 1 at cycle %d : clusters initialised\n",
     759               __FUNCTION__, (uint32_t)hal_time_stamp());
     760
     761    /////////////////////////////////////////////////////////////////////////////////
     762    // STEP 2 : all CP0s initialize the process_zero descriptor.
     763    //          CP0 in cluster 0 initialises the IOPIC device.
     764    //          all CP0s complete the distibuted LAPIC initialization.
     765    /////////////////////////////////////////////////////////////////////////////////
     766
     767    // all cores get pointer on local cluster manager & core descriptor
    725768    cluster = &cluster_manager;
    726769    core    = &cluster->core_tbl[core_lid];
    727770
    728     // CP0 initializes the process_zero descriptor
     771    // all CP0s initialize the process_zero descriptor
    729772    if( core_lid == 0 ) process_reference_init( &process_zero , 0 , XPTR_NULL );
    730773
    731 #ifdef __HAL_x86_64__
    732         return; /* XXX temporary */
    733 #endif
    734 
    735     // CP0 allocates and initializes the internal peripheral chdev descriptors.
    736     // Each CP0[cxy] scan the set of its internal (private) peripherals,
     774    // CP0 in cluster 0 initializes the PIC chdev,
     775    if( (core_lid == 0) && (local_cxy == 0) ) iopic_init( info );
     776   
     777    // all CP0s initialize their local LAPIC extension,
     778    if( core_lid == 0 ) lapic_init( info );
     779
     780    ////////////////////////////////////////////////////////////////////////////////
     781    if( core_lid == 0 ) remote_barrier( XPTR( io_cxy , &global_barrier ),
     782                                        (info->x_size * info->y_size) );
     783    barrier_wait( &local_barrier , info->cores_nr );
     784    ////////////////////////////////////////////////////////////////////////////////
     785
     786    if( (core_lid ==  0) && (local_cxy == 0) )
     787    kinit_dmsg("\n[INFO] %s exit barrier 2 at cycle %d : PIC initialised\n",
     788               __FUNCTION__, (uint32_t)hal_time_stamp());
     789
     790    ////////////////////////////////////////////////////////////////////////////////
     791    // STEP 3 : all CP0s initialize their local chdev descriptors
     792    //          (both internal devices and external devices).
     793    ////////////////////////////////////////////////////////////////////////////////
     794
     795    // CP0 scan the internal (private) peripherals,
    737796    // and allocates memory for the corresponding chdev descriptors.
    738797    if( core_lid == 0 ) internal_devices_init( info );
    739 
    740     // CP0 allocates one WTI mailbox per core for Inter Processor Interrupt
    741     // this must be done after ICU chdev initialisation, by CP0 only, and before
    742     // external devices initialisation to enforce the rule :
    743     // "The WTI index for the IPI routed to core[lid] is lid"
    744     if( core_lid == 1 )
    745     {
    746         uint32_t  wti_id;
    747         uint32_t  lid;
    748         for( lid = 0 ; lid < LOCAL_CLUSTER->cores_nr ; lid++ )
    749         {
    750             wti_id = dev_icu_wti_alloc();
    751 
    752             if( wti_id != lid )
    753             {
    754                 nolock_printk("\n[PANIC] in %s : WTI index for IPI = %d / core_lid = %d",
    755                               __FUNCTION__ , wti_id , lid );
    756                 hal_core_sleep();
    757             }
    758 
    759             dev_icu_enable_irq( lid , WTI_TYPE , wti_id , NULL );
    760         }
    761     }
     798       
    762799
    763800    // All CP0s contribute to initialise external peripheral chdev descriptors.
     
    765802    // and allocates memory for the chdev descriptors that must be placed
    766803    // on the (cxy) cluster according to the global index value.
     804
    767805    if( core_lid == 0 ) external_devices_init( info );
    768806
    769807    /////////////////////////////////////////////////////////////////////////////////
    770     // global &local synchro to protect access to peripherals
    771     if( core_lid == 0 ) remote_barrier( XPTR( info->io_cxy , &global_barrier ),
     808    if( core_lid == 0 ) remote_barrier( XPTR( io_cxy , &global_barrier ),
    772809                                        (info->x_size * info->y_size) );
    773810    barrier_wait( &local_barrier , info->cores_nr );
    774811    /////////////////////////////////////////////////////////////////////////////////
    775812
    776     if( (core_lid ==  0) && (local_cxy == info->io_cxy) )
    777     {
    778         kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 2 at cycle %d\n",
    779                    __FUNCTION__ , core_cxy , core_lid , hal_get_cycles() );
    780     }
    781 
     813    if( (core_lid ==  0) && (local_cxy == 0) )
     814    kinit_dmsg("\n[INFO] %s exit barrier 3 at cycle %d : all chdev initialised\n",
     815               __FUNCTION__, (uint32_t)hal_time_stamp());
     816
     817    /////////////////////////////////////////////////////////////////////////////////
     818    // STEP 4 : Alls cores initialize their private IDLE thread.
     819    //          Only CP0 in cluster 0 creates the VFS root inode.
     820    //          It access the boot device to initialize the file system context.
     821    /////////////////////////////////////////////////////////////////////////////////
     822
     823    // all cores create idle thread descriptor
    782824    error = thread_kernel_init( thread,
    783825                                THREAD_IDLE,
     
    792834    }
    793835
    794     // register idle thread in scheduler
     836    // all cores register idle thread in scheduler
    795837    core->scheduler.idle = thread;
    796838
    797     // activate the idle thread
     839    // all core activate the idle thread
    798840    thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
    799841
    800     if( (core_lid ==  0) && (local_cxy == info->io_cxy) )
    801     {
    802         kinit_dmsg("\n[INFO] %s : core[%x][%d] created idle thread %x at cycle %d\n",
    803                    __FUNCTION__ , core_cxy , core_lid , thread , hal_get_cycles());
    804     }
    805 
    806     // CP0 in all clusters initializes cooperatively VFS and DEVFS
    807     if( (core_lid == 0)  )
    808     {
    809         xptr_t  root_inode_xp;
    810 
    811         // initialize root File System (must be FATFS in this implementation)
     842    if( (core_lid ==  0) && (local_cxy == 0) )
     843    {
     844        kinit_dmsg("\n[INFO] %s : created idle thread %x at cycle %d\n",
     845                   __FUNCTION__ , thread , (uint32_t)hal_time_stamp());
     846    }
     847
     848    // CPO in cluster 0 creates the VFS root
     849    if( (core_lid ==  0) && (local_cxy == 0 ) )
     850    {
     851        vfs_root_inode_xp = XPTR_NULL;
     852
     853        // File System must be FATFS in this implementation,
     854        // but other File System can be introduced here
    812855        if( CONFIG_VFS_ROOT_IS_FATFS )
    813856        {
    814             root_inode_xp = fatfs_init();
     857            // 1. create FATFS context in cluster 0
     858            fatfs_ctx_t * fatfs_ctx = fatfs_ctx_alloc();
     859
     860            nolock_assert( (fatfs_ctx != NULL) , __FUNCTION__ ,
     861                           "cannot create FATFS context in cluster 0\n" );
     862
     863            // 2. access boot device to initialize FATFS context
     864            fatfs_ctx_init( fatfs_ctx );
     865 
     866            // 3. get various informations from FATFS context
     867            uint32_t root_dir_cluster = fatfs_ctx->root_dir_cluster;
     868            uint32_t cluster_size     = fatfs_ctx->bytes_per_sector *
     869                                        fatfs_ctx->sectors_per_cluster;
     870            uint32_t total_clusters   = fatfs_ctx->fat_sectors_count << 7;
     871 
     872            // 4. create VFS root inode in cluster 0
     873            error = vfs_inode_create( XPTR_NULL,                           // dentry_xp
     874                                      FS_TYPE_FATFS,                       // fs_type
     875                                      INODE_TYPE_DIR,                      // inode_type
     876                                      (void *)(intptr_t)root_dir_cluster,  // extend
     877                                      0,                                   // attr
     878                                      0,                                   // rights
     879                                      0,                                   // uid
     880                                      0,                                   // gid
     881                                      &vfs_root_inode_xp );                // return
     882
     883            nolock_assert( (error == 0) , __FUNCTION__ ,
     884                           "cannot create VFS root inode\n" );
     885
     886            // 5. initialize VFS context for FAT in cluster 0
     887            vfs_ctx_init( FS_TYPE_FATFS,                 // file system type
     888                          0,                             // attributes
     889                              total_clusters,               
     890                              cluster_size,
     891                              vfs_root_inode_xp,             // VFS root
     892                          fatfs_ctx );                   // extend
    815893        }
    816894        else
     
    820898        }
    821899
    822         if( root_inode_xp == XPTR_NULL )
    823         {
    824             nolock_printk("\n[PANIC] in %s : core[%x][%d] cannot initialize file system\n",
    825                    __FUNCTION__ , local_cxy , core_lid );
    826             hal_core_sleep();
    827         }
    828 
    829900        // register VFS root inode in process_zero
    830         process_zero.vfs_root_xp = root_inode_xp;
    831         process_zero.vfs_cwd_xp  = root_inode_xp;
    832 
    833         // mount the DEVFS File system
    834         devfs_mount( root_inode_xp , "dev" );
    835     }
    836 
    837 
    838     // CP0 in I/O cluster creates the process_init and print banner
    839     if( (core_lid ==  0) && (local_cxy == info->io_cxy) )
     901        process_zero.vfs_root_xp = vfs_root_inode_xp;
     902        process_zero.vfs_cwd_xp  = vfs_root_inode_xp;
     903    }
     904
     905    /////////////////////////////////////////////////////////////////////////////////
     906    if( core_lid == 0 ) remote_barrier( XPTR( io_cxy , &global_barrier ),
     907                                        (info->x_size * info->y_size) );
     908    barrier_wait( &local_barrier , info->cores_nr );
     909    /////////////////////////////////////////////////////////////////////////////////
     910
     911    if( (core_lid ==  0) && (local_cxy == 0) )
     912    kinit_dmsg("\n[INFO] %s exit barrier 4 at cycle %d : VFS OK in cluster 0\n",
     913               __FUNCTION__, (uint32_t)hal_time_stamp());
     914
     915    /////////////////////////////////////////////////////////////////////////////////
     916    // STEP 5 : Other CP0s allocate memory for the selected FS context,
     917    //          and initialise both the local FS context and the local VFS context
     918    //          from values stored in cluster 0.
     919    //          They get the VFS root inode extended pointer from cluster 0.
     920    /////////////////////////////////////////////////////////////////////////////////
     921
     922    if( (core_lid ==  0) && (local_cxy != 0) )
     923    {
     924        // File System must be FATFS in this implementation,
     925        // but other File System can be introduced here
     926        if( CONFIG_VFS_ROOT_IS_FATFS )
     927        {
     928            // allocate memory for FATFS context
     929            fatfs_ctx_t * fatfs_ctx = fatfs_ctx_alloc();
     930
     931            nolock_assert( (fatfs_ctx != NULL) , __FUNCTION__ ,
     932                           "cannot create FATFS context\n" );
     933
     934            // get local pointer on VFS context for FATFS
     935            vfs_ctx_t   * vfs_ctx = &fs_context[FS_TYPE_FATFS];
     936
     937            // copy VFS context from cluster 0 to local cluster
     938            hal_remote_memcpy( XPTR( local_cxy , vfs_ctx ),
     939                               XPTR( 0 , vfs_ctx ),
     940                               sizeof(vfs_ctx_t) );
     941
     942            // copy FATFS context from cluster 0 to local cluster
     943            hal_remote_memcpy( XPTR( local_cxy , fatfs_ctx ),
     944                               XPTR( 0 , fatfs_ctx ),
     945                               sizeof(fatfs_ctx_t) );
     946
     947            // update extend field in local copy of VFS context
     948            vfs_ctx->extend = fatfs_ctx;
     949        }
     950
     951        // get extended pointer on VFS root inode from cluster 0
     952        vfs_root_inode_xp = hal_remote_lwd( XPTR( 0 , process_zero.vfs_root_xp ) );
     953
     954        // update local process_zero descriptor
     955        process_zero.vfs_root_xp = vfs_root_inode_xp;
     956        process_zero.vfs_cwd_xp  = vfs_root_inode_xp;
     957    }
     958
     959    /////////////////////////////////////////////////////////////////////////////////
     960    // global &local synchro to protect File System initialisation
     961    if( core_lid == 0 ) remote_barrier( XPTR( io_cxy , &global_barrier ),
     962                                        (info->x_size * info->y_size) );
     963    barrier_wait( &local_barrier , info->cores_nr );
     964
     965    if( (core_lid ==  0) && (local_cxy == 0) )
     966    kinit_dmsg("\n[INFO] %s exit barrier 5 at cycle %d : VFS OK in all clusters\n",
     967               __FUNCTION__, (uint32_t)hal_time_stamp());
     968
     969
     970    /////////////////////////////////////////////////////////////////////////////////
     971    // STEP 6 : CP0 in cluster IO makes the global DEVFS tree initialisation:
     972    //          It creates the DEVFS root directory and the DEVFS "external"
     973    //          diretory in cluster IO and mount these inodes into VFS.
     974    /////////////////////////////////////////////////////////////////////////////////
     975
     976    if( (core_lid ==  0) && (local_cxy == io_cxy) )
     977    {
     978        xptr_t  devfs_root_inode_xp;       // extended pointer on DEVFS root directory
     979        xptr_t  devfs_external_inode_xp;   // extended pointer on DEVFS external directory   
     980
     981        // create "dev" and "external" directories.
     982        devfs_global_init( process_zero.vfs_root_xp,
     983                           &devfs_root_inode_xp,
     984                           &devfs_external_inode_xp );
     985
     986        // creates the DEVFS context in cluster IO
     987        devfs_ctx_t * devfs_ctx = devfs_ctx_alloc();
     988
     989        nolock_assert( (devfs_ctx != NULL) , __FUNCTION__ ,
     990                       "cannot create DEVFS context in cluster IO\n");
     991
     992        // register DEVFS root and external directories
     993        devfs_ctx_init( devfs_ctx, devfs_root_inode_xp, devfs_external_inode_xp );
     994    }   
     995
     996    /////////////////////////////////////////////////////////////////////////////////
     997    // global &local synchro to protect File System initialisation
     998    if( core_lid == 0 ) remote_barrier( XPTR( io_cxy , &global_barrier ),
     999                                        (info->x_size * info->y_size) );
     1000    barrier_wait( &local_barrier , info->cores_nr );
     1001
     1002    if( (core_lid ==  0) && (local_cxy == 0) )
     1003    kinit_dmsg("\n[INFO] %s exit barrier 6 at cycle %d : DEVFS OK in cluster IO\n",
     1004               __FUNCTION__, (uint32_t)hal_time_stamp());
     1005
     1006    /////////////////////////////////////////////////////////////////////////////////
     1007    // STEP 7 : All CP0s complete in parallel the DEVFS tree initialization.
     1008    //          Each CP0 get the "dev" and "external" extended pointers from
     1009    //          values storred in cluster IO. Then CP0 in cluster(i) creates the
     1010    //          DEVFS "internal directory, and creates the pseudo-files for all
     1011    //          chdevs contained in cluster (i).
     1012    /////////////////////////////////////////////////////////////////////////////////
     1013
     1014    if( core_lid == 0 )
     1015    {
     1016        xptr_t  root_inode_xp;       // extended pointer on DEVFS root directory
     1017        xptr_t  external_inode_xp;   // extended pointer on DEVFS external directory   
     1018
     1019        // get extended pointer on "extend" field of VFS context for DEVFS in cluster IO
     1020        xptr_t  extend_xp = XPTR( io_cxy , &fs_context[FS_TYPE_DEVFS].extend );
     1021
     1022        // get pointer on DEVFS context in cluster IO
     1023        devfs_ctx_t * devfs_ctx = hal_remote_lpt( extend_xp );
     1024       
     1025        root_inode_xp     = hal_remote_lwd( XPTR( io_cxy , &devfs_ctx->root_inode_xp ) );
     1026        external_inode_xp = hal_remote_lwd( XPTR( io_cxy , &devfs_ctx->external_inode_xp ) );
     1027
     1028        devfs_local_init( root_inode_xp,
     1029                          external_inode_xp );
     1030    }
     1031
     1032    /////////////////////////////////////////////////////////////////////////////////
     1033    // global &local synchro to protect File System initialisation
     1034    if( core_lid == 0 ) remote_barrier( XPTR( io_cxy , &global_barrier ),
     1035                                        (info->x_size * info->y_size) );
     1036    barrier_wait( &local_barrier , info->cores_nr );
     1037
     1038    if( (core_lid ==  0) && (local_cxy == 0) )
     1039    kinit_dmsg("\n[INFO] %s exit barrier 7 at cycle %d : DEVFS OK in all clusters\n",
     1040               __FUNCTION__, (uint32_t)hal_time_stamp());
     1041
     1042    /////////////////////////////////////////////////////////////////////////////////
     1043    // STEP 8 : CP0 in I/O cluster creates the process_init and print banner.
     1044    /////////////////////////////////////////////////////////////////////////////////
     1045
     1046    if( (core_lid ==  0) && (local_cxy == io_cxy) )
    8401047    {
    8411048        process_init_create();
    842 
     1049    }
     1050
     1051    /////////////////////////////////////////////////////////////////////////////////
     1052    // global syncho to protect access to File System
     1053    if( core_lid == 0 ) remote_barrier( XPTR( info->io_cxy , &global_barrier ),
     1054                                        (info->x_size * info->y_size) );
     1055    barrier_wait( &local_barrier , info->cores_nr );
     1056
     1057    if( (core_lid ==  0) && (local_cxy == 0) )
     1058    kinit_dmsg("\n[INFO] %s exit barrier 8 at cycle %d : process init created\n",
     1059               __FUNCTION__ , (uint32_t)hal_time_stamp() );
     1060
     1061    /////////////////////////////////////////////////////////////////////////////////
     1062    // STEP 9 : CP0 in cluster 0 print banner
     1063    /////////////////////////////////////////////////////////////////////////////////
     1064   
     1065    if( (core_lid ==  0) && (local_cxy == io_cxy) )
     1066    {
    8431067        print_banner( (info->x_size * info->y_size) , info->cores_nr );
    8441068
     
    8861110    }
    8871111
    888     /////////////////////////////////////////////////////////////////////////////////
    889     // global syncho to protect access to File System
    890     if( core_lid == 0 ) remote_barrier( XPTR( info->io_cxy , &global_barrier ),
    891                                         (info->x_size * info->y_size) );
    892     barrier_wait( &local_barrier , info->cores_nr );
    893     /////////////////////////////////////////////////////////////////////////////////
    894 
    895     if( (core_lid ==  0) && (local_cxy == info->io_cxy) )
    896     {
    897         kinit_dmsg("\n[INFO] %s : core[%x][%d] exit barrier 3 at cycle %d\n",
    898                    __FUNCTION__ , core_cxy , core_lid , hal_get_cycles() );
    899     }
    900 
    9011112    // each core activates its private PTI IRQ
    902     dev_icu_set_period( core_lid , CONFIG_SCHED_TICK_PERIOD );
    903     dev_icu_enable_irq( core_lid , PTI_TYPE , core_lid , NULL );
    904 
    905     // each core get its private IRQ masks values
    906     uint32_t hwi_mask;
    907     uint32_t wti_mask;
    908     uint32_t pti_mask;
    909     dev_icu_get_masks( core_lid , &hwi_mask , &wti_mask , &pti_mask );
    910 
    911     thread_dmsg("\n[INFO] %s : core[%x][%d] complete kernel init at cycle %d\n"
    912                 "   hwi_mask = %x / wti_mask = %x / pti_mask = %x\n",
    913                     __FUNCTION__ , local_cxy , core_lid , hal_get_cycles() ,
    914                     hwi_mask , wti_mask , pti_mask );
     1113    dev_pic_enable_timer( CONFIG_SCHED_TICK_PERIOD );
     1114
     1115    if( (core_lid ==  0) && (local_cxy == io_cxy) )
     1116    thread_dmsg("\n[INFO] %s complete kernel init in cluster 0 at cycle %d\n"
     1117                __FUNCTION__ , (uint32_t)hal_time_stamp() )
    9151118
    9161119    // each core jump to idle thread
  • trunk/kernel/kern/printk.c

    r103 r188  
    3535///////////////////////////////////////////////////////////////////////////////////
    3636
    37 extern chdev_t            txt0_chdev;        // allocated in kernel_init.c
     37extern chdev_directory_t  chdev_dir;  // defined in chdev.h / allocated in kernel_init.c
    3838
    3939/////////////////////////////////////
     
    369369    uint32_t      save_sr;
    370370
     371    // get pointers on TXT0 chdev
     372    xptr_t    txt0_xp  = chdev_dir.txt[0];
     373    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
     374    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
     375
    371376    // get extended pointer on remote TXT0 chdev lock
    372     xptr_t  txt0_lock_xp = XPTR( LOCAL_CLUSTER->io_cxy , &txt0_chdev.wait_lock );
     377    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
    373378
    374379    // get TXT0 lock in busy waiting mode
    375     remote_spinlock_lock_busy( txt0_lock_xp , &save_sr );
     380    remote_spinlock_lock_busy( lock_xp , &save_sr );
    376381
    377382    // call kernel_printf on TXT0, in busy waiting mode
     
    381386
    382387    // release lock
    383     remote_spinlock_unlock_busy( txt0_lock_xp , save_sr );
     388    remote_spinlock_unlock_busy( lock_xp , save_sr );
    384389}
    385390
     
    406411    }
    407412}
     413
     414//////////////////////////////////////////////////
     415inline void nolock_assert( bool_t       condition,
     416                           const char * function_name,
     417                           char       * string )
     418{
     419    if( condition == false )
     420    {
     421        nolock_printk("\n[PANIC] in %s : %s\n" , function_name , string );
     422        hal_core_sleep();
     423    }
     424}
     425
    408426
    409427
  • trunk/kernel/kern/printk.h

    r103 r188  
    8383
    8484/**********************************************************************************
    85  * This function displaya "PANIC" message and force the calling core in
     85 * This function displays a "PANIC" message and force the calling core in
    8686 * sleeping mode if a Boolean condition is false.
    8787 * These functions are actually used to debug the kernel...
     
    9595                    char       * string );
    9696
     97/**********************************************************************************
     98 * This function displays a "PANIC" message and force the calling core in
     99 * sleeping mode if a Boolean condition is false,
     100 * without taking the the lock protecting exclusive access to TXT0 terminal.
     101 **********************************************************************************
     102 * @ condition     : condition that must be true.
     103 * @ function_name : name of the calling function.
     104 * @ string        : error message if condition is false.
     105 *********************************************************************************/
     106inline void nolock_assert( bool_t       condition,
     107                           const char * function_name,
     108                           char       * string );
     109
    97110///////////////////////////////////////////////////////////////////////////////////
    98111//       Conditionnal debug macros
     
    171184#endif
    172185
    173 #if CONFIG_ICU_DEBUG
    174 #define icu_dmsg(...)   printk(__VA_ARGS__)
    175 #else
    176 #define icu_dmsg(...)
    177 #endif
    178 
    179186#if CONFIG_IDLE_DEBUG
    180187#define idle_dmsg(...) printk(__VA_ARGS__)
     
    187194#else
    188195#define ioc_dmsg(...)
     196#endif
     197
     198#if CONFIG_IRQ_DEBUG
     199#define irq_dmsg(...)   printk(__VA_ARGS__)
     200#else
     201#define irq_dmsg(...)
    189202#endif
    190203
  • trunk/kernel/kern/process.c

    r186 r188  
    9999        assert( (pid == 0) , __FUNCTION__ , "process_zero must have PID = 0\n");
    100100
    101         parent_pid = 0;  // process_zero is its own parent...
     101        parent_cxy = 0;
     102        parent_ptr = NULL;
     103        parent_pid = 0;      // process_zero is its own parent...
    102104    }
    103105    else
  • trunk/kernel/kern/rpc.c

    r101 r188  
    537537                                  uint32_t       fs_type,    // in
    538538                                  uint32_t       inode_type, // in
     539                                  void         * extend,     // in
    539540                                  uint32_t       attr,       // in
    540541                                  uint32_t       rights,     // in
     
    560561    rpc.args[1] = (uint64_t)fs_type;
    561562    rpc.args[2] = (uint64_t)inode_type;
    562     rpc.args[3] = (uint64_t)attr;
    563     rpc.args[4] = (uint64_t)rights;
    564     rpc.args[5] = (uint64_t)uid;
    565     rpc.args[6] = (uint64_t)gid;
     563    rpc.args[3] = (uint64_t)(intptr_t)extend;
     564    rpc.args[4] = (uint64_t)attr;
     565    rpc.args[5] = (uint64_t)rights;
     566    rpc.args[6] = (uint64_t)uid;
     567    rpc.args[7] = (uint64_t)gid;
    566568
    567569    // register RPC request in remote RPC fifo (blocking function)
     
    569571
    570572    // get output values from RPC descriptor
    571     *inode_xp = (xptr_t)rpc.args[7];
    572     *error    = (error_t)rpc.args[8];
     573    *inode_xp = (xptr_t)rpc.args[8];
     574    *error    = (error_t)rpc.args[9];
    573575}
    574576
     
    579581    uint32_t         fs_type;
    580582    uint32_t         inode_type;
     583    void           * extend;
    581584    uint32_t         attr;
    582585    uint32_t         rights;
     
    591594
    592595    // get input arguments from client rpc descriptor
    593     dentry_xp  = (xptr_t)  hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
    594     fs_type    = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
    595     inode_type = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) );
    596     attr       = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[3] ) );
    597     rights     = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[4] ) );
    598     uid        = (uid_t)   hal_remote_lwd( XPTR( client_cxy , &desc->args[5] ) );
    599     gid        = (gid_t)   hal_remote_lwd( XPTR( client_cxy , &desc->args[6] ) );
     596    dentry_xp  = (xptr_t)          hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
     597    fs_type    = (uint32_t)        hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
     598    inode_type = (uint32_t)        hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) );
     599    extend     = (void *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[3] ) );
     600    attr       = (uint32_t)        hal_remote_lwd( XPTR( client_cxy , &desc->args[4] ) );
     601    rights     = (uint32_t)        hal_remote_lwd( XPTR( client_cxy , &desc->args[5] ) );
     602    uid        = (uid_t)           hal_remote_lwd( XPTR( client_cxy , &desc->args[6] ) );
     603    gid        = (gid_t)           hal_remote_lwd( XPTR( client_cxy , &desc->args[7] ) );
    600604
    601605    // call local kernel function
     
    603607                              fs_type,
    604608                              inode_type,
     609                              extend,
    605610                              attr,
    606611                              rights,
     
    610615
    611616    // set output arguments
    612     hal_remote_swd( XPTR( client_cxy , &desc->args[7] ) , (uint64_t)inode_xp );
    613     hal_remote_swd( XPTR( client_cxy , &desc->args[8] ) , (uint64_t)error );
     617    hal_remote_swd( XPTR( client_cxy , &desc->args[8] ) , (uint64_t)inode_xp );
     618    hal_remote_swd( XPTR( client_cxy , &desc->args[9] ) , (uint64_t)error );
    614619}
    615620
     
    12901295                if( cores == 0 ) // no core in kernel mode in server
    12911296                {
    1292                     dev_icu_send_ipi( server_cxy , client_lid );
     1297                    dev_pic_send_ipi( server_cxy , client_lid );
    12931298
    12941299                    rpc_dmsg("\n[INFO] %s : core %d in cluster %x send IPI to core %d in cluster %x\n",
     
    14541459
    14551460        // update core descriptor counter 
    1456             core->rpc_threads++;
     1461            hal_atomic_add( &core->rpc_threads , 1 );
    14571462    }
    14581463
     
    15491554
    15501555            // update core descriptor counter
    1551                         this->core->rpc_threads--;
     1556                hal_atomic_add( &this->core->rpc_threads , -1 );
    15521557
    15531558            // suicide
  • trunk/kernel/kern/rpc.h

    r23 r188  
    325325 * @ fs_type    : [in]  file system type.
    326326 * @ inode_type : [in]  file system type.
     327 * @ extend     : [in]  fs_type_specific inode extension.
    327328 * @ attr       : [in]  inode attributes.
    328329 * @ rights     : [in]  access rights
     
    336337                                  uint32_t   fs_type,
    337338                                  uint32_t   inode_type,
     339                                  void     * extend,
    338340                                  uint32_t   attr,   
    339341                                  uint32_t   rights, 
  • trunk/kernel/kern/thread.c

    r185 r188  
    3434#include <process.h>
    3535#include <scheduler.h>
    36 #include <dev_icu.h>
     36#include <dev_pic.h>
    3737#include <core.h>
    3838#include <list.h>
     
    718718    thread_block( target , THREAD_BLOCKED_GLOBAL );
    719719
    720     // send an IPI to reschedule the target thread core.
    721     dev_icu_send_ipi( local_cxy , target->core->lid );
     720    // send an IPI to schedule the target thread core.
     721    dev_pic_send_ipi( local_cxy , target->core->lid );
    722722}
    723723
     
    739739        idle_dmsg("\n[INFO] %s : core[%x][%d] wake up at cycle %d\n",
    740740                    __FUNCTION__ , local_cxy , lid , hal_get_cycles() );
    741 
    742                 // acknowledge IRQ
    743         dev_icu_irq_handler();
    744741
    745742        // force scheduling
  • trunk/kernel/libk/xhtab.c

    r50 r188  
    3535
    3636///////////////////////////////////////////////////////////////////////////////////////////
    37 // Item type specific (static) functions (two functions for each item type).
    38 // - for type <vfs_dentry_t>, identifier is the name field.
    39 ///////////////////////////////////////////////////////////////////////////////////////////
    40 
    41 ///////////////////////////////////////////////////////////////////////////////////////////
    42 // These static functions compute the hash index from the key.
    43 ///////////////////////////////////////////////////////////////////////////////////////////
    44 // @ key      : local pointer on key.
     37// Item type specific functions (three functions for each item type).
     38///////////////////////////////////////////////////////////////////////////////////////////
     39
     40///////////////////////////////////////////////////////////////////////////////////////////
     41// This functions compute the hash index from the key when item is a vfs_dentry_t.
     42// The key is the directory entry name.
     43///////////////////////////////////////////////////////////////////////////////////////////
     44// @ key      : local pointer on name.
    4545// @ return the index value, from 0 to (HASHTAB_SIZE - 1)
    4646///////////////////////////////////////////////////////////////////////////////////////////
    47 
    48 /////////////////////////////////////////
    49 uint32_t xhtab_dentry_index( void * key )
     47static uint32_t xhtab_dentry_index_from_key( void * key )
    5048{
    5149        char     * name  = key;
     
    5553        index = index + (*(name++) ^ index);
    5654    }
    57         return index % HASHTAB_SIZE;
     55        return index % XHASHTAB_SIZE;
    5856}
    5957
     58///////////////////////////////////////////////////////////////////////////////////////////
     59// This functions returns the extended pointer on the item, from the extended pointer
     60// on xlist contained in the item, when the item is a vfs_entry_t.
     61///////////////////////////////////////////////////////////////////////////////////////////
     62// @ xlist_xp      : extended pointer on embedded xlist entry.
     63// @ return the extended pointer on the dentry containing this xlist entry.
     64///////////////////////////////////////////////////////////////////////////////////////////
     65static xptr_t xhtab_dentry_item_from_xlist( xptr_t xlist_xp )
     66{
     67    return XLIST_ELEMENT( xlist_xp , vfs_dentry_t , list );
     68}
     69
    6070////////////////////////////////////////////////////////////////////////////////////////////
    61 // These static function are used by xhtab_lookup(), xhtab_insert(), xhtab_remove().
    62 // They scan one sub-list identified by  <index> to find an item  identified by <key>.
    63 // The sub-list is not modified, but the readlock must have been taken by the caller.
     71// This function compare the identifier of an item to a given <key>. For a vfs_entry_t,
     72// it returns true when the directory name matches the name pointed by the <key> argument.
    6473////////////////////////////////////////////////////////////////////////////////////////////
    65 // @ xhtab_xp  : extended pointer on hash table.
    66 // @ index     : index of sub-list to be scanned.
    67 // @ key       : local pointer on item identifier.
    68 // return an extended pointer on item if found / return XPTR_NULL if not found.
     74// @ item_xp   : extended pointer on item.
     75// @ key       : pointer on searched item identifier.
     76// returns true if given name matches directory entry name.
    6977////////////////////////////////////////////////////////////////////////////////////////////
    70 
    71 ////////////////////////////////////////////////////
    72 static xptr_t xhtab_dentry_scan( xptr_t    xhtab_xp,
    73                                  uint32_t  index,
    74                                  void    * key )
     78static bool_t xhtab_dentry_item_match_key( xptr_t item_xp,
     79                                           void    * key )
     80{
     81    vfs_dentry_t * dentry_ptr;
     82    cxy_t          dentry_cxy;
     83
     84    char           name[CONFIG_VFS_MAX_NAME_LENGTH];
     85
     86    // get dentry cluster and local pointer
     87    dentry_cxy = GET_CXY( item_xp );
     88    dentry_ptr = (vfs_dentry_t *)GET_PTR( item_xp );
     89
     90    // make a local copy of directory entry name
     91    hal_remote_strcpy( XPTR( local_cxy , name ) ,
     92                       XPTR( dentry_cxy , &dentry_ptr->name ) );
     93
     94    return( strcmp( name , (char*)key ) == 0 );
     95}
     96                       
     97////////////////////////////////////////////////////////////////////////////////////////
     98//         Generic access functions
     99////////////////////////////////////////////////////////////////////////////////////////
     100
     101//////////////////////////////////////////
     102void xhtab_init( xhtab_t          * xhtab,
     103                 xhtab_item_type_t  type )
     104{
     105        uint32_t i;
     106
     107    // initialize readlock
     108    remote_rwlock_init( XPTR( local_cxy , &xhtab->lock) );
     109
     110    xhtab->items  = 0;
     111
     112    if( type == XHTAB_DENTRY_TYPE )
     113    {
     114        xhtab->item_match_key  = &xhtab_dentry_item_match_key;
     115        xhtab->index_from_key  = &xhtab_dentry_index_from_key;
     116        xhtab->item_from_xlist = &xhtab_dentry_item_from_xlist;
     117    }
     118    else
     119    {
     120        printk("\n[PANIC] in %s : illegal item type\n", __FUNCTION__ );
     121        hal_core_sleep();
     122    }
     123
     124        for( i=0 ; i < XHASHTAB_SIZE ; i++ )
     125    {
     126                xlist_root_init( XPTR( local_cxy , &xhtab->roots[i] ) );
     127    } 
     128
     129}  // end xhtab_init()
     130
     131//////////////////////////////////////
     132xptr_t xhtab_scan( xptr_t    xhtab_xp,
     133                   uint32_t  index,
     134                   void    * key )
    75135{
    76136    xptr_t    xlist_xp;                                 // xlist_entry_t (iterator)
     137    xptr_t    item_xp;                                  // associated item
    77138    xhtab_t * xhtab_ptr;                                // hash table local pointer
    78139    cxy_t     xhtab_cxy;                                // hash table cluster
    79     char      local_name[CONFIG_VFS_MAX_NAME_LENGTH];   // local copy of dentry name
    80140
    81141    // get hash table cluster and local pointer
     
    86146    XLIST_FOREACH( XPTR( xhtab_cxy , &xhtab_ptr->roots[index] ) , xlist_xp )
    87147    {
    88         // get extended pointer on dentry containing the xlist_entry_t
    89             xptr_t dentry_xp = XLIST_ELEMENT( xlist_xp , vfs_dentry_t , xlist );
    90 
    91         // get dentry cluster and local pointer
    92         cxy_t          dentry_cxy = GET_CXY( dentry_xp );
    93         vfs_dentry_t * dentry_ptr = (vfs_dentry_t *)GET_PTR( dentry_xp );
    94    
    95         // make a local copy of dentry name
    96         hal_remote_memcpy( XPTR( local_cxy  , local_name ) ,
    97                            XPTR( dentry_cxy , dentry_ptr->name ),
    98                            CONFIG_VFS_MAX_NAME_LENGTH  );
    99 
    100         // check matching
    101         if( strcmp( local_name , (char *)key ) == 0 ) return dentry_xp;
     148        // get extended pointer on item containing the xlist entry
     149            item_xp = xhtab_ptr->item_from_xlist( xlist_xp );
     150
     151        // check matching
     152        if( xhtab_ptr->item_match_key( item_xp , key ) ) return item_xp;
    102153    }
    103154
    104155    // No matching item found
    105156    return XPTR_NULL;
    106 }
    107 
    108 ////////////////////////////////////////////////////////////////////////////////////////
    109 //         Generic access functions
    110 ////////////////////////////////////////////////////////////////////////////////////////
    111 
    112 //////////////////////////////////////////
    113 void xhtab_init( xhtab_t          * xhtab,
    114                  xhtab_item_type_t  type )
    115 {
    116         uint32_t i;
    117 
    118     // initialize readlock
    119     remote_rwlock_init( XPTR( local_cxy , &xhtab->lock) );
    120 
    121     xhtab->items  = 0;
    122 
    123     if( type == XHTAB_DENTRY_TYPE )
    124     {
    125         xhtab->scan  = &xhtab_dentry_scan;
    126         xhtab->index = &xhtab_dentry_index;
    127     }
    128     else
    129     {
    130         printk("\n[PANIC] in %s : illegal item type\n", __FUNCTION__ );
    131         hal_core_sleep();
    132     }
    133 
    134         for( i=0 ; i < HASHTAB_SIZE ; i++ )
    135     {
    136                 xlist_root_init( XPTR( local_cxy , &xhtab->roots[i] ) );
    137     } 
    138157}
    139158
     
    148167
    149168    // compute index from key
    150         uint32_t index = xhtab_ptr->index( key );
     169        uint32_t index = xhtab_ptr->index_from_key( key );
    151170
    152171    // take the lock protecting hash table
     
    154173
    155174    // search a matching item
    156     xptr_t item_xp = xhtab_ptr->scan( xhtab_xp , index , key );
     175    xptr_t item_xp = xhtab_scan( xhtab_xp , index , key );
    157176
    158177    if( item_xp != XPTR_NULL )    // error if found
     
    188207
    189208    // compute index from key
    190         uint32_t index = xhtab_ptr->index( key );
     209        uint32_t index = xhtab_ptr->index_from_key( key );
    191210
    192211    // take the lock protecting hash table
     
    194213
    195214    // get extended pointer on item to remove
    196     xptr_t item_xp = xhtab_ptr->scan( xhtab_xp , index , key );
     215    xptr_t item_xp = xhtab_scan( xhtab_xp , index , key );
    197216
    198217    if( item_xp == XPTR_NULL )    // error if not found
     
    229248
    230249    // compute index from key
    231         uint32_t index = xhtab_ptr->index( key );
     250        uint32_t index = xhtab_ptr->index_from_key( key );
    232251
    233252    // take the lock protecting hash table
     
    235254
    236255    // scan sub-list
    237     item_xp = xhtab_ptr->scan( xhtab_xp , index , key );
     256    item_xp = xhtab_scan( xhtab_xp , index , key );
    238257
    239258    // release the lock protecting hash table
     
    244263}  // end xhtab_lookup()
    245264
    246 
     265///////////////////////////////////////
     266void xhtab_read_lock( xptr_t xhtab_xp )
     267{
     268    // get xhtab cluster and local pointer
     269    cxy_t     xhtab_cxy = GET_CXY( xhtab_xp );
     270    xhtab_t * xhtab_ptr = (xhtab_t *)GET_PTR( xhtab_xp );
     271
     272    // take the lock protecting hash table
     273    remote_rwlock_rd_lock( XPTR( xhtab_cxy , &xhtab_ptr->lock ) );
     274}
     275
     276/////////////////////////////////////////
     277void xhtab_read_unlock( xptr_t xhtab_xp )
     278{
     279    // get xhtab cluster and local pointer
     280    cxy_t     xhtab_cxy = GET_CXY( xhtab_xp );
     281    xhtab_t * xhtab_ptr = (xhtab_t *)GET_PTR( xhtab_xp );
     282
     283    // release the lock protecting hash table
     284    remote_rwlock_rd_unlock( XPTR( xhtab_cxy , &xhtab_ptr->lock ) );
     285}
     286
     287/////////////////////////////////////////
     288xptr_t xhtab_get_first( xptr_t xhtab_xp )
     289{
     290    uint32_t index;
     291    xptr_t   xlist_xp;
     292    xptr_t   item_xp;
     293    xptr_t   root_xp;
     294
     295    // get xhtab cluster and local pointer
     296    cxy_t     xhtab_cxy = GET_CXY( xhtab_xp );
     297    xhtab_t * xhtab_ptr = (xhtab_t *)GET_PTR( xhtab_xp );
     298
     299    //loop on subsets
     300    for( index = 0 ; index < XHASHTAB_SIZE ; index++ )
     301    {
     302        // get root of subset
     303        root_xp = XPTR( xhtab_cxy , &xhtab_ptr->roots[index] );
     304
     305        // get first item
     306        xlist_xp = xlist_next( root_xp , root_xp );
     307
     308        if( xlist_xp != XPTR_NULL )  // first item found
     309        {
     310            // get extended pointer on item containing the xlist entry
     311                item_xp = xhtab_ptr->item_from_xlist( xlist_xp );
     312
     313            // register item in hash table header
     314            hal_remote_sw ( XPTR( xhtab_cxy , &xhtab_ptr->current_index ) , index );
     315            hal_remote_swd( XPTR( xhtab_cxy , &xhtab_ptr->current_xlist_xp ) , xlist_xp );
     316
     317            return item_xp;
     318        }
     319    }
     320           
     321    // item not found
     322    return XPTR_NULL;
     323
     324} // end xhtab_get_first()
     325   
     326////////////////////////////////////////
     327xptr_t xhtab_get_next( xptr_t xhtab_xp )
     328{
     329    uint32_t index;
     330    xptr_t   xlist_xp;
     331    xptr_t   item_xp;
     332    xptr_t   root_xp;
     333
     334    uint32_t current_index;
     335    xptr_t   current_xlist_xp;
     336
     337    // get xhtab cluster and local pointer
     338    cxy_t     xhtab_cxy = GET_CXY( xhtab_xp );
     339    xhtab_t * xhtab_ptr = (xhtab_t *)GET_PTR( xhtab_xp );
     340
     341    // get current item pointers
     342    current_index    = hal_remote_lw ( XPTR( xhtab_cxy , &xhtab_ptr->current_index ) );
     343    current_xlist_xp = hal_remote_lwd( XPTR( xhtab_cxy , &xhtab_ptr->current_xlist_xp ) );
     344
     345    //loop on subsets
     346    for( index = current_index ; index < XHASHTAB_SIZE ; index++ )
     347    {
     348        // get root of subset
     349        root_xp = XPTR( xhtab_cxy , &xhtab_ptr->roots[index] );
     350
     351        // get next item
     352        xlist_xp = xlist_next( root_xp , current_xlist_xp );
     353
     354        if( xlist_xp != XPTR_NULL )  // next item found
     355        {
     356            // get extended pointer on item containing the xlist entry
     357                item_xp = xhtab_ptr->item_from_xlist( xlist_xp );
     358
     359            // register item in hash table header
     360            hal_remote_sw ( XPTR( xhtab_cxy , &xhtab_ptr->current_index ) , index );
     361            hal_remote_swd( XPTR( xhtab_cxy , &xhtab_ptr->current_xlist_xp ) , xlist_xp );
     362
     363            return item_xp;
     364        }
     365    }
     366           
     367    // item not found
     368    return XPTR_NULL;
     369
     370} // end xhtab_get_next()
     371
     372
  • trunk/kernel/libk/xhtab.h

    r23 r188  
    3838// The main goal is to speedup search by key for a large number of items of same type.
    3939// For this purpose the set of all registered items is split in several subsets.
    40 // Each subset is organised an embedded double linked lists.
    41 // - an item is uniquely identified by a <key>, that can be a single uint32_t,
    42 //   a name (character string), or a more complex structure.
    43 // - From the pointer on <key>, we use an item type specific xhtab_index() function,
     40// Each subset is organised as an embedded double linked lists.
     41// - an item is uniquely identified by a <key>, that is a single uint32_t value.
     42// - From the <key> value,the hash table uses an item type specific xhtab_index() function,
    4443//   to compute an <index> value, defining a subset of registered items.
    45 // - to discriminate between items that have the same <index>, the hash table uses another
    46 //   item type specific "xhtab_scan()" function for the associative search in subset.
     44// - to discriminate between items that have the same <index>, the hash table makes
     45//   an associative search in subset.
    4746// - Each registered item is a structure, that must contain an embedded xlist_entry,
    4847//   that is part of the xlist implementing the subset.
    4948//
    50 // Implementation Note: for each supported item type ***, you must define the two
    51 //                      xhtab_***_index() and xhtab_***_scan() functions, and
    52 //                      update the xhtab_init() function.
     49// A total order is defined for all registered items by the increasing index values,
     50// and for each index value by the position in the partial xlist.
     51// This order is used by the two functions xhtab_get_first() and xhtab_get_next(), that
     52// are used to scan all registered items. The two "current_index" and "current_xlist_xp"
     53// fields in the hash table header register the current item during a scan.
     54//
     55// Implementation Note:
     56// For each supported item type ***, you must define the three item-type-specific
     57// functions specified below, and you must update the xhtab_init() function
     58// and the xhtab_item_type_t.
    5359///////////////////////////////////////////////////////////////////////////////////////////
    5460
    55 #define HASHTAB_SIZE    64   // number of subsets
     61#define XHASHTAB_SIZE    64   // number of subsets
    5662
    5763/******************************************************************************************
    58  * These typedef define the two item type specific function prototypes.
     64 * This define the three item type specific function prototypes.
    5965 *****************************************************************************************/
    6066
    61 typedef  xptr_t    xhtab_scan_t( xptr_t xhtab_xp , uint32_t index , void * key );
    62 
    63 typedef  uint32_t  xhtab_index_t( void * key );
     67typedef  bool_t    xhtab_match_t ( xptr_t item_xp , void * key );
     68typedef  xptr_t    xhtab_item_t  ( xptr_t xlist_xp );
     69typedef  uint32_t  xhtab_index_t ( void * key );
    6470
    6571/******************************************************************************************
     
    7985typedef struct xhtab_s
    8086{
    81         xlist_entry_t      roots[HASHTAB_SIZE];   /*! array of roots of xlist                */
    82     xhtab_index_t    * index;                 /*! item specific function                 */
    83     xhtab_scan_t     * scan;                  /*! item specific function                 */
     87        xlist_entry_t      roots[XHASHTAB_SIZE];  /*! array of roots of xlist                */
     88    xhtab_index_t    * index_from_key;        /*! item specific function                 */
     89    xhtab_match_t    * item_match_key;        /*! item specific function                 */
     90    xhtab_item_t     * item_from_xlist;       /*! item specific function                 */
    8491    uint32_t           items;                 /*! number of registered items             */
    8592    remote_rwlock_t    lock;                  /*! lock protecting hash table accesses    */
     93    uint32_t           current_index;         /*! current item subset index              */
     94    xptr_t           * current_xlist_xp;      /*! xptr on current item xlist entry       */
    8695}
    8796xhtab_t;
     
    131140                      void    * key );
    132141
     142/******************************************************************************************
     143 * This blocking function takes the lock protecting exclusive access to the hash table.
     144 * It should be called before the xhtab_get_first() & xhtab_get_next() functions.
     145 ******************************************************************************************
     146 * @ xhtab_xp  : extended pointer on hash table.
     147 *****************************************************************************************/
     148void xhtab_read_lock( xptr_t xhtab_xp );
     149
     150/******************************************************************************************
     151 * This function releases the lock protecting exclusive access to the hash table.
     152 * It should be called after the xhtab_get_first() & xhtab_get_next() functions.
     153 ******************************************************************************************
     154 * @ xhtab_xp  : extended pointer on hash table.
     155 *****************************************************************************************/
     156void xhtab_read_unlock( xptr_t xhtab_xp );
     157
     158/******************************************************************************************
     159 * This function returns an extended pointer on the first item registered in hash table,
     160 * and register this pointer in the hash table header.
     161 * The lock protecting the hash table must have been previously taken by the caller.
     162 ******************************************************************************************
     163 * @ xhtab_xp  : extended pointer on hash table.
     164 * @ return extended pointer on item if success / XPTR_NULL if not found.
     165 *****************************************************************************************/
     166xptr_t xhtab_get_first( xptr_t xhtab_xp );
     167
     168/******************************************************************************************
     169 * This function returns an extended pointer on item following the currently pointed
     170 * item in the hash table header.
     171 * The lock protecting the hash table must have been previously taken by the caller.
     172 ******************************************************************************************
     173 * @ xhtab_xp  : extended pointer on hash table.
     174 * @ return extended pointer on item if success / XPTR_NULL if not found.
     175 *****************************************************************************************/
     176xptr_t xhtab_get_next( xptr_t xhtab_xp );
     177
     178
    133179
    134180#endif  /* _XHTAB_H_ */
  • trunk/kernel/mm/kcm.h

    r161 r188  
    9898
    9999/****************************************************************************************
    100  * This function allocates one single object in a Kernel Cache Manager
     100 * This function allocates one single object from a Kernel Cache Manager
    101101 * The object size must be smaller than one page size.
    102102 ****************************************************************************************
  • trunk/kernel/mm/kmem.c

    r181 r188  
    8282uint32_t  kmem_type_size( uint32_t type )
    8383{
    84         if     ( type == KMEM_PAGE )          return CONFIG_PPM_PAGE_SIZE;
    85         else if( type == KMEM_GENERIC )       return 0;
    86         else if( type == KMEM_KCM )           return sizeof( kcm_t );
    87         else if( type == KMEM_VSEG )          return sizeof( vseg_t );
    88         else if( type == KMEM_DEVICE )        return sizeof( chdev_t );
    89         else if( type == KMEM_MAPPER )        return sizeof( mapper_t );
    90         else if( type == KMEM_PROCESS )       return sizeof( process_t );
    91         else if( type == KMEM_CPU_CTX )       return sizeof( hal_cpu_context_t );
    92         else if( type == KMEM_FPU_CTX )       return sizeof( hal_fpu_context_t );
    93         else if( type == KMEM_BARRIER )       return sizeof( remote_barrier_t );
    94 
    95         else if( type == KMEM_FATFS_INODE )   return sizeof( fatfs_inode_t );
    96         else if( type == KMEM_FATFS_CTX )     return sizeof( fatfs_ctx_t );
    97         else if( type == KMEM_DEVFS_INODE )   return sizeof( devfs_inode_t );
    98         else if( type == KMEM_MUTEX )         return sizeof( remote_mutex_t );
    99         else if( type == KMEM_VFS_CTX )       return sizeof( vfs_ctx_t );
    100         else if( type == KMEM_VFS_INODE )     return sizeof( vfs_inode_t );
    101         else if( type == KMEM_VFS_DENTRY )    return sizeof( vfs_dentry_t );
    102         else if( type == KMEM_VFS_FILE )      return sizeof( vfs_file_t );
    103         else if( type == KMEM_SEM )           return sizeof( remote_sem_t );
    104         else if( type == KMEM_CONDVAR )       return sizeof( remote_condvar_t );
    105 
     84    if     ( type == KMEM_PAGE )          return CONFIG_PPM_PAGE_SIZE;
     85    else if( type == KMEM_GENERIC )       return 0;
     86    else if( type == KMEM_KCM )           return sizeof( kcm_t );
     87    else if( type == KMEM_VSEG )          return sizeof( vseg_t );
     88    else if( type == KMEM_DEVICE )        return sizeof( chdev_t );
     89    else if( type == KMEM_MAPPER )        return sizeof( mapper_t );
     90    else if( type == KMEM_PROCESS )       return sizeof( process_t );
     91    else if( type == KMEM_CPU_CTX )       return CONFIG_CPU_CTX_SIZE;
     92    else if( type == KMEM_FPU_CTX )       return CONFIG_FPU_CTX_SIZE;
     93    else if( type == KMEM_BARRIER )       return sizeof( remote_barrier_t );
     94
     95    else if( type == KMEM_DEVFS_CTX )     return sizeof( fatfs_ctx_t );
     96    else if( type == KMEM_FATFS_CTX )     return sizeof( fatfs_ctx_t );
     97    else if( type == KMEM_VFS_CTX )       return sizeof( vfs_ctx_t );
     98    else if( type == KMEM_VFS_INODE )     return sizeof( vfs_inode_t );
     99    else if( type == KMEM_VFS_DENTRY )    return sizeof( vfs_dentry_t );
     100    else if( type == KMEM_VFS_FILE )      return sizeof( vfs_file_t );
     101    else if( type == KMEM_SEM )           return sizeof( remote_sem_t );
     102    else if( type == KMEM_CONDVAR )       return sizeof( remote_condvar_t );
     103    else if( type == KMEM_MUTEX )         return sizeof( remote_mutex_t );
    106104        else if( type == KMEM_512_BYTES )     return 512;
    107105
     
    123121        else if( type == KMEM_BARRIER )       return "KMEM_BARRIER";
    124122
    125         else if( type == KMEM_FATFS_INODE )   return "KMEM_FATFS_INODE";
    126         else if( type == KMEM_FATFS_CTX )     return "KMEM_FATFS_CTX";
    127         else if( type == KMEM_DEVFS_INODE )   return "KMEM_DEVFS_INODE";
    128         else if( type == KMEM_MUTEX )         return "KMEM_MUTEX";
    129         else if( type == KMEM_VFS_CTX )       return "KMEM_VFS_CTX";
    130         else if( type == KMEM_VFS_INODE )     return "KMEM_VFS_INODE";
    131         else if( type == KMEM_VFS_DENTRY )    return "KMEM_VFS_DENTRY";
    132         else if( type == KMEM_VFS_FILE )      return "KMEM_VFS_FILE";
    133         else if( type == KMEM_SEM )           return "KMEM_SEM";
    134         else if( type == KMEM_SEM )           return "KMEM_CONDVAR";
    135 
     123    else if( type == KMEM_DEVFS_CTX )     return "KMEM_DEVFS_CTX";
     124    else if( type == KMEM_FATFS_CTX )     return "KMEM_FATFS_CTX";
     125    else if( type == KMEM_VFS_CTX )       return "KMEM_VFS_CTX";
     126    else if( type == KMEM_VFS_INODE )     return "KMEM_VFS_INODE";
     127    else if( type == KMEM_VFS_DENTRY )    return "KMEM_VFS_DENTRY";
     128    else if( type == KMEM_VFS_FILE )      return "KMEM_VFS_FILE";
     129    else if( type == KMEM_SEM )           return "KMEM_SEM";
     130    else if( type == KMEM_CONDVAR )       return "KMEM_CONDVAR";
     131    else if( type == KMEM_MUTEX )         return "KMEM_MUTEX";
    136132        else if( type == KMEM_512_BYTES )     return "KMEM_512_BYTES";
    137133
  • trunk/kernel/mm/kmem.h

    r159 r188  
    4848  KMEM_BARRIER          = 9,   /*! remote_barrier_t                                 */
    4949
    50   KMEM_FATFS_INODE      = 10,  /*! fatfs_inode_t                                    */
     50  KMEM_DEVFS_CTX        = 10,  /*! fatfs_inode_t                                    */
    5151  KMEM_FATFS_CTX        = 11,  /*! fatfs_ctx_t                                      */
    52   KMEM_DEVFS_INODE      = 12,  /*  devfs_inode_t                                    */
    53   KMEM_MUTEX            = 13,  /*! remote_mutex_t                                   */
    54   KMEM_VFS_CTX          = 14,  /*! vfs_context_t                                    */
    55   KMEM_VFS_INODE        = 15,  /*! vfs_inode_t                                      */
    56   KMEM_VFS_DENTRY       = 16,  /*! vfs_dentry_t                                     */
    57   KMEM_VFS_FILE         = 17,  /*! vfs_file_t                                       */
    58   KMEM_SEM              = 18,  /*! remote_sem_t                                     */
    59   KMEM_CONDVAR          = 19,  /*! remote_condvar_t                                 */
    60 
    61   KMEM_512_BYTES        = 20,  /*! 512 bytes aligned                                */
     52  KMEM_VFS_CTX          = 12,  /*! vfs_context_t                                    */
     53  KMEM_VFS_INODE        = 13,  /*! vfs_inode_t                                      */
     54  KMEM_VFS_DENTRY       = 14,  /*! vfs_dentry_t                                     */
     55  KMEM_VFS_FILE         = 15,  /*! vfs_file_t                                       */
     56  KMEM_SEM              = 16,  /*! remote_sem_t                                     */
     57  KMEM_CONDVAR          = 17,  /*! remote_condvar_t                                 */
     58  KMEM_MUTEX            = 18,  /*! remote_mutex_t                                   */
     59  KMEM_512_BYTES        = 19,  /*! 512 bytes aligned                                */
    6260
    6361  KMEM_TYPES_NR         = 21,
  • trunk/kernel/vfs/devfs.c

    r50 r188  
    2626#include <hal_special.h>
    2727#include <printk.h>
     28#include <chdev.h>
     29#include <cluster.h>
     30#include <vfs.h>
    2831#include <kmem.h>
    29 #include <string.h>
    30 #include <chdev.h>
    31 #include <core.h>
    32 #include <thread.h>
    33 #include <vfs.h>
    34 #include <errno.h>
    3532#include <devfs.h>
    36 #include <rpc.h>
    37 
    38 
    39 //////////////////////////////////////////////////////////////////////////////////////////
    40 //          Extern  variables         
    41 //////////////////////////////////////////////////////////////////////////////////////////
    42 
    43 extern vfs_ctx_t          fs_context[FS_TYPES_NR];   // allocated in vfs.c file
    44 
    45 extern remote_barrier_t   global_barrier;            // allocated in kernel_init.c
    46  
    47 extern chdev_directory_t  chdev_dir;                 // allocated in kernel_init.c
    48 
    49 ////////////////////////////////////////////////////////////////////////////////////////
    50 //                DEVFS private functions
    51 ////////////////////////////////////////////////////////////////////////////////////////
    52 
    53 ////////////////////////////////////////////////////////////////////////////////////////
    54 // This function creates in the local cluster the dentry and the associated inode,
    55 // for a DEVFS directory (level 0 or level 1 in DEVFS tree).
    56 ////////////////////////////////////////////////////////////////////////////////////////
    57 // @ name        : directory entry name.
    58 // @ parent_xp   : extended pointer on parent inode.
    59 // @ inode_xp    : [out] buffer for extended pointer on created inode.
    60 ////////////////////////////////////////////////////////////////////////////////////////
    61 static void devfs_create_directory( char        * name,
    62                                     xptr_t        parent_xp,
    63                                     xptr_t      * inode_xp )
    64 {
    65     error_t       error;
    66     xptr_t        new_dentry_xp;     // extended pointer on created dentry
    67     xptr_t        new_inode_xp;      // extended pointer on created inode
    68  
    69     // get parent inode cluster and local pointer
    70     cxy_t         parent_cxy = GET_CXY( parent_xp );
    71     vfs_inode_t * parent_ptr = (vfs_inode_t *)GET_PTR( parent_xp );
    72 
    73     // create vfs_dentry in cluster containing the parent inode
    74     if( parent_cxy == local_cxy )
    75     {
    76         error = vfs_dentry_create( FS_TYPE_DEVFS,
    77                                    name,
    78                                    parent_ptr,
    79                                    &new_dentry_xp );
    80     }
    81     else
    82     {
    83         rpc_vfs_dentry_create_client( parent_cxy,
    84                                       FS_TYPE_DEVFS,
    85                                       name,
    86                                       parent_ptr,
    87                                       &new_dentry_xp,
    88                                       &error );
    89     }
    90 
    91     if ( error )
    92     {
    93         printk("\n[PANIC] in %s : cannot create dentry for %s in cluster %x/n",
    94                __FUNCTION__ , name , local_cxy );
    95         hal_core_sleep();
    96     }
    97 
    98     // create vfs_inode in local cluster TODO define the 4 arguments below [AG]
    99     uint32_t  attr   = 0;
    100     uint32_t  rights = 0;
    101     uid_t     uid    = 0;
    102     gid_t     gid    = 0;
    103     error = vfs_inode_create( new_dentry_xp,
    104                               FS_TYPE_DEVFS,
    105                               INODE_TYPE_DIR,
    106                               attr,
    107                               rights,
    108                               uid,
    109                               gid,
    110                               &new_inode_xp );
    111     if( error )
    112     {
    113         printk("\n[PANIC] in %s : cannot create inode for %s in cluster %x/n",
    114                __FUNCTION__ , name , local_cxy );
    115         hal_core_sleep();
    116     }
    117 
    118     // return extended pointer on directory inode
    119     *inode_xp = new_inode_xp;
    120 
    121 }  // end devfs_create_directory()
    122                                    
    123 ////////////////////////////////////////////////////////////////////////////////////////
    124 // This function creates in the local cluster the dentry and the associated inode,
    125 // for a chdev (level 2 in DEVFS tree).
    126 ////////////////////////////////////////////////////////////////////////////////////////
    127 // @ chdev    : local pointer on local chdev.
    128 // @ name     : directory entry name.
    129 // @ parent   : local pointer on local parent inode.
    130 // @ inode_xp : [out] buffer for extended pointer on created inode.
    131 ////////////////////////////////////////////////////////////////////////////////////////
    132 static void devfs_register_chdev( chdev_t     * chdev,
    133                                   char        * name,
    134                                   vfs_inode_t * parent,
    135                                   xptr_t      * inode_xp )
     33
     34/////////////////////////////////////////////////////////////////////////////////////////
     35//     Extern variables
     36/////////////////////////////////////////////////////////////////////////////////////////
     37
     38extern vfs_ctx_t            fs_context[];   // allocated in kernel_init.c
     39extern chdev_directory_t    chdev_dir;      // allocated in kernel_init.c
     40
     41///////////////////////////////
     42devfs_ctx_t * devfs_ctx_alloc()
     43{
     44    kmem_req_t    req;
     45
     46        req.type    = KMEM_DEVFS_CTX;
     47        req.size    = sizeof(devfs_ctx_t);
     48    req.flags   = AF_KERNEL | AF_ZERO;
     49
     50        return (devfs_ctx_t *)kmem_alloc( &req );
     51}
     52
     53/////////////////////////////////////////////
     54void devfs_ctx_init( devfs_ctx_t * devfs_ctx,
     55                     xptr_t        devfs_root_inode_xp,
     56                     xptr_t        devfs_external_inode_xp )
     57{
     58    devfs_ctx->root_inode_xp     = devfs_root_inode_xp;
     59    devfs_ctx->external_inode_xp = devfs_external_inode_xp;
     60
     61    fs_context[FS_TYPE_DEVFS].extend = devfs_ctx;
     62}
     63
     64/////////////////////////////////////////////////
     65void devfs_ctx_destroy( devfs_ctx_t * devfs_ctx )
     66{
     67    kmem_req_t    req;
     68
     69    req.type = KMEM_DEVFS_CTX;
     70    req.ptr  = devfs_ctx;
     71    kmem_free( &req );
     72}
     73
     74///////////////////////////////////////////////////
     75void devfs_global_init( xptr_t   parent_inode_xp,
     76                        xptr_t * devfs_root_inode_xp,
     77                        xptr_t * devfs_external_inode_xp )
    13678{
    13779    error_t  error;
    138     xptr_t   new_dentry_xp;
    139     xptr_t   new_inode_xp;
    140 
    141     devfs_dmsg("\n[INFO] %s : create dentry for %s\n", __FUNCTION__ , name );
    142    
    143     // create vfs_dentry in local cluster
    144     error = vfs_dentry_create( FS_TYPE_DEVFS,
    145                                name,
    146                                parent,
    147                                &new_dentry_xp );
    148     if ( error )
    149     {
    150         printk("\n[PANIC] in %s : cannot create dentry for %s in cluster %x/n",
    151                __FUNCTION__ , name , local_cxy );
    152         hal_core_sleep();
    153     }
    154 
    155     devfs_dmsg("\n[INFO] %s : create inode for %s\n", __FUNCTION__ , name );
    156    
    157     // create vfs_inode in local cluster
    158     uint32_t  attr   = 0;
    159     uint32_t  rights = 0;
    160     uid_t     uid    = 0;
    161     gid_t     gid    = 0;
    162     error = vfs_inode_create( new_dentry_xp,
    163                               FS_TYPE_DEVFS,
    164                               INODE_TYPE_DEV,
    165                               attr,
    166                               rights,
    167                               uid,
    168                               gid,
    169                               &new_inode_xp );
    170     if( error )
    171     {
    172         printk("\n[PANIC] in %s : cannot create inode for %s in cluster %x/n",
    173                __FUNCTION__ , name , local_cxy );
    174         hal_core_sleep();
    175     }
    176 
    177     // return extended pointer on chdev inode
    178     *inode_xp = new_inode_xp;
    179    
    180 }  // end devfs_register_chdev()
    181 
    182 
    183 
    184 ///////////////////////////////////////////////////////////////////////////////////////
    185 // Generic API : the following functions are called by the VFS,
    186 //               and must be defined by all supported file systems.
    187 ///////////////////////////////////////////////////////////////////////////////////////
    188 
    189 ////////////////////////////////////////////
    190 
    191 ////////////////////////////////////////////
    192 error_t devfs_mount( xptr_t   parent_inode_xp,
    193                      char   * devfs_root_name )
    194 {
    195     assert( (CURRENT_CORE->lid == 0) , __FUNCTION__ , "only CP0 should do it" );
    196 
    197     vfs_inode_t * parent_inode_ptr;
    198     cxy_t         parent_inode_cxy;
    199     vfs_ctx_t   * vfs_ctx;
    200 
     80
     81    // creates DEVFS "dev" inode in cluster IO
     82    error = vfs_add_child_in_parent( LOCAL_CLUSTER->io_cxy,
     83                                     INODE_TYPE_DIR,
     84                                     FS_TYPE_DEVFS,
     85                                     parent_inode_xp,
     86                                     "dev",
     87                                     NULL,
     88                                     devfs_root_inode_xp );
     89
     90    nolock_assert( (error == 0) , __FUNCTION__ , "cannot create <dev>\n" );
     91
     92    // create DEVFS "external" inode in cluster IO
     93    error = vfs_add_child_in_parent( LOCAL_CLUSTER->io_cxy,
     94                                     INODE_TYPE_DIR,
     95                                     FS_TYPE_DEVFS,
     96                                     *devfs_root_inode_xp,
     97                                     "dev",
     98                                     NULL,
     99                                     devfs_external_inode_xp );
     100
     101    nolock_assert( (error == 0) , __FUNCTION__ , "cannot create <external>\n" );
     102}
     103
     104//////////////////////////////////////////////////
     105void devfs_local_init( xptr_t devfs_root_inode_xp,
     106                       xptr_t devfs_external_inode_xp )
     107{
    201108    char          node_name[16];
     109    xptr_t        chdev_xp;
     110    cxy_t         chdev_cxy;
     111    xptr_t        inode_xp;
     112    xptr_t        internal_inode_xp;
    202113    uint32_t      channel;
    203114
    204     xptr_t        root_inode_xp;
    205     xptr_t        external_inode_xp;
    206     xptr_t        internal_inode_xp;
    207     xptr_t        chdev_inode_xp;
    208 
    209     chdev_t     * chdev_ptr;
    210 
    211     // get number of kernel instances and extended pointer on global barrier
    212     cluster_t * cluster     = LOCAL_CLUSTER;
    213     uint32_t    nb_clusters = cluster->x_size * cluster->y_size;
    214     xptr_t      barrier_xp  = XPTR( cluster->io_cxy , &global_barrier );
    215 
    216     // get VFS root inode cluster and local pointer
    217     parent_inode_cxy = GET_CXY( parent_inode_xp );
    218     parent_inode_ptr = (vfs_inode_t *)GET_PTR( parent_inode_xp );
    219 
    220     // get local pointer on VFS context for DEVFS
    221     vfs_ctx = &fs_context[FS_TYPE_DEVFS];
    222 
    223     ///// step 1 : all clusters initialize local DEVFS context  /////
    224 
    225     devfs_ctx_init( vfs_ctx , parent_inode_xp );
    226 
    227     ///// step 2 : cluster_0 creates DEVFS root    /////
    228 
    229     if( local_cxy == 0 )
    230     {
    231         devfs_create_directory( devfs_root_name,
    232                                 parent_inode_xp,
    233                                 &root_inode_xp );
    234     }
    235 
    236     // synchronize all clusters
    237     remote_barrier( barrier_xp , nb_clusters );
    238 
    239     ///// step 3 : all clusters create "internal" directory and chdevs  /////
    240 
    241     // TODO check device existence : (chdev_xp != XPTR_NULL) in chdev_dir
    242 
     115    // create "internal" directory linked to "dev"
    243116    snprintf( node_name , 16 , "internal_%x" , local_cxy );
    244 
    245     devfs_create_directory( node_name,
    246                             root_inode_xp,
    247                             &internal_inode_xp );
     117    vfs_add_child_in_parent( local_cxy,
     118                             INODE_TYPE_DIR,
     119                             FS_TYPE_DEVFS,
     120                             devfs_root_inode_xp,
     121                             node_name,
     122                             NULL,
     123                             &internal_inode_xp );
    248124
    249125    // create ICU chdev inode
    250     chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.icu[local_cxy] );
    251     devfs_register_chdev( chdev_ptr,
    252                           "icu",
    253                           (vfs_inode_t *)GET_PTR( internal_inode_xp ),
    254                           &chdev_inode_xp );
     126    chdev_xp = chdev_dir.icu[local_cxy];
     127    if( chdev_xp != XPTR_NULL)
     128    {
     129        vfs_add_child_in_parent( local_cxy,
     130                                 INODE_TYPE_DEV,
     131                                 FS_TYPE_DEVFS,
     132                                 internal_inode_xp,
     133                                 "icu",
     134                                 GET_PTR( chdev_xp ),
     135                                 &inode_xp );
     136    }
    255137
    256138    // create MMC chdev inode
    257     chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.mmc[local_cxy] );
    258     devfs_register_chdev( chdev_ptr,
    259                           "mmc",
    260                           (vfs_inode_t *)GET_PTR( internal_inode_xp ),
    261                           &chdev_inode_xp );
     139    chdev_xp = chdev_dir.mmc[local_cxy];
     140    if( chdev_xp != XPTR_NULL)
     141    {
     142        vfs_add_child_in_parent( local_cxy,
     143                                 INODE_TYPE_DEV,
     144                                 FS_TYPE_DEVFS,
     145                                 internal_inode_xp,
     146                                 "mmc",
     147                                 GET_PTR( chdev_xp ),
     148                                 &inode_xp );
     149    }
    262150
    263151    // create DMA chdev inodes (one DMA channel per core)
    264     for( channel = 0 ; channel < cluster->cores_nr ; channel++ )
    265     {
    266         chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.dma[channel] );
    267         snprintf( node_name , 16 , "dma_%d" , channel );
    268         devfs_register_chdev( chdev_ptr,
    269                               node_name,
    270                               (vfs_inode_t *)GET_PTR( internal_inode_xp ),
    271                               &chdev_inode_xp );
    272     }
    273 
    274     ///// step 4 : cluster_io creates "external" directory and chdevs /////
    275 
    276     // TODO check device existence : (chdev_xp != XPTR_NULL) in chdev_dir
    277 
    278     if( local_cxy == cluster->io_cxy )
    279     {
    280         devfs_create_directory( "external",
    281                                 root_inode_xp,
    282                                 &external_inode_xp );
    283 
    284         // create IOB chdev inode
    285         chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.iob );
    286         devfs_register_chdev( chdev_ptr,
    287                               "iob",
    288                               (vfs_inode_t *)GET_PTR( external_inode_xp ),
    289                               &chdev_inode_xp );
     152    for( channel = 0 ; channel < LOCAL_CLUSTER->cores_nr ; channel++ )
     153    {
     154        chdev_xp = chdev_dir.dma[channel];
     155        if( chdev_xp != XPTR_NULL)
     156        {
     157            snprintf( node_name , 16 , "dma_%d" , channel );
     158            vfs_add_child_in_parent( local_cxy,
     159                                     INODE_TYPE_DEV,
     160                                     FS_TYPE_DEVFS,
     161                                     internal_inode_xp,
     162                                     node_name,
     163                                     GET_PTR( chdev_xp ),
     164                                     &inode_xp );
     165        }
     166    }
     167
     168    // create an IOB inode in cluster containing IOB chdev
     169    chdev_xp = chdev_dir.iob;
     170    if( chdev_xp != XPTR_NULL )
     171    {
     172        chdev_cxy = GET_CXY( chdev_xp );
     173        if( chdev_cxy == local_cxy )
     174        {
     175            vfs_add_child_in_parent( local_cxy,
     176                                     INODE_TYPE_DEV,
     177                                     FS_TYPE_DEVFS,
     178                                     devfs_external_inode_xp,
     179                                     "iob",
     180                                     GET_PTR( chdev_xp ),
     181                                     &inode_xp );
     182        }
     183    }
    290184       
    291         // create PIC chdev inode
    292         chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.pic );
    293         devfs_register_chdev( chdev_ptr,
    294                               "pic",
    295                               (vfs_inode_t *)GET_PTR( external_inode_xp ),
    296                               &chdev_inode_xp );
    297 
    298         // create TXT chdev inodes
    299         for( channel = 0 ; channel < CONFIG_MAX_TXT_CHANNELS ; channel++ )
    300         {
    301             chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.txt[channel] );
    302             snprintf( node_name , 16 , "txt_%d" , channel );
    303             devfs_register_chdev( chdev_ptr,
    304                                   node_name,
    305                                   (vfs_inode_t *)GET_PTR( external_inode_xp ),
    306                                   &chdev_inode_xp );
    307         }
    308 
    309         // create IOC chdev inodes
    310         for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ )
    311         {
    312             chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.ioc[channel] );
    313             snprintf( node_name , 16 , "ioc_%d" , channel );
    314             devfs_register_chdev( chdev_ptr,
    315                                   node_name,
    316                                   (vfs_inode_t *)GET_PTR( external_inode_xp ),
    317                                   &chdev_inode_xp );
    318         }
    319 
    320         // create FBF chdev inodes
    321         for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ )
    322         {
    323             chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.ioc[channel] );
    324             snprintf( node_name , 16 , "fbf_%d" , channel );
    325             devfs_register_chdev( chdev_ptr,
    326                                   node_name,
    327                                   (vfs_inode_t *)GET_PTR( external_inode_xp ),
    328                                   &chdev_inode_xp );
    329         }
    330 
    331         // create NIC_RX chdevs
    332         for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
    333         {
    334             chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.nic_rx[channel] );
    335             snprintf( node_name , 16 , "nic_rx_%d" , channel );
    336             devfs_register_chdev( chdev_ptr,
    337                                   node_name,
    338                                   (vfs_inode_t *)GET_PTR( external_inode_xp ),
    339                                   &chdev_inode_xp );
    340         }
    341 
    342         // create NIC_TX chdev inodes
    343         for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
    344         {
    345             chdev_ptr = (chdev_t *)GET_PTR( chdev_dir.nic_tx[channel] );
    346             snprintf( node_name , 16 , "nic_tx_%d" , channel );
    347             devfs_register_chdev( chdev_ptr,
    348                                   node_name,
    349                                   (vfs_inode_t *)GET_PTR( external_inode_xp ),
    350                                   &chdev_inode_xp );
    351         }
    352     }
    353 
    354     // synchronize all clusters
    355     remote_barrier( barrier_xp , nb_clusters );
    356 
    357     return 0;
    358 
    359 }  // end devfs_init()
    360 
    361 
    362 ////////////////////////////////////////////
    363 error_t devfs_ctx_init( vfs_ctx_t * vfs_ctx,
    364                         xptr_t      root_inode_xp )
    365 {
    366     vfs_ctx->type    = FS_TYPE_DEVFS;
    367     vfs_ctx->attr    = 0;                // not READ_ONLY / not SYNC
    368     vfs_ctx->count   = 0;                // unused for DEVFS
    369     vfs_ctx->blksize = 0;                // unused for DEVFS
    370     vfs_ctx->root_xp = root_inode_xp;
    371     vfs_ctx->extend  = NULL;             // unused for DEVFS
    372 
    373     spinlock_init( &vfs_ctx->lock );
    374 
    375     bitmap_init( vfs_ctx->bitmap , CONFIG_VFS_MAX_INODES );
    376 
    377     return 0;
    378 }
    379 
    380 
    381 ////////////////////////////////////////////////////
    382 error_t devfs_inode_create( vfs_inode_t * vfs_inode,
    383                             chdev_t     * chdev )
    384 {
    385     kmem_req_t      req;
    386     devfs_inode_t * devfs_inode;
    387 
    388     // allocate memory for FATFS inode extension
    389         req.type    = KMEM_DEVFS_INODE;
    390         req.size    = sizeof(devfs_inode_t);
    391     req.flags   = AF_KERNEL | AF_ZERO;
    392         devfs_inode = (devfs_inode_t *)kmem_alloc( &req );
    393 
    394     if( devfs_inode == NULL ) return ENOMEM;
    395 
    396     // link DEVFS inode to VFS inode
    397     vfs_inode->extend = devfs_inode;
    398 
    399     // initialise DEVFS inode 
    400     devfs_inode->chdev = chdev;
    401  
    402     return 0;
    403 }
    404 
    405 ///////////////////////////////////////////////////
    406 void devfs_inode_destroy( vfs_inode_t * vfs_inode )
    407 {
    408     kmem_req_t      req;
    409     devfs_inode_t * devfs_inode;
    410 
    411     // get pointer on DEVFS inode
    412     devfs_inode = (devfs_inode_t *)vfs_inode->extend;
    413 
    414     req.type = KMEM_DEVFS_INODE;
    415     req.ptr  = devfs_inode;
    416     kmem_free( &req );
    417 
    418         vfs_inode->extend = NULL;
    419 }
    420 
    421 
    422 /* deprecated [AG]
    423 
    424 error_t devfs_open_file( vfs_file_t * file,
    425                          void       * extend );
    426 {
    427         error_t err;
    428         register struct devfs_context_s *ctx;
    429         register struct devfs_file_s *info;
    430         chdev_t       * chdev;
    431         vfs_inode_t   * inode;
    432         dev_request_t   rq;
    433         kmem_req_t      req;
    434 
    435         inode = file->inode;
    436 
    437         info = file->fr_pv;
    438         ctx  = (struct devfs_context_s *)&inode->i_ctx->ctx_devfs;
    439 
    440         if(!(inode->i_attr & VFS_DIR))
    441         {
    442                 dev = (struct device_s*)inode->i_pv;
    443    
    444                 if(dev->type == DEV_INTERNAL)
    445                         return EPERM;
    446 
    447                 if(dev->type == DEV_BLK)
    448                         VFS_SET(inode->i_attr,VFS_DEV_BLK);
    449                 else
    450                         VFS_SET(inode->i_attr,VFS_DEV_CHR);
    451  
    452                 if(dev->op.dev.open != NULL)
    453                 {
    454                         rq.fremote = file;
    455                         if((err=dev->op.dev.open(dev, &rq)))
    456                                 return err;
    457                 }
    458 
    459                 priv->dev = (void*)dev;
    460 
    461                 return 0;
    462         }
    463 
    464         if(info == NULL)
    465         {
    466                 req.type  = KMEM_DEVFS_FILE;
    467                 req.size  = sizeof(*info);
    468                 req.flags = AF_KERNEL;
    469                 info      = kmem_alloc(&req);
    470         }
    471 
    472         if(info == NULL) return ENOMEM;
    473 
    474         metafs_iter_init(&devfs_db.root, &info->iter);
    475         info->ctx  = ctx;
    476         file->fr_pv = info;
    477  
    478         metafs_print(&devfs_db.root);
    479         return 0;
    480 }
    481 
    482 #define TMP_BUFF_SZ 512
    483 
    484 //FIXME:
    485 //add a "while" loop for the case where the
    486 //buffer TMP_BUFF_SZ is smaller than
    487 //buffer->size
    488 //////////////////////////////
    489 devfs_read( vfs_file_t * file,
    490             char       * buffer )
    491 {
    492         chdev_t       * chdev;
    493         dev_request_t   rq;
    494         uint32_t        count;
    495     uint8_t         buff[TMP_BUFF_SZ];
    496 
    497     // get pointer on chdev
    498         chdev = (chdev_t *)file->extend;
    499 
    500     if( chdev->func == DEV_FUNC_TXT )
    501     {
    502     }
    503     if( chdev->func == DEV_FUNC_IOC )
    504     {
    505     }
    506     else
    507     {
    508         printk("\n[PANIC] in %s : illegal device functionnal type
    509 
    510         rq.dst   = &buff[0];
    511         rq.count = TMP_BUFF_SZ;
    512         rq.flags = 0;
    513         rq.file  = file;
    514 
    515         if((count = dev->op.dev.read(dev, &rq)) < 0)
    516                 return count;
    517 
    518         buffer->scpy_to_buff(buffer, &buff[0], count);
    519         return count;
    520 }
    521 
    522 //FIXME: To improve this an avoid the extra copy,
    523 //we could set along with the buffer(src and dest)
    524 //the functions to manipulate them, such as in
    525 //do_exec.c
    526 ///////////////////////////////
    527 devfs_write( vfs_file_t * file,
    528              char       * buffer )
    529 {
    530         register struct device_s *dev;
    531         uint8_t buff[TMP_BUFF_SZ];
    532         dev_request_t rq;
    533        
    534         dev = (struct device_s*)file->f_private.dev;
    535        
    536         //FIXME avoid the extra copy ?
    537         buffer->scpy_from_buff(buffer, (void*)&buff[0], TMP_BUFF_SZ);
    538         rq.src   = (void*)&buff[0];
    539         rq.count = buffer->size;
    540         rq.flags = 0;
    541         rq.file  = file;
    542  
    543         return dev->op.dev.write(dev, &rq);
    544 }
    545 
    546 VFS_LSEEK_FILE(devfs_lseek)
    547 {
    548         register struct device_s *dev;
    549         dev_request_t rq;
    550 
    551         dev = (struct device_s*)file->fr_inode->i_pv;
    552 
    553         if(dev->op.dev.lseek == NULL)
    554                 return VFS_ENOTUSED;
    555  
    556         rq.fremote = file;
    557         return dev->op.dev.lseek(dev, &rq);
    558 }
    559 
    560 VFS_CLOSE_FILE(devfs_close)
    561 {
    562         register struct device_s *dev;
    563         dev_request_t rq;
    564 
    565         if(file->fr_inode->i_attr & VFS_DIR)
    566                 return 0;
    567 
    568         dev = (struct device_s*)file->fr_inode->i_pv;
    569 
    570         if(dev->op.dev.close == NULL)
    571                 return 0;
    572  
    573         rq.fremote = file;
    574         return dev->op.dev.close(dev, &rq);
    575 }
    576 
    577 VFS_RELEASE_FILE(devfs_release)
    578 
    579         kmem_req_t req;
    580 
    581         if(file->fr_pv == NULL)
    582                 return 0;
    583  
    584         req.type = KMEM_DEVFS_FILE;
    585         req.ptr  = file->fr_pv;
    586         kmem_free(&req);
    587 
    588         file->fr_pv = NULL;
    589         return 0;
    590 }
    591 
    592 VFS_READ_DIR(devfs_readdir)
    593 {
    594         register struct devfs_file_s *info;
    595         register struct metafs_s *current;
    596         register struct device_s *current_dev;
    597  
    598         info = file->fr_pv;
    599  
    600         if(file->fr_pv == NULL)
    601                 return ENOTDIR;
    602 
    603         if((current = metafs_lookup_next(&devfs_db.root, &info->iter)) == NULL)
    604                 return EEODIR;
    605 
    606         current_dev    = metafs_container(current, struct device_s, node);
    607         dirent->u_attr = (current_dev->type == DEV_BLK) ? VFS_DEV_BLK : VFS_DEV_CHR;
    608 
    609         strcpy((char*)dirent->u_name, metafs_get_name(current));
    610 
    611         dirent->u_ino = (uint_t) current_dev->base_paddr;
    612 
    613         return 0;
    614 }
    615 
    616 VFS_MMAP_FILE(devfs_mmap)
    617 {
    618         register struct device_s *dev;
    619         dev_request_t rq;
    620  
    621         dev = (struct device_s*)file->f_private.dev;
    622 
    623         if(dev->op.dev.mmap == NULL)
    624                 return ENODEV;
    625 
    626         rq.flags  = 0;
    627         rq.file   = file;
    628         rq.region = region;
    629 
    630         return dev->op.dev.mmap(dev, &rq);
    631 }
    632 
    633 VFS_MMAP_FILE(devfs_munmap)
    634 {
    635         register struct device_s *dev;
    636         dev_request_t rq;
    637 
    638         dev = (struct device_s*)file->f_private.dev;
    639 
    640         if(dev->op.dev.munmap == NULL)
    641                 return ENODEV;
    642 
    643         rq.flags  = 0;
    644         rq.file   = file;
    645         rq.region = region;
    646 
    647         return dev->op.dev.munmap(dev, &rq);
    648 }
    649 
    650 
    651 */
    652 
    653 
     185    // create a PIC inode in cluster containing PIC chdev
     186    chdev_xp = chdev_dir.pic;
     187    if( chdev_xp != XPTR_NULL )
     188    {
     189        chdev_cxy = GET_CXY( chdev_xp );
     190        if( chdev_cxy == local_cxy )
     191        {
     192            vfs_add_child_in_parent( local_cxy,
     193                                     INODE_TYPE_DEV,
     194                                     FS_TYPE_DEVFS,
     195                                     devfs_external_inode_xp,
     196                                     "pic",
     197                                     GET_PTR( chdev_xp ),
     198                                     &inode_xp );
     199        }
     200    }
     201
     202    // create a TXT inode in each cluster containing a TXT chdev
     203    for( channel = 0 ; channel < CONFIG_MAX_TXT_CHANNELS ; channel++ )
     204    {
     205        chdev_xp = chdev_dir.txt[channel];
     206        if( chdev_xp != XPTR_NULL )
     207        {
     208            chdev_cxy = GET_CXY( chdev_xp );
     209            if( chdev_cxy == local_cxy )
     210            {
     211                snprintf( node_name , 16 , "txt_%d" , channel );
     212                vfs_add_child_in_parent( local_cxy,
     213                                         INODE_TYPE_DEV,
     214                                         FS_TYPE_DEVFS,
     215                                         devfs_external_inode_xp,
     216                                         node_name,
     217                                         GET_PTR( chdev_xp ),
     218                                         &inode_xp );
     219            }
     220        }
     221    }
     222
     223    // create an IOC inode in each cluster containing an IOC chdev
     224    for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ )
     225    {
     226        chdev_xp = chdev_dir.ioc[channel];
     227        if( chdev_xp != XPTR_NULL )
     228        {
     229            chdev_cxy = GET_CXY( chdev_xp );
     230            if( chdev_cxy == local_cxy )
     231            {
     232                snprintf( node_name , 16 , "ioc_%d" , channel );
     233                vfs_add_child_in_parent( local_cxy,
     234                                         INODE_TYPE_DEV,
     235                                         FS_TYPE_DEVFS,
     236                                         devfs_external_inode_xp,
     237                                         node_name,
     238                                         GET_PTR( chdev_xp ),
     239                                         &inode_xp );
     240            }
     241        }
     242    }
     243
     244    // create a FBF inode in each cluster containing a FBF chdev
     245    for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ )
     246    {
     247        chdev_xp = chdev_dir.fbf[channel];
     248        if( chdev_xp != XPTR_NULL )
     249        {
     250            chdev_cxy = GET_CXY( chdev_xp );
     251            if( chdev_cxy == local_cxy )
     252            {
     253                snprintf( node_name , 16 , "fbf_%d" , channel );
     254                vfs_add_child_in_parent( local_cxy,
     255                                         INODE_TYPE_DEV,
     256                                         FS_TYPE_DEVFS,
     257                                         devfs_external_inode_xp,
     258                                         node_name,
     259                                         GET_PTR( chdev_xp ),
     260                                         &inode_xp );
     261            }
     262        }
     263    }
     264
     265    // create a NIC_RX inode in each cluster containing a NIC_RX chdev
     266    for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
     267    {
     268        chdev_xp = chdev_dir.nic_rx[channel];
     269        if( chdev_xp != XPTR_NULL )
     270        {
     271            chdev_cxy = GET_CXY( chdev_xp );
     272            if( chdev_cxy == local_cxy )
     273            {
     274                snprintf( node_name , 16 , "nic_rx_%d" , channel );
     275                vfs_add_child_in_parent( local_cxy,
     276                                         INODE_TYPE_DEV,
     277                                         FS_TYPE_DEVFS,
     278                                         devfs_external_inode_xp,
     279                                         node_name,
     280                                         GET_PTR( chdev_xp ),
     281                                         &inode_xp );
     282            }
     283        }
     284    }
     285
     286    // create a NIC_TX inode in each cluster containing a NIC_TX chdev
     287    for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
     288    {
     289        chdev_xp = chdev_dir.nic_tx[channel];
     290        if( chdev_xp != XPTR_NULL )
     291        {
     292            chdev_cxy = GET_CXY( chdev_xp );
     293            if( chdev_cxy == local_cxy )
     294            {
     295                snprintf( node_name , 16 , "nic_tx_%d" , channel );
     296                vfs_add_child_in_parent( local_cxy,
     297                                         INODE_TYPE_DEV,
     298                                         FS_TYPE_DEVFS,
     299                                         devfs_external_inode_xp,
     300                                         node_name,
     301                                         GET_PTR( chdev_xp ),
     302                                         &inode_xp );
     303            }
     304        }
     305    }
     306}  // end devfs_local_init()
     307
  • trunk/kernel/vfs/devfs.h

    r23 r188  
    2626#define _DEVFS_H_
    2727
    28 ///////////////////////////////////////////////////////////////////////////////////////////
    29 // The DEVFS File System contains inodes associated to all chdev descriptors availables
    30 // in the target architecture.  It is a three levels tree structure:
    31 // - The "dev" directory inode is stored in cluster_0. It is the root of the devfs
    32 //   file system. The parent inode is the "/" global root.
     28//////////////////////////////////////////////////////////////////////////////////////////
     29// The DEVFS File System contains inodes and dentries associated to all chdev descriptors
     30// availables in the architecture. It is structured as a three levels tree structure :
     31// - The "dev" directory inode is stored in cluster_IO. It is the root of the DEVFS
     32//   file system. The parent inode is the "/" VFS root.
    3333// - There is one "internal_cxy" directory inode per cluster, that is the parent of
    34 //   the local children inodes associated to the local chdev descriptors.
    35 //   The parent inode and dentry are stored in cluster_0.
     34//   the local children inodes associated to the local, internal chdev descriptors.
     35//   The parent dentry is stored in cluster_IO.
    3636// - The I/O cluster contains one "external" directory inode, that is the parent of
    37 //   the remote children inodes associated to the remote external descriptors.
    38 //   The parent inode and dentry are stored in cluster_0.
     37//   the remote children inodes associated to the remote external chdev descriptors.
     38//   The parent dentry is stored in cluster_IO.
    3939//
    40 // The DEVFS File system does not require a context extension, but requires an inode
    41 // extension to store the pointer on the associated chdev descriptor.
    42 ///////////////////////////////////////////////////////////////////////////////////////////
     40// The DEVFS file system uses the DEVFS context extension to register an extended pointer
     41// on the DEVFS "dev" inode, and and another extended pointer on the "external" inode.
     42//
     43// The DEVFS file system uses the VFS inode extension to store the pointer
     44// on the associated chdev descriptor.
     45//////////////////////////////////////////////////////////////////////////////////////////
    4346
    44 /**************  Forward declarations     ************************************************/
     47/*****************************************************************************************
     48 * This structure defines the DEVFS context extension.
     49 ****************************************************************************************/
    4550
    46 struct chdev_s;
    47 
    48 /******************************************************************************************
    49  * This structure defines the DEVFS inode descriptor extension.
    50  *****************************************************************************************/
    51 
    52 typedef struct devfs_inode_ext_s
     51typedef struct devfs_ctx_s
    5352{
    54     struct chdev_s * chdev;       /* extended pointer on associated chdev                */
     53    xptr_t   root_inode_xp;              /*! extended pointer on DEVFS root inode       */
     54    xptr_t   external_inode_xp;          /*! extended pointer on DEVFS external inode   */
    5555}
    56 devfs_inode_t;
     56devfs_ctx_t;
    5757
    5858
    59 
    60 
    61 
    62 //////////////////////////////////////////////////////////////////////////////////////////
    63 //                 These functions are called by the VFS.
    64 //////////////////////////////////////////////////////////////////////////////////////////
    65 
    66 /******************************************************************************************
    67  * This function  does not exist for the DEVFS file system, as this File System
    68  * cannot be mounted as the root FS.
    69  *****************************************************************************************/
    70 xptr_t devfs_init();
    71 
    72 
    73 /******************************************************************************************
    74  * This function mount the DEVFS file system on the root FS.
    75  * It is executed cooperatively during kernel init by all CP0s in all clusters,
    76  * to create the DEVFS 3-levels tree structure.
    77  * This is a four phases procedure, and it uses the global barrier to synchronize
    78  * the cooperating kernel instances when required.
    79  * - phase 1 : In all clusters, it creates the local extension of the DEVFS context,
    80  *    and initialises it.
    81  * - phase 2 : In cluster_0 only, it creates the dentry and the associated inode for
    82  *   the DEVFS root directory.
    83  * - phase 3 : In all cluster(x,y), it creates the dentry and the associated inode for
    84  *   the "internal_cxy" directory. It also creates the dentry and associated inode
    85  *   for all local internal chdevs.
    86  * - phase 4 : In cluster_io only, it creates the dentry and the associated inode
    87  *   for the "external" directory. It also creates the dentry and associated inode
    88  *   for all external chdevs.
    89  ******************************************************************************************
    90  * @ parent_inode_xp   : extended pointer on the parent inode in root FS.
    91  * @ devfs_root_name   : DEVFS root directory name.
    92  *****************************************************************************************/
    93 error_t devfs_mount( xptr_t   parent_inode_xp,
    94                      char   * devfs_root_name );
     59/*****************************************************************************************
     60 * This fuction allocates memory from local cluster for a DEVFS context descriptor.
     61 *****************************************************************************************
     62 * @ return a pointer on the created context / return NULL if failure.
     63 ****************************************************************************************/
     64devfs_ctx_t * devfs_ctx_alloc();
    9565
    9666/*****************************************************************************************
    97  * This function initializes all fields of the VFS context.
    98  * No extra memory is allocated for a DEVFS context.
     67 * This function initialises the DEVFS context from arguments values, and link it
     68 * to the relevant VFS context in the local cluster.
    9969 *****************************************************************************************
    100  * @ vfs_ctx        : local pointer on VFS context for FATFS.
    101  * @ root_inode_xp  : extended pointer on the VFS root inode.
     70 * @ devfs_ctx               : local pointer on DEVFS context.
     71 * @ devfs_root_inode_xp     : [out] extended pointer on created <dev> inode.
     72 * @ devfs_external_inode_xp : [out] extended pointer on created <external> inode.
    10273 ****************************************************************************************/
    103 error_t devfs_ctx_init( struct vfs_ctx_s * vfs_ctx,
    104                         xptr_t             root_inode_xp );
     74void devfs_ctx_init( devfs_ctx_t * devfs_ctx,
     75                     xptr_t        devfs_root_inode_xp,
     76                     xptr_t        devfs_external_inode_xp );
    10577
    10678/*****************************************************************************************
    107  * This function does not exist for a DEVFS context, as there is no DEVFS context.
     79 * This function releases memory dynamically allocated for the DEVFS context.
     80 *****************************************************************************************
     81 * @ devfs_ctx   : local pointer on DEVFS context.
    10882 ****************************************************************************************/
    109 error_t devfs_ctx_destroy();
     83void devfs_ctx_destroy( devfs_ctx_t * devfs_ctx );
    11084
    11185/*****************************************************************************************
    112  * This function allocates memory for a DEVFS inode, initialise it,
    113  * and link it to the VFS inode.
     86 * This function start to create the DEVFS subtree.
     87 * This function should be called once in the cluster containing the VFS parent inode.
     88 * More precisely, it creates in cluster IO the "dev" and "external" DEVFS directories.
     89 * For each one, it creates the inode and link the associated dentry to parent inode.
     90 * The DEVFS root inode is linked to the VFS parent inode identified by <parent_inode_xp>.
    11491 *****************************************************************************************
    115  * @ inode          : local pointer on the VFS inode.
    116  * @ chdev          : local pointer on the chdev to be inserted in DEVFS.
     92 * @ parent_inode_xp         : extended pointer on the parent VFS inode.
     93 * @ devfs_root_inode_xp     : [out] extended pointer on created <dev> inode.
     94 * @ devfs_external_inode_xp : [out] extended pointer on created <external> inode.
    11795 ****************************************************************************************/
    118 error_t devfs_inode_create( struct vfs_inode_s * inode,
    119                             struct chdev_s     * chdev );
     96void devfs_global_init( xptr_t   parent_inode_xp,
     97                        xptr_t * devfs_root_inode_xp,
     98                        xptr_t * devfs_external_inode_xp );
    12099
    121100/*****************************************************************************************
    122  * This function releases memory allocated for a DEVFS inode.
     101 * This function completes the initialisation of the DEVFS subtree.
     102 * It should be called once in each cluster.
     103 * 1. In each cluster (i), it creates the "internal" directory,
     104 *    linked to the DEVFS "dev" parent directory.
     105 * 2. In each cluster (i), it creates - for each external chdev in cluster (i) -
     106 *    a pseudo-file, linked to the DEVFS "external" parent directory.
     107 * 3. In each cluster (i), it creates - for each internal chdev in cluster (i) -
     108 *    a pseudo-file, linked to the DEVFS "internal" parent directory.
    123109 *****************************************************************************************
    124  * @ inode   : local pointer on vfs_inode.
     110 * @ devfs_root_inode_xp     : extended pointer on DEVFS root inode.
     111 * @ devfs_external_inode_xp : extended pointer on DEVFS external inode.
    125112 ****************************************************************************************/
    126 void devfs_inode_destroy( struct vfs_inode_s * inode );
    127 
    128 /*****************************************************************************************
    129  * This function does not exist for the DEVFS File System.
    130  ****************************************************************************************/
    131 error_t devfs_write_page( struct page_s * page );
    132 
    133 /*****************************************************************************************
    134  * This function does not exist for the DEVFS File System.
    135  ****************************************************************************************/
    136 error_t devfs_read_page( struct page_s * page );
    137 
    138 
    139 
     113void devfs_local_init( xptr_t devfs_root_inode_xp,
     114                       xptr_t devfs_external_inode_xp );
     115                       
    140116#endif  /* _DEVFS_H_ */
  • trunk/kernel/vfs/fatfs.c

    r101 r188  
    4646 
    4747//////////////////////////////////////////////////////////////////////////////////////////
    48 // FATFS specific functions : these functions cannot be called by the VFS
    49 //////////////////////////////////////////////////////////////////////////////////////////
    50 
    51 //////////////////////////////////////////////////////////
    52 inline uint32_t fatfs_lba_from_cluster( fatfs_ctx_t * ctx,
    53                                         uint32_t      cluster )
     48//              FATFS private functions
     49//////////////////////////////////////////////////////////////////////////////////////////
     50
     51//////////////////////////////////////////////////////////////////////////////////////////
     52// This function returns the LBA of the first sector of a FAT cluster.
     53// This function can be called by any thread running in any cluster.
     54//////////////////////////////////////////////////////////////////////////////////////////
     55// @ ctx          :     pointer on FATFS context.
     56// @ cluster  : cluster index in FATFS.
     57// @ return the lba value.
     58//////////////////////////////////////////////////////////////////////////////////////////
     59static inline uint32_t fatfs_lba_from_cluster( fatfs_ctx_t * ctx,
     60                                               uint32_t      cluster )
    5461{
    5562    return (ctx->cluster_begin_lba + ((cluster - 2) << 3));
     
    200207
    201208///////////////////////////////////////////////////////////////////////////////////////
    202 //          The following functions are called by the VFS.
     209// Generic API : the following functions are called by the kernel
     210//               and must be defined by all supported file systems.
    203211///////////////////////////////////////////////////////////////////////////////////////
    204212
    205 
    206 ///////////////////
    207 xptr_t fatfs_init()
     213///////////////////////////////
     214fatfs_ctx_t * fatfs_ctx_alloc()
    208215{
    209216    kmem_req_t    req;
    210     fatfs_ctx_t * fatfs_ctx;       // local pointer on FATFS context
    211     vfs_ctx_t   * vfs_ctx;         // local pointer on VFS context
    212     xptr_t        root_inode_xp;   // extended pointer on root inode
    213     error_t       error;
    214 
    215     // get local pointer on VFS context for FATFS
    216     vfs_ctx = &fs_context[FS_TYPE_FATFS];
    217 
    218     // get number of kernel instances and extended pointer on global barrier
    219     cluster_t * cluster     = LOCAL_CLUSTER;
    220     uint32_t    nb_clusters = cluster->x_size * cluster->y_size;
    221     xptr_t      barrier_xp  = XPTR( cluster->io_cxy , &global_barrier );
    222 
    223     ///// step 1 : all clusters allocate memory for FATFS context
    224 
    225     // allocate memory for FATFS context extension
    226217        req.type    = KMEM_FATFS_CTX;
    227218        req.size    = sizeof(fatfs_ctx_t);
    228219    req.flags   = AF_KERNEL | AF_ZERO;
    229         fatfs_ctx   = (fatfs_ctx_t *)kmem_alloc( &req );
    230 
    231     if( fatfs_ctx == NULL )
    232     {
    233         printk("\n[PANIC] in %s : no memory for FATFS context\n", __FUNCTION__ );
    234         hal_core_sleep();
    235     }
    236    
    237     ///// step 2 : only cluster_0 access device and creates root inode
    238 
    239     if( local_cxy == 0 )
    240     {
    241         // create VFS root inode
    242         error = vfs_inode_create( XPTR_NULL,        // no parent dentry
    243                                   FS_TYPE_FATFS,
    244                                   INODE_TYPE_DIR,
    245                                   0,                // attr
    246                                   0,                // rights
    247                                   0,                // uid
    248                                   0,                // gid
    249                                   &root_inode_xp );
    250 
    251         assert( (error == 0 ) , __FUNCTION__ , "cannot create VFS root inode" );
    252 
    253         // initialize VFS context / access device to initialize FATFS context
    254         error = fatfs_ctx_init( vfs_ctx,
    255                                 fatfs_ctx,
    256                                 root_inode_xp );
    257 
    258         // create FATFS root inode
    259         error = fatfs_inode_create( GET_PTR( root_inode_xp ) ,
    260                                     fatfs_ctx->root_dir_cluster );
    261 
    262         if( error )
    263         {
    264             printk("\n[PANIC] in %s : cannot create FATFS root inode\n", __FUNCTION__ );
    265             hal_core_sleep();
    266         }
    267 
    268     }
    269 
    270     //////////////// synchronize all clusters
    271     remote_barrier( barrier_xp , nb_clusters );
    272 
    273     ///// step 3 : all others clusters initialize both context and extension
    274 
    275     if( local_cxy != 0 )
    276     {
    277         // copy VFS context from remote cluster_0 to local cluster
    278         hal_remote_memcpy( XPTR( local_cxy , vfs_ctx ),
    279                            XPTR( 0 , vfs_ctx ),
    280                            sizeof(vfs_ctx_t) );
    281 
    282         // copy FATFS context from remote cluster_0 to local cluster
    283         hal_remote_memcpy( XPTR( local_cxy , fatfs_ctx ),
    284                            XPTR( 0 , vfs_ctx->extend ) ,
    285                            sizeof(fatfs_ctx_t) );
    286 
    287         // update extend field in local copy of VFS context
    288         vfs_ctx->extend = fatfs_ctx;
    289     }
    290 
    291     return root_inode_xp;
    292 
    293 }  // end fatfs_init()
     220
     221        return (fatfs_ctx_t *)kmem_alloc( &req );
     222}
    294223
    295224//////////////////////////////////////////////
    296 error_t fatfs_ctx_init( vfs_ctx_t   * vfs_ctx,
    297                         fatfs_ctx_t * fatfs_ctx,
    298                         xptr_t        root_inode_xp )
    299 {
    300     error_t     error;
    301     uint8_t   * buffer;
    302     kmem_req_t  req;
     225void fatfs_ctx_init( fatfs_ctx_t * fatfs_ctx )
     226{
     227    error_t       error;
     228    kmem_req_t    req;
     229    uint8_t     * buffer;
     230
     231    fatfs_dmsg("\n[INFO] %s : enters at cycle %d\n",
     232               __FUNCTION__ , hal_get_cycles() );
     233
     234    // allocate memory for FATFS context
     235        req.type    = KMEM_FATFS_CTX;
     236        req.size    = sizeof(fatfs_ctx_t);
     237    req.flags   = AF_KERNEL | AF_ZERO;
     238
     239        fatfs_ctx = (fatfs_ctx_t *)kmem_alloc( &req );
     240
     241    nolock_assert( (fatfs_ctx != NULL) , __FUNCTION__ ,
     242                   "cannot allocate memory for FATFS context\n" );
    303243
    304244    // allocate a 512 bytes buffer to store the boot record
     
    306246    req.flags   = AF_KERNEL | AF_ZERO;
    307247        buffer      = (uint8_t *)kmem_alloc( &req );
     248
     249    nolock_assert( (buffer != NULL) , __FUNCTION__ ,
     250                   "cannot allocate memory for 512 bytes buffer\n" );
    308251     
    309     fatfs_dmsg("\n[INFO] %s : enters with buffer = %x\n",
    310                __FUNCTION__ , (intptr_t)buffer );
    311 
    312252    // load the boot record from device
    313253    // using a synchronous access to IOC device 
    314254    error = dev_ioc_sync_read( buffer , 0 , 1 );
    315255
    316     assert( (error == 0) , __FUNCTION__ , "cannot access boot record" );
     256    nolock_assert( (error == 0) , __FUNCTION__ ,
     257                   "cannot access boot record\n" );
    317258
    318259#if CONFIG_FATFS_DEBUG
     
    336277    uint32_t sector_size = get_record_from_buffer( BPB_BYTSPERSEC , buffer , 1 );
    337278
    338     assert( (sector_size == 512) , __FUNCTION__ , "sector size must be 512 bytes" );
     279    nolock_assert( (sector_size == 512) , __FUNCTION__ ,
     280                   "sector size must be 512 bytes\n" );
    339281
    340282    // check cluster size from boot record
    341283    uint32_t nb_sectors = get_record_from_buffer( BPB_SECPERCLUS , buffer , 1 );
    342284
    343     assert( (nb_sectors == 8) , __FUNCTION__ , "cluster size must be 8 sectors" );
     285    nolock_assert( (nb_sectors == 8) , __FUNCTION__ ,
     286                   "cluster size must be 8 sectors\n" );
    344287
    345288    // check number of FAT copies from boot record
    346289    uint32_t nb_fats = get_record_from_buffer( BPB_NUMFATS , buffer , 1 );
    347290
    348     assert( (nb_fats == 1) , __FUNCTION__ , "number of FAT copies must be 1" );
     291    nolock_assert( (nb_fats == 1) , __FUNCTION__ ,
     292                   "number of FAT copies must be 1\n" );
    349293
    350294    // get & check number of sectors in FAT from boot record
    351295    uint32_t fat_sectors = get_record_from_buffer( BPB_FAT32_FATSZ32 , buffer , 1 );
    352296
    353     assert( ((fat_sectors & 0xF) == 0) , __FUNCTION__ , "FAT not multiple of 16 sectors");
     297    nolock_assert( ((fat_sectors & 0xF) == 0) , __FUNCTION__ ,
     298                   "FAT not multiple of 16 sectors\n");
    354299
    355300    // get and check root cluster from boot record
    356301    uint32_t root_cluster = get_record_from_buffer( BPB_FAT32_ROOTCLUS , buffer , 1 );
    357302
    358     assert( (root_cluster == 2) , __FUNCTION__ , "Root cluster index must be  2");
     303    nolock_assert( (root_cluster == 2) , __FUNCTION__ ,
     304                   "root cluster index must be  2\n");
    359305
    360306    // get FAT lba from boot record
     
    375321    fatfs_ctx->fat_sectors_count     = fat_sectors;
    376322    fatfs_ctx->bytes_per_sector      = sector_size;
    377     fatfs_ctx->bytes_per_cluster     = sector_size * nb_sectors;
     323    fatfs_ctx->sectors_per_cluster   = nb_sectors;
    378324    fatfs_ctx->cluster_begin_lba     = fat_lba + fat_sectors;
    379325    fatfs_ctx->root_dir_cluster      = 2;
     
    396342               fatfs_ctx->fat_mapper_xp );
    397343
    398     // initialize the VFS context
    399     vfs_ctx->type    = FS_TYPE_FATFS;
    400     vfs_ctx->attr    = 0;                    // not READ_ONLY / not SYNC
    401     vfs_ctx->count   = fat_sectors << 10;    // total number of sectors in data region
    402     vfs_ctx->blksize = 512;                  // number of bytes per sector
    403     vfs_ctx->root_xp = root_inode_xp;
    404     vfs_ctx->extend  = fatfs_ctx;
    405 
    406     spinlock_init( &vfs_ctx->lock );
    407 
    408     bitmap_init( vfs_ctx->bitmap , CONFIG_VFS_MAX_INODES );
    409 
    410     return 0;
    411 
    412344}  // end fatfs_ctx_init()
    413  
    414 
    415 
    416 ////////////////////////////////////////////////////
    417 void fatfs_ctx_destroy( struct vfs_ctx_s * vfs_ctx )
     345
     346/////////////////////////////////////////////////
     347void fatfs_ctx_destroy( fatfs_ctx_t * fatfs_ctx )
    418348{
    419349    kmem_req_t    req;
    420     fatfs_ctx_t * fatfs_ctx;
    421 
    422     // get pointer on FATFS context extension
    423     fatfs_ctx = (fatfs_ctx_t *)vfs_ctx->extend;
    424 
    425     req.type = KMEM_FATFS_INODE;
     350    req.type = KMEM_FATFS_CTX;
    426351    req.ptr  = fatfs_ctx;
    427352    kmem_free( &req );
    428353}
    429 
    430 
    431 ////////////////////////////////////////////////////
    432 error_t fatfs_inode_create( vfs_inode_t * vfs_inode,
    433                             uint32_t      first_cluster )
    434 {
    435     kmem_req_t      req;
    436     fatfs_inode_t * fatfs_inode;
    437 
    438     // allocate memory for FATFS inode extension
    439         req.type    = KMEM_FATFS_INODE;
    440         req.size    = sizeof(fatfs_inode_t);
    441     req.flags   = AF_KERNEL | AF_ZERO;
    442         fatfs_inode = (fatfs_inode_t *)kmem_alloc( &req );
    443 
    444     if( fatfs_inode == NULL ) return ENOMEM;
    445 
    446     // link FATFS inode to VFS inode
    447     vfs_inode->extend = fatfs_inode;
    448 
    449     // initialise FATFS inode
    450     fatfs_inode->first_cluster = first_cluster;
    451  
    452     return 0;
    453 }
    454 
    455 ///////////////////////////////////////////////////
    456 void fatfs_inode_destroy( vfs_inode_t * vfs_inode )
    457 {
    458     kmem_req_t      req;
    459     fatfs_inode_t * fatfs_inode;
    460 
    461     // get pointer on FATFS inode
    462     fatfs_inode = (fatfs_inode_t *)vfs_inode->extend;
    463 
    464     req.type = KMEM_FATFS_INODE;
    465     req.ptr  = fatfs_inode;
    466     kmem_free( &req );
    467 
    468         vfs_inode->extend = NULL;
    469 }
    470 
    471354
    472355////////////////////////////////////////////////
     
    484367    vfs_inode_t * vfs_inode = mapper->inode;
    485368
    486     // get FATFS inode pointer for VFS inode
    487     fatfs_inode_t * fatfs_inode = (fatfs_inode_t *)vfs_inode->extend;
    488 
    489     // get first cluster index from FATFS inode
    490     uint32_t  first_cluster = fatfs_inode->first_cluster;
    491 
    492     // get FATFS context pointer from FATFS inode
    493     fatfs_ctx_t * fatfs_ctx = (fatfs_ctx_t *)vfs_inode->ctx->extend;
     369    // get first cluster index from VFS inode
     370    uint32_t  first_cluster = (uint32_t)(intptr_t)vfs_inode->extend;
     371
     372    // get FATFS context pointer from VFS context
     373    fatfs_ctx_t * fatfs_ctx = (fatfs_ctx_t *)fs_context[FS_TYPE_FATFS].extend;
    494374
    495375    // get number of sectors
  • trunk/kernel/vfs/fatfs.h

    r23 r188  
    160160typedef struct fatfs_ctx_s
    161161{
     162    uint32_t          fat_sectors_count;     /*! number of sectors in FAT region        */
     163    uint32_t          bytes_per_sector;      /*! number of bytes per sector             */
     164    uint32_t          sectors_per_cluster;   /*! number of sectors per cluster          */
    162165    uint32_t          fat_begin_lba;         /*! lba of FAT region                      */
    163     uint32_t          fat_sectors_count;     /*! number of sectors in FAT region        */
    164     uint32_t          bytes_per_sector;      /*!                                        */
    165     uint32_t          bytes_per_cluster;     /*!                                        */
    166166    uint32_t          cluster_begin_lba;     /*! lba of data region                     */
    167     uint32_t          sectors_per_cluster;   /*! cluster index for root directory       */
    168     uint32_t          root_dir_cluster;      /*!                                        */
     167    uint32_t          root_dir_cluster;      /*! cluster index for the root directory   */
    169168    uint32_t          last_allocated_sector; /*! TODO ???                               */
    170169    uint32_t          last_allocated_index;  /*! TODO ???                               */
     
    173172fatfs_ctx_t;
    174173
    175 /*****************************************************************************************
    176  * This structure defines the FATFS specific inode (extension to VFS inode).
    177  ****************************************************************************************/
    178 
    179 typedef struct fatfs_inode_s
    180 {
    181         uint32_t          first_cluster;         /*! first cluster for this file/dir        */
    182 }
    183 fatfs_inode_t;
    184 
    185 
    186 
    187 
    188174//////////////////////////////////////////////////////////////////////////////////////////
    189 // These functions are specific to the FATFS, and cannot be called by the VFS.
     175// Generic API: These functions are called by the kernel,
     176//              and must be implemented by all File Systems.
    190177//////////////////////////////////////////////////////////////////////////////////////////
    191178
    192 /*****************************************************************************************
    193  * This function returns the LBA of the first sector of a FAT cluster.
    194  * This function can be called by any thread running in any cluster.
    195  *****************************************************************************************
    196  * @ ctx          :     pointer on FATFS context.
    197  * @ cluster  : cluster index in FATFS.
    198  * @ return the lba value.
    199  ****************************************************************************************/
    200 inline uint32_t fatfs_lba_from_cluster( fatfs_ctx_t * ctx,
    201                                         uint32_t      cluster );
     179/******************************************************************************************
     180 * This fuction allocates memory from local cluster for a FATFS context descriptor.
     181 ******************************************************************************************
     182 * @ return a pointer on the created context / return NULL if failure.
     183 *****************************************************************************************/
     184fatfs_ctx_t * fatfs_ctx_alloc();
     185
     186/*****************************************************************************************
     187 * This function access the external boot device, and initialises it
     188 * from informations contained in the boot record.
     189 *****************************************************************************************
     190 * @ vfs_ctx   : local pointer on VFS context for FATFS.
     191 ****************************************************************************************/
     192void fatfs_ctx_init( fatfs_ctx_t * fatfs_ctx );
     193
     194/*****************************************************************************************
     195 * This function releases memory dynamically allocated for the FATFS context extension.
     196 *****************************************************************************************
     197 * @ vfs_ctx   : local pointer on VFS context.
     198 ****************************************************************************************/
     199void fatfs_ctx_destroy( fatfs_ctx_t * fatfs_ctx );
     200
     201/*****************************************************************************************
     202 * This function moves a page from the mapper to the FATFS file system on device.
     203 * It must be called by a thread running in cluster containing the mapper.
     204 * The pointer on the mapper and the page index in file are registered
     205 * in the page descriptor.
     206 *****************************************************************************************
     207 * @ page    : local pointer on page descriptor.
     208 * @ return 0 if success / return EIO if error.
     209 ****************************************************************************************/
     210error_t fatfs_write_page( struct page_s * page );
     211
     212/*****************************************************************************************
     213 * This function moves a page from the FATFS file system on device to the mapper.
     214 * It must be called by a thread running in cluster containing the mapper.
     215 * The pointer on the mapper and the page index in file are registered
     216 * in the page descriptor.
     217 *****************************************************************************************
     218 * @ page    : local pointer on page descriptor.
     219 * @ return 0 if success / return EIO if error.
     220 ****************************************************************************************/
     221error_t fatfs_read_page( struct page_s * page );
    202222
    203223/*****************************************************************************************
     
    214234 * automatically updates the FAT mapper from informations stored on device in case of miss.
    215235 *****************************************************************************************
    216  * @ mapper      : local pointer on the FAT mapper.
    217  * @ first       : index of the first FATFS cluster allocated to the file.
    218  * @ page    : index of searched page in the file.
    219  * @ cluster : [out] pointer on buffer for the found FATFS cluster index.
     236 * @ mapper              : local pointer on the FAT mapper.
     237 * @ first_cluster       : index of the first FATFS cluster allocated to the file.
     238 * @ searched_page   : index of searched page in the file.
     239 * @ cluster         : [out] pointer on buffer for the found FATFS cluster index.
    220240 * @ return 0 if success / return EIO if FAT mapper miss cannot be solved.
    221241 ****************************************************************************************/
     
    223243                           uint32_t          first_cluster,
    224244                           uint32_t          searched_page,
    225                            uint32_t        * cluster );
    226 
    227 
    228 
    229 
    230 //////////////////////////////////////////////////////////////////////////////////////////
    231 // These functions are called by the VFS, and must be implemented by all File Systems.
    232 //////////////////////////////////////////////////////////////////////////////////////////
    233 
    234 /******************************************************************************************
    235  * This function initializes the FATFS file system as the root FS.
    236  * It is executed cooperatively during kernel init by all CP0s in all clusters.
    237  * The initilisation is made in three phases, separated by synchronisation barrier:     
    238  * - phase 1 : all CP0s in all clusters allocate memory for the local copy of
    239  *   the FATFS context.
    240  * - phase 2 : cluster_0 only creates the root inode descriptor, access the external
    241  *   device to get information stored on the boot record, and initialises both
    242  *   the VFS context, and the FATFS context.
    243  * - phase 3 : all other clusters initialize their local VFS context and FATFS context
    244  *   from values contained in cluster_0, using hal_remote_memcpy().
    245  ******************************************************************************************
    246  * @ return an extended pointer on the created root inode / return XPTR_NULL if failure.
    247  *****************************************************************************************/
    248 xptr_t fatfs_init();
    249 
    250 /******************************************************************************************
    251  * This function mount the FATFS on the root FS.
    252  * TODO not implemented [AG]
    253  ******************************************************************************************
    254  * @ parent_inode_xp : extended pointer on the parent inode.
    255  *****************************************************************************************/
    256 error_t fatfs_mount( xptr_t parent_inode_xp );
    257 
    258 
    259 /*****************************************************************************************
    260  * This function  initializes both the VFS context and the FATFS context.
    261  * Both the VFS context and the FATFS context must have been previously allocated.
    262  * It access the device to read the boot record, and is supposed to be called only
    263  * in cluster_0 (in other clusters these contexts are replicated from values
    264  * contained in cluster_0).
    265  *****************************************************************************************
    266  * @ vfs_ctx        : local pointer on VFS context for FATFS.
    267  * @ fatfs_ctx      : local pointer on specific FATFS context.
    268  * @ root_inode_xp  : extended pointer on VFS root inode.
    269  ****************************************************************************************/
    270 error_t fatfs_ctx_init( struct vfs_ctx_s   * vfs_ctx,
    271                         struct fatfs_ctx_s * fatfs_ctx,
    272                         xptr_t               root_inode_xp );
    273 
    274 /*****************************************************************************************
    275  * This function releases memory dynamically allocated for the FATFS context extension.
    276  *****************************************************************************************
    277  * @ vfs_ctx   : local pointer on VFS context.
    278  ****************************************************************************************/
    279 void fatfs_ctx_destroy( struct vfs_ctx_s * vfs_ctx );
    280 
    281 
    282 
    283 /*****************************************************************************************
    284  * This function allocates memory for a FATFS inode, initializes it,
    285  * and link it to the VFS inode.
    286  *****************************************************************************************
    287  * @ inode         : local pointer on the VFS inode.
    288  * @ first_cluster : first cluster index in the FAT32.
    289  * @ return 0 if success / return ENOMEM if error.
    290  ****************************************************************************************/
    291 error_t fatfs_inode_create( struct vfs_inode_s * inode,
    292                             uint32_t             first_cluster);
    293 
    294 /*****************************************************************************************
    295  * This function releases memory allocated for a FATFS inode.
    296  *****************************************************************************************
    297  * @ inode   : local pointer on vfs_inode.
    298  ****************************************************************************************/
    299 void fatfs_inode_destroy( struct vfs_inode_s * inode );
    300 
    301 
    302 
    303 /*****************************************************************************************
    304  * This function moves a page from the mapper to the FATFS file system on device.
    305  * It must be called by a thread running in cluster containing the mapper.
    306  * The pointer on the mapper and the page index in file are registered
    307  * in the page descriptor.
    308  *****************************************************************************************
    309  * @ page    : local pointer on page descriptor.
    310  * @ return 0 if success / return EIO if error.
    311  ****************************************************************************************/
    312 error_t fatfs_write_page( struct page_s * page );
    313 
    314 /*****************************************************************************************
    315  * This function moves a page from the FATFS file system on device to the mapper.
    316  * It must be called by a thread running in cluster containing the mapper.
    317  * The pointer on the mapper and the page index in file are registered
    318  * in the page descriptor.
    319  *****************************************************************************************
    320  * @ page    : local pointer on page descriptor.
    321  * @ return 0 if success / return EIO if error.
    322  ****************************************************************************************/
    323 error_t fatfs_read_page( struct page_s * page );
    324 
    325 
    326 
     245                           uint32_t *        cluster );
    327246
    328247#endif  /* _FATFS_H_ */
  • trunk/kernel/vfs/ramfs.c

    r23 r188  
    3232
    3333
    34 
    35 
    36 
    37 ///////////////////////////////////////////////////////////////////////////////////////
    38 //             The following functions are called by the VFS.
    39 ///////////////////////////////////////////////////////////////////////////////////////
    40 
    4134//////////////////////////////////////////////
    4235error_t ramfs_mount( xptr_t   parent_inode_xp,
    4336                     char   * ramfs_root_name )
    4437{
    45     xptr_t        root_inode_xp;   // unused                     
     38    xptr_t    root_inode_xp;   // unused                     
    4639 
     40    cxy_t     cxy = vfs_cluster_random_select();
     41
    4742    // create VFS dentry and VFS inode for RAMFS root directory
    48     return  vfs_add_child_in_parent( INODE_TYPE_DIR,
     43    return  vfs_add_child_in_parent( cxy,
     44                                     INODE_TYPE_DIR,
    4945                                     FS_TYPE_RAMFS,
    5046                                     parent_inode_xp,
    5147                                     ramfs_root_name,
     48                                     NULL,
    5249                                     &root_inode_xp );
    5350}
    5451
    55 
    56 ////////////////////////////////////////////
    57 error_t ramfs_ctx_init( vfs_ctx_t * vfs_ctx,
    58                         xptr_t      root_inode_xp )
    59 
    60 {
    61     vfs_ctx->type    = FS_TYPE_RAMFS;
    62     vfs_ctx->attr    = 0;                // not READ_ONLY / not SYNC
    63     vfs_ctx->count   = 0;                // unused for RAMFS
    64     vfs_ctx->blksize = 512;              // unused for RAMFS
    65     vfs_ctx->root_xp = root_inode_xp;
    66     vfs_ctx->extend  = NULL;             // unused for DEVFS
    67 
    68     spinlock_init( &vfs_ctx->lock );
    69 
    70     bitmap_init( vfs_ctx->bitmap , CONFIG_VFS_MAX_INODES );
    71 
    72     return 0;
    73 }
    74 
  • trunk/kernel/vfs/ramfs.h

    r23 r188  
    2727
    2828///////////////////////////////////////////////////////////////////////////////////////////
    29 // The RAMFS File System Rdoes not uses any external device to store data.
     29// The RAMFS File System does not uses any external device to store data.
    3030// It stores the dynamically created files and directories in the VFS mappers.
    3131// The ramfs_read_page() and ramfs_write_page() functions should never be used.
    32 // The RAMFS cannot be used as the root FS.
     32// The RAMFS cannot be used as the root File System.
     33//
    3334// There is no RAMFS context extension, and no RAMFS inode extension.
    3435///////////////////////////////////////////////////////////////////////////////////////////
    3536
    3637
    37 /****  Forward declarations  ****/
    38 
    39 
    40 //////////////////////////////////////////////////////////////////////////////////////////
    41 // These functions are called by the VFS, and must be implemented by all FS.
    42 //////////////////////////////////////////////////////////////////////////////////////////
    43 
    44 /******************************************************************************************
    45  * This function does not exist, as the RAMFS cannot be the root FS.
    46  *****************************************************************************************/
    47 xptr_t ramfs_init();
    4838
    4939/******************************************************************************************
     
    5242 * and create a new VFS inode in another cluster.
    5343 ******************************************************************************************
    54  * @ parent_inode_xp : extended pointer on the parent inode.
     44 * @ parent_inode_xp : extended pointer on the parent inode in VFS.
    5545 * @ ramfs_root_name : RAMFS root directory name.
    5646 *****************************************************************************************/
     
    5848                     char   * ramfs_root_name );
    5949
    60 /*****************************************************************************************
    61  * This function initializes all fields of the VFS context.
    62  * No extra memory is allocated for a RAMFS context.
    63  ****************************************************************************************/
    64 error_t ramfs_ctx_init( struct vfs_ctx_s * vfs_ctx,
    65                         xptr_t             root_inode_xp );
    66 
    67 /*****************************************************************************************
    68  * This function does not exist for a RAMFS context, as there is no RAMFS context.
    69  ****************************************************************************************/
    70 error_t ramfs_ctx_destroy();
    71 
    72 /*****************************************************************************************
    73  * This function does not exist, as the RAMFS does not use a RAMFS inode extension.
    74  ****************************************************************************************/
    75 error_t ramfs_inode_create( struct vfs_inode_s * inode );
    76 
    77 /*****************************************************************************************
    78  * This function does not exist, as the RAMFS does not use a RAMFS inode extension.
    79  ****************************************************************************************/
    80 void ramfs_inode_destroy( struct vfs_inode_s * inode );
    81 
    82 /*****************************************************************************************
    83  * This function does nothing for the RAMFS File System.
    84  ****************************************************************************************/
    85 error_t ramfs_write_page( struct page_s * page );
    86 
    87 /*****************************************************************************************
    88  * This function does not exist for the RAMFS File System.
    89  ****************************************************************************************/
    90 error_t ramfs_read_page( struct page_s * page );
    91 
    92 
    9350#endif  /* _RAMFS_H_ */
  • trunk/kernel/vfs/vfs.c

    r124 r188  
    5252//////////////////////////////////////////////////////////////////////////////////////////
    5353
    54 extern vfs_ctx_t   fs_context[FS_TYPES_NR];    // allocate in kernel_init.c
     54extern vfs_ctx_t   fs_context[FS_TYPES_NR];    // allocated in kernel_init.c
     55
    5556 
    5657//////////////////////////////////////////////////////////////////////////////////////////
    5758//           Context related functions
    5859//////////////////////////////////////////////////////////////////////////////////////////
     60
     61////////////////////////////////////////
     62void vfs_ctx_init( vfs_fs_type_t   type,
     63                   uint32_t        attr,
     64                       uint32_t        total_clusters,
     65                       uint32_t        cluster_size,
     66                       xptr_t          vfs_root_xp,
     67                   void          * extend )
     68{
     69    vfs_ctx_t * vfs_ctx = &fs_context[type];
     70
     71    vfs_ctx->type           = type;
     72    vfs_ctx->attr           = attr;
     73    vfs_ctx->total_clusters = total_clusters;
     74    vfs_ctx->cluster_size   = cluster_size;
     75    vfs_ctx->vfs_root_xp    = vfs_root_xp;
     76    vfs_ctx->extend         = extend;
     77
     78    spinlock_init( &vfs_ctx->lock );
     79
     80    bitmap_init( vfs_ctx->bitmap , BITMAP_SIZE(CONFIG_VFS_MAX_INODES) );
     81}
    5982
    6083////////////////////////////////////////////
     
    101124//////////////////////////////////////////////////////////////////////////////////////////
    102125
     126char * vfs_inode_type_str( uint32_t type )
     127{
     128    if     ( type == INODE_TYPE_FILE ) return "FILE";
     129    else if( type == INODE_TYPE_DIR  ) return "DIR ";
     130    else if( type == INODE_TYPE_FIFO ) return "FIFO";
     131    else if( type == INODE_TYPE_PIPE ) return "PIPE";
     132    else if( type == INODE_TYPE_SOCK ) return "SOCK";
     133    else if( type == INODE_TYPE_DEV  ) return "DEV ";
     134    else if( type == INODE_TYPE_SYML ) return "SYML";
     135    else                               return "undefined";
     136}
     137
    103138//////////////////////////////////////////////////////
    104 
    105139error_t vfs_inode_create( xptr_t            dentry_xp,
    106140                          vfs_fs_type_t     fs_type,
    107141                          vfs_inode_type_t  inode_type,
     142                          void            * extend,
    108143                          uint32_t          attr,
    109144                          uint32_t          rights,
     
    175210    inode->ctx        = ctx;
    176211    inode->mapper     = NULL; 
     212    inode->extend     = extend;
    177213
    178214    // initialise threads waiting queue
     
    307343        kmem_req_t       req;        // request to kernel memory allocator
    308344
    309     // check type and get pointer on context
     345    // get pointer on context
    310346    if     ( fs_type == FS_TYPE_FATFS ) ctx = &fs_context[FS_TYPE_FATFS];
    311347    else if( fs_type == FS_TYPE_RAMFS ) ctx = &fs_context[FS_TYPE_RAMFS];
     
    349385    xhtab_insert( XPTR( local_cxy , &parent->children ),
    350386                  name,
    351                   XPTR( local_cxy , &dentry->xlist ) );
     387                  XPTR( local_cxy , &dentry->list ) );
    352388
    353389    // return extended pointer on dentry
     
    372408        kmem_free( &req );
    373409}
     410
    374411
    375412
     
    797834
    798835
    799 /////////////////////////////////////////////////////////////////////////////////////////r
     836//////////////////////////////////////////////////////////////////////////////////////////
    800837//            Inode Tree functions
    801838//////////////////////////////////////////////////////////////////////////////////////////
     839
     840/////////////////////////////////
     841cxy_t vfs_cluster_random_select()
     842{
     843    uint32_t  x_size    = LOCAL_CLUSTER->x_size;
     844    uint32_t  y_size    = LOCAL_CLUSTER->y_size;
     845    uint32_t  y_width   = LOCAL_CLUSTER->y_width;
     846    uint32_t  index     = ( hal_get_cycles() + hal_get_gid() ) % (x_size * y_size);
     847    uint32_t  x         = index / y_size;   
     848    uint32_t  y         = index % y_size;
     849
     850    return (x<<y_width) + y;
     851}
     852
     853
     854//////////////////////////////////////////////////////////////////////////
     855// This static function is called by the vfs_display() function.
     856//////////////////////////////////////////////////////////////////////////
     857static void vfs_recursive_display( xptr_t   inode_xp,
     858                                   xptr_t   name_xp,
     859                                   uint32_t indent )
     860{
     861    cxy_t              inode_cxy;
     862    vfs_inode_t      * inode_ptr;
     863    vfs_inode_type_t   inode_type;
     864    xptr_t             inode_children_xp;    // extended pointer on children xhtab
     865
     866    xptr_t             dentry_xp;
     867    cxy_t              dentry_cxy;
     868    vfs_dentry_t     * dentry_ptr;
     869
     870    char               name[CONFIG_VFS_MAX_NAME_LENGTH];
     871
     872    xptr_t             child_inode_xp;
     873    xptr_t             dentry_name_xp;
     874
     875    char *             indent_str[] = { "",                                  // level 0
     876                                        "  ",                                // level 1
     877                                        "    ",                              // level 2
     878                                        "      ",                            // level 3
     879                                        "        ",                          // level 4
     880                                        "          ",                        // level 5
     881                                        "            ",                      // level 6
     882                                        "              ",                    // level 7
     883                                        "                ",                  // level 8
     884                                        "                  ",                // level 9
     885                                        "                    ",              // level 10
     886                                        "                      ",            // level 11
     887                                        "                        ",          // level 12
     888                                        "                          ",        // level 13
     889                                        "                            ",      // level 14
     890                                        "                              " };  // level 15
     891
     892    assert( (inode_xp != XPTR_NULL) , __FUNCTION__ , "inode_xp cannot be NULL\n" );
     893    assert( (name_xp  != XPTR_NULL) , __FUNCTION__ , "name_xp cannot be NULL\n" );
     894    assert( (indent < 16)           , __FUNCTION__ , "depth cannot be larger than 15\n" );
     895   
     896    // get inode cluster and local pointer
     897    inode_cxy = GET_CXY( inode_xp );
     898    inode_ptr = (vfs_inode_t *)GET_PTR( inode_xp );
     899
     900    // get inode type
     901    inode_type = hal_remote_lw( XPTR( inode_cxy , &inode_ptr->type ) );
     902
     903    // make a local copy of node name
     904    hal_remote_strcpy( XPTR( local_cxy , name ) , name_xp );
     905
     906    // display inode
     907    printk(" %s %s : %s\n", indent_str[indent], vfs_inode_type_str( inode_type ), name );
     908
     909    // scan directory entries 
     910    if( inode_type == INODE_TYPE_DIR )
     911    {
     912        // get extended pointer on directory entries xhtab
     913        inode_children_xp = hal_remote_lwd( XPTR( inode_cxy , &inode_ptr->children ) );
     914
     915        // get xhtab lock
     916        xhtab_read_lock( inode_children_xp );
     917
     918        // get first dentry from xhtab
     919        dentry_xp = xhtab_get_first( inode_children_xp );
     920
     921        while( dentry_xp != XPTR_NULL )
     922        {
     923            // get dentry cluster and local pointer
     924            dentry_cxy = GET_CXY( dentry_xp );
     925            dentry_ptr = (vfs_dentry_t *)GET_PTR( dentry_xp );
     926
     927            // get extended pointer on child inode
     928            child_inode_xp = hal_remote_lwd( XPTR( dentry_cxy , &dentry_ptr->child_xp ) );
     929
     930            // get extended pointer on dentry name
     931            dentry_name_xp = XPTR( dentry_cxy , &dentry_ptr->name );
     932
     933            // recursive call on child inode
     934            vfs_recursive_display( child_inode_xp , dentry_name_xp , indent+1 );
     935
     936            // get next dentry
     937            dentry_xp = xhtab_get_next( inode_children_xp );
     938        }
     939
     940        // release xhtab lock
     941        xhtab_read_unlock( inode_children_xp );
     942    }
     943}  // end vfs_recursive_display()
     944
     945///////////////////////////////////
     946void vfs_display( xptr_t inode_xp )
     947{
     948    xptr_t         name_xp;      // extended pointer on string containing the inode name
     949    xptr_t         dentry_xp;
     950    cxy_t          dentry_cxy;
     951    vfs_dentry_t * dentry_ptr;
     952
     953printk("\n@@@ %s enters\n", __FUNCTION__ );
     954
     955    // get target inode cluster and local pointer
     956    cxy_t         inode_cxy = GET_CXY( inode_xp );
     957    vfs_inode_t * inode_ptr = (vfs_inode_t *)GET_PTR( inode_xp );
     958
     959    // get extended pointer on associated dentry
     960    dentry_xp = hal_remote_lwd( XPTR( inode_cxy , &inode_ptr->parent_xp ) );
     961
     962    // check if target inode is the File System root
     963    if( dentry_xp == XPTR_NULL )
     964    {
     965        // build extended pointer on root name
     966        name_xp = XPTR( local_cxy , "/" );
     967    }
     968    else
     969    {
     970        // get dentry cluster and local pointer
     971        dentry_cxy = GET_CXY( dentry_xp );
     972        dentry_ptr = (vfs_dentry_t *)GET_PTR( dentry_xp );
     973
     974        // get extended pointer on dentry name
     975        name_xp = XPTR( dentry_cxy , &dentry_ptr->name );
     976    }
     977
     978    // print header
     979    printk("\n*** Current VFS content ***\n");
     980
     981    // call recursive function
     982    vfs_recursive_display( inode_xp , name_xp , 0 );
     983
     984}  // end vfs_diplay()
    802985
    803986//////////////////////////////////////////////////////////////////////////////////////////
     
    9131096    return 0;
    9141097}
    915 
     1098   
    9161099//////////////////////////////////////////////
    9171100error_t vfs_lookup( xptr_t             cwd_xp,
     
    9931176            else                                             inode_type = INODE_TYPE_FILE;
    9941177
    995             // insert a child dentry/inode in parent inode
    996             error = vfs_add_child_in_parent( inode_type,
     1178            // select a cluster for child inode
     1179            cxy_t child_cxy = vfs_cluster_random_select();
     1180                     
     1181            // insert a new child dentry/inode in parent inode
     1182            error = vfs_add_child_in_parent( child_cxy,
     1183                                             inode_type,
    9971184                                             fs_type,
    9981185                                             parent_xp,
     1186                                             NULL,           // fs_type_specific inode extend
    9991187                                             name,
    10001188                                             &child_xp );
     
    10021190            if( error )
    10031191            {
    1004                 printk("\n[ERROR] in %s : inode %s not found in path %s\n",
     1192                printk("\n[ERROR] in %s : node %s not found in path %s\n",
    10051193                       __FUNCTION__ , name , pathname );
    10061194                return ENOENT;
     
    10241212        // }
    10251213
    1026 printk("\n@@@ bloup 0 : parent lock owner = %l / child lock owner = %l\n",
    1027        vfs_inode_owner( parent_xp ) , vfs_inode_owner( child_xp ) );
     1214        // TODO TODO TODO access device and load inode mapper if required...
    10281215
    10291216        // take lock on child inode if not last
    10301217        if( last == false ) vfs_inode_lock( child_xp );
    10311218
    1032 printk("\n@@@ bloup 1\n");
    1033 
    10341219        // release lock on parent inode
    10351220        vfs_inode_unlock( parent_xp );
    1036 
    1037 printk("\n@@@ bloup 2\n");
    10381221
    10391222        // update loop variables
     
    10601243
    10611244}  // end vfs_lookup()
    1062 
    10631245
    10641246////////////////////////////////////////////
     
    11311313}  // end vfs_get_path()
    11321314
    1133 ///////////////////////////////////////////////////////////////
    1134 error_t vfs_add_child_in_parent( vfs_inode_type_t   inode_type,
     1315     
     1316//////////////////////////////////////////////////////////////
     1317error_t vfs_add_child_in_parent( cxy_t              child_cxy,
     1318                                 vfs_inode_type_t   inode_type,
    11351319                                 vfs_fs_type_t      fs_type,
    11361320                                 xptr_t             parent_xp,
    11371321                                 char             * name,
     1322                                 void             * extend,
    11381323                                 xptr_t           * child_xp )
    11391324{
     
    11741359        printk("\n[ERROR] in %s : cannot create dentry in cluster %x\n",
    11751360               __FUNCTION__ , parent_cxy );
    1176 
    11771361        return error;
    11781362    }
    11791363
    1180     // select a target cluster for child inode
    1181     uint32_t  x_size    = LOCAL_CLUSTER->x_size;
    1182     uint32_t  y_size    = LOCAL_CLUSTER->y_size;
    1183     uint32_t  y_width   = LOCAL_CLUSTER->y_width;