]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/i386/isa/atpic_vector.s
Move ICU_* defines into icu.h.
[FreeBSD/FreeBSD.git] / sys / i386 / isa / atpic_vector.s
1 /*
2  *      from: vector.s, 386BSD 0.1 unknown origin
3  * $FreeBSD$
4  */
5
6 #define IRQ_BIT(irq_num)        (1 << ((irq_num) % 8))
7 #define IRQ_LBIT(irq_num)       (1 << (irq_num))
8 #define IRQ_BYTE(irq_num)       ((irq_num) >> 3)
9
10 #ifdef AUTO_EOI_1
11
12 #define ENABLE_ICU1             /* use auto-EOI to reduce i/o */
13 #define OUTB_ICU1
14
15 #else
16
17 #define ENABLE_ICU1                                                     \
18         movb    $ICU_EOI,%al ;  /* as soon as possible send EOI ... */  \
19         OUTB_ICU1               /* ... to clear in service bit */
20
21 #define OUTB_ICU1                                                       \
22         outb    %al,$IO_ICU1
23
24 #endif
25
26 #ifdef AUTO_EOI_2
27 /*
28  * The data sheet says no auto-EOI on slave, but it sometimes works.
29  */
30 #define ENABLE_ICU1_AND_2       ENABLE_ICU1
31
32 #else
33
34 #define ENABLE_ICU1_AND_2                                               \
35         movb    $ICU_EOI,%al ;  /* as above */                          \
36         outb    %al,$IO_ICU2 ;  /* but do second icu first ... */       \
37         OUTB_ICU1               /* ... then first icu (if !AUTO_EOI_1) */
38
39 #endif
40
41 #define PUSH_FRAME                                                      \
42         pushl   $0 ;            /* dummy error code */                  \
43         pushl   $0 ;            /* dummy trap type */                   \
44         pushal ;                /* 8 ints */                            \
45         pushl   %ds ;           /* save data and extra segments ... */  \
46         pushl   %es ;                                                   \
47         pushl   %fs
48
49 #define PUSH_DUMMY                                                      \
50         pushfl ;                /* eflags */                            \
51         pushl   %cs ;           /* cs */                                \
52         pushl   12(%esp) ;      /* original caller eip */               \
53         pushl   $0 ;            /* dummy error code */                  \
54         pushl   $0 ;            /* dummy trap type */                   \
55         subl    $11*4,%esp
56
57 #define POP_FRAME                                                       \
58         popl    %fs ;                                                   \
59         popl    %es ;                                                   \
60         popl    %ds ;                                                   \
61         popal ;                                                         \
62         addl    $4+4,%esp
63
64 #define POP_DUMMY                                                       \
65         addl    $16*4,%esp
66
67 #define MASK_IRQ(icu, irq_num)                                          \
68         movb    imen + IRQ_BYTE(irq_num),%al ;                          \
69         orb     $IRQ_BIT(irq_num),%al ;                                 \
70         movb    %al,imen + IRQ_BYTE(irq_num) ;                          \
71         outb    %al,$icu+ICU_IMR_OFFSET
72
73 #define UNMASK_IRQ(icu, irq_num)                                        \
74         movb    imen + IRQ_BYTE(irq_num),%al ;                          \
75         andb    $~IRQ_BIT(irq_num),%al ;                                \
76         movb    %al,imen + IRQ_BYTE(irq_num) ;                          \
77         outb    %al,$icu+ICU_IMR_OFFSET
78 /*
79  * Macros for interrupt interrupt entry, call to handler, and exit.
80  */
81
82 #define FAST_INTR(irq_num, vec_name, icu, enable_icus)                  \
83         .text ;                                                         \
84         SUPERALIGN_TEXT ;                                               \
85 IDTVEC(vec_name) ;                                                      \
86         PUSH_FRAME ;                                                    \
87         mov     $KDSEL,%ax ;                                            \
88         mov     %ax,%ds ;                                               \
89         mov     %ax,%es ;                                               \
90         mov     $KPSEL,%ax ;                                            \
91         mov     %ax,%fs ;                                               \
92         FAKE_MCOUNT((12+ACTUALLY_PUSHED)*4(%esp)) ;                     \
93         movl    PCPU(CURTHREAD),%ebx ;                                  \
94         cmpl    $0,TD_CRITNEST(%ebx) ;                                  \
95         je      1f ;                                                    \
96 ;                                                                       \
97         movl    $1,PCPU(INT_PENDING) ;                                  \
98         orl     $IRQ_LBIT(irq_num),PCPU(FPENDING) ;                     \
99         MASK_IRQ(icu, irq_num) ;                                        \
100         enable_icus ;                                                   \
101         jmp     10f ;                                                   \
102 1: ;                                                                    \
103         incl    TD_CRITNEST(%ebx) ;                                     \
104         incl    TD_INTR_NESTING_LEVEL(%ebx) ;                           \
105         pushl   intr_unit + (irq_num) * 4 ;                             \
106         call    *intr_handler + (irq_num) * 4 ;                         \
107         addl    $4,%esp ;                                               \
108         enable_icus ;                                                   \
109         incl    cnt+V_INTR ;    /* book-keeping can wait */             \
110         movl    intr_countp + (irq_num) * 4,%eax ;                      \
111         incl    (%eax) ;                                                \
112         decl    TD_CRITNEST(%ebx) ;                                     \
113         cmpl    $0,PCPU(INT_PENDING) ;                                  \
114         je      2f ;                                                    \
115 ;                                                                       \
116         call    i386_unpend ;                                           \
117 2: ;                                                                    \
118         decl    TD_INTR_NESTING_LEVEL(%ebx) ;                           \
119 10: ;                                                                   \
120         MEXITCOUNT ;                                                    \
121         jmp     doreti
122
123 /*
124  * Restart a fast interrupt that was held up by a critical section.
125  * This routine is called from unpend().  unpend() ensures we are
126  * in a critical section and deals with the interrupt nesting level
127  * for us.  If we previously masked the irq, we have to unmask it.
128  *
129  * We have a choice.  We can regenerate the irq using the 'int'
130  * instruction or we can create a dummy frame and call the interrupt
131  * handler directly.  I've chosen to use the dummy-frame method.
132  */
133 #define FAST_UNPEND(irq_num, vec_name, icu)                             \
134         .text ;                                                         \
135         SUPERALIGN_TEXT ;                                               \
136 IDTVEC(vec_name) ;                                                      \
137 ;                                                                       \
138         pushl %ebp ;                                                    \
139         movl %esp, %ebp ;                                               \
140         PUSH_DUMMY ;                                                    \
141         pushl   intr_unit + (irq_num) * 4 ;                             \
142         call    *intr_handler + (irq_num) * 4 ; /* do the work ASAP */  \
143         addl    $4, %esp ;                                              \
144         incl    cnt+V_INTR ;    /* book-keeping can wait */             \
145         movl    intr_countp + (irq_num) * 4,%eax ;                      \
146         incl    (%eax) ;                                                \
147         UNMASK_IRQ(icu, irq_num) ;                                      \
148         POP_DUMMY ;                                                     \
149         popl %ebp ;                                                     \
150         ret
151
152 /* 
153  * Slow, threaded interrupts.
154  *
155  * XXX Most of the parameters here are obsolete.  Fix this when we're
156  * done.
157  * XXX we really shouldn't return via doreti if we just schedule the
158  * interrupt handler and don't run anything.  We could just do an
159  * iret.  FIXME.
160  */
161 #define INTR(irq_num, vec_name, icu, enable_icus, maybe_extra_ipending) \
162         .text ;                                                         \
163         SUPERALIGN_TEXT ;                                               \
164 IDTVEC(vec_name) ;                                                      \
165         PUSH_FRAME ;                                                    \
166         mov     $KDSEL,%ax ;    /* load kernel ds, es and fs */         \
167         mov     %ax,%ds ;                                               \
168         mov     %ax,%es ;                                               \
169         mov     $KPSEL,%ax ;                                            \
170         mov     %ax,%fs ;                                               \
171 ;                                                                       \
172         maybe_extra_ipending ;                                          \
173         MASK_IRQ(icu, irq_num) ;                                        \
174         enable_icus ;                                                   \
175 ;                                                                       \
176         movl    PCPU(CURTHREAD),%ebx ;                                  \
177         cmpl    $0,TD_CRITNEST(%ebx) ;                                  \
178         je      1f ;                                                    \
179         movl    $1,PCPU(INT_PENDING);                                   \
180         orl     $IRQ_LBIT(irq_num),PCPU(IPENDING) ;                     \
181         jmp     10f ;                                                   \
182 1: ;                                                                    \
183         incl    TD_INTR_NESTING_LEVEL(%ebx) ;                           \
184 ;                                                                       \
185         FAKE_MCOUNT(13*4(%esp)) ;       /* XXX late to avoid double count */ \
186         cmpl    $0,PCPU(INT_PENDING) ;                                  \
187         je      9f ;                                                    \
188         call    i386_unpend ;                                           \
189 9: ;                                                                    \
190         pushl   $irq_num;       /* pass the IRQ */                      \
191         call    sched_ithd ;                                            \
192         addl    $4, %esp ;      /* discard the parameter */             \
193 ;                                                                       \
194         decl    TD_INTR_NESTING_LEVEL(%ebx) ;                           \
195 10: ;                                                                   \
196         MEXITCOUNT ;                                                    \
197         jmp     doreti
198
199 MCOUNT_LABEL(bintr)
200         FAST_INTR(0,fastintr0, IO_ICU1, ENABLE_ICU1)
201         FAST_INTR(1,fastintr1, IO_ICU1, ENABLE_ICU1)
202         FAST_INTR(2,fastintr2, IO_ICU1, ENABLE_ICU1)
203         FAST_INTR(3,fastintr3, IO_ICU1, ENABLE_ICU1)
204         FAST_INTR(4,fastintr4, IO_ICU1, ENABLE_ICU1)
205         FAST_INTR(5,fastintr5, IO_ICU1, ENABLE_ICU1)
206         FAST_INTR(6,fastintr6, IO_ICU1, ENABLE_ICU1)
207         FAST_INTR(7,fastintr7, IO_ICU1, ENABLE_ICU1)
208         FAST_INTR(8,fastintr8, IO_ICU2, ENABLE_ICU1_AND_2)
209         FAST_INTR(9,fastintr9, IO_ICU2, ENABLE_ICU1_AND_2)
210         FAST_INTR(10,fastintr10, IO_ICU2, ENABLE_ICU1_AND_2)
211         FAST_INTR(11,fastintr11, IO_ICU2, ENABLE_ICU1_AND_2)
212         FAST_INTR(12,fastintr12, IO_ICU2, ENABLE_ICU1_AND_2)
213         FAST_INTR(13,fastintr13, IO_ICU2, ENABLE_ICU1_AND_2)
214         FAST_INTR(14,fastintr14, IO_ICU2, ENABLE_ICU1_AND_2)
215         FAST_INTR(15,fastintr15, IO_ICU2, ENABLE_ICU1_AND_2)
216
217 #define CLKINTR_PENDING movl $1,CNAME(clkintr_pending)
218 /* Threaded interrupts */
219         INTR(0,intr0, IO_ICU1, ENABLE_ICU1, CLKINTR_PENDING)
220         INTR(1,intr1, IO_ICU1, ENABLE_ICU1,)
221         INTR(2,intr2, IO_ICU1, ENABLE_ICU1,)
222         INTR(3,intr3, IO_ICU1, ENABLE_ICU1,)
223         INTR(4,intr4, IO_ICU1, ENABLE_ICU1,)
224         INTR(5,intr5, IO_ICU1, ENABLE_ICU1,)
225         INTR(6,intr6, IO_ICU1, ENABLE_ICU1,)
226         INTR(7,intr7, IO_ICU1, ENABLE_ICU1,)
227         INTR(8,intr8, IO_ICU2, ENABLE_ICU1_AND_2,)
228         INTR(9,intr9, IO_ICU2, ENABLE_ICU1_AND_2,)
229         INTR(10,intr10, IO_ICU2, ENABLE_ICU1_AND_2,)
230         INTR(11,intr11, IO_ICU2, ENABLE_ICU1_AND_2,)
231         INTR(12,intr12, IO_ICU2, ENABLE_ICU1_AND_2,)
232         INTR(13,intr13, IO_ICU2, ENABLE_ICU1_AND_2,)
233         INTR(14,intr14, IO_ICU2, ENABLE_ICU1_AND_2,)
234         INTR(15,intr15, IO_ICU2, ENABLE_ICU1_AND_2,)
235
236         FAST_UNPEND(0,fastunpend0, IO_ICU1)
237         FAST_UNPEND(1,fastunpend1, IO_ICU1)
238         FAST_UNPEND(2,fastunpend2, IO_ICU1)
239         FAST_UNPEND(3,fastunpend3, IO_ICU1)
240         FAST_UNPEND(4,fastunpend4, IO_ICU1)
241         FAST_UNPEND(5,fastunpend5, IO_ICU1)
242         FAST_UNPEND(6,fastunpend6, IO_ICU1)
243         FAST_UNPEND(7,fastunpend7, IO_ICU1)
244         FAST_UNPEND(8,fastunpend8, IO_ICU2)
245         FAST_UNPEND(9,fastunpend9, IO_ICU2)
246         FAST_UNPEND(10,fastunpend10, IO_ICU2)
247         FAST_UNPEND(11,fastunpend11, IO_ICU2)
248         FAST_UNPEND(12,fastunpend12, IO_ICU2)
249         FAST_UNPEND(13,fastunpend13, IO_ICU2)
250         FAST_UNPEND(14,fastunpend14, IO_ICU2)
251         FAST_UNPEND(15,fastunpend15, IO_ICU2)
252 MCOUNT_LABEL(eintr)
253