79 lines
1.5 KiB
C
79 lines
1.5 KiB
C
#include <stdint.h>
|
|
#include "io.h"
|
|
#include "interrupts.h"
|
|
#include "rtc.h"
|
|
|
|
uint8_t read_cmos(uint16_t reg)
|
|
{
|
|
outb_wait(CMOS_ADDRESS, reg);
|
|
return inb_wait(CMOS_DATA);
|
|
}
|
|
|
|
uint8_t get_update_in_progress_flag()
|
|
{
|
|
outb_wait(CMOS_ADDRESS, 0x0A);
|
|
return inb_wait(CMOS_DATA) & 0x80;
|
|
}
|
|
|
|
void rtc_handler()
|
|
{
|
|
outb_wait(CMOS_ADDRESS, 0x0C);
|
|
inb_wait(CMOS_DATA);
|
|
}
|
|
|
|
uint8_t bcd_to_bin(uint8_t val)
|
|
{
|
|
return ((val / 16) * 10) + (val & 0x0F);
|
|
}
|
|
|
|
struct Rtc_time get_rtc_time()
|
|
{
|
|
struct Rtc_time time;
|
|
|
|
while (get_update_in_progress_flag())
|
|
;
|
|
|
|
time.sec = read_cmos(REG_SECONDS);
|
|
|
|
time.min = read_cmos(REG_MINUTES);
|
|
time.hour = read_cmos(REG_HOURS);
|
|
|
|
time.mday = read_cmos(REG_DAY);
|
|
time.mon = read_cmos(REG_MONTH);
|
|
time.year = read_cmos(REG_YEAR);
|
|
|
|
uint8_t registerB = read_cmos(0x0B);
|
|
|
|
if (!(registerB & 0x04))
|
|
{
|
|
time.sec = bcd_to_bin(time.sec);
|
|
time.min = bcd_to_bin(time.min);
|
|
time.hour = bcd_to_bin(time.hour);
|
|
time.mday = bcd_to_bin(time.mday);
|
|
time.mon = bcd_to_bin(time.mon);
|
|
time.year = bcd_to_bin(time.year);
|
|
}
|
|
|
|
if (time.year < 70)
|
|
{
|
|
time.year += 100;
|
|
}
|
|
else if (time.year >= 100)
|
|
{
|
|
time.year -= 100;
|
|
}
|
|
|
|
time.year += 1900;
|
|
|
|
return time;
|
|
}
|
|
|
|
void rtc_init()
|
|
{
|
|
outb_wait(CMOS_ADDRESS, 0x8A);
|
|
uint8_t prev = inb_wait(CMOS_DATA);
|
|
outb_wait(CMOS_ADDRESS, 0x8A);
|
|
outb_wait(CMOS_DATA, (prev & 0xF0) | 0x0F);
|
|
|
|
irq_install_handler(8, rtc_handler);
|
|
} |