irq.c 2.5 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * arch/sh64/kernel/irq.c
 *
 * Copyright (C) 2000, 2001  Paolo Alberelli
 * Copyright (C) 2003  Paul Mundt
 *
 */

/*
 * IRQs are in fact implemented a bit like signal handlers for the kernel.
 * Naturally it's not a 1:1 relation, but there are similarities.
 */

#include <linux/errno.h>
#include <linux/kernel_stat.h>
#include <linux/signal.h>
#include <linux/rwsem.h>
#include <linux/sched.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/timex.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/smp.h>
#include <linux/init.h>
#include <linux/seq_file.h>
#include <linux/bitops.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/smp.h>
#include <asm/pgalloc.h>
#include <asm/delay.h>
#include <asm/irq.h>
#include <linux/irq.h>

void ack_bad_irq(unsigned int irq)
{
	printk("unexpected IRQ trap at irq %02x\n", irq);
}

#if defined(CONFIG_PROC_FS)
int show_interrupts(struct seq_file *p, void *v)
{
	int i = *(loff_t *) v, j;
	struct irqaction * action;
	unsigned long flags;

	if (i == 0) {
		seq_puts(p, "           ");
54 55
		for_each_online_cpu(j)
			seq_printf(p, "CPU%d       ",j);
L
Linus Torvalds 已提交
56 57 58 59 60 61 62 63 64 65
		seq_putc(p, '\n');
	}

	if (i < NR_IRQS) {
		spin_lock_irqsave(&irq_desc[i].lock, flags);
		action = irq_desc[i].action;
		if (!action)
			goto unlock;
		seq_printf(p, "%3d: ",i);
		seq_printf(p, "%10u ", kstat_irqs(i));
66
		seq_printf(p, " %14s", irq_desc[i].chip->typename);
L
Linus Torvalds 已提交
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
		seq_printf(p, "  %s", action->name);

		for (action=action->next; action; action = action->next)
			seq_printf(p, ", %s", action->name);
		seq_putc(p, '\n');
unlock:
		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
	}
	return 0;
}
#endif

/*
 * do_NMI handles all Non-Maskable Interrupts.
 */
asmlinkage void do_NMI(unsigned long vector_num, struct pt_regs * regs)
{
	if (regs->sr & 0x40000000)
		printk("unexpected NMI trap in system mode\n");
	else
		printk("unexpected NMI trap in user mode\n");

	/* No statistics */
}

/*
 * do_IRQ handles all normal device IRQ's.
 */
asmlinkage int do_IRQ(unsigned long vector_num, struct pt_regs * regs)
{
97
	struct pt_regs *old_regs = set_irq_regs(regs);
L
Linus Torvalds 已提交
98 99 100 101 102 103 104
	int irq;

	irq_enter();

	irq = irq_demux(vector_num);

	if (irq >= 0) {
105
		__do_IRQ(irq);
L
Linus Torvalds 已提交
106 107 108 109 110 111
	} else {
		printk("unexpected IRQ trap at vector %03lx\n", vector_num);
	}

	irq_exit();

112
	set_irq_regs(old_regs);
L
Linus Torvalds 已提交
113 114 115
	return 1;
}