source: rtems/c/src/lib/libcpu/powerpc/ppc403/ictrl/ictrl.c @ e9ae97fb

4.104.114.84.95
Last change on this file since e9ae97fb was e9ae97fb, checked in by Joel Sherrill <joel.sherrill@…>, on 11/09/01 at 00:04:57

2001-11-08 Dennis Ehlin (ECS) <Dennis.Ehlin@…>

This modification is part of the submitted modifications necessary to
support the IBM PPC405 family. This submission was reviewed by
Thomas Doerfler <Thomas.Doerfler@…> who ensured it did
not negatively impact the ppc403 BSPs. The submission and tracking
process was captured as PR50.

  • ppc403/console/console405.c ppc403/tty_drv/.cvsignore, ppc403/tty_drv/Makefile.am, ppc403/tty_drv/tty_drv.c, ppc403/tty_drv/tty_drv.h: New files.
  • Makefile.am, README, configure.ac, old_exception_processing/cpu.c, old_exception_processing/cpu.h, ppc403/Makefile.am, ppc403/clock/clock.c, ppc403/console/Makefile.am, ppc403/console/console.c, ppc403/ictrl/ictrl.c, ppc403/ictrl/ictrl.h, ppc403/timer/timer.c: Modified.
  • Property mode set to 100644
File size: 6.4 KB
Line 
1/*  ictrl.c
2 *
3 *  This routine installs and handles external interrupt vectors for
4 *  PowerPC 403 CPU built-in external interrupt controller
5 *
6 *  Author: Thomas Doerfler <td@imd.m.isar.de>
7 *
8 *  COPYRIGHT (c) 1998 by IMD, Puchheim, Germany
9 *
10 *  To anyone who acknowledges that this file is provided "AS IS"
11 *  without any express or implied warranty:
12 *      permission to use, copy, modify, and distribute this file
13 *      for any purpose is hereby granted without fee, provided that
14 *      the above copyright notice and this notice appears in all
15 *      copies, and that the name of IMD not be used in
16 *      advertising or publicity pertaining to distribution of the
17 *      software without specific, written prior permission.
18 *      IMD makes no representations about the suitability
19 *      of this software for any purpose.
20 *
21 *  Modifications for PPC405GP by Dennis Ehlin
22 *
23 */
24
25#include "ictrl.h"
26#include <rtems.h>
27#include <rtems/libio.h>
28
29#include <stdlib.h>                     /* for atexit() */
30
31/*
32 *  ISR vector table to dispatch external interrupts
33 */
34 
35rtems_isr_entry ictrl_vector_table[PPC_IRQ_EXT_MAX];
36
37/*
38 *
39 *  some utilities to access the EXI* registers
40 *
41 */
42
43/*
44 *  clear bits in EXISR that have a bit set in mask
45 */
46#if defined(ppc405)
47RTEMS_INLINE_ROUTINE void
48clr_exisr(unsigned32 mask)
49{
50    asm volatile ("mtdcr 0xC0,%0"::"r" (mask));/*EXISR*/
51}
52
53/*
54 *  get value of EXISR
55 */
56RTEMS_INLINE_ROUTINE unsigned32
57get_exisr(void)
58{
59    unsigned32 val;
60
61    asm volatile ("mfdcr %0,0xC0":"=r" (val));/*EXISR*/
62    return val;
63}
64
65/*
66 *  get value of EXIER
67 */
68RTEMS_INLINE_ROUTINE unsigned32
69get_exier(void)
70{
71    unsigned32 val;
72    asm volatile ("mfdcr %0,0xC2":"=r" (val));/*EXIER*/
73    return val;
74}
75
76/*
77 *  set value of EXIER
78 */
79RTEMS_INLINE_ROUTINE void
80set_exier(unsigned32 val)
81{
82    asm volatile ("mtdcr 0xC2,%0"::"r" (val));/*EXIER*/
83}
84
85#else /* not ppc405 */
86
87RTEMS_INLINE_ROUTINE void
88clr_exisr(unsigned32 mask)
89{
90    asm volatile ("mtdcr 0x40,%0"::"r" (mask));/*EXISR*/
91}
92
93/*
94 *  get value of EXISR
95 */
96RTEMS_INLINE_ROUTINE unsigned32
97get_exisr(void)
98{
99    unsigned32 val;
100
101    asm volatile ("mfdcr %0,0x40":"=r" (val));/*EXISR*/
102    return val;
103}
104
105/*
106 *  get value of EXIER
107 */
108RTEMS_INLINE_ROUTINE unsigned32
109get_exier(void)
110{
111    unsigned32 val;
112    asm volatile ("mfdcr %0,0x42":"=r" (val));/*EXIER*/
113    return val;
114}
115
116/*
117 *  set value of EXIER
118 */
119RTEMS_INLINE_ROUTINE void
120set_exier(unsigned32 val)
121{
122    asm volatile ("mtdcr 0x42,%0"::"r" (val));/*EXIER*/
123}
124#endif /* ppc405 */
125/*
126 *  enable an external interrupt, make this interrupt consistent
127 */
128RTEMS_INLINE_ROUTINE void
129enable_ext_irq( unsigned32 mask)
130{
131    unsigned32 isrlvl;
132    _CPU_ISR_Disable(isrlvl);
133    set_exier(get_exier() | ((mask)&PPC_EXI_MASK));
134    _CPU_ISR_Enable(isrlvl);
135}
136
137/*
138 *  disable an external interrupt, make this interrupt consistent
139 */
140RTEMS_INLINE_ROUTINE void
141disable_ext_irq( unsigned32 mask)
142{
143    unsigned32 isrlvl;
144    _CPU_ISR_Disable(isrlvl);
145    set_exier(get_exier() & ~(mask) & PPC_EXI_MASK);
146    _CPU_ISR_Enable(isrlvl);
147}
148
149/*
150 *
151 *  this function is called, when a external interrupt is present and
152 *  enabled but there is no handler installed. It will clear
153 *  the corresponding enable bits and call the spurious handler
154 *  present in the CPU Configuration Table, if any.
155 *
156 */
157void
158ictrl_spurious_handler(unsigned32 spurious_mask,
159                       CPU_Interrupt_frame *cpu_frame)
160{
161  int v;
162 
163  for (v=0; v < PPC_IRQ_EXT_MAX; v++) {
164    if (VEC_TO_EXMSK(v) & spurious_mask) {
165      clr_exisr(VEC_TO_EXMSK(v));
166      disable_ext_irq(VEC_TO_EXMSK(v));
167#if 0
168      printf("spurious external interrupt: %d at pc 0x%x; disabling\n",
169             vector, cpu_frame->Interrupt.pcoqfront);
170#endif
171      if (rtems_cpu_configuration_get_spurious_handler()) {
172        rtems_cpu_configuration_get_spurious_handler()(v + PPC_IRQ_EXT_BASE,cpu_frame);
173      }
174    }
175  }
176}
177
178
179/*
180 *  ISR Handler: this is called from the primary exception dispatcher
181 */
182 
183void
184ictrl_isr(rtems_vector_number vector,CPU_Interrupt_frame *cpu_frame)
185{
186  unsigned32        istat,
187                    mask,
188                    global_vec;
189  int               exvec;
190  rtems_isr_entry handler;
191
192  istat = get_exisr() & get_exier() & PPC_EXI_MASK;
193
194  /* FIXME: this may be speeded up using cntlzw instruction */
195  for (exvec = 0;exvec < PPC_IRQ_EXT_MAX;exvec++) {
196    mask = VEC_TO_EXMSK(exvec);
197    if (0 != (istat & mask)) {
198      clr_exisr(mask);
199      handler = ictrl_vector_table[exvec];
200      if (handler) {
201        istat &= ~mask;
202        global_vec = exvec + PPC_IRQ_EXT_BASE;
203        (handler)(global_vec);
204      }
205    }
206  }
207  if (istat != 0) { /* anything left? then we have a spurious interrupt */
208    ictrl_spurious_handler(istat,cpu_frame);
209  }
210}
211
212/*
213 *
214 * the following functions form the user interface
215 *
216 */
217
218/*
219 *
220 * install a user vector for one of the external interrupt sources
221 *
222 */
223rtems_status_code
224ictrl_set_vector(rtems_isr_entry   new_handler,
225                 unsigned32        vector,
226                 rtems_isr_entry   *old_handler
227)
228{
229  /*
230   *  We put the actual user ISR address in 'ictrl_vector_table'.  This will
231   *  be used by the _ictrl_isr so the user gets control.
232   */
233
234  /* check for valid vector range */
235  if ((vector >= PPC_IRQ_EXT_BASE) &&
236      (vector <  PPC_IRQ_EXT_BASE + PPC_IRQ_EXT_MAX)) {
237    /* return old handler entry */
238    *old_handler = ictrl_vector_table[vector - PPC_IRQ_EXT_BASE];
239
240    if (new_handler != NULL) {
241      /* store handler function... */
242      ictrl_vector_table[vector - PPC_IRQ_EXT_BASE] = new_handler;
243      /* then enable it in EXIER register */
244      enable_ext_irq(VEC_TO_EXMSK(vector - PPC_IRQ_EXT_BASE));
245    }
246    else { /* new_handler == NULL */
247      /* then disable it in EXIER register */
248      disable_ext_irq(VEC_TO_EXMSK(vector - PPC_IRQ_EXT_BASE));
249      ictrl_vector_table[vector - PPC_IRQ_EXT_BASE] = NULL;
250    }
251    return RTEMS_SUCCESSFUL;
252  }
253  else {
254    return RTEMS_INVALID_NUMBER;
255  }
256}
257
258/*
259 * Called via atexit()
260 * deactivate the interrupt controller
261 */
262
263void
264ictrl_exit(void)
265{
266  /* mark them all unused */
267  disable_ext_irq(~0);
268  clr_exisr(~0);
269 
270}
271
272/*
273 * activate the interrupt controller
274 */
275
276rtems_status_code
277ictrl_init(void)
278{
279  proc_ptr dummy;
280
281  /* mark them all unused */
282  disable_ext_irq(~0);
283  clr_exisr(~0);
284 
285  /* install the external interrupt handler */
286  _CPU_ISR_install_vector(PPC_IRQ_EXTERNAL,
287                          ictrl_isr,
288                          &dummy);
289  atexit(ictrl_exit);
290  return RTEMS_SUCCESSFUL;
291}
292
Note: See TracBrowser for help on using the repository browser.