///                MentOS, The Mentoring Operating system project
/// @file idt.h
/// @brief Data structures concerning the Interrupt Descriptor Table (IDT).
/// @copyright (c) 2014-2021 This file is distributed under the MIT License.
/// See LICENSE.md for details.
/// @addtogroup descriptor_tables Descriptor Tables
/// @{
/// @addtogroup idt Interrupt Descriptor Table (IDT)
/// @brief Is a data structure used by the x86 architecture to implement an 
/// interrupt vector table. The IDT is used by the processor to determine the 
/// correct response to interrupts and exceptions.
/// @{

#pragma once

#include "stdint.h"

/// The maximum dimension of the IDT.
#define IDT_SIZE 256
/// When an exception occurs whose entry is a Task Gate, a task switch results.
#define TASK_GATE 0x5
/// Used to specify an interrupt service routine (16-bit).
#define INT16_GATE 0x6
/// @brief Similar to an Interrupt gate (16-bit).
#define TRAP16_GATE 0x7
/// Used to specify an interrupt service routine (32-bit).
#define INT32_GATE 0xE
/// @brief Similar to an Interrupt gate (32-bit).
#define TRAP32_GATE 0xF

/*
 * Trap and Interrupt gates are similar, and their descriptors are
 * structurally the same, they differ only in the "type" field. The
 * difference is that for interrupt gates, interrupts are automatically
 * disabled upon entry and reenabled upon IRET which restores the saved EFLAGS.
 */

/// @brief This structure describes one interrupt gate.
typedef struct idt_descriptor_t {
    /// TODO: Comment.
    unsigned short offset_low;
    /// Segment selector.
    unsigned short seg_selector;
    /// This will ALWAYS be set to 0.
    unsigned char null_par;
    /// @brief IDT descriptor options:
    ///        |P|DPL|01110|.
    ///        P present, DPL required Ring (2bits).
    unsigned char options;
    /// TODO: Comment.
    unsigned short offset_high;
} __attribute__((packed)) idt_descriptor_t;

/// @brief A pointer structure used for informing the CPU about our IDT.
typedef struct idt_pointer_t {
    /// The size of the IDT (entry number).
    unsigned short int limit;
    /// The start address of the IDT.
    unsigned int base;
} __attribute__((packed)) idt_pointer_t;

/// @brief Initialise the interrupt descriptor table.
void init_idt();

// == List of exceptions generated internally by the CPU ======================
//! @cond Doxygen_Suppress

extern void INT_0();

extern void INT_1();

extern void INT_2();

extern void INT_3();

extern void INT_4();

extern void INT_5();

extern void INT_6();

extern void INT_7();

extern void INT_8();

extern void INT_9();

extern void INT_10();

extern void INT_11();

extern void INT_12();

extern void INT_13();

extern void INT_14();

extern void INT_15();

extern void INT_16();

extern void INT_17();

extern void INT_18();

extern void INT_19();

extern void INT_20();

extern void INT_21();

extern void INT_22();

extern void INT_23();

extern void INT_24();

extern void INT_25();

extern void INT_26();

extern void INT_27();

extern void INT_28();

extern void INT_29();

extern void INT_30();

extern void INT_31();

extern void INT_80();

// == List of interrupts generated by PIC =====================================
extern void IRQ_0();

extern void IRQ_1();

extern void IRQ_2();

extern void IRQ_3();

extern void IRQ_4();

extern void IRQ_5();

extern void IRQ_6();

extern void IRQ_7();

extern void IRQ_8();

extern void IRQ_9();

extern void IRQ_10();

extern void IRQ_11();

extern void IRQ_12();

extern void IRQ_13();

extern void IRQ_14();

extern void IRQ_15();

/// @}
/// @}