📄 irq.c
字号:
__save_flags(flags); if ((flags & PSR_PIL) != PSR_PIL) local_enabled = 1; /* default to local */ retval = 2 + local_enabled; /* check for global flags if we're not in an interrupt */ if (!local_irq_count(smp_processor_id())) { if (local_enabled) retval = 1; if (global_irq_holder == (unsigned char) smp_processor_id()) retval = 0; } return retval;}void __global_restore_flags(unsigned long flags){ switch (flags) { case 0: __global_cli(); break; case 1: __global_sti(); break; case 2: __cli(); break; case 3: __sti(); break; default: { unsigned long pc; __asm__ __volatile__("mov %%i7, %0" : "=r" (pc)); printk("global_restore_flags: Bogon flags(%08lx) caller %08lx\n", flags, pc); } }}#endif /* CONFIG_SMP */void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs){ int i; struct irqaction * action; unsigned int cpu_irq; cpu_irq = irq & NR_IRQS; action = *(cpu_irq + irq_action); printk("IO device interrupt, irq = %d\n", irq); printk("PC = %08lx NPC = %08lx FP=%08lx\n", regs->pc, regs->npc, regs->u_regs[14]); if (action) { printk("Expecting: "); for (i = 0; i < 16; i++) if (action->handler) prom_printf("[%s:%d:0x%x] ", action->name, (int) i, (unsigned int) action->handler); } printk("AIEEE\n"); panic("bogus interrupt received");}void handler_irq(int irq, struct pt_regs * regs){ struct irqaction * action; int cpu = smp_processor_id();#ifdef CONFIG_SMP extern void smp4m_irq_rotate(int cpu);#endif irq_enter(cpu, irq); disable_pil_irq(irq);#ifdef CONFIG_SMP /* Only rotate on lower priority IRQ's (scsi, ethernet, etc.). */ if(irq < 10) smp4m_irq_rotate(cpu);#endif action = *(irq + irq_action); kstat.irqs[cpu][irq]++; do { if (!action || !action->handler) unexpected_irq(irq, 0, regs); action->handler(irq, action->dev_id, regs); action = action->next; } while (action); enable_pil_irq(irq); irq_exit(cpu, irq);}#ifdef CONFIG_BLK_DEV_FDextern void floppy_interrupt(int irq, void *dev_id, struct pt_regs *regs);void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs){ int cpu = smp_processor_id(); disable_pil_irq(irq); irq_enter(cpu, irq); kstat.irqs[cpu][irq]++; floppy_interrupt(irq, dev_id, regs); irq_exit(cpu, irq); enable_pil_irq(irq);}#endif/* Fast IRQ's on the Sparc can only have one routine attached to them, * thus no sharing possible. */int request_fast_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char *devname){ struct irqaction *action; unsigned long flags; unsigned int cpu_irq;#ifdef CONFIG_SMP struct tt_entry *trap_table; extern struct tt_entry trapbase_cpu1, trapbase_cpu2, trapbase_cpu3;#endif cpu_irq = irq & NR_IRQS; if(cpu_irq > 14) return -EINVAL; if(!handler) return -EINVAL; action = *(cpu_irq + irq_action); if(action) { if(action->flags & SA_SHIRQ) panic("Trying to register fast irq when already shared.\n"); if(irqflags & SA_SHIRQ) 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"); return -EBUSY; } save_and_cli(flags); /* 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 = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); if (!action) { restore_flags(flags); return -ENOMEM; } /* 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->handler = handler; action->flags = irqflags; action->mask = 0; action->name = devname; action->dev_id = NULL; action->next = NULL; *(cpu_irq + irq_action) = action; enable_irq(irq); restore_flags(flags); return 0;}int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void *dev_id){ struct irqaction * action, *tmp = NULL; unsigned long flags; unsigned int cpu_irq; if (sparc_cpu_model == sun4d) { extern int sun4d_request_irq(unsigned int, void (*)(int, void *, struct pt_regs *), unsigned long, const char *, void *); return sun4d_request_irq(irq, handler, irqflags, devname, dev_id); } cpu_irq = irq & NR_IRQS; if(cpu_irq > 14) return -EINVAL; if (!handler) return -EINVAL; action = *(cpu_irq + irq_action); if (action) { if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) { for (tmp = action; tmp->next; tmp = tmp->next); } else { return -EBUSY; } if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) { printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq); return -EBUSY; } action = NULL; /* Or else! */ } save_and_cli(flags); /* 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 = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); if (!action) { restore_flags(flags); return -ENOMEM; } action->handler = handler; action->flags = irqflags; action->mask = 0; action->name = devname; action->next = NULL; action->dev_id = dev_id; if (tmp) tmp->next = action; else *(cpu_irq + irq_action) = action; enable_irq(irq); restore_flags(flags); return 0;}/* 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;}int probe_irq_off(unsigned long mask){ return 0;}/* 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 IRQ's on this Sun machine..."); break; } btfixup();}void init_irq_proc(void){ /* For now, nothing... */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -