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> 19 externvoiddisable_irq(unsigned int); 20 externvoidenable_irq(unsigned int); 23 #define STR(x) __STR(x) 37 "movl $" STR(KERNEL_DS)",%edx\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. 62 "movl $" STR(KERNEL_DS)",%edx\n\t" \ 66 #define RESTORE_MOST \ 75 * Some fast irq handlers might want to access saved registers (mostly 79 struct fast_irq_regs
{ 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) \ 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" \ 106 "1:\tmovb $0x20,%al\n\t" \ 109 #define ACK_SECOND(mask,nr) \ 110 "inb $0xA1,%al\n\t" \ 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" \ 118 "1:\tmovb $0x20,%al\n\t" \ 119 "outb %al,$0xA0\n\t" \ 122 "1:\toutb %al,$0x20\n\t" 124 #define UNBLK_FIRST(mask) \ 125 "inb $0x21,%al\n\t" \ 128 "1:\tandb $~(" #mask"),"SYMBOL_NAME_STR(cache_21)"\n\t" \ 129 "movb "SYMBOL_NAME_STR(cache_21)",%al\n\t" \ 132 #define UNBLK_SECOND(mask) \ 133 "inb $0xA1,%al\n\t" \ 136 "1:\tandb $~(" #mask"),"SYMBOL_NAME_STR(cache_A1)"\n\t" \ 137 "movb "SYMBOL_NAME_STR(cache_A1)",%al\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) 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" 156 #define GET_CURRENT \ 157 "movl " SYMBOL_NAME_STR(current_set)",%ebx\n\t" 164 * SMP has a few special interrupts for IPI messages 167 #define BUILD_SMP_INTERRUPT(x) \ 168 asmlinkage void x(void); \ 170 "\n"__ALIGN_STR"\n" \ 171 SYMBOL_NAME_STR(x)":\n\t" \ 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); \ 180 "\n"__ALIGN_STR"\n" \ 181 SYMBOL_NAME_STR(x)":\n\t" \ 184 "movl %esp,%eax\n\t" \ 186 "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \ 188 "jmp ret_from_intr\n"); 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); \ 197 "\n"__ALIGN_STR"\n" \ 198 SYMBOL_NAME_STR(IRQ) #nr"_interrupt:\n\t" \ 199 "pushl $-"#nr"-2\n\t" \ 201 ACK_##chip(mask,(nr&7)) \ 202 "movl %esp,%eax\n\t" \ 204 "pushl $" #nr"\n\t" \ 205 "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \ 208 "jmp ret_from_intr\n" \ 209 "\n"__ALIGN_STR"\n" \ 210 SYMBOL_NAME_STR(fast_IRQ) #nr"_interrupt:\n\t" \ 212 ACK_##chip(mask,(nr&7)) \ 213 "pushl $" #nr"\n\t" \ 214 "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \ 218 "\n"__ALIGN_STR"\n" \ 219 SYMBOL_NAME_STR(bad_IRQ) #nr"_interrupt:\n\t" \ 221 ACK_##chip(mask,(nr&7)) \ 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); \ 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" \ 235 ACK_##chip(mask,(nr&7)) \ 236 "movl %esp,%eax\n\t" \ 238 "pushl $" #nr"\n\t" \ 239 "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \ 242 "jmp ret_from_intr\n"); 244 #endif/* _ASM_IRQ_H */