root/include/asm-i386/irq.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


   1 #ifndef _ASM_IRQ_H
   2 #define _ASM_IRQ_H
   3 
   4 /*
   5  *      linux/include/asm/irq.h
   6  *
   7  *      (C) 1992, 1993 Linus Torvalds
   8  *
   9  *      IRQ/IPI changes taken from work by Thomas Radke <tomsoft@informatik.tu-chemnitz.de>
  10  */
  11 
  12 #include <linux/linkage.h>
  13 #include <asm/segment.h>
  14 
  15 #define NR_IRQS 16
  16 
  17 extern void disable_irq(unsigned int);
  18 extern void enable_irq(unsigned int);
  19 
  20 #define __STR(x) #x
  21 #define STR(x) __STR(x)
  22  
  23 #define SAVE_ALL \
  24         "cld\n\t" \
  25         "push %gs\n\t" \
  26         "push %fs\n\t" \
  27         "push %es\n\t" \
  28         "push %ds\n\t" \
  29         "pushl %eax\n\t" \
  30         "pushl %ebp\n\t" \
  31         "pushl %edi\n\t" \
  32         "pushl %esi\n\t" \
  33         "pushl %edx\n\t" \
  34         "pushl %ecx\n\t" \
  35         "pushl %ebx\n\t" \
  36         "movl $" STR(KERNEL_DS) ",%edx\n\t" \
  37         "mov %dx,%ds\n\t" \
  38         "mov %dx,%es\n\t" \
  39         "movl $" STR(USER_DS) ",%edx\n\t" \
  40         "mov %dx,%fs\n\t"   \
  41         "movl $0,%edx\n\t"  \
  42         "movl %edx,%db7\n\t"
  43 
  44 /*
  45  * SAVE_MOST/RESTORE_MOST is used for the faster version of IRQ handlers,
  46  * installed by using the SA_INTERRUPT flag. These kinds of IRQ's don't
  47  * call the routines that do signal handling etc on return, and can have
  48  * more relaxed register-saving etc. They are also atomic, and are thus
  49  * suited for small, fast interrupts like the serial lines or the harddisk
  50  * drivers, which don't actually need signal handling etc.
  51  *
  52  * Also note that we actually save only those registers that are used in
  53  * C subroutines (%eax, %edx and %ecx), so if you do something weird,
  54  * you're on your own. The only segments that are saved (not counting the
  55  * automatic stack and code segment handling) are %ds and %es, and they
  56  * point to kernel space. No messing around with %fs here.
  57  */
  58 #define SAVE_MOST \
  59         "cld\n\t" \
  60         "push %es\n\t" \
  61         "push %ds\n\t" \
  62         "pushl %eax\n\t" \
  63         "pushl %edx\n\t" \
  64         "pushl %ecx\n\t" \
  65         "movl $" STR(KERNEL_DS) ",%edx\n\t" \
  66         "mov %dx,%ds\n\t" \
  67         "mov %dx,%es\n\t"
  68 
  69 #define RESTORE_MOST \
  70         "popl %ecx\n\t" \
  71         "popl %edx\n\t" \
  72         "popl %eax\n\t" \
  73         "pop %ds\n\t" \
  74         "pop %es\n\t" \
  75         "iret"
  76 
  77 /*
  78  * The "inb" instructions are not needed, but seem to change the timings
  79  * a bit - without them it seems that the harddisk driver won't work on
  80  * all hardware. Arghh.
  81  */
  82 #define ACK_FIRST(mask) \
  83         "inb $0x21,%al\n\t" \
  84         "jmp 1f\n" \
  85         "1:\tjmp 1f\n" \
  86         "1:\torb $" #mask ","SYMBOL_NAME_STR(cache_21)"\n\t" \
  87         "movb "SYMBOL_NAME_STR(cache_21)",%al\n\t" \
  88         "outb %al,$0x21\n\t" \
  89         "jmp 1f\n" \
  90         "1:\tjmp 1f\n" \
  91         "1:\tmovb $0x20,%al\n\t" \
  92         "outb %al,$0x20\n\t"
  93 
  94 #define ACK_SECOND(mask) \
  95         "inb $0xA1,%al\n\t" \
  96         "jmp 1f\n" \
  97         "1:\tjmp 1f\n" \
  98         "1:\torb $" #mask ","SYMBOL_NAME_STR(cache_A1)"\n\t" \
  99         "movb "SYMBOL_NAME_STR(cache_A1)",%al\n\t" \
 100         "outb %al,$0xA1\n\t" \
 101         "jmp 1f\n" \
 102         "1:\tjmp 1f\n" \
 103         "1:\tmovb $0x20,%al\n\t" \
 104         "outb %al,$0xA0\n\t" \
 105         "jmp 1f\n" \
 106         "1:\tjmp 1f\n" \
 107         "1:\toutb %al,$0x20\n\t"
 108 
 109 #define UNBLK_FIRST(mask) \
 110         "inb $0x21,%al\n\t" \
 111         "jmp 1f\n" \
 112         "1:\tjmp 1f\n" \
 113         "1:\tandb $~(" #mask "),"SYMBOL_NAME_STR(cache_21)"\n\t" \
 114         "movb "SYMBOL_NAME_STR(cache_21)",%al\n\t" \
 115         "outb %al,$0x21\n\t"
 116 
 117 #define UNBLK_SECOND(mask) \
 118         "inb $0xA1,%al\n\t" \
 119         "jmp 1f\n" \
 120         "1:\tjmp 1f\n" \
 121         "1:\tandb $~(" #mask "),"SYMBOL_NAME_STR(cache_A1)"\n\t" \
 122         "movb "SYMBOL_NAME_STR(cache_A1)",%al\n\t" \
 123         "outb %al,$0xA1\n\t"
 124 
 125 #define IRQ_NAME2(nr) nr##_interrupt(void)
 126 #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
 127 #define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr)
 128 #define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr)
 129 
 130 #ifdef  __SMP__
 131 
 132 #define GET_PROCESSOR_ID \
 133         "movl "SYMBOL_NAME_STR(apic_reg)", %edx\n\t" \
 134         "movl 32(%edx), %eax\n\t" \
 135         "shrl $24,%eax\n\t" \
 136         "andb $0x0F,%al\n"
 137         
 138 #define ENTER_KERNEL \
 139         "pushl %eax\n\t" \
 140         "pushl %edx\n\t" \
 141         "pushfl\n\t" \
 142         "cli\n\t" \
 143         GET_PROCESSOR_ID \
 144         "1: " \
 145         "lock\n\t" \
 146         "btsl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \
 147         "jnc 3f\n\t" \
 148         "cmpb "SYMBOL_NAME_STR(active_kernel_processor)", %al\n\t" \
 149         "je 4f\n\t" \
 150         "2: " \
 151         "incl "SYMBOL_NAME_STR(smp_spins)"\n\t" \
 152         "btl %al, "SYMBOL_NAME_STR(smp_invalidate_needed)"\n\t" \
 153         "jnc 5f\n\t" \
 154         "lock\n\t" \
 155         "btrl %al, "SYMBOL_NAME_STR(smp_invalidate_needed)"\n\t" \
 156         "jnc 5f\n\t" \
 157         "movl %cr3,%edx\n\t" \
 158         "movl %edx,%cr3\n" \
 159         "5: btl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \
 160         "jc 2b\n\t" \
 161         "jmp 1b\n\t" \
 162         "3: " \
 163         "movb %al, "SYMBOL_NAME_STR(active_kernel_processor)"\n\t" \
 164         "4: " \
 165         "incl "SYMBOL_NAME_STR(kernel_counter)"\n\t" \
 166         "popfl\n\t" \
 167         "popl %edx\n\t" \
 168         "popl %eax\n\t"
 169 
 170 #define LEAVE_KERNEL \
 171         "pushfl\n\t" \
 172         "cli\n\t" \
 173         "decl "SYMBOL_NAME_STR(kernel_counter)"\n\t" \
 174         "jnz 1f\n\t" \
 175         "movb $" STR (NO_PROC_ID) ", "SYMBOL_NAME_STR(active_kernel_processor)"\n\t" \
 176         "lock\n\t" \
 177         "btrl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \
 178         "1: " \
 179         "popfl\n\t"
 180         
 181         
 182 /*
 183  *      the syscall count inc is a gross hack because ret_from_syscall is used by both irq and
 184  *      syscall return paths (urghh).
 185  */
 186  
 187 #define BUILD_IRQ(chip,nr,mask) \
 188 asmlinkage void IRQ_NAME(nr); \
 189 asmlinkage void FAST_IRQ_NAME(nr); \
 190 asmlinkage void BAD_IRQ_NAME(nr); \
 191 __asm__( \
 192 "\n"__ALIGN_STR"\n" \
 193 SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
 194         "pushl $-"#nr"-2\n\t" \
 195         SAVE_ALL \
 196         ENTER_KERNEL \
 197         ACK_##chip(mask) \
 198         "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
 199         "sti\n\t" \
 200         "movl %esp,%ebx\n\t" \
 201         "pushl %ebx\n\t" \
 202         "pushl $" #nr "\n\t" \
 203         "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
 204         "addl $8,%esp\n\t" \
 205         "cli\n\t" \
 206         UNBLK_##chip(mask) \
 207         "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
 208         "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \
 209         "jmp ret_from_sys_call\n" \
 210 "\n"__ALIGN_STR"\n" \
 211 SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
 212         SAVE_MOST \
 213         ENTER_KERNEL \
 214         ACK_##chip(mask) \
 215         "incl "SYMBOL_NAME_STR(intr_count)"\n\t" \
 216         "pushl $" #nr "\n\t" \
 217         "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \
 218         "addl $4,%esp\n\t" \
 219         "cli\n\t" \
 220         UNBLK_##chip(mask) \
 221         "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
 222         LEAVE_KERNEL \
 223         RESTORE_MOST \
 224 "\n"__ALIGN_STR"\n" \
 225 SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
 226         SAVE_MOST \
 227         ENTER_KERNEL \
 228         ACK_##chip(mask) \
 229         LEAVE_KERNEL \
 230         RESTORE_MOST);
 231         
 232         
 233 /*
 234  *      Message pass must be a fast IRQ..
 235  */
 236 
 237 #define BUILD_MSGIRQ(chip,nr,mask) \
 238 asmlinkage void IRQ_NAME(nr); \
 239 asmlinkage void FAST_IRQ_NAME(nr); \
 240 asmlinkage void BAD_IRQ_NAME(nr); \
 241 __asm__( \
 242 "\n"__ALIGN_STR"\n" \
 243 SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
 244         "pushl $-"#nr"-2\n\t" \
 245         SAVE_ALL \
 246         ENTER_KERNEL \
 247         ACK_##chip(mask) \
 248         "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
 249         "sti\n\t" \
 250         "movl %esp,%ebx\n\t" \
 251         "pushl %ebx\n\t" \
 252         "pushl $" #nr "\n\t" \
 253         "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
 254         "addl $8,%esp\n\t" \
 255         "cli\n\t" \
 256         UNBLK_##chip(mask) \
 257         "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
 258         "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \
 259         "jmp ret_from_sys_call\n" \
 260 "\n"__ALIGN_STR"\n" \
 261 SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
 262         SAVE_MOST \
 263         ACK_##chip(mask) \
 264         "incl "SYMBOL_NAME_STR(ipi_count)"\n\t" \
 265         "pushl $" #nr "\n\t" \
 266         "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \
 267         "addl $4,%esp\n\t" \
 268         "cli\n\t" \
 269         UNBLK_##chip(mask) \
 270         RESTORE_MOST \
 271 "\n"__ALIGN_STR"\n" \
 272 SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
 273         SAVE_MOST \
 274         ACK_##chip(mask) \
 275         RESTORE_MOST);
 276 
 277 #define BUILD_RESCHEDIRQ(nr) \
 278 asmlinkage void IRQ_NAME(nr); \
 279 __asm__( \
 280 "\n"__ALIGN_STR"\n" \
 281 SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
 282         "pushl $-"#nr"-2\n\t" \
 283         SAVE_ALL \
 284         ENTER_KERNEL \
 285         "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
 286         "sti\n\t" \
 287         "movl %esp,%ebx\n\t" \
 288         "pushl %ebx\n\t" \
 289         "pushl $" #nr "\n\t" \
 290         "call "SYMBOL_NAME_STR(smp_reschedule_irq)"\n\t" \
 291         "addl $8,%esp\n\t" \
 292         "cli\n\t" \
 293         "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
 294         "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \
 295         "jmp ret_from_sys_call\n");
 296 #else
 297         
 298 #define BUILD_IRQ(chip,nr,mask) \
 299 asmlinkage void IRQ_NAME(nr); \
 300 asmlinkage void FAST_IRQ_NAME(nr); \
 301 asmlinkage void BAD_IRQ_NAME(nr); \
 302 __asm__( \
 303 "\n"__ALIGN_STR"\n" \
 304 SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
 305         "pushl $-"#nr"-2\n\t" \
 306         SAVE_ALL \
 307         ACK_##chip(mask) \
 308         "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
 309         "sti\n\t" \
 310         "movl %esp,%ebx\n\t" \
 311         "pushl %ebx\n\t" \
 312         "pushl $" #nr "\n\t" \
 313         "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
 314         "addl $8,%esp\n\t" \
 315         "cli\n\t" \
 316         UNBLK_##chip(mask) \
 317         "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
 318         "jmp ret_from_sys_call\n" \
 319 "\n"__ALIGN_STR"\n" \
 320 SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
 321         SAVE_MOST \
 322         ACK_##chip(mask) \
 323         "incl "SYMBOL_NAME_STR(intr_count)"\n\t" \
 324         "pushl $" #nr "\n\t" \
 325         "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \
 326         "addl $4,%esp\n\t" \
 327         "cli\n\t" \
 328         UNBLK_##chip(mask) \
 329         "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
 330         RESTORE_MOST \
 331 "\n"__ALIGN_STR"\n" \
 332 SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
 333         SAVE_MOST \
 334         ACK_##chip(mask) \
 335         RESTORE_MOST);
 336 
 337 #endif
 338 #endif

/* [previous][next][first][last][top][bottom][index][help] */