summaryrefslogtreecommitdiff
path: root/kernel/source/timer.asm
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/source/timer.asm')
-rw-r--r--kernel/source/timer.asm162
1 files changed, 162 insertions, 0 deletions
diff --git a/kernel/source/timer.asm b/kernel/source/timer.asm
new file mode 100644
index 0000000..d5f6f73
--- /dev/null
+++ b/kernel/source/timer.asm
@@ -0,0 +1,162 @@
+bits 64
+
+section .rodata
+
+section .text
+
+read_cmos_byte:
+;dil in = register number
+;al out = value
+;rdx and rcx are not touched
+
+ mov al, dil
+ out 0x70, al
+ in al, 0x71
+ ret
+
+global enable_rtc_interrupts
+enable_rtc_interrupts:
+
+ ;secondary status register
+ mov dil, 11
+ call read_cmos_byte
+
+ ;enable interrupts
+ or al, 0x40
+ mov cl, al
+
+ ;do cmos write
+ mov al, 11
+ out 0x70, al
+ mov al, cl
+ out 0x71, al
+
+ ret
+
+global acknowledge_rtc_interrupt
+acknowledge_rtc_interrupt:
+ mov dil, 12
+ jmp read_cmos_byte
+
+convert_bcd:
+;al in = byte (possibly bcd)
+;al out = byte (not bcd)
+;sil 0x02 = bcd
+;does not touch rdx, rcx, sil
+ test sil, 0x02
+ jz .no_convert
+
+ mov dil, al
+ and dil, 0xf0
+ and al, 0x0f
+ shr dil, 3
+ add al, dil
+ shl dil, 2
+ add al, dil
+
+.no_convert:
+ ret
+
+convert_hours:
+;al in = byte (possibly bcd and 12 hour)
+;al out = byte (not bcd or 12 hour)
+;sil 0x02 = bcd, sil 0x01 = 12 hour
+;does not touch rdx, rcx, sil
+ test sil, 0x01
+ jz convert_bcd
+
+ test al, 0x80
+ jz .am
+
+ and al, 0x7f
+ call convert_bcd
+ cmp al, 12
+ je .noon
+
+ add al, 12
+ ret
+
+.noon:
+ ret
+
+.am:
+ call convert_bcd
+ cmp al, 12
+ je .midnight
+
+ ret
+
+.midnight:
+ xor al, al
+ ret
+
+global get_time_from_rtc
+get_time_from_rtc:
+;rax out = time (see timer.cpp for encoding)
+;we assume the year is 20xx (sorry)
+
+ mov dil, 11
+ call read_cmos_byte
+
+ shr al, 1
+ not al
+ and al, 3
+ mov sil, al
+
+ xor rdx, rdx
+
+.outer_loop:
+ mov rcx, rdx
+
+.wait_for_update_loop:
+ ;status register - 0x80 is update in progress
+ mov dil, 10
+ call read_cmos_byte
+ test al, 0x80
+ jnz .wait_for_update_loop
+
+ ;years
+ mov dil, 9
+ call read_cmos_byte
+ call convert_bcd
+ mov dh, al
+
+ ;months
+ mov dil, 8
+ call read_cmos_byte
+ call convert_bcd
+ mov dl, al
+
+ shl edx, 16
+
+ ;days
+ mov dil, 7
+ call read_cmos_byte
+ call convert_bcd
+ mov dh, al
+
+ ;hours
+ mov dil, 4
+ call read_cmos_byte
+ call convert_hours
+ mov dl, al
+
+ shl rdx, 16
+
+ ;minutes
+ mov dil, 2
+ call read_cmos_byte
+ call convert_bcd
+ mov dh, al
+
+ ;seconds
+ xor dil, dil
+ call read_cmos_byte
+ call convert_bcd
+ mov dl, al
+
+ cmp rdx, rcx
+ jne .outer_loop
+
+ mov rax, rdx
+ ret