source: rtems/c/src/lib/libbsp/i386/shared/irq/irq_asm.s @ 26b5c77f

4.104.114.84.95
Last change on this file since 26b5c77f was 8b2ee37c, checked in by Joel Sherrill <joel.sherrill@…>, on 08/19/98 at 20:09:59

Patch from Eric Valette <valette@…>:

  • Use the "hlt" instruction for the Idle thread,
  • Optimise interrupt PATH leadding to thread wakeup,
  • Preparation for Intel exception management that should come before the end of the week...
  • 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.OARcorp.com/rtems/license.html.
10 *
11 *  $Id$
12 */
13
14#include "asm.h"       
15#include <irq_asm.h>
16
17SYM (_ISR_Handler):     
18       /*
19        *  Before this was point is reached the vectors unique
20        *  entry point did the following:
21        *
22        *     1. saved scratch registers registers eax edx ecx"
23        *     2. put the vector number in ecx.
24        *
25        * BEGINNING OF ESTABLISH SEGMENTS
26        *
27        *  WARNING: If an interrupt can occur when the segments are
28        *           not correct, then this is where we should establish
29        *           the segments.  In addition to establishing the
30        *           segments, it may be necessary to establish a stack
31        *           in the current data area on the outermost interrupt.
32        *
33        *  NOTE:  If the previous values of the segment registers are
34        *         pushed, do not forget to adjust SAVED_REGS.
35        *
36        *  NOTE:  Make sure the exit code which restores these
37        *         when this type of code is needed.
38        */
39
40       /***** ESTABLISH SEGMENTS CODE GOES HERE  ******/
41
42       /*
43        * END OF ESTABLISH SEGMENTS
44        */
45
46        /*
47         *  Now switch stacks if necessary
48         */
49
50        movw      SYM (i8259s_cache), ax # move current i8259 interrupt mask in ax
51        pushl     eax                         # push it on the stack
52        /*
53         * compute the new PIC mask:
54         *
55         * <new mask> = <old mask> | irq_mask_or_tbl[<intr number aka ecx>]
56         */
57        movw      SYM (irq_mask_or_tbl) (,ecx,2), dx
58        orw       dx, ax
59        /*
60         * Install new computed value on the i8259 and update cache
61         * accordingly
62         */
63        movw      ax, SYM (i8259s_cache)
64        outb      $PIC_MASTER_IMR_IO_PORT
65        movb      ah, al
66        outb      $PIC_SLAVE_IMR_IO_PORT
67
68        /*
69         * acknowledge the interrupt
70         *
71         */
72        movb    $PIC_EOI, al
73        cmpl    $7, ecx
74        jbe     .master
75        outb    $PIC_SLAVE_COMMAND_IO_PORT
76.master:
77        outb    $PIC_MASTER_COMMAND_IO_PORT
78       
79.check_stack_switch:
80        pushl     ebp
81        movl      esp, ebp                  # ebp = previous stack pointer
82        cmpl      $0, SYM (_ISR_Nest_level) # is this the outermost interrupt?
83        jne       nested                    # No, then continue
84        movl      SYM (_CPU_Interrupt_stack_high), esp
85
86        /*
87         *  We want to insure that the old stack pointer is on the
88         *  stack we will be on at the end of the ISR when we restore it.
89         *  By saving it on every interrupt, all we have to do is pop it
90         *  near the end of every interrupt.
91         */
92
93nested:
94        incl      SYM (_ISR_Nest_level)     # one nest level deeper
95        incl      SYM (_Thread_Dispatch_disable_level) # disable multitasking
96        /*
97         * re-enable interrupts at processor level as the current
98         * interrupt source is now masked via i8259
99         */
100        sti
101       
102        /*
103         *  ECX is preloaded with the vector number but it is a scratch register
104         *  so we must save it again.
105         */
106       
107        pushl     ecx                       # push vector number
108        mov       SYM (current_irq) (,ecx,4),eax
109                                            # eax = Users handler
110        call      *eax                      # invoke user ISR
111        /*
112         * disable interrupts_again
113         */
114        cli
115        popl       ecx                       # ecx = vector number
116        /*
117         * restore stack
118         */
119        movl      ebp, esp
120        popl      ebp
121
122        /*
123         * restore the original i8259 masks
124         */
125        popl      eax
126        movw      ax, SYM (i8259s_cache)
127        outb      $PIC_MASTER_IMR_IO_PORT
128        movb      ah, al
129        outb      $PIC_SLAVE_IMR_IO_PORT
130       
131       
132        decl      SYM (_ISR_Nest_level)     # one less ISR nest level
133                                            # If interrupts are nested,
134                                            #   then dispatching is disabled
135
136        decl      SYM (_Thread_Dispatch_disable_level)
137                                            # unnest multitasking
138                                            # Is dispatch disabled
139        jne       .exit                     # Yes, then exit
140
141        cmpl      $0, SYM (_Context_Switch_necessary)
142                                            # Is task switch necessary?
143        jne       .schedule                 # Yes, then call the scheduler
144
145        cmpl      $0, SYM (_ISR_Signals_to_thread_executing)
146                                            # signals sent to Run_thread
147                                            #   while in interrupt handler?
148        je        .exit                     # No, exit
149
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                               
205#define DISTINCT_INTERRUPT_ENTRY(_vector) \
206        .p2align 4                         ; \
207        PUBLIC (rtems_irq_prologue_ ## _vector ) ; \
208SYM (rtems_irq_prologue_ ## _vector ):             \
209        pushl   eax             ; \
210        pushl   ecx             ; \
211        pushl   edx             ; \
212        movl    $ _vector, ecx  ; \
213        jmp   SYM (_ISR_Handler) ;
214
215DISTINCT_INTERRUPT_ENTRY(0)
216DISTINCT_INTERRUPT_ENTRY(1)
217DISTINCT_INTERRUPT_ENTRY(2)
218DISTINCT_INTERRUPT_ENTRY(3)
219DISTINCT_INTERRUPT_ENTRY(4)
220DISTINCT_INTERRUPT_ENTRY(5)
221DISTINCT_INTERRUPT_ENTRY(6)
222DISTINCT_INTERRUPT_ENTRY(7)
223DISTINCT_INTERRUPT_ENTRY(8)
224DISTINCT_INTERRUPT_ENTRY(9)
225DISTINCT_INTERRUPT_ENTRY(10)
226DISTINCT_INTERRUPT_ENTRY(11)
227DISTINCT_INTERRUPT_ENTRY(12)
228DISTINCT_INTERRUPT_ENTRY(13)
229DISTINCT_INTERRUPT_ENTRY(14)
230DISTINCT_INTERRUPT_ENTRY(15)
231       
232        /*
233         * routine used to initialize the IDT by default
234         */
235               
236PUBLIC (default_raw_idt_handler)
237PUBLIC (raw_idt_notify)
238               
239SYM (default_raw_idt_handler):
240        pusha
241        cld
242        call    raw_idt_notify
243        popa
244        iret
245       
Note: See TracBrowser for help on using the repository browser.