Changeset 188 for trunk/kernel/devices


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

Redefine the PIC device API.

Location:
trunk/kernel/devices
Files:
10 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
Note: See TracChangeset for help on using the changeset viewer.