2018-07-20 15:41:58 +02:00
|
|
|
#include "irq.h"
|
|
|
|
#include "idt.h"
|
2021-10-07 21:23:32 +02:00
|
|
|
#include "io.h"
|
|
|
|
#include "klibc.h"
|
2018-07-20 15:41:58 +02:00
|
|
|
#include "pic.h"
|
2018-08-06 21:00:58 +02:00
|
|
|
#include "stdarg.h"
|
2021-10-07 21:23:32 +02:00
|
|
|
#include "types.h"
|
2018-07-20 15:41:58 +02:00
|
|
|
|
|
|
|
int irqSetup()
|
|
|
|
{
|
2020-04-27 00:14:37 +02:00
|
|
|
initPic();
|
|
|
|
return 0;
|
2018-07-20 15:41:58 +02:00
|
|
|
}
|
|
|
|
|
2021-10-07 21:23:32 +02:00
|
|
|
// Assembly defined array. This is used to wrap C function than cannot:
|
|
|
|
// * get some cpu state
|
|
|
|
// * return using "iret" instead of "ret" without some compiler __attribute__
|
2021-10-07 23:11:17 +02:00
|
|
|
extern native_irq_handler irq_handler_wrapper_array[IRQ_NUM];
|
2021-10-07 21:23:32 +02:00
|
|
|
|
2020-04-27 00:14:37 +02:00
|
|
|
irq_handler irq_handler_array[IRQ_NUM] = {
|
|
|
|
NULL,
|
|
|
|
};
|
2018-07-20 15:41:58 +02:00
|
|
|
|
2021-10-07 23:11:17 +02:00
|
|
|
void interrupt_handler_pic(int interrupt, struct cpu_state *frame)
|
2021-10-07 21:23:32 +02:00
|
|
|
{
|
|
|
|
if (0 > interrupt || IRQ_NUM <= interrupt) {
|
|
|
|
pr_err("Trying to handle unknow interrupt %d\n", interrupt);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOIIrq(interrupt);
|
|
|
|
|
|
|
|
if (irq_handler_array[interrupt] != NULL)
|
|
|
|
irq_handler_array[interrupt](frame);
|
|
|
|
}
|
|
|
|
|
2021-10-07 23:11:17 +02:00
|
|
|
int irqSetRoutine(int irq, native_irq_handler handler)
|
2018-07-20 15:41:58 +02:00
|
|
|
{
|
|
|
|
uint32_t flags;
|
|
|
|
if ((irq < 0) || irq >= IRQ_NUM)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
disable_IRQs(flags);
|
|
|
|
|
|
|
|
if (handler != NULL) {
|
2020-04-27 00:14:37 +02:00
|
|
|
int ret = idt_set_handler(IRQ_INTERRUPT_BASE_ADDRESS + irq,
|
2021-10-07 23:11:17 +02:00
|
|
|
(unsigned int)handler, 0);
|
2018-07-20 15:41:58 +02:00
|
|
|
if (!ret)
|
|
|
|
enableIrq(irq);
|
|
|
|
}
|
|
|
|
restore_IRQs(flags);
|
|
|
|
return 0;
|
|
|
|
}
|
2021-10-07 21:23:32 +02:00
|
|
|
|
|
|
|
int irqSetRoutineWrapped(int irq, irq_handler handler)
|
|
|
|
{
|
|
|
|
uint32_t flags;
|
|
|
|
if ((irq < 0) || irq >= IRQ_NUM)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
disable_IRQs(flags);
|
|
|
|
|
|
|
|
irq_handler_array[irq] = handler;
|
|
|
|
|
|
|
|
if (handler != NULL) {
|
|
|
|
int ret = idt_set_handler(IRQ_INTERRUPT_BASE_ADDRESS + irq,
|
|
|
|
(unsigned int)irq_handler_wrapper_array[irq], 0);
|
|
|
|
if (!ret)
|
|
|
|
enableIrq(irq);
|
|
|
|
}
|
|
|
|
restore_IRQs(flags);
|
|
|
|
return 0;
|
|
|
|
}
|