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

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