mirror of
https://github.com/drasko/codezero.git
synced 2026-01-26 09:43:14 +01:00
Initial commit
This commit is contained in:
77
src/generic/irq.c
Normal file
77
src/generic/irq.c
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Kernel irq handling (core irqs like timer). Also hope to add thread-level
|
||||
* irq handling in the future.
|
||||
*
|
||||
* Copyright (C) 2007 Bahadir Balban
|
||||
*
|
||||
*/
|
||||
#include <l4/config.h>
|
||||
#include <l4/macros.h>
|
||||
#include <l4/generic/platform.h>
|
||||
#include <l4/generic/irq.h>
|
||||
#include <l4/lib/mutex.h>
|
||||
#include <l4/generic/scheduler.h>
|
||||
#include <l4/lib/printk.h>
|
||||
#include INC_PLAT(irq.h)
|
||||
#include INC_ARCH(exception.h)
|
||||
|
||||
/* This enables the lower chip on the current chip, if such chaining exists. */
|
||||
static inline void cascade_irq_chip(struct irq_chip *this_chip)
|
||||
{
|
||||
if (this_chip->cascade >= 0) {
|
||||
BUG_ON(IRQ_CHIPS_MAX == 1);
|
||||
this_chip->ops.unmask(this_chip->cascade);
|
||||
}
|
||||
}
|
||||
|
||||
void irq_controllers_init(void)
|
||||
{
|
||||
struct irq_chip *this_chip;
|
||||
|
||||
for (int i = 0; i < IRQ_CHIPS_MAX; i++) {
|
||||
this_chip = irq_chip_array + i;
|
||||
/* Initialise the irq chips (e.g. reset all registers) */
|
||||
this_chip->ops.init();
|
||||
/* Enable cascaded irqs if needed */
|
||||
cascade_irq_chip(this_chip);
|
||||
}
|
||||
}
|
||||
|
||||
int global_irq_index(void)
|
||||
{
|
||||
struct irq_chip *this_chip;
|
||||
int irq_index = 0;
|
||||
|
||||
/* Loop over irq chips from top to bottom until
|
||||
* the actual irq on the lowest chip is found */
|
||||
for (int i = 0; i < IRQ_CHIPS_MAX; i++) {
|
||||
this_chip = irq_chip_array + i;
|
||||
BUG_ON((irq_index = this_chip->ops.read_irq()) < 0);
|
||||
if (irq_index != this_chip->cascade) {
|
||||
irq_index += this_chip->offset;
|
||||
/* Found the real irq, return */
|
||||
break;
|
||||
}
|
||||
/* Hit the cascading irq. Continue on next irq chip. */
|
||||
}
|
||||
return irq_index;
|
||||
}
|
||||
|
||||
void do_irq(void)
|
||||
{
|
||||
int irq_index = global_irq_index();
|
||||
struct irq_desc *this_irq = irq_desc_array + irq_index;
|
||||
|
||||
/* TODO: This can be easily done few instructions quicker by some
|
||||
* immediate read/disable/enable_all(). We stick with this clear
|
||||
* implementation for now. */
|
||||
irq_disable(irq_index);
|
||||
enable_irqs();
|
||||
/* TODO: Call irq_thread_notify(irq_index) for threaded irqs. */
|
||||
BUG_ON(!this_irq->handler);
|
||||
if (this_irq->handler() != IRQ_HANDLED) {
|
||||
printk("Spurious or broken irq\n"); BUG();
|
||||
}
|
||||
irq_enable(irq_index);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user