Files
SystemPaw3/paw/stos/arch/amd64/cpu/intr.c
T
2026-06-23 21:20:09 +00:00

77 lines
1.7 KiB
C

/*
* Copyright (c) 2026, Chloe M.
* Provided under the BSD-3 clause.
*
* Description: Interrupt management
* Author: Chloe M.
*/
#include <hal/intr.h>
#include <machine/idt.h>
#include <stdef.h>
/* Interrupt priority level shift */
#define IPL_SHIFT 4
/* Globals */
static INTR_HANDLER Handlers[256];
ST_STATUS
HalRegisterIntr(const INTR_HANDLER *Handler, BOOLEAN IsUser)
{
UCHAR Vector, Idx;
INTR_HANDLER *HandlerSlot;
if (Handler == NULL) {
return STATUS_INVALID_PARAM;
}
/* Must have a valid handler */
if (Handler->Handler == NULL) {
return STATUS_INVALID_PARAM;
}
/* Ensure that the priority is valid */
switch (Handler->Irql) {
case IRQL_PASSIVE:
case IRQL_APC:
case IRQL_DEVICE:
case IRQL_HIGH:
break;
default:
return STATUS_INVALID_PARAM;
}
/*
* 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.
*/
Vector = MAX(0x20, Handler->Irql << IPL_SHIFT);
for (Idx = Vector; Idx < Vector + 16; ++Idx) {
HandlerSlot = &Handlers[Idx];
/* This entry is present, don't overwrite */
if (HandlerSlot->Present) {
continue;
}
/* Fill the slot */
*HandlerSlot = *(INTR_HANDLER *)Handler;
HandlerSlot->Present = 1;
/* Register the interrupt */
MdIdtSetEntry(
Idx,
(UPTR)Handler->Handler,
(IsUser) ? IDT_USER_GATE : IDT_INT_GATE,
0
);
return STATUS_SUCCESS;
}
/* No entry found */
return STATUS_NOT_FOUND;
}