OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libbsp/] [i386/] [shared/] [irq/] [irq.c] - Blame information for rev 173

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.