Working RTC access

This commit is contained in:
Gitea 2020-12-01 20:59:42 -06:00
parent 4091148d2e
commit e04489a8c3
2 changed files with 95 additions and 0 deletions

68
arch/i386/cmos.c Normal file
View file

@ -0,0 +1,68 @@
#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;
}

27
include/kernel/cmos.h Normal file
View file

@ -0,0 +1,27 @@
#ifndef _KERNEL_CMOS
#define _KERNEL_CMOS
/* This is kinda important, and has to be changed each year. */
#define RELEASE_YEAR 2020
struct _rtc_val {
unsigned char second;
unsigned char minute;
unsigned char hour;
unsigned char day;
unsigned char month;
unsigned int year;
};
static struct _rtc_val cur_time;
enum {
cmos_address = 0x70,
cmos_data = 0x71
};
int _check_update_in_progress(void);
unsigned char _get_rtc_reg(unsigned char reg);
unsigned long int read_rtc();
#endif