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

4.104.114.84.95
Last change on this file since a3c7123 was a3c7123, checked in by Joel Sherrill <joel.sherrill@…>, on Sep 4, 2003 at 6:51:24 PM

2003-09-04 Joel Sherrill <joel@…>

  • comm/gdb_glue.c, irq/idt.c, irq/irq.c, irq/irq.h, irq/irq_asm.S, irq/irq_asm.h, irq/irq_init.c: URL for license changed.
  • Property mode set to 100644
File size: 6.7 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 "asm.h"       
15#include <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        mov       SYM (current_irq) (,ecx,4),eax
111                                            # eax = Users handler
112        call      *eax                      # invoke user ISR
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       
134        decl      SYM (_ISR_Nest_level)     # one less ISR nest level
135                                            # If interrupts are nested,
136                                            #   then dispatching is disabled
137
138        decl      SYM (_Thread_Dispatch_disable_level)
139                                            # unnest multitasking
140                                            # Is dispatch disabled
141        jne       .exit                     # Yes, then exit
142
143        cmpl      $0, SYM (_Context_Switch_necessary)
144                                            # Is task switch necessary?
145        jne       .schedule                 # Yes, then call the scheduler
146
147        cmpl      $0, SYM (_ISR_Signals_to_thread_executing)
148                                            # signals sent to Run_thread
149                                            #   while in interrupt handler?
150        je        .exit                     # No, exit
151
152       
153.bframe:
154        movl      $0, SYM (_ISR_Signals_to_thread_executing)
155        /*
156         * This code is the less critical path. In order to have a single
157         * Thread Context, we take the same frame than the one pushed on
158         * exceptions. This makes sense because Signal is a software
159         * exception.
160         */
161        popl    edx
162        popl    ecx
163        popl    eax
164
165        pushl   $0      # fake fault code
166        pushl   $0      # fake exception number
167
168        pusha
169        pushl   esp
170        call    _ThreadProcessSignalsFromIrq
171        addl    $4, esp
172        popa
173        addl    $8, esp
174        iret
175                       
176.schedule:
177        /*
178         * the scratch registers have already been saved and we are already
179         * back on the thread system stack. So we can call _Thread_Displatch
180         * directly
181         */
182        call _Thread_Dispatch
183        /*
184         * fall through exit to restore complete contex (scratch registers
185         * eip, CS, Flags).
186         */
187.exit:
188       /*
189        * BEGINNING OF DE-ESTABLISH SEGMENTS
190        *
191        *  NOTE:  Make sure there is code here if code is added to
192        *         load the segment registers.
193        *
194        */
195
196       /******* DE-ESTABLISH SEGMENTS CODE GOES HERE ********/
197
198       /*
199        * END OF DE-ESTABLISH SEGMENTS
200        */
201        popl    edx
202        popl    ecx
203        popl    eax
204        iret
205
206                               
207#define DISTINCT_INTERRUPT_ENTRY(_vector) \
208        .p2align 4                         ; \
209        PUBLIC (rtems_irq_prologue_ ## _vector ) ; \
210SYM (rtems_irq_prologue_ ## _vector ):             \
211        pushl   eax             ; \
212        pushl   ecx             ; \
213        pushl   edx             ; \
214        movl    $ _vector, ecx  ; \
215        jmp   SYM (_ISR_Handler) ;
216
217DISTINCT_INTERRUPT_ENTRY(0)
218DISTINCT_INTERRUPT_ENTRY(1)
219DISTINCT_INTERRUPT_ENTRY(2)
220DISTINCT_INTERRUPT_ENTRY(3)
221DISTINCT_INTERRUPT_ENTRY(4)
222DISTINCT_INTERRUPT_ENTRY(5)
223DISTINCT_INTERRUPT_ENTRY(6)
224DISTINCT_INTERRUPT_ENTRY(7)
225DISTINCT_INTERRUPT_ENTRY(8)
226DISTINCT_INTERRUPT_ENTRY(9)
227DISTINCT_INTERRUPT_ENTRY(10)
228DISTINCT_INTERRUPT_ENTRY(11)
229DISTINCT_INTERRUPT_ENTRY(12)
230DISTINCT_INTERRUPT_ENTRY(13)
231DISTINCT_INTERRUPT_ENTRY(14)
232DISTINCT_INTERRUPT_ENTRY(15)
233       
234        /*
235         * routine used to initialize the IDT by default
236         */
237               
238PUBLIC (default_raw_idt_handler)
239PUBLIC (raw_idt_notify)
240               
241SYM (default_raw_idt_handler):
242        pusha
243        cld
244        call    raw_idt_notify
245        popa
246        iret
247       
248END_CODE
249
250END
Note: See TracBrowser for help on using the repository browser.