]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) | |
3 | * Licensed under the GPL | |
4 | * Derived (i.e. mostly copied) from arch/i386/kernel/irq.c: | |
5 | * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar | |
6 | */ | |
7 | ||
8 | #include "linux/config.h" | |
9 | #include "linux/kernel.h" | |
10 | #include "linux/module.h" | |
11 | #include "linux/smp.h" | |
12 | #include "linux/irq.h" | |
13 | #include "linux/kernel_stat.h" | |
14 | #include "linux/interrupt.h" | |
15 | #include "linux/random.h" | |
16 | #include "linux/slab.h" | |
17 | #include "linux/file.h" | |
18 | #include "linux/proc_fs.h" | |
19 | #include "linux/init.h" | |
20 | #include "linux/seq_file.h" | |
21 | #include "linux/profile.h" | |
22 | #include "linux/hardirq.h" | |
23 | #include "asm/irq.h" | |
24 | #include "asm/hw_irq.h" | |
25 | #include "asm/atomic.h" | |
26 | #include "asm/signal.h" | |
27 | #include "asm/system.h" | |
28 | #include "asm/errno.h" | |
29 | #include "asm/uaccess.h" | |
30 | #include "user_util.h" | |
31 | #include "kern_util.h" | |
32 | #include "irq_user.h" | |
33 | #include "irq_kern.h" | |
34 | ||
35 | ||
36 | /* | |
37 | * Generic, controller-independent functions: | |
38 | */ | |
39 | ||
40 | int show_interrupts(struct seq_file *p, void *v) | |
41 | { | |
42 | int i = *(loff_t *) v, j; | |
43 | struct irqaction * action; | |
44 | unsigned long flags; | |
45 | ||
46 | if (i == 0) { | |
47 | seq_printf(p, " "); | |
48 | for_each_online_cpu(j) | |
49 | seq_printf(p, "CPU%d ",j); | |
50 | seq_putc(p, '\n'); | |
51 | } | |
52 | ||
53 | if (i < NR_IRQS) { | |
54 | spin_lock_irqsave(&irq_desc[i].lock, flags); | |
55 | action = irq_desc[i].action; | |
56 | if (!action) | |
57 | goto skip; | |
58 | seq_printf(p, "%3d: ",i); | |
59 | #ifndef CONFIG_SMP | |
60 | seq_printf(p, "%10u ", kstat_irqs(i)); | |
61 | #else | |
62 | for_each_online_cpu(j) | |
63 | seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); | |
64 | #endif | |
65 | seq_printf(p, " %14s", irq_desc[i].handler->typename); | |
66 | seq_printf(p, " %s", action->name); | |
67 | ||
68 | for (action=action->next; action; action = action->next) | |
69 | seq_printf(p, ", %s", action->name); | |
70 | ||
71 | seq_putc(p, '\n'); | |
72 | skip: | |
73 | spin_unlock_irqrestore(&irq_desc[i].lock, flags); | |
74 | } else if (i == NR_IRQS) { | |
75 | seq_putc(p, '\n'); | |
76 | } | |
77 | ||
78 | return 0; | |
79 | } | |
80 | ||
81 | /* | |
82 | * do_IRQ handles all normal device IRQ's (the special | |
83 | * SMP cross-CPU interrupts have their own specific | |
84 | * handlers). | |
85 | */ | |
86 | unsigned int do_IRQ(int irq, union uml_pt_regs *regs) | |
87 | { | |
88 | irq_enter(); | |
89 | __do_IRQ(irq, (struct pt_regs *) regs); | |
90 | irq_exit(); | |
91 | return 1; | |
92 | } | |
93 | ||
94 | int um_request_irq(unsigned int irq, int fd, int type, | |
95 | irqreturn_t (*handler)(int, void *, struct pt_regs *), | |
96 | unsigned long irqflags, const char * devname, | |
97 | void *dev_id) | |
98 | { | |
99 | int err; | |
100 | ||
101 | err = request_irq(irq, handler, irqflags, devname, dev_id); | |
102 | if(err) | |
103 | return(err); | |
104 | ||
105 | if(fd != -1) | |
106 | err = activate_fd(irq, fd, type, dev_id); | |
107 | return(err); | |
108 | } | |
109 | EXPORT_SYMBOL(um_request_irq); | |
110 | EXPORT_SYMBOL(reactivate_fd); | |
111 | ||
112 | static DEFINE_SPINLOCK(irq_spinlock); | |
113 | ||
114 | unsigned long irq_lock(void) | |
115 | { | |
116 | unsigned long flags; | |
117 | ||
118 | spin_lock_irqsave(&irq_spinlock, flags); | |
119 | return(flags); | |
120 | } | |
121 | ||
122 | void irq_unlock(unsigned long flags) | |
123 | { | |
124 | spin_unlock_irqrestore(&irq_spinlock, flags); | |
125 | } | |
126 | ||
127 | /* presently hw_interrupt_type must define (startup || enable) && | |
128 | * disable && end */ | |
129 | static void dummy(unsigned int irq) | |
130 | { | |
131 | } | |
132 | ||
133 | static struct hw_interrupt_type SIGIO_irq_type = { | |
134 | .typename = "SIGIO", | |
135 | .disable = dummy, | |
136 | .enable = dummy, | |
137 | .ack = dummy, | |
138 | .end = dummy | |
139 | }; | |
140 | ||
141 | static struct hw_interrupt_type SIGVTALRM_irq_type = { | |
142 | .typename = "SIGVTALRM", | |
143 | .shutdown = dummy, /* never called */ | |
144 | .disable = dummy, | |
145 | .enable = dummy, | |
146 | .ack = dummy, | |
147 | .end = dummy | |
148 | }; | |
149 | ||
150 | void __init init_IRQ(void) | |
151 | { | |
152 | int i; | |
153 | ||
154 | irq_desc[TIMER_IRQ].status = IRQ_DISABLED; | |
155 | irq_desc[TIMER_IRQ].action = NULL; | |
156 | irq_desc[TIMER_IRQ].depth = 1; | |
157 | irq_desc[TIMER_IRQ].handler = &SIGVTALRM_irq_type; | |
158 | enable_irq(TIMER_IRQ); | |
159 | for(i=1;i<NR_IRQS;i++){ | |
160 | irq_desc[i].status = IRQ_DISABLED; | |
161 | irq_desc[i].action = NULL; | |
162 | irq_desc[i].depth = 1; | |
163 | irq_desc[i].handler = &SIGIO_irq_type; | |
164 | enable_irq(i); | |
165 | } | |
1da177e4 LT |
166 | } |
167 | ||
168 | /* | |
169 | * Overrides for Emacs so that we follow Linus's tabbing style. | |
170 | * Emacs will notice this stuff at the end of the file and automatically | |
171 | * adjust the settings for this buffer only. This must remain at the end | |
172 | * of the file. | |
173 | * --------------------------------------------------------------------------- | |
174 | * Local variables: | |
175 | * c-file-style: "linux" | |
176 | * End: | |
177 | */ |