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

Last change on this file since 641 was 547, checked in by alain, 10 years ago

Move the peripheral initialisation from the boot.c to the kernel_init.c

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