/** * Reconnect all previously connected ISR * This is useful on a SOC resume phase when RAM was preserved but not IRQ * controller state. */ void irq_resume() { /* Static interrupts simply need to be reconnected */ int i; for (i = 0; i < 32; i++) { _SysIntVecProgram(_IRQ_TO_INTERRUPT_VECTOR(i), i, 0); } /* Dynamic interrupts need to be re-declared on resume */ }
/** * * @brief Allocate interrupt vector * * This routine is used by the x86's irq_connect_dynamic(). It performs the * following functions: * * a) Allocates a vector satisfying the requested priority. The utility * routine _IntVecAlloc() provided by the nanokernel will be used to * perform the the allocation since the local APIC prioritizes interrupts * as assumed by _IntVecAlloc(). * b) If an interrupt vector can be allocated, the IOAPIC redirection table * (RED) or the LOAPIC local vector table (LVT) will be updated with the * allocated interrupt vector. * * The board virtualizes IRQs as follows: * * - The first CONFIG_IOAPIC_NUM_RTES IRQs are provided by the IOAPIC * - The remaining IRQs are provided by the LOAPIC. * * Thus, for example, if the IOAPIC supports 24 IRQs: * * - IRQ0 to IRQ23 map to IOAPIC IRQ0 to IRQ23 * - IRQ24 to IRQ29 map to LOAPIC LVT entries as follows: * * IRQ24 -> LOAPIC_TIMER * IRQ25 -> LOAPIC_THERMAL * IRQ26 -> LOAPIC_PMC * IRQ27 -> LOAPIC_LINT0 * IRQ28 -> LOAPIC_LINT1 * IRQ29 -> LOAPIC_ERROR * * @param irq virtualized IRQ * @param priority get vector from <priority> group * @param flags Interrupt flags * * @return the allocated interrupt vector * * @internal * For debug kernels, this routine will return -1 if there are no vectors * remaining in the specified <priority> level, or if the <priority> or <irq> * parameters are invalid. * @endinternal */ int _SysIntVecAlloc( unsigned int irq, /* virtualized IRQ */ unsigned int priority, /* get vector from <priority> group */ uint32_t flags /* interrupt flags */ ) { int vector; __ASSERT(priority < 14, "invalid priority"); __ASSERT(irq >= 0 && irq <= HARDWARE_IRQ_LIMIT, "invalid irq line"); vector = __LocalIntVecAlloc(irq, priority); /* * Set up the appropriate interrupt controller to generate the allocated * interrupt vector for the specified IRQ */ __ASSERT(vector != -1, "bad vector id"); _SysIntVecProgram(vector, irq, flags); return vector; }
int irq_connect_dynamic(unsigned int irq, unsigned int priority, void (*routine)(void *parameter), void *parameter, uint32_t flags) { int vector; int stub_idx; /* * Check if the same IRQ was already connected before, in such as case, * simply re-connect the existing stub. */ int i; for (i=0; i<next_irq_stub; ++i) { if (dyn_irq_list[i].irq == irq) { __ASSERT(dyn_irq_list[i].priority == priority, "Non consistent priority"); dyn_irq_list[i].handler = routine; dyn_irq_list[i].param = parameter; _SysIntVecProgram(dyn_irq_list[i].vector, irq, flags); _IntVecSet(dyn_irq_list[i].vector, _get_dynamic_stub(i, &_DynIntStubsBegin), 0); return dyn_irq_list[i].vector; } } /* * Invoke the interrupt controller routine _SysIntVecAlloc() which will: * a) allocate a vector satisfying the requested priority, * b) create a new entry in the dynamic stub array * c) program the underlying interrupt controller device such that * when <irq> is asserted, the allocated interrupt vector will be * presented to the CPU. * * The _SysIntVecAlloc() routine will use the "utility" routine * _IntVecAlloc() provided in this module to scan the * _interrupt_vectors_allocated[] array for a suitable vector. */ vector = _SysIntVecAlloc(irq, priority, flags); #if defined(DEBUG) /* * The return value from _SysIntVecAlloc() will be -1 if an invalid * <irq> or <priority> was specified, or if a vector could not be * allocated to honour the requested priority (for the boards that can * support programming the interrupt vector for each IRQ). */ if (vector == -1) return (-1); #endif /* DEBUG */ stub_idx = _stub_alloc(&next_irq_stub, ALL_DYN_IRQ_STUBS); __ASSERT(stub_idx != -1, "No available interrupt stubs found"); dyn_irq_list[stub_idx].handler = routine; dyn_irq_list[stub_idx].param = parameter; dyn_irq_list[stub_idx].vector = vector; dyn_irq_list[stub_idx].irq = irq; dyn_irq_list[stub_idx].priority = priority; _IntVecSet(vector, _get_dynamic_stub(stub_idx, &_DynIntStubsBegin), 0); return vector; }