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

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