#include "mm.h"
#include "libk.h"
#include "interrupts.h"
#include "drivers/apic.h"

#define ISR_NAME(index) isr_stub_ ## index

#define IDT_INSTALL_CLI(index, ist) ({ \
	void ISR_NAME(index)(void); \
	idt_set_gate(index, ISR_NAME(index), ist, 0x8E); })

#define IDT_INSTALL_STI(index, ist) ({ \
	void ISR_NAME(index)(void); \
	idt_set_gate(index, ISR_NAME(index), ist, 0x8F); })

extern struct idt_entry idt64[256];

void idt_set_gate(uint8_t index, virtaddr_t entry, uint8_t ist, uint8_t type_attr)
{
	uintptr_t p = (uintptr_t)entry;
	struct idt_entry e = {
		.offset_low = (p & 0xFFFF),
		.selector = 0x08,  // Kernel code segment
		.ist_index = ist,
		.type_attr = type_attr,
		.offset_mid = ((p & 0xFFFF0000) >> 16),
		.offset_high = ((p & 0xFFFFFFFF00000000) >> 32)
	};
	idt64[index] = e;
}

void idt_init(void)
{
	IDT_INSTALL_CLI(0, IST_NONE);
	IDT_INSTALL_CLI(1, IST_NONE);
	IDT_INSTALL_CLI(2, IST_NMI);
	IDT_INSTALL_CLI(3, IST_NONE);
	IDT_INSTALL_CLI(4, IST_NONE);
	IDT_INSTALL_CLI(5, IST_NONE);
	IDT_INSTALL_CLI(6, IST_NONE);
	IDT_INSTALL_CLI(7, IST_NONE);
	IDT_INSTALL_CLI(8, IST_DOUBLE_FAULT);
	IDT_INSTALL_CLI(9, IST_NONE);
	IDT_INSTALL_CLI(10, IST_NONE);
	IDT_INSTALL_CLI(11, IST_NONE);
	IDT_INSTALL_CLI(12, IST_NONE);
	IDT_INSTALL_CLI(13, IST_NONE);
	IDT_INSTALL_CLI(14, IST_NONE);
	IDT_INSTALL_CLI(15, IST_NONE);
	IDT_INSTALL_CLI(16, IST_NONE);
	IDT_INSTALL_CLI(17, IST_NONE);
	IDT_INSTALL_CLI(18, IST_NONE);
	IDT_INSTALL_CLI(19, IST_NONE);
	IDT_INSTALL_CLI(20, IST_NONE);
	IDT_INSTALL_CLI(21, IST_NONE);
	IDT_INSTALL_CLI(22, IST_NONE);
	IDT_INSTALL_CLI(23, IST_NONE);
	IDT_INSTALL_CLI(24, IST_NONE);
	IDT_INSTALL_CLI(25, IST_NONE);
	IDT_INSTALL_CLI(26, IST_NONE);
	IDT_INSTALL_CLI(27, IST_NONE);
	IDT_INSTALL_CLI(28, IST_NONE);
	IDT_INSTALL_CLI(29, IST_NONE);
	IDT_INSTALL_CLI(30, IST_NONE);
	IDT_INSTALL_CLI(31, IST_NONE);
	IDT_INSTALL_STI(32, IST_NONE);
	IDT_INSTALL_STI(33, IST_NONE);
	IDT_INSTALL_STI(34, IST_NONE);
	IDT_INSTALL_STI(35, IST_NONE);
	IDT_INSTALL_STI(36, IST_NONE);
	IDT_INSTALL_STI(37, IST_NONE);
	IDT_INSTALL_STI(38, IST_NONE);
	IDT_INSTALL_STI(39, IST_NONE);
	IDT_INSTALL_STI(40, IST_NONE);
	IDT_INSTALL_STI(41, IST_NONE);
	IDT_INSTALL_STI(42, IST_NONE);
	IDT_INSTALL_STI(43, IST_NONE);
	IDT_INSTALL_STI(44, IST_NONE);
	IDT_INSTALL_STI(45, IST_NONE);
	IDT_INSTALL_STI(46, IST_NONE);
	IDT_INSTALL_STI(47, IST_NONE);
	IDT_INSTALL_STI(48, IST_NONE);
	IDT_INSTALL_STI(49, IST_NONE);
	IDT_INSTALL_STI(50, IST_NONE);
	IDT_INSTALL_STI(51, IST_NONE);
	IDT_INSTALL_STI(52, IST_NONE);
	IDT_INSTALL_STI(53, IST_NONE);
	IDT_INSTALL_STI(54, IST_NONE);
	IDT_INSTALL_STI(55, IST_NONE);
	IDT_INSTALL_STI(56, IST_NONE);
	IDT_INSTALL_STI(57, IST_NONE);
	IDT_INSTALL_STI(58, IST_NONE);
	IDT_INSTALL_STI(59, IST_NONE);
	IDT_INSTALL_STI(60, IST_NONE);
	IDT_INSTALL_STI(61, IST_NONE);
	IDT_INSTALL_STI(62, IST_NONE);
	IDT_INSTALL_STI(63, IST_NONE);
	IDT_INSTALL_STI(64, IST_NONE);
	IDT_INSTALL_STI(65, IST_NONE);
	IDT_INSTALL_STI(66, IST_NONE);
	IDT_INSTALL_STI(67, IST_NONE);
	IDT_INSTALL_STI(68, IST_NONE);
	IDT_INSTALL_STI(69, IST_NONE);
	IDT_INSTALL_STI(70, IST_NONE);
	IDT_INSTALL_STI(71, IST_NONE);
	IDT_INSTALL_STI(72, IST_NONE);
	IDT_INSTALL_STI(73, IST_NONE);
	IDT_INSTALL_STI(74, IST_NONE);
	IDT_INSTALL_STI(75, IST_NONE);
	IDT_INSTALL_STI(76, IST_NONE);
	IDT_INSTALL_STI(77, IST_NONE);
	IDT_INSTALL_STI(78, IST_NONE);
	IDT_INSTALL_STI(79, IST_NONE);
	IDT_INSTALL_STI(80, IST_NONE);
	IDT_INSTALL_STI(81, IST_NONE);
	IDT_INSTALL_STI(82, IST_NONE);
	IDT_INSTALL_STI(83, IST_NONE);
	IDT_INSTALL_STI(84, IST_NONE);
	IDT_INSTALL_STI(85, IST_NONE);
	IDT_INSTALL_STI(86, IST_NONE);
	IDT_INSTALL_STI(87, IST_NONE);
	IDT_INSTALL_STI(88, IST_NONE);
	IDT_INSTALL_STI(89, IST_NONE);
	IDT_INSTALL_STI(90, IST_NONE);
	IDT_INSTALL_STI(91, IST_NONE);
	IDT_INSTALL_STI(92, IST_NONE);
	IDT_INSTALL_STI(93, IST_NONE);
	IDT_INSTALL_STI(94, IST_NONE);
	IDT_INSTALL_STI(95, IST_NONE);
	IDT_INSTALL_STI(96, IST_NONE);
	IDT_INSTALL_STI(97, IST_NONE);
	IDT_INSTALL_STI(98, IST_NONE);
	IDT_INSTALL_STI(99, IST_NONE);
	IDT_INSTALL_STI(100, IST_NONE);
	IDT_INSTALL_STI(101, IST_NONE);
	IDT_INSTALL_STI(102, IST_NONE);
	IDT_INSTALL_STI(103, IST_NONE);
	IDT_INSTALL_STI(104, IST_NONE);
	IDT_INSTALL_STI(105, IST_NONE);
	IDT_INSTALL_STI(106, IST_NONE);
	IDT_INSTALL_STI(107, IST_NONE);
	IDT_INSTALL_STI(108, IST_NONE);
	IDT_INSTALL_STI(109, IST_NONE);
	IDT_INSTALL_STI(110, IST_NONE);
	IDT_INSTALL_STI(111, IST_NONE);
	IDT_INSTALL_STI(112, IST_NONE);
	IDT_INSTALL_STI(113, IST_NONE);
	IDT_INSTALL_STI(114, IST_NONE);
	IDT_INSTALL_STI(115, IST_NONE);
	IDT_INSTALL_STI(116, IST_NONE);
	IDT_INSTALL_STI(117, IST_NONE);
	IDT_INSTALL_STI(118, IST_NONE);
	IDT_INSTALL_STI(119, IST_NONE);
	IDT_INSTALL_STI(120, IST_NONE);
	IDT_INSTALL_STI(121, IST_NONE);
	IDT_INSTALL_STI(122, IST_NONE);
	IDT_INSTALL_STI(123, IST_NONE);
	IDT_INSTALL_STI(124, IST_NONE);
	IDT_INSTALL_STI(125, IST_NONE);
	IDT_INSTALL_STI(126, IST_NONE);
	IDT_INSTALL_STI(127, IST_NONE);
	IDT_INSTALL_STI(128, IST_NONE);
	IDT_INSTALL_STI(129, IST_NONE);
	IDT_INSTALL_STI(130, IST_NONE);
	IDT_INSTALL_STI(131, IST_NONE);
	IDT_INSTALL_STI(132, IST_NONE);
	IDT_INSTALL_STI(133, IST_NONE);
	IDT_INSTALL_STI(134, IST_NONE);
	IDT_INSTALL_STI(135, IST_NONE);
	IDT_INSTALL_STI(136, IST_NONE);
	IDT_INSTALL_STI(137, IST_NONE);
	IDT_INSTALL_STI(138, IST_NONE);
	IDT_INSTALL_STI(139, IST_NONE);
	IDT_INSTALL_STI(140, IST_NONE);
	IDT_INSTALL_STI(141, IST_NONE);
	IDT_INSTALL_STI(142, IST_NONE);
	IDT_INSTALL_STI(143, IST_NONE);
	IDT_INSTALL_STI(144, IST_NONE);
	IDT_INSTALL_STI(145, IST_NONE);
	IDT_INSTALL_STI(146, IST_NONE);
	IDT_INSTALL_STI(147, IST_NONE);
	IDT_INSTALL_STI(148, IST_NONE);
	IDT_INSTALL_STI(149, IST_NONE);
	IDT_INSTALL_STI(150, IST_NONE);
	IDT_INSTALL_STI(151, IST_NONE);
	IDT_INSTALL_STI(152, IST_NONE);
	IDT_INSTALL_STI(153, IST_NONE);
	IDT_INSTALL_STI(154, IST_NONE);
	IDT_INSTALL_STI(155, IST_NONE);
	IDT_INSTALL_STI(156, IST_NONE);
	IDT_INSTALL_STI(157, IST_NONE);
	IDT_INSTALL_STI(158, IST_NONE);
	IDT_INSTALL_STI(159, IST_NONE);
	IDT_INSTALL_STI(160, IST_NONE);
	IDT_INSTALL_STI(161, IST_NONE);
	IDT_INSTALL_STI(162, IST_NONE);
	IDT_INSTALL_STI(163, IST_NONE);
	IDT_INSTALL_STI(164, IST_NONE);
	IDT_INSTALL_STI(165, IST_NONE);
	IDT_INSTALL_STI(166, IST_NONE);
	IDT_INSTALL_STI(167, IST_NONE);
	IDT_INSTALL_STI(168, IST_NONE);
	IDT_INSTALL_STI(169, IST_NONE);
	IDT_INSTALL_STI(170, IST_NONE);
	IDT_INSTALL_STI(171, IST_NONE);
	IDT_INSTALL_STI(172, IST_NONE);
	IDT_INSTALL_STI(173, IST_NONE);
	IDT_INSTALL_STI(174, IST_NONE);
	IDT_INSTALL_STI(175, IST_NONE);
	IDT_INSTALL_STI(176, IST_NONE);
	IDT_INSTALL_STI(177, IST_NONE);
	IDT_INSTALL_STI(178, IST_NONE);
	IDT_INSTALL_STI(179, IST_NONE);
	IDT_INSTALL_STI(180, IST_NONE);
	IDT_INSTALL_STI(181, IST_NONE);
	IDT_INSTALL_STI(182, IST_NONE);
	IDT_INSTALL_STI(183, IST_NONE);
	IDT_INSTALL_STI(184, IST_NONE);
	IDT_INSTALL_STI(185, IST_NONE);
	IDT_INSTALL_STI(186, IST_NONE);
	IDT_INSTALL_STI(187, IST_NONE);
	IDT_INSTALL_STI(188, IST_NONE);
	IDT_INSTALL_STI(189, IST_NONE);
	IDT_INSTALL_STI(190, IST_NONE);
	IDT_INSTALL_STI(191, IST_NONE);
	IDT_INSTALL_STI(192, IST_NONE);
	IDT_INSTALL_STI(193, IST_NONE);
	IDT_INSTALL_STI(194, IST_NONE);
	IDT_INSTALL_STI(195, IST_NONE);
	IDT_INSTALL_STI(196, IST_NONE);
	IDT_INSTALL_STI(197, IST_NONE);
	IDT_INSTALL_STI(198, IST_NONE);
	IDT_INSTALL_STI(199, IST_NONE);
	IDT_INSTALL_STI(200, IST_NONE);
	IDT_INSTALL_STI(201, IST_NONE);
	IDT_INSTALL_STI(202, IST_NONE);
	IDT_INSTALL_STI(203, IST_NONE);
	IDT_INSTALL_STI(204, IST_NONE);
	IDT_INSTALL_STI(205, IST_NONE);
	IDT_INSTALL_STI(206, IST_NONE);
	IDT_INSTALL_STI(207, IST_NONE);
	IDT_INSTALL_STI(208, IST_NONE);
	IDT_INSTALL_STI(209, IST_NONE);
	IDT_INSTALL_STI(210, IST_NONE);
	IDT_INSTALL_STI(211, IST_NONE);
	IDT_INSTALL_STI(212, IST_NONE);
	IDT_INSTALL_STI(213, IST_NONE);
	IDT_INSTALL_STI(214, IST_NONE);
	IDT_INSTALL_STI(215, IST_NONE);
	IDT_INSTALL_STI(216, IST_NONE);
	IDT_INSTALL_STI(217, IST_NONE);
	IDT_INSTALL_STI(218, IST_NONE);
	IDT_INSTALL_STI(219, IST_NONE);
	IDT_INSTALL_STI(220, IST_NONE);
	IDT_INSTALL_STI(221, IST_NONE);
	IDT_INSTALL_STI(222, IST_NONE);
	IDT_INSTALL_STI(223, IST_NONE);
	IDT_INSTALL_STI(224, IST_NONE);
	IDT_INSTALL_STI(225, IST_NONE);
	IDT_INSTALL_STI(226, IST_NONE);
	IDT_INSTALL_STI(227, IST_NONE);
	IDT_INSTALL_STI(228, IST_NONE);
	IDT_INSTALL_STI(229, IST_NONE);
	IDT_INSTALL_STI(230, IST_NONE);
	IDT_INSTALL_STI(231, IST_NONE);
	IDT_INSTALL_STI(232, IST_NONE);
	IDT_INSTALL_STI(233, IST_NONE);
	IDT_INSTALL_STI(234, IST_NONE);
	IDT_INSTALL_STI(235, IST_NONE);
	IDT_INSTALL_STI(236, IST_NONE);
	IDT_INSTALL_STI(237, IST_NONE);
	IDT_INSTALL_STI(238, IST_NONE);
	IDT_INSTALL_STI(239, IST_NONE);
	IDT_INSTALL_STI(240, IST_NONE);
	IDT_INSTALL_STI(241, IST_NONE);
	IDT_INSTALL_STI(242, IST_NONE);
	IDT_INSTALL_STI(243, IST_NONE);
	IDT_INSTALL_STI(244, IST_NONE);
	IDT_INSTALL_STI(245, IST_NONE);
	IDT_INSTALL_STI(246, IST_NONE);
	IDT_INSTALL_STI(247, IST_NONE);
	IDT_INSTALL_STI(248, IST_NONE);
	IDT_INSTALL_STI(249, IST_NONE);
	IDT_INSTALL_STI(250, IST_NONE);
	IDT_INSTALL_STI(251, IST_NONE);
	IDT_INSTALL_CLI(252, IST_NMI); // NMI
	IDT_INSTALL_STI(253, IST_NONE);
	IDT_INSTALL_STI(254, IST_NONE);
	IDT_INSTALL_STI(255, IST_NONE);
}
