stos/amd64: cpu: Add HAL interrupt registration
Signed-off-by: Chloe M. <chloe@mensia.org>
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
Reference in New Issue
Block a user