source: rtems/c/src/lib/libbsp/powerpc/gen5200/irq/irq.c @ a9e62c2

4.104.114.95
Last change on this file since a9e62c2 was a9e62c2, checked in by Till Straumann <strauman@…>, on 12/08/07 at 17:26:19

2007-12-08 Till Straumann <strauman@…>

  • ep1a/irq/irq.c, gen5200/irq/irq.c, gen83xx/irq/irq_init.c, mbx8xx/irq/irq.c, mpc8260ads/irq/irq.c, mvme5500/irq/irq.c, psim/irq/no_pic.c, score603e/irq/irq.c, shared/irq/irq_supp.h, shared/irq/openpic_i8259_irq.c, virtex/irq/irq_init.c: let C_dispatch_irq_handler() return zero to indicate to low-level exception handling code that the exception was handled (not used yet).
  • Property mode set to 100644
File size: 29.0 KB
Line 
1/*===============================================================*\
2| Project: RTEMS generic MPC5200 BSP                              |
3+-----------------------------------------------------------------+
4| Partially based on the code references which are named below.   |
5| Adaptions, modifications, enhancements and any recent parts of  |
6| the code are:                                                   |
7|                    Copyright (c) 2005                           |
8|                    Embedded Brains GmbH                         |
9|                    Obere Lagerstr. 30                           |
10|                    D-82178 Puchheim                             |
11|                    Germany                                      |
12|                    rtems@embedded-brains.de                     |
13+-----------------------------------------------------------------+
14| The license and distribution terms for this file may be         |
15| found in the file LICENSE in this distribution or at            |
16|                                                                 |
17| http://www.rtems.com/license/LICENSE.                           |
18|                                                                 |
19+-----------------------------------------------------------------+
20| this file contains the irq controller handler                   |
21\*===============================================================*/
22/***********************************************************************/
23/*                                                                     */
24/*   Module:       irq.c                                               */
25/*   Date:         07/17/2003                                          */
26/*   Purpose:      RTEMS MPC5x00 CPU main interrupt handler & routines */
27/*                                                                     */
28/*---------------------------------------------------------------------*/
29/*                                                                     */
30/*   Description:  This file contains the implementation of the        */
31/*                 functions described in irq.h                        */
32/*                                                                     */
33/*---------------------------------------------------------------------*/
34/*                                                                     */
35/*   Code                                                              */
36/*   References:   MPC8260ads main interrupt handler & routines        */
37/*   Module:       irc.c                                               */
38/*   Project:      RTEMS 4.6.0pre1 / MCF8260ads BSP                    */
39/*   Version       1.2                                                 */
40/*   Date:         04/18/2002                                          */
41/*                                                                     */
42/*   Author(s) / Copyright(s):                                         */
43/*                                                                     */
44/*   Copyright (C) 1998, 1999 valette@crf.canon.fr                     */
45/*                                                                     */
46/*   Modified for mpc8260 Andy Dachs <a.dachs@sstl.co.uk>              */
47/*   Surrey Satellite Technology Limited, 2000                         */
48/*   Nested exception handlers not working yet.                        */
49/*                                                                     */
50/*   The license and distribution terms for this file may be           */
51/*   found in found in the file LICENSE in this distribution or at     */
52/*   http://www.rtems.com/license/LICENSE.                        */
53/*                                                                     */
54/*---------------------------------------------------------------------*/
55/*                                                                     */
56/*   Partially based on the code references which are named above.     */
57/*   Adaptions, modifications, enhancements and any recent parts of    */
58/*   the code are under the right of                                   */
59/*                                                                     */
60/*         IPR Engineering, Dachauer Straße 38, D-80335 MÃŒnchen        */
61/*                        Copyright(C) 2003                            */
62/*                                                                     */
63/*---------------------------------------------------------------------*/
64/*                                                                     */
65/*   IPR Engineering makes no representation or warranties with        */
66/*   respect to the performance of this computer program, and          */
67/*   specifically disclaims any responsibility for any damages,        */
68/*   special or consequential, connected with the use of this program. */
69/*                                                                     */
70/*---------------------------------------------------------------------*/
71/*                                                                     */
72/*   Version history:  1.0                                             */
73/*                                                                     */
74/***********************************************************************/
75
76#include <bsp.h>
77#include <rtems.h>
78#include "../irq/irq.h"
79#include <rtems/score/apiext.h>
80#include <rtems/bspIo.h>
81#include <libcpu/raw_exception.h>
82#include "../vectors/vectors.h"
83#include "../include/mpc5200.h"
84
85
86extern uint32_t irqMaskTable[];
87
88/*
89 * default handler connected on each irq after bsp initialization
90 */
91static rtems_irq_connect_data  default_rtems_entry;
92
93/*
94 * location used to store initial tables used for interrupt
95 * management.
96 */
97static rtems_irq_global_settings*   internal_config;
98static rtems_irq_connect_data*      rtems_hdl_tbl;
99
100/*
101 * bit in the SIU mask registers (PPC bit numbering) that should
102 * be set to enable the relevant interrupt, mask of 32 is for unused entries
103 *
104 */
105const static unsigned int SIU_MaskBit[BSP_SIU_IRQ_NUMBER] =
106  {
107  0, 1, 2, 3,       /* smart_comm, psc1, psc2, psc3            */
108  4, 5, 6, 7,       /* irda/psc6, eth, usb, ata                */
109  8, 9, 10, 11,     /* pci_ctrl, pci_sc_rx, pci_sc_tx, psc4    */
110  12, 13, 14, 15,   /* psc5,spi_modf, spi_spif, i2c1           */
111  16, 17, 18, 19,   /* i2c, can1, can2, ir_rx                  */
112  20, 21, 15, 16,   /* ir_rx, xlb_arb, slice_tim2, irq1,       */
113  17, 18, 19, 20,   /* irq2, irq3, lo_int, rtc_pint            */
114  21, 22, 23, 24,   /* rtc_sint, gpio_std, gpio_wkup, tmr0     */
115  25, 26, 27, 28,   /* tmr1, tmr2, tmr3, tmr4                  */
116  29, 30, 31, 32,   /* tmr5, tmr6, tmr7, res                   */
117  32, 32, 32        /* res, res, res                           */
118  };
119
120/*
121 * Check if symbolic IRQ name is a Processor IRQ
122 */
123static inline int is_processor_irq(const rtems_irq_symbolic_name irqLine)
124{
125
126  return (((int)irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET) &
127          ((int)irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET));
128}
129
130/*
131 * Check for SIU IRQ and return base index
132 */
133static inline int is_siu_irq(const rtems_irq_symbolic_name irqLine)
134{
135
136  return (((int)irqLine <= BSP_SIU_IRQ_MAX_OFFSET) &&
137           ((int)irqLine >= BSP_SIU_IRQ_LOWEST_OFFSET));
138
139}
140
141
142/*
143 * Check for SIU IRQ and return base index
144 */
145static inline int get_siu_irq_base_index(const rtems_irq_symbolic_name irqLine)
146{
147
148  if (irqLine <= BSP_PER_IRQ_MAX_OFFSET)
149    return BSP_PER_IRQ_LOWEST_OFFSET;
150
151  if (irqLine <= BSP_MAIN_IRQ_MAX_OFFSET)
152    return BSP_MAIN_IRQ_LOWEST_OFFSET;
153  if (irqLine <= BSP_CRIT_IRQ_MAX_OFFSET)
154    return BSP_CRIT_IRQ_LOWEST_OFFSET;
155
156  return -1;
157}
158
159
160static inline void BSP_enable_per_irq_at_siu(
161  const rtems_irq_symbolic_name irqLine
162)
163{
164  uint8_t lo_hi_ind = 0, prio_index_offset;
165  uint32_t *reg;
166  rtems_irq_prio *irqPrioTable = internal_config->irqPrioTbl;
167  volatile uint32_t per_pri_1,main_pri_1, crit_pri_main_mask, per_mask;
168
169  /* calculate the index offset of priority value bit field */
170  prio_index_offset = (irqLine - BSP_PER_IRQ_LOWEST_OFFSET) % 8;
171
172  /* set interrupt priorities */
173  if (irqPrioTable[irqLine] <= 15) {
174
175    /* set peripheral int priority */
176    reg = (uint32_t *)(&(mpc5200.per_pri_1));
177
178    /* choose proper register */
179    reg += (irqLine >> 3);
180
181    /* set priority as given in priority table */
182    *reg |= (irqPrioTable[irqLine] << (28 - (prio_index_offset<< 2)));
183
184    /* test msb (hash-bit) and set LO_/HI_int indicator */
185    if ((lo_hi_ind = (irqPrioTable[irqLine] >> 3))) {
186
187      /* set critical HI_int priority */
188      reg = (uint32_t *)(&(mpc5200.crit_pri_main_mask));
189      *reg |= (irqPrioTable[BSP_SIU_IRQ_HI_INT] << 26);
190
191      /*
192       * critical interrupt handling for the 603le core is not
193       * yet supported, routing of critical interrupts is forced
194       * to core_int (bit 31 / CEb)
195       */
196       mpc5200.ext_en_type |= 1;
197
198    } else {
199      if (irqPrioTable[irqLine] <= 15) {
200        /* set main LO_int priority */
201        reg = (uint32_t *)(&(mpc5200.main_pri_1));
202        *reg |= (irqPrioTable[BSP_SIU_IRQ_LO_INT] << 16);
203      }
204    }
205  }
206
207  /* if LO_int ind., enable (unmask) main interrupt */
208  if (!lo_hi_ind) {
209    mpc5200.crit_pri_main_mask &=
210      ~(0x80000000 >> SIU_MaskBit[BSP_SIU_IRQ_LO_INT]);
211  }
212
213
214  /* enable (unmask) peripheral interrupt */
215  mpc5200.per_mask &= ~(0x80000000 >> SIU_MaskBit[irqLine]);
216
217  main_pri_1         = mpc5200.main_pri_1;
218  crit_pri_main_mask = mpc5200.crit_pri_main_mask;
219  per_pri_1          = mpc5200.per_pri_1;
220  per_mask           = mpc5200.per_mask;
221
222
223}
224
225
226static inline void BSP_enable_main_irq_at_siu(
227  const rtems_irq_symbolic_name irqLine
228)
229{
230
231  uint8_t prio_index_offset;
232  uint32_t *reg;
233  rtems_irq_prio *irqPrioTable = internal_config->irqPrioTbl;
234
235  /* calculate the index offset of priority value bit field */
236  prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8;
237
238  /* set main interrupt priority */
239  if (irqPrioTable[irqLine] <= 15) {
240
241    /* set main int priority */
242    reg = (uint32_t *)(&(mpc5200.main_pri_1));
243
244    /* choose proper register */
245    reg += (irqLine >> 3);
246
247    /* set priority as given in priority table */
248    *reg |= (irqPrioTable[irqLine] << (28 - (prio_index_offset << 2)));
249
250    if ((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3)) {
251      /* enable external irq-pin */
252      mpc5200.ext_en_type |= (0x80000000 >> (20 + prio_index_offset));
253    }
254  }
255
256  /* enable (unmask) main interrupt */
257  mpc5200.crit_pri_main_mask &= ~(0x80000000 >> SIU_MaskBit[irqLine]);
258
259}
260
261
262static inline void BSP_enable_crit_irq_at_siu(
263  const rtems_irq_symbolic_name irqLine
264)
265{
266  uint8_t prio_index_offset;
267  uint32_t *reg;
268  rtems_irq_prio *irqPrioTable = internal_config->irqPrioTbl;
269
270  prio_index_offset = irqLine - BSP_CRIT_IRQ_LOWEST_OFFSET;
271
272  /*
273   * critical interrupt handling for the 603Le core is not
274   * yet supported, routing of critical interrupts is forced
275   * to core_int (bit 31 / CEb)
276   */
277  mpc5200.ext_en_type |= 1;
278
279
280  /* set critical interrupt priorities */
281  if (irqPrioTable[irqLine] <= 3) {
282
283    /* choose proper register */
284    reg = (uint32_t *)(&(mpc5200.crit_pri_main_mask));
285
286    /* set priority as given in priority table */
287    *reg |= (irqPrioTable[irqLine] << (30 - (prio_index_offset << 1)));
288
289    /* external irq0-pin */
290    if (irqLine == BSP_SIU_IRQ_IRQ1) {
291      /* enable external irq-pin */
292      mpc5200.ext_en_type |= (0x80000000 >> (20 + prio_index_offset));
293    }
294  }
295}
296
297
298static inline void BSP_disable_per_irq_at_siu(
299  const rtems_irq_symbolic_name irqLine
300)
301{
302  uint8_t prio_index_offset;
303  uint32_t *reg;
304
305  /* calculate the index offset of priority value bit field */
306  prio_index_offset = (irqLine - BSP_PER_IRQ_LOWEST_OFFSET) % 8;
307
308  /* disable (mask) peripheral interrupt */
309  mpc5200.per_mask |= (0x80000000 >> SIU_MaskBit[irqLine]);
310
311  /* reset priority to lowest level (reset value) */
312  reg = (uint32_t *)(&(mpc5200.per_pri_1));
313  reg += (irqLine >> 3);
314  *reg &= ~(15 << (28 - (prio_index_offset << 2)));
315}
316
317
318static inline void BSP_disable_main_irq_at_siu(
319  const rtems_irq_symbolic_name irqLine
320)
321{
322  uint8_t prio_index_offset;
323  uint32_t *reg;
324
325  /* calculate the index offset of priority value bit field */
326  prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8;
327
328  /* disable (mask) main interrupt */
329  mpc5200.crit_pri_main_mask |= (0x80000000 >> SIU_MaskBit[irqLine]);
330
331  if ((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3)) {
332    /* disable external irq-pin */
333    mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset));
334  }
335
336  /* reset priority to lowest level (reset value) */
337  reg = (uint32_t *)(&(mpc5200.main_pri_1));
338  reg  += (irqLine >> 3);
339  *reg &= ~(15 << (28 - (prio_index_offset << 2)));
340}
341
342
343static inline void BSP_disable_crit_irq_at_siu(
344  const rtems_irq_symbolic_name irqLine
345)
346{
347  uint8_t prio_index_offset;
348  uint32_t *reg;
349
350  prio_index_offset = irqLine - BSP_CRIT_IRQ_LOWEST_OFFSET;
351
352  /* reset critical int priority to lowest level (reset value) */
353  reg = (uint32_t *)(&(mpc5200.crit_pri_main_mask));
354  *reg &= ~(3 << (30 - (prio_index_offset << 1)));
355
356  if (irqLine == BSP_SIU_IRQ_IRQ1) {
357    /* disable external irq0-pin */
358    mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset));
359  }
360}
361
362
363/*
364 * ------------------------ RTEMS Irq helper functions ----------------
365 */
366
367
368/*
369 * This function check that the value given for the irq line
370 * is valid.
371 */
372static int isValidInterrupt(int irq)
373{
374  if ( (irq < BSP_LOWEST_OFFSET) || (irq > BSP_MAX_OFFSET) )
375    return 0;
376  return 1;
377}
378
379
380 /*
381  * This function enables a given siu interrupt
382  */
383int BSP_irq_enable_at_siu(const rtems_irq_symbolic_name irqLine)
384{
385  int base_index;
386
387  if (is_siu_irq(irqLine)) {
388    if ((base_index = get_siu_irq_base_index(irqLine)) != -1) {
389
390      switch(base_index) {
391        case BSP_PER_IRQ_LOWEST_OFFSET:
392          BSP_enable_per_irq_at_siu(irqLine);
393          break;
394        case BSP_MAIN_IRQ_LOWEST_OFFSET:
395          BSP_enable_main_irq_at_siu(irqLine);
396          break;
397        case BSP_CRIT_IRQ_LOWEST_OFFSET:
398          BSP_enable_crit_irq_at_siu(irqLine);
399          break;
400        default:
401          printk("No valid base index\n");
402          break;
403      }
404    }
405  }
406  return 0;
407}
408
409/*
410 * This function disables a given siu interrupt
411 */
412int BSP_irq_disable_at_siu(const rtems_irq_symbolic_name irqLine)
413{
414  int base_index;
415
416  if ( (base_index = get_siu_irq_base_index(irqLine)) == -1)
417    return 1;
418
419  switch(base_index) {
420    case BSP_PER_IRQ_LOWEST_OFFSET:
421      BSP_disable_per_irq_at_siu(irqLine);
422      break;
423    case BSP_MAIN_IRQ_LOWEST_OFFSET:
424      BSP_disable_main_irq_at_siu(irqLine);
425      break;
426    case BSP_CRIT_IRQ_LOWEST_OFFSET:
427      BSP_disable_crit_irq_at_siu(irqLine);
428      break;
429    default:
430      printk("No valid base index\n");
431      break;
432  }
433  return 0;
434}
435
436
437/*
438 * --------------------- RTEMS Single Irq Handler Mngt Routines -------------
439 */
440
441 /*
442  * This function removes the default entry and installs a device
443  * interrupt handler
444  */
445int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq)
446{
447  rtems_interrupt_level level;
448
449  if (!isValidInterrupt(irq->name)) {
450    printk("not a valid interrupt\n");
451    return 0;
452  }
453
454  /*
455   * Check if default handler is actually connected. If not issue an error.
456   * RATIONALE : to always have the same transition by forcing the user
457   * to get the previous handler before accepting to disconnect.
458   */
459  if (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl) {
460    printk( "Default handler not there\n" );
461    return 0;
462  }
463
464  rtems_interrupt_disable(level);
465
466  /*
467   * store the data provided by user
468   */
469  rtems_hdl_tbl[irq->name] = *irq;
470
471  if (is_siu_irq(irq->name)) {
472    /*
473     * Enable interrupt at siu level
474     */
475    BSP_irq_enable_at_siu(irq->name);
476  } else {
477    if (is_processor_irq(irq->name)) {
478      /*
479       * Should Enable exception at processor level but not needed.
480       * Will restore EE flags at the end of the routine anyway.
481       */
482    } else {
483      printk("not a valid interrupt\n");
484      return 0;
485    }
486  }
487
488  /*
489   * Enable interrupt on device
490   */
491  if (irq->on)
492    irq->on(irq);
493
494  rtems_interrupt_enable(level);
495  return 1;
496}
497
498
499 /*
500  * This function procures the current interrupt handler
501  */
502int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* irq)
503{
504  if (!isValidInterrupt(irq->name)) {
505    return 0;
506  }
507  *irq = rtems_hdl_tbl[irq->name];
508  return 1;
509}
510
511
512 /*
513  * This function removes a device interrupt handler and restores
514  * the default entry
515  */
516int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq)
517{
518  rtems_interrupt_level level;
519
520  if (!isValidInterrupt(irq->name)) {
521    return 0;
522  }
523
524  /*
525   * Check if default handler is actually connected. If not issue an error.
526   * RATIONALE : to always have the same transition by forcing the user
527   * to get the previous handler before accepting to disconnect.
528   */
529  if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) {
530    return 0;
531  }
532
533  rtems_interrupt_disable(level);
534
535  if (is_siu_irq(irq->name)) {
536    /*
537     * disable interrupt at PIC level
538     */
539    BSP_irq_disable_at_siu(irq->name);
540  }
541
542  if (is_processor_irq(irq->name)) {
543    /*
544     * disable exception at processor level
545     */
546  }
547
548  /*
549   * Disable interrupt on device
550   */
551  if (irq->off)
552    irq->off(irq);
553
554  /*
555   * restore the default irq value
556   */
557  rtems_hdl_tbl[irq->name] = default_rtems_entry;
558
559  rtems_interrupt_enable(level);
560
561  return 1;
562}
563
564
565/*
566 * --------------------- RTEMS Global Irq Handler Mngt Routines -------------
567 */
568
569/*
570 * This function set up interrupt management dependent on the
571 * given configuration
572 */
573int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
574{
575  int                   i;
576  rtems_interrupt_level level;
577
578  /*
579   * Store various code accelerators
580   */
581  internal_config   = config;
582  default_rtems_entry   = config->defaultEntry;
583  rtems_hdl_tbl   = config->irqHdlTbl;
584
585  rtems_interrupt_disable(level);
586
587  /*
588   * start with SIU IRQs
589   */
590  for (i=BSP_SIU_IRQ_LOWEST_OFFSET;
591       i < BSP_SIU_IRQ_LOWEST_OFFSET + BSP_SIU_IRQ_NUMBER ;
592       i++) {
593
594    if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
595      BSP_irq_enable_at_siu(i);
596      if (rtems_hdl_tbl[i].on)
597        rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
598
599    } else {
600      if (rtems_hdl_tbl[i].off)
601        rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
602      BSP_irq_disable_at_siu(i);
603    }
604  }
605
606  /*
607   * finish with Processor exceptions handled like IRQs
608   */
609  for (i=BSP_PROCESSOR_IRQ_LOWEST_OFFSET;
610       i < BSP_PROCESSOR_IRQ_LOWEST_OFFSET + BSP_PROCESSOR_IRQ_NUMBER;
611       i++) {
612
613    if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
614      if (rtems_hdl_tbl[i].on)
615        rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
616
617    } else {
618      if (rtems_hdl_tbl[i].off)
619        rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
620    }
621  }
622
623  rtems_interrupt_enable(level);
624  return 1;
625}
626
627
628int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** config)
629{
630  *config = internal_config;
631  return 0;
632}
633
634
635/*
636 * High level IRQ handler called from shared_raw_irq_code_entry
637 */
638int C_dispatch_irq_handler (CPU_Interrupt_frame *frame, unsigned int excNum)
639{
640  register unsigned int irq;
641  register unsigned int msr;
642  register unsigned int new_msr;
643  register unsigned int pmce;
644  register unsigned int crit_pri_main_mask, per_mask;
645
646  switch (excNum) {
647    /*
648     * Handle decrementer interrupt
649     */
650    case ASM_DEC_VECTOR:
651
652      /* call the module specific handler and pass the specific handler */
653      rtems_hdl_tbl[BSP_DECREMENTER].hdl(0);
654
655      return 0;
656
657    case ASM_60X_SYSMGMT_VECTOR:
658
659      /* get the content of main interrupt status register */
660      pmce =  mpc5200.pmce;
661
662      /* main interrupts may be routed to SMI, see bit SMI/INT select
663       * bit in main int. priorities
664       */
665      while (CHK_MSE_STICKY(pmce)) {
666
667        /* check for main interrupt sources (hirarchical order)
668         * -> LO_int indicates peripheral sources
669         */
670        if (CHK_MSE_STICKY(pmce)) {
671          /* get source of main interrupt */
672          irq = MSE_SOURCE(pmce);
673          switch(irq) {
674
675            /* irq1-3, RTC, GPIO, TMR0-7 detected (attention:
676             * slice timer 2 is always routed to SMI)
677             */
678            case 0: /* slice timer 2 */
679            case 1:
680            case 2:
681            case 3:
682            case 5:
683            case 6:
684            case 7:
685            case 8:
686            case 9:
687            case 10:
688            case 11:
689            case 12:
690            case 13:
691            case 14:
692            case 15:
693            case 16:
694
695              /* add proper offset for main interrupts in
696               * the siu handler array
697               */
698              irq += BSP_MAIN_IRQ_LOWEST_OFFSET;
699
700              /* save original mask and disable all lower
701               * priorized main interrupts
702               */
703              crit_pri_main_mask =  mpc5200.crit_pri_main_mask;
704              mpc5200.crit_pri_main_mask |= irqMaskTable[irq];
705
706              /* enable interrupt nesting */
707              _CPU_MSR_GET(msr);
708              new_msr = msr | MSR_EE;
709              _CPU_MSR_SET(new_msr);
710
711              /* call the module specific handler and pass the
712               * specific handler
713               */
714              rtems_hdl_tbl[irq].hdl(0);
715
716              /* disable interrupt nesting */
717              _CPU_MSR_SET(msr);
718
719              /* restore original interrupt mask */
720              mpc5200.crit_pri_main_mask = crit_pri_main_mask;
721
722              break;
723
724            /* peripheral LO_int interrupt source detected */
725            case 4:
726
727              /* check for valid peripheral interrupt source */
728              if (CHK_PSE_STICKY(pmce)) {
729                /* get source of peripheral interrupt */
730                irq = PSE_SOURCE(pmce);
731
732                /* add proper offset for peripheral interrupts
733                 * in the siu handler array
734                 */
735                irq += BSP_PER_IRQ_LOWEST_OFFSET;
736
737                /* save original mask and disable all lower
738                 * priorized main interrupts
739                 */
740                per_mask =  mpc5200.per_mask;
741                mpc5200.per_mask |= irqMaskTable[irq];
742
743                /* enable interrupt nesting */
744                _CPU_MSR_GET(msr);
745                new_msr = msr | MSR_EE;
746                _CPU_MSR_SET(new_msr);
747
748                /* call the module specific handler and pass
749                 * the specific handler
750                 */
751                rtems_hdl_tbl[irq].hdl(0);
752
753                /* disable interrupt nesting */
754                _CPU_MSR_SET(msr);
755
756                /* restore original interrupt mask */
757                mpc5200.per_mask = per_mask;
758
759                /* force re-evaluation of peripheral interrupts */
760                CLR_PSE_STICKY(mpc5200.pmce);
761              } else {
762                /* this case may not occur: no valid peripheral
763                 * interrupt source
764                 */
765                printk("No valid peripheral LO_int interrupt source\n");
766              }
767              break;
768              /* error: unknown interrupt source */
769            default:
770              printk("Unknown peripheral LO_int interrupt source\n");
771              break;
772          }
773
774          /* force re-evaluation of main interrupts */
775          CLR_MSE_STICKY(mpc5200.pmce);
776        }
777
778        /* get the content of main interrupt status register */
779        pmce =  mpc5200.pmce;
780      }
781      break;
782
783    case ASM_EXT_VECTOR:
784      /* get the content of main interrupt status register */
785      pmce =  mpc5200.pmce;
786
787      /* critical interrupts may be routed to the core_int
788       * dependent on premature initialization, see bit 31 (CEbsH)
789       */
790      while((CHK_CE_SHADOW(pmce) && CHK_CSE_STICKY(pmce)) ||
791             CHK_MSE_STICKY(pmce) || CHK_PSE_STICKY(pmce) ) {
792
793        /* first: check for critical interrupt sources (hierarchical order)
794         * -> HI_int indicates peripheral sources
795         */
796        if (CHK_CE_SHADOW(pmce) && CHK_CSE_STICKY(pmce)) {
797          /* get source of critical interrupt */
798          irq = CSE_SOURCE(pmce);
799          switch(irq) {
800            /* irq0, slice timer 1 or ccs wakeup detected */
801            case 0:
802            case 1:
803            case 3:
804
805              /* add proper offset for critical interrupts in the siu
806               * handler array */
807              irq += BSP_CRIT_IRQ_LOWEST_OFFSET;
808
809              /* call the module specific handler and pass the
810               * specific handler */
811              rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle);
812              break;
813
814            /* peripheral HI_int interrupt source detected */
815            case 2:
816              /* check for valid peripheral interrupt source */
817              if (CHK_PSE_STICKY(pmce)) {
818                /* get source of peripheral interrupt */
819                irq = PSE_SOURCE(pmce);
820
821                /* add proper offset for peripheral interrupts in the
822                 * siu handler array */
823                irq += BSP_PER_IRQ_LOWEST_OFFSET;
824
825                /* save original mask and disable all lower
826                 * priorized main interrupts */
827                per_mask =  mpc5200.per_mask;
828                mpc5200.per_mask |= irqMaskTable[irq];
829
830                /* enable interrupt nesting */
831                _CPU_MSR_GET(msr);
832                new_msr = msr | MSR_EE;
833                _CPU_MSR_SET(new_msr);
834
835                /* call the module specific handler and pass the
836                 * specific handler */
837                rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle);
838
839                _CPU_MSR_SET(msr);
840
841                /* restore original interrupt mask */
842                mpc5200.per_mask = per_mask;
843
844                /* force re-evaluation of peripheral interrupts */
845                CLR_PSE_STICKY(mpc5200.pmce);
846              } else {
847                /* this case may not occur: no valid peripheral
848                 * interrupt source */
849                printk("No valid peripheral HI_int interrupt source\n");
850              }
851              break;
852            default:
853              /* error: unknown interrupt source */
854              printk("Unknown HI_int interrupt source\n");
855              break;
856          }
857          /* force re-evaluation of critical interrupts */
858          CLR_CSE_STICKY(mpc5200.pmce);
859        }
860
861        /* second: check for main interrupt sources (hierarchical order)
862         * -> LO_int indicates peripheral sources */
863        if (CHK_MSE_STICKY(pmce)) {
864          /* get source of main interrupt */
865          irq = MSE_SOURCE(pmce);
866
867          switch (irq) {
868
869            /* irq1-3, RTC, GPIO, TMR0-7 detected (attention: slice timer
870             * 2 is always routed to SMI) */
871            case 1:
872            case 2:
873            case 3:
874            case 5:
875            case 6:
876            case 7:
877            case 8:
878            case 9:
879            case 10:
880            case 11:
881            case 12:
882            case 13:
883            case 14:
884            case 15:
885            case 16:
886              /* add proper offset for main interrupts in the siu
887               * handler array */
888              irq += BSP_MAIN_IRQ_LOWEST_OFFSET;
889
890              /* save original mask and disable all lower priorized
891               * main interrupts*/
892              crit_pri_main_mask =  mpc5200.crit_pri_main_mask;
893              mpc5200.crit_pri_main_mask |= irqMaskTable[irq];
894
895              /* enable interrupt nesting */
896              _CPU_MSR_GET(msr);
897              new_msr = msr | MSR_EE;
898              _CPU_MSR_SET(new_msr);
899
900              /* call the module specific handler and pass the specific
901               * handler */
902              rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle);
903
904              /* disable interrupt nesting */
905              _CPU_MSR_SET(msr);
906
907              /* restore original interrupt mask */
908              mpc5200.crit_pri_main_mask = crit_pri_main_mask;
909              break;
910
911          /* peripheral LO_int interrupt source detected */
912            case 4:
913              /* check for valid peripheral interrupt source */
914              if (CHK_PSE_STICKY(pmce)) {
915                /* get source of peripheral interrupt */
916                irq = PSE_SOURCE(pmce);
917
918                /* add proper offset for peripheral interrupts in the siu
919                 * handler array */
920                irq += BSP_PER_IRQ_LOWEST_OFFSET;
921
922                /* save original mask and disable all lower priorized main
923                 * interrupts */
924                per_mask =  mpc5200.per_mask;
925                mpc5200.per_mask |= irqMaskTable[irq];
926
927                /* enable interrupt nesting */
928                _CPU_MSR_GET(msr);
929                new_msr = msr | MSR_EE;
930                _CPU_MSR_SET(new_msr);
931
932                /* call the module specific handler and pass the
933                 * specific handler */
934                rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle);
935
936                /* disable interrupt nesting */
937                _CPU_MSR_SET(msr);
938
939                /* restore original interrupt mask */
940                mpc5200.per_mask = per_mask;
941
942                /* force re-evaluation of peripheral interrupts */
943                CLR_PSE_STICKY(mpc5200.pmce);
944              } else {
945                /* this case may not occur: no valid peripheral
946                 * interrupt source */
947                printk("No valid peripheral LO_int interrupt source\n");
948              }
949              break;
950
951            /* error: unknown interrupt source */
952            default:
953              printk("Unknown peripheral LO_int interrupt source\n");
954              break;
955          }
956          /* force re-evaluation of main interrupts */
957          CLR_MSE_STICKY(mpc5200.pmce);
958        }
959        /* get the content of main interrupt status register */
960        pmce =  mpc5200.pmce;
961      }
962      break;
963
964    default:
965      printk("Unknown processor exception\n");
966      break;
967
968  } /* end of switch(excNum) */
969  return 0;
970}
971
972
973void _ThreadProcessSignalsFromIrq (BSP_Exception_frame* ctx)
974{
975  /*
976   * Process pending signals that have not already been
977   * processed by _Thread_Displatch. This happens quite
978   * unfrequently : the ISR must have posted an action
979   * to the current running thread.
980   */
981  if ( _Thread_Do_post_task_switch_extension ||
982       _Thread_Executing->do_post_task_switch_extension )
983    {
984
985    _Thread_Executing->do_post_task_switch_extension = FALSE;
986    _API_extensions_Run_postswitch();
987
988    }
989  /*
990   * I plan to process other thread related events here.
991   * This will include DEBUG session requested from keyboard...
992   */
993}
Note: See TracBrowser for help on using the repository browser.