summaryrefslogtreecommitdiffhomepage
path: root/dev/Kernel/HALKit/AMD64/HalDescriptorLoader.cc
diff options
context:
space:
mode:
authorAmlal <amlalelmahrouss@icloud.com>2024-12-21 21:59:13 +0100
committerAmlal <amlalelmahrouss@icloud.com>2024-12-21 21:59:45 +0100
commit610f91d87152cbe48d3054fcf437d8239da6ef35 (patch)
treea386f7047ab73d088169ab2371ddc6ffe8020f1c /dev/Kernel/HALKit/AMD64/HalDescriptorLoader.cc
parent509fcca5986651c8ba712fb395f8498f2dea4109 (diff)
IMP: :boom: Breaking changes some checks are needed to be done.
Signed-off-by: Amlal <amlalelmahrouss@icloud.com>
Diffstat (limited to 'dev/Kernel/HALKit/AMD64/HalDescriptorLoader.cc')
-rw-r--r--dev/Kernel/HALKit/AMD64/HalDescriptorLoader.cc126
1 files changed, 126 insertions, 0 deletions
diff --git a/dev/Kernel/HALKit/AMD64/HalDescriptorLoader.cc b/dev/Kernel/HALKit/AMD64/HalDescriptorLoader.cc
new file mode 100644
index 00000000..e5a3700b
--- /dev/null
+++ b/dev/Kernel/HALKit/AMD64/HalDescriptorLoader.cc
@@ -0,0 +1,126 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, TQ B.V, all rights reserved.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.h>
+#include <HALKit/AMD64/Processor.h>
+
+#define kPITDefaultTicks (100U)
+
+namespace Kernel::HAL
+{
+ namespace Detail
+ {
+ STATIC ::Kernel::Detail::AMD64::InterruptDescriptorAMD64
+ kInterruptVectorTable[kKernelIdtSize] = {};
+
+ STATIC void hal_set_irq_mask(UInt8 irql);
+ STATIC void hal_clear_irq_mask(UInt8 irql);
+
+ STATIC Void hal_enable_pit(UInt16 ticks) noexcept
+ {
+ if (ticks == 0)
+ ticks = kPITDefaultTicks;
+
+ // Configure PIT to receieve scheduler interrupts.
+
+ UInt16 cCommonDivisor = kPITFrequency / ticks; // 100 Hz.
+
+ HAL::rt_out8(kPITControlPort, 0x36); // Command to PIT
+ HAL::rt_out8(kPITChannel0Port, cCommonDivisor & 0xFF); // Send low byte
+ HAL::rt_out8(kPITChannel0Port, (cCommonDivisor >> 8) & 0xFF); // Send high byte
+
+ hal_clear_irq_mask(32);
+ }
+
+ STATIC void hal_set_irq_mask(UInt8 irql)
+ {
+ UInt16 port;
+ UInt8 value;
+
+ if (irql < 8)
+ {
+ port = kPICData;
+ }
+ else
+ {
+ port = kPIC2Data;
+ irql -= 8;
+ }
+
+ value = rt_in8(port) | (1 << irql);
+ rt_out8(port, value);
+ }
+
+ STATIC void hal_clear_irq_mask(UInt8 irql)
+ {
+ UInt16 port;
+ UInt8 value;
+
+ if (irql < 8)
+ {
+ port = kPICData;
+ }
+ else
+ {
+ port = kPIC2Data;
+ irql -= 8;
+ }
+
+ value = rt_in8(port) & ~(1 << irql);
+ rt_out8(port, value);
+ }
+ } // namespace Detail
+
+ /// @brief Loads the provided Global Descriptor Table.
+ /// @param gdt
+ /// @return
+ Void GDTLoader::Load(RegisterGDT& gdt)
+ {
+ hal_load_gdt(gdt);
+ }
+
+ Void IDTLoader::Load(Register64& idt)
+ {
+ rt_cli();
+
+ const Int16 kPITTickForScheduler = kPITDefaultTicks;
+
+ volatile ::Kernel::UIntPtr** ptr_ivt = (volatile ::Kernel::UIntPtr**)idt.Base;
+
+ for (SizeT idt_indx = 0; idt_indx < kKernelIdtSize; ++idt_indx)
+ {
+ Detail::kInterruptVectorTable[idt_indx].Selector = kIDTSelector;
+ Detail::kInterruptVectorTable[idt_indx].Ist = 0;
+ Detail::kInterruptVectorTable[idt_indx].TypeAttributes = kInterruptGate;
+ Detail::kInterruptVectorTable[idt_indx].OffsetLow = ((UIntPtr)ptr_ivt[idt_indx] & 0xFFFF);
+ Detail::kInterruptVectorTable[idt_indx].OffsetMid = (((UIntPtr)ptr_ivt[idt_indx] >> 16) & 0xFFFF);
+ Detail::kInterruptVectorTable[idt_indx].OffsetHigh =
+ (((UIntPtr)ptr_ivt[idt_indx] >> 32) & 0xFFFFFFFF);
+
+ Detail::kInterruptVectorTable[idt_indx].Zero = 0;
+ }
+
+ idt.Base = (UIntPtr)&Detail::kInterruptVectorTable[0];
+ idt.Limit = sizeof(::Kernel::Detail::AMD64::InterruptDescriptorAMD64) *
+ (kKernelIdtSize);
+
+ hal_load_idt(idt);
+
+ Detail::hal_enable_pit(kPITTickForScheduler);
+
+ rt_sti();
+ }
+
+ void GDTLoader::Load(Ref<RegisterGDT>& gdt)
+ {
+ GDTLoader::Load(gdt.Leak());
+ }
+
+ void IDTLoader::Load(Ref<Register64>& idt)
+ {
+ IDTLoader::Load(idt.Leak());
+ }
+} // namespace Kernel::HAL