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

4.104.114.84.95
Last change on this file since 1af911b8 was 1af911b8, checked in by Ralf Corsepius <ralf.corsepius@…>, on 10/17/06 at 02:40:57

Convert to utf-8.

  • Property mode set to 100644
File size: 29.3 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.OARcorp.com/rtems/license.html.                        */
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) & ((int)irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET));
127
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) && ((int)irqLine >= BSP_SIU_IRQ_LOWEST_OFFSET));
137
138  }
139
140
141/*
142 * Check for SIU IRQ and return base index
143 */
144static inline int get_siu_irq_base_index(const rtems_irq_symbolic_name irqLine)
145  {
146
147  if(irqLine <= BSP_PER_IRQ_MAX_OFFSET)
148    return BSP_PER_IRQ_LOWEST_OFFSET;
149  else
150    if(irqLine <= BSP_MAIN_IRQ_MAX_OFFSET)
151      return BSP_MAIN_IRQ_LOWEST_OFFSET;
152    else
153      if(irqLine <= BSP_CRIT_IRQ_MAX_OFFSET)
154        return BSP_CRIT_IRQ_LOWEST_OFFSET;
155      else
156        return -1;
157
158  }
159
160
161static inline void BSP_enable_per_irq_at_siu(const rtems_irq_symbolic_name irqLine)
162  {
163  uint8_t lo_hi_ind = 0, prio_index_offset;
164  uint32_t *reg;
165  rtems_irq_prio *irqPrioTable = internal_config->irqPrioTbl;
166  volatile uint32_t per_pri_1,main_pri_1, crit_pri_main_mask, per_mask;
167
168  /* calculate the index offset of priority value bit field */
169  prio_index_offset = (irqLine - BSP_PER_IRQ_LOWEST_OFFSET) % 8;
170
171  /* set interrupt priorities */
172  if(irqPrioTable[irqLine] <= 15)
173    {
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
188      /* set critical HI_int priority */
189      reg = (uint32_t *)(&(mpc5200.crit_pri_main_mask));
190      *reg |= (irqPrioTable[BSP_SIU_IRQ_HI_INT] << 26);
191
192          /*
193           * critical interrupt handling for the 603le core is not
194           * yet supported, routing of critical interrupts is forced
195           * to core_int (bit 31 / CEb)
196           */
197           mpc5200.ext_en_type |= 1;
198
199      }
200    else
201      {
202
203      if(irqPrioTable[irqLine] <= 15)
204                {
205
206            /* set main LO_int priority */
207            reg = (uint32_t *)(&(mpc5200.main_pri_1));
208            *reg |= (irqPrioTable[BSP_SIU_IRQ_LO_INT] << 16);
209
210                }
211
212      }
213
214    }
215
216  /* if LO_int ind., enable (unmask) main interrupt */
217  if(!lo_hi_ind)
218    {
219
220        mpc5200.crit_pri_main_mask &= ~(0x80000000 >> SIU_MaskBit[BSP_SIU_IRQ_LO_INT]);
221
222    }
223
224
225  /* enable (unmask) peripheral interrupt */
226  mpc5200.per_mask &= ~(0x80000000 >> SIU_MaskBit[irqLine]);
227
228  main_pri_1         = mpc5200.main_pri_1;
229  crit_pri_main_mask = mpc5200.crit_pri_main_mask;
230  per_pri_1          = mpc5200.per_pri_1;
231  per_mask           = mpc5200.per_mask;
232
233
234  }
235
236
237static inline void BSP_enable_main_irq_at_siu(const rtems_irq_symbolic_name irqLine)
238  {
239
240  uint8_t prio_index_offset;
241  uint32_t *reg;
242  rtems_irq_prio *irqPrioTable = internal_config->irqPrioTbl;
243
244  /* calculate the index offset of priority value bit field */
245  prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8;
246
247  /* set main interrupt priority */
248  if(irqPrioTable[irqLine] <= 15)
249    {
250
251    /* set main int priority */
252        reg = (uint32_t *)(&(mpc5200.main_pri_1));
253
254        /* choose proper register */
255    reg += (irqLine >> 3);
256
257    /* set priority as given in priority table */
258    *reg |= (irqPrioTable[irqLine] << (28 - (prio_index_offset << 2)));
259
260    if((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3))
261      {
262
263      /* enable external irq-pin */
264          mpc5200.ext_en_type |= (0x80000000 >> (20 + prio_index_offset));
265
266      }
267
268    }
269
270  /* enable (unmask) main interrupt */
271  mpc5200.crit_pri_main_mask &= ~(0x80000000 >> SIU_MaskBit[irqLine]);
272
273  }
274
275
276static inline void BSP_enable_crit_irq_at_siu(const rtems_irq_symbolic_name irqLine)
277  {
278
279  uint8_t prio_index_offset;
280  uint32_t *reg;
281  rtems_irq_prio *irqPrioTable = internal_config->irqPrioTbl;
282
283  prio_index_offset = irqLine - BSP_CRIT_IRQ_LOWEST_OFFSET;
284
285  /*
286   * critical interrupt handling for the 603Le core is not
287   * yet supported, routing of critical interrupts is forced
288   * to core_int (bit 31 / CEb)
289   */
290  mpc5200.ext_en_type |= 1;
291
292
293  /* set critical interrupt priorities */
294  if(irqPrioTable[irqLine] <= 3)
295    {
296
297    /* choose proper register */
298    reg = (uint32_t *)(&(mpc5200.crit_pri_main_mask));
299
300    /* set priority as given in priority table */
301    *reg |= (irqPrioTable[irqLine] << (30 - (prio_index_offset << 1)));
302
303    /* external irq0-pin */
304    if(irqLine == BSP_SIU_IRQ_IRQ1)
305      {
306
307      /* enable external irq-pin */
308          mpc5200.ext_en_type |= (0x80000000 >> (20 + prio_index_offset));
309
310      }
311
312    }
313
314  }
315
316
317static inline void BSP_disable_per_irq_at_siu(const rtems_irq_symbolic_name irqLine)
318  {
319
320  uint8_t prio_index_offset;
321  uint32_t *reg;
322
323  /* calculate the index offset of priority value bit field */
324  prio_index_offset = (irqLine - BSP_PER_IRQ_LOWEST_OFFSET) % 8;
325
326  /* disable (mask) peripheral interrupt */
327  mpc5200.per_mask |= (0x80000000 >> SIU_MaskBit[irqLine]);
328
329  /* reset priority to lowest level (reset value) */
330  reg = (uint32_t *)(&(mpc5200.per_pri_1));
331  reg += (irqLine >> 3);
332  *reg &= ~(15 << (28 - (prio_index_offset << 2)));
333
334  }
335
336
337static inline void BSP_disable_main_irq_at_siu(const rtems_irq_symbolic_name irqLine)
338  {
339
340  uint8_t prio_index_offset;
341  uint32_t *reg;
342
343  /* calculate the index offset of priority value bit field */
344  prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8;
345
346  /* disable (mask) main interrupt */
347  mpc5200.crit_pri_main_mask |= (0x80000000 >> SIU_MaskBit[irqLine]);
348
349  if((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3))
350    {
351
352    /* disable external irq-pin */
353    mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset));
354
355    }
356
357  /* reset priority to lowest level (reset value) */
358  reg = (uint32_t *)(&(mpc5200.main_pri_1));
359  reg  += (irqLine >> 3);
360  *reg &= ~(15 << (28 - (prio_index_offset << 2)));
361
362  }
363
364
365static inline void BSP_disable_crit_irq_at_siu(const rtems_irq_symbolic_name irqLine)
366  {
367
368  uint8_t prio_index_offset;
369  uint32_t *reg;
370
371  prio_index_offset = irqLine - BSP_CRIT_IRQ_LOWEST_OFFSET;
372
373  /* reset critical int priority to lowest level (reset value) */
374  reg = (uint32_t *)(&(mpc5200.crit_pri_main_mask));
375  *reg &= ~(3 << (30 - (prio_index_offset << 1)));
376
377  if(irqLine == BSP_SIU_IRQ_IRQ1)
378    {
379
380    /* disable external irq0-pin */
381    mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset));
382
383    }
384
385  }
386
387
388/*
389 * ------------------------ RTEMS Irq helper functions ----------------
390 */
391
392
393/*
394 * This function check that the value given for the irq line
395 * is valid.
396 */
397static int isValidInterrupt(int irq)
398  {
399  if ( (irq < BSP_LOWEST_OFFSET) || (irq > BSP_MAX_OFFSET) )
400    return 0;
401  return 1;
402  }
403
404
405 /*
406  * This function enables a given siu interrupt
407  */
408int BSP_irq_enable_at_siu(const rtems_irq_symbolic_name irqLine)
409  {
410  int base_index;
411
412  if(is_siu_irq(irqLine))
413    {
414
415
416    if((base_index = get_siu_irq_base_index(irqLine)) != -1)
417      {
418
419      switch(base_index)
420        {
421
422        case BSP_PER_IRQ_LOWEST_OFFSET:
423          BSP_enable_per_irq_at_siu(irqLine);
424          break;
425
426            case BSP_MAIN_IRQ_LOWEST_OFFSET:
427          BSP_enable_main_irq_at_siu(irqLine);
428          break;
429
430            case BSP_CRIT_IRQ_LOWEST_OFFSET:
431              BSP_enable_crit_irq_at_siu(irqLine);
432              break;
433
434            default:
435          printk("No valid base index\n");
436          break;
437
438        }
439
440      }
441
442    }
443
444  return 0;
445
446  }
447
448/*
449 * This function disables a given siu interrupt
450 */
451int BSP_irq_disable_at_siu(const rtems_irq_symbolic_name irqLine)
452  {
453  int base_index;
454
455  if ( (base_index = get_siu_irq_base_index(irqLine)) == -1)
456    return 1;
457
458  switch(base_index)
459    {
460
461    case BSP_PER_IRQ_LOWEST_OFFSET:
462      BSP_disable_per_irq_at_siu(irqLine);
463
464      break;
465
466        case BSP_MAIN_IRQ_LOWEST_OFFSET:
467      BSP_disable_main_irq_at_siu(irqLine);
468      break;
469
470        case BSP_CRIT_IRQ_LOWEST_OFFSET:
471          BSP_disable_crit_irq_at_siu(irqLine);
472          break;
473
474    default:
475      printk("No valid base index\n");
476      break;
477
478    }
479
480  return 0;
481  }
482
483
484/*
485 * ------------------------ RTEMS Single Irq Handler Mngt Routines ----------------
486 */
487
488 /*
489  * This function removes the default entry and installs a device interrupt handler
490  */
491int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq)
492  {
493  unsigned int level;
494
495  if(!isValidInterrupt(irq->name))
496    {
497
498    printk("not a valid interrupt\n");
499    return 0;
500
501    }
502
503  /*
504   * Check if default handler is actually connected. If not issue an error.
505   * RATIONALE : to always have the same transition by forcing the user
506   * to get the previous handler before accepting to disconnect.
507   */
508  if (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl)
509    {
510
511    printk( "Default handler not there\n" );
512    return 0;
513
514    }
515
516  _CPU_ISR_Disable(level);
517
518  /*
519   * store the data provided by user
520   */
521  rtems_hdl_tbl[irq->name] = *irq;
522
523  if(is_siu_irq(irq->name))
524    {
525
526    /*
527     * Enable interrupt at siu level
528     */
529    BSP_irq_enable_at_siu(irq->name);
530
531    }
532  else
533    {
534
535    if(is_processor_irq(irq->name))
536      {
537
538      /*
539       * Should Enable exception at processor level but not needed.  Will restore
540       * EE flags at the end of the routine anyway.
541       */
542
543
544      }
545    else
546      {
547
548          printk("not a valid interrupt\n");
549          return 0;
550
551          }
552
553    }
554
555
556    /*
557     * Enable interrupt on device
558     */
559  irq->on(irq);
560
561  _CPU_ISR_Enable(level);
562
563  return 1;
564
565  }
566
567
568 /*
569  * This function procures the current interrupt handler
570  */
571int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* irq)
572  {
573
574  if(!isValidInterrupt(irq->name))
575    {
576
577    return 0;
578
579    }
580
581  *irq = rtems_hdl_tbl[irq->name];
582  return 1;
583
584  }
585
586
587 /*
588  * This function removes a device interrupt handler and restores the default entry
589  */
590int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq)
591  {
592  unsigned int level;
593
594  if(!isValidInterrupt(irq->name))
595    {
596
597    return 0;
598
599    }
600
601  /*
602   * Check if default handler is actually connected. If not issue an error.
603   * RATIONALE : to always have the same transition by forcing the user
604   * to get the previous handler before accepting to disconnect.
605   */
606  if(rtems_hdl_tbl[irq->name].hdl != irq->hdl)
607    {
608
609    return 0;
610
611    }
612
613  _CPU_ISR_Disable(level);
614
615  if(is_siu_irq(irq->name))
616    {
617
618    /*
619     * disable interrupt at PIC level
620     */
621    BSP_irq_disable_at_siu(irq->name);
622
623    }
624
625  if(is_processor_irq(irq->name))
626    {
627    /*
628     * disable exception at processor level
629     */
630    }
631
632  /*
633   * Disable interrupt on device
634   */
635  irq->off(irq);
636
637  /*
638   * restore the default irq value
639   */
640  rtems_hdl_tbl[irq->name] = default_rtems_entry;
641
642  _CPU_ISR_Enable(level);
643
644  return 1;
645
646  }
647
648
649/*
650 * ------------------------ RTEMS Global Irq Handler Mngt Routines ----------------
651 */
652
653/*
654 * This function set up interrupt management dependent on the given configuration
655 */
656int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
657  {
658  int i;
659  unsigned int level;
660
661 /*
662  * Store various code accelerators
663  */
664  internal_config               = config;
665  default_rtems_entry   = config->defaultEntry;
666  rtems_hdl_tbl                 = config->irqHdlTbl;
667
668  _CPU_ISR_Disable(level);
669
670  /*
671   * start with SIU IRQs
672   */
673  for (i=BSP_SIU_IRQ_LOWEST_OFFSET; i < BSP_SIU_IRQ_LOWEST_OFFSET + BSP_SIU_IRQ_NUMBER ; i++)
674    {
675
676    if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl)
677      {
678
679          BSP_irq_enable_at_siu(i);
680          rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
681
682      }
683    else
684      {
685
686          rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
687          BSP_irq_disable_at_siu(i);
688
689      }
690
691    }
692
693  /*
694   * finish with Processor exceptions handled like IRQs
695   */
696  for (i=BSP_PROCESSOR_IRQ_LOWEST_OFFSET; i < BSP_PROCESSOR_IRQ_LOWEST_OFFSET + BSP_PROCESSOR_IRQ_NUMBER; i++)
697    {
698
699    if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl)
700      {
701
702          rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
703
704      }
705    else
706      {
707
708          rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
709
710      }
711
712    }
713
714    _CPU_ISR_Enable(level);
715    return 1;
716
717  }
718
719
720int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** config)
721  {
722
723  *config = internal_config;
724  return 0;
725
726  }
727
728
729/*
730 * High level IRQ handler called from shared_raw_irq_code_entry
731 */
732void C_dispatch_irq_handler (CPU_Interrupt_frame *frame, unsigned int excNum)
733  {
734  register unsigned int irq;
735  register unsigned int msr;
736  register unsigned int new_msr;
737  register unsigned int pmce;
738  register unsigned int crit_pri_main_mask, per_mask;
739
740  switch(excNum)
741    {
742
743
744    /*
745     * Handle decrementer interrupt
746     */
747    case ASM_DEC_VECTOR:
748
749      /* call the module specific handler and pass the specific handler */
750      rtems_hdl_tbl[BSP_DECREMENTER].hdl(0);
751
752      return;
753
754    case ASM_SYSMGMT_VECTOR:
755
756      /* get the content of main interrupt status register */
757          pmce =  mpc5200.pmce;
758
759          /* main interrupts may be routed to SMI, see bit SMI/INT select bit in main int. priorities */
760          while(CHK_MSE_STICKY(pmce))
761            {
762
763        /* check for main interrupt sources (hirarchical order) -> LO_int indicates peripheral sources */
764        if(CHK_MSE_STICKY(pmce))
765          {
766
767          /* get source of main interrupt */
768                  irq = MSE_SOURCE(pmce);
769
770              switch(irq)
771            {
772
773            /* irq1-3, RTC, GPIO, TMR0-7 detected (attention: slice timer 2 is always routed to SMI) */
774            case 0: /* slice timer 2 */
775            case 1:
776            case 2:
777            case 3:
778            case 5:
779            case 6:
780            case 7:
781            case 8:
782            case 9:
783            case 10:
784            case 11:
785            case 12:
786            case 13:
787            case 14:
788            case 15:
789            case 16:
790
791              /* add proper offset for main interrupts in the siu handler array */
792                          irq += BSP_MAIN_IRQ_LOWEST_OFFSET;
793
794              /* save original mask and disable all lower priorized main interrupts*/
795                          crit_pri_main_mask =  mpc5200.crit_pri_main_mask;
796                      mpc5200.crit_pri_main_mask |= irqMaskTable[irq];
797
798              /* enable interrupt nesting */
799                          _CPU_MSR_GET(msr);
800                          new_msr = msr | MSR_EE;
801                          _CPU_MSR_SET(new_msr);
802
803              /* call the module specific handler and pass the specific handler */
804              rtems_hdl_tbl[irq].hdl(0);
805
806              /* disable interrupt nesting */
807              _CPU_MSR_SET(msr);
808
809              /* restore original interrupt mask */
810              mpc5200.crit_pri_main_mask = crit_pri_main_mask;
811
812              break;
813
814            /* peripheral LO_int interrupt source detected */
815            case 4:
816
817              /* check for valid peripheral interrupt source */
818                          if(CHK_PSE_STICKY(pmce))
819                            {
820
821                /* get source of peripheral interrupt */
822                    irq = PSE_SOURCE(pmce);
823
824                    /* add proper offset for peripheral interrupts in the siu handler array */
825                    irq += BSP_PER_IRQ_LOWEST_OFFSET;
826
827                    /* save original mask and disable all lower priorized main interrupts */
828                per_mask =  mpc5200.per_mask;
829                mpc5200.per_mask |= irqMaskTable[irq];
830
831                /* enable interrupt nesting */
832                                _CPU_MSR_GET(msr);
833                                new_msr = msr | MSR_EE;
834                                _CPU_MSR_SET(new_msr);
835
836                /* call the module specific handler and pass the specific handler */
837                    rtems_hdl_tbl[irq].hdl(0);
838
839
840                    /* disable interrupt nesting */
841                                _CPU_MSR_SET(msr);
842
843                                /* restore original interrupt mask */
844                mpc5200.per_mask = per_mask;
845
846                /* force re-evaluation of peripheral interrupts */
847                    CLR_PSE_STICKY(mpc5200.pmce);
848
849                            }
850                          /* this case may not occur: no valid peripheral interrupt source */
851                  else
852                    {
853
854                            printk("No valid peripheral LO_int interrupt source\n");
855
856                            }
857
858              break;
859
860            /* error: unknown interrupt source */
861                default:
862                  printk("Unknown peripheral LO_int interrupt source\n");
863                  break;
864
865                }
866
867              /* force re-evaluation of main interrupts */
868          CLR_MSE_STICKY(mpc5200.pmce);
869
870          }
871
872        /* get the content of main interrupt status register */
873                pmce =  mpc5200.pmce;
874
875            }
876
877      break;
878
879    case ASM_EXT_VECTOR:
880
881      /* get the content of main interrupt status register */
882          pmce =  mpc5200.pmce;
883
884      /* critical interrupts may be routed to the core_int dependent on premature initialization, see bit 31 (CEbsH) */
885      while((CHK_CE_SHADOW(pmce) && CHK_CSE_STICKY(pmce)) || CHK_MSE_STICKY(pmce) || CHK_PSE_STICKY(pmce) )
886        {
887
888        /* first: check for critical interrupt sources (hirarchical order) -> HI_int indicates peripheral sources */
889        if(CHK_CE_SHADOW(pmce) && CHK_CSE_STICKY(pmce))
890          {
891
892          /* get source of critical interrupt */
893              irq = CSE_SOURCE(pmce);
894
895              switch(irq)
896            {
897            /* irq0, slice timer 1 or ccs wakeup detected */
898            case 0:
899            case 1:
900            case 3:
901
902              /* add proper offset for critical interrupts in the siu handler array */
903                          irq += BSP_CRIT_IRQ_LOWEST_OFFSET;
904
905              /* call the module specific handler and pass the specific handler */
906              rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle);
907
908              break;
909
910            /* peripheral HI_int interrupt source detected */
911            case 2:
912
913              /* check for valid peripheral interrupt source */
914                          if(CHK_PSE_STICKY(pmce))
915                            {
916
917                /* get source of peripheral interrupt */
918                irq = PSE_SOURCE(pmce);
919
920                /* add proper offset for peripheral interrupts in the siu handler array */
921                irq += BSP_PER_IRQ_LOWEST_OFFSET;
922
923                /* save original mask and disable all lower priorized main 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 specific handler */
933                rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle);
934
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
945                            }
946                          /* this case may not occur: no valid peripheral interrupt source */
947                  else
948                    {
949
950                            printk("No valid peripheral HI_int interrupt source\n");
951
952                            }
953
954              break;
955
956            /* error: unknown interrupt source */
957                default:
958                  printk("Unknown HI_int interrupt source\n");
959                  break;
960
961                }
962
963              /* force re-evaluation of critical interrupts */
964              CLR_CSE_STICKY(mpc5200.pmce);
965
966          }
967
968        /* second: check for main interrupt sources (hirarchical order) -> LO_int indicates peripheral sources */
969        if(CHK_MSE_STICKY(pmce))
970          {
971
972          /* get source of main interrupt */
973                  irq = MSE_SOURCE(pmce);
974
975              switch(irq)
976            {
977
978            /* irq1-3, RTC, GPIO, TMR0-7 detected (attention: slice timer 2 is always routed to SMI) */
979            case 1:
980            case 2:
981            case 3:
982            case 5:
983            case 6:
984            case 7:
985            case 8:
986            case 9:
987            case 10:
988            case 11:
989            case 12:
990            case 13:
991            case 14:
992            case 15:
993            case 16:
994
995              /* add proper offset for main interrupts in the siu handler array */
996                          irq += BSP_MAIN_IRQ_LOWEST_OFFSET;
997
998              /* save original mask and disable all lower priorized main interrupts*/
999                          crit_pri_main_mask =  mpc5200.crit_pri_main_mask;
1000                      mpc5200.crit_pri_main_mask |= irqMaskTable[irq];
1001
1002              /* enable interrupt nesting */
1003                          _CPU_MSR_GET(msr);
1004                          new_msr = msr | MSR_EE;
1005                          _CPU_MSR_SET(new_msr);
1006
1007              /* call the module specific handler and pass the specific handler */
1008              rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle);
1009
1010              /* disable interrupt nesting */
1011              _CPU_MSR_SET(msr);
1012
1013              /* restore original interrupt mask */
1014              mpc5200.crit_pri_main_mask = crit_pri_main_mask;
1015
1016              break;
1017
1018            /* peripheral LO_int interrupt source detected */
1019            case 4:
1020
1021              /* check for valid peripheral interrupt source */
1022                          if(CHK_PSE_STICKY(pmce))
1023                            {
1024
1025                /* get source of peripheral interrupt */
1026                    irq = PSE_SOURCE(pmce);
1027
1028                    /* add proper offset for peripheral interrupts in the siu handler array */
1029                    irq += BSP_PER_IRQ_LOWEST_OFFSET;
1030
1031                    /* save original mask and disable all lower priorized main interrupts */
1032                per_mask =  mpc5200.per_mask;
1033                mpc5200.per_mask |= irqMaskTable[irq];
1034
1035                /* enable interrupt nesting */
1036                                _CPU_MSR_GET(msr);
1037                                new_msr = msr | MSR_EE;
1038                                _CPU_MSR_SET(new_msr);
1039
1040                /* call the module specific handler and pass the specific handler */
1041                    rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle);
1042
1043
1044                    /* disable interrupt nesting */
1045                                _CPU_MSR_SET(msr);
1046
1047                                /* restore original interrupt mask */
1048                mpc5200.per_mask = per_mask;
1049
1050                /* force re-evaluation of peripheral interrupts */
1051                    CLR_PSE_STICKY(mpc5200.pmce);
1052
1053                            }
1054                          /* this case may not occur: no valid peripheral interrupt source */
1055                  else
1056                    {
1057
1058                            printk("No valid peripheral LO_int interrupt source\n");
1059
1060                            }
1061
1062              break;
1063
1064            /* error: unknown interrupt source */
1065                default:
1066                  printk("Unknown peripheral LO_int interrupt source\n");
1067                  break;
1068
1069                }
1070
1071              /* force re-evaluation of main interrupts */
1072          CLR_MSE_STICKY(mpc5200.pmce);
1073
1074          }
1075
1076
1077        /* get the content of main interrupt status register */
1078                pmce =  mpc5200.pmce;
1079
1080            }
1081
1082      break;
1083
1084    default:
1085      printk("Unknown processor exception\n");
1086          break;
1087
1088    } /* end of switch(excNum) */
1089
1090  return;
1091
1092  }
1093
1094
1095void _ThreadProcessSignalsFromIrq (BSP_Exception_frame* ctx)
1096  {
1097  /*
1098   * Process pending signals that have not already been
1099   * processed by _Thread_Displatch. This happens quite
1100   * unfrequently : the ISR must have posted an action
1101   * to the current running thread.
1102   */
1103  if ( _Thread_Do_post_task_switch_extension ||
1104       _Thread_Executing->do_post_task_switch_extension )
1105    {
1106
1107    _Thread_Executing->do_post_task_switch_extension = FALSE;
1108    _API_extensions_Run_postswitch();
1109
1110    }
1111  /*
1112   * I plan to process other thread related events here.
1113   * This will include DEBUG session requested from keyboard...
1114   */
1115}
Note: See TracBrowser for help on using the repository browser.