|
|
1.1 root 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: "inb $0x21,%al\n\t" \
64: "jmp 1f\n" \
65: "1:\tjmp 1f\n" \
66: "1:\torb $" #mask ",%al\n\t" \
67: "outb %al,$0x21\n\t" \
68: "jmp 1f\n" \
69: "1:\tjmp 1f\n" \
70: "1:\tmovb $0x20,%al\n\t" \
71: "outb %al,$0x20\n\t"
72:
73: #define ACK_SECOND(mask) \
74: "inb $0xA1,%al\n\t" \
75: "jmp 1f\n" \
76: "1:\tjmp 1f\n" \
77: "1:\torb $" #mask ",%al\n\t" \
78: "outb %al,$0xA1\n\t" \
79: "jmp 1f\n" \
80: "1:\tjmp 1f\n" \
81: "1:\tmovb $0x20,%al\n\t" \
82: "outb %al,$0xA0\n\t" \
83: "jmp 1f\n" \
84: "1:\tjmp 1f\n" \
85: "1:\toutb %al,$0x20\n\t"
86:
87: #define UNBLK_FIRST(mask) \
88: "inb $0x21,%al\n\t" \
89: "jmp 1f\n" \
90: "1:\tjmp 1f\n" \
91: "1:\tandb $~(" #mask "),%al\n\t" \
92: "outb %al,$0x21\n\t"
93:
94: #define UNBLK_SECOND(mask) \
95: "inb $0xA1,%al\n\t" \
96: "jmp 1f\n" \
97: "1:\tjmp 1f\n" \
98: "1:\tandb $~(" #mask "),%al\n\t" \
99: "outb %al,$0xA1\n\t"
100:
101: #define IRQ_NAME2(nr) nr##_interrupt()
102: #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
103: #define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr)
104: #define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr)
105:
106: #define BUILD_IRQ(chip,nr,mask) \
107: void IRQ_NAME(nr); \
108: void FAST_IRQ_NAME(nr); \
109: void BAD_IRQ_NAME(nr); \
110: __asm__( \
111: "\n.align 2\n" \
112: "_IRQ" #nr "_interrupt:\n\t" \
1.1.1.2 ! root 113: "pushl $-"#nr"-2\n\t" \
1.1 root 114: SAVE_ALL \
115: ACK_##chip(mask) \
116: "sti\n\t" \
117: "movl %esp,%ebx\n\t" \
118: "pushl %ebx\n\t" \
119: "pushl $" #nr "\n\t" \
120: "call _do_IRQ\n\t" \
121: "addl $8,%esp\n\t" \
122: "testl %eax,%eax\n\t" \
123: "jne ret_from_sys_call\n\t" \
124: "cli\n\t" \
125: UNBLK_##chip(mask) \
126: "jmp ret_from_sys_call\n" \
127: "\n.align 2\n" \
128: "_fast_IRQ" #nr "_interrupt:\n\t" \
129: SAVE_MOST \
130: ACK_##chip(mask) \
131: "pushl $" #nr "\n\t" \
132: "call _do_fast_IRQ\n\t" \
133: "addl $4,%esp\n\t" \
134: "testl %eax,%eax\n\t" \
135: "jne 2f\n\t" \
136: "cli\n\t" \
137: UNBLK_##chip(mask) \
138: "\n2:\t" \
139: RESTORE_MOST \
140: "\n\n.align 2\n" \
141: "_bad_IRQ" #nr "_interrupt:\n\t" \
142: "pushl %eax\n\t" \
143: ACK_##chip(mask) \
144: "popl %eax\n\t" \
145: "iret");
146:
147: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.