/*
 * Copyright (c) 2026, Chloe M.
 * Provided under the BSD-3 clause.
 *
 * Description:  Interrupt management
 * Author:       Chloe M.
 */

#ifndef _HAL_INTR_H_
#define _HAL_INTR_H_ 1

#include <stdef.h>
#include <stapi/status.h>

/*
 * Valid interrupt request levels
 *
 * @IRQL_PASSIVE:   Standard user/kernel operation
 * @IRQL_APC:       Asynchronous procedure call
 * @IRQL_DISPATCH:  Deferred procedure call dispatch
 * @IRQL_CRITICAL:  Critical section
 * @IRQL_HIGH:      Block everything
 */
#define IRQL_PASSIVE  0
#define IRQL_APC      1
#define IRQL_DISPATCH 2
#define IRQL_DEVICE   3
#define IRQL_CRITICAL 4
#define IRQL_HIGH     5

/* IRQLs are of this type */
typedef UCHAR IRQL;

/*
 * Interrupt data that is given to a service routine
 *
 * @Vector:  Interrupt vector that fired
 * @Data:    Driver specific data
 */
typedef struct {
    UCHAR Vector;
    VOID *Data;
} INTR_DATA;

/*
 * Interrupt handler descriptor
 *
 * @Irql:     Prioirty of handler
 * @Present:  Must be 1 to be valid
 * @Data:     Driver specific data
 * @Handler:  Reference to interrupt handler
 *
 * XXX: There is no need to set the present bit when
 *      creating an instance as it is set automatically.
 */
typedef struct {
    IRQL Irql;
    UCHAR Present : 1;
    VOID *Data;
    LONG(*Handler)(INTR_DATA *Data);
} INTR_HANDLER;

/*
 * Register an interrupt handler
 *
 * @Handler: Interrupt handler to register
 * @IsUser:  Should be set if user interrupt
 *
 * XXX: Most of the times, @IsUser should remain unset,
 *      it is mostly there for the sake of scalability.
 */
ST_STATUS HalRegisterIntr(const INTR_HANDLER *Handler, BOOLEAN IsUser);

/*
 * Returns the current IRQL
 */
IRQL HalGetIrql(VOID);

/*
 * Raise the IRQL level to a higher level
 *
 * @Irql: IRQL to raise to
 *
 * Returns the previous IRQL
 */
IRQL HalRaiseIrql(IRQL Irql);

/*
 * Lower the IRQL level to a lower level
 *
 * @Irql: IRQL to lower to
 *
 * Returns the previous IRQL
 */
IRQL HalLowerIrql(IRQL Irql);

#endif  /* !_HAL_INTR_H_ */
