aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/irq_32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/kernel/irq_32.c')
-rw-r--r--arch/sparc/kernel/irq_32.c610
1 files changed, 152 insertions, 458 deletions
diff --git a/arch/sparc/kernel/irq_32.c b/arch/sparc/kernel/irq_32.c
index e1af43728329..9b89d842913c 100644
--- a/arch/sparc/kernel/irq_32.c
+++ b/arch/sparc/kernel/irq_32.c
@@ -1,8 +1,8 @@
1/* 1/*
2 * arch/sparc/kernel/irq.c: Interrupt request handling routines. On the 2 * Interrupt request handling routines. On the
3 * Sparc the IRQs are basically 'cast in stone' 3 * Sparc the IRQs are basically 'cast in stone'
4 * and you are supposed to probe the prom's device 4 * and you are supposed to probe the prom's device
5 * node trees to find out who's got which IRQ. 5 * node trees to find out who's got which IRQ.
6 * 6 *
7 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) 7 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
8 * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) 8 * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -11,40 +11,12 @@
11 * Copyright (C) 1998-2000 Anton Blanchard (anton@samba.org) 11 * Copyright (C) 1998-2000 Anton Blanchard (anton@samba.org)
12 */ 12 */
13 13
14#include <linux/module.h>
15#include <linux/sched.h>
16#include <linux/ptrace.h>
17#include <linux/errno.h>
18#include <linux/linkage.h>
19#include <linux/kernel_stat.h> 14#include <linux/kernel_stat.h>
20#include <linux/signal.h>
21#include <linux/interrupt.h>
22#include <linux/slab.h>
23#include <linux/random.h>
24#include <linux/init.h>
25#include <linux/smp.h>
26#include <linux/delay.h>
27#include <linux/threads.h>
28#include <linux/spinlock.h>
29#include <linux/seq_file.h> 15#include <linux/seq_file.h>
30 16
31#include <asm/ptrace.h>
32#include <asm/processor.h>
33#include <asm/system.h>
34#include <asm/psr.h>
35#include <asm/smp.h>
36#include <asm/vaddrs.h>
37#include <asm/timer.h>
38#include <asm/openprom.h>
39#include <asm/oplib.h>
40#include <asm/traps.h>
41#include <asm/irq.h>
42#include <asm/io.h>
43#include <asm/pgalloc.h>
44#include <asm/pgtable.h>
45#include <asm/pcic.h>
46#include <asm/cacheflush.h> 17#include <asm/cacheflush.h>
47#include <asm/irq_regs.h> 18#include <asm/cpudata.h>
19#include <asm/pcic.h>
48#include <asm/leon.h> 20#include <asm/leon.h>
49 21
50#include "kernel.h" 22#include "kernel.h"
@@ -57,7 +29,11 @@
57#define SMP_NOP2 29#define SMP_NOP2
58#define SMP_NOP3 30#define SMP_NOP3
59#endif /* SMP */ 31#endif /* SMP */
60unsigned long __raw_local_irq_save(void) 32
33/* platform specific irq setup */
34struct sparc_irq_config sparc_irq_config;
35
36unsigned long arch_local_irq_save(void)
61{ 37{
62 unsigned long retval; 38 unsigned long retval;
63 unsigned long tmp; 39 unsigned long tmp;
@@ -74,8 +50,9 @@ unsigned long __raw_local_irq_save(void)
74 50
75 return retval; 51 return retval;
76} 52}
53EXPORT_SYMBOL(arch_local_irq_save);
77 54
78void raw_local_irq_enable(void) 55void arch_local_irq_enable(void)
79{ 56{
80 unsigned long tmp; 57 unsigned long tmp;
81 58
@@ -89,8 +66,9 @@ void raw_local_irq_enable(void)
89 : "i" (PSR_PIL) 66 : "i" (PSR_PIL)
90 : "memory"); 67 : "memory");
91} 68}
69EXPORT_SYMBOL(arch_local_irq_enable);
92 70
93void raw_local_irq_restore(unsigned long old_psr) 71void arch_local_irq_restore(unsigned long old_psr)
94{ 72{
95 unsigned long tmp; 73 unsigned long tmp;
96 74
@@ -105,10 +83,7 @@ void raw_local_irq_restore(unsigned long old_psr)
105 : "i" (PSR_PIL), "r" (old_psr) 83 : "i" (PSR_PIL), "r" (old_psr)
106 : "memory"); 84 : "memory");
107} 85}
108 86EXPORT_SYMBOL(arch_local_irq_restore);
109EXPORT_SYMBOL(__raw_local_irq_save);
110EXPORT_SYMBOL(raw_local_irq_enable);
111EXPORT_SYMBOL(raw_local_irq_restore);
112 87
113/* 88/*
114 * Dave Redman (djhr@tadpole.co.uk) 89 * Dave Redman (djhr@tadpole.co.uk)
@@ -127,309 +102,185 @@ EXPORT_SYMBOL(raw_local_irq_restore);
127 * directed CPU interrupts using the existing enable/disable irq code 102 * directed CPU interrupts using the existing enable/disable irq code
128 * with tweaks. 103 * with tweaks.
129 * 104 *
105 * Sun4d complicates things even further. IRQ numbers are arbitrary
106 * 32-bit values in that case. Since this is similar to sparc64,
107 * we adopt a virtual IRQ numbering scheme as is done there.
108 * Virutal interrupt numbers are allocated by build_irq(). So NR_IRQS
109 * just becomes a limit of how many interrupt sources we can handle in
110 * a single system. Even fully loaded SS2000 machines top off at
111 * about 32 interrupt sources or so, therefore a NR_IRQS value of 64
112 * is more than enough.
113 *
114 * We keep a map of per-PIL enable interrupts. These get wired
115 * up via the irq_chip->startup() method which gets invoked by
116 * the generic IRQ layer during request_irq().
130 */ 117 */
131 118
132static void irq_panic(void)
133{
134 extern char *cputypval;
135 prom_printf("machine: %s doesn't have irq handlers defined!\n",cputypval);
136 prom_halt();
137}
138 119
139void (*sparc_init_timers)(irq_handler_t ) = 120/* Table of allocated irqs. Unused entries has irq == 0 */
140 (void (*)(irq_handler_t )) irq_panic; 121static struct irq_bucket irq_table[NR_IRQS];
122/* Protect access to irq_table */
123static DEFINE_SPINLOCK(irq_table_lock);
141 124
142/* 125/* Map between the irq identifier used in hw to the irq_bucket. */
143 * Dave Redman (djhr@tadpole.co.uk) 126struct irq_bucket *irq_map[SUN4D_MAX_IRQ];
144 * 127/* Protect access to irq_map */
145 * There used to be extern calls and hard coded values here.. very sucky! 128static DEFINE_SPINLOCK(irq_map_lock);
146 * instead, because some of the devices attach very early, I do something
147 * equally sucky but at least we'll never try to free statically allocated
148 * space or call kmalloc before kmalloc_init :(.
149 *
150 * In fact it's the timer10 that attaches first.. then timer14
151 * then kmalloc_init is called.. then the tty interrupts attach.
152 * hmmm....
153 *
154 */
155#define MAX_STATIC_ALLOC 4
156struct irqaction static_irqaction[MAX_STATIC_ALLOC];
157int static_irq_count;
158
159static struct {
160 struct irqaction *action;
161 int flags;
162} sparc_irq[NR_IRQS];
163#define SPARC_IRQ_INPROGRESS 1
164 129
165/* Used to protect the IRQ action lists */ 130/* Allocate a new irq from the irq_table */
166DEFINE_SPINLOCK(irq_action_lock); 131unsigned int irq_alloc(unsigned int real_irq, unsigned int pil)
167
168int show_interrupts(struct seq_file *p, void *v)
169{ 132{
170 int i = *(loff_t *) v;
171 struct irqaction * action;
172 unsigned long flags; 133 unsigned long flags;
173#ifdef CONFIG_SMP 134 unsigned int i;
174 int j;
175#endif
176 135
177 if (sparc_cpu_model == sun4d) { 136 spin_lock_irqsave(&irq_table_lock, flags);
178 extern int show_sun4d_interrupts(struct seq_file *, void *); 137 for (i = 1; i < NR_IRQS; i++) {
179 138 if (irq_table[i].real_irq == real_irq && irq_table[i].pil == pil)
180 return show_sun4d_interrupts(p, v); 139 goto found;
181 } 140 }
182 spin_lock_irqsave(&irq_action_lock, flags); 141
142 for (i = 1; i < NR_IRQS; i++) {
143 if (!irq_table[i].irq)
144 break;
145 }
146
183 if (i < NR_IRQS) { 147 if (i < NR_IRQS) {
184 action = sparc_irq[i].action; 148 irq_table[i].real_irq = real_irq;
185 if (!action) 149 irq_table[i].irq = i;
186 goto out_unlock; 150 irq_table[i].pil = pil;
187 seq_printf(p, "%3d: ", i); 151 } else {
188#ifndef CONFIG_SMP 152 printk(KERN_ERR "IRQ: Out of virtual IRQs.\n");
189 seq_printf(p, "%10u ", kstat_irqs(i)); 153 i = 0;
190#else
191 for_each_online_cpu(j) {
192 seq_printf(p, "%10u ",
193 kstat_cpu(j).irqs[i]);
194 }
195#endif
196 seq_printf(p, " %c %s",
197 (action->flags & IRQF_DISABLED) ? '+' : ' ',
198 action->name);
199 for (action=action->next; action; action = action->next) {
200 seq_printf(p, ",%s %s",
201 (action->flags & IRQF_DISABLED) ? " +" : "",
202 action->name);
203 }
204 seq_putc(p, '\n');
205 } 154 }
206out_unlock: 155found:
207 spin_unlock_irqrestore(&irq_action_lock, flags); 156 spin_unlock_irqrestore(&irq_table_lock, flags);
208 return 0; 157
158 return i;
209} 159}
210 160
211void free_irq(unsigned int irq, void *dev_id) 161/* Based on a single pil handler_irq may need to call several
162 * interrupt handlers. Use irq_map as entry to irq_table,
163 * and let each entry in irq_table point to the next entry.
164 */
165void irq_link(unsigned int irq)
212{ 166{
213 struct irqaction * action; 167 struct irq_bucket *p;
214 struct irqaction **actionp; 168 unsigned long flags;
215 unsigned long flags; 169 unsigned int pil;
216 unsigned int cpu_irq;
217
218 if (sparc_cpu_model == sun4d) {
219 extern void sun4d_free_irq(unsigned int, void *);
220
221 sun4d_free_irq(irq, dev_id);
222 return;
223 }
224 cpu_irq = irq & (NR_IRQS - 1);
225 if (cpu_irq > 14) { /* 14 irq levels on the sparc */
226 printk("Trying to free bogus IRQ %d\n", irq);
227 return;
228 }
229
230 spin_lock_irqsave(&irq_action_lock, flags);
231 170
232 actionp = &sparc_irq[cpu_irq].action; 171 BUG_ON(irq >= NR_IRQS);
233 action = *actionp;
234 172
235 if (!action->handler) { 173 spin_lock_irqsave(&irq_map_lock, flags);
236 printk("Trying to free free IRQ%d\n",irq);
237 goto out_unlock;
238 }
239 if (dev_id) {
240 for (; action; action = action->next) {
241 if (action->dev_id == dev_id)
242 break;
243 actionp = &action->next;
244 }
245 if (!action) {
246 printk("Trying to free free shared IRQ%d\n",irq);
247 goto out_unlock;
248 }
249 } else if (action->flags & IRQF_SHARED) {
250 printk("Trying to free shared IRQ%d with NULL device ID\n", irq);
251 goto out_unlock;
252 }
253 if (action->flags & SA_STATIC_ALLOC)
254 {
255 /* This interrupt is marked as specially allocated
256 * so it is a bad idea to free it.
257 */
258 printk("Attempt to free statically allocated IRQ%d (%s)\n",
259 irq, action->name);
260 goto out_unlock;
261 }
262 174
263 *actionp = action->next; 175 p = &irq_table[irq];
176 pil = p->pil;
177 BUG_ON(pil > SUN4D_MAX_IRQ);
178 p->next = irq_map[pil];
179 irq_map[pil] = p;
264 180
265 spin_unlock_irqrestore(&irq_action_lock, flags); 181 spin_unlock_irqrestore(&irq_map_lock, flags);
182}
266 183
267 synchronize_irq(irq); 184void irq_unlink(unsigned int irq)
185{
186 struct irq_bucket *p, **pnext;
187 unsigned long flags;
268 188
269 spin_lock_irqsave(&irq_action_lock, flags); 189 BUG_ON(irq >= NR_IRQS);
270 190
271 kfree(action); 191 spin_lock_irqsave(&irq_map_lock, flags);
272 192
273 if (!sparc_irq[cpu_irq].action) 193 p = &irq_table[irq];
274 __disable_irq(irq); 194 BUG_ON(p->pil > SUN4D_MAX_IRQ);
195 pnext = &irq_map[p->pil];
196 while (*pnext != p)
197 pnext = &(*pnext)->next;
198 *pnext = p->next;
275 199
276out_unlock: 200 spin_unlock_irqrestore(&irq_map_lock, flags);
277 spin_unlock_irqrestore(&irq_action_lock, flags);
278} 201}
279 202
280EXPORT_SYMBOL(free_irq);
281 203
282/* 204/* /proc/interrupts printing */
283 * This is called when we want to synchronize with 205int arch_show_interrupts(struct seq_file *p, int prec)
284 * interrupts. We may for example tell a device to
285 * stop sending interrupts: but to make sure there
286 * are no interrupts that are executing on another
287 * CPU we need to call this function.
288 */
289#ifdef CONFIG_SMP
290void synchronize_irq(unsigned int irq)
291{ 206{
292 unsigned int cpu_irq; 207 int j;
293
294 cpu_irq = irq & (NR_IRQS - 1);
295 while (sparc_irq[cpu_irq].flags & SPARC_IRQ_INPROGRESS)
296 cpu_relax();
297}
298EXPORT_SYMBOL(synchronize_irq);
299#endif /* SMP */
300 208
301void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs) 209#ifdef CONFIG_SMP
302{ 210 seq_printf(p, "RES: ");
303 int i; 211 for_each_online_cpu(j)
304 struct irqaction * action; 212 seq_printf(p, "%10u ", cpu_data(j).irq_resched_count);
305 unsigned int cpu_irq; 213 seq_printf(p, " IPI rescheduling interrupts\n");
306 214 seq_printf(p, "CAL: ");
307 cpu_irq = irq & (NR_IRQS - 1); 215 for_each_online_cpu(j)
308 action = sparc_irq[cpu_irq].action; 216 seq_printf(p, "%10u ", cpu_data(j).irq_call_count);
309 217 seq_printf(p, " IPI function call interrupts\n");
310 printk("IO device interrupt, irq = %d\n", irq); 218#endif
311 printk("PC = %08lx NPC = %08lx FP=%08lx\n", regs->pc, 219 seq_printf(p, "NMI: ");
312 regs->npc, regs->u_regs[14]); 220 for_each_online_cpu(j)
313 if (action) { 221 seq_printf(p, "%10u ", cpu_data(j).counter);
314 printk("Expecting: "); 222 seq_printf(p, " Non-maskable interrupts\n");
315 for (i = 0; i < 16; i++) 223 return 0;
316 if (action->handler)
317 printk("[%s:%d:0x%x] ", action->name,
318 (int) i, (unsigned int) action->handler);
319 }
320 printk("AIEEE\n");
321 panic("bogus interrupt received");
322} 224}
323 225
324void handler_irq(int irq, struct pt_regs * regs) 226void handler_irq(unsigned int pil, struct pt_regs *regs)
325{ 227{
326 struct pt_regs *old_regs; 228 struct pt_regs *old_regs;
327 struct irqaction * action; 229 struct irq_bucket *p;
328 int cpu = smp_processor_id();
329#ifdef CONFIG_SMP
330 extern void smp4m_irq_rotate(int cpu);
331#endif
332 230
231 BUG_ON(pil > 15);
333 old_regs = set_irq_regs(regs); 232 old_regs = set_irq_regs(regs);
334 irq_enter(); 233 irq_enter();
335 disable_pil_irq(irq); 234
336#ifdef CONFIG_SMP 235 p = irq_map[pil];
337 /* Only rotate on lower priority IRQs (scsi, ethernet, etc.). */ 236 while (p) {
338 if((sparc_cpu_model==sun4m) && (irq < 10)) 237 struct irq_bucket *next = p->next;
339 smp4m_irq_rotate(cpu); 238
340#endif 239 generic_handle_irq(p->irq);
341 action = sparc_irq[irq].action; 240 p = next;
342 sparc_irq[irq].flags |= SPARC_IRQ_INPROGRESS; 241 }
343 kstat_cpu(cpu).irqs[irq]++;
344 do {
345 if (!action || !action->handler)
346 unexpected_irq(irq, NULL, regs);
347 action->handler(irq, action->dev_id);
348 action = action->next;
349 } while (action);
350 sparc_irq[irq].flags &= ~SPARC_IRQ_INPROGRESS;
351 enable_pil_irq(irq);
352 irq_exit(); 242 irq_exit();
353 set_irq_regs(old_regs); 243 set_irq_regs(old_regs);
354} 244}
355 245
356#if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE) 246#if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)
247static unsigned int floppy_irq;
357 248
358/* Fast IRQs on the Sparc can only have one routine attached to them, 249int sparc_floppy_request_irq(unsigned int irq, irq_handler_t irq_handler)
359 * thus no sharing possible.
360 */
361static int request_fast_irq(unsigned int irq,
362 void (*handler)(void),
363 unsigned long irqflags, const char *devname)
364{ 250{
365 struct irqaction *action;
366 unsigned long flags;
367 unsigned int cpu_irq; 251 unsigned int cpu_irq;
368 int ret; 252 int err;
369#ifdef CONFIG_SMP 253
254#if defined CONFIG_SMP && !defined CONFIG_SPARC_LEON
370 struct tt_entry *trap_table; 255 struct tt_entry *trap_table;
371 extern struct tt_entry trapbase_cpu1, trapbase_cpu2, trapbase_cpu3;
372#endif 256#endif
373
374 cpu_irq = irq & (NR_IRQS - 1);
375 if(cpu_irq > 14) {
376 ret = -EINVAL;
377 goto out;
378 }
379 if(!handler) {
380 ret = -EINVAL;
381 goto out;
382 }
383 257
384 spin_lock_irqsave(&irq_action_lock, flags); 258 err = request_irq(irq, irq_handler, 0, "floppy", NULL);
259 if (err)
260 return -1;
385 261
386 action = sparc_irq[cpu_irq].action; 262 /* Save for later use in floppy interrupt handler */
387 if(action) { 263 floppy_irq = irq;
388 if(action->flags & IRQF_SHARED)
389 panic("Trying to register fast irq when already shared.\n");
390 if(irqflags & IRQF_SHARED)
391 panic("Trying to register fast irq as shared.\n");
392 264
393 /* Anyway, someone already owns it so cannot be made fast. */ 265 cpu_irq = (irq & (NR_IRQS - 1));
394 printk("request_fast_irq: Trying to register yet already owned.\n");
395 ret = -EBUSY;
396 goto out_unlock;
397 }
398
399 /* If this is flagged as statically allocated then we use our
400 * private struct which is never freed.
401 */
402 if (irqflags & SA_STATIC_ALLOC) {
403 if (static_irq_count < MAX_STATIC_ALLOC)
404 action = &static_irqaction[static_irq_count++];
405 else
406 printk("Fast IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n",
407 irq, devname);
408 }
409
410 if (action == NULL)
411 action = kmalloc(sizeof(struct irqaction),
412 GFP_ATOMIC);
413
414 if (!action) {
415 ret = -ENOMEM;
416 goto out_unlock;
417 }
418 266
419 /* Dork with trap table if we get this far. */ 267 /* Dork with trap table if we get this far. */
420#define INSTANTIATE(table) \ 268#define INSTANTIATE(table) \
421 table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_one = SPARC_RD_PSR_L0; \ 269 table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_one = SPARC_RD_PSR_L0; \
422 table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two = \ 270 table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two = \
423 SPARC_BRANCH((unsigned long) handler, \ 271 SPARC_BRANCH((unsigned long) floppy_hardint, \
424 (unsigned long) &table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two);\ 272 (unsigned long) &table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two);\
425 table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_three = SPARC_RD_WIM_L3; \ 273 table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_three = SPARC_RD_WIM_L3; \
426 table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_four = SPARC_NOP; 274 table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_four = SPARC_NOP;
427 275
428 INSTANTIATE(sparc_ttable) 276 INSTANTIATE(sparc_ttable)
429#ifdef CONFIG_SMP 277#if defined CONFIG_SMP && !defined CONFIG_SPARC_LEON
430 trap_table = &trapbase_cpu1; INSTANTIATE(trap_table) 278 trap_table = &trapbase_cpu1;
431 trap_table = &trapbase_cpu2; INSTANTIATE(trap_table) 279 INSTANTIATE(trap_table)
432 trap_table = &trapbase_cpu3; INSTANTIATE(trap_table) 280 trap_table = &trapbase_cpu2;
281 INSTANTIATE(trap_table)
282 trap_table = &trapbase_cpu3;
283 INSTANTIATE(trap_table)
433#endif 284#endif
434#undef INSTANTIATE 285#undef INSTANTIATE
435 /* 286 /*
@@ -438,24 +289,12 @@ static int request_fast_irq(unsigned int irq,
438 * writing we have no CPU-neutral interface to fine-grained flushes. 289 * writing we have no CPU-neutral interface to fine-grained flushes.
439 */ 290 */
440 flush_cache_all(); 291 flush_cache_all();
441 292 return 0;
442 action->flags = irqflags;
443 action->name = devname;
444 action->dev_id = NULL;
445 action->next = NULL;
446
447 sparc_irq[cpu_irq].action = action;
448
449 __enable_irq(irq);
450
451 ret = 0;
452out_unlock:
453 spin_unlock_irqrestore(&irq_action_lock, flags);
454out:
455 return ret;
456} 293}
294EXPORT_SYMBOL(sparc_floppy_request_irq);
457 295
458/* These variables are used to access state from the assembler 296/*
297 * These variables are used to access state from the assembler
459 * interrupt handler, floppy_hardint, so we cannot put these in 298 * interrupt handler, floppy_hardint, so we cannot put these in
460 * the floppy driver image because that would not work in the 299 * the floppy driver image because that would not work in the
461 * modular case. 300 * modular case.
@@ -478,155 +317,23 @@ EXPORT_SYMBOL(pdma_base);
478unsigned long pdma_areasize; 317unsigned long pdma_areasize;
479EXPORT_SYMBOL(pdma_areasize); 318EXPORT_SYMBOL(pdma_areasize);
480 319
481extern void floppy_hardint(void); 320/* Use the generic irq support to call floppy_interrupt
482 321 * which was setup using request_irq() in sparc_floppy_request_irq().
483static irq_handler_t floppy_irq_handler; 322 * We only have one floppy interrupt so we do not need to check
484 323 * for additional handlers being wired up by irq_link()
324 */
485void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs) 325void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs)
486{ 326{
487 struct pt_regs *old_regs; 327 struct pt_regs *old_regs;
488 int cpu = smp_processor_id();
489 328
490 old_regs = set_irq_regs(regs); 329 old_regs = set_irq_regs(regs);
491 disable_pil_irq(irq);
492 irq_enter(); 330 irq_enter();
493 kstat_cpu(cpu).irqs[irq]++; 331 generic_handle_irq(floppy_irq);
494 floppy_irq_handler(irq, dev_id);
495 irq_exit(); 332 irq_exit();
496 enable_pil_irq(irq);
497 set_irq_regs(old_regs); 333 set_irq_regs(old_regs);
498 // XXX Eek, it's totally changed with preempt_count() and such
499 // if (softirq_pending(cpu))
500 // do_softirq();
501} 334}
502
503int sparc_floppy_request_irq(int irq, unsigned long flags,
504 irq_handler_t irq_handler)
505{
506 floppy_irq_handler = irq_handler;
507 return request_fast_irq(irq, floppy_hardint, flags, "floppy");
508}
509EXPORT_SYMBOL(sparc_floppy_request_irq);
510
511#endif 335#endif
512 336
513int request_irq(unsigned int irq,
514 irq_handler_t handler,
515 unsigned long irqflags, const char * devname, void *dev_id)
516{
517 struct irqaction * action, **actionp;
518 unsigned long flags;
519 unsigned int cpu_irq;
520 int ret;
521
522 if (sparc_cpu_model == sun4d) {
523 extern int sun4d_request_irq(unsigned int,
524 irq_handler_t ,
525 unsigned long, const char *, void *);
526 return sun4d_request_irq(irq, handler, irqflags, devname, dev_id);
527 }
528 cpu_irq = irq & (NR_IRQS - 1);
529 if(cpu_irq > 14) {
530 ret = -EINVAL;
531 goto out;
532 }
533 if (!handler) {
534 ret = -EINVAL;
535 goto out;
536 }
537
538 spin_lock_irqsave(&irq_action_lock, flags);
539
540 actionp = &sparc_irq[cpu_irq].action;
541 action = *actionp;
542 if (action) {
543 if (!(action->flags & IRQF_SHARED) || !(irqflags & IRQF_SHARED)) {
544 ret = -EBUSY;
545 goto out_unlock;
546 }
547 if ((action->flags & IRQF_DISABLED) != (irqflags & IRQF_DISABLED)) {
548 printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
549 ret = -EBUSY;
550 goto out_unlock;
551 }
552 for ( ; action; action = *actionp)
553 actionp = &action->next;
554 }
555
556 /* If this is flagged as statically allocated then we use our
557 * private struct which is never freed.
558 */
559 if (irqflags & SA_STATIC_ALLOC) {
560 if (static_irq_count < MAX_STATIC_ALLOC)
561 action = &static_irqaction[static_irq_count++];
562 else
563 printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n", irq, devname);
564 }
565
566 if (action == NULL)
567 action = kmalloc(sizeof(struct irqaction),
568 GFP_ATOMIC);
569
570 if (!action) {
571 ret = -ENOMEM;
572 goto out_unlock;
573 }
574
575 action->handler = handler;
576 action->flags = irqflags;
577 action->name = devname;
578 action->next = NULL;
579 action->dev_id = dev_id;
580
581 *actionp = action;
582
583 __enable_irq(irq);
584
585 ret = 0;
586out_unlock:
587 spin_unlock_irqrestore(&irq_action_lock, flags);
588out:
589 return ret;
590}
591
592EXPORT_SYMBOL(request_irq);
593
594void disable_irq_nosync(unsigned int irq)
595{
596 __disable_irq(irq);
597}
598EXPORT_SYMBOL(disable_irq_nosync);
599
600void disable_irq(unsigned int irq)
601{
602 __disable_irq(irq);
603}
604EXPORT_SYMBOL(disable_irq);
605
606void enable_irq(unsigned int irq)
607{
608 __enable_irq(irq);
609}
610
611EXPORT_SYMBOL(enable_irq);
612
613/* We really don't need these at all on the Sparc. We only have
614 * stubs here because they are exported to modules.
615 */
616unsigned long probe_irq_on(void)
617{
618 return 0;
619}
620
621EXPORT_SYMBOL(probe_irq_on);
622
623int probe_irq_off(unsigned long mask)
624{
625 return 0;
626}
627
628EXPORT_SYMBOL(probe_irq_off);
629
630/* djhr 337/* djhr
631 * This could probably be made indirect too and assigned in the CPU 338 * This could probably be made indirect too and assigned in the CPU
632 * bits of the code. That would be much nicer I think and would also 339 * bits of the code. That would be much nicer I think and would also
@@ -637,27 +344,20 @@ EXPORT_SYMBOL(probe_irq_off);
637 344
638void __init init_IRQ(void) 345void __init init_IRQ(void)
639{ 346{
640 extern void sun4c_init_IRQ( void ); 347 switch (sparc_cpu_model) {
641 extern void sun4m_init_IRQ( void );
642 extern void sun4d_init_IRQ( void );
643
644 switch(sparc_cpu_model) {
645 case sun4c: 348 case sun4c:
646 case sun4: 349 case sun4:
647 sun4c_init_IRQ(); 350 sun4c_init_IRQ();
648 break; 351 break;
649 352
650 case sun4m: 353 case sun4m:
651#ifdef CONFIG_PCI
652 pcic_probe(); 354 pcic_probe();
653 if (pcic_present()) { 355 if (pcic_present())
654 sun4m_pci_init_IRQ(); 356 sun4m_pci_init_IRQ();
655 break; 357 else
656 } 358 sun4m_init_IRQ();
657#endif
658 sun4m_init_IRQ();
659 break; 359 break;
660 360
661 case sun4d: 361 case sun4d:
662 sun4d_init_IRQ(); 362 sun4d_init_IRQ();
663 break; 363 break;
@@ -673,9 +373,3 @@ void __init init_IRQ(void)
673 btfixup(); 373 btfixup();
674} 374}
675 375
676#ifdef CONFIG_PROC_FS
677void init_irq_proc(void)
678{
679 /* For now, nothing... */
680}
681#endif /* CONFIG_PROC_FS */