diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/m68knommu/platform/5307/ints.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/m68knommu/platform/5307/ints.c')
-rw-r--r-- | arch/m68knommu/platform/5307/ints.c | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/arch/m68knommu/platform/5307/ints.c b/arch/m68knommu/platform/5307/ints.c new file mode 100644 index 000000000000..0117754d44f3 --- /dev/null +++ b/arch/m68knommu/platform/5307/ints.c | |||
@@ -0,0 +1,280 @@ | |||
1 | /* | ||
2 | * linux/arch/m68knommu/kernel/ints.c -- General interrupt handling code | ||
3 | * | ||
4 | * Copyright (C) 1999-2002 Greg Ungerer (gerg@snapgear.com) | ||
5 | * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>, | ||
6 | * Kenneth Albanowski <kjahds@kjahds.com>, | ||
7 | * Copyright (C) 2000 Lineo Inc. (www.lineo.com) | ||
8 | * | ||
9 | * Based on: | ||
10 | * | ||
11 | * linux/arch/m68k/kernel/ints.c -- Linux/m68k general interrupt handling code | ||
12 | * | ||
13 | * This file is subject to the terms and conditions of the GNU General Public | ||
14 | * License. See the file COPYING in the main directory of this archive | ||
15 | * for more details. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/types.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/sched.h> | ||
22 | #include <linux/kernel_stat.h> | ||
23 | #include <linux/errno.h> | ||
24 | #include <linux/config.h> | ||
25 | #include <linux/seq_file.h> | ||
26 | |||
27 | #include <asm/system.h> | ||
28 | #include <asm/irq.h> | ||
29 | #include <asm/traps.h> | ||
30 | #include <asm/page.h> | ||
31 | #include <asm/machdep.h> | ||
32 | |||
33 | /* | ||
34 | * This table stores the address info for each vector handler. | ||
35 | */ | ||
36 | irq_handler_t irq_list[SYS_IRQS]; | ||
37 | |||
38 | #define NUM_IRQ_NODES 16 | ||
39 | static irq_node_t nodes[NUM_IRQ_NODES]; | ||
40 | |||
41 | /* The number of spurious interrupts */ | ||
42 | volatile unsigned int num_spurious; | ||
43 | |||
44 | unsigned int local_bh_count[NR_CPUS]; | ||
45 | unsigned int local_irq_count[NR_CPUS]; | ||
46 | |||
47 | static irqreturn_t default_irq_handler(int irq, void *ptr, struct pt_regs *regs) | ||
48 | { | ||
49 | #if 1 | ||
50 | printk(KERN_INFO "%s(%d): default irq handler vec=%d [0x%x]\n", | ||
51 | __FILE__, __LINE__, irq, irq); | ||
52 | #endif | ||
53 | return(IRQ_HANDLED); | ||
54 | } | ||
55 | |||
56 | /* | ||
57 | * void init_IRQ(void) | ||
58 | * | ||
59 | * Parameters: None | ||
60 | * | ||
61 | * Returns: Nothing | ||
62 | * | ||
63 | * This function should be called during kernel startup to initialize | ||
64 | * the IRQ handling routines. | ||
65 | */ | ||
66 | |||
67 | void __init init_IRQ(void) | ||
68 | { | ||
69 | int i; | ||
70 | |||
71 | for (i = 0; i < SYS_IRQS; i++) { | ||
72 | if (mach_default_handler) | ||
73 | irq_list[i].handler = (*mach_default_handler)[i]; | ||
74 | else | ||
75 | irq_list[i].handler = default_irq_handler; | ||
76 | irq_list[i].flags = IRQ_FLG_STD; | ||
77 | irq_list[i].dev_id = NULL; | ||
78 | irq_list[i].devname = NULL; | ||
79 | } | ||
80 | |||
81 | for (i = 0; i < NUM_IRQ_NODES; i++) | ||
82 | nodes[i].handler = NULL; | ||
83 | |||
84 | if (mach_init_IRQ) | ||
85 | mach_init_IRQ(); | ||
86 | } | ||
87 | |||
88 | irq_node_t *new_irq_node(void) | ||
89 | { | ||
90 | irq_node_t *node; | ||
91 | short i; | ||
92 | |||
93 | for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) | ||
94 | if (!node->handler) | ||
95 | return node; | ||
96 | |||
97 | printk(KERN_INFO "new_irq_node: out of nodes\n"); | ||
98 | return NULL; | ||
99 | } | ||
100 | |||
101 | int request_irq( | ||
102 | unsigned int irq, | ||
103 | irqreturn_t (*handler)(int, void *, struct pt_regs *), | ||
104 | unsigned long flags, | ||
105 | const char *devname, | ||
106 | void *dev_id) | ||
107 | { | ||
108 | if (irq < 0 || irq >= NR_IRQS) { | ||
109 | printk(KERN_WARNING "%s: Incorrect IRQ %d from %s\n", __FUNCTION__, | ||
110 | irq, devname); | ||
111 | return -ENXIO; | ||
112 | } | ||
113 | |||
114 | if (!(irq_list[irq].flags & IRQ_FLG_STD)) { | ||
115 | if (irq_list[irq].flags & IRQ_FLG_LOCK) { | ||
116 | printk(KERN_WARNING "%s: IRQ %d from %s is not replaceable\n", | ||
117 | __FUNCTION__, irq, irq_list[irq].devname); | ||
118 | return -EBUSY; | ||
119 | } | ||
120 | if (flags & IRQ_FLG_REPLACE) { | ||
121 | printk(KERN_WARNING "%s: %s can't replace IRQ %d from %s\n", | ||
122 | __FUNCTION__, devname, irq, irq_list[irq].devname); | ||
123 | return -EBUSY; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | if (flags & IRQ_FLG_FAST) { | ||
128 | extern asmlinkage void fasthandler(void); | ||
129 | extern void set_evector(int vecnum, void (*handler)(void)); | ||
130 | set_evector(irq, fasthandler); | ||
131 | } | ||
132 | |||
133 | irq_list[irq].handler = handler; | ||
134 | irq_list[irq].flags = flags; | ||
135 | irq_list[irq].dev_id = dev_id; | ||
136 | irq_list[irq].devname = devname; | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | EXPORT_SYMBOL(request_irq); | ||
141 | |||
142 | void free_irq(unsigned int irq, void *dev_id) | ||
143 | { | ||
144 | if (irq >= NR_IRQS) { | ||
145 | printk(KERN_WARNING "%s: Incorrect IRQ %d\n", __FUNCTION__, irq); | ||
146 | return; | ||
147 | } | ||
148 | |||
149 | if (irq_list[irq].dev_id != dev_id) | ||
150 | printk(KERN_WARNING "%s: Removing probably wrong IRQ %d from %s\n", | ||
151 | __FUNCTION__, irq, irq_list[irq].devname); | ||
152 | |||
153 | if (irq_list[irq].flags & IRQ_FLG_FAST) { | ||
154 | extern asmlinkage void inthandler(void); | ||
155 | extern void set_evector(int vecnum, void (*handler)(void)); | ||
156 | set_evector(irq, inthandler); | ||
157 | } | ||
158 | |||
159 | if (mach_default_handler) | ||
160 | irq_list[irq].handler = (*mach_default_handler)[irq]; | ||
161 | else | ||
162 | irq_list[irq].handler = default_irq_handler; | ||
163 | irq_list[irq].flags = IRQ_FLG_STD; | ||
164 | irq_list[irq].dev_id = NULL; | ||
165 | irq_list[irq].devname = NULL; | ||
166 | } | ||
167 | |||
168 | EXPORT_SYMBOL(free_irq); | ||
169 | |||
170 | |||
171 | int sys_request_irq(unsigned int irq, | ||
172 | irqreturn_t (*handler)(int, void *, struct pt_regs *), | ||
173 | unsigned long flags, const char *devname, void *dev_id) | ||
174 | { | ||
175 | if (irq > IRQ7) { | ||
176 | printk(KERN_WARNING "%s: Incorrect IRQ %d from %s\n", | ||
177 | __FUNCTION__, irq, devname); | ||
178 | return -ENXIO; | ||
179 | } | ||
180 | |||
181 | #if 0 | ||
182 | if (!(irq_list[irq].flags & IRQ_FLG_STD)) { | ||
183 | if (irq_list[irq].flags & IRQ_FLG_LOCK) { | ||
184 | printk(KERN_WARNING "%s: IRQ %d from %s is not replaceable\n", | ||
185 | __FUNCTION__, irq, irq_list[irq].devname); | ||
186 | return -EBUSY; | ||
187 | } | ||
188 | if (!(flags & IRQ_FLG_REPLACE)) { | ||
189 | printk(KERN_WARNING "%s: %s can't replace IRQ %d from %s\n", | ||
190 | __FUNCTION__, devname, irq, irq_list[irq].devname); | ||
191 | return -EBUSY; | ||
192 | } | ||
193 | } | ||
194 | #endif | ||
195 | |||
196 | irq_list[irq].handler = handler; | ||
197 | irq_list[irq].flags = flags; | ||
198 | irq_list[irq].dev_id = dev_id; | ||
199 | irq_list[irq].devname = devname; | ||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | void sys_free_irq(unsigned int irq, void *dev_id) | ||
204 | { | ||
205 | if (irq > IRQ7) { | ||
206 | printk(KERN_WARNING "%s: Incorrect IRQ %d\n", __FUNCTION__, irq); | ||
207 | return; | ||
208 | } | ||
209 | |||
210 | if (irq_list[irq].dev_id != dev_id) | ||
211 | printk(KERN_WARNING "%s: Removing probably wrong IRQ %d from %s\n", | ||
212 | __FUNCTION__, irq, irq_list[irq].devname); | ||
213 | |||
214 | irq_list[irq].handler = (*mach_default_handler)[irq]; | ||
215 | irq_list[irq].flags = 0; | ||
216 | irq_list[irq].dev_id = NULL; | ||
217 | irq_list[irq].devname = NULL; | ||
218 | } | ||
219 | |||
220 | /* | ||
221 | * Do we need these probe functions on the m68k? | ||
222 | * | ||
223 | * ... may be useful with ISA devices | ||
224 | */ | ||
225 | unsigned long probe_irq_on (void) | ||
226 | { | ||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | EXPORT_SYMBOL(probe_irq_on); | ||
231 | |||
232 | int probe_irq_off (unsigned long irqs) | ||
233 | { | ||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | EXPORT_SYMBOL(probe_irq_off); | ||
238 | |||
239 | asmlinkage void process_int(unsigned long vec, struct pt_regs *fp) | ||
240 | { | ||
241 | if (vec >= VEC_INT1 && vec <= VEC_INT7) { | ||
242 | vec -= VEC_SPUR; | ||
243 | kstat_cpu(0).irqs[vec]++; | ||
244 | irq_list[vec].handler(vec, irq_list[vec].dev_id, fp); | ||
245 | } else { | ||
246 | if (mach_process_int) | ||
247 | mach_process_int(vec, fp); | ||
248 | else | ||
249 | panic("Can't process interrupt vector %ld\n", vec); | ||
250 | return; | ||
251 | } | ||
252 | } | ||
253 | |||
254 | |||
255 | int show_interrupts(struct seq_file *p, void *v) | ||
256 | { | ||
257 | int i = *(loff_t *) v; | ||
258 | |||
259 | if (i < NR_IRQS) { | ||
260 | if (! (irq_list[i].flags & IRQ_FLG_STD)) { | ||
261 | seq_printf(p, "%3d: %10u ", i, | ||
262 | (i ? kstat_cpu(0).irqs[i] : num_spurious)); | ||
263 | if (irq_list[i].flags & IRQ_FLG_LOCK) | ||
264 | seq_printf(p, "L "); | ||
265 | else | ||
266 | seq_printf(p, " "); | ||
267 | seq_printf(p, "%s\n", irq_list[i].devname); | ||
268 | } | ||
269 | } | ||
270 | |||
271 | if (i == NR_IRQS && mach_get_irq_list) | ||
272 | mach_get_irq_list(p, v); | ||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | void init_irq_proc(void) | ||
277 | { | ||
278 | /* Insert /proc/irq driver here */ | ||
279 | } | ||
280 | |||