Import 2.2.8pre2
[davej-history.git] / arch / i386 / kernel / irq.h
blob533ab9c9a7596fc5ea3bd9c50010c19fd9811cb7
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 MTRR_CHANGE_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 smp_send_mtrr(void);
103 extern void init_VISWS_APIC_irqs(void);
104 extern void setup_IO_APIC(void);
105 extern int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn);
106 extern void make_8259A_irq(unsigned int irq);
107 extern void send_IPI(int dest, int vector);
108 extern void init_pic_mode(void);
109 extern void print_IO_APIC(void);
111 extern unsigned long io_apic_irqs;
113 extern char _stext, _etext;
115 #define MAX_IRQ_SOURCES 128
116 #define MAX_MP_BUSSES 32
117 enum mp_bustype {
118 MP_BUS_ISA,
119 MP_BUS_EISA,
120 MP_BUS_PCI
122 extern int mp_bus_id_to_type [MAX_MP_BUSSES];
123 extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES];
124 extern char ioapic_OEM_ID [16];
125 extern char ioapic_Product_ID [16];
127 extern spinlock_t irq_controller_lock;
129 #ifdef __SMP__
131 #include <asm/atomic.h>
133 static inline void irq_enter(int cpu, unsigned int irq)
135 hardirq_enter(cpu);
136 while (test_bit(0,&global_irq_lock)) {
137 /* nothing */;
141 static inline void irq_exit(int cpu, unsigned int irq)
143 hardirq_exit(cpu);
146 #define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs))
148 #else
150 #define irq_enter(cpu, irq) (++local_irq_count[cpu])
151 #define irq_exit(cpu, irq) (--local_irq_count[cpu])
153 #define IO_APIC_IRQ(x) (0)
155 #endif
157 #define __STR(x) #x
158 #define STR(x) __STR(x)
160 #define SAVE_ALL \
161 "cld\n\t" \
162 "pushl %es\n\t" \
163 "pushl %ds\n\t" \
164 "pushl %eax\n\t" \
165 "pushl %ebp\n\t" \
166 "pushl %edi\n\t" \
167 "pushl %esi\n\t" \
168 "pushl %edx\n\t" \
169 "pushl %ecx\n\t" \
170 "pushl %ebx\n\t" \
171 "movl $" STR(__KERNEL_DS) ",%edx\n\t" \
172 "movl %dx,%ds\n\t" \
173 "movl %dx,%es\n\t"
175 #define IRQ_NAME2(nr) nr##_interrupt(void)
176 #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
178 #define GET_CURRENT \
179 "movl %esp, %ebx\n\t" \
180 "andl $-8192, %ebx\n\t"
182 #ifdef __SMP__
185 * SMP has a few special interrupts for IPI messages
188 #define BUILD_SMP_INTERRUPT(x) \
189 asmlinkage void x(void); \
190 __asm__( \
191 "\n"__ALIGN_STR"\n" \
192 SYMBOL_NAME_STR(x) ":\n\t" \
193 "pushl $-1\n\t" \
194 SAVE_ALL \
195 "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
196 "jmp ret_from_intr\n");
198 #define BUILD_SMP_TIMER_INTERRUPT(x) \
199 asmlinkage void x(struct pt_regs * regs); \
200 __asm__( \
201 "\n"__ALIGN_STR"\n" \
202 SYMBOL_NAME_STR(x) ":\n\t" \
203 "pushl $-1\n\t" \
204 SAVE_ALL \
205 "movl %esp,%eax\n\t" \
206 "pushl %eax\n\t" \
207 "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
208 "addl $4,%esp\n\t" \
209 "jmp ret_from_intr\n");
211 #endif /* __SMP__ */
213 #define BUILD_COMMON_IRQ() \
214 __asm__( \
215 "\n" __ALIGN_STR"\n" \
216 "common_interrupt:\n\t" \
217 SAVE_ALL \
218 "pushl $ret_from_intr\n\t" \
219 "jmp "SYMBOL_NAME_STR(do_IRQ));
222 * subtle. orig_eax is used by the signal code to distinct between
223 * system calls and interrupted 'random user-space'. Thus we have
224 * to put a negative value into orig_eax here. (the problem is that
225 * both system calls and IRQs want to have small integer numbers in
226 * orig_eax, and the syscall code has won the optimization conflict ;)
228 #define BUILD_IRQ(nr) \
229 asmlinkage void IRQ_NAME(nr); \
230 __asm__( \
231 "\n"__ALIGN_STR"\n" \
232 SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
233 "pushl $"#nr"-256\n\t" \
234 "jmp common_interrupt");
237 * x86 profiling function, SMP safe. We might want to do this in
238 * assembly totally?
240 static inline void x86_do_profile (unsigned long eip)
242 if (prof_buffer && current->pid) {
243 eip -= (unsigned long) &_stext;
244 eip >>= prof_shift;
246 * Don't ignore out-of-bounds EIP values silently,
247 * put them into the last histogram slot, so if
248 * present, they will show up as a sharp peak.
250 if (eip > prof_len-1)
251 eip = prof_len-1;
252 atomic_inc((atomic_t *)&prof_buffer[eip]);
256 #endif