2 * linux/arch/ia64/kernel/irq.c
4 * Copyright (C) 1998-2000 Hewlett-Packard Co
5 * Copyright (C) 1998, 1999 Stephane Eranian <eranian@hpl.hp.com>
6 * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
8 * 6/10/99: Updated to bring in sync with x86 version to facilitate
9 * support for SMP and different interrupt controllers.
11 * 09/15/00 Goutham Rao <goutham.rao@intel.com> Implemented pci_irq_to_vector
12 * PCI to vector allocation routine.
15 #include <linux/config.h>
17 #include <linux/sched.h>
18 #include <linux/errno.h>
19 #include <linux/init.h>
20 #include <linux/interrupt.h>
21 #include <linux/ioport.h>
22 #include <linux/kernel_stat.h>
23 #include <linux/malloc.h>
24 #include <linux/ptrace.h>
25 #include <linux/random.h> /* for rand_initialize_irq() */
26 #include <linux/signal.h>
27 #include <linux/smp.h>
28 #include <linux/smp_lock.h>
29 #include <linux/threads.h>
31 #include <asm/bitops.h>
32 #include <asm/delay.h>
34 #include <asm/hw_irq.h>
35 #include <asm/machvec.h>
36 #include <asm/pgtable.h>
37 #include <asm/system.h>
41 /* default base addr of IPI table */
42 unsigned long ipi_base_addr = (__IA64_UNCACHED_OFFSET | IPI_DEFAULT_BASE_ADDR);
45 * Legacy IRQ to IA-64 vector translation table.
47 __u8 isa_irq_to_vector_map[16] = {
48 /* 8259 IRQ translation, first 16 entries */
49 0x2f, 0x20, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29,
50 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21
56 static int next_irq = FIRST_DEVICE_IRQ;
58 if (next_irq > LAST_DEVICE_IRQ)
59 /* XXX could look for sharable vectors instead of panic'ing... */
60 panic("ia64_alloc_irq: out of interrupt vectors!");
65 * That's where the IVT branches when we get an external
66 * interrupt. This branches to the correct hardware IRQ handler via
70 ia64_handle_irq (unsigned long vector, struct pt_regs *regs)
72 unsigned long saved_tpr;
76 unsigned long bsp, sp;
79 * Note: if the interrupt happened while executing in
80 * the context switch routine (ia64_switch_to), we may
81 * get a spurious stack overflow here. This is
82 * because the register and the memory stack are not
83 * switched atomically.
85 asm ("mov %0=ar.bsp" : "=r"(bsp));
86 asm ("mov %0=sp" : "=r"(sp));
88 if ((sp - bsp) < 1024) {
89 static unsigned char count;
90 static long last_time;
92 if (count > 5 && jiffies - last_time > 5*HZ)
96 printk("ia64_handle_irq: DANGER: less than "
97 "1KB of free stack space!!\n"
98 "(bsp=0x%lx, sp=%lx)\n", bsp, sp);
102 #endif /* IRQ_DEBUG */
105 * Always set TPR to limit maximum interrupt nesting depth to
106 * 16 (without this, it would be ~240, which could easily lead
107 * to kernel stack overflows).
109 saved_tpr = ia64_get_tpr();
112 if (vector >= NR_IRQS) {
113 printk("handle_irq: invalid vector %lu\n", vector);
114 ia64_set_tpr(saved_tpr);
118 ia64_set_tpr(vector);
121 if ((irq_desc[vector].status & IRQ_PER_CPU) != 0)
122 do_IRQ_per_cpu(vector, regs);
124 do_IRQ(vector, regs);
127 * Disable interrupts and send EOI:
130 ia64_set_tpr(saved_tpr);
132 vector = ia64_get_ivr();
133 } while (vector != IA64_SPURIOUS_INT);
138 extern void handle_IPI (int irq, void *dev_id, struct pt_regs *regs);
140 static struct irqaction ipi_irqaction = {
151 * Disable all local interrupts
157 irq_desc[IA64_SPURIOUS_INT].handler = &irq_type_ia64_sapic;
160 * Configure the IPI vector and handler
162 irq_desc[IPI_IRQ].status |= IRQ_PER_CPU;
163 irq_desc[IPI_IRQ].handler = &irq_type_ia64_sapic;
164 setup_irq(IPI_IRQ, &ipi_irqaction);
167 ia64_set_pmv(1 << 16);
168 ia64_set_cmcv(CMC_IRQ); /* XXX fix me */
172 /* clear TPR to enable all interrupt classes: */
177 ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect)
179 unsigned long ipi_addr;
180 unsigned long ipi_data;
181 unsigned long phys_cpu_id;
184 phys_cpu_id = cpu_physical_id(cpu);
186 phys_cpu_id = (ia64_get_lid() >> 16) & 0xffff;
190 * cpu number is in 8bit ID and 8bit EID
193 ipi_data = (delivery_mode << 8) | (vector & 0xff);
194 ipi_addr = ipi_base_addr | (phys_cpu_id << 4) | ((redirect & 1) << 3);
196 writeq(ipi_data, ipi_addr);