source: rtems/c/src/lib/libbsp/i386/shared/irq/irq_asm.s @ 67a2288

4.104.114.84.9
Last change on this file since 67a2288 was 67a2288, checked in by Joel Sherrill <joel.sherrill@…>, on Jul 23, 1998 at 10:02:34 PM

Patch from Eric VALETTE <valette@…>:

Here is a enhanced version of my previous patch. This patch enables
to potentially share the new interrupt management code for all Intel targets
(pc386, go32 and force386) bsp.

Note : this patch is complete only for pc386. It still needs to

be completed for go32 and force386. I carrefully checked
that anything needed is in for force386 (only some function
name changes for IDT manipulation and GDT segment
manipulation). But anyway I will not be able to test any
of theses targets...

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