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