root/include/asm/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 
  10 #include <linux/segment.h>
  11 #include <linux/linkage.h>
  12 
  13 extern void disable_irq(unsigned int);
  14 extern void enable_irq(unsigned int);
  15 
  16 #define __STR(x) #x
  17 #define STR(x) __STR(x)
  18  
  19 #define SAVE_ALL \
  20         "cld\n\t" \
  21         "push %gs\n\t" \
  22         "push %fs\n\t" \
  23         "push %es\n\t" \
  24         "push %ds\n\t" \
  25         "pushl %eax\n\t" \
  26         "pushl %ebp\n\t" \
  27         "pushl %edi\n\t" \
  28         "pushl %esi\n\t" \
  29         "pushl %edx\n\t" \
  30         "pushl %ecx\n\t" \
  31         "pushl %ebx\n\t" \
  32         "movl $" STR(KERNEL_DS) ",%edx\n\t" \
  33         "mov %dx,%ds\n\t" \
  34         "mov %dx,%es\n\t" \
  35         "movl $" STR(USER_DS) ",%edx\n\t" \
  36         "mov %dx,%fs\n\t"   \
  37         "movl $0,%edx\n\t"  \
  38         "movl %edx,%db7\n"
  39 
  40 /*
  41  * SAVE_MOST/RESTORE_MOST is used for the faster version of IRQ handlers,
  42  * installed by using the SA_INTERRUPT flag. These kinds of IRQ's don't
  43  * call the routines that do signal handling etc on return, and can have
  44  * more relaxed register-saving etc. They are also atomic, and are thus
  45  * suited for small, fast interrupts like the serial lines or the harddisk
  46  * drivers, which don't actually need signal handling etc.
  47  *
  48  * Also note that we actually save only those registers that are used in
  49  * C subroutines (%eax, %edx and %ecx), so if you do something weird,
  50  * you're on your own. The only segments that are saved (not counting the
  51  * automatic stack and code segment handling) are %ds and %es, and they
  52  * point to kernel space. No messing around with %fs here.
  53  */
  54 #define SAVE_MOST \
  55         "cld\n\t" \
  56         "push %es\n\t" \
  57         "push %ds\n\t" \
  58         "pushl %eax\n\t" \
  59         "pushl %edx\n\t" \
  60         "pushl %ecx\n\t" \
  61         "movl $" STR(KERNEL_DS) ",%edx\n\t" \
  62         "mov %dx,%ds\n\t" \
  63         "mov %dx,%es\n\t"
  64 
  65 #define RESTORE_MOST \
  66         "popl %ecx\n\t" \
  67         "popl %edx\n\t" \
  68         "popl %eax\n\t" \
  69         "pop %ds\n\t" \
  70         "pop %es\n\t" \
  71         "iret"
  72 
  73 /*
  74  * The "inb" instructions are not needed, but seem to change the timings
  75  * a bit - without them it seems that the harddisk driver won't work on
  76  * all hardware. Arghh.
  77  */
  78 #define ACK_FIRST(mask) \
  79         "inb $0x21,%al\n\t" \
  80         "jmp 1f\n" \
  81         "1:\tjmp 1f\n" \
  82         "1:\torb $" #mask ",_cache_21\n\t" \
  83         "movb _cache_21,%al\n\t" \
  84         "outb %al,$0x21\n\t" \
  85         "jmp 1f\n" \
  86         "1:\tjmp 1f\n" \
  87         "1:\tmovb $0x20,%al\n\t" \
  88         "outb %al,$0x20\n\t"
  89 
  90 #define ACK_SECOND(mask) \
  91         "inb $0xA1,%al\n\t" \
  92         "jmp 1f\n" \
  93         "1:\tjmp 1f\n" \
  94         "1:\torb $" #mask ",_cache_A1\n\t" \
  95         "movb _cache_A1,%al\n\t" \
  96         "outb %al,$0xA1\n\t" \
  97         "jmp 1f\n" \
  98         "1:\tjmp 1f\n" \
  99         "1:\tmovb $0x20,%al\n\t" \
 100         "outb %al,$0xA0\n\t" \
 101         "jmp 1f\n" \
 102         "1:\tjmp 1f\n" \
 103         "1:\toutb %al,$0x20\n\t"
 104 
 105 #define UNBLK_FIRST(mask) \
 106         "inb $0x21,%al\n\t" \
 107         "jmp 1f\n" \
 108         "1:\tjmp 1f\n" \
 109         "1:\tandb $~(" #mask "),_cache_21\n\t" \
 110         "movb _cache_21,%al\n\t" \
 111         "outb %al,$0x21\n\t"
 112 
 113 #define UNBLK_SECOND(mask) \
 114         "inb $0xA1,%al\n\t" \
 115         "jmp 1f\n" \
 116         "1:\tjmp 1f\n" \
 117         "1:\tandb $~(" #mask "),_cache_A1\n\t" \
 118         "movb _cache_A1,%al\n\t" \
 119         "outb %al,$0xA1\n\t"
 120 
 121 #define IRQ_NAME2(nr) nr##_interrupt(void)
 122 #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
 123 #define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr)
 124 #define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr)
 125         
 126 #define BUILD_IRQ(chip,nr,mask) \
 127 asmlinkage void IRQ_NAME(nr); \
 128 asmlinkage void FAST_IRQ_NAME(nr); \
 129 asmlinkage void BAD_IRQ_NAME(nr); \
 130 __asm__( \
 131 "\n.align 4\n" \
 132 "_IRQ" #nr "_interrupt:\n\t" \
 133         "pushl $-"#nr"-2\n\t" \
 134         SAVE_ALL \
 135         ACK_##chip(mask) \
 136         "incl _intr_count\n\t"\
 137         "sti\n\t" \
 138         "movl %esp,%ebx\n\t" \
 139         "pushl %ebx\n\t" \
 140         "pushl $" #nr "\n\t" \
 141         "call _do_IRQ\n\t" \
 142         "addl $8,%esp\n\t" \
 143         "cli\n\t" \
 144         UNBLK_##chip(mask) \
 145         "decl _intr_count\n\t" \
 146         "jmp ret_from_sys_call\n" \
 147 "\n.align 4\n" \
 148 "_fast_IRQ" #nr "_interrupt:\n\t" \
 149         SAVE_MOST \
 150         ACK_##chip(mask) \
 151         "incl _intr_count\n\t" \
 152         "pushl $" #nr "\n\t" \
 153         "call _do_fast_IRQ\n\t" \
 154         "addl $4,%esp\n\t" \
 155         "cli\n\t" \
 156         UNBLK_##chip(mask) \
 157         "decl _intr_count\n\t" \
 158         RESTORE_MOST \
 159 "\n\n.align 4\n" \
 160 "_bad_IRQ" #nr "_interrupt:\n\t" \
 161         SAVE_MOST \
 162         ACK_##chip(mask) \
 163         RESTORE_MOST);
 164 
 165 #endif

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