2 * linux/arch/m68knommu/kernel/ints.c -- General interrupt handling code
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)
11 * linux/arch/m68k/kernel/ints.c -- Linux/m68k general interrupt handling code
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
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>
27 #include <asm/system.h>
29 #include <asm/irqnode.h>
30 #include <asm/traps.h>
32 #include <asm/machdep.h>
35 * This table stores the address info for each vector handler.
37 irq_handler_t irq_list
[SYS_IRQS
];
39 #define NUM_IRQ_NODES 16
40 static irq_node_t nodes
[NUM_IRQ_NODES
];
42 /* The number of spurious interrupts */
43 volatile unsigned int num_spurious
;
45 unsigned int local_bh_count
[NR_CPUS
];
46 unsigned int local_irq_count
[NR_CPUS
];
48 static irqreturn_t
default_irq_handler(int irq
, void *ptr
, struct pt_regs
*regs
)
51 printk(KERN_INFO
"%s(%d): default irq handler vec=%d [0x%x]\n",
52 __FILE__
, __LINE__
, irq
, irq
);
64 * This function should be called during kernel startup to initialize
65 * the IRQ handling routines.
68 void __init
init_IRQ(void)
72 for (i
= 0; i
< SYS_IRQS
; i
++) {
73 if (mach_default_handler
)
74 irq_list
[i
].handler
= (*mach_default_handler
)[i
];
76 irq_list
[i
].handler
= default_irq_handler
;
77 irq_list
[i
].flags
= IRQ_FLG_STD
;
78 irq_list
[i
].dev_id
= NULL
;
79 irq_list
[i
].devname
= NULL
;
82 for (i
= 0; i
< NUM_IRQ_NODES
; i
++)
83 nodes
[i
].handler
= NULL
;
89 irq_node_t
*new_irq_node(void)
94 for (node
= nodes
, i
= NUM_IRQ_NODES
-1; i
>= 0; node
++, i
--)
98 printk(KERN_INFO
"new_irq_node: out of nodes\n");
104 irqreturn_t (*handler
)(int, void *, struct pt_regs
*),
109 if (irq
< 0 || irq
>= NR_IRQS
) {
110 printk(KERN_WARNING
"%s: Incorrect IRQ %d from %s\n", __FUNCTION__
,
115 if (!(irq_list
[irq
].flags
& IRQ_FLG_STD
)) {
116 if (irq_list
[irq
].flags
& IRQ_FLG_LOCK
) {
117 printk(KERN_WARNING
"%s: IRQ %d from %s is not replaceable\n",
118 __FUNCTION__
, irq
, irq_list
[irq
].devname
);
121 if (flags
& IRQ_FLG_REPLACE
) {
122 printk(KERN_WARNING
"%s: %s can't replace IRQ %d from %s\n",
123 __FUNCTION__
, devname
, irq
, irq_list
[irq
].devname
);
128 if (flags
& IRQ_FLG_FAST
) {
129 extern asmlinkage
void fasthandler(void);
130 extern void set_evector(int vecnum
, void (*handler
)(void));
131 set_evector(irq
, fasthandler
);
134 irq_list
[irq
].handler
= handler
;
135 irq_list
[irq
].flags
= flags
;
136 irq_list
[irq
].dev_id
= dev_id
;
137 irq_list
[irq
].devname
= devname
;
141 EXPORT_SYMBOL(request_irq
);
143 void free_irq(unsigned int irq
, void *dev_id
)
145 if (irq
>= NR_IRQS
) {
146 printk(KERN_WARNING
"%s: Incorrect IRQ %d\n", __FUNCTION__
, irq
);
150 if (irq_list
[irq
].dev_id
!= dev_id
)
151 printk(KERN_WARNING
"%s: Removing probably wrong IRQ %d from %s\n",
152 __FUNCTION__
, irq
, irq_list
[irq
].devname
);
154 if (irq_list
[irq
].flags
& IRQ_FLG_FAST
) {
155 extern asmlinkage
void inthandler(void);
156 extern void set_evector(int vecnum
, void (*handler
)(void));
157 set_evector(irq
, inthandler
);
160 if (mach_default_handler
)
161 irq_list
[irq
].handler
= (*mach_default_handler
)[irq
];
163 irq_list
[irq
].handler
= default_irq_handler
;
164 irq_list
[irq
].flags
= IRQ_FLG_STD
;
165 irq_list
[irq
].dev_id
= NULL
;
166 irq_list
[irq
].devname
= NULL
;
169 EXPORT_SYMBOL(free_irq
);
172 int sys_request_irq(unsigned int irq
,
173 irqreturn_t (*handler
)(int, void *, struct pt_regs
*),
174 unsigned long flags
, const char *devname
, void *dev_id
)
177 printk(KERN_WARNING
"%s: Incorrect IRQ %d from %s\n",
178 __FUNCTION__
, irq
, devname
);
183 if (!(irq_list
[irq
].flags
& IRQ_FLG_STD
)) {
184 if (irq_list
[irq
].flags
& IRQ_FLG_LOCK
) {
185 printk(KERN_WARNING
"%s: IRQ %d from %s is not replaceable\n",
186 __FUNCTION__
, irq
, irq_list
[irq
].devname
);
189 if (!(flags
& IRQ_FLG_REPLACE
)) {
190 printk(KERN_WARNING
"%s: %s can't replace IRQ %d from %s\n",
191 __FUNCTION__
, devname
, irq
, irq_list
[irq
].devname
);
197 irq_list
[irq
].handler
= handler
;
198 irq_list
[irq
].flags
= flags
;
199 irq_list
[irq
].dev_id
= dev_id
;
200 irq_list
[irq
].devname
= devname
;
204 void sys_free_irq(unsigned int irq
, void *dev_id
)
207 printk(KERN_WARNING
"%s: Incorrect IRQ %d\n", __FUNCTION__
, irq
);
211 if (irq_list
[irq
].dev_id
!= dev_id
)
212 printk(KERN_WARNING
"%s: Removing probably wrong IRQ %d from %s\n",
213 __FUNCTION__
, irq
, irq_list
[irq
].devname
);
215 irq_list
[irq
].handler
= (*mach_default_handler
)[irq
];
216 irq_list
[irq
].flags
= 0;
217 irq_list
[irq
].dev_id
= NULL
;
218 irq_list
[irq
].devname
= NULL
;
222 * Do we need these probe functions on the m68k?
224 * ... may be useful with ISA devices
226 unsigned long probe_irq_on (void)
231 EXPORT_SYMBOL(probe_irq_on
);
233 int probe_irq_off (unsigned long irqs
)
238 EXPORT_SYMBOL(probe_irq_off
);
240 asmlinkage
void process_int(unsigned long vec
, struct pt_regs
*fp
)
242 if (vec
>= VEC_INT1
&& vec
<= VEC_INT7
) {
244 kstat_cpu(0).irqs
[vec
]++;
245 irq_list
[vec
].handler(vec
, irq_list
[vec
].dev_id
, fp
);
247 if (mach_process_int
)
248 mach_process_int(vec
, fp
);
250 panic("Can't process interrupt vector %ld\n", vec
);
256 int show_interrupts(struct seq_file
*p
, void *v
)
258 int i
= *(loff_t
*) v
;
261 if (! (irq_list
[i
].flags
& IRQ_FLG_STD
)) {
262 seq_printf(p
, "%3d: %10u ", i
,
263 (i
? kstat_cpu(0).irqs
[i
] : num_spurious
));
264 if (irq_list
[i
].flags
& IRQ_FLG_LOCK
)
268 seq_printf(p
, "%s\n", irq_list
[i
].devname
);
272 if (i
== NR_IRQS
&& mach_get_irq_list
)
273 mach_get_irq_list(p
, v
);
277 void init_irq_proc(void)
279 /* Insert /proc/irq driver here */