Exemplo n.º 1
0
/**
 * 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 */
}
Exemplo n.º 2
0
/**
 *
 * @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;
}
Exemplo n.º 3
0
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;
}