void free_irq(unsigned int irq, void *dev_id) { struct irqaction * action, **p; unsigned long flags; if (irq >= NR_IRQS) { printk("Trying to free IRQ%d\n",irq); return; } if (IS_RESERVED_IRQ(irq)) { printk("Trying to free reserved IRQ %d\n", irq); return; } for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { if (action->dev_id != dev_id) continue; /* Found it - now free it */ save_flags(flags); cli(); *p = action->next; if (!irq[irq_action]) mask_irq(irq); restore_flags(flags); kfree(action); return; } printk("Trying to free free IRQ%d\n",irq); }
int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void *dev_id) { int shared = 0; struct irqaction * action, **p; unsigned long flags; if (irq >= NR_IRQS) return -EINVAL; if (IS_RESERVED_IRQ(irq)) return -EINVAL; if (!handler) return -EINVAL; p = irq_action + irq; action = *p; if (action) { /* Can't share interrupts unless both agree to */ if (!(action->flags & irqflags & SA_SHIRQ)) return -EBUSY; /* Can't share interrupts unless both are same type */ if ((action->flags ^ irqflags) & SA_INTERRUPT) return -EBUSY; /* add new interrupt at end of irq queue */ do { p = &action->next; action = *p; } while (action); shared = 1; } action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); if (!action) return -ENOMEM; if (irqflags & SA_SAMPLE_RANDOM) rand_initialize_irq(irq); action->handler = handler; action->flags = irqflags; action->mask = 0; action->name = devname; action->next = NULL; action->dev_id = dev_id; save_flags(flags); cli(); *p = action; if (!shared) unmask_irq(irq); restore_flags(flags); return 0; }
/* * Routine to check and install requested interrupt. Just sets up logical * structures, doesn't alter interrupts at all. */ int uHALr_RequestInterrupt(unsigned int intNum, PrHandler handler, const unsigned char *devname) { struct uHALis_IRQ *action; if (intNum >= NR_IRQS) return -1; if (IS_RESERVED_IRQ(intNum)) return -1; if (!handler) return -1; action = &uHALv_IRQVector[intNum]; /* Can't share interrupts (yet) */ if (action->handler) return -1; action->handler = handler; action->name = devname; action->flags = 0; action->mask = 0; action->next = 0; return 0; }
/* Call this routine before trying to change the routine attached to an IRQ */ int uHALr_FreeInterrupt(unsigned int intNum) { if (intNum >= NR_IRQS) { uHALr_printf("Can't free Interrupt %d\n", intNum); return -1; } if (IS_RESERVED_IRQ(intNum)) { uHALr_printf("Can't free reserved Interrupt %d\n", intNum); return -1; } // Disable the interrupt & then remove the handler uHALr_DisableInterrupt(intNum); uHALv_IRQVector[intNum].handler = (PrHandler) 0; #ifdef DEBUG uHALr_printf("free'd Interrupt %d\n", intNum); #endif return 0; }