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

4.104.114.84.95
Last change on this file since f93630d was f93630d, checked in by Joel Sherrill <joel.sherrill@…>, on Sep 12, 2007 at 3:23:44 PM

2007-09-12 Joel Sherrill <joel.sherrill@…>

PR 1257/bsps

  • mpc5xx/exceptions/raw_exception.c, mpc5xx/irq/irq.c, mpc6xx/exceptions/raw_exception.c, mpc8260/exceptions/raw_exception.c, mpc8xx/exceptions/raw_exception.c, new-exceptions/raw_exception.c, ppc403/ictrl/ictrl.c, ppc403/irq/ictrl.c: Code outside of cpukit should use the public API for rtems_interrupt_disable/rtems_interrupt_enable. By bypassing the public API and directly accessing _CPU_ISR_Disable and _CPU_ISR_Enable, they were bypassing the compiler memory barrier directive which could lead to problems. This patch also changes the type of the variable passed into these routines and addresses minor style issues.
  • Property mode set to 100644
File size: 6.5 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(uint32_t   mask) 
49{
50    asm volatile ("mtdcr 0xC0,%0"::"r" (mask));/*EXISR*/
51} 
52
53/*
54 *  get value of EXISR
55 */
56RTEMS_INLINE_ROUTINE uint32_t   
57get_exisr(void) 
58{
59    uint32_t   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 uint32_t   
69get_exier(void) 
70{
71    uint32_t   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(uint32_t   val) 
81{
82    asm volatile ("mtdcr 0xC2,%0"::"r" (val));/*EXIER*/
83} 
84
85#else /* not ppc405 */
86
87RTEMS_INLINE_ROUTINE void 
88clr_exisr(uint32_t   mask) 
89{
90    asm volatile ("mtdcr 0x40,%0"::"r" (mask));/*EXISR*/
91} 
92
93/*
94 *  get value of EXISR
95 */
96RTEMS_INLINE_ROUTINE uint32_t   
97get_exisr(void) 
98{
99    uint32_t   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 uint32_t   
109get_exier(void) 
110{
111    uint32_t   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(uint32_t   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( uint32_t   mask)
130{
131  rtems_interrupt_level level;
132
133  rtems_interrupt_disable(level);
134    set_exier(get_exier() | ((mask)&PPC_EXI_MASK));
135  rtems_interrupt_enable(level);
136}
137
138/*
139 *  disable an external interrupt, make this interrupt consistent
140 */
141RTEMS_INLINE_ROUTINE void 
142disable_ext_irq( uint32_t   mask)
143{
144  rtems_interrupt_level level;
145
146  rtems_interrupt_disable(level);
147    set_exier(get_exier() & ~(mask) & PPC_EXI_MASK);
148  rtems_interrupt_enable(level);
149}
150
151/*
152 *
153 *  this function is called, when a external interrupt is present and
154 *  enabled but there is no handler installed. It will clear
155 *  the corresponding enable bits and call the spurious handler
156 *  present in the CPU Configuration Table, if any.
157 *
158 */
159void 
160ictrl_spurious_handler(uint32_t   spurious_mask, 
161                       CPU_Interrupt_frame *cpu_frame)
162{
163  int v;
164 
165  for (v=0; v < PPC_IRQ_EXT_MAX; v++) {
166    if (VEC_TO_EXMSK(v) & spurious_mask) {
167      clr_exisr(VEC_TO_EXMSK(v));
168      disable_ext_irq(VEC_TO_EXMSK(v));
169#if 0
170      printf("spurious external interrupt: %d at pc 0x%x; disabling\n",
171             vector, cpu_frame->Interrupt.pcoqfront);
172#endif
173      if (rtems_cpu_configuration_get_spurious_handler()) {
174        rtems_cpu_configuration_get_spurious_handler()(v + PPC_IRQ_EXT_BASE,cpu_frame);
175      }
176    }
177  }
178}
179
180
181/*
182 *  ISR Handler: this is called from the primary exception dispatcher
183 */
184 
185void
186ictrl_isr(rtems_vector_number vector,CPU_Interrupt_frame *cpu_frame)
187{
188  uint32_t          istat,
189                    mask,
190                    global_vec;
191  int               exvec;
192  rtems_isr_entry handler;
193
194  istat = get_exisr() & get_exier() & PPC_EXI_MASK;
195
196  /* FIXME: this may be speeded up using cntlzw instruction */
197  for (exvec = 0;exvec < PPC_IRQ_EXT_MAX;exvec++) {
198    mask = VEC_TO_EXMSK(exvec);
199    if (0 != (istat & mask)) {
200      /*clr_exisr(mask); too early to ack*/
201      handler = ictrl_vector_table[exvec];
202      if (handler) {
203        istat &= ~mask;
204        global_vec = exvec + PPC_IRQ_EXT_BASE;
205        (handler)(global_vec);
206      }
207      clr_exisr(mask);/* now we can ack*/
208    }
209  }
210  if (istat != 0) { /* anything left? then we have a spurious interrupt */
211    ictrl_spurious_handler(istat,cpu_frame);
212  }
213}
214
215/*
216 *
217 * the following functions form the user interface
218 *
219 */
220
221/*
222 *
223 * install a user vector for one of the external interrupt sources
224 *
225 */ 
226rtems_status_code
227ictrl_set_vector(rtems_isr_entry   new_handler,
228                 uint32_t          vector,
229                 rtems_isr_entry   *old_handler
230)
231{
232  /*
233   *  We put the actual user ISR address in 'ictrl_vector_table'.  This will
234   *  be used by the _ictrl_isr so the user gets control.
235   */
236
237  /* check for valid vector range */
238  if ((vector >= PPC_IRQ_EXT_BASE) &&
239      (vector <  PPC_IRQ_EXT_BASE + PPC_IRQ_EXT_MAX)) {
240    /* return old handler entry */
241    *old_handler = ictrl_vector_table[vector - PPC_IRQ_EXT_BASE];
242
243    if (new_handler != NULL) {
244      /* store handler function... */
245      ictrl_vector_table[vector - PPC_IRQ_EXT_BASE] = new_handler;
246      /* then enable it in EXIER register */
247      enable_ext_irq(VEC_TO_EXMSK(vector - PPC_IRQ_EXT_BASE));
248    }
249    else { /* new_handler == NULL */
250      /* then disable it in EXIER register */
251      disable_ext_irq(VEC_TO_EXMSK(vector - PPC_IRQ_EXT_BASE));
252      ictrl_vector_table[vector - PPC_IRQ_EXT_BASE] = NULL;
253    }
254    return RTEMS_SUCCESSFUL;
255  }
256  else {
257    return RTEMS_INVALID_NUMBER;
258  }
259}
260
261/*
262 * Called via atexit()
263 * deactivate the interrupt controller
264 */
265
266void
267ictrl_exit(void)
268{
269  /* mark them all unused */
270  disable_ext_irq(~0);
271  clr_exisr(~0);
272 
273}
274
275/*
276 * activate the interrupt controller
277 */
278
279rtems_status_code
280ictrl_init(void)
281{
282  proc_ptr dummy;
283
284  /* mark them all unused */
285  disable_ext_irq(~0);
286  clr_exisr(~0);
287 
288  /* install the external interrupt handler */
289  _CPU_ISR_install_vector(PPC_IRQ_EXTERNAL,
290                          ictrl_isr,
291                          &dummy);
292  atexit(ictrl_exit);
293  return RTEMS_SUCCESSFUL;
294}
Note: See TracBrowser for help on using the repository browser.