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