This source file includes following definitions.
- sun4c_disable_irq
- sun4m_disable_irq
- disable_irq
- sun4c_enable_irq
- sun4m_enable_irq
- enable_irq
- get_irq_list
- free_irq
- unexpected_irq
- handler_irq
- do_IRQ
- do_fast_IRQ
- request_fast_irq
- request_irq
- probe_irq_on
- probe_irq_off
- sun4c_init_IRQ
- sun4m_init_IRQ
- init_IRQ
1
2
3
4
5
6
7
8
9
10
11
12 #include <linux/ptrace.h>
13 #include <linux/errno.h>
14 #include <linux/linkage.h>
15 #include <linux/kernel_stat.h>
16 #include <linux/signal.h>
17 #include <linux/sched.h>
18 #include <linux/interrupt.h>
19
20 #include <asm/ptrace.h>
21 #include <asm/processor.h>
22 #include <asm/system.h>
23 #include <asm/psr.h>
24 #include <asm/vaddrs.h>
25 #include <asm/timer.h>
26 #include <asm/openprom.h>
27 #include <asm/oplib.h>
28 #include <asm/traps.h>
29 #include <asm/irq.h>
30 #include <asm/io.h>
31
32
33 unsigned char *interrupt_enable = 0;
34 struct sun4m_intregs *sun4m_interrupts;
35
36 void
37 sun4c_disable_irq(unsigned int irq_nr)
38 {
39 unsigned long flags;
40 unsigned char current_mask, new_mask;
41
42 if(sparc_cpu_model != sun4c)
43 return;
44 save_flags(flags); cli();
45 current_mask = *interrupt_enable;
46 switch(irq_nr) {
47 case 1:
48 new_mask = ((current_mask) & (~(SUN4C_INT_E1)));
49 break;
50 case 8:
51 new_mask = ((current_mask) & (~(SUN4C_INT_E8)));
52 break;
53 case 10:
54 new_mask = ((current_mask) & (~(SUN4C_INT_E10)));
55 break;
56 case 14:
57 new_mask = ((current_mask) & (~(SUN4C_INT_E14)));
58 break;
59 default:
60 restore_flags(flags);
61 return;
62 };
63
64 *interrupt_enable = new_mask;
65 restore_flags(flags);
66 }
67
68 void
69 sun4m_disable_irq(unsigned int irq_nr)
70 {
71 printk("IRQ routines not yet written for the sun4m\n");
72 panic("disable_irq: Unsupported arch.");
73 }
74
75 void
76 disable_irq(unsigned int irq_nr)
77 {
78 switch(sparc_cpu_model) {
79 case sun4c:
80 sun4c_disable_irq(irq_nr);
81 break;
82 case sun4m:
83 sun4m_disable_irq(irq_nr);
84 default:
85 panic("disable_irq: Unsupported arch.");
86 }
87 }
88
89 void
90 sun4c_enable_irq(unsigned int irq_nr)
91 {
92 unsigned long flags;
93 unsigned char current_mask, new_mask;
94
95 if(sparc_cpu_model != sun4c)
96 return;
97 save_flags(flags); cli();
98 current_mask = *interrupt_enable;
99 switch(irq_nr) {
100 case 1:
101 new_mask = ((current_mask) | SUN4C_INT_E1);
102 break;
103 case 8:
104 new_mask = ((current_mask) | SUN4C_INT_E8);
105 break;
106 case 10:
107 new_mask = ((current_mask) | SUN4C_INT_E10);
108 break;
109 case 14:
110 new_mask = ((current_mask) | SUN4C_INT_E14);
111 break;
112 default:
113 restore_flags(flags);
114 return;
115 };
116
117 *interrupt_enable = new_mask;
118 restore_flags(flags);
119 }
120
121 void
122 sun4m_enable_irq(unsigned int irq_nr)
123 {
124 printk("IRQ routines not written for the sun4m yet.\n");
125 panic("IRQ unsupported arch.");
126 }
127
128 void
129 enable_irq(unsigned int irq_nr)
130 {
131 switch(sparc_cpu_model) {
132 case sun4c:
133 sun4c_enable_irq(irq_nr);
134 break;
135 case sun4m:
136 sun4m_enable_irq(irq_nr);
137 break;
138 default:
139 panic("IRQ unsupported arch.");
140 }
141 }
142
143
144
145
146 struct irqaction {
147 void (*handler)(int, struct pt_regs *);
148 unsigned long flags;
149 unsigned long mask;
150 const char *name;
151 };
152
153 static struct irqaction irq_action[16] = {
154 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
155 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
156 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
157 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
158 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
159 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
160 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
161 { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }
162 };
163
164
165 int
166 get_irq_list(char *buf)
167 {
168 int i, len = 0;
169 struct irqaction * action = irq_action;
170
171 for (i = 0 ; i < 16 ; i++, action++) {
172 if (!action->handler)
173 continue;
174 len += sprintf(buf+len, "%2d: %8d %c %s\n",
175 i, kstat.interrupts[i],
176 (action->flags & SA_INTERRUPT) ? '+' : ' ',
177 action->name);
178 }
179 return len;
180 }
181
182 void
183 free_irq(unsigned int irq)
184 {
185 struct irqaction * action = irq + irq_action;
186 unsigned long flags;
187
188 if (irq > 14) {
189 printk("Trying to free bogus IRQ %d\n", irq);
190 return;
191 }
192 if (!action->handler) {
193 printk("Trying to free free IRQ%d\n", irq);
194 return;
195 }
196 save_flags(flags); cli();
197 disable_irq(irq);
198 action->handler = NULL;
199 action->flags = 0;
200 action->mask = 0;
201 action->name = NULL;
202 restore_flags(flags);
203 }
204
205 void
206 unexpected_irq(int irq, struct pt_regs * regs)
207 {
208 int i;
209
210 printk("IO device interrupt, irq = %d\n", irq);
211 printk("PC = %08lx NPC = %08lx FP=%08lx\n", regs->pc,
212 regs->npc, regs->u_regs[14]);
213 printk("Expecting: ");
214 for (i = 0; i < 16; i++)
215 if (irq_action[i].handler)
216 prom_printf("[%s:%d:0x%x] ", irq_action[i].name, (int) i,
217 (unsigned int) irq_action[i].handler);
218 printk("AIEEE\n");
219 panic("bogus interrupt received");
220 }
221
222 void
223 handler_irq(int irq, struct pt_regs * regs)
224 {
225 struct irqaction * action = irq_action + irq;
226
227 kstat.interrupts[irq]++;
228 if (!action->handler)
229 unexpected_irq(irq, regs);
230 else
231 action->handler(irq, regs);
232 }
233
234
235
236
237
238
239
240
241 asmlinkage void
242 do_IRQ(int irq, struct pt_regs * regs)
243 {
244 struct irqaction *action = irq + irq_action;
245
246 kstat.interrupts[irq]++;
247 action->handler(irq, regs);
248 return;
249 }
250
251
252
253
254
255
256 asmlinkage void
257 do_fast_IRQ(int irq)
258 {
259 kstat.interrupts[irq]++;
260 printk("Got FAST_IRQ number %04lx\n", (long unsigned int) irq);
261 return;
262 }
263
264 int
265 request_fast_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
266 unsigned long irqflags, const char *devname)
267 {
268 struct irqaction *action;
269 unsigned long flags;
270
271 if(irq > 14)
272 return -EINVAL;
273 action = irq + irq_action;
274 if(action->handler)
275 return -EBUSY;
276 if(!handler)
277 return -EINVAL;
278
279 save_flags(flags); cli();
280
281
282 sparc_ttable[SP_TRAP_IRQ1+(irq-1)].inst_one =
283 SPARC_BRANCH((unsigned long) handler,
284 (unsigned long) &sparc_ttable[SP_TRAP_IRQ1+(irq-1)].inst_one);
285 sparc_ttable[SP_TRAP_IRQ1+(irq-1)].inst_two = SPARC_RD_PSR_L0;
286 sparc_ttable[SP_TRAP_IRQ1+(irq-1)].inst_three = SPARC_NOP;
287 sparc_ttable[SP_TRAP_IRQ1+(irq-1)].inst_four = SPARC_NOP;
288
289 action->handler = handler;
290 action->flags = irqflags;
291 action->mask = 0;
292 action->name = devname;
293
294 restore_flags(flags);
295 return 0;
296 }
297
298 extern void probe_clock(void);
299
300 int
301 request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
302 unsigned long irqflags, const char * devname)
303 {
304 struct irqaction *action;
305 unsigned long flags;
306
307 if(irq > 14)
308 return -EINVAL;
309
310 action = irq + irq_action;
311 if(action->handler)
312 return -EBUSY;
313 if(!handler)
314 return -EINVAL;
315
316 save_flags(flags); cli();
317 action->handler = handler;
318 action->flags = irqflags;
319 action->mask = 0;
320 action->name = devname;
321 enable_irq(irq);
322 if(irq == 10)
323 probe_clock();
324 restore_flags(flags);
325 return 0;
326 }
327
328
329
330
331 unsigned long probe_irq_on(void)
332 {
333 return 0;
334 }
335
336 int probe_irq_off(unsigned long mask)
337 {
338 return 0;
339 }
340
341 void
342 sun4c_init_IRQ(void)
343 {
344 struct linux_prom_registers int_regs[2];
345 int ie_node;
346
347 ie_node = prom_searchsiblings (prom_getchild(prom_root_node),
348 "interrupt-enable");
349 if(ie_node == 0)
350 panic("Cannot find /interrupt-enable node");
351
352 prom_getproperty(ie_node, "reg", (char *) int_regs, sizeof(int_regs));
353 sparc_alloc_io(int_regs[0].phys_addr, (void *) INTREG_VADDR,
354 int_regs[0].reg_size, "sun4c_interrupts",
355 int_regs[0].which_io, 0x0);
356
357 interrupt_enable = (char *) INTREG_VADDR;
358
359
360 *interrupt_enable = (SUN4C_INT_ENABLE);
361 sti();
362 }
363
364 void
365 sun4m_init_IRQ(void)
366 {
367 int ie_node;
368
369 struct linux_prom_registers int_regs[PROMREG_MAX];
370 int num_regs;
371
372 cli();
373
374 if((ie_node = prom_searchsiblings(prom_getchild(prom_root_node), "obio")) == 0 ||
375 (ie_node = prom_getchild (ie_node)) == 0 ||
376 (ie_node = prom_searchsiblings (ie_node, "interrupt")) == 0)
377 panic("Cannot find /obio/interrupt node\n");
378 num_regs = prom_getproperty(ie_node, "reg", (char *) int_regs,
379 sizeof(int_regs));
380 num_regs = (num_regs/sizeof(struct linux_prom_registers));
381
382
383 prom_apply_obio_ranges(int_regs, num_regs);
384
385
386 sparc_alloc_io(int_regs[0].phys_addr, (void *) INTREG_VADDR,
387 PAGE_SIZE*NCPUS, "interrupts_percpu",
388 int_regs[0].which_io, 0x0);
389
390
391 sparc_alloc_io(int_regs[num_regs-1].phys_addr,
392 (void *) INTREG_VADDR+(NCPUS*PAGE_SIZE),
393 int_regs[num_regs-1].reg_size, "interrupts_system",
394 int_regs[num_regs-1].which_io, 0x0);
395
396 sun4m_interrupts = (struct sun4m_intregs *) INTREG_VADDR;
397 sti();
398 }
399
400 void
401 init_IRQ(void)
402 {
403 switch(sparc_cpu_model) {
404 case sun4c:
405 sun4c_init_IRQ();
406 break;
407 case sun4m:
408 sun4m_init_IRQ();
409 break;
410 default:
411 panic("Cannot initialize IRQ's on this Sun machine...");
412 break;
413 };
414 }