7 * Interrupt controller descriptor. This is all we need
8 * to describe about the low-level hardware.
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
;
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.
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 */
46 * IDT vectors usable for external interrupt sources start
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
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
;
128 #include <asm/atomic.h>
130 static inline void irq_enter(int cpu
, unsigned int irq
)
133 while (test_bit(0,&global_irq_lock
)) {
138 static inline void irq_exit(int cpu
, unsigned int irq
)
143 #define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs))
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)
155 #define STR(x) __STR(x)
168 "movl $" STR(__KERNEL_DS) ",%edx\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"
182 * SMP has a few special interrupts for IPI messages
185 #define BUILD_SMP_INTERRUPT(x) \
186 asmlinkage void x(void); \
188 "\n"__ALIGN_STR"\n" \
189 SYMBOL_NAME_STR(x) ":\n\t" \
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); \
198 "\n"__ALIGN_STR"\n" \
199 SYMBOL_NAME_STR(x) ":\n\t" \
202 "movl %esp,%eax\n\t" \
204 "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
206 "jmp ret_from_intr\n");
210 #define BUILD_COMMON_IRQ() \
212 "\n" __ALIGN_STR"\n" \
213 "common_interrupt:\n\t" \
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); \
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
237 static inline void x86_do_profile (unsigned long eip
)
240 eip
-= (unsigned long) &_stext
;
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)
249 atomic_inc((atomic_t
*)&prof_buffer
[eip
]);