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