Import 2.1.34
[davej-history.git] / include / asm-i386 / irq.h
blobd9ff5e78ec6c89d6d7457e2362515f93c135f15a
1 #ifndef _ASM_IRQ_H
2 #define _ASM_IRQ_H
4 /*
5 * linux/include/asm/irq.h
7 * (C) 1992, 1993 Linus Torvalds
9 * IRQ/IPI changes taken from work by Thomas Radke <tomsoft@informatik.tu-chemnitz.de>
12 #include <linux/linkage.h>
13 #include <asm/segment.h>
15 #define NR_IRQS 16
17 #define TIMER_IRQ 0
19 externvoiddisable_irq(unsigned int);
20 externvoidenable_irq(unsigned int);
22 #define __STR(x) #x
23 #define STR(x) __STR(x)
26 #define SAVE_ALL \
27 "cld\n\t" \
28 "push %es\n\t" \
29 "push %ds\n\t" \
30 "pushl %eax\n\t" \
31 "pushl %ebp\n\t" \
32 "pushl %edi\n\t" \
33 "pushl %esi\n\t" \
34 "pushl %edx\n\t" \
35 "pushl %ecx\n\t" \
36 "pushl %ebx\n\t" \
37 "movl $" STR(KERNEL_DS)",%edx\n\t" \
38 "mov %dx,%ds\n\t" \
39 "mov %dx,%es\n\t"
42 * SAVE_MOST/RESTORE_MOST is used for the faster version of IRQ handlers,
43 * installed by using the SA_INTERRUPT flag. These kinds of IRQ's don't
44 * call the routines that do signal handling etc on return, and can have
45 * more relaxed register-saving etc. They are also atomic, and are thus
46 * suited for small, fast interrupts like the serial lines or the harddisk
47 * drivers, which don't actually need signal handling etc.
49 * Also note that we actually save only those registers that are used in
50 * C subroutines (%eax, %edx and %ecx), so if you do something weird,
51 * you're on your own. The only segments that are saved (not counting the
52 * automatic stack and code segment handling) are %ds and %es, and they
53 * point to kernel space. No messing around with %fs here.
55 #define SAVE_MOST \
56 "cld\n\t" \
57 "push %es\n\t" \
58 "push %ds\n\t" \
59 "pushl %eax\n\t" \
60 "pushl %edx\n\t" \
61 "pushl %ecx\n\t" \
62 "movl $" STR(KERNEL_DS)",%edx\n\t" \
63 "mov %dx,%ds\n\t" \
64 "mov %dx,%es\n\t"
66 #define RESTORE_MOST \
67 "popl %ecx\n\t" \
68 "popl %edx\n\t" \
69 "popl %eax\n\t" \
70 "pop %ds\n\t" \
71 "pop %es\n\t" \
72 "iret"
75 * Some fast irq handlers might want to access saved registers (mostly
76 * cs or flags)
79 struct fast_irq_regs {
80 long ecx;
81 long edx;
82 long eax;
83 int xds;
84 int xes;
85 long eip;
86 int xcs;
87 long eflags;
88 long esp;
89 int xss;
93 * The "inb" instructions are not needed, but seem to change the timings
94 * a bit - without them it seems that the harddisk driver won't work on
95 * all hardware. Arghh.
97 #define ACK_FIRST(mask,nr) \
98 "inb $0x21,%al\n\t" \
99 "jmp 1f\n" \
100 "1:\tjmp 1f\n" \
101 "1:\torb $" #mask","SYMBOL_NAME_STR(cache_21)"\n\t" \
102 "movb "SYMBOL_NAME_STR(cache_21)",%al\n\t" \
103 "outb %al,$0x21\n\t" \
104 "jmp 1f\n" \
105 "1:\tjmp 1f\n" \
106 "1:\tmovb $0x20,%al\n\t" \
107 "outb %al,$0x20\n\t"
109 #define ACK_SECOND(mask,nr) \
110 "inb $0xA1,%al\n\t" \
111 "jmp 1f\n" \
112 "1:\tjmp 1f\n" \
113 "1:\torb $" #mask","SYMBOL_NAME_STR(cache_A1)"\n\t" \
114 "movb "SYMBOL_NAME_STR(cache_A1)",%al\n\t" \
115 "outb %al,$0xA1\n\t" \
116 "jmp 1f\n" \
117 "1:\tjmp 1f\n" \
118 "1:\tmovb $0x20,%al\n\t" \
119 "outb %al,$0xA0\n\t" \
120 "jmp 1f\n" \
121 "1:\tjmp 1f\n" \
122 "1:\toutb %al,$0x20\n\t"
124 #define UNBLK_FIRST(mask) \
125 "inb $0x21,%al\n\t" \
126 "jmp 1f\n" \
127 "1:\tjmp 1f\n" \
128 "1:\tandb $~(" #mask"),"SYMBOL_NAME_STR(cache_21)"\n\t" \
129 "movb "SYMBOL_NAME_STR(cache_21)",%al\n\t" \
130 "outb %al,$0x21\n\t"
132 #define UNBLK_SECOND(mask) \
133 "inb $0xA1,%al\n\t" \
134 "jmp 1f\n" \
135 "1:\tjmp 1f\n" \
136 "1:\tandb $~(" #mask"),"SYMBOL_NAME_STR(cache_A1)"\n\t" \
137 "movb "SYMBOL_NAME_STR(cache_A1)",%al\n\t" \
138 "outb %al,$0xA1\n\t"
140 #define IRQ_NAME2(nr) nr##_interrupt(void)
141 #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
142 #define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr)
143 #define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr)
145 #ifdef __SMP__
147 #define GET_CURRENT \
148 "movl "SYMBOL_NAME_STR(apic_reg)", %ebx\n\t" \
149 "movl 32(%ebx), %ebx\n\t" \
150 "shrl $22,%ebx\n\t" \
151 "andl $0x3C,%ebx\n\t" \
152 "movl " SYMBOL_NAME_STR(current_set)"(,%ebx),%ebx\n\t"
154 #else
156 #define GET_CURRENT \
157 "movl " SYMBOL_NAME_STR(current_set)",%ebx\n\t"
159 #endif
161 #ifdef __SMP__
164 * SMP has a few special interrupts for IPI messages
167 #define BUILD_SMP_INTERRUPT(x) \
168 asmlinkage void x(void); \
169 __asm__( \
170 "\n"__ALIGN_STR"\n" \
171 SYMBOL_NAME_STR(x)":\n\t" \
172 "pushl $-1\n\t" \
173 SAVE_ALL \
174 "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
175 "jmp ret_from_intr\n");
177 #define BUILD_SMP_TIMER_INTERRUPT(x) \
178 asmlinkage void x(struct pt_regs * regs); \
179 __asm__( \
180 "\n"__ALIGN_STR"\n" \
181 SYMBOL_NAME_STR(x)":\n\t" \
182 "pushl $-1\n\t" \
183 SAVE_ALL \
184 "movl %esp,%eax\n\t" \
185 "pushl %eax\n\t" \
186 "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
187 "addl $4,%esp\n\t" \
188 "jmp ret_from_intr\n");
190 #endif/* __SMP__ */
192 #define BUILD_IRQ(chip,nr,mask) \
193 asmlinkage void IRQ_NAME(nr); \
194 asmlinkage void FAST_IRQ_NAME(nr); \
195 asmlinkage void BAD_IRQ_NAME(nr); \
196 __asm__( \
197 "\n"__ALIGN_STR"\n" \
198 SYMBOL_NAME_STR(IRQ) #nr"_interrupt:\n\t" \
199 "pushl $-"#nr"-2\n\t" \
200 SAVE_ALL \
201 ACK_##chip(mask,(nr&7)) \
202 "movl %esp,%eax\n\t" \
203 "pushl %eax\n\t" \
204 "pushl $" #nr"\n\t" \
205 "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
206 "addl $8,%esp\n\t" \
207 UNBLK_##chip(mask) \
208 "jmp ret_from_intr\n" \
209 "\n"__ALIGN_STR"\n" \
210 SYMBOL_NAME_STR(fast_IRQ) #nr"_interrupt:\n\t" \
211 SAVE_MOST \
212 ACK_##chip(mask,(nr&7)) \
213 "pushl $" #nr"\n\t" \
214 "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \
215 "addl $4,%esp\n\t" \
216 UNBLK_##chip(mask) \
217 RESTORE_MOST \
218 "\n"__ALIGN_STR"\n" \
219 SYMBOL_NAME_STR(bad_IRQ) #nr"_interrupt:\n\t" \
220 SAVE_MOST \
221 ACK_##chip(mask,(nr&7)) \
222 RESTORE_MOST);
224 #define BUILD_TIMER_IRQ(chip,nr,mask) \
225 asmlinkage void IRQ_NAME(nr); \
226 asmlinkage void FAST_IRQ_NAME(nr); \
227 asmlinkage void BAD_IRQ_NAME(nr); \
228 __asm__( \
229 "\n"__ALIGN_STR"\n" \
230 SYMBOL_NAME_STR(fast_IRQ) #nr"_interrupt:\n\t" \
231 SYMBOL_NAME_STR(bad_IRQ) #nr"_interrupt:\n\t" \
232 SYMBOL_NAME_STR(IRQ) #nr"_interrupt:\n\t" \
233 "pushl $-"#nr"-2\n\t" \
234 SAVE_ALL \
235 ACK_##chip(mask,(nr&7)) \
236 "movl %esp,%eax\n\t" \
237 "pushl %eax\n\t" \
238 "pushl $" #nr"\n\t" \
239 "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
240 "addl $8,%esp\n\t" \
241 UNBLK_##chip(mask) \
242 "jmp ret_from_intr\n");
244 #endif/* _ASM_IRQ_H */
close