source: rtems/c/src/lib/libbsp/i386/shared/irq/irq_asm.S @ a62222fb

4.104.115
Last change on this file since a62222fb was a62222fb, checked in by Joel Sherrill <joel.sherrill@…>, on 02/19/09 at 20:22:25

2009-02-19 Joel Sherrill <joel.sherrill@…>

  • shared/irq/irq.c, shared/irq/irq.h, shared/irq/irq_asm.S: Add shared interrupt support to i386.
  • Property mode set to 100644
File size: 6.6 KB
Line 
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
9 *  http://www.rtems.com/license/LICENSE.
10 *
11 *  $Id$
12 */
13
14#include <rtems/asm.h>
15#include <bsp/irq_asm.h>
16
17               BEGIN_CODE
18
19SYM (_ISR_Handler):
20       /*
21        *  Before this was point is reached the vectors unique
22        *  entry point did the following:
23        *
24        *     1. saved scratch registers registers eax edx ecx"
25        *     2. put the vector number in ecx.
26        *
27        * BEGINNING OF ESTABLISH SEGMENTS
28        *
29        *  WARNING: If an interrupt can occur when the segments are
30        *           not correct, then this is where we should establish
31        *           the segments.  In addition to establishing the
32        *           segments, it may be necessary to establish a stack
33        *           in the current data area on the outermost interrupt.
34        *
35        *  NOTE:  If the previous values of the segment registers are
36        *         pushed, do not forget to adjust SAVED_REGS.
37        *
38        *  NOTE:  Make sure the exit code which restores these
39        *         when this type of code is needed.
40        */
41
42       /***** ESTABLISH SEGMENTS CODE GOES HERE  ******/
43
44       /*
45        * END OF ESTABLISH SEGMENTS
46        */
47
48        /*
49         *  Now switch stacks if necessary
50         */
51
52        movw      SYM (i8259s_cache), ax /* move current i8259 interrupt mask in ax */
53        pushl     eax                         /* push it on the stack */
54        /*
55         * compute the new PIC mask:
56         *
57         * <new mask> = <old mask> | irq_mask_or_tbl[<intr number aka ecx>]
58         */
59        movw      SYM (irq_mask_or_tbl) (,ecx,2), dx
60        orw       dx, ax
61        /*
62         * Install new computed value on the i8259 and update cache
63         * accordingly
64         */
65        movw      ax, SYM (i8259s_cache)
66        outb      $PIC_MASTER_IMR_IO_PORT
67        movb      ah, al
68        outb      $PIC_SLAVE_IMR_IO_PORT
69
70        /*
71         * acknowledge the interrupt
72         *
73         */
74        movb    $PIC_EOI, al
75        cmpl    $7, ecx
76        jbe     .master
77        outb    $PIC_SLAVE_COMMAND_IO_PORT
78.master:
79        outb    $PIC_MASTER_COMMAND_IO_PORT
80
81.check_stack_switch:
82        pushl     ebp
83        movl      esp, ebp                  /* ebp = previous stack pointer */
84        cmpl      $0, SYM (_ISR_Nest_level) /* is this the outermost interrupt? */
85        jne       nested                    /* No, then continue */
86        movl      SYM (_CPU_Interrupt_stack_high), esp
87
88        /*
89         *  We want to insure that the old stack pointer is on the
90         *  stack we will be on at the end of the ISR when we restore it.
91         *  By saving it on every interrupt, all we have to do is pop it
92         *  near the end of every interrupt.
93         */
94
95nested:
96        incl      SYM (_ISR_Nest_level)     /* one nest level deeper */
97        incl      SYM (_Thread_Dispatch_disable_level) /* disable multitasking */
98        /*
99         * re-enable interrupts at processor level as the current
100         * interrupt source is now masked via i8259
101         */
102        sti
103
104        /*
105         *  ECX is preloaded with the vector number but it is a scratch register
106         *  so we must save it again.
107         */
108
109        pushl     ecx                       /* push vector number */
110        call      C_dispatch_isr
111        addl      $4, esp
112
113        /*
114         * disable interrupts_again
115         */
116        cli
117        popl       ecx                       /* ecx = vector number */
118        /*
119         * restore stack
120         */
121        movl      ebp, esp
122        popl      ebp
123
124        /*
125         * restore the original i8259 masks
126         */
127        popl      eax
128        movw      ax, SYM (i8259s_cache)
129        outb      $PIC_MASTER_IMR_IO_PORT
130        movb      ah, al
131        outb      $PIC_SLAVE_IMR_IO_PORT
132
133        decl      SYM (_ISR_Nest_level)     /* one less ISR nest level */
134                                            /* If interrupts are nested, */
135                                            /*   then dispatching is disabled */
136
137        decl      SYM (_Thread_Dispatch_disable_level)
138                                            /* unnest multitasking */
139                                            /* Is dispatch disabled */
140        jne       .exit                     /* Yes, then exit */
141
142        cmpl      $0, SYM (_Context_Switch_necessary)
143                                            /* Is task switch necessary? */
144        jne       .schedule                 /* Yes, then call the scheduler */
145
146        cmpl      $0, SYM (_ISR_Signals_to_thread_executing)
147                                            /* signals sent to Run_thread */
148                                            /*   while in interrupt handler? */
149        je        .exit                     /* No, exit */
150
151.bframe:
152        movl      $0, SYM (_ISR_Signals_to_thread_executing)
153        /*
154         * This code is the less critical path. In order to have a single
155         * Thread Context, we take the same frame than the one pushed on
156         * exceptions. This makes sense because Signal is a software
157         * exception.
158         */
159        popl    edx
160        popl    ecx
161        popl    eax
162
163        pushl   $0      # fake fault code
164        pushl   $0      # fake exception number
165
166        pusha
167        pushl   esp
168        call    _ThreadProcessSignalsFromIrq
169        addl    $4, esp
170        popa
171        addl    $8, esp
172        iret
173
174.schedule:
175        /*
176         * the scratch registers have already been saved and we are already
177         * back on the thread system stack. So we can call _Thread_Displatch
178         * directly
179         */
180        call _Thread_Dispatch
181        /*
182         * fall through exit to restore complete contex (scratch registers
183         * eip, CS, Flags).
184         */
185.exit:
186       /*
187        * BEGINNING OF DE-ESTABLISH SEGMENTS
188        *
189        *  NOTE:  Make sure there is code here if code is added to
190        *         load the segment registers.
191        *
192        */
193
194       /******* DE-ESTABLISH SEGMENTS CODE GOES HERE ********/
195
196       /*
197        * END OF DE-ESTABLISH SEGMENTS
198        */
199        popl    edx
200        popl    ecx
201        popl    eax
202        iret
203
204#define DISTINCT_INTERRUPT_ENTRY(_vector) \
205        .p2align 4                         ; \
206        PUBLIC (rtems_irq_prologue_ ## _vector ) ; \
207SYM (rtems_irq_prologue_ ## _vector ):             \
208        pushl   eax             ; \
209        pushl   ecx             ; \
210        pushl   edx             ; \
211        movl    $ _vector, ecx  ; \
212        jmp   SYM (_ISR_Handler) ;
213
214DISTINCT_INTERRUPT_ENTRY(0)
215DISTINCT_INTERRUPT_ENTRY(1)
216DISTINCT_INTERRUPT_ENTRY(2)
217DISTINCT_INTERRUPT_ENTRY(3)
218DISTINCT_INTERRUPT_ENTRY(4)
219DISTINCT_INTERRUPT_ENTRY(5)
220DISTINCT_INTERRUPT_ENTRY(6)
221DISTINCT_INTERRUPT_ENTRY(7)
222DISTINCT_INTERRUPT_ENTRY(8)
223DISTINCT_INTERRUPT_ENTRY(9)
224DISTINCT_INTERRUPT_ENTRY(10)
225DISTINCT_INTERRUPT_ENTRY(11)
226DISTINCT_INTERRUPT_ENTRY(12)
227DISTINCT_INTERRUPT_ENTRY(13)
228DISTINCT_INTERRUPT_ENTRY(14)
229DISTINCT_INTERRUPT_ENTRY(15)
230
231        /*
232         * routine used to initialize the IDT by default
233         */
234
235PUBLIC (default_raw_idt_handler)
236PUBLIC (raw_idt_notify)
237
238SYM (default_raw_idt_handler):
239        pusha
240        cld
241        call    raw_idt_notify
242        popa
243        iret
244
245END_CODE
246
247END
Note: See TracBrowser for help on using the repository browser.