diff --git a/service/ptos/arch/amd64/cpu/intr.c b/service/ptos/arch/amd64/cpu/intr.c new file mode 100644 index 0000000..c76ab45 --- /dev/null +++ b/service/ptos/arch/amd64/cpu/intr.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2026, Chloe M. + * Provided under the BSD-3 clause. + * + * Description: High-level interrupt management + * Author: Chloe M. + */ + +#include +#include +#include +#include + +/* Globals */ +static INTR_HANDLER HandlerTable[256]; + +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; +} diff --git a/service/ptos/head/arch/amd64/intr.h b/service/ptos/head/arch/amd64/intr.h new file mode 100644 index 0000000..822af6d --- /dev/null +++ b/service/ptos/head/arch/amd64/intr.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2026, Chloe M. + * Provided under the BSD-3 clause. + * + * Description: High-level interrupt management + * Author: Chloe M. + */ + +#ifndef _MACHINE_INTR_H_ +#define _MACHINE_INTR_H_ 1 + +/* Interrupt priority class shift operand */ +#define IPRI_CLASS_SHIFT 4 + +#endif /* !_MACHINE_INTR_H_ */ diff --git a/service/ptos/head/hal/intr.h b/service/ptos/head/hal/intr.h index 9155245..6548cba 100644 --- a/service/ptos/head/hal/intr.h +++ b/service/ptos/head/hal/intr.h @@ -10,6 +10,7 @@ #define _HAL_INTR_H_ 1 #include +#include /* * Represents value interrupt request levels that can be set within @@ -40,4 +41,15 @@ typedef struct _INTR_HANDLER { BOOLEAN Present; } INTR_HANDLER; +/* + * Register an interrupt handler and obtain the interrupt + * vector. + * + * @Handler: Handler to register + * @IsUser: If set, is user-level interrupt + * + * Returned values of zero are invalid + */ +UCHAR HalIntrRegister(INTR_HANDLER *Handler, BOOLEAN IsUser); + #endif /* !_HAL_INTR_H_ */