#include #include #include #include #include #include [[__percpu]] struct irq_percpu irq_data; bool irq_set_state(bool state) { return arch_irq_set_state(state); } bool irq_get_state() { return arch_irq_get_state(); } void irq_wait() { arch_irq_wait(); } void irq_lock() { bool prev = arch_irq_set_state(false); struct irq_percpu* state = percpu_ref(irq_data); if (state->depth++ == 0) state->saved_state = prev; } void irq_unlock() { struct irq_percpu* state = percpu_ref(irq_data); if (--state->depth == 0 && state->saved_state) arch_irq_set_state(true); } void irq_line_program(struct irq_line* line, enum irq_trigger_mode trigger, enum irq_polarity polarity) { irq_lock(); line->mode = line->set_config(line, trigger, polarity); irq_unlock(); } void irq_line_raise(struct irq_line* line) { assert(!arch_irq_get_state(), "Raised an IRQ line with interrupts enabled"); irq_lock(); line->is_busy = true; bool claimed = false; struct irq_handler* handler; list_foreach(handler, &line->handlers, next) { if (handler->raise(handler) == IRQ_STATUS_HANDLED) claimed = true; } if (!claimed) log("irq: Spurious interrupt\n"); if ((line->mode & IRQ_MODE_EOI) && line->eoi) line->eoi(line); line->is_busy = false; irq_unlock(); } void irq_line_attach(struct irq_line* line, struct irq_handler* handler) { irq_lock(); list_insert_head(&line->handlers, handler, next); irq_unlock(); }