source: rtems/c/src/lib/libbsp/powerpc/score603e/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: 11.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 *  $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    rtems_interrupt_level   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    rtems_interrupt_disable(level);
98
99    if ( (int)rtems_hdl_tbl[irq->name].next_handler  == -1 ) {
100      rtems_interrupt_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    rtems_interrupt_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    rtems_interrupt_level       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    rtems_interrupt_disable(level);
159    if (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl) {
160      rtems_interrupt_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    rtems_interrupt_enable(level);
189
190    return 1;
191}
192
193int BSP_get_current_rtems_irq_handler   (rtems_irq_connect_data* irq)
194{
195    rtems_interrupt_level       level;
196
197    if (!isValidInterrupt(irq->name)) {
198      return 0;
199    }
200    rtems_interrupt_disable(level);
201      *irq = rtems_hdl_tbl[irq->name];
202    rtems_interrupt_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    rtems_interrupt_level       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    rtems_interrupt_disable(level);
222    if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) {
223      rtems_interrupt_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          rtems_interrupt_enable(level);
244          return 0;
245       }
246    }
247    else
248    {
249       if (rtems_hdl_tbl[irq->name].hdl != irq->hdl)
250       {
251          rtems_interrupt_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    rtems_interrupt_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    rtems_interrupt_level  level;
311
312    /*
313     * Store various code accelerators
314     */
315    internal_config             = config;
316    default_rtems_entry         = config->defaultEntry;
317    rtems_hdl_tbl               = config->irqHdlTbl;
318
319    rtems_interrupt_disable(level);
320    /*
321     * set up internal tables used by rtems interrupt prologue
322     */
323
324    /*
325     *  XXX - FIX ME !!! 
326     */
327    for (i=BSP_PCI_IRQ_LOWEST_OFFSET; i < BSP_PCI_IRQ_LOWEST_OFFSET + BSP_PCI_IRQ_NUMBER ; i++) {
328      if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
329         {
330            rtems_irq_connect_data* vchain;
331            for( vchain = &rtems_hdl_tbl[i];
332                 ((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl);
333                 vchain = (rtems_irq_connect_data*)vchain->next_handler )
334            {
335               vchain->on(vchain);
336            }
337         }
338
339      }
340      else {
341         /* rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]); */
342         {
343            rtems_irq_connect_data* vchain;
344            for( vchain = &rtems_hdl_tbl[i];
345                 ((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl);
346                 vchain = (rtems_irq_connect_data*)vchain->next_handler )
347            {
348               vchain->off(vchain);
349            }
350         }
351      }
352    }
353    /*
354     * finish with Processor exceptions handled like IRQ
355     */
356    for (i=BSP_PROCESSOR_IRQ_LOWEST_OFFSET; i < BSP_PROCESSOR_IRQ_LOWEST_OFFSET+BSP_PROCESSOR_IRQ_NUMBER; i++){
357      if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
358         {
359            rtems_irq_connect_data* vchain;
360            for( vchain = &rtems_hdl_tbl[i];
361                 ((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl);
362                 vchain = (rtems_irq_connect_data*)vchain->next_handler )
363            {
364               vchain->on(vchain);
365            }
366         }
367
368      }
369      else {
370         {
371            rtems_irq_connect_data* vchain;
372            for( vchain = &rtems_hdl_tbl[i];
373                 ((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl);
374                 vchain = (rtems_irq_connect_data*)vchain->next_handler )
375            {
376               vchain->off(vchain);
377            }
378         }
379
380      }
381    }
382    rtems_interrupt_enable(level);
383    return 1;
384}
385
386int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** config)
387{
388    *config = internal_config;
389    return 0;
390}
391
392unsigned BSP_spuriousIntr = 0;
393/*
394 * High level IRQ handler called from shared_raw_irq_code_entry
395 */
396void C_dispatch_irq_handler (CPU_Interrupt_frame *frame, unsigned int excNum)
397{
398  register unsigned int irq;
399  register unsigned msr;
400  register unsigned new_msr;
401
402  if (excNum == ASM_DEC_VECTOR) {
403    _CPU_MSR_GET(msr);
404    new_msr = msr | MSR_EE;
405    _CPU_MSR_SET(new_msr);
406
407    rtems_hdl_tbl[BSP_DECREMENTER].hdl(rtems_hdl_tbl[BSP_DECREMENTER].handle);
408
409    _CPU_MSR_SET(msr);
410    return;
411
412  }
413  irq = read_and_clear_irq();
414  _CPU_MSR_GET(msr);
415  new_msr = msr | MSR_EE;
416  _CPU_MSR_SET(new_msr);
417
418  /* rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle); */
419  {
420     rtems_irq_connect_data* vchain;
421     for( vchain = &rtems_hdl_tbl[irq];
422          ((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl);
423          vchain = (rtems_irq_connect_data*)vchain->next_handler )
424     {
425        vchain->hdl(vchain->handle);
426     }
427  }
428
429  _CPU_MSR_SET(msr);
430
431}
432
433void _ThreadProcessSignalsFromIrq (BSP_Exception_frame* ctx)
434{
435  /*
436   * Process pending signals that have not already been
437   * processed by _Thread_Displatch. This happens quite
438   * unfrequently : the ISR must have posted an action
439   * to the current running thread.
440   */
441  if ( _Thread_Do_post_task_switch_extension ||
442       _Thread_Executing->do_post_task_switch_extension ) {
443    _Thread_Executing->do_post_task_switch_extension = FALSE;
444    _API_extensions_Run_postswitch();
445  }
446  /*
447   * I plan to process other thread related events here.
448   * This will include DEBUG session requested from keyboard...
449   */
450}
Note: See TracBrowser for help on using the repository browser.