Files
mop3/kernel/amd64/rtc.c
kamkow1 245196b80f
All checks were successful
Build ISO image / build-and-deploy (push) Successful in 32s
Build documentation / build-and-deploy (push) Successful in 41s
date_time () syscall, Get date-time from RTC
2026-04-12 21:13:20 +02:00

113 lines
2.9 KiB
C

#include <amd64/io.h>
#include <amd64/rtc.h>
#include <libk/std.h>
#include <limine/requests.h>
#include <sys/debug.h>
#include <sys/spin.h>
#include <sys/stall.h>
#include <time.h>
#include <uacpi/acpi.h>
#include <uacpi/status.h>
#include <uacpi/tables.h>
#include <uacpi/uacpi.h>
#define RTC_CMOS_ADDR 0x70
#define RTC_CMOS_DATA 0x71
static uint8_t rtc_century;
#define RTC_SEC 0x00
#define RTC_SEC_ALARM 0x01
#define RTC_MIN 0x02
#define RTC_MIN_ALARM 0x03
#define RTC_HOUR 0x04
#define RTC_HOUR_ALARM 0x05
#define RTC_WEEK_DAY 0x06
#define RTC_DAY 0x07
#define RTC_MONTH 0x08
#define RTC_YEAR 0x09
#define RTC_REG_A 0x0A
#define RTC_REG_B 0x0B
#define RTC_REG_C 0x0C
#define RTC_REG_D 0x0D
#define RTC_REG_A_UIP (1 << 7)
#define RTC_REG_B_HOURFMT (1 << 1)
#define RTC_REG_B_DATAMODE (1 << 2)
static uint8_t rtc_read (uint8_t addr) {
outb (RTC_CMOS_ADDR, RTC_REG_A);
while (inb (RTC_CMOS_DATA) & RTC_REG_A_UIP)
;
outb (RTC_CMOS_ADDR, addr);
return inb (RTC_CMOS_DATA);
}
static void rtc_write (uint8_t addr, uint8_t value) {
outb (RTC_CMOS_ADDR, addr);
outb (RTC_CMOS_DATA, value);
}
static uint8_t rtc_bcd_to_bin (uint8_t value) { return (value & 0xF) + (value >> 4) * 10; }
static uint8_t rtc_bin_to_bcd (uint8_t value) { return ((value / 10) << 4) + (value % 10); }
void rtc_init (void) {
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
struct uacpi_table fadt_table;
uacpi_status status = uacpi_table_find_by_signature (ACPI_FADT_SIGNATURE, &fadt_table);
if (status != UACPI_STATUS_OK) {
DEBUG ("Could not find FADT table!\n");
spin ();
}
struct acpi_fadt* fadt = (struct acpi_fadt*)fadt_table.virt_addr;
rtc_century = fadt->century;
}
void rtc_date_time (struct date_time* date_time) {
if (rtc_read (RTC_REG_A) & RTC_REG_A_UIP)
stall_ms (1);
uint8_t sec = rtc_read (RTC_SEC);
uint8_t min = rtc_read (RTC_MIN);
uint8_t hour = rtc_read (RTC_HOUR);
uint8_t weekday = rtc_read (RTC_WEEK_DAY);
uint8_t day = rtc_read (RTC_DAY);
uint8_t month = rtc_read (RTC_MONTH);
uint8_t year = rtc_read (RTC_YEAR);
uint8_t century = rtc_century != 0 ? rtc_read (rtc_century) : 0;
uint8_t b = rtc_read (RTC_REG_B);
/* BCD */
if ((~b) & RTC_REG_B_DATAMODE) {
sec = rtc_bcd_to_bin (sec);
min = rtc_bcd_to_bin (min);
hour = rtc_bcd_to_bin (hour);
day = rtc_bcd_to_bin (day);
month = rtc_bcd_to_bin (month);
year = rtc_bcd_to_bin (year);
if (rtc_century != 0)
century = rtc_bcd_to_bin (century);
}
weekday--;
int full_year;
if (rtc_century != 0)
full_year = (century * 100) + year;
else
full_year = (year < 80) ? (2000 + year) : (1900 + year);
date_time->sec = sec;
date_time->min = min;
date_time->hour = hour;
date_time->day = day;
date_time->weekday = weekday;
date_time->month = month;
date_time->year = full_year;
}