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 /*
  63  * The "inb" instructions are not needed, but seem to change the timings
  64  * a bit - without them it seems that the harddisk driver won't work on
  65  * all hardware. Arghh.
  66  */
  67 #define ACK_FIRST(mask) \
  68         "inb $0x21,%al\n\t" \
  69         "jmp 1f\n" \
  70         "1:\tjmp 1f\n" \
  71         "1:\torb $" #mask ",_cache_21\n\t" \
  72         "movb _cache_21,%al\n\t" \
  73         "outb %al,$0x21\n\t" \
  74         "jmp 1f\n" \
  75         "1:\tjmp 1f\n" \
  76         "1:\tmovb $0x20,%al\n\t" \
  77         "outb %al,$0x20\n\t"
  78 
  79 #define ACK_SECOND(mask) \
  80         "inb $0xA1,%al\n\t" \
  81         "jmp 1f\n" \
  82         "1:\tjmp 1f\n" \
  83         "1:\torb $" #mask ",_cache_A1\n\t" \
  84         "movb _cache_A1,%al\n\t" \
  85         "outb %al,$0xA1\n\t" \
  86         "jmp 1f\n" \
  87         "1:\tjmp 1f\n" \
  88         "1:\tmovb $0x20,%al\n\t" \
  89         "outb %al,$0xA0\n\t" \
  90         "jmp 1f\n" \
  91         "1:\tjmp 1f\n" \
  92         "1:\toutb %al,$0x20\n\t"
  93 
  94 #define UNBLK_FIRST(mask) \
  95         "inb $0x21,%al\n\t" \
  96         "jmp 1f\n" \
  97         "1:\tjmp 1f\n" \
  98         "1:\tandb $~(" #mask "),_cache_21\n\t" \
  99         "movb _cache_21,%al\n\t" \
 100         "outb %al,$0x21\n\t"
 101 
 102 #define UNBLK_SECOND(mask) \
 103         "inb $0xA1,%al\n\t" \
 104         "jmp 1f\n" \
 105         "1:\tjmp 1f\n" \
 106         "1:\tandb $~(" #mask "),_cache_A1\n\t" \
 107         "movb _cache_A1,%al\n\t" \
 108         "outb %al,$0xA1\n\t"
 109 
 110 #define IRQ_NAME2(nr) nr##_interrupt()
 111 #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
 112 #define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr)
 113 #define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr)
 114         
 115 #define BUILD_IRQ(chip,nr,mask) \
 116 void IRQ_NAME(nr); \
 117 void FAST_IRQ_NAME(nr); \
 118 void BAD_IRQ_NAME(nr); \
 119 __asm__( \
 120 "\n.align 4\n" \
 121 "_IRQ" #nr "_interrupt:\n\t" \
 122         "pushl $-"#nr"-2\n\t" \
 123         SAVE_ALL \
 124         ACK_##chip(mask) \
 125         "incl _intr_count\n\t"\
 126         "sti\n\t" \
 127         "movl %esp,%ebx\n\t" \
 128         "pushl %ebx\n\t" \
 129         "pushl $" #nr "\n\t" \
 130         "call _do_IRQ\n\t" \
 131         "addl $8,%esp\n\t" \
 132         "cli\n\t" \
 133         UNBLK_##chip(mask) \
 134         "decl _intr_count\n\t" \
 135         "jne ret_from_sys_call\n\t" \
 136         "movl _bh_mask,%eax\n\t" \
 137         "andl _bh_active,%eax\n\t" \
 138         "je ret_from_sys_call\n\t" \
 139         "incl _intr_count\n\t" \
 140         "sti\n\t" \
 141         "bsfl %eax,%eax\n\t" \
 142         "btrl %eax,_bh_active\n\t" \
 143         "pushl %eax\n\t" \
 144         "call _do_bottom_half\n\t" \
 145         "addl $4,%esp\n\t" \
 146         "cli\n\t" \
 147         "decl _intr_count\n\t" \
 148         "jmp ret_from_sys_call\n" \
 149 "\n.align 4\n" \
 150 "_fast_IRQ" #nr "_interrupt:\n\t" \
 151         SAVE_MOST \
 152         ACK_##chip(mask) \
 153         "incl _intr_count\n\t" \
 154         "pushl $" #nr "\n\t" \
 155         "call _do_fast_IRQ\n\t" \
 156         "addl $4,%esp\n\t" \
 157         "cli\n\t" \
 158         UNBLK_##chip(mask) \
 159         "decl _intr_count\n\t" \
 160         "jne 1f\n\t" \
 161         "movl _bh_mask,%eax\n\t" \
 162         "andl _bh_active,%eax\n\t" \
 163         "jne 2f\n" \
 164         "1:\t" \
 165         RESTORE_MOST \
 166         "\n.align 4\n" \
 167         "2:\tincl _intr_count\n\t" \
 168         "sti\n\t" \
 169         "bsfl %eax,%eax\n\t" \
 170         "btrl %eax,_bh_active\n\t" \
 171         "pushl %eax\n\t" \
 172         "call _do_bottom_half\n\t" \
 173         "addl $4,%esp\n\t" \
 174         "cli\n\t" \
 175         "decl _intr_count\n\t" \
 176         RESTORE_MOST \
 177 "\n\n.align 4\n" \
 178 "_bad_IRQ" #nr "_interrupt:\n\t" \
 179         SAVE_MOST \
 180         ACK_##chip(mask) \
 181         RESTORE_MOST);
 182 
 183 #endif

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