Ignore:
Timestamp:
Aug 13, 2012, 10:52:25 PM (12 years ago)
Author:
alain
Message:

Introducing support for XICU

File:
1 edited

Legend:

Unmodified
Added
Removed
  • soft/giet_vm/sys/drivers.c

    r199 r203  
    1111// - vci_multi_dma
    1212// - vci_multi_icu
    13 // - vci_xicu
     13// - vci_xicu & vci_multi_icu
    1414// - vci_gcd
    1515// - vci_frame_buffer
     
    2323// - NB_TTYS   
    2424//
    25 // The following base addresses must be defined in the sys.ld file:
     25// The following virtual base addresses must be defined in the sys.ld file:
    2626// - seg_icu_base
    27 // - seg_timer_base
     27// - seg_tim_base
    2828// - seg_tty_base
    2929// - seg_gcd_base
    3030// - seg_dma_base
    31 // - seg_fb_base
     31// - seg_fbf_base
    3232// - seg_ioc_base
    3333///////////////////////////////////////////////////////////////////////////////////
     
    9393#define in_unckdata __attribute__((section (".unckdata")))
    9494
    95 
    9695//////////////////////////////////////////////////////////////////////////////
    97 //      VciMultiTimer driver
     96//      Timers driver
    9897//////////////////////////////////////////////////////////////////////////////
    99 // There is one multi_timer (or xicu) component per cluster.
    100 // The global index is cluster_id*(NB_PROCS_MAX+NB_TIMERS_MAX) + local_id
     98// The timers can be implemented in a vci_timer component or in a vci_xicu
     99// component (depending on the GIET_USE_XICU parameter).
     100// There is one timer (or xicu) component per cluster.
    101101// There is two types of timers:
    102102// - "system" timers : one per processor, used for context switch.
    103103//   local_id in [0, NB_PROCS_MAX-1],
    104104// - "user" timers : requested by the task in the mapping_info data structure.
    105 //   local_id in [NB_PROC_MAX, NB_PROCS_MAX+NB_TIMERS_MAX-1],
    106 //   For each user timer, the tty_id is stored in the context of the task
    107 //   and must be explicitely defined in the boot code.
    108 // These timers can be implemented in a vci_multi_timer component
    109 // or in a vci_xicu component (depending on the GIET_USE_XICU parameter).
     105//   local_id in [NB_PROC_MAX, NB_PROCS_MAX + NB_TIMERS_MAX - 1]
     106//   For each user timer, the timer_id is stored in the context of the task.
     107// The global index is cluster_id * (NB_PROCS_MAX+NB_TIMERS_MAX) + local_id
    110108//////////////////////////////////////////////////////////////////////////////
    111109
     
    118116
    119117//////////////////////////////////////////////////////////////////////////////
    120 //     _timer_access()
    121 // This function is the only way to access a timer device.
    122 // It can be a multi-timer component or an xicu component.
    123 // It can be used by the kernel to initialise a "system" timer,
     118//     _timer_start()
     119// This function activates a timer in the vci_timer (or vci_xicu) component
     120// by writing in the proper register the period value.
     121// It can be used by both the kernel to initialise a "system" timer,
    124122// or by a task (through a system call) to configure an "user" timer.
    125123// Returns 0 if success, > 0 if error.
    126124//////////////////////////////////////////////////////////////////////////////
    127 unsigned int _timer_access( unsigned int        read,
    128                             unsigned int        cluster_id,
    129                             unsigned int        local_id,
    130                             unsigned int        register_id,
    131                             unsigned int*       buffer )
     125unsigned int _timer_start( unsigned int cluster_id,
     126                           unsigned int local_id,
     127                           unsigned int period )
    132128{
    133129    // parameters checking
    134     if ( register_id >= TIMER_SPAN)                                     return 1;
    135130    if ( cluster_id >= NB_CLUSTERS)                                     return 1;
    136131    if ( local_id >= NB_TIMERS_MAX + NB_PROCS_MAX ) return 1;
    137132
    138133#if GIET_USE_XICU
    139 
    140     unsigned int* timer_address = //TODO
    141 
     134    unsigned int* timer_address = (unsigned int*)&seg_icu_base +
     135                                  (cluster_id * CLUSTER_SPAN);
     136
     137    timer_address[XICU_REG(XICU_PTI_PER, local_id)] = period;
    142138#else
    143 
    144     unsigned int* timer_address = (unsigned int*)&seg_timer_base +
    145                                   (cluster_id * CLUSTER_SPAN)  +
    146                                   (local_id * TIMER_SPAN);
    147 #endif
    148 
    149     if (read)   *buffer = timer_address[register_id]; // read word
    150     else                timer_address[register_id] = *buffer; // write word
     139    unsigned int* timer_address = (unsigned int*)&seg_tim_base +
     140                                  (cluster_id * CLUSTER_SPAN);
     141
     142    timer_address[local_id * TIMER_SPAN + TIMER_PERIOD] = period;
     143    timer_address[local_id * TIMER_SPAN + TIMER_MODE]   = 0x3;
     144#endif
     145
    151146    return 0;
    152147}
    153148//////////////////////////////////////////////////////////////////////////////
    154 //     _timer_write()
    155 // This function implements a write access to a "user" timer register.
    156 // It gets the cluster_id and local_id from the global index stored in
    157 // the task context and use the timer_access() function to make the write.
     149//     _timer_stop()
     150// This function desactivates a timer in the vci_timer (or vci_xicu) component
     151// by writing in the proper register.
    158152// Returns 0 if success, > 0 if error.
    159153//////////////////////////////////////////////////////////////////////////////
    160 unsigned int _timer_write( unsigned int register_id,
    161                            unsigned int value )
    162 {
    163     unsigned int buffer     = value;
    164     unsigned int task_id    = _get_current_task_id();
    165     unsigned int timer_id   = _get_context_slot(task_id, CTX_TIMER_ID);
    166     unsigned int cluster_id = timer_id / (NB_PROCS_MAX + NB_TIMERS_MAX);
    167     unsigned int local_id   = timer_id % (NB_PROCS_MAX + NB_TIMERS_MAX);
    168 
    169     // checking user timer
    170     if ( local_id < NB_PROCS_MAX )
    171     {
    172         return 2;
    173     }
    174     else
    175     {
    176         return _timer_access ( 0,                               // write access
    177                                cluster_id,
    178                                local_id,
    179                                register_id,
    180                                &buffer );
    181     }
     154unsigned int _timer_stop( unsigned int  cluster_id,
     155                          unsigned int  local_id )
     156{
     157    // parameters checking
     158    if ( cluster_id >= NB_CLUSTERS)                                     return 1;
     159    if ( local_id >= NB_TIMERS_MAX + NB_PROCS_MAX ) return 1;
     160
     161#if GIET_USE_XICU
     162    unsigned int* timer_address = (unsigned int*)&seg_icu_base +
     163                                  (cluster_id * CLUSTER_SPAN);
     164
     165    timer_address[XICU_REG(XICU_PTI_PER, local_id)] = 0;
     166#else
     167    unsigned int* timer_address = (unsigned int*)&seg_tim_base +
     168                                  (cluster_id * CLUSTER_SPAN);
     169
     170    timer_address[local_id * TIMER_SPAN + TIMER_MODE] = 0;
     171#endif
     172
     173    return 0;
    182174}
    183175//////////////////////////////////////////////////////////////////////////////
    184 //     _timer_read()
    185 // This function implements a read access to a "user" timer register.
    186 // It gets the cluster_id and local_id from the global index stored in
    187 // the task context and use the timer_access() function to make the read.
     176//     _timer_reset_irq()
     177// This function acknowlegge a timer interrupt in the vci_timer (or vci_xicu)
     178// component by writing in the proper register the period value.
     179// It can be used by both the isr_switch() for a "system" timer,
     180// or by the _isr_timer() for an "user" timer.
    188181// Returns 0 if success, > 0 if error.
    189182//////////////////////////////////////////////////////////////////////////////
    190 unsigned int _timer_read( unsigned int  register_id,
    191                           unsigned int* buffer )
    192 {
    193     unsigned int task_id    = _get_current_task_id();
    194     unsigned int timer_id   = _get_context_slot(task_id, CTX_TIMER_ID);
    195     unsigned int cluster_id = timer_id / (NB_PROCS_MAX + NB_TIMERS_MAX);
    196     unsigned int local_id   = timer_id % (NB_PROCS_MAX + NB_TIMERS_MAX);
    197 
    198     // checking user timer
    199     if ( local_id < NB_PROCS_MAX )
    200     {
    201         return 2;
    202     }
    203     else
    204     {
    205         return _timer_access ( 1,                               // read access
    206                                cluster_id,
    207                                local_id,
    208                                register_id,
    209                                buffer );
    210     }
    211 }
    212 /////////////////////////////////////////////////////////////////////////////////
    213 //     _timer_check()
    214 /////////////////////////////////////////////////////////////////////////////////
     183unsigned int _timer_reset_irq( unsigned int     cluster_id,
     184                               unsigned int     local_id )
     185{
     186    // parameters checking
     187    if ( cluster_id >= NB_CLUSTERS)                                     return 1;
     188    if ( local_id >= NB_TIMERS_MAX + NB_PROCS_MAX ) return 1;
     189
     190#if GIET_USE_XICU
     191    unsigned int* timer_address = (unsigned int*)&seg_icu_base +
     192                                  (cluster_id * CLUSTER_SPAN);
     193
     194    unsigned int bloup = timer_address[XICU_REG(XICU_PTI_ACK, local_id)];
     195#else
     196    unsigned int* timer_address = (unsigned int*)&seg_tim_base +
     197                                  (cluster_id * CLUSTER_SPAN);
     198
     199    timer_address[local_id * TIMER_SPAN + TIMER_RESETIRQ] = 0;
     200#endif
     201
     202    return 0;
     203}
    215204
    216205/////////////////////////////////////////////////////////////////////////////////
     
    349338//      VciMultiIcu and VciXicu drivers
    350339////////////////////////////////////////////////////////////////////////////////
    351 // There is in principle one vci_multi_icu (or vci_xicu) component per cluster,
    352 // and the number of independant ICUs is equal to NB_PROCS_MAX, because there is
    353 // one private interrupr controler per processor.
    354 ////////////////////////////////////////////////////////////////////////////////
    355 
    356 ////////////////////////////////////////////////////////////////////////////////
    357 //     _icu_write()
    358 // Write a 32-bit word in a memory mapped register of the MULTI_ICU device,
    359 // identified by the cluster index, and a processor local index.
    360 // Returns 0 if success, > 0 if error.
    361 ////////////////////////////////////////////////////////////////////////////////
    362 unsigned int _icu_write( unsigned int cluster_index,
    363                          unsigned int proc_index,
    364                          unsigned int register_index,
    365                          unsigned int value )
    366 {
     340// There is one vci_multi_icu (or vci_xicu) component per cluster,
     341// and the number of independant ICUs is equal to NB_PROCS_MAX,
     342// because there is one private interrupr controler per processor.
     343////////////////////////////////////////////////////////////////////////////////
     344
     345////////////////////////////////////////////////////////////////////////////////
     346//     _icu_set_mask()
     347// This function can be used with both the vci_xicu & vci_multi_icu components.
     348// It set the mask register for the ICU channel identified by the cluster index
     349// and the processor index: all '1' bits are set / all '0' bits are not modified.
     350// Returns 0 if success, > 0 if error.
     351////////////////////////////////////////////////////////////////////////////////
     352unsigned int _icu_set_mask( unsigned int cluster_id,
     353                            unsigned int proc_id,
     354                            unsigned int value,
     355                            unsigned int is_timer )
     356{
     357    // parameters checking
     358    if ( cluster_id >= NB_CLUSTERS)             return 1;
     359    if ( proc_id    >= NB_PROCS_MAX )   return 1;
     360
     361    unsigned int* icu_address = (unsigned int*)&seg_icu_base +
     362                                (cluster_id * CLUSTER_SPAN);
    367363#if GIET_USE_XICU
    368 
     364    if ( is_timer ) icu_address[XICU_REG(XICU_MSK_PTI_ENABLE, proc_id)] = value;
     365    else            icu_address[XICU_REG(XICU_MSK_HWI_ENABLE, proc_id)] = value;
    369366#else
    370 
     367    icu_address[proc_id * ICU_SPAN + ICU_MASK_SET] = value;
     368#endif
     369
     370    return 0;
     371}
     372////////////////////////////////////////////////////////////////////////////////
     373//     _icu_get_index()
     374// This function can be used with both the vci_xicu & vci_multi_icu components.
     375// It returns the index of the highest priority (smaller index) active HWI.
     376// The ICU channel is identified by the cluster index and the processor index.
     377// Returns 0 if success, > 0 if error.
     378////////////////////////////////////////////////////////////////////////////////
     379unsigned int _icu_get_index(  unsigned int cluster_id,
     380                              unsigned int proc_id,
     381                              unsigned int* buffer )
     382{
    371383    // parameters checking
    372     if ( register_index >= ICU_SPAN)            return 1;
    373     if ( cluster_index >= NB_CLUSTERS)          return 1;
    374     if ( proc_index >= NB_PROCS_MAX )       return 1;
    375 
    376     unsigned int *icu_address = (unsigned int*)&seg_icu_base +
    377                                 (cluster_index * CLUSTER_SPAN)  +
    378                                 (proc_index * ICU_SPAN);
    379 
    380     icu_address[register_index] = value;   // write word
     384    if ( cluster_id >= NB_CLUSTERS)             return 1;
     385    if ( proc_id    >= NB_PROCS_MAX )   return 1;
     386
     387    unsigned int* icu_address = (unsigned int*)&seg_icu_base +
     388                                (cluster_id * CLUSTER_SPAN);
     389#if GIET_USE_XICU
     390    unsigned int prio   = icu_address[XICU_REG(XICU_PRIO, proc_id)];
     391    unsigned int pti_ok = (prio & 0x00000001);
     392    unsigned int hwi_ok = (prio & 0x00000002);
     393    unsigned int swi_ok = (prio & 0x00000004);
     394    unsigned int pti_id = (prio & 0x00001F00) >> 8;
     395    unsigned int hwi_id = (prio & 0x001F0000) >> 16;
     396    unsigned int swi_id = (prio & 0x1F000000) >> 24;
     397    if      (pti_ok)    *buffer = pti_id;
     398    else if (hwi_ok)    *buffer = hwi_id;
     399    else if (swi_ok)    *buffer = swi_id;
     400    else                *buffer = 32;
     401#else
     402    *buffer = icu_address[proc_id * ICU_SPAN + ICU_IT_VECTOR];
     403#endif
     404
    381405    return 0;
    382 
    383 #endif
    384 }
    385 ////////////////////////////////////////////////////////////////////////////////
    386 //     _icu_read()
    387 // Read a 32-bit word in a memory mapped register of the MULTI_ICU device,
    388 // identified by the cluster index and a processor local index.
    389 // Returns 0 if success, > 0 if error.
    390 ////////////////////////////////////////////////////////////////////////////////
    391 unsigned int _icu_read(  unsigned int cluster_index,
    392                          unsigned int proc_index,
    393                          unsigned int register_index,
    394                          unsigned int* buffer )
    395 {
    396 #if GIET_USE_XICU
    397 
    398 #else
    399 
    400     // parameters checking
    401     if ( register_index >= ICU_SPAN)            return 1;
    402     if ( cluster_index >= NB_CLUSTERS)          return 1;
    403     if ( proc_index >= NB_PROCS_MAX )       return 1;
    404 
    405     unsigned int *icu_address = (unsigned int*)&seg_icu_base +
    406                                 (cluster_index * CLUSTER_SPAN)  +
    407                                 (proc_index * ICU_SPAN);
    408 
    409     *buffer = icu_address[register_index]; // read word
    410     return 0;
    411 
    412 #endif
    413406}
    414407
     
    763756    else
    764757    {
    765         unsigned char *fb_address = (unsigned char*)&seg_fb_base + offset;
     758        unsigned char *fb_address = (unsigned char*)&seg_fbf_base + offset;
    766759        memcpy((void*)fb_address, (void*)buffer, length);
    767760        return 0;
     
    789782    else
    790783    {
    791         unsigned char *fb_address = (unsigned char*)&seg_fb_base + offset;
     784        unsigned char *fb_address = (unsigned char*)&seg_fbf_base + offset;
    792785        memcpy((void*)buffer, (void*)fb_address, length);
    793786        return 0;
     
    833826    if ( (user_vaddr & 0x3) || (length & 0x3) )
    834827    {
     828        _get_lock(&_tty_put_lock);
    835829        _puts("[GIET ERROR] in _fbdma_access() : user buffer not word aligned\n");
     830        _release_lock(&_tty_put_lock);
    836831        return 1;
    837832    }
     
    841836
    842837    // compute frame buffer pbase address
    843     unsigned int fb_vaddr = (unsigned int)&seg_fb_base + offset;
     838    unsigned int fb_vaddr = (unsigned int)&seg_fbf_base + offset;
    844839
    845840    ko = _v2p_translate( (page_table_t*)user_ptab,
     
    851846    if ( ko )
    852847    {
     848        _get_lock(&_tty_put_lock);
    853849        _puts("[GIET ERROR] in _fbdma_access() : frame buffer unmapped\n");
     850        _release_lock(&_tty_put_lock);
    854851        return 2;
    855852    }
     
    864861    if ( ko )
    865862    {
     863        _get_lock(&_tty_put_lock);
    866864        _puts("[GIET ERROR] in _fbdma_access() : user buffer unmapped\n");
     865        _release_lock(&_tty_put_lock);
    867866        return 3;
    868867    }
    869868    if ( (flags & PTE_U) == 0 )
    870869    {
     870        _get_lock(&_tty_put_lock);
    871871        _puts("[GIET ERROR] in _fbdma_access() : user buffer not in user space\n");
     872        _release_lock(&_tty_put_lock);
    872873        return 4;
    873874    }
    874875    if ( ( (flags & PTE_W) == 0 ) && to_user )
    875876    {
     877        _get_lock(&_tty_put_lock);
    876878        _puts("[GIET ERROR] in _fbdma_access() : user buffer not writable\n");
     879        _release_lock(&_tty_put_lock);
    877880        return 5;
    878881    }
Note: See TracChangeset for help on using the changeset viewer.