summaryrefslogtreecommitdiffhomepage
path: root/dev/kernel/HALKit/AMD64/HalTimer.cc
diff options
context:
space:
mode:
authorAmlal El Mahrouss <amlal@nekernel.org>2025-05-25 09:56:46 +0200
committerAmlal El Mahrouss <amlal@nekernel.org>2025-05-25 09:56:46 +0200
commit5b30cacacf0f0ca6fb06bb34389f04b05ceb2b15 (patch)
tree85c1fb5b167d3089483affe7060155a7d148d641 /dev/kernel/HALKit/AMD64/HalTimer.cc
parentef3e3db6fafb43afd3e254b17c7169c603cdf416 (diff)
kernel!: lots of changes, see commit details.
refactor(hal): unify file naming and drop redundant architecture suffixes feat(build): rename kernel and bootloader to 'ne_kernel' and 'ne_bootz' refactor(memory): replace mm_get_phys_address with mm_get_page_addr feat(bitmap): track bitmap allocator usage and add out-of-memory error fix(heap): correct heap magic naming and alignment logic chore(fs): downgrade HeFS disk size check to warning chore(tools): clean up formatting in 'ping' and 'manual' docs(design): update OS_DESIGN.drawio to reflect Hypr86 and new layout Signed-off-by: Amlal El Mahrouss <amlal@nekernel.org>
Diffstat (limited to 'dev/kernel/HALKit/AMD64/HalTimer.cc')
-rw-r--r--dev/kernel/HALKit/AMD64/HalTimer.cc97
1 files changed, 97 insertions, 0 deletions
diff --git a/dev/kernel/HALKit/AMD64/HalTimer.cc b/dev/kernel/HALKit/AMD64/HalTimer.cc
new file mode 100644
index 00000000..13573880
--- /dev/null
+++ b/dev/kernel/HALKit/AMD64/HalTimer.cc
@@ -0,0 +1,97 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved.
+
+ File: HalTimer.cc
+ Purpose: HAL timer
+
+ Revision History:
+
+ 07/07/24: Added file (amlel)
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/Timer.h>
+#include <modules/ACPI/ACPIFactoryInterface.h>
+
+// timer slot 0
+
+#define kHPETSignature ("HPET")
+
+#define kHPETCounterRegValue (0x00)
+#define kHPETConfigRegValue (0x20)
+#define kHPETCompRegValue (0x24)
+#define kHPETInterruptRegValue (0x2C)
+
+///! BUGS: 0
+///! @file HalTimer.cc
+///! @brief Hardware Timer (HPET)
+
+namespace Kernel::Detail {
+struct HPET_BLOCK : public Kernel::SDT {
+ Kernel::UInt8 hardware_rev_id;
+ Kernel::UInt8 comparator_count : 5;
+ Kernel::UInt8 counter_size : 1;
+ Kernel::UInt8 reserved : 1;
+ Kernel::UInt8 legacy_replacement : 1;
+ Kernel::UInt16 pci_vendor_id;
+ ACPI_ADDRESS address;
+ Kernel::UInt8 hpet_number;
+ Kernel::UInt16 minimum_tick;
+ Kernel::UInt8 page_protection;
+} PACKED;
+} // namespace Kernel::Detail
+
+using namespace Kernel;
+
+HardwareTimer::HardwareTimer(UInt64 ms) : fWaitFor(ms) {
+ auto power = PowerFactoryInterface(kHandoverHeader->f_HardwareTables.f_VendorPtr);
+
+ auto hpet = (Detail::HPET_BLOCK*) power.Find(kHPETSignature).Leak().Leak();
+ MUST_PASS(hpet);
+
+ fDigitalTimer = (UInt8*) hpet->address.Address;
+
+ if (hpet->page_protection) {
+ HAL::mm_map_page((VoidPtr) fDigitalTimer, (VoidPtr) fDigitalTimer,
+ HAL::kMMFlagsWr | HAL::kMMFlagsPCD | HAL::kMMFlagsPwt);
+ }
+
+ // if not enabled yet.
+ if (!(*((volatile UInt64*) ((UInt8*) fDigitalTimer + kHPETConfigRegValue)) & (1 << 0))) {
+ *((volatile UInt64*) ((UInt8*) fDigitalTimer + kHPETConfigRegValue)) =
+ *((volatile UInt64*) ((UInt8*) fDigitalTimer + kHPETConfigRegValue)) |
+ (1 << 0); // enable timer
+ *((volatile UInt64*) ((UInt8*) fDigitalTimer + kHPETConfigRegValue)) =
+ *((volatile UInt64*) ((UInt8*) fDigitalTimer + kHPETConfigRegValue)) |
+ (1 << 3); // one shot conf
+ }
+}
+
+HardwareTimer::~HardwareTimer() {
+ fDigitalTimer = nullptr;
+ fWaitFor = 0;
+}
+
+/***********************************************************************************/
+/// @brief Wait for the timer to stop spinning.
+/***********************************************************************************/
+
+BOOL HardwareTimer::Wait() noexcept {
+ if (fWaitFor < 1) return NO;
+
+ UInt64 hpet_cap = *((volatile UInt64*) (fDigitalTimer + kHPETCounterRegValue));
+ UInt64 femtoseconds_per_tick = (hpet_cap >> 32);
+
+ if (femtoseconds_per_tick == 0) return NO;
+
+ volatile UInt64* timer = (volatile UInt64*) (fDigitalTimer + kHPETCounterRegValue);
+
+ UInt64 now = *timer;
+ UInt64 prev = now + (fWaitFor / femtoseconds_per_tick);
+
+ while (*timer < (prev)) asm volatile("pause");
+
+ return YES;
+}