summaryrefslogtreecommitdiff
path: root/kernel/arch
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2024-07-03 01:21:16 +0200
committerAnton Kling <anton@kling.gg>2024-07-03 01:21:28 +0200
commitdd9aece19f93c1cafe07dfc0e63e1599a06db04b (patch)
treeaf5ef66b2eba21d0eaa2d3a00abcfec64cea98b4 /kernel/arch
parent5751b4ff0baf41fd3f38b30b0cb58d09631e9bc0 (diff)
Kernel: Add simple support for timer using TSC
Diffstat (limited to 'kernel/arch')
-rw-r--r--kernel/arch/i386/asm_tsc.s63
-rw-r--r--kernel/arch/i386/tsc.h4
2 files changed, 67 insertions, 0 deletions
diff --git a/kernel/arch/i386/asm_tsc.s b/kernel/arch/i386/asm_tsc.s
new file mode 100644
index 0000000..963687e
--- /dev/null
+++ b/kernel/arch/i386/asm_tsc.s
@@ -0,0 +1,63 @@
+.intel_syntax noprefix
+
+.global get_tsc
+.global get_hz
+
+# 1.193182 MHz
+# So 0xFFFF is roughly 0.05492 seconds
+# So take the result times 18 and you got your Hz
+
+get_tsc:
+ rdtsc
+ ret
+
+get_hz:
+ cli
+ # Disable the gate for channel 2 so the clock can be set.
+ # This should only matter if the channel already has count
+ inb al, 0x61
+ and al, 0xFE
+ or al, 0x1
+ outb 0x61, al
+
+ # Set mode
+ mov al, 0b10110010
+ outb 0x43, al
+
+ # 0x2e9b = 11931 which is close to the PIT Hz divided by 100
+ mov al, 0x9b
+ outb 0x42, al
+ mov al, 0x2e
+ outb 0x42, al
+
+ rdtsc
+ mov ecx, eax
+ mov esi, edx
+
+ # Set the gate for channel 2
+ inb al, 0x61
+ or al, 0x1
+ outb 0x61, al
+
+ # The fifth bit will(seems to) flip when the count is low.
+ and al, 0x20
+ jnz none_zero_check
+
+zero_check:
+ inb al, 0x61
+ andb al, 0x20
+ cmp al, 0
+ jz zero_check
+ jmp end
+
+none_zero_check:
+ inb al, 0x61
+ andb al, 0x20
+ cmp al, 0
+ jnz none_zero_check
+end:
+ rdtsc
+
+ sub eax, ecx
+ sub edx, esi
+ ret
diff --git a/kernel/arch/i386/tsc.h b/kernel/arch/i386/tsc.h
new file mode 100644
index 0000000..2e29cf3
--- /dev/null
+++ b/kernel/arch/i386/tsc.h
@@ -0,0 +1,4 @@
+#include <typedefs.h>
+
+u64 get_tsc();
+u64 get_hz();