source: rtems/c/src/lib/libbsp/powerpc/score603e/irq/irq.c @ 7068d7ac

4.104.114.84.95
Last change on this file since 7068d7ac was 7068d7ac, checked in by Jennifer Averett <Jennifer.Averett@…>, on 05/17/05 at 15:05:03

2005-05-17 Jennifer Averett <jennifer.averett@…>

  • irq/irq.c, irq/irq.h: Modified to use rtems/irq.h.
  • Property mode set to 100644
File size: 10.9 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 *  $Id$
12 */
13
14#include <stdlib.h>
15
16#include <bsp.h>
17#include <bsp/irq.h>
18#include <bsp/VME.h>
19#include <rtems/score/apiext.h>  /* for post ISR signal processing */
20#include <libcpu/raw_exception.h>
21#include <libcpu/io.h>
22#include <bsp/vectors.h>
23#include <stdlib.h>
24#include <rtems/bspIo.h> /* for printk */
25
26/*
27 * default handler connected on each irq after bsp initialization
28 */
29static rtems_irq_connect_data   default_rtems_entry;
30
31/*
32 * location used to store initial tables used for interrupt
33 * management.
34 */
35static rtems_irq_global_settings*       internal_config;
36static rtems_irq_connect_data*          rtems_hdl_tbl;
37
38/*
39 * Check if IRQ is an ISA IRQ
40 */
41static inline int is_isa_irq(const rtems_irq_number irqLine)
42{
43  return (((int) irqLine <= BSP_ISA_IRQ_MAX_OFFSET) &
44          ((int) irqLine >= BSP_ISA_IRQ_LOWEST_OFFSET)
45         );
46}
47
48/*
49 * Check if IRQ is an pci IRQ
50 */
51static inline int is_pci_irq(const rtems_irq_number irqLine)
52{
53  return (((int) irqLine <= BSP_PCI_IRQ_MAX_OFFSET) &
54          ((int) irqLine >= BSP_PCI_IRQ_LOWEST_OFFSET)
55         );
56}
57
58/*
59 * Check if IRQ is a Processor IRQ
60 */
61static inline int is_processor_irq(const rtems_irq_number irqLine)
62{
63  return (((int) irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET) &
64          ((int) irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET)
65         );
66}
67
68/*
69 * ------------------------ RTEMS Irq helper functions ----------------
70 */
71
72/*
73 * This function check that the value given for the irq line
74 * is valid.
75 */
76
77static int isValidInterrupt(int irq)
78{
79  if ( (irq < BSP_LOWEST_OFFSET) || (irq > BSP_MAX_OFFSET))
80    return 0;
81  return 1;
82}
83
84/*
85 * ------------------------ RTEMS Shared Irq Handler Mngt Routines ----------------
86 */
87int BSP_install_rtems_shared_irq_handler  (const rtems_irq_connect_data* irq)
88{
89    unsigned int level;
90    rtems_irq_connect_data* vchain;
91
92    if (!isValidInterrupt(irq->name)) {
93      printk("Invalid interrupt vector %d\n",irq->name);
94      return 0;
95    }
96
97    _CPU_ISR_Disable(level);
98
99    if ( (int)rtems_hdl_tbl[irq->name].next_handler  == -1 ) {
100      _CPU_ISR_Enable(level);
101      printk("IRQ vector %d already connected to an unshared handler\n",irq->name);
102      return 0;
103    }
104
105     vchain = (rtems_irq_connect_data*)malloc(sizeof(rtems_irq_connect_data));
106
107    /* save off topmost handler */
108    vchain[0]= rtems_hdl_tbl[irq->name];
109
110    /*
111     * store the data provided by user
112     */
113    rtems_hdl_tbl[irq->name] = *irq;
114
115    /* link chain to new topmost handler */
116    rtems_hdl_tbl[irq->name].next_handler = (void *)vchain;
117
118    /*
119     * XXX FIX ME
120     */
121    if (is_pci_irq(irq->name)) {
122    }
123
124    if (is_processor_irq(irq->name)) {
125      /*
126       * Enable exception at processor level
127       */
128    }
129    /*
130     * Enable interrupt on device
131     */
132    irq->on(irq);
133
134    _CPU_ISR_Enable(level);
135
136    return 1;
137}
138
139/*
140 * ------------------------ RTEMS Single Irq Handler Mngt Routines ----------------
141 */
142
143int BSP_install_rtems_irq_handler  (const rtems_irq_connect_data* irq)
144{
145    unsigned int level;
146
147    if (!isValidInterrupt(irq->name)) {
148      printk("Invalid interrupt vector %d\n",irq->name);
149      return 0;
150    }
151    /*
152     * Check if default handler is actually connected. If not issue an error.
153     * You must first get the current handler via i386_get_current_idt_entry
154     * and then disconnect it using i386_delete_idt_entry.
155     * RATIONALE : to always have the same transition by forcing the user
156     * to get the previous handler before accepting to disconnect.
157     */
158    _CPU_ISR_Disable(level);
159    if (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl) {
160      _CPU_ISR_Enable(level);
161      printk("IRQ vector %d already connected\n",irq->name);
162      return 0;
163    }
164
165    /*
166     * store the data provided by user
167     */
168    rtems_hdl_tbl[irq->name] = *irq;
169    rtems_hdl_tbl[irq->name].next_handler = (void *)-1;
170
171    /* XXX -FIX ME !! */
172    if (is_pci_irq(irq->name)) {
173      /*
174       * Enable interrupt
175       */
176    }
177
178    if (is_processor_irq(irq->name)) {
179      /*
180       * Enable exception at processor level
181       */
182    }
183    /*
184     * Enable interrupt on device
185     */
186    irq->on(irq);
187
188    _CPU_ISR_Enable(level);
189
190    return 1;
191}
192
193int BSP_get_current_rtems_irq_handler   (rtems_irq_connect_data* irq)
194{
195     unsigned int level;
196
197     if (!isValidInterrupt(irq->name)) {
198      return 0;
199     }
200     _CPU_ISR_Disable(level);
201     *irq = rtems_hdl_tbl[irq->name];
202     _CPU_ISR_Enable(level);
203     return 1;
204}
205
206int BSP_remove_rtems_irq_handler  (const rtems_irq_connect_data* irq)
207{
208   rtems_irq_connect_data *pchain= NULL, *vchain = NULL;
209    unsigned int level;
210
211    if (!isValidInterrupt(irq->name)) {
212      return 0;
213    }
214    /*
215     * Check if default handler is actually connected. If not issue an error.
216     * You must first get the current handler via i386_get_current_idt_entry
217     * and then disconnect it using i386_delete_idt_entry.
218     * RATIONALE : to always have the same transition by forcing the user
219     * to get the previous handler before accepting to disconnect.
220     */
221    _CPU_ISR_Disable(level);
222    if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) {
223      _CPU_ISR_Enable(level);
224      return 0;
225    }
226
227    if( (int)rtems_hdl_tbl[irq->name].next_handler != -1 )
228    {
229       int found = 0;
230
231       for( (pchain= NULL, vchain = &rtems_hdl_tbl[irq->name]);
232            (vchain->hdl != default_rtems_entry.hdl);
233            (pchain= vchain, vchain = (rtems_irq_connect_data*)vchain->next_handler) )
234       {
235          if( vchain->hdl == irq->hdl )
236          {
237             found= -1; break;
238          }
239       }
240
241       if( !found )
242       {
243          _CPU_ISR_Enable(level);
244          return 0;
245       }
246    }
247    else
248    {
249       if (rtems_hdl_tbl[irq->name].hdl != irq->hdl)
250       {
251          _CPU_ISR_Enable(level);
252         return 0;
253       }
254    }
255
256    /* XXX - FIX ME !! */
257    if (is_pci_irq(irq->name)) {
258      /*
259       * disable interrupt
260       */
261    }
262    if (is_processor_irq(irq->name)) {
263      /*
264       * disable exception at processor level
265       */
266    }
267
268    /*
269     * Disable interrupt on device
270     */
271    irq->off(irq);
272
273    /*
274     * restore the default irq value
275     */
276    if( !vchain )
277    {
278       /* single handler vector... */
279       rtems_hdl_tbl[irq->name] = default_rtems_entry;
280    }
281    else
282    {
283       if( pchain )
284       {
285          /* non-first handler being removed */
286          pchain->next_handler = vchain->next_handler;
287       }
288       else
289       {
290          /* first handler isn't malloc'ed, so just overwrite it.  Since
291          the contents of vchain are being struct copied, vchain itself
292          goes away */
293          rtems_hdl_tbl[irq->name]= *vchain;
294       }
295       free(vchain);
296    }
297
298    _CPU_ISR_Enable(level);
299
300    return 1;
301}
302
303/*
304 * RTEMS Global Interrupt Handler Management Routines
305 */
306
307int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
308{
309    int i;
310    unsigned int level;
311   /*
312    * Store various code accelerators
313    */
314    internal_config             = config;
315    default_rtems_entry         = config->defaultEntry;
316    rtems_hdl_tbl               = config->irqHdlTbl;
317
318    _CPU_ISR_Disable(level);
319    /*
320     * set up internal tables used by rtems interrupt prologue
321     */
322
323    /*
324     *  XXX - FIX ME !!! 
325     */
326    for (i=BSP_PCI_IRQ_LOWEST_OFFSET; i < BSP_PCI_IRQ_LOWEST_OFFSET + BSP_PCI_IRQ_NUMBER ; i++) {
327      if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
328         {
329            rtems_irq_connect_data* vchain;
330            for( vchain = &rtems_hdl_tbl[i];
331                 ((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl);
332                 vchain = (rtems_irq_connect_data*)vchain->next_handler )
333            {
334               vchain->on(vchain);
335            }
336         }
337
338      }
339      else {
340         /* rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]); */
341         {
342            rtems_irq_connect_data* vchain;
343            for( vchain = &rtems_hdl_tbl[i];
344                 ((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl);
345                 vchain = (rtems_irq_connect_data*)vchain->next_handler )
346            {
347               vchain->off(vchain);
348            }
349         }
350      }
351    }
352    /*
353     * finish with Processor exceptions handled like IRQ
354     */
355    for (i=BSP_PROCESSOR_IRQ_LOWEST_OFFSET; i < BSP_PROCESSOR_IRQ_LOWEST_OFFSET+BSP_PROCESSOR_IRQ_NUMBER; i++){
356      if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
357         {
358            rtems_irq_connect_data* vchain;
359            for( vchain = &rtems_hdl_tbl[i];
360                 ((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl);
361                 vchain = (rtems_irq_connect_data*)vchain->next_handler )
362            {
363               vchain->on(vchain);
364            }
365         }
366
367      }
368      else {
369         {
370            rtems_irq_connect_data* vchain;
371            for( vchain = &rtems_hdl_tbl[i];
372                 ((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl);
373                 vchain = (rtems_irq_connect_data*)vchain->next_handler )
374            {
375               vchain->off(vchain);
376            }
377         }
378
379      }
380    }
381    _CPU_ISR_Enable(level);
382    return 1;
383}
384
385int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** config)
386{
387    *config = internal_config;
388    return 0;
389}
390
391int _BSP_vme_bridge_irq = -1;
392
393unsigned BSP_spuriousIntr = 0;
394/*
395 * High level IRQ handler called from shared_raw_irq_code_entry
396 */
397void C_dispatch_irq_handler (CPU_Interrupt_frame *frame, unsigned int excNum)
398{
399  register unsigned int irq;
400  register unsigned msr;
401  register unsigned new_msr;
402
403  if (excNum == ASM_DEC_VECTOR) {
404    _CPU_MSR_GET(msr);
405    new_msr = msr | MSR_EE;
406    _CPU_MSR_SET(new_msr);
407
408    rtems_hdl_tbl[BSP_DECREMENTER].hdl(rtems_hdl_tbl[BSP_DECREMENTER].handle);
409
410    _CPU_MSR_SET(msr);
411    return;
412
413  }
414  irq = read_and_clear_irq();
415  _CPU_MSR_GET(msr);
416  new_msr = msr | MSR_EE;
417  _CPU_MSR_SET(new_msr);
418
419  /* rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle); */
420  {
421     rtems_irq_connect_data* vchain;
422     for( vchain = &rtems_hdl_tbl[irq];
423          ((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl);
424          vchain = (rtems_irq_connect_data*)vchain->next_handler )
425     {
426        vchain->hdl(vchain->handle);
427     }
428  }
429
430  _CPU_MSR_SET(msr);
431
432}
433
434void _ThreadProcessSignalsFromIrq (BSP_Exception_frame* ctx)
435{
436  /*
437   * Process pending signals that have not already been
438   * processed by _Thread_Displatch. This happens quite
439   * unfrequently : the ISR must have posted an action
440   * to the current running thread.
441   */
442  if ( _Thread_Do_post_task_switch_extension ||
443       _Thread_Executing->do_post_task_switch_extension ) {
444    _Thread_Executing->do_post_task_switch_extension = FALSE;
445    _API_extensions_Run_postswitch();
446  }
447  /*
448   * I plan to process other thread related events here.
449   * This will include DEBUG session requested from keyboard...
450   */
451}
Note: See TracBrowser for help on using the repository browser.