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