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 #ifndef __SMP_PROF__
 133 #define SMP_PROF_INT_SPINS 
 134 #define SMP_PROF_IPI_CNT 
 135 #else
 136 #define SMP_PROF_INT_SPINS "incl "SYMBOL_NAME_STR(smp_spins)"(,%eax,4)\n\t"
 137 #define SMP_PROF_IPI_CNT "incl "SYMBOL_NAME_STR(ipi_count)"\n\t" 
 138 #endif
 139 
 140 #define GET_PROCESSOR_ID \
 141         "movl "SYMBOL_NAME_STR(apic_reg)", %edx\n\t" \
 142         "movl 32(%edx), %eax\n\t" \
 143         "shrl $24,%eax\n\t" \
 144         "andb $0x0F,%al\n"
 145         
 146 #define ENTER_KERNEL \
 147         "pushl %eax\n\t" \
 148         "pushl %edx\n\t" \
 149         "pushfl\n\t" \
 150         "cli\n\t" \
 151         GET_PROCESSOR_ID \
 152         "1: " \
 153         "lock\n\t" \
 154         "btsl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \
 155         "jnc 3f\n\t" \
 156         "cmpb "SYMBOL_NAME_STR(active_kernel_processor)", %al\n\t" \
 157         "je 4f\n\t" \
 158         "2: " \
 159         SMP_PROF_INT_SPINS \
 160         "btl %al, "SYMBOL_NAME_STR(smp_invalidate_needed)"\n\t" \
 161         "jnc 5f\n\t" \
 162         "lock\n\t" \
 163         "btrl %al, "SYMBOL_NAME_STR(smp_invalidate_needed)"\n\t" \
 164         "jnc 5f\n\t" \
 165         "movl %cr3,%edx\n\t" \
 166         "movl %edx,%cr3\n" \
 167         "5: btl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \
 168         "jc 2b\n\t" \
 169         "jmp 1b\n\t" \
 170         "3: " \
 171         "movb %al, "SYMBOL_NAME_STR(active_kernel_processor)"\n\t" \
 172         "4: " \
 173         "incl "SYMBOL_NAME_STR(kernel_counter)"\n\t" \
 174         "popfl\n\t" \
 175         "popl %edx\n\t" \
 176         "popl %eax\n\t"
 177 
 178 #define LEAVE_KERNEL \
 179         "pushfl\n\t" \
 180         "cli\n\t" \
 181         "decl "SYMBOL_NAME_STR(kernel_counter)"\n\t" \
 182         "jnz 1f\n\t" \
 183         "movb $" STR (NO_PROC_ID) ", "SYMBOL_NAME_STR(active_kernel_processor)"\n\t" \
 184         "lock\n\t" \
 185         "btrl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \
 186         "1: " \
 187         "popfl\n\t"
 188         
 189         
 190 /*
 191  *      the syscall count inc is a gross hack because ret_from_syscall is used by both irq and
 192  *      syscall return paths (urghh).
 193  */
 194  
 195 #define BUILD_IRQ(chip,nr,mask) \
 196 asmlinkage void IRQ_NAME(nr); \
 197 asmlinkage void FAST_IRQ_NAME(nr); \
 198 asmlinkage void BAD_IRQ_NAME(nr); \
 199 __asm__( \
 200 "\n"__ALIGN_STR"\n" \
 201 SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
 202         "pushl $-"#nr"-2\n\t" \
 203         SAVE_ALL \
 204         ENTER_KERNEL \
 205         ACK_##chip(mask) \
 206         "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
 207         "sti\n\t" \
 208         "movl %esp,%ebx\n\t" \
 209         "pushl %ebx\n\t" \
 210         "pushl $" #nr "\n\t" \
 211         "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
 212         "addl $8,%esp\n\t" \
 213         "cli\n\t" \
 214         UNBLK_##chip(mask) \
 215         "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
 216         "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \
 217         "jmp ret_from_sys_call\n" \
 218 "\n"__ALIGN_STR"\n" \
 219 SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
 220         SAVE_MOST \
 221         ENTER_KERNEL \
 222         ACK_##chip(mask) \
 223         "incl "SYMBOL_NAME_STR(intr_count)"\n\t" \
 224         "pushl $" #nr "\n\t" \
 225         "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \
 226         "addl $4,%esp\n\t" \
 227         "cli\n\t" \
 228         UNBLK_##chip(mask) \
 229         "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
 230         LEAVE_KERNEL \
 231         RESTORE_MOST \
 232 "\n"__ALIGN_STR"\n" \
 233 SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
 234         SAVE_MOST \
 235         ENTER_KERNEL \
 236         ACK_##chip(mask) \
 237         LEAVE_KERNEL \
 238         RESTORE_MOST);
 239         
 240         
 241 /*
 242  *      Message pass must be a fast IRQ..
 243  */
 244 
 245 #define BUILD_MSGIRQ(chip,nr,mask) \
 246 asmlinkage void IRQ_NAME(nr); \
 247 asmlinkage void FAST_IRQ_NAME(nr); \
 248 asmlinkage void BAD_IRQ_NAME(nr); \
 249 __asm__( \
 250 "\n"__ALIGN_STR"\n" \
 251 SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
 252         "pushl $-"#nr"-2\n\t" \
 253         SAVE_ALL \
 254         ENTER_KERNEL \
 255         ACK_##chip(mask) \
 256         "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
 257         "sti\n\t" \
 258         "movl %esp,%ebx\n\t" \
 259         "pushl %ebx\n\t" \
 260         "pushl $" #nr "\n\t" \
 261         "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
 262         "addl $8,%esp\n\t" \
 263         "cli\n\t" \
 264         UNBLK_##chip(mask) \
 265         "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
 266         "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \
 267         "jmp ret_from_sys_call\n" \
 268 "\n"__ALIGN_STR"\n" \
 269 SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
 270         SAVE_MOST \
 271         ACK_##chip(mask) \
 272         SMP_PROF_IPI_CNT \
 273         "pushl $" #nr "\n\t" \
 274         "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \
 275         "addl $4,%esp\n\t" \
 276         "cli\n\t" \
 277         UNBLK_##chip(mask) \
 278         RESTORE_MOST \
 279 "\n"__ALIGN_STR"\n" \
 280 SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
 281         SAVE_MOST \
 282         ACK_##chip(mask) \
 283         RESTORE_MOST);
 284 
 285 #define BUILD_RESCHEDIRQ(nr) \
 286 asmlinkage void IRQ_NAME(nr); \
 287 __asm__( \
 288 "\n"__ALIGN_STR"\n" \
 289 SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
 290         "pushl $-"#nr"-2\n\t" \
 291         SAVE_ALL \
 292         ENTER_KERNEL \
 293         "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
 294         "sti\n\t" \
 295         "movl %esp,%ebx\n\t" \
 296         "pushl %ebx\n\t" \
 297         "pushl $" #nr "\n\t" \
 298         "call "SYMBOL_NAME_STR(smp_reschedule_irq)"\n\t" \
 299         "addl $8,%esp\n\t" \
 300         "cli\n\t" \
 301         "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
 302         "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \
 303         "jmp ret_from_sys_call\n");
 304 #else
 305         
 306 #define BUILD_IRQ(chip,nr,mask) \
 307 asmlinkage void IRQ_NAME(nr); \
 308 asmlinkage void FAST_IRQ_NAME(nr); \
 309 asmlinkage void BAD_IRQ_NAME(nr); \
 310 __asm__( \
 311 "\n"__ALIGN_STR"\n" \
 312 SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
 313         "pushl $-"#nr"-2\n\t" \
 314         SAVE_ALL \
 315         ACK_##chip(mask) \
 316         "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
 317         "sti\n\t" \
 318         "movl %esp,%ebx\n\t" \
 319         "pushl %ebx\n\t" \
 320         "pushl $" #nr "\n\t" \
 321         "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
 322         "addl $8,%esp\n\t" \
 323         "cli\n\t" \
 324         UNBLK_##chip(mask) \
 325         "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
 326         "jmp ret_from_sys_call\n" \
 327 "\n"__ALIGN_STR"\n" \
 328 SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
 329         SAVE_MOST \
 330         ACK_##chip(mask) \
 331         "incl "SYMBOL_NAME_STR(intr_count)"\n\t" \
 332         "pushl $" #nr "\n\t" \
 333         "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \
 334         "addl $4,%esp\n\t" \
 335         "cli\n\t" \
 336         UNBLK_##chip(mask) \
 337         "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
 338         RESTORE_MOST \
 339 "\n"__ALIGN_STR"\n" \
 340 SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
 341         SAVE_MOST \
 342         ACK_##chip(mask) \
 343         RESTORE_MOST);
 344 
 345 #endif
 346 #endif

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