source: rtems/c/src/lib/libbsp/i386/shared/irq/irq.c @ 529cebf0

4.104.114.84.95
Last change on this file since 529cebf0 was 529cebf0, checked in by Jennifer Averett <Jennifer.Averett@…>, on 05/06/05 at 19:55:45

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

  • Makefile.am, comm/i386-stub-glue.c, comm/tty_drv.c, comm/uart.c, irq/idt.c, irq/irq.c, irq/irq.h, irq/irq_asm.S, irq/irq_init.c: Moved irq.h and irq_asm.h to bsp subdirectory.
  • Property mode set to 100644
File size: 9.3 KB
RevLine 
[67a2288]1/* irq.c
2 *
3 *  This file contains the implementation of the function described in irq.h
4 *
5 *  CopyRight (C) 1998 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
[a3c7123]9 *  http://www.rtems.com/license/LICENSE.
[67a2288]10 *
11 *  $Id$
12 */
13
14#include <bsp.h>
[529cebf0]15#include <bsp/irq.h>
[eb562f2]16#include <rtems/score/thread.h>
17#include <rtems/score/apiext.h>
18
[67a2288]19/*
20 * pointer to the mask representing the additionnal irq vectors
21 * that must be disabled when a particular entry is activated.
22 * They will be dynamically computed from teh prioruty table given
[0ebbf66]23 * in BSP_rtems_irq_mngt_set();
[67a2288]24 * CAUTION : this table is accessed directly by interrupt routine
25 *           prologue.
26 */
[0ebbf66]27rtems_i8259_masks       irq_mask_or_tbl[BSP_IRQ_LINES_NUMBER];
[67a2288]28
29/*
30 * default handler connected on each irq after bsp initialization
31 */
32static rtems_irq_connect_data   default_rtems_entry;
33
34/*
35 * location used to store initial tables used for interrupt
36 * management.
37 */
38static rtems_irq_global_settings*       internal_config;
[f0a2528]39rtems_irq_connect_data*                 rtems_hdl_tbl;
[67a2288]40/*-------------------------------------------------------------------------+
41| Cache for 1st and 2nd PIC IRQ line's status (enabled or disabled) register.
42+--------------------------------------------------------------------------*/
43/*
44 * lower byte is interrupt mask on the master PIC.
45 * while upper bits are interrupt on the slave PIC.
46 * This cache is initialized in ldseg.s
47 */
[a1c70a2]48rtems_i8259_masks i8259s_cache = 0xFFFB;
[67a2288]49
50/*-------------------------------------------------------------------------+
[0ebbf66]51|         Function:  BSP_irq_disable_at_i8259s
[67a2288]52|      Description: Mask IRQ line in appropriate PIC chip.
53| Global Variables: i8259s_cache
54|        Arguments: vector_offset - number of IRQ line to mask.
[6128a4a]55|          Returns: Nothing.
[67a2288]56+--------------------------------------------------------------------------*/
[0ebbf66]57int BSP_irq_disable_at_i8259s    (const rtems_irq_symbolic_name irqLine)
[67a2288]58{
59  unsigned short mask;
60  unsigned int  level;
61
[0ebbf66]62  if ( ((int)irqLine < BSP_LOWEST_OFFSET) ||
63       ((int)irqLine > BSP_MAX_OFFSET )
[67a2288]64       )
65    return 1;
[6128a4a]66
[67a2288]67  _CPU_ISR_Disable(level);
[6128a4a]68
[67a2288]69  mask = 1 << irqLine;
70  i8259s_cache |= mask;
[6128a4a]71
[67a2288]72  if (irqLine < 8)
73  {
74    outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff);
75  }
76  else
77  {
[783e8322]78    outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) >> 8));
[67a2288]79  }
80  _CPU_ISR_Enable (level);
81
82  return 0;
[6128a4a]83}
[67a2288]84
85/*-------------------------------------------------------------------------+
[0ebbf66]86|         Function:  BSP_irq_enable_at_i8259s
[67a2288]87|      Description: Unmask IRQ line in appropriate PIC chip.
88| Global Variables: i8259s_cache
89|        Arguments: irqLine - number of IRQ line to mask.
[6128a4a]90|          Returns: Nothing.
[67a2288]91+--------------------------------------------------------------------------*/
[0ebbf66]92int BSP_irq_enable_at_i8259s    (const rtems_irq_symbolic_name irqLine)
[67a2288]93{
94  unsigned short mask;
95  unsigned int  level;
96
[0ebbf66]97  if ( ((int)irqLine < BSP_LOWEST_OFFSET) ||
98       ((int)irqLine > BSP_MAX_OFFSET )
[67a2288]99       )
100    return 1;
101
102  _CPU_ISR_Disable(level);
[6128a4a]103
[67a2288]104  mask = ~(1 << irqLine);
105  i8259s_cache &= mask;
[6128a4a]106
[67a2288]107  if (irqLine < 8)
108  {
109    outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff);
110  }
111  else
112  {
[783e8322]113    outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) >> 8));
[67a2288]114  }
115  _CPU_ISR_Enable (level);
116
117  return 0;
118} /* mask_irq */
119
[0ebbf66]120int BSP_irq_enabled_at_i8259s           (const rtems_irq_symbolic_name irqLine)
[67a2288]121{
122  unsigned short mask;
123
[0ebbf66]124  if ( ((int)irqLine < BSP_LOWEST_OFFSET) ||
125       ((int)irqLine > BSP_MAX_OFFSET )
[67a2288]126     )
127    return 1;
128
129  mask = (1 << irqLine);
130  return  (~(i8259s_cache & mask));
131}
[6128a4a]132
[67a2288]133/*-------------------------------------------------------------------------+
[0ebbf66]134|         Function: BSP_irq_ack_at_i8259s
[67a2288]135|      Description: Signal generic End Of Interrupt (EOI) to appropriate PIC.
136| Global Variables: None.
137|        Arguments: irqLine - number of IRQ line to acknowledge.
[6128a4a]138|          Returns: Nothing.
[67a2288]139+--------------------------------------------------------------------------*/
[0ebbf66]140int BSP_irq_ack_at_i8259s       (const rtems_irq_symbolic_name irqLine)
[67a2288]141{
[0ebbf66]142  if ( ((int)irqLine < BSP_LOWEST_OFFSET) ||
143       ((int)irqLine > BSP_MAX_OFFSET )
[67a2288]144       )
145    return 1;
146
147  if (irqLine >= 8) {
148   outport_byte(PIC_SLAVE_COMMAND_IO_PORT, PIC_EOI);
149  }
150  outport_byte(PIC_MASTER_COMMAND_IO_PORT, PIC_EOI);
151
152  return 0;
153
154} /* ackIRQ */
155
156/*
157 * ------------------------ RTEMS Irq helper functions ----------------
158 */
[6128a4a]159
[67a2288]160/*
161 * Caution : this function assumes the variable "internal_config"
162 * is already set and that the tables it contains are still valid
163 * and accessible.
164 */
165static void compute_i8259_masks_from_prio ()
166{
167  unsigned int i;
168  unsigned int j;
169  /*
170   * Always mask at least current interrupt to prevent re-entrance
171   */
172  for (i=0; i < internal_config->irqNb; i++) {
173    * ((unsigned short*) &irq_mask_or_tbl[i]) = (1 << i);
174    for (j = 0; j < internal_config->irqNb; j++) {
175      /*
176       * Mask interrupts at i8259 level that have a lower priority
177       */
178      if (internal_config->irqPrioTbl [i] > internal_config->irqPrioTbl [j]) {
179        * ((unsigned short*) &irq_mask_or_tbl[i]) |= (1 << j);
180      }
181    }
182  }
183}
184
185/*
186 * This function check that the value given for the irq line
187 * is valid.
188 */
189
190static int isValidInterrupt(int irq)
191{
[0ebbf66]192  if ( (irq < BSP_LOWEST_OFFSET) || (irq > BSP_MAX_OFFSET))
[67a2288]193    return 0;
194  return 1;
195}
196
197/*
198 * ------------------------ RTEMS Single Irq Handler Mngt Routines ----------------
199 */
200
[0ebbf66]201int BSP_install_rtems_irq_handler  (const rtems_irq_connect_data* irq)
[67a2288]202{
203    unsigned int level;
[6128a4a]204
[67a2288]205    if (!isValidInterrupt(irq->name)) {
206      return 0;
207    }
208    /*
209     * Check if default handler is actually connected. If not issue an error.
210     * You must first get the current handler via i386_get_current_idt_entry
211     * and then disconnect it using i386_delete_idt_entry.
212     * RATIONALE : to always have the same transition by forcing the user
213     * to get the previous handler before accepting to disconnect.
214     */
[fe235a1e]215    _CPU_ISR_Disable(level);
[67a2288]216    if (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl) {
[fe235a1e]217          _CPU_ISR_Enable(level);
[67a2288]218      return 0;
219    }
220
221    /*
222     * store the data provided by user
223     */
224    rtems_hdl_tbl[irq->name] = *irq;
225    /*
226     * Enable interrupt at PIC level
227     */
[0ebbf66]228    BSP_irq_enable_at_i8259s (irq->name);
[67a2288]229    /*
230     * Enable interrupt on device
231     */
232    irq->on(irq);
[6128a4a]233
[67a2288]234    _CPU_ISR_Enable(level);
235
236    return 1;
237}
238
[0ebbf66]239int BSP_get_current_rtems_irq_handler   (rtems_irq_connect_data* irq)
[67a2288]240{
[fe235a1e]241     unsigned int level;
242
[67a2288]243     if (!isValidInterrupt(irq->name)) {
244      return 0;
245     }
[fe235a1e]246    _CPU_ISR_Disable(level);
[67a2288]247     *irq = rtems_hdl_tbl[irq->name];
[fe235a1e]248    _CPU_ISR_Enable(level);
[67a2288]249     return 1;
250}
251
[0ebbf66]252int BSP_remove_rtems_irq_handler  (const rtems_irq_connect_data* irq)
[67a2288]253{
254    unsigned int level;
[6128a4a]255
[67a2288]256    if (!isValidInterrupt(irq->name)) {
257      return 0;
258    }
259    /*
260     * Check if default handler is actually connected. If not issue an error.
261     * You must first get the current handler via i386_get_current_idt_entry
262     * and then disconnect it using i386_delete_idt_entry.
263     * RATIONALE : to always have the same transition by forcing the user
264     * to get the previous handler before accepting to disconnect.
265     */
[fe235a1e]266    _CPU_ISR_Disable(level);
[67a2288]267    if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) {
[fe235a1e]268      _CPU_ISR_Enable(level);
[67a2288]269      return 0;
270    }
271
272    /*
273     * disable interrupt at PIC level
274     */
[0ebbf66]275    BSP_irq_disable_at_i8259s (irq->name);
[67a2288]276
277    /*
278     * Disable interrupt on device
279     */
280    irq->off(irq);
281
282    /*
283     * restore the default irq value
284     */
285    rtems_hdl_tbl[irq->name] = default_rtems_entry;
286
287    _CPU_ISR_Enable(level);
288
289    return 1;
290}
291
292/*
293 * ------------------------ RTEMS Global Irq Handler Mngt Routines ----------------
294 */
295
[0ebbf66]296int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
[67a2288]297{
298    int i;
299    unsigned int level;
300   /*
301    * Store various code accelerators
302    */
303    internal_config             = config;
304    default_rtems_entry         = config->defaultEntry;
305    rtems_hdl_tbl               = config->irqHdlTbl;
306
307    _CPU_ISR_Disable(level);
308    /*
309     * set up internal tables used by rtems interrupt prologue
310     */
311    compute_i8259_masks_from_prio ();
312
313    for (i=0; i < internal_config->irqNb; i++) {
314      if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
[0ebbf66]315        BSP_irq_enable_at_i8259s (i);
[67a2288]316        rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
317      }
318      else {
319        rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
[0ebbf66]320        BSP_irq_disable_at_i8259s (i);
[67a2288]321      }
322    }
323    /*
[ba46ffa6]324     * must enable slave pic anyway
[67a2288]325     */
[0ebbf66]326    BSP_irq_enable_at_i8259s (2);
[67a2288]327    _CPU_ISR_Enable(level);
328    return 1;
329}
330
[0ebbf66]331int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** config)
[67a2288]332{
333    *config = internal_config;
334    return 0;
[6128a4a]335}
[8b2ee37c]336
337void _ThreadProcessSignalsFromIrq (CPU_Exception_frame* ctx)
338{
339  /*
[eb562f2]340   * Process pending signals that have not already been
341   * processed by _Thread_Displatch. This happens quite
342   * unfrequently : the ISR must have posted an action
343   * to the current running thread.
344   */
345  if ( _Thread_Do_post_task_switch_extension ||
346       _Thread_Executing->do_post_task_switch_extension ) {
347    _Thread_Executing->do_post_task_switch_extension = FALSE;
348    _API_extensions_Run_postswitch();
349  }
350  /*
351   * I plan to process other thread related events here.
[ba46ffa6]352   * This will include DEBUG session requested from keyboard...
[8b2ee37c]353   */
354}
[f0a2528]355
356void processIrq(unsigned index)
357{
358  rtems_hdl_tbl[index].hdl(rtems_hdl_tbl[index].handle);
359}
360
Note: See TracBrowser for help on using the repository browser.