• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500-V1.0.1.40_1.0.68/src/linux/linux-2.6/arch/m68knommu/platform/5307/
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/interrupt.h>
23#include <linux/kernel_stat.h>
24#include <linux/errno.h>
25#include <linux/seq_file.h>
26
27#include <asm/system.h>
28#include <asm/irq.h>
29#include <asm/irqnode.h>
30#include <asm/traps.h>
31#include <asm/page.h>
32#include <asm/machdep.h>
33
34/*
35 *	This table stores the address info for each vector handler.
36 */
37struct irq_entry irq_list[SYS_IRQS];
38
39#define NUM_IRQ_NODES 16
40static irq_node_t nodes[NUM_IRQ_NODES];
41
42/* The number of spurious interrupts */
43volatile unsigned int num_spurious;
44
45unsigned int local_irq_count[NR_CPUS];
46
47static irqreturn_t default_irq_handler(int irq, void *ptr)
48{
49	printk(KERN_INFO "%s(%d): default irq handler vec=%d [0x%x]\n",
50		__FILE__, __LINE__, irq, irq);
51	return(IRQ_HANDLED);
52}
53
54/*
55 * void init_IRQ(void)
56 *
57 * Parameters:	None
58 *
59 * Returns:	Nothing
60 *
61 * This function should be called during kernel startup to initialize
62 * the IRQ handling routines.
63 */
64
65void __init init_IRQ(void)
66{
67	int i;
68
69	for (i = 0; i < SYS_IRQS; i++) {
70		if (mach_default_handler)
71			irq_list[i].handler = mach_default_handler;
72		else
73			irq_list[i].handler = default_irq_handler;
74		irq_list[i].flags   = IRQ_FLG_STD;
75		irq_list[i].dev_id  = NULL;
76		irq_list[i].devname = NULL;
77	}
78
79	for (i = 0; i < NUM_IRQ_NODES; i++)
80		nodes[i].handler = NULL;
81
82	if (mach_init_IRQ)
83		mach_init_IRQ();
84}
85
86irq_node_t *new_irq_node(void)
87{
88	irq_node_t *node;
89	short i;
90
91	for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--)
92		if (!node->handler)
93			return node;
94
95	printk(KERN_INFO "new_irq_node: out of nodes\n");
96	return NULL;
97}
98
99int request_irq(
100	unsigned int irq,
101	irq_handler_t handler,
102	unsigned long flags,
103	const char *devname,
104	void *dev_id)
105{
106	if (irq < 0 || irq >= NR_IRQS) {
107		printk(KERN_WARNING "%s: Incorrect IRQ %d from %s\n", __FUNCTION__,
108			irq, devname);
109		return -ENXIO;
110	}
111
112	if (!(irq_list[irq].flags & IRQ_FLG_STD)) {
113		if (irq_list[irq].flags & IRQ_FLG_LOCK) {
114			printk(KERN_WARNING "%s: IRQ %d from %s is not replaceable\n",
115			       __FUNCTION__, irq, irq_list[irq].devname);
116			return -EBUSY;
117		}
118		if (flags & IRQ_FLG_REPLACE) {
119			printk(KERN_WARNING "%s: %s can't replace IRQ %d from %s\n",
120			       __FUNCTION__, devname, irq, irq_list[irq].devname);
121			return -EBUSY;
122		}
123	}
124
125	if (flags & IRQ_FLG_FAST) {
126		extern asmlinkage void fasthandler(void);
127		extern void set_evector(int vecnum, void (*handler)(void));
128		set_evector(irq, fasthandler);
129	}
130
131	irq_list[irq].handler = handler;
132	irq_list[irq].flags   = flags;
133	irq_list[irq].dev_id  = dev_id;
134	irq_list[irq].devname = devname;
135	return 0;
136}
137
138EXPORT_SYMBOL(request_irq);
139
140void free_irq(unsigned int irq, void *dev_id)
141{
142	if (irq >= NR_IRQS) {
143		printk(KERN_WARNING "%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
144		return;
145	}
146
147	if (irq_list[irq].dev_id != dev_id)
148		printk(KERN_WARNING "%s: Removing probably wrong IRQ %d from %s\n",
149		       __FUNCTION__, irq, irq_list[irq].devname);
150
151	if (irq_list[irq].flags & IRQ_FLG_FAST) {
152		extern asmlinkage void inthandler(void);
153		extern void set_evector(int vecnum, void (*handler)(void));
154		set_evector(irq, inthandler);
155	}
156
157	if (mach_default_handler)
158		irq_list[irq].handler = mach_default_handler;
159	else
160		irq_list[irq].handler = default_irq_handler;
161	irq_list[irq].flags   = IRQ_FLG_STD;
162	irq_list[irq].dev_id  = NULL;
163	irq_list[irq].devname = NULL;
164}
165
166EXPORT_SYMBOL(free_irq);
167
168
169int sys_request_irq(unsigned int irq, irq_handler_t handler,
170                    unsigned long flags, const char *devname, void *dev_id)
171{
172	if (irq > IRQ7) {
173		printk(KERN_WARNING "%s: Incorrect IRQ %d from %s\n",
174		       __FUNCTION__, irq, devname);
175		return -ENXIO;
176	}
177
178
179	irq_list[irq].handler = handler;
180	irq_list[irq].flags   = flags;
181	irq_list[irq].dev_id  = dev_id;
182	irq_list[irq].devname = devname;
183	return 0;
184}
185
186void sys_free_irq(unsigned int irq, void *dev_id)
187{
188	if (irq > IRQ7) {
189		printk(KERN_WARNING "%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
190		return;
191	}
192
193	if (irq_list[irq].dev_id != dev_id)
194		printk(KERN_WARNING "%s: Removing probably wrong IRQ %d from %s\n",
195		       __FUNCTION__, irq, irq_list[irq].devname);
196
197	irq_list[irq].handler = mach_default_handler;
198	irq_list[irq].flags   = 0;
199	irq_list[irq].dev_id  = NULL;
200	irq_list[irq].devname = NULL;
201}
202
203/*
204 * Do we need these probe functions on the m68k?
205 *
206 *  ... may be useful with ISA devices
207 */
208unsigned long probe_irq_on (void)
209{
210	return 0;
211}
212
213EXPORT_SYMBOL(probe_irq_on);
214
215int probe_irq_off (unsigned long irqs)
216{
217	return 0;
218}
219
220EXPORT_SYMBOL(probe_irq_off);
221
222asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
223{
224	if (vec >= VEC_INT1 && vec <= VEC_INT7) {
225		vec -= VEC_SPUR;
226		kstat_cpu(0).irqs[vec]++;
227		irq_list[vec].handler(vec, irq_list[vec].dev_id);
228	} else {
229		if (mach_process_int)
230			mach_process_int(vec, fp);
231		else
232			panic("Can't process interrupt vector %ld\n", vec);
233		return;
234	}
235}
236
237
238int show_interrupts(struct seq_file *p, void *v)
239{
240	int i = *(loff_t *) v;
241
242	if (i < NR_IRQS) {
243		if (! (irq_list[i].flags & IRQ_FLG_STD)) {
244			seq_printf(p, "%3d: %10u ", i,
245				(i ? kstat_cpu(0).irqs[i] : num_spurious));
246			if (irq_list[i].flags & IRQ_FLG_LOCK)
247				seq_printf(p, "L ");
248			else
249				seq_printf(p, "  ");
250			seq_printf(p, "%s\n", irq_list[i].devname);
251		}
252	}
253
254	if (i == NR_IRQS && mach_get_irq_list)
255		mach_get_irq_list(p, v);
256	return 0;
257}
258
259void init_irq_proc(void)
260{
261	/* Insert /proc/irq driver here */
262}
263