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

#ifndef _MACHINE_LAPIC_H_
#define _MACHINE_LAPIC_H_ 1

#include <ptdef.h>
#include <hal/kpcr.h>

/*
 * Destination shorthand values for inter-processor
 * interrupts.
 *
 * @IPI_XND_NONE:  No shorthand
 * @IPI_XND_SELF:  Self shorthand
 * @IPI_XND_AIS:   All including self shorthand
 * @IPI_XND_AES:   All exclduing self shorthand
 */
typedef enum {
    IPI_XND_NONE,
    IPI_XND_SELF,
    IPI_XND_AIS,
    IPI_XND_AES
} IPI_SHORTHAND;

/*
 * Delivery mode values for inter-processor
 * interrupts.
 *
 * @IPI_DELMOD_FIXED:       Deliver a specific interrupt vector to a slutty core~
 * @IPI_LOWPRI:             Equivalent to a FIXED IPI but lowest priority
 * @IPI_DELMOD_SMI:         Sends an SMI, we don't use this
 * @IPI_DELMOD_RESERVED:    Reserved
 * @IPI_DELMOD_NMI:         Deliver a non-maskable interrupt
 * @IPI_DELMOD_INIT:        Deliver an INIT IPI to a processor
 * @IPI_DELMOD_STARTUP:     Deliver a STARTUP IPI to a processor
 */
typedef enum {
    IPI_DELMOD_FIXED,
    IPI_DELMOD_LOWPRI,
    IPI_DELMOD_SMI,
    IPI_DELMOD_RESERVED,
    IPI_DELMOD_NMI,
    IPI_DELMOD_INIT,
    IPI_DELMOD_STARTUP
} IPI_DELMOD;

/* IPI Delivery status bits */
#define IPI_DELSTAT_PENDING BIT(12)

/* IPI Destination mode */
#define IPI_DELMOD_LOGICAL BIT(0)

/*
 * Initialize the Local APIC unit for the current
 * processor.
 *
 * @Kpcr: KPCR of current processor
 */
VOID MdLapicInit(KPCR *Kpcr);

/*
 * Obtain the APIC ID of the current processor
 */
ULONG MdLapicId(VOID);

/*
 * Send an inter-processor interrupt
 *
 * @Vector:         Interrupt vector to assign to ICR
 * @DestId:         Target APIC ID [depends on @LogicalDest]
 * @LogicalDest:    If true, IPI destination is logical
 * @Xnd:            Destination shorthand
 * @Delmod:         Delivery mode
 */
VOID MdLapicSendIpi(
    UCHAR Vector, UCHAR DestId,
    BOOLEAN LogicalDest, IPI_SHORTHAND Xnd,
    IPI_DELMOD DelMod
);

/*
 * Start the Local APIC timer in oneshot mode and fire after
 * a number of microseconds
 *
 * @Usec: Number of microseconds to fire after
 */
VOID MdLapicTimerOneshotUs(USIZE Usec);

/*
 * Send an end-of-interrupt signal to the Local APIC unit
 */
VOID MdLapicSendEoi(VOID);

#endif  /* !_MACHINE_LAPIC_H_ */
