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

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