source: rtems/c/src/lib/libbsp/powerpc/psim/irq/irq.c @ ec1d0b9d

4.104.114.84.95
Last change on this file since ec1d0b9d was ec1d0b9d, checked in by Joel Sherrill <joel.sherrill@…>, on 09/12/07 at 15:16:36

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

PR 1257/bsps

  • irq/irq.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: 8.1 KB
Line 
1/*
2 *
3 *  This file contains the implementation of the function described in irq.h
4 *
5 *  Copyright (C) 1998, 1999 valette@crf.canon.fr
6 *
7 *  The license and distribution terms for this file may be
8 *  found in found in the file LICENSE in this distribution or at
9 *  http://www.rtems.com/license/LICENSE.
10 *
11 *  irq.c,v 1.4.2.8 2003/09/04 18:45:20 joel Exp
12 */
13 
14#include <rtems/system.h>
15#include <bsp.h>
16#include <bsp/irq.h>
17#if 0
18#include <bsp/VME.h>
19#include <bsp/openpic.h>
20#endif
21#include <stdlib.h>
22
23#include <rtems/score/thread.h>
24#include <rtems/score/apiext.h>
25#include <libcpu/raw_exception.h>
26#include <libcpu/io.h>
27#include <bsp/vectors.h>
28
29#include <rtems/bspIo.h> /* for printk */
30#define RAVEN_INTR_ACK_REG 0xfeff0030
31
32/*
33 * pointer to the mask representing the additionnal irq vectors
34 * that must be disabled when a particular entry is activated.
35 * They will be dynamically computed from teh prioruty table given
36 * in BSP_rtems_irq_mngt_set();
37 * CAUTION : this table is accessed directly by interrupt routine
38 *           prologue.
39 */
40rtems_i8259_masks       irq_mask_or_tbl[BSP_IRQ_NUMBER];
41/*
42 * default handler connected on each irq after bsp initialization
43 */
44static rtems_irq_connect_data   default_rtems_entry;
45
46/*
47 * location used to store initial tables used for interrupt
48 * management.
49 */
50static rtems_irq_global_settings*       internal_config;
51static rtems_irq_connect_data*          rtems_hdl_tbl;
52
53/*
54 * Check if IRQ is an ISA IRQ
55 */
56static inline int is_isa_irq(const rtems_irq_number irqLine)
57{
58  return (((int) irqLine <= BSP_ISA_IRQ_MAX_OFFSET) &
59          ((int) irqLine >= BSP_ISA_IRQ_LOWEST_OFFSET)
60         );
61}
62
63/*
64 * Check if IRQ is an OPENPIC IRQ
65 */
66static inline int is_pci_irq(const rtems_irq_number irqLine)
67{
68  return (((int) irqLine <= BSP_PCI_IRQ_MAX_OFFSET) &
69          ((int) irqLine >= BSP_PCI_IRQ_LOWEST_OFFSET)
70         );
71}
72
73/*
74 * Check if IRQ is a Porcessor IRQ
75 */
76static inline int is_processor_irq(const rtems_irq_number irqLine)
77{
78  return (((int) irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET) &
79          ((int) irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET)
80         );
81}
82
83
84/*
85 * ------------------------ RTEMS Irq helper functions ----------------
86 */
87 
88/*
89 * This function check that the value given for the irq line
90 * is valid.
91 */
92
93static int isValidInterrupt(int irq)
94{
95  if ( (irq < BSP_LOWEST_OFFSET) || (irq > BSP_MAX_OFFSET))
96    return 0;
97  return 1;
98}
99
100
101/*
102 * ------------------------ RTEMS Shared Irq Handler Mngt Routines ----------------
103 */
104int BSP_install_rtems_shared_irq_handler  (const rtems_irq_connect_data* irq)
105{
106  printk("BSP_insall_rtems_shared_irq_handler Not supported in psim\n");
107  return 0;
108}
109
110
111/*
112 * ------------------------ RTEMS Single Irq Handler Mngt Routines ----------------
113 */
114
115int BSP_install_rtems_irq_handler  (const rtems_irq_connect_data* irq)
116{
117    rtems_interrupt_level       level;
118 
119    if (!isValidInterrupt(irq->name)) {
120      printk("Invalid interrupt vector %d\n",irq->name);
121      return 0;
122    }
123    /*
124     * Check if default handler is actually connected. If not issue an error.
125     * You must first get the current handler via i386_get_current_idt_entry
126     * and then disconnect it using i386_delete_idt_entry.
127     * RATIONALE : to always have the same transition by forcing the user
128     * to get the previous handler before accepting to disconnect.
129     */
130    rtems_interrupt_disable(level);
131    if (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl) {
132      rtems_interrupt_enable(level);
133      printk("IRQ vector %d already connected\n",irq->name);
134      return 0;
135    }
136
137    /*
138     * store the data provided by user
139     */
140    rtems_hdl_tbl[irq->name] = *irq;
141    rtems_hdl_tbl[irq->name].next_handler = (void *)-1;
142   
143    if (is_isa_irq(irq->name)) {
144      printk("What's a isa_irq on psim?");
145    }
146
147    if (is_processor_irq(irq->name)) {
148      /*
149       * Enable exception at processor level
150       */
151    }
152    /*
153     * Enable interrupt on device
154     */
155    irq->on(irq);
156   
157    rtems_interrupt_enable(level);
158
159    return 1;
160}
161
162
163int BSP_get_current_rtems_irq_handler   (rtems_irq_connect_data* irq)
164{
165    rtems_interrupt_level       level;
166
167    if (!isValidInterrupt(irq->name)) {
168      return 0;
169    }
170    rtems_interrupt_disable(level);
171      *irq = rtems_hdl_tbl[irq->name];
172    rtems_interrupt_enable(level);
173    return 1;
174}
175
176int BSP_remove_rtems_irq_handler  (const rtems_irq_connect_data* irq)
177{
178    rtems_irq_connect_data *pchain= NULL, *vchain = NULL;
179    rtems_interrupt_level   level;
180 
181    if (!isValidInterrupt(irq->name)) {
182      return 0;
183    }
184    /*
185     * Check if default handler is actually connected. If not issue an error.
186     * You must first get the current handler via i386_get_current_idt_entry
187     * and then disconnect it using i386_delete_idt_entry.
188     * RATIONALE : to always have the same transition by forcing the user
189     * to get the previous handler before accepting to disconnect.
190     */
191    rtems_interrupt_disable(level);
192    if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) {
193      rtems_interrupt_enable(level);
194      return 0;
195    }
196
197    if( (int)rtems_hdl_tbl[irq->name].next_handler != -1 )
198    {
199       int found = 0;
200
201       for( (pchain= NULL, vchain = &rtems_hdl_tbl[irq->name]);
202            (vchain->hdl != default_rtems_entry.hdl);
203            (pchain= vchain, vchain = (rtems_irq_connect_data*)vchain->next_handler) )
204       {
205          if( vchain->hdl == irq->hdl )
206          {
207             found= -1; break;
208          }
209       }
210
211       if( !found )
212       {
213          rtems_interrupt_enable(level);
214          return 0;
215       }
216    }
217    else
218    {
219       if (rtems_hdl_tbl[irq->name].hdl != irq->hdl)
220       {
221         rtems_interrupt_enable(level);
222         return 0;
223       }
224    }
225
226    if (is_isa_irq(irq->name)) {
227      printk("isa irq on psim?");
228    }
229    if (is_processor_irq(irq->name)) {
230      /*
231       * disable exception at processor level
232       */
233    }   
234
235    /*
236     * Disable interrupt on device
237     */
238    irq->off(irq);
239
240    /*
241     * restore the default irq value
242     */
243    if( !vchain )
244    {
245       /* single handler vector... */
246       rtems_hdl_tbl[irq->name] = default_rtems_entry;
247    }
248    else
249    {
250       if( pchain )
251       {
252          /* non-first handler being removed */
253          pchain->next_handler = vchain->next_handler;
254       }
255       else
256       {
257          /* first handler isn't malloc'ed, so just overwrite it.  Since
258          the contents of vchain are being struct copied, vchain itself
259          goes away */
260          rtems_hdl_tbl[irq->name]= *vchain;
261       }
262       free(vchain);
263    }
264
265    rtems_interrupt_enable(level);
266
267    return 1;
268}
269
270/*
271 * ------------------------ RTEMS Global Irq Handler Mngt Routines ----------------
272 */
273
274int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
275{
276   /*
277    * Store various code accelerators
278    */
279    internal_config             = config;
280    default_rtems_entry         = config->defaultEntry;
281    rtems_hdl_tbl               = config->irqHdlTbl;
282   
283    return 1;
284}
285
286int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** config)
287{
288    *config = internal_config;
289    return 0;
290}   
291
292int _BSP_vme_bridge_irq = -1;
293 
294unsigned BSP_spuriousIntr = 0;
295
296/*
297 * High level IRQ handler called from shared_raw_irq_code_entry
298 */
299void C_dispatch_irq_handler (CPU_Interrupt_frame *frame, unsigned int excNum)
300{
301  register unsigned msr;
302  register unsigned new_msr;
303
304  if (excNum == ASM_DEC_VECTOR) {
305    _CPU_MSR_GET(msr);
306    new_msr = msr | MSR_EE;
307    _CPU_MSR_SET(new_msr);
308   
309    rtems_hdl_tbl[BSP_DECREMENTER].hdl(rtems_hdl_tbl[BSP_DECREMENTER].handle);
310
311    _CPU_MSR_SET(msr);
312    return;
313   
314  }
315}
316   
317   
318 
319void _ThreadProcessSignalsFromIrq (BSP_Exception_frame* ctx)
320{
321  /*
322   * Process pending signals that have not already been
323   * processed by _Thread_Displatch. This happens quite
324   * unfrequently : the ISR must have posted an action
325   * to the current running thread.
326   */
327  if ( _Thread_Do_post_task_switch_extension ||
328       _Thread_Executing->do_post_task_switch_extension ) {
329    _Thread_Executing->do_post_task_switch_extension = FALSE;
330    _API_extensions_Run_postswitch();
331  }
332  /*
333   * I plan to process other thread related events here.
334   * This will include DEBUG session requested from keyboard...
335   */
336}
Note: See TracBrowser for help on using the repository browser.