FENIX_kernel/arch/i386/cmos.c

69 lines
2.3 KiB
C

#include <kernel/cmos.h>
int _check_update_in_progress(void) {
unsigned char ret_val = 0;
__asm__ volatile("mov $0x0A, %%al\n\t" "outb %%al, $0x70\n\t" "inb $0x71, %%al\n\t" "mov %%al, %0":"=b" (ret_val)::"%al");
return ret_val;
}
unsigned char _get_rtc_reg(unsigned char reg) {
unsigned char ret_val = 0;
__asm__ volatile("mov %1, %%al\n\t" "outb %%al, $0x70\n\t" "inb $0x71, %%al\n\t" "mov %%al, %0":"=b" (ret_val):"c" (reg):"%al");
return ret_val;
}
unsigned long int read_rtc() {
unsigned char regb;
unsigned long int ret_val;
/* I might need to add this check back in, but it's fine for now. */
/* while(_check_update_in_progress()); */
cur_time.second = _get_rtc_reg(0x00);
cur_time.minute = _get_rtc_reg(0x02);
cur_time.hour = _get_rtc_reg(0x04);
cur_time.day = _get_rtc_reg(0x07);
cur_time.month = _get_rtc_reg(0x08);
cur_time.year = _get_rtc_reg(0x09);
regb = _get_rtc_reg(0x0B);
/* Convert bcd to binary if needed */
if(!(regb & 0x04)) {
cur_time.second = (cur_time.second & 0x0F) + ((cur_time.second / 16) * 10);
cur_time.minute = (cur_time.minute & 0x0F) + ((cur_time.minute / 16) * 10);
cur_time.hour = ((cur_time.hour & 0x0F) + (((cur_time.hour & 0x70) / 16) * 10)) | (cur_time.hour & 0x80);
cur_time.day = (cur_time.day & 0x0F) + ((cur_time.day / 16) * 10);
cur_time.month = (cur_time.month & 0x0F) + ((cur_time.month / 16) * 10);
cur_time.year = (cur_time.year & 0x0F) + ((cur_time.year / 16) * 10);
}
/* Convert to 24H time if needed */
if(!(regb & 0x02) && (cur_time.hour & 0x80)) {
cur_time.hour = ((cur_time.hour & 0x7F) + 12) % 24;
}
/* Get year. TODO: Use century register for this. */
cur_time.year += (RELEASE_YEAR / 100) * 100; /* Add century of release year */
if(cur_time.year < RELEASE_YEAR) cur_time.year += 100;
ret_val = cur_time.second;
ret_val += cur_time.minute * 60;
ret_val += cur_time.hour * 3600;
unsigned int tot_days = cur_time.day;
unsigned char month_days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
for(unsigned int i = 1970; i < cur_time.year; i++) {
if(i % 400 == 0 || (i % 100 != 0 && i % 4 == 0)) {
tot_days += 366;
}
else {
tot_days += 365;
}
}
for(int i = 0; i < (cur_time.month - 1); i++) {
tot_days += month_days[i];
}
ret_val += tot_days * 86400;
return ret_val;
}