summaryrefslogtreecommitdiff
path: root/kernel/source/timer.asm
blob: d5f6f7319764ac391a2321ce6635b8b869792add (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
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