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

4.104.114.84.95
Last change on this file since cba119c9 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: 6.8 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        lea       (ecx,ecx,2), eax
111        mov       SYM (rtems_hdl_tbl), edx
112        shl       $0x3,eax
113        pushl     0x8(edx,eax,1)            /* push hdl argument */
114        call      *0x4(edx,eax,1)           /* call hdl */
115        addl      $4, esp
116
117        /*
118         * disable interrupts_again
119         */
120        cli
121        popl       ecx                       /* ecx = vector number */
122        /*
123         * restore stack
124         */
125        movl      ebp, esp
126        popl      ebp
127
128        /*
129         * restore the original i8259 masks
130         */
131        popl      eax
132        movw      ax, SYM (i8259s_cache)
133        outb      $PIC_MASTER_IMR_IO_PORT
134        movb      ah, al
135        outb      $PIC_SLAVE_IMR_IO_PORT
136
137        decl      SYM (_ISR_Nest_level)     /* one less ISR nest level */
138                                            /* If interrupts are nested, */
139                                            /*   then dispatching is disabled */
140
141        decl      SYM (_Thread_Dispatch_disable_level)
142                                            /* unnest multitasking */
143                                            /* Is dispatch disabled */
144        jne       .exit                     /* Yes, then exit */
145
146        cmpl      $0, SYM (_Context_Switch_necessary)
147                                            /* Is task switch necessary? */
148        jne       .schedule                 /* Yes, then call the scheduler */
149
150        cmpl      $0, SYM (_ISR_Signals_to_thread_executing)
151                                            /* signals sent to Run_thread */
152                                            /*   while in interrupt handler? */
153        je        .exit                     /* No, exit */
154
155.bframe:
156        movl      $0, SYM (_ISR_Signals_to_thread_executing)
157        /*
158         * This code is the less critical path. In order to have a single
159         * Thread Context, we take the same frame than the one pushed on
160         * exceptions. This makes sense because Signal is a software
161         * exception.
162         */
163        popl    edx
164        popl    ecx
165        popl    eax
166
167        pushl   $0      # fake fault code
168        pushl   $0      # fake exception number
169
170        pusha
171        pushl   esp
172        call    _ThreadProcessSignalsFromIrq
173        addl    $4, esp
174        popa
175        addl    $8, esp
176        iret
177
178.schedule:
179        /*
180         * the scratch registers have already been saved and we are already
181         * back on the thread system stack. So we can call _Thread_Displatch
182         * directly
183         */
184        call _Thread_Dispatch
185        /*
186         * fall through exit to restore complete contex (scratch registers
187         * eip, CS, Flags).
188         */
189.exit:
190       /*
191        * BEGINNING OF DE-ESTABLISH SEGMENTS
192        *
193        *  NOTE:  Make sure there is code here if code is added to
194        *         load the segment registers.
195        *
196        */
197
198       /******* DE-ESTABLISH SEGMENTS CODE GOES HERE ********/
199
200       /*
201        * END OF DE-ESTABLISH SEGMENTS
202        */
203        popl    edx
204        popl    ecx
205        popl    eax
206        iret
207
208#define DISTINCT_INTERRUPT_ENTRY(_vector) \
209        .p2align 4                         ; \
210        PUBLIC (rtems_irq_prologue_ ## _vector ) ; \
211SYM (rtems_irq_prologue_ ## _vector ):             \
212        pushl   eax             ; \
213        pushl   ecx             ; \
214        pushl   edx             ; \
215        movl    $ _vector, ecx  ; \
216        jmp   SYM (_ISR_Handler) ;
217
218DISTINCT_INTERRUPT_ENTRY(0)
219DISTINCT_INTERRUPT_ENTRY(1)
220DISTINCT_INTERRUPT_ENTRY(2)
221DISTINCT_INTERRUPT_ENTRY(3)
222DISTINCT_INTERRUPT_ENTRY(4)
223DISTINCT_INTERRUPT_ENTRY(5)
224DISTINCT_INTERRUPT_ENTRY(6)
225DISTINCT_INTERRUPT_ENTRY(7)
226DISTINCT_INTERRUPT_ENTRY(8)
227DISTINCT_INTERRUPT_ENTRY(9)
228DISTINCT_INTERRUPT_ENTRY(10)
229DISTINCT_INTERRUPT_ENTRY(11)
230DISTINCT_INTERRUPT_ENTRY(12)
231DISTINCT_INTERRUPT_ENTRY(13)
232DISTINCT_INTERRUPT_ENTRY(14)
233DISTINCT_INTERRUPT_ENTRY(15)
234
235        /*
236         * routine used to initialize the IDT by default
237         */
238
239PUBLIC (default_raw_idt_handler)
240PUBLIC (raw_idt_notify)
241
242SYM (default_raw_idt_handler):
243        pusha
244        cld
245        call    raw_idt_notify
246        popa
247        iret
248
249END_CODE
250
251END
Note: See TracBrowser for help on using the repository browser.