/* * Deregister an interrupt handler. */ void sa11x0_intr_disestablish(sa11x0_chipset_tag_t ic, void *arg) { struct irqhandler *ih = arg; int irq = ih->ih_irq; int saved_cpsr; struct irqhandler **p, *q; #if DIAGNOSTIC if (irq < 0 || irq >= ICU_LEN) panic("intr_disestablish: bogus irq"); #endif /* * Remove the handler from the chain. * This is O(n^2), too. */ for (p = &irqhandlers[irq]; (q = *p) != NULL && q != ih; p = &q->ih_next) ; if (q) *p = q->ih_next; else panic("intr_disestablish: handler not registered"); free(ih, M_DEVBUF); intr_calculatemasks(); saved_cpsr = SetCPSR(I32_bit, I32_bit); set_spl_masks(); irq_setmasks(); SetCPSR(I32_bit, saved_cpsr & I32_bit); }
void * sa11x0_intr_establish(sa11x0_chipset_tag_t ic, int irq, int type, int level, int (*ih_fun)(void *), void *ih_arg) { int saved_cpsr; struct irqhandler **p, *q, *ih; static struct irqhandler fakehand = {fakeintr}; /* no point in sleeping unless someone can free memory. */ ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK); if (ih == NULL) panic("sa11x0_intr_establish: can't malloc handler info"); if (irq < 0 || irq >= ICU_LEN || type == IST_NONE) panic("intr_establish: bogus irq or type"); /* All interrupts are level intrs. */ /* * Figure out where to put the handler. * This is O(N^2), but we want to preserve the order, and N is * generally small. */ for (p = &irqhandlers[irq]; (q = *p) != NULL; p = &q->ih_next) ; /* * Actually install a fake handler momentarily, since we might be doing * this with interrupts enabled and don't want the real routine called * until masking is set up. */ fakehand.ih_level = level; *p = &fakehand; intr_calculatemasks(); /* * Poke the real handler in now. */ ih->ih_func = ih_fun; ih->ih_arg = ih_arg; ih->ih_count = 0; ih->ih_next = NULL; ih->ih_level = level; ih->ih_irq = irq; ih->ih_name = NULL; /* XXX */ *p = ih; saved_cpsr = SetCPSR(I32_bit, I32_bit); set_spl_masks(); irq_setmasks(); SetCPSR(I32_bit, saved_cpsr & I32_bit); #ifdef DEBUG dumpirqhandlers(); #endif return (ih); }
void enable_irq(int irq) { u_int oldirqstate; oldirqstate = disable_interrupts(I32_bit); current_mask |= (1 << irq); irq_setmasks(); restore_interrupts(oldirqstate); }