irq.c
来自「linux 内核源代码」· C语言 代码 · 共 675 行 · 第 1/2 页
C
675 行
sparc_irq[irq].flags |= SPARC_IRQ_INPROGRESS; kstat_cpu(cpu).irqs[irq]++; do { if (!action || !action->handler) unexpected_irq(irq, NULL, regs); action->handler(irq, action->dev_id); action = action->next; } while (action); sparc_irq[irq].flags &= ~SPARC_IRQ_INPROGRESS; enable_pil_irq(irq); irq_exit(); set_irq_regs(old_regs);}#if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)/* Fast IRQs on the Sparc can only have one routine attached to them, * thus no sharing possible. */static int request_fast_irq(unsigned int irq, void (*handler)(void), unsigned long irqflags, const char *devname){ struct irqaction *action; unsigned long flags; unsigned int cpu_irq; int ret;#ifdef CONFIG_SMP struct tt_entry *trap_table; extern struct tt_entry trapbase_cpu1, trapbase_cpu2, trapbase_cpu3;#endif cpu_irq = irq & (NR_IRQS - 1); if(cpu_irq > 14) { ret = -EINVAL; goto out; } if(!handler) { ret = -EINVAL; goto out; } spin_lock_irqsave(&irq_action_lock, flags); action = sparc_irq[cpu_irq].action; if(action) { if(action->flags & IRQF_SHARED) panic("Trying to register fast irq when already shared.\n"); if(irqflags & IRQF_SHARED) panic("Trying to register fast irq as shared.\n"); /* Anyway, someone already owns it so cannot be made fast. */ printk("request_fast_irq: Trying to register yet already owned.\n"); ret = -EBUSY; goto out_unlock; } /* If this is flagged as statically allocated then we use our * private struct which is never freed. */ if (irqflags & SA_STATIC_ALLOC) { if (static_irq_count < MAX_STATIC_ALLOC) action = &static_irqaction[static_irq_count++]; else printk("Fast IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n", irq, devname); } if (action == NULL) action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC); if (!action) { ret = -ENOMEM; goto out_unlock; } /* Dork with trap table if we get this far. */#define INSTANTIATE(table) \ table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_one = SPARC_RD_PSR_L0; \ table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two = \ SPARC_BRANCH((unsigned long) handler, \ (unsigned long) &table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two);\ table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_three = SPARC_RD_WIM_L3; \ table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_four = SPARC_NOP; INSTANTIATE(sparc_ttable)#ifdef CONFIG_SMP trap_table = &trapbase_cpu1; INSTANTIATE(trap_table) trap_table = &trapbase_cpu2; INSTANTIATE(trap_table) trap_table = &trapbase_cpu3; INSTANTIATE(trap_table)#endif#undef INSTANTIATE /* * XXX Correct thing whould be to flush only I- and D-cache lines * which contain the handler in question. But as of time of the * writing we have no CPU-neutral interface to fine-grained flushes. */ flush_cache_all(); action->flags = irqflags; cpus_clear(action->mask); action->name = devname; action->dev_id = NULL; action->next = NULL; sparc_irq[cpu_irq].action = action; __enable_irq(irq); ret = 0;out_unlock: spin_unlock_irqrestore(&irq_action_lock, flags);out: return ret;}/* These variables are used to access state from the assembler * interrupt handler, floppy_hardint, so we cannot put these in * the floppy driver image because that would not work in the * modular case. */volatile unsigned char *fdc_status;EXPORT_SYMBOL(fdc_status);char *pdma_vaddr;EXPORT_SYMBOL(pdma_vaddr);unsigned long pdma_size;EXPORT_SYMBOL(pdma_size);volatile int doing_pdma;EXPORT_SYMBOL(doing_pdma);char *pdma_base;EXPORT_SYMBOL(pdma_base);unsigned long pdma_areasize;EXPORT_SYMBOL(pdma_areasize);extern void floppy_hardint(void);static irq_handler_t floppy_irq_handler;void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs){ struct pt_regs *old_regs; int cpu = smp_processor_id(); old_regs = set_irq_regs(regs); disable_pil_irq(irq); irq_enter(); kstat_cpu(cpu).irqs[irq]++; floppy_irq_handler(irq, dev_id); irq_exit(); enable_pil_irq(irq); set_irq_regs(old_regs); // XXX Eek, it's totally changed with preempt_count() and such // if (softirq_pending(cpu)) // do_softirq();}int sparc_floppy_request_irq(int irq, unsigned long flags, irq_handler_t irq_handler){ floppy_irq_handler = irq_handler; return request_fast_irq(irq, floppy_hardint, flags, "floppy");}EXPORT_SYMBOL(sparc_floppy_request_irq);#endifint request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char * devname, void *dev_id){ struct irqaction * action, **actionp; unsigned long flags; unsigned int cpu_irq; int ret; if (sparc_cpu_model == sun4d) { extern int sun4d_request_irq(unsigned int, irq_handler_t , unsigned long, const char *, void *); return sun4d_request_irq(irq, handler, irqflags, devname, dev_id); } cpu_irq = irq & (NR_IRQS - 1); if(cpu_irq > 14) { ret = -EINVAL; goto out; } if (!handler) { ret = -EINVAL; goto out; } spin_lock_irqsave(&irq_action_lock, flags); actionp = &sparc_irq[cpu_irq].action; action = *actionp; if (action) { if (!(action->flags & IRQF_SHARED) || !(irqflags & IRQF_SHARED)) { ret = -EBUSY; goto out_unlock; } if ((action->flags & IRQF_DISABLED) != (irqflags & IRQF_DISABLED)) { printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq); ret = -EBUSY; goto out_unlock; } for ( ; action; action = *actionp) actionp = &action->next; } /* If this is flagged as statically allocated then we use our * private struct which is never freed. */ if (irqflags & SA_STATIC_ALLOC) { if (static_irq_count < MAX_STATIC_ALLOC) action = &static_irqaction[static_irq_count++]; else printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n", irq, devname); } if (action == NULL) action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC); if (!action) { ret = -ENOMEM; goto out_unlock; } action->handler = handler; action->flags = irqflags; cpus_clear(action->mask); action->name = devname; action->next = NULL; action->dev_id = dev_id; *actionp = action; __enable_irq(irq); ret = 0;out_unlock: spin_unlock_irqrestore(&irq_action_lock, flags);out: return ret;}EXPORT_SYMBOL(request_irq);void disable_irq_nosync(unsigned int irq){ return __disable_irq(irq);}EXPORT_SYMBOL(disable_irq_nosync);void disable_irq(unsigned int irq){ return __disable_irq(irq);}EXPORT_SYMBOL(disable_irq);void enable_irq(unsigned int irq){ return __enable_irq(irq);}EXPORT_SYMBOL(enable_irq);/* We really don't need these at all on the Sparc. We only have * stubs here because they are exported to modules. */unsigned long probe_irq_on(void){ return 0;}EXPORT_SYMBOL(probe_irq_on);int probe_irq_off(unsigned long mask){ return 0;}EXPORT_SYMBOL(probe_irq_off);/* djhr * This could probably be made indirect too and assigned in the CPU * bits of the code. That would be much nicer I think and would also * fit in with the idea of being able to tune your kernel for your machine * by removing unrequired machine and device support. * */void __init init_IRQ(void){ extern void sun4c_init_IRQ( void ); extern void sun4m_init_IRQ( void ); extern void sun4d_init_IRQ( void ); switch(sparc_cpu_model) { case sun4c: case sun4: sun4c_init_IRQ(); break; case sun4m:#ifdef CONFIG_PCI pcic_probe(); if (pcic_present()) { sun4m_pci_init_IRQ(); break; }#endif sun4m_init_IRQ(); break; case sun4d: sun4d_init_IRQ(); break; default: prom_printf("Cannot initialize IRQs on this Sun machine..."); break; } btfixup();}void init_irq_proc(void){ /* For now, nothing... */}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?