/* * Copyright (c) 2026, Chloe M. * Provided under the BSD-3 clause. * * Description: Interrupt management * Author: Chloe M. */ #include #include #include /* 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; }