2081b15219
Signed-off-by: Chloe M. <chloe@mensia.org>
116 lines
2.2 KiB
C
116 lines
2.2 KiB
C
/*
|
|
* Copyright (c) 2026, Chloe M.
|
|
* Provided under the BSD-3 clause.
|
|
*
|
|
* Description: High-level interrupt management
|
|
* Author: Chloe M.
|
|
*/
|
|
|
|
#include <hal/intr.h>
|
|
#include <ke/bugcheck.h>
|
|
#include <machine/intr.h>
|
|
#include <machine/idt.h>
|
|
#include <ptdef.h>
|
|
|
|
/* Globals */
|
|
static INTR_HANDLER HandlerTable[256];
|
|
|
|
/*
|
|
* Set a new IRQL
|
|
*/
|
|
static inline VOID
|
|
SetIrql(IRQL Irql)
|
|
{
|
|
ASMV(
|
|
"mov %0, %%cr8"
|
|
:
|
|
: "r" ((UQUAD)Irql)
|
|
: "memory"
|
|
);
|
|
}
|
|
|
|
UCHAR
|
|
HalIntrRegister(INTR_HANDLER *Handler, BOOLEAN IsUser)
|
|
{
|
|
UCHAR VectorBase, Vector;
|
|
INTR_HANDLER *HandlerSlot;
|
|
|
|
/*
|
|
* We have 16 priorities at every band as 4-bits makes up
|
|
* the interrupt priority level. Our job is to find a slot
|
|
* that is free for our interrupt handler at its given IRQL.
|
|
*/
|
|
VectorBase = MAX(Handler->Irql << IPRI_CLASS_SHIFT, 0x20);
|
|
for (Vector = VectorBase; Vector < Vector + 16; ++Vector) {
|
|
/* Skip system reserved vectors */
|
|
switch (Vector) {
|
|
/* Timer vector */
|
|
case 0x81: continue;
|
|
/* System call vector */
|
|
case 0x2E: continue;
|
|
}
|
|
|
|
/* Don't overwrite present entries */
|
|
HandlerSlot = &HandlerTable[Vector];
|
|
if (Handler->Present) {
|
|
continue;
|
|
}
|
|
|
|
*HandlerSlot = *Handler;
|
|
HandlerSlot->Present = 1;
|
|
MdIdtSetGate(
|
|
Vector,
|
|
(UPTR)Handler->Handler,
|
|
(IsUser) ? IDT_USER_GATE : IDT_INT_GATE,
|
|
0
|
|
);
|
|
|
|
return Vector;
|
|
}
|
|
|
|
/* No more vectors */
|
|
return 0;
|
|
}
|
|
|
|
IRQL
|
|
HalGetIrql(VOID)
|
|
{
|
|
UQUAD CurrentIrql;
|
|
|
|
ASMV(
|
|
"mov %%cr8, %0"
|
|
: "=r" (CurrentIrql)
|
|
:
|
|
: "memory"
|
|
);
|
|
|
|
return (IRQL)CurrentIrql;
|
|
}
|
|
|
|
IRQL
|
|
HalRaiseIrql(IRQL Irql)
|
|
{
|
|
IRQL CurrentIrql;
|
|
|
|
CurrentIrql = HalGetIrql();
|
|
if (Irql < CurrentIrql) {
|
|
KeBugCheck(BUGCHECK_IRQL_NOT_GTE, "got bad irql\n");
|
|
}
|
|
|
|
SetIrql(Irql);
|
|
return CurrentIrql;
|
|
}
|
|
|
|
IRQL
|
|
HalLowerIrql(IRQL Irql)
|
|
{
|
|
IRQL CurrentIrql;
|
|
|
|
CurrentIrql = HalGetIrql();
|
|
if (Irql > CurrentIrql) {
|
|
KeBugCheck(BUGCHECK_IRQL_NOT_LTE, "got bad irql\n");
|
|
}
|
|
|
|
return CurrentIrql;
|
|
}
|