Import 2.3.10pre1
[davej-history.git] / arch / i386 / kernel / irq.h
blob1023cd4da31e1997af0f7633b2be94a5fa70e89f
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 might be merged
61 * into a single vector to save vector space. TLB, reschedule and
62 * 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];
123 extern char ioapic_OEM_ID [16];
124 extern char ioapic_Product_ID [16];
126 extern spinlock_t irq_controller_lock;
128 #ifdef __SMP__
130 #include <asm/atomic.h>
132 static inline void irq_enter(int cpu, unsigned int irq)
134 hardirq_enter(cpu);
135 while (test_bit(0,&global_irq_lock)) {
136 /* nothing */;
140 static inline void irq_exit(int cpu, unsigned int irq)
142 hardirq_exit(cpu);
145 #define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs))
147 #else
149 #define irq_enter(cpu, irq) (++local_irq_count[cpu])
150 #define irq_exit(cpu, irq) (--local_irq_count[cpu])
152 #define IO_APIC_IRQ(x) (0)
154 #endif
156 #define __STR(x) #x
157 #define STR(x) __STR(x)
159 #define SAVE_ALL \
160 "cld\n\t" \
161 "pushl %es\n\t" \
162 "pushl %ds\n\t" \
163 "pushl %eax\n\t" \
164 "pushl %ebp\n\t" \
165 "pushl %edi\n\t" \
166 "pushl %esi\n\t" \
167 "pushl %edx\n\t" \
168 "pushl %ecx\n\t" \
169 "pushl %ebx\n\t" \
170 "movl $" STR(__KERNEL_DS) ",%edx\n\t" \
171 "movl %dx,%ds\n\t" \
172 "movl %dx,%es\n\t"
174 #define IRQ_NAME2(nr) nr##_interrupt(void)
175 #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
177 #define GET_CURRENT \
178 "movl %esp, %ebx\n\t" \
179 "andl $-8192, %ebx\n\t"
181 #ifdef __SMP__
184 * SMP has a few special interrupts for IPI messages
187 #define BUILD_SMP_INTERRUPT(x) \
188 asmlinkage void x(void); \
189 __asm__( \
190 "\n"__ALIGN_STR"\n" \
191 SYMBOL_NAME_STR(x) ":\n\t" \
192 "pushl $-1\n\t" \
193 SAVE_ALL \
194 "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
195 "jmp ret_from_intr\n");
197 #define BUILD_SMP_TIMER_INTERRUPT(x) \
198 asmlinkage void x(struct pt_regs * regs); \
199 __asm__( \
200 "\n"__ALIGN_STR"\n" \
201 SYMBOL_NAME_STR(x) ":\n\t" \
202 "pushl $-1\n\t" \
203 SAVE_ALL \
204 "movl %esp,%eax\n\t" \
205 "pushl %eax\n\t" \
206 "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
207 "addl $4,%esp\n\t" \
208 "jmp ret_from_intr\n");
210 #endif /* __SMP__ */
212 #define BUILD_COMMON_IRQ() \
213 __asm__( \
214 "\n" __ALIGN_STR"\n" \
215 "common_interrupt:\n\t" \
216 SAVE_ALL \
217 "pushl $ret_from_intr\n\t" \
218 "jmp "SYMBOL_NAME_STR(do_IRQ));
221 * subtle. orig_eax is used by the signal code to distinct between
222 * system calls and interrupted 'random user-space'. Thus we have
223 * to put a negative value into orig_eax here. (the problem is that
224 * both system calls and IRQs want to have small integer numbers in
225 * orig_eax, and the syscall code has won the optimization conflict ;)
227 #define BUILD_IRQ(nr) \
228 asmlinkage void IRQ_NAME(nr); \
229 __asm__( \
230 "\n"__ALIGN_STR"\n" \
231 SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
232 "pushl $"#nr"-256\n\t" \
233 "jmp common_interrupt");
236 * x86 profiling function, SMP safe. We might want to do this in
237 * assembly totally?
239 static inline void x86_do_profile (unsigned long eip)
241 if (prof_buffer) {
242 eip -= (unsigned long) &_stext;
243 eip >>= prof_shift;
245 * Don't ignore out-of-bounds EIP values silently,
246 * put them into the last histogram slot, so if
247 * present, they will show up as a sharp peak.
249 if (eip > prof_len-1)
250 eip = prof_len-1;
251 atomic_inc((atomic_t *)&prof_buffer[eip]);
255 #endif