OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [ia64/] [kernel/] [irq_ia64.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * linux/arch/ia64/kernel/irq.c
3
 *
4
 * Copyright (C) 1998-2001 Hewlett-Packard Co
5
 *      Stephane Eranian <eranian@hpl.hp.com>
6
 *      David Mosberger-Tang <davidm@hpl.hp.com>
7
 *
8
 *  6/10/99: Updated to bring in sync with x86 version to facilitate
9
 *           support for SMP and different interrupt controllers.
10
 *
11
 * 09/15/00 Goutham Rao <goutham.rao@intel.com> Implemented pci_irq_to_vector
12
 *                      PCI to vector allocation routine.
13
 */
14
 
15
#include <linux/config.h>
16
 
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/slab.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>
30
 
31
#include <asm/bitops.h>
32
#include <asm/delay.h>
33
#include <asm/io.h>
34
#include <asm/hw_irq.h>
35
#include <asm/machvec.h>
36
#include <asm/pgtable.h>
37
#include <asm/system.h>
38
 
39
#ifdef CONFIG_PERFMON
40
# include <asm/perfmon.h>
41
#endif
42
 
43
#define IRQ_DEBUG       0
44
 
45
/* default base addr of IPI table */
46
unsigned long ipi_base_addr = (__IA64_UNCACHED_OFFSET | IA64_IPI_DEFAULT_BASE_ADDR);
47
 
48
/*
49
 * Legacy IRQ to IA-64 vector translation table.
50
 */
51
__u8 isa_irq_to_vector_map[16] = {
52
        /* 8259 IRQ translation, first 16 entries */
53
        0x2f, 0x20, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29,
54
        0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21
55
};
56
 
57
int
58
ia64_alloc_vector (void)
59
{
60
        static int next_vector = IA64_FIRST_DEVICE_VECTOR;
61
 
62
        if (next_vector > IA64_LAST_DEVICE_VECTOR)
63
                /* XXX could look for sharable vectors instead of panic'ing... */
64
                panic("%s: out of interrupt vectors!", __FUNCTION__);
65
        return next_vector++;
66
}
67
 
68
extern unsigned int do_IRQ(unsigned long irq, struct pt_regs *regs);
69
 
70
/*
71
 * That's where the IVT branches when we get an external
72
 * interrupt. This branches to the correct hardware IRQ handler via
73
 * function ptr.
74
 */
75
void
76
ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
77
{
78
        unsigned long saved_tpr;
79
#ifdef CONFIG_SMP
80
#       define IS_RESCHEDULE(vec)       (vec == IA64_IPI_RESCHEDULE)
81
#else
82
#       define IS_RESCHEDULE(vec)       (0)
83
#endif
84
 
85
#if IRQ_DEBUG
86
        {
87
                unsigned long bsp, sp;
88
 
89
                /*
90
                 * Note: if the interrupt happened while executing in
91
                 * the context switch routine (ia64_switch_to), we may
92
                 * get a spurious stack overflow here.  This is
93
                 * because the register and the memory stack are not
94
                 * switched atomically.
95
                 */
96
                asm ("mov %0=ar.bsp" : "=r"(bsp));
97
                asm ("mov %0=sp" : "=r"(sp));
98
 
99
                if ((sp - bsp) < 1024) {
100
                        static unsigned char count;
101
                        static long last_time;
102
 
103
                        if (jiffies - last_time > 5*HZ)
104
                                count = 0;
105
                        if (++count < 5) {
106
                                last_time = jiffies;
107
                                printk("ia64_handle_irq: DANGER: less than "
108
                                       "1KB of free stack space!!\n"
109
                                       "(bsp=0x%lx, sp=%lx)\n", bsp, sp);
110
                        }
111
                }
112
        }
113
#endif /* IRQ_DEBUG */
114
 
115
        /*
116
         * Always set TPR to limit maximum interrupt nesting depth to
117
         * 16 (without this, it would be ~240, which could easily lead
118
         * to kernel stack overflows).
119
         */
120
        saved_tpr = ia64_get_tpr();
121
        ia64_srlz_d();
122
        while (vector != IA64_SPURIOUS_INT_VECTOR) {
123
                if (!IS_RESCHEDULE(vector)) {
124
                        ia64_set_tpr(vector);
125
                        ia64_srlz_d();
126
 
127
                        do_IRQ(local_vector_to_irq(vector), regs);
128
 
129
                        /*
130
                         * Disable interrupts and send EOI:
131
                         */
132
                        local_irq_disable();
133
                        ia64_set_tpr(saved_tpr);
134
                }
135
                ia64_eoi();
136
                vector = ia64_get_ivr();
137
        }
138
        /*
139
         * This must be done *after* the ia64_eoi().  For example, the keyboard softirq
140
         * handler needs to be able to wait for further keyboard interrupts, which can't
141
         * come through until ia64_eoi() has been done.
142
         */
143
        if (local_softirq_pending())
144
                do_softirq();
145
}
146
 
147
#ifdef CONFIG_SMP
148
extern void handle_IPI (int irq, void *dev_id, struct pt_regs *regs);
149
 
150
static struct irqaction ipi_irqaction = {
151
        .handler =      handle_IPI,
152
        .flags =        SA_INTERRUPT,
153
        .name =         "IPI"
154
};
155
#endif
156
 
157
void
158
register_percpu_irq (ia64_vector vec, struct irqaction *action)
159
{
160
        irq_desc_t *desc;
161
        unsigned int irq;
162
 
163
        for (irq = 0; irq < NR_IRQS; ++irq)
164
                if (irq_to_vector(irq) == vec) {
165
                        desc = irq_desc(irq);
166
                        desc->status |= IRQ_PER_CPU;
167
                        desc->handler = &irq_type_ia64_lsapic;
168
                        if (action)
169
                                setup_irq(irq, action);
170
                }
171
}
172
 
173
void __init
174
init_IRQ (void)
175
{
176
        register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL);
177
#ifdef CONFIG_SMP
178
        register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction);
179
#endif
180
#ifdef CONFIG_PERFMON
181
        pfm_init_percpu();
182
#endif
183
        platform_irq_init();
184
}
185
 
186
void
187
ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect)
188
{
189
        unsigned long ipi_addr;
190
        unsigned long ipi_data;
191
        unsigned long phys_cpu_id;
192
 
193
#ifdef CONFIG_SMP
194
        phys_cpu_id = cpu_physical_id(cpu);
195
#else
196
        phys_cpu_id = (ia64_get_lid() >> 16) & 0xffff;
197
#endif
198
 
199
        /*
200
         * cpu number is in 8bit ID and 8bit EID
201
         */
202
 
203
        ipi_data = (delivery_mode << 8) | (vector & 0xff);
204
        ipi_addr = ipi_base_addr | (phys_cpu_id << 4) | ((redirect & 1)  << 3);
205
 
206
        writeq(ipi_data, ipi_addr);
207
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.