static inline int xnintr_irq_attach(xnintr_t *intr) { xnintr_irq_t *shirq = &xnirqs[intr->irq]; xnintr_t *prev, **p = &shirq->handlers; int err; if (intr->irq >= RTHAL_NR_IRQS) return -EINVAL; if (__testbits(intr->flags, XN_ISR_ATTACHED)) return -EPERM; if ((prev = *p) != NULL) { /* Check on whether the shared mode is allowed. */ if (!(prev->flags & intr->flags & XN_ISR_SHARED) || (prev->iack != intr->iack) || ((prev->flags & XN_ISR_EDGE) != (intr->flags & XN_ISR_EDGE))) return -EBUSY; /* Get a position at the end of the list to insert the new element. */ while (prev) { p = &prev->next; prev = *p; } } else { /* Initialize the corresponding interrupt channel */ void (*handler) (unsigned, void *) = &xnintr_irq_handler; if (intr->flags & XN_ISR_SHARED) { if (intr->flags & XN_ISR_EDGE) handler = &xnintr_edge_shirq_handler; else handler = &xnintr_shirq_handler; } shirq->unhandled = 0; err = xnarch_hook_irq(intr->irq, handler, intr->iack, intr); if (err) return err; } __setbits(intr->flags, XN_ISR_ATTACHED); intr->next = NULL; /* Add the given interrupt object. No need to synchronise with the IRQ handler, we are only extending the chain. */ *p = intr; return 0; }
static inline int xnintr_irq_attach(xnintr_t *intr) { return xnarch_hook_irq(intr->irq, &xnintr_irq_handler, (rthal_irq_ackfn_t)intr->iack, intr); }