irq.h

Go to the documentation of this file.
00001 #ifndef _ASM_IRQ_H
00002 #define _ASM_IRQ_H
00003 
00004 /**
00005 *
00006 
00007  *      linux/include/asm/irq.h
00008  *
00009  *      (C) 1992, 1993 Linus Torvalds
00010 
00011 
00012 */
00013 
00014 #include <linux/segment.h>
00015 #include <linux/linkage.h>
00016 
00017 extern void disable_irq(unsigned int);
00018 extern void enable_irq(unsigned int);
00019 
00020 #define __STR(x) #x
00021 #define STR(x) __STR(x)
00022  
00023 #define SAVE_ALL \
00024         "cld\n\t" \
00025         "push %gs\n\t" \
00026         "push %fs\n\t" \
00027         "push %es\n\t" \
00028         "push %ds\n\t" \
00029         "pushl %eax\n\t" \
00030         "pushl %ebp\n\t" \
00031         "pushl %edi\n\t" \
00032         "pushl %esi\n\t" \
00033         "pushl %edx\n\t" \
00034         "pushl %ecx\n\t" \
00035         "pushl %ebx\n\t" \
00036         "movl $" STR(KERNEL_DS) ",%edx\n\t" \
00037         "mov %dx,%ds\n\t" \
00038         "mov %dx,%es\n\t" \
00039         "movl $" STR(USER_DS) ",%edx\n\t" \
00040         "mov %dx,%fs\n\t"   \
00041         "movl $0,%edx\n\t"  \
00042         "movl %edx,%db7\n\t"
00043 
00044 /**
00045 *
00046 
00047  * SAVE_MOST/RESTORE_MOST is used for the faster version of IRQ handlers,
00048  * installed by using the SA_INTERRUPT flag. These kinds of IRQ's don't
00049  * call the routines that do signal handling etc on return, and can have
00050  * more relaxed register-saving etc. They are also atomic, and are thus
00051  * suited for small, fast interrupts like the serial lines or the harddisk
00052  * drivers, which don't actually need signal handling etc.
00053  *
00054  * Also note that we actually save only those registers that are used in
00055  * C subroutines (%eax, %edx and %ecx), so if you do something weird,
00056  * you're on your own. The only segments that are saved (not counting the
00057  * automatic stack and code segment handling) are %ds and %es, and they
00058  * point to kernel space. No messing around with %fs here.
00059 
00060 
00061 */
00062 #define SAVE_MOST \
00063         "cld\n\t" \
00064         "push %es\n\t" \
00065         "push %ds\n\t" \
00066         "pushl %eax\n\t" \
00067         "pushl %edx\n\t" \
00068         "pushl %ecx\n\t" \
00069         "movl $" STR(KERNEL_DS) ",%edx\n\t" \
00070         "mov %dx,%ds\n\t" \
00071         "mov %dx,%es\n\t"
00072 
00073 #define RESTORE_MOST \
00074         "popl %ecx\n\t" \
00075         "popl %edx\n\t" \
00076         "popl %eax\n\t" \
00077         "pop %ds\n\t" \
00078         "pop %es\n\t" \
00079         "iret"
00080 
00081 /**
00082 *
00083 
00084  * The "inb" instructions are not needed, but seem to change the timings
00085  * a bit - without them it seems that the harddisk driver won't work on
00086  * all hardware. Arghh.
00087 
00088 
00089 */
00090 #define ACK_FIRST(mask) \
00091         "inb $0x21,%al\n\t" \
00092         "jmp 1f\n" \
00093         "1:\tjmp 1f\n" \
00094         "1:\torb $" #mask ",_cache_21\n\t" \
00095         "movb _cache_21,%al\n\t" \
00096         "outb %al,$0x21\n\t" \
00097         "jmp 1f\n" \
00098         "1:\tjmp 1f\n" \
00099         "1:\tmovb $0x20,%al\n\t" \
00100         "outb %al,$0x20\n\t"
00101 
00102 #define ACK_SECOND(mask) \
00103         "inb $0xA1,%al\n\t" \
00104         "jmp 1f\n" \
00105         "1:\tjmp 1f\n" \
00106         "1:\torb $" #mask ",_cache_A1\n\t" \
00107         "movb _cache_A1,%al\n\t" \
00108         "outb %al,$0xA1\n\t" \
00109         "jmp 1f\n" \
00110         "1:\tjmp 1f\n" \
00111         "1:\tmovb $0x20,%al\n\t" \
00112         "outb %al,$0xA0\n\t" \
00113         "jmp 1f\n" \
00114         "1:\tjmp 1f\n" \
00115         "1:\toutb %al,$0x20\n\t"
00116 
00117 #define UNBLK_FIRST(mask) \
00118         "inb $0x21,%al\n\t" \
00119         "jmp 1f\n" \
00120         "1:\tjmp 1f\n" \
00121         "1:\tandb $~(" #mask "),_cache_21\n\t" \
00122         "movb _cache_21,%al\n\t" \
00123         "outb %al,$0x21\n\t"
00124 
00125 #define UNBLK_SECOND(mask) \
00126         "inb $0xA1,%al\n\t" \
00127         "jmp 1f\n" \
00128         "1:\tjmp 1f\n" \
00129         "1:\tandb $~(" #mask "),_cache_A1\n\t" \
00130         "movb _cache_A1,%al\n\t" \
00131         "outb %al,$0xA1\n\t"
00132 
00133 #define IRQ_NAME2(nr) nr##_interrupt(void)
00134 #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
00135 #define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr)
00136 #define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr)
00137         
00138 #define BUILD_IRQ(chip,nr,mask) \
00139 asmlinkage void IRQ_NAME(nr); \
00140 asmlinkage void FAST_IRQ_NAME(nr); \
00141 asmlinkage void BAD_IRQ_NAME(nr); \
00142 __asm__( \
00143 "\n.align 4\n" \
00144 "_IRQ" #nr "_interrupt:\n\t" \
00145         "pushl $-"#nr"-2\n\t" \
00146         SAVE_ALL \
00147         ACK_##chip(mask) \
00148         "incl _intr_count\n\t"\
00149         "sti\n\t" \
00150         "movl %esp,%ebx\n\t" \
00151         "pushl %ebx\n\t" \
00152         "pushl $" #nr "\n\t" \
00153         "call _do_IRQ\n\t" \
00154         "addl $8,%esp\n\t" \
00155         "cli\n\t" \
00156         UNBLK_##chip(mask) \
00157         "decl _intr_count\n\t" \
00158         "jmp ret_from_sys_call\n" \
00159 "\n.align 4\n" \
00160 "_fast_IRQ" #nr "_interrupt:\n\t" \
00161         SAVE_MOST \
00162         ACK_##chip(mask) \
00163         "incl _intr_count\n\t" \
00164         "pushl $" #nr "\n\t" \
00165         "call _do_fast_IRQ\n\t" \
00166         "addl $4,%esp\n\t" \
00167         "cli\n\t" \
00168         UNBLK_##chip(mask) \
00169         "decl _intr_count\n\t" \
00170         RESTORE_MOST \
00171 "\n\n.align 4\n" \
00172 "_bad_IRQ" #nr "_interrupt:\n\t" \
00173         SAVE_MOST \
00174         ACK_##chip(mask) \
00175         RESTORE_MOST);
00176 
00177 #endif

Generated on Mon May 1 21:46:59 2006 for KernelAPI by  doxygen 1.4.6-5