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

Last change on this file since 561f53b was 561f53b, checked in by Jennifer Averett <Jennifer.Averett@…>, on Nov 22, 2004 at 10:30:59 PM

2004-11-22 Jennifer Averett <jennifer@…>

PR 581/bsps

  • Makefile.am, bsp_specs, configure.ac, clock/Makefile.am, include/bsp.h, start/Makefile.am, start/start.S, startup/Makefile.am, startup/bspstart.c, startup/linkcmds, vectors/Makefile.am, vectors/vectors.S, wrapup/Makefile.am: Convert PSIM to new exception model.
  • irq/Makefile.am, irq/irq.c, irq/irq.h, irq/irq_asm.S, irq/irq_init.c: New files.
  • clock/clock.c: Removed.
  • Property mode set to 100644
File size: 8.7 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_symbolic_name 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_symbolic_name 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_symbolic_name 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 * Caution : this function assumes the variable "internal_config"
90 * is already set and that the tables it contains are still valid
91 * and accessible.
92 */
93static void compute_i8259_masks_from_prio ()
94{
95  int i;
96  int j;
97  /*
98   * Always mask at least current interrupt to prevent re-entrance
99   */
100  for (i=BSP_ISA_IRQ_LOWEST_OFFSET; i < BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER; i++) {
101    * ((unsigned short*) &irq_mask_or_tbl[i]) = (1 << i);
102    for (j = BSP_ISA_IRQ_LOWEST_OFFSET; j < BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER; j++) {
103      /*
104       * Mask interrupts at i8259 level that have a lower priority
105       */
106      if (internal_config->irqPrioTbl [i] > internal_config->irqPrioTbl [j]) {
107        * ((unsigned short*) &irq_mask_or_tbl[i]) |= (1 << j);
108      }
109    }
110  }
111}
112
113/*
114 * This function check that the value given for the irq line
115 * is valid.
116 */
117
118static int isValidInterrupt(int irq)
119{
120  if ( (irq < BSP_LOWEST_OFFSET) || (irq > BSP_MAX_OFFSET))
121    return 0;
122  return 1;
123}
124
125
126/*
127 * ------------------------ RTEMS Shared Irq Handler Mngt Routines ----------------
128 */
129int BSP_install_rtems_shared_irq_handler  (const rtems_irq_connect_data* irq)
130{
131  printk("BSP_insall_rtems_shared_irq_handler Not supported in psim\n");
132  return 0;
133}
134
135
136/*
137 * ------------------------ RTEMS Single Irq Handler Mngt Routines ----------------
138 */
139
140int BSP_install_rtems_irq_handler  (const rtems_irq_connect_data* irq)
141{
142    unsigned int level;
143 
144    if (!isValidInterrupt(irq->name)) {
145      printk("Invalid interrupt vector %d\n",irq->name);
146      return 0;
147    }
148    /*
149     * Check if default handler is actually connected. If not issue an error.
150     * You must first get the current handler via i386_get_current_idt_entry
151     * and then disconnect it using i386_delete_idt_entry.
152     * RATIONALE : to always have the same transition by forcing the user
153     * to get the previous handler before accepting to disconnect.
154     */
155    _CPU_ISR_Disable(level);
156    if (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl) {
157      _CPU_ISR_Enable(level);
158      printk("IRQ vector %d already connected\n",irq->name);
159      return 0;
160    }
161
162    /*
163     * store the data provided by user
164     */
165    rtems_hdl_tbl[irq->name] = *irq;
166    rtems_hdl_tbl[irq->name].next_handler = (void *)-1;
167   
168    if (is_isa_irq(irq->name)) {
169      printk("What's a isa_irq on psim?");
170    }
171
172    if (is_processor_irq(irq->name)) {
173      /*
174       * Enable exception at processor level
175       */
176    }
177    /*
178     * Enable interrupt on device
179     */
180    irq->on(irq);
181   
182    _CPU_ISR_Enable(level);
183
184    return 1;
185}
186
187
188int BSP_get_current_rtems_irq_handler   (rtems_irq_connect_data* irq)
189{
190     unsigned int level;
191
192     if (!isValidInterrupt(irq->name)) {
193      return 0;
194     }
195     _CPU_ISR_Disable(level);
196     *irq = rtems_hdl_tbl[irq->name];
197     _CPU_ISR_Enable(level);
198     return 1;
199}
200
201int BSP_remove_rtems_irq_handler  (const rtems_irq_connect_data* irq)
202{
203   rtems_irq_connect_data *pchain= NULL, *vchain = NULL;
204    unsigned int level;
205 
206    if (!isValidInterrupt(irq->name)) {
207      return 0;
208    }
209    /*
210     * Check if default handler is actually connected. If not issue an error.
211     * You must first get the current handler via i386_get_current_idt_entry
212     * and then disconnect it using i386_delete_idt_entry.
213     * RATIONALE : to always have the same transition by forcing the user
214     * to get the previous handler before accepting to disconnect.
215     */
216    _CPU_ISR_Disable(level);
217    if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) {
218      _CPU_ISR_Enable(level);
219      return 0;
220    }
221
222    if( (int)rtems_hdl_tbl[irq->name].next_handler != -1 )
223    {
224       int found = 0;
225
226       for( (pchain= NULL, vchain = &rtems_hdl_tbl[irq->name]);
227            (vchain->hdl != default_rtems_entry.hdl);
228            (pchain= vchain, vchain = (rtems_irq_connect_data*)vchain->next_handler) )
229       {
230          if( vchain->hdl == irq->hdl )
231          {
232             found= -1; break;
233          }
234       }
235
236       if( !found )
237       {
238          _CPU_ISR_Enable(level);
239          return 0;
240       }
241    }
242    else
243    {
244       if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) 
245       {
246          _CPU_ISR_Enable(level);
247         return 0;
248       }
249    }
250
251    if (is_isa_irq(irq->name)) {
252      printk("isa irq on psim?");
253    }
254    if (is_processor_irq(irq->name)) {
255      /*
256       * disable exception at processor level
257       */
258    }   
259
260    /*
261     * Disable interrupt on device
262     */
263    irq->off(irq);
264
265    /*
266     * restore the default irq value
267     */
268    if( !vchain )
269    {
270       /* single handler vector... */
271       rtems_hdl_tbl[irq->name] = default_rtems_entry;
272    }
273    else
274    {
275       if( pchain )
276       {
277          /* non-first handler being removed */
278          pchain->next_handler = vchain->next_handler;
279       }
280       else
281       {
282          /* first handler isn't malloc'ed, so just overwrite it.  Since
283          the contents of vchain are being struct copied, vchain itself
284          goes away */
285          rtems_hdl_tbl[irq->name]= *vchain;
286       }
287       free(vchain);
288    }
289
290    _CPU_ISR_Enable(level);
291
292    return 1;
293}
294
295/*
296 * ------------------------ RTEMS Global Irq Handler Mngt Routines ----------------
297 */
298
299int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
300{
301   /*
302    * Store various code accelerators
303    */
304    internal_config             = config;
305    default_rtems_entry         = config->defaultEntry;
306    rtems_hdl_tbl               = config->irqHdlTbl;
307   
308    return 1;
309}
310
311int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** config)
312{
313    *config = internal_config;
314    return 0;
315}   
316
317int _BSP_vme_bridge_irq = -1;
318 
319unsigned BSP_spuriousIntr = 0;
320
321/*
322 * High level IRQ handler called from shared_raw_irq_code_entry
323 */
324void C_dispatch_irq_handler (CPU_Interrupt_frame *frame, unsigned int excNum)
325{
326  register unsigned msr;
327  register unsigned new_msr;
328
329  if (excNum == ASM_DEC_VECTOR) {
330    _CPU_MSR_GET(msr);
331    new_msr = msr | MSR_EE;
332    _CPU_MSR_SET(new_msr);
333   
334    rtems_hdl_tbl[BSP_DECREMENTER].hdl();
335
336    _CPU_MSR_SET(msr);
337    return;
338   
339  }
340}
341   
342   
343 
344void _ThreadProcessSignalsFromIrq (BSP_Exception_frame* ctx)
345{
346  /*
347   * Process pending signals that have not already been
348   * processed by _Thread_Displatch. This happens quite
349   * unfrequently : the ISR must have posted an action
350   * to the current running thread.
351   */
352  if ( _Thread_Do_post_task_switch_extension ||
353       _Thread_Executing->do_post_task_switch_extension ) {
354    _Thread_Executing->do_post_task_switch_extension = FALSE;
355    _API_extensions_Run_postswitch();
356  }
357  /*
358   * I plan to process other thread related events here.
359   * This will include DEBUG session requested from keyboard...
360   */
361}
Note: See TracBrowser for help on using the repository browser.