Import 2.3.12pre3
[davej-history.git] / arch / i386 / kernel / irq.h
bloba6ee1948de739c2172b2c24329e0fe6404110384
1 #ifndef __irq_h
2 #define __irq_h
4 #include <asm/irq.h>
6 /*
7 * Interrupt controller descriptor. This is all we need
8 * to describe about the low-level hardware.
9 */
10 struct hw_interrupt_type {
11 const char * typename;
12 void (*startup)(unsigned int irq);
13 void (*shutdown)(unsigned int irq);
14 void (*handle)(unsigned int irq, struct pt_regs * regs);
15 void (*enable)(unsigned int irq);
16 void (*disable)(unsigned int irq);
19 extern struct hw_interrupt_type no_irq_type;
22 * IRQ line status.
24 #define IRQ_INPROGRESS 1 /* IRQ handler active - do not enter! */
25 #define IRQ_DISABLED 2 /* IRQ disabled - do not enter! */
26 #define IRQ_PENDING 4 /* IRQ pending - replay on enable */
27 #define IRQ_REPLAY 8 /* IRQ has been replayed but not acked yet */
28 #define IRQ_AUTODETECT 16 /* IRQ is being autodetected */
29 #define IRQ_WAITING 32 /* IRQ not yet seen - for autodetection */
32 * This is the "IRQ descriptor", which contains various information
33 * about the irq, including what kind of hardware handling it has,
34 * whether it is disabled etc etc.
36 * Pad this out to 32 bytes for cache and indexing reasons.
38 typedef struct {
39 unsigned int status; /* IRQ status - IRQ_INPROGRESS, IRQ_DISABLED */
40 struct hw_interrupt_type *handler; /* handle/enable/disable functions */
41 struct irqaction *action; /* IRQ action list */
42 unsigned int depth; /* Disable depth for nested irq disables */
43 } irq_desc_t;
46 * IDT vectors usable for external interrupt sources start
47 * at 0x20:
49 #define FIRST_EXTERNAL_VECTOR 0x20
51 #define SYSCALL_VECTOR 0x80
54 * Vectors 0x20-0x2f are used for ISA interrupts.
58 * Special IRQ vectors used by the SMP architecture:
60 * (some of the following vectors are 'rare', they are merged
61 * into a single vector (FUNCTION_VECTOR) to save vector space.
62 * TLB, reschedule and local APIC vectors are performance-critical.)
64 #define RESCHEDULE_VECTOR 0x30
65 #define INVALIDATE_TLB_VECTOR 0x31
66 #define STOP_CPU_VECTOR 0x40
67 #define LOCAL_TIMER_VECTOR 0x41
68 #define CALL_FUNCTION_VECTOR 0x50
71 * First APIC vector available to drivers: (vectors 0x51-0xfe)
73 #define IRQ0_TRAP_VECTOR 0x51
76 * This IRQ should never happen, but we print a message nevertheless.
78 #define SPURIOUS_APIC_VECTOR 0xff
80 extern irq_desc_t irq_desc[NR_IRQS];
81 extern int irq_vector[NR_IRQS];
82 #define IO_APIC_VECTOR(irq) irq_vector[irq]
84 extern void init_IRQ_SMP(void);
85 extern int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
86 extern int setup_x86_irq(unsigned int, struct irqaction *);
89 * Various low-level irq details needed by irq.c, process.c,
90 * time.c, io_apic.c and smp.c
92 * Interrupt entry/exit code at both C and assembly level
95 extern void no_action(int cpl, void *dev_id, struct pt_regs *regs);
96 extern void mask_irq(unsigned int irq);
97 extern void unmask_irq(unsigned int irq);
98 extern void disable_8259A_irq(unsigned int irq);
99 extern int i8259A_irq_pending(unsigned int irq);
100 extern void ack_APIC_irq(void);
101 extern void FASTCALL(send_IPI_self(int vector));
102 extern void init_VISWS_APIC_irqs(void);
103 extern void setup_IO_APIC(void);
104 extern int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn);
105 extern void make_8259A_irq(unsigned int irq);
106 extern void send_IPI(int dest, int vector);
107 extern void init_pic_mode(void);
108 extern void print_IO_APIC(void);
110 extern unsigned long io_apic_irqs;
112 extern char _stext, _etext;
114 #define MAX_IRQ_SOURCES 128
115 #define MAX_MP_BUSSES 32
116 enum mp_bustype {
117 MP_BUS_ISA,
118 MP_BUS_EISA,
119 MP_BUS_PCI
121 extern int mp_bus_id_to_type [MAX_MP_BUSSES];
122 extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES];
124 extern spinlock_t irq_controller_lock;
126 #ifdef __SMP__
128 #include <asm/atomic.h>
130 static inline void irq_enter(int cpu, unsigned int irq)
132 hardirq_enter(cpu);
133 while (test_bit(0,&global_irq_lock)) {
134 /* nothing */;
138 static inline void irq_exit(int cpu, unsigned int irq)
140 hardirq_exit(cpu);
143 #define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs))
145 #else
147 #define irq_enter(cpu, irq) (++local_irq_count[cpu])
148 #define irq_exit(cpu, irq) (--local_irq_count[cpu])
150 #define IO_APIC_IRQ(x) (0)
152 #endif
154 #define __STR(x) #x
155 #define STR(x) __STR(x)
157 #define SAVE_ALL \
158 "cld\n\t" \
159 "pushl %es\n\t" \
160 "pushl %ds\n\t" \
161 "pushl %eax\n\t" \
162 "pushl %ebp\n\t" \
163 "pushl %edi\n\t" \
164 "pushl %esi\n\t" \
165 "pushl %edx\n\t" \
166 "pushl %ecx\n\t" \
167 "pushl %ebx\n\t" \
168 "movl $" STR(__KERNEL_DS) ",%edx\n\t" \
169 "movl %dx,%ds\n\t" \
170 "movl %dx,%es\n\t"
172 #define IRQ_NAME2(nr) nr##_interrupt(void)
173 #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
175 #define GET_CURRENT \
176 "movl %esp, %ebx\n\t" \
177 "andl $-8192, %ebx\n\t"
179 #ifdef __SMP__
182 * SMP has a few special interrupts for IPI messages
185 #define BUILD_SMP_INTERRUPT(x) \
186 asmlinkage void x(void); \
187 __asm__( \
188 "\n"__ALIGN_STR"\n" \
189 SYMBOL_NAME_STR(x) ":\n\t" \
190 "pushl $-1\n\t" \
191 SAVE_ALL \
192 "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
193 "jmp ret_from_intr\n");
195 #define BUILD_SMP_TIMER_INTERRUPT(x) \
196 asmlinkage void x(struct pt_regs * regs); \
197 __asm__( \
198 "\n"__ALIGN_STR"\n" \
199 SYMBOL_NAME_STR(x) ":\n\t" \
200 "pushl $-1\n\t" \
201 SAVE_ALL \
202 "movl %esp,%eax\n\t" \
203 "pushl %eax\n\t" \
204 "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
205 "addl $4,%esp\n\t" \
206 "jmp ret_from_intr\n");
208 #endif /* __SMP__ */
210 #define BUILD_COMMON_IRQ() \
211 __asm__( \
212 "\n" __ALIGN_STR"\n" \
213 "common_interrupt:\n\t" \
214 SAVE_ALL \
215 "pushl $ret_from_intr\n\t" \
216 "jmp "SYMBOL_NAME_STR(do_IRQ));
219 * subtle. orig_eax is used by the signal code to distinct between
220 * system calls and interrupted 'random user-space'. Thus we have
221 * to put a negative value into orig_eax here. (the problem is that
222 * both system calls and IRQs want to have small integer numbers in
223 * orig_eax, and the syscall code has won the optimization conflict ;)
225 #define BUILD_IRQ(nr) \
226 asmlinkage void IRQ_NAME(nr); \
227 __asm__( \
228 "\n"__ALIGN_STR"\n" \
229 SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
230 "pushl $"#nr"-256\n\t" \
231 "jmp common_interrupt");
234 * x86 profiling function, SMP safe. We might want to do this in
235 * assembly totally?
237 static inline void x86_do_profile (unsigned long eip)
239 if (prof_buffer) {
240 eip -= (unsigned long) &_stext;
241 eip >>= prof_shift;
243 * Don't ignore out-of-bounds EIP values silently,
244 * put them into the last histogram slot, so if
245 * present, they will show up as a sharp peak.
247 if (eip > prof_len-1)
248 eip = prof_len-1;
249 atomic_inc((atomic_t *)&prof_buffer[eip]);
253 #endif