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

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