#ifndef IDT_H
#define IDT_H

#include "lib/common/common.h"
#include "../../Kdriver/screen/printk.h"

#define IRQ0 32
#define IRQ1 33
#define IRQ2 34
#define IRQ3 35
#define IRQ4 36
#define IRQ5 37
#define IRQ6 38
#define IRQ7 39
#define IRQ8 40
#define IRQ9 41
#define IRQ10 42
#define IRQ11 43
#define IRQ12 44
#define IRQ13 45
#define IRQ14 46
#define IRQ15 47

// A struct describing an interrupt gate.
#pragma pack(push, 1)
struct idt_entry
{
   uint16_t   baseLow;
   uint16_t   selector;
   uint8_t    reservedIst;
   uint8_t    flags;
   uint16_t   baseMid;
   uint32_t   baseHigh;
   uint32_t   reserved;
};
typedef struct idt_entry idt_entry_t;

// A struct describing a pointer to an array of interrupt handlers.
#pragma pack(push, 1)
struct idt_ptr_struct
{
    uint16_t limit;
    uint64_t base;                // The address of the first element in our idt_entry_t array.
};
typedef struct idt_ptr_struct idt_ptr_struct_t;

idt_ptr_struct_t idt_pointer __attribute__((aligned(4)));
idt_entry_t IDT[256] __attribute__((aligned (4)));

#pragma pack(push, 1)
typedef struct {
    uint64_t r15, r14, r13, r12, r11, r10, r9, r8;  /* pushed by 'pushall' */
    uint64_t rdi, rsi, rbp, rdx, rcx, rbx, rax;  /* pushed by 'pushall' */
    uint64_t intNo, errCode;
    uint64_t rip, cs, eflags, userrsp, ss;   /* pushed by the processor automatically */
} registers;

typedef void (*isr_t)(registers*);

isr_t interrupt_handlers[256];

void idt_Start(void);
void idt_Set(uint8_t, uint64_t, uint16_t, uint8_t);
void register_all_interrupt();
void ISR_handle(registers *regs);
void IRQ_handle(registers *regs);
void register_interrupt_handler(uint8_t n, isr_t handler);
void isr_handler(registers* regs);
void irq_handler(registers* regs);
void reg_dump(registers *regs);

extern void idtInit();
extern void isr0();
extern void isr1();
extern void isr2();
extern void isr3();
extern void isr4();
extern void isr5();
extern void isr6();
extern void isr7();
extern void isr8();
extern void isr9();
extern void isr10();
extern void isr11();
extern void isr12();
extern void isr13();
extern void isr14();
extern void isr15();
extern void isr16();
extern void isr17();
extern void isr18();
extern void isr19();
extern void isr20();
extern void isr21();
extern void isr22();
extern void isr23();
extern void isr24();
extern void isr25();
extern void isr26();
extern void isr27();
extern void isr28();
extern void isr29();
extern void isr30();
extern void isr31();
extern void irq0 ();
extern void irq1 ();
extern void irq2 ();
extern void irq3 ();
extern void irq4 ();
extern void irq5 ();
extern void irq6 ();
extern void irq7 ();
extern void irq8 ();
extern void irq9 ();
extern void irq10();
extern void irq11();
extern void irq12();
extern void irq13();
extern void irq14();
extern void irq15();

#endif
