source: soft/giet_vm/giet_kernel/irq_handler.c @ 541

Last change on this file since 541 was 528, checked in by alain, 10 years ago

1) Introducing support for external IRQs dynamic routing.
2) Simplifying the _v2p_translate() function.
3) Removing the generic IOC driver (integrated in the FAT library).

  • Property svn:executable set to *
File size: 14.6 KB
RevLine 
[528]1///////////////////////////////////////////////////////////////////////////
[258]2// File     : irq_handler.c
3// Date     : 01/04/2012
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
[528]6///////////////////////////////////////////////////////////////////////////
[258]7
8#include <giet_config.h>
9#include <irq_handler.h>
10#include <sys_handler.h>
11#include <ctx_handler.h>
12#include <tim_driver.h>
13#include <xcu_driver.h>
[528]14#include <pic_driver.h>
[258]15#include <tty_driver.h>
[294]16#include <nic_driver.h>
17#include <cma_driver.h>
[297]18#include <mmc_driver.h>
[294]19#include <bdv_driver.h>
[258]20#include <dma_driver.h>
[322]21#include <spi_driver.h>
[528]22#include <mwr_driver.h>
[281]23#include <mapping_info.h>
[258]24#include <utils.h>
[459]25#include <tty0.h>
[258]26
[528]27/////////////////////////////////////////////////////////////////////////
28//       Global variables
29/////////////////////////////////////////////////////////////////////////
[258]30
[528]31// array of external IRQ indexes for each (isr/channel) couple
32__attribute__((section(".kdata")))
33unsigned char _ext_irq_index[GIET_ISR_TYPE_MAX][GIET_ISR_CHANNEL_MAX];
34
35// WTI mailbox allocators for external IRQ routing (3 allocators per proc)
36__attribute__((section(".kdata")))
37unsigned char _wti_alloc_one[X_SIZE][Y_SIZE][NB_PROCS_MAX];
38__attribute__((section(".kdata")))
39unsigned char _wti_alloc_two[X_SIZE][Y_SIZE][NB_PROCS_MAX];
40__attribute__((section(".kdata")))
41unsigned char _wti_alloc_ter[X_SIZE][Y_SIZE][NB_PROCS_MAX];
42
[519]43/////////////////////////////////////////////////////////////////////////
[528]44// this array is allocated in the boot.c or kernel_init.c
45/////////////////////////////////////////////////////////////////////////
46
47extern static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX]; 
48
49/////////////////////////////////////////////////////////////////////////
[519]50// These ISR_TYPE names for display must be consistent with values in
51// irq_handler.h / mapping.py / xml_driver.c
52/////////////////////////////////////////////////////////////////////////
[494]53__attribute__((section(".kdata")))
[440]54char* _isr_type_name[] = { "DEFAULT",
55                           "TICK"   ,
56                           "TTY_RX" ,
57                           "TTY_TX" ,
58                           "BDV"    ,
59                           "TIMER"  ,
60                           "WAKUP"  ,
61                           "NIC_RX" ,
62                           "NIC_TX" ,
63                           "CMA"    ,
64                           "MMC"    ,
65                           "DMA"    ,
[519]66                           "SPI"    ,
[528]67                           "MWR"    ,
68                           "HBA"    };
69
70////////////////////
71void _ext_irq_init()
72{
73    mapping_header_t*    header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
74    mapping_cluster_t*   cluster = _get_cluster_base(header);
75    mapping_periph_t*    periph  = _get_periph_base(header);
76    mapping_irq_t*       irq     = _get_irq_base(header);
77    unsigned int         periph_id;   // peripheral index in mapping_info
78    unsigned int         irq_id;      // irq index in mapping_info
79
80    // get cluster_io index in mapping
81    unsigned int         x_io       = header->x_io; 
82    unsigned int         y_io       = header->y_io; 
83    unsigned int         cluster_io = (x_io * Y_SIZE) + y_io; 
84    mapping_periph_t*    pic        = NULL;
85
86    // scan external peripherals to find XCU
87    unsigned int min = cluster[cluster_io].periph_offset ;
88    unsigned int max = min + cluster[cluster_io].periphs ;
89   
90    for ( periph_id = min ; periph_id < max ; periph_id++ )
91    {
92        if ( periph[periph_id].type == PERIPH_TYPE_PIC ) 
93        {
94            pic = &periph[periph_id];
95            break;
96        }
97    } 
98
99    if ( pic == NULL )
100    {
101        _printf("\n[GIET ERROR] in _ext_irq_init() : No PIC component found\n");
102        _exit();
103    }
104
105    // scan PIC IRQS defined in mapping
106    for ( irq_id = pic->irq_offset ;
107          irq_id < pic->irq_offset + pic->irqs ;
108          irq_id++ )
109    {
110        unsigned int type    = irq[irq_id].srctype;
111        unsigned int srcid   = irq[irq_id].srcid;
112        unsigned int isr     = irq[irq_id].isr;
113        unsigned int channel = irq[irq_id].channel;
114
115        if ( (type != IRQ_TYPE_HWI)            || 
116             (srcid > 31)                      || 
117             (isr >= GIET_ISR_TYPE_MAX)        ||
118             (channel >= GIET_ISR_CHANNEL_MAX) )
119        {
120            _printf("\n[GIET ERROR] in _ext_irq_init() : Bad PIC IRQ\n"
121                    "  type = %d / srcid = %d / isr = %d / channel = %d\n",
122                    type , srcid , isr , channel );
123            _exit();
124        }
125        _ext_irq_index[isr][channel] = srcid;
126    }
127}  // end _ext_irq_init()
128
129////////////////////////////////////////////
130void _ext_irq_alloc( unsigned int   isr_type,
131                     unsigned int   isr_channel,
132                     unsigned int*  wti_index )
133{
134    unsigned int wti_id;        // allocated WTI mailbox index in XCU
135    unsigned int irq_id;        // external IRQ index in PIC (input)
136    unsigned int wti_addr;      // WTI mailbox physical address (32 lsb bits)
137
138    // check arguments
139    if ( isr_type >= GIET_ISR_TYPE_MAX )
140    {
141        _printf("\n[GIET ERROR] in _ext_irq_alloc() : illegal ISR type\n");
142        _exit();
143    }
144    if ( isr_channel >= GIET_ISR_CHANNEL_MAX )
145    {
146        _printf("\n[GIET ERROR] in _ext_irq_alloc() : illegal ISR channel\n");
147        _exit();
148    }
149
150    // get processor coordinates [x,y,p]
151    unsigned int gpid           = _get_procid();
152    unsigned int cluster_xy     = gpid >> P_WIDTH;
153    unsigned int x              = cluster_xy >> Y_WIDTH;
154    unsigned int y              = cluster_xy & ((1<<Y_WIDTH)-1);
155    unsigned int p              = gpid & ((1<<P_WIDTH)-1);
156
157    // allocate a WTI mailbox to proc[x,y,p] (blocking until success)
158    while ( 1 )
159    {
160        if ( _wti_alloc_one[x][y][p] == 0 )
161        {
162            _wti_alloc_one[x][y][p] = 1;
163            wti_id = p + NB_PROCS_MAX;
164            break;
165        }
166        if ( _wti_alloc_two[x][y][p] == 0 )
167        {
168            _wti_alloc_two[x][y][p] = 1;
169            wti_id = p + 2*NB_PROCS_MAX;
170            break;
171        }
172        if ( _wti_alloc_ter[x][y][p] == 0 )
173        {
174            _wti_alloc_ter[x][y][p] = 1;
175            wti_id = p + 3*NB_PROCS_MAX;
176            break;
177        }
178    }   
179    *wti_index = wti_id;
180
181    // register the mailbox physical address in IOPIC
182    irq_id   = _ext_irq_index[isr_type][isr_channel];
183    _xcu_get_wti_address( wti_id , &wti_addr );
184    _pic_init( irq_id , wti_addr, cluster_xy );
185   
186    // initializes the WTI interrupt vector entry for XCU
187    _schedulers[x][y][p]->wti_vector[wti_id] = isr_channel<<16 | isr_type;
188
189}  // end ext_irq_alloc()
190
191////////////////////////////////////////////
192void _ext_irq_release( unsigned int isr_type,
193                       unsigned int isr_channel,
194                       unsigned int wti_index )
195{
196    unsigned int irq_id;        // external IRQ index in PIC (input)
197
198    // get processor coordinates [x,y,p]
199    unsigned int gpid           = _get_procid();
200    unsigned int cluster_xy     = gpid >> P_WIDTH;
201    unsigned int x              = cluster_xy >> Y_WIDTH;
202    unsigned int y              = cluster_xy & ((1<<Y_WIDTH)-1);
203    unsigned int p              = gpid & ((1<<P_WIDTH)-1);
204
205    // check arguments
206    if ( isr_type >= GIET_ISR_TYPE_MAX )
207    {
208        _printf("\n[GIET ERROR] in _ext_irq_release() illegal ISR type\n");
209        _exit();
210    }
211    if ( isr_channel >= GIET_ISR_CHANNEL_MAX )
212    {
213        _printf("\n[GIET ERROR] in _ext_irq_release() : illegal ISR channel\n");
214        _exit();
215    }
216
217    // desactivates dynamically allocated PIC entry
218    irq_id = _ext_irq_index[isr_type][isr_channel];
219    _pic_set_register( irq_id , IOPIC_MASK , 0 );
220
221    // releases dynamically allocated WTI mailbox
222    if      ( wti_index == p +   NB_PROCS_MAX ) _wti_alloc_one[x][y][p] = 0;
223    else if ( wti_index == p + 2*NB_PROCS_MAX ) _wti_alloc_two[x][y][p] = 0;
224    else if ( wti_index == p + 3*NB_PROCS_MAX ) _wti_alloc_ter[x][y][p] = 0;
225    else
226    {
227        _printf("\n[GIET ERROR] in _ext_irq_release() : illegal WTI index\n");
228        _exit();
229    }
230}  // end ext_irq_release()
231
[440]232/////////////////
[258]233void _irq_demux() 
234{
[294]235    unsigned int gpid           = _get_procid();
[428]236    unsigned int cluster_xy     = gpid >> P_WIDTH;
[294]237    unsigned int x              = cluster_xy >> Y_WIDTH;
238    unsigned int y              = cluster_xy & ((1<<Y_WIDTH)-1);
[428]239    unsigned int lpid           = gpid & ((1<<P_WIDTH)-1);
[258]240    unsigned int irq_id;
[294]241    unsigned int irq_type;
[258]242
243    // get the highest priority active IRQ index
[294]244    unsigned int icu_out_index = lpid * IRQ_PER_PROCESSOR;
[258]245
[294]246    _xcu_get_index( cluster_xy, icu_out_index, &irq_id, &irq_type );
[258]247
248    if (irq_id < 32) 
249    {
[294]250        static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
[346]251        unsigned int        entry = 0;
[294]252        unsigned int        isr_type;
253        unsigned int        channel;
[258]254
[294]255        if      (irq_type == IRQ_TYPE_HWI) entry = psched->hwi_vector[irq_id];
256        else if (irq_type == IRQ_TYPE_PTI) entry = psched->pti_vector[irq_id];
257        else if (irq_type == IRQ_TYPE_WTI) entry = psched->wti_vector[irq_id];
258        else
[258]259        {
[294]260            _printf("\n[GIET ERROR] illegal irq_type in irq_demux()\n");
261            _exit();
[258]262        }
[294]263
264        isr_type   = (entry    ) & 0x0000FFFF;
265        channel    = (entry>>16) & 0x00007FFF;
266
267#if GIET_DEBUG_IRQS // we don't take the TTY lock to avoid deadlocks
[310]268char* irq_type_str[] = { "HWI", "WTI", "PTI" }; 
[294]269_puts("\n[IRQS DEBUG] Processor[");
270_putd(x);
271_puts(",");
272_putd(y);
273_puts(",");
274_putd(lpid);
275_puts("] enters _irq_demux() at cycle ");
276_putd(_get_proctime() );
277_puts("\n  ");
278_puts(irq_type_str[irq_type] );
279_puts(" : irq_id = ");
280_putd(irq_id);
281_puts(" / isr_type = ");
282_putd(isr_type);
283_puts(" / channel = ");
284_putd(channel);
285_puts("\n");
286#endif
287
288        // ISR call
289        if      ( isr_type == ISR_TICK   ) _isr_tick   ( irq_type, irq_id, channel );
290        else if ( isr_type == ISR_WAKUP  ) _isr_wakup  ( irq_type, irq_id, channel );
291        else if ( isr_type == ISR_BDV    ) _bdv_isr    ( irq_type, irq_id, channel );
292        else if ( isr_type == ISR_CMA    ) _cma_isr    ( irq_type, irq_id, channel );
293        else if ( isr_type == ISR_TTY_RX ) _tty_rx_isr ( irq_type, irq_id, channel );
294        else if ( isr_type == ISR_TTY_TX ) _tty_tx_isr ( irq_type, irq_id, channel );
295        else if ( isr_type == ISR_NIC_RX ) _nic_rx_isr ( irq_type, irq_id, channel );
296        else if ( isr_type == ISR_NIC_TX ) _nic_tx_isr ( irq_type, irq_id, channel );
297        else if ( isr_type == ISR_TIMER  ) _timer_isr  ( irq_type, irq_id, channel );
[297]298        else if ( isr_type == ISR_MMC    ) _mmc_isr    ( irq_type, irq_id, channel );
[322]299        else if ( isr_type == ISR_DMA    ) _dma_isr    ( irq_type, irq_id, channel );
300        else if ( isr_type == ISR_SPI    ) _spi_isr    ( irq_type, irq_id, channel );
[519]301        else if ( isr_type == ISR_MWR    ) _mwr_isr    ( irq_type, irq_id, channel );
[294]302        else
[258]303        {
[310]304            _printf("\n[GIET ERROR] in _irq_demux() :"
305                    " illegal ISR type on processor[%d,%d,%d] at cycle %d\n"
306                    " - irq_type = %d\n"
307                    " - irq_id   = %d\n"
308                    " - isr_type = %x\n",
309                    x, y, lpid, _get_proctime(), irq_type, irq_id, isr_type );
[258]310        }
311    }
[294]312    else   // no interrupt active
313    {
314        _isr_default();
315    } 
[258]316}
317
[440]318///////////////////
[294]319void _isr_default()
[258]320{
[294]321    unsigned int gpid       = _get_procid();
[428]322    unsigned int cluster_xy = gpid >> P_WIDTH;
[294]323    unsigned int x          = cluster_xy >> Y_WIDTH;
324    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
[428]325    unsigned int lpid       = gpid & ((1<<P_WIDTH)-1);
[258]326
[322]327    _printf("\n[GIET WARNING] IRQ handler called but no active IRQ "
328            "on processor[%d,%d,%d] at cycle %d\n",
329            x, y, lpid, _get_proctime() );
[258]330}
331
332
[440]333////////////////////////////////////////////////////////////
[294]334void _isr_wakup( unsigned int irq_type,   // HWI / WTI / PTI
335                 unsigned int irq_id,     // index returned by ICU
336                 unsigned int channel )   // unused
[258]337{
[428]338    unsigned int gpid       = _get_procid();
339    unsigned int cluster_xy = gpid >> P_WIDTH;
[294]340    unsigned int x          = cluster_xy >> Y_WIDTH;
341    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
[528]342    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
[428]343
[528]344    unsigned int value;     // WTI mailbox value
345    unsigned int save_sr;   // save SR value in pre-empted task stack
[258]346
[528]347    unsigned int ltid       = _get_current_task_id();
348
[294]349    if ( irq_type != IRQ_TYPE_WTI )
[258]350    {
[528]351        _printf("[GIET ERROR] P[%d,%d,%d] enters _isr_wakup() at cycle %d\n"
352                " but not called by a WTI interrupt\n",
353                x , y , p , _get_proctime() );
[294]354        _exit();
[258]355    }
356
[294]357    // get mailbox value and acknowledge WTI
358    _xcu_get_wti_value( cluster_xy, irq_id, &value );
359
[528]360#if GIET_DEBUG_SWITCH
361_printf("\n[DEBUG SWITCH] P[%d,%d,%d] enters _isr_wakup() at cycle %d\n"
362        "  WTI index = %d / current ltid = %d / mailbox value = %x\n",
363        x , y , p , _get_proctime() , irq_id , ltid , value );
[258]364#endif
365
[528]366    // enter critical section and swich context (if required)
367    if ( (ltid == IDLE_TASK_INDEX) || (value != 0) )
368    {
369        _it_disable( &save_sr );
370        _ctx_switch();
371        _it_restore( &save_sr );
372    }
373
[440]374} // end _isr_wakup
[258]375
[440]376///////////////////////////////////////////////////////////
[294]377void _isr_tick( unsigned int irq_type,   // HWI / WTI / PTI
378                unsigned int irq_id,     // index returned by ICU
379                unsigned int channel )   // channel index if HWI
[258]380{
[428]381    unsigned int gpid       = _get_procid();
382    unsigned int cluster_xy = gpid >> P_WIDTH;
[440]383    unsigned int x          = cluster_xy >> Y_WIDTH;
384    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
[528]385    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
[258]386
[528]387    unsigned int save_sr;   // save SR value in pre-empted task stack
388
[440]389    if ( irq_type != IRQ_TYPE_PTI )
390    {
[528]391        _printf("[GIET ERROR] P[%d,%d,%d] enters _isr_tick() at cycle %d\n"
392                " but not called by a PTI interrupt\n",
393                x , y , p , _get_proctime() );
[440]394        _exit();
395    }
[258]396
[440]397    // acknowledge PTI
398    _xcu_timer_reset_irq( cluster_xy, irq_id );
399
[528]400#if GIET_DEBUG_SWITCH
401unsigned int ltid  = _get_current_task_id();
402_printf("\n[DEBUG SWITCH] P[%d,%d,%d] enters _isr_tick() at cycle %d\n"
403        "  WTI index = %d / current ltid = %d\n",
404        x , y , p , _get_proctime() , irq_id , ltid );
[258]405#endif
406
[528]407    // enter critical section and switch context
408    _it_disable( &save_sr );
[258]409    _ctx_switch();
[528]410    _it_restore( &save_sr );
411
[440]412}  // end _isr_tick
[258]413
414
415// Local Variables:
416// tab-width: 4
417// c-basic-offset: 4
418// c-file-offsets:((innamespace . 0)(inline-open . 0))
419// indent-tabs-mode: nil
420// End:
421// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
422
Note: See TracBrowser for help on using the repository browser.