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

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