2005-04-16 15:20:36 -07:00
# include <linux/linkage.h>
# include <linux/errno.h>
# include <linux/signal.h>
# include <linux/sched.h>
# include <linux/ioport.h>
# include <linux/interrupt.h>
# include <linux/timex.h>
# include <linux/slab.h>
# include <linux/random.h>
# include <linux/init.h>
# include <linux/kernel_stat.h>
# include <linux/sysdev.h>
# include <linux/bitops.h>
# include <asm/acpi.h>
# include <asm/atomic.h>
# include <asm/system.h>
# include <asm/io.h>
# include <asm/hw_irq.h>
# include <asm/pgtable.h>
# include <asm/delay.h>
# include <asm/desc.h>
# include <asm/apic.h>
2008-01-30 13:30:29 +01:00
# include <asm/i8259.h>
2005-04-16 15:20:36 -07:00
/*
* ISA PIC or low IO - APIC triggered ( INTA - cycle or APIC ) interrupts :
2007-03-28 23:10:29 -06:00
* ( these are usually mapped to vectors 0x30 - 0x3f )
2005-04-16 15:20:36 -07:00
*/
/*
2008-01-30 13:30:29 +01:00
* The IO - APIC gives us many more interrupt sources . Most of these
2005-04-16 15:20:36 -07:00
* are unused but an SMP system is supposed to have enough memory . . .
* sometimes ( mostly wrt . hw bugs ) we get corrupted vectors all
* across the spectrum , so we really want to be prepared to get all
* of these . Plus , more powerful systems might have more than 64
* IO - APIC registers .
*
* ( these are usually mapped into the 0x30 - 0xff vector range )
*/
2008-01-30 13:30:29 +01:00
2005-04-16 15:20:36 -07:00
/*
* IRQ2 is cascade interrupt to second interrupt controller
*/
2007-10-17 18:04:36 +02:00
static struct irqaction irq2 = {
. handler = no_action ,
. mask = CPU_MASK_NONE ,
. name = " cascade " ,
} ;
2006-10-04 02:16:51 -07:00
DEFINE_PER_CPU ( vector_irq_t , vector_irq ) = {
2007-02-23 04:38:26 -07:00
[ 0 . . . IRQ0_VECTOR - 1 ] = - 1 ,
[ IRQ0_VECTOR ] = 0 ,
[ IRQ1_VECTOR ] = 1 ,
[ IRQ2_VECTOR ] = 2 ,
[ IRQ3_VECTOR ] = 3 ,
[ IRQ4_VECTOR ] = 4 ,
[ IRQ5_VECTOR ] = 5 ,
[ IRQ6_VECTOR ] = 6 ,
[ IRQ7_VECTOR ] = 7 ,
[ IRQ8_VECTOR ] = 8 ,
[ IRQ9_VECTOR ] = 9 ,
[ IRQ10_VECTOR ] = 10 ,
[ IRQ11_VECTOR ] = 11 ,
[ IRQ12_VECTOR ] = 12 ,
[ IRQ13_VECTOR ] = 13 ,
[ IRQ14_VECTOR ] = 14 ,
[ IRQ15_VECTOR ] = 15 ,
[ IRQ15_VECTOR + 1 . . . NR_VECTORS - 1 ] = - 1
2006-10-04 02:16:50 -07:00
} ;
2005-04-16 15:20:36 -07:00
2008-07-11 15:12:39 -03:00
void __init init_ISA_irqs ( void )
2005-04-16 15:20:36 -07:00
{
int i ;
init_bsp_APIC ( ) ;
init_8259A ( 0 ) ;
2008-12-05 18:58:32 -08:00
for ( i = 0 ; i < NR_IRQS_LEGACY ; i + + ) {
2008-10-15 14:34:09 +02:00
struct irq_desc * desc = irq_to_desc ( i ) ;
2008-08-19 20:50:05 -07:00
desc - > status = IRQ_DISABLED ;
desc - > action = NULL ;
desc - > depth = 1 ;
2005-04-16 15:20:36 -07:00
2008-08-19 20:50:11 -07:00
/*
* 16 old - style INTA - cycle interrupts :
*/
set_irq_chip_and_handler_name ( i , & i8259A_chip ,
2006-10-17 00:10:03 -07:00
handle_level_irq , " XT " ) ;
2005-04-16 15:20:36 -07:00
}
}
2008-01-30 13:33:19 +01:00
void init_IRQ ( void ) __attribute__ ( ( weak , alias ( " native_init_IRQ " ) ) ) ;
2008-09-25 22:22:12 -07:00
static void __init smp_intr_init ( void )
2005-04-16 15:20:36 -07:00
{
# ifdef CONFIG_SMP
/*
* The reschedule interrupt is a CPU - to - CPU reschedule - helper
* IPI , driven by wakeup .
*/
2008-04-15 15:36:56 -05:00
alloc_intr_gate ( RESCHEDULE_VECTOR , reschedule_interrupt ) ;
2005-04-16 15:20:36 -07:00
2005-09-12 18:49:24 +02:00
/* IPIs for invalidation */
2008-04-15 15:36:56 -05:00
alloc_intr_gate ( INVALIDATE_TLB_VECTOR_START + 0 , invalidate_interrupt0 ) ;
alloc_intr_gate ( INVALIDATE_TLB_VECTOR_START + 1 , invalidate_interrupt1 ) ;
alloc_intr_gate ( INVALIDATE_TLB_VECTOR_START + 2 , invalidate_interrupt2 ) ;
alloc_intr_gate ( INVALIDATE_TLB_VECTOR_START + 3 , invalidate_interrupt3 ) ;
alloc_intr_gate ( INVALIDATE_TLB_VECTOR_START + 4 , invalidate_interrupt4 ) ;
alloc_intr_gate ( INVALIDATE_TLB_VECTOR_START + 5 , invalidate_interrupt5 ) ;
alloc_intr_gate ( INVALIDATE_TLB_VECTOR_START + 6 , invalidate_interrupt6 ) ;
alloc_intr_gate ( INVALIDATE_TLB_VECTOR_START + 7 , invalidate_interrupt7 ) ;
2005-04-16 15:20:36 -07:00
/* IPI for generic function call */
2008-04-15 15:36:56 -05:00
alloc_intr_gate ( CALL_FUNCTION_VECTOR , call_function_interrupt ) ;
2007-02-23 04:40:58 -07:00
2008-07-15 21:55:59 +02:00
/* IPI for generic single function call */
alloc_intr_gate ( CALL_FUNCTION_SINGLE_VECTOR ,
call_function_single_interrupt ) ;
2007-02-23 04:40:58 -07:00
/* Low priority IPI to cleanup after moving an irq */
set_intr_gate ( IRQ_MOVE_CLEANUP_VECTOR , irq_move_cleanup_interrupt ) ;
# endif
2008-07-11 15:08:39 -03:00
}
2008-09-25 22:22:12 -07:00
static void __init apic_intr_init ( void )
2008-07-11 15:08:39 -03:00
{
smp_intr_init ( ) ;
2008-04-15 15:36:56 -05:00
alloc_intr_gate ( THERMAL_APIC_VECTOR , thermal_interrupt ) ;
alloc_intr_gate ( THRESHOLD_APIC_VECTOR , threshold_interrupt ) ;
2005-04-16 15:20:36 -07:00
/* self generated IPI for local APIC timer */
2008-04-15 15:36:56 -05:00
alloc_intr_gate ( LOCAL_TIMER_VECTOR , apic_timer_interrupt ) ;
2005-04-16 15:20:36 -07:00
/* IPI vectors for APIC spurious and error interrupts */
2008-04-15 15:36:56 -05:00
alloc_intr_gate ( SPURIOUS_APIC_VECTOR , spurious_interrupt ) ;
alloc_intr_gate ( ERROR_APIC_VECTOR , error_interrupt ) ;
2008-07-11 15:08:39 -03:00
}
void __init native_init_IRQ ( void )
{
int i ;
init_ISA_irqs ( ) ;
/*
* Cover the whole vector space , no vector can escape
* us . ( some of these will be overridden and become
* ' special ' SMP interrupts )
*/
for ( i = 0 ; i < ( NR_VECTORS - FIRST_EXTERNAL_VECTOR ) ; i + + ) {
int vector = FIRST_EXTERNAL_VECTOR + i ;
if ( vector ! = IA32_SYSCALL_VECTOR )
set_intr_gate ( vector , interrupt [ i ] ) ;
}
apic_intr_init ( ) ;
2005-04-16 15:20:36 -07:00
if ( ! acpi_ioapic )
setup_irq ( 2 , & irq2 ) ;
}